int pciehp_poll_mode;
 int pciehp_poll_time;
 int pciehp_force;
-static int pciehp_slot_with_bus;
+int pciehp_slot_with_bus;
 struct workqueue_struct *pciehp_wq;
 
 #define DRIVER_VERSION "0.4"
  */
 static void release_slot(struct hotplug_slot *hotplug_slot)
 {
-       struct slot *slot = hotplug_slot->private;
-
        dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
 
-       kfree(slot->hotplug_slot->info);
-       kfree(slot->hotplug_slot);
-       kfree(slot);
-}
-
-static void make_slot_name(struct slot *slot)
-{
-       if (pciehp_slot_with_bus)
-               snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
-                        slot->bus, slot->number);
-       else
-               snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d",
-                        slot->number);
+       kfree(hotplug_slot->info);
+       kfree(hotplug_slot);
 }
 
 static int init_slots(struct controller *ctrl)
        struct hotplug_slot *hotplug_slot;
        struct hotplug_slot_info *info;
        int retval = -ENOMEM;
-       int i;
-
-       for (i = 0; i < ctrl->num_slots; i++) {
-               slot = kzalloc(sizeof(*slot), GFP_KERNEL);
-               if (!slot)
-                       goto error;
 
+       list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
                hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
                if (!hotplug_slot)
-                       goto error_slot;
-               slot->hotplug_slot = hotplug_slot;
+                       goto error;
 
                info = kzalloc(sizeof(*info), GFP_KERNEL);
                if (!info)
                        goto error_hpslot;
-               hotplug_slot->info = info;
-
-               hotplug_slot->name = slot->name;
-
-               slot->hp_slot = i;
-               slot->ctrl = ctrl;
-               slot->bus = ctrl->pci_dev->subordinate->number;
-               slot->device = ctrl->slot_device_offset + i;
-               slot->hpc_ops = ctrl->hpc_ops;
-               slot->number = ctrl->first_slot;
-               mutex_init(&slot->lock);
-               INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
 
                /* register this slot with the hotplug pci core */
+               hotplug_slot->info = info;
+               hotplug_slot->name = slot->name;
                hotplug_slot->private = slot;
                hotplug_slot->release = &release_slot;
-               make_slot_name(slot);
                hotplug_slot->ops = &pciehp_hotplug_slot_ops;
-
                get_power_status(hotplug_slot, &info->power_status);
                get_attention_status(hotplug_slot, &info->attention_status);
                get_latch_status(hotplug_slot, &info->latch_status);
                get_adapter_status(hotplug_slot, &info->adapter_status);
+               slot->hotplug_slot = hotplug_slot;
 
                dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
                    "slot_device_offset=%x\n", slot->bus, slot->device,
                                goto error_info;
                        }
                }
-
-               list_add(&slot->slot_list, &ctrl->slot_list);
        }
 
        return 0;
        kfree(info);
 error_hpslot:
        kfree(hotplug_slot);
-error_slot:
-       kfree(slot);
 error:
        return retval;
 }
 
 static void cleanup_slots(struct controller *ctrl)
 {
-       struct list_head *tmp;
-       struct list_head *next;
        struct slot *slot;
 
-       list_for_each_safe(tmp, next, &ctrl->slot_list) {
-               slot = list_entry(tmp, struct slot, slot_list);
-               list_del(&slot->slot_list);
+       list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
                if (EMI(ctrl))
                        sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj,
                                &hotplug_slot_attr_lock.attr);
-               cancel_delayed_work(&slot->work);
-               flush_scheduled_work();
-               flush_workqueue(pciehp_wq);
                pci_hp_deregister(slot->hotplug_slot);
        }
 }
        else if (pciehp_get_hp_hw_control_from_firmware(pdev))
                goto err_out_none;
 
-       ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+       ctrl = pcie_init(dev);
        if (!ctrl) {
-               err("%s : out of memory\n", __func__);
-               goto err_out_none;
-       }
-       INIT_LIST_HEAD(&ctrl->slot_list);
-
-       rc = pcie_init(ctrl, dev);
-       if (rc) {
                dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME);
-               goto err_out_free_ctrl;
+               goto err_out_none;
        }
