aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/counter/counter-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/counter/counter-core.c')
-rw-r--r--drivers/counter/counter-core.c56
1 files changed, 51 insertions, 5 deletions
diff --git a/drivers/counter/counter-core.c b/drivers/counter/counter-core.c
index 3cda2c47bacb..5acc54539623 100644
--- a/drivers/counter/counter-core.c
+++ b/drivers/counter/counter-core.c
@@ -3,14 +3,22 @@
* Generic Counter interface
* Copyright (C) 2020 William Breathitt Gray
*/
+#include <linux/cdev.h>
#include <linux/counter.h>
#include <linux/device.h>
+#include <linux/device/bus.h>
#include <linux/export.h>
+#include <linux/fs.h>
#include <linux/gfp.h>
#include <linux/idr.h>
#include <linux/init.h>
+#include <linux/kdev_t.h>
#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include "counter-chrdev.h"
#include "counter-sysfs.h"
/* Provides a unique ID for each counter device */
@@ -18,6 +26,9 @@ static DEFINE_IDA(counter_ida);
static void counter_device_release(struct device *dev)
{
+ struct counter_device *const counter = dev_get_drvdata(dev);
+
+ counter_chrdev_remove(counter);
ida_free(&counter_ida, dev->id);
}
@@ -31,6 +42,8 @@ static struct bus_type counter_bus_type = {
.dev_name = "counter",
};
+static dev_t counter_devt;
+
/**
* counter_register - register Counter to the system
* @counter: pointer to Counter to register
@@ -53,10 +66,13 @@ int counter_register(struct counter_device *const counter)
if (id < 0)
return id;
+ mutex_init(&counter->ops_exist_lock);
+
/* Configure device structure for Counter */
dev->id = id;
dev->type = &counter_device_type;
dev->bus = &counter_bus_type;
+ dev->devt = MKDEV(MAJOR(counter_devt), id);
if (counter->parent) {
dev->parent = counter->parent;
dev->of_node = counter->parent->of_node;
@@ -64,18 +80,22 @@ int counter_register(struct counter_device *const counter)
device_initialize(dev);
dev_set_drvdata(dev, counter);
- /* Add Counter sysfs attributes */
err = counter_sysfs_add(counter);
if (err < 0)
goto err_free_id;
- /* Add device to system */
- err = device_add(dev);
+ err = counter_chrdev_add(counter);
if (err < 0)
goto err_free_id;
+ err = cdev_device_add(&counter->chrdev, dev);
+ if (err < 0)
+ goto err_remove_chrdev;
+
return 0;
+err_remove_chrdev:
+ counter_chrdev_remove(counter);
err_free_id:
put_device(dev);
return err;
@@ -93,7 +113,16 @@ void counter_unregister(struct counter_device *const counter)
if (!counter)
return;
- device_unregister(&counter->dev);
+ cdev_device_del(&counter->chrdev, &counter->dev);
+
+ mutex_lock(&counter->ops_exist_lock);
+
+ counter->ops = NULL;
+ wake_up(&counter->events_wait);
+
+ mutex_unlock(&counter->ops_exist_lock);
+
+ put_device(&counter->dev);
}
EXPORT_SYMBOL_GPL(counter_unregister);
@@ -127,13 +156,30 @@ int devm_counter_register(struct device *dev,
}
EXPORT_SYMBOL_GPL(devm_counter_register);
+#define COUNTER_DEV_MAX 256
+
static int __init counter_init(void)
{
- return bus_register(&counter_bus_type);
+ int err;
+
+ err = bus_register(&counter_bus_type);
+ if (err < 0)
+ return err;
+
+ err = alloc_chrdev_region(&counter_devt, 0, COUNTER_DEV_MAX, "counter");
+ if (err < 0)
+ goto err_unregister_bus;
+
+ return 0;
+
+err_unregister_bus:
+ bus_unregister(&counter_bus_type);
+ return err;
}
static void __exit counter_exit(void)
{
+ unregister_chrdev_region(counter_devt, COUNTER_DEV_MAX);
bus_unregister(&counter_bus_type);
}