Author: mlaier
Date: Sat Feb 13 16:04:58 2010
New Revision: 203834
URL: http://svn.freebsd.org/changeset/base/203834

Log:
  Fix drbr and altq interaction:
   - introduce drbr_needs_enqueue that returns whether the interface/br needs
     an enqueue operation: returns true if altq is enabled or there are
     already packets in the ring (as we need to maintain packet order)
   - update all drbr consumers
   - fix drbr_flush
   - avoid using the driver queue (IFQ_DRV_*) in the altq case as the
     multiqueue consumer does not provide enough protection, serialize altq
     interaction with the main queue lock
   - make drbr_dequeue_cond work with altq
  
  Discussed with:               kmacy, yongari, jfv
  MFC after:            4 weeks

Modified:
  head/sys/dev/cxgb/cxgb_sge.c
  head/sys/dev/e1000/if_em.c
  head/sys/dev/e1000/if_igb.c
  head/sys/dev/ixgbe/ixgbe.c
  head/sys/dev/mxge/if_mxge.c
  head/sys/net/if_var.h

Modified: head/sys/dev/cxgb/cxgb_sge.c
==============================================================================
--- head/sys/dev/cxgb/cxgb_sge.c        Sat Feb 13 15:36:33 2010        
(r203833)
+++ head/sys/dev/cxgb/cxgb_sge.c        Sat Feb 13 16:04:58 2010        
(r203834)
@@ -228,6 +228,8 @@ static uint8_t flit_desc_map[] = {
 #define        TXQ_LOCK(qs)            mtx_lock(&(qs)->lock)   
 #define        TXQ_UNLOCK(qs)          mtx_unlock(&(qs)->lock) 
 #define        TXQ_RING_EMPTY(qs)      drbr_empty((qs)->port->ifp, 
(qs)->txq[TXQ_ETH].txq_mr)
+#define        TXQ_RING_NEEDS_ENQUEUE(qs)                                      
\
+       drbr_needs_enqueue((qs)->port->ifp, (qs)->txq[TXQ_ETH].txq_mr)
 #define        TXQ_RING_FLUSH(qs)      drbr_flush((qs)->port->ifp, 
(qs)->txq[TXQ_ETH].txq_mr)
 #define        TXQ_RING_DEQUEUE_COND(qs, func, arg)                            
\
        drbr_dequeue_cond((qs)->port->ifp, (qs)->txq[TXQ_ETH].txq_mr, func, arg)
