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