aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/ena
diff options
context:
space:
mode:
authorMarcin Wojtas <mw@FreeBSD.org>2019-10-31 16:02:42 +0000
committerMarcin Wojtas <mw@FreeBSD.org>2019-10-31 16:02:42 +0000
commit358bcc4c6cde30dd7f785d14327ba391f552b3e0 (patch)
tree1fe3ee41ebd6d70cc01f897776d6026f572584d7 /sys/dev/ena
parent6f2128c7ed361cc22b1810c779760a40106e62e8 (diff)
downloadsrc-358bcc4c6cde30dd7f785d14327ba391f552b3e0.tar.gz
src-358bcc4c6cde30dd7f785d14327ba391f552b3e0.zip
Add support for ENA NETMAP partial initialization
In NETMAP mode not all queues need to be allocated to NETMAP. Some of them could be left to the kernel. Configuration is managed by the flags nr_mode and nr_pending_mode provided per each NETMAP kring. ENA driver checks those flags and perform proper rings initialization. Differential Revision: https://reviews.freebsd.org/D21937 Submitted by: Rafal Kozik <rk@semihalf.com> Michal Krawczyk <mk@semihalf.com> Obtained from: Semihalf Sponsored by: Amazon, Inc.
Notes
Notes: svn path=/head/; revision=354224
Diffstat (limited to 'sys/dev/ena')
-rw-r--r--sys/dev/ena/ena.c2
-rw-r--r--sys/dev/ena/ena_netmap.c66
-rw-r--r--sys/dev/ena/ena_netmap.h2
3 files changed, 64 insertions, 6 deletions
diff --git a/sys/dev/ena/ena.c b/sys/dev/ena/ena.c
index 609907874951..a5687d0213fd 100644
--- a/sys/dev/ena/ena.c
+++ b/sys/dev/ena/ena.c
@@ -1087,7 +1087,7 @@ ena_refill_rx_bufs(struct ena_ring *rx_ring, uint32_t num)
req_id = rx_ring->free_rx_ids[next_to_use];
rx_info = &rx_ring->rx_buffer_info[req_id];
#ifdef DEV_NETMAP
- if (adapter->ifp->if_capenable & IFCAP_NETMAP)
+ if (ena_rx_ring_in_netmap(adapter, rx_ring->qid))
rc = ena_netmap_alloc_rx_slot(adapter, rx_ring, rx_info);
else
#endif /* DEV_NETMAP */
diff --git a/sys/dev/ena/ena_netmap.c b/sys/dev/ena/ena_netmap.c
index e0a9a846ce6c..77a7436195ee 100644
--- a/sys/dev/ena/ena_netmap.c
+++ b/sys/dev/ena/ena_netmap.c
@@ -206,6 +206,8 @@ ena_netmap_free_rx_slot(struct ena_adapter *adapter,
BUS_DMASYNC_POSTREAD);
netmap_unload_map(na, adapter->rx_buf_tag, rx_info->map);
+ KASSERT(kring->ring == NULL, ("Netmap Rx ring is NULL\n"));
+
slot = &kring->ring->slot[nm_i];
ENA_ASSERT(slot->buf_idx == 0, "Overwrite slot buf\n");
@@ -216,18 +218,54 @@ ena_netmap_free_rx_slot(struct ena_adapter *adapter,
kring->nr_hwcur = nm_i;
}
+static bool
+ena_ring_in_netmap(struct ena_adapter *adapter, int qid, enum txrx x)
+{
+ struct netmap_adapter *na;
+ struct netmap_kring *kring;
+
+ if (adapter->ifp->if_capenable & IFCAP_NETMAP) {
+ na = NA(adapter->ifp);
+ kring = (x == NR_RX) ? na->rx_rings[qid] : na->tx_rings[qid];
+ if (kring->nr_mode == NKR_NETMAP_ON)
+ return true;
+ }
+ return false;
+}
+
+bool
+ena_tx_ring_in_netmap(struct ena_adapter *adapter, int qid)
+{
+ return ena_ring_in_netmap(adapter, qid, NR_TX);
+}
+
+bool
+ena_rx_ring_in_netmap(struct ena_adapter *adapter, int qid)
+{
+ return ena_ring_in_netmap(adapter, qid, NR_RX);
+}
+
+static void
+ena_netmap_reset_ring(struct ena_adapter *adapter, int qid, enum txrx x)
+{
+ if (!ena_ring_in_netmap(adapter, qid, x))
+ return;
+
+ netmap_reset(NA(adapter->ifp), x, qid, 0);
+ ena_trace(ENA_NETMAP, "%s ring %d is in netmap mode\n",
+ (x == NR_TX) ? "Tx" : "Rx", qid);
+}
+
void
ena_netmap_reset_rx_ring(struct ena_adapter *adapter, int qid)
{
- if (adapter->ifp->if_capenable & IFCAP_NETMAP)
- netmap_reset(NA(adapter->ifp), NR_RX, qid, 0);
+ ena_netmap_reset_ring(adapter, qid, NR_RX);
}
void
ena_netmap_reset_tx_ring(struct ena_adapter *adapter, int qid)
{
- if (adapter->ifp->if_capenable & IFCAP_NETMAP)
- netmap_reset(NA(adapter->ifp), NR_TX, qid, 0);
+ ena_netmap_reset_ring(adapter, qid, NR_TX);
}
static int
@@ -235,7 +273,9 @@ ena_netmap_reg(struct netmap_adapter *na, int onoff)
{
struct ifnet *ifp = na->ifp;
struct ena_adapter* adapter = ifp->if_softc;
- int rc;
+ struct netmap_kring *kring;
+ enum txrx t;
+ int rc, i;
sx_xlock(&adapter->ioctl_sx);
ENA_FLAG_CLEAR_ATOMIC(ENA_FLAG_TRIGGER_RESET, adapter);
@@ -243,10 +283,26 @@ ena_netmap_reg(struct netmap_adapter *na, int onoff)
if (onoff) {
ena_trace(ENA_NETMAP, "netmap on\n");
+ for_rx_tx(t) {
+ for (i = 0; i <= nma_get_nrings(na, t); i++) {
+ kring = NMR(na, t)[i];
+ if (nm_kring_pending_on(kring)) {
+ kring->nr_mode = NKR_NETMAP_ON;
+ }
+ }
+ }
nm_set_native_flags(na);
} else {
ena_trace(ENA_NETMAP, "netmap off\n");
nm_clear_native_flags(na);
+ for_rx_tx(t) {
+ for (i = 0; i <= nma_get_nrings(na, t); i++) {
+ kring = NMR(na, t)[i];
+ if (nm_kring_pending_off(kring)) {
+ kring->nr_mode = NKR_NETMAP_OFF;
+ }
+ }
+ }
}
rc = ena_up(adapter);
diff --git a/sys/dev/ena/ena_netmap.h b/sys/dev/ena/ena_netmap.h
index 0f9e0e6bb26b..a6b57ef3948d 100644
--- a/sys/dev/ena/ena_netmap.h
+++ b/sys/dev/ena/ena_netmap.h
@@ -51,6 +51,8 @@ int ena_netmap_alloc_rx_slot(struct ena_adapter *, struct ena_ring *,
struct ena_rx_buffer *);
void ena_netmap_free_rx_slot(struct ena_adapter *, struct ena_ring *,
struct ena_rx_buffer *);
+bool ena_rx_ring_in_netmap(struct ena_adapter *, int);
+bool ena_tx_ring_in_netmap(struct ena_adapter *, int);
void ena_netmap_reset_rx_ring(struct ena_adapter *, int);
void ena_netmap_reset_tx_ring(struct ena_adapter *, int);
void ena_netmap_unload(struct ena_adapter *, bus_dmamap_t);