@@ -464,10 +464,15 @@ static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb,
464464void usbnet_defer_kevent (struct usbnet * dev , int work )
465465{
466466 set_bit (work , & dev -> flags );
467- if (!schedule_work (& dev -> kevent ))
468- netdev_dbg (dev -> net , "kevent %s may have been dropped\n" , usbnet_event_names [work ]);
469- else
470- netdev_dbg (dev -> net , "kevent %s scheduled\n" , usbnet_event_names [work ]);
467+ if (!usbnet_going_away (dev )) {
468+ if (!schedule_work (& dev -> kevent ))
469+ netdev_dbg (dev -> net ,
470+ "kevent %s may have been dropped\n" ,
471+ usbnet_event_names [work ]);
472+ else
473+ netdev_dbg (dev -> net ,
474+ "kevent %s scheduled\n" , usbnet_event_names [work ]);
475+ }
471476}
472477EXPORT_SYMBOL_GPL (usbnet_defer_kevent );
473478
@@ -535,7 +540,8 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
535540 tasklet_schedule (& dev -> bh );
536541 break ;
537542 case 0 :
538- __usbnet_queue_skb (& dev -> rxq , skb , rx_start );
543+ if (!usbnet_going_away (dev ))
544+ __usbnet_queue_skb (& dev -> rxq , skb , rx_start );
539545 }
540546 } else {
541547 netif_dbg (dev , ifdown , dev -> net , "rx: stopped\n" );
@@ -843,9 +849,18 @@ int usbnet_stop (struct net_device *net)
843849
844850 /* deferred work (timer, softirq, task) must also stop */
845851 dev -> flags = 0 ;
846- del_timer_sync (& dev -> delay );
847- tasklet_kill (& dev -> bh );
852+ del_timer_sync (& dev -> delay );
853+ tasklet_kill (& dev -> bh );
848854 cancel_work_sync (& dev -> kevent );
855+
856+ /* We have cyclic dependencies. Those calls are needed
857+ * to break a cycle. We cannot fall into the gaps because
858+ * we have a flag
859+ */
860+ tasklet_kill (& dev -> bh );
861+ del_timer_sync (& dev -> delay );
862+ cancel_work_sync (& dev -> kevent );
863+
849864 if (!pm )
850865 usb_autopm_put_interface (dev -> intf );
851866
@@ -1171,7 +1186,8 @@ usbnet_deferred_kevent (struct work_struct *work)
11711186 status );
11721187 } else {
11731188 clear_bit (EVENT_RX_HALT , & dev -> flags );
1174- tasklet_schedule (& dev -> bh );
1189+ if (!usbnet_going_away (dev ))
1190+ tasklet_schedule (& dev -> bh );
11751191 }
11761192 }
11771193
@@ -1196,7 +1212,8 @@ usbnet_deferred_kevent (struct work_struct *work)
11961212 usb_autopm_put_interface (dev -> intf );
11971213fail_lowmem :
11981214 if (resched )
1199- tasklet_schedule (& dev -> bh );
1215+ if (!usbnet_going_away (dev ))
1216+ tasklet_schedule (& dev -> bh );
12001217 }
12011218 }
12021219
@@ -1559,6 +1576,7 @@ static void usbnet_bh (struct timer_list *t)
15591576 } else if (netif_running (dev -> net ) &&
15601577 netif_device_present (dev -> net ) &&
15611578 netif_carrier_ok (dev -> net ) &&
1579+ !usbnet_going_away (dev ) &&
15621580 !timer_pending (& dev -> delay ) &&
15631581 !test_bit (EVENT_RX_PAUSED , & dev -> flags ) &&
15641582 !test_bit (EVENT_RX_HALT , & dev -> flags )) {
@@ -1606,6 +1624,7 @@ void usbnet_disconnect (struct usb_interface *intf)
16061624 usb_set_intfdata (intf , NULL );
16071625 if (!dev )
16081626 return ;
1627+ usbnet_mark_going_away (dev );
16091628
16101629 xdev = interface_to_usbdev (intf );
16111630
0 commit comments