On 2012年12月12日 23:56, Alan Stern wrote: > On Wed, 12 Dec 2012, Lan Tianyu wrote: > >>>> I tested a usb ssd which consumes about 1s to makes usb port status >>>> enter into connect status after powering off and powering on the port. >>>> So I set the tries 20 and the longest latency is larger than 2s. >>>> The debounce routine only guarantees port status stable rather than >>>> enter into connect status. >>> >>> Then a better solution would be to first wait (up to 2 seconds) for a >>> connect status and then call the debounce routine. >> But some devices don't need to wait 2s such long time, 200ms is enough >> for them. So I try to check status everytime after debounce. If it's >> connected, go away. > > You should test the connect status in a loop. Each time through the > loop, if it's not connected wait another 20 or so. > Hi Alan: debounce is still needed. If connect status was not stable, resume operation will fail. So how about following? int usb_port_wait_for_connected(struct usb_hub *hub, int port1) { u16 portchange, portstatus; int total_time, ret; for (total_time = 0; total_time < 2000; total_time += 20) { ret = hub_port_status(hub, port1, &portstatus, &portchange); if (ret < 0) return ret; if ((portstatus & USB_PORT_STAT_CONNECTION) && (hub_port_debounce(hub, port1) & USB_PORT_STAT_CONNECTION)) { /* * just clear enable-change feature since debounce * has cleared connect-change feature. */ clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_ENABLE); return 0; } mdelay(20); } return -ETIMEDOUT; } > >>>>> You need to store somewhere the fact that you made this call, so that >>>>> you will know whether or not to make the corresponding >>>>> pm_runtime_get_sync call in usb_port_resume. >>>> You mean I should add a new flag to keep the >>>> pm_runtime_put_sync/put(port_dev) being called paired, right? >>>> How about "needs_resume"? >>> >>> What you need isn't a resume; it's pm_runtime_get_sync. >> How about "needs_runtime_get"? > > Or maybe "did_runtime_put". Something like that. > > >>>> Even the power is still on but the PORT_POWER feature has been cleared. >>>> So there should be no event from port, right? >>> >>> "should be" -- but buggy hardware might send an event anyway. Also, >>> many root hubs don't pay attention to the power feature. If this >>> happens, you probably should handle the connect change properly. I >>> don't see any point in ignoring it. >> How to deal with these connect change event or how to identify whether >> the connect change event is trigger by real power off or not? > > If you get a connect change immediately after turning off the port > power, there's no way to know whether it was because the power is now > off or because the device really disconnected. So the best you can do > is turn on the busy_bits entry, turn off the power, clear the > connect-change and enable-change statuses, and turn off the busy_bits > entry. > You mean this? static int usb_port_runtime_suspend(struct device *dev) { struct usb_port *port_dev = to_usb_port(dev); struct usb_device *hdev = to_usb_device(dev->parent->parent); struct usb_hub *hub = hdev_to_hub(hdev); int port1 = port_dev->portnum; int retval; if (dev_pm_qos_flags(&port_dev->dev, PM_QOS_FLAG_NO_POWER_OFF) == PM_QOS_FLAGS_ALL) return -EAGAIN; set_bit(port1, hub->busy_bits); retval = usb_hub_set_port_power(hdev, port1, false); clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION); clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE); clear_bit(port1, hub->busy_bits); return retval; } > Alan Stern > -- Best regards Tianyu Lan -- 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