summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2010-01-21 17:55:47 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2010-01-21 17:55:47 +0000
commitc3895badf7af698d10fdd2c6d3bbb188c8346b02 (patch)
treea245209c1640a0b080e5a0e5f1a25029c890f0c2 /sys/kern
parent219503bacf6d613fab7bbd8bc36692f1cdf989c3 (diff)
Notes
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/bus_if.m20
-rw-r--r--sys/kern/kern_intr.c59
-rw-r--r--sys/kern/subr_bus.c40
3 files changed, 116 insertions, 3 deletions
diff --git a/sys/kern/bus_if.m b/sys/kern/bus_if.m
index 72817e72f7b8..3e23a8b915f3 100644
--- a/sys/kern/bus_if.m
+++ b/sys/kern/bus_if.m
@@ -509,7 +509,6 @@ METHOD int bind_intr {
int _cpu;
} DEFAULT bus_generic_bind_intr;
-
/**
* @brief Allow (bus) drivers to specify the trigger mode and polarity
* of the specified interrupt.
@@ -527,6 +526,25 @@ METHOD int config_intr {
} DEFAULT bus_generic_config_intr;
/**
+ * @brief Allow drivers to associate a description with an active
+ * interrupt handler.
+ *
+ * @param _dev the parent device of @p _child
+ * @param _child the device which allocated the resource
+ * @param _irq the resource representing the interrupt
+ * @param _cookie the cookie value returned when the interrupt
+ * was originally registered
+ * @param _descr the description to associate with the interrupt
+ */
+METHOD int describe_intr {
+ device_t _dev;
+ device_t _child;
+ struct resource *_irq;
+ void *_cookie;
+ const char *_descr;
+} DEFAULT bus_generic_describe_intr;
+
+/**
* @brief Notify a (bus) driver about a child that the hints mechanism
* believes it has discovered.
*
diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c
index e2bf380ecc2d..b09fe829337c 100644
--- a/sys/kern/kern_intr.c
+++ b/sys/kern/kern_intr.c
@@ -506,7 +506,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)
@@ -579,7 +579,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)
@@ -647,6 +647,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 found 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.
*/
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index 127691e94af1..7bcaf92fb546 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -3264,6 +3264,24 @@ bus_generic_config_intr(device_t dev, int irq, enum intr_trigger trig,
}
/**
+ * @brief Helper function for implementing BUS_DESCRIBE_INTR().
+ *
+ * This simple implementation of BUS_DESCRIBE_INTR() simply calls the
+ * BUS_DESCRIBE_INTR() method of the parent of @p dev.
+ */
+int
+bus_generic_describe_intr(device_t dev, device_t child, struct resource *irq,
+ void *cookie, const char *descr)
+{
+
+ /* Propagate up the bus hierarchy until someone handles it. */
+ if (dev->parent)
+ return (BUS_DESCRIBE_INTR(dev->parent, child, irq, cookie,
+ descr));
+ return (EINVAL);
+}
+
+/**
* @brief Helper function for implementing BUS_GET_DMA_TAG().
*
* This simple implementation of BUS_GET_DMA_TAG() simply calls the
@@ -3569,6 +3587,28 @@ bus_bind_intr(device_t dev, struct resource *r, int cpu)
}
/**
+ * @brief Wrapper function for BUS_DESCRIBE_INTR().
+ *
+ * This function first formats the requested description into a
+ * temporary buffer and then calls the BUS_DESCRIBE_INTR() method of
+ * the parent of @p dev.
+ */
+int
+bus_describe_intr(device_t dev, struct resource *irq, void *cookie,
+ const char *fmt, ...)
+{
+ char descr[MAXCOMLEN];
+ va_list ap;
+
+ if (dev->parent == NULL)
+ return (EINVAL);
+ va_start(ap, fmt);
+ vsnprintf(descr, sizeof(descr), fmt, ap);
+ va_end(ap);
+ return (BUS_DESCRIBE_INTR(dev->parent, dev, irq, cookie, descr));
+}
+
+/**
* @brief Wrapper function for BUS_SET_RESOURCE().
*
* This function simply calls the BUS_SET_RESOURCE() method of the