mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
BACKPORT: FROMGIT: scsi: ufs: core: Allow UFS host drivers to override the sg entry size
Modify the UFSHCD core to allow 'struct ufshcd_sg_entry' to be
variable-length. The default is the standard length, but variants can
override ufs_hba::sg_entry_size with a larger value if there are
vendor-specific fields following the standard ones.
This is needed to support inline encryption with ufs-exynos (FMP).
Cc: Eric Biggers <ebiggers@google.com>
Reviewed-by: Avri Altman <avri.altman@wdc.com>
Change-Id: I4fa3303b0ed70951ea4ec345bb3d58c6a008917d
Signed-off-by: Eric Biggers <ebiggers@google.com>
[ bvanassche: edited commit message and introduced CONFIG_SCSI_UFS_VARIABLE_SG_ENTRY_SIZE ]
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Bug: 258234315
(cherry picked from commit ada1e653a5 git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next)
[ bvanassche: backported this patch to the Android kernel tree ]
Signed-off-by: Bart Van Assche <bvanassche@google.com>
This commit is contained in:
@@ -47,7 +47,7 @@ static inline void ufshcd_crypto_clear_prdt(struct ufs_hba *hba,
|
||||
return;
|
||||
|
||||
memzero_explicit(lrbp->ucd_prdt_ptr,
|
||||
hba->sg_entry_size * scsi_sg_count(lrbp->cmd));
|
||||
ufshcd_sg_entry_size(hba) * scsi_sg_count(lrbp->cmd));
|
||||
}
|
||||
|
||||
bool ufshcd_crypto_enable(struct ufs_hba *hba);
|
||||
|
||||
@@ -538,7 +538,7 @@ void ufshcd_print_trs(struct ufs_hba *hba, unsigned long bitmap, bool pr_prdt)
|
||||
prdt_length = le16_to_cpu(
|
||||
lrbp->utr_descriptor_ptr->prd_table_length);
|
||||
if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN)
|
||||
prdt_length /= hba->sg_entry_size;
|
||||
prdt_length /= ufshcd_sg_entry_size(hba);
|
||||
|
||||
dev_err(hba->dev,
|
||||
"UPIU[%d] - PRDT - %d entries phys@0x%llx\n",
|
||||
@@ -547,7 +547,7 @@ void ufshcd_print_trs(struct ufs_hba *hba, unsigned long bitmap, bool pr_prdt)
|
||||
|
||||
if (pr_prdt)
|
||||
ufshcd_hex_dump("UPIU PRDT: ", lrbp->ucd_prdt_ptr,
|
||||
hba->sg_entry_size * prdt_length);
|
||||
ufshcd_sg_entry_size(hba) * prdt_length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2470,7 +2470,7 @@ static void ufshcd_sgl_to_prdt(struct ufs_hba *hba, struct ufshcd_lrb *lrbp, int
|
||||
|
||||
if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN)
|
||||
lrbp->utr_descriptor_ptr->prd_table_length =
|
||||
cpu_to_le16(sg_entries * hba->sg_entry_size);
|
||||
cpu_to_le16(sg_entries * ufshcd_sg_entry_size(hba));
|
||||
else
|
||||
lrbp->utr_descriptor_ptr->prd_table_length = cpu_to_le16(sg_entries);
|
||||
|
||||
@@ -2491,7 +2491,7 @@ static void ufshcd_sgl_to_prdt(struct ufs_hba *hba, struct ufshcd_lrb *lrbp, int
|
||||
prd->size = cpu_to_le32(len - 1);
|
||||
prd->addr = cpu_to_le64(sg->dma_address);
|
||||
prd->reserved = 0;
|
||||
prd = (void *)prd + hba->sg_entry_size;
|
||||
prd = (void *)prd + ufshcd_sg_entry_size(hba);
|
||||
}
|
||||
} else {
|
||||
lrbp->utr_descriptor_ptr->prd_table_length = 0;
|
||||
@@ -2816,7 +2816,7 @@ static void ufshcd_init_lrb(struct ufs_hba *hba, struct ufshcd_lrb *lrb, int i)
|
||||
lrb->utr_descriptor_ptr = utrdlp + i;
|
||||
lrb->utrd_dma_addr = hba->utrdl_dma_addr +
|
||||
i * sizeof(struct utp_transfer_req_desc);
|
||||
lrb->ucd_req_ptr = (struct utp_upiu_req *)cmd_descp;
|
||||
lrb->ucd_req_ptr = (struct utp_upiu_req *)cmd_descp->command_upiu;
|
||||
lrb->ucd_req_dma_addr = cmd_desc_element_addr;
|
||||
lrb->ucd_rsp_ptr = (struct utp_upiu_rsp *)cmd_descp->response_upiu;
|
||||
lrb->ucd_rsp_dma_addr = cmd_desc_element_addr + response_offset;
|
||||
@@ -3715,7 +3715,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
|
||||
size_t utmrdl_size, utrdl_size, ucdl_size;
|
||||
|
||||
/* Allocate memory for UTP command descriptors */
|
||||
ucdl_size = (sizeof_utp_transfer_cmd_desc(hba) * hba->nutrs);
|
||||
ucdl_size = sizeof_utp_transfer_cmd_desc(hba) * hba->nutrs;
|
||||
hba->ucdl_base_addr = dmam_alloc_coherent(hba->dev,
|
||||
ucdl_size,
|
||||
&hba->ucdl_dma_addr,
|
||||
@@ -9829,7 +9829,7 @@ int ufshcd_alloc_host(struct device *dev, struct ufs_hba **hba_handle)
|
||||
hba->dev = dev;
|
||||
hba->dev_ref_clk_freq = REF_CLK_FREQ_INVAL;
|
||||
hba->nop_out_timeout = NOP_OUT_TIMEOUT;
|
||||
hba->sg_entry_size = sizeof(struct ufshcd_sg_entry);
|
||||
ufshcd_set_sg_entry_size(hba, sizeof(struct ufshcd_sg_entry));
|
||||
INIT_LIST_HEAD(&hba->clk_list_head);
|
||||
spin_lock_init(&hba->outstanding_lock);
|
||||
|
||||
|
||||
@@ -124,3 +124,7 @@ config SCSI_UFS_EXYNOS
|
||||
|
||||
Select this if you have UFS host controller on Samsung Exynos SoC.
|
||||
If unsure, say N.
|
||||
|
||||
config SCSI_UFS_VARIABLE_SG_ENTRY_SIZE
|
||||
bool
|
||||
default y if SCSI_UFS_EXYNOS && SCSI_UFS_CRYPTO
|
||||
|
||||
@@ -915,7 +915,9 @@ struct ufs_hba {
|
||||
const struct ufs_hba_variant_ops *vops;
|
||||
struct ufs_hba_variant_params *vps;
|
||||
void *priv;
|
||||
#ifdef CONFIG_SCSI_UFS_VARIABLE_SG_ENTRY_SIZE
|
||||
size_t sg_entry_size;
|
||||
#endif
|
||||
unsigned int irq;
|
||||
bool is_irq_enabled;
|
||||
enum ufs_ref_clk_freq dev_ref_clk_freq;
|
||||
@@ -1026,6 +1028,32 @@ struct ufs_hba {
|
||||
ANDROID_KABI_RESERVE(4);
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SCSI_UFS_VARIABLE_SG_ENTRY_SIZE
|
||||
static inline size_t ufshcd_sg_entry_size(const struct ufs_hba *hba)
|
||||
{
|
||||
return hba->sg_entry_size;
|
||||
}
|
||||
|
||||
static inline void ufshcd_set_sg_entry_size(struct ufs_hba *hba, size_t sg_entry_size)
|
||||
{
|
||||
WARN_ON_ONCE(sg_entry_size < sizeof(struct ufshcd_sg_entry));
|
||||
hba->sg_entry_size = sg_entry_size;
|
||||
}
|
||||
#else
|
||||
static inline size_t ufshcd_sg_entry_size(const struct ufs_hba *hba)
|
||||
{
|
||||
return sizeof(struct ufshcd_sg_entry);
|
||||
}
|
||||
|
||||
#define ufshcd_set_sg_entry_size(hba, sg_entry_size) \
|
||||
({ (void)(hba); BUILD_BUG_ON(sg_entry_size != sizeof(struct ufshcd_sg_entry)); })
|
||||
#endif
|
||||
|
||||
static inline size_t sizeof_utp_transfer_cmd_desc(const struct ufs_hba *hba)
|
||||
{
|
||||
return sizeof(struct utp_transfer_cmd_desc) + SG_ALL * ufshcd_sg_entry_size(hba);
|
||||
}
|
||||
|
||||
/* Returns true if clocks can be gated. Otherwise false */
|
||||
static inline bool ufshcd_is_clkgating_allowed(struct ufs_hba *hba)
|
||||
{
|
||||
|
||||
@@ -425,7 +425,7 @@ struct ufshcd_sg_entry {
|
||||
__le32 size;
|
||||
/*
|
||||
* followed by variant-specific fields if
|
||||
* hba->sg_entry_size != sizeof(struct ufshcd_sg_entry)
|
||||
* CONFIG_SCSI_UFS_VARIABLE_SG_ENTRY_SIZE has been defined.
|
||||
*/
|
||||
};
|
||||
|
||||
@@ -442,9 +442,6 @@ struct utp_transfer_cmd_desc {
|
||||
u8 prd_table[];
|
||||
};
|
||||
|
||||
#define sizeof_utp_transfer_cmd_desc(hba) \
|
||||
(sizeof(struct utp_transfer_cmd_desc) + SG_ALL * (hba)->sg_entry_size)
|
||||
|
||||
/**
|
||||
* struct request_desc_header - Descriptor Header common to both UTRD and UTMRD
|
||||
* @dword0: Descriptor Header DW0
|
||||
|
||||
Reference in New Issue
Block a user