Commit 159a7ff7 authored by Gwendal Grignou's avatar Gwendal Grignou Committed by Jeff Garzik

sata_mv: Prevent PIO commands to be defered too long if traffic in progress.

Use excl_link when non NCQ commands are defered, to be sure they are processed
as soon as outstanding commands are completed. It prevents some commands to be
defered indifinitely when using a port multiplier.
Signed-off-by: default avatarGwendal Grignou <gwendal@google.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 6d4f950e
......@@ -1382,6 +1382,25 @@ static int mv_qc_defer(struct ata_queued_cmd *qc)
*/
if (pp->pp_flags & MV_PP_FLAG_DELAYED_EH)
return ATA_DEFER_PORT;
/* PIO commands need exclusive link: no other commands [DMA or PIO]
* can run concurrently.
* set excl_link when we want to send a PIO command in DMA mode
* or a non-NCQ command in NCQ mode.
* When we receive a command from that link, and there are no
* outstanding commands, mark a flag to clear excl_link and let
* the command go through.
*/
if (unlikely(ap->excl_link)) {
if (link == ap->excl_link) {
if (ap->nr_active_links)
return ATA_DEFER_PORT;
qc->flags |= ATA_QCFLAG_CLEAR_EXCL;
return 0;
} else
return ATA_DEFER_PORT;
}
/*
* If the port is completely idle, then allow the new qc.
*/
......@@ -1395,8 +1414,14 @@ static int mv_qc_defer(struct ata_queued_cmd *qc)
* doesn't allow it.
*/
if ((pp->pp_flags & MV_PP_FLAG_EDMA_EN) &&
(pp->pp_flags & MV_PP_FLAG_NCQ_EN) && ata_is_ncq(qc->tf.protocol))
return 0;
(pp->pp_flags & MV_PP_FLAG_NCQ_EN)) {
if (ata_is_ncq(qc->tf.protocol))
return 0;
else {
ap->excl_link = link;
return ATA_DEFER_PORT;
}
}
return ATA_DEFER_PORT;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment