diff options
author | Chris Bainbridge <chris.bainbridge@gmail.com> | 2015-05-19 09:30:51 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-05-24 12:23:28 -0400 |
commit | a00918d0521df1c7a2ec9143142a3ea998c8526d (patch) | |
tree | a1a467fb29397ac72250da249b3db1ff21a85ac4 /drivers/usb/host/xhci.c | |
parent | b04c846ceaad42f9e37f3626c7e8f457603863f0 (diff) |
usb: host: xhci: add mutex for non-thread-safe data
Regression in commit 638139eb95d2 ("usb: hub: allow to process more usb
hub events in parallel")
The regression resulted in intermittent failure to initialise a 10-port
hub (with three internal VL812 4-port hub controllers) on boot, with a
failure rate of around 8%, due to multiple race conditions when
accessing addr_dev and slot_id in struct xhci_hcd.
This regression also exposed a problem with xhci_setup_device, which
"should be protected by the usb_address0_mutex" but no longer is due to
commit 6fecd4f2a58c ("USB: separate usb_address0 mutexes for each bus")
With separate buses (and locks) it is no longer the case that a single
lock will protect xhci_setup_device from accesses by two parallel
threads processing events on the two buses.
Fix this by adding a mutex to protect addr_dev and slot_id in struct
xhci_hcd, and by making the assignment of slot_id atomic.
Fixes multiple boot errors:
[ 0.583008] xhci_hcd 0000:00:14.0: Bad Slot ID 2
[ 0.583009] xhci_hcd 0000:00:14.0: Could not allocate xHCI USB device data structures
[ 0.583012] usb usb1-port3: couldn't allocate usb_device
And:
[ 0.637409] xhci_hcd 0000:00:14.0: Error while assigning device slot ID
[ 0.637417] xhci_hcd 0000:00:14.0: Max number of devices this xHCI host supports is 32.
[ 0.637421] usb usb1-port1: couldn't allocate usb_device
And:
[ 0.753372] xhci_hcd 0000:00:14.0: ERROR: unexpected setup context command completion code 0x0.
[ 0.753373] usb 1-3: hub failed to enable device, error -22
[ 0.753400] xhci_hcd 0000:00:14.0: Error while assigning device slot ID
[ 0.753402] xhci_hcd 0000:00:14.0: Max number of devices this xHCI host supports is 32.
[ 0.753403] usb usb1-port3: couldn't allocate usb_device
And:
[ 11.018386] usb 1-3: device descriptor read/all, error -110
And:
[ 5.753838] xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command
Tested with 200 reboots, resulting in no USB hub init related errors.
Fixes: 638139eb95d2 ("usb: hub: allow to process more usb hub events in parallel")
Link: https://lkml.kernel.org/g/CAP-bSRb=A0iEYobdGCLpwynS7pkxpt_9ZnwyZTPVAoy0Y=Zo3Q@mail.gmail.com
Signed-off-by: Chris Bainbridge <chris.bainbridge@gmail.com>
Cc: <stable@vger.kernel.org> # 3.18+
[changed git commit description style for checkpatch -Mathias]
Signed-off-by: Mathias Nyman <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.c | 49 |
1 files changed, 30 insertions, 19 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 4299cbf47793..36bf089b708f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
@@ -3682,18 +3682,21 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) | |||
3682 | { | 3682 | { |
3683 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 3683 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
3684 | unsigned long flags; | 3684 | unsigned long flags; |
3685 | int ret; | 3685 | int ret, slot_id; |
3686 | struct xhci_command *command; | 3686 | struct xhci_command *command; |
3687 | 3687 | ||
3688 | command = xhci_alloc_command(xhci, false, false, GFP_KERNEL); | 3688 | command = xhci_alloc_command(xhci, false, false, GFP_KERNEL); |
3689 | if (!command) | 3689 | if (!command) |
3690 | return 0; | 3690 | return 0; |
3691 | 3691 | ||
3692 | /* xhci->slot_id and xhci->addr_dev are not thread-safe */ | ||
3693 | mutex_lock(&xhci->mutex); | ||
3692 | spin_lock_irqsave(&xhci->lock, flags); | 3694 | spin_lock_irqsave(&xhci->lock, flags); |
3693 | command->completion = &xhci->addr_dev; | 3695 | command->completion = &xhci->addr_dev; |
3694 | ret = xhci_queue_slot_control(xhci, command, TRB_ENABLE_SLOT, 0); | 3696 | ret = xhci_queue_slot_control(xhci, command, TRB_ENABLE_SLOT, 0); |
3695 | if (ret) { | 3697 | if (ret) { |
3696 | spin_unlock_irqrestore(&xhci->lock, flags); | 3698 | spin_unlock_irqrestore(&xhci->lock, flags); |
3699 | mutex_unlock(&xhci->mutex); | ||
3697 | xhci_dbg(xhci, "FIXME: allocate a command ring segment\n"); | 3700 | xhci_dbg(xhci, "FIXME: allocate a command ring segment\n"); |
3698 | kfree(command); | 3701 | kfree(command); |
3699 | return 0; | 3702 | return 0; |
@@ -3702,8 +3705,10 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) | |||
3702 | spin_unlock_irqrestore(&xhci->lock, flags); | 3705 | spin_unlock_irqrestore(&xhci->lock, flags); |
3703 | 3706 | ||
3704 | wait_for_completion(command->completion); | 3707 | wait_for_completion(command->completion); |
3708 | slot_id = xhci->slot_id; | ||
3709 | mutex_unlock(&xhci->mutex); | ||
3705 | 3710 | ||
3706 | if (!xhci->slot_id || command->status != COMP_SUCCESS) { | 3711 | if (!slot_id || command->status != COMP_SUCCESS) { |
3707 | xhci_err(xhci, "Error while assigning device slot ID\n"); | 3712 | xhci_err(xhci, "Error while assigning device slot ID\n"); |
3708 | xhci_err(xhci, "Max number of devices this xHCI host supports is %u.\n", | 3713 | xhci_err(xhci, "Max number of devices this xHCI host supports is %u.\n", |
3709 | HCS_MAX_SLOTS( | 3714 | HCS_MAX_SLOTS( |
@@ -3728,11 +3733,11 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) | |||
3728 | * xhci_discover_or_reset_device(), which may be called as part of | 3733 | * xhci_discover_or_reset_device(), which may be called as part of |
3729 | * mass storage driver error handling. | 3734 | * mass storage driver error handling. |
3730 | */ | 3735 | */ |
3731 | if (!xhci_alloc_virt_device(xhci, xhci->slot_id, udev, GFP_NOIO)) { | 3736 | if (!xhci_alloc_virt_device(xhci, slot_id, udev, GFP_NOIO)) { |
3732 | xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n"); | 3737 | xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n"); |
3733 | goto disable_slot; | 3738 | goto disable_slot; |
3734 | } | 3739 | } |
3735 | udev->slot_id = xhci->slot_id; | 3740 | udev->slot_id = slot_id; |
3736 | 3741 | ||
3737 | #ifndef CONFIG_USB_DEFAULT_PERSIST | 3742 | #ifndef CONFIG_USB_DEFAULT_PERSIST |
3738 | /* | 3743 | /* |
@@ -3778,12 +3783,15 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, | |||
3778 | struct xhci_slot_ctx *slot_ctx; | 3783 | struct xhci_slot_ctx *slot_ctx; |
3779 | struct xhci_input_control_ctx *ctrl_ctx; | 3784 | struct xhci_input_control_ctx *ctrl_ctx; |
3780 | u64 temp_64; | 3785 | u64 temp_64; |
3781 | struct xhci_command *command; | 3786 | struct xhci_command *command = NULL; |
3787 | |||
3788 | mutex_lock(&xhci->mutex); | ||
3782 | 3789 | ||
3783 | if (!udev->slot_id) { | 3790 | if (!udev->slot_id) { |
3784 | xhci_dbg_trace(xhci, trace_xhci_dbg_address, | 3791 | xhci_dbg_trace(xhci, trace_xhci_dbg_address, |
3785 | "Bad Slot ID %d", udev->slot_id); | 3792 | "Bad Slot ID %d", udev->slot_id); |
3786 | return -EINVAL; | 3793 | ret = -EINVAL; |
3794 | goto out; | ||
3787 | } | 3795 | } |
3788 | 3796 | ||
3789 | virt_dev = xhci->devs[udev->slot_id]; | 3797 | virt_dev = xhci->devs[udev->slot_id]; |
@@ -3796,7 +3804,8 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, | |||
3796 | */ | 3804 | */ |
3797 | xhci_warn(xhci, "Virt dev invalid for slot_id 0x%x!\n", | 3805 | xhci_warn(xhci, "Virt dev invalid for slot_id 0x%x!\n", |
3798 | udev->slot_id); | 3806 | udev->slot_id); |
3799 | return -EINVAL; | 3807 | ret = -EINVAL; |
3808 | goto out; | ||
3800 | } | 3809 | } |
3801 | 3810 | ||
3802 | if (setup == SETUP_CONTEXT_ONLY) { | 3811 | if (setup == SETUP_CONTEXT_ONLY) { |
@@ -3804,13 +3813,15 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, | |||
3804 | if (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state)) == | 3813 | if (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state)) == |
3805 | SLOT_STATE_DEFAULT) { | 3814 | SLOT_STATE_DEFAULT) { |
3806 | xhci_dbg(xhci, "Slot already in default state\n"); | 3815 | xhci_dbg(xhci, "Slot already in default state\n"); |
3807 | return 0; | 3816 | goto out; |
3808 | } | 3817 | } |
3809 | } | 3818 | } |
3810 | 3819 | ||
3811 | command = xhci_alloc_command(xhci, false, false, GFP_KERNEL); | 3820 | command = xhci_alloc_command(xhci, false, false, GFP_KERNEL); |
3812 | if (!command) | 3821 | if (!command) { |
3813 | return -ENOMEM; | 3822 | ret = -ENOMEM; |
3823 | goto out; | ||
3824 | } | ||
3814 | 3825 | ||
3815 | command->in_ctx = virt_dev->in_ctx; | 3826 | command->in_ctx = virt_dev->in_ctx; |
3816 | command->completion = &xhci->addr_dev; | 3827 | command->completion = &xhci->addr_dev; |
@@ -3820,8 +3831,8 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, | |||
3820 | if (!ctrl_ctx) { | 3831 | if (!ctrl_ctx) { |
3821 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", | 3832 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", |
3822 | __func__); | 3833 | __func__); |
3823 | kfree(command); | 3834 | ret = -EINVAL; |
3824 | return -EINVAL; | 3835 | goto out; |
3825 | } | 3836 | } |
3826 | /* | 3837 | /* |
3827 | * If this is the first Set Address since device plug-in or | 3838 | * If this is the first Set Address since device plug-in or |
@@ -3848,8 +3859,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, | |||
3848 | spin_unlock_irqrestore(&xhci->lock, flags); | 3859 | spin_unlock_irqrestore(&xhci->lock, flags); |
3849 | xhci_dbg_trace(xhci, trace_xhci_dbg_address, | 3860 | xhci_dbg_trace(xhci, trace_xhci_dbg_address, |
3850 | "FIXME: allocate a command ring segment"); | 3861 | "FIXME: allocate a command ring segment"); |
3851 | kfree(command); | 3862 | goto out; |
3852 | return ret; | ||
3853 | } | 3863 | } |
3854 | xhci_ring_cmd_db(xhci); | 3864 | xhci_ring_cmd_db(xhci); |
3855 | spin_unlock_irqrestore(&xhci->lock, flags); | 3865 | spin_unlock_irqrestore(&xhci->lock, flags); |
@@ -3896,10 +3906,8 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, | |||
3896 | ret = -EINVAL; | 3906 | ret = -EINVAL; |
3897 | break; | 3907 | break; |
3898 | } | 3908 | } |
3899 | if (ret) { | 3909 | if (ret) |
3900 | kfree(command); | 3910 | goto out; |
3901 | return ret; | ||
3902 | } | ||
3903 | temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); | 3911 | temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); |
3904 | xhci_dbg_trace(xhci, trace_xhci_dbg_address, | 3912 | xhci_dbg_trace(xhci, trace_xhci_dbg_address, |
3905 | "Op regs DCBAA ptr = %#016llx", temp_64); | 3913 | "Op regs DCBAA ptr = %#016llx", temp_64); |
@@ -3932,8 +3940,10 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, | |||
3932 | xhci_dbg_trace(xhci, trace_xhci_dbg_address, | 3940 | xhci_dbg_trace(xhci, trace_xhci_dbg_address, |
3933 | "Internal device address = %d", | 3941 | "Internal device address = %d", |
3934 | le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK); | 3942 | le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK); |
3943 | out: | ||
3944 | mutex_unlock(&xhci->mutex); | ||
3935 | kfree(command); | 3945 | kfree(command); |
3936 | return 0; | 3946 | return ret; |
3937 | } | 3947 | } |
3938 | 3948 | ||
3939 | int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) | 3949 | int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) |
@@ -4855,6 +4865,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) | |||
4855 | return 0; | 4865 | return 0; |
4856 | } | 4866 | } |
4857 | 4867 | ||
4868 | mutex_init(&xhci->mutex); | ||
4858 | xhci->cap_regs = hcd->regs; | 4869 | xhci->cap_regs = hcd->regs; |
4859 | xhci->op_regs = hcd->regs + | 4870 | xhci->op_regs = hcd->regs + |
4860 | HC_LENGTH(readl(&xhci->cap_regs->hc_capbase)); | 4871 | HC_LENGTH(readl(&xhci->cap_regs->hc_capbase)); |