diff options
Diffstat (limited to 'drivers/ata')
32 files changed, 690 insertions, 819 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, |