From 87e44f2aac8d45c1e48c94017942fa10037daae0 Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Fri, 11 Nov 2016 15:13:30 +0200 Subject: [PATCH] usb: xhci: remove the use of xhci->addr_dev xhci->addr_dev is used for the completion of both address device and enable slot commands. It's shared by enumerations of all USB devices connected to an xhci host. Hence, it's just a source for possible races. Since we've introduced command structure and the command queue to xhci driver. It is time to get rid of addr_dev and use the completion in the command structure instead. Signed-off-by: Lu Baolu Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 1 - drivers/usb/host/xhci.c | 18 ++++++++++-------- drivers/usb/host/xhci.h | 1 - 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 8102a86f249c..5da765a23fe1 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -2535,7 +2535,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) * something other than the default (~1ms minimum between interrupts). * See section 5.5.1.2. */ - init_completion(&xhci->addr_dev); for (i = 0; i < MAX_HC_SLOTS; ++i) xhci->devs[i] = NULL; for (i = 0; i < USB_MAXCHILDREN; ++i) { diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index ea338e05ae27..63c902a1f02a 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3687,20 +3687,19 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) int ret, slot_id; struct xhci_command *command; - command = xhci_alloc_command(xhci, false, false, GFP_KERNEL); + command = xhci_alloc_command(xhci, false, true, GFP_KERNEL); if (!command) return 0; /* xhci->slot_id and xhci->addr_dev are not thread-safe */ mutex_lock(&xhci->mutex); spin_lock_irqsave(&xhci->lock, flags); - command->completion = &xhci->addr_dev; ret = xhci_queue_slot_control(xhci, command, TRB_ENABLE_SLOT, 0); if (ret) { spin_unlock_irqrestore(&xhci->lock, flags); mutex_unlock(&xhci->mutex); xhci_dbg(xhci, "FIXME: allocate a command ring segment\n"); - kfree(command); + xhci_free_command(xhci, command); return 0; } xhci_ring_cmd_db(xhci); @@ -3715,7 +3714,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) xhci_err(xhci, "Max number of devices this xHCI host supports is %u.\n", HCS_MAX_SLOTS( readl(&xhci->cap_regs->hcs_params1))); - kfree(command); + xhci_free_command(xhci, command); return 0; } @@ -3751,7 +3750,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) #endif - kfree(command); + xhci_free_command(xhci, command); /* Is this a LS or FS device under a HS hub? */ /* Hub or peripherial? */ return 1; @@ -3759,6 +3758,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) disable_slot: /* Disable slot, if we can do it without mem alloc */ spin_lock_irqsave(&xhci->lock, flags); + kfree(command->completion); command->completion = NULL; command->status = 0; if (!xhci_queue_slot_control(xhci, command, TRB_DISABLE_SLOT, @@ -3820,14 +3820,13 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, } } - command = xhci_alloc_command(xhci, false, false, GFP_KERNEL); + command = xhci_alloc_command(xhci, false, true, GFP_KERNEL); if (!command) { ret = -ENOMEM; goto out; } command->in_ctx = virt_dev->in_ctx; - command->completion = &xhci->addr_dev; slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx); ctrl_ctx = xhci_get_input_control_ctx(virt_dev->in_ctx); @@ -3945,7 +3944,10 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK); out: mutex_unlock(&xhci->mutex); - kfree(command); + if (command) { + kfree(command->completion); + kfree(command); + } return ret; } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 2561924c34f2..f24ae0ac12ae 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1584,7 +1584,6 @@ struct xhci_hcd { /* slot enabling and address device helpers */ /* these are not thread safe so use mutex */ struct mutex mutex; - struct completion addr_dev; int slot_id; /* For USB 3.0 LPM enable/disable. */ struct xhci_command *lpm_command; -- 2.20.1