|
@@ -24,6 +24,10 @@
|
|
|
#include "tkip.h"
|
|
|
#include "wme.h"
|
|
|
|
|
|
+u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
|
|
|
+ struct tid_ampdu_rx *tid_agg_rx,
|
|
|
+ struct sk_buff *skb, u16 mpdu_seq_num,
|
|
|
+ int bar_req);
|
|
|
/*
|
|
|
* monitor mode reception
|
|
|
*
|
|
@@ -64,7 +68,9 @@ static inline int should_drop_frame(struct ieee80211_rx_status *status,
|
|
|
if (((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_FTYPE)) ==
|
|
|
cpu_to_le16(IEEE80211_FTYPE_CTL)) &&
|
|
|
((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE)) !=
|
|
|
- cpu_to_le16(IEEE80211_STYPE_PSPOLL)))
|
|
|
+ cpu_to_le16(IEEE80211_STYPE_PSPOLL)) &&
|
|
|
+ ((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE)) !=
|
|
|
+ cpu_to_le16(IEEE80211_STYPE_BACK_REQ)))
|
|
|
return 1;
|
|
|
return 0;
|
|
|
}
|
|
@@ -634,7 +640,8 @@ ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx)
|
|
|
* BSSID to avoid keeping the current IBSS network alive in cases where
|
|
|
* other STAs are using different BSSID. */
|
|
|
if (rx->sdata->type == IEEE80211_IF_TYPE_IBSS) {
|
|
|
- u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len);
|
|
|
+ u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
|
|
|
+ IEEE80211_IF_TYPE_IBSS);
|
|
|
if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0)
|
|
|
sta->last_rx = jiffies;
|
|
|
} else
|
|
@@ -1376,6 +1383,49 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
|
|
|
return TXRX_QUEUED;
|
|
|
}
|
|
|
|
|
|
+static ieee80211_txrx_result
|
|
|
+ieee80211_rx_h_ctrl(struct ieee80211_txrx_data *rx)
|
|
|
+{
|
|
|
+ struct ieee80211_local *local = rx->local;
|
|
|
+ struct ieee80211_hw *hw = &local->hw;
|
|
|
+ struct sk_buff *skb = rx->skb;
|
|
|
+ struct ieee80211_bar *bar = (struct ieee80211_bar *) skb->data;
|
|
|
+ struct tid_ampdu_rx *tid_agg_rx;
|
|
|
+ u16 start_seq_num;
|
|
|
+ u16 tid;
|
|
|
+
|
|
|
+ if (likely((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL))
|
|
|
+ return TXRX_CONTINUE;
|
|
|
+
|
|
|
+ if ((rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BACK_REQ) {
|
|
|
+ if (!rx->sta)
|
|
|
+ return TXRX_CONTINUE;
|
|
|
+ tid = le16_to_cpu(bar->control) >> 12;
|
|
|
+ tid_agg_rx = &(rx->sta->ampdu_mlme.tid_rx[tid]);
|
|
|
+ if (tid_agg_rx->state != HT_AGG_STATE_OPERATIONAL)
|
|
|
+ return TXRX_CONTINUE;
|
|
|
+
|
|
|
+ start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4;
|
|
|
+
|
|
|
+ /* reset session timer */
|
|
|
+ if (tid_agg_rx->timeout) {
|
|
|
+ unsigned long expires =
|
|
|
+ jiffies + (tid_agg_rx->timeout / 1000) * HZ;
|
|
|
+ mod_timer(&tid_agg_rx->session_timer, expires);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* manage reordering buffer according to requested */
|
|
|
+ /* sequence number */
|
|
|
+ rcu_read_lock();
|
|
|
+ ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL,
|
|
|
+ start_seq_num, 1);
|
|
|
+ rcu_read_unlock();
|
|
|
+ return TXRX_DROP;
|
|
|
+ }
|
|
|
+
|
|
|
+ return TXRX_CONTINUE;
|
|
|
+}
|
|
|
+
|
|
|
static ieee80211_txrx_result
|
|
|
ieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx)
|
|
|
{
|
|
@@ -1527,6 +1577,7 @@ ieee80211_rx_handler ieee80211_rx_handlers[] =
|
|
|
ieee80211_rx_h_remove_qos_control,
|
|
|
ieee80211_rx_h_amsdu,
|
|
|
ieee80211_rx_h_data,
|
|
|
+ ieee80211_rx_h_ctrl,
|
|
|
ieee80211_rx_h_mgmt,
|
|
|
NULL
|
|
|
};
|
|
@@ -1683,8 +1734,6 @@ void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- bssid = ieee80211_get_bssid(hdr, skb->len);
|
|
|
-
|
|
|
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
|
|
if (!netif_running(sdata->dev))
|
|
|
continue;
|
|
@@ -1692,6 +1741,7 @@ void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|
|
if (sdata->type == IEEE80211_IF_TYPE_MNTR)
|
|
|
continue;
|
|
|
|
|
|
+ bssid = ieee80211_get_bssid(hdr, skb->len, sdata->type);
|
|
|
rx.flags |= IEEE80211_TXRXD_RXRA_MATCH;
|
|
|
prepares = prepare_for_handlers(sdata, bssid, &rx, hdr);
|
|
|
/* prepare_for_handlers can change sta */
|
|
@@ -1767,6 +1817,10 @@ static inline u16 seq_sub(u16 sq1, u16 sq2)
|
|
|
}
|
|
|
|
|
|
|
|
|
+/*
|
|
|
+ * As it function blongs to Rx path it must be called with
|
|
|
+ * the proper rcu_read_lock protection for its flow.
|
|
|
+ */
|
|
|
u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
|
|
|
struct tid_ampdu_rx *tid_agg_rx,
|
|
|
struct sk_buff *skb, u16 mpdu_seq_num,
|