From: Md Sadre Alam Date: Wed, 26 Nov 2025 06:42:51 +0000 (+0530) Subject: mmc: sdhci-msm: Enable ICE for CQE-capable controllers with non-CQE cards X-Git-Tag: v7.1-rc1~157^2~124 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3d9ce86b52b7b328f5662436904789942a5eca1f;p=thirdparty%2Fkernel%2Fstable.git mmc: sdhci-msm: Enable ICE for CQE-capable controllers with non-CQE cards Enable Inline Crypto Engine (ICE) support for CQE-capable sdhci-msm controllers when used with eMMC cards that do not support CQE. This addresses the scenario where: - The host controller supports CQE (and has CQHCI crypto infrastructure) - The eMMC card does not support CQE - Standard (non-CMDQ) requests need crypto support This allows hardware-accelerated encryption and decryption for standard requests on CQE-capable hardware by utilizing the existing CQHCI crypto register space even when CQE functionality is not available due to card limitations. The implementation: - Adds ICE register definitions for non-CQE crypto configuration - Implements per-request crypto setup via sdhci_msm_ice_cfg() - Hooks into the request path via mmc_host_ops.request for non-CQE requests - Uses CQHCI register space (NONCQ_CRYPTO_PARM/DUN) for crypto configuration With this, CQE-capable controllers can benefit from inline encryption when paired with non-CQE cards, improving performance for encrypted I/O while maintaining compatibility with existing CQE crypto support. Signed-off-by: Md Sadre Alam Acked-by: Adrian Hunter Acked-by: Eric Biggers Signed-off-by: Ulf Hansson --- diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 3b85233131b38..da356627d9de6 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -157,6 +157,17 @@ #define CQHCI_VENDOR_CFG1 0xA00 #define CQHCI_VENDOR_DIS_RST_ON_CQ_EN (0x3 << 13) +/* non command queue crypto enable register*/ +#define NONCQ_CRYPTO_PARM 0x70 +#define NONCQ_CRYPTO_DUN 0x74 + +#define DISABLE_CRYPTO BIT(15) +#define CRYPTO_GENERAL_ENABLE BIT(1) +#define HC_VENDOR_SPECIFIC_FUNC4 0x260 + +#define ICE_HCI_PARAM_CCI GENMASK(7, 0) +#define ICE_HCI_PARAM_CE GENMASK(8, 8) + struct sdhci_msm_offset { u32 core_hc_mode; u32 core_mci_data_cnt; @@ -300,6 +311,7 @@ struct sdhci_msm_host { u32 dll_config; u32 ddr_config; bool vqmmc_enabled; + bool non_cqe_ice_init_done; }; static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host) @@ -2012,6 +2024,68 @@ static int sdhci_msm_ice_keyslot_evict(struct blk_crypto_profile *profile, return qcom_ice_evict_key(msm_host->ice, slot); } +static void sdhci_msm_non_cqe_ice_init(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); + struct mmc_host *mmc = msm_host->mmc; + struct cqhci_host *cq_host = mmc->cqe_private; + u32 config; + + config = sdhci_readl(host, HC_VENDOR_SPECIFIC_FUNC4); + config &= ~DISABLE_CRYPTO; + sdhci_writel(host, config, HC_VENDOR_SPECIFIC_FUNC4); + config = cqhci_readl(cq_host, CQHCI_CFG); + config |= CRYPTO_GENERAL_ENABLE; + cqhci_writel(cq_host, config, CQHCI_CFG); +} + +static void sdhci_msm_ice_cfg(struct sdhci_host *host, struct mmc_request *mrq) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); + struct mmc_host *mmc = msm_host->mmc; + struct cqhci_host *cq_host = mmc->cqe_private; + unsigned int crypto_params = 0; + int key_index; + + if (mrq->crypto_ctx) { + if (!msm_host->non_cqe_ice_init_done) { + sdhci_msm_non_cqe_ice_init(host); + msm_host->non_cqe_ice_init_done = true; + } + + key_index = mrq->crypto_key_slot; + crypto_params = FIELD_PREP(ICE_HCI_PARAM_CE, 1) | + FIELD_PREP(ICE_HCI_PARAM_CCI, key_index); + + cqhci_writel(cq_host, crypto_params, NONCQ_CRYPTO_PARM); + cqhci_writel(cq_host, lower_32_bits(mrq->crypto_ctx->bc_dun[0]), + NONCQ_CRYPTO_DUN); + } else { + cqhci_writel(cq_host, crypto_params, NONCQ_CRYPTO_PARM); + } + + /* Ensure crypto configuration is written before proceeding */ + wmb(); +} + +/* + * Handle non-CQE MMC requests with ICE crypto support. + * Configures ICE registers before passing the request to + * the standard SDHCI handler. + */ +static void sdhci_msm_request(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct sdhci_host *host = mmc_priv(mmc); + + /* Only need to handle non-CQE crypto requests in this path */ + if (mmc->caps2 & MMC_CAP2_CRYPTO) + sdhci_msm_ice_cfg(host, mrq); + + sdhci_request(mmc, mrq); +} + static const struct blk_crypto_ll_ops sdhci_msm_crypto_ops = { .keyslot_program = sdhci_msm_ice_keyslot_program, .keyslot_evict = sdhci_msm_ice_keyslot_evict, @@ -2762,6 +2836,9 @@ static int sdhci_msm_probe(struct platform_device *pdev) msm_host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_NEED_RSP_BUSY; +#ifdef CONFIG_MMC_CRYPTO + host->mmc_host_ops.request = sdhci_msm_request; +#endif /* Set the timeout value to max possible */ host->max_timeout_count = 0xF;