vserver 1.9.5.x5
[linux-2.6.git] / drivers / pci / hotplug / shpchp_ctrl.c
index 09d2d1b..9f90eb8 100644 (file)
@@ -137,6 +137,8 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
        p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
        p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
        p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+       dbg("%s: Card present %x Power status %x\n", __FUNCTION__,
+               func->presence_save, func->pwr_save);
 
        if (getstatus) {
                /*
@@ -145,6 +147,10 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
                info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
                func->switch_save = 0;
                taskInfo->event_type = INT_SWITCH_OPEN;
+               if (func->pwr_save && func->presence_save) {
+                       taskInfo->event_type = INT_POWER_FAULT;
+                       err("Surprise Removal of card\n");
+               }
        } else {
                /*
                 *  Switch closed
@@ -396,7 +402,7 @@ static struct pci_resource *do_pre_bridge_resource_split (struct pci_resource **
                /* This one isn't an aligned length, so we'll make a new entry
                 * and split it up.
                 */
-               split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+               split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
 
                if (!split_node)
                        return(NULL);
@@ -530,7 +536,7 @@ static struct pci_resource *get_io_resource (struct pci_resource **head, u32 siz
                        if ((node->length - (temp_dword - node->base)) < size)
                                continue;
 
-                       split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+                       split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
 
                        if (!split_node)
                                return(NULL);
@@ -549,7 +555,7 @@ static struct pci_resource *get_io_resource (struct pci_resource **head, u32 siz
                if (node->length > size) {
                        /* This one is longer than we need
                           so we'll make a new entry and split it up */
-                       split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+                       split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
 
                        if (!split_node)
                                return(NULL);
@@ -630,7 +636,7 @@ static struct pci_resource *get_max_resource (struct pci_resource **head, u32 si
                        if ((max->length - (temp_dword - max->base)) < size)
                                continue;
 
-                       split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+                       split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
 
                        if (!split_node)
                                return(NULL);
@@ -648,7 +654,7 @@ static struct pci_resource *get_max_resource (struct pci_resource **head, u32 si
                if ((max->base + max->length) & (size - 1)) {
                        /* This one isn't end aligned properly at the top
                           so we'll make a new entry and split it up */
-                       split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+                       split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
 
                        if (!split_node)
                                return(NULL);
@@ -669,7 +675,8 @@ static struct pci_resource *get_max_resource (struct pci_resource **head, u32 si
 
                for ( i = 0; max_size[i] > size; i++) {
                        if (max->length > max_size[i]) {
-                               split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+                               split_node = kmalloc(sizeof(*split_node),
+                                                       GFP_KERNEL);
                                if (!split_node)
                                        break;  /* return (NULL); */
                                split_node->base = max->base + max_size[i];
@@ -744,7 +751,7 @@ static struct pci_resource *get_resource (struct pci_resource **head, u32 size)
                        if ((node->length - (temp_dword - node->base)) < size)
                                continue;
 
-                       split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+                       split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
 
                        if (!split_node)
                                return(NULL);
@@ -764,7 +771,7 @@ static struct pci_resource *get_resource (struct pci_resource **head, u32 size)
                        dbg("%s: too big\n", __FUNCTION__);
                        /* this one is longer than we need
                           so we'll make a new entry and split it up */
-                       split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+                       split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
 
                        if (!split_node)
                                return(NULL);
@@ -882,7 +889,7 @@ struct pci_func *shpchp_slot_create(u8 busnumber)
        struct pci_func *new_slot;
        struct pci_func *next;
 
-       new_slot = (struct pci_func *) kmalloc(sizeof(struct pci_func), GFP_KERNEL);
+       new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL);
 
        if (new_slot == NULL) {
                return(new_slot);
@@ -1043,7 +1050,64 @@ static int is_bridge(struct pci_func * func)
 /* The following routines constitute the bulk of the 
    hotplug controller logic
  */
+static u32 change_bus_speed(struct controller *ctrl, struct slot *p_slot, enum pci_bus_speed speed)
+{ 
+       u32 rc = 0;
 
+       dbg("%s: change to speed %d\n", __FUNCTION__, speed);
+       down(&ctrl->crit_sect);
+       if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) {
+               err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
+               up(&ctrl->crit_sect);
+               return WRONG_BUS_FREQUENCY;
+       }
+       wait_for_ctrl_irq (ctrl);
+               
+       if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
+               err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
+                         __FUNCTION__);
+               err("%s: Error code (%d)\n", __FUNCTION__, rc);
+               up(&ctrl->crit_sect);
+               return WRONG_BUS_FREQUENCY;
+       }
+       up(&ctrl->crit_sect);
+       return rc;
+}
+
+static u32 fix_bus_speed(struct controller *ctrl, struct slot *pslot, u8 flag, 
+enum pci_bus_speed asp, enum pci_bus_speed bsp, enum pci_bus_speed msp)
+{ 
+       u32 rc = 0;
+       
+       if (flag != 0) { /* Other slots on the same bus are occupied */
+               if ( asp < bsp ) {
+                       err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bsp, asp);
+                       return WRONG_BUS_FREQUENCY;
+               }
+       } else {
+               /* Other slots on the same bus are empty */
+               if (msp == bsp) {
+               /* if adapter_speed >= bus_speed, do nothing */
+                       if (asp < bsp) {
+                               /* 
+                               * Try to lower bus speed to accommodate the adapter if other slots 
+                               * on the same controller are empty
+                               */
+                               if ((rc = change_bus_speed(ctrl, pslot, asp)))
+                                       return rc;
+                       } 
+               } else {
+                       if (asp < msp) {
+                               if ((rc = change_bus_speed(ctrl, pslot, asp)))
+                                       return rc;
+                       } else {
+                               if ((rc = change_bus_speed(ctrl, pslot, msp)))
+                                       return rc;
+                       }
+               }
+       }
+       return rc;
+}
 
 /**
  * board_added - Called after a board has been added to the system.
@@ -1054,14 +1118,13 @@ static int is_bridge(struct pci_func * func)
  */
 static u32 board_added(struct pci_func * func, struct controller * ctrl)
 {
-       u8 hp_slot, slot;
+       u8 hp_slot;
        u8 slots_not_empty = 0;
        int index;
        u32 temp_register = 0xFFFFFFFF;
        u32 retval, rc = 0;
        struct pci_func *new_func = NULL;
-       struct pci_func *t_func = NULL;
-       struct slot *p_slot, *pslot;
+       struct slot *p_slot;
        struct resource_lists res_lists;
        enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed;
        u8 pi, mode;
@@ -1094,6 +1157,40 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
                return -1;
        }
 
+       
+       if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) {
+               if (slots_not_empty)
+                       return WRONG_BUS_FREQUENCY;
+               
+               if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) {
+                       err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
+                       up(&ctrl->crit_sect);
+                       return WRONG_BUS_FREQUENCY;
+               }
+               wait_for_ctrl_irq (ctrl);
+               
+               if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
+                       err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
+                                 __FUNCTION__);
+                       err("%s: Error code (%d)\n", __FUNCTION__, rc);
+                       up(&ctrl->crit_sect);
+                       return WRONG_BUS_FREQUENCY;
+               }
+               /* turn on board, blink green LED, turn off Amber LED */
+               if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
+                       err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
+                       up(&ctrl->crit_sect);
+                       return rc;
+               }
+               wait_for_ctrl_irq (ctrl);
+
+               if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
+                       err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc);
+                       up(&ctrl->crit_sect);
+                       return rc;  
+               }
+       }
        rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed);
        /* 0 = PCI 33Mhz, 1 = PCI 66 Mhz, 2 = PCI-X 66 PA, 4 = PCI-X 66 ECC, */
        /* 5 = PCI-X 133 PA, 7 = PCI-X 133 ECC,  0xa = PCI-X 133 Mhz 266, */
