vserver 1.9.5.x5
[linux-2.6.git] / drivers / pci / hotplug / pciehp_ctrl.c
index 4c5bb2f..0dbcf04 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/wait.h>
 #include <linux/smp_lock.h>
 #include <linux/pci.h>
+#include "../pci.h"
 #include "pciehp.h"
 #include "pciehprm.h"
 
@@ -51,6 +52,7 @@ static struct semaphore event_semaphore;      /* mutex for process loop (up if someth
 static struct semaphore event_exit;            /* guard ensure thread has exited before calling it quits */
 static int event_finished;
 static unsigned long pushbutton_pending;       /* = 0 */
+static unsigned long surprise_rm_pending;      /* = 0 */
 
 u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id)
 {
@@ -1058,6 +1060,38 @@ static int is_bridge(struct pci_func * func)
    hotplug controller logic
  */
 
+static void set_slot_off(struct controller *ctrl, struct slot * pslot)
+{
+       /* Wait for exclusive access to hardware */
+       down(&ctrl->crit_sect);
+
+       /* turn off slot, turn on Amber LED, turn off Green LED if supported*/
+       if (POWER_CTRL(ctrl->ctrlcap)) {
+               if (pslot->hpc_ops->power_off_slot(pslot)) {   
+                       err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
+                       up(&ctrl->crit_sect);
+                       return;
+               }
+               wait_for_ctrl_irq (ctrl);
+       }
+
+       if (PWR_LED(ctrl->ctrlcap)) {
+               pslot->hpc_ops->green_led_off(pslot);   
+               wait_for_ctrl_irq (ctrl);
+       }
+
+       if (ATTN_LED(ctrl->ctrlcap)) { 
+               if (pslot->hpc_ops->set_attention_status(pslot, 1)) {   
+                       err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
+                       up(&ctrl->crit_sect);
+                       return;
+               }
+               wait_for_ctrl_irq (ctrl);
+       }
+
+       /* Done with exclusive hardware access */
+       up(&ctrl->crit_sect);
+}
 
 /**
  * board_added - Called after a board has been added to the system.
@@ -1071,7 +1105,7 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
        u8 hp_slot;
        int index;
        u32 temp_register = 0xFFFFFFFF;
-       u32 retval, rc = 0;
+       u32 rc = 0;
        struct pci_func *new_func = NULL;
        struct slot *p_slot;
        struct resource_lists res_lists;
@@ -1084,18 +1118,24 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
        /* Wait for exclusive access to hardware */
        down(&ctrl->crit_sect);
 
-       /* Power on slot */
-       rc = p_slot->hpc_ops->power_on_slot(p_slot);
-       if (rc)
-               return -1;
+       if (POWER_CTRL(ctrl->ctrlcap)) {
+               /* Power on slot */
+               rc = p_slot->hpc_ops->power_on_slot(p_slot);
+               if (rc) {
+                       up(&ctrl->crit_sect);
+                       return -1;
+               }
 
-       /* Wait for the command to complete */
-       wait_for_ctrl_irq (ctrl);
+               /* Wait for the command to complete */
+               wait_for_ctrl_irq (ctrl);
+       }
        
-       p_slot->hpc_ops->green_led_blink(p_slot);
+       if (PWR_LED(ctrl->ctrlcap)) {
+               p_slot->hpc_ops->green_led_blink(p_slot);
                        
-       /* Wait for the command to complete */
-       wait_for_ctrl_irq (ctrl);
+               /* Wait for the command to complete */
+               wait_for_ctrl_irq (ctrl);
+       }
 
        /* Done with exclusive hardware access */
        up(&ctrl->crit_sect);
@@ -1105,11 +1145,12 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
        wait_for_ctrl_irq (ctrl);
        dbg("%s: afterlong_delay\n", __FUNCTION__);
 
-       /*  Make this to check for link training status */
+       /*  Check link training status */
        rc = p_slot->hpc_ops->check_lnk_status(ctrl);  
        if (rc) {
                err("%s: Failed to check link status\n", __FUNCTION__);
-               return -1;
+               set_slot_off(ctrl, p_slot);
+               return rc;
        }
 
        dbg("%s: func status = %x\n", __FUNCTION__, func->status);
@@ -1159,36 +1200,7 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
                pciehp_resource_sort_and_combine(&(ctrl->bus_head));
 
                if (rc) {
-                       /* Wait for exclusive access to hardware */
-                       down(&ctrl->crit_sect);
-
-                       /* turn off slot, turn on Amber LED, turn off Green LED */
-                       retval = p_slot->hpc_ops->power_off_slot(p_slot);   
-                       /* In PCI Express, just power off slot */
-                       if (retval) {
-                               err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
-                               return retval;
-                       }
-                       /* Wait for the command to complete */
-                       wait_for_ctrl_irq (ctrl);
-
-                       p_slot->hpc_ops->green_led_off(p_slot);   
-                       
-                       /* Wait for the command to complete */
-                       wait_for_ctrl_irq (ctrl);
-
-                       /* turn on Amber LED */
-                       retval = p_slot->hpc_ops->set_attention_status(p_slot, 1);   
-                       if (retval) {
-                               err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
-                               return retval;
-                       }
-                       /* Wait for the command to complete */
-                       wait_for_ctrl_irq (ctrl);
-
-                       /* Done with exclusive hardware access */
-                       up(&ctrl->crit_sect);
-
+                       set_slot_off(ctrl, p_slot);
                        return rc;
                }
                pciehp_save_slot_config(ctrl, func);
@@ -1210,50 +1222,27 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
                        }
                } while (new_func);
 
