Use PCI hotplug lock to globally serialize hotplug operations triggered by PCI hotplug sysfs interfaces. Signed-off-by: Jiang Liu <jiang.liu@xxxxxxxxxx> --- drivers/pci/hotplug/pci_hotplug_core.c | 18 ++++++++++++++++-- 1 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 1572665..9bbbe3e 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -39,6 +39,7 @@ #include <linux/mutex.h> #include <linux/pci.h> #include <linux/pci_hotplug.h> +#include <linux/delay.h> #include <asm/uaccess.h> #include "../pci.h" @@ -121,6 +122,17 @@ static ssize_t power_write_file(struct pci_slot *pci_slot, const char *buf, retval = -ENODEV; goto exit; } + + /* Avoid deadlock with pci_hp_deregister() */ + while (!pci_hotplug_try_enter()) { + /* Check whether the slot has been deregistered. */ + if (list_empty(&slot->slot_list)) { + retval = -ENODEV; + goto exit_put; + } + msleep(1); + } + switch (power) { case 0: if (slot->ops->disable_slot) @@ -136,8 +148,10 @@ static ssize_t power_write_file(struct pci_slot *pci_slot, const char *buf, err ("Illegal value specified for power\n"); retval = -EINVAL; } - module_put(slot->ops->owner); + pci_hotplug_exit(); +exit_put: + module_put(slot->ops->owner); exit: if (retval) return retval; @@ -500,7 +514,7 @@ int pci_hp_deregister(struct hotplug_slot *hotplug) return -ENODEV; } - list_del(&hotplug->slot_list); + list_del_init(&hotplug->slot_list); slot = hotplug->pci_slot; fs_remove_slot(slot); -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html