Linux-libre 5.3-gnu
[librecmc/linux-libre.git] / drivers / staging / rtl8192e / rtl819x_BAProc.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
4  *
5  * Contact Information: wlanfae <wlanfae@realtek.com>
6  */
7 #include <asm/byteorder.h>
8 #include <asm/unaligned.h>
9 #include <linux/etherdevice.h>
10 #include "rtllib.h"
11 #include "rtl819x_BA.h"
12
13 static void ActivateBAEntry(struct rtllib_device *ieee, struct ba_record *pBA,
14                             u16 Time)
15 {
16         pBA->bValid = true;
17         if (Time != 0)
18                 mod_timer(&pBA->Timer, jiffies + msecs_to_jiffies(Time));
19 }
20
21 static void DeActivateBAEntry(struct rtllib_device *ieee, struct ba_record *pBA)
22 {
23         pBA->bValid = false;
24         del_timer_sync(&pBA->Timer);
25 }
26
27 static u8 TxTsDeleteBA(struct rtllib_device *ieee, struct tx_ts_record *pTxTs)
28 {
29         struct ba_record *pAdmittedBa = &pTxTs->TxAdmittedBARecord;
30         struct ba_record *pPendingBa = &pTxTs->TxPendingBARecord;
31         u8 bSendDELBA = false;
32
33         if (pPendingBa->bValid) {
34                 DeActivateBAEntry(ieee, pPendingBa);
35                 bSendDELBA = true;
36         }
37
38         if (pAdmittedBa->bValid) {
39                 DeActivateBAEntry(ieee, pAdmittedBa);
40                 bSendDELBA = true;
41         }
42         return bSendDELBA;
43 }
44
45 static u8 RxTsDeleteBA(struct rtllib_device *ieee, struct rx_ts_record *pRxTs)
46 {
47         struct ba_record *pBa = &pRxTs->RxAdmittedBARecord;
48         u8                      bSendDELBA = false;
49
50         if (pBa->bValid) {
51                 DeActivateBAEntry(ieee, pBa);
52                 bSendDELBA = true;
53         }
54
55         return bSendDELBA;
56 }
57
58 void ResetBaEntry(struct ba_record *pBA)
59 {
60         pBA->bValid                     = false;
61         pBA->BaParamSet.shortData       = 0;
62         pBA->BaTimeoutValue             = 0;
63         pBA->DialogToken                = 0;
64         pBA->BaStartSeqCtrl.ShortData   = 0;
65 }
66 static struct sk_buff *rtllib_ADDBA(struct rtllib_device *ieee, u8 *Dst,
67                                     struct ba_record *pBA,
68                                     u16 StatusCode, u8 type)
69 {
70         struct sk_buff *skb = NULL;
71         struct rtllib_hdr_3addr *BAReq = NULL;
72         u8 *tag = NULL;
73         u16 len = ieee->tx_headroom + 9;
74
75         netdev_dbg(ieee->dev, "%s(): frame(%d) sentd to: %pM, ieee->dev:%p\n",
76                    __func__, type, Dst, ieee->dev);
77
78         if (!pBA) {
79                 netdev_warn(ieee->dev, "pBA is NULL\n");
80                 return NULL;
81         }
82         skb = dev_alloc_skb(len + sizeof(struct rtllib_hdr_3addr));
83         if (!skb)
84                 return NULL;
85
86         memset(skb->data, 0, sizeof(struct rtllib_hdr_3addr));
87
88         skb_reserve(skb, ieee->tx_headroom);
89
90         BAReq = skb_put(skb, sizeof(struct rtllib_hdr_3addr));
91
92         ether_addr_copy(BAReq->addr1, Dst);
93         ether_addr_copy(BAReq->addr2, ieee->dev->dev_addr);
94
95         ether_addr_copy(BAReq->addr3, ieee->current_network.bssid);
96         BAReq->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT);
97
98         tag = skb_put(skb, 9);
99         *tag++ = ACT_CAT_BA;
100         *tag++ = type;
101         *tag++ = pBA->DialogToken;
102
103         if (type == ACT_ADDBARSP) {
104                 RT_TRACE(COMP_DBG, "====>to send ADDBARSP\n");
105
106                 put_unaligned_le16(StatusCode, tag);
107                 tag += 2;
108         }
109
110         put_unaligned_le16(pBA->BaParamSet.shortData, tag);
111         tag += 2;
112
113         put_unaligned_le16(pBA->BaTimeoutValue, tag);
114         tag += 2;
115
116         if (type == ACT_ADDBAREQ) {
117                 memcpy(tag, (u8 *)&(pBA->BaStartSeqCtrl), 2);
118                 tag += 2;
119         }
120
121 #ifdef VERBOSE_DEBUG
122         print_hex_dump_bytes("rtllib_ADDBA(): ", DUMP_PREFIX_NONE, skb->data,
123                              skb->len);
124 #endif
125         return skb;
126 }
127
128 static struct sk_buff *rtllib_DELBA(struct rtllib_device *ieee, u8 *dst,
129                                     struct ba_record *pBA,
130                                     enum tr_select TxRxSelect, u16 ReasonCode)
131 {
132         union delba_param_set DelbaParamSet;
133         struct sk_buff *skb = NULL;
134         struct rtllib_hdr_3addr *Delba = NULL;
135         u8 *tag = NULL;
136         u16 len = 6 + ieee->tx_headroom;
137
138         if (net_ratelimit())
139                 netdev_dbg(ieee->dev, "%s(): ReasonCode(%d) sentd to: %pM\n",
140                            __func__, ReasonCode, dst);
141
142         memset(&DelbaParamSet, 0, 2);
143
144         DelbaParamSet.field.Initiator = (TxRxSelect == TX_DIR) ? 1 : 0;
145         DelbaParamSet.field.TID = pBA->BaParamSet.field.TID;
146
147         skb = dev_alloc_skb(len + sizeof(struct rtllib_hdr_3addr));
148         if (!skb)
149                 return NULL;
150
151         skb_reserve(skb, ieee->tx_headroom);
152
153         Delba = skb_put(skb, sizeof(struct rtllib_hdr_3addr));
154
155         ether_addr_copy(Delba->addr1, dst);
156         ether_addr_copy(Delba->addr2, ieee->dev->dev_addr);
157         ether_addr_copy(Delba->addr3, ieee->current_network.bssid);
158         Delba->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT);
159
160         tag = skb_put(skb, 6);
161
162         *tag++ = ACT_CAT_BA;
163         *tag++ = ACT_DELBA;
164
165
166         put_unaligned_le16(DelbaParamSet.shortData, tag);
167         tag += 2;
168
169         put_unaligned_le16(ReasonCode, tag);
170         tag += 2;
171
172 #ifdef VERBOSE_DEBUG
173         print_hex_dump_bytes("rtllib_DELBA(): ", DUMP_PREFIX_NONE, skb->data,
174                              skb->len);
175 #endif
176         return skb;
177 }
178
179 static void rtllib_send_ADDBAReq(struct rtllib_device *ieee, u8 *dst,
180                                  struct ba_record *pBA)
181 {
182         struct sk_buff *skb;
183
184         skb = rtllib_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ);
185
186         if (skb) {
187                 RT_TRACE(COMP_DBG, "====>to send ADDBAREQ!!!!!\n");
188                 softmac_mgmt_xmit(skb, ieee);
189         } else {
190                 netdev_dbg(ieee->dev, "Failed to generate ADDBAReq packet.\n");
191         }
192 }
193
194 static void rtllib_send_ADDBARsp(struct rtllib_device *ieee, u8 *dst,
195                                  struct ba_record *pBA, u16 StatusCode)
196 {
197         struct sk_buff *skb;
198
199         skb = rtllib_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP);
200         if (skb)
201                 softmac_mgmt_xmit(skb, ieee);
202         else
203                 netdev_dbg(ieee->dev, "Failed to generate ADDBARsp packet.\n");
204 }
205
206 static void rtllib_send_DELBA(struct rtllib_device *ieee, u8 *dst,
207                               struct ba_record *pBA, enum tr_select TxRxSelect,
208                               u16 ReasonCode)
209 {
210         struct sk_buff *skb;
211
212         skb = rtllib_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode);
213         if (skb)
214                 softmac_mgmt_xmit(skb, ieee);
215         else
216                 netdev_dbg(ieee->dev, "Failed to generate DELBA packet.\n");
217 }
218
219 int rtllib_rx_ADDBAReq(struct rtllib_device *ieee, struct sk_buff *skb)
220 {
221         struct rtllib_hdr_3addr *req = NULL;
222         u16 rc = 0;
223         u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
224         struct ba_record *pBA = NULL;
225         union ba_param_set *pBaParamSet = NULL;
226         u16 *pBaTimeoutVal = NULL;
227         union sequence_control *pBaStartSeqCtrl = NULL;
228         struct rx_ts_record *pTS = NULL;
229
230         if (skb->len < sizeof(struct rtllib_hdr_3addr) + 9) {
231                 netdev_warn(ieee->dev, "Invalid skb len in BAREQ(%d / %d)\n",
232                             (int)skb->len,
233                             (int)(sizeof(struct rtllib_hdr_3addr) + 9));
234                 return -1;
235         }
236
237 #ifdef VERBOSE_DEBUG
238         print_hex_dump_bytes("rtllib_rx_ADDBAReq(): ", DUMP_PREFIX_NONE,
239                              skb->data, skb->len);
240 #endif
241
242         req = (struct rtllib_hdr_3addr *) skb->data;
243         tag = (u8 *)req;
244         dst = (u8 *)(&req->addr2[0]);
245         tag += sizeof(struct rtllib_hdr_3addr);
246         pDialogToken = tag + 2;
247         pBaParamSet = (union ba_param_set *)(tag + 3);
248         pBaTimeoutVal = (u16 *)(tag + 5);
249         pBaStartSeqCtrl = (union sequence_control *)(req + 7);
250
251         RT_TRACE(COMP_DBG, "====>rx ADDBAREQ from : %pM\n", dst);
252         if (!ieee->current_network.qos_data.active ||
253             !ieee->pHTInfo->bCurrentHTSupport ||
254             (ieee->pHTInfo->IOTAction & HT_IOT_ACT_REJECT_ADDBA_REQ)) {
255                 rc = ADDBA_STATUS_REFUSED;
256                 netdev_warn(ieee->dev,
257                             "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n",
258                             ieee->current_network.qos_data.active,
259                             ieee->pHTInfo->bCurrentHTSupport);
260                 goto OnADDBAReq_Fail;
261         }
262         if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst,
263             (u8)(pBaParamSet->field.TID), RX_DIR, true)) {
264                 rc = ADDBA_STATUS_REFUSED;
265                 netdev_warn(ieee->dev, "%s(): can't get TS\n", __func__);
266                 goto OnADDBAReq_Fail;
267         }
268         pBA = &pTS->RxAdmittedBARecord;
269
270         if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) {
271                 rc = ADDBA_STATUS_INVALID_PARAM;
272                 netdev_warn(ieee->dev, "%s(): BA Policy is not correct\n",
273                             __func__);
274                 goto OnADDBAReq_Fail;
275         }
276
277         rtllib_FlushRxTsPendingPkts(ieee, pTS);
278
279         DeActivateBAEntry(ieee, pBA);
280         pBA->DialogToken = *pDialogToken;
281         pBA->BaParamSet = *pBaParamSet;
282         pBA->BaTimeoutValue = *pBaTimeoutVal;
283         pBA->BaStartSeqCtrl = *pBaStartSeqCtrl;
284
285         if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev) ||
286            (ieee->pHTInfo->IOTAction & HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT))
287                 pBA->BaParamSet.field.BufferSize = 1;
288         else
289                 pBA->BaParamSet.field.BufferSize = 32;
290
291         ActivateBAEntry(ieee, pBA, 0);
292         rtllib_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);
293
294         return 0;
295
296 OnADDBAReq_Fail:
297         {
298                 struct ba_record BA;
299
300                 BA.BaParamSet = *pBaParamSet;
301                 BA.BaTimeoutValue = *pBaTimeoutVal;
302                 BA.DialogToken = *pDialogToken;
303                 BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE;
304                 rtllib_send_ADDBARsp(ieee, dst, &BA, rc);
305                 return 0;
306         }
307 }
308
309 int rtllib_rx_ADDBARsp(struct rtllib_device *ieee, struct sk_buff *skb)
310 {
311         struct rtllib_hdr_3addr *rsp = NULL;
312         struct ba_record *pPendingBA, *pAdmittedBA;
313         struct tx_ts_record *pTS = NULL;
314         u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
315         u16 *pStatusCode = NULL, *pBaTimeoutVal = NULL;
316         union ba_param_set *pBaParamSet = NULL;
317         u16                     ReasonCode;
318
319         if (skb->len < sizeof(struct rtllib_hdr_3addr) + 9) {
320                 netdev_warn(ieee->dev, "Invalid skb len in BARSP(%d / %d)\n",
321                             (int)skb->len,
322                             (int)(sizeof(struct rtllib_hdr_3addr) + 9));
323                 return -1;
324         }
325         rsp = (struct rtllib_hdr_3addr *)skb->data;
326         tag = (u8 *)rsp;
327         dst = (u8 *)(&rsp->addr2[0]);
328         tag += sizeof(struct rtllib_hdr_3addr);
329         pDialogToken = tag + 2;
330         pStatusCode = (u16 *)(tag + 3);
331         pBaParamSet = (union ba_param_set *)(tag + 5);
332         pBaTimeoutVal = (u16 *)(tag + 7);
333
334         RT_TRACE(COMP_DBG, "====>rx ADDBARSP from : %pM\n", dst);
335         if (!ieee->current_network.qos_data.active ||
336             !ieee->pHTInfo->bCurrentHTSupport ||
337             !ieee->pHTInfo->bCurrentAMPDUEnable) {
338                 netdev_warn(ieee->dev,
339                             "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",
340                             ieee->current_network.qos_data.active,
341                             ieee->pHTInfo->bCurrentHTSupport,
342                             ieee->pHTInfo->bCurrentAMPDUEnable);
343                 ReasonCode = DELBA_REASON_UNKNOWN_BA;
344                 goto OnADDBARsp_Reject;
345         }
346
347
348         if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst,
349                    (u8)(pBaParamSet->field.TID), TX_DIR, false)) {
350                 netdev_warn(ieee->dev, "%s(): can't get TS\n", __func__);
351                 ReasonCode = DELBA_REASON_UNKNOWN_BA;
352                 goto OnADDBARsp_Reject;
353         }
354
355         pTS->bAddBaReqInProgress = false;
356         pPendingBA = &pTS->TxPendingBARecord;
357         pAdmittedBA = &pTS->TxAdmittedBARecord;
358
359
360         if (pAdmittedBA->bValid) {
361                 netdev_dbg(ieee->dev, "%s(): ADDBA response already admitted\n",
362                            __func__);
363                 return -1;
364         } else if (!pPendingBA->bValid ||
365                    (*pDialogToken != pPendingBA->DialogToken)) {
366                 netdev_warn(ieee->dev,
367                             "%s(): ADDBA Rsp. BA invalid, DELBA!\n",
368                             __func__);
369                 ReasonCode = DELBA_REASON_UNKNOWN_BA;
370                 goto OnADDBARsp_Reject;
371         } else {
372                 netdev_dbg(ieee->dev,
373                            "%s(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n",
374                            __func__, *pStatusCode);
375                 DeActivateBAEntry(ieee, pPendingBA);
376         }
377
378
379         if (*pStatusCode == ADDBA_STATUS_SUCCESS) {
380                 if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) {
381                         pTS->bAddBaReqDelayed = true;
382                         DeActivateBAEntry(ieee, pAdmittedBA);
383                         ReasonCode = DELBA_REASON_END_BA;
384                         goto OnADDBARsp_Reject;
385                 }
386
387
388                 pAdmittedBA->DialogToken = *pDialogToken;
389                 pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal;
390                 pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl;
391                 pAdmittedBA->BaParamSet = *pBaParamSet;
392                 DeActivateBAEntry(ieee, pAdmittedBA);
393                 ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
394         } else {
395                 pTS->bAddBaReqDelayed = true;
396                 pTS->bDisable_AddBa = true;
397                 ReasonCode = DELBA_REASON_END_BA;
398                 goto OnADDBARsp_Reject;
399         }
400
401         return 0;
402
403 OnADDBARsp_Reject:
404         {
405                 struct ba_record BA;
406
407                 BA.BaParamSet = *pBaParamSet;
408                 rtllib_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
409                 return 0;
410         }
411 }
412
413 int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb)
414 {
415         struct rtllib_hdr_3addr *delba = NULL;
416         union delba_param_set *pDelBaParamSet = NULL;
417         u8 *dst = NULL;
418
419         if (skb->len < sizeof(struct rtllib_hdr_3addr) + 6) {
420                 netdev_warn(ieee->dev, "Invalid skb len in DELBA(%d / %d)\n",
421                             (int)skb->len,
422                             (int)(sizeof(struct rtllib_hdr_3addr) + 6));
423                 return -1;
424         }
425
426         if (!ieee->current_network.qos_data.active ||
427                 !ieee->pHTInfo->bCurrentHTSupport) {
428                 netdev_warn(ieee->dev,
429                             "received DELBA while QOS or HT is not supported(%d, %d)\n",
430                             ieee->current_network. qos_data.active,
431                             ieee->pHTInfo->bCurrentHTSupport);
432                 return -1;
433         }
434
435 #ifdef VERBOSE_DEBUG
436         print_hex_dump_bytes("rtllib_rx_DELBA(): ", DUMP_PREFIX_NONE, skb->data,
437                              skb->len);
438 #endif
439         delba = (struct rtllib_hdr_3addr *)skb->data;
440         dst = (u8 *)(&delba->addr2[0]);
441         pDelBaParamSet = (union delba_param_set *)&delba->payload[2];
442
443         if (pDelBaParamSet->field.Initiator == 1) {
444                 struct rx_ts_record *pRxTs;
445
446                 if (!GetTs(ieee, (struct ts_common_info **)&pRxTs, dst,
447                     (u8)pDelBaParamSet->field.TID, RX_DIR, false)) {
448                         netdev_warn(ieee->dev,
449                                     "%s(): can't get TS for RXTS. dst:%pM TID:%d\n",
450                                     __func__, dst,
451                                     (u8)pDelBaParamSet->field.TID);
452                         return -1;
453                 }
454
455                 RxTsDeleteBA(ieee, pRxTs);
456         } else {
457                 struct tx_ts_record *pTxTs;
458
459                 if (!GetTs(ieee, (struct ts_common_info **)&pTxTs, dst,
460                            (u8)pDelBaParamSet->field.TID, TX_DIR, false)) {
461                         netdev_warn(ieee->dev, "%s(): can't get TS for TXTS\n",
462                                     __func__);
463                         return -1;
464                 }
465
466                 pTxTs->bUsingBa = false;
467                 pTxTs->bAddBaReqInProgress = false;
468                 pTxTs->bAddBaReqDelayed = false;
469                 del_timer_sync(&pTxTs->TsAddBaTimer);
470                 TxTsDeleteBA(ieee, pTxTs);
471         }
472         return 0;
473 }
474
475 void TsInitAddBA(struct rtllib_device *ieee, struct tx_ts_record *pTS,
476                  u8 Policy, u8  bOverwritePending)
477 {
478         struct ba_record *pBA = &pTS->TxPendingBARecord;
479
480         if (pBA->bValid && !bOverwritePending)
481                 return;
482
483         DeActivateBAEntry(ieee, pBA);
484
485         pBA->DialogToken++;
486         pBA->BaParamSet.field.AMSDU_Support = 0;
487         pBA->BaParamSet.field.BAPolicy = Policy;
488         pBA->BaParamSet.field.TID =
489                          pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID;
490         pBA->BaParamSet.field.BufferSize = 32;
491         pBA->BaTimeoutValue = 0;
492         pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096;
493
494         ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
495
496         rtllib_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA);
497 }
498
499 void TsInitDelBA(struct rtllib_device *ieee,
500                  struct ts_common_info *pTsCommonInfo,
501                  enum tr_select TxRxSelect)
502 {
503         if (TxRxSelect == TX_DIR) {
504                 struct tx_ts_record *pTxTs =
505                          (struct tx_ts_record *)pTsCommonInfo;
506
507                 if (TxTsDeleteBA(ieee, pTxTs))
508                         rtllib_send_DELBA(ieee, pTsCommonInfo->Addr,
509                                           (pTxTs->TxAdmittedBARecord.bValid) ?
510                                          (&pTxTs->TxAdmittedBARecord) :
511                                         (&pTxTs->TxPendingBARecord),
512                                          TxRxSelect, DELBA_REASON_END_BA);
513         } else if (TxRxSelect == RX_DIR) {
514                 struct rx_ts_record *pRxTs =
515                                  (struct rx_ts_record *)pTsCommonInfo;
516                 if (RxTsDeleteBA(ieee, pRxTs))
517                         rtllib_send_DELBA(ieee, pTsCommonInfo->Addr,
518                                           &pRxTs->RxAdmittedBARecord,
519                                           TxRxSelect, DELBA_REASON_END_BA);
520         }
521 }
522
523 void BaSetupTimeOut(struct timer_list *t)
524 {
525         struct tx_ts_record *pTxTs = from_timer(pTxTs, t,
526                                               TxPendingBARecord.Timer);
527
528         pTxTs->bAddBaReqInProgress = false;
529         pTxTs->bAddBaReqDelayed = true;
530         pTxTs->TxPendingBARecord.bValid = false;
531 }
532
533 void TxBaInactTimeout(struct timer_list *t)
534 {
535         struct tx_ts_record *pTxTs = from_timer(pTxTs, t,
536                                               TxAdmittedBARecord.Timer);
537         struct rtllib_device *ieee = container_of(pTxTs, struct rtllib_device,
538                                      TxTsRecord[pTxTs->num]);
539         TxTsDeleteBA(ieee, pTxTs);
540         rtllib_send_DELBA(ieee, pTxTs->TsCommonInfo.Addr,
541                           &pTxTs->TxAdmittedBARecord, TX_DIR,
542                           DELBA_REASON_TIMEOUT);
543 }
544
545 void RxBaInactTimeout(struct timer_list *t)
546 {
547         struct rx_ts_record *pRxTs = from_timer(pRxTs, t,
548                                               RxAdmittedBARecord.Timer);
549         struct rtllib_device *ieee = container_of(pRxTs, struct rtllib_device,
550                                      RxTsRecord[pRxTs->num]);
551
552         RxTsDeleteBA(ieee, pRxTs);
553         rtllib_send_DELBA(ieee, pRxTs->TsCommonInfo.Addr,
554                           &pRxTs->RxAdmittedBARecord, RX_DIR,
555                           DELBA_REASON_TIMEOUT);
556 }