ahci: SYNC with empty NCQ queue only

Fixes #3746
This commit is contained in:
Sebastian Sumpf 2020-05-04 14:24:39 +02:00 committed by Norman Feske
parent 04aeaa25e5
commit ea78d85d35
1 changed files with 18 additions and 8 deletions

View File

@ -124,6 +124,8 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable
{
private:
bool _syncing { false };
struct Request : Block::Request
{
bool valid() const { return operation.valid(); }
@ -162,6 +164,9 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable
block_number_t end = block_number + request.operation.count - 1;
auto overlap_check = [&] (Request const &req) {
if (req.operation.type == Block::Operation::Type::SYNC)
return false;
block_number_t pending_start = req.operation.block_number;
block_number_t pending_end = pending_start + req.operation.count - 1;
@ -266,6 +271,8 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable
_slot_states = port.read<Port::Ci>() | port.read<Port::Sact>();
port.stop();
_syncing = false;
}
Block::Session::Info info() const override
@ -280,10 +287,18 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable
Response submit(Port &port, Block::Request const request) override
{
if (_writeable == false && request.operation.type == Block::Operation::Type::WRITE)
Block::Operation const op = request.operation;
bool const sync = (op.type == Block::Operation::Type::SYNC);
bool const write = (op.type == Block::Operation::Type::WRITE);
if ((sync && _slot_states) || _syncing)
return Response::RETRY;
if (_writeable == false && write)
return Response::REJECTED;
if (Block::Operation::has_payload(request.operation.type)) {
if (Block::Operation::has_payload(op.type)) {
if (port.sanity_check(request) == false || port.dma_base == 0)
return Response::REJECTED;
@ -298,7 +313,6 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable
*r = request;
Block::Operation op = request.operation;
size_t slot = _slots.index(*r);
_slot_states |= 1u << slot;
@ -308,13 +322,9 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable
op.count * _block_size());
/* setup ATA command */
/* write bit for command header + read/write ATA requests */
bool const write = (op.type == Block::Operation::Type::WRITE);
bool const sync = (op.type == Block::Operation::Type::SYNC);
if (sync) {
table.fis.flush_cache_ext();
_syncing = true;
} else if (_ncq_support(port)) {
table.fis.fpdma(write == false, op.block_number, op.count, slot);
/* ensure that 'Cmd::St' is 1 before writing 'Sact' */