In preparation for getting rid of switchdev_ops, create a dedicated NDO
operation for getting the port's parent identifier. There are
essentially two classes of drivers that need to implement getting the
port's parent ID which are VF/PF drivers with a built-in switch, and
pure switchdev drivers such as mlxsw, ocelot, dsa etc.

Convert the bridge, core and ipv4 multicast routing code to check for
such ndo_get_port_parent_id() and call it when valid before falling back
to switchdev_port_attr_get(). This will allow us to convert all relevant
drivers in one go instead of having to implement both
switchdev_port_attr_get() and ndo_get_port_parent_id() operations.

Signed-off-by: Florian Fainelli <f.faine...@gmail.com>
---
 include/linux/netdevice.h | 6 ++++++
 net/bridge/br_switchdev.c | 6 +++++-
 net/core/net-sysfs.c      | 6 +++++-
 net/core/rtnetlink.c      | 6 +++++-
 net/ipv4/ipmr.c           | 8 +++++++-
 5 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index ba57d0ba425e..1bdfbbe1e768 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1188,6 +1188,10 @@ struct dev_ifalias {
  *     not implement this, it is assumed that the hw is not able to have
  *     multiple net devices on single physical port.
  *
+ * int (*ndo_get_port_parent_id)(struct net_device *dev,
+ *                              struct netdev_phys_item_id *ppid);
+ *     Called to get the parent ID of the physical port of this device.
+ *
  * void (*ndo_udp_tunnel_add)(struct net_device *dev,
  *                           struct udp_tunnel_info *ti);
  *     Called by UDP tunnel to notify a driver about the UDP port and socket
@@ -1412,6 +1416,8 @@ struct net_device_ops {
                                                      bool new_carrier);
        int                     (*ndo_get_phys_port_id)(struct net_device *dev,
                                                        struct 
netdev_phys_item_id *ppid);
+       int                     (*ndo_get_port_parent_id)(struct net_device 
*dev,
+                                                         struct 
netdev_phys_item_id *ppid);
        int                     (*ndo_get_phys_port_name)(struct net_device 
*dev,
                                                          char *name, size_t 
len);
        void                    (*ndo_udp_tunnel_add)(struct net_device *dev,
diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
index 4d2b9eb7604a..501a4221220a 100644
--- a/net/bridge/br_switchdev.c
+++ b/net/bridge/br_switchdev.c
@@ -23,6 +23,7 @@ static int br_switchdev_mark_get(struct net_bridge *br, 
struct net_device *dev)
 
 int nbp_switchdev_mark_set(struct net_bridge_port *p)
 {
+       const struct net_device_ops *ops = p->dev->netdev_ops;
        struct switchdev_attr attr = {
                .orig_dev = p->dev,
                .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID,
@@ -31,7 +32,10 @@ int nbp_switchdev_mark_set(struct net_bridge_port *p)
 
        ASSERT_RTNL();
 
-       err = switchdev_port_attr_get(p->dev, &attr);
+       if (ops->ndo_get_port_parent_id)
+               err = ops->ndo_get_port_parent_id(p->dev, &attr.u.ppid);
+       else
+               err = switchdev_port_attr_get(p->dev, &attr);
        if (err) {
                if (err == -EOPNOTSUPP)
                        return 0;
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index ff9fd2bb4ce4..cc05e8b72657 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -495,6 +495,7 @@ static ssize_t phys_switch_id_show(struct device *dev,
                                   struct device_attribute *attr, char *buf)
 {
        struct net_device *netdev = to_net_dev(dev);
+       const struct net_device_ops *ops = netdev->netdev_ops;
        ssize_t ret = -EINVAL;
 
        if (!rtnl_trylock())
@@ -507,7 +508,10 @@ static ssize_t phys_switch_id_show(struct device *dev,
                        .flags = SWITCHDEV_F_NO_RECURSE,
                };
 
-               ret = switchdev_port_attr_get(netdev, &attr);
+               if (ops->ndo_get_port_parent_id)
+                       ret = ops->ndo_get_port_parent_id(netdev, &attr.u.ppid);
+               else
+                       ret = switchdev_port_attr_get(netdev, &attr);
                if (!ret)
                        ret = sprintf(buf, "%*phN\n", attr.u.ppid.id_len,
                                      attr.u.ppid.id);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index f5a98082ac7a..ed8564eb97c8 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1146,6 +1146,7 @@ static int rtnl_phys_port_name_fill(struct sk_buff *skb, 
struct net_device *dev)
 
 static int rtnl_phys_switch_id_fill(struct sk_buff *skb, struct net_device 
*dev)
 {
+       const struct net_device_ops *ops = dev->netdev_ops;
        int err;
        struct switchdev_attr attr = {
                .orig_dev = dev,
@@ -1153,7 +1154,10 @@ static int rtnl_phys_switch_id_fill(struct sk_buff *skb, 
struct net_device *dev)
                .flags = SWITCHDEV_F_NO_RECURSE,
        };
 
-       err = switchdev_port_attr_get(dev, &attr);
+       if (ops->ndo_get_port_parent_id)
+               err = ops->ndo_get_port_parent_id(dev, &attr.u.ppid);
+       else
+               err = switchdev_port_attr_get(dev, &attr);
        if (err) {
                if (err == -EOPNOTSUPP)
                        return 0;
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index fb99002c3d4e..9f67394b6691 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -837,6 +837,7 @@ static void ipmr_update_thresholds(struct mr_table *mrt, 
struct mr_mfc *cache,
 static int vif_add(struct net *net, struct mr_table *mrt,
                   struct vifctl *vifc, int mrtsock)
 {
+       const struct net_device_ops *ops;
        int vifi = vifc->vifc_vifi;
        struct switchdev_attr attr = {
                .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID,
@@ -920,7 +921,12 @@ static int vif_add(struct net *net, struct mr_table *mrt,
                        (VIFF_TUNNEL | VIFF_REGISTER));
 
        attr.orig_dev = dev;
-       if (!switchdev_port_attr_get(dev, &attr)) {
+       ops = dev->netdev_ops;
+       if (ops->ndo_get_port_parent_id &&
+           !ops->ndo_get_port_parent_id(dev, &attr.ppid)) {
+               memcpy(v->dev_parent_id.id, attr.u.ppid.id, attr.u.ppid.id_len);
+               v->dev_parent_id.id_len = attr.u.ppid.id_len;
+       } else if (!switchdev_port_attr_get(dev, &attr)) {
                memcpy(v->dev_parent_id.id, attr.u.ppid.id, attr.u.ppid.id_len);
                v->dev_parent_id.id_len = attr.u.ppid.id_len;
        } else {
-- 
2.17.1

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to