Dave:

I just realized there is another problem connected with level-triggered
root-hub status interrupts.  It probably hasn't affected your tests but
the potential is there.

Two routines in the hub driver can cause port-change events to occur 
outside the scope of khubd: usb_reset_device and usb_resume_device.  That 
is, these routines are called by processes other than khubd, and they 
create PORT_STATUS_C_RESET and PORT_STATUS_C_SUSPEND events respectively.

Normally khubd would see these events and start interfering with the
reset/resume.  That is explicitly prevented in usb_reset_device by code
that sets hub->busy_bits.  (Analogous code should be present in
hub_port_resume; leaving it out was an oversight.)  When khubd sees a port
is busy, it simply skips over that port.

This works okay with external hubs that are polled only 4 times per second
and with edge-triggered status interrupts (like UHCI and, I assume, EHCI).  
But with level-triggered interrupts it will fail badly.  Khubd will 
not clear the source before re-enabling the interrupt.

I can think of two possible solutions.  The first is to call hub_quiesce 
instead of setting hub->busy_bits.  This has the disadvantage that khubd 
won't be able to respond to events on other ports while one port is being 
reset or resumed.

The second solution is to avoid calling usb_enable_root_hub_irq if 
hub->busy_bits is nonzero.  This has the same disadvantage but it affects 
only OHCI controllers, not all hubs, both root and external.

Do you have a preference?

Alan Stern



_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to