aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/sata_sil24.c
diff options
context:
space:
mode:
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 96fd5260446d..b4c674d83769 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)
832 struct ata_link *link = qc->dev->link; 832 struct ata_link *link = qc->dev->link;
833 struct ata_port *ap = link->ap; 833 struct ata_port *ap = link->ap;
834 u8 prot = qc->tf.protocol; 834 u8 prot = qc->tf.protocol;
835 int is_atapi = (prot == ATA_PROT_ATAPI || 835
836 prot == ATA_PROT_ATAPI_NODATA || 836 /*
837 prot == ATA_PROT_ATAPI_DMA); 837 * There is a bug in the chip:
838 838 * Port LRAM Causes the PRB/SGT Data to be Corrupted
839 /* ATAPI commands completing with CHECK_SENSE cause various 839 * If the host issues a read request for LRAM and SActive registers
840 * weird problems if other commands are active. PMP DMA CS 840 * while active commands are available in the port, PRB/SGT data in
841 * errata doesn't cover all and HSM violation occurs even with 841 * the LRAM can become corrupted. This issue applies only when
842 * only one other device active. Always run an ATAPI command 842 * reading from, but not writing to, the LRAM.
843 * by itself. 843 *
844 */ 844 * Therefore, reading LRAM when there is no particular error [and
845 * other commands may be outstanding] is prohibited.
846 *
847 * To avoid this bug there are two situations where a command must run
848 * exclusive of any other commands on the port:
849 *
850 * - ATAPI commands which check the sense data
851 * - Passthrough ATA commands which always have ATA_QCFLAG_RESULT_TF
852 * set.
853 *
854 */
855 int is_excl = (prot == ATA_PROT_ATAPI ||
856 prot == ATA_PROT_ATAPI_NODATA ||
857 prot == ATA_PROT_ATAPI_DMA ||
858 (qc->flags & ATA_QCFLAG_RESULT_TF));
859
845 if (unlikely(ap->excl_link)) { 860 if (unlikely(ap->excl_link)) {
846 if (link == ap->excl_link) { 861 if (link == ap->excl_link) {
847 if (ap->nr_active_links) 862 if (ap->nr_active_links)
@@ -849,7 +864,7 @@ static int sil24_qc_defer(struct ata_queued_cmd *qc)
849 qc->flags |= ATA_QCFLAG_CLEAR_EXCL; 864 qc->flags |= ATA_QCFLAG_CLEAR_EXCL;
850 } else 865 } else
851 return ATA_DEFER_PORT; 866 return ATA_DEFER_PORT;
852 } else if (unlikely(is_atapi)) { 867 } else if (unlikely(is_excl)) {
853 ap->excl_link = link; 868 ap->excl_link = link;
854 if (ap->nr_active_links) 869 if (ap->nr_active_links)
855 return ATA_DEFER_PORT; 870 return ATA_DEFER_PORT;