-
        pci_set_drvdata(pdev, ctrl);
 
-       dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
-           __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
-           PCI_FUNC(pdev->devfn), pdev->irq);
-
        /* Setup the slot information structures */
        rc = init_slots(ctrl);
        if (rc) {
        cleanup_slots(ctrl);
 err_out_release_ctlr:
        ctrl->hpc_ops->release_ctlr(ctrl);
-err_out_free_ctrl:
-       kfree(ctrl);
 err_out_none:
        return -ENODEV;
 }
 
        cleanup_slots(ctrl);
        ctrl->hpc_ops->release_ctlr(ctrl);
-       kfree(ctrl);
 }
 
 #ifdef CONFIG_PM
                u8 status;
 
                /* reinitialize the chipset's event detection logic */
-               pcie_init_hardware_part2(ctrl, dev);
+               pcie_enable_notification(ctrl);
 
                t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
 
 
            __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 }
 
-static void hpc_release_ctlr(struct controller *ctrl)
-{
-       /* Mask Hot-plug Interrupt Enable */
-       if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE))
-               err("%s: Cannot mask hotplug interrupt enable\n", __func__);
-
-       /* Free interrupt handler or interrupt polling timer */
-       pciehp_free_irq(ctrl);
-
-       /*
-        * If this is the last controller to be released, destroy the
-        * pciehp work queue
-        */
-       if (atomic_dec_and_test(&pciehp_num_controllers))
-               destroy_workqueue(pciehp_wq);
-}
-
 static int hpc_power_on_slot(struct slot * slot)
 {
        struct controller *ctrl = slot->ctrl;
        if (!(intr_loc & ~CMD_COMPLETED))
                return IRQ_HANDLED;
 
-       /*
-        * Return without handling events if this handler routine is
-        * called before controller initialization is done. This may
-        * happen if hotplug event or another interrupt that shares
-        * the IRQ with pciehp arrives before slot initialization is
-        * done after interrupt handler is registered.
-        *
-        * FIXME - Need more structural fixes. We need to be ready to
-        * handle the event before installing interrupt handler.
-        */
        p_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
-       if (!p_slot || !p_slot->hpc_ops)
-               return IRQ_HANDLED;
 
        /* Check MRL Sensor Changed */
        if (intr_loc & MRL_SENS_CHANGED)
        return retval;
 }
 
+static void pcie_release_ctrl(struct controller *ctrl);
 static struct hpc_ops pciehp_hpc_ops = {
        .power_on_slot                  = hpc_power_on_slot,
        .power_off_slot                 = hpc_power_off_slot,
        .green_led_off                  = hpc_set_green_led_off,
        .green_led_blink                = hpc_set_green_led_blink,
 
-       .release_ctlr                   = hpc_release_ctlr,
+       .release_ctlr                   = pcie_release_ctrl,
        .check_lnk_status               = hpc_check_lnk_status,
 };
 
-static int pcie_init_hardware_part1(struct controller *ctrl,
-                                   struct pcie_device *dev)
-{
-       /* Clear all remaining event bits in Slot Status register */
-       if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) {
-               err("%s: Cannot write to SLOTSTATUS register\n", __func__);
-               return -1;
-       }
-
-       /* Mask Hot-plug Interrupt Enable */
-       if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) {
-               err("%s: Cannot mask hotplug interrupt enable\n", __func__);
-               return -1;
-       }
-       return 0;
-}
-
-int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
+int pcie_enable_notification(struct controller *ctrl)
 {
        u16 cmd, mask;
 
                err("%s: Cannot enable software notification\n", __func__);
                return -1;
        }
