aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorAndiry Xu <andiry.xu@amd.com>2011-09-23 17:19:51 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-09-26 18:51:10 -0400
commit9574323c39d1f8359a04843075d89c9f32d8b7e6 (patch)
tree38514abe7e4485face5fa1fb081c4a51a6f300c7 /drivers/usb
parentfc71ff7583b14347fa1cb592b698f088ecff36e3 (diff)
xHCI: test USB2 software LPM
This patch tests USB2 software LPM for a USB2 LPM-capable device. When a lpm-capable device is addressed, if the host also supports software LPM, apply a test by putting the device into L1 state and resume it to see if the device can do L1 suspend/resume successfully. If the device fails to enter L1 or resume from L1 state, it may not function normally and usbcore may disconnect and re-enumerate it. In this case, store the device's Vid and Pid information, make sure the host will not test LPM for it twice. The test result is per device/host. Some devices claim to be lpm-capable, but fail to enter L1 or resume. So the test is necessary. The xHCI 1.0 errata has modified the USB2.0 LPM implementation. It redefines the HIRD field to BESL, and adds another register Port Hardware LPM Control (PORTHLPMC). However, this should not affect the LPM behavior on xHC which does not implement 1.0 errata. USB2.0 LPM errata defines a new bit BESL in the device's USB 2.0 extension descriptor. If the device reports it uses BESL, driver should use BESL instead of HIRD for it. Signed-off-by: Andiry Xu <andiry.xu@amd.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/xhci-mem.c11
-rw-r--r--drivers/usb/host/xhci-pci.c4
-rw-r--r--drivers/usb/host/xhci.c181
-rw-r--r--drivers/usb/host/xhci.h16
4 files changed, 211 insertions, 1 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 9c7ddf0f3a43..3ec2ac9636fe 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1685,6 +1685,8 @@ void xhci_free_command(struct xhci_hcd *xhci,
1685void xhci_mem_cleanup(struct xhci_hcd *xhci) 1685void xhci_mem_cleanup(struct xhci_hcd *xhci)
1686{ 1686{
1687 struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); 1687 struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
1688 struct dev_info *dev_info, *next;
1689 unsigned long flags;
1688 int size; 1690 int size;
1689 int i; 1691 int i;
1690 1692
@@ -1742,6 +1744,13 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
1742 1744
1743 scratchpad_free(xhci); 1745 scratchpad_free(xhci);
1744 1746
1747 spin_lock_irqsave(&xhci->lock, flags);
1748 list_for_each_entry_safe(dev_info, next, &xhci->lpm_failed_devs, list) {
1749 list_del(&dev_info->list);
1750 kfree(dev_info);
1751 }
1752 spin_unlock_irqrestore(&xhci->lock, flags);
1753
1745 xhci->num_usb2_ports = 0; 1754 xhci->num_usb2_ports = 0;
1746 xhci->num_usb3_ports = 0; 1755 xhci->num_usb3_ports = 0;
1747 kfree(xhci->usb2_ports); 1756 kfree(xhci->usb2_ports);
@@ -2328,6 +2337,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
2328 if (xhci_setup_port_arrays(xhci, flags)) 2337 if (xhci_setup_port_arrays(xhci, flags))
2329 goto fail; 2338 goto fail;
2330 2339
2340 INIT_LIST_HEAD(&xhci->lpm_failed_devs);
2341
2331 return 0; 2342 return 0;
2332 2343
2333fail: 2344fail:
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index a1110996b76f..213a7d73b118 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -345,6 +345,10 @@ static const struct hc_driver xhci_pci_hc_driver = {
345 .hub_status_data = xhci_hub_status_data, 345 .hub_status_data = xhci_hub_status_data,
346 .bus_suspend = xhci_bus_suspend, 346 .bus_suspend = xhci_bus_suspend,
347 .bus_resume = xhci_bus_resume, 347 .bus_resume = xhci_bus_resume,
348 /*
349 * call back when device connected and addressed
350 */
351 .update_device = xhci_update_device,
348}; 352};
349 353
350/*-------------------------------------------------------------------------*/ 354/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 54cb762d15c8..b0649a4bd315 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3539,6 +3539,187 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
3539 return 0; 3539 return 0;
3540} 3540}
3541 3541
3542#ifdef CONFIG_USB_SUSPEND
3543
3544/* BESL to HIRD Encoding array for USB2 LPM */
3545static int xhci_besl_encoding[16] = {125, 150, 200, 300, 400, 500, 1000, 2000,
3546 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000};
3547
3548/* Calculate HIRD/BESL for USB2 PORTPMSC*/
3549static int xhci_calculate_hird_besl(int u2del, bool use_besl)
3550{
3551 int hird;
3552
3553 if (use_besl) {
3554 for (hird = 0; hird < 16; hird++) {
3555 if (xhci_besl_encoding[hird] >= u2del)
3556 break;
3557 }
3558 } else {
3559 if (u2del <= 50)
3560 hird = 0;
3561 else
3562 hird = (u2del - 51) / 75 + 1;
3563
3564 if (hird > 15)
3565 hird = 15;
3566 }
3567
3568 return hird;
3569}
3570
3571static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd,
3572 struct usb_device *udev)
3573{
3574 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
3575 struct dev_info *dev_info;
3576 __le32 __iomem **port_array;
3577 __le32 __iomem *addr, *pm_addr;
3578 u32 temp, dev_id;
3579 unsigned int port_num;
3580 unsigned long flags;
3581 int u2del, hird;
3582 int ret;
3583
3584 if (hcd->speed == HCD_USB3 || !xhci->sw_lpm_support ||
3585 !udev->lpm_capable)
3586 return -EINVAL;
3587
3588 /* we only support lpm for non-hub device connected to root hub yet */
3589 if (!udev->parent || udev->parent->parent ||
3590 udev->descriptor.bDeviceClass == USB_CLASS_HUB)
3591 return -EINVAL;
3592
3593 spin_lock_irqsave(&xhci->lock, flags);
3594
3595 /* Look for devices in lpm_failed_devs list */
3596 dev_id = le16_to_cpu(udev->descriptor.idVendor) << 16 |
3597 le16_to_cpu(udev->descriptor.idProduct);
3598 list_for_each_entry(dev_info, &xhci->lpm_failed_devs, list) {
3599 if (dev_info->dev_id == dev_id) {
3600 ret = -EINVAL;
3601 goto finish;
3602 }
3603 }
3604
3605 port_array = xhci->usb2_ports;
3606 port_num = udev->portnum - 1;
3607
3608 if (port_num > HCS_MAX_PORTS(xhci->hcs_params1)) {
3609 xhci_dbg(xhci, "invalid port number %d\n", udev->portnum);
3610 ret = -EINVAL;
3611 goto finish;
3612 }
3613
3614 /*
3615 * Test USB 2.0 software LPM.
3616 * FIXME: some xHCI 1.0 hosts may implement a new register to set up
3617 * hardware-controlled USB 2.0 LPM. See section 5.4.11 and 4.23.5.1.1.1
3618 * in the June 2011 errata release.
3619 */
3620 xhci_dbg(xhci, "test port %d software LPM\n", port_num);
3621 /*
3622 * Set L1 Device Slot and HIRD/BESL.
3623 * Check device's USB 2.0 extension descriptor to determine whether
3624 * HIRD or BESL shoule be used. See USB2.0 LPM errata.
3625 */
3626 pm_addr = port_array[port_num] + 1;
3627 u2del = HCS_U2_LATENCY(xhci->hcs_params3);
3628 if (le32_to_cpu(udev->bos->ext_cap->bmAttributes) & (1 << 2))
3629 hird = xhci_calculate_hird_besl(u2del, 1);
3630 else
3631 hird = xhci_calculate_hird_besl(u2del, 0);
3632
3633 temp = PORT_L1DS(udev->slot_id) | PORT_HIRD(hird);
3634 xhci_writel(xhci, temp, pm_addr);
3635
3636 /* Set port link state to U2(L1) */
3637 addr = port_array[port_num];
3638 xhci_set_link_state(xhci, port_array, port_num, XDEV_U2);
3639
3640 /* wait for ACK */
3641 spin_unlock_irqrestore(&xhci->lock, flags);
3642 msleep(10);
3643 spin_lock_irqsave(&xhci->lock, flags);
3644
3645 /* Check L1 Status */
3646 ret = handshake(xhci, pm_addr, PORT_L1S_MASK, PORT_L1S_SUCCESS, 125);
3647 if (ret != -ETIMEDOUT) {
3648 /* enter L1 successfully */
3649 temp = xhci_readl(xhci, addr);
3650 xhci_dbg(xhci, "port %d entered L1 state, port status 0x%x\n",
3651 port_num, temp);
3652 ret = 0;
3653 } else {
3654 temp = xhci_readl(xhci, pm_addr);
3655 xhci_dbg(xhci, "port %d software lpm failed, L1 status %d\n",
3656 port_num, temp & PORT_L1S_MASK);
3657 ret = -EINVAL;
3658 }
3659
3660 /* Resume the port */
3661 xhci_set_link_state(xhci, port_array, port_num, XDEV_U0);
3662
3663 spin_unlock_irqrestore(&xhci->lock, flags);
3664 msleep(10);
3665 spin_lock_irqsave(&xhci->lock, flags);
3666
3667 /* Clear PLC */
3668 xhci_test_and_clear_bit(xhci, port_array, port_num, PORT_PLC);
3669
3670 /* Check PORTSC to make sure the device is in the right state */
3671 if (!ret) {
3672 temp = xhci_readl(xhci, addr);
3673 xhci_dbg(xhci, "resumed port %d status 0x%x\n", port_num, temp);
3674 if (!(temp & PORT_CONNECT) || !(temp & PORT_PE) ||
3675 (temp & PORT_PLS_MASK) != XDEV_U0) {
3676 xhci_dbg(xhci, "port L1 resume fail\n");
3677 ret = -EINVAL;
3678 }
3679 }
3680
3681 if (ret) {
3682 /* Insert dev to lpm_failed_devs list */
3683 xhci_warn(xhci, "device LPM test failed, may disconnect and "
3684 "re-enumerate\n");
3685 dev_info = kzalloc(sizeof(struct dev_info), GFP_ATOMIC);
3686 if (!dev_info) {
3687 ret = -ENOMEM;
3688 goto finish;
3689 }
3690 dev_info->dev_id = dev_id;
3691 INIT_LIST_HEAD(&dev_info->list);
3692 list_add(&dev_info->list, &xhci->lpm_failed_devs);
3693 } else {
3694 xhci_ring_device(xhci, udev->slot_id);
3695 }
3696
3697finish:
3698 spin_unlock_irqrestore(&xhci->lock, flags);
3699 return ret;
3700}
3701
3702int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
3703{
3704 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
3705 int ret;
3706
3707 ret = xhci_usb2_software_lpm_test(hcd, udev);
3708 if (!ret)
3709 xhci_dbg(xhci, "software LPM test succeed\n");
3710
3711 return 0;
3712}
3713
3714#else
3715
3716int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
3717{
3718 return 0;
3719}
3720
3721#endif /* CONFIG_USB_SUSPEND */
3722
3542/* Once a hub descriptor is fetched for a device, we need to update the xHC's 3723/* Once a hub descriptor is fetched for a device, we need to update the xHC's
3543 * internal data structures for the device. 3724 * internal data structures for the device.
3544 */ 3725 */
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 8673f985046e..b24c4fce457e 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -272,6 +272,7 @@ struct xhci_op_regs {
272 */ 272 */
273#define PORT_PLS_MASK (0xf << 5) 273#define PORT_PLS_MASK (0xf << 5)
274#define XDEV_U0 (0x0 << 5) 274#define XDEV_U0 (0x0 << 5)
275#define XDEV_U2 (0x2 << 5)
275#define XDEV_U3 (0x3 << 5) 276#define XDEV_U3 (0x3 << 5)
276#define XDEV_RESUME (0xf << 5) 277#define XDEV_RESUME (0xf << 5)
277/* true: port has power (see HCC_PPC) */ 278/* true: port has power (see HCC_PPC) */
@@ -362,7 +363,11 @@ struct xhci_op_regs {
362/* Bits 24:31 for port testing */ 363/* Bits 24:31 for port testing */
363 364
364/* USB2 Protocol PORTSPMSC */ 365/* USB2 Protocol PORTSPMSC */
365#define PORT_RWE (1 << 0x3) 366#define PORT_L1S_MASK 7
367#define PORT_L1S_SUCCESS 1
368#define PORT_RWE (1 << 3)
369#define PORT_HIRD(p) (((p) & 0xf) << 4)
370#define PORT_L1DS(p) (((p) & 0xff) << 8)
366 371
367/** 372/**
368 * struct xhci_intr_reg - Interrupt Register Set 373 * struct xhci_intr_reg - Interrupt Register Set
@@ -1324,6 +1329,12 @@ struct s3_save {
1324 u64 erst_dequeue; 1329 u64 erst_dequeue;
1325}; 1330};
1326 1331
1332/* Use for lpm */
1333struct dev_info {
1334 u32 dev_id;
1335 struct list_head list;
1336};
1337
1327struct xhci_bus_state { 1338struct xhci_bus_state {
1328 unsigned long bus_suspended; 1339 unsigned long bus_suspended;
1329 unsigned long next_statechange; 1340 unsigned long next_statechange;
@@ -1387,6 +1398,8 @@ struct xhci_hcd {
1387 struct xhci_erst erst; 1398 struct xhci_erst erst;
1388 /* Scratchpad */ 1399 /* Scratchpad */
1389 struct xhci_scratchpad *scratchpad; 1400 struct xhci_scratchpad *scratchpad;
1401 /* Store LPM test failed devices' information */
1402 struct list_head lpm_failed_devs;
1390 1403
1391 /* slot enabling and address device helpers */ 1404 /* slot enabling and address device helpers */
1392 struct completion addr_dev; 1405 struct completion addr_dev;
@@ -1663,6 +1676,7 @@ int xhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
1663 struct usb_host_endpoint **eps, unsigned int num_eps, 1676 struct usb_host_endpoint **eps, unsigned int num_eps,
1664 gfp_t mem_flags); 1677 gfp_t mem_flags);
1665int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev); 1678int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev);
1679int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev);
1666int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, 1680int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
1667 struct usb_tt *tt, gfp_t mem_flags); 1681 struct usb_tt *tt, gfp_t mem_flags);
1668int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags); 1682int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags);