PCI: more fixes for PCIe Hotplug so that it works with ExpressCard slots on Dell...
[sfrench/cifs-2.6.git] / drivers / pci / hotplug / pciehp_hpc.c
index f6143175de719b54de9f1d93012f690986fe9dce..8b11d80bf651b3def184635640d4dacfa79cb199 100644 (file)
@@ -129,10 +129,10 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value)
 /* Link Width Encoding */
 #define LNK_X1         0x01
 #define LNK_X2         0x02
-#define LNK_X4         0x04    
+#define LNK_X4         0x04
 #define LNK_X8         0x08
 #define LNK_X12                0x0C
-#define LNK_X16                0x10    
+#define LNK_X16                0x10
 #define LNK_X32                0x20
 
 /*Field definitions of Link Status Register */
@@ -203,7 +203,7 @@ static void int_poll_timeout(unsigned long data)
 
        init_timer(&ctrl->poll_timer);
        if (!pciehp_poll_time)
-               pciehp_poll_time = 2; /* reset timer to poll in 2 secs if user doesn't specify at module installation*/
+               pciehp_poll_time = 2; /* default polling interval is 2 sec */
 
        start_int_poll_timer(ctrl, pciehp_poll_time);
 }
@@ -262,7 +262,7 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
                goto out;
        }
 
-       if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { 
+       if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) {
                /* After 1 sec and CMD_COMPLETED still not set, just
                   proceed forward to issue the next command according
                   to spec.  Just print out the error message */
@@ -310,7 +310,7 @@ static int hpc_check_lnk_status(struct controller *ctrl)
        }
 
        dbg("%s: lnk_status = %x\n", __FUNCTION__, lnk_status);
-       if ( (lnk_status & LNK_TRN) || (lnk_status & LNK_TRN_ERR) || 
+       if ( (lnk_status & LNK_TRN) || (lnk_status & LNK_TRN_ERR) ||
                !(lnk_status & NEG_LINK_WD)) {
                err("%s : Link Training Error occurs \n", __FUNCTION__);
                retval = -1;
@@ -320,7 +320,6 @@ static int hpc_check_lnk_status(struct controller *ctrl)
        return retval;
 }
 
-
 static int hpc_get_attention_status(struct slot *slot, u8 *status)
 {
        struct controller *ctrl = slot->ctrl;
@@ -382,7 +381,7 @@ static int hpc_get_power_status(struct slot *slot, u8 *status)
                *status = 1;
                break;
        case 1:
-               *status = 0;    
+               *status = 0;
                break;
        default:
                *status = 0xFF;
@@ -392,7 +391,6 @@ static int hpc_get_power_status(struct slot *slot, u8 *status)
        return retval;
 }
 
-
 static int hpc_get_latch_status(struct slot *slot, u8 *status)
 {
        struct controller *ctrl = slot->ctrl;
@@ -405,7 +403,7 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
                return retval;
        }
 
-       *status = (((slot_status & MRL_STATE) >> 5) == 0) ? 0 : 1;  
+       *status = (((slot_status & MRL_STATE) >> 5) == 0) ? 0 : 1;
 
        return 0;
 }
@@ -441,7 +439,7 @@ static int hpc_query_power_fault(struct slot *slot)
                return retval;
        }
        pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1);
-       
+
        return pwr_fault;
 }
 
@@ -509,17 +507,16 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
        rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
        dbg("%s: SLOTCTRL %x write cmd %x\n",
            __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
-       
+
        return rc;
 }
 
