staticvoid set_slot_off(struct controller *ctrl)
{ /* * Turn off slot, turn on attention indicator, turn off power * indicator
*/ if (POWER_CTRL(ctrl)) {
pciehp_power_off_slot(ctrl);
/* * After turning power off, we must wait for at least 1 second * before taking any action that relies on power having been * removed from the slot/adapter.
*/
msleep(1000);
}
/** * board_added - Called after a board has been added to the system. * @ctrl: PCIe hotplug controller where board is added * * Turns power on for the board. * Configures board.
*/ staticint board_added(struct controller *ctrl)
{ int retval = 0; struct pci_bus *parent = ctrl->pcie->port->subordinate;
if (POWER_CTRL(ctrl)) { /* Power on slot */
retval = pciehp_power_on_slot(ctrl); if (retval) return retval;
}
/* Check link training status */
retval = pciehp_check_link_status(ctrl); if (retval) goto err_exit;
/* Check for a power fault */ if (ctrl->power_fault_detected || pciehp_query_power_fault(ctrl)) {
ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(ctrl));
retval = -EIO; goto err_exit;
}
retval = pciehp_configure_device(ctrl); if (retval) { if (retval != -EEXIST) {
ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n",
pci_domain_nr(parent), parent->number); goto err_exit;
}
}
/** * remove_board - Turn off slot and Power Indicator * @ctrl: PCIe hotplug controller where board is being removed * @safe_removal: whether the board is safely removed (versus surprise removed)
*/ staticvoid remove_board(struct controller *ctrl, bool safe_removal)
{
pciehp_unconfigure_device(ctrl, safe_removal);
if (POWER_CTRL(ctrl)) {
pciehp_power_off_slot(ctrl);
/* * After turning power off, we must wait for at least 1 second * before taking any action that relies on power having been * removed from the slot/adapter.
*/
msleep(1000);
/* Ignore link or presence changes caused by power off */
atomic_and(~(PCI_EXP_SLTSTA_DLLSC | PCI_EXP_SLTSTA_PDC),
&ctrl->pending_events);
}
mutex_lock(&ctrl->state_lock); switch (ctrl->state) { case BLINKINGOFF_STATE:
pciehp_request(ctrl, DISABLE_SLOT); break; case BLINKINGON_STATE:
pciehp_request(ctrl, PCI_EXP_SLTSTA_PDC); break; default: break;
}
mutex_unlock(&ctrl->state_lock);
}
void pciehp_handle_button_press(struct controller *ctrl)
{
mutex_lock(&ctrl->state_lock); switch (ctrl->state) { case OFF_STATE: case ON_STATE: if (ctrl->state == ON_STATE) {
ctrl->state = BLINKINGOFF_STATE;
ctrl_info(ctrl, "Slot(%s): Button press: will power off in 5 sec\n",
slot_name(ctrl));
} else {
ctrl->state = BLINKINGON_STATE;
ctrl_info(ctrl, "Slot(%s): Button press: will power on in 5 sec\n",
slot_name(ctrl));
} /* blink power indicator and turn off attention */
pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_BLINK,
PCI_EXP_SLTCTL_ATTN_IND_OFF);
schedule_delayed_work(&ctrl->button_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
*/
cancel_delayed_work(&ctrl->button_work); if (ctrl->state == BLINKINGOFF_STATE) {
ctrl->state = ON_STATE;
pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_ON,
PCI_EXP_SLTCTL_ATTN_IND_OFF);
ctrl_info(ctrl, "Slot(%s): Button press: canceling request to power off\n",
slot_name(ctrl));
} else {
ctrl->state = OFF_STATE;
pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
PCI_EXP_SLTCTL_ATTN_IND_OFF);
ctrl_info(ctrl, "Slot(%s): Button press: canceling request to power on\n",
slot_name(ctrl));
} break; default:
ctrl_err(ctrl, "Slot(%s): Button press: ignoring invalid state %#x\n",
slot_name(ctrl), ctrl->state); break;
}
mutex_unlock(&ctrl->state_lock);
}
void pciehp_handle_disable_request(struct controller *ctrl)
{
mutex_lock(&ctrl->state_lock); switch (ctrl->state) { case BLINKINGON_STATE: case BLINKINGOFF_STATE:
cancel_delayed_work(&ctrl->button_work); break;
}
ctrl->state = POWEROFF_STATE;
mutex_unlock(&ctrl->state_lock);
void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events)
{ int present, link_active;
/* * If the slot is on and presence or link has changed, turn it off. * Even if it's occupied again, we cannot assume the card is the same.
*/
mutex_lock(&ctrl->state_lock); switch (ctrl->state) { case BLINKINGOFF_STATE:
cancel_delayed_work(&ctrl->button_work);
fallthrough; case ON_STATE:
ctrl->state = POWEROFF_STATE;
mutex_unlock(&ctrl->state_lock); if (events & PCI_EXP_SLTSTA_DLLSC)
ctrl_info(ctrl, "Slot(%s): Link Down\n",
slot_name(ctrl)); if (events & PCI_EXP_SLTSTA_PDC)
ctrl_info(ctrl, "Slot(%s): Card not present\n",
slot_name(ctrl));
pciehp_disable_slot(ctrl, SURPRISE_REMOVAL); break; default:
mutex_unlock(&ctrl->state_lock); break;
}
/* Turn the slot on if it's occupied or link is up */
mutex_lock(&ctrl->state_lock);
present = pciehp_card_present(ctrl);
link_active = pciehp_check_link_active(ctrl); if (present <= 0 && link_active <= 0) { if (ctrl->state == BLINKINGON_STATE) {
ctrl->state = OFF_STATE;
cancel_delayed_work(&ctrl->button_work);
pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
INDICATOR_NOOP);
ctrl_info(ctrl, "Slot(%s): Card not present\n",
slot_name(ctrl));
}
mutex_unlock(&ctrl->state_lock); return;
}
switch (ctrl->state) { case BLINKINGON_STATE:
cancel_delayed_work(&ctrl->button_work);
fallthrough; case OFF_STATE:
ctrl->state = POWERON_STATE;
mutex_unlock(&ctrl->state_lock); if (present)
ctrl_info(ctrl, "Slot(%s): Card present\n",
slot_name(ctrl)); if (link_active)
ctrl_info(ctrl, "Slot(%s): Link Up\n",
slot_name(ctrl));
ctrl->request_result = pciehp_enable_slot(ctrl); break; default:
mutex_unlock(&ctrl->state_lock); break;
}
}
if (MRL_SENS(ctrl)) {
pciehp_get_latch_status(ctrl, &getstatus); if (getstatus) {
ctrl_info(ctrl, "Slot(%s): Latch open\n",
slot_name(ctrl)); return -ENODEV;
}
}
if (POWER_CTRL(ctrl)) {
pciehp_get_power_status(ctrl, &getstatus); if (getstatus) {
ctrl_info(ctrl, "Slot(%s): Already enabled\n",
slot_name(ctrl)); return 0;
}
}
return board_added(ctrl);
}
staticint pciehp_enable_slot(struct controller *ctrl)
{ int ret;
pm_runtime_get_sync(&ctrl->pcie->port->dev);
ret = __pciehp_enable_slot(ctrl); if (ret && ATTN_BUTTN(ctrl)) /* may be blinking */
pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
INDICATOR_NOOP);
pm_runtime_put(&ctrl->pcie->port->dev);
mutex_lock(&ctrl->state_lock);
ctrl->state = ret ? OFF_STATE : ON_STATE;
mutex_unlock(&ctrl->state_lock);
int pciehp_sysfs_enable_slot(struct hotplug_slot *hotplug_slot)
{ struct controller *ctrl = to_ctrl(hotplug_slot);
mutex_lock(&ctrl->state_lock); switch (ctrl->state) { case BLINKINGON_STATE: case OFF_STATE:
mutex_unlock(&ctrl->state_lock); /* * The IRQ thread becomes a no-op if the user pulls out the * card before the thread wakes up, so initialize to -ENODEV.
*/
ctrl->request_result = -ENODEV;
pciehp_request(ctrl, PCI_EXP_SLTSTA_PDC);
wait_event(ctrl->requester,
!atomic_read(&ctrl->pending_events) &&
!ctrl->ist_running); return ctrl->request_result; case POWERON_STATE:
ctrl_info(ctrl, "Slot(%s): Already in powering on state\n",
slot_name(ctrl)); break; case BLINKINGOFF_STATE: case ON_STATE: case POWEROFF_STATE:
ctrl_info(ctrl, "Slot(%s): Already enabled\n",
slot_name(ctrl)); break; default:
ctrl_err(ctrl, "Slot(%s): Invalid state %#x\n",
slot_name(ctrl), ctrl->state); break;
}
mutex_unlock(&ctrl->state_lock);
return -ENODEV;
}
int pciehp_sysfs_disable_slot(struct hotplug_slot *hotplug_slot)
{ struct controller *ctrl = to_ctrl(hotplug_slot);
mutex_lock(&ctrl->state_lock); switch (ctrl->state) { case BLINKINGOFF_STATE: case ON_STATE:
mutex_unlock(&ctrl->state_lock);
pciehp_request(ctrl, DISABLE_SLOT);
wait_event(ctrl->requester,
!atomic_read(&ctrl->pending_events) &&
!ctrl->ist_running); return ctrl->request_result; case POWEROFF_STATE:
ctrl_info(ctrl, "Slot(%s): Already in powering off state\n",
slot_name(ctrl)); break; case BLINKINGON_STATE: case OFF_STATE: case POWERON_STATE:
ctrl_info(ctrl, "Slot(%s): Already disabled\n",
slot_name(ctrl)); break; default:
ctrl_err(ctrl, "Slot(%s): Invalid state %#x\n",
slot_name(ctrl), ctrl->state); break;
}
mutex_unlock(&ctrl->state_lock);
return -ENODEV;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.15 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.