@@ -1125,258 +1222,72 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
        /* Done with exclusive hardware access */
        up(&ctrl->crit_sect);
 
-       rc  = p_slot->hpc_ops->get_prog_int(p_slot, &pi);
-       if (rc) {
+       if ((rc  = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) {
                err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__);
                pi = 1;
        }
+
+       /* Check if there are other slots or devices on the same bus */
+       if (!list_empty(&ctrl->pci_dev->subordinate->devices))
+               slots_not_empty = 1;
+
+       dbg("%s: slots_not_empty %d, pi %d\n", __FUNCTION__, 
+               slots_not_empty, pi);
+       dbg("adapter_speed %d, bus_speed %d, max_bus_speed %d\n", 
+               adapter_speed, bus_speed, max_bus_speed);
+
        if (pi == 2) {
-               for ( slot = 0; slot < ctrl->num_slots; slot++) {
-                       if (slot != hp_slot) {
-                               pslot = shpchp_find_slot(ctrl, slot + ctrl->slot_device_offset);
-                               t_func = shpchp_slot_find(pslot->bus, pslot->device, 0);
-                               slots_not_empty |= t_func->is_a_board;
-                       }
+               dbg("%s: In PI = %d\n", __FUNCTION__, pi);
+               if ((rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode))) {
+                       err("%s: Can't get Mode1_ECC, set mode to 0\n", __FUNCTION__);
+                       mode = 0;
                }
 
                switch (adapter_speed) {
-               case PCI_SPEED_133MHz_PCIX_533: 
+               case PCI_SPEED_133MHz_PCIX_533:
                case PCI_SPEED_133MHz_PCIX_266:
-                       if ((( bus_speed < 0xa ) || (bus_speed < 0xd)) && (max_bus_speed > bus_speed) &&
-                               ((max_bus_speed <= 0xa) || (max_bus_speed <= 0xd)) && (!slots_not_empty)) {
-                       
-                               /* Wait for exclusive access to hardware */
-                               down(&ctrl->crit_sect);
-
-                               rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed);
-                               if (rc) {
-                                       err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
-                                       /* Done with exclusive hardware access */
-                                       up(&ctrl->crit_sect);                           
-                                       return WRONG_BUS_FREQUENCY;
-                               }
-                               
-                               /* Wait for the command to complete */
-                               wait_for_ctrl_irq (ctrl);
-               
-                               rc = p_slot->hpc_ops->check_cmd_status(ctrl);
-                               if (rc) {
-                                       err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
-                                                         __FUNCTION__);
-                                       err("%s: Error code (%d)\n", __FUNCTION__, rc);
-                                       /* Done with exclusive hardware access */
-                                       up(&ctrl->crit_sect);                           
-                                       return WRONG_BUS_FREQUENCY;
-                               }
-                               /* Done with exclusive hardware access */
-                               up(&ctrl->crit_sect);
-                       }
-                       break;
+                       if ((bus_speed != adapter_speed) &&
+                          ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
+                               return rc;
+                       break;  
                case PCI_SPEED_133MHz_PCIX_ECC:
                case PCI_SPEED_133MHz_PCIX:
-
-                       rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode);
-
-                       if (rc) {
-                               err("%s: PI is 1 \n", __FUNCTION__);
-                               return WRONG_BUS_FREQUENCY;
-                       }
-
                        if (mode) { /* Bus - Mode 1 ECC */
-
-                               if (bus_speed > 0x7)  {
-                                       err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
-                                       return WRONG_BUS_FREQUENCY;
-                               }
-
-                               if ((bus_speed < 0x7) && (max_bus_speed <= 0x7) &&
-                                       (bus_speed < max_bus_speed) && (!slots_not_empty)) {
-
-                                       /* Wait for exclusive access to hardware */
-                                       down(&ctrl->crit_sect);
-
-                                       rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed);
-                                       if (rc) {
-                                               err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
-                                               /* Done with exclusive hardware access */
-                                               up(&ctrl->crit_sect);                           
-                                               return WRONG_BUS_FREQUENCY;
-                                       }
-                               
-                                       /* Wait for the command to complete */
-                                       wait_for_ctrl_irq (ctrl);
-               
-                                       rc = p_slot->hpc_ops->check_cmd_status(ctrl);
-                                       if (rc) {
-                                               err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
-                                                         __FUNCTION__);
-                                               err("%s: Error code (%d)\n", __FUNCTION__, rc);
-                                               /* Done with exclusive hardware access */
-                                               up(&ctrl->crit_sect);                           
-                                               return WRONG_BUS_FREQUENCY;
-                                       }
-                                       /* Done with exclusive hardware access */
-                                       up(&ctrl->crit_sect);
-                               }
+                               if ((bus_speed != 0x7) &&
+                                  ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
+                                       return rc;
                        } else {
-                               if (bus_speed > 0x4) {
-                                       err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
-                                       return WRONG_BUS_FREQUENCY;
-                               }
-
-                               if ((bus_speed < 0x4) && (max_bus_speed <= 0x4) &&
-                                       (bus_speed < max_bus_speed) && (!slots_not_empty)) {
-
-                                       /* Wait for exclusive access to hardware */
-                                       down(&ctrl->crit_sect);
-
-                                       rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed);
-                                       if (rc) {
-                                               err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
-                                               /* Done with exclusive hardware access */
-                                               up(&ctrl->crit_sect);                           
-                                               return WRONG_BUS_FREQUENCY;
-                                       }
-                               
-                                       /* Wait for the command to complete */
-                                       wait_for_ctrl_irq (ctrl);
-               
-                                       rc = p_slot->hpc_ops->check_cmd_status(ctrl);
-                                       if (rc) {
-                                               err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
-                                                         __FUNCTION__);
-                                               err("%s: Error code (%d)\n", __FUNCTION__, rc);
-                                               /* Done with exclusive hardware access */
-                                               up(&ctrl->crit_sect);                           
-                                               return WRONG_BUS_FREQUENCY;
-                                       }
-                                       /* Done with exclusive hardware access */
-                                       up(&ctrl->crit_sect);
-                               }
+                               if ((bus_speed != 0x4) &&
+                                  ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
+                                       return rc;
                        }
                        break;
                case PCI_SPEED_66MHz_PCIX_ECC:
                case PCI_SPEED_66MHz_PCIX:
