xhci: Don't create stream debugfs files with spinlock held.
authorMathias Nyman <mathias.nyman@linux.intel.com>
Wed, 28 Oct 2020 20:31:24 +0000 (22:31 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 Oct 2020 07:29:21 +0000 (08:29 +0100)
Creating debugfs files while loding the spin_lock_irqsave(xhci->lock)
creates a lock dependecy that could possibly deadlock.

Lockdep warns:

=====================================================
WARNING: HARDIRQ-safe -> HARDIRQ-unsafe lock order detected
5.10.0-rc1pdx86+ #8 Not tainted
-----------------------------------------------------
systemd-udevd/386 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire:
ffffffffb1a94038 (pin_fs_lock){+.+.}-{2:2}, at: simple_pin_fs+0x22/0xa0

and this task is already holding:
ffff9e7b87fbc430 (&xhci->lock){-.-.}-{2:2}, at: xhci_alloc_streams+0x5f9/0x810
which would create a new lock dependency:
(&xhci->lock){-.-.}-{2:2} -> (pin_fs_lock){+.+.}-{2:2}

Create the files a bit later after lock is released.

Fixes: 673d74683627 ("usb: xhci: add debugfs support for ep with stream")
CC: Li Jun <jun.li@nxp.com>
Reported-by: Hans de Goede <hdegoede@redhat.com>
Reported-by: Mike Galbraith <efault@gmx.de>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20201028203124.375344-4-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci.c

index 482fe8c..d4a8d0e 100644 (file)
@@ -3533,11 +3533,14 @@ static int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
                xhci_dbg(xhci, "Slot %u ep ctx %u now has streams.\n",
                         udev->slot_id, ep_index);
                vdev->eps[ep_index].ep_state |= EP_HAS_STREAMS;
-               xhci_debugfs_create_stream_files(xhci, vdev, ep_index);
        }
        xhci_free_command(xhci, config_cmd);
        spin_unlock_irqrestore(&xhci->lock, flags);
 
+       for (i = 0; i < num_eps; i++) {
+               ep_index = xhci_get_endpoint_index(&eps[i]->desc);
+               xhci_debugfs_create_stream_files(xhci, vdev, ep_index);
+       }
        /* Subtract 1 for stream 0, which drivers can't use */
        return num_streams - 1;