vserver 1.9.3
[linux-2.6.git] / drivers / pci / hotplug / shpchp_ctrl.c
index 09d2d1b..d71925c 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);
@@ -1426,6 +1433,7 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
                                        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__);
+                                               up(&ctrl->crit_sect);
                                                return WRONG_BUS_FREQUENCY;
                                        }
                                
@@ -1437,6 +1445,7 @@ static u32 board_added(struct pci_func * func, struct controller * 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;
                                        }
                                        /* Done with exclusive hardware access */
@@ -1572,7 +1581,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 +1597,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 +1790,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 +1806,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 +1890,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 +1916,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 +2071,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 +2080,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 +2089,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 +2109,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 +2119,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 +2163,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 +2178,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 +2493,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 +2523,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 +2544,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 +2571,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 +2598,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 */