svn commit: r218154 - head/sys/dev/ath

Adrian Chadd adrian at FreeBSD.org
Tue Feb 1 06:59:44 UTC 2011


Author: adrian
Date: Tue Feb  1 06:59:44 2011
New Revision: 218154
URL: http://svn.freebsd.org/changeset/base/218154

Log:
  * Add a rather hacky "does this speak the 11n TX descriptor format"
    function; which will be later used by the TX path to determine
    whether to use the extended features or not.
  
  * Break out the descriptor chaining logic into a separate function;
    again so it can be switched out later on for the 11n version when
    needed.
  
  * Refactor out the encryption-swizzling code that's common in the
    raw and normal TX path.

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

Modified: head/sys/dev/ath/if_ath_tx.c
==============================================================================
--- head/sys/dev/ath/if_ath_tx.c	Tue Feb  1 06:42:46 2011	(r218153)
+++ head/sys/dev/ath/if_ath_tx.c	Tue Feb  1 06:59:44 2011	(r218154)
@@ -98,6 +98,15 @@ __FBSDID("$FreeBSD$");
 #include <dev/ath/if_ath_misc.h>
 #include <dev/ath/if_ath_tx.h>
 
+/*
+ * Whether to use the 11n rate scenario functions or not
+ */
+static inline int
+ath_tx_is_11n(struct ath_softc *sc)
+{
+	return (sc->sc_ah->ah_magic == 0x20065416);
+}
+
 void
 ath_txfrag_cleanup(struct ath_softc *sc,
 	ath_bufhead *frags, struct ieee80211_node *ni)
@@ -216,7 +225,7 @@ ath_tx_dmasetup(struct ath_softc *sc, st
 }
 
 static void
-ath_tx_handoff(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf)
+ath_tx_chaindesclist(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf)
 {
 	struct ath_hal *ah = sc->sc_ah;
 	struct ath_desc *ds, *ds0;
@@ -243,6 +252,17 @@ ath_tx_handoff(struct ath_softc *sc, str
 			__func__, i, ds->ds_link, ds->ds_data,
 			ds->ds_ctl0, ds->ds_ctl1, ds->ds_hw[0], ds->ds_hw[1]);
 	}
+
+}
+
+static void
+ath_tx_handoff(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf)
+{
+	struct ath_hal *ah = sc->sc_ah;
+
+	/* Fill in the details in the descriptor list */
+	ath_tx_chaindesclist(sc, txq, bf);
+
 	/*
 	 * Insert the frame on the outbound list and pass it on
 	 * to the hardware.  Multicast frames buffered for power
@@ -348,6 +368,57 @@ ath_tx_handoff(struct ath_softc *sc, str
 	ATH_TXQ_UNLOCK(txq);
 }
 
+static int
+ath_tx_tag_crypto(struct ath_softc *sc, struct ieee80211_node *ni,
+    struct mbuf *m0, int iswep, int isfrag, int *hdrlen, int *pktlen, int *keyix)
+{
+	if (iswep) {
+		const struct ieee80211_cipher *cip;
+		struct ieee80211_key *k;
+
+		/*
+		 * Construct the 802.11 header+trailer for an encrypted
+		 * frame. The only reason this can fail is because of an
+		 * unknown or unsupported cipher/key type.
+		 */
+		k = ieee80211_crypto_encap(ni, m0);
+		if (k == NULL) {
+			/*
+			 * This can happen when the key is yanked after the
+			 * frame was queued.  Just discard the frame; the
+			 * 802.11 layer counts failures and provides
+			 * debugging/diagnostics.
+			 */
+			return 0;
+		}
+		/*
+		 * Adjust the packet + header lengths for the crypto
+		 * additions and calculate the h/w key index.  When
+		 * a s/w mic is done the frame will have had any mic
+		 * added to it prior to entry so m0->m_pkthdr.len will
+		 * account for it. Otherwise we need to add it to the
+		 * packet length.
+		 */
+		cip = k->wk_cipher;
+		(*hdrlen) += cip->ic_header;
+		(*pktlen) += cip->ic_header + cip->ic_trailer;
+		/* NB: frags always have any TKIP MIC done in s/w */
+		if ((k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && !isfrag)
+			(*pktlen) += cip->ic_miclen;
+		(*keyix) = k->wk_keyix;
+	} else if (ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) {
+		/*
+		 * Use station key cache slot, if assigned.
+		 */
+		(*keyix) = ni->ni_ucastkey.wk_keyix;
+		if ((*keyix) == IEEE80211_KEYIX_NONE)
+			(*keyix) = HAL_TXKEYIX_INVALID;
+	} else
+		(*keyix) = HAL_TXKEYIX_INVALID;
+
+	return 1;
+}
+
 int
 ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf,
     struct mbuf *m0)
