]> Gentwo Git Trees - linux/.git/commitdiff
net: hsr: create an API to get hsr port type
authorXiaoliang Yang <xiaoliang.yang_1@nxp.com>
Sun, 30 Nov 2025 13:16:44 +0000 (15:16 +0200)
committerJakub Kicinski <kuba@kernel.org>
Tue, 2 Dec 2025 00:45:06 +0000 (16:45 -0800)
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>
include/linux/if_hsr.h
net/hsr/hsr_device.c
net/hsr/hsr_slave.c

index d7941fd8803295beb356cbb9d5b45fa801a08516..f4cf2dd36d193d5d694939c7f5b16395b9fa1710 100644 (file)
@@ -43,6 +43,8 @@ extern bool is_hsr_master(struct net_device *dev);
 extern int hsr_get_version(struct net_device *dev, enum hsr_version *ver);
 struct net_device *hsr_get_port_ndev(struct net_device *ndev,
                                     enum hsr_port_type pt);
+int hsr_get_port_type(struct net_device *hsr_dev, struct net_device *dev,
+                     enum hsr_port_type *type);
 #else
 static inline bool is_hsr_master(struct net_device *dev)
 {
@@ -59,6 +61,13 @@ static inline struct net_device *hsr_get_port_ndev(struct net_device *ndev,
 {
        return ERR_PTR(-EINVAL);
 }
+
+static inline int hsr_get_port_type(struct net_device *hsr_dev,
+                                   struct net_device *dev,
+                                   enum hsr_port_type *type)
+{
+       return -EINVAL;
+}
 #endif /* CONFIG_HSR */
 
 #endif /*_LINUX_IF_HSR_H_*/
index 492cbc78ab75a0384b1881dca5708adff5eb5758..d1bfc49b5f017bc7fbbdedcc1eeab4d7e95e56be 100644 (file)
@@ -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
index 8177ac6c2d26de75ec12cd33e41c1511069b0e00..afe06ba00ea44700ed250527c4319f005344e216 100644 (file)
@@ -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;
 }