aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/kern_intr.c
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2009-10-15 14:54:35 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2009-10-15 14:54:35 +0000
commit37b8ef16cddbe2381080d5d710d7accb37c14870 (patch)
tree822343884edf055be1b27eb1097d39bdd975cf43 /sys/kern/kern_intr.c
parent54dd21686df08177e6b5dbea46332680d28aac18 (diff)
downloadsrc-37b8ef16cddbe2381080d5d710d7accb37c14870.tar.gz
src-37b8ef16cddbe2381080d5d710d7accb37c14870.zip
Add a facility for associating optional descriptions with active interrupt
handlers. This is primarily intended as a way to allow devices that use multiple interrupts (e.g. MSI) to meaningfully distinguish the various interrupt handlers. - Add a new BUS_DESCRIBE_INTR() method to the bus interface to associate a description with an active interrupt handler setup by BUS_SETUP_INTR. It has a default method (bus_generic_describe_intr()) which simply passes the request up to the parent device. - Add a bus_describe_intr() wrapper around BUS_DESCRIBE_INTR() that supports printf(9) style formatting using var args. - Reserve MAXCOMLEN bytes in the intr_handler structure to hold the name of an interrupt handler and copy the name passed to intr_event_add_handler() into that buffer instead of just saving the pointer to the name. - Add a new intr_event_describe_handler() which appends a description string to an interrupt handler's name. - Implement support for interrupt descriptions on amd64 and i386 by having the nexus(4) driver supply a custom bus_describe_intr method that invokes a new intr_describe() MD routine which in turn looks up the associated interrupt event and invokes intr_event_describe_handler(). Requested by: many Reviewed by: scottl MFC after: 2 weeks
Notes
Notes: svn path=/head/; revision=198134
Diffstat (limited to 'sys/kern/kern_intr.c')
-rw-r--r--sys/kern/kern_intr.c59
1 files changed, 57 insertions, 2 deletions
diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c
index 3eb2c6ca3f88..42d5f167bd42 100644
--- a/sys/kern/kern_intr.c
+++ b/sys/kern/kern_intr.c
@@ -524,7 +524,7 @@ intr_event_add_handler(struct intr_event *ie, const char *name,
ih->ih_filter = filter;
ih->ih_handler = handler;
ih->ih_argument = arg;
- ih->ih_name = name;
+ strlcpy(ih->ih_name, name, sizeof(ih->ih_name));
ih->ih_event = ie;
ih->ih_pri = pri;
if (flags & INTR_EXCL)
@@ -597,7 +597,7 @@ intr_event_add_handler(struct intr_event *ie, const char *name,
ih->ih_filter = filter;
ih->ih_handler = handler;
ih->ih_argument = arg;
- ih->ih_name = name;
+ strlcpy(ih->ih_name, name, sizeof(ih->ih_name));
ih->ih_event = ie;
ih->ih_pri = pri;
if (flags & INTR_EXCL)
@@ -665,6 +665,61 @@ intr_event_add_handler(struct intr_event *ie, const char *name,
#endif
/*
+ * Append a description preceded by a ':' to the name of the specified
+ * interrupt handler.
+ */
+int
+intr_event_describe_handler(struct intr_event *ie, void *cookie,
+ const char *descr)
+{
+ struct intr_handler *ih;
+ size_t space;
+ char *start;
+
+ mtx_lock(&ie->ie_lock);
+#ifdef INVARIANTS
+ TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
+ if (ih == cookie)
+ break;
+ }
+ if (ih == NULL) {
+ mtx_unlock(&ie->ie_lock);
+ panic("handler %p not find in interrupt event %p", cookie, ie);
+ }
+#endif
+ ih = cookie;
+
+ /*
+ * Look for an existing description by checking for an
+ * existing ":". This assumes device names do not include
+ * colons. If one is found, prepare to insert the new
+ * description at that point. If one is not found, find the
+ * end of the name to use as the insertion point.
+ */
+ start = index(ih->ih_name, ':');
+ if (start == NULL)
+ start = index(ih->ih_name, 0);
+
+ /*
+ * See if there is enough remaining room in the string for the
+ * description + ":". The "- 1" leaves room for the trailing
+ * '\0'. The "+ 1" accounts for the colon.
+ */
+ space = sizeof(ih->ih_name) - (start - ih->ih_name) - 1;
+ if (strlen(descr) + 1 > space) {
+ mtx_unlock(&ie->ie_lock);
+ return (ENOSPC);
+ }
+
+ /* Append a colon followed by the description. */
+ *start = ':';
+ strcpy(start + 1, descr);
+ intr_event_update(ie);
+ mtx_unlock(&ie->ie_lock);
+ return (0);
+}
+
+/*
* Return the ie_source field from the intr_event an intr_handler is
* associated with.
*/