Skip to content

Commit

Permalink
scsi: ufs: Add program_key() variant op
Browse files Browse the repository at this point in the history
On Snapdragon SoCs, the Linux kernel isn't permitted to directly access the
standard UFS 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
ufs_hba_variant_ops'.  This allows overriding the UFS standard key
programming / eviction procedure.

Link: https://lore.kernel.org/r/20200710072013.177481-5-ebiggers@kernel.org
Reviewed-by: Avri Altman <avri.altman@wdc.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
  • Loading branch information
Eric Biggers authored and Martin K. Petersen committed Jul 25, 2020
1 parent 083dd78 commit 1bc726e
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 10 deletions.
27 changes: 17 additions & 10 deletions drivers/scsi/ufs/ufshcd-crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,20 @@ static const struct ufs_crypto_alg_entry {
},
};

static void ufshcd_program_key(struct ufs_hba *hba,
const union ufs_crypto_cfg_entry *cfg,
int slot)
static int ufshcd_program_key(struct ufs_hba *hba,
const union ufs_crypto_cfg_entry *cfg, int slot)
{
int i;
u32 slot_offset = hba->crypto_cfg_register + slot * sizeof(*cfg);
int err = 0;

ufshcd_hold(hba, false);

if (hba->vops && hba->vops->program_key) {
err = hba->vops->program_key(hba, cfg, slot);
goto out;
}

/* Ensure that CFGE is cleared before programming the key */
ufshcd_writel(hba, 0, slot_offset + 16 * sizeof(cfg->reg_val[0]));
for (i = 0; i < 16; i++) {
Expand All @@ -37,7 +43,9 @@ static void ufshcd_program_key(struct ufs_hba *hba,
/* Dword 16 must be written last */
ufshcd_writel(hba, le32_to_cpu(cfg->reg_val[16]),
slot_offset + 16 * sizeof(cfg->reg_val[0]));
out:
ufshcd_release(hba);
return err;
}

static int ufshcd_crypto_keyslot_program(struct blk_keyslot_manager *ksm,
Expand All @@ -52,6 +60,7 @@ static int ufshcd_crypto_keyslot_program(struct blk_keyslot_manager *ksm,
int i;
int cap_idx = -1;
union ufs_crypto_cfg_entry cfg = { 0 };
int err;

BUILD_BUG_ON(UFS_CRYPTO_KEY_SIZE_INVALID != 0);
for (i = 0; i < hba->crypto_capabilities.num_crypto_cap; i++) {
Expand Down Expand Up @@ -79,21 +88,21 @@ static int ufshcd_crypto_keyslot_program(struct blk_keyslot_manager *ksm,
memcpy(cfg.crypto_key, key->raw, key->size);
}

ufshcd_program_key(hba, &cfg, slot);
err = ufshcd_program_key(hba, &cfg, slot);

memzero_explicit(&cfg, sizeof(cfg));
return 0;
return err;
}

static void ufshcd_clear_keyslot(struct ufs_hba *hba, int slot)
static int ufshcd_clear_keyslot(struct ufs_hba *hba, int slot)
{
/*
* Clear the crypto cfg on the device. Clearing CFGE
* might not be sufficient, so just clear the entire cfg.
*/
union ufs_crypto_cfg_entry cfg = { 0 };

ufshcd_program_key(hba, &cfg, slot);
return ufshcd_program_key(hba, &cfg, slot);
}

static int ufshcd_crypto_keyslot_evict(struct blk_keyslot_manager *ksm,
Expand All @@ -102,9 +111,7 @@ static int ufshcd_crypto_keyslot_evict(struct blk_keyslot_manager *ksm,
{
struct ufs_hba *hba = container_of(ksm, struct ufs_hba, ksm);

ufshcd_clear_keyslot(hba, slot);

return 0;
return ufshcd_clear_keyslot(hba, slot);
}

bool ufshcd_crypto_enable(struct ufs_hba *hba)
Expand Down
3 changes: 3 additions & 0 deletions drivers/scsi/ufs/ufshcd.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ struct ufs_pwr_mode_info {
* @dbg_register_dump: used to dump controller debug information
* @phy_initialization: used to initialize phys
* @device_reset: called to issue a reset pulse on the UFS device
* @program_key: program or evict an inline encryption key
*/
struct ufs_hba_variant_ops {
const char *name;
Expand Down Expand Up @@ -314,6 +315,8 @@ struct ufs_hba_variant_ops {
void (*config_scaling_param)(struct ufs_hba *hba,
struct devfreq_dev_profile *profile,
void *data);
int (*program_key)(struct ufs_hba *hba,
const union ufs_crypto_cfg_entry *cfg, int slot);
};

/* clock gating state */
Expand Down

0 comments on commit 1bc726e

Please sign in to comment.