Skip to content

Commit 617bfaa

Browse files
bvanasschemartinkpetersen
authored andcommitted
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Avri Altman <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 67a2a89 commit 617bfaa

File tree

3 files changed

+115
-108
lines changed

3 files changed

+115
-108
lines changed

drivers/ufs/core/ufshcd.c

Lines changed: 60 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -882,35 +882,7 @@ static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba *hba)
882882
static inline enum upiu_response_transaction
883883
ufshcd_get_req_rsp(struct utp_upiu_rsp *ucd_rsp_ptr)
884884
{
885-
return be32_to_cpu(ucd_rsp_ptr->header.dword_0) >> 24;
886-
}
887-
888-
/**
889-
* ufshcd_get_rsp_upiu_result - Get the result from response UPIU
890-
* @ucd_rsp_ptr: pointer to response UPIU
891-
*
892-
* This function gets the response status and scsi_status from response UPIU
893-
*
894-
* Return: the response result code.
895-
*/
896-
static inline int
897-
ufshcd_get_rsp_upiu_result(struct utp_upiu_rsp *ucd_rsp_ptr)
898-
{
899-
return be32_to_cpu(ucd_rsp_ptr->header.dword_1) & MASK_RSP_UPIU_RESULT;
900-
}
901-
902-
/*
903-
* ufshcd_get_rsp_upiu_data_seg_len - Get the data segment length
904-
* from response UPIU
905-
* @ucd_rsp_ptr: pointer to response UPIU
906-
*
907-
* Return: the data segment length.
908-
*/
909-
static inline unsigned int
910-
ufshcd_get_rsp_upiu_data_seg_len(struct utp_upiu_rsp *ucd_rsp_ptr)
911-
{
912-
return be32_to_cpu(ucd_rsp_ptr->header.dword_2) &
913-
MASK_RSP_UPIU_DATA_SEG_LEN;
885+
return ucd_rsp_ptr->header.transaction_code;
914886
}
915887

916888
/**
@@ -924,8 +896,7 @@ ufshcd_get_rsp_upiu_data_seg_len(struct utp_upiu_rsp *ucd_rsp_ptr)
924896
*/
925897
static inline bool ufshcd_is_exception_event(struct utp_upiu_rsp *ucd_rsp_ptr)
926898
{
927-
return be32_to_cpu(ucd_rsp_ptr->header.dword_2) &
928-
MASK_RSP_EXCEPTION_EVENT;
899+
return ucd_rsp_ptr->header.device_information & 1;
929900
}
930901

931902
/**
@@ -2224,10 +2195,11 @@ void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag,
22242195
static inline void ufshcd_copy_sense_data(struct ufshcd_lrb *lrbp)
22252196
{
22262197
u8 *const sense_buffer = lrbp->cmd->sense_buffer;
2198+
u16 resp_len;
22272199
int len;
22282200

2229-
if (sense_buffer &&
2230-
ufshcd_get_rsp_upiu_data_seg_len(lrbp->ucd_rsp_ptr)) {
2201+
resp_len = be16_to_cpu(lrbp->ucd_rsp_ptr->header.data_segment_length);
2202+
if (sense_buffer && resp_len) {
22312203
int len_to_copy;
22322204

22332205
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)
22622234
u16 buf_len;
22632235

22642236
/* data segment length */
2265-
resp_len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) &
2266-
MASK_QUERY_DATA_SEG_LEN;
2237+
resp_len = be16_to_cpu(lrbp->ucd_rsp_ptr->header
2238+
.data_segment_length);
22672239
buf_len = be16_to_cpu(
22682240
hba->dev_cmd.query.request.upiu_req.length);
22692241
if (likely(buf_len >= resp_len)) {
@@ -2636,15 +2608,13 @@ void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u8 upiu_flags)
26362608
struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
26372609
unsigned short cdb_len;
26382610

2639-
/* command descriptor fields */
2640-
ucd_req_ptr->header.dword_0 = upiu_header_dword(
2641-
UPIU_TRANSACTION_COMMAND, upiu_flags,
2642-
lrbp->lun, lrbp->task_tag);
2643-
ucd_req_ptr->header.dword_1 = upiu_header_dword(
2644-
UPIU_COMMAND_SET_TYPE_SCSI, 0, 0, 0);
2645-
2646-
/* Total EHS length and Data segment length will be zero */
2647-
ucd_req_ptr->header.dword_2 = 0;
2611+
ucd_req_ptr->header = (struct utp_upiu_header){
2612+
.transaction_code = UPIU_TRANSACTION_COMMAND,
2613+
.flags = upiu_flags,
2614+
.lun = lrbp->lun,
2615+
.task_tag = lrbp->task_tag,
2616+
.command_set_type = UPIU_COMMAND_SET_TYPE_SCSI,
2617+
};
26482618