-               /* Wait for exclusive access to hardware */
-               down(&ctrl->crit_sect);
-
-               p_slot->hpc_ops->green_led_on(p_slot);
-
-               /* Wait for the command to complete */
-               wait_for_ctrl_irq (ctrl);
-
-
-               /* Done with exclusive hardware access */
-               up(&ctrl->crit_sect);
-
+               /* 
+                * Some PCI Express root ports require fixup after hot-plug operation.
+                */
+               if (pcie_mch_quirk)
+                       pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
+               if (PWR_LED(ctrl->ctrlcap)) {
+                       /* Wait for exclusive access to hardware */
+                       down(&ctrl->crit_sect);
+   
+                       p_slot->hpc_ops->green_led_on(p_slot);
+  
+                       /* Wait for the command to complete */
+                       wait_for_ctrl_irq (ctrl);
+       
+                       /* Done with exclusive hardware access */
+                       up(&ctrl->crit_sect);
+               }
        } else {
-               /* Wait for exclusive access to hardware */
-               down(&ctrl->crit_sect);
-
-               /* turn off slot, turn on Amber LED, turn off Green LED */
-               retval = p_slot->hpc_ops->power_off_slot(p_slot);   
-               /* In PCI Express, just power off slot */
-               if (retval) {
-                       err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
-                       return retval;
-               }
-               /* Wait for the command to complete */
-               wait_for_ctrl_irq (ctrl);
-
-               p_slot->hpc_ops->green_led_off(p_slot);   
-               
-               /* Wait for the command to complete */
-               wait_for_ctrl_irq (ctrl);
-
-               /* turn on Amber LED */
-               retval = p_slot->hpc_ops->set_attention_status(p_slot, 1);   
-               if (retval) {
-                       err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
-                       return retval;
-               }
-               /* Wait for the command to complete */
-               wait_for_ctrl_irq (ctrl);
-
-               /* Done with exclusive hardware access */
-               up(&ctrl->crit_sect);
-
-               return rc;
+               set_slot_off(ctrl, p_slot);
+               return -1;
        }
        return 0;
 }
@@ -1316,20 +1305,25 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl)
        /* Wait for exclusive access to hardware */
        down(&ctrl->crit_sect);
 
