summaryrefslogtreecommitdiffstats
path: root/sys/dev/iwn
diff options
context:
space:
mode:
authorbschmidt <bschmidt@FreeBSD.org>2011-05-08 11:58:23 +0000
committerbschmidt <bschmidt@FreeBSD.org>2011-05-08 11:58:23 +0000
commit0d4f0158245d1dec8c02b0b7e64af9a9e856e85a (patch)
treef2753d0c35560e77873cf013387494a451441831 /sys/dev/iwn
parentd5baa66cc184aed9fe2f0dab0131dd0a2ce2ec49 (diff)
downloadFreeBSD-src-0d4f0158245d1dec8c02b0b7e64af9a9e856e85a.zip
FreeBSD-src-0d4f0158245d1dec8c02b0b7e64af9a9e856e85a.tar.gz
Add support for RX packet aggregation.
Diffstat (limited to 'sys/dev/iwn')
-rw-r--r--sys/dev/iwn/if_iwn.c57
-rw-r--r--sys/dev/iwn/if_iwnvar.h5
2 files changed, 45 insertions, 17 deletions
diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c
index 8faba34..49a05f4 100644
--- a/sys/dev/iwn/if_iwn.c
+++ b/sys/dev/iwn/if_iwn.c
@@ -251,11 +251,11 @@ static uint8_t *ieee80211_add_ssid(uint8_t *, const uint8_t *, u_int);
static int iwn_scan(struct iwn_softc *);
static int iwn_auth(struct iwn_softc *, struct ieee80211vap *vap);
static int iwn_run(struct iwn_softc *, struct ieee80211vap *vap);
+static int iwn_ampdu_rx_start(struct ieee80211_node *,
+ struct ieee80211_rx_ampdu *, int, int, int);
+static void iwn_ampdu_rx_stop(struct ieee80211_node *,
+ struct ieee80211_rx_ampdu *);
#if 0 /* HT */
-static int iwn_ampdu_rx_start(struct ieee80211com *,
- struct ieee80211_node *, uint8_t);
-static void iwn_ampdu_rx_stop(struct ieee80211com *,
- struct ieee80211_node *, uint8_t);
static int iwn_ampdu_tx_start(struct ieee80211com *,
struct ieee80211_node *, uint8_t);
static void iwn_ampdu_tx_stop(struct ieee80211com *,
@@ -653,9 +653,11 @@ iwn_attach(device_t dev)
ic->ic_vap_delete = iwn_vap_delete;
ic->ic_raw_xmit = iwn_raw_xmit;
ic->ic_node_alloc = iwn_node_alloc;
-#if 0 /* HT */
+ sc->sc_ampdu_rx_start = ic->ic_ampdu_rx_start;
ic->ic_ampdu_rx_start = iwn_ampdu_rx_start;
+ sc->sc_ampdu_rx_stop = ic->ic_ampdu_rx_stop;
ic->ic_ampdu_rx_stop = iwn_ampdu_rx_stop;
+#if 0 /* HT */
ic->ic_ampdu_tx_start = iwn_ampdu_tx_start;
ic->ic_ampdu_tx_stop = iwn_ampdu_tx_stop;
#endif
@@ -2434,6 +2436,8 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
/* Send the frame to the 802.11 layer. */
if (ni != NULL) {
+ if (ni->ni_flags & IEEE80211_NODE_HT)
+ m->m_flags |= M_AMPDU;
(void)ieee80211_input(ni, m, rssi - nf, nf);
/* Node is no longer needed. */
ieee80211_free_node(ni);
@@ -3765,7 +3769,8 @@ iwn_cmd(struct iwn_softc *sc, int code, const void *buf, int size, int async)
bus_addr_t paddr;
int totlen, error;
- IWN_LOCK_ASSERT(sc);
+ if (async == 0)
+ IWN_LOCK_ASSERT(sc);
desc = &ring->desc[ring->cur];
data = &ring->data[ring->cur];
@@ -5321,30 +5326,39 @@ iwn_run(struct iwn_softc *sc, struct ieee80211vap *vap)
#undef MS
}
-#if 0 /* HT */
/*
* This function is called by upper layer when an ADDBA request is received
* from another STA and before the ADDBA response is sent.
*/
static int
-iwn_ampdu_rx_start(struct ieee80211com *ic, struct ieee80211_node *ni,
- uint8_t tid)
+iwn_ampdu_rx_start(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap,
+ int baparamset, int batimeout, int baseqctl)
{
- struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];
- struct iwn_softc *sc = ic->ic_softc;
+#define MS(_v, _f) (((_v) & _f) >> _f##_S)
+ struct iwn_softc *sc = ni->ni_ic->ic_ifp->if_softc;
struct iwn_ops *ops = &sc->ops;
struct iwn_node *wn = (void *)ni;
struct iwn_node_info node;
+ uint16_t ssn;
+ uint8_t tid;
+ int error;
+
+ tid = MS(le16toh(baparamset), IEEE80211_BAPS_TID);
+ ssn = MS(le16toh(baseqctl), IEEE80211_BASEQ_START);
memset(&node, 0, sizeof node);
node.id = wn->id;
node.control = IWN_NODE_UPDATE;
node.flags = IWN_FLAG_SET_ADDBA;
node.addba_tid = tid;
- node.addba_ssn = htole16(ba->ba_winstart);
+ node.addba_ssn = htole16(ssn);
DPRINTF(sc, IWN_DEBUG_RECV, "ADDBA RA=%d TID=%d SSN=%d\n",
- wn->id, tid, ba->ba_winstart);
- return ops->add_node(sc, &node, 1);
+ wn->id, tid, ssn);
+ error = ops->add_node(sc, &node, 1);
+ if (error != 0)
+ return error;
+ return sc->sc_ampdu_rx_start(ni, rap, baparamset, batimeout, baseqctl);
+#undef MS
}
/*
@@ -5352,13 +5366,20 @@ iwn_ampdu_rx_start(struct ieee80211com *ic, struct ieee80211_node *ni,
* Block Ack agreement (eg. uppon receipt of a DELBA frame).
*/
static void
-iwn_ampdu_rx_stop(struct ieee80211com *ic, struct ieee80211_node *ni,
- uint8_t tid)
+iwn_ampdu_rx_stop(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap)
{
- struct iwn_softc *sc = ic->ic_softc;
+ struct ieee80211com *ic = ni->ni_ic;
+ struct iwn_softc *sc = ic->ic_ifp->if_softc;
struct iwn_ops *ops = &sc->ops;
struct iwn_node *wn = (void *)ni;
struct iwn_node_info node;
+ uint8_t tid;
+
+ /* XXX: tid as an argument */
+ for (tid = 0; tid < WME_NUM_TID; tid++) {
+ if (&ni->ni_rx_ampdu[tid] == rap)
+ break;
+ }
memset(&node, 0, sizeof node);
node.id = wn->id;
@@ -5367,8 +5388,10 @@ iwn_ampdu_rx_stop(struct ieee80211com *ic, struct ieee80211_node *ni,
node.delba_tid = tid;
DPRINTF(sc, IWN_DEBUG_RECV, "DELBA RA=%d TID=%d\n", wn->id, tid);
(void)ops->add_node(sc, &node, 1);
+ sc->sc_ampdu_rx_stop(ni, rap);
}
+#if 0 /* HT */
/*
* This function is called by upper layer when an ADDBA response is received
* from another STA.
diff --git a/sys/dev/iwn/if_iwnvar.h b/sys/dev/iwn/if_iwnvar.h
index 9bf4a3c..ed1947e 100644
--- a/sys/dev/iwn/if_iwnvar.h
+++ b/sys/dev/iwn/if_iwnvar.h
@@ -306,6 +306,11 @@ struct iwn_softc {
int sc_tx_timer;
+ int (*sc_ampdu_rx_start)(struct ieee80211_node *,
+ struct ieee80211_rx_ampdu *, int, int, int);
+ void (*sc_ampdu_rx_stop)(struct ieee80211_node *,
+ struct ieee80211_rx_ampdu *);
+
struct iwn_rx_radiotap_header sc_rxtap;
struct iwn_tx_radiotap_header sc_txtap;
};
OpenPOWER on IntegriCloud