summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvri Altman <avri.altman@wdc.com>2019-02-20 02:11:12 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2019-02-27 08:56:32 -0500
commit4eaa329e331343dd64996297583f2eee7d215e2a (patch)
tree7e6a2cffd23c310a9077ba89b295f90928688eb6
parente9cb9655f84137c020496572ac6e43beafe0b4a7 (diff)
scsi: ufs-bsg: Change the calling convention for write descriptor
When we had a write descriptor query upiu, we appended the descriptor right after the bsg request. This was fine as the bsg driver allows to allocate whatever buffer we needed in its job request. Still, the proper way to deliver payload, however small (we only write config descriptors of 144 bytes), is by using the job request payload data buffer. So change this ABI now, while ufs-bsg is still new, and nobody is actually using it. Signed-off-by: Avri Altman <avri.altman@wdc.com> Reviewed-by: Evan Green <evgreen@chromium.org> Reviewed-by: Bean Huo <beanhuo@micron.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--Documentation/scsi/ufs.txt6
-rw-r--r--drivers/scsi/ufs/ufs_bsg.c47
2 files changed, 32 insertions, 21 deletions
diff --git a/Documentation/scsi/ufs.txt b/Documentation/scsi/ufs.txt
index 520b5b033256..78fe7cbfae48 100644
--- a/Documentation/scsi/ufs.txt
+++ b/Documentation/scsi/ufs.txt
@@ -147,6 +147,12 @@ send SG_IO with the applicable sg_io_v4:
147 io_hdr_v4.max_response_len = reply_len; 147 io_hdr_v4.max_response_len = reply_len;
148 io_hdr_v4.request_len = request_len; 148 io_hdr_v4.request_len = request_len;
149 io_hdr_v4.request = (__u64)request_upiu; 149 io_hdr_v4.request = (__u64)request_upiu;
150 if (dir == SG_DXFER_TO_DEV) {
151 io_hdr_v4.dout_xfer_len = (uint32_t)byte_cnt;
152 io_hdr_v4.dout_xferp = (uintptr_t)(__u64)buff;
153 }
154
155If you wish to write a descriptor, use the dout_xferp sg_io_v4.
150 156
151UFS Specifications can be found at, 157UFS Specifications can be found at,
152UFS - http://www.jedec.org/sites/default/files/docs/JESD220.pdf 158UFS - http://www.jedec.org/sites/default/files/docs/JESD220.pdf
diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index 775bb4e5e36e..2fd0769efafe 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -27,15 +27,11 @@ static int ufs_bsg_get_query_desc_size(struct ufs_hba *hba, int *desc_len,
27 27
28static int ufs_bsg_verify_query_size(struct ufs_hba *hba, 28static int ufs_bsg_verify_query_size(struct ufs_hba *hba,
29 unsigned int request_len, 29 unsigned int request_len,
30 unsigned int reply_len, 30 unsigned int reply_len)
31 int desc_len, enum query_opcode desc_op)
32{ 31{
33 int min_req_len = sizeof(struct ufs_bsg_request); 32 int min_req_len = sizeof(struct ufs_bsg_request);
34 int min_rsp_len = sizeof(struct ufs_bsg_reply); 33 int min_rsp_len = sizeof(struct ufs_bsg_reply);
35 34
36 if (desc_op == UPIU_QUERY_OPCODE_WRITE_DESC)
37 min_req_len += desc_len;
38
39 if (min_req_len > request_len || min_rsp_len > reply_len) { 35 if (min_req_len > request_len || min_rsp_len > reply_len) {
40 dev_err(hba->dev, "not enough space assigned\n"); 36 dev_err(hba->dev, "not enough space assigned\n");
41 return -EINVAL; 37 return -EINVAL;
@@ -44,14 +40,13 @@ static int ufs_bsg_verify_query_size(struct ufs_hba *hba,
44 return 0; 40 return 0;
45} 41}
46 42
47static int ufs_bsg_verify_query_params(struct ufs_hba *hba, 43static int ufs_bsg_alloc_desc_buffer(struct ufs_hba *hba, struct bsg_job *job,
48 struct ufs_bsg_request *bsg_request, 44 uint8_t **desc_buff, int *desc_len,
49 unsigned int request_len, 45 enum query_opcode desc_op)
50 unsigned int reply_len,
51 uint8_t *desc_buff, int *desc_len,
52 enum query_opcode desc_op)
53{ 46{
47 struct ufs_bsg_request *bsg_request = job->request;
54 struct utp_upiu_query *qr; 48 struct utp_upiu_query *qr;
49 u8 *descp;
55 50
56 if (desc_op == UPIU_QUERY_OPCODE_READ_DESC) { 51 if (desc_op == UPIU_QUERY_OPCODE_READ_DESC) {
57 dev_err(hba->dev, "unsupported opcode %d\n", desc_op); 52 dev_err(hba->dev, "unsupported opcode %d\n", desc_op);
@@ -67,11 +62,19 @@ static int ufs_bsg_verify_query_params(struct ufs_hba *hba,
67 return -EINVAL; 62 return -EINVAL;
68 } 63 }
69 64
70 if (ufs_bsg_verify_query_size(hba, request_len, reply_len, *desc_len, 65 if (*desc_len > job->request_payload.payload_len) {
71 desc_op)) 66 dev_err(hba->dev, "Illegal desc size\n");
72 return -EINVAL; 67 return -EINVAL;
68 }
69
70 descp = kzalloc(*desc_len, GFP_KERNEL);
71 if (!descp)
72 return -ENOMEM;
73 73
74 desc_buff = (uint8_t *)(bsg_request + 1); 74 sg_copy_to_buffer(job->request_payload.sg_list,
75 job->request_payload.sg_cnt, descp, *desc_len);
76
77 *desc_buff = descp;
75 78
76out: 79out:
77 return 0; 80 return 0;
@@ -91,7 +94,7 @@ static int ufs_bsg_request(struct bsg_job *job)
91 enum query_opcode desc_op = UPIU_QUERY_OPCODE_NOP; 94 enum query_opcode desc_op = UPIU_QUERY_OPCODE_NOP;
92 int ret; 95 int ret;
93 96
94 ret = ufs_bsg_verify_query_size(hba, req_len, reply_len, 0, desc_op); 97 ret = ufs_bsg_verify_query_size(hba, req_len, reply_len);
95 if (ret) 98 if (ret)
96 goto out; 99 goto out;
97 100
@@ -101,9 +104,8 @@ static int ufs_bsg_request(struct bsg_job *job)
101 switch (msgcode) { 104 switch (msgcode) {
102 case UPIU_TRANSACTION_QUERY_REQ: 105 case UPIU_TRANSACTION_QUERY_REQ:
103 desc_op = bsg_request->upiu_req.qr.opcode; 106 desc_op = bsg_request->upiu_req.qr.opcode;
104 ret = ufs_bsg_verify_query_params(hba, bsg_request, req_len, 107 ret = ufs_bsg_alloc_desc_buffer(hba, job, &desc_buff,
105 reply_len, desc_buff, 108 &desc_len, desc_op);
106 &desc_len, desc_op);
107 if (ret) 109 if (ret)
108 goto out; 110 goto out;
109 111
@@ -135,11 +137,14 @@ static int ufs_bsg_request(struct bsg_job *job)
135 break; 137 break;
136 } 138 }
137 139
140 if (!desc_buff)
141 goto out;
142
143 kfree(desc_buff);
144
138out: 145out:
139 bsg_reply->result = ret; 146 bsg_reply->result = ret;
140 job->reply_len = sizeof(struct ufs_bsg_reply) + 147 job->reply_len = sizeof(struct ufs_bsg_reply);
141 bsg_reply->reply_payload_rcv_len;
142
143 bsg_job_done(job, ret, bsg_reply->reply_payload_rcv_len); 148 bsg_job_done(job, ret, bsg_reply->reply_payload_rcv_len);
144 149
145 return ret; 150 return ret;