summaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/xhci.c')
-rw-r--r--drivers/usb/host/xhci.c65
1 files changed, 29 insertions, 36 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 2d378543bc3a..642610c78f58 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -65,7 +65,7 @@ static bool td_on_ring(struct xhci_td *td, struct xhci_ring *ring)
* handshake done). There are two failure modes: "usec" have passed (major
* hardware flakeout), or the register reads as all-ones (hardware removed).
*/
-int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec)
+int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, u64 timeout_us)
{
u32 result;
int ret;
@@ -73,7 +73,7 @@ int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec)
ret = readl_poll_timeout_atomic(ptr, result,
(result & mask) == done ||
result == U32_MAX,
- 1, usec);
+ 1, timeout_us);
if (result == U32_MAX) /* card removed */
return -ENODEV;
@@ -110,6 +110,7 @@ void xhci_quiesce(struct xhci_hcd *xhci)
int xhci_halt(struct xhci_hcd *xhci)
{
int ret;
+
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Halt the HC");
xhci_quiesce(xhci);
@@ -119,8 +120,10 @@ int xhci_halt(struct xhci_hcd *xhci)
xhci_warn(xhci, "Host halt failed, %d\n", ret);
return ret;
}
+
xhci->xhc_state |= XHCI_STATE_HALTED;
xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
+
return ret;
}
@@ -162,7 +165,7 @@ int xhci_start(struct xhci_hcd *xhci)
* Transactions will be terminated immediately, and operational registers
* will be set to their defaults.
*/
-int xhci_reset(struct xhci_hcd *xhci)
+int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us)
{
u32 command;
u32 state;
@@ -195,8 +198,7 @@ int xhci_reset(struct xhci_hcd *xhci)
if (xhci->quirks & XHCI_INTEL_HOST)
udelay(1000);
- ret = xhci_handshake(&xhci->op_regs->command,
- CMD_RESET, 0, 10 * 1000 * 1000);
+ ret = xhci_handshake(&xhci->op_regs->command, CMD_RESET, 0, timeout_us);
if (ret)
return ret;
@@ -209,8 +211,7 @@ int xhci_reset(struct xhci_hcd *xhci)
* xHCI cannot write to any doorbells or operational registers other
* than status until the "Controller Not Ready" flag is cleared.
*/
- ret = xhci_handshake(&xhci->op_regs->status,
- STS_CNR, 0, 10 * 1000 * 1000);
+ ret = xhci_handshake(&xhci->op_regs->status, STS_CNR, 0, timeout_us);
xhci->usb2_rhub.bus_state.port_c_suspend = 0;
xhci->usb2_rhub.bus_state.suspended_ports = 0;
@@ -324,7 +325,7 @@ static int xhci_setup_msi(struct xhci_hcd *xhci)
*/
static int xhci_setup_msix(struct xhci_hcd *xhci)
{
- int i, ret = 0;
+ int i, ret;
struct usb_hcd *hcd = xhci_to_hcd(xhci);
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
@@ -578,7 +579,7 @@ static int xhci_all_ports_seen_u0(struct xhci_hcd *xhci)
static int xhci_init(struct usb_hcd *hcd)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
- int retval = 0;
+ int retval;
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "xhci_init");
spin_lock_init(&xhci->lock);
@@ -695,7 +696,7 @@ int xhci_run(struct usb_hcd *hcd)
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"Finished xhci_run for USB2 roothub");
- xhci_dbc_init(xhci);
+ xhci_create_dbc_dev(xhci);
xhci_debugfs_init(xhci);
@@ -725,13 +726,13 @@ static void xhci_stop(struct usb_hcd *hcd)
return;
}
- xhci_dbc_exit(xhci);
+ xhci_remove_dbc_dev(xhci);
spin_lock_irq(&xhci->lock);
xhci->xhc_state |= XHCI_STATE_HALTED;
xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
xhci_halt(xhci);
- xhci_reset(xhci);
+ xhci_reset(xhci, XHCI_RESET_SHORT_USEC);
spin_unlock_irq(&xhci->lock);
xhci_cleanup_msix(xhci);
@@ -784,7 +785,7 @@ void xhci_shutdown(struct usb_hcd *hcd)
xhci_halt(xhci);
/* Workaround for spurious wakeups at shutdown with HSW */
if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
- xhci_reset(xhci);
+ xhci_reset(xhci, XHCI_RESET_SHORT_USEC);
spin_unlock_irq(&xhci->lock);
xhci_cleanup_msix(xhci);
@@ -1170,7 +1171,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
xhci_dbg(xhci, "Stop HCD\n");
xhci_halt(xhci);
xhci_zero_64b_regs(xhci);
- retval = xhci_reset(xhci);
+ retval = xhci_reset(xhci, XHCI_RESET_LONG_USEC);
spin_unlock_irq(&xhci->lock);
if (retval)
return retval;
@@ -3160,8 +3161,6 @@ rescan:
ep_index = xhci_get_endpoint_index(&host_ep->desc);
ep = &vdev->eps[ep_index];
- if (!ep)
- goto done;
/* wait for hub_tt_work to finish clearing hub TT */
if (ep->ep_state & EP_CLEARING_TT) {
@@ -3219,8 +3218,6 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
return;
ep_index = xhci_get_endpoint_index(&host_ep->desc);
ep = &vdev->eps[ep_index];
- if (!ep)
- return;
/* Bail out if toggle is already being cleared by a endpoint reset */
spin_lock_irqsave(&xhci->lock, flags);
@@ -3978,7 +3975,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)
struct xhci_command *command;
unsigned long flags;
u32 state;
- int ret = 0;
+ int ret;
command = xhci_alloc_command(xhci, true, GFP_KERNEL);
if (!command)
@@ -4014,7 +4011,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)
xhci_free_command(xhci, command);
- return ret;
+ return 0;
}
/*
@@ -4354,6 +4351,10 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci,
unsigned long flags;
int ret;
+ command = xhci_alloc_command_with_ctx(xhci, true, GFP_KERNEL);
+ if (!command)
+ return -ENOMEM;
+
spin_lock_irqsave(&xhci->lock, flags);
virt_dev = xhci->devs[udev->slot_id];
@@ -4370,10 +4371,10 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci,
}
/* Attempt to issue an Evaluate Context command to change the MEL. */
- command = xhci->lpm_command;
ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx);
if (!ctrl_ctx) {
spin_unlock_irqrestore(&xhci->lock, flags);
+ xhci_free_command(xhci, command);
xhci_warn(xhci, "%s: Could not get input context, bad type.\n",
__func__);
return -ENOMEM;
@@ -4400,6 +4401,9 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci,
virt_dev->current_mel = max_exit_latency;
spin_unlock_irqrestore(&xhci->lock, flags);
}
+
+ xhci_free_command(xhci, command);
+
return ret;
}
@@ -4520,18 +4524,8 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
exit_latency = xhci_besl_encoding[hird];
spin_unlock_irqrestore(&xhci->lock, flags);
- /* USB 3.0 code dedicate one xhci->lpm_command->in_ctx
- * input context for link powermanagement evaluate
- * context commands. It is protected by hcd->bandwidth
- * mutex and is shared by all devices. We need to set
- * the max ext latency in USB 2 BESL LPM as well, so
- * use the same mutex and xhci_change_max_exit_latency()
- */
- mutex_lock(hcd->bandwidth_mutex);
ret = xhci_change_max_exit_latency(xhci, udev,
exit_latency);
- mutex_unlock(hcd->bandwidth_mutex);
-
if (ret < 0)
return ret;
spin_lock_irqsave(&xhci->lock, flags);
@@ -4559,9 +4553,7 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
readl(pm_addr);
if (udev->usb2_hw_lpm_besl_capable) {
spin_unlock_irqrestore(&xhci->lock, flags);
- mutex_lock(hcd->bandwidth_mutex);
xhci_change_max_exit_latency(xhci, udev, 0);
- mutex_unlock(hcd->bandwidth_mutex);
readl_poll_timeout(ports[port_num]->addr, pm_val,
(pm_val & PORT_PLS_MASK) == XDEV_U0,
100, 10000);
@@ -5290,8 +5282,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
xhci->hcs_params1 = readl(&xhci->cap_regs->hcs_params1);
xhci->hcs_params2 = readl(&xhci->cap_regs->hcs_params2);
xhci->hcs_params3 = readl(&xhci->cap_regs->hcs_params3);
- xhci->hcc_params = readl(&xhci->cap_regs->hc_capbase);
- xhci->hci_version = HC_VERSION(xhci->hcc_params);
+ xhci->hci_version = HC_VERSION(readl(&xhci->cap_regs->hc_capbase));
xhci->hcc_params = readl(&xhci->cap_regs->hcc_params);
if (xhci->hci_version > 0x100)
xhci->hcc_params2 = readl(&xhci->cap_regs->hcc_params2);
@@ -5316,7 +5307,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
xhci_dbg(xhci, "Resetting HCD\n");
/* Reset the internal HC memory state and registers. */
- retval = xhci_reset(xhci);
+ retval = xhci_reset(xhci, XHCI_RESET_LONG_USEC);
if (retval)
return retval;
xhci_dbg(xhci, "Reset complete\n");
@@ -5505,6 +5496,7 @@ static int __init xhci_hcd_init(void)
return -ENODEV;
xhci_debugfs_create_root();
+ xhci_dbc_init();
return 0;
}
@@ -5516,6 +5508,7 @@ static int __init xhci_hcd_init(void)
static void __exit xhci_hcd_fini(void)
{
xhci_debugfs_remove_root();
+ xhci_dbc_exit();
}
module_init(xhci_hcd_init);