From ae8d4ee7ff429136c8b482c3b38ed994c021d3fc Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sun, 4 Nov 2007 22:05:49 -0500 Subject: libata: Disable ATA8-ACS proposed Trusted Computing features by default Historically word 48 in the identify data was used to mean 32bit I/O was supported for VLB IDE etc. ATA8 reassigns this word to the Trusted Computing Group, where it is used for TCG features. This means that an ATA8 TCG drive is going to trigger 32bit I/O on some systems which will be funny. Anyway we need to sort this out ready for ATA8 so: - Reorder the ata.h header a bit so the ata_version function occurs early in it - Make dword_io check the ATA version - Add an ATA8 version checking TCG presence test While we are at it the current drafts have a flaw where it may not be possible to disable TCG features at boot (and opt out of the trusted model) as TCG intends because it relies on presence of a different optional feature (DCS). Handle this in software by refusing the TCG commands if libata.allow_tpm is not set. (We must make it possible as some environments such as proprietary VDR devices will doubtless want to use it to lock up content) Finally as with CPRM print a warning so that the user knows they may not be able to full access and use the device. Signed-off-by: Alan Cox --- drivers/ata/libata-core.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 6380726f7538..9b7f3c477730 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -119,6 +119,10 @@ int libata_noacpi = 0; module_param_named(noacpi, libata_noacpi, int, 0444); MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in probe/suspend/resume when set"); +int libata_allow_tpm = 0; +module_param_named(allow_tpm, libata_allow_tpm, int, 0444); +MODULE_PARM_DESC(allow_tpm, "Permit the use of TPM commands"); + MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("Library module for ATA devices"); MODULE_LICENSE("GPL"); @@ -2161,8 +2165,14 @@ int ata_dev_configure(struct ata_device *dev) "supports DRM functions and may " "not be fully accessable.\n"); snprintf(revbuf, 7, "CFA"); - } else + } else { snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id)); + /* Warn the user if the device has TPM extensions */ + if (ata_id_has_tpm(id)) + ata_dev_printk(dev, KERN_WARNING, + "supports DRM functions and may " + "not be fully accessable.\n"); + } dev->n_sectors = ata_id_n_sectors(id); -- cgit v1.2.3 From b9f8ab2dafba2dc12dd94e5d2db31d5cf495775f Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 19 Nov 2007 14:33:11 +0000 Subject: libata: IORDY handling I believe this version meets all Sergei's objections Correct the logic for when we issue a set features for transfer mode - If the device has IORDY and the controller has IORDY - set the mode - If the device has IORDY and the controller does not - turn IORDY off - If neither has IORDY do nothing Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 9b7f3c477730..3dd0e942df36 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4373,7 +4373,14 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev) tf.feature = SETFEATURES_XFER; tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_POLLING; tf.protocol = ATA_PROT_NODATA; - tf.nsect = dev->xfer_mode; + /* If we are using IORDY we must send the mode setting command */ + if (ata_pio_need_iordy(dev)) + tf.nsect = dev->xfer_mode; + /* If the device has IORDY and the controller does not - turn it off */ + else if (ata_id_has_iordy(dev->id)) + tf.nsect = 0x01; + else /* In the ancient relic department - skip all of this */ + return 0; err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); -- cgit v1.2.3 From 11b7becca9425aab50807503c8102b2db9e5ecf0 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 23 Nov 2007 21:12:14 -0500 Subject: libata: checkpatch fixes Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 6 +++--- drivers/ata/pata_ali.c | 2 +- drivers/ata/pata_ninja32.c | 10 ++++++---- 3 files changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 3dd0e942df36..bb9e025522ba 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4374,11 +4374,11 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev) tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_POLLING; tf.protocol = ATA_PROT_NODATA; /* If we are using IORDY we must send the mode setting command */ - if (ata_pio_need_iordy(dev)) - tf.nsect = dev->xfer_mode; + if (ata_pio_need_iordy(dev)) + tf.nsect = dev->xfer_mode; /* If the device has IORDY and the controller does not - turn it off */ else if (ata_id_has_iordy(dev->id)) - tf.nsect = 0x01; + tf.nsect = 0x01; else /* In the ancient relic department - skip all of this */ return 0; diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index 8caf9afc8b90..7e68edf3c0f3 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -64,7 +64,7 @@ static int ali_cable_override(struct pci_dev *pdev) if (pdev->subsystem_vendor == 0x10CF && pdev->subsystem_device == 0x10AF) return 1; /* Mitac 8317 (Winbook-A) and relatives */ - if (pdev->subsystem_vendor == 0x1071 && pdev->subsystem_device == 0x8317) + if (pdev->subsystem_vendor == 0x1071 && pdev->subsystem_device == 0x8317) return 1; /* Systems by DMI */ if (dmi_check_system(cable_dmi_table)) diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c index 04acd3f86120..1c1b83541d13 100644 --- a/drivers/ata/pata_ninja32.c +++ b/drivers/ata/pata_ninja32.c @@ -61,7 +61,8 @@ static void ninja32_set_piomode(struct ata_port *ap, struct ata_device *adev) static u16 pio_timing[5] = { 0xd6, 0x85, 0x44, 0x33, 0x13 }; - iowrite8(pio_timing[adev->pio_mode - XFER_PIO_0], ap->ioaddr.bmdma_addr + 0x1f); + iowrite8(pio_timing[adev->pio_mode - XFER_PIO_0], + ap->ioaddr.bmdma_addr + 0x1f); ap->private_data = adev; } @@ -176,12 +177,13 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id) iowrite8(0xB3, base + 0x02); /* Burst, ?? setup */ iowrite8(0x00, base + 0x04); /* WAIT0 ? */ /* FIXME: Should we disable them at remove ? */ - return ata_host_activate(host, dev->irq, ata_interrupt, IRQF_SHARED, &ninja32_sht); + return ata_host_activate(host, dev->irq, ata_interrupt, + IRQF_SHARED, &ninja32_sht); } static const struct pci_device_id ninja32[] = { - { 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { 0x1145, 0xf024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0x1145, 0xf024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { }, }; -- cgit v1.2.3 From 405e66b38797875e80669eaf72d313dbb76533c3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 27 Nov 2007 19:28:53 +0900 Subject: libata: implement protocol tests Implement protocol tests - ata_is_atapi(), ata_is_nodata(), ata_is_pio(), ata_is_dma(), ata_is_ncq() and ata_is_data() and use them to replace is_atapi_taskfile() and hard coded protocol tests. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 2 +- drivers/ata/libata-core.c | 36 +++++----------------- drivers/ata/sata_fsl.c | 2 +- drivers/ata/sata_sil.c | 10 +++--- drivers/ata/sata_sil24.c | 24 +++------------ drivers/scsi/libsas/sas_ata.c | 2 +- include/linux/ata.h | 71 ++++++++++++++++++++++++++++++++++++++----- 7 files changed, 82 insertions(+), 65 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index ef5e6b6e6e69..5eee91c73c90 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1511,7 +1511,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct ahci_port_priv *pp = ap->private_data; - int is_atapi = is_atapi_taskfile(&qc->tf); + int is_atapi = ata_is_atapi(qc->tf.protocol); void *cmd_tbl; u32 opts; const u32 cmd_fis_len = 5; /* five dwords */ diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index bb9e025522ba..8c7af2c8e8d4 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5358,7 +5358,7 @@ static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *q (qc->tf.flags & ATA_TFLAG_WRITE)) return 1; - if (is_atapi_taskfile(&qc->tf) && + if (ata_is_atapi(qc->tf.protocol) && !(qc->dev->flags & ATA_DFLAG_CDB_INTR)) return 1; } @@ -5955,30 +5955,6 @@ int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active, return nr_done; } -static inline int ata_should_dma_map(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - - switch (qc->tf.protocol) { - case ATA_PROT_NCQ: - case ATA_PROT_DMA: - case ATA_PROT_ATAPI_DMA: - return 1; - - case ATA_PROT_ATAPI: - case ATA_PROT_PIO: - if (ap->flags & ATA_FLAG_PIO_DMA) - return 1; - - /* fall through */ - - default: - return 0; - } - - /* never reached */ -} - /** * ata_qc_issue - issue taskfile to device * @qc: command to issue to device @@ -5995,6 +5971,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct ata_link *link = qc->dev->link; + u8 prot = qc->tf.protocol; /* Make sure only one non-NCQ command is outstanding. The * check is skipped for old EH because it reuses active qc to @@ -6002,7 +5979,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc) */ WARN_ON(ap->ops->error_handler && ata_tag_valid(link->active_tag)); - if (qc->tf.protocol == ATA_PROT_NCQ) { + if (prot == ATA_PROT_NCQ) { WARN_ON(link->sactive & (1 << qc->tag)); if (!link->sactive) @@ -6018,7 +5995,8 @@ void ata_qc_issue(struct ata_queued_cmd *qc) qc->flags |= ATA_QCFLAG_ACTIVE; ap->qc_active |= 1 << qc->tag; - if (ata_should_dma_map(qc)) { + if (ata_is_dma(prot) || (ata_is_pio(prot) && + (ap->flags & ATA_FLAG_PIO_DMA))) { if (qc->flags & ATA_QCFLAG_SG) { if (ata_sg_setup(qc)) goto sg_err; @@ -6217,8 +6195,8 @@ inline unsigned int ata_host_intr(struct ata_port *ap, */ /* Check the ATA_DFLAG_CDB_INTR flag is enough here. - * The flag was turned on only for atapi devices. - * No need to check is_atapi_taskfile(&qc->tf) again. + * The flag was turned on only for atapi devices. No + * need to check ata_is_atapi(qc->tf.protocol) again. */ if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) goto idle_irq; diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index d015b4adcfe0..a3c33f165427 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -417,7 +417,7 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc) } /* setup "ACMD - atapi command" in cmd. desc. if this is ATAPI cmd */ - if (is_atapi_taskfile(&qc->tf)) { + if (ata_is_atapi(qc->tf.protocol)) { desc_info |= ATAPI_CMD; memset((void *)&cd->acmd, 0, 32); memcpy((void *)&cd->acmd, qc->cdb, qc->dev->cdb_len); diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index f5119bf40c24..0b8191b52f97 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -416,15 +416,14 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2) */ /* Check the ATA_DFLAG_CDB_INTR flag is enough here. - * The flag was turned on only for atapi devices. - * No need to check is_atapi_taskfile(&qc->tf) again. + * The flag was turned on only for atapi devices. No + * need to check ata_is_atapi(qc->tf.protocol) again. */ if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) goto err_hsm; break; case HSM_ST_LAST: - if (qc->tf.protocol == ATA_PROT_DMA || - qc->tf.protocol == ATA_PROT_ATAPI_DMA) { + if (ata_is_dma(qc->tf.protocol)) { /* clear DMA-Start bit */ ap->ops->bmdma_stop(qc); @@ -451,8 +450,7 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2) /* kick HSM in the ass */ ata_hsm_move(ap, qc, status, 0); - if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA || - qc->tf.protocol == ATA_PROT_ATAPI_DMA)) + if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol)) ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2); return; diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 864c1c1b8511..fdd3ceac329b 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -852,9 +852,7 @@ static int sil24_qc_defer(struct ata_queued_cmd *qc) * set. * */ - int is_excl = (prot == ATA_PROT_ATAPI || - prot == ATA_PROT_ATAPI_NODATA || - prot == ATA_PROT_ATAPI_DMA || + int is_excl = (ata_is_atapi(prot) || (qc->flags & ATA_QCFLAG_RESULT_TF)); if (unlikely(ap->excl_link)) { @@ -885,35 +883,21 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) cb = &pp->cmd_block[sil24_tag(qc->tag)]; - switch (qc->tf.protocol) { - case ATA_PROT_PIO: - case ATA_PROT_DMA: - case ATA_PROT_NCQ: - case ATA_PROT_NODATA: + if (!ata_is_atapi(qc->tf.protocol)) { prb = &cb->ata.prb; sge = cb->ata.sge; - break; - - case ATA_PROT_ATAPI: - case ATA_PROT_ATAPI_DMA: - case ATA_PROT_ATAPI_NODATA: + } else { prb = &cb->atapi.prb; sge = cb->atapi.sge; memset(cb->atapi.cdb, 0, 32); memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len); - if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) { + if (ata_is_data(qc->tf.protocol)) { if (qc->tf.flags & ATA_TFLAG_WRITE) ctrl = PRB_CTRL_PACKET_WRITE; else ctrl = PRB_CTRL_PACKET_READ; } - break; - - default: - prb = NULL; /* shut up, gcc */ - sge = NULL; - BUG(); } prb->ctrl = cpu_to_le16(ctrl); diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 0829b55c64d2..831294de1d8d 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -176,7 +176,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis); task->uldd_task = qc; - if (is_atapi_taskfile(&qc->tf)) { + if (ata_is_atapi(qc->tf.protocol)) { memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len); task->total_xfer_len = qc->nbytes + qc->pad_len; task->num_scatter = qc->pad_len ? qc->n_elem + 1 : qc->n_elem; diff --git a/include/linux/ata.h b/include/linux/ata.h index 3fbe6d7784ab..43fecf62773a 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -324,6 +324,13 @@ enum { ATA_TFLAG_LBA = (1 << 4), /* enable LBA */ ATA_TFLAG_FUA = (1 << 5), /* enable FUA */ ATA_TFLAG_POLLING = (1 << 6), /* set nIEN to 1 and use polling */ + + /* protocol flags */ + ATA_PROT_FLAG_PIO = (1 << 0), /* is PIO */ + ATA_PROT_FLAG_DMA = (1 << 1), /* is DMA */ + ATA_PROT_FLAG_DATA = ATA_PROT_FLAG_PIO | ATA_PROT_FLAG_DMA, + ATA_PROT_FLAG_NCQ = (1 << 2), /* is NCQ */ + ATA_PROT_FLAG_ATAPI = (1 << 3), /* is ATAPI */ }; enum ata_tf_protocols { @@ -373,6 +380,63 @@ struct ata_taskfile { u8 command; /* IO operation */ }; +/* + * protocol tests + */ +static inline unsigned int ata_prot_flags(u8 prot) +{ + switch (prot) { + case ATA_PROT_NODATA: + return 0; + case ATA_PROT_PIO: + return ATA_PROT_FLAG_PIO; + case ATA_PROT_DMA: + return ATA_PROT_FLAG_DMA; + case ATA_PROT_NCQ: + return ATA_PROT_FLAG_DMA | ATA_PROT_FLAG_NCQ; + case ATA_PROT_ATAPI_NODATA: + return ATA_PROT_FLAG_ATAPI; + case ATA_PROT_ATAPI: + return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_PIO; + case ATA_PROT_ATAPI_DMA: + return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_DMA; + } + return 0; +} + +static inline int ata_is_atapi(u8 prot) +{ + return ata_prot_flags(prot) & ATA_PROT_FLAG_ATAPI; +} + +static inline int ata_is_nodata(u8 prot) +{ + return !(ata_prot_flags(prot) & ATA_PROT_FLAG_DATA); +} + +static inline int ata_is_pio(u8 prot) +{ + return ata_prot_flags(prot) & ATA_PROT_FLAG_PIO; +} + +static inline int ata_is_dma(u8 prot) +{ + return ata_prot_flags(prot) & ATA_PROT_FLAG_DMA; +} + +static inline int ata_is_ncq(u8 prot) +{ + return ata_prot_flags(prot) & ATA_PROT_FLAG_NCQ; +} + +static inline int ata_is_data(u8 prot) +{ + return ata_prot_flags(prot) & ATA_PROT_FLAG_DATA; +} + +/* + * id tests + */ #define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0) #define ata_id_has_lba(id) ((id)[49] & (1 << 9)) #define ata_id_has_dma(id) ((id)[49] & (1 << 8)) @@ -594,13 +658,6 @@ static inline int atapi_command_packet_set(const u16 *dev_id) return (dev_id[0] >> 8) & 0x1f; } -static inline int is_atapi_taskfile(const struct ata_taskfile *tf) -{ - return (tf->protocol == ATA_PROT_ATAPI) || - (tf->protocol == ATA_PROT_ATAPI_NODATA) || - (tf->protocol == ATA_PROT_ATAPI_DMA); -} - static inline int is_multi_taskfile(struct ata_taskfile *tf) { return (tf->command == ATA_CMD_READ_MULTI) || -- cgit v1.2.3 From 6f1d1e3a03fd04a9d9c82fd3cf414020097bb142 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 27 Nov 2007 19:28:55 +0900 Subject: libata: move ata_set_mode() to libata-eh.c Move ata_set_mode() to libata-eh.c. ata_set_mode() is surely an EH action and will be more tightly coupled with the rest of error handling. Move it to libata-eh.c. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 25 ------------------------- drivers/ata/libata-eh.c | 25 +++++++++++++++++++++++++ drivers/ata/libata.h | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 8c7af2c8e8d4..86c10cc751e9 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -3182,31 +3182,6 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) return rc; } -/** - * ata_set_mode - Program timings and issue SET FEATURES - XFER - * @link: link on which timings will be programmed - * @r_failed_dev: out paramter for failed device - * - * Set ATA device disk transfer mode (PIO3, UDMA6, etc.). If - * ata_set_mode() fails, pointer to the failing device is - * returned in @r_failed_dev. - * - * LOCKING: - * PCI/etc. bus probe sem. - * - * RETURNS: - * 0 on success, negative errno otherwise - */ -int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) -{ - struct ata_port *ap = link->ap; - - /* has private set_mode? */ - if (ap->ops->set_mode) - return ap->ops->set_mode(link, r_failed_dev); - return ata_do_set_mode(link, r_failed_dev); -} - /** * ata_tf_to_host - issue ATA taskfile to host controller * @ap: port to which command is being issued diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index b16c81a24ba3..ebab75958900 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2329,6 +2329,31 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, return rc; } +/** + * ata_set_mode - Program timings and issue SET FEATURES - XFER + * @link: link on which timings will be programmed + * @r_failed_dev: out paramter for failed device + * + * Set ATA device disk transfer mode (PIO3, UDMA6, etc.). If + * ata_set_mode() fails, pointer to the failing device is + * returned in @r_failed_dev. + * + * LOCKING: + * PCI/etc. bus probe sem. + * + * RETURNS: + * 0 on success, negative errno otherwise + */ +int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) +{ + struct ata_port *ap = link->ap; + + /* has private set_mode? */ + if (ap->ops->set_mode) + return ap->ops->set_mode(link, r_failed_dev); + return ata_do_set_mode(link, r_failed_dev); +} + static int ata_link_nr_enabled(struct ata_link *link) { struct ata_device *dev; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 8cf0874f248b..409ffb9af163 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -86,7 +86,6 @@ extern int ata_dev_configure(struct ata_device *dev); extern int sata_down_spd_limit(struct ata_link *link); extern int sata_set_spd_needed(struct ata_link *link); extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel); -extern int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev); extern void ata_sg_clean(struct ata_queued_cmd *qc); extern void ata_qc_free(struct ata_queued_cmd *qc); extern void ata_qc_issue(struct ata_queued_cmd *qc); @@ -187,6 +186,7 @@ extern void ata_eh_report(struct ata_port *ap); extern int ata_eh_reset(struct ata_link *link, int classify, ata_prereset_fn_t prereset, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset); +extern int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev); extern int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset, -- cgit v1.2.3 From 00115e0f5bc3bfdf3f3855ad89c8895f10458f92 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 27 Nov 2007 19:28:58 +0900 Subject: libata: implement ATA_DFLAG_DUBIOUS_XFER ATA_DFLAG_DUBIOUS_XFER is set whenever data transfer speed or method changes and gets cleared when data transfer command succeeds in the newly configured transfer mode. This will be used to improve speed down logic. Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 19 +++++++++++++++++++ drivers/ata/libata-eh.c | 33 +++++++++++++++++++++++++++++++-- include/linux/libata.h | 3 +++ 3 files changed, 53 insertions(+), 2 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 86c10cc751e9..124b6f111cc3 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5797,6 +5797,22 @@ static void fill_result_tf(struct ata_queued_cmd *qc) ap->ops->tf_read(ap, &qc->result_tf); } +static void ata_verify_xfer(struct ata_queued_cmd *qc) +{ + struct ata_device *dev = qc->dev; + + if (ata_tag_internal(qc->tag)) + return; + + if (ata_is_nodata(qc->tf.protocol)) + return; + + if ((dev->mwdma_mask || dev->udma_mask) && ata_is_pio(qc->tf.protocol)) + return; + + dev->flags &= ~ATA_DFLAG_DUBIOUS_XFER; +} + /** * ata_qc_complete - Complete an active ATA command * @qc: Command to complete @@ -5868,6 +5884,9 @@ void ata_qc_complete(struct ata_queued_cmd *qc) break; } + if (unlikely(dev->flags & ATA_DFLAG_DUBIOUS_XFER)) + ata_verify_xfer(qc); + __ata_qc_complete(qc); } else { if (qc->flags & ATA_QCFLAG_EH_SCHEDULED) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 7d766ada7a5d..359a5ace8473 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -456,9 +456,20 @@ void ata_scsi_error(struct Scsi_Host *host) spin_lock_irqsave(ap->lock, flags); __ata_port_for_each_link(link, ap) { + struct ata_eh_context *ehc = &link->eh_context; + struct ata_device *dev; + memset(&link->eh_context, 0, sizeof(link->eh_context)); link->eh_context.i = link->eh_info; memset(&link->eh_info, 0, sizeof(link->eh_info)); + + ata_link_for_each_dev(dev, link) { + int devno = dev->devno; + + ehc->saved_xfer_mode[devno] = dev->xfer_mode; + if (ata_ncq_enabled(dev)) + ehc->saved_ncq_enabled |= 1 << devno; + } } ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS; @@ -2376,11 +2387,27 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) { struct ata_port *ap = link->ap; + struct ata_device *dev; + int rc; /* has private set_mode? */ if (ap->ops->set_mode) - return ap->ops->set_mode(link, r_failed_dev); - return ata_do_set_mode(link, r_failed_dev); + rc = ap->ops->set_mode(link, r_failed_dev); + else + rc = ata_do_set_mode(link, r_failed_dev); + + /* if transfer mode has changed, set DUBIOUS_XFER on device */ + ata_link_for_each_dev(dev, link) { + struct ata_eh_context *ehc = &link->eh_context; + u8 saved_xfer_mode = ehc->saved_xfer_mode[dev->devno]; + u8 saved_ncq = !!(ehc->saved_ncq_enabled & (1 << dev->devno)); + + if (dev->xfer_mode != saved_xfer_mode || + ata_ncq_enabled(dev) != saved_ncq) + dev->flags |= ATA_DFLAG_DUBIOUS_XFER; + } + + return rc; } static int ata_link_nr_enabled(struct ata_link *link) @@ -2441,6 +2468,8 @@ static int ata_eh_schedule_probe(struct ata_device *dev) ata_dev_init(dev); ehc->did_probe_mask |= (1 << dev->devno); ehc->i.action |= ATA_EH_SOFTRESET; + ehc->saved_xfer_mode[dev->devno] = 0; + ehc->saved_ncq_enabled &= ~(1 << dev->devno); return 1; } diff --git a/include/linux/libata.h b/include/linux/libata.h index 74f1255e2524..131fb6625e14 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -143,6 +143,7 @@ enum { ATA_DFLAG_NCQ_OFF = (1 << 13), /* device limited to non-NCQ mode */ ATA_DFLAG_SPUNDOWN = (1 << 14), /* XXX: for spindown_compat */ ATA_DFLAG_SLEEPING = (1 << 15), /* device is sleeping */ + ATA_DFLAG_DUBIOUS_XFER = (1 << 16), /* data transfer not verified */ ATA_DFLAG_INIT_MASK = (1 << 24) - 1, ATA_DFLAG_DETACH = (1 << 24), @@ -560,6 +561,8 @@ struct ata_eh_context { int tries[ATA_MAX_DEVICES]; unsigned int classes[ATA_MAX_DEVICES]; unsigned int did_probe_mask; + unsigned int saved_ncq_enabled; + u8 saved_xfer_mode[ATA_MAX_DEVICES]; }; struct ata_acpi_drive -- cgit v1.2.3 From 6357357cae7794dcb89cace758108dec612e7ed5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 27 Nov 2007 19:43:39 +0900 Subject: libata: export xfermode / PATA timing related functions Export the following xfermode related functions. * ata_pack_xfermask() * ata_unpack_xfermask() * ata_xfer_mask2mode() * ata_xfer_mode2mask() * ata_xfer_mode2shift() * ata_mode_string() * ata_id_xfermask() * ata_timing_find_mode() These functions will be used later by LLD updates. While at it, change unsigned short @speed to u8 @xfer_mode in ata_timing_find_mode() for consistency. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 33 +++++++++++++++++++-------------- include/linux/libata.h | 10 ++++++++++ 2 files changed, 29 insertions(+), 14 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 124b6f111cc3..a2f2ff864b37 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -454,9 +454,8 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, * RETURNS: * Packed xfer_mask. */ -static unsigned int ata_pack_xfermask(unsigned int pio_mask, - unsigned int mwdma_mask, - unsigned int udma_mask) +unsigned int ata_pack_xfermask(unsigned int pio_mask, + unsigned int mwdma_mask, unsigned int udma_mask) { return ((pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO) | ((mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA) | @@ -473,10 +472,8 @@ static unsigned int ata_pack_xfermask(unsigned int pio_mask, * Unpack @xfer_mask into @pio_mask, @mwdma_mask and @udma_mask. * Any NULL distination masks will be ignored. */ -static void ata_unpack_xfermask(unsigned int xfer_mask, - unsigned int *pio_mask, - unsigned int *mwdma_mask, - unsigned int *udma_mask) +void ata_unpack_xfermask(unsigned int xfer_mask, unsigned int *pio_mask, + unsigned int *mwdma_mask, unsigned int *udma_mask) { if (pio_mask) *pio_mask = (xfer_mask & ATA_MASK_PIO) >> ATA_SHIFT_PIO; @@ -509,7 +506,7 @@ static const struct ata_xfer_ent { * RETURNS: * Matching XFER_* value, 0 if no match found. */ -static u8 ata_xfer_mask2mode(unsigned int xfer_mask) +u8 ata_xfer_mask2mode(unsigned int xfer_mask) { int highbit = fls(xfer_mask) - 1; const struct ata_xfer_ent *ent; @@ -532,7 +529,7 @@ static u8 ata_xfer_mask2mode(unsigned int xfer_mask) * RETURNS: * Matching xfer_mask, 0 if no match found. */ -static unsigned int ata_xfer_mode2mask(u8 xfer_mode) +unsigned int ata_xfer_mode2mask(u8 xfer_mode) { const struct ata_xfer_ent *ent; @@ -554,7 +551,7 @@ static unsigned int ata_xfer_mode2mask(u8 xfer_mode) * RETURNS: * Matching xfer_shift, -1 if no match found. */ -static int ata_xfer_mode2shift(unsigned int xfer_mode) +int ata_xfer_mode2shift(unsigned int xfer_mode) { const struct ata_xfer_ent *ent; @@ -578,7 +575,7 @@ static int ata_xfer_mode2shift(unsigned int xfer_mode) * Constant C string representing highest speed listed in * @mode_mask, or the constant C string "". */ -static const char *ata_mode_string(unsigned int xfer_mask) +const char *ata_mode_string(unsigned int xfer_mask) { static const char * const xfer_mode_str[] = { "PIO0", @@ -1468,7 +1465,7 @@ static inline void ata_dump_id(const u16 *id) * RETURNS: * Computed xfermask */ -static unsigned int ata_id_xfermask(const u16 *id) +unsigned int ata_id_xfermask(const u16 *id) { unsigned int pio_mask, mwdma_mask, udma_mask; @@ -2855,11 +2852,11 @@ void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b, if (what & ATA_TIMING_UDMA ) m->udma = max(a->udma, b->udma); } -static const struct ata_timing *ata_timing_find_mode(unsigned short speed) +const struct ata_timing *ata_timing_find_mode(u8 xfer_mode) { const struct ata_timing *t; - for (t = ata_timing; t->mode != speed; t++) + for (t = ata_timing; t->mode != xfer_mode; t++) if (t->mode == 0xFF) return NULL; return t; @@ -7590,6 +7587,13 @@ EXPORT_SYMBOL_GPL(ata_std_dev_select); EXPORT_SYMBOL_GPL(sata_print_link_status); EXPORT_SYMBOL_GPL(ata_tf_to_fis); EXPORT_SYMBOL_GPL(ata_tf_from_fis); +EXPORT_SYMBOL_GPL(ata_pack_xfermask); +EXPORT_SYMBOL_GPL(ata_unpack_xfermask); +EXPORT_SYMBOL_GPL(ata_xfer_mask2mode); +EXPORT_SYMBOL_GPL(ata_xfer_mode2mask); +EXPORT_SYMBOL_GPL(ata_xfer_mode2shift); +EXPORT_SYMBOL_GPL(ata_mode_string); +EXPORT_SYMBOL_GPL(ata_id_xfermask); EXPORT_SYMBOL_GPL(ata_check_status); EXPORT_SYMBOL_GPL(ata_altstatus); EXPORT_SYMBOL_GPL(ata_exec_command); @@ -7655,6 +7659,7 @@ EXPORT_SYMBOL_GPL(ata_id_to_dma_mode); EXPORT_SYMBOL_GPL(ata_scsi_simulate); EXPORT_SYMBOL_GPL(ata_pio_need_iordy); +EXPORT_SYMBOL_GPL(ata_timing_find_mode); EXPORT_SYMBOL_GPL(ata_timing_compute); EXPORT_SYMBOL_GPL(ata_timing_merge); diff --git a/include/linux/libata.h b/include/linux/libata.h index 131fb6625e14..083dd77b120d 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -851,6 +851,15 @@ extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf); extern void ata_tf_to_fis(const struct ata_taskfile *tf, u8 pmp, int is_cmd, u8 *fis); extern void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf); +extern unsigned int ata_pack_xfermask(unsigned int pio_mask, + unsigned int mwdma_mask, unsigned int udma_mask); +extern void ata_unpack_xfermask(unsigned int xfer_mask, unsigned int *pio_mask, + unsigned int *mwdma_mask, unsigned int *udma_mask); +extern u8 ata_xfer_mask2mode(unsigned int xfer_mask); +extern unsigned int ata_xfer_mode2mask(u8 xfer_mode); +extern int ata_xfer_mode2shift(unsigned int xfer_mode); +extern const char *ata_mode_string(unsigned int xfer_mask); +extern unsigned int ata_id_xfermask(const u16 *id); extern void ata_noop_dev_select(struct ata_port *ap, unsigned int device); extern void ata_std_dev_select(struct ata_port *ap, unsigned int device); extern u8 ata_check_status(struct ata_port *ap); @@ -920,6 +929,7 @@ extern int ata_cable_unknown(struct ata_port *ap); */ extern unsigned int ata_pio_need_iordy(const struct ata_device *); +extern const struct ata_timing *ata_timing_find_mode(u8 xfer_mode); extern int ata_timing_compute(struct ata_device *, unsigned short, struct ata_timing *, int, int); extern void ata_timing_merge(const struct ata_timing *, -- cgit v1.2.3 From 70cd071e4ecc06c985189665af75c108601fd5a3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 27 Nov 2007 19:43:40 +0900 Subject: libata: clean up xfermode / PATA timing related stuff * s/ATA_BITS_(PIO|MWDMA|UDMA)/ATA_NR_\1_MODES/g * Consistently use 0xff to indicate invalid transfer mode (0x00 is valid for PIO_SLOW). * Make ata_xfer_mode2mask() return proper mode mask instead of just the highest bit. * Sort ata_timing table in increasing xfermode order and update ata_timing_find_mode() accordingly. This patch doesn't introduce any behavior change. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 82 +++++++++++++++++++++++------------------------ include/linux/libata.h | 21 ++++++------ 2 files changed, 52 insertions(+), 51 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index a2f2ff864b37..a70ed7b3bc55 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -487,9 +487,9 @@ static const struct ata_xfer_ent { int shift, bits; u8 base; } ata_xfer_tbl[] = { - { ATA_SHIFT_PIO, ATA_BITS_PIO, XFER_PIO_0 }, - { ATA_SHIFT_MWDMA, ATA_BITS_MWDMA, XFER_MW_DMA_0 }, - { ATA_SHIFT_UDMA, ATA_BITS_UDMA, XFER_UDMA_0 }, + { ATA_SHIFT_PIO, ATA_NR_PIO_MODES, XFER_PIO_0 }, + { ATA_SHIFT_MWDMA, ATA_NR_MWDMA_MODES, XFER_MW_DMA_0 }, + { ATA_SHIFT_UDMA, ATA_NR_UDMA_MODES, XFER_UDMA_0 }, { -1, }, }; @@ -504,7 +504,7 @@ static const struct ata_xfer_ent { * None. * * RETURNS: - * Matching XFER_* value, 0 if no match found. + * Matching XFER_* value, 0xff if no match found. */ u8 ata_xfer_mask2mode(unsigned int xfer_mask) { @@ -514,7 +514,7 @@ u8 ata_xfer_mask2mode(unsigned int xfer_mask) for (ent = ata_xfer_tbl; ent->shift >= 0; ent++) if (highbit >= ent->shift && highbit < ent->shift + ent->bits) return ent->base + highbit - ent->shift; - return 0; + return 0xff; } /** @@ -535,7 +535,8 @@ unsigned int ata_xfer_mode2mask(u8 xfer_mode) for (ent = ata_xfer_tbl; ent->shift >= 0; ent++) if (xfer_mode >= ent->base && xfer_mode < ent->base + ent->bits) - return 1 << (ent->shift + xfer_mode - ent->base); + return ((2 << (ent->shift + xfer_mode - ent->base)) - 1) + & ~((1 << ent->shift) - 1); return 0; } @@ -1314,7 +1315,7 @@ void ata_id_to_dma_mode(struct ata_device *dev, u8 unknown) /* Select the mode in use */ mode = ata_xfer_mask2mode(mask); - if (mode != 0) { + if (mode != 0xff) { ata_dev_printk(dev, KERN_INFO, "configured for %s\n", ata_mode_string(mask)); } else { @@ -2788,38 +2789,33 @@ int sata_set_spd(struct ata_link *link) */ static const struct ata_timing ata_timing[] = { +/* { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960, 0 }, */ + { XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0 }, + { XFER_PIO_1, 50, 290, 93, 383, 125, 100, 383, 0 }, + { XFER_PIO_2, 30, 290, 40, 330, 100, 90, 240, 0 }, + { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 }, + { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 }, + { XFER_PIO_5, 15, 65, 25, 100, 65, 25, 100, 0 }, + { XFER_PIO_6, 10, 55, 20, 80, 55, 20, 80, 0 }, - { XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 15 }, - { XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 20 }, - { XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 30 }, - { XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 45 }, + { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 }, + { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 }, + { XFER_SW_DMA_2, 60, 0, 0, 0, 120, 120, 240, 0 }, - { XFER_MW_DMA_4, 25, 0, 0, 0, 55, 20, 80, 0 }, + { XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 480, 0 }, + { XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 150, 0 }, + { XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 120, 0 }, { XFER_MW_DMA_3, 25, 0, 0, 0, 65, 25, 100, 0 }, - { XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 60 }, - { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 }, - { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 }, + { XFER_MW_DMA_4, 25, 0, 0, 0, 55, 20, 80, 0 }, /* { XFER_UDMA_SLOW, 0, 0, 0, 0, 0, 0, 0, 150 }, */ - - { XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 120, 0 }, - { XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 150, 0 }, - { XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 480, 0 }, - - { XFER_SW_DMA_2, 60, 0, 0, 0, 120, 120, 240, 0 }, - { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 }, - { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 }, - - { XFER_PIO_6, 10, 55, 20, 80, 55, 20, 80, 0 }, - { XFER_PIO_5, 15, 65, 25, 100, 65, 25, 100, 0 }, - { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 }, - { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 }, - - { XFER_PIO_2, 30, 290, 40, 330, 100, 90, 240, 0 }, - { XFER_PIO_1, 50, 290, 93, 383, 125, 100, 383, 0 }, - { XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0 }, - -/* { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960, 0 }, */ + { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 }, + { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 }, + { XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 60 }, + { XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 45 }, + { XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 30 }, + { XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 20 }, + { XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 15 }, { 0xFF } }; @@ -2854,12 +2850,14 @@ void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b, const struct ata_timing *ata_timing_find_mode(u8 xfer_mode) { - const struct ata_timing *t; + const struct ata_timing *t = ata_timing; + + while (xfer_mode > t->mode) + t++; - for (t = ata_timing; t->mode != xfer_mode; t++) - if (t->mode == 0xFF) - return NULL; - return t; + if (xfer_mode == t->mode) + return t; + return NULL; } int ata_timing_compute(struct ata_device *adev, unsigned short speed, @@ -3122,7 +3120,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) dev->dma_mode = ata_xfer_mask2mode(dma_mask); found = 1; - if (dev->dma_mode) + if (dev->dma_mode != 0xff) used_dma = 1; } if (!found) @@ -3133,7 +3131,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) if (!ata_dev_enabled(dev)) continue; - if (!dev->pio_mode) { + if (dev->pio_mode == 0xff) { ata_dev_printk(dev, KERN_WARNING, "no PIO support\n"); rc = -EINVAL; goto out; @@ -3147,7 +3145,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) /* step 3: set host DMA timings */ ata_link_for_each_dev(dev, link) { - if (!ata_dev_enabled(dev) || !dev->dma_mode) + if (!ata_dev_enabled(dev) || dev->dma_mode == 0xff) continue; dev->xfer_mode = dev->dma_mode; diff --git a/include/linux/libata.h b/include/linux/libata.h index 083dd77b120d..e2ed3bac8c5b 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -269,17 +269,20 @@ enum { /* encoding various smaller bitmaps into a single * unsigned int bitmap */ - ATA_BITS_PIO = 7, - ATA_BITS_MWDMA = 5, - ATA_BITS_UDMA = 8, + ATA_NR_PIO_MODES = 7, + ATA_NR_MWDMA_MODES = 5, + ATA_NR_UDMA_MODES = 8, ATA_SHIFT_PIO = 0, - ATA_SHIFT_MWDMA = ATA_SHIFT_PIO + ATA_BITS_PIO, - ATA_SHIFT_UDMA = ATA_SHIFT_MWDMA + ATA_BITS_MWDMA, - - ATA_MASK_PIO = ((1 << ATA_BITS_PIO) - 1) << ATA_SHIFT_PIO, - ATA_MASK_MWDMA = ((1 << ATA_BITS_MWDMA) - 1) << ATA_SHIFT_MWDMA, - ATA_MASK_UDMA = ((1 << ATA_BITS_UDMA) - 1) << ATA_SHIFT_UDMA, + ATA_SHIFT_MWDMA = ATA_SHIFT_PIO + ATA_NR_PIO_MODES, + ATA_SHIFT_UDMA = ATA_SHIFT_MWDMA + ATA_NR_MWDMA_MODES, + + ATA_MASK_PIO = ((1 << ATA_NR_PIO_MODES) - 1) + << ATA_SHIFT_PIO, + ATA_MASK_MWDMA = ((1 << ATA_NR_MWDMA_MODES) - 1) + << ATA_SHIFT_MWDMA, + ATA_MASK_UDMA = ((1 << ATA_NR_UDMA_MODES) - 1) + << ATA_SHIFT_UDMA, /* size of buffer to pad xfers ending on unaligned boundaries */ ATA_DMA_PAD_SZ = 4, -- cgit v1.2.3 From 9d3501ab962b1506d93974faf8509251b4a85fbc Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 27 Nov 2007 19:43:41 +0900 Subject: libata: kill ata_id_to_dma_mode() ata_id_to_dma_mode() isn't quite generic. The function is basically privately implemented ata_id_xfermask() combined with hardcoded mode printing and configuration which are specific to ata_generic. Kill the function and open code it in generic_set_mode() using generic xfermode handling functions. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/ata_generic.c | 17 ++++++++++++++++- drivers/ata/libata-core.c | 43 ------------------------------------------- include/linux/libata.h | 1 - 3 files changed, 16 insertions(+), 45 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index fb5434c8ae6e..d11a4f1fe86a 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c @@ -63,7 +63,22 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused) /* We do need the right mode information for DMA or PIO and this comes from the current configuration flags */ if (dma_enabled & (1 << (5 + dev->devno))) { - ata_id_to_dma_mode(dev, XFER_MW_DMA_0); + unsigned int xfer_mask = ata_id_xfermask(dev->id); + const char *name; + + if (xfer_mask & (ATA_MASK_MWDMA | ATA_MASK_UDMA)) + name = ata_mode_string(xfer_mask); + else { + /* SWDMA perhaps? */ + name = "DMA"; + xfer_mask |= ata_xfer_mode2mask(XFER_MW_DMA_0); + } + + ata_dev_printk(dev, KERN_INFO, "configured for %s\n", + name); + + dev->xfer_mode = ata_xfer_mask2mode(xfer_mask); + dev->xfer_shift = ata_xfer_mode2shift(dev->xfer_mode); dev->flags &= ~ATA_DFLAG_PIO; } else { ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index a70ed7b3bc55..ab84772235c9 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1287,48 +1287,6 @@ static int ata_hpa_resize(struct ata_device *dev) return 0; } -/** - * ata_id_to_dma_mode - Identify DMA mode from id block - * @dev: device to identify - * @unknown: mode to assume if we cannot tell - * - * Set up the timing values for the device based upon the identify - * reported values for the DMA mode. This function is used by drivers - * which rely upon firmware configured modes, but wish to report the - * mode correctly when possible. - * - * In addition we emit similarly formatted messages to the default - * ata_dev_set_mode handler, in order to provide consistency of - * presentation. - */ - -void ata_id_to_dma_mode(struct ata_device *dev, u8 unknown) -{ - unsigned int mask; - u8 mode; - - /* Pack the DMA modes */ - mask = ((dev->id[63] >> 8) << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA; - if (dev->id[53] & 0x04) - mask |= ((dev->id[88] >> 8) << ATA_SHIFT_UDMA) & ATA_MASK_UDMA; - - /* Select the mode in use */ - mode = ata_xfer_mask2mode(mask); - - if (mode != 0xff) { - ata_dev_printk(dev, KERN_INFO, "configured for %s\n", - ata_mode_string(mask)); - } else { - /* SWDMA perhaps ? */ - mode = unknown; - ata_dev_printk(dev, KERN_INFO, "configured for DMA\n"); - } - - /* Configure the device reporting */ - dev->xfer_mode = mode; - dev->xfer_shift = ata_xfer_mode2shift(mode); -} - /** * ata_noop_dev_select - Select device 0/1 on ATA bus * @ap: ATA channel to manipulate @@ -7653,7 +7611,6 @@ EXPORT_SYMBOL_GPL(ata_host_resume); #endif /* CONFIG_PM */ EXPORT_SYMBOL_GPL(ata_id_string); EXPORT_SYMBOL_GPL(ata_id_c_string); -EXPORT_SYMBOL_GPL(ata_id_to_dma_mode); EXPORT_SYMBOL_GPL(ata_scsi_simulate); EXPORT_SYMBOL_GPL(ata_pio_need_iordy); diff --git a/include/linux/libata.h b/include/linux/libata.h index e2ed3bac8c5b..d33702fe78f9 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -890,7 +890,6 @@ extern void ata_id_string(const u16 *id, unsigned char *s, unsigned int ofs, unsigned int len); extern void ata_id_c_string(const u16 *id, unsigned char *s, unsigned int ofs, unsigned int len); -extern void ata_id_to_dma_mode(struct ata_device *dev, u8 unknown); extern void ata_bmdma_setup(struct ata_queued_cmd *qc); extern void ata_bmdma_start(struct ata_queued_cmd *qc); extern void ata_bmdma_stop(struct ata_queued_cmd *qc); -- cgit v1.2.3 From 7dc951aefdc1dc20228691b04867fb6195864d67 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 27 Nov 2007 19:43:42 +0900 Subject: libata: xfer_mask is unsigned long not unsigned int Jeff says xfer_mask is unsigned long not unsigned int. Convert all xfermask fields and handling functions to deal with unsigned longs. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 29 +++++++++++++++-------------- include/linux/libata.h | 46 +++++++++++++++++++++++++--------------------- 2 files changed, 40 insertions(+), 35 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index ab84772235c9..711595390996 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -454,8 +454,9 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, * RETURNS: * Packed xfer_mask. */ -unsigned int ata_pack_xfermask(unsigned int pio_mask, - unsigned int mwdma_mask, unsigned int udma_mask) +unsigned long ata_pack_xfermask(unsigned long pio_mask, + unsigned long mwdma_mask, + unsigned long udma_mask) { return ((pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO) | ((mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA) | @@ -472,8 +473,8 @@ unsigned int ata_pack_xfermask(unsigned int pio_mask, * Unpack @xfer_mask into @pio_mask, @mwdma_mask and @udma_mask. * Any NULL distination masks will be ignored. */ -void ata_unpack_xfermask(unsigned int xfer_mask, unsigned int *pio_mask, - unsigned int *mwdma_mask, unsigned int *udma_mask) +void ata_unpack_xfermask(unsigned long xfer_mask, unsigned long *pio_mask, + unsigned long *mwdma_mask, unsigned long *udma_mask) { if (pio_mask) *pio_mask = (xfer_mask & ATA_MASK_PIO) >> ATA_SHIFT_PIO; @@ -506,7 +507,7 @@ static const struct ata_xfer_ent { * RETURNS: * Matching XFER_* value, 0xff if no match found. */ -u8 ata_xfer_mask2mode(unsigned int xfer_mask) +u8 ata_xfer_mask2mode(unsigned long xfer_mask) { int highbit = fls(xfer_mask) - 1; const struct ata_xfer_ent *ent; @@ -529,7 +530,7 @@ u8 ata_xfer_mask2mode(unsigned int xfer_mask) * RETURNS: * Matching xfer_mask, 0 if no match found. */ -unsigned int ata_xfer_mode2mask(u8 xfer_mode) +unsigned long ata_xfer_mode2mask(u8 xfer_mode) { const struct ata_xfer_ent *ent; @@ -552,7 +553,7 @@ unsigned int ata_xfer_mode2mask(u8 xfer_mode) * RETURNS: * Matching xfer_shift, -1 if no match found. */ -int ata_xfer_mode2shift(unsigned int xfer_mode) +int ata_xfer_mode2shift(unsigned long xfer_mode) { const struct ata_xfer_ent *ent; @@ -576,7 +577,7 @@ int ata_xfer_mode2shift(unsigned int xfer_mode) * Constant C string representing highest speed listed in * @mode_mask, or the constant C string "". */ -const char *ata_mode_string(unsigned int xfer_mask) +const char *ata_mode_string(unsigned long xfer_mask) { static const char * const xfer_mode_str[] = { "PIO0", @@ -1424,9 +1425,9 @@ static inline void ata_dump_id(const u16 *id) * RETURNS: * Computed xfermask */ -unsigned int ata_id_xfermask(const u16 *id) +unsigned long ata_id_xfermask(const u16 *id) { - unsigned int pio_mask, mwdma_mask, udma_mask; + unsigned long pio_mask, mwdma_mask, udma_mask; /* Usual case. Word 53 indicates word 64 is valid */ if (id[ATA_ID_FIELD_VALID] & (1 << 1)) { @@ -2050,7 +2051,7 @@ int ata_dev_configure(struct ata_device *dev) struct ata_eh_context *ehc = &dev->link->eh_context; int print_info = ehc->i.flags & ATA_EHI_PRINTINFO; const u16 *id = dev->id; - unsigned int xfer_mask; + unsigned long xfer_mask; char revbuf[7]; /* XYZ-99\0 */ char fwrevbuf[ATA_ID_FW_REV_LEN+1]; char modelbuf[ATA_ID_PROD_LEN+1]; @@ -2907,8 +2908,8 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel) { char buf[32]; - unsigned int orig_mask, xfer_mask; - unsigned int pio_mask, mwdma_mask, udma_mask; + unsigned long orig_mask, xfer_mask; + unsigned long pio_mask, mwdma_mask, udma_mask; int quiet, highbit; quiet = !!(sel & ATA_DNXFER_QUIET); @@ -3052,7 +3053,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) /* step 1: calculate xfer_mask */ ata_link_for_each_dev(dev, link) { - unsigned int pio_mask, dma_mask; + unsigned long pio_mask, dma_mask; unsigned int mode_mask; if (!ata_dev_enabled(dev)) diff --git a/include/linux/libata.h b/include/linux/libata.h index d33702fe78f9..d9eb20c67bb6 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -267,7 +267,7 @@ enum { PORT_DISABLED = 2, /* encoding various smaller bitmaps into a single - * unsigned int bitmap + * unsigned long bitmap */ ATA_NR_PIO_MODES = 7, ATA_NR_MWDMA_MODES = 5, @@ -277,13 +277,6 @@ enum { ATA_SHIFT_MWDMA = ATA_SHIFT_PIO + ATA_NR_PIO_MODES, ATA_SHIFT_UDMA = ATA_SHIFT_MWDMA + ATA_NR_MWDMA_MODES, - ATA_MASK_PIO = ((1 << ATA_NR_PIO_MODES) - 1) - << ATA_SHIFT_PIO, - ATA_MASK_MWDMA = ((1 << ATA_NR_MWDMA_MODES) - 1) - << ATA_SHIFT_MWDMA, - ATA_MASK_UDMA = ((1 << ATA_NR_UDMA_MODES) - 1) - << ATA_SHIFT_UDMA, - /* size of buffer to pad xfers ending on unaligned boundaries */ ATA_DMA_PAD_SZ = 4, ATA_DMA_PAD_BUF_SZ = ATA_DMA_PAD_SZ * ATA_MAX_QUEUE, @@ -355,6 +348,15 @@ enum { ATA_DMA_MASK_CFA = (1 << 2), /* DMA on CF Card */ }; +enum ata_xfer_mask { + ATA_MASK_PIO = ((1LU << ATA_NR_PIO_MODES) - 1) + << ATA_SHIFT_PIO, + ATA_MASK_MWDMA = ((1LU << ATA_NR_MWDMA_MODES) - 1) + << ATA_SHIFT_MWDMA, + ATA_MASK_UDMA = ((1LU << ATA_NR_UDMA_MODES) - 1) + << ATA_SHIFT_UDMA, +}; + enum hsm_task_states { HSM_ST_IDLE, /* no command on going */ HSM_ST_FIRST, /* (waiting the device to) @@ -526,9 +528,9 @@ struct ata_device { unsigned int cdb_len; /* per-dev xfer mask */ - unsigned int pio_mask; - unsigned int mwdma_mask; - unsigned int udma_mask; + unsigned long pio_mask; + unsigned long mwdma_mask; + unsigned long udma_mask; /* for CHS addressing */ u16 cylinders; /* Number of cylinders */ @@ -854,15 +856,16 @@ extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf); extern void ata_tf_to_fis(const struct ata_taskfile *tf, u8 pmp, int is_cmd, u8 *fis); extern void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf); -extern unsigned int ata_pack_xfermask(unsigned int pio_mask, - unsigned int mwdma_mask, unsigned int udma_mask); -extern void ata_unpack_xfermask(unsigned int xfer_mask, unsigned int *pio_mask, - unsigned int *mwdma_mask, unsigned int *udma_mask); -extern u8 ata_xfer_mask2mode(unsigned int xfer_mask); -extern unsigned int ata_xfer_mode2mask(u8 xfer_mode); -extern int ata_xfer_mode2shift(unsigned int xfer_mode); -extern const char *ata_mode_string(unsigned int xfer_mask); -extern unsigned int ata_id_xfermask(const u16 *id); +extern unsigned long ata_pack_xfermask(unsigned long pio_mask, + unsigned long mwdma_mask, unsigned long udma_mask); +extern void ata_unpack_xfermask(unsigned long xfer_mask, + unsigned long *pio_mask, unsigned long *mwdma_mask, + unsigned long *udma_mask); +extern u8 ata_xfer_mask2mode(unsigned long xfer_mask); +extern unsigned long ata_xfer_mode2mask(u8 xfer_mode); +extern int ata_xfer_mode2shift(unsigned long xfer_mode); +extern const char *ata_mode_string(unsigned long xfer_mask); +extern unsigned long ata_id_xfermask(const u16 *id); extern void ata_noop_dev_select(struct ata_port *ap, unsigned int device); extern void ata_std_dev_select(struct ata_port *ap, unsigned int device); extern u8 ata_check_status(struct ata_port *ap); @@ -1001,7 +1004,8 @@ extern int ata_pci_prepare_sff_host(struct pci_dev *pdev, const struct ata_port_info * const * ppi, struct ata_host **r_host); extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits); -extern unsigned long ata_pci_default_filter(struct ata_device *, unsigned long); +extern unsigned long ata_pci_default_filter(struct ata_device *dev, + unsigned long xfer_mask); #endif /* CONFIG_PCI */ /* -- cgit v1.2.3 From c88f90c3779cd5e710f2acdf59ad2bd0380de98d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 27 Nov 2007 19:43:48 +0900 Subject: libata: add ATA_CBL_PATA_IGN ATA_CBL_PATA_UNK indicates that the cable type can't be determined from the host side and might be either 80c or 40c. libata applies drive or other generic limit in this case. However, there are controllers where both host and drive side detections are misimplemented and the driver has to rely solely on private method - peeking BIOS or ACPI configuration or using some other private mechanism. This patch adds ATA_CBL_PATA_IGN which tells libata to ignore the cable type completely and just let the LLD determine the transfer mode via host transfer mode masks and ->mode_filter(). Signed-off-by: Tejun Heo Cc: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 13 +++++++++++++ include/linux/ata.h | 7 ++++--- include/linux/libata.h | 1 + 3 files changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 711595390996..62c4b328b0b6 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2353,6 +2353,18 @@ int ata_cable_unknown(struct ata_port *ap) return ATA_CBL_PATA_UNK; } +/** + * ata_cable_ignore - return ignored PATA cable. + * @ap: port + * + * Helper method for drivers which don't use cable type to limit + * transfer mode. + */ +int ata_cable_ignore(struct ata_port *ap) +{ + return ATA_CBL_PATA_IGN; +} + /** * ata_cable_sata - return SATA cable type * @ap: port @@ -7665,4 +7677,5 @@ EXPORT_SYMBOL_GPL(ata_dev_try_classify); EXPORT_SYMBOL_GPL(ata_cable_40wire); EXPORT_SYMBOL_GPL(ata_cable_80wire); EXPORT_SYMBOL_GPL(ata_cable_unknown); +EXPORT_SYMBOL_GPL(ata_cable_ignore); EXPORT_SYMBOL_GPL(ata_cable_sata); diff --git a/include/linux/ata.h b/include/linux/ata.h index 43fecf62773a..c17e9404c88d 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -286,9 +286,10 @@ enum { ATA_CBL_NONE = 0, ATA_CBL_PATA40 = 1, ATA_CBL_PATA80 = 2, - ATA_CBL_PATA40_SHORT = 3, /* 40 wire cable to high UDMA spec */ - ATA_CBL_PATA_UNK = 4, - ATA_CBL_SATA = 5, + ATA_CBL_PATA40_SHORT = 3, /* 40 wire cable to high UDMA spec */ + ATA_CBL_PATA_UNK = 4, /* don't know, maybe 80c? */ + ATA_CBL_PATA_IGN = 5, /* don't know, ignore cable handling */ + ATA_CBL_SATA = 6, /* SATA Status and Control Registers */ SCR_STATUS = 0, diff --git a/include/linux/libata.h b/include/linux/libata.h index d9eb20c67bb6..bdb7c6e13993 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -927,6 +927,7 @@ extern u8 ata_irq_on(struct ata_port *ap); extern int ata_cable_40wire(struct ata_port *ap); extern int ata_cable_80wire(struct ata_port *ap); extern int ata_cable_sata(struct ata_port *ap); +extern int ata_cable_ignore(struct ata_port *ap); extern int ata_cable_unknown(struct ata_port *ap); /* -- cgit v1.2.3 From a0f79b929acaba10d4780acd2543eff20bf4b5b0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 18 Dec 2007 16:33:05 +0900 Subject: libata: implement ata_timing_cycle2mode() and use it in libata-acpi and pata_acpi libata-acpi is using separate timing tables for transfer modes although libata-core has the complete ata_timing table. Implement ata_timing_cycle2mode() to look for matching mode given transfer type and cycle duration and use it in libata-acpi and pata_acpi to replace private timing tables. Signed-off-by: Tejun Heo Cc: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/libata-acpi.c | 62 ++++++++++++----------------------------------- drivers/ata/libata-core.c | 52 +++++++++++++++++++++++++++++++++++++++ drivers/ata/pata_acpi.c | 13 +++++----- include/linux/libata.h | 5 +--- 4 files changed, 75 insertions(+), 57 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 9f0b208afcf5..a6f1a6b56d8c 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -441,22 +441,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf) return rc; } -/* Welcome to ACPI, bring a bucket */ -const unsigned int ata_acpi_pio_cycle[7] = { - 600, 383, 240, 180, 120, 100, 80 -}; -EXPORT_SYMBOL_GPL(ata_acpi_pio_cycle); - -const unsigned int ata_acpi_mwdma_cycle[5] = { - 480, 150, 120, 100, 80 -}; -EXPORT_SYMBOL_GPL(ata_acpi_mwdma_cycle); - -const unsigned int ata_acpi_udma_cycle[7] = { - 120, 80, 60, 45, 30, 20, 15 -}; -EXPORT_SYMBOL_GPL(ata_acpi_udma_cycle); - /** * ata_acpi_gtm_xfermode - determine xfermode from GTM parameter * @dev: target device @@ -473,49 +457,33 @@ EXPORT_SYMBOL_GPL(ata_acpi_udma_cycle); unsigned long ata_acpi_gtm_xfermask(struct ata_device *dev, const struct ata_acpi_gtm *gtm) { - unsigned long pio_mask = 0, mwdma_mask = 0, udma_mask = 0; - int unit, i; - u32 t; + unsigned long xfer_mask = 0; + unsigned int type; + int unit; + u8 mode; /* we always use the 0 slot for crap hardware */ unit = dev->devno; if (!(gtm->flags & 0x10)) unit = 0; - /* Values larger than the longest cycle results in 0 mask - * while values equal to smaller than the shortest cycle - * results in mask which includes all supported modes. - * Disabled transfer method has the value of 0xffffffff which - * will always result in 0 mask. - */ - - /* start by scanning for PIO modes */ - t = gtm->drive[unit].pio; - for (i = 0; i < ARRAY_SIZE(ata_acpi_pio_cycle); i++) - if (t > ata_acpi_pio_cycle[i]) - break; - pio_mask = (1 << i) - 1; + /* PIO */ + mode = ata_timing_cycle2mode(ATA_SHIFT_PIO, gtm->drive[unit].pio); + xfer_mask |= ata_xfer_mode2mask(mode); /* See if we have MWDMA or UDMA data. We don't bother with * MWDMA if UDMA is available as this means the BIOS set UDMA * and our error changedown if it works is UDMA to PIO anyway. */ - t = gtm->drive[unit].dma; - if (!(gtm->flags & (1 << (2 * unit)))) { - /* MWDMA */ - for (i = 0; i < ARRAY_SIZE(ata_acpi_mwdma_cycle); i++) - if (t > ata_acpi_mwdma_cycle[i]) - break; - mwdma_mask = (1 << i) - 1; - } else { - /* UDMA */ - for (i = 0; i < ARRAY_SIZE(ata_acpi_udma_cycle); i++) - if (t > ata_acpi_udma_cycle[i]) - break; - udma_mask = (1 << i) - 1; - } + if (!(gtm->flags & (1 << (2 * unit)))) + type = ATA_SHIFT_MWDMA; + else + type = ATA_SHIFT_UDMA; + + mode = ata_timing_cycle2mode(type, gtm->drive[unit].dma); + xfer_mask |= ata_xfer_mode2mask(mode); - return ata_pack_xfermask(pio_mask, mwdma_mask, udma_mask); + return xfer_mask; } EXPORT_SYMBOL_GPL(ata_acpi_gtm_xfermask); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 62c4b328b0b6..f01c1734b1d0 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2902,6 +2902,57 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, return 0; } +/** + * ata_timing_cycle2mode - find xfer mode for the specified cycle duration + * @xfer_shift: ATA_SHIFT_* value for transfer type to examine. + * @cycle: cycle duration in ns + * + * Return matching xfer mode for @cycle. The returned mode is of + * the transfer type specified by @xfer_shift. If @cycle is too + * slow for @xfer_shift, 0xff is returned. If @cycle is faster + * than the fastest known mode, the fasted mode is returned. + * + * LOCKING: + * None. + * + * RETURNS: + * Matching xfer_mode, 0xff if no match found. + */ +u8 ata_timing_cycle2mode(unsigned int xfer_shift, int cycle) +{ + u8 base_mode = 0xff, last_mode = 0xff; + const struct ata_xfer_ent *ent; + const struct ata_timing *t; + + for (ent = ata_xfer_tbl; ent->shift >= 0; ent++) + if (ent->shift == xfer_shift) + base_mode = ent->base; + + for (t = ata_timing_find_mode(base_mode); + t && ata_xfer_mode2shift(t->mode) == xfer_shift; t++) { + unsigned short this_cycle; + + switch (xfer_shift) { + case ATA_SHIFT_PIO: + case ATA_SHIFT_MWDMA: + this_cycle = t->cycle; + break; + case ATA_SHIFT_UDMA: + this_cycle = t->udma; + break; + default: + return 0xff; + } + + if (cycle > this_cycle) + break; + + last_mode = t->mode; + } + + return last_mode; +} + /** * ata_down_xfermask_limit - adjust dev xfer masks downward * @dev: Device to adjust xfer masks @@ -7630,6 +7681,7 @@ EXPORT_SYMBOL_GPL(ata_pio_need_iordy); EXPORT_SYMBOL_GPL(ata_timing_find_mode); EXPORT_SYMBOL_GPL(ata_timing_compute); EXPORT_SYMBOL_GPL(ata_timing_merge); +EXPORT_SYMBOL_GPL(ata_timing_cycle2mode); #ifdef CONFIG_PCI EXPORT_SYMBOL_GPL(pci_test_config_bits); diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c index a4737a3d31cb..244098a80ce4 100644 --- a/drivers/ata/pata_acpi.c +++ b/drivers/ata/pata_acpi.c @@ -133,13 +133,14 @@ static void pacpi_set_piomode(struct ata_port *ap, struct ata_device *adev) { int unit = adev->devno; struct pata_acpi *acpi = ap->private_data; + const struct ata_timing *t; if (!(acpi->gtm.flags & 0x10)) unit = 0; /* Now stuff the nS values into the structure */ - acpi->gtm.drive[unit].pio = - ata_acpi_pio_cycle[adev->pio_mode - XFER_PIO_0]; + t = ata_timing_find_mode(adev->pio_mode); + acpi->gtm.drive[unit].pio = t->cycle; ata_acpi_stm(ap, &acpi->gtm); /* See what mode we actually got */ ata_acpi_gtm(ap, &acpi->gtm); @@ -155,18 +156,18 @@ static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev) { int unit = adev->devno; struct pata_acpi *acpi = ap->private_data; + const struct ata_timing *t; if (!(acpi->gtm.flags & 0x10)) unit = 0; /* Now stuff the nS values into the structure */ + t = ata_timing_find_mode(adev->dma_mode); if (adev->dma_mode >= XFER_UDMA_0) { - acpi->gtm.drive[unit].dma = - ata_acpi_udma_cycle[adev->dma_mode - XFER_UDMA_0]; + acpi->gtm.drive[unit].dma = t->udma; acpi->gtm.flags |= (1 << (2 * unit)); } else { - acpi->gtm.drive[unit].dma = - ata_acpi_mwdma_cycle[adev->dma_mode - XFER_MW_DMA_0]; + acpi->gtm.drive[unit].dma = t->cycle; acpi->gtm.flags &= ~(1 << (2 * unit)); } ata_acpi_stm(ap, &acpi->gtm); diff --git a/include/linux/libata.h b/include/linux/libata.h index 8022e5b2224d..8ede93b5c7a6 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -941,6 +941,7 @@ extern int ata_timing_compute(struct ata_device *, unsigned short, extern void ata_timing_merge(const struct ata_timing *, const struct ata_timing *, struct ata_timing *, unsigned int); +extern u8 ata_timing_cycle2mode(unsigned int xfer_shift, int cycle); enum { ATA_TIMING_SETUP = (1 << 0), @@ -961,10 +962,6 @@ enum { /* libata-acpi.c */ #ifdef CONFIG_ATA_ACPI -extern const unsigned int ata_acpi_pio_cycle[7]; -extern const unsigned int ata_acpi_mwdma_cycle[5]; -extern const unsigned int ata_acpi_udma_cycle[7]; - static inline const struct ata_acpi_gtm *ata_acpi_init_gtm(struct ata_port *ap) { if (ap->pflags & ATA_PFLAG_INIT_GTM_VALID) -- cgit v1.2.3 From 1973a023a616b40ba33fd0d38b1055c62c88e73d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 5 Dec 2007 10:36:13 +0900 Subject: libata: convert NCQ test in ata_qc_issue() to ata_is_ncq() I missed one while converting to ata_is_*() protocol test helpers. Convert it. Pointed out by Jeff Garzik. 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/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index f01c1734b1d0..2b57547bd740 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5990,7 +5990,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc) */ WARN_ON(ap->ops->error_handler && ata_tag_valid(link->active_tag)); - if (prot == ATA_PROT_NCQ) { + if (ata_is_ncq(prot)) { WARN_ON(link->sactive & (1 << qc->tag)); if (!link->sactive) -- cgit v1.2.3 From 0106372db6dc135f300035ce8e93cddd7283a26a Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Wed, 5 Dec 2007 16:43:02 +0900 Subject: libata: zero xfer length on ATAPI data xfer IRQ is HSM violation Treat zero xfer length as HSM violation. While at it, add unlikely()'s to ATAPI ireason and transfer length checks. tj: Formatted patch and added unlikely()'s. Signed-off-by: Albert Lee Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 2b57547bd740..c9e6bd4d0686 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5309,12 +5309,15 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc) bytes = (bc_hi << 8) | bc_lo; /* shall be cleared to zero, indicating xfer of data */ - if (ireason & (1 << 0)) + if (unlikely(ireason & (1 << 0))) goto err_out; /* make sure transfer direction matches expected */ i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0; - if (do_write != i_write) + if (unlikely(do_write != i_write)) + goto err_out; + + if (unlikely(!bytes)) goto err_out; VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes); -- cgit v1.2.3 From 0dc36888d4422140f9eaf50f24953ec109f750a3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 18 Dec 2007 16:34:43 -0500 Subject: libata: rename ATA_PROT_ATAPI_* to ATAPI_PROT_* ATA_PROT_ATAPI_* are ugly and naming schemes between ATA_PROT_* and ATA_PROT_ATAPI_* are inconsistent causing confusion. Rename them to ATAPI_PROT_* and make them consistent with ATA counterpart. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 28 ++++++++++++++-------------- drivers/ata/libata-eh.c | 8 ++++---- drivers/ata/libata-scsi.c | 10 +++++----- drivers/ata/libata-sff.c | 2 +- drivers/ata/pata_pdc202xx_old.c | 5 ++--- drivers/ata/pdc_adma.c | 2 +- drivers/ata/sata_inic162x.c | 2 +- drivers/ata/sata_promise.c | 26 ++++++++++++-------------- drivers/ata/sata_qstor.c | 2 +- drivers/ata/sata_sx4.c | 2 +- drivers/scsi/ipr.c | 6 +++--- drivers/scsi/libsas/sas_ata.c | 2 +- include/linux/ata.h | 12 ++++++------ 13 files changed, 52 insertions(+), 55 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index c9e6bd4d0686..2c9745a74d50 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4678,8 +4678,8 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc) */ static int atapi_qc_may_overflow(struct ata_queued_cmd *qc) { - if (qc->tf.protocol != ATA_PROT_ATAPI && - qc->tf.protocol != ATA_PROT_ATAPI_DMA) + if (qc->tf.protocol != ATAPI_PROT_PIO && + qc->tf.protocol != ATAPI_PROT_DMA) return 0; if (qc->tf.flags & ATA_TFLAG_WRITE) @@ -5161,13 +5161,13 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) ata_altstatus(ap); /* flush */ switch (qc->tf.protocol) { - case ATA_PROT_ATAPI: + case ATAPI_PROT_PIO: ap->hsm_task_state = HSM_ST; break; - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_NODATA: ap->hsm_task_state = HSM_ST_LAST; break; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: ap->hsm_task_state = HSM_ST_LAST; /* initiate bmdma */ ap->ops->bmdma_start(qc); @@ -5518,7 +5518,7 @@ fsm_start: case HSM_ST: /* complete command or read/write the data register */ - if (qc->tf.protocol == ATA_PROT_ATAPI) { + if (qc->tf.protocol == ATAPI_PROT_PIO) { /* ATAPI PIO protocol */ if ((status & ATA_DRQ) == 0) { /* No more data to transfer or device error. @@ -6073,11 +6073,11 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) switch (qc->tf.protocol) { case ATA_PROT_PIO: case ATA_PROT_NODATA: - case ATA_PROT_ATAPI: - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_PIO: + case ATAPI_PROT_NODATA: qc->tf.flags |= ATA_TFLAG_POLLING; break; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: if (qc->dev->flags & ATA_DFLAG_CDB_INTR) /* see ata_dma_blacklisted() */ BUG(); @@ -6141,8 +6141,8 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) break; - case ATA_PROT_ATAPI: - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_PIO: + case ATAPI_PROT_NODATA: if (qc->tf.flags & ATA_TFLAG_POLLING) ata_qc_set_polling(qc); @@ -6156,7 +6156,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) ata_port_queue_task(ap, ata_pio_task, qc, 0); break; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING); ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ @@ -6217,7 +6217,7 @@ inline unsigned int ata_host_intr(struct ata_port *ap, break; case HSM_ST_LAST: if (qc->tf.protocol == ATA_PROT_DMA || - qc->tf.protocol == ATA_PROT_ATAPI_DMA) { + qc->tf.protocol == ATAPI_PROT_DMA) { /* check status of DMA engine */ host_stat = ap->ops->bmdma_status(ap); VPRINTK("ata%u: host_stat 0x%X\n", @@ -6259,7 +6259,7 @@ inline unsigned int ata_host_intr(struct ata_port *ap, ata_hsm_move(ap, qc, status, 0); if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA || - qc->tf.protocol == ATA_PROT_ATAPI_DMA)) + qc->tf.protocol == ATAPI_PROT_DMA)) ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat); return 1; /* irq handled */ diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 1bc1acf3bbbb..419552603a16 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1299,10 +1299,10 @@ static unsigned int atapi_eh_request_sense(struct ata_queued_cmd *qc) /* is it pointless to prefer PIO for "safety reasons"? */ if (ap->flags & ATA_FLAG_PIO_DMA) { - tf.protocol = ATA_PROT_ATAPI_DMA; + tf.protocol = ATAPI_PROT_DMA; tf.feature |= ATAPI_PKT_DMA; } else { - tf.protocol = ATA_PROT_ATAPI; + tf.protocol = ATAPI_PROT_PIO; tf.lbam = SCSI_SENSE_BUFFERSIZE; tf.lbah = 0; } @@ -1979,8 +1979,8 @@ static void ata_eh_link_report(struct ata_link *link) [ATA_PROT_PIO] = "pio", [ATA_PROT_DMA] = "dma", [ATA_PROT_NCQ] = "ncq", - [ATA_PROT_ATAPI] = "pio", - [ATA_PROT_ATAPI_DMA] = "dma", + [ATAPI_PROT_PIO] = "pio", + [ATAPI_PROT_DMA] = "dma", }; snprintf(data_buf, sizeof(data_buf), " %s %u %s", diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 021cdc4cc260..5fd780e509d4 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2354,10 +2354,10 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) qc->tf.command = ATA_CMD_PACKET; if (ata_pio_use_silly(ap)) { - qc->tf.protocol = ATA_PROT_ATAPI_DMA; + qc->tf.protocol = ATAPI_PROT_DMA; qc->tf.feature |= ATAPI_PKT_DMA; } else { - qc->tf.protocol = ATA_PROT_ATAPI; + qc->tf.protocol = ATAPI_PROT_PIO; qc->tf.lbam = SCSI_SENSE_BUFFERSIZE; qc->tf.lbah = 0; } @@ -2528,12 +2528,12 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) if (using_pio || nodata) { /* no data, or PIO data xfer */ if (nodata) - qc->tf.protocol = ATA_PROT_ATAPI_NODATA; + qc->tf.protocol = ATAPI_PROT_NODATA; else - qc->tf.protocol = ATA_PROT_ATAPI; + qc->tf.protocol = ATAPI_PROT_PIO; } else { /* DMA data xfer */ - qc->tf.protocol = ATA_PROT_ATAPI_DMA; + qc->tf.protocol = ATAPI_PROT_DMA; qc->tf.feature |= ATAPI_PKT_DMA; if (atapi_dmadir && (scmd->sc_data_direction != DMA_TO_DEVICE)) diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index fd5fe4e7e75a..edeb4bea586c 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -417,7 +417,7 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, ap->hsm_task_state = HSM_ST_IDLE; if (qc && (qc->tf.protocol == ATA_PROT_DMA || - qc->tf.protocol == ATA_PROT_ATAPI_DMA)) { + qc->tf.protocol == ATAPI_PROT_DMA)) { u8 host_stat; host_stat = ap->ops->bmdma_status(ap); diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index 6c9689b59b06..3ed866723e0c 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -168,8 +168,7 @@ static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc) pdc202xx_set_dmamode(ap, qc->dev); /* Cases the state machine will not complete correctly without help */ - if ((tf->flags & ATA_TFLAG_LBA48) || tf->protocol == ATA_PROT_ATAPI_DMA) - { + if ((tf->flags & ATA_TFLAG_LBA48) || tf->protocol == ATAPI_PROT_DMA) { len = qc->nbytes / 2; if (tf->flags & ATA_TFLAG_WRITE) @@ -208,7 +207,7 @@ static void pdc2026x_bmdma_stop(struct ata_queued_cmd *qc) void __iomem *atapi_reg = master + 0x20 + (4 * ap->port_no); /* Cases the state machine will not complete correctly */ - if (tf->protocol == ATA_PROT_ATAPI_DMA || ( tf->flags & ATA_TFLAG_LBA48)) { + if (tf->protocol == ATAPI_PROT_DMA || (tf->flags & ATA_TFLAG_LBA48)) { iowrite32(0, atapi_reg); iowrite8(ioread8(clock) & ~sel66, clock); } diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c index bd4c2a3c88d7..459cb7bb7d7f 100644 --- a/drivers/ata/pdc_adma.c +++ b/drivers/ata/pdc_adma.c @@ -455,7 +455,7 @@ static unsigned int adma_qc_issue(struct ata_queued_cmd *qc) adma_packet_start(qc); return 0; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: BUG(); break; diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 323c087e8cc1..96e614a1c169 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -585,7 +585,7 @@ static struct ata_port_operations inic_port_ops = { }; static struct ata_port_info inic_port_info = { - /* For some reason, ATA_PROT_ATAPI is broken on this + /* For some reason, ATAPI_PROT_PIO is broken on this * controller, and no, PIO_POLLING does't fix it. It somehow * manages to report the wrong ireason and ignoring ireason * results in machine lock up. Tell libata to always prefer diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 9638faaa8111..01738d736d44 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -456,13 +456,13 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc) * and seq id (byte 2) */ switch (qc->tf.protocol) { - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: if (!(qc->tf.flags & ATA_TFLAG_WRITE)) buf32[0] = cpu_to_le32(PDC_PKT_READ); else buf32[0] = 0; break; - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_NODATA: buf32[0] = cpu_to_le32(PDC_PKT_NODATA); break; default: @@ -489,7 +489,7 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc) buf[19] = qc->tf.lbal; /* set feature and byte counter registers */ - if (qc->tf.protocol != ATA_PROT_ATAPI_DMA) + if (qc->tf.protocol != ATAPI_PROT_DMA) feature = PDC_FEATURE_ATAPI_PIO; else feature = PDC_FEATURE_ATAPI_DMA; @@ -619,14 +619,14 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc) pdc_pkt_footer(&qc->tf, pp->pkt, i); break; - case ATA_PROT_ATAPI: + case ATAPI_PROT_PIO: pdc_fill_sg(qc); break; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: pdc_fill_sg(qc); /*FALLTHROUGH*/ - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_NODATA: pdc_atapi_pkt(qc); break; @@ -746,8 +746,8 @@ static inline unsigned int pdc_host_intr(struct ata_port *ap, switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NODATA: - case ATA_PROT_ATAPI_DMA: - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_DMA: + case ATAPI_PROT_NODATA: qc->err_mask |= ac_err_mask(ata_wait_idle(ap)); ata_qc_complete(qc); handled = 1; @@ -892,7 +892,7 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc) static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc) { switch (qc->tf.protocol) { - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_NODATA: if (qc->dev->flags & ATA_DFLAG_CDB_INTR) break; /*FALLTHROUGH*/ @@ -900,7 +900,7 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc) if (qc->tf.flags & ATA_TFLAG_POLLING) break; /*FALLTHROUGH*/ - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: case ATA_PROT_DMA: pdc_packet_start(qc); return 0; @@ -914,16 +914,14 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc) static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf) { - WARN_ON(tf->protocol == ATA_PROT_DMA || - tf->protocol == ATA_PROT_ATAPI_DMA); + WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA); ata_tf_load(ap, tf); } static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf) { - WARN_ON(tf->protocol == ATA_PROT_DMA || - tf->protocol == ATA_PROT_ATAPI_DMA); + WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA); ata_exec_command(ap, tf); } diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index c68b241805fd..4e5f07bdd069 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -376,7 +376,7 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc) qs_packet_start(qc); return 0; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: BUG(); break; diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index 4d857185f33b..3de0c27caf53 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -700,7 +700,7 @@ static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc) pdc20621_packet_start(qc); return 0; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: BUG(); break; diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 0841df01bc19..3e78bc2d9170 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -5222,12 +5222,12 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc) regs->flags |= IPR_ATA_FLAG_XFER_TYPE_DMA; break; - case ATA_PROT_ATAPI: - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_PIO: + case ATAPI_PROT_NODATA: regs->flags |= IPR_ATA_FLAG_PACKET_CMD; break; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: regs->flags |= IPR_ATA_FLAG_PACKET_CMD; regs->flags |= IPR_ATA_FLAG_XFER_TYPE_DMA; break; diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 831294de1d8d..f78d0605747d 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -200,7 +200,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) case ATA_PROT_NCQ: task->ata_task.use_ncq = 1; /* fall through */ - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: case ATA_PROT_DMA: task->ata_task.dma_xfer = 1; break; diff --git a/include/linux/ata.h b/include/linux/ata.h index c17e9404c88d..bc55471a4b2c 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -341,9 +341,9 @@ enum ata_tf_protocols { ATA_PROT_PIO, /* PIO data xfer */ ATA_PROT_DMA, /* DMA */ ATA_PROT_NCQ, /* NCQ */ - ATA_PROT_ATAPI, /* packet command, PIO data xfer*/ - ATA_PROT_ATAPI_NODATA, /* packet command, no data */ - ATA_PROT_ATAPI_DMA, /* packet command with special DMA sauce */ + ATAPI_PROT_NODATA, /* packet command, no data */ + ATAPI_PROT_PIO, /* packet command, PIO data xfer*/ + ATAPI_PROT_DMA, /* packet command with special DMA sauce */ }; enum ata_ioctls { @@ -395,11 +395,11 @@ static inline unsigned int ata_prot_flags(u8 prot) return ATA_PROT_FLAG_DMA; case ATA_PROT_NCQ: return ATA_PROT_FLAG_DMA | ATA_PROT_FLAG_NCQ; - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_NODATA: return ATA_PROT_FLAG_ATAPI; - case ATA_PROT_ATAPI: + case ATAPI_PROT_PIO: return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_PIO; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_DMA; } return 0; -- cgit v1.2.3 From 55dba3120fbcbea6800f9a18503d25f73212a347 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 5 Dec 2007 16:43:07 +0900 Subject: libata: update ->data_xfer hook for ATAPI Depending on how many bytes are transferred as a unit, PIO data transfer may consume more bytes than requested. Knowing how much data is consumed is necessary to determine how much is left for draining. This patch update ->data_xfer such that it returns the number of consumed bytes. While at it, it also makes the following changes. * s/adev/dev/ * use READ/WRITE constants for rw indication * misc clean ups Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 46 +++++++++++++++++++++++++++++--------------- drivers/ata/pata_bf54x.c | 28 ++++++++++++++------------- drivers/ata/pata_ixp4xx_cf.c | 26 +++++++++++++------------ drivers/ata/pata_legacy.c | 36 ++++++++++++++++++---------------- drivers/ata/pata_qdi.c | 30 ++++++++++++++++------------- drivers/ata/pata_scc.c | 30 +++++++++++++++-------------- drivers/ata/pata_winbond.c | 28 +++++++++++++++------------ include/linux/libata.h | 11 ++++++----- 8 files changed, 133 insertions(+), 102 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 2c9745a74d50..39cedd949ed4 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4994,7 +4994,7 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) /** * ata_data_xfer - Transfer data by PIO - * @adev: device to target + * @dev: device to target * @buf: data buffer * @buflen: buffer length * @write_data: read/write @@ -5003,37 +5003,44 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) * * LOCKING: * Inherited from caller. + * + * RETURNS: + * Bytes consumed. */ -void ata_data_xfer(struct ata_device *adev, unsigned char *buf, - unsigned int buflen, int write_data) +unsigned int ata_data_xfer(struct ata_device *dev, unsigned char *buf, + unsigned int buflen, int rw) { - struct ata_port *ap = adev->link->ap; + struct ata_port *ap = dev->link->ap; + void __iomem *data_addr = ap->ioaddr.data_addr; unsigned int words = buflen >> 1; /* Transfer multiple of 2 bytes */ - if (write_data) - iowrite16_rep(ap->ioaddr.data_addr, buf, words); + if (rw == READ) + ioread16_rep(data_addr, buf, words); else - ioread16_rep(ap->ioaddr.data_addr, buf, words); + iowrite16_rep(data_addr, buf, words); /* Transfer trailing 1 byte, if any. */ if (unlikely(buflen & 0x01)) { u16 align_buf[1] = { 0 }; unsigned char *trailing_buf = buf + buflen - 1; - if (write_data) { - memcpy(align_buf, trailing_buf, 1); - iowrite16(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr); - } else { - align_buf[0] = cpu_to_le16(ioread16(ap->ioaddr.data_addr)); + if (rw == READ) { + align_buf[0] = cpu_to_le16(ioread16(data_addr)); memcpy(trailing_buf, align_buf, 1); + } else { + memcpy(align_buf, trailing_buf, 1); + iowrite16(le16_to_cpu(align_buf[0]), data_addr); } + words++; } + + return words << 1; } /** * ata_data_xfer_noirq - Transfer data by PIO - * @adev: device to target + * @dev: device to target * @buf: data buffer * @buflen: buffer length * @write_data: read/write @@ -5043,14 +5050,21 @@ void ata_data_xfer(struct ata_device *adev, unsigned char *buf, * * LOCKING: * Inherited from caller. + * + * RETURNS: + * Bytes consumed. */ -void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf, - unsigned int buflen, int write_data) +unsigned int ata_data_xfer_noirq(struct ata_device *dev, unsigned char *buf, + unsigned int buflen, int rw) { unsigned long flags; + unsigned int consumed; + local_irq_save(flags); - ata_data_xfer(adev, buf, buflen, write_data); + consumed = ata_data_xfer(dev, buf, buflen, rw); local_irq_restore(flags); + + return consumed; } diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index 7842cc487359..41cd921082ba 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c @@ -1167,34 +1167,36 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap) * Note: Original code is ata_data_xfer(). */ -static void bfin_data_xfer(struct ata_device *adev, unsigned char *buf, - unsigned int buflen, int write_data) +static unsigned int bfin_data_xfer(struct ata_device *dev, unsigned char *buf, + unsigned int buflen, int rw) { - struct ata_port *ap = adev->link->ap; - unsigned int words = buflen >> 1; - unsigned short *buf16 = (u16 *) buf; + struct ata_port *ap = dev->link->ap; void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; + unsigned int words = buflen >> 1; + unsigned short *buf16 = (u16 *)buf; /* Transfer multiple of 2 bytes */ - if (write_data) { - write_atapi_data(base, words, buf16); - } else { + if (rw == READ) read_atapi_data(base, words, buf16); - } + else + write_atapi_data(base, words, buf16); /* Transfer trailing 1 byte, if any. */ if (unlikely(buflen & 0x01)) { unsigned short align_buf[1] = { 0 }; unsigned char *trailing_buf = buf + buflen - 1; - if (write_data) { - memcpy(align_buf, trailing_buf, 1); - write_atapi_data(base, 1, align_buf); - } else { + if (rw == READ) { read_atapi_data(base, 1, align_buf); memcpy(trailing_buf, align_buf, 1); + } else { + memcpy(align_buf, trailing_buf, 1); + write_atapi_data(base, 1, align_buf); } + words++; } + + return words << 1; } /** diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index 120b5bfa7ce6..030878fedeb5 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -42,13 +42,13 @@ static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error) return 0; } -static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf, - unsigned int buflen, int write_data) +static unsigned int ixp4xx_mmio_data_xfer(struct ata_device *dev, + unsigned char *buf, unsigned int buflen, int rw) { unsigned int i; unsigned int words = buflen >> 1; u16 *buf16 = (u16 *) buf; - struct ata_port *ap = adev->link->ap; + struct ata_port *ap = dev->link->ap; void __iomem *mmio = ap->ioaddr.data_addr; struct ixp4xx_pata_data *data = ap->host->dev->platform_data; @@ -59,30 +59,32 @@ static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf, udelay(100); /* Transfer multiple of 2 bytes */ - if (write_data) { - for (i = 0; i < words; i++) - writew(buf16[i], mmio); - } else { + if (rw == READ) for (i = 0; i < words; i++) buf16[i] = readw(mmio); - } + else + for (i = 0; i < words; i++) + writew(buf16[i], mmio); /* Transfer trailing 1 byte, if any. */ if (unlikely(buflen & 0x01)) { u16 align_buf[1] = { 0 }; unsigned char *trailing_buf = buf + buflen - 1; - if (write_data) { - memcpy(align_buf, trailing_buf, 1); - writew(align_buf[0], mmio); - } else { + if (rw == READ) { align_buf[0] = readw(mmio); memcpy(trailing_buf, align_buf, 1); + } else { + memcpy(align_buf, trailing_buf, 1); + writew(align_buf[0], mmio); } + words++; } udelay(100); *data->cs0_cfg |= 0x01; + + return words << 1; } static struct scsi_host_template ixp4xx_sht = { diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index 17159b5e1e43..dae85aa12e32 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c @@ -249,13 +249,14 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev) } -static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) +static unsigned int pdc_data_xfer_vlb(struct ata_device *dev, + unsigned char *buf, unsigned int buflen, int rw) { - struct ata_port *ap = adev->link->ap; - int slop = buflen & 3; - unsigned long flags; - if (ata_id_has_dword_io(adev->id)) { + struct ata_port *ap = dev->link->ap; + int slop = buflen & 3; + unsigned long flags; + local_irq_save(flags); /* Perform the 32bit I/O synchronization sequence */ @@ -264,26 +265,27 @@ static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsig ioread8(ap->ioaddr.nsect_addr); /* Now the data */ - - if (write_data) - iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); - else + if (rw == READ) ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); + else + iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); if (unlikely(slop)) { - __le32 pad = 0; - if (write_data) { - memcpy(&pad, buf + buflen - slop, slop); - iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); - } else { + u32 pad; + if (rw == READ) { pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); memcpy(buf + buflen - slop, &pad, slop); + } else { + memcpy(&pad, buf + buflen - slop, slop); + iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); } + buflen += 4 - slop; } local_irq_restore(flags); - } - else - ata_data_xfer_noirq(adev, buf, buflen, write_data); + } else + buflen = ata_data_xfer_noirq(dev, buf, buflen, rw); + + return buflen; } static struct ata_port_operations pdc20230_port_ops = { diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c index a4c0e502cb42..9f308ed76cc8 100644 --- a/drivers/ata/pata_qdi.c +++ b/drivers/ata/pata_qdi.c @@ -124,29 +124,33 @@ static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc) return ata_qc_issue_prot(qc); } -static void qdi_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) +static unsigned int qdi_data_xfer(struct ata_device *dev, unsigned char *buf, + unsigned int buflen, int rw) { - struct ata_port *ap = adev->link->ap; - int slop = buflen & 3; + if (ata_id_has_dword_io(dev->id)) { + struct ata_port *ap = dev->link->ap; + int slop = buflen & 3; - if (ata_id_has_dword_io(adev->id)) { - if (write_data) - iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); - else + if (rw == READ) ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); + else + iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); if (unlikely(slop)) { - __le32 pad = 0; - if (write_data) { - memcpy(&pad, buf + buflen - slop, slop); - iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); - } else { + u32 pad; + if (rw == READ) { pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); memcpy(buf + buflen - slop, &pad, slop); + } else { + memcpy(&pad, buf + buflen - slop, slop); + iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); } + buflen += 4 - slop; } } else - ata_data_xfer(adev, buf, buflen, write_data); + buflen = ata_data_xfer(dev, buf, buflen, rw); + + return buflen; } static struct scsi_host_template qdi_sht = { diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index ea2ef9fc15be..55055b27524c 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -768,45 +768,47 @@ static u8 scc_bmdma_status (struct ata_port *ap) /** * scc_data_xfer - Transfer data by PIO - * @adev: device for this I/O + * @dev: device for this I/O * @buf: data buffer * @buflen: buffer length - * @write_data: read/write + * @rw: read/write * * Note: Original code is ata_data_xfer(). */ -static void scc_data_xfer (struct ata_device *adev, unsigned char *buf, - unsigned int buflen, int write_data) +static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf, + unsigned int buflen, int rw) { - struct ata_port *ap = adev->link->ap; + struct ata_port *ap = dev->link->ap; unsigned int words = buflen >> 1; unsigned int i; u16 *buf16 = (u16 *) buf; void __iomem *mmio = ap->ioaddr.data_addr; /* Transfer multiple of 2 bytes */ - if (write_data) { - for (i = 0; i < words; i++) - out_be32(mmio, cpu_to_le16(buf16[i])); - } else { + if (rw == READ) for (i = 0; i < words; i++) buf16[i] = le16_to_cpu(in_be32(mmio)); - } + else + for (i = 0; i < words; i++) + out_be32(mmio, cpu_to_le16(buf16[i])); /* Transfer trailing 1 byte, if any. */ if (unlikely(buflen & 0x01)) { u16 align_buf[1] = { 0 }; unsigned char *trailing_buf = buf + buflen - 1; - if (write_data) { - memcpy(align_buf, trailing_buf, 1); - out_be32(mmio, cpu_to_le16(align_buf[0])); - } else { + if (rw == READ) { align_buf[0] = le16_to_cpu(in_be32(mmio)); memcpy(trailing_buf, align_buf, 1); + } else { + memcpy(align_buf, trailing_buf, 1); + out_be32(mmio, cpu_to_le16(align_buf[0])); } + words++; } + + return words << 1; } /** diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c index 7116a9e7a8b2..7312e9182d69 100644 --- a/drivers/ata/pata_winbond.c +++ b/drivers/ata/pata_winbond.c @@ -92,29 +92,33 @@ static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev) } -static void winbond_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) +static void winbond_data_xfer(struct ata_device *dev, unsigned char *buf, + unsigned int buflen, int rw) { - struct ata_port *ap = adev->link->ap; + struct ata_port *ap = dev->link->ap; int slop = buflen & 3; - if (ata_id_has_dword_io(adev->id)) { - if (write_data) - iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); - else + if (ata_id_has_dword_io(dev->id)) { + if (rw == READ) ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); + else + iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); if (unlikely(slop)) { - __le32 pad = 0; - if (write_data) { - memcpy(&pad, buf + buflen - slop, slop); - iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); - } else { + u32 pad; + if (rw == READ) { pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); memcpy(buf + buflen - slop, &pad, slop); + } else { + memcpy(&pad, buf + buflen - slop, slop); + iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); } + buflen += 4 - slop; } } else - ata_data_xfer(adev, buf, buflen, write_data); + buflen = ata_data_xfer(dev, buf, buflen, rw); + + return buflen; } static struct scsi_host_template winbond_sht = { diff --git a/include/linux/libata.h b/include/linux/libata.h index 03afcd63202d..7fa96cb4f6db 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -701,7 +701,8 @@ struct ata_port_operations { void (*bmdma_setup) (struct ata_queued_cmd *qc); void (*bmdma_start) (struct ata_queued_cmd *qc); - void (*data_xfer) (struct ata_device *, unsigned char *, unsigned int, int); + unsigned int (*data_xfer) (struct ata_device *dev, unsigned char *buf, + unsigned int buflen, int rw); int (*qc_defer) (struct ata_queued_cmd *qc); void (*qc_prep) (struct ata_queued_cmd *qc); @@ -881,10 +882,10 @@ 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); -extern void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf, - unsigned int buflen, int write_data); +extern unsigned int ata_data_xfer(struct ata_device *dev, + unsigned char *buf, unsigned int buflen, int rw); +extern unsigned int ata_data_xfer_noirq(struct ata_device *dev, + unsigned char *buf, unsigned int buflen, int rw); extern int ata_std_qc_defer(struct ata_queued_cmd *qc); extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc); extern void ata_qc_prep(struct ata_queued_cmd *qc); -- cgit v1.2.3 From 001102d7859be0e7f7b9f2d62b841f2c0f9c2640 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 5 Dec 2007 16:43:09 +0900 Subject: libata: kill non-sg DMA interface With atapi_request_sense() converted to use sg, there's no user of non-sg interface. Kill non-sg interface. * ATA_QCFLAG_SINGLE and ATA_QCFLAG_SG are removed. ATA_QCFLAG_DMAMAP is used instead. (this way no LLD change is necessary) * qc->buf_virt is removed. * ata_sg_init_one() and ata_sg_setup_one() are removed. Signed-off-by: Tejun Heo Cc: Rusty Russel Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 148 +++++----------------------------------------- include/linux/libata.h | 7 +-- 2 files changed, 16 insertions(+), 139 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 39cedd949ed4..76360f0ca20d 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4478,9 +4478,6 @@ void ata_sg_clean(struct ata_queued_cmd *qc) WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP)); WARN_ON(sg == NULL); - if (qc->flags & ATA_QCFLAG_SINGLE) - WARN_ON(qc->n_elem > 1); - VPRINTK("unmapping %u sg elements\n", qc->n_elem); /* if we padded the buffer out to 32-bit bound, and data @@ -4490,27 +4487,15 @@ void ata_sg_clean(struct ata_queued_cmd *qc) if (qc->pad_len && !(qc->tf.flags & ATA_TFLAG_WRITE)) pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ); - if (qc->flags & ATA_QCFLAG_SG) { - if (qc->n_elem) - dma_unmap_sg(ap->dev, sg, qc->n_elem, dir); - /* restore last sg */ - sg_last(sg, qc->orig_n_elem)->length += qc->pad_len; - if (pad_buf) { - struct scatterlist *psg = &qc->pad_sgent; - void *addr = kmap_atomic(sg_page(psg), KM_IRQ0); - memcpy(addr + psg->offset, pad_buf, qc->pad_len); - kunmap_atomic(addr, KM_IRQ0); - } - } else { - if (qc->n_elem) - dma_unmap_single(ap->dev, - sg_dma_address(&sg[0]), sg_dma_len(&sg[0]), - dir); - /* restore sg */ - sg->length += qc->pad_len; - if (pad_buf) - memcpy(qc->buf_virt + sg->length - qc->pad_len, - pad_buf, qc->pad_len); + if (qc->n_elem) + dma_unmap_sg(ap->dev, sg, qc->n_elem, dir); + /* restore last sg */ + sg_last(sg, qc->orig_n_elem)->length += qc->pad_len; + if (pad_buf) { + struct scatterlist *psg = &qc->pad_sgent; + void *addr = kmap_atomic(sg_page(psg), KM_IRQ0); + memcpy(addr + psg->offset, pad_buf, qc->pad_len); + kunmap_atomic(addr, KM_IRQ0); } qc->flags &= ~ATA_QCFLAG_DMAMAP; @@ -4764,33 +4749,6 @@ void ata_dumb_qc_prep(struct ata_queued_cmd *qc) void ata_noop_qc_prep(struct ata_queued_cmd *qc) { } -/** - * ata_sg_init_one - Associate command with memory buffer - * @qc: Command to be associated - * @buf: Memory buffer - * @buflen: Length of memory buffer, in bytes. - * - * Initialize the data-related elements of queued_cmd @qc - * to point to a single memory buffer, @buf of byte length @buflen. - * - * LOCKING: - * spin_lock_irqsave(host lock) - */ - -void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen) -{ - qc->flags |= ATA_QCFLAG_SINGLE; - - qc->__sg = &qc->sgent; - qc->n_elem = 1; - qc->orig_n_elem = 1; - qc->buf_virt = buf; - qc->nbytes = buflen; - qc->cursg = qc->__sg; - - sg_init_one(&qc->sgent, buf, buflen); -} - /** * ata_sg_init - Associate command with scatter-gather table. * @qc: Command to be associated @@ -4808,82 +4766,13 @@ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen) void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, unsigned int n_elem) { - qc->flags |= ATA_QCFLAG_SG; + qc->flags |= ATA_QCFLAG_DMAMAP; qc->__sg = sg; qc->n_elem = n_elem; qc->orig_n_elem = n_elem; qc->cursg = qc->__sg; } -/** - * ata_sg_setup_one - DMA-map the memory buffer associated with a command. - * @qc: Command with memory buffer to be mapped. - * - * DMA-map the memory buffer associated with queued_cmd @qc. - * - * LOCKING: - * spin_lock_irqsave(host lock) - * - * RETURNS: - * Zero on success, negative on error. - */ - -static int ata_sg_setup_one(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - int dir = qc->dma_dir; - struct scatterlist *sg = qc->__sg; - dma_addr_t dma_address; - int trim_sg = 0; - - /* we must lengthen transfers to end on a 32-bit boundary */ - qc->pad_len = sg->length & 3; - if (qc->pad_len) { - void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ); - struct scatterlist *psg = &qc->pad_sgent; - - WARN_ON(qc->dev->class != ATA_DEV_ATAPI); - - memset(pad_buf, 0, ATA_DMA_PAD_SZ); - - if (qc->tf.flags & ATA_TFLAG_WRITE) - memcpy(pad_buf, qc->buf_virt + sg->length - qc->pad_len, - qc->pad_len); - - sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ); - sg_dma_len(psg) = ATA_DMA_PAD_SZ; - /* trim sg */ - sg->length -= qc->pad_len; - if (sg->length == 0) - trim_sg = 1; - - DPRINTK("padding done, sg->length=%u pad_len=%u\n", - sg->length, qc->pad_len); - } - - if (trim_sg) { - qc->n_elem--; - goto skip_map; - } - - dma_address = dma_map_single(ap->dev, qc->buf_virt, - sg->length, dir); - if (dma_mapping_error(dma_address)) { - /* restore sg */ - sg->length += qc->pad_len; - return -1; - } - - sg_dma_address(sg) = dma_address; - sg_dma_len(sg) = sg->length; - -skip_map: - DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg), - qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); - - return 0; -} - /** * ata_sg_setup - DMA-map the scatter-gather table associated with a command. * @qc: Command with scatter-gather table to be mapped. @@ -4906,7 +4795,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) int n_elem, pre_n_elem, dir, trim_sg = 0; VPRINTK("ENTER, ata%u\n", ap->print_id); - WARN_ON(!(qc->flags & ATA_QCFLAG_SG)); + WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP)); /* we must lengthen transfers to end on a 32-bit boundary */ qc->pad_len = lsg->length & 3; @@ -6025,16 +5914,10 @@ void ata_qc_issue(struct ata_queued_cmd *qc) if (ata_is_dma(prot) || (ata_is_pio(prot) && (ap->flags & ATA_FLAG_PIO_DMA))) { - if (qc->flags & ATA_QCFLAG_SG) { - if (ata_sg_setup(qc)) - goto sg_err; - } else if (qc->flags & ATA_QCFLAG_SINGLE) { - if (ata_sg_setup_one(qc)) - goto sg_err; - } - } else { - qc->flags &= ~ATA_QCFLAG_DMAMAP; - } + if (ata_sg_setup(qc)) + goto sg_err; + } else + qc->flags &= ATA_QCFLAG_DMAMAP; /* if device is sleeping, schedule softreset and abort the link */ if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) { @@ -7612,7 +7495,6 @@ EXPORT_SYMBOL_GPL(ata_host_register); EXPORT_SYMBOL_GPL(ata_host_activate); EXPORT_SYMBOL_GPL(ata_host_detach); EXPORT_SYMBOL_GPL(ata_sg_init); -EXPORT_SYMBOL_GPL(ata_sg_init_one); EXPORT_SYMBOL_GPL(ata_hsm_move); EXPORT_SYMBOL_GPL(ata_qc_complete); EXPORT_SYMBOL_GPL(ata_qc_complete_multiple); diff --git a/include/linux/libata.h b/include/linux/libata.h index 7fa96cb4f6db..acd90ad78417 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -219,9 +219,7 @@ enum { /* struct ata_queued_cmd flags */ ATA_QCFLAG_ACTIVE = (1 << 0), /* cmd not yet ack'd to scsi lyer */ - ATA_QCFLAG_SG = (1 << 1), /* have s/g table? */ - ATA_QCFLAG_SINGLE = (1 << 2), /* no s/g, just a single buffer */ - ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, + ATA_QCFLAG_DMAMAP = (1 << 1), /* SG table is DMA mapped */ ATA_QCFLAG_IO = (1 << 3), /* standard IO command */ ATA_QCFLAG_RESULT_TF = (1 << 4), /* result TF requested */ ATA_QCFLAG_CLEAR_EXCL = (1 << 5), /* clear excl_link on completion */ @@ -475,7 +473,6 @@ struct ata_queued_cmd { struct scatterlist sgent; struct scatterlist pad_sgent; - void *buf_virt; /* DO NOT iterate over __sg manually, use ata_for_each_sg() */ struct scatterlist *__sg; @@ -891,8 +888,6 @@ extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc); extern void ata_qc_prep(struct ata_queued_cmd *qc); extern void ata_noop_qc_prep(struct ata_queued_cmd *qc); extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc); -extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, - unsigned int buflen); extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, unsigned int n_elem); extern unsigned int ata_dev_classify(const struct ata_taskfile *tf); -- cgit v1.2.3 From f92a26365a72333f418abe82700c6030d4a1a807 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 5 Dec 2007 16:43:10 +0900 Subject: libata: change ATA_QCFLAG_DMAMAP semantics ATA_QCFLAG_DMAMAP was a bit peculiar in that it got set during qc initialization and cleared if DMA mapping wasn't necessary. Make it more straight forward by making the following changes. * Don't set it during initialization. Set it after DMA is actually mapped. * Add BUG_ON() to guarantee that there is data to transfer if DMAMAP is set. This always holds for the current code. The BUG_ON() is for docummentation and sanity check. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 76360f0ca20d..865428a64de3 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4475,7 +4475,6 @@ void ata_sg_clean(struct ata_queued_cmd *qc) int dir = qc->dma_dir; void *pad_buf = NULL; - WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP)); WARN_ON(sg == NULL); VPRINTK("unmapping %u sg elements\n", qc->n_elem); @@ -4762,11 +4761,9 @@ void ata_noop_qc_prep(struct ata_queued_cmd *qc) { } * LOCKING: * spin_lock_irqsave(host lock) */ - void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, unsigned int n_elem) { - qc->flags |= ATA_QCFLAG_DMAMAP; qc->__sg = sg; qc->n_elem = n_elem; qc->orig_n_elem = n_elem; @@ -4795,7 +4792,6 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) int n_elem, pre_n_elem, dir, trim_sg = 0; VPRINTK("ENTER, ata%u\n", ap->print_id); - WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP)); /* we must lengthen transfers to end on a 32-bit boundary */ qc->pad_len = lsg->length & 3; @@ -4855,6 +4851,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) skip_map: qc->n_elem = n_elem; + qc->flags |= ATA_QCFLAG_DMAMAP; return 0; } @@ -5912,12 +5909,15 @@ void ata_qc_issue(struct ata_queued_cmd *qc) qc->flags |= ATA_QCFLAG_ACTIVE; ap->qc_active |= 1 << qc->tag; + /* We guarantee to LLDs that they will have at least one + * non-zero sg if the command is a data command. + */ + BUG_ON(ata_is_data(prot) && (!qc->__sg || !qc->n_elem || !qc->nbytes)); + if (ata_is_dma(prot) || (ata_is_pio(prot) && - (ap->flags & ATA_FLAG_PIO_DMA))) { + (ap->flags & ATA_FLAG_PIO_DMA))) if (ata_sg_setup(qc)) goto sg_err; - } else - qc->flags &= ATA_QCFLAG_DMAMAP; /* if device is sleeping, schedule softreset and abort the link */ if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) { @@ -5935,7 +5935,6 @@ void ata_qc_issue(struct ata_queued_cmd *qc) return; sg_err: - qc->flags &= ~ATA_QCFLAG_DMAMAP; qc->err_mask |= AC_ERR_SYSTEM; err: ata_qc_complete(qc); -- cgit v1.2.3 From ff2aeb1eb64c8a4770a6304f9addbae9f9828646 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 5 Dec 2007 16:43:11 +0900 Subject: libata: convert to chained sg libata used private sg iterator to handle padding sg. Now that sg can be chained, padding can be handled using standard sg ops. Convert to chained sg. * s/qc->__sg/qc->sg/ * s/qc->pad_sgent/qc->extra_sg[]/. Because chaining consumes one sg entry. There need to be two extra sg entries. The renaming is also for future addition of other extra sg entries. * Padding setup is moved into ata_sg_setup_extra() which is organized in a way that future addition of other extra sg entries is easy. * qc->orig_n_elem is unused and removed. * qc->n_elem now contains the number of sg entries that LLDs should map. qc->mapped_n_elem is added to carry the original number of mapped sgs for unmapping. * The last sg of the original sg list is used to chain to extra sg list. The original last sg is pointed to by qc->last_sg and the content is stored in qc->saved_last_sg. It's restored during ata_sg_clean(). * All sg walking code has been updated. Unnecessary assertions and checks for conditions the core layer already guarantees are removed. Signed-off-by: Tejun Heo Cc: Jens Axboe Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 18 ++-- drivers/ata/libata-core.c | 201 +++++++++++++++++++++++++----------------- drivers/ata/libata-scsi.c | 2 +- drivers/ata/pata_bf54x.c | 13 +-- drivers/ata/pata_icside.c | 3 +- drivers/ata/pdc_adma.c | 3 +- drivers/ata/sata_fsl.c | 4 +- drivers/ata/sata_mv.c | 3 +- drivers/ata/sata_nv.c | 25 ++---- drivers/ata/sata_promise.c | 40 ++++----- drivers/ata/sata_qstor.c | 13 +-- drivers/ata/sata_sil24.c | 6 +- drivers/ata/sata_sx4.c | 4 +- drivers/scsi/ipr.c | 3 +- drivers/scsi/libsas/sas_ata.c | 10 +-- include/linux/libata.h | 42 ++------- 16 files changed, 193 insertions(+), 197 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 5eee91c73c90..cffad07c65bf 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1483,28 +1483,24 @@ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf) static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl) { struct scatterlist *sg; - struct ahci_sg *ahci_sg; - unsigned int n_sg = 0; + struct ahci_sg *ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ; + unsigned int si; VPRINTK("ENTER\n"); /* * Next, the S/G list. */ - ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ; - ata_for_each_sg(sg, qc) { + for_each_sg(qc->sg, sg, qc->n_elem, si) { dma_addr_t addr = sg_dma_address(sg); u32 sg_len = sg_dma_len(sg); - ahci_sg->addr = cpu_to_le32(addr & 0xffffffff); - ahci_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16); - ahci_sg->flags_size = cpu_to_le32(sg_len - 1); - - ahci_sg++; - n_sg++; + ahci_sg[si].addr = cpu_to_le32(addr & 0xffffffff); + ahci_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16); + ahci_sg[si].flags_size = cpu_to_le32(sg_len - 1); } - return n_sg; + return si; } static void ahci_qc_prep(struct ata_queued_cmd *qc) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 865428a64de3..e998028302da 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4471,13 +4471,13 @@ static unsigned int ata_dev_init_params(struct ata_device *dev, void ata_sg_clean(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - struct scatterlist *sg = qc->__sg; + struct scatterlist *sg = qc->sg; int dir = qc->dma_dir; void *pad_buf = NULL; WARN_ON(sg == NULL); - VPRINTK("unmapping %u sg elements\n", qc->n_elem); + VPRINTK("unmapping %u sg elements\n", qc->mapped_n_elem); /* if we padded the buffer out to 32-bit bound, and data * xfer direction is from-device, we must copy from the @@ -4486,19 +4486,20 @@ void ata_sg_clean(struct ata_queued_cmd *qc) if (qc->pad_len && !(qc->tf.flags & ATA_TFLAG_WRITE)) pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ); - if (qc->n_elem) - dma_unmap_sg(ap->dev, sg, qc->n_elem, dir); + if (qc->mapped_n_elem) + dma_unmap_sg(ap->dev, sg, qc->mapped_n_elem, dir); /* restore last sg */ - sg_last(sg, qc->orig_n_elem)->length += qc->pad_len; + if (qc->last_sg) + *qc->last_sg = qc->saved_last_sg; if (pad_buf) { - struct scatterlist *psg = &qc->pad_sgent; + struct scatterlist *psg = &qc->extra_sg[1]; void *addr = kmap_atomic(sg_page(psg), KM_IRQ0); memcpy(addr + psg->offset, pad_buf, qc->pad_len); kunmap_atomic(addr, KM_IRQ0); } qc->flags &= ~ATA_QCFLAG_DMAMAP; - qc->__sg = NULL; + qc->sg = NULL; } /** @@ -4516,13 +4517,10 @@ static void ata_fill_sg(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct scatterlist *sg; - unsigned int idx; + unsigned int si, pi; - WARN_ON(qc->__sg == NULL); - WARN_ON(qc->n_elem == 0 && qc->pad_len == 0); - - idx = 0; - ata_for_each_sg(sg, qc) { + pi = 0; + for_each_sg(qc->sg, sg, qc->n_elem, si) { u32 addr, offset; u32 sg_len, len; @@ -4539,18 +4537,17 @@ static void ata_fill_sg(struct ata_queued_cmd *qc) if ((offset + sg_len) > 0x10000) len = 0x10000 - offset; - ap->prd[idx].addr = cpu_to_le32(addr); - ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff); - VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len); + ap->prd[pi].addr = cpu_to_le32(addr); + ap->prd[pi].flags_len = cpu_to_le32(len & 0xffff); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len); - idx++; + pi++; sg_len -= len; addr += len; } } - if (idx) - ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); + ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); } /** @@ -4570,13 +4567,10 @@ static void ata_fill_sg_dumb(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct scatterlist *sg; - unsigned int idx; - - WARN_ON(qc->__sg == NULL); - WARN_ON(qc->n_elem == 0 && qc->pad_len == 0); + unsigned int si, pi; - idx = 0; - ata_for_each_sg(sg, qc) { + pi = 0; + for_each_sg(qc->sg, sg, qc->n_elem, si) { u32 addr, offset; u32 sg_len, len, blen; @@ -4594,25 +4588,24 @@ static void ata_fill_sg_dumb(struct ata_queued_cmd *qc) len = 0x10000 - offset; blen = len & 0xffff; - ap->prd[idx].addr = cpu_to_le32(addr); + ap->prd[pi].addr = cpu_to_le32(addr); if (blen == 0) { /* Some PATA chipsets like the CS5530 can't cope with 0x0000 meaning 64K as the spec says */ - ap->prd[idx].flags_len = cpu_to_le32(0x8000); + ap->prd[pi].flags_len = cpu_to_le32(0x8000); blen = 0x8000; - ap->prd[++idx].addr = cpu_to_le32(addr + 0x8000); + ap->prd[++pi].addr = cpu_to_le32(addr + 0x8000); } - ap->prd[idx].flags_len = cpu_to_le32(blen); - VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len); + ap->prd[pi].flags_len = cpu_to_le32(blen); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len); - idx++; + pi++; sg_len -= len; addr += len; } } - if (idx) - ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); + ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); } /** @@ -4764,54 +4757,48 @@ void ata_noop_qc_prep(struct ata_queued_cmd *qc) { } void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, unsigned int n_elem) { - qc->__sg = sg; + qc->sg = sg; qc->n_elem = n_elem; - qc->orig_n_elem = n_elem; - qc->cursg = qc->__sg; + qc->cursg = qc->sg; } -/** - * ata_sg_setup - DMA-map the scatter-gather table associated with a command. - * @qc: Command with scatter-gather table to be mapped. - * - * DMA-map the scatter-gather table associated with queued_cmd @qc. - * - * LOCKING: - * spin_lock_irqsave(host lock) - * - * RETURNS: - * Zero on success, negative on error. - * - */ - -static int ata_sg_setup(struct ata_queued_cmd *qc) +static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc, + unsigned int *n_elem_extra) { struct ata_port *ap = qc->ap; - struct scatterlist *sg = qc->__sg; - struct scatterlist *lsg = sg_last(qc->__sg, qc->n_elem); - int n_elem, pre_n_elem, dir, trim_sg = 0; + unsigned int n_elem = qc->n_elem; + struct scatterlist *lsg, *copy_lsg = NULL, *tsg = NULL, *esg = NULL; - VPRINTK("ENTER, ata%u\n", ap->print_id); + *n_elem_extra = 0; + + /* needs padding? */ + qc->pad_len = qc->nbytes & 3; + + if (likely(!qc->pad_len)) + return n_elem; + + /* locate last sg and save it */ + lsg = sg_last(qc->sg, n_elem); + qc->last_sg = lsg; + qc->saved_last_sg = *lsg; + + sg_init_table(qc->extra_sg, ARRAY_SIZE(qc->extra_sg)); - /* we must lengthen transfers to end on a 32-bit boundary */ - qc->pad_len = lsg->length & 3; if (qc->pad_len) { + struct scatterlist *psg = &qc->extra_sg[1]; void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ); - struct scatterlist *psg = &qc->pad_sgent; unsigned int offset; WARN_ON(qc->dev->class != ATA_DEV_ATAPI); memset(pad_buf, 0, ATA_DMA_PAD_SZ); - /* - * psg->page/offset are used to copy to-be-written + /* psg->page/offset are used to copy to-be-written * data in this function or read data in ata_sg_clean. */ offset = lsg->offset + lsg->length - qc->pad_len; - sg_init_table(psg, 1); sg_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT), - qc->pad_len, offset_in_page(offset)); + qc->pad_len, offset_in_page(offset)); if (qc->tf.flags & ATA_TFLAG_WRITE) { void *addr = kmap_atomic(sg_page(psg), KM_IRQ0); @@ -4821,36 +4808,84 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ); sg_dma_len(psg) = ATA_DMA_PAD_SZ; - /* trim last sg */ + + /* Trim the last sg entry and chain the original and + * padding sg lists. + * + * Because chaining consumes one sg entry, one extra + * sg entry is allocated and the last sg entry is + * copied to it if the length isn't zero after padded + * amount is removed. + * + * If the last sg entry is completely replaced by + * padding sg entry, the first sg entry is skipped + * while chaining. + */ lsg->length -= qc->pad_len; - if (lsg->length == 0) - trim_sg = 1; + if (lsg->length) { + copy_lsg = &qc->extra_sg[0]; + tsg = &qc->extra_sg[0]; + } else { + n_elem--; + tsg = &qc->extra_sg[1]; + } + + esg = &qc->extra_sg[1]; - DPRINTK("padding done, sg[%d].length=%u pad_len=%u\n", - qc->n_elem - 1, lsg->length, qc->pad_len); + (*n_elem_extra)++; } - pre_n_elem = qc->n_elem; - if (trim_sg && pre_n_elem) - pre_n_elem--; + if (copy_lsg) + sg_set_page(copy_lsg, sg_page(lsg), lsg->length, lsg->offset); - if (!pre_n_elem) { - n_elem = 0; - goto skip_map; + sg_chain(lsg, 1, tsg); + sg_mark_end(esg); + + /* sglist can't start with chaining sg entry, fast forward */ + if (qc->sg == lsg) { + qc->sg = tsg; + qc->cursg = tsg; } - dir = qc->dma_dir; - n_elem = dma_map_sg(ap->dev, sg, pre_n_elem, dir); - if (n_elem < 1) { - /* restore last sg */ - lsg->length += qc->pad_len; - return -1; + return n_elem; +} + +/** + * ata_sg_setup - DMA-map the scatter-gather table associated with a command. + * @qc: Command with scatter-gather table to be mapped. + * + * DMA-map the scatter-gather table associated with queued_cmd @qc. + * + * LOCKING: + * spin_lock_irqsave(host lock) + * + * RETURNS: + * Zero on success, negative on error. + * + */ +static int ata_sg_setup(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + unsigned int n_elem, n_elem_extra; + + VPRINTK("ENTER, ata%u\n", ap->print_id); + + n_elem = ata_sg_setup_extra(qc, &n_elem_extra); + + if (n_elem) { + n_elem = dma_map_sg(ap->dev, qc->sg, n_elem, qc->dma_dir); + if (n_elem < 1) { + /* restore last sg */ + if (qc->last_sg) + *qc->last_sg = qc->saved_last_sg; + return -1; + } + DPRINTK("%d sg elements mapped\n", n_elem); } - DPRINTK("%d sg elements mapped\n", n_elem); + qc->n_elem = qc->mapped_n_elem = n_elem; + qc->n_elem += n_elem_extra; -skip_map: - qc->n_elem = n_elem; qc->flags |= ATA_QCFLAG_DMAMAP; return 0; @@ -5912,7 +5947,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc) /* We guarantee to LLDs that they will have at least one * non-zero sg if the command is a data command. */ - BUG_ON(ata_is_data(prot) && (!qc->__sg || !qc->n_elem || !qc->nbytes)); + BUG_ON(ata_is_data(prot) && (!qc->sg || !qc->n_elem || !qc->nbytes)); if (ata_is_dma(prot) || (ata_is_pio(prot) && (ap->flags & ATA_FLAG_PIO_DMA))) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 5fd780e509d4..42bf61599730 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -517,7 +517,7 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, qc->scsicmd = cmd; qc->scsidone = done; - qc->__sg = scsi_sglist(cmd); + qc->sg = scsi_sglist(cmd); qc->n_elem = scsi_sg_count(cmd); } else { cmd->result = (DID_OK << 16) | (QUEUE_FULL << 1); diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index 41cd921082ba..a32e3c44a606 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c @@ -832,6 +832,7 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc) { unsigned short config = WDSIZE_16; struct scatterlist *sg; + unsigned int si; pr_debug("in atapi dma setup\n"); /* Program the ATA_CTRL register with dir */ @@ -839,7 +840,7 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc) /* fill the ATAPI DMA controller */ set_dma_config(CH_ATAPI_TX, config); set_dma_x_modify(CH_ATAPI_TX, 2); - ata_for_each_sg(sg, qc) { + for_each_sg(qc->sg, sg, qc->n_elem, si) { set_dma_start_addr(CH_ATAPI_TX, sg_dma_address(sg)); set_dma_x_count(CH_ATAPI_TX, sg_dma_len(sg) >> 1); } @@ -848,7 +849,7 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc) /* fill the ATAPI DMA controller */ set_dma_config(CH_ATAPI_RX, config); set_dma_x_modify(CH_ATAPI_RX, 2); - ata_for_each_sg(sg, qc) { + for_each_sg(qc->sg, sg, qc->n_elem, si) { set_dma_start_addr(CH_ATAPI_RX, sg_dma_address(sg)); set_dma_x_count(CH_ATAPI_RX, sg_dma_len(sg) >> 1); } @@ -867,6 +868,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; struct scatterlist *sg; + unsigned int si; pr_debug("in atapi dma start\n"); if (!(ap->udma_mask || ap->mwdma_mask)) @@ -881,7 +883,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc) * data cache is enabled. Otherwise, this loop * is an empty loop and optimized out. */ - ata_for_each_sg(sg, qc) { + for_each_sg(qc->sg, sg, qc->n_elem, si) { flush_dcache_range(sg_dma_address(sg), sg_dma_address(sg) + sg_dma_len(sg)); } @@ -910,7 +912,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc) ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | TFRCNT_RST); /* Set transfer length to buffer len */ - ata_for_each_sg(sg, qc) { + for_each_sg(qc->sg, sg, qc->n_elem, si) { ATAPI_SET_XFER_LEN(base, (sg_dma_len(sg) >> 1)); } @@ -932,6 +934,7 @@ static void bfin_bmdma_stop(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct scatterlist *sg; + unsigned int si; pr_debug("in atapi dma stop\n"); if (!(ap->udma_mask || ap->mwdma_mask)) @@ -950,7 +953,7 @@ static void bfin_bmdma_stop(struct ata_queued_cmd *qc) * data cache is enabled. Otherwise, this loop * is an empty loop and optimized out. */ - ata_for_each_sg(sg, qc) { + for_each_sg(qc->sg, sg, qc->n_elem, si) { invalidate_dcache_range( sg_dma_address(sg), sg_dma_address(sg) diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c index 842fe08a3c13..5b8586dac63b 100644 --- a/drivers/ata/pata_icside.c +++ b/drivers/ata/pata_icside.c @@ -224,6 +224,7 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc) struct pata_icside_state *state = ap->host->private_data; struct scatterlist *sg, *rsg = state->sg; unsigned int write = qc->tf.flags & ATA_TFLAG_WRITE; + unsigned int si; /* * We are simplex; BUG if we try to fiddle with DMA @@ -234,7 +235,7 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc) /* * Copy ATAs scattered sg list into a contiguous array of sg */ - ata_for_each_sg(sg, qc) { + for_each_sg(qc->sg, sg, qc->n_elem, si) { memcpy(rsg, sg, sizeof(*sg)); rsg++; } diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c index 459cb7bb7d7f..8e1b7e9c0ae4 100644 --- a/drivers/ata/pdc_adma.c +++ b/drivers/ata/pdc_adma.c @@ -321,8 +321,9 @@ static int adma_fill_sg(struct ata_queued_cmd *qc) u8 *buf = pp->pkt, *last_buf = NULL; int i = (2 + buf[3]) * 8; u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0); + unsigned int si; - ata_for_each_sg(sg, qc) { + for_each_sg(qc->sg, sg, qc->n_elem, si) { u32 addr; u32 len; diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index a3c33f165427..d041709dee1a 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -323,6 +323,7 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc, struct scatterlist *sg; unsigned int num_prde = 0; u32 ttl_dwords = 0; + unsigned int si; /* * NOTE : direct & indirect prdt's are contigiously allocated @@ -333,13 +334,14 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc, struct prde *prd_ptr_to_indirect_ext = NULL; unsigned indirect_ext_segment_sz = 0; dma_addr_t indirect_ext_segment_paddr; + unsigned int si; VPRINTK("SATA FSL : cd = 0x%x, prd = 0x%x\n", cmd_desc, prd); indirect_ext_segment_paddr = cmd_desc_paddr + SATA_FSL_CMD_DESC_OFFSET_TO_PRDT + SATA_FSL_MAX_PRD_DIRECT * 16; - ata_for_each_sg(sg, qc) { + for_each_sg(qc->sg, sg, qc->n_elem, si) { dma_addr_t sg_addr = sg_dma_address(sg); u32 sg_len = sg_dma_len(sg); diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 37b850ae0845..7e72463a90eb 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1136,9 +1136,10 @@ static void mv_fill_sg(struct ata_queued_cmd *qc) struct mv_port_priv *pp = qc->ap->private_data; struct scatterlist *sg; struct mv_sg *mv_sg, *last_sg = NULL; + unsigned int si; mv_sg = pp->sg_tbl; - ata_for_each_sg(sg, qc) { + for_each_sg(qc->sg, sg, qc->n_elem, si) { dma_addr_t addr = sg_dma_address(sg); u32 sg_len = sg_dma_len(sg); diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index ed5dc7cb50cd..a0f98fdab7a0 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -1336,21 +1336,18 @@ static void nv_adma_fill_aprd(struct ata_queued_cmd *qc, static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb) { struct nv_adma_port_priv *pp = qc->ap->private_data; - unsigned int idx; struct nv_adma_prd *aprd; struct scatterlist *sg; + unsigned int si; VPRINTK("ENTER\n"); - idx = 0; - - ata_for_each_sg(sg, qc) { - aprd = (idx < 5) ? &cpb->aprd[idx] : - &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (idx-5)]; - nv_adma_fill_aprd(qc, sg, idx, aprd); - idx++; + for_each_sg(qc->sg, sg, qc->n_elem, si) { + aprd = (si < 5) ? &cpb->aprd[si] : + &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (si-5)]; + nv_adma_fill_aprd(qc, sg, si, aprd); } - if (idx > 5) + if (si > 5) cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag))); else cpb->next_aprd = cpu_to_le64(0); @@ -1995,17 +1992,14 @@ static void nv_swncq_fill_sg(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct scatterlist *sg; - unsigned int idx; struct nv_swncq_port_priv *pp = ap->private_data; struct ata_prd *prd; - - WARN_ON(qc->__sg == NULL); - WARN_ON(qc->n_elem == 0 && qc->pad_len == 0); + unsigned int si, idx; prd = pp->prd + ATA_MAX_PRD * qc->tag; idx = 0; - ata_for_each_sg(sg, qc) { + for_each_sg(qc->sg, sg, qc->n_elem, si) { u32 addr, offset; u32 sg_len, len; @@ -2027,8 +2021,7 @@ static void nv_swncq_fill_sg(struct ata_queued_cmd *qc) } } - if (idx) - prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); + prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); } static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap, diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 01738d736d44..a07d319f6e8c 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -533,17 +533,15 @@ static void pdc_fill_sg(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct scatterlist *sg; - unsigned int idx; const u32 SG_COUNT_ASIC_BUG = 41*4; + unsigned int si, idx; + u32 len; if (!(qc->flags & ATA_QCFLAG_DMAMAP)) return; - WARN_ON(qc->__sg == NULL); - WARN_ON(qc->n_elem == 0 && qc->pad_len == 0); - idx = 0; - ata_for_each_sg(sg, qc) { + for_each_sg(qc->sg, sg, qc->n_elem, si) { u32 addr, offset; u32 sg_len, len; @@ -570,29 +568,27 @@ static void pdc_fill_sg(struct ata_queued_cmd *qc) } } - if (idx) { - u32 len = le32_to_cpu(ap->prd[idx - 1].flags_len); + len = le32_to_cpu(ap->prd[idx - 1].flags_len); - if (len > SG_COUNT_ASIC_BUG) { - u32 addr; + if (len > SG_COUNT_ASIC_BUG) { + u32 addr; - VPRINTK("Splitting last PRD.\n"); + VPRINTK("Splitting last PRD.\n"); - addr = le32_to_cpu(ap->prd[idx - 1].addr); - ap->prd[idx - 1].flags_len = cpu_to_le32(len - SG_COUNT_ASIC_BUG); - VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG); + addr = le32_to_cpu(ap->prd[idx - 1].addr); + ap->prd[idx - 1].flags_len = cpu_to_le32(len - SG_COUNT_ASIC_BUG); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG); - addr = addr + len - SG_COUNT_ASIC_BUG; - len = SG_COUNT_ASIC_BUG; - ap->prd[idx].addr = cpu_to_le32(addr); - ap->prd[idx].flags_len = cpu_to_le32(len); - VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len); + addr = addr + len - SG_COUNT_ASIC_BUG; + len = SG_COUNT_ASIC_BUG; + ap->prd[idx].addr = cpu_to_le32(addr); + ap->prd[idx].flags_len = cpu_to_le32(len); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len); - idx++; - } - - ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); + idx++; } + + ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); } static void pdc_qc_prep(struct ata_queued_cmd *qc) diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index 4e5f07bdd069..91cc12c82040 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -287,14 +287,10 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc) struct scatterlist *sg; struct ata_port *ap = qc->ap; struct qs_port_priv *pp = ap->private_data; - unsigned int nelem; u8 *prd = pp->pkt + QS_CPB_BYTES; + unsigned int si; - WARN_ON(qc->__sg == NULL); - WARN_ON(qc->n_elem == 0 && qc->pad_len == 0); - - nelem = 0; - ata_for_each_sg(sg, qc) { + for_each_sg(qc->sg, sg, qc->n_elem, si) { u64 addr; u32 len; @@ -306,12 +302,11 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc) *(__le32 *)prd = cpu_to_le32(len); prd += sizeof(u64); - VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", nelem, + VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", si, (unsigned long long)addr, len); - nelem++; } - return nelem; + return si; } static void qs_qc_prep(struct ata_queued_cmd *qc) diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index fdd3ceac329b..b4b1f91ea693 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -813,8 +813,9 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc, { struct scatterlist *sg; struct sil24_sge *last_sge = NULL; + unsigned int si; - ata_for_each_sg(sg, qc) { + for_each_sg(qc->sg, sg, qc->n_elem, si) { sge->addr = cpu_to_le64(sg_dma_address(sg)); sge->cnt = cpu_to_le32(sg_dma_len(sg)); sge->flags = 0; @@ -823,8 +824,7 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc, sge++; } - if (likely(last_sge)) - last_sge->flags = cpu_to_le32(SGE_TRM); + last_sge->flags = cpu_to_le32(SGE_TRM); } static int sil24_qc_defer(struct ata_queued_cmd *qc) diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index 3de0c27caf53..211ba8da64f4 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -473,7 +473,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc) void __iomem *mmio = ap->host->iomap[PDC_MMIO_BAR]; void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR]; unsigned int portno = ap->port_no; - unsigned int i, idx, total_len = 0, sgt_len; + unsigned int i, si, idx, total_len = 0, sgt_len; u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ]; WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP)); @@ -487,7 +487,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc) * Build S/G table */ idx = 0; - ata_for_each_sg(sg, qc) { + for_each_sg(qc->sg, sg, qc->n_elem, si) { buf[idx++] = cpu_to_le32(sg_dma_address(sg)); buf[idx++] = cpu_to_le32(sg_dma_len(sg)); total_len += sg_dma_len(sg); diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 3e78bc2d9170..aa0df0a4b22a 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -5142,6 +5142,7 @@ static void ipr_build_ata_ioadl(struct ipr_cmnd *ipr_cmd, struct ipr_ioadl_desc *last_ioadl = NULL; int len = qc->nbytes + qc->pad_len; struct scatterlist *sg; + unsigned int si; if (len == 0) return; @@ -5159,7 +5160,7 @@ static void ipr_build_ata_ioadl(struct ipr_cmnd *ipr_cmd, cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg); } - ata_for_each_sg(sg, qc) { + for_each_sg(qc->sg, sg, qc->n_elem, si) { ioadl->flags_and_data_len = cpu_to_be32(ioadl_flags | sg_dma_len(sg)); ioadl->address = cpu_to_be32(sg_dma_address(sg)); diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index f78d0605747d..827cfb132f21 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -158,8 +158,8 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) struct Scsi_Host *host = sas_ha->core.shost; struct sas_internal *i = to_sas_internal(host->transportt); struct scatterlist *sg; - unsigned int num = 0; unsigned int xfer = 0; + unsigned int si; task = sas_alloc_task(GFP_ATOMIC); if (!task) @@ -181,17 +181,15 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) task->total_xfer_len = qc->nbytes + qc->pad_len; task->num_scatter = qc->pad_len ? qc->n_elem + 1 : qc->n_elem; } else { - ata_for_each_sg(sg, qc) { - num++; + for_each_sg(qc->sg, sg, qc->n_elem, si) xfer += sg->length; - } task->total_xfer_len = xfer; - task->num_scatter = num; + task->num_scatter = si; } task->data_dir = qc->dma_dir; - task->scatter = qc->__sg; + task->scatter = qc->sg; task->ata_task.retry_count = 1; task->task_state_flags = SAS_TASK_STATE_PENDING; qc->lldd_task = task; diff --git a/include/linux/libata.h b/include/linux/libata.h index acd90ad78417..162f8b5509ac 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -458,7 +458,7 @@ struct ata_queued_cmd { unsigned int tag; unsigned int n_elem; unsigned int n_iter; - unsigned int orig_n_elem; + unsigned int mapped_n_elem; int dma_dir; @@ -471,11 +471,12 @@ struct ata_queued_cmd { struct scatterlist *cursg; unsigned int cursg_ofs; + struct scatterlist *last_sg; + struct scatterlist saved_last_sg; struct scatterlist sgent; - struct scatterlist pad_sgent; + struct scatterlist extra_sg[2]; - /* DO NOT iterate over __sg manually, use ata_for_each_sg() */ - struct scatterlist *__sg; + struct scatterlist *sg; unsigned int err_mask; struct ata_taskfile result_tf; @@ -1123,35 +1124,6 @@ extern void ata_port_pbar_desc(struct ata_port *ap, int bar, ssize_t offset, const char *name); #endif -/* - * qc helpers - */ -static inline struct scatterlist * -ata_qc_first_sg(struct ata_queued_cmd *qc) -{ - qc->n_iter = 0; - if (qc->n_elem) - return qc->__sg; - if (qc->pad_len) - return &qc->pad_sgent; - return NULL; -} - -static inline struct scatterlist * -ata_qc_next_sg(struct scatterlist *sg, struct ata_queued_cmd *qc) -{ - if (sg == &qc->pad_sgent) - return NULL; - if (++qc->n_iter < qc->n_elem) - return sg_next(sg); - if (qc->pad_len) - return &qc->pad_sgent; - return NULL; -} - -#define ata_for_each_sg(sg, qc) \ - for (sg = ata_qc_first_sg(qc); sg; sg = ata_qc_next_sg(sg, qc)) - static inline unsigned int ata_tag_valid(unsigned int tag) { return (tag < ATA_MAX_QUEUE) ? 1 : 0; @@ -1386,15 +1358,17 @@ static inline void ata_tf_init(struct ata_device *dev, struct ata_taskfile *tf) static inline void ata_qc_reinit(struct ata_queued_cmd *qc) { qc->dma_dir = DMA_NONE; - qc->__sg = NULL; + qc->sg = NULL; qc->flags = 0; qc->cursg = NULL; qc->cursg_ofs = 0; qc->nbytes = qc->curbytes = 0; qc->n_elem = 0; + qc->mapped_n_elem = 0; qc->n_iter = 0; qc->err_mask = 0; qc->pad_len = 0; + qc->last_sg = NULL; qc->sect_size = ATA_SECT_SIZE; ata_tf_init(qc->dev, &qc->tf); -- cgit v1.2.3 From 0bcc65ad78ae517de16b2ca07a2891f49d44d156 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 5 Dec 2007 16:43:12 +0900 Subject: libata: make qc->nbytes include extra buffers qc->nbytes didn't use to include extra buffers setup by libata core layer and my be odd. This patch makes qc->nbytes include any extra buffers setup by libata core layer and guaranteed to be aligned on 4 byte boundary. This value is to be used to program the host controller. As this represents the actual length of buffer available to the controller and the controller must be able to deal with short transfers for ATAPI commands which can transfer variable length, this shouldn't break any controllers while making problems like rounding-down and controllers choking up on odd transfer bytes much less likely. The unmodified value is stored in new field qc->raw_nbytes. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 14 ++++++++++---- include/linux/libata.h | 3 ++- 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index e998028302da..ee72994500a3 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4763,13 +4763,15 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, } static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc, - unsigned int *n_elem_extra) + unsigned int *n_elem_extra, + unsigned int *nbytes_extra) { struct ata_port *ap = qc->ap; unsigned int n_elem = qc->n_elem; struct scatterlist *lsg, *copy_lsg = NULL, *tsg = NULL, *esg = NULL; *n_elem_extra = 0; + *nbytes_extra = 0; /* needs padding? */ qc->pad_len = qc->nbytes & 3; @@ -4833,6 +4835,7 @@ static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc, esg = &qc->extra_sg[1]; (*n_elem_extra)++; + (*nbytes_extra) += 4 - qc->pad_len; } if (copy_lsg) @@ -4866,11 +4869,11 @@ static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc, static int ata_sg_setup(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - unsigned int n_elem, n_elem_extra; + unsigned int n_elem, n_elem_extra, nbytes_extra; VPRINTK("ENTER, ata%u\n", ap->print_id); - n_elem = ata_sg_setup_extra(qc, &n_elem_extra); + n_elem = ata_sg_setup_extra(qc, &n_elem_extra, &nbytes_extra); if (n_elem) { n_elem = dma_map_sg(ap->dev, qc->sg, n_elem, qc->dma_dir); @@ -4885,7 +4888,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) qc->n_elem = qc->mapped_n_elem = n_elem; qc->n_elem += n_elem_extra; - + qc->nbytes += nbytes_extra; qc->flags |= ATA_QCFLAG_DMAMAP; return 0; @@ -5949,6 +5952,9 @@ void ata_qc_issue(struct ata_queued_cmd *qc) */ BUG_ON(ata_is_data(prot) && (!qc->sg || !qc->n_elem || !qc->nbytes)); + /* ata_sg_setup() may update nbytes */ + qc->raw_nbytes = qc->nbytes; + if (ata_is_dma(prot) || (ata_is_pio(prot) && (ap->flags & ATA_FLAG_PIO_DMA))) if (ata_sg_setup(qc)) diff --git a/include/linux/libata.h b/include/linux/libata.h index 162f8b5509ac..7b7c78e42077 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -466,6 +466,7 @@ struct ata_queued_cmd { unsigned int sect_size; unsigned int nbytes; + unsigned int raw_nbytes; unsigned int curbytes; struct scatterlist *cursg; @@ -1362,7 +1363,7 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) qc->flags = 0; qc->cursg = NULL; qc->cursg_ofs = 0; - qc->nbytes = qc->curbytes = 0; + qc->nbytes = qc->raw_nbytes = qc->curbytes = 0; qc->n_elem = 0; qc->mapped_n_elem = 0; qc->n_iter = 0; -- cgit v1.2.3 From c5038fc05d4aa4ae0671776199459690e4c973cb Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 25 Oct 2007 14:21:16 +0100 Subject: libata/pata_it821x: Improve handling of poorly compatible emulations Some it821x RAID firmwares return 0 for the err return off both devices. A similar issue occurs with the slave returning 0 not 1 if you plug a gigabyte sata ramdisk into a controller that fakes two SATA ports as master/slave on an SFF channel. The patch does the following - Allow the 'failed diagnostics' case on both master and slave - Move the HORKAGE_DIAGNOSTIC check after ->dev_config This second change also allows IT821x to fix up a problem where we report drive diagnostic failures when in fact the drive is fine but the microcontroller firmware doesn't appear to get it right. IT821x clears the flag again to avoid giving the user bogus warnings about their disk. The other IT821x change is a bit ugly, we slightly abuse the cable type hook to fiddle with the identify data for the devices. We could add a new hook for this but as we have only one offender and no more seeming likely it seems better to keep libata-core clean. Please let this sit in -mm briefly, just in case the relaxed checking breaks some other emulated interface. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 36 ++++++++++++++++++++---------------- drivers/ata/pata_it821x.c | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 18 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index ee72994500a3..627703cba9a6 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -950,8 +950,8 @@ unsigned int ata_dev_try_classify(struct ata_device *dev, int present, if (r_err) *r_err = err; - /* see if device passed diags: if master then continue and warn later */ - if (err == 0 && dev->devno == 0) + /* see if device passed diags: continue and warn later */ + if (err == 0) /* diagnostic fail : do nothing _YET_ */ dev->horkage |= ATA_HORKAGE_DIAGNOSTIC; else if (err == 1) @@ -2262,19 +2262,8 @@ int ata_dev_configure(struct ata_device *dev) dev->flags |= ATA_DFLAG_DIPM; } - if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) { - /* Let the user know. We don't want to disallow opens for - rescue purposes, or in case the vendor is just a blithering - idiot */ - if (print_info) { - ata_dev_printk(dev, KERN_WARNING, -"Drive reports diagnostics failure. This may indicate a drive\n"); - ata_dev_printk(dev, KERN_WARNING, -"fault or invalid emulation. Contact drive vendor for information.\n"); - } - } - - /* limit bridge transfers to udma5, 200 sectors */ + /* Limit PATA drive on SATA cable bridge transfers to udma5, + 200 sectors */ if (ata_dev_knobble(dev)) { if (ata_msg_drv(ap) && print_info) ata_dev_printk(dev, KERN_INFO, @@ -2303,6 +2292,21 @@ int ata_dev_configure(struct ata_device *dev) if (ap->ops->dev_config) ap->ops->dev_config(dev); + if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) { + /* Let the user know. We don't want to disallow opens for + rescue purposes, or in case the vendor is just a blithering + idiot. Do this after the dev_config call as some controllers + with buggy firmware may want to avoid reporting false device + bugs */ + + if (print_info) { + ata_dev_printk(dev, KERN_WARNING, +"Drive reports diagnostics failure. This may indicate a drive\n"); + ata_dev_printk(dev, KERN_WARNING, +"fault or invalid emulation. Contact drive vendor for information.\n"); + } + } + if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n", __FUNCTION__, ata_chk_status(ap)); @@ -3066,7 +3070,7 @@ static int ata_dev_set_mode(struct ata_device *dev) /* Early MWDMA devices do DMA but don't allow DMA mode setting. Don't fail an MWDMA0 set IFF the device indicates it is in MWDMA0 */ - if (dev->xfer_shift == ATA_SHIFT_MWDMA && + if (dev->xfer_shift == ATA_SHIFT_MWDMA && dev->dma_mode == XFER_MW_DMA_0 && (dev->id[63] >> 8) & 1) err_mask &= ~AC_ERR_DEV; diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index ca9aae09daed..109ddd42c266 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -430,7 +430,7 @@ static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc) return ata_qc_issue_prot(qc); } printk(KERN_DEBUG "it821x: can't process command 0x%02X\n", qc->tf.command); - return AC_ERR_INVALID; + return AC_ERR_DEV; } /** @@ -516,6 +516,37 @@ static void it821x_dev_config(struct ata_device *adev) printk("(%dK stripe)", adev->id[146]); printk(".\n"); } + /* This is a controller firmware triggered funny, don't + report the drive faulty! */ + adev->horkage &= ~ATA_HORKAGE_DIAGNOSTIC; +} + +/** + * it821x_ident_hack - Hack identify data up + * @ap: Port + * + * Walk the devices on this firmware driven port and slightly + * mash the identify data to stop us and common tools trying to + * use features not firmware supported. The firmware itself does + * some masking (eg SMART) but not enough. + * + * This is a bit of an abuse of the cable method, but it is the + * only method called at the right time. We could modify the libata + * core specifically for ident hacking but while we have one offender + * it seems better to keep the fallout localised. + */ + +static int it821x_ident_hack(struct ata_port *ap) +{ + struct ata_device *adev; + ata_link_for_each_dev(adev, &ap->link) { + if (ata_dev_enabled(adev)) { + adev->id[84] &= ~(1 << 6); /* No FUA */ + adev->id[85] &= ~(1 << 10); /* No HPA */ + adev->id[76] = 0; /* No NCQ/AN etc */ + } + } + return ata_cable_unknown(ap); } @@ -634,7 +665,7 @@ static struct ata_port_operations it821x_smart_port_ops = { .thaw = ata_bmdma_thaw, .error_handler = ata_bmdma_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, - .cable_detect = ata_cable_unknown, + .cable_detect = it821x_ident_hack, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, -- cgit v1.2.3 From 442eacc362c2576aac8ebfd41b99252e28e0f49c Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 19 Dec 2007 04:25:10 -0500 Subject: libata: make ata_port_queue_task() an internal function ata_port_queue_task() served a single user: ata_pio_task() Rename to ata_pio_queue_task() and un-export it, as nobody outside of libata-core.c uses it. Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 24 +++++++++++------------- include/linux/libata.h | 2 -- 2 files changed, 11 insertions(+), 15 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 627703cba9a6..4020a1d3eb2c 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1480,7 +1480,7 @@ unsigned long ata_id_xfermask(const u16 *id) } /** - * ata_port_queue_task - Queue port_task + * ata_pio_queue_task - Queue port_task * @ap: The ata_port to queue port_task for * @fn: workqueue function to be scheduled * @data: data for @fn to use @@ -1492,16 +1492,15 @@ unsigned long ata_id_xfermask(const u16 *id) * one task is active at any given time. * * libata core layer takes care of synchronization between - * port_task and EH. ata_port_queue_task() may be ignored for EH + * port_task and EH. ata_pio_queue_task() may be ignored for EH * synchronization. * * LOCKING: * Inherited from caller. */ -void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data, - unsigned long delay) +static void ata_pio_queue_task(struct ata_port *ap, void *data, + unsigned long delay) { - PREPARE_DELAYED_WORK(&ap->port_task, fn); ap->port_task_data = data; /* may fail if ata_port_flush_task() in progress */ @@ -5618,7 +5617,7 @@ fsm_start: msleep(2); status = ata_busy_wait(ap, ATA_BUSY, 10); if (status & ATA_BUSY) { - ata_port_queue_task(ap, ata_pio_task, qc, ATA_SHORT_PAUSE); + ata_pio_queue_task(ap, qc, ATA_SHORT_PAUSE); return; } } @@ -6041,7 +6040,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) ap->hsm_task_state = HSM_ST_LAST; if (qc->tf.flags & ATA_TFLAG_POLLING) - ata_port_queue_task(ap, ata_pio_task, qc, 0); + ata_pio_queue_task(ap, qc, 0); break; @@ -6063,7 +6062,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) if (qc->tf.flags & ATA_TFLAG_WRITE) { /* PIO data out protocol */ ap->hsm_task_state = HSM_ST_FIRST; - ata_port_queue_task(ap, ata_pio_task, qc, 0); + ata_pio_queue_task(ap, qc, 0); /* always send first data block using * the ata_pio_task() codepath. @@ -6073,7 +6072,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) ap->hsm_task_state = HSM_ST; if (qc->tf.flags & ATA_TFLAG_POLLING) - ata_port_queue_task(ap, ata_pio_task, qc, 0); + ata_pio_queue_task(ap, qc, 0); /* if polling, ata_pio_task() handles the rest. * otherwise, interrupt handler takes over from here. @@ -6094,7 +6093,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) /* send cdb by polling if no cdb interrupt */ if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) || (qc->tf.flags & ATA_TFLAG_POLLING)) - ata_port_queue_task(ap, ata_pio_task, qc, 0); + ata_pio_queue_task(ap, qc, 0); break; case ATAPI_PROT_DMA: @@ -6106,7 +6105,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) /* send cdb by polling if no cdb interrupt */ if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) - ata_port_queue_task(ap, ata_pio_task, qc, 0); + ata_pio_queue_task(ap, qc, 0); break; default: @@ -6722,7 +6721,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host) ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN; #endif - INIT_DELAYED_WORK(&ap->port_task, NULL); + INIT_DELAYED_WORK(&ap->port_task, ata_pio_task); INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug); INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan); INIT_LIST_HEAD(&ap->eh_done_q); @@ -7599,7 +7598,6 @@ EXPORT_SYMBOL_GPL(ata_wait_register); EXPORT_SYMBOL_GPL(ata_busy_sleep); EXPORT_SYMBOL_GPL(ata_wait_after_reset); EXPORT_SYMBOL_GPL(ata_wait_ready); -EXPORT_SYMBOL_GPL(ata_port_queue_task); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); EXPORT_SYMBOL_GPL(ata_scsi_slave_config); diff --git a/include/linux/libata.h b/include/linux/libata.h index 7b7c78e42077..ccb055636f37 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -847,8 +847,6 @@ extern int ata_busy_sleep(struct ata_port *ap, unsigned long timeout_pat, unsigned long timeout); extern void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline); extern int ata_wait_ready(struct ata_port *ap, unsigned long deadline); -extern void ata_port_queue_task(struct ata_port *ap, work_func_t fn, - void *data, unsigned long delay); extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, unsigned long interval_msec, unsigned long timeout_msec); -- cgit v1.2.3 From 4ca4e439640cd1d3659cbcf60e7a73c2ae0450b3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 30 Dec 2007 09:32:22 +0000 Subject: libata annotations and fixes Signed-off-by: Al Viro Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 18 +++++++++--------- drivers/ata/libata-core.c | 2 +- drivers/ata/libata-scsi.c | 4 ++-- drivers/ata/pata_cs5520.c | 2 +- drivers/ata/pata_pdc2027x.c | 2 +- drivers/ata/sata_promise.h | 2 +- drivers/ata/sata_sx4.c | 9 +++++---- include/linux/ata.h | 4 ++-- 8 files changed, 22 insertions(+), 21 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index cffad07c65bf..49761bc12cf2 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -198,18 +198,18 @@ enum { }; struct ahci_cmd_hdr { - u32 opts; - u32 status; - u32 tbl_addr; - u32 tbl_addr_hi; - u32 reserved[4]; + __le32 opts; + __le32 status; + __le32 tbl_addr; + __le32 tbl_addr_hi; + __le32 reserved[4]; }; struct ahci_sg { - u32 addr; - u32 addr_hi; - u32 reserved; - u32 flags_size; + __le32 addr; + __le32 addr_hi; + __le32 reserved; + __le32 flags_size; }; struct ahci_host_priv { diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 4020a1d3eb2c..8c82193b077e 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4949,7 +4949,7 @@ unsigned int ata_data_xfer(struct ata_device *dev, unsigned char *buf, /* Transfer trailing 1 byte, if any. */ if (unlikely(buflen & 0x01)) { - u16 align_buf[1] = { 0 }; + __le16 align_buf[1] = { 0 }; unsigned char *trailing_buf = buf + buflen - 1; if (rw == READ) { diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 42bf61599730..15a4c8a20358 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2210,7 +2210,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, /* sector size */ ATA_SCSI_RBUF_SET(6, ATA_SECT_SIZE >> 8); - ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE); + ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE & 0xff); } else { /* sector count, 64-bit */ ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 7)); @@ -2224,7 +2224,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, /* sector size */ ATA_SCSI_RBUF_SET(10, ATA_SECT_SIZE >> 8); - ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE); + ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE & 0xff); } return 0; diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index 33f7f0843f4f..d4590f546c49 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c @@ -198,7 +198,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi }; const struct ata_port_info *ppi[2]; u8 pcicfg; - void *iomap[5]; + void __iomem *iomap[5]; struct ata_host *host; struct ata_ioports *ioaddr; int i, rc; diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index 2622577521a1..028af5dbeed6 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c @@ -348,7 +348,7 @@ static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long ata_id_c_string(pair->id, model_num, ATA_ID_PROD, ATA_ID_PROD_LEN + 1); /* If the master is a maxtor in UDMA6 then the slave should not use UDMA 6 */ - if (strstr(model_num, "Maxtor") == 0 && pair->dma_mode == XFER_UDMA_6) + if (strstr(model_num, "Maxtor") == NULL && pair->dma_mode == XFER_UDMA_6) mask &= ~ (1 << (6 + ATA_SHIFT_UDMA)); return ata_pci_default_filter(adev, mask); diff --git a/drivers/ata/sata_promise.h b/drivers/ata/sata_promise.h index 6ee5e190262d..00d6000e546f 100644 --- a/drivers/ata/sata_promise.h +++ b/drivers/ata/sata_promise.h @@ -46,7 +46,7 @@ static inline unsigned int pdc_pkt_header(struct ata_taskfile *tf, unsigned int devno, u8 *buf) { u8 dev_reg; - u32 *buf32 = (u32 *) buf; + __le32 *buf32 = (__le32 *) buf; /* set control bits (byte 0), zero delay seq id (byte 3), * and seq id (byte 2) diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index 211ba8da64f4..e3d56bc6726d 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -334,7 +334,7 @@ static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf, { u32 addr; unsigned int dw = PDC_DIMM_APKT_PRD >> 2; - u32 *buf32 = (u32 *) buf; + __le32 *buf32 = (__le32 *) buf; /* output ATA packet S/G table */ addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA + @@ -356,7 +356,7 @@ static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf, { u32 addr; unsigned int dw = PDC_DIMM_HPKT_PRD >> 2; - u32 *buf32 = (u32 *) buf; + __le32 *buf32 = (__le32 *) buf; /* output Host DMA packet S/G table */ addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA + @@ -377,7 +377,7 @@ static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf, unsigned int portno) { unsigned int i, dw; - u32 *buf32 = (u32 *) buf; + __le32 *buf32 = (__le32 *) buf; u8 dev_reg; unsigned int dimm_sg = PDC_20621_DIMM_BASE + @@ -429,7 +429,8 @@ static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf, unsigned int portno) { unsigned int dw; - u32 tmp, *buf32 = (u32 *) buf; + u32 tmp; + __le32 *buf32 = (__le32 *) buf; unsigned int host_sg = PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * portno) + diff --git a/include/linux/ata.h b/include/linux/ata.h index bc55471a4b2c..78bbacaed8c4 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -354,8 +354,8 @@ enum ata_ioctls { /* core structures */ struct ata_prd { - u32 addr; - u32 flags_len; + __le32 addr; + __le32 flags_len; }; struct ata_taskfile { -- cgit v1.2.3 From 4e6b79fa61091a0ed9b0af0f573cc257772cd88d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 18 Jan 2008 18:36:28 +0900 Subject: libata: factor out ata_pci_activate_sff_host() from ata_pci_one() Factor out ata_pci_activate_sff_host() from ata_pci_one(). This does about the same thing as ata_host_activate() but needs to be separate because SFF controllers use different and multiple IRQs in legacy mode. This will be used to make SFF LLD initialization more flexible. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 1 + drivers/ata/libata-sff.c | 187 +++++++++++++++++++++++++--------------------- include/linux/libata.h | 3 + 3 files changed, 107 insertions(+), 84 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 8c82193b077e..ce803d18e96a 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -7629,6 +7629,7 @@ EXPORT_SYMBOL_GPL(pci_test_config_bits); EXPORT_SYMBOL_GPL(ata_pci_init_sff_host); EXPORT_SYMBOL_GPL(ata_pci_init_bmdma); EXPORT_SYMBOL_GPL(ata_pci_prepare_sff_host); +EXPORT_SYMBOL_GPL(ata_pci_activate_sff_host); EXPORT_SYMBOL_GPL(ata_pci_init_one); EXPORT_SYMBOL_GPL(ata_pci_remove_one); #ifdef CONFIG_PM diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 97dd8f2796b7..60cd4b179766 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -713,6 +713,99 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev, return rc; } +/** + * ata_pci_activate_sff_host - start SFF host, request IRQ and register it + * @host: target SFF ATA host + * @irq_handler: irq_handler used when requesting IRQ(s) + * @sht: scsi_host_template to use when registering the host + * + * This is the counterpart of ata_host_activate() for SFF ATA + * hosts. This separate helper is necessary because SFF hosts + * use two separate interrupts in legacy mode. + * + * LOCKING: + * Inherited from calling layer (may sleep). + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +int ata_pci_activate_sff_host(struct ata_host *host, + irq_handler_t irq_handler, + struct scsi_host_template *sht) +{ + struct device *dev = host->dev; + struct pci_dev *pdev = to_pci_dev(dev); + const char *drv_name = dev_driver_string(host->dev); + int legacy_mode = 0, rc; + + rc = ata_host_start(host); + if (rc) + return rc; + + if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) { + u8 tmp8, mask; + + /* TODO: What if one channel is in native mode ... */ + pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8); + mask = (1 << 2) | (1 << 0); + if ((tmp8 & mask) != mask) + legacy_mode = 1; +#if defined(CONFIG_NO_ATA_LEGACY) + /* Some platforms with PCI limits cannot address compat + port space. In that case we punt if their firmware has + left a device in compatibility mode */ + if (legacy_mode) { + printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n"); + return -EOPNOTSUPP; + } +#endif + } + + if (!devres_open_group(dev, NULL, GFP_KERNEL)) + return -ENOMEM; + + if (!legacy_mode && pdev->irq) { + rc = devm_request_irq(dev, pdev->irq, irq_handler, + IRQF_SHARED, drv_name, host); + if (rc) + goto out; + + ata_port_desc(host->ports[0], "irq %d", pdev->irq); + ata_port_desc(host->ports[1], "irq %d", pdev->irq); + } else if (legacy_mode) { + if (!ata_port_is_dummy(host->ports[0])) { + rc = devm_request_irq(dev, ATA_PRIMARY_IRQ(pdev), + irq_handler, IRQF_SHARED, + drv_name, host); + if (rc) + goto out; + + ata_port_desc(host->ports[0], "irq %d", + ATA_PRIMARY_IRQ(pdev)); + } + + if (!ata_port_is_dummy(host->ports[1])) { + rc = devm_request_irq(dev, ATA_SECONDARY_IRQ(pdev), + irq_handler, IRQF_SHARED, + drv_name, host); + if (rc) + goto out; + + ata_port_desc(host->ports[1], "irq %d", + ATA_SECONDARY_IRQ(pdev)); + } + } + + rc = ata_host_register(host, sht); + out: + if (rc == 0) + devres_remove_group(dev, NULL); + else + devres_release_group(dev, NULL); + + return rc; +} + /** * ata_pci_init_one - Initialize/register PCI IDE host controller * @pdev: Controller to be initialized @@ -742,9 +835,6 @@ int ata_pci_init_one(struct pci_dev *pdev, struct device *dev = &pdev->dev; const struct ata_port_info *pi = NULL; struct ata_host *host = NULL; - const char *drv_name = dev_driver_string(&pdev->dev); - u8 mask; - int legacy_mode = 0; int i, rc; DPRINTK("ENTER\n"); @@ -766,95 +856,24 @@ int ata_pci_init_one(struct pci_dev *pdev, if (!devres_open_group(dev, NULL, GFP_KERNEL)) return -ENOMEM; - /* FIXME: Really for ATA it isn't safe because the device may be - multi-purpose and we want to leave it alone if it was already - enabled. Secondly for shared use as Arjan says we want refcounting - - Checking dev->is_enabled is insufficient as this is not set at - boot for the primary video which is BIOS enabled - */ - rc = pcim_enable_device(pdev); if (rc) - goto err_out; + goto out; - if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) { - u8 tmp8; - - /* TODO: What if one channel is in native mode ... */ - pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8); - mask = (1 << 2) | (1 << 0); - if ((tmp8 & mask) != mask) - legacy_mode = 1; -#if defined(CONFIG_NO_ATA_LEGACY) - /* Some platforms with PCI limits cannot address compat - port space. In that case we punt if their firmware has - left a device in compatibility mode */ - if (legacy_mode) { - printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n"); - rc = -EOPNOTSUPP; - goto err_out; - } -#endif - } - - /* prepare host */ + /* prepare and activate SFF host */ rc = ata_pci_prepare_sff_host(pdev, ppi, &host); if (rc) - goto err_out; + goto out; pci_set_master(pdev); + rc = ata_pci_activate_sff_host(host, pi->port_ops->irq_handler, + pi->sht); + out: + if (rc == 0) + devres_remove_group(&pdev->dev, NULL); + else + devres_release_group(&pdev->dev, NULL); - /* start host and request IRQ */ - rc = ata_host_start(host); - if (rc) - goto err_out; - - if (!legacy_mode && pdev->irq) { - /* We may have no IRQ assigned in which case we can poll. This - shouldn't happen on a sane system but robustness is cheap - in this case */ - rc = devm_request_irq(dev, pdev->irq, pi->port_ops->irq_handler, - IRQF_SHARED, drv_name, host); - if (rc) - goto err_out; - - ata_port_desc(host->ports[0], "irq %d", pdev->irq); - ata_port_desc(host->ports[1], "irq %d", pdev->irq); - } else if (legacy_mode) { - if (!ata_port_is_dummy(host->ports[0])) { - rc = devm_request_irq(dev, ATA_PRIMARY_IRQ(pdev), - pi->port_ops->irq_handler, - IRQF_SHARED, drv_name, host); - if (rc) - goto err_out; - - ata_port_desc(host->ports[0], "irq %d", - ATA_PRIMARY_IRQ(pdev)); - } - - if (!ata_port_is_dummy(host->ports[1])) { - rc = devm_request_irq(dev, ATA_SECONDARY_IRQ(pdev), - pi->port_ops->irq_handler, - IRQF_SHARED, drv_name, host); - if (rc) - goto err_out; - - ata_port_desc(host->ports[1], "irq %d", - ATA_SECONDARY_IRQ(pdev)); - } - } - - /* register */ - rc = ata_host_register(host, pi->sht); - if (rc) - goto err_out; - - devres_remove_group(dev, NULL); - return 0; - -err_out: - devres_release_group(dev, NULL); return rc; } diff --git a/include/linux/libata.h b/include/linux/libata.h index ccb055636f37..4374c4277780 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1033,6 +1033,9 @@ extern int ata_pci_init_bmdma(struct ata_host *host); extern int ata_pci_prepare_sff_host(struct pci_dev *pdev, const struct ata_port_info * const * ppi, struct ata_host **r_host); +extern int ata_pci_activate_sff_host(struct ata_host *host, + irq_handler_t irq_handler, + struct scsi_host_template *sht); extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits); extern unsigned long ata_pci_default_filter(struct ata_device *dev, unsigned long xfer_mask); -- cgit v1.2.3 From 0affa456cb6da51a31a6dd76b3d8827f467f807d Mon Sep 17 00:00:00 2001 From: Linus Nilsson Date: Mon, 28 Jan 2008 15:56:27 +0100 Subject: libata: Change "write_data" to "rw" for some function documentations The documentation for ata_data_xfer and ata_data_xfer_noirq had the 'rw' parameter named 'write_data'. Signed-off-by: Linus Nilsson Signed-off-by: Linus Torvalds --- drivers/ata/libata-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/ata/libata-core.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index ce803d18e96a..bdbd55af7022 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4924,7 +4924,7 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) * @dev: device to target * @buf: data buffer * @buflen: buffer length - * @write_data: read/write + * @rw: read/write * * Transfer data from/to the device data register by PIO. * @@ -4970,7 +4970,7 @@ unsigned int ata_data_xfer(struct ata_device *dev, unsigned char *buf, * @dev: device to target * @buf: data buffer * @buflen: buffer length - * @write_data: read/write + * @rw: read/write * * Transfer data from/to the device data register by PIO. Do the * transfer with interrupts disabled. -- cgit v1.2.3