# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.660 -> 1.661 # drivers/hotplug/ibmphp_hpc.c 1.2 -> 1.3 # drivers/hotplug/ibmphp_ebda.c 1.2 -> 1.3 # drivers/hotplug/ibmphp_pci.c 1.1 -> 1.2 # drivers/hotplug/ibmphp.h 1.2 -> 1.3 # drivers/hotplug/ibmphp_res.c 1.1 -> 1.2 # drivers/hotplug/ibmphp_core.c 1.3 -> 1.4 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/09/13 zubarev@us.ibm.com 1.661 # [PATCH] IBM PCI Hotplug driver update # # - fix polling logic # - add ability to write [chassis/rxe]#slot# instead of just slot# # -------------------------------------------- # diff -Nru a/drivers/hotplug/ibmphp.h b/drivers/hotplug/ibmphp.h --- a/drivers/hotplug/ibmphp.h Fri Sep 13 10:57:25 2002 +++ b/drivers/hotplug/ibmphp.h Fri Sep 13 10:57:25 2002 @@ -39,7 +39,8 @@ #else #define MY_NAME THIS_MODULE->name #endif -#define debug(fmt, arg...) do { if (ibmphp_debug) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0) +#define debug(fmt, arg...) do { if (ibmphp_debug == 1) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0) +#define debug_pci(fmt, arg...) do { if (ibmphp_debug) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0) #define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg) #define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg) @@ -121,6 +122,7 @@ u8 port1_port_connect; u8 port2_node_connect; u8 port2_port_connect; + u8 chassis_num; // struct list_head scal_detail_list; }; @@ -139,9 +141,27 @@ u8 port1_port_connect; u8 first_slot_num; u8 status; -// struct list_head rio_detail_list; + u8 wpindex; + u8 chassis_num; + struct list_head rio_detail_list; }; +struct opt_rio { + u8 rio_type; + u8 chassis_num; + u8 first_slot_num; + u8 middle_num; + struct list_head opt_rio_list; +}; + +struct opt_rio_lo { + u8 rio_type; + u8 chassis_num; + u8 first_slot_num; + u8 middle_num; + u8 pack_count; + struct list_head opt_rio_lo_list; +}; /**************************************************************** * HPC DESCRIPTOR NODE * @@ -153,7 +173,6 @@ short phys_addr; // struct list_head ebda_hpc_list; }; - /***************************************************************** * IN HPC DATA STRUCTURE, THE ASSOCIATED SLOT AND BUS * * STRUCTURE * @@ -195,6 +214,9 @@ u8 i2c_addr; }; +#define HPC_DEVICE_ID 0x0246 +#define HPC_SUBSYSTEM_ID 0x0247 +#define HPC_PCI_OFFSET 0x40 /************************************************************************* * RSTC DESCRIPTOR NODE * *************************************************************************/ @@ -215,8 +237,9 @@ u8 rsrc_type; u8 bus_num; u8 dev_fun; - ulong start_addr; - ulong end_addr; + u32 start_addr; + u32 end_addr; + u8 marked; /* for NVRAM */ struct list_head ebda_pci_rsrc_list; }; @@ -248,7 +271,7 @@ ***********************************************************/ extern struct list_head ibmphp_ebda_pci_rsrc_head; extern struct list_head ibmphp_slot_head; - +extern struct list_head ibmphp_res_head; /*********************************************************** * FUNCTION PROTOTYPES * ***********************************************************/ @@ -263,6 +286,7 @@ extern struct bus_info *ibmphp_find_same_bus_num (u32); extern int ibmphp_get_bus_index (u8); extern u16 ibmphp_get_total_controllers (void); +extern int ibmphp_register_pci (void); /* passed parameters */ #define MEM 0 @@ -739,6 +763,7 @@ extern int ibmphp_update_slot_info (struct slot *); /* This function is called from HPC, so we need it to not be be static */ extern int ibmphp_configure_card (struct pci_func *, u8); extern int ibmphp_unconfigure_card (struct slot **, int); +extern void ibmphp_increase_count (void); extern struct hotplug_slot_ops ibmphp_hotplug_slot_ops; static inline void long_delay (int delay) diff -Nru a/drivers/hotplug/ibmphp_core.c b/drivers/hotplug/ibmphp_core.c --- a/drivers/hotplug/ibmphp_core.c Fri Sep 13 10:57:25 2002 +++ b/drivers/hotplug/ibmphp_core.c Fri Sep 13 10:57:25 2002 @@ -44,7 +44,7 @@ #define get_ctrl_revision(sl, rev) ibmphp_hpc_readslot (sl, READ_REVLEVEL, rev) #define get_hpc_options(sl, opt) ibmphp_hpc_readslot (sl, READ_HPCOPTIONS, opt) -#define DRIVER_VERSION "0.3" +#define DRIVER_VERSION "0.6" #define DRIVER_DESC "IBM Hot Plug PCI Controller Driver" int ibmphp_debug; @@ -88,6 +88,8 @@ slot_cur->bus_on->current_speed = CURRENT_BUS_SPEED (slot_cur->busstatus); if (READ_BUS_MODE (slot_cur->ctrl)) slot_cur->bus_on->current_bus_mode = CURRENT_BUS_MODE (slot_cur->busstatus); + else + slot_cur->bus_on->current_bus_mode = 0xFF; debug ("busstatus = %x, bus_speed = %x, bus_mode = %x\n", slot_cur->busstatus, slot_cur->bus_on->current_speed, slot_cur->bus_on->current_bus_mode); @@ -108,11 +110,15 @@ static int get_max_slots (void) { + struct slot * slot_cur; struct list_head * tmp; - int slot_count = 0; + u8 slot_count = 0; - list_for_each (tmp, &ibmphp_slot_head) - ++slot_count; + list_for_each (tmp, &ibmphp_slot_head) { + slot_cur = list_entry (tmp, struct slot, ibm_slot_list); + /* sometimes the hot-pluggable slots start with 4 (not always from 1 */ + slot_count = max (slot_count, slot_cur->number); + } return slot_count; } @@ -330,7 +336,7 @@ memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot)); hpcrc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &(myslot.status)); if (!hpcrc) { - *value = SLOT_POWER (myslot.status); + *value = SLOT_PWRGD (myslot.status); rc = 0; } } @@ -394,15 +400,22 @@ if (pslot) { rc = 0; mode = pslot->supported_bus_mode; - *value = pslot->supported_speed; - *value &= 0x0f; - - if (mode == BUS_MODE_PCIX) - *value |= 0x80; - else if (mode == BUS_MODE_PCI) - *value |= 0x40; - else - *value |= 0x20; + *value = pslot->supported_speed; + switch (*value) { + case BUS_SPEED_33: + break; + case BUS_SPEED_66: + if (mode == BUS_MODE_PCIX) + *value += 0x01; + break; + case BUS_SPEED_100: + case BUS_SPEED_133: + *value = pslot->supported_speed + 0x01; + break; + default: +*/ /* Note (will need to change): there would be soon 256, 512 also */ +/* rc = -ENODEV; + } } } else rc = -ENODEV; @@ -429,14 +442,25 @@ if (!rc) { mode = pslot->bus_on->current_bus_mode; *value = pslot->bus_on->current_speed; - *value &= 0x0f; - - if (mode == BUS_MODE_PCIX) - *value |= 0x80; - else if (mode == BUS_MODE_PCI) - *value |= 0x40; - else - *value |= 0x20; + switch (*value) { + case BUS_SPEED_33: + break; + case BUS_SPEED_66: + if (mode == BUS_MODE_PCIX) + *value += 0x01; + else if (mode == BUS_MODE_PCI) + ; + else + *value = PCI_SPEED_UNKNOWN; + break; + case BUS_SPEED_100: + case BUS_SPEED_133: + *value += 0x01; + break; + default: +*/ /* Note of change: there would also be 256, 512 soon */ +/* rc = -ENODEV; + } } } } else @@ -454,7 +478,7 @@ int hpcrc = 0; struct slot myslot; - debug ("get_max_adapter_speed - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong)hotplug_slot, (ulong) value); + debug ("get_max_adapter_speed_1 - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong)hotplug_slot, (ulong) value); if (flag) ibmphp_lock_operations (); @@ -485,17 +509,16 @@ if (flag) ibmphp_unlock_operations (); - debug ("get_adapter_present - Exit rc[%d] hpcrc[%x] value[%x]\n", rc, hpcrc, *value); + debug ("get_max_adapter_speed_1 - Exit rc[%d] hpcrc[%x] value[%x]\n", rc, hpcrc, *value); return rc; } -static int get_card_bus_names (struct hotplug_slot *hotplug_slot, char * value) +static int get_bus_name (struct hotplug_slot *hotplug_slot, char * value) { int rc = -ENODEV; struct slot *pslot = NULL; - struct pci_dev * dev = NULL; - debug ("get_card_bus_names - Entry hotplug_slot[%lx] \n", (ulong)hotplug_slot); + debug ("get_bus_name - Entry hotplug_slot[%lx] \n", (ulong)hotplug_slot); ibmphp_lock_operations (); @@ -503,26 +526,17 @@ pslot = (struct slot *) hotplug_slot->private; if (pslot) { rc = 0; - if (pslot->func) - dev = pslot->func->dev; - else - dev = pci_find_slot (pslot->bus, (pslot->device << 3) | (0x00 & 0x7)); - if (dev) - snprintf (value, 100, "Bus %d : %s", pslot->bus,dev->name); - else - snprintf (value, 100, "Bus %d", pslot->bus); - - + snprintf (value, 100, "Bus %x", pslot->bus); } } else rc = -ENODEV; ibmphp_unlock_operations (); - debug ("get_card_bus_names - Exit rc[%d] value[%x]\n", rc, *value); + debug ("get_bus_name - Exit rc[%d] value[%x]\n", rc, *value); return rc; } - */ + /******************************************************************************* * This routine will initialize the ops data structure used in the validate * function. It will also power off empty slots that are powered on since BIOS @@ -531,12 +545,14 @@ static int init_ops (void) { struct slot *slot_cur; + struct list_head *tmp; int retval; - int j; int rc; + int j; for (j = 0; j < MAX_OPS; j++) { ops[j] = (int *) kmalloc ((max_slots + 1) * sizeof (int), GFP_KERNEL); + memset (ops[j], 0, (max_slots + 1) * sizeof (int)); if (!ops[j]) { err ("out of system memory \n"); return -ENOMEM; @@ -547,12 +563,13 @@ ops[REMOVE][0] = 0; ops[DETAIL][0] = 0; - for (j = 1; j <= max_slots; j++) { + list_for_each (tmp, &ibmphp_slot_head) { + slot_cur = list_entry (tmp, struct slot, ibm_slot_list); - slot_cur = ibmphp_get_slot_from_physical_num (j); + if (!slot_cur) + return -ENODEV; debug ("BEFORE GETTING SLOT STATUS, slot # %x\n", slot_cur->number); - if (slot_cur->ctrl->revision == 0xFF) if (get_ctrl_revision (slot_cur, &slot_cur->ctrl->revision)) return -1; @@ -572,21 +589,21 @@ debug ("status = %x, ext_status = %x\n", slot_cur->status, slot_cur->ext_status); debug ("SLOT_POWER = %x, SLOT_PRESENT = %x, SLOT_LATCH = %x\n", SLOT_POWER (slot_cur->status), SLOT_PRESENT (slot_cur->status), SLOT_LATCH (slot_cur->status)); - if (!(SLOT_POWER (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) + if (!(SLOT_PWRGD (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) /* No power, adapter, and latch closed */ - ops[ADD][j] = 1; + ops[ADD][slot_cur->number] = 1; else - ops[ADD][j] = 0; + ops[ADD][slot_cur->number] = 0; - ops[DETAIL][j] = 1; + ops[DETAIL][slot_cur->number] = 1; - if ((SLOT_POWER (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) + if ((SLOT_PWRGD (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) /*Power,adapter,latch closed */ - ops[REMOVE][j] = 1; + ops[REMOVE][slot_cur->number] = 1; else - ops[REMOVE][j] = 0; + ops[REMOVE][slot_cur->number] = 0; - if ((SLOT_POWER (slot_cur->status)) && !(SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) { + if ((SLOT_PWRGD (slot_cur->status)) && !(SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) { debug ("BEFORE POWER OFF COMMAND\n"); rc = power_off (slot_cur); if (rc) @@ -624,7 +641,7 @@ if (retval) return retval; - if (!(SLOT_POWER (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) + if (!(SLOT_PWRGD (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) ops[ADD][number] = 1; else @@ -632,7 +649,7 @@ ops[DETAIL][number] = 1; - if ((SLOT_POWER (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) + if ((SLOT_PWRGD (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) ops[REMOVE][number] = 1; else @@ -678,7 +695,7 @@ } snprintf (buffer, 10, "%d", slot_cur->number); - info->power_status = SLOT_POWER (slot_cur->status); + info->power_status = SLOT_PWRGD (slot_cur->status); info->attention_status = SLOT_ATTN (slot_cur->status, slot_cur->ext_status); info->latch_status = SLOT_LATCH (slot_cur->status); if (!SLOT_PRESENT (slot_cur->status)) { @@ -688,8 +705,8 @@ info->adapter_status = 1; // get_max_adapter_speed_1 (slot_cur->hotplug_slot, &info->max_adapter_speed_status, 0); } -/* - bus_speed = slot_cur->bus_on->current_speed; + /* !!!!!!!!!TO DO: THIS NEEDS TO CHANGE!!!!!!!!!!!!! */ +/* bus_speed = slot_cur->bus_on->current_speed; bus_speed &= 0x0f; if (slot_cur->bus_on->current_bus_mode == BUS_MODE_PCIX) @@ -701,7 +718,7 @@ info->cur_bus_speed_status = bus_speed; info->max_bus_speed_status = slot_cur->hotplug_slot->info->max_bus_speed_status; - // To do: card_bus_names + // To do: bus_names */ rc = pci_hp_change_slot_info (buffer, info); kfree (info); @@ -775,8 +792,10 @@ struct list_head * tmp; struct list_head * next; - list_for_each_safe (tmp, next, &ibmphp_slot_head) { + debug ("%s -- enter\n", __FUNCTION__); + list_for_each_safe (tmp, next, &ibmphp_slot_head) { + slot_cur = list_entry (tmp, struct slot, ibm_slot_list); pci_hp_deregister (slot_cur->hotplug_slot); @@ -795,7 +814,9 @@ ibmphp_unconfigure_card (&slot_cur, -1); /* we don't want to actually remove the resources, since free_resources will do just that */ kfree (slot_cur); + slot_cur = NULL; } + debug ("%s -- exit\n", __FUNCTION__); } static int ibm_is_pci_dev_in_use (struct pci_dev *dev) @@ -851,7 +872,7 @@ if (temp_func) temp_func->dev = NULL; else - err ("No pci_func representation for bus, devfn = %d, %x\n", dev->bus->number, dev->devfn); + debug ("No pci_func representation for bus, devfn = %d, %x\n", dev->bus->number, dev->devfn); return 0; } @@ -965,6 +986,34 @@ visit_pci_dev: configure_visit_pci_dev, }; + +/* + * The following function is to fix kernel bug regarding + * getting bus entries, here we manually add those primary + * bus entries to kernel bus structure whenever apply + */ + +static u8 bus_structure_fixup (u8 busno) +{ + struct pci_bus bus_t; + struct pci_dev dev_t; + u16 l; + + if (!find_bus (busno) || !(ibmphp_find_same_bus_num (busno))) + return 1; + bus_t.number = busno; + bus_t.ops = ibmphp_pci_root_ops; + dev_t.bus = &bus_t; + for (dev_t.devfn=0; dev_t.devfn<256; dev_t.devfn += 8) { + if (!pci_read_config_word (&dev_t, PCI_VENDOR_ID, &l) && l != 0x0000 && l != 0xffff) { + debug ("%s - Inside bus_struture_fixup() \n", __FUNCTION__); + pci_scan_bus (busno, ibmphp_pci_root_ops, NULL); + break; + } + } + return 0; +} + static int ibm_configure_device (struct pci_func *func) { unsigned char bus; @@ -972,6 +1021,7 @@ struct pci_bus *child; struct pci_dev *temp; int rc = 0; + int flag = 0; /* this is to make sure we don't double scan the bus, for bridged devices primarily */ struct pci_dev_wrapped wrapped_dev; struct pci_bus_wrapped wrapped_bus; @@ -980,6 +1030,8 @@ memset (&wrapped_bus, 0, sizeof (struct pci_bus_wrapped)); memset (&dev0, 0, sizeof (struct pci_dev)); + if (!(bus_structure_fixup (func->busno))) + flag = 1; if (func->dev == NULL) func->dev = pci_find_slot (func->busno, (func->device << 3) | (func->function & 0x7)); @@ -995,7 +1047,7 @@ return 0; } } - if (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) { pci_read_config_byte (func->dev, PCI_SECONDARY_BUS, &bus); child = (struct pci_bus *) pci_add_new_bus (func->dev->bus, (func->dev), bus); pci_do_scan_bus (child); @@ -1028,7 +1080,7 @@ rc = slot_update (&tmp_slot); if (rc) return 0; - if (SLOT_PRESENT (tmp_slot->status) && SLOT_POWER (tmp_slot->status)) + if (SLOT_PRESENT (tmp_slot->status) && SLOT_PWRGD (tmp_slot->status)) return 0; i++; } @@ -1046,6 +1098,9 @@ int rc; u8 speed; u8 cmd = 0x0; + const struct list_head *tmp; + struct pci_dev * dev; + int retval; debug ("%s - entry slot # %d \n", __FUNCTION__, slot_cur->number); if (SET_BUS_STATUS (slot_cur->ctrl) && is_bus_empty (slot_cur)) { @@ -1091,6 +1146,14 @@ cmd = HPC_BUS_100PCIXMODE; break; case BUS_SPEED_133: + /* This is to take care of the bug in CIOBX chip*/ + list_for_each (tmp, &pci_devices) { + dev = (struct pci_dev *) pci_dev_g (tmp); + if (dev) { + if ((dev->vendor == 0x1166) && (dev->device == 0x0101)) + ibmphp_hpc_writeslot (slot_cur, HPC_BUS_100PCIXMODE); + } + } cmd = HPC_BUS_133PCIXMODE; break; default: @@ -1103,9 +1166,17 @@ return -ENODEV; } debug ("setting bus speed for slot %d, cmd %x\n", slot_cur->number, cmd); - ibmphp_hpc_writeslot (slot_cur, cmd); + retval = ibmphp_hpc_writeslot (slot_cur, cmd); + if (retval) { + err ("setting bus speed failed\n"); + return retval; + } + if (CTLR_RESULT (slot_cur->ctrl->status)) { + err ("command not completed successfully in set_bus \n"); + return -EIO; + } } - /* This is for x400, once Brandon fixes the firmware, + /* This is for x440, once Brandon fixes the firmware, will not need this delay */ long_delay (1 * HZ); debug ("%s -Exit \n", __FUNCTION__); @@ -1128,7 +1199,7 @@ for (i = slot_cur->bus_on->slot_min; i <= slot_cur->bus_on->slot_max; i++) { tmp_slot = ibmphp_get_slot_from_physical_num (i); - if ((SLOT_POWER (tmp_slot->status)) && !(SLOT_CONNECT (tmp_slot->status))) + if ((SLOT_PWRGD (tmp_slot->status)) && !(SLOT_CONNECT (tmp_slot->status))) count++; } get_cur_bus_info (&slot_cur); @@ -1384,11 +1455,15 @@ debug ("DISABLING SLOT... \n"); - if (slot_cur == NULL) + if (slot_cur == NULL) { + ibmphp_unlock_operations (); return -ENODEV; + } - if (slot_cur->ctrl == NULL) + if (slot_cur->ctrl == NULL) { + ibmphp_unlock_operations (); return -ENODEV; + } flag = slot_cur->flag; /* to see if got here from polling */ @@ -1463,7 +1538,8 @@ return -EFAULT; } - ibmphp_update_slot_info (slot_cur); + if (flag) + ibmphp_update_slot_info (slot_cur); ibmphp_unlock_operations (); return -EFAULT; } @@ -1493,6 +1569,14 @@ return rc; } +/* This routine is for NVRAM module to increase the count so we can rmmod + * the ibmphp module + */ +void ibmphp_increase_count (void) +{ + MOD_INC_USE_COUNT; +} + struct hotplug_slot_ops ibmphp_hotplug_slot_ops = { owner: THIS_MODULE, set_attention_status: set_attention_status, @@ -1506,7 +1590,7 @@ /* get_max_bus_speed_status: get_max_bus_speed, get_max_adapter_speed_status: get_max_adapter_speed, get_cur_bus_speed_status: get_cur_bus_speed, - get_card_bus_names_status: get_card_bus_names, + get_bus_name_status: get_bus_name, */ }; @@ -1559,7 +1643,7 @@ debug ("AFTER Resource & EBDA INITIALIZATIONS\n"); max_slots = get_max_slots (); - + if (init_ops ()) { ibmphp_unload (); return -ENODEV; @@ -1570,11 +1654,9 @@ return -ENODEV; } - /* lock ourselves into memory with a module count of -1 - * so that no one can unload us. */ + /* if no NVRAM module selected, lock ourselves into memory with a + * module count of -1 so that no one can unload us. */ MOD_DEC_USE_COUNT; - - return 0; } diff -Nru a/drivers/hotplug/ibmphp_ebda.c b/drivers/hotplug/ibmphp_ebda.c --- a/drivers/hotplug/ibmphp_ebda.c Fri Sep 13 10:57:25 2002 +++ b/drivers/hotplug/ibmphp_ebda.c Fri Sep 13 10:57:25 2002 @@ -55,11 +55,17 @@ /* Local variables */ static struct ebda_hpc_list *hpc_list_ptr; static struct ebda_rsrc_list *rsrc_list_ptr; -static struct rio_table_hdr *rio_table_ptr; +static struct rio_table_hdr *rio_table_ptr = NULL; static LIST_HEAD (ebda_hpc_head); static LIST_HEAD (bus_info_head); +static LIST_HEAD (rio_vg_head); +static LIST_HEAD (rio_lo_head); +static LIST_HEAD (opt_vg_head); +static LIST_HEAD (opt_lo_head); static void *io_mem; +char *chassis_str, *rxe_str, *str; + /* Local functions */ static int ebda_rsrc_controller (void); static int ebda_rsrc_rsrc (void); @@ -172,6 +178,40 @@ } } +static void print_lo_info (void) +{ + struct rio_detail *ptr; + struct list_head *ptr1; + debug ("print_lo_info ---- \n"); + list_for_each (ptr1, &rio_lo_head) { + ptr = list_entry (ptr1, struct rio_detail, rio_detail_list); + debug ("%s - rio_node_id = %x\n", __FUNCTION__, ptr->rio_node_id); + debug ("%s - rio_type = %x\n", __FUNCTION__, ptr->rio_type); + debug ("%s - owner_id = %x\n", __FUNCTION__, ptr->owner_id); + debug ("%s - first_slot_num = %x\n", __FUNCTION__, ptr->first_slot_num); + debug ("%s - wpindex = %x\n", __FUNCTION__, ptr->wpindex); + debug ("%s - chassis_num = %x\n", __FUNCTION__, ptr->chassis_num); + + } +} + +static void print_vg_info (void) +{ + struct rio_detail *ptr; + struct list_head *ptr1; + debug ("print_vg_info --- \n"); + list_for_each (ptr1, &rio_vg_head) { + ptr = list_entry (ptr1, struct rio_detail, rio_detail_list); + debug ("%s - rio_node_id = %x\n", __FUNCTION__, ptr->rio_node_id); + debug ("%s - rio_type = %x\n", __FUNCTION__, ptr->rio_type); + debug ("%s - owner_id = %x\n", __FUNCTION__, ptr->owner_id); + debug ("%s - first_slot_num = %x\n", __FUNCTION__, ptr->first_slot_num); + debug ("%s - wpindex = %x\n", __FUNCTION__, ptr->wpindex); + debug ("%s - chassis_num = %x\n", __FUNCTION__, ptr->chassis_num); + + } +} + static void print_ebda_pci_rsrc (void) { struct ebda_pci_rsrc *ptr; @@ -179,11 +219,36 @@ list_for_each (ptr1, &ibmphp_ebda_pci_rsrc_head) { ptr = list_entry (ptr1, struct ebda_pci_rsrc, ebda_pci_rsrc_list); - debug ("%s - rsrc type: %x bus#: %x dev_func: %x start addr: %lx end addr: %lx\n", + debug ("%s - rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n", __FUNCTION__, ptr->rsrc_type ,ptr->bus_num, ptr->dev_fun,ptr->start_addr, ptr->end_addr); } } +static void print_ibm_slot (void) +{ + struct slot *ptr; + struct list_head *ptr1; + + list_for_each (ptr1, &ibmphp_slot_head) { + ptr = list_entry (ptr1, struct slot, ibm_slot_list); + debug ("%s - slot_number: %x \n", __FUNCTION__, ptr->number); + } +} + +static void print_opt_vg (void) +{ + struct opt_rio *ptr; + struct list_head *ptr1; + debug ("print_opt_vg --- \n"); + list_for_each (ptr1, &opt_vg_head) { + ptr = list_entry (ptr1, struct opt_rio, opt_rio_list); + debug ("%s - rio_type %x \n", __FUNCTION__, ptr->rio_type); + debug ("%s - chassis_num: %x \n", __FUNCTION__, ptr->chassis_num); + debug ("%s - first_slot_num: %x \n", __FUNCTION__, ptr->first_slot_num); + debug ("%s - middle_num: %x \n", __FUNCTION__, ptr->middle_num); + } +} + static void print_ebda_hpc (void) { struct controller *hpc_ptr; @@ -220,6 +285,7 @@ break; case 2: + case 4: debug ("%s - wpegbbar: %lx\n", __FUNCTION__, hpc_ptr->u.wpeg_ctlr.wpegbbar); debug ("%s - i2c_addr: %x\n", __FUNCTION__, hpc_ptr->u.wpeg_ctlr.i2c_addr); debug ("%s - irq: %x\n", __FUNCTION__, hpc_ptr->irq); @@ -356,31 +422,380 @@ rio_complete = 1; } + } - if (hs_complete && rio_complete) { - rc = ebda_rsrc_controller (); - if (rc) { - iounmap(io_mem); - return rc; - } - rc = ebda_rsrc_rsrc (); - if (rc) { - iounmap(io_mem); - return rc; - } + if (!hs_complete && !rio_complete) { + iounmap (io_mem); + return -ENODEV; + } + + if (rio_table_ptr) { + if (rio_complete == 1 && rio_table_ptr->ver_num == 3) { rc = ebda_rio_table (); if (rc) { - iounmap(io_mem); + iounmap (io_mem); return rc; - } - iounmap (io_mem); - return 0; + } } } + rc = ebda_rsrc_controller (); + if (rc) { + iounmap (io_mem); + return rc; + } + + rc = ebda_rsrc_rsrc (); + if (rc) { + iounmap (io_mem); + return rc; + } + iounmap (io_mem); - return -ENODEV; + return 0; +} + +/* + * map info of scalability details and rio details from physical address + */ +static int ebda_rio_table (void) +{ + u16 offset; + u8 i; + struct rio_detail *rio_detail_ptr; + + offset = rio_table_ptr->offset; + offset += 12 * rio_table_ptr->scal_count; + + // we do concern about rio details + for (i = 0; i < rio_table_ptr->riodev_count; i++) { + rio_detail_ptr = kmalloc (sizeof (struct rio_detail), GFP_KERNEL); + if (!rio_detail_ptr) + return -ENOMEM; + memset (rio_detail_ptr, 0, sizeof (struct rio_detail)); + rio_detail_ptr->rio_node_id = readb (io_mem + offset); + rio_detail_ptr->bbar = readl (io_mem + offset + 1); + rio_detail_ptr->rio_type = readb (io_mem + offset + 5); + rio_detail_ptr->owner_id = readb (io_mem + offset + 6); + rio_detail_ptr->port0_node_connect = readb (io_mem + offset + 7); + rio_detail_ptr->port0_port_connect = readb (io_mem + offset + 8); + rio_detail_ptr->port1_node_connect = readb (io_mem + offset + 9); + rio_detail_ptr->port1_port_connect = readb (io_mem + offset + 10); + rio_detail_ptr->first_slot_num = readb (io_mem + offset + 11); + rio_detail_ptr->status = readb (io_mem + offset + 12); + rio_detail_ptr->wpindex = readb (io_mem + offset + 13); + rio_detail_ptr->chassis_num = readb (io_mem + offset + 14); +// debug ("rio_node_id: %x\nbbar: %x\nrio_type: %x\nowner_id: %x\nport0_node: %x\nport0_port: %x\nport1_node: %x\nport1_port: %x\nfirst_slot_num: %x\nstatus: %x\n", rio_detail_ptr->rio_node_id, rio_detail_ptr->bbar, rio_detail_ptr->rio_type, rio_detail_ptr->owner_id, rio_detail_ptr->port0_node_connect, rio_detail_ptr->port0_port_connect, rio_detail_ptr->port1_node_connect, rio_detail_ptr->port1_port_connect, rio_detail_ptr->first_slot_num, rio_detail_ptr->status); + //create linked list of chassis + if (rio_detail_ptr->rio_type == 4 || rio_detail_ptr->rio_type == 5) + list_add (&rio_detail_ptr->rio_detail_list, &rio_vg_head); + //create linked list of expansion box + else if (rio_detail_ptr->rio_type == 6 || rio_detail_ptr->rio_type == 7) + list_add (&rio_detail_ptr->rio_detail_list, &rio_lo_head); + else + // not in my concern + kfree (rio_detail_ptr); + offset += 15; + } + print_lo_info (); + print_vg_info (); + return 0; +} + +/* + * reorganizing linked list of chassis + */ +static struct opt_rio *search_opt_vg (u8 chassis_num) +{ + struct opt_rio *ptr; + struct list_head *ptr1; + list_for_each (ptr1, &opt_vg_head) { + ptr = list_entry (ptr1, struct opt_rio, opt_rio_list); + if (ptr->chassis_num == chassis_num) + return ptr; + } + return NULL; +} + +static int combine_wpg_for_chassis (void) +{ + struct opt_rio *opt_rio_ptr = NULL; + struct rio_detail *rio_detail_ptr = NULL; + struct list_head *list_head_ptr = NULL; + + list_for_each (list_head_ptr, &rio_vg_head) { + rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list); + opt_rio_ptr = search_opt_vg (rio_detail_ptr->chassis_num); + if (!opt_rio_ptr) { + opt_rio_ptr = (struct opt_rio *) kmalloc (sizeof (struct opt_rio), GFP_KERNEL); + if (!opt_rio_ptr) + return -ENOMEM; + memset (opt_rio_ptr, 0, sizeof (struct opt_rio)); + opt_rio_ptr->rio_type = rio_detail_ptr->rio_type; + opt_rio_ptr->chassis_num = rio_detail_ptr->chassis_num; + opt_rio_ptr->first_slot_num = rio_detail_ptr->first_slot_num; + opt_rio_ptr->middle_num = rio_detail_ptr->first_slot_num; + list_add (&opt_rio_ptr->opt_rio_list, &opt_vg_head); + } else { + opt_rio_ptr->first_slot_num = min (opt_rio_ptr->first_slot_num, rio_detail_ptr->first_slot_num); + opt_rio_ptr->middle_num = max (opt_rio_ptr->middle_num, rio_detail_ptr->first_slot_num); + } + } + print_opt_vg (); + return 0; +} + +/* + * reorgnizing linked list of expansion box + */ +static struct opt_rio_lo *search_opt_lo (u8 chassis_num) +{ + struct opt_rio_lo *ptr; + struct list_head *ptr1; + list_for_each (ptr1, &opt_lo_head) { + ptr = list_entry (ptr1, struct opt_rio_lo, opt_rio_lo_list); + if (ptr->chassis_num == chassis_num) + return ptr; + } + return NULL; +} + +static int combine_wpg_for_expansion (void) +{ + struct opt_rio_lo *opt_rio_lo_ptr = NULL; + struct rio_detail *rio_detail_ptr = NULL; + struct list_head *list_head_ptr = NULL; + + list_for_each (list_head_ptr, &rio_lo_head) { + rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list); + opt_rio_lo_ptr = search_opt_lo (rio_detail_ptr->chassis_num); + if (!opt_rio_lo_ptr) { + opt_rio_lo_ptr = (struct opt_rio_lo *) kmalloc (sizeof (struct opt_rio_lo), GFP_KERNEL); + if (!opt_rio_lo_ptr) + return -ENOMEM; + memset (opt_rio_lo_ptr, 0, sizeof (struct opt_rio_lo)); + opt_rio_lo_ptr->rio_type = rio_detail_ptr->rio_type; + opt_rio_lo_ptr->chassis_num = rio_detail_ptr->chassis_num; + opt_rio_lo_ptr->first_slot_num = rio_detail_ptr->first_slot_num; + opt_rio_lo_ptr->middle_num = rio_detail_ptr->first_slot_num; + opt_rio_lo_ptr->pack_count = 1; + + list_add (&opt_rio_lo_ptr->opt_rio_lo_list, &opt_lo_head); + } else { + opt_rio_lo_ptr->first_slot_num = min (opt_rio_lo_ptr->first_slot_num, rio_detail_ptr->first_slot_num); + opt_rio_lo_ptr->middle_num = max (opt_rio_lo_ptr->middle_num, rio_detail_ptr->first_slot_num); + opt_rio_lo_ptr->pack_count = 2; + } + } + return 0; +} + +static char *convert_2digits_to_char (int var) +{ + int bit; + char *str1; + + str = (char *) kmalloc (3, GFP_KERNEL); + memset (str, 0, 3); + str1 = (char *) kmalloc (2, GFP_KERNEL); + memset (str, 0, 3); + bit = (int)(var / 10); + switch (bit) { + case 0: + //one digit number + *str = (char)(var + 48); + return str; + default: + //2 digits number + *str1 = (char)(bit + 48); + strncpy (str, str1, 1); + memset (str1, 0, 3); + *str1 = (char)((var % 10) + 48); + strcat (str, str1); + return str; + } + return NULL; +} + +/* Since we don't know the max slot number per each chassis, hence go + * through the list of all chassis to find out the range + * Arguments: slot_num, 1st slot number of the chassis we think we are on, + * var (0 = chassis, 1 = expansion box) + */ +static int first_slot_num (u8 slot_num, u8 first_slot, u8 var) +{ + struct opt_rio *opt_vg_ptr = NULL; + struct opt_rio_lo *opt_lo_ptr = NULL; + struct list_head *ptr = NULL; + int rc = 0; + + if (!var) { + list_for_each (ptr, &opt_vg_head) { + opt_vg_ptr = list_entry (ptr, struct opt_rio, opt_rio_list); + if ((first_slot < opt_vg_ptr->first_slot_num) && (slot_num >= opt_vg_ptr->first_slot_num)) { + rc = -ENODEV; + break; + } + } + } else { + list_for_each (ptr, &opt_lo_head) { + opt_lo_ptr = list_entry (ptr, struct opt_rio_lo, opt_rio_lo_list); + if ((first_slot < opt_lo_ptr->first_slot_num) && (slot_num >= opt_lo_ptr->first_slot_num)) { + rc = -ENODEV; + break; + } + } + } + return rc; } +static struct opt_rio_lo * find_rxe_num (u8 slot_num) +{ + struct opt_rio_lo *opt_lo_ptr; + struct list_head *ptr; + + list_for_each (ptr, &opt_lo_head) { + opt_lo_ptr = list_entry (ptr, struct opt_rio_lo, opt_rio_lo_list); + //check to see if this slot_num belongs to expansion box + if ((slot_num >= opt_lo_ptr->first_slot_num) && (!first_slot_num (slot_num, opt_lo_ptr->first_slot_num, 1))) + return opt_lo_ptr; + } + return NULL; +} + +static struct opt_rio * find_chassis_num (u8 slot_num) +{ + struct opt_rio *opt_vg_ptr; + struct list_head *ptr; + + list_for_each (ptr, &opt_vg_head) { + opt_vg_ptr = list_entry (ptr, struct opt_rio, opt_rio_list); + //check to see if this slot_num belongs to chassis + if ((slot_num >= opt_vg_ptr->first_slot_num) && (!first_slot_num (slot_num, opt_vg_ptr->first_slot_num, 0))) + return opt_vg_ptr; + } + return NULL; +} + +/* This routine will find out how many slots are in the chassis, so that + * the slot numbers for rxe100 would start from 1, and not from 7, or 6 etc + */ +static u8 calculate_first_slot (u8 slot_num) +{ + u8 first_slot = 1; + struct list_head * list; + struct slot * slot_cur; + + list_for_each (list, &ibmphp_slot_head) { + slot_cur = list_entry (list, struct slot, ibm_slot_list); + if (slot_cur->ctrl) { + if ((slot_cur->ctrl->ctlr_type != 4) && (slot_cur->ctrl->ending_slot_num > first_slot) && (slot_num > slot_cur->ctrl->ending_slot_num)) + first_slot = slot_cur->ctrl->ending_slot_num; + } + } + return first_slot + 1; + +} +static char *create_file_name (struct slot * slot_cur) +{ + struct opt_rio *opt_vg_ptr = NULL; + struct opt_rio_lo *opt_lo_ptr = NULL; + char *ptr_chassis_num, *ptr_rxe_num, *ptr_slot_num; + int which = 0; /* rxe = 1, chassis = 0 */ + u8 number = 1; /* either chassis or rxe # */ + u8 first_slot = 1; + u8 slot_num; + u8 flag = 0; + + if (!slot_cur) { + err ("Structure passed is empty \n"); + return NULL; + } + + slot_num = slot_cur->number; + + chassis_str = (char *) kmalloc (30, GFP_KERNEL); + memset (chassis_str, 0, 30); + rxe_str = (char *) kmalloc (30, GFP_KERNEL); + memset (rxe_str, 0, 30); + ptr_chassis_num = (char *) kmalloc (3, GFP_KERNEL); + memset (ptr_chassis_num, 0, 3); + ptr_rxe_num = (char *) kmalloc (3, GFP_KERNEL); + memset (ptr_rxe_num, 0, 3); + ptr_slot_num = (char *) kmalloc (3, GFP_KERNEL); + memset (ptr_slot_num, 0, 3); + + strcpy (chassis_str, "chassis"); + strcpy (rxe_str, "rxe"); + + if (rio_table_ptr) { + if (rio_table_ptr->ver_num == 3) { + opt_vg_ptr = find_chassis_num (slot_num); + opt_lo_ptr = find_rxe_num (slot_num); + } + } + if (opt_vg_ptr) { + if (opt_lo_ptr) { + if ((slot_num - opt_vg_ptr->first_slot_num) > (slot_num - opt_lo_ptr->first_slot_num)) { + number = opt_lo_ptr->chassis_num; + first_slot = opt_lo_ptr->first_slot_num; + which = 1; /* it is RXE */ + } else { + first_slot = opt_vg_ptr->first_slot_num; + number = opt_vg_ptr->chassis_num; + which = 0; + } + } else { + first_slot = opt_vg_ptr->first_slot_num; + number = opt_vg_ptr->chassis_num; + which = 0; + } + ++flag; + } else if (opt_lo_ptr) { + number = opt_lo_ptr->chassis_num; + first_slot = opt_lo_ptr->first_slot_num; + which = 1; + ++flag; + } else if (rio_table_ptr) { + if (rio_table_ptr->ver_num == 3) { + /* if both NULL and we DO have correct RIO table in BIOS */ + return NULL; + } + } + if (!flag) { + if (slot_cur->ctrl->ctlr_type == 4) { + first_slot = calculate_first_slot (slot_num); + which = 1; + } else { + which = 0; + } + } + + switch (which) { + case 0: + /* Chassis */ + *ptr_chassis_num = (char)(number + 48); + strcat (chassis_str, ptr_chassis_num); + kfree (ptr_chassis_num); + strcat (chassis_str, "slot"); + ptr_slot_num = convert_2digits_to_char (slot_num - first_slot + 1); + strcat (chassis_str, ptr_slot_num); + kfree (ptr_slot_num); + return chassis_str; + break; + case 1: + /* RXE */ + *ptr_rxe_num = (char)(number + 48); + strcat (rxe_str, ptr_rxe_num); + kfree (ptr_rxe_num); + strcat (rxe_str, "slot"); + ptr_slot_num = convert_2digits_to_char (slot_num - first_slot + 1); + strcat (rxe_str, ptr_slot_num); + kfree (ptr_slot_num); + return rxe_str; + break; + } + return NULL; +} /* * map info (ctlr-id, slot count, slot#.. bus count, bus#, ctlr type...) of @@ -399,6 +814,8 @@ struct ebda_hpc_slot *slot_ptr; struct bus_info *bus_info_ptr1, *bus_info_ptr2; int rc; + struct slot *slot_cur; + struct list_head *list; addr = hpc_list_ptr->phys_addr; for (ctlr = 0; ctlr < hpc_list_ptr->num_ctlrs; ctlr++) { @@ -509,7 +926,7 @@ hpc_ptr->u.pci_ctlr.bus = readb (io_mem + addr); hpc_ptr->u.pci_ctlr.dev_fun = readb (io_mem + addr + 1); hpc_ptr->irq = readb (io_mem + addr + 2); - addr += 3; + addr += 3; break; case 0: @@ -520,12 +937,6 @@ break; case 2: - hpc_ptr->u.wpeg_ctlr.wpegbbar = readl (io_mem + addr); - hpc_ptr->u.wpeg_ctlr.i2c_addr = readb (io_mem + addr + 4); - - hpc_ptr->irq = readb (io_mem + addr + 5); - addr += 6; - break; case 4: hpc_ptr->u.wpeg_ctlr.wpegbbar = readl (io_mem + addr); hpc_ptr->u.wpeg_ctlr.i2c_addr = readb (io_mem + addr + 4); @@ -536,12 +947,16 @@ iounmap (io_mem); return -ENODEV; } + /* following 3 line: Now our driver only supports I2c ctlrType */ if ((hpc_ptr->ctlr_type != 2) && (hpc_ptr->ctlr_type != 4)) { err ("Please run this driver on ibm xseries440\n "); return -ENODEV; } + //reorganize chassis' linked list + combine_wpg_for_chassis (); + combine_wpg_for_expansion (); hpc_ptr->revision = 0xff; hpc_ptr->options = 0xff; hpc_ptr->starting_slot_num = hpc_ptr->slots[0].slot_num; @@ -565,7 +980,7 @@ } memset (hp_slot_ptr->info, 0, sizeof (struct hotplug_slot_info)); - hp_slot_ptr->name = (char *) kmalloc (10, GFP_KERNEL); + hp_slot_ptr->name = (char *) kmalloc (30, GFP_KERNEL); if (!hp_slot_ptr->name) { iounmap (io_mem); kfree (hp_slot_ptr->info); @@ -582,9 +997,7 @@ return -ENOMEM; } - ((struct slot *)hp_slot_ptr->private)->flag = TRUE; - snprintf (hp_slot_ptr->name, 10, "%d", hpc_ptr->slots[index].slot_num); ((struct slot *) hp_slot_ptr->private)->capabilities = hpc_ptr->slots[index].slot_cap; if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_133_MAX) == EBDA_SLOT_133_MAX) @@ -616,7 +1029,6 @@ ((struct slot *) hp_slot_ptr->private)->number = hpc_ptr->slots[index].slot_num; ((struct slot *) hp_slot_ptr->private)->hotplug_slot = hp_slot_ptr; - rc = ibmphp_hpc_fillhpslotinfo (hp_slot_ptr); if (rc) { iounmap (io_mem); @@ -630,8 +1042,6 @@ } hp_slot_ptr->ops = &ibmphp_hotplug_slot_ops; - pci_hp_register (hp_slot_ptr); - // end of registering ibm slot with hotplug core list_add (& ((struct slot *)(hp_slot_ptr->private))->ibm_slot_list, &ibmphp_slot_head); @@ -641,7 +1051,20 @@ list_add (&hpc_ptr->ebda_hpc_list, &ebda_hpc_head ); } /* each hpc */ + + list_for_each (list, &ibmphp_slot_head) { + slot_cur = list_entry (list, struct slot, ibm_slot_list); + + snprintf (slot_cur->hotplug_slot->name, 30, "%s", create_file_name (slot_cur)); + if (chassis_str) + kfree (chassis_str); + if (rxe_str) + kfree (rxe_str); + pci_hp_register (slot_cur->hotplug_slot); + } + print_ebda_hpc (); + print_ibm_slot (); return 0; } @@ -681,7 +1104,7 @@ addr += 6; debug ("rsrc from io type ----\n"); - debug ("rsrc type: %x bus#: %x dev_func: %x start addr: %lx end addr: %lx\n", + debug ("rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n", rsrc_ptr->rsrc_type, rsrc_ptr->bus_num, rsrc_ptr->dev_fun, rsrc_ptr->start_addr, rsrc_ptr->end_addr); list_add (&rsrc_ptr->ebda_pci_rsrc_list, &ibmphp_ebda_pci_rsrc_head); @@ -702,7 +1125,7 @@ addr += 10; debug ("rsrc from mem or pfm ---\n"); - debug ("rsrc type: %x bus#: %x dev_func: %x start addr: %lx end addr: %lx\n", + debug ("rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n", rsrc_ptr->rsrc_type, rsrc_ptr->bus_num, rsrc_ptr->dev_fun, rsrc_ptr->start_addr, rsrc_ptr->end_addr); list_add (&rsrc_ptr->ebda_pci_rsrc_list, &ibmphp_ebda_pci_rsrc_head); @@ -714,56 +1137,6 @@ return 0; } -/* - * map info of scalability details and rio details from physical address - */ -static int ebda_rio_table(void) -{ - u16 offset; - u8 i; - struct scal_detail *scal_detail_ptr; - struct rio_detail *rio_detail_ptr; - - offset = rio_table_ptr->offset; - for (i = 0; i < rio_table_ptr->scal_count; i++) { - - scal_detail_ptr = kmalloc (sizeof (struct scal_detail), GFP_KERNEL ); - if (!scal_detail_ptr ) - return -ENOMEM; - memset (scal_detail_ptr, 0, sizeof (struct scal_detail) ); - scal_detail_ptr->node_id = readb (io_mem + offset); - scal_detail_ptr->cbar = readl (io_mem+ offset + 1); - scal_detail_ptr->port0_node_connect = readb (io_mem + 5); - scal_detail_ptr->port0_port_connect = readb (io_mem + 6); - scal_detail_ptr->port1_node_connect = readb (io_mem + 7); - scal_detail_ptr->port1_port_connect = readb (io_mem + 8); - scal_detail_ptr->port2_node_connect = readb (io_mem + 9); - scal_detail_ptr->port2_port_connect = readb (io_mem + 10); - debug ("node_id: %x\ncbar: %x\nport0_node: %x\nport0_port: %x\nport1_node: %x\nport1_port: %x\nport2_node: %x\nport2_port: %x\n", scal_detail_ptr->node_id, scal_detail_ptr->cbar, scal_detail_ptr->port0_node_connect, scal_detail_ptr->port0_port_connect, scal_detail_ptr->port1_node_connect, scal_detail_ptr->port1_port_connect, scal_detail_ptr->port2_node_connect, scal_detail_ptr->port2_port_connect); -// list_add (&scal_detail_ptr->scal_detail_list, &scal_detail_head); - offset += 11; - } - for (i=0; i < rio_table_ptr->riodev_count; i++) { - rio_detail_ptr = kmalloc (sizeof (struct rio_detail), GFP_KERNEL ); - if (!rio_detail_ptr ) - return -ENOMEM; - memset (rio_detail_ptr, 0, sizeof (struct rio_detail) ); - rio_detail_ptr->rio_node_id = readb (io_mem + offset ); - rio_detail_ptr->bbar = readl (io_mem + offset + 1); - rio_detail_ptr->rio_type = readb (io_mem + offset + 5); - rio_detail_ptr->owner_id = readb (io_mem + offset + 6); - rio_detail_ptr->port0_node_connect = readb (io_mem + offset + 7); - rio_detail_ptr->port0_port_connect = readb (io_mem + offset + 8); - rio_detail_ptr->port1_node_connect = readb (io_mem + offset + 9); - rio_detail_ptr->port1_port_connect = readb (io_mem + offset + 10); - rio_detail_ptr->first_slot_num = readb (io_mem + offset + 11); - rio_detail_ptr->status = readb (io_mem + offset + 12); - debug ("rio_node_id: %x\nbbar: %x\nrio_type: %x\nowner_id: %x\nport0_node: %x\nport0_port: %x\nport1_node: %x\nport1_port: %x\nfirst_slot_num: %x\nstatus: %x\n", rio_detail_ptr->rio_node_id, rio_detail_ptr->bbar, rio_detail_ptr->rio_type, rio_detail_ptr->owner_id, rio_detail_ptr->port0_node_connect, rio_detail_ptr->port0_port_connect, rio_detail_ptr->port1_node_connect, rio_detail_ptr->port1_port_connect, rio_detail_ptr->first_slot_num, rio_detail_ptr->status); - offset += 13; - } - return 0; -} - u16 ibmphp_get_total_controllers (void) { return hpc_list_ptr->num_ctlrs; @@ -829,27 +1202,9 @@ } } -/* - * Calculate the total hot pluggable slots controlled by total hpcs - */ -/* -int ibmphp_get_total_hp_slots (void) -{ - struct ebda_hpc *ptr; - int slot_num = 0; - - ptr = ebda_hpc_head; - while (ptr != NULL) { - slot_num += ptr->slot_count; - ptr = ptr->next; - } - return slot_num; -} -*/ - void ibmphp_free_ebda_hpc_queue (void) { - struct controller *controller; + struct controller *controller = NULL; struct list_head *list; struct list_head *next; @@ -871,4 +1226,3 @@ resource = NULL; } } - diff -Nru a/drivers/hotplug/ibmphp_hpc.c b/drivers/hotplug/ibmphp_hpc.c --- a/drivers/hotplug/ibmphp_hpc.c Fri Sep 13 10:57:25 2002 +++ b/drivers/hotplug/ibmphp_hpc.c Fri Sep 13 10:57:25 2002 @@ -106,8 +106,8 @@ //---------------------------------------------------------------------------- // local function prototypes //---------------------------------------------------------------------------- -static u8 ctrl_read (struct controller *, void *, u8); -static u8 ctrl_write (struct controller *, void *, u8, u8); +static u8 i2c_ctrl_read (struct controller *, void *, u8); +static u8 i2c_ctrl_write (struct controller *, void *, u8, u8); static u8 hpc_writecmdtoindex (u8, u8); static u8 hpc_readcmdtoindex (u8, u8); static void get_hpc_access (void); @@ -141,12 +141,12 @@ } /*---------------------------------------------------------------------- -* Name: ctrl_read +* Name: i2c_ctrl_read * * Action: read from HPC over I2C * *---------------------------------------------------------------------*/ -static u8 ctrl_read (struct controller *ctlr_ptr, void *WPGBbar, u8 index) +static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void *WPGBbar, u8 index) { u8 status; int i; @@ -248,13 +248,13 @@ } /*---------------------------------------------------------------------- -* Name: ctrl_write +* Name: i2c_ctrl_write * * Action: write to HPC over I2C * * Return 0 or error codes *---------------------------------------------------------------------*/ -static u8 ctrl_write (struct controller *ctlr_ptr, void *WPGBbar, u8 index, u8 cmd) +static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void *WPGBbar, u8 index, u8 cmd) { u8 rc; void *wpg_addr; // base addr + offset @@ -350,6 +350,33 @@ return (rc); } +static u8 ctrl_read (struct controller *ctlr, void *base, u8 offset) +{ + u8 rc; + switch (ctlr->ctlr_type) { + case 2: + case 4: + rc = i2c_ctrl_read (ctlr, base, offset); + break; + default: + return -ENODEV; + } + return rc; +} + +static u8 ctrl_write (struct controller *ctlr, void *base, u8 offset, u8 data) +{ + u8 rc = 0; + switch (ctlr->ctlr_type) { + case 2: + case 4: + rc = i2c_ctrl_write(ctlr, base, offset, data); + break; + default: + return -ENODEV; + } + return rc; +} /*---------------------------------------------------------------------- * Name: hpc_writecmdtoindex() * @@ -448,7 +475,7 @@ *---------------------------------------------------------------------*/ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus) { - void *wpg_bbar; + void *wpg_bbar = NULL; struct controller *ctlr_ptr; struct list_head *pslotlist; u8 index, status; @@ -490,7 +517,8 @@ //-------------------------------------------------------------------- // map physical address to logical address //-------------------------------------------------------------------- - wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE); + if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) + wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE); //-------------------------------------------------------------------- // check controller status before reading @@ -568,7 +596,11 @@ //-------------------------------------------------------------------- // cleanup //-------------------------------------------------------------------- - iounmap (wpg_bbar); // remove physical to logical address mapping + + // remove physical to logical address mapping + if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) + iounmap (wpg_bbar); + free_hpc_access (); debug_polling ("%s - Exit rc[%d]\n", __FUNCTION__, rc); @@ -582,7 +614,7 @@ *---------------------------------------------------------------------*/ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) { - void *wpg_bbar; + void *wpg_bbar = NULL; struct controller *ctlr_ptr; u8 index, status; int busindex; @@ -625,12 +657,13 @@ //-------------------------------------------------------------------- // map physical address to logical address //-------------------------------------------------------------------- - wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE); + if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) { + wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE); - debug ("%s - ctlr id[%x] physical[%lx] logical[%lx] i2c[%x]\n", __FUNCTION__, + debug ("%s - ctlr id[%x] physical[%lx] logical[%lx] i2c[%x]\n", __FUNCTION__, ctlr_ptr->ctlr_id, (ulong) (ctlr_ptr->u.wpeg_ctlr.wpegbbar), (ulong) wpg_bbar, ctlr_ptr->u.wpeg_ctlr.i2c_addr); - + } //-------------------------------------------------------------------- // check controller status before writing //-------------------------------------------------------------------- @@ -667,7 +700,10 @@ ctlr_ptr->status = status; } // cleanup - iounmap (wpg_bbar); // remove physical to logical address mapping + + // remove physical to logical address mapping + if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) + iounmap (wpg_bbar); free_hpc_access (); debug_polling ("%s - Exit rc[%d]\n", __FUNCTION__, rc); @@ -700,6 +736,7 @@ void ibmphp_lock_operations (void) { down (&semOperations); + to_debug = TRUE; } /*---------------------------------------------------------------------- @@ -709,6 +746,7 @@ { debug ("%s - Entry\n", __FUNCTION__); up (&semOperations); + to_debug = FALSE; debug ("%s - Exit\n", __FUNCTION__); } @@ -733,82 +771,86 @@ debug ("%s - Entry\n", __FUNCTION__); while (!ibmphp_shutdown) { + if (ibmphp_shutdown) + break; + /* try to get the lock to do some kind of harware access */ down (&semOperations); switch (poll_state) { - case POLL_LATCH_REGISTER: - oldlatchlow = curlatchlow; - ctrl_count = 0x00; - list_for_each (pslotlist, &ibmphp_slot_head) { - if (ctrl_count >= ibmphp_get_total_controllers()) - break; - pslot = list_entry (pslotlist, struct slot, ibm_slot_list); - if (pslot->ctrl->ctlr_relative_id == ctrl_count) { - ctrl_count++; - if (READ_SLOT_LATCH (pslot->ctrl)) { - rc = ibmphp_hpc_readslot (pslot, - READ_SLOTLATCHLOWREG, - &curlatchlow); - if (oldlatchlow != curlatchlow) - process_changeinlatch (oldlatchlow, - curlatchlow, - pslot->ctrl); - } + case POLL_LATCH_REGISTER: + oldlatchlow = curlatchlow; + ctrl_count = 0x00; + list_for_each (pslotlist, &ibmphp_slot_head) { + if (ctrl_count >= ibmphp_get_total_controllers()) + break; + pslot = list_entry (pslotlist, struct slot, ibm_slot_list); + if (pslot->ctrl->ctlr_relative_id == ctrl_count) { + ctrl_count++; + if (READ_SLOT_LATCH (pslot->ctrl)) { + rc = ibmphp_hpc_readslot (pslot, + READ_SLOTLATCHLOWREG, + &curlatchlow); + if (oldlatchlow != curlatchlow) + process_changeinlatch (oldlatchlow, + curlatchlow, + pslot->ctrl); } } - poll_state = POLL_SLOTS; - break; - - case POLL_SLOTS: - list_for_each (pslotlist, &ibmphp_slot_head) { - pslot = list_entry (pslotlist, struct slot, ibm_slot_list); - // make a copy of the old status - memcpy ((void *) &myslot, (void *) pslot, - sizeof (struct slot)); - rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL); - if ((myslot.status != pslot->status) - || (myslot.ext_status != pslot->ext_status)) - process_changeinstatus (pslot, &myslot); + } + ++poll_count; + poll_state = POLL_SLEEP; + break; + case POLL_SLOTS: + list_for_each (pslotlist, &ibmphp_slot_head) { + pslot = list_entry (pslotlist, struct slot, ibm_slot_list); + // make a copy of the old status + memcpy ((void *) &myslot, (void *) pslot, + sizeof (struct slot)); + rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL); + if ((myslot.status != pslot->status) + || (myslot.ext_status != pslot->ext_status)) + process_changeinstatus (pslot, &myslot); + } + ctrl_count = 0x00; + list_for_each (pslotlist, &ibmphp_slot_head) { + if (ctrl_count >= ibmphp_get_total_controllers()) + break; + pslot = list_entry (pslotlist, struct slot, ibm_slot_list); + if (pslot->ctrl->ctlr_relative_id == ctrl_count) { + ctrl_count++; + if (READ_SLOT_LATCH (pslot->ctrl)) + rc = ibmphp_hpc_readslot (pslot, + READ_SLOTLATCHLOWREG, + &curlatchlow); } + } + ++poll_count; + poll_state = POLL_SLEEP; + break; + case POLL_SLEEP: + /* don't sleep with a lock on the hardware */ + up (&semOperations); + long_delay (POLL_INTERVAL_SEC * HZ); - ctrl_count = 0x00; - list_for_each (pslotlist, &ibmphp_slot_head) { - if (ctrl_count >= ibmphp_get_total_controllers()) - break; - pslot = list_entry (pslotlist, struct slot, ibm_slot_list); - if (pslot->ctrl->ctlr_relative_id == ctrl_count) { - ctrl_count++; - if (READ_SLOT_LATCH (pslot->ctrl)) - rc = ibmphp_hpc_readslot (pslot, - READ_SLOTLATCHLOWREG, - &curlatchlow); - } - } - ++poll_count; - if (poll_count >= POLL_LATCH_CNT) { - poll_count = 0; - poll_state = POLL_SLEEP; - } + if (ibmphp_shutdown) break; - - case POLL_SLEEP: - /* don't sleep with a lock on the hardware */ - up (&semOperations); - long_delay (POLL_INTERVAL_SEC * HZ); - down (&semOperations); + + down (&semOperations); + + if (poll_count >= POLL_LATCH_CNT) { + poll_count = 0; + poll_state = POLL_SLOTS; + } else poll_state = POLL_LATCH_REGISTER; - break; - } - + break; + } /* give up the harware semaphore */ up (&semOperations); - /* sleep for a short time just for good measure */ set_current_state (TASK_INTERRUPTIBLE); schedule_timeout (HZ/10); } - up (&sem_exit); debug ("%s - Exit\n", __FUNCTION__); } @@ -1070,15 +1112,23 @@ debug ("ibmphp_hpc_stop_poll_thread - Entry\n"); ibmphp_shutdown = TRUE; + debug ("before locking operations \n"); ibmphp_lock_operations (); - + debug ("after locking operations \n"); + // wait for poll thread to exit + debug ("before sem_exit down \n"); down (&sem_exit); + debug ("after sem_exit down \n"); // cleanup + debug ("before free_hpc_access \n"); free_hpc_access (); + debug ("after free_hpc_access \n"); ibmphp_unlock_operations (); + debug ("after unlock operations \n"); up (&sem_exit); + debug ("after sem exit up\n"); debug ("ibmphp_hpc_stop_poll_thread - Exit\n"); } diff -Nru a/drivers/hotplug/ibmphp_pci.c b/drivers/hotplug/ibmphp_pci.c --- a/drivers/hotplug/ibmphp_pci.c Fri Sep 13 10:57:25 2002 +++ b/drivers/hotplug/ibmphp_pci.c Fri Sep 13 10:57:25 2002 @@ -920,16 +920,30 @@ debug ("flag_io = %x, flag_mem = %x, flag_pfmem = %x\n", flag_io, flag_mem, flag_pfmem); if (flag_io && flag_mem && flag_pfmem) { - bus = kmalloc (sizeof (struct bus_node), GFP_KERNEL); + /* If on bootup, there was a bridged card in this slot, + * then card was removed and ibmphp got unloaded and loaded + * back again, there's no way for us to remove the bus + * struct, so no need to kmalloc, can use existing node + */ + bus = ibmphp_find_res_bus (sec_number); if (!bus) { - err ("out of system memory \n"); - retval = -ENOMEM; + bus = kmalloc (sizeof (struct bus_node), GFP_KERNEL); + if (!bus) { + err ("out of system memory \n"); + retval = -ENOMEM; + goto error; + } + memset (bus, 0, sizeof (struct bus_node)); + bus->busno = sec_number; + debug ("b4 adding new bus\n"); + rc = add_new_bus (bus, io, mem, pfmem, func->busno); + } else if (!(bus->rangeIO) && !(bus->rangeMem) && !(bus->rangePFMem)) + rc = add_new_bus (bus, io, mem, pfmem, 0xFF); + else { + err ("expected bus structure not empty? \n"); + retval = -EIO; goto error; } - memset (bus, 0, sizeof (struct bus_node)); - bus->busno = sec_number; - debug ("b4 adding new bus\n"); - rc = add_new_bus (bus, io, mem, pfmem, func->busno); if (rc) { if (rc == -ENOMEM) { ibmphp_remove_bus (bus, func->busno); @@ -1579,7 +1593,6 @@ } if (sl->func) { - debug ("do we come in here? \n"); cur_func = sl->func; while (cur_func) { /* TO DO: WILL MOST LIKELY NEED TO GET RID OF THE BUS STRUCTURE FROM RESOURCES AS WELL */ @@ -1619,6 +1632,7 @@ sl->func = NULL; *slot_cur = sl; + debug ("%s - exit\n", __FUNCTION__); return 0; } @@ -1638,14 +1652,15 @@ struct bus_node *cur_bus = NULL; /* Trying to find the parent bus number */ - cur_bus = ibmphp_find_res_bus (parent_busno); - if (!cur_bus) { - err ("strange, cannot find bus which is supposed to be at the system... something is terribly wrong...\n"); - return -ENODEV; + if (parent_busno != 0xFF) { + cur_bus = ibmphp_find_res_bus (parent_busno); + if (!cur_bus) { + err ("strange, cannot find bus which is supposed to be at the system... something is terribly wrong...\n"); + return -ENODEV; + } + + list_add (&bus->bus_list, &cur_bus->bus_list); } - - list_add (&bus->bus_list, &cur_bus->bus_list); - if (io) { io_range = kmalloc (sizeof (struct range_node), GFP_KERNEL); if (!io_range) { @@ -1698,6 +1713,7 @@ int min, max; u8 busno; struct bus_info *bus; + struct bus_node *bus_cur; bus = ibmphp_find_same_bus_num (primary_busno); if (!bus) { @@ -1712,7 +1728,12 @@ } busno = (u8) (slotno - (u8) min); busno += primary_busno + 0x01; - if (!ibmphp_find_res_bus (busno)) + bus_cur = ibmphp_find_res_bus (busno); + /* either there is no such bus number, or there are no ranges, which + * can only happen if we removed the bridged device in previous load + * of the driver, and now only have the skeleton bus struct + */ + if ((!bus_cur) || (!(bus_cur->rangeIO) && !(bus_cur->rangeMem) && !(bus_cur->rangePFMem))) return busno; return 0xff; } diff -Nru a/drivers/hotplug/ibmphp_res.c b/drivers/hotplug/ibmphp_res.c --- a/drivers/hotplug/ibmphp_res.c Fri Sep 13 10:57:25 2002 +++ b/drivers/hotplug/ibmphp_res.c Fri Sep 13 10:57:25 2002 @@ -44,11 +44,16 @@ static inline struct bus_node *find_bus_wprev (u8, struct bus_node **, u8); static LIST_HEAD(gbuses); - -static struct bus_node * alloc_error_bus (struct ebda_pci_rsrc * curr) +LIST_HEAD(ibmphp_res_head); +static struct bus_node * alloc_error_bus (struct ebda_pci_rsrc * curr, u8 busno, int flag) { struct bus_node * newbus; + if (!(curr) && !(flag)) { + err ("NULL pointer passed \n"); + return NULL; + } + newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL); if (!newbus) { err ("out of system memory \n"); @@ -56,14 +61,24 @@ } memset (newbus, 0, sizeof (struct bus_node)); - newbus->busno = curr->bus_num; + if (flag) + newbus->busno = busno; + else + newbus->busno = curr->bus_num; list_add_tail (&newbus->bus_list, &gbuses); return newbus; } static struct resource_node * alloc_resources (struct ebda_pci_rsrc * curr) { - struct resource_node *rs = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + struct resource_node *rs; + + if (!curr) { + err ("NULL passed to allocate \n"); + return NULL; + } + + rs = kmalloc (sizeof (struct resource_node), GFP_KERNEL); if (!rs) { err ("out of system memory \n"); return NULL; @@ -298,7 +313,7 @@ * actually appears... */ if (ibmphp_add_resource (new_mem) < 0) { - newbus = alloc_error_bus (curr); + newbus = alloc_error_bus (curr, 0, 0); if (!newbus) return -ENOMEM; newbus->firstMem = new_mem; @@ -315,7 +330,7 @@ new_pfmem->type = PFMEM; new_pfmem->fromMem = FALSE; if (ibmphp_add_resource (new_pfmem) < 0) { - newbus = alloc_error_bus (curr); + newbus = alloc_error_bus (curr, 0, 0); if (!newbus) return -ENOMEM; newbus->firstPFMem = new_pfmem; @@ -339,7 +354,7 @@ * range actually appears... */ if (ibmphp_add_resource (new_io) < 0) { - newbus = alloc_error_bus (curr); + newbus = alloc_error_bus (curr, 0, 0); if (!newbus) return -ENOMEM; newbus->firstIO = new_io; @@ -351,8 +366,6 @@ } } - debug ("after the while loop in rsrc_init \n"); - list_for_each (tmp, &gbuses) { bus_cur = list_entry (tmp, struct bus_node, bus_list); /* This is to get info about PPB resources, since EBDA doesn't put this info into the primary bus info */ @@ -360,11 +373,9 @@ if (rc) return rc; } - debug ("b4 once_over in rsrc_init \n"); rc = once_over (); /* This is to align ranges (so no -1) */ if (rc) return rc; - debug ("after once_over in rsrc_init \n"); return 0; } @@ -579,7 +590,7 @@ * based on their resource type and sorted by their starting addresses. It assigns * the ptrs to next and nextRange if needed. * - * Input: 3 diff. resources (nulled out if not needed) + * Input: resource ptr * Output: ptrs assigned (to the node) * 0 or -1 *******************************************************************************/ @@ -592,12 +603,17 @@ struct resource_node *res_start = NULL; debug ("%s - enter\n", __FUNCTION__); + + if (!res) { + err ("NULL passed to add \n"); + return -ENODEV; + } bus_cur = find_bus_wprev (res->busno, NULL, 0); if (!bus_cur) { /* didn't find a bus, smth's wrong!!! */ - err ("no bus in the system, either pci_dev's wrong or allocation failed\n"); + debug ("no bus in the system, either pci_dev's wrong or allocation failed\n"); return -ENODEV; } @@ -768,6 +784,11 @@ struct resource_node *mem_cur; char * type = ""; + if (!res) { + err ("resource to remove is NULL \n"); + return -ENODEV; + } + bus_cur = find_bus_wprev (res->busno, NULL, 0); if (!bus_cur) { @@ -796,7 +817,6 @@ res_prev = NULL; while (res_cur) { - /* ???????????DO WE _NEED_ TO BE CHECKING FOR END AS WELL?????????? */ if ((res_cur->start == res->start) && (res_cur->end == res->end)) break; res_prev = res_cur; @@ -980,7 +1000,7 @@ if (!bus_cur) { /* didn't find a bus, smth's wrong!!! */ - err ("no bus in the system, either pci_dev's wrong or allocation failed \n"); + debug ("no bus in the system, either pci_dev's wrong or allocation failed \n"); return -EINVAL; } @@ -1339,7 +1359,7 @@ prev_bus = find_bus_wprev (parent_busno, NULL, 0); if (!prev_bus) { - err ("something terribly wrong. Cannot find parent bus to the one to remove\n"); + debug ("something terribly wrong. Cannot find parent bus to the one to remove\n"); return -ENODEV; } @@ -1466,13 +1486,18 @@ /* * find the resource node in the bus - * Input: Resource needed, start address of the resource, type or resource + * Input: Resource needed, start address of the resource, type of resource */ int ibmphp_find_resource (struct bus_node *bus, u32 start_address, struct resource_node **res, int flag) { struct resource_node *res_cur = NULL; char * type = ""; + if (!bus) { + err ("The bus passed in NULL to find resource \n"); + return -ENODEV; + } + switch (flag) { case IO: res_cur = bus->firstIO; @@ -1513,11 +1538,11 @@ res_cur = res_cur->next; } if (!res_cur) { - err ("SOS...cannot find %s resource in the bus. \n", type); + debug ("SOS...cannot find %s resource in the bus. \n", type); return -EINVAL; } } else { - err ("SOS... cannot find %s resource in the bus. \n", type); + debug ("SOS... cannot find %s resource in the bus. \n", type); return -EINVAL; } } @@ -1755,6 +1780,8 @@ struct range_node *range; struct resource_node *res; struct list_head *tmp; + + debug_pci ("*****************START**********************\n"); if ((!list_empty(&gbuses)) && flags) { err ("The GBUSES is not NULL?!?!?!?!?\n"); @@ -1763,50 +1790,50 @@ list_for_each (tmp, &gbuses) { bus_cur = list_entry (tmp, struct bus_node, bus_list); - debug ("This is bus # %d. There are \n", bus_cur->busno); - debug ("IORanges = %d\t", bus_cur->noIORanges); - debug ("MemRanges = %d\t", bus_cur->noMemRanges); - debug ("PFMemRanges = %d\n", bus_cur->noPFMemRanges); - debug ("The IO Ranges are as follows:\n"); + debug_pci ("This is bus # %d. There are \n", bus_cur->busno); + debug_pci ("IORanges = %d\t", bus_cur->noIORanges); + debug_pci ("MemRanges = %d\t", bus_cur->noMemRanges); + debug_pci ("PFMemRanges = %d\n", bus_cur->noPFMemRanges); + debug_pci ("The IO Ranges are as follows:\n"); if (bus_cur->rangeIO) { range = bus_cur->rangeIO; for (i = 0; i < bus_cur->noIORanges; i++) { - debug ("rangeno is %d\n", range->rangeno); - debug ("[%x - %x]\n", range->start, range->end); + debug_pci ("rangeno is %d\n", range->rangeno); + debug_pci ("[%x - %x]\n", range->start, range->end); range = range->next; } } - debug ("The Mem Ranges are as follows:\n"); + debug_pci ("The Mem Ranges are as follows:\n"); if (bus_cur->rangeMem) { range = bus_cur->rangeMem; for (i = 0; i < bus_cur->noMemRanges; i++) { - debug ("rangeno is %d\n", range->rangeno); - debug ("[%x - %x]\n", range->start, range->end); + debug_pci ("rangeno is %d\n", range->rangeno); + debug_pci ("[%x - %x]\n", range->start, range->end); range = range->next; } } - debug ("The PFMem Ranges are as follows:\n"); + debug_pci ("The PFMem Ranges are as follows:\n"); if (bus_cur->rangePFMem) { range = bus_cur->rangePFMem; for (i = 0; i < bus_cur->noPFMemRanges; i++) { - debug ("rangeno is %d\n", range->rangeno); - debug ("[%x - %x]\n", range->start, range->end); + debug_pci ("rangeno is %d\n", range->rangeno); + debug_pci ("[%x - %x]\n", range->start, range->end); range = range->next; } } - debug ("The resources on this bus are as follows\n"); + debug_pci ("The resources on this bus are as follows\n"); - debug ("IO...\n"); + debug_pci ("IO...\n"); if (bus_cur->firstIO) { res = bus_cur->firstIO; while (res) { - debug ("The range # is %d\n", res->rangeno); - debug ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); - debug ("[%x - %x], len=%x\n", res->start, res->end, res->len); + debug_pci ("The range # is %d\n", res->rangeno); + debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); + debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len); if (res->next) res = res->next; else if (res->nextRange) @@ -1815,13 +1842,13 @@ break; } } - debug ("Mem...\n"); + debug_pci ("Mem...\n"); if (bus_cur->firstMem) { res = bus_cur->firstMem; while (res) { - debug ("The range # is %d\n", res->rangeno); - debug ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); - debug ("[%x - %x], len=%x\n", res->start, res->end, res->len); + debug_pci ("The range # is %d\n", res->rangeno); + debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); + debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len); if (res->next) res = res->next; else if (res->nextRange) @@ -1830,13 +1857,13 @@ break; } } - debug ("PFMem...\n"); + debug_pci ("PFMem...\n"); if (bus_cur->firstPFMem) { res = bus_cur->firstPFMem; while (res) { - debug ("The range # is %d\n", res->rangeno); - debug ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); - debug ("[%x - %x], len=%x\n", res->start, res->end, res->len); + debug_pci ("The range # is %d\n", res->rangeno); + debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); + debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len); if (res->next) res = res->next; else if (res->nextRange) @@ -1846,23 +1873,53 @@ } } - debug ("PFMemFromMem...\n"); + debug_pci ("PFMemFromMem...\n"); if (bus_cur->firstPFMemFromMem) { res = bus_cur->firstPFMemFromMem; while (res) { - debug ("The range # is %d\n", res->rangeno); - debug ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); - debug ("[%x - %x], len=%x\n", res->start, res->end, res->len); + debug_pci ("The range # is %d\n", res->rangeno); + debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); + debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len); res = res->next; } } } + debug_pci ("***********************END***********************\n"); +} + +int static range_exists_already (struct range_node * range, struct bus_node * bus_cur, u8 type) +{ + struct range_node * range_cur = NULL; + switch (type) { + case IO: + range_cur = bus_cur->rangeIO; + break; + case MEM: + range_cur = bus_cur->rangeMem; + break; + case PFMEM: + range_cur = bus_cur->rangePFMem; + break; + default: + err ("wrong type passed to find out if range already exists \n"); + return -ENODEV; + } + + while (range_cur) { + if ((range_cur->start == range->start) && (range_cur->end == range->end)) + return 1; + range_cur = range_cur->next; + } + + return 0; } /* This routine will read the windows for any PPB we have and update the * range info for the secondary bus, and will also input this info into * primary bus, since BIOS doesn't. This is for PPB that are in the system - * on bootup + * on bootup. For bridged cards that were added during previous load of the + * driver, only the ranges and the bus structure are added, the devices are + * added from NVRAM * Input: primary busno * Returns: none * Note: this function doesn't take into account IO restrictions etc, @@ -1883,6 +1940,8 @@ struct resource_node *pfmem; struct range_node *range; bus_cur = *bus; + if (!bus_cur) + return -ENODEV; busno = bus_cur->busno; debug ("inside update_bridge_ranges \n"); @@ -1915,6 +1974,12 @@ */ pci_read_config_byte_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_SECONDARY_BUS, &sec_busno); bus_sec = find_bus_wprev (sec_busno, NULL, 0); + /* this bus structure doesn't exist yet, PPB was configured during previous loading of ibmphp */ + if (!bus_sec) { + bus_sec = alloc_error_bus (NULL, sec_busno, 1); + /* the rest will be populated during NVRAM call */ + return 0; + } pci_read_config_byte_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_IO_BASE, &start_io_address); pci_read_config_byte_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_IO_LIMIT, &end_io_address); pci_read_config_word_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_IO_BASE_UPPER16, &upper_io_start); @@ -1925,9 +1990,7 @@ end_address |= (upper_io_end << 16); if ((start_address) && (start_address <= end_address)) { - range = kmalloc (sizeof (struct range_node), GFP_KERNEL); - if (!range) { err ("out of system memory \n"); return -ENOMEM; @@ -1936,33 +1999,39 @@ range->start = start_address; range->end = end_address + 0xfff; - if (bus_sec->noIORanges > 0) - add_range (IO, range, bus_sec); - else { + if (bus_sec->noIORanges > 0) { + if (!range_exists_already (range, bus_sec, IO)) { + add_range (IO, range, bus_sec); + ++bus_sec->noIORanges; + } else { + kfree (range); + range = NULL; + } + } else { /* 1st IO Range on the bus */ range->rangeno = 1; bus_sec->rangeIO = range; + ++bus_sec->noIORanges; } - - ++bus_sec->noIORanges; fix_resources (bus_sec); - - io = kmalloc (sizeof (struct resource_node), GFP_KERNEL); - if (!io) { - kfree (range); - err ("out of system memory \n"); - return -ENOMEM; - } - memset (io, 0, sizeof (struct resource_node)); - io->type = IO; - io->busno = bus_cur->busno; - io->devfunc = ((device << 3) | (function & 0x7)); - io->start = start_address; - io->end = end_address + 0xfff; - io->len = io->end - io->start + 1; - ibmphp_add_resource (io); - } + if (ibmphp_find_resource (bus_cur, start_address, &io, IO)) { + io = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + if (!io) { + kfree (range); + err ("out of system memory \n"); + return -ENOMEM; + } + memset (io, 0, sizeof (struct resource_node)); + io->type = IO; + io->busno = bus_cur->busno; + io->devfunc = ((device << 3) | (function & 0x7)); + io->start = start_address; + io->end = end_address + 0xfff; + io->len = io->end - io->start + 1; + ibmphp_add_resource (io); + } + } pci_read_config_word_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_MEMORY_BASE, &start_mem_address); pci_read_config_word_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_MEMORY_LIMIT, &end_mem_address); @@ -1981,31 +2050,39 @@ range->start = start_address; range->end = end_address + 0xfffff; - if (bus_sec->noMemRanges > 0) - add_range (MEM, range, bus_sec); - else { + if (bus_sec->noMemRanges > 0) { + if (!range_exists_already (range, bus_sec, MEM)) { + add_range (MEM, range, bus_sec); + ++bus_sec->noMemRanges; + } else { + kfree (range); + range = NULL; + } + } else { /* 1st Mem Range on the bus */ range->rangeno = 1; bus_sec->rangeMem = range; + ++bus_sec->noMemRanges; } - ++bus_sec->noMemRanges; fix_resources (bus_sec); - mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); - if (!mem) { - kfree (range); - err ("out of system memory \n"); - return -ENOMEM; + if (ibmphp_find_resource (bus_cur, start_address, &mem, MEM)) { + mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + if (!mem) { + kfree (range); + err ("out of system memory \n"); + return -ENOMEM; + } + memset (mem, 0, sizeof (struct resource_node)); + mem->type = MEM; + mem->busno = bus_cur->busno; + mem->devfunc = ((device << 3) | (function & 0x7)); + mem->start = start_address; + mem->end = end_address + 0xfffff; + mem->len = mem->end - mem->start + 1; + ibmphp_add_resource (mem); } - memset (mem, 0, sizeof (struct resource_node)); - mem->type = MEM; - mem->busno = bus_cur->busno; - mem->devfunc = ((device << 3) | (function & 0x7)); - mem->start = start_address; - mem->end = end_address + 0xfffff; - mem->len = mem->end - mem->start + 1; - ibmphp_add_resource (mem); } pci_read_config_word_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_PREF_MEMORY_BASE, &start_mem_address); pci_read_config_word_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_PREF_MEMORY_LIMIT, &end_mem_address); @@ -2029,32 +2106,40 @@ range->start = start_address; range->end = end_address + 0xfffff; - if (bus_sec->noPFMemRanges > 0) - add_range (PFMEM, range, bus_sec); - else { + if (bus_sec->noPFMemRanges > 0) { + if (!range_exists_already (range, bus_sec, PFMEM)) { + add_range (PFMEM, range, bus_sec); + ++bus_sec->noPFMemRanges; + } else { + kfree (range); + range = NULL; + } + } else { /* 1st PFMem Range on the bus */ range->rangeno = 1; bus_sec->rangePFMem = range; + ++bus_sec->noPFMemRanges; } - ++bus_sec->noPFMemRanges; fix_resources (bus_sec); + if (ibmphp_find_resource (bus_cur, start_address, &pfmem, PFMEM)) { + pfmem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + if (!pfmem) { + kfree (range); + err ("out of system memory \n"); + return -ENOMEM; + } + memset (pfmem, 0, sizeof (struct resource_node)); + pfmem->type = PFMEM; + pfmem->busno = bus_cur->busno; + pfmem->devfunc = ((device << 3) | (function & 0x7)); + pfmem->start = start_address; + pfmem->end = end_address + 0xfffff; + pfmem->len = pfmem->end - pfmem->start + 1; + pfmem->fromMem = FALSE; - pfmem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); - if (!pfmem) { - kfree (range); - err ("out of system memory \n"); - return -ENOMEM; + ibmphp_add_resource (pfmem); } - memset (pfmem, 0, sizeof (struct resource_node)); - pfmem->type = PFMEM; - pfmem->busno = bus_cur->busno; - pfmem->devfunc = ((device << 3) | (function & 0x7)); - pfmem->start = start_address; - pfmem->end = end_address + 0xfffff; - pfmem->len = pfmem->end - pfmem->start + 1; - pfmem->fromMem = FALSE; - ibmphp_add_resource (pfmem); } break; } /* end of switch */