From d92e74d353345d19f762e9501a50b0a5f43f7ba8 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 7 Jun 2007 16:19:15 +0100 Subject: libata-core/sff: Fix multiple assumptions about DMA The ata IRQ ack functions are only used when debugging. Unfortunately almost every controller that calls them can cause crashes in some configurations as there are missing checks for bmdma presence. In addition ata_port_start insists of installing DMA buffers and pad buffers for controllers regardless. The SFF controllers actually need to make that decision dynamically at controller setup time and all need the same helper - so we add ata_sff_port_start. Future patches will switch the SFF drivers to use this. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- include/linux/libata.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/libata.h b/include/linux/libata.h index a6a3113120a4..745c4f9b4caa 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -753,6 +753,7 @@ extern u8 ata_check_status(struct ata_port *ap); extern u8 ata_altstatus(struct ata_port *ap); extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf); extern int ata_port_start (struct ata_port *ap); +extern int ata_sff_port_start (struct ata_port *ap); extern irqreturn_t ata_interrupt (int irq, void *dev_instance); extern void ata_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data); -- cgit v1.2.3-59-g8ed1b From 1dce589c38c36ae69614840ee230183f3a7d43c5 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Thu, 7 Jun 2007 15:49:22 +0800 Subject: libata passthru: support PIO multi commands support the pass through of PIO multi commands. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/ata/libata-scsi.c | 20 ++++++++++++++++---- include/linux/ata.h | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index f70431a4c9e9..8a66ca5f9530 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2551,10 +2551,6 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0) goto invalid_fld; - if (cdb[1] & 0xe0) - /* PIO multi not supported yet */ - goto invalid_fld; - /* * 12 and 16 byte CDBs use different offsets to * provide the various register values. @@ -2606,6 +2602,22 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) tf->device = qc->dev->devno ? tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1; + /* sanity check for pio multi commands */ + if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf)) + goto invalid_fld; + + if (is_multi_taskfile(tf)) { + unsigned int multi_count = 1 << (cdb[1] >> 5); + + /* compare the passed through multi_count + * with the cached multi_count of libata + */ + if (multi_count != dev->multi_count) + ata_dev_printk(dev, KERN_WARNING, + "invalid multi_count %u ignored\n", + multi_count); + } + /* READ/WRITE LONG use a non-standard sect_size */ qc->sect_size = ATA_SECT_SIZE; switch (tf->command) { diff --git a/include/linux/ata.h b/include/linux/ata.h index edb31bfff68f..3e95e5c402d4 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -249,7 +249,7 @@ enum ata_tf_protocols { /* ATA taskfile protocols */ ATA_PROT_UNKNOWN, /* unknown/invalid */ ATA_PROT_NODATA, /* no data */ - ATA_PROT_PIO, /* PIO single sector */ + ATA_PROT_PIO, /* PIO data xfer */ ATA_PROT_DMA, /* DMA */ ATA_PROT_NCQ, /* NCQ */ ATA_PROT_ATAPI, /* packet command, PIO data xfer*/ -- cgit v1.2.3-59-g8ed1b From 2c3d2a46f1ccf591850b20f4fdde12bcf2bf3dfd Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Thu, 7 Jun 2007 16:01:17 +0800 Subject: libata passthru: update cached device paramters INIT_DEV_PARAMS and SET_MULTI_MODE change the device parameters cached by libata. Re-read IDENTIFY DEVICE info and update the cached device paramters when seeing these commands. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/ata/libata-scsi.c | 22 ++++++++++++++++------ include/linux/ata.h | 1 + 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 884f52f43f8f..c228df298bd8 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1363,12 +1363,22 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) * schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE * cache */ - if (ap->ops->error_handler && - !need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) && - ((qc->tf.feature == SETFEATURES_WC_ON) || - (qc->tf.feature == SETFEATURES_WC_OFF))) { - ap->eh_info.action |= ATA_EH_REVALIDATE; - ata_port_schedule_eh(ap); + if (ap->ops->error_handler && !need_sense) { + switch (qc->tf.command) { + case ATA_CMD_SET_FEATURES: + if ((qc->tf.feature == SETFEATURES_WC_ON) || + (qc->tf.feature == SETFEATURES_WC_OFF)) { + ap->eh_info.action |= ATA_EH_REVALIDATE; + ata_port_schedule_eh(ap); + } + break; + + case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */ + case ATA_CMD_SET_MULTI: /* multi_count changed */ + ap->eh_info.action |= ATA_EH_REVALIDATE; + ata_port_schedule_eh(ap); + break; + } } /* For ATA pass thru (SAT) commands, generate a sense block if diff --git a/include/linux/ata.h b/include/linux/ata.h index 3e95e5c402d4..703febb2df31 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -151,6 +151,7 @@ enum { ATA_CMD_WRITE_MULTI_EXT = 0x39, ATA_CMD_WRITE_MULTI_FUA_EXT = 0xCE, ATA_CMD_SET_FEATURES = 0xEF, + ATA_CMD_SET_MULTI = 0xC6, ATA_CMD_PACKET = 0xA0, ATA_CMD_VERIFY = 0x40, ATA_CMD_VERIFY_EXT = 0x42, -- cgit v1.2.3-59-g8ed1b