+       return 0;
+}
+
+static void pcie_disable_notification(struct controller *ctrl)
+{
+       u16 mask;
+       mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE | MRL_DETECT_ENABLE |
+              PWR_FAULT_DETECT_ENABLE | HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE;
+       if (pcie_write_cmd(ctrl, 0, mask))
+               warn("%s: Cannot disable software notification\n", __func__);
+}
+
+static int pcie_init_notification(struct controller *ctrl)
+{
+       if (pciehp_request_irq(ctrl))
+               return -1;
+       if (pcie_enable_notification(ctrl)) {
+               pciehp_free_irq(ctrl);
+               return -1;
+       }
+       return 0;
+}
+
+static void pcie_shutdown_notification(struct controller *ctrl)
+{
+       pcie_disable_notification(ctrl);
+       pciehp_free_irq(ctrl);
+}
+
+static void make_slot_name(struct slot *slot)
+{
+       if (pciehp_slot_with_bus)
+               snprintf(slot->name, SLOT_NAME_SIZE, "%04d_%04d",
+                        slot->bus, slot->number);
+       else
+               snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number);
+}
 
+static int pcie_init_slot(struct controller *ctrl)
+{
+       struct slot *slot;
+
+       slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+       if (!slot)
+               return -ENOMEM;
+
+       slot->hp_slot = 0;
+       slot->ctrl = ctrl;
+       slot->bus = ctrl->pci_dev->subordinate->number;
+       slot->device = ctrl->slot_device_offset + slot->hp_slot;
+       slot->hpc_ops = ctrl->hpc_ops;
+       slot->number = ctrl->first_slot;
+       make_slot_name(slot);
+       mutex_init(&slot->lock);
+       INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
+       list_add(&slot->slot_list, &ctrl->slot_list);
        return 0;
 }
 
+static void pcie_cleanup_slot(struct controller *ctrl)
+{
+       struct slot *slot;
+       slot = list_first_entry(&ctrl->slot_list, struct slot, slot_list);
+       list_del(&slot->slot_list);
+       cancel_delayed_work(&slot->work);
+       flush_scheduled_work();
+       flush_workqueue(pciehp_wq);
+       kfree(slot);
+}
+
 static inline void dbg_ctrl(struct controller *ctrl)
 {
        int i;
        dbg("Slot Control           : 0x%04x\n", reg16);
 }
 
-int pcie_init(struct controller *ctrl, struct pcie_device *dev)
+struct controller *pcie_init(struct pcie_device *dev)
 {
+       struct controller *ctrl;
        u32 slot_cap;
        struct pci_dev *pdev = dev->port;
 
+       ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+       if (!ctrl) {
+               err("%s : out of memory\n", __func__);
+               goto abort;
+       }
+       INIT_LIST_HEAD(&ctrl->slot_list);
+
        ctrl->pci_dev = pdev;
        ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
        if (!ctrl->cap_base) {
            !(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl)))
            ctrl->no_cmd_complete = 1;
 
-       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);
+       /* Clear all remaining event bits in Slot Status register */
+       if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f))
+               goto abort_ctrl;
 
-       if (pcie_init_hardware_part1(ctrl, dev))
-               goto abort;
-
-       if (pciehp_request_irq(ctrl))
-               goto abort;
+       /* Disable sotfware notification */
+       pcie_disable_notification(ctrl);
 
        /*
         * If this is the first controller to be initialized,
         */
        if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
                pciehp_wq = create_singlethread_workqueue("pciehpd");
-               if (!pciehp_wq) {
-                       goto abort_free_irq;
-               }
+               if (!pciehp_wq)
+                       goto abort_ctrl;
        }
 
-       if (pcie_init_hardware_part2(ctrl, dev))
-               goto abort_free_irq;
+       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 (pcie_init_slot(ctrl))
+               goto abort_ctrl;
 
-       return 0;
+       if (pcie_init_notification(ctrl))
+               goto abort_slot;
 
-abort_free_irq:
-       pciehp_free_irq(ctrl);
+       return ctrl;
+
+abort_slot:
+       pcie_cleanup_slot(ctrl);
+abort_ctrl:
+       kfree(ctrl);
 abort:
-       return -1;
+       return NULL;
+}
+
+void pcie_release_ctrl(struct controller *ctrl)
+{
+       pcie_shutdown_notification(ctrl);
+       pcie_cleanup_slot(ctrl);
+       /*
+        * If this is the last controller to be released, destroy the
+        * pciehp work queue
+        */
+       if (atomic_dec_and_test(&pciehp_num_controllers))
+               destroy_workqueue(pciehp_wq);
+       kfree(ctrl);
 }