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