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