summaryrefslogtreecommitdiff
path: root/include/linux/counter.h
diff options
context:
space:
mode:
authorWilliam Breathitt Gray <vilhelm.gray@gmail.com>2021-09-29 06:15:59 +0300
committerJonathan Cameron <Jonathan.Cameron@huawei.com>2021-10-17 12:53:52 +0300
commitb6c50affda5957a3629b149a91c7f6688ffce7f7 (patch)
tree8d6e0890410abbf4acb52f851b62cee7ee541f05 /include/linux/counter.h
parente65c26f413718ed2e6d788491adcd8cebc0f44b6 (diff)
downloadlinux-b6c50affda5957a3629b149a91c7f6688ffce7f7.tar.xz
counter: Add character device interface
This patch introduces a character device interface for the Counter subsystem. Device data is exposed through standard character device read operations. Device data is gathered when a Counter event is pushed by the respective Counter device driver. Configuration is handled via ioctl operations on the respective Counter character device node. Cc: David Lechner <david@lechnology.com> Cc: Gwendal Grignou <gwendal@chromium.org> Cc: Dan Carpenter <dan.carpenter@oracle.com> Cc: Oleksij Rempel <o.rempel@pengutronix.de> Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com> Link: https://lore.kernel.org/r/b8b8c64b4065aedff43699ad1f0e2f8d1419c15b.1632884256.git.vilhelm.gray@gmail.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Diffstat (limited to 'include/linux/counter.h')
-rw-r--r--include/linux/counter.h56
1 files changed, 56 insertions, 0 deletions
diff --git a/include/linux/counter.h b/include/linux/counter.h
index 7c9f7e23953a..22b14a552b1d 100644
--- a/include/linux/counter.h
+++ b/include/linux/counter.h
@@ -6,9 +6,14 @@
#ifndef _COUNTER_H_
#define _COUNTER_H_
+#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/kernel.h>
+#include <linux/kfifo.h>
+#include <linux/mutex.h>
+#include <linux/spinlock_types.h>
#include <linux/types.h>
+#include <linux/wait.h>
#include <uapi/linux/counter.h>
struct counter_device;
@@ -200,6 +205,20 @@ struct counter_count {
};
/**
+ * struct counter_event_node - Counter Event node
+ * @l: list of current watching Counter events
+ * @event: event that triggers
+ * @channel: event channel
+ * @comp_list: list of components to watch when event triggers
+ */
+struct counter_event_node {
+ struct list_head l;
+ u8 event;
+ u8 channel;
+ struct list_head comp_list;
+};
+
+/**
* struct counter_ops - Callbacks from driver
* @signal_read: optional read callback for Signals. The read level of
* the respective Signal should be passed back via the
@@ -222,6 +241,13 @@ struct counter_count {
* @action_write: optional write callback for Synapse action modes. The
* action mode to write for the respective Synapse is
* passed in via the action parameter.
+ * @events_configure: optional write callback to configure events. The list of
+ * struct counter_event_node may be accessed via the
+ * events_list member of the counter parameter.
+ * @watch_validate: optional callback to validate a watch. The Counter
+ * component watch configuration is passed in via the watch
+ * parameter. A return value of 0 indicates a valid Counter
+ * component watch configuration.
*/
struct counter_ops {
int (*signal_read)(struct counter_device *counter,
@@ -245,6 +271,9 @@ struct counter_ops {
struct counter_count *count,
struct counter_synapse *synapse,
enum counter_synapse_action action);
+ int (*events_configure)(struct counter_device *counter);
+ int (*watch_validate)(struct counter_device *counter,
+ const struct counter_watch *watch);
};
/**
@@ -260,6 +289,16 @@ struct counter_ops {
* @num_ext: number of Counter device extensions specified in @ext
* @priv: optional private data supplied by driver
* @dev: internal device structure
+ * @chrdev: internal character device structure
+ * @events_list: list of current watching Counter events
+ * @events_list_lock: lock to protect Counter events list operations
+ * @next_events_list: list of next watching Counter events
+ * @n_events_list_lock: lock to protect Counter next events list operations
+ * @events: queue of detected Counter events
+ * @events_wait: wait queue to allow blocking reads of Counter events
+ * @events_lock: lock to protect Counter events queue read operations
+ * @chrdev_lock: lock to limit chrdev to a single open at a time
+ * @ops_exist_lock: lock to prevent use during removal
*/
struct counter_device {
const char *name;
@@ -278,12 +317,29 @@ struct counter_device {
void *priv;
struct device dev;
+ struct cdev chrdev;
+ struct list_head events_list;
+ spinlock_t events_list_lock;
+ struct list_head next_events_list;
+ struct mutex n_events_list_lock;
+ DECLARE_KFIFO_PTR(events, struct counter_event);
+ wait_queue_head_t events_wait;
+ struct mutex events_lock;
+ /*
+ * chrdev_lock is locked by counter_chrdev_open() and unlocked by
+ * counter_chrdev_release(), so a mutex is not possible here because
+ * chrdev_lock will invariably be held when returning to user space
+ */
+ atomic_t chrdev_lock;
+ struct mutex ops_exist_lock;
};
int counter_register(struct counter_device *const counter);
void counter_unregister(struct counter_device *const counter);
int devm_counter_register(struct device *dev,
struct counter_device *const counter);
+void counter_push_event(struct counter_device *const counter, const u8 event,
+ const u8 channel);
#define COUNTER_COMP_DEVICE_U8(_name, _read, _write) \
{ \