Blame view
block/bsg.c
12.4 KB
3d6392cfb bsg: support for ... |
1 |
/* |
0c6a89ba6 [SCSI] bsg: updat... |
2 |
* bsg.c - block layer implementation of the sg v4 interface |
3d6392cfb bsg: support for ... |
3 4 5 6 7 8 9 10 11 |
* * Copyright (C) 2004 Jens Axboe <axboe@suse.de> SUSE Labs * Copyright (C) 2004 Peter M. Jones <pjones@redhat.com> * * This file is subject to the terms and conditions of the GNU General Public * License version 2. See the file "COPYING" in the main directory of this * archive for more details. * */ |
3d6392cfb bsg: support for ... |
12 13 14 15 |
#include <linux/module.h> #include <linux/init.h> #include <linux/file.h> #include <linux/blkdev.h> |
3d6392cfb bsg: support for ... |
16 |
#include <linux/cdev.h> |
ad5ebd2fa block: jiffies fixes |
17 |
#include <linux/jiffies.h> |
3d6392cfb bsg: support for ... |
18 |
#include <linux/percpu.h> |
598443a21 [SCSI] bsg: use l... |
19 |
#include <linux/idr.h> |
3d6392cfb bsg: support for ... |
20 |
#include <linux/bsg.h> |
5a0e3ad6a include cleanup: ... |
21 |
#include <linux/slab.h> |
3d6392cfb bsg: support for ... |
22 23 24 25 |
#include <scsi/scsi.h> #include <scsi/scsi_ioctl.h> #include <scsi/scsi_cmnd.h> |
4e2872d6b bind bsg to all S... |
26 27 |
#include <scsi/scsi_device.h> #include <scsi/scsi_driver.h> |
3d6392cfb bsg: support for ... |
28 |
#include <scsi/sg.h> |
0ed081ce2 bsg: minor cleanup |
29 30 |
#define BSG_DESCRIPTION "Block layer SCSI generic (bsg) driver" #define BSG_VERSION "0.4" |
3d6392cfb bsg: support for ... |
31 |
|
3124b65da bsg: use pr_debug... |
32 33 |
#define bsg_dbg(bd, fmt, ...) \ pr_debug("%s: " fmt, (bd)->name, ##__VA_ARGS__) |
3d6392cfb bsg: support for ... |
34 |
struct bsg_device { |
165125e1e [BLOCK] Get rid o... |
35 |
struct request_queue *queue; |
3d6392cfb bsg: support for ... |
36 |
spinlock_t lock; |
3d6392cfb bsg: support for ... |
37 |
struct hlist_node dev_list; |
db193954e block: bsg: move ... |
38 |
refcount_t ref_count; |
3ada8b7e9 block: struct dev... |
39 |
char name[20]; |
3d6392cfb bsg: support for ... |
40 |
int max_queue; |
3d6392cfb bsg: support for ... |
41 |
}; |
5309cb38d Add queue resizin... |
42 |
#define BSG_DEFAULT_CMDS 64 |
292b7f271 improve bsg devic... |
43 |
#define BSG_MAX_DEVS 32768 |
3d6392cfb bsg: support for ... |
44 |
|
3d6392cfb bsg: support for ... |
45 |
static DEFINE_MUTEX(bsg_mutex); |
598443a21 [SCSI] bsg: use l... |
46 |
static DEFINE_IDR(bsg_minor_idr); |
3d6392cfb bsg: support for ... |
47 |
|
25fd16430 bsg: address vari... |
48 |
#define BSG_LIST_ARRAY_SIZE 8 |
25fd16430 bsg: address vari... |
49 |
static struct hlist_head bsg_device_list[BSG_LIST_ARRAY_SIZE]; |
3d6392cfb bsg: support for ... |
50 51 |
static struct class *bsg_class; |
46f6ef4af bsg: convert to d... |
52 |
static int bsg_major; |
3d6392cfb bsg: support for ... |
53 |
|
1c1133e1f bsg: device hash ... |
54 |
static inline struct hlist_head *bsg_dev_idx_hash(int index) |
3d6392cfb bsg: support for ... |
55 |
{ |
1c1133e1f bsg: device hash ... |
56 |
return &bsg_device_list[index & (BSG_LIST_ARRAY_SIZE - 1)]; |
3d6392cfb bsg: support for ... |
57 |
} |
17cb960f2 bsg: split handli... |
58 59 60 61 62 63 64 65 66 67 68 69 |
#define uptr64(val) ((void __user *)(uintptr_t)(val)) static int bsg_scsi_check_proto(struct sg_io_v4 *hdr) { if (hdr->protocol != BSG_PROTOCOL_SCSI || hdr->subprotocol != BSG_SUB_PROTOCOL_SCSI_CMD) return -EINVAL; return 0; } static int bsg_scsi_fill_hdr(struct request *rq, struct sg_io_v4 *hdr, fmode_t mode) |
70e36ecea bsg: replace SG v... |
70 |
{ |
17cb960f2 bsg: split handli... |
71 |
struct scsi_request *sreq = scsi_req(rq); |
82ed4db49 block: split scsi... |
72 |
|
17cb960f2 bsg: split handli... |
73 74 75 76 |
sreq->cmd_len = hdr->request_len; if (sreq->cmd_len > BLK_MAX_CDB) { sreq->cmd = kzalloc(sreq->cmd_len, GFP_KERNEL); if (!sreq->cmd) |
9f5de6b10 [SCSI] bsg: add l... |
77 78 |
return -ENOMEM; } |
70e36ecea bsg: replace SG v... |
79 |
|
17cb960f2 bsg: split handli... |
80 |
if (copy_from_user(sreq->cmd, uptr64(hdr->request), sreq->cmd_len)) |
70e36ecea bsg: replace SG v... |
81 |
return -EFAULT; |
17cb960f2 bsg: split handli... |
82 |
if (blk_verify_command(sreq->cmd, mode)) |
70e36ecea bsg: replace SG v... |
83 |
return -EPERM; |
70e36ecea bsg: replace SG v... |
84 85 |
return 0; } |
17cb960f2 bsg: split handli... |
86 |
static int bsg_scsi_complete_rq(struct request *rq, struct sg_io_v4 *hdr) |
3d6392cfb bsg: support for ... |
87 |
{ |
17cb960f2 bsg: split handli... |
88 |
struct scsi_request *sreq = scsi_req(rq); |
15d10b611 bsg: add SCSI tra... |
89 |
int ret = 0; |
17cb960f2 bsg: split handli... |
90 91 92 93 94 95 96 97 98 99 |
/* * fill in all the output members */ hdr->device_status = sreq->result & 0xff; hdr->transport_status = host_byte(sreq->result); hdr->driver_status = driver_byte(sreq->result); hdr->info = 0; if (hdr->device_status || hdr->transport_status || hdr->driver_status) hdr->info |= SG_INFO_CHECK; hdr->response_len = 0; |
3d6392cfb bsg: support for ... |
100 |
|
17cb960f2 bsg: split handli... |
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
if (sreq->sense_len && hdr->response) { int len = min_t(unsigned int, hdr->max_response_len, sreq->sense_len); if (copy_to_user(uptr64(hdr->response), sreq->sense, len)) ret = -EFAULT; else hdr->response_len = len; } if (rq->next_rq) { hdr->dout_resid = sreq->resid_len; hdr->din_resid = scsi_req(rq->next_rq)->resid_len; } else if (rq_data_dir(rq) == READ) { hdr->din_resid = sreq->resid_len; } else { hdr->dout_resid = sreq->resid_len; |
15d10b611 bsg: add SCSI tra... |
118 |
} |
70e36ecea bsg: replace SG v... |
119 |
|
15d10b611 bsg: add SCSI tra... |
120 |
return ret; |
3d6392cfb bsg: support for ... |
121 |
} |
17cb960f2 bsg: split handli... |
122 123 124 125 126 127 128 129 130 131 132 |
static void bsg_scsi_free_rq(struct request *rq) { scsi_req_free_cmd(scsi_req(rq)); } static const struct bsg_ops bsg_scsi_ops = { .check_proto = bsg_scsi_check_proto, .fill_hdr = bsg_scsi_fill_hdr, .complete_rq = bsg_scsi_complete_rq, .free_rq = bsg_scsi_free_rq, }; |
3d6392cfb bsg: support for ... |
133 |
static struct request * |
17cb960f2 bsg: split handli... |
134 |
bsg_map_hdr(struct request_queue *q, struct sg_io_v4 *hdr, fmode_t mode) |
3d6392cfb bsg: support for ... |
135 |
{ |
2c9ecdf40 bsg: add bidi sup... |
136 |
struct request *rq, *next_rq = NULL; |
aebf526b5 block: fold cmd_t... |
137 |
int ret; |
c7a841f3a [SCSI] bsg: corre... |
138 |
|
17cb960f2 bsg: split handli... |
139 |
if (!q->bsg_dev.class_dev) |
c7a841f3a [SCSI] bsg: corre... |
140 |
return ERR_PTR(-ENXIO); |
3d6392cfb bsg: support for ... |
141 |
|
17cb960f2 bsg: split handli... |
142 143 |
if (hdr->guard != 'Q') return ERR_PTR(-EINVAL); |
3d6392cfb bsg: support for ... |
144 |
|
17cb960f2 bsg: split handli... |
145 |
ret = q->bsg_dev.ops->check_proto(hdr); |
3d6392cfb bsg: support for ... |
146 147 |
if (ret) return ERR_PTR(ret); |
17cb960f2 bsg: split handli... |
148 |
rq = blk_get_request(q, hdr->dout_xfer_len ? |
ff005a066 block: sanitize b... |
149 |
REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, 0); |
a492f0754 block,scsi: fixup... |
150 151 |
if (IS_ERR(rq)) return rq; |
f27b087b8 block: add blk_rq... |
152 |
|
17cb960f2 bsg: split handli... |
153 |
ret = q->bsg_dev.ops->fill_hdr(rq, hdr, mode); |
2c9ecdf40 bsg: add bidi sup... |
154 155 |
if (ret) goto out; |
17cb960f2 bsg: split handli... |
156 157 158 159 160 161 162 163 164 |
rq->timeout = msecs_to_jiffies(hdr->timeout); if (!rq->timeout) rq->timeout = q->sg_timeout; if (!rq->timeout) rq->timeout = BLK_DEFAULT_SG_TIMEOUT; if (rq->timeout < BLK_MIN_SG_TIMEOUT) rq->timeout = BLK_MIN_SG_TIMEOUT; if (hdr->dout_xfer_len && hdr->din_xfer_len) { |
2c9ecdf40 bsg: add bidi sup... |
165 166 167 168 |
if (!test_bit(QUEUE_FLAG_BIDI, &q->queue_flags)) { ret = -EOPNOTSUPP; goto out; } |
ff005a066 block: sanitize b... |
169 |
next_rq = blk_get_request(q, REQ_OP_SCSI_IN, 0); |
a492f0754 block,scsi: fixup... |
170 171 |
if (IS_ERR(next_rq)) { ret = PTR_ERR(next_rq); |
2c9ecdf40 bsg: add bidi sup... |
172 173 |
goto out; } |
2c9ecdf40 bsg: add bidi sup... |
174 |
|
17cb960f2 bsg: split handli... |
175 176 |
rq->next_rq = next_rq; ret = blk_rq_map_user(q, next_rq, NULL, uptr64(hdr->din_xferp), |
152e283fd block: introduce ... |
177 |
hdr->din_xfer_len, GFP_KERNEL); |
2c9ecdf40 bsg: add bidi sup... |
178 |
if (ret) |
17cb960f2 bsg: split handli... |
179 |
goto out_free_nextrq; |
3d6392cfb bsg: support for ... |
180 |
} |
70e36ecea bsg: replace SG v... |
181 |
if (hdr->dout_xfer_len) { |
17cb960f2 bsg: split handli... |
182 183 |
ret = blk_rq_map_user(q, rq, NULL, uptr64(hdr->dout_xferp), hdr->dout_xfer_len, GFP_KERNEL); |
70e36ecea bsg: replace SG v... |
184 |
} else if (hdr->din_xfer_len) { |
17cb960f2 bsg: split handli... |
185 186 |
ret = blk_rq_map_user(q, rq, NULL, uptr64(hdr->din_xferp), hdr->din_xfer_len, GFP_KERNEL); |
3d6392cfb bsg: support for ... |
187 |
} |
c1c201200 bsg: Fix sense bu... |
188 |
|
17cb960f2 bsg: split handli... |
189 190 |
if (ret) goto out_unmap_nextrq; |
3d6392cfb bsg: support for ... |
191 |
return rq; |
17cb960f2 bsg: split handli... |
192 193 194 195 196 197 198 |
out_unmap_nextrq: if (rq->next_rq) blk_rq_unmap_user(rq->next_rq->bio); out_free_nextrq: if (rq->next_rq) blk_put_request(rq->next_rq); |
2c9ecdf40 bsg: add bidi sup... |
199 |
out: |
17cb960f2 bsg: split handli... |
200 |
q->bsg_dev.ops->free_rq(rq); |
2c9ecdf40 bsg: add bidi sup... |
201 |
blk_put_request(rq); |
2c9ecdf40 bsg: add bidi sup... |
202 |
return ERR_PTR(ret); |
3d6392cfb bsg: support for ... |
203 |
} |
70e36ecea bsg: replace SG v... |
204 |
static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr, |
2c9ecdf40 bsg: add bidi sup... |
205 |
struct bio *bio, struct bio *bidi_bio) |
70e36ecea bsg: replace SG v... |
206 |
{ |
17cb960f2 bsg: split handli... |
207 |
int ret; |
70e36ecea bsg: replace SG v... |
208 |
|
17cb960f2 bsg: split handli... |
209 |
ret = rq->q->bsg_dev.ops->complete_rq(rq, hdr); |
70e36ecea bsg: replace SG v... |
210 |
|
2c9ecdf40 bsg: add bidi sup... |
211 212 213 |
if (rq->next_rq) { blk_rq_unmap_user(bidi_bio); blk_put_request(rq->next_rq); |
17cb960f2 bsg: split handli... |
214 |
} |
2d507a01d [SCSI] libsas, bs... |
215 |
|
70e36ecea bsg: replace SG v... |
216 |
blk_rq_unmap_user(bio); |
17cb960f2 bsg: split handli... |
217 |
rq->q->bsg_dev.ops->free_rq(rq); |
70e36ecea bsg: replace SG v... |
218 |
blk_put_request(rq); |
70e36ecea bsg: replace SG v... |
219 220 |
return ret; } |
3d6392cfb bsg: support for ... |
221 222 |
static struct bsg_device *bsg_alloc_device(void) { |
3d6392cfb bsg: support for ... |
223 |
struct bsg_device *bd; |
3d6392cfb bsg: support for ... |
224 225 226 227 228 229 |
bd = kzalloc(sizeof(struct bsg_device), GFP_KERNEL); if (unlikely(!bd)) return NULL; spin_lock_init(&bd->lock); |
5309cb38d Add queue resizin... |
230 |
bd->max_queue = BSG_DEFAULT_CMDS; |
3d6392cfb bsg: support for ... |
231 |
INIT_HLIST_NODE(&bd->dev_list); |
3d6392cfb bsg: support for ... |
232 |
return bd; |
3d6392cfb bsg: support for ... |
233 234 235 236 |
} static int bsg_put_device(struct bsg_device *bd) { |
97f46ae45 [SCSI] bsg: add r... |
237 |
struct request_queue *q = bd->queue; |
3d6392cfb bsg: support for ... |
238 239 |
mutex_lock(&bsg_mutex); |
db193954e block: bsg: move ... |
240 |
if (!refcount_dec_and_test(&bd->ref_count)) { |
3f27e3ed1 [SCSI] bsg: fix b... |
241 |
mutex_unlock(&bsg_mutex); |
28519c891 bsg: remove read/... |
242 |
return 0; |
3f27e3ed1 [SCSI] bsg: fix b... |
243 244 245 246 |
} hlist_del(&bd->dev_list); mutex_unlock(&bsg_mutex); |
3d6392cfb bsg: support for ... |
247 |
|
3124b65da bsg: use pr_debug... |
248 249 |
bsg_dbg(bd, "tearing down "); |
3d6392cfb bsg: support for ... |
250 251 252 253 |
/* * close can always block */ |
5309cb38d Add queue resizin... |
254 |
kfree(bd); |
28519c891 bsg: remove read/... |
255 256 |
blk_put_queue(q); return 0; |
3d6392cfb bsg: support for ... |
257 258 259 |
} static struct bsg_device *bsg_add_device(struct inode *inode, |
d351af01b bsg: bind bsg to ... |
260 |
struct request_queue *rq, |
3d6392cfb bsg: support for ... |
261 262 |
struct file *file) { |
25fd16430 bsg: address vari... |
263 |
struct bsg_device *bd; |
3d6392cfb bsg: support for ... |
264 |
unsigned char buf[32]; |
d9f972644 bsg: Check queue ... |
265 |
|
d6c73964f bsg: fix race of ... |
266 |
lockdep_assert_held(&bsg_mutex); |
09ac46c42 block: misc updat... |
267 |
if (!blk_get_queue(rq)) |
c3ff1b90d [SCSI] bsg: repla... |
268 |
return ERR_PTR(-ENXIO); |
3d6392cfb bsg: support for ... |
269 270 |
bd = bsg_alloc_device(); |
c3ff1b90d [SCSI] bsg: repla... |
271 272 |
if (!bd) { blk_put_queue(rq); |
3d6392cfb bsg: support for ... |
273 |
return ERR_PTR(-ENOMEM); |
c3ff1b90d [SCSI] bsg: repla... |
274 |
} |
3d6392cfb bsg: support for ... |
275 |
|
d351af01b bsg: bind bsg to ... |
276 |
bd->queue = rq; |
0b07de85a allow userspace t... |
277 |
|
db193954e block: bsg: move ... |
278 |
refcount_set(&bd->ref_count, 1); |
842ea771c [SCSI] bsg: remov... |
279 |
hlist_add_head(&bd->dev_list, bsg_dev_idx_hash(iminor(inode))); |
3d6392cfb bsg: support for ... |
280 |
|
3ada8b7e9 block: struct dev... |
281 |
strncpy(bd->name, dev_name(rq->bsg_dev.class_dev), sizeof(bd->name) - 1); |
3124b65da bsg: use pr_debug... |
282 283 |
bsg_dbg(bd, "bound to <%s>, max queue %d ", |
9e69fbb53 bsg: minor cleanups |
284 |
format_dev_t(buf, inode->i_rdev), bd->max_queue); |
3d6392cfb bsg: support for ... |
285 |
|
3d6392cfb bsg: support for ... |
286 287 |
return bd; } |
842ea771c [SCSI] bsg: remov... |
288 |
static struct bsg_device *__bsg_get_device(int minor, struct request_queue *q) |
3d6392cfb bsg: support for ... |
289 |
{ |
43ac9e62c [SCSI] bsg: use b... |
290 |
struct bsg_device *bd; |
3d6392cfb bsg: support for ... |
291 |
|
d6c73964f bsg: fix race of ... |
292 |
lockdep_assert_held(&bsg_mutex); |
3d6392cfb bsg: support for ... |
293 |
|
b67bfe0d4 hlist: drop the n... |
294 |
hlist_for_each_entry(bd, bsg_dev_idx_hash(minor), dev_list) { |
842ea771c [SCSI] bsg: remov... |
295 |
if (bd->queue == q) { |
db193954e block: bsg: move ... |
296 |
refcount_inc(&bd->ref_count); |
43ac9e62c [SCSI] bsg: use b... |
297 |
goto found; |
3d6392cfb bsg: support for ... |
298 |
} |
3d6392cfb bsg: support for ... |
299 |
} |
43ac9e62c [SCSI] bsg: use b... |
300 301 |
bd = NULL; found: |
3d6392cfb bsg: support for ... |
302 303 304 305 306 |
return bd; } static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file) { |
598443a21 [SCSI] bsg: use l... |
307 308 |
struct bsg_device *bd; struct bsg_class_device *bcd; |
3d6392cfb bsg: support for ... |
309 |
|
3d6392cfb bsg: support for ... |
310 311 312 |
/* * find the class device */ |
3d6392cfb bsg: support for ... |
313 |
mutex_lock(&bsg_mutex); |
598443a21 [SCSI] bsg: use l... |
314 |
bcd = idr_find(&bsg_minor_idr, iminor(inode)); |
3d6392cfb bsg: support for ... |
315 |
|
d6c73964f bsg: fix race of ... |
316 317 318 319 |
if (!bcd) { bd = ERR_PTR(-ENODEV); goto out_unlock; } |
3d6392cfb bsg: support for ... |
320 |
|
842ea771c [SCSI] bsg: remov... |
321 |
bd = __bsg_get_device(iminor(inode), bcd->queue); |
d6c73964f bsg: fix race of ... |
322 323 |
if (!bd) bd = bsg_add_device(inode, bcd->queue, file); |
d45ac4fa8 [SCSI] bsg: takes... |
324 |
|
d6c73964f bsg: fix race of ... |
325 326 |
out_unlock: mutex_unlock(&bsg_mutex); |
d45ac4fa8 [SCSI] bsg: takes... |
327 |
return bd; |
3d6392cfb bsg: support for ... |
328 329 330 331 |
} static int bsg_open(struct inode *inode, struct file *file) { |
75bd2ef14 bsg: cdev lock_ke... |
332 |
struct bsg_device *bd; |
75bd2ef14 bsg: cdev lock_ke... |
333 |
bd = bsg_get_device(inode, file); |
3d6392cfb bsg: support for ... |
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
if (IS_ERR(bd)) return PTR_ERR(bd); file->private_data = bd; return 0; } static int bsg_release(struct inode *inode, struct file *file) { struct bsg_device *bd = file->private_data; file->private_data = NULL; return bsg_put_device(bd); } |
25fd16430 bsg: address vari... |
349 |
static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
3d6392cfb bsg: support for ... |
350 351 352 |
{ struct bsg_device *bd = file->private_data; int __user *uarg = (int __user *) arg; |
2d507a01d [SCSI] libsas, bs... |
353 |
int ret; |
3d6392cfb bsg: support for ... |
354 |
|
3d6392cfb bsg: support for ... |
355 356 357 358 359 360 |
switch (cmd) { /* * our own ioctls */ case SG_GET_COMMAND_Q: return put_user(bd->max_queue, uarg); |
5309cb38d Add queue resizin... |
361 |
case SG_SET_COMMAND_Q: { |
3d6392cfb bsg: support for ... |
362 363 364 365 |
int queue; if (get_user(queue, uarg)) return -EFAULT; |
5309cb38d Add queue resizin... |
366 |
if (queue < 1) |
3d6392cfb bsg: support for ... |
367 |
return -EINVAL; |
5309cb38d Add queue resizin... |
368 |
spin_lock_irq(&bd->lock); |
3d6392cfb bsg: support for ... |
369 |
bd->max_queue = queue; |
5309cb38d Add queue resizin... |
370 |
spin_unlock_irq(&bd->lock); |
3d6392cfb bsg: support for ... |
371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
return 0; } /* * SCSI/sg ioctls */ case SG_GET_VERSION_NUM: case SCSI_IOCTL_GET_IDLUN: case SCSI_IOCTL_GET_BUS_NUMBER: case SG_SET_TIMEOUT: case SG_GET_TIMEOUT: case SG_GET_RESERVED_SIZE: case SG_SET_RESERVED_SIZE: case SG_EMULATED_HOST: |
3d6392cfb bsg: support for ... |
385 386 |
case SCSI_IOCTL_SEND_COMMAND: { void __user *uarg = (void __user *) arg; |
74f3c8aff [PATCH] switch sc... |
387 |
return scsi_cmd_ioctl(bd->queue, NULL, file->f_mode, cmd, uarg); |
3d6392cfb bsg: support for ... |
388 |
} |
10e8855b9 bsg: add SG_IO to... |
389 390 |
case SG_IO: { struct request *rq; |
2c9ecdf40 bsg: add bidi sup... |
391 |
struct bio *bio, *bidi_bio = NULL; |
10e8855b9 bsg: add SG_IO to... |
392 |
struct sg_io_v4 hdr; |
05378940c bsg: add support ... |
393 |
int at_head; |
10e8855b9 bsg: add SG_IO to... |
394 395 396 |
if (copy_from_user(&hdr, uarg, sizeof(hdr))) return -EFAULT; |
17cb960f2 bsg: split handli... |
397 |
rq = bsg_map_hdr(bd->queue, &hdr, file->f_mode); |
10e8855b9 bsg: add SG_IO to... |
398 399 400 401 |
if (IS_ERR(rq)) return PTR_ERR(rq); bio = rq->bio; |
2c9ecdf40 bsg: add bidi sup... |
402 403 |
if (rq->next_rq) bidi_bio = rq->next_rq->bio; |
05378940c bsg: add support ... |
404 405 406 |
at_head = (0 == (hdr.flags & BSG_FLAG_Q_AT_TAIL)); blk_execute_rq(bd->queue, NULL, rq, at_head); |
2d507a01d [SCSI] libsas, bs... |
407 |
ret = blk_complete_sgv4_hdr_rq(rq, &hdr, bio, bidi_bio); |
10e8855b9 bsg: add SG_IO to... |
408 409 410 |
if (copy_to_user(uarg, &hdr, sizeof(hdr))) return -EFAULT; |
b711afa69 bsg: style cleanup |
411 |
|
2d507a01d [SCSI] libsas, bs... |
412 |
return ret; |
10e8855b9 bsg: add SG_IO to... |
413 |
} |
3d6392cfb bsg: support for ... |
414 |
default: |
3d6392cfb bsg: support for ... |
415 |
return -ENOTTY; |
3d6392cfb bsg: support for ... |
416 417 |
} } |
7344be053 bsg: mark struct ... |
418 |
static const struct file_operations bsg_fops = { |
3d6392cfb bsg: support for ... |
419 420 |
.open = bsg_open, .release = bsg_release, |
25fd16430 bsg: address vari... |
421 |
.unlocked_ioctl = bsg_ioctl, |
3d6392cfb bsg: support for ... |
422 |
.owner = THIS_MODULE, |
6038f373a llseek: automatic... |
423 |
.llseek = default_llseek, |
3d6392cfb bsg: support for ... |
424 |
}; |
d351af01b bsg: bind bsg to ... |
425 |
void bsg_unregister_queue(struct request_queue *q) |
3d6392cfb bsg: support for ... |
426 |
{ |
d351af01b bsg: bind bsg to ... |
427 |
struct bsg_class_device *bcd = &q->bsg_dev; |
3d6392cfb bsg: support for ... |
428 |
|
df468820b [SCSI] bsg: fix b... |
429 430 |
if (!bcd->class_dev) return; |
3d6392cfb bsg: support for ... |
431 432 |
mutex_lock(&bsg_mutex); |
598443a21 [SCSI] bsg: use l... |
433 |
idr_remove(&bsg_minor_idr, bcd->minor); |
37b40adf2 bsg: fix sysfs li... |
434 435 |
if (q->kobj.sd) sysfs_remove_link(&q->kobj, "bsg"); |
ee959b00c SCSI: convert str... |
436 |
device_unregister(bcd->class_dev); |
3d6392cfb bsg: support for ... |
437 |
bcd->class_dev = NULL; |
3d6392cfb bsg: support for ... |
438 439 |
mutex_unlock(&bsg_mutex); } |
4cf0723ac bsg: minor bug fixes |
440 |
EXPORT_SYMBOL_GPL(bsg_unregister_queue); |
3d6392cfb bsg: support for ... |
441 |
|
97f46ae45 [SCSI] bsg: add r... |
442 |
int bsg_register_queue(struct request_queue *q, struct device *parent, |
5de815a7e block: remove par... |
443 |
const char *name, const struct bsg_ops *ops) |
3d6392cfb bsg: support for ... |
444 |
{ |
598443a21 [SCSI] bsg: use l... |
445 |
struct bsg_class_device *bcd; |
3d6392cfb bsg: support for ... |
446 |
dev_t dev; |
bab998d62 block: convert to... |
447 |
int ret; |
ee959b00c SCSI: convert str... |
448 |
struct device *class_dev = NULL; |
3d6392cfb bsg: support for ... |
449 450 451 452 |
/* * we need a proper transport to send commands, not a stacked device */ |
49fd524f9 bsg: update check... |
453 |
if (!queue_is_rq_based(q)) |
3d6392cfb bsg: support for ... |
454 |
return 0; |
d351af01b bsg: bind bsg to ... |
455 |
bcd = &q->bsg_dev; |
3d6392cfb bsg: support for ... |
456 |
memset(bcd, 0, sizeof(*bcd)); |
3d6392cfb bsg: support for ... |
457 458 |
mutex_lock(&bsg_mutex); |
292b7f271 improve bsg devic... |
459 |
|
bab998d62 block: convert to... |
460 461 462 463 464 465 466 |
ret = idr_alloc(&bsg_minor_idr, bcd, 0, BSG_MAX_DEVS, GFP_KERNEL); if (ret < 0) { if (ret == -ENOSPC) { printk(KERN_ERR "bsg: too many bsg devices "); ret = -EINVAL; } |
598443a21 [SCSI] bsg: use l... |
467 |
goto unlock; |
598443a21 [SCSI] bsg: use l... |
468 |
} |
bab998d62 block: convert to... |
469 |
bcd->minor = ret; |
d351af01b bsg: bind bsg to ... |
470 |
bcd->queue = q; |
17cb960f2 bsg: split handli... |
471 |
bcd->ops = ops; |
46f6ef4af bsg: convert to d... |
472 |
dev = MKDEV(bsg_major, bcd->minor); |
5de815a7e block: remove par... |
473 |
class_dev = device_create(bsg_class, parent, dev, NULL, "%s", name); |
4e2872d6b bind bsg to all S... |
474 475 |
if (IS_ERR(class_dev)) { ret = PTR_ERR(class_dev); |
5de815a7e block: remove par... |
476 |
goto idr_remove; |
4e2872d6b bind bsg to all S... |
477 478 |
} bcd->class_dev = class_dev; |
abce891a1 Fix new generic b... |
479 |
if (q->kobj.sd) { |
4e2872d6b bind bsg to all S... |
480 481 |
ret = sysfs_create_link(&q->kobj, &bcd->class_dev->kobj, "bsg"); if (ret) |
598443a21 [SCSI] bsg: use l... |
482 |
goto unregister_class_dev; |
4e2872d6b bind bsg to all S... |
483 |
} |
3d6392cfb bsg: support for ... |
484 485 |
mutex_unlock(&bsg_mutex); return 0; |
6826ee4fd [SCSI] bsg: fix b... |
486 |
|
598443a21 [SCSI] bsg: use l... |
487 |
unregister_class_dev: |
ee959b00c SCSI: convert str... |
488 |
device_unregister(class_dev); |
5de815a7e block: remove par... |
489 |
idr_remove: |
bab998d62 block: convert to... |
490 |
idr_remove(&bsg_minor_idr, bcd->minor); |
598443a21 [SCSI] bsg: use l... |
491 |
unlock: |
264a04721 bsg: add cheasy e... |
492 |
mutex_unlock(&bsg_mutex); |
4e2872d6b bind bsg to all S... |
493 494 |
return ret; } |
17cb960f2 bsg: split handli... |
495 496 497 498 499 500 501 502 |
int bsg_scsi_register_queue(struct request_queue *q, struct device *parent) { if (!blk_queue_scsi_passthrough(q)) { WARN_ONCE(true, "Attempt to register a non-SCSI queue "); return -EINVAL; } |
5de815a7e block: remove par... |
503 |
return bsg_register_queue(q, parent, dev_name(parent), &bsg_scsi_ops); |
17cb960f2 bsg: split handli... |
504 505 |
} EXPORT_SYMBOL_GPL(bsg_scsi_register_queue); |
4e2872d6b bind bsg to all S... |
506 |
|
7e7654a92 cdev: remove unne... |
507 |
static struct cdev bsg_cdev; |
292b7f271 improve bsg devic... |
508 |
|
2c9ede55e switch device_get... |
509 |
static char *bsg_devnode(struct device *dev, umode_t *mode) |
2bdf91491 Driver Core: bsg:... |
510 511 512 |
{ return kasprintf(GFP_KERNEL, "bsg/%s", dev_name(dev)); } |
3d6392cfb bsg: support for ... |
513 514 515 |
static int __init bsg_init(void) { int ret, i; |
46f6ef4af bsg: convert to d... |
516 |
dev_t devid; |
3d6392cfb bsg: support for ... |
517 |
|
25fd16430 bsg: address vari... |
518 |
for (i = 0; i < BSG_LIST_ARRAY_SIZE; i++) |
3d6392cfb bsg: support for ... |
519 520 521 |
INIT_HLIST_HEAD(&bsg_device_list[i]); bsg_class = class_create(THIS_MODULE, "bsg"); |
28519c891 bsg: remove read/... |
522 523 |
if (IS_ERR(bsg_class)) return PTR_ERR(bsg_class); |
e454cea20 Driver-Core: exte... |
524 |
bsg_class->devnode = bsg_devnode; |
3d6392cfb bsg: support for ... |
525 |
|
46f6ef4af bsg: convert to d... |
526 |
ret = alloc_chrdev_region(&devid, 0, BSG_MAX_DEVS, "bsg"); |
9b9f770ce bsg: fix initiali... |
527 528 |
if (ret) goto destroy_bsg_class; |
292b7f271 improve bsg devic... |
529 |
|
46f6ef4af bsg: convert to d... |
530 |
bsg_major = MAJOR(devid); |
292b7f271 improve bsg devic... |
531 |
cdev_init(&bsg_cdev, &bsg_fops); |
46f6ef4af bsg: convert to d... |
532 |
ret = cdev_add(&bsg_cdev, MKDEV(bsg_major, 0), BSG_MAX_DEVS); |
9b9f770ce bsg: fix initiali... |
533 534 |
if (ret) goto unregister_chrdev; |
3d6392cfb bsg: support for ... |
535 |
|
5d3a8cd34 bsg: fix missing ... |
536 |
printk(KERN_INFO BSG_DESCRIPTION " version " BSG_VERSION |
0ed081ce2 bsg: minor cleanup |
537 538 |
" loaded (major %d) ", bsg_major); |
3d6392cfb bsg: support for ... |
539 |
return 0; |
9b9f770ce bsg: fix initiali... |
540 541 542 543 |
unregister_chrdev: unregister_chrdev_region(MKDEV(bsg_major, 0), BSG_MAX_DEVS); destroy_bsg_class: class_destroy(bsg_class); |
9b9f770ce bsg: fix initiali... |
544 |
return ret; |
3d6392cfb bsg: support for ... |
545 546 547 |
} MODULE_AUTHOR("Jens Axboe"); |
0ed081ce2 bsg: minor cleanup |
548 |
MODULE_DESCRIPTION(BSG_DESCRIPTION); |
3d6392cfb bsg: support for ... |
549 |
MODULE_LICENSE("GPL"); |
4e2872d6b bind bsg to all S... |
550 |
device_initcall(bsg_init); |