RE: Remote wakeup timing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



 
> >
> > > > A better approach might be to have ehci_bus_resume check the port
> > > > statuses before turning on CMD_RUN, and re-suspend any enabled port
> > > > that isn't already suspended.  Then when the controller starts
> > sending
> > > > SOF packets, the host shouldn't think the device had disconnected.
> > > > Would that solve your problem?
> >
> > What about this patch?
> >
> Good patch, Alan. Only one thing is that it needs a delay between
> re-suspend, and send resume again. (Sorry, I can't find the detail
> delay time between suspend and resume signal at usb2.0 spec).
> 
> I will test this patch, and give you a response.
> 

I have some problems with patch, and the SOF isn't out after the second resume has finishes.
I will go on debugging this problem next week.

I think this patch has some risks, and it needs both host and device's behavior to be correct
after 2 times suspend/resume for every remote wakeup occurrence. Remote wakeup occurs:

- Device remote wakeup signal at both autosuspend/system suspend situation
- Device connect/disconnect with/without HUB cases at both autosuspend/system suspend situation.

Esp for 3G/LTE modem cases, if it supports autosuspend at runtime, remote wakeup occurs very frequently. 

> 
> > Alan Stern
> >
> >
> >
> >  drivers/usb/host/ehci-hub.c |   63
> > +++++++++++++++++++++++++++++++++++++++++---
> >  1 file changed, 59 insertions(+), 4 deletions(-)
> >
> > Index: usb-3.4/drivers/usb/host/ehci-hub.c
> > ===================================================================
> > --- usb-3.4.orig/drivers/usb/host/ehci-hub.c
> > +++ usb-3.4/drivers/usb/host/ehci-hub.c
> > @@ -329,6 +329,59 @@ static int ehci_bus_suspend (struct usb_
> >  }
> >
> >
> > +static void ehci_resuspend_ports(struct ehci_hcd *ehci)
> > +{
> > +	u32			temp;
> > +	int			i;
> > +	unsigned long		resuspend_needed = 0;
> > +
> > +	/*
> > +	 * If a remote wakeup request was received, the controller will
> > +	 * already have begun resume signalling on that port.  Some buggy
> > +	 * controllers (e.g., Synopsys) automatically turn off the resume
> > +	 * signal after 20 ms, leaving the port active and using high-speed
> > +	 * signalling.  But since CMD_RUN has been turned off, the device
> > +	 * will not have received any SOF packets, so it will have gone
> > +	 * back into suspend, using full-speed signalling.  As a result,
> > +	 * when the controller starts sending SOF packets again, it will
> > +	 * think the device has disconnected.
> > +	 *
> > +	 * To avoid this problem, check to see if any enabled ports are
> > +	 * resumed or resuming, and force them back into suspend before
> > +	 * turning on CMD_RUN.
> > +	 */
> > +	i = HCS_N_PORTS(ehci->hcs_params);
> > +	while (i--) {
> > +		temp = ehci_readl(ehci, &ehci->regs->port_status[i]);
> > +		temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
> > +		if ((temp & PORT_PE) && (!(temp & PORT_SUSPEND) ||
> > +				(temp & PORT_RESUME))) {
> > +			__set_bit(i, &resuspend_needed);
> > +			temp &= ~PORT_RESUME;
> > +			ehci_writel(ehci, temp, &ehci->regs->port_status[i]);
> > +		}
> > +	}
> > +
> > +	/* Give the port time to leave suspend, then resuspend it */
> > +	if (resuspend_needed) {
> > +		spin_unlock_irq(&ehci->lock);
> > +		msleep(3);
> > +		spin_lock_irq(&ehci->lock);
> > +
> > +		i = HCS_N_PORTS(ehci->hcs_params);
> > +		while (i--) {
> > +			if (test_bit(i, &resuspend_needed)) {
> > +				temp = ehci_readl(ehci,
> > +						&ehci->regs->port_status[i]);
> > +				temp &= ~PORT_RWC_BITS;
> > +				temp |= PORT_SUSPEND;
> > +				ehci_writel(ehci, temp,
> > +						&ehci->regs->port_status[i]);
> > +			}
> > +		}
> > +	}
> > +}
> > +
> >  /* caller has locked the root hub, and should reset/reinit on error */
> >  static int ehci_bus_resume (struct usb_hcd *hcd)
> >  {
> > @@ -373,10 +426,6 @@ static int ehci_bus_resume (struct usb_h
> >  	ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
> >  	ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs-
> > >async_next);
> >
> > -	/* restore CMD_RUN, framelist size, and irq threshold */
> > -	ehci_writel(ehci, ehci->command, &ehci->regs->command);
> > -	ehci->rh_state = EHCI_RH_RUNNING;
> > -
> >  	/* Some controller/firmware combinations need a delay during which
> >  	 * they set up the port statuses.  See Bugzilla #8190. */
> >  	spin_unlock_irq(&ehci->lock);
> > @@ -402,6 +451,12 @@ static int ehci_bus_resume (struct usb_h
> >  		spin_lock_irq(&ehci->lock);
> >  	}
> >
> > +	ehci_resuspend_ports(ehci);
> > +
> > +	/* restore CMD_RUN, framelist size, and irq threshold */
> > +	ehci_writel(ehci, ehci->command, &ehci->regs->command);
> > +	ehci->rh_state = EHCI_RH_RUNNING;
> > +
> >  	/* manually resume the ports we suspended during bus_suspend() */
> >  	i = HCS_N_PORTS (ehci->hcs_params);
> >  	while (i--) {
> >


--
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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux