From: Alan Cox This will allow us to handle the tape drive problems Mark Lord reported On Thu, 20 Sep 2007 22:42:17 +0100 Alan Cox wrote: > > According to information I have received, some ATA (and possibly ATAPI?) > > devices intentionally return some data in these cases. In the case of > > certain ATA devices, this returned data permits inspection of the > > incorrected data. > > News to me. ATA like ST-506/ST-412 exposes error data on I/O READ/WRITE > via the READ_BUFFER functionality but its basically useless without a lot > of knowledge of the drive on anything post ST-412 era. > > Got any references ? > > The other possibility is to whine but accept it happens - on the other > hand being lax about HSM errors is asking for corruption and it seems > to be unique to this tape device. > > (and someone please don't tell me early pre ATAPI standard devices are > trying to return the sense data in this way or I'll be ill) Signed-off-by: Alan Cox Signed-off-by: Andrew Morton --- drivers/ata/libata-core.c | 9 +++++++-- include/linux/libata.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff -puN drivers/ata/libata-core.c~libata-add-a-horkage-entry-for-drq-mishandling-atapi drivers/ata/libata-core.c --- a/drivers/ata/libata-core.c~libata-add-a-horkage-entry-for-drq-mishandling-atapi +++ a/drivers/ata/libata-core.c @@ -5139,8 +5139,13 @@ fsm_start: if (unlikely(status & (ATA_ERR | ATA_DF))) { ata_port_printk(ap, KERN_WARNING, "DRQ=1 with device " "error, dev_stat 0x%X\n", status); - qc->err_mask |= AC_ERR_HSM; - ap->hsm_task_state = HSM_ST_ERR; + + /* Some tape drives muck this up so don't explode + in those cases */ + if (!(qc->dev->horkage & ATA_HORKAGE_DRQ)) { + qc->err_mask |= AC_ERR_HSM; + ap->hsm_task_state = HSM_ST_ERR; + } goto fsm_start; } diff -puN include/linux/libata.h~libata-add-a-horkage-entry-for-drq-mishandling-atapi include/linux/libata.h --- a/include/linux/libata.h~libata-add-a-horkage-entry-for-drq-mishandling-atapi +++ a/include/linux/libata.h @@ -315,6 +315,7 @@ enum { ATA_HORKAGE_NONCQ = (1 << 2), /* Don't use NCQ */ ATA_HORKAGE_MAX_SEC_128 = (1 << 3), /* Limit max sects to 128 */ ATA_HORKAGE_BROKEN_HPA = (1 << 4), /* Broken HPA */ + ATA_HORKAGE_DRQ = (1 << 5), /* Device forgets to clear DRQ on error */ /* DMA mask for user DMA control: User visible values do not renumber */ _