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: Gwendal Grignou <gwendal@google.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
Родитель
6d4f950e9e
Коммит
159a7ff7a1
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче