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