From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757141AbcBDTrz (ORCPT ); Thu, 4 Feb 2016 14:47:55 -0500 Received: from mail-wm0-f49.google.com ([74.125.82.49]:37551 "EHLO mail-wm0-f49.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751503AbcBDTrx (ORCPT ); Thu, 4 Feb 2016 14:47:53 -0500 From: Chris Bainbridge To: mathias.nyman@linux.intel.com Cc: Chris Bainbridge , johan@kernel.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, stern@rowland.harvard.edu Subject: [PATCH] usb: host: xhci: Replace bus lock with host controller lock Date: Thu, 4 Feb 2016 19:46:29 +0000 Message-Id: <1454615189-6862-1-git-send-email-chris.bainbridge@gmail.com> X-Mailer: git-send-email 2.1.4 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The XHCI controller presents two USB buses to the system - one for USB 2 and one for USB 3. When only one bus is locked there is a race condition during hub init that results in errors like: [ 13.183701] usb 3-3: device descriptor read/all, error -110 On a test system this error occurred on 6% of boots. Fix this by locking the bus controller instead of the bus, thus preventing simultaneous hub init on both buses. Fixes: 638139eb95d2 ("usb: hub: allow to process more usb hub events in parallel") Signed-off-by: Chris Bainbridge --- drivers/usb/core/hcd.c | 2 +- drivers/usb/core/hub.c | 8 ++++---- include/linux/usb.h | 3 +-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index df0e3b92533a..c468d047ec5e 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -966,7 +966,7 @@ static void usb_bus_init (struct usb_bus *bus) bus->bandwidth_allocated = 0; bus->bandwidth_int_reqs = 0; bus->bandwidth_isoc_reqs = 0; - mutex_init(&bus->usb_address0_mutex); + mutex_init(&bus->devnum_next_mutex); INIT_LIST_HEAD (&bus->bus_list); } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 350dcd9af5d8..e03c2f05c2f6 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2066,7 +2066,7 @@ static void choose_devnum(struct usb_device *udev) struct usb_bus *bus = udev->bus; /* be safe when more hub events are proceed in parallel */ - mutex_lock(&bus->usb_address0_mutex); + mutex_lock(&bus->devnum_next_mutex); if (udev->wusb) { devnum = udev->portnum + 1; BUG_ON(test_bit(devnum, bus->devmap.devicemap)); @@ -2084,7 +2084,7 @@ static void choose_devnum(struct usb_device *udev) set_bit(devnum, bus->devmap.devicemap); udev->devnum = devnum; } - mutex_unlock(&bus->usb_address0_mutex); + mutex_unlock(&bus->devnum_next_mutex); } static void release_devnum(struct usb_device *udev) @@ -4312,7 +4312,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, if (oldspeed == USB_SPEED_LOW) delay = HUB_LONG_RESET_TIME; - mutex_lock(&hdev->bus->usb_address0_mutex); + mutex_lock(&hdev->bus->controller->mutex); /* Reset the device; full speed may morph to high speed */ /* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */ @@ -4588,7 +4588,7 @@ fail: hub_port_disable(hub, port1, 0); update_devnum(udev, devnum); /* for disconnect processing */ } - mutex_unlock(&hdev->bus->usb_address0_mutex); + mutex_unlock(&hdev->bus->controller->mutex); return retval; } diff --git a/include/linux/usb.h b/include/linux/usb.h index 89533ba38691..6b736c82b9d1 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -371,14 +371,13 @@ struct usb_bus { int devnum_next; /* Next open device number in * round-robin allocation */ + struct mutex devnum_next_mutex; /* devnum_next mutex */ struct usb_devmap devmap; /* device address allocation map */ struct usb_device *root_hub; /* Root hub */ struct usb_bus *hs_companion; /* Companion EHCI bus, if any */ struct list_head bus_list; /* list of busses */ - struct mutex usb_address0_mutex; /* unaddressed device mutex */ - int bandwidth_allocated; /* on this bus: how much of the time * reserved for periodic (intr/iso) * requests is used, on average? -- 2.1.4