Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * BSG helper library
4 : : *
5 : : * Copyright (C) 2008 James Smart, Emulex Corporation
6 : : * Copyright (C) 2011 Red Hat, Inc. All rights reserved.
7 : : * Copyright (C) 2011 Mike Christie
8 : : */
9 : : #include <linux/slab.h>
10 : : #include <linux/blk-mq.h>
11 : : #include <linux/delay.h>
12 : : #include <linux/scatterlist.h>
13 : : #include <linux/bsg-lib.h>
14 : : #include <linux/export.h>
15 : : #include <scsi/scsi_cmnd.h>
16 : : #include <scsi/sg.h>
17 : :
18 : : #define uptr64(val) ((void __user *)(uintptr_t)(val))
19 : :
20 : : struct bsg_set {
21 : : struct blk_mq_tag_set tag_set;
22 : : bsg_job_fn *job_fn;
23 : : bsg_timeout_fn *timeout_fn;
24 : : };
25 : :
26 : 0 : static int bsg_transport_check_proto(struct sg_io_v4 *hdr)
27 : : {
28 [ # # # # ]: 0 : if (hdr->protocol != BSG_PROTOCOL_SCSI ||
29 : 0 : hdr->subprotocol != BSG_SUB_PROTOCOL_SCSI_TRANSPORT)
30 : : return -EINVAL;
31 [ # # ]: 0 : if (!capable(CAP_SYS_RAWIO))
32 : : return -EPERM;
33 : 0 : return 0;
34 : : }
35 : :
36 : 0 : static int bsg_transport_fill_hdr(struct request *rq, struct sg_io_v4 *hdr,
37 : : fmode_t mode)
38 : : {
39 : : struct bsg_job *job = blk_mq_rq_to_pdu(rq);
40 : : int ret;
41 : :
42 : 0 : job->request_len = hdr->request_len;
43 : 0 : job->request = memdup_user(uptr64(hdr->request), hdr->request_len);
44 [ # # ]: 0 : if (IS_ERR(job->request))
45 : 0 : return PTR_ERR(job->request);
46 : :
47 [ # # # # ]: 0 : if (hdr->dout_xfer_len && hdr->din_xfer_len) {
48 : 0 : job->bidi_rq = blk_get_request(rq->q, REQ_OP_SCSI_IN, 0);
49 [ # # ]: 0 : if (IS_ERR(job->bidi_rq)) {
50 : : ret = PTR_ERR(job->bidi_rq);
51 : 0 : goto out;
52 : : }
53 : :
54 : 0 : ret = blk_rq_map_user(rq->q, job->bidi_rq, NULL,
55 : 0 : uptr64(hdr->din_xferp), hdr->din_xfer_len,
56 : : GFP_KERNEL);
57 [ # # ]: 0 : if (ret)
58 : : goto out_free_bidi_rq;
59 : :
60 : 0 : job->bidi_bio = job->bidi_rq->bio;
61 : : } else {
62 : 0 : job->bidi_rq = NULL;
63 : 0 : job->bidi_bio = NULL;
64 : : }
65 : :
66 : : return 0;
67 : :
68 : : out_free_bidi_rq:
69 [ # # ]: 0 : if (job->bidi_rq)
70 : 0 : blk_put_request(job->bidi_rq);
71 : : out:
72 : 0 : kfree(job->request);
73 : 0 : return ret;
74 : : }
75 : :
76 : 0 : static int bsg_transport_complete_rq(struct request *rq, struct sg_io_v4 *hdr)
77 : : {
78 : : struct bsg_job *job = blk_mq_rq_to_pdu(rq);
79 : : int ret = 0;
80 : :
81 : : /*
82 : : * The assignments below don't make much sense, but are kept for
83 : : * bug by bug backwards compatibility:
84 : : */
85 : 0 : hdr->device_status = job->result & 0xff;
86 : 0 : hdr->transport_status = host_byte(job->result);
87 : 0 : hdr->driver_status = driver_byte(job->result);
88 : 0 : hdr->info = 0;
89 [ # # # # : 0 : if (hdr->device_status || hdr->transport_status || hdr->driver_status)
# # ]
90 : 0 : hdr->info |= SG_INFO_CHECK;
91 : 0 : hdr->response_len = 0;
92 : :
93 [ # # ]: 0 : if (job->result < 0) {
94 : : /* we're only returning the result field in the reply */
95 : 0 : job->reply_len = sizeof(u32);
96 : : ret = job->result;
97 : : }
98 : :
99 [ # # # # ]: 0 : if (job->reply_len && hdr->response) {
100 : 0 : int len = min(hdr->max_response_len, job->reply_len);
101 : :
102 [ # # ]: 0 : if (copy_to_user(uptr64(hdr->response), job->reply, len))
103 : : ret = -EFAULT;
104 : : else
105 : 0 : hdr->response_len = len;
106 : : }
107 : :
108 : : /* we assume all request payload was transferred, residual == 0 */
109 : 0 : hdr->dout_resid = 0;
110 : :
111 [ # # ]: 0 : if (job->bidi_rq) {
112 : 0 : unsigned int rsp_len = job->reply_payload.payload_len;
113 : :
114 [ # # # # ]: 0 : if (WARN_ON(job->reply_payload_rcv_len > rsp_len))
115 : 0 : hdr->din_resid = 0;
116 : : else
117 : 0 : hdr->din_resid = rsp_len - job->reply_payload_rcv_len;
118 : : } else {
119 : 0 : hdr->din_resid = 0;
120 : : }
121 : :
122 : 0 : return ret;
123 : : }
124 : :
125 : 0 : static void bsg_transport_free_rq(struct request *rq)
126 : : {
127 : : struct bsg_job *job = blk_mq_rq_to_pdu(rq);
128 : :
129 [ # # ]: 0 : if (job->bidi_rq) {
130 : 0 : blk_rq_unmap_user(job->bidi_bio);
131 : 0 : blk_put_request(job->bidi_rq);
132 : : }
133 : :
134 : 0 : kfree(job->request);
135 : 0 : }
136 : :
137 : : static const struct bsg_ops bsg_transport_ops = {
138 : : .check_proto = bsg_transport_check_proto,
139 : : .fill_hdr = bsg_transport_fill_hdr,
140 : : .complete_rq = bsg_transport_complete_rq,
141 : : .free_rq = bsg_transport_free_rq,
142 : : };
143 : :
144 : : /**
145 : : * bsg_teardown_job - routine to teardown a bsg job
146 : : * @kref: kref inside bsg_job that is to be torn down
147 : : */
148 : 0 : static void bsg_teardown_job(struct kref *kref)
149 : : {
150 : : struct bsg_job *job = container_of(kref, struct bsg_job, kref);
151 : : struct request *rq = blk_mq_rq_from_pdu(job);
152 : :
153 : 0 : put_device(job->dev); /* release reference for the request */
154 : :
155 : 0 : kfree(job->request_payload.sg_list);
156 : 0 : kfree(job->reply_payload.sg_list);
157 : :
158 : 0 : blk_mq_end_request(rq, BLK_STS_OK);
159 : 0 : }
160 : :
161 : 0 : void bsg_job_put(struct bsg_job *job)
162 : : {
163 : 0 : kref_put(&job->kref, bsg_teardown_job);
164 : 0 : }
165 : : EXPORT_SYMBOL_GPL(bsg_job_put);
166 : :
167 : 0 : int bsg_job_get(struct bsg_job *job)
168 : : {
169 : 0 : return kref_get_unless_zero(&job->kref);
170 : : }
171 : : EXPORT_SYMBOL_GPL(bsg_job_get);
172 : :
173 : : /**
174 : : * bsg_job_done - completion routine for bsg requests
175 : : * @job: bsg_job that is complete
176 : : * @result: job reply result
177 : : * @reply_payload_rcv_len: length of payload recvd
178 : : *
179 : : * The LLD should call this when the bsg job has completed.
180 : : */
181 : 0 : void bsg_job_done(struct bsg_job *job, int result,
182 : : unsigned int reply_payload_rcv_len)
183 : : {
184 : 0 : job->result = result;
185 : 0 : job->reply_payload_rcv_len = reply_payload_rcv_len;
186 : 0 : blk_mq_complete_request(blk_mq_rq_from_pdu(job));
187 : 0 : }
188 : : EXPORT_SYMBOL_GPL(bsg_job_done);
189 : :
190 : : /**
191 : : * bsg_complete - softirq done routine for destroying the bsg requests
192 : : * @rq: BSG request that holds the job to be destroyed
193 : : */
194 : 0 : static void bsg_complete(struct request *rq)
195 : : {
196 : : struct bsg_job *job = blk_mq_rq_to_pdu(rq);
197 : :
198 : : bsg_job_put(job);
199 : 0 : }
200 : :
201 : 0 : static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
202 : : {
203 : 0 : size_t sz = (sizeof(struct scatterlist) * req->nr_phys_segments);
204 : :
205 [ # # ]: 0 : BUG_ON(!req->nr_phys_segments);
206 : :
207 : 0 : buf->sg_list = kzalloc(sz, GFP_KERNEL);
208 [ # # ]: 0 : if (!buf->sg_list)
209 : : return -ENOMEM;
210 : 0 : sg_init_table(buf->sg_list, req->nr_phys_segments);
211 : 0 : buf->sg_cnt = blk_rq_map_sg(req->q, req, buf->sg_list);
212 : 0 : buf->payload_len = blk_rq_bytes(req);
213 : 0 : return 0;
214 : : }
215 : :
216 : : /**
217 : : * bsg_prepare_job - create the bsg_job structure for the bsg request
218 : : * @dev: device that is being sent the bsg request
219 : : * @req: BSG request that needs a job structure
220 : : */
221 : 0 : static bool bsg_prepare_job(struct device *dev, struct request *req)
222 : : {
223 : : struct bsg_job *job = blk_mq_rq_to_pdu(req);
224 : : int ret;
225 : :
226 : 0 : job->timeout = req->timeout;
227 : :
228 [ # # ]: 0 : if (req->bio) {
229 : 0 : ret = bsg_map_buffer(&job->request_payload, req);
230 [ # # ]: 0 : if (ret)
231 : : goto failjob_rls_job;
232 : : }
233 [ # # ]: 0 : if (job->bidi_rq) {
234 : 0 : ret = bsg_map_buffer(&job->reply_payload, job->bidi_rq);
235 [ # # ]: 0 : if (ret)
236 : : goto failjob_rls_rqst_payload;
237 : : }
238 : 0 : job->dev = dev;
239 : : /* take a reference for the request */
240 : 0 : get_device(job->dev);
241 : : kref_init(&job->kref);
242 : 0 : return true;
243 : :
244 : : failjob_rls_rqst_payload:
245 : 0 : kfree(job->request_payload.sg_list);
246 : : failjob_rls_job:
247 : 0 : job->result = -ENOMEM;
248 : 0 : return false;
249 : : }
250 : :
251 : : /**
252 : : * bsg_queue_rq - generic handler for bsg requests
253 : : * @hctx: hardware queue
254 : : * @bd: queue data
255 : : *
256 : : * On error the create_bsg_job function should return a -Exyz error value
257 : : * that will be set to ->result.
258 : : *
259 : : * Drivers/subsys should pass this to the queue init function.
260 : : */
261 : 0 : static blk_status_t bsg_queue_rq(struct blk_mq_hw_ctx *hctx,
262 : : const struct blk_mq_queue_data *bd)
263 : : {
264 : 0 : struct request_queue *q = hctx->queue;
265 : 0 : struct device *dev = q->queuedata;
266 : 0 : struct request *req = bd->rq;
267 : : struct bsg_set *bset =
268 : 0 : container_of(q->tag_set, struct bsg_set, tag_set);
269 : : blk_status_t sts = BLK_STS_IOERR;
270 : : int ret;
271 : :
272 : 0 : blk_mq_start_request(req);
273 : :
274 [ # # ]: 0 : if (!get_device(dev))
275 : : return BLK_STS_IOERR;
276 : :
277 [ # # ]: 0 : if (!bsg_prepare_job(dev, req))
278 : : goto out;
279 : :
280 : 0 : ret = bset->job_fn(blk_mq_rq_to_pdu(req));
281 [ # # ]: 0 : if (!ret)
282 : : sts = BLK_STS_OK;
283 : :
284 : : out:
285 : 0 : put_device(dev);
286 : 0 : return sts;
287 : : }
288 : :
289 : : /* called right after the request is allocated for the request_queue */
290 : 0 : static int bsg_init_rq(struct blk_mq_tag_set *set, struct request *req,
291 : : unsigned int hctx_idx, unsigned int numa_node)
292 : : {
293 : : struct bsg_job *job = blk_mq_rq_to_pdu(req);
294 : :
295 : 0 : job->reply = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
296 [ # # ]: 0 : if (!job->reply)
297 : : return -ENOMEM;
298 : 0 : return 0;
299 : : }
300 : :
301 : : /* called right before the request is given to the request_queue user */
302 : 0 : static void bsg_initialize_rq(struct request *req)
303 : : {
304 : : struct bsg_job *job = blk_mq_rq_to_pdu(req);
305 : 0 : void *reply = job->reply;
306 : :
307 : 0 : memset(job, 0, sizeof(*job));
308 : 0 : job->reply = reply;
309 : 0 : job->reply_len = SCSI_SENSE_BUFFERSIZE;
310 : 0 : job->dd_data = job + 1;
311 : 0 : }
312 : :
313 : 0 : static void bsg_exit_rq(struct blk_mq_tag_set *set, struct request *req,
314 : : unsigned int hctx_idx)
315 : : {
316 : : struct bsg_job *job = blk_mq_rq_to_pdu(req);
317 : :
318 : 0 : kfree(job->reply);
319 : 0 : }
320 : :
321 : 0 : void bsg_remove_queue(struct request_queue *q)
322 : : {
323 [ # # ]: 0 : if (q) {
324 : : struct bsg_set *bset =
325 : 0 : container_of(q->tag_set, struct bsg_set, tag_set);
326 : :
327 : 0 : bsg_unregister_queue(q);
328 : 0 : blk_cleanup_queue(q);
329 : 0 : blk_mq_free_tag_set(&bset->tag_set);
330 : 0 : kfree(bset);
331 : : }
332 : 0 : }
333 : : EXPORT_SYMBOL_GPL(bsg_remove_queue);
334 : :
335 : 0 : static enum blk_eh_timer_return bsg_timeout(struct request *rq, bool reserved)
336 : : {
337 : : struct bsg_set *bset =
338 : 0 : container_of(rq->q->tag_set, struct bsg_set, tag_set);
339 : :
340 [ # # ]: 0 : if (!bset->timeout_fn)
341 : : return BLK_EH_DONE;
342 : 0 : return bset->timeout_fn(rq);
343 : : }
344 : :
345 : : static const struct blk_mq_ops bsg_mq_ops = {
346 : : .queue_rq = bsg_queue_rq,
347 : : .init_request = bsg_init_rq,
348 : : .exit_request = bsg_exit_rq,
349 : : .initialize_rq_fn = bsg_initialize_rq,
350 : : .complete = bsg_complete,
351 : : .timeout = bsg_timeout,
352 : : };
353 : :
354 : : /**
355 : : * bsg_setup_queue - Create and add the bsg hooks so we can receive requests
356 : : * @dev: device to attach bsg device to
357 : : * @name: device to give bsg device
358 : : * @job_fn: bsg job handler
359 : : * @timeout: timeout handler function pointer
360 : : * @dd_job_size: size of LLD data needed for each job
361 : : */
362 : 0 : struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
363 : : bsg_job_fn *job_fn, bsg_timeout_fn *timeout, int dd_job_size)
364 : : {
365 : : struct bsg_set *bset;
366 : : struct blk_mq_tag_set *set;
367 : : struct request_queue *q;
368 : : int ret = -ENOMEM;
369 : :
370 : 0 : bset = kzalloc(sizeof(*bset), GFP_KERNEL);
371 [ # # ]: 0 : if (!bset)
372 : : return ERR_PTR(-ENOMEM);
373 : :
374 : 0 : bset->job_fn = job_fn;
375 : 0 : bset->timeout_fn = timeout;
376 : :
377 : 0 : set = &bset->tag_set;
378 : 0 : set->ops = &bsg_mq_ops,
379 : 0 : set->nr_hw_queues = 1;
380 : 0 : set->queue_depth = 128;
381 : 0 : set->numa_node = NUMA_NO_NODE;
382 : 0 : set->cmd_size = sizeof(struct bsg_job) + dd_job_size;
383 : 0 : set->flags = BLK_MQ_F_NO_SCHED | BLK_MQ_F_BLOCKING;
384 [ # # ]: 0 : if (blk_mq_alloc_tag_set(set))
385 : : goto out_tag_set;
386 : :
387 : 0 : q = blk_mq_init_queue(set);
388 [ # # ]: 0 : if (IS_ERR(q)) {
389 : : ret = PTR_ERR(q);
390 : 0 : goto out_queue;
391 : : }
392 : :
393 : 0 : q->queuedata = dev;
394 : 0 : blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT);
395 : :
396 : 0 : ret = bsg_register_queue(q, dev, name, &bsg_transport_ops);
397 [ # # ]: 0 : if (ret) {
398 : 0 : printk(KERN_ERR "%s: bsg interface failed to "
399 : : "initialize - register queue\n", dev->kobj.name);
400 : : goto out_cleanup_queue;
401 : : }
402 : :
403 : : return q;
404 : : out_cleanup_queue:
405 : 0 : blk_cleanup_queue(q);
406 : : out_queue:
407 : 0 : blk_mq_free_tag_set(set);
408 : : out_tag_set:
409 : 0 : kfree(bset);
410 : 0 : return ERR_PTR(ret);
411 : : }
412 : : EXPORT_SYMBOL_GPL(bsg_setup_queue);
|