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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to