pci/shpc: more generic handle hot-unplug in shpc_slot_command()
Free slot if both conditions (power-led = OFF and state = DISABLED) becomes true regardless of the sequence. It is similar to how PCIe hotplug works. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> Reviewed-by: Anton Kuchin <antonkuchin@yandex-team.ru> Message-Id: <20230216180356.156832-5-vsementsov@yandex-team.ru> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
025e2088db
commit
dedf052a25
@ -258,41 +258,52 @@ static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool shpc_slot_is_off(uint8_t state, uint8_t power, uint8_t attn)
|
||||||
|
{
|
||||||
|
return state == SHPC_STATE_DISABLED && power == SHPC_LED_OFF;
|
||||||
|
}
|
||||||
|
|
||||||
static void shpc_slot_command(SHPCDevice *shpc, uint8_t target,
|
static void shpc_slot_command(SHPCDevice *shpc, uint8_t target,
|
||||||
uint8_t state, uint8_t power, uint8_t attn)
|
uint8_t state, uint8_t power, uint8_t attn)
|
||||||
{
|
{
|
||||||
uint8_t current_state;
|
|
||||||
int slot = SHPC_LOGICAL_TO_IDX(target);
|
int slot = SHPC_LOGICAL_TO_IDX(target);
|
||||||
|
uint8_t old_state = shpc_get_status(shpc, slot, SHPC_SLOT_STATE_MASK);
|
||||||
|
uint8_t old_power = shpc_get_status(shpc, slot, SHPC_SLOT_PWR_LED_MASK);
|
||||||
|
uint8_t old_attn = shpc_get_status(shpc, slot, SHPC_SLOT_ATTN_LED_MASK);
|
||||||
|
|
||||||
if (target < SHPC_CMD_TRGT_MIN || slot >= shpc->nslots) {
|
if (target < SHPC_CMD_TRGT_MIN || slot >= shpc->nslots) {
|
||||||
shpc_invalid_command(shpc);
|
shpc_invalid_command(shpc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
current_state = shpc_get_status(shpc, slot, SHPC_SLOT_STATE_MASK);
|
|
||||||
if (current_state == SHPC_STATE_ENABLED && state == SHPC_STATE_PWRONLY) {
|
if (old_state == SHPC_STATE_ENABLED && state == SHPC_STATE_PWRONLY) {
|
||||||
shpc_invalid_command(shpc);
|
shpc_invalid_command(shpc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (power != SHPC_LED_NO) {
|
if (power == SHPC_LED_NO) {
|
||||||
|
power = old_power;
|
||||||
|
} else {
|
||||||
/* TODO: send event to monitor */
|
/* TODO: send event to monitor */
|
||||||
shpc_set_status(shpc, slot, power, SHPC_SLOT_PWR_LED_MASK);
|
shpc_set_status(shpc, slot, power, SHPC_SLOT_PWR_LED_MASK);
|
||||||
}
|
}
|
||||||
if (attn != SHPC_LED_NO) {
|
|
||||||
|
if (attn == SHPC_LED_NO) {
|
||||||
|
attn = old_attn;
|
||||||
|
} else {
|
||||||
/* TODO: send event to monitor */
|
/* TODO: send event to monitor */
|
||||||
shpc_set_status(shpc, slot, attn, SHPC_SLOT_ATTN_LED_MASK);
|
shpc_set_status(shpc, slot, attn, SHPC_SLOT_ATTN_LED_MASK);
|
||||||
}
|
}
|
||||||
if (state != SHPC_STATE_NO) {
|
|
||||||
|
if (state == SHPC_STATE_NO) {
|
||||||
|
state = old_state;
|
||||||
|
} else {
|
||||||
shpc_set_status(shpc, slot, state, SHPC_SLOT_STATE_MASK);
|
shpc_set_status(shpc, slot, state, SHPC_SLOT_STATE_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((current_state == SHPC_STATE_ENABLED ||
|
if (!shpc_slot_is_off(old_state, old_power, old_attn) &&
|
||||||
current_state == SHPC_STATE_PWRONLY) &&
|
shpc_slot_is_off(state, power, attn))
|
||||||
state == SHPC_STATE_DISABLED)
|
|
||||||
{
|
{
|
||||||
power = shpc_get_status(shpc, slot, SHPC_SLOT_PWR_LED_MASK);
|
|
||||||
/* TODO: track what monitor requested. */
|
|
||||||
/* Look at LED to figure out whether it's ok to remove the device. */
|
|
||||||
if (power == SHPC_LED_OFF) {
|
|
||||||
shpc_free_devices_in_slot(shpc, slot);
|
shpc_free_devices_in_slot(shpc, slot);
|
||||||
shpc_set_status(shpc, slot, 1, SHPC_SLOT_STATUS_MRL_OPEN);
|
shpc_set_status(shpc, slot, 1, SHPC_SLOT_STATUS_MRL_OPEN);
|
||||||
shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_EMPTY,
|
shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_EMPTY,
|
||||||
@ -301,7 +312,6 @@ static void shpc_slot_command(SHPCDevice *shpc, uint8_t target,
|
|||||||
SHPC_SLOT_EVENT_MRL |
|
SHPC_SLOT_EVENT_MRL |
|
||||||
SHPC_SLOT_EVENT_PRESENCE;
|
SHPC_SLOT_EVENT_PRESENCE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void shpc_command(SHPCDevice *shpc)
|
static void shpc_command(SHPCDevice *shpc)
|
||||||
|
Loading…
Reference in New Issue
Block a user