From a4ba7fe2a6c2b61419b290035bff398ab2591c54 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 2 Apr 2008 10:35:15 +0900 Subject: libata: fix IDENTIFY order in ata_bus_probe() Commit f58229f8060055b08b34008ea08f31de1e2f003c accidentally made ata_bus_probe() not use reverse order probing. Fix it. There currently isn't any PATA driver which uses obsolete ata_bus_probe() path, so this patch is mainly for correctness. Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Tejun Heo 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 48519887f94..2db5c9c9ca1 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2660,7 +2660,7 @@ int ata_bus_probe(struct ata_port *ap) specific sequence bass-ackwards so that PDIAG- is released by the slave device */ - ata_link_for_each_dev(dev, &ap->link) { + ata_link_for_each_dev_reverse(dev, &ap->link) { if (tries[dev->devno]) dev->class = classes[dev->devno]; -- cgit v1.2.3 From 436d34b36202ef724778ded1e9cb10f8c37b32bc Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 2 Apr 2008 17:28:46 +0900 Subject: libata: uninline atapi_cmd_type() Uninline atapi_cmd_type(). It doesn't really have to be inline and more case will be added which need to access unexported libata variable. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 2db5c9c9ca1..e9b69ba489d 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -325,6 +325,39 @@ static void ata_force_horkage(struct ata_device *dev) } } +/** + * atapi_cmd_type - Determine ATAPI command type from SCSI opcode + * @opcode: SCSI opcode + * + * Determine ATAPI command type from @opcode. + * + * LOCKING: + * None. + * + * RETURNS: + * ATAPI_{READ|WRITE|READ_CD|PASS_THRU|MISC} + */ +int atapi_cmd_type(u8 opcode) +{ + switch (opcode) { + case GPCMD_READ_10: + case GPCMD_READ_12: + return ATAPI_READ; + + case GPCMD_WRITE_10: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_10: + return ATAPI_WRITE; + + case GPCMD_READ_CD: + case GPCMD_READ_CD_MSF: + return ATAPI_READ_CD; + + default: + return ATAPI_MISC; + } +} + /** * ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure * @tf: Taskfile to convert @@ -7774,6 +7807,7 @@ EXPORT_SYMBOL_GPL(ata_tf_read); EXPORT_SYMBOL_GPL(ata_noop_dev_select); EXPORT_SYMBOL_GPL(ata_std_dev_select); EXPORT_SYMBOL_GPL(sata_print_link_status); +EXPORT_SYMBOL_GPL(atapi_cmd_type); EXPORT_SYMBOL_GPL(ata_tf_to_fis); EXPORT_SYMBOL_GPL(ata_tf_from_fis); EXPORT_SYMBOL_GPL(ata_pack_xfermask); -- cgit v1.2.3 From e52dcc4899cf1b7601379c31542bd91cd2997a64 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 2 Apr 2008 17:35:19 +0900 Subject: libata: ATA_12/16 doesn't fall into ATAPI_MISC SAT passthrus don't really fit into ATAPI_MISC class. SAT passthru commands always transfer multiple of 512 bytes and variable length response is not allowed. This patch creates a separate category - ATAPI_PASS_THRU - for these. This fixes HSM violation on "hdparm -I". Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index e9b69ba489d..be95fdb6972 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -353,6 +353,11 @@ int atapi_cmd_type(u8 opcode) case GPCMD_READ_CD_MSF: return ATAPI_READ_CD; + case ATA_16: + case ATA_12: + if (atapi_passthru16) + return ATAPI_PASS_THRU; + /* fall thru */ default: return ATAPI_MISC; } -- cgit v1.2.3 From 8243e636c060fe7c10c9cf3bf53fdd2d48901525 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 3 Apr 2008 14:40:55 +0900 Subject: pata_ali: disable ATAPI DMA ATAPI DMA just doesn't work reliably on pata_ali. The IDE driver can do it but for some mysterious reason, pata_ali can't. This patch disables it by default and makes the driver whine during initialization. "pata_ali.atapi_dma" parameter is added so that user can bypass the workaround. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/pata_ali.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index 8786455c901..ce830fe3a36 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -36,6 +36,10 @@ #define DRV_NAME "pata_ali" #define DRV_VERSION "0.7.5" +int ali_atapi_dma = 0; +module_param_named(atapi_dma, ali_atapi_dma, int, 0644); +MODULE_PARM_DESC(atapi_dma, "Enable ATAPI DMA (0=disable, 1=enable)"); + /* * Cable special cases */ @@ -269,6 +273,27 @@ static void ali_set_dmamode(struct ata_port *ap, struct ata_device *adev) } } +/** + * ali_warn_atapi_dma - Warn about ATAPI DMA disablement + * @adev: Device + * + * Whine about ATAPI DMA disablement if @adev is an ATAPI device. + * Can be used as ->dev_config. + */ + +static void ali_warn_atapi_dma(struct ata_device *adev) +{ + struct ata_eh_context *ehc = &adev->link->eh_context; + int print_info = ehc->i.flags & ATA_EHI_PRINTINFO; + + if (print_info && adev->class == ATA_DEV_ATAPI && !ali_atapi_dma) { + ata_dev_printk(adev, KERN_WARNING, + "WARNING: ATAPI DMA disabled for reliablity issues. It can be enabled\n"); + ata_dev_printk(adev, KERN_WARNING, + "WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n"); + } +} + /** * ali_lock_sectors - Keep older devices to 255 sector mode * @adev: Device @@ -283,6 +308,7 @@ static void ali_set_dmamode(struct ata_port *ap, struct ata_device *adev) static void ali_lock_sectors(struct ata_device *adev) { adev->max_sectors = 255; + ali_warn_atapi_dma(adev); } /** @@ -294,6 +320,18 @@ static void ali_lock_sectors(struct ata_device *adev) static int ali_check_atapi_dma(struct ata_queued_cmd *qc) { + if (!ali_atapi_dma) { + /* FIXME: pata_ali can't do ATAPI DMA reliably but the + * IDE alim15x3 driver can. I tried lots of things + * but couldn't find what the actual difference was. + * If you got an idea, please write it to + * linux-ide@vger.kernel.org and cc htejun@gmail.com. + * + * Disable ATAPI DMA for now. + */ + return -EOPNOTSUPP; + } + /* If its not a media command, its not worth it */ if (atapi_cmd_type(qc->cdb[0]) == ATAPI_MISC) return -EOPNOTSUPP; @@ -359,6 +397,7 @@ static struct ata_port_operations ali_20_port_ops = { .tf_load = ata_tf_load, .tf_read = ata_tf_read, + .check_atapi_dma = ali_check_atapi_dma, .check_status = ata_check_status, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, @@ -438,6 +477,7 @@ static struct ata_port_operations ali_c5_port_ops = { .check_status = ata_check_status, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, + .dev_config = ali_warn_atapi_dma, .freeze = ata_bmdma_freeze, .thaw = ata_bmdma_thaw, -- cgit v1.2.3