Staging: hv: Properly handle errors in hv_pci_probe()
authorK. Y. Srinivasan <kys@microsoft.com>
Fri, 29 Apr 2011 20:45:04 +0000 (13:45 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 3 May 2011 20:31:27 +0000 (13:31 -0700)
Much of the vmbus driver initialization is done within the hv_pci_probe()
function. Properly handle errors in hv_pci_probe so that we can
appropriately deal with loading of the vmbus driver.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/hv/vmbus_drv.c

index 5f88249ece8e02502b7229c69a1c33e39498df49..8663f6459dd8ecf6a9f128590ee3e7cfc489b302 100644 (file)
@@ -54,6 +54,8 @@ EXPORT_SYMBOL(vmbus_loglevel);
        /* (ALL_MODULES << 16 | DEBUG_LVL_ENTEREXIT); */
        /* (((VMBUS | VMBUS_DRV)<<16) | DEBUG_LVL_ENTEREXIT); */
 
+static int pci_probe_error;
+static struct completion probe_event;
 
 static void get_channel_info(struct hv_device *device,
                             struct hv_device_info *info)
@@ -722,19 +724,19 @@ void vmbus_child_device_unregister(struct hv_device *device_obj)
 static int __devinit hv_pci_probe(struct pci_dev *pdev,
                                const struct pci_device_id *ent)
 {
-       int err;
-
        hv_pci_dev = pdev;
 
-       err = pci_enable_device(pdev);
-       if (err)
-               return err;
+       pci_probe_error = pci_enable_device(pdev);
+       if (pci_probe_error)
+               goto probe_cleanup;
 
-       err = vmbus_bus_init(pdev);
-       if (err)
+       pci_probe_error = vmbus_bus_init(pdev);
+       if (pci_probe_error)
                pci_disable_device(pdev);
 
-       return err;
+probe_cleanup:
+       complete(&probe_event);
+       return pci_probe_error;
 }
 
 /*
@@ -757,7 +759,21 @@ static struct pci_driver hv_bus_driver = {
 
 static int __init hv_pci_init(void)
 {
-       return pci_register_driver(&hv_bus_driver);
+       int ret;
+       init_completion(&probe_event);
+       ret = pci_register_driver(&hv_bus_driver);
+       if (ret)
+               return ret;
+       /*
+        * All the vmbus initialization occurs within the
+        * hv_pci_probe() function. Wait for hv_pci_probe()
+        * to complete.
+        */
+       wait_for_completion(&probe_event);
+
+       if (pci_probe_error)
+               pci_unregister_driver(&hv_bus_driver);
+       return pci_probe_error;
 }