From 03d38c74d06bc3a676f7702075a230e27f5f4375 Mon Sep 17 00:00:00 2001 From: Rayyan Ansari Date: Wed, 17 Jul 2024 11:03:06 +0100 Subject: [PATCH 01/39] dt-bindings: ata: qcom,ipq806x-ahci: use dtschema Remove old text bindings and add ipq806x AHCI compatible to ahci-common.yaml, as well as its required properties. Signed-off-by: Rayyan Ansari Reviewed-by: Krzysztof Kozlowski Signed-off-by: Damien Le Moal --- .../bindings/ata/ahci-platform.yaml | 30 +++++++++++- .../devicetree/bindings/ata/qcom-sata.txt | 48 ------------------- 2 files changed, 28 insertions(+), 50 deletions(-) delete mode 100644 Documentation/devicetree/bindings/ata/qcom-sata.txt diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.yaml b/Documentation/devicetree/bindings/ata/ahci-platform.yaml index 358617115bb8..2c8fdfc3df9b 100644 --- a/Documentation/devicetree/bindings/ata/ahci-platform.yaml +++ b/Documentation/devicetree/bindings/ata/ahci-platform.yaml @@ -30,6 +30,7 @@ select: - marvell,armada-3700-ahci - marvell,armada-8k-ahci - marvell,berlin2q-ahci + - qcom,ipq806x-ahci - socionext,uniphier-pro4-ahci - socionext,uniphier-pxs2-ahci - socionext,uniphier-pxs3-ahci @@ -45,6 +46,7 @@ properties: - marvell,armada-8k-ahci - marvell,berlin2-ahci - marvell,berlin2q-ahci + - qcom,ipq806x-ahci - socionext,uniphier-pro4-ahci - socionext,uniphier-pxs2-ahci - socionext,uniphier-pxs3-ahci @@ -64,11 +66,11 @@ properties: clocks: minItems: 1 - maxItems: 3 + maxItems: 5 clock-names: minItems: 1 - maxItems: 3 + maxItems: 5 interrupts: maxItems: 1 @@ -97,6 +99,30 @@ required: allOf: - $ref: ahci-common.yaml# + + - if: + properties: + compatible: + contains: + enum: + - qcom,ipq806x-ahci + then: + properties: + clocks: + minItems: 5 + clock-names: + items: + - const: slave_iface + - const: iface + - const: core + - const: rxoob + - const: pmalive + required: + - phys + - phy-names + - clocks + - clock-names + - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/ata/qcom-sata.txt b/Documentation/devicetree/bindings/ata/qcom-sata.txt deleted file mode 100644 index 094de91cd9fd..000000000000 --- a/Documentation/devicetree/bindings/ata/qcom-sata.txt +++ /dev/null @@ -1,48 +0,0 @@ -* Qualcomm AHCI SATA Controller - -SATA nodes are defined to describe on-chip Serial ATA controllers. -Each SATA controller should have its own node. - -Required properties: -- compatible : compatible list, must contain "generic-ahci" -- interrupts : -- reg : -- phys : Must contain exactly one entry as specified - in phy-bindings.txt -- phy-names : Must be "sata-phy" - -Required properties for "qcom,ipq806x-ahci" compatible: -- clocks : Must contain an entry for each entry in clock-names. -- clock-names : Shall be: - "slave_iface" - Fabric port AHB clock for SATA - "iface" - AHB clock - "core" - core clock - "rxoob" - RX out-of-band clock - "pmalive" - Power Module Alive clock -- assigned-clocks : Shall be: - SATA_RXOOB_CLK - SATA_PMALIVE_CLK -- assigned-clock-rates : Shall be: - 100Mhz (100000000) for SATA_RXOOB_CLK - 100Mhz (100000000) for SATA_PMALIVE_CLK - -Example: - sata@29000000 { - compatible = "qcom,ipq806x-ahci", "generic-ahci"; - reg = <0x29000000 0x180>; - - interrupts = <0 209 0x0>; - - clocks = <&gcc SFAB_SATA_S_H_CLK>, - <&gcc SATA_H_CLK>, - <&gcc SATA_A_CLK>, - <&gcc SATA_RXOOB_CLK>, - <&gcc SATA_PMALIVE_CLK>; - clock-names = "slave_iface", "iface", "core", - "rxoob", "pmalive"; - assigned-clocks = <&gcc SATA_RXOOB_CLK>, <&gcc SATA_PMALIVE_CLK>; - assigned-clock-rates = <100000000>, <100000000>; - - phys = <&sata_phy>; - phy-names = "sata-phy"; - }; From 837dcea001593c1b82a6de9b23cfe975ac88868c Mon Sep 17 00:00:00 2001 From: Rayyan Ansari Date: Wed, 17 Jul 2024 11:03:07 +0100 Subject: [PATCH 02/39] dt-bindings: ata: qcom,apq8064-ahci: add to dtschema The APQ8064 SATA AHCI controller is used in apq8064.dtsi, although it was not documented in the old text bindings. Add its compatible to ahci-platform.yaml. Signed-off-by: Rayyan Ansari Reviewed-by: Krzysztof Kozlowski Signed-off-by: Damien Le Moal --- Documentation/devicetree/bindings/ata/ahci-platform.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.yaml b/Documentation/devicetree/bindings/ata/ahci-platform.yaml index 2c8fdfc3df9b..ef19468e3022 100644 --- a/Documentation/devicetree/bindings/ata/ahci-platform.yaml +++ b/Documentation/devicetree/bindings/ata/ahci-platform.yaml @@ -30,6 +30,7 @@ select: - marvell,armada-3700-ahci - marvell,armada-8k-ahci - marvell,berlin2q-ahci + - qcom,apq8064-ahci - qcom,ipq806x-ahci - socionext,uniphier-pro4-ahci - socionext,uniphier-pxs2-ahci @@ -46,6 +47,7 @@ properties: - marvell,armada-8k-ahci - marvell,berlin2-ahci - marvell,berlin2q-ahci + - qcom,apq8064-ahci - qcom,ipq806x-ahci - socionext,uniphier-pro4-ahci - socionext,uniphier-pxs2-ahci @@ -105,6 +107,7 @@ allOf: compatible: contains: enum: + - qcom,apq8064-ahci - qcom,ipq806x-ahci then: properties: From f8f26f743ccfa882620f39a8fbca6d5d138d2e46 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Wed, 24 Jul 2024 07:45:56 +0900 Subject: [PATCH 03/39] ata: libata: Change ata_dev_knobble() to return a bool Change the function ata_dev_knobble() to return a boolean instead of a u8. Signed-off-by: Damien Le Moal Reviewed-by: Igor Pylypiv Reviewed-by: Niklas Cassel --- drivers/ata/libata-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index c7752dc80028..c49334e13c0b 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2219,12 +2219,12 @@ static int ata_do_link_spd_horkage(struct ata_device *dev) return 0; } -static inline u8 ata_dev_knobble(struct ata_device *dev) +static inline bool ata_dev_knobble(struct ata_device *dev) { struct ata_port *ap = dev->link->ap; if (ata_dev_blacklisted(dev) & ATA_HORKAGE_BRIDGE_OK) - return 0; + return false; return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); } From f209d8ed5249691076a3b425667a1bd94f90887b Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 18 Jul 2024 17:06:44 +0900 Subject: [PATCH 04/39] ata: libata: Rename ata_dma_blacklisted() Rename the function ata_dma_blacklisted() to ata_dev_nodma() as this new name is more neutral. The function signature is also changed to return a boolean instead of an int. Signed-off-by: Damien Le Moal Reviewed-by: Igor Pylypiv Reviewed-by: Niklas Cassel --- drivers/ata/libata-core.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index c49334e13c0b..f1e5055e33fe 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4287,16 +4287,17 @@ static unsigned long ata_dev_blacklisted(const struct ata_device *dev) return 0; } -static int ata_dma_blacklisted(const struct ata_device *dev) +static bool ata_dev_nodma(const struct ata_device *dev) { - /* We don't support polling DMA. - * DMA blacklist those ATAPI devices with CDB-intr (and use PIO) - * if the LLDD handles only interrupts in the HSM_ST_LAST state. + /* + * We do not support polling DMA. Deny DMA for those ATAPI devices + * with CDB-intr (and use PIO) if the LLDD handles only interrupts in + * the HSM_ST_LAST state. */ if ((dev->link->ap->flags & ATA_FLAG_PIO_POLLING) && (dev->flags & ATA_DFLAG_CDB_INTR)) - return 1; - return (dev->horkage & ATA_HORKAGE_NODMA) ? 1 : 0; + return true; + return dev->horkage & ATA_HORKAGE_NODMA; } /** @@ -4404,10 +4405,10 @@ static void ata_dev_xfermask(struct ata_device *dev) xfer_mask &= ~(0x03 << (ATA_SHIFT_MWDMA + 3)); } - if (ata_dma_blacklisted(dev)) { + if (ata_dev_nodma(dev)) { xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); ata_dev_warn(dev, - "device is on DMA blacklist, disabling DMA\n"); + "device does not support DMA, disabling DMA\n"); } if ((host->flags & ATA_HOST_SIMPLEX) && From 7ebd8c5acad5f8ca41f37b36dc62570e1fa13d8b Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 18 Jul 2024 16:59:06 +0900 Subject: [PATCH 05/39] ata: libata: Use QUIRK instead of HORKAGE According to Wiktionary, the verb "hork" is computing slang defined as "To foul up; to be occupied with difficulty, tangle, or unpleasantness; to be broken" (https://en.wiktionary.org/wiki/hork#Verb). libata uses this with the term "horkage" to refer to broken device features. Given that this term is not widely used and its meaning unknown to many, rename it to the more commonly used term "quirk", similar to many other places in the kernel. The renaming done is: 1) Rename all ATA_HORKAGE_XXX flags to ATA_QUIRK_XXX 2) Rename struct ata_device horkage field to quirks 3) Rename struct ata_blacklist_entry to struct ata_dev_quirks_entry. The array of these structures defining quirks for known devices is renamed __ata_dev_quirks. 4) The functions ata_dev_blacklisted() and ata_force_horkage() are renamed to ata_dev_quirks() and ata_force_quirks() respectively. 5) All the force_horkage_xxx() macros are renamed to force_quirk_xxx() And while at it, make sure that the type "unsigned int" is used consistantly for quirk flags variables and data structure fields. Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Igor Pylypiv --- drivers/ata/libata-core.c | 490 ++++++++++++++++----------------- drivers/ata/libata-sata.c | 2 +- drivers/ata/libata-scsi.c | 9 +- drivers/ata/libata-sff.c | 10 +- drivers/ata/libata-transport.c | 6 +- drivers/ata/pata_it821x.c | 4 +- drivers/ata/sata_sil.c | 2 +- include/linux/libata.h | 71 ++--- 8 files changed, 297 insertions(+), 297 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index f1e5055e33fe..19b041bd7588 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -84,7 +84,7 @@ static unsigned int ata_dev_init_params(struct ata_device *dev, u16 heads, u16 sectors); static unsigned int ata_dev_set_xfermode(struct ata_device *dev); static void ata_dev_xfermask(struct ata_device *dev); -static unsigned long ata_dev_blacklisted(const struct ata_device *dev); +static unsigned int ata_dev_quirks(const struct ata_device *dev); static DEFINE_IDA(ata_ida); @@ -94,8 +94,8 @@ struct ata_force_param { u8 cbl; u8 spd_limit; unsigned int xfer_mask; - unsigned int horkage_on; - unsigned int horkage_off; + unsigned int quirk_on; + unsigned int quirk_off; u16 lflags_on; u16 lflags_off; }; @@ -457,17 +457,17 @@ static void ata_force_xfermask(struct ata_device *dev) } /** - * ata_force_horkage - force horkage according to libata.force + * ata_force_quirks - force quirks according to libata.force * @dev: ATA device of interest * - * Force horkage according to libata.force and whine about it. + * Force quirks according to libata.force and whine about it. * For consistency with link selection, device number 15 selects * the first device connected to the host link. * * LOCKING: * EH context. */ -static void ata_force_horkage(struct ata_device *dev) +static void ata_force_quirks(struct ata_device *dev) { int devno = dev->link->pmp + dev->devno; int alt_devno = devno; @@ -487,21 +487,21 @@ static void ata_force_horkage(struct ata_device *dev) fe->device != alt_devno) continue; - if (!(~dev->horkage & fe->param.horkage_on) && - !(dev->horkage & fe->param.horkage_off)) + if (!(~dev->quirks & fe->param.quirk_on) && + !(dev->quirks & fe->param.quirk_off)) continue; - dev->horkage |= fe->param.horkage_on; - dev->horkage &= ~fe->param.horkage_off; + dev->quirks |= fe->param.quirk_on; + dev->quirks &= ~fe->param.quirk_off; - ata_dev_notice(dev, "FORCE: horkage modified (%s)\n", + ata_dev_notice(dev, "FORCE: modified (%s)\n", fe->param.name); } } #else static inline void ata_force_link_limits(struct ata_link *link) { } static inline void ata_force_xfermask(struct ata_device *dev) { } -static inline void ata_force_horkage(struct ata_device *dev) { } +static inline void ata_force_quirks(struct ata_device *dev) { } #endif /** @@ -1221,7 +1221,7 @@ static int ata_read_native_max_address(struct ata_device *dev, u64 *max_sectors) *max_sectors = ata_tf_to_lba48(&tf) + 1; else *max_sectors = ata_tf_to_lba(&tf) + 1; - if (dev->horkage & ATA_HORKAGE_HPA_SIZE) + if (dev->quirks & ATA_QUIRK_HPA_SIZE) (*max_sectors)--; return 0; } @@ -1306,7 +1306,7 @@ static int ata_hpa_resize(struct ata_device *dev) /* do we need to do it? */ if ((dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ZAC) || !ata_id_has_lba(dev->id) || !ata_id_hpa_enabled(dev->id) || - (dev->horkage & ATA_HORKAGE_BROKEN_HPA)) + (dev->quirks & ATA_QUIRK_BROKEN_HPA)) return 0; /* read native max address */ @@ -1318,7 +1318,7 @@ static int ata_hpa_resize(struct ata_device *dev) if (rc == -EACCES || !unlock_hpa) { ata_dev_warn(dev, "HPA support seems broken, skipping HPA handling\n"); - dev->horkage |= ATA_HORKAGE_BROKEN_HPA; + dev->quirks |= ATA_QUIRK_BROKEN_HPA; /* we can continue if device aborted the command */ if (rc == -EACCES) @@ -1355,7 +1355,7 @@ static int ata_hpa_resize(struct ata_device *dev) "device aborted resize (%llu -> %llu), skipping HPA handling\n", (unsigned long long)sectors, (unsigned long long)native_sectors); - dev->horkage |= ATA_HORKAGE_BROKEN_HPA; + dev->quirks |= ATA_QUIRK_BROKEN_HPA; return 0; } else if (rc) return rc; @@ -1835,7 +1835,7 @@ retry: goto err_out; } - if (dev->horkage & ATA_HORKAGE_DUMP_ID) { + if (dev->quirks & ATA_QUIRK_DUMP_ID) { ata_dev_info(dev, "dumping IDENTIFY data, " "class=%d may_fallback=%d tried_spinup=%d\n", class, may_fallback, tried_spinup); @@ -2104,7 +2104,7 @@ unsigned int ata_read_log_page(struct ata_device *dev, u8 log, retry: ata_tf_init(dev, &tf); if (ata_dma_enabled(dev) && ata_id_has_read_log_dma_ext(dev->id) && - !(dev->horkage & ATA_HORKAGE_NO_DMA_LOG)) { + !(dev->quirks & ATA_QUIRK_NO_DMA_LOG)) { tf.command = ATA_CMD_READ_LOG_DMA_EXT; tf.protocol = ATA_PROT_DMA; dma = true; @@ -2124,7 +2124,7 @@ retry: if (err_mask) { if (dma) { - dev->horkage |= ATA_HORKAGE_NO_DMA_LOG; + dev->quirks |= ATA_QUIRK_NO_DMA_LOG; if (!ata_port_is_frozen(dev->link->ap)) goto retry; } @@ -2140,7 +2140,7 @@ static int ata_log_supported(struct ata_device *dev, u8 log) { struct ata_port *ap = dev->link->ap; - if (dev->horkage & ATA_HORKAGE_NO_LOG_DIR) + if (dev->quirks & ATA_QUIRK_NO_LOG_DIR) return 0; if (ata_read_log_page(dev, ATA_LOG_DIRECTORY, 0, ap->sector_buf, 1)) @@ -2153,7 +2153,7 @@ static bool ata_identify_page_supported(struct ata_device *dev, u8 page) struct ata_port *ap = dev->link->ap; unsigned int err, i; - if (dev->horkage & ATA_HORKAGE_NO_ID_DEV_LOG) + if (dev->quirks & ATA_QUIRK_NO_ID_DEV_LOG) return false; if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE)) { @@ -2165,7 +2165,7 @@ static bool ata_identify_page_supported(struct ata_device *dev, u8 page) if (ata_id_major_version(dev->id) >= 10) ata_dev_warn(dev, "ATA Identify Device Log not supported\n"); - dev->horkage |= ATA_HORKAGE_NO_ID_DEV_LOG; + dev->quirks |= ATA_QUIRK_NO_ID_DEV_LOG; return false; } @@ -2186,7 +2186,7 @@ static bool ata_identify_page_supported(struct ata_device *dev, u8 page) return false; } -static int ata_do_link_spd_horkage(struct ata_device *dev) +static int ata_do_link_spd_quirk(struct ata_device *dev) { struct ata_link *plink = ata_dev_phys_link(dev); u32 target, target_limit; @@ -2194,7 +2194,7 @@ static int ata_do_link_spd_horkage(struct ata_device *dev) if (!sata_scr_valid(plink)) return 0; - if (dev->horkage & ATA_HORKAGE_1_5_GBPS) + if (dev->quirks & ATA_QUIRK_1_5_GBPS) target = 1; else return 0; @@ -2212,7 +2212,7 @@ static int ata_do_link_spd_horkage(struct ata_device *dev) * guaranteed by setting sata_spd_limit to target_limit above. */ if (plink->sata_spd > target) { - ata_dev_info(dev, "applying link speed limit horkage to %s\n", + ata_dev_info(dev, "applying link speed limit quirk to %s\n", sata_spd_string(target)); return -EAGAIN; } @@ -2223,7 +2223,7 @@ static inline bool ata_dev_knobble(struct ata_device *dev) { struct ata_port *ap = dev->link->ap; - if (ata_dev_blacklisted(dev) & ATA_HORKAGE_BRIDGE_OK) + if (ata_dev_quirks(dev) & ATA_QUIRK_BRIDGE_OK) return false; return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); @@ -2246,7 +2246,7 @@ static void ata_dev_config_ncq_send_recv(struct ata_device *dev) dev->flags |= ATA_DFLAG_NCQ_SEND_RECV; memcpy(cmds, ap->sector_buf, ATA_LOG_NCQ_SEND_RECV_SIZE); - if (dev->horkage & ATA_HORKAGE_NO_NCQ_TRIM) { + if (dev->quirks & ATA_QUIRK_NO_NCQ_TRIM) { ata_dev_dbg(dev, "disabling queued TRIM support\n"); cmds[ATA_LOG_NCQ_SEND_RECV_DSM_OFFSET] &= ~ATA_LOG_NCQ_SEND_RECV_DSM_TRIM; @@ -2334,12 +2334,12 @@ static int ata_dev_config_ncq(struct ata_device *dev, } if (!IS_ENABLED(CONFIG_SATA_HOST)) return 0; - if (dev->horkage & ATA_HORKAGE_NONCQ) { + if (dev->quirks & ATA_QUIRK_NONCQ) { snprintf(desc, desc_sz, "NCQ (not used)"); return 0; } - if (dev->horkage & ATA_HORKAGE_NO_NCQ_ON_ATI && + if (dev->quirks & ATA_QUIRK_NO_NCQ_ON_ATI && ata_dev_check_adapter(dev, PCI_VENDOR_ID_ATI)) { snprintf(desc, desc_sz, "NCQ (not used)"); return 0; @@ -2350,7 +2350,7 @@ static int ata_dev_config_ncq(struct ata_device *dev, dev->flags |= ATA_DFLAG_NCQ; } - if (!(dev->horkage & ATA_HORKAGE_BROKEN_FPDMA_AA) && + if (!(dev->quirks & ATA_QUIRK_BROKEN_FPDMA_AA) && (ap->flags & ATA_FLAG_FPDMA_AA) && ata_id_has_fpdma_aa(dev->id)) { err_mask = ata_dev_set_feature(dev, SETFEATURES_SATA_ENABLE, @@ -2360,7 +2360,7 @@ static int ata_dev_config_ncq(struct ata_device *dev, "failed to enable AA (error_mask=0x%x)\n", err_mask); if (err_mask != AC_ERR_DEV) { - dev->horkage |= ATA_HORKAGE_BROKEN_FPDMA_AA; + dev->quirks |= ATA_QUIRK_BROKEN_FPDMA_AA; return -EIO; } } else @@ -2689,7 +2689,7 @@ static void ata_dev_config_fua(struct ata_device *dev) goto nofua; /* Ignore known bad devices and devices that lack NCQ support */ - if (!ata_ncq_supported(dev) || (dev->horkage & ATA_HORKAGE_NO_FUA)) + if (!ata_ncq_supported(dev) || (dev->quirks & ATA_QUIRK_NO_FUA)) goto nofua; dev->flags |= ATA_DFLAG_FUA; @@ -2829,11 +2829,11 @@ int ata_dev_configure(struct ata_device *dev) return 0; } - /* set horkage */ - dev->horkage |= ata_dev_blacklisted(dev); - ata_force_horkage(dev); + /* Set quirks */ + dev->quirks |= ata_dev_quirks(dev); + ata_force_quirks(dev); - if (dev->horkage & ATA_HORKAGE_DISABLE) { + if (dev->quirks & ATA_QUIRK_DISABLE) { ata_dev_info(dev, "unsupported device, disabling\n"); ata_dev_disable(dev); return 0; @@ -2848,19 +2848,19 @@ int ata_dev_configure(struct ata_device *dev) return 0; } - rc = ata_do_link_spd_horkage(dev); + rc = ata_do_link_spd_quirk(dev); if (rc) return rc; /* some WD SATA-1 drives have issues with LPM, turn on NOLPM for them */ - if ((dev->horkage & ATA_HORKAGE_WD_BROKEN_LPM) && + if ((dev->quirks & ATA_QUIRK_WD_BROKEN_LPM) && (id[ATA_ID_SATA_CAPABILITY] & 0xe) == 0x2) - dev->horkage |= ATA_HORKAGE_NOLPM; + dev->quirks |= ATA_QUIRK_NOLPM; if (ap->flags & ATA_FLAG_NO_LPM) - dev->horkage |= ATA_HORKAGE_NOLPM; + dev->quirks |= ATA_QUIRK_NOLPM; - if (dev->horkage & ATA_HORKAGE_NOLPM) { + if (dev->quirks & ATA_QUIRK_NOLPM) { ata_dev_warn(dev, "LPM support broken, forcing max_power\n"); dev->link->ap->target_lpm_policy = ATA_LPM_MAX_POWER; } @@ -3006,7 +3006,8 @@ int ata_dev_configure(struct ata_device *dev) cdb_intr_string = ", CDB intr"; } - if (atapi_dmadir || (dev->horkage & ATA_HORKAGE_ATAPI_DMADIR) || atapi_id_dmadir(dev->id)) { + if (atapi_dmadir || (dev->quirks & ATA_QUIRK_ATAPI_DMADIR) || + atapi_id_dmadir(dev->id)) { dev->flags |= ATA_DFLAG_DMADIR; dma_dir_string = ", DMADIR"; } @@ -3043,24 +3044,24 @@ int ata_dev_configure(struct ata_device *dev) if ((dev->class == ATA_DEV_ATAPI) && (atapi_command_packet_set(id) == TYPE_TAPE)) { dev->max_sectors = ATA_MAX_SECTORS_TAPE; - dev->horkage |= ATA_HORKAGE_STUCK_ERR; + dev->quirks |= ATA_QUIRK_STUCK_ERR; } - if (dev->horkage & ATA_HORKAGE_MAX_SEC_128) + if (dev->quirks & ATA_QUIRK_MAX_SEC_128) dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128, dev->max_sectors); - if (dev->horkage & ATA_HORKAGE_MAX_SEC_1024) + if (dev->quirks & ATA_QUIRK_MAX_SEC_1024) dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_1024, dev->max_sectors); - if (dev->horkage & ATA_HORKAGE_MAX_SEC_LBA48) + if (dev->quirks & ATA_QUIRK_MAX_SEC_LBA48) dev->max_sectors = ATA_MAX_SECTORS_LBA48; if (ap->ops->dev_config) ap->ops->dev_config(dev); - if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) { + if (dev->quirks & ATA_QUIRK_DIAGNOSTIC) { /* Let the user know. We don't want to disallow opens for rescue purposes, or in case the vendor is just a blithering idiot. Do this after the dev_config call as some controllers @@ -3075,7 +3076,7 @@ int ata_dev_configure(struct ata_device *dev) } } - if ((dev->horkage & ATA_HORKAGE_FIRMWARE_WARN) && print_info) { + if ((dev->quirks & ATA_QUIRK_FIRMWARE_WARN) && print_info) { ata_dev_warn(dev, "WARNING: device requires firmware update to be fully functional\n"); ata_dev_warn(dev, " contact the vendor or visit http://ata.wiki.kernel.org\n"); } @@ -3425,7 +3426,7 @@ static int ata_dev_set_mode(struct ata_device *dev) { struct ata_port *ap = dev->link->ap; struct ata_eh_context *ehc = &dev->link->eh_context; - const bool nosetxfer = dev->horkage & ATA_HORKAGE_NOSETXFER; + const bool nosetxfer = dev->quirks & ATA_QUIRK_NOSETXFER; const char *dev_err_whine = ""; int ign_dev_err = 0; unsigned int err_mask = 0; @@ -3969,7 +3970,7 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, */ if (dev->n_native_sectors == n_native_sectors && dev->n_sectors < n_sectors && n_sectors == n_native_sectors && - !(dev->horkage & ATA_HORKAGE_BROKEN_HPA)) { + !(dev->quirks & ATA_QUIRK_BROKEN_HPA)) { ata_dev_warn(dev, "old n_sectors matches native, probably " "late HPA lock, will try to unlock HPA\n"); @@ -3987,223 +3988,223 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, return rc; } -struct ata_blacklist_entry { +struct ata_dev_quirks_entry { const char *model_num; const char *model_rev; - unsigned long horkage; + unsigned int quirks; }; -static const struct ata_blacklist_entry ata_device_blacklist [] = { +static const struct ata_dev_quirks_entry __ata_dev_quirks[] = { /* Devices with DMA related problems under Linux */ - { "WDC AC11000H", NULL, ATA_HORKAGE_NODMA }, - { "WDC AC22100H", NULL, ATA_HORKAGE_NODMA }, - { "WDC AC32500H", NULL, ATA_HORKAGE_NODMA }, - { "WDC AC33100H", NULL, ATA_HORKAGE_NODMA }, - { "WDC AC31600H", NULL, ATA_HORKAGE_NODMA }, - { "WDC AC32100H", "24.09P07", ATA_HORKAGE_NODMA }, - { "WDC AC23200L", "21.10N21", ATA_HORKAGE_NODMA }, - { "Compaq CRD-8241B", NULL, ATA_HORKAGE_NODMA }, - { "CRD-8400B", NULL, ATA_HORKAGE_NODMA }, - { "CRD-848[02]B", NULL, ATA_HORKAGE_NODMA }, - { "CRD-84", NULL, ATA_HORKAGE_NODMA }, - { "SanDisk SDP3B", NULL, ATA_HORKAGE_NODMA }, - { "SanDisk SDP3B-64", NULL, ATA_HORKAGE_NODMA }, - { "SANYO CD-ROM CRD", NULL, ATA_HORKAGE_NODMA }, - { "HITACHI CDR-8", NULL, ATA_HORKAGE_NODMA }, - { "HITACHI CDR-8[34]35",NULL, ATA_HORKAGE_NODMA }, - { "Toshiba CD-ROM XM-6202B", NULL, ATA_HORKAGE_NODMA }, - { "TOSHIBA CD-ROM XM-1702BC", NULL, ATA_HORKAGE_NODMA }, - { "CD-532E-A", NULL, ATA_HORKAGE_NODMA }, - { "E-IDE CD-ROM CR-840",NULL, ATA_HORKAGE_NODMA }, - { "CD-ROM Drive/F5A", NULL, ATA_HORKAGE_NODMA }, - { "WPI CDD-820", NULL, ATA_HORKAGE_NODMA }, - { "SAMSUNG CD-ROM SC-148C", NULL, ATA_HORKAGE_NODMA }, - { "SAMSUNG CD-ROM SC", NULL, ATA_HORKAGE_NODMA }, - { "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL,ATA_HORKAGE_NODMA }, - { "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA }, - { "SAMSUNG CD-ROM SN-124", "N001", ATA_HORKAGE_NODMA }, - { "Seagate STT20000A", NULL, ATA_HORKAGE_NODMA }, - { " 2GB ATA Flash Disk", "ADMA428M", ATA_HORKAGE_NODMA }, - { "VRFDFC22048UCHC-TE*", NULL, ATA_HORKAGE_NODMA }, + { "WDC AC11000H", NULL, ATA_QUIRK_NODMA }, + { "WDC AC22100H", NULL, ATA_QUIRK_NODMA }, + { "WDC AC32500H", NULL, ATA_QUIRK_NODMA }, + { "WDC AC33100H", NULL, ATA_QUIRK_NODMA }, + { "WDC AC31600H", NULL, ATA_QUIRK_NODMA }, + { "WDC AC32100H", "24.09P07", ATA_QUIRK_NODMA }, + { "WDC AC23200L", "21.10N21", ATA_QUIRK_NODMA }, + { "Compaq CRD-8241B", NULL, ATA_QUIRK_NODMA }, + { "CRD-8400B", NULL, ATA_QUIRK_NODMA }, + { "CRD-848[02]B", NULL, ATA_QUIRK_NODMA }, + { "CRD-84", NULL, ATA_QUIRK_NODMA }, + { "SanDisk SDP3B", NULL, ATA_QUIRK_NODMA }, + { "SanDisk SDP3B-64", NULL, ATA_QUIRK_NODMA }, + { "SANYO CD-ROM CRD", NULL, ATA_QUIRK_NODMA }, + { "HITACHI CDR-8", NULL, ATA_QUIRK_NODMA }, + { "HITACHI CDR-8[34]35", NULL, ATA_QUIRK_NODMA }, + { "Toshiba CD-ROM XM-6202B", NULL, ATA_QUIRK_NODMA }, + { "TOSHIBA CD-ROM XM-1702BC", NULL, ATA_QUIRK_NODMA }, + { "CD-532E-A", NULL, ATA_QUIRK_NODMA }, + { "E-IDE CD-ROM CR-840", NULL, ATA_QUIRK_NODMA }, + { "CD-ROM Drive/F5A", NULL, ATA_QUIRK_NODMA }, + { "WPI CDD-820", NULL, ATA_QUIRK_NODMA }, + { "SAMSUNG CD-ROM SC-148C", NULL, ATA_QUIRK_NODMA }, + { "SAMSUNG CD-ROM SC", NULL, ATA_QUIRK_NODMA }, + { "ATAPI CD-ROM DRIVE 40X MAXIMUM", NULL, ATA_QUIRK_NODMA }, + { "_NEC DV5800A", NULL, ATA_QUIRK_NODMA }, + { "SAMSUNG CD-ROM SN-124", "N001", ATA_QUIRK_NODMA }, + { "Seagate STT20000A", NULL, ATA_QUIRK_NODMA }, + { " 2GB ATA Flash Disk", "ADMA428M", ATA_QUIRK_NODMA }, + { "VRFDFC22048UCHC-TE*", NULL, ATA_QUIRK_NODMA }, /* Odd clown on sil3726/4726 PMPs */ - { "Config Disk", NULL, ATA_HORKAGE_DISABLE }, + { "Config Disk", NULL, ATA_QUIRK_DISABLE }, /* Similar story with ASMedia 1092 */ - { "ASMT109x- Config", NULL, ATA_HORKAGE_DISABLE }, + { "ASMT109x- Config", NULL, ATA_QUIRK_DISABLE }, /* Weird ATAPI devices */ - { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 }, - { "QUANTUM DAT DAT72-000", NULL, ATA_HORKAGE_ATAPI_MOD16_DMA }, - { "Slimtype DVD A DS8A8SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 }, - { "Slimtype DVD A DS8A9SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 }, + { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_QUIRK_MAX_SEC_128 }, + { "QUANTUM DAT DAT72-000", NULL, ATA_QUIRK_ATAPI_MOD16_DMA }, + { "Slimtype DVD A DS8A8SH", NULL, ATA_QUIRK_MAX_SEC_LBA48 }, + { "Slimtype DVD A DS8A9SH", NULL, ATA_QUIRK_MAX_SEC_LBA48 }, /* * Causes silent data corruption with higher max sects. * http://lkml.kernel.org/g/x49wpy40ysk.fsf@segfault.boston.devel.redhat.com */ - { "ST380013AS", "3.20", ATA_HORKAGE_MAX_SEC_1024 }, + { "ST380013AS", "3.20", ATA_QUIRK_MAX_SEC_1024 }, /* * These devices time out with higher max sects. * https://bugzilla.kernel.org/show_bug.cgi?id=121671 */ - { "LITEON CX1-JB*-HP", NULL, ATA_HORKAGE_MAX_SEC_1024 }, - { "LITEON EP1-*", NULL, ATA_HORKAGE_MAX_SEC_1024 }, + { "LITEON CX1-JB*-HP", NULL, ATA_QUIRK_MAX_SEC_1024 }, + { "LITEON EP1-*", NULL, ATA_QUIRK_MAX_SEC_1024 }, /* Devices we expect to fail diagnostics */ /* Devices where NCQ should be avoided */ /* NCQ is slow */ - { "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ }, - { "WDC WD740ADFD-00NLR1", NULL, ATA_HORKAGE_NONCQ }, + { "WDC WD740ADFD-00", NULL, ATA_QUIRK_NONCQ }, + { "WDC WD740ADFD-00NLR1", NULL, ATA_QUIRK_NONCQ }, /* http://thread.gmane.org/gmane.linux.ide/14907 */ - { "FUJITSU MHT2060BH", NULL, ATA_HORKAGE_NONCQ }, + { "FUJITSU MHT2060BH", NULL, ATA_QUIRK_NONCQ }, /* NCQ is broken */ - { "Maxtor *", "BANC*", ATA_HORKAGE_NONCQ }, - { "Maxtor 7V300F0", "VA111630", ATA_HORKAGE_NONCQ }, - { "ST380817AS", "3.42", ATA_HORKAGE_NONCQ }, - { "ST3160023AS", "3.42", ATA_HORKAGE_NONCQ }, - { "OCZ CORE_SSD", "02.10104", ATA_HORKAGE_NONCQ }, + { "Maxtor *", "BANC*", ATA_QUIRK_NONCQ }, + { "Maxtor 7V300F0", "VA111630", ATA_QUIRK_NONCQ }, + { "ST380817AS", "3.42", ATA_QUIRK_NONCQ }, + { "ST3160023AS", "3.42", ATA_QUIRK_NONCQ }, + { "OCZ CORE_SSD", "02.10104", ATA_QUIRK_NONCQ }, /* Seagate NCQ + FLUSH CACHE firmware bug */ - { "ST31500341AS", "SD1[5-9]", ATA_HORKAGE_NONCQ | - ATA_HORKAGE_FIRMWARE_WARN }, + { "ST31500341AS", "SD1[5-9]", ATA_QUIRK_NONCQ | + ATA_QUIRK_FIRMWARE_WARN }, - { "ST31000333AS", "SD1[5-9]", ATA_HORKAGE_NONCQ | - ATA_HORKAGE_FIRMWARE_WARN }, + { "ST31000333AS", "SD1[5-9]", ATA_QUIRK_NONCQ | + ATA_QUIRK_FIRMWARE_WARN }, - { "ST3640[36]23AS", "SD1[5-9]", ATA_HORKAGE_NONCQ | - ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3640[36]23AS", "SD1[5-9]", ATA_QUIRK_NONCQ | + ATA_QUIRK_FIRMWARE_WARN }, - { "ST3320[68]13AS", "SD1[5-9]", ATA_HORKAGE_NONCQ | - ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3320[68]13AS", "SD1[5-9]", ATA_QUIRK_NONCQ | + ATA_QUIRK_FIRMWARE_WARN }, /* drives which fail FPDMA_AA activation (some may freeze afterwards) the ST disks also have LPM issues */ - { "ST1000LM024 HN-M101MBB", NULL, ATA_HORKAGE_BROKEN_FPDMA_AA | - ATA_HORKAGE_NOLPM }, - { "VB0250EAVER", "HPG7", ATA_HORKAGE_BROKEN_FPDMA_AA }, + { "ST1000LM024 HN-M101MBB", NULL, ATA_QUIRK_BROKEN_FPDMA_AA | + ATA_QUIRK_NOLPM }, + { "VB0250EAVER", "HPG7", ATA_QUIRK_BROKEN_FPDMA_AA }, /* Blacklist entries taken from Silicon Image 3124/3132 Windows driver .inf file - also several Linux problem reports */ - { "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ }, - { "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ }, - { "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ }, + { "HTS541060G9SA00", "MB3OC60D", ATA_QUIRK_NONCQ }, + { "HTS541080G9SA00", "MB4OC60D", ATA_QUIRK_NONCQ }, + { "HTS541010G9SA00", "MBZOC60D", ATA_QUIRK_NONCQ }, /* https://bugzilla.kernel.org/show_bug.cgi?id=15573 */ - { "C300-CTFDDAC128MAG", "0001", ATA_HORKAGE_NONCQ }, + { "C300-CTFDDAC128MAG", "0001", ATA_QUIRK_NONCQ }, /* Sandisk SD7/8/9s lock up hard on large trims */ - { "SanDisk SD[789]*", NULL, ATA_HORKAGE_MAX_TRIM_128M }, + { "SanDisk SD[789]*", NULL, ATA_QUIRK_MAX_TRIM_128M }, /* devices which puke on READ_NATIVE_MAX */ - { "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA }, - { "WDC WD3200JD-00KLB0", "WD-WCAMR1130137", ATA_HORKAGE_BROKEN_HPA }, - { "WDC WD2500JD-00HBB0", "WD-WMAL71490727", ATA_HORKAGE_BROKEN_HPA }, - { "MAXTOR 6L080L4", "A93.0500", ATA_HORKAGE_BROKEN_HPA }, + { "HDS724040KLSA80", "KFAOA20N", ATA_QUIRK_BROKEN_HPA }, + { "WDC WD3200JD-00KLB0", "WD-WCAMR1130137", ATA_QUIRK_BROKEN_HPA }, + { "WDC WD2500JD-00HBB0", "WD-WMAL71490727", ATA_QUIRK_BROKEN_HPA }, + { "MAXTOR 6L080L4", "A93.0500", ATA_QUIRK_BROKEN_HPA }, /* this one allows HPA unlocking but fails IOs on the area */ - { "OCZ-VERTEX", "1.30", ATA_HORKAGE_BROKEN_HPA }, + { "OCZ-VERTEX", "1.30", ATA_QUIRK_BROKEN_HPA }, /* Devices which report 1 sector over size HPA */ - { "ST340823A", NULL, ATA_HORKAGE_HPA_SIZE }, - { "ST320413A", NULL, ATA_HORKAGE_HPA_SIZE }, - { "ST310211A", NULL, ATA_HORKAGE_HPA_SIZE }, + { "ST340823A", NULL, ATA_QUIRK_HPA_SIZE }, + { "ST320413A", NULL, ATA_QUIRK_HPA_SIZE }, + { "ST310211A", NULL, ATA_QUIRK_HPA_SIZE }, /* Devices which get the IVB wrong */ - { "QUANTUM FIREBALLlct10 05", "A03.0900", ATA_HORKAGE_IVB }, - /* Maybe we should just blacklist TSSTcorp... */ - { "TSSTcorp CDDVDW SH-S202[HJN]", "SB0[01]", ATA_HORKAGE_IVB }, + { "QUANTUM FIREBALLlct10 05", "A03.0900", ATA_QUIRK_IVB }, + /* Maybe we should just add all TSSTcorp devices... */ + { "TSSTcorp CDDVDW SH-S202[HJN]", "SB0[01]", ATA_QUIRK_IVB }, /* Devices that do not need bridging limits applied */ - { "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK }, - { "BUFFALO HD-QSU2/R5", NULL, ATA_HORKAGE_BRIDGE_OK }, + { "MTRON MSP-SATA*", NULL, ATA_QUIRK_BRIDGE_OK }, + { "BUFFALO HD-QSU2/R5", NULL, ATA_QUIRK_BRIDGE_OK }, /* Devices which aren't very happy with higher link speeds */ - { "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS }, - { "Seagate FreeAgent GoFlex", NULL, ATA_HORKAGE_1_5_GBPS }, + { "WD My Book", NULL, ATA_QUIRK_1_5_GBPS }, + { "Seagate FreeAgent GoFlex", NULL, ATA_QUIRK_1_5_GBPS }, /* * Devices which choke on SETXFER. Applies only if both the * device and controller are SATA. */ - { "PIONEER DVD-RW DVRTD08", NULL, ATA_HORKAGE_NOSETXFER }, - { "PIONEER DVD-RW DVRTD08A", NULL, ATA_HORKAGE_NOSETXFER }, - { "PIONEER DVD-RW DVR-215", NULL, ATA_HORKAGE_NOSETXFER }, - { "PIONEER DVD-RW DVR-212D", NULL, ATA_HORKAGE_NOSETXFER }, - { "PIONEER DVD-RW DVR-216D", NULL, ATA_HORKAGE_NOSETXFER }, + { "PIONEER DVD-RW DVRTD08", NULL, ATA_QUIRK_NOSETXFER }, + { "PIONEER DVD-RW DVRTD08A", NULL, ATA_QUIRK_NOSETXFER }, + { "PIONEER DVD-RW DVR-215", NULL, ATA_QUIRK_NOSETXFER }, + { "PIONEER DVD-RW DVR-212D", NULL, ATA_QUIRK_NOSETXFER }, + { "PIONEER DVD-RW DVR-216D", NULL, ATA_QUIRK_NOSETXFER }, /* These specific Pioneer models have LPM issues */ - { "PIONEER BD-RW BDR-207M", NULL, ATA_HORKAGE_NOLPM }, - { "PIONEER BD-RW BDR-205", NULL, ATA_HORKAGE_NOLPM }, + { "PIONEER BD-RW BDR-207M", NULL, ATA_QUIRK_NOLPM }, + { "PIONEER BD-RW BDR-205", NULL, ATA_QUIRK_NOLPM }, /* Crucial devices with broken LPM support */ - { "CT*0BX*00SSD1", NULL, ATA_HORKAGE_NOLPM }, + { "CT*0BX*00SSD1", NULL, ATA_QUIRK_NOLPM }, /* 512GB MX100 with MU01 firmware has both queued TRIM and LPM issues */ - { "Crucial_CT512MX100*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | - ATA_HORKAGE_ZERO_AFTER_TRIM | - ATA_HORKAGE_NOLPM }, + { "Crucial_CT512MX100*", "MU01", ATA_QUIRK_NO_NCQ_TRIM | + ATA_QUIRK_ZERO_AFTER_TRIM | + ATA_QUIRK_NOLPM }, /* 512GB MX100 with newer firmware has only LPM issues */ - { "Crucial_CT512MX100*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM | - ATA_HORKAGE_NOLPM }, + { "Crucial_CT512MX100*", NULL, ATA_QUIRK_ZERO_AFTER_TRIM | + ATA_QUIRK_NOLPM }, /* 480GB+ M500 SSDs have both queued TRIM and LPM issues */ - { "Crucial_CT480M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | - ATA_HORKAGE_ZERO_AFTER_TRIM | - ATA_HORKAGE_NOLPM }, - { "Crucial_CT960M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | - ATA_HORKAGE_ZERO_AFTER_TRIM | - ATA_HORKAGE_NOLPM }, + { "Crucial_CT480M500*", NULL, ATA_QUIRK_NO_NCQ_TRIM | + ATA_QUIRK_ZERO_AFTER_TRIM | + ATA_QUIRK_NOLPM }, + { "Crucial_CT960M500*", NULL, ATA_QUIRK_NO_NCQ_TRIM | + ATA_QUIRK_ZERO_AFTER_TRIM | + ATA_QUIRK_NOLPM }, /* AMD Radeon devices with broken LPM support */ - { "R3SL240G", NULL, ATA_HORKAGE_NOLPM }, + { "R3SL240G", NULL, ATA_QUIRK_NOLPM }, /* Apacer models with LPM issues */ - { "Apacer AS340*", NULL, ATA_HORKAGE_NOLPM }, + { "Apacer AS340*", NULL, ATA_QUIRK_NOLPM }, /* These specific Samsung models/firmware-revs do not handle LPM well */ - { "SAMSUNG MZMPC128HBFU-000MV", "CXM14M1Q", ATA_HORKAGE_NOLPM }, - { "SAMSUNG SSD PM830 mSATA *", "CXM13D1Q", ATA_HORKAGE_NOLPM }, - { "SAMSUNG MZ7TD256HAFV-000L9", NULL, ATA_HORKAGE_NOLPM }, - { "SAMSUNG MZ7TE512HMHP-000L1", "EXT06L0Q", ATA_HORKAGE_NOLPM }, + { "SAMSUNG MZMPC128HBFU-000MV", "CXM14M1Q", ATA_QUIRK_NOLPM }, + { "SAMSUNG SSD PM830 mSATA *", "CXM13D1Q", ATA_QUIRK_NOLPM }, + { "SAMSUNG MZ7TD256HAFV-000L9", NULL, ATA_QUIRK_NOLPM }, + { "SAMSUNG MZ7TE512HMHP-000L1", "EXT06L0Q", ATA_QUIRK_NOLPM }, /* devices that don't properly handle queued TRIM commands */ - { "Micron_M500IT_*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | - ATA_HORKAGE_ZERO_AFTER_TRIM }, - { "Micron_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 }, - { "Micron_1100_*", 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 }, - { "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 840 EVO*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | - ATA_HORKAGE_NO_DMA_LOG | - ATA_HORKAGE_ZERO_AFTER_TRIM }, - { "Samsung SSD 840*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | - ATA_HORKAGE_ZERO_AFTER_TRIM }, - { "Samsung SSD 850*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | - ATA_HORKAGE_ZERO_AFTER_TRIM }, - { "Samsung SSD 860*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | - ATA_HORKAGE_ZERO_AFTER_TRIM | - ATA_HORKAGE_NO_NCQ_ON_ATI }, - { "Samsung SSD 870*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | - ATA_HORKAGE_ZERO_AFTER_TRIM | - ATA_HORKAGE_NO_NCQ_ON_ATI }, - { "SAMSUNG*MZ7LH*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | - ATA_HORKAGE_ZERO_AFTER_TRIM | - ATA_HORKAGE_NO_NCQ_ON_ATI, }, - { "FCCT*M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | - ATA_HORKAGE_ZERO_AFTER_TRIM }, + { "Micron_M500IT_*", "MU01", ATA_QUIRK_NO_NCQ_TRIM | + ATA_QUIRK_ZERO_AFTER_TRIM }, + { "Micron_M500_*", NULL, ATA_QUIRK_NO_NCQ_TRIM | + ATA_QUIRK_ZERO_AFTER_TRIM }, + { "Micron_M5[15]0_*", "MU01", ATA_QUIRK_NO_NCQ_TRIM | + ATA_QUIRK_ZERO_AFTER_TRIM }, + { "Micron_1100_*", NULL, ATA_QUIRK_NO_NCQ_TRIM | + ATA_QUIRK_ZERO_AFTER_TRIM, }, + { "Crucial_CT*M500*", NULL, ATA_QUIRK_NO_NCQ_TRIM | + ATA_QUIRK_ZERO_AFTER_TRIM }, + { "Crucial_CT*M550*", "MU01", ATA_QUIRK_NO_NCQ_TRIM | + ATA_QUIRK_ZERO_AFTER_TRIM }, + { "Crucial_CT*MX100*", "MU01", ATA_QUIRK_NO_NCQ_TRIM | + ATA_QUIRK_ZERO_AFTER_TRIM }, + { "Samsung SSD 840 EVO*", NULL, ATA_QUIRK_NO_NCQ_TRIM | + ATA_QUIRK_NO_DMA_LOG | + ATA_QUIRK_ZERO_AFTER_TRIM }, + { "Samsung SSD 840*", NULL, ATA_QUIRK_NO_NCQ_TRIM | + ATA_QUIRK_ZERO_AFTER_TRIM }, + { "Samsung SSD 850*", NULL, ATA_QUIRK_NO_NCQ_TRIM | + ATA_QUIRK_ZERO_AFTER_TRIM }, + { "Samsung SSD 860*", NULL, ATA_QUIRK_NO_NCQ_TRIM | + ATA_QUIRK_ZERO_AFTER_TRIM | + ATA_QUIRK_NO_NCQ_ON_ATI }, + { "Samsung SSD 870*", NULL, ATA_QUIRK_NO_NCQ_TRIM | + ATA_QUIRK_ZERO_AFTER_TRIM | + ATA_QUIRK_NO_NCQ_ON_ATI }, + { "SAMSUNG*MZ7LH*", NULL, ATA_QUIRK_NO_NCQ_TRIM | + ATA_QUIRK_ZERO_AFTER_TRIM | + ATA_QUIRK_NO_NCQ_ON_ATI, }, + { "FCCT*M500*", NULL, ATA_QUIRK_NO_NCQ_TRIM | + ATA_QUIRK_ZERO_AFTER_TRIM }, /* devices that don't properly handle TRIM commands */ - { "SuperSSpeed S238*", NULL, ATA_HORKAGE_NOTRIM }, - { "M88V29*", NULL, ATA_HORKAGE_NOTRIM }, + { "SuperSSpeed S238*", NULL, ATA_QUIRK_NOTRIM }, + { "M88V29*", NULL, ATA_QUIRK_NOTRIM }, /* * As defined, the DRAT (Deterministic Read After Trim) and RZAT @@ -4223,14 +4224,14 @@ 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 }, - { "SAMSUNG*SSD*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM }, - { "SAMSUNG*MZ7KM*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM }, - { "ST[1248][0248]0[FH]*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM }, + { "Micron*", NULL, ATA_QUIRK_ZERO_AFTER_TRIM }, + { "Crucial*", NULL, ATA_QUIRK_ZERO_AFTER_TRIM }, + { "INTEL*SSD*", NULL, ATA_QUIRK_ZERO_AFTER_TRIM }, + { "SSD*INTEL*", NULL, ATA_QUIRK_ZERO_AFTER_TRIM }, + { "Samsung*SSD*", NULL, ATA_QUIRK_ZERO_AFTER_TRIM }, + { "SAMSUNG*SSD*", NULL, ATA_QUIRK_ZERO_AFTER_TRIM }, + { "SAMSUNG*MZ7KM*", NULL, ATA_QUIRK_ZERO_AFTER_TRIM }, + { "ST[1248][0248]0[FH]*", NULL, ATA_QUIRK_ZERO_AFTER_TRIM }, /* * Some WD SATA-I drives spin up and down erratically when the link @@ -4241,36 +4242,36 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { * * https://bugzilla.kernel.org/show_bug.cgi?id=57211 */ - { "WDC WD800JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM }, - { "WDC WD1200JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM }, - { "WDC WD1600JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM }, - { "WDC WD2000JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM }, - { "WDC WD2500JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM }, - { "WDC WD3000JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM }, - { "WDC WD3200JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM }, + { "WDC WD800JD-*", NULL, ATA_QUIRK_WD_BROKEN_LPM }, + { "WDC WD1200JD-*", NULL, ATA_QUIRK_WD_BROKEN_LPM }, + { "WDC WD1600JD-*", NULL, ATA_QUIRK_WD_BROKEN_LPM }, + { "WDC WD2000JD-*", NULL, ATA_QUIRK_WD_BROKEN_LPM }, + { "WDC WD2500JD-*", NULL, ATA_QUIRK_WD_BROKEN_LPM }, + { "WDC WD3000JD-*", NULL, ATA_QUIRK_WD_BROKEN_LPM }, + { "WDC WD3200JD-*", NULL, ATA_QUIRK_WD_BROKEN_LPM }, /* * This sata dom device goes on a walkabout when the ATA_LOG_DIRECTORY * log page is accessed. Ensure we never ask for this log page with * these devices. */ - { "SATADOM-ML 3ME", NULL, ATA_HORKAGE_NO_LOG_DIR }, + { "SATADOM-ML 3ME", NULL, ATA_QUIRK_NO_LOG_DIR }, /* Buggy FUA */ - { "Maxtor", "BANC1G10", ATA_HORKAGE_NO_FUA }, - { "WDC*WD2500J*", NULL, ATA_HORKAGE_NO_FUA }, - { "OCZ-VERTEX*", NULL, ATA_HORKAGE_NO_FUA }, - { "INTEL*SSDSC2CT*", NULL, ATA_HORKAGE_NO_FUA }, + { "Maxtor", "BANC1G10", ATA_QUIRK_NO_FUA }, + { "WDC*WD2500J*", NULL, ATA_QUIRK_NO_FUA }, + { "OCZ-VERTEX*", NULL, ATA_QUIRK_NO_FUA }, + { "INTEL*SSDSC2CT*", NULL, ATA_QUIRK_NO_FUA }, /* End Marker */ { } }; -static unsigned long ata_dev_blacklisted(const struct ata_device *dev) +static unsigned int ata_dev_quirks(const struct ata_device *dev) { unsigned char model_num[ATA_ID_PROD_LEN + 1]; unsigned char model_rev[ATA_ID_FW_REV_LEN + 1]; - const struct ata_blacklist_entry *ad = ata_device_blacklist; + const struct ata_dev_quirks_entry *ad = __ata_dev_quirks; ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); ata_id_c_string(dev->id, model_rev, ATA_ID_FW_REV, sizeof(model_rev)); @@ -4278,9 +4279,9 @@ static unsigned long ata_dev_blacklisted(const struct ata_device *dev) while (ad->model_num) { if (glob_match(ad->model_num, model_num)) { if (ad->model_rev == NULL) - return ad->horkage; + return ad->quirks; if (glob_match(ad->model_rev, model_rev)) - return ad->horkage; + return ad->quirks; } ad++; } @@ -4297,7 +4298,7 @@ static bool ata_dev_nodma(const struct ata_device *dev) if ((dev->link->ap->flags & ATA_FLAG_PIO_POLLING) && (dev->flags & ATA_DFLAG_CDB_INTR)) return true; - return dev->horkage & ATA_HORKAGE_NODMA; + return dev->quirks & ATA_QUIRK_NODMA; } /** @@ -4310,7 +4311,7 @@ static bool ata_dev_nodma(const struct ata_device *dev) static int ata_is_40wire(struct ata_device *dev) { - if (dev->horkage & ATA_HORKAGE_IVB) + if (dev->quirks & ATA_QUIRK_IVB) return ata_drive_40wire_relaxed(dev->id); return ata_drive_40wire(dev->id); } @@ -4372,8 +4373,7 @@ static int cable_is_40wire(struct ata_port *ap) * * Compute supported xfermask of @dev and store it in * dev->*_mask. This function is responsible for applying all - * known limits including host controller limits, device - * blacklist, etc... + * known limits including host controller limits, device quirks, etc... * * LOCKING: * None. @@ -4589,7 +4589,7 @@ int atapi_check_dma(struct ata_queued_cmd *qc) /* Don't allow DMA if it isn't multiple of 16 bytes. Quite a * few ATAPI devices choke on such DMA requests. */ - if (!(qc->dev->horkage & ATA_HORKAGE_ATAPI_MOD16_DMA) && + if (!(qc->dev->quirks & ATA_QUIRK_ATAPI_MOD16_DMA) && unlikely(qc->nbytes & 15)) return 1; @@ -5369,7 +5369,7 @@ void ata_dev_init(struct ata_device *dev) */ spin_lock_irqsave(ap->lock, flags); dev->flags &= ~ATA_DFLAG_INIT_MASK; - dev->horkage = 0; + dev->quirks = 0; spin_unlock_irqrestore(ap->lock, flags); memset((void *)dev + ATA_DEVICE_CLEAR_BEGIN, 0, @@ -6298,12 +6298,12 @@ EXPORT_SYMBOL_GPL(ata_platform_remove_one); { "no" #name, .lflags_on = (flags) }, \ { #name, .lflags_off = (flags) } -#define force_horkage_on(name, flag) \ - { #name, .horkage_on = (flag) } +#define force_quirk_on(name, flag) \ + { #name, .quirk_on = (flag) } -#define force_horkage_onoff(name, flag) \ - { "no" #name, .horkage_on = (flag) }, \ - { #name, .horkage_off = (flag) } +#define force_quirk_onoff(name, flag) \ + { "no" #name, .quirk_on = (flag) }, \ + { #name, .quirk_off = (flag) } static const struct ata_force_param force_tbl[] __initconst = { force_cbl(40c, ATA_CBL_PATA40), @@ -6357,32 +6357,32 @@ static const struct ata_force_param force_tbl[] __initconst = { force_lflag_on(rstonce, ATA_LFLAG_RST_ONCE), force_lflag_onoff(dbdelay, ATA_LFLAG_NO_DEBOUNCE_DELAY), - force_horkage_onoff(ncq, ATA_HORKAGE_NONCQ), - force_horkage_onoff(ncqtrim, ATA_HORKAGE_NO_NCQ_TRIM), - force_horkage_onoff(ncqati, ATA_HORKAGE_NO_NCQ_ON_ATI), + force_quirk_onoff(ncq, ATA_QUIRK_NONCQ), + force_quirk_onoff(ncqtrim, ATA_QUIRK_NO_NCQ_TRIM), + force_quirk_onoff(ncqati, ATA_QUIRK_NO_NCQ_ON_ATI), - force_horkage_onoff(trim, ATA_HORKAGE_NOTRIM), - force_horkage_on(trim_zero, ATA_HORKAGE_ZERO_AFTER_TRIM), - force_horkage_on(max_trim_128m, ATA_HORKAGE_MAX_TRIM_128M), + force_quirk_onoff(trim, ATA_QUIRK_NOTRIM), + force_quirk_on(trim_zero, ATA_QUIRK_ZERO_AFTER_TRIM), + force_quirk_on(max_trim_128m, ATA_QUIRK_MAX_TRIM_128M), - force_horkage_onoff(dma, ATA_HORKAGE_NODMA), - force_horkage_on(atapi_dmadir, ATA_HORKAGE_ATAPI_DMADIR), - force_horkage_on(atapi_mod16_dma, ATA_HORKAGE_ATAPI_MOD16_DMA), + force_quirk_onoff(dma, ATA_QUIRK_NODMA), + force_quirk_on(atapi_dmadir, ATA_QUIRK_ATAPI_DMADIR), + force_quirk_on(atapi_mod16_dma, ATA_QUIRK_ATAPI_MOD16_DMA), - force_horkage_onoff(dmalog, ATA_HORKAGE_NO_DMA_LOG), - force_horkage_onoff(iddevlog, ATA_HORKAGE_NO_ID_DEV_LOG), - force_horkage_onoff(logdir, ATA_HORKAGE_NO_LOG_DIR), + force_quirk_onoff(dmalog, ATA_QUIRK_NO_DMA_LOG), + force_quirk_onoff(iddevlog, ATA_QUIRK_NO_ID_DEV_LOG), + force_quirk_onoff(logdir, ATA_QUIRK_NO_LOG_DIR), - force_horkage_on(max_sec_128, ATA_HORKAGE_MAX_SEC_128), - force_horkage_on(max_sec_1024, ATA_HORKAGE_MAX_SEC_1024), - force_horkage_on(max_sec_lba48, ATA_HORKAGE_MAX_SEC_LBA48), + force_quirk_on(max_sec_128, ATA_QUIRK_MAX_SEC_128), + force_quirk_on(max_sec_1024, ATA_QUIRK_MAX_SEC_1024), + force_quirk_on(max_sec_lba48, ATA_QUIRK_MAX_SEC_LBA48), - force_horkage_onoff(lpm, ATA_HORKAGE_NOLPM), - force_horkage_onoff(setxfer, ATA_HORKAGE_NOSETXFER), - force_horkage_on(dump_id, ATA_HORKAGE_DUMP_ID), - force_horkage_onoff(fua, ATA_HORKAGE_NO_FUA), + force_quirk_onoff(lpm, ATA_QUIRK_NOLPM), + force_quirk_onoff(setxfer, ATA_QUIRK_NOSETXFER), + force_quirk_on(dump_id, ATA_QUIRK_DUMP_ID), + force_quirk_onoff(fua, ATA_QUIRK_NO_FUA), - force_horkage_on(disable, ATA_HORKAGE_DISABLE), + force_quirk_on(disable, ATA_QUIRK_DISABLE), }; static int __init ata_parse_force_one(char **cur, diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c index 48660d445602..ecd37649d4d4 100644 --- a/drivers/ata/libata-sata.c +++ b/drivers/ata/libata-sata.c @@ -818,7 +818,7 @@ static ssize_t ata_scsi_lpm_store(struct device *device, ata_for_each_link(link, ap, EDGE) { ata_for_each_dev(dev, &ap->link, ENABLED) { - if (dev->horkage & ATA_HORKAGE_NOLPM) { + if (dev->quirks & ATA_QUIRK_NOLPM) { count = -EOPNOTSUPP; goto out_unlock; } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index d6f5e25e1ed8..3a442f564b0d 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2083,7 +2083,7 @@ static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf) if (ata_id_has_trim(args->id)) { u64 max_blocks = 65535 * ATA_MAX_TRIM_RNUM; - if (dev->horkage & ATA_HORKAGE_MAX_TRIM_128M) + if (dev->quirks & ATA_QUIRK_MAX_TRIM_128M) max_blocks = 128 << (20 - SECTOR_SHIFT); put_unaligned_be64(max_blocks, &rbuf[36]); @@ -2561,11 +2561,11 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf) rbuf[15] = lowest_aligned; if (ata_id_has_trim(args->id) && - !(dev->horkage & ATA_HORKAGE_NOTRIM)) { + !(dev->quirks & ATA_QUIRK_NOTRIM)) { rbuf[14] |= 0x80; /* LBPME */ if (ata_id_has_zero_after_trim(args->id) && - dev->horkage & ATA_HORKAGE_ZERO_AFTER_TRIM) { + dev->quirks & ATA_QUIRK_ZERO_AFTER_TRIM) { ata_dev_info(dev, "Enabling discard_zeroes_data\n"); rbuf[14] |= 0x40; /* LBPRZ */ } @@ -3229,8 +3229,7 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) } scsi_16_lba_len(cdb, &block, &n_block); - if (!unmap || - (dev->horkage & ATA_HORKAGE_NOTRIM) || + if (!unmap || (dev->quirks & ATA_QUIRK_NOTRIM) || !ata_id_has_trim(dev->id)) { fp = 1; bp = 3; diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 250f7dae05fd..06868ec5b1fd 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -970,7 +970,7 @@ fsm_start: * We ignore ERR here to workaround and proceed sending * the CDB. */ - if (!(qc->dev->horkage & ATA_HORKAGE_STUCK_ERR)) { + if (!(qc->dev->quirks & ATA_QUIRK_STUCK_ERR)) { ata_ehi_push_desc(ehi, "ST_FIRST: " "DRQ=1 with device error, " "dev_stat 0x%X", status); @@ -1045,8 +1045,8 @@ fsm_start: * IDENTIFY, it's likely a phantom * device. Mark hint. */ - if (qc->dev->horkage & - ATA_HORKAGE_DIAGNOSTIC) + if (qc->dev->quirks & + ATA_QUIRK_DIAGNOSTIC) qc->err_mask |= AC_ERR_NODEV_HINT; } else { @@ -1762,7 +1762,7 @@ unsigned int ata_sff_dev_classify(struct ata_device *dev, int present, /* see if device passed diags: continue and warn later */ if (err == 0) /* diagnostic fail : do nothing _YET_ */ - dev->horkage |= ATA_HORKAGE_DIAGNOSTIC; + dev->quirks |= ATA_QUIRK_DIAGNOSTIC; else if (err == 1) /* do nothing */ ; else if ((dev->devno == 0) && (err == 0x81)) @@ -1781,7 +1781,7 @@ unsigned int ata_sff_dev_classify(struct ata_device *dev, int present, * device signature is invalid with diagnostic * failure. */ - if (present && (dev->horkage & ATA_HORKAGE_DIAGNOSTIC)) + if (present && (dev->quirks & ATA_QUIRK_DIAGNOSTIC)) class = ATA_DEV_ATA; else class = ATA_DEV_NONE; diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index 9e24c33388f9..48800cd0e75d 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -617,10 +617,10 @@ show_ata_dev_trim(struct device *dev, if (!ata_id_has_trim(ata_dev->id)) mode = "unsupported"; - else if (ata_dev->horkage & ATA_HORKAGE_NOTRIM) + else if (ata_dev->quirks & ATA_QUIRK_NOTRIM) mode = "forced_unsupported"; - else if (ata_dev->horkage & ATA_HORKAGE_NO_NCQ_TRIM) - mode = "forced_unqueued"; + else if (ata_dev->quirks & ATA_QUIRK_NO_NCQ_TRIM) + mode = "forced_unqueued"; else if (ata_fpdma_dsm_supported(ata_dev)) mode = "queued"; else diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index 2fe3fb6102ce..042f6ad1f7c6 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -519,9 +519,9 @@ static void it821x_dev_config(struct ata_device *adev) } /* This is a controller firmware triggered funny, don't report the drive faulty! */ - adev->horkage &= ~ATA_HORKAGE_DIAGNOSTIC; + adev->quirks &= ~ATA_QUIRK_DIAGNOSTIC; /* No HPA in 'smart' mode */ - adev->horkage |= ATA_HORKAGE_BROKEN_HPA; + adev->quirks |= ATA_QUIRK_BROKEN_HPA; } /** diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index cc77c0248284..354b68ef91bc 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -616,7 +616,7 @@ static void sil_dev_config(struct ata_device *dev) unsigned char model_num[ATA_ID_PROD_LEN + 1]; /* This controller doesn't support trim */ - dev->horkage |= ATA_HORKAGE_NOTRIM; + dev->quirks |= ATA_QUIRK_NOTRIM; ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); diff --git a/include/linux/libata.h b/include/linux/libata.h index 17394098bee9..05dd7038ab30 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -362,40 +362,41 @@ enum { */ ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 8, - /* Horkage types. May be set by libata or controller on drives - (some horkage may be drive/controller pair dependent */ - - ATA_HORKAGE_DIAGNOSTIC = (1 << 0), /* Failed boot diag */ - ATA_HORKAGE_NODMA = (1 << 1), /* DMA problems */ - ATA_HORKAGE_NONCQ = (1 << 2), /* Don't use NCQ */ - ATA_HORKAGE_MAX_SEC_128 = (1 << 3), /* Limit max sects to 128 */ - ATA_HORKAGE_BROKEN_HPA = (1 << 4), /* Broken HPA */ - ATA_HORKAGE_DISABLE = (1 << 5), /* Disable it */ - ATA_HORKAGE_HPA_SIZE = (1 << 6), /* native size off by one */ - ATA_HORKAGE_IVB = (1 << 8), /* cbl det validity bit bugs */ - ATA_HORKAGE_STUCK_ERR = (1 << 9), /* stuck ERR on next PACKET */ - ATA_HORKAGE_BRIDGE_OK = (1 << 10), /* no bridge limits */ - ATA_HORKAGE_ATAPI_MOD16_DMA = (1 << 11), /* use ATAPI DMA for commands - not multiple of 16 bytes */ - ATA_HORKAGE_FIRMWARE_WARN = (1 << 12), /* firmware update warning */ - ATA_HORKAGE_1_5_GBPS = (1 << 13), /* force 1.5 Gbps */ - ATA_HORKAGE_NOSETXFER = (1 << 14), /* skip SETXFER, SATA only */ - ATA_HORKAGE_BROKEN_FPDMA_AA = (1 << 15), /* skip AA */ - ATA_HORKAGE_DUMP_ID = (1 << 16), /* dump IDENTIFY data */ - ATA_HORKAGE_MAX_SEC_LBA48 = (1 << 17), /* Set max sects to 65535 */ - ATA_HORKAGE_ATAPI_DMADIR = (1 << 18), /* device requires dmadir */ - ATA_HORKAGE_NO_NCQ_TRIM = (1 << 19), /* don't use queued TRIM */ - ATA_HORKAGE_NOLPM = (1 << 20), /* don't use LPM */ - ATA_HORKAGE_WD_BROKEN_LPM = (1 << 21), /* some WDs have broken LPM */ - ATA_HORKAGE_ZERO_AFTER_TRIM = (1 << 22),/* guarantees zero after trim */ - ATA_HORKAGE_NO_DMA_LOG = (1 << 23), /* don't use DMA for log read */ - ATA_HORKAGE_NOTRIM = (1 << 24), /* don't use TRIM */ - ATA_HORKAGE_MAX_SEC_1024 = (1 << 25), /* Limit max sects to 1024 */ - ATA_HORKAGE_MAX_TRIM_128M = (1 << 26), /* Limit max trim size to 128M */ - ATA_HORKAGE_NO_NCQ_ON_ATI = (1 << 27), /* Disable NCQ on ATI chipset */ - ATA_HORKAGE_NO_ID_DEV_LOG = (1 << 28), /* Identify device log missing */ - ATA_HORKAGE_NO_LOG_DIR = (1 << 29), /* Do not read log directory */ - ATA_HORKAGE_NO_FUA = (1 << 30), /* Do not use FUA */ + /* + * Quirk flags: may be set by libata or controller drivers on drives. + * Some quirks may be drive/controller pair dependent. + */ + ATA_QUIRK_DIAGNOSTIC = (1 << 0), /* Failed boot diag */ + ATA_QUIRK_NODMA = (1 << 1), /* DMA problems */ + ATA_QUIRK_NONCQ = (1 << 2), /* Do not use NCQ */ + ATA_QUIRK_MAX_SEC_128 = (1 << 3), /* Limit max sects to 128 */ + ATA_QUIRK_BROKEN_HPA = (1 << 4), /* Broken HPA */ + ATA_QUIRK_DISABLE = (1 << 5), /* Disable it */ + ATA_QUIRK_HPA_SIZE = (1 << 6), /* Native size off by one */ + ATA_QUIRK_IVB = (1 << 8), /* CBL det validity bit bugs */ + ATA_QUIRK_STUCK_ERR = (1 << 9), /* Stuck ERR on next PACKET */ + ATA_QUIRK_BRIDGE_OK = (1 << 10), /* No bridge limits */ + ATA_QUIRK_ATAPI_MOD16_DMA = (1 << 11), /* Use ATAPI DMA for commands */ + /* not multiple of 16 bytes */ + ATA_QUIRK_FIRMWARE_WARN = (1 << 12), /* Firmware update warning */ + ATA_QUIRK_1_5_GBPS = (1 << 13), /* Force 1.5 Gbps */ + ATA_QUIRK_NOSETXFER = (1 << 14), /* Skip SETXFER, SATA only */ + ATA_QUIRK_BROKEN_FPDMA_AA = (1 << 15), /* Skip AA */ + ATA_QUIRK_DUMP_ID = (1 << 16), /* Dump IDENTIFY data */ + ATA_QUIRK_MAX_SEC_LBA48 = (1 << 17), /* Set max sects to 65535 */ + ATA_QUIRK_ATAPI_DMADIR = (1 << 18), /* Device requires dmadir */ + ATA_QUIRK_NO_NCQ_TRIM = (1 << 19), /* Do not use queued TRIM */ + ATA_QUIRK_NOLPM = (1 << 20), /* Do not use LPM */ + ATA_QUIRK_WD_BROKEN_LPM = (1 << 21), /* Some WDs have broken LPM */ + ATA_QUIRK_ZERO_AFTER_TRIM = (1 << 22), /* Guarantees zero after trim */ + ATA_QUIRK_NO_DMA_LOG = (1 << 23), /* Do not use DMA for log read */ + ATA_QUIRK_NOTRIM = (1 << 24), /* Do not use TRIM */ + ATA_QUIRK_MAX_SEC_1024 = (1 << 25), /* Limit max sects to 1024 */ + ATA_QUIRK_MAX_TRIM_128M = (1 << 26), /* Limit max trim size to 128M */ + ATA_QUIRK_NO_NCQ_ON_ATI = (1 << 27), /* Disable NCQ on ATI chipset */ + ATA_QUIRK_NO_ID_DEV_LOG = (1 << 28), /* Identify device log missing */ + ATA_QUIRK_NO_LOG_DIR = (1 << 29), /* Do not read log directory */ + ATA_QUIRK_NO_FUA = (1 << 30), /* Do not use FUA */ /* DMA mask for user DMA control: User visible values; DO NOT renumber */ @@ -663,7 +664,7 @@ struct ata_cpr_log { struct ata_device { struct ata_link *link; unsigned int devno; /* 0 or 1 */ - unsigned int horkage; /* List of broken features */ + unsigned int quirks; /* List of broken features */ unsigned long flags; /* ATA_DFLAG_xxx */ struct scsi_device *sdev; /* attached SCSI device */ void *private_data; From 58157d607aecb4e05ab793408038b014c84e466f Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 18 Jul 2024 16:54:03 +0900 Subject: [PATCH 06/39] ata: libata: Print quirks applied to devices Introduce the function ata_dev_print_quirks() to print the quirk flags that will be applied to a scanned device. This new function is called from ata_dev_quirks() when a match on a device model or device model and revision is found for a device in the __ata_dev_quirks array. To implement this function, the ATA_QUIRK_ flags are redefined using the new enum ata_quirk which defines the bit shift for each quirk flag. The array of strings ata_quirk_names is used to define the name of each flag, which are printed by ata_dev_print_quirks(). Example output for a device listed in the __ata_dev_quirks array and which has the ATA_QUIRK_DISABLE flag applied: [10193.461270] ata1: SATA link up 6.0 Gbps (SStatus 133 SControl 300) [10193.469190] ata1.00: Model 'ASMT109x- Config', rev '2143 5', applying quirks: disable [10193.469195] ata1.00: unsupported device, disabling [10193.481564] ata1.00: disable device enum ata_quirk also defines the __ATA_QUIRK_MAX value as one plus the last quirk flag defined. This value is used in ata_dev_quirks() to add a build time check that all quirk flags fit within the unsigned int (32-bits) quirks field of struct ata_device. Signed-off-by: Damien Le Moal Reviewed-by: Igor Pylypiv Reviewed-by: Niklas Cassel --- drivers/ata/libata-core.c | 76 ++++++++++++++++++++++++++-- include/linux/libata.h | 104 ++++++++++++++++++++++++++------------ 2 files changed, 142 insertions(+), 38 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 19b041bd7588..fc9fcfda42b8 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -3988,6 +3988,69 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, return rc; } +static const char * const ata_quirk_names[] = { + [__ATA_QUIRK_DIAGNOSTIC] = "diagnostic", + [__ATA_QUIRK_NODMA] = "nodma", + [__ATA_QUIRK_NONCQ] = "noncq", + [__ATA_QUIRK_MAX_SEC_128] = "maxsec128", + [__ATA_QUIRK_BROKEN_HPA] = "brokenhpa", + [__ATA_QUIRK_DISABLE] = "disable", + [__ATA_QUIRK_HPA_SIZE] = "hpasize", + [__ATA_QUIRK_IVB] = "ivb", + [__ATA_QUIRK_STUCK_ERR] = "stuckerr", + [__ATA_QUIRK_BRIDGE_OK] = "bridgeok", + [__ATA_QUIRK_ATAPI_MOD16_DMA] = "atapimod16dma", + [__ATA_QUIRK_FIRMWARE_WARN] = "firmwarewarn", + [__ATA_QUIRK_1_5_GBPS] = "1.5gbps", + [__ATA_QUIRK_NOSETXFER] = "nosetxfer", + [__ATA_QUIRK_BROKEN_FPDMA_AA] = "brokenfpdmaaa", + [__ATA_QUIRK_DUMP_ID] = "dumpid", + [__ATA_QUIRK_MAX_SEC_LBA48] = "maxseclba48", + [__ATA_QUIRK_ATAPI_DMADIR] = "atapidmadir", + [__ATA_QUIRK_NO_NCQ_TRIM] = "noncqtrim", + [__ATA_QUIRK_NOLPM] = "nolpm", + [__ATA_QUIRK_WD_BROKEN_LPM] = "wdbrokenlpm", + [__ATA_QUIRK_ZERO_AFTER_TRIM] = "zeroaftertrim", + [__ATA_QUIRK_NO_DMA_LOG] = "nodmalog", + [__ATA_QUIRK_NOTRIM] = "notrim", + [__ATA_QUIRK_MAX_SEC_1024] = "maxsec1024", + [__ATA_QUIRK_MAX_TRIM_128M] = "maxtrim128m", + [__ATA_QUIRK_NO_NCQ_ON_ATI] = "noncqonati", + [__ATA_QUIRK_NO_ID_DEV_LOG] = "noiddevlog", + [__ATA_QUIRK_NO_LOG_DIR] = "nologdir", + [__ATA_QUIRK_NO_FUA] = "nofua", +}; + +static void ata_dev_print_quirks(const struct ata_device *dev, + const char *model, const char *rev, + unsigned int quirks) +{ + int n = 0, i; + size_t sz; + char *str; + + if (!quirks) + return; + + sz = 64 + ARRAY_SIZE(ata_quirk_names) * 16; + str = kmalloc(sz, GFP_KERNEL); + if (!str) + return; + + n = snprintf(str, sz, "Model '%s', rev '%s', applying quirks:", + model, rev); + + for (i = 0; i < ARRAY_SIZE(ata_quirk_names); i++) { + if (quirks & (1U << i)) + n += snprintf(str + n, sz - n, + " %s", ata_quirk_names[i]); + } + + ata_dev_warn(dev, "%s\n", str); + + kfree(str); +} + struct ata_dev_quirks_entry { const char *model_num; const char *model_rev; @@ -4273,15 +4336,18 @@ static unsigned int ata_dev_quirks(const struct ata_device *dev) unsigned char model_rev[ATA_ID_FW_REV_LEN + 1]; const struct ata_dev_quirks_entry *ad = __ata_dev_quirks; + /* dev->quirks is an unsigned int. */ + BUILD_BUG_ON(__ATA_QUIRK_MAX > 32); + ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); ata_id_c_string(dev->id, model_rev, ATA_ID_FW_REV, sizeof(model_rev)); while (ad->model_num) { - if (glob_match(ad->model_num, model_num)) { - if (ad->model_rev == NULL) - return ad->quirks; - if (glob_match(ad->model_rev, model_rev)) - return ad->quirks; + if (glob_match(ad->model_num, model_num) && + (!ad->model_rev || glob_match(ad->model_rev, model_rev))) { + ata_dev_print_quirks(dev, model_num, model_rev, + ad->quirks); + return ad->quirks; } ad++; } diff --git a/include/linux/libata.h b/include/linux/libata.h index 05dd7038ab30..d598ef690e50 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -55,6 +55,46 @@ /* defines only for the constants which don't work well as enums */ #define ATA_TAG_POISON 0xfafbfcfdU +/* + * Quirk flags bits. + * ata_device->quirks is an unsigned int, so __ATA_QUIRK_MAX must not exceed 32. + */ +enum ata_quirks { + __ATA_QUIRK_DIAGNOSTIC, /* Failed boot diag */ + __ATA_QUIRK_NODMA, /* DMA problems */ + __ATA_QUIRK_NONCQ, /* Don't use NCQ */ + __ATA_QUIRK_MAX_SEC_128, /* Limit max sects to 128 */ + __ATA_QUIRK_BROKEN_HPA, /* Broken HPA */ + __ATA_QUIRK_DISABLE, /* Disable it */ + __ATA_QUIRK_HPA_SIZE, /* Native size off by one */ + __ATA_QUIRK_IVB, /* cbl det validity bit bugs */ + __ATA_QUIRK_STUCK_ERR, /* Stuck ERR on next PACKET */ + __ATA_QUIRK_BRIDGE_OK, /* No bridge limits */ + __ATA_QUIRK_ATAPI_MOD16_DMA, /* Use ATAPI DMA for commands that */ + /* are not a multiple of 16 bytes */ + __ATA_QUIRK_FIRMWARE_WARN, /* Firmware update warning */ + __ATA_QUIRK_1_5_GBPS, /* Force 1.5 Gbps */ + __ATA_QUIRK_NOSETXFER, /* Skip SETXFER, SATA only */ + __ATA_QUIRK_BROKEN_FPDMA_AA, /* Skip AA */ + __ATA_QUIRK_DUMP_ID, /* Dump IDENTIFY data */ + __ATA_QUIRK_MAX_SEC_LBA48, /* Set max sects to 65535 */ + __ATA_QUIRK_ATAPI_DMADIR, /* Device requires dmadir */ + __ATA_QUIRK_NO_NCQ_TRIM, /* Do not use queued TRIM */ + __ATA_QUIRK_NOLPM, /* Do not use LPM */ + __ATA_QUIRK_WD_BROKEN_LPM, /* Some WDs have broken LPM */ + __ATA_QUIRK_ZERO_AFTER_TRIM, /* Guarantees zero after trim */ + __ATA_QUIRK_NO_DMA_LOG, /* Do not use DMA for log read */ + __ATA_QUIRK_NOTRIM, /* Do not use TRIM */ + __ATA_QUIRK_MAX_SEC_1024, /* Limit max sects to 1024 */ + __ATA_QUIRK_MAX_TRIM_128M, /* Limit max trim size to 128M */ + __ATA_QUIRK_NO_NCQ_ON_ATI, /* Disable NCQ on ATI chipset */ + __ATA_QUIRK_NO_ID_DEV_LOG, /* Identify device log missing */ + __ATA_QUIRK_NO_LOG_DIR, /* Do not read log directory */ + __ATA_QUIRK_NO_FUA, /* Do not use FUA */ + + __ATA_QUIRK_MAX, +}; + enum { /* various global constants */ LIBATA_MAX_PRD = ATA_MAX_PRD / 2, @@ -366,40 +406,38 @@ enum { * Quirk flags: may be set by libata or controller drivers on drives. * Some quirks may be drive/controller pair dependent. */ - ATA_QUIRK_DIAGNOSTIC = (1 << 0), /* Failed boot diag */ - ATA_QUIRK_NODMA = (1 << 1), /* DMA problems */ - ATA_QUIRK_NONCQ = (1 << 2), /* Do not use NCQ */ - ATA_QUIRK_MAX_SEC_128 = (1 << 3), /* Limit max sects to 128 */ - ATA_QUIRK_BROKEN_HPA = (1 << 4), /* Broken HPA */ - ATA_QUIRK_DISABLE = (1 << 5), /* Disable it */ - ATA_QUIRK_HPA_SIZE = (1 << 6), /* Native size off by one */ - ATA_QUIRK_IVB = (1 << 8), /* CBL det validity bit bugs */ - ATA_QUIRK_STUCK_ERR = (1 << 9), /* Stuck ERR on next PACKET */ - ATA_QUIRK_BRIDGE_OK = (1 << 10), /* No bridge limits */ - ATA_QUIRK_ATAPI_MOD16_DMA = (1 << 11), /* Use ATAPI DMA for commands */ - /* not multiple of 16 bytes */ - ATA_QUIRK_FIRMWARE_WARN = (1 << 12), /* Firmware update warning */ - ATA_QUIRK_1_5_GBPS = (1 << 13), /* Force 1.5 Gbps */ - ATA_QUIRK_NOSETXFER = (1 << 14), /* Skip SETXFER, SATA only */ - ATA_QUIRK_BROKEN_FPDMA_AA = (1 << 15), /* Skip AA */ - ATA_QUIRK_DUMP_ID = (1 << 16), /* Dump IDENTIFY data */ - ATA_QUIRK_MAX_SEC_LBA48 = (1 << 17), /* Set max sects to 65535 */ - ATA_QUIRK_ATAPI_DMADIR = (1 << 18), /* Device requires dmadir */ - ATA_QUIRK_NO_NCQ_TRIM = (1 << 19), /* Do not use queued TRIM */ - ATA_QUIRK_NOLPM = (1 << 20), /* Do not use LPM */ - ATA_QUIRK_WD_BROKEN_LPM = (1 << 21), /* Some WDs have broken LPM */ - ATA_QUIRK_ZERO_AFTER_TRIM = (1 << 22), /* Guarantees zero after trim */ - ATA_QUIRK_NO_DMA_LOG = (1 << 23), /* Do not use DMA for log read */ - ATA_QUIRK_NOTRIM = (1 << 24), /* Do not use TRIM */ - ATA_QUIRK_MAX_SEC_1024 = (1 << 25), /* Limit max sects to 1024 */ - ATA_QUIRK_MAX_TRIM_128M = (1 << 26), /* Limit max trim size to 128M */ - ATA_QUIRK_NO_NCQ_ON_ATI = (1 << 27), /* Disable NCQ on ATI chipset */ - ATA_QUIRK_NO_ID_DEV_LOG = (1 << 28), /* Identify device log missing */ - ATA_QUIRK_NO_LOG_DIR = (1 << 29), /* Do not read log directory */ - ATA_QUIRK_NO_FUA = (1 << 30), /* Do not use FUA */ + ATA_QUIRK_DIAGNOSTIC = (1U << __ATA_QUIRK_DIAGNOSTIC), + ATA_QUIRK_NODMA = (1U << __ATA_QUIRK_NODMA), + ATA_QUIRK_NONCQ = (1U << __ATA_QUIRK_NONCQ), + ATA_QUIRK_MAX_SEC_128 = (1U << __ATA_QUIRK_MAX_SEC_128), + ATA_QUIRK_BROKEN_HPA = (1U << __ATA_QUIRK_BROKEN_HPA), + ATA_QUIRK_DISABLE = (1U << __ATA_QUIRK_DISABLE), + ATA_QUIRK_HPA_SIZE = (1U << __ATA_QUIRK_HPA_SIZE), + ATA_QUIRK_IVB = (1U << __ATA_QUIRK_IVB), + ATA_QUIRK_STUCK_ERR = (1U << __ATA_QUIRK_STUCK_ERR), + ATA_QUIRK_BRIDGE_OK = (1U << __ATA_QUIRK_BRIDGE_OK), + ATA_QUIRK_ATAPI_MOD16_DMA = (1U << __ATA_QUIRK_ATAPI_MOD16_DMA), + ATA_QUIRK_FIRMWARE_WARN = (1U << __ATA_QUIRK_FIRMWARE_WARN), + ATA_QUIRK_1_5_GBPS = (1U << __ATA_QUIRK_1_5_GBPS), + ATA_QUIRK_NOSETXFER = (1U << __ATA_QUIRK_NOSETXFER), + ATA_QUIRK_BROKEN_FPDMA_AA = (1U << __ATA_QUIRK_BROKEN_FPDMA_AA), + ATA_QUIRK_DUMP_ID = (1U << __ATA_QUIRK_DUMP_ID), + ATA_QUIRK_MAX_SEC_LBA48 = (1U << __ATA_QUIRK_MAX_SEC_LBA48), + ATA_QUIRK_ATAPI_DMADIR = (1U << __ATA_QUIRK_ATAPI_DMADIR), + ATA_QUIRK_NO_NCQ_TRIM = (1U << __ATA_QUIRK_NO_NCQ_TRIM), + ATA_QUIRK_NOLPM = (1U << __ATA_QUIRK_NOLPM), + ATA_QUIRK_WD_BROKEN_LPM = (1U << __ATA_QUIRK_WD_BROKEN_LPM), + ATA_QUIRK_ZERO_AFTER_TRIM = (1U << __ATA_QUIRK_ZERO_AFTER_TRIM), + ATA_QUIRK_NO_DMA_LOG = (1U << __ATA_QUIRK_NO_DMA_LOG), + ATA_QUIRK_NOTRIM = (1U << __ATA_QUIRK_NOTRIM), + ATA_QUIRK_MAX_SEC_1024 = (1U << __ATA_QUIRK_MAX_SEC_1024), + ATA_QUIRK_MAX_TRIM_128M = (1U << __ATA_QUIRK_MAX_TRIM_128M), + ATA_QUIRK_NO_NCQ_ON_ATI = (1U << __ATA_QUIRK_NO_NCQ_ON_ATI), + ATA_QUIRK_NO_ID_DEV_LOG = (1U << __ATA_QUIRK_NO_ID_DEV_LOG), + ATA_QUIRK_NO_LOG_DIR = (1U << __ATA_QUIRK_NO_LOG_DIR), + ATA_QUIRK_NO_FUA = (1U << __ATA_QUIRK_NO_FUA), - /* DMA mask for user DMA control: User visible values; DO NOT - renumber */ + /* User visible DMA mask for DMA control. DO NOT renumber. */ ATA_DMA_MASK_ATA = (1 << 0), /* DMA on ATA Disk */ ATA_DMA_MASK_ATAPI = (1 << 1), /* DMA on ATAPI */ ATA_DMA_MASK_CFA = (1 << 2), /* DMA on CF Card */ From 858048568c9e3887d8b19e101ee72f129d65cb15 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Fri, 26 Jul 2024 10:58:36 +0900 Subject: [PATCH 07/39] ata: pata_serverworks: Do not use the term blacklist Let's not use the term blacklist in the function serverworks_osb4_filter() documentation comment and rather simply refer to what that function looks at: the list of devices with groken UDMA5. While at it, also constify the values of the csb_bad_ata100 array. Of note is that all of this should probably be handled using libata quirk mechanism but it is unclear if these UDMA5 quirks are specific to this controller only. Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Igor Pylypiv --- drivers/ata/pata_serverworks.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index 549ff24a9823..4edddf6bcc15 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -46,10 +46,11 @@ #define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ #define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */ -/* Seagate Barracuda ATA IV Family drives in UDMA mode 5 - * can overrun their FIFOs when used with the CSB5 */ - -static const char *csb_bad_ata100[] = { +/* + * Seagate Barracuda ATA IV Family drives in UDMA mode 5 + * can overrun their FIFOs when used with the CSB5. + */ +static const char * const csb_bad_ata100[] = { "ST320011A", "ST340016A", "ST360021A", @@ -163,10 +164,11 @@ static unsigned int serverworks_osb4_filter(struct ata_device *adev, unsigned in * @adev: ATA device * @mask: Mask of proposed modes * - * Check the blacklist and disable UDMA5 if matched + * Check the list of devices with broken UDMA5 and + * disable UDMA5 if matched. */ - -static unsigned int serverworks_csb_filter(struct ata_device *adev, unsigned int mask) +static unsigned int serverworks_csb_filter(struct ata_device *adev, + unsigned int mask) { const char *p; char model_num[ATA_ID_PROD_LEN + 1]; From ca8040b071455d8485343d8f1ee9332a18575343 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Fri, 26 Jul 2024 11:07:17 +0900 Subject: [PATCH 08/39] ata: ahci: Rephrase comment to not use the term blacklist Rephrase the comment for the eMachines entry in the sysids array of ahci_broken_suspend() to not use the term blacklist. Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Igor Pylypiv --- drivers/ata/ahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index a05c17249448..45f63b09828a 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1370,7 +1370,7 @@ static bool ahci_broken_suspend(struct pci_dev *pdev) * V1.03 is known to be broken. V3.04 is known to * work. Between, there are V1.06, V2.06 and V3.03 * that we don't have much idea about. For now, - * blacklist anything older than V3.04. + * assume that anything older than V3.04 is broken. * * http://bugzilla.kernel.org/show_bug.cgi?id=15104 */ From 93b0f9e11ce511353c65b7f924cf5f95bd9c3aba Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Fri, 26 Jul 2024 11:14:11 +0900 Subject: [PATCH 09/39] ata: sata_sil: Rename sil_blacklist to sil_quirks Rename the array sil_blacklist to sil_quirks as this name is more neutral and is also consistent with how this driver define quirks with the SIL_QUIRK_XXX flags. Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Igor Pylypiv --- drivers/ata/sata_sil.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 354b68ef91bc..3a99f66198a9 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -128,7 +128,7 @@ static const struct pci_device_id sil_pci_tbl[] = { static const struct sil_drivelist { const char *product; unsigned int quirk; -} sil_blacklist [] = { +} sil_quirks[] = { { "ST320012AS", SIL_QUIRK_MOD15WRITE }, { "ST330013AS", SIL_QUIRK_MOD15WRITE }, { "ST340017AS", SIL_QUIRK_MOD15WRITE }, @@ -600,8 +600,8 @@ static void sil_thaw(struct ata_port *ap) * list, and apply the fixups to only the specific * devices/hosts/firmwares that need it. * - * 20040111 - Seagate drives affected by the Mod15Write bug are blacklisted - * The Maxtor quirk is in the blacklist, but I'm keeping the original + * 20040111 - Seagate drives affected by the Mod15Write bug are quirked + * The Maxtor quirk is in sil_quirks, but I'm keeping the original * pessimistic fix for the following reasons... * - There seems to be less info on it, only one device gleaned off the * Windows driver, maybe only one is affected. More info would be greatly @@ -620,9 +620,9 @@ static void sil_dev_config(struct ata_device *dev) ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); - for (n = 0; sil_blacklist[n].product; n++) - if (!strcmp(sil_blacklist[n].product, model_num)) { - quirks = sil_blacklist[n].quirk; + for (n = 0; sil_quirks[n].product; n++) + if (!strcmp(sil_quirks[n].product, model_num)) { + quirks = sil_quirks[n].quirk; break; } From 8a3f41a335e9d1c1d348b6849d7b1e99bb22d629 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Fri, 26 Jul 2024 11:20:27 +0900 Subject: [PATCH 10/39] ata: ata_piix: Remove useless comment in piix_init_sidpr() Remove the comment using the term "blacklist" from piix_init_sidpr(). That comment is useless given that the function piix_no_sidpr() name is clear about what is being checked. Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Igor Pylypiv --- drivers/ata/ata_piix.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index ec3c5bd1f813..093b940bc953 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -1446,7 +1446,6 @@ static int piix_init_sidpr(struct ata_host *host) if (hpriv->map[i] == IDE) return 0; - /* is it blacklisted? */ if (piix_no_sidpr(host)) return 0; From 022eb2792022a8b53b996bf75774f0c6a3b295bf Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Fri, 26 Jul 2024 11:28:37 +0900 Subject: [PATCH 11/39] ata: pata_cs5520: Rephrase file header comment Remove the use of the term "blacklist". What the comment using that term refers to does not seem to exist at all anyway as the driver does not have such list but rather only a list of compatible controllers. Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Igor Pylypiv --- drivers/ata/pata_cs5520.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index 027cf67101ef..3163c8d9cef5 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c @@ -8,9 +8,9 @@ * PIO mode and smarter silicon. * * The practical upshot of this is that we must always tune the - * drive for the right PIO mode. We must also ignore all the blacklists - * and the drive bus mastering DMA information. Also to confuse matters - * further we can do DMA on PIO only drives. + * drive for the right PIO mode and ignore the drive bus mastering DMA + * information. Also to confuse matters further we can do DMA on PIO only + * drives. * * DMA on the 5510 also requires we disable_hlt() during DMA on early * revisions. From 16000756f39d7fb05ae85ff3d3fc18cf1231cd2b Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Fri, 26 Jul 2024 11:32:37 +0900 Subject: [PATCH 12/39] ata: pata_hpt366: Rename hpt_dma_blacklisted() Rename the function hpt_dma_blacklisted() to the more neutral hpt_dma_broken(). Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Igor Pylypiv --- drivers/ata/pata_hpt366.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index bdccd1ba1524..5280e9960025 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -170,8 +170,8 @@ static const char * const bad_ata66_3[] = { NULL }; -static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, - const char * const list[]) +static int hpt_dma_broken(const struct ata_device *dev, char *modestr, + const char * const list[]) { unsigned char model_num[ATA_ID_PROD_LEN + 1]; int i; @@ -197,11 +197,11 @@ static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, static unsigned int hpt366_filter(struct ata_device *adev, unsigned int mask) { if (adev->class == ATA_DEV_ATA) { - if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33)) + if (hpt_dma_broken(adev, "UDMA", bad_ata33)) mask &= ~ATA_MASK_UDMA; - if (hpt_dma_blacklisted(adev, "UDMA3", bad_ata66_3)) + if (hpt_dma_broken(adev, "UDMA3", bad_ata66_3)) mask &= ~(0xF8 << ATA_SHIFT_UDMA); - if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4)) + if (hpt_dma_broken(adev, "UDMA4", bad_ata66_4)) mask &= ~(0xF0 << ATA_SHIFT_UDMA); } else if (adev->class == ATA_DEV_ATAPI) mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); From 73eb824914ff6371b27b37706eab42c30747ca89 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Fri, 26 Jul 2024 11:35:15 +0900 Subject: [PATCH 13/39] ata: pata_hpt37x: Rename hpt_dma_blacklisted() Rename the function hpt_dma_blacklisted() to the more neutral hpt_dma_broken(). Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Igor Pylypiv --- drivers/ata/pata_hpt37x.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index c0329cf01135..4af22b819416 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -218,8 +218,8 @@ static u32 hpt37x_find_mode(struct ata_port *ap, int speed) return 0xffffffffU; /* silence compiler warning */ } -static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, - const char * const list[]) +static int hpt_dma_broken(const struct ata_device *dev, char *modestr, + const char * const list[]) { unsigned char model_num[ATA_ID_PROD_LEN + 1]; int i; @@ -281,9 +281,9 @@ static const char * const bad_ata100_5[] = { static unsigned int hpt370_filter(struct ata_device *adev, unsigned int mask) { if (adev->class == ATA_DEV_ATA) { - if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33)) + if (hpt_dma_broken(adev, "UDMA", bad_ata33)) mask &= ~ATA_MASK_UDMA; - if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5)) + if (hpt_dma_broken(adev, "UDMA100", bad_ata100_5)) mask &= ~(0xE0 << ATA_SHIFT_UDMA); } return mask; @@ -300,7 +300,7 @@ static unsigned int hpt370_filter(struct ata_device *adev, unsigned int mask) static unsigned int hpt370a_filter(struct ata_device *adev, unsigned int mask) { if (adev->class == ATA_DEV_ATA) { - if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5)) + if (hpt_dma_broken(adev, "UDMA100", bad_ata100_5)) mask &= ~(0xE0 << ATA_SHIFT_UDMA); } return mask; From b40824500eaa77668026b6d1ade6924901a680f9 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Tue, 30 Jul 2024 14:38:07 +0900 Subject: [PATCH 14/39] ata: libata: Remove ata_noop_qc_prep() The function ata_noop_qc_prep(), as its name implies, does nothing and simply returns AC_ERR_OK. For drivers that do not need any special preparations of queued commands, we can avoid having to define struct ata_port qc_prep operation by simply testing if that operation is defined or not in ata_qc_issue(). Make this change and remove ata_noop_qc_prep(). Signed-off-by: Damien Le Moal Reviewed-by: John Garry Reviewed-by: Sergey Shtylyov --- drivers/ata/libata-core.c | 18 +++++++----------- drivers/ata/libata-sff.c | 1 - drivers/ata/pata_ep93xx.c | 2 -- drivers/ata/pata_icside.c | 2 -- drivers/ata/pata_mpc52xx.c | 1 - drivers/ata/pata_octeon_cf.c | 1 - drivers/scsi/libsas/sas_ata.c | 1 - include/linux/libata.h | 1 - 8 files changed, 7 insertions(+), 20 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index fc9fcfda42b8..b4fdb78579c8 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4696,12 +4696,6 @@ int ata_std_qc_defer(struct ata_queued_cmd *qc) } EXPORT_SYMBOL_GPL(ata_std_qc_defer); -enum ata_completion_errors ata_noop_qc_prep(struct ata_queued_cmd *qc) -{ - return AC_ERR_OK; -} -EXPORT_SYMBOL_GPL(ata_noop_qc_prep); - /** * ata_sg_init - Associate command with scatter-gather table. * @qc: Command to be associated @@ -5088,10 +5082,13 @@ void ata_qc_issue(struct ata_queued_cmd *qc) return; } - trace_ata_qc_prep(qc); - qc->err_mask |= ap->ops->qc_prep(qc); - if (unlikely(qc->err_mask)) - goto err; + if (ap->ops->qc_prep) { + trace_ata_qc_prep(qc); + qc->err_mask |= ap->ops->qc_prep(qc); + if (unlikely(qc->err_mask)) + goto err; + } + trace_ata_qc_issue(qc); qc->err_mask |= ap->ops->qc_issue(qc); if (unlikely(qc->err_mask)) @@ -6724,7 +6721,6 @@ static void ata_dummy_error_handler(struct ata_port *ap) } struct ata_port_operations ata_dummy_port_ops = { - .qc_prep = ata_noop_qc_prep, .qc_issue = ata_dummy_qc_issue, .error_handler = ata_dummy_error_handler, .sched_eh = ata_std_sched_eh, diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 06868ec5b1fd..67f277e1c3bf 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -26,7 +26,6 @@ static struct workqueue_struct *ata_sff_wq; const struct ata_port_operations ata_sff_port_ops = { .inherits = &ata_base_port_ops, - .qc_prep = ata_noop_qc_prep, .qc_issue = ata_sff_qc_issue, .qc_fill_rtf = ata_sff_qc_fill_rtf, diff --git a/drivers/ata/pata_ep93xx.c b/drivers/ata/pata_ep93xx.c index c84a20892f1b..a34e56a9d535 100644 --- a/drivers/ata/pata_ep93xx.c +++ b/drivers/ata/pata_ep93xx.c @@ -884,8 +884,6 @@ static const struct scsi_host_template ep93xx_pata_sht = { static struct ata_port_operations ep93xx_pata_port_ops = { .inherits = &ata_bmdma_port_ops, - .qc_prep = ata_noop_qc_prep, - .softreset = ep93xx_pata_softreset, .hardreset = ATA_OP_NULL, diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c index 9cfb064782c3..61d8760f09d9 100644 --- a/drivers/ata/pata_icside.c +++ b/drivers/ata/pata_icside.c @@ -328,8 +328,6 @@ static void pata_icside_postreset(struct ata_link *link, unsigned int *classes) static struct ata_port_operations pata_icside_port_ops = { .inherits = &ata_bmdma_port_ops, - /* no need to build any PRD tables for DMA */ - .qc_prep = ata_noop_qc_prep, .sff_data_xfer = ata_sff_data_xfer32, .bmdma_setup = pata_icside_bmdma_setup, .bmdma_start = pata_icside_bmdma_start, diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index 6c317a461a1f..3f9258677915 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c @@ -620,7 +620,6 @@ static struct ata_port_operations mpc52xx_ata_port_ops = { .bmdma_start = mpc52xx_bmdma_start, .bmdma_stop = mpc52xx_bmdma_stop, .bmdma_status = mpc52xx_bmdma_status, - .qc_prep = ata_noop_qc_prep, }; static int mpc52xx_ata_init_one(struct device *dev, diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c index 2884acfc4863..0bb9607e7348 100644 --- a/drivers/ata/pata_octeon_cf.c +++ b/drivers/ata/pata_octeon_cf.c @@ -789,7 +789,6 @@ static unsigned int octeon_cf_qc_issue(struct ata_queued_cmd *qc) static struct ata_port_operations octeon_cf_ops = { .inherits = &ata_sff_port_ops, .check_atapi_dma = octeon_cf_check_atapi_dma, - .qc_prep = ata_noop_qc_prep, .qc_issue = octeon_cf_qc_issue, .sff_dev_select = octeon_cf_dev_select, .sff_irq_on = octeon_cf_ata_port_noaction, diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 88714b7b0dba..7b4e7a61965a 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -564,7 +564,6 @@ static struct ata_port_operations sas_sata_ops = { .error_handler = ata_std_error_handler, .post_internal_cmd = sas_ata_post_internal, .qc_defer = ata_std_qc_defer, - .qc_prep = ata_noop_qc_prep, .qc_issue = sas_ata_qc_issue, .qc_fill_rtf = sas_ata_qc_fill_rtf, .set_dmamode = sas_ata_set_dmamode, diff --git a/include/linux/libata.h b/include/linux/libata.h index d598ef690e50..d5446e18d9df 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1168,7 +1168,6 @@ extern int ata_xfer_mode2shift(u8 xfer_mode); extern const char *ata_mode_string(unsigned int xfer_mask); extern unsigned int ata_id_xfermask(const u16 *id); extern int ata_std_qc_defer(struct ata_queued_cmd *qc); -extern enum ata_completion_errors ata_noop_qc_prep(struct ata_queued_cmd *qc); extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, unsigned int n_elem); extern unsigned int ata_dev_classify(const struct ata_taskfile *tf); From bf1807c6ee1f66608c7835f6f9d9139c9c477942 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 1 Aug 2024 18:04:22 +0900 Subject: [PATCH 15/39] ata: libata: Print device quirks only once In ata_dev_print_quirks(), return early if ata_dev_print_info() returns false or if we already printed quirk information. This is to avoid printing a device quirks multiple times (that is, each time ata_dev_revalidate() is called). To remember if ata_dev_print_quirks() was already executed, define the EH context flag ATA_EHI_DID_PRINT_QUIRKS and set this flag in ata_dev_print_quirks(). Reported-by: Geert Uytterhoeven Fixes: 58157d607aec ("ata: libata: Print quirks applied to devices") Signed-off-by: Damien Le Moal Tested-by: Geert Uytterhoeven --- drivers/ata/libata-core.c | 8 +++++++- include/linux/libata.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b4fdb78579c8..e4023fc288ac 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -160,7 +160,7 @@ MODULE_DESCRIPTION("Library module for ATA devices"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); -static inline bool ata_dev_print_info(struct ata_device *dev) +static inline bool ata_dev_print_info(const struct ata_device *dev) { struct ata_eh_context *ehc = &dev->link->eh_context; @@ -4025,10 +4025,16 @@ static void ata_dev_print_quirks(const struct ata_device *dev, const char *model, const char *rev, unsigned int quirks) { + struct ata_eh_context *ehc = &dev->link->eh_context; int n = 0, i; size_t sz; char *str; + if (!ata_dev_print_info(dev) || ehc->i.flags & ATA_EHI_DID_PRINT_QUIRKS) + return; + + ehc->i.flags |= ATA_EHI_DID_PRINT_QUIRKS; + if (!quirks) return; diff --git a/include/linux/libata.h b/include/linux/libata.h index d5446e18d9df..0279c0a6302f 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -378,6 +378,7 @@ enum { ATA_EHI_PRINTINFO = (1 << 18), /* print configuration info */ ATA_EHI_SETMODE = (1 << 19), /* configure transfer mode */ ATA_EHI_POST_SETMODE = (1 << 20), /* revalidating after setmode */ + ATA_EHI_DID_PRINT_QUIRKS = (1 << 21), /* already printed quirks info */ ATA_EHI_DID_RESET = ATA_EHI_DID_SOFTRESET | ATA_EHI_DID_HARDRESET, From 5ff80684fb23c5483219fb3a25ef6f87df7c7d51 Mon Sep 17 00:00:00 2001 From: Richard Zhu Date: Mon, 12 Aug 2024 10:00:51 +0800 Subject: [PATCH 16/39] dt-bindings: ata: Add i.MX8QM AHCI compatible string Add i.MX8QM AHCI "fsl,imx8qm-ahci" compatible strings. i.MX8QM AHCI SATA doesn't require AHB clock rate to set the vendor specified TIMER1MS register. ahb clock is not required by i.MX8QM AHCI. Update the description of clocks in the dt-binding accordingly. Signed-off-by: Richard Zhu Reviewed-by: Rob Herring (Arm) Reviewed-by: Frank Li Link: https://lore.kernel.org/r/1723428055-27021-2-git-send-email-hongxing.zhu@nxp.com Signed-off-by: Niklas Cassel --- .../devicetree/bindings/ata/imx-sata.yaml | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/Documentation/devicetree/bindings/ata/imx-sata.yaml b/Documentation/devicetree/bindings/ata/imx-sata.yaml index 68ffb97ddc9b..f4eb3550a096 100644 --- a/Documentation/devicetree/bindings/ata/imx-sata.yaml +++ b/Documentation/devicetree/bindings/ata/imx-sata.yaml @@ -19,6 +19,7 @@ properties: - fsl,imx53-ahci - fsl,imx6q-ahci - fsl,imx6qp-ahci + - fsl,imx8qm-ahci reg: maxItems: 1 @@ -27,12 +28,14 @@ properties: maxItems: 1 clocks: + minItems: 2 items: - description: sata clock - description: sata reference clock - description: ahb clock clock-names: + minItems: 2 items: - const: sata - const: sata_ref @@ -58,6 +61,25 @@ properties: $ref: /schemas/types.yaml#/definitions/flag description: if present, disable spread-spectrum clocking on the SATA link. + phys: + items: + - description: phandle to SATA PHY. + Since "REXT" pin is only present for first lane of i.MX8QM PHY, it's + calibration result will be stored, passed through second lane, and + shared with all three lanes PHY. The first two lanes PHY are used as + calibration PHYs, although only the third lane PHY is used by SATA. + - description: phandle to the first lane PHY of i.MX8QM. + - description: phandle to the second lane PHY of i.MX8QM. + + phy-names: + items: + - const: sata-phy + - const: cali-phy0 + - const: cali-phy1 + + power-domains: + maxItems: 1 + required: - compatible - reg @@ -65,6 +87,31 @@ required: - clocks - clock-names +allOf: + - if: + properties: + compatible: + contains: + enum: + - fsl,imx53-ahci + - fsl,imx6q-ahci + - fsl,imx6qp-ahci + then: + properties: + clock-names: + minItems: 3 + + - if: + properties: + compatible: + contains: + enum: + - fsl,imx8qm-ahci + then: + properties: + clock-names: + minItems: 2 + additionalProperties: false examples: From 4147e9d2408aab6df9315900f18f4142ca6e7c3f Mon Sep 17 00:00:00 2001 From: Richard Zhu Date: Mon, 12 Aug 2024 10:00:52 +0800 Subject: [PATCH 17/39] ata: ahci_imx: Clean up code by using i.MX8Q HSIO PHY driver Clean up code by using PHY interface provided by the PHY driver under PHY subsystem(drivers/phy/freescale/phy-fsl-imx8qm-hsio.c). Signed-off-by: Richard Zhu Reviewed-by: Frank Li Link: https://lore.kernel.org/r/1723428055-27021-3-git-send-email-hongxing.zhu@nxp.com Signed-off-by: Niklas Cassel --- drivers/ata/ahci_imx.c | 363 +++++++++-------------------------------- 1 file changed, 79 insertions(+), 284 deletions(-) diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index cb768f66f0a7..75258ed42d2e 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "ahci.h" @@ -44,42 +45,6 @@ enum { /* Clock Reset Register */ IMX_CLOCK_RESET = 0x7f3f, IMX_CLOCK_RESET_RESET = 1 << 0, - /* IMX8QM HSIO AHCI definitions */ - IMX8QM_SATA_PHY_RX_IMPED_RATIO_OFFSET = 0x03, - IMX8QM_SATA_PHY_TX_IMPED_RATIO_OFFSET = 0x09, - IMX8QM_SATA_PHY_IMPED_RATIO_85OHM = 0x6c, - IMX8QM_LPCG_PHYX2_OFFSET = 0x00000, - IMX8QM_CSR_PHYX2_OFFSET = 0x90000, - IMX8QM_CSR_PHYX1_OFFSET = 0xa0000, - IMX8QM_CSR_PHYX_STTS0_OFFSET = 0x4, - IMX8QM_CSR_PCIEA_OFFSET = 0xb0000, - IMX8QM_CSR_PCIEB_OFFSET = 0xc0000, - IMX8QM_CSR_SATA_OFFSET = 0xd0000, - IMX8QM_CSR_PCIE_CTRL2_OFFSET = 0x8, - IMX8QM_CSR_MISC_OFFSET = 0xe0000, - - IMX8QM_LPCG_PHYX2_PCLK0_MASK = (0x3 << 16), - IMX8QM_LPCG_PHYX2_PCLK1_MASK = (0x3 << 20), - IMX8QM_PHY_APB_RSTN_0 = BIT(0), - IMX8QM_PHY_MODE_SATA = BIT(19), - IMX8QM_PHY_MODE_MASK = (0xf << 17), - IMX8QM_PHY_PIPE_RSTN_0 = BIT(24), - IMX8QM_PHY_PIPE_RSTN_OVERRIDE_0 = BIT(25), - IMX8QM_PHY_PIPE_RSTN_1 = BIT(26), - IMX8QM_PHY_PIPE_RSTN_OVERRIDE_1 = BIT(27), - IMX8QM_STTS0_LANE0_TX_PLL_LOCK = BIT(4), - IMX8QM_MISC_IOB_RXENA = BIT(0), - IMX8QM_MISC_IOB_TXENA = BIT(1), - IMX8QM_MISC_PHYX1_EPCS_SEL = BIT(12), - IMX8QM_MISC_CLKREQN_OUT_OVERRIDE_1 = BIT(24), - IMX8QM_MISC_CLKREQN_OUT_OVERRIDE_0 = BIT(25), - IMX8QM_MISC_CLKREQN_IN_OVERRIDE_1 = BIT(28), - IMX8QM_MISC_CLKREQN_IN_OVERRIDE_0 = BIT(29), - IMX8QM_SATA_CTRL_RESET_N = BIT(12), - IMX8QM_SATA_CTRL_EPCS_PHYRESET_N = BIT(7), - IMX8QM_CTRL_BUTTON_RST_N = BIT(21), - IMX8QM_CTRL_POWER_UP_RST_N = BIT(23), - IMX8QM_CTRL_LTSSM_ENABLE = BIT(4), }; enum ahci_imx_type { @@ -95,14 +60,10 @@ struct imx_ahci_priv { struct clk *sata_clk; struct clk *sata_ref_clk; struct clk *ahb_clk; - struct clk *epcs_tx_clk; - struct clk *epcs_rx_clk; - struct clk *phy_apbclk; - struct clk *phy_pclk0; - struct clk *phy_pclk1; - void __iomem *phy_base; - struct gpio_desc *clkreq_gpiod; struct regmap *gpr; + struct phy *sata_phy; + struct phy *cali_phy0; + struct phy *cali_phy1; bool no_device; bool first_time; u32 phy_params; @@ -450,201 +411,73 @@ ATTRIBUTE_GROUPS(fsl_sata_ahci); static int imx8_sata_enable(struct ahci_host_priv *hpriv) { - u32 val, reg; - int i, ret; + u32 val; + int ret; struct imx_ahci_priv *imxpriv = hpriv->plat_data; struct device *dev = &imxpriv->ahci_pdev->dev; - /* configure the hsio for sata */ - ret = clk_prepare_enable(imxpriv->phy_pclk0); - if (ret < 0) { - dev_err(dev, "can't enable phy_pclk0.\n"); + /* + * Since "REXT" pin is only present for first lane of i.MX8QM + * PHY, its calibration results will be stored, passed through + * to the second lane PHY, and shared with all three lane PHYs. + * + * Initialize the first two lane PHYs here, although only the + * third lane PHY is used by SATA. + */ + ret = phy_init(imxpriv->cali_phy0); + if (ret) { + dev_err(dev, "cali PHY init failed\n"); return ret; } - ret = clk_prepare_enable(imxpriv->phy_pclk1); - if (ret < 0) { - dev_err(dev, "can't enable phy_pclk1.\n"); - goto disable_phy_pclk0; + ret = phy_power_on(imxpriv->cali_phy0); + if (ret) { + dev_err(dev, "cali PHY power on failed\n"); + goto err_cali_phy0_exit; } - ret = clk_prepare_enable(imxpriv->epcs_tx_clk); - if (ret < 0) { - dev_err(dev, "can't enable epcs_tx_clk.\n"); - goto disable_phy_pclk1; + ret = phy_init(imxpriv->cali_phy1); + if (ret) { + dev_err(dev, "cali PHY1 init failed\n"); + goto err_cali_phy0_off; } - ret = clk_prepare_enable(imxpriv->epcs_rx_clk); - if (ret < 0) { - dev_err(dev, "can't enable epcs_rx_clk.\n"); - goto disable_epcs_tx_clk; + ret = phy_power_on(imxpriv->cali_phy1); + if (ret) { + dev_err(dev, "cali PHY1 power on failed\n"); + goto err_cali_phy1_exit; } - ret = clk_prepare_enable(imxpriv->phy_apbclk); - if (ret < 0) { - dev_err(dev, "can't enable phy_apbclk.\n"); - goto disable_epcs_rx_clk; + ret = phy_init(imxpriv->sata_phy); + if (ret) { + dev_err(dev, "sata PHY init failed\n"); + goto err_cali_phy1_off; } - /* Configure PHYx2 PIPE_RSTN */ - regmap_read(imxpriv->gpr, IMX8QM_CSR_PCIEA_OFFSET + - IMX8QM_CSR_PCIE_CTRL2_OFFSET, &val); - if ((val & IMX8QM_CTRL_LTSSM_ENABLE) == 0) { - /* The link of the PCIEA of HSIO is down */ - regmap_update_bits(imxpriv->gpr, - IMX8QM_CSR_PHYX2_OFFSET, - IMX8QM_PHY_PIPE_RSTN_0 | - IMX8QM_PHY_PIPE_RSTN_OVERRIDE_0, - IMX8QM_PHY_PIPE_RSTN_0 | - IMX8QM_PHY_PIPE_RSTN_OVERRIDE_0); + ret = phy_set_mode(imxpriv->sata_phy, PHY_MODE_SATA); + if (ret) { + dev_err(dev, "unable to set SATA PHY mode\n"); + goto err_sata_phy_exit; } - regmap_read(imxpriv->gpr, IMX8QM_CSR_PCIEB_OFFSET + - IMX8QM_CSR_PCIE_CTRL2_OFFSET, ®); - if ((reg & IMX8QM_CTRL_LTSSM_ENABLE) == 0) { - /* The link of the PCIEB of HSIO is down */ - regmap_update_bits(imxpriv->gpr, - IMX8QM_CSR_PHYX2_OFFSET, - IMX8QM_PHY_PIPE_RSTN_1 | - IMX8QM_PHY_PIPE_RSTN_OVERRIDE_1, - IMX8QM_PHY_PIPE_RSTN_1 | - IMX8QM_PHY_PIPE_RSTN_OVERRIDE_1); - } - if (((reg | val) & IMX8QM_CTRL_LTSSM_ENABLE) == 0) { - /* The links of both PCIA and PCIEB of HSIO are down */ - regmap_update_bits(imxpriv->gpr, - IMX8QM_LPCG_PHYX2_OFFSET, - IMX8QM_LPCG_PHYX2_PCLK0_MASK | - IMX8QM_LPCG_PHYX2_PCLK1_MASK, - 0); + ret = phy_power_on(imxpriv->sata_phy); + if (ret) { + dev_err(dev, "sata PHY power up failed\n"); + goto err_sata_phy_exit; } - /* set PWR_RST and BT_RST of csr_pciea */ - val = IMX8QM_CSR_PCIEA_OFFSET + IMX8QM_CSR_PCIE_CTRL2_OFFSET; - regmap_update_bits(imxpriv->gpr, - val, - IMX8QM_CTRL_BUTTON_RST_N, - IMX8QM_CTRL_BUTTON_RST_N); - regmap_update_bits(imxpriv->gpr, - val, - IMX8QM_CTRL_POWER_UP_RST_N, - IMX8QM_CTRL_POWER_UP_RST_N); + /* The cali_phy# can be turned off after SATA PHY is initialized. */ + phy_power_off(imxpriv->cali_phy1); + phy_exit(imxpriv->cali_phy1); + phy_power_off(imxpriv->cali_phy0); + phy_exit(imxpriv->cali_phy0); - /* PHYX1_MODE to SATA */ - regmap_update_bits(imxpriv->gpr, - IMX8QM_CSR_PHYX1_OFFSET, - IMX8QM_PHY_MODE_MASK, - IMX8QM_PHY_MODE_SATA); + return 0; - /* - * BIT0 RXENA 1, BIT1 TXENA 0 - * BIT12 PHY_X1_EPCS_SEL 1. - */ - regmap_update_bits(imxpriv->gpr, - IMX8QM_CSR_MISC_OFFSET, - IMX8QM_MISC_IOB_RXENA, - IMX8QM_MISC_IOB_RXENA); - regmap_update_bits(imxpriv->gpr, - IMX8QM_CSR_MISC_OFFSET, - IMX8QM_MISC_IOB_TXENA, - 0); - regmap_update_bits(imxpriv->gpr, - IMX8QM_CSR_MISC_OFFSET, - IMX8QM_MISC_PHYX1_EPCS_SEL, - IMX8QM_MISC_PHYX1_EPCS_SEL); - /* - * It is possible, for PCIe and SATA are sharing - * the same clock source, HPLL or external oscillator. - * When PCIe is in low power modes (L1.X or L2 etc), - * the clock source can be turned off. In this case, - * if this clock source is required to be toggling by - * SATA, then SATA functions will be abnormal. - * Set the override here to avoid it. - */ - regmap_update_bits(imxpriv->gpr, - IMX8QM_CSR_MISC_OFFSET, - IMX8QM_MISC_CLKREQN_OUT_OVERRIDE_1 | - IMX8QM_MISC_CLKREQN_OUT_OVERRIDE_0 | - IMX8QM_MISC_CLKREQN_IN_OVERRIDE_1 | - IMX8QM_MISC_CLKREQN_IN_OVERRIDE_0, - IMX8QM_MISC_CLKREQN_OUT_OVERRIDE_1 | - IMX8QM_MISC_CLKREQN_OUT_OVERRIDE_0 | - IMX8QM_MISC_CLKREQN_IN_OVERRIDE_1 | - IMX8QM_MISC_CLKREQN_IN_OVERRIDE_0); - - /* clear PHY RST, then set it */ - regmap_update_bits(imxpriv->gpr, - IMX8QM_CSR_SATA_OFFSET, - IMX8QM_SATA_CTRL_EPCS_PHYRESET_N, - 0); - - regmap_update_bits(imxpriv->gpr, - IMX8QM_CSR_SATA_OFFSET, - IMX8QM_SATA_CTRL_EPCS_PHYRESET_N, - IMX8QM_SATA_CTRL_EPCS_PHYRESET_N); - - /* CTRL RST: SET -> delay 1 us -> CLEAR -> SET */ - regmap_update_bits(imxpriv->gpr, - IMX8QM_CSR_SATA_OFFSET, - IMX8QM_SATA_CTRL_RESET_N, - IMX8QM_SATA_CTRL_RESET_N); - udelay(1); - regmap_update_bits(imxpriv->gpr, - IMX8QM_CSR_SATA_OFFSET, - IMX8QM_SATA_CTRL_RESET_N, - 0); - regmap_update_bits(imxpriv->gpr, - IMX8QM_CSR_SATA_OFFSET, - IMX8QM_SATA_CTRL_RESET_N, - IMX8QM_SATA_CTRL_RESET_N); - - /* APB reset */ - regmap_update_bits(imxpriv->gpr, - IMX8QM_CSR_PHYX1_OFFSET, - IMX8QM_PHY_APB_RSTN_0, - IMX8QM_PHY_APB_RSTN_0); - - for (i = 0; i < 100; i++) { - reg = IMX8QM_CSR_PHYX1_OFFSET + - IMX8QM_CSR_PHYX_STTS0_OFFSET; - regmap_read(imxpriv->gpr, reg, &val); - val &= IMX8QM_STTS0_LANE0_TX_PLL_LOCK; - if (val == IMX8QM_STTS0_LANE0_TX_PLL_LOCK) - break; - udelay(1); - } - - if (val != IMX8QM_STTS0_LANE0_TX_PLL_LOCK) { - dev_err(dev, "TX PLL of the PHY is not locked\n"); - ret = -ENODEV; - } else { - writeb(imxpriv->imped_ratio, imxpriv->phy_base + - IMX8QM_SATA_PHY_RX_IMPED_RATIO_OFFSET); - writeb(imxpriv->imped_ratio, imxpriv->phy_base + - IMX8QM_SATA_PHY_TX_IMPED_RATIO_OFFSET); - reg = readb(imxpriv->phy_base + - IMX8QM_SATA_PHY_RX_IMPED_RATIO_OFFSET); - if (unlikely(reg != imxpriv->imped_ratio)) - dev_info(dev, "Can't set PHY RX impedance ratio.\n"); - reg = readb(imxpriv->phy_base + - IMX8QM_SATA_PHY_TX_IMPED_RATIO_OFFSET); - if (unlikely(reg != imxpriv->imped_ratio)) - dev_info(dev, "Can't set PHY TX impedance ratio.\n"); - usleep_range(50, 100); - - /* - * To reduce the power consumption, gate off - * the PHY clks - */ - clk_disable_unprepare(imxpriv->phy_apbclk); - clk_disable_unprepare(imxpriv->phy_pclk1); - clk_disable_unprepare(imxpriv->phy_pclk0); - return ret; - } - - clk_disable_unprepare(imxpriv->phy_apbclk); -disable_epcs_rx_clk: - clk_disable_unprepare(imxpriv->epcs_rx_clk); -disable_epcs_tx_clk: - clk_disable_unprepare(imxpriv->epcs_tx_clk); -disable_phy_pclk1: - clk_disable_unprepare(imxpriv->phy_pclk1); -disable_phy_pclk0: - clk_disable_unprepare(imxpriv->phy_pclk0); +err_sata_phy_exit: + phy_exit(imxpriv->sata_phy); +err_cali_phy1_off: + phy_power_off(imxpriv->cali_phy1); +err_cali_phy1_exit: + phy_exit(imxpriv->cali_phy1); +err_cali_phy0_off: + phy_power_off(imxpriv->cali_phy0); +err_cali_phy0_exit: + phy_exit(imxpriv->cali_phy0); return ret; } @@ -698,6 +531,9 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv) } } else if (imxpriv->type == AHCI_IMX8QM) { ret = imx8_sata_enable(hpriv); + if (ret) + goto disable_clk; + } usleep_range(1000, 2000); @@ -736,8 +572,10 @@ static void imx_sata_disable(struct ahci_host_priv *hpriv) break; case AHCI_IMX8QM: - clk_disable_unprepare(imxpriv->epcs_rx_clk); - clk_disable_unprepare(imxpriv->epcs_tx_clk); + if (imxpriv->sata_phy) { + phy_power_off(imxpriv->sata_phy); + phy_exit(imxpriv->sata_phy); + } break; default: @@ -760,6 +598,9 @@ static void ahci_imx_error_handler(struct ata_port *ap) ahci_error_handler(ap); + if (imxpriv->type == AHCI_IMX8QM) + return; + if (!(imxpriv->first_time) || ahci_imx_hotplug) return; @@ -986,65 +827,19 @@ static const struct scsi_host_template ahci_platform_sht = { static int imx8_sata_probe(struct device *dev, struct imx_ahci_priv *imxpriv) { - struct resource *phy_res; - struct platform_device *pdev = imxpriv->ahci_pdev; - struct device_node *np = dev->of_node; - - if (of_property_read_u32(np, "fsl,phy-imp", &imxpriv->imped_ratio)) - imxpriv->imped_ratio = IMX8QM_SATA_PHY_IMPED_RATIO_85OHM; - phy_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); - if (phy_res) { - imxpriv->phy_base = devm_ioremap(dev, phy_res->start, - resource_size(phy_res)); - if (!imxpriv->phy_base) { - dev_err(dev, "error with ioremap\n"); - return -ENOMEM; - } - } else { - dev_err(dev, "missing *phy* reg region.\n"); - return -ENOMEM; - } - imxpriv->gpr = - syscon_regmap_lookup_by_phandle(np, "hsio"); - if (IS_ERR(imxpriv->gpr)) { - dev_err(dev, "unable to find gpr registers\n"); - return PTR_ERR(imxpriv->gpr); - } - - imxpriv->epcs_tx_clk = devm_clk_get(dev, "epcs_tx"); - if (IS_ERR(imxpriv->epcs_tx_clk)) { - dev_err(dev, "can't get epcs_tx_clk clock.\n"); - return PTR_ERR(imxpriv->epcs_tx_clk); - } - imxpriv->epcs_rx_clk = devm_clk_get(dev, "epcs_rx"); - if (IS_ERR(imxpriv->epcs_rx_clk)) { - dev_err(dev, "can't get epcs_rx_clk clock.\n"); - return PTR_ERR(imxpriv->epcs_rx_clk); - } - imxpriv->phy_pclk0 = devm_clk_get(dev, "phy_pclk0"); - if (IS_ERR(imxpriv->phy_pclk0)) { - dev_err(dev, "can't get phy_pclk0 clock.\n"); - return PTR_ERR(imxpriv->phy_pclk0); - } - imxpriv->phy_pclk1 = devm_clk_get(dev, "phy_pclk1"); - if (IS_ERR(imxpriv->phy_pclk1)) { - dev_err(dev, "can't get phy_pclk1 clock.\n"); - return PTR_ERR(imxpriv->phy_pclk1); - } - imxpriv->phy_apbclk = devm_clk_get(dev, "phy_apbclk"); - if (IS_ERR(imxpriv->phy_apbclk)) { - dev_err(dev, "can't get phy_apbclk clock.\n"); - return PTR_ERR(imxpriv->phy_apbclk); - } - - /* Fetch GPIO, then enable the external OSC */ - imxpriv->clkreq_gpiod = devm_gpiod_get_optional(dev, "clkreq", - GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE); - if (IS_ERR(imxpriv->clkreq_gpiod)) - return PTR_ERR(imxpriv->clkreq_gpiod); - if (imxpriv->clkreq_gpiod) - gpiod_set_consumer_name(imxpriv->clkreq_gpiod, "SATA CLKREQ"); + imxpriv->sata_phy = devm_phy_get(dev, "sata-phy"); + if (IS_ERR(imxpriv->sata_phy)) + return dev_err_probe(dev, PTR_ERR(imxpriv->sata_phy), + "Failed to get sata_phy\n"); + imxpriv->cali_phy0 = devm_phy_get(dev, "cali-phy0"); + if (IS_ERR(imxpriv->cali_phy0)) + return dev_err_probe(dev, PTR_ERR(imxpriv->cali_phy0), + "Failed to get cali_phy0\n"); + imxpriv->cali_phy1 = devm_phy_get(dev, "cali-phy1"); + if (IS_ERR(imxpriv->cali_phy1)) + return dev_err_probe(dev, PTR_ERR(imxpriv->cali_phy1), + "Failed to get cali_phy1\n"); return 0; } From 3156e1b2c07181f43cd65baf828c7e6acb022c12 Mon Sep 17 00:00:00 2001 From: Richard Zhu Date: Mon, 12 Aug 2024 10:00:53 +0800 Subject: [PATCH 18/39] ata: ahci_imx: AHB clock rate setting is not required on i.MX8QM AHCI SATA i.MX8QM AHCI SATA doesn't need set AHB clock rate to config the vendor specified TIMER1MS register. Set AHB clock rate only for i.MX53 and i.MX6Q. Signed-off-by: Richard Zhu Reviewed-by: Frank Li Link: https://lore.kernel.org/r/1723428055-27021-4-git-send-email-hongxing.zhu@nxp.com Signed-off-by: Niklas Cassel --- drivers/ata/ahci_imx.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 75258ed42d2e..4dd98368f856 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -872,12 +872,6 @@ static int imx_ahci_probe(struct platform_device *pdev) return PTR_ERR(imxpriv->sata_ref_clk); } - imxpriv->ahb_clk = devm_clk_get(dev, "ahb"); - if (IS_ERR(imxpriv->ahb_clk)) { - dev_err(dev, "can't get ahb clock.\n"); - return PTR_ERR(imxpriv->ahb_clk); - } - if (imxpriv->type == AHCI_IMX6Q || imxpriv->type == AHCI_IMX6QP) { u32 reg_value; @@ -937,11 +931,8 @@ static int imx_ahci_probe(struct platform_device *pdev) goto disable_clk; /* - * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL, - * and IP vendor specific register IMX_TIMER1MS. - * Configure CAP_SSS (support stagered spin up). - * Implement the port0. - * Get the ahb clock rate, and configure the TIMER1MS register. + * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL. + * Set CAP_SSS (support stagered spin up) and Implement the port0. */ reg_val = readl(hpriv->mmio + HOST_CAP); if (!(reg_val & HOST_CAP_SSS)) { @@ -954,8 +945,19 @@ static int imx_ahci_probe(struct platform_device *pdev) writel(reg_val, hpriv->mmio + HOST_PORTS_IMPL); } - reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000; - writel(reg_val, hpriv->mmio + IMX_TIMER1MS); + if (imxpriv->type != AHCI_IMX8QM) { + /* + * Get AHB clock rate and configure the vendor specified + * TIMER1MS register on i.MX53, i.MX6Q and i.MX6QP only. + */ + imxpriv->ahb_clk = devm_clk_get(dev, "ahb"); + if (IS_ERR(imxpriv->ahb_clk)) { + dev_err(dev, "Failed to get ahb clock\n"); + goto disable_sata; + } + reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000; + writel(reg_val, hpriv->mmio + IMX_TIMER1MS); + } ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info, &ahci_platform_sht); From 803f9fb819fd533fb41025898f625ec8835034e1 Mon Sep 17 00:00:00 2001 From: Richard Zhu Date: Mon, 12 Aug 2024 10:00:54 +0800 Subject: [PATCH 19/39] ata: ahci_imx: Enlarge RX water mark for i.MX8QM SATA The RXWM(RxWaterMark) sets the minimum number of free location within the RX FIFO before the watermark is exceeded which in turn will cause the Transport Layer to instruct the Link Layer to transmit HOLDS to the transmitting end. Based on the default RXWM value 0x20, RX FIFO overflow might be observed on i.MX8QM MEK board, when some Gen3 SATA disks are used. The FIFO overflow will result in CRC error, internal error and protocol error, then the SATA link is not stable anymore. To fix this issue, enlarge RX water mark setting from 0x20 to 0x29. Signed-off-by: Richard Zhu Link: https://lore.kernel.org/r/1723428055-27021-5-git-send-email-hongxing.zhu@nxp.com Signed-off-by: Niklas Cassel --- drivers/ata/ahci_imx.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 4dd98368f856..627b36cc4b5c 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -45,6 +45,10 @@ enum { /* Clock Reset Register */ IMX_CLOCK_RESET = 0x7f3f, IMX_CLOCK_RESET_RESET = 1 << 0, + /* IMX8QM SATA specific control registers */ + IMX8QM_SATA_AHCI_PTC = 0xc8, + IMX8QM_SATA_AHCI_PTC_RXWM_MASK = GENMASK(6, 0), + IMX8QM_SATA_AHCI_PTC_RXWM = 0x29, }; enum ahci_imx_type { @@ -466,6 +470,12 @@ static int imx8_sata_enable(struct ahci_host_priv *hpriv) phy_power_off(imxpriv->cali_phy0); phy_exit(imxpriv->cali_phy0); + /* RxWaterMark setting */ + val = readl(hpriv->mmio + IMX8QM_SATA_AHCI_PTC); + val &= ~IMX8QM_SATA_AHCI_PTC_RXWM_MASK; + val |= IMX8QM_SATA_AHCI_PTC_RXWM; + writel(val, hpriv->mmio + IMX8QM_SATA_AHCI_PTC); + return 0; err_sata_phy_exit: From 6773e058ae5a9eaebe0a62a2c1b8fceb190ece82 Mon Sep 17 00:00:00 2001 From: Richard Zhu Date: Mon, 12 Aug 2024 10:00:55 +0800 Subject: [PATCH 20/39] ata: ahci_imx: Correct the email address Correct the email address of driver author. Signed-off-by: Richard Zhu Reviewed-by: Frank Li Link: https://lore.kernel.org/r/1723428055-27021-6-git-send-email-hongxing.zhu@nxp.com Signed-off-by: Niklas Cassel --- drivers/ata/ahci_imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 627b36cc4b5c..65f98e8fdf07 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -1036,6 +1036,6 @@ static struct platform_driver imx_ahci_driver = { module_platform_driver(imx_ahci_driver); MODULE_DESCRIPTION("Freescale i.MX AHCI SATA platform driver"); -MODULE_AUTHOR("Richard Zhu "); +MODULE_AUTHOR("Richard Zhu "); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DRV_NAME); From aa3ca1faf3222af7aaa194a910995820135fc54e Mon Sep 17 00:00:00 2001 From: Zhang Zekun Date: Sat, 10 Aug 2024 10:34:26 +0800 Subject: [PATCH 21/39] ata: libahci_platform: Simplify code with for_each_child_of_node_scoped() for_each_child_of_node_scoped() can put the device_node automatically. So let's use it to make the code simpler by avoiding the need to explicitly call of_node_put(). Signed-off-by: Zhang Zekun Link: https://lore.kernel.org/r/20240810023426.110624-1-zhangzekun11@huawei.com Signed-off-by: Niklas Cassel --- drivers/ata/libahci_platform.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c index 581704e61f28..7a8064520a35 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -410,7 +410,6 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port, static int ahci_platform_get_firmware(struct ahci_host_priv *hpriv, struct device *dev) { - struct device_node *child; u32 port; if (!of_property_read_u32(dev->of_node, "hba-cap", &hpriv->saved_cap)) @@ -419,14 +418,12 @@ static int ahci_platform_get_firmware(struct ahci_host_priv *hpriv, of_property_read_u32(dev->of_node, "ports-implemented", &hpriv->saved_port_map); - for_each_child_of_node(dev->of_node, child) { + for_each_child_of_node_scoped(dev->of_node, child) { if (!of_device_is_available(child)) continue; - if (of_property_read_u32(child, "reg", &port)) { - of_node_put(child); + if (of_property_read_u32(child, "reg", &port)) return -EINVAL; - } if (!of_property_read_u32(child, "hba-port-cap", &hpriv->saved_port_cap[port])) hpriv->saved_port_cap[port] &= PORT_CMD_CAP; @@ -460,7 +457,6 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev, int child_nodes, rc = -ENOMEM, enabled_ports = 0; struct device *dev = &pdev->dev; struct ahci_host_priv *hpriv; - struct device_node *child; u32 mask_port_map = 0; if (!devres_open_group(dev, NULL, GFP_KERNEL)) @@ -579,7 +575,7 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev, } if (child_nodes) { - for_each_child_of_node(dev->of_node, child) { + for_each_child_of_node_scoped(dev->of_node, child) { u32 port; struct platform_device *port_dev __maybe_unused; @@ -588,7 +584,6 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev, if (of_property_read_u32(child, "reg", &port)) { rc = -EINVAL; - of_node_put(child); goto err_out; } @@ -606,18 +601,14 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev, if (port_dev) { rc = ahci_platform_get_regulator(hpriv, port, &port_dev->dev); - if (rc == -EPROBE_DEFER) { - of_node_put(child); + if (rc == -EPROBE_DEFER) goto err_out; - } } #endif rc = ahci_platform_get_phy(hpriv, port, dev, child); - if (rc) { - of_node_put(child); + if (rc) goto err_out; - } enabled_ports++; } From 66afec7c6992a04f8ab65b54421bdb5f8ac806e6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 15 Aug 2024 14:25:08 +0300 Subject: [PATCH 22/39] ata: ahci_imx: Fix error code in probe() Return a negative error code if devm_clk_get() fails. Don't return success. Fixes: 3156e1b2c071 ("ata: ahci_imx: AHB clock rate setting is not required on i.MX8QM AHCI SATA") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/cbcbdfc2-ddc7-4684-8ad4-018227823546@stanley.mountain Signed-off-by: Niklas Cassel --- drivers/ata/ahci_imx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 65f98e8fdf07..6f955e9105e8 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -963,6 +963,7 @@ static int imx_ahci_probe(struct platform_device *pdev) imxpriv->ahb_clk = devm_clk_get(dev, "ahb"); if (IS_ERR(imxpriv->ahb_clk)) { dev_err(dev, "Failed to get ahb clock\n"); + ret = PTR_ERR(imxpriv->ahb_clk); goto disable_sata; } reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000; From 13acf2b74803a9a9ab3475c306d5814cf3cefbd8 Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Mon, 26 Aug 2024 14:32:42 +0800 Subject: [PATCH 23/39] ata: libata: Remove obsolete function declarations The function ata_schedule_scsi_eh() was removed with commit f8bbfc247efb ("[PATCH] SCSI: make scsi_implement_eh() generic API for SCSI transports"), and the function ata_sff_irq_clear() was removed with commit 37f65b8bc262("libata-sff: ata_sff_irq_clear() is BMDMA specific"). Remove the now useless declarations of these functions in drivers/ata/libata.h and include/linux/libata.h. Signed-off-by: Gaosheng Cui Signed-off-by: Damien Le Moal --- drivers/ata/libata.h | 1 - include/linux/libata.h | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 6abf265f626e..22e667394368 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -124,7 +124,6 @@ extern void ata_scsi_set_sense_information(struct ata_device *dev, 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); extern void ata_scsi_dev_rescan(struct work_struct *work); extern int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, unsigned int id, u64 lun); diff --git a/include/linux/libata.h b/include/linux/libata.h index 0279c0a6302f..6552e90753ae 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -2006,7 +2006,6 @@ extern unsigned int ata_sff_data_xfer(struct ata_queued_cmd *qc, extern unsigned int ata_sff_data_xfer32(struct ata_queued_cmd *qc, unsigned char *buf, unsigned int buflen, int rw); extern void ata_sff_irq_on(struct ata_port *ap); -extern void ata_sff_irq_clear(struct ata_port *ap); extern int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, u8 status, int in_wq); extern void ata_sff_queue_work(struct work_struct *work); From 43d37fffda9b7ad10ae90122ea532a829bdd2f92 Mon Sep 17 00:00:00 2001 From: Zhang Zekun Date: Tue, 27 Aug 2024 18:58:23 +0800 Subject: [PATCH 24/39] ata: ahci_brcm: Use devm_platform_ioremap_resource_byname() helper function platform_get_resource_byname() and devm_ioremap_resource() can be replaced by devm_platform_ioremap_resource_byname(), which can simplify the code logic a bit, No functional change here. Signed-off-by: Zhang Zekun Signed-off-by: Damien Le Moal --- drivers/ata/ahci_brcm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c index 70c3a33eee6f..2f16524c2526 100644 --- a/drivers/ata/ahci_brcm.c +++ b/drivers/ata/ahci_brcm.c @@ -437,7 +437,6 @@ static int brcm_ahci_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct brcm_ahci_priv *priv; struct ahci_host_priv *hpriv; - struct resource *res; int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -451,8 +450,7 @@ static int brcm_ahci_probe(struct platform_device *pdev) priv->version = (unsigned long)of_id->data; priv->dev = dev; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "top-ctrl"); - priv->top_ctrl = devm_ioremap_resource(dev, res); + priv->top_ctrl = devm_platform_ioremap_resource_byname(pdev, "top-ctrl"); if (IS_ERR(priv->top_ctrl)) return PTR_ERR(priv->top_ctrl); From 9526dec226f0779d72f798e7a18375bf8d414775 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Wed, 28 Aug 2024 09:27:04 +0200 Subject: [PATCH 25/39] ata: libata: Add helper ata_eh_decide_disposition() Every time I see libata code calling scsi_check_sense(), I get confused why the code path that is working fine for SCSI code, is not sufficient for libata code. The reason is that SCSI usually gets the sense data as part of the completion, and will thus automatically call scsi_check_sense(), which will set the SCSI ML byte (if any). However, for libata queued commands, we always need to fetch the sense data via SCSI EH, and thus do not get the luxury of having scsi_check_sense() called automatically. Add a new helper, ata_eh_decide_disposition(), that has a ata_eh_ prefix to more clearly highlight that this is only needed for code called by EH, while also having a similar name to scsi_decide_disposition(), such that it is easier to compare the libata code with the equivalent SCSI code. Also add a big kdoc comment explaining why this helper is called/needed in the first place. Signed-off-by: Niklas Cassel Signed-off-by: Damien Le Moal --- drivers/ata/libata-eh.c | 47 ++++++++++++++++++++++++++++++++++----- drivers/ata/libata-sata.c | 8 +++---- drivers/ata/libata.h | 1 + 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 214b935c2ced..7de97ee8e78b 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1401,6 +1401,43 @@ unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key) return err_mask; } +/** + * ata_eh_decide_disposition - Disposition a qc based on sense data + * @qc: qc to examine + * + * For a regular SCSI command, the SCSI completion callback (scsi_done()) + * will call scsi_complete(), which will call scsi_decide_disposition(), + * which will call scsi_check_sense(). scsi_complete() finally calls + * scsi_finish_command(). This is fine for SCSI, since any eventual sense + * data is usually returned in the completion itself (without invoking SCSI + * EH). However, for a QC, we always need to fetch the sense data + * explicitly using SCSI EH. + * + * A command that is completed via SCSI EH will instead be completed using + * scsi_eh_flush_done_q(), which will call scsi_finish_command() directly + * (without ever calling scsi_check_sense()). + * + * For a command that went through SCSI EH, it is the responsibility of the + * SCSI EH strategy handler to call scsi_decide_disposition(), see e.g. how + * scsi_eh_get_sense() calls scsi_decide_disposition() for SCSI LLDDs that + * do not get the sense data as part of the completion. + * + * Thus, for QC commands that went via SCSI EH, we need to call + * scsi_check_sense() ourselves, similar to how scsi_eh_get_sense() calls + * scsi_decide_disposition(), which calls scsi_check_sense(), in order to + * set the correct SCSI ML byte (if any). + * + * LOCKING: + * EH context. + * + * RETURNS: + * SUCCESS or FAILED or NEEDS_RETRY or ADD_TO_MLQUEUE + */ +enum scsi_disposition ata_eh_decide_disposition(struct ata_queued_cmd *qc) +{ + return scsi_check_sense(qc->scsicmd); +} + /** * ata_eh_request_sense - perform REQUEST_SENSE_DATA_EXT * @qc: qc to perform REQUEST_SENSE_SENSE_DATA_EXT to @@ -1627,7 +1664,8 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc) } if (qc->flags & ATA_QCFLAG_SENSE_VALID) { - enum scsi_disposition ret = scsi_check_sense(qc->scsicmd); + enum scsi_disposition ret = ata_eh_decide_disposition(qc); + /* * SUCCESS here means that the sense code could be * evaluated and should be passed to the upper layers @@ -1942,11 +1980,10 @@ static int ata_eh_read_sense_success_non_ncq(struct ata_link *link) return -EIO; /* - * If we have sense data, call scsi_check_sense() in order to set the - * correct SCSI ML byte (if any). No point in checking the return value, - * since the command has already completed successfully. + * No point in checking the return value, since the command has already + * completed successfully. */ - scsi_check_sense(qc->scsicmd); + ata_eh_decide_disposition(qc); return 0; } diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c index ecd37649d4d4..ea6126c139af 100644 --- a/drivers/ata/libata-sata.c +++ b/drivers/ata/libata-sata.c @@ -1455,12 +1455,10 @@ int ata_eh_read_sense_success_ncq_log(struct ata_link *link) qc->flags |= ATA_QCFLAG_SENSE_VALID; /* - * If we have sense data, call scsi_check_sense() in order to - * set the correct SCSI ML byte (if any). No point in checking - * the return value, since the command has already completed - * successfully. + * No point in checking the return value, since the command has + * already completed successfully. */ - scsi_check_sense(qc->scsicmd); + ata_eh_decide_disposition(qc); } return ret; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 22e667394368..ab4bd44ba17c 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -161,6 +161,7 @@ extern void ata_eh_finish(struct ata_port *ap); extern int ata_ering_map(struct ata_ering *ering, int (*map_fn)(struct ata_ering_entry *, void *), void *arg); +enum scsi_disposition ata_eh_decide_disposition(struct ata_queued_cmd *qc); extern unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key); extern unsigned int atapi_eh_request_sense(struct ata_device *dev, u8 *sense_buf, u8 dfl_sense_key); From 4b4e1a961f6e72c6889f37694cafbd30ea10ec36 Mon Sep 17 00:00:00 2001 From: Liao Chen Date: Sat, 31 Aug 2024 07:21:56 +0000 Subject: [PATCH 26/39] ata: pata_ftide010: Enable module autoloading Add MODULE_DEVICE_TABLE(), so modules can be properly autoloaded based on the alias from of_device_id table. Signed-off-by: Liao Chen Reviewed-by: Sergey Shtylyov Reviewed-by: Linus Walleij Signed-off-by: Damien Le Moal --- drivers/ata/pata_ftide010.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/pata_ftide010.c b/drivers/ata/pata_ftide010.c index 4d6ef90ccc77..73a9a5109238 100644 --- a/drivers/ata/pata_ftide010.c +++ b/drivers/ata/pata_ftide010.c @@ -549,6 +549,7 @@ static const struct of_device_id pata_ftide010_of_match[] = { { .compatible = "faraday,ftide010", }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, pata_ftide010_of_match); static struct platform_driver pata_ftide010_driver = { .driver = { From 619c98622b74f97e78ec71cc99ee0d365bcc690f Mon Sep 17 00:00:00 2001 From: Liao Chen Date: Sat, 31 Aug 2024 07:21:57 +0000 Subject: [PATCH 27/39] ata: pata_ixp4xx: Enable module autoloading Add MODULE_DEVICE_TABLE(), so modules can be properly autoloaded based on the alias from of_device_id table. Signed-off-by: Liao Chen Reviewed-by: Sergey Shtylyov Reviewed-by: Linus Walleij Signed-off-by: Damien Le Moal --- drivers/ata/pata_ixp4xx_cf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index 246bb4f8f1f7..8a9ee828478f 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -290,6 +290,7 @@ static const struct of_device_id ixp4xx_pata_of_match[] = { { .compatible = "intel,ixp4xx-compact-flash", }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, ixp4xx_pata_of_match); static struct platform_driver ixp4xx_pata_platform_driver = { .driver = { From 0f3e1eaaf7f97839ac65f525efec392161d73219 Mon Sep 17 00:00:00 2001 From: Liao Chen Date: Sat, 31 Aug 2024 07:21:58 +0000 Subject: [PATCH 28/39] ata: sata_gemini: Enable module autoloading Add MODULE_DEVICE_TABLE(), so modules can be properly autoloaded based on the alias from of_device_id table. Signed-off-by: Liao Chen Reviewed-by: Linus Walleij Signed-off-by: Damien Le Moal --- drivers/ata/sata_gemini.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/sata_gemini.c b/drivers/ata/sata_gemini.c index 4c270999ba3c..f574e3c3f5b4 100644 --- a/drivers/ata/sata_gemini.c +++ b/drivers/ata/sata_gemini.c @@ -417,6 +417,7 @@ static const struct of_device_id gemini_sata_of_match[] = { { .compatible = "cortina,gemini-sata-bridge", }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, gemini_sata_of_match); static struct platform_driver gemini_sata_driver = { .driver = { From c494708d1f680027c7cbbaa670198179774f7d4d Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Mon, 19 Aug 2024 11:32:15 +0900 Subject: [PATCH 29/39] ata: libata: Cleanup libata-transport Move the ATA link transport device related functions after the ATA transport device related functions to avoid the need for forward declaring ata_tdev_add() and ata_tdev_delete(). And while at it, do the following: 1) Change ata_is_ata_dev() and ata_is_link() to return a boolean 2) Fix a pointer declaration style in ata_is_ata_dev() 3) Improve the kdoc comments for ata_tdev_free(), ata_tdev_delete(), ata_tdev_add(), ata_tlink_delete() and ata_tlink_add() No functional changes are introduced by this cleanup. Signed-off-by: Damien Le Moal Reviewed-by: Hannes Reinecke Reviewed-by: Niklas Cassel --- drivers/ata/libata-transport.c | 299 ++++++++++++++++----------------- 1 file changed, 147 insertions(+), 152 deletions(-) diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index 48800cd0e75d..d9a1888eac34 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -80,12 +80,6 @@ struct ata_internal { #define transport_class_to_port(dev) \ tdev_to_port((dev)->parent) - -/* Device objects are always created whit link objects */ -static int ata_tdev_add(struct ata_device *dev); -static void ata_tdev_delete(struct ata_device *dev); - - /* * Hack to allow attributes of the same name in different objects. */ @@ -364,135 +358,6 @@ unsigned int ata_port_classify(struct ata_port *ap, } EXPORT_SYMBOL_GPL(ata_port_classify); -/* - * ATA link attributes - */ -static int noop(int x) { return x; } - -#define ata_link_show_linkspeed(field, format) \ -static ssize_t \ -show_ata_link_##field(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct ata_link *link = transport_class_to_link(dev); \ - \ - return sprintf(buf, "%s\n", sata_spd_string(format(link->field))); \ -} - -#define ata_link_linkspeed_attr(field, format) \ - ata_link_show_linkspeed(field, format) \ -static DEVICE_ATTR(field, S_IRUGO, show_ata_link_##field, NULL) - -ata_link_linkspeed_attr(hw_sata_spd_limit, fls); -ata_link_linkspeed_attr(sata_spd_limit, fls); -ata_link_linkspeed_attr(sata_spd, noop); - - -static DECLARE_TRANSPORT_CLASS(ata_link_class, - "ata_link", NULL, NULL, NULL); - -static void ata_tlink_release(struct device *dev) -{ -} - -/** - * ata_is_link -- check if a struct device represents a ATA link - * @dev: device to check - * - * Returns: - * %1 if the device represents a ATA link, %0 else - */ -static int ata_is_link(const struct device *dev) -{ - return dev->release == ata_tlink_release; -} - -static int ata_tlink_match(struct attribute_container *cont, - struct device *dev) -{ - struct ata_internal* i = to_ata_internal(ata_scsi_transport_template); - if (!ata_is_link(dev)) - return 0; - return &i->link_attr_cont.ac == cont; -} - -/** - * ata_tlink_delete -- remove ATA LINK - * @link: ATA LINK to remove - * - * Removes the specified ATA LINK. remove associated ATA device(s) as well. - */ -void ata_tlink_delete(struct ata_link *link) -{ - struct device *dev = &link->tdev; - struct ata_device *ata_dev; - - ata_for_each_dev(ata_dev, link, ALL) { - ata_tdev_delete(ata_dev); - } - - transport_remove_device(dev); - device_del(dev); - transport_destroy_device(dev); - put_device(dev); -} - -/** - * ata_tlink_add -- initialize a transport ATA link structure - * @link: allocated ata_link structure. - * - * Initialize an ATA LINK structure for sysfs. It will be added in the - * device tree below the ATA PORT it belongs to. - * - * Returns %0 on success - */ -int ata_tlink_add(struct ata_link *link) -{ - struct device *dev = &link->tdev; - struct ata_port *ap = link->ap; - struct ata_device *ata_dev; - int error; - - device_initialize(dev); - dev->parent = &ap->tdev; - dev->release = ata_tlink_release; - if (ata_is_host_link(link)) - dev_set_name(dev, "link%d", ap->print_id); - else - dev_set_name(dev, "link%d.%d", ap->print_id, link->pmp); - - transport_setup_device(dev); - - error = device_add(dev); - if (error) { - goto tlink_err; - } - - error = transport_add_device(dev); - if (error) - goto tlink_transport_err; - transport_configure_device(dev); - - ata_for_each_dev(ata_dev, link, ALL) { - error = ata_tdev_add(ata_dev); - if (error) { - goto tlink_dev_err; - } - } - return 0; - tlink_dev_err: - while (--ata_dev >= link->device) { - ata_tdev_delete(ata_dev); - } - transport_remove_device(dev); - tlink_transport_err: - device_del(dev); - tlink_err: - transport_destroy_device(dev); - put_device(dev); - return error; -} - /* * ATA device attributes */ @@ -643,9 +508,9 @@ static void ata_tdev_release(struct device *dev) * @dev: device to check * * Returns: - * %1 if the device represents a ATA device, %0 else + * true if the device represents a ATA device, false otherwise */ -static int ata_is_ata_dev(const struct device *dev) +static bool ata_is_ata_dev(const struct device *dev) { return dev->release == ata_tdev_release; } @@ -653,21 +518,22 @@ static int ata_is_ata_dev(const struct device *dev) static int ata_tdev_match(struct attribute_container *cont, struct device *dev) { - struct ata_internal* i = to_ata_internal(ata_scsi_transport_template); + struct ata_internal *i = to_ata_internal(ata_scsi_transport_template); + if (!ata_is_ata_dev(dev)) return 0; return &i->dev_attr_cont.ac == cont; } /** - * ata_tdev_free -- free a ATA LINK - * @dev: ATA PHY to free + * ata_tdev_free -- free an ATA transport device + * @dev: struct ata_device owning the transport device to free * - * Frees the specified ATA PHY. + * Free the ATA transport device for the specified ATA device. * * Note: - * This function must only be called on a PHY that has not - * successfully been added using ata_tdev_add(). + * This function must only be called for a ATA transport device that has not + * yet successfully been added using ata_tdev_add(). */ static void ata_tdev_free(struct ata_device *dev) { @@ -676,10 +542,10 @@ static void ata_tdev_free(struct ata_device *dev) } /** - * ata_tdev_delete -- remove ATA device - * @ata_dev: ATA device to remove + * ata_tdev_delete -- remove an ATA transport device + * @ata_dev: struct ata_device owning the transport device to delete * - * Removes the specified ATA device. + * Removes the ATA transport device for the specified ATA device. */ static void ata_tdev_delete(struct ata_device *ata_dev) { @@ -690,15 +556,14 @@ static void ata_tdev_delete(struct ata_device *ata_dev) ata_tdev_free(ata_dev); } - /** - * ata_tdev_add -- initialize a transport ATA device structure. - * @ata_dev: ata_dev structure. + * ata_tdev_add -- initialize an ATA transport device + * @ata_dev: struct ata_device owning the transport device to add * - * Initialize an ATA device structure for sysfs. It will be added in the - * device tree below the ATA LINK device it belongs to. + * Initialize an ATA transport device for sysfs. It will be added in the + * device tree below the ATA link device it belongs to. * - * Returns %0 on success + * Returns %0 on success and a negative error code on error. */ static int ata_tdev_add(struct ata_device *ata_dev) { @@ -734,6 +599,136 @@ static int ata_tdev_add(struct ata_device *ata_dev) return 0; } +/* + * ATA link attributes + */ +static int noop(int x) +{ + return x; +} + +#define ata_link_show_linkspeed(field, format) \ +static ssize_t \ +show_ata_link_##field(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct ata_link *link = transport_class_to_link(dev); \ + \ + return sprintf(buf, "%s\n", \ + sata_spd_string(format(link->field))); \ +} + +#define ata_link_linkspeed_attr(field, format) \ + ata_link_show_linkspeed(field, format) \ +static DEVICE_ATTR(field, 0444, show_ata_link_##field, NULL) + +ata_link_linkspeed_attr(hw_sata_spd_limit, fls); +ata_link_linkspeed_attr(sata_spd_limit, fls); +ata_link_linkspeed_attr(sata_spd, noop); + +static DECLARE_TRANSPORT_CLASS(ata_link_class, + "ata_link", NULL, NULL, NULL); + +static void ata_tlink_release(struct device *dev) +{ +} + +/** + * ata_is_link -- check if a struct device represents a ATA link + * @dev: device to check + * + * Returns: + * true if the device represents a ATA link, false otherwise + */ +static bool ata_is_link(const struct device *dev) +{ + return dev->release == ata_tlink_release; +} + +static int ata_tlink_match(struct attribute_container *cont, + struct device *dev) +{ + struct ata_internal *i = to_ata_internal(ata_scsi_transport_template); + + if (!ata_is_link(dev)) + return 0; + return &i->link_attr_cont.ac == cont; +} + +/** + * ata_tlink_delete -- remove an ATA link transport device + * @link: struct ata_link owning the link transport device to remove + * + * Removes the link transport device of the specified ATA link. This also + * removes the ATA device(s) associated with the link as well. + */ +void ata_tlink_delete(struct ata_link *link) +{ + struct device *dev = &link->tdev; + struct ata_device *ata_dev; + + ata_for_each_dev(ata_dev, link, ALL) { + ata_tdev_delete(ata_dev); + } + + transport_remove_device(dev); + device_del(dev); + transport_destroy_device(dev); + put_device(dev); +} + +/** + * ata_tlink_add -- initialize an ATA link transport device + * @ata_link: struct ata_link owning the link transport device to initialize + * + * Initialize an ATA link transport device for sysfs. It will be added in the + * device tree below the ATA port it belongs to. + * + * Returns %0 on success and a negative error code on error. + */ +int ata_tlink_add(struct ata_link *link) +{ + struct device *dev = &link->tdev; + struct ata_port *ap = link->ap; + struct ata_device *ata_dev; + int error; + + device_initialize(dev); + dev->parent = &ap->tdev; + dev->release = ata_tlink_release; + if (ata_is_host_link(link)) + dev_set_name(dev, "link%d", ap->print_id); + else + dev_set_name(dev, "link%d.%d", ap->print_id, link->pmp); + + transport_setup_device(dev); + + error = device_add(dev); + if (error) + goto tlink_err; + + error = transport_add_device(dev); + if (error) + goto tlink_transport_err; + transport_configure_device(dev); + + ata_for_each_dev(ata_dev, link, ALL) { + error = ata_tdev_add(ata_dev); + if (error) + goto tlink_dev_err; + } + return 0; + tlink_dev_err: + while (--ata_dev >= link->device) + ata_tdev_delete(ata_dev); + transport_remove_device(dev); + tlink_transport_err: + device_del(dev); + tlink_err: + transport_destroy_device(dev); + put_device(dev); + return error; +} /* * Setup / Teardown code From a16951510fae8fa9b934673404c4fc990d124ccd Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 5 Sep 2024 11:00:59 +0900 Subject: [PATCH 30/39] ata: libata-scsi: Improve ata_scsi_handle_link_detach() A struct ata_device flags should always be set and cleared with the device port locked. Testing for a flag should thus also be done while holding the device port lock. In accordance to this principle, modify ata_scsi_handle_link_detach() to test and clear the ATA_DFLAG_DETACHED flag while holding the device port lock. Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel --- drivers/ata/libata-scsi.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 3a442f564b0d..6bd7ab27fcbb 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -4605,10 +4605,12 @@ static void ata_scsi_handle_link_detach(struct ata_link *link) ata_for_each_dev(dev, link, ALL) { unsigned long flags; - if (!(dev->flags & ATA_DFLAG_DETACHED)) - continue; - spin_lock_irqsave(ap->lock, flags); + if (!(dev->flags & ATA_DFLAG_DETACHED)) { + spin_unlock_irqrestore(ap->lock, flags); + continue; + } + dev->flags &= ~ATA_DFLAG_DETACHED; spin_unlock_irqrestore(ap->lock, flags); From 5bb52d926598a018b1510fd6684dcbaed31d57f2 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Tue, 25 Jun 2024 21:07:32 +0900 Subject: [PATCH 31/39] ata: libata: Improve __ata_qc_complete() The function __ata_qc_complete() is always called with a qc that already has been dereferenced and so is guaranteed to be non-NULL (as otherwise the kernel would have crashed). So remove the warning for a NULL qc as it is useless. Furthermore, the qc passed to __ata_qc_complete() must always be marked as active with the ATA_QCFLAG_ACTIVE flag. If that is not the case, in addition to the existing warning, return early so that we do not attempt to complete an invalid qc. Finally, fix the comment related to clearing the qc active flag as that operation applies to all devices, not just ATAPI ones. Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Hannes Reinecke --- drivers/ata/libata-core.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index e4023fc288ac..5acc37397f4b 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4829,8 +4829,9 @@ void __ata_qc_complete(struct ata_queued_cmd *qc) struct ata_port *ap; struct ata_link *link; - WARN_ON_ONCE(qc == NULL); /* ata_qc_from_tag _might_ return NULL */ - WARN_ON_ONCE(!(qc->flags & ATA_QCFLAG_ACTIVE)); + if (WARN_ON_ONCE(!(qc->flags & ATA_QCFLAG_ACTIVE))) + return; + ap = qc->ap; link = qc->dev->link; @@ -4852,9 +4853,10 @@ void __ata_qc_complete(struct ata_queued_cmd *qc) ap->excl_link == link)) ap->excl_link = NULL; - /* atapi: mark qc as inactive to prevent the interrupt handler - * from completing the command twice later, before the error handler - * is called. (when rc != 0 and atapi request sense is needed) + /* + * Mark qc as inactive to prevent the port interrupt handler from + * completing the command twice later, before the error handler is + * called. */ qc->flags &= ~ATA_QCFLAG_ACTIVE; ap->qc_active &= ~(1ULL << qc->tag); From b642212d8858059f652b2a81b0cb73541416d2e3 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Wed, 17 Jul 2024 17:39:29 +0900 Subject: [PATCH 32/39] ata: libata: Move sata_down_spd_limit() to libata-sata.c Move the definition of the function sata_down_spd_limit() to libata-sata.c where it belongs, together with sata_set_spd(). The helper function ata_sstatus_online() is also changed to be an inline function defined in drivers/ata/libata.h. Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Hannes Reinecke --- drivers/ata/libata-core.c | 85 --------------------------------------- drivers/ata/libata-sata.c | 80 ++++++++++++++++++++++++++++++++++++ drivers/ata/libata.h | 17 +++++++- 3 files changed, 96 insertions(+), 86 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 5acc37397f4b..b957eb900a00 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -167,11 +167,6 @@ static inline bool ata_dev_print_info(const struct ata_device *dev) return ehc->i.flags & ATA_EHI_PRINTINFO; } -static bool ata_sstatus_online(u32 sstatus) -{ - return (sstatus & 0xf) == 0x3; -} - /** * ata_link_next - link iteration helper * @link: the previous link, NULL to start @@ -3200,86 +3195,6 @@ struct ata_device *ata_dev_pair(struct ata_device *adev) } EXPORT_SYMBOL_GPL(ata_dev_pair); -/** - * sata_down_spd_limit - adjust SATA spd limit downward - * @link: Link to adjust SATA spd limit for - * @spd_limit: Additional limit - * - * Adjust SATA spd limit of @link downward. Note that this - * function only adjusts the limit. The change must be applied - * using sata_set_spd(). - * - * If @spd_limit is non-zero, the speed is limited to equal to or - * lower than @spd_limit if such speed is supported. If - * @spd_limit is slower than any supported speed, only the lowest - * supported speed is allowed. - * - * LOCKING: - * Inherited from caller. - * - * RETURNS: - * 0 on success, negative errno on failure - */ -int sata_down_spd_limit(struct ata_link *link, u32 spd_limit) -{ - u32 sstatus, spd, mask; - int rc, bit; - - if (!sata_scr_valid(link)) - return -EOPNOTSUPP; - - /* If SCR can be read, use it to determine the current SPD. - * If not, use cached value in link->sata_spd. - */ - rc = sata_scr_read(link, SCR_STATUS, &sstatus); - if (rc == 0 && ata_sstatus_online(sstatus)) - spd = (sstatus >> 4) & 0xf; - else - spd = link->sata_spd; - - mask = link->sata_spd_limit; - if (mask <= 1) - return -EINVAL; - - /* unconditionally mask off the highest bit */ - bit = fls(mask) - 1; - mask &= ~(1 << bit); - - /* - * Mask off all speeds higher than or equal to the current one. At - * this point, if current SPD is not available and we previously - * recorded the link speed from SStatus, the driver has already - * masked off the highest bit so mask should already be 1 or 0. - * Otherwise, we should not force 1.5Gbps on a link where we have - * not previously recorded speed from SStatus. Just return in this - * case. - */ - if (spd > 1) - mask &= (1 << (spd - 1)) - 1; - else if (link->sata_spd) - return -EINVAL; - - /* were we already at the bottom? */ - if (!mask) - return -EINVAL; - - if (spd_limit) { - if (mask & ((1 << spd_limit) - 1)) - mask &= (1 << spd_limit) - 1; - else { - bit = ffs(mask) - 1; - mask = 1 << bit; - } - } - - link->sata_spd_limit = mask; - - ata_link_warn(link, "limiting SATA link speed to %s\n", - sata_spd_string(fls(mask))); - - return 0; -} - #ifdef CONFIG_ATA_ACPI /** * ata_timing_cycle2mode - find xfer mode for the specified cycle duration diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c index ea6126c139af..124e2b2ea3c0 100644 --- a/drivers/ata/libata-sata.c +++ b/drivers/ata/libata-sata.c @@ -517,6 +517,86 @@ int sata_set_spd(struct ata_link *link) } EXPORT_SYMBOL_GPL(sata_set_spd); +/** + * sata_down_spd_limit - adjust SATA spd limit downward + * @link: Link to adjust SATA spd limit for + * @spd_limit: Additional limit + * + * Adjust SATA spd limit of @link downward. Note that this + * function only adjusts the limit. The change must be applied + * using sata_set_spd(). + * + * If @spd_limit is non-zero, the speed is limited to equal to or + * lower than @spd_limit if such speed is supported. If + * @spd_limit is slower than any supported speed, only the lowest + * supported speed is allowed. + * + * LOCKING: + * Inherited from caller. + * + * RETURNS: + * 0 on success, negative errno on failure + */ +int sata_down_spd_limit(struct ata_link *link, u32 spd_limit) +{ + u32 sstatus, spd, mask; + int rc, bit; + + if (!sata_scr_valid(link)) + return -EOPNOTSUPP; + + /* If SCR can be read, use it to determine the current SPD. + * If not, use cached value in link->sata_spd. + */ + rc = sata_scr_read(link, SCR_STATUS, &sstatus); + if (rc == 0 && ata_sstatus_online(sstatus)) + spd = (sstatus >> 4) & 0xf; + else + spd = link->sata_spd; + + mask = link->sata_spd_limit; + if (mask <= 1) + return -EINVAL; + + /* unconditionally mask off the highest bit */ + bit = fls(mask) - 1; + mask &= ~(1 << bit); + + /* + * Mask off all speeds higher than or equal to the current one. At + * this point, if current SPD is not available and we previously + * recorded the link speed from SStatus, the driver has already + * masked off the highest bit so mask should already be 1 or 0. + * Otherwise, we should not force 1.5Gbps on a link where we have + * not previously recorded speed from SStatus. Just return in this + * case. + */ + if (spd > 1) + mask &= (1 << (spd - 1)) - 1; + else if (link->sata_spd) + return -EINVAL; + + /* were we already at the bottom? */ + if (!mask) + return -EINVAL; + + if (spd_limit) { + if (mask & ((1 << spd_limit) - 1)) + mask &= (1 << spd_limit) - 1; + else { + bit = ffs(mask) - 1; + mask = 1 << bit; + } + } + + link->sata_spd_limit = mask; + + ata_link_warn(link, "limiting SATA link speed to %s\n", + sata_spd_string(fls(mask))); + + return 0; +} + /** * sata_link_hardreset - reset link via SATA phy reset * @link: link to reset diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index ab4bd44ba17c..3df17da08c7f 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -38,6 +38,12 @@ extern int libata_noacpi; extern int libata_allow_tpm; extern const struct device_type ata_port_type; extern struct ata_link *ata_dev_phys_link(struct ata_device *dev); + +static inline bool ata_sstatus_online(u32 sstatus) +{ + return (sstatus & 0xf) == 0x3; +} + #ifdef CONFIG_ATA_FORCE extern void ata_force_cbl(struct ata_port *ap); #else @@ -65,7 +71,6 @@ extern bool ata_dev_power_init_tf(struct ata_device *dev, struct ata_taskfile *tf, bool set_active); extern void ata_dev_power_set_standby(struct ata_device *dev); extern void ata_dev_power_set_active(struct ata_device *dev); -extern int sata_down_spd_limit(struct ata_link *link, u32 spd_limit); extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel); extern unsigned int ata_dev_set_feature(struct ata_device *dev, u8 subcmd, u8 action); @@ -87,6 +92,16 @@ extern unsigned int ata_read_log_page(struct ata_device *dev, u8 log, #define to_ata_port(d) container_of(d, struct ata_port, tdev) +/* libata-sata.c */ +#ifdef CONFIG_SATA_HOST +int sata_down_spd_limit(struct ata_link *link, u32 spd_limit); +#else +static inline int sata_down_spd_limit(struct ata_link *link, u32 spd_limit) +{ + return -EOPNOTSUPP; +} +#endif + /* libata-acpi.c */ #ifdef CONFIG_ATA_ACPI extern unsigned int ata_acpi_gtf_filter; From 78f76b09c915d7281317d8e082c4c02f325a0366 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Wed, 17 Jul 2024 17:48:16 +0900 Subject: [PATCH 33/39] ata: libata: Move sata_std_hardreset() definition to libata-sata.c Unlike ata_std_prereset() and ata_std_postreset(), the function sata_std_hardreset() applies only to SATA devices, as its name implies. So move its definition to libata-sata.c. Together with this, also move the definition of sata_port_ops to libata-sata.c, where it belongs. Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Hannes Reinecke --- drivers/ata/libata-core.c | 35 ----------------------------------- drivers/ata/libata-sata.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 9 +++++++-- 3 files changed, 43 insertions(+), 37 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b957eb900a00..b5a051bbb01f 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -72,14 +72,6 @@ const struct ata_port_operations ata_base_port_ops = { .end_eh = ata_std_end_eh, }; -const struct ata_port_operations sata_port_ops = { - .inherits = &ata_base_port_ops, - - .qc_defer = ata_std_qc_defer, - .hardreset = sata_std_hardreset, -}; -EXPORT_SYMBOL_GPL(sata_port_ops); - static unsigned int ata_dev_init_params(struct ata_device *dev, u16 heads, u16 sectors); static unsigned int ata_dev_set_xfermode(struct ata_device *dev); @@ -3676,33 +3668,6 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline) } EXPORT_SYMBOL_GPL(ata_std_prereset); -/** - * sata_std_hardreset - COMRESET w/o waiting or classification - * @link: link to reset - * @class: resulting class of attached device - * @deadline: deadline jiffies for the operation - * - * Standard SATA COMRESET w/o waiting or classification. - * - * LOCKING: - * Kernel thread context (may sleep) - * - * RETURNS: - * 0 if link offline, -EAGAIN if link online, -errno on errors. - */ -int sata_std_hardreset(struct ata_link *link, unsigned int *class, - unsigned long deadline) -{ - const unsigned int *timing = sata_ehc_deb_timing(&link->eh_context); - bool online; - int rc; - - /* do hardreset */ - rc = sata_link_hardreset(link, timing, deadline, &online, NULL); - return online ? -EAGAIN : rc; -} -EXPORT_SYMBOL_GPL(sata_std_hardreset); - /** * ata_std_postreset - standard postreset callback * @link: the target ata_link diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c index 124e2b2ea3c0..40f70de94fbd 100644 --- a/drivers/ata/libata-sata.c +++ b/drivers/ata/libata-sata.c @@ -706,6 +706,34 @@ int sata_link_hardreset(struct ata_link *link, const unsigned int *timing, } EXPORT_SYMBOL_GPL(sata_link_hardreset); +/** + * sata_std_hardreset - COMRESET w/o waiting or classification + * @link: link to reset + * @class: resulting class of attached device + * @deadline: deadline jiffies for the operation + * + * Standard SATA COMRESET w/o waiting or classification. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 if link offline, -EAGAIN if link online, -errno on errors. + */ +int sata_std_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +{ + const unsigned int *timing = sata_ehc_deb_timing(&link->eh_context); + bool online; + int rc; + + rc = sata_link_hardreset(link, timing, deadline, &online, NULL); + if (online) + return -EAGAIN; + return rc; +} +EXPORT_SYMBOL_GPL(sata_std_hardreset); + /** * ata_qc_complete_multiple - Complete multiple qcs successfully * @ap: port in question @@ -1654,3 +1682,11 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) ehc->i.err_mask &= ~AC_ERR_DEV; } EXPORT_SYMBOL_GPL(ata_eh_analyze_ncq_error); + +const struct ata_port_operations sata_port_ops = { + .inherits = &ata_base_port_ops, + + .qc_defer = ata_std_qc_defer, + .hardreset = sata_std_hardreset, +}; +EXPORT_SYMBOL_GPL(sata_port_ops); diff --git a/include/linux/libata.h b/include/linux/libata.h index 6552e90753ae..d52ae7723c05 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1104,8 +1104,6 @@ static inline bool ata_port_is_frozen(const struct ata_port *ap) extern int ata_std_prereset(struct ata_link *link, unsigned long deadline); extern int ata_wait_after_reset(struct ata_link *link, unsigned long deadline, int (*check_ready)(struct ata_link *link)); -extern int sata_std_hardreset(struct ata_link *link, unsigned int *class, - unsigned long deadline); extern void ata_std_postreset(struct ata_link *link, unsigned int *classes); extern struct ata_host *ata_host_alloc(struct device *dev, int n_ports); @@ -1229,6 +1227,8 @@ extern int sata_scr_read(struct ata_link *link, int reg, u32 *val); extern int sata_scr_write(struct ata_link *link, int reg, u32 val); extern int sata_scr_write_flush(struct ata_link *link, int reg, u32 val); extern int sata_set_spd(struct ata_link *link); +int sata_std_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline); extern int sata_link_hardreset(struct ata_link *link, const unsigned int *timing, unsigned long deadline, bool *online, int (*check_ready)(struct ata_link *)); @@ -1256,6 +1256,11 @@ static inline int sata_scr_write_flush(struct ata_link *link, int reg, u32 val) return -EOPNOTSUPP; } static inline int sata_set_spd(struct ata_link *link) { return -EOPNOTSUPP; } +static inline int sata_std_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +{ + return -EOPNOTSUPP; +} static inline int sata_link_hardreset(struct ata_link *link, const unsigned int *timing, unsigned long deadline, From 10e807637f288f9963340a30ae8da9bb06beca3c Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Mon, 10 Jun 2024 19:11:31 +0900 Subject: [PATCH 34/39] ata: libata: Rename ata_eh_read_sense_success_ncq_log() The function ata_eh_read_sense_success_ncq_log() does more that just reading the sense data for successful NCQ commands log page as it also sets the sense data for all commands listed in the log page. Rename this function to ata_eh_get_ncq_success_sense() to better describe what the function does. Furthermore, since this function is only called from ata_eh_get_success_sense() in libata-eh.c, there is no need to export it and its declaration can be moved to drivers/ata/libata.h. To be consistent with this change, the function ata_eh_read_sense_success_non_ncq() is also renamed to ata_eh_get_non_ncq_success_sense(). Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Hannes Reinecke --- drivers/ata/libata-eh.c | 6 +++--- drivers/ata/libata-sata.c | 7 +++---- drivers/ata/libata.h | 5 +++++ include/linux/libata.h | 5 ----- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 7de97ee8e78b..d2747a0d684c 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1962,7 +1962,7 @@ static inline bool ata_eh_quiet(struct ata_queued_cmd *qc) return qc->flags & ATA_QCFLAG_QUIET; } -static int ata_eh_read_sense_success_non_ncq(struct ata_link *link) +static int ata_eh_get_non_ncq_success_sense(struct ata_link *link) { struct ata_port *ap = link->ap; struct ata_queued_cmd *qc; @@ -2013,9 +2013,9 @@ static void ata_eh_get_success_sense(struct ata_link *link) * request sense ext command to retrieve the sense data. */ if (link->sactive) - ret = ata_eh_read_sense_success_ncq_log(link); + ret = ata_eh_get_ncq_success_sense(link); else - ret = ata_eh_read_sense_success_non_ncq(link); + ret = ata_eh_get_non_ncq_success_sense(link); if (ret) goto out; diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c index 40f70de94fbd..4e063cb42018 100644 --- a/drivers/ata/libata-sata.c +++ b/drivers/ata/libata-sata.c @@ -1487,8 +1487,8 @@ static int ata_eh_read_log_10h(struct ata_device *dev, } /** - * ata_eh_read_sense_success_ncq_log - Read the sense data for successful - * NCQ commands log + * ata_eh_get_ncq_success_sense - Read and process the sense data for + * successful NCQ commands log page * @link: ATA link to get sense data for * * Read the sense data for successful NCQ commands log page to obtain @@ -1501,7 +1501,7 @@ static int ata_eh_read_log_10h(struct ata_device *dev, * RETURNS: * 0 on success, -errno otherwise. */ -int ata_eh_read_sense_success_ncq_log(struct ata_link *link) +int ata_eh_get_ncq_success_sense(struct ata_link *link) { struct ata_device *dev = link->device; struct ata_port *ap = dev->link->ap; @@ -1571,7 +1571,6 @@ int ata_eh_read_sense_success_ncq_log(struct ata_link *link) return ret; } -EXPORT_SYMBOL_GPL(ata_eh_read_sense_success_ncq_log); /** * ata_eh_analyze_ncq_error - analyze NCQ error diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 3df17da08c7f..2a9d1bbf2482 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -95,11 +95,16 @@ extern unsigned int ata_read_log_page(struct ata_device *dev, u8 log, /* libata-sata.c */ #ifdef CONFIG_SATA_HOST int sata_down_spd_limit(struct ata_link *link, u32 spd_limit); +int ata_eh_get_ncq_success_sense(struct ata_link *link); #else static inline int sata_down_spd_limit(struct ata_link *link, u32 spd_limit) { return -EOPNOTSUPP; } +static inline int ata_eh_get_ncq_success_sense(struct ata_link *link) +{ + return -EOPNOTSUPP; +} #endif /* libata-acpi.c */ diff --git a/include/linux/libata.h b/include/linux/libata.h index d52ae7723c05..55a6b57742bc 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1234,7 +1234,6 @@ extern int sata_link_hardreset(struct ata_link *link, bool *online, int (*check_ready)(struct ata_link *)); extern int sata_link_resume(struct ata_link *link, const unsigned int *params, unsigned long deadline); -extern int ata_eh_read_sense_success_ncq_log(struct ata_link *link); extern void ata_eh_analyze_ncq_error(struct ata_link *link); #else static inline const unsigned int * @@ -1277,10 +1276,6 @@ static inline int sata_link_resume(struct ata_link *link, { return -EOPNOTSUPP; } -static inline int ata_eh_read_sense_success_ncq_log(struct ata_link *link) -{ - return -EOPNOTSUPP; -} static inline void ata_eh_analyze_ncq_error(struct ata_link *link) { } #endif extern int sata_link_debounce(struct ata_link *link, From da65bbdd3bc1e8d2193e01167a413d90d9988c04 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Wed, 28 Aug 2024 11:07:43 +0900 Subject: [PATCH 35/39] ata: libata: Move sector_buf from struct ata_port to struct ata_device The 512B buffer sector_buf field of struct ata_port is used for scanning devices as well as during error recovery with ata EH. This buffer is thus useless if a port does not have a device connected to it. And also given that commands using this buffer are issued to devices, and not to ports, move this buffer definition from struct ata_port to struct ata_device. This change slightly increases system memory usage for systems using a port-multiplier as in that case we do not need a per-device buffer for scanning devices (PMP does not allow parallel scanning) nor for EH (as when entering EH we are guaranteed that all commands to all devices connected to the PMP have completed or have been aborted). However, this change reduces memory usage on systems that have many ports with only few devices rives connected, which is a much more common use case than the PMP use case. Suggested-by: Niklas Cassel Signed-off-by: Damien Le Moal Reviewed-by: Hannes Reinecke Reviewed-by: Niklas Cassel --- drivers/ata/libata-core.c | 63 ++++++++++++++++---------------------- drivers/ata/libata-eh.c | 2 +- drivers/ata/libata-pmp.c | 3 +- drivers/ata/libata-sata.c | 2 +- drivers/ata/libata-zpodd.c | 2 +- include/linux/libata.h | 4 ++- 6 files changed, 33 insertions(+), 43 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b5a051bbb01f..32325a1c07af 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2125,19 +2125,16 @@ retry: static int ata_log_supported(struct ata_device *dev, u8 log) { - struct ata_port *ap = dev->link->ap; - if (dev->quirks & ATA_QUIRK_NO_LOG_DIR) return 0; - if (ata_read_log_page(dev, ATA_LOG_DIRECTORY, 0, ap->sector_buf, 1)) + if (ata_read_log_page(dev, ATA_LOG_DIRECTORY, 0, dev->sector_buf, 1)) return 0; - return get_unaligned_le16(&ap->sector_buf[log * 2]); + return get_unaligned_le16(&dev->sector_buf[log * 2]); } static bool ata_identify_page_supported(struct ata_device *dev, u8 page) { - struct ata_port *ap = dev->link->ap; unsigned int err, i; if (dev->quirks & ATA_QUIRK_NO_ID_DEV_LOG) @@ -2160,13 +2157,13 @@ static bool ata_identify_page_supported(struct ata_device *dev, u8 page) * Read IDENTIFY DEVICE data log, page 0, to figure out if the page is * supported. */ - err = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, 0, ap->sector_buf, - 1); + err = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, 0, + dev->sector_buf, 1); if (err) return false; - for (i = 0; i < ap->sector_buf[8]; i++) { - if (ap->sector_buf[9 + i] == page) + for (i = 0; i < dev->sector_buf[8]; i++) { + if (dev->sector_buf[9 + i] == page) return true; } @@ -2218,7 +2215,6 @@ static inline bool ata_dev_knobble(struct ata_device *dev) static void ata_dev_config_ncq_send_recv(struct ata_device *dev) { - struct ata_port *ap = dev->link->ap; unsigned int err_mask; if (!ata_log_supported(dev, ATA_LOG_NCQ_SEND_RECV)) { @@ -2226,12 +2222,12 @@ static void ata_dev_config_ncq_send_recv(struct ata_device *dev) return; } err_mask = ata_read_log_page(dev, ATA_LOG_NCQ_SEND_RECV, - 0, ap->sector_buf, 1); + 0, dev->sector_buf, 1); if (!err_mask) { u8 *cmds = dev->ncq_send_recv_cmds; dev->flags |= ATA_DFLAG_NCQ_SEND_RECV; - memcpy(cmds, ap->sector_buf, ATA_LOG_NCQ_SEND_RECV_SIZE); + memcpy(cmds, dev->sector_buf, ATA_LOG_NCQ_SEND_RECV_SIZE); if (dev->quirks & ATA_QUIRK_NO_NCQ_TRIM) { ata_dev_dbg(dev, "disabling queued TRIM support\n"); @@ -2243,7 +2239,6 @@ static void ata_dev_config_ncq_send_recv(struct ata_device *dev) static void ata_dev_config_ncq_non_data(struct ata_device *dev) { - struct ata_port *ap = dev->link->ap; unsigned int err_mask; if (!ata_log_supported(dev, ATA_LOG_NCQ_NON_DATA)) { @@ -2252,17 +2247,14 @@ static void ata_dev_config_ncq_non_data(struct ata_device *dev) return; } err_mask = ata_read_log_page(dev, ATA_LOG_NCQ_NON_DATA, - 0, ap->sector_buf, 1); - if (!err_mask) { - u8 *cmds = dev->ncq_non_data_cmds; - - memcpy(cmds, ap->sector_buf, ATA_LOG_NCQ_NON_DATA_SIZE); - } + 0, dev->sector_buf, 1); + if (!err_mask) + memcpy(dev->ncq_non_data_cmds, dev->sector_buf, + ATA_LOG_NCQ_NON_DATA_SIZE); } static void ata_dev_config_ncq_prio(struct ata_device *dev) { - struct ata_port *ap = dev->link->ap; unsigned int err_mask; if (!ata_identify_page_supported(dev, ATA_LOG_SATA_SETTINGS)) @@ -2271,12 +2263,11 @@ static void ata_dev_config_ncq_prio(struct ata_device *dev) err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, ATA_LOG_SATA_SETTINGS, - ap->sector_buf, - 1); + dev->sector_buf, 1); if (err_mask) goto not_supported; - if (!(ap->sector_buf[ATA_LOG_NCQ_PRIO_OFFSET] & BIT(3))) + if (!(dev->sector_buf[ATA_LOG_NCQ_PRIO_OFFSET] & BIT(3))) goto not_supported; dev->flags |= ATA_DFLAG_NCQ_PRIO; @@ -2392,9 +2383,8 @@ static void ata_dev_config_sense_reporting(struct ata_device *dev) static void ata_dev_config_zac(struct ata_device *dev) { - struct ata_port *ap = dev->link->ap; unsigned int err_mask; - u8 *identify_buf = ap->sector_buf; + u8 *identify_buf = dev->sector_buf; dev->zac_zones_optimal_open = U32_MAX; dev->zac_zones_optimal_nonseq = U32_MAX; @@ -2446,7 +2436,6 @@ static void ata_dev_config_zac(struct ata_device *dev) static void ata_dev_config_trusted(struct ata_device *dev) { - struct ata_port *ap = dev->link->ap; u64 trusted_cap; unsigned int err; @@ -2460,11 +2449,11 @@ static void ata_dev_config_trusted(struct ata_device *dev) } err = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, ATA_LOG_SECURITY, - ap->sector_buf, 1); + dev->sector_buf, 1); if (err) return; - trusted_cap = get_unaligned_le64(&ap->sector_buf[40]); + trusted_cap = get_unaligned_le64(&dev->sector_buf[40]); if (!(trusted_cap & (1ULL << 63))) { ata_dev_dbg(dev, "Trusted Computing capability qword not valid!\n"); @@ -2492,12 +2481,12 @@ static void ata_dev_config_cdl(struct ata_device *dev) err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, ATA_LOG_SUPPORTED_CAPABILITIES, - ap->sector_buf, 1); + dev->sector_buf, 1); if (err_mask) goto not_supported; /* Check Command Duration Limit Supported bits */ - val = get_unaligned_le64(&ap->sector_buf[168]); + val = get_unaligned_le64(&dev->sector_buf[168]); if (!(val & BIT_ULL(63)) || !(val & BIT_ULL(0))) goto not_supported; @@ -2510,7 +2499,7 @@ static void ata_dev_config_cdl(struct ata_device *dev) * We must have support for the sense data for successful NCQ commands * log indicated by the successful NCQ command sense data supported bit. */ - val = get_unaligned_le64(&ap->sector_buf[8]); + val = get_unaligned_le64(&dev->sector_buf[8]); if (!(val & BIT_ULL(63)) || !(val & BIT_ULL(47))) { ata_dev_warn(dev, "CDL supported but Successful NCQ Command Sense Data is not supported\n"); @@ -2530,11 +2519,11 @@ static void ata_dev_config_cdl(struct ata_device *dev) */ err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, ATA_LOG_CURRENT_SETTINGS, - ap->sector_buf, 1); + dev->sector_buf, 1); if (err_mask) goto not_supported; - val = get_unaligned_le64(&ap->sector_buf[8]); + val = get_unaligned_le64(&dev->sector_buf[8]); cdl_enabled = val & BIT_ULL(63) && val & BIT_ULL(21); if (dev->flags & ATA_DFLAG_CDL_ENABLED) { if (!cdl_enabled) { @@ -2591,13 +2580,13 @@ static void ata_dev_config_cdl(struct ata_device *dev) * Command duration limits is supported: cache the CDL log page 18h * (command duration descriptors). */ - err_mask = ata_read_log_page(dev, ATA_LOG_CDL, 0, ap->sector_buf, 1); + err_mask = ata_read_log_page(dev, ATA_LOG_CDL, 0, dev->sector_buf, 1); if (err_mask) { ata_dev_warn(dev, "Read Command Duration Limits log failed\n"); goto not_supported; } - memcpy(dev->cdl, ap->sector_buf, ATA_LOG_CDL_SIZE); + memcpy(dev->cdl, dev->sector_buf, ATA_LOG_CDL_SIZE); dev->flags |= ATA_DFLAG_CDL; return; @@ -2689,7 +2678,7 @@ nofua: static void ata_dev_config_devslp(struct ata_device *dev) { - u8 *sata_setting = dev->link->ap->sector_buf; + u8 *sata_setting = dev->sector_buf; unsigned int err_mask; int i, j; @@ -3759,7 +3748,7 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class, int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags) { unsigned int class = dev->class; - u16 *id = (void *)dev->link->ap->sector_buf; + u16 *id = (void *)dev->sector_buf; int rc; /* read ID data */ diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index d2747a0d684c..ed535e1b4225 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -3284,7 +3284,7 @@ static int atapi_eh_clear_ua(struct ata_device *dev) int i; for (i = 0; i < ATA_EH_UA_TRIES; i++) { - u8 *sense_buffer = dev->link->ap->sector_buf; + u8 *sense_buffer = dev->sector_buf; u8 sense_key = 0; unsigned int err_mask; diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index e2e9cbd405fa..d5d189328ae6 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -648,8 +648,7 @@ static int sata_pmp_same_pmp(struct ata_device *dev, const u32 *new_gscr) static int sata_pmp_revalidate(struct ata_device *dev, unsigned int new_class) { struct ata_link *link = dev->link; - struct ata_port *ap = link->ap; - u32 *gscr = (void *)ap->sector_buf; + u32 *gscr = (void *)dev->sector_buf; int rc; ata_eh_about_to_do(link, NULL, ATA_EH_REVALIDATE); diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c index 4e063cb42018..498430db86f7 100644 --- a/drivers/ata/libata-sata.c +++ b/drivers/ata/libata-sata.c @@ -1448,7 +1448,7 @@ EXPORT_SYMBOL_GPL(sata_async_notification); static int ata_eh_read_log_10h(struct ata_device *dev, int *tag, struct ata_taskfile *tf) { - u8 *buf = dev->link->ap->sector_buf; + u8 *buf = dev->sector_buf; unsigned int err_mask; u8 csum; int i; diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c index eefda51f97d3..4b83b517caec 100644 --- a/drivers/ata/libata-zpodd.c +++ b/drivers/ata/libata-zpodd.c @@ -112,7 +112,7 @@ static bool zpready(struct ata_device *dev) if (!ret || sense_key != NOT_READY) return false; - sense_buf = dev->link->ap->sector_buf; + sense_buf = dev->sector_buf; ret = atapi_eh_request_sense(dev, sense_buf, sense_key); if (ret) return false; diff --git a/include/linux/libata.h b/include/linux/libata.h index 55a6b57742bc..aac38dcd2230 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -769,6 +769,9 @@ struct ata_device { int spdn_cnt; /* ering is CLEAR_END, read comment above CLEAR_END */ struct ata_ering ering; + + /* For EH */ + u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned; }; /* Fields between ATA_DEVICE_CLEAR_BEGIN and ATA_DEVICE_CLEAR_END are @@ -916,7 +919,6 @@ struct ata_port { #endif /* owned by EH */ u8 *ncq_sense_buf; - u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned; }; /* The following initializer overrides a method to NULL whether one of From 5f8319c4b3ec4e8fdc7f7bf61f47f985e1a6f074 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 5 Sep 2024 10:51:19 +0900 Subject: [PATCH 36/39] ata: libata: Introduce ata_dev_free_resources Introduce the function ata_dev_free_resources() to free the resources allocated to support a device features. For now, this function is reduced to calling zpodd_exit() for devices that have this feature enabled. ata_dev_free_resources() is called from ata_eh_dev_disable() as this function is always called for all devices attached to a port that is being detached and for devices that are being disabled due to being removed (detached) from the system or due to errors. With this change, the call to zpodd_exit() done in ata_port_detach() and ata_scsi_handle_link_detach() are removed as these functions remove all devices attached to the link or port using libata EH, thus resulting in ata_eh_dev_disable() being called and the zpodd_exit() function being executed. Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel --- drivers/ata/libata-core.c | 27 +++++++++++++++++++-------- drivers/ata/libata-eh.c | 5 ++++- drivers/ata/libata-scsi.c | 3 --- drivers/ata/libata.h | 1 + 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 32325a1c07af..bfd452b0d46d 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5976,6 +5976,21 @@ int ata_host_activate(struct ata_host *host, int irq, } EXPORT_SYMBOL_GPL(ata_host_activate); +/** + * ata_dev_free_resources - Free a device resources + * @dev: Target ATA device + * + * Free resources allocated to support a device features. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +void ata_dev_free_resources(struct ata_device *dev) +{ + if (zpodd_dev_enabled(dev)) + zpodd_exit(dev); +} + /** * ata_port_detach - Detach ATA port in preparation of device removal * @ap: ATA port to be detached @@ -6030,19 +6045,15 @@ static void ata_port_detach(struct ata_port *ap) cancel_delayed_work_sync(&ap->hotplug_task); cancel_delayed_work_sync(&ap->scsi_rescan_task); - /* clean up zpodd on port removal */ - ata_for_each_link(link, ap, HOST_FIRST) { - ata_for_each_dev(dev, link, ALL) { - if (zpodd_dev_enabled(dev)) - zpodd_exit(dev); - } - } + /* Delete port multiplier link transport devices */ if (ap->pmp_link) { int i; + for (i = 0; i < SATA_PMP_MAX_PORTS; i++) ata_tlink_delete(&ap->pmp_link[i]); } - /* remove the associated SCSI host */ + + /* Remove the associated SCSI host */ scsi_remove_host(ap->scsi_host); ata_tport_delete(ap); } diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index ed535e1b4225..364828b8a22d 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -500,10 +500,13 @@ static void ata_eh_dev_disable(struct ata_device *dev) ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | ATA_DNXFER_QUIET); dev->class++; - /* From now till the next successful probe, ering is used to + /* + * From now till the next successful probe, ering is used to * track probe failures. Clear accumulated device error info. */ ata_ering_clear(&dev->ering); + + ata_dev_free_resources(dev); } static void ata_eh_unload(struct ata_port *ap) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 6bd7ab27fcbb..4fb45565c142 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -4614,9 +4614,6 @@ static void ata_scsi_handle_link_detach(struct ata_link *link) dev->flags &= ~ATA_DFLAG_DETACHED; spin_unlock_irqrestore(ap->lock, flags); - if (zpodd_dev_enabled(dev)) - zpodd_exit(dev); - ata_scsi_remove_dev(dev); } } diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 2a9d1bbf2482..927d77bde7ef 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -71,6 +71,7 @@ extern bool ata_dev_power_init_tf(struct ata_device *dev, struct ata_taskfile *tf, bool set_active); extern void ata_dev_power_set_standby(struct ata_device *dev); extern void ata_dev_power_set_active(struct ata_device *dev); +void ata_dev_free_resources(struct ata_device *dev); extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel); extern unsigned int ata_dev_set_feature(struct ata_device *dev, u8 subcmd, u8 action); From 602bcf212637633d537ee74bf39c6bc5722efb9b Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Wed, 17 Jul 2024 17:55:31 +0900 Subject: [PATCH 37/39] ata: libata: Improve CDL resource management The ncq_sense_buf buffer field of struct ata_port is allocated and used only for devices that support the Command Duration Limits (CDL) feature. However, the cdl buffer of struct ata_device, which is used to cache the command duration limits log page for devices supporting CDL is always allocated as part of struct ata_device, which is wasteful of memory for devices that do not support this feature. Clean this up by defining both buffers as part of the new ata_cdl structure and allocating this structure only for devices that support the CDL feature. This new structure is attached to struct ata_device using the cdl pointer. The functions ata_dev_init_cdl_resources() and ata_dev_cleanup_cdl_resources() are defined to manage this new structure allocation, initialization and freeing when a port is removed or a device disabled. ata_dev_init_cdl_resources() is called from ata_dev_config_cdl() only for devices that support CDL. ata_dev_cleanup_cdl_resources() is called from ata_dev_free_resources() to free the ata_cdl structure when a device is being disabled by EH. Note that the name of the former cdl log buffer of struct ata_device is changed to desc_log_buf to make it clearer that it is a buffer for the limit descriptors log page. This change reduces the size of struct ata_device, thus reducing memory usage for ATA devices that do not support the CDL feature. Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel --- drivers/ata/libata-core.c | 61 ++++++++++++++++++++++++--------------- drivers/ata/libata-sata.c | 2 +- drivers/ata/libata-scsi.c | 2 +- drivers/ata/libata.h | 1 + include/linux/libata.h | 21 +++++++++++--- 5 files changed, 57 insertions(+), 30 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index bfd452b0d46d..082179c38e1b 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2464,12 +2464,41 @@ static void ata_dev_config_trusted(struct ata_device *dev) dev->flags |= ATA_DFLAG_TRUSTED; } +void ata_dev_cleanup_cdl_resources(struct ata_device *dev) +{ + kfree(dev->cdl); + dev->cdl = NULL; +} + +static int ata_dev_init_cdl_resources(struct ata_device *dev) +{ + struct ata_cdl *cdl = dev->cdl; + unsigned int err_mask; + + if (!cdl) { + cdl = kzalloc(sizeof(*cdl), GFP_KERNEL); + if (!cdl) + return -ENOMEM; + dev->cdl = cdl; + } + + err_mask = ata_read_log_page(dev, ATA_LOG_CDL, 0, cdl->desc_log_buf, + ATA_LOG_CDL_SIZE / ATA_SECT_SIZE); + if (err_mask) { + ata_dev_warn(dev, "Read Command Duration Limits log failed\n"); + ata_dev_cleanup_cdl_resources(dev); + return -EIO; + } + + return 0; +} + static void ata_dev_config_cdl(struct ata_device *dev) { - struct ata_port *ap = dev->link->ap; unsigned int err_mask; bool cdl_enabled; u64 val; + int ret; if (ata_id_major_version(dev->id) < 11) goto not_supported; @@ -2564,37 +2593,20 @@ static void ata_dev_config_cdl(struct ata_device *dev) } } - /* - * Allocate a buffer to handle reading the sense data for successful - * NCQ Commands log page for commands using a CDL with one of the limit - * policy set to 0xD (successful completion with sense data available - * bit set). - */ - if (!ap->ncq_sense_buf) { - ap->ncq_sense_buf = kmalloc(ATA_LOG_SENSE_NCQ_SIZE, GFP_KERNEL); - if (!ap->ncq_sense_buf) - goto not_supported; - } - - /* - * Command duration limits is supported: cache the CDL log page 18h - * (command duration descriptors). - */ - err_mask = ata_read_log_page(dev, ATA_LOG_CDL, 0, dev->sector_buf, 1); - if (err_mask) { - ata_dev_warn(dev, "Read Command Duration Limits log failed\n"); + /* CDL is supported: allocate and initialize needed resources. */ + ret = ata_dev_init_cdl_resources(dev); + if (ret) { + ata_dev_warn(dev, "Initialize CDL resources failed\n"); goto not_supported; } - memcpy(dev->cdl, dev->sector_buf, ATA_LOG_CDL_SIZE); dev->flags |= ATA_DFLAG_CDL; return; not_supported: dev->flags &= ~(ATA_DFLAG_CDL | ATA_DFLAG_CDL_ENABLED); - kfree(ap->ncq_sense_buf); - ap->ncq_sense_buf = NULL; + ata_dev_cleanup_cdl_resources(dev); } static int ata_dev_config_lba(struct ata_device *dev) @@ -5451,7 +5463,6 @@ void ata_port_free(struct ata_port *ap) kfree(ap->pmp_link); kfree(ap->slave_link); - kfree(ap->ncq_sense_buf); ida_free(&ata_ida, ap->print_id); kfree(ap); } @@ -5989,6 +6000,8 @@ void ata_dev_free_resources(struct ata_device *dev) { if (zpodd_dev_enabled(dev)) zpodd_exit(dev); + + ata_dev_cleanup_cdl_resources(dev); } /** diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c index 498430db86f7..c8b119a06bb2 100644 --- a/drivers/ata/libata-sata.c +++ b/drivers/ata/libata-sata.c @@ -1505,7 +1505,7 @@ int ata_eh_get_ncq_success_sense(struct ata_link *link) { struct ata_device *dev = link->device; struct ata_port *ap = dev->link->ap; - u8 *buf = ap->ncq_sense_buf; + u8 *buf = dev->cdl->ncq_sense_log_buf; struct ata_queued_cmd *qc; unsigned int err_mask, tag; u8 *sense, sk = 0, asc = 0, ascq = 0; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 4fb45565c142..9f75d26808bf 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2248,7 +2248,7 @@ static inline u16 ata_xlat_cdl_limit(u8 *buf) static unsigned int ata_msense_control_spgt2(struct ata_device *dev, u8 *buf, u8 spg) { - u8 *b, *cdl = dev->cdl, *desc; + u8 *b, *cdl = dev->cdl->desc_log_buf, *desc; u32 policy; int i; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 927d77bde7ef..0337be4faec7 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -90,6 +90,7 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); extern const char *sata_spd_string(unsigned int spd); extern unsigned int ata_read_log_page(struct ata_device *dev, u8 log, u8 page, void *buf, unsigned int sectors); +void ata_dev_cleanup_cdl_resources(struct ata_device *dev); #define to_ata_port(d) container_of(d, struct ata_port, tdev) diff --git a/include/linux/libata.h b/include/linux/libata.h index aac38dcd2230..9b4a6ff03235 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -700,6 +700,21 @@ struct ata_cpr_log { struct ata_cpr cpr[] __counted_by(nr_cpr); }; +struct ata_cdl { + /* + * Buffer to cache the CDL log page 18h (command duration descriptors) + * for SCSI-ATA translation. + */ + u8 desc_log_buf[ATA_LOG_CDL_SIZE]; + + /* + * Buffer to handle reading the sense data for successful NCQ Commands + * log page for commands using a CDL with one of the limits policy set + * to 0xD (successful completion with sense data available bit set). + */ + u8 ncq_sense_log_buf[ATA_LOG_SENSE_NCQ_SIZE]; +}; + struct ata_device { struct ata_link *link; unsigned int devno; /* 0 or 1 */ @@ -762,8 +777,8 @@ struct ata_device { /* Concurrent positioning ranges */ struct ata_cpr_log *cpr_log; - /* Command Duration Limits log support */ - u8 cdl[ATA_LOG_CDL_SIZE]; + /* Command Duration Limits support */ + struct ata_cdl *cdl; /* error history */ int spdn_cnt; @@ -917,8 +932,6 @@ struct ata_port { #ifdef CONFIG_ATA_ACPI struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */ #endif - /* owned by EH */ - u8 *ncq_sense_buf; }; /* The following initializer overrides a method to NULL whether one of From d647bdf4d080208b71a205ec19a1c9f18ca83f00 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Sat, 7 Sep 2024 10:56:32 +0900 Subject: [PATCH 38/39] ata: libata: Fix W=1 compilation warning Commit c494708d1f68 ("ata: libata: Cleanup libata-transport") inadvertently changed the name of the link argument to ata_link in the kdoc description of ata_tlink_add(), causing warnings to be issue when compiling with W=1: drivers/ata/libata-transport.c:690: warning: Function parameter or struct member 'link' not described in 'ata_tlink_add' drivers/ata/libata-transport.c:690: warning: Excess function parameter 'ata_link' description in 'ata_tlink_add' Change the kdoc argument name to "link" to avoid these warnings. Fixes: c494708d1f68 ("ata: libata: Cleanup libata-transport") Signed-off-by: Damien Le Moal --- drivers/ata/libata-transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index d9a1888eac34..e898be49df6b 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -679,7 +679,7 @@ void ata_tlink_delete(struct ata_link *link) /** * ata_tlink_add -- initialize an ATA link transport device - * @ata_link: struct ata_link owning the link transport device to initialize + * @link: struct ata_link owning the link transport device to initialize * * Initialize an ATA link transport device for sysfs. It will be added in the * device tree below the ATA port it belongs to. From e5dd410acb34c7341a0a93b429dcf3dabf9e3323 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Mon, 9 Sep 2024 17:42:38 +0200 Subject: [PATCH 39/39] ata: libata: Clear DID_TIME_OUT for ATA PT commands with sense data When ata_qc_complete() schedules a command for EH using ata_qc_schedule_eh(), blk_abort_request() will be called, which leads to req->q->mq_ops->timeout() / scsi_timeout() being called. scsi_timeout(), if the LLDD has no abort handler (libata has no abort handler), will set host byte to DID_TIME_OUT, and then call scsi_eh_scmd_add() to add the command to EH. Thus, when commands first enter libata's EH strategy_handler, all the commands that have been added to EH will have DID_TIME_OUT set. libata has its own flag (AC_ERR_TIMEOUT), that it sets for commands that have not received a completion at the time of entering EH. Thus, libata doesn't really care about DID_TIME_OUT at all, and currently clears the host byte at the end of EH, in ata_scsi_qc_complete(), before scsi_eh_finish_cmd() is called. However, this clearing in ata_scsi_qc_complete() is currently only done for commands that are not ATA passthrough commands. Since the host byte is visible in the completion that we return to user space for ATA passthrough commands, for ATA passthrough commands that got completed via EH (commands with sense data), the user will incorrectly see: ATA pass-through(16): transport error: Host_status=0x03 [DID_TIME_OUT] Fix this by moving the clearing of the host byte (which is currently only done for commands that are not ATA passthrough commands) from ata_scsi_qc_complete() to the start of EH (regardless if the command is ATA passthrough or not). While at it, use the proper helper function to clear the host byte, rather than open coding the clearing. This will make sure that we: -Correctly clear DID_TIME_OUT for both ATA passthrough commands and commands that are not ATA passthrough commands. -Do not needlessly clear the host byte for commands that did not go via EH. ata_scsi_qc_complete() is called both for commands that are completed normally (without going via EH), and for commands that went via EH, however, only commands that went via EH will have DID_TIME_OUT set. Fixes: 24aeebbf8ea9 ("scsi: ata: libata: Change ata_eh_request_sense() to not set CHECK_CONDITION") Reported-by: Igor Pylypiv Closes: https://lore.kernel.org/linux-ide/ZttIN8He8TOZ7Lct@google.com/ Signed-off-by: Niklas Cassel Tested-by: Igor Pylypiv Reviewed-by: Hannes Reinecke Signed-off-by: Damien Le Moal --- drivers/ata/libata-eh.c | 8 ++++++++ drivers/ata/libata-scsi.c | 3 --- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 364828b8a22d..3f0144e7dc80 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -633,6 +633,14 @@ void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, list_for_each_entry_safe(scmd, tmp, eh_work_q, eh_entry) { struct ata_queued_cmd *qc; + /* + * If the scmd was added to EH, via ata_qc_schedule_eh() -> + * scsi_timeout() -> scsi_eh_scmd_add(), scsi_timeout() will + * have set DID_TIME_OUT (since libata does not have an abort + * handler). Thus, to clear DID_TIME_OUT, clear the host byte. + */ + set_host_byte(scmd, DID_OK); + ata_qc_for_each_raw(ap, qc, i) { if (qc->flags & ATA_QCFLAG_ACTIVE && qc->scsicmd == scmd) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 9f75d26808bf..061fe63497bf 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1680,9 +1680,6 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) set_status_byte(qc->scsicmd, SAM_STAT_CHECK_CONDITION); } else if (is_error && !have_sense) { ata_gen_ata_sense(qc); - } else { - /* Keep the SCSI ML and status byte, clear host byte. */ - cmd->result &= 0x0000ffff; } ata_qc_done(qc);