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:
Greg Kroah-Hartman 2015-04-10 13:45:27 +02:00
commit c8d1bc12c7
16 changed files with 59 additions and 28 deletions

View file

@ -3406,10 +3406,10 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
if (status) {
dev_dbg(&port_dev->dev, "can't resume, status %d\n", status);
} else {
/* drive resume for at least 20 msec */
/* drive resume for USB_RESUME_TIMEOUT msec */
dev_dbg(&udev->dev, "usb %sresume\n",
(PMSG_IS_AUTO(msg) ? "auto-" : ""));
msleep(25);
msleep(USB_RESUME_TIMEOUT);
/* Virtual root hubs can trigger on GET_PORT_STATUS to
* stop resume signaling. Then finish the resume

View file

@ -1529,7 +1529,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
dev_dbg(hsotg->dev,
"ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
writel(0, hsotg->regs + PCGCTL);
usleep_range(20000, 40000);
msleep(USB_RESUME_TIMEOUT);
hprt0 = dwc2_read_hprt0(hsotg);
hprt0 |= HPRT0_RES;

View file

@ -792,12 +792,12 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
ehci->reset_done[i] == 0))
continue;
/* start 20 msec resume signaling from this port,
* and make hub_wq collect PORT_STAT_C_SUSPEND to
* stop that signaling. Use 5 ms extra for safety,
* like usb_port_resume() does.
/* start USB_RESUME_TIMEOUT msec resume signaling from
* this port, and make hub_wq collect
* PORT_STAT_C_SUSPEND to stop that signaling.
*/
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);
ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
usb_hcd_start_port_resume(&hcd->self, i);

View file

@ -471,10 +471,13 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
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) {
spin_unlock_irq(&ehci->lock);
msleep(20);
msleep(USB_RESUME_TIMEOUT);
spin_lock_irq(&ehci->lock);
if (ehci->shutdown)
goto shutdown;
@ -942,7 +945,7 @@ int ehci_hub_control(
temp &= ~PORT_WAKE_BITS;
ehci_writel(ehci, temp | PORT_RESUME, status_reg);
ehci->reset_done[wIndex] = jiffies
+ msecs_to_jiffies(20);
+ msecs_to_jiffies(USB_RESUME_TIMEOUT);
set_bit(wIndex, &ehci->resuming_ports);
usb_hcd_start_port_resume(&hcd->self, wIndex);
break;

View file

@ -1595,7 +1595,7 @@ static int fotg210_hub_control(
/* resume signaling for 20 msec */
fotg210_writel(fotg210, temp | PORT_RESUME, status_reg);
fotg210->reset_done[wIndex] = jiffies
+ msecs_to_jiffies(20);
+ msecs_to_jiffies(USB_RESUME_TIMEOUT);
break;
case USB_PORT_FEAT_C_SUSPEND:
clear_bit(wIndex, &fotg210->port_c_suspend);

View file

@ -1550,10 +1550,9 @@ static int fusbh200_hub_control (
if ((temp & PORT_PE) == 0)
goto error;
/* resume signaling for 20 msec */
fusbh200_writel(fusbh200, temp | PORT_RESUME, status_reg);
fusbh200->reset_done[wIndex] = jiffies
+ msecs_to_jiffies(20);
+ msecs_to_jiffies(USB_RESUME_TIMEOUT);
break;
case USB_PORT_FEAT_C_SUSPEND:
clear_bit(wIndex, &fusbh200->port_c_suspend);

View file

@ -1490,7 +1490,7 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
spin_unlock_irq(&isp116x->lock);
hcd->state = HC_STATE_RESUMING;
msleep(20);
msleep(USB_RESUME_TIMEOUT);
/* Go operational */
spin_lock_irq(&isp116x->lock);

View file

@ -2500,11 +2500,12 @@ static irqreturn_t oxu210_hcd_irq(struct usb_hcd *hcd)
|| oxu->reset_done[i] != 0)
continue;
/* start 20 msec resume signaling from this port,
* and make hub_wq collect PORT_STAT_C_SUSPEND to
/* start USB_RESUME_TIMEOUT resume signaling from this
* port, and make hub_wq collect PORT_STAT_C_SUSPEND to
* 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);
mod_timer(&hcd->rh_timer, oxu->reset_done[i]);
}

View file

@ -2301,7 +2301,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd)
rh->port &= ~USB_PORT_STAT_SUSPEND;
rh->port |= USB_PORT_STAT_C_SUSPEND << 16;
r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg);
msleep(50);
msleep(USB_RESUME_TIMEOUT);
r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg);
}

View file

@ -1259,7 +1259,7 @@ sl811h_hub_control(
sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1);
mod_timer(&sl811->timer, jiffies
+ msecs_to_jiffies(20));
+ msecs_to_jiffies(USB_RESUME_TIMEOUT));
break;
case USB_PORT_FEAT_POWER:
port_power(sl811, 0);

View file

@ -166,7 +166,7 @@ static void uhci_check_ports(struct uhci_hcd *uhci)
/* Port received a wakeup request */
set_bit(port, &uhci->resuming_ports);
uhci->ports_timeout = jiffies +
msecs_to_jiffies(25);
msecs_to_jiffies(USB_RESUME_TIMEOUT);
usb_hcd_start_port_resume(
&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);
/* 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;
case USB_PORT_FEAT_POWER:
/* UHCI has no power switching */

View file

@ -1574,7 +1574,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
} else {
xhci_dbg(xhci, "resume HS port %d\n", port_id);
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);
mod_timer(&hcd->rh_timer,
bus_state->resume_done[faked_port_index]);

View file

@ -1869,7 +1869,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
reg_write32(hcd->regs, HC_PORTSC1,
temp | PORT_RESUME);
priv->reset_done = jiffies +
msecs_to_jiffies(20);
msecs_to_jiffies(USB_RESUME_TIMEOUT);
}
break;
case USB_PORT_FEAT_C_SUSPEND:

View file

@ -99,6 +99,7 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/usb.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)
| MUSB_PORT_STAT_RESUME;
musb->rh_timer = jiffies
+ msecs_to_jiffies(20);
+ msecs_to_jiffies(USB_RESUME_TIMEOUT);
musb->need_finish_resume = 1;
musb->xceiv->otg->state = OTG_STATE_A_HOST;
@ -2463,7 +2464,7 @@ static int musb_resume(struct device *dev)
if (musb->need_finish_resume) {
musb->need_finish_resume = 0;
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) {
musb->need_finish_resume = 0;
schedule_delayed_work(&musb->finish_resume_work,
msecs_to_jiffies(20));
msecs_to_jiffies(USB_RESUME_TIMEOUT));
}
return 0;

View file

@ -136,7 +136,7 @@ void musb_port_suspend(struct musb *musb, bool do_suspend)
/* later, GetPortStatus will stop RESUME signaling */
musb->port1_status |= MUSB_PORT_STAT_RESUME;
schedule_delayed_work(&musb->finish_resume_work,
msecs_to_jiffies(20));
msecs_to_jiffies(USB_RESUME_TIMEOUT));
}
}

View file

@ -205,6 +205,32 @@ void usb_put_intf(struct usb_interface *intf);
#define USB_MAXINTERFACES 32
#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
* @num_altsetting: number of altsettings defined.