m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
path: root/char.c
diff options
context:
space:
mode:
Diffstat (limited to 'char.c')
-rw-r--r--char.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/char.c b/char.c
index 90bd16c..cdf4029 100644
--- a/char.c
+++ b/char.c
@@ -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);
}