summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2011-02-01 06:59:44 +0000
committeradrian <adrian@FreeBSD.org>2011-02-01 06:59:44 +0000
commitac497e209c8794f8cbb775e30c15c2f91c668de3 (patch)
tree02db709b2741d9791570184a188c90301f31d125
parent1138f32d735e977490bce549a2c19c22bf9bf301 (diff)
downloadFreeBSD-src-ac497e209c8794f8cbb775e30c15c2f91c668de3.zip
FreeBSD-src-ac497e209c8794f8cbb775e30c15c2f91c668de3.tar.gz
* 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.
-rw-r--r--sys/dev/ath/if_ath_tx.c180
1 files changed, 86 insertions, 94 deletions
diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c
index 5568f43..054ec75 100644
--- a/sys/dev/ath/if_ath_tx.c
+++ b/sys/dev/ath/if_ath_tx.c
@@ -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, struct ath_buf *bf, struct mbuf *m0)
}
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, struct ath_txq *txq, struct ath_buf *bf)
__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, struct ath_txq *txq, struct ath_buf *bf)
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, struct ieee80211_node *ni, struct ath_buf *bf
*/
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, struct ieee80211_node *ni,
/* 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)
OpenPOWER on IntegriCloud