Commit | Line | Data |
---|---|---|
94a79942 LF |
1 | /****************************************************************************** |
2 | * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. | |
3 | * | |
4 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
5 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
6 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
7 | * more details. | |
8 | * | |
9 | * You should have received a copy of the GNU General Public License along with | |
10 | * this program; if not, write to the Free Software Foundation, Inc., | |
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | |
12 | * | |
13 | * The full GNU General Public License is included in this distribution in the | |
14 | * file called LICENSE. | |
15 | * | |
16 | * Contact Information: | |
17 | * wlanfae <wlanfae@realtek.com> | |
18 | ******************************************************************************/ | |
19 | #include "rtllib.h" | |
20 | #include <linux/etherdevice.h> | |
21 | #include "rtl819x_TS.h" | |
cb762154 | 22 | |
ec0dc6be | 23 | static void TsSetupTimeOut(unsigned long data) |
94a79942 LF |
24 | { |
25 | } | |
26 | ||
ec0dc6be | 27 | static void TsInactTimeout(unsigned long data) |
94a79942 LF |
28 | { |
29 | } | |
30 | ||
ec0dc6be | 31 | static void RxPktPendingTimeout(unsigned long data) |
94a79942 | 32 | { |
2c47ae28 | 33 | struct rx_ts_record *pRxTs = (struct rx_ts_record *)data; |
f88ec6cb LF |
34 | struct rtllib_device *ieee = container_of(pRxTs, struct rtllib_device, |
35 | RxTsRecord[pRxTs->num]); | |
94a79942 | 36 | |
8cba1432 | 37 | struct rx_reorder_entry *pReorderEntry = NULL; |
94a79942 LF |
38 | |
39 | unsigned long flags = 0; | |
40 | struct rtllib_rxb *stats_IndicateArray[REORDER_WIN_SIZE]; | |
41 | u8 index = 0; | |
42 | bool bPktInBuf = false; | |
43 | ||
44 | spin_lock_irqsave(&(ieee->reorder_spinlock), flags); | |
f88ec6cb LF |
45 | if (pRxTs->RxTimeoutIndicateSeq != 0xffff) { |
46 | while (!list_empty(&pRxTs->RxPendingPktList)) { | |
47 | pReorderEntry = (struct rx_reorder_entry *) | |
48 | list_entry(pRxTs->RxPendingPktList.prev, | |
49 | struct rx_reorder_entry, List); | |
94a79942 LF |
50 | if (index == 0) |
51 | pRxTs->RxIndicateSeq = pReorderEntry->SeqNum; | |
52 | ||
f88ec6cb LF |
53 | if (SN_LESS(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) || |
54 | SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq)) { | |
94a79942 LF |
55 | list_del_init(&pReorderEntry->List); |
56 | ||
f88ec6cb LF |
57 | if (SN_EQUAL(pReorderEntry->SeqNum, |
58 | pRxTs->RxIndicateSeq)) | |
59 | pRxTs->RxIndicateSeq = | |
60 | (pRxTs->RxIndicateSeq + 1) % 4096; | |
94a79942 | 61 | |
f88ec6cb LF |
62 | RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Indicate" |
63 | " SeqNum: %d\n", __func__, | |
64 | pReorderEntry->SeqNum); | |
65 | stats_IndicateArray[index] = | |
66 | pReorderEntry->prxb; | |
94a79942 LF |
67 | index++; |
68 | ||
f88ec6cb LF |
69 | list_add_tail(&pReorderEntry->List, |
70 | &ieee->RxReorder_Unused_List); | |
71 | } else { | |
94a79942 LF |
72 | bPktInBuf = true; |
73 | break; | |
74 | } | |
75 | } | |
76 | } | |
77 | ||
f88ec6cb | 78 | if (index > 0) { |
94a79942 LF |
79 | pRxTs->RxTimeoutIndicateSeq = 0xffff; |
80 | ||
f88ec6cb LF |
81 | if (index > REORDER_WIN_SIZE) { |
82 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket():" | |
83 | " Rx Reorer struct buffer full!!\n"); | |
84 | spin_unlock_irqrestore(&(ieee->reorder_spinlock), | |
85 | flags); | |
94a79942 LF |
86 | return; |
87 | } | |
88 | rtllib_indicate_packets(ieee, stats_IndicateArray, index); | |
89 | bPktInBuf = false; | |
90 | } | |
91 | ||
f88ec6cb | 92 | if (bPktInBuf && (pRxTs->RxTimeoutIndicateSeq == 0xffff)) { |
94a79942 | 93 | pRxTs->RxTimeoutIndicateSeq = pRxTs->RxIndicateSeq; |
f88ec6cb LF |
94 | mod_timer(&pRxTs->RxPktPendingTimer, jiffies + |
95 | MSECS(ieee->pHTInfo->RxReorderPendingTime)); | |
94a79942 LF |
96 | } |
97 | spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); | |
98 | } | |
99 | ||
ec0dc6be | 100 | static void TsAddBaProcess(unsigned long data) |
94a79942 | 101 | { |
60554f2b | 102 | struct tx_ts_record *pTxTs = (struct tx_ts_record *)data; |
94a79942 | 103 | u8 num = pTxTs->num; |
f88ec6cb LF |
104 | struct rtllib_device *ieee = container_of(pTxTs, struct rtllib_device, |
105 | TxTsRecord[num]); | |
94a79942 LF |
106 | |
107 | TsInitAddBA(ieee, pTxTs, BA_POLICY_IMMEDIATE, false); | |
f88ec6cb LF |
108 | RTLLIB_DEBUG(RTLLIB_DL_BA, "TsAddBaProcess(): ADDBA Req is " |
109 | "started!!\n"); | |
94a79942 LF |
110 | } |
111 | ||
ec0dc6be | 112 | static void ResetTsCommonInfo(struct ts_common_info *pTsCommonInfo) |
94a79942 LF |
113 | { |
114 | memset(pTsCommonInfo->Addr, 0, 6); | |
ed306e48 | 115 | memset(&pTsCommonInfo->TSpec, 0, sizeof(union tspec_body)); |
626f951d | 116 | memset(&pTsCommonInfo->TClass, 0, sizeof(union qos_tclas)*TCLAS_NUM); |
94a79942 LF |
117 | pTsCommonInfo->TClasProc = 0; |
118 | pTsCommonInfo->TClasNum = 0; | |
119 | } | |
120 | ||
ec0dc6be | 121 | static void ResetTxTsEntry(struct tx_ts_record *pTS) |
94a79942 LF |
122 | { |
123 | ResetTsCommonInfo(&pTS->TsCommonInfo); | |
124 | pTS->TxCurSeq = 0; | |
125 | pTS->bAddBaReqInProgress = false; | |
126 | pTS->bAddBaReqDelayed = false; | |
127 | pTS->bUsingBa = false; | |
128 | pTS->bDisable_AddBa = false; | |
129 | ResetBaEntry(&pTS->TxAdmittedBARecord); | |
130 | ResetBaEntry(&pTS->TxPendingBARecord); | |
131 | } | |
132 | ||
ec0dc6be | 133 | static void ResetRxTsEntry(struct rx_ts_record *pTS) |
94a79942 LF |
134 | { |
135 | ResetTsCommonInfo(&pTS->TsCommonInfo); | |
136 | pTS->RxIndicateSeq = 0xffff; | |
137 | pTS->RxTimeoutIndicateSeq = 0xffff; | |
138 | ResetBaEntry(&pTS->RxAdmittedBARecord); | |
139 | } | |
94a79942 LF |
140 | |
141 | void TSInitialize(struct rtllib_device *ieee) | |
142 | { | |
60554f2b | 143 | struct tx_ts_record *pTxTS = ieee->TxTsRecord; |
2c47ae28 | 144 | struct rx_ts_record *pRxTS = ieee->RxTsRecord; |
8cba1432 | 145 | struct rx_reorder_entry *pRxReorderEntry = ieee->RxReorderEntry; |
94a79942 LF |
146 | u8 count = 0; |
147 | RTLLIB_DEBUG(RTLLIB_DL_TS, "==========>%s()\n", __func__); | |
148 | INIT_LIST_HEAD(&ieee->Tx_TS_Admit_List); | |
149 | INIT_LIST_HEAD(&ieee->Tx_TS_Pending_List); | |
150 | INIT_LIST_HEAD(&ieee->Tx_TS_Unused_List); | |
151 | ||
f88ec6cb | 152 | for (count = 0; count < TOTAL_TS_NUM; count++) { |
94a79942 LF |
153 | pTxTS->num = count; |
154 | _setup_timer(&pTxTS->TsCommonInfo.SetupTimer, | |
155 | TsSetupTimeOut, | |
156 | (unsigned long) pTxTS); | |
157 | ||
158 | _setup_timer(&pTxTS->TsCommonInfo.InactTimer, | |
159 | TsInactTimeout, | |
160 | (unsigned long) pTxTS); | |
161 | ||
162 | _setup_timer(&pTxTS->TsAddBaTimer, | |
163 | TsAddBaProcess, | |
164 | (unsigned long) pTxTS); | |
165 | ||
166 | _setup_timer(&pTxTS->TxPendingBARecord.Timer, | |
167 | BaSetupTimeOut, | |
168 | (unsigned long) pTxTS); | |
169 | _setup_timer(&pTxTS->TxAdmittedBARecord.Timer, | |
170 | TxBaInactTimeout, | |
171 | (unsigned long) pTxTS); | |
172 | ||
173 | ResetTxTsEntry(pTxTS); | |
174 | list_add_tail(&pTxTS->TsCommonInfo.List, | |
175 | &ieee->Tx_TS_Unused_List); | |
176 | pTxTS++; | |
177 | } | |
178 | ||
179 | INIT_LIST_HEAD(&ieee->Rx_TS_Admit_List); | |
180 | INIT_LIST_HEAD(&ieee->Rx_TS_Pending_List); | |
181 | INIT_LIST_HEAD(&ieee->Rx_TS_Unused_List); | |
f88ec6cb | 182 | for (count = 0; count < TOTAL_TS_NUM; count++) { |
94a79942 LF |
183 | pRxTS->num = count; |
184 | INIT_LIST_HEAD(&pRxTS->RxPendingPktList); | |
185 | ||
186 | _setup_timer(&pRxTS->TsCommonInfo.SetupTimer, | |
187 | TsSetupTimeOut, | |
188 | (unsigned long) pRxTS); | |
189 | ||
190 | _setup_timer(&pRxTS->TsCommonInfo.InactTimer, | |
191 | TsInactTimeout, | |
192 | (unsigned long) pRxTS); | |
193 | ||
194 | _setup_timer(&pRxTS->RxAdmittedBARecord.Timer, | |
195 | RxBaInactTimeout, | |
196 | (unsigned long) pRxTS); | |
197 | ||
198 | _setup_timer(&pRxTS->RxPktPendingTimer, | |
199 | RxPktPendingTimeout, | |
200 | (unsigned long) pRxTS); | |
201 | ||
202 | ResetRxTsEntry(pRxTS); | |
f88ec6cb LF |
203 | list_add_tail(&pRxTS->TsCommonInfo.List, |
204 | &ieee->Rx_TS_Unused_List); | |
94a79942 LF |
205 | pRxTS++; |
206 | } | |
207 | INIT_LIST_HEAD(&ieee->RxReorder_Unused_List); | |
f88ec6cb LF |
208 | for (count = 0; count < REORDER_ENTRY_NUM; count++) { |
209 | list_add_tail(&pRxReorderEntry->List, | |
210 | &ieee->RxReorder_Unused_List); | |
94a79942 LF |
211 | if (count == (REORDER_ENTRY_NUM-1)) |
212 | break; | |
213 | pRxReorderEntry = &ieee->RxReorderEntry[count+1]; | |
214 | } | |
215 | ||
216 | } | |
217 | ||
ec0dc6be LF |
218 | static void AdmitTS(struct rtllib_device *ieee, |
219 | struct ts_common_info *pTsCommonInfo, u32 InactTime) | |
94a79942 LF |
220 | { |
221 | del_timer_sync(&pTsCommonInfo->SetupTimer); | |
222 | del_timer_sync(&pTsCommonInfo->InactTimer); | |
223 | ||
f88ec6cb LF |
224 | if (InactTime != 0) |
225 | mod_timer(&pTsCommonInfo->InactTimer, jiffies + | |
226 | MSECS(InactTime)); | |
94a79942 LF |
227 | } |
228 | ||
ec0dc6be LF |
229 | static struct ts_common_info *SearchAdmitTRStream(struct rtllib_device *ieee, |
230 | u8 *Addr, u8 TID, | |
231 | enum tr_select TxRxSelect) | |
94a79942 LF |
232 | { |
233 | u8 dir; | |
ec0dc6be | 234 | bool search_dir[4] = {0}; |
f88ec6cb | 235 | struct list_head *psearch_list; |
74724de1 | 236 | struct ts_common_info *pRet = NULL; |
f88ec6cb LF |
237 | if (ieee->iw_mode == IW_MODE_MASTER) { |
238 | if (TxRxSelect == TX_DIR) { | |
94a79942 | 239 | search_dir[DIR_DOWN] = true; |
f88ec6cb LF |
240 | search_dir[DIR_BI_DIR] = true; |
241 | } else { | |
242 | search_dir[DIR_UP] = true; | |
243 | search_dir[DIR_BI_DIR] = true; | |
94a79942 | 244 | } |
f88ec6cb | 245 | } else if (ieee->iw_mode == IW_MODE_ADHOC) { |
94a79942 | 246 | if (TxRxSelect == TX_DIR) |
f88ec6cb | 247 | search_dir[DIR_UP] = true; |
94a79942 LF |
248 | else |
249 | search_dir[DIR_DOWN] = true; | |
f88ec6cb LF |
250 | } else { |
251 | if (TxRxSelect == TX_DIR) { | |
252 | search_dir[DIR_UP] = true; | |
253 | search_dir[DIR_BI_DIR] = true; | |
254 | search_dir[DIR_DIRECT] = true; | |
255 | } else { | |
94a79942 | 256 | search_dir[DIR_DOWN] = true; |
f88ec6cb LF |
257 | search_dir[DIR_BI_DIR] = true; |
258 | search_dir[DIR_DIRECT] = true; | |
94a79942 LF |
259 | } |
260 | } | |
261 | ||
262 | if (TxRxSelect == TX_DIR) | |
263 | psearch_list = &ieee->Tx_TS_Admit_List; | |
264 | else | |
265 | psearch_list = &ieee->Rx_TS_Admit_List; | |
266 | ||
f88ec6cb LF |
267 | for (dir = 0; dir <= DIR_BI_DIR; dir++) { |
268 | if (search_dir[dir] == false) | |
94a79942 | 269 | continue; |
f88ec6cb | 270 | list_for_each_entry(pRet, psearch_list, List) { |
94a79942 LF |
271 | if (memcmp(pRet->Addr, Addr, 6) == 0) |
272 | if (pRet->TSpec.f.TSInfo.field.ucTSID == TID) | |
273 | if (pRet->TSpec.f.TSInfo.field.ucDirection == dir) | |
94a79942 | 274 | break; |
94a79942 LF |
275 | |
276 | } | |
277 | if (&pRet->List != psearch_list) | |
278 | break; | |
279 | } | |
280 | ||
f88ec6cb | 281 | if (&pRet->List != psearch_list) |
94a79942 | 282 | return pRet ; |
94a79942 LF |
283 | else |
284 | return NULL; | |
285 | } | |
286 | ||
ec0dc6be LF |
287 | static void MakeTSEntry(struct ts_common_info *pTsCommonInfo, u8 *Addr, |
288 | union tspec_body *pTSPEC, union qos_tclas *pTCLAS, | |
289 | u8 TCLAS_Num, u8 TCLAS_Proc) | |
94a79942 LF |
290 | { |
291 | u8 count; | |
292 | ||
293 | if (pTsCommonInfo == NULL) | |
294 | return; | |
295 | ||
296 | memcpy(pTsCommonInfo->Addr, Addr, 6); | |
297 | ||
298 | if (pTSPEC != NULL) | |
f88ec6cb LF |
299 | memcpy((u8 *)(&(pTsCommonInfo->TSpec)), (u8 *)pTSPEC, |
300 | sizeof(union tspec_body)); | |
94a79942 LF |
301 | |
302 | for (count = 0; count < TCLAS_Num; count++) | |
f88ec6cb LF |
303 | memcpy((u8 *)(&(pTsCommonInfo->TClass[count])), |
304 | (u8 *)pTCLAS, sizeof(union qos_tclas)); | |
94a79942 LF |
305 | |
306 | pTsCommonInfo->TClasProc = TCLAS_Proc; | |
307 | pTsCommonInfo->TClasNum = TCLAS_Num; | |
308 | } | |
309 | ||
f88ec6cb LF |
310 | bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS, |
311 | u8 *Addr, u8 TID, enum tr_select TxRxSelect, bool bAddNewTs) | |
94a79942 LF |
312 | { |
313 | u8 UP = 0; | |
f88ec6cb LF |
314 | if (is_broadcast_ether_addr(Addr) || is_multicast_ether_addr(Addr)) { |
315 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR! get TS for Broadcast or " | |
316 | "Multicast\n"); | |
94a79942 LF |
317 | return false; |
318 | } | |
319 | if (ieee->current_network.qos_data.supported == 0) { | |
320 | UP = 0; | |
321 | } else { | |
322 | if (!IsACValid(TID)) { | |
f88ec6cb LF |
323 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR! in %s(), TID(%d) is " |
324 | "not valid\n", __func__, TID); | |
94a79942 LF |
325 | return false; |
326 | } | |
327 | ||
328 | switch (TID) { | |
329 | case 0: | |
330 | case 3: | |
331 | UP = 0; | |
332 | break; | |
333 | case 1: | |
334 | case 2: | |
335 | UP = 2; | |
336 | break; | |
337 | case 4: | |
338 | case 5: | |
339 | UP = 5; | |
340 | break; | |
341 | case 6: | |
342 | case 7: | |
343 | UP = 7; | |
344 | break; | |
345 | } | |
346 | } | |
347 | ||
f88ec6cb LF |
348 | *ppTS = SearchAdmitTRStream(ieee, Addr, UP, TxRxSelect); |
349 | if (*ppTS != NULL) { | |
94a79942 | 350 | return true; |
f88ec6cb LF |
351 | } else { |
352 | if (bAddNewTs == false) { | |
353 | RTLLIB_DEBUG(RTLLIB_DL_TS, "add new TS failed" | |
354 | "(tid:%d)\n", UP); | |
94a79942 | 355 | return false; |
f88ec6cb | 356 | } else { |
ed306e48 | 357 | union tspec_body TSpec; |
42c53e7a | 358 | union qos_tsinfo *pTSInfo = &TSpec.f.TSInfo; |
f88ec6cb LF |
359 | struct list_head *pUnusedList = |
360 | (TxRxSelect == TX_DIR) ? | |
361 | (&ieee->Tx_TS_Unused_List) : | |
362 | (&ieee->Rx_TS_Unused_List); | |
363 | ||
364 | struct list_head *pAddmitList = | |
365 | (TxRxSelect == TX_DIR) ? | |
366 | (&ieee->Tx_TS_Admit_List) : | |
367 | (&ieee->Rx_TS_Admit_List); | |
368 | ||
369 | enum direction_value Dir = | |
370 | (ieee->iw_mode == IW_MODE_MASTER) ? | |
371 | ((TxRxSelect == TX_DIR) ? DIR_DOWN : DIR_UP) : | |
372 | ((TxRxSelect == TX_DIR) ? DIR_UP : DIR_DOWN); | |
94a79942 | 373 | RTLLIB_DEBUG(RTLLIB_DL_TS, "to add Ts\n"); |
f88ec6cb LF |
374 | if (!list_empty(pUnusedList)) { |
375 | (*ppTS) = list_entry(pUnusedList->next, | |
376 | struct ts_common_info, List); | |
94a79942 | 377 | list_del_init(&(*ppTS)->List); |
f88ec6cb LF |
378 | if (TxRxSelect == TX_DIR) { |
379 | struct tx_ts_record *tmp = | |
380 | container_of(*ppTS, | |
381 | struct tx_ts_record, | |
382 | TsCommonInfo); | |
94a79942 | 383 | ResetTxTsEntry(tmp); |
f88ec6cb LF |
384 | } else { |
385 | struct rx_ts_record *tmp = | |
386 | container_of(*ppTS, | |
387 | struct rx_ts_record, | |
388 | TsCommonInfo); | |
94a79942 LF |
389 | ResetRxTsEntry(tmp); |
390 | } | |
391 | ||
f88ec6cb | 392 | RTLLIB_DEBUG(RTLLIB_DL_TS, "to init current TS" |
ac50ddaa | 393 | ", UP:%d, Dir:%d, addr: %pM" |
f88ec6cb | 394 | " ppTs=%p\n", UP, Dir, |
ac50ddaa | 395 | Addr, *ppTS); |
94a79942 LF |
396 | pTSInfo->field.ucTrafficType = 0; |
397 | pTSInfo->field.ucTSID = UP; | |
398 | pTSInfo->field.ucDirection = Dir; | |
399 | pTSInfo->field.ucAccessPolicy = 1; | |
400 | pTSInfo->field.ucAggregation = 0; | |
401 | pTSInfo->field.ucPSB = 0; | |
402 | pTSInfo->field.ucUP = UP; | |
403 | pTSInfo->field.ucTSInfoAckPolicy = 0; | |
404 | pTSInfo->field.ucSchedule = 0; | |
405 | ||
406 | MakeTSEntry(*ppTS, Addr, &TSpec, NULL, 0, 0); | |
407 | AdmitTS(ieee, *ppTS, 0); | |
408 | list_add_tail(&((*ppTS)->List), pAddmitList); | |
409 | ||
410 | return true; | |
f88ec6cb LF |
411 | } else { |
412 | RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR!!in function " | |
413 | "%s() There is not enough dir=%d" | |
414 | "(0=up down=1) TS record to be " | |
415 | "used!!", __func__, Dir); | |
94a79942 LF |
416 | return false; |
417 | } | |
418 | } | |
419 | } | |
420 | } | |
421 | ||
ec0dc6be LF |
422 | static void RemoveTsEntry(struct rtllib_device *ieee, struct ts_common_info *pTs, |
423 | enum tr_select TxRxSelect) | |
94a79942 LF |
424 | { |
425 | del_timer_sync(&pTs->SetupTimer); | |
426 | del_timer_sync(&pTs->InactTimer); | |
427 | TsInitDelBA(ieee, pTs, TxRxSelect); | |
428 | ||
f88ec6cb | 429 | if (TxRxSelect == RX_DIR) { |
8cba1432 | 430 | struct rx_reorder_entry *pRxReorderEntry; |
2c47ae28 | 431 | struct rx_ts_record *pRxTS = (struct rx_ts_record *)pTs; |
94a79942 LF |
432 | |
433 | if (timer_pending(&pRxTS->RxPktPendingTimer)) | |
434 | del_timer_sync(&pRxTS->RxPktPendingTimer); | |
435 | ||
f88ec6cb LF |
436 | while (!list_empty(&pRxTS->RxPendingPktList)) { |
437 | pRxReorderEntry = (struct rx_reorder_entry *) | |
438 | list_entry(pRxTS->RxPendingPktList.prev, | |
439 | struct rx_reorder_entry, List); | |
440 | RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Delete SeqNum " | |
441 | "%d!\n", __func__, | |
442 | pRxReorderEntry->SeqNum); | |
94a79942 LF |
443 | list_del_init(&pRxReorderEntry->List); |
444 | { | |
445 | int i = 0; | |
f88ec6cb LF |
446 | struct rtllib_rxb *prxb = pRxReorderEntry->prxb; |
447 | if (unlikely(!prxb)) | |
94a79942 | 448 | return; |
f88ec6cb | 449 | for (i = 0; i < prxb->nr_subframes; i++) |
94a79942 | 450 | dev_kfree_skb(prxb->subframes[i]); |
94a79942 LF |
451 | kfree(prxb); |
452 | prxb = NULL; | |
453 | } | |
f88ec6cb LF |
454 | list_add_tail(&pRxReorderEntry->List, |
455 | &ieee->RxReorder_Unused_List); | |
94a79942 | 456 | } |
f88ec6cb | 457 | } else { |
60554f2b | 458 | struct tx_ts_record *pTxTS = (struct tx_ts_record *)pTs; |
94a79942 LF |
459 | del_timer_sync(&pTxTS->TsAddBaTimer); |
460 | } | |
461 | } | |
462 | ||
f88ec6cb | 463 | void RemovePeerTS(struct rtllib_device *ieee, u8 *Addr) |
94a79942 | 464 | { |
74724de1 | 465 | struct ts_common_info *pTS, *pTmpTS; |
ac50ddaa | 466 | printk(KERN_INFO "===========>RemovePeerTS, %pM\n", Addr); |
4f6807e8 | 467 | |
f88ec6cb LF |
468 | list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List) { |
469 | if (memcmp(pTS->Addr, Addr, 6) == 0) { | |
94a79942 LF |
470 | RemoveTsEntry(ieee, pTS, TX_DIR); |
471 | list_del_init(&pTS->List); | |
472 | list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List); | |
473 | } | |
474 | } | |
475 | ||
f88ec6cb LF |
476 | list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List) { |
477 | if (memcmp(pTS->Addr, Addr, 6) == 0) { | |
478 | printk(KERN_INFO "====>remove Tx_TS_admin_list\n"); | |
94a79942 LF |
479 | RemoveTsEntry(ieee, pTS, TX_DIR); |
480 | list_del_init(&pTS->List); | |
481 | list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List); | |
482 | } | |
483 | } | |
484 | ||
f88ec6cb LF |
485 | list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List) { |
486 | if (memcmp(pTS->Addr, Addr, 6) == 0) { | |
94a79942 LF |
487 | RemoveTsEntry(ieee, pTS, RX_DIR); |
488 | list_del_init(&pTS->List); | |
489 | list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List); | |
490 | } | |
491 | } | |
492 | ||
f88ec6cb LF |
493 | list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List) { |
494 | if (memcmp(pTS->Addr, Addr, 6) == 0) { | |
94a79942 LF |
495 | RemoveTsEntry(ieee, pTS, RX_DIR); |
496 | list_del_init(&pTS->List); | |
497 | list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List); | |
498 | } | |
499 | } | |
94a79942 LF |
500 | } |
501 | ||
f88ec6cb | 502 | void RemoveAllTS(struct rtllib_device *ieee) |
94a79942 | 503 | { |
74724de1 | 504 | struct ts_common_info *pTS, *pTmpTS; |
4f6807e8 | 505 | |
f88ec6cb | 506 | list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List) { |
94a79942 LF |
507 | RemoveTsEntry(ieee, pTS, TX_DIR); |
508 | list_del_init(&pTS->List); | |
509 | list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List); | |
510 | } | |
511 | ||
f88ec6cb | 512 | list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List) { |
94a79942 LF |
513 | RemoveTsEntry(ieee, pTS, TX_DIR); |
514 | list_del_init(&pTS->List); | |
515 | list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List); | |
516 | } | |
517 | ||
f88ec6cb | 518 | list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List) { |
94a79942 LF |
519 | RemoveTsEntry(ieee, pTS, RX_DIR); |
520 | list_del_init(&pTS->List); | |
521 | list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List); | |
522 | } | |
523 | ||
f88ec6cb | 524 | list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List) { |
94a79942 LF |
525 | RemoveTsEntry(ieee, pTS, RX_DIR); |
526 | list_del_init(&pTS->List); | |
527 | list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List); | |
528 | } | |
94a79942 LF |
529 | } |
530 | ||
f88ec6cb | 531 | void TsStartAddBaProcess(struct rtllib_device *ieee, struct tx_ts_record *pTxTS) |
94a79942 | 532 | { |
f88ec6cb | 533 | if (pTxTS->bAddBaReqInProgress == false) { |
94a79942 | 534 | pTxTS->bAddBaReqInProgress = true; |
4f6807e8 | 535 | |
f88ec6cb LF |
536 | if (pTxTS->bAddBaReqDelayed) { |
537 | RTLLIB_DEBUG(RTLLIB_DL_BA, "TsStartAddBaProcess(): " | |
538 | "Delayed Start ADDBA after 60 sec!!\n"); | |
539 | mod_timer(&pTxTS->TsAddBaTimer, jiffies + | |
540 | MSECS(TS_ADDBA_DELAY)); | |
541 | } else { | |
542 | RTLLIB_DEBUG(RTLLIB_DL_BA, "TsStartAddBaProcess(): " | |
543 | "Immediately Start ADDBA now!!\n"); | |
94a79942 LF |
544 | mod_timer(&pTxTS->TsAddBaTimer, jiffies+10); |
545 | } | |
f88ec6cb LF |
546 | } else |
547 | RTLLIB_DEBUG(RTLLIB_DL_BA, "%s()==>BA timer is already added\n", | |
548 | __func__); | |
94a79942 | 549 | } |