aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKip Macy <kmacy@FreeBSD.org>2009-04-14 03:36:59 +0000
committerKip Macy <kmacy@FreeBSD.org>2009-04-14 03:36:59 +0000
commitf2502470b51e2db800ec10cfb7f197dca504e106 (patch)
treefd9be265fbdc00d827942e96ade26b477bbfdb2d
parentaee3056f646e1d994e9c465a96b7661a9d75ef98 (diff)
downloadsrc-f2502470b51e2db800ec10cfb7f197dca504e106.tar.gz
src-f2502470b51e2db800ec10cfb7f197dca504e106.zip
- define em_transmit and em_qflush
- make buF_ring usage conditional but enabled by default Reviewed by: jfv
Notes
Notes: svn path=/head/; revision=191038
-rw-r--r--sys/dev/e1000/if_em.c141
-rw-r--r--sys/dev/e1000/if_em.h10
2 files changed, 138 insertions, 13 deletions
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index df54a53a385c..645ef06e9aeb 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -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>
@@ -897,6 +898,9 @@ em_detach(device_t dev)
bus_generic_detach(dev);
if_free(ifp);
+#ifdef IFNET_BUF_RING
+ drbr_free(adapter->br, M_DEVBUF);
+#endif
em_free_transmit_structures(adapter);
em_free_receive_structures(adapter);
@@ -991,6 +995,110 @@ em_resume(device_t dev)
* the packet is requeued.
**********************************************************************/
+#ifdef IFNET_BUF_RING
+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 (ADAPTER_RING_EMPTY(adapter) &&
+ (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 (!ADAPTER_RING_EMPTY(adapter))
+ em_start_locked(ifp);
+
+ return (0);
+}
+
+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);
+}
+
+static void
+em_qflush(struct ifnet *ifp)
+{
+ struct mbuf *m;
+ struct adapter *adapter = (struct adapter *)ifp->if_softc;
+
+ EM_TX_LOCK(adapter);
+ while ((m = buf_ring_dequeue_sc(adapter->br)) != NULL)
+ m_freem(m);
+ EM_TX_UNLOCK(adapter);
+}
+
+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)
+ && (!ADAPTER_RING_EMPTY(adapter))) {
+
+ 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)
{
@@ -1030,6 +1138,8 @@ em_start_locked(struct ifnet *ifp)
}
}
+#endif
+
static void
em_start(struct ifnet *ifp)
{
@@ -1603,7 +1713,7 @@ em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
EM_TX_LOCK(adapter);
em_txeof(adapter);
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ if (!ADAPTER_RING_EMPTY(adapter))
em_start_locked(ifp);
EM_TX_UNLOCK(adapter);
}
@@ -1658,7 +1768,7 @@ em_intr(void *arg)
out:
EM_CORE_UNLOCK(adapter);
if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
- !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ !ADAPTER_RING_EMPTY(adapter))
em_start(ifp);
}
@@ -1697,7 +1807,7 @@ em_handle_rxtx(void *context, int pending)
EM_TX_LOCK(adapter);
em_txeof(adapter);
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ if (!ADAPTER_RING_EMPTY(adapter))
em_start_locked(ifp);
EM_TX_UNLOCK(adapter);
}
@@ -1853,9 +1963,15 @@ em_handle_tx(void *context, int pending)
struct ifnet *ifp = adapter->ifp;
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+#ifdef IFNET_BUF_RING
+ if (!EM_TX_TRYLOCK(adapter))
+ return;
+#else
EM_TX_LOCK(adapter);
+#endif
+
em_txeof(adapter);
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ if (!ADAPTER_RING_EMPTY(adapter))
em_start_locked(ifp);
EM_TX_UNLOCK(adapter);
}
@@ -2075,22 +2191,14 @@ em_xmit(struct adapter *adapter, struct mbuf **m_headp)
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,6 +2639,8 @@ em_local_timer(void *arg)
EM_CORE_LOCK_ASSERT(adapter);
+ taskqueue_enqueue(adapter->tq,
+ &adapter->rxtx_task);
em_update_link_status(adapter);
em_update_stats_counters(adapter);
@@ -3126,6 +3236,11 @@ em_setup_interface(device_t dev, struct adapter *adapter)
ifp->if_capabilities = ifp->if_capenable = 0;
+#ifdef IFNET_BUF_RING
+ ifp->if_transmit = em_transmit;
+ ifp->if_qflush = em_qflush;
+ 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
diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h
index 889ceae5feaf..b9ae02a1f3ab 100644
--- a/sys/dev/e1000/if_em.h
+++ b/sys/dev/e1000/if_em.h
@@ -36,6 +36,7 @@
#ifndef _EM_H_DEFINED_
#define _EM_H_DEFINED_
+#define IFNET_BUF_RING
/* Tunables */
/*
@@ -301,6 +302,9 @@ struct em_dma_alloc {
/* Our adapter structure */
struct adapter {
struct ifnet *ifp;
+#ifdef IFNET_BUF_RING
+ 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)
@@ -489,4 +494,9 @@ typedef struct _DESCRIPTOR_PAIR
#define EM_CORE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->core_mtx, MA_OWNED)
#define EM_TX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->tx_mtx, MA_OWNED)
+#ifdef IFNET_BUF_RING
+#define ADAPTER_RING_EMPTY(adapter) drbr_empty((adapter)->ifp, (adapter)->br)
+#else
+#define ADAPTER_RING_EMPTY(adapter) IFQ_DRV_IS_EMPTY(&((adapter)->ifp->if_snd))
+#endif
#endif /* _EM_H_DEFINED_ */