Author: adrian
Date: Mon Jan 21 04:06:04 2013
New Revision: 245708
URL: http://svnweb.freebsd.org/changeset/base/245708

Log:
  Migrate CLRDMASK to be a per-node flag, rather than a per-TID flag.
  
  This is easily possible now that the TX is protected by a single
  lock, rather than a per-TXQ (and thus per-TID) lock.
  
  Only set CLRDMASK if none of the destinations are filtered.
  This likely will need some tuning when it comes time to do UASPD/PS-POLL
  TX, however at that point it should be manually set anyway.
  
  Tested:
  
  * AR9280, STA mode
  
  TODO:
  
  * More thorough testing in AP mode
  * test other chipsets, just to be safe/sure.

Modified:
  head/sys/dev/ath/if_ath_tx.c
  head/sys/dev/ath/if_athvar.h

Modified: head/sys/dev/ath/if_ath_tx.c
==============================================================================
--- head/sys/dev/ath/if_ath_tx.c        Mon Jan 21 02:47:14 2013        
(r245707)
+++ head/sys/dev/ath/if_ath_tx.c        Mon Jan 21 04:06:04 2013        
(r245708)
@@ -1397,12 +1397,13 @@ static void
 ath_tx_update_clrdmask(struct ath_softc *sc, struct ath_tid *tid,
     struct ath_buf *bf)
 {
+       struct ath_node *an = ATH_NODE(bf->bf_node);
 
        ATH_TX_LOCK_ASSERT(sc);
 
-       if (tid->clrdmask == 1) {
+       if (an->clrdmask == 1) {
                bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK;
-               tid->clrdmask = 0;
+               an->clrdmask = 0;
        }
 }
 
@@ -2888,6 +2889,29 @@ ath_tx_swq(struct ath_softc *sc, struct 
 }
 
 /*
+ * Only set the clrdmask bit if none of the nodes are currently
+ * filtered.
+ *
+ * XXX TODO: go through all the callers and check to see
+ * which are being called in the context of looping over all
+ * TIDs (eg, if all tids are being paused, resumed, etc.)
+ * That'll avoid O(n^2) complexity here.
+ */
+static void
+ath_tx_set_clrdmask(struct ath_softc *sc, struct ath_node *an)
+{
+       int i;
+
+       ATH_TX_LOCK_ASSERT(sc);
+
+       for (i = 0; i < IEEE80211_TID_SIZE; i++) {
+               if (an->an_tid[i].isfiltered == 1)
+                       break;
+       }
+       an->clrdmask = 1;
+}
+
+/*
  * Configure the per-TID node state.
  *
  * This likely belongs in if_ath_node.c but I can't think of anywhere
@@ -2918,12 +2942,12 @@ ath_tx_tid_init(struct ath_softc *sc, st
                atid->sched = 0;
                atid->hwq_depth = 0;
                atid->cleanup_inprogress = 0;
-               atid->clrdmask = 1;     /* Always start by setting this bit */
                if (i == IEEE80211_NONQOS_TID)
                        atid->ac = ATH_NONQOS_TID_AC;
                else
                        atid->ac = TID_TO_WME_AC(i);
        }
+       an->clrdmask = 1;       /* Always start by setting this bit */
 }
 
 /*
@@ -2949,7 +2973,6 @@ ath_tx_tid_pause(struct ath_softc *sc, s
 static void
 ath_tx_tid_resume(struct ath_softc *sc, struct ath_tid *tid)
 {
-
        ATH_TX_LOCK_ASSERT(sc);
 
        tid->paused--;
@@ -2964,7 +2987,7 @@ ath_tx_tid_resume(struct ath_softc *sc, 
         * Override the clrdmask configuration for the next frame
         * from this TID, just to get the ball rolling.
         */
-       tid->clrdmask = 1;
+       ath_tx_set_clrdmask(sc, tid->an);
 
        if (tid->axq_depth == 0)
                return;
@@ -3047,7 +3070,8 @@ ath_tx_tid_filt_comp_complete(struct ath
        DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: hwq=0, transition back\n",
            __func__);
        tid->isfiltered = 0;
-       tid->clrdmask = 1;
+       /* XXX ath_tx_tid_resume() also calls ath_tx_set_clrdmask()! */
+       ath_tx_set_clrdmask(sc, tid->an);
 
        /* XXX this is really quite inefficient */
        while ((bf = ATH_TID_FILT_LAST(tid, ath_bufhead_s)) != NULL) {
@@ -3303,7 +3327,7 @@ ath_tx_tid_bar_tx(struct ath_softc *sc, 
         * Override the clrdmask configuration for the next frame,
         * just to get the ball rolling.
         */
-       tid->clrdmask = 1;
+       ath_tx_set_clrdmask(sc, tid->an);
 
        /*
         * Calculate new BAW left edge, now that all frames have either
@@ -3484,7 +3508,7 @@ ath_tx_tid_drain(struct ath_softc *sc, s
         *
         * This won't hurt things if the TID is about to be freed.
         */
-       tid->clrdmask = 1;
+       ath_tx_set_clrdmask(sc, tid->an);
 
        /*
         * Now that it's completed, grab the TID lock and update

Modified: head/sys/dev/ath/if_athvar.h
==============================================================================
--- head/sys/dev/ath/if_athvar.h        Mon Jan 21 02:47:14 2013        
(r245707)
+++ head/sys/dev/ath/if_athvar.h        Mon Jan 21 04:06:04 2013        
(r245708)
@@ -132,7 +132,6 @@ struct ath_tid {
        int                     bar_wait;       /* waiting for BAR */
        int                     bar_tx;         /* BAR TXed */
        int                     isfiltered;     /* is this node currently 
filtered */
-       int                     clrdmask;       /* has clrdmask been set */
 
        /*
         * Is the TID being cleaned up after a transition
@@ -182,6 +181,7 @@ struct ath_node {
        struct mtx      an_mtx;         /* protecting the ath_node state */
        uint32_t        an_swq_depth;   /* how many SWQ packets for this
                                           node */
+       int                     clrdmask;       /* has clrdmask been set */
        /* variable-length rate control state follows */
 };
 #define        ATH_NODE(ni)    ((struct ath_node *)(ni))
_______________________________________________
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