On Tue, 18 Dec 2012, lantianyu wrote:
> > What you want here is sort of an alternate debounce routine. The
> > normal routine waits until the connect status has been stable for 100
> > ms. But you want to wait until the status has stable in the
> > "connected" state for 100 ms.
> Yesh.
> > Maybe it would be better to do this by passing an extra argument to the
> > regular debounce routine.
> How about this?
It would be easier to read a patch, particularly if it wasn't
whitespace-damaged.
> static int hub_port_debounce(struct usb_hub *hub, int port1, bool
> must_connected)
This should be "must_be_connected".
> {
> int ret;
> int total_time, stable_time = 0;
> u16 portchange, portstatus;
> unsigned connection = 0xffff;
>
> for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) {
> ret = hub_port_status(hub, port1, &portstatus, &portchange);
> if (ret < 0)
> return ret;
>
> if (!(portchange & USB_PORT_STAT_C_CONNECTION) &&
> (portstatus & USB_PORT_STAT_CONNECTION) == connection){
>
> if (!must_connected || (connection == USB_PORT_STAT_CONNECTION))
> stable_time += HUB_DEBOUNCE_STEP;
>
> if (stable_time >= HUB_DEBOUNCE_STABLE)
> break;
> } else {
> stable_time = 0;
> connection = portstatus & USB_PORT_STAT_CONNECTION;
> }
>
> if (portchange & USB_PORT_STAT_C_CONNECTION) {
> clear_port_feature(hub->hdev, port1,
> USB_PORT_FEAT_C_CONNECTION);
> }
>
> if (total_time >= HUB_DEBOUNCE_TIMEOUT)
> break;
> msleep(HUB_DEBOUNCE_STEP);
> }
>
> dev_dbg (hub->intfdev,
> "debounce: port %d: total %dms stable %dms status 0x%x\n",
> port1, total_time, stable_time, portstatus);
>
> if (stable_time < HUB_DEBOUNCE_STABLE)
> return -ETIMEDOUT;
> return portstatus;
> }
Yes, that seems okay. You'll want to increase HUB_DEBOUNCE_TIMEOUT.
> > No, no, not at all. The set_bit and clear_bit operations don't need
> > any protection -- they are atomic. What we need to do is make sure
> > that two different threads don't try to manage the same port at the
> > same time. For example, it should not be possible for one thread to
> > reset the port while another thread is trying to suspend it.
> >
> > I'm pretty sure that this can't happen with the existing code. The
> > only places where a port gets used are:
> >
> > when a device is connected;
> >
> > when a device is disconnected;
> >
> > when a device is reset;
> >
> > when a device is suspended or resumed.
> >
> > We should check that these things really are mutually exclusive, and
> > that they remain mutually exclusive when your changes are added.
> I just find busy_bits is set or clear in the usb_port_resume() and
> usb_reset_and_verify_device(). So currently we should keep my changes
> mutually exclusive with them, right?
Don't forget about what happens when a device is removed.
> My changes add two new places: when port is resumed and when is suspended.
>
> Port's resume/suspend may occur in device's resume/suspend and Pm Qos
> change by
> pm_runtime_get_sync/put(port_dev).
>
> The case in device's resume/suspend will not conflict with
> usb_port_resume() and
> usb_reset_and_verify_device() since they are all in the same thread or
> will not occur at
> the same time.
Yes.
> For the case of Pm Qos change, actually it only happens when user set
> NO_POWER_OFF flag
> after the device being power off. The port will be resumed at that time.
> One case is
> that device resume and Pm Qos change take place at the same time. The
> usb_port_resume()
> is calling pm_runtime_get_sync(port_dev) and PM core also is doing the
> same thing. So two
> port resume will be executed in the parallel. Assuming that the one
> triggered by usb_port_resume()
> is finished firstly and it goes back to usb_port_resume() position where
> just before set busy_bits. The
> second, port resume operation will be executed. Will this happen? If
> yes, there will be a race problem.
> Just one case I have found.
The PM core guarantees that runtime PM callbacks are mutually
exclusive. It also guarantees that the runtime_resume routine won't be
called if the device is currently active (and the runtime_suspend
routine won't be called if the device is currently suspended).
Therefore it suffices to make sure that usb_port_resume does
pm_runtime_get_sync(port_dev) before it touches busy_bits.
The other race, against usb_reset_and_verify_device, should also be
okay. Aside from the resume pathway, the only place that routine gets
called is from usb_reset_device, which is careful to prevent the device
from being suspended during the reset.
> Is it possble to add a lock to prevent the busy_bits from being cleared
> by other thread?
It looks like we don't need it.
Alan Stern
--
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