forked from luck/tmp_suning_uos_patched
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:
parent
fcb71f6f03
commit
13cc546be3
@ -832,16 +832,31 @@ static int sil24_qc_defer(struct ata_queued_cmd *qc)
|
|||||||
struct ata_link *link = qc->dev->link;
|
struct ata_link *link = qc->dev->link;
|
||||||
struct ata_port *ap = link->ap;
|
struct ata_port *ap = link->ap;
|
||||||
u8 prot = qc->tf.protocol;
|
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
|
* There is a bug in the chip:
|
||||||
* errata doesn't cover all and HSM violation occurs even with
|
* Port LRAM Causes the PRB/SGT Data to be Corrupted
|
||||||
* only one other device active. Always run an ATAPI command
|
* If the host issues a read request for LRAM and SActive registers
|
||||||
* by itself.
|
* 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 (unlikely(ap->excl_link)) {
|
||||||
if (link == ap->excl_link) {
|
if (link == ap->excl_link) {
|
||||||
if (ap->nr_active_links)
|
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;
|
qc->flags |= ATA_QCFLAG_CLEAR_EXCL;
|
||||||
} else
|
} else
|
||||||
return ATA_DEFER_PORT;
|
return ATA_DEFER_PORT;
|
||||||
} else if (unlikely(is_atapi)) {
|
} else if (unlikely(is_excl)) {
|
||||||
ap->excl_link = link;
|
ap->excl_link = link;
|
||||||
if (ap->nr_active_links)
|
if (ap->nr_active_links)
|
||||||
return ATA_DEFER_PORT;
|
return ATA_DEFER_PORT;
|
||||||
|
Loading…
Reference in New Issue
Block a user