From 8f7e505394e41e6069164a3d37e3232dcf3a871c Mon Sep 17 00:00:00 2001 From: Xiongfeng Wang <wangxiongfeng2@huawei.com> Date: Wed, 17 Jul 2019 18:44:41 +0800 Subject: [PATCH] pciehp: do not wake up irq_thread for sysfs operation hulk inclusion category: bugfix bugzilla: NA CVE: NA ------------------- This patch fix the same issue as commit cdda3bbfd0ca ("pciehp: use completion to wait irq_thread 'pciehp_ist'"). But the previous patch didn't fix the issue completely. This patch power off the slot directly instead of waking up the irq_thread 'pciehp_ist' This patch also check 'slot_being_removed_rescanned' before powering off the slot to avoid the dead lock issue similar as commit 764cafd9875e ("pciehp: fix a race between pciehp and removing operations by sysfs") Signed-off-by: Xiongfeng Wang <wangxiongfeng2@huawei.com> Reviewed-by: Yao Hongbo <yaohongbo@huawei.com> Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> --- drivers/pci/hotplug/pciehp_ctrl.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index b6274e58f95d..5c26328da66c 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -392,6 +392,7 @@ static int pciehp_disable_slot(struct slot *slot, bool safe_removal) int pciehp_sysfs_enable_slot(struct slot *p_slot) { struct controller *ctrl = p_slot->ctrl; + struct pci_dev *pdev = ctrl->pcie->port; mutex_lock(&p_slot->lock); switch (p_slot->state) { @@ -403,9 +404,12 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot) * card before the thread wakes up, so initialize to -ENODEV. */ ctrl->request_result = -ENODEV; - pciehp_request(ctrl, PCI_EXP_SLTSTA_PDC); - wait_event(ctrl->requester, - !atomic_read(&ctrl->pending_events)); + pci_config_pm_runtime_get(pdev); + down_read(&ctrl->reset_lock); + pciehp_handle_presence_or_link_change(p_slot, + PCI_EXP_SLTSTA_PDC); + up_read(&ctrl->reset_lock); + pci_config_pm_runtime_put(pdev); return ctrl->request_result; case POWERON_STATE: ctrl_info(ctrl, "Slot(%s): Already in powering on state\n", @@ -430,15 +434,25 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot) int pciehp_sysfs_disable_slot(struct slot *p_slot) { struct controller *ctrl = p_slot->ctrl; + struct pci_dev *pdev = ctrl->pcie->port; + + if (test_and_set_bit(0, &slot_being_removed_rescanned)) { + ctrl_info(ctrl, "Slot(%s): Slot is being removed or rescanned, please try later!\n", + slot_name(p_slot)); + return -EINVAL; + } mutex_lock(&p_slot->lock); switch (p_slot->state) { case BLINKINGOFF_STATE: case ON_STATE: mutex_unlock(&p_slot->lock); - pciehp_request(ctrl, DISABLE_SLOT); - wait_event(ctrl->requester, - !atomic_read(&ctrl->pending_events)); + pci_config_pm_runtime_get(pdev); + down_read(&ctrl->reset_lock); + pciehp_handle_disable_request(p_slot); + up_read(&ctrl->reset_lock); + pci_config_pm_runtime_put(pdev); + slot_being_removed_rescanned = 0; return ctrl->request_result; case POWEROFF_STATE: ctrl_info(ctrl, "Slot(%s): Already in powering off state\n", @@ -457,5 +471,7 @@ int pciehp_sysfs_disable_slot(struct slot *p_slot) } mutex_unlock(&p_slot->lock); + slot_being_removed_rescanned = 0; + return -ENODEV; } -- GitLab