From c8d1db7a34494d14757924e29352dc48d4e1639a Mon Sep 17 00:00:00 2001 From: Jonathan Bell Date: Fri, 10 Jan 2025 10:18:36 +0000 Subject: [PATCH 1/4] DT: bcm2712: override supports-cqe to a cell We want to be able to control the interop surface exposed by Command Queueing across bcm2712 products to a more restrictive default, with selectable disable and permissive behaviour. Changing the bool to a cell lets it relay a tristate value. Also add the override parameter to CM5 as CM5-lite may interface with arbitrary eMMC or SD cards. (Reimplemented on 6.12 - bcm2712 dts now has a downstream/upstream split.) Signed-off-by: Jonathan Bell --- arch/arm/boot/dts/overlays/README | 11 ++++++++--- arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi | 2 +- arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts | 4 ++-- arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi | 3 ++- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README index 6baa4577834960..a0824eccf0444b 100644 --- a/arch/arm/boot/dts/overlays/README +++ b/arch/arm/boot/dts/overlays/README @@ -405,9 +405,14 @@ Params: non-lite SKU of CM4). (default "on") - sd_cqe Set to "off" to disable Command Queueing if you - have an incompatible Class A2 SD card - (Pi 5 only, default "on") + sd_cqe Modify Command Queuing behaviour on the main SD + interface. Legal values are: + 0: disable CQ + 1: allow CQ for known-good SD A2 cards, and all + eMMC cards + 2: allow CQ for all SD A2 cards that aren't + known-bad, and all eMMC cards. + (2712 only, default "1") sd_overclock Clock (in MHz) to use when the MMC framework requests 50MHz diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi index adff5ae55b1f46..82d97d4af84bfe 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi @@ -586,7 +586,7 @@ clocks = <&clk_emmc2>; sdhci-caps-mask = <0x0000C000 0x0>; sdhci-caps = <0x0 0x0>; - supports-cqe; + supports-cqe = <1>; mmc-ddr-3_3v; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts index 83b88b0107f3c5..b6cb76ada0a2d2 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts +++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts @@ -322,7 +322,7 @@ dpi_16bit_gpio2: &rp1_dpi_16bit_gpio2 { }; sd-uhs-sdr50; sd-uhs-ddr50; sd-uhs-sdr104; - supports-cqe; + supports-cqe = <1>; cd-gpios = <&gio_aon 5 GPIO_ACTIVE_LOW>; //no-1-8-v; status = "okay"; @@ -703,7 +703,7 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; / { __overrides__ { - sd_cqe = <&sdio1>, "supports-cqe?"; + sd_cqe = <&sdio1>, "supports-cqe:0"; }; }; diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi index 79666d85c31a24..129d7be38eb930 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi @@ -296,7 +296,7 @@ dpi_16bit_gpio2: &rp1_dpi_16bit_gpio2 { }; mmc-hs400-1_8v; mmc-hs400-enhanced-strobe; broken-cd; - supports-cqe; + supports-cqe = <1>; status = "okay"; }; @@ -710,5 +710,6 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; <&ant2>, "output-low?=on"; noanthogs = <&ant1>,"status=disabled", <&ant2>, "status=disabled"; + sd_cqe = <&sdio1>, "supports-cqe:0"; }; }; From f1ca191c3c1c4975f14988a906f79f7415a08f40 Mon Sep 17 00:00:00 2001 From: Jonathan Bell Date: Wed, 8 Jan 2025 15:09:53 +0000 Subject: [PATCH 2/4] mmc: sd: filter card CQ support based on an allow-list We have found that many SD cards in the field, even of the same make and model, have latent bugs in their CQ implementation. Some product lines have fewer bugs with newer manufacture dates, but this is not a guarantee that a particular card is at a particular firmware revision level. Many of these bugs lead to card hangs or data corruption. Add a quirk to mark a card as having a tested, working CQ implementation and ignore the capability if absent. Signed-off-by: Jonathan Bell --- drivers/mmc/core/card.h | 5 +++++ drivers/mmc/core/sd.c | 4 ++++ include/linux/mmc/card.h | 1 + 3 files changed, 10 insertions(+) diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h index 0efdd58841f75f..950e21238bcf2e 100644 --- a/drivers/mmc/core/card.h +++ b/drivers/mmc/core/card.h @@ -295,4 +295,9 @@ static inline int mmc_card_broken_sd_poweroff_notify(const struct mmc_card *c) return c->quirks & MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY; } +static inline int mmc_card_working_sd_cq(const struct mmc_card *c) +{ + return c->quirks & MMC_QUIRK_WORKING_SD_CQ; +} + #endif diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index cd0cef8aebe03d..ece494e6c078a8 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1501,6 +1501,10 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, goto free_card; } + /* Disallow command queueing on unvetted cards */ + if (!mmc_card_working_sd_cq(card)) + card->ext_csd.cmdq_support = false; + /* Enable command queueing if supported */ if (card->ext_csd.cmdq_support && host->caps2 & MMC_CAP2_CQE) { /* diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 92255a1dc0c6d3..6289155f806f15 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -295,6 +295,7 @@ struct mmc_card { #define MMC_QUIRK_BROKEN_SD_CACHE (1<<15) /* Disable broken SD cache support */ #define MMC_QUIRK_BROKEN_CACHE_FLUSH (1<<16) /* Don't flush cache until the write has occurred */ #define MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY (1<<17) /* Disable broken SD poweroff notify support */ +#define MMC_QUIRK_WORKING_SD_CQ (1<<30) /* SD card has known-good CQ implementation */ #define MMC_QUIRK_ERASE_BROKEN (1<<31) /* Skip erase */ bool written_flag; /* Indicates eMMC has been written since power on */ From 37dee3b545a1639bd8ed1f1a9f4f096d46593afb Mon Sep 17 00:00:00 2001 From: Jonathan Bell Date: Wed, 8 Jan 2025 15:18:33 +0000 Subject: [PATCH 3/4] mmc: set MMC_QUIRK_KNOWN_WORKING_SD_CQ on Raspberry Pi class A2 cards These cards have a known-good CQ implementation and are based on a Longsys product. Add the MANFID for Longsys SD, and the particular CID details for the Pi card. Signed-off-by: Jonathan Bell --- drivers/mmc/core/card.h | 1 + drivers/mmc/core/quirks.h | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h index 950e21238bcf2e..273bdb5b49b8f3 100644 --- a/drivers/mmc/core/card.h +++ b/drivers/mmc/core/card.h @@ -93,6 +93,7 @@ struct mmc_fixup { #define CID_MANFID_KINGSTON 0x70 #define CID_MANFID_HYNIX 0x90 #define CID_MANFID_KINGSTON_SD 0x9F +#define CID_MANFID_LONGSYS_SD 0xAD #define CID_MANFID_NUMONYX 0xFE #define END_FIXUP { NULL } diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h index 0cbcc8bda05f37..9f8f5e121bc3fc 100644 --- a/drivers/mmc/core/quirks.h +++ b/drivers/mmc/core/quirks.h @@ -66,6 +66,12 @@ static const struct mmc_fixup __maybe_unused mmc_sd_fixups[] = { 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY), + /* SD A2 allow-list - only trust CQ on these cards */ + /* Raspberry Pi A2 cards */ + _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_LONGSYS_SD, 0x4c53, CID_YEAR_ANY, CID_MONTH_ANY, + cid_rev(1, 0, 0, 0), -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, + MMC_QUIRK_WORKING_SD_CQ, EXT_CSD_REV_ANY), + END_FIXUP }; From a4d15819f212daccc7a852250524c98f347a303a Mon Sep 17 00:00:00 2001 From: Jonathan Bell Date: Wed, 8 Jan 2025 16:02:27 +0000 Subject: [PATCH 4/4] mmc: use downstream DT property to modify CQE and/or SD CQ behaviour Implement a tristate-style option for "supports-cqe". If the property is absent or zero, disable CQ completely. For 1, enable CQ unconditionally for eMMC cards, and known-good SD cards. For 2, enable for eMMC cards, and all SD cards that are not known-bad. The sdhci-brcmstb driver needs to know about the tristate as its probe sequence would otherwise override a disable in mmc_of_parse(). Signed-off-by: Jonathan Bell --- drivers/mmc/core/host.c | 11 ++++++++++- drivers/mmc/core/sd.c | 4 ++-- drivers/mmc/host/sdhci-brcmstb.c | 6 ++++-- include/linux/mmc/host.h | 1 + 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 48bda70145ee68..018b77ade4c690 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -272,7 +272,7 @@ EXPORT_SYMBOL(mmc_of_parse_clk_phase); int mmc_of_parse(struct mmc_host *host) { struct device *dev = host->parent; - u32 bus_width, drv_type, cd_debounce_delay_ms; + u32 bus_width, drv_type, cd_debounce_delay_ms, cq_allow; int ret; if (!dev || !dev_fwnode(dev)) @@ -407,6 +407,15 @@ int mmc_of_parse(struct mmc_host *host) host->caps2 &= ~(MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V | MMC_CAP2_HS400_ES); + cq_allow = 0; + /* + * Downstream property - if a u32 and 2 instead of a bool, + * trust most A2 SD cards claiming CQ support. + */ + device_property_read_u32(dev, "supports-cqe", &cq_allow); + if (cq_allow == 2) + host->caps2 |= MMC_CAP2_SD_CQE_PERMISSIVE; + /* Must be after "non-removable" check */ if (device_property_read_u32(dev, "fixed-emmc-driver-type", &drv_type) == 0) { if (host->caps & MMC_CAP_NONREMOVABLE) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index ece494e6c078a8..ea42fa2ef4a6e8 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1501,8 +1501,8 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, goto free_card; } - /* Disallow command queueing on unvetted cards */ - if (!mmc_card_working_sd_cq(card)) + /* Disallow command queueing on unvetted cards unless overridden */ + if (!(host->caps2 & MMC_CAP2_SD_CQE_PERMISSIVE) && !mmc_card_working_sd_cq(card)) card->ext_csd.cmdq_support = false; /* Enable command queueing if supported */ diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index 9743d6cf921b85..1f267c9336d467 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -571,7 +571,7 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) struct sdhci_pltfm_host *pltfm_host; const struct of_device_id *match; struct sdhci_brcmstb_priv *priv; - u32 actual_clock_mhz; + u32 actual_clock_mhz, cqe; struct sdhci_host *host; struct resource *iomem; bool no_pinctrl = false; @@ -600,7 +600,9 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) pltfm_host->clk = clk; priv = sdhci_pltfm_priv(pltfm_host); - if (device_property_read_bool(&pdev->dev, "supports-cqe")) { + cqe = 0; + device_property_read_u32(&pdev->dev, "supports-cqe", &cqe); + if (cqe > 0) { priv->flags |= BRCMSTB_PRIV_FLAGS_HAS_CQE; match_priv->ops->irq = sdhci_brcmstb_cqhci_irq; } diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 8fc2b328ec4d19..b89232b091b63a 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -404,6 +404,7 @@ struct mmc_host { #define MMC_CAP2_CRYPTO 0 #endif #define MMC_CAP2_ALT_GPT_TEGRA (1 << 28) /* Host with eMMC that has GPT entry at a non-standard location */ +#define MMC_CAP2_SD_CQE_PERMISSIVE (1 << 31) /* Ignore allow-list for CQ capable SD card detection */ int fixed_drv_type; /* fixed driver type for non-removable media */