-       /* power off slot */
-       rc = p_slot->hpc_ops->power_off_slot(p_slot);
-       if (rc) {
-               err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
-               return rc;
+       if (POWER_CTRL(ctrl->ctrlcap)) {
+               /* power off slot */
+               rc = p_slot->hpc_ops->power_off_slot(p_slot);
+               if (rc) {
+                       err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
+                       up(&ctrl->crit_sect);
+                       return rc;
+               }
+               /* Wait for the command to complete */
+               wait_for_ctrl_irq (ctrl);
        }
-       /* Wait for the command to complete */
-       wait_for_ctrl_irq (ctrl);
 
-       /* turn off Green LED */
-       p_slot->hpc_ops->green_led_off(p_slot);
+       if (PWR_LED(ctrl->ctrlcap)) {
+               /* turn off Green LED */
+               p_slot->hpc_ops->green_led_off(p_slot);
        
-       /* Wait for the command to complete */
-       wait_for_ctrl_irq (ctrl);
+               /* Wait for the command to complete */
+               wait_for_ctrl_irq (ctrl);
+       }
 
        /* Done with exclusive hardware access */
        up(&ctrl->crit_sect);
@@ -1360,10 +1354,11 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl)
                                dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", 
                                        ctrl->seg, func->bus, func->device, func->function);
                                bridge_slot_remove(func);
-                       } else
+                       } else {
                                dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", 
                                        ctrl->seg, func->bus, func->device, func->function);
                                slot_remove(func);
+                       }
 
                        func = pciehp_slot_find(ctrl->slot_bus, device, 0);
                }
@@ -1394,7 +1389,6 @@ static void pushbutton_helper_thread(unsigned long data)
        up(&event_semaphore);
 }
 
-
 /**
  * pciehp_pushbutton_thread
  *
@@ -1406,7 +1400,6 @@ static void pciehp_pushbutton_thread(unsigned long slot)
 {
        struct slot *p_slot = (struct slot *) slot;
        u8 getstatus;
-       int rc;
        
        pushbutton_pending = 0;
 
@@ -1420,17 +1413,18 @@ static void pciehp_pushbutton_thread(unsigned long slot)
                p_slot->state = POWEROFF_STATE;
                dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
 
-               if (pciehp_disable_slot(p_slot)) {
+               pciehp_disable_slot(p_slot);
+               p_slot->state = STATIC_STATE;
+       } else {
+               p_slot->state = POWERON_STATE;
+               dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
+
+               if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
                        /* Wait for exclusive access to hardware */
                        down(&p_slot->ctrl->crit_sect);
 
-                       /* Turn on the Attention LED */
-                       rc = p_slot->hpc_ops->set_attention_status(p_slot, 1);
-                       if (rc) {
-                               err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__);
-                               return;
-                       }
-       
+                       p_slot->hpc_ops->green_led_off(p_slot);
+
                        /* Wait for the command to complete */
                        wait_for_ctrl_irq (p_slot->ctrl);
 
@@ -1438,23 +1432,45 @@ static void pciehp_pushbutton_thread(unsigned long slot)
                        up(&p_slot->ctrl->crit_sect);
                }
                p_slot->state = STATIC_STATE;
