1 /*- 2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include <sys/cdefs.h> 27 __FBSDID("$FreeBSD$"); 28 29 /* 30 * IEEE 802.11 power save support. 31 */ 32 #include "opt_wlan.h" 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 38 #include <sys/socket.h> 39 40 #include <net/if.h> 41 #include <net/if_var.h> 42 #include <net/if_media.h> 43 #include <net/ethernet.h> 44 45 #include <net80211/ieee80211_var.h> 46 47 #include <net/bpf.h> 48 49 static void ieee80211_update_ps(struct ieee80211vap *, int); 50 static int ieee80211_set_tim(struct ieee80211_node *, int); 51 52 static MALLOC_DEFINE(M_80211_POWER, "80211power", "802.11 power save state"); 53 54 void 55 ieee80211_power_attach(struct ieee80211com *ic) 56 { 57 } 58 59 void 60 ieee80211_power_detach(struct ieee80211com *ic) 61 { 62 } 63 64 void 65 ieee80211_power_vattach(struct ieee80211vap *vap) 66 { 67 if (vap->iv_opmode == IEEE80211_M_HOSTAP || 68 vap->iv_opmode == IEEE80211_M_IBSS) { 69 /* NB: driver should override */ 70 vap->iv_update_ps = ieee80211_update_ps; 71 vap->iv_set_tim = ieee80211_set_tim; 72 } 73 vap->iv_node_ps = ieee80211_node_pwrsave; 74 vap->iv_sta_ps = ieee80211_sta_pwrsave; 75 } 76 77 void 78 ieee80211_power_latevattach(struct ieee80211vap *vap) 79 { 80 /* 81 * Allocate these only if needed. Beware that we 82 * know adhoc mode doesn't support ATIM yet... 83 */ 84 if (vap->iv_opmode == IEEE80211_M_HOSTAP) { 85 vap->iv_tim_len = howmany(vap->iv_max_aid,8) * sizeof(uint8_t); 86 vap->iv_tim_bitmap = (uint8_t *) IEEE80211_MALLOC(vap->iv_tim_len, 87 M_80211_POWER, 88 IEEE80211_M_NOWAIT | IEEE80211_M_ZERO); 89 if (vap->iv_tim_bitmap == NULL) { 90 printf("%s: no memory for TIM bitmap!\n", __func__); 91 /* XXX good enough to keep from crashing? */ 92 vap->iv_tim_len = 0; 93 } 94 } 95 } 96 97 void 98 ieee80211_power_vdetach(struct ieee80211vap *vap) 99 { 100 if (vap->iv_tim_bitmap != NULL) { 101 IEEE80211_FREE(vap->iv_tim_bitmap, M_80211_POWER); 102 vap->iv_tim_bitmap = NULL; 103 } 104 } 105 106 void 107 ieee80211_psq_init(struct ieee80211_psq *psq, const char *name) 108 { 109 memset(psq, 0, sizeof(*psq)); 110 psq->psq_maxlen = IEEE80211_PS_MAX_QUEUE; 111 IEEE80211_PSQ_INIT(psq, name); /* OS-dependent setup */ 112 } 113 114 void 115 ieee80211_psq_cleanup(struct ieee80211_psq *psq) 116 { 117 #if 0 118 psq_drain(psq); /* XXX should not be needed? */ 119 #else 120 KASSERT(psq->psq_len == 0, ("%d frames on ps q", psq->psq_len)); 121 #endif 122 IEEE80211_PSQ_DESTROY(psq); /* OS-dependent cleanup */ 123 } 124 125 /* 126 * Return the highest priority frame in the ps queue. 127 */ 128 struct mbuf * 129 ieee80211_node_psq_dequeue(struct ieee80211_node *ni, int *qlen) 130 { 131 struct ieee80211_psq *psq = &ni->ni_psq; 132 struct ieee80211_psq_head *qhead; 133 struct mbuf *m; 134 135 IEEE80211_PSQ_LOCK(psq); 136 qhead = &psq->psq_head[0]; 137 again: 138 if ((m = qhead->head) != NULL) { 139 if ((qhead->head = m->m_nextpkt) == NULL) 140 qhead->tail = NULL; 141 KASSERT(qhead->len > 0, ("qhead len %d", qhead->len)); 142 qhead->len--; 143 KASSERT(psq->psq_len > 0, ("psq len %d", psq->psq_len)); 144 psq->psq_len--; 145 m->m_nextpkt = NULL; 146 } 147 if (m == NULL && qhead == &psq->psq_head[0]) { 148 /* Algol-68 style for loop */ 149 qhead = &psq->psq_head[1]; 150 goto again; 151 } 152 if (qlen != NULL) 153 *qlen = psq->psq_len; 154 IEEE80211_PSQ_UNLOCK(psq); 155 return m; 156 } 157 158 /* 159 * Reclaim an mbuf from the ps q. If marked with M_ENCAP 160 * we assume there is a node reference that must be relcaimed. 161 */ 162 static void 163 psq_mfree(struct mbuf *m) 164 { 165 if (m->m_flags & M_ENCAP) { 166 struct ieee80211_node *ni = (void *) m->m_pkthdr.rcvif; 167 ieee80211_free_node(ni); 168 } 169 m->m_nextpkt = NULL; 170 m_freem(m); 171 } 172 173 /* 174 * Clear any frames queued in the power save queue. 175 * The number of frames that were present is returned. 176 */ 177 static int 178 psq_drain(struct ieee80211_psq *psq) 179 { 180 struct ieee80211_psq_head *qhead; 181 struct mbuf *m; 182 int qlen; 183 184 IEEE80211_PSQ_LOCK(psq); 185 qlen = psq->psq_len; 186 qhead = &psq->psq_head[0]; 187 again: 188 while ((m = qhead->head) != NULL) { 189 qhead->head = m->m_nextpkt; 190 psq_mfree(m); 191 } 192 qhead->tail = NULL; 193 qhead->len = 0; 194 if (qhead == &psq->psq_head[0]) { /* Algol-68 style for loop */ 195 qhead = &psq->psq_head[1]; 196 goto again; 197 } 198 psq->psq_len = 0; 199 IEEE80211_PSQ_UNLOCK(psq); 200 201 return qlen; 202 } 203 204 /* 205 * Clear any frames queued in the power save queue. 206 * The number of frames that were present is returned. 207 */ 208 int 209 ieee80211_node_psq_drain(struct ieee80211_node *ni) 210 { 211 return psq_drain(&ni->ni_psq); 212 } 213 214 /* 215 * Age frames on the power save queue. The aging interval is 216 * 4 times the listen interval specified by the station. This 217 * number is factored into the age calculations when the frame 218 * is placed on the queue. We store ages as time differences 219 * so we can check and/or adjust only the head of the list. 220 * If a frame's age exceeds the threshold then discard it. 221 * The number of frames discarded is returned so the caller 222 * can check if it needs to adjust the tim. 223 */ 224 int 225 ieee80211_node_psq_age(struct ieee80211_node *ni) 226 { 227 struct ieee80211_psq *psq = &ni->ni_psq; 228 int discard = 0; 229 230 if (psq->psq_len != 0) { 231 #ifdef IEEE80211_DEBUG 232 struct ieee80211vap *vap = ni->ni_vap; 233 #endif 234 struct ieee80211_psq_head *qhead; 235 struct mbuf *m; 236 237 IEEE80211_PSQ_LOCK(psq); 238 qhead = &psq->psq_head[0]; 239 again: 240 while ((m = qhead->head) != NULL && 241 M_AGE_GET(m) < IEEE80211_INACT_WAIT) { 242 IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni, 243 "discard frame, age %u", M_AGE_GET(m)); 244 if ((qhead->head = m->m_nextpkt) == NULL) 245 qhead->tail = NULL; 246 KASSERT(qhead->len > 0, ("qhead len %d", qhead->len)); 247 qhead->len--; 248 KASSERT(psq->psq_len > 0, ("psq len %d", psq->psq_len)); 249 psq->psq_len--; 250 psq_mfree(m); 251 discard++; 252 } 253 if (qhead == &psq->psq_head[0]) { /* Algol-68 style for loop */ 254 qhead = &psq->psq_head[1]; 255 goto again; 256 } 257 if (m != NULL) 258 M_AGE_SUB(m, IEEE80211_INACT_WAIT); 259 IEEE80211_PSQ_UNLOCK(psq); 260 261 IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni, 262 "discard %u frames for age", discard); 263 IEEE80211_NODE_STAT_ADD(ni, ps_discard, discard); 264 } 265 return discard; 266 } 267 268 /* 269 * Handle a change in the PS station occupancy. 270 */ 271 static void 272 ieee80211_update_ps(struct ieee80211vap *vap, int nsta) 273 { 274 275 KASSERT(vap->iv_opmode == IEEE80211_M_HOSTAP || 276 vap->iv_opmode == IEEE80211_M_IBSS, 277 ("operating mode %u", vap->iv_opmode)); 278 } 279 280 /* 281 * Indicate whether there are frames queued for a station in power-save mode. 282 */ 283 static int 284 ieee80211_set_tim(struct ieee80211_node *ni, int set) 285 { 286 struct ieee80211vap *vap = ni->ni_vap; 287 struct ieee80211com *ic = ni->ni_ic; 288 uint16_t aid; 289 int changed; 290 291 KASSERT(vap->iv_opmode == IEEE80211_M_HOSTAP || 292 vap->iv_opmode == IEEE80211_M_IBSS, 293 ("operating mode %u", vap->iv_opmode)); 294 295 aid = IEEE80211_AID(ni->ni_associd); 296 KASSERT(aid < vap->iv_max_aid, 297 ("bogus aid %u, max %u", aid, vap->iv_max_aid)); 298 299 IEEE80211_LOCK(ic); 300 changed = (set != (isset(vap->iv_tim_bitmap, aid) != 0)); 301 if (changed) { 302 if (set) { 303 setbit(vap->iv_tim_bitmap, aid); 304 vap->iv_ps_pending++; 305 } else { 306 clrbit(vap->iv_tim_bitmap, aid); 307 vap->iv_ps_pending--; 308 } 309 /* NB: we know vap is in RUN state so no need to check */ 310 vap->iv_update_beacon(vap, IEEE80211_BEACON_TIM); 311 } 312 IEEE80211_UNLOCK(ic); 313 314 return changed; 315 } 316 317 /* 318 * Save an outbound packet for a node in power-save sleep state. 319 * The new packet is placed on the node's saved queue, and the TIM 320 * is changed, if necessary. 321 */ 322 int 323 ieee80211_pwrsave(struct ieee80211_node *ni, struct mbuf *m) 324 { 325 struct ieee80211_psq *psq = &ni->ni_psq; 326 struct ieee80211vap *vap = ni->ni_vap; 327 struct ieee80211com *ic = ni->ni_ic; 328 struct ieee80211_psq_head *qhead; 329 int qlen, age; 330 331 IEEE80211_PSQ_LOCK(psq); 332 if (psq->psq_len >= psq->psq_maxlen) { 333 psq->psq_drops++; 334 IEEE80211_PSQ_UNLOCK(psq); 335 IEEE80211_NOTE(vap, IEEE80211_MSG_ANY, ni, 336 "pwr save q overflow, drops %d (size %d)", 337 psq->psq_drops, psq->psq_len); 338 #ifdef IEEE80211_DEBUG 339 if (ieee80211_msg_dumppkts(vap)) 340 ieee80211_dump_pkt(ni->ni_ic, mtod(m, caddr_t), 341 m->m_len, -1, -1); 342 #endif 343 psq_mfree(m); 344 return ENOSPC; 345 } 346 /* 347 * Tag the frame with it's expiry time and insert it in 348 * the appropriate queue. The aging interval is 4 times 349 * the listen interval specified by the station. Frames 350 * that sit around too long are reclaimed using this 351 * information. 352 */ 353 /* TU -> secs. XXX handle overflow? */ 354 age = IEEE80211_TU_TO_MS((ni->ni_intval * ic->ic_bintval) << 2) / 1000; 355 /* 356 * Encapsulated frames go on the high priority queue, 357 * other stuff goes on the low priority queue. We use 358 * this to order frames returned out of the driver 359 * ahead of frames we collect in ieee80211_start. 360 */ 361 if (m->m_flags & M_ENCAP) 362 qhead = &psq->psq_head[0]; 363 else 364 qhead = &psq->psq_head[1]; 365 if (qhead->tail == NULL) { 366 struct mbuf *mh; 367 368 qhead->head = m; 369 /* 370 * Take care to adjust age when inserting the first 371 * frame of a queue and the other queue already has 372 * frames. We need to preserve the age difference 373 * relationship so ieee80211_node_psq_age works. 374 */ 375 if (qhead == &psq->psq_head[1]) { 376 mh = psq->psq_head[0].head; 377 if (mh != NULL) 378 age-= M_AGE_GET(mh); 379 } else { 380 mh = psq->psq_head[1].head; 381 if (mh != NULL) { 382 int nage = M_AGE_GET(mh) - age; 383 /* XXX is clamping to zero good 'nuf? */ 384 M_AGE_SET(mh, nage < 0 ? 0 : nage); 385 } 386 } 387 } else { 388 qhead->tail->m_nextpkt = m; 389 age -= M_AGE_GET(qhead->head); 390 } 391 KASSERT(age >= 0, ("age %d", age)); 392 M_AGE_SET(m, age); 393 m->m_nextpkt = NULL; 394 qhead->tail = m; 395 qhead->len++; 396 qlen = ++(psq->psq_len); 397 IEEE80211_PSQ_UNLOCK(psq); 398 399 IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni, 400 "save frame with age %d, %u now queued", age, qlen); 401 402 if (qlen == 1 && vap->iv_set_tim != NULL) 403 vap->iv_set_tim(ni, 1); 404 405 return 0; 406 } 407 408 /* 409 * Move frames from the ps q to the vap's send queue 410 * and/or the driver's send queue; and kick the start 411 * method for each, as appropriate. Note we're careful 412 * to preserve packet ordering here. 413 */ 414 static void 415 pwrsave_flushq(struct ieee80211_node *ni) 416 { 417 struct ieee80211_psq *psq = &ni->ni_psq; 418 struct ieee80211com *ic = ni->ni_ic; 419 struct ieee80211vap *vap = ni->ni_vap; 420 struct ieee80211_psq_head *qhead; 421 struct ifnet *parent, *ifp; 422 struct mbuf *parent_q = NULL, *ifp_q = NULL; 423 struct mbuf *m; 424 425 IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni, 426 "flush ps queue, %u packets queued", psq->psq_len); 427 428 IEEE80211_PSQ_LOCK(psq); 429 qhead = &psq->psq_head[0]; /* 802.11 frames */ 430 if (qhead->head != NULL) { 431 /* XXX could dispatch through vap and check M_ENCAP */ 432 parent = vap->iv_ic->ic_ifp; 433 /* XXX need different driver interface */ 434 /* XXX bypasses q max and OACTIVE */ 435 parent_q = qhead->head; 436 qhead->head = qhead->tail = NULL; 437 qhead->len = 0; 438 } else 439 parent = NULL; 440 441 qhead = &psq->psq_head[1]; /* 802.3 frames */ 442 if (qhead->head != NULL) { 443 ifp = vap->iv_ifp; 444 /* XXX need different driver interface */ 445 /* XXX bypasses q max and OACTIVE */ 446 ifp_q = qhead->head; 447 qhead->head = qhead->tail = NULL; 448 qhead->len = 0; 449 } else 450 ifp = NULL; 451 psq->psq_len = 0; 452 IEEE80211_PSQ_UNLOCK(psq); 453 454 /* NB: do this outside the psq lock */ 455 /* XXX packets might get reordered if parent is OACTIVE */ 456 /* parent frames, should be encapsulated */ 457 if (parent != NULL) { 458 while (parent_q != NULL) { 459 m = parent_q; 460 parent_q = m->m_nextpkt; 461 m->m_nextpkt = NULL; 462 /* must be encapsulated */ 463 KASSERT((m->m_flags & M_ENCAP), 464 ("%s: parentq with non-M_ENCAP frame!\n", 465 __func__)); 466 /* 467 * For encaped frames, we need to free the node 468 * reference upon failure. 469 */ 470 if (ieee80211_parent_xmitpkt(ic, m) != 0) 471 ieee80211_free_node(ni); 472 } 473 } 474 475 /* VAP frames, aren't encapsulated */ 476 if (ifp != NULL) { 477 while (ifp_q != NULL) { 478 m = ifp_q; 479 ifp_q = m->m_nextpkt; 480 m->m_nextpkt = NULL; 481 KASSERT((!(m->m_flags & M_ENCAP)), 482 ("%s: vapq with M_ENCAP frame!\n", __func__)); 483 (void) ieee80211_vap_xmitpkt(vap, m); 484 } 485 } 486 } 487 488 /* 489 * Handle station power-save state change. 490 */ 491 void 492 ieee80211_node_pwrsave(struct ieee80211_node *ni, int enable) 493 { 494 struct ieee80211vap *vap = ni->ni_vap; 495 int update; 496 497 update = 0; 498 if (enable) { 499 if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) { 500 vap->iv_ps_sta++; 501 update = 1; 502 } 503 ni->ni_flags |= IEEE80211_NODE_PWR_MGT; 504 IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni, 505 "power save mode on, %u sta's in ps mode", vap->iv_ps_sta); 506 507 if (update) 508 vap->iv_update_ps(vap, vap->iv_ps_sta); 509 } else { 510 if (ni->ni_flags & IEEE80211_NODE_PWR_MGT) { 511 vap->iv_ps_sta--; 512 update = 1; 513 } 514 ni->ni_flags &= ~IEEE80211_NODE_PWR_MGT; 515 IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni, 516 "power save mode off, %u sta's in ps mode", vap->iv_ps_sta); 517 518 /* NB: order here is intentional so TIM is clear before flush */ 519 if (vap->iv_set_tim != NULL) 520 vap->iv_set_tim(ni, 0); 521 if (update) { 522 /* NB if no sta's in ps, driver should flush mc q */ 523 vap->iv_update_ps(vap, vap->iv_ps_sta); 524 } 525 if (ni->ni_psq.psq_len != 0) 526 pwrsave_flushq(ni); 527 } 528 } 529 530 /* 531 * Handle power-save state change in station mode. 532 */ 533 void 534 ieee80211_sta_pwrsave(struct ieee80211vap *vap, int enable) 535 { 536 struct ieee80211_node *ni = vap->iv_bss; 537 538 if (!((enable != 0) ^ ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) != 0))) 539 return; 540 541 IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni, 542 "sta power save mode %s", enable ? "on" : "off"); 543 if (!enable) { 544 ni->ni_flags &= ~IEEE80211_NODE_PWR_MGT; 545 ieee80211_send_nulldata(ieee80211_ref_node(ni)); 546 /* 547 * Flush any queued frames; we can do this immediately 548 * because we know they'll be queued behind the null 549 * data frame we send the ap. 550 * XXX can we use a data frame to take us out of ps? 551 */ 552 if (ni->ni_psq.psq_len != 0) 553 pwrsave_flushq(ni); 554 } else { 555 ni->ni_flags |= IEEE80211_NODE_PWR_MGT; 556 ieee80211_send_nulldata(ieee80211_ref_node(ni)); 557 } 558 } 559 560 /* 561 * Handle being notified that we have data available for us in a TIM/ATIM. 562 * 563 * This may schedule a transition from _SLEEP -> _RUN if it's appropriate. 564 * 565 * In STA mode, we may have put to sleep during scan and need to be dragged 566 * back out of powersave mode. 567 */ 568 void 569 ieee80211_sta_tim_notify(struct ieee80211vap *vap, int set) 570 { 571 struct ieee80211com *ic = vap->iv_ic; 572 573 /* 574 * Schedule the driver state change. It'll happen at some point soon. 575 * Since the hardware shouldn't know that we're running just yet 576 * (and thus tell the peer that we're awake before we actually wake 577 * up said hardware), we leave the actual node state transition 578 * up to the transition to RUN. 579 * 580 * XXX TODO: verify that the transition to RUN will wake up the 581 * BSS node! 582 */ 583 IEEE80211_LOCK(vap->iv_ic); 584 if (set == 1 && vap->iv_state == IEEE80211_S_SLEEP) { 585 ieee80211_new_state_locked(vap, IEEE80211_S_RUN, 0); 586 IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER, 587 "%s: TIM=%d; wakeup\n", __func__, set); 588 } else if ((set == 1) && (ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN)) { 589 /* 590 * XXX only do this if we're in RUN state? 591 */ 592 IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER, 593 "%s: wake up from bgscan vap sleep\n", 594 __func__); 595 /* 596 * We may be in BGSCAN mode - this means the VAP is is in STA 597 * mode powersave. If it is, we need to wake it up so we 598 * can process outbound traffic. 599 */ 600 vap->iv_sta_ps(vap, 0); 601 } 602 IEEE80211_UNLOCK(vap->iv_ic); 603 } 604 605 /* 606 * Timer check on whether the VAP has had any transmit activity. 607 * 608 * This may schedule a transition from _RUN -> _SLEEP if it's appropriate. 609 */ 610 void 611 ieee80211_sta_ps_timer_check(struct ieee80211vap *vap) 612 { 613 struct ieee80211com *ic = vap->iv_ic; 614 615 /* XXX lock assert */ 616 617 /* For no, only do this in STA mode */ 618 if (! (vap->iv_caps & IEEE80211_C_SWSLEEP)) 619 goto out; 620 621 if (vap->iv_opmode != IEEE80211_M_STA) 622 goto out; 623 624 /* If we're not at run state, bail */ 625 if (vap->iv_state != IEEE80211_S_RUN) 626 goto out; 627 628 IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER, 629 "%s: lastdata=%llu, ticks=%llu\n", 630 __func__, (unsigned long long) ic->ic_lastdata, 631 (unsigned long long) ticks); 632 633 /* If powersave is disabled on the VAP, don't bother */ 634 if (! (vap->iv_flags & IEEE80211_F_PMGTON)) 635 goto out; 636 637 /* If we've done any data within our idle interval, bail */ 638 /* XXX hard-coded to one second for now, ew! */ 639 if (time_after(ic->ic_lastdata + 500, ticks)) 640 goto out; 641 642 /* 643 * Signify we're going into power save and transition the 644 * node to powersave. 645 */ 646 if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) 647 vap->iv_sta_ps(vap, 1); 648 649 /* 650 * XXX The driver has to handle the fact that we're going 651 * to sleep but frames may still be transmitted; 652 * hopefully it and/or us will do the right thing and mark any 653 * transmitted frames with PWRMGT set to 1. 654 */ 655 ieee80211_new_state_locked(vap, IEEE80211_S_SLEEP, 0); 656 657 IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER, 658 "%s: time delta=%d msec\n", __func__, 659 (int) ticks_to_msecs(ticks - ic->ic_lastdata)); 660 661 out: 662 return; 663 } 664