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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html