-
-                       rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode);
-
-                       if (rc) {
-                               err("%s: PI is 1 \n", __FUNCTION__);
-                               return WRONG_BUS_FREQUENCY;
-                       }
-
                        if (mode) { /* Bus - Mode 1 ECC */
-
-                               if (bus_speed > 0x5)  {
-                                       err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
-                                       return WRONG_BUS_FREQUENCY;
-                               }
-
-                               if ((bus_speed < 0x5) && (max_bus_speed <= 0x5) &&
-                                       (bus_speed < max_bus_speed) && (!slots_not_empty)) {
-
-                                       /* Wait for exclusive access to hardware */
-                                       down(&ctrl->crit_sect);
-
-                                       rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed);
-                                       if (rc) {
-                                               err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
-                                               /* Done with exclusive hardware access */
-                                               up(&ctrl->crit_sect);                           
-                                               return WRONG_BUS_FREQUENCY;
-                                       }
-                               
-                                       /* Wait for the command to complete */
-                                       wait_for_ctrl_irq (ctrl);
-               
-                                       rc = p_slot->hpc_ops->check_cmd_status(ctrl);
-                                       if (rc) {
-                                               err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
-                                                         __FUNCTION__);
-                                               err("%s: Error code (%d)\n", __FUNCTION__, rc);
-                                               /* Done with exclusive hardware access */
-                                               up(&ctrl->crit_sect);                           
-                                               return WRONG_BUS_FREQUENCY;
-                                       }
-                                       /* Done with exclusive hardware access */
-                                       up(&ctrl->crit_sect);
-                               }
+                               if ((bus_speed != 0x5) &&
+                                  ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
+                                       return rc;
                        } else {
-                               if (bus_speed > 0x2) {
-                                       err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
-                                       return WRONG_BUS_FREQUENCY;
-                               }
-
-                               if ((bus_speed < 0x2) && (max_bus_speed <= 0x2) &&
-                                       (bus_speed < max_bus_speed) && (!slots_not_empty)) {
-
-                                       /* Wait for exclusive access to hardware */
-                                       down(&ctrl->crit_sect);
-
-                                       rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed);
-                                       if (rc) {
-                                               err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
-                                               /* Done with exclusive hardware access */
-                                               up(&ctrl->crit_sect);                           
-                                               return WRONG_BUS_FREQUENCY;
-                                       }
-                               
-                                       /* Wait for the command to complete */
-                                       wait_for_ctrl_irq (ctrl);
-               
-                                       rc = p_slot->hpc_ops->check_cmd_status(ctrl);
-                                       if (rc) {
-                                               err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
-                                                         __FUNCTION__);
-                                               err("%s: Error code (%d)\n", __FUNCTION__, rc);
-                                               /* Done with exclusive hardware access */
-                                               up(&ctrl->crit_sect);                           
-                                               return WRONG_BUS_FREQUENCY;
-                                       }
-                                       /* Done with exclusive hardware access */
-                                       up(&ctrl->crit_sect);
-                               }
+                               if ((bus_speed != 0x2) &&
+                                  ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
+                                       return rc;
                        }
                        break;
                case PCI_SPEED_66MHz:
