summaryrefslogtreecommitdiff
path: root/drivers/usb/host/xhci.c
diff options
context:
space:
mode:
authorMathias Nyman <mathias.nyman@linux.intel.com>2022-02-16 12:51:50 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-02-17 18:20:45 +0300
commit5c2a380a5aa8c15985359904b6d47466528d2993 (patch)
treef156ab04f51cd44f6090e9a724fbec8d14e0b02d /drivers/usb/host/xhci.c
parente1ec140f273e1e30cea7e6d5f50934d877232121 (diff)
downloadlinux-5c2a380a5aa8c15985359904b6d47466528d2993.tar.xz
xhci: Allocate separate command structures for each LPM command
Every lpm commmand, both for USB 2 and USB 3 devies used the same xhci->lpm_command structure to change max exit latency. xhci->lpm_command is only protected by a hcd->bandwidth mutex, which is not enoungh as USB 2 and USB 3 devices are behind separate HCDs. Simplify code and avoid unnecessary locking risks by allocating separate command structures for each lpm command, just like with all other commands. Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Link: https://lore.kernel.org/r/20220216095153.1303105-7-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/xhci.c')
-rw-r--r--drivers/usb/host/xhci.c21
1 files changed, 8 insertions, 13 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 17a561abfab7..2a58677d9b7a 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -4344,6 +4344,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];
@@ -4360,10 +4364,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;
@@ -4390,6 +4394,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;
}
@@ -4510,18 +4517,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);
@@ -4549,9 +4546,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);