]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net: dsa: propagate extack to .port_vlan_filtering
authorVladimir Oltean <vladimir.oltean@nxp.com>
Sat, 13 Feb 2021 20:43:19 +0000 (22:43 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 15 Feb 2021 01:38:12 +0000 (17:38 -0800)
Some drivers can't dynamically change the VLAN filtering option, or
impose some restrictions, it would be nice to propagate this info
through netlink instead of printing it to a kernel log that might never
be read. Also netlink extack includes the module that emitted the
message, which means that it's easier to figure out which ones are
driver-generated errors as opposed to command misuse.

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>
21 files changed:
drivers/net/dsa/b53/b53_common.c
drivers/net/dsa/b53/b53_priv.h
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.h
drivers/net/dsa/sja1105/sja1105_devlink.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 98cc051e513ebc4681320b04e33e9c57377b673d..ae86ded1e2a1849e38a9d3ec2ff9268478d82d34 100644 (file)
@@ -1409,7 +1409,8 @@ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port,
 }
 EXPORT_SYMBOL(b53_phylink_mac_link_up);
 
-int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
+int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
+                      struct netlink_ext_ack *extack)
 {
        struct b53_device *dev = ds->priv;
 
index fc5d6fddb3fe425211142006816f595ad3e45c55..faf983fbca82a76ae532b3d0b011c9d2e55d0889 100644 (file)
@@ -346,7 +346,8 @@ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port,
                             struct phy_device *phydev,
                             int speed, int duplex,
                             bool tx_pause, bool rx_pause);
-int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering);
+int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
+                      struct netlink_ext_ack *extack);
 int b53_vlan_add(struct dsa_switch *ds, int port,
                 const struct switchdev_obj_port_vlan *vlan,
                 struct netlink_ext_ack *extack);
index e55b63a7e9073148146bd7bd36d68a985574e6ab..bfdf3324aac3a24172b096ef48c05d656a633a38 100644 (file)
@@ -190,7 +190,8 @@ static void dsa_loop_port_stp_state_set(struct dsa_switch *ds, int port,
 }
 
 static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port,
-                                       bool vlan_filtering)
+                                       bool vlan_filtering,
+                                       struct netlink_ext_ack *extack)
 {
        dev_dbg(ds->dev, "%s: port: %d, vlan_filtering: %d\n",
                __func__, port, vlan_filtering);
index 5816ef922e553916d5bb1170962dc37fdb41e895..463137c39db25ade14b0f6d71b7c3a3ecd44ab18 100644 (file)
@@ -875,7 +875,8 @@ static int hellcreek_fdb_dump(struct dsa_switch *ds, int port,
 }
 
 static int hellcreek_vlan_filtering(struct dsa_switch *ds, int port,
-                                   bool vlan_filtering)
+                                   bool vlan_filtering,
+                                   struct netlink_ext_ack *extack)
 {
        struct hellcreek *hellcreek = ds->priv;
 
index 174ca3a484a09da0407c0c66ec5ff551e2d314b8..52e865a3912cfc651edc9b5a87f2a8430121bf2d 100644 (file)
@@ -727,14 +727,18 @@ static int gswip_pce_load_microcode(struct gswip_priv *priv)
 }
 
 static int gswip_port_vlan_filtering(struct dsa_switch *ds, int port,
-                                    bool vlan_filtering)
+                                    bool vlan_filtering,
+                                    struct netlink_ext_ack *extack)
 {
        struct net_device *bridge = dsa_to_port(ds, port)->bridge_dev;
        struct gswip_priv *priv = ds->priv;
 
        /* Do not allow changing the VLAN filtering options while in bridge */
-       if (bridge && !!(priv->port_vlan_filter & BIT(port)) != vlan_filtering)
+       if (bridge && !!(priv->port_vlan_filter & BIT(port)) != vlan_filtering) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Dynamic toggling of vlan_filtering not supported");
                return -EIO;
+       }
 
        if (vlan_filtering) {
                /* Use port based VLAN tag */
@@ -773,7 +777,7 @@ static int gswip_setup(struct dsa_switch *ds)
        /* disable port fetch/store dma on all ports */
        for (i = 0; i < priv->hw_info->max_ports; i++) {
                gswip_port_disable(ds, i);
-               gswip_port_vlan_filtering(ds, i, false);
+               gswip_port_vlan_filtering(ds, i, false, NULL);
        }
 
        /* enable Switch */
index 1e27a3e581413f72fdd21681b26bc4d49a379d9d..b4b7de63ca7933969837a633c4aa4acd3e44f96a 100644 (file)
@@ -783,7 +783,8 @@ static void ksz8795_flush_dyn_mac_table(struct ksz_device *dev, int port)
 }
 
 static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port,
-                                      bool flag)
+                                      bool flag,
+                                      struct netlink_ext_ack *extack)
 {
        struct ksz_device *dev = ds->priv;
 
index 772e34d5b6b8ad62ecdb8e25fe72f8840179c2cc..55e5d479acce332046aa177ddbcc72f6e5920c09 100644 (file)
@@ -493,7 +493,8 @@ static void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port)
 }
 
 static int ksz9477_port_vlan_filtering(struct dsa_switch *ds, int port,
-                                      bool flag)
+                                      bool flag,
+                                      struct netlink_ext_ack *extack)
 {
        struct ksz_device *dev = ds->priv;
 
index c089cd48e65def1b35bffe2446e1936f9967ac3c..c17de2bcf2fef7233efc3f047ffb54c3ac71815d 100644 (file)
@@ -1376,8 +1376,8 @@ mt7530_vlan_cmd(struct mt7530_priv *priv, enum mt7530_vlan_cmd cmd, u16 vid)
 }
 
 static int
-mt7530_port_vlan_filtering(struct dsa_switch *ds, int port,
-                          bool vlan_filtering)
+mt7530_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
+                          struct netlink_ext_ack *extack)
 {
        if (vlan_filtering) {
                /* The port is being kept as VLAN-unaware port when bridge is
index d46f0c096c9713bc2bbc105ff320d9bebc99403c..903d619e08ed1e6e6ca5ae363f8750e86a24b846 100644 (file)
@@ -1600,7 +1600,8 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
 }
 
 static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
-                                        bool vlan_filtering)
+                                        bool vlan_filtering,
+                                        struct netlink_ext_ack *extack)
 {
        struct mv88e6xxx_chip *chip = ds->priv;
        u16 mode = vlan_filtering ? MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE :
index 3951189e5a9ab54f1ef1aa0d06436df34ebbb338..800f27d65c6ce6f7b691a64f1221ac1ff0a28ae3 100644 (file)
@@ -781,7 +781,8 @@ static int felix_vlan_prepare(struct dsa_switch *ds, int port,
                                   flags & BRIDGE_VLAN_INFO_UNTAGGED);
 }
 
-static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
+static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled,
+                               struct netlink_ext_ack *extack)
 {
        struct ocelot *ocelot = ds->priv;
 
index 73978e7e85cd29bde6977c3ff5a189f073c5fc60..cdaf9f85a2cb9a2e20e3c1e128ff52ce7de2b56a 100644 (file)
@@ -1294,7 +1294,8 @@ qca8k_port_fdb_dump(struct dsa_switch *ds, int port,
 }
 
 static int
-qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
+qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
+                         struct netlink_ext_ack *extack)
 {
        struct qca8k_priv *priv = ds->priv;
 
index 93a3e05a6f711c5455d7856196377a43c0a5f38f..fcf465f7f92266a63b87e710a7cd8f360b313fde 100644 (file)
@@ -130,8 +130,8 @@ int rtl8366_enable_vlan4k(struct realtek_smi *smi, bool enable);
 int rtl8366_enable_vlan(struct realtek_smi *smi, bool enable);
 int rtl8366_reset_vlan(struct realtek_smi *smi);
 int rtl8366_init_vlan(struct realtek_smi *smi);
-int rtl8366_vlan_filtering(struct dsa_switch *ds, int port,
-                          bool vlan_filtering);
+int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
+                          struct netlink_ext_ack *extack);
 int rtl8366_vlan_add(struct dsa_switch *ds, int port,
                     const struct switchdev_obj_port_vlan *vlan,
                     struct netlink_ext_ack *extack);
index 76303a77aa8290d7e45d01b3e9f0f59c60ea1ab9..75897a3690969fdc5f4e5fcb2dd523d2900530a6 100644 (file)
@@ -340,7 +340,8 @@ int rtl8366_init_vlan(struct realtek_smi *smi)
 }
 EXPORT_SYMBOL_GPL(rtl8366_init_vlan);
 
-int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
+int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
+                          struct netlink_ext_ack *extack)
 {
        struct realtek_smi *smi = ds->priv;
        struct rtl8366_vlan_4k vlan4k;
index 15a0893d0ff1530cf143ca78ab5fd2fe7bc42051..90f0f6f3124e4aed6b7a5b66456bd051051f57bf 100644 (file)
@@ -247,7 +247,8 @@ enum sja1105_reset_reason {
 
 int sja1105_static_config_reload(struct sja1105_private *priv,
                                 enum sja1105_reset_reason reason);
-int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled);
+int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled,
+                          struct netlink_ext_ack *extack);
 void sja1105_frame_memory_partitioning(struct sja1105_private *priv);
 
 /* From sja1105_devlink.c */
index b4bf1b10e66cabc1d7b4d34a700a39573272492b..b6a4a16b8c7e1a6030a684ee8f39a702ee7c42d9 100644 (file)
@@ -143,7 +143,7 @@ static int sja1105_best_effort_vlan_filtering_set(struct sja1105_private *priv,
                dp = dsa_to_port(ds, port);
                vlan_filtering = dsa_port_is_vlan_filtering(dp);
 
-               rc = sja1105_vlan_filtering(ds, port, vlan_filtering);
+               rc = sja1105_vlan_filtering(ds, port, vlan_filtering, NULL);
                if (rc)
                        break;
        }
index 92c7cea3ce6ebacbcf75786370a4c93d83e88de2..0818a67a7b2d41229e55f8488b0fd78f2ce85f06 100644 (file)
@@ -2639,7 +2639,8 @@ out:
  * which can only be partially reconfigured at runtime (and not the TPID).
  * So a switch reset is required.
  */
-int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
+int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled,
+                          struct netlink_ext_ack *extack)
 {
        struct sja1105_l2_lookup_params_entry *l2_lookup_params;
        struct sja1105_general_params_entry *general_params;
@@ -2653,8 +2654,8 @@ int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
 
        list_for_each_entry(rule, &priv->flow_block.rules, list) {
                if (rule->type == SJA1105_RULE_VL) {
-                       dev_err(ds->dev,
-                               "Cannot change VLAN filtering with active VL rules\n");
+                       NL_SET_ERR_MSG_MOD(extack,
+                                          "Cannot change VLAN filtering with active VL rules");
                        return -EBUSY;
                }
        }
@@ -2736,7 +2737,7 @@ int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
 
        rc = sja1105_static_config_reload(priv, SJA1105_VLAN_FILTERING);
        if (rc)
-               dev_err(ds->dev, "Failed to change VLAN Ethertype\n");
+               NL_SET_ERR_MSG_MOD(extack, "Failed to change VLAN Ethertype");
 
        /* Switch port identification based on 802.1Q is only passable
         * if we are not under a vlan_filtering bridge. So make sure
index 01bd154798c52ccaddd8095fc661855191847889..68f8159564a36cff2010472bf606fce8c6ec9ce1 100644 (file)
@@ -641,7 +641,8 @@ struct dsa_switch_ops {
         * VLAN support
         */
        int     (*port_vlan_filtering)(struct dsa_switch *ds, int port,
-                                      bool vlan_filtering);
+                                      bool vlan_filtering,
+                                      struct netlink_ext_ack *extack);
        int     (*port_vlan_add)(struct dsa_switch *ds, int port,
                                 const struct switchdev_obj_port_vlan *vlan,
                                 struct netlink_ext_ack *extack);
index 17a9f82db937012cf337e484cab9108111c5752b..e9d1e76c42ba261fde9599fb8232425caae2066b 100644 (file)
@@ -170,7 +170,8 @@ int dsa_port_lag_change(struct dsa_port *dp,
 int dsa_port_lag_join(struct dsa_port *dp, struct net_device *lag_dev,
                      struct netdev_lag_upper_info *uinfo);
 void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag_dev);
-int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering);
+int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
+                           struct netlink_ext_ack *extack);
 bool dsa_port_skip_vlan_configuration(struct dsa_port *dp);
 int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock);
 int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu,
