vserver 1.9.5.x5
[linux-2.6.git] / drivers / pci / hotplug / pciehp_hpc.c
index 1774a5e..9e70c46 100644 (file)
@@ -182,7 +182,7 @@ static int pcie_cap_base = 0;               /* Base of the PCI Express capability item struct
 #define MRL_SENS_PRSN  0x00000004
 #define ATTN_LED_PRSN  0x00000008
 #define PWR_LED_PRSN   0x00000010
-#define HP_SUPR_RM     0x00000020
+#define HP_SUPR_RM_SUP 0x00000020
 #define HP_CAP         0x00000040
 #define SLOT_PWR_VALUE 0x000003F8
 #define SLOT_PWR_LIMIT 0x00000C00
@@ -237,7 +237,7 @@ struct php_ctlr_state_s {
 static spinlock_t hpc_event_lock;
 
 DEFINE_DBG_BUFFER              /* Debug string buffer for entire HPC defined here */
-static struct php_ctlr_state_s *php_ctlr_list_head = 0;        /* HPC state linked list */
+static struct php_ctlr_state_s *php_ctlr_list_head; /* HPC state linked list */
 static int ctlr_seq_num = 0;   /* Controller sequence # */
 static spinlock_t list_lock;
 
@@ -291,14 +291,14 @@ static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds)
 
 static int pcie_write_cmd(struct slot *slot, u16 cmd)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        int retval = 0;
        u16 slot_status;
 
        DBG_ENTER_ROUTINE 
        
        dbg("%s : Enter\n", __FUNCTION__);
-       if (!slot->ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return -1;
        }
@@ -331,13 +331,13 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)
 
 static int hpc_check_lnk_status(struct controller *ctrl)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
        u16 lnk_status;
        int retval = 0;
 
        DBG_ENTER_ROUTINE 
 
-       if (!ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return -1;
        }
@@ -349,7 +349,9 @@ static int hpc_check_lnk_status(struct controller *ctrl)
                return retval;
        }
 
-       if ( (lnk_status & (LNK_TRN | LNK_TRN_ERR)) == 0x0C00) {
+       dbg("%s: lnk_status = %x\n", __FUNCTION__, lnk_status);
+       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;
                return retval;
@@ -362,14 +364,14 @@ static int hpc_check_lnk_status(struct controller *ctrl)
 
 static int hpc_get_attention_status(struct slot *slot, u8 *status)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u16 slot_ctrl;
        u8 atten_led_state;
        int retval = 0;
        
        DBG_ENTER_ROUTINE 
 
-       if (!slot->ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return -1;
        }
@@ -409,14 +411,14 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
 
 static int hpc_get_power_status(struct slot * slot, u8 *status)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u16 slot_ctrl;
        u8 pwr_state;
        int     retval = 0;
        
        DBG_ENTER_ROUTINE 
 
-       if (!slot->ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return -1;
        }
@@ -450,13 +452,13 @@ static int hpc_get_power_status(struct slot * slot, u8 *status)
 
 static int hpc_get_latch_status(struct slot *slot, u8 *status)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u16 slot_status;
        int retval = 0;
 
        DBG_ENTER_ROUTINE 
 
-       if (!slot->ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return -1;
        }
@@ -476,14 +478,14 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
 
 static int hpc_get_adapter_status(struct slot *slot, u8 *status)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u16 slot_status;
        u8 card_state;
        int retval = 0;
 
        DBG_ENTER_ROUTINE 
 
-       if (!slot->ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return -1;
        }
@@ -503,7 +505,7 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
 
 static int hpc_query_power_fault(struct slot * slot)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u16 slot_status;
        u8 pwr_fault;
        int retval = 0;
@@ -511,7 +513,7 @@ static int hpc_query_power_fault(struct slot * slot)
 
        DBG_ENTER_ROUTINE 
 
-       if (!slot->ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return -1;
        }
@@ -532,13 +534,13 @@ static int hpc_query_power_fault(struct slot * slot)
 
 static int hpc_set_attention_status(struct slot *slot, u8 value)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u16 slot_cmd = 0;
        u16 slot_ctrl;
        int rc = 0;
 
        dbg("%s: \n", __FUNCTION__);
-       if (!slot->ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return -1;
        }
@@ -580,13 +582,13 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
 
 static void hpc_set_green_led_on(struct slot *slot)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u16 slot_cmd;
        u16 slot_ctrl;
        int rc = 0;
                
        dbg("%s: \n", __FUNCTION__);    
-       if (!slot->ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return ;
        }
@@ -615,13 +617,13 @@ static void hpc_set_green_led_on(struct slot *slot)
 
 static void hpc_set_green_led_off(struct slot *slot)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u16 slot_cmd;
        u16 slot_ctrl;
        int rc = 0;
 
        dbg("%s: \n", __FUNCTION__);    
-       if (!slot->ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return ;
        }
@@ -651,13 +653,13 @@ static void hpc_set_green_led_off(struct slot *slot)
 
 static void hpc_set_green_led_blink(struct slot *slot)
 {
-       struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u16 slot_cmd;
        u16 slot_ctrl;
        int rc = 0; 
        
        dbg("%s: \n", __FUNCTION__);    
-       if (!slot->ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return ;
        }
@@ -689,16 +691,15 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl,
        int *num_ctlr_slots,    /* number of slots in this HPC; only 1 in PCIE  */      
        int *first_device_num,  /* PCI dev num of the first slot in this PCIE   */
        int *physical_slot_num, /* phy slot num of the first slot in this PCIE  */
-       int *updown,            /* physical_slot_num increament: 1 or -1        */
-       int *flags)
+       u8 *ctrlcap)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
        u32 slot_cap;
        int rc = 0;
        
        DBG_ENTER_ROUTINE 
 
