@@ -108,17 +108,25 @@ static int ufshcd_crypto_keyslot_evict(struct blk_crypto_profile *profile,
union ufs_crypto_cfg_entry cfg = {};
return ufshcd_program_key(hba, &cfg, slot);
}
+/*
+ * Reprogram the keyslots if needed, and return true if CRYPTO_GENERAL_ENABLE
+ * should be used in the host controller initialization sequence.
+ */
bool ufshcd_crypto_enable(struct ufs_hba *hba)
{
if (!(hba->caps & UFSHCD_CAP_CRYPTO))
return false;
/* Reset might clear all keys, so reprogram all the keys. */
blk_crypto_reprogram_all_keys(&hba->crypto_profile);
+
+ if (hba->quirks & UFSHCD_QUIRK_BROKEN_CRYPTO_ENABLE)
+ return false;
+
return true;
}
static const struct blk_crypto_ll_ops ufshcd_crypto_ops = {
.keyslot_program = ufshcd_crypto_keyslot_program,
@@ -650,10 +650,17 @@ enum ufshcd_quirks {
* nonstandard way and/or needs to override blk_crypto_ll_ops. If
* enabled, the standard code won't initialize the blk_crypto_profile;
* ufs_hba_variant_ops::init() must do it instead.
*/
UFSHCD_QUIRK_CUSTOM_CRYPTO_PROFILE = 1 << 22,
+
+ /*
+ * This quirk needs to be enabled if the host controller supports inline
+ * encryption but does not support the CRYPTO_GENERAL_ENABLE bit, i.e.
+ * host controller initialization fails if that bit is set.
+ */
+ UFSHCD_QUIRK_BROKEN_CRYPTO_ENABLE = 1 << 23,
};
enum ufshcd_caps {
/* Allow dynamic clk gating */
UFSHCD_CAP_CLK_GATING = 1 << 0,