Author: adrian
Date: Tue Jan 15 17:50:07 2013
New Revision: 245464
URL: http://svnweb.freebsd.org/changeset/base/245464

Log:
  Remove the use of the ifnet send queue and if_start() in the power
  save queue code.
  
  Instead, use if_transmit() directly - and handle the cases where frame
  transmission fails.
  
  I don't necessarily like this and I think at this point the M_ENCAP check,
  node freeing upon fail and the actual if_transmit() call should be done
  in methods in ieee80211_freebsd.c, but I digress slightly..
  
  This removes one of the last few uses of if_start() and the ifnet
  if_snd queue.  The last major offender is ieee80211_output.c, where
  ieee80211_start() implements if_start() and uses the ifnet queue
  directly.
  
  (There's a couple of gotchas here, where the if_start pointer is
  compared to ieee80211_start(), but that's a later problem.)

Modified:
  head/sys/net80211/ieee80211_power.c

Modified: head/sys/net80211/ieee80211_power.c
==============================================================================
--- head/sys/net80211/ieee80211_power.c Tue Jan 15 17:17:54 2013        
(r245463)
+++ head/sys/net80211/ieee80211_power.c Tue Jan 15 17:50:07 2013        
(r245464)
@@ -416,6 +416,8 @@ pwrsave_flushq(struct ieee80211_node *ni
        struct ieee80211vap *vap = ni->ni_vap;
        struct ieee80211_psq_head *qhead;
        struct ifnet *parent, *ifp;
+       struct mbuf *parent_q = NULL, *ifp_q = NULL;
+       struct mbuf *m;
 
        IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
            "flush ps queue, %u packets queued", psq->psq_len);
@@ -427,8 +429,7 @@ pwrsave_flushq(struct ieee80211_node *ni
                parent = vap->iv_ic->ic_ifp;
                /* XXX need different driver interface */
                /* XXX bypasses q max and OACTIVE */
-               IF_PREPEND_LIST(&parent->if_snd, qhead->head, qhead->tail,
-                   qhead->len);
+               parent_q = qhead->head;
                qhead->head = qhead->tail = NULL;
                qhead->len = 0;
        } else
@@ -439,8 +440,7 @@ pwrsave_flushq(struct ieee80211_node *ni
                ifp = vap->iv_ifp;
                /* XXX need different driver interface */
                /* XXX bypasses q max and OACTIVE */
-               IF_PREPEND_LIST(&ifp->if_snd, qhead->head, qhead->tail,
-                   qhead->len);
+               ifp_q = qhead->head;
                qhead->head = qhead->tail = NULL;
                qhead->len = 0;
        } else
@@ -450,10 +450,34 @@ pwrsave_flushq(struct ieee80211_node *ni
 
        /* NB: do this outside the psq lock */
        /* XXX packets might get reordered if parent is OACTIVE */
-       if (parent != NULL)
-               if_start(parent);
-       if (ifp != NULL)
-               if_start(ifp);
+       /* parent frames, should be encapsulated */
+       if (parent != NULL) {
+               while (parent_q != NULL) {
+                       m = parent_q;
+                       parent_q = m->m_nextpkt;
+                       /* must be encapsulated */
+                       KASSERT((m->m_flags & M_ENCAP),
+                           ("%s: parentq with non-M_ENCAP frame!\n",
+                           __func__));
+                       /*
+                        * For encaped frames, we need to free the node
+                        * reference upon failure.
+                        */
+                       if (parent->if_transmit(parent, m) != 0)
+                               ieee80211_free_node(ni);
+               }
+       }
+
+       /* VAP frames, aren't encapsulated */
+       if (ifp != NULL) {
+               while (ifp_q != NULL) {
+                       m = ifp_q;
+                       ifp_q = m->m_nextpkt;
+                       KASSERT((!(m->m_flags & M_ENCAP)),
+                           ("%s: vapq with M_ENCAP frame!\n", __func__));
+                       (void) ifp->if_transmit(ifp, m);
+               }
+       }
 }
 
 /*
_______________________________________________
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