sata_sil24: prevent hba lockup when pass-through ATA commands are used
Fix commands timeout with Sil3124/3132 based HBA when pass-through ATA commands [where ATA_QCFLAG_RESULT_TF is set] are used while other commands are active on other devices connected to the same port with a Port Multiplier. Due to a hardware bug, these commands must be sent alone, like ATAPI commands. Signed-off-by: Gwendal Grignou <gwendal@google.com> Acked-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
Родитель
fcb71f6f03
Коммит
13cc546be3
|
@ -832,16 +832,31 @@ static int sil24_qc_defer(struct ata_queued_cmd *qc)
|
|||
struct ata_link *link = qc->dev->link;
|
||||
struct ata_port *ap = link->ap;
|
||||
u8 prot = qc->tf.protocol;
|
||||
int is_atapi = (prot == ATA_PROT_ATAPI ||
|
||||
prot == ATA_PROT_ATAPI_NODATA ||
|
||||
prot == ATA_PROT_ATAPI_DMA);
|
||||
|
||||
/* ATAPI commands completing with CHECK_SENSE cause various
|
||||
* weird problems if other commands are active. PMP DMA CS
|
||||
* errata doesn't cover all and HSM violation occurs even with
|
||||
* only one other device active. Always run an ATAPI command
|
||||
* by itself.
|
||||
*/
|
||||
/*
|
||||
* There is a bug in the chip:
|
||||
* Port LRAM Causes the PRB/SGT Data to be Corrupted
|
||||
* If the host issues a read request for LRAM and SActive registers
|
||||
* while active commands are available in the port, PRB/SGT data in
|
||||
* the LRAM can become corrupted. This issue applies only when
|
||||
* reading from, but not writing to, the LRAM.
|
||||
*
|
||||
* Therefore, reading LRAM when there is no particular error [and
|
||||
* other commands may be outstanding] is prohibited.
|
||||
*
|
||||
* To avoid this bug there are two situations where a command must run
|
||||
* exclusive of any other commands on the port:
|
||||
*
|
||||
* - ATAPI commands which check the sense data
|
||||
* - Passthrough ATA commands which always have ATA_QCFLAG_RESULT_TF
|
||||
* set.
|
||||
*
|
||||
*/
|
||||
int is_excl = (prot == ATA_PROT_ATAPI ||
|
||||
prot == ATA_PROT_ATAPI_NODATA ||
|
||||
prot == ATA_PROT_ATAPI_DMA ||
|
||||
(qc->flags & ATA_QCFLAG_RESULT_TF));
|
||||
|
||||
if (unlikely(ap->excl_link)) {
|
||||
if (link == ap->excl_link) {
|
||||
if (ap->nr_active_links)
|
||||
|
@ -849,7 +864,7 @@ static int sil24_qc_defer(struct ata_queued_cmd *qc)
|
|||
qc->flags |= ATA_QCFLAG_CLEAR_EXCL;
|
||||
} else
|
||||
return ATA_DEFER_PORT;
|
||||
} else if (unlikely(is_atapi)) {
|
||||
} else if (unlikely(is_excl)) {
|
||||
ap->excl_link = link;
|
||||
if (ap->nr_active_links)
|
||||
return ATA_DEFER_PORT;
|
||||
|
|
Загрузка…
Ссылка в новой задаче