1 /*
2 * Copyright (c) 2015 South Silicon Valley Microelectronics Inc.
3 * Copyright (c) 2015 iComm Corporation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 #include <linux/version.h>
18 #include <ssv6200.h>
19 #include "dev.h"
20 #include "ap.h"
21 #include "sec.h"
22 #include "ssv_rc_common.h"
23 #include "ssv_ht_rc.h"
24 extern struct ieee80211_ops ssv6200_ops;
25 #define BA_WAIT_TIMEOUT (800)
26 #define AMPDU_BA_FRAME_LEN (68)
27 #define ampdu_skb_hdr(skb) ((struct ieee80211_hdr*)((u8*)((skb)->data)+AMPDU_DELIMITER_LEN))
28 #define ampdu_skb_ssn(skb) ((ampdu_skb_hdr(skb)->seq_ctrl)>>SSV_SEQ_NUM_SHIFT)
29 #define ampdu_hdr_ssn(hdr) ((hdr)->seq_ctrl>>SSV_SEQ_NUM_SHIFT)
30 #if 0
31 #define prn_aggr_dbg(fmt,...) \
32 do { \
33 printk(KERN_DEBUG fmt, ##__VA_ARGS__); \
34 } while (0)
35 #else
36 #undef prn_aggr_dbg
37 #define prn_aggr_dbg(fmt,...)
38 #endif
39 #if 0
40 #define prn_aggr_err(fmt,...) \
41 do { \
42 printk(KERN_ERR fmt, ##__VA_ARGS__);\
43 } while (0)
44 #else
void_func(const char * fmt,...)45 static void void_func(const char *fmt, ...)
46 {
47 }
48 #define prn_aggr_err(fmt,...) \
49 do { \
50 void_func(KERN_ERR fmt, ##__VA_ARGS__);\
51 } while (0)
52 #endif
53 #define get_tid_aggr_len(agg_len,tid_data) \
54 ({ \
55 u32 agg_max_num = (tid_data)->agg_num_max; \
56 u32 to_agg_len = (agg_len); \
57 (agg_len >= agg_max_num) ? agg_max_num : to_agg_len; \
58 })
59 #define INDEX_PKT_BY_SSN(tid,ssn) \
60 ((tid)->aggr_pkts[(ssn) % SSV_AMPDU_BA_WINDOW_SIZE])
61 #define NEXT_PKT_SN(sn) \
62 ({ (sn + 1) % SSV_AMPDU_MAX_SSN; })
63 #define INC_PKT_SN(sn) \
64 ({ \
65 sn = NEXT_PKT_SN(sn); \
66 sn; \
67 })
68 #ifdef CONFIG_SSV6XXX_DEBUGFS
69 static ssize_t ampdu_tx_mib_dump(struct ssv_sta_priv_data *ssv_sta_priv,
70 char *mib_str, ssize_t length);
71 static int _dump_ba_skb(char *buf, int buf_size, struct sk_buff *ba_skb);
72 #endif
73 static struct sk_buff* _aggr_retry_mpdu (struct ssv_softc *sc,
74 struct AMPDU_TID_st *cur_AMPDU_TID,
75 struct sk_buff_head *retry_queue,
76 u32 max_aggr_len);
77 static int _dump_BA_notification (char *buf,
78 struct ampdu_ba_notify_data *ba_notification);
79 static struct sk_buff *_alloc_ampdu_skb (struct ssv_softc *sc,
80 struct AMPDU_TID_st *ampdu_tid,
81 u32 len);
82 static bool _sync_ampdu_pkt_arr (struct AMPDU_TID_st *ampdu_tid,
83 struct sk_buff *ampdu_skb, bool retry);
84 static void _put_mpdu_to_ampdu (struct sk_buff *ampdu,
85 struct sk_buff *mpdu);
86 static void _add_ampdu_txinfo (struct ssv_softc *sc, struct sk_buff *ampdu_skb);
87 static u32 _flush_early_ampdu_q (struct ssv_softc *sc,
88 struct AMPDU_TID_st *ampdu_tid);
89 static bool _is_skb_q_empty (struct ssv_softc *sc, struct sk_buff *skb);
90 static void _aggr_ampdu_tx_q (struct ieee80211_hw *hw,
91 struct AMPDU_TID_st *ampdu_tid);
92 static void _queue_early_ampdu (struct ssv_softc *sc,
93 struct AMPDU_TID_st *ampdu_tid,
94 struct sk_buff *ampdu_skb);
95 static int _mark_skb_retry (struct SKB_info_st *skb_info, struct sk_buff *skb);
96 #ifdef CONFIG_DEBUG_SKB_TIMESTAMP
cal_duration_of_ampdu(struct sk_buff * ampdu_skb,int stage)97 unsigned int cal_duration_of_ampdu(struct sk_buff *ampdu_skb, int stage)
98 {
99 unsigned int timeout;
100 SKB_info *mpdu_skb_info;
101 u16 ssn = 0;
102 struct sk_buff *mpdu = NULL;
103 struct ampdu_hdr_st *ampdu_hdr = NULL;
104 ktime_t current_ktime;
105 ampdu_hdr = (struct ampdu_hdr_st *) ampdu_skb->head;
106 ssn = ampdu_hdr->ssn[0];
107 mpdu = INDEX_PKT_BY_SSN(ampdu_hdr->ampdu_tid, ssn);
108 if (mpdu == NULL)
109 return 0;
110 mpdu_skb_info = (SKB_info *) (mpdu->head);
111 current_ktime = ktime_get();
112 timeout = (unsigned int)ktime_to_ms(ktime_sub(current_ktime, mpdu_skb_info->timestamp));
113 if (timeout > SKB_DURATION_TIMEOUT_MS) {
114 if (stage == SKB_DURATION_STAGE_TO_SDIO)
115 printk("*a_to_sdio: %ums\n", timeout);
116 else if (stage == SKB_DURATION_STAGE_TX_ENQ)
117 printk("*a_to_txenqueue: %ums\n", timeout);
118 else
119 printk("*a_in_hwq: %ums\n", timeout);
120 }
121 return timeout;
122 }
123 #endif
_cal_ampdu_delm_half_crc(u8 value)124 static u8 _cal_ampdu_delm_half_crc (u8 value)
125 {
126 u32 c32 = value, v32 = value;
127 c32 ^= (v32 >> 1) | (v32 << 7);
128 c32 ^= (v32 >> 2);
129 if (v32 & 2)
130 c32 ^= (0xC0);
131 c32 ^= ((v32 << 4) & 0x30);
132 return (u8) c32;
133 }
_cal_ampdu_delm_crc(u8 * pointer)134 static u8 _cal_ampdu_delm_crc (u8 *pointer)
135 {
136 u8 crc = 0xCF;
137 crc ^= _cal_ampdu_delm_half_crc(*pointer++);
138 crc = _cal_ampdu_delm_half_crc(crc) ^ _cal_ampdu_delm_half_crc(*pointer);
139 return ~crc;
140 }
ssv6200_ampdu_add_delimiter_and_crc32(struct sk_buff * mpdu)141 static bool ssv6200_ampdu_add_delimiter_and_crc32 (struct sk_buff *mpdu)
142 {
143 p_AMPDU_DELIMITER delimiter_p;
144 struct ieee80211_hdr *mpdu_hdr;
145 int ret;
146 u32 orig_mpdu_len = mpdu->len;
147 u32 pad = (4 - (orig_mpdu_len % 4)) % 4;
148 mpdu_hdr = (struct ieee80211_hdr*) (mpdu->data);
149 mpdu_hdr->duration_id = AMPDU_TX_NAV_MCS_567;
150 ret = skb_padto(mpdu, mpdu->len + (AMPDU_FCS_LEN + pad));
151 if (ret)
152 {
153 printk(KERN_ERR "Failed to extand skb for aggregation.");
154 return false;
155 }
156 skb_put(mpdu, AMPDU_FCS_LEN + pad);
157 skb_push(mpdu, AMPDU_DELIMITER_LEN);
158 delimiter_p = (p_AMPDU_DELIMITER) mpdu->data;
159 delimiter_p->reserved = 0;
160 delimiter_p->length = orig_mpdu_len + AMPDU_FCS_LEN;
161 delimiter_p->signature = AMPDU_SIGNATURE;
162 delimiter_p->crc = _cal_ampdu_delm_crc((u8*) (delimiter_p));
163 return true;
164 }
ssv6200_ampdu_hw_init(struct ieee80211_hw * hw)165 static void ssv6200_ampdu_hw_init (struct ieee80211_hw *hw)
166 {
167 struct ssv_softc *sc = hw->priv;
168 u32 temp32;
169 SMAC_REG_READ(sc->sh, ADR_MTX_MISC_EN, &temp32);
170 temp32 |= (0x1 << MTX_AMPDU_CRC_AUTO_SFT);
171 SMAC_REG_WRITE(sc->sh, ADR_MTX_MISC_EN, temp32);
172 SMAC_REG_READ(sc->sh, ADR_MTX_MISC_EN, &temp32);
173 }
_sync_ampdu_pkt_arr(struct AMPDU_TID_st * ampdu_tid,struct sk_buff * ampdu,bool retry)174 bool _sync_ampdu_pkt_arr (struct AMPDU_TID_st *ampdu_tid, struct sk_buff *ampdu,
175 bool retry)
176 {
177 struct sk_buff **pp_aggr_pkt;
178 struct sk_buff *p_aggr_pkt;
179 unsigned long flags;
180 struct ampdu_hdr_st *ampdu_hdr = (struct ampdu_hdr_st *) ampdu->head;
181 struct sk_buff *mpdu;
182 u32 first_ssn = SSV_ILLEGAL_SN;
183 u32 old_aggr_pkt_num;
184 u32 old_baw_head;
185 u32 sync_num = skb_queue_len(&du_hdr->mpdu_q);
186 bool ret = true;
187 spin_lock_irqsave(&du_tid->pkt_array_lock, flags);
188 old_baw_head = ampdu_tid->ssv_baw_head;
189 old_aggr_pkt_num = ampdu_tid->aggr_pkt_num;
190 ampdu_tid->mib.ampdu_mib_ampdu_counter += 1;
191 ampdu_tid->mib.ampdu_mib_dist[sync_num] += 1;
192 do
193 {
194 if (!retry)
195 {
196 ampdu_tid->mib.ampdu_mib_mpdu_counter += sync_num;
197 mpdu = skb_peek_tail(&du_hdr->mpdu_q);
198 if (mpdu == NULL)
199 {
200 ret = false;
201 break;
202 }
203 else
204 {
205 u32 ssn = ampdu_skb_ssn(mpdu);
206 p_aggr_pkt = INDEX_PKT_BY_SSN(ampdu_tid, ssn);
207 if (p_aggr_pkt != NULL)
208 {
209 char msg[256];
210 u32 sn = ampdu_skb_ssn(mpdu);
211 skb_queue_walk(&du_hdr->mpdu_q, mpdu)
212 {
213 sn = ampdu_skb_ssn(mpdu);
214 sprintf(msg, " %d", sn);
215 }
216 prn_aggr_err("ES %d -> %d (%s)\n",
217 ssn, ampdu_skb_ssn(p_aggr_pkt), msg);
218 ret = false;
219 break;
220 }
221 }
222 }
223 else
224 ampdu_tid->mib.ampdu_mib_aggr_retry_counter += 1;
225 skb_queue_walk(&du_hdr->mpdu_q, mpdu)
226 {
227 u32 ssn = ampdu_skb_ssn(mpdu);
228 SKB_info *mpdu_skb_info = (SKB_info *) (mpdu->head);
229 if (first_ssn == SSV_ILLEGAL_SN)
230 first_ssn = ssn;
231 pp_aggr_pkt = &INDEX_PKT_BY_SSN(ampdu_tid, ssn);
232 p_aggr_pkt = *pp_aggr_pkt;
233 *pp_aggr_pkt = mpdu;
234 if (!retry)
235 ampdu_tid->aggr_pkt_num++;
236 mpdu_skb_info->ampdu_tx_status = AMPDU_ST_AGGREGATED;
237 if (ampdu_tid->ssv_baw_head == SSV_ILLEGAL_SN)
238 {
239 ampdu_tid->ssv_baw_head = ssn;
240 }
241 if ((p_aggr_pkt != NULL) && (mpdu != p_aggr_pkt))
242 prn_aggr_err(
243 "%d -> %d (H%d, N%d, Q%d)\n",
244 ssn, ampdu_skb_ssn(p_aggr_pkt), old_baw_head, old_aggr_pkt_num, sync_num);
245 }
246 } while (0);
247 spin_unlock_irqrestore(&du_tid->pkt_array_lock, flags);
248 #if 1
249 {
250 u32 page_count = (ampdu->len + SSV6200_ALLOC_RSVD);
251 if (page_count & HW_MMU_PAGE_MASK)
252 page_count = (page_count >> HW_MMU_PAGE_SHIFT) + 1;
253 else page_count = page_count >> HW_MMU_PAGE_SHIFT;
254 if (page_count > (SSV6200_PAGE_TX_THRESHOLD / 2))
255 printk(KERN_ERR "AMPDU requires pages %d(%d-%d-%d) exceeds resource limit %d.\n",
256 page_count, ampdu->len, ampdu_hdr->max_size, ampdu_hdr->size,
257 (SSV6200_PAGE_TX_THRESHOLD / 2));
258 }
259 #endif
260 return ret;
261 }
_aggr_retry_mpdu(struct ssv_softc * sc,struct AMPDU_TID_st * ampdu_tid,struct sk_buff_head * retry_queue,u32 max_aggr_len)262 struct sk_buff* _aggr_retry_mpdu (struct ssv_softc *sc,
263 struct AMPDU_TID_st *ampdu_tid,
264 struct sk_buff_head *retry_queue,
265 u32 max_aggr_len)
266 {
267 struct sk_buff *retry_mpdu;
268 struct sk_buff *new_ampdu_skb;
269 u32 num_retry_mpdu;
270 u32 temp_i;
271 u32 total_skb_size;
272 unsigned long flags;
273 u16 head_ssn = ampdu_tid->ssv_baw_head;
274 struct ampdu_hdr_st *ampdu_hdr;
275 #if 0
276 if (cur_AMPDU_TID->ssv_baw_head == SSV_ILLEGAL_SN)
277 {
278 struct sk_buff *skb = skb_peek(ampdu_skb_retry_queue);
279 prn_aggr_err("Rr %d\n", (skb == NULL) ? (-1) : ampdu_skb_ssn(skb));
280 return NULL;
281 }
282 #else
283 BUG_ON(head_ssn == SSV_ILLEGAL_SN);
284 #endif
285 num_retry_mpdu = skb_queue_len(retry_queue);
286 if (num_retry_mpdu == 0)
287 return NULL;
288 new_ampdu_skb = _alloc_ampdu_skb(sc, ampdu_tid, max_aggr_len);
289 if (new_ampdu_skb == 0)
290 return NULL;
291 ampdu_hdr = (struct ampdu_hdr_st *)new_ampdu_skb->head;
292 total_skb_size = 0;
293 spin_lock_irqsave(&retry_queue->lock, flags);
294 for (temp_i = 0; temp_i < ampdu_tid->agg_num_max; temp_i++)
295 {
296 struct ieee80211_hdr *mpdu_hdr;
297 u16 mpdu_sn;
298 u16 diff;
299 u32 new_total_skb_size;
300 retry_mpdu = skb_peek(retry_queue);
301 if (retry_mpdu == NULL)
302 {
303 break;
304 }
305 mpdu_hdr = ampdu_skb_hdr(retry_mpdu);
306 mpdu_sn = ampdu_hdr_ssn(mpdu_hdr);
307 diff = SSV_AMPDU_SN_a_minus_b(head_ssn, mpdu_sn);
308 if ((head_ssn != SSV_ILLEGAL_SN)
309 && (diff > 0)
310 && (diff <= ampdu_tid->ssv_baw_size))
311 {
312 struct SKB_info_st *skb_info;
313 prn_aggr_err("Z. release skb (s %d, h %d, d %d)\n",
314 mpdu_sn, head_ssn, diff);
315 skb_info = (struct SKB_info_st *) (retry_mpdu->head);
316 skb_info->ampdu_tx_status = AMPDU_ST_DROPPED;
317 ampdu_tid->mib.ampdu_mib_discard_counter++;
318 continue;
319 }
320 new_total_skb_size = total_skb_size + retry_mpdu->len;
321 if (new_total_skb_size > ampdu_hdr->max_size)
322 break;
323 total_skb_size = new_total_skb_size;
324 #if 0
325 if (ampdu_skb_retry_queue != NULL)
326 prn_aggr_err("R %d\n", SerialNumber);
327 #endif
328 retry_mpdu = __skb_dequeue(retry_queue);
329 _put_mpdu_to_ampdu(new_ampdu_skb, retry_mpdu);
330 ampdu_tid->mib.ampdu_mib_retry_counter++;
331 }
332 ampdu_tid->mib.ampdu_mib_aggr_retry_counter += 1;
333 ampdu_tid->mib.ampdu_mib_dist[temp_i] += 1;
334 spin_unlock_irqrestore(&retry_queue->lock, flags);
335 #if 0
336 {
337 struct ampdu_hdr_st *ampdu_hdr = (struct ampdu_hdr_st *)new_ampdu_skb->head;
338 retry_mpdu = skb_peek(&du_hdr->mpdu_q);
339 dev_alert(sc->dev, "rA %d - %d\n", ampdu_skb_ssn(retry_mpdu),
340 skb_queue_len(&du_hdr->mpdu_q));
341 }
342 #endif
343 if (ampdu_hdr->mpdu_num == 0) {
344 dev_kfree_skb_any(new_ampdu_skb);
345 return NULL;
346 }
347 return new_ampdu_skb;
348 }
_add_ampdu_txinfo(struct ssv_softc * sc,struct sk_buff * ampdu_skb)349 static void _add_ampdu_txinfo (struct ssv_softc *sc, struct sk_buff *ampdu_skb)
350 {
351 struct ssv6200_tx_desc *tx_desc;
352 ssv6xxx_add_txinfo(sc, ampdu_skb);
353 tx_desc = (struct ssv6200_tx_desc *) ampdu_skb->data;
354 tx_desc->tx_report = 1;
355 #if 0
356 tx_desc->len = ampdu_skb->len;
357 tx_desc->c_type = M2_TXREQ;
358 tx_desc->f80211 = 1;
359 tx_desc->ht = 1;
360 tx_desc->qos = 1;
361 tx_desc->use_4addr = 0;
362 tx_desc->security = 0;
363 tx_desc->more_data = 0;
364 tx_desc->stype_b5b4 = 0;
365 tx_desc->extra_info = 0;
366 tx_desc->hdr_offset = sc->sh->cfg.txpb_offset;;
367 tx_desc->frag = 0;
368 tx_desc->unicast = 1;
369 tx_desc->hdr_len = 0;
370 tx_desc->RSVD_4 = 0;
371 tx_desc->tx_burst = 0;
372 tx_desc->ack_policy = 1;
373 tx_desc->aggregation = 1;
374 tx_desc->RSVD_1 = 0;
375 tx_desc->do_rts_cts = 0;
376 tx_desc->reason = 0;
377 tx_desc->payload_offset = tx_desc->hdr_offset + tx_desc->hdr_len;
378 tx_desc->RSVD_4 = 0;
379 tx_desc->RSVD_2 = 0;
380 tx_desc->fCmdIdx = 0;
381 tx_desc->wsid = 0;
382 tx_desc->txq_idx = 0;
383 tx_desc->TxF_ID = 0;
384 tx_desc->rts_cts_nav = 0;
385 tx_desc->frame_consume_time = 0;
386 tx_desc->crate_idx=0;
387 tx_desc->drate_idx = 22;
388 tx_desc->dl_length = 56;
389 tx_desc->RSVD_3 = 0;
390 #endif
391 #if 0
392 if(ampdu_skb != 0)
393 {
394 u32 temp_i;
395 u8* temp8_p = (u8*)ampdu_skb->data;
396 ampdu_db_log("print txinfo.\n");
397 for(temp_i=0; temp_i < 24; temp_i++)
398 {
399 ampdu_db_log_simple("%02x",*(u8*)(temp8_p + temp_i));
400 if(((temp_i+1) % 4) == 0)
401 {
402 ampdu_db_log_simple("\n");
403 }
404 }
405 ampdu_db_log_simple("\n");
406 }
407 #endif
408 #if 0
409 if(ampdu_skb != 0)
410 {
411 u32 temp_i;
412 u8* temp8_p = (u8*)ampdu_skb->data;
413 ampdu_db_log("print all skb.\n");
414 for(temp_i=0; temp_i < ampdu_skb->len; temp_i++)
415 {
416 ampdu_db_log_simple("%02x",*(u8*)(temp8_p + temp_i));
417 if(((temp_i+1) % 4) == 0)
418 {
419 ampdu_db_log_simple("\n");
420 }
421 }
422 ampdu_db_log_simple("\n");
423 }
424 #endif
425 }
_send_hci_skb(struct ssv_softc * sc,struct sk_buff * skb,u32 tx_flag)426 void _send_hci_skb (struct ssv_softc *sc, struct sk_buff *skb, u32 tx_flag)
427 {
428 struct ssv6200_tx_desc *tx_desc = (struct ssv6200_tx_desc *)skb->data;
429 int ret = AMPDU_HCI_SEND(sc->sh, skb, tx_desc->txq_idx, tx_flag);
430 #if 1
431 if ((tx_desc->txq_idx > 3) && (ret <= 0))
432 {
433 prn_aggr_err("BUG!! %d %d\n", tx_desc->txq_idx, ret);
434 }
435 #else
436 BUG_ON(tx_desc->txq_idx>3 && ret<=0);
437 #endif
438 }
ssv6200_ampdu_add_txinfo_and_send_HCI(struct ssv_softc * sc,struct sk_buff * ampdu_skb,u32 tx_flag)439 static void ssv6200_ampdu_add_txinfo_and_send_HCI (struct ssv_softc *sc,
440 struct sk_buff *ampdu_skb,
441 u32 tx_flag)
442 {
443 _add_ampdu_txinfo(sc, ampdu_skb);
444 _send_hci_skb(sc, ampdu_skb, tx_flag);
445 }
ssv6200_ampdu_send_retry(struct ieee80211_hw * hw,AMPDU_TID * cur_ampdu_tid,struct sk_buff_head * ampdu_skb_retry_queue_p,bool send_aggr_tx)446 static void ssv6200_ampdu_send_retry (
447 struct ieee80211_hw *hw, AMPDU_TID *cur_ampdu_tid,
448 struct sk_buff_head *ampdu_skb_retry_queue_p, bool send_aggr_tx)
449 {
450 struct ssv_softc *sc = hw->priv;
451 struct sk_buff *ampdu_retry_skb;
452 u32 ampdu_skb_retry_queue_len;
453 u32 max_agg_len;
454 u16 lowest_rate;
455 struct fw_rc_retry_params rates[SSV62XX_TX_MAX_RATES];
456 ampdu_skb_retry_queue_len = skb_queue_len(ampdu_skb_retry_queue_p);
457 if (ampdu_skb_retry_queue_len == 0)
458 return;
459 ampdu_retry_skb = skb_peek(ampdu_skb_retry_queue_p);
460 lowest_rate = ssv62xx_ht_rate_update(ampdu_retry_skb, sc, rates);
461 max_agg_len = ampdu_max_transmit_length[lowest_rate];
462 if (max_agg_len > 0)
463 {
464 u32 cur_ampdu_max_size = SSV_GET_MAX_AMPDU_SIZE(sc->sh);
465 if (max_agg_len >= cur_ampdu_max_size)
466 max_agg_len = cur_ampdu_max_size;
467 while (ampdu_skb_retry_queue_len > 0)
468 {
469 struct sk_buff *retry_mpdu = skb_peek(ampdu_skb_retry_queue_p);
470 SKB_info *mpdu_skb_info = (SKB_info *)(retry_mpdu->head);
471 mpdu_skb_info->lowest_rate = lowest_rate;
472 memcpy(mpdu_skb_info->rates, rates, sizeof(rates));
473 ampdu_retry_skb = _aggr_retry_mpdu(sc, cur_ampdu_tid, ampdu_skb_retry_queue_p,
474 max_agg_len);
475 if (ampdu_retry_skb != NULL)
476 {
477 _sync_ampdu_pkt_arr(cur_ampdu_tid, ampdu_retry_skb, true);
478 ssv6200_ampdu_add_txinfo_and_send_HCI(sc, ampdu_retry_skb,
479 AMPDU_HCI_SEND_HEAD_WITHOUT_FLOWCTRL);
480 }
481 else
482 {
483 prn_aggr_err("AMPDU retry failed.\n");
484 return;
485 }
486 ampdu_skb_retry_queue_len = skb_queue_len(ampdu_skb_retry_queue_p);
487 }
488 }
489 else
490 {
491 struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];
492 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(ampdu_retry_skb);
493 memcpy(rates, info->control.rates, sizeof(info->control.rates));
494 while ((ampdu_retry_skb = __skb_dequeue_tail(ampdu_skb_retry_queue_p)) != NULL)
495 {
496 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(ampdu_retry_skb);
497 info->flags &= ~IEEE80211_TX_CTL_AMPDU;
498 memcpy(info->control.rates, rates, sizeof(info->control.rates));
499 ssv6xxx_update_txinfo(sc, ampdu_retry_skb);
500 _send_hci_skb(sc, ampdu_retry_skb, AMPDU_HCI_SEND_HEAD_WITHOUT_FLOWCTRL);
501 }
502 }
503 }
ssv6200_ampdu_init(struct ieee80211_hw * hw)504 void ssv6200_ampdu_init (struct ieee80211_hw *hw)
505 {
506 struct ssv_softc *sc = hw->priv;
507 ssv6200_ampdu_hw_init(hw);
508 sc->tx.ampdu_tx_group_id = 0;
509 #ifdef USE_ENCRYPT_WORK
510 INIT_WORK(&sc->ampdu_tx_encry_work, encry_work);
511 INIT_WORK(&sc->sync_hwkey_work, sync_hw_key_work);
512 #endif
513 }
ssv6200_ampdu_deinit(struct ieee80211_hw * hw)514 void ssv6200_ampdu_deinit (struct ieee80211_hw *hw)
515 {
516 }
ssv6200_ampdu_release_skb(struct sk_buff * skb,struct ieee80211_hw * hw)517 void ssv6200_ampdu_release_skb (struct sk_buff *skb, struct ieee80211_hw *hw)
518 {
519 #if LINUX_VERSION_CODE >= 0x030400
520 ieee80211_free_txskb(hw, skb);
521 #else
522 dev_kfree_skb_any(skb);
523 #endif
524 }
525 #ifdef CONFIG_SSV6XXX_DEBUGFS
526 struct mib_dump_data {
527 char *prt_buff;
528 size_t buff_size;
529 size_t prt_len;
530 };
531 #define AMPDU_TX_MIB_SUMMARY_BUF_SIZE (4096)
ampdu_tx_mib_summary_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)532 static ssize_t ampdu_tx_mib_summary_read (struct file *file,
533 char __user *user_buf, size_t count,
534 loff_t *ppos)
535 {
536 struct ssv_sta_priv_data *ssv_sta_priv =
537 (struct ssv_sta_priv_data *) file->private_data;
538 char *summary_buf = kzalloc(AMPDU_TX_MIB_SUMMARY_BUF_SIZE, GFP_KERNEL);
539 ssize_t summary_size;
540 ssize_t ret;
541 if (!summary_buf)
542 return -ENOMEM;
543 summary_size = ampdu_tx_mib_dump(ssv_sta_priv, summary_buf,
544 AMPDU_TX_MIB_SUMMARY_BUF_SIZE);
545 ret = simple_read_from_buffer(user_buf, count, ppos, summary_buf,
546 summary_size);
547 kfree(summary_buf);
548 return ret;
549 }
ampdu_tx_mib_summary_open(struct inode * inode,struct file * file)550 static int ampdu_tx_mib_summary_open (struct inode *inode, struct file *file)
551 {
552 file->private_data = inode->i_private;
553 return 0;
554 }
555 static const struct file_operations mib_summary_fops = { .read =
556 ampdu_tx_mib_summary_read, .open = ampdu_tx_mib_summary_open, };
ampdu_tx_tid_window_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)557 static ssize_t ampdu_tx_tid_window_read (struct file *file,
558 char __user *user_buf, size_t count,
559 loff_t *ppos)
560 {
561 struct AMPDU_TID_st *ampdu_tid = (struct AMPDU_TID_st *)file->private_data;
562 char *summary_buf = kzalloc(AMPDU_TX_MIB_SUMMARY_BUF_SIZE, GFP_KERNEL);
563 ssize_t ret;
564 char *prn_ptr = summary_buf;
565 int prt_size;
566 int buf_size = AMPDU_TX_MIB_SUMMARY_BUF_SIZE;
567 int i;
568 struct sk_buff *ba_skb, *tmp_ba_skb;
569 if (!summary_buf)
570 return -ENOMEM;
571 prt_size = snprintf(prn_ptr, buf_size, "\nWMM_TID %d:\n"
572 "\tWindow:",
573 ampdu_tid->tidno);
574 prn_ptr += prt_size;
575 buf_size -= prt_size;
576 for (i = 0; i < SSV_AMPDU_BA_WINDOW_SIZE; i++)
577 {
578 struct sk_buff *skb = ampdu_tid->aggr_pkts[i];
579 if ((i % 8) == 0)
580 {
581 prt_size = snprintf(prn_ptr, buf_size, "\n\t\t");
582 prn_ptr += prt_size;
583 buf_size -= prt_size;
584 }
585 if (skb == NULL)
586 prt_size = snprintf(prn_ptr, buf_size, " %s", "NULL ");
587 else
588 {
589 struct SKB_info_st *skb_info = (struct SKB_info_st *)(skb->head);
590 const char status_symbol[] = {'N',
591 'A',
592 'S',
593 'R',
594 'P',
595 'D'};
596 prt_size = snprintf(prn_ptr, buf_size, " %4d%c", ampdu_skb_ssn(skb),
597 ( (skb_info->ampdu_tx_status <= AMPDU_ST_DONE)
598 ? status_symbol[skb_info->ampdu_tx_status]
599 : 'X'));
600 }
601 prn_ptr += prt_size;
602 buf_size -= prt_size;
603 }
604 prt_size = snprintf(prn_ptr, buf_size, "\n\tEarly aggregated #: %d\n", ampdu_tid->early_aggr_skb_num);
605 prn_ptr += prt_size;
606 buf_size -= prt_size;
607 prt_size = snprintf(prn_ptr, buf_size, "\tBAW skb #: %d\n", ampdu_tid->aggr_pkt_num);
608 prn_ptr += prt_size;
609 buf_size -= prt_size;
610 prt_size = snprintf(prn_ptr, buf_size, "\tBAW head: %d\n", ampdu_tid->ssv_baw_head);
611 prn_ptr += prt_size;
612 buf_size -= prt_size;
613 prt_size = snprintf(prn_ptr, buf_size, "\tState: %d\n", ampdu_tid->state);
614 prn_ptr += prt_size;
615 buf_size -= prt_size;
616 prt_size = snprintf(prn_ptr, buf_size, "\tBA:\n");
617 prn_ptr += prt_size;
618 buf_size -= prt_size;
619 skb_queue_walk_safe(&du_tid->ba_q, ba_skb, tmp_ba_skb)
620 {
621 prt_size = _dump_ba_skb(prn_ptr, buf_size, ba_skb);
622 prn_ptr += prt_size;
623 buf_size -= prt_size;
624 }
625 buf_size = AMPDU_TX_MIB_SUMMARY_BUF_SIZE - buf_size;
626 ret = simple_read_from_buffer(user_buf, count, ppos, summary_buf,
627 buf_size);
628 kfree(summary_buf);
629 return ret;
630 }
ampdu_tx_tid_window_open(struct inode * inode,struct file * file)631 static int ampdu_tx_tid_window_open (struct inode *inode, struct file *file)
632 {
633 file->private_data = inode->i_private;
634 return 0;
635 }
636 static const struct file_operations tid_window_fops = { .read =
637 ampdu_tx_tid_window_read, .open = ampdu_tx_tid_window_open, };
ampdu_tx_mib_reset_open(struct inode * inode,struct file * file)638 static int ampdu_tx_mib_reset_open (struct inode *inode, struct file *file)
639 {
640 file->private_data = inode->i_private;
641 return 0;
642 }
ampdu_tx_mib_reset_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)643 static ssize_t ampdu_tx_mib_reset_read (struct file *file,
644 char __user *user_buf, size_t count,
645 loff_t *ppos)
646 {
647 char *reset_buf = kzalloc(64, GFP_KERNEL);
648 ssize_t ret;
649 u32 reset_size;
650 if (!reset_buf)
651 return -ENOMEM;
652 reset_size = snprintf(reset_buf, 63, "%d", 0);
653 ret = simple_read_from_buffer(user_buf, count, ppos, reset_buf,
654 reset_size);
655 kfree(reset_buf);
656 return ret;
657 }
ampdu_tx_mib_reset_write(struct file * file,const char __user * buffer,size_t count,loff_t * pos)658 static ssize_t ampdu_tx_mib_reset_write (struct file *file,
659 const char __user *buffer,
660 size_t count,
661 loff_t *pos)
662 {
663 struct AMPDU_TID_st *ampdu_tid = (struct AMPDU_TID_st *)file->private_data;
664 memset(&du_tid->mib, 0, sizeof(struct AMPDU_MIB_st));
665 return count;
666 }
667 static const struct file_operations mib_reset_fops
668 = { .read = ampdu_tx_mib_reset_read,
669 .open = ampdu_tx_mib_reset_open,
670 .write = ampdu_tx_mib_reset_write};
ssv6200_ampdu_tx_init_debugfs(struct ssv_softc * sc,struct ssv_sta_priv_data * ssv_sta_priv)671 static void ssv6200_ampdu_tx_init_debugfs (
672 struct ssv_softc *sc, struct ssv_sta_priv_data *ssv_sta_priv)
673 {
674 struct ssv_sta_info *sta_info = ssv_sta_priv->sta_info;
675 int i;
676 struct dentry *sta_debugfs_dir = sta_info->debugfs_dir;
677 dev_info(sc->dev, "Creating AMPDU TX debugfs.\n");
678 if (sta_debugfs_dir == NULL)
679 {
680 dev_err(sc->dev, "No STA debugfs.\n");
681 return;
682 }
683 debugfs_create_file("ampdu_tx_summary", 00444, sta_debugfs_dir,
684 ssv_sta_priv, &mib_summary_fops);
685 debugfs_create_u32("total_BA", 00644, sta_debugfs_dir,
686 &ssv_sta_priv->ampdu_mib_total_BA_counter);
687 for (i = 0; i < WMM_TID_NUM; i++)
688 {
689 char debugfs_name[20];
690 struct dentry *ampdu_tx_debugfs_dir;
691 int j;
692 struct AMPDU_TID_st *ampdu_tid = &ssv_sta_priv->ampdu_tid[i];
693 struct AMPDU_MIB_st *ampdu_mib = &du_tid->mib;
694 snprintf(debugfs_name, sizeof(debugfs_name), "ampdu_tx_%d", i);
695 ampdu_tx_debugfs_dir = debugfs_create_dir(debugfs_name,
696 sta_debugfs_dir);
697 if (ampdu_tx_debugfs_dir == NULL)
698 {
699 dev_err(sc->dev,
700 "Failed to create debugfs for AMPDU TX TID %d: %s\n", i,
701 debugfs_name);
702 continue;
703 }
704 ssv_sta_priv->ampdu_tid[i].debugfs_dir = ampdu_tx_debugfs_dir;
705 debugfs_create_file("baw_status", 00444, ampdu_tx_debugfs_dir,
706 ampdu_tid, &tid_window_fops);
707 debugfs_create_file("reset", 00644, ampdu_tx_debugfs_dir,
708 ampdu_tid, &mib_reset_fops);
709 debugfs_create_u32("total", 00444, ampdu_tx_debugfs_dir,
710 &du_mib->ampdu_mib_ampdu_counter);
711 debugfs_create_u32("retry", 00444, ampdu_tx_debugfs_dir,
712 &du_mib->ampdu_mib_retry_counter);
713 debugfs_create_u32("aggr_retry", 00444, ampdu_tx_debugfs_dir,
714 &du_mib->ampdu_mib_aggr_retry_counter);
715 debugfs_create_u32("BAR", 00444, ampdu_tx_debugfs_dir,
716 &du_mib->ampdu_mib_bar_counter);
717 debugfs_create_u32("Discarded", 00444, ampdu_tx_debugfs_dir,
718 &du_mib->ampdu_mib_discard_counter);
719 debugfs_create_u32("BA", 00444, ampdu_tx_debugfs_dir,
720 &du_mib->ampdu_mib_BA_counter);
721 debugfs_create_u32("Pass", 00444, ampdu_tx_debugfs_dir,
722 &du_mib->ampdu_mib_pass_counter);
723 for (j = 0; j <= SSV_AMPDU_aggr_num_max; j++)
724 {
725 char dist_dbg_name[10];
726 snprintf(dist_dbg_name, sizeof(dist_dbg_name), "aggr_%d", j);
727 debugfs_create_u32(dist_dbg_name, 00444, ampdu_tx_debugfs_dir,
728 &du_mib->ampdu_mib_dist[j]);
729 }
730 skb_queue_head_init(&ssv_sta_priv->ampdu_tid[i].ba_q);
731 }
732 }
733 #endif
ssv6200_ampdu_tx_add_sta(struct ieee80211_hw * hw,struct ieee80211_sta * sta)734 void ssv6200_ampdu_tx_add_sta (struct ieee80211_hw *hw,
735 struct ieee80211_sta *sta)
736 {
737 struct ssv_sta_priv_data *ssv_sta_priv;
738 struct ssv_softc *sc;
739 u32 temp_i;
740 ssv_sta_priv = (struct ssv_sta_priv_data *) sta->drv_priv;
741 sc = (struct ssv_softc *) hw->priv;
742 for (temp_i = 0; temp_i < WMM_TID_NUM; temp_i++)
743 {
744 ssv_sta_priv->ampdu_tid[temp_i].sta = sta;
745 ssv_sta_priv->ampdu_tid[temp_i].state = AMPDU_STATE_STOP;
746 spin_lock_init(
747 &ssv_sta_priv->ampdu_tid[temp_i].ampdu_skb_tx_queue_lock);
748 spin_lock_init(&ssv_sta_priv->ampdu_tid[temp_i].pkt_array_lock);
749 }
750 #ifdef CONFIG_SSV6XXX_DEBUGFS
751 ssv6200_ampdu_tx_init_debugfs(sc, ssv_sta_priv);
752 #endif
753 }
ssv6200_ampdu_tx_start(u16 tid,struct ieee80211_sta * sta,struct ieee80211_hw * hw,u16 * ssn)754 void ssv6200_ampdu_tx_start (u16 tid, struct ieee80211_sta *sta,
755 struct ieee80211_hw *hw, u16 *ssn)
756 {
757 struct ssv_softc *sc = hw->priv;
758 struct ssv_sta_priv_data *ssv_sta_priv;
759 struct AMPDU_TID_st *ampdu_tid;
760 int i;
761 ssv_sta_priv = (struct ssv_sta_priv_data *) sta->drv_priv;
762 ampdu_tid = &ssv_sta_priv->ampdu_tid[tid];
763 ampdu_tid->ssv_baw_head = SSV_ILLEGAL_SN;
764 #if 0
765 if (list_empty(&sc->tx.ampdu_tx_que))
766 {
767 sc->ampdu_rekey_pause = AMPDU_REKEY_PAUSE_STOP;
768 }
769 #endif
770 #ifdef DEBUG_AMPDU_FLUSH
771 printk(KERN_ERR "Adding %02X-%02X-%02X-%02X-%02X-%02X TID %d (%p).\n",
772 sta->addr[0], sta->addr[1], sta->addr[2],
773 sta->addr[3], sta->addr[4], sta->addr[5],
774 ampdu_tid->tidno, ampdu_tid);
775 {
776 int j;
777 for (j = 0; j <= MAX_TID; j++)
778 {
779 if (sc->tid[j] == 0)
780 break;
781 }
782 if (j == MAX_TID)
783 {
784 printk(KERN_ERR "No room for new TID.\n");
785 }
786 else
787 sc->tid[j] = ampdu_tid;
788 }
789 #endif
790 list_add_tail_rcu(&du_tid->list, &sc->tx.ampdu_tx_que);
791 skb_queue_head_init(&du_tid->ampdu_skb_tx_queue);
792 #ifdef ENABLE_INCREMENTAL_AGGREGATION
793 skb_queue_head_init(&du_tid->early_aggr_ampdu_q);
794 ampdu_tid->early_aggr_skb_num = 0;
795 #endif
796 skb_queue_head_init(&du_tid->ampdu_skb_wait_encry_queue);
797 skb_queue_head_init(&du_tid->retry_queue);
798 skb_queue_head_init(&du_tid->release_queue);
799 for (i = 0;
800 i < (sizeof(ampdu_tid->aggr_pkts) / sizeof(ampdu_tid->aggr_pkts[0]));
801 i++)
802 ampdu_tid->aggr_pkts[i] = 0;
803 ampdu_tid->aggr_pkt_num = 0;
804 #ifdef ENABLE_AGGREGATE_IN_TIME
805 ampdu_tid->cur_ampdu_pkt = _alloc_ampdu_skb(sc, ampdu_tid, 0);
806 #endif
807 #ifdef AMPDU_CHECK_SKB_SEQNO
808 ssv_sta_priv->ampdu_tid[tid].last_seqno = (-1);
809 #endif
810 ssv_sta_priv->ampdu_mib_total_BA_counter = 0;
811 memset(&ssv_sta_priv->ampdu_tid[tid].mib, 0, sizeof(struct AMPDU_MIB_st));
812 ssv_sta_priv->ampdu_tid[tid].state = AMPDU_STATE_START;
813 #ifdef CONFIG_SSV6XXX_DEBUGFS
814 skb_queue_head_init(&ssv_sta_priv->ampdu_tid[tid].ba_q);
815 #endif
816 }
ssv6200_ampdu_tx_operation(u16 tid,struct ieee80211_sta * sta,struct ieee80211_hw * hw,u8 buffer_size)817 void ssv6200_ampdu_tx_operation (u16 tid, struct ieee80211_sta *sta,
818 struct ieee80211_hw *hw, u8 buffer_size)
819 {
820 struct ssv_sta_priv_data *ssv_sta_priv;
821 ssv_sta_priv = (struct ssv_sta_priv_data *) sta->drv_priv;
822 ssv_sta_priv->ampdu_tid[tid].tidno = tid;
823 ssv_sta_priv->ampdu_tid[tid].sta = sta;
824 ssv_sta_priv->ampdu_tid[tid].agg_num_max = MAX_AGGR_NUM;
825 #if 1
826 if (buffer_size > IEEE80211_MAX_AMPDU_BUF)
827 {
828 buffer_size = IEEE80211_MAX_AMPDU_BUF;
829 }
830 printk("ssv6200_ampdu_tx_operation:buffer_size=%d\n", buffer_size);
831 ssv_sta_priv->ampdu_tid[tid].ssv_baw_size = SSV_AMPDU_WINDOW_SIZE;
832 #else
833 ssv_sta_priv->ampdu_tid[tid].ssv_baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
834 if(buffer_size > IEEE80211_MAX_AMPDU_BUF)
835 {
836 buffer_size = IEEE80211_MAX_AMPDU_BUF;
837 }
838 if(ssv_sta_priv->ampdu_tid[tid].ssv_baw_size > buffer_size)
839 {
840 ssv_sta_priv->ampdu_tid[tid].ssv_baw_size = buffer_size;
841 }
842 #endif
843 ssv_sta_priv->ampdu_tid[tid].state = AMPDU_STATE_OPERATION;
844 }
_clear_mpdu_q(struct ieee80211_hw * hw,struct sk_buff_head * q,bool aggregated_mpdu)845 static void _clear_mpdu_q (struct ieee80211_hw *hw, struct sk_buff_head *q,
846 bool aggregated_mpdu)
847 {
848 struct sk_buff *skb;
849 while (1)
850 {
851 skb = skb_dequeue(q);
852 if (!skb)
853 break;
854 if (aggregated_mpdu)
855 skb_pull(skb, AMPDU_DELIMITER_LEN);
856 ieee80211_tx_status(hw, skb);
857 }
858 }
ssv6200_ampdu_tx_stop(u16 tid,struct ieee80211_sta * sta,struct ieee80211_hw * hw)859 void ssv6200_ampdu_tx_stop (u16 tid, struct ieee80211_sta *sta,
860 struct ieee80211_hw *hw)
861 {
862 struct ssv_softc *sc = hw->priv;
863 struct ssv_sta_priv_data *ssv_sta_priv;
864 ssv_sta_priv = (struct ssv_sta_priv_data *) sta->drv_priv;
865 if (ssv_sta_priv->ampdu_tid[tid].state == AMPDU_STATE_STOP)
866 return;
867 ssv_sta_priv->ampdu_tid[tid].state = AMPDU_STATE_STOP;
868 printk("ssv6200_ampdu_tx_stop\n");
869 if (!list_empty(&sc->tx.ampdu_tx_que))
870 {
871 #ifdef DEBUG_AMPDU_FLUSH
872 {
873 int j;
874 struct AMPDU_TID_st *ampdu_tid = &ssv_sta_priv->ampdu_tid[tid];
875 for (j = 0; j <= MAX_TID; j++)
876 {
877 if (sc->tid[j] == ampdu_tid)
878 break;
879 }
880 if (j == MAX_TID)
881 {
882 printk(KERN_ERR "No TID found when deleting it.\n");
883 }
884 else
885 sc->tid[j] = NULL;
886 printk(KERN_ERR "Deleting %02X-%02X-%02X-%02X-%02X-%02X TID %d (%p).\n",
887 sta->addr[0], sta->addr[1], sta->addr[2],
888 sta->addr[3], sta->addr[4], sta->addr[5],
889 ampdu_tid->tidno, ampdu_tid);
890 }
891 #endif
892 list_del_rcu(&ssv_sta_priv->ampdu_tid[tid].list);
893 }
894 printk("clear tx q len=%d\n",
895 skb_queue_len(&ssv_sta_priv->ampdu_tid[tid].ampdu_skb_tx_queue));
896 _clear_mpdu_q(sc->hw, &ssv_sta_priv->ampdu_tid[tid].ampdu_skb_tx_queue,
897 true);
898 printk("clear retry q len=%d\n",
899 skb_queue_len(&ssv_sta_priv->ampdu_tid[tid].retry_queue));
900 _clear_mpdu_q(sc->hw, &ssv_sta_priv->ampdu_tid[tid].retry_queue, true);
901 #ifdef USE_ENCRYPT_WORK
902 printk("clear encrypt q len=%d\n",skb_queue_len(&ssv_sta_priv->ampdu_tid[tid].ampdu_skb_wait_encry_queue));
903 _clear_mpdu_q(sc->hw, &ssv_sta_priv->ampdu_tid[tid].ampdu_skb_wait_encry_queue, false);
904 #endif
905 #ifdef ENABLE_AGGREGATE_IN_TIME
906 if (ssv_sta_priv->ampdu_tid[tid].cur_ampdu_pkt != NULL)
907 {
908 dev_kfree_skb_any(ssv_sta_priv->ampdu_tid[tid].cur_ampdu_pkt);
909 ssv_sta_priv->ampdu_tid[tid].cur_ampdu_pkt = NULL;
910 }
911 #endif
912 ssv6200_tx_flow_control((void *) sc,
913 sc->tx.hw_txqid[ssv_sta_priv->ampdu_tid[tid].ac],
914 false, 1000);
915 }
ssv6200_ampdu_tx_state_stop_func(struct ssv_softc * sc,struct ieee80211_sta * sta,struct sk_buff * skb,struct AMPDU_TID_st * cur_AMPDU_TID)916 static void ssv6200_ampdu_tx_state_stop_func (
917 struct ssv_softc *sc, struct ieee80211_sta *sta, struct sk_buff *skb,
918 struct AMPDU_TID_st *cur_AMPDU_TID)
919 {
920 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
921 u8 *skb_qos_ctl = ieee80211_get_qos_ctl(hdr);
922 u8 tid_no = skb_qos_ctl[0] & 0xf;
923 if ((sta->ht_cap.ht_supported == true)
924 && (!!(sc->sh->cfg.hw_caps & SSV6200_HW_CAP_AMPDU_TX)))
925 {
926 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,32)
927 ieee80211_start_tx_ba_session(sc->hw, (u8*)(sta->addr), (u16)tid_no);
928 #elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,37)
929 ieee80211_start_tx_ba_session(sta, tid_no);
930 #else
931 ieee80211_start_tx_ba_session(sta, tid_no, 0);
932 #endif
933 ampdu_db_log("start ampdu_tx(rc) : tid_no = %d\n", tid_no);
934 }
935 }
ssv6200_ampdu_tx_state_operation_func(struct ssv_softc * sc,struct ieee80211_sta * sta,struct sk_buff * skb,struct AMPDU_TID_st * cur_AMPDU_TID)936 static void ssv6200_ampdu_tx_state_operation_func (
937 struct ssv_softc *sc, struct ieee80211_sta *sta, struct sk_buff *skb,
938 struct AMPDU_TID_st *cur_AMPDU_TID)
939 {
940 #if 0
941 else if (sc->ampdu_rekey_pause == AMPDU_REKEY_PAUSE_ONGOING)
942 {
943 pause_ampdu = true;
944 printk("!!!ampdu_rekey_pause\n");
945 }
946 #endif
947 }
ssv6200_ampdu_tx_update_state(void * priv,struct ieee80211_sta * sta,struct sk_buff * skb)948 void ssv6200_ampdu_tx_update_state (void *priv, struct ieee80211_sta *sta,
949 struct sk_buff *skb)
950 {
951 struct ssv_softc *sc = (struct ssv_softc *) priv;
952 struct ssv_sta_priv_data *ssv_sta_priv =
953 (struct ssv_sta_priv_data *) sta->drv_priv;
954 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
955 u8 *skb_qos_ctl;
956 u8 tid_no;
957 {
958 skb_qos_ctl = ieee80211_get_qos_ctl(hdr);
959 tid_no = skb_qos_ctl[0] & 0xf;
960 switch (ssv_sta_priv->ampdu_tid[tid_no].state)
961 {
962 case AMPDU_STATE_STOP:
963 ssv6200_ampdu_tx_state_stop_func(
964 sc, sta, skb, &(ssv_sta_priv->ampdu_tid[tid_no]));
965 break;
966 case AMPDU_STATE_START:
967 break;
968 case AMPDU_STATE_OPERATION:
969 ssv6200_ampdu_tx_state_operation_func(
970 sc, sta, skb, &(ssv_sta_priv->ampdu_tid[tid_no]));
971 break;
972 default:
973 break;
974 }
975 }
976 }
_put_mpdu_to_ampdu(struct sk_buff * ampdu,struct sk_buff * mpdu)977 void _put_mpdu_to_ampdu (struct sk_buff *ampdu, struct sk_buff *mpdu)
978 {
979 bool is_empty_ampdu = (ampdu->len == 0);
980 unsigned char *data_dest;
981 struct ampdu_hdr_st *ampdu_hdr = (struct ampdu_hdr_st *) ampdu->head;
982 BUG_ON(skb_tailroom(ampdu) < mpdu->len);
983 data_dest = skb_tail_pointer(ampdu);
984 skb_put(ampdu, mpdu->len);
985 if (is_empty_ampdu)
986 {
987 struct ieee80211_tx_info *ampdu_info = IEEE80211_SKB_CB(ampdu);
988 struct ieee80211_tx_info *mpdu_info = IEEE80211_SKB_CB(mpdu);
989 SKB_info *mpdu_skb_info = (SKB_info *)(mpdu->head);
990 u32 max_size_for_rate = ampdu_max_transmit_length[mpdu_skb_info->lowest_rate];
991 BUG_ON(max_size_for_rate == 0);
992 memcpy(ampdu_info, mpdu_info, sizeof(struct ieee80211_tx_info));
993 skb_set_queue_mapping(ampdu, skb_get_queue_mapping(mpdu));
994 ampdu_hdr->first_sn = ampdu_skb_ssn(mpdu);
995 ampdu_hdr->sta = ((struct SKB_info_st *)mpdu->head)->sta;
996 if (ampdu_hdr->max_size > max_size_for_rate)
997 ampdu_hdr->max_size = max_size_for_rate;
998 memcpy(ampdu_hdr->rates, mpdu_skb_info->rates, sizeof(ampdu_hdr->rates));
999 }
1000 memcpy(data_dest, mpdu->data, mpdu->len);
1001 __skb_queue_tail(&du_hdr->mpdu_q, mpdu);
1002 ampdu_hdr->ssn[ampdu_hdr->mpdu_num++] = ampdu_skb_ssn(mpdu);
1003 ampdu_hdr->size += mpdu->len;
1004 BUG_ON(ampdu_hdr->size > ampdu_hdr->max_size);
1005 }
_flush_early_ampdu_q(struct ssv_softc * sc,struct AMPDU_TID_st * ampdu_tid)1006 u32 _flush_early_ampdu_q (struct ssv_softc *sc, struct AMPDU_TID_st *ampdu_tid)
1007 {
1008 u32 flushed_ampdu = 0;
1009 unsigned long flags;
1010 struct sk_buff_head *early_aggr_ampdu_q = &du_tid->early_aggr_ampdu_q;
1011 spin_lock_irqsave(&early_aggr_ampdu_q->lock, flags);
1012 while (skb_queue_len(early_aggr_ampdu_q))
1013 {
1014 struct sk_buff *head_ampdu;
1015 struct ampdu_hdr_st *head_ampdu_hdr;
1016 u32 ampdu_aggr_num;
1017 head_ampdu = skb_peek(early_aggr_ampdu_q);
1018 head_ampdu_hdr = (struct ampdu_hdr_st *) head_ampdu->head;
1019 ampdu_aggr_num = skb_queue_len(&head_ampdu_hdr->mpdu_q);
1020 if ((SSV_AMPDU_BA_WINDOW_SIZE - ampdu_tid->aggr_pkt_num)
1021 < ampdu_aggr_num)
1022 break;
1023 if (_sync_ampdu_pkt_arr(ampdu_tid, head_ampdu, false))
1024 {
1025 head_ampdu = __skb_dequeue(early_aggr_ampdu_q);
1026 ampdu_tid->early_aggr_skb_num -= ampdu_aggr_num;
1027 #ifdef SSV_AMPDU_FLOW_CONTROL
1028 if (ampdu_tid->early_aggr_skb_num
1029 <= SSV_AMPDU_FLOW_CONTROL_LOWER_BOUND)
1030 {
1031 ssv6200_tx_flow_control((void *) sc,
1032 sc->tx.hw_txqid[ampdu_tid->ac], false, 1000);
1033 }
1034 #endif
1035 if ((skb_queue_len(early_aggr_ampdu_q) == 0)
1036 && (ampdu_tid->early_aggr_skb_num > 0))
1037 {
1038 printk(KERN_ERR "Empty early Q w. %d.\n", ampdu_tid->early_aggr_skb_num);
1039 }
1040 spin_unlock_irqrestore(&early_aggr_ampdu_q->lock, flags);
1041 _send_hci_skb(sc, head_ampdu,
1042 AMPDU_HCI_SEND_TAIL_WITHOUT_FLOWCTRL);
1043 spin_lock_irqsave(&early_aggr_ampdu_q->lock, flags);
1044 flushed_ampdu++;
1045 }
1046 else
1047 break;
1048 }
1049 spin_unlock_irqrestore(&early_aggr_ampdu_q->lock, flags);
1050 return flushed_ampdu;
1051 }
1052 volatile int max_aggr_num = 24;
_aggr_ampdu_tx_q(struct ieee80211_hw * hw,struct AMPDU_TID_st * ampdu_tid)1053 void _aggr_ampdu_tx_q (struct ieee80211_hw *hw, struct AMPDU_TID_st *ampdu_tid)
1054 {
1055 struct ssv_softc *sc = hw->priv;
1056 struct sk_buff *ampdu_skb = ampdu_tid->cur_ampdu_pkt;
1057 while (skb_queue_len(&du_tid->ampdu_skb_tx_queue))
1058 {
1059 u32 aggr_len;
1060 struct sk_buff *mpdu_skb;
1061 struct ampdu_hdr_st *ampdu_hdr;
1062 bool is_aggr_full = false;
1063 if (ampdu_skb == NULL)
1064 {
1065 ampdu_skb = _alloc_ampdu_skb(sc, ampdu_tid, 0);
1066 if (ampdu_skb == NULL)
1067 break;
1068 ampdu_tid->cur_ampdu_pkt = ampdu_skb;
1069 }
1070 ampdu_hdr = (struct ampdu_hdr_st *) ampdu_skb->head;
1071 aggr_len = skb_queue_len(&du_hdr->mpdu_q);
1072 do
1073 {
1074 struct sk_buff_head *tx_q = &du_tid->ampdu_skb_tx_queue;
1075 unsigned long flags;
1076 spin_lock_irqsave(&tx_q->lock, flags);
1077 mpdu_skb = skb_peek(&du_tid->ampdu_skb_tx_queue);
1078 if (mpdu_skb == NULL)
1079 {
1080 spin_unlock_irqrestore(&tx_q->lock, flags);
1081 break;
1082 }
1083 if ((mpdu_skb->len + ampdu_hdr->size) > ampdu_hdr->max_size)
1084 {
1085 is_aggr_full = true;
1086 spin_unlock_irqrestore(&tx_q->lock, flags);
1087 break;
1088 }
1089 mpdu_skb = __skb_dequeue(&du_tid->ampdu_skb_tx_queue);
1090 spin_unlock_irqrestore(&tx_q->lock, flags);
1091 _put_mpdu_to_ampdu(ampdu_skb, mpdu_skb);
1092 } while (++aggr_len < max_aggr_num );
1093 if ( (is_aggr_full || (aggr_len >= max_aggr_num))
1094 || ( (aggr_len > 0)
1095 && (skb_queue_len(&du_tid->early_aggr_ampdu_q) == 0)
1096 && (ampdu_tid->ssv_baw_head == SSV_ILLEGAL_SN)
1097 && _is_skb_q_empty(sc, ampdu_skb)))
1098 {
1099 _add_ampdu_txinfo(sc, ampdu_skb);
1100 _queue_early_ampdu(sc, ampdu_tid, ampdu_skb);
1101 ampdu_tid->cur_ampdu_pkt = ampdu_skb = NULL;
1102 }
1103 _flush_early_ampdu_q(sc, ampdu_tid);
1104 }
1105 }
_queue_early_ampdu(struct ssv_softc * sc,struct AMPDU_TID_st * ampdu_tid,struct sk_buff * ampdu_skb)1106 void _queue_early_ampdu (struct ssv_softc *sc, struct AMPDU_TID_st *ampdu_tid,
1107 struct sk_buff *ampdu_skb)
1108 {
1109 unsigned long flags;
1110 struct ampdu_hdr_st *ampdu_hdr = (struct ampdu_hdr_st *) ampdu_skb->head;
1111 spin_lock_irqsave(&du_tid->early_aggr_ampdu_q.lock, flags);
1112 __skb_queue_tail(&du_tid->early_aggr_ampdu_q, ampdu_skb);
1113 ampdu_tid->early_aggr_skb_num += skb_queue_len(&du_hdr->mpdu_q);
1114 #ifdef SSV_AMPDU_FLOW_CONTROL
1115 if (ampdu_tid->early_aggr_skb_num >= SSV_AMPDU_FLOW_CONTROL_UPPER_BOUND)
1116 {
1117 ssv6200_tx_flow_control((void *) sc, sc->tx.hw_txqid[ampdu_tid->ac],
1118 true, 1000);
1119 }
1120 #endif
1121 spin_unlock_irqrestore(&du_tid->early_aggr_ampdu_q.lock, flags);
1122 }
_flush_mpdu(struct ssv_softc * sc,struct ieee80211_sta * sta)1123 void _flush_mpdu (struct ssv_softc *sc, struct ieee80211_sta *sta)
1124 {
1125 unsigned long flags;
1126 struct ssv_sta_priv_data *ssv_sta_priv = (struct ssv_sta_priv_data *) sta->drv_priv;
1127 int i;
1128 for (i = 0; i < (sizeof(ssv_sta_priv->ampdu_tid) / sizeof(ssv_sta_priv->ampdu_tid[0])); i++)
1129 {
1130 struct AMPDU_TID_st *ampdu_tid = &ssv_sta_priv->ampdu_tid[i];
1131 struct sk_buff_head *early_aggr_ampdu_q;
1132 struct sk_buff *ampdu;
1133 struct ampdu_hdr_st *ampdu_hdr;
1134 struct sk_buff_head *mpdu_q;
1135 struct sk_buff *mpdu;
1136 if (ampdu_tid->state != AMPDU_STATE_OPERATION)
1137 continue;
1138 early_aggr_ampdu_q = &du_tid->early_aggr_ampdu_q;
1139 spin_lock_irqsave(&early_aggr_ampdu_q->lock, flags);
1140 while ((ampdu = __skb_dequeue(early_aggr_ampdu_q)) != NULL)
1141 {
1142 ampdu_hdr = (struct ampdu_hdr_st *)ampdu->head;
1143 mpdu_q = &du_hdr->mpdu_q;
1144 spin_unlock_irqrestore(&early_aggr_ampdu_q->lock, flags);
1145 while ((mpdu = __skb_dequeue(mpdu_q)) != NULL)
1146 {
1147 _send_hci_skb(sc, mpdu, AMPDU_HCI_SEND_TAIL_WITHOUT_FLOWCTRL);
1148 }
1149 ssv6200_ampdu_release_skb(ampdu, sc->hw);
1150 spin_lock_irqsave(&early_aggr_ampdu_q->lock, flags);
1151 }
1152 if (ampdu_tid->cur_ampdu_pkt != NULL)
1153 {
1154 ampdu_hdr = (struct ampdu_hdr_st *)ampdu_tid->cur_ampdu_pkt->head;
1155 mpdu_q = &du_hdr->mpdu_q;
1156 spin_unlock_irqrestore(&early_aggr_ampdu_q->lock, flags);
1157 while ((mpdu = __skb_dequeue(mpdu_q)) != NULL)
1158 {
1159 _send_hci_skb(sc, mpdu, AMPDU_HCI_SEND_TAIL_WITHOUT_FLOWCTRL);
1160 }
1161 ssv6200_ampdu_release_skb(ampdu_tid->cur_ampdu_pkt, sc->hw);
1162 spin_lock_irqsave(&early_aggr_ampdu_q->lock, flags);
1163 ampdu_tid->cur_ampdu_pkt = NULL;
1164 }
1165 spin_unlock_irqrestore(&early_aggr_ampdu_q->lock, flags);
1166 }
1167 }
ssv6200_ampdu_tx_handler(struct ieee80211_hw * hw,struct sk_buff * skb)1168 bool ssv6200_ampdu_tx_handler (struct ieee80211_hw *hw, struct sk_buff *skb)
1169 {
1170 struct ssv_softc *sc = hw->priv;
1171 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1172 #ifdef REPORT_TX_STATUS_DIRECTLY
1173 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1174 struct sk_buff *tx_skb = skb;
1175 struct sk_buff *copy_skb = NULL;
1176 #endif
1177 struct SKB_info_st *mpdu_skb_info_p = (SKB_info *) (skb->head);
1178 struct ieee80211_sta *sta = mpdu_skb_info_p->sta;
1179 struct ssv_sta_priv_data *ssv_sta_priv =
1180 (struct ssv_sta_priv_data *) sta->drv_priv;
1181 u8 tidno;
1182 struct AMPDU_TID_st *ampdu_tid;
1183 if (sta == NULL)
1184 {
1185 WARN_ON(1);
1186 return false;
1187 }
1188 tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
1189 ampdu_db_log("tidno = %d\n", tidno);
1190 ampdu_tid = &ssv_sta_priv->ampdu_tid[tidno];
1191 if (ampdu_tid->state != AMPDU_STATE_OPERATION)
1192 return false;
1193 #ifdef AMPDU_CHECK_SKB_SEQNO
1194 {
1195 u32 skb_seqno = ((struct ieee80211_hdr*) (skb->data))->seq_ctrl
1196 >> SSV_SEQ_NUM_SHIFT;
1197 u32 tid_seqno = ampdu_tid->last_seqno;
1198 if ((tid_seqno != (-1)) && (skb_seqno != NEXT_PKT_SN(tid_seqno)))
1199 {
1200 prn_aggr_err("Non continueous seq no: %d - %d\n", tid_seqno, skb_seqno);
1201 return false;
1202 }
1203 ampdu_tid->last_seqno = skb_seqno;
1204 }
1205 #endif
1206 #if 1
1207 mpdu_skb_info_p->lowest_rate = ssv62xx_ht_rate_update(skb, sc, mpdu_skb_info_p->rates);
1208 if (ampdu_max_transmit_length[mpdu_skb_info_p->lowest_rate] == 0)
1209 {
1210 _flush_mpdu(sc, sta);
1211 return false;
1212 }
1213 #endif
1214 #if 0
1215 if ((ampdu_tid->ssv_baw_head == SSV_ILLEGAL_SN)
1216 && (skb_queue_len(&du_tid->ampdu_skb_tx_queue) == 0)
1217 && (skb_queue_len(&du_tid->early_aggr_ampdu_q) == 0)
1218 && ((ampdu_tid->cur_ampdu_pkt == NULL)
1219 || (skb_queue_len(
1220 &((struct ampdu_hdr_st *) (ampdu_tid->cur_ampdu_pkt->head))->mpdu_q)
1221 == 0))
1222 && _is_skb_q_empty(sc, skb))
1223 {
1224 ampdu_tid->mib.ampdu_mib_pass_counter++;
1225 #if 0
1226 prn_aggr_err(
1227 "pass %d\n",
1228 ((struct ieee80211_hdr*)(skb->data))->seq_ctrl >> SSV_SEQ_NUM_SHIFT);
1229 #else
1230 if ((ssv_sta_priv->ampdu_tid[tidno].mib.ampdu_mib_pass_counter % 1024) == 0)
1231 prn_aggr_err("STA %d TID %d passed %d\n", ssv_sta_priv->sta_idx,
1232 ampdu_tid->tidno,
1233 ampdu_tid->mib.ampdu_mib_pass_counter);
1234 #endif
1235 return false;
1236 }
1237 #endif
1238 mpdu_skb_info_p = (SKB_info *) (skb->head);
1239 mpdu_skb_info_p->mpdu_retry_counter = 0;
1240 mpdu_skb_info_p->ampdu_tx_status = AMPDU_ST_NON_AMPDU;
1241 mpdu_skb_info_p->ampdu_tx_final_retry_count = 0;
1242 ssv_sta_priv->ampdu_tid[tidno].ac = skb_get_queue_mapping(skb);
1243 #if 0
1244 #ifndef CONFIG_SSV_SW_ENCRYPT_HW_DECRYPT
1245 if ((sc->ampdu_ccmp_encrypt == true))
1246 {
1247 skb_queue_tail(&ssv_sta_priv->ampdu_tid[tidno].ampdu_skb_wait_encry_queue, skb);
1248 if (sc->ampdu_encry_work_scheduled == false)
1249 {
1250 schedule_work(&sc->ampdu_tx_encry_work);
1251 }
1252 }
1253 else if (sc->algorithm != ME_NONE)
1254 {
1255 printk("None ccmp skb into AMPDU sc->algorithm = %d\n",sc->algorithm);
1256 info = IEEE80211_SKB_CB(skb);
1257 info->flags &= (~IEEE80211_TX_CTL_AMPDU);
1258 if(ssv6200_mpdu_send_HCI(sc->hw, skb))
1259 ieee80211_tx_status_irqsafe(sc->hw, skb);
1260 }
1261 else
1262 #endif
1263 #endif
1264 #ifdef REPORT_TX_STATUS_DIRECTLY
1265 info->flags |= IEEE80211_TX_STAT_ACK;
1266 copy_skb = skb_copy(tx_skb, GFP_ATOMIC);
1267 if (!copy_skb) {
1268 printk("create TX skb copy failed!\n");
1269 return false;
1270 }
1271 ieee80211_tx_status(sc->hw, tx_skb);
1272 skb = copy_skb;
1273 #endif
1274 {
1275 bool ret;
1276 ret = ssv6200_ampdu_add_delimiter_and_crc32(skb);
1277 if (ret == false)
1278 {
1279 ssv6200_ampdu_release_skb(skb, hw);
1280 return false;
1281 }
1282 skb_queue_tail(&ssv_sta_priv->ampdu_tid[tidno].ampdu_skb_tx_queue, skb);
1283 ssv_sta_priv->ampdu_tid[tidno].timestamp = jiffies;
1284 }
1285 _aggr_ampdu_tx_q(hw, &ssv_sta_priv->ampdu_tid[tidno]);
1286 return true;
1287 }
ssv6xxx_ampdu_flush(struct ieee80211_hw * hw)1288 u32 ssv6xxx_ampdu_flush (struct ieee80211_hw *hw)
1289 {
1290 struct ssv_softc *sc = hw->priv;
1291 struct AMPDU_TID_st *cur_AMPDU_TID;
1292 u32 flushed_ampdu = 0;
1293 u32 tid_idx = 0;
1294 if (!list_empty(&sc->tx.ampdu_tx_que))
1295 {
1296 list_for_each_entry_rcu(cur_AMPDU_TID, &sc->tx.ampdu_tx_que, list)
1297 {
1298 tid_idx++;
1299 #ifdef DEBUG_AMPDU_FLUSH
1300 {
1301 int i = 0;
1302 for (i = 0; i < MAX_TID; i++)
1303 if (sc->tid[i] == cur_AMPDU_TID)
1304 break;
1305 if (i == MAX_TID)
1306 {
1307 printk(KERN_ERR "No matching TID (%d) found! %p\n", tid_idx, cur_AMPDU_TID);
1308 continue;
1309 }
1310 }
1311 #endif
1312 if (cur_AMPDU_TID->state != AMPDU_STATE_OPERATION)
1313 {
1314 struct ieee80211_sta *sta = cur_AMPDU_TID->sta;
1315 struct ssv_sta_priv_data *sta_priv = (struct ssv_sta_priv_data *)sta->drv_priv;
1316 dev_dbg(sc->dev, "STA %d TID %d is @%d\n",
1317 sta_priv->sta_idx, cur_AMPDU_TID->tidno,
1318 cur_AMPDU_TID->state);
1319 continue;
1320 }
1321 if ((cur_AMPDU_TID->state == AMPDU_STATE_OPERATION)
1322 && (skb_queue_len(&cur_AMPDU_TID->early_aggr_ampdu_q) == 0)
1323 && (cur_AMPDU_TID->cur_ampdu_pkt != NULL))
1324 {
1325 struct ampdu_hdr_st *ampdu_hdr =
1326 (struct ampdu_hdr_st *) (cur_AMPDU_TID->cur_ampdu_pkt->head);
1327 u32 aggr_len = skb_queue_len(&du_hdr->mpdu_q);
1328 if (aggr_len)
1329 {
1330 struct sk_buff *ampdu_skb = cur_AMPDU_TID->cur_ampdu_pkt;
1331 cur_AMPDU_TID->cur_ampdu_pkt = NULL;
1332 _add_ampdu_txinfo(sc, ampdu_skb);
1333 _queue_early_ampdu(sc, cur_AMPDU_TID, ampdu_skb);
1334 #if 0
1335 prn_aggr_err("A%c %d %d\n", sc->tx_q_empty ? 'e' : 't',
1336 ampdu_hdr->first_sn, aggr_len);
1337 #endif
1338 }
1339 }
1340 if (skb_queue_len(&cur_AMPDU_TID->early_aggr_ampdu_q) > 0)
1341 flushed_ampdu += _flush_early_ampdu_q(sc, cur_AMPDU_TID);
1342 }
1343 }
1344 return flushed_ampdu;
1345 }
_dump_BA_notification(char * buf,struct ampdu_ba_notify_data * ba_notification)1346 int _dump_BA_notification (char *buf,
1347 struct ampdu_ba_notify_data *ba_notification)
1348 {
1349 int i;
1350 char *orig_buf = buf;
1351 for (i = 0; i < MAX_AGGR_NUM; i++)
1352 {
1353 if (ba_notification->seq_no[i] == (u16) (-1))
1354 break;
1355 buf += sprintf(buf, " %d", ba_notification->seq_no[i]);
1356 }
1357 return ((size_t)buf - (size_t)orig_buf);
1358 }
_dump_ba_skb(char * buf,int buf_size,struct sk_buff * ba_skb)1359 int _dump_ba_skb (char *buf, int buf_size, struct sk_buff *ba_skb)
1360 {
1361 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) (ba_skb->data
1362 + SSV6XXX_RX_DESC_LEN);
1363 AMPDU_BLOCKACK *BA_frame = (AMPDU_BLOCKACK *) hdr;
1364 u32 ssn = BA_frame->BA_ssn;
1365 struct ampdu_ba_notify_data *ba_notification =
1366 (struct ampdu_ba_notify_data *) (ba_skb->data + ba_skb->len
1367 - sizeof(struct ampdu_ba_notify_data));
1368 int prt_size;
1369 prt_size = snprintf(buf, buf_size, "\n\t\t%04d %08X %08X -",
1370 ssn, BA_frame->BA_sn_bit_map[0], BA_frame->BA_sn_bit_map[1]);
1371 buf_size -= prt_size;
1372 buf += prt_size;
1373 prt_size = prt_size + _dump_BA_notification(buf, ba_notification);
1374 return prt_size;
1375 }
_ssn_to_bit_idx(u32 start_ssn,u32 mpdu_ssn,u32 * word_idx,u32 * bit_idx)1376 static bool _ssn_to_bit_idx (u32 start_ssn, u32 mpdu_ssn, u32 *word_idx,
1377 u32 *bit_idx)
1378 {
1379 u32 ret_bit_idx, ret_word_idx = 0;
1380 s32 diff = mpdu_ssn - start_ssn;
1381 if (diff >= 0)
1382 {
1383 if (diff >= SSV_AMPDU_BA_WINDOW_SIZE)
1384 {
1385 return false;
1386 }
1387 ret_bit_idx = diff;
1388 }
1389 else
1390 {
1391 diff = -diff;
1392 if (diff <= (SSV_AMPDU_MAX_SSN - SSV_AMPDU_BA_WINDOW_SIZE))
1393 {
1394 *word_idx = 0;
1395 *bit_idx = 0;
1396 return false;
1397 }
1398 ret_bit_idx = SSV_AMPDU_MAX_SSN - diff;
1399 }
1400 if (ret_bit_idx >= 32)
1401 {
1402 ret_bit_idx -= 32;
1403 ret_word_idx = 1;
1404 }
1405 *bit_idx = ret_bit_idx;
1406 *word_idx = ret_word_idx;
1407 return true;
1408 }
_inc_bit_idx(u32 ssn_1st,u32 ssn_next,u32 * word_idx,u32 * bit_idx)1409 static bool _inc_bit_idx (u32 ssn_1st, u32 ssn_next, u32 *word_idx,
1410 u32 *bit_idx)
1411 {
1412 u32 ret_word_idx = *word_idx, ret_bit_idx = *bit_idx;
1413 s32 diff = (s32) ssn_1st - (s32) ssn_next;
1414 if (diff > 0)
1415 {
1416 if (diff < (SSV_AMPDU_MAX_SSN - SSV_AMPDU_BA_WINDOW_SIZE))
1417 {
1418 prn_aggr_err("Irrational SN distance in AMPDU: %d %d.\n",
1419 ssn_1st, ssn_next);
1420 return false;
1421 }
1422 diff = SSV_AMPDU_MAX_SSN - diff;
1423 }
1424 else
1425 {
1426 diff = -diff;
1427 }
1428 if (diff > SSV_AMPDU_MAX_SSN)
1429 prn_aggr_err("DF %d - %d = %d\n", ssn_1st, ssn_next, diff);
1430 ret_bit_idx += diff;
1431 if (ret_bit_idx >= 32)
1432 {
1433 ret_bit_idx -= 32;
1434 ret_word_idx++;
1435 }
1436 *word_idx = ret_word_idx;
1437 *bit_idx = ret_bit_idx;
1438 return true;
1439 }
_release_frames(struct AMPDU_TID_st * ampdu_tid)1440 static void _release_frames (struct AMPDU_TID_st *ampdu_tid)
1441 {
1442 u32 head_ssn, head_ssn_before, last_ssn;
1443 struct sk_buff **skb;
1444 struct SKB_info_st *skb_info;
1445 spin_lock_bh(&du_tid->pkt_array_lock);
1446 head_ssn_before = ampdu_tid->ssv_baw_head;
1447 #if 1
1448 if (head_ssn_before >= SSV_AMPDU_MAX_SSN)
1449 {
1450 spin_unlock_bh(&du_tid->pkt_array_lock);
1451 prn_aggr_err("l x.x %d\n", head_ssn_before);
1452 return;
1453 }
1454 #else
1455 BUG_ON(head_ssn_before >= SSV_AMPDU_MAX_SSN);
1456 #endif
1457 head_ssn = ampdu_tid->ssv_baw_head;
1458 last_ssn = head_ssn;
1459 do
1460 {
1461 skb = &INDEX_PKT_BY_SSN(ampdu_tid, head_ssn);
1462 if (*skb == NULL)
1463 {
1464 head_ssn = SSV_ILLEGAL_SN;
1465 {
1466 int i;
1467 char sn_str[66 * 5] = "";
1468 char *str = sn_str;
1469 for (i = 0; i < 64; i++)
1470 if (ampdu_tid->aggr_pkts[i] != NULL)
1471 {
1472 str += sprintf(str, "%d ",
1473 ampdu_skb_ssn(ampdu_tid->aggr_pkts[i]));
1474 }
1475 *str = 0;
1476 if (str == sn_str)
1477 {
1478 }
1479 else
1480 prn_aggr_err(
1481 "ILL %d %d - %d (%s)\n",
1482 head_ssn_before, last_ssn, ampdu_tid->aggr_pkt_num, sn_str);
1483 }
1484 break;
1485 }
1486 skb_info = (struct SKB_info_st *) ((*skb)->head);
1487 if ((skb_info->ampdu_tx_status == AMPDU_ST_DONE)
1488 || (skb_info->ampdu_tx_status == AMPDU_ST_DROPPED))
1489 {
1490 __skb_queue_tail(&du_tid->release_queue, *skb);
1491 *skb = NULL;
1492 last_ssn = head_ssn;
1493 INC_PKT_SN(head_ssn);
1494 ampdu_tid->aggr_pkt_num--;
1495 if (skb_info->ampdu_tx_status == AMPDU_ST_DROPPED)
1496 ampdu_tid->mib.ampdu_mib_discard_counter++;
1497 }
1498 else
1499 {
1500 break;
1501 }
1502 } while (1);
1503 ampdu_tid->ssv_baw_head = head_ssn;
1504 #if 0
1505 if (head_ssn == SSV_ILLEGAL_SN)
1506 {
1507 u32 i = head_ssn_before;
1508 do
1509 {
1510 skb = &INDEX_PKT_BY_SSN(ampdu_tid, i);
1511 if (*skb != NULL)
1512 prn_aggr_err("O.o %d: %d - %d\n", head_ssn_before, i, ampdu_skb_ssn(*skb));
1513 INC_PKT_SN(i);
1514 }while (i != head_ssn_before);
1515 }
1516 #endif
1517 spin_unlock_bh(&du_tid->pkt_array_lock);
1518 #if 0
1519 if (head_ssn_before != head_ssn)
1520 {
1521 prn_aggr_err("H %d -> %d (%d - %d)\n", head_ssn_before, head_ssn,
1522 ampdu_tid->aggr_pkt_num, skb_queue_len(&du_tid->ampdu_skb_tx_queue));
1523 }
1524 #endif
1525 }
_collect_retry_frames(struct AMPDU_TID_st * ampdu_tid)1526 static int _collect_retry_frames (struct AMPDU_TID_st *ampdu_tid)
1527 {
1528 u16 ssn, head_ssn, end_ssn;
1529 int num_retry = 0;
1530 int timeout_check = 1;
1531 unsigned long check_jiffies = jiffies;
1532 head_ssn = ampdu_tid->ssv_baw_head;
1533 ssn = head_ssn;
1534 if (ssn == SSV_ILLEGAL_SN)
1535 return 0;
1536 end_ssn = (head_ssn + SSV_AMPDU_BA_WINDOW_SIZE) % SSV_AMPDU_MAX_SSN;
1537 do
1538 {
1539 struct sk_buff *skb = INDEX_PKT_BY_SSN(ampdu_tid, ssn);
1540 struct SKB_info_st *skb_info;
1541 int timeout_retry = 0;
1542 if (skb == NULL)
1543 break;
1544 skb_info = (SKB_info *) (skb->head);
1545 if ( timeout_check
1546 && (skb_info->ampdu_tx_status == AMPDU_ST_SENT))
1547 {
1548 unsigned long cur_jiffies = jiffies;
1549 unsigned long timeout_jiffies = skb_info->aggr_timestamp
1550 + msecs_to_jiffies(BA_WAIT_TIMEOUT);
1551 u32 delta_ms;
1552 if (time_before(cur_jiffies, timeout_jiffies))
1553 {
1554 timeout_check = 0;
1555 continue;
1556 }
1557 _mark_skb_retry(skb_info, skb);
1558 delta_ms = jiffies_to_msecs(cur_jiffies - skb_info->aggr_timestamp);
1559 prn_aggr_err("t S%d-T%d-%d (%u)\n",
1560 ((struct ssv_sta_priv_data *)skb_info->sta->drv_priv)->sta_idx,
1561 ampdu_tid->tidno, ssn,
1562 delta_ms);
1563 if (delta_ms > 1000)
1564 {
1565 prn_aggr_err("Last checktime %lu - %lu = %u\n",
1566 check_jiffies, ampdu_tid->timestamp,
1567 jiffies_to_msecs(check_jiffies - ampdu_tid->timestamp));
1568 }
1569 timeout_retry = 1;
1570 }
1571 if (skb_info->ampdu_tx_status == AMPDU_ST_RETRY)
1572 {
1573 #if 0
1574 if (!timeout_retry)
1575 prn_aggr_dbg("r %d - %d\n", ssn, ampdu_skb_ssn(skb));
1576 #endif
1577 skb_queue_tail(&du_tid->retry_queue, skb);
1578 ampdu_tid->mib.ampdu_mib_retry_counter++;
1579 num_retry++;
1580 }
1581 INC_PKT_SN(ssn);
1582 } while (ssn != end_ssn);
1583 ampdu_tid->timestamp = check_jiffies;
1584 return num_retry;
1585 }
_mark_skb_retry(struct SKB_info_st * skb_info,struct sk_buff * skb)1586 int _mark_skb_retry (struct SKB_info_st *skb_info, struct sk_buff *skb)
1587 {
1588 if (skb_info->mpdu_retry_counter < SSV_AMPDU_retry_counter_max)
1589 {
1590 if (skb_info->mpdu_retry_counter == 0)
1591 {
1592 struct ieee80211_hdr *skb_hdr = ampdu_skb_hdr(skb);
1593 skb_hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
1594 }
1595 skb_info->ampdu_tx_status = AMPDU_ST_RETRY;
1596 skb_info->mpdu_retry_counter++;
1597 return 1;
1598 }
1599 else
1600 {
1601 skb_info->ampdu_tx_status = AMPDU_ST_DROPPED;
1602 prn_aggr_err("p %d\n", ampdu_skb_ssn(skb));
1603 return 0;
1604 }
1605 }
_ba_map_walker(struct AMPDU_TID_st * ampdu_tid,u32 start_ssn,u32 sn_bit_map[2],struct ampdu_ba_notify_data * ba_notify_data,u32 * p_acked_num)1606 static u32 _ba_map_walker (struct AMPDU_TID_st *ampdu_tid, u32 start_ssn,
1607 u32 sn_bit_map[2],
1608 struct ampdu_ba_notify_data *ba_notify_data,
1609 u32 *p_acked_num)
1610 {
1611 int i = 0;
1612 u32 ssn = ba_notify_data->seq_no[0];
1613 u32 word_idx = (-1), bit_idx = (-1);
1614 bool found = _ssn_to_bit_idx(start_ssn, ssn, &word_idx, &bit_idx);
1615 bool first_found = found;
1616 u32 aggr_num = 0;
1617 u32 acked_num = 0;
1618 if (found && (word_idx >= 2 || bit_idx >= 32))
1619 prn_aggr_err("idx error 1: %d %d %d %d\n",
1620 start_ssn, ssn, word_idx, bit_idx);
1621 while ((i < MAX_AGGR_NUM) && (ssn < SSV_AMPDU_MAX_SSN))
1622 {
1623 u32 cur_ssn;
1624 struct sk_buff *skb = INDEX_PKT_BY_SSN(ampdu_tid, ssn);
1625 u32 skb_ssn = (skb == NULL) ? (-1) : ampdu_skb_ssn(skb);
1626 struct SKB_info_st *skb_info;
1627 aggr_num++;
1628 if (skb_ssn != ssn)
1629 {
1630 prn_aggr_err("Unmatched SSN packet: %d - %d - %d\n",
1631 ssn, skb_ssn, start_ssn);
1632 }
1633 else
1634 {
1635 skb_info = (struct SKB_info_st *) (skb->head);
1636 if (found && (sn_bit_map[word_idx] & (1 << bit_idx)))
1637 {
1638 if (skb_info->ampdu_tx_status != AMPDU_ST_SENT)
1639 {
1640 printk(KERN_ERR "BA marks a MPDU of status %d!\n",
1641 skb_info->ampdu_tx_status);
1642 }
1643 skb_info->ampdu_tx_status = AMPDU_ST_DONE;
1644 acked_num++;
1645 }
1646 else
1647 {
1648 _mark_skb_retry(skb_info, skb);
1649 }
1650 }
1651 cur_ssn = ssn;
1652 if (++i >= MAX_AGGR_NUM)
1653 break;
1654 ssn = ba_notify_data->seq_no[i];
1655 if (ssn >= SSV_AMPDU_MAX_SSN)
1656 break;
1657 if (first_found)
1658 {
1659 u32 old_word_idx = word_idx, old_bit_idx = bit_idx;
1660 found = _inc_bit_idx(cur_ssn, ssn, &word_idx, &bit_idx);
1661 if (found && (word_idx >= 2 || bit_idx >= 32))
1662 {
1663 prn_aggr_err(
1664 "idx error 2: %d 0x%08X 0X%08X %d %d (%d %d) (%d %d)\n",
1665 start_ssn, sn_bit_map[1], sn_bit_map[0], cur_ssn, ssn, word_idx, bit_idx, old_word_idx, old_bit_idx);
1666 found = false;
1667 }
1668 else if (!found)
1669 {
1670 char strbuf[256];
1671 _dump_BA_notification(strbuf, ba_notify_data);
1672 prn_aggr_err("SN out-of-order: %d\n%s\n", start_ssn, strbuf);
1673 }
1674 }
1675 else
1676 {
1677 found = _ssn_to_bit_idx(start_ssn, ssn, &word_idx, &bit_idx);
1678 first_found = found;
1679 if (found && (word_idx >= 2 || bit_idx >= 32))
1680 prn_aggr_err("idx error 3: %d %d %d %d\n",
1681 cur_ssn, ssn, word_idx, bit_idx);
1682 }
1683 }
1684 _release_frames(ampdu_tid);
1685 if (p_acked_num != NULL)
1686 *p_acked_num = acked_num;
1687 return aggr_num;
1688 }
_flush_release_queue(struct ieee80211_hw * hw,struct sk_buff_head * release_queue)1689 static void _flush_release_queue (struct ieee80211_hw *hw,
1690 struct sk_buff_head *release_queue)
1691 {
1692 do
1693 {
1694 struct sk_buff *ampdu_skb = __skb_dequeue(release_queue);
1695 struct ieee80211_tx_info *tx_info;
1696 struct SKB_info_st *skb_info;
1697 if (ampdu_skb == NULL)
1698 break;
1699 skb_info = (struct SKB_info_st *) (ampdu_skb->head);
1700 skb_pull(ampdu_skb, AMPDU_DELIMITER_LEN);
1701 tx_info = IEEE80211_SKB_CB(ampdu_skb);
1702 ieee80211_tx_info_clear_status(tx_info);
1703 tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
1704 if (skb_info->ampdu_tx_status == AMPDU_ST_DONE)
1705 tx_info->flags |= IEEE80211_TX_STAT_ACK;
1706 tx_info->status.ampdu_len = 1;
1707 tx_info->status.ampdu_ack_len = 1;
1708 #ifdef REPORT_TX_STATUS_DIRECTLY
1709 dev_kfree_skb_any(ampdu_skb);
1710 #else
1711 #if defined(USE_THREAD_RX) && !defined(IRQ_PROC_TX_DATA)
1712 ieee80211_tx_status(hw, ampdu_skb);
1713 #else
1714 ieee80211_tx_status_irqsafe(hw, ampdu_skb);
1715 #endif
1716 #endif
1717 } while (1);
1718 }
1719 #if 0
1720 static u16 _get_BA_notification_hits(u16 ssn,u32 *bit_map,struct ampdu_ba_notify_data *ba_notification,u16 *max_continue_hits,u16 *aggr_num)
1721 {
1722 int i;
1723 u16 hits=0,continue_hits=0;
1724 u64 bitMap=0;
1725 if(bit_map)
1726 bitMap = ((u64)bit_map[1]<<32) | (u64)(bit_map[0]);
1727 for (i = 0; i < MAX_AGGR_NUM; i++)
1728 {
1729 if (ba_notification->seq_no[i] == (u16)(-1))
1730 break;
1731 if(ssn <= ba_notification->seq_no[i])
1732 {
1733 if((bitMap>>(ba_notification->seq_no[i]-ssn))&0x1)
1734 {
1735 hits++;
1736 continue_hits++;
1737 if(*max_continue_hits<=continue_hits)
1738 *max_continue_hits = continue_hits;
1739 }
1740 else
1741 {
1742 continue_hits=0;
1743 }
1744 }
1745 }
1746 *aggr_num = i;
1747 return hits;
1748 }
1749 #endif
ssv6200_ampdu_no_BA_handler(struct ieee80211_hw * hw,struct sk_buff * skb)1750 void ssv6200_ampdu_no_BA_handler (struct ieee80211_hw *hw, struct sk_buff *skb)
1751 {
1752 struct cfg_host_event *host_event = (struct cfg_host_event *) skb->data;
1753 struct ampdu_ba_notify_data *ba_notification =
1754 (struct ampdu_ba_notify_data *) &host_event->dat[0];
1755 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) (ba_notification + 1);
1756 struct ssv_softc *sc = hw->priv;
1757 struct ieee80211_sta *sta = ssv6xxx_find_sta_by_addr(sc, hdr->addr1);
1758 u8 tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
1759 struct ssv_sta_priv_data *ssv_sta_priv;
1760 char seq_str[256];
1761 struct AMPDU_TID_st *ampdu_tid;
1762 int i;
1763 u16 aggr_num = 0;
1764 struct firmware_rate_control_report_data *report_data;
1765 if (sta == NULL)
1766 {
1767 prn_aggr_err(
1768 "NO BA for %d to unmatched STA %02X-%02X-%02X-%02X-%02X-%02X: %s\n",
1769 tidno, hdr->addr1[0], hdr->addr1[1], hdr->addr1[2], hdr->addr1[3], hdr->addr1[4], hdr->addr1[5], seq_str);
1770 dev_kfree_skb_any(skb);
1771 return;
1772 }
1773 ssv_sta_priv = (struct ssv_sta_priv_data *) sta->drv_priv;
1774 _dump_BA_notification(seq_str, ba_notification);
1775 prn_aggr_err(
1776 "NO BA for %d to %02X-%02X-%02X-%02X-%02X-%02X: %s\n",
1777 tidno, sta->addr[0], sta->addr[1], sta->addr[2], sta->addr[3], sta->addr[4], sta->addr[5], seq_str);
1778 ampdu_tid = &ssv_sta_priv->ampdu_tid[tidno];
1779 if (ampdu_tid->state != AMPDU_STATE_OPERATION)
1780 {
1781 dev_kfree_skb_any(skb);
1782 return;
1783 }
1784 for (i = 0; i < MAX_AGGR_NUM; i++)
1785 {
1786 u32 ssn = ba_notification->seq_no[i];
1787 struct sk_buff *skb;
1788 u32 skb_ssn;
1789 struct SKB_info_st *skb_info;
1790 if (ssn >= (4096))
1791 break;
1792 aggr_num++;
1793 skb = INDEX_PKT_BY_SSN(ampdu_tid, ssn);
1794 skb_ssn = (skb == NULL) ? (-1) : ampdu_skb_ssn(skb);
1795 if (skb_ssn != ssn)
1796 {
1797 prn_aggr_err("Unmatched SSN packet: %d - %d\n", ssn, skb_ssn);
1798 continue;
1799 }
1800 skb_info = (struct SKB_info_st *) (skb->head);
1801 if (skb_info->ampdu_tx_status == AMPDU_ST_SENT)
1802 {
1803 if (skb_info->mpdu_retry_counter < SSV_AMPDU_retry_counter_max)
1804 {
1805 if (skb_info->mpdu_retry_counter == 0)
1806 {
1807 struct ieee80211_hdr *skb_hdr = ampdu_skb_hdr(skb);
1808 skb_hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
1809 }
1810 skb_info->ampdu_tx_status = AMPDU_ST_RETRY;
1811 skb_info->mpdu_retry_counter++;
1812 }
1813 else
1814 {
1815 skb_info->ampdu_tx_status = AMPDU_ST_DROPPED;
1816 prn_aggr_err("p %d\n", skb_ssn);
1817 }
1818 }
1819 else
1820 {
1821 prn_aggr_err("S %d %d\n", skb_ssn, skb_info->ampdu_tx_status);
1822 }
1823 }
1824 _release_frames(ampdu_tid);
1825 host_event->h_event = SOC_EVT_RC_AMPDU_REPORT;
1826 report_data =
1827 (struct firmware_rate_control_report_data *) &host_event->dat[0];
1828 report_data->ampdu_len = aggr_num;
1829 report_data->ampdu_ack_len = 0;
1830 report_data->wsid = ssv_sta_priv->sta_info->hw_wsid;
1831 #if 0
1832 printk("AMPDU report NO BA!!wsid[%d]didx[%d]F[%d]R[%d]S[%d]\n",report_data->wsid,report_data->data_rate,report_data->mpduFrames,report_data->mpduFrameRetry,report_data->mpduFrameSuccess);
1833 #endif
1834 skb_queue_tail(&sc->rc_report_queue, skb);
1835 if (sc->rc_sample_sechedule == 0)
1836 queue_work(sc->rc_sample_workqueue, &sc->rc_sample_work);
1837 }
ssv6200_ampdu_BA_handler(struct ieee80211_hw * hw,struct sk_buff * skb)1838 void ssv6200_ampdu_BA_handler (struct ieee80211_hw *hw, struct sk_buff *skb)
1839 {
1840 struct ssv_softc *sc = hw->priv;
1841 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) (skb->data
1842 + SSV6XXX_RX_DESC_LEN);
1843 AMPDU_BLOCKACK *BA_frame = (AMPDU_BLOCKACK *) hdr;
1844 struct ieee80211_sta *sta;
1845 struct ssv_sta_priv_data *ssv_sta_priv;
1846 struct ampdu_ba_notify_data *ba_notification;
1847 u32 ssn, aggr_num = 0, acked_num = 0;
1848 u8 tid_no;
1849 u32 sn_bit_map[2];
1850 struct firmware_rate_control_report_data *report_data;
1851 HDR_HostEvent *host_evt;
1852 sta = ssv6xxx_find_sta_by_rx_skb(sc, skb);
1853 if (sta == NULL)
1854 {
1855 if (skb->len > AMPDU_BA_FRAME_LEN)
1856 {
1857 char strbuf[256];
1858 struct ampdu_ba_notify_data *ba_notification =
1859 (struct ampdu_ba_notify_data *) (skb->data + skb->len
1860 - sizeof(struct ampdu_ba_notify_data));
1861 _dump_BA_notification(strbuf, ba_notification);
1862 prn_aggr_err("BA from not connected STA (%02X-%02X-%02X-%02X-%02X-%02X) (%s)\n",
1863 BA_frame->ta_addr[0], BA_frame->ta_addr[1], BA_frame->ta_addr[2],
1864 BA_frame->ta_addr[3], BA_frame->ta_addr[4], BA_frame->ta_addr[5], strbuf);
1865 }
1866 dev_kfree_skb_any(skb);
1867 return;
1868 }
1869 ssv_sta_priv = (struct ssv_sta_priv_data *) sta->drv_priv;
1870 ssn = BA_frame->BA_ssn;
1871 sn_bit_map[0] = BA_frame->BA_sn_bit_map[0];
1872 sn_bit_map[1] = BA_frame->BA_sn_bit_map[1];
1873 tid_no = BA_frame->tid_info;
1874 ssv_sta_priv->ampdu_mib_total_BA_counter++;
1875 if (ssv_sta_priv->ampdu_tid[tid_no].state == AMPDU_STATE_STOP)
1876 {
1877 prn_aggr_err("ssv6200_ampdu_BA_handler state == AMPDU_STATE_STOP.\n");
1878 dev_kfree_skb_any(skb);
1879 return;
1880 }
1881 ssv_sta_priv->ampdu_tid[tid_no].mib.ampdu_mib_BA_counter++;
1882 if (skb->len <= AMPDU_BA_FRAME_LEN)
1883 {
1884 prn_aggr_err("b %d\n", ssn);
1885 dev_kfree_skb_any(skb);
1886 return;
1887 }
1888 ba_notification =
1889 (struct ampdu_ba_notify_data *) (skb->data + skb->len
1890 - sizeof(struct ampdu_ba_notify_data));
1891 #if 0
1892 if (1)
1893 {
1894 char strbuf[256];
1895 _dump_BA_notification(strbuf, ba_notification);
1896 prn_aggr_err("B %d %08X %08X: %s\n", ssn, sn_bit_map[0], sn_bit_map[1], strbuf);
1897 }
1898 #endif
1899 aggr_num = _ba_map_walker(&(ssv_sta_priv->ampdu_tid[tid_no]), ssn,
1900 sn_bit_map, ba_notification, &acked_num);
1901 #ifdef CONFIG_SSV6XXX_DEBUGFS
1902 if (ssv_sta_priv->ampdu_tid[tid_no].debugfs_dir)
1903 {
1904 struct sk_buff *dup_skb;
1905 if (skb_queue_len(&ssv_sta_priv->ampdu_tid[tid_no].ba_q) > 24)
1906 {
1907 struct sk_buff *ba_skb = skb_dequeue(&ssv_sta_priv->ampdu_tid[tid_no].ba_q);
1908 if (ba_skb)
1909 dev_kfree_skb_any(ba_skb);
1910 }
1911 dup_skb = skb_clone(skb, GFP_ATOMIC);
1912 if (dup_skb)
1913 skb_queue_tail(&ssv_sta_priv->ampdu_tid[tid_no].ba_q, dup_skb);
1914 }
1915 #endif
1916 skb_trim(skb, skb->len - sizeof(struct ampdu_ba_notify_data));
1917 #if 0
1918 total_debug_count++;
1919 if (ba_notification_hits != ba_notification_aggr_num)
1920 printk("rate[%d] firmware retry [%d] agg nums[%d] hits[%d] continue_hits[%d] \n",ba_notification.data_rate,ba_notification.retry_count,ba_notification_aggr_num,ba_notification_hits,ba_notification_continue_hits);
1921 else
1922 {
1923 if (ba_notification.retry_count==0)
1924 total_perfect_debug_count++;
1925 else
1926 total_perfect_debug_count_but_firmware_retry++;
1927 }
1928 if ((total_debug_count % 2000) == 0)
1929 {
1930 printk("Percentage %d/2000\n",total_perfect_debug_count);
1931 printk("firmware retry [%d] no BA[%d]\n",total_perfect_debug_count_but_firmware_retry,no_ba_debug_count);
1932 total_debug_count = 0;
1933 total_perfect_debug_count_but_firmware_retry=0;
1934 total_perfect_debug_count = 0;
1935 no_ba_debug_count = 0;
1936 }
1937 #endif
1938 host_evt = (HDR_HostEvent *) skb->data;
1939 host_evt->h_event = SOC_EVT_RC_AMPDU_REPORT;
1940 report_data =
1941 (struct firmware_rate_control_report_data *) &host_evt->dat[0];
1942 memcpy(report_data, ba_notification,
1943 sizeof(struct firmware_rate_control_report_data));
1944 report_data->ampdu_len = aggr_num;
1945 report_data->ampdu_ack_len = acked_num;
1946 #ifdef RATE_CONTROL_HT_PERCENTAGE_TRACE
1947 if((acked_num) && (acked_num != aggr_num))
1948 {
1949 int i;
1950 for (i = 0; i < SSV62XX_TX_MAX_RATES ; i++) {
1951 if(report_data->rates[i].data_rate == -1)
1952 break;
1953 if(report_data->rates[i].count == 0) {
1954 printk("*********************************\n");
1955 printk(" Illegal HT report \n");
1956 printk("*********************************\n");
1957 }
1958 printk(" i=[%d] rate[%d] count[%d]\n",i,report_data->rates[i].data_rate,report_data->rates[i].count);
1959 }
1960 printk("AMPDU percentage = %d%% \n",acked_num*100/aggr_num);
1961 }
1962 else if(acked_num == 0)
1963 {
1964 printk("AMPDU percentage = 0%% aggr_num=%d acked_num=%d\n",aggr_num,acked_num);
1965 }
1966 #endif
1967 skb_queue_tail(&sc->rc_report_queue, skb);
1968 if (sc->rc_sample_sechedule == 0)
1969 queue_work(sc->rc_sample_workqueue, &sc->rc_sample_work);
1970 }
_postprocess_BA(struct ssv_softc * sc,struct ssv_sta_info * sta_info,void * param)1971 static void _postprocess_BA (struct ssv_softc *sc, struct ssv_sta_info *sta_info, void *param)
1972 {
1973 int j;
1974 struct ssv_sta_priv_data *ssv_sta_priv;
1975 if ( (sta_info->sta == NULL)
1976 || ((sta_info->s_flags & STA_FLAG_VALID) == 0))
1977 return;
1978 ssv_sta_priv = (struct ssv_sta_priv_data *) sta_info->sta->drv_priv;
1979 for (j = 0; j < WMM_TID_NUM; j++)
1980 {
1981 AMPDU_TID *ampdu_tid = &ssv_sta_priv->ampdu_tid[j];
1982 if (ampdu_tid->state != AMPDU_STATE_OPERATION)
1983 continue;
1984 _collect_retry_frames(ampdu_tid);
1985 ssv6200_ampdu_send_retry(sc->hw, ampdu_tid, &du_tid->retry_queue,
1986 true);
1987 _flush_early_ampdu_q(sc, ampdu_tid);
1988 _flush_release_queue(sc->hw, &du_tid->release_queue);
1989 }
1990 }
ssv6xxx_ampdu_postprocess_BA(struct ieee80211_hw * hw)1991 void ssv6xxx_ampdu_postprocess_BA (struct ieee80211_hw *hw)
1992 {
1993 struct ssv_softc *sc = hw->priv;
1994 ssv6xxx_foreach_sta(sc, _postprocess_BA, NULL);
1995 }
ssv6200_hw_set_rx_ba_session(struct ssv_hw * sh,bool on,u8 * ta,u16 tid,u16 ssn,u8 buf_size)1996 static void ssv6200_hw_set_rx_ba_session (struct ssv_hw *sh, bool on, u8 *ta,
1997 u16 tid, u16 ssn, u8 buf_size)
1998 {
1999 if (on)
2000 {
2001 u32 u32ta;
2002 u32ta = 0;
2003 u32ta |= (ta[0] & 0xff) << (8 * 0);
2004 u32ta |= (ta[1] & 0xff) << (8 * 1);
2005 u32ta |= (ta[2] & 0xff) << (8 * 2);
2006 u32ta |= (ta[3] & 0xff) << (8 * 3);
2007 SMAC_REG_WRITE(sh, ADR_BA_TA_0, u32ta);
2008 u32ta = 0;
2009 u32ta |= (ta[4] & 0xff) << (8 * 0);
2010 u32ta |= (ta[5] & 0xff) << (8 * 1);
2011 SMAC_REG_WRITE(sh, ADR_BA_TA_1, u32ta);
2012 SMAC_REG_WRITE(sh, ADR_BA_TID, tid);
2013 SMAC_REG_WRITE(sh, ADR_BA_ST_SEQ, ssn);
2014 SMAC_REG_WRITE(sh, ADR_BA_SB0, 0);
2015 SMAC_REG_WRITE(sh, ADR_BA_SB1, 0);
2016 SMAC_REG_WRITE(sh, ADR_BA_CTRL, 0xb);
2017 }
2018 else
2019 {
2020 SMAC_REG_WRITE(sh, ADR_BA_CTRL, 0x0);
2021 }
2022 }
ssv6xxx_set_ampdu_rx_add_work(struct work_struct * work)2023 void ssv6xxx_set_ampdu_rx_add_work (struct work_struct *work)
2024 {
2025 struct ssv_softc
2026 *sc = container_of(work, struct ssv_softc, set_ampdu_rx_add_work);
2027 ssv6200_hw_set_rx_ba_session(sc->sh, true, sc->ba_ra_addr, sc->ba_tid,
2028 sc->ba_ssn, 64);
2029 }
ssv6xxx_set_ampdu_rx_del_work(struct work_struct * work)2030 void ssv6xxx_set_ampdu_rx_del_work (struct work_struct *work)
2031 {
2032 struct ssv_softc*sc = container_of(work, struct ssv_softc,
2033 set_ampdu_rx_del_work);
2034 u8 addr[6] = { 0 };
2035 ssv6200_hw_set_rx_ba_session(sc->sh, false, addr, 0, 0, 0);
2036 }
_reset_ampdu_mib(struct ssv_softc * sc,struct ssv_sta_info * sta_info,void * param)2037 static void _reset_ampdu_mib (struct ssv_softc *sc, struct ssv_sta_info *sta_info, void *param)
2038 {
2039 struct ieee80211_sta *sta = sta_info->sta;
2040 struct ssv_sta_priv_data *ssv_sta_priv;
2041 int i;
2042 ssv_sta_priv = (struct ssv_sta_priv_data *)sta->drv_priv;
2043 for (i = 0; i < WMM_TID_NUM; i++)
2044 {
2045 ssv_sta_priv->ampdu_tid[i].ampdu_mib_reset = 1;
2046 }
2047 }
ssv6xxx_ampdu_mib_reset(struct ieee80211_hw * hw)2048 void ssv6xxx_ampdu_mib_reset (struct ieee80211_hw *hw)
2049 {
2050 struct ssv_softc *sc = hw->priv;
2051 if (sc == NULL)
2052 return;
2053 ssv6xxx_foreach_sta(sc, _reset_ampdu_mib, NULL);
2054 }
2055 #ifdef CONFIG_SSV6XXX_DEBUGFS
ampdu_tx_mib_dump(struct ssv_sta_priv_data * ssv_sta_priv,char * mib_str,ssize_t length)2056 ssize_t ampdu_tx_mib_dump (struct ssv_sta_priv_data *ssv_sta_priv,
2057 char *mib_str, ssize_t length)
2058 {
2059 ssize_t buf_size = length;
2060 ssize_t prt_size;
2061 int j;
2062 struct ssv_sta_info *ssv_sta = ssv_sta_priv->sta_info;
2063 if (ssv_sta->sta == NULL)
2064 {
2065 prt_size = snprintf(mib_str, buf_size, "\n NULL STA.\n");
2066 mib_str += prt_size;
2067 buf_size -= prt_size;
2068 goto mib_dump_exit;
2069 }
2070 for (j = 0; j < WMM_TID_NUM; j++)
2071 {
2072 int k;
2073 struct AMPDU_TID_st *ampdu_tid = &ssv_sta_priv->ampdu_tid[j];
2074 struct AMPDU_MIB_st *ampdu_mib = &du_tid->mib;
2075 prt_size = snprintf(mib_str, buf_size, "\n WMM_TID %d@%d\n", j,
2076 ampdu_tid->state);
2077 mib_str += prt_size;
2078 buf_size -= prt_size;
2079 if (ampdu_tid->state != AMPDU_STATE_OPERATION)
2080 continue;
2081 prt_size = snprintf(mib_str, buf_size, " BA window size: %d\n",
2082 ampdu_tid->ssv_baw_size);
2083 mib_str += prt_size;
2084 buf_size -= prt_size;
2085 prt_size = snprintf(mib_str, buf_size, " BA window head: %d\n",
2086 ampdu_tid->ssv_baw_head);
2087 mib_str += prt_size;
2088 buf_size -= prt_size;
2089 prt_size = snprintf(mib_str, buf_size,
2090 " Sending aggregated #: %d\n",
2091 ampdu_tid->aggr_pkt_num);
2092 mib_str += prt_size;
2093 buf_size -= prt_size;
2094 prt_size = snprintf(
2095 mib_str, buf_size, " Waiting #: %d\n",
2096 skb_queue_len(&du_tid->ampdu_skb_tx_queue));
2097 mib_str += prt_size;
2098 buf_size -= prt_size;
2099 prt_size = snprintf(mib_str, buf_size, " Early aggregated %d\n",
2100 ampdu_tid->early_aggr_skb_num);
2101 mib_str += prt_size;
2102 buf_size -= prt_size;
2103 prt_size = snprintf(mib_str, buf_size,
2104 " MPDU: %d\n",
2105 ampdu_mib->ampdu_mib_mpdu_counter);
2106 mib_str += prt_size;
2107 buf_size -= prt_size;
2108 prt_size = snprintf(mib_str, buf_size,
2109 " Passed: %d\n", ampdu_mib->ampdu_mib_pass_counter);
2110 mib_str += prt_size;
2111 buf_size -= prt_size;
2112 prt_size = snprintf(mib_str, buf_size,
2113 " Retry: %d\n",
2114 ampdu_mib->ampdu_mib_retry_counter);
2115 mib_str += prt_size;
2116 buf_size -= prt_size;
2117 prt_size = snprintf(mib_str, buf_size,
2118 " AMPDU: %d\n",
2119 ampdu_mib->ampdu_mib_ampdu_counter);
2120 mib_str += prt_size;
2121 buf_size -= prt_size;
2122 prt_size = snprintf(mib_str, buf_size,
2123 " Retry AMPDU: %d\n",
2124 ampdu_mib->ampdu_mib_aggr_retry_counter);
2125 mib_str += prt_size;
2126 buf_size -= prt_size;
2127 prt_size = snprintf(mib_str, buf_size,
2128 " BAR count: %d\n",
2129 ampdu_mib->ampdu_mib_bar_counter);
2130 mib_str += prt_size;
2131 buf_size -= prt_size;
2132 prt_size = snprintf(mib_str, buf_size,
2133 " Discard count: %d\n",
2134 ampdu_mib->ampdu_mib_discard_counter);
2135 mib_str += prt_size;
2136 buf_size -= prt_size;
2137 prt_size = snprintf(mib_str, buf_size,
2138 " BA count: %d\n",
2139 ampdu_mib->ampdu_mib_BA_counter);
2140 mib_str += prt_size;
2141 buf_size -= prt_size;
2142 prt_size = snprintf(mib_str, buf_size, " Total BA count: %d\n",
2143 ssv_sta_priv->ampdu_mib_total_BA_counter);
2144 mib_str += prt_size;
2145 buf_size -= prt_size;
2146 prt_size = snprintf(mib_str, buf_size, " Aggr # count:\n");
2147 mib_str += prt_size;
2148 buf_size -= prt_size;
2149 for (k = 0; k <= SSV_AMPDU_aggr_num_max; k++)
2150 {
2151 prt_size = snprintf(mib_str, buf_size, " %d: %d\n", k,
2152 ampdu_mib->ampdu_mib_dist[k]);
2153 mib_str += prt_size;
2154 buf_size -= prt_size;
2155 }
2156 }
2157 mib_dump_exit:
2158 return (length - buf_size);
2159 }
_dump_ampdu_mib(struct ssv_softc * sc,struct ssv_sta_info * sta_info,void * param)2160 static void _dump_ampdu_mib (struct ssv_softc *sc, struct ssv_sta_info *sta_info, void *param)
2161 {
2162 struct mib_dump_data *dump_data = (struct mib_dump_data *)param;
2163 struct ieee80211_sta *sta;
2164 struct ssv_sta_priv_data *ssv_sta_priv;
2165 ssize_t buf_size;
2166 ssize_t prt_size;
2167 char *mib_str = dump_data->prt_buff;
2168 if (param == NULL)
2169 return;
2170 buf_size = dump_data->buff_size - 1;
2171 sta = sta_info->sta;
2172 if ((sta == NULL) || ((sta_info->s_flags & STA_FLAG_VALID) == 0))
2173 return;
2174 prt_size = snprintf(mib_str, buf_size,
2175 "STA: %02X-%02X-%02X-%02X-%02X-%02X:\n",
2176 sta->addr[0], sta->addr[1], sta->addr[2],
2177 sta->addr[3], sta->addr[4], sta->addr[5]);
2178 mib_str += prt_size;
2179 buf_size -= prt_size;
2180 ssv_sta_priv = (struct ssv_sta_priv_data *) sta->drv_priv;
2181 prt_size = ampdu_tx_mib_dump(ssv_sta_priv, mib_str, buf_size);
2182 mib_str += prt_size;
2183 buf_size -= prt_size;
2184 dump_data->prt_len = (dump_data->buff_size - 1 - buf_size);
2185 dump_data->prt_buff = mib_str;
2186 dump_data->buff_size = buf_size;
2187 }
ssv6xxx_ampdu_mib_dump(struct ieee80211_hw * hw,char * mib_str,ssize_t length)2188 ssize_t ssv6xxx_ampdu_mib_dump (struct ieee80211_hw *hw, char *mib_str,
2189 ssize_t length)
2190 {
2191 struct ssv_softc *sc = hw->priv;
2192 ssize_t buf_size = length - 1;
2193 struct mib_dump_data dump_data = {mib_str, buf_size, 0};
2194 if (sc == NULL)
2195 return 0;
2196 ssv6xxx_foreach_sta(sc, _dump_ampdu_mib, &dump_data);
2197 return dump_data.prt_len;
2198 }
2199 #endif
_alloc_ampdu_skb(struct ssv_softc * sc,struct AMPDU_TID_st * ampdu_tid,u32 len)2200 struct sk_buff *_alloc_ampdu_skb (struct ssv_softc *sc, struct AMPDU_TID_st *ampdu_tid, u32 len)
2201 {
2202 unsigned char *payload_addr;
2203 u32 headroom = sc->hw->extra_tx_headroom;
2204 u32 offset;
2205 u32 cur_max_ampdu_size = SSV_GET_MAX_AMPDU_SIZE(sc->sh);
2206 u32 extra_room = sc->sh->tx_desc_len * 2 + 48;
2207 u32 max_physical_len = (len && ((len + extra_room) < cur_max_ampdu_size))
2208 ? (len + extra_room)
2209 : cur_max_ampdu_size;
2210 u32 skb_len = max_physical_len + headroom + 3;
2211 struct sk_buff *ampdu_skb = __dev_alloc_skb(skb_len, GFP_KERNEL);
2212 struct ampdu_hdr_st *ampdu_hdr;
2213 if (ampdu_skb == NULL)
2214 {
2215 dev_err(sc->dev, "AMPDU allocation of size %d(%d) failed\n", len, skb_len);
2216 return NULL;
2217 }
2218 payload_addr = ampdu_skb->data + headroom - sc->sh->tx_desc_len;
2219 offset = ((size_t) payload_addr) % 4U;
2220 if (offset)
2221 {
2222 printk(KERN_ERR "Align AMPDU data %d\n", offset);
2223 skb_reserve(ampdu_skb, headroom + 4 - offset);
2224 }
2225 else
2226 skb_reserve(ampdu_skb, headroom);
2227 ampdu_hdr = (struct ampdu_hdr_st *) ampdu_skb->head;
2228 skb_queue_head_init(&du_hdr->mpdu_q);
2229 ampdu_hdr->max_size = max_physical_len - extra_room;
2230 ampdu_hdr->size = 0;
2231 ampdu_hdr->ampdu_tid = ampdu_tid;
2232 memset(ampdu_hdr->ssn, 0xFF, sizeof(ampdu_hdr->ssn));
2233 ampdu_hdr->mpdu_num = 0;
2234 return ampdu_skb;
2235 }
_is_skb_q_empty(struct ssv_softc * sc,struct sk_buff * skb)2236 bool _is_skb_q_empty (struct ssv_softc *sc, struct sk_buff *skb)
2237 {
2238 u32 ac = skb_get_queue_mapping(skb);
2239 u32 hw_txqid = sc->tx.hw_txqid[ac];
2240 return AMPDU_HCI_Q_EMPTY(sc->sh, hw_txqid);
2241 }
_check_timeout(struct AMPDU_TID_st * ampdu_tid)2242 static u32 _check_timeout (struct AMPDU_TID_st *ampdu_tid)
2243 {
2244 u16 ssn, head_ssn, end_ssn;
2245 unsigned long check_jiffies = jiffies;
2246 u32 has_retry = 0;
2247 head_ssn = ampdu_tid->ssv_baw_head;
2248 ssn = head_ssn;
2249 if (ssn == SSV_ILLEGAL_SN)
2250 return 0;
2251 end_ssn = (head_ssn + SSV_AMPDU_BA_WINDOW_SIZE)% SSV_AMPDU_MAX_SSN;
2252 do {
2253 struct sk_buff *skb = INDEX_PKT_BY_SSN(ampdu_tid, ssn);
2254 struct SKB_info_st *skb_info;
2255 unsigned long cur_jiffies;
2256 unsigned long timeout_jiffies;
2257 u32 delta_ms;
2258 if (skb == NULL)
2259 break;
2260 skb_info = (SKB_info *) (skb->head);
2261 cur_jiffies = jiffies;
2262 timeout_jiffies = skb_info->aggr_timestamp + msecs_to_jiffies(BA_WAIT_TIMEOUT);
2263 if ( (skb_info->ampdu_tx_status != AMPDU_ST_SENT)
2264 || time_before(cur_jiffies, timeout_jiffies))
2265 break;
2266 delta_ms = jiffies_to_msecs(cur_jiffies - skb_info->aggr_timestamp);
2267 prn_aggr_err("rt S%d-T%d-%d (%u)\n",
2268 ((struct ssv_sta_priv_data *)skb_info->sta->drv_priv)->sta_idx,
2269 ampdu_tid->tidno, ssn,
2270 delta_ms);
2271 if (delta_ms > 1000)
2272 {
2273 prn_aggr_err("Last checktime %lu - %lu = %u\n",
2274 check_jiffies, ampdu_tid->timestamp,
2275 jiffies_to_msecs(check_jiffies - ampdu_tid->timestamp));
2276 }
2277 has_retry += _mark_skb_retry(skb_info, skb);
2278 INC_PKT_SN(ssn);
2279 } while (ssn != end_ssn);
2280 ampdu_tid->timestamp = check_jiffies;
2281 return has_retry;
2282 }
ssv6xxx_ampdu_check_timeout(struct ieee80211_hw * hw)2283 void ssv6xxx_ampdu_check_timeout (struct ieee80211_hw *hw)
2284 {
2285 struct ssv_softc *sc = hw->priv;
2286 struct AMPDU_TID_st *cur_AMPDU_TID;
2287 if (!list_empty(&sc->tx.ampdu_tx_que))
2288 {
2289 list_for_each_entry_rcu(cur_AMPDU_TID, &sc->tx.ampdu_tx_que, list)
2290 {
2291 u32 has_retry;
2292 if (cur_AMPDU_TID->state != AMPDU_STATE_OPERATION)
2293 continue;
2294 has_retry = _check_timeout(cur_AMPDU_TID);
2295 if (has_retry)
2296 {
2297 _collect_retry_frames(cur_AMPDU_TID);
2298 ssv6200_ampdu_send_retry(sc->hw, cur_AMPDU_TID, &cur_AMPDU_TID->retry_queue,
2299 true);
2300 }
2301 }
2302 }
2303 }
ssv6xxx_ampdu_sent(struct ieee80211_hw * hw,struct sk_buff * ampdu)2304 void ssv6xxx_ampdu_sent(struct ieee80211_hw *hw, struct sk_buff *ampdu)
2305 {
2306 struct ssv_softc *sc = hw->priv;
2307 struct ampdu_hdr_st *ampdu_hdr = (struct ampdu_hdr_st *) ampdu->head;
2308 struct sk_buff *mpdu;
2309 unsigned long cur_jiffies = jiffies;
2310 int i;
2311 SKB_info *mpdu_skb_info;
2312 u16 ssn;
2313 if (ampdu_hdr->ampdu_tid->state != AMPDU_STATE_OPERATION)
2314 return;
2315 spin_lock_bh(&du_hdr->ampdu_tid->pkt_array_lock);
2316 for (i = 0; i < ampdu_hdr->mpdu_num; i++)
2317 {
2318 ssn = ampdu_hdr->ssn[i];
2319 mpdu = INDEX_PKT_BY_SSN(ampdu_hdr->ampdu_tid, ssn);
2320 if (mpdu == NULL)
2321 {
2322 dev_err(sc->dev, "T%d-%d is a NULL MPDU.\n",
2323 ampdu_hdr->ampdu_tid->tidno, ssn);
2324 continue;
2325 }
2326 if (ampdu_skb_ssn(mpdu) != ssn)
2327 {
2328 dev_err(sc->dev, "T%d-%d does not match %d MPDU.\n",
2329 ampdu_hdr->ampdu_tid->tidno, ssn, ampdu_skb_ssn(mpdu));
2330 continue;
2331 }
2332 mpdu_skb_info = (SKB_info *) (mpdu->head);
2333 mpdu_skb_info->aggr_timestamp = cur_jiffies;
2334 mpdu_skb_info->ampdu_tx_status = AMPDU_ST_SENT;
2335 }
2336 spin_unlock_bh(&du_hdr->ampdu_tid->pkt_array_lock);
2337 }
2338