-
 static void hpc_set_green_led_on(struct slot *slot)
 {
        struct controller *ctrl = slot->ctrl;
        u16 slot_cmd;
        u16 cmd_mask;
-               
+
        slot_cmd = 0x0100;
        cmd_mask = PWR_LED_CTRL;
        if (!pciehp_poll_mode) {
@@ -556,7 +553,7 @@ static void hpc_set_green_led_blink(struct slot *slot)
        struct controller *ctrl = slot->ctrl;
        u16 slot_cmd;
        u16 cmd_mask;
-       
+
        slot_cmd = 0x0200;
        cmd_mask = PWR_LED_CTRL;
        if (!pciehp_poll_mode) {
@@ -695,8 +692,8 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
                return IRQ_NONE;
        }
 
-       intr_detect = ( ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED | MRL_SENS_CHANGED |
-                                       PRSN_DETECT_CHANGED | CMD_COMPLETED );
+       intr_detect = (ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED |
+                      MRL_SENS_CHANGED | PRSN_DETECT_CHANGED | CMD_COMPLETED);
 
        intr_loc = slot_status & intr_detect;
 
@@ -718,7 +715,8 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
 
                dbg("%s: pciehp_readw(SLOTCTRL) with value %x\n",
                    __FUNCTION__, temp_word);
-               temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
+               temp_word = (temp_word & ~HP_INTR_ENABLE &
+                            ~CMD_CMPL_INTR_ENABLE) | 0x00;
                rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
                if (rc) {
                        err("%s: Cannot write to SLOTCTRL register\n",
@@ -736,7 +734,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
                }
                dbg("%s: pciehp_readw(SLOTSTATUS) with value %x\n",
                    __FUNCTION__, slot_status);
-               
+
                /* Clear command complete interrupt caused by this write */
                temp_word = 0x1f;
                rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
@@ -746,10 +744,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
                        return IRQ_NONE;
                }
        }
-       
+
        if (intr_loc & CMD_COMPLETED) {
-               /* 
-                * Command Complete Interrupt Pending 
+               /*
+                * Command Complete Interrupt Pending
                 */
                ctrl->cmd_busy = 0;
                wake_up_interruptible(&ctrl->queue);
@@ -803,7 +801,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
                            __FUNCTION__);
                        return IRQ_NONE;
                }
-               
+
                /* Clear command complete interrupt caused by this write */
                temp_word = 0x1F;
                rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
@@ -815,11 +813,11 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
                dbg("%s: pciehp_writew(SLOTSTATUS) with value %x\n",
                    __FUNCTION__, temp_word);
        }
-       
+
        return IRQ_HANDLED;
 }
 
-static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
+static int hpc_get_max_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
 {
        struct controller *ctrl = slot->ctrl;
        enum pcie_link_speed lnk_speed;
@@ -847,7 +845,8 @@ static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
        return retval;
 }
 
-static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value)
+static int hpc_get_max_lnk_width(struct slot *slot,
+                                enum pcie_link_width *value)
 {
        struct controller *ctrl = slot->ctrl;
        enum pcie_link_width lnk_wdth;
@@ -896,7 +895,7 @@ static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value
        return retval;
 }
 
-static int hpc_get_cur_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
+static int hpc_get_cur_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
 {
        struct controller *ctrl = slot->ctrl;
        enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN;
@@ -924,7 +923,8 @@ static int hpc_get_cur_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
        return retval;
 }
 
-static int hpc_get_cur_lnk_width (struct slot *slot, enum pcie_link_width *value)
+static int hpc_get_cur_lnk_width(struct slot *slot,
+                                enum pcie_link_width *value)
 {
        struct controller *ctrl = slot->ctrl;
        enum pcie_link_width lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;
@@ -936,7 +936,7 @@ static int hpc_get_cur_lnk_width (struct slot *slot, enum pcie_link_width *value
                err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__);
                return retval;
        }
-       
+
        switch ((lnk_status & 0x03F0) >> 4){
        case 0:
                lnk_wdth = PCIE_LNK_WIDTH_RESRV;
@@ -988,12 +988,12 @@ static struct hpc_ops pciehp_hpc_ops = {
        .get_cur_bus_speed              = hpc_get_cur_lnk_speed,
        .get_max_lnk_width              = hpc_get_max_lnk_width,
        .get_cur_lnk_width              = hpc_get_cur_lnk_width,
-       
+
        .query_power_fault              = hpc_query_power_fault,
        .green_led_on                   = hpc_set_green_led_on,
        .green_led_off                  = hpc_set_green_led_off,
        .green_led_blink                = hpc_set_green_led_blink,
-       
+
        .release_ctlr                   = hpc_release_ctlr,
        .check_lnk_status               = hpc_check_lnk_status,
 };
@@ -1067,98 +1067,22 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
 }
 #endif
 