-                       if (bus_speed > 0x1) {
-                               err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
-                               return WRONG_BUS_FREQUENCY;
-                       }
-                       if (bus_speed == 0x1)
-                               ;
-                       if ((bus_speed == 0x0) && ( max_bus_speed == 0x1))  {
-                               /* Wait for exclusive access to hardware */
-                               down(&ctrl->crit_sect);
-
-                               rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed);
-                               if (rc) {
-                                       err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
-                                       /* Done with exclusive hardware access */
-                                       up(&ctrl->crit_sect);                           
-                                       return WRONG_BUS_FREQUENCY;
-                               }
-                               
-                               /* Wait for the command to complete */
-                               wait_for_ctrl_irq (ctrl);
-               
-                               rc = p_slot->hpc_ops->check_cmd_status(ctrl);
-                               if (rc) {
-                                       err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
-                                                         __FUNCTION__);
-                                       err("%s: Error code (%d)\n", __FUNCTION__, rc);
-                                       /* Done with exclusive hardware access */
-                                       up(&ctrl->crit_sect);                           
-                                       return WRONG_BUS_FREQUENCY;
-                               }
-                               /* Done with exclusive hardware access */
-                               up(&ctrl->crit_sect);
-                       }
+                       if ((bus_speed != 0x1) &&
+                          ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) 
+                               return rc;
                        break;  
                case PCI_SPEED_33MHz:
                        if (bus_speed > 0x0) {
-                               err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
-                               return WRONG_BUS_FREQUENCY;
+                               if (slots_not_empty == 0) {
+                                       if ((rc = change_bus_speed(ctrl, p_slot, adapter_speed)))
+                                               return rc;
+                               } else {
+                                       err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
+                                       return WRONG_BUS_FREQUENCY;
+                               }
                        }
                        break;
                default:
