PCI hotplug: ioremap balanced with iounmap
authorAmol Lad <amol@verismonetworks.com>
Thu, 5 Oct 2006 06:37:32 +0000 (12:07 +0530)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 18 Oct 2006 18:36:11 +0000 (11:36 -0700)
1. ioremap must be balanced by an iounmap and failing to do so can
   result in a memory leak.
2. Handle return value correctly

Tested (compilation only) with:
- allmodconfig

Signed-off-by: Amol Lad <amol@verismonetworks.com>
Cc: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/pci/hotplug/shpchp_hpc.c

index bbe450f..83a5226 100644 (file)
@@ -1118,7 +1118,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
 {
        struct php_ctlr_state_s *php_ctlr, *p;
        void *instance_id = ctrl;
-       int rc, num_slots = 0;
+       int rc = -1, num_slots = 0;
        u8 hp_slot;
        u32 shpc_base_offset;
        u32 tempdword, slot_reg, slot_config;
@@ -1184,11 +1184,15 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
        info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, 
                pdev->subsystem_device);
        
-       if (pci_enable_device(pdev))
+       rc = pci_enable_device(pdev);
+       if (rc) {
+               err("%s: pci_enable_device failed\n", __FUNCTION__);
                goto abort_free_ctlr;
+       }
 
        if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) {
                err("%s: cannot reserve MMIO region\n", __FUNCTION__);
+               rc = -1;
                goto abort_free_ctlr;
        }
 
@@ -1197,6 +1201,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
                err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__,
                    ctrl->mmio_size, ctrl->mmio_base);
                release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
+               rc = -1;
                goto abort_free_ctlr;
        }
        dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg);
@@ -1299,8 +1304,10 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
         */
        if (atomic_add_return(1, &shpchp_num_controllers) == 1) {
                shpchp_wq = create_singlethread_workqueue("shpchpd");
-               if (!shpchp_wq)
-                       return -ENOMEM;
+               if (!shpchp_wq) {
+                       rc = -ENOMEM;
+                       goto abort_free_ctlr;
+               }
        }
 
        /*
@@ -1330,8 +1337,10 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
 
        /* We end up here for the many possible ways to fail this API.  */
 abort_free_ctlr:
+       if (php_ctlr->creg)
+               iounmap(php_ctlr->creg);
        kfree(php_ctlr);
 abort:
        DBG_LEAVE_ROUTINE
-       return -1;
+       return rc;
 }