From b692edb8f2b01e90a904f2917032945b355b69df Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 8 Jul 2024 16:53:28 -0700 Subject: [PATCH] BACKPORT: scsi: ufs: core: Add fill_crypto_prdt variant op Add a variant op to allow host drivers to initialize nonstandard crypto-related fields in the PRDT. This is needed to support inline encryption on the "Exynos" UFS controller. Note that this will be used together with the support for overriding the PRDT entry size that was already added by commit ada1e653a5ea ("scsi: ufs: core: Allow UFS host drivers to override the sg entry size"). Reviewed-by: Bart Van Assche Reviewed-by: Peter Griffin Signed-off-by: Eric Biggers Link: https://lore.kernel.org/r/20240708235330.103590-5-ebiggers@kernel.org Reviewed-by: Alim Akhtar Signed-off-by: Martin K. Petersen Bug: 162257402 (cherry picked from commit 8ecea3da1567e0648b5d37a6faec73fc9c8571ba) (For now, kept the vendor hook alongside the new variant op.) Change-Id: Ib529babb1f6a5ae5a28af5104e3355772cc2accf Signed-off-by: Eric Biggers --- drivers/ufs/core/ufshcd-crypto.h | 19 +++++++++++++++++++ drivers/ufs/core/ufshcd.c | 9 ++++++++- include/ufs/ufshcd.h | 4 ++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/ufs/core/ufshcd-crypto.h b/drivers/ufs/core/ufshcd-crypto.h index be8596f20ba2..3eb8df42e194 100644 --- a/drivers/ufs/core/ufshcd-crypto.h +++ b/drivers/ufs/core/ufshcd-crypto.h @@ -37,6 +37,19 @@ ufshcd_prepare_req_desc_hdr_crypto(struct ufshcd_lrb *lrbp, h->dunu = cpu_to_le32(upper_32_bits(lrbp->data_unit_num)); } +static inline int ufshcd_crypto_fill_prdt(struct ufs_hba *hba, + struct ufshcd_lrb *lrbp) +{ + struct scsi_cmnd *cmd = lrbp->cmd; + const struct bio_crypt_ctx *crypt_ctx = scsi_cmd_to_rq(cmd)->crypt_ctx; + + if (crypt_ctx && hba->vops && hba->vops->fill_crypto_prdt) + return hba->vops->fill_crypto_prdt(hba, crypt_ctx, + lrbp->ucd_prdt_ptr, + scsi_sg_count(cmd)); + return 0; +} + bool ufshcd_crypto_enable(struct ufs_hba *hba); int ufshcd_hba_init_crypto_capabilities(struct ufs_hba *hba); @@ -54,6 +67,12 @@ static inline void ufshcd_prepare_req_desc_hdr_crypto(struct ufshcd_lrb *lrbp, struct request_desc_header *h) { } +static inline int ufshcd_crypto_fill_prdt(struct ufs_hba *hba, + struct ufshcd_lrb *lrbp) +{ + return 0; +} + static inline bool ufshcd_crypto_enable(struct ufs_hba *hba) { return false; diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 3c7dca8cc471..3ee842f5cf18 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -2645,9 +2645,16 @@ static int ufshcd_map_sg(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) ufshcd_sgl_to_prdt(hba, lrbp, sg_segments, scsi_sglist(cmd)); + /* + * TODO(b/160883801): remove this vendor hook in favor of the upstream + * variant op. This isn't possible yet because the upstream variant op + * doesn't yet make it possible for the host driver to get the keyslot. + */ err = 0; trace_android_vh_ufs_fill_prdt(hba, lrbp, sg_segments, &err); - return err; + if (err) + return err; + return ufshcd_crypto_fill_prdt(hba, lrbp); } /** diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index 8806a1c2c980..12d790fb07c6 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -321,6 +321,7 @@ struct ufs_pwr_mode_info { * @device_reset: called to issue a reset pulse on the UFS device * @config_scaling_param: called to configure clock scaling parameters * @program_key: program or evict an inline encryption key + * @fill_crypto_prdt: initialize crypto-related fields in the PRDT * @event_notify: called to notify important events * @reinit_notify: called to notify reinit of UFSHCD during max gear switch * @mcq_config_resource: called to configure MCQ platform resources @@ -365,6 +366,9 @@ struct ufs_hba_variant_ops { struct devfreq_simple_ondemand_data *data); int (*program_key)(struct ufs_hba *hba, const union ufs_crypto_cfg_entry *cfg, int slot); + int (*fill_crypto_prdt)(struct ufs_hba *hba, + const struct bio_crypt_ctx *crypt_ctx, + void *prdt, unsigned int num_segments); void (*event_notify)(struct ufs_hba *hba, enum ufs_event_type evt, void *data); void (*reinit_notify)(struct ufs_hba *);