summaryrefslogtreecommitdiffstats
path: root/sys/dev/ixl
diff options
context:
space:
mode:
authorluigi <luigi@FreeBSD.org>2015-02-24 06:20:50 +0000
committerluigi <luigi@FreeBSD.org>2015-02-24 06:20:50 +0000
commitb870399cc1909cf33491444a48060837e8e6e3e8 (patch)
tree6c790aa5b0f2af40c18d7c6a317a28485574ec7d /sys/dev/ixl
parentfa8630798cb68d399f17a2202982f0ce4ce6adbb (diff)
downloadFreeBSD-src-b870399cc1909cf33491444a48060837e8e6e3e8.zip
FreeBSD-src-b870399cc1909cf33491444a48060837e8e6e3e8.tar.gz
Add native netmap support to ixl.
Preliminary tests indicate 32 Mpps on tx, 24 Mpps on rx with source and receiver on two different ports of the same 40G card. Optimizations are likely possible. The code follows closely the one for ixgbe so i do not expect stability issues. Hardware kindly supplied by Intel. Reviewed by: Jack Vogel MFC after: 1 week
Diffstat (limited to 'sys/dev/ixl')
-rwxr-xr-xsys/dev/ixl/if_ixl.c22
-rwxr-xr-xsys/dev/ixl/ixl_txrx.c70
2 files changed, 92 insertions, 0 deletions
diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c
index e631030..ca34f62 100755
--- a/sys/dev/ixl/if_ixl.c
+++ b/sys/dev/ixl/if_ixl.c
@@ -213,6 +213,9 @@ DRIVER_MODULE(ixl, pci, ixl_driver, ixl_devclass, 0, 0);
MODULE_DEPEND(ixl, pci, 1, 1, 1);
MODULE_DEPEND(ixl, ether, 1, 1, 1);
+#ifdef DEV_NETMAP
+MODULE_DEPEND(ixl, netmap, 1, 1, 1);
+#endif /* DEV_NETMAP */
/*
** Global reset mutex
@@ -287,6 +290,10 @@ int ixl_atr_rate = 20;
TUNABLE_INT("hw.ixl.atr_rate", &ixl_atr_rate);
#endif
+#ifdef DEV_NETMAP
+#define NETMAP_IXL_MAIN /* only bring in one part of the netmap code */
+#include <dev/netmap/if_ixl_netmap.h>
+#endif /* DEV_NETMAP */
static char *ixl_fc_string[6] = {
"None",
@@ -647,6 +654,9 @@ ixl_attach(device_t dev)
ixl_unregister_vlan, vsi, EVENTHANDLER_PRI_FIRST);
+#ifdef DEV_NETMAP
+ ixl_netmap_attach(vsi);
+#endif /* DEV_NETMAP */
INIT_DEBUGOUT("ixl_attach: end");
return (0);
@@ -725,6 +735,9 @@ ixl_detach(device_t dev)
EVENTHANDLER_DEREGISTER(vlan_unconfig, vsi->vlan_detach);
callout_drain(&pf->timer);
+#ifdef DEV_NETMAP
+ netmap_detach(vsi->ifp);
+#endif /* DEV_NETMAP */
ixl_free_pci_resources(pf);
@@ -2662,6 +2675,15 @@ ixl_initialize_vsi(struct ixl_vsi *vsi)
break;
}
wr32(vsi->hw, I40E_QRX_TAIL(que->me), 0);
+#ifdef DEV_NETMAP
+ /* preserve queue */
+ if (vsi->ifp->if_capenable & IFCAP_NETMAP) {
+ struct netmap_adapter *na = NA(vsi->ifp);
+ struct netmap_kring *kring = &na->rx_rings[i];
+ int t = na->num_rx_desc - 1 - nm_kr_rxspace(kring);
+ wr32(vsi->hw, I40E_QRX_TAIL(que->me), t);
+ } else
+#endif /* DEV_NETMAP */
wr32(vsi->hw, I40E_QRX_TAIL(que->me), que->num_desc - 1);
}
return (err);
diff --git a/sys/dev/ixl/ixl_txrx.c b/sys/dev/ixl/ixl_txrx.c
index 89b07d1..5942e7c 100755
--- a/sys/dev/ixl/ixl_txrx.c
+++ b/sys/dev/ixl/ixl_txrx.c
@@ -62,6 +62,10 @@ static __inline void ixl_rx_discard(struct rx_ring *, int);
static __inline void ixl_rx_input(struct rx_ring *, struct ifnet *,
struct mbuf *, u8);
+#ifdef DEV_NETMAP
+#include <dev/netmap/if_ixl_netmap.h>
+#endif /* DEV_NETMAP */
+
/*
** Multiqueue Transmit driver
**
@@ -486,9 +490,21 @@ ixl_init_tx_ring(struct ixl_queue *que)
{
struct tx_ring *txr = &que->txr;
struct ixl_tx_buf *buf;
+#ifdef DEV_NETMAP
+ struct netmap_adapter *na = NA(que->vsi->ifp);
+ struct netmap_slot *slot;
+#endif /* DEV_NETMAP */
/* Clear the old ring contents */
IXL_TX_LOCK(txr);
+#ifdef DEV_NETMAP
+ /*
+ * (under lock): if in netmap mode, do some consistency
+ * checks and set slot to entry 0 of the netmap ring.
+ */
+ slot = netmap_reset(na, NR_TX, que->me, 0);
+#endif /* DEV_NETMAP */
+
bzero((void *)txr->base,
(sizeof(struct i40e_tx_desc)) * que->num_desc);
@@ -512,6 +528,19 @@ ixl_init_tx_ring(struct ixl_queue *que)
m_freem(buf->m_head);
buf->m_head = NULL;
}
+#ifdef DEV_NETMAP
+ /*
+ * In netmap mode, set the map for the packet buffer.
+ * NOTE: Some drivers (not this one) also need to set
+ * the physical buffer address in the NIC ring.
+ * netmap_idx_n2k() maps a nic index, i, into the corresponding
+ * netmap slot index, si
+ */
+ if (slot) {
+ int si = netmap_idx_n2k(&na->tx_rings[que->me], i);
+ netmap_load_map(na, buf->tag, buf->map, NMB(na, slot + si));
+ }
+#endif /* DEV_NETMAP */
/* Clear the EOP index */
buf->eop_index = -1;
}
@@ -823,6 +852,11 @@ ixl_txeof(struct ixl_queue *que)
mtx_assert(&txr->mtx, MA_OWNED);
+#ifdef DEV_NETMAP
+ // XXX todo: implement moderation
+ if (netmap_tx_irq(que->vsi->ifp, que->me))
+ return FALSE;
+#endif /* DEF_NETMAP */
/* These are not the descriptors you seek, move along :) */
if (txr->avail == que->num_desc) {
@@ -1124,8 +1158,16 @@ ixl_init_rx_ring(struct ixl_queue *que)
struct ixl_rx_buf *buf;
bus_dma_segment_t pseg[1], hseg[1];
int rsize, nsegs, error = 0;
+#ifdef DEV_NETMAP
+ struct netmap_adapter *na = NA(que->vsi->ifp);
+ struct netmap_slot *slot;
+#endif /* DEV_NETMAP */
IXL_RX_LOCK(rxr);
+#ifdef DEV_NETMAP
+ /* same as in ixl_init_tx_ring() */
+ slot = netmap_reset(na, NR_RX, que->me, 0);
+#endif /* DEV_NETMAP */
/* Clear the ring contents */
rsize = roundup2(que->num_desc *
sizeof(union i40e_rx_desc), DBA_ALIGN);
@@ -1159,6 +1201,28 @@ ixl_init_rx_ring(struct ixl_queue *que)
struct mbuf *mh, *mp;
buf = &rxr->buffers[j];
+#ifdef DEV_NETMAP
+ /*
+ * In netmap mode, fill the map and set the buffer
+ * address in the NIC ring, considering the offset
+ * between the netmap and NIC rings (see comment in
+ * ixgbe_setup_transmit_ring() ). No need to allocate
+ * an mbuf, so end the block with a continue;
+ */
+ if (slot) {
+ int sj = netmap_idx_n2k(&na->rx_rings[que->me], j);
+ uint64_t paddr;
+ void *addr;
+
+ addr = PNMB(na, slot + sj, &paddr);
+ netmap_load_map(na, rxr->dma.tag, buf->pmap, addr);
+ /* Update descriptor and the cached value */
+ rxr->base[j].read.pkt_addr = htole64(paddr);
+ rxr->base[j].read.hdr_addr = 0;
+ continue;
+ }
+#endif /* DEV_NETMAP */
+
/*
** Don't allocate mbufs if not
** doing header split, its wasteful
@@ -1458,6 +1522,12 @@ ixl_rxeof(struct ixl_queue *que, int count)
IXL_RX_LOCK(rxr);
+#ifdef DEV_NETMAP
+ if (netmap_rx_irq(ifp, que->me, &count)) {
+ IXL_RX_UNLOCK(rxr);
+ return (FALSE);
+ }
+#endif /* DEV_NETMAP */
for (i = rxr->next_check; count != 0;) {
struct mbuf *sendmp, *mh, *mp;
OpenPOWER on IntegriCloud