@@ -1384,131 +1295,34 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
                        return WRONG_BUS_FREQUENCY;
                }
        } else {
-               /* if adpater_speed == bus_speed, nothing to do here */
-               if (adapter_speed != bus_speed) {
-                       for ( slot = 0; slot < ctrl->num_slots; slot++) {
-                               if (slot != hp_slot) {
-                                       pslot = shpchp_find_slot(ctrl, slot + ctrl->slot_device_offset);
-                                       t_func = shpchp_slot_find(pslot->bus, pslot->device, 0);
-                                       slots_not_empty |= t_func->is_a_board;
-                               }
-                       }
-
-                       if (slots_not_empty != 0) { /* Other slots on the same bus are occupied */
-                               if ( adapter_speed < bus_speed ) {
-                                       err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed);
-                                       return WRONG_BUS_FREQUENCY;
-                               }
-                               /* Do nothing if adapter_speed >= bus_speed */
-                       }
-               }
-                       
-               if ((adapter_speed != bus_speed) && (slots_not_empty == 0))  {
-                       /* Other slots on the same bus are empty */
-                       
-                       rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &max_bus_speed);
-                       if (rc || max_bus_speed == PCI_SPEED_UNKNOWN) {
-                               err("%s: Can't get max bus operation speed\n", __FUNCTION__);
-                               max_bus_speed = bus_speed;
-                       }
-
-                       if (max_bus_speed == bus_speed) {
-                               /* if adapter_speed >= bus_speed, do nothing */
-                               if (adapter_speed < bus_speed) {
-                               /* 
-                                * Try to lower bus speed to accommodate the adapter if other slots 
-                                * on the same controller are empty
-                                */
-                                       
-                                       /* Wait for exclusive access to hardware */
-                                       down(&ctrl->crit_sect);
-
-                                       rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, adapter_speed);
-                                       if (rc) {
-                                               err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
-                                               return WRONG_BUS_FREQUENCY;
-                                       }
-                               
-                                       /* Wait for the command to complete */
-                                       wait_for_ctrl_irq (ctrl);
-               
-                                       rc = p_slot->hpc_ops->check_cmd_status(ctrl);
-                                       if (rc) {
-                                               err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
-                                                                 __FUNCTION__);
-                                               err("%s: Error code (%d)\n", __FUNCTION__, rc);
-                                               return WRONG_BUS_FREQUENCY;
-                                       }
-                                       /* Done with exclusive hardware access */
-                                       up(&ctrl->crit_sect);
-
-                               } 
-                       } else {
-                               /* Wait for exclusive access to hardware */
-                               down(&ctrl->crit_sect);
-
-                               /* max_bus_speed != bus_speed. Note: max_bus_speed should be > than bus_speed */
-                               if (adapter_speed < max_bus_speed) 
-                                       rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, adapter_speed);
-                               else  
-                                       rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed);
-                               
-                               if (rc) {
-                                       err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
-                                       /* Done with exclusive hardware access */
-                                       up(&ctrl->crit_sect);
-                                       return WRONG_BUS_FREQUENCY;
-                               }
-                               
-                               /* Wait for the command to complete */
-                               wait_for_ctrl_irq (ctrl);
-               
-                               rc = p_slot->hpc_ops->check_cmd_status(ctrl);
-                               if (rc) {
-                                       err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", 
-                                               __FUNCTION__);
-                                       err("%s: Error code (%d)\n", __FUNCTION__, rc);
-                                       /* Done with exclusive hardware access */
-                                       up(&ctrl->crit_sect);
-                                       return WRONG_BUS_FREQUENCY;
-                               }
-                               /* Done with exclusive hardware access */
-                               up(&ctrl->crit_sect);
-
-                       }
-               }
+               /* If adpater_speed == bus_speed, nothing to do here */
+               dbg("%s: In PI = %d\n", __FUNCTION__, pi);
+               if ((adapter_speed != bus_speed) &&
+                  ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed))))
+                               return rc;
        }
 
