summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbschmidt <bschmidt@FreeBSD.org>2011-04-16 13:25:19 +0000
committerbschmidt <bschmidt@FreeBSD.org>2011-04-16 13:25:19 +0000
commit20e8c16a03a1c56d0cfee5075e79e3f650527dd0 (patch)
tree238437f240b653718834f4113066f44af54cf1bc
parent52a6150689609acdfd882f6db838052f033d3d4b (diff)
downloadFreeBSD-src-20e8c16a03a1c56d0cfee5075e79e3f650527dd0.zip
FreeBSD-src-20e8c16a03a1c56d0cfee5075e79e3f650527dd0.tar.gz
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
-rw-r--r--sys/dev/iwn/if_iwn.c70
1 files changed, 43 insertions, 27 deletions
diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c
index c4b0888..d1b4dc1 100644
--- a/sys/dev/iwn/if_iwn.c
+++ b/sys/dev/iwn/if_iwn.c
@@ -158,7 +158,10 @@ static void iwn5000_reset_sched(struct iwn_softc *, int, int);
#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 mbuf *m, struct ieee80211_node *ni,
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 mbuf *m, struct ieee80211_node *ni,
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 mbuf *m, struct ieee80211_node *ni,
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 mbuf *m, struct ieee80211_node *ni,
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 mbuf *m, struct ieee80211_node *ni,
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 mbuf *m, struct ieee80211_node *ni,
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, struct mbuf *m,
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, struct mbuf *m,
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, struct mbuf *m,
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, struct mbuf *m,
}
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;
}
OpenPOWER on IntegriCloud