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 } 479