+       }
+
+       return;
+}
+
+/**
+ * pciehp_surprise_rm_thread
+ *
+ * Scheduled procedure to handle blocking stuff for the surprise removal
+ * Handles all pending events and exits.
+ *
+ */
+static void pciehp_surprise_rm_thread(unsigned long slot)
+{
+       struct slot *p_slot = (struct slot *) slot;
+       u8 getstatus;
+       
+       surprise_rm_pending = 0;
+
+       if (!p_slot) {
+               dbg("%s: Error! slot NULL\n", __FUNCTION__);
+               return;
+       }
+
+       p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
+       if (!getstatus) {
+               p_slot->state = POWEROFF_STATE;
+               dbg("In removing board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
+
+               pciehp_disable_slot(p_slot);
+               p_slot->state = STATIC_STATE;
        } else {
                p_slot->state = POWERON_STATE;
                dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
 
-               if (pciehp_enable_slot(p_slot)) {
+               if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
                        /* Wait for exclusive access to hardware */
                        down(&p_slot->ctrl->crit_sect);
 
-                       /* Turn off the green LED */
-                       rc = p_slot->hpc_ops->set_attention_status(p_slot, 1);
-                       if (rc) {
-                               err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__);
-                               return;
-                       }
-                       /* Wait for the command to complete */
-                       wait_for_ctrl_irq (p_slot->ctrl);
-                       
                        p_slot->hpc_ops->green_led_off(p_slot);
 
                        /* Wait for the command to complete */
@@ -1470,6 +1486,7 @@ static void pciehp_pushbutton_thread(unsigned long slot)
 }
 
 
+
 /* this is the main worker thread */
 static int event_thread(void* data)
 {
@@ -1488,6 +1505,8 @@ static int event_thread(void* data)
                /* Do stuff here */
                if (pushbutton_pending)
                        pciehp_pushbutton_thread(pushbutton_pending);
+               else if (surprise_rm_pending)
+                       pciehp_surprise_rm_thread(surprise_rm_pending);
                else
                        for (ctrl = pciehp_ctrl_list; ctrl; ctrl=ctrl->next)
                                interrupt_event_handler(ctrl);
@@ -1506,7 +1525,7 @@ int pciehp_event_start_thread(void)
        event_finished=0;
 
        init_MUTEX_LOCKED(&event_semaphore);
-       pid = kernel_thread(event_thread, 0, 0);
+       pid = kernel_thread(event_thread, NULL, 0);
 
        if (pid < 0) {
                err ("Can't start up our event thread\n");
@@ -1580,16 +1599,18 @@ static void interrupt_event_handler(struct controller *ctrl)
                                        case BLINKINGOFF_STATE:
                                                /* Wait for exclusive access to hardware */
                                                down(&ctrl->crit_sect);
-
-                                               p_slot->hpc_ops->green_led_on(p_slot);
-                                               /* Wait for the command to complete */
-                                               wait_for_ctrl_irq (ctrl);
-
-                                               p_slot->hpc_ops->set_attention_status(p_slot, 0);
-
-                                               /* Wait for the command to complete */
-                                               wait_for_ctrl_irq (ctrl);
-
+                                               
+                                               if (PWR_LED(ctrl->ctrlcap)) {
+                                                       p_slot->hpc_ops->green_led_on(p_slot);
+                                                       /* Wait for the command to complete */
+                                                       wait_for_ctrl_irq (ctrl);
+                                               }
+                                               if (ATTN_LED(ctrl->ctrlcap)) {
+                                                       p_slot->hpc_ops->set_attention_status(p_slot, 0);
+
+                                                       /* Wait for the command to complete */
+                                                       wait_for_ctrl_irq (ctrl);
+                                               }
                                                /* Done with exclusive hardware access */
                                                up(&ctrl->crit_sect);
                                                break;
@@ -1597,14 +1618,16 @@ static void interrupt_event_handler(struct controller *ctrl)
                                                /* Wait for exclusive access to hardware */
                                                down(&ctrl->crit_sect);
 
-                                               p_slot->hpc_ops->green_led_off(p_slot);
-                                               /* Wait for the command to complete */
-                                               wait_for_ctrl_irq (ctrl);
-
-                                               p_slot->hpc_ops->set_attention_status(p_slot, 0);
-                                               /* Wait for the command to complete */
-                                               wait_for_ctrl_irq (ctrl);
-
+                                               if (PWR_LED(ctrl->ctrlcap)) {
+                                                       p_slot->hpc_ops->green_led_off(p_slot);
+                                                       /* Wait for the command to complete */
+                                                       wait_for_ctrl_irq (ctrl);
+                                               }
+                                               if (ATTN_LED(ctrl->ctrlcap)){
+                                                       p_slot->hpc_ops->set_attention_status(p_slot, 0);
+                                                       /* Wait for the command to complete */
+                                                       wait_for_ctrl_irq (ctrl);
+                                               }
                                                /* Done with exclusive hardware access */
                                                up(&ctrl->crit_sect);
 
@@ -1618,56 +1641,83 @@ static void interrupt_event_handler(struct controller *ctrl)
                                }
                                /* ***********Button Pressed (No action on 1st press...) */
                                else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) {
-                                       dbg("Button pressed\n");
-
-                                       p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
-                                       if (getstatus) {
-                                               /* slot is on */
-                                               dbg("slot is on\n");
-                                               p_slot->state = BLINKINGOFF_STATE;
-                                               info(msg_button_off, p_slot->number);
-                                       } else {
-                                               /* slot is off */
-                                               dbg("slot is off\n");
-                                               p_slot->state = BLINKINGON_STATE;
-                                               info(msg_button_on, p_slot->number);
-                                       }
+                                       
+                                       if (ATTN_BUTTN(ctrl->ctrlcap)) {
+                                               dbg("Button pressed\n");
+                                               p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+                                               if (getstatus) {
+                                                       /* slot is on */
+                                                       dbg("slot is on\n");
+                                                       p_slot->state = BLINKINGOFF_STATE;
+                                                       info(msg_button_off, p_slot->number);
+                                               } else {
+                                                       /* slot is off */
+                                                       dbg("slot is off\n");
+                                                       p_slot->state = BLINKINGON_STATE;
+                                                       info(msg_button_on, p_slot->number);
+                                               }
 
-                                       /* Wait for exclusive access to hardware */
-                                       down(&ctrl->crit_sect);
+                                               /* Wait for exclusive access to hardware */
+                                               down(&ctrl->crit_sect);
 
-                                       /* blink green LED and turn off amber */
-                                       p_slot->hpc_ops->green_led_blink(p_slot);
-                                       /* Wait for the command to complete */
-                                       wait_for_ctrl_irq (ctrl);
-                                       
-                                       p_slot->hpc_ops->set_attention_status(p_slot, 0);
+                                               /* blink green LED and turn off amber */
+                                               if (PWR_LED(ctrl->ctrlcap)) {
+                                                       p_slot->hpc_ops->green_led_blink(p_slot);
+                                                       /* Wait for the command to complete */
+                                                       wait_for_ctrl_irq (ctrl);
+                                               }
 
-                                       /* Wait for the command to complete */
-                                       wait_for_ctrl_irq (ctrl);
+                                               if (ATTN_LED(ctrl->ctrlcap)) {
+                                                       p_slot->hpc_ops->set_attention_status(p_slot, 0);
 
-                                       /* Done with exclusive hardware access */
-                                       up(&ctrl->crit_sect);
+                                                       /* Wait for the command to complete */
+                                                       wait_for_ctrl_irq (ctrl);
+                                               }
+
+                                               /* Done with exclusive hardware access */
+                                               up(&ctrl->crit_sect);
 
-                                       init_timer(&p_slot->task_event);
-                                       p_slot->task_event.expires = jiffies + 5 * HZ;   /* 5 second delay */
-                                       p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
-                                       p_slot->task_event.data = (unsigned long) p_slot;
+                                               init_timer(&p_slot->task_event);
+                                               p_slot->task_event.expires = jiffies + 5 * HZ;   /* 5 second delay */
+                                               p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
+                                               p_slot->task_event.data = (unsigned long) p_slot;
 
-                                       dbg("add_timer p_slot = %p\n", (void *) p_slot);
-                                       add_timer(&p_slot->task_event);
+                                               dbg("add_timer p_slot = %p\n", (void *) p_slot);
+                                               add_timer(&p_slot->task_event);
+                                       }
                                }
                                /***********POWER FAULT********************/
                                else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
-                                       dbg("power fault\n");
-                                       /* Wait for exclusive access to hardware */
-                                       down(&ctrl->crit_sect);
+                                       if (POWER_CTRL(ctrl->ctrlcap)) {
+                                               dbg("power fault\n");
+                                               /* Wait for exclusive access to hardware */
+                                               down(&ctrl->crit_sect);
 
-                                       p_slot->hpc_ops->set_attention_status(p_slot, 1);
-                                       p_slot->hpc_ops->green_led_off(p_slot);
+                                               if (ATTN_LED(ctrl->ctrlcap)) {
+                                                       p_slot->hpc_ops->set_attention_status(p_slot, 1);
+                                                       wait_for_ctrl_irq (ctrl);
+                                               }
 
-                                       /* Done with exclusive hardware access */
-                                       up(&ctrl->crit_sect);
+                                               if (PWR_LED(ctrl->ctrlcap)) {
+                                                       p_slot->hpc_ops->green_led_off(p_slot);
+                                                       wait_for_ctrl_irq (ctrl);
+                                               }
+
+                                               /* Done with exclusive hardware access */
+                                               up(&ctrl->crit_sect);
+                                       }
+                               }
+                               /***********SURPRISE REMOVAL********************/
+                               else if ((ctrl->event_queue[loop].event_type == INT_PRESENCE_ON) || 
+                                       (ctrl->event_queue[loop].event_type == INT_PRESENCE_OFF)) {
+                                       if (HP_SUPR_RM(ctrl->ctrlcap)) {
+                                               dbg("Surprise Removal\n");
+                                               if (p_slot) {
+                                                       surprise_rm_pending = (unsigned long) p_slot;
+                                                       up(&event_semaphore);
+                                                       update_slot_info(p_slot);
+                                               }
+                                       }
                                } else {
                                        /* refresh notification */
                                        if (p_slot)
@@ -1697,25 +1747,29 @@ int pciehp_enable_slot(struct slot *p_slot)
 
        /* Check to see if (latch closed, card present, power off) */
        down(&p_slot->ctrl->crit_sect);
+
        rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
        if (rc || !getstatus) {
                info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
                up(&p_slot->ctrl->crit_sect);
-               return 0;
+               return 1;
        }
-       
-       rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
-       if (rc || getstatus) {
-               info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
-               up(&p_slot->ctrl->crit_sect);
-               return 0;
+       if (MRL_SENS(p_slot->ctrl->ctrlcap)) {  
+               rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+               if (rc || getstatus) {
+                       info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
+                       up(&p_slot->ctrl->crit_sect);
+                       return 1;
+               }
        }
        
-       rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
-       if (rc || getstatus) {
-               info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
-               up(&p_slot->ctrl->crit_sect);
-               return 0;
+       if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {        
+               rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+               if (rc || getstatus) {
+                       info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
+                       up(&p_slot->ctrl->crit_sect);
+                       return 1;
+               }
        }
        up(&p_slot->ctrl->crit_sect);
 
@@ -1784,26 +1838,33 @@ int pciehp_disable_slot(struct slot *p_slot)
        /* Check to see if (latch closed, card present, power on) */
        down(&p_slot->ctrl->crit_sect);
 
-       ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
-       if (ret || !getstatus) {
-               info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
-               up(&p_slot->ctrl->crit_sect);
-               return 0;
+       if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) {       
+               ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
+               if (ret || !getstatus) {
+                       info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
+                       up(&p_slot->ctrl->crit_sect);
+                       return 1;
+               }
        }
 
-       ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
-       if (ret || getstatus) {
-               info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
-               up(&p_slot->ctrl->crit_sect);
-               return 0;
+       if (MRL_SENS(p_slot->ctrl->ctrlcap)) {  
+               ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+               if (ret || getstatus) {
+                       info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
+                       up(&p_slot->ctrl->crit_sect);
+                       return 1;
+               }
        }
 
-       ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
-       if (ret || !getstatus) {
-               info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
-               up(&p_slot->ctrl->crit_sect);
-               return 0;
+       if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {        
+               ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+               if (ret || !getstatus) {
+                       info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
+                       up(&p_slot->ctrl->crit_sect);
+                       return 1;
+               }
        }
+
        up(&p_slot->ctrl->crit_sect);
 
        func = pciehp_slot_find(p_slot->bus, p_slot->device, index++);