-       /* Wait for exclusive access to hardware */
        down(&ctrl->crit_sect);
-
        /* turn on board, blink green LED, turn off Amber LED */
-       rc = p_slot->hpc_ops->slot_enable(p_slot);
-       
-       if (rc) {
+       if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
                err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
-               /* Done with exclusive hardware access */
                up(&ctrl->crit_sect);
                return rc;
        }
-       /* Wait for the command to complete */
        wait_for_ctrl_irq (ctrl);
 
-       rc = p_slot->hpc_ops->check_cmd_status(ctrl);
-       if (rc) {
+       if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
                err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc);
-               /* Done with exclusive hardware access */
                up(&ctrl->crit_sect);
                return rc;  
        }
 
-       /* Done with exclusive hardware access */
        up(&ctrl->crit_sect);
 
        /* Wait for ~1 second */
        dbg("%s: before long_delay\n", __FUNCTION__);
        wait_for_ctrl_irq (ctrl);
-       dbg("%s: afterlong_delay\n", __FUNCTION__);
+       dbg("%s: after long_delay\n", __FUNCTION__);
 
        dbg("%s: func status = %x\n", __FUNCTION__, func->status);
        /* Check for a power fault */
@@ -1572,7 +1386,7 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
 
                        retval = p_slot->hpc_ops->check_cmd_status(ctrl);
                        if (retval) {
-                               err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc);
+                               err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, retval);
                                /* Done with exclusive hardware access */
                                up(&ctrl->crit_sect);
                                return retval;  
@@ -1588,8 +1402,9 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
                func->status = 0;
                func->switch_save = 0x10;
                func->is_a_board = 0x01;
+               func->pwr_save = 1;
 
-               /* next, we will instantiate the linux pci_dev structures 
+               /* Next, we will instantiate the linux pci_dev structures 
                 * (with appropriate driver notification, if already present) 
                 */
                index = 0;
@@ -1780,6 +1595,7 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl)
                func->function = 0;
                func->configured = 0;
                func->switch_save = 0x10;
+               func->pwr_save = 0;
                func->is_a_board = 0;
        }
 
@@ -1795,6 +1611,55 @@ static void pushbutton_helper_thread (unsigned long data)
 }
 
 
