From d7372cb6290eedadcf2d191b033388df3c0c39f2 Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Sat, 23 Jul 2016 02:34:08 +0800 Subject: libata-scsi: use u8 array to store mode page copy ata_mselect_*() would initialize a char array for storing a copy of the current mode page. However, char could be signed char. In that case, bytes larger than 127 would be converted to negative number. For example, 0xff from def_control_mpage[] would become -1. This prevented ata_mselect_control() from working at all, since when it did the read-only bits check, there would always be a mismatch. Signed-off-by: Tom Yan Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index e207b33..0bc4532 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3610,7 +3610,7 @@ static int ata_mselect_caching(struct ata_queued_cmd *qc, { struct ata_taskfile *tf = &qc->tf; struct ata_device *dev = qc->dev; - char mpage[CACHE_MPAGE_LEN]; + u8 mpage[CACHE_MPAGE_LEN]; u8 wce; int i; @@ -3666,7 +3666,7 @@ static int ata_mselect_control(struct ata_queued_cmd *qc, const u8 *buf, int len, u16 *fp) { struct ata_device *dev = qc->dev; - char mpage[CONTROL_MPAGE_LEN]; + u8 mpage[CONTROL_MPAGE_LEN]; u8 d_sense; int i; -- cgit v0.10.2 From 535fd072202dbc8afe5a4093178132bdd4ac2424 Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Fri, 22 Jul 2016 02:41:54 +0800 Subject: libata-scsi: fix MODE SELECT translation for Control mode page scsi_done() was called repeatedly and apparently because of that, the kernel would call trace when we touch the Control mode page: Call Trace: [] dump_stack+0x63/0x81 [] __warn+0xcb/0xf0 [] warn_slowpath_null+0x1d/0x20 [] ata_eh_finish+0xe0/0xf0 [libata] [] sata_pmp_error_handler+0x640/0xa50 [libata] [] ahci_error_handler+0x1d/0x70 [libahci] [] ata_scsi_port_error_handler+0x430/0x770 [libata] [] ? ata_scsi_cmd_error_handler+0xdd/0x160 [libata] [] ata_scsi_error+0xa7/0xf0 [libata] [] scsi_error_handler+0xaa/0x560 [scsi_mod] [] ? scsi_eh_get_sense+0x180/0x180 [scsi_mod] [] kthread+0xd8/0xf0 [] ret_from_fork+0x1f/0x40 [] ? kthread_worker_fn+0x170/0x170 ---[ end trace 8b7501047e928a17 ]--- Removed the unnecessary code and let ata_scsi_translate() do the job. Also, since ata_mselect_control() has no ATA command to send to the device, ata_scsi_mode_select_xlat() should return 1 for it, so that ata_scsi_translate() will finish early to avoid ata_qc_issue(). Signed-off-by: Tom Yan Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 0bc4532..be9c76c 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3701,8 +3701,6 @@ static int ata_mselect_control(struct ata_queued_cmd *qc, dev->flags |= ATA_DFLAG_D_SENSE; else dev->flags &= ~ATA_DFLAG_D_SENSE; - qc->scsicmd->result = SAM_STAT_GOOD; - qc->scsicmd->scsi_done(qc->scsicmd); return 0; } @@ -3829,6 +3827,8 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) if (ata_mselect_control(qc, p, pg_len, &fp) < 0) { fp += hdr_len + bd_len; goto invalid_param; + } else { + goto skip; /* No ATA command to send */ } break; default: /* invalid page code */ -- cgit v0.10.2 From 107a077d19341b4d47ae06f0bd24883b94e64628 Mon Sep 17 00:00:00 2001 From: Tang Yuantian Date: Tue, 9 Aug 2016 09:51:21 +0800 Subject: ahci: qoriq: adjust sata parameter The default values for Port Phy2Cfg register and Port Phy3Cfg register are better, no need to overwrite them. Signed-off-by: Tang Yuantian Signed-off-by: Tejun Heo diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c index 7bdee9b..ed357a1 100644 --- a/drivers/ata/ahci_qoriq.c +++ b/drivers/ata/ahci_qoriq.c @@ -44,10 +44,6 @@ #define SATA_ECC_DISABLE 0x00020000 -/* for ls1043a */ -#define LS1043A_PORT_PHY2 0x28184d1f -#define LS1043A_PORT_PHY3 0x0e081509 - enum ahci_qoriq_type { AHCI_LS1021A, AHCI_LS1043A, @@ -166,8 +162,6 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv) case AHCI_LS1043A: writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1); - writel(LS1043A_PORT_PHY2, reg_base + PORT_PHY2); - writel(LS1043A_PORT_PHY3, reg_base + PORT_PHY3); writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS); break; -- cgit v0.10.2 From 16af080e47785d14919bf94bf8a4097c5c8529fb Mon Sep 17 00:00:00 2001 From: Tang Yuantian Date: Tue, 9 Aug 2016 09:51:22 +0800 Subject: ahci: qoriq: enable snoopable sata read and write By default the SATA IP on the qoriq SoCs does not generating coherent/snoopable transactions. This patch enable it in the sata axicc register. In addition, the dma-coherent property must be set on the SATA controller nodes. Signed-off-by: Tang Yuantian Signed-off-by: Tejun Heo diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi index e669fbd..e8e4c3e 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi @@ -495,10 +495,11 @@ }; sata: sata@3200000 { - compatible = "fsl,ls1043a-ahci", "fsl,ls1021a-ahci"; + compatible = "fsl,ls1043a-ahci"; reg = <0x0 0x3200000 0x0 0x10000>; interrupts = <0 69 0x4>; clocks = <&clockgen 4 0>; + dma-coherent; }; msi1: msi-controller1@1571000 { diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi index 21023a3..5ead17c 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi @@ -679,6 +679,7 @@ reg = <0x0 0x3200000 0x0 0x10000>; interrupts = <0 133 0x4>; /* Level high type */ clocks = <&clockgen 4 3>; + dma-coherent; }; sata1: sata@3210000 { @@ -687,6 +688,7 @@ reg = <0x0 0x3210000 0x0 0x10000>; interrupts = <0 136 0x4>; /* Level high type */ clocks = <&clockgen 4 3>; + dma-coherent; }; usb0: usb3@3100000 { diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c index ed357a1..925c4b6 100644 --- a/drivers/ata/ahci_qoriq.c +++ b/drivers/ata/ahci_qoriq.c @@ -30,17 +30,20 @@ #define PORT_PHY3 0xB0 #define PORT_PHY4 0xB4 #define PORT_PHY5 0xB8 +#define PORT_AXICC 0xBC #define PORT_TRANS 0xC8 /* port register default value */ #define AHCI_PORT_PHY_1_CFG 0xa003fffe #define AHCI_PORT_TRANS_CFG 0x08000029 +#define AHCI_PORT_AXICC_CFG 0x3fffffff /* for ls1021a */ #define LS1021A_PORT_PHY2 0x28183414 #define LS1021A_PORT_PHY3 0x0e080e06 #define LS1021A_PORT_PHY4 0x064a080b #define LS1021A_PORT_PHY5 0x2aa86470 +#define LS1021A_AXICC_ADDR 0xC0 #define SATA_ECC_DISABLE 0x00020000 @@ -158,16 +161,19 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv) writel(LS1021A_PORT_PHY4, reg_base + PORT_PHY4); writel(LS1021A_PORT_PHY5, reg_base + PORT_PHY5); writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS); + writel(AHCI_PORT_AXICC_CFG, reg_base + LS1021A_AXICC_ADDR); break; case AHCI_LS1043A: writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1); writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS); + writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC); break; case AHCI_LS2080A: writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1); writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS); + writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC); break; } -- cgit v0.10.2 From e7190699ca8c8daa52bfc62c01a71dea6decc9ee Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Wed, 10 Aug 2016 17:37:29 +0200 Subject: ahci: st: Add ports-implemented property in support Despite ST AHCI version = 1.3, reading HOST_PORTS_IMPL returns 0. So force_port_map to 1 by using ports-implemented DT property. Signed-off-by: Patrice Chotard Signed-off-by: Tejun Heo diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c index 8ff428f..bc345f2 100644 --- a/drivers/ata/ahci_st.c +++ b/drivers/ata/ahci_st.c @@ -147,6 +147,7 @@ static struct scsi_host_template ahci_platform_sht = { static int st_ahci_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct st_ahci_drv_data *drv_data; struct ahci_host_priv *hpriv; int err; @@ -170,6 +171,9 @@ static int st_ahci_probe(struct platform_device *pdev) st_ahci_configure_oob(hpriv->mmio); + of_property_read_u32(dev->of_node, + "ports-implemented", &hpriv->force_port_map); + err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info, &ahci_platform_sht); if (err) { -- cgit v0.10.2 From b55d2c847454d197a7cf5ce2e1c175b080012184 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Wed, 10 Aug 2016 17:37:30 +0200 Subject: ARM: dts: STiH407-family: Add ports-implemented property in sata nodes Despite ST AHCI version = 1.3, reading HOST_PORTS_IMPL returns 0. So force HOST_PORTS_IMPL to 1 by using ports-implemented DT property. Signed-off-by: Patrice Chotard Signed-off-by: Tejun Heo diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index d294e82..36d40f0 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -608,6 +608,8 @@ clock-names = "ahci_clk"; clocks = <&clk_s_c0_flexgen CLK_ICN_REG>; + ports-implemented = <0x1>; + status = "disabled"; }; @@ -631,6 +633,8 @@ clock-names = "ahci_clk"; clocks = <&clk_s_c0_flexgen CLK_ICN_REG>; + ports-implemented = <0x1>; + status = "disabled"; }; -- cgit v0.10.2 From cd27396e6103a43c3df76f70db1feafa16206471 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 11 Aug 2016 07:26:02 -0700 Subject: ahci: also use a per-port lock for the multi-MSIX case Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 7461a58..7c01192 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -2378,7 +2378,7 @@ static int ahci_port_start(struct ata_port *ap) /* * Switch to per-port locking in case each port has its own MSI vector. */ - if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) { + if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX)) { spin_lock_init(&pp->lock); ap->lock = &pp->lock; } -- cgit v0.10.2 From 9379e6b8e0f995365dc6158a1463c8dab4f2c8da Mon Sep 17 00:00:00 2001 From: Shaun Tancheff Date: Sun, 21 Aug 2016 23:23:18 -0500 Subject: libata: Safely overwrite attached page in WRITE SAME xlat Safely overwriting the attached page to ATA format from the SCSI formatted variant. Signed-off-by: Shaun Tancheff Reviewed-by: Hannes Reinecke Acked-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index be9c76c..84e7f48 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3282,6 +3282,54 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) return 1; } +/** + * ata_format_dsm_trim_descr() - SATL Write Same to DSM Trim + * @cmd: SCSI command being translated + * @num: Maximum number of entries (nominally 64). + * @sector: Starting sector + * @count: Total Range of request + * + * Rewrite the WRITE SAME descriptor to be a DSM TRIM little-endian formatted + * descriptor. + * + * Upto 64 entries of the format: + * 63:48 Range Length + * 47:0 LBA + * + * Range Length of 0 is ignored. + * LBA's should be sorted order and not overlap. + * + * NOTE: this is the same format as ADD LBA(S) TO NV CACHE PINNED SET + */ +static unsigned int ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 num, + u64 sector, u32 count) +{ + __le64 *buffer; + u32 i = 0, used_bytes; + unsigned long flags; + + BUILD_BUG_ON(512 > ATA_SCSI_RBUF_SIZE); + + spin_lock_irqsave(&ata_scsi_rbuf_lock, flags); + buffer = ((void *)ata_scsi_rbuf); + while (i < num) { + u64 entry = sector | + ((u64)(count > 0xffff ? 0xffff : count) << 48); + buffer[i++] = __cpu_to_le64(entry); + if (count <= 0xffff) + break; + count -= 0xffff; + sector += 0xffff; + } + + used_bytes = ALIGN(i * 8, 512); + memset(buffer + i, 0, used_bytes - i * 8); + sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buffer, 512); + spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags); + + return used_bytes; +} + static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) { struct ata_taskfile *tf = &qc->tf; @@ -3290,8 +3338,8 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) const u8 *cdb = scmd->cmnd; u64 block; u32 n_block; + const u32 trmax = ATA_MAX_TRIM_RNUM; u32 size; - void *buf; u16 fp; u8 bp = 0xff; @@ -3319,10 +3367,8 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) if (!scsi_sg_count(scmd)) goto invalid_param_len; - buf = page_address(sg_page(scsi_sglist(scmd))); - - if (n_block <= 65535 * ATA_MAX_TRIM_RNUM) { - size = ata_set_lba_range_entries(buf, ATA_MAX_TRIM_RNUM, block, n_block); + if (n_block <= 0xffff * trmax) { + size = ata_format_dsm_trim_descr(scmd, trmax, block, n_block); } else { fp = 2; goto invalid_fld; diff --git a/include/linux/ata.h b/include/linux/ata.h index adbc812..45a1d71 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -1071,32 +1071,6 @@ static inline void ata_id_to_hd_driveid(u16 *id) #endif } -/* - * Write LBA Range Entries to the buffer that will cover the extent from - * sector to sector + count. This is used for TRIM and for ADD LBA(S) - * TO NV CACHE PINNED SET. - */ -static inline unsigned ata_set_lba_range_entries(void *_buffer, - unsigned num, u64 sector, unsigned long count) -{ - __le64 *buffer = _buffer; - unsigned i = 0, used_bytes; - - while (i < num) { - u64 entry = sector | - ((u64)(count > 0xffff ? 0xffff : count) << 48); - buffer[i++] = __cpu_to_le64(entry); - if (count <= 0xffff) - break; - count -= 0xffff; - sector += 0xffff; - } - - used_bytes = ALIGN(i * 8, 512); - memset(buffer + i, 0, used_bytes - i * 8); - return used_bytes; -} - static inline bool ata_ok(u8 status) { return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR)) -- cgit v0.10.2 From 7b20309428598df00ffeb0b01f5948dea6aaf1f7 Mon Sep 17 00:00:00 2001 From: Shaun Tancheff Date: Sun, 21 Aug 2016 23:23:19 -0500 Subject: libata: Add support for SCT Write Same SATA drives may support write same via SCT. This is useful for setting the drive contents to a specific pattern (0's). Translate a SCSI WRITE SAME 16 command to be either a DSM TRIM command or an SCT Write Same command. Based on the UNMAP flag: - When set translate to DSM TRIM - When not set translate to SCT Write Same Signed-off-by: Shaun Tancheff Reviewed-by: Hannes Reinecke Acked-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 84e7f48..08d9c8e 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1159,8 +1159,6 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev) { sdev->use_10_for_rw = 1; sdev->use_10_for_ms = 1; - sdev->no_report_opcodes = 1; - sdev->no_write_same = 1; /* Schedule policy is determined by ->qc_defer() callback and * it needs to see every deferred qc. Set dev_blocked to 1 to @@ -3287,7 +3285,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) * @cmd: SCSI command being translated * @num: Maximum number of entries (nominally 64). * @sector: Starting sector - * @count: Total Range of request + * @count: Total Range of request in logical sectors * * Rewrite the WRITE SAME descriptor to be a DSM TRIM little-endian formatted * descriptor. @@ -3330,6 +3328,45 @@ static unsigned int ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 num, return used_bytes; } +/** + * ata_format_dsm_trim_descr() - SATL Write Same to ATA SCT Write Same + * @cmd: SCSI command being translated + * @lba: Starting sector + * @num: Number of logical sectors to be zero'd. + * + * Rewrite the WRITE SAME descriptor to be an SCT Write Same formatted + * descriptor. + * NOTE: Writes a pattern (0's) in the foreground. + * Large write-same requents can timeout. + */ +static void ata_format_sct_write_same(struct scsi_cmnd *cmd, u64 lba, u64 num) +{ + u16 *sctpg; + unsigned long flags; + + spin_lock_irqsave(&ata_scsi_rbuf_lock, flags); + sctpg = ((void *)ata_scsi_rbuf); + + put_unaligned_le16(0x0002, &sctpg[0]); /* SCT_ACT_WRITE_SAME */ + put_unaligned_le16(0x0101, &sctpg[1]); /* WRITE PTRN FG */ + put_unaligned_le64(lba, &sctpg[2]); + put_unaligned_le64(num, &sctpg[6]); + put_unaligned_le32(0u, &sctpg[10]); + + sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), sctpg, 512); + spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags); +} + +/** + * ata_scsi_write_same_xlat() - SATL Write Same to ATA SCT Write Same + * @qc: Command to be translated + * + * Translate a SCSI WRITE SAME command to be either a DSM TRIM command or + * an SCT Write Same command. + * Based on WRITE SAME has the UNMAP flag + * When set translate to DSM TRIM + * When clear translate to SCT Write Same + */ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) { struct ata_taskfile *tf = &qc->tf; @@ -3342,6 +3379,7 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) u32 size; u16 fp; u8 bp = 0xff; + u8 unmap = cdb[1] & 0x8; /* we may not issue DMA commands if no DMA mode is set */ if (unlikely(!dev->dma_mode)) @@ -3353,11 +3391,26 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) } scsi_16_lba_len(cdb, &block, &n_block); - /* for now we only support WRITE SAME with the unmap bit set */ - if (unlikely(!(cdb[1] & 0x8))) { - fp = 1; - bp = 3; - goto invalid_fld; + if (unmap) { + /* If trim is not enabled the cmd is invalid. */ + if ((dev->horkage & ATA_HORKAGE_NOTRIM) || + !ata_id_has_trim(dev->id)) { + fp = 1; + bp = 3; + goto invalid_fld; + } + /* If the request is too large the cmd is invalid */ + if (n_block > 0xffff * trmax) { + fp = 2; + goto invalid_fld; + } + } else { + /* If write same is not available the cmd is invalid */ + if (!ata_id_sct_write_same(dev->id)) { + fp = 1; + bp = 3; + goto invalid_fld; + } } /* @@ -3367,30 +3420,42 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) if (!scsi_sg_count(scmd)) goto invalid_param_len; - if (n_block <= 0xffff * trmax) { + if (unmap) { size = ata_format_dsm_trim_descr(scmd, trmax, block, n_block); + if (ata_ncq_enabled(dev) && ata_fpdma_dsm_supported(dev)) { + /* Newer devices support queued TRIM commands */ + tf->protocol = ATA_PROT_NCQ; + tf->command = ATA_CMD_FPDMA_SEND; + tf->hob_nsect = ATA_SUBCMD_FPDMA_SEND_DSM & 0x1f; + tf->nsect = qc->tag << 3; + tf->hob_feature = (size / 512) >> 8; + tf->feature = size / 512; + + tf->auxiliary = 1; + } else { + tf->protocol = ATA_PROT_DMA; + tf->hob_feature = 0; + tf->feature = ATA_DSM_TRIM; + tf->hob_nsect = (size / 512) >> 8; + tf->nsect = size / 512; + tf->command = ATA_CMD_DSM; + } } else { - fp = 2; - goto invalid_fld; - } - - if (ata_ncq_enabled(dev) && ata_fpdma_dsm_supported(dev)) { - /* Newer devices support queued TRIM commands */ - tf->protocol = ATA_PROT_NCQ; - tf->command = ATA_CMD_FPDMA_SEND; - tf->hob_nsect = ATA_SUBCMD_FPDMA_SEND_DSM & 0x1f; - tf->nsect = qc->tag << 3; - tf->hob_feature = (size / 512) >> 8; - tf->feature = size / 512; + ata_format_sct_write_same(scmd, block, n_block); - tf->auxiliary = 1; - } else { - tf->protocol = ATA_PROT_DMA; tf->hob_feature = 0; - tf->feature = ATA_DSM_TRIM; - tf->hob_nsect = (size / 512) >> 8; - tf->nsect = size / 512; - tf->command = ATA_CMD_DSM; + tf->feature = 0; + tf->hob_nsect = 0; + tf->nsect = 1; + tf->lbah = 0; + tf->lbam = 0; + tf->lbal = ATA_CMD_STANDBYNOW1; + tf->hob_lbah = 0; + tf->hob_lbam = 0; + tf->hob_lbal = 0; + tf->device = ATA_CMD_STANDBYNOW1; + tf->protocol = ATA_PROT_DMA; + tf->command = ATA_CMD_WRITE_LOG_DMA_EXT; } tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48 | @@ -3414,6 +3479,76 @@ invalid_opcode: } /** + * ata_scsiop_maint_in - Simulate a subset of MAINTENANCE_IN + * @args: device MAINTENANCE_IN data / SCSI command of interest. + * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. + * + * Yields a subset to satisfy scsi_report_opcode() + * + * LOCKING: + * spin_lock_irqsave(host lock) + */ +static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) +{ + struct ata_device *dev = args->dev; + u8 *cdb = args->cmd->cmnd; + u8 supported = 0; + unsigned int err = 0; + + if (cdb[2] != 1) { + ata_dev_warn(dev, "invalid command format %d\n", cdb[2]); + err = 2; + goto out; + } + switch (cdb[3]) { + case INQUIRY: + case MODE_SENSE: + case MODE_SENSE_10: + case READ_CAPACITY: + case SERVICE_ACTION_IN_16: + case REPORT_LUNS: + case REQUEST_SENSE: + case SYNCHRONIZE_CACHE: + case REZERO_UNIT: + case SEEK_6: + case SEEK_10: + case TEST_UNIT_READY: + case SEND_DIAGNOSTIC: + case MAINTENANCE_IN: + case READ_6: + case READ_10: + case READ_16: + case WRITE_6: + case WRITE_10: + case WRITE_16: + case ATA_12: + case ATA_16: + case VERIFY: + case VERIFY_16: + case MODE_SELECT: + case MODE_SELECT_10: + case START_STOP: + supported = 3; + break; + case WRITE_SAME_16: + if (ata_id_sct_write_same(dev->id)) + supported = 3; + break; + case ZBC_IN: + case ZBC_OUT: + if (ata_id_zoned_cap(dev->id) || + dev->class == ATA_DEV_ZAC) + supported = 3; + break; + default: + break; + } +out: + rbuf[1] = supported; /* supported */ + return err; +} + +/** * ata_scsi_report_zones_complete - convert ATA output * @qc: command structure returning the data * @@ -4193,6 +4328,13 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) ata_scsi_invalid_field(dev, cmd, 1); break; + case MAINTENANCE_IN: + if (scsicmd[1] == MI_REPORT_SUPPORTED_OPERATION_CODES) + ata_scsi_rbuf_fill(&args, ata_scsiop_maint_in); + else + ata_scsi_invalid_field(dev, cmd, 1); + break; + /* all other commands */ default: ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x20, 0x0); @@ -4225,7 +4367,6 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht) shost->max_lun = 1; shost->max_channel = 1; shost->max_cmd_len = 16; - shost->no_write_same = 1; /* Schedule policy is determined by ->qc_defer() * callback and it needs to see every deferred qc. diff --git a/include/linux/ata.h b/include/linux/ata.h index 45a1d71..fdb1803 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -105,6 +105,7 @@ enum { ATA_ID_CFA_KEY_MGMT = 162, ATA_ID_CFA_MODES = 163, ATA_ID_DATA_SET_MGMT = 169, + ATA_ID_SCT_CMD_XPORT = 206, ATA_ID_ROT_SPEED = 217, ATA_ID_PIO4 = (1 << 1), @@ -789,6 +790,48 @@ static inline bool ata_id_sense_reporting_enabled(const u16 *id) } /** + * + * Word: 206 - SCT Command Transport + * 15:12 - Vendor Specific + * 11:6 - Reserved + * 5 - SCT Command Transport Data Tables supported + * 4 - SCT Command Transport Features Control supported + * 3 - SCT Command Transport Error Recovery Control supported + * 2 - SCT Command Transport Write Same supported + * 1 - SCT Command Transport Long Sector Access supported + * 0 - SCT Command Transport supported + */ +static inline bool ata_id_sct_data_tables(const u16 *id) +{ + return id[ATA_ID_SCT_CMD_XPORT] & (1 << 5) ? true : false; +} + +static inline bool ata_id_sct_features_ctrl(const u16 *id) +{ + return id[ATA_ID_SCT_CMD_XPORT] & (1 << 4) ? true : false; +} + +static inline bool ata_id_sct_error_recovery_ctrl(const u16 *id) +{ + return id[ATA_ID_SCT_CMD_XPORT] & (1 << 3) ? true : false; +} + +static inline bool ata_id_sct_write_same(const u16 *id) +{ + return id[ATA_ID_SCT_CMD_XPORT] & (1 << 2) ? true : false; +} + +static inline bool ata_id_sct_long_sector_access(const u16 *id) +{ + return id[ATA_ID_SCT_CMD_XPORT] & (1 << 1) ? true : false; +} + +static inline bool ata_id_sct_supported(const u16 *id) +{ + return id[ATA_ID_SCT_CMD_XPORT] & (1 << 0) ? true : false; +} + +/** * ata_id_major_version - get ATA level of drive * @id: Identify data * -- cgit v0.10.2 From ef2d7392c4ece5c3cd12a6c7ca9366cd8f189aff Mon Sep 17 00:00:00 2001 From: Shaun Tancheff Date: Wed, 24 Aug 2016 13:08:14 -0500 Subject: libata: SCT Write Same / DSM Trim Correct handling of devices with sector_size other that 512 bytes. In the case of a 4Kn device sector_size it is possible to describe a much larger DSM Trim than the current fixed default of 512 bytes. This patch assumes the minimum descriptor is sector_size and fills out the descriptor accordingly. The ACS-2 specification is quite clear that the DSM command payload is sized as number of 512 byte transfers so a 4Kn device will operate correctly without this patch. Signed-off-by: Shaun Tancheff Acked-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 08d9c8e..35b1f9e 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3283,7 +3283,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) /** * ata_format_dsm_trim_descr() - SATL Write Same to DSM Trim * @cmd: SCSI command being translated - * @num: Maximum number of entries (nominally 64). + * @trmax: Maximum number of entries that will fit in sector_size bytes. * @sector: Starting sector * @count: Total Range of request in logical sectors * @@ -3298,63 +3298,80 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) * LBA's should be sorted order and not overlap. * * NOTE: this is the same format as ADD LBA(S) TO NV CACHE PINNED SET + * + * Return: Number of bytes copied into sglist. */ -static unsigned int ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 num, - u64 sector, u32 count) +static size_t ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 trmax, + u64 sector, u32 count) { - __le64 *buffer; - u32 i = 0, used_bytes; + struct scsi_device *sdp = cmd->device; + size_t len = sdp->sector_size; + size_t r; + __le64 *buf; + u32 i = 0; unsigned long flags; - BUILD_BUG_ON(512 > ATA_SCSI_RBUF_SIZE); + WARN_ON(len > ATA_SCSI_RBUF_SIZE); + + if (len > ATA_SCSI_RBUF_SIZE) + len = ATA_SCSI_RBUF_SIZE; spin_lock_irqsave(&ata_scsi_rbuf_lock, flags); - buffer = ((void *)ata_scsi_rbuf); - while (i < num) { + buf = ((void *)ata_scsi_rbuf); + memset(buf, 0, len); + while (i < trmax) { u64 entry = sector | ((u64)(count > 0xffff ? 0xffff : count) << 48); - buffer[i++] = __cpu_to_le64(entry); + buf[i++] = __cpu_to_le64(entry); if (count <= 0xffff) break; count -= 0xffff; sector += 0xffff; } - - used_bytes = ALIGN(i * 8, 512); - memset(buffer + i, 0, used_bytes - i * 8); - sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buffer, 512); + r = sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf, len); spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags); - return used_bytes; + return r; } /** * ata_format_dsm_trim_descr() - SATL Write Same to ATA SCT Write Same * @cmd: SCSI command being translated * @lba: Starting sector - * @num: Number of logical sectors to be zero'd. + * @num: Number of sectors to be zero'd. * - * Rewrite the WRITE SAME descriptor to be an SCT Write Same formatted + * Rewrite the WRITE SAME payload to be an SCT Write Same formatted * descriptor. * NOTE: Writes a pattern (0's) in the foreground. - * Large write-same requents can timeout. + * + * Return: Number of bytes copied into sglist. */ -static void ata_format_sct_write_same(struct scsi_cmnd *cmd, u64 lba, u64 num) +static size_t ata_format_sct_write_same(struct scsi_cmnd *cmd, u64 lba, u64 num) { - u16 *sctpg; + struct scsi_device *sdp = cmd->device; + size_t len = sdp->sector_size; + size_t r; + u16 *buf; unsigned long flags; spin_lock_irqsave(&ata_scsi_rbuf_lock, flags); - sctpg = ((void *)ata_scsi_rbuf); + buf = ((void *)ata_scsi_rbuf); + + put_unaligned_le16(0x0002, &buf[0]); /* SCT_ACT_WRITE_SAME */ + put_unaligned_le16(0x0101, &buf[1]); /* WRITE PTRN FG */ + put_unaligned_le64(lba, &buf[2]); + put_unaligned_le64(num, &buf[6]); + put_unaligned_le32(0u, &buf[10]); /* pattern */ + + WARN_ON(len > ATA_SCSI_RBUF_SIZE); - put_unaligned_le16(0x0002, &sctpg[0]); /* SCT_ACT_WRITE_SAME */ - put_unaligned_le16(0x0101, &sctpg[1]); /* WRITE PTRN FG */ - put_unaligned_le64(lba, &sctpg[2]); - put_unaligned_le64(num, &sctpg[6]); - put_unaligned_le32(0u, &sctpg[10]); + if (len > ATA_SCSI_RBUF_SIZE) + len = ATA_SCSI_RBUF_SIZE; - sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), sctpg, 512); + r = sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf, len); spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags); + + return r; } /** @@ -3371,11 +3388,13 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) { struct ata_taskfile *tf = &qc->tf; struct scsi_cmnd *scmd = qc->scsicmd; + struct scsi_device *sdp = scmd->device; + size_t len = sdp->sector_size; struct ata_device *dev = qc->dev; const u8 *cdb = scmd->cmnd; u64 block; u32 n_block; - const u32 trmax = ATA_MAX_TRIM_RNUM; + const u32 trmax = len >> 3; u32 size; u16 fp; u8 bp = 0xff; @@ -3420,8 +3439,16 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) if (!scsi_sg_count(scmd)) goto invalid_param_len; + /* + * size must match sector size in bytes + * For DATA SET MANAGEMENT TRIM in ACS-2 nsect (aka count) + * is defined as number of 512 byte blocks to be transferred. + */ if (unmap) { size = ata_format_dsm_trim_descr(scmd, trmax, block, n_block); + if (size != len) + goto invalid_param_len; + if (ata_ncq_enabled(dev) && ata_fpdma_dsm_supported(dev)) { /* Newer devices support queued TRIM commands */ tf->protocol = ATA_PROT_NCQ; @@ -3441,7 +3468,9 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) tf->command = ATA_CMD_DSM; } } else { - ata_format_sct_write_same(scmd, block, n_block); + size = ata_format_sct_write_same(scmd, block, n_block); + if (size != len) + goto invalid_param_len; tf->hob_feature = 0; tf->feature = 0; -- cgit v0.10.2 From 7d36dd00ab8d57134cce86ad4febc2f5bbdf3e72 Mon Sep 17 00:00:00 2001 From: Shaun Tancheff Date: Sun, 21 Aug 2016 23:23:21 -0500 Subject: libata: SCT Write Same handle ATA_DFLAG_PIO Use non DMA write log when ATA_DFLAG_PIO is set. Signed-off-by: Shaun Tancheff Reviewed-by: Hannes Reinecke Acked-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 35b1f9e..2f5487f 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3485,6 +3485,8 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) tf->device = ATA_CMD_STANDBYNOW1; tf->protocol = ATA_PROT_DMA; tf->command = ATA_CMD_WRITE_LOG_DMA_EXT; + if (unlikely(dev->flags & ATA_DFLAG_PIO)) + tf->command = ATA_CMD_WRITE_LOG_EXT; } tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48 | -- cgit v0.10.2 From 0b9e2988ab2261fd6d4a0039edf81ed1e3662be8 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 5 Sep 2016 17:21:45 +0200 Subject: ahci: use pci_alloc_irq_vectors Use the new pci_alloc_irq_vectors API to allocate MSI-X and MSI vectors. The big advantage over the old code is that we can use the same API for MSI and MSI-X, and that we don't need to store the MSI-X vector mapping in driver-private data structures. This first conversion keeps the probe order as-is: MSI-X multi vector, MSI multi vector, MSI single vector, MSI-X single vector and last a single least legacy interrupt line. There is one small change of behavior: we now check the "MSI Revert to Single Message" flag for MSI-X in addition to MSI. Because the API to find the Linux IRQ number for a MSI/MSI-X vector is PCI specific, but libahaci is bus-agnostic I had to a get_irq_vector function pointer to struct ahci_host_priv. The alternative would be to move the multi-vector case of ahci_host_activate to ahci.c and just call ata_host_activate directly from the others users of ahci_host_activate. Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 90eabaf..ba5f11c 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1400,142 +1400,56 @@ static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance) } #endif -/* - * ahci_init_msix() - optionally enable per-port MSI-X otherwise defer - * to single msi. - */ -static int ahci_init_msix(struct pci_dev *pdev, unsigned int n_ports, - struct ahci_host_priv *hpriv, unsigned long flags) +static int ahci_get_irq_vector(struct ata_host *host, int port) { - int nvec, i, rc; - - /* Do not init MSI-X if MSI is disabled for the device */ - if (hpriv->flags & AHCI_HFLAG_NO_MSI) - return -ENODEV; - - nvec = pci_msix_vec_count(pdev); - if (nvec < 0) - return nvec; - - /* - * Proper MSI-X implementations will have a vector per-port. - * Barring that, we prefer single-MSI over single-MSIX. If this - * check fails (not enough MSI-X vectors for all ports) we will - * be called again with the flag clear iff ahci_init_msi() - * fails. - */ - if (flags & AHCI_HFLAG_MULTI_MSIX) { - if (nvec < n_ports) - return -ENODEV; - nvec = n_ports; - } else if (nvec) { - nvec = 1; - } else { - /* - * Emit dev_err() since this was the non-legacy irq - * method of last resort. - */ - rc = -ENODEV; - goto fail; - } - - for (i = 0; i < nvec; i++) - hpriv->msix[i].entry = i; - rc = pci_enable_msix_exact(pdev, hpriv->msix, nvec); - if (rc < 0) - goto fail; - - if (nvec > 1) - hpriv->flags |= AHCI_HFLAG_MULTI_MSIX; - hpriv->irq = hpriv->msix[0].vector; /* for single msi-x */ - - return nvec; -fail: - dev_err(&pdev->dev, - "failed to enable MSI-X with error %d, # of vectors: %d\n", - rc, nvec); - - return rc; + return pci_irq_vector(to_pci_dev(host->dev), port); } static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports, struct ahci_host_priv *hpriv) { - int rc, nvec; + int nvec; if (hpriv->flags & AHCI_HFLAG_NO_MSI) return -ENODEV; - nvec = pci_msi_vec_count(pdev); - if (nvec < 0) - return nvec; - /* * If number of MSIs is less than number of ports then Sharing Last * Message mode could be enforced. In this case assume that advantage * of multipe MSIs is negated and use single MSI mode instead. */ - if (nvec < n_ports) - goto single_msi; - - rc = pci_enable_msi_exact(pdev, nvec); - if (rc == -ENOSPC) - goto single_msi; - if (rc < 0) - return rc; + nvec = pci_alloc_irq_vectors(pdev, n_ports, INT_MAX, + PCI_IRQ_MSIX | PCI_IRQ_MSI); + if (nvec > 0) { + if (!(readl(hpriv->mmio + HOST_CTL) & HOST_MRSM)) { + hpriv->get_irq_vector = ahci_get_irq_vector; + hpriv->flags |= AHCI_HFLAG_MULTI_MSI; + return nvec; + } - /* fallback to single MSI mode if the controller enforced MRSM mode */ - if (readl(hpriv->mmio + HOST_CTL) & HOST_MRSM) { - pci_disable_msi(pdev); + /* + * Fallback to single MSI mode if the controller enforced MRSM + * mode. + */ printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n"); - goto single_msi; + pci_free_irq_vectors(pdev); } - if (nvec > 1) - hpriv->flags |= AHCI_HFLAG_MULTI_MSI; - - goto out; - -single_msi: - nvec = 1; - - rc = pci_enable_msi(pdev); - if (rc < 0) - return rc; -out: - hpriv->irq = pdev->irq; - - return nvec; -} - -static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports, - struct ahci_host_priv *hpriv) -{ - int nvec; - /* - * Try to enable per-port MSI-X. If the host is not capable - * fall back to single MSI before finally attempting single - * MSI-X. + * -ENOSPC indicated we don't have enough vectors. Don't bother trying + * a single vectors for any other error: */ - nvec = ahci_init_msix(pdev, n_ports, hpriv, AHCI_HFLAG_MULTI_MSIX); - if (nvec >= 0) + if (nvec < 0 && nvec != -ENOSPC) return nvec; - nvec = ahci_init_msi(pdev, n_ports, hpriv); - if (nvec >= 0) - return nvec; - - /* try single-msix */ - nvec = ahci_init_msix(pdev, n_ports, hpriv, 0); - if (nvec >= 0) + /* + * If the host is not capable of supporting per-port vectors, fall + * back to single MSI before finally attempting single MSI-X. + */ + nvec = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); + if (nvec == 1) return nvec; - - /* legacy intx interrupts */ - pci_intx(pdev, 1); - hpriv->irq = pdev->irq; - - return 0; + return pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX); } static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -1698,11 +1612,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (!host) return -ENOMEM; host->private_data = hpriv; - hpriv->msix = devm_kzalloc(&pdev->dev, - sizeof(struct msix_entry) * n_ports, GFP_KERNEL); - if (!hpriv->msix) - return -ENOMEM; - ahci_init_interrupts(pdev, n_ports, hpriv); + + if (ahci_init_msi(pdev, n_ports, hpriv) < 0) { + /* legacy intx interrupts */ + pci_intx(pdev, 1); + } + hpriv->irq = pdev->irq; if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) host->flags |= ATA_HOST_PARALLEL_SCAN; diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 70b06bc..0cc08f8 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -242,12 +242,10 @@ enum { AHCI_HFLAG_NO_FBS = (1 << 18), /* no FBS */ #ifdef CONFIG_PCI_MSI - AHCI_HFLAG_MULTI_MSI = (1 << 20), /* multiple PCI MSIs */ - AHCI_HFLAG_MULTI_MSIX = (1 << 21), /* per-port MSI-X */ + AHCI_HFLAG_MULTI_MSI = (1 << 20), /* per-port MSI(-X) */ #else /* compile out MSI infrastructure */ AHCI_HFLAG_MULTI_MSI = 0, - AHCI_HFLAG_MULTI_MSIX = 0, #endif AHCI_HFLAG_WAKE_BEFORE_STOP = (1 << 22), /* wake before DMA stop */ @@ -351,7 +349,6 @@ struct ahci_host_priv { * the PHY position in this array. */ struct phy **phys; - struct msix_entry *msix; /* Optional MSI-X support */ unsigned nports; /* Number of ports */ void *plat_data; /* Other platform data */ unsigned int irq; /* interrupt line */ @@ -362,22 +359,11 @@ struct ahci_host_priv { */ void (*start_engine)(struct ata_port *ap); irqreturn_t (*irq_handler)(int irq, void *dev_instance); -}; -#ifdef CONFIG_PCI_MSI -static inline int ahci_irq_vector(struct ahci_host_priv *hpriv, int port) -{ - if (hpriv->flags & AHCI_HFLAG_MULTI_MSIX) - return hpriv->msix[port].vector; - else - return hpriv->irq + port; -} -#else -static inline int ahci_irq_vector(struct ahci_host_priv *hpriv, int port) -{ - return hpriv->irq; -} -#endif + /* only required for per-port MSI(-X) support */ + int (*get_irq_vector)(struct ata_host *host, + int port); +}; extern int ahci_ignore_sss; diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 5a1329e..0d028ea 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -2378,7 +2378,7 @@ static int ahci_port_start(struct ata_port *ap) /* * Switch to per-port locking in case each port has its own MSI vector. */ - if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX)) { + if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) { spin_lock_init(&pp->lock); ap->lock = &pp->lock; } @@ -2520,7 +2520,7 @@ static int ahci_host_activate_multi_irqs(struct ata_host *host, */ for (i = 0; i < host->n_ports; i++) { struct ahci_port_priv *pp = host->ports[i]->private_data; - int irq = ahci_irq_vector(hpriv, i); + int irq = hpriv->get_irq_vector(host, i); /* Do not receive interrupts sent by dummy ports */ if (!pp) { @@ -2556,10 +2556,15 @@ int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht) int irq = hpriv->irq; int rc; - if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX)) { + if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) { if (hpriv->irq_handler) dev_warn(host->dev, "both AHCI_HFLAG_MULTI_MSI flag set and custom irq handler implemented\n"); + if (!hpriv->get_irq_vector) { + dev_err(host->dev, + "AHCI_HFLAG_MULTI_MSI requires ->get_irq_vector!\n"); + return -EIO; + } rc = ahci_host_activate_multi_irqs(host, sht); } else { -- cgit v0.10.2 From 0ce1b18c42a5b1613ad84d3bf93ee4f5bb3f8b33 Mon Sep 17 00:00:00 2001 From: Shaun Tancheff Date: Fri, 9 Sep 2016 11:44:19 -0500 Subject: libata: Some drives failing on SCT Write Same Restrict support SCT Write Same to devices which also support ZAC where support is required. Reported-by: Mike Krinkin Signed-off-by: Shaun Tancheff Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 2f5487f..9cceb4a 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3562,9 +3562,9 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) supported = 3; break; case WRITE_SAME_16: - if (ata_id_sct_write_same(dev->id)) - supported = 3; - break; + if (!ata_id_sct_write_same(dev->id)) + break; + /* fallthrough: if SCT ... only enable for ZBC */ case ZBC_IN: case ZBC_OUT: if (ata_id_zoned_cap(dev->id) || -- cgit v0.10.2 From 6ec76070f17993aa9ac0344330b971783d10c9c2 Mon Sep 17 00:00:00 2001 From: Harman Kalra Date: Wed, 21 Sep 2016 01:14:40 +0530 Subject: ata: sata_mv: Replacing dma_pool_alloc and memset with a single call dma_pool_zalloc. Replacing dma_pool_alloc and memset with a single call to dma_pool_zalloc Signed-off-by: Harman Kalra Signed-off-by: Tejun Heo diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 745489a..efc48bf 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1727,15 +1727,13 @@ static int mv_port_start(struct ata_port *ap) return -ENOMEM; ap->private_data = pp; - pp->crqb = dma_pool_alloc(hpriv->crqb_pool, GFP_KERNEL, &pp->crqb_dma); + pp->crqb = dma_pool_zalloc(hpriv->crqb_pool, GFP_KERNEL, &pp->crqb_dma); if (!pp->crqb) return -ENOMEM; - memset(pp->crqb, 0, MV_CRQB_Q_SZ); - pp->crpb = dma_pool_alloc(hpriv->crpb_pool, GFP_KERNEL, &pp->crpb_dma); + pp->crpb = dma_pool_zalloc(hpriv->crpb_pool, GFP_KERNEL, &pp->crpb_dma); if (!pp->crpb) goto out_port_free_dma_mem; - memset(pp->crpb, 0, MV_CRPB_Q_SZ); /* 6041/6081 Rev. "C0" (and newer) are okay with async notify */ if (hpriv->hp_flags & MV_HP_ERRATA_60X1C0) -- cgit v0.10.2 From 02d9d3cbac53bd59fe18fc32adc7bc7cde1037ae Mon Sep 17 00:00:00 2001 From: Harman Kalra Date: Thu, 22 Sep 2016 01:29:48 +0530 Subject: ata: Replace BUG() with BUG_ON(). Replace BUG() with BUG_ON(). Caught by coccinelle. Signed-off-by: Harman Kalra Signed-off-by: Tejun Heo diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c index 2724595..475a006 100644 --- a/drivers/ata/pata_octeon_cf.c +++ b/drivers/ata/pata_octeon_cf.c @@ -152,8 +152,7 @@ static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev) div = 8; T = (int)((1000000000000LL * div) / octeon_get_io_clock_rate()); - if (ata_timing_compute(dev, dev->pio_mode, &timing, T, T)) - BUG(); + BUG_ON(ata_timing_compute(dev, dev->pio_mode, &timing, T, T)); t1 = timing.setup; if (t1) -- cgit v0.10.2 From 70a19b7e406da9dc5cea20fedba443374a5cae70 Mon Sep 17 00:00:00 2001 From: Harman Kalra Date: Thu, 22 Sep 2016 01:18:31 +0530 Subject: pata_at91: Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR Signed-off-by: Harman Kalra Signed-off-by: Tejun Heo diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c index 9f27b14..1611e0e 100644 --- a/drivers/ata/pata_at91.c +++ b/drivers/ata/pata_at91.c @@ -347,10 +347,8 @@ static int at91sam9_smc_fields_init(struct device *dev) field.reg = AT91SAM9_SMC_MODE(AT91SAM9_SMC_GENERIC); fields.mode = devm_regmap_field_alloc(dev, smc, field); - if (IS_ERR(fields.mode)) - return PTR_ERR(fields.mode); - return 0; + return PTR_ERR_OR_ZERO(fields.mode); } static int pata_at91_probe(struct platform_device *pdev) -- cgit v0.10.2 From 014b44e7a4683ccef09cc58c53012e5bc53daece Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 22 Sep 2016 07:49:49 -0700 Subject: libata: remove unused definitions from Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo diff --git a/arch/ia64/include/asm/libata-portmap.h b/arch/ia64/include/asm/libata-portmap.h index 0e00c9a..7a1f831 100644 --- a/arch/ia64/include/asm/libata-portmap.h +++ b/arch/ia64/include/asm/libata-portmap.h @@ -1,12 +1,8 @@ #ifndef __ASM_IA64_LIBATA_PORTMAP_H #define __ASM_IA64_LIBATA_PORTMAP_H -#define ATA_PRIMARY_CMD 0x1F0 -#define ATA_PRIMARY_CTL 0x3F6 #define ATA_PRIMARY_IRQ(dev) isa_irq_to_vector(14) -#define ATA_SECONDARY_CMD 0x170 -#define ATA_SECONDARY_CTL 0x376 #define ATA_SECONDARY_IRQ(dev) isa_irq_to_vector(15) #endif diff --git a/arch/powerpc/include/asm/libata-portmap.h b/arch/powerpc/include/asm/libata-portmap.h index 4d85180..4396db5 100644 --- a/arch/powerpc/include/asm/libata-portmap.h +++ b/arch/powerpc/include/asm/libata-portmap.h @@ -1,12 +1,8 @@ #ifndef __ASM_POWERPC_LIBATA_PORTMAP_H #define __ASM_POWERPC_LIBATA_PORTMAP_H -#define ATA_PRIMARY_CMD 0x1F0 -#define ATA_PRIMARY_CTL 0x3F6 #define ATA_PRIMARY_IRQ(dev) pci_get_legacy_ide_irq(dev, 0) -#define ATA_SECONDARY_CMD 0x170 -#define ATA_SECONDARY_CTL 0x376 #define ATA_SECONDARY_IRQ(dev) pci_get_legacy_ide_irq(dev, 1) #endif -- cgit v0.10.2 From dcd3ea81f572fba57d18e91743a525a9787c1f6e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 22 Sep 2016 07:49:50 -0700 Subject: libata: remove asm-generic is only intended for architecture defaults, and we can simply kill it off by moving the two defintions directly to . Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo diff --git a/include/asm-generic/libata-portmap.h b/include/asm-generic/libata-portmap.h deleted file mode 100644 index cf14f2f..0000000 --- a/include/asm-generic/libata-portmap.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __ASM_GENERIC_LIBATA_PORTMAP_H -#define __ASM_GENERIC_LIBATA_PORTMAP_H - -#define ATA_PRIMARY_IRQ(dev) 14 -#define ATA_SECONDARY_IRQ(dev) 15 - -#endif diff --git a/include/linux/libata.h b/include/linux/libata.h index e37d4f9..616eef4 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -46,7 +46,8 @@ #ifdef CONFIG_ATA_NONSTANDARD #include #else -#include +#define ATA_PRIMARY_IRQ(dev) 14 +#define ATA_SECONDARY_IRQ(dev) 15 #endif /* -- cgit v0.10.2 From 1ce788d24268a33513d832d9030ceab93f1c2ce2 Mon Sep 17 00:00:00 2001 From: Tang Yuantian Date: Fri, 30 Sep 2016 14:13:13 +0800 Subject: ahci: qoriq: Revert "ahci: qoriq: Disable NCQ on ls2080a SoC" This reverts commit 640847298e2b7f19 ("ahci: qoriq: Disable NCQ on ls2080a SoC") The erratum has been fixed in ls2080a v2.0 and later soc. In reality, customer will not get any ls2080a v1.0 soc. Neither apply to any products. So reverting this commit won't create any side effect. Blacklisting v2.0 could also be a option, but that needs to check the soc version which is not suitable in the driver. Signed-off-by: Tang Yuantian Signed-off-by: Tejun Heo diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c index 925c4b6..1eba8df 100644 --- a/drivers/ata/ahci_qoriq.c +++ b/drivers/ata/ahci_qoriq.c @@ -136,7 +136,7 @@ static struct ata_port_operations ahci_qoriq_ops = { .hardreset = ahci_qoriq_hardreset, }; -static struct ata_port_info ahci_qoriq_port_info = { +static const struct ata_port_info ahci_qoriq_port_info = { .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ, .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, @@ -221,12 +221,6 @@ static int ahci_qoriq_probe(struct platform_device *pdev) if (rc) goto disable_resources; - /* Workaround for ls2080a */ - if (qoriq_priv->type == AHCI_LS2080A) { - hpriv->flags |= AHCI_HFLAG_NO_NCQ; - ahci_qoriq_port_info.flags &= ~ATA_FLAG_NCQ; - } - rc = ahci_platform_init_host(pdev, hpriv, &ahci_qoriq_port_info, &ahci_qoriq_sht); if (rc) -- cgit v0.10.2