1
2#include "ieee80211.h"
3#include <linux/etherdevice.h>
4#include <linux/slab.h>
5#include "rtl819x_TS.h"
6
7static void TsSetupTimeOut(struct timer_list *unused)
8{
9
10
11}
12
13static void TsInactTimeout(struct timer_list *unused)
14{
15
16
17
18}
19
20
21
22
23
24
25
26static void RxPktPendingTimeout(struct timer_list *t)
27{
28 struct rx_ts_record *pRxTs = from_timer(pRxTs, t, rx_pkt_pending_timer);
29 struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
30
31 struct rx_reorder_entry *pReorderEntry = NULL;
32
33
34 unsigned long flags = 0;
35 u8 index = 0;
36 bool bPktInBuf = false;
37
38 spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
39 IEEE80211_DEBUG(IEEE80211_DL_REORDER, "==================>%s()\n", __func__);
40 if (pRxTs->rx_timeout_indicate_seq != 0xffff) {
41
42 while (!list_empty(&pRxTs->rx_pending_pkt_list)) {
43 pReorderEntry = list_entry(pRxTs->rx_pending_pkt_list.prev, struct rx_reorder_entry, List);
44 if (index == 0)
45 pRxTs->rx_indicate_seq = pReorderEntry->SeqNum;
46
47 if (SN_LESS(pReorderEntry->SeqNum, pRxTs->rx_indicate_seq) ||
48 SN_EQUAL(pReorderEntry->SeqNum, pRxTs->rx_indicate_seq)) {
49 list_del_init(&pReorderEntry->List);
50
51 if (SN_EQUAL(pReorderEntry->SeqNum, pRxTs->rx_indicate_seq))
52 pRxTs->rx_indicate_seq = (pRxTs->rx_indicate_seq + 1) % 4096;
53
54 IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s: IndicateSeq: %d\n", __func__, pReorderEntry->SeqNum);
55 ieee->stats_IndicateArray[index] = pReorderEntry->prxb;
56 index++;
57
58 list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List);
59 } else {
60 bPktInBuf = true;
61 break;
62 }
63 }
64 }
65
66 if (index > 0) {
67
68 pRxTs->rx_timeout_indicate_seq = 0xffff;
69
70
71 if (index > REORDER_WIN_SIZE) {
72 IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorder buffer full!! \n");
73 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
74 return;
75 }
76 ieee80211_indicate_packets(ieee, ieee->stats_IndicateArray, index);
77 }
78
79 if (bPktInBuf && (pRxTs->rx_timeout_indicate_seq == 0xffff)) {
80 pRxTs->rx_timeout_indicate_seq = pRxTs->rx_indicate_seq;
81 mod_timer(&pRxTs->rx_pkt_pending_timer,
82 jiffies + msecs_to_jiffies(ieee->pHTInfo->RxReorderPendingTime));
83 }
84 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
85}
86
87
88
89
90
91
92
93static void TsAddBaProcess(struct timer_list *t)
94{
95 struct tx_ts_record *pTxTs = from_timer(pTxTs, t, ts_add_ba_timer);
96 u8 num = pTxTs->num;
97 struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[num]);
98
99 TsInitAddBA(ieee, pTxTs, BA_POLICY_IMMEDIATE, false);
100 IEEE80211_DEBUG(IEEE80211_DL_BA, "%s: ADDBA Req is started!! \n", __func__);
101}
102
103
104static void ResetTsCommonInfo(struct ts_common_info *pTsCommonInfo)
105{
106 eth_zero_addr(pTsCommonInfo->addr);
107 memset(&pTsCommonInfo->t_spec, 0, sizeof(struct tspec_body));
108 memset(&pTsCommonInfo->t_class, 0, sizeof(union qos_tclas) * TCLAS_NUM);
109 pTsCommonInfo->t_clas_proc = 0;
110 pTsCommonInfo->t_clas_num = 0;
111}
112
113static void ResetTxTsEntry(struct tx_ts_record *pTS)
114{
115 ResetTsCommonInfo(&pTS->ts_common_info);
116 pTS->tx_cur_seq = 0;
117 pTS->add_ba_req_in_progress = false;
118 pTS->add_ba_req_delayed = false;
119 pTS->using_ba = false;
120 ResetBaEntry(&pTS->tx_admitted_ba_record);
121 ResetBaEntry(&pTS->tx_pending_ba_record);
122}
123
124static void ResetRxTsEntry(struct rx_ts_record *pTS)
125{
126 ResetTsCommonInfo(&pTS->ts_common_info);
127 pTS->rx_indicate_seq = 0xffff;
128 pTS->rx_timeout_indicate_seq = 0xffff;
129 ResetBaEntry(&pTS->rx_admitted_ba_record);
130}
131
132void TSInitialize(struct ieee80211_device *ieee)
133{
134 struct tx_ts_record *pTxTS = ieee->TxTsRecord;
135 struct rx_ts_record *pRxTS = ieee->RxTsRecord;
136 struct rx_reorder_entry *pRxReorderEntry = ieee->RxReorderEntry;
137 u8 count = 0;
138 IEEE80211_DEBUG(IEEE80211_DL_TS, "==========>%s()\n", __func__);
139
140 INIT_LIST_HEAD(&ieee->Tx_TS_Admit_List);
141 INIT_LIST_HEAD(&ieee->Tx_TS_Pending_List);
142 INIT_LIST_HEAD(&ieee->Tx_TS_Unused_List);
143
144 for (count = 0; count < TOTAL_TS_NUM; count++) {
145
146 pTxTS->num = count;
147
148
149 timer_setup(&pTxTS->ts_common_info.setup_timer, TsSetupTimeOut,
150 0);
151 timer_setup(&pTxTS->ts_common_info.inact_timer, TsInactTimeout,
152 0);
153 timer_setup(&pTxTS->ts_add_ba_timer, TsAddBaProcess, 0);
154 timer_setup(&pTxTS->tx_pending_ba_record.timer, BaSetupTimeOut,
155 0);
156 timer_setup(&pTxTS->tx_admitted_ba_record.timer,
157 TxBaInactTimeout, 0);
158 ResetTxTsEntry(pTxTS);
159 list_add_tail(&pTxTS->ts_common_info.list, &ieee->Tx_TS_Unused_List);
160 pTxTS++;
161 }
162
163
164 INIT_LIST_HEAD(&ieee->Rx_TS_Admit_List);
165 INIT_LIST_HEAD(&ieee->Rx_TS_Pending_List);
166 INIT_LIST_HEAD(&ieee->Rx_TS_Unused_List);
167 for (count = 0; count < TOTAL_TS_NUM; count++) {
168 pRxTS->num = count;
169 INIT_LIST_HEAD(&pRxTS->rx_pending_pkt_list);
170 timer_setup(&pRxTS->ts_common_info.setup_timer, TsSetupTimeOut,
171 0);
172 timer_setup(&pRxTS->ts_common_info.inact_timer, TsInactTimeout,
173 0);
174 timer_setup(&pRxTS->rx_admitted_ba_record.timer,
175 RxBaInactTimeout, 0);
176 timer_setup(&pRxTS->rx_pkt_pending_timer, RxPktPendingTimeout, 0);
177 ResetRxTsEntry(pRxTS);
178 list_add_tail(&pRxTS->ts_common_info.list, &ieee->Rx_TS_Unused_List);
179 pRxTS++;
180 }
181
182 INIT_LIST_HEAD(&ieee->RxReorder_Unused_List);
183 for (count = 0; count < REORDER_ENTRY_NUM; count++) {
184 list_add_tail(&pRxReorderEntry->List, &ieee->RxReorder_Unused_List);
185 if (count == (REORDER_ENTRY_NUM - 1))
186 break;
187 pRxReorderEntry = &ieee->RxReorderEntry[count + 1];
188 }
189}
190
191static void AdmitTS(struct ieee80211_device *ieee,
192 struct ts_common_info *pTsCommonInfo, u32 InactTime)
193{
194 del_timer_sync(&pTsCommonInfo->setup_timer);
195 del_timer_sync(&pTsCommonInfo->inact_timer);
196
197 if (InactTime != 0)
198 mod_timer(&pTsCommonInfo->inact_timer,
199 jiffies + msecs_to_jiffies(InactTime));
200}
201
202
203static struct ts_common_info *SearchAdmitTRStream(struct ieee80211_device *ieee,
204 u8 *Addr, u8 TID,
205 enum tr_select TxRxSelect)
206{
207
208 u8 dir;
209 bool search_dir[4] = {0};
210 struct list_head *psearch_list;
211 struct ts_common_info *pRet = NULL;
212 if (ieee->iw_mode == IW_MODE_MASTER) {
213 if (TxRxSelect == TX_DIR) {
214 search_dir[DIR_DOWN] = true;
215 search_dir[DIR_BI_DIR] = true;
216 } else {
217 search_dir[DIR_UP] = true;
218 search_dir[DIR_BI_DIR] = true;
219 }
220 } else if (ieee->iw_mode == IW_MODE_ADHOC) {
221 if (TxRxSelect == TX_DIR)
222 search_dir[DIR_UP] = true;
223 else
224 search_dir[DIR_DOWN] = true;
225 } else {
226 if (TxRxSelect == TX_DIR) {
227 search_dir[DIR_UP] = true;
228 search_dir[DIR_BI_DIR] = true;
229 search_dir[DIR_DIRECT] = true;
230 } else {
231 search_dir[DIR_DOWN] = true;
232 search_dir[DIR_BI_DIR] = true;
233 search_dir[DIR_DIRECT] = true;
234 }
235 }
236
237 if (TxRxSelect == TX_DIR)
238 psearch_list = &ieee->Tx_TS_Admit_List;
239 else
240 psearch_list = &ieee->Rx_TS_Admit_List;
241
242
243 for (dir = 0; dir <= DIR_BI_DIR; dir++) {
244 if (!search_dir[dir])
245 continue;
246 list_for_each_entry(pRet, psearch_list, list) {
247
248 if (memcmp(pRet->addr, Addr, 6) == 0)
249 if (pRet->t_spec.ts_info.uc_tsid == TID)
250 if (pRet->t_spec.ts_info.uc_direction == dir) {
251
252 break;
253 }
254 }
255 if (&pRet->list != psearch_list)
256 break;
257 }
258
259 if (&pRet->list != psearch_list)
260 return pRet;
261 else
262 return NULL;
263}
264
265static void MakeTSEntry(struct ts_common_info *pTsCommonInfo, u8 *Addr,
266 struct tspec_body *pTSPEC, union qos_tclas *pTCLAS, u8 TCLAS_Num,
267 u8 TCLAS_Proc)
268{
269 u8 count;
270
271 if (pTsCommonInfo == NULL)
272 return;
273
274 memcpy(pTsCommonInfo->addr, Addr, 6);
275
276 if (pTSPEC != NULL)
277 memcpy((u8 *)(&(pTsCommonInfo->t_spec)), (u8 *)pTSPEC, sizeof(struct tspec_body));
278
279 for (count = 0; count < TCLAS_Num; count++)
280 memcpy((u8 *)(&(pTsCommonInfo->t_class[count])), (u8 *)pTCLAS, sizeof(union qos_tclas));
281
282 pTsCommonInfo->t_clas_proc = TCLAS_Proc;
283 pTsCommonInfo->t_clas_num = TCLAS_Num;
284}
285
286
287bool GetTs(
288 struct ieee80211_device *ieee,
289 struct ts_common_info **ppTS,
290 u8 *Addr,
291 u8 TID,
292 enum tr_select TxRxSelect,
293 bool bAddNewTs
294 )
295{
296 u8 UP = 0;
297
298
299
300
301 if (is_multicast_ether_addr(Addr)) {
302 IEEE80211_DEBUG(IEEE80211_DL_ERR, "get TS for Broadcast or Multicast\n");
303 return false;
304 }
305
306 if (ieee->current_network.qos_data.supported == 0) {
307 UP = 0;
308 } else {
309
310 if (!is_ac_valid(TID)) {
311 IEEE80211_DEBUG(IEEE80211_DL_ERR, " in %s(), TID(%d) is not valid\n", __func__, TID);
312 return false;
313 }
314
315 switch (TID) {
316 case 0:
317 case 3:
318 UP = 0;
319 break;
320
321 case 1:
322 case 2:
323 UP = 2;
324 break;
325
326 case 4:
327 case 5:
328 UP = 5;
329 break;
330
331 case 6:
332 case 7:
333 UP = 7;
334 break;
335 }
336 }
337
338 *ppTS = SearchAdmitTRStream(
339 ieee,
340 Addr,
341 UP,
342 TxRxSelect);
343 if (*ppTS != NULL) {
344 return true;
345 } else {
346 if (!bAddNewTs) {
347 IEEE80211_DEBUG(IEEE80211_DL_TS, "add new TS failed(tid:%d)\n", UP);
348 return false;
349 } else {
350
351
352
353
354
355 struct tspec_body TSpec;
356 struct qos_tsinfo *pTSInfo = &TSpec.ts_info;
357 struct list_head *pUnusedList =
358 (TxRxSelect == TX_DIR) ?
359 (&ieee->Tx_TS_Unused_List) :
360 (&ieee->Rx_TS_Unused_List);
361
362 struct list_head *pAddmitList =
363 (TxRxSelect == TX_DIR) ?
364 (&ieee->Tx_TS_Admit_List) :
365 (&ieee->Rx_TS_Admit_List);
366
367 enum direction_value Dir = (ieee->iw_mode == IW_MODE_MASTER) ?
368 ((TxRxSelect == TX_DIR) ? DIR_DOWN : DIR_UP) :
369 ((TxRxSelect == TX_DIR) ? DIR_UP : DIR_DOWN);
370 IEEE80211_DEBUG(IEEE80211_DL_TS, "to add Ts\n");
371 if (!list_empty(pUnusedList)) {
372 (*ppTS) = list_entry(pUnusedList->next, struct ts_common_info, list);
373 list_del_init(&(*ppTS)->list);
374 if (TxRxSelect == TX_DIR) {
375 struct tx_ts_record *tmp = container_of(*ppTS, struct tx_ts_record, ts_common_info);
376 ResetTxTsEntry(tmp);
377 } else {
378 struct rx_ts_record *tmp = container_of(*ppTS, struct rx_ts_record, ts_common_info);
379 ResetRxTsEntry(tmp);
380 }
381
382 IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:%pM\n", UP, Dir, Addr);
383
384 pTSInfo->uc_traffic_type = 0;
385 pTSInfo->uc_tsid = UP;
386 pTSInfo->uc_direction = Dir;
387 pTSInfo->uc_access_policy = 1;
388 pTSInfo->uc_aggregation = 0;
389 pTSInfo->uc_psb = 0;
390 pTSInfo->uc_up = UP;
391 pTSInfo->uc_ts_info_ack_policy = 0;
392 pTSInfo->uc_schedule = 0;
393
394 MakeTSEntry(*ppTS, Addr, &TSpec, NULL, 0, 0);
395 AdmitTS(ieee, *ppTS, 0);
396 list_add_tail(&((*ppTS)->list), pAddmitList);
397
398
399 return true;
400 } else {
401 IEEE80211_DEBUG(IEEE80211_DL_ERR, "in function %s() There is not enough TS record to be used!!", __func__);
402 return false;
403 }
404 }
405 }
406}
407
408static void RemoveTsEntry(struct ieee80211_device *ieee, struct ts_common_info *pTs,
409 enum tr_select TxRxSelect)
410{
411
412 unsigned long flags = 0;
413 del_timer_sync(&pTs->setup_timer);
414 del_timer_sync(&pTs->inact_timer);
415 TsInitDelBA(ieee, pTs, TxRxSelect);
416
417 if (TxRxSelect == RX_DIR) {
418 struct rx_reorder_entry *pRxReorderEntry;
419 struct rx_ts_record *pRxTS = (struct rx_ts_record *)pTs;
420 if (timer_pending(&pRxTS->rx_pkt_pending_timer))
421 del_timer_sync(&pRxTS->rx_pkt_pending_timer);
422
423 while (!list_empty(&pRxTS->rx_pending_pkt_list)) {
424 spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
425
426 pRxReorderEntry = list_entry(pRxTS->rx_pending_pkt_list.prev, struct rx_reorder_entry, List);
427 list_del_init(&pRxReorderEntry->List);
428 {
429 int i = 0;
430 struct ieee80211_rxb *prxb = pRxReorderEntry->prxb;
431 if (unlikely(!prxb)) {
432 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
433 return;
434 }
435 for (i = 0; i < prxb->nr_subframes; i++)
436 dev_kfree_skb(prxb->subframes[i]);
437
438 kfree(prxb);
439 prxb = NULL;
440 }
441 list_add_tail(&pRxReorderEntry->List, &ieee->RxReorder_Unused_List);
442 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
443 }
444
445 } else {
446 struct tx_ts_record *pTxTS = (struct tx_ts_record *)pTs;
447 del_timer_sync(&pTxTS->ts_add_ba_timer);
448 }
449}
450
451void RemovePeerTS(struct ieee80211_device *ieee, u8 *Addr)
452{
453 struct ts_common_info *pTS, *pTmpTS;
454
455 printk("===========>%s,%pM\n", __func__, Addr);
456 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, list) {
457 if (memcmp(pTS->addr, Addr, 6) == 0) {
458 RemoveTsEntry(ieee, pTS, TX_DIR);
459 list_del_init(&pTS->list);
460 list_add_tail(&pTS->list, &ieee->Tx_TS_Unused_List);
461 }
462 }
463
464 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, list) {
465 if (memcmp(pTS->addr, Addr, 6) == 0) {
466 printk("====>remove Tx_TS_admin_list\n");
467 RemoveTsEntry(ieee, pTS, TX_DIR);
468 list_del_init(&pTS->list);
469 list_add_tail(&pTS->list, &ieee->Tx_TS_Unused_List);
470 }
471 }
472
473 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, list) {
474 if (memcmp(pTS->addr, Addr, 6) == 0) {
475 RemoveTsEntry(ieee, pTS, RX_DIR);
476 list_del_init(&pTS->list);
477 list_add_tail(&pTS->list, &ieee->Rx_TS_Unused_List);
478 }
479 }
480
481 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, list) {
482 if (memcmp(pTS->addr, Addr, 6) == 0) {
483 RemoveTsEntry(ieee, pTS, RX_DIR);
484 list_del_init(&pTS->list);
485 list_add_tail(&pTS->list, &ieee->Rx_TS_Unused_List);
486 }
487 }
488}
489
490void RemoveAllTS(struct ieee80211_device *ieee)
491{
492 struct ts_common_info *pTS, *pTmpTS;
493
494 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, list) {
495 RemoveTsEntry(ieee, pTS, TX_DIR);
496 list_del_init(&pTS->list);
497 list_add_tail(&pTS->list, &ieee->Tx_TS_Unused_List);
498 }
499
500 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, list) {
501 RemoveTsEntry(ieee, pTS, TX_DIR);
502 list_del_init(&pTS->list);
503 list_add_tail(&pTS->list, &ieee->Tx_TS_Unused_List);
504 }
505
506 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, list) {
507 RemoveTsEntry(ieee, pTS, RX_DIR);
508 list_del_init(&pTS->list);
509 list_add_tail(&pTS->list, &ieee->Rx_TS_Unused_List);
510 }
511
512 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, list) {
513 RemoveTsEntry(ieee, pTS, RX_DIR);
514 list_del_init(&pTS->list);
515 list_add_tail(&pTS->list, &ieee->Rx_TS_Unused_List);
516 }
517}
518
519void TsStartAddBaProcess(struct ieee80211_device *ieee, struct tx_ts_record *pTxTS)
520{
521 if (!pTxTS->add_ba_req_in_progress) {
522 pTxTS->add_ba_req_in_progress = true;
523 if (pTxTS->add_ba_req_delayed) {
524 IEEE80211_DEBUG(IEEE80211_DL_BA, "%s: Delayed Start ADDBA after 60 sec!!\n", __func__);
525 mod_timer(&pTxTS->ts_add_ba_timer,
526 jiffies + msecs_to_jiffies(TS_ADDBA_DELAY));
527 } else {
528 IEEE80211_DEBUG(IEEE80211_DL_BA, "%s: Immediately Start ADDBA now!!\n", __func__);
529 mod_timer(&pTxTS->ts_add_ba_timer, jiffies + 10);
530 }
531 } else {
532 IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s()==>BA timer is already added\n", __func__);
533 }
534}
535