diff options
Diffstat (limited to 'drivers/ata/sata_sil24.c')
-rw-r--r-- | drivers/ata/sata_sil24.c | 37 |
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; |