Blame view

block/bsg-lib.c 9.82 KB
a497ee34a   Christoph Hellwig   block: switch all...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
aa387cc89   Mike Christie   block: add bsg he...
2
3
4
5
6
7
  /*
   *  BSG helper library
   *
   *  Copyright (C) 2008   James Smart, Emulex Corporation
   *  Copyright (C) 2011   Red Hat, Inc.  All rights reserved.
   *  Copyright (C) 2011   Mike Christie
aa387cc89   Mike Christie   block: add bsg he...
8
9
   */
  #include <linux/slab.h>
cd2f076f1   Jens Axboe   bsg: convert to u...
10
  #include <linux/blk-mq.h>
aa387cc89   Mike Christie   block: add bsg he...
11
12
13
  #include <linux/delay.h>
  #include <linux/scatterlist.h>
  #include <linux/bsg-lib.h>
6adb1236b   Paul Gortmaker   block: Change mod...
14
  #include <linux/export.h>
aa387cc89   Mike Christie   block: add bsg he...
15
  #include <scsi/scsi_cmnd.h>
17cb960f2   Christoph Hellwig   bsg: split handli...
16
17
18
  #include <scsi/sg.h>
  
  #define uptr64(val) ((void __user *)(uintptr_t)(val))
1028e4b33   Jens Axboe   bsg: move bsg-lib...
19
20
21
22
23
  struct bsg_set {
  	struct blk_mq_tag_set	tag_set;
  	bsg_job_fn		*job_fn;
  	bsg_timeout_fn		*timeout_fn;
  };
17cb960f2   Christoph Hellwig   bsg: split handli...
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  static int bsg_transport_check_proto(struct sg_io_v4 *hdr)
  {
  	if (hdr->protocol != BSG_PROTOCOL_SCSI  ||
  	    hdr->subprotocol != BSG_SUB_PROTOCOL_SCSI_TRANSPORT)
  		return -EINVAL;
  	if (!capable(CAP_SYS_RAWIO))
  		return -EPERM;
  	return 0;
  }
  
  static int bsg_transport_fill_hdr(struct request *rq, struct sg_io_v4 *hdr,
  		fmode_t mode)
  {
  	struct bsg_job *job = blk_mq_rq_to_pdu(rq);
972248e91   Christoph Hellwig   scsi: bsg-lib: ha...
38
  	int ret;
17cb960f2   Christoph Hellwig   bsg: split handli...
39
40
41
  
  	job->request_len = hdr->request_len;
  	job->request = memdup_user(uptr64(hdr->request), hdr->request_len);
972248e91   Christoph Hellwig   scsi: bsg-lib: ha...
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  	if (IS_ERR(job->request))
  		return PTR_ERR(job->request);
  
  	if (hdr->dout_xfer_len && hdr->din_xfer_len) {
  		job->bidi_rq = blk_get_request(rq->q, REQ_OP_SCSI_IN, 0);
  		if (IS_ERR(job->bidi_rq)) {
  			ret = PTR_ERR(job->bidi_rq);
  			goto out;
  		}
  
  		ret = blk_rq_map_user(rq->q, job->bidi_rq, NULL,
  				uptr64(hdr->din_xferp), hdr->din_xfer_len,
  				GFP_KERNEL);
  		if (ret)
  			goto out_free_bidi_rq;
  
  		job->bidi_bio = job->bidi_rq->bio;
  	} else {
  		job->bidi_rq = NULL;
  		job->bidi_bio = NULL;
  	}
472554919   zhong jiang   block/bsg-lib: us...
63

972248e91   Christoph Hellwig   scsi: bsg-lib: ha...
64
65
66
67
68
69
70
71
  	return 0;
  
  out_free_bidi_rq:
  	if (job->bidi_rq)
  		blk_put_request(job->bidi_rq);
  out:
  	kfree(job->request);
  	return ret;
17cb960f2   Christoph Hellwig   bsg: split handli...
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
  }
  
  static int bsg_transport_complete_rq(struct request *rq, struct sg_io_v4 *hdr)
  {
  	struct bsg_job *job = blk_mq_rq_to_pdu(rq);
  	int ret = 0;
  
  	/*
  	 * The assignments below don't make much sense, but are kept for
  	 * bug by bug backwards compatibility:
  	 */
  	hdr->device_status = job->result & 0xff;
  	hdr->transport_status = host_byte(job->result);
  	hdr->driver_status = driver_byte(job->result);
  	hdr->info = 0;
  	if (hdr->device_status || hdr->transport_status || hdr->driver_status)
  		hdr->info |= SG_INFO_CHECK;
  	hdr->response_len = 0;
  
  	if (job->result < 0) {
  		/* we're only returning the result field in the reply */
  		job->reply_len = sizeof(u32);
  		ret = job->result;
  	}
  
  	if (job->reply_len && hdr->response) {
  		int len = min(hdr->max_response_len, job->reply_len);
  
  		if (copy_to_user(uptr64(hdr->response), job->reply, len))
  			ret = -EFAULT;
  		else
  			hdr->response_len = len;
  	}
  
  	/* we assume all request payload was transferred, residual == 0 */
  	hdr->dout_resid = 0;
972248e91   Christoph Hellwig   scsi: bsg-lib: ha...
108
  	if (job->bidi_rq) {
17cb960f2   Christoph Hellwig   bsg: split handli...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
  		unsigned int rsp_len = job->reply_payload.payload_len;
  
  		if (WARN_ON(job->reply_payload_rcv_len > rsp_len))
  			hdr->din_resid = 0;
  		else
  			hdr->din_resid = rsp_len - job->reply_payload_rcv_len;
  	} else {
  		hdr->din_resid = 0;
  	}
  
  	return ret;
  }
  
  static void bsg_transport_free_rq(struct request *rq)
  {
  	struct bsg_job *job = blk_mq_rq_to_pdu(rq);
972248e91   Christoph Hellwig   scsi: bsg-lib: ha...
125
126
127
128
  	if (job->bidi_rq) {
  		blk_rq_unmap_user(job->bidi_bio);
  		blk_put_request(job->bidi_rq);
  	}
17cb960f2   Christoph Hellwig   bsg: split handli...
129
130
131
132
133
134
135
136
137
  	kfree(job->request);
  }
  
  static const struct bsg_ops bsg_transport_ops = {
  	.check_proto		= bsg_transport_check_proto,
  	.fill_hdr		= bsg_transport_fill_hdr,
  	.complete_rq		= bsg_transport_complete_rq,
  	.free_rq		= bsg_transport_free_rq,
  };
