/* * Button pressed - See if need to TAKE ACTION!!!
*/
ctrl_info(ctrl, "Button pressed on Slot(%s)\n", slot_name(p_slot));
event_type = INT_BUTTON_PRESS;
if (!(shpchp_query_power_fault(p_slot))) { /* * Power fault Cleared
*/
ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n",
slot_name(p_slot));
p_slot->status = 0x00;
event_type = INT_POWER_FAULT_CLEAR;
} else { /* * Power fault
*/
ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot));
event_type = INT_POWER_FAULT; /* set power fault status for this board */
p_slot->status = 0xFF;
ctrl_info(ctrl, "Power fault bit %x set\n", hp_slot);
}
queue_interrupt_event(p_slot, event_type);
return 1;
}
/* The following routines constitute the bulk of the hotplug controller logic
*/ staticint change_bus_speed(struct controller *ctrl, struct slot *p_slot, enum pci_bus_speed speed)
{ int rc = 0;
ctrl_dbg(ctrl, "Change speed to %d\n", speed);
rc = shpchp_set_bus_speed_mode(p_slot, speed); if (rc) {
ctrl_err(ctrl, "%s: Issue of set bus speed mode command failed\n",
__func__); return WRONG_BUS_FREQUENCY;
} return rc;
}
/* * If other slots on the same bus are occupied, we cannot * change the bus speed.
*/ if (flag) { if (asp < bsp) {
ctrl_err(ctrl, "Speed of bus %x and adapter %x mismatch\n",
bsp, asp);
rc = WRONG_BUS_FREQUENCY;
} return rc;
}
if (asp < msp) { if (bsp != asp)
rc = change_bus_speed(ctrl, pslot, asp);
} else { if (bsp != msp)
rc = change_bus_speed(ctrl, pslot, msp);
} return rc;
}
/** * board_added - Called after a board has been added to the system. * @p_slot: target &slot * * Turns power on for the board. * Configures board.
*/ staticint board_added(struct slot *p_slot)
{
u8 hp_slot;
u8 slots_not_empty = 0; int rc = 0; enum pci_bus_speed asp, bsp, msp; struct controller *ctrl = p_slot->ctrl; struct pci_bus *parent = ctrl->pci_dev->subordinate;
/* Power on slot without connecting to bus */
rc = shpchp_power_on_slot(p_slot); if (rc) {
ctrl_err(ctrl, "Failed to power on slot\n"); return -1;
}
if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) {
rc = shpchp_set_bus_speed_mode(p_slot, PCI_SPEED_33MHz); if (rc) {
ctrl_err(ctrl, "%s: Issue of set bus speed mode command failed\n",
__func__); return WRONG_BUS_FREQUENCY;
}
/* turn on board, blink green LED, turn off Amber LED */
rc = shpchp_slot_enable(p_slot); if (rc) {
ctrl_err(ctrl, "Issue of Slot Enable command failed\n"); return rc;
}
}
rc = shpchp_get_adapter_speed(p_slot, &asp); if (rc) {
ctrl_err(ctrl, "Can't get adapter speed or bus mode mismatch\n"); return WRONG_BUS_FREQUENCY;
}
/* turn on board, blink green LED, turn off Amber LED */
rc = shpchp_slot_enable(p_slot);
if (rc) {
ctrl_err(ctrl, "Issue of Slot Enable command failed\n");
return rc;
}
/* Wait for ~1 second */
msleep(1000);
ctrl_dbg(ctrl, "%s: slot status = %x\n", __func__, p_slot->status);
/* Check for a power fault */
if (p_slot->status == 0xFF) {
/* power fault occurred, but it was benign */
ctrl_dbg(ctrl, "%s: Power fault\n", __func__);
p_slot->status = 0;
goto err_exit;
}
if (shpchp_configure_device(p_slot)) {
ctrl_err(ctrl, "Cannot add device at %04x:%02x:%02x\n",
pci_domain_nr(parent), p_slot->bus, p_slot->device);
goto err_exit;
}
err_exit:
/* turn off slot, turn on Amber LED, turn off Green LED */
rc = shpchp_slot_disable(p_slot);
if (rc) {
ctrl_err(ctrl, "%s: Issue of Slot Disable command failed\n",
__func__);
return rc;
}
return(rc);
}
/**
* remove_board - Turns off slot and LEDs
* @p_slot: target &slot
*/
static int remove_board(struct slot *p_slot)
{
struct controller *ctrl = p_slot->ctrl;
u8 hp_slot;
int rc;
/* Change status to shutdown */
if (p_slot->is_a_board)
p_slot->status = 0x01;
/* turn off slot, turn on Amber LED, turn off Green LED */
rc = shpchp_slot_disable(p_slot);
if (rc) {
ctrl_err(ctrl, "%s: Issue of Slot Disable command failed\n",
__func__);
return rc;
}
rc = shpchp_set_attention_status(p_slot, 0);
if (rc) {
ctrl_err(ctrl, "Issue of Set Attention command failed\n");
return rc;
}
/*
* Note: This function must be called with slot->lock held
*/
static void handle_button_press_event(struct slot *p_slot)
{
u8 getstatus;
struct controller *ctrl = p_slot->ctrl;
switch (p_slot->state) {
case STATIC_STATE:
shpchp_get_power_status(p_slot, &getstatus);
if (getstatus) {
p_slot->state = BLINKINGOFF_STATE;
ctrl_info(ctrl, "PCI slot #%s - powering off due to button press\n",
slot_name(p_slot));
} else {
p_slot->state = BLINKINGON_STATE;
ctrl_info(ctrl, "PCI slot #%s - powering on due to button press\n",
slot_name(p_slot));
}
/* blink green LED and turn off amber */
shpchp_green_led_blink(p_slot);
shpchp_set_attention_status(p_slot, 0);
queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ);
break;
case BLINKINGOFF_STATE:
case BLINKINGON_STATE:
/*
* Cancel if we are still blinking; this means that we
* press the attention again before the 5 sec. limit
* expires to cancel hot-add or hot-remove
*/
ctrl_info(ctrl, "Button cancel on Slot(%s)\n",
slot_name(p_slot));
cancel_delayed_work(&p_slot->work);
if (p_slot->state == BLINKINGOFF_STATE)
shpchp_green_led_on(p_slot);
else
shpchp_green_led_off(p_slot);
shpchp_set_attention_status(p_slot, 0);
ctrl_info(ctrl, "PCI slot #%s - action canceled due to button press\n",
slot_name(p_slot));
p_slot->state = STATIC_STATE;
break;
case POWEROFF_STATE:
case POWERON_STATE:
/*
* Ignore if the slot is on power-on or power-off state;
* this means that the previous attention button action
* to hot-add or hot-remove is undergoing
*/
ctrl_info(ctrl, "Button ignore on Slot(%s)\n",
slot_name(p_slot));
update_slot_info(p_slot);
break;
default:
ctrl_warn(ctrl, "Not a valid state\n");
break;
}
}
/* Check to see if (latch closed, card present, power off) */
mutex_lock(&p_slot->ctrl->crit_sect);
rc = shpchp_get_adapter_status(p_slot, &getstatus);
if (rc || !getstatus) {
ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot));
goto out;
}
rc = shpchp_get_latch_status(p_slot, &getstatus);
if (rc || getstatus) {
ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot));
goto out;
}
rc = shpchp_get_power_status(p_slot, &getstatus);
if (rc || getstatus) {
ctrl_info(ctrl, "Already enabled on slot(%s)\n",
slot_name(p_slot));
goto out;
}
p_slot->is_a_board = 1;
/* We have to save the presence info for these slots */
shpchp_get_adapter_status(p_slot, &p_slot->presence_save);
shpchp_get_power_status(p_slot, &p_slot->pwr_save);
ctrl_dbg(ctrl, "%s: p_slot->pwr_save %x\n", __func__, p_slot->pwr_save);
shpchp_get_latch_status(p_slot, &getstatus);
if ((p_slot->ctrl->pci_dev->vendor == PCI_VENDOR_ID_AMD &&
p_slot->ctrl->pci_dev->device == PCI_DEVICE_ID_AMD_POGO_7458)
&& p_slot->ctrl->num_slots == 1) {
/* handle AMD POGO errata; this must be done before enable */
amd_pogo_errata_save_misc_reg(p_slot);
retval = board_added(p_slot);
/* handle AMD POGO errata; this must be done after enable */
amd_pogo_errata_restore_misc_reg(p_slot);
} else
retval = board_added(p_slot);
if (retval) {
shpchp_get_adapter_status(p_slot, &p_slot->presence_save);
shpchp_get_latch_status(p_slot, &getstatus);
}
int shpchp_sysfs_enable_slot(struct slot *p_slot)
{
int retval = -ENODEV;
struct controller *ctrl = p_slot->ctrl;
mutex_lock(&p_slot->lock);
switch (p_slot->state) {
case BLINKINGON_STATE:
cancel_delayed_work(&p_slot->work);
fallthrough;
case STATIC_STATE:
p_slot->state = POWERON_STATE;
mutex_unlock(&p_slot->lock);
retval = shpchp_enable_slot(p_slot);
mutex_lock(&p_slot->lock);
p_slot->state = STATIC_STATE;
break;
case POWERON_STATE:
ctrl_info(ctrl, "Slot %s is already in powering on state\n",
slot_name(p_slot));
break;
case BLINKINGOFF_STATE:
case POWEROFF_STATE:
ctrl_info(ctrl, "Already enabled on slot %s\n",
slot_name(p_slot));
break;
default:
ctrl_err(ctrl, "Not a valid state on slot %s\n",
slot_name(p_slot));
break;
}
mutex_unlock(&p_slot->lock);
return retval;
}
int shpchp_sysfs_disable_slot(struct slot *p_slot)
{
int retval = -ENODEV;
struct controller *ctrl = p_slot->ctrl;
mutex_lock(&p_slot->lock);
switch (p_slot->state) {
case BLINKINGOFF_STATE:
cancel_delayed_work(&p_slot->work);
fallthrough;
case STATIC_STATE:
p_slot->state = POWEROFF_STATE;
mutex_unlock(&p_slot->lock);
retval = shpchp_disable_slot(p_slot);
mutex_lock(&p_slot->lock);
p_slot->state = STATIC_STATE;
break;
case POWEROFF_STATE:
ctrl_info(ctrl, "Slot %s is already in powering off state\n",
slot_name(p_slot));
break;
case BLINKINGON_STATE:
case POWERON_STATE:
ctrl_info(ctrl, "Already disabled on slot %s\n",
slot_name(p_slot));
break;
default:
ctrl_err(ctrl, "Not a valid state on slot %s\n",
slot_name(p_slot));
break;
}
mutex_unlock(&p_slot->lock);
return retval;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.26 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.