Index: sys/dev/ixgbe/if_ix.c =================================================================== --- sys/dev/ixgbe/if_ix.c +++ sys/dev/ixgbe/if_ix.c @@ -349,7 +349,7 @@ * is varied over time based on the * traffic for that interrupt vector */ -static int ixgbe_enable_aim = false; +static int ixgbe_enable_aim = 1; SYSCTL_INT(_hw_ix, OID_AUTO, enable_aim, CTLFLAG_RWTUN, &ixgbe_enable_aim, 0, "Enable adaptive interrupt moderation"); @@ -1671,8 +1671,8 @@ queue_list = SYSCTL_CHILDREN(queue_node); SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate", - CTLTYPE_UINT | CTLFLAG_RW, - &sc->rx_queues[i], 0, + CTLTYPE_UINT | CTLFLAG_RD, + rx_que, false, ixgbe_sysctl_interrupt_rate_handler, "IU", "Interrupt Rate"); SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs", @@ -2183,7 +2183,7 @@ { uint32_t newitr = 0; struct rx_ring *rxr = &que->rxr; - /* FIXME struct tx_ring *txr = ... ->txr; */ + struct tx_ring *txr = &sc->tx_queues[que->msix].txr; /* * Do Adaptive Interrupt Moderation: @@ -2196,21 +2196,16 @@ que->eitr_setting); } - que->eitr_setting = 0; /* Idle, do nothing */ - if (rxr->bytes == 0) { - /* FIXME && txr->bytes == 0 */ + if (txr->bytes == 0 && rxr->bytes == 0) return; - } + que->eitr_setting = 0; + + if ((txr->bytes) && (txr->packets)) + newitr = txr->bytes/txr->packets; if ((rxr->bytes) && (rxr->packets)) - newitr = rxr->bytes / rxr->packets; - /* FIXME for transmit accounting - * if ((txr->bytes) && (txr->packets)) - * newitr = txr->bytes/txr->packets; - * if ((rxr->bytes) && (rxr->packets)) - * newitr = max(newitr, (rxr->bytes / rxr->packets)); - */ + newitr = max(newitr, rxr->bytes / rxr->packets); newitr += 24; /* account for hardware frame, crc */ /* set an upper boundary */ @@ -2233,8 +2228,8 @@ que->eitr_setting = newitr; /* Reset state */ - /* FIXME txr->bytes = 0; */ - /* FIXME txr->packets = 0; */ + txr->bytes = 0; + txr->packets = 0; rxr->bytes = 0; rxr->packets = 0; @@ -2251,6 +2246,8 @@ struct ixgbe_softc *sc = que->sc; if_t ifp = iflib_get_ifp(que->sc->ctx); + uint32_t newitr = 0; + /* Protect against spurious interrupts */ if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) return (FILTER_HANDLED); @@ -2261,6 +2258,9 @@ /* Check for AIM */ if (sc->enable_aim) { ixgbe_perform_aim(sc, que); + } else { + newitr = IXGBE_INTS_TO_EITR(ixgbe_max_interrupt_rate); + IXGBE_WRITE_REG(&sc->hw, IXGBE_EITR(que->msix), newitr); } return (FILTER_SCHEDULE_THREAD); @@ -2688,31 +2688,34 @@ static int ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS) { - struct ix_rx_queue *que = ((struct ix_rx_queue *)oidp->oid_arg1); + struct ix_rx_queue *rque; + struct ix_tx_queue *tque; int error; unsigned int reg, usec, rate; - if (atomic_load_acq_int(&que->sc->recovery_mode)) - return (EPERM); + bool tx = oidp->oid_arg2; - reg = IXGBE_READ_REG(&que->sc->hw, IXGBE_EITR(que->msix)); - usec = ((reg & 0x0FF8) >> 3); + if (tx) { + tque = oidp->oid_arg1; + if (atomic_load_acq_int(&tque->sc->recovery_mode)) + return (EPERM); + reg = IXGBE_READ_REG(&tque->sc->hw, IXGBE_EITR(tque->txr.me)); + } else { + rque = oidp->oid_arg1; + if (atomic_load_acq_int(&rque->sc->recovery_mode)) + return (EPERM); + reg = IXGBE_READ_REG(&rque->sc->hw, IXGBE_EITR(rque->msix)); + } + + usec = (reg & IXGBE_QVECTOR_MASK); // >> 3; if (usec > 0) - rate = 500000 / usec; + rate = IXGBE_INTS_TO_EITR(reg); // rate = 500000 / usec; else rate = 0; + error = sysctl_handle_int(oidp, &rate, 0, req); if (error || !req->newptr) return error; - reg &= ~0xfff; /* default, no limitation */ - ixgbe_max_interrupt_rate = 0; - if (rate > 0 && rate < 500000) { - if (rate < 1000) - rate = 1000; - ixgbe_max_interrupt_rate = rate; - reg |= ((4000000/rate) & 0xff8); - } - IXGBE_WRITE_REG(&que->sc->hw, IXGBE_EITR(que->msix), reg); return (0); } /* ixgbe_sysctl_interrupt_rate_handler */ @@ -3314,7 +3317,7 @@ u32 newitr; if (ixgbe_max_interrupt_rate > 0) - newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8; + newitr = IXGBE_INTS_TO_EITR(ixgbe_max_interrupt_rate); else { /* * Disable DMA coalescing if interrupt moderation is Index: sys/dev/ixgbe/ix_txrx.c =================================================================== --- sys/dev/ixgbe/ix_txrx.c +++ sys/dev/ixgbe/ix_txrx.c @@ -235,6 +235,7 @@ } txd->read.cmd_type_len |= htole32(IXGBE_TXD_CMD_EOP | flags); + ++txr->packets; txr->bytes += pi->ipi_len; pi->ipi_new_pidx = i; Index: sys/dev/ixgbe/ixgbe.h =================================================================== --- sys/dev/ixgbe/ixgbe.h +++ sys/dev/ixgbe/ixgbe.h @@ -204,6 +204,11 @@ #define DEVMETHOD_END { NULL, NULL } #endif +#define IXGBE_EITR_DIVIDEND 4000000 +#define IXGBE_QVECTOR_MASK 0x0FF8 +#define IXGBE_INTS_TO_EITR(i) (((IXGBE_EITR_DIVIDEND/i) & \ + IXGBE_QVECTOR_MASK)) + /* * Interrupt Moderation parameters */