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 <baolu.lu@xxxxxxxxxxxxxxx> --- 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 6afe323..4c27828 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -2536,7 +2536,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 ad06243..e254af7 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3683,20 +3683,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); @@ -3711,7 +3710,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; } @@ -3747,7 +3746,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; @@ -3755,6 +3754,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, @@ -3818,14 +3818,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); @@ -3943,7 +3942,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 f945380..60f254a 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1583,7 +1583,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.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html