If there is a pending work, we just need to add the new dr into
the dr_list.

This is suggested by Michael Kelley.

Signed-off-by: Dexuan Cui <de...@microsoft.com>
Cc: Vitaly Kuznetsov <vkuzn...@redhat.com>
Cc: Jack Morgenstein <ja...@mellanox.com>
Cc: sta...@vger.kernel.org
Cc: Stephen Hemminger <sthem...@microsoft.com>
Cc: K. Y. Srinivasan <k...@microsoft.com>
Cc: Michael Kelley (EOSG) <michael.h.kel...@microsoft.com>
---
 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 3a385212f666..d3aa6736a9bb 100644
--- a/drivers/pci/host/pci-hyperv.c
+++ b/drivers/pci/host/pci-hyperv.c
@@ -1733,6 +1733,7 @@ static void hv_pci_devices_present(struct 
hv_pcibus_device *hbus,
        struct hv_dr_state *dr;
        struct hv_dr_work *dr_wrk;
        unsigned long flags;
+       bool pending_dr;
 
        dr_wrk = kzalloc(sizeof(*dr_wrk), GFP_NOWAIT);
        if (!dr_wrk)
@@ -1756,11 +1757,23 @@ static void hv_pci_devices_present(struct 
hv_pcibus_device *hbus,
        }
 
        spin_lock_irqsave(&hbus->device_list_lock, flags);
+
+       /*
+        * If pending_dr is true, we have already queued a work,
+        * which will see the new dr. Otherwise, we need to
+        * queue a new work.
+        */
+       pending_dr = !list_empty(&hbus->dr_list);
        list_add_tail(&dr->list_entry, &hbus->dr_list);
-       spin_unlock_irqrestore(&hbus->device_list_lock, flags);
 
-       get_hvpcibus(hbus);
-       queue_work(hbus->wq, &dr_wrk->wrk);
+       if (pending_dr) {
+               kfree(dr_wrk);
+       } else {
+               get_hvpcibus(hbus);
+               queue_work(hbus->wq, &dr_wrk->wrk);
+       }
+
+       spin_unlock_irqrestore(&hbus->device_list_lock, flags);
 }
 
 /**
-- 
2.7.4

Reply via email to