--- //depot/vendor/freebsd/src/sys/dev/em/if_em.c 2005/06/10 16:51:34 +++ //depot/user/rwatson/ifnet/src/sys/dev/em/if_em.c 2005/06/12 16:49:13 @@ -650,6 +650,68 @@ return; } +static void +em_startmbuf_locked(struct ifnet *ifp) +{ + struct mbuf *m_head; + struct adapter *adapter = ifp->if_softc; + struct ifqueue *ifq = (struct ifqueue *)&ifp->if_snd; + + mtx_assert(&adapter->mtx, MA_OWNED); + + while (_IF_QLEN(ifq) != 0) { + + _IF_DEQUEUE(ifq, m_head); + + if (m_head == NULL) break; + + /* + * em_encap() can modify our pointer, and or make it NULL on + * failure. In that event, we can't requeue. + */ + if (em_encap(adapter, &m_head)) { + if (m_head == NULL) + break; + ifp->if_flags |= IFF_OACTIVE; + _IF_PREPEND(ifq, m_head); + break; + } + + /* Send a copy of the frame to the BPF listener */ + BPF_MTAP(ifp, m_head); + + /* Set timeout in case hardware has problems transmitting */ + ifp->if_timer = EM_TX_TIMEOUT; + + } + return; +} + +static int +em_startmbuf(struct ifnet *ifp, struct mbuf *m, int adjust) +{ + struct adapter *adapter = ifp->if_softc; + struct ifqueue *ifq = (struct ifqueue *)&ifp->if_snd; + int ret; + + if (!adapter->link_active) { + m_freem(m); + return (1); /* Emulate success case. */ + } + + /* + * XXXRW: We could fast path the queue length zero case, but for now + * insert into the driver-locked queue and then try to proceed + * normally. + */ + EM_LOCK(adapter); + ret = if_startmbuf_enqueue(ifq, m, ifp, adjust); + if (ret == 1) + em_startmbuf_locked(ifp); + EM_UNLOCK(adapter); + return (ret); +} + /********************************************************************* * Ioctl entry point * @@ -1940,6 +2002,7 @@ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = em_ioctl; ifp->if_start = em_start; + ifp->if_startmbuf = em_startmbuf; ifp->if_watchdog = em_watchdog; IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 1); ifp->if_snd.ifq_drv_maxlen = adapter->num_tx_desc - 1; --- //depot/vendor/freebsd/src/sys/net/if.c 2005/06/12 00:55:43 +++ //depot/user/rwatson/ifnet/src/sys/net/if.c 2005/06/12 15:49:54 @@ -2127,11 +2127,18 @@ (ifp->if_start)(ifp); } +static int startmbuf_enabled; +SYSCTL_INT(_net, OID_AUTO, startmbuf_enabled, CTLFLAG_RW, &startmbuf_enabled, + 0, ""); + int if_handoff(struct ifqueue *ifq, struct mbuf *m, struct ifnet *ifp, int adjust) { int active = 0; + if (startmbuf_enabled && ifp != NULL && ifp->if_startmbuf != NULL) + return ((ifp->if_startmbuf)(ifp, m, adjust)); + IF_LOCK(ifq); if (_IF_QFULL(ifq)) { _IF_DROP(ifq); @@ -2152,6 +2159,23 @@ return (1); } +int +if_startmbuf_enqueue(struct ifqueue *ifq, struct mbuf *m, struct ifnet *ifp, + int adjust) +{ + + if (_IF_QFULL(ifq)) { + _IF_DROP(ifq); + m_freem(m); + return (0); + } + ifp->if_obytes += m->m_pkthdr.len + adjust; + if (m->m_flags & (M_BCAST|M_MCAST)) + ifp->if_omcasts++; + _IF_ENQUEUE(ifq, m); + return (1); +} + void if_register_com_alloc(u_char type, if_com_alloc_t *a, if_com_free_t *f) --- //depot/vendor/freebsd/src/sys/net/if_var.h 2005/06/10 16:51:34 +++ //depot/user/rwatson/ifnet/src/sys/net/if_var.h 2005/06/12 08:07:53 @@ -158,7 +158,8 @@ (void *); int (*if_resolvemulti) /* validate/resolve multicast */ (struct ifnet *, struct sockaddr **, struct sockaddr *); - void *if_spare1; /* spare pointer 1 */ + int (*if_startmbuf) /* enqueue and start output */ + (struct ifnet *, struct mbuf *, int adjust); void *if_spare2; /* spare pointer 2 */ void *if_spare3; /* spare pointer 3 */ u_int if_spare_flags1; /* spare flags 1 */ @@ -324,6 +325,9 @@ int if_handoff(struct ifqueue *ifq, struct mbuf *m, struct ifnet *ifp, int adjust); +int if_startmbuf_enqueue(struct ifqueue *ifq, struct mbuf *m, + struct ifnet *ifp, int adjust); + #define IF_HANDOFF(ifq, m, ifp) \ if_handoff((struct ifqueue *)ifq, m, ifp, 0) #define IF_HANDOFF_ADJ(ifq, m, ifp, adj) \