diff options
Diffstat (limited to 'block/bsg.c')
-rw-r--r-- | block/bsg.c | 49 |
1 files changed, 41 insertions, 8 deletions
diff --git a/block/bsg.c b/block/bsg.c index cd0221c61bfe..4ef3cc550244 100644 --- a/block/bsg.c +++ b/block/bsg.c | |||
@@ -58,6 +58,7 @@ enum { | |||
58 | }; | 58 | }; |
59 | 59 | ||
60 | #define BSG_DEFAULT_CMDS 64 | 60 | #define BSG_DEFAULT_CMDS 64 |
61 | #define BSG_MAX_DEVS 32768 | ||
61 | 62 | ||
62 | #undef BSG_DEBUG | 63 | #undef BSG_DEBUG |
63 | 64 | ||
@@ -75,7 +76,7 @@ enum { | |||
75 | #define BSG_MAJOR (240) | 76 | #define BSG_MAJOR (240) |
76 | 77 | ||
77 | static DEFINE_MUTEX(bsg_mutex); | 78 | static DEFINE_MUTEX(bsg_mutex); |
78 | static int bsg_device_nr; | 79 | static int bsg_device_nr, bsg_minor_idx; |
79 | 80 | ||
80 | #define BSG_LIST_SIZE (8) | 81 | #define BSG_LIST_SIZE (8) |
81 | #define bsg_list_idx(minor) ((minor) & (BSG_LIST_SIZE - 1)) | 82 | #define bsg_list_idx(minor) ((minor) & (BSG_LIST_SIZE - 1)) |
@@ -957,14 +958,15 @@ void bsg_unregister_queue(struct request_queue *q) | |||
957 | class_device_destroy(bsg_class, MKDEV(BSG_MAJOR, bcd->minor)); | 958 | class_device_destroy(bsg_class, MKDEV(BSG_MAJOR, bcd->minor)); |
958 | bcd->class_dev = NULL; | 959 | bcd->class_dev = NULL; |
959 | list_del_init(&bcd->list); | 960 | list_del_init(&bcd->list); |
961 | bsg_device_nr--; | ||
960 | mutex_unlock(&bsg_mutex); | 962 | mutex_unlock(&bsg_mutex); |
961 | } | 963 | } |
962 | 964 | ||
963 | int bsg_register_queue(struct request_queue *q, char *name) | 965 | int bsg_register_queue(struct request_queue *q, char *name) |
964 | { | 966 | { |
965 | struct bsg_class_device *bcd; | 967 | struct bsg_class_device *bcd, *__bcd; |
966 | dev_t dev; | 968 | dev_t dev; |
967 | int ret; | 969 | int ret = -EMFILE; |
968 | struct class_device *class_dev = NULL; | 970 | struct class_device *class_dev = NULL; |
969 | 971 | ||
970 | /* | 972 | /* |
@@ -978,10 +980,27 @@ int bsg_register_queue(struct request_queue *q, char *name) | |||
978 | INIT_LIST_HEAD(&bcd->list); | 980 | INIT_LIST_HEAD(&bcd->list); |
979 | 981 | ||
980 | mutex_lock(&bsg_mutex); | 982 | mutex_lock(&bsg_mutex); |
981 | dev = MKDEV(BSG_MAJOR, bsg_device_nr); | 983 | if (bsg_device_nr == BSG_MAX_DEVS) { |
982 | bcd->minor = bsg_device_nr; | 984 | printk(KERN_ERR "bsg: too many bsg devices\n"); |
983 | bsg_device_nr++; | 985 | goto err; |
986 | } | ||
987 | |||
988 | retry: | ||
989 | list_for_each_entry(__bcd, &bsg_class_list, list) { | ||
990 | if (__bcd->minor == bsg_minor_idx) { | ||
991 | bsg_minor_idx++; | ||
992 | if (bsg_minor_idx == BSG_MAX_DEVS) | ||
993 | bsg_minor_idx = 0; | ||
994 | goto retry; | ||
995 | } | ||
996 | } | ||
997 | |||
998 | bcd->minor = bsg_minor_idx++; | ||
999 | if (bsg_minor_idx == BSG_MAX_DEVS) | ||
1000 | bsg_minor_idx = 0; | ||
1001 | |||
984 | bcd->queue = q; | 1002 | bcd->queue = q; |
1003 | dev = MKDEV(BSG_MAJOR, bcd->minor); | ||
985 | class_dev = class_device_create(bsg_class, NULL, dev, bcd->dev, "%s", name); | 1004 | class_dev = class_device_create(bsg_class, NULL, dev, bcd->dev, "%s", name); |
986 | if (IS_ERR(class_dev)) { | 1005 | if (IS_ERR(class_dev)) { |
987 | ret = PTR_ERR(class_dev); | 1006 | ret = PTR_ERR(class_dev); |
@@ -996,11 +1015,11 @@ int bsg_register_queue(struct request_queue *q, char *name) | |||
996 | } | 1015 | } |
997 | 1016 | ||
998 | list_add_tail(&bcd->list, &bsg_class_list); | 1017 | list_add_tail(&bcd->list, &bsg_class_list); |
1018 | bsg_device_nr++; | ||
999 | 1019 | ||
1000 | mutex_unlock(&bsg_mutex); | 1020 | mutex_unlock(&bsg_mutex); |
1001 | return 0; | 1021 | return 0; |
1002 | err: | 1022 | err: |
1003 | bsg_device_nr--; | ||
1004 | if (class_dev) | 1023 | if (class_dev) |
1005 | class_device_destroy(bsg_class, MKDEV(BSG_MAJOR, bcd->minor)); | 1024 | class_device_destroy(bsg_class, MKDEV(BSG_MAJOR, bcd->minor)); |
1006 | mutex_unlock(&bsg_mutex); | 1025 | mutex_unlock(&bsg_mutex); |
@@ -1030,6 +1049,11 @@ static struct class_interface bsg_intf = { | |||
1030 | .remove = bsg_remove, | 1049 | .remove = bsg_remove, |
1031 | }; | 1050 | }; |
1032 | 1051 | ||
1052 | static struct cdev bsg_cdev = { | ||
1053 | .kobj = {.name = "bsg", }, | ||
1054 | .owner = THIS_MODULE, | ||
1055 | }; | ||
1056 | |||
1033 | static int __init bsg_init(void) | 1057 | static int __init bsg_init(void) |
1034 | { | 1058 | { |
1035 | int ret, i; | 1059 | int ret, i; |
@@ -1050,10 +1074,19 @@ static int __init bsg_init(void) | |||
1050 | return PTR_ERR(bsg_class); | 1074 | return PTR_ERR(bsg_class); |
1051 | } | 1075 | } |
1052 | 1076 | ||
1053 | ret = register_chrdev(BSG_MAJOR, "bsg", &bsg_fops); | 1077 | ret = register_chrdev_region(MKDEV(BSG_MAJOR, 0), BSG_MAX_DEVS, "bsg"); |
1078 | if (ret) { | ||
1079 | kmem_cache_destroy(bsg_cmd_cachep); | ||
1080 | class_destroy(bsg_class); | ||
1081 | return ret; | ||
1082 | } | ||
1083 | |||
1084 | cdev_init(&bsg_cdev, &bsg_fops); | ||
1085 | ret = cdev_add(&bsg_cdev, MKDEV(BSG_MAJOR, 0), BSG_MAX_DEVS); | ||
1054 | if (ret) { | 1086 | if (ret) { |
1055 | kmem_cache_destroy(bsg_cmd_cachep); | 1087 | kmem_cache_destroy(bsg_cmd_cachep); |
1056 | class_destroy(bsg_class); | 1088 | class_destroy(bsg_class); |
1089 | unregister_chrdev_region(MKDEV(BSG_MAJOR, 0), BSG_MAX_DEVS); | ||
1057 | return ret; | 1090 | return ret; |
1058 | } | 1091 | } |
1059 | 1092 | ||