index 03ecefe1064af3a3de9e549182332303b5814590..14a1d0d776573d381ed0cbbc5fcb5dbd59f1c83e 100644 (file)
@@ -294,7 +294,8 @@ void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag)
 
 /* Must be called under rcu_read_lock() */
 static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp,
-                                             bool vlan_filtering)
+                                             bool vlan_filtering,
+                                             struct netlink_ext_ack *extack)
 {
        struct dsa_switch *ds = dp->ds;
        int err, i;
@@ -324,8 +325,8 @@ static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp,
                         */
                        err = br_vlan_get_info(br, vid, &br_info);
                        if (err == 0) {
-                               dev_err(ds->dev, "Must remove upper %s first\n",
-                                       upper_dev->name);
+                               NL_SET_ERR_MSG_MOD(extack,
+                                                  "Must first remove VLAN uppers having VIDs also present in bridge");
                                return false;
                        }
                }
@@ -351,14 +352,16 @@ static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp,
                if (other_bridge == dp->bridge_dev)
                        continue;
                if (br_vlan_enabled(other_bridge) != vlan_filtering) {
-                       dev_err(ds->dev, "VLAN filtering is a global setting\n");
+                       NL_SET_ERR_MSG_MOD(extack,
+                                          "VLAN filtering is a global setting");
                        return false;
                }
        }
        return true;
 }
 
