1 // SPDX-License-Identifier: GPL-2.0
3 * bsg endpoint that supports UPIUs
5 * Copyright (C) 2018 Western Digital Corporation
9 static int ufs_bsg_get_query_desc_size(struct ufs_hba
*hba
, int *desc_len
,
10 struct utp_upiu_query
*qr
)
12 int desc_size
= be16_to_cpu(qr
->length
);
13 int desc_id
= qr
->idn
;
19 ret
= ufshcd_map_desc_id_to_length(hba
, desc_id
, desc_len
);
20 if (ret
|| !*desc_len
)
23 *desc_len
= min_t(int, *desc_len
, desc_size
);
28 static int ufs_bsg_verify_query_size(struct ufs_hba
*hba
,
29 unsigned int request_len
,
30 unsigned int reply_len
)
32 int min_req_len
= sizeof(struct ufs_bsg_request
);
33 int min_rsp_len
= sizeof(struct ufs_bsg_reply
);
35 if (min_req_len
> request_len
|| min_rsp_len
> reply_len
) {
36 dev_err(hba
->dev
, "not enough space assigned\n");
43 static int ufs_bsg_alloc_desc_buffer(struct ufs_hba
*hba
, struct bsg_job
*job
,
44 uint8_t **desc_buff
, int *desc_len
,
45 enum query_opcode desc_op
)
47 struct ufs_bsg_request
*bsg_request
= job
->request
;
48 struct utp_upiu_query
*qr
;
51 if (desc_op
!= UPIU_QUERY_OPCODE_WRITE_DESC
&&
52 desc_op
!= UPIU_QUERY_OPCODE_READ_DESC
)
55 qr
= &bsg_request
->upiu_req
.qr
;
56 if (ufs_bsg_get_query_desc_size(hba
, desc_len
, qr
)) {
57 dev_err(hba
->dev
, "Illegal desc size\n");
61 if (*desc_len
> job
->request_payload
.payload_len
) {
62 dev_err(hba
->dev
, "Illegal desc size\n");
66 descp
= kzalloc(*desc_len
, GFP_KERNEL
);
70 if (desc_op
== UPIU_QUERY_OPCODE_WRITE_DESC
)
71 sg_copy_to_buffer(job
->request_payload
.sg_list
,
72 job
->request_payload
.sg_cnt
, descp
,
81 static int ufs_bsg_request(struct bsg_job
*job
)
83 struct ufs_bsg_request
*bsg_request
= job
->request
;
84 struct ufs_bsg_reply
*bsg_reply
= job
->reply
;
85 struct ufs_hba
*hba
= shost_priv(dev_to_shost(job
->dev
->parent
));
86 unsigned int req_len
= job
->request_len
;
87 unsigned int reply_len
= job
->reply_len
;
88 struct uic_command uc
= {};
90 uint8_t *desc_buff
= NULL
;
92 enum query_opcode desc_op
= UPIU_QUERY_OPCODE_NOP
;
95 ret
= ufs_bsg_verify_query_size(hba
, req_len
, reply_len
);
99 bsg_reply
->reply_payload_rcv_len
= 0;
101 pm_runtime_get_sync(hba
->dev
);
103 msgcode
= bsg_request
->msgcode
;
105 case UPIU_TRANSACTION_QUERY_REQ
:
106 desc_op
= bsg_request
->upiu_req
.qr
.opcode
;
107 ret
= ufs_bsg_alloc_desc_buffer(hba
, job
, &desc_buff
,
110 pm_runtime_put_sync(hba
->dev
);
115 case UPIU_TRANSACTION_NOP_OUT
:
116 case UPIU_TRANSACTION_TASK_REQ
:
117 ret
= ufshcd_exec_raw_upiu_cmd(hba
, &bsg_request
->upiu_req
,
118 &bsg_reply
->upiu_rsp
, msgcode
,
119 desc_buff
, &desc_len
, desc_op
);
122 "exe raw upiu: error code %d\n", ret
);
125 case UPIU_TRANSACTION_UIC_CMD
:
126 memcpy(&uc
, &bsg_request
->upiu_req
.uc
, UIC_CMD_SIZE
);
127 ret
= ufshcd_send_uic_cmd(hba
, &uc
);
130 "send uic cmd: error code %d\n", ret
);
132 memcpy(&bsg_reply
->upiu_rsp
.uc
, &uc
, UIC_CMD_SIZE
);
137 dev_err(hba
->dev
, "unsupported msgcode 0x%x\n", msgcode
);
142 pm_runtime_put_sync(hba
->dev
);
147 if (desc_op
== UPIU_QUERY_OPCODE_READ_DESC
&& desc_len
)
148 bsg_reply
->reply_payload_rcv_len
=
149 sg_copy_from_buffer(job
->request_payload
.sg_list
,
150 job
->request_payload
.sg_cnt
,
151 desc_buff
, desc_len
);
156 bsg_reply
->result
= ret
;
157 job
->reply_len
= sizeof(struct ufs_bsg_reply
);
158 /* complete the job here only if no error */
160 bsg_job_done(job
, ret
, bsg_reply
->reply_payload_rcv_len
);
166 * ufs_bsg_remove - detach and remove the added ufs-bsg node
167 * @hba: per adapter object
169 * Should be called when unloading the driver.
171 void ufs_bsg_remove(struct ufs_hba
*hba
)
173 struct device
*bsg_dev
= &hba
->bsg_dev
;
178 bsg_remove_queue(hba
->bsg_queue
);
184 static inline void ufs_bsg_node_release(struct device
*dev
)
186 put_device(dev
->parent
);
190 * ufs_bsg_probe - Add ufs bsg device node
191 * @hba: per adapter object
193 * Called during initial loading of the driver, and before scsi_scan_host.
195 int ufs_bsg_probe(struct ufs_hba
*hba
)
197 struct device
*bsg_dev
= &hba
->bsg_dev
;
198 struct Scsi_Host
*shost
= hba
->host
;
199 struct device
*parent
= &shost
->shost_gendev
;
200 struct request_queue
*q
;
203 device_initialize(bsg_dev
);
205 bsg_dev
->parent
= get_device(parent
);
206 bsg_dev
->release
= ufs_bsg_node_release
;
208 dev_set_name(bsg_dev
, "ufs-bsg%u", shost
->host_no
);
210 ret
= device_add(bsg_dev
);
214 q
= bsg_setup_queue(bsg_dev
, dev_name(bsg_dev
), ufs_bsg_request
, NULL
, 0);
225 dev_err(bsg_dev
, "fail to initialize a bsg dev %d\n", shost
->host_no
);