diff options
author | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2017-07-14 19:09:53 +0000 |
---|---|---|
committer | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2017-07-14 19:09:53 +0000 |
commit | 43765c1e5874eb5cc1286b4ec35600d3ebcd13a8 (patch) | |
tree | b35a6c84735852c7781c683b2894dbf8b01b2323 /sys/dev/pv | |
parent | f333118936ab5e0a57d6800a356a59f3c9a714d9 (diff) |
Silence the interrupt source until the interrupt task has done its job
This small change significantly improves performance under load and halves
the number of received interrupts.
Diffstat (limited to 'sys/dev/pv')
-rw-r--r-- | sys/dev/pv/xen.c | 63 | ||||
-rw-r--r-- | sys/dev/pv/xenvar.h | 4 |
2 files changed, 48 insertions, 19 deletions
diff --git a/sys/dev/pv/xen.c b/sys/dev/pv/xen.c index 96795da2957..d66293f14a4 100644 --- a/sys/dev/pv/xen.c +++ b/sys/dev/pv/xen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xen.c,v 1.82 2017/06/02 20:25:50 mikeb Exp $ */ +/* $OpenBSD: xen.c,v 1.83 2017/07/14 19:09:52 mikeb Exp $ */ /* * Copyright (c) 2015, 2016, 2017 Mike Belopuhov @@ -71,6 +71,7 @@ int xen_getfeatures(struct xen_softc *); int xen_init_info_page(struct xen_softc *); int xen_init_cbvec(struct xen_softc *); int xen_init_interrupts(struct xen_softc *); +void xen_intr_dispatch(void *); int xen_init_grant_tables(struct xen_softc *); struct xen_gntent * xen_grant_table_grow(struct xen_softc *); @@ -634,6 +635,27 @@ xen_intsrc_remove(struct xen_softc *sc, evtchn_port_t port) return (xi); } +static inline void +xen_intr_mask_acquired(struct xen_softc *sc, struct xen_intsrc *xi) +{ + xi->xi_masked = 1; + set_bit(xi->xi_port, &sc->sc_ipg->evtchn_mask[0]); +} + +static inline int +xen_intr_unmask_release(struct xen_softc *sc, struct xen_intsrc *xi) +{ + struct evtchn_unmask eu; + + xi->xi_masked = 0; + if (!test_bit(xi->xi_port, &sc->sc_ipg->evtchn_mask[0])) + return (0); + eu.port = xi->xi_port; + xen_intsrc_release(sc, xi); + return (xen_evtchn_hypercall(sc, EVTCHNOP_unmask, &eu, + sizeof(eu))); +} + void xen_intr_ack(void) { @@ -678,8 +700,8 @@ xen_intr(void) continue; } xi->xi_evcnt.ec_count++; + xen_intr_mask_acquired(sc, xi); task_add(xi->xi_taskq, &xi->xi_task); - xen_intsrc_release(sc, xi); } } } @@ -690,10 +712,8 @@ xen_intr_schedule(xen_intr_handle_t xih) struct xen_softc *sc = xen_sc; struct xen_intsrc *xi; - if ((xi = xen_intsrc_acquire(sc, (evtchn_port_t)xih)) != NULL) { + if ((xi = xen_intsrc_acquire(sc, (evtchn_port_t)xih)) != NULL) task_add(xi->xi_taskq, &xi->xi_task); - xen_intsrc_release(sc, xi); - } } static void @@ -780,6 +800,9 @@ xen_intr_establish(evtchn_port_t port, xen_intr_handle_t *xih, int domain, xi->xi_port = (evtchn_port_t)*xih; + xi->xi_handler = handler; + xi->xi_ctx = arg; + xi->xi_taskq = taskq_create(name, 1, IPL_NET, TASKQ_MPSAFE); if (!xi->xi_taskq) { printf("%s: failed to create interrupt task for %s\n", @@ -787,7 +810,7 @@ xen_intr_establish(evtchn_port_t port, xen_intr_handle_t *xih, int domain, free(xi, M_DEVBUF, sizeof(*xi)); return (-1); } - task_set(&xi->xi_task, handler, arg); + task_set(&xi->xi_task, xen_intr_dispatch, xi); if (port == 0) { /* We're being asked to allocate a new event port */ @@ -886,6 +909,18 @@ xen_intr_disestablish(xen_intr_handle_t xih) } void +xen_intr_dispatch(void *arg) +{ + struct xen_softc *sc = xen_sc; + struct xen_intsrc *xi = arg; + + if (xi->xi_handler) + xi->xi_handler(xi->xi_ctx); + + xen_intr_unmask_release(sc, xi); +} + +void xen_intr_enable(void) { struct xen_softc *sc = xen_sc; @@ -917,8 +952,7 @@ xen_intr_mask(xen_intr_handle_t xih) struct xen_intsrc *xi; if ((xi = xen_intsrc_acquire(sc, port)) != NULL) { - xi->xi_masked = 1; - set_bit(xi->xi_port, &sc->sc_ipg->evtchn_mask[0]); + xen_intr_mask_acquired(sc, xi); xen_intsrc_release(sc, xi); } } @@ -929,17 +963,10 @@ xen_intr_unmask(xen_intr_handle_t xih) struct xen_softc *sc = xen_sc; evtchn_port_t port = (evtchn_port_t)xih; struct xen_intsrc *xi; - struct evtchn_unmask eu; - if ((xi = xen_intsrc_acquire(sc, port)) != NULL) { - xi->xi_masked = 0; - if (!test_bit(xi->xi_port, &sc->sc_ipg->evtchn_mask[0])) - return (0); - eu.port = xi->xi_port; - xen_intsrc_release(sc, xi); - return (xen_evtchn_hypercall(sc, EVTCHNOP_unmask, &eu, - sizeof(eu))); - } + if ((xi = xen_intsrc_acquire(sc, port)) != NULL) + return (xen_intr_unmask_release(sc, xi)); + return (0); } diff --git a/sys/dev/pv/xenvar.h b/sys/dev/pv/xenvar.h index 61a4dcb920b..dc43698f0cf 100644 --- a/sys/dev/pv/xenvar.h +++ b/sys/dev/pv/xenvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: xenvar.h,v 1.49 2017/02/08 16:15:52 mikeb Exp $ */ +/* $OpenBSD: xenvar.h,v 1.50 2017/07/14 19:09:52 mikeb Exp $ */ /* * Copyright (c) 2015 Mike Belopuhov @@ -49,6 +49,8 @@ struct xen_intsrc { struct refcnt xi_refcnt; struct task xi_task; struct taskq *xi_taskq; + void (*xi_handler)(void *); + void *xi_ctx; }; struct xen_gntent { |