summaryrefslogtreecommitdiffstats
path: root/drivers/ata/sata_sil24.c
diff options
context:
space:
mode:
authorGwendal Grignou <gwendal@google.com>2008-01-10 15:47:56 +0900
committerJeff Garzik <jeff@garzik.org>2008-01-10 16:54:01 -0500
commit13cc546be3060324de9d92ebde3bc9dbd950df23 (patch)
tree19c49aea192b14682bf094ea1a34fca17ddf102f /drivers/ata/sata_sil24.c
parentfcb71f6f034c6c4f6a3ab4a55404c95db6e32653 (diff)
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>
Diffstat (limited to 'drivers/ata/sata_sil24.c')
-rw-r--r--drivers/ata/sata_sil24.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 96fd5260446..b4c674d8376 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -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;