Merge tag 'ipsec-2023-10-17' of git://git.kernel.org/pub/scm/linux/kernel/git/klasser...
[linux-2.6-microblaze.git] / drivers / staging / rtl8192e / rtl819x_TSProc.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 "rtllib.h"
8 #include <linux/etherdevice.h>
9 #include "rtl819x_TS.h"
10
11 static void RxPktPendingTimeout(struct timer_list *t)
12 {
13         struct rx_ts_record *pRxTs = from_timer(pRxTs, t,
14                                                      rx_pkt_pending_timer);
15         struct rtllib_device *ieee = container_of(pRxTs, struct rtllib_device,
16                                                   RxTsRecord[pRxTs->num]);
17
18         struct rx_reorder_entry *pReorderEntry = NULL;
19
20         unsigned long flags = 0;
21         u8 index = 0;
22         bool bPktInBuf = false;
23
24         spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
25         if (pRxTs->rx_timeout_indicate_seq != 0xffff) {
26                 while (!list_empty(&pRxTs->rx_pending_pkt_list)) {
27                         pReorderEntry = (struct rx_reorder_entry *)
28                                         list_entry(pRxTs->rx_pending_pkt_list.prev,
29                                         struct rx_reorder_entry, List);
30                         if (index == 0)
31                                 pRxTs->rx_indicate_seq = pReorderEntry->SeqNum;
32
33                         if (SN_LESS(pReorderEntry->SeqNum,
34                                     pRxTs->rx_indicate_seq) ||
35                             SN_EQUAL(pReorderEntry->SeqNum,
36                                      pRxTs->rx_indicate_seq)) {
37                                 list_del_init(&pReorderEntry->List);
38
39                                 if (SN_EQUAL(pReorderEntry->SeqNum,
40                                     pRxTs->rx_indicate_seq))
41                                         pRxTs->rx_indicate_seq =
42                                               (pRxTs->rx_indicate_seq + 1) % 4096;
43
44                                 netdev_dbg(ieee->dev,
45                                            "%s(): Indicate SeqNum: %d\n",
46                                            __func__, pReorderEntry->SeqNum);
47                                 ieee->stats_IndicateArray[index] =
48                                                          pReorderEntry->prxb;
49                                 index++;
50
51                                 list_add_tail(&pReorderEntry->List,
52                                               &ieee->RxReorder_Unused_List);
53                         } else {
54                                 bPktInBuf = true;
55                                 break;
56                         }
57                 }
58         }
59
60         if (index > 0) {
61                 pRxTs->rx_timeout_indicate_seq = 0xffff;
62
63                 if (index > REORDER_WIN_SIZE) {
64                         netdev_warn(ieee->dev,
65                                     "%s(): Rx Reorder struct buffer full\n",
66                                     __func__);
67                         spin_unlock_irqrestore(&(ieee->reorder_spinlock),
68                                                flags);
69                         return;
70                 }
71                 rtllib_indicate_packets(ieee, ieee->stats_IndicateArray, index);
72                 bPktInBuf = false;
73         }
74
75         if (bPktInBuf && (pRxTs->rx_timeout_indicate_seq == 0xffff)) {
76                 pRxTs->rx_timeout_indicate_seq = pRxTs->rx_indicate_seq;
77                 mod_timer(&pRxTs->rx_pkt_pending_timer,  jiffies +
78                           msecs_to_jiffies(ieee->ht_info->rx_reorder_pending_time)
79                           );
80         }
81         spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
82 }
83
84 static void TsAddBaProcess(struct timer_list *t)
85 {
86         struct tx_ts_record *pTxTs = from_timer(pTxTs, t, TsAddBaTimer);
87         u8 num = pTxTs->num;
88         struct rtllib_device *ieee = container_of(pTxTs, struct rtllib_device,
89                                      TxTsRecord[num]);
90
91         rtllib_ts_init_add_ba(ieee, pTxTs, BA_POLICY_IMMEDIATE, false);
92         netdev_dbg(ieee->dev, "%s(): ADDBA Req is started\n", __func__);
93 }
94
95 static void ResetTsCommonInfo(struct ts_common_info *pTsCommonInfo)
96 {
97         eth_zero_addr(pTsCommonInfo->Addr);
98         memset(&pTsCommonInfo->TSpec, 0, sizeof(union tspec_body));
99         memset(&pTsCommonInfo->TClass, 0, sizeof(union qos_tclas) * TCLAS_NUM);
100         pTsCommonInfo->TClasProc = 0;
101         pTsCommonInfo->TClasNum = 0;
102 }
103
104 static void ResetTxTsEntry(struct tx_ts_record *pTS)
105 {
106         ResetTsCommonInfo(&pTS->TsCommonInfo);
107         pTS->TxCurSeq = 0;
108         pTS->bAddBaReqInProgress = false;
109         pTS->bAddBaReqDelayed = false;
110         pTS->bUsingBa = false;
111         pTS->bDisable_AddBa = false;
112         rtllib_reset_ba_entry(&pTS->TxAdmittedBARecord);
113         rtllib_reset_ba_entry(&pTS->TxPendingBARecord);
114 }
115
116 static void ResetRxTsEntry(struct rx_ts_record *pTS)
117 {
118         ResetTsCommonInfo(&pTS->ts_common_info);
119         pTS->rx_indicate_seq = 0xffff;
120         pTS->rx_timeout_indicate_seq = 0xffff;
121         rtllib_reset_ba_entry(&pTS->rx_admitted_ba_record);
122 }
123
124 void TSInitialize(struct rtllib_device *ieee)
125 {
126         struct tx_ts_record *pTxTS  = ieee->TxTsRecord;
127         struct rx_ts_record *pRxTS  = ieee->RxTsRecord;
128         struct rx_reorder_entry *pRxReorderEntry = ieee->RxReorderEntry;
129         u8                              count = 0;
130
131         INIT_LIST_HEAD(&ieee->Tx_TS_Admit_List);
132         INIT_LIST_HEAD(&ieee->Tx_TS_Pending_List);
133         INIT_LIST_HEAD(&ieee->Tx_TS_Unused_List);
134
135         for (count = 0; count < TOTAL_TS_NUM; count++) {
136                 pTxTS->num = count;
137                 timer_setup(&pTxTS->TsAddBaTimer, TsAddBaProcess, 0);
138
139                 timer_setup(&pTxTS->TxPendingBARecord.timer, rtllib_ba_setup_timeout,
140                             0);
141                 timer_setup(&pTxTS->TxAdmittedBARecord.timer,
142                             rtllib_tx_ba_inact_timeout, 0);
143
144                 ResetTxTsEntry(pTxTS);
145                 list_add_tail(&pTxTS->TsCommonInfo.List,
146                                 &ieee->Tx_TS_Unused_List);
147                 pTxTS++;
148         }
149
150         INIT_LIST_HEAD(&ieee->Rx_TS_Admit_List);
151         INIT_LIST_HEAD(&ieee->Rx_TS_Pending_List);
152         INIT_LIST_HEAD(&ieee->Rx_TS_Unused_List);
153         for (count = 0; count < TOTAL_TS_NUM; count++) {
154                 pRxTS->num = count;
155                 INIT_LIST_HEAD(&pRxTS->rx_pending_pkt_list);
156                 timer_setup(&pRxTS->rx_admitted_ba_record.timer,
157                             rtllib_rx_ba_inact_timeout, 0);
158
159                 timer_setup(&pRxTS->rx_pkt_pending_timer, RxPktPendingTimeout, 0);
160
161                 ResetRxTsEntry(pRxTS);
162                 list_add_tail(&pRxTS->ts_common_info.List,
163                               &ieee->Rx_TS_Unused_List);
164                 pRxTS++;
165         }
166         INIT_LIST_HEAD(&ieee->RxReorder_Unused_List);
167         for (count = 0; count < REORDER_ENTRY_NUM; count++) {
168                 list_add_tail(&pRxReorderEntry->List,
169                               &ieee->RxReorder_Unused_List);
170                 if (count == (REORDER_ENTRY_NUM - 1))
171                         break;
172                 pRxReorderEntry = &ieee->RxReorderEntry[count + 1];
173         }
174 }
175
176 static struct ts_common_info *SearchAdmitTRStream(struct rtllib_device *ieee,
177                                                   u8 *Addr, u8 TID,
178                                                   enum tr_select TxRxSelect)
179 {
180         u8      dir;
181         bool    search_dir[4] = {0};
182         struct list_head *psearch_list;
183         struct ts_common_info *pRet = NULL;
184
185         if (ieee->iw_mode == IW_MODE_ADHOC) {
186                 if (TxRxSelect == TX_DIR)
187                         search_dir[DIR_UP] = true;
188                 else
189                         search_dir[DIR_DOWN] = true;
190         } else {
191                 if (TxRxSelect == TX_DIR) {
192                         search_dir[DIR_UP] = true;
193                         search_dir[DIR_BI_DIR] = true;
194                         search_dir[DIR_DIRECT] = true;
195                 } else {
196                         search_dir[DIR_DOWN] = true;
197                         search_dir[DIR_BI_DIR] = true;
198                         search_dir[DIR_DIRECT] = true;
199                 }
200         }
201
202         if (TxRxSelect == TX_DIR)
203                 psearch_list = &ieee->Tx_TS_Admit_List;
204         else
205                 psearch_list = &ieee->Rx_TS_Admit_List;
206
207         for (dir = 0; dir <= DIR_BI_DIR; dir++) {
208                 if (!search_dir[dir])
209                         continue;
210                 list_for_each_entry(pRet, psearch_list, List) {
211                         if (memcmp(pRet->Addr, Addr, 6) == 0 &&
212                             pRet->TSpec.f.TSInfo.field.ucTSID == TID &&
213                             pRet->TSpec.f.TSInfo.field.ucDirection == dir)
214                                 break;
215                 }
216                 if (&pRet->List  != psearch_list)
217                         break;
218         }
219
220         if (pRet && &pRet->List  != psearch_list)
221                 return pRet;
222         return NULL;
223 }
224
225 static void MakeTSEntry(struct ts_common_info *pTsCommonInfo, u8 *Addr,
226                         union tspec_body *pTSPEC, union qos_tclas *pTCLAS,
227                         u8 TCLAS_Num, u8 TCLAS_Proc)
228 {
229         u8      count;
230
231         if (!pTsCommonInfo)
232                 return;
233
234         memcpy(pTsCommonInfo->Addr, Addr, 6);
235
236         if (pTSPEC)
237                 memcpy((u8 *)(&(pTsCommonInfo->TSpec)), (u8 *)pTSPEC,
238                         sizeof(union tspec_body));
239
240         for (count = 0; count < TCLAS_Num; count++)
241                 memcpy((u8 *)(&(pTsCommonInfo->TClass[count])),
242                        (u8 *)pTCLAS, sizeof(union qos_tclas));
243
244         pTsCommonInfo->TClasProc = TCLAS_Proc;
245         pTsCommonInfo->TClasNum = TCLAS_Num;
246 }
247
248 bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS,
249            u8 *Addr, u8 TID, enum tr_select TxRxSelect, bool bAddNewTs)
250 {
251         u8      UP = 0;
252         union tspec_body TSpec;
253         union qos_tsinfo *pTSInfo = &TSpec.f.TSInfo;
254         struct list_head *pUnusedList;
255         struct list_head *pAddmitList;
256         enum direction_value Dir;
257
258         if (is_multicast_ether_addr(Addr)) {
259                 netdev_warn(ieee->dev, "Get TS for Broadcast or Multicast\n");
260                 return false;
261         }
262         if (ieee->current_network.qos_data.supported == 0) {
263                 UP = 0;
264         } else {
265                 switch (TID) {
266                 case 0:
267                 case 3:
268                         UP = 0;
269                         break;
270                 case 1:
271                 case 2:
272                         UP = 2;
273                         break;
274                 case 4:
275                 case 5:
276                         UP = 5;
277                         break;
278                 case 6:
279                 case 7:
280                         UP = 7;
281                         break;
282                 default:
283                         netdev_warn(ieee->dev, "%s(): TID(%d) is not valid\n",
284                                     __func__, TID);
285                         return false;
286                 }
287         }
288
289         *ppTS = SearchAdmitTRStream(ieee, Addr, UP, TxRxSelect);
290         if (*ppTS)
291                 return true;
292
293         if (!bAddNewTs) {
294                 netdev_dbg(ieee->dev, "add new TS failed(tid:%d)\n", UP);
295                 return false;
296         }
297
298         pUnusedList = (TxRxSelect == TX_DIR) ?
299                                 (&ieee->Tx_TS_Unused_List) :
300                                 (&ieee->Rx_TS_Unused_List);
301
302         pAddmitList = (TxRxSelect == TX_DIR) ?
303                                 (&ieee->Tx_TS_Admit_List) :
304                                 (&ieee->Rx_TS_Admit_List);
305
306         Dir = ((TxRxSelect == TX_DIR) ? DIR_UP : DIR_DOWN);
307
308         if (!list_empty(pUnusedList)) {
309                 (*ppTS) = list_entry(pUnusedList->next,
310                           struct ts_common_info, List);
311                 list_del_init(&(*ppTS)->List);
312                 if (TxRxSelect == TX_DIR) {
313                         struct tx_ts_record *tmp =
314                                 container_of(*ppTS,
315                                 struct tx_ts_record,
316                                 TsCommonInfo);
317                         ResetTxTsEntry(tmp);
318                 } else {
319                         struct rx_ts_record *tmp =
320                                  container_of(*ppTS,
321                                  struct rx_ts_record,
322                                  ts_common_info);
323                         ResetRxTsEntry(tmp);
324                 }
325
326                 netdev_dbg(ieee->dev,
327                            "to init current TS, UP:%d, Dir:%d, addr: %pM ppTs=%p\n",
328                            UP, Dir, Addr, *ppTS);
329                 pTSInfo->field.ucTrafficType = 0;
330                 pTSInfo->field.ucTSID = UP;
331                 pTSInfo->field.ucDirection = Dir;
332                 pTSInfo->field.ucAccessPolicy = 1;
333                 pTSInfo->field.ucAggregation = 0;
334                 pTSInfo->field.ucPSB = 0;
335                 pTSInfo->field.ucUP = UP;
336                 pTSInfo->field.ucTSInfoAckPolicy = 0;
337                 pTSInfo->field.ucSchedule = 0;
338
339                 MakeTSEntry(*ppTS, Addr, &TSpec, NULL, 0, 0);
340                 list_add_tail(&((*ppTS)->List), pAddmitList);
341
342                 return true;
343         }
344
345         netdev_warn(ieee->dev,
346                     "There is not enough dir=%d(0=up down=1) TS record to be used!",
347                     Dir);
348         return false;
349 }
350
351 static void RemoveTsEntry(struct rtllib_device *ieee,
352                           struct ts_common_info *pTs, enum tr_select TxRxSelect)
353 {
354         rtllib_ts_init_del_ba(ieee, pTs, TxRxSelect);
355
356         if (TxRxSelect == RX_DIR) {
357                 struct rx_reorder_entry *pRxReorderEntry;
358                 struct rx_ts_record *pRxTS = (struct rx_ts_record *)pTs;
359
360                 if (timer_pending(&pRxTS->rx_pkt_pending_timer))
361                         del_timer_sync(&pRxTS->rx_pkt_pending_timer);
362
363                 while (!list_empty(&pRxTS->rx_pending_pkt_list)) {
364                         pRxReorderEntry = (struct rx_reorder_entry *)
365                                         list_entry(pRxTS->rx_pending_pkt_list.prev,
366                                         struct rx_reorder_entry, List);
367                         netdev_dbg(ieee->dev,  "%s(): Delete SeqNum %d!\n",
368                                    __func__, pRxReorderEntry->SeqNum);
369                         list_del_init(&pRxReorderEntry->List);
370                         {
371                                 int i = 0;
372                                 struct rtllib_rxb *prxb = pRxReorderEntry->prxb;
373
374                                 if (unlikely(!prxb))
375                                         return;
376                                 for (i = 0; i < prxb->nr_subframes; i++)
377                                         dev_kfree_skb(prxb->subframes[i]);
378                                 kfree(prxb);
379                                 prxb = NULL;
380                         }
381                         list_add_tail(&pRxReorderEntry->List,
382                                       &ieee->RxReorder_Unused_List);
383                 }
384         } else {
385                 struct tx_ts_record *pTxTS = (struct tx_ts_record *)pTs;
386
387                 del_timer_sync(&pTxTS->TsAddBaTimer);
388         }
389 }
390
391 void RemovePeerTS(struct rtllib_device *ieee, u8 *Addr)
392 {
393         struct ts_common_info *pTS, *pTmpTS;
394
395         netdev_info(ieee->dev, "===========>%s, %pM\n", __func__, Addr);
396
397         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List) {
398                 if (memcmp(pTS->Addr, Addr, 6) == 0) {
399                         RemoveTsEntry(ieee, pTS, TX_DIR);
400                         list_del_init(&pTS->List);
401                         list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
402                 }
403         }
404
405         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List) {
406                 if (memcmp(pTS->Addr, Addr, 6) == 0) {
407                         netdev_info(ieee->dev,
408                                     "====>remove Tx_TS_admin_list\n");
409                         RemoveTsEntry(ieee, pTS, TX_DIR);
410                         list_del_init(&pTS->List);
411                         list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
412                 }
413         }
414
415         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List) {
416                 if (memcmp(pTS->Addr, Addr, 6) == 0) {
417                         RemoveTsEntry(ieee, pTS, RX_DIR);
418                         list_del_init(&pTS->List);
419                         list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
420                 }
421         }
422
423         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List) {
424                 if (memcmp(pTS->Addr, Addr, 6) == 0) {
425                         RemoveTsEntry(ieee, pTS, RX_DIR);
426                         list_del_init(&pTS->List);
427                         list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
428                 }
429         }
430 }
431 EXPORT_SYMBOL(RemovePeerTS);
432
433 void RemoveAllTS(struct rtllib_device *ieee)
434 {
435         struct ts_common_info *pTS, *pTmpTS;
436
437         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List) {
438                 RemoveTsEntry(ieee, pTS, TX_DIR);
439                 list_del_init(&pTS->List);
440                 list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
441         }
442
443         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List) {
444                 RemoveTsEntry(ieee, pTS, TX_DIR);
445                 list_del_init(&pTS->List);
446                 list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
447         }
448
449         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List) {
450                 RemoveTsEntry(ieee, pTS, RX_DIR);
451                 list_del_init(&pTS->List);
452                 list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
453         }
454
455         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List) {
456                 RemoveTsEntry(ieee, pTS, RX_DIR);
457                 list_del_init(&pTS->List);
458                 list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
459         }
460 }
461
462 void TsStartAddBaProcess(struct rtllib_device *ieee, struct tx_ts_record *pTxTS)
463 {
464         if (pTxTS->bAddBaReqInProgress == false) {
465                 pTxTS->bAddBaReqInProgress = true;
466
467                 if (pTxTS->bAddBaReqDelayed) {
468                         netdev_dbg(ieee->dev, "Start ADDBA after 60 sec!!\n");
469                         mod_timer(&pTxTS->TsAddBaTimer, jiffies +
470                                   msecs_to_jiffies(TS_ADDBA_DELAY));
471                 } else {
472                         netdev_dbg(ieee->dev, "Immediately Start ADDBA\n");
473                         mod_timer(&pTxTS->TsAddBaTimer, jiffies + 10);
474                 }
475         } else {
476                 netdev_dbg(ieee->dev, "BA timer is already added\n");
477         }
478 }