summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/subr_bus.c80
-rw-r--r--sys/sys/bus.h9
2 files changed, 70 insertions, 19 deletions
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index 9a65242..6a35313 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -369,6 +369,65 @@ devpoll(dev_t dev, int events, d_thread_t *td)
}
/*
+ * Generic interface to queue data to the devctl device. It is
+ * assumed that data is properly formatted. It is further assumed
+ * that data is allocated.
+ */
+void
+devctl_queue_data(char *data)
+{
+ struct dev_event_info *n1 = NULL;
+ struct proc *p;
+
+ n1 = malloc(sizeof(*n1), M_BUS, M_NOWAIT);
+ if (n1 == NULL)
+ return;
+ n1->dei_data = data;
+ mtx_lock(&devsoftc.mtx);
+ TAILQ_INSERT_TAIL(&devsoftc.devq, n1, dei_link);
+ cv_broadcast(&devsoftc.cv);
+ mtx_unlock(&devsoftc.mtx);
+ selwakeup(&devsoftc.sel);
+ p = devsoftc.async_proc;
+ if (p != NULL) {
+ PROC_LOCK(p);
+ psignal(p, SIGIO);
+ PROC_UNLOCK(p);
+ }
+}
+
+/*
+ * Send a 'notification' to userland, using standard ways
+ */
+void
+devctl_notify(const char *system, const char *subsystem, const char *type,
+ const char *data)
+{
+ int len = 0;
+ char *msg;
+
+ if (system == NULL)
+ return; /* BOGUS! Must specify system. */
+ if (subsystem == NULL)
+ return; /* BOGUS! Must specify subsystem. */
+ if (type == NULL)
+ return; /* BOGUS! Must specify type. */
+ len += strlen(" system=") + strlen(system);
+ len += strlen(" subsystem=") + strlen(subsystem);
+ len += strlen(" type=") + strlen(type);
+ /* add in the data message plus newline. */
+ if (data != NULL)
+ len += strlen(data);
+ len += 3; /* '!', '\n', and NUL */
+ msg = malloc(len, M_BUS, M_NOWAIT);
+ if (msg == NULL)
+ return; /* Drop it on the floor */
+ snprintf(msg, len, "!system=%s subsystem=%s type=%s %s\n", system,
+ subsystem, type, data);
+ devctl_queue_data(msg);
+}
+
+/*
* Common routine that tries to make sending messages as easy as possible.
* We allocate memory for the data, copy strings into that, but do not
* free it unless there's an error. The dequeue part of the driver should
@@ -379,17 +438,12 @@ devpoll(dev_t dev, int events, d_thread_t *td)
static void
devaddq(const char *type, const char *what, device_t dev)
{
- struct dev_event_info *n1 = NULL;
- struct proc *p;
char *data = NULL;
char *loc;
const char *parstr;
if (devctl_disable)
return;
- n1 = malloc(sizeof(*n1), M_BUS, M_NOWAIT);
- if (n1 == NULL)
- goto bad;
data = malloc(1024, M_BUS, M_NOWAIT);
if (data == NULL)
goto bad;
@@ -404,22 +458,10 @@ devaddq(const char *type, const char *what, device_t dev)
parstr = device_get_nameunit(device_get_parent(dev));
snprintf(data, 1024, "%s%s at %s on %s\n", type, what, loc, parstr);
free(loc, M_BUS);
- n1->dei_data = data;
- mtx_lock(&devsoftc.mtx);
- TAILQ_INSERT_TAIL(&devsoftc.devq, n1, dei_link);
- cv_broadcast(&devsoftc.cv);
- mtx_unlock(&devsoftc.mtx);
- selwakeup(&devsoftc.sel);
- p = devsoftc.async_proc;
- if (p != NULL) {
- PROC_LOCK(p);
- psignal(p, SIGIO);
- PROC_UNLOCK(p);
- }
+ devctl_queue_data(data);
return;
-bad:;
+bad:
free(data, M_BUS);
- free(n1, M_BUS);
return;
}
diff --git a/sys/sys/bus.h b/sys/sys/bus.h
index 7e69b2c..79d4d157 100644
--- a/sys/sys/bus.h
+++ b/sys/sys/bus.h
@@ -72,6 +72,15 @@ struct u_device {
#include <sys/kobj.h>
/*
+ * devctl hooks. Typically one should use the devctl_notify
+ * hook to send the message. However, devctl_queue_data is also
+ * included in case devctl_notify isn't sufficiently general.
+ */
+void devctl_notify(const char *__system, const char *__subsystem,
+ const char *__type, const char *__data);
+void devctl_queue_data(char *__data);
+
+/*
* Forward declarations
*/
typedef struct device *device_t;
OpenPOWER on IntegriCloud