summaryrefslogtreecommitdiffstats
path: root/sys/dev/netmap/ixgbe_netmap.h
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/netmap/ixgbe_netmap.h')
-rw-r--r--sys/dev/netmap/ixgbe_netmap.h55
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
OpenPOWER on IntegriCloud