From 74e7fc049218b7482696c7d8418ada05986ed9f6 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 29 Sep 2020 11:01:15 -0700 Subject: [PATCH] ANDROID: scsi: ufs: split up UFSHCD_QUIRK_NO_KEYSLOTS UFSHCD_QUIRK_NO_KEYSLOTS does several different things: 1. Skip writing CRYPTO_GENERAL_ENABLE to REG_CONTROLLER_ENABLE. 2. Skip initializing the keyslot manager via the standard UFS crypto capability registers. 3. Skip clearing and re-programming all keyslots. The current use case for this is FMP, which needs all these behaviors. However, some new hardware will still need behaviors (1) and (2), but will no longer need (3) since the hardware will have keyslots. To support this hardware, split up UFSHCD_QUIRK_NO_KEYSLOTS as follows: 1. UFSHCD_QUIRK_BROKEN_CRYPTO_ENABLE 2. UFSHCD_QUIRK_BROKEN_CRYPTO_CAPS 3. No quirk bit; just use hba->ksm.num_slots. Also adjust the crypto quirk bits to start at (1 << 20) to avoid collisions with backports from upstream. Bug: 166139333 Bug: 162257402 Change-Id: I1e740f7ce0db7a1bafada0eb73343cd04966fee0 Signed-off-by: Eric Biggers --- drivers/scsi/ufs/ufshcd-crypto.c | 17 ++++++++--------- drivers/scsi/ufs/ufshcd.h | 18 ++++++++++++------ 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd-crypto.c b/drivers/scsi/ufs/ufshcd-crypto.c index 4a7b7a411fd4..f6f51e9bdfe5 100644 --- a/drivers/scsi/ufs/ufshcd-crypto.c +++ b/drivers/scsi/ufs/ufshcd-crypto.c @@ -119,11 +119,13 @@ bool ufshcd_crypto_enable(struct ufs_hba *hba) if (!(hba->caps & UFSHCD_CAP_CRYPTO)) return false; - if (hba->quirks & UFSHCD_QUIRK_NO_KEYSLOTS) + /* Reset might clear all keys, so reprogram all the keys. */ + if (hba->ksm.num_slots) + blk_ksm_reprogram_all_keys(&hba->ksm); + + if (hba->quirks & UFSHCD_QUIRK_BROKEN_CRYPTO_ENABLE) return false; - /* Reset might clear all keys, so reprogram all the keys. */ - blk_ksm_reprogram_all_keys(&hba->ksm); return true; } @@ -160,7 +162,7 @@ int ufshcd_hba_init_crypto_capabilities(struct ufs_hba *hba) int err = 0; enum blk_crypto_mode_num blk_mode_num; - if (hba->quirks & UFSHCD_QUIRK_NO_KEYSLOTS) + if (hba->quirks & UFSHCD_QUIRK_BROKEN_CRYPTO_CAPS) return 0; /* @@ -234,11 +236,8 @@ void ufshcd_init_crypto(struct ufs_hba *hba) if (!(hba->caps & UFSHCD_CAP_CRYPTO)) return; - if (hba->quirks & UFSHCD_QUIRK_NO_KEYSLOTS) - return; - - /* Clear all keyslots - the number of keyslots is (CFGC + 1) */ - for (slot = 0; slot < hba->crypto_capabilities.config_count + 1; slot++) + /* Clear all keyslots */ + for (slot = 0; slot < hba->ksm.num_slots; slot++) ufshcd_clear_keyslot(hba, slot); } diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 6497799213a1..90e5a3307993 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -547,19 +547,25 @@ enum ufshcd_quirks { /* * This quirk needs to be enabled if the host controller supports inline - * encryption, but it uses a nonstandard mechanism where the standard - * crypto registers aren't used and there is no concept of keyslots. - * ufs_hba_variant_ops::init() is expected to initialize ufs_hba::ksm as - * a passthrough keyslot manager. + * encryption, but it doesn't use the standard crypto capability + * registers. If enabled, the standard code won't initialize the + * keyslot manager; ufs_hba_variant_ops::init() must do it instead. */ - UFSHCD_QUIRK_NO_KEYSLOTS = 1 << 12, + UFSHCD_QUIRK_BROKEN_CRYPTO_CAPS = 1 << 20, + + /* + * This quirk needs to be enabled if the host controller supports inline + * encryption, but the CRYPTO_GENERAL_ENABLE bit is not implemented and + * breaks the HCE sequence if used. + */ + UFSHCD_QUIRK_BROKEN_CRYPTO_ENABLE = 1 << 21, /* * This quirk needs to be enabled if the host controller requires that * the PRDT be cleared after each encrypted request because encryption * keys were stored in it. */ - UFSHCD_QUIRK_KEYS_IN_PRDT = 1 << 13, + UFSHCD_QUIRK_KEYS_IN_PRDT = 1 << 22, }; enum ufshcd_caps {