-
-
-int pcie_init(struct controller * ctrl, struct pcie_device *dev)
+int pcie_init_hardware(struct controller *ctrl, struct pcie_device *dev)
 {
        int rc;
        u16 temp_word;
-       u16 cap_reg;
        u16 intr_enable = 0;
        u32 slot_cap;
-       int cap_base;
-       u16 slot_status, slot_ctrl;
+       u16 slot_status;
        struct pci_dev *pdev;
 
        pdev = dev->port;
-       ctrl->pci_dev = pdev;   /* save pci_dev in context */
-
-       dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
-                       __FUNCTION__, pdev->vendor, pdev->device);
-
-       if ((cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP)) == 0) {
-               dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__);
-               goto abort_free_ctlr;
-       }
-
-       ctrl->cap_base = cap_base;
-
-       dbg("%s: pcie_cap_base %x\n", __FUNCTION__, cap_base);
-
-       rc = pciehp_readw(ctrl, CAPREG, &cap_reg);
-       if (rc) {
-               err("%s: Cannot read CAPREG register\n", __FUNCTION__);
-               goto abort_free_ctlr;
-       }
-       dbg("%s: CAPREG offset %x cap_reg %x\n",
-           __FUNCTION__, ctrl->cap_base + CAPREG, cap_reg);
-
-       if (((cap_reg & SLOT_IMPL) == 0) || (((cap_reg & DEV_PORT_TYPE) != 0x0040)
-               && ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
-               dbg("%s : This is not a root port or the port is not connected to a slot\n", __FUNCTION__);
-               goto abort_free_ctlr;
-       }
 
        rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
        if (rc) {
                err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
                goto abort_free_ctlr;
        }
-       dbg("%s: SLOTCAP offset %x slot_cap %x\n",
-           __FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap);
-
-       if (!(slot_cap & HP_CAP)) {
-               dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
-               goto abort_free_ctlr;
-       }
-       /* For debugging purpose */
-       rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-       if (rc) {
-               err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
-               goto abort_free_ctlr;
-       }
-       dbg("%s: SLOTSTATUS offset %x slot_status %x\n",
-           __FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status);
-
-       rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
-       if (rc) {
-               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-               goto abort_free_ctlr;
-       }
-       dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
-           __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
-
-       for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
-               if (pci_resource_len(pdev, rc) > 0)
-                       dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc,
-                           (unsigned long long)pci_resource_start(pdev, rc),
-                           (unsigned long long)pci_resource_len(pdev, rc));
-
-       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);
-
-       mutex_init(&ctrl->crit_sect);
-       mutex_init(&ctrl->ctrl_lock);
-       spin_lock_init(&ctrl->lock);
-
-       /* setup wait queue */
-       init_waitqueue_head(&ctrl->queue);
-
-       /* return PCI Controller Info */
-       ctrl->slot_device_offset = 0;
-       ctrl->num_slots = 1;
-       ctrl->first_slot = slot_cap >> 19;
-       ctrl->ctrlcap = slot_cap & 0x0000007f;
 
        /* Mask Hot-plug Interrupt Enable */
        rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
@@ -1169,7 +1093,8 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 
        dbg("%s: SLOTCTRL %x value read %x\n",
            __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);
