Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 16 Apr 2011 13:25:20 +0000 (UTC)
From:      Bernhard Schmidt <bschmidt@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r220720 - head/sys/dev/iwn
Message-ID:  <201104161325.p3GDPKpu006461@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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;
 	}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201104161325.p3GDPKpu006461>