From ca156e006add67e4beea7896be395160735e09b0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 24 Jun 2019 09:32:50 -0700 Subject: [PATCH 1/9] libata: don't request sense data on !ZAC ATA devices ZAC support added sense data requesting on error for both ZAC and ATA devices. This seems to cause erratic error handling behaviors on some SSDs where the device reports sense data availability and then delivers the wrong content making EH take the wrong actions. The failure mode was sporadic on a LITE-ON ssd and couldn't be reliably reproduced. There is no value in requesting sense data from non-ZAC ATA devices while there's a significant risk of introducing EH misbehaviors which are difficult to reproduce and fix. Let's do the sense data dancing only for ZAC devices. Reviewed-by: Hannes Reinecke Tested-by: Masato Suzuki Reviewed-by: Damien Le Moal Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- drivers/ata/libata-eh.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 9d687e1d4325..3bfd9da58473 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1469,7 +1469,7 @@ 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)) + if (dev->class == ATA_DEV_ZAC && ata_id_has_ncq_autosense(dev->id)) tf->auxiliary = buf[14] << 16 | buf[15] << 8 | buf[16]; return 0; @@ -1716,7 +1716,8 @@ 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.command & ATA_SENSE) || qc->result_tf.auxiliary) { + if (dev->class == ATA_DEV_ZAC && + ((qc->result_tf.command & ATA_SENSE) || qc->result_tf.auxiliary)) { char sense_key, asc, ascq; sense_key = (qc->result_tf.auxiliary >> 16) & 0xff; @@ -1770,10 +1771,11 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, } switch (qc->dev->class) { - case ATA_DEV_ATA: case ATA_DEV_ZAC: if (stat & ATA_SENSE) ata_eh_request_sense(qc, qc->scsicmd); + /* fall through */ + case ATA_DEV_ATA: if (err & ATA_ICRC) qc->err_mask |= AC_ERR_ATA_BUS; if (err & (ATA_UNC | ATA_AMNF)) From fec36aae0de14e31c7cf3e8be172d10a966de2ea Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Fri, 28 Jun 2019 01:33:46 +0800 Subject: [PATCH 2/9] ata: acard-ahci: Remove call to memset after dmam_alloc_coherent In commit af7ddd8a627c ("Merge tag 'dma-mapping-4.21' of git://git.infradead.org/users/hch/dma-mapping"), dmam_alloc_coherent has already zeroed the memory. So memset is not needed. Signed-off-by: Fuqian Huang Signed-off-by: Jens Axboe --- drivers/ata/acard-ahci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/ata/acard-ahci.c b/drivers/ata/acard-ahci.c index b1b49dbd0b14..85357f27a66b 100644 --- a/drivers/ata/acard-ahci.c +++ b/drivers/ata/acard-ahci.c @@ -344,7 +344,6 @@ static int acard_ahci_port_start(struct ata_port *ap) mem = dmam_alloc_coherent(dev, dma_sz, &mem_dma, GFP_KERNEL); if (!mem) return -ENOMEM; - memset(mem, 0, dma_sz); /* * First item in chunk of DMA memory: 32-slot command table, From 602e40a78567ffd7e5eaf235a116fd808cf85b75 Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Fri, 28 Jun 2019 01:34:01 +0800 Subject: [PATCH 3/9] ata: libahci: Remove call to memset after dmam_alloc_coherent In commit af7ddd8a627c ("Merge tag 'dma-mapping-4.21' of git://git.infradead.org/users/hch/dma-mapping"), dmam_alloc_coherent has already zeroed the memory. So memset is not needed. Signed-off-by: Fuqian Huang Signed-off-by: Jens Axboe --- drivers/ata/libahci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 0984c4b76d7e..e4c45d3cca79 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -2365,7 +2365,6 @@ static int ahci_port_start(struct ata_port *ap) mem = dmam_alloc_coherent(dev, dma_sz, &mem_dma, GFP_KERNEL); if (!mem) return -ENOMEM; - memset(mem, 0, dma_sz); /* * First item in chunk of DMA memory: 32-slot command table, From 65315bbbfd9fdb7863c0bfea5011b400e67bc38b Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Fri, 28 Jun 2019 01:34:10 +0800 Subject: [PATCH 4/9] ata: pdc_adma: Remove call to memset after dmam_alloc_coherent In commit af7ddd8a627c ("Merge tag 'dma-mapping-4.21' of git://git.infradead.org/users/hch/dma-mapping"), dmam_alloc_coherent has already zeroed the memory. So memset is not needed. Signed-off-by: Fuqian Huang Signed-off-by: Jens Axboe --- drivers/ata/pdc_adma.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c index 52fa8606a25f..c5bbb07aa7d9 100644 --- a/drivers/ata/pdc_adma.c +++ b/drivers/ata/pdc_adma.c @@ -550,7 +550,6 @@ static int adma_port_start(struct ata_port *ap) (u32)pp->pkt_dma); return -ENOMEM; } - memset(pp->pkt, 0, ADMA_PKT_BYTES); ap->private_data = pp; adma_reinit_engine(ap); return 0; From 523e099b69551961dc3f3070a960338328ac0774 Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Fri, 28 Jun 2019 01:34:18 +0800 Subject: [PATCH 5/9] ata: sata_nv: Remove call to memset after dmam_alloc_coherent In commit af7ddd8a627c ("Merge tag 'dma-mapping-4.21' of git://git.infradead.org/users/hch/dma-mapping"), dmam_alloc_coherent has already zeroed the memory. So memset is not needed. Signed-off-by: Fuqian Huang Signed-off-by: Jens Axboe --- drivers/ata/sata_nv.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 54bfab15c74a..b44b4b64354c 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -1136,7 +1136,6 @@ static int nv_adma_port_start(struct ata_port *ap) &mem_dma, GFP_KERNEL); if (!mem) return -ENOMEM; - memset(mem, 0, NV_ADMA_PORT_PRIV_DMA_SZ); /* * First item in chunk of DMA memory: @@ -1946,7 +1945,6 @@ static int nv_swncq_port_start(struct ata_port *ap) &pp->prd_dma, GFP_KERNEL); if (!pp->prd) return -ENOMEM; - memset(pp->prd, 0, ATA_PRD_TBL_SZ * ATA_MAX_QUEUE); ap->private_data = pp; pp->sactive_block = ap->ioaddr.scr_addr + 4 * SCR_ACTIVE; From b39f5da467188bdfdd17b5049cef54a4af27cd7f Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Fri, 28 Jun 2019 01:34:26 +0800 Subject: [PATCH 6/9] ata:sata_qstor: Remove call to memset after dmam_alloc_coherent In commit af7ddd8a627c ("Merge tag 'dma-mapping-4.21' of git://git.infradead.org/users/hch/dma-mapping"), dmam_alloc_coherent has already zeroed the memory. So memset is not needed. Signed-off-by: Fuqian Huang Signed-off-by: Jens Axboe --- drivers/ata/sata_qstor.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index 7ec0c216a6a6..865e5c58bd94 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -477,7 +477,6 @@ static int qs_port_start(struct ata_port *ap) GFP_KERNEL); if (!pp->pkt) return -ENOMEM; - memset(pp->pkt, 0, QS_PKT_BYTES); ap->private_data = pp; qs_enter_reg_mode(ap); From e675697eaca208edcebb42fd8c30a71bd5258c40 Mon Sep 17 00:00:00 2001 From: Fuqian Huang Date: Fri, 28 Jun 2019 01:34:34 +0800 Subject: [PATCH 7/9] ata: sata_sil24: Remove call to memset after dmam_alloc_coherent In commit af7ddd8a627c ("Merge tag 'dma-mapping-4.21' of git://git.infradead.org/users/hch/dma-mapping"),, dmam_alloc_coherent has already zeroed the memory. So memset is not needed. Signed-off-by: Fuqian Huang Signed-off-by: Jens Axboe --- drivers/ata/sata_sil24.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index bfdf41912588..98aad8206921 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -1202,7 +1202,6 @@ static int sil24_port_start(struct ata_port *ap) cb = dmam_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL); if (!cb) return -ENOMEM; - memset(cb, 0, cb_size); pp->cmd_block = cb; pp->cmd_block_dma = cb_dma; From 8756a25b07e6fe878c1a3a40e71a322b18ba57af Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 1 Jul 2019 18:58:13 +0200 Subject: [PATCH 8/9] libata: Drop firmware version check from the ST1000LM024 quirk There are several firmware versions between version 2AR10001 and 2BA30001, presumably these also have broken FPDMA_AA activation, so lets play it safe and apply the quirk to all firmware versions. Suggested-by: Martin K. Petersen Reviewed-by: Martin K. Petersen Signed-off-by: Hans de Goede Signed-off-by: Jens Axboe --- drivers/ata/libata-core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 4a2dff303865..28c492be0a57 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4462,9 +4462,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* drives which fail FPDMA_AA activation (some may freeze afterwards) the ST disks also have LPM issues */ - { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA | - ATA_HORKAGE_NOLPM, }, - { "ST1000LM024 HN-M101MBB", "2BA30001", ATA_HORKAGE_BROKEN_FPDMA_AA | + { "ST1000LM024 HN-M101MBB", NULL, ATA_HORKAGE_BROKEN_FPDMA_AA | ATA_HORKAGE_NOLPM, }, { "VB0250EAVER", "HPG7", ATA_HORKAGE_BROKEN_FPDMA_AA }, From 120357ea176e420d313cf8cf2ff35fbe233d3bab Mon Sep 17 00:00:00 2001 From: Uenal Mutlu Date: Mon, 13 May 2019 16:24:10 +0200 Subject: [PATCH 9/9] drivers: ata: ahci_sunxi: Increased SATA/AHCI DMA TX/RX FIFOs Increasing the SATA/AHCI DMA TX/RX FIFOs (P0DMACR.TXTS and .RXTS, ie. TX_TRANSACTION_SIZE and RX_TRANSACTION_SIZE) from default 0x0 each to 0x3 each, gives a write performance boost of 120 MiB/s to 132 MiB/s from lame 36 MiB/s to 45 MiB/s previously. Read performance is above 200 MiB/s. [tested on SSD using dd bs=4K/8K/12K/16K/20K/24K/32K: peak-perf at 12K] Tested on the SBCs Banana Pi R1 (aka Lamobo R1) and Banana Pi M1 which are based on the Allwinner A20 32bit-SoC (ARMv7-a / arm-linux-gnueabihf). These devices are RaspberryPi-like small devices. This problem of slow SATA write-speed with these small devices lasts for about 7 years now (beginning with the A10 SoC). Many commentators throughout the years wrongly assumed the slow write speed was a hardware limitation. This patch finally solves the problem, which in fact was just a hard-to-find software problem due to lack of SATA/AHCI documentation by the SoC-maker Allwinner Technology. Lists of the affected sunxi and other boards and SoCs with SATA using the ahci_sunxi driver: $ grep -i -e "^&ahci" arch/arm/boot/dts/sun*dts and http://linux-sunxi.org/SATA#Devices_with_SATA_ports See also http://linux-sunxi.org/Category:Devices_with_SATA_port Tested-by: Chen-Yu Tsai Acked-by: Maxime Ripard Reviewed-by: Hans de Goede Signed-off-by: Uenal Mutlu Signed-off-by: Jens Axboe --- drivers/ata/ahci_sunxi.c | 47 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c index 4100e904376b..cb69b737cb49 100644 --- a/drivers/ata/ahci_sunxi.c +++ b/drivers/ata/ahci_sunxi.c @@ -149,8 +149,51 @@ static void ahci_sunxi_start_engine(struct ata_port *ap) void __iomem *port_mmio = ahci_port_base(ap); struct ahci_host_priv *hpriv = ap->host->private_data; - /* Setup DMA before DMA start */ - sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ff00, 0x00004400); + /* Setup DMA before DMA start + * + * NOTE: A similar SoC with SATA/AHCI by Texas Instruments documents + * this Vendor Specific Port (P0DMACR, aka PxDMACR) in its + * User's Guide document (TMS320C674x/OMAP-L1x Processor + * Serial ATA (SATA) Controller, Literature Number: SPRUGJ8C, + * March 2011, Chapter 4.33 Port DMA Control Register (P0DMACR), + * p.68, https://www.ti.com/lit/ug/sprugj8c/sprugj8c.pdf) + * as equivalent to the following struct: + * + * struct AHCI_P0DMACR_t + * { + * unsigned TXTS : 4; + * unsigned RXTS : 4; + * unsigned TXABL : 4; + * unsigned RXABL : 4; + * unsigned Reserved : 16; + * }; + * + * TXTS: Transmit Transaction Size (TX_TRANSACTION_SIZE). + * This field defines the DMA transaction size in DWORDs for + * transmit (system bus read, device write) operation. [...] + * + * RXTS: Receive Transaction Size (RX_TRANSACTION_SIZE). + * This field defines the Port DMA transaction size in DWORDs + * for receive (system bus write, device read) operation. [...] + * + * TXABL: Transmit Burst Limit. + * This field allows software to limit the VBUSP master read + * burst size. [...] + * + * RXABL: Receive Burst Limit. + * Allows software to limit the VBUSP master write burst + * size. [...] + * + * Reserved: Reserved. + * + * + * NOTE: According to the above document, the following alternative + * to the code below could perhaps be a better option + * (or preparation) for possible further improvements later: + * sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ffff, + * 0x00000033); + */ + sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ffff, 0x00004433); /* Start DMA */ sunxi_setbits(port_mmio + PORT_CMD, PORT_CMD_START);