aa387cc89   Mike Christie   block: add bsg he...
138
139
  
  /**
50b4d4855   Benjamin Block   bsg-lib: fix kern...
140
   * bsg_teardown_job - routine to teardown a bsg job
aa98192de   Bart Van Assche   block: Fix kernel...
141
   * @kref: kref inside bsg_job that is to be torn down
aa387cc89   Mike Christie   block: add bsg he...
142
   */
50b4d4855   Benjamin Block   bsg-lib: fix kern...
143
  static void bsg_teardown_job(struct kref *kref)
aa387cc89   Mike Christie   block: add bsg he...
144
  {
bf0f2d380   Johannes Thumshirn   block: add refere...
145
  	struct bsg_job *job = container_of(kref, struct bsg_job, kref);
ef6fa64f9   Christoph Hellwig   bsg-lib: remove b...
146
  	struct request *rq = blk_mq_rq_from_pdu(job);
c00da4c90   Johannes Thumshirn   scsi: fc: Use bsg...
147

aa387cc89   Mike Christie   block: add bsg he...
148
149
150
151
  	put_device(job->dev);	/* release reference for the request */
  
  	kfree(job->request_payload.sg_list);
  	kfree(job->reply_payload.sg_list);
50b4d4855   Benjamin Block   bsg-lib: fix kern...
152

cd2f076f1   Jens Axboe   bsg: convert to u...
153
  	blk_mq_end_request(rq, BLK_STS_OK);
aa387cc89   Mike Christie   block: add bsg he...
154
  }
fb6f7c8d8   Johannes Thumshirn   block: add bsg_jo...
155
156
  void bsg_job_put(struct bsg_job *job)
  {
50b4d4855   Benjamin Block   bsg-lib: fix kern...
157
  	kref_put(&job->kref, bsg_teardown_job);
fb6f7c8d8   Johannes Thumshirn   block: add bsg_jo...
158
159
160
161
162
163
164
165
  }
  EXPORT_SYMBOL_GPL(bsg_job_put);
  
  int bsg_job_get(struct bsg_job *job)
  {
  	return kref_get_unless_zero(&job->kref);
  }
  EXPORT_SYMBOL_GPL(bsg_job_get);