26492619
ucd_req_ptr->sc.exp_data_transfer_len = cpu_to_be32(cmd->sdb.length);
26502620

@@ -2669,18 +2639,19 @@ static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba,
26692639
u16 len = be16_to_cpu(query->request.upiu_req.length);
26702640

26712641
/* Query request header */
2672-
ucd_req_ptr->header.dword_0 = upiu_header_dword(
2673-
UPIU_TRANSACTION_QUERY_REQ, upiu_flags,
2674-
lrbp->lun, lrbp->task_tag);
2675-
ucd_req_ptr->header.dword_1 = upiu_header_dword(
2676-
0, query->request.query_func, 0, 0);
2677-
2678-
/* Data segment length only need for WRITE_DESC */
2679-
if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC)
2680-
ucd_req_ptr->header.dword_2 =
2681-
upiu_header_dword(0, 0, len >> 8, (u8)len);
2682-
else
2683-
ucd_req_ptr->header.dword_2 = 0;
2642+
ucd_req_ptr->header = (struct utp_upiu_header){
2643+
.transaction_code = UPIU_TRANSACTION_QUERY_REQ,
2644+
.flags = upiu_flags,
2645+
.lun = lrbp->lun,
2646+
.task_tag = lrbp->task_tag,
2647+
.query_function = query->request.query_func,
2648+
/* Data segment length only need for WRITE_DESC */
2649+
.data_segment_length =
2650+
query->request.upiu_req.opcode ==
2651+
UPIU_QUERY_OPCODE_WRITE_DESC ?
2652+
cpu_to_be16(len) :
2653+
0,
2654+
};
26842655

26852656
/* Copy the Query Request buffer as is */
26862657
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)
26992670

27002671
memset(ucd_req_ptr, 0, sizeof(struct utp_upiu_req));
27012672

2702-
/* command descriptor fields */
2703-
ucd_req_ptr->header.dword_0 = upiu_header_dword(
2704-
UPIU_TRANSACTION_NOP_OUT, 0, 0, lrbp->task_tag);
2705-
/* clear rest of the fields of basic header */
2706-
ucd_req_ptr->header.dword_1 = 0;
2707-
ucd_req_ptr->header.dword_2 = 0;
2673+
ucd_req_ptr->header = (struct utp_upiu_header){
2674+
.transaction_code = UPIU_TRANSACTION_NOP_OUT,
2675+
.task_tag = lrbp->task_tag,
2676+
};
27082677

27092678
memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
27102679
}
@@ -3008,13 +2977,6 @@ static int ufshcd_clear_cmd(struct ufs_hba *hba, u32 task_tag)
30082977
mask, ~mask, 1000, 1000);
30092978
}
30102979

3011-
static int
3012-
ufshcd_check_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
3013-
{
3014-
return ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr) >>
3015-
UPIU_RSP_CODE_OFFSET;
3016-
}
3017-
30182980
/**
30192981
* ufshcd_dev_cmd_completion() - handles device management command responses
30202982
* @hba: per adapter instance
@@ -3039,11 +3001,13 @@ ufshcd_dev_cmd_completion(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
30393001
__func__, resp);
30403002
}
30413003
break;
3042-
case UPIU_TRANSACTION_QUERY_RSP:
3043-
err = ufshcd_check_query_response(hba, lrbp);
3044-
if (!err)
3004+
case UPIU_TRANSACTION_QUERY_RSP: {
3005+
u8 response = lrbp->ucd_rsp_ptr->header.response;
3006+
3007+
if (response == 0)
30453008
err = ufshcd_copy_query_response(hba, lrbp);
30463009
break;
3010+
}
30473011
case UPIU_TRANSACTION_REJECT_UPIU:
30483012
/* TODO: handle Reject UPIU Response */
30493013
err = -EPERM;
@@ -5244,7 +5208,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp,
52445208
u8 upiu_flags;
52455209
u32 resid;
52465210

