From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-sg2apc01on0106.outbound.protection.outlook.com ([104.47.125.106]:49948 "EHLO APC01-SG2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932890AbeCCAUz (ORCPT ); Fri, 2 Mar 2018 19:20:55 -0500 From: Dexuan Cui To: "bhelgaas@google.com" , "linux-pci@vger.kernel.org" , KY Srinivasan , Stephen Hemminger CC: "linux-kernel@vger.kernel.org" , "driverdev-devel@linuxdriverproject.org" , Haiyang Zhang , "olaf@aepfle.de" , "apw@canonical.com" , "jasowang@redhat.com" , "vkuznets@redhat.com" , "marcelo.cerri@canonical.com" , Dexuan Cui , Jack Morgenstein , "stable@vger.kernel.org" Subject: [PATCH 2/3] PCI: hv: serialize the present/eject work items Date: Sat, 3 Mar 2018 00:20:46 +0000 Message-ID: <20180303001947.20564-2-decui@microsoft.com> References: <20180303001947.20564-1-decui@microsoft.com> In-Reply-To: <20180303001947.20564-1-decui@microsoft.com> Content-Language: en-US Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org List-ID: When we hot-remove the device, we first receive a PCI_EJECT message and then receive a PCI_BUS_RELATIONS message with bus_rel->device_count =3D=3D = 0. The first message is offloaded to hv_eject_device_work(), and the second is offloaded to pci_devices_present_work(). Both the paths can be running list_del(&hpdev->list_entry), causing general protection fault, because system_wq can run them concurrently. The patch eliminates the race condition. Signed-off-by: Dexuan Cui Tested-by: Adrian Suhov Tested-by: Chris Valean Cc: Vitaly Kuznetsov Cc: Jack Morgenstein Cc: stable@vger.kernel.org Cc: Stephen Hemminger Cc: K. Y. Srinivasan --- drivers/pci/host/pci-hyperv.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c index 1233300f41c6..57b1fb3ebdb9 100644 --- a/drivers/pci/host/pci-hyperv.c +++ b/drivers/pci/host/pci-hyperv.c @@ -461,6 +461,8 @@ struct hv_pcibus_device { struct retarget_msi_interrupt retarget_msi_interrupt_params; =20 spinlock_t retarget_msi_interrupt_lock; + + struct workqueue_struct *wq; }; =20 /* @@ -1770,7 +1772,7 @@ static void hv_pci_devices_present(struct hv_pcibus_d= evice *hbus, spin_unlock_irqrestore(&hbus->device_list_lock, flags); =20 get_hvpcibus(hbus); - schedule_work(&dr_wrk->wrk); + queue_work(hbus->wq, &dr_wrk->wrk); } =20 /** @@ -1848,7 +1850,7 @@ static void hv_pci_eject_device(struct hv_pci_dev *hp= dev) get_pcichild(hpdev, hv_pcidev_ref_pnp); INIT_WORK(&hpdev->wrk, hv_eject_device_work); get_hvpcibus(hpdev->hbus); - schedule_work(&hpdev->wrk); + queue_work(hpdev->hbus->wq, &hpdev->wrk); } =20 /** @@ -2463,11 +2465,17 @@ static int hv_pci_probe(struct hv_device *hdev, spin_lock_init(&hbus->retarget_msi_interrupt_lock); sema_init(&hbus->enum_sem, 1); init_completion(&hbus->remove_event); + hbus->wq =3D alloc_ordered_workqueue("hv_pci_%x", 0, + hbus->sysdata.domain); + if (!hbus->wq) { + ret =3D -ENOMEM; + goto free_bus; + } =20 ret =3D vmbus_open(hdev->channel, pci_ring_size, pci_ring_size, NULL, 0, hv_pci_onchannelcallback, hbus); if (ret) - goto free_bus; + goto destroy_wq; =20 hv_set_drvdata(hdev, hbus); =20 @@ -2536,6 +2544,9 @@ static int hv_pci_probe(struct hv_device *hdev, hv_free_config_window(hbus); close: vmbus_close(hdev->channel); +destroy_wq: + drain_workqueue(hbus->wq); + destroy_workqueue(hbus->wq); free_bus: free_page((unsigned long)hbus); return ret; @@ -2615,6 +2626,8 @@ static int hv_pci_remove(struct hv_device *hdev) irq_domain_free_fwnode(hbus->sysdata.fwnode); put_hvpcibus(hbus); wait_for_completion(&hbus->remove_event); + drain_workqueue(hbus->wq); + destroy_workqueue(hbus->wq); free_page((unsigned long)hbus); return 0; } --=20 2.7.4