diff options
Diffstat (limited to 'drivers/pci/hotplug/cpqphp_core.c')
| -rw-r--r-- | drivers/pci/hotplug/cpqphp_core.c | 1232 |
1 files changed, 588 insertions, 644 deletions
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 9aed8efe6a1..4aaee746df8 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -25,11 +25,9 @@ * Send feedback to <greg@kroah.com> * * Jan 12, 2003 - Added 66/100/133MHz PCI-X support, - * Torben Mathiasen <torben.mathiasen@hp.com> - * + * Torben Mathiasen <torben.mathiasen@hp.com> */ -#include <linux/config.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> @@ -38,6 +36,7 @@ #include <linux/slab.h> #include <linux/workqueue.h> #include <linux/pci.h> +#include <linux/pci_hotplug.h> #include <linux/init.h> #include <linux/interrupt.h> @@ -45,7 +44,6 @@ #include "cpqphp.h" #include "cpqphp_nvram.h" -#include "../../../arch/i386/pci/pci.h" /* horrible hack showing how processor dependent we are... */ /* Global variables */ @@ -53,13 +51,14 @@ int cpqhp_debug; int cpqhp_legacy_mode; struct controller *cpqhp_ctrl_list; /* = NULL */ struct pci_func *cpqhp_slot_list[256]; +struct irq_routing_table *cpqhp_routing_table; /* local variables */ static void __iomem *smbios_table; static void __iomem *smbios_start; static void __iomem *cpqhp_rom_start; -static int power_mode; -static int debug; +static bool power_mode; +static bool debug; static int initialized; #define DRIVER_VERSION "0.9.8" @@ -78,33 +77,6 @@ MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); #define CPQHPC_MODULE_MINOR 208 -static int one_time_init (void); -static int set_attention_status (struct hotplug_slot *slot, u8 value); -static int process_SI (struct hotplug_slot *slot); -static int process_SS (struct hotplug_slot *slot); -static int hardware_test (struct hotplug_slot *slot, u32 value); -static int get_power_status (struct hotplug_slot *slot, u8 *value); -static int get_attention_status (struct hotplug_slot *slot, u8 *value); -static int get_latch_status (struct hotplug_slot *slot, u8 *value); -static int get_adapter_status (struct hotplug_slot *slot, u8 *value); -static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); -static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); - -static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = { - .owner = THIS_MODULE, - .set_attention_status = set_attention_status, - .enable_slot = process_SI, - .disable_slot = process_SS, - .hardware_test = hardware_test, - .get_power_status = get_power_status, - .get_attention_status = get_attention_status, - .get_latch_status = get_latch_status, - .get_adapter_status = get_adapter_status, - .get_max_bus_speed = get_max_bus_speed, - .get_cur_bus_speed = get_cur_bus_speed, -}; - - static inline int is_slot64bit(struct slot *slot) { return (readb(slot->p_sm_slot + SMBIOS_SLOT_WIDTH) == 0x06) ? 1 : 0; @@ -117,14 +89,12 @@ static inline int is_slot66mhz(struct slot *slot) /** * detect_SMBIOS_pointer - find the System Management BIOS Table in mem region. - * * @begin: begin pointer for region to be scanned. * @end: end pointer for region to be scanned. * - * Returns pointer to the head of the SMBIOS tables (or NULL) - * + * Returns pointer to the head of the SMBIOS tables (or %NULL). */ -static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *end) +static void __iomem *detect_SMBIOS_pointer(void __iomem *begin, void __iomem *end) { void __iomem *fp; void __iomem *endp; @@ -146,7 +116,7 @@ static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *e break; } } - + if (!status) fp = NULL; @@ -157,11 +127,11 @@ static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *e /** * init_SERR - Initializes the per slot SERR generation. + * @ctrl: controller to use * * For unexpected switch opens - * */ -static int init_SERR(struct controller * ctrl) +static int init_SERR(struct controller *ctrl) { u32 tempdword; u32 number_of_slots; @@ -173,7 +143,7 @@ static int init_SERR(struct controller * ctrl) tempdword = ctrl->first_slot; number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; - // Loop through slots + /* Loop through slots */ while (number_of_slots) { physical_slot = tempdword; writeb(0, ctrl->hpc_reg + SLOT_SERR); @@ -184,54 +154,56 @@ static int init_SERR(struct controller * ctrl) return 0; } - -/* nice debugging output */ -static int pci_print_IRQ_route (void) +static int init_cpqhp_routing_table(void) { - struct irq_routing_table *routing_table; int len; - int loop; - - u8 tbus, tdevice, tslot; - routing_table = pcibios_get_irq_routing_table(); - if (routing_table == NULL) { - err("No BIOS Routing Table??? Not good\n"); + cpqhp_routing_table = pcibios_get_irq_routing_table(); + if (cpqhp_routing_table == NULL) return -ENOMEM; - } - len = (routing_table->size - sizeof(struct irq_routing_table)) / - sizeof(struct irq_info); - // Make sure I got at least one entry + len = cpqhp_routing_table_length(); if (len == 0) { - kfree(routing_table); + kfree(cpqhp_routing_table); + cpqhp_routing_table = NULL; return -1; } - dbg("bus dev func slot\n"); + return 0; +} + +/* nice debugging output */ +static void pci_print_IRQ_route(void) +{ + int len; + int loop; + u8 tbus, tdevice, tslot; + + len = cpqhp_routing_table_length(); + dbg("bus dev func slot\n"); for (loop = 0; loop < len; ++loop) { - tbus = routing_table->slots[loop].bus; - tdevice = routing_table->slots[loop].devfn; - tslot = routing_table->slots[loop].slot; + tbus = cpqhp_routing_table->slots[loop].bus; + tdevice = cpqhp_routing_table->slots[loop].devfn; + tslot = cpqhp_routing_table->slots[loop].slot; dbg("%d %d %d %d\n", tbus, tdevice >> 3, tdevice & 0x7, tslot); } - kfree(routing_table); - return 0; + return; } /** * get_subsequent_smbios_entry: get the next entry from bios table. - * - * Gets the first entry if previous == NULL - * Otherwise, returns the next entry - * Uses global SMBIOS Table pointer - * + * @smbios_start: where to start in the SMBIOS table + * @smbios_table: location of the SMBIOS table * @curr: %NULL or pointer to previously returned structure * - * returns a pointer to an SMBIOS structure or NULL if none found + * Gets the first entry if previous == NULL; + * otherwise, returns the next entry. + * Uses global SMBIOS Table pointer. + * + * Returns a pointer to an SMBIOS structure or NULL if none found. */ static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start, void __iomem *smbios_table, @@ -243,9 +215,9 @@ static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start, void __iomem *p_max; if (!smbios_table || !curr) - return(NULL); + return NULL; - // set p_max to the end of the table + /* set p_max to the end of the table */ p_max = smbios_start + readw(smbios_table + ST_LENGTH); p_temp = curr; @@ -254,35 +226,35 @@ static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start, while ((p_temp < p_max) && !bail) { /* Look for the double NULL terminator * The first condition is the previous byte - * and the second is the curr */ - if (!previous_byte && !(readb(p_temp))) { + * and the second is the curr + */ + if (!previous_byte && !(readb(p_temp))) bail = 1; - } previous_byte = readb(p_temp); p_temp++; } - if (p_temp < p_max) { + if (p_temp < p_max) return p_temp; - } else { + else return NULL; - } } /** - * get_SMBIOS_entry - * - * @type:SMBIOS structure type to be returned + * get_SMBIOS_entry - return the requested SMBIOS entry or %NULL + * @smbios_start: where to start in the SMBIOS table + * @smbios_table: location of the SMBIOS table + * @type: SMBIOS structure type to be returned * @previous: %NULL or pointer to previously returned structure * - * Gets the first entry of the specified type if previous == NULL + * Gets the first entry of the specified type if previous == %NULL; * Otherwise, returns the next entry of the given type. - * Uses global SMBIOS Table pointer - * Uses get_subsequent_smbios_entry + * Uses global SMBIOS Table pointer. + * Uses get_subsequent_smbios_entry. * - * returns a pointer to an SMBIOS structure or %NULL if none found + * Returns a pointer to an SMBIOS structure or %NULL if none found. */ static void __iomem *get_SMBIOS_entry(void __iomem *smbios_start, void __iomem *smbios_table, @@ -292,21 +264,18 @@ static void __iomem *get_SMBIOS_entry(void __iomem *smbios_start, if (!smbios_table) return NULL; - if (!previous) { + if (!previous) previous = smbios_start; - } else { + else previous = get_subsequent_smbios_entry(smbios_start, smbios_table, previous); - } - while (previous) { - if (readb(previous + SMBIOS_GENERIC_TYPE) != type) { + while (previous) + if (readb(previous + SMBIOS_GENERIC_TYPE) != type) previous = get_subsequent_smbios_entry(smbios_start, smbios_table, previous); - } else { + else break; - } - } return previous; } @@ -315,144 +284,14 @@ static void release_slot(struct hotplug_slot *hotplug_slot) { struct slot *slot = hotplug_slot->private; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); kfree(slot); } -static int ctrl_slot_setup(struct controller *ctrl, - void __iomem *smbios_start, - void __iomem *smbios_table) -{ - struct slot *new_slot; - u8 number_of_slots; - u8 slot_device; - u8 slot_number; - u8 ctrl_slot; - u32 tempdword; - void __iomem *slot_entry= NULL; - int result = -ENOMEM; - - dbg("%s\n", __FUNCTION__); - - tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); - - number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; - slot_device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4; - slot_number = ctrl->first_slot; - - while (number_of_slots) { - new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL); - if (!new_slot) - goto error; - - memset(new_slot, 0, sizeof(struct slot)); - new_slot->hotplug_slot = kmalloc(sizeof(*(new_slot->hotplug_slot)), - GFP_KERNEL); - if (!new_slot->hotplug_slot) - goto error_slot; - memset(new_slot->hotplug_slot, 0, sizeof(struct hotplug_slot)); - - new_slot->hotplug_slot->info = - kmalloc(sizeof(*(new_slot->hotplug_slot->info)), - GFP_KERNEL); - if (!new_slot->hotplug_slot->info) - goto error_hpslot; - memset(new_slot->hotplug_slot->info, 0, - sizeof(struct hotplug_slot_info)); - new_slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); - if (!new_slot->hotplug_slot->name) - goto error_info; - - new_slot->ctrl = ctrl; - new_slot->bus = ctrl->bus; - new_slot->device = slot_device; - new_slot->number = slot_number; - dbg("slot->number = %d\n",new_slot->number); - - slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, - slot_entry); - - while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) != new_slot->number)) { - slot_entry = get_SMBIOS_entry(smbios_start, - smbios_table, 9, slot_entry); - } - - new_slot->p_sm_slot = slot_entry; - - init_timer(&new_slot->task_event); - new_slot->task_event.expires = jiffies + 5 * HZ; - new_slot->task_event.function = cpqhp_pushbutton_thread; - - //FIXME: these capabilities aren't used but if they are - // they need to be correctly implemented - new_slot->capabilities |= PCISLOT_REPLACE_SUPPORTED; - new_slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED; - - if (is_slot64bit(new_slot)) - new_slot->capabilities |= PCISLOT_64_BIT_SUPPORTED; - if (is_slot66mhz(new_slot)) - new_slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED; - if (ctrl->speed == PCI_SPEED_66MHz) - new_slot->capabilities |= PCISLOT_66_MHZ_OPERATION; - - ctrl_slot = slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4); - - // Check presence - new_slot->capabilities |= ((((~tempdword) >> 23) | ((~tempdword) >> 15)) >> ctrl_slot) & 0x02; - // Check the switch state - new_slot->capabilities |= ((~tempdword & 0xFF) >> ctrl_slot) & 0x01; - // Check the slot enable - new_slot->capabilities |= ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04; - - /* register this slot with the hotplug pci core */ - new_slot->hotplug_slot->release = &release_slot; - new_slot->hotplug_slot->private = new_slot; - make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot); - new_slot->hotplug_slot->ops = &cpqphp_hotplug_slot_ops; - - new_slot->hotplug_slot->info->power_status = get_slot_enabled(ctrl, new_slot); - new_slot->hotplug_slot->info->attention_status = cpq_get_attention_status(ctrl, new_slot); - new_slot->hotplug_slot->info->latch_status = cpq_get_latch_status(ctrl, new_slot); - new_slot->hotplug_slot->info->adapter_status = get_presence_status(ctrl, new_slot); - - dbg ("registering bus %d, dev %d, number %d, " - "ctrl->slot_device_offset %d, slot %d\n", - new_slot->bus, new_slot->device, - new_slot->number, ctrl->slot_device_offset, - slot_number); - result = pci_hp_register (new_slot->hotplug_slot); - if (result) { - err ("pci_hp_register failed with error %d\n", result); - goto error_name; - } - - new_slot->next = ctrl->slot; - ctrl->slot = new_slot; - - number_of_slots--; - slot_device++; - slot_number++; - } - - return 0; - -error_name: - kfree(new_slot->hotplug_slot->name); -error_info: - kfree(new_slot->hotplug_slot->info); -error_hpslot: - kfree(new_slot->hotplug_slot); -error_slot: - kfree(new_slot); -error: - return result; -} - -static int ctrl_slot_cleanup (struct controller * ctrl) +static int ctrl_slot_cleanup (struct controller *ctrl) { struct slot *old_slot, *next_slot; @@ -466,111 +305,98 @@ static int ctrl_slot_cleanup (struct controller * ctrl) old_slot = next_slot; } - //Free IRQ associated with hot plug device + cpqhp_remove_debugfs_files(ctrl); + + /* Free IRQ associated with hot plug device */ free_irq(ctrl->interrupt, ctrl); - //Unmap the memory + /* Unmap the memory */ iounmap(ctrl->hpc_reg); - //Finally reclaim PCI mem + /* Finally reclaim PCI mem */ release_mem_region(pci_resource_start(ctrl->pci_dev, 0), pci_resource_len(ctrl->pci_dev, 0)); - return(0); + return 0; } -//============================================================================ -// function: get_slot_mapping -// -// Description: Attempts to determine a logical slot mapping for a PCI -// device. Won't work for more than one PCI-PCI bridge -// in a slot. -// -// Input: u8 bus_num - bus number of PCI device -// u8 dev_num - device number of PCI device -// u8 *slot - Pointer to u8 where slot number will -// be returned -// -// Output: SUCCESS or FAILURE -//============================================================================= +/** + * get_slot_mapping - determine logical slot mapping for PCI device + * + * Won't work for more than one PCI-PCI bridge in a slot. + * + * @bus_num - bus number of PCI device + * @dev_num - device number of PCI device + * @slot - Pointer to u8 where slot number will be returned + * + * Output: SUCCESS or FAILURE + */ static int get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot) { - struct irq_routing_table *PCIIRQRoutingInfoLength; u32 work; long len; long loop; u8 tbus, tdevice, tslot, bridgeSlot; - dbg("%s: %p, %d, %d, %p\n", __FUNCTION__, bus, bus_num, dev_num, slot); + dbg("%s: %p, %d, %d, %p\n", __func__, bus, bus_num, dev_num, slot); bridgeSlot = 0xFF; - PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table(); - if (!PCIIRQRoutingInfoLength) - return -1; - - len = (PCIIRQRoutingInfoLength->size - - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); - // Make sure I got at least one entry - if (len == 0) { - kfree(PCIIRQRoutingInfoLength); - return -1; - } - + len = cpqhp_routing_table_length(); for (loop = 0; loop < len; ++loop) { - tbus = PCIIRQRoutingInfoLength->slots[loop].bus; - tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn >> 3; - tslot = PCIIRQRoutingInfoLength->slots[loop].slot; + tbus = cpqhp_routing_table->slots[loop].bus; + tdevice = cpqhp_routing_table->slots[loop].devfn >> 3; + tslot = cpqhp_routing_table->slots[loop].slot; if ((tbus == bus_num) && (tdevice == dev_num)) { *slot = tslot; - kfree(PCIIRQRoutingInfoLength); return 0; } else { /* Did not get a match on the target PCI device. Check - * if the current IRQ table entry is a PCI-to-PCI bridge - * device. If so, and it's secondary bus matches the - * bus number for the target device, I need to save the - * bridge's slot number. If I can not find an entry for - * the target device, I will have to assume it's on the - * other side of the bridge, and assign it the bridge's - * slot. */ + * if the current IRQ table entry is a PCI-to-PCI + * bridge device. If so, and it's secondary bus + * matches the bus number for the target device, I need + * to save the bridge's slot number. If I can not find + * an entry for the target device, I will have to + * assume it's on the other side of the bridge, and + * assign it the bridge's slot. + */ bus->number = tbus; pci_bus_read_config_dword(bus, PCI_DEVFN(tdevice, 0), - PCI_REVISION_ID, &work); + PCI_CLASS_REVISION, &work); if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) { pci_bus_read_config_dword(bus, PCI_DEVFN(tdevice, 0), PCI_PRIMARY_BUS, &work); // See if bridge's secondary bus matches target bus. - if (((work >> 8) & 0x000000FF) == (long) bus_num) { + if (((work >> 8) & 0x000000FF) == (long) bus_num) bridgeSlot = tslot; - } } } } - // If we got here, we didn't find an entry in the IRQ mapping table - // for the target PCI device. If we did determine that the target - // device is on the other side of a PCI-to-PCI bridge, return the - // slot number for the bridge. + /* If we got here, we didn't find an entry in the IRQ mapping table for + * the target PCI device. If we did determine that the target device + * is on the other side of a PCI-to-PCI bridge, return the slot number + * for the bridge. + */ if (bridgeSlot != 0xFF) { *slot = bridgeSlot; - kfree(PCIIRQRoutingInfoLength); return 0; } - kfree(PCIIRQRoutingInfoLength); - // Couldn't find an entry in the routing table for this PCI device + /* Couldn't find an entry in the routing table for this PCI device */ return -1; } /** * cpqhp_set_attention_status - Turns the Amber LED for a slot on or off - * + * @ctrl: struct controller to use + * @func: PCI device/function info + * @status: LED control flag: 1 = LED on, 0 = LED off */ static int cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, @@ -579,38 +405,39 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, u8 hp_slot; if (func == NULL) - return(1); + return 1; hp_slot = func->device - ctrl->slot_device_offset; - // Wait for exclusive access to hardware - down(&ctrl->crit_sect); + /* Wait for exclusive access to hardware */ + mutex_lock(&ctrl->crit_sect); - if (status == 1) { + if (status == 1) amber_LED_on (ctrl, hp_slot); - } else if (status == 0) { + else if (status == 0) amber_LED_off (ctrl, hp_slot); - } else { - // Done with exclusive hardware access - up(&ctrl->crit_sect); - return(1); + else { + /* Done with exclusive hardware access */ + mutex_unlock(&ctrl->crit_sect); + return 1; } set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - // Done with exclusive hardware access - up(&ctrl->crit_sect); + /* Done with exclusive hardware access */ + mutex_unlock(&ctrl->crit_sect); - return(0); + return 0; } /** * set_attention_status - Turns the Amber LED for a slot on or off - * + * @hotplug_slot: slot to change LED on + * @status: LED control flag */ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) { @@ -622,7 +449,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) u8 device; u8 function; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1) return -ENODEV; @@ -649,7 +476,7 @@ static int process_SI(struct hotplug_slot *hotplug_slot) u8 device; u8 function; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1) return -ENODEV; @@ -681,7 +508,7 @@ static int process_SS(struct hotplug_slot *hotplug_slot) u8 device; u8 function; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1) return -ENODEV; @@ -694,7 +521,7 @@ static int process_SS(struct hotplug_slot *hotplug_slot) if (!slot_func) return -ENODEV; - dbg("In %s, slot_func = %p, ctrl = %p\n", __FUNCTION__, slot_func, ctrl); + dbg("In %s, slot_func = %p, ctrl = %p\n", __func__, slot_func, ctrl); return cpqhp_process_SS(ctrl, slot_func); } @@ -704,9 +531,9 @@ static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value) struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); - return cpqhp_hardware_test(ctrl, value); + return cpqhp_hardware_test(ctrl, value); } @@ -715,7 +542,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); *value = get_slot_enabled(ctrl, slot); return 0; @@ -725,8 +552,8 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) { struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; - - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); *value = cpq_get_attention_status(ctrl, slot); return 0; @@ -737,7 +564,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); *value = cpq_get_latch_status(ctrl, slot); @@ -749,35 +576,239 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) struct slot *slot = hotplug_slot->private; struct controller *ctrl = slot->ctrl; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); *value = get_presence_status(ctrl, slot); return 0; } -static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) +static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = { + .set_attention_status = set_attention_status, + .enable_slot = process_SI, + .disable_slot = process_SS, + .hardware_test = hardware_test, + .get_power_status = get_power_status, + .get_attention_status = get_attention_status, + .get_latch_status = get_latch_status, + .get_adapter_status = get_adapter_status, +}; + +#define SLOT_NAME_SIZE 10 + +static int ctrl_slot_setup(struct controller *ctrl, + void __iomem *smbios_start, + void __iomem *smbios_table) { - struct slot *slot = hotplug_slot->private; - struct controller *ctrl = slot->ctrl; + struct slot *slot; + struct hotplug_slot *hotplug_slot; + struct hotplug_slot_info *hotplug_slot_info; + struct pci_bus *bus = ctrl->pci_bus; + u8 number_of_slots; + u8 slot_device; + u8 slot_number; + u8 ctrl_slot; + u32 tempdword; + char name[SLOT_NAME_SIZE]; + void __iomem *slot_entry= NULL; + int result; + + dbg("%s\n", __func__); - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); - *value = ctrl->speed_capability; + number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; + slot_device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4; + slot_number = ctrl->first_slot; + + while (number_of_slots) { + slot = kzalloc(sizeof(*slot), GFP_KERNEL); + if (!slot) { + result = -ENOMEM; + goto error; + } + + slot->hotplug_slot = kzalloc(sizeof(*(slot->hotplug_slot)), + GFP_KERNEL); + if (!slot->hotplug_slot) { + result = -ENOMEM; + goto error_slot; + } + hotplug_slot = slot->hotplug_slot; + + hotplug_slot->info = kzalloc(sizeof(*(hotplug_slot->info)), + GFP_KERNEL); + if (!hotplug_slot->info) { + result = -ENOMEM; + goto error_hpslot; + } + hotplug_slot_info = hotplug_slot->info; + + slot->ctrl = ctrl; + slot->bus = ctrl->bus; + slot->device = slot_device; + slot->number = slot_number; + dbg("slot->number = %u\n", slot->number); + + slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, + slot_entry); + + while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) != + slot->number)) { + slot_entry = get_SMBIOS_entry(smbios_start, + smbios_table, 9, slot_entry); + } + + slot->p_sm_slot = slot_entry; + + init_timer(&slot->task_event); + slot->task_event.expires = jiffies + 5 * HZ; + slot->task_event.function = cpqhp_pushbutton_thread; + + /*FIXME: these capabilities aren't used but if they are + * they need to be correctly implemented + */ + slot->capabilities |= PCISLOT_REPLACE_SUPPORTED; + slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED; + + if (is_slot64bit(slot)) + slot->capabilities |= PCISLOT_64_BIT_SUPPORTED; + if (is_slot66mhz(slot)) + slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED; + if (bus->cur_bus_speed == PCI_SPEED_66MHz) + slot->capabilities |= PCISLOT_66_MHZ_OPERATION; + + ctrl_slot = + slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4); + + /* Check presence */ + slot->capabilities |= + ((((~tempdword) >> 23) | + ((~tempdword) >> 15)) >> ctrl_slot) & 0x02; + /* Check the switch state */ + slot->capabilities |= + ((~tempdword & 0xFF) >> ctrl_slot) & 0x01; + /* Check the slot enable */ + slot->capabilities |= + ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04; + + /* register this slot with the hotplug pci core */ + hotplug_slot->release = &release_slot; + hotplug_slot->private = slot; + snprintf(name, SLOT_NAME_SIZE, "%u", slot->number); + hotplug_slot->ops = &cpqphp_hotplug_slot_ops; + + hotplug_slot_info->power_status = get_slot_enabled(ctrl, slot); + hotplug_slot_info->attention_status = + cpq_get_attention_status(ctrl, slot); + hotplug_slot_info->latch_status = + cpq_get_latch_status(ctrl, slot); + hotplug_slot_info->adapter_status = + get_presence_status(ctrl, slot); + + dbg("registering bus %d, dev %d, number %d, ctrl->slot_device_offset %d, slot %d\n", + slot->bus, slot->device, + slot->number, ctrl->slot_device_offset, + slot_number); + result = pci_hp_register(hotplug_slot, + ctrl->pci_dev->bus, + slot->device, + name); + if (result) { + err("pci_hp_register failed with error %d\n", result); + goto error_info; + } + + slot->next = ctrl->slot; + ctrl->slot = slot; + + number_of_slots--; + slot_device++; + slot_number++; + } return 0; +error_info: + kfree(hotplug_slot_info); +error_hpslot: + kfree(hotplug_slot); +error_slot: + kfree(slot); +error: + return result; } -static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) +static int one_time_init(void) { - struct slot *slot = hotplug_slot->private; - struct controller *ctrl = slot->ctrl; + int loop; + int retval = 0; - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + if (initialized) + return 0; - *value = ctrl->speed; + power_mode = 0; - return 0; + retval = init_cpqhp_routing_table(); + if (retval) + goto error; + + if (cpqhp_debug) + pci_print_IRQ_route(); + + dbg("Initialize + Start the notification mechanism \n"); + + retval = cpqhp_event_start_thread(); + if (retval) + goto error; + + dbg("Initialize slot lists\n"); + for (loop = 0; loop < 256; loop++) + cpqhp_slot_list[loop] = NULL; + + /* FIXME: We also need to hook the NMI handler eventually. + * this also needs to be worked with Christoph + * register_NMI_handler(); + */ + /* Map rom address */ + cpqhp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN); + if (!cpqhp_rom_start) { + err ("Could not ioremap memory region for ROM\n"); + retval = -EIO; + goto error; + } + + /* Now, map the int15 entry point if we are on compaq specific + * hardware + */ + compaq_nvram_init(cpqhp_rom_start); + + /* Map smbios table entry point structure */ + smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start, + cpqhp_rom_start + ROM_PHY_LEN); + if (!smbios_table) { + err ("Could not find the SMBIOS pointer in memory\n"); + retval = -EIO; + goto error_rom_start; + } + + smbios_start = ioremap(readl(smbios_table + ST_ADDRESS), + readw(smbios_table + ST_LENGTH)); + if (!smbios_start) { + err ("Could not ioremap memory region taken from SMBIOS values\n"); + retval = -EIO; + goto error_smbios_start; + } + + initialized = 1; + + return retval; + +error_smbios_start: + iounmap(smbios_start); +error_rom_start: + iounmap(cpqhp_rom_start); +error: + return retval; } static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -785,7 +816,6 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) u8 num_of_slots = 0; u8 hp_slot = 0; u8 device; - u8 rev; u8 bus_cap; u16 temp_word; u16 vendor_id; @@ -794,6 +824,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) u32 rc; struct controller *ctrl; struct pci_func *func; + struct pci_bus *bus; int err; err = pci_enable_device(pdev); @@ -803,241 +834,233 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return err; } - // Need to read VID early b/c it's used to differentiate CPQ and INTC discovery - rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id); - if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) { + bus = pdev->subordinate; + if (!bus) { + dev_notice(&pdev->dev, "the device is not a bridge, skipping\n"); + rc = -ENODEV; + goto err_disable_device; + } + + /* Need to read VID early b/c it's used to differentiate CPQ and INTC + * discovery + */ + vendor_id = pdev->vendor; + if ((vendor_id != PCI_VENDOR_ID_COMPAQ) && + (vendor_id != PCI_VENDOR_ID_INTEL)) { err(msg_HPC_non_compaq_or_intel); rc = -ENODEV; goto err_disable_device; } dbg("Vendor ID: %x\n", vendor_id); - rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); - dbg("revision: %d\n", rev); - if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!rev))) { + dbg("revision: %d\n", pdev->revision); + if ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!pdev->revision)) { err(msg_HPC_rev_error); rc = -ENODEV; goto err_disable_device; } - /* Check for the proper subsytem ID's - * Intel uses a different SSID programming model than Compaq. + /* Check for the proper subsystem IDs + * Intel uses a different SSID programming model than Compaq. * For Intel, each SSID bit identifies a PHP capability. - * Also Intel HPC's may have RID=0. + * Also Intel HPCs may have RID=0. */ - if ((rev > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) { - // TODO: This code can be made to support non-Compaq or Intel subsystem IDs - rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid); - if (rc) { - err("%s : pci_read_config_word failed\n", __FUNCTION__); - goto err_disable_device; - } - dbg("Subsystem Vendor ID: %x\n", subsystem_vid); - if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) { - err(msg_HPC_non_compaq_or_intel); - rc = -ENODEV; - goto err_disable_device; - } + if ((pdev->revision <= 2) && (vendor_id != PCI_VENDOR_ID_INTEL)) { + err(msg_HPC_not_supported); + return -ENODEV; + } - ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL); - if (!ctrl) { - err("%s : out of memory\n", __FUNCTION__); - rc = -ENOMEM; - goto err_disable_device; - } - memset(ctrl, 0, sizeof(struct controller)); + /* TODO: This code can be made to support non-Compaq or Intel + * subsystem IDs + */ + subsystem_vid = pdev->subsystem_vendor; + dbg("Subsystem Vendor ID: %x\n", subsystem_vid); + if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) { + err(msg_HPC_non_compaq_or_intel); + rc = -ENODEV; + goto err_disable_device; + } - rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid); - if (rc) { - err("%s : pci_read_config_word failed\n", __FUNCTION__); - goto err_free_ctrl; - } + ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL); + if (!ctrl) { + err("%s : out of memory\n", __func__); + rc = -ENOMEM; + goto err_disable_device; + } - info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid); - - /* Set Vendor ID, so it can be accessed later from other functions */ - ctrl->vendor_id = vendor_id; - - switch (subsystem_vid) { - case PCI_VENDOR_ID_COMPAQ: - if (rev >= 0x13) { /* CIOBX */ - ctrl->push_flag = 1; - ctrl->slot_switch_type = 1; - ctrl->push_button = 1; - ctrl->pci_config_space = 1; - ctrl->defeature_PHP = 1; - ctrl->pcix_support = 1; - ctrl->pcix_speed_capability = 1; - pci_read_config_byte(pdev, 0x41, &bus_cap); - if (bus_cap & 0x80) { - dbg("bus max supports 133MHz PCI-X\n"); - ctrl->speed_capability = PCI_SPEED_133MHz_PCIX; - break; - } - if (bus_cap & 0x40) { - dbg("bus max supports 100MHz PCI-X\n"); - ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; - break; - } - if (bus_cap & 20) { - dbg("bus max supports 66MHz PCI-X\n"); - ctrl->speed_capability = PCI_SPEED_66MHz_PCIX; - break; - } - if (bus_cap & 10) { - dbg("bus max supports 66MHz PCI\n"); - ctrl->speed_capability = PCI_SPEED_66MHz; - break; - } - - break; - } - - switch (subsystem_deviceid) { - case PCI_SUB_HPC_ID: - /* Original 6500/7000 implementation */ - ctrl->slot_switch_type = 1; - ctrl->speed_capability = PCI_SPEED_33MHz; - ctrl->push_button = 0; - ctrl->pci_config_space = 1; - ctrl->defeature_PHP = 1; - ctrl->pcix_support = 0; - ctrl->pcix_speed_capability = 0; - break; - case PCI_SUB_HPC_ID2: - /* First Pushbutton implementation */ - ctrl->push_flag = 1; - ctrl->slot_switch_type = 1; - ctrl->speed_capability = PCI_SPEED_33MHz; - ctrl->push_button = 1; - ctrl->pci_config_space = 1; - ctrl->defeature_PHP = 1; - ctrl->pcix_support = 0; - ctrl->pcix_speed_capability = 0; - break; - case PCI_SUB_HPC_ID_INTC: - /* Third party (6500/7000) */ - ctrl->slot_switch_type = 1; - ctrl->speed_capability = PCI_SPEED_33MHz; - ctrl->push_button = 0; - ctrl->pci_config_space = 1; - ctrl->defeature_PHP = 1; - ctrl->pcix_support = 0; - ctrl->pcix_speed_capability = 0; - break; - case PCI_SUB_HPC_ID3: - /* First 66 Mhz implementation */ - ctrl->push_flag = 1; - ctrl->slot_switch_type = 1; - ctrl->speed_capability = PCI_SPEED_66MHz; - ctrl->push_button = 1; - ctrl->pci_config_space = 1; - ctrl->defeature_PHP = 1; - ctrl->pcix_support = 0; - ctrl->pcix_speed_capability = 0; - break; - case PCI_SUB_HPC_ID4: - /* First PCI-X implementation, 100MHz */ - ctrl->push_flag = 1; - ctrl->slot_switch_type = 1; - ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; - ctrl->push_button = 1; - ctrl->pci_config_space = 1; - ctrl->defeature_PHP = 1; - ctrl->pcix_support = 1; - ctrl->pcix_speed_capability = 0; - break; - default: - err(msg_HPC_not_supported); - rc = -ENODEV; - goto err_free_ctrl; - } - break; + subsystem_deviceid = pdev->subsystem_device; - case PCI_VENDOR_ID_INTEL: - /* Check for speed capability (0=33, 1=66) */ - if (subsystem_deviceid & 0x0001) { - ctrl->speed_capability = PCI_SPEED_66MHz; - } else { - ctrl->speed_capability = PCI_SPEED_33MHz; - } - - /* Check for push button */ - if (subsystem_deviceid & 0x0002) { - /* no push button */ - ctrl->push_button = 0; - } else { - /* push button supported */ - ctrl->push_button = 1; - } - - /* Check for slot switch type (0=mechanical, 1=not mechanical) */ - if (subsystem_deviceid & 0x0004) { - /* no switch */ - ctrl->slot_switch_type = 0; - } else { - /* switch */ - ctrl->slot_switch_type = 1; - } - - /* PHP Status (0=De-feature PHP, 1=Normal operation) */ - if (subsystem_deviceid & 0x0008) { - ctrl->defeature_PHP = 1; // PHP supported - } else { - ctrl->defeature_PHP = 0; // PHP not supported - } - - /* Alternate Base Address Register Interface (0=not supported, 1=supported) */ - if (subsystem_deviceid & 0x0010) { - ctrl->alternate_base_address = 1; // supported - } else { - ctrl->alternate_base_address = 0; // not supported - } - - /* PCI Config Space Index (0=not supported, 1=supported) */ - if (subsystem_deviceid & 0x0020) { - ctrl->pci_config_space = 1; // supported - } else { - ctrl->pci_config_space = 0; // not supported - } - - /* PCI-X support */ - if (subsystem_deviceid & 0x0080) { - /* PCI-X capable */ - ctrl->pcix_support = 1; - /* Frequency of operation in PCI-X mode */ - if (subsystem_deviceid & 0x0040) { - /* 133MHz PCI-X if bit 7 is 1 */ - ctrl->pcix_speed_capability = 1; - } else { - /* 100MHz PCI-X if bit 7 is 1 and bit 0 is 0, */ - /* 66MHz PCI-X if bit 7 is 1 and bit 0 is 1 */ - ctrl->pcix_speed_capability = 0; - } - } else { - /* Conventional PCI */ - ctrl->pcix_support = 0; - ctrl->pcix_speed_capability = 0; - } + info("Hot Plug Subsystem Device ID: %x\n", subsystem_deviceid); + + /* Set Vendor ID, so it can be accessed later from other + * functions + */ + ctrl->vendor_id = vendor_id; + + switch (subsystem_vid) { + case PCI_VENDOR_ID_COMPAQ: + if (pdev->revision >= 0x13) { /* CIOBX */ + ctrl->push_flag = 1; + ctrl->slot_switch_type = 1; + ctrl->push_button = 1; + ctrl->pci_config_space = 1; + ctrl->defeature_PHP = 1; + ctrl->pcix_support = 1; + ctrl->pcix_speed_capability = 1; + pci_read_config_byte(pdev, 0x41, &bus_cap); + if (bus_cap & 0x80) { + dbg("bus max supports 133MHz PCI-X\n"); + bus->max_bus_speed = PCI_SPEED_133MHz_PCIX; + break; + } + if (bus_cap & 0x40) { + dbg("bus max supports 100MHz PCI-X\n"); + bus->max_bus_speed = PCI_SPEED_100MHz_PCIX; + break; + } + if (bus_cap & 0x20) { + dbg("bus max supports 66MHz PCI-X\n"); + bus->max_bus_speed = PCI_SPEED_66MHz_PCIX; break; + } + if (bus_cap & 0x10) { + dbg("bus max supports 66MHz PCI\n"); + bus->max_bus_speed = PCI_SPEED_66MHz; + break; + } - default: - err(msg_HPC_not_supported); - rc = -ENODEV; - goto err_free_ctrl; + break; } - } else { + switch (subsystem_deviceid) { + case PCI_SUB_HPC_ID: + /* Original 6500/7000 implementation */ + ctrl->slot_switch_type = 1; + bus->max_bus_speed = PCI_SPEED_33MHz; + ctrl->push_button = 0; + ctrl->pci_config_space = 1; + ctrl->defeature_PHP = 1; + ctrl->pcix_support = 0; + ctrl->pcix_speed_capability = 0; + break; + case PCI_SUB_HPC_ID2: + /* First Pushbutton implementation */ + ctrl->push_flag = 1; + ctrl->slot_switch_type = 1; + bus->max_bus_speed = PCI_SPEED_33MHz; + ctrl->push_button = 1; + ctrl->pci_config_space = 1; + ctrl->defeature_PHP = 1; + ctrl->pcix_support = 0; + ctrl->pcix_speed_capability = 0; + break; + case PCI_SUB_HPC_ID_INTC: + /* Third party (6500/7000) */ + ctrl->slot_switch_type = 1; + bus->max_bus_speed = PCI_SPEED_33MHz; + ctrl->push_button = 0; + ctrl->pci_config_space = 1; + ctrl->defeature_PHP = 1; + ctrl->pcix_support = 0; + ctrl->pcix_speed_capability = 0; + break; + case PCI_SUB_HPC_ID3: + /* First 66 Mhz implementation */ + ctrl->push_flag = 1; + ctrl->slot_switch_type = 1; + bus->max_bus_speed = PCI_SPEED_66MHz; + ctrl->push_button = 1; + ctrl->pci_config_space = 1; + ctrl->defeature_PHP = 1; + ctrl->pcix_support = 0; + ctrl->pcix_speed_capability = 0; + break; + case PCI_SUB_HPC_ID4: + /* First PCI-X implementation, 100MHz */ + ctrl->push_flag = 1; + ctrl->slot_switch_type = 1; + bus->max_bus_speed = PCI_SPEED_100MHz_PCIX; + ctrl->push_button = 1; + ctrl->pci_config_space = 1; + ctrl->defeature_PHP = 1; + ctrl->pcix_support = 1; + ctrl->pcix_speed_capability = 0; + break; + default: + err(msg_HPC_not_supported); + rc = -ENODEV; + goto err_free_ctrl; + } + break; + + case PCI_VENDOR_ID_INTEL: + /* Check for speed capability (0=33, 1=66) */ + if (subsystem_deviceid & 0x0001) + bus->max_bus_speed = PCI_SPEED_66MHz; + else + bus->max_bus_speed = PCI_SPEED_33MHz; + + /* Check for push button */ + if (subsystem_deviceid & 0x0002) + ctrl->push_button = 0; + else + ctrl->push_button = 1; + + /* Check for slot switch type (0=mechanical, 1=not mechanical) */ + if (subsystem_deviceid & 0x0004) + ctrl->slot_switch_type = 0; + else + ctrl->slot_switch_type = 1; + + /* PHP Status (0=De-feature PHP, 1=Normal operation) */ + if (subsystem_deviceid & 0x0008) + ctrl->defeature_PHP = 1; /* PHP supported */ + else + ctrl->defeature_PHP = 0; /* PHP not supported */ + + /* Alternate Base Address Register Interface + * (0=not supported, 1=supported) + */ + if (subsystem_deviceid & 0x0010) + ctrl->alternate_base_address = 1; + else + ctrl->alternate_base_address = 0; + + /* PCI Config Space Index (0=not supported, 1=supported) */ + if (subsystem_deviceid & 0x0020) + ctrl->pci_config_space = 1; + else + ctrl->pci_config_space = 0; + + /* PCI-X support */ + if (subsystem_deviceid & 0x0080) { + ctrl->pcix_support = 1; + if (subsystem_deviceid & 0x0040) + /* 133MHz PCI-X if bit 7 is 1 */ + ctrl->pcix_speed_capability = 1; + else + /* 100MHz PCI-X if bit 7 is 1 and bit 0 is 0, */ + /* 66MHz PCI-X if bit 7 is 1 and bit 0 is 1 */ + ctrl->pcix_speed_capability = 0; + } else { + /* Conventional PCI */ + ctrl->pcix_support = 0; + ctrl->pcix_speed_capability = 0; + } + break; + + default: err(msg_HPC_not_supported); - return -ENODEV; + rc = -ENODEV; + goto err_free_ctrl; } - // Tell the user that we found one. + /* Tell the user that we found one. */ info("Initializing the PCI hot plug controller residing on PCI bus %d\n", pdev->bus->number); dbg("Hotplug controller capabilities:\n"); - dbg(" speed_capability %d\n", ctrl->speed_capability); + dbg(" speed_capability %d\n", bus->max_bus_speed); dbg(" slot_switch_type %s\n", ctrl->slot_switch_type ? "switch present" : "no switch"); dbg(" defeature_PHP %s\n", ctrl->defeature_PHP ? @@ -1056,20 +1079,19 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* make our own copy of the pci bus structure, * as we like tweaking it a lot */ - ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL); + ctrl->pci_bus = kmemdup(pdev->bus, sizeof(*ctrl->pci_bus), GFP_KERNEL); if (!ctrl->pci_bus) { err("out of memory\n"); rc = -ENOMEM; goto err_free_ctrl; } - memcpy(ctrl->pci_bus, pdev->bus, sizeof(*ctrl->pci_bus)); ctrl->bus = pdev->bus->number; - ctrl->rev = rev; + ctrl->rev = pdev->revision; dbg("bus device function rev: %d %d %d %d\n", ctrl->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev); - init_MUTEX(&ctrl->crit_sect); + mutex_init(&ctrl->crit_sect); init_waitqueue_head(&ctrl->queue); /* initialize our threads if they haven't already been started up */ @@ -1077,10 +1099,10 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) { goto err_free_bus; } - + dbg("pdev = %p\n", pdev); - dbg("pci resource start %lx\n", pci_resource_start(pdev, 0)); - dbg("pci resource len %lx\n", pci_resource_len(pdev, 0)); + dbg("pci resource start %llx\n", (unsigned long long)pci_resource_start(pdev, 0)); + dbg("pci resource len %llx\n", (unsigned long long)pci_resource_len(pdev, 0)); if (!request_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0), MY_NAME)) { @@ -1092,15 +1114,15 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ctrl->hpc_reg = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); if (!ctrl->hpc_reg) { - err("cannot remap MMIO region %lx @ %lx\n", - pci_resource_len(pdev, 0), - pci_resource_start(pdev, 0)); + err("cannot remap MMIO region %llx @ %llx\n", + (unsigned long long)pci_resource_len(pdev, 0), + (unsigned long long)pci_resource_start(pdev, 0)); rc = -ENODEV; goto err_free_mem_region; } - // Check for 66Mhz operation - ctrl->speed = get_controller_speed(ctrl); + /* Check for 66Mhz operation */ + bus->cur_bus_speed = get_controller_speed(ctrl); /******************************************************** @@ -1110,7 +1132,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * ********************************************************/ - // find the physical slot number of the first hot plug slot + /* find the physical slot number of the first hot plug slot */ /* Get slot won't work for devices behind bridges, but * in this case it will always be called for the "base" @@ -1127,18 +1149,18 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_iounmap; } - // Store PCI Config Space for all devices on this bus + /* Store PCI Config Space for all devices on this bus */ rc = cpqhp_save_config(ctrl, ctrl->bus, readb(ctrl->hpc_reg + SLOT_MASK)); if (rc) { err("%s: unable to save PCI configuration data, error %d\n", - __FUNCTION__, rc); + __func__, rc); goto err_iounmap; } /* * Get IO, memory, and IRQ resources for new devices */ - // The next line is required for cpqhp_find_available_resources + /* The next line is required for cpqhp_find_available_resources */ ctrl->interrupt = pdev->irq; if (ctrl->interrupt < 0x10) { cpqhp_legacy_mode = 1; @@ -1169,29 +1191,31 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) { err(msg_initialization_err, 6); err("%s: unable to save PCI configuration data, error %d\n", - __FUNCTION__, rc); + __func__, rc); goto err_iounmap; } - + /* Mask all general input interrupts */ writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_MASK); /* set up the interrupt */ dbg("HPC interrupt = %d \n", ctrl->interrupt); if (request_irq(ctrl->interrupt, cpqhp_ctrl_intr, - SA_SHIRQ, MY_NAME, ctrl)) { + IRQF_SHARED, MY_NAME, ctrl)) { err("Can't get irq %d for the hotplug pci controller\n", ctrl->interrupt); rc = -ENODEV; goto err_iounmap; } - /* Enable Shift Out interrupt and clear it, also enable SERR on power fault */ + /* Enable Shift Out interrupt and clear it, also enable SERR on power + * fault + */ temp_word = readw(ctrl->hpc_reg + MISC); temp_word |= 0x4006; writew(temp_word, ctrl->hpc_reg + MISC); - // Changed 05/05/97 to clear all interrupts at start + /* Changed 05/05/97 to clear all interrupts at start */ writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_INPUT_CLEAR); ctrl->ctrl_int_comp = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); @@ -1206,13 +1230,14 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) cpqhp_ctrl_list = ctrl; } - // turn off empty slots here unless command line option "ON" set - // Wait for exclusive access to hardware - down(&ctrl->crit_sect); + /* turn off empty slots here unless command line option "ON" set + * Wait for exclusive access to hardware + */ + mutex_lock(&ctrl->crit_sect); num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; - // find first device number for the ctrl + /* find first device number for the ctrl */ device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4; while (num_of_slots) { @@ -1224,23 +1249,21 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hp_slot = func->device - ctrl->slot_device_offset; dbg("hp_slot: %d\n", hp_slot); - // We have to save the presence info for these slots + /* We have to save the presence info for these slots */ temp_word = ctrl->ctrl_int_comp >> 16; func->presence_save = (temp_word >> hp_slot) & 0x01; func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02; - if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) { + if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) func->switch_save = 0; - } else { + else func->switch_save = 0x10; - } - if (!power_mode) { + if (!power_mode) if (!func->is_a_board) { green_LED_off(ctrl, hp_slot); slot_disable(ctrl, hp_slot); } - } device++; num_of_slots--; @@ -1248,21 +1271,21 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (!power_mode) { set_SOGO(ctrl); - // Wait for SOBS to be unset + /* Wait for SOBS to be unset */ wait_for_ctrl_irq(ctrl); } rc = init_SERR(ctrl); if (rc) { err("init_SERR failed\n"); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); goto err_free_irq; } - // Done with exclusive hardware access - up(&ctrl->crit_sect); + /* Done with exclusive hardware access */ + mutex_unlock(&ctrl->crit_sect); - cpqhp_create_ctrl_files(ctrl); + cpqhp_create_debugfs_files(ctrl); return 0; @@ -1281,77 +1304,6 @@ err_disable_device: return rc; } - -static int one_time_init(void) -{ - int loop; - int retval = 0; - - if (initialized) - return 0; - - power_mode = 0; - - retval = pci_print_IRQ_route(); - if (retval) - goto error; - - dbg("Initialize + Start the notification mechanism \n"); - - retval = cpqhp_event_start_thread(); - if (retval) - goto error; - - dbg("Initialize slot lists\n"); - for (loop = 0; loop < 256; loop++) { - cpqhp_slot_list[loop] = NULL; - } - - // FIXME: We also need to hook the NMI handler eventually. - // this also needs to be worked with Christoph - // register_NMI_handler(); - - // Map rom address - cpqhp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN); - if (!cpqhp_rom_start) { - err ("Could not ioremap memory region for ROM\n"); - retval = -EIO; - goto error; - } - - /* Now, map the int15 entry point if we are on compaq specific hardware */ - compaq_nvram_init(cpqhp_rom_start); - - /* Map smbios table entry point structure */ - smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start, - cpqhp_rom_start + ROM_PHY_LEN); - if (!smbios_table) { - err ("Could not find the SMBIOS pointer in memory\n"); - retval = -EIO; - goto error_rom_start; - } - - smbios_start = ioremap(readl(smbios_table + ST_ADDRESS), - readw(smbios_table + ST_LENGTH)); - if (!smbios_start) { - err ("Could not ioremap memory region taken from SMBIOS values\n"); - retval = -EIO; - goto error_smbios_start; - } - - initialized = 1; - - return retval; - -error_smbios_start: - iounmap(smbios_start); -error_rom_start: - iounmap(cpqhp_rom_start); -error: - return retval; -} - - static void __exit unload_cpqphpd(void) { struct pci_func *next; @@ -1371,10 +1323,10 @@ static void __exit unload_cpqphpd(void) if (ctrl->hpc_reg) { u16 misc; rc = read_slot_enable (ctrl); - + writeb(0, ctrl->hpc_reg + SLOT_SERR); writel(0xFFFFFFC0L | ~rc, ctrl->hpc_reg + INT_MASK); - + misc = readw(ctrl->hpc_reg + MISC); misc &= 0xFFFD; writew(misc, ctrl->hpc_reg + MISC); @@ -1454,38 +1406,34 @@ static void __exit unload_cpqphpd(void) } } - // Stop the notification mechanism + /* Stop the notification mechanism */ if (initialized) cpqhp_event_stop_thread(); - //unmap the rom address + /* unmap the rom address */ if (cpqhp_rom_start) iounmap(cpqhp_rom_start); if (smbios_start) iounmap(smbios_start); } - - static struct pci_device_id hpcd_pci_tbl[] = { { /* handle any PCI Hotplug controller */ .class = ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00), .class_mask = ~0, - + /* no matter who makes it */ .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - + }, { /* end: all zeroes */ } }; MODULE_DEVICE_TABLE(pci, hpcd_pci_tbl); - - static struct pci_driver cpqhpc_driver = { .name = "compaq_pci_hotplug", .id_table = hpcd_pci_tbl, @@ -1493,8 +1441,6 @@ static struct pci_driver cpqhpc_driver = { /* remove: cpqhpc_remove_one, */ }; - - static int __init cpqhpc_init(void) { int result; @@ -1502,12 +1448,12 @@ static int __init cpqhpc_init(void) cpqhp_debug = debug; info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); + cpqhp_initialize_debugfs(); result = pci_register_driver(&cpqhpc_driver); dbg("pci_register_driver = %d\n", result); return result; } - static void __exit cpqhpc_cleanup(void) { dbg("unload_cpqphpd()\n"); @@ -1515,10 +1461,8 @@ static void __exit cpqhpc_cleanup(void) dbg("pci_unregister_driver\n"); pci_unregister_driver(&cpqhpc_driver); + cpqhp_shutdown_debugfs(); } - module_init(cpqhpc_init); module_exit(cpqhpc_cleanup); - - |
