Commit | Line | Data |
---|---|---|
92b96797 FB |
1 | /* |
2 | * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. | |
3 | * All rights reserved. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License as published by | |
7 | * the Free Software Foundation; either version 2 of the License, or | |
8 | * (at your option) any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License along | |
16 | * with this program; if not, write to the Free Software Foundation, Inc., | |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 | * | |
19 | * File: dpc.c | |
20 | * | |
21 | * Purpose: handle dpc rx functions | |
22 | * | |
23 | * Author: Lyndon Chen | |
24 | * | |
25 | * Date: May 20, 2003 | |
26 | * | |
27 | * Functions: | |
28 | * device_receive_frame - Rcv 802.11 frame function | |
29 | * s_bAPModeRxCtl- AP Rcv frame filer Ctl. | |
30 | * s_bAPModeRxData- AP Rcv data frame handle | |
31 | * s_bHandleRxEncryption- Rcv decrypted data via on-fly | |
92b96797 FB |
32 | * s_byGetRateIdx- get rate index |
33 | * s_vGetDASA- get data offset | |
34 | * s_vProcessRxMACHeader- Rcv 802.11 and translate to 802.3 | |
35 | * | |
36 | * Revision History: | |
37 | * | |
38 | */ | |
39 | ||
d820fa95 | 40 | #include "dpc.h" |
92b96797 | 41 | #include "device.h" |
92b96797 | 42 | #include "rxtx.h" |
92b96797 | 43 | #include "tether.h" |
92b96797 | 44 | #include "card.h" |
92b96797 | 45 | #include "bssdb.h" |
92b96797 | 46 | #include "mac.h" |
92b96797 | 47 | #include "baseband.h" |
92b96797 | 48 | #include "michael.h" |
92b96797 | 49 | #include "tkip.h" |
92b96797 | 50 | #include "tcrc.h" |
92b96797 | 51 | #include "wctl.h" |
92b96797 | 52 | #include "rf.h" |
92b96797 | 53 | #include "iowpa.h" |
92b96797 | 54 | #include "aes_ccmp.h" |
92b96797 | 55 | #include "datarate.h" |
92b96797 | 56 | #include "usbpipe.h" |
92b96797 | 57 | |
92b96797 FB |
58 | //static int msglevel =MSG_LEVEL_DEBUG; |
59 | static int msglevel =MSG_LEVEL_INFO; | |
60 | ||
3b138851 | 61 | static const u8 acbyRxRate[MAX_RATE] = |
92b96797 FB |
62 | {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108}; |
63 | ||
b902fbfe | 64 | static u8 s_byGetRateIdx(u8 byRate); |
92b96797 FB |
65 | |
66 | static | |
8611a29a | 67 | void |
92b96797 | 68 | s_vGetDASA( |
b902fbfe | 69 | u8 * pbyRxBufferAddr, |
93a94c42 | 70 | unsigned int *pcbHeaderSize, |
ceb8c5da | 71 | struct ethhdr *psEthHeader |
92b96797 FB |
72 | ); |
73 | ||
45c73bb1 MP |
74 | static void s_vProcessRxMACHeader(struct vnt_private *pDevice, |
75 | u8 *pbyRxBufferAddr, u32 cbPacketSize, int bIsWEP, int bExtIV, | |
76 | u32 *pcbHeadSize); | |
92b96797 | 77 | |
45c73bb1 MP |
78 | static int s_bAPModeRxCtl(struct vnt_private *pDevice, u8 *pbyFrame, |
79 | s32 iSANodeIndex); | |
92b96797 | 80 | |
45c73bb1 MP |
81 | static int s_bAPModeRxData(struct vnt_private *pDevice, struct sk_buff *skb, |
82 | u32 FrameSize, u32 cbHeaderOffset, s32 iSANodeIndex, s32 iDANodeIndex); | |
92b96797 | 83 | |
45c73bb1 MP |
84 | static int s_bHandleRxEncryption(struct vnt_private *pDevice, u8 *pbyFrame, |
85 | u32 FrameSize, u8 *pbyRsr, u8 *pbyNewRsr, PSKeyItem *pKeyOut, | |
86 | s32 *pbExtIV, u16 *pwRxTSC15_0, u32 *pdwRxTSC47_16); | |
92b96797 | 87 | |
92b96797 FB |
88 | /*+ |
89 | * | |
90 | * Description: | |
91 | * Translate Rcv 802.11 header to 802.3 header with Rx buffer | |
92 | * | |
93 | * Parameters: | |
94 | * In: | |
95 | * pDevice | |
96 | * dwRxBufferAddr - Address of Rcv Buffer | |
97 | * cbPacketSize - Rcv Packet size | |
98 | * bIsWEP - If Rcv with WEP | |
99 | * Out: | |
100 | * pcbHeaderSize - 802.11 header size | |
101 | * | |
102 | * Return Value: None | |
103 | * | |
104 | -*/ | |
45c73bb1 MP |
105 | |
106 | static void s_vProcessRxMACHeader(struct vnt_private *pDevice, | |
107 | u8 *pbyRxBufferAddr, u32 cbPacketSize, int bIsWEP, int bExtIV, | |
108 | u32 *pcbHeadSize) | |
92b96797 | 109 | { |
45c73bb1 MP |
110 | u8 *pbyRxBuffer; |
111 | u32 cbHeaderSize = 0; | |
112 | u16 *pwType; | |
1cac4a4b | 113 | struct ieee80211_hdr *pMACHeader; |
45c73bb1 | 114 | int ii; |
92b96797 | 115 | |
1cac4a4b | 116 | pMACHeader = (struct ieee80211_hdr *) (pbyRxBufferAddr + cbHeaderSize); |
92b96797 | 117 | |
b902fbfe | 118 | s_vGetDASA((u8 *)pMACHeader, &cbHeaderSize, &pDevice->sRxEthHeader); |
92b96797 FB |
119 | |
120 | if (bIsWEP) { | |
121 | if (bExtIV) { | |
122 | // strip IV&ExtIV , add 8 byte | |
123 | cbHeaderSize += (WLAN_HDR_ADDR3_LEN + 8); | |
124 | } else { | |
125 | // strip IV , add 4 byte | |
126 | cbHeaderSize += (WLAN_HDR_ADDR3_LEN + 4); | |
127 | } | |
128 | } | |
129 | else { | |
130 | cbHeaderSize += WLAN_HDR_ADDR3_LEN; | |
131 | }; | |
132 | ||
b902fbfe | 133 | pbyRxBuffer = (u8 *) (pbyRxBufferAddr + cbHeaderSize); |
8329419a | 134 | if (ether_addr_equal(pbyRxBuffer, pDevice->abySNAP_Bridgetunnel)) { |
92b96797 | 135 | cbHeaderSize += 6; |
8329419a | 136 | } else if (ether_addr_equal(pbyRxBuffer, pDevice->abySNAP_RFC1042)) { |
92b96797 | 137 | cbHeaderSize += 6; |
3eaca0d2 | 138 | pwType = (u16 *) (pbyRxBufferAddr + cbHeaderSize); |
aa209eef | 139 | if ((*pwType == cpu_to_be16(ETH_P_IPX)) || |
203e4615 AM |
140 | (*pwType == cpu_to_le16(0xF380))) { |
141 | cbHeaderSize -= 8; | |
3eaca0d2 | 142 | pwType = (u16 *) (pbyRxBufferAddr + cbHeaderSize); |
92b96797 FB |
143 | if (bIsWEP) { |
144 | if (bExtIV) { | |
145 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8); // 8 is IV&ExtIV | |
146 | } else { | |
147 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 4); // 4 is IV | |
148 | } | |
149 | } | |
150 | else { | |
151 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN); | |
152 | } | |
153 | } | |
154 | } | |
155 | else { | |
156 | cbHeaderSize -= 2; | |
3eaca0d2 | 157 | pwType = (u16 *) (pbyRxBufferAddr + cbHeaderSize); |
92b96797 FB |
158 | if (bIsWEP) { |
159 | if (bExtIV) { | |
160 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8); // 8 is IV&ExtIV | |
161 | } else { | |
162 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 4); // 4 is IV | |
163 | } | |
164 | } | |
165 | else { | |
166 | *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN); | |
167 | } | |
168 | } | |
169 | ||
9a0e756c | 170 | cbHeaderSize -= (ETH_ALEN * 2); |
b902fbfe | 171 | pbyRxBuffer = (u8 *) (pbyRxBufferAddr + cbHeaderSize); |
9a0e756c | 172 | for (ii = 0; ii < ETH_ALEN; ii++) |
ceb8c5da | 173 | *pbyRxBuffer++ = pDevice->sRxEthHeader.h_dest[ii]; |
9a0e756c | 174 | for (ii = 0; ii < ETH_ALEN; ii++) |
ceb8c5da | 175 | *pbyRxBuffer++ = pDevice->sRxEthHeader.h_source[ii]; |
92b96797 FB |
176 | |
177 | *pcbHeadSize = cbHeaderSize; | |
178 | } | |
179 | ||
b902fbfe | 180 | static u8 s_byGetRateIdx(u8 byRate) |
92b96797 | 181 | { |
b902fbfe | 182 | u8 byRateIdx; |
92b96797 FB |
183 | |
184 | for (byRateIdx = 0; byRateIdx <MAX_RATE ; byRateIdx++) { | |
185 | if (acbyRxRate[byRateIdx%MAX_RATE] == byRate) | |
186 | return byRateIdx; | |
187 | } | |
188 | return 0; | |
189 | } | |
190 | ||
92b96797 | 191 | static |
8611a29a | 192 | void |
92b96797 | 193 | s_vGetDASA ( |
b902fbfe | 194 | u8 * pbyRxBufferAddr, |
93a94c42 | 195 | unsigned int *pcbHeaderSize, |
ceb8c5da | 196 | struct ethhdr *psEthHeader |
92b96797 FB |
197 | ) |
198 | { | |
cc856e61 | 199 | unsigned int cbHeaderSize = 0; |
1cac4a4b | 200 | struct ieee80211_hdr *pMACHeader; |
9a0e756c AM |
201 | int ii; |
202 | ||
1cac4a4b | 203 | pMACHeader = (struct ieee80211_hdr *) (pbyRxBufferAddr + cbHeaderSize); |
9a0e756c | 204 | |
1cac4a4b AM |
205 | if ((pMACHeader->frame_control & FC_TODS) == 0) { |
206 | if (pMACHeader->frame_control & FC_FROMDS) { | |
9a0e756c | 207 | for (ii = 0; ii < ETH_ALEN; ii++) { |
ceb8c5da | 208 | psEthHeader->h_dest[ii] = |
1cac4a4b | 209 | pMACHeader->addr1[ii]; |
ceb8c5da | 210 | psEthHeader->h_source[ii] = |
1cac4a4b | 211 | pMACHeader->addr3[ii]; |
9a0e756c AM |
212 | } |
213 | } else { | |
214 | /* IBSS mode */ | |
215 | for (ii = 0; ii < ETH_ALEN; ii++) { | |
ceb8c5da | 216 | psEthHeader->h_dest[ii] = |
1cac4a4b | 217 | pMACHeader->addr1[ii]; |
ceb8c5da | 218 | psEthHeader->h_source[ii] = |
1cac4a4b | 219 | pMACHeader->addr2[ii]; |
9a0e756c AM |
220 | } |
221 | } | |
222 | } else { | |
223 | /* Is AP mode.. */ | |
1cac4a4b | 224 | if (pMACHeader->frame_control & FC_FROMDS) { |
9a0e756c | 225 | for (ii = 0; ii < ETH_ALEN; ii++) { |
ceb8c5da | 226 | psEthHeader->h_dest[ii] = |
1cac4a4b | 227 | pMACHeader->addr3[ii]; |
ceb8c5da | 228 | psEthHeader->h_source[ii] = |
1cac4a4b | 229 | pMACHeader->addr4[ii]; |
9a0e756c AM |
230 | cbHeaderSize += 6; |
231 | } | |
232 | } else { | |
233 | for (ii = 0; ii < ETH_ALEN; ii++) { | |
ceb8c5da | 234 | psEthHeader->h_dest[ii] = |
1cac4a4b | 235 | pMACHeader->addr3[ii]; |
ceb8c5da | 236 | psEthHeader->h_source[ii] = |
1cac4a4b | 237 | pMACHeader->addr2[ii]; |
9a0e756c AM |
238 | } |
239 | } | |
240 | }; | |
92b96797 FB |
241 | *pcbHeaderSize = cbHeaderSize; |
242 | } | |
243 | ||
115cac2e | 244 | int RXbBulkInProcessData(struct vnt_private *pDevice, struct vnt_rcb *pRCB, |
45c73bb1 | 245 | unsigned long BytesToIndicate) |
92b96797 | 246 | { |
45c73bb1 MP |
247 | struct net_device_stats *pStats = &pDevice->stats; |
248 | struct sk_buff *skb; | |
249 | struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; | |
250 | struct vnt_rx_mgmt *pRxPacket = &pMgmt->sRxPacket; | |
1cac4a4b | 251 | struct ieee80211_hdr *p802_11Header; |
45c73bb1 | 252 | u8 *pbyRsr, *pbyNewRsr, *pbyRSSI, *pbyFrame; |
7c65fa2a | 253 | u64 *pqwTSFTime; |
e269fc2d | 254 | u32 bDeFragRx = false; |
45c73bb1 | 255 | u32 cbHeaderOffset, cbIVOffset; |
cf5d170e | 256 | u32 FrameSize; |
45c73bb1 MP |
257 | u16 wEtherType = 0; |
258 | s32 iSANodeIndex = -1, iDANodeIndex = -1; | |
259 | int ii; | |
260 | u8 *pbyRxSts, *pbyRxRate, *pbySQ, *pby3SQ; | |
261 | u32 cbHeaderSize; | |
262 | PSKeyItem pKey = NULL; | |
263 | u16 wRxTSC15_0 = 0; | |
264 | u32 dwRxTSC47_16 = 0; | |
45c73bb1 | 265 | /* signed long ldBm = 0; */ |
e269fc2d | 266 | int bIsWEP = false; int bExtIV = false; |
cf5d170e | 267 | u32 dwWbkStatus; |
115cac2e | 268 | struct vnt_rcb *pRCBIndicate = pRCB; |
45c73bb1 MP |
269 | u8 *pbyDAddress; |
270 | u16 *pwPLCP_Length; | |
271 | u8 abyVaildRate[MAX_RATE] | |
272 | = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108}; | |
273 | u16 wPLCPwithPadding; | |
1cac4a4b | 274 | struct ieee80211_hdr *pMACHeader; |
e269fc2d | 275 | int bRxeapol_key = false; |
92b96797 | 276 | |
92b96797 FB |
277 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---------- RXbBulkInProcessData---\n"); |
278 | ||
279 | skb = pRCB->skb; | |
280 | ||
cf5d170e MP |
281 | /* [31:16]RcvByteCount ( not include 4-byte Status ) */ |
282 | dwWbkStatus = *((u32 *)(skb->data)); | |
283 | FrameSize = dwWbkStatus >> 16; | |
284 | FrameSize += 4; | |
92b96797 | 285 | |
cf5d170e MP |
286 | if (BytesToIndicate != FrameSize) { |
287 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"------- WRONG Length 1\n"); | |
9a450f9a | 288 | pStats->rx_frame_errors++; |
e269fc2d | 289 | return false; |
cf5d170e | 290 | } |
92b96797 | 291 | |
bd2bc4c7 | 292 | if ((BytesToIndicate > 2372) || (BytesToIndicate <= 40)) { |
92b96797 | 293 | // Frame Size error drop this packet. |
bd2bc4c7 | 294 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "---------- WRONG Length 2\n"); |
9a450f9a | 295 | pStats->rx_frame_errors++; |
e269fc2d | 296 | return false; |
92b96797 FB |
297 | } |
298 | ||
b902fbfe | 299 | pbyDAddress = (u8 *)(skb->data); |
92b96797 FB |
300 | pbyRxSts = pbyDAddress+4; |
301 | pbyRxRate = pbyDAddress+5; | |
302 | ||
303 | //real Frame Size = USBFrameSize -4WbkStatus - 4RxStatus - 8TSF - 4RSR - 4SQ3 - ?Padding | |
304 | //if SQ3 the range is 24~27, if no SQ3 the range is 20~23 | |
305 | //real Frame size in PLCPLength field. | |
3eaca0d2 | 306 | pwPLCP_Length = (u16 *) (pbyDAddress + 6); |
92b96797 FB |
307 | //Fix hardware bug => PLCP_Length error |
308 | if ( ((BytesToIndicate - (*pwPLCP_Length)) > 27) || | |
309 | ((BytesToIndicate - (*pwPLCP_Length)) < 24) || | |
310 | (BytesToIndicate < (*pwPLCP_Length)) ) { | |
311 | ||
312 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Wrong PLCP Length %x\n", (int) *pwPLCP_Length); | |
9a450f9a | 313 | pStats->rx_frame_errors++; |
e269fc2d | 314 | return false; |
92b96797 FB |
315 | } |
316 | for ( ii=RATE_1M;ii<MAX_RATE;ii++) { | |
317 | if ( *pbyRxRate == abyVaildRate[ii] ) { | |
318 | break; | |
319 | } | |
320 | } | |
321 | if ( ii==MAX_RATE ) { | |
322 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Wrong RxRate %x\n",(int) *pbyRxRate); | |
e269fc2d | 323 | return false; |
92b96797 FB |
324 | } |
325 | ||
326 | wPLCPwithPadding = ( (*pwPLCP_Length / 4) + ( (*pwPLCP_Length % 4) ? 1:0 ) ) *4; | |
327 | ||
7c65fa2a | 328 | pqwTSFTime = (u64 *)(pbyDAddress + 8 + wPLCPwithPadding); |
92b96797 FB |
329 | if(pDevice->byBBType == BB_TYPE_11G) { |
330 | pby3SQ = pbyDAddress + 8 + wPLCPwithPadding + 12; | |
331 | pbySQ = pby3SQ; | |
332 | } | |
333 | else { | |
334 | pbySQ = pbyDAddress + 8 + wPLCPwithPadding + 8; | |
335 | pby3SQ = pbySQ; | |
336 | } | |
92b96797 FB |
337 | pbyNewRsr = pbyDAddress + 8 + wPLCPwithPadding + 9; |
338 | pbyRSSI = pbyDAddress + 8 + wPLCPwithPadding + 10; | |
339 | pbyRsr = pbyDAddress + 8 + wPLCPwithPadding + 11; | |
340 | ||
341 | FrameSize = *pwPLCP_Length; | |
342 | ||
343 | pbyFrame = pbyDAddress + 8; | |
92b96797 | 344 | |
1cac4a4b | 345 | pMACHeader = (struct ieee80211_hdr *) pbyFrame; |
92b96797 FB |
346 | |
347 | //mike add: to judge if current AP is activated? | |
348 | if ((pMgmt->eCurrMode == WMAC_MODE_STANDBY) || | |
349 | (pMgmt->eCurrMode == WMAC_MODE_ESS_STA)) { | |
350 | if (pMgmt->sNodeDBTable[0].bActive) { | |
8329419a | 351 | if (ether_addr_equal(pMgmt->abyCurrBSSID, pMACHeader->addr2)) { |
92b96797 FB |
352 | if (pMgmt->sNodeDBTable[0].uInActiveCount != 0) |
353 | pMgmt->sNodeDBTable[0].uInActiveCount = 0; | |
354 | } | |
355 | } | |
356 | } | |
357 | ||
1cac4a4b AM |
358 | if (!is_multicast_ether_addr(pMACHeader->addr1)) { |
359 | if (WCTLbIsDuplicate(&(pDevice->sDupRxCache), (struct ieee80211_hdr *) pbyFrame)) { | |
e269fc2d | 360 | return false; |
92b96797 FB |
361 | } |
362 | ||
8329419a | 363 | if (!ether_addr_equal(pDevice->abyCurrentNetAddr, pMACHeader->addr1)) { |
e269fc2d | 364 | return false; |
92b96797 FB |
365 | } |
366 | } | |
367 | ||
92b96797 FB |
368 | // Use for TKIP MIC |
369 | s_vGetDASA(pbyFrame, &cbHeaderSize, &pDevice->sRxEthHeader); | |
370 | ||
8329419a JP |
371 | if (ether_addr_equal((u8 *)pDevice->sRxEthHeader.h_source, |
372 | pDevice->abyCurrentNetAddr)) | |
e269fc2d | 373 | return false; |
92b96797 FB |
374 | |
375 | if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) { | |
376 | if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) { | |
1cac4a4b | 377 | p802_11Header = (struct ieee80211_hdr *) (pbyFrame); |
92b96797 | 378 | // get SA NodeIndex |
1cac4a4b | 379 | if (BSSbIsSTAInNodeDB(pDevice, (u8 *)(p802_11Header->addr2), &iSANodeIndex)) { |
92b96797 FB |
380 | pMgmt->sNodeDBTable[iSANodeIndex].ulLastRxJiffer = jiffies; |
381 | pMgmt->sNodeDBTable[iSANodeIndex].uInActiveCount = 0; | |
382 | } | |
383 | } | |
384 | } | |
385 | ||
386 | if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { | |
4e9b5e2b | 387 | if (s_bAPModeRxCtl(pDevice, pbyFrame, iSANodeIndex) == true) { |
e269fc2d | 388 | return false; |
92b96797 FB |
389 | } |
390 | } | |
391 | ||
92b96797 | 392 | if (IS_FC_WEP(pbyFrame)) { |
e269fc2d | 393 | bool bRxDecryOK = false; |
92b96797 FB |
394 | |
395 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"rx WEP pkt\n"); | |
4e9b5e2b | 396 | bIsWEP = true; |
90f96acd MP |
397 | |
398 | bRxDecryOK = s_bHandleRxEncryption(pDevice, pbyFrame, FrameSize, | |
399 | pbyRsr, pbyNewRsr, &pKey, &bExtIV, &wRxTSC15_0, &dwRxTSC47_16); | |
92b96797 FB |
400 | |
401 | if (bRxDecryOK) { | |
402 | if ((*pbyNewRsr & NEWRSR_DECRYPTOK) == 0) { | |
403 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV Fail\n"); | |
404 | if ( (pMgmt->eAuthenMode == WMAC_AUTH_WPA) || | |
405 | (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || | |
406 | (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) || | |
407 | (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || | |
408 | (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { | |
92b96797 | 409 | } |
e269fc2d | 410 | return false; |
92b96797 FB |
411 | } |
412 | } else { | |
413 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"WEP Func Fail\n"); | |
e269fc2d | 414 | return false; |
92b96797 FB |
415 | } |
416 | if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_CCMP)) | |
417 | FrameSize -= 8; // Message Integrity Code | |
418 | else | |
419 | FrameSize -= 4; // 4 is ICV | |
420 | } | |
421 | ||
92b96797 FB |
422 | // |
423 | // RX OK | |
424 | // | |
abad19d0 AM |
425 | /* remove the FCS/CRC length */ |
426 | FrameSize -= ETH_FCS_LEN; | |
92b96797 | 427 | |
8a3d91b0 | 428 | if ( !(*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) && // unicast address |
92b96797 FB |
429 | (IS_FRAGMENT_PKT((pbyFrame))) |
430 | ) { | |
431 | // defragment | |
1cac4a4b | 432 | bDeFragRx = WCTLbHandleFragment(pDevice, (struct ieee80211_hdr *) (pbyFrame), FrameSize, bIsWEP, bExtIV); |
92b96797 FB |
433 | if (bDeFragRx) { |
434 | // defrag complete | |
435 | // TODO skb, pbyFrame | |
436 | skb = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb; | |
437 | FrameSize = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength; | |
438 | pbyFrame = skb->data + 8; | |
439 | } | |
440 | else { | |
e269fc2d | 441 | return false; |
92b96797 FB |
442 | } |
443 | } | |
444 | ||
445 | // | |
446 | // Management & Control frame Handle | |
447 | // | |
e269fc2d | 448 | if ((IS_TYPE_DATA((pbyFrame))) == false) { |
92b96797 FB |
449 | // Handle Control & Manage Frame |
450 | ||
451 | if (IS_TYPE_MGMT((pbyFrame))) { | |
b902fbfe AM |
452 | u8 * pbyData1; |
453 | u8 * pbyData2; | |
92b96797 FB |
454 | |
455 | pRxPacket = &(pRCB->sMngPacket); | |
456 | pRxPacket->p80211Header = (PUWLAN_80211HDR)(pbyFrame); | |
457 | pRxPacket->cbMPDULen = FrameSize; | |
458 | pRxPacket->uRSSI = *pbyRSSI; | |
459 | pRxPacket->bySQ = *pbySQ; | |
7c65fa2a | 460 | pRxPacket->qwLocalTSF = cpu_to_le64(*pqwTSFTime); |
92b96797 FB |
461 | if (bIsWEP) { |
462 | // strip IV | |
463 | pbyData1 = WLAN_HDR_A3_DATA_PTR(pbyFrame); | |
464 | pbyData2 = WLAN_HDR_A3_DATA_PTR(pbyFrame) + 4; | |
465 | for (ii = 0; ii < (FrameSize - 4); ii++) { | |
466 | *pbyData1 = *pbyData2; | |
467 | pbyData1++; | |
468 | pbyData2++; | |
469 | } | |
470 | } | |
471 | ||
472 | pRxPacket->byRxRate = s_byGetRateIdx(*pbyRxRate); | |
473 | ||
474 | if ( *pbyRxSts == 0 ) { | |
475 | //Discard beacon packet which channel is 0 | |
476 | if ( (WLAN_GET_FC_FSTYPE((pRxPacket->p80211Header->sA3.wFrameCtl)) == WLAN_FSTYPE_BEACON) || | |
477 | (WLAN_GET_FC_FSTYPE((pRxPacket->p80211Header->sA3.wFrameCtl)) == WLAN_FSTYPE_PROBERESP) ) { | |
e269fc2d | 478 | return false; |
92b96797 FB |
479 | } |
480 | } | |
481 | pRxPacket->byRxChannel = (*pbyRxSts) >> 2; | |
482 | ||
92b96797 FB |
483 | // |
484 | // Insert the RCB in the Recv Mng list | |
485 | // | |
486 | EnqueueRCB(pDevice->FirstRecvMngList, pDevice->LastRecvMngList, pRCBIndicate); | |
487 | pDevice->NumRecvMngList++; | |
e269fc2d | 488 | if ( bDeFragRx == false) { |
92b96797 FB |
489 | pRCB->Ref++; |
490 | } | |
e269fc2d | 491 | if (pDevice->bIsRxMngWorkItemQueued == false) { |
4e9b5e2b | 492 | pDevice->bIsRxMngWorkItemQueued = true; |
a21fc2f5 | 493 | schedule_work(&pDevice->rx_mng_work_item); |
92b96797 FB |
494 | } |
495 | ||
496 | } | |
497 | else { | |
498 | // Control Frame | |
499 | }; | |
e269fc2d | 500 | return false; |
92b96797 FB |
501 | } |
502 | else { | |
503 | if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { | |
504 | //In AP mode, hw only check addr1(BSSID or RA) if equal to local MAC. | |
8a3d91b0 | 505 | if ( !(*pbyRsr & RSR_BSSIDOK)) { |
92b96797 FB |
506 | if (bDeFragRx) { |
507 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
508 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", | |
509 | pDevice->dev->name); | |
510 | } | |
511 | } | |
e269fc2d | 512 | return false; |
92b96797 FB |
513 | } |
514 | } | |
515 | else { | |
516 | // discard DATA packet while not associate || BSSID error | |
e269fc2d | 517 | if ((pDevice->bLinkPass == false) || |
8a3d91b0 | 518 | !(*pbyRsr & RSR_BSSIDOK)) { |
92b96797 FB |
519 | if (bDeFragRx) { |
520 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
521 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", | |
522 | pDevice->dev->name); | |
523 | } | |
524 | } | |
e269fc2d | 525 | return false; |
92b96797 FB |
526 | } |
527 | //mike add:station mode check eapol-key challenge---> | |
528 | { | |
b902fbfe AM |
529 | u8 Protocol_Version; //802.1x Authentication |
530 | u8 Packet_Type; //802.1x Authentication | |
531 | u8 Descriptor_type; | |
3eaca0d2 | 532 | u16 Key_info; |
92b96797 FB |
533 | if (bIsWEP) |
534 | cbIVOffset = 8; | |
535 | else | |
536 | cbIVOffset = 0; | |
537 | wEtherType = (skb->data[cbIVOffset + 8 + 24 + 6] << 8) | | |
538 | skb->data[cbIVOffset + 8 + 24 + 6 + 1]; | |
539 | Protocol_Version = skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1]; | |
540 | Packet_Type = skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1+1]; | |
541 | if (wEtherType == ETH_P_PAE) { //Protocol Type in LLC-Header | |
542 | if(((Protocol_Version==1) ||(Protocol_Version==2)) && | |
543 | (Packet_Type==3)) { //802.1x OR eapol-key challenge frame receive | |
4e9b5e2b | 544 | bRxeapol_key = true; |
92b96797 FB |
545 | Descriptor_type = skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1+1+1+2]; |
546 | Key_info = (skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1+1+1+2+1]<<8) |skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1+1+1+2+2] ; | |
547 | if(Descriptor_type==2) { //RSN | |
548 | // printk("WPA2_Rx_eapol-key_info<-----:%x\n",Key_info); | |
549 | } | |
550 | else if(Descriptor_type==254) { | |
551 | // printk("WPA_Rx_eapol-key_info<-----:%x\n",Key_info); | |
552 | } | |
553 | } | |
554 | } | |
555 | } | |
556 | //mike add:station mode check eapol-key challenge<--- | |
557 | } | |
558 | } | |
559 | ||
92b96797 FB |
560 | // Data frame Handle |
561 | ||
92b96797 FB |
562 | if (pDevice->bEnablePSMode) { |
563 | if (IS_FC_MOREDATA((pbyFrame))) { | |
8a3d91b0 | 564 | if (*pbyRsr & RSR_ADDROK) { |
92b96797 FB |
565 | //PSbSendPSPOLL((PSDevice)pDevice); |
566 | } | |
567 | } | |
568 | else { | |
4e9b5e2b | 569 | if (pMgmt->bInTIMWake == true) { |
e269fc2d | 570 | pMgmt->bInTIMWake = false; |
92b96797 FB |
571 | } |
572 | } | |
9fc86028 | 573 | } |
92b96797 FB |
574 | |
575 | // Now it only supports 802.11g Infrastructure Mode, and support rate must up to 54 Mbps | |
576 | if (pDevice->bDiversityEnable && (FrameSize>50) && | |
a0ad2776 | 577 | pDevice->op_mode == NL80211_IFTYPE_STATION && |
4e9b5e2b | 578 | (pDevice->bLinkPass == true)) { |
92b96797 FB |
579 | BBvAntennaDiversity(pDevice, s_byGetRateIdx(*pbyRxRate), 0); |
580 | } | |
581 | ||
582 | // ++++++++ For BaseBand Algorithm +++++++++++++++ | |
583 | pDevice->uCurrRSSI = *pbyRSSI; | |
584 | pDevice->byCurrSQ = *pbySQ; | |
585 | ||
586 | // todo | |
587 | /* | |
588 | if ((*pbyRSSI != 0) && | |
589 | (pMgmt->pCurrBSS!=NULL)) { | |
590 | RFvRSSITodBm(pDevice, *pbyRSSI, &ldBm); | |
a0a1f61a | 591 | // Monitor if RSSI is too strong. |
92b96797 FB |
592 | pMgmt->pCurrBSS->byRSSIStatCnt++; |
593 | pMgmt->pCurrBSS->byRSSIStatCnt %= RSSI_STAT_COUNT; | |
594 | pMgmt->pCurrBSS->ldBmAverage[pMgmt->pCurrBSS->byRSSIStatCnt] = ldBm; | |
33d33e42 AM |
595 | for (ii = 0; ii < RSSI_STAT_COUNT; ii++) { |
596 | if (pMgmt->pCurrBSS->ldBmAverage[ii] != 0) { | |
597 | pMgmt->pCurrBSS->ldBmMAX = | |
598 | max(pMgmt->pCurrBSS->ldBmAverage[ii], ldBm); | |
599 | } | |
92b96797 FB |
600 | } |
601 | } | |
602 | */ | |
603 | ||
92b96797 FB |
604 | if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) { |
605 | if (bIsWEP) { | |
606 | FrameSize -= 8; //MIC | |
607 | } | |
608 | } | |
609 | ||
610 | //-------------------------------------------------------------------------------- | |
611 | // Soft MIC | |
612 | if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) { | |
613 | if (bIsWEP) { | |
52a7e64b AM |
614 | u32 * pdwMIC_L; |
615 | u32 * pdwMIC_R; | |
616 | u32 dwMIC_Priority; | |
617 | u32 dwMICKey0 = 0, dwMICKey1 = 0; | |
618 | u32 dwLocalMIC_L = 0; | |
619 | u32 dwLocalMIC_R = 0; | |
92b96797 | 620 | |
92b96797 | 621 | if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { |
52a7e64b AM |
622 | dwMICKey0 = cpu_to_le32(*(u32 *)(&pKey->abyKey[24])); |
623 | dwMICKey1 = cpu_to_le32(*(u32 *)(&pKey->abyKey[28])); | |
92b96797 FB |
624 | } |
625 | else { | |
626 | if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { | |
52a7e64b AM |
627 | dwMICKey0 = cpu_to_le32(*(u32 *)(&pKey->abyKey[16])); |
628 | dwMICKey1 = cpu_to_le32(*(u32 *)(&pKey->abyKey[20])); | |
92b96797 | 629 | } else if ((pKey->dwKeyIndex & BIT28) == 0) { |
52a7e64b AM |
630 | dwMICKey0 = cpu_to_le32(*(u32 *)(&pKey->abyKey[16])); |
631 | dwMICKey1 = cpu_to_le32(*(u32 *)(&pKey->abyKey[20])); | |
92b96797 | 632 | } else { |
52a7e64b AM |
633 | dwMICKey0 = cpu_to_le32(*(u32 *)(&pKey->abyKey[24])); |
634 | dwMICKey1 = cpu_to_le32(*(u32 *)(&pKey->abyKey[28])); | |
92b96797 FB |
635 | } |
636 | } | |
637 | ||
638 | MIC_vInit(dwMICKey0, dwMICKey1); | |
ceb8c5da | 639 | MIC_vAppend((u8 *)&(pDevice->sRxEthHeader.h_dest[0]), 12); |
92b96797 | 640 | dwMIC_Priority = 0; |
b902fbfe | 641 | MIC_vAppend((u8 *)&dwMIC_Priority, 4); |
92b96797 | 642 | // 4 is Rcv buffer header, 24 is MAC Header, and 8 is IV and Ext IV. |
b902fbfe | 643 | MIC_vAppend((u8 *)(skb->data + 8 + WLAN_HDR_ADDR3_LEN + 8), |
92b96797 FB |
644 | FrameSize - WLAN_HDR_ADDR3_LEN - 8); |
645 | MIC_vGetMIC(&dwLocalMIC_L, &dwLocalMIC_R); | |
646 | MIC_vUnInit(); | |
647 | ||
52a7e64b AM |
648 | pdwMIC_L = (u32 *)(skb->data + 8 + FrameSize); |
649 | pdwMIC_R = (u32 *)(skb->data + 8 + FrameSize + 4); | |
92b96797 | 650 | |
92b96797 | 651 | if ((cpu_to_le32(*pdwMIC_L) != dwLocalMIC_L) || (cpu_to_le32(*pdwMIC_R) != dwLocalMIC_R) || |
4e9b5e2b | 652 | (pDevice->bRxMICFail == true)) { |
92b96797 | 653 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC comparison is fail!\n"); |
e269fc2d | 654 | pDevice->bRxMICFail = false; |
92b96797 FB |
655 | if (bDeFragRx) { |
656 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
657 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", | |
658 | pDevice->dev->name); | |
659 | } | |
660 | } | |
92b96797 | 661 | //send event to wpa_supplicant |
4e9b5e2b | 662 | //if(pDevice->bWPASuppWextEnabled == true) |
92b96797 FB |
663 | { |
664 | union iwreq_data wrqu; | |
665 | struct iw_michaelmicfailure ev; | |
666 | int keyidx = pbyFrame[cbHeaderSize+3] >> 6; //top two-bits | |
667 | memset(&ev, 0, sizeof(ev)); | |
668 | ev.flags = keyidx & IW_MICFAILURE_KEY_ID; | |
669 | if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && | |
670 | (pMgmt->eCurrState == WMAC_STATE_ASSOC) && | |
671 | (*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) { | |
672 | ev.flags |= IW_MICFAILURE_PAIRWISE; | |
673 | } else { | |
674 | ev.flags |= IW_MICFAILURE_GROUP; | |
675 | } | |
676 | ||
677 | ev.src_addr.sa_family = ARPHRD_ETHER; | |
1cac4a4b | 678 | memcpy(ev.src_addr.sa_data, pMACHeader->addr2, ETH_ALEN); |
92b96797 FB |
679 | memset(&wrqu, 0, sizeof(wrqu)); |
680 | wrqu.data.length = sizeof(ev); | |
681 | PRINT_K("wireless_send_event--->IWEVMICHAELMICFAILURE\n"); | |
682 | wireless_send_event(pDevice->dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev); | |
683 | ||
684 | } | |
92b96797 | 685 | |
e269fc2d | 686 | return false; |
92b96797 FB |
687 | |
688 | } | |
689 | } | |
690 | } //---end of SOFT MIC----------------------------------------------------------------------- | |
691 | ||
692 | // ++++++++++ Reply Counter Check +++++++++++++ | |
693 | ||
694 | if ((pKey != NULL) && ((pKey->byCipherSuite == KEY_CTL_TKIP) || | |
695 | (pKey->byCipherSuite == KEY_CTL_CCMP))) { | |
696 | if (bIsWEP) { | |
3eaca0d2 | 697 | u16 wLocalTSC15_0 = 0; |
52a7e64b | 698 | u32 dwLocalTSC47_16 = 0; |
cc856e61 | 699 | unsigned long long RSC = 0; |
92b96797 | 700 | // endian issues |
cc856e61 | 701 | RSC = *((unsigned long long *) &(pKey->KeyRSC)); |
3eaca0d2 | 702 | wLocalTSC15_0 = (u16) RSC; |
52a7e64b | 703 | dwLocalTSC47_16 = (u32) (RSC>>16); |
92b96797 FB |
704 | |
705 | RSC = dwRxTSC47_16; | |
706 | RSC <<= 16; | |
707 | RSC += wRxTSC15_0; | |
7c65fa2a | 708 | memcpy(&(pKey->KeyRSC), &RSC, sizeof(u64)); |
92b96797 | 709 | |
14c5ef57 MP |
710 | if (pDevice->vnt_mgmt.eCurrMode == WMAC_MODE_ESS_STA && |
711 | pDevice->vnt_mgmt.eCurrState == WMAC_STATE_ASSOC) { | |
712 | /* check RSC */ | |
92b96797 FB |
713 | if ( (wRxTSC15_0 < wLocalTSC15_0) && |
714 | (dwRxTSC47_16 <= dwLocalTSC47_16) && | |
715 | !((dwRxTSC47_16 == 0) && (dwLocalTSC47_16 == 0xFFFFFFFF))) { | |
716 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC is illegal~~!\n "); | |
92b96797 FB |
717 | |
718 | if (bDeFragRx) { | |
719 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
720 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", | |
721 | pDevice->dev->name); | |
722 | } | |
723 | } | |
e269fc2d | 724 | return false; |
92b96797 FB |
725 | } |
726 | } | |
727 | } | |
728 | } // ----- End of Reply Counter Check -------------------------- | |
729 | ||
b902fbfe | 730 | s_vProcessRxMACHeader(pDevice, (u8 *)(skb->data+8), FrameSize, bIsWEP, bExtIV, &cbHeaderOffset); |
92b96797 FB |
731 | FrameSize -= cbHeaderOffset; |
732 | cbHeaderOffset += 8; // 8 is Rcv buffer header | |
733 | ||
734 | // Null data, framesize = 12 | |
735 | if (FrameSize < 12) | |
e269fc2d | 736 | return false; |
92b96797 FB |
737 | |
738 | if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { | |
739 | if (s_bAPModeRxData(pDevice, | |
740 | skb, | |
741 | FrameSize, | |
742 | cbHeaderOffset, | |
743 | iSANodeIndex, | |
744 | iDANodeIndex | |
e269fc2d | 745 | ) == false) { |
92b96797 FB |
746 | |
747 | if (bDeFragRx) { | |
748 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
749 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", | |
750 | pDevice->dev->name); | |
751 | } | |
752 | } | |
e269fc2d | 753 | return false; |
92b96797 FB |
754 | } |
755 | ||
756 | } | |
757 | ||
758 | skb->data += cbHeaderOffset; | |
759 | skb->tail += cbHeaderOffset; | |
760 | skb_put(skb, FrameSize); | |
761 | skb->protocol=eth_type_trans(skb, skb->dev); | |
762 | skb->ip_summed=CHECKSUM_NONE; | |
763 | pStats->rx_bytes +=skb->len; | |
764 | pStats->rx_packets++; | |
765 | netif_rx(skb); | |
766 | if (bDeFragRx) { | |
767 | if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { | |
768 | DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", | |
769 | pDevice->dev->name); | |
770 | } | |
e269fc2d | 771 | return false; |
92b96797 FB |
772 | } |
773 | ||
4e9b5e2b | 774 | return true; |
92b96797 FB |
775 | } |
776 | ||
45c73bb1 MP |
777 | static int s_bAPModeRxCtl(struct vnt_private *pDevice, u8 *pbyFrame, |
778 | s32 iSANodeIndex) | |
92b96797 | 779 | { |
14c5ef57 | 780 | struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; |
1cac4a4b | 781 | struct ieee80211_hdr *p802_11Header; |
45c73bb1 | 782 | CMD_STATUS Status; |
92b96797 | 783 | |
92b96797 FB |
784 | if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) { |
785 | ||
1cac4a4b | 786 | p802_11Header = (struct ieee80211_hdr *) (pbyFrame); |
92b96797 FB |
787 | if (!IS_TYPE_MGMT(pbyFrame)) { |
788 | ||
789 | // Data & PS-Poll packet | |
790 | // check frame class | |
791 | if (iSANodeIndex > 0) { | |
792 | // frame class 3 fliter & checking | |
793 | if (pMgmt->sNodeDBTable[iSANodeIndex].eNodeState < NODE_AUTH) { | |
794 | // send deauth notification | |
795 | // reason = (6) class 2 received from nonauth sta | |
796 | vMgrDeAuthenBeginSta(pDevice, | |
797 | pMgmt, | |
1cac4a4b | 798 | (u8 *)(p802_11Header->addr2), |
92b96797 FB |
799 | (WLAN_MGMT_REASON_CLASS2_NONAUTH), |
800 | &Status | |
801 | ); | |
802 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDeAuthenBeginSta 1\n"); | |
4e9b5e2b | 803 | return true; |
9fc86028 | 804 | } |
92b96797 FB |
805 | if (pMgmt->sNodeDBTable[iSANodeIndex].eNodeState < NODE_ASSOC) { |
806 | // send deassoc notification | |
807 | // reason = (7) class 3 received from nonassoc sta | |
808 | vMgrDisassocBeginSta(pDevice, | |
809 | pMgmt, | |
1cac4a4b | 810 | (u8 *)(p802_11Header->addr2), |
92b96797 FB |
811 | (WLAN_MGMT_REASON_CLASS3_NONASSOC), |
812 | &Status | |
813 | ); | |
814 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDisassocBeginSta 2\n"); | |
4e9b5e2b | 815 | return true; |
9fc86028 | 816 | } |
92b96797 FB |
817 | |
818 | if (pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable) { | |
819 | // delcare received ps-poll event | |
820 | if (IS_CTL_PSPOLL(pbyFrame)) { | |
4e9b5e2b | 821 | pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = true; |
0cbd8d98 AM |
822 | bScheduleCommand((void *) pDevice, |
823 | WLAN_CMD_RX_PSPOLL, | |
824 | NULL); | |
92b96797 FB |
825 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 1\n"); |
826 | } | |
827 | else { | |
828 | // check Data PS state | |
829 | // if PW bit off, send out all PS bufferring packets. | |
830 | if (!IS_FC_POWERMGT(pbyFrame)) { | |
e269fc2d | 831 | pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = false; |
4e9b5e2b | 832 | pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = true; |
0cbd8d98 AM |
833 | bScheduleCommand((void *) pDevice, |
834 | WLAN_CMD_RX_PSPOLL, | |
835 | NULL); | |
92b96797 FB |
836 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 2\n"); |
837 | } | |
838 | } | |
839 | } | |
840 | else { | |
841 | if (IS_FC_POWERMGT(pbyFrame)) { | |
4e9b5e2b | 842 | pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = true; |
92b96797 | 843 | // Once if STA in PS state, enable multicast bufferring |
4e9b5e2b | 844 | pMgmt->sNodeDBTable[0].bPSEnable = true; |
92b96797 FB |
845 | } |
846 | else { | |
847 | // clear all pending PS frame. | |
848 | if (pMgmt->sNodeDBTable[iSANodeIndex].wEnQueueCnt > 0) { | |
e269fc2d | 849 | pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = false; |
4e9b5e2b | 850 | pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = true; |
0cbd8d98 AM |
851 | bScheduleCommand((void *) pDevice, |
852 | WLAN_CMD_RX_PSPOLL, | |
853 | NULL); | |
92b96797 FB |
854 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 3\n"); |
855 | ||
856 | } | |
857 | } | |
858 | } | |
859 | } | |
860 | else { | |
861 | vMgrDeAuthenBeginSta(pDevice, | |
862 | pMgmt, | |
1cac4a4b | 863 | (u8 *)(p802_11Header->addr2), |
92b96797 FB |
864 | (WLAN_MGMT_REASON_CLASS2_NONAUTH), |
865 | &Status | |
866 | ); | |
867 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDeAuthenBeginSta 3\n"); | |
d6a32aa1 | 868 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSID:%pM\n", |
1cac4a4b | 869 | p802_11Header->addr3); |
d6a32aa1 | 870 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR2:%pM\n", |
1cac4a4b | 871 | p802_11Header->addr2); |
d6a32aa1 | 872 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR1:%pM\n", |
1cac4a4b AM |
873 | p802_11Header->addr1); |
874 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: frame_control= %x\n", p802_11Header->frame_control); | |
4e9b5e2b | 875 | return true; |
92b96797 FB |
876 | } |
877 | } | |
878 | } | |
e269fc2d | 879 | return false; |
92b96797 FB |
880 | |
881 | } | |
882 | ||
45c73bb1 MP |
883 | static int s_bHandleRxEncryption(struct vnt_private *pDevice, u8 *pbyFrame, |
884 | u32 FrameSize, u8 *pbyRsr, u8 *pbyNewRsr, PSKeyItem *pKeyOut, | |
885 | s32 *pbExtIV, u16 *pwRxTSC15_0, u32 *pdwRxTSC47_16) | |
92b96797 | 886 | { |
45c73bb1 MP |
887 | struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; |
888 | u32 PayloadLen = FrameSize; | |
889 | u8 *pbyIV; | |
890 | u8 byKeyIdx; | |
891 | PSKeyItem pKey = NULL; | |
892 | u8 byDecMode = KEY_CTL_WEP; | |
92b96797 | 893 | |
92b96797 FB |
894 | *pwRxTSC15_0 = 0; |
895 | *pdwRxTSC47_16 = 0; | |
896 | ||
897 | pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN; | |
3eaca0d2 AM |
898 | if ( WLAN_GET_FC_TODS(*(u16 *)pbyFrame) && |
899 | WLAN_GET_FC_FROMDS(*(u16 *)pbyFrame) ) { | |
92b96797 FB |
900 | pbyIV += 6; // 6 is 802.11 address4 |
901 | PayloadLen -= 6; | |
902 | } | |
903 | byKeyIdx = (*(pbyIV+3) & 0xc0); | |
904 | byKeyIdx >>= 6; | |
905 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\nKeyIdx: %d\n", byKeyIdx); | |
906 | ||
907 | if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA) || | |
908 | (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || | |
909 | (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) || | |
910 | (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || | |
911 | (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { | |
912 | if (((*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) && | |
913 | (pMgmt->byCSSPK != KEY_CTL_NONE)) { | |
914 | // unicast pkt use pairwise key | |
915 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"unicast pkt\n"); | |
4e9b5e2b | 916 | if (KeybGetKey(&(pDevice->sKey), pDevice->abyBSSID, 0xFFFFFFFF, &pKey) == true) { |
92b96797 FB |
917 | if (pMgmt->byCSSPK == KEY_CTL_TKIP) |
918 | byDecMode = KEY_CTL_TKIP; | |
919 | else if (pMgmt->byCSSPK == KEY_CTL_CCMP) | |
920 | byDecMode = KEY_CTL_CCMP; | |
921 | } | |
922 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"unicast pkt: %d, %p\n", byDecMode, pKey); | |
923 | } else { | |
924 | // use group key | |
925 | KeybGetKey(&(pDevice->sKey), pDevice->abyBSSID, byKeyIdx, &pKey); | |
926 | if (pMgmt->byCSSGK == KEY_CTL_TKIP) | |
927 | byDecMode = KEY_CTL_TKIP; | |
928 | else if (pMgmt->byCSSGK == KEY_CTL_CCMP) | |
929 | byDecMode = KEY_CTL_CCMP; | |
930 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"group pkt: %d, %d, %p\n", byKeyIdx, byDecMode, pKey); | |
931 | } | |
932 | } | |
933 | // our WEP only support Default Key | |
934 | if (pKey == NULL) { | |
935 | // use default group key | |
936 | KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, byKeyIdx, &pKey); | |
937 | if (pMgmt->byCSSGK == KEY_CTL_TKIP) | |
938 | byDecMode = KEY_CTL_TKIP; | |
939 | else if (pMgmt->byCSSGK == KEY_CTL_CCMP) | |
940 | byDecMode = KEY_CTL_CCMP; | |
941 | } | |
942 | *pKeyOut = pKey; | |
943 | ||
944 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"AES:%d %d %d\n", pMgmt->byCSSPK, pMgmt->byCSSGK, byDecMode); | |
945 | ||
946 | if (pKey == NULL) { | |
947 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey == NULL\n"); | |
e269fc2d | 948 | return false; |
92b96797 FB |
949 | } |
950 | if (byDecMode != pKey->byCipherSuite) { | |
92b96797 | 951 | *pKeyOut = NULL; |
e269fc2d | 952 | return false; |
92b96797 FB |
953 | } |
954 | if (byDecMode == KEY_CTL_WEP) { | |
955 | // handle WEP | |
956 | if ((pDevice->byLocalID <= REV_ID_VT3253_A1) || | |
4e9b5e2b | 957 | (((PSKeyTable)(pKey->pvKeyTable))->bSoftWEP == true)) { |
92b96797 FB |
958 | // Software WEP |
959 | // 1. 3253A | |
960 | // 2. WEP 256 | |
961 | ||
962 | PayloadLen -= (WLAN_HDR_ADDR3_LEN + 4 + 4); // 24 is 802.11 header,4 is IV, 4 is crc | |
3e362598 JL |
963 | memcpy(pDevice->abyPRNG, pbyIV, 3); |
964 | memcpy(pDevice->abyPRNG + 3, pKey->abyKey, pKey->uKeyLength); | |
92b96797 FB |
965 | rc4_init(&pDevice->SBox, pDevice->abyPRNG, pKey->uKeyLength + 3); |
966 | rc4_encrypt(&pDevice->SBox, pbyIV+4, pbyIV+4, PayloadLen); | |
967 | ||
968 | if (ETHbIsBufferCrc32Ok(pbyIV+4, PayloadLen)) { | |
969 | *pbyNewRsr |= NEWRSR_DECRYPTOK; | |
970 | } | |
971 | } | |
972 | } else if ((byDecMode == KEY_CTL_TKIP) || | |
973 | (byDecMode == KEY_CTL_CCMP)) { | |
974 | // TKIP/AES | |
975 | ||
976 | PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc | |
52a7e64b | 977 | *pdwRxTSC47_16 = cpu_to_le32(*(u32 *)(pbyIV + 4)); |
b4dc03af | 978 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16); |
92b96797 FB |
979 | if (byDecMode == KEY_CTL_TKIP) { |
980 | *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); | |
981 | } else { | |
3eaca0d2 | 982 | *pwRxTSC15_0 = cpu_to_le16(*(u16 *)pbyIV); |
92b96797 FB |
983 | } |
984 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC0_15: %x\n", *pwRxTSC15_0); | |
985 | ||
986 | if ((byDecMode == KEY_CTL_TKIP) && | |
987 | (pDevice->byLocalID <= REV_ID_VT3253_A1)) { | |
988 | // Software TKIP | |
989 | // 1. 3253 A | |
1cac4a4b AM |
990 | struct ieee80211_hdr *pMACHeader = (struct ieee80211_hdr *) (pbyFrame); |
991 | TKIPvMixKey(pKey->abyKey, pMACHeader->addr2, *pwRxTSC15_0, *pdwRxTSC47_16, pDevice->abyPRNG); | |
92b96797 FB |
992 | rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN); |
993 | rc4_encrypt(&pDevice->SBox, pbyIV+8, pbyIV+8, PayloadLen); | |
994 | if (ETHbIsBufferCrc32Ok(pbyIV+8, PayloadLen)) { | |
995 | *pbyNewRsr |= NEWRSR_DECRYPTOK; | |
996 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV OK!\n"); | |
997 | } else { | |
998 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV FAIL!!!\n"); | |
999 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PayloadLen = %d\n", PayloadLen); | |
1000 | } | |
1001 | } | |
1002 | }// end of TKIP/AES | |
1003 | ||
1004 | if ((*(pbyIV+3) & 0x20) != 0) | |
4e9b5e2b AM |
1005 | *pbExtIV = true; |
1006 | return true; | |
92b96797 FB |
1007 | } |
1008 | ||
45c73bb1 MP |
1009 | static int s_bAPModeRxData(struct vnt_private *pDevice, struct sk_buff *skb, |
1010 | u32 FrameSize, u32 cbHeaderOffset, s32 iSANodeIndex, s32 iDANodeIndex) | |
92b96797 | 1011 | { |
45c73bb1 MP |
1012 | struct sk_buff *skbcpy; |
1013 | struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; | |
e269fc2d AM |
1014 | int bRelayAndForward = false; |
1015 | int bRelayOnly = false; | |
45c73bb1 MP |
1016 | u8 byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; |
1017 | u16 wAID; | |
92b96797 | 1018 | |
92b96797 | 1019 | if (FrameSize > CB_MAX_BUF_SIZE) |
e269fc2d | 1020 | return false; |
92b96797 | 1021 | // check DA |
b902fbfe | 1022 | if (is_multicast_ether_addr((u8 *)(skb->data+cbHeaderOffset))) { |
92b96797 FB |
1023 | if (pMgmt->sNodeDBTable[0].bPSEnable) { |
1024 | ||
29263661 | 1025 | skbcpy = netdev_alloc_skb(pDevice->dev, pDevice->rx_buf_sz); |
92b96797 FB |
1026 | |
1027 | // if any node in PS mode, buffer packet until DTIM. | |
1028 | if (skbcpy == NULL) { | |
1029 | DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "relay multicast no skb available \n"); | |
1030 | } | |
1031 | else { | |
92b96797 FB |
1032 | skbcpy->len = FrameSize; |
1033 | memcpy(skbcpy->data, skb->data+cbHeaderOffset, FrameSize); | |
1034 | skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skbcpy); | |
1035 | pMgmt->sNodeDBTable[0].wEnQueueCnt++; | |
1036 | // set tx map | |
1037 | pMgmt->abyPSTxMap[0] |= byMask[0]; | |
1038 | } | |
1039 | } | |
1040 | else { | |
4e9b5e2b | 1041 | bRelayAndForward = true; |
92b96797 FB |
1042 | } |
1043 | } | |
1044 | else { | |
1045 | // check if relay | |
b902fbfe | 1046 | if (BSSbIsSTAInNodeDB(pDevice, (u8 *)(skb->data+cbHeaderOffset), &iDANodeIndex)) { |
92b96797 FB |
1047 | if (pMgmt->sNodeDBTable[iDANodeIndex].eNodeState >= NODE_ASSOC) { |
1048 | if (pMgmt->sNodeDBTable[iDANodeIndex].bPSEnable) { | |
1049 | // queue this skb until next PS tx, and then release. | |
1050 | ||
1051 | skb->data += cbHeaderOffset; | |
1052 | skb->tail += cbHeaderOffset; | |
1053 | skb_put(skb, FrameSize); | |
1054 | skb_queue_tail(&pMgmt->sNodeDBTable[iDANodeIndex].sTxPSQueue, skb); | |
1055 | ||
1056 | pMgmt->sNodeDBTable[iDANodeIndex].wEnQueueCnt++; | |
1057 | wAID = pMgmt->sNodeDBTable[iDANodeIndex].wAID; | |
1058 | pMgmt->abyPSTxMap[wAID >> 3] |= byMask[wAID & 7]; | |
1059 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "relay: index= %d, pMgmt->abyPSTxMap[%d]= %d\n", | |
1060 | iDANodeIndex, (wAID >> 3), pMgmt->abyPSTxMap[wAID >> 3]); | |
4e9b5e2b | 1061 | return true; |
92b96797 FB |
1062 | } |
1063 | else { | |
4e9b5e2b | 1064 | bRelayOnly = true; |
92b96797 FB |
1065 | } |
1066 | } | |
9fc86028 | 1067 | } |
92b96797 FB |
1068 | } |
1069 | ||
1070 | if (bRelayOnly || bRelayAndForward) { | |
1071 | // relay this packet right now | |
1072 | if (bRelayAndForward) | |
1073 | iDANodeIndex = 0; | |
1074 | ||
1075 | if ((pDevice->uAssocCount > 1) && (iDANodeIndex >= 0)) { | |
b902fbfe | 1076 | bRelayPacketSend(pDevice, (u8 *) (skb->data + cbHeaderOffset), |
cc856e61 | 1077 | FrameSize, (unsigned int) iDANodeIndex); |
92b96797 FB |
1078 | } |
1079 | ||
1080 | if (bRelayOnly) | |
e269fc2d | 1081 | return false; |
92b96797 FB |
1082 | } |
1083 | // none associate, don't forward | |
1084 | if (pDevice->uAssocCount == 0) | |
e269fc2d | 1085 | return false; |
92b96797 | 1086 | |
4e9b5e2b | 1087 | return true; |
92b96797 FB |
1088 | } |
1089 | ||
81d720d3 | 1090 | void RXvWorkItem(struct work_struct *work) |
92b96797 | 1091 | { |
49d73a98 | 1092 | struct vnt_private *priv = |
81d720d3 | 1093 | container_of(work, struct vnt_private, read_work_item); |
49d73a98 MP |
1094 | int status; |
1095 | struct vnt_rcb *rcb = NULL; | |
92b96797 | 1096 | |
49d73a98 | 1097 | if (priv->Flags & fMP_DISCONNECTED) |
17f3ced0 MP |
1098 | return; |
1099 | ||
49d73a98 | 1100 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Rx Polling Thread\n"); |
731047f9 | 1101 | |
49d73a98 MP |
1102 | spin_lock_irq(&priv->lock); |
1103 | ||
1104 | while ((priv->Flags & fMP_POST_READS) && MP_IS_READY(priv) && | |
1105 | (priv->NumRecvFreeList != 0)) { | |
1106 | rcb = priv->FirstRecvFreeList; | |
1107 | ||
1108 | priv->NumRecvFreeList--; | |
1109 | ||
1110 | DequeueRCB(priv->FirstRecvFreeList, priv->LastRecvFreeList); | |
1111 | ||
1112 | status = PIPEnsBulkInUsbRead(priv, rcb); | |
1113 | } | |
1114 | ||
1115 | priv->bIsRxWorkItemQueued = false; | |
92b96797 | 1116 | |
49d73a98 | 1117 | spin_unlock_irq(&priv->lock); |
92b96797 FB |
1118 | } |
1119 | ||
5a30e0b6 | 1120 | void RXvFreeRCB(struct vnt_rcb *rcb, int re_alloc_skb) |
92b96797 | 1121 | { |
5a30e0b6 | 1122 | struct vnt_private *priv = rcb->pDevice; |
92b96797 | 1123 | |
5a30e0b6 | 1124 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->RXvFreeRCB\n"); |
92b96797 | 1125 | |
5a30e0b6 MP |
1126 | if (re_alloc_skb == false) { |
1127 | kfree_skb(rcb->skb); | |
1128 | re_alloc_skb = true; | |
28044e01 MP |
1129 | } |
1130 | ||
5a30e0b6 | 1131 | if (re_alloc_skb == true) { |
29263661 | 1132 | rcb->skb = netdev_alloc_skb(priv->dev, priv->rx_buf_sz); |
5a30e0b6 | 1133 | /* TODO error handling */ |
29263661 | 1134 | if (!rcb->skb) { |
5a30e0b6 MP |
1135 | DBG_PRT(MSG_LEVEL_ERR, KERN_ERR |
1136 | " Failed to re-alloc rx skb\n"); | |
5a30e0b6 MP |
1137 | } |
1138 | } | |
92b96797 | 1139 | |
5a30e0b6 MP |
1140 | /* Insert the RCB back in the Recv free list */ |
1141 | EnqueueRCB(priv->FirstRecvFreeList, priv->LastRecvFreeList, rcb); | |
1142 | priv->NumRecvFreeList++; | |
92b96797 | 1143 | |
5a30e0b6 MP |
1144 | if ((priv->Flags & fMP_POST_READS) && MP_IS_READY(priv) && |
1145 | (priv->bIsRxWorkItemQueued == false)) { | |
1146 | priv->bIsRxWorkItemQueued = true; | |
1147 | schedule_work(&priv->read_work_item); | |
1148 | } | |
1149 | ||
1150 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----RXFreeRCB %d %d\n", | |
1151 | priv->NumRecvFreeList, priv->NumRecvMngList); | |
92b96797 FB |
1152 | } |
1153 | ||
a21fc2f5 | 1154 | void RXvMngWorkItem(struct work_struct *work) |
92b96797 | 1155 | { |
a21fc2f5 MP |
1156 | struct vnt_private *pDevice = |
1157 | container_of(work, struct vnt_private, rx_mng_work_item); | |
115cac2e | 1158 | struct vnt_rcb *pRCB = NULL; |
45c73bb1 | 1159 | struct vnt_rx_mgmt *pRxPacket; |
e269fc2d | 1160 | int bReAllocSkb = false; |
e03ce839 | 1161 | unsigned long flags; |
92b96797 | 1162 | |
17f3ced0 MP |
1163 | if (pDevice->Flags & fMP_DISCONNECTED) |
1164 | return; | |
1165 | ||
92b96797 FB |
1166 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Rx Mng Thread\n"); |
1167 | ||
92b96797 FB |
1168 | while (pDevice->NumRecvMngList!=0) |
1169 | { | |
e03ce839 MP |
1170 | spin_lock_irqsave(&pDevice->lock, flags); |
1171 | ||
92b96797 FB |
1172 | pRCB = pDevice->FirstRecvMngList; |
1173 | pDevice->NumRecvMngList--; | |
1174 | DequeueRCB(pDevice->FirstRecvMngList, pDevice->LastRecvMngList); | |
e03ce839 MP |
1175 | |
1176 | spin_unlock_irqrestore(&pDevice->lock, flags); | |
1177 | ||
92b96797 FB |
1178 | if(!pRCB){ |
1179 | break; | |
1180 | } | |
92b96797 | 1181 | pRxPacket = &(pRCB->sMngPacket); |
14c5ef57 | 1182 | vMgrRxManagePacket(pDevice, &pDevice->vnt_mgmt, pRxPacket); |
92b96797 | 1183 | pRCB->Ref--; |
e03ce839 MP |
1184 | if (pRCB->Ref == 0) { |
1185 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeMng %d %d\n", | |
1186 | pDevice->NumRecvFreeList, pDevice->NumRecvMngList); | |
1187 | ||
1188 | spin_lock_irqsave(&pDevice->lock, flags); | |
1189 | ||
1190 | RXvFreeRCB(pRCB, bReAllocSkb); | |
1191 | ||
1192 | spin_unlock_irqrestore(&pDevice->lock, flags); | |
1193 | } else { | |
92b96797 FB |
1194 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rx Mng Only we have the right to free RCB\n"); |
1195 | } | |
1196 | } | |
1197 | ||
e269fc2d | 1198 | pDevice->bIsRxMngWorkItemQueued = false; |
92b96797 FB |
1199 | } |
1200 |