@@ -464,10 +464,15 @@ static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb,
464
464
void usbnet_defer_kevent (struct usbnet * dev , int work )
465
465
{
466
466
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
+ }
471
476
}
472
477
EXPORT_SYMBOL_GPL (usbnet_defer_kevent );
473
478
@@ -535,7 +540,8 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
535
540
tasklet_schedule (& dev -> bh );
536
541
break ;
537
542
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 );
539
545
}
540
546
} else {
541
547
netif_dbg (dev , ifdown , dev -> net , "rx: stopped\n" );
@@ -843,9 +849,18 @@ int usbnet_stop (struct net_device *net)
843
849
844
850
/* deferred work (timer, softirq, task) must also stop */
845
851
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 );
848
854
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
+
849
864
if (!pm )
850
865
usb_autopm_put_interface (dev -> intf );
851
866
@@ -1171,7 +1186,8 @@ usbnet_deferred_kevent (struct work_struct *work)
1171
1186
status );
1172
1187
} else {
1173
1188
clear_bit (EVENT_RX_HALT , & dev -> flags );
1174
- tasklet_schedule (& dev -> bh );
1189
+ if (!usbnet_going_away (dev ))
1190
+ tasklet_schedule (& dev -> bh );
1175
1191
}
1176
1192
}
1177
1193
@@ -1196,7 +1212,8 @@ usbnet_deferred_kevent (struct work_struct *work)
1196
1212
usb_autopm_put_interface (dev -> intf );
1197
1213
fail_lowmem :
1198
1214
if (resched )
1199
- tasklet_schedule (& dev -> bh );
1215
+ if (!usbnet_going_away (dev ))
1216
+ tasklet_schedule (& dev -> bh );
1200
1217
}
1201
1218
}
1202
1219
@@ -1559,6 +1576,7 @@ static void usbnet_bh (struct timer_list *t)
1559
1576
} else if (netif_running (dev -> net ) &&
1560
1577
netif_device_present (dev -> net ) &&
1561
1578
netif_carrier_ok (dev -> net ) &&
1579
+ !usbnet_going_away (dev ) &&
1562
1580
!timer_pending (& dev -> delay ) &&
1563
1581
!test_bit (EVENT_RX_PAUSED , & dev -> flags ) &&
1564
1582
!test_bit (EVENT_RX_HALT , & dev -> flags )) {
@@ -1606,6 +1624,7 @@ void usbnet_disconnect (struct usb_interface *intf)
1606
1624
usb_set_intfdata (intf , NULL );
1607
1625
if (!dev )
1608
1626
return ;
1627
+ usbnet_mark_going_away (dev );
1609
1628
1610
1629
xdev = interface_to_usbdev (intf );
1611
1630
0 commit comments