RE: [PATCH v4 1/2] PCI: hv: Serialize the present and eject work items

2018-03-15 Thread Dexuan Cui
> From: Dexuan Cui
> > From: Lorenzo Pieralisi 
> > I need to know either what commit you are fixing (ie Fixes: tag - which
> > is preferrable) or you tell me which kernel versions we are targeting
> > for the stable backport.
> > Lorenzo
> 
> Sorry.  Here I was hesitant to add a "Fixes:" because the bug was there the 
> first
> day
> when the driver was introduced.
> 
> Please use
> Fixes: 4daace0d8ce8 ("PCI: hv: Add paravirtual PCI front-end for Microsoft
> Hyper-V VMs")
> or
> Cc:  # v4.6+

BTW, the bug here is a race condtion which couldn't be easily hit in the past,
probably because most of the time only one PCI device was only added into the
VM once. But now it's becoming typical that a VM can have 4 GPU devices so we
start to notice this bug. With 7 Mellanox VFs assigned to a VM, we can easily
reproduce the bug by "hot-remove and hot-add VFs" test:

general protection fault:  [#1] SMP
...
Workqueue: events hv_eject_device_work [pci_hyperv]
task: 8800ed5e5400 ti: 8800ee674000 task.ti: 8800ee674000
RIP: 0010:[]  ... hv_eject_device_work+0xbe/0x160 [pci_hyperv]
...
Call Trace:
 [] ? __schedule+0x3b6/0xa30
 [] process_one_work+0x165/0x480
 [] worker_thread+0x4b/0x4c0
 [] ? process_one_work+0x480/0x480
 [] kthread+0xe5/0x100
 [] ? kthread_create_on_node+0x1e0/0x1e0
 [] ret_from_fork+0x3f/0x70
 [] ? kthread_create_on_node+0x1e0/0x1e0
Code: ...
RIP  [] hv_eject_device_work+0xbe/0x160 [pci_hyperv]
...
BUG: unable to handle kernel paging request at ffd8
IP: [] kthread_data+0x10/0x20
PGD 1e0d067 PUD 1e0f067 PMD 0
Oops:  [#2] SMP
 
Thanks,
-- Dexuan
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


RE: [PATCH v4 1/2] PCI: hv: Serialize the present and eject work items

2018-03-15 Thread Dexuan Cui
> From: Lorenzo Pieralisi 
> Sent: Thursday, March 15, 2018 10:02
> On Thu, Mar 15, 2018 at 02:20:53PM +, Dexuan Cui wrote:
> > 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 ==
> 0.
> >
> > The first message is offloaded to   (), and the second
> > is offloaded to pci_devices_present_work(). Both the paths can be running
> > list_del(>list_entry), causing general protection fault, because
> > system_wq can run them concurrently.
> >
> > The patch eliminates the race condition.
> >
> > Cc: sta...@vger.kernel.org
> 
> I need to know either what commit you are fixing (ie Fixes: tag - which
> is preferrable) or you tell me which kernel versions we are targeting
> for the stable backport.
> 
> Thanks,
> Lorenzo

Sorry.  Here I was hesitant to add a "Fixes:" because the bug was there the 
first day
when the driver was introduced.

Please use
Fixes: 4daace0d8ce8 ("PCI: hv: Add paravirtual PCI front-end for Microsoft 
Hyper-V VMs")
or 
Cc:  # v4.6+

Thanks,
-- Dexuan
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH v4 1/2] PCI: hv: Serialize the present and eject work items

2018-03-15 Thread Lorenzo Pieralisi
On Thu, Mar 15, 2018 at 02:20:53PM +, Dexuan Cui wrote:
> 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 == 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(>list_entry), causing general protection fault, because
> system_wq can run them concurrently.
> 
> The patch eliminates the race condition.
> 
> Tested-by: Adrian Suhov 
> Tested-by: Chris Valean 
> Signed-off-by: Dexuan Cui 
> Reviewed-by: Michael Kelley 
> Acked-by: Haiyang Zhang 
> Cc: sta...@vger.kernel.org

I need to know either what commit you are fixing (ie Fixes: tag - which
is preferrable) or you tell me which kernel versions we are targeting
for the stable backport.

Thanks,
Lorenzo

> Cc: Vitaly Kuznetsov 
> Cc: Jack Morgenstein 
> Cc: Stephen Hemminger 
> Cc: K. Y. Srinivasan 
> ---
>  drivers/pci/host/pci-hyperv.c | 17 ++---
>  1 file changed, 14 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c
> index 2faf38eab785..5e67dff779a7 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;
>  
>   spinlock_t retarget_msi_interrupt_lock;
> +
> + struct workqueue_struct *wq;
>  };
>  
>  /*
> @@ -1770,7 +1772,7 @@ static void hv_pci_devices_present(struct 
> hv_pcibus_device *hbus,
>   spin_unlock_irqrestore(>device_list_lock, flags);
>  
>   get_hvpcibus(hbus);
> - schedule_work(_wrk->wrk);
> + queue_work(hbus->wq, _wrk->wrk);
>  }
>  
>  /**
> @@ -1848,7 +1850,7 @@ static void hv_pci_eject_device(struct hv_pci_dev 
> *hpdev)
>   get_pcichild(hpdev, hv_pcidev_ref_pnp);
>   INIT_WORK(>wrk, hv_eject_device_work);
>   get_hvpcibus(hpdev->hbus);
> - schedule_work(>wrk);
> + queue_work(hpdev->hbus->wq, >wrk);
>  }
>  
>  /**
> @@ -2463,11 +2465,17 @@ static int hv_pci_probe(struct hv_device *hdev,
>   spin_lock_init(>retarget_msi_interrupt_lock);
>   sema_init(>enum_sem, 1);
>   init_completion(>remove_event);
> + hbus->wq = alloc_ordered_workqueue("hv_pci_%x", 0,
> +hbus->sysdata.domain);
> + if (!hbus->wq) {
> + ret = -ENOMEM;
> + goto free_bus;
> + }
>  
>   ret = vmbus_open(hdev->channel, pci_ring_size, pci_ring_size, NULL, 0,
>hv_pci_onchannelcallback, hbus);
>   if (ret)
> - goto free_bus;
> + goto destroy_wq;
>  
>   hv_set_drvdata(hdev, hbus);
>  
> @@ -2536,6 +2544,8 @@ static int hv_pci_probe(struct hv_device *hdev,
>   hv_free_config_window(hbus);
>  close:
>   vmbus_close(hdev->channel);
> +destroy_wq:
> + destroy_workqueue(hbus->wq);
>  free_bus:
>   free_page((unsigned long)hbus);
>   return ret;
> @@ -2615,6 +2625,7 @@ static int hv_pci_remove(struct hv_device *hdev)
>   irq_domain_free_fwnode(hbus->sysdata.fwnode);
>   put_hvpcibus(hbus);
>   wait_for_completion(>remove_event);
> + destroy_workqueue(hbus->wq);
>   free_page((unsigned long)hbus);
>   return 0;
>  }
> -- 
> 2.7.4
> 
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v4 1/2] PCI: hv: Serialize the present and eject work items

2018-03-15 Thread Dexuan Cui
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 == 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(>list_entry), causing general protection fault, because
system_wq can run them concurrently.

The patch eliminates the race condition.

Tested-by: Adrian Suhov 
Tested-by: Chris Valean 
Signed-off-by: Dexuan Cui 
Reviewed-by: Michael Kelley 
Acked-by: Haiyang Zhang 
Cc: sta...@vger.kernel.org
Cc: Vitaly Kuznetsov 
Cc: Jack Morgenstein 
Cc: Stephen Hemminger 
Cc: K. Y. Srinivasan 
---
 drivers/pci/host/pci-hyperv.c | 17 ++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c
index 2faf38eab785..5e67dff779a7 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;
 
spinlock_t retarget_msi_interrupt_lock;
+
+   struct workqueue_struct *wq;
 };
 
 /*
@@ -1770,7 +1772,7 @@ static void hv_pci_devices_present(struct 
hv_pcibus_device *hbus,
spin_unlock_irqrestore(>device_list_lock, flags);
 
get_hvpcibus(hbus);
-   schedule_work(_wrk->wrk);
+   queue_work(hbus->wq, _wrk->wrk);
 }
 
 /**
@@ -1848,7 +1850,7 @@ static void hv_pci_eject_device(struct hv_pci_dev *hpdev)
get_pcichild(hpdev, hv_pcidev_ref_pnp);
INIT_WORK(>wrk, hv_eject_device_work);
get_hvpcibus(hpdev->hbus);
-   schedule_work(>wrk);
+   queue_work(hpdev->hbus->wq, >wrk);
 }
 
 /**
@@ -2463,11 +2465,17 @@ static int hv_pci_probe(struct hv_device *hdev,
spin_lock_init(>retarget_msi_interrupt_lock);
sema_init(>enum_sem, 1);
init_completion(>remove_event);
+   hbus->wq = alloc_ordered_workqueue("hv_pci_%x", 0,
+  hbus->sysdata.domain);
+   if (!hbus->wq) {
+   ret = -ENOMEM;
+   goto free_bus;
+   }
 
ret = vmbus_open(hdev->channel, pci_ring_size, pci_ring_size, NULL, 0,
 hv_pci_onchannelcallback, hbus);
if (ret)
-   goto free_bus;
+   goto destroy_wq;
 
hv_set_drvdata(hdev, hbus);
 
@@ -2536,6 +2544,8 @@ static int hv_pci_probe(struct hv_device *hdev,
hv_free_config_window(hbus);
 close:
vmbus_close(hdev->channel);
+destroy_wq:
+   destroy_workqueue(hbus->wq);
 free_bus:
free_page((unsigned long)hbus);
return ret;
@@ -2615,6 +2625,7 @@ static int hv_pci_remove(struct hv_device *hdev)
irq_domain_free_fwnode(hbus->sysdata.fwnode);
put_hvpcibus(hbus);
wait_for_completion(>remove_event);
+   destroy_workqueue(hbus->wq);
free_page((unsigned long)hbus);
return 0;
 }
-- 
2.7.4

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel