Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=713647169e3aaca16be4cfba42513bd4558abec0
Commit:     713647169e3aaca16be4cfba42513bd4558abec0
Parent:     b580781e038968fb2529460e8b61e3bf77de112a
Author:     Ron Rindjunsky <[EMAIL PROTECTED]>
AuthorDate: Tue Dec 25 17:00:36 2007 +0200
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Mon Jan 28 15:01:01 2008 -0800

    mac80211: A-MPDU Rx adding BAR handling capability
    
    This patch adds the ability to handle Block Ack Request
    
    Signed-off-by: Ron Rindjunsky <[EMAIL PROTECTED]>
    Signed-off-by: John W. Linville <[EMAIL PROTECTED]>
    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
---
 net/mac80211/ieee80211_i.h |    3 +-
 net/mac80211/rx.c          |   62 +++++++++++++++++++++++++++++++++++++++++---
 net/mac80211/util.c        |   15 ++++++++++-
 3 files changed, 74 insertions(+), 6 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 740d69d..662e69e 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -801,7 +801,8 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, struct 
net_device *dev);
 extern void *mac80211_wiphy_privid; /* for wiphy privid */
 extern const unsigned char rfc1042_header[6];
 extern const unsigned char bridge_tunnel_header[6];
-u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len);
+u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
+                       enum ieee80211_if_types type);
 int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
                             int rate, int erp, int short_preamble);
 void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index e7b1eb8..ed3b816 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -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
@@ -1377,6 +1384,49 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
 }
 
 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)
 {
        struct ieee80211_sub_if_data *sdata;
@@ -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,
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 2b02b2b..adb85dd 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -127,7 +127,8 @@ void ieee80211_prepare_rates(struct ieee80211_local *local,
        }
 }
 
-u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len)
+u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
+                       enum ieee80211_if_types type)
 {
        u16 fc;
 
@@ -159,6 +160,18 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t 
len)
        case IEEE80211_FTYPE_CTL:
                if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)
                        return hdr->addr1;
+               else if ((fc & IEEE80211_FCTL_STYPE) ==
+                                               IEEE80211_STYPE_BACK_REQ) {
+                       switch (type) {
+                       case IEEE80211_IF_TYPE_STA:
+                               return hdr->addr2;
+                       case IEEE80211_IF_TYPE_AP:
+                       case IEEE80211_IF_TYPE_VLAN:
+                               return hdr->addr1;
+                       default:
+                               return NULL;
+                       }
+               }
                else
                        return NULL;
        }
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to