+/**
+ * shpchp_pushbutton_thread
+ *
+ * Scheduled procedure to handle blocking stuff for the pushbuttons
+ * Handles all pending events and exits.
+ *
+ */
+static void shpchp_pushbutton_thread (unsigned long slot)
+{
+       struct slot *p_slot = (struct slot *) slot;
+       u8 getstatus;
+       
+       pushbutton_pending = 0;
+
+       if (!p_slot) {
+               dbg("%s: Error! slot NULL\n", __FUNCTION__);
+               return;
+       }
+
+       p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+       if (getstatus) {
+               p_slot->state = POWEROFF_STATE;
+               dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
+
+               shpchp_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 (shpchp_enable_slot(p_slot)) {
+                       /* Wait for exclusive access to hardware */
+                       down(&p_slot->ctrl->crit_sect);
+
+                       p_slot->hpc_ops->green_led_off(p_slot);
+
+                       /* Wait for the command to complete */
+                       wait_for_ctrl_irq (p_slot->ctrl);
+
+                       /* Done with exclusive hardware access */
+                       up(&p_slot->ctrl->crit_sect);
+               }
+               p_slot->state = STATIC_STATE;
+       }
+
+       return;
+}
+
+
 /* this is the main worker thread */
 static int event_thread(void* data)
 {
@@ -1830,7 +1695,7 @@ int shpchp_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");
@@ -1856,7 +1721,7 @@ static int update_slot_info (struct slot *slot)
        struct hotplug_slot_info *info;
        int result;
 
-       info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
+       info = kmalloc(sizeof(*info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
 
@@ -2011,81 +1876,6 @@ static void interrupt_event_handler(struct controller *ctrl)
 }
 
 
-/**
- * shpchp_pushbutton_thread
- *
- * Scheduled procedure to handle blocking stuff for the pushbuttons
- * Handles all pending events and exits.
- *
- */
-void shpchp_pushbutton_thread (unsigned long slot)
-{
-       struct slot *p_slot = (struct slot *) slot;
-       u8 getstatus;
-       int rc;
-       
-       pushbutton_pending = 0;
-
-       if (!p_slot) {
-               dbg("%s: Error! slot NULL\n", __FUNCTION__);
-               return;
-       }
-
-       p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
-       if (getstatus) {
-               p_slot->state = POWEROFF_STATE;
-               dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
-
-               if (shpchp_disable_slot(p_slot)) {
-                       /* 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;
-                       }
-       
-                       /* Wait for the command to complete */
-                       wait_for_ctrl_irq (p_slot->ctrl);
-
-                       /* Done with exclusive hardware access */
-                       up(&p_slot->ctrl->crit_sect);
-               }
-               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 (shpchp_enable_slot(p_slot)) {
-                       /* 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 */
-                       wait_for_ctrl_irq (p_slot->ctrl);
-
-                       /* Done with exclusive hardware access */
-                       up(&p_slot->ctrl->crit_sect);
-               }
-               p_slot->state = STATIC_STATE;
-       }
-
-       return;
-}
-
-
 int shpchp_enable_slot (struct slot *p_slot)
 {
        u8 getstatus = 0;
@@ -2095,7 +1885,7 @@ int shpchp_enable_slot (struct slot *p_slot)
        func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
        if (!func) {
                dbg("%s: Error! slot NULL\n", __FUNCTION__);
-               return (1);
+               return 1;
        }
 
        /* Check to see if (latch closed, card present, power off) */
@@ -2104,19 +1894,19 @@ int shpchp_enable_slot (struct slot *p_slot)
        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);
+               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);
+               return 1;
        }
        up(&p_slot->ctrl->crit_sect);
 
@@ -2124,7 +1914,7 @@ int shpchp_enable_slot (struct slot *p_slot)
 
        func = shpchp_slot_create(p_slot->bus);
        if (func == NULL)
-               return (1);
+               return 1;
 
        func->bus = p_slot->bus;
        func->device = p_slot->device;
@@ -2134,6 +1924,8 @@ int shpchp_enable_slot (struct slot *p_slot)
 
        /* We have to save the presence info for these slots */
        p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+       p_slot->hpc_ops->get_power_status(p_slot, &(func->pwr_save));
+       dbg("%s: func->pwr_save %x\n", __FUNCTION__, func->pwr_save);
        p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
        func->switch_save = !getstatus? 0x10:0;
 
