From: Wei Wang Add a new netdev event for dev unregister and handle the removal of this dev from psp->assoc_dev_list. Signed-off-by: Wei Wang --- net/psp/psp_main.c | 64 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/net/psp/psp_main.c b/net/psp/psp_main.c index 178b848989f1..8e00ade706e4 100644 --- a/net/psp/psp_main.c +++ b/net/psp/psp_main.c @@ -375,10 +375,72 @@ int psp_dev_rcv(struct sk_buff *skb, u16 dev_id, u8 generation, bool strip_icv) } EXPORT_SYMBOL(psp_dev_rcv); +static void psp_dev_disassoc_one(struct psp_dev *psd, struct net_device *dev) +{ + struct psp_assoc_dev *entry, *tmp; + + list_for_each_entry_safe(entry, tmp, &psd->assoc_dev_list, dev_list) { + if (entry->assoc_dev == dev) { + list_del(&entry->dev_list); + rcu_assign_pointer(entry->assoc_dev->psp_dev, NULL); + netdev_put(entry->assoc_dev, &entry->dev_tracker); + kfree(entry); + return; + } + } +} + +static int psp_netdev_event(struct notifier_block *nb, unsigned long event, + void *ptr) +{ + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct psp_dev *psd; + + if (event != NETDEV_UNREGISTER) + return NOTIFY_DONE; + + rcu_read_lock(); + psd = rcu_dereference(dev->psp_dev); + if (psd && psp_dev_tryget(psd)) { + rcu_read_unlock(); + mutex_lock(&psd->lock); + psp_dev_disassoc_one(psd, dev); + mutex_unlock(&psd->lock); + psp_dev_put(psd); + } else { + rcu_read_unlock(); + } + + return NOTIFY_DONE; +} + +static struct notifier_block psp_netdev_notifier = { + .notifier_call = psp_netdev_event, +}; + static int __init psp_init(void) { + int err; + mutex_init(&psp_devs_lock); + err = register_netdevice_notifier(&psp_netdev_notifier); + if (err) + return err; + + err = genl_register_family(&psp_nl_family); + if (err) { + unregister_netdevice_notifier(&psp_netdev_notifier); + return err; + } + + return 0; +} - return genl_register_family(&psp_nl_family); +static void __exit psp_exit(void) +{ + genl_unregister_family(&psp_nl_family); + unregister_netdevice_notifier(&psp_netdev_notifier); } + subsys_initcall(psp_init); +module_exit(psp_exit); -- 2.52.0