usb: generic resume timeout for v4.1
This part 2 pull request contains only the patches which make sure everybody on linux uses the same resume timeout value. Signed-off-by: Felipe Balbi <balbi@ti.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJVJEivAAoJEIaOsuA1yqREV6QP/1oJVdBxzOeQVXyGZsZT4k0E T8SKmTIJmaCdSjgazSXAhqF7IR992sTM7urHZ2hww3tftODNVHvfFkgDlSguHwkr GV95YpNv99ash7spjod3xVOt8lDvrt6FHs7Foj4b0yQZ1yXUZsOH4j8G4gMYOgTd bq1mO2/NaaM7xiddzPMCGpSkL6NcsWrurJ8JiOlBXaUIkSR+Cwe9+8vzEDrxfSM+ 6yBTLQCdvR0ammqV0YMNsF9dGLO8yiDotC6b104i3yCqpAZnyj0RJQ3riH7ESxsG eSKkCXXGY0OWDGDcnWTskYEHJ7iDfg5MrlzBJyneMjauGKNeIoJRRYWP/f6NSV9m GHxRV1ITKC61Dtt3w+Oy2a16UpAbq7/w1q/SkQl4YtJ8l0P1PUb+TfOZpTOsCLLF cLXUKJufGWhuGbo+e2m6GizNCsDi5LlfdZcjIjVKRXpyiZI0peqyGj16mTm70UUY /A9nsLtE7c6bqHMTcFQFRx4d2iHmkilyzQqOvx4ulo1rovNMafgmZJF7Kq0LY7ZO Uj4s2rEAjqbELbOiEIf8HzGP+J/QuECG4SHyPEQsiG0drYyoCOqGR1S3kV7aJgFz krl4zTvXR8EOk2IpPa8PDzmMr7YCYzlXOxzmSoJiZhqqpLH7cHYkDiRTmyxn+eB3 lEjEzBA8J9CG4iRIFjk3 =RqsO -----END PGP SIGNATURE----- Merge tag 'usb-for-v4.1-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-testing Felipe writes: usb: generic resume timeout for v4.1 This part 2 pull request contains only the patches which make sure everybody on linux uses the same resume timeout value. Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
commit
c8d1bc12c7
@ -3406,10 +3406,10 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
|
|||||||
if (status) {
|
if (status) {
|
||||||
dev_dbg(&port_dev->dev, "can't resume, status %d\n", status);
|
dev_dbg(&port_dev->dev, "can't resume, status %d\n", status);
|
||||||
} else {
|
} else {
|
||||||
/* drive resume for at least 20 msec */
|
/* drive resume for USB_RESUME_TIMEOUT msec */
|
||||||
dev_dbg(&udev->dev, "usb %sresume\n",
|
dev_dbg(&udev->dev, "usb %sresume\n",
|
||||||
(PMSG_IS_AUTO(msg) ? "auto-" : ""));
|
(PMSG_IS_AUTO(msg) ? "auto-" : ""));
|
||||||
msleep(25);
|
msleep(USB_RESUME_TIMEOUT);
|
||||||
|
|
||||||
/* Virtual root hubs can trigger on GET_PORT_STATUS to
|
/* Virtual root hubs can trigger on GET_PORT_STATUS to
|
||||||
* stop resume signaling. Then finish the resume
|
* stop resume signaling. Then finish the resume
|
||||||
|
@ -1529,7 +1529,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
|
|||||||
dev_dbg(hsotg->dev,
|
dev_dbg(hsotg->dev,
|
||||||
"ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
|
"ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
|
||||||
writel(0, hsotg->regs + PCGCTL);
|
writel(0, hsotg->regs + PCGCTL);
|
||||||
usleep_range(20000, 40000);
|
msleep(USB_RESUME_TIMEOUT);
|
||||||
|
|
||||||
hprt0 = dwc2_read_hprt0(hsotg);
|
hprt0 = dwc2_read_hprt0(hsotg);
|
||||||
hprt0 |= HPRT0_RES;
|
hprt0 |= HPRT0_RES;
|
||||||
|
@ -792,12 +792,12 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
|
|||||||
ehci->reset_done[i] == 0))
|
ehci->reset_done[i] == 0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* start 20 msec resume signaling from this port,
|
/* start USB_RESUME_TIMEOUT msec resume signaling from
|
||||||
* and make hub_wq collect PORT_STAT_C_SUSPEND to
|
* this port, and make hub_wq collect
|
||||||
* stop that signaling. Use 5 ms extra for safety,
|
* PORT_STAT_C_SUSPEND to stop that signaling.
|
||||||
* like usb_port_resume() does.
|
|
||||||
*/
|
*/
|
||||||
ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
|
ehci->reset_done[i] = jiffies +
|
||||||
|
msecs_to_jiffies(USB_RESUME_TIMEOUT);
|
||||||
set_bit(i, &ehci->resuming_ports);
|
set_bit(i, &ehci->resuming_ports);
|
||||||
ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
|
ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
|
||||||
usb_hcd_start_port_resume(&hcd->self, i);
|
usb_hcd_start_port_resume(&hcd->self, i);
|
||||||
|
@ -471,10 +471,13 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
|
|||||||
ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
|
ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* msleep for 20ms only if code is trying to resume port */
|
/*
|
||||||
|
* msleep for USB_RESUME_TIMEOUT ms only if code is trying to resume
|
||||||
|
* port
|
||||||
|
*/
|
||||||
if (resume_needed) {
|
if (resume_needed) {
|
||||||
spin_unlock_irq(&ehci->lock);
|
spin_unlock_irq(&ehci->lock);
|
||||||
msleep(20);
|
msleep(USB_RESUME_TIMEOUT);
|
||||||
spin_lock_irq(&ehci->lock);
|
spin_lock_irq(&ehci->lock);
|
||||||
if (ehci->shutdown)
|
if (ehci->shutdown)
|
||||||
goto shutdown;
|
goto shutdown;
|
||||||
@ -942,7 +945,7 @@ int ehci_hub_control(
|
|||||||
temp &= ~PORT_WAKE_BITS;
|
temp &= ~PORT_WAKE_BITS;
|
||||||
ehci_writel(ehci, temp | PORT_RESUME, status_reg);
|
ehci_writel(ehci, temp | PORT_RESUME, status_reg);
|
||||||
ehci->reset_done[wIndex] = jiffies
|
ehci->reset_done[wIndex] = jiffies
|
||||||
+ msecs_to_jiffies(20);
|
+ msecs_to_jiffies(USB_RESUME_TIMEOUT);
|
||||||
set_bit(wIndex, &ehci->resuming_ports);
|
set_bit(wIndex, &ehci->resuming_ports);
|
||||||
usb_hcd_start_port_resume(&hcd->self, wIndex);
|
usb_hcd_start_port_resume(&hcd->self, wIndex);
|
||||||
break;
|
break;
|
||||||
|
@ -1595,7 +1595,7 @@ static int fotg210_hub_control(
|
|||||||
/* resume signaling for 20 msec */
|
/* resume signaling for 20 msec */
|
||||||
fotg210_writel(fotg210, temp | PORT_RESUME, status_reg);
|
fotg210_writel(fotg210, temp | PORT_RESUME, status_reg);
|
||||||
fotg210->reset_done[wIndex] = jiffies
|
fotg210->reset_done[wIndex] = jiffies
|
||||||
+ msecs_to_jiffies(20);
|
+ msecs_to_jiffies(USB_RESUME_TIMEOUT);
|
||||||
break;
|
break;
|
||||||
case USB_PORT_FEAT_C_SUSPEND:
|
case USB_PORT_FEAT_C_SUSPEND:
|
||||||
clear_bit(wIndex, &fotg210->port_c_suspend);
|
clear_bit(wIndex, &fotg210->port_c_suspend);
|
||||||
|
@ -1550,10 +1550,9 @@ static int fusbh200_hub_control (
|
|||||||
if ((temp & PORT_PE) == 0)
|
if ((temp & PORT_PE) == 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* resume signaling for 20 msec */
|
|
||||||
fusbh200_writel(fusbh200, temp | PORT_RESUME, status_reg);
|
fusbh200_writel(fusbh200, temp | PORT_RESUME, status_reg);
|
||||||
fusbh200->reset_done[wIndex] = jiffies
|
fusbh200->reset_done[wIndex] = jiffies
|
||||||
+ msecs_to_jiffies(20);
|
+ msecs_to_jiffies(USB_RESUME_TIMEOUT);
|
||||||
break;
|
break;
|
||||||
case USB_PORT_FEAT_C_SUSPEND:
|
case USB_PORT_FEAT_C_SUSPEND:
|
||||||
clear_bit(wIndex, &fusbh200->port_c_suspend);
|
clear_bit(wIndex, &fusbh200->port_c_suspend);
|
||||||
|
@ -1490,7 +1490,7 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
|
|||||||
spin_unlock_irq(&isp116x->lock);
|
spin_unlock_irq(&isp116x->lock);
|
||||||
|
|
||||||
hcd->state = HC_STATE_RESUMING;
|
hcd->state = HC_STATE_RESUMING;
|
||||||
msleep(20);
|
msleep(USB_RESUME_TIMEOUT);
|
||||||
|
|
||||||
/* Go operational */
|
/* Go operational */
|
||||||
spin_lock_irq(&isp116x->lock);
|
spin_lock_irq(&isp116x->lock);
|
||||||
|
@ -2500,11 +2500,12 @@ static irqreturn_t oxu210_hcd_irq(struct usb_hcd *hcd)
|
|||||||
|| oxu->reset_done[i] != 0)
|
|| oxu->reset_done[i] != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* start 20 msec resume signaling from this port,
|
/* start USB_RESUME_TIMEOUT resume signaling from this
|
||||||
* and make hub_wq collect PORT_STAT_C_SUSPEND to
|
* port, and make hub_wq collect PORT_STAT_C_SUSPEND to
|
||||||
* stop that signaling.
|
* stop that signaling.
|
||||||
*/
|
*/
|
||||||
oxu->reset_done[i] = jiffies + msecs_to_jiffies(20);
|
oxu->reset_done[i] = jiffies +
|
||||||
|
msecs_to_jiffies(USB_RESUME_TIMEOUT);
|
||||||
oxu_dbg(oxu, "port %d remote wakeup\n", i + 1);
|
oxu_dbg(oxu, "port %d remote wakeup\n", i + 1);
|
||||||
mod_timer(&hcd->rh_timer, oxu->reset_done[i]);
|
mod_timer(&hcd->rh_timer, oxu->reset_done[i]);
|
||||||
}
|
}
|
||||||
|
@ -2301,7 +2301,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd)
|
|||||||
rh->port &= ~USB_PORT_STAT_SUSPEND;
|
rh->port &= ~USB_PORT_STAT_SUSPEND;
|
||||||
rh->port |= USB_PORT_STAT_C_SUSPEND << 16;
|
rh->port |= USB_PORT_STAT_C_SUSPEND << 16;
|
||||||
r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg);
|
r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg);
|
||||||
msleep(50);
|
msleep(USB_RESUME_TIMEOUT);
|
||||||
r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg);
|
r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1259,7 +1259,7 @@ sl811h_hub_control(
|
|||||||
sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1);
|
sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1);
|
||||||
|
|
||||||
mod_timer(&sl811->timer, jiffies
|
mod_timer(&sl811->timer, jiffies
|
||||||
+ msecs_to_jiffies(20));
|
+ msecs_to_jiffies(USB_RESUME_TIMEOUT));
|
||||||
break;
|
break;
|
||||||
case USB_PORT_FEAT_POWER:
|
case USB_PORT_FEAT_POWER:
|
||||||
port_power(sl811, 0);
|
port_power(sl811, 0);
|
||||||
|
@ -166,7 +166,7 @@ static void uhci_check_ports(struct uhci_hcd *uhci)
|
|||||||
/* Port received a wakeup request */
|
/* Port received a wakeup request */
|
||||||
set_bit(port, &uhci->resuming_ports);
|
set_bit(port, &uhci->resuming_ports);
|
||||||
uhci->ports_timeout = jiffies +
|
uhci->ports_timeout = jiffies +
|
||||||
msecs_to_jiffies(25);
|
msecs_to_jiffies(USB_RESUME_TIMEOUT);
|
||||||
usb_hcd_start_port_resume(
|
usb_hcd_start_port_resume(
|
||||||
&uhci_to_hcd(uhci)->self, port);
|
&uhci_to_hcd(uhci)->self, port);
|
||||||
|
|
||||||
@ -338,7 +338,8 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||||||
uhci_finish_suspend(uhci, port, port_addr);
|
uhci_finish_suspend(uhci, port, port_addr);
|
||||||
|
|
||||||
/* USB v2.0 7.1.7.5 */
|
/* USB v2.0 7.1.7.5 */
|
||||||
uhci->ports_timeout = jiffies + msecs_to_jiffies(50);
|
uhci->ports_timeout = jiffies +
|
||||||
|
msecs_to_jiffies(USB_RESUME_TIMEOUT);
|
||||||
break;
|
break;
|
||||||
case USB_PORT_FEAT_POWER:
|
case USB_PORT_FEAT_POWER:
|
||||||
/* UHCI has no power switching */
|
/* UHCI has no power switching */
|
||||||
|
@ -1574,7 +1574,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
|
|||||||
} else {
|
} else {
|
||||||
xhci_dbg(xhci, "resume HS port %d\n", port_id);
|
xhci_dbg(xhci, "resume HS port %d\n", port_id);
|
||||||
bus_state->resume_done[faked_port_index] = jiffies +
|
bus_state->resume_done[faked_port_index] = jiffies +
|
||||||
msecs_to_jiffies(20);
|
msecs_to_jiffies(USB_RESUME_TIMEOUT);
|
||||||
set_bit(faked_port_index, &bus_state->resuming_ports);
|
set_bit(faked_port_index, &bus_state->resuming_ports);
|
||||||
mod_timer(&hcd->rh_timer,
|
mod_timer(&hcd->rh_timer,
|
||||||
bus_state->resume_done[faked_port_index]);
|
bus_state->resume_done[faked_port_index]);
|
||||||
|
@ -1869,7 +1869,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
|
|||||||
reg_write32(hcd->regs, HC_PORTSC1,
|
reg_write32(hcd->regs, HC_PORTSC1,
|
||||||
temp | PORT_RESUME);
|
temp | PORT_RESUME);
|
||||||
priv->reset_done = jiffies +
|
priv->reset_done = jiffies +
|
||||||
msecs_to_jiffies(20);
|
msecs_to_jiffies(USB_RESUME_TIMEOUT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case USB_PORT_FEAT_C_SUSPEND:
|
case USB_PORT_FEAT_C_SUSPEND:
|
||||||
|
@ -99,6 +99,7 @@
|
|||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/usb.h>
|
||||||
|
|
||||||
#include "musb_core.h"
|
#include "musb_core.h"
|
||||||
|
|
||||||
@ -549,7 +550,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
|
|||||||
(USB_PORT_STAT_C_SUSPEND << 16)
|
(USB_PORT_STAT_C_SUSPEND << 16)
|
||||||
| MUSB_PORT_STAT_RESUME;
|
| MUSB_PORT_STAT_RESUME;
|
||||||
musb->rh_timer = jiffies
|
musb->rh_timer = jiffies
|
||||||
+ msecs_to_jiffies(20);
|
+ msecs_to_jiffies(USB_RESUME_TIMEOUT);
|
||||||
musb->need_finish_resume = 1;
|
musb->need_finish_resume = 1;
|
||||||
|
|
||||||
musb->xceiv->otg->state = OTG_STATE_A_HOST;
|
musb->xceiv->otg->state = OTG_STATE_A_HOST;
|
||||||
@ -2463,7 +2464,7 @@ static int musb_resume(struct device *dev)
|
|||||||
if (musb->need_finish_resume) {
|
if (musb->need_finish_resume) {
|
||||||
musb->need_finish_resume = 0;
|
musb->need_finish_resume = 0;
|
||||||
schedule_delayed_work(&musb->finish_resume_work,
|
schedule_delayed_work(&musb->finish_resume_work,
|
||||||
msecs_to_jiffies(20));
|
msecs_to_jiffies(USB_RESUME_TIMEOUT));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2506,7 +2507,7 @@ static int musb_runtime_resume(struct device *dev)
|
|||||||
if (musb->need_finish_resume) {
|
if (musb->need_finish_resume) {
|
||||||
musb->need_finish_resume = 0;
|
musb->need_finish_resume = 0;
|
||||||
schedule_delayed_work(&musb->finish_resume_work,
|
schedule_delayed_work(&musb->finish_resume_work,
|
||||||
msecs_to_jiffies(20));
|
msecs_to_jiffies(USB_RESUME_TIMEOUT));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -136,7 +136,7 @@ void musb_port_suspend(struct musb *musb, bool do_suspend)
|
|||||||
/* later, GetPortStatus will stop RESUME signaling */
|
/* later, GetPortStatus will stop RESUME signaling */
|
||||||
musb->port1_status |= MUSB_PORT_STAT_RESUME;
|
musb->port1_status |= MUSB_PORT_STAT_RESUME;
|
||||||
schedule_delayed_work(&musb->finish_resume_work,
|
schedule_delayed_work(&musb->finish_resume_work,
|
||||||
msecs_to_jiffies(20));
|
msecs_to_jiffies(USB_RESUME_TIMEOUT));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +205,32 @@ void usb_put_intf(struct usb_interface *intf);
|
|||||||
#define USB_MAXINTERFACES 32
|
#define USB_MAXINTERFACES 32
|
||||||
#define USB_MAXIADS (USB_MAXINTERFACES/2)
|
#define USB_MAXIADS (USB_MAXINTERFACES/2)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Resume Timer: Every Host controller driver should drive the resume
|
||||||
|
* signalling on the bus for the amount of time defined by this macro.
|
||||||
|
*
|
||||||
|
* That way we will have a 'stable' behavior among all HCDs supported by Linux.
|
||||||
|
*
|
||||||
|
* Note that the USB Specification states we should drive resume for *at least*
|
||||||
|
* 20 ms, but it doesn't give an upper bound. This creates two possible
|
||||||
|
* situations which we want to avoid:
|
||||||
|
*
|
||||||
|
* (a) sometimes an msleep(20) might expire slightly before 20 ms, which causes
|
||||||
|
* us to fail USB Electrical Tests, thus failing Certification
|
||||||
|
*
|
||||||
|
* (b) Some (many) devices actually need more than 20 ms of resume signalling,
|
||||||
|
* and while we can argue that's against the USB Specification, we don't have
|
||||||
|
* control over which devices a certification laboratory will be using for
|
||||||
|
* certification. If CertLab uses a device which was tested against Windows and
|
||||||
|
* that happens to have relaxed resume signalling rules, we might fall into
|
||||||
|
* situations where we fail interoperability and electrical tests.
|
||||||
|
*
|
||||||
|
* In order to avoid both conditions, we're using a 40 ms resume timeout, which
|
||||||
|
* should cope with both LPJ calibration errors and devices not following every
|
||||||
|
* detail of the USB Specification.
|
||||||
|
*/
|
||||||
|
#define USB_RESUME_TIMEOUT 40 /* ms */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct usb_interface_cache - long-term representation of a device interface
|
* struct usb_interface_cache - long-term representation of a device interface
|
||||||
* @num_altsetting: number of altsettings defined.
|
* @num_altsetting: number of altsettings defined.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user