]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net: dsa: propagate extack to .port_vlan_add
authorVladimir Oltean <vladimir.oltean@nxp.com>
Sat, 13 Feb 2021 20:43:18 +0000 (22:43 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 15 Feb 2021 01:38:11 +0000 (17:38 -0800)
Allow drivers to communicate their restrictions to user space directly,
instead of printing to the kernel log. Where the conversion would have
been lossy and things like VLAN ID could no longer be conveyed (due to
the lack of support for printf format specifier in netlink extack), I
chose to keep the messages in full form to the kernel log only, and
leave it up to individual driver maintainers to move more messages to
extack.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
20 files changed:
drivers/net/dsa/b53/b53_common.c
drivers/net/dsa/b53/b53_priv.h
drivers/net/dsa/bcm_sf2_cfp.c
drivers/net/dsa/dsa_loop.c
drivers/net/dsa/hirschmann/hellcreek.c
drivers/net/dsa/lantiq_gswip.c
drivers/net/dsa/microchip/ksz8795.c
drivers/net/dsa/microchip/ksz9477.c
drivers/net/dsa/mt7530.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/ocelot/felix.c
drivers/net/dsa/qca8k.c
drivers/net/dsa/realtek-smi-core.h
drivers/net/dsa/rtl8366.c
drivers/net/dsa/sja1105/sja1105_main.c
include/net/dsa.h
net/dsa/dsa_priv.h
net/dsa/port.c
net/dsa/slave.c
net/dsa/switch.c

index 72c75c7bdb6536d111819c66b70784cf2b4da928..98cc051e513ebc4681320b04e33e9c57377b673d 100644 (file)
@@ -1444,7 +1444,8 @@ static int b53_vlan_prepare(struct dsa_switch *ds, int port,
 }
 
 int b53_vlan_add(struct dsa_switch *ds, int port,
-                const struct switchdev_obj_port_vlan *vlan)
+                const struct switchdev_obj_port_vlan *vlan,
+                struct netlink_ext_ack *extack)
 {
        struct b53_device *dev = ds->priv;
        bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
index ae72ef46b0b663f1219da781b42e7c11ca29dc87..fc5d6fddb3fe425211142006816f595ad3e45c55 100644 (file)
@@ -348,7 +348,8 @@ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port,
                             bool tx_pause, bool rx_pause);
 int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering);
 int b53_vlan_add(struct dsa_switch *ds, int port,
-                const struct switchdev_obj_port_vlan *vlan);
+                const struct switchdev_obj_port_vlan *vlan,
+                struct netlink_ext_ack *extack);
 int b53_vlan_del(struct dsa_switch *ds, int port,
                 const struct switchdev_obj_port_vlan *vlan);
 int b53_fdb_add(struct dsa_switch *ds, int port,
index 178218cf73a3ff62e77b3d9264a7dc234dc97f7d..a7e2fcf2df2c9f282ac41fc66b448da9fb28bbe8 100644 (file)
@@ -891,7 +891,7 @@ static int bcm_sf2_cfp_rule_insert(struct dsa_switch *ds, int port,
                else
                        vlan.flags = 0;
 
-               ret = ds->ops->port_vlan_add(ds, port_num, &vlan);
+               ret = ds->ops->port_vlan_add(ds, port_num, &vlan, NULL);
                if (ret)
                        return ret;
        }
index 8c283f59158b0e5fe971bfcbc71399b2cc2a61da..e55b63a7e9073148146bd7bd36d68a985574e6ab 100644 (file)
@@ -199,7 +199,8 @@ static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port,
 }
 
 static int dsa_loop_port_vlan_add(struct dsa_switch *ds, int port,
-                                 const struct switchdev_obj_port_vlan *vlan)
+                                 const struct switchdev_obj_port_vlan *vlan,
+                                 struct netlink_ext_ack *extack)
 {
        bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
        bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
index f984ca75a71f46b58056af2d00bc9be65fe96933..5816ef922e553916d5bb1170962dc37fdb41e895 100644 (file)
@@ -341,7 +341,8 @@ static u16 hellcreek_private_vid(int port)
 }
 
 static int hellcreek_vlan_prepare(struct dsa_switch *ds, int port,
-                                 const struct switchdev_obj_port_vlan *vlan)
+                                 const struct switchdev_obj_port_vlan *vlan,
+                                 struct netlink_ext_ack *extack)
 {
        struct hellcreek *hellcreek = ds->priv;
        int i;
@@ -358,8 +359,10 @@ static int hellcreek_vlan_prepare(struct dsa_switch *ds, int port,
                if (!dsa_is_user_port(ds, i))
                        continue;
 
-               if (vlan->vid == restricted_vid)
+               if (vlan->vid == restricted_vid) {
+                       NL_SET_ERR_MSG_MOD(extack, "VID restricted by driver");
                        return -EBUSY;
+               }
        }
 
        return 0;
@@ -445,14 +448,15 @@ static void hellcreek_unapply_vlan(struct hellcreek *hellcreek, int port,
 }
 
 static int hellcreek_vlan_add(struct dsa_switch *ds, int port,
-                             const struct switchdev_obj_port_vlan *vlan)
+                             const struct switchdev_obj_port_vlan *vlan,
+                             struct netlink_ext_ack *extack)
 {
        bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
        bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
        struct hellcreek *hellcreek = ds->priv;
        int err;
 
-       err = hellcreek_vlan_prepare(ds, port, vlan);
+       err = hellcreek_vlan_prepare(ds, port, vlan, extack);
        if (err)
                return err;
 
index 9fec97773a156ecd688cb7f068d028641e7ffed6..174ca3a484a09da0407c0c66ec5ff551e2d314b8 100644 (file)
@@ -1128,7 +1128,8 @@ static void gswip_port_bridge_leave(struct dsa_switch *ds, int port,
 }
 
 static int gswip_port_vlan_prepare(struct dsa_switch *ds, int port,
-                                  const struct switchdev_obj_port_vlan *vlan)
+                                  const struct switchdev_obj_port_vlan *vlan,
+                                  struct netlink_ext_ack *extack)
 {
        struct gswip_priv *priv = ds->priv;
        struct net_device *bridge = dsa_to_port(ds, port)->bridge_dev;
@@ -1163,15 +1164,18 @@ static int gswip_port_vlan_prepare(struct dsa_switch *ds, int port,
                        }
                }
 
-               if (idx == -1)
+               if (idx == -1) {
+                       NL_SET_ERR_MSG_MOD(extack, "No slot in VLAN table");
                        return -ENOSPC;
+               }
        }
 
        return 0;
 }
 
 static int gswip_port_vlan_add(struct dsa_switch *ds, int port,
-                              const struct switchdev_obj_port_vlan *vlan)
+                              const struct switchdev_obj_port_vlan *vlan,
+                              struct netlink_ext_ack *extack)
 {
        struct gswip_priv *priv = ds->priv;
        struct net_device *bridge = dsa_to_port(ds, port)->bridge_dev;
@@ -1179,7 +1183,7 @@ static int gswip_port_vlan_add(struct dsa_switch *ds, int port,
        bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
        int err;
 
-       err = gswip_port_vlan_prepare(ds, port, vlan);
+       err = gswip_port_vlan_prepare(ds, port, vlan, extack);
        if (err)
                return err;
 
index c87d445b30fd097b6c21c10798ae85207489ec29..1e27a3e581413f72fdd21681b26bc4d49a379d9d 100644 (file)
@@ -793,7 +793,8 @@ static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port,
 }
 
 static int ksz8795_port_vlan_add(struct dsa_switch *ds, int port,
-                                const struct switchdev_obj_port_vlan *vlan)
+                                const struct switchdev_obj_port_vlan *vlan,
+                                struct netlink_ext_ack *extack)
 {
        bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
        struct ksz_device *dev = ds->priv;
index 00e38c8e0d010d864b7f1ce55c1e4aa5502f5d48..772e34d5b6b8ad62ecdb8e25fe72f8840179c2cc 100644 (file)
@@ -511,7 +511,8 @@ static int ksz9477_port_vlan_filtering(struct dsa_switch *ds, int port,
 }
 
 static int ksz9477_port_vlan_add(struct dsa_switch *ds, int port,
-                                const struct switchdev_obj_port_vlan *vlan)
+                                const struct switchdev_obj_port_vlan *vlan,
+                                struct netlink_ext_ack *extack)
 {
        struct ksz_device *dev = ds->priv;
        u32 vlan_table[3];
@@ -520,7 +521,7 @@ static int ksz9477_port_vlan_add(struct dsa_switch *ds, int port,
 
        err = ksz9477_get_vlan_table(dev, vlan->vid, vlan_table);
        if (err) {
-               dev_dbg(dev->dev, "Failed to get vlan table\n");
+               NL_SET_ERR_MSG_MOD(extack, "Failed to get vlan table");
                return err;
        }
 
@@ -535,7 +536,7 @@ static int ksz9477_port_vlan_add(struct dsa_switch *ds, int port,
 
        err = ksz9477_set_vlan_table(dev, vlan->vid, vlan_table);
        if (err) {
-               dev_dbg(dev->dev, "Failed to set vlan table\n");
+               NL_SET_ERR_MSG_MOD(extack, "Failed to set vlan table");
                return err;
        }
 
index eb13ba79dd018fb93d53b7f6326407b1249968cb..c089cd48e65def1b35bffe2446e1936f9967ac3c 100644 (file)
@@ -1483,7 +1483,8 @@ mt7530_hw_vlan_update(struct mt7530_priv *priv, u16 vid,
 
 static int
 mt7530_port_vlan_add(struct dsa_switch *ds, int port,
-                    const struct switchdev_obj_port_vlan *vlan)
+                    const struct switchdev_obj_port_vlan *vlan,
+                    struct netlink_ext_ack *extack)
 {
        bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
        bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
index 0ef1fadfec68ec4f5da7def078a40d15712d3828..d46f0c096c9713bc2bbc105ff320d9bebc99403c 100644 (file)
@@ -1982,7 +1982,8 @@ static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port,
 }
 
 static int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
-                                  const struct switchdev_obj_port_vlan *vlan)
+                                  const struct switchdev_obj_port_vlan *vlan,
+                                  struct netlink_ext_ack *extack)
 {
        struct mv88e6xxx_chip *chip = ds->priv;
        bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
index 336d93d03a9a9f2e0622afd6b0a8f914cd19d1ff..3951189e5a9ab54f1ef1aa0d06436df34ebbb338 100644 (file)
@@ -789,7 +789,8 @@ static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
 }
 
 static int felix_vlan_add(struct dsa_switch *ds, int port,
-                         const struct switchdev_obj_port_vlan *vlan)
+                         const struct switchdev_obj_port_vlan *vlan,
+                         struct netlink_ext_ack *extack)
 {
        struct ocelot *ocelot = ds->priv;
        u16 flags = vlan->flags;
index 6127823d6c2e440dd6b1c7167250ea97f4c92b71..73978e7e85cd29bde6977c3ff5a189f073c5fc60 100644 (file)
@@ -1313,7 +1313,8 @@ qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
 
 static int
 qca8k_port_vlan_add(struct dsa_switch *ds, int port,
-                   const struct switchdev_obj_port_vlan *vlan)
+                   const struct switchdev_obj_port_vlan *vlan,
+                   struct netlink_ext_ack *extack)
 {
        bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
        bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
index 26376b052594a6342ea4e6394d97c194eec02e66..93a3e05a6f711c5455d7856196377a43c0a5f38f 100644 (file)
@@ -133,7 +133,8 @@ int rtl8366_init_vlan(struct realtek_smi *smi);
 int rtl8366_vlan_filtering(struct dsa_switch *ds, int port,
                           bool vlan_filtering);
 int rtl8366_vlan_add(struct dsa_switch *ds, int port,
-                    const struct switchdev_obj_port_vlan *vlan);
+                    const struct switchdev_obj_port_vlan *vlan,
+                    struct netlink_ext_ack *extack);
 int rtl8366_vlan_del(struct dsa_switch *ds, int port,
                     const struct switchdev_obj_port_vlan *vlan);
 void rtl8366_get_strings(struct dsa_switch *ds, int port, u32 stringset,
index 3b24f2e13200add32b97987d03ec08992848bdad..76303a77aa8290d7e45d01b3e9f0f59c60ea1ab9 100644 (file)
@@ -375,7 +375,8 @@ int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
 EXPORT_SYMBOL_GPL(rtl8366_vlan_filtering);
 
 int rtl8366_vlan_add(struct dsa_switch *ds, int port,
-                    const struct switchdev_obj_port_vlan *vlan)
+                    const struct switchdev_obj_port_vlan *vlan,
+                    struct netlink_ext_ack *extack)
 {
        bool untagged = !!(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
        bool pvid = !!(vlan->flags & BRIDGE_VLAN_INFO_PVID);
@@ -384,16 +385,20 @@ int rtl8366_vlan_add(struct dsa_switch *ds, int port,
        u32 untag = 0;
        int ret;
 
-       if (!smi->ops->is_vlan_valid(smi, vlan->vid))
+       if (!smi->ops->is_vlan_valid(smi, vlan->vid)) {
+               NL_SET_ERR_MSG_MOD(extack, "VLAN ID not valid");
                return -EINVAL;
+       }
 
        /* Enable VLAN in the hardware
         * FIXME: what's with this 4k business?
         * Just rtl8366_enable_vlan() seems inconclusive.
         */
        ret = rtl8366_enable_vlan4k(smi, true);
-       if (ret)
+       if (ret) {
+               NL_SET_ERR_MSG_MOD(extack, "Failed to enable VLAN 4K");
                return ret;
+       }
 
        dev_info(smi->dev, "add VLAN %d on port %d, %s, %s\n",
                 vlan->vid, port, untagged ? "untagged" : "tagged",
index 1dad94540cc9c256182d742cfa4c5bf94f240125..92c7cea3ce6ebacbcf75786370a4c93d83e88de2 100644 (file)
@@ -2795,7 +2795,8 @@ static int sja1105_vlan_del_one(struct dsa_switch *ds, int port, u16 vid,
 }
 
 static int sja1105_vlan_add(struct dsa_switch *ds, int port,
-                           const struct switchdev_obj_port_vlan *vlan)
+                           const struct switchdev_obj_port_vlan *vlan,
+                           struct netlink_ext_ack *extack)
 {
        struct sja1105_private *priv = ds->priv;
        bool vlan_table_changed = false;
@@ -2807,7 +2808,8 @@ static int sja1105_vlan_add(struct dsa_switch *ds, int port,
         */
        if (priv->vlan_state != SJA1105_VLAN_FILTERING_FULL &&
            vid_is_dsa_8021q(vlan->vid)) {
-               dev_err(ds->dev, "Range 1024-3071 reserved for dsa_8021q operation\n");
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Range 1024-3071 reserved for dsa_8021q operation");
                return -EBUSY;
        }
 
index b095ef114fe8702cfcc2ce9417e83c9fd1bc66d0..01bd154798c52ccaddd8095fc661855191847889 100644 (file)
@@ -643,7 +643,8 @@ struct dsa_switch_ops {
        int     (*port_vlan_filtering)(struct dsa_switch *ds, int port,
                                       bool vlan_filtering);
        int     (*port_vlan_add)(struct dsa_switch *ds, int port,
-                                const struct switchdev_obj_port_vlan *vlan);
+                                const struct switchdev_obj_port_vlan *vlan,
+                                struct netlink_ext_ack *extack);
        int     (*port_vlan_del)(struct dsa_switch *ds, int port,
                                 const struct switchdev_obj_port_vlan *vlan);
        /*
index f5949b39f6f75bfa0c1166d18fc72d59048acdf0..17a9f82db937012cf337e484cab9108111c5752b 100644 (file)
@@ -75,6 +75,7 @@ struct dsa_notifier_vlan_info {
        const struct switchdev_obj_port_vlan *vlan;
        int sw_index;
        int port;
+       struct netlink_ext_ack *extack;
 };
 
 /* DSA_NOTIFIER_MTU */
@@ -192,7 +193,8 @@ int dsa_port_bridge_flags(const struct dsa_port *dp,
 int dsa_port_mrouter(struct dsa_port *dp, bool mrouter,
                     struct netlink_ext_ack *extack);
 int dsa_port_vlan_add(struct dsa_port *dp,
-                     const struct switchdev_obj_port_vlan *vlan);
+                     const struct switchdev_obj_port_vlan *vlan,
+                     struct netlink_ext_ack *extack);
 int dsa_port_vlan_del(struct dsa_port *dp,
                      const struct switchdev_obj_port_vlan *vlan);
 int dsa_port_link_register_of(struct dsa_port *dp);
index 80e6471a7a5c61ea01a8a3bd385ce093491f254a..03ecefe1064af3a3de9e549182332303b5814590 100644 (file)
@@ -535,12 +535,14 @@ int dsa_port_mdb_del(const struct dsa_port *dp,
 }
 
 int dsa_port_vlan_add(struct dsa_port *dp,
-                     const struct switchdev_obj_port_vlan *vlan)
+                     const struct switchdev_obj_port_vlan *vlan,
+                     struct netlink_ext_ack *extack)
 {
        struct dsa_notifier_vlan_info info = {
                .sw_index = dp->ds->index,
                .port = dp->index,
                .vlan = vlan,
+               .extack = extack,
        };
 
        return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info);
index 8c9a41a7209ac761939a7a810e348099d15af468..9ec487b63e13b462e4fc692a2ff06fd3507b6d9f 100644 (file)
@@ -357,11 +357,14 @@ static int dsa_slave_vlan_add(struct net_device *dev,
                rcu_read_lock();
                err = dsa_slave_vlan_check_for_8021q_uppers(dev, &vlan);
                rcu_read_unlock();
-               if (err)
+               if (err) {
+                       NL_SET_ERR_MSG_MOD(extack,
+                                          "Port already has a VLAN upper with this VID");
                        return err;
+               }
        }
 
-       err = dsa_port_vlan_add(dp, &vlan);
+       err = dsa_port_vlan_add(dp, &vlan, extack);
        if (err)
                return err;
 
@@ -371,7 +374,7 @@ static int dsa_slave_vlan_add(struct net_device *dev,
         */
        vlan.flags &= ~BRIDGE_VLAN_INFO_PVID;
 
-       err = dsa_port_vlan_add(dp->cpu_dp, &vlan);
+       err = dsa_port_vlan_add(dp->cpu_dp, &vlan, extack);
        if (err)
                return err;
 
@@ -1287,17 +1290,25 @@ static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
                /* This API only allows programming tagged, non-PVID VIDs */
                .flags = 0,
        };
+       struct netlink_ext_ack extack = {0};
        int ret;
 
        /* User port... */
-       ret = dsa_port_vlan_add(dp, &vlan);
-       if (ret)
+       ret = dsa_port_vlan_add(dp, &vlan, &extack);
+       if (ret) {
+               if (extack._msg)
+                       netdev_err(dev, "%s\n", extack._msg);
                return ret;
+       }
 
        /* And CPU port... */
-       ret = dsa_port_vlan_add(dp->cpu_dp, &vlan);
-       if (ret)
+       ret = dsa_port_vlan_add(dp->cpu_dp, &vlan, &extack);
+       if (ret) {
+               if (extack._msg)
+                       netdev_err(dev, "CPU port %d: %s\n", dp->cpu_dp->index,
+                                  extack._msg);
                return ret;
+       }
 
        return vlan_vid_add(master, proto, vid);
 }
index 1906179e59f78220b46613f0e1592917e100191c..c82d201181a5bc56ff68f474f160f946d7fc76a5 100644 (file)
@@ -291,7 +291,8 @@ static int dsa_switch_vlan_add(struct dsa_switch *ds,
 
        for (port = 0; port < ds->num_ports; port++) {
                if (dsa_switch_vlan_match(ds, port, info)) {
-                       err = ds->ops->port_vlan_add(ds, port, info->vlan);
+                       err = ds->ops->port_vlan_add(ds, port, info->vlan,
+                                                    info->extack);
                        if (err)
                                return err;
                }