1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Handling of a single switch chip, part of a switch fabric 4 * 5 * Copyright (c) 2017 Savoir-faire Linux Inc. 6 * Vivien Didelot <vivien.didelot@savoirfairelinux.com> 7 */ 8 9 #include <linux/if_bridge.h> 10 #include <linux/netdevice.h> 11 #include <linux/notifier.h> 12 #include <linux/if_vlan.h> 13 #include <net/switchdev.h> 14 15 #include "dsa_priv.h" 16 17 static unsigned int dsa_switch_fastest_ageing_time(struct dsa_switch *ds, 18 unsigned int ageing_time) 19 { 20 int i; 21 22 for (i = 0; i < ds->num_ports; ++i) { 23 struct dsa_port *dp = dsa_to_port(ds, i); 24 25 if (dp->ageing_time && dp->ageing_time < ageing_time) 26 ageing_time = dp->ageing_time; 27 } 28 29 return ageing_time; 30 } 31 32 static int dsa_switch_ageing_time(struct dsa_switch *ds, 33 struct dsa_notifier_ageing_time_info *info) 34 { 35 unsigned int ageing_time = info->ageing_time; 36 37 if (ds->ageing_time_min && ageing_time < ds->ageing_time_min) 38 return -ERANGE; 39 40 if (ds->ageing_time_max && ageing_time > ds->ageing_time_max) 41 return -ERANGE; 42 43 /* Program the fastest ageing time in case of multiple bridges */ 44 ageing_time = dsa_switch_fastest_ageing_time(ds, ageing_time); 45 46 if (ds->ops->set_ageing_time) 47 return ds->ops->set_ageing_time(ds, ageing_time); 48 49 return 0; 50 } 51 52 static bool dsa_switch_mtu_match(struct dsa_switch *ds, int port, 53 struct dsa_notifier_mtu_info *info) 54 { 55 if (ds->index == info->sw_index && port == info->port) 56 return true; 57 58 /* Do not propagate to other switches in the tree if the notifier was 59 * targeted for a single switch. 60 */ 61 if (info->targeted_match) 62 return false; 63 64 if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port)) 65 return true; 66 67 return false; 68 } 69 70 static int dsa_switch_mtu(struct dsa_switch *ds, 71 struct dsa_notifier_mtu_info *info) 72 { 73 int port, ret; 74 75 if (!ds->ops->port_change_mtu) 76 return -EOPNOTSUPP; 77 78 for (port = 0; port < ds->num_ports; port++) { 79 if (dsa_switch_mtu_match(ds, port, info)) { 80 ret = ds->ops->port_change_mtu(ds, port, info->mtu); 81 if (ret) 82 return ret; 83 } 84 } 85 86 return 0; 87 } 88 89 static int dsa_switch_bridge_join(struct dsa_switch *ds, 90 struct dsa_notifier_bridge_info *info) 91 { 92 struct dsa_switch_tree *dst = ds->dst; 93 94 if (dst->index == info->tree_index && ds->index == info->sw_index && 95 ds->ops->port_bridge_join) 96 return ds->ops->port_bridge_join(ds, info->port, info->br); 97 98 if ((dst->index != info->tree_index || ds->index != info->sw_index) && 99 ds->ops->crosschip_bridge_join) 100 return ds->ops->crosschip_bridge_join(ds, info->tree_index, 101 info->sw_index, 102 info->port, info->br); 103 104 return 0; 105 } 106 107 static int dsa_switch_bridge_leave(struct dsa_switch *ds, 108 struct dsa_notifier_bridge_info *info) 109 { 110 bool unset_vlan_filtering = br_vlan_enabled(info->br); 111 struct dsa_switch_tree *dst = ds->dst; 112 struct netlink_ext_ack extack = {0}; 113 int err, port; 114 115 if (dst->index == info->tree_index && ds->index == info->sw_index && 116 ds->ops->port_bridge_join) 117 ds->ops->port_bridge_leave(ds, info->port, info->br); 118 119 if ((dst->index != info->tree_index || ds->index != info->sw_index) && 120 ds->ops->crosschip_bridge_join) 121 ds->ops->crosschip_bridge_leave(ds, info->tree_index, 122 info->sw_index, info->port, 123 info->br); 124 125 /* If the bridge was vlan_filtering, the bridge core doesn't trigger an 126 * event for changing vlan_filtering setting upon slave ports leaving 127 * it. That is a good thing, because that lets us handle it and also 128 * handle the case where the switch's vlan_filtering setting is global 129 * (not per port). When that happens, the correct moment to trigger the 130 * vlan_filtering callback is only when the last port leaves the last 131 * VLAN-aware bridge. 132 */ 133 if (unset_vlan_filtering && ds->vlan_filtering_is_global) { 134 for (port = 0; port < ds->num_ports; port++) { 135 struct net_device *bridge_dev; 136 137 bridge_dev = dsa_to_port(ds, port)->bridge_dev; 138 139 if (bridge_dev && br_vlan_enabled(bridge_dev)) { 140 unset_vlan_filtering = false; 141 break; 142 } 143 } 144 } 145 if (unset_vlan_filtering) { 146 err = dsa_port_vlan_filtering(dsa_to_port(ds, info->port), 147 false, &extack); 148 if (extack._msg) 149 dev_err(ds->dev, "port %d: %s\n", info->port, 150 extack._msg); 151 if (err && err != EOPNOTSUPP) 152 return err; 153 } 154 return 0; 155 } 156 157 static int dsa_switch_fdb_add(struct dsa_switch *ds, 158 struct dsa_notifier_fdb_info *info) 159 { 160 int port = dsa_towards_port(ds, info->sw_index, info->port); 161 162 if (!ds->ops->port_fdb_add) 163 return -EOPNOTSUPP; 164 165 return ds->ops->port_fdb_add(ds, port, info->addr, info->vid); 166 } 167 168 static int dsa_switch_fdb_del(struct dsa_switch *ds, 169 struct dsa_notifier_fdb_info *info) 170 { 171 int port = dsa_towards_port(ds, info->sw_index, info->port); 172 173 if (!ds->ops->port_fdb_del) 174 return -EOPNOTSUPP; 175 176 return ds->ops->port_fdb_del(ds, port, info->addr, info->vid); 177 } 178 179 static int dsa_switch_hsr_join(struct dsa_switch *ds, 180 struct dsa_notifier_hsr_info *info) 181 { 182 if (ds->index == info->sw_index && ds->ops->port_hsr_join) 183 return ds->ops->port_hsr_join(ds, info->port, info->hsr); 184 185 return -EOPNOTSUPP; 186 } 187 188 static int dsa_switch_hsr_leave(struct dsa_switch *ds, 189 struct dsa_notifier_hsr_info *info) 190 { 191 if (ds->index == info->sw_index && ds->ops->port_hsr_leave) 192 return ds->ops->port_hsr_leave(ds, info->port, info->hsr); 193 194 return -EOPNOTSUPP; 195 } 196 197 static int dsa_switch_lag_change(struct dsa_switch *ds, 198 struct dsa_notifier_lag_info *info) 199 { 200 if (ds->index == info->sw_index && ds->ops->port_lag_change) 201 return ds->ops->port_lag_change(ds, info->port); 202 203 if (ds->index != info->sw_index && ds->ops->crosschip_lag_change) 204 return ds->ops->crosschip_lag_change(ds, info->sw_index, 205 info->port); 206 207 return 0; 208 } 209 210 static int dsa_switch_lag_join(struct dsa_switch *ds, 211 struct dsa_notifier_lag_info *info) 212 { 213 if (ds->index == info->sw_index && ds->ops->port_lag_join) 214 return ds->ops->port_lag_join(ds, info->port, info->lag, 215 info->info); 216 217 if (ds->index != info->sw_index && ds->ops->crosschip_lag_join) 218 return ds->ops->crosschip_lag_join(ds, info->sw_index, 219 info->port, info->lag, 220 info->info); 221 222 return 0; 223 } 224 225 static int dsa_switch_lag_leave(struct dsa_switch *ds, 226 struct dsa_notifier_lag_info *info) 227 { 228 if (ds->index == info->sw_index && ds->ops->port_lag_leave) 229 return ds->ops->port_lag_leave(ds, info->port, info->lag); 230 231 if (ds->index != info->sw_index && ds->ops->crosschip_lag_leave) 232 return ds->ops->crosschip_lag_leave(ds, info->sw_index, 233 info->port, info->lag); 234 235 return 0; 236 } 237 238 static int dsa_switch_mdb_add(struct dsa_switch *ds, 239 struct dsa_notifier_mdb_info *info) 240 { 241 int port = dsa_towards_port(ds, info->sw_index, info->port); 242 243 if (!ds->ops->port_mdb_add) 244 return -EOPNOTSUPP; 245 246 return ds->ops->port_mdb_add(ds, port, info->mdb); 247 } 248 249 static int dsa_switch_mdb_del(struct dsa_switch *ds, 250 struct dsa_notifier_mdb_info *info) 251 { 252 if (!ds->ops->port_mdb_del) 253 return -EOPNOTSUPP; 254 255 if (ds->index == info->sw_index) 256 return ds->ops->port_mdb_del(ds, info->port, info->mdb); 257 258 return 0; 259 } 260 261 static bool dsa_switch_vlan_match(struct dsa_switch *ds, int port, 262 struct dsa_notifier_vlan_info *info) 263 { 264 if (ds->index == info->sw_index && port == info->port) 265 return true; 266 267 if (dsa_is_dsa_port(ds, port)) 268 return true; 269 270 return false; 271 } 272 273 static int dsa_switch_vlan_add(struct dsa_switch *ds, 274 struct dsa_notifier_vlan_info *info) 275 { 276 int port, err; 277 278 if (!ds->ops->port_vlan_add) 279 return -EOPNOTSUPP; 280 281 for (port = 0; port < ds->num_ports; port++) { 282 if (dsa_switch_vlan_match(ds, port, info)) { 283 err = ds->ops->port_vlan_add(ds, port, info->vlan, 284 info->extack); 285 if (err) 286 return err; 287 } 288 } 289 290 return 0; 291 } 292 293 static int dsa_switch_vlan_del(struct dsa_switch *ds, 294 struct dsa_notifier_vlan_info *info) 295 { 296 if (!ds->ops->port_vlan_del) 297 return -EOPNOTSUPP; 298 299 if (ds->index == info->sw_index) 300 return ds->ops->port_vlan_del(ds, info->port, info->vlan); 301 302 /* Do not deprogram the DSA links as they may be used as conduit 303 * for other VLAN members in the fabric. 304 */ 305 return 0; 306 } 307 308 static int dsa_switch_change_tag_proto(struct dsa_switch *ds, 309 struct dsa_notifier_tag_proto_info *info) 310 { 311 const struct dsa_device_ops *tag_ops = info->tag_ops; 312 int port, err; 313 314 if (!ds->ops->change_tag_protocol) 315 return -EOPNOTSUPP; 316 317 ASSERT_RTNL(); 318 319 for (port = 0; port < ds->num_ports; port++) { 320 if (!dsa_is_cpu_port(ds, port)) 321 continue; 322 323 err = ds->ops->change_tag_protocol(ds, port, tag_ops->proto); 324 if (err) 325 return err; 326 327 dsa_port_set_tag_protocol(dsa_to_port(ds, port), tag_ops); 328 } 329 330 /* Now that changing the tag protocol can no longer fail, let's update 331 * the remaining bits which are "duplicated for faster access", and the 332 * bits that depend on the tagger, such as the MTU. 333 */ 334 for (port = 0; port < ds->num_ports; port++) { 335 if (dsa_is_user_port(ds, port)) { 336 struct net_device *slave; 337 338 slave = dsa_to_port(ds, port)->slave; 339 dsa_slave_setup_tagger(slave); 340 341 /* rtnl_mutex is held in dsa_tree_change_tag_proto */ 342 dsa_slave_change_mtu(slave, slave->mtu); 343 } 344 } 345 346 return 0; 347 } 348 349 static int dsa_switch_mrp_add(struct dsa_switch *ds, 350 struct dsa_notifier_mrp_info *info) 351 { 352 if (!ds->ops->port_mrp_add) 353 return -EOPNOTSUPP; 354 355 if (ds->index == info->sw_index) 356 return ds->ops->port_mrp_add(ds, info->port, info->mrp); 357 358 return 0; 359 } 360 361 static int dsa_switch_mrp_del(struct dsa_switch *ds, 362 struct dsa_notifier_mrp_info *info) 363 { 364 if (!ds->ops->port_mrp_del) 365 return -EOPNOTSUPP; 366 367 if (ds->index == info->sw_index) 368 return ds->ops->port_mrp_del(ds, info->port, info->mrp); 369 370 return 0; 371 } 372 373 static int 374 dsa_switch_mrp_add_ring_role(struct dsa_switch *ds, 375 struct dsa_notifier_mrp_ring_role_info *info) 376 { 377 if (!ds->ops->port_mrp_add) 378 return -EOPNOTSUPP; 379 380 if (ds->index == info->sw_index) 381 return ds->ops->port_mrp_add_ring_role(ds, info->port, 382 info->mrp); 383 384 return 0; 385 } 386 387 static int 388 dsa_switch_mrp_del_ring_role(struct dsa_switch *ds, 389 struct dsa_notifier_mrp_ring_role_info *info) 390 { 391 if (!ds->ops->port_mrp_del) 392 return -EOPNOTSUPP; 393 394 if (ds->index == info->sw_index) 395 return ds->ops->port_mrp_del_ring_role(ds, info->port, 396 info->mrp); 397 398 return 0; 399 } 400 401 static int dsa_switch_event(struct notifier_block *nb, 402 unsigned long event, void *info) 403 { 404 struct dsa_switch *ds = container_of(nb, struct dsa_switch, nb); 405 int err; 406 407 switch (event) { 408 case DSA_NOTIFIER_AGEING_TIME: 409 err = dsa_switch_ageing_time(ds, info); 410 break; 411 case DSA_NOTIFIER_BRIDGE_JOIN: 412 err = dsa_switch_bridge_join(ds, info); 413 break; 414 case DSA_NOTIFIER_BRIDGE_LEAVE: 415 err = dsa_switch_bridge_leave(ds, info); 416 break; 417 case DSA_NOTIFIER_FDB_ADD: 418 err = dsa_switch_fdb_add(ds, info); 419 break; 420 case DSA_NOTIFIER_FDB_DEL: 421 err = dsa_switch_fdb_del(ds, info); 422 break; 423 case DSA_NOTIFIER_HSR_JOIN: 424 err = dsa_switch_hsr_join(ds, info); 425 break; 426 case DSA_NOTIFIER_HSR_LEAVE: 427 err = dsa_switch_hsr_leave(ds, info); 428 break; 429 case DSA_NOTIFIER_LAG_CHANGE: 430 err = dsa_switch_lag_change(ds, info); 431 break; 432 case DSA_NOTIFIER_LAG_JOIN: 433 err = dsa_switch_lag_join(ds, info); 434 break; 435 case DSA_NOTIFIER_LAG_LEAVE: 436 err = dsa_switch_lag_leave(ds, info); 437 break; 438 case DSA_NOTIFIER_MDB_ADD: 439 err = dsa_switch_mdb_add(ds, info); 440 break; 441 case DSA_NOTIFIER_MDB_DEL: 442 err = dsa_switch_mdb_del(ds, info); 443 break; 444 case DSA_NOTIFIER_VLAN_ADD: 445 err = dsa_switch_vlan_add(ds, info); 446 break; 447 case DSA_NOTIFIER_VLAN_DEL: 448 err = dsa_switch_vlan_del(ds, info); 449 break; 450 case DSA_NOTIFIER_MTU: 451 err = dsa_switch_mtu(ds, info); 452 break; 453 case DSA_NOTIFIER_TAG_PROTO: 454 err = dsa_switch_change_tag_proto(ds, info); 455 break; 456 case DSA_NOTIFIER_MRP_ADD: 457 err = dsa_switch_mrp_add(ds, info); 458 break; 459 case DSA_NOTIFIER_MRP_DEL: 460 err = dsa_switch_mrp_del(ds, info); 461 break; 462 case DSA_NOTIFIER_MRP_ADD_RING_ROLE: 463 err = dsa_switch_mrp_add_ring_role(ds, info); 464 break; 465 case DSA_NOTIFIER_MRP_DEL_RING_ROLE: 466 err = dsa_switch_mrp_del_ring_role(ds, info); 467 break; 468 default: 469 err = -EOPNOTSUPP; 470 break; 471 } 472 473 if (err) 474 dev_dbg(ds->dev, "breaking chain for DSA event %lu (%d)\n", 475 event, err); 476 477 return notifier_from_errno(err); 478 } 479 480 int dsa_switch_register_notifier(struct dsa_switch *ds) 481 { 482 ds->nb.notifier_call = dsa_switch_event; 483 484 return raw_notifier_chain_register(&ds->dst->nh, &ds->nb); 485 } 486 487 void dsa_switch_unregister_notifier(struct dsa_switch *ds) 488 { 489 int err; 490 491 err = raw_notifier_chain_unregister(&ds->dst->nh, &ds->nb); 492 if (err) 493 dev_err(ds->dev, "failed to unregister notifier (%d)\n", err); 494 } 495