diff options
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 11 | ||||
-rw-r--r-- | drivers/usb/host/xhci-pci.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/xhci.c | 181 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 16 |
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, | |||
1685 | void xhci_mem_cleanup(struct xhci_hcd *xhci) | 1685 | void 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 | ||
2333 | fail: | 2344 | fail: |
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 */ | ||
3545 | static 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*/ | ||
3549 | static 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 | |||
3571 | static 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 | |||
3697 | finish: | ||
3698 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
3699 | return ret; | ||
3700 | } | ||
3701 | |||
3702 | int 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 | |||
3716 | int 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 */ | ||
1333 | struct dev_info { | ||
1334 | u32 dev_id; | ||
1335 | struct list_head list; | ||
1336 | }; | ||
1337 | |||
1327 | struct xhci_bus_state { | 1338 | struct 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); |
1665 | int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev); | 1678 | int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev); |
1679 | int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev); | ||
1666 | int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, | 1680 | int 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); |
1668 | int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags); | 1682 | int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags); |