diff options
author | Eric Biggers <ebiggers@google.com> | 2021-01-25 16:14:52 -0800 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2021-02-01 12:02:33 +0100 |
commit | 0a0c866f377ebea6ed5b65942cf1269651c21072 (patch) | |
tree | 60dbfb78ab0daffb006653703625d1d3bd1abf5b /drivers/mmc/host/cqhci-crypto.c | |
parent | 1e80709bdbfc1e1f3cac0ba8ed9a58f5789bcf51 (diff) | |
download | linux-0a0c866f377ebea6ed5b65942cf1269651c21072.tar.gz |
mmc: cqhci: add cqhci_host_ops::program_key
On Snapdragon SoCs, the Linux kernel isn't permitted to directly access
the standard CQHCI crypto configuration registers. Instead, programming
and evicting keys must be done through vendor-specific SMC calls.
To support this hardware, add a ->program_key() method to
'struct cqhci_host_ops'. This allows overriding the standard CQHCI
crypto key programming / eviction procedure.
This is inspired by the corresponding UFS crypto support, which uses
these same SMC calls. See commit 1bc726e26ef3 ("scsi: ufs: Add
program_key() variant op").
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Satya Tangirala <satyat@google.com>
Reviewed-and-tested-by: Peng Zhou <peng.zhou@mediatek.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
Link: https://lore.kernel.org/r/20210126001456.382989-6-ebiggers@kernel.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc/host/cqhci-crypto.c')
-rw-r--r-- | drivers/mmc/host/cqhci-crypto.c | 22 |
1 files changed, 13 insertions, 9 deletions
diff --git a/drivers/mmc/host/cqhci-crypto.c b/drivers/mmc/host/cqhci-crypto.c index 0e2a9dcac630..6419cfbb4ab7 100644 --- a/drivers/mmc/host/cqhci-crypto.c +++ b/drivers/mmc/host/cqhci-crypto.c @@ -30,13 +30,16 @@ cqhci_host_from_ksm(struct blk_keyslot_manager *ksm) return mmc->cqe_private; } -static void cqhci_crypto_program_key(struct cqhci_host *cq_host, - const union cqhci_crypto_cfg_entry *cfg, - int slot) +static int cqhci_crypto_program_key(struct cqhci_host *cq_host, + const union cqhci_crypto_cfg_entry *cfg, + int slot) { u32 slot_offset = cq_host->crypto_cfg_register + slot * sizeof(*cfg); int i; + if (cq_host->ops->program_key) + return cq_host->ops->program_key(cq_host, cfg, slot); + /* Clear CFGE */ cqhci_writel(cq_host, 0, slot_offset + 16 * sizeof(cfg->reg_val[0])); @@ -51,6 +54,7 @@ static void cqhci_crypto_program_key(struct cqhci_host *cq_host, /* Write dword 16, which includes the new value of CFGE */ cqhci_writel(cq_host, le32_to_cpu(cfg->reg_val[16]), slot_offset + 16 * sizeof(cfg->reg_val[0])); + return 0; } static int cqhci_crypto_keyslot_program(struct blk_keyslot_manager *ksm, @@ -67,6 +71,7 @@ static int cqhci_crypto_keyslot_program(struct blk_keyslot_manager *ksm, int i; int cap_idx = -1; union cqhci_crypto_cfg_entry cfg = {}; + int err; BUILD_BUG_ON(CQHCI_CRYPTO_KEY_SIZE_INVALID != 0); for (i = 0; i < cq_host->crypto_capabilities.num_crypto_cap; i++) { @@ -93,13 +98,13 @@ static int cqhci_crypto_keyslot_program(struct blk_keyslot_manager *ksm, memcpy(cfg.crypto_key, key->raw, key->size); } - cqhci_crypto_program_key(cq_host, &cfg, slot); + err = cqhci_crypto_program_key(cq_host, &cfg, slot); memzero_explicit(&cfg, sizeof(cfg)); - return 0; + return err; } -static void cqhci_crypto_clear_keyslot(struct cqhci_host *cq_host, int slot) +static int cqhci_crypto_clear_keyslot(struct cqhci_host *cq_host, int slot) { /* * Clear the crypto cfg on the device. Clearing CFGE @@ -107,7 +112,7 @@ static void cqhci_crypto_clear_keyslot(struct cqhci_host *cq_host, int slot) */ union cqhci_crypto_cfg_entry cfg = {}; - cqhci_crypto_program_key(cq_host, &cfg, slot); + return cqhci_crypto_program_key(cq_host, &cfg, slot); } static int cqhci_crypto_keyslot_evict(struct blk_keyslot_manager *ksm, @@ -116,8 +121,7 @@ static int cqhci_crypto_keyslot_evict(struct blk_keyslot_manager *ksm, { struct cqhci_host *cq_host = cqhci_host_from_ksm(ksm); - cqhci_crypto_clear_keyslot(cq_host, slot); - return 0; + return cqhci_crypto_clear_keyslot(cq_host, slot); } /* |