From 3d6392cfbd7dc11f23058e3493683afab4ac13a3 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 9 Jul 2007 12:38:05 +0200 Subject: bsg: support for full generic block layer SG v3 Signed-off-by: Jens Axboe --- include/linux/bsg.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 include/linux/bsg.h (limited to 'include/linux/bsg.h') diff --git a/include/linux/bsg.h b/include/linux/bsg.h new file mode 100644 index 00000000000..dc0d7282c4c --- /dev/null +++ b/include/linux/bsg.h @@ -0,0 +1,21 @@ +#ifndef BSG_H +#define BSG_H + +#if defined(CONFIG_BLK_DEV_BSG) +struct bsg_class_device { + struct class_device *class_dev; + struct device *dev; + int minor; + struct gendisk *disk; + struct list_head list; +}; + +extern int bsg_register_disk(struct gendisk *); +extern void bsg_unregister_disk(struct gendisk *); +#else +struct bsg_class_device { }; +#define bsg_register_disk(disk) (0) +#define bsg_unregister_disk(disk) do { } while (0) +#endif + +#endif -- cgit v1.2.3-70-g09d2 From 45977d0e87ac988d04fccfb89221727aaf8d78a4 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 20 Dec 2006 11:19:32 +0100 Subject: bsg: add sg_io_v4 structure This patch adds sg_io_v4 structure that Doug proposed last month. There's one major change from the RFC. I dropped iovec, which needs compat stuff. The bsg code simply calls blk_rq_map_user against dout_xferp/din_xferp. So if possible, the page frames are directly mapped. If not possible, the block layer allocates new page frames and does memory copies. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- include/linux/bsg.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'include/linux/bsg.h') diff --git a/include/linux/bsg.h b/include/linux/bsg.h index dc0d7282c4c..0d212cc06ab 100644 --- a/include/linux/bsg.h +++ b/include/linux/bsg.h @@ -1,6 +1,47 @@ #ifndef BSG_H #define BSG_H +struct sg_io_v4 { + int32_t guard; /* [i] 'Q' to differentiate from v3 */ + uint32_t protocol; /* [i] 0 -> SCSI , .... */ + uint32_t subprotocol; /* [i] 0 -> SCSI command, 1 -> SCSI task + management function, .... */ + + uint32_t request_len; /* [i] in bytes */ + uint64_t request; /* [i], [*i] {SCSI: cdb} */ + uint32_t request_attr; /* [i] {SCSI: task attribute} */ + uint32_t request_tag; /* [i] {SCSI: task tag (only if flagged)} */ + uint32_t request_priority; /* [i] {SCSI: task priority} */ + uint32_t max_response_len; /* [i] in bytes */ + uint64_t response; /* [i], [*o] {SCSI: (auto)sense data} */ + + /* "din_" for data in (from device); "dout_" for data out (to device) */ + uint32_t dout_xfer_len; /* [i] bytes to be transferred to device */ + uint32_t din_xfer_len; /* [i] bytes to be transferred from device */ + uint64_t dout_xferp; /* [i], [*i] */ + uint64_t din_xferp; /* [i], [*o] */ + + uint32_t timeout; /* [i] units: millisecond */ + uint32_t flags; /* [i] bit mask */ + uint64_t usr_ptr; /* [i->o] unused internally */ + uint32_t spare_in; /* [i] */ + + uint32_t driver_status; /* [o] 0 -> ok */ + uint32_t transport_status; /* [o] 0 -> ok */ + uint32_t device_status; /* [o] {SCSI: command completion status} */ + uint32_t retry_delay; /* [o] {SCSI: status auxiliary information} */ + uint32_t info; /* [o] additional information */ + uint32_t duration; /* [o] time to complete, in milliseconds */ + uint32_t response_len; /* [o] bytes of response actually written */ + int32_t din_resid; /* [o] actual_din_xfer_len - din_xfer_len */ + uint32_t generated_tag; /* [o] {SCSI: task tag that transport chose} */ + uint32_t spare_out; /* [o] */ + + uint32_t padding; +}; + +#ifdef __KERNEL__ + #if defined(CONFIG_BLK_DEV_BSG) struct bsg_class_device { struct class_device *class_dev; @@ -18,4 +59,6 @@ struct bsg_class_device { }; #define bsg_unregister_disk(disk) do { } while (0) #endif +#endif /* __KERNEL__ */ + #endif -- cgit v1.2.3-70-g09d2 From 1594a3f0eb526c73bc3915e8da13f2abf0ea1acd Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 20 Dec 2006 11:23:35 +0100 Subject: bsg: use u32 etc instead of uint32_t Signed-off-by: Jens Axboe --- include/linux/bsg.h | 58 ++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'include/linux/bsg.h') diff --git a/include/linux/bsg.h b/include/linux/bsg.h index 0d212cc06ab..f968726cfad 100644 --- a/include/linux/bsg.h +++ b/include/linux/bsg.h @@ -2,42 +2,42 @@ #define BSG_H struct sg_io_v4 { - int32_t guard; /* [i] 'Q' to differentiate from v3 */ - uint32_t protocol; /* [i] 0 -> SCSI , .... */ - uint32_t subprotocol; /* [i] 0 -> SCSI command, 1 -> SCSI task + s32 guard; /* [i] 'Q' to differentiate from v3 */ + u32 protocol; /* [i] 0 -> SCSI , .... */ + u32 subprotocol; /* [i] 0 -> SCSI command, 1 -> SCSI task management function, .... */ - uint32_t request_len; /* [i] in bytes */ - uint64_t request; /* [i], [*i] {SCSI: cdb} */ - uint32_t request_attr; /* [i] {SCSI: task attribute} */ - uint32_t request_tag; /* [i] {SCSI: task tag (only if flagged)} */ - uint32_t request_priority; /* [i] {SCSI: task priority} */ - uint32_t max_response_len; /* [i] in bytes */ - uint64_t response; /* [i], [*o] {SCSI: (auto)sense data} */ + u32 request_len; /* [i] in bytes */ + u64 request; /* [i], [*i] {SCSI: cdb} */ + u32 request_attr; /* [i] {SCSI: task attribute} */ + u32 request_tag; /* [i] {SCSI: task tag (only if flagged)} */ + u32 request_priority; /* [i] {SCSI: task priority} */ + u32 max_response_len; /* [i] in bytes */ + u64 response; /* [i], [*o] {SCSI: (auto)sense data} */ /* "din_" for data in (from device); "dout_" for data out (to device) */ - uint32_t dout_xfer_len; /* [i] bytes to be transferred to device */ - uint32_t din_xfer_len; /* [i] bytes to be transferred from device */ - uint64_t dout_xferp; /* [i], [*i] */ - uint64_t din_xferp; /* [i], [*o] */ + u32 dout_xfer_len; /* [i] bytes to be transferred to device */ + u32 din_xfer_len; /* [i] bytes to be transferred from device */ + u64 dout_xferp; /* [i], [*i] */ + u64 din_xferp; /* [i], [*o] */ - uint32_t timeout; /* [i] units: millisecond */ - uint32_t flags; /* [i] bit mask */ - uint64_t usr_ptr; /* [i->o] unused internally */ - uint32_t spare_in; /* [i] */ + u32 timeout; /* [i] units: millisecond */ + u32 flags; /* [i] bit mask */ + u64 usr_ptr; /* [i->o] unused internally */ + u32 spare_in; /* [i] */ - uint32_t driver_status; /* [o] 0 -> ok */ - uint32_t transport_status; /* [o] 0 -> ok */ - uint32_t device_status; /* [o] {SCSI: command completion status} */ - uint32_t retry_delay; /* [o] {SCSI: status auxiliary information} */ - uint32_t info; /* [o] additional information */ - uint32_t duration; /* [o] time to complete, in milliseconds */ - uint32_t response_len; /* [o] bytes of response actually written */ - int32_t din_resid; /* [o] actual_din_xfer_len - din_xfer_len */ - uint32_t generated_tag; /* [o] {SCSI: task tag that transport chose} */ - uint32_t spare_out; /* [o] */ + u32 driver_status; /* [o] 0 -> ok */ + u32 transport_status; /* [o] 0 -> ok */ + u32 device_status; /* [o] {SCSI: command completion status} */ + u32 retry_delay; /* [o] {SCSI: status auxiliary information} */ + u32 info; /* [o] additional information */ + u32 duration; /* [o] time to complete, in milliseconds */ + u32 response_len; /* [o] bytes of response actually written */ + s32 din_resid; /* [o] actual_din_xfer_len - din_xfer_len */ + u32 generated_tag; /* [o] {SCSI: task tag that transport chose} */ + u32 spare_out; /* [o] */ - uint32_t padding; + u32 padding; }; #ifdef __KERNEL__ -- cgit v1.2.3-70-g09d2 From 3862153b673516b2efa0447b9b3778f47ac8f8c8 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 22 Dec 2006 09:43:51 +0100 Subject: Replace s32, u32 and u64 with __s32, __u32 and __u64 in bsg.h for userspace Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- include/linux/bsg.h | 58 ++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'include/linux/bsg.h') diff --git a/include/linux/bsg.h b/include/linux/bsg.h index f968726cfad..2154a6dfbd5 100644 --- a/include/linux/bsg.h +++ b/include/linux/bsg.h @@ -2,42 +2,42 @@ #define BSG_H struct sg_io_v4 { - s32 guard; /* [i] 'Q' to differentiate from v3 */ - u32 protocol; /* [i] 0 -> SCSI , .... */ - u32 subprotocol; /* [i] 0 -> SCSI command, 1 -> SCSI task + __s32 guard; /* [i] 'Q' to differentiate from v3 */ + __u32 protocol; /* [i] 0 -> SCSI , .... */ + __u32 subprotocol; /* [i] 0 -> SCSI command, 1 -> SCSI task management function, .... */ - u32 request_len; /* [i] in bytes */ - u64 request; /* [i], [*i] {SCSI: cdb} */ - u32 request_attr; /* [i] {SCSI: task attribute} */ - u32 request_tag; /* [i] {SCSI: task tag (only if flagged)} */ - u32 request_priority; /* [i] {SCSI: task priority} */ - u32 max_response_len; /* [i] in bytes */ - u64 response; /* [i], [*o] {SCSI: (auto)sense data} */ + __u32 request_len; /* [i] in bytes */ + __u64 request; /* [i], [*i] {SCSI: cdb} */ + __u32 request_attr; /* [i] {SCSI: task attribute} */ + __u32 request_tag; /* [i] {SCSI: task tag (only if flagged)} */ + __u32 request_priority; /* [i] {SCSI: task priority} */ + __u32 max_response_len; /* [i] in bytes */ + __u64 response; /* [i], [*o] {SCSI: (auto)sense data} */ /* "din_" for data in (from device); "dout_" for data out (to device) */ - u32 dout_xfer_len; /* [i] bytes to be transferred to device */ - u32 din_xfer_len; /* [i] bytes to be transferred from device */ - u64 dout_xferp; /* [i], [*i] */ - u64 din_xferp; /* [i], [*o] */ + __u32 dout_xfer_len; /* [i] bytes to be transferred to device */ + __u32 din_xfer_len; /* [i] bytes to be transferred from device */ + __u64 dout_xferp; /* [i], [*i] */ + __u64 din_xferp; /* [i], [*o] */ - u32 timeout; /* [i] units: millisecond */ - u32 flags; /* [i] bit mask */ - u64 usr_ptr; /* [i->o] unused internally */ - u32 spare_in; /* [i] */ + __u32 timeout; /* [i] units: millisecond */ + __u32 flags; /* [i] bit mask */ + __u64 usr_ptr; /* [i->o] unused internally */ + __u32 spare_in; /* [i] */ - u32 driver_status; /* [o] 0 -> ok */ - u32 transport_status; /* [o] 0 -> ok */ - u32 device_status; /* [o] {SCSI: command completion status} */ - u32 retry_delay; /* [o] {SCSI: status auxiliary information} */ - u32 info; /* [o] additional information */ - u32 duration; /* [o] time to complete, in milliseconds */ - u32 response_len; /* [o] bytes of response actually written */ - s32 din_resid; /* [o] actual_din_xfer_len - din_xfer_len */ - u32 generated_tag; /* [o] {SCSI: task tag that transport chose} */ - u32 spare_out; /* [o] */ + __u32 driver_status; /* [o] 0 -> ok */ + __u32 transport_status; /* [o] 0 -> ok */ + __u32 device_status; /* [o] {SCSI: command completion status} */ + __u32 retry_delay; /* [o] {SCSI: status auxiliary information} */ + __u32 info; /* [o] additional information */ + __u32 duration; /* [o] time to complete, in milliseconds */ + __u32 response_len; /* [o] bytes of response actually written */ + __s32 din_resid; /* [o] actual_din_xfer_len - din_xfer_len */ + __u32 generated_tag; /* [o] {SCSI: task tag that transport chose} */ + __u32 spare_out; /* [o] */ - u32 padding; + __u32 padding; }; #ifdef __KERNEL__ -- cgit v1.2.3-70-g09d2 From d351af01b9307566135cb0f355ca65d0952c10b5 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 9 Jul 2007 12:40:35 +0200 Subject: bsg: bind bsg to request_queue instead of gendisk This patch binds bsg devices to request_queue instead of gendisk. Any objects (like transport entities) can define own request_handler and create own bsg device. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- block/bsg.c | 37 +++++++++++++++++-------------------- block/ll_rw_blk.c | 4 ++-- include/linux/blkdev.h | 5 +++++ include/linux/bsg.h | 10 +++++----- include/linux/genhd.h | 2 -- 5 files changed, 29 insertions(+), 29 deletions(-) (limited to 'include/linux/bsg.h') diff --git a/block/bsg.c b/block/bsg.c index 0427ece9b6d..4ea4bedb413 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -34,7 +34,6 @@ static char bsg_version[] = "block layer sg (bsg) 0.4"; struct bsg_device { - struct gendisk *disk; request_queue_t *queue; spinlock_t lock; struct list_head busy_list; @@ -46,7 +45,7 @@ struct bsg_device { int done_cmds; wait_queue_head_t wq_done; wait_queue_head_t wq_free; - char name[BDEVNAME_SIZE]; + char name[BUS_ID_SIZE]; int max_queue; unsigned long flags; }; @@ -375,7 +374,7 @@ static void bsg_add_command(struct bsg_device *bd, request_queue_t *q, dprintk("%s: queueing rq %p, bc %p\n", bd->name, rq, bc); rq->end_io_data = bc; - blk_execute_rq_nowait(q, bd->disk, rq, 1, bsg_rq_end_io); + blk_execute_rq_nowait(q, NULL, rq, 1, bsg_rq_end_io); } static inline struct bsg_command *bsg_next_done_cmd(struct bsg_device *bd) @@ -741,7 +740,7 @@ out: } static struct bsg_device *bsg_add_device(struct inode *inode, - struct gendisk *disk, + struct request_queue *rq, struct file *file) { struct bsg_device *bd = NULL; @@ -753,17 +752,16 @@ static struct bsg_device *bsg_add_device(struct inode *inode, if (!bd) return ERR_PTR(-ENOMEM); - bd->disk = disk; - bd->queue = disk->queue; - kobject_get(&disk->queue->kobj); + bd->queue = rq; + kobject_get(&rq->kobj); bsg_set_block(bd, file); atomic_set(&bd->ref_count, 1); bd->minor = iminor(inode); mutex_lock(&bsg_mutex); - hlist_add_head(&bd->dev_list,&bsg_device_list[bsg_list_idx(bd->minor)]); + hlist_add_head(&bd->dev_list, &bsg_device_list[bsg_list_idx(bd->minor)]); - strncpy(bd->name, disk->disk_name, sizeof(bd->name) - 1); + strncpy(bd->name, rq->bsg_dev.class_dev->class_id, sizeof(bd->name) - 1); dprintk("bound to <%s>, max queue %d\n", format_dev_t(buf, inode->i_rdev), bd->max_queue); @@ -817,7 +815,7 @@ static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file) if (!bcd) return ERR_PTR(-ENODEV); - return bsg_add_device(inode, bcd->disk, file); + return bsg_add_device(inode, bcd->queue, file); } static int bsg_open(struct inode *inode, struct file *file) @@ -900,7 +898,7 @@ bsg_ioctl(struct inode *inode, struct file *file, unsigned int cmd, case SG_EMULATED_HOST: case SCSI_IOCTL_SEND_COMMAND: { void __user *uarg = (void __user *) arg; - return scsi_cmd_ioctl(file, bd->queue, bd->disk, cmd, uarg); + return scsi_cmd_ioctl(file, bd->queue, NULL, cmd, uarg); } case SG_IO: { struct request *rq; @@ -915,7 +913,7 @@ bsg_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return PTR_ERR(rq); bio = rq->bio; - blk_execute_rq(bd->queue, bd->disk, rq, 0); + blk_execute_rq(bd->queue, NULL, rq, 0); blk_complete_sgv4_hdr_rq(rq, &hdr, bio); if (copy_to_user(uarg, &hdr, sizeof(hdr))) @@ -945,24 +943,23 @@ static struct file_operations bsg_fops = { .owner = THIS_MODULE, }; -void bsg_unregister_disk(struct gendisk *disk) +void bsg_unregister_queue(struct request_queue *q) { - struct bsg_class_device *bcd = &disk->bsg_dev; + struct bsg_class_device *bcd = &q->bsg_dev; if (!bcd->class_dev) return; mutex_lock(&bsg_mutex); - sysfs_remove_link(&bcd->disk->queue->kobj, "bsg"); + sysfs_remove_link(&q->kobj, "bsg"); class_device_destroy(bsg_class, MKDEV(BSG_MAJOR, bcd->minor)); bcd->class_dev = NULL; list_del_init(&bcd->list); mutex_unlock(&bsg_mutex); } -int bsg_register_disk(struct gendisk *disk) +int bsg_register_queue(struct request_queue *q, char *name) { - request_queue_t *q = disk->queue; struct bsg_class_device *bcd; dev_t dev; @@ -972,7 +969,7 @@ int bsg_register_disk(struct gendisk *disk) if (!q->request_fn) return 0; - bcd = &disk->bsg_dev; + bcd = &q->bsg_dev; memset(bcd, 0, sizeof(*bcd)); INIT_LIST_HEAD(&bcd->list); @@ -980,8 +977,8 @@ int bsg_register_disk(struct gendisk *disk) dev = MKDEV(BSG_MAJOR, bsg_device_nr); bcd->minor = bsg_device_nr; bsg_device_nr++; - bcd->disk = disk; - bcd->class_dev = class_device_create(bsg_class, NULL, dev, bcd->dev, "%s", disk->disk_name); + bcd->queue = q; + bcd->class_dev = class_device_create(bsg_class, NULL, dev, bcd->dev, "%s", name); if (!bcd->class_dev) goto err; list_add_tail(&bcd->list, &bsg_class_list); diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 3795e0708a2..74a5498c29a 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -4091,7 +4091,7 @@ int blk_register_queue(struct gendisk *disk) return ret; } - ret = bsg_register_disk(disk); + ret = bsg_register_queue(q, disk->disk_name); if (ret) { elv_unregister_queue(q); kobject_unregister(&q->kobj); @@ -4106,7 +4106,7 @@ void blk_unregister_queue(struct gendisk *disk) request_queue_t *q = disk->queue; if (q && q->request_fn) { - bsg_unregister_disk(disk); + bsg_unregister_queue(q); elv_unregister_queue(q); kobject_uevent(&q->kobj, KOBJ_REMOVE); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 2746632c226..24b474e05a4 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -470,6 +471,10 @@ struct request_queue unsigned int bi_size; struct mutex sysfs_lock; + +#if defined(CONFIG_BLK_DEV_BSG) + struct bsg_class_device bsg_dev; +#endif }; #define QUEUE_FLAG_CLUSTER 0 /* cluster several segments into 1 */ diff --git a/include/linux/bsg.h b/include/linux/bsg.h index 2154a6dfbd5..0475a6d3ff6 100644 --- a/include/linux/bsg.h +++ b/include/linux/bsg.h @@ -47,16 +47,16 @@ struct bsg_class_device { struct class_device *class_dev; struct device *dev; int minor; - struct gendisk *disk; struct list_head list; + struct request_queue *queue; }; -extern int bsg_register_disk(struct gendisk *); -extern void bsg_unregister_disk(struct gendisk *); +extern int bsg_register_queue(struct request_queue *, char *); +extern void bsg_unregister_queue(struct request_queue *); #else struct bsg_class_device { }; -#define bsg_register_disk(disk) (0) -#define bsg_unregister_disk(disk) do { } while (0) +#define bsg_register_queue(disk, name) (0) +#define bsg_unregister_queue(disk) do { } while (0) #endif #endif /* __KERNEL__ */ diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 8c43d703261..9756fc102a8 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -67,7 +67,6 @@ struct partition { #include #include #include -#include struct partition { unsigned char boot_ind; /* 0x80 - active */ @@ -92,7 +91,6 @@ struct hd_struct { #ifdef CONFIG_FAIL_MAKE_REQUEST int make_it_fail; #endif - struct bsg_class_device bsg_dev; }; #define GENHD_FL_REMOVABLE 1 -- cgit v1.2.3-70-g09d2 From 4cf0723ac89b5f2189da2ad07ef875de26b83c77 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 30 Mar 2007 11:19:39 +0200 Subject: bsg: minor bug fixes This fixes the following minor issues: - add EXPORT_SYMBOL_GPL for bsg_register_queue and bsg_unregister_queue. - shut up gcc warnings Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- block/bsg.c | 4 +++- include/linux/bsg.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'include/linux/bsg.h') diff --git a/block/bsg.c b/block/bsg.c index 4ef3cc55024..a333c933709 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -961,8 +961,9 @@ void bsg_unregister_queue(struct request_queue *q) bsg_device_nr--; mutex_unlock(&bsg_mutex); } +EXPORT_SYMBOL_GPL(bsg_unregister_queue); -int bsg_register_queue(struct request_queue *q, char *name) +int bsg_register_queue(struct request_queue *q, const char *name) { struct bsg_class_device *bcd, *__bcd; dev_t dev; @@ -1025,6 +1026,7 @@ err: mutex_unlock(&bsg_mutex); return ret; } +EXPORT_SYMBOL_GPL(bsg_register_queue); static int bsg_add(struct class_device *cl_dev, struct class_interface *cl_intf) { diff --git a/include/linux/bsg.h b/include/linux/bsg.h index 0475a6d3ff6..0dd01f90ba5 100644 --- a/include/linux/bsg.h +++ b/include/linux/bsg.h @@ -51,7 +51,7 @@ struct bsg_class_device { struct request_queue *queue; }; -extern int bsg_register_queue(struct request_queue *, char *); +extern int bsg_register_queue(struct request_queue *, const char *); extern void bsg_unregister_queue(struct request_queue *); #else struct bsg_class_device { }; -- cgit v1.2.3-70-g09d2 From 15d10b611fa94b52f004a08a1d4cf7b39de3cba3 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 16 Jul 2007 08:52:16 +0200 Subject: bsg: add SCSI transport-level request support This enables bsg to handle SCSI transport-level request like SAS management protocol (SMP). - add BSG_SUB_PROTOCOL_{SCSI_CMD, SCSI_TMF, SCSI_TRANSPORT} definitions. - SCSI transport-level requests skip blk_verify_command(). Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- block/bsg.c | 27 +++++++++++++++++++++------ include/linux/bsg.h | 6 ++++++ 2 files changed, 27 insertions(+), 6 deletions(-) (limited to 'include/linux/bsg.h') diff --git a/block/bsg.c b/block/bsg.c index 13ecc951a4c..461c9f56f3e 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -208,7 +208,11 @@ static int blk_fill_sgv4_hdr_rq(request_queue_t *q, struct request *rq, if (copy_from_user(rq->cmd, (void *)(unsigned long)hdr->request, hdr->request_len)) return -EFAULT; - if (blk_verify_command(rq->cmd, has_write_perm)) + + if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) { + if (blk_verify_command(rq->cmd, has_write_perm)) + return -EPERM; + } else if (!capable(CAP_SYS_RAWIO)) return -EPERM; /* @@ -232,6 +236,8 @@ static int blk_fill_sgv4_hdr_rq(request_queue_t *q, struct request *rq, static int bsg_validate_sgv4_hdr(request_queue_t *q, struct sg_io_v4 *hdr, int *rw) { + int ret = 0; + if (hdr->guard != 'Q') return -EINVAL; if (hdr->request_len > BLK_MAX_CDB) @@ -240,13 +246,22 @@ bsg_validate_sgv4_hdr(request_queue_t *q, struct sg_io_v4 *hdr, int *rw) hdr->din_xfer_len > (q->max_sectors << 9)) return -EIO; - /* not supported currently */ - if (hdr->protocol || hdr->subprotocol) - return -EINVAL; + switch (hdr->protocol) { + case BSG_PROTOCOL_SCSI: + switch (hdr->subprotocol) { + case BSG_SUB_PROTOCOL_SCSI_CMD: + case BSG_SUB_PROTOCOL_SCSI_TRANSPORT: + break; + default: + ret = -EINVAL; + } + break; + default: + ret = -EINVAL; + } *rw = hdr->dout_xfer_len ? WRITE : READ; - - return 0; + return ret; } /* diff --git a/include/linux/bsg.h b/include/linux/bsg.h index 0dd01f90ba5..bd998ca6cb2 100644 --- a/include/linux/bsg.h +++ b/include/linux/bsg.h @@ -1,6 +1,12 @@ #ifndef BSG_H #define BSG_H +#define BSG_PROTOCOL_SCSI 0 + +#define BSG_SUB_PROTOCOL_SCSI_CMD 0 +#define BSG_SUB_PROTOCOL_SCSI_TMF 1 +#define BSG_SUB_PROTOCOL_SCSI_TRANSPORT 2 + struct sg_io_v4 { __s32 guard; /* [i] 'Q' to differentiate from v3 */ __u32 protocol; /* [i] 0 -> SCSI , .... */ -- cgit v1.2.3-70-g09d2