};
 
 #define BSG_DEFAULT_CMDS       64
+#define BSG_MAX_DEVS           32768
 
 #undef BSG_DEBUG
 
 #define BSG_MAJOR      (240)
 
 static DEFINE_MUTEX(bsg_mutex);
-static int bsg_device_nr;
+static int bsg_device_nr, bsg_minor_idx;
 
 #define BSG_LIST_SIZE  (8)
 #define bsg_list_idx(minor)    ((minor) & (BSG_LIST_SIZE - 1))
        class_device_destroy(bsg_class, MKDEV(BSG_MAJOR, bcd->minor));
        bcd->class_dev = NULL;
        list_del_init(&bcd->list);
+       bsg_device_nr--;
        mutex_unlock(&bsg_mutex);
 }
 
 int bsg_register_queue(struct request_queue *q, char *name)
 {
-       struct bsg_class_device *bcd;
+       struct bsg_class_device *bcd, *__bcd;
        dev_t dev;
-       int ret;
+       int ret = -EMFILE;
        struct class_device *class_dev = NULL;
 
        /*
        INIT_LIST_HEAD(&bcd->list);
 
        mutex_lock(&bsg_mutex);
-       dev = MKDEV(BSG_MAJOR, bsg_device_nr);
-       bcd->minor = bsg_device_nr;
-       bsg_device_nr++;
+       if (bsg_device_nr == BSG_MAX_DEVS) {
+               printk(KERN_ERR "bsg: too many bsg devices\n");
+               goto err;
+       }
+
+retry:
+       list_for_each_entry(__bcd, &bsg_class_list, list) {
+               if (__bcd->minor == bsg_minor_idx) {
+                       bsg_minor_idx++;
+                       if (bsg_minor_idx == BSG_MAX_DEVS)
+                               bsg_minor_idx = 0;
+                       goto retry;
+               }
+       }
+
+       bcd->minor = bsg_minor_idx++;
+       if (bsg_minor_idx == BSG_MAX_DEVS)
+               bsg_minor_idx = 0;
+
        bcd->queue = q;
+       dev = MKDEV(BSG_MAJOR, bcd->minor);
        class_dev = class_device_create(bsg_class, NULL, dev, bcd->dev, "%s", name);
        if (IS_ERR(class_dev)) {
                ret = PTR_ERR(class_dev);
        }
 
        list_add_tail(&bcd->list, &bsg_class_list);
+       bsg_device_nr++;
 
        mutex_unlock(&bsg_mutex);
        return 0;
 err:
-       bsg_device_nr--;
        if (class_dev)
                class_device_destroy(bsg_class, MKDEV(BSG_MAJOR, bcd->minor));
        mutex_unlock(&bsg_mutex);
        .remove = bsg_remove,
 };
 
+static struct cdev bsg_cdev = {
+       .kobj   = {.name = "bsg", },
+       .owner  = THIS_MODULE,
+};
+
 static int __init bsg_init(void)
 {
        int ret, i;
                return PTR_ERR(bsg_class);
        }
 
-       ret = register_chrdev(BSG_MAJOR, "bsg", &bsg_fops);
+       ret = register_chrdev_region(MKDEV(BSG_MAJOR, 0), BSG_MAX_DEVS, "bsg");
+       if (ret) {
+               kmem_cache_destroy(bsg_cmd_cachep);
+               class_destroy(bsg_class);
+               return ret;
+       }
+
+       cdev_init(&bsg_cdev, &bsg_fops);
+       ret = cdev_add(&bsg_cdev, MKDEV(BSG_MAJOR, 0), BSG_MAX_DEVS);
        if (ret) {
                kmem_cache_destroy(bsg_cmd_cachep);
                class_destroy(bsg_class);
+               unregister_chrdev_region(MKDEV(BSG_MAJOR, 0), BSG_MAX_DEVS);
                return ret;
        }