• Lukas Wunner's avatar
    genirq: Synchronize only with single thread on free_irq() · 519cc865
    Lukas Wunner authored
    When pciehp is converted to threaded IRQ handling, removal of unplugged
    devices below a PCIe hotplug port happens synchronously in the IRQ thread.
    Removal of devices typically entails a call to free_irq() by their drivers.
    
    If those devices share their IRQ with the hotplug port, __free_irq()
    deadlocks because it calls synchronize_irq() to wait for all hard IRQ
    handlers as well as all threads sharing the IRQ to finish.
    
    Actually it's sufficient to wait only for the IRQ thread of the removed
    device, so call synchronize_hardirq() to wait for all hard IRQ handlers to
    finish, but no longer for any threads.  Compensate by rearranging the
    control flow in irq_wait_for_interrupt() such that the device's thread is
    allowed to run one last time after kthread_stop() has been called.
    
    kthread_stop() blocks until the IRQ thread has completed.  On completion
    the IRQ thread clears its oneshot thread_mask bit.  This is safe because
    __free_irq() holds the request_mutex, thereby preventing __setup_irq() from
    handing out the same oneshot thread_mask bit to a newly requested action.
    
    Stack trace for posterity:
        INFO: task irq/17-pciehp:94 blocked for more than 120 seconds.
        schedule+0x28/0x80
        synchronize_irq+0x6e/0xa0
        __free_irq+0x15a/0x2b0
        free_irq+0x33/0x70
        pciehp_release_ctrl+0x98/0xb0
        pcie_port_remove_service+0x2f/0x40
        device_release_driver_internal+0x157/0x220
        bus_remove_device+0xe2/0x150
        device_del+0x124/0x340
        device_unregister+0x16/0x60
        remove_iter+0x1a/0x20
        device_for_each_child+0x4b/0x90
        pcie_port_device_remove+0x1e/0x30
        pci_device_remove+0x36/0xb0
        device_release_driver_internal+0x157/0x220
        pci_stop_bus_device+0x7d/0xa0
        pci_stop_bus_device+0x3d/0xa0
        pci_stop_and_remove_bus_device+0xe/0x20
        pciehp_unconfigure_device+0xb8/0x160
        pciehp_disable_slot+0x84/0x130
        pciehp_ist+0x158/0x190
        irq_thread_fn+0x1b/0x50
        irq_thread+0x143/0x1a0
        kthread+0x111/0x130
    Signed-off-by: default avatarLukas Wunner <lukas@wunner.de>
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Cc: Bjorn Helgaas <bhelgaas@google.com>
    Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
    Cc: linux-pci@vger.kernel.org
    Link: https://lkml.kernel.org/r/d72b41309f077c8d3bee6cc08ad3662d50b5d22a.1529828292.git.lukas@wunner.de
    519cc865
manage.c 59 KB