Date: Tue, 1 Feb 2011 06:59:44 +0000 (UTC) From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r218154 - head/sys/dev/ath Message-ID: <201102010659.p116xic9061733@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201102010659.p116xic9061733>