Commit 60724d4bae14cd295b27b1610cad9a2720eb0860
Committed by
David S. Miller
1 parent
3f7832c26c
net: dsa: Add support for DSA specific notifiers
In preparation for communicating a given DSA network device's port number and switch index, create a specialized DSA notifier and two events: DSA_PORT_REGISTER and DSA_PORT_UNREGISTER that communicate: the slave network device (slave_dev), port number and switch number in the tree. This will be later used for network device drivers like bcmsysport which needs to cooperate with its DSA network devices to set-up queue mapping and scheduling. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 3 changed files with 81 additions and 0 deletions Side-by-side Diff
include/net/dsa.h
... | ... | @@ -471,5 +471,50 @@ |
471 | 471 | } |
472 | 472 | #endif /* CONFIG_PM_SLEEP */ |
473 | 473 | |
474 | +enum dsa_notifier_type { | |
475 | + DSA_PORT_REGISTER, | |
476 | + DSA_PORT_UNREGISTER, | |
477 | +}; | |
478 | + | |
479 | +struct dsa_notifier_info { | |
480 | + struct net_device *dev; | |
481 | +}; | |
482 | + | |
483 | +struct dsa_notifier_register_info { | |
484 | + struct dsa_notifier_info info; /* must be first */ | |
485 | + struct net_device *master; | |
486 | + unsigned int port_number; | |
487 | + unsigned int switch_number; | |
488 | +}; | |
489 | + | |
490 | +static inline struct net_device * | |
491 | +dsa_notifier_info_to_dev(const struct dsa_notifier_info *info) | |
492 | +{ | |
493 | + return info->dev; | |
494 | +} | |
495 | + | |
496 | +#if IS_ENABLED(CONFIG_NET_DSA) | |
497 | +int register_dsa_notifier(struct notifier_block *nb); | |
498 | +int unregister_dsa_notifier(struct notifier_block *nb); | |
499 | +int call_dsa_notifiers(unsigned long val, struct net_device *dev, | |
500 | + struct dsa_notifier_info *info); | |
501 | +#else | |
502 | +static inline int register_dsa_notifier(struct notifier_block *nb) | |
503 | +{ | |
504 | + return 0; | |
505 | +} | |
506 | + | |
507 | +static inline int unregister_dsa_notifier(struct notifier_block *nb) | |
508 | +{ | |
509 | + return 0; | |
510 | +} | |
511 | + | |
512 | +static inline int call_dsa_notifiers(unsigned long val, struct net_device *dev, | |
513 | + struct dsa_notifier_info *info) | |
514 | +{ | |
515 | + return NOTIFY_DONE; | |
516 | +} | |
517 | +#endif | |
518 | + | |
474 | 519 | #endif |
net/dsa/dsa.c
... | ... | @@ -14,6 +14,7 @@ |
14 | 14 | #include <linux/platform_device.h> |
15 | 15 | #include <linux/slab.h> |
16 | 16 | #include <linux/module.h> |
17 | +#include <linux/notifier.h> | |
17 | 18 | #include <linux/of.h> |
18 | 19 | #include <linux/of_mdio.h> |
19 | 20 | #include <linux/of_platform.h> |
... | ... | @@ -260,6 +261,28 @@ |
260 | 261 | { |
261 | 262 | return queue_work(dsa_owq, work); |
262 | 263 | } |
264 | + | |
265 | +static ATOMIC_NOTIFIER_HEAD(dsa_notif_chain); | |
266 | + | |
267 | +int register_dsa_notifier(struct notifier_block *nb) | |
268 | +{ | |
269 | + return atomic_notifier_chain_register(&dsa_notif_chain, nb); | |
270 | +} | |
271 | +EXPORT_SYMBOL_GPL(register_dsa_notifier); | |
272 | + | |
273 | +int unregister_dsa_notifier(struct notifier_block *nb) | |
274 | +{ | |
275 | + return atomic_notifier_chain_unregister(&dsa_notif_chain, nb); | |
276 | +} | |
277 | +EXPORT_SYMBOL_GPL(unregister_dsa_notifier); | |
278 | + | |
279 | +int call_dsa_notifiers(unsigned long val, struct net_device *dev, | |
280 | + struct dsa_notifier_info *info) | |
281 | +{ | |
282 | + info->dev = dev; | |
283 | + return atomic_notifier_call_chain(&dsa_notif_chain, val, info); | |
284 | +} | |
285 | +EXPORT_SYMBOL_GPL(call_dsa_notifiers); | |
263 | 286 | |
264 | 287 | static int __init dsa_init_module(void) |
265 | 288 | { |
net/dsa/slave.c
... | ... | @@ -1116,6 +1116,7 @@ |
1116 | 1116 | |
1117 | 1117 | int dsa_slave_create(struct dsa_port *port, const char *name) |
1118 | 1118 | { |
1119 | + struct dsa_notifier_register_info rinfo = { }; | |
1119 | 1120 | struct dsa_switch *ds = port->ds; |
1120 | 1121 | struct net_device *master; |
1121 | 1122 | struct net_device *slave_dev; |
... | ... | @@ -1177,6 +1178,12 @@ |
1177 | 1178 | goto out_free; |
1178 | 1179 | } |
1179 | 1180 | |
1181 | + rinfo.info.dev = slave_dev; | |
1182 | + rinfo.master = master; | |
1183 | + rinfo.port_number = p->dp->index; | |
1184 | + rinfo.switch_number = p->dp->ds->index; | |
1185 | + call_dsa_notifiers(DSA_PORT_REGISTER, slave_dev, &rinfo.info); | |
1186 | + | |
1180 | 1187 | ret = register_netdev(slave_dev); |
1181 | 1188 | if (ret) { |
1182 | 1189 | netdev_err(master, "error %d registering interface %s\n", |
... | ... | @@ -1200,6 +1207,7 @@ |
1200 | 1207 | void dsa_slave_destroy(struct net_device *slave_dev) |
1201 | 1208 | { |
1202 | 1209 | struct dsa_slave_priv *p = netdev_priv(slave_dev); |
1210 | + struct dsa_notifier_register_info rinfo = { }; | |
1203 | 1211 | struct device_node *port_dn; |
1204 | 1212 | |
1205 | 1213 | port_dn = p->dp->dn; |
... | ... | @@ -1211,6 +1219,11 @@ |
1211 | 1219 | if (of_phy_is_fixed_link(port_dn)) |
1212 | 1220 | of_phy_deregister_fixed_link(port_dn); |
1213 | 1221 | } |
1222 | + rinfo.info.dev = slave_dev; | |
1223 | + rinfo.master = p->dp->cpu_dp->netdev; | |
1224 | + rinfo.port_number = p->dp->index; | |
1225 | + rinfo.switch_number = p->dp->ds->index; | |
1226 | + call_dsa_notifiers(DSA_PORT_UNREGISTER, slave_dev, &rinfo.info); | |
1214 | 1227 | unregister_netdev(slave_dev); |
1215 | 1228 | free_percpu(p->stats64); |
1216 | 1229 | free_netdev(slave_dev); |