aa387cc89   Mike Christie   block: add bsg he...
166
167
168
169
170
171
172
173
174
175
176
177
  
  /**
   * bsg_job_done - completion routine for bsg requests
   * @job: bsg_job that is complete
   * @result: job reply result
   * @reply_payload_rcv_len: length of payload recvd
   *
   * The LLD should call this when the bsg job has completed.
   */
  void bsg_job_done(struct bsg_job *job, int result,
  		  unsigned int reply_payload_rcv_len)
  {
17cb960f2   Christoph Hellwig   bsg: split handli...
178
179
  	job->result = result;
  	job->reply_payload_rcv_len = reply_payload_rcv_len;
cd2f076f1   Jens Axboe   bsg: convert to u...
180
  	blk_mq_complete_request(blk_mq_rq_from_pdu(job));
aa387cc89   Mike Christie   block: add bsg he...
181
182
183
184
  }
  EXPORT_SYMBOL_GPL(bsg_job_done);
  
  /**
cd2f076f1   Jens Axboe   bsg: convert to u...
185
   * bsg_complete - softirq done routine for destroying the bsg requests
aa387cc89   Mike Christie   block: add bsg he...
186
187
   * @rq: BSG request that holds the job to be destroyed
   */
cd2f076f1   Jens Axboe   bsg: convert to u...
188
  static void bsg_complete(struct request *rq)
aa387cc89   Mike Christie   block: add bsg he...
189
  {
50b4d4855   Benjamin Block   bsg-lib: fix kern...
190
  	struct bsg_job *job = blk_mq_rq_to_pdu(rq);
aa387cc89   Mike Christie   block: add bsg he...
191

fb6f7c8d8   Johannes Thumshirn   block: add bsg_jo...
192
  	bsg_job_put(job);
aa387cc89   Mike Christie   block: add bsg he...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
  }
  
  static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
  {
  	size_t sz = (sizeof(struct scatterlist) * req->nr_phys_segments);
  
  	BUG_ON(!req->nr_phys_segments);
  
  	buf->sg_list = kzalloc(sz, GFP_KERNEL);
  	if (!buf->sg_list)
  		return -ENOMEM;
  	sg_init_table(buf->sg_list, req->nr_phys_segments);
  	buf->sg_cnt = blk_rq_map_sg(req->q, req, buf->sg_list);
  	buf->payload_len = blk_rq_bytes(req);
  	return 0;
  }
  
  /**
50b4d4855   Benjamin Block   bsg-lib: fix kern...
211
   * bsg_prepare_job - create the bsg_job structure for the bsg request
aa387cc89   Mike Christie   block: add bsg he...
212
213
214
   * @dev: device that is being sent the bsg request
   * @req: BSG request that needs a job structure
   */
17cb960f2   Christoph Hellwig   bsg: split handli...
215
  static bool bsg_prepare_job(struct device *dev, struct request *req)
aa387cc89   Mike Christie   block: add bsg he...
216
  {
50b4d4855   Benjamin Block   bsg-lib: fix kern...
217
  	struct bsg_job *job = blk_mq_rq_to_pdu(req);
aa387cc89   Mike Christie   block: add bsg he...
218
  	int ret;
31156ec37   Christoph Hellwig   bsg-lib: introduc...
219
  	job->timeout = req->timeout;
50b4d4855   Benjamin Block   bsg-lib: fix kern...
220

aa387cc89   Mike Christie   block: add bsg he...
221
222
223
224
225
  	if (req->bio) {
  		ret = bsg_map_buffer(&job->request_payload, req);
  		if (ret)
  			goto failjob_rls_job;
  	}
972248e91   Christoph Hellwig   scsi: bsg-lib: ha...
226
227
  	if (job->bidi_rq) {
  		ret = bsg_map_buffer(&job->reply_payload, job->bidi_rq);
aa387cc89   Mike Christie   block: add bsg he...
228
229
230
231
232
233
  		if (ret)
  			goto failjob_rls_rqst_payload;
  	}
  	job->dev = dev;
  	/* take a reference for the request */
  	get_device(job->dev);
bf0f2d380   Johannes Thumshirn   block: add refere...
234
  	kref_init(&job->kref);
17cb960f2   Christoph Hellwig   bsg: split handli...
235
  	return true;
aa387cc89   Mike Christie   block: add bsg he...
236
237
238
239
  
  failjob_rls_rqst_payload:
  	kfree(job->request_payload.sg_list);
  failjob_rls_job:
17cb960f2   Christoph Hellwig   bsg: split handli...
240
241
  	job->result = -ENOMEM;
  	return false;
aa387cc89   Mike Christie   block: add bsg he...
242
  }
