On Wed, 8 Jul 2009, Yang Fei-AFY095 wrote: >> Hello All, >> >> I'm trying to understand the debounce introduced in function >> hub_activate, in file drivers/usb/core/hub.c. >> This used to be a very simple function which doesn't do much except >> submitting an URB to query port status and kicking off hub_thread. (in >> some early 2.6.27 versions or older) The function became more >> complicated in recent releases (such as 2.6.29), and the most >> significant change I noticed is the 100ms debounce for port status >> change. >> >> ------ snip ------ >> #define HUB_DEBOUNCE_STABLE 100 >> ...... >> >> if (need_debounce_delay) >> msleep(HUB_DEBOUNCE_STABLE); >> ------ snip ------ >> >> Here are my questions, >You are looking at the wrong code. To answer question 4, you need to >look at hub_port_connect_change, not hub_activate. I will answer your >other questions anyway... Alan, hub_activate is called because we suspend the bus for power management purpose, when device disconnects during the time bus is suspended, hub_activate gets called first, then hub_thread is kicked off (at the end of hub_activate) to scan hub ports for connection change, and hub_port_connect_change gets called by the hub_thread. Here is the stack dump, [<c003e0e8>] (dump_stack+0x0/0x14) from [<c02740fc>] (hub_activate+0x10c/0x2b4) [<c0273ff0>] (hub_activate+0x0/0x2b4) from [<c0276378>] (hub_resume+0x18/0x20) [<c0276360>] (hub_resume+0x0/0x20) from [<c027bbe0>] (usb_resume_interface+0xf8/0x190) [<c027bae8>] (usb_resume_interface+0x0/0x190) from [<c027c128>] (usb_resume_both+0x11c/0x154) r5:00000001 r4:cd5da800 [<c027c00c>] (usb_resume_both+0x0/0x154) from [<c027ca50>] (usb_external_resume_device+0x38/0x78) r7:ced4c3c0 r6:cd5da800 r5:cd5daaf0 r4:00000210 [<c027ca18>] (usb_external_resume_device+0x0/0x78) from [<c02777f8>] (hcd_resume_work+0x34/0x44) r7:ced4c3c0 r6:c02777c4 r5:cd5da8e8 r4:cd5da800 [<c02777c4>] (hcd_resume_work+0x0/0x44) from [<c0077ea0>] (run_workqueue+0xa4/0x120) r5:cecde000 r4:ced4c3c0 [<c0077dfc>] (run_workqueue+0x0/0x120) from [<c0078a28>] (worker_thread+0xf0/0x104) r7:ced4c3c0 r6:cecde000 r5:cec67940 r4:cecdffb8 [<c0078938>] (worker_thread+0x0/0x104) from [<c007b838>] (kthread+0x54/0x80) r7:00000000 r6:00000000 r5:c0078938 r4:ced4c3c0 [<c007b7e4>] (kthread+0x0/0x80) from [<c006b5f8>] (do_exit+0x0/0x670) r5:00000000 r4:00000000 >> 4. To be more specific, please allow me to present an issue I'm >> dealing with. In this system, there is an EHCI controller connected to >> the device through TLL (12pin ULPI interface). The device could switch >> mode >What do you mean by "switch mode"? I meant the device can re-enumerate with completely different configurations. Normally the device would enumerate with one default set of device/configuration descriptors, but under certain circumstances, the device could disconnect and try to enumerate with a completely different set of device/configuration descriptors. >> anytime by disconnect and reconnect to the host controller in a very >> short time. It used to work with older linux versions before the >> debounce was introduced into hub_activate function. However, with >> recent releases, the hub_activate function sees portstatus=0x0100 and >> portchange=0x0001 which indicates device disconnected, because of this >> 100ms debounce and the device switch mode very quickly, by the time >> hub_thread is started, the device reconnect already and the portstatus >> becomes 0x0501 and portchange=0x0001, the hub_port_connect_change >> function returns before even calling usb_disconnect, >That is where you should be looking. This sequence of events has nothing to do with hub_activate or debouncing. Agree. But for our case, since the bus is suspend, the issue is really coming from the debounce in hub_activate as it is the one who wakes up the hub_thread. >> thus enumeration >> for the second mode doesn't even happen. As I'm not clear about the >> reasoning behind this debounce in hub_activate function, I don't know >> if this problem should be fixed from the host driver side or the >> device side. If this should be fixed on the device side, how do we >> decide the interval between disconnect and connect, which is directly >> related to the question #2. >You seem to think that hub_port_connect_change should always call usb_disconnect. >To see why it doesn't, examine the code following the comment > > /* Try to resuscitate an existing device */ > >To the hub driver, it looks like the device's connection was momentarily broken and then reestablished. >Since the device is unchanged between before and after, there's no need to go through disconnect and reenumeration. > >If you really want the device to be reenumerated, you have to make it clear that something has changed. >For example, changing any part of the device or configuration descriptors would be enough to force reenumeration. I did not think hub_port_connect_change should always call usb_disconnect, the issue here is the disconnect event gets filtered out because of the 100ms debounce in hub_activate, so when hub_thread scan the ports there doesn't seem to be anything changed. Anyway I was just trying to get some idea about this 100ms debounce in hub_activate, to see if we should make change on host side or device side to resolve our re-enumeration issue. Right now I can resolve it by having a delay between disconnect and reconnect on the device side. You mentioned force re-enumeration by changing descriptors, can you please elaborate on that? When our device disconnect and trying to re-enumerate, we do have a completely different device descriptor, but the problem is the host doesn't even start the enumeration process because disconnect event gets filtered out. It would be really nice if there is any way to force re-enumeration by simply doing something with descriptors. Fei -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html