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