-       if (!ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return -1;
        }
@@ -714,8 +715,9 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl,
        }
        
        *physical_slot_num = slot_cap >> 19;
-
-       *updown = -1;
+       dbg("%s: PSN %d \n", __FUNCTION__, *physical_slot_num);
+       
+       *ctrlcap = slot_cap & 0x0000007f;
 
        DBG_LEAVE_ROUTINE 
        return 0;
@@ -723,12 +725,12 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl,
 
 static void hpc_release_ctlr(struct controller *ctrl)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
        struct php_ctlr_state_s *p, *p_prev;
 
        DBG_ENTER_ROUTINE 
 
-       if (!ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return ;
        }
@@ -739,10 +741,12 @@ static void hpc_release_ctlr(struct controller *ctrl)
                if (php_ctlr->irq) {
                        free_irq(php_ctlr->irq, ctrl);
                        php_ctlr->irq = 0;
+                       if (!pcie_mch_quirk) 
+                               pci_disable_msi(php_ctlr->pci_dev);
                }
        }
        if (php_ctlr->pci_dev) 
-               php_ctlr->pci_dev = 0;
+               php_ctlr->pci_dev = NULL;
 
        spin_lock(&list_lock);
        p = php_ctlr_list_head;
@@ -769,7 +773,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
 
 static int hpc_power_on_slot(struct slot * slot)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u16 slot_cmd;
        u16 slot_ctrl;
 
@@ -778,7 +782,7 @@ static int hpc_power_on_slot(struct slot * slot)
        DBG_ENTER_ROUTINE 
        dbg("%s: \n", __FUNCTION__);    
 
-       if (!slot->ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return -1;
        }
@@ -818,7 +822,7 @@ static int hpc_power_on_slot(struct slot * slot)
 
 static int hpc_power_off_slot(struct slot * slot)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        u16 slot_cmd;
        u16 slot_ctrl;
 
@@ -827,7 +831,7 @@ static int hpc_power_off_slot(struct slot * slot)
        DBG_ENTER_ROUTINE 
        dbg("%s: \n", __FUNCTION__);    
 
-       if (!slot->ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return -1;
        }
@@ -879,10 +883,10 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
                return IRQ_NONE;
 
        if (!pciehp_poll_mode) { 
-               ctrl = (struct controller *)dev_id;
+               ctrl = dev_id;
                php_ctlr = ctrl->hpc_ctlr_handle;
        } else {
-               php_ctlr = (struct php_ctlr_state_s *) dev_id;
+               php_ctlr = dev_id;
                ctrl = (struct controller *)php_ctlr->callback_instance_id;
        }
 
@@ -1015,16 +1019,16 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
        return IRQ_HANDLED;
 }
 
-static int hpc_get_max_lnk_speed (struct slot *slot, enum pcie_link_speed *value)
+static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        enum pcie_link_speed lnk_speed;
        u32     lnk_cap;
        int retval = 0;
 
        DBG_ENTER_ROUTINE 
 
-       if (!slot->ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return -1;
        }
@@ -1058,14 +1062,14 @@ static int hpc_get_max_lnk_speed (struct slot *slot, enum pcie_link_speed *value
 
 static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        enum pcie_link_width lnk_wdth;
        u32     lnk_cap;
        int retval = 0;
 
        DBG_ENTER_ROUTINE 
 
-       if (!slot->ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return -1;
        }
@@ -1118,16 +1122,16 @@ 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 pcie_link_speed *value)
+static int hpc_get_cur_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN;
        int retval = 0;
        u16 lnk_status;
 
        DBG_ENTER_ROUTINE 
 
