diff options
author | Eric Biggers <ebiggers@google.com> | 2024-12-12 20:19:46 -0800 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2025-01-02 13:36:15 -0500 |
commit | 30b32c647cf309d8fc70ba068a2918033e3a1bc4 (patch) | |
tree | 8104fcedeb6f45c0420abbe864ca070bf055b241 | |
parent | 75d0c649eca47af21533d9636723574116fe6987 (diff) |
scsi: ufs: qcom: Convert to use UFSHCD_QUIRK_CUSTOM_CRYPTO_PROFILE
By default the UFS core is responsible for initializing the
blk_crypto_profile, but Qualcomm platforms have their own way of
programming and evicting crypto keys. So currently
ufs_hba_variant_ops::program_key is used to redirect control flow from
ufshcd_program_key(). This has worked until now, but it's a bit of a hack,
given that the key (and algorithm ID etc.) ends up being converted from
blk_crypto_key => ufs_crypto_cfg_entry => SCM call parameters, where the
intermediate ufs_crypto_cfg_entry step is unnecessary. Taking a similar
approach with the upcoming wrapped key support, the implementation of which
is similarly platform-specific, would require adding four new methods to
ufs_hba_variant_ops, changing program_key to take the struct
blk_crypto_key, and adding a new UFSHCD_CAP_* flag to indicate support for
wrapped keys.
This patch takes a different approach. It changes ufs-qcom to use the
existing UFSHCD_QUIRK_CUSTOM_CRYPTO_PROFILE which was recently added for
ufs-exynos. This allows it to override the full blk_crypto_profile,
eliminating the need for the existing ufs_hba_variant_ops::program_key and
the hooks that would have been needed for wrapped key support. It does
require a bit of duplicated code to read the crypto capability registers,
but it's worth the simplification in design with ufs-qcom and ufs-exynos
now using the same method to customize the crypto profile, and it makes it
much easier to add wrapped key support.
Tested-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> # sm8650
Signed-off-by: Eric Biggers <ebiggers@google.com>
Link: https://lore.kernel.org/r/20241213041958.202565-4-ebiggers@kernel.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r-- | drivers/ufs/host/ufs-qcom.c | 91 |
1 files changed, 72 insertions, 19 deletions
diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 65487839ed98..eae8dfb8c91e 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -112,11 +112,18 @@ static inline void ufs_qcom_ice_enable(struct ufs_qcom_host *host) qcom_ice_enable(host->ice); } +static const struct blk_crypto_ll_ops ufs_qcom_crypto_ops; /* forward decl */ + static int ufs_qcom_ice_init(struct ufs_qcom_host *host) { struct ufs_hba *hba = host->hba; + struct blk_crypto_profile *profile = &hba->crypto_profile; struct device *dev = hba->dev; struct qcom_ice *ice; + union ufs_crypto_capabilities caps; + union ufs_crypto_cap_entry cap; + int err; + int i; ice = of_qcom_ice_get(dev); if (ice == ERR_PTR(-EOPNOTSUPP)) { @@ -128,8 +135,38 @@ static int ufs_qcom_ice_init(struct ufs_qcom_host *host) return PTR_ERR_OR_ZERO(ice); host->ice = ice; - hba->caps |= UFSHCD_CAP_CRYPTO; + /* Initialize the blk_crypto_profile */ + + caps.reg_val = cpu_to_le32(ufshcd_readl(hba, REG_UFS_CCAP)); + + /* The number of keyslots supported is (CFGC+1) */ + err = devm_blk_crypto_profile_init(dev, profile, caps.config_count + 1); + if (err) + return err; + + profile->ll_ops = ufs_qcom_crypto_ops; + profile->max_dun_bytes_supported = 8; + profile->dev = dev; + + /* + * Currently this driver only supports AES-256-XTS. All known versions + * of ICE support it, but to be safe make sure it is really declared in + * the crypto capability registers. The crypto capability registers + * also give the supported data unit size(s). + */ + for (i = 0; i < caps.num_crypto_cap; i++) { + cap.reg_val = cpu_to_le32(ufshcd_readl(hba, + REG_UFS_CRYPTOCAP + + i * sizeof(__le32))); + if (cap.algorithm_id == UFS_CRYPTO_ALG_AES_XTS && + cap.key_size == UFS_CRYPTO_KEY_SIZE_256) + profile->modes_supported[BLK_ENCRYPTION_MODE_AES_256_XTS] |= + cap.sdus_mask * 512; + } + + hba->caps |= UFSHCD_CAP_CRYPTO; + hba->quirks |= UFSHCD_QUIRK_CUSTOM_CRYPTO_PROFILE; return 0; } @@ -149,32 +186,49 @@ static inline int ufs_qcom_ice_suspend(struct ufs_qcom_host *host) return 0; } -static int ufs_qcom_ice_program_key(struct ufs_hba *hba, - const union ufs_crypto_cfg_entry *cfg, - int slot) +static int ufs_qcom_ice_keyslot_program(struct blk_crypto_profile *profile, + const struct blk_crypto_key *key, + unsigned int slot) { + struct ufs_hba *hba = ufs_hba_from_crypto_profile(profile); struct ufs_qcom_host *host = ufshcd_get_variant(hba); - union ufs_crypto_cap_entry cap; - - if (!(cfg->config_enable & UFS_CRYPTO_CONFIGURATION_ENABLE)) - return qcom_ice_evict_key(host->ice, slot); + int err; /* Only AES-256-XTS has been tested so far. */ - cap = hba->crypto_cap_array[cfg->crypto_cap_idx]; - if (cap.algorithm_id != UFS_CRYPTO_ALG_AES_XTS || - cap.key_size != UFS_CRYPTO_KEY_SIZE_256) + if (key->crypto_cfg.crypto_mode != BLK_ENCRYPTION_MODE_AES_256_XTS) return -EOPNOTSUPP; - return qcom_ice_program_key(host->ice, - QCOM_ICE_CRYPTO_ALG_AES_XTS, - QCOM_ICE_CRYPTO_KEY_SIZE_256, - cfg->crypto_key, - cfg->data_unit_size, slot); + ufshcd_hold(hba); + err = qcom_ice_program_key(host->ice, + QCOM_ICE_CRYPTO_ALG_AES_XTS, + QCOM_ICE_CRYPTO_KEY_SIZE_256, + key->raw, + key->crypto_cfg.data_unit_size / 512, + slot); + ufshcd_release(hba); + return err; } -#else +static int ufs_qcom_ice_keyslot_evict(struct blk_crypto_profile *profile, + const struct blk_crypto_key *key, + unsigned int slot) +{ + struct ufs_hba *hba = ufs_hba_from_crypto_profile(profile); + struct ufs_qcom_host *host = ufshcd_get_variant(hba); + int err; + + ufshcd_hold(hba); + err = qcom_ice_evict_key(host->ice, slot); + ufshcd_release(hba); + return err; +} -#define ufs_qcom_ice_program_key NULL +static const struct blk_crypto_ll_ops ufs_qcom_crypto_ops = { + .keyslot_program = ufs_qcom_ice_keyslot_program, + .keyslot_evict = ufs_qcom_ice_keyslot_evict, +}; + +#else static inline void ufs_qcom_ice_enable(struct ufs_qcom_host *host) { @@ -1822,7 +1876,6 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = { .dbg_register_dump = ufs_qcom_dump_dbg_regs, .device_reset = ufs_qcom_device_reset, .config_scaling_param = ufs_qcom_config_scaling_param, - .program_key = ufs_qcom_ice_program_key, .reinit_notify = ufs_qcom_reinit_notify, .mcq_config_resource = ufs_qcom_mcq_config_resource, .get_hba_mac = ufs_qcom_get_hba_mac, |