@@ -2176,11 +1968,13 @@ int shpchp_disable_slot (struct slot *p_slot)
        u32 rc = 0;
        int ret = 0;
        unsigned int devfn;
-       struct pci_bus *pci_bus = p_slot->ctrl->pci_dev->subordinate;
+       struct pci_bus *pci_bus;
        struct pci_func *func;
 
        if (!p_slot->ctrl)
-               return (1);
+               return 1;
+
+       pci_bus = p_slot->ctrl->pci_dev->subordinate;
 
        /* Check to see if (latch closed, card present, power on) */
        down(&p_slot->ctrl->crit_sect);
@@ -2189,19 +1983,19 @@ int shpchp_disable_slot (struct slot *p_slot)
        if (ret || !getstatus) {
                info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
                up(&p_slot->ctrl->crit_sect);
-               return (0);
+               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);
+               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);
+               return 1;
        }
        up(&p_slot->ctrl->crit_sect);
 
@@ -2504,22 +2298,18 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f
                /* Make copies of the nodes we are going to pass down so that
                 * if there is a problem,we can just use these to free resources
                 */
-               hold_bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-               hold_IO_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-               hold_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-               hold_p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+               hold_bus_node = kmalloc(sizeof(*hold_bus_node), GFP_KERNEL);
+               hold_IO_node = kmalloc(sizeof(*hold_IO_node), GFP_KERNEL);
+               hold_mem_node = kmalloc(sizeof(*hold_mem_node), GFP_KERNEL);
+               hold_p_mem_node = kmalloc(sizeof(*hold_p_mem_node), GFP_KERNEL);
 
                if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) {
-                       if (hold_bus_node)
-                               kfree(hold_bus_node);
-                       if (hold_IO_node)
-                               kfree(hold_IO_node);
-                       if (hold_mem_node)
-                               kfree(hold_mem_node);
-                       if (hold_p_mem_node)
-                               kfree(hold_p_mem_node);
+                       kfree(hold_bus_node);
+                       kfree(hold_IO_node);
+                       kfree(hold_mem_node);
+                       kfree(hold_p_mem_node);
 
-                       return(1);
+                       return 1;
                }
 
                memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource));
@@ -2538,11 +2328,11 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f
                        /* set IO base and Limit registers */
                        RES_CHECK(io_node->base, 8);
                        temp_byte = (u8)(io_node->base >> 8);
-                       rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte);
+                       rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte);
 
                        RES_CHECK(io_node->base + io_node->length - 1, 8);
                        temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8);
-                       rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
+                       rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
                } else {
                        kfree(hold_IO_node);
                        hold_IO_node = NULL;
@@ -2559,17 +2349,17 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f
                        /* set Mem base and Limit registers */
                        RES_CHECK(mem_node->base, 16);
                        temp_word = (u32)(mem_node->base >> 16);
-                       rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
 
                        RES_CHECK(mem_node->base + mem_node->length - 1, 16);
                        temp_word = (u32)((mem_node->base + mem_node->length - 1) >> 16);
-                       rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
                } else {
                        temp_word = 0xFFFF;
-                       rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
 
                        temp_word = 0x0000;
-                       rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
 
                        kfree(hold_mem_node);
                        hold_mem_node = NULL;
@@ -2586,17 +2376,17 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f
                        /* set Pre Mem base and Limit registers */
                        RES_CHECK(p_mem_node->base, 16);
                        temp_word = (u32)(p_mem_node->base >> 16);
-                       rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
+                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
 
                        RES_CHECK(p_mem_node->base + p_mem_node->length - 1, 16);
                        temp_word = (u32)((p_mem_node->base + p_mem_node->length - 1) >> 16);
-                       rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
                } else {
                        temp_word = 0xFFFF;
-                       rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
+                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
 
                        temp_word = 0x0000;
-                       rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+                       rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
 
                        kfree(hold_p_mem_node);
                        hold_p_mem_node = NULL;
@@ -2613,7 +2403,8 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f
 
                        ID = 0xFFFFFFFF;
                        pci_bus->number = hold_bus_node->base;
-                       pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
+                       pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0),
+                                       PCI_VENDOR_ID, &ID);
                        pci_bus->number = func->bus;
 
                        if (ID != 0xFFFFFFFF) {   /*  device Present */