m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Chrzanowski <marcin.j.chrzanowski@gmail.com>2018-05-04 17:47:41 +0200
committerMarcin Chrzanowski <marcin.j.chrzanowski@gmail.com>2018-05-04 17:47:41 +0200
commit92ea475ae6afe103cd5b2e68fdc84f02e3aa1657 (patch)
tree3e92c2d9ba0ba1a0f6e226bbd480f4c4656b294b
parent77c090b85d2dc085dce3712d4a5faf8452531d58 (diff)
Fix cdev creation and destruction
-rw-r--r--char.c38
-rw-r--r--pci.h5
2 files changed, 29 insertions, 14 deletions
diff --git a/char.c b/char.c
index b13b08a..4efcb80 100644
--- a/char.c
+++ b/char.c
@@ -37,33 +37,41 @@ int new_doomdev(struct pci_dev *dev)
{
int err = 0;
int minor;
- dev_t devt;
- struct cdev *doom_cdev;
- struct device *doomdev;
struct doom_data *doom_data;
+ dev_t devt;
+
if (next_minor >= DOOMDEV_COUNT) {
return -ENOMEM;
}
- doom_cdev = cdev_alloc();
- if (doom_cdev == NULL) {
+ doom_data = kmalloc(sizeof(*doom_data), GFP_KERNEL);
+ if (doom_data == NULL) {
+ err = -ENOMEM;
+ goto error_kmalloc;
+ }
+
+ doom_data->cdev = cdev_alloc();
+ if (doom_data->cdev == NULL) {
return -ENOMEM;
}
+ cdev_init(doom_data->cdev, &doomdev_fops);
+ ORFAIL(cdev_add(doom_data->cdev, first, 1), error_add);
- doom_cdev->ops = &doomdev_fops;
- ORFAIL(cdev_add(doom_cdev, first, 1), error_add);
minor = next_minor++;
- doom_data = kmalloc(sizeof(*doom_data), GFP_KERNEL);
- doom_data->minor = minor;
- pci_set_drvdata(dev, doom_data);
devt = MKDEV(major, minor);
ORFAIL_PTR(device_create(doom_class, NULL, devt, NULL,
"doom%d", minor),
- doomdev, error_create);
+ doom_data->device, error_create);
+
+ pci_set_drvdata(dev, doom_data);
+
+ return 0;
error_create:
- cdev_del(doom_cdev);
+ cdev_del(doom_data->cdev);
error_add:
+ kfree(doom_data);
+error_kmalloc:
return err;
}
@@ -71,7 +79,8 @@ void destroy_doomdev(struct pci_dev *dev)
{
struct doom_data *data;
data = pci_get_drvdata(dev);
- device_destroy(doom_class, MKDEV(major, data->minor));
+ device_destroy(doom_class, data->device->devt);
+ cdev_del(data->cdev);
kfree(data);
}
@@ -87,6 +96,8 @@ int char_init(void)
goto error_create;
}
+ return 0;
+
error_create:
unregister_chrdev_region(first, DOOMDEV_COUNT);
error_region:
@@ -97,4 +108,5 @@ void char_cleanup(void)
{
unregister_chrdev_region(first, DOOMDEV_COUNT);
class_unregister(doom_class);
+ class_destroy(doom_class);
}
diff --git a/pci.h b/pci.h
index 04c48f2..9e8d07f 100644
--- a/pci.h
+++ b/pci.h
@@ -1,8 +1,11 @@
#ifndef PCI_H
#define PCI_H
+#include <linux/device.h>
+
struct doom_data {
- int minor;
+ struct cdev *cdev;
+ struct device *device;
};
int pci_init(void);