root/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. TsSetupTimeOut
  2. TsInactTimeout
  3. RxPktPendingTimeout
  4. TsAddBaProcess
  5. ResetTsCommonInfo
  6. ResetTxTsEntry
  7. ResetRxTsEntry
  8. TSInitialize
  9. AdmitTS
  10. SearchAdmitTRStream
  11. MakeTSEntry
  12. GetTs
  13. RemoveTsEntry
  14. RemovePeerTS
  15. RemoveAllTS
  16. TsStartAddBaProcess

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include "ieee80211.h"
   3 #include <linux/etherdevice.h>
   4 #include <linux/slab.h>
   5 #include "rtl819x_TS.h"
   6 
   7 static void TsSetupTimeOut(struct timer_list *unused)
   8 {
   9         // Not implement yet
  10         // This is used for WMMSA and ACM , that would send ADDTSReq frame.
  11 }
  12 
  13 static void TsInactTimeout(struct timer_list *unused)
  14 {
  15         // Not implement yet
  16         // This is used for WMMSA and ACM.
  17         // This function would be call when TS is no Tx/Rx for some period of time.
  18 }
  19 
  20 /********************************************************************************************************************
  21  *function:  I still not understand this function, so wait for further implementation
  22  *   input:  unsigned long       data           //acturally we send struct tx_ts_record or struct rx_ts_record to these timer
  23  *  return:  NULL
  24  *  notice:
  25  ********************************************************************************************************************/
  26 static void RxPktPendingTimeout(struct timer_list *t)
  27 {
  28         struct rx_ts_record     *pRxTs = from_timer(pRxTs, t, rx_pkt_pending_timer);
  29         struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
  30 
  31         struct rx_reorder_entry *pReorderEntry = NULL;
  32 
  33         //u32 flags = 0;
  34         unsigned long flags = 0;
  35         u8 index = 0;
  36         bool bPktInBuf = false;
  37 
  38         spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
  39         IEEE80211_DEBUG(IEEE80211_DL_REORDER, "==================>%s()\n", __func__);
  40         if (pRxTs->rx_timeout_indicate_seq != 0xffff) {
  41                 // Indicate the pending packets sequentially according to SeqNum until meet the gap.
  42                 while (!list_empty(&pRxTs->rx_pending_pkt_list)) {
  43                         pReorderEntry = list_entry(pRxTs->rx_pending_pkt_list.prev, struct rx_reorder_entry, List);
  44                         if (index == 0)
  45                                 pRxTs->rx_indicate_seq = pReorderEntry->SeqNum;
  46 
  47                         if (SN_LESS(pReorderEntry->SeqNum, pRxTs->rx_indicate_seq) ||
  48                                 SN_EQUAL(pReorderEntry->SeqNum, pRxTs->rx_indicate_seq)) {
  49                                 list_del_init(&pReorderEntry->List);
  50 
  51                                 if (SN_EQUAL(pReorderEntry->SeqNum, pRxTs->rx_indicate_seq))
  52                                         pRxTs->rx_indicate_seq = (pRxTs->rx_indicate_seq + 1) % 4096;
  53 
  54                                 IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s: IndicateSeq: %d\n", __func__, pReorderEntry->SeqNum);
  55                                 ieee->stats_IndicateArray[index] = pReorderEntry->prxb;
  56                                 index++;
  57 
  58                                 list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List);
  59                         } else {
  60                                 bPktInBuf = true;
  61                                 break;
  62                         }
  63                 }
  64         }
  65 
  66         if (index > 0) {
  67                 // Set rx_timeout_indicate_seq to 0xffff to indicate no pending packets in buffer now.
  68                 pRxTs->rx_timeout_indicate_seq = 0xffff;
  69 
  70                 // Indicate packets
  71                 if (index > REORDER_WIN_SIZE) {
  72                         IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorder buffer full!! \n");
  73                         spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
  74                         return;
  75                 }
  76                 ieee80211_indicate_packets(ieee, ieee->stats_IndicateArray, index);
  77         }
  78 
  79         if (bPktInBuf && (pRxTs->rx_timeout_indicate_seq == 0xffff)) {
  80                 pRxTs->rx_timeout_indicate_seq = pRxTs->rx_indicate_seq;
  81                 mod_timer(&pRxTs->rx_pkt_pending_timer,
  82                           jiffies + msecs_to_jiffies(ieee->pHTInfo->RxReorderPendingTime));
  83         }
  84         spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
  85 }
  86 
  87 /********************************************************************************************************************
  88  *function:  Add BA timer function
  89  *   input:  unsigned long       data           //acturally we send struct tx_ts_record or struct rx_ts_record to these timer
  90  *  return:  NULL
  91  *  notice:
  92  ********************************************************************************************************************/
  93 static void TsAddBaProcess(struct timer_list *t)
  94 {
  95         struct tx_ts_record *pTxTs = from_timer(pTxTs, t, ts_add_ba_timer);
  96         u8 num = pTxTs->num;
  97         struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[num]);
  98 
  99         TsInitAddBA(ieee, pTxTs, BA_POLICY_IMMEDIATE, false);
 100         IEEE80211_DEBUG(IEEE80211_DL_BA, "%s: ADDBA Req is started!! \n", __func__);
 101 }
 102 
 103 
 104 static void ResetTsCommonInfo(struct ts_common_info *pTsCommonInfo)
 105 {
 106         eth_zero_addr(pTsCommonInfo->addr);
 107         memset(&pTsCommonInfo->t_spec, 0, sizeof(struct tspec_body));
 108         memset(&pTsCommonInfo->t_class, 0, sizeof(union qos_tclas) * TCLAS_NUM);
 109         pTsCommonInfo->t_clas_proc = 0;
 110         pTsCommonInfo->t_clas_num = 0;
 111 }
 112 
 113 static void ResetTxTsEntry(struct tx_ts_record *pTS)
 114 {
 115         ResetTsCommonInfo(&pTS->ts_common_info);
 116         pTS->tx_cur_seq = 0;
 117         pTS->add_ba_req_in_progress = false;
 118         pTS->add_ba_req_delayed = false;
 119         pTS->using_ba = false;
 120         ResetBaEntry(&pTS->tx_admitted_ba_record); //For BA Originator
 121         ResetBaEntry(&pTS->tx_pending_ba_record);
 122 }
 123 
 124 static void ResetRxTsEntry(struct rx_ts_record *pTS)
 125 {
 126         ResetTsCommonInfo(&pTS->ts_common_info);
 127         pTS->rx_indicate_seq = 0xffff; // This indicate the rx_indicate_seq is not used now!!
 128         pTS->rx_timeout_indicate_seq = 0xffff; // This indicate the rx_timeout_indicate_seq is not used now!!
 129         ResetBaEntry(&pTS->rx_admitted_ba_record);        // For BA Recipient
 130 }
 131 
 132 void TSInitialize(struct ieee80211_device *ieee)
 133 {
 134         struct tx_ts_record     *pTxTS  = ieee->TxTsRecord;
 135         struct rx_ts_record     *pRxTS  = ieee->RxTsRecord;
 136         struct rx_reorder_entry *pRxReorderEntry = ieee->RxReorderEntry;
 137         u8                              count = 0;
 138         IEEE80211_DEBUG(IEEE80211_DL_TS, "==========>%s()\n", __func__);
 139         // Initialize Tx TS related info.
 140         INIT_LIST_HEAD(&ieee->Tx_TS_Admit_List);
 141         INIT_LIST_HEAD(&ieee->Tx_TS_Pending_List);
 142         INIT_LIST_HEAD(&ieee->Tx_TS_Unused_List);
 143 
 144         for (count = 0; count < TOTAL_TS_NUM; count++) {
 145                 //
 146                 pTxTS->num = count;
 147                 // The timers for the operation of Traffic Stream and Block Ack.
 148                 // DLS related timer will be add here in the future!!
 149                 timer_setup(&pTxTS->ts_common_info.setup_timer, TsSetupTimeOut,
 150                             0);
 151                 timer_setup(&pTxTS->ts_common_info.inact_timer, TsInactTimeout,
 152                             0);
 153                 timer_setup(&pTxTS->ts_add_ba_timer, TsAddBaProcess, 0);
 154                 timer_setup(&pTxTS->tx_pending_ba_record.timer, BaSetupTimeOut,
 155                             0);
 156                 timer_setup(&pTxTS->tx_admitted_ba_record.timer,
 157                             TxBaInactTimeout, 0);
 158                 ResetTxTsEntry(pTxTS);
 159                 list_add_tail(&pTxTS->ts_common_info.list, &ieee->Tx_TS_Unused_List);
 160                 pTxTS++;
 161         }
 162 
 163         // Initialize Rx TS related info.
 164         INIT_LIST_HEAD(&ieee->Rx_TS_Admit_List);
 165         INIT_LIST_HEAD(&ieee->Rx_TS_Pending_List);
 166         INIT_LIST_HEAD(&ieee->Rx_TS_Unused_List);
 167         for (count = 0; count < TOTAL_TS_NUM; count++) {
 168                 pRxTS->num = count;
 169                 INIT_LIST_HEAD(&pRxTS->rx_pending_pkt_list);
 170                 timer_setup(&pRxTS->ts_common_info.setup_timer, TsSetupTimeOut,
 171                             0);
 172                 timer_setup(&pRxTS->ts_common_info.inact_timer, TsInactTimeout,
 173                             0);
 174                 timer_setup(&pRxTS->rx_admitted_ba_record.timer,
 175                             RxBaInactTimeout, 0);
 176                 timer_setup(&pRxTS->rx_pkt_pending_timer, RxPktPendingTimeout, 0);
 177                 ResetRxTsEntry(pRxTS);
 178                 list_add_tail(&pRxTS->ts_common_info.list, &ieee->Rx_TS_Unused_List);
 179                 pRxTS++;
 180         }
 181         // Initialize unused Rx Reorder List.
 182         INIT_LIST_HEAD(&ieee->RxReorder_Unused_List);
 183         for (count = 0; count < REORDER_ENTRY_NUM; count++) {
 184                 list_add_tail(&pRxReorderEntry->List, &ieee->RxReorder_Unused_List);
 185                 if (count == (REORDER_ENTRY_NUM - 1))
 186                         break;
 187                 pRxReorderEntry = &ieee->RxReorderEntry[count + 1];
 188         }
 189 }
 190 
 191 static void AdmitTS(struct ieee80211_device *ieee,
 192                     struct ts_common_info *pTsCommonInfo, u32 InactTime)
 193 {
 194         del_timer_sync(&pTsCommonInfo->setup_timer);
 195         del_timer_sync(&pTsCommonInfo->inact_timer);
 196 
 197         if (InactTime != 0)
 198                 mod_timer(&pTsCommonInfo->inact_timer,
 199                           jiffies + msecs_to_jiffies(InactTime));
 200 }
 201 
 202 
 203 static struct ts_common_info *SearchAdmitTRStream(struct ieee80211_device *ieee,
 204                                                   u8 *Addr, u8 TID,
 205                                                   enum tr_select TxRxSelect)
 206 {
 207         //DIRECTION_VALUE       dir;
 208         u8      dir;
 209         bool                            search_dir[4] = {0};
 210         struct list_head                *psearch_list; //FIXME
 211         struct ts_common_info   *pRet = NULL;
 212         if (ieee->iw_mode == IW_MODE_MASTER) { //ap mode
 213                 if (TxRxSelect == TX_DIR) {
 214                         search_dir[DIR_DOWN] = true;
 215                         search_dir[DIR_BI_DIR] = true;
 216                 } else {
 217                         search_dir[DIR_UP]      = true;
 218                         search_dir[DIR_BI_DIR] = true;
 219                 }
 220         } else if (ieee->iw_mode == IW_MODE_ADHOC) {
 221                 if (TxRxSelect == TX_DIR)
 222                         search_dir[DIR_UP]      = true;
 223                 else
 224                         search_dir[DIR_DOWN] = true;
 225         } else {
 226                 if (TxRxSelect == TX_DIR) {
 227                         search_dir[DIR_UP]      = true;
 228                         search_dir[DIR_BI_DIR] = true;
 229                         search_dir[DIR_DIRECT] = true;
 230                 } else {
 231                         search_dir[DIR_DOWN] = true;
 232                         search_dir[DIR_BI_DIR] = true;
 233                         search_dir[DIR_DIRECT] = true;
 234                 }
 235         }
 236 
 237         if (TxRxSelect == TX_DIR)
 238                 psearch_list = &ieee->Tx_TS_Admit_List;
 239         else
 240                 psearch_list = &ieee->Rx_TS_Admit_List;
 241 
 242         //for(dir = DIR_UP; dir <= DIR_BI_DIR; dir++)
 243         for (dir = 0; dir <= DIR_BI_DIR; dir++) {
 244                 if (!search_dir[dir])
 245                         continue;
 246                 list_for_each_entry(pRet, psearch_list, list) {
 247         //              IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:%pM, TID:%d, dir:%d\n", pRet->Addr, pRet->TSpec.ts_info.ucTSID, pRet->TSpec.ts_info.ucDirection);
 248                         if (memcmp(pRet->addr, Addr, 6) == 0)
 249                                 if (pRet->t_spec.ts_info.uc_tsid == TID)
 250                                         if (pRet->t_spec.ts_info.uc_direction == dir) {
 251         //                                      printk("Bingo! got it\n");
 252                                                 break;
 253                                         }
 254                 }
 255                 if (&pRet->list  != psearch_list)
 256                         break;
 257         }
 258 
 259         if (&pRet->list  != psearch_list)
 260                 return pRet;
 261         else
 262                 return NULL;
 263 }
 264 
 265 static void MakeTSEntry(struct ts_common_info *pTsCommonInfo, u8 *Addr,
 266                         struct tspec_body *pTSPEC, union qos_tclas *pTCLAS, u8 TCLAS_Num,
 267                         u8 TCLAS_Proc)
 268 {
 269         u8      count;
 270 
 271         if (pTsCommonInfo == NULL)
 272                 return;
 273 
 274         memcpy(pTsCommonInfo->addr, Addr, 6);
 275 
 276         if (pTSPEC != NULL)
 277                 memcpy((u8 *)(&(pTsCommonInfo->t_spec)), (u8 *)pTSPEC, sizeof(struct tspec_body));
 278 
 279         for (count = 0; count < TCLAS_Num; count++)
 280                 memcpy((u8 *)(&(pTsCommonInfo->t_class[count])), (u8 *)pTCLAS, sizeof(union qos_tclas));
 281 
 282         pTsCommonInfo->t_clas_proc = TCLAS_Proc;
 283         pTsCommonInfo->t_clas_num = TCLAS_Num;
 284 }
 285 
 286 
 287 bool GetTs(
 288         struct ieee80211_device         *ieee,
 289         struct ts_common_info           **ppTS,
 290         u8                              *Addr,
 291         u8                              TID,
 292         enum tr_select                  TxRxSelect,  //Rx:1, Tx:0
 293         bool                            bAddNewTs
 294         )
 295 {
 296         u8      UP = 0;
 297         //
 298         // We do not build any TS for Broadcast or Multicast stream.
 299         // So reject these kinds of search here.
 300         //
 301         if (is_multicast_ether_addr(Addr)) {
 302                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "get TS for Broadcast or Multicast\n");
 303                 return false;
 304         }
 305 
 306         if (ieee->current_network.qos_data.supported == 0) {
 307                 UP = 0;
 308         } else {
 309                 // In WMM case: we use 4 TID only
 310                 if (!is_ac_valid(TID)) {
 311                         IEEE80211_DEBUG(IEEE80211_DL_ERR, " in %s(), TID(%d) is not valid\n", __func__, TID);
 312                         return false;
 313                 }
 314 
 315                 switch (TID) {
 316                 case 0:
 317                 case 3:
 318                         UP = 0;
 319                         break;
 320 
 321                 case 1:
 322                 case 2:
 323                         UP = 2;
 324                         break;
 325 
 326                 case 4:
 327                 case 5:
 328                         UP = 5;
 329                         break;
 330 
 331                 case 6:
 332                 case 7:
 333                         UP = 7;
 334                         break;
 335                 }
 336         }
 337 
 338         *ppTS = SearchAdmitTRStream(
 339                         ieee,
 340                         Addr,
 341                         UP,
 342                         TxRxSelect);
 343         if (*ppTS != NULL) {
 344                 return true;
 345         } else {
 346                 if (!bAddNewTs) {
 347                         IEEE80211_DEBUG(IEEE80211_DL_TS, "add new TS failed(tid:%d)\n", UP);
 348                         return false;
 349                 } else {
 350                         //
 351                         // Create a new Traffic stream for current Tx/Rx
 352                         // This is for EDCA and WMM to add a new TS.
 353                         // For HCCA or WMMSA, TS cannot be addmit without negotiation.
 354                         //
 355                         struct tspec_body       TSpec;
 356                         struct qos_tsinfo       *pTSInfo = &TSpec.ts_info;
 357                         struct list_head        *pUnusedList =
 358                                                                 (TxRxSelect == TX_DIR) ?
 359                                                                 (&ieee->Tx_TS_Unused_List) :
 360                                                                 (&ieee->Rx_TS_Unused_List);
 361 
 362                         struct list_head        *pAddmitList =
 363                                                                 (TxRxSelect == TX_DIR) ?
 364                                                                 (&ieee->Tx_TS_Admit_List) :
 365                                                                 (&ieee->Rx_TS_Admit_List);
 366 
 367                         enum direction_value    Dir =           (ieee->iw_mode == IW_MODE_MASTER) ?
 368                                                                 ((TxRxSelect == TX_DIR) ? DIR_DOWN : DIR_UP) :
 369                                                                 ((TxRxSelect == TX_DIR) ? DIR_UP : DIR_DOWN);
 370                         IEEE80211_DEBUG(IEEE80211_DL_TS, "to add Ts\n");
 371                         if (!list_empty(pUnusedList)) {
 372                                 (*ppTS) = list_entry(pUnusedList->next, struct ts_common_info, list);
 373                                 list_del_init(&(*ppTS)->list);
 374                                 if (TxRxSelect == TX_DIR) {
 375                                         struct tx_ts_record *tmp = container_of(*ppTS, struct tx_ts_record, ts_common_info);
 376                                         ResetTxTsEntry(tmp);
 377                                 } else {
 378                                         struct rx_ts_record *tmp = container_of(*ppTS, struct rx_ts_record, ts_common_info);
 379                                         ResetRxTsEntry(tmp);
 380                                 }
 381 
 382                                 IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:%pM\n", UP, Dir, Addr);
 383                                 // Prepare TS Info releated field
 384                                 pTSInfo->uc_traffic_type = 0;           // Traffic type: WMM is reserved in this field
 385                                 pTSInfo->uc_tsid = UP;                  // TSID
 386                                 pTSInfo->uc_direction = Dir;            // Direction: if there is DirectLink, this need additional consideration.
 387                                 pTSInfo->uc_access_policy = 1;          // Access policy
 388                                 pTSInfo->uc_aggregation = 0;            // Aggregation
 389                                 pTSInfo->uc_psb = 0;                    // Aggregation
 390                                 pTSInfo->uc_up = UP;                    // User priority
 391                                 pTSInfo->uc_ts_info_ack_policy = 0;     // Ack policy
 392                                 pTSInfo->uc_schedule = 0;               // Schedule
 393 
 394                                 MakeTSEntry(*ppTS, Addr, &TSpec, NULL, 0, 0);
 395                                 AdmitTS(ieee, *ppTS, 0);
 396                                 list_add_tail(&((*ppTS)->list), pAddmitList);
 397                                 // if there is DirectLink, we need to do additional operation here!!
 398 
 399                                 return true;
 400                         } else {
 401                                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "in function %s() There is not enough TS record to be used!!", __func__);
 402                                 return false;
 403                         }
 404                 }
 405         }
 406 }
 407 
 408 static void RemoveTsEntry(struct ieee80211_device *ieee, struct ts_common_info *pTs,
 409                           enum tr_select TxRxSelect)
 410 {
 411         //u32 flags = 0;
 412         unsigned long flags = 0;
 413         del_timer_sync(&pTs->setup_timer);
 414         del_timer_sync(&pTs->inact_timer);
 415         TsInitDelBA(ieee, pTs, TxRxSelect);
 416 
 417         if (TxRxSelect == RX_DIR) {
 418                 struct rx_reorder_entry *pRxReorderEntry;
 419                 struct rx_ts_record     *pRxTS = (struct rx_ts_record *)pTs;
 420                 if (timer_pending(&pRxTS->rx_pkt_pending_timer))
 421                         del_timer_sync(&pRxTS->rx_pkt_pending_timer);
 422 
 423                 while (!list_empty(&pRxTS->rx_pending_pkt_list)) {
 424                         spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
 425                         //pRxReorderEntry = list_entry(&pRxTS->rx_pending_pkt_list.prev,RX_REORDER_ENTRY,List);
 426                         pRxReorderEntry = list_entry(pRxTS->rx_pending_pkt_list.prev, struct rx_reorder_entry, List);
 427                         list_del_init(&pRxReorderEntry->List);
 428                         {
 429                                 int i = 0;
 430                                 struct ieee80211_rxb *prxb = pRxReorderEntry->prxb;
 431                                 if (unlikely(!prxb)) {
 432                                         spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
 433                                         return;
 434                                 }
 435                                 for (i =  0; i < prxb->nr_subframes; i++)
 436                                         dev_kfree_skb(prxb->subframes[i]);
 437 
 438                                 kfree(prxb);
 439                                 prxb = NULL;
 440                         }
 441                         list_add_tail(&pRxReorderEntry->List, &ieee->RxReorder_Unused_List);
 442                         spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
 443                 }
 444 
 445         } else {
 446                 struct tx_ts_record *pTxTS = (struct tx_ts_record *)pTs;
 447                 del_timer_sync(&pTxTS->ts_add_ba_timer);
 448         }
 449 }
 450 
 451 void RemovePeerTS(struct ieee80211_device *ieee, u8 *Addr)
 452 {
 453         struct ts_common_info   *pTS, *pTmpTS;
 454 
 455         printk("===========>%s,%pM\n", __func__, Addr);
 456         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, list) {
 457                 if (memcmp(pTS->addr, Addr, 6) == 0) {
 458                         RemoveTsEntry(ieee, pTS, TX_DIR);
 459                         list_del_init(&pTS->list);
 460                         list_add_tail(&pTS->list, &ieee->Tx_TS_Unused_List);
 461                 }
 462         }
 463 
 464         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, list) {
 465                 if (memcmp(pTS->addr, Addr, 6) == 0) {
 466                         printk("====>remove Tx_TS_admin_list\n");
 467                         RemoveTsEntry(ieee, pTS, TX_DIR);
 468                         list_del_init(&pTS->list);
 469                         list_add_tail(&pTS->list, &ieee->Tx_TS_Unused_List);
 470                 }
 471         }
 472 
 473         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, list) {
 474                 if (memcmp(pTS->addr, Addr, 6) == 0) {
 475                         RemoveTsEntry(ieee, pTS, RX_DIR);
 476                         list_del_init(&pTS->list);
 477                         list_add_tail(&pTS->list, &ieee->Rx_TS_Unused_List);
 478                 }
 479         }
 480 
 481         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, list) {
 482                 if (memcmp(pTS->addr, Addr, 6) == 0) {
 483                         RemoveTsEntry(ieee, pTS, RX_DIR);
 484                         list_del_init(&pTS->list);
 485                         list_add_tail(&pTS->list, &ieee->Rx_TS_Unused_List);
 486                 }
 487         }
 488 }
 489 
 490 void RemoveAllTS(struct ieee80211_device *ieee)
 491 {
 492         struct ts_common_info *pTS, *pTmpTS;
 493 
 494         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, list) {
 495                 RemoveTsEntry(ieee, pTS, TX_DIR);
 496                 list_del_init(&pTS->list);
 497                 list_add_tail(&pTS->list, &ieee->Tx_TS_Unused_List);
 498         }
 499 
 500         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, list) {
 501                 RemoveTsEntry(ieee, pTS, TX_DIR);
 502                 list_del_init(&pTS->list);
 503                 list_add_tail(&pTS->list, &ieee->Tx_TS_Unused_List);
 504         }
 505 
 506         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, list) {
 507                 RemoveTsEntry(ieee, pTS, RX_DIR);
 508                 list_del_init(&pTS->list);
 509                 list_add_tail(&pTS->list, &ieee->Rx_TS_Unused_List);
 510         }
 511 
 512         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, list) {
 513                 RemoveTsEntry(ieee, pTS, RX_DIR);
 514                 list_del_init(&pTS->list);
 515                 list_add_tail(&pTS->list, &ieee->Rx_TS_Unused_List);
 516         }
 517 }
 518 
 519 void TsStartAddBaProcess(struct ieee80211_device *ieee, struct tx_ts_record *pTxTS)
 520 {
 521         if (!pTxTS->add_ba_req_in_progress) {
 522                 pTxTS->add_ba_req_in_progress = true;
 523                 if (pTxTS->add_ba_req_delayed)  {
 524                         IEEE80211_DEBUG(IEEE80211_DL_BA, "%s: Delayed Start ADDBA after 60 sec!!\n", __func__);
 525                         mod_timer(&pTxTS->ts_add_ba_timer,
 526                                   jiffies + msecs_to_jiffies(TS_ADDBA_DELAY));
 527                 } else {
 528                         IEEE80211_DEBUG(IEEE80211_DL_BA, "%s: Immediately Start ADDBA now!!\n", __func__);
 529                         mod_timer(&pTxTS->ts_add_ba_timer, jiffies + 10); //set 10 ticks
 530                 }
 531         } else {
 532                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s()==>BA timer is already added\n", __func__);
 533         }
 534 }

/* [<][>][^][v][top][bottom][index][help] */