in hotplug/ibmphp_core.c [893:1054]
static int enable_slot(struct hotplug_slot *hs)
{
int rc, i, rcpr;
struct slot *slot_cur;
u8 function;
struct pci_func *tmp_func;
ibmphp_lock_operations();
debug("ENABLING SLOT........\n");
slot_cur = to_slot(hs);
rc = validate(slot_cur, ENABLE);
if (rc) {
err("validate function failed\n");
goto error_nopower;
}
attn_LED_blink(slot_cur);
rc = set_bus(slot_cur);
if (rc) {
err("was not able to set the bus\n");
goto error_nopower;
}
/*-----------------debugging------------------------------*/
get_cur_bus_info(&slot_cur);
debug("the current bus speed right after set_bus = %x\n",
slot_cur->bus_on->current_speed);
/*----------------------------------------------------------*/
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("Try hot-adding into another bus\n");
rc = -EINVAL;
goto error_nopower;
}
rc = power_on(slot_cur);
if (rc) {
err("something wrong when powering up... please see below for details\n");
/* need to turn off before on, otherwise, blinking overwrites */
attn_off(slot_cur);
attn_on(slot_cur);
if (slot_update(&slot_cur)) {
attn_off(slot_cur);
attn_on(slot_cur);
rc = -ENODEV;
goto exit;
}
/* Check to see the error of why it failed */
if ((SLOT_POWER(slot_cur->status)) &&
!(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");
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");
print_card_capability(slot_cur);
}
ibmphp_update_slot_info(slot_cur);
goto exit;
}
debug("after power_on\n");
/*-----------------------debugging---------------------------*/
get_cur_bus_info(&slot_cur);
debug("the current bus speed right after power_on = %x\n",
slot_cur->bus_on->current_speed);
/*----------------------------------------------------------*/
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");
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))) {
err("power on failed...\n");
goto error_power;
}
slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL);
if (!slot_cur->func) {
/* do update_slot_info here? */
rc = -ENOMEM;
goto error_power;
}
slot_cur->func->busno = slot_cur->bus;
slot_cur->func->device = slot_cur->device;
for (i = 0; i < 4; i++)
slot_cur->func->irq[i] = slot_cur->irq[i];
debug("b4 configure_card, slot_cur->bus = %x, slot_cur->device = %x\n",
slot_cur->bus, slot_cur->device);
if (ibmphp_configure_card(slot_cur->func, slot_cur->number)) {
err("configure_card was unsuccessful...\n");
/* true because don't need to actually deallocate resources,
* just remove references */
ibmphp_unconfigure_card(&slot_cur, 1);
debug("after unconfigure_card\n");
slot_cur->func = NULL;
rc = -ENOMEM;
goto error_power;
}
function = 0x00;
do {
tmp_func = ibm_slot_find(slot_cur->bus, slot_cur->func->device,
function++);
if (tmp_func && !(tmp_func->dev))
ibm_configure_device(tmp_func);
} while (tmp_func);
attn_off(slot_cur);
if (slot_update(&slot_cur)) {
rc = -EFAULT;
goto exit;
}
ibmphp_print_test();
rc = ibmphp_update_slot_info(slot_cur);
exit:
ibmphp_unlock_operations();
return rc;
error_nopower:
attn_off(slot_cur); /* need to turn off if was blinking b4 */
attn_on(slot_cur);
error_cont:
rcpr = slot_update(&slot_cur);
if (rcpr) {
rc = rcpr;
goto exit;
}
ibmphp_update_slot_info(slot_cur);
goto exit;
error_power:
attn_off(slot_cur); /* need to turn off if was blinking b4 */
attn_on(slot_cur);
rcpr = power_off(slot_cur);
if (rcpr) {
rc = rcpr;
goto exit;
}
goto error_cont;
}