powerpc/pci/rpadlpar: Fix device reference leaks
[pandora-kernel.git] / drivers / pci / hotplug / pciehp_hpc.c
index 96dc473..fef1748 100644 (file)
@@ -280,6 +280,14 @@ int pciehp_check_link_status(struct controller *ctrl)
         else
                 msleep(1000);
 
+       /*
+        * Need to wait for 1000 ms after Data Link Layer Link Active
+        * (DLLLA) bit reads 1b before sending configuration request.
+        * We need it before checking Link Training (LT) bit becuase
+        * LT is still set even after DLLLA bit is set on some platform.
+        */
+       msleep(1000);
+
        retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
        if (retval) {
                ctrl_err(ctrl, "Cannot read LNKSTATUS register\n");
@@ -294,6 +302,16 @@ int pciehp_check_link_status(struct controller *ctrl)
                return retval;
        }
 
+       /*
+        * If the port supports Link speeds greater than 5.0 GT/s, we
+        * must wait for 100 ms after Link training completes before
+        * sending configuration request.
+        */
+       if (ctrl->pcie->port->subordinate->max_bus_speed > PCIE_SPEED_5_0GT)
+               msleep(100);
+
+       pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
+
        return retval;
 }
 
@@ -484,7 +502,6 @@ int pciehp_power_on_slot(struct slot * slot)
        u16 slot_cmd;
        u16 cmd_mask;
        u16 slot_status;
-       u16 lnk_status;
        int retval = 0;
 
        /* Clear sticky power-fault bit from previous power failures */
@@ -516,14 +533,6 @@ int pciehp_power_on_slot(struct slot * slot)
        ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
                 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
 
-       retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
-       if (retval) {
-               ctrl_err(ctrl, "%s: Cannot read LNKSTA register\n",
-                               __func__);
-               return retval;
-       }
-       pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
-
        return retval;
 }
 
@@ -780,24 +789,32 @@ static void pcie_shutdown_notification(struct controller *ctrl)
 static int pcie_init_slot(struct controller *ctrl)
 {
        struct slot *slot;
+       char name[32];
 
        slot = kzalloc(sizeof(*slot), GFP_KERNEL);
        if (!slot)
                return -ENOMEM;
 
+       snprintf(name, sizeof(name), "pciehp-%u", PSN(ctrl));
+       slot->wq = alloc_workqueue(name, 0, 0);
+       if (!slot->wq)
+               goto abort;
+
        slot->ctrl = ctrl;
        mutex_init(&slot->lock);
        INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
        ctrl->slot = slot;
        return 0;
+abort:
+       kfree(slot);
+       return -ENOMEM;
 }
 
 static void pcie_cleanup_slot(struct controller *ctrl)
 {
        struct slot *slot = ctrl->slot;
        cancel_delayed_work(&slot->work);
-       flush_workqueue(pciehp_wq);
-       flush_workqueue(pciehp_ordered_wq);
+       destroy_workqueue(slot->wq);
        kfree(slot);
 }