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
This commit is contained in:
Bernhard Schmidt 2011-04-16 13:25:19 +00:00
parent baa8b4ad20
commit 4e61a8e57c

View File

@ -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;
}