diff options
Diffstat (limited to 'drivers/ata')
34 files changed, 697 insertions, 847 deletions
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index ae41107afc1f..b67e995179a9 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -111,7 +111,8 @@ obj-$(CONFIG_ATA_GENERIC) += ata_generic.o # Should be last libata driver obj-$(CONFIG_PATA_LEGACY) += pata_legacy.o -libata-y := libata-core.o libata-scsi.o libata-eh.o libata-transport.o +libata-y := libata-core.o libata-scsi.o libata-eh.o \ + libata-transport.o libata-trace.o libata-$(CONFIG_ATA_SFF) += libata-sff.o libata-$(CONFIG_SATA_PMP) += libata-pmp.o libata-$(CONFIG_ATA_ACPI) += libata-acpi.o diff --git a/drivers/ata/acard-ahci.c b/drivers/ata/acard-ahci.c index c962886d7e71..12489ce863c4 100644 --- a/drivers/ata/acard-ahci.c +++ b/drivers/ata/acard-ahci.c @@ -181,10 +181,10 @@ static int acard_ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) int rc; if (using_dac && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); if (rc) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "64-bit DMA enable failed\n"); @@ -192,12 +192,12 @@ static int acard_ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) } } } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit DMA enable failed\n"); return rc; } - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n"); diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 33bb06e006c9..c7a92a743ed0 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -738,10 +738,10 @@ static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) return 0; if (using_dac && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); if (rc) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "64-bit DMA enable failed\n"); @@ -749,12 +749,12 @@ static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) } } } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit DMA enable failed\n"); return rc; } - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n"); diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c index bc971af262e7..ea0ff005b86c 100644 --- a/drivers/ata/ahci_st.c +++ b/drivers/ata/ahci_st.c @@ -68,8 +68,6 @@ static int st_ahci_deassert_resets(struct device *dev) } } - st_ahci_configure_oob(drv_data->hpriv->mmio); - if (drv_data->sw_rst) { err = reset_control_deassert(drv_data->sw_rst); if (err) { @@ -172,6 +170,8 @@ static int st_ahci_probe(struct platform_device *pdev) if (err) return err; + st_ahci_configure_oob(drv_data->hpriv->mmio); + err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info, &ahci_platform_sht); if (err) { @@ -222,6 +222,8 @@ static int st_ahci_resume(struct device *dev) return err; } + st_ahci_configure_oob(drv_data->hpriv->mmio); + return ahci_platform_resume_host(dev); } #endif diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c index 2e8bb603e447..2b78510d94dd 100644 --- a/drivers/ata/ahci_xgene.c +++ b/drivers/ata/ahci_xgene.c @@ -22,6 +22,7 @@ * NOTE: PM support is not currently available. * */ +#include <linux/acpi.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/ahci_platform.h> @@ -718,6 +719,14 @@ disable_resources: return rc; } +#ifdef CONFIG_ACPI +static const struct acpi_device_id xgene_ahci_acpi_match[] = { + { "APMC0D0D", }, + { } +}; +MODULE_DEVICE_TABLE(acpi, xgene_ahci_acpi_match); +#endif + static const struct of_device_id xgene_ahci_of_match[] = { {.compatible = "apm,xgene-ahci"}, {}, @@ -730,6 +739,7 @@ static struct platform_driver xgene_ahci_driver = { .driver = { .name = DRV_NAME, .of_match_table = xgene_ahci_of_match, + .acpi_match_table = ACPI_PTR(xgene_ahci_acpi_match), }, }; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 4c35f0822d06..f6cb1f1b30b7 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -70,6 +70,9 @@ #include <linux/pm_runtime.h> #include <linux/platform_device.h> +#define CREATE_TRACE_POINTS +#include <trace/events/libata.h> + #include "libata.h" #include "libata-transport.h" @@ -691,11 +694,11 @@ static int ata_rwcmd_protocol(struct ata_taskfile *tf, struct ata_device *dev) * RETURNS: * Block address read from @tf. */ -u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev) +u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev) { u64 block = 0; - if (tf->flags & ATA_TFLAG_LBA) { + if (!dev || tf->flags & ATA_TFLAG_LBA) { if (tf->flags & ATA_TFLAG_LBA48) { block |= (u64)tf->hob_lbah << 40; block |= (u64)tf->hob_lbam << 32; @@ -2144,6 +2147,24 @@ static int ata_dev_config_ncq(struct ata_device *dev, return 0; } +static void ata_dev_config_sense_reporting(struct ata_device *dev) +{ + unsigned int err_mask; + + if (!ata_id_has_sense_reporting(dev->id)) + return; + + if (ata_id_sense_reporting_enabled(dev->id)) + return; + + err_mask = ata_dev_set_feature(dev, SETFEATURE_SENSE_DATA, 0x1); + if (err_mask) { + ata_dev_dbg(dev, + "failed to enable Sense Data Reporting, Emask 0x%x\n", + err_mask); + } +} + /** * ata_dev_configure - Configure the specified ATA/ATAPI device * @dev: Target device to configure @@ -2366,7 +2387,7 @@ int ata_dev_configure(struct ata_device *dev) dev->devslp_timing[i] = sata_setting[j]; } } - + ata_dev_config_sense_reporting(dev); dev->cdb_len = 16; } @@ -4204,9 +4225,18 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "PIONEER DVD-RW DVR-216D", NULL, ATA_HORKAGE_NOSETXFER }, /* devices that don't properly handle queued TRIM commands */ - { "Micron_M[56]*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | + { "Micron_M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | + ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "Crucial_CT*M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | + ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "Micron_M5[15]0*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | + ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "Crucial_CT*M550*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | + ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "Crucial_CT*MX100*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | + ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "Samsung SSD 850 PRO*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | ATA_HORKAGE_ZERO_AFTER_TRIM, }, - { "Crucial_CT*SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, /* * As defined, the DRAT (Deterministic Read After Trim) and RZAT @@ -4226,6 +4256,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { */ { "INTEL*SSDSC2MH*", NULL, 0, }, + { "Micron*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, }, + { "Crucial*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, }, { "INTEL*SSD*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, }, { "SSD*INTEL*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, }, { "Samsung*SSD*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, }, @@ -4737,7 +4769,7 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag) return NULL; /* libsas case */ - if (!ap->scsi_host) { + if (ap->flags & ATA_FLAG_SAS_HOST) { tag = ata_sas_allocate_tag(ap); if (tag < 0) return NULL; @@ -4776,7 +4808,7 @@ void ata_qc_free(struct ata_queued_cmd *qc) tag = qc->tag; if (likely(ata_tag_valid(tag))) { qc->tag = ATA_TAG_POISON; - if (!ap->scsi_host) + if (ap->flags & ATA_FLAG_SAS_HOST) ata_sas_free_tag(tag, ap); } } @@ -4886,6 +4918,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) */ if (unlikely(ata_tag_internal(qc->tag))) { fill_result_tf(qc); + trace_ata_qc_complete_internal(qc); __ata_qc_complete(qc); return; } @@ -4896,6 +4929,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) */ if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { fill_result_tf(qc); + trace_ata_qc_complete_failed(qc); ata_qc_schedule_eh(qc); return; } @@ -4906,6 +4940,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) if (qc->flags & ATA_QCFLAG_RESULT_TF) fill_result_tf(qc); + trace_ata_qc_complete_done(qc); /* Some commands need post-processing after successful * completion. */ @@ -5053,7 +5088,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc) } ap->ops->qc_prep(qc); - + trace_ata_qc_issue(qc); qc->err_mask |= ap->ops->qc_issue(qc); if (unlikely(qc->err_mask)) goto err; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index d2029a462e2c..07f41be38fbe 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -46,6 +46,7 @@ #include <linux/libata.h> +#include <trace/events/libata.h> #include "libata.h" enum { @@ -1510,13 +1511,18 @@ unsigned int ata_read_log_page(struct ata_device *dev, u8 log, DPRINTK("read log page - log 0x%x, page 0x%x\n", log, page); ata_tf_init(dev, &tf); - tf.command = ATA_CMD_READ_LOG_EXT; + if (dev->dma_mode && ata_id_has_read_log_dma_ext(dev->id)) { + tf.command = ATA_CMD_READ_LOG_DMA_EXT; + tf.protocol = ATA_PROT_DMA; + } else { + tf.command = ATA_CMD_READ_LOG_EXT; + tf.protocol = ATA_PROT_PIO; + } tf.lbal = log; tf.lbam = page; tf.nsect = sectors; tf.hob_nsect = sectors >> 8; tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE; - tf.protocol = ATA_PROT_PIO; err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE, buf, sectors * ATA_SECT_SIZE, 0); @@ -1575,6 +1581,8 @@ static int ata_eh_read_log_10h(struct ata_device *dev, tf->hob_lbah = buf[10]; tf->nsect = buf[12]; tf->hob_nsect = buf[13]; + if (ata_id_has_ncq_autosense(dev->id)) + tf->auxiliary = buf[14] << 16 | buf[15] << 8 | buf[16]; return 0; } @@ -1611,6 +1619,70 @@ unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key) } /** + * ata_eh_request_sense - perform REQUEST_SENSE_DATA_EXT + * @dev: device to perform REQUEST_SENSE_SENSE_DATA_EXT to + * @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long) + * @dfl_sense_key: default sense key to use + * + * Perform REQUEST_SENSE_DATA_EXT after the device reported CHECK + * SENSE. This function is EH helper. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * encoded sense data on success, 0 on failure or if sense data + * is not available. + */ +static u32 ata_eh_request_sense(struct ata_queued_cmd *qc, + struct scsi_cmnd *cmd) +{ + struct ata_device *dev = qc->dev; + struct ata_taskfile tf; + unsigned int err_mask; + + if (!cmd) + return 0; + + DPRINTK("ATA request sense\n"); + ata_dev_warn(dev, "request sense\n"); + if (!ata_id_sense_reporting_enabled(dev->id)) { + ata_dev_warn(qc->dev, "sense data reporting disabled\n"); + return 0; + } + ata_tf_init(dev, &tf); + + tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48; + tf.command = ATA_CMD_REQ_SENSE_DATA; + tf.protocol = ATA_PROT_NODATA; + + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); + /* + * ACS-4 states: + * The device may set the SENSE DATA AVAILABLE bit to one in the + * STATUS field and clear the ERROR bit to zero in the STATUS field + * to indicate that the command returned completion without an error + * and the sense data described in table 306 is available. + * + * IOW the 'ATA_SENSE' bit might not be set even though valid + * sense data is available. + * So check for both. + */ + if ((tf.command & ATA_SENSE) || + tf.lbah != 0 || tf.lbam != 0 || tf.lbal != 0) { + ata_scsi_set_sense(cmd, tf.lbah, tf.lbam, tf.lbal); + qc->flags |= ATA_QCFLAG_SENSE_VALID; + ata_dev_warn(dev, "sense data %02x/%02x/%02x\n", + tf.lbah, tf.lbam, tf.lbal); + } else { + ata_dev_warn(dev, "request sense failed stat %02x emask %x\n", + tf.command, err_mask); + } + return err_mask; +} + +/** * atapi_eh_request_sense - perform ATAPI REQUEST_SENSE * @dev: device to perform REQUEST_SENSE to * @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long) @@ -1772,6 +1844,19 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) memcpy(&qc->result_tf, &tf, sizeof(tf)); qc->result_tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_LBA | ATA_TFLAG_LBA48; qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ; + if (qc->result_tf.auxiliary) { + char sense_key, asc, ascq; + + sense_key = (qc->result_tf.auxiliary >> 16) & 0xff; + asc = (qc->result_tf.auxiliary >> 8) & 0xff; + ascq = qc->result_tf.auxiliary & 0xff; + ata_dev_dbg(dev, "NCQ Autosense %02x/%02x/%02x\n", + sense_key, asc, ascq); + ata_scsi_set_sense(qc->scsicmd, sense_key, asc, ascq); + ata_scsi_set_sense_information(qc->scsicmd, &qc->result_tf); + qc->flags |= ATA_QCFLAG_SENSE_VALID; + } + ehc->i.err_mask &= ~AC_ERR_DEV; } @@ -1801,6 +1886,27 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, return ATA_EH_RESET; } + /* + * Sense data reporting does not work if the + * device fault bit is set. + */ + if ((stat & ATA_SENSE) && !(stat & ATA_DF) && + !(qc->flags & ATA_QCFLAG_SENSE_VALID)) { + if (!(qc->ap->pflags & ATA_PFLAG_FROZEN)) { + tmp = ata_eh_request_sense(qc, qc->scsicmd); + if (tmp) + qc->err_mask |= tmp; + else + ata_scsi_set_sense_information(qc->scsicmd, tf); + } else { + ata_dev_warn(qc->dev, "sense data available but port frozen\n"); + } + } + + /* Set by NCQ autosense or request sense above */ + if (qc->flags & ATA_QCFLAG_SENSE_VALID) + return 0; + if (stat & (ATA_ERR | ATA_DF)) qc->err_mask |= AC_ERR_DEV; else @@ -2186,6 +2292,7 @@ static void ata_eh_link_autopsy(struct ata_link *link) all_err_mask |= qc->err_mask; if (qc->flags & ATA_QCFLAG_IO) eflags |= ATA_EFLAG_IS_IO; + trace_ata_eh_link_autopsy_qc(qc); } /* enforce default EH actions */ @@ -2220,7 +2327,7 @@ static void ata_eh_link_autopsy(struct ata_link *link) eflags |= ATA_EFLAG_DUBIOUS_XFER; ehc->i.action |= ata_eh_speed_down(dev, eflags, all_err_mask); } - + trace_ata_eh_link_autopsy(dev, ehc->i.action, all_err_mask); DPRINTK("EXIT\n"); } @@ -2289,27 +2396,27 @@ const char *ata_get_cmd_descript(u8 command) const char *text; } cmd_descr[] = { { ATA_CMD_DEV_RESET, "DEVICE RESET" }, - { ATA_CMD_CHK_POWER, "CHECK POWER MODE" }, - { ATA_CMD_STANDBY, "STANDBY" }, - { ATA_CMD_IDLE, "IDLE" }, - { ATA_CMD_EDD, "EXECUTE DEVICE DIAGNOSTIC" }, - { ATA_CMD_DOWNLOAD_MICRO, "DOWNLOAD MICROCODE" }, + { ATA_CMD_CHK_POWER, "CHECK POWER MODE" }, + { ATA_CMD_STANDBY, "STANDBY" }, + { ATA_CMD_IDLE, "IDLE" }, + { ATA_CMD_EDD, "EXECUTE DEVICE DIAGNOSTIC" }, + { ATA_CMD_DOWNLOAD_MICRO, "DOWNLOAD MICROCODE" }, { ATA_CMD_DOWNLOAD_MICRO_DMA, "DOWNLOAD MICROCODE DMA" }, { ATA_CMD_NOP, "NOP" }, - { ATA_CMD_FLUSH, "FLUSH CACHE" }, - { ATA_CMD_FLUSH_EXT, "FLUSH CACHE EXT" }, - { ATA_CMD_ID_ATA, "IDENTIFY DEVICE" }, - { ATA_CMD_ID_ATAPI, "IDENTIFY PACKET DEVICE" }, - { ATA_CMD_SERVICE, "SERVICE" }, - { ATA_CMD_READ, "READ DMA" }, - { ATA_CMD_READ_EXT, "READ DMA EXT" }, - { ATA_CMD_READ_QUEUED, "READ DMA QUEUED" }, - { ATA_CMD_READ_STREAM_EXT, "READ STREAM EXT" }, + { ATA_CMD_FLUSH, "FLUSH CACHE" }, + { ATA_CMD_FLUSH_EXT, "FLUSH CACHE EXT" }, + { ATA_CMD_ID_ATA, "IDENTIFY DEVICE" }, + { ATA_CMD_ID_ATAPI, "IDENTIFY PACKET DEVICE" }, + { ATA_CMD_SERVICE, "SERVICE" }, + { ATA_CMD_READ, "READ DMA" }, + { ATA_CMD_READ_EXT, "READ DMA EXT" }, + { ATA_CMD_READ_QUEUED, "READ DMA QUEUED" }, + { ATA_CMD_READ_STREAM_EXT, "READ STREAM EXT" }, { ATA_CMD_READ_STREAM_DMA_EXT, "READ STREAM DMA EXT" }, - { ATA_CMD_WRITE, "WRITE DMA" }, - { ATA_CMD_WRITE_EXT, "WRITE DMA EXT" }, - { ATA_CMD_WRITE_QUEUED, "WRITE DMA QUEUED EXT" }, - { ATA_CMD_WRITE_STREAM_EXT, "WRITE STREAM EXT" }, + { ATA_CMD_WRITE, "WRITE DMA" }, + { ATA_CMD_WRITE_EXT, "WRITE DMA EXT" }, + { ATA_CMD_WRITE_QUEUED, "WRITE DMA QUEUED EXT" }, + { ATA_CMD_WRITE_STREAM_EXT, "WRITE STREAM EXT" }, { ATA_CMD_WRITE_STREAM_DMA_EXT, "WRITE STREAM DMA EXT" }, { ATA_CMD_WRITE_FUA_EXT, "WRITE DMA FUA EXT" }, { ATA_CMD_WRITE_QUEUED_FUA_EXT, "WRITE DMA QUEUED FUA EXT" }, @@ -2325,7 +2432,7 @@ const char *ata_get_cmd_descript(u8 command) { ATA_CMD_READ_MULTI_EXT, "READ MULTIPLE EXT" }, { ATA_CMD_WRITE_MULTI, "WRITE MULTIPLE" }, { ATA_CMD_WRITE_MULTI_EXT, "WRITE MULTIPLE EXT" }, - { ATA_CMD_WRITE_MULTI_FUA_EXT, "WRITE MULTIPLE FUA EXT" }, + { ATA_CMD_WRITE_MULTI_FUA_EXT, "WRITE MULTIPLE FUA EXT" }, { ATA_CMD_SET_FEATURES, "SET FEATURES" }, { ATA_CMD_SET_MULTI, "SET MULTIPLE MODE" }, { ATA_CMD_VERIFY, "READ VERIFY SECTOR(S)" }, @@ -2342,12 +2449,12 @@ const char *ata_get_cmd_descript(u8 command) { ATA_CMD_READ_LOG_EXT, "READ LOG EXT" }, { ATA_CMD_WRITE_LOG_EXT, "WRITE LOG EXT" }, { ATA_CMD_READ_LOG_DMA_EXT, "READ LOG DMA EXT" }, - { ATA_CMD_WRITE_LOG_DMA_EXT, "WRITE LOG DMA EXT" }, + { ATA_CMD_WRITE_LOG_DMA_EXT, "WRITE LOG DMA EXT" }, { ATA_CMD_TRUSTED_NONDATA, "TRUSTED NON-DATA" }, { ATA_CMD_TRUSTED_RCV, "TRUSTED RECEIVE" }, - { ATA_CMD_TRUSTED_RCV_DMA, "TRUSTED RECEIVE DMA" }, + { ATA_CMD_TRUSTED_RCV_DMA, "TRUSTED RECEIVE DMA" }, { ATA_CMD_TRUSTED_SND, "TRUSTED SEND" }, - { ATA_CMD_TRUSTED_SND_DMA, "TRUSTED SEND DMA" }, + { ATA_CMD_TRUSTED_SND_DMA, "TRUSTED SEND DMA" }, { ATA_CMD_PMP_READ, "READ BUFFER" }, { ATA_CMD_PMP_READ_DMA, "READ BUFFER DMA" }, { ATA_CMD_PMP_WRITE, "WRITE BUFFER" }, @@ -2364,12 +2471,12 @@ const char *ata_get_cmd_descript(u8 command) { ATA_CMD_MEDIA_LOCK, "DOOR LOCK" }, { ATA_CMD_MEDIA_UNLOCK, "DOOR UNLOCK" }, { ATA_CMD_DSM, "DATA SET MANAGEMENT" }, - { ATA_CMD_CHK_MED_CRD_TYP, "CHECK MEDIA CARD TYPE" }, - { ATA_CMD_CFA_REQ_EXT_ERR, "CFA REQUEST EXTENDED ERROR" }, + { ATA_CMD_CHK_MED_CRD_TYP, "CHECK MEDIA CARD TYPE" }, + { ATA_CMD_CFA_REQ_EXT_ERR, "CFA REQUEST EXTENDED ERROR" }, { ATA_CMD_CFA_WRITE_NE, "CFA WRITE SECTORS WITHOUT ERASE" }, { ATA_CMD_CFA_TRANS_SECT, "CFA TRANSLATE SECTOR" }, { ATA_CMD_CFA_ERASE, "CFA ERASE SECTORS" }, - { ATA_CMD_CFA_WRITE_MULT_NE, "CFA WRITE MULTIPLE WITHOUT ERASE" }, + { ATA_CMD_CFA_WRITE_MULT_NE, "CFA WRITE MULTIPLE WITHOUT ERASE" }, { ATA_CMD_REQ_SENSE_DATA, "REQUEST SENSE DATA EXT" }, { ATA_CMD_SANITIZE_DEVICE, "SANITIZE DEVICE" }, { ATA_CMD_READ_LONG, "READ LONG (with retries)" }, @@ -2543,14 +2650,15 @@ static void ata_eh_link_report(struct ata_link *link) #ifdef CONFIG_ATA_VERBOSE_ERROR if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | - ATA_ERR)) { + ATA_SENSE | ATA_ERR)) { if (res->command & ATA_BUSY) ata_dev_err(qc->dev, "status: { Busy }\n"); else - ata_dev_err(qc->dev, "status: { %s%s%s%s}\n", + ata_dev_err(qc->dev, "status: { %s%s%s%s%s}\n", res->command & ATA_DRDY ? "DRDY " : "", res->command & ATA_DF ? "DF " : "", res->command & ATA_DRQ ? "DRQ " : "", + res->command & ATA_SENSE ? "SENSE " : "", res->command & ATA_ERR ? "ERR " : ""); } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index b061ba2c31d8..3131adcc1f87 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -270,13 +270,28 @@ DEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR, ata_scsi_park_show, ata_scsi_park_store); EXPORT_SYMBOL_GPL(dev_attr_unload_heads); -static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq) +void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq) { + if (!cmd) + return; + cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq); } +void ata_scsi_set_sense_information(struct scsi_cmnd *cmd, + const struct ata_taskfile *tf) +{ + u64 information; + + if (!cmd) + return; + + information = ata_tf_read_block(tf, NULL); + scsi_set_sense_information(cmd->sense_buffer, information); +} + static ssize_t ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -799,26 +814,27 @@ static void ata_dump_status(unsigned id, struct ata_taskfile *tf) if (stat & ATA_BUSY) { printk("Busy }\n"); /* Data is not valid in this case */ } else { - if (stat & 0x40) printk("DriveReady "); - if (stat & 0x20) printk("DeviceFault "); - if (stat & 0x10) printk("SeekComplete "); - if (stat & 0x08) printk("DataRequest "); - if (stat & 0x04) printk("CorrectedError "); - if (stat & 0x02) printk("Index "); - if (stat & 0x01) printk("Error "); + if (stat & ATA_DRDY) printk("DriveReady "); + if (stat & ATA_DF) printk("DeviceFault "); + if (stat & ATA_DSC) printk("SeekComplete "); + if (stat & ATA_DRQ) printk("DataRequest "); + if (stat & ATA_CORR) printk("CorrectedError "); + if (stat & ATA_SENSE) printk("Sense "); + if (stat & ATA_ERR) printk("Error "); printk("}\n"); if (err) { printk(KERN_WARNING "ata%u: error=0x%02x { ", id, err); - if (err & 0x04) printk("DriveStatusError "); - if (err & 0x80) { - if (err & 0x04) printk("BadCRC "); + if (err & ATA_ABORTED) printk("DriveStatusError "); + if (err & ATA_ICRC) { + if (err & ATA_ABORTED) + printk("BadCRC "); else printk("Sector "); } - if (err & 0x40) printk("UncorrectableError "); - if (err & 0x10) printk("SectorIdNotFound "); - if (err & 0x02) printk("TrackZeroNotFound "); - if (err & 0x01) printk("AddrMarkNotFound "); + if (err & ATA_UNC) printk("UncorrectableError "); + if (err & ATA_IDNF) printk("SectorIdNotFound "); + if (err & ATA_TRK0NF) printk("TrackZeroNotFound "); + if (err & ATA_AMNF) printk("AddrMarkNotFound "); printk("}\n"); } } @@ -849,40 +865,59 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, /* Based on the 3ware driver translation table */ static const unsigned char sense_table[][4] = { /* BBD|ECC|ID|MAR */ - {0xd1, ABORTED_COMMAND, 0x00, 0x00}, // Device busy Aborted command + {0xd1, ABORTED_COMMAND, 0x00, 0x00}, + // Device busy Aborted command /* BBD|ECC|ID */ - {0xd0, ABORTED_COMMAND, 0x00, 0x00}, // Device busy Aborted command + {0xd0, ABORTED_COMMAND, 0x00, 0x00}, + // Device busy Aborted command /* ECC|MC|MARK */ - {0x61, HARDWARE_ERROR, 0x00, 0x00}, // Device fault Hardware error + {0x61, HARDWARE_ERROR, 0x00, 0x00}, + // Device fault Hardware error /* ICRC|ABRT */ /* NB: ICRC & !ABRT is BBD */ - {0x84, ABORTED_COMMAND, 0x47, 0x00}, // Data CRC error SCSI parity error + {0x84, ABORTED_COMMAND, 0x47, 0x00}, + // Data CRC error SCSI parity error /* MC|ID|ABRT|TRK0|MARK */ - {0x37, NOT_READY, 0x04, 0x00}, // Unit offline Not ready + {0x37, NOT_READY, 0x04, 0x00}, + // Unit offline Not ready /* MCR|MARK */ - {0x09, NOT_READY, 0x04, 0x00}, // Unrecovered disk error Not ready + {0x09, NOT_READY, 0x04, 0x00}, + // Unrecovered disk error Not ready /* Bad address mark */ - {0x01, MEDIUM_ERROR, 0x13, 0x00}, // Address mark not found Address mark not found for data field - /* TRK0 */ - {0x02, HARDWARE_ERROR, 0x00, 0x00}, // Track 0 not found Hardware error + {0x01, MEDIUM_ERROR, 0x13, 0x00}, + // Address mark not found for data field + /* TRK0 - Track 0 not found */ + {0x02, HARDWARE_ERROR, 0x00, 0x00}, + // Hardware error /* Abort: 0x04 is not translated here, see below */ /* Media change request */ - {0x08, NOT_READY, 0x04, 0x00}, // Media change request FIXME: faking offline - /* SRV/IDNF */ - {0x10, ILLEGAL_REQUEST, 0x21, 0x00}, // ID not found Logical address out of range - /* MC */ - {0x20, UNIT_ATTENTION, 0x28, 0x00}, // Media Changed Not ready to ready change, medium may have changed - /* ECC */ - {0x40, MEDIUM_ERROR, 0x11, 0x04}, // Uncorrectable ECC error Unrecovered read error + {0x08, NOT_READY, 0x04, 0x00}, + // FIXME: faking offline + /* SRV/IDNF - ID not found */ + {0x10, ILLEGAL_REQUEST, 0x21, 0x00}, + // Logical address out of range + /* MC - Media Changed */ + {0x20, UNIT_ATTENTION, 0x28, 0x00}, + // Not ready to ready change, medium may have changed + /* ECC - Uncorrectable ECC error */ + {0x40, MEDIUM_ERROR, 0x11, 0x04}, + // Unrecovered read error /* BBD - block marked bad */ - {0x80, MEDIUM_ERROR, 0x11, 0x04}, // Block marked bad Medium error, unrecovered read error + {0x80, MEDIUM_ERROR, 0x11, 0x04}, + // Block marked bad Medium error, unrecovered read error {0xFF, 0xFF, 0xFF, 0xFF}, // END mark }; static const unsigned char stat_table[][4] = { /* Must be first because BUSY means no other bits valid */ - {0x80, ABORTED_COMMAND, 0x47, 0x00}, // Busy, fake parity for now - {0x20, HARDWARE_ERROR, 0x44, 0x00}, // Device fault, internal target failure - {0x08, ABORTED_COMMAND, 0x47, 0x00}, // Timed out in xfer, fake parity for now - {0x04, RECOVERED_ERROR, 0x11, 0x00}, // Recovered ECC error Medium error, recovered + {0x80, ABORTED_COMMAND, 0x47, 0x00}, + // Busy, fake parity for now + {0x40, ILLEGAL_REQUEST, 0x21, 0x04}, + // Device ready, unaligned write command + {0x20, HARDWARE_ERROR, 0x44, 0x00}, + // Device fault, internal target failure + {0x08, ABORTED_COMMAND, 0x47, 0x00}, + // Timed out in xfer, fake parity for now + {0x04, RECOVERED_ERROR, 0x11, 0x00}, + // Recovered ECC error Medium error, recovered {0xFF, 0xFF, 0xFF, 0xFF}, // END mark }; @@ -1757,7 +1792,9 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) ((cdb[2] & 0x20) || need_sense)) { ata_gen_passthru_sense(qc); } else { - if (!need_sense) { + if (qc->flags & ATA_QCFLAG_SENSE_VALID) { + cmd->result = SAM_STAT_CHECK_CONDITION; + } else if (!need_sense) { cmd->result = SAM_STAT_GOOD; } else { /* TODO: decide which descriptor format to use @@ -4240,10 +4277,7 @@ int ata_sas_allocate_tag(struct ata_port *ap) unsigned int i, tag; for (i = 0, tag = ap->sas_last_tag + 1; i < max_queue; i++, tag++) { - if (ap->flags & ATA_FLAG_LOWTAG) - tag = 1; - else - tag = tag < max_queue ? tag : 0; + tag = tag < max_queue ? tag : 0; /* the last tag is reserved for internal command. */ if (tag == ATA_TAG_INTERNAL) diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 2e86e3b85266..cdf6215a9a22 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -3220,11 +3220,11 @@ void ata_pci_bmdma_init(struct ata_host *host) * ->sff_irq_clear method. Try to initialize bmdma_addr * regardless of dma masks. */ - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) ata_bmdma_nodma(host, "failed to set dma mask"); if (!rc) { - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) ata_bmdma_nodma(host, "failed to set consistent dma mask"); diff --git a/drivers/ata/libata-trace.c b/drivers/ata/libata-trace.c new file mode 100644 index 000000000000..fd30b8c10cf5 --- /dev/null +++ b/drivers/ata/libata-trace.c @@ -0,0 +1,151 @@ +/* + * libata-trace.c - trace functions for libata + * + * Copyright 2015 Hannes Reinecke + * Copyright 2015 SUSE Linux GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/kernel.h> +#include <linux/trace_seq.h> +#include <trace/events/libata.h> + +const char * +libata_trace_parse_status(struct trace_seq *p, unsigned char status) +{ + const char *ret = trace_seq_buffer_ptr(p); + + trace_seq_printf(p, "{ "); + if (status & ATA_BUSY) + trace_seq_printf(p, "BUSY "); + if (status & ATA_DRDY) + trace_seq_printf(p, "DRDY "); + if (status & ATA_DF) + trace_seq_printf(p, "DF "); + if (status & ATA_DSC) + trace_seq_printf(p, "DSC "); + if (status & ATA_DRQ) + trace_seq_printf(p, "DRQ "); + if (status & ATA_CORR) + trace_seq_printf(p, "CORR "); + if (status & ATA_SENSE) + trace_seq_printf(p, "SENSE "); + if (status & ATA_ERR) + trace_seq_printf(p, "ERR "); + trace_seq_putc(p, '}'); + trace_seq_putc(p, 0); + + return ret; +} + +const char * +libata_trace_parse_eh_action(struct trace_seq *p, unsigned int eh_action) +{ + const char *ret = trace_seq_buffer_ptr(p); + + trace_seq_printf(p, "%x", eh_action); + if (eh_action) { + trace_seq_printf(p, "{ "); + if (eh_action & ATA_EH_REVALIDATE) + trace_seq_printf(p, "REVALIDATE "); + if (eh_action & (ATA_EH_SOFTRESET | ATA_EH_HARDRESET)) + trace_seq_printf(p, "RESET "); + else if (eh_action & ATA_EH_SOFTRESET) + trace_seq_printf(p, "SOFTRESET "); + else if (eh_action & ATA_EH_HARDRESET) + trace_seq_printf(p, "HARDRESET "); + if (eh_action & ATA_EH_ENABLE_LINK) + trace_seq_printf(p, "ENABLE_LINK "); + if (eh_action & ATA_EH_PARK) + trace_seq_printf(p, "PARK "); + trace_seq_putc(p, '}'); + } + trace_seq_putc(p, 0); + + return ret; +} + +const char * +libata_trace_parse_eh_err_mask(struct trace_seq *p, unsigned int eh_err_mask) +{ + const char *ret = trace_seq_buffer_ptr(p); + + trace_seq_printf(p, "%x", eh_err_mask); + if (eh_err_mask) { + trace_seq_printf(p, "{ "); + if (eh_err_mask & AC_ERR_DEV) + trace_seq_printf(p, "DEV "); + if (eh_err_mask & AC_ERR_HSM) + trace_seq_printf(p, "HSM "); + if (eh_err_mask & AC_ERR_TIMEOUT) + trace_seq_printf(p, "TIMEOUT "); + if (eh_err_mask & AC_ERR_MEDIA) + trace_seq_printf(p, "MEDIA "); + if (eh_err_mask & AC_ERR_ATA_BUS) + trace_seq_printf(p, "ATA_BUS "); + if (eh_err_mask & AC_ERR_HOST_BUS) + trace_seq_printf(p, "HOST_BUS "); + if (eh_err_mask & AC_ERR_SYSTEM) + trace_seq_printf(p, "SYSTEM "); + if (eh_err_mask & AC_ERR_INVALID) + trace_seq_printf(p, "INVALID "); + if (eh_err_mask & AC_ERR_OTHER) + trace_seq_printf(p, "OTHER "); + if (eh_err_mask & AC_ERR_NODEV_HINT) + trace_seq_printf(p, "NODEV_HINT "); + if (eh_err_mask & AC_ERR_NCQ) + trace_seq_printf(p, "NCQ "); + trace_seq_putc(p, '}'); + } + trace_seq_putc(p, 0); + + return ret; +} + +const char * +libata_trace_parse_qc_flags(struct trace_seq *p, unsigned int qc_flags) +{ + const char *ret = trace_seq_buffer_ptr(p); + + trace_seq_printf(p, "%x", qc_flags); + if (qc_flags) { + trace_seq_printf(p, "{ "); + if (qc_flags & ATA_QCFLAG_ACTIVE) + trace_seq_printf(p, "ACTIVE "); + if (qc_flags & ATA_QCFLAG_DMAMAP) + trace_seq_printf(p, "DMAMAP "); + if (qc_flags & ATA_QCFLAG_IO) + trace_seq_printf(p, "IO "); + if (qc_flags & ATA_QCFLAG_RESULT_TF) + trace_seq_printf(p, "RESULT_TF "); + if (qc_flags & ATA_QCFLAG_CLEAR_EXCL) + trace_seq_printf(p, "CLEAR_EXCL "); + if (qc_flags & ATA_QCFLAG_QUIET) + trace_seq_printf(p, "QUIET "); + if (qc_flags & ATA_QCFLAG_RETRY) + trace_seq_printf(p, "RETRY "); + if (qc_flags & ATA_QCFLAG_FAILED) + trace_seq_printf(p, "FAILED "); + if (qc_flags & ATA_QCFLAG_SENSE_VALID) + trace_seq_printf(p, "SENSE_VALID "); + if (qc_flags & ATA_QCFLAG_EH_SCHEDULED) + trace_seq_printf(p, "EH_SCHEDULED "); + trace_seq_putc(p, '}'); + } + trace_seq_putc(p, 0); + + return ret; +} diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index f840ca18a7c0..a998a175f9f1 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -67,7 +67,8 @@ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag); extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags, unsigned int tag); -extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev); +extern u64 ata_tf_read_block(const struct ata_taskfile *tf, + struct ata_device *dev); extern unsigned ata_exec_internal(struct ata_device *dev, struct ata_taskfile *tf, const u8 *cdb, int dma_dir, void *buf, unsigned int buflen, @@ -137,6 +138,9 @@ extern int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht); extern void ata_scsi_scan_host(struct ata_port *ap, int sync); extern int ata_scsi_offline_dev(struct ata_device *dev); +extern void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq); +extern void ata_scsi_set_sense_information(struct scsi_cmnd *cmd, + const struct ata_taskfile *tf); extern void ata_scsi_media_change_notify(struct ata_device *dev); extern void ata_scsi_hotplug(struct work_struct *work); extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); diff --git a/drivers/ata/pata_atp867x.c b/drivers/ata/pata_atp867x.c index a705cfca90f7..3ea50dc5ea47 100644 --- a/drivers/ata/pata_atp867x.c +++ b/drivers/ata/pata_atp867x.c @@ -475,11 +475,11 @@ static int atp867x_ata_pci_sff_init_host(struct ata_host *host) atp867x_fixup(host); - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); return rc; } diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index d65cb9d2fa8c..4cb24070cc2d 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c @@ -164,11 +164,11 @@ static int cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return -ENODEV; } - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { + if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) { printk(KERN_ERR DRV_NAME ": unable to configure DMA mask.\n"); return -ENODEV; } - if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { + if (dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32))) { printk(KERN_ERR DRV_NAME ": unable to configure consistent DMA mask.\n"); return -ENODEV; } diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index d019cdd5bc9f..b2fc023783b1 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c @@ -221,10 +221,10 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id) if (rc) return rc; host->iomap = pcim_iomap_table(pdev); - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c index b33d1f99b3a4..994f168b54a8 100644 --- a/drivers/ata/pata_isapnp.c +++ b/drivers/ata/pata_isapnp.c @@ -128,20 +128,8 @@ static struct pnp_driver isapnp_driver = { .remove = isapnp_remove_one, }; -static int __init isapnp_init(void) -{ - return pnp_register_driver(&isapnp_driver); -} - -static void __exit isapnp_exit(void) -{ - pnp_unregister_driver(&isapnp_driver); -} - +module_pnp_driver(isapnp_driver); MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("low-level driver for ISA PnP ATA"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); - -module_init(isapnp_init); -module_exit(isapnp_exit); diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c index a02f76fdcfcd..b0028588ff1c 100644 --- a/drivers/ata/pata_macio.c +++ b/drivers/ata/pata_macio.c @@ -540,9 +540,9 @@ static void pata_macio_qc_prep(struct ata_queued_cmd *qc) BUG_ON (pi++ >= MAX_DCMDS); len = (sg_len < MAX_DBDMA_SEG) ? sg_len : MAX_DBDMA_SEG; - st_le16(&table->command, write ? OUTPUT_MORE: INPUT_MORE); - st_le16(&table->req_count, len); - st_le32(&table->phy_addr, addr); + table->command = cpu_to_le16(write ? OUTPUT_MORE: INPUT_MORE); + table->req_count = cpu_to_le16(len); + table->phy_addr = cpu_to_le32(addr); table->cmd_dep = 0; table->xfer_status = 0; table->res_count = 0; @@ -557,12 +557,12 @@ static void pata_macio_qc_prep(struct ata_queued_cmd *qc) /* Convert the last command to an input/output */ table--; - st_le16(&table->command, write ? OUTPUT_LAST: INPUT_LAST); + table->command = cpu_to_le16(write ? OUTPUT_LAST: INPUT_LAST); table++; /* Add the stop command to the end of the list */ memset(table, 0, sizeof(struct dbdma_cmd)); - st_le16(&table->command, DBDMA_STOP); + table->command = cpu_to_le16(DBDMA_STOP); dev_dbgdma(priv->dev, "%s: %d DMA list entries\n", __func__, pi); } diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c index efb272da8567..633aa2934a18 100644 --- a/drivers/ata/pata_ninja32.c +++ b/drivers/ata/pata_ninja32.c @@ -122,10 +122,10 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id) return rc; host->iomap = pcim_iomap_table(dev); - rc = pci_set_dma_mask(dev, ATA_DMA_MASK); + rc = dma_set_mask(&dev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(dev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&dev->dev, ATA_DMA_MASK); if (rc) return rc; pci_set_master(dev); diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index dca8251b1aea..d9ef9e276225 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c @@ -730,11 +730,11 @@ static int pdc2027x_init_one(struct pci_dev *pdev, return rc; host->iomap = pcim_iomap_table(pdev); - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index 7f4cb76ed9fa..5cd60d6388ec 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -1029,10 +1029,10 @@ static int scc_host_init(struct ata_host *host) if (rc) return rc; - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index f597edccedec..c14071be4f55 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -374,10 +374,10 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) host->iomap = pcim_iomap_table(pdev); /* Setup DMA masks */ - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; pci_set_master(pdev); diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c index f10631beffa8..64d682c6ee57 100644 --- a/drivers/ata/pdc_adma.c +++ b/drivers/ata/pdc_adma.c @@ -593,12 +593,12 @@ static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base) { int rc; - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit DMA enable failed\n"); return rc; } - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n"); return rc; diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index fdb0f2879ea7..902034991517 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -36,11 +36,16 @@ #include <linux/platform_device.h> #include <linux/libata.h> #include <linux/slab.h> + #include "libata.h" #include <scsi/scsi_host.h> #include <scsi/scsi_cmnd.h> +/* Supported DMA engine drivers */ +#include <linux/platform_data/dma-dw.h> +#include <linux/dma/dw.h> + /* These two are defined in "libata.h" */ #undef DRV_NAME #undef DRV_VERSION @@ -60,153 +65,9 @@ #define NO_IRQ 0 #endif -/* SATA DMA driver Globals */ -#define DMA_NUM_CHANS 1 -#define DMA_NUM_CHAN_REGS 8 - -/* SATA DMA Register definitions */ #define AHB_DMA_BRST_DFLT 64 /* 16 data items burst length*/ -struct dmareg { - u32 low; /* Low bits 0-31 */ - u32 high; /* High bits 32-63 */ -}; - -/* DMA Per Channel registers */ -struct dma_chan_regs { - struct dmareg sar; /* Source Address */ - struct dmareg dar; /* Destination address */ - struct dmareg llp; /* Linked List Pointer */ - struct dmareg ctl; /* Control */ - struct dmareg sstat; /* Source Status not implemented in core */ - struct dmareg dstat; /* Destination Status not implemented in core*/ - struct dmareg sstatar; /* Source Status Address not impl in core */ - struct dmareg dstatar; /* Destination Status Address not implemente */ - struct dmareg cfg; /* Config */ - struct dmareg sgr; /* Source Gather */ - struct dmareg dsr; /* Destination Scatter */ -}; - -/* Generic Interrupt Registers */ -struct dma_interrupt_regs { - struct dmareg tfr; /* Transfer Interrupt */ - struct dmareg block; /* Block Interrupt */ - struct dmareg srctran; /* Source Transfer Interrupt */ - struct dmareg dsttran; /* Dest Transfer Interrupt */ - struct dmareg error; /* Error */ -}; - -struct ahb_dma_regs { - struct dma_chan_regs chan_regs[DMA_NUM_CHAN_REGS]; - struct dma_interrupt_regs interrupt_raw; /* Raw Interrupt */ - struct dma_interrupt_regs interrupt_status; /* Interrupt Status */ - struct dma_interrupt_regs interrupt_mask; /* Interrupt Mask */ - struct dma_interrupt_regs interrupt_clear; /* Interrupt Clear */ - struct dmareg statusInt; /* Interrupt combined*/ - struct dmareg rq_srcreg; /* Src Trans Req */ - struct dmareg rq_dstreg; /* Dst Trans Req */ - struct dmareg rq_sgl_srcreg; /* Sngl Src Trans Req*/ - struct dmareg rq_sgl_dstreg; /* Sngl Dst Trans Req*/ - struct dmareg rq_lst_srcreg; /* Last Src Trans Req*/ - struct dmareg rq_lst_dstreg; /* Last Dst Trans Req*/ - struct dmareg dma_cfg; /* DMA Config */ - struct dmareg dma_chan_en; /* DMA Channel Enable*/ - struct dmareg dma_id; /* DMA ID */ - struct dmareg dma_test; /* DMA Test */ - struct dmareg res1; /* reserved */ - struct dmareg res2; /* reserved */ - /* - * DMA Comp Params - * Param 6 = dma_param[0], Param 5 = dma_param[1], - * Param 4 = dma_param[2] ... - */ - struct dmareg dma_params[6]; -}; - -/* Data structure for linked list item */ -struct lli { - u32 sar; /* Source Address */ - u32 dar; /* Destination address */ - u32 llp; /* Linked List Pointer */ - struct dmareg ctl; /* Control */ - struct dmareg dstat; /* Destination Status */ -}; - -enum { - SATA_DWC_DMAC_LLI_SZ = (sizeof(struct lli)), - SATA_DWC_DMAC_LLI_NUM = 256, - SATA_DWC_DMAC_LLI_TBL_SZ = (SATA_DWC_DMAC_LLI_SZ * \ - SATA_DWC_DMAC_LLI_NUM), - SATA_DWC_DMAC_TWIDTH_BYTES = 4, - SATA_DWC_DMAC_CTRL_TSIZE_MAX = (0x00000800 * \ - SATA_DWC_DMAC_TWIDTH_BYTES), -}; - -/* DMA Register Operation Bits */ -enum { - DMA_EN = 0x00000001, /* Enable AHB DMA */ - DMA_CTL_LLP_SRCEN = 0x10000000, /* Blk chain enable Src */ - DMA_CTL_LLP_DSTEN = 0x08000000, /* Blk chain enable Dst */ -}; - -#define DMA_CTL_BLK_TS(size) ((size) & 0x000000FFF) /* Blk Transfer size */ -#define DMA_CHANNEL(ch) (0x00000001 << (ch)) /* Select channel */ - /* Enable channel */ -#define DMA_ENABLE_CHAN(ch) ((0x00000001 << (ch)) | \ - ((0x000000001 << (ch)) << 8)) - /* Disable channel */ -#define DMA_DISABLE_CHAN(ch) (0x00000000 | ((0x000000001 << (ch)) << 8)) - /* Transfer Type & Flow Controller */ -#define DMA_CTL_TTFC(type) (((type) & 0x7) << 20) -#define DMA_CTL_SMS(num) (((num) & 0x3) << 25) /* Src Master Select */ -#define DMA_CTL_DMS(num) (((num) & 0x3) << 23)/* Dst Master Select */ - /* Src Burst Transaction Length */ -#define DMA_CTL_SRC_MSIZE(size) (((size) & 0x7) << 14) - /* Dst Burst Transaction Length */ -#define DMA_CTL_DST_MSIZE(size) (((size) & 0x7) << 11) - /* Source Transfer Width */ -#define DMA_CTL_SRC_TRWID(size) (((size) & 0x7) << 4) - /* Destination Transfer Width */ -#define DMA_CTL_DST_TRWID(size) (((size) & 0x7) << 1) - -/* Assign HW handshaking interface (x) to destination / source peripheral */ -#define DMA_CFG_HW_HS_DEST(int_num) (((int_num) & 0xF) << 11) -#define DMA_CFG_HW_HS_SRC(int_num) (((int_num) & 0xF) << 7) -#define DMA_CFG_HW_CH_PRIOR(int_num) (((int_num) & 0xF) << 5) -#define DMA_LLP_LMS(addr, master) (((addr) & 0xfffffffc) | (master)) - -/* - * This define is used to set block chaining disabled in the control low - * register. It is already in little endian format so it can be &'d dirctly. - * It is essentially: cpu_to_le32(~(DMA_CTL_LLP_SRCEN | DMA_CTL_LLP_DSTEN)) - */ enum { - DMA_CTL_LLP_DISABLE_LE32 = 0xffffffe7, - DMA_CTL_TTFC_P2M_DMAC = 0x00000002, /* Per to mem, DMAC cntr */ - DMA_CTL_TTFC_M2P_PER = 0x00000003, /* Mem to per, peripheral cntr */ - DMA_CTL_SINC_INC = 0x00000000, /* Source Address Increment */ - DMA_CTL_SINC_DEC = 0x00000200, - DMA_CTL_SINC_NOCHANGE = 0x00000400, - DMA_CTL_DINC_INC = 0x00000000, /* Destination Address Increment */ - DMA_CTL_DINC_DEC = 0x00000080, - DMA_CTL_DINC_NOCHANGE = 0x00000100, - DMA_CTL_INT_EN = 0x00000001, /* Interrupt Enable */ - -/* Channel Configuration Register high bits */ - DMA_CFG_FCMOD_REQ = 0x00000001, /* Flow Control - request based */ - DMA_CFG_PROTCTL = (0x00000003 << 2),/* Protection Control */ - -/* Channel Configuration Register low bits */ - DMA_CFG_RELD_DST = 0x80000000, /* Reload Dest / Src Addr */ - DMA_CFG_RELD_SRC = 0x40000000, - DMA_CFG_HS_SELSRC = 0x00000800, /* Software handshake Src/ Dest */ - DMA_CFG_HS_SELDST = 0x00000400, - DMA_CFG_FIFOEMPTY = (0x00000001 << 9), /* FIFO Empty bit */ - -/* Channel Linked List Pointer Register */ - DMA_LLP_AHBMASTER1 = 0, /* List Master Select */ - DMA_LLP_AHBMASTER2 = 1, - SATA_DWC_MAX_PORTS = 1, SATA_DWC_SCR_OFFSET = 0x24, @@ -287,7 +148,7 @@ struct sata_dwc_device { struct ata_host *host; u8 __iomem *reg_base; struct sata_dwc_regs *sata_dwc_regs; /* DW Synopsys SATA specific */ - int irq_dma; + struct dw_dma_chip *dma; }; #define SATA_DWC_QCMD_MAX 32 @@ -295,10 +156,13 @@ struct sata_dwc_device { struct sata_dwc_device_port { struct sata_dwc_device *hsdev; int cmd_issued[SATA_DWC_QCMD_MAX]; - struct lli *llit[SATA_DWC_QCMD_MAX]; /* DMA LLI table */ - dma_addr_t llit_dma[SATA_DWC_QCMD_MAX]; - u32 dma_chan[SATA_DWC_QCMD_MAX]; int dma_pending[SATA_DWC_QCMD_MAX]; + + /* DMA info */ + struct dw_dma_slave *dws; + struct dma_chan *chan; + struct dma_async_tx_descriptor *desc[SATA_DWC_QCMD_MAX]; + u32 dma_interrupt_count; }; /* @@ -330,14 +194,17 @@ struct sata_dwc_host_priv { void __iomem *scr_addr_sstatus; u32 sata_dwc_sactive_issued ; u32 sata_dwc_sactive_queued ; - u32 dma_interrupt_count; - struct ahb_dma_regs *sata_dma_regs; - struct device *dwc_dev; - int dma_channel; }; static struct sata_dwc_host_priv host_pvt; +static struct dw_dma_slave sata_dwc_dma_dws = { + .src_id = 0, + .dst_id = 0, + .src_master = 0, + .dst_master = 1, +}; + /* * Prototypes */ @@ -347,12 +214,6 @@ static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc, static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status); static void sata_dwc_port_stop(struct ata_port *ap); static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag); -static int dma_dwc_init(struct sata_dwc_device *hsdev, int irq); -static void dma_dwc_exit(struct sata_dwc_device *hsdev); -static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems, - struct lli *lli, dma_addr_t dma_lli, - void __iomem *addr, int dir); -static void dma_dwc_xfer_start(int dma_ch); static const char *get_prot_descript(u8 protocol) { @@ -390,90 +251,23 @@ static const char *get_dma_dir_descript(int dma_dir) } } -static void sata_dwc_tf_dump(struct ata_taskfile *tf) +static void sata_dwc_tf_dump(struct ata_port *ap, struct ata_taskfile *tf) { - dev_vdbg(host_pvt.dwc_dev, "taskfile cmd: 0x%02x protocol: %s flags:" - "0x%lx device: %x\n", tf->command, - get_prot_descript(tf->protocol), tf->flags, tf->device); - dev_vdbg(host_pvt.dwc_dev, "feature: 0x%02x nsect: 0x%x lbal: 0x%x " - "lbam: 0x%x lbah: 0x%x\n", tf->feature, tf->nsect, tf->lbal, - tf->lbam, tf->lbah); - dev_vdbg(host_pvt.dwc_dev, "hob_feature: 0x%02x hob_nsect: 0x%x " - "hob_lbal: 0x%x hob_lbam: 0x%x hob_lbah: 0x%x\n", + dev_vdbg(ap->dev, + "taskfile cmd: 0x%02x protocol: %s flags: 0x%lx device: %x\n", + tf->command, get_prot_descript(tf->protocol), tf->flags, + tf->device); + dev_vdbg(ap->dev, + "feature: 0x%02x nsect: 0x%x lbal: 0x%x lbam: 0x%x lbah: 0x%x\n", + tf->feature, tf->nsect, tf->lbal, tf->lbam, tf->lbah); + dev_vdbg(ap->dev, + "hob_feature: 0x%02x hob_nsect: 0x%x hob_lbal: 0x%x hob_lbam: 0x%x hob_lbah: 0x%x\n", tf->hob_feature, tf->hob_nsect, tf->hob_lbal, tf->hob_lbam, tf->hob_lbah); } -/* - * Function: get_burst_length_encode - * arguments: datalength: length in bytes of data - * returns value to be programmed in register corresponding to data length - * This value is effectively the log(base 2) of the length - */ -static int get_burst_length_encode(int datalength) -{ - int items = datalength >> 2; /* div by 4 to get lword count */ - - if (items >= 64) - return 5; - - if (items >= 32) - return 4; - - if (items >= 16) - return 3; - - if (items >= 8) - return 2; - - if (items >= 4) - return 1; - - return 0; -} - -static void clear_chan_interrupts(int c) +static void dma_dwc_xfer_done(void *hsdev_instance) { - out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.tfr.low), - DMA_CHANNEL(c)); - out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.block.low), - DMA_CHANNEL(c)); - out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.srctran.low), - DMA_CHANNEL(c)); - out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.dsttran.low), - DMA_CHANNEL(c)); - out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.error.low), - DMA_CHANNEL(c)); -} - -/* - * Function: dma_request_channel - * arguments: None - * returns channel number if available else -1 - * This function assigns the next available DMA channel from the list to the - * requester - */ -static int dma_request_channel(void) -{ - /* Check if the channel is not currently in use */ - if (!(in_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low)) & - DMA_CHANNEL(host_pvt.dma_channel))) - return host_pvt.dma_channel; - dev_err(host_pvt.dwc_dev, "%s Channel %d is currently in use\n", - __func__, host_pvt.dma_channel); - return -1; -} - -/* - * Function: dma_dwc_interrupt - * arguments: irq, dev_id, pt_regs - * returns channel number if available else -1 - * Interrupt Handler for DW AHB SATA DMA - */ -static irqreturn_t dma_dwc_interrupt(int irq, void *hsdev_instance) -{ - int chan; - u32 tfr_reg, err_reg; unsigned long flags; struct sata_dwc_device *hsdev = hsdev_instance; struct ata_host *host = (struct ata_host *)hsdev->host; @@ -487,341 +281,65 @@ static irqreturn_t dma_dwc_interrupt(int irq, void *hsdev_instance) hsdevp = HSDEVP_FROM_AP(ap); tag = ap->link.active_tag; - tfr_reg = in_le32(&(host_pvt.sata_dma_regs->interrupt_status.tfr\ - .low)); - err_reg = in_le32(&(host_pvt.sata_dma_regs->interrupt_status.error\ - .low)); - - dev_dbg(ap->dev, "eot=0x%08x err=0x%08x pending=%d active port=%d\n", - tfr_reg, err_reg, hsdevp->dma_pending[tag], port); - - chan = host_pvt.dma_channel; - if (chan >= 0) { - /* Check for end-of-transfer interrupt. */ - if (tfr_reg & DMA_CHANNEL(chan)) { - /* - * Each DMA command produces 2 interrupts. Only - * complete the command after both interrupts have been - * seen. (See sata_dwc_isr()) - */ - host_pvt.dma_interrupt_count++; - sata_dwc_clear_dmacr(hsdevp, tag); - - if (hsdevp->dma_pending[tag] == - SATA_DWC_DMA_PENDING_NONE) { - dev_err(ap->dev, "DMA not pending eot=0x%08x " - "err=0x%08x tag=0x%02x pending=%d\n", - tfr_reg, err_reg, tag, - hsdevp->dma_pending[tag]); - } - - if ((host_pvt.dma_interrupt_count % 2) == 0) - sata_dwc_dma_xfer_complete(ap, 1); - - /* Clear the interrupt */ - out_le32(&(host_pvt.sata_dma_regs->interrupt_clear\ - .tfr.low), - DMA_CHANNEL(chan)); - } - - /* Check for error interrupt. */ - if (err_reg & DMA_CHANNEL(chan)) { - /* TODO Need error handler ! */ - dev_err(ap->dev, "error interrupt err_reg=0x%08x\n", - err_reg); - - /* Clear the interrupt. */ - out_le32(&(host_pvt.sata_dma_regs->interrupt_clear\ - .error.low), - DMA_CHANNEL(chan)); - } - } - spin_unlock_irqrestore(&host->lock, flags); - return IRQ_HANDLED; -} - -/* - * Function: dma_request_interrupts - * arguments: hsdev - * returns status - * This function registers ISR for a particular DMA channel interrupt - */ -static int dma_request_interrupts(struct sata_dwc_device *hsdev, int irq) -{ - int retval = 0; - int chan = host_pvt.dma_channel; - - if (chan >= 0) { - /* Unmask error interrupt */ - out_le32(&(host_pvt.sata_dma_regs)->interrupt_mask.error.low, - DMA_ENABLE_CHAN(chan)); - - /* Unmask end-of-transfer interrupt */ - out_le32(&(host_pvt.sata_dma_regs)->interrupt_mask.tfr.low, - DMA_ENABLE_CHAN(chan)); - } - - retval = request_irq(irq, dma_dwc_interrupt, 0, "SATA DMA", hsdev); - if (retval) { - dev_err(host_pvt.dwc_dev, "%s: could not get IRQ %d\n", - __func__, irq); - return -ENODEV; - } - - /* Mark this interrupt as requested */ - hsdev->irq_dma = irq; - return 0; -} - -/* - * Function: map_sg_to_lli - * The Synopsis driver has a comment proposing that better performance - * is possible by only enabling interrupts on the last item in the linked list. - * However, it seems that could be a problem if an error happened on one of the - * first items. The transfer would halt, but no error interrupt would occur. - * Currently this function sets interrupts enabled for each linked list item: - * DMA_CTL_INT_EN. - */ -static int map_sg_to_lli(struct scatterlist *sg, int num_elems, - struct lli *lli, dma_addr_t dma_lli, - void __iomem *dmadr_addr, int dir) -{ - int i, idx = 0; - int fis_len = 0; - dma_addr_t next_llp; - int bl; - int sms_val, dms_val; - - sms_val = 0; - dms_val = 1 + host_pvt.dma_channel; - dev_dbg(host_pvt.dwc_dev, - "%s: sg=%p nelem=%d lli=%p dma_lli=0x%pad dmadr=0x%p\n", - __func__, sg, num_elems, lli, &dma_lli, dmadr_addr); - - bl = get_burst_length_encode(AHB_DMA_BRST_DFLT); - - for (i = 0; i < num_elems; i++, sg++) { - u32 addr, offset; - u32 sg_len, len; - - addr = (u32) sg_dma_address(sg); - sg_len = sg_dma_len(sg); - - dev_dbg(host_pvt.dwc_dev, "%s: elem=%d sg_addr=0x%x sg_len" - "=%d\n", __func__, i, addr, sg_len); - - while (sg_len) { - if (idx >= SATA_DWC_DMAC_LLI_NUM) { - /* The LLI table is not large enough. */ - dev_err(host_pvt.dwc_dev, "LLI table overrun " - "(idx=%d)\n", idx); - break; - } - len = (sg_len > SATA_DWC_DMAC_CTRL_TSIZE_MAX) ? - SATA_DWC_DMAC_CTRL_TSIZE_MAX : sg_len; - - offset = addr & 0xffff; - if ((offset + sg_len) > 0x10000) - len = 0x10000 - offset; - - /* - * Make sure a LLI block is not created that will span - * 8K max FIS boundary. If the block spans such a FIS - * boundary, there is a chance that a DMA burst will - * cross that boundary -- this results in an error in - * the host controller. - */ - if (fis_len + len > 8192) { - dev_dbg(host_pvt.dwc_dev, "SPLITTING: fis_len=" - "%d(0x%x) len=%d(0x%x)\n", fis_len, - fis_len, len, len); - len = 8192 - fis_len; - fis_len = 0; - } else { - fis_len += len; - } - if (fis_len == 8192) - fis_len = 0; - - /* - * Set DMA addresses and lower half of control register - * based on direction. - */ - if (dir == DMA_FROM_DEVICE) { - lli[idx].dar = cpu_to_le32(addr); - lli[idx].sar = cpu_to_le32((u32)dmadr_addr); - - lli[idx].ctl.low = cpu_to_le32( - DMA_CTL_TTFC(DMA_CTL_TTFC_P2M_DMAC) | - DMA_CTL_SMS(sms_val) | - DMA_CTL_DMS(dms_val) | - DMA_CTL_SRC_MSIZE(bl) | - DMA_CTL_DST_MSIZE(bl) | - DMA_CTL_SINC_NOCHANGE | - DMA_CTL_SRC_TRWID(2) | - DMA_CTL_DST_TRWID(2) | - DMA_CTL_INT_EN | - DMA_CTL_LLP_SRCEN | - DMA_CTL_LLP_DSTEN); - } else { /* DMA_TO_DEVICE */ - lli[idx].sar = cpu_to_le32(addr); - lli[idx].dar = cpu_to_le32((u32)dmadr_addr); - - lli[idx].ctl.low = cpu_to_le32( - DMA_CTL_TTFC(DMA_CTL_TTFC_M2P_PER) | - DMA_CTL_SMS(dms_val) | - DMA_CTL_DMS(sms_val) | - DMA_CTL_SRC_MSIZE(bl) | - DMA_CTL_DST_MSIZE(bl) | - DMA_CTL_DINC_NOCHANGE | - DMA_CTL_SRC_TRWID(2) | - DMA_CTL_DST_TRWID(2) | - DMA_CTL_INT_EN | - DMA_CTL_LLP_SRCEN | - DMA_CTL_LLP_DSTEN); - } - - dev_dbg(host_pvt.dwc_dev, "%s setting ctl.high len: " - "0x%08x val: 0x%08x\n", __func__, - len, DMA_CTL_BLK_TS(len / 4)); - - /* Program the LLI CTL high register */ - lli[idx].ctl.high = cpu_to_le32(DMA_CTL_BLK_TS\ - (len / 4)); - - /* Program the next pointer. The next pointer must be - * the physical address, not the virtual address. - */ - next_llp = (dma_lli + ((idx + 1) * sizeof(struct \ - lli))); - - /* The last 2 bits encode the list master select. */ - next_llp = DMA_LLP_LMS(next_llp, DMA_LLP_AHBMASTER2); - - lli[idx].llp = cpu_to_le32(next_llp); - idx++; - sg_len -= len; - addr += len; - } - } - /* - * The last next ptr has to be zero and the last control low register - * has to have LLP_SRC_EN and LLP_DST_EN (linked list pointer source - * and destination enable) set back to 0 (disabled.) This is what tells - * the core that this is the last item in the linked list. + * Each DMA command produces 2 interrupts. Only + * complete the command after both interrupts have been + * seen. (See sata_dwc_isr()) */ - if (idx) { - lli[idx-1].llp = 0x00000000; - lli[idx-1].ctl.low &= DMA_CTL_LLP_DISABLE_LE32; + hsdevp->dma_interrupt_count++; + sata_dwc_clear_dmacr(hsdevp, tag); - /* Flush cache to memory */ - dma_cache_sync(NULL, lli, (sizeof(struct lli) * idx), - DMA_BIDIRECTIONAL); + if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_NONE) { + dev_err(ap->dev, "DMA not pending tag=0x%02x pending=%d\n", + tag, hsdevp->dma_pending[tag]); } - return idx; -} + if ((hsdevp->dma_interrupt_count % 2) == 0) + sata_dwc_dma_xfer_complete(ap, 1); -/* - * Function: dma_dwc_xfer_start - * arguments: Channel number - * Return : None - * Enables the DMA channel - */ -static void dma_dwc_xfer_start(int dma_ch) -{ - /* Enable the DMA channel */ - out_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low), - in_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low)) | - DMA_ENABLE_CHAN(dma_ch)); + spin_unlock_irqrestore(&host->lock, flags); } -static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems, - struct lli *lli, dma_addr_t dma_lli, - void __iomem *addr, int dir) +static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd *qc) { - int dma_ch; - int num_lli; - /* Acquire DMA channel */ - dma_ch = dma_request_channel(); - if (dma_ch == -1) { - dev_err(host_pvt.dwc_dev, "%s: dma channel unavailable\n", - __func__); - return -EAGAIN; + struct ata_port *ap = qc->ap; + struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); + struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); + dma_addr_t addr = (dma_addr_t)&hsdev->sata_dwc_regs->dmadr; + struct dma_slave_config sconf; + struct dma_async_tx_descriptor *desc; + + if (qc->dma_dir == DMA_DEV_TO_MEM) { + sconf.src_addr = addr; + sconf.device_fc = true; + } else { /* DMA_MEM_TO_DEV */ + sconf.dst_addr = addr; + sconf.device_fc = false; } - /* Convert SG list to linked list of items (LLIs) for AHB DMA */ - num_lli = map_sg_to_lli(sg, num_elems, lli, dma_lli, addr, dir); - - dev_dbg(host_pvt.dwc_dev, "%s sg: 0x%p, count: %d lli: %p dma_lli:" - " 0x%0xlx addr: %p lli count: %d\n", __func__, sg, num_elems, - lli, (u32)dma_lli, addr, num_lli); - - clear_chan_interrupts(dma_ch); + sconf.direction = qc->dma_dir; + sconf.src_maxburst = AHB_DMA_BRST_DFLT; + sconf.dst_maxburst = AHB_DMA_BRST_DFLT; + sconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + sconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - /* Program the CFG register. */ - out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].cfg.high), - DMA_CFG_HW_HS_SRC(dma_ch) | DMA_CFG_HW_HS_DEST(dma_ch) | - DMA_CFG_PROTCTL | DMA_CFG_FCMOD_REQ); - out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].cfg.low), - DMA_CFG_HW_CH_PRIOR(dma_ch)); + dmaengine_slave_config(hsdevp->chan, &sconf); - /* Program the address of the linked list */ - out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].llp.low), - DMA_LLP_LMS(dma_lli, DMA_LLP_AHBMASTER2)); - - /* Program the CTL register with src enable / dst enable */ - out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].ctl.low), - DMA_CTL_LLP_SRCEN | DMA_CTL_LLP_DSTEN); - return dma_ch; -} - -/* - * Function: dma_dwc_exit - * arguments: None - * returns status - * This function exits the SATA DMA driver - */ -static void dma_dwc_exit(struct sata_dwc_device *hsdev) -{ - dev_dbg(host_pvt.dwc_dev, "%s:\n", __func__); - if (host_pvt.sata_dma_regs) { - iounmap((void __iomem *)host_pvt.sata_dma_regs); - host_pvt.sata_dma_regs = NULL; - } - - if (hsdev->irq_dma) { - free_irq(hsdev->irq_dma, hsdev); - hsdev->irq_dma = 0; - } -} - -/* - * Function: dma_dwc_init - * arguments: hsdev - * returns status - * This function initializes the SATA DMA driver - */ -static int dma_dwc_init(struct sata_dwc_device *hsdev, int irq) -{ - int err; + /* Convert SG list to linked list of items (LLIs) for AHB DMA */ + desc = dmaengine_prep_slave_sg(hsdevp->chan, qc->sg, qc->n_elem, + qc->dma_dir, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - err = dma_request_interrupts(hsdev, irq); - if (err) { - dev_err(host_pvt.dwc_dev, "%s: dma_request_interrupts returns" - " %d\n", __func__, err); - return err; - } + if (!desc) + return NULL; - /* Enabe DMA */ - out_le32(&(host_pvt.sata_dma_regs->dma_cfg.low), DMA_EN); + desc->callback = dma_dwc_xfer_done; + desc->callback_param = hsdev; - dev_notice(host_pvt.dwc_dev, "DMA initialized\n"); - dev_dbg(host_pvt.dwc_dev, "SATA DMA registers=0x%p\n", host_pvt.\ - sata_dma_regs); + dev_dbg(hsdev->dev, "%s sg: 0x%p, count: %d addr: %pad\n", + __func__, qc->sg, qc->n_elem, &addr); - return 0; + return desc; } static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val) @@ -891,21 +409,18 @@ static void sata_dwc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc; u32 serror; u8 status, tag; - u32 err_reg; ata_ehi_clear_desc(ehi); serror = core_scr_read(SCR_ERROR); status = ap->ops->sff_check_status(ap); - err_reg = in_le32(&(host_pvt.sata_dma_regs->interrupt_status.error.\ - low)); tag = ap->link.active_tag; - dev_err(ap->dev, "%s SCR_ERROR=0x%08x intpr=0x%08x status=0x%08x " - "dma_intp=%d pending=%d issued=%d dma_err_status=0x%08x\n", - __func__, serror, intpr, status, host_pvt.dma_interrupt_count, - hsdevp->dma_pending[tag], hsdevp->cmd_issued[tag], err_reg); + dev_err(ap->dev, + "%s SCR_ERROR=0x%08x intpr=0x%08x status=0x%08x dma_intp=%d pending=%d issued=%d", + __func__, serror, intpr, status, hsdevp->dma_interrupt_count, + hsdevp->dma_pending[tag], hsdevp->cmd_issued[tag]); /* Clear error register and interrupt bit */ clear_serror(); @@ -1003,8 +518,9 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) /* DEV interrupt w/ no active qc? */ if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { - dev_err(ap->dev, "%s interrupt with no active qc " - "qc=%p\n", __func__, qc); + dev_err(ap->dev, + "%s interrupt with no active qc qc=%p\n", + __func__, qc); ap->ops->sff_check_status(ap); handled = 1; goto DONE; @@ -1031,16 +547,16 @@ DRVSTILLBUSY: * operation done interrupt. The command should be * completed only after both interrupts are seen. */ - host_pvt.dma_interrupt_count++; + hsdevp->dma_interrupt_count++; if (hsdevp->dma_pending[tag] == \ SATA_DWC_DMA_PENDING_NONE) { - dev_err(ap->dev, "%s: DMA not pending " - "intpr=0x%08x status=0x%08x pending" - "=%d\n", __func__, intpr, status, + dev_err(ap->dev, + "%s: DMA not pending intpr=0x%08x status=0x%08x pending=%d\n", + __func__, intpr, status, hsdevp->dma_pending[tag]); } - if ((host_pvt.dma_interrupt_count % 2) == 0) + if ((hsdevp->dma_interrupt_count % 2) == 0) sata_dwc_dma_xfer_complete(ap, 1); } else if (ata_is_pio(qc->tf.protocol)) { ata_sff_hsm_move(ap, qc, status, 0); @@ -1068,17 +584,17 @@ DRVSTILLBUSY: if (sactive != 0 || (host_pvt.sata_dwc_sactive_issued) > 1 || \ tag_mask > 1) { - dev_dbg(ap->dev, "%s NCQ:sactive=0x%08x sactive_issued=0x%08x" - "tag_mask=0x%08x\n", __func__, sactive, - host_pvt.sata_dwc_sactive_issued, tag_mask); + dev_dbg(ap->dev, + "%s NCQ:sactive=0x%08x sactive_issued=0x%08x tag_mask=0x%08x\n", + __func__, sactive, host_pvt.sata_dwc_sactive_issued, + tag_mask); } if ((tag_mask | (host_pvt.sata_dwc_sactive_issued)) != \ (host_pvt.sata_dwc_sactive_issued)) { - dev_warn(ap->dev, "Bad tag mask? sactive=0x%08x " - "(host_pvt.sata_dwc_sactive_issued)=0x%08x tag_mask" - "=0x%08x\n", sactive, host_pvt.sata_dwc_sactive_issued, - tag_mask); + dev_warn(ap->dev, + "Bad tag mask? sactive=0x%08x (host_pvt.sata_dwc_sactive_issued)=0x%08x tag_mask=0x%08x\n", + sactive, host_pvt.sata_dwc_sactive_issued, tag_mask); } /* read just to clear ... not bad if currently still busy */ @@ -1114,12 +630,12 @@ DRVSTILLBUSY: dev_dbg(ap->dev, "%s NCQ command, protocol: %s\n", __func__, get_prot_descript(qc->tf.protocol)); if (ata_is_dma(qc->tf.protocol)) { - host_pvt.dma_interrupt_count++; + hsdevp->dma_interrupt_count++; if (hsdevp->dma_pending[tag] == \ SATA_DWC_DMA_PENDING_NONE) dev_warn(ap->dev, "%s: DMA not pending?\n", __func__); - if ((host_pvt.dma_interrupt_count % 2) == 0) + if ((hsdevp->dma_interrupt_count % 2) == 0) sata_dwc_dma_xfer_complete(ap, 1); } else { if (unlikely(sata_dwc_qc_complete(ap, qc, 1))) @@ -1142,8 +658,9 @@ STILLBUSY: */ sactive2 = core_scr_read(SCR_ACTIVE); if (sactive2 != sactive) { - dev_dbg(ap->dev, "More completed - sactive=0x%x sactive2" - "=0x%x\n", sactive, sactive2); + dev_dbg(ap->dev, + "More completed - sactive=0x%x sactive2=0x%x\n", + sactive, sactive2); } handled = 1; @@ -1169,11 +686,10 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag) * This should not happen, it indicates the driver is out of * sync. If it does happen, clear dmacr anyway. */ - dev_err(host_pvt.dwc_dev, "%s DMA protocol RX and" - "TX DMA not pending tag=0x%02x pending=%d" - " dmacr: 0x%08x\n", __func__, tag, - hsdevp->dma_pending[tag], - in_le32(&(hsdev->sata_dwc_regs->dmacr))); + dev_err(hsdev->dev, + "%s DMA protocol RX and TX DMA not pending tag=0x%02x pending=%d dmacr: 0x%08x\n", + __func__, tag, hsdevp->dma_pending[tag], + in_le32(&hsdev->sata_dwc_regs->dmacr)); out_le32(&(hsdev->sata_dwc_regs->dmacr), SATA_DWC_DMACR_TXRXCH_CLEAR); } @@ -1195,8 +711,9 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status) #ifdef DEBUG_NCQ if (tag > 0) { - dev_info(ap->dev, "%s tag=%u cmd=0x%02x dma dir=%s proto=%s " - "dmacr=0x%08x\n", __func__, qc->tag, qc->tf.command, + dev_info(ap->dev, + "%s tag=%u cmd=0x%02x dma dir=%s proto=%s dmacr=0x%08x\n", + __func__, qc->tag, qc->tf.command, get_dma_dir_descript(qc->dma_dir), get_prot_descript(qc->tf.protocol), in_le32(&(hsdev->sata_dwc_regs->dmacr))); @@ -1205,8 +722,9 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status) if (ata_is_dma(qc->tf.protocol)) { if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_NONE) { - dev_err(ap->dev, "%s DMA protocol RX and TX DMA not " - "pending dmacr: 0x%08x\n", __func__, + dev_err(ap->dev, + "%s DMA protocol RX and TX DMA not pending dmacr: 0x%08x\n", + __func__, in_le32(&(hsdev->sata_dwc_regs->dmacr))); } @@ -1232,9 +750,9 @@ static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc, dev_err(ap->dev, "TX DMA PENDING\n"); else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_RX) dev_err(ap->dev, "RX DMA PENDING\n"); - dev_dbg(ap->dev, "QC complete cmd=0x%02x status=0x%02x ata%u:" - " protocol=%d\n", qc->tf.command, status, ap->print_id, - qc->tf.protocol); + dev_dbg(ap->dev, + "QC complete cmd=0x%02x status=0x%02x ata%u: protocol=%d\n", + qc->tf.command, status, ap->print_id, qc->tf.protocol); /* clear active bit */ mask = (~(qcmd_tag_to_mask(tag))); @@ -1260,11 +778,23 @@ static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev) */ out_le32(&hsdev->sata_dwc_regs->errmr, SATA_DWC_SERROR_ERR_BITS); - dev_dbg(host_pvt.dwc_dev, "%s: INTMR = 0x%08x, ERRMR = 0x%08x\n", + dev_dbg(hsdev->dev, "%s: INTMR = 0x%08x, ERRMR = 0x%08x\n", __func__, in_le32(&hsdev->sata_dwc_regs->intmr), in_le32(&hsdev->sata_dwc_regs->errmr)); } +static bool sata_dwc_dma_filter(struct dma_chan *chan, void *param) +{ + struct sata_dwc_device_port *hsdevp = param; + struct dw_dma_slave *dws = hsdevp->dws; + + if (dws->dma_dev != chan->device->dev) + return false; + + chan->private = dws; + return true; +} + static void sata_dwc_setup_port(struct ata_ioports *port, unsigned long base) { port->cmd_addr = (void __iomem *)base + 0x00; @@ -1299,6 +829,7 @@ static int sata_dwc_port_start(struct ata_port *ap) struct sata_dwc_device *hsdev; struct sata_dwc_device_port *hsdevp = NULL; struct device *pdev; + dma_cap_mask_t mask; int i; hsdev = HSDEV_FROM_AP(ap); @@ -1322,29 +853,27 @@ static int sata_dwc_port_start(struct ata_port *ap) } hsdevp->hsdev = hsdev; + hsdevp->dws = &sata_dwc_dma_dws; + hsdevp->dws->dma_dev = hsdev->dev; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + /* Acquire DMA channel */ + hsdevp->chan = dma_request_channel(mask, sata_dwc_dma_filter, hsdevp); + if (!hsdevp->chan) { + dev_err(hsdev->dev, "%s: dma channel unavailable\n", + __func__); + err = -EAGAIN; + goto CLEANUP_ALLOC; + } + for (i = 0; i < SATA_DWC_QCMD_MAX; i++) hsdevp->cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT; ap->bmdma_prd = NULL; /* set these so libata doesn't use them */ ap->bmdma_prd_dma = 0; - /* - * DMA - Assign scatter gather LLI table. We can't use the libata - * version since it's PRD is IDE PCI specific. - */ - for (i = 0; i < SATA_DWC_QCMD_MAX; i++) { - hsdevp->llit[i] = dma_alloc_coherent(pdev, - SATA_DWC_DMAC_LLI_TBL_SZ, - &(hsdevp->llit_dma[i]), - GFP_ATOMIC); - if (!hsdevp->llit[i]) { - dev_err(ap->dev, "%s: dma_alloc_coherent failed\n", - __func__); - err = -ENOMEM; - goto CLEANUP_ALLOC; - } - } - if (ap->port_no == 0) { dev_dbg(ap->dev, "%s: clearing TXCHEN, RXCHEN in DMAC\n", __func__); @@ -1373,22 +902,14 @@ CLEANUP: static void sata_dwc_port_stop(struct ata_port *ap) { - int i; - struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); dev_dbg(ap->dev, "%s: ap->id = %d\n", __func__, ap->print_id); - if (hsdevp && hsdev) { - /* deallocate LLI table */ - for (i = 0; i < SATA_DWC_QCMD_MAX; i++) { - dma_free_coherent(ap->host->dev, - SATA_DWC_DMAC_LLI_TBL_SZ, - hsdevp->llit[i], hsdevp->llit_dma[i]); - } + dmaengine_terminate_all(hsdevp->chan); + dma_release_channel(hsdevp->chan); - kfree(hsdevp); - } + kfree(hsdevp); ap->private_data = NULL; } @@ -1444,12 +965,12 @@ static void sata_dwc_bmdma_setup(struct ata_queued_cmd *qc) static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag) { int start_dma; - u32 reg, dma_chan; + u32 reg; struct sata_dwc_device *hsdev = HSDEV_FROM_QC(qc); struct ata_port *ap = qc->ap; struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); + struct dma_async_tx_descriptor *desc = hsdevp->desc[tag]; int dir = qc->dma_dir; - dma_chan = hsdevp->dma_chan[tag]; if (hsdevp->cmd_issued[tag] != SATA_DWC_CMD_ISSUED_NOT) { start_dma = 1; @@ -1458,16 +979,17 @@ static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag) else hsdevp->dma_pending[tag] = SATA_DWC_DMA_PENDING_RX; } else { - dev_err(ap->dev, "%s: Command not pending cmd_issued=%d " - "(tag=%d) DMA NOT started\n", __func__, - hsdevp->cmd_issued[tag], tag); + dev_err(ap->dev, + "%s: Command not pending cmd_issued=%d (tag=%d) DMA NOT started\n", + __func__, hsdevp->cmd_issued[tag], tag); start_dma = 0; } - dev_dbg(ap->dev, "%s qc=%p tag: %x cmd: 0x%02x dma_dir: %s " - "start_dma? %x\n", __func__, qc, tag, qc->tf.command, + dev_dbg(ap->dev, + "%s qc=%p tag: %x cmd: 0x%02x dma_dir: %s start_dma? %x\n", + __func__, qc, tag, qc->tf.command, get_dma_dir_descript(qc->dma_dir), start_dma); - sata_dwc_tf_dump(&(qc->tf)); + sata_dwc_tf_dump(ap, &qc->tf); if (start_dma) { reg = core_scr_read(SCR_ERROR); @@ -1484,7 +1006,8 @@ static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag) SATA_DWC_DMACR_RXCHEN); /* Enable AHB DMA transfer on the specified channel */ - dma_dwc_xfer_start(dma_chan); + dmaengine_submit(desc); + dma_async_issue_pending(hsdevp->chan); } } @@ -1510,26 +1033,21 @@ static void sata_dwc_bmdma_start(struct ata_queued_cmd *qc) */ static void sata_dwc_qc_prep_by_tag(struct ata_queued_cmd *qc, u8 tag) { - struct scatterlist *sg = qc->sg; + struct dma_async_tx_descriptor *desc; struct ata_port *ap = qc->ap; - int dma_chan; - struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); dev_dbg(ap->dev, "%s: port=%d dma dir=%s n_elem=%d\n", __func__, ap->port_no, get_dma_dir_descript(qc->dma_dir), qc->n_elem); - dma_chan = dma_dwc_xfer_setup(sg, qc->n_elem, hsdevp->llit[tag], - hsdevp->llit_dma[tag], - (void __iomem *)&hsdev->sata_dwc_regs->dmadr, - qc->dma_dir); - if (dma_chan < 0) { - dev_err(ap->dev, "%s: dma_dwc_xfer_setup returns err %d\n", - __func__, dma_chan); + desc = dma_dwc_xfer_setup(qc); + if (!desc) { + dev_err(ap->dev, "%s: dma_dwc_xfer_setup returns NULL\n", + __func__); return; } - hsdevp->dma_chan[tag] = dma_chan; + hsdevp->desc[tag] = desc; } static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) @@ -1540,8 +1058,8 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) #ifdef DEBUG_NCQ if (qc->tag > 0 || ap->link.sactive > 1) - dev_info(ap->dev, "%s ap id=%d cmd(0x%02x)=%s qc tag=%d " - "prot=%s ap active_tag=0x%08x ap sactive=0x%08x\n", + dev_info(ap->dev, + "%s ap id=%d cmd(0x%02x)=%s qc tag=%d prot=%s ap active_tag=0x%08x ap sactive=0x%08x\n", __func__, ap->print_id, qc->tf.command, ata_get_cmd_descript(qc->tf.command), qc->tag, get_prot_descript(qc->tf.protocol), @@ -1557,9 +1075,9 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) sactive |= (0x00000001 << tag); core_scr_write(SCR_ACTIVE, sactive); - dev_dbg(qc->ap->dev, "%s: tag=%d ap->link.sactive = 0x%08x " - "sactive=0x%08x\n", __func__, tag, qc->ap->link.sactive, - sactive); + dev_dbg(qc->ap->dev, + "%s: tag=%d ap->link.sactive = 0x%08x sactive=0x%08x\n", + __func__, tag, qc->ap->link.sactive, sactive); ap->ops->sff_tf_load(ap, &qc->tf); sata_dwc_exec_command_by_tag(ap, &qc->tf, qc->tag, @@ -1673,7 +1191,6 @@ static int sata_dwc_probe(struct platform_device *ofdev) struct ata_port_info pi = sata_dwc_port_info[0]; const struct ata_port_info *ppi[] = { &pi, NULL }; struct device_node *np = ofdev->dev.of_node; - u32 dma_chan; /* Allocate DWC SATA device */ host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_DWC_MAX_PORTS); @@ -1683,18 +1200,11 @@ static int sata_dwc_probe(struct platform_device *ofdev) host->private_data = hsdev; - if (of_property_read_u32(np, "dma-channel", &dma_chan)) { - dev_warn(&ofdev->dev, "no dma-channel property set." - " Use channel 0\n"); - dma_chan = 0; - } - host_pvt.dma_channel = dma_chan; - /* Ioremap SATA registers */ base = of_iomap(np, 0); if (!base) { - dev_err(&ofdev->dev, "ioremap failed for SATA register" - " address\n"); + dev_err(&ofdev->dev, + "ioremap failed for SATA register address\n"); return -ENODEV; } hsdev->reg_base = base; @@ -1716,27 +1226,29 @@ static int sata_dwc_probe(struct platform_device *ofdev) idr, ver[0], ver[1], ver[2]); /* Get SATA DMA interrupt number */ - irq = irq_of_parse_and_map(np, 1); - if (irq == NO_IRQ) { + hsdev->dma->irq = irq_of_parse_and_map(np, 1); + if (hsdev->dma->irq == NO_IRQ) { dev_err(&ofdev->dev, "no SATA DMA irq\n"); err = -ENODEV; goto error_iomap; } /* Get physical SATA DMA register base address */ - host_pvt.sata_dma_regs = (void *)of_iomap(np, 1); - if (!(host_pvt.sata_dma_regs)) { - dev_err(&ofdev->dev, "ioremap failed for AHBDMA register" - " address\n"); + hsdev->dma->regs = of_iomap(np, 1); + if (!hsdev->dma->regs) { + dev_err(&ofdev->dev, + "ioremap failed for AHBDMA register address\n"); err = -ENODEV; goto error_iomap; } /* Save dev for later use in dev_xxx() routines */ - host_pvt.dwc_dev = &ofdev->dev; + hsdev->dev = &ofdev->dev; + + hsdev->dma->dev = &ofdev->dev; /* Initialize AHB DMAC */ - err = dma_dwc_init(hsdev, irq); + err = dw_dma_probe(hsdev->dma, NULL); if (err) goto error_dma_iomap; @@ -1765,9 +1277,9 @@ static int sata_dwc_probe(struct platform_device *ofdev) error_out: /* Free SATA DMA resources */ - dma_dwc_exit(hsdev); + dw_dma_remove(hsdev->dma); error_dma_iomap: - iounmap((void __iomem *)host_pvt.sata_dma_regs); + iounmap(hsdev->dma->regs); error_iomap: iounmap(base); return err; @@ -1782,9 +1294,9 @@ static int sata_dwc_remove(struct platform_device *ofdev) ata_host_detach(host); /* Free SATA DMA resources */ - dma_dwc_exit(hsdev); + dw_dma_remove(hsdev->dma); - iounmap((void __iomem *)host_pvt.sata_dma_regs); + iounmap(hsdev->dma->regs); iounmap(hsdev->reg_base); dev_dbg(&ofdev->dev, "done\n"); return 0; @@ -1809,5 +1321,5 @@ module_platform_driver(sata_dwc_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Mark Miesfeld <mmiesfeld@amcc.com>"); -MODULE_DESCRIPTION("DesignWare Cores SATA controller low lever driver"); +MODULE_DESCRIPTION("DesignWare Cores SATA controller low level driver"); MODULE_VERSION(DRV_VERSION); diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index f9054cd36a72..5389579c5120 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -869,6 +869,8 @@ try_offline_again: */ ata_msleep(ap, 1); + sata_set_spd(link); + /* * Now, bring the host controller online again, this can take time * as PHY reset and communication establishment, 1st D2H FIS and diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 069827826b20..e81a8217f1ff 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -856,13 +856,13 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } /* Set dma_mask. This devices doesn't support 64bit addressing. */ - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit DMA enable failed\n"); return rc; } - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n"); return rc; diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index f8c33e3772b8..bd74ee555278 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -306,6 +306,11 @@ enum { MV5_PHY_CTL = 0x0C, SATA_IFCFG = 0x050, LP_PHY_CTL = 0x058, + LP_PHY_CTL_PIN_PU_PLL = (1 << 0), + LP_PHY_CTL_PIN_PU_RX = (1 << 1), + LP_PHY_CTL_PIN_PU_TX = (1 << 2), + LP_PHY_CTL_GEN_TX_3G = (1 << 5), + LP_PHY_CTL_GEN_RX_3G = (1 << 9), MV_M2_PREAMP_MASK = 0x7e0, @@ -1391,10 +1396,17 @@ static int mv_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val) /* * Set PHY speed according to SControl speed. */ - if ((val & 0xf0) == 0x10) - writelfl(0x7, lp_phy_addr); - else - writelfl(0x227, lp_phy_addr); + u32 lp_phy_val = + LP_PHY_CTL_PIN_PU_PLL | + LP_PHY_CTL_PIN_PU_RX | + LP_PHY_CTL_PIN_PU_TX; + + if ((val & 0xf0) != 0x10) + lp_phy_val |= + LP_PHY_CTL_GEN_TX_3G | + LP_PHY_CTL_GEN_RX_3G; + + writelfl(lp_phy_val, lp_phy_addr); } } writelfl(val, addr); @@ -4308,10 +4320,10 @@ static int pci_go_64(struct pci_dev *pdev) { int rc; - if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); if (rc) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "64-bit DMA enable failed\n"); @@ -4319,12 +4331,12 @@ static int pci_go_64(struct pci_dev *pdev) } } } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit DMA enable failed\n"); return rc; } - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n"); diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 1db6f5ce5e89..7ece85f43020 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -756,10 +756,10 @@ static int nv_adma_slave_config(struct scsi_device *sdev) blk_queue_bounce_limit(sdev1->request_queue, ATA_DMA_MASK); - pci_set_dma_mask(pdev, ATA_DMA_MASK); + dma_set_mask(&pdev->dev, ATA_DMA_MASK); } else { /** This shouldn't fail as it was set to this value before */ - pci_set_dma_mask(pdev, pp->adma_dma_mask); + dma_set_mask(&pdev->dev, pp->adma_dma_mask); if (sdev0) blk_queue_bounce_limit(sdev0->request_queue, pp->adma_dma_mask); @@ -1133,10 +1133,10 @@ static int nv_adma_port_start(struct ata_port *ap) /* Ensure DMA mask is set to 32-bit before allocating legacy PRD and pad buffers */ - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) return rc; @@ -1161,8 +1161,8 @@ static int nv_adma_port_start(struct ata_port *ap) These are allowed to fail since we store the value that ends up being used to set as the bounce limit in slave_config later if needed. */ - pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); - pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); + dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); pp->adma_dma_mask = *dev->dma_mask; mem = dmam_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ, diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 3638887476f6..0fa211e2831c 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -1246,10 +1246,10 @@ static int pdc_ata_init_one(struct pci_dev *pdev, /* initialize adapter */ pdc_host_init(host); - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index 9a6bd4cd29a0..af987a4f33d1 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -557,10 +557,10 @@ static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base) int rc, have_64bit_bus = (bus_info & QS_HPHY_64BIT); if (have_64bit_bus && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); if (rc) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "64-bit DMA enable failed\n"); @@ -568,12 +568,12 @@ static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base) } } } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit DMA enable failed\n"); return rc; } - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n"); diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 40b76b2d18c6..dea6edcbf145 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -770,10 +770,10 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return rc; host->iomap = pcim_iomap_table(pdev); - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index ba2667fa0528..4b1995e2d044 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -246,7 +246,7 @@ enum { /* host flags */ SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA | ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA | - ATA_FLAG_AN | ATA_FLAG_PMP | ATA_FLAG_LOWTAG, + ATA_FLAG_AN | ATA_FLAG_PMP, SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ IRQ_STAT_4PORTS = 0xf, @@ -1312,10 +1312,10 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) host->iomap = iomap; /* configure and activate the device */ - if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); if (rc) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "64-bit DMA enable failed\n"); @@ -1323,12 +1323,12 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } } } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit DMA enable failed\n"); return rc; } - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n"); diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index c630fa812624..ff614be55d0f 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -47,11 +47,7 @@ #include <scsi/scsi_cmnd.h> #include <scsi/scsi.h> #include <linux/libata.h> - -#ifdef CONFIG_PPC_OF -#include <asm/prom.h> -#include <asm/pci-bridge.h> -#endif /* CONFIG_PPC_OF */ +#include <linux/of.h> #define DRV_NAME "sata_svw" #define DRV_VERSION "2.3" @@ -320,7 +316,6 @@ static u8 k2_stat_check_status(struct ata_port *ap) return readl(ap->ioaddr.status_addr); } -#ifdef CONFIG_PPC_OF static int k2_sata_show_info(struct seq_file *m, struct Scsi_Host *shost) { struct ata_port *ap; @@ -350,14 +345,10 @@ static int k2_sata_show_info(struct seq_file *m, struct Scsi_Host *shost) } return 0; } -#endif /* CONFIG_PPC_OF */ - static struct scsi_host_template k2_sata_sht = { ATA_BMDMA_SHT(DRV_NAME), -#ifdef CONFIG_PPC_OF .show_info = k2_sata_show_info, -#endif }; @@ -496,10 +487,10 @@ static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *en ata_port_pbar_desc(ap, 5, offset, "port"); } - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index 39b5de60a1f9..3a18a8a719b4 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -1476,10 +1476,10 @@ static int pdc_sata_init_one(struct pci_dev *pdev, } /* configure and activate */ - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 47bf89464cef..17d31fc009ab 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -502,10 +502,10 @@ static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) for (i = 0; i < host->n_ports; i++) vt6421_init_addrs(host->ports[i]); - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c index 29e847aac34b..183eb52085df 100644 --- a/drivers/ata/sata_vsc.c +++ b/drivers/ata/sata_vsc.c @@ -387,10 +387,10 @@ static int vsc_sata_init_one(struct pci_dev *pdev, /* * Use 32 bit DMA mask, because 64 bit address support is poor. */ - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) return rc; |