On Sun, 11 Mar 2007, Milan Plzik wrote: > Hello, > > I noticed that there could potentially be a sort of race condition in > ohci-hcd.c file, related to interrupt handling. This caused Oops when > removing ohci_hcd driver on one device I was working with - OHCI cell on > SAMCOP chip used in ipaq h5000 devices. Please Cc: me as I am not > subscribed to linux-usb-devel. Bugreport below: > > Summary: ohci-hcd module can possibly crash when unloading due race > condition. > > Description: > In usb_remove_hcd there is possible place where race condition can > occur. Problematic is caused by usb_hcd_poll_rh_status, which is > normally called periodically from timer, or from ohci_irq handler. > Removing HCD uses roughly following algorithm: > > 1) delete rh_timer, so it should not be called again > 2) call ohci_stop, which does some magic and then disables interrupts. > > The problem is within the "some magic" part. Its execution takes some > time and within this time, OHCI irq can possibly occur. This results in > call of usb_hcd_poll_rh_status, which again calls timer_mod and > re-enables rh_timer. Consecutively, we now have ohci driver which is > short before unloading, but has active timer. This results in paging > fault. > > It is possible that the interrupt occurs because of ohci_usb_reset > called just prior to disabling interrupts, but I have no idea whether > this is real. This problem also might or might not be visible depending > on debugging turned on or off.
Yes, this looks like a real bug. Does it happen reproducibly on your device? Does the patch below fix it? Alan Stern Index: usb-2.6/drivers/usb/core/hcd.c =================================================================== --- usb-2.6.orig/drivers/usb/core/hcd.c +++ usb-2.6/drivers/usb/core/hcd.c @@ -544,6 +544,8 @@ void usb_hcd_poll_rh_status(struct usb_h unsigned long flags; char buffer[4]; /* Any root hubs with > 31 ports? */ + if (unlikely(!hcd->rh_registered)) + return; if (!hcd->uses_new_polling && !hcd->status_urb) return; @@ -1670,12 +1672,12 @@ void usb_remove_hcd(struct usb_hcd *hcd) usb_disconnect(&hcd->self.root_hub); mutex_unlock(&usb_bus_list_lock); - hcd->poll_rh = 0; - del_timer_sync(&hcd->rh_timer); - hcd->driver->stop(hcd); hcd->state = HC_STATE_HALT; + hcd->poll_rh = 0; + del_timer_sync(&hcd->rh_timer); + if (hcd->irq >= 0) free_irq(hcd->irq, hcd); usb_deregister_bus(&hcd->self); ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel