|
@@ -1466,8 +1466,7 @@ EXPORT_SYMBOL(unregister_netdevice_notifier);
|
|
|
|
|
|
int call_netdevice_notifiers(unsigned long val, struct net_device *dev)
|
|
|
{
|
|
|
- if (val != NETDEV_UNREGISTER_FINAL)
|
|
|
- ASSERT_RTNL();
|
|
|
+ ASSERT_RTNL();
|
|
|
return raw_notifier_call_chain(&netdev_chain, val, dev);
|
|
|
}
|
|
|
EXPORT_SYMBOL(call_netdevice_notifiers);
|
|
@@ -5782,7 +5781,11 @@ static void netdev_wait_allrefs(struct net_device *dev)
|
|
|
|
|
|
/* Rebroadcast unregister notification */
|
|
|
call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
|
|
|
+
|
|
|
+ __rtnl_unlock();
|
|
|
rcu_barrier();
|
|
|
+ rtnl_lock();
|
|
|
+
|
|
|
call_netdevice_notifiers(NETDEV_UNREGISTER_FINAL, dev);
|
|
|
if (test_bit(__LINK_STATE_LINKWATCH_PENDING,
|
|
|
&dev->state)) {
|
|
@@ -5855,7 +5858,9 @@ void netdev_run_todo(void)
|
|
|
= list_first_entry(&list, struct net_device, todo_list);
|
|
|
list_del(&dev->todo_list);
|
|
|
|
|
|
+ rtnl_lock();
|
|
|
call_netdevice_notifiers(NETDEV_UNREGISTER_FINAL, dev);
|
|
|
+ __rtnl_unlock();
|
|
|
|
|
|
if (unlikely(dev->reg_state != NETREG_UNREGISTERING)) {
|
|
|
pr_err("network todo '%s' but state %d\n",
|