]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
networking: make skb_put & friends return void pointers
[mirror_ubuntu-artful-kernel.git] / drivers / staging / rtl8192u / ieee80211 / rtl819x_BAProc.c
1 /********************************************************************************************************************************
2 * This file is created to process BA Action Frame. According to 802.11 spec, there are 3 BA action types at all. And as BA is
3 * related to TS, this part need some structure defined in QOS side code. Also TX RX is going to be resturctured, so how to send
4 * ADDBAREQ ADDBARSP and DELBA packet is still on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue.
5 * WB 2008-05-27
6 * *****************************************************************************************************************************/
7 #include <asm/byteorder.h>
8 #include <asm/unaligned.h>
9 #include "ieee80211.h"
10 #include "rtl819x_BA.h"
11
12 /********************************************************************************************************************
13 *function: Activate BA entry. And if Time is nozero, start timer.
14 * input: PBA_RECORD pBA //BA entry to be enabled
15 * u16 Time //indicate time delay.
16 * output: none
17 ********************************************************************************************************************/
18 static void ActivateBAEntry(struct ieee80211_device *ieee, PBA_RECORD pBA, u16 Time)
19 {
20 pBA->bValid = true;
21 if(Time != 0)
22 mod_timer(&pBA->Timer, jiffies + msecs_to_jiffies(Time));
23 }
24
25 /********************************************************************************************************************
26 *function: deactivate BA entry, including its timer.
27 * input: PBA_RECORD pBA //BA entry to be disabled
28 * output: none
29 ********************************************************************************************************************/
30 static void DeActivateBAEntry(struct ieee80211_device *ieee, PBA_RECORD pBA)
31 {
32 pBA->bValid = false;
33 del_timer_sync(&pBA->Timer);
34 }
35 /********************************************************************************************************************
36 *function: deactivete BA entry in Tx Ts, and send DELBA.
37 * input:
38 * PTX_TS_RECORD pTxTs //Tx Ts which is to deactivate BA entry.
39 * output: none
40 * notice: As PTX_TS_RECORD structure will be defined in QOS, so wait to be merged. //FIXME
41 ********************************************************************************************************************/
42 static u8 TxTsDeleteBA(struct ieee80211_device *ieee, PTX_TS_RECORD pTxTs)
43 {
44 PBA_RECORD pAdmittedBa = &pTxTs->TxAdmittedBARecord; //These two BA entries must exist in TS structure
45 PBA_RECORD pPendingBa = &pTxTs->TxPendingBARecord;
46 u8 bSendDELBA = false;
47
48 // Delete pending BA
49 if (pPendingBa->bValid) {
50 DeActivateBAEntry(ieee, pPendingBa);
51 bSendDELBA = true;
52 }
53
54 // Delete admitted BA
55 if (pAdmittedBa->bValid) {
56 DeActivateBAEntry(ieee, pAdmittedBa);
57 bSendDELBA = true;
58 }
59
60 return bSendDELBA;
61 }
62
63 /********************************************************************************************************************
64 *function: deactivete BA entry in Tx Ts, and send DELBA.
65 * input:
66 * PRX_TS_RECORD pRxTs //Rx Ts which is to deactivate BA entry.
67 * output: none
68 * notice: As PRX_TS_RECORD structure will be defined in QOS, so wait to be merged. //FIXME, same with above
69 ********************************************************************************************************************/
70 static u8 RxTsDeleteBA(struct ieee80211_device *ieee, PRX_TS_RECORD pRxTs)
71 {
72 PBA_RECORD pBa = &pRxTs->RxAdmittedBARecord;
73 u8 bSendDELBA = false;
74
75 if (pBa->bValid) {
76 DeActivateBAEntry(ieee, pBa);
77 bSendDELBA = true;
78 }
79
80 return bSendDELBA;
81 }
82
83 /********************************************************************************************************************
84 *function: reset BA entry
85 * input:
86 * PBA_RECORD pBA //entry to be reset
87 * output: none
88 ********************************************************************************************************************/
89 void ResetBaEntry(PBA_RECORD pBA)
90 {
91 pBA->bValid = false;
92 pBA->BaParamSet.shortData = 0;
93 pBA->BaTimeoutValue = 0;
94 pBA->DialogToken = 0;
95 pBA->BaStartSeqCtrl.ShortData = 0;
96 }
97 //These functions need porting here or not?
98 /*******************************************************************************************************************************
99 *function: construct ADDBAREQ and ADDBARSP frame here together.
100 * input: u8* Dst //ADDBA frame's destination
101 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA.
102 * u16 StatusCode //status code in RSP and I will use it to indicate whether it's RSP or REQ(will I?)
103 * u8 type //indicate whether it's RSP(ACT_ADDBARSP) ow REQ(ACT_ADDBAREQ)
104 * output: none
105 * return: sk_buff* skb //return constructed skb to xmit
106 *******************************************************************************************************************************/
107 static struct sk_buff *ieee80211_ADDBA(struct ieee80211_device *ieee, u8 *Dst, PBA_RECORD pBA, u16 StatusCode, u8 type)
108 {
109 struct sk_buff *skb = NULL;
110 struct rtl_80211_hdr_3addr *BAReq = NULL;
111 u8 *tag = NULL;
112 u16 len = ieee->tx_headroom + 9;
113 //category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) + BA Timeout Value(2) + BA Start SeqCtrl(2)(or StatusCode(2))
114 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __func__, type, Dst, ieee->dev);
115 if (pBA == NULL) {
116 IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA is NULL\n");
117 return NULL;
118 }
119 skb = dev_alloc_skb(len + sizeof( struct rtl_80211_hdr_3addr)); //need to add something others? FIXME
120 if (!skb) {
121 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
122 return NULL;
123 }
124
125 memset(skb->data, 0, sizeof( struct rtl_80211_hdr_3addr)); //I wonder whether it's necessary. Apparently kernel will not do it when alloc a skb.
126 skb_reserve(skb, ieee->tx_headroom);
127
128 BAReq = skb_put(skb, sizeof(struct rtl_80211_hdr_3addr));
129
130 memcpy(BAReq->addr1, Dst, ETH_ALEN);
131 memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN);
132
133 memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
134
135 BAReq->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
136
137 //tag += sizeof( struct rtl_80211_hdr_3addr); //move to action field
138 tag = skb_put(skb, 9);
139 *tag ++= ACT_CAT_BA;
140 *tag ++= type;
141 // Dialog Token
142 *tag ++= pBA->DialogToken;
143
144 if (ACT_ADDBARSP == type) {
145 // Status Code
146 printk(KERN_INFO "=====>to send ADDBARSP\n");
147
148 put_unaligned_le16(StatusCode, tag);
149 tag += 2;
150 }
151 // BA Parameter Set
152
153 put_unaligned_le16(pBA->BaParamSet.shortData, tag);
154 tag += 2;
155 // BA Timeout Value
156
157 put_unaligned_le16(pBA->BaTimeoutValue, tag);
158 tag += 2;
159
160 if (ACT_ADDBAREQ == type) {
161 // BA Start SeqCtrl
162 memcpy(tag, (u8 *)&(pBA->BaStartSeqCtrl), 2);
163 tag += 2;
164 }
165
166 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
167 return skb;
168 //return NULL;
169 }
170
171
172 /********************************************************************************************************************
173 *function: construct DELBA frame
174 * input: u8* dst //DELBA frame's destination
175 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA
176 * TR_SELECT TxRxSelect //TX RX direction
177 * u16 ReasonCode //status code.
178 * output: none
179 * return: sk_buff* skb //return constructed skb to xmit
180 ********************************************************************************************************************/
181 static struct sk_buff *ieee80211_DELBA(
182 struct ieee80211_device *ieee,
183 u8 *dst,
184 PBA_RECORD pBA,
185 TR_SELECT TxRxSelect,
186 u16 ReasonCode
187 )
188 {
189 DELBA_PARAM_SET DelbaParamSet;
190 struct sk_buff *skb = NULL;
191 struct rtl_80211_hdr_3addr *Delba = NULL;
192 u8 *tag = NULL;
193 //len = head len + DELBA Parameter Set(2) + Reason Code(2)
194 u16 len = 6 + ieee->tx_headroom;
195
196 if (net_ratelimit())
197 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:%pM\n", __func__, ReasonCode, dst);
198
199 memset(&DelbaParamSet, 0, 2);
200
201 DelbaParamSet.field.Initiator = (TxRxSelect==TX_DIR)?1:0;
202 DelbaParamSet.field.TID = pBA->BaParamSet.field.TID;
203
204 skb = dev_alloc_skb(len + sizeof( struct rtl_80211_hdr_3addr)); //need to add something others? FIXME
205 if (!skb) {
206 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
207 return NULL;
208 }
209 // memset(skb->data, 0, len+sizeof( struct rtl_80211_hdr_3addr));
210 skb_reserve(skb, ieee->tx_headroom);
211
212 Delba = skb_put(skb, sizeof(struct rtl_80211_hdr_3addr));
213
214 memcpy(Delba->addr1, dst, ETH_ALEN);
215 memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
216 memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
217 Delba->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
218
219 tag = skb_put(skb, 6);
220
221 *tag ++= ACT_CAT_BA;
222 *tag ++= ACT_DELBA;
223
224 // DELBA Parameter Set
225
226 put_unaligned_le16(DelbaParamSet.shortData, tag);
227 tag += 2;
228 // Reason Code
229
230 put_unaligned_le16(ReasonCode, tag);
231 tag += 2;
232
233 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
234 if (net_ratelimit())
235 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "<=====%s()\n", __func__);
236 return skb;
237 }
238
239 /********************************************************************************************************************
240 *function: send ADDBAReq frame out
241 * input: u8* dst //ADDBAReq frame's destination
242 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA
243 * output: none
244 * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
245 ********************************************************************************************************************/
246 static void ieee80211_send_ADDBAReq(struct ieee80211_device *ieee,
247 u8 *dst, PBA_RECORD pBA)
248 {
249 struct sk_buff *skb;
250 skb = ieee80211_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); //construct ACT_ADDBAREQ frames so set statuscode zero.
251
252 if (skb) {
253 softmac_mgmt_xmit(skb, ieee);
254 //add statistic needed here.
255 //and skb will be freed in softmac_mgmt_xmit(), so omit all dev_kfree_skb_any() outside softmac_mgmt_xmit()
256 //WB
257 }
258 else {
259 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __func__);
260 }
261 }
262
263 /********************************************************************************************************************
264 *function: send ADDBARSP frame out
265 * input: u8* dst //DELBA frame's destination
266 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA
267 * u16 StatusCode //RSP StatusCode
268 * output: none
269 * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
270 ********************************************************************************************************************/
271 static void ieee80211_send_ADDBARsp(struct ieee80211_device *ieee, u8 *dst,
272 PBA_RECORD pBA, u16 StatusCode)
273 {
274 struct sk_buff *skb;
275 skb = ieee80211_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); //construct ACT_ADDBARSP frames
276 if (skb) {
277 softmac_mgmt_xmit(skb, ieee);
278 //same above
279 }
280 else {
281 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __func__);
282 }
283
284 return;
285
286 }
287 /********************************************************************************************************************
288 *function: send ADDBARSP frame out
289 * input: u8* dst //DELBA frame's destination
290 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA
291 * TR_SELECT TxRxSelect //TX or RX
292 * u16 ReasonCode //DEL ReasonCode
293 * output: none
294 * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
295 ********************************************************************************************************************/
296
297 static void ieee80211_send_DELBA(struct ieee80211_device *ieee, u8 *dst,
298 PBA_RECORD pBA, TR_SELECT TxRxSelect,
299 u16 ReasonCode)
300 {
301 struct sk_buff *skb;
302 skb = ieee80211_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode); //construct ACT_ADDBARSP frames
303 if (skb) {
304 softmac_mgmt_xmit(skb, ieee);
305 //same above
306 }
307 else {
308 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __func__);
309 }
310 }
311
312 /********************************************************************************************************************
313 *function: RX ADDBAReq
314 * input: struct sk_buff * skb //incoming ADDBAReq skb.
315 * return: 0(pass), other(fail)
316 * notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
317 ********************************************************************************************************************/
318 int ieee80211_rx_ADDBAReq(struct ieee80211_device *ieee, struct sk_buff *skb)
319 {
320 struct rtl_80211_hdr_3addr *req = NULL;
321 u16 rc = 0;
322 u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
323 PBA_RECORD pBA = NULL;
324 PBA_PARAM_SET pBaParamSet = NULL;
325 u16 *pBaTimeoutVal = NULL;
326 PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL;
327 PRX_TS_RECORD pTS = NULL;
328
329 if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 9) {
330 IEEE80211_DEBUG(IEEE80211_DL_ERR,
331 " Invalid skb len in BAREQ(%d / %zu)\n",
332 skb->len,
333 (sizeof(struct rtl_80211_hdr_3addr) + 9));
334 return -1;
335 }
336
337 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
338
339 req = (struct rtl_80211_hdr_3addr *) skb->data;
340 tag = (u8 *)req;
341 dst = &req->addr2[0];
342 tag += sizeof(struct rtl_80211_hdr_3addr);
343 pDialogToken = tag + 2; //category+action
344 pBaParamSet = (PBA_PARAM_SET)(tag + 3); //+DialogToken
345 pBaTimeoutVal = (u16 *)(tag + 5);
346 pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
347
348 printk(KERN_INFO "====================>rx ADDBAREQ from :%pM\n", dst);
349 //some other capability is not ready now.
350 if ((ieee->current_network.qos_data.active == 0) ||
351 (!ieee->pHTInfo->bCurrentHTSupport)) //||
352 // (!ieee->pStaQos->bEnableRxImmBA) )
353 {
354 rc = ADDBA_STATUS_REFUSED;
355 IEEE80211_DEBUG(IEEE80211_DL_ERR, "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
356 goto OnADDBAReq_Fail;
357 }
358 // Search for related traffic stream.
359 // If there is no matched TS, reject the ADDBA request.
360 if (!GetTs(
361 ieee,
362 (PTS_COMMON_INFO *)(&pTS),
363 dst,
364 (u8)(pBaParamSet->field.TID),
365 RX_DIR,
366 true) ) {
367 rc = ADDBA_STATUS_REFUSED;
368 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __func__);
369 goto OnADDBAReq_Fail;
370 }
371 pBA = &pTS->RxAdmittedBARecord;
372 // To Determine the ADDBA Req content
373 // We can do much more check here, including BufferSize, AMSDU_Support, Policy, StartSeqCtrl...
374 // I want to check StartSeqCtrl to make sure when we start aggregation!!!
375 //
376 if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) {
377 rc = ADDBA_STATUS_INVALID_PARAM;
378 IEEE80211_DEBUG(IEEE80211_DL_ERR, "BA Policy is not correct in %s()\n", __func__);
379 goto OnADDBAReq_Fail;
380 }
381 // Admit the ADDBA Request
382 //
383 DeActivateBAEntry(ieee, pBA);
384 pBA->DialogToken = *pDialogToken;
385 pBA->BaParamSet = *pBaParamSet;
386 pBA->BaTimeoutValue = *pBaTimeoutVal;
387 pBA->BaStartSeqCtrl = *pBaStartSeqCtrl;
388 //for half N mode we only aggregate 1 frame
389 if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
390 pBA->BaParamSet.field.BufferSize = 1;
391 else
392 pBA->BaParamSet.field.BufferSize = 32;
393 ActivateBAEntry(ieee, pBA, pBA->BaTimeoutValue);
394 ieee80211_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);
395
396 // End of procedure.
397 return 0;
398
399 OnADDBAReq_Fail:
400 {
401 BA_RECORD BA;
402 BA.BaParamSet = *pBaParamSet;
403 BA.BaTimeoutValue = *pBaTimeoutVal;
404 BA.DialogToken = *pDialogToken;
405 BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE;
406 ieee80211_send_ADDBARsp(ieee, dst, &BA, rc);
407 return 0; //we send RSP out.
408 }
409
410 }
411
412 /********************************************************************************************************************
413 *function: RX ADDBARSP
414 * input: struct sk_buff * skb //incoming ADDBAReq skb.
415 * return: 0(pass), other(fail)
416 * notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
417 ********************************************************************************************************************/
418 int ieee80211_rx_ADDBARsp(struct ieee80211_device *ieee, struct sk_buff *skb)
419 {
420 struct rtl_80211_hdr_3addr *rsp = NULL;
421 PBA_RECORD pPendingBA, pAdmittedBA;
422 PTX_TS_RECORD pTS = NULL;
423 u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
424 u16 *pStatusCode = NULL, *pBaTimeoutVal = NULL;
425 PBA_PARAM_SET pBaParamSet = NULL;
426 u16 ReasonCode;
427
428 if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 9) {
429 IEEE80211_DEBUG(IEEE80211_DL_ERR,
430 " Invalid skb len in BARSP(%d / %zu)\n",
431 skb->len,
432 (sizeof(struct rtl_80211_hdr_3addr) + 9));
433 return -1;
434 }
435 rsp = (struct rtl_80211_hdr_3addr *)skb->data;
436 tag = (u8 *)rsp;
437 dst = &rsp->addr2[0];
438 tag += sizeof(struct rtl_80211_hdr_3addr);
439 pDialogToken = tag + 2;
440 pStatusCode = (u16 *)(tag + 3);
441 pBaParamSet = (PBA_PARAM_SET)(tag + 5);
442 pBaTimeoutVal = (u16 *)(tag + 7);
443
444 // Check the capability
445 // Since we can always receive A-MPDU, we just check if it is under HT mode.
446 if (ieee->current_network.qos_data.active == 0 ||
447 !ieee->pHTInfo->bCurrentHTSupport ||
448 !ieee->pHTInfo->bCurrentAMPDUEnable) {
449 IEEE80211_DEBUG(IEEE80211_DL_ERR, "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bCurrentAMPDUEnable);
450 ReasonCode = DELBA_REASON_UNKNOWN_BA;
451 goto OnADDBARsp_Reject;
452 }
453
454
455 //
456 // Search for related TS.
457 // If there is no TS found, we wil reject ADDBA Rsp by sending DELBA frame.
458 //
459 if (!GetTs(
460 ieee,
461 (PTS_COMMON_INFO *)(&pTS),
462 dst,
463 (u8)(pBaParamSet->field.TID),
464 TX_DIR,
465 false) ) {
466 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __func__);
467 ReasonCode = DELBA_REASON_UNKNOWN_BA;
468 goto OnADDBARsp_Reject;
469 }
470
471 pTS->bAddBaReqInProgress = false;
472 pPendingBA = &pTS->TxPendingBARecord;
473 pAdmittedBA = &pTS->TxAdmittedBARecord;
474
475
476 //
477 // Check if related BA is waiting for setup.
478 // If not, reject by sending DELBA frame.
479 //
480 if (pAdmittedBA->bValid) {
481 // Since BA is already setup, we ignore all other ADDBA Response.
482 IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n");
483 return -1;
484 }
485 else if((!pPendingBA->bValid) ||(*pDialogToken != pPendingBA->DialogToken)) {
486 IEEE80211_DEBUG(IEEE80211_DL_ERR, "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n");
487 ReasonCode = DELBA_REASON_UNKNOWN_BA;
488 goto OnADDBARsp_Reject;
489 }
490 else {
491 IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode);
492 DeActivateBAEntry(ieee, pPendingBA);
493 }
494
495
496 if(*pStatusCode == ADDBA_STATUS_SUCCESS) {
497 //
498 // Determine ADDBA Rsp content here.
499 // We can compare the value of BA parameter set that Peer returned and Self sent.
500 // If it is OK, then admitted. Or we can send DELBA to cancel BA mechanism.
501 //
502 if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) {
503 // Since this is a kind of ADDBA failed, we delay next ADDBA process.
504 pTS->bAddBaReqDelayed = true;
505 DeActivateBAEntry(ieee, pAdmittedBA);
506 ReasonCode = DELBA_REASON_END_BA;
507 goto OnADDBARsp_Reject;
508 }
509
510
511 //
512 // Admitted condition
513 //
514 pAdmittedBA->DialogToken = *pDialogToken;
515 pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal;
516 pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl;
517 pAdmittedBA->BaParamSet = *pBaParamSet;
518 DeActivateBAEntry(ieee, pAdmittedBA);
519 ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
520 }
521 else {
522 // Delay next ADDBA process.
523 pTS->bAddBaReqDelayed = true;
524 }
525
526 // End of procedure
527 return 0;
528
529 OnADDBARsp_Reject:
530 {
531 BA_RECORD BA;
532 BA.BaParamSet = *pBaParamSet;
533 ieee80211_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
534 return 0;
535 }
536
537 }
538
539 /********************************************************************************************************************
540 *function: RX DELBA
541 * input: struct sk_buff * skb //incoming ADDBAReq skb.
542 * return: 0(pass), other(fail)
543 * notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
544 ********************************************************************************************************************/
545 int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb)
546 {
547 struct rtl_80211_hdr_3addr *delba = NULL;
548 PDELBA_PARAM_SET pDelBaParamSet = NULL;
549 u8 *dst = NULL;
550
551 if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 6) {
552 IEEE80211_DEBUG(IEEE80211_DL_ERR,
553 " Invalid skb len in DELBA(%d / %zu)\n",
554 skb->len,
555 (sizeof(struct rtl_80211_hdr_3addr) + 6));
556 return -1;
557 }
558
559 if (ieee->current_network.qos_data.active == 0 ||
560 !ieee->pHTInfo->bCurrentHTSupport) {
561 IEEE80211_DEBUG(IEEE80211_DL_ERR, "received DELBA while QOS or HT is not supported(%d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
562 return -1;
563 }
564
565 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
566 delba = (struct rtl_80211_hdr_3addr *)skb->data;
567 dst = &delba->addr2[0];
568 pDelBaParamSet = (PDELBA_PARAM_SET)&delba->payload[2];
569
570 if(pDelBaParamSet->field.Initiator == 1) {
571 PRX_TS_RECORD pRxTs;
572
573 if (!GetTs(
574 ieee,
575 (PTS_COMMON_INFO *)&pRxTs,
576 dst,
577 (u8)pDelBaParamSet->field.TID,
578 RX_DIR,
579 false) ) {
580 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for RXTS in %s()\n", __func__);
581 return -1;
582 }
583
584 RxTsDeleteBA(ieee, pRxTs);
585 }
586 else {
587 PTX_TS_RECORD pTxTs;
588
589 if (!GetTs(
590 ieee,
591 (PTS_COMMON_INFO *)&pTxTs,
592 dst,
593 (u8)pDelBaParamSet->field.TID,
594 TX_DIR,
595 false) ) {
596 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for TXTS in %s()\n", __func__);
597 return -1;
598 }
599
600 pTxTs->bUsingBa = false;
601 pTxTs->bAddBaReqInProgress = false;
602 pTxTs->bAddBaReqDelayed = false;
603 del_timer_sync(&pTxTs->TsAddBaTimer);
604 //PlatformCancelTimer(Adapter, &pTxTs->TsAddBaTimer);
605 TxTsDeleteBA(ieee, pTxTs);
606 }
607 return 0;
608 }
609
610 //
611 // ADDBA initiate. This can only be called by TX side.
612 //
613 void
614 TsInitAddBA(
615 struct ieee80211_device *ieee,
616 PTX_TS_RECORD pTS,
617 u8 Policy,
618 u8 bOverwritePending
619 )
620 {
621 PBA_RECORD pBA = &pTS->TxPendingBARecord;
622
623 if (pBA->bValid && !bOverwritePending)
624 return;
625
626 // Set parameters to "Pending" variable set
627 DeActivateBAEntry(ieee, pBA);
628
629 pBA->DialogToken++; // DialogToken: Only keep the latest dialog token
630 pBA->BaParamSet.field.AMSDU_Support = 0; // Do not support A-MSDU with A-MPDU now!!
631 pBA->BaParamSet.field.BAPolicy = Policy; // Policy: Delayed or Immediate
632 pBA->BaParamSet.field.TID = pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID; // TID
633 // BufferSize: This need to be set according to A-MPDU vector
634 pBA->BaParamSet.field.BufferSize = 32; // BufferSize: This need to be set according to A-MPDU vector
635 pBA->BaTimeoutValue = 0; // Timeout value: Set 0 to disable Timer
636 pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096; // Block Ack will start after 3 packets later.
637
638 ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
639
640 ieee80211_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA);
641 }
642
643 void
644 TsInitDelBA( struct ieee80211_device *ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect)
645 {
646
647 if(TxRxSelect == TX_DIR) {
648 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)pTsCommonInfo;
649
650 if(TxTsDeleteBA(ieee, pTxTs))
651 ieee80211_send_DELBA(
652 ieee,
653 pTsCommonInfo->Addr,
654 (pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord),
655 TxRxSelect,
656 DELBA_REASON_END_BA);
657 }
658 else if(TxRxSelect == RX_DIR) {
659 PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)pTsCommonInfo;
660 if(RxTsDeleteBA(ieee, pRxTs))
661 ieee80211_send_DELBA(
662 ieee,
663 pTsCommonInfo->Addr,
664 &pRxTs->RxAdmittedBARecord,
665 TxRxSelect,
666 DELBA_REASON_END_BA );
667 }
668 }
669 /********************************************************************************************************************
670 *function: BA setup timer
671 * input: unsigned long data //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
672 * return: NULL
673 * notice:
674 ********************************************************************************************************************/
675 void BaSetupTimeOut(unsigned long data)
676 {
677 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data;
678
679 pTxTs->bAddBaReqInProgress = false;
680 pTxTs->bAddBaReqDelayed = true;
681 pTxTs->TxPendingBARecord.bValid = false;
682 }
683
684 void TxBaInactTimeout(unsigned long data)
685 {
686 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data;
687 struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[pTxTs->num]);
688 TxTsDeleteBA(ieee, pTxTs);
689 ieee80211_send_DELBA(
690 ieee,
691 pTxTs->TsCommonInfo.Addr,
692 &pTxTs->TxAdmittedBARecord,
693 TX_DIR,
694 DELBA_REASON_TIMEOUT);
695 }
696
697 void RxBaInactTimeout(unsigned long data)
698 {
699 PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)data;
700 struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
701
702 RxTsDeleteBA(ieee, pRxTs);
703 ieee80211_send_DELBA(
704 ieee,
705 pRxTs->TsCommonInfo.Addr,
706 &pRxTs->RxAdmittedBARecord,
707 RX_DIR,
708 DELBA_REASON_TIMEOUT);
709 }