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 related 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 } 535