-       if (!slot->ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return -1;
        }
@@ -1161,14 +1165,14 @@ static int hpc_get_cur_lnk_speed (struct slot *slot, enum pcie_link_speed *value
 
 static int hpc_get_cur_lnk_width (struct slot *slot, enum pcie_link_width *value)
 {
-       struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+       struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
        enum pcie_link_width lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;
        int retval = 0;
        u16 lnk_status;
 
        DBG_ENTER_ROUTINE 
 
-       if (!slot->ctrl->hpc_ctlr_handle) {
+       if (!php_ctlr) {
                err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
                return -1;
        }
@@ -1245,7 +1249,7 @@ static struct hpc_ops pciehp_hpc_ops = {
 };
 
 int pcie_init(struct controller * ctrl,
-       struct pci_dev * pdev,
+       struct pcie_device *dev,
        php_intr_callback_t attention_button_callback,
        php_intr_callback_t switch_change_callback,
        php_intr_callback_t presence_change_callback,
@@ -1257,10 +1261,11 @@ int pcie_init(struct controller * ctrl,
        static int first = 1;
        u16 temp_word;
        u16 cap_reg;
-       u16 intr_enable;
+       u16 intr_enable = 0;
        u32 slot_cap;
        int cap_base, saved_cap_base;
        u16 slot_status, slot_ctrl;
+       struct pci_dev *pdev;
 
        DBG_ENTER_ROUTINE
        
@@ -1273,7 +1278,8 @@ int pcie_init(struct controller * ctrl,
        }
 
        memset(php_ctlr, 0, sizeof(struct php_ctlr_state_s));
-
+       
+       pdev = dev->port;
        php_ctlr->pci_dev = pdev;       /* save pci_dev in context */
 
        dbg("%s: pdev->vendor %x pdev->device %x\n", __FUNCTION__,
@@ -1334,7 +1340,7 @@ int pcie_init(struct controller * ctrl,
        }
 
        dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number, 
-               PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev->irq);
+               PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);
        for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
                if (pci_resource_len(pdev, rc) > 0)
                        dbg("pci resource[%d] start=0x%lx(len=0x%lx)\n", rc,
@@ -1343,12 +1349,15 @@ int pcie_init(struct controller * ctrl,
        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))
+               goto abort_free_ctlr;
+       
        init_MUTEX(&ctrl->crit_sect);
        /* setup wait queue */
        init_waitqueue_head(&ctrl->queue);
 
        /* find the IRQ */
-       php_ctlr->irq = pdev->irq;
+       php_ctlr->irq = dev->irq;
        dbg("HPC interrupt = %d\n", php_ctlr->irq);
 
        /* Save interrupt callback info */
@@ -1400,16 +1409,6 @@ int pcie_init(struct controller * ctrl,
                start_int_poll_timer( php_ctlr, 10 );   /* start with 10 second delay */
        } else {
                /* Installs the interrupt handler */
-               dbg("%s: pciehp_msi_quirk = %x\n", __FUNCTION__, pciehp_msi_quirk);
-               if (!pciehp_msi_quirk) {
-                       rc = pci_enable_msi(pdev);
-                       if (rc) {
-                               info("Can't get msi for the hotplug controller\n");
-                               info("Use INTx for the hotplug controller\n");
-                               dbg("%s: rc = %x\n", __FUNCTION__, rc);
-                       } else 
-                               php_ctlr->irq = pdev->irq;
-               }
                rc = request_irq(php_ctlr->irq, pcie_isr, SA_SHIRQ, MY_NAME, (void *) ctrl);
                dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc);
                if (rc) {
@@ -1424,9 +1423,18 @@ int pcie_init(struct controller * ctrl,
                goto abort_free_ctlr;
        }
        dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word);
+       dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap);
 
-       intr_enable = ATTN_BUTTN_ENABLE | PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
-                                       PRSN_DETECT_ENABLE;
+       intr_enable = intr_enable | PRSN_DETECT_ENABLE;
+
+       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; 
 
@@ -1465,7 +1473,7 @@ int pcie_init(struct controller * ctrl,
        if (php_ctlr_list_head == 0) {
                php_ctlr_list_head = php_ctlr;
                p = php_ctlr_list_head;
-               p->pnext = 0;
+               p->pnext = NULL;
        } else {
                p = php_ctlr_list_head;