summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorXiaoliang Yang <xiaoliang.yang_1@nxp.com>2025-11-30 15:16:44 +0200
committerJakub Kicinski <kuba@kernel.org>2025-12-01 16:45:06 -0800
commita0244e76213980f3b9bb5d40b0b6705fcf24230d (patch)
treeb4c094859e4c3dff6fc2c1d8d730e80b0742cc88 /net
parent3b87e60d213150bc1f8475ec3c542f4c8cdd2e2c (diff)
net: hsr: create an API to get hsr port type
Since the introduction of HSR_PT_INTERLINK in commit 5055cccfc2d1 ("net: hsr: Provide RedBox support (HSR-SAN)"), we see that different port types require different settings for hardware offload, which was not the case before when we only had HSR_PT_SLAVE_A and HSR_PT_SLAVE_B. But there is currently no way to know which port is which type, so create the hsr_get_port_type() API function and export it. When hsr_get_port_type() is called from the device driver, the port can must be found in the HSR port list. An important use case is for this function to work from offloading drivers' NETDEV_CHANGEUPPER handler, which is triggered by hsr_portdev_setup() -> netdev_master_upper_dev_link(). Therefore, we need to move the addition of the hsr_port to the HSR port list prior to calling hsr_portdev_setup(). This makes the error restoration path also more similar to hsr_del_port(), where kfree_rcu(port) is already used. Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Cc: Lukasz Majewski <lukma@denx.de> Signed-off-by: Xiaoliang Yang <xiaoliang.yang_1@nxp.com> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Reviewed-by: Ɓukasz Majewski <lukma@nabladev.com> Link: https://patch.msgid.link/20251130131657.65080-3-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net')
-rw-r--r--net/hsr/hsr_device.c20
-rw-r--r--net/hsr/hsr_slave.c7
2 files changed, 24 insertions, 3 deletions
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index 492cbc78ab75..d1bfc49b5f01 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -690,6 +690,26 @@ struct net_device *hsr_get_port_ndev(struct net_device *ndev,
}
EXPORT_SYMBOL(hsr_get_port_ndev);
+int hsr_get_port_type(struct net_device *hsr_dev, struct net_device *dev,
+ enum hsr_port_type *type)
+{
+ struct hsr_priv *hsr = netdev_priv(hsr_dev);
+ struct hsr_port *port;
+
+ rcu_read_lock();
+ hsr_for_each_port(hsr, port) {
+ if (port->dev == dev) {
+ *type = port->type;
+ rcu_read_unlock();
+ return 0;
+ }
+ }
+ rcu_read_unlock();
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(hsr_get_port_type);
+
/* Default multicast address for HSR Supervision frames */
static const unsigned char def_multicast_addr[ETH_ALEN] __aligned(2) = {
0x01, 0x15, 0x4e, 0x00, 0x01, 0x00
diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c
index 8177ac6c2d26..afe06ba00ea4 100644
--- a/net/hsr/hsr_slave.c
+++ b/net/hsr/hsr_slave.c
@@ -207,14 +207,14 @@ int hsr_add_port(struct hsr_priv *hsr, struct net_device *dev,
port->type = type;
ether_addr_copy(port->original_macaddress, dev->dev_addr);
+ list_add_tail_rcu(&port->port_list, &hsr->ports);
+
if (type != HSR_PT_MASTER) {
res = hsr_portdev_setup(hsr, dev, port, extack);
if (res)
goto fail_dev_setup;
}
- list_add_tail_rcu(&port->port_list, &hsr->ports);
-
master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
netdev_update_features(master->dev);
dev_set_mtu(master->dev, hsr_get_max_mtu(hsr));
@@ -222,7 +222,8 @@ int hsr_add_port(struct hsr_priv *hsr, struct net_device *dev,
return 0;
fail_dev_setup:
- kfree(port);
+ list_del_rcu(&port->port_list);
+ kfree_rcu(port, rcu);
return res;
}