b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | From 4d776482ecc689bdd68627985ac4cb5a6f325953 Mon Sep 17 00:00:00 2001 |
| 2 | From: Florian Fainelli <f.fainelli@gmail.com> |
| 3 | Date: Tue, 7 Jan 2020 21:06:05 -0800 |
| 4 | Subject: [PATCH] net: dsa: Get information about stacked DSA protocol |
| 5 | |
| 6 | It is possible to stack multiple DSA switches in a way that they are not |
| 7 | part of the tree (disjoint) but the DSA master of a switch is a DSA |
| 8 | slave of another. When that happens switch drivers may have to know this |
| 9 | is the case so as to determine whether their tagging protocol has a |
| 10 | remove chance of working. |
| 11 | |
| 12 | This is useful for specific switch drivers such as b53 where devices |
| 13 | have been known to be stacked in the wild without the Broadcom tag |
| 14 | protocol supporting that feature. This allows b53 to continue supporting |
| 15 | those devices by forcing the disabling of Broadcom tags on the outermost |
| 16 | switches if necessary. |
| 17 | |
| 18 | The get_tag_protocol() function is therefore updated to gain an |
| 19 | additional enum dsa_tag_protocol argument which denotes the current |
| 20 | tagging protocol used by the DSA master we are attached to, else |
| 21 | DSA_TAG_PROTO_NONE for the top of the dsa_switch_tree. |
| 22 | |
| 23 | Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> |
| 24 | Signed-off-by: David S. Miller <davem@davemloft.net> |
| 25 | --- |
| 26 | drivers/net/dsa/b53/b53_common.c | 22 +++++++++++------- |
| 27 | drivers/net/dsa/b53/b53_priv.h | 4 +++- |
| 28 | drivers/net/dsa/dsa_loop.c | 3 ++- |
| 29 | drivers/net/dsa/lan9303-core.c | 3 ++- |
| 30 | drivers/net/dsa/lantiq_gswip.c | 3 ++- |
| 31 | drivers/net/dsa/microchip/ksz8795.c | 3 ++- |
| 32 | drivers/net/dsa/microchip/ksz9477.c | 3 ++- |
| 33 | drivers/net/dsa/mt7530.c | 3 ++- |
| 34 | drivers/net/dsa/mv88e6060.c | 3 ++- |
| 35 | drivers/net/dsa/mv88e6xxx/chip.c | 3 ++- |
| 36 | drivers/net/dsa/ocelot/felix.c | 3 ++- |
| 37 | drivers/net/dsa/qca/ar9331.c | 3 ++- |
| 38 | drivers/net/dsa/qca8k.c | 3 ++- |
| 39 | drivers/net/dsa/rtl8366rb.c | 3 ++- |
| 40 | drivers/net/dsa/sja1105/sja1105_main.c | 3 ++- |
| 41 | drivers/net/dsa/vitesse-vsc73xx-core.c | 3 ++- |
| 42 | include/net/dsa.h | 3 ++- |
| 43 | net/dsa/dsa2.c | 31 ++++++++++++++++++++++++-- |
| 44 | net/dsa/dsa_priv.h | 1 + |
| 45 | net/dsa/slave.c | 4 +--- |
| 46 | 20 files changed, 78 insertions(+), 29 deletions(-) |
| 47 | |
| 48 | --- a/drivers/net/dsa/b53/b53_common.c |
| 49 | +++ b/drivers/net/dsa/b53/b53_common.c |
| 50 | @@ -587,9 +587,8 @@ EXPORT_SYMBOL(b53_disable_port); |
| 51 | |
| 52 | void b53_brcm_hdr_setup(struct dsa_switch *ds, int port) |
| 53 | { |
| 54 | - bool tag_en = !(ds->ops->get_tag_protocol(ds, port) == |
| 55 | - DSA_TAG_PROTO_NONE); |
| 56 | struct b53_device *dev = ds->priv; |
| 57 | + bool tag_en = !(dev->tag_protocol == DSA_TAG_PROTO_NONE); |
| 58 | u8 hdr_ctl, val; |
| 59 | u16 reg; |
| 60 | |
| 61 | @@ -1921,7 +1920,8 @@ static bool b53_can_enable_brcm_tags(str |
| 62 | return ret; |
| 63 | } |
| 64 | |
| 65 | -enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds, int port) |
| 66 | +enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds, int port, |
| 67 | + enum dsa_tag_protocol mprot) |
| 68 | { |
| 69 | struct b53_device *dev = ds->priv; |
| 70 | |
| 71 | @@ -1931,16 +1931,22 @@ enum dsa_tag_protocol b53_get_tag_protoc |
| 72 | * misses on multicast addresses (TBD). |
| 73 | */ |
| 74 | if (is5325(dev) || is5365(dev) || is539x(dev) || is531x5(dev) || |
| 75 | - !b53_can_enable_brcm_tags(ds, port)) |
| 76 | - return DSA_TAG_PROTO_NONE; |
| 77 | + !b53_can_enable_brcm_tags(ds, port)) { |
| 78 | + dev->tag_protocol = DSA_TAG_PROTO_NONE; |
| 79 | + goto out; |
| 80 | + } |
| 81 | |
| 82 | /* Broadcom BCM58xx chips have a flow accelerator on Port 8 |
| 83 | * which requires us to use the prepended Broadcom tag type |
| 84 | */ |
| 85 | - if (dev->chip_id == BCM58XX_DEVICE_ID && port == B53_CPU_PORT) |
| 86 | - return DSA_TAG_PROTO_BRCM_PREPEND; |
| 87 | + if (dev->chip_id == BCM58XX_DEVICE_ID && port == B53_CPU_PORT) { |
| 88 | + dev->tag_protocol = DSA_TAG_PROTO_BRCM_PREPEND; |
| 89 | + goto out; |
| 90 | + } |
| 91 | |
| 92 | - return DSA_TAG_PROTO_BRCM; |
| 93 | + dev->tag_protocol = DSA_TAG_PROTO_BRCM; |
| 94 | +out: |
| 95 | + return dev->tag_protocol; |
| 96 | } |
| 97 | EXPORT_SYMBOL(b53_get_tag_protocol); |
| 98 | |
| 99 | --- a/drivers/net/dsa/b53/b53_priv.h |
| 100 | +++ b/drivers/net/dsa/b53/b53_priv.h |
| 101 | @@ -118,6 +118,7 @@ struct b53_device { |
| 102 | u8 jumbo_size_reg; |
| 103 | int reset_gpio; |
| 104 | u8 num_arl_entries; |
| 105 | + enum dsa_tag_protocol tag_protocol; |
| 106 | |
| 107 | /* used ports mask */ |
| 108 | u16 enabled_ports; |
| 109 | @@ -359,7 +360,8 @@ int b53_mdb_del(struct dsa_switch *ds, i |
| 110 | const struct switchdev_obj_port_mdb *mdb); |
| 111 | int b53_mirror_add(struct dsa_switch *ds, int port, |
| 112 | struct dsa_mall_mirror_tc_entry *mirror, bool ingress); |
| 113 | -enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds, int port); |
| 114 | +enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds, int port, |
| 115 | + enum dsa_tag_protocol mprot); |
| 116 | void b53_mirror_del(struct dsa_switch *ds, int port, |
| 117 | struct dsa_mall_mirror_tc_entry *mirror); |
| 118 | int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy); |
| 119 | --- a/drivers/net/dsa/dsa_loop.c |
| 120 | +++ b/drivers/net/dsa/dsa_loop.c |
| 121 | @@ -61,7 +61,8 @@ struct dsa_loop_priv { |
| 122 | static struct phy_device *phydevs[PHY_MAX_ADDR]; |
| 123 | |
| 124 | static enum dsa_tag_protocol dsa_loop_get_protocol(struct dsa_switch *ds, |
| 125 | - int port) |
| 126 | + int port, |
| 127 | + enum dsa_tag_protocol mp) |
| 128 | { |
| 129 | dev_dbg(ds->dev, "%s: port: %d\n", __func__, port); |
| 130 | |
| 131 | --- a/drivers/net/dsa/lan9303-core.c |
| 132 | +++ b/drivers/net/dsa/lan9303-core.c |
| 133 | @@ -889,7 +889,8 @@ static int lan9303_check_device(struct l |
| 134 | /* ---------------------------- DSA -----------------------------------*/ |
| 135 | |
| 136 | static enum dsa_tag_protocol lan9303_get_tag_protocol(struct dsa_switch *ds, |
| 137 | - int port) |
| 138 | + int port, |
| 139 | + enum dsa_tag_protocol mp) |
| 140 | { |
| 141 | return DSA_TAG_PROTO_LAN9303; |
| 142 | } |
| 143 | --- a/drivers/net/dsa/lantiq_gswip.c |
| 144 | +++ b/drivers/net/dsa/lantiq_gswip.c |
| 145 | @@ -860,7 +860,8 @@ static int gswip_setup(struct dsa_switch |
| 146 | } |
| 147 | |
| 148 | static enum dsa_tag_protocol gswip_get_tag_protocol(struct dsa_switch *ds, |
| 149 | - int port) |
| 150 | + int port, |
| 151 | + enum dsa_tag_protocol mp) |
| 152 | { |
| 153 | return DSA_TAG_PROTO_GSWIP; |
| 154 | } |
| 155 | --- a/drivers/net/dsa/microchip/ksz8795.c |
| 156 | +++ b/drivers/net/dsa/microchip/ksz8795.c |
| 157 | @@ -645,7 +645,8 @@ static void ksz8795_w_phy(struct ksz_dev |
| 158 | } |
| 159 | |
| 160 | static enum dsa_tag_protocol ksz8795_get_tag_protocol(struct dsa_switch *ds, |
| 161 | - int port) |
| 162 | + int port, |
| 163 | + enum dsa_tag_protocol mp) |
| 164 | { |
| 165 | return DSA_TAG_PROTO_KSZ8795; |
| 166 | } |
| 167 | --- a/drivers/net/dsa/microchip/ksz9477.c |
| 168 | +++ b/drivers/net/dsa/microchip/ksz9477.c |
| 169 | @@ -295,7 +295,8 @@ static void ksz9477_port_init_cnt(struct |
| 170 | } |
| 171 | |
| 172 | static enum dsa_tag_protocol ksz9477_get_tag_protocol(struct dsa_switch *ds, |
| 173 | - int port) |
| 174 | + int port, |
| 175 | + enum dsa_tag_protocol mp) |
| 176 | { |
| 177 | enum dsa_tag_protocol proto = DSA_TAG_PROTO_KSZ9477; |
| 178 | struct ksz_device *dev = ds->priv; |
| 179 | --- a/drivers/net/dsa/mt7530.c |
| 180 | +++ b/drivers/net/dsa/mt7530.c |
| 181 | @@ -1144,7 +1144,8 @@ mt7530_port_vlan_del(struct dsa_switch * |
| 182 | } |
| 183 | |
| 184 | static enum dsa_tag_protocol |
| 185 | -mtk_get_tag_protocol(struct dsa_switch *ds, int port) |
| 186 | +mtk_get_tag_protocol(struct dsa_switch *ds, int port, |
| 187 | + enum dsa_tag_protocol mp) |
| 188 | { |
| 189 | struct mt7530_priv *priv = ds->priv; |
| 190 | |
| 191 | --- a/drivers/net/dsa/mv88e6060.c |
| 192 | +++ b/drivers/net/dsa/mv88e6060.c |
| 193 | @@ -43,7 +43,8 @@ static const char *mv88e6060_get_name(st |
| 194 | } |
| 195 | |
| 196 | static enum dsa_tag_protocol mv88e6060_get_tag_protocol(struct dsa_switch *ds, |
| 197 | - int port) |
| 198 | + int port, |
| 199 | + enum dsa_tag_protocol m) |
| 200 | { |
| 201 | return DSA_TAG_PROTO_TRAILER; |
| 202 | } |
| 203 | --- a/drivers/net/dsa/mv88e6xxx/chip.c |
| 204 | +++ b/drivers/net/dsa/mv88e6xxx/chip.c |
| 205 | @@ -4878,7 +4878,8 @@ static struct mv88e6xxx_chip *mv88e6xxx_ |
| 206 | } |
| 207 | |
| 208 | static enum dsa_tag_protocol mv88e6xxx_get_tag_protocol(struct dsa_switch *ds, |
| 209 | - int port) |
| 210 | + int port, |
| 211 | + enum dsa_tag_protocol m) |
| 212 | { |
| 213 | struct mv88e6xxx_chip *chip = ds->priv; |
| 214 | |
| 215 | --- a/drivers/net/dsa/qca8k.c |
| 216 | +++ b/drivers/net/dsa/qca8k.c |
| 217 | @@ -1016,7 +1016,8 @@ qca8k_port_fdb_dump(struct dsa_switch *d |
| 218 | } |
| 219 | |
| 220 | static enum dsa_tag_protocol |
| 221 | -qca8k_get_tag_protocol(struct dsa_switch *ds, int port) |
| 222 | +qca8k_get_tag_protocol(struct dsa_switch *ds, int port, |
| 223 | + enum dsa_tag_protocol mp) |
| 224 | { |
| 225 | return DSA_TAG_PROTO_QCA; |
| 226 | } |
| 227 | --- a/drivers/net/dsa/rtl8366rb.c |
| 228 | +++ b/drivers/net/dsa/rtl8366rb.c |
| 229 | @@ -964,7 +964,8 @@ static int rtl8366rb_setup(struct dsa_sw |
| 230 | } |
| 231 | |
| 232 | static enum dsa_tag_protocol rtl8366_get_tag_protocol(struct dsa_switch *ds, |
| 233 | - int port) |
| 234 | + int port, |
| 235 | + enum dsa_tag_protocol mp) |
| 236 | { |
| 237 | /* For now, the RTL switches are handled without any custom tags. |
| 238 | * |
| 239 | --- a/drivers/net/dsa/sja1105/sja1105_main.c |
| 240 | +++ b/drivers/net/dsa/sja1105/sja1105_main.c |
| 241 | @@ -1591,7 +1591,8 @@ static int sja1105_setup_8021q_tagging(s |
| 242 | } |
| 243 | |
| 244 | static enum dsa_tag_protocol |
| 245 | -sja1105_get_tag_protocol(struct dsa_switch *ds, int port) |
| 246 | +sja1105_get_tag_protocol(struct dsa_switch *ds, int port, |
| 247 | + enum dsa_tag_protocol mp) |
| 248 | { |
| 249 | return DSA_TAG_PROTO_SJA1105; |
| 250 | } |
| 251 | --- a/drivers/net/dsa/vitesse-vsc73xx-core.c |
| 252 | +++ b/drivers/net/dsa/vitesse-vsc73xx-core.c |
| 253 | @@ -542,7 +542,8 @@ static int vsc73xx_phy_write(struct dsa_ |
| 254 | } |
| 255 | |
| 256 | static enum dsa_tag_protocol vsc73xx_get_tag_protocol(struct dsa_switch *ds, |
| 257 | - int port) |
| 258 | + int port, |
| 259 | + enum dsa_tag_protocol mp) |
| 260 | { |
| 261 | /* The switch internally uses a 8 byte header with length, |
| 262 | * source port, tag, LPA and priority. This is supposedly |
| 263 | --- a/include/net/dsa.h |
| 264 | +++ b/include/net/dsa.h |
| 265 | @@ -353,7 +353,8 @@ typedef int dsa_fdb_dump_cb_t(const unsi |
| 266 | bool is_static, void *data); |
| 267 | struct dsa_switch_ops { |
| 268 | enum dsa_tag_protocol (*get_tag_protocol)(struct dsa_switch *ds, |
| 269 | - int port); |
| 270 | + int port, |
| 271 | + enum dsa_tag_protocol mprot); |
| 272 | |
| 273 | int (*setup)(struct dsa_switch *ds); |
| 274 | void (*teardown)(struct dsa_switch *ds); |
| 275 | --- a/net/dsa/dsa2.c |
| 276 | +++ b/net/dsa/dsa2.c |
| 277 | @@ -631,6 +631,32 @@ static int dsa_port_parse_dsa(struct dsa |
| 278 | return 0; |
| 279 | } |
| 280 | |
| 281 | +static enum dsa_tag_protocol dsa_get_tag_protocol(struct dsa_port *dp, |
| 282 | + struct net_device *master) |
| 283 | +{ |
| 284 | + enum dsa_tag_protocol tag_protocol = DSA_TAG_PROTO_NONE; |
| 285 | + struct dsa_switch *mds, *ds = dp->ds; |
| 286 | + unsigned int mdp_upstream; |
| 287 | + struct dsa_port *mdp; |
| 288 | + |
| 289 | + /* It is possible to stack DSA switches onto one another when that |
| 290 | + * happens the switch driver may want to know if its tagging protocol |
| 291 | + * is going to work in such a configuration. |
| 292 | + */ |
| 293 | + if (dsa_slave_dev_check(master)) { |
| 294 | + mdp = dsa_slave_to_port(master); |
| 295 | + mds = mdp->ds; |
| 296 | + mdp_upstream = dsa_upstream_port(mds, mdp->index); |
| 297 | + tag_protocol = mds->ops->get_tag_protocol(mds, mdp_upstream, |
| 298 | + DSA_TAG_PROTO_NONE); |
| 299 | + } |
| 300 | + |
| 301 | + /* If the master device is not itself a DSA slave in a disjoint DSA |
| 302 | + * tree, then return immediately. |
| 303 | + */ |
| 304 | + return ds->ops->get_tag_protocol(ds, dp->index, tag_protocol); |
| 305 | +} |
| 306 | + |
| 307 | static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master) |
| 308 | { |
| 309 | struct dsa_switch *ds = dp->ds; |
| 310 | @@ -638,20 +664,21 @@ static int dsa_port_parse_cpu(struct dsa |
| 311 | const struct dsa_device_ops *tag_ops; |
| 312 | enum dsa_tag_protocol tag_protocol; |
| 313 | |
| 314 | - tag_protocol = ds->ops->get_tag_protocol(ds, dp->index); |
| 315 | + tag_protocol = dsa_get_tag_protocol(dp, master); |
| 316 | tag_ops = dsa_tag_driver_get(tag_protocol); |
| 317 | if (IS_ERR(tag_ops)) { |
| 318 | if (PTR_ERR(tag_ops) == -ENOPROTOOPT) |
| 319 | return -EPROBE_DEFER; |
| 320 | dev_warn(ds->dev, "No tagger for this switch\n"); |
| 321 | + dp->master = NULL; |
| 322 | return PTR_ERR(tag_ops); |
| 323 | } |
| 324 | |
| 325 | + dp->master = master; |
| 326 | dp->type = DSA_PORT_TYPE_CPU; |
| 327 | dp->filter = tag_ops->filter; |
| 328 | dp->rcv = tag_ops->rcv; |
| 329 | dp->tag_ops = tag_ops; |
| 330 | - dp->master = master; |
| 331 | dp->dst = dst; |
| 332 | |
| 333 | return 0; |
| 334 | --- a/net/dsa/dsa_priv.h |
| 335 | +++ b/net/dsa/dsa_priv.h |
| 336 | @@ -189,6 +189,7 @@ extern const struct dsa_device_ops notag |
| 337 | void dsa_slave_mii_bus_init(struct dsa_switch *ds); |
| 338 | int dsa_slave_create(struct dsa_port *dp); |
| 339 | void dsa_slave_destroy(struct net_device *slave_dev); |
| 340 | +bool dsa_slave_dev_check(const struct net_device *dev); |
| 341 | int dsa_slave_suspend(struct net_device *slave_dev); |
| 342 | int dsa_slave_resume(struct net_device *slave_dev); |
| 343 | int dsa_slave_register_notifier(void); |
| 344 | --- a/net/dsa/slave.c |
| 345 | +++ b/net/dsa/slave.c |
| 346 | @@ -22,8 +22,6 @@ |
| 347 | |
| 348 | #include "dsa_priv.h" |
| 349 | |
| 350 | -static bool dsa_slave_dev_check(const struct net_device *dev); |
| 351 | - |
| 352 | /* slave mii_bus handling ***************************************************/ |
| 353 | static int dsa_slave_phy_read(struct mii_bus *bus, int addr, int reg) |
| 354 | { |
| 355 | @@ -1494,7 +1492,7 @@ void dsa_slave_destroy(struct net_device |
| 356 | free_netdev(slave_dev); |
| 357 | } |
| 358 | |
| 359 | -static bool dsa_slave_dev_check(const struct net_device *dev) |
| 360 | +bool dsa_slave_dev_check(const struct net_device *dev) |
| 361 | { |
| 362 | return dev->netdev_ops == &dsa_slave_netdev_ops; |
| 363 | } |