aa387cc89   Mike Christie   block: add bsg he...
243
  /**
cd2f076f1   Jens Axboe   bsg: convert to u...
244
245
246
   * bsg_queue_rq - generic handler for bsg requests
   * @hctx: hardware queue
   * @bd: queue data
aa387cc89   Mike Christie   block: add bsg he...
247
248
   *
   * On error the create_bsg_job function should return a -Exyz error value
17d5363b8   Christoph Hellwig   scsi: introduce a...
249
   * that will be set to ->result.
aa387cc89   Mike Christie   block: add bsg he...
250
251
252
   *
   * Drivers/subsys should pass this to the queue init function.
   */
cd2f076f1   Jens Axboe   bsg: convert to u...
253
254
  static blk_status_t bsg_queue_rq(struct blk_mq_hw_ctx *hctx,
  				 const struct blk_mq_queue_data *bd)
aa387cc89   Mike Christie   block: add bsg he...
255
  {
cd2f076f1   Jens Axboe   bsg: convert to u...
256
  	struct request_queue *q = hctx->queue;
aa387cc89   Mike Christie   block: add bsg he...
257
  	struct device *dev = q->queuedata;
cd2f076f1   Jens Axboe   bsg: convert to u...
258
  	struct request *req = bd->rq;
1028e4b33   Jens Axboe   bsg: move bsg-lib...
259
260
  	struct bsg_set *bset =
  		container_of(q->tag_set, struct bsg_set, tag_set);
c44a4edb2   Bart Van Assche   block: Fix the ty...
261
  	blk_status_t sts = BLK_STS_IOERR;
aa387cc89   Mike Christie   block: add bsg he...
262
  	int ret;
cd2f076f1   Jens Axboe   bsg: convert to u...
263
  	blk_mq_start_request(req);
aa387cc89   Mike Christie   block: add bsg he...
264
  	if (!get_device(dev))
cd2f076f1   Jens Axboe   bsg: convert to u...
265
266
267
  		return BLK_STS_IOERR;
  
  	if (!bsg_prepare_job(dev, req))
d46fe2cb2   Martin Wilck   block: drop devic...
268
  		goto out;
cd2f076f1   Jens Axboe   bsg: convert to u...
269

1028e4b33   Jens Axboe   bsg: move bsg-lib...
270
  	ret = bset->job_fn(blk_mq_rq_to_pdu(req));
d46fe2cb2   Martin Wilck   block: drop devic...
271
272
  	if (!ret)
  		sts = BLK_STS_OK;
aa387cc89   Mike Christie   block: add bsg he...
273

d46fe2cb2   Martin Wilck   block: drop devic...
274
  out:
aa387cc89   Mike Christie   block: add bsg he...
275
  	put_device(dev);
d46fe2cb2   Martin Wilck   block: drop devic...
276
  	return sts;
aa387cc89   Mike Christie   block: add bsg he...
277
  }
aa387cc89   Mike Christie   block: add bsg he...
278

17cb960f2   Christoph Hellwig   bsg: split handli...
279
  /* called right after the request is allocated for the request_queue */
cd2f076f1   Jens Axboe   bsg: convert to u...
280
281
  static int bsg_init_rq(struct blk_mq_tag_set *set, struct request *req,
  		       unsigned int hctx_idx, unsigned int numa_node)