5247-
upiu_flags = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_0) >> 16;
5211+
upiu_flags = lrbp->ucd_rsp_ptr->header.flags;
52485212
resid = be32_to_cpu(lrbp->ucd_rsp_ptr->sr.residual_transfer_count);
52495213
/*
52505214
* 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,
52575221
ocs = ufshcd_get_tr_ocs(lrbp, cqe);
52585222

52595223
if (hba->quirks & UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR) {
5260-
if (be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_1) &
5261-
MASK_RSP_UPIU_RESULT)
5224+
if (lrbp->ucd_rsp_ptr->header.response ||
5225+
lrbp->ucd_rsp_ptr->header.status)
52625226
ocs = OCS_SUCCESS;
52635227
}
52645228

@@ -5267,17 +5231,11 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp,
52675231
hba->ufs_stats.last_hibern8_exit_tstamp = ktime_set(0, 0);
52685232
switch (ufshcd_get_req_rsp(lrbp->ucd_rsp_ptr)) {
52695233
case UPIU_TRANSACTION_RESPONSE:
5270-
/*
5271-
* get the response UPIU result to extract
5272-
* the SCSI command status
5273-
*/
5274-
result = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr);
5275-
52765234
/*
52775235
* get the result based on SCSI status response
52785236
* to notify the SCSI midlayer of the command status
52795237
*/
5280-
scsi_status = result & MASK_SCSI_STATUS;
5238+
scsi_status = lrbp->ucd_rsp_ptr->header.status;
52815239
result = ufshcd_scsi_cmd_status(lrbp, scsi_status);
52825240

52835241
/*
@@ -6967,7 +6925,7 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
69676925
WARN_ONCE(task_tag < 0 || task_tag >= hba->nutmrs, "Invalid tag %d\n",
69686926
task_tag);
69696927
hba->tmf_rqs[req->tag] = req;
6970-
treq->upiu_req.req_header.dword_0 |= cpu_to_be32(task_tag);
6928+
treq->upiu_req.req_header.task_tag = task_tag;
69716929

69726930
memcpy(hba->utmrdl_base_addr + task_tag, treq, sizeof(*treq));
69736931
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,
70346992
treq.header.ocs = OCS_INVALID_COMMAND_STATUS;
70356993

70366994
/* Configure task request UPIU */
7037-
treq.upiu_req.req_header.dword_0 = cpu_to_be32(lun_id << 8) |
7038-
cpu_to_be32(UPIU_TRANSACTION_TASK_REQ << 24);
7039-
treq.upiu_req.req_header.dword_1 = cpu_to_be32(tm_function << 16);
6995+
treq.upiu_req.req_header.transaction_code = UPIU_TRANSACTION_TASK_REQ;
6996+
treq.upiu_req.req_header.lun = lun_id;
6997+
treq.upiu_req.req_header.tm_function = tm_function;
70406998

70416999
/*
70427000
* 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,
71107068
lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE;
71117069

71127070
/* update the task tag in the request upiu */
7113-
req_upiu->header.dword_0 |= cpu_to_be32(tag);
7071+
req_upiu->header.task_tag = tag;
71147072

71157073
ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE, 0);
71167074

@@ -7143,8 +7101,8 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
71437101
memcpy(rsp_upiu, lrbp->ucd_rsp_ptr, sizeof(*rsp_upiu));
71447102
if (desc_buff && desc_op == UPIU_QUERY_OPCODE_READ_DESC) {
71457103
u8 *descp = (u8 *)lrbp->ucd_rsp_ptr + sizeof(*rsp_upiu);
7146-
u16 resp_len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) &
7147-
MASK_QUERY_DATA_SEG_LEN;
7104+
u16 resp_len = be16_to_cpu(lrbp->ucd_rsp_ptr->header
7105+
.data_segment_length);
71487106

