diff options
Diffstat (limited to 'sys/dev/netmap/ixgbe_netmap.h')
-rw-r--r-- | sys/dev/netmap/ixgbe_netmap.h | 55 |
1 files changed, 46 insertions, 9 deletions
diff --git a/sys/dev/netmap/ixgbe_netmap.h b/sys/dev/netmap/ixgbe_netmap.h index f456044..8e5fe1b 100644 --- a/sys/dev/netmap/ixgbe_netmap.h +++ b/sys/dev/netmap/ixgbe_netmap.h @@ -191,6 +191,10 @@ fail: * (this is also true for every use of ring in the kernel). * * ring->avail is never used, only checked for bogus values. + * + * do_lock is set iff the function is called from the ioctl handler. + * In this case, grab a lock around the body, and also reclaim transmitted + * buffers irrespective of interrupt mitigation. */ static int ixgbe_netmap_txsync(void *a, u_int ring_nr, int do_lock) @@ -292,10 +296,11 @@ ring_reset: * need this. */ curr->read.buffer_addr = htole64(paddr); - curr->read.olinfo_status = 0; + curr->read.olinfo_status = htole32(len << IXGBE_ADVTXD_PAYLEN_SHIFT); curr->read.cmd_type_len = htole32(txr->txd_cmd | len | (IXGBE_ADVTXD_DTYP_DATA | + IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DCMD_IFCS | IXGBE_TXD_CMD_EOP | flags) ); /* If the buffer has changed, unload and reload map @@ -328,15 +333,41 @@ ring_reset: } /* - * If no packets are sent, or there is no room in the tx ring, - * Check whether there are completed transmissions. - * Because this is expensive (we need a register etc.) - * we only do it if absolutely necessary, i.e. there is no room - * in the tx ring, or where were no completed transmissions - * (meaning that probably the caller really wanted to check - * for completed transmissions). + * Reclaim buffers for completed transmissions. + * Because this is expensive (we read a NIC register etc.) + * we only do it in specific cases (see below). + * In all cases kring->nr_kflags indicates which slot will be + * checked upon a tx interrupt (nkr_num_slots means none). */ - if (n == 0 || kring->nr_hwavail < 1) { + if (do_lock) { + j = 1; /* forced reclaim, ignore interrupts */ + kring->nr_kflags = kring->nkr_num_slots; + } else if (kring->nr_hwavail > 0) { + j = 0; /* buffers still available: no reclaim, ignore intr. */ + kring->nr_kflags = kring->nkr_num_slots; + } else { + /* + * no buffers available, locate a slot for which we request + * ReportStatus (approximately half ring after next_to_clean) + * and record it in kring->nr_kflags. + * If the slot has DD set, do the reclaim looking at TDH, + * otherwise we go to sleep (in netmap_poll()) and will be + * woken up when slot nr_kflags will be ready. + */ + struct ixgbe_legacy_tx_desc *txd = (struct ixgbe_legacy_tx_desc *)txr->tx_base; + + j = txr->next_to_clean + kring->nkr_num_slots/2; + if (j >= kring->nkr_num_slots) + j -= kring->nkr_num_slots; + // round to the closest with dd set + j= (j < kring->nkr_num_slots / 4 || j >= kring->nkr_num_slots*3/4) ? + 0 : report_frequency; + kring->nr_kflags = j; /* the slot to check */ + j = txd[j].upper.fields.status & IXGBE_TXD_STAT_DD; + } + if (!j) { + netmap_skip_txsync++; + } else { int delta; /* @@ -391,6 +422,8 @@ ring_reset: * We must subtract the newly consumed slots (cur - nr_hwcur) * from nr_hwavail, make the descriptors available for the next reads, * and set kring->nr_hwcur = ring->cur and ring->avail = kring->nr_hwavail. + * + * do_lock has a special meaning: please refer to txsync. */ static int ixgbe_netmap_rxsync(void *a, u_int ring_nr, int do_lock) @@ -401,6 +434,7 @@ ixgbe_netmap_rxsync(void *a, u_int ring_nr, int do_lock) struct netmap_kring *kring = &na->rx_rings[ring_nr]; struct netmap_ring *ring = kring->ring; int j, k, l, n, lim = kring->nkr_num_slots - 1; + int force_update = do_lock || kring->nr_kflags & NKR_PENDINTR; k = ring->cur; /* cache and check value, same as in txsync */ n = k - kring->nr_hwcur; @@ -437,6 +471,7 @@ ixgbe_netmap_rxsync(void *a, u_int ring_nr, int do_lock) if (j > lim) j -= lim + 1; + if (force_update) { for (n = 0; ; n++) { union ixgbe_adv_rx_desc *curr = &rxr->rx_base[l]; uint32_t staterr = le32toh(curr->wb.upper.status_error); @@ -453,6 +488,8 @@ ixgbe_netmap_rxsync(void *a, u_int ring_nr, int do_lock) rxr->next_to_check = l; kring->nr_hwavail += n; } + kring->nr_kflags &= ~NKR_PENDINTR; + } /* * Skip past packets that userspace has already processed |