From owner-svn-src-user@FreeBSD.ORG Tue Dec 30 04:22:48 2008 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4B462106566B; Tue, 30 Dec 2008 04:22:48 +0000 (UTC) (envelope-from ps@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 3AAA48FC19; Tue, 30 Dec 2008 04:22:48 +0000 (UTC) (envelope-from ps@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id mBU4Mmp5075802; Tue, 30 Dec 2008 04:22:48 GMT (envelope-from ps@svn.freebsd.org) Received: (from ps@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id mBU4Mm8W075800; Tue, 30 Dec 2008 04:22:48 GMT (envelope-from ps@svn.freebsd.org) Message-Id: <200812300422.mBU4Mm8W075800@svn.freebsd.org> From: Paul Saab Date: Tue, 30 Dec 2008 04:22:48 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r186584 - user/kmacy/HEAD_fast_net/sys/dev/e1000 X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 30 Dec 2008 04:22:48 -0000 Author: ps Date: Tue Dec 30 04:22:47 2008 New Revision: 186584 URL: http://svn.freebsd.org/changeset/base/186584 Log: Bring in if_transmit support for if_em and also fix a use after free bug that was fixed in r185621 Modified: user/kmacy/HEAD_fast_net/sys/dev/e1000/if_em.c user/kmacy/HEAD_fast_net/sys/dev/e1000/if_em.h Modified: user/kmacy/HEAD_fast_net/sys/dev/e1000/if_em.c ============================================================================== --- user/kmacy/HEAD_fast_net/sys/dev/e1000/if_em.c Tue Dec 30 04:20:06 2008 (r186583) +++ user/kmacy/HEAD_fast_net/sys/dev/e1000/if_em.c Tue Dec 30 04:22:47 2008 (r186584) @@ -39,6 +39,7 @@ #include #include +#include #include #include #include @@ -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/sys/dev/e1000/if_em.h ============================================================================== --- user/kmacy/HEAD_fast_net/sys/dev/e1000/if_em.h Tue Dec 30 04:20:06 2008 (r186583) +++ user/kmacy/HEAD_fast_net/sys/dev/e1000/if_em.h Tue Dec 30 04:22:47 2008 (r186584) @@ -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)