From: Niklas Cassel <niklas.cas...@wdc.com> A command that has ERR_STAT set, does not get to clear PxCI. See AHCI 1.3.1, section 5.3.8, states RegFIS:Entry and RegFIS:ClearCI, and 5.3.16.5 ERR:FatalTaskfile.
Some tests, e.g. test_atapi_tray() call ahci_atapi_test_ready() with ready == false, intentionally sending a command that will cause an error. Thus, ahci_port_check_nonbusy() cannot assume that PxCI and PxSACT will always be cleared for the executed command. Signed-off-by: Niklas Cassel <niklas.cas...@wdc.com> --- tests/qtest/libqos/ahci.c | 27 +++++++++++++++++++++------ tests/qtest/libqos/ahci.h | 2 +- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/tests/qtest/libqos/ahci.c b/tests/qtest/libqos/ahci.c index c1d571e477..2d4981dae4 100644 --- a/tests/qtest/libqos/ahci.c +++ b/tests/qtest/libqos/ahci.c @@ -444,17 +444,32 @@ void ahci_port_check_interrupts(AHCIQState *ahci, uint8_t port, g_assert_cmphex(ahci_px_rreg(ahci, port, AHCI_PX_IS), ==, 0); } -void ahci_port_check_nonbusy(AHCIQState *ahci, uint8_t port, uint8_t slot) +void ahci_port_check_nonbusy(AHCIQState *ahci, AHCICommand *cmd) { + uint8_t slot = cmd->slot; + uint8_t port = cmd->port; uint32_t reg; - /* Assert that the command slot is no longer busy (NCQ) */ + /* For NCQ command with error PxSACT bit should still be set. + * For NCQ command without error, PxSACT bit should be cleared. + * For non-NCQ command, PxSACT bit should always be cleared. */ reg = ahci_px_rreg(ahci, port, AHCI_PX_SACT); - ASSERT_BIT_CLEAR(reg, (1 << slot)); + if (cmd->props->ncq && cmd->errors) { + ASSERT_BIT_SET(reg, (1 << slot)); + } else { + ASSERT_BIT_CLEAR(reg, (1 << slot)); + } - /* Non-NCQ */ + /* For non-NCQ command with error, PxCI bit should still be set. + * For non-NCQ command without error, PxCI bit should be cleared. + * For NCQ command without error, PxCI bit should be cleared. + * For NCQ command with error, PxCI bit may or may not be cleared. */ reg = ahci_px_rreg(ahci, port, AHCI_PX_CI); - ASSERT_BIT_CLEAR(reg, (1 << slot)); + if (!cmd->props->ncq && cmd->errors) { + ASSERT_BIT_SET(reg, (1 << slot)); + } else if (!cmd->errors) { + ASSERT_BIT_CLEAR(reg, (1 << slot)); + } /* And assert that we are generally not busy. */ reg = ahci_px_rreg(ahci, port, AHCI_PX_TFD); @@ -1229,7 +1244,7 @@ void ahci_command_verify(AHCIQState *ahci, AHCICommand *cmd) ahci_port_check_error(ahci, port, cmd->interrupts, cmd->errors); ahci_port_check_interrupts(ahci, port, cmd->interrupts); - ahci_port_check_nonbusy(ahci, port, slot); + ahci_port_check_nonbusy(ahci, cmd); ahci_port_check_cmd_sanity(ahci, cmd); if (cmd->interrupts & AHCI_PX_IS_DHRS) { ahci_port_check_d2h_sanity(ahci, port, slot); diff --git a/tests/qtest/libqos/ahci.h b/tests/qtest/libqos/ahci.h index 88835b6228..2234f46862 100644 --- a/tests/qtest/libqos/ahci.h +++ b/tests/qtest/libqos/ahci.h @@ -594,7 +594,7 @@ void ahci_port_check_error(AHCIQState *ahci, uint8_t port, uint32_t imask, uint8_t emask); void ahci_port_check_interrupts(AHCIQState *ahci, uint8_t port, uint32_t intr_mask); -void ahci_port_check_nonbusy(AHCIQState *ahci, uint8_t port, uint8_t slot); +void ahci_port_check_nonbusy(AHCIQState *ahci, AHCICommand *cmd); void ahci_port_check_d2h_sanity(AHCIQState *ahci, uint8_t port, uint8_t slot); void ahci_port_check_pio_sanity(AHCIQState *ahci, AHCICommand *cmd); void ahci_port_check_cmd_sanity(AHCIQState *ahci, AHCICommand *cmd); -- 2.40.1