diff options
author | Marcin Chrzanowski <marcin.j.chrzanowski@gmail.com> | 2018-05-28 22:50:44 +0200 |
---|---|---|
committer | Marcin Chrzanowski <marcin.j.chrzanowski@gmail.com> | 2018-05-28 22:50:44 +0200 |
commit | 34d2c2e0137b3ad637a3cfa9c7afbdf636fc6384 (patch) | |
tree | d86ebb9b8e283e83811ecbc6f88b09acd0986cc1 | |
parent | a40c683a8cf32a15b67eaa5ecc1a11f72fb4fb42 (diff) |
Allocate minor numbers sensibly
-rw-r--r-- | char.c | 27 |
1 files changed, 22 insertions, 5 deletions
@@ -121,6 +121,23 @@ struct file_operations doomdev_fops = { struct class *doom_class; +int alloc_minor(void) { + int i; + + for (i = 0; i < DOOMDEV_COUNT; i++) { + if (!minors[i]) { + minors[i] = true; + return i; + } + } + + return -EOVERFLOW; +} + +void free_minor(int minor) { + minors[minor] = false; +} + int new_doomdev(struct pci_dev *dev) { int err = 0; @@ -128,16 +145,13 @@ int new_doomdev(struct pci_dev *dev) struct doom_data *doom_data; dev_t devt; - if (next_minor >= DOOMDEV_COUNT) { - return -EOVERFLOW; - } - doom_data = pci_get_drvdata(dev); cdev_init(&doom_data->cdev, &doomdev_fops); ORFAIL(cdev_add(&doom_data->cdev, first, 1), error_add); - minor = next_minor++; + minor = alloc_minor(); + ORFAIL(minor, error_minor); devt = MKDEV(major, minor); doom_data->device = device_create(doom_class, &dev->dev, devt, NULL, "doom%d", minor); @@ -146,6 +160,8 @@ int new_doomdev(struct pci_dev *dev) return 0; error_create: + free_minor(minor); +error_minor: cdev_del(&doom_data->cdev); error_add: return err; @@ -153,6 +169,7 @@ error_add: void destroy_doomdev(struct doom_data *doom_data) { + free_minor(MINOR(doom_data->device->devt)); device_destroy(doom_class, doom_data->device->devt); cdev_del(&doom_data->cdev); } |