71497107
if (*buff_len >= resp_len) {
71507108
memcpy(desc_buff, descp, resp_len);
@@ -7192,7 +7150,7 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
71927150
enum dev_cmd_type cmd_type = DEV_CMD_TYPE_QUERY;
71937151
struct utp_task_req_desc treq = { };
71947152
enum utp_ocs ocs_value;
7195-
u8 tm_f = be32_to_cpu(req_upiu->header.dword_1) >> 16 & MASK_TM_FUNC;
7153+
u8 tm_f = req_upiu->header.tm_function;
71967154

71977155
switch (msgcode) {
71987156
case UPIU_TRANSACTION_NOP_OUT:
@@ -7284,7 +7242,9 @@ int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *r
72847242
ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, dir, 2);
72857243

72867244
/* update the task tag and LUN in the request upiu */
7287-
req_upiu->header.dword_0 |= cpu_to_be32(upiu_flags << 16 | UFS_UPIU_RPMB_WLUN << 8 | tag);
7245+
req_upiu->header.flags = upiu_flags;
7246+
req_upiu->header.lun = UFS_UPIU_RPMB_WLUN;
7247+
req_upiu->header.task_tag = tag;
72887248

72897249
/* copy the UPIU(contains CDB) request as it is */
72907250
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
73067266
/* Just copy the upiu response as it is */
73077267
memcpy(rsp_upiu, lrbp->ucd_rsp_ptr, sizeof(*rsp_upiu));
73087268
/* Get the response UPIU result */
7309-
result = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr);
7269+
result = (lrbp->ucd_rsp_ptr->header.response << 8) |
7270+
lrbp->ucd_rsp_ptr->header.status;
73107271

7311-
ehs_len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) >> 24;
7272+
ehs_len = lrbp->ucd_rsp_ptr->header.ehs_length;
73127273
/*
73137274
* Since the bLength in EHS indicates the total size of the EHS Header and EHS Data
73147275
* 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)
1059410555
BUILD_BUG_ON(((__le32 *)&(struct request_desc_header){
1059510556
.dunu = cpu_to_le32(0xbadcafe)})[3] !=
1059610557
cpu_to_le32(0xbadcafe));
10558+
10559+
BUILD_BUG_ON(((u8 *)&(struct utp_upiu_header){
10560+
.iid = 0xf })[4] != 0xf0);
10561+
10562+
BUILD_BUG_ON(((u8 *)&(struct utp_upiu_header){
10563+
.command_set_type = 0xf })[4] != 0xf);
1059710564
}
1059810565

1059910566
/*

include/uapi/scsi/scsi_bsg_ufs.h

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#ifndef SCSI_BSG_UFS_H
99
#define SCSI_BSG_UFS_H
1010

11+
#include <asm/byteorder.h>
1112
#include <linux/types.h>
1213
/*
1314
* This file intended to be included by both kernel and user space
@@ -40,11 +41,56 @@ enum ufs_rpmb_op_type {
4041
* @dword_0: UPIU header DW-0
4142
* @dword_1: UPIU header DW-1
4243
* @dword_2: UPIU header DW-2
44+
*
45+
* @transaction_code: Type of request or response. See also enum
46+
* upiu_request_transaction and enum upiu_response_transaction.
47+
* @flags: UPIU flags. The meaning of individual flags depends on the
48+
* transaction code.
49+
* @lun: Logical unit number.
50+
* @task_tag: Task tag.
51+
* @iid: Initiator ID.
52+
* @command_set_type: 0 for SCSI command set; 1 for UFS specific.
53+
* @tm_function: Task management function in case of a task management request
54+
* UPIU.
55+
* @query_function: Query function in case of a query request UPIU.
56+
* @response: 0 for success; 1 for failure.
57+
* @status: SCSI status if this is the header of a response to a SCSI command.
58+
* @ehs_length: EHS length in units of 32 bytes.
59+
* @device_information:
60+
* @data_segment_length: data segment length.
4361
*/
4462
struct utp_upiu_header {
45-
__be32 dword_0;
46-
__be32 dword_1;
47-
__be32 dword_2;
63+
union {
64+
struct {
65+
__be32 dword_0;
66+
__be32 dword_1;
67+
__be32 dword_2;
68+
};
69+
struct {
70+
__u8 transaction_code;
71+
__u8 flags;
72+
__u8 lun;
73+
__u8 task_tag;
74+
#if defined(__BIG_ENDIAN)
75+
__u8 iid: 4;
76+
__u8 command_set_type: 4;
77+
#elif defined(__LITTLE_ENDIAN)
78+
__u8 command_set_type: 4;
79+
__u8 iid: 4;
80+
#else
81+
#error
82+
#endif
83+
union {
84+
__u8 tm_function;
85+
__u8 query_function;
86+
};
87+
__u8 response;
88+
__u8 status;
89+
__u8 ehs_length;
90+
__u8 device_information;
91+
__be16 data_segment_length;
92+
};
93+
};
4894
};
4995

5096
/**

0 commit comments

Comments
 (0)