@@ -1712,7 +1714,7 @@ cxgb_transmit_locked(struct ifnet *ifp, 
         * - there is space in hardware transmit queue 
         */
        if (check_pkt_coalesce(qs) == 0 &&
-           TXQ_RING_EMPTY(qs) && avail > 4) {
+           !TXQ_RING_NEEDS_ENQUEUE(qs) && avail > 4) {
                if (t3_encap(qs, &m)) {
                        if (m != NULL &&
                            (error = drbr_enqueue(ifp, br, m)) != 0) 

Modified: head/sys/dev/e1000/if_em.c
==============================================================================
--- head/sys/dev/e1000/if_em.c  Sat Feb 13 15:36:33 2010        (r203833)
+++ head/sys/dev/e1000/if_em.c  Sat Feb 13 16:04:58 2010        (r203834)
@@ -955,7 +955,7 @@ em_mq_start_locked(struct ifnet *ifp, st
            || (!adapter->link_active)) {
                error = drbr_enqueue(ifp, adapter->br, m);
                return (error);
-       } else if (drbr_empty(ifp, adapter->br) &&
+       } else if (!drbr_needs_enqueue(ifp, adapter->br) &&
            (adapter->num_tx_desc_avail > EM_TX_OP_THRESHOLD)) {
                if ((error = em_xmit(adapter, &m)) != 0) {
                        if (m)

Modified: head/sys/dev/e1000/if_igb.c
==============================================================================
--- head/sys/dev/e1000/if_igb.c Sat Feb 13 15:36:33 2010        (r203833)
+++ head/sys/dev/e1000/if_igb.c Sat Feb 13 16:04:58 2010        (r203834)
@@ -842,9 +842,13 @@ igb_mq_start_locked(struct ifnet *ifp, s
        }
 
        enq = 0;
-       if (m == NULL)
+       if (m == NULL) {
                next = drbr_dequeue(ifp, txr->br);
-       else
+       } else if (drbr_needs_enqueue(ifp, txr->br)) {
+               if ((err = drbr_enqueue(ifp, txr->br, m)) != 0)
+                       return (err);
+               next = drbr_dequeue(ifp, txr->br);
+       } else
                next = m;
        /* Process the queue */
        while (next != NULL) {

Modified: head/sys/dev/ixgbe/ixgbe.c
==============================================================================
--- head/sys/dev/ixgbe/ixgbe.c  Sat Feb 13 15:36:33 2010        (r203833)
+++ head/sys/dev/ixgbe/ixgbe.c  Sat Feb 13 16:04:58 2010        (r203834)
@@ -861,7 +861,7 @@ ixgbe_mq_start_locked(struct ifnet *ifp,
                goto process;
 
        /* If nothing queued go right to xmit */
-       if (drbr_empty(ifp, txr->br)) {
+       if (!drbr_needs_enqueue(ifp, txr->br)) {
                if ((err = ixgbe_xmit(txr, &m)) != 0) {
                        if (m != NULL)
                                err = drbr_enqueue(ifp, txr->br, m);

Modified: head/sys/dev/mxge/if_mxge.c
==============================================================================
--- head/sys/dev/mxge/if_mxge.c Sat Feb 13 15:36:33 2010        (r203833)
+++ head/sys/dev/mxge/if_mxge.c Sat Feb 13 16:04:58 2010        (r203834)
@@ -2249,7 +2249,7 @@ mxge_transmit_locked(struct mxge_slice_s
                return (err);
        }
 
-       if (drbr_empty(ifp, tx->br) &&
+       if (!drbr_needs_enqueue(ifp, tx->br) &&
            ((tx->mask - (tx->req - tx->done)) > tx->max_desc)) {
                /* let BPF see it */
                BPF_MTAP(ifp, m);

Modified: head/sys/net/if_var.h
==============================================================================
--- head/sys/net/if_var.h       Sat Feb 13 15:36:33 2010        (r203833)
+++ head/sys/net/if_var.h       Sat Feb 13 16:04:58 2010        (r203834)
@@ -603,12 +603,8 @@ drbr_flush(struct ifnet *ifp, struct buf
        struct mbuf *m;
 
 #ifdef ALTQ
-       if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
-               while (!IFQ_IS_EMPTY(&ifp->if_snd)) {
-                       IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
-                       m_freem(m);
-               }
-       }
+       if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd))
+               IFQ_PURGE(&ifp->if_snd);
 #endif 
        while ((m = buf_ring_dequeue_sc(br)) != NULL)
                m_freem(m);
@@ -629,7 +625,7 @@ drbr_dequeue(struct ifnet *ifp, struct b
        struct mbuf *m;
 
        if (ALTQ_IS_ENABLED(&ifp->if_snd)) {    
-               IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+               IFQ_DEQUEUE(&ifp->if_snd, m);
                return (m);
        }
 #endif
@@ -642,11 +638,15 @@ drbr_dequeue_cond(struct ifnet *ifp, str
 {
        struct mbuf *m;
 #ifdef ALTQ
-       /*
-        * XXX need to evaluate / requeue 
-        */
-       if (ALTQ_IS_ENABLED(&ifp->if_snd)) {    
-               IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+       if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
+               IFQ_LOCK(&ifp->if_snd);
+               IFQ_POLL_NOLOCK(&ifp->if_snd, m);
+               if (m != NULL && func(m, arg) == 0) {
+                       IFQ_UNLOCK(&ifp->if_snd);
+                       return (NULL);
+               }
+               IFQ_DEQUEUE(&ifp->if_snd, m);
+               IFQ_UNLOCK(&ifp->if_snd);
                return (m);
        }
 #endif
@@ -662,12 +662,22 @@ drbr_empty(struct ifnet *ifp, struct buf
 {
 #ifdef ALTQ
        if (ALTQ_IS_ENABLED(&ifp->if_snd))
-               return (IFQ_DRV_IS_EMPTY(&ifp->if_snd));
+               return (IFQ_IS_EMPTY(&ifp->if_snd));
 #endif
        return (buf_ring_empty(br));
 }
 
 static __inline int
+drbr_needs_enqueue(struct ifnet *ifp, struct buf_ring *br)
+{
+#ifdef ALTQ
+       if (ALTQ_IS_ENABLED(&ifp->if_snd))
+               return (1);
+#endif
+       return (!buf_ring_empty(br));
+}
+
+static __inline int
 drbr_inuse(struct ifnet *ifp, struct buf_ring *br)
 {
 #ifdef ALTQ
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to