Commit | Line | Data |
---|---|---|
4bd43f50 LR |
1 | /* |
2 | * Copyright (c) 2007-2008 Atheros Communications Inc. | |
3 | * | |
4 | * Permission to use, copy, modify, and/or distribute this software for any | |
5 | * purpose with or without fee is hereby granted, provided that the above | |
6 | * copyright notice and this permission notice appear in all copies. | |
7 | * | |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 | */ | |
16 | ||
17 | /** | |
18 | * The power saving manager is to save the power as much as possible. | |
19 | * Generally speaking, it controls: | |
20 | * | |
21 | * - when to sleep | |
22 | * - | |
23 | * | |
24 | */ | |
25 | #include "cprecomp.h" | |
26 | ||
27 | void zfPowerSavingMgrInit(zdev_t* dev) | |
28 | { | |
29 | zmw_get_wlan_dev(dev); | |
30 | ||
31 | wd->sta.powerSaveMode = ZM_STA_PS_NONE; | |
32 | wd->sta.psMgr.state = ZM_PS_MSG_STATE_ACTIVE; | |
33 | wd->sta.psMgr.isSleepAllowed = 0; | |
34 | wd->sta.psMgr.maxSleepPeriods = 1; | |
35 | wd->sta.psMgr.ticks = 0; | |
36 | wd->sta.psMgr.sleepAllowedtick = 0; | |
37 | } | |
38 | ||
39 | static u16_t zfPowerSavingMgrHandlePsNone(zdev_t* dev, u8_t *isWakeUpRequired) | |
40 | { | |
41 | u16_t ret = 0; | |
42 | zmw_get_wlan_dev(dev); | |
43 | ||
44 | switch(wd->sta.psMgr.state) | |
45 | { | |
46 | case ZM_PS_MSG_STATE_ACTIVE: | |
47 | *isWakeUpRequired = 0; | |
48 | break; | |
49 | ||
50 | case ZM_PS_MSG_STATE_T1: | |
51 | case ZM_PS_MSG_STATE_T2: | |
52 | case ZM_PS_MSG_STATE_SLEEP: | |
53 | default: | |
54 | *isWakeUpRequired = 1; | |
55 | zm_debug_msg0("zfPowerSavingMgrHandlePsNone: Wake up now\n"); | |
56 | if ( zfStaIsConnected(dev) ) | |
57 | { | |
58 | zm_debug_msg0("zfPowerSavingMgrOnHandleT1 send Null data\n"); | |
59 | //zfSendNullData(dev, 0); | |
60 | ret = 1; | |
61 | } | |
62 | ||
63 | wd->sta.psMgr.state = ZM_PS_MSG_STATE_ACTIVE; | |
64 | break; | |
65 | } | |
66 | return ret; | |
67 | } | |
68 | ||
69 | static void zfPowerSavingMgrHandlePs(zdev_t* dev) | |
70 | { | |
71 | zmw_get_wlan_dev(dev); | |
72 | ||
73 | switch(wd->sta.psMgr.state) | |
74 | { | |
75 | case ZM_PS_MSG_STATE_ACTIVE: | |
76 | //zm_debug_msg0("zfPowerSavingMgrHandlePs: Prepare to sleep...\n"); | |
77 | //wd->sta.psMgr.state = ZM_PS_MSG_STATE_T1; | |
78 | break; | |
79 | ||
80 | case ZM_PS_MSG_STATE_T1: | |
81 | case ZM_PS_MSG_STATE_T2: | |
82 | case ZM_PS_MSG_STATE_SLEEP: | |
83 | default: | |
84 | break; | |
85 | } | |
86 | } | |
87 | ||
88 | void zfPowerSavingMgrSetMode(zdev_t* dev, u8_t mode) | |
89 | { | |
90 | u16_t sendNull = 0; | |
91 | u8_t isWakeUpRequired = 0; | |
92 | ||
93 | zmw_get_wlan_dev(dev); | |
94 | zmw_declare_for_critical_section(); | |
95 | ||
96 | zm_debug_msg1("mode = ", mode); | |
97 | ||
98 | if (mode > ZM_STA_PS_LIGHT) | |
99 | { | |
100 | zm_debug_msg0("return - wrong power save mode"); | |
101 | return; | |
102 | } | |
103 | ||
104 | zmw_enter_critical_section(dev); | |
105 | ||
106 | #if 1 | |
107 | switch(mode) | |
108 | { | |
109 | case ZM_STA_PS_NONE: | |
110 | sendNull = zfPowerSavingMgrHandlePsNone(dev, &isWakeUpRequired); | |
111 | break; | |
112 | ||
113 | case ZM_STA_PS_FAST: | |
114 | case ZM_STA_PS_LIGHT: | |
115 | wd->sta.psMgr.maxSleepPeriods = 1; | |
116 | zfPowerSavingMgrHandlePs(dev); | |
117 | break; | |
118 | ||
119 | case ZM_STA_PS_MAX: | |
120 | wd->sta.psMgr.maxSleepPeriods = ZM_PS_MAX_SLEEP_PERIODS; | |
121 | zfPowerSavingMgrHandlePs(dev); | |
122 | break; | |
123 | } | |
124 | #else | |
125 | switch(wd->sta.psMgr.state) | |
126 | { | |
127 | case ZM_PS_MSG_STATE_ACTIVE: | |
128 | if ( mode != ZM_STA_PS_NONE ) | |
129 | { | |
130 | zm_debug_msg0("zfPowerSavingMgrSetMode: switch from ZM_PS_MSG_STATE_ACTIVE to ZM_PS_MSG_STATE_T1\n"); | |
131 | // Stall the TX & start to wait the pending TX to be completed | |
132 | wd->sta.psMgr.state = ZM_PS_MSG_STATE_T1; | |
133 | } | |
134 | break; | |
135 | ||
136 | case ZM_PS_MSG_STATE_SLEEP: | |
137 | break; | |
138 | } | |
139 | #endif | |
140 | ||
141 | wd->sta.powerSaveMode = mode; | |
142 | zmw_leave_critical_section(dev); | |
143 | ||
144 | if ( isWakeUpRequired ) | |
145 | { | |
146 | zfHpPowerSaveSetState(dev, 0); | |
147 | wd->sta.psMgr.tempWakeUp = 0; | |
148 | } | |
149 | ||
150 | if ( zfStaIsConnected(dev) | |
151 | && (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) ) | |
152 | { | |
153 | switch(mode) | |
154 | { | |
155 | case ZM_STA_PS_NONE: | |
156 | zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval); | |
157 | break; | |
158 | ||
159 | case ZM_STA_PS_FAST: | |
160 | case ZM_STA_PS_MAX: | |
161 | case ZM_STA_PS_LIGHT: | |
162 | zfHpPowerSaveSetMode(dev, 0, 1, wd->beaconInterval); | |
163 | break; | |
164 | ||
165 | default: | |
166 | zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval); | |
167 | break; | |
168 | } | |
169 | } | |
170 | ||
171 | if (sendNull == 1) | |
172 | { | |
173 | zfSendNullData(dev, 0); | |
174 | } | |
175 | ||
176 | return; | |
177 | } | |
178 | ||
179 | static void zfPowerSavingMgrNotifyPSToAP(zdev_t *dev) | |
180 | { | |
181 | zmw_get_wlan_dev(dev); | |
182 | zmw_declare_for_critical_section(); | |
183 | ||
184 | if ( (wd->sta.psMgr.tempWakeUp != 1)&& | |
185 | (wd->sta.psMgr.lastTxUnicastFrm != wd->commTally.txUnicastFrm || | |
186 | wd->sta.psMgr.lastTxBroadcastFrm != wd->commTally.txBroadcastFrm || | |
187 | wd->sta.psMgr.lastTxMulticastFrm != wd->commTally.txMulticastFrm) ) | |
188 | { | |
189 | zmw_enter_critical_section(dev); | |
190 | wd->sta.psMgr.lastTxUnicastFrm = wd->commTally.txUnicastFrm; | |
191 | wd->sta.psMgr.lastTxBroadcastFrm = wd->commTally.txBroadcastFrm; | |
192 | wd->sta.psMgr.lastTxMulticastFrm = wd->commTally.txMulticastFrm; | |
193 | zmw_leave_critical_section(dev); | |
194 | ||
195 | zfSendNullData(dev, 1); | |
196 | } | |
197 | } | |
198 | ||
199 | static void zfPowerSavingMgrOnHandleT1(zdev_t* dev) | |
200 | { | |
201 | zmw_get_wlan_dev(dev); | |
202 | zmw_declare_for_critical_section(); | |
203 | ||
204 | // If the tx Q is not empty...return | |
205 | if ( zfIsVtxqEmpty(dev) == FALSE ) | |
206 | { | |
207 | return; | |
208 | } | |
209 | ||
210 | zm_debug_msg0("VtxQ is empty now...Check if HAL TXQ is empty\n"); | |
211 | ||
212 | // The the HAL TX Q is not empty...return | |
213 | if ( zfHpGetFreeTxdCount(dev) != zfHpGetMaxTxdCount(dev) ) | |
214 | { | |
215 | return; | |
216 | } | |
217 | ||
218 | zm_debug_msg0("HAL TXQ is empty now...Could go to sleep...\n"); | |
219 | ||
220 | zmw_enter_critical_section(dev); | |
221 | ||
222 | if (wd->sta.powerSaveMode == ZM_STA_PS_LIGHT) | |
223 | { | |
224 | if (wd->sta.ReceivedPktRatePerSecond > 200) | |
225 | { | |
226 | zmw_leave_critical_section(dev); | |
227 | return; | |
228 | } | |
229 | ||
230 | if ( zfStaIsConnected(dev) | |
231 | && (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) ) | |
232 | { | |
233 | if (wd->sta.psMgr.sleepAllowedtick) { | |
234 | wd->sta.psMgr.sleepAllowedtick--; | |
235 | zmw_leave_critical_section(dev); | |
236 | return; | |
237 | } | |
238 | } | |
239 | } | |
240 | ||
241 | wd->sta.psMgr.state = ZM_PS_MSG_STATE_T2; | |
242 | ||
243 | zmw_leave_critical_section(dev); | |
244 | ||
245 | // Send the Null pkt to AP to notify that I'm going to sleep | |
246 | if ( zfStaIsConnected(dev) ) | |
247 | { | |
248 | zm_debug_msg0("zfPowerSavingMgrOnHandleT1 send Null data\n"); | |
249 | zfPowerSavingMgrNotifyPSToAP(dev); | |
250 | } | |
251 | ||
252 | // Stall the TX now | |
253 | // zfTxEngineStop(dev); | |
254 | } | |
255 | ||
256 | static void zfPowerSavingMgrOnHandleT2(zdev_t* dev) | |
257 | { | |
258 | zmw_get_wlan_dev(dev); | |
259 | zmw_declare_for_critical_section(); | |
260 | ||
261 | // Wait until the Null pkt is transmitted | |
262 | if ( zfHpGetFreeTxdCount(dev) != zfHpGetMaxTxdCount(dev) ) | |
263 | { | |
264 | return; | |
265 | } | |
266 | ||
267 | zmw_enter_critical_section(dev); | |
268 | wd->sta.psMgr.state = ZM_PS_MSG_STATE_SLEEP; | |
269 | wd->sta.psMgr.lastTxUnicastFrm = wd->commTally.txUnicastFrm; | |
270 | wd->sta.psMgr.lastTxBroadcastFrm = wd->commTally.txBroadcastFrm; | |
271 | wd->sta.psMgr.lastTxMulticastFrm = wd->commTally.txMulticastFrm; | |
272 | zmw_leave_critical_section(dev); | |
273 | ||
274 | // Let CHIP sleep now | |
275 | zm_debug_msg0("zfPowerSavingMgrOnHandleT2 zzzz....\n"); | |
276 | zfHpPowerSaveSetState(dev, 1); | |
277 | wd->sta.psMgr.tempWakeUp = 0; | |
278 | } | |
279 | ||
280 | u8_t zfPowerSavingMgrIsSleeping(zdev_t *dev) | |
281 | { | |
282 | u8_t isSleeping = FALSE; | |
283 | zmw_get_wlan_dev(dev); | |
284 | zmw_declare_for_critical_section(); | |
285 | ||
286 | zmw_enter_critical_section(dev); | |
287 | if ( wd->sta.psMgr.state == ZM_PS_MSG_STATE_SLEEP || | |
288 | wd->sta.psMgr.state == ZM_PS_MSG_STATE_T2) | |
289 | { | |
290 | isSleeping = TRUE; | |
291 | } | |
292 | zmw_leave_critical_section(dev); | |
293 | return isSleeping; | |
294 | } | |
295 | ||
296 | static u8_t zfPowerSavingMgrIsIdle(zdev_t *dev) | |
297 | { | |
298 | u8_t isIdle = 0; | |
299 | ||
300 | zmw_get_wlan_dev(dev); | |
301 | zmw_declare_for_critical_section(); | |
302 | ||
303 | zmw_enter_critical_section(dev); | |
304 | ||
305 | if ( zfStaIsConnected(dev) && wd->sta.psMgr.isSleepAllowed == 0 ) | |
306 | { | |
307 | goto done; | |
308 | } | |
309 | ||
310 | if ( wd->sta.bChannelScan ) | |
311 | { | |
312 | goto done; | |
313 | } | |
314 | ||
315 | if ( zfStaIsConnecting(dev) ) | |
316 | { | |
317 | goto done; | |
318 | } | |
319 | ||
320 | if (wd->sta.powerSaveMode == ZM_STA_PS_LIGHT) | |
321 | { | |
322 | if (wd->sta.ReceivedPktRatePerSecond > 200) | |
323 | { | |
324 | goto done; | |
325 | } | |
326 | ||
327 | if ( zfStaIsConnected(dev) | |
328 | && (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) ) | |
329 | { | |
330 | if (wd->sta.psMgr.sleepAllowedtick) { | |
331 | wd->sta.psMgr.sleepAllowedtick--; | |
332 | goto done; | |
333 | } | |
334 | } | |
335 | } | |
336 | ||
337 | isIdle = 1; | |
338 | ||
339 | done: | |
340 | zmw_leave_critical_section(dev); | |
341 | ||
342 | if ( zfIsVtxqEmpty(dev) == FALSE ) | |
343 | { | |
344 | isIdle = 0; | |
345 | } | |
346 | ||
347 | return isIdle; | |
348 | } | |
349 | ||
350 | static void zfPowerSavingMgrSleepIfIdle(zdev_t *dev) | |
351 | { | |
352 | u8_t isIdle; | |
353 | ||
354 | zmw_get_wlan_dev(dev); | |
355 | zmw_declare_for_critical_section(); | |
356 | ||
357 | isIdle = zfPowerSavingMgrIsIdle(dev); | |
358 | ||
359 | if ( isIdle == 0 ) | |
360 | { | |
361 | return; | |
362 | } | |
363 | ||
364 | zmw_enter_critical_section(dev); | |
365 | ||
366 | switch(wd->sta.powerSaveMode) | |
367 | { | |
368 | case ZM_STA_PS_NONE: | |
369 | break; | |
370 | ||
371 | case ZM_STA_PS_MAX: | |
372 | case ZM_STA_PS_FAST: | |
373 | case ZM_STA_PS_LIGHT: | |
374 | zm_debug_msg0("zfPowerSavingMgrSleepIfIdle: IDLE so slep now...\n"); | |
375 | wd->sta.psMgr.state = ZM_PS_MSG_STATE_T1; | |
376 | break; | |
377 | } | |
378 | ||
379 | zmw_leave_critical_section(dev); | |
380 | } | |
381 | ||
382 | static void zfPowerSavingMgrDisconnectMain(zdev_t* dev) | |
383 | { | |
4bd43f50 LR |
384 | #ifdef ZM_ENABLE_DISCONNECT_PS |
385 | switch(wd->sta.psMgr.state) | |
386 | { | |
387 | case ZM_PS_MSG_STATE_ACTIVE: | |
388 | zfPowerSavingMgrSleepIfIdle(dev); | |
389 | break; | |
390 | ||
391 | case ZM_PS_MSG_STATE_SLEEP: | |
392 | break; | |
393 | ||
394 | case ZM_PS_MSG_STATE_T1: | |
395 | zfPowerSavingMgrOnHandleT1(dev); | |
396 | break; | |
397 | ||
398 | case ZM_PS_MSG_STATE_T2: | |
399 | zfPowerSavingMgrOnHandleT2(dev); | |
400 | break; | |
401 | } | |
402 | #else | |
403 | zfPowerSavingMgrWakeup(dev); | |
404 | #endif | |
405 | } | |
406 | ||
407 | static void zfPowerSavingMgrInfraMain(zdev_t* dev) | |
408 | { | |
409 | zmw_get_wlan_dev(dev); | |
410 | ||
411 | switch(wd->sta.psMgr.state) | |
412 | { | |
413 | case ZM_PS_MSG_STATE_ACTIVE: | |
414 | zfPowerSavingMgrSleepIfIdle(dev); | |
415 | break; | |
416 | ||
417 | case ZM_PS_MSG_STATE_SLEEP: | |
418 | break; | |
419 | ||
420 | case ZM_PS_MSG_STATE_T1: | |
421 | zfPowerSavingMgrOnHandleT1(dev); | |
422 | break; | |
423 | ||
424 | case ZM_PS_MSG_STATE_T2: | |
425 | zfPowerSavingMgrOnHandleT2(dev); | |
426 | break; | |
427 | } | |
428 | } | |
429 | ||
430 | void zfPowerSavingMgrAtimWinExpired(zdev_t* dev) | |
431 | { | |
432 | zmw_get_wlan_dev(dev); | |
433 | ||
434 | //printk("zfPowerSavingMgrAtimWinExpired #1\n"); | |
435 | if ( wd->sta.powerSaveMode == ZM_STA_PS_NONE ) | |
436 | { | |
437 | return; | |
438 | } | |
439 | ||
440 | //printk("zfPowerSavingMgrAtimWinExpired #2\n"); | |
441 | // if we received any ATIM window from the others to indicate we have buffered data | |
442 | // at the other station, we can't go to sleep | |
443 | if ( wd->sta.recvAtim ) | |
444 | { | |
445 | wd->sta.recvAtim = 0; | |
446 | zm_debug_msg0("Can't sleep due to receving ATIM window!"); | |
447 | return; | |
448 | } | |
449 | ||
450 | // if we are the one to tx beacon during last beacon interval. we can't go to sleep | |
451 | // since we need to be alive to respond the probe request! | |
452 | if ( wd->sta.txBeaconInd ) | |
453 | { | |
454 | zm_debug_msg0("Can't sleep due to just transmit a beacon!"); | |
455 | return; | |
456 | } | |
457 | ||
458 | // If we buffer any data for the other stations. we could not go to sleep | |
459 | if ( wd->sta.ibssPrevPSDataCount != 0 ) | |
460 | { | |
461 | zm_debug_msg0("Can't sleep due to buffering data for the others!"); | |
462 | return; | |
463 | } | |
464 | ||
465 | // before sleeping, we still need to notify the others by transmitting null | |
466 | // pkt with power mgmt bit turned on. | |
467 | zfPowerSavingMgrOnHandleT1(dev); | |
468 | } | |
469 | ||
470 | static void zfPowerSavingMgrIBSSMain(zdev_t* dev) | |
471 | { | |
472 | // wait for the end of | |
473 | // if need to wait to know if we are the one to transmit the beacon | |
474 | // during the beacon interval. If it's me, we can't go to sleep. | |
475 | ||
476 | zmw_get_wlan_dev(dev); | |
477 | ||
478 | switch(wd->sta.psMgr.state) | |
479 | { | |
480 | case ZM_PS_MSG_STATE_ACTIVE: | |
481 | case ZM_PS_MSG_STATE_SLEEP: | |
482 | case ZM_PS_MSG_STATE_T1: | |
483 | break; | |
484 | ||
485 | case ZM_PS_MSG_STATE_T2: | |
486 | zfPowerSavingMgrOnHandleT2(dev); | |
487 | break; | |
488 | } | |
489 | ||
490 | return; | |
491 | } | |
492 | ||
493 | #if 1 | |
494 | void zfPowerSavingMgrMain(zdev_t* dev) | |
495 | { | |
496 | zmw_get_wlan_dev(dev); | |
497 | ||
498 | switch (wd->sta.adapterState) | |
499 | { | |
500 | case ZM_STA_STATE_DISCONNECT: | |
501 | zfPowerSavingMgrDisconnectMain(dev); | |
502 | break; | |
503 | case ZM_STA_STATE_CONNECTED: | |
504 | { | |
505 | if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) { | |
506 | zfPowerSavingMgrInfraMain(dev); | |
507 | } else if (wd->wlanMode == ZM_MODE_IBSS) { | |
508 | zfPowerSavingMgrIBSSMain(dev); | |
509 | } | |
510 | } | |
511 | break; | |
512 | case ZM_STA_STATE_CONNECTING: | |
513 | default: | |
514 | break; | |
515 | } | |
516 | } | |
517 | #else | |
518 | void zfPowerSavingMgrMain(zdev_t* dev) | |
519 | { | |
520 | zmw_get_wlan_dev(dev); | |
521 | ||
522 | if ( wd->wlanMode != ZM_MODE_INFRASTRUCTURE ) | |
523 | { | |
524 | return; | |
525 | } | |
526 | ||
527 | switch(wd->sta.psMgr.state) | |
528 | { | |
529 | case ZM_PS_MSG_STATE_ACTIVE: | |
530 | goto check_sleep; | |
531 | break; | |
532 | ||
533 | case ZM_PS_MSG_STATE_SLEEP: | |
534 | goto sleeping; | |
535 | break; | |
536 | ||
537 | case ZM_PS_MSG_STATE_T1: | |
538 | zfPowerSavingMgrOnHandleT1(dev); | |
539 | break; | |
540 | ||
541 | case ZM_PS_MSG_STATE_T2: | |
542 | zfPowerSavingMgrOnHandleT2(dev); | |
543 | break; | |
544 | } | |
545 | ||
546 | return; | |
547 | ||
548 | sleeping: | |
549 | return; | |
550 | ||
551 | check_sleep: | |
552 | zfPowerSavingMgrSleepIfIdle(dev); | |
553 | return; | |
554 | } | |
555 | #endif | |
556 | ||
557 | #ifdef ZM_ENABLE_POWER_SAVE | |
558 | void zfPowerSavingMgrWakeup(zdev_t* dev) | |
559 | { | |
560 | zmw_get_wlan_dev(dev); | |
561 | zmw_declare_for_critical_section(); | |
562 | ||
563 | //zm_debug_msg0("zfPowerSavingMgrWakeup"); | |
564 | ||
565 | //if ( wd->sta.psMgr.state != ZM_PS_MSG_STATE_ACTIVE && ( zfPowerSavingMgrIsIdle(dev) == 0 )) | |
566 | if ( wd->sta.psMgr.state != ZM_PS_MSG_STATE_ACTIVE ) | |
567 | { | |
568 | zmw_enter_critical_section(dev); | |
569 | ||
570 | wd->sta.psMgr.isSleepAllowed = 0; | |
571 | wd->sta.psMgr.state = ZM_PS_MSG_STATE_ACTIVE; | |
572 | ||
573 | if ( wd->sta.powerSaveMode > ZM_STA_PS_NONE ) | |
574 | wd->sta.psMgr.tempWakeUp = 1; | |
575 | ||
576 | zmw_leave_critical_section(dev); | |
577 | ||
578 | // Wake up the CHIP now!! | |
579 | zfHpPowerSaveSetState(dev, 0); | |
580 | } | |
581 | } | |
582 | #else | |
583 | void zfPowerSavingMgrWakeup(zdev_t* dev) | |
584 | { | |
585 | } | |
586 | #endif | |
587 | ||
588 | void zfPowerSavingMgrProcessBeacon(zdev_t* dev, zbuf_t* buf) | |
589 | { | |
590 | u8_t length, bitmap; | |
591 | u16_t offset, n1, n2, q, r; | |
592 | zbuf_t* psBuf; | |
593 | ||
594 | zmw_get_wlan_dev(dev); | |
595 | zmw_declare_for_critical_section(); | |
596 | ||
597 | if ( wd->sta.powerSaveMode == ZM_STA_PS_NONE ) | |
598 | //if ( wd->sta.psMgr.state != ZM_PS_MSG_STATE_SLEEP ) | |
599 | { | |
600 | return; | |
601 | } | |
602 | ||
603 | wd->sta.psMgr.isSleepAllowed = 1; | |
604 | ||
92363b52 JP |
605 | offset = zfFindElement(dev, buf, ZM_WLAN_EID_TIM); |
606 | if (offset != 0xffff) | |
4bd43f50 LR |
607 | { |
608 | length = zmw_rx_buf_readb(dev, buf, offset+1); | |
609 | ||
610 | if ( length > 3 ) | |
611 | { | |
612 | n1 = zmw_rx_buf_readb(dev, buf, offset+4) & (~ZM_BIT_0); | |
613 | n2 = length + n1 - 4; | |
614 | q = wd->sta.aid >> 3; | |
615 | r = wd->sta.aid & 7; | |
616 | ||
617 | if ((q >= n1) && (q <= n2)) | |
618 | { | |
619 | bitmap = zmw_rx_buf_readb(dev, buf, offset+5+q-n1); | |
620 | ||
621 | if ( (bitmap >> r) & ZM_BIT_0 ) | |
622 | { | |
623 | //if ( wd->sta.powerSaveMode == ZM_STA_PS_FAST ) | |
624 | if ( 0 ) | |
625 | { | |
626 | wd->sta.psMgr.state = ZM_PS_MSG_STATE_S1; | |
627 | //zfSendPSPoll(dev); | |
628 | zfSendNullData(dev, 0); | |
629 | } | |
630 | else | |
631 | { | |
632 | if ((wd->sta.qosInfo&0xf) != 0xf) | |
633 | { | |
634 | /* send ps-poll */ | |
635 | //printk("zfSendPSPoll #1\n"); | |
636 | ||
637 | wd->sta.psMgr.isSleepAllowed = 0; | |
638 | ||
639 | switch (wd->sta.powerSaveMode) | |
640 | { | |
641 | case ZM_STA_PS_MAX: | |
642 | case ZM_STA_PS_FAST: | |
643 | //zm_debug_msg0("wake up and send PS-Poll\n"); | |
644 | zfSendPSPoll(dev); | |
645 | break; | |
646 | case ZM_STA_PS_LIGHT: | |
647 | zm_debug_msg0("wake up and send null data\n"); | |
648 | ||
649 | zmw_enter_critical_section(dev); | |
650 | wd->sta.psMgr.sleepAllowedtick = 400; | |
651 | zmw_leave_critical_section(dev); | |
652 | ||
653 | zfSendNullData(dev, 0); | |
654 | break; | |
655 | } | |
656 | ||
657 | wd->sta.psMgr.tempWakeUp = 0; | |
658 | } | |
659 | } | |
660 | } | |
661 | } | |
662 | } | |
663 | } | |
664 | ||
665 | while ((psBuf = zfQueueGet(dev, wd->sta.uapsdQ)) != NULL) | |
666 | { | |
667 | zfTxSendEth(dev, psBuf, 0, ZM_EXTERNAL_ALLOC_BUF, 0); | |
668 | } | |
669 | ||
670 | //printk("zfPowerSavingMgrProcessBeacon #1\n"); | |
671 | zfPowerSavingMgrMain(dev); | |
672 | } | |
673 | ||
674 | void zfPowerSavingMgrConnectNotify(zdev_t *dev) | |
675 | { | |
676 | zmw_get_wlan_dev(dev); | |
677 | ||
678 | if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE ) | |
679 | { | |
680 | switch(wd->sta.powerSaveMode) | |
681 | { | |
682 | case ZM_STA_PS_NONE: | |
683 | zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval); | |
684 | break; | |
685 | ||
686 | case ZM_STA_PS_FAST: | |
687 | case ZM_STA_PS_MAX: | |
688 | case ZM_STA_PS_LIGHT: | |
689 | zfHpPowerSaveSetMode(dev, 0, 1, wd->beaconInterval); | |
690 | break; | |
691 | ||
692 | default: | |
693 | zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval); | |
694 | break; | |
695 | } | |
696 | } | |
697 | } | |
698 | ||
699 | void zfPowerSavingMgrPreTBTTInterrupt(zdev_t *dev) | |
700 | { | |
701 | zmw_get_wlan_dev(dev); | |
702 | zmw_declare_for_critical_section(); | |
703 | ||
704 | /* disable TBTT interrupt when change from connection to disconnect */ | |
705 | if (zfStaIsDisconnect(dev)) { | |
706 | zfHpPowerSaveSetMode(dev, 0, 0, 0); | |
707 | zfPowerSavingMgrWakeup(dev); | |
708 | return; | |
709 | } | |
710 | ||
711 | zmw_enter_critical_section(dev); | |
712 | wd->sta.psMgr.ticks++; | |
713 | ||
714 | if ( wd->sta.psMgr.ticks < wd->sta.psMgr.maxSleepPeriods ) | |
715 | { | |
716 | zmw_leave_critical_section(dev); | |
717 | return; | |
718 | } | |
719 | else | |
720 | { | |
721 | wd->sta.psMgr.ticks = 0; | |
722 | } | |
723 | ||
724 | zmw_leave_critical_section(dev); | |
725 | ||
726 | zfPowerSavingMgrWakeup(dev); | |
727 | } | |
728 | ||
729 | /* Leave an empty line below to remove warning message on some compiler */ | |
730 |