diff options
Diffstat (limited to 'drivers/pci/hotplug/ibmphp_core.c')
| -rw-r--r-- | drivers/pci/hotplug/ibmphp_core.c | 282 |
1 files changed, 119 insertions, 163 deletions
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index 7485ffda950..f7b8684a773 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c @@ -49,7 +49,7 @@ int ibmphp_debug; -static int debug; +static bool debug; module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC (debug, "Debugging mode enabled or not"); MODULE_LICENSE ("GPL"); @@ -58,7 +58,7 @@ MODULE_DESCRIPTION (DRIVER_DESC); struct pci_bus *ibmphp_pci_bus; static int max_slots; -static int irqs[16]; /* PIC mode IRQ's we're using so far (in case MPS +static int irqs[16]; /* PIC mode IRQs we're using so far (in case MPS * tables don't provide default info for empty slots */ static int init_flag; @@ -71,20 +71,20 @@ static inline int get_max_adapter_speed (struct hotplug_slot *hs, u8 *value) return get_max_adapter_speed_1 (hs, value, 1); } */ -static inline int get_cur_bus_info(struct slot **sl) +static inline int get_cur_bus_info(struct slot **sl) { int rc = 1; - struct slot * slot_cur = *sl; + struct slot *slot_cur = *sl; debug("options = %x\n", slot_cur->ctrl->options); - debug("revision = %x\n", slot_cur->ctrl->revision); + debug("revision = %x\n", slot_cur->ctrl->revision); - if (READ_BUS_STATUS(slot_cur->ctrl)) + if (READ_BUS_STATUS(slot_cur->ctrl)) rc = ibmphp_hpc_readslot(slot_cur, READ_BUSSTATUS, NULL); - - if (rc) + + if (rc) return rc; - + 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 = @@ -96,7 +96,7 @@ static inline int get_cur_bus_info(struct slot **sl) slot_cur->busstatus, slot_cur->bus_on->current_speed, slot_cur->bus_on->current_bus_mode); - + *sl = slot_cur; return 0; } @@ -104,8 +104,8 @@ static inline int get_cur_bus_info(struct slot **sl) static inline int slot_update(struct slot **sl) { int rc; - rc = ibmphp_hpc_readslot(*sl, READ_ALLSTAT, NULL); - if (rc) + rc = ibmphp_hpc_readslot(*sl, READ_ALLSTAT, NULL); + if (rc) return rc; if (!init_flag) rc = get_cur_bus_info(sl); @@ -114,8 +114,8 @@ static inline int slot_update(struct slot **sl) static int __init get_max_slots (void) { - struct slot * slot_cur; - struct list_head * tmp; + struct slot *slot_cur; + struct list_head *tmp; u8 slot_count = 0; list_for_each(tmp, &ibmphp_slot_head) { @@ -172,7 +172,7 @@ int ibmphp_init_devno(struct slot **cur_slot) debug("(*cur_slot)->irq[3] = %x\n", (*cur_slot)->irq[3]); - debug("rtable->exlusive_irqs = %x\n", + debug("rtable->exclusive_irqs = %x\n", rtable->exclusive_irqs); debug("rtable->slots[loop].irq[0].bitmap = %x\n", rtable->slots[loop].irq[0].bitmap); @@ -271,7 +271,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value) else rc = -ENODEV; } - } else + } else rc = -ENODEV; ibmphp_unlock_operations(); @@ -280,7 +280,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value) return rc; } -static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value) +static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) { int rc = -ENODEV; struct slot *pslot; @@ -288,7 +288,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value) debug("get_attention_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value); - + ibmphp_lock_operations(); if (hotplug_slot) { pslot = hotplug_slot->private; @@ -311,7 +311,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value) return rc; } -static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value) +static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) { int rc = -ENODEV; struct slot *pslot; @@ -338,7 +338,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value) } -static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value) +static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) { int rc = -ENODEV; struct slot *pslot; @@ -364,7 +364,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value) return rc; } -static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 * value) +static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 *value) { int rc = -ENODEV; struct slot *pslot; @@ -395,94 +395,45 @@ static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 * value) return rc; } -static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) +static int get_max_bus_speed(struct slot *slot) { - int rc = -ENODEV; - struct slot *pslot; + int rc; u8 mode = 0; + enum pci_bus_speed speed; + struct pci_bus *bus = slot->hotplug_slot->pci_slot->bus; - debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __func__, - hotplug_slot, value); + debug("%s - Entry slot[%p]\n", __func__, slot); ibmphp_lock_operations(); - - if (hotplug_slot) { - pslot = hotplug_slot->private; - if (pslot) { - rc = 0; - mode = pslot->supported_bus_mode; - *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; - } - } - } - + mode = slot->supported_bus_mode; + speed = slot->supported_speed; ibmphp_unlock_operations(); - debug("%s - Exit rc[%d] value[%x]\n", __func__, rc, *value); - return rc; -} - -static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) -{ - int rc = -ENODEV; - struct slot *pslot; - u8 mode = 0; - - debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __func__, - hotplug_slot, value); - ibmphp_lock_operations(); - - if (hotplug_slot) { - pslot = hotplug_slot->private; - if (pslot) { - rc = get_cur_bus_info(&pslot); - if (!rc) { - mode = pslot->bus_on->current_bus_mode; - *value = pslot->bus_on->current_speed; - 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; - } - } - } + switch (speed) { + case BUS_SPEED_33: + break; + case BUS_SPEED_66: + if (mode == BUS_MODE_PCIX) + speed += 0x01; + break; + case BUS_SPEED_100: + case BUS_SPEED_133: + speed += 0x01; + break; + default: + /* Note (will need to change): there would be soon 256, 512 also */ + rc = -ENODEV; } - ibmphp_unlock_operations(); - debug("%s - Exit rc[%d] value[%x]\n", __func__, rc, *value); + if (!rc) + bus->max_bus_speed = speed; + + debug("%s - Exit rc[%d] speed[%x]\n", __func__, rc, speed); return rc; } /* -static int get_max_adapter_speed_1(struct hotplug_slot *hotplug_slot, u8 * value, u8 flag) +static int get_max_adapter_speed_1(struct hotplug_slot *hotplug_slot, u8 *value, u8 flag) { int rc = -ENODEV; struct slot *pslot; @@ -520,7 +471,7 @@ static int get_max_adapter_speed_1(struct hotplug_slot *hotplug_slot, u8 * value return rc; } -static int get_bus_name(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; @@ -564,14 +515,15 @@ static int __init init_ops(void) debug("BEFORE GETTING SLOT STATUS, slot # %x\n", slot_cur->number); - if (slot_cur->ctrl->revision == 0xFF) + if (slot_cur->ctrl->revision == 0xFF) if (get_ctrl_revision(slot_cur, &slot_cur->ctrl->revision)) return -1; - if (slot_cur->bus_on->current_speed == 0xFF) - if (get_cur_bus_info(&slot_cur)) + if (slot_cur->bus_on->current_speed == 0xFF) + if (get_cur_bus_info(&slot_cur)) return -1; + get_max_bus_speed(slot_cur); if (slot_cur->ctrl->options == 0xFF) if (get_hpc_options(slot_cur, &slot_cur->ctrl->options)) @@ -587,8 +539,8 @@ static int __init init_ops(void) debug("SLOT_PRESENT = %x\n", SLOT_PRESENT(slot_cur->status)); debug("SLOT_LATCH = %x\n", SLOT_LATCH(slot_cur->status)); - if ((SLOT_PWRGD(slot_cur->status)) && - !(SLOT_PRESENT(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); @@ -629,13 +581,13 @@ static int validate(struct slot *slot_cur, int opn) switch (opn) { case ENABLE: - if (!(SLOT_PWRGD(slot_cur->status)) && - (SLOT_PRESENT(slot_cur->status)) && + if (!(SLOT_PWRGD(slot_cur->status)) && + (SLOT_PRESENT(slot_cur->status)) && !(SLOT_LATCH(slot_cur->status))) return 0; break; case DISABLE: - if ((SLOT_PWRGD(slot_cur->status)) && + if ((SLOT_PWRGD(slot_cur->status)) && (SLOT_PRESENT(slot_cur->status)) && !(SLOT_LATCH(slot_cur->status))) return 0; @@ -655,6 +607,7 @@ static int validate(struct slot *slot_cur, int opn) int ibmphp_update_slot_info(struct slot *slot_cur) { struct hotplug_slot_info *info; + struct pci_bus *bus = slot_cur->hotplug_slot->pci_slot->bus; int rc; u8 bus_speed; u8 mode; @@ -664,7 +617,7 @@ int ibmphp_update_slot_info(struct slot *slot_cur) err("out of system memory\n"); return -ENOMEM; } - + info->power_status = SLOT_PWRGD(slot_cur->status); info->attention_status = SLOT_ATTN(slot_cur->status, slot_cur->ext_status); @@ -685,7 +638,7 @@ int ibmphp_update_slot_info(struct slot *slot_cur) case BUS_SPEED_33: break; case BUS_SPEED_66: - if (mode == BUS_MODE_PCIX) + if (mode == BUS_MODE_PCIX) bus_speed += 0x01; else if (mode == BUS_MODE_PCI) ; @@ -700,10 +653,9 @@ int ibmphp_update_slot_info(struct slot *slot_cur) bus_speed = PCI_SPEED_UNKNOWN; } - info->cur_bus_speed = bus_speed; - info->max_bus_speed = slot_cur->hotplug_slot->info->max_bus_speed; - // To do: bus_names - + bus->cur_bus_speed = bus_speed; + // To do: bus_names + rc = pci_hp_change_slot_info(slot_cur->hotplug_slot, info); kfree(info); return rc; @@ -719,7 +671,7 @@ static struct pci_func *ibm_slot_find(u8 busno, u8 device, u8 function) { struct pci_func *func_cur; struct slot *slot_cur; - struct list_head * tmp; + struct list_head *tmp; list_for_each(tmp, &ibmphp_slot_head) { slot_cur = list_entry(tmp, struct slot, ibm_slot_list); if (slot_cur->func) { @@ -744,8 +696,8 @@ static struct pci_func *ibm_slot_find(u8 busno, u8 device, u8 function) static void free_slots(void) { struct slot *slot_cur; - struct list_head * tmp; - struct list_head * next; + struct list_head *tmp; + struct list_head *next; debug("%s -- enter\n", __func__); @@ -766,19 +718,24 @@ static void ibm_unconfigure_device(struct pci_func *func) func->device, func->function); debug("func->device << 3 | 0x0 = %x\n", func->device << 3 | 0x0); + pci_lock_rescan_remove(); + for (j = 0; j < 0x08; j++) { temp = pci_get_bus_and_slot(func->busno, (func->device << 3) | j); if (temp) { - pci_remove_bus_device(temp); + pci_stop_and_remove_bus_device(temp); pci_dev_put(temp); } } + pci_dev_put(func->dev); + + pci_unlock_rescan_remove(); } /* - * The following function is to fix kernel bug regarding - * getting bus entries, here we manually add those primary + * 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) @@ -808,7 +765,7 @@ static u8 bus_structure_fixup(u8 busno) for (dev->devfn = 0; dev->devfn < 256; dev->devfn += 8) { if (!pci_read_config_word(dev, PCI_VENDOR_ID, &l) && (l != 0x0000) && (l != 0xffff)) { - debug("%s - Inside bus_struture_fixup()\n", + debug("%s - Inside bus_structure_fixup()\n", __func__); pci_scan_bus(busno, ibmphp_pci_bus->ops, NULL); break; @@ -823,12 +780,13 @@ static u8 bus_structure_fixup(u8 busno) static int ibm_configure_device(struct pci_func *func) { - unsigned char bus; struct pci_bus *child; int num; int flag = 0; /* this is to make sure we don't double scan the bus, for bridged devices primarily */ + pci_lock_rescan_remove(); + if (!(bus_structure_fixup(func->busno))) flag = 1; if (func->dev == NULL) @@ -838,7 +796,7 @@ static int ibm_configure_device(struct pci_func *func) if (func->dev == NULL) { struct pci_bus *bus = pci_find_bus(0, func->busno); if (!bus) - return 0; + goto out; num = pci_scan_slot(bus, PCI_DEVFN(func->device, func->function)); @@ -849,25 +807,28 @@ static int ibm_configure_device(struct pci_func *func) PCI_DEVFN(func->device, func->function)); if (func->dev == NULL) { err("ERROR... : pci_dev still NULL\n"); - return 0; + goto out; } } if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) { - pci_read_config_byte(func->dev, PCI_SECONDARY_BUS, &bus); - child = pci_add_new_bus(func->dev->bus, func->dev, bus); - pci_do_scan_bus(child); + pci_hp_add_bridge(func->dev); + child = func->dev->subordinate; + if (child) + pci_bus_add_devices(child); } + out: + pci_unlock_rescan_remove(); return 0; } /******************************************************* - * Returns whether the bus is empty or not + * Returns whether the bus is empty or not *******************************************************/ -static int is_bus_empty(struct slot * slot_cur) +static int is_bus_empty(struct slot *slot_cur) { int rc; - struct slot * tmp_slot; + struct slot *tmp_slot; u8 i = slot_cur->bus_on->slot_min; while (i <= slot_cur->bus_on->slot_max) { @@ -890,12 +851,12 @@ static int is_bus_empty(struct slot * slot_cur) } /*********************************************************** - * If the HPC permits and the bus currently empty, tries to set the + * If the HPC permits and the bus currently empty, tries to set the * bus speed and mode at the maximum card and bus capability * Parameters: slot * Returns: bus is set (0) or error code ***********************************************************/ -static int set_bus(struct slot * slot_cur) +static int set_bus(struct slot *slot_cur) { int rc; u8 speed; @@ -904,7 +865,7 @@ static int set_bus(struct slot * slot_cur) static struct pci_device_id ciobx[] = { { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, 0x0101) }, { }, - }; + }; debug("%s - entry slot # %d\n", __func__, slot_cur->number); if (SET_BUS_STATUS(slot_cur->ctrl) && is_bus_empty(slot_cur)) { @@ -925,7 +886,7 @@ static int set_bus(struct slot * slot_cur) else if (!SLOT_BUS_MODE(slot_cur->ext_status)) /* if max slot/bus capability is 66 pci and there's no bus mode mismatch, then - the adapter supports 66 pci */ + the adapter supports 66 pci */ cmd = HPC_BUS_66CONVMODE; else cmd = HPC_BUS_33CONVMODE; @@ -978,7 +939,7 @@ static int set_bus(struct slot * slot_cur) return -EIO; } } - /* This is for x440, once Brandon fixes the firmware, + /* This is for x440, once Brandon fixes the firmware, will not need this delay */ msleep(1000); debug("%s -Exit\n", __func__); @@ -986,16 +947,16 @@ static int set_bus(struct slot * slot_cur) } /* This routine checks the bus limitations that the slot is on from the BIOS. - * This is used in deciding whether or not to power up the slot. + * This is used in deciding whether or not to power up the slot. * (electrical/spec limitations. For example, >1 133 MHz or >2 66 PCI cards on - * same bus) + * same bus) * Parameters: slot * Returns: 0 = no limitations, -EINVAL = exceeded limitations on the bus */ static int check_limitations(struct slot *slot_cur) { u8 i; - struct slot * tmp_slot; + struct slot *tmp_slot; u8 count = 0; u8 limitation = 0; @@ -1034,7 +995,7 @@ static int check_limitations(struct slot *slot_cur) static inline void print_card_capability(struct slot *slot_cur) { info("capability of the card is "); - if ((slot_cur->ext_status & CARD_INFO) == PCIX133) + if ((slot_cur->ext_status & CARD_INFO) == PCIX133) info(" 133 MHz PCI-X\n"); else if ((slot_cur->ext_status & CARD_INFO) == PCIX66) info(" 66 MHz PCI-X\n"); @@ -1068,7 +1029,7 @@ static int enable_slot(struct hotplug_slot *hs) } attn_LED_blink(slot_cur); - + rc = set_bus(slot_cur); if (rc) { err("was not able to set the bus\n"); @@ -1084,8 +1045,7 @@ static int enable_slot(struct hotplug_slot *hs) rc = check_limitations(slot_cur); if (rc) { err("Adding this card exceeds the limitations of this bus.\n"); - err("(i.e., >1 133MHz cards running on same bus, or " - ">2 66 PCI cards running on same bus.\n"); + err("(i.e., >1 133MHz cards running on same bus, or >2 66 PCI cards running on same bus.\n"); err("Try hot-adding into another bus\n"); rc = -EINVAL; goto error_nopower; @@ -1109,12 +1069,10 @@ static int enable_slot(struct hotplug_slot *hs) !(SLOT_PWRGD(slot_cur->status))) err("power fault occurred trying to power up\n"); else if (SLOT_BUS_SPEED(slot_cur->status)) { - err("bus speed mismatch occurred. please check " - "current bus speed and card capability\n"); + err("bus speed mismatch occurred. please check current bus speed and card capability\n"); print_card_capability(slot_cur); } else if (SLOT_BUS_MODE(slot_cur->ext_status)) { - err("bus mode mismatch occurred. please check " - "current bus mode and card capability\n"); + err("bus mode mismatch occurred. please check current bus mode and card capability\n"); print_card_capability(slot_cur); } ibmphp_update_slot_info(slot_cur); @@ -1130,18 +1088,17 @@ static int enable_slot(struct hotplug_slot *hs) rc = slot_update(&slot_cur); if (rc) goto error_power; - + rc = -EINVAL; if (SLOT_POWER(slot_cur->status) && !(SLOT_PWRGD(slot_cur->status))) { err("power fault occurred trying to power up...\n"); goto error_power; } if (SLOT_POWER(slot_cur->status) && (SLOT_BUS_SPEED(slot_cur->status))) { - err("bus speed mismatch occurred. please check current bus " - "speed and card capability\n"); + err("bus speed mismatch occurred. please check current bus speed and card capability\n"); print_card_capability(slot_cur); goto error_power; - } + } /* Don't think this case will happen after above checks... * but just in case, for paranoia sake */ if (!(SLOT_POWER(slot_cur->status))) { @@ -1192,7 +1149,7 @@ static int enable_slot(struct hotplug_slot *hs) ibmphp_print_test(); rc = ibmphp_update_slot_info(slot_cur); exit: - ibmphp_unlock_operations(); + ibmphp_unlock_operations(); return rc; error_nopower: @@ -1228,7 +1185,7 @@ static int ibmphp_disable_slot(struct hotplug_slot *hotplug_slot) { struct slot *slot = hotplug_slot->private; int rc; - + ibmphp_lock_operations(); rc = ibmphp_do_disable_slot(slot); ibmphp_unlock_operations(); @@ -1240,12 +1197,12 @@ int ibmphp_do_disable_slot(struct slot *slot_cur) int rc; u8 flag; - debug("DISABLING SLOT...\n"); - + debug("DISABLING SLOT...\n"); + if ((slot_cur == NULL) || (slot_cur->ctrl == NULL)) { return -ENODEV; } - + flag = slot_cur->flag; slot_cur->flag = 1; @@ -1258,7 +1215,7 @@ int ibmphp_do_disable_slot(struct slot *slot_cur) attn_LED_blink(slot_cur); if (slot_cur->func == NULL) { - /* We need this for fncs's that were there on bootup */ + /* We need this for functions that were there on bootup */ slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL); if (!slot_cur->func) { err("out of system memory\n"); @@ -1270,12 +1227,13 @@ int ibmphp_do_disable_slot(struct slot *slot_cur) } ibm_unconfigure_device(slot_cur->func); - - /* If we got here from latch suddenly opening on operating card or - a power fault, there's no power to the card, so cannot - read from it to determine what resources it occupied. This operation - is forbidden anyhow. The best we can do is remove it from kernel - lists at least */ + + /* + * If we got here from latch suddenly opening on operating card or + * a power fault, there's no power to the card, so cannot + * read from it to determine what resources it occupied. This operation + * is forbidden anyhow. The best we can do is remove it from kernel + * lists at least */ if (!flag) { attn_off(slot_cur); @@ -1312,7 +1270,7 @@ error: rc = -EFAULT; goto exit; } - if (flag) + if (flag) ibmphp_update_slot_info(slot_cur); goto exit; } @@ -1326,8 +1284,6 @@ struct hotplug_slot_ops ibmphp_hotplug_slot_ops = { .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_present, - .get_max_bus_speed = get_max_bus_speed, - .get_cur_bus_speed = get_cur_bus_speed, /* .get_max_adapter_speed = get_max_adapter_speed, .get_bus_name_status = get_bus_name, */ @@ -1389,7 +1345,7 @@ static int __init ibmphp_init(void) debug("AFTER Resource & EBDA INITIALIZATIONS\n"); max_slots = get_max_slots(); - + if ((rc = ibmphp_register_pci())) goto error; |
