Author: bschmidt
Date: Sat Apr 16 13:25:19 2011
New Revision: 220720
URL: http://svn.freebsd.org/changeset/base/220720

Log:
  Fix WME/QoS handling:
  - move the TX queue selection into iwn_tx_data/iwn_tx_data_raw
  - extract traffic identifier and use it
  - do not expect ACKs for frames marked as such

Modified:
  head/sys/dev/iwn/if_iwn.c

Modified: head/sys/dev/iwn/if_iwn.c
==============================================================================
--- head/sys/dev/iwn/if_iwn.c   Sat Apr 16 13:12:12 2011        (r220719)
+++ head/sys/dev/iwn/if_iwn.c   Sat Apr 16 13:25:19 2011        (r220720)
@@ -158,7 +158,10 @@ static void        iwn5000_reset_sched(struct i
 #endif
 static uint8_t iwn_plcp_signal(int);
 static int     iwn_tx_data(struct iwn_softc *, struct mbuf *,
-                   struct ieee80211_node *, struct iwn_tx_ring *);
+                   struct ieee80211_node *);
+static int     iwn_tx_data_raw(struct iwn_softc *, struct mbuf *,
+                   struct ieee80211_node *,
+                   const struct ieee80211_bpf_params *params);
 static int     iwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
                    const struct ieee80211_bpf_params *);
 static void    iwn_start(struct ifnet *);
@@ -2913,8 +2916,7 @@ iwn_plcp_signal(int rate) {
 }
 
 static int
-iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
-    struct iwn_tx_ring *ring)
+iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
 {
        const struct iwn_hal *hal = sc->sc_hal;
        const struct ieee80211_txparam *tp;
@@ -2922,6 +2924,7 @@ iwn_tx_data(struct iwn_softc *sc, struct
        struct ieee80211vap *vap = ni->ni_vap;
        struct ieee80211com *ic = ni->ni_ic;
        struct iwn_node *wn = (void *)ni;
+       struct iwn_tx_ring *ring;
        struct iwn_tx_desc *desc;
        struct iwn_tx_data *data;
        struct iwn_tx_cmd *cmd;
@@ -2931,9 +2934,10 @@ iwn_tx_data(struct iwn_softc *sc, struct
        struct mbuf *m1;
        bus_dma_segment_t *seg, segs[IWN_MAX_SCATTER];
        uint32_t flags;
+       uint16_t qos;
        u_int hdrlen;
-       int totlen, error, pad, nsegs = 0, i, rate;
-       uint8_t ridx, type, txant;
+       uint8_t tid, ridx, type, txant;
+       int ac, i, totlen, error, pad, nsegs = 0, rate;
 
        IWN_LOCK_ASSERT(sc);
 
@@ -2941,6 +2945,17 @@ iwn_tx_data(struct iwn_softc *sc, struct
        hdrlen = ieee80211_anyhdrsize(wh);
        type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
 
+       /* Select EDCA Access Category and TX ring for this frame. */
+       if (IEEE80211_QOS_HAS_SEQ(wh)) {
+               qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0];
+               tid = qos & IEEE80211_QOS_TID;
+       } else {
+               qos = 0;
+               tid = 0;
+       }
+       ac = M_WME_GETAC(m);
+
+       ring = &sc->txq[ac];
        desc = &ring->desc[ring->cur];
        data = &ring->data[ring->cur];
 
@@ -2995,8 +3010,12 @@ iwn_tx_data(struct iwn_softc *sc, struct
        tx->scratch = 0;        /* clear "scratch" area */
 
        flags = 0;
-       if (!IEEE80211_IS_MULTICAST(wh->i_addr1))
-               flags |= IWN_TX_NEED_ACK;
+       if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+               /* Unicast frame, check if an ACK is expected. */
+               if (!qos || (qos & IEEE80211_QOS_ACKPOLICY) !=
+                   IEEE80211_QOS_ACKPOLICY_NOACK)
+                       flags |= IWN_TX_NEED_ACK;
+       }
        if ((wh->i_fc[0] &
            (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==
            (IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_BAR))
@@ -3056,7 +3075,7 @@ iwn_tx_data(struct iwn_softc *sc, struct
                pad = 0;
 
        tx->len = htole16(totlen);
-       tx->tid = 0;
+       tx->tid = tid;
        tx->rts_ntries = 60;
        tx->data_ntries = 15;
        tx->lifetime = htole32(IWN_LIFETIME_INFINITE);
@@ -3161,8 +3180,7 @@ iwn_tx_data(struct iwn_softc *sc, struct
 
 static int
 iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m,
-    struct ieee80211_node *ni, struct iwn_tx_ring *ring,
-    const struct ieee80211_bpf_params *params)
+    struct ieee80211_node *ni, const struct ieee80211_bpf_params *params)
 {
        const struct iwn_hal *hal = sc->sc_hal;
        const struct iwn_rate *rinfo;
@@ -3172,13 +3190,14 @@ iwn_tx_data_raw(struct iwn_softc *sc, st
        struct iwn_tx_cmd *cmd;
        struct iwn_cmd_data *tx;
        struct ieee80211_frame *wh;
+       struct iwn_tx_ring *ring;
        struct iwn_tx_desc *desc;
        struct iwn_tx_data *data;
        struct mbuf *m1;
        bus_dma_segment_t *seg, segs[IWN_MAX_SCATTER];
        uint32_t flags;
        u_int hdrlen;
-       int totlen, error, pad, nsegs = 0, i, rate;
+       int ac, totlen, error, pad, nsegs = 0, i, rate;
        uint8_t ridx, type, txant;
 
        IWN_LOCK_ASSERT(sc);
@@ -3187,6 +3206,9 @@ iwn_tx_data_raw(struct iwn_softc *sc, st
        hdrlen = ieee80211_anyhdrsize(wh);
        type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
 
+       ac = params->ibp_pri & 3;
+
+       ring = &sc->txq[ac];
        desc = &ring->desc[ring->cur];
        data = &ring->data[ring->cur];
 
@@ -3362,12 +3384,11 @@ iwn_tx_data_raw(struct iwn_softc *sc, st
 
 static int
 iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
-       const struct ieee80211_bpf_params *params)
+    const struct ieee80211_bpf_params *params)
 {
        struct ieee80211com *ic = ni->ni_ic;
        struct ifnet *ifp = ic->ic_ifp;
        struct iwn_softc *sc = ifp->if_softc;
-       struct iwn_tx_ring *txq;
        int error = 0;
 
        if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
@@ -3377,23 +3398,18 @@ iwn_raw_xmit(struct ieee80211_node *ni, 
        }
 
        IWN_LOCK(sc);
-       if (params == NULL)
-               txq = &sc->txq[M_WME_GETAC(m)];
-       else
-               txq = &sc->txq[params->ibp_pri & 3];
-
        if (params == NULL) {
                /*
                 * Legacy path; interpret frame contents to decide
                 * precisely how to send the frame.
                 */
-               error = iwn_tx_data(sc, m, ni, txq);
+               error = iwn_tx_data(sc, m, ni);
        } else {
                /*
                 * Caller supplied explicit parameters to use in
                 * sending the frame.
                 */
-               error = iwn_tx_data_raw(sc, m, ni, txq, params);
+               error = iwn_tx_data_raw(sc, m, ni, params);
        }
        if (error != 0) {
                /* NB: m is reclaimed on tx failure */
@@ -3421,12 +3437,14 @@ iwn_start_locked(struct ifnet *ifp)
 {
        struct iwn_softc *sc = ifp->if_softc;
        struct ieee80211_node *ni;
-       struct iwn_tx_ring *txq;
        struct mbuf *m;
-       int pri;
 
        IWN_LOCK_ASSERT(sc);
 
+       if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
+           (ifp->if_drv_flags & IFF_DRV_OACTIVE))
+               return;
+
        for (;;) {
                if (sc->qfullmsk != 0) {
                        ifp->if_drv_flags |= IFF_DRV_OACTIVE;
@@ -3436,12 +3454,10 @@ iwn_start_locked(struct ifnet *ifp)
                if (m == NULL)
                        break;
                ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
-               pri = M_WME_GETAC(m);
-               txq = &sc->txq[pri];
-               if (iwn_tx_data(sc, m, ni, txq) != 0) {
-                       ifp->if_oerrors++;
+               if (iwn_tx_data(sc, m, ni) != 0) {
                        ieee80211_free_node(ni);
-                       break;
+                       ifp->if_oerrors++;
+                       continue;
                }
                sc->sc_tx_timer = 5;
        }
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to