--- //depot/user/jhb/intr/amd64/amd64/intr_machdep.c +++ /home/jhb/work/p4/intr/amd64/amd64/intr_machdep.c @@ -476,6 +476,23 @@ return (intr_event_bind(isrc->is_event, cpu)); } +/* Tag an active interrupt handler. */ +int +intr_tag(u_int vector, void *ih, const char *tag) +{ + struct intsrc *isrc; + int error; + + isrc = intr_lookup_source(vector); + if (isrc == NULL) + return (EINVAL); + error = intr_event_tag_handler(isrc->is_event, ih, tag); + if (error) + return (error); + intrcnt_updatename(isrc); + return (0); +} + /* * Add a CPU to our mask of valid CPUs that can be destinations of * interrupts. --- //depot/user/jhb/intr/amd64/amd64/nexus.c +++ /home/jhb/work/p4/intr/amd64/amd64/nexus.c @@ -101,6 +101,8 @@ static int nexus_setup_intr(device_t, device_t, struct resource *, int flags, driver_filter_t filter, void (*)(void *), void *, void **); +static int nexus_tag_intr(device_t dev, device_t child, struct resource *irq, + void *cookie, const char *tag); static int nexus_teardown_intr(device_t, device_t, struct resource *, void *); static struct resource_list *nexus_get_reslist(device_t dev, device_t child); @@ -135,6 +137,7 @@ DEVMETHOD(bus_bind_intr, nexus_bind_intr), #endif DEVMETHOD(bus_config_intr, nexus_config_intr), + DEVMETHOD(bus_tag_intr, nexus_tag_intr), DEVMETHOD(bus_get_resource_list, nexus_get_reslist), DEVMETHOD(bus_set_resource, nexus_set_resource), DEVMETHOD(bus_get_resource, nexus_get_resource), @@ -479,6 +482,14 @@ return (intr_config_intr(irq, trig, pol)); } +static int +nexus_tag_intr(device_t dev, device_t child, struct resource *irq, + void *cookie, const char *tag) +{ + + return (intr_tag(rman_get_start(irq), cookie, tag)); +} + static struct resource_list * nexus_get_reslist(device_t dev, device_t child) { --- //depot/user/jhb/intr/amd64/include/intr_machdep.h +++ /home/jhb/work/p4/intr/amd64/include/intr_machdep.h @@ -160,6 +160,7 @@ int intr_remove_handler(void *cookie); void intr_resume(void); void intr_suspend(void); +int intr_tag(u_int vector, void *ih, const char *tag); void intrcnt_add(const char *name, u_long **countp); void nexus_add_irq(u_long irq); int msi_alloc(device_t dev, int count, int maxcount, int *irqs); --- //depot/user/jhb/intr/dev/e1000/if_igb.c +++ /home/jhb/work/p4/intr/dev/e1000/if_igb.c @@ -2160,6 +2160,7 @@ struct tx_ring *txr = adapter->tx_rings; struct rx_ring *rxr = adapter->rx_rings; int error, rid, vector = 0; + char buf[MAXCOMLEN]; /* * Setup the interrupt handlers @@ -2181,9 +2182,13 @@ igb_msix_tx, txr, &txr->tag); if (error) { txr->res = NULL; - device_printf(dev, "Failed to register TX handler"); + device_printf(dev, "Failed to register TX handler\n"); return (error); } + snprintf(buf, sizeof(buf), "tx %d", i); + error = bus_tag_intr(dev, txr->res, txr->tag, buf); + if (error) + device_printf(dev, "Failed to tag TX handler\n"); /* Make tasklet for deferred handling - one per queue */ TASK_INIT(&txr->tx_task, 0, igb_handle_tx, txr); txr->msix = vector; @@ -2215,9 +2220,13 @@ igb_msix_rx, rxr, &rxr->tag); if (error) { rxr->res = NULL; - device_printf(dev, "Failed to register RX handler"); + device_printf(dev, "Failed to register RX handler\n"); return (error); } + snprintf(buf, sizeof(buf), "rx %d", i); + error = bus_tag_intr(dev, rxr->res, rxr->tag, buf); + if (error) + device_printf(dev, "Failed to tag RX handler\n"); /* Make tasklet for deferred handling - one per queue */ TASK_INIT(&rxr->rx_task, 0, igb_handle_rx, rxr); rxr->msix = vector; @@ -2251,9 +2260,12 @@ if ((error = bus_setup_intr(dev, adapter->res, INTR_TYPE_NET | INTR_MPSAFE, NULL, igb_msix_link, adapter, &adapter->tag)) != 0) { - device_printf(dev, "Failed to register Link handler"); + device_printf(dev, "Failed to register Link handler\n"); return (error); } + error = bus_tag_intr(dev, adapter->res, adapter->tag, "link"); + if (error) + device_printf(dev, "Failed to tag link handler\n"); adapter->linkvec = vector; adapter->tq = taskqueue_create_fast("igb_taskq", M_NOWAIT, taskqueue_thread_enqueue, &adapter->tq); --- //depot/user/jhb/intr/kern/bus_if.m +++ /home/jhb/work/p4/intr/kern/bus_if.m @@ -509,6 +509,23 @@ int _cpu; } DEFAULT bus_generic_bind_intr; +/** + * @brief Allow drivers to associate a tag 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 _tag the tag string to associate with the interrupt + */ +METHOD int tag_intr { + device_t _dev; + device_t _child; + struct resource *_irq; + void *_cookie; + const char *_tag; +} DEFAULT bus_generic_tag_intr; /** * @brief Allow (bus) drivers to specify the trigger mode and polarity --- //depot/user/jhb/intr/kern/kern_intr.c +++ /home/jhb/work/p4/intr/kern/kern_intr.c @@ -524,7 +524,7 @@ ih->ih_filter = filter; ih->ih_handler = handler; ih->ih_argument = arg; - ih->ih_name = name; + strncpy(ih->ih_name, name, sizeof(ih->ih_name - 1)); ih->ih_event = ie; ih->ih_pri = pri; if (flags & INTR_EXCL) @@ -597,7 +597,7 @@ ih->ih_filter = filter; ih->ih_handler = handler; ih->ih_argument = arg; - ih->ih_name = name; + strncpy(ih->ih_name, name, sizeof(ih->ih_name - 1)); ih->ih_event = ie; ih->ih_pri = pri; if (flags & INTR_EXCL) @@ -665,6 +665,60 @@ #endif /* + * Append a tag preceded by a ':' to the name of the specified + * interrupt handler. + */ +int +intr_event_tag_handler(struct intr_event *ie, void *cookie, const char *tag) +{ + 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 tag by checking for an existing ":". + * This assumes device names do not include colons. If one is + * found, prepare to insert the new tag 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 + * tag + ":". 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(tag) + 1 > space) { + mtx_unlock(&ie->ie_lock); + return (ENOSPC); + } + + /* Append a colon followed by the tag. */ + *start = ':'; + strcpy(start + 1, tag); + 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. */ --- //depot/user/jhb/intr/kern/subr_bus.c +++ /home/jhb/work/p4/intr/kern/subr_bus.c @@ -3519,6 +3519,23 @@ } /** + * @brief Helper function for implementing BUS_TAG_INTR(). + * + * This simple implementation of BUS_TAG_INTR() simply calls the + * BUS_TAG_INTR() method of the parent of @p dev. + */ +int +bus_generic_tag_intr(device_t dev, device_t child, struct resource *irq, + void *cookie, const char *tag) +{ + + /* Propagate up the bus hierarchy until someone handles it. */ + if (dev->parent) + return (BUS_TAG_INTR(dev->parent, child, irq, cookie, tag)); + return (EINVAL); +} + +/** * @brief Helper function for implementing BUS_CONFIG_INTR(). * * This simple implementation of BUS_CONFIG_INTR() simply calls the @@ -3840,6 +3857,20 @@ } /** + * @brief Wrapper function for BUS_TAG_INTR(). + * + * This function simply calls the BUS_TAG_INTR() method of the parent + * of @p dev. + */ +int +bus_tag_intr(device_t dev, struct resource *irq, void *cookie, const char *tag) +{ + if (dev->parent == NULL) + return (EINVAL); + return (BUS_TAG_INTR(dev->parent, dev, irq, cookie, tag)); +} + +/** * @brief Wrapper function for BUS_SET_RESOURCE(). * * This function simply calls the BUS_SET_RESOURCE() method of the --- //depot/user/jhb/intr/sys/bus.h +++ /home/jhb/work/p4/intr/sys/bus.h @@ -331,6 +331,8 @@ int bus_generic_shutdown(device_t dev); int bus_generic_suspend(device_t dev); +int bus_generic_tag_intr(device_t dev, device_t child, struct resource *irq, + void *cookie, const char *tag); int bus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie); int bus_generic_write_ivar(device_t dev, device_t child, int which, @@ -347,8 +349,10 @@ int flags; }; -int bus_alloc_resources(device_t dev, struct resource_spec *rs, struct resource **res); -void bus_release_resources(device_t dev, const struct resource_spec *rs, struct resource **res); +int bus_alloc_resources(device_t dev, struct resource_spec *rs, + struct resource **res); +void bus_release_resources(device_t dev, const struct resource_spec *rs, + struct resource **res); struct resource *bus_alloc_resource(device_t dev, int type, int *rid, u_long start, u_long end, u_long count, @@ -364,6 +368,8 @@ int bus_setup_intr(device_t dev, struct resource *r, int flags, driver_filter_t filter, driver_intr_t handler, void *arg, void **cookiep); +int bus_tag_intr(device_t dev, struct resource *irq, void *cookie, + const char *tag); int bus_teardown_intr(device_t dev, struct resource *r, void *cookie); int bus_bind_intr(device_t dev, struct resource *r, int cpu); int bus_set_resource(device_t dev, int type, int rid, --- //depot/user/jhb/intr/sys/interrupt.h +++ /home/jhb/work/p4/intr/sys/interrupt.h @@ -47,7 +47,7 @@ driver_intr_t *ih_handler; /* Threaded handler function. */ void *ih_argument; /* Argument to pass to handlers. */ int ih_flags; - const char *ih_name; /* Name of handler. */ + char ih_name[MAXCOMLEN]; /* Name of handler. */ struct intr_event *ih_event; /* Event we are connected to. */ int ih_need; /* Needs service. */ TAILQ_ENTRY(intr_handler) ih_next; /* Next handler for this event. */ @@ -172,6 +172,8 @@ void intr_event_execute_handlers(struct proc *p, struct intr_event *ie); int intr_event_handle(struct intr_event *ie, struct trapframe *frame); int intr_event_remove_handler(void *cookie); +int intr_event_tag_handler(struct intr_event *ie, void *cookie, + const char *tag); int intr_getaffinity(int irq, void *mask); void *intr_handler_source(void *cookie); int intr_setaffinity(int irq, void *mask);