50b4d4855   Benjamin Block   bsg-lib: fix kern...
282
283
  {
  	struct bsg_job *job = blk_mq_rq_to_pdu(req);
eab40cf33   Benjamin Block   bsg-lib: fix use-...
284

cd2f076f1   Jens Axboe   bsg: convert to u...
285
  	job->reply = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
17cb960f2   Christoph Hellwig   bsg: split handli...
286
  	if (!job->reply)
eab40cf33   Benjamin Block   bsg-lib: fix use-...
287
  		return -ENOMEM;
eab40cf33   Benjamin Block   bsg-lib: fix use-...
288
289
  	return 0;
  }
17cb960f2   Christoph Hellwig   bsg: split handli...
290
  /* called right before the request is given to the request_queue user */
eab40cf33   Benjamin Block   bsg-lib: fix use-...
291
292
293
  static void bsg_initialize_rq(struct request *req)
  {
  	struct bsg_job *job = blk_mq_rq_to_pdu(req);
17cb960f2   Christoph Hellwig   bsg: split handli...
294
  	void *reply = job->reply;
eab40cf33   Benjamin Block   bsg-lib: fix use-...
295

50b4d4855   Benjamin Block   bsg-lib: fix kern...
296
  	memset(job, 0, sizeof(*job));
17cb960f2   Christoph Hellwig   bsg: split handli...
297
298
  	job->reply = reply;
  	job->reply_len = SCSI_SENSE_BUFFERSIZE;
50b4d4855   Benjamin Block   bsg-lib: fix kern...
299
  	job->dd_data = job + 1;
50b4d4855   Benjamin Block   bsg-lib: fix kern...
300
  }
cd2f076f1   Jens Axboe   bsg: convert to u...
301
302
  static void bsg_exit_rq(struct blk_mq_tag_set *set, struct request *req,
  		       unsigned int hctx_idx)
50b4d4855   Benjamin Block   bsg-lib: fix kern...
303
304
  {
  	struct bsg_job *job = blk_mq_rq_to_pdu(req);
50b4d4855   Benjamin Block   bsg-lib: fix kern...
305

17cb960f2   Christoph Hellwig   bsg: split handli...
306
  	kfree(job->reply);
50b4d4855   Benjamin Block   bsg-lib: fix kern...
307
  }
5e28b8d8a   Jens Axboe   bsg: provide bsg_...
308
309
310
  void bsg_remove_queue(struct request_queue *q)
  {
  	if (q) {
1028e4b33   Jens Axboe   bsg: move bsg-lib...
311
312
  		struct bsg_set *bset =
  			container_of(q->tag_set, struct bsg_set, tag_set);
cd2f076f1   Jens Axboe   bsg: convert to u...
313

5e28b8d8a   Jens Axboe   bsg: provide bsg_...
314
315
  		bsg_unregister_queue(q);
  		blk_cleanup_queue(q);
1028e4b33   Jens Axboe   bsg: move bsg-lib...
316
317
  		blk_mq_free_tag_set(&bset->tag_set);
  		kfree(bset);
5e28b8d8a   Jens Axboe   bsg: provide bsg_...
318
319
320
  	}
  }
  EXPORT_SYMBOL_GPL(bsg_remove_queue);
cd2f076f1   Jens Axboe   bsg: convert to u...
321
322
  static enum blk_eh_timer_return bsg_timeout(struct request *rq, bool reserved)
  {
1028e4b33   Jens Axboe   bsg: move bsg-lib...
323
324
  	struct bsg_set *bset =
  		container_of(rq->q->tag_set, struct bsg_set, tag_set);
cd2f076f1   Jens Axboe   bsg: convert to u...
325

1028e4b33   Jens Axboe   bsg: move bsg-lib...
326
327
328
  	if (!bset->timeout_fn)
  		return BLK_EH_DONE;
  	return bset->timeout_fn(rq);
cd2f076f1   Jens Axboe   bsg: convert to u...
329
330
331
332
333
334
335
336
337
338
  }
  
  static const struct blk_mq_ops bsg_mq_ops = {
  	.queue_rq		= bsg_queue_rq,
  	.init_request		= bsg_init_rq,
  	.exit_request		= bsg_exit_rq,
  	.initialize_rq_fn	= bsg_initialize_rq,
  	.complete		= bsg_complete,
  	.timeout		= bsg_timeout,
  };