-int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering)
+int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
+                           struct netlink_ext_ack *extack)
 {
        struct dsa_switch *ds = dp->ds;
        bool apply;
@@ -372,7 +375,7 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering)
         * dsa_slave_switchdev_event().
         */
        rcu_read_lock();
-       apply = dsa_port_can_apply_vlan_filtering(dp, vlan_filtering);
+       apply = dsa_port_can_apply_vlan_filtering(dp, vlan_filtering, extack);
        rcu_read_unlock();
        if (!apply)
                return -EINVAL;
@@ -380,7 +383,8 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering)
        if (dsa_port_is_vlan_filtering(dp) == vlan_filtering)
                return 0;
 
-       err = ds->ops->port_vlan_filtering(ds, dp->index, vlan_filtering);
+       err = ds->ops->port_vlan_filtering(ds, dp->index, vlan_filtering,
+                                          extack);
        if (err)
                return err;
 
index 9ec487b63e13b462e4fc692a2ff06fd3507b6d9f..5ecb43a1b6e07b6ef356002a8bbd5f6738ec1152 100644 (file)
@@ -286,7 +286,8 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
                ret = dsa_port_set_state(dp, attr->u.stp_state);
                break;
        case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
-               ret = dsa_port_vlan_filtering(dp, attr->u.vlan_filtering);
+               ret = dsa_port_vlan_filtering(dp, attr->u.vlan_filtering,
+                                             extack);
                break;
        case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
                ret = dsa_port_ageing_time(dp, attr->u.ageing_time);
index c82d201181a5bc56ff68f474f160f946d7fc76a5..db2a9b22198891582111523e8ee850fe8d1f03a7 100644 (file)
@@ -106,6 +106,7 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds,
 {
        bool unset_vlan_filtering = br_vlan_enabled(info->br);
        struct dsa_switch_tree *dst = ds->dst;
+       struct netlink_ext_ack extack = {0};
        int err, i;
 
        if (dst->index == info->tree_index && ds->index == info->sw_index &&
@@ -137,7 +138,10 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds,
        }
        if (unset_vlan_filtering) {
                err = dsa_port_vlan_filtering(dsa_to_port(ds, info->port),
-                                             false);
+                                             false, &extack);
+               if (extack._msg)
+                       dev_err(ds->dev, "port %d: %s\n", info->port,
+                               extack._msg);
                if (err && err != EOPNOTSUPP)
                        return err;
        }