diff options
Diffstat (limited to 'drivers/usb/host/xhci.c')
-rw-r--r-- | drivers/usb/host/xhci.c | 182 |
1 files changed, 23 insertions, 159 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 6e0d886bcce5..4265b48856f6 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
@@ -3459,7 +3459,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) | |||
3459 | /* Wait for the Reset Device command to finish */ | 3459 | /* Wait for the Reset Device command to finish */ |
3460 | timeleft = wait_for_completion_interruptible_timeout( | 3460 | timeleft = wait_for_completion_interruptible_timeout( |
3461 | reset_device_cmd->completion, | 3461 | reset_device_cmd->completion, |
3462 | USB_CTRL_SET_TIMEOUT); | 3462 | XHCI_CMD_DEFAULT_TIMEOUT); |
3463 | if (timeleft <= 0) { | 3463 | if (timeleft <= 0) { |
3464 | xhci_warn(xhci, "%s while waiting for reset device command\n", | 3464 | xhci_warn(xhci, "%s while waiting for reset device command\n", |
3465 | timeleft == 0 ? "Timeout" : "Signal"); | 3465 | timeleft == 0 ? "Timeout" : "Signal"); |
@@ -3583,11 +3583,6 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) | |||
3583 | del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); | 3583 | del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); |
3584 | } | 3584 | } |
3585 | 3585 | ||
3586 | if (udev->usb2_hw_lpm_enabled) { | ||
3587 | xhci_set_usb2_hardware_lpm(hcd, udev, 0); | ||
3588 | udev->usb2_hw_lpm_enabled = 0; | ||
3589 | } | ||
3590 | |||
3591 | spin_lock_irqsave(&xhci->lock, flags); | 3586 | spin_lock_irqsave(&xhci->lock, flags); |
3592 | /* Don't disable the slot if the host controller is dead. */ | 3587 | /* Don't disable the slot if the host controller is dead. */ |
3593 | state = xhci_readl(xhci, &xhci->op_regs->status); | 3588 | state = xhci_readl(xhci, &xhci->op_regs->status); |
@@ -3721,9 +3716,6 @@ disable_slot: | |||
3721 | * the device). | 3716 | * the device). |
3722 | * We should be protected by the usb_address0_mutex in khubd's hub_port_init, so | 3717 | * We should be protected by the usb_address0_mutex in khubd's hub_port_init, so |
3723 | * we should only issue and wait on one address command at the same time. | 3718 | * we should only issue and wait on one address command at the same time. |
3724 | * | ||
3725 | * We add one to the device address issued by the hardware because the USB core | ||
3726 | * uses address 1 for the root hubs (even though they're not really devices). | ||
3727 | */ | 3719 | */ |
3728 | int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) | 3720 | int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) |
3729 | { | 3721 | { |
@@ -3868,16 +3860,13 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) | |||
3868 | slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx); | 3860 | slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx); |
3869 | trace_xhci_address_ctx(xhci, virt_dev->out_ctx, | 3861 | trace_xhci_address_ctx(xhci, virt_dev->out_ctx, |
3870 | slot_ctx->dev_info >> 27); | 3862 | slot_ctx->dev_info >> 27); |
3871 | /* Use kernel assigned address for devices; store xHC assigned | ||
3872 | * address locally. */ | ||
3873 | virt_dev->address = (le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK) | ||
3874 | + 1; | ||
3875 | /* Zero the input context control for later use */ | 3863 | /* Zero the input context control for later use */ |
3876 | ctrl_ctx->add_flags = 0; | 3864 | ctrl_ctx->add_flags = 0; |
3877 | ctrl_ctx->drop_flags = 0; | 3865 | ctrl_ctx->drop_flags = 0; |
3878 | 3866 | ||
3879 | xhci_dbg_trace(xhci, trace_xhci_dbg_address, | 3867 | xhci_dbg_trace(xhci, trace_xhci_dbg_address, |
3880 | "Internal device address = %d", virt_dev->address); | 3868 | "Internal device address = %d", |
3869 | le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK); | ||
3881 | 3870 | ||
3882 | return 0; | 3871 | return 0; |
3883 | } | 3872 | } |
@@ -4025,133 +4014,6 @@ static int xhci_calculate_usb2_hw_lpm_params(struct usb_device *udev) | |||
4025 | return PORT_BESLD(besld) | PORT_L1_TIMEOUT(l1) | PORT_HIRDM(hirdm); | 4014 | return PORT_BESLD(besld) | PORT_L1_TIMEOUT(l1) | PORT_HIRDM(hirdm); |
4026 | } | 4015 | } |
4027 | 4016 | ||
4028 | static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd, | ||
4029 | struct usb_device *udev) | ||
4030 | { | ||
4031 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
4032 | struct dev_info *dev_info; | ||
4033 | __le32 __iomem **port_array; | ||
4034 | __le32 __iomem *addr, *pm_addr; | ||
4035 | u32 temp, dev_id; | ||
4036 | unsigned int port_num; | ||
4037 | unsigned long flags; | ||
4038 | int hird; | ||
4039 | int ret; | ||
4040 | |||
4041 | if (hcd->speed == HCD_USB3 || !xhci->sw_lpm_support || | ||
4042 | !udev->lpm_capable) | ||
4043 | return -EINVAL; | ||
4044 | |||
4045 | /* we only support lpm for non-hub device connected to root hub yet */ | ||
4046 | if (!udev->parent || udev->parent->parent || | ||
4047 | udev->descriptor.bDeviceClass == USB_CLASS_HUB) | ||
4048 | return -EINVAL; | ||
4049 | |||
4050 | spin_lock_irqsave(&xhci->lock, flags); | ||
4051 | |||
4052 | /* Look for devices in lpm_failed_devs list */ | ||
4053 | dev_id = le16_to_cpu(udev->descriptor.idVendor) << 16 | | ||
4054 | le16_to_cpu(udev->descriptor.idProduct); | ||
4055 | list_for_each_entry(dev_info, &xhci->lpm_failed_devs, list) { | ||
4056 | if (dev_info->dev_id == dev_id) { | ||
4057 | ret = -EINVAL; | ||
4058 | goto finish; | ||
4059 | } | ||
4060 | } | ||
4061 | |||
4062 | port_array = xhci->usb2_ports; | ||
4063 | port_num = udev->portnum - 1; | ||
4064 | |||
4065 | if (port_num > HCS_MAX_PORTS(xhci->hcs_params1)) { | ||
4066 | xhci_dbg(xhci, "invalid port number %d\n", udev->portnum); | ||
4067 | ret = -EINVAL; | ||
4068 | goto finish; | ||
4069 | } | ||
4070 | |||
4071 | /* | ||
4072 | * Test USB 2.0 software LPM. | ||
4073 | * FIXME: some xHCI 1.0 hosts may implement a new register to set up | ||
4074 | * hardware-controlled USB 2.0 LPM. See section 5.4.11 and 4.23.5.1.1.1 | ||
4075 | * in the June 2011 errata release. | ||
4076 | */ | ||
4077 | xhci_dbg(xhci, "test port %d software LPM\n", port_num); | ||
4078 | /* | ||
4079 | * Set L1 Device Slot and HIRD/BESL. | ||
4080 | * Check device's USB 2.0 extension descriptor to determine whether | ||
4081 | * HIRD or BESL shoule be used. See USB2.0 LPM errata. | ||
4082 | */ | ||
4083 | pm_addr = port_array[port_num] + PORTPMSC; | ||
4084 | hird = xhci_calculate_hird_besl(xhci, udev); | ||
4085 | temp = PORT_L1DS(udev->slot_id) | PORT_HIRD(hird); | ||
4086 | xhci_writel(xhci, temp, pm_addr); | ||
4087 | |||
4088 | /* Set port link state to U2(L1) */ | ||
4089 | addr = port_array[port_num]; | ||
4090 | xhci_set_link_state(xhci, port_array, port_num, XDEV_U2); | ||
4091 | |||
4092 | /* wait for ACK */ | ||
4093 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
4094 | msleep(10); | ||
4095 | spin_lock_irqsave(&xhci->lock, flags); | ||
4096 | |||
4097 | /* Check L1 Status */ | ||
4098 | ret = xhci_handshake(xhci, pm_addr, | ||
4099 | PORT_L1S_MASK, PORT_L1S_SUCCESS, 125); | ||
4100 | if (ret != -ETIMEDOUT) { | ||
4101 | /* enter L1 successfully */ | ||
4102 | temp = xhci_readl(xhci, addr); | ||
4103 | xhci_dbg(xhci, "port %d entered L1 state, port status 0x%x\n", | ||
4104 | port_num, temp); | ||
4105 | ret = 0; | ||
4106 | } else { | ||
4107 | temp = xhci_readl(xhci, pm_addr); | ||
4108 | xhci_dbg(xhci, "port %d software lpm failed, L1 status %d\n", | ||
4109 | port_num, temp & PORT_L1S_MASK); | ||
4110 | ret = -EINVAL; | ||
4111 | } | ||
4112 | |||
4113 | /* Resume the port */ | ||
4114 | xhci_set_link_state(xhci, port_array, port_num, XDEV_U0); | ||
4115 | |||
4116 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
4117 | msleep(10); | ||
4118 | spin_lock_irqsave(&xhci->lock, flags); | ||
4119 | |||
4120 | /* Clear PLC */ | ||
4121 | xhci_test_and_clear_bit(xhci, port_array, port_num, PORT_PLC); | ||
4122 | |||
4123 | /* Check PORTSC to make sure the device is in the right state */ | ||
4124 | if (!ret) { | ||
4125 | temp = xhci_readl(xhci, addr); | ||
4126 | xhci_dbg(xhci, "resumed port %d status 0x%x\n", port_num, temp); | ||
4127 | if (!(temp & PORT_CONNECT) || !(temp & PORT_PE) || | ||
4128 | (temp & PORT_PLS_MASK) != XDEV_U0) { | ||
4129 | xhci_dbg(xhci, "port L1 resume fail\n"); | ||
4130 | ret = -EINVAL; | ||
4131 | } | ||
4132 | } | ||
4133 | |||
4134 | if (ret) { | ||
4135 | /* Insert dev to lpm_failed_devs list */ | ||
4136 | xhci_warn(xhci, "device LPM test failed, may disconnect and " | ||
4137 | "re-enumerate\n"); | ||
4138 | dev_info = kzalloc(sizeof(struct dev_info), GFP_ATOMIC); | ||
4139 | if (!dev_info) { | ||
4140 | ret = -ENOMEM; | ||
4141 | goto finish; | ||
4142 | } | ||
4143 | dev_info->dev_id = dev_id; | ||
4144 | INIT_LIST_HEAD(&dev_info->list); | ||
4145 | list_add(&dev_info->list, &xhci->lpm_failed_devs); | ||
4146 | } else { | ||
4147 | xhci_ring_device(xhci, udev->slot_id); | ||
4148 | } | ||
4149 | |||
4150 | finish: | ||
4151 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
4152 | return ret; | ||
4153 | } | ||
4154 | |||
4155 | int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, | 4017 | int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, |
4156 | struct usb_device *udev, int enable) | 4018 | struct usb_device *udev, int enable) |
4157 | { | 4019 | { |
@@ -4228,7 +4090,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, | |||
4228 | } | 4090 | } |
4229 | 4091 | ||
4230 | pm_val &= ~PORT_HIRD_MASK; | 4092 | pm_val &= ~PORT_HIRD_MASK; |
4231 | pm_val |= PORT_HIRD(hird) | PORT_RWE; | 4093 | pm_val |= PORT_HIRD(hird) | PORT_RWE | PORT_L1DS(udev->slot_id); |
4232 | xhci_writel(xhci, pm_val, pm_addr); | 4094 | xhci_writel(xhci, pm_val, pm_addr); |
4233 | pm_val = xhci_readl(xhci, pm_addr); | 4095 | pm_val = xhci_readl(xhci, pm_addr); |
4234 | pm_val |= PORT_HLE; | 4096 | pm_val |= PORT_HLE; |
@@ -4236,7 +4098,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, | |||
4236 | /* flush write */ | 4098 | /* flush write */ |
4237 | xhci_readl(xhci, pm_addr); | 4099 | xhci_readl(xhci, pm_addr); |
4238 | } else { | 4100 | } else { |
4239 | pm_val &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK); | 4101 | pm_val &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK | PORT_L1DS_MASK); |
4240 | xhci_writel(xhci, pm_val, pm_addr); | 4102 | xhci_writel(xhci, pm_val, pm_addr); |
4241 | /* flush write */ | 4103 | /* flush write */ |
4242 | xhci_readl(xhci, pm_addr); | 4104 | xhci_readl(xhci, pm_addr); |
@@ -4279,24 +4141,26 @@ static int xhci_check_usb2_port_capability(struct xhci_hcd *xhci, int port, | |||
4279 | int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) | 4141 | int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) |
4280 | { | 4142 | { |
4281 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 4143 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
4282 | int ret; | ||
4283 | int portnum = udev->portnum - 1; | 4144 | int portnum = udev->portnum - 1; |
4284 | 4145 | ||
4285 | ret = xhci_usb2_software_lpm_test(hcd, udev); | 4146 | if (hcd->speed == HCD_USB3 || !xhci->sw_lpm_support || |
4286 | if (!ret) { | 4147 | !udev->lpm_capable) |
4287 | xhci_dbg(xhci, "software LPM test succeed\n"); | 4148 | return 0; |
4288 | if (xhci->hw_lpm_support == 1 && | 4149 | |
4289 | xhci_check_usb2_port_capability(xhci, portnum, XHCI_HLC)) { | 4150 | /* we only support lpm for non-hub device connected to root hub yet */ |
4290 | udev->usb2_hw_lpm_capable = 1; | 4151 | if (!udev->parent || udev->parent->parent || |
4291 | udev->l1_params.timeout = XHCI_L1_TIMEOUT; | 4152 | udev->descriptor.bDeviceClass == USB_CLASS_HUB) |
4292 | udev->l1_params.besl = XHCI_DEFAULT_BESL; | 4153 | return 0; |
4293 | if (xhci_check_usb2_port_capability(xhci, portnum, | 4154 | |
4294 | XHCI_BLC)) | 4155 | if (xhci->hw_lpm_support == 1 && |
4295 | udev->usb2_hw_lpm_besl_capable = 1; | 4156 | xhci_check_usb2_port_capability( |
4296 | ret = xhci_set_usb2_hardware_lpm(hcd, udev, 1); | 4157 | xhci, portnum, XHCI_HLC)) { |
4297 | if (!ret) | 4158 | udev->usb2_hw_lpm_capable = 1; |
4298 | udev->usb2_hw_lpm_enabled = 1; | 4159 | udev->l1_params.timeout = XHCI_L1_TIMEOUT; |
4299 | } | 4160 | udev->l1_params.besl = XHCI_DEFAULT_BESL; |
4161 | if (xhci_check_usb2_port_capability(xhci, portnum, | ||
4162 | XHCI_BLC)) | ||
4163 | udev->usb2_hw_lpm_besl_capable = 1; | ||
4300 | } | 4164 | } |
4301 | 4165 | ||
4302 | return 0; | 4166 | return 0; |