aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAvinash Patil <patila@marvell.com>2012-08-03 21:06:10 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-08-06 15:12:55 -0400
commit5a009adf32d28bacc02da2ddeb69765848266ce1 (patch)
treeed1b97a0f917c0de4e394e46edfb5f01ddf6bf1f /drivers/net
parentd1cf3b958cb6940cb4e0a71697458035dad9e5b9 (diff)
mwifiex: add 11n Block Ack support for uAP
This patch adds support for handling BA request and BA setup events for AP interface. RA list is marked as either 11n enabled or disabled from station's capabilities in association request. BA setup is initiated only after some specific number of packets for particular RA list are transmitted. Signed-off-by: Avinash Patil <patila@marvell.com> Signed-off-by: Kiran Divekar <dkiran@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/mwifiex/11n.h14
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.c15
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.h2
-rw-r--r--drivers/net/wireless/mwifiex/main.h3
-rw-r--r--drivers/net/wireless/mwifiex/uap_event.c21
-rw-r--r--drivers/net/wireless/mwifiex/wmm.c59
6 files changed, 105 insertions, 9 deletions
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h
index 28366e9211fb..6d2edb4c2ad2 100644
--- a/drivers/net/wireless/mwifiex/11n.h
+++ b/drivers/net/wireless/mwifiex/11n.h
@@ -157,4 +157,18 @@ mwifiex_is_ba_stream_setup(struct mwifiex_private *priv,
157 157
158 return false; 158 return false;
159} 159}
160
161/*
162 * This function checks whether associated station is 11n enabled
163 */
164static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv,
165 struct mwifiex_sta_node *node)
166{
167
168 if (!node || (priv->bss_role != MWIFIEX_BSS_ROLE_UAP) ||
169 !priv->ap_11n_enabled)
170 return 0;
171
172 return node->is_11n_enabled;
173}
160#endif /* !_MWIFIEX_11N_H_ */ 174#endif /* !_MWIFIEX_11N_H_ */
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index 20367fe1de44..e43d27dc06bf 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -235,6 +235,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
235 struct mwifiex_rx_reorder_tbl *tbl, *new_node; 235 struct mwifiex_rx_reorder_tbl *tbl, *new_node;
236 u16 last_seq = 0; 236 u16 last_seq = 0;
237 unsigned long flags; 237 unsigned long flags;
238 struct mwifiex_sta_node *node;
238 239
239 /* 240 /*
240 * If we get a TID, ta pair which is already present dispatch all the 241 * If we get a TID, ta pair which is already present dispatch all the
@@ -257,13 +258,19 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
257 new_node->tid = tid; 258 new_node->tid = tid;
258 memcpy(new_node->ta, ta, ETH_ALEN); 259 memcpy(new_node->ta, ta, ETH_ALEN);
259 new_node->start_win = seq_num; 260 new_node->start_win = seq_num;
260 if (mwifiex_queuing_ra_based(priv)) 261
261 /* TODO for adhoc */ 262 if (mwifiex_queuing_ra_based(priv)) {
262 dev_dbg(priv->adapter->dev, 263 dev_dbg(priv->adapter->dev,
263 "info: ADHOC:last_seq=%d start_win=%d\n", 264 "info: AP/ADHOC:last_seq=%d start_win=%d\n",
264 last_seq, new_node->start_win); 265 last_seq, new_node->start_win);
265 else 266 if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
267 node = mwifiex_get_sta_entry(priv, ta);
268 if (node)
269 last_seq = node->rx_seq[tid];
270 }
271 } else {
266 last_seq = priv->rx_seq[tid]; 272 last_seq = priv->rx_seq[tid];
273 }
267 274
268 if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM && 275 if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM &&
269 last_seq >= new_node->start_win) 276 last_seq >= new_node->start_win)
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h
index 1cd51d86fa57..13ecb6101e23 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.h
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h
@@ -38,6 +38,8 @@
38#define ADDBA_RSP_STATUS_ACCEPT 0 38#define ADDBA_RSP_STATUS_ACCEPT 0
39 39
40#define MWIFIEX_DEF_11N_RX_SEQ_NUM 0xffff 40#define MWIFIEX_DEF_11N_RX_SEQ_NUM 0xffff
41#define BA_SETUP_MAX_PACKET_THRESHOLD 16
42#define BA_SETUP_PACKET_OFFSET 16
41 43
42static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv) 44static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv)
43{ 45{
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 014fe9ab221f..c39cd8e50f9f 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -200,6 +200,9 @@ struct mwifiex_ra_list_tbl {
200 u8 ra[ETH_ALEN]; 200 u8 ra[ETH_ALEN];
201 u32 total_pkts_size; 201 u32 total_pkts_size;
202 u32 is_11n_enabled; 202 u32 is_11n_enabled;
203 u16 max_amsdu;
204 u16 pkt_count;
205 u8 ba_packet_thr;
203}; 206};
204 207
205struct mwifiex_tid_tbl { 208struct mwifiex_tid_tbl {
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index 6270c809130a..a10bd95aec12 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -19,6 +19,7 @@
19 19
20#include "decl.h" 20#include "decl.h"
21#include "main.h" 21#include "main.h"
22#include "11n.h"
22 23
23/* 24/*
24 * This function will return the pointer to station entry in station list 25 * This function will return the pointer to station entry in station list
@@ -168,6 +169,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
168 struct mwifiex_assoc_event *event; 169 struct mwifiex_assoc_event *event;
169 struct mwifiex_sta_node *node; 170 struct mwifiex_sta_node *node;
170 u8 *deauth_mac; 171 u8 *deauth_mac;
172 struct host_cmd_ds_11n_batimeout *ba_timeout;
171 173
172 switch (eventcause) { 174 switch (eventcause) {
173 case EVENT_UAP_STA_ASSOC: 175 case EVENT_UAP_STA_ASSOC:
@@ -255,6 +257,25 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
255 adapter->tx_buf_size); 257 adapter->tx_buf_size);
256 } 258 }
257 break; 259 break;
260 case EVENT_ADDBA:
261 dev_dbg(adapter->dev, "event: ADDBA Request\n");
262 if (priv->media_connected)
263 mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_RSP,
264 HostCmd_ACT_GEN_SET, 0,
265 adapter->event_body);
266 break;
267 case EVENT_DELBA:
268 dev_dbg(adapter->dev, "event: DELBA Request\n");
269 if (priv->media_connected)
270 mwifiex_11n_delete_ba_stream(priv, adapter->event_body);
271 break;
272 case EVENT_BA_STREAM_TIEMOUT:
273 dev_dbg(adapter->dev, "event: BA Stream timeout\n");
274 if (priv->media_connected) {
275 ba_timeout = (void *)adapter->event_body;
276 mwifiex_11n_ba_stream_timeout(priv, ba_timeout);
277 }
278 break;
258 default: 279 default:
259 dev_dbg(adapter->dev, "event: unknown event id: %#x\n", 280 dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
260 eventcause); 281 eventcause);
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 3fa4d4176993..8ccd6999fa9f 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -127,6 +127,29 @@ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra)
127 return ra_list; 127 return ra_list;
128} 128}
129 129
130/* This function returns random no between 16 and 32 to be used as threshold
131 * for no of packets after which BA setup is initiated.
132 */
133static u8 mwifiex_get_random_ba_threshold(void)
134{
135 u32 sec, usec;
136 struct timeval ba_tstamp;
137 u8 ba_threshold;
138
139 /* setup ba_packet_threshold here random number between
140 * [BA_SETUP_PACKET_OFFSET,
141 * BA_SETUP_PACKET_OFFSET+BA_SETUP_MAX_PACKET_THRESHOLD-1]
142 */
143
144 do_gettimeofday(&ba_tstamp);
145 sec = (ba_tstamp.tv_sec & 0xFFFF) + (ba_tstamp.tv_sec >> 16);
146 usec = (ba_tstamp.tv_usec & 0xFFFF) + (ba_tstamp.tv_usec >> 16);
147 ba_threshold = (((sec << 16) + usec) % BA_SETUP_MAX_PACKET_THRESHOLD)
148 + BA_SETUP_PACKET_OFFSET;
149
150 return ba_threshold;
151}
152
130/* 153/*
131 * This function allocates and adds a RA list for all TIDs 154 * This function allocates and adds a RA list for all TIDs
132 * with the given RA. 155 * with the given RA.
@@ -137,6 +160,12 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
137 int i; 160 int i;
138 struct mwifiex_ra_list_tbl *ra_list; 161 struct mwifiex_ra_list_tbl *ra_list;
139 struct mwifiex_adapter *adapter = priv->adapter; 162 struct mwifiex_adapter *adapter = priv->adapter;
163 struct mwifiex_sta_node *node;
164 unsigned long flags;
165
166 spin_lock_irqsave(&priv->sta_list_spinlock, flags);
167 node = mwifiex_get_sta_entry(priv, ra);
168 spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
140 169
141 for (i = 0; i < MAX_NUM_TID; ++i) { 170 for (i = 0; i < MAX_NUM_TID; ++i) {
142 ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra); 171 ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra);
@@ -145,14 +174,24 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
145 if (!ra_list) 174 if (!ra_list)
146 break; 175 break;
147 176
148 if (!mwifiex_queuing_ra_based(priv)) 177 ra_list->is_11n_enabled = 0;
178 if (!mwifiex_queuing_ra_based(priv)) {
149 ra_list->is_11n_enabled = IS_11N_ENABLED(priv); 179 ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
150 else 180 } else {
151 ra_list->is_11n_enabled = false; 181 ra_list->is_11n_enabled =
182 mwifiex_is_sta_11n_enabled(priv, node);
183 if (ra_list->is_11n_enabled)
184 ra_list->max_amsdu = node->max_amsdu;
185 }
152 186
153 dev_dbg(adapter->dev, "data: ralist %p: is_11n_enabled=%d\n", 187 dev_dbg(adapter->dev, "data: ralist %p: is_11n_enabled=%d\n",
154 ra_list, ra_list->is_11n_enabled); 188 ra_list, ra_list->is_11n_enabled);
155 189
190 if (ra_list->is_11n_enabled) {
191 ra_list->pkt_count = 0;
192 ra_list->ba_packet_thr =
193 mwifiex_get_random_ba_threshold();
194 }
156 list_add_tail(&ra_list->list, 195 list_add_tail(&ra_list->list,
157 &priv->wmm.tid_tbl_ptr[i].ra_list); 196 &priv->wmm.tid_tbl_ptr[i].ra_list);
158 197
@@ -647,6 +686,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
647 skb_queue_tail(&ra_list->skb_head, skb); 686 skb_queue_tail(&ra_list->skb_head, skb);
648 687
649 ra_list->total_pkts_size += skb->len; 688 ra_list->total_pkts_size += skb->len;
689 ra_list->pkt_count++;
650 690
651 atomic_inc(&priv->wmm.tx_pkts_queued); 691 atomic_inc(&priv->wmm.tx_pkts_queued);
652 692
@@ -986,10 +1026,17 @@ mwifiex_is_11n_aggragation_possible(struct mwifiex_private *priv,
986{ 1026{
987 int count = 0, total_size = 0; 1027 int count = 0, total_size = 0;
988 struct sk_buff *skb, *tmp; 1028 struct sk_buff *skb, *tmp;
1029 int max_amsdu_size;
1030
1031 if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP && priv->ap_11n_enabled &&
1032 ptr->is_11n_enabled)
1033 max_amsdu_size = min_t(int, ptr->max_amsdu, max_buf_size);
1034 else
1035 max_amsdu_size = max_buf_size;
989 1036
990 skb_queue_walk_safe(&ptr->skb_head, skb, tmp) { 1037 skb_queue_walk_safe(&ptr->skb_head, skb, tmp) {
991 total_size += skb->len; 1038 total_size += skb->len;
992 if (total_size >= max_buf_size) 1039 if (total_size >= max_amsdu_size)
993 break; 1040 break;
994 if (++count >= MIN_NUM_AMSDU) 1041 if (++count >= MIN_NUM_AMSDU)
995 return true; 1042 return true;
@@ -1050,6 +1097,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
1050 skb_queue_tail(&ptr->skb_head, skb); 1097 skb_queue_tail(&ptr->skb_head, skb);
1051 1098
1052 ptr->total_pkts_size += skb->len; 1099 ptr->total_pkts_size += skb->len;
1100 ptr->pkt_count++;
1053 tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; 1101 tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
1054 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 1102 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
1055 ra_list_flags); 1103 ra_list_flags);
@@ -1231,7 +1279,8 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
1231 /* ra_list_spinlock has been freed in 1279 /* ra_list_spinlock has been freed in
1232 mwifiex_send_single_packet() */ 1280 mwifiex_send_single_packet() */
1233 } else { 1281 } else {
1234 if (mwifiex_is_ampdu_allowed(priv, tid)) { 1282 if (mwifiex_is_ampdu_allowed(priv, tid) &&
1283 ptr->pkt_count > ptr->ba_packet_thr) {
1235 if (mwifiex_space_avail_for_new_ba_stream(adapter)) { 1284 if (mwifiex_space_avail_for_new_ba_stream(adapter)) {
1236 mwifiex_create_ba_tbl(priv, ptr->ra, tid, 1285 mwifiex_create_ba_tbl(priv, ptr->ra, tid,
1237 BA_SETUP_INPROGRESS); 1286 BA_SETUP_INPROGRESS);