From cce9fd602ca0c5b0a310dbe457aa61d1beaa2d38 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 27 Jul 2023 12:41:17 -0700 Subject: scsi: ufs: Minimize #include directives Only #include those header files that are needed. Note: include/ufs/ufshcd.h needs because of SG_ALL. Signed-off-by: Bart Van Assche Link: https://lore.kernel.org/r/20230727194457.3152309-6-bvanassche@acm.org Signed-off-by: Martin K. Petersen --- include/ufs/ufs.h | 2 +- include/ufs/ufshcd.h | 1 + include/ufs/ufshci.h | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'include/ufs') diff --git a/include/ufs/ufs.h b/include/ufs/ufs.h index c789252b5fad..0fb733683953 100644 --- a/include/ufs/ufs.h +++ b/include/ufs/ufs.h @@ -11,7 +11,7 @@ #ifndef _UFS_H #define _UFS_H -#include +#include #include #include diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index fc80de57a4c6..67bd089e70bc 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/include/ufs/ufshci.h b/include/ufs/ufshci.h index 146fbea76d98..c48135554d5c 100644 --- a/include/ufs/ufshci.h +++ b/include/ufs/ufshci.h @@ -11,7 +11,8 @@ #ifndef _UFSHCI_H #define _UFSHCI_H -#include +#include +#include enum { TASK_REQ_UPIU_SIZE_DWORDS = 8, -- cgit v1.2.3 From 08108d31129a104b06628b3ac95af2af9f5e9e4c Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 27 Jul 2023 12:41:19 -0700 Subject: scsi: ufs: Improve type safety Assign names to the enumeration types for UPIU types. Use these enumeration types where appropriate. Signed-off-by: Bart Van Assche Link: https://lore.kernel.org/r/20230727194457.3152309-8-bvanassche@acm.org Signed-off-by: Martin K. Petersen --- drivers/ufs/core/ufshcd-priv.h | 2 +- drivers/ufs/core/ufshcd.c | 9 ++++----- include/ufs/ufs.h | 4 ++-- include/ufs/ufshcd.h | 6 ------ 4 files changed, 7 insertions(+), 14 deletions(-) (limited to 'include/ufs') diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h index 4feccd5c1ba2..f42d99ce5bf1 100644 --- a/drivers/ufs/core/ufshcd-priv.h +++ b/drivers/ufs/core/ufshcd-priv.h @@ -93,7 +93,7 @@ int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd); int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, struct utp_upiu_req *req_upiu, struct utp_upiu_req *rsp_upiu, - int msgcode, + enum upiu_request_transaction msgcode, u8 *desc_buff, int *buff_len, enum query_opcode desc_op); diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 5e248c60f887..19c210ef74f5 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -879,7 +879,7 @@ static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba *hba) * * Return: UPIU type. */ -static inline int +static inline enum upiu_response_transaction ufshcd_get_req_rsp(struct utp_upiu_rsp *ucd_rsp_ptr) { return be32_to_cpu(ucd_rsp_ptr->header.dword_0) >> 24; @@ -3032,7 +3032,7 @@ ufshcd_check_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) static int ufshcd_dev_cmd_completion(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) { - int resp; + enum upiu_response_transaction resp; int err = 0; hba->ufs_stats.last_hibern8_exit_tstamp = ktime_set(0, 0); @@ -5271,9 +5271,8 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp, switch (ocs) { case OCS_SUCCESS: - result = ufshcd_get_req_rsp(lrbp->ucd_rsp_ptr); hba->ufs_stats.last_hibern8_exit_tstamp = ktime_set(0, 0); - switch (result) { + switch (ufshcd_get_req_rsp(lrbp->ucd_rsp_ptr)) { case UPIU_TRANSACTION_RESPONSE: /* * get the response UPIU result to extract @@ -7199,7 +7198,7 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba, int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, struct utp_upiu_req *req_upiu, struct utp_upiu_req *rsp_upiu, - int msgcode, + enum upiu_request_transaction msgcode, u8 *desc_buff, int *buff_len, enum query_opcode desc_op) { diff --git a/include/ufs/ufs.h b/include/ufs/ufs.h index 0fb733683953..797bf033c19a 100644 --- a/include/ufs/ufs.h +++ b/include/ufs/ufs.h @@ -78,7 +78,7 @@ enum { }; /* UTP UPIU Transaction Codes Initiator to Target */ -enum { +enum upiu_request_transaction { UPIU_TRANSACTION_NOP_OUT = 0x00, UPIU_TRANSACTION_COMMAND = 0x01, UPIU_TRANSACTION_DATA_OUT = 0x02, @@ -87,7 +87,7 @@ enum { }; /* UTP UPIU Transaction Codes Target to Initiator */ -enum { +enum upiu_response_transaction { UPIU_TRANSACTION_NOP_IN = 0x20, UPIU_TRANSACTION_RESPONSE = 0x21, UPIU_TRANSACTION_DATA_IN = 0x22, diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index 67bd089e70bc..2b1f4f2a4464 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -1357,12 +1357,6 @@ int ufshcd_get_vreg(struct device *dev, struct ufs_vreg *vreg); int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd); -int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, - struct utp_upiu_req *req_upiu, - struct utp_upiu_req *rsp_upiu, - int msgcode, - u8 *desc_buff, int *buff_len, - enum query_opcode desc_op); int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *req_upiu, struct utp_upiu_req *rsp_upiu, struct ufs_ehs *ehs_req, struct ufs_ehs *ehs_rsp, int sg_cnt, -- cgit v1.2.3 From e2566e0b7937f0a0b84f8b662fceebac6a1386c7 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 27 Jul 2023 12:41:22 -0700 Subject: scsi: ufs: Remove a member variable Remove the 'response' member variable because no code reads its value. Additionally, move the ufs_query_req and ufs_query_res data structure definitions into include/ufs/ufshcd.h because these data structures are related to the UFS host controller driver. Reviewed-by: Avri Altman Signed-off-by: Bart Van Assche Link: https://lore.kernel.org/r/20230727194457.3152309-11-bvanassche@acm.org Signed-off-by: Martin K. Petersen --- drivers/ufs/core/ufshcd.c | 6 +----- include/ufs/ufs.h | 20 -------------------- include/ufs/ufshcd.h | 19 +++++++++++++++++++ 3 files changed, 20 insertions(+), 25 deletions(-) (limited to 'include/ufs') diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index bf76ea59ba6c..4348b0dfde29 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -3014,12 +3014,8 @@ static int ufshcd_clear_cmd(struct ufs_hba *hba, u32 task_tag) static int ufshcd_check_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) { - struct ufs_query_res *query_res = &hba->dev_cmd.query.response; - - /* Get the UPIU response */ - query_res->response = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr) >> + return ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr) >> UPIU_RSP_CODE_OFFSET; - return query_res->response; } /** diff --git a/include/ufs/ufs.h b/include/ufs/ufs.h index 797bf033c19a..0ee1fdf2fe83 100644 --- a/include/ufs/ufs.h +++ b/include/ufs/ufs.h @@ -537,26 +537,6 @@ struct utp_upiu_rsp { }; }; -/** - * struct ufs_query_req - parameters for building a query request - * @query_func: UPIU header query function - * @upiu_req: the query request data - */ -struct ufs_query_req { - u8 query_func; - struct utp_upiu_query upiu_req; -}; - -/** - * struct ufs_query_resp - UPIU QUERY - * @response: device response code - * @upiu_res: query response data - */ -struct ufs_query_res { - u8 response; - struct utp_upiu_query upiu_res; -}; - /* * VCCQ & VCCQ2 current requirement when UFS device is in sleep state * and link is in Hibern8 state. diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index 2b1f4f2a4464..bf4070a4b95f 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -202,6 +202,25 @@ struct ufshcd_lrb { bool req_abort_skip; }; +/** + * struct ufs_query_req - parameters for building a query request + * @query_func: UPIU header query function + * @upiu_req: the query request data + */ +struct ufs_query_req { + u8 query_func; + struct utp_upiu_query upiu_req; +}; + +/** + * struct ufs_query_resp - UPIU QUERY + * @response: device response code + * @upiu_res: query response data + */ +struct ufs_query_res { + struct utp_upiu_query upiu_res; +}; + /** * struct ufs_query - holds relevant data structures for query request * @request: request upiu and function -- cgit v1.2.3 From 67a2a8973832cbeb23a5c04a1dda94da71490a0d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 27 Jul 2023 12:41:23 -0700 Subject: scsi: ufs: Simplify transfer request header initialization Make the code that initializes UTP transfer request headers easier to read by using bitfields instead of __le32 where appropriate. Cc: "Bao D. Nguyen" Cc: Eric Biggers Cc: Avri Altman Cc: Bean Huo Cc: Adrian Hunter Signed-off-by: Bart Van Assche Link: https://lore.kernel.org/r/20230727194457.3152309-12-bvanassche@acm.org Reviewed-by: Avri Altman Signed-off-by: Martin K. Petersen --- drivers/ufs/core/ufs-mcq.c | 7 +--- drivers/ufs/core/ufshcd-crypto.h | 20 +++++------ drivers/ufs/core/ufshcd.c | 77 ++++++++++++++++++++++++++++------------ include/ufs/ufs.h | 3 -- include/ufs/ufshci.h | 50 +++++++++++++++++--------- 5 files changed, 99 insertions(+), 58 deletions(-) (limited to 'include/ufs') diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c index a3d4ef8aa3b9..66a4e24484a3 100644 --- a/drivers/ufs/core/ufs-mcq.c +++ b/drivers/ufs/core/ufs-mcq.c @@ -558,12 +558,7 @@ unlock: */ static void ufshcd_mcq_nullify_sqe(struct utp_transfer_req_desc *utrd) { - u32 dword_0; - - dword_0 = le32_to_cpu(utrd->header.dword_0); - dword_0 &= ~UPIU_COMMAND_TYPE_MASK; - dword_0 |= FIELD_PREP(UPIU_COMMAND_TYPE_MASK, 0xF); - utrd->header.dword_0 = cpu_to_le32(dword_0); + utrd->header.command_type = 0xf; } /** diff --git a/drivers/ufs/core/ufshcd-crypto.h b/drivers/ufs/core/ufshcd-crypto.h index 504cc841540b..be8596f20ba2 100644 --- a/drivers/ufs/core/ufshcd-crypto.h +++ b/drivers/ufs/core/ufshcd-crypto.h @@ -26,15 +26,15 @@ static inline void ufshcd_prepare_lrbp_crypto(struct request *rq, } static inline void -ufshcd_prepare_req_desc_hdr_crypto(struct ufshcd_lrb *lrbp, u32 *dword_0, - u32 *dword_1, u32 *dword_3) +ufshcd_prepare_req_desc_hdr_crypto(struct ufshcd_lrb *lrbp, + struct request_desc_header *h) { - if (lrbp->crypto_key_slot >= 0) { - *dword_0 |= UTP_REQ_DESC_CRYPTO_ENABLE_CMD; - *dword_0 |= lrbp->crypto_key_slot; - *dword_1 = lower_32_bits(lrbp->data_unit_num); - *dword_3 = upper_32_bits(lrbp->data_unit_num); - } + if (lrbp->crypto_key_slot < 0) + return; + h->enable_crypto = 1; + h->cci = lrbp->crypto_key_slot; + h->dunl = cpu_to_le32(lower_32_bits(lrbp->data_unit_num)); + h->dunu = cpu_to_le32(upper_32_bits(lrbp->data_unit_num)); } bool ufshcd_crypto_enable(struct ufs_hba *hba); @@ -51,8 +51,8 @@ static inline void ufshcd_prepare_lrbp_crypto(struct request *rq, struct ufshcd_lrb *lrbp) { } static inline void -ufshcd_prepare_req_desc_hdr_crypto(struct ufshcd_lrb *lrbp, u32 *dword_0, - u32 *dword_1, u32 *dword_3) { } +ufshcd_prepare_req_desc_hdr_crypto(struct ufshcd_lrb *lrbp, + struct request_desc_header *h) { } static inline bool ufshcd_crypto_enable(struct ufs_hba *hba) { diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 4348b0dfde29..b85c7a28fff5 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -794,7 +794,7 @@ static enum utp_ocs ufshcd_get_tr_ocs(struct ufshcd_lrb *lrbp, if (cqe) return le32_to_cpu(cqe->status) & MASK_OCS; - return le32_to_cpu(lrbp->utr_descriptor_ptr->header.dword_2) & MASK_OCS; + return lrbp->utr_descriptor_ptr->header.ocs & MASK_OCS; } /** @@ -2587,10 +2587,10 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp, u8 *upiu_flags, enum dma_data_direction cmd_dir, int ehs_length) { struct utp_transfer_req_desc *req_desc = lrbp->utr_descriptor_ptr; - u32 data_direction; - u32 dword_0; - u32 dword_1 = 0; - u32 dword_3 = 0; + struct request_desc_header *h = &req_desc->header; + enum utp_data_direction data_direction; + + *h = (typeof(*h)){ }; if (cmd_dir == DMA_FROM_DEVICE) { data_direction = UTP_DEVICE_TO_HOST; @@ -2603,25 +2603,22 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp, u8 *upiu_flags, *upiu_flags = UPIU_CMD_FLAGS_NONE; } - dword_0 = data_direction | (lrbp->command_type << UPIU_COMMAND_TYPE_OFFSET) | - ehs_length << 8; + h->command_type = lrbp->command_type; + h->data_direction = data_direction; + h->ehs_length = ehs_length; + if (lrbp->intr_cmd) - dword_0 |= UTP_REQ_DESC_INT_CMD; + h->interrupt = 1; /* Prepare crypto related dwords */ - ufshcd_prepare_req_desc_hdr_crypto(lrbp, &dword_0, &dword_1, &dword_3); + ufshcd_prepare_req_desc_hdr_crypto(lrbp, h); - /* Transfer request descriptor header fields */ - req_desc->header.dword_0 = cpu_to_le32(dword_0); - req_desc->header.dword_1 = cpu_to_le32(dword_1); /* * assigning invalid value for command status. Controller * updates OCS on command completion, with the command * status */ - req_desc->header.dword_2 = - cpu_to_le32(OCS_INVALID_COMMAND_STATUS); - req_desc->header.dword_3 = cpu_to_le32(dword_3); + h->ocs = OCS_INVALID_COMMAND_STATUS; req_desc->prd_table_length = 0; } @@ -5445,8 +5442,7 @@ void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag, if (hba->dev_cmd.complete) { if (cqe) { ocs = le32_to_cpu(cqe->status) & MASK_OCS; - lrbp->utr_descriptor_ptr->header.dword_2 = - cpu_to_le32(ocs); + lrbp->utr_descriptor_ptr->header.ocs = ocs; } complete(hba->dev_cmd.complete); ufshcd_clk_scaling_update_busy(hba); @@ -7034,8 +7030,8 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id, int err; /* Configure task request descriptor */ - treq.header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD); - treq.header.dword_2 = cpu_to_le32(OCS_INVALID_COMMAND_STATUS); + treq.header.interrupt = 1; + treq.header.ocs = OCS_INVALID_COMMAND_STATUS; /* Configure task request UPIU */ treq.upiu_req.req_header.dword_0 = cpu_to_be32(lun_id << 8) | @@ -7053,7 +7049,7 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id, if (err == -ETIMEDOUT) return err; - ocs_value = le32_to_cpu(treq.header.dword_2) & MASK_OCS; + ocs_value = treq.header.ocs & MASK_OCS; if (ocs_value != OCS_SUCCESS) dev_err(hba->dev, "%s: failed, ocs = 0x%x\n", __func__, ocs_value); @@ -7213,8 +7209,8 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, break; case UPIU_TRANSACTION_TASK_REQ: - treq.header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD); - treq.header.dword_2 = cpu_to_le32(OCS_INVALID_COMMAND_STATUS); + treq.header.interrupt = 1; + treq.header.ocs = OCS_INVALID_COMMAND_STATUS; memcpy(&treq.upiu_req, req_upiu, sizeof(*req_upiu)); @@ -7222,7 +7218,7 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, if (err == -ETIMEDOUT) break; - ocs_value = le32_to_cpu(treq.header.dword_2) & MASK_OCS; + ocs_value = treq.header.ocs & MASK_OCS; if (ocs_value != OCS_SUCCESS) { dev_err(hba->dev, "%s: failed, ocs = 0x%x\n", __func__, ocs_value); @@ -10567,6 +10563,39 @@ static const struct dev_pm_ops ufshcd_wl_pm_ops = { SET_RUNTIME_PM_OPS(ufshcd_wl_runtime_suspend, ufshcd_wl_runtime_resume, NULL) }; +static void ufshcd_check_header_layout(void) +{ + BUILD_BUG_ON(((u8 *)&(struct request_desc_header){ + .cci = 3})[0] != 3); + + BUILD_BUG_ON(((u8 *)&(struct request_desc_header){ + .ehs_length = 2})[1] != 2); + + BUILD_BUG_ON(((u8 *)&(struct request_desc_header){ + .enable_crypto = 1})[2] + != 0x80); + + BUILD_BUG_ON((((u8 *)&(struct request_desc_header){ + .command_type = 5, + .data_direction = 3, + .interrupt = 1, + })[3]) != ((5 << 4) | (3 << 1) | 1)); + + BUILD_BUG_ON(((__le32 *)&(struct request_desc_header){ + .dunl = cpu_to_le32(0xdeadbeef)})[1] != + cpu_to_le32(0xdeadbeef)); + + BUILD_BUG_ON(((u8 *)&(struct request_desc_header){ + .ocs = 4})[8] != 4); + + BUILD_BUG_ON(((u8 *)&(struct request_desc_header){ + .cds = 5})[9] != 5); + + BUILD_BUG_ON(((__le32 *)&(struct request_desc_header){ + .dunu = cpu_to_le32(0xbadcafe)})[3] != + cpu_to_le32(0xbadcafe)); +} + /* * ufs_dev_wlun_template - describes ufs device wlun * ufs-device wlun - used to send pm commands @@ -10592,6 +10621,8 @@ static int __init ufshcd_core_init(void) { int ret; + ufshcd_check_header_layout(); + ufs_debugfs_init(); ret = scsi_register_driver(&ufs_dev_wlun_template.gendrv); diff --git a/include/ufs/ufs.h b/include/ufs/ufs.h index 0ee1fdf2fe83..80fae9484807 100644 --- a/include/ufs/ufs.h +++ b/include/ufs/ufs.h @@ -473,9 +473,6 @@ enum { UPIU_COMMAND_SET_TYPE_QUERY = 0x2, }; -/* UTP Transfer Request Command Offset */ -#define UPIU_COMMAND_TYPE_OFFSET 28 - /* Offset of the response code in the UPIU header */ #define UPIU_RSP_CODE_OFFSET 8 diff --git a/include/ufs/ufshci.h b/include/ufs/ufshci.h index c48135554d5c..d5accacae6bc 100644 --- a/include/ufs/ufshci.h +++ b/include/ufs/ufshci.h @@ -127,7 +127,6 @@ enum { }; #define SQ_ICU_ERR_CODE_MASK GENMASK(7, 4) -#define UPIU_COMMAND_TYPE_MASK GENMASK(31, 28) #define UFS_MASK(mask, offset) ((mask) << (offset)) /* UFS Version 08h */ @@ -439,15 +438,13 @@ enum { UTP_SCSI_COMMAND = 0x00000000, UTP_NATIVE_UFS_COMMAND = 0x10000000, UTP_DEVICE_MANAGEMENT_FUNCTION = 0x20000000, - UTP_REQ_DESC_INT_CMD = 0x01000000, - UTP_REQ_DESC_CRYPTO_ENABLE_CMD = 0x00800000, }; /* UTP Transfer Request Data Direction (DD) */ -enum { - UTP_NO_DATA_TRANSFER = 0x00000000, - UTP_HOST_TO_DEVICE = 0x02000000, - UTP_DEVICE_TO_HOST = 0x04000000, +enum utp_data_direction { + UTP_NO_DATA_TRANSFER = 0, + UTP_HOST_TO_DEVICE = 1, + UTP_DEVICE_TO_HOST = 2, }; /* Overall command status values */ @@ -506,17 +503,38 @@ struct utp_transfer_cmd_desc { /** * struct request_desc_header - Descriptor Header common to both UTRD and UTMRD - * @dword0: Descriptor Header DW0 - * @dword1: Descriptor Header DW1 - * @dword2: Descriptor Header DW2 - * @dword3: Descriptor Header DW3 */ struct request_desc_header { - __le32 dword_0; - __le32 dword_1; - __le32 dword_2; - __le32 dword_3; -}; + u8 cci; + u8 ehs_length; +#if defined(__BIG_ENDIAN) + u8 enable_crypto:1; + u8 reserved2:7; + + u8 command_type:4; + u8 reserved1:1; + u8 data_direction:2; + u8 interrupt:1; +#elif defined(__LITTLE_ENDIAN) + u8 reserved2:7; + u8 enable_crypto:1; + + u8 interrupt:1; + u8 data_direction:2; + u8 reserved1:1; + u8 command_type:4; +#else +#error +#endif + + __le32 dunl; + u8 ocs; + u8 cds; + __le16 ldbc; + __le32 dunu; +}; + +static_assert(sizeof(struct request_desc_header) == 16); /** * struct utp_transfer_req_desc - UTP Transfer Request Descriptor (UTRD) -- cgit v1.2.3 From 617bfaa8dd50d6a3ffc8694b4696bf2aa196bd44 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 27 Jul 2023 12:41:24 -0700 Subject: scsi: ufs: Simplify response header parsing Make the code that parses UTP transfer request headers easier to read by using u8 instead of __be32 where appropriate. Signed-off-by: Bart Van Assche Link: https://lore.kernel.org/r/20230727194457.3152309-13-bvanassche@acm.org Reviewed-by: Avri Altman Signed-off-by: Martin K. Petersen --- drivers/ufs/core/ufshcd.c | 153 +++++++++++++++------------------------ include/uapi/scsi/scsi_bsg_ufs.h | 52 ++++++++++++- include/ufs/ufs.h | 18 ++--- 3 files changed, 115 insertions(+), 108 deletions(-) (limited to 'include/ufs') diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index b85c7a28fff5..2e669e64872c 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -882,35 +882,7 @@ static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba *hba) static inline enum upiu_response_transaction ufshcd_get_req_rsp(struct utp_upiu_rsp *ucd_rsp_ptr) { - return be32_to_cpu(ucd_rsp_ptr->header.dword_0) >> 24; -} - -/** - * ufshcd_get_rsp_upiu_result - Get the result from response UPIU - * @ucd_rsp_ptr: pointer to response UPIU - * - * This function gets the response status and scsi_status from response UPIU - * - * Return: the response result code. - */ -static inline int -ufshcd_get_rsp_upiu_result(struct utp_upiu_rsp *ucd_rsp_ptr) -{ - return be32_to_cpu(ucd_rsp_ptr->header.dword_1) & MASK_RSP_UPIU_RESULT; -} - -/* - * ufshcd_get_rsp_upiu_data_seg_len - Get the data segment length - * from response UPIU - * @ucd_rsp_ptr: pointer to response UPIU - * - * Return: the data segment length. - */ -static inline unsigned int -ufshcd_get_rsp_upiu_data_seg_len(struct utp_upiu_rsp *ucd_rsp_ptr) -{ - return be32_to_cpu(ucd_rsp_ptr->header.dword_2) & - MASK_RSP_UPIU_DATA_SEG_LEN; + return ucd_rsp_ptr->header.transaction_code; } /** @@ -924,8 +896,7 @@ ufshcd_get_rsp_upiu_data_seg_len(struct utp_upiu_rsp *ucd_rsp_ptr) */ static inline bool ufshcd_is_exception_event(struct utp_upiu_rsp *ucd_rsp_ptr) { - return be32_to_cpu(ucd_rsp_ptr->header.dword_2) & - MASK_RSP_EXCEPTION_EVENT; + return ucd_rsp_ptr->header.device_information & 1; } /** @@ -2224,10 +2195,11 @@ void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag, static inline void ufshcd_copy_sense_data(struct ufshcd_lrb *lrbp) { u8 *const sense_buffer = lrbp->cmd->sense_buffer; + u16 resp_len; int len; - if (sense_buffer && - ufshcd_get_rsp_upiu_data_seg_len(lrbp->ucd_rsp_ptr)) { + resp_len = be16_to_cpu(lrbp->ucd_rsp_ptr->header.data_segment_length); + if (sense_buffer && resp_len) { int len_to_copy; len = be16_to_cpu(lrbp->ucd_rsp_ptr->sr.sense_data_len); @@ -2262,8 +2234,8 @@ int ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) u16 buf_len; /* data segment length */ - resp_len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) & - MASK_QUERY_DATA_SEG_LEN; + resp_len = be16_to_cpu(lrbp->ucd_rsp_ptr->header + .data_segment_length); buf_len = be16_to_cpu( hba->dev_cmd.query.request.upiu_req.length); if (likely(buf_len >= resp_len)) { @@ -2636,15 +2608,13 @@ void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u8 upiu_flags) struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr; unsigned short cdb_len; - /* command descriptor fields */ - ucd_req_ptr->header.dword_0 = upiu_header_dword( - UPIU_TRANSACTION_COMMAND, upiu_flags, - lrbp->lun, lrbp->task_tag); - ucd_req_ptr->header.dword_1 = upiu_header_dword( - UPIU_COMMAND_SET_TYPE_SCSI, 0, 0, 0); - - /* Total EHS length and Data segment length will be zero */ - ucd_req_ptr->header.dword_2 = 0; + ucd_req_ptr->header = (struct utp_upiu_header){ + .transaction_code = UPIU_TRANSACTION_COMMAND, + .flags = upiu_flags, + .lun = lrbp->lun, + .task_tag = lrbp->task_tag, + .command_set_type = UPIU_COMMAND_SET_TYPE_SCSI, + }; ucd_req_ptr->sc.exp_data_transfer_len = cpu_to_be32(cmd->sdb.length); @@ -2669,18 +2639,19 @@ static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba, u16 len = be16_to_cpu(query->request.upiu_req.length); /* Query request header */ - ucd_req_ptr->header.dword_0 = upiu_header_dword( - UPIU_TRANSACTION_QUERY_REQ, upiu_flags, - lrbp->lun, lrbp->task_tag); - ucd_req_ptr->header.dword_1 = upiu_header_dword( - 0, query->request.query_func, 0, 0); - - /* Data segment length only need for WRITE_DESC */ - if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC) - ucd_req_ptr->header.dword_2 = - upiu_header_dword(0, 0, len >> 8, (u8)len); - else - ucd_req_ptr->header.dword_2 = 0; + ucd_req_ptr->header = (struct utp_upiu_header){ + .transaction_code = UPIU_TRANSACTION_QUERY_REQ, + .flags = upiu_flags, + .lun = lrbp->lun, + .task_tag = lrbp->task_tag, + .query_function = query->request.query_func, + /* Data segment length only need for WRITE_DESC */ + .data_segment_length = + query->request.upiu_req.opcode == + UPIU_QUERY_OPCODE_WRITE_DESC ? + cpu_to_be16(len) : + 0, + }; /* Copy the Query Request buffer as is */ memcpy(&ucd_req_ptr->qr, &query->request.upiu_req, @@ -2699,12 +2670,10 @@ static inline void ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp) memset(ucd_req_ptr, 0, sizeof(struct utp_upiu_req)); - /* command descriptor fields */ - ucd_req_ptr->header.dword_0 = upiu_header_dword( - UPIU_TRANSACTION_NOP_OUT, 0, 0, lrbp->task_tag); - /* clear rest of the fields of basic header */ - ucd_req_ptr->header.dword_1 = 0; - ucd_req_ptr->header.dword_2 = 0; + ucd_req_ptr->header = (struct utp_upiu_header){ + .transaction_code = UPIU_TRANSACTION_NOP_OUT, + .task_tag = lrbp->task_tag, + }; memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp)); } @@ -3008,13 +2977,6 @@ static int ufshcd_clear_cmd(struct ufs_hba *hba, u32 task_tag) mask, ~mask, 1000, 1000); } -static int -ufshcd_check_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) -{ - return ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr) >> - UPIU_RSP_CODE_OFFSET; -} - /** * ufshcd_dev_cmd_completion() - handles device management command responses * @hba: per adapter instance @@ -3039,11 +3001,13 @@ ufshcd_dev_cmd_completion(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) __func__, resp); } break; - case UPIU_TRANSACTION_QUERY_RSP: - err = ufshcd_check_query_response(hba, lrbp); - if (!err) + case UPIU_TRANSACTION_QUERY_RSP: { + u8 response = lrbp->ucd_rsp_ptr->header.response; + + if (response == 0) err = ufshcd_copy_query_response(hba, lrbp); break; + } case UPIU_TRANSACTION_REJECT_UPIU: /* TODO: handle Reject UPIU Response */ err = -EPERM; @@ -5244,7 +5208,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp, u8 upiu_flags; u32 resid; - upiu_flags = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_0) >> 16; + upiu_flags = lrbp->ucd_rsp_ptr->header.flags; resid = be32_to_cpu(lrbp->ucd_rsp_ptr->sr.residual_transfer_count); /* * Test !overflow instead of underflow to support UFS devices that do @@ -5257,8 +5221,8 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp, ocs = ufshcd_get_tr_ocs(lrbp, cqe); if (hba->quirks & UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR) { - if (be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_1) & - MASK_RSP_UPIU_RESULT) + if (lrbp->ucd_rsp_ptr->header.response || + lrbp->ucd_rsp_ptr->header.status) ocs = OCS_SUCCESS; } @@ -5267,17 +5231,11 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp, hba->ufs_stats.last_hibern8_exit_tstamp = ktime_set(0, 0); switch (ufshcd_get_req_rsp(lrbp->ucd_rsp_ptr)) { case UPIU_TRANSACTION_RESPONSE: - /* - * get the response UPIU result to extract - * the SCSI command status - */ - result = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr); - /* * get the result based on SCSI status response * to notify the SCSI midlayer of the command status */ - scsi_status = result & MASK_SCSI_STATUS; + scsi_status = lrbp->ucd_rsp_ptr->header.status; result = ufshcd_scsi_cmd_status(lrbp, scsi_status); /* @@ -6967,7 +6925,7 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba, WARN_ONCE(task_tag < 0 || task_tag >= hba->nutmrs, "Invalid tag %d\n", task_tag); hba->tmf_rqs[req->tag] = req; - treq->upiu_req.req_header.dword_0 |= cpu_to_be32(task_tag); + treq->upiu_req.req_header.task_tag = task_tag; memcpy(hba->utmrdl_base_addr + task_tag, treq, sizeof(*treq)); ufshcd_vops_setup_task_mgmt(hba, task_tag, tm_function); @@ -7034,9 +6992,9 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id, treq.header.ocs = OCS_INVALID_COMMAND_STATUS; /* Configure task request UPIU */ - treq.upiu_req.req_header.dword_0 = cpu_to_be32(lun_id << 8) | - cpu_to_be32(UPIU_TRANSACTION_TASK_REQ << 24); - treq.upiu_req.req_header.dword_1 = cpu_to_be32(tm_function << 16); + treq.upiu_req.req_header.transaction_code = UPIU_TRANSACTION_TASK_REQ; + treq.upiu_req.req_header.lun = lun_id; + treq.upiu_req.req_header.tm_function = tm_function; /* * The host shall provide the same value for LUN field in the basic @@ -7110,7 +7068,7 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba, lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE; /* update the task tag in the request upiu */ - req_upiu->header.dword_0 |= cpu_to_be32(tag); + req_upiu->header.task_tag = tag; ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE, 0); @@ -7143,8 +7101,8 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba, memcpy(rsp_upiu, lrbp->ucd_rsp_ptr, sizeof(*rsp_upiu)); if (desc_buff && desc_op == UPIU_QUERY_OPCODE_READ_DESC) { u8 *descp = (u8 *)lrbp->ucd_rsp_ptr + sizeof(*rsp_upiu); - u16 resp_len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) & - MASK_QUERY_DATA_SEG_LEN; + u16 resp_len = be16_to_cpu(lrbp->ucd_rsp_ptr->header + .data_segment_length); if (*buff_len >= resp_len) { memcpy(desc_buff, descp, resp_len); @@ -7192,7 +7150,7 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, enum dev_cmd_type cmd_type = DEV_CMD_TYPE_QUERY; struct utp_task_req_desc treq = { }; enum utp_ocs ocs_value; - u8 tm_f = be32_to_cpu(req_upiu->header.dword_1) >> 16 & MASK_TM_FUNC; + u8 tm_f = req_upiu->header.tm_function; switch (msgcode) { case UPIU_TRANSACTION_NOP_OUT: @@ -7284,7 +7242,9 @@ int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *r ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, dir, 2); /* update the task tag and LUN in the request upiu */ - req_upiu->header.dword_0 |= cpu_to_be32(upiu_flags << 16 | UFS_UPIU_RPMB_WLUN << 8 | tag); + req_upiu->header.flags = upiu_flags; + req_upiu->header.lun = UFS_UPIU_RPMB_WLUN; + req_upiu->header.task_tag = tag; /* copy the UPIU(contains CDB) request as it is */ memcpy(lrbp->ucd_req_ptr, req_upiu, sizeof(*lrbp->ucd_req_ptr)); @@ -7306,9 +7266,10 @@ int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *r /* Just copy the upiu response as it is */ memcpy(rsp_upiu, lrbp->ucd_rsp_ptr, sizeof(*rsp_upiu)); /* Get the response UPIU result */ - result = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr); + result = (lrbp->ucd_rsp_ptr->header.response << 8) | + lrbp->ucd_rsp_ptr->header.status; - ehs_len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) >> 24; + ehs_len = lrbp->ucd_rsp_ptr->header.ehs_length; /* * Since the bLength in EHS indicates the total size of the EHS Header and EHS Data * in 32 Byte units, the value of the bLength Request/Response for Advanced RPMB @@ -10594,6 +10555,12 @@ static void ufshcd_check_header_layout(void) BUILD_BUG_ON(((__le32 *)&(struct request_desc_header){ .dunu = cpu_to_le32(0xbadcafe)})[3] != cpu_to_le32(0xbadcafe)); + + BUILD_BUG_ON(((u8 *)&(struct utp_upiu_header){ + .iid = 0xf })[4] != 0xf0); + + BUILD_BUG_ON(((u8 *)&(struct utp_upiu_header){ + .command_set_type = 0xf })[4] != 0xf); } /* diff --git a/include/uapi/scsi/scsi_bsg_ufs.h b/include/uapi/scsi/scsi_bsg_ufs.h index 2801b65299aa..bf1832dc35db 100644 --- a/include/uapi/scsi/scsi_bsg_ufs.h +++ b/include/uapi/scsi/scsi_bsg_ufs.h @@ -8,6 +8,7 @@ #ifndef SCSI_BSG_UFS_H #define SCSI_BSG_UFS_H +#include #include /* * This file intended to be included by both kernel and user space @@ -40,11 +41,56 @@ enum ufs_rpmb_op_type { * @dword_0: UPIU header DW-0 * @dword_1: UPIU header DW-1 * @dword_2: UPIU header DW-2 + * + * @transaction_code: Type of request or response. See also enum + * upiu_request_transaction and enum upiu_response_transaction. + * @flags: UPIU flags. The meaning of individual flags depends on the + * transaction code. + * @lun: Logical unit number. + * @task_tag: Task tag. + * @iid: Initiator ID. + * @command_set_type: 0 for SCSI command set; 1 for UFS specific. + * @tm_function: Task management function in case of a task management request + * UPIU. + * @query_function: Query function in case of a query request UPIU. + * @response: 0 for success; 1 for failure. + * @status: SCSI status if this is the header of a response to a SCSI command. + * @ehs_length: EHS length in units of 32 bytes. + * @device_information: + * @data_segment_length: data segment length. */ struct utp_upiu_header { - __be32 dword_0; - __be32 dword_1; - __be32 dword_2; + union { + struct { + __be32 dword_0; + __be32 dword_1; + __be32 dword_2; + }; + struct { + __u8 transaction_code; + __u8 flags; + __u8 lun; + __u8 task_tag; +#if defined(__BIG_ENDIAN) + __u8 iid: 4; + __u8 command_set_type: 4; +#elif defined(__LITTLE_ENDIAN) + __u8 command_set_type: 4; + __u8 iid: 4; +#else +#error +#endif + union { + __u8 tm_function; + __u8 query_function; + }; + __u8 response; + __u8 status; + __u8 ehs_length; + __u8 device_information; + __be16 data_segment_length; + }; + }; }; /** diff --git a/include/ufs/ufs.h b/include/ufs/ufs.h index 80fae9484807..3ebb677d993a 100644 --- a/include/ufs/ufs.h +++ b/include/ufs/ufs.h @@ -15,6 +15,12 @@ #include #include +/* + * Using static_assert() is not allowed in UAPI header files. Hence the check + * in this header file of the size of struct utp_upiu_header. + */ +static_assert(sizeof(struct utp_upiu_header) == 12); + #define GENERAL_UPIU_REQUEST_SIZE (sizeof(struct utp_upiu_req)) #define QUERY_DESC_MAX_SIZE 255 #define QUERY_DESC_MIN_SIZE 2 @@ -23,11 +29,6 @@ (sizeof(struct utp_upiu_header))) #define UFS_SENSE_SIZE 18 -static inline __be32 upiu_header_dword(u8 byte3, u8 byte2, u8 byte1, u8 byte0) -{ - return cpu_to_be32(byte3 << 24 | byte2 << 16 | byte1 << 8 | byte0); -} - /* * UFS device may have standard LUs and LUN id could be from 0x00 to * 0x7F. Standard LUs use "Peripheral Device Addressing Format". @@ -477,14 +478,7 @@ enum { #define UPIU_RSP_CODE_OFFSET 8 enum { - MASK_SCSI_STATUS = 0xFF, - MASK_TASK_RESPONSE = 0xFF00, - MASK_RSP_UPIU_RESULT = 0xFFFF, - MASK_QUERY_DATA_SEG_LEN = 0xFFFF, - MASK_RSP_UPIU_DATA_SEG_LEN = 0xFFFF, - MASK_RSP_EXCEPTION_EVENT = 0x10000, MASK_TM_SERVICE_RESP = 0xFF, - MASK_TM_FUNC = 0xFF, }; /* Task management service response */ -- cgit v1.2.3