@@ -383,53 +454,14 @@ ath_tx_start(struct ath_softc *sc, struc
 	 */
 	pktlen = m0->m_pkthdr.len - (hdrlen & 3);
 
-	if (iswep) {
-		const struct ieee80211_cipher *cip;
-		struct ieee80211_key *k;
-
-		/*
-		 * Construct the 802.11 header+trailer for an encrypted
-		 * frame. The only reason this can fail is because of an
-		 * unknown or unsupported cipher/key type.
-		 */
-		k = ieee80211_crypto_encap(ni, m0);
-		if (k == NULL) {
-			/*
-			 * This can happen when the key is yanked after the
-			 * frame was queued.  Just discard the frame; the
-			 * 802.11 layer counts failures and provides
-			 * debugging/diagnostics.
-			 */
-			ath_freetx(m0);
-			return EIO;
-		}
-		/*
-		 * Adjust the packet + header lengths for the crypto
-		 * additions and calculate the h/w key index.  When
-		 * a s/w mic is done the frame will have had any mic
-		 * added to it prior to entry so m0->m_pkthdr.len will
-		 * account for it. Otherwise we need to add it to the
-		 * packet length.
-		 */
-		cip = k->wk_cipher;
-		hdrlen += cip->ic_header;
-		pktlen += cip->ic_header + cip->ic_trailer;
-		/* NB: frags always have any TKIP MIC done in s/w */
-		if ((k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && !isfrag)
-			pktlen += cip->ic_miclen;
-		keyix = k->wk_keyix;
+	/* Handle encryption twiddling if needed */
+	if (! ath_tx_tag_crypto(sc, ni, m0, iswep, isfrag, &hdrlen, &pktlen, &keyix)) {
+		ath_freetx(m0);
+		return EIO;
+	}
 
-		/* packet header may have moved, reset our local pointer */
-		wh = mtod(m0, struct ieee80211_frame *);
-	} else if (ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) {
-		/*
-		 * Use station key cache slot, if assigned.
-		 */
-		keyix = ni->ni_ucastkey.wk_keyix;
-		if (keyix == IEEE80211_KEYIX_NONE)
-			keyix = HAL_TXKEYIX_INVALID;
-	} else
-		keyix = HAL_TXKEYIX_INVALID;
+	/* packet header may have moved, reset our local pointer */
+	wh = mtod(m0, struct ieee80211_frame *);
 
 	pktlen += IEEE80211_CRC_LEN;
 
@@ -787,53 +819,13 @@ ath_tx_raw_start(struct ath_softc *sc, s
 	/* XXX honor IEEE80211_BPF_DATAPAD */
 	pktlen = m0->m_pkthdr.len - (hdrlen & 3) + IEEE80211_CRC_LEN;
 
-	if (params->ibp_flags & IEEE80211_BPF_CRYPTO) {
-		const struct ieee80211_cipher *cip;
-		struct ieee80211_key *k;
-
-		/*
-		 * Construct the 802.11 header+trailer for an encrypted
-		 * frame. The only reason this can fail is because of an
-		 * unknown or unsupported cipher/key type.
-		 */
-		k = ieee80211_crypto_encap(ni, m0);
-		if (k == NULL) {
-			/*
-			 * This can happen when the key is yanked after the
-			 * frame was queued.  Just discard the frame; the
-			 * 802.11 layer counts failures and provides
-			 * debugging/diagnostics.
-			 */
-			ath_freetx(m0);
-			return EIO;
-		}
-		/*
-		 * Adjust the packet + header lengths for the crypto
-		 * additions and calculate the h/w key index.  When
-		 * a s/w mic is done the frame will have had any mic
-		 * added to it prior to entry so m0->m_pkthdr.len will
-		 * account for it. Otherwise we need to add it to the
-		 * packet length.
-		 */
-		cip = k->wk_cipher;
-		hdrlen += cip->ic_header;
-		pktlen += cip->ic_header + cip->ic_trailer;
-		/* NB: frags always have any TKIP MIC done in s/w */
-		if ((k->wk_flags & IEEE80211_KEY_SWMIC) == 0)
-			pktlen += cip->ic_miclen;
-		keyix = k->wk_keyix;
-
-		/* packet header may have moved, reset our local pointer */
-		wh = mtod(m0, struct ieee80211_frame *);
-	} else if (ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) {
-		/*
-		 * Use station key cache slot, if assigned.
-		 */
-		keyix = ni->ni_ucastkey.wk_keyix;
-		if (keyix == IEEE80211_KEYIX_NONE)
-			keyix = HAL_TXKEYIX_INVALID;
-	} else
-		keyix = HAL_TXKEYIX_INVALID;
+	/* Handle encryption twiddling if needed */
+	if (! ath_tx_tag_crypto(sc, ni, m0, params->ibp_flags & IEEE80211_BPF_CRYPTO, 0, &hdrlen, &pktlen, &keyix)) {
+		ath_freetx(m0);
+		return EIO;
+	}
+	/* packet header may have moved, reset our local pointer */
+	wh = mtod(m0, struct ieee80211_frame *);
 
 	error = ath_tx_dmasetup(sc, bf, m0);
 	if (error != 0)


More information about the svn-src-head mailing list