diff --git a/drivers/scsi/ufs/ufshcd-crypto.h b/drivers/scsi/ufs/ufshcd-crypto.h index d53851be5541..b75d8ca12a6f 100644 --- a/drivers/scsi/ufs/ufshcd-crypto.h +++ b/drivers/scsi/ufs/ufshcd-crypto.h @@ -34,6 +34,19 @@ ufshcd_prepare_req_desc_hdr_crypto(struct ufshcd_lrb *lrbp, u32 *dword_0, } } +static inline void ufshcd_crypto_clear_prdt(struct ufs_hba *hba, + struct ufshcd_lrb *lrbp) +{ + if (!(hba->quirks & UFSHCD_QUIRK_KEYS_IN_PRDT)) + return; + + if (!lrbp->cmd->request->crypt_ctx) + return; + + memzero_explicit(lrbp->ucd_prdt_ptr, + hba->sg_entry_size * scsi_sg_count(lrbp->cmd)); +} + bool ufshcd_crypto_enable(struct ufs_hba *hba); int ufshcd_hba_init_crypto_capabilities(struct ufs_hba *hba); @@ -54,6 +67,9 @@ static inline void ufshcd_prepare_req_desc_hdr_crypto(struct ufshcd_lrb *lrbp, u32 *dword_0, u32 *dword_1, u32 *dword_3) { } +static inline void ufshcd_crypto_clear_prdt(struct ufs_hba *hba, + struct ufshcd_lrb *lrbp) { } + static inline bool ufshcd_crypto_enable(struct ufs_hba *hba) { return false; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 9f96ce9d9ee2..7af9c246965a 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -4927,6 +4927,7 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, result = ufshcd_transfer_rsp_status(hba, lrbp); scsi_dma_unmap(cmd); cmd->result = result; + ufshcd_crypto_clear_prdt(hba, lrbp); /* Mark completed command as NULL in LRB */ lrbp->cmd = NULL; /* Do not touch lrbp after scsi done */ diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 6a2d38124fb0..43c4d73eee64 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -539,6 +539,13 @@ enum ufshcd_quirks { * a passthrough keyslot manager. */ UFSHCD_QUIRK_NO_KEYSLOTS = 1 << 12, + + /* + * 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, }; enum ufshcd_caps {