From 4742d54fa4b391342dfb8f34de14d51da101fb39 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Mon, 2 Apr 2007 16:20:35 -0400 Subject: 2.6.21 fix lba48 bug in libata fill_result_tf() Current 2.6.21 libata does the following: void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) { struct ata_ioports *ioaddr = &ap->ioaddr; tf->command = ata_check_status(ap); ... if (tf->flags & ATA_TFLAG_LBA48) { iowrite8(tf->ctl | ATA_HOB, ioaddr->ctl_addr); tf->hob_feature = ioread8(ioaddr->error_addr); ... } } ... static void fill_result_tf(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; ap->ops->tf_read(ap, &qc->result_tf); qc->result_tf.flags = qc->tf.flags; } Based on this, those last two statements fill_result_tf() appear to me to be in the wrong order, in that the tf->flags are uninitialized at the point where tf_read() is invoked. So for lba48 commands, tf_read() won't be reading back the full lba48 register contents.. Correct? This patch corrects fill_result_tf() so that the flags get copied to result_tf before they are used by tf_read(). Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index ddb3909d728..e07142b4bb5 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4717,8 +4717,8 @@ static void fill_result_tf(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - ap->ops->tf_read(ap, &qc->result_tf); qc->result_tf.flags = qc->tf.flags; + ap->ops->tf_read(ap, &qc->result_tf); } /** -- cgit v1.2.3 From 277239f228654fc03affdf2aa0e7a3969f420415 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Fri, 30 Mar 2007 17:45:52 -0400 Subject: libata bugfix: preserve LBA bit for HDIO_DRIVE_TASK Preserve the LBA bit in the DevSel/Head register for HDIO_DRIVE_TASK. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/libata-scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 6cc817a1020..e9364434182 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -333,7 +333,7 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) scsi_cmd[8] = args[3]; scsi_cmd[10] = args[4]; scsi_cmd[12] = args[5]; - scsi_cmd[13] = args[6] & 0x0f; + scsi_cmd[13] = args[6] & 0x4f; scsi_cmd[14] = args[0]; /* Good values for timeout and retries? Values below -- cgit v1.2.3 From 56287768e31268969abd94b38b931a29d1ced1ce Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Mon, 2 Apr 2007 11:30:46 +0800 Subject: libata: Clear tf before doing request sense (take 3) patch 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) Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index c89664a77a9..39f556c0299 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -982,26 +982,27 @@ static int ata_eh_read_log_10h(struct ata_device *dev, * 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(struct ata_queued_cmd *qc, case 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 -- cgit v1.2.3 From 18d6e9d51891f91af4e7351cbab3cb180bb9f430 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Mon, 2 Apr 2007 11:34:15 +0800 Subject: libata: Limit max sector to 128 for TORiSAN DVD drives (take 3) patch 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) Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index e07142b4bb5..84f6f857596 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1784,6 +1784,9 @@ int ata_dev_configure(struct ata_device *dev) 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 ata_device_blacklist [] = { { "_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 */ -- cgit v1.2.3 From 6f23a31d1cbe791a1ce86ffa9b23251ab0a1ef45 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Mon, 2 Apr 2007 11:39:25 +0800 Subject: libata: Limit ATAPI DMA to R/W commands only for TORiSAN DVD drives (take 3) patch 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) Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 84f6f857596..cf2338cbe4e 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1787,6 +1787,10 @@ int ata_dev_configure(struct ata_device *dev) if (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 ata_device_blacklist [] = { { "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 */ @@ -3680,6 +3685,26 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc) struct 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); -- cgit v1.2.3