libata: Workaround/fixes for ATAPI devices (take 3)
cover libata: Workaround/fixes for ATAPI devices (take 3)
patch 1/4: Reorder HSM_ST_FIRST
patch 2/4: Clear tf before doing request sense
patch 3/4: Limit max sector to 128 for TORiSAN DVD drives patch 4/4: Limit ATAPI DMA to R/W commands only for TORiSAN DVD drives
(patch 2/4 revised per Tejun's advice.)
(patch 3/4 revised per Vlad's new test result.)
PATCH 1/4 libata: reorder HSM_ST_FIRST for easier decoding (take 3)
patch 1/4:
Reorder HSM_ST_FIRST, such that the task state transition is easier decoded with human eyes.
---
Patch against libata-dev tree, for your review, thanks.
include/linux/libata.h +2 -2
@@ -315,11 +315,11 @@ enum {enum hsm_task_states {HSM_ST_IDLE ,/* no command on going */ +HSM_ST_FIRST ,/* (waiting the device to) +write CDB or first data block */ HSM_ST ,/* (waiting the device to) transfer data */ HSM_ST_LAST ,/* (waiting the device to) complete command */ HSM_ST_ERR ,/* error */ -HSM_ST_FIRST ,/* (waiting the device to) -write CDB or first data block */ };enum ata_completion_errors {
Re: [PATCH 1/4] libata: reorder HSM_ST_FIRST for easier decoding (take 3)
Quoted 12 lines · Albert Lee
patch 1/4:
ReorderHSM_ST_FIRST, such that the task state transition is easier decoded with human eyes.Signed-off-by Albert Lee <[email protected]>---
Patch against libata-dev tree, for your review, thanks.diff -Nrup
00_libata-dev.ori/include/linux/libata.h01_hsm_st/include/linux/libata.hinclude/linux/libata.h +0
-0@@ -315,11 +315,11 @@ enum {
include/linux/libata.h enum { · line 323
Quoted 10 lines
include/linux/libata.h +2
-2enum hsm_task_states {HSM_ST_IDLE ,/* no command on going */ +HSM_ST_FIRST ,/* (waiting the device to) +write CDB or first data block */ HSM_ST ,/* (waiting the device to) transfer data */ HSM_ST_LAST ,/* (waiting the device to) complete command */ HSM_ST_ERR ,/* error */ -HSM_ST_FIRST ,/* (waiting the device to) -write CDB or first data block */ };
applied 1-4
PATCH 2/4 libata: Clear tf before doing request sense (take 3)
In reply to Albert Leepatch 2/4:
Clear tf before doing request sense.
This fixes the AOpen 56X/AKH timeout problem.
(http://bugzilla.kernel.org/show_bug.cgi?id=8244)
---
Per Tejun's advice to use result_tf instead. Patch against libata-dev tree, for your review, thanks.
drivers/ata/libata-eh.c +11 -11
@@ -982,26 +982,27 @@ static int ata_eh_read_log_10h(struct at* RETURNS: * 0 on success, AC_ERR_* mask on failure */ -static unsigned int atapi_eh_request_sense (struct ata_device *dev, -unsigned char *sense_buf) +static unsigned int atapi_eh_request_sense (struct ata_queued_cmd *qc) { +struct ata_device *dev = qc->dev; +unsigned char *sense_buf = qc->scsicmd->sense_buffer;struct ata_port *ap = dev->ap;struct ata_taskfile tf;u8 cdb[ATAPI_CDB_LEN ];DPRINTK ("ATAPI request sense\n" ); -ata_tf_init (dev, &tf); -/* FIXME: is this needed? */ memset (sense_buf,0 ,SCSI_SENSE_BUFFERSIZE ); -/* XXX: why tf_read here? */ - ap->ops->tf_read (ap, &tf); - -/* fill these in, for the case where they are -not- overwritten */ +/* initialize sense_buf with the error register, +* for the case where they are -not- overwritten +*/ sense_buf[0 ] =0x70 ; - sense_buf[2 ] = tf.feature >>4 ; + sense_buf[2 ] = qc->result_tf.feature >>4 ; + +/* some devices time out if garbage left in tf */ +ata_tf_init (dev, &tf);memset (cdb,0 ,ATAPI_CDB_LEN ); cdb[0 ] =REQUEST_SENSE ;
@@ -1165,8 +1166,7 @@ static unsigned int ata_eh_analyze_tf(stcase ATA_DEV_ATAPI :if (!(qc->ap->pflags &ATA_PFLAG_FROZEN )) { - tmp =atapi_eh_request_sense (qc->dev, - qc->scsicmd->sense_buffer); + tmp =atapi_eh_request_sense (qc);if (!tmp) {/* ATA_QCFLAG_SENSE_VALID is used to * tell atapi_qc_complete() that sense
PATCH 3/4 libata: Limit max sector to 128 for TORiSAN DVD drives (take 3)
In reply to Albert Leepatch 3/4:
The TORiSAN drive locks up when max sector == 256. Limit max sector to 128 for the TORiSAN DRD-N216 drives.
(http://bugzilla.kernel.org/show_bug.cgi?id=6710)
---
Revised to use max sector = 128 per Vlad's new test result. Patch against libata-dev tree, for your review, thanks.
drivers/ata/libata-core.c +6 -0
@@ -1784,6 +1784,9 @@ int ata_dev_configure(struct ata_device dev->max_sectors =ATA_MAX_SECTORS ; } +if (ata_device_blacklisted (dev) &ATA_HORKAGE_MAX_SEC_128 ) + dev->max_sectors =min (ATA_MAX_SECTORS_128 , dev->max_sectors); +if (ap->ops->dev_config) ap->ops->dev_config (ap, dev);
@@ -3352,6 +3355,9 @@ static const struct ata_blacklist_entry { "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA }, { "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA }, +/* Weird ATAPI devices */ + { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 }, +/* Devices we expect to fail diagnostics */ /* Devices where NCQ should be avoided */
include/linux/ata.h +1 -0
@@ -40,6 +40,7 @@ enum {ATA_MAX_DEVICES =2 ,/* per bus/port */ ATA_MAX_PRD =256 ,/* we could make these 256/256 */ ATA_SECT_SIZE =512 , +ATA_MAX_SECTORS_128 =128 ,ATA_MAX_SECTORS =256 , ATA_MAX_SECTORS_LBA48 = 65535,/* TODO: 65536? */
include/linux/libata.h +1 -0
@@ -311,6 +311,7 @@ enum {ATA_HORKAGE_DIAGNOSTIC = (1 <<0 ),/* Failed boot diag */ ATA_HORKAGE_NODMA = (1 <<1 ),/* DMA problems */ ATA_HORKAGE_NONCQ = (1 <<2 ),/* Don't use NCQ */ + ATA_HORKAGE_MAX_SEC_128 = (1 << 3), /* Limit max sects to 128 */ }; enum hsm_task_states {
PATCH 4/4 libata: Limit ATAPI DMA to R/W commands only for TORiSAN DVD drives (take 3)
In reply to Albert Leepatch 4/4:
Limit ATAPI DMA to R/W commands only for TORiSAN DRD-N216 DVD-ROM drives
(http://bugzilla.kernel.org/show_bug.cgi?id=6710)
---
Other command like READ_DVD_STRUCTURE seems to work under ATAPI DMA, but I am convervative about it. So, only allow ATAPI DMA for Read/Write for safty.
Patch against libata-dev tree, for your review, thanks.
drivers/ata/libata-core.c +26 -1
@@ -1787,6 +1787,10 @@ int ata_dev_configure(struct ata_deviceif (ata_device_blacklisted (dev) &ATA_HORKAGE_MAX_SEC_128 ) dev->max_sectors =min (ATA_MAX_SECTORS_128 , dev->max_sectors); +/* limit ATAPI DMA to R/W commands only */ +if (ata_device_blacklisted (dev) &ATA_HORKAGE_DMA_RW_ONLY ) + dev->horkage |=ATA_HORKAGE_DMA_RW_ONLY ; +if (ap->ops->dev_config) ap->ops->dev_config (ap, dev);
@@ -3356,7 +3360,8 @@ static const struct ata_blacklist_entry { "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA },/* Weird ATAPI devices */ - { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 }, + { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 | + ATA_HORKAGE_DMA_RW_ONLY },/* Devices we expect to fail diagnostics */
@@ -3676,6 +3681,26 @@ int ata_check_atapi_dma(struct ata_queuestruct ata_port *ap = qc->ap;int rc =0 ;/* Assume ATAPI DMA is OK by default */ +/* some drives can only do ATAPI DMA on read/write */ +if (unlikely (qc->dev->horkage &ATA_HORKAGE_DMA_RW_ONLY )) { +struct scsi_cmnd *cmd = qc->scsicmd; +u8 *scsicmd = cmd->cmnd; + +switch (scsicmd[0 ]) { +case READ_10 : +case WRITE_10 : +case READ_12 : +case WRITE_12 : +case READ_6 : +case WRITE_6 : +/* atapi dma maybe ok */ +break ; +default : +/* turn off atapi dma */ +return 1 ; + } + } +if (ap->ops->check_atapi_dma) rc = ap->ops->check_atapi_dma (qc);
include/linux/libata.h +1 -0
@@ -312,6 +312,7 @@ enum {ATA_HORKAGE_NODMA = (1 <<1 ),/* DMA problems */ ATA_HORKAGE_NONCQ = (1 <<2 ),/* Don't use NCQ */ ATA_HORKAGE_MAX_SEC_128 = (1 <<3 ),/* Limit max sects to 128 */ + ATA_HORKAGE_DMA_RW_ONLY = (1 << 4), /* ATAPI DMA for RW only */ }; enum hsm_task_states {