-       temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
+       temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
+               0x00;
 
        rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
        if (rc) {
@@ -1232,14 +1157,14 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 
        if (ATTN_BUTTN(slot_cap))
                intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
-       
+
        if (POWER_CTRL(slot_cap))
                intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
-       
+
        if (MRL_SENS(slot_cap))
                intr_enable = intr_enable | MRL_DETECT_ENABLE;
 
-       temp_word = (temp_word & ~intr_enable) | intr_enable; 
+       temp_word = (temp_word & ~intr_enable) | intr_enable;
 
        if (pciehp_poll_mode) {
                temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
@@ -1247,7 +1172,10 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
                temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
        }
 
-       /* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */
+       /*
+        * Unmask Hot-plug Interrupt Enable for the interrupt
+        * notification mechanism case.
+        */
        rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
        if (rc) {
                err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
@@ -1258,14 +1186,14 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
                err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
                goto abort_disable_intr;
        }
-       
+
        temp_word =  0x1F; /* Clear all events */
        rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
        if (rc) {
                err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
                goto abort_disable_intr;
        }
-       
+
        if (pciehp_force) {
                dbg("Bypassing BIOS check for pciehp use on %s\n",
                                pci_name(ctrl->pci_dev));
@@ -1275,11 +1203,9 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
                        goto abort_disable_intr;
        }
 
-       ctrl->hpc_ops = &pciehp_hpc_ops;
-
        return 0;
 
-       /* We end up here for the many possible ways to fail this API.  */
+       /* We end up here for the many possible ways to fail this API. */
 abort_disable_intr:
        rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
        if (!rc) {
@@ -1298,3 +1224,105 @@ abort_free_irq:
 abort_free_ctlr:
        return -1;
 }
+
+int pcie_init(struct controller *ctrl, struct pcie_device *dev)
+{
+       int rc;
+       u16 cap_reg;
+       u32 slot_cap;
+       int cap_base;
+       u16 slot_status, slot_ctrl;
+       struct pci_dev *pdev;
+
+       pdev = dev->port;
+       ctrl->pci_dev = pdev;   /* save pci_dev in context */
+
+       dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
+                       __FUNCTION__, pdev->vendor, pdev->device);
+
+       cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       if (cap_base == 0) {
+               dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__);
+               goto abort;
+       }
+
+       ctrl->cap_base = cap_base;
+
+       dbg("%s: pcie_cap_base %x\n", __FUNCTION__, cap_base);
+
+       rc = pciehp_readw(ctrl, CAPREG, &cap_reg);
+       if (rc) {
+               err("%s: Cannot read CAPREG register\n", __FUNCTION__);
+               goto abort;
+       }
+       dbg("%s: CAPREG offset %x cap_reg %x\n",
+           __FUNCTION__, ctrl->cap_base + CAPREG, cap_reg);
+
+       if (((cap_reg & SLOT_IMPL) == 0) ||
+           (((cap_reg & DEV_PORT_TYPE) != 0x0040)
+               && ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
+               dbg("%s : This is not a root port or the port is not "
+                   "connected to a slot\n", __FUNCTION__);
+               goto abort;
+       }
+
+       rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+       if (rc) {
+               err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
+               goto abort;
+       }
+       dbg("%s: SLOTCAP offset %x slot_cap %x\n",
+           __FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap);
+
+       if (!(slot_cap & HP_CAP)) {
+               dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
+               goto abort;
+       }
+       /* For debugging purpose */
+       rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+       if (rc) {
+               err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
+               goto abort;
+       }
+       dbg("%s: SLOTSTATUS offset %x slot_status %x\n",
+           __FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status);
+
+       rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
+       if (rc) {
+               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+               goto abort;
+       }
+       dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
+           __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
+
+       for (rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
+               if (pci_resource_len(pdev, rc) > 0)
+                       dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc,
+                           (unsigned long long)pci_resource_start(pdev, rc),
+                           (unsigned long long)pci_resource_len(pdev, rc));
+
+       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);
+
+       mutex_init(&ctrl->crit_sect);
+       mutex_init(&ctrl->ctrl_lock);
+       spin_lock_init(&ctrl->lock);
+
+       /* setup wait queue */
+       init_waitqueue_head(&ctrl->queue);
+
+       /* return PCI Controller Info */
+       ctrl->slot_device_offset = 0;
+       ctrl->num_slots = 1;
+       ctrl->first_slot = slot_cap >> 19;
+       ctrl->ctrlcap = slot_cap & 0x0000007f;
+
+       rc = pcie_init_hardware(ctrl, dev);
+       if (rc == 0) {
+               ctrl->hpc_ops = &pciehp_hpc_ops;
+               return 0;
+       }
+abort:
+       return -1;
+}