svn commit: r189378 - user/kmacy/HEAD_fast_net_merge/sys/dev/e1000
Kip Macy
kmacy at FreeBSD.org
Wed Mar 4 14:22:31 PST 2009
Author: kmacy
Date: Wed Mar 4 22:22:30 2009
New Revision: 189378
URL: http://svn.freebsd.org/changeset/base/189378
Log:
add option to make em use a buf_ring
186584
186584:
- Bring in if_transmit support for if_em
- fix a use after free bug that was fixed in r185621
Modified:
user/kmacy/HEAD_fast_net_merge/sys/dev/e1000/if_em.c
user/kmacy/HEAD_fast_net_merge/sys/dev/e1000/if_em.h
Modified: user/kmacy/HEAD_fast_net_merge/sys/dev/e1000/if_em.c
==============================================================================
--- user/kmacy/HEAD_fast_net_merge/sys/dev/e1000/if_em.c Wed Mar 4 22:05:25 2009 (r189377)
+++ user/kmacy/HEAD_fast_net_merge/sys/dev/e1000/if_em.c Wed Mar 4 22:22:30 2009 (r189378)
@@ -39,6 +39,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/buf_ring.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/kernel.h>
@@ -889,6 +890,7 @@ em_detach(device_t dev)
em_free_pci_resources(adapter);
bus_generic_detach(dev);
if_free(ifp);
+ drbr_free(adapter->br, M_DEVBUF);
em_free_transmit_structures(adapter);
em_free_receive_structures(adapter);
@@ -984,6 +986,81 @@ em_resume(device_t dev)
* the packet is requeued.
**********************************************************************/
+#ifdef IFNET_MULTIQUEUE
+static int
+em_transmit_locked(struct ifnet *ifp, struct mbuf *m)
+{
+ struct adapter *adapter = ifp->if_softc;
+ int error;
+
+ EM_TX_LOCK_ASSERT(adapter);
+ if (((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) !=
+ IFF_DRV_RUNNING)
+ || (!adapter->link_active)) {
+ error = drbr_enqueue(ifp, adapter->br, m);
+ return (error);
+ }
+
+ if (buf_ring_empty(adapter->br) &&
+ (adapter->num_tx_desc_avail > EM_TX_OP_THRESHOLD)) {
+ if (em_xmit(adapter, &m)) {
+ if (m && (error = drbr_enqueue(ifp, adapter->br, m)) != 0) {
+ return (error);
+ }
+ } else{
+ /* Send a copy of the frame to the BPF listener */
+ ETHER_BPF_MTAP(ifp, m);
+ }
+ } else if ((error = drbr_enqueue(ifp, adapter->br, m)) != 0)
+ return (error);
+
+ if (!buf_ring_empty(adapter->br))
+ em_start_locked(ifp);
+
+ return (0);
+}
+
+static void
+em_start_locked(struct ifnet *ifp)
+{
+ struct adapter *adapter = ifp->if_softc;
+ struct mbuf *m_head;
+
+ EM_TX_LOCK_ASSERT(adapter);
+
+ if ((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) !=
+ IFF_DRV_RUNNING)
+ return;
+ if (!adapter->link_active)
+ return;
+
+ while ((adapter->num_tx_desc_avail > EM_TX_OP_THRESHOLD)
+ && (!buf_ring_empty(adapter->br))) {
+
+ m_head = buf_ring_dequeue_sc(adapter->br);
+ if (m_head == NULL)
+ break;
+ /*
+ * Encapsulation can modify our pointer, and or make it
+ * NULL on failure. In that event, we can't requeue.
+ */
+ if (em_xmit(adapter, &m_head)) {
+ if (m_head == NULL)
+ break;
+ break;
+ }
+
+ /* Send a copy of the frame to the BPF listener */
+ ETHER_BPF_MTAP(ifp, m_head);
+
+ /* Set timeout in case hardware has problems transmitting. */
+ adapter->watchdog_timer = EM_TX_TIMEOUT;
+ }
+ if ((adapter->num_tx_desc_avail <= EM_TX_OP_THRESHOLD))
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+
+}
+#else
static void
em_start_locked(struct ifnet *ifp)
{
@@ -1022,6 +1099,7 @@ em_start_locked(struct ifnet *ifp)
adapter->watchdog_timer = EM_TX_TIMEOUT;
}
}
+#endif
static void
em_start(struct ifnet *ifp)
@@ -1034,6 +1112,23 @@ em_start(struct ifnet *ifp)
EM_TX_UNLOCK(adapter);
}
+static int
+em_transmit(struct ifnet *ifp, struct mbuf *m)
+{
+
+ struct adapter *adapter = ifp->if_softc;
+ int error = 0;
+
+ if(EM_TX_TRYLOCK(adapter)) {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ error = em_transmit_locked(ifp, m);
+ EM_TX_UNLOCK(adapter);
+ } else
+ error = drbr_enqueue(ifp, adapter->br, m);
+
+ return (error);
+}
+
/*********************************************************************
* Ioctl entry point
*
@@ -1597,7 +1692,11 @@ em_poll(struct ifnet *ifp, enum poll_cmd
EM_TX_LOCK(adapter);
em_txeof(adapter);
+#ifdef IFNET_MULTIQUEUE
+ if (!buf_ring_empty(adapter->br))
+#else
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+#endif
em_start_locked(ifp);
EM_TX_UNLOCK(adapter);
}
@@ -1665,8 +1764,15 @@ em_intr(void *arg)
}
EM_CORE_UNLOCK(adapter);
+
if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
- !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+#ifdef IFNET_MULTIQUEUE
+ !buf_ring_empty(adapter->br)
+#else
+ !IFQ_DRV_IS_EMPTY(&ifp->if_snd)
+#endif
+ )
+
em_start(ifp);
}
@@ -1705,7 +1811,11 @@ em_handle_rxtx(void *context, int pendin
EM_TX_LOCK(adapter);
em_txeof(adapter);
+#ifdef IFNET_MULTIQUEUE
+ if (!buf_ring_empty(adapter->br))
+#else
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+#endif
em_start_locked(ifp);
EM_TX_UNLOCK(adapter);
}
@@ -1732,9 +1842,19 @@ em_handle_tx(void *context, int pending)
struct ifnet *ifp = adapter->ifp;
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+#ifdef IFNET_MULTIQUEUE
+ if (!EM_TX_TRYLOCK(adapter))
+ return;
+#else
EM_TX_LOCK(adapter);
+#endif
+
em_txeof(adapter);
+#ifdef IFNET_MULTIQUEUE
+ if (!buf_ring_empty(adapter->br))
+#else
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+#endif
em_start_locked(ifp);
EM_TX_UNLOCK(adapter);
}
@@ -2083,22 +2203,14 @@ em_xmit(struct adapter *adapter, struct
error = bus_dmamap_load_mbuf_sg(adapter->txtag, map,
*m_headp, segs, &nsegs, BUS_DMA_NOWAIT);
- if (error == ENOMEM) {
- adapter->no_tx_dma_setup++;
- return (error);
- } else if (error != 0) {
+ if (error) {
adapter->no_tx_dma_setup++;
m_freem(*m_headp);
*m_headp = NULL;
return (error);
}
- } else if (error == ENOMEM) {
- adapter->no_tx_dma_setup++;
- return (error);
} else if (error != 0) {
adapter->no_tx_dma_setup++;
- m_freem(*m_headp);
- *m_headp = NULL;
return (error);
}
@@ -2531,7 +2643,8 @@ em_local_timer(void *arg)
struct ifnet *ifp = adapter->ifp;
EM_CORE_LOCK_ASSERT(adapter);
-
+ taskqueue_enqueue(adapter->tq,
+ &adapter->rxtx_task);
em_update_link_status(adapter);
em_update_stats_counters(adapter);
@@ -3125,7 +3238,11 @@ em_setup_interface(device_t dev, struct
ether_ifattach(ifp, adapter->hw.mac.addr);
ifp->if_capabilities = ifp->if_capenable = 0;
-
+#ifdef IFNET_MULTIQUEUE
+ ifp->if_transmit = em_transmit;
+ adapter->br = buf_ring_alloc(2048, M_DEVBUF, M_WAITOK, &adapter->tx_mtx);
+#endif
+
if (adapter->hw.mac.type >= e1000_82543) {
int version_cap;
#if __FreeBSD_version < 700000
Modified: user/kmacy/HEAD_fast_net_merge/sys/dev/e1000/if_em.h
==============================================================================
--- user/kmacy/HEAD_fast_net_merge/sys/dev/e1000/if_em.h Wed Mar 4 22:05:25 2009 (r189377)
+++ user/kmacy/HEAD_fast_net_merge/sys/dev/e1000/if_em.h Wed Mar 4 22:22:30 2009 (r189378)
@@ -36,6 +36,7 @@
#ifndef _EM_H_DEFINED_
#define _EM_H_DEFINED_
+#define IFNET_MULTIQUEUE
/* Tunables */
/*
@@ -301,6 +302,9 @@ struct em_dma_alloc {
/* Our adapter structure */
struct adapter {
struct ifnet *ifp;
+#ifdef IFNET_MULTIQUEUE
+ struct buf_ring *br;
+#endif
struct e1000_hw hw;
/* FreeBSD operating-system-specific structures. */
@@ -482,6 +486,7 @@ typedef struct _DESCRIPTOR_PAIR
#define EM_RX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rx_mtx)
#define EM_CORE_LOCK(_sc) mtx_lock(&(_sc)->core_mtx)
#define EM_TX_LOCK(_sc) mtx_lock(&(_sc)->tx_mtx)
+#define EM_TX_TRYLOCK(_sc) mtx_trylock(&(_sc)->tx_mtx)
#define EM_RX_LOCK(_sc) mtx_lock(&(_sc)->rx_mtx)
#define EM_CORE_UNLOCK(_sc) mtx_unlock(&(_sc)->core_mtx)
#define EM_TX_UNLOCK(_sc) mtx_unlock(&(_sc)->tx_mtx)
More information about the svn-src-user
mailing list