aa387cc89   Mike Christie   block: add bsg he...
339
340
341
  /**
   * bsg_setup_queue - Create and add the bsg hooks so we can receive requests
   * @dev: device to attach bsg device to
aa387cc89   Mike Christie   block: add bsg he...
342
343
   * @name: device to give bsg device
   * @job_fn: bsg job handler
a0b77e36e   Bart Van Assche   block: Fix bsg_se...
344
   * @timeout: timeout handler function pointer
aa387cc89   Mike Christie   block: add bsg he...
345
   * @dd_job_size: size of LLD data needed for each job
aa387cc89   Mike Christie   block: add bsg he...
346
   */
c1225f01a   Christoph Hellwig   scsi: bsg-lib: pa...
347
  struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
1028e4b33   Jens Axboe   bsg: move bsg-lib...
348
  		bsg_job_fn *job_fn, bsg_timeout_fn *timeout, int dd_job_size)
aa387cc89   Mike Christie   block: add bsg he...
349
  {
1028e4b33   Jens Axboe   bsg: move bsg-lib...
350
  	struct bsg_set *bset;
cd2f076f1   Jens Axboe   bsg: convert to u...
351
  	struct blk_mq_tag_set *set;
8ae94eb65   Christoph Hellwig   block/bsg: move q...
352
  	struct request_queue *q;
cd2f076f1   Jens Axboe   bsg: convert to u...
353
  	int ret = -ENOMEM;
aa387cc89   Mike Christie   block: add bsg he...
354

1028e4b33   Jens Axboe   bsg: move bsg-lib...
355
356
  	bset = kzalloc(sizeof(*bset), GFP_KERNEL);
  	if (!bset)
8ae94eb65   Christoph Hellwig   block/bsg: move q...
357
  		return ERR_PTR(-ENOMEM);
82ed4db49   Christoph Hellwig   block: split scsi...
358

1028e4b33   Jens Axboe   bsg: move bsg-lib...
359
360
361
362
  	bset->job_fn = job_fn;
  	bset->timeout_fn = timeout;
  
  	set = &bset->tag_set;
cd2f076f1   Jens Axboe   bsg: convert to u...
363
364
365
366
367
368
369
370
371
372
373
374
375
376
  	set->ops = &bsg_mq_ops,
  	set->nr_hw_queues = 1;
  	set->queue_depth = 128;
  	set->numa_node = NUMA_NO_NODE;
  	set->cmd_size = sizeof(struct bsg_job) + dd_job_size;
  	set->flags = BLK_MQ_F_NO_SCHED | BLK_MQ_F_BLOCKING;
  	if (blk_mq_alloc_tag_set(set))
  		goto out_tag_set;
  
  	q = blk_mq_init_queue(set);
  	if (IS_ERR(q)) {
  		ret = PTR_ERR(q);
  		goto out_queue;
  	}
8ae94eb65   Christoph Hellwig   block/bsg: move q...
377

aa387cc89   Mike Christie   block: add bsg he...
378
  	q->queuedata = dev;
aa387cc89   Mike Christie   block: add bsg he...
379
  	blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT);
5de815a7e   Christoph Hellwig   block: remove par...
380
  	ret = bsg_register_queue(q, dev, name, &bsg_transport_ops);
aa387cc89   Mike Christie   block: add bsg he...
381
382
383
384
  	if (ret) {
  		printk(KERN_ERR "%s: bsg interface failed to "
  		       "initialize - register queue
  ", dev->kobj.name);
82ed4db49   Christoph Hellwig   block: split scsi...
385
  		goto out_cleanup_queue;
aa387cc89   Mike Christie   block: add bsg he...
386
  	}
8ae94eb65   Christoph Hellwig   block/bsg: move q...
387
  	return q;
82ed4db49   Christoph Hellwig   block: split scsi...
388
389
  out_cleanup_queue:
  	blk_cleanup_queue(q);
cd2f076f1   Jens Axboe   bsg: convert to u...
390
391
392
  out_queue:
  	blk_mq_free_tag_set(set);
  out_tag_set:
1028e4b33   Jens Axboe   bsg: move bsg-lib...
393
  	kfree(bset);
82ed4db49   Christoph Hellwig   block: split scsi...
394
  	return ERR_PTR(ret);
aa387cc89   Mike Christie   block: add bsg he...
395
396
  }
  EXPORT_SYMBOL_GPL(bsg_setup_queue);