aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/bsg.c49
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
77static DEFINE_MUTEX(bsg_mutex); 78static DEFINE_MUTEX(bsg_mutex);
78static int bsg_device_nr; 79static 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
963int bsg_register_queue(struct request_queue *q, char *name) 965int 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
988retry:
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;
1002err: 1022err:
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
1052static struct cdev bsg_cdev = {
1053 .kobj = {.name = "bsg", },
1054 .owner = THIS_MODULE,
1055};
1056
1033static int __init bsg_init(void) 1057static 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