From: Greg Kroah-Hartman Date: Wed, 22 Mar 2017 16:07:29 +0000 (+0100) Subject: 4.4-stable patches X-Git-Tag: v4.4.57~14 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=58322ff68b83375a088f82e0d4c46e13ed66c783;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: usb-core-hub-hub_port_init-lock-controller-instead-of-bus.patch usb-don-t-free-bandwidth_mutex-too-early.patch --- diff --git a/queue-4.10/series b/queue-4.10/series new file mode 100644 index 00000000000..e69de29bb2d diff --git a/queue-4.4/series b/queue-4.4/series new file mode 100644 index 00000000000..ff59d1b84c7 --- /dev/null +++ b/queue-4.4/series @@ -0,0 +1,2 @@ +usb-core-hub-hub_port_init-lock-controller-instead-of-bus.patch +usb-don-t-free-bandwidth_mutex-too-early.patch diff --git a/queue-4.4/usb-core-hub-hub_port_init-lock-controller-instead-of-bus.patch b/queue-4.4/usb-core-hub-hub_port_init-lock-controller-instead-of-bus.patch new file mode 100644 index 00000000000..b927baccde5 --- /dev/null +++ b/queue-4.4/usb-core-hub-hub_port_init-lock-controller-instead-of-bus.patch @@ -0,0 +1,216 @@ +From feb26ac31a2a5cb88d86680d9a94916a6343e9e6 Mon Sep 17 00:00:00 2001 +From: Chris Bainbridge +Date: Mon, 25 Apr 2016 13:48:38 +0100 +Subject: usb: core: hub: hub_port_init lock controller instead of bus + +From: Chris Bainbridge + +commit feb26ac31a2a5cb88d86680d9a94916a6343e9e6 upstream. + +The XHCI controller presents two USB buses to the system - one for USB2 +and one for USB3. The hub init code (hub_port_init) is reentrant but +only locks one bus per thread, leading to a race condition failure when +two threads attempt to simultaneously initialise a USB2 and USB3 device: + +[ 8.034843] xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command +[ 13.183701] usb 3-3: device descriptor read/all, error -110 + +On a test system this failure occurred on 6% of all boots. + +The call traces at the point of failure are: + +Call Trace: + [] schedule+0x37/0x90 + [] usb_kill_urb+0x8d/0xd0 + [] ? wake_up_atomic_t+0x30/0x30 + [] usb_start_wait_urb+0xbe/0x150 + [] usb_control_msg+0xbc/0xf0 + [] hub_port_init+0x51e/0xb70 + [] hub_event+0x817/0x1570 + [] process_one_work+0x1ff/0x620 + [] ? process_one_work+0x15f/0x620 + [] worker_thread+0x64/0x4b0 + [] ? rescuer_thread+0x390/0x390 + [] kthread+0x105/0x120 + [] ? kthread_create_on_node+0x200/0x200 + [] ret_from_fork+0x3f/0x70 + [] ? kthread_create_on_node+0x200/0x200 + +Call Trace: + [] xhci_setup_device+0x53d/0xa40 + [] xhci_address_device+0xe/0x10 + [] hub_port_init+0x1bf/0xb70 + [] ? trace_hardirqs_on+0xd/0x10 + [] hub_event+0x817/0x1570 + [] process_one_work+0x1ff/0x620 + [] ? process_one_work+0x15f/0x620 + [] worker_thread+0x64/0x4b0 + [] ? rescuer_thread+0x390/0x390 + [] kthread+0x105/0x120 + [] ? kthread_create_on_node+0x200/0x200 + [] ret_from_fork+0x3f/0x70 + [] ? kthread_create_on_node+0x200/0x200 + +Which results from the two call chains: + +hub_port_init + usb_get_device_descriptor + usb_get_descriptor + usb_control_msg + usb_internal_control_msg + usb_start_wait_urb + usb_submit_urb / wait_for_completion_timeout / usb_kill_urb + +hub_port_init + hub_set_address + xhci_address_device + xhci_setup_device + +Mathias Nyman explains the current behaviour violates the XHCI spec: + + hub_port_reset() will end up moving the corresponding xhci device slot + to default state. + + As hub_port_reset() is called several times in hub_port_init() it + sounds reasonable that we could end up with two threads having their + xhci device slots in default state at the same time, which according to + xhci 4.5.3 specs still is a big no no: + + "Note: Software shall not transition more than one Device Slot to the + Default State at a time" + + So both threads fail at their next task after this. + One fails to read the descriptor, and the other fails addressing the + device. + +Fix this in hub_port_init by locking the USB controller (instead of an +individual bus) to prevent simultaneous initialisation of both buses. + +Fixes: 638139eb95d2 ("usb: hub: allow to process more usb hub events in parallel") +Link: https://lkml.org/lkml/2016/2/8/312 +Link: https://lkml.org/lkml/2016/2/4/748 +Signed-off-by: Chris Bainbridge +Cc: stable +Acked-by: Mathias Nyman +Signed-off-by: Sumit Semwal + [sumits: minor merge conflict resolution for linux-4.4.y] +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/hcd.c | 15 +++++++++++++-- + drivers/usb/core/hub.c | 8 ++++---- + include/linux/usb.h | 3 +-- + include/linux/usb/hcd.h | 1 + + 4 files changed, 19 insertions(+), 8 deletions(-) + +--- 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->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); + } +@@ -2497,6 +2497,14 @@ struct usb_hcd *usb_create_shared_hcd(co + return NULL; + } + if (primary_hcd == NULL) { ++ hcd->address0_mutex = kmalloc(sizeof(*hcd->address0_mutex), ++ GFP_KERNEL); ++ if (!hcd->address0_mutex) { ++ kfree(hcd); ++ dev_dbg(dev, "hcd address0 mutex alloc failed\n"); ++ return NULL; ++ } ++ mutex_init(hcd->address0_mutex); + hcd->bandwidth_mutex = kmalloc(sizeof(*hcd->bandwidth_mutex), + GFP_KERNEL); + if (!hcd->bandwidth_mutex) { +@@ -2508,6 +2516,7 @@ struct usb_hcd *usb_create_shared_hcd(co + dev_set_drvdata(dev, hcd); + } else { + mutex_lock(&usb_port_peer_mutex); ++ hcd->address0_mutex = primary_hcd->address0_mutex; + hcd->bandwidth_mutex = primary_hcd->bandwidth_mutex; + hcd->primary_hcd = primary_hcd; + primary_hcd->primary_hcd = primary_hcd; +@@ -2574,8 +2583,10 @@ static void hcd_release(struct kref *kre + struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref); + + mutex_lock(&usb_port_peer_mutex); +- if (usb_hcd_is_primary_hcd(hcd)) ++ if (usb_hcd_is_primary_hcd(hcd)) { ++ kfree(hcd->address0_mutex); + kfree(hcd->bandwidth_mutex); ++ } + if (hcd->shared_hcd) { + struct usb_hcd *peer = hcd->shared_hcd; + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -1980,7 +1980,7 @@ static void choose_devnum(struct usb_dev + 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)); +@@ -1998,7 +1998,7 @@ static void choose_devnum(struct usb_dev + 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) +@@ -4262,7 +4262,7 @@ hub_port_init(struct usb_hub *hub, struc + if (oldspeed == USB_SPEED_LOW) + delay = HUB_LONG_RESET_TIME; + +- mutex_lock(&hdev->bus->usb_address0_mutex); ++ mutex_lock(hcd->address0_mutex); + + /* Reset the device; full speed may morph to high speed */ + /* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */ +@@ -4548,7 +4548,7 @@ fail: + hub_port_disable(hub, port1, 0); + update_devnum(udev, devnum); /* for disconnect processing */ + } +- mutex_unlock(&hdev->bus->usb_address0_mutex); ++ mutex_unlock(hcd->address0_mutex); + return retval; + } + +--- 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? +--- a/include/linux/usb/hcd.h ++++ b/include/linux/usb/hcd.h +@@ -180,6 +180,7 @@ struct usb_hcd { + * bandwidth_mutex should be dropped after a successful control message + * to the device, or resetting the bandwidth after a failed attempt. + */ ++ struct mutex *address0_mutex; + struct mutex *bandwidth_mutex; + struct usb_hcd *shared_hcd; + struct usb_hcd *primary_hcd; diff --git a/queue-4.4/usb-don-t-free-bandwidth_mutex-too-early.patch b/queue-4.4/usb-don-t-free-bandwidth_mutex-too-early.patch new file mode 100644 index 00000000000..c8c8a9b9947 --- /dev/null +++ b/queue-4.4/usb-don-t-free-bandwidth_mutex-too-early.patch @@ -0,0 +1,124 @@ +From ab2a4bf83902c170d29ba130a8abb5f9d90559e1 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Mon, 27 Jun 2016 10:23:10 -0400 +Subject: USB: don't free bandwidth_mutex too early + +From: Alan Stern + +commit ab2a4bf83902c170d29ba130a8abb5f9d90559e1 upstream. + +The USB core contains a bug that can show up when a USB-3 host +controller is removed. If the primary (USB-2) hcd structure is +released before the shared (USB-3) hcd, the core will try to do a +double-free of the common bandwidth_mutex. + +The problem was described in graphical form by Chung-Geol Kim, who +first reported it: + +================================================= + At *remove USB(3.0) Storage + sequence <1> --> <5> ((Problem Case)) +================================================= + VOLD +------------------------------------|------------ + (uevent) + ________|_________ + |<1> | + |dwc3_otg_sm_work | + |usb_put_hcd | + |peer_hcd(kref=2)| + |__________________| + ________|_________ + |<2> | + |New USB BUS #2 | + | | + |peer_hcd(kref=1) | + | | + --(Link)-bandXX_mutex| + | |__________________| + | + ___________________ | + |<3> | | + |dwc3_otg_sm_work | | + |usb_put_hcd | | + |primary_hcd(kref=1)| | + |___________________| | + _________|_________ | + |<4> | | + |New USB BUS #1 | | + |hcd_release | | + |primary_hcd(kref=0)| | + | | | + |bandXX_mutex(free) |<- + |___________________| + (( VOLD )) + ______|___________ + |<5> | + | SCSI | + |usb_put_hcd | + |peer_hcd(kref=0) | + |*hcd_release | + |bandXX_mutex(free*)|<- double free + |__________________| + +================================================= + +This happens because hcd_release() frees the bandwidth_mutex whenever +it sees a primary hcd being released (which is not a very good idea +in any case), but in the course of releasing the primary hcd, it +changes the pointers in the shared hcd in such a way that the shared +hcd will appear to be primary when it gets released. + +This patch fixes the problem by changing hcd_release() so that it +deallocates the bandwidth_mutex only when the _last_ hcd structure +referencing it is released. The patch also removes an unnecessary +test, so that when an hcd is released, both the shared_hcd and +primary_hcd pointers in the hcd's peer will be cleared. + +Signed-off-by: Alan Stern +Reported-by: Chung-Geol Kim +Tested-by: Chung-Geol Kim +Cc: Sumit Semwal +Signed-off-by: Greg Kroah-Hartman + + +--- + drivers/usb/core/hcd.c | 17 +++++++---------- + 1 file changed, 7 insertions(+), 10 deletions(-) + +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -2573,26 +2573,23 @@ EXPORT_SYMBOL_GPL(usb_create_hcd); + * Don't deallocate the bandwidth_mutex until the last shared usb_hcd is + * deallocated. + * +- * Make sure to only deallocate the bandwidth_mutex when the primary HCD is +- * freed. When hcd_release() is called for either hcd in a peer set +- * invalidate the peer's ->shared_hcd and ->primary_hcd pointers to +- * block new peering attempts ++ * Make sure to deallocate the bandwidth_mutex only when the last HCD is ++ * freed. When hcd_release() is called for either hcd in a peer set, ++ * invalidate the peer's ->shared_hcd and ->primary_hcd pointers. + */ + static void hcd_release(struct kref *kref) + { + struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref); + + mutex_lock(&usb_port_peer_mutex); +- if (usb_hcd_is_primary_hcd(hcd)) { +- kfree(hcd->address0_mutex); +- kfree(hcd->bandwidth_mutex); +- } + if (hcd->shared_hcd) { + struct usb_hcd *peer = hcd->shared_hcd; + + peer->shared_hcd = NULL; +- if (peer->primary_hcd == hcd) +- peer->primary_hcd = NULL; ++ peer->primary_hcd = NULL; ++ } else { ++ kfree(hcd->address0_mutex); ++ kfree(hcd->bandwidth_mutex); + } + mutex_unlock(&usb_port_peer_mutex); + kfree(hcd); diff --git a/queue-4.9/series b/queue-4.9/series new file mode 100644 index 00000000000..f832a55cfb1 --- /dev/null +++ b/queue-4.9/series @@ -0,0 +1,2 @@ +drm-vc4-fix-termination-of-the-initial-scan-for-branch-targets.patch +drm-vc4-use-runtime-autosuspend-to-avoid-thrashing-v3d-power-state.patch