diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/Kconfig | 2 | ||||
-rw-r--r-- | block/bsg.c | 61 | ||||
-rw-r--r-- | block/scsi_ioctl.c | 13 |
3 files changed, 29 insertions, 47 deletions
diff --git a/block/Kconfig b/block/Kconfig index 0768741d6813..ca2ef4e08497 100644 --- a/block/Kconfig +++ b/block/Kconfig | |||
@@ -53,7 +53,7 @@ endif # BLOCK | |||
53 | 53 | ||
54 | config BLK_DEV_BSG | 54 | config BLK_DEV_BSG |
55 | bool "Block layer SG support v4 (EXPERIMENTAL)" | 55 | bool "Block layer SG support v4 (EXPERIMENTAL)" |
56 | depends on (SCSI=y) && EXPERIMENTAL | 56 | depends on EXPERIMENTAL |
57 | ---help--- | 57 | ---help--- |
58 | Saying Y here will enable generic SG (SCSI generic) v4 support | 58 | Saying Y here will enable generic SG (SCSI generic) v4 support |
59 | for any block device. | 59 | for any block device. |
diff --git a/block/bsg.c b/block/bsg.c index f2992e72b841..b571869928a8 100644 --- a/block/bsg.c +++ b/block/bsg.c | |||
@@ -932,24 +932,34 @@ void bsg_unregister_queue(struct request_queue *q) | |||
932 | { | 932 | { |
933 | struct bsg_class_device *bcd = &q->bsg_dev; | 933 | struct bsg_class_device *bcd = &q->bsg_dev; |
934 | 934 | ||
935 | WARN_ON(!bcd->class_dev); | 935 | if (!bcd->class_dev) |
936 | return; | ||
936 | 937 | ||
937 | mutex_lock(&bsg_mutex); | 938 | mutex_lock(&bsg_mutex); |
938 | sysfs_remove_link(&q->kobj, "bsg"); | 939 | sysfs_remove_link(&q->kobj, "bsg"); |
939 | class_device_destroy(bsg_class, MKDEV(bsg_major, bcd->minor)); | 940 | class_device_unregister(bcd->class_dev); |
941 | put_device(bcd->dev); | ||
940 | bcd->class_dev = NULL; | 942 | bcd->class_dev = NULL; |
943 | bcd->dev = NULL; | ||
941 | list_del_init(&bcd->list); | 944 | list_del_init(&bcd->list); |
942 | bsg_device_nr--; | 945 | bsg_device_nr--; |
943 | mutex_unlock(&bsg_mutex); | 946 | mutex_unlock(&bsg_mutex); |
944 | } | 947 | } |
945 | EXPORT_SYMBOL_GPL(bsg_unregister_queue); | 948 | EXPORT_SYMBOL_GPL(bsg_unregister_queue); |
946 | 949 | ||
947 | int bsg_register_queue(struct request_queue *q, const char *name) | 950 | int bsg_register_queue(struct request_queue *q, struct device *gdev, |
951 | const char *name) | ||
948 | { | 952 | { |
949 | struct bsg_class_device *bcd, *__bcd; | 953 | struct bsg_class_device *bcd, *__bcd; |
950 | dev_t dev; | 954 | dev_t dev; |
951 | int ret = -EMFILE; | 955 | int ret = -EMFILE; |
952 | struct class_device *class_dev = NULL; | 956 | struct class_device *class_dev = NULL; |
957 | const char *devname; | ||
958 | |||
959 | if (name) | ||
960 | devname = name; | ||
961 | else | ||
962 | devname = gdev->bus_id; | ||
953 | 963 | ||
954 | /* | 964 | /* |
955 | * we need a proper transport to send commands, not a stacked device | 965 | * we need a proper transport to send commands, not a stacked device |
@@ -982,18 +992,20 @@ retry: | |||
982 | bsg_minor_idx = 0; | 992 | bsg_minor_idx = 0; |
983 | 993 | ||
984 | bcd->queue = q; | 994 | bcd->queue = q; |
995 | bcd->dev = get_device(gdev); | ||
985 | dev = MKDEV(bsg_major, bcd->minor); | 996 | dev = MKDEV(bsg_major, bcd->minor); |
986 | class_dev = class_device_create(bsg_class, NULL, dev, bcd->dev, "%s", name); | 997 | class_dev = class_device_create(bsg_class, NULL, dev, gdev, "%s", |
998 | devname); | ||
987 | if (IS_ERR(class_dev)) { | 999 | if (IS_ERR(class_dev)) { |
988 | ret = PTR_ERR(class_dev); | 1000 | ret = PTR_ERR(class_dev); |
989 | goto err; | 1001 | goto err_put; |
990 | } | 1002 | } |
991 | bcd->class_dev = class_dev; | 1003 | bcd->class_dev = class_dev; |
992 | 1004 | ||
993 | if (q->kobj.sd) { | 1005 | if (q->kobj.sd) { |
994 | ret = sysfs_create_link(&q->kobj, &bcd->class_dev->kobj, "bsg"); | 1006 | ret = sysfs_create_link(&q->kobj, &bcd->class_dev->kobj, "bsg"); |
995 | if (ret) | 1007 | if (ret) |
996 | goto err; | 1008 | goto err_unregister; |
997 | } | 1009 | } |
998 | 1010 | ||
999 | list_add_tail(&bcd->list, &bsg_class_list); | 1011 | list_add_tail(&bcd->list, &bsg_class_list); |
@@ -1001,37 +1013,17 @@ retry: | |||
1001 | 1013 | ||
1002 | mutex_unlock(&bsg_mutex); | 1014 | mutex_unlock(&bsg_mutex); |
1003 | return 0; | 1015 | return 0; |
1016 | |||
1017 | err_unregister: | ||
1018 | class_device_unregister(class_dev); | ||
1019 | err_put: | ||
1020 | put_device(gdev); | ||
1004 | err: | 1021 | err: |
1005 | if (class_dev) | ||
1006 | class_device_destroy(bsg_class, MKDEV(bsg_major, bcd->minor)); | ||
1007 | mutex_unlock(&bsg_mutex); | 1022 | mutex_unlock(&bsg_mutex); |
1008 | return ret; | 1023 | return ret; |
1009 | } | 1024 | } |
1010 | EXPORT_SYMBOL_GPL(bsg_register_queue); | 1025 | EXPORT_SYMBOL_GPL(bsg_register_queue); |
1011 | 1026 | ||
1012 | static int bsg_add(struct class_device *cl_dev, struct class_interface *cl_intf) | ||
1013 | { | ||
1014 | int ret; | ||
1015 | struct scsi_device *sdp = to_scsi_device(cl_dev->dev); | ||
1016 | struct request_queue *rq = sdp->request_queue; | ||
1017 | |||
1018 | if (rq->kobj.parent) | ||
1019 | ret = bsg_register_queue(rq, kobject_name(rq->kobj.parent)); | ||
1020 | else | ||
1021 | ret = bsg_register_queue(rq, kobject_name(&sdp->sdev_gendev.kobj)); | ||
1022 | return ret; | ||
1023 | } | ||
1024 | |||
1025 | static void bsg_remove(struct class_device *cl_dev, struct class_interface *cl_intf) | ||
1026 | { | ||
1027 | bsg_unregister_queue(to_scsi_device(cl_dev->dev)->request_queue); | ||
1028 | } | ||
1029 | |||
1030 | static struct class_interface bsg_intf = { | ||
1031 | .add = bsg_add, | ||
1032 | .remove = bsg_remove, | ||
1033 | }; | ||
1034 | |||
1035 | static struct cdev bsg_cdev = { | 1027 | static struct cdev bsg_cdev = { |
1036 | .kobj = {.name = "bsg", }, | 1028 | .kobj = {.name = "bsg", }, |
1037 | .owner = THIS_MODULE, | 1029 | .owner = THIS_MODULE, |
@@ -1069,16 +1061,9 @@ static int __init bsg_init(void) | |||
1069 | if (ret) | 1061 | if (ret) |
1070 | goto unregister_chrdev; | 1062 | goto unregister_chrdev; |
1071 | 1063 | ||
1072 | ret = scsi_register_interface(&bsg_intf); | ||
1073 | if (ret) | ||
1074 | goto remove_cdev; | ||
1075 | |||
1076 | printk(KERN_INFO BSG_DESCRIPTION " version " BSG_VERSION | 1064 | printk(KERN_INFO BSG_DESCRIPTION " version " BSG_VERSION |
1077 | " loaded (major %d)\n", bsg_major); | 1065 | " loaded (major %d)\n", bsg_major); |
1078 | return 0; | 1066 | return 0; |
1079 | remove_cdev: | ||
1080 | printk(KERN_ERR "bsg: failed register scsi interface %d\n", ret); | ||
1081 | cdev_del(&bsg_cdev); | ||
1082 | unregister_chrdev: | 1067 | unregister_chrdev: |
1083 | unregister_chrdev_region(MKDEV(bsg_major, 0), BSG_MAX_DEVS); | 1068 | unregister_chrdev_region(MKDEV(bsg_major, 0), BSG_MAX_DEVS); |
1084 | destroy_bsg_class: | 1069 | destroy_bsg_class: |
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 71bdf88884b2..d359a715bbc8 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c | |||
@@ -214,8 +214,8 @@ int blk_verify_command(unsigned char *cmd, int has_write_perm) | |||
214 | } | 214 | } |
215 | EXPORT_SYMBOL_GPL(blk_verify_command); | 215 | EXPORT_SYMBOL_GPL(blk_verify_command); |
216 | 216 | ||
217 | int blk_fill_sghdr_rq(request_queue_t *q, struct request *rq, | 217 | static int blk_fill_sghdr_rq(request_queue_t *q, struct request *rq, |
218 | struct sg_io_hdr *hdr, int has_write_perm) | 218 | struct sg_io_hdr *hdr, int has_write_perm) |
219 | { | 219 | { |
220 | memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */ | 220 | memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */ |
221 | 221 | ||
@@ -238,22 +238,20 @@ int blk_fill_sghdr_rq(request_queue_t *q, struct request *rq, | |||
238 | 238 | ||
239 | return 0; | 239 | return 0; |
240 | } | 240 | } |
241 | EXPORT_SYMBOL_GPL(blk_fill_sghdr_rq); | ||
242 | 241 | ||
243 | /* | 242 | /* |
244 | * unmap a request that was previously mapped to this sg_io_hdr. handles | 243 | * unmap a request that was previously mapped to this sg_io_hdr. handles |
245 | * both sg and non-sg sg_io_hdr. | 244 | * both sg and non-sg sg_io_hdr. |
246 | */ | 245 | */ |
247 | int blk_unmap_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr) | 246 | static int blk_unmap_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr) |
248 | { | 247 | { |
249 | blk_rq_unmap_user(rq->bio); | 248 | blk_rq_unmap_user(rq->bio); |
250 | blk_put_request(rq); | 249 | blk_put_request(rq); |
251 | return 0; | 250 | return 0; |
252 | } | 251 | } |
253 | EXPORT_SYMBOL_GPL(blk_unmap_sghdr_rq); | ||
254 | 252 | ||
255 | int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, | 253 | static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, |
256 | struct bio *bio) | 254 | struct bio *bio) |
257 | { | 255 | { |
258 | int r, ret = 0; | 256 | int r, ret = 0; |
259 | 257 | ||
@@ -287,7 +285,6 @@ int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, | |||
287 | 285 | ||
288 | return r; | 286 | return r; |
289 | } | 287 | } |
290 | EXPORT_SYMBOL_GPL(blk_complete_sghdr_rq); | ||
291 | 288 | ||
292 | static int sg_io(struct file *file, request_queue_t *q, | 289 | static int sg_io(struct file *file, request_queue_t *q, |
293 | struct gendisk *bd_disk, struct sg_io_hdr *hdr) | 290 | struct gendisk *bd_disk, struct sg_io_hdr *hdr) |