aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/recv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/recv.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c194
1 files changed, 162 insertions, 32 deletions
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index b46badd21f73..5014a19b0f75 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -473,6 +473,159 @@ void ath_flushrecv(struct ath_softc *sc)
473 spin_unlock_bh(&sc->rx.rxflushlock); 473 spin_unlock_bh(&sc->rx.rxflushlock);
474} 474}
475 475
476static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
477{
478 /* Check whether the Beacon frame has DTIM indicating buffered bc/mc */
479 struct ieee80211_mgmt *mgmt;
480 u8 *pos, *end, id, elen;
481 struct ieee80211_tim_ie *tim;
482
483 mgmt = (struct ieee80211_mgmt *)skb->data;
484 pos = mgmt->u.beacon.variable;
485 end = skb->data + skb->len;
486
487 while (pos + 2 < end) {
488 id = *pos++;
489 elen = *pos++;
490 if (pos + elen > end)
491 break;
492
493 if (id == WLAN_EID_TIM) {
494 if (elen < sizeof(*tim))
495 break;
496 tim = (struct ieee80211_tim_ie *) pos;
497 if (tim->dtim_count != 0)
498 break;
499 return tim->bitmap_ctrl & 0x01;
500 }
501
502 pos += elen;
503 }
504
505 return false;
506}
507
508static void ath_rx_ps_back_to_sleep(struct ath_softc *sc)
509{
510 sc->sc_flags &= ~(SC_OP_WAIT_FOR_BEACON | SC_OP_WAIT_FOR_CAB);
511}
512
513static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
514{
515 struct ieee80211_mgmt *mgmt;
516
517 if (skb->len < 24 + 8 + 2 + 2)
518 return;
519
520 mgmt = (struct ieee80211_mgmt *)skb->data;
521 if (memcmp(sc->curbssid, mgmt->bssid, ETH_ALEN) != 0)
522 return; /* not from our current AP */
523
524 if (sc->sc_flags & SC_OP_BEACON_SYNC) {
525 sc->sc_flags &= ~SC_OP_BEACON_SYNC;
526 DPRINTF(sc, ATH_DBG_PS, "Reconfigure Beacon timers based on "
527 "timestamp from the AP\n");
528 ath_beacon_config(sc, NULL);
529 }
530
531 if (!(sc->hw->conf.flags & IEEE80211_CONF_PS)) {
532 /* We are not in PS mode anymore; remain awake */
533 DPRINTF(sc, ATH_DBG_PS, "Not in PS mode anymore, remain "
534 "awake\n");
535 sc->sc_flags &= ~(SC_OP_WAIT_FOR_BEACON | SC_OP_WAIT_FOR_CAB);
536 return;
537 }
538
539 if (ath_beacon_dtim_pending_cab(skb)) {
540 /*
541 * Remain awake waiting for buffered broadcast/multicast
542 * frames.
543 */
544 DPRINTF(sc, ATH_DBG_PS, "Received DTIM beacon indicating "
545 "buffered broadcast/multicast frame(s)\n");
546 sc->sc_flags |= SC_OP_WAIT_FOR_CAB;
547 return;
548 }
549
550 if (sc->sc_flags & SC_OP_WAIT_FOR_CAB) {
551 /*
552 * This can happen if a broadcast frame is dropped or the AP
553 * fails to send a frame indicating that all CAB frames have
554 * been delivered.
555 */
556 DPRINTF(sc, ATH_DBG_PS, "PS wait for CAB frames timed out\n");
557 }
558
559 /* No more broadcast/multicast frames to be received at this point. */
560 ath_rx_ps_back_to_sleep(sc);
561}
562
563static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
564{
565 struct ieee80211_hdr *hdr;
566
567 hdr = (struct ieee80211_hdr *)skb->data;
568
569 /* Process Beacon and CAB receive in PS state */
570 if ((sc->sc_flags & SC_OP_WAIT_FOR_BEACON) &&
571 ieee80211_is_beacon(hdr->frame_control))
572 ath_rx_ps_beacon(sc, skb);
573 else if ((sc->sc_flags & SC_OP_WAIT_FOR_CAB) &&
574 (ieee80211_is_data(hdr->frame_control) ||
575 ieee80211_is_action(hdr->frame_control)) &&
576 is_multicast_ether_addr(hdr->addr1) &&
577 !ieee80211_has_moredata(hdr->frame_control)) {
578 DPRINTF(sc, ATH_DBG_PS, "All PS CAB frames received, back to "
579 "sleep\n");
580 /*
581 * No more broadcast/multicast frames to be received at this
582 * point.
583 */
584 ath_rx_ps_back_to_sleep(sc);
585 } else if ((sc->sc_flags & SC_OP_WAIT_FOR_PSPOLL_DATA) &&
586 !is_multicast_ether_addr(hdr->addr1) &&
587 !ieee80211_has_morefrags(hdr->frame_control)) {
588 sc->sc_flags &= ~SC_OP_WAIT_FOR_PSPOLL_DATA;
589 DPRINTF(sc, ATH_DBG_PS, "Going back to sleep after having "
590 "received PS-Poll data (0x%x)\n",
591 sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
592 SC_OP_WAIT_FOR_CAB |
593 SC_OP_WAIT_FOR_PSPOLL_DATA |
594 SC_OP_WAIT_FOR_TX_ACK));
595 }
596}
597
598static void ath_rx_send_to_mac80211(struct ath_softc *sc, struct sk_buff *skb,
599 struct ieee80211_rx_status *rx_status)
600{
601 struct ieee80211_hdr *hdr;
602
603 hdr = (struct ieee80211_hdr *)skb->data;
604
605 /* Send the frame to mac80211 */
606 if (is_multicast_ether_addr(hdr->addr1)) {
607 int i;
608 /*
609 * Deliver broadcast/multicast frames to all suitable
610 * virtual wiphys.
611 */
612 /* TODO: filter based on channel configuration */
613 for (i = 0; i < sc->num_sec_wiphy; i++) {
614 struct ath_wiphy *aphy = sc->sec_wiphy[i];
615 struct sk_buff *nskb;
616 if (aphy == NULL)
617 continue;
618 nskb = skb_copy(skb, GFP_ATOMIC);
619 if (nskb)
620 __ieee80211_rx(aphy->hw, nskb, rx_status);
621 }
622 __ieee80211_rx(sc->hw, skb, rx_status);
623 } else {
624 /* Deliver unicast frames based on receiver address */
625 __ieee80211_rx(ath_get_virt_hw(sc, hdr), skb, rx_status);
626 }
627}
628
476int ath_rx_tasklet(struct ath_softc *sc, int flush) 629int ath_rx_tasklet(struct ath_softc *sc, int flush)
477{ 630{
478#define PA2DESC(_sc, _pa) \ 631#define PA2DESC(_sc, _pa) \
@@ -622,7 +775,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
622 775
623 if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) { 776 if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) {
624 rx_status.flag |= RX_FLAG_DECRYPTED; 777 rx_status.flag |= RX_FLAG_DECRYPTED;
625 } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) 778 } else if (ieee80211_has_protected(fc)
626 && !decrypt_error && skb->len >= hdrlen + 4) { 779 && !decrypt_error && skb->len >= hdrlen + 4) {
627 keyix = skb->data[hdrlen + 3] >> 6; 780 keyix = skb->data[hdrlen + 3] >> 6;
628 781
@@ -631,36 +784,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
631 } 784 }
632 if (ah->sw_mgmt_crypto && 785 if (ah->sw_mgmt_crypto &&
633 (rx_status.flag & RX_FLAG_DECRYPTED) && 786 (rx_status.flag & RX_FLAG_DECRYPTED) &&
634 ieee80211_is_mgmt(hdr->frame_control)) { 787 ieee80211_is_mgmt(fc)) {
635 /* Use software decrypt for management frames. */ 788 /* Use software decrypt for management frames. */
636 rx_status.flag &= ~RX_FLAG_DECRYPTED; 789 rx_status.flag &= ~RX_FLAG_DECRYPTED;
637 } 790 }
638 791
639 /* Send the frame to mac80211 */
640 if (hdr->addr1[5] & 0x01) {
641 int i;
642 /*
643 * Deliver broadcast/multicast frames to all suitable
644 * virtual wiphys.
645 */
646 /* TODO: filter based on channel configuration */
647 for (i = 0; i < sc->num_sec_wiphy; i++) {
648 struct ath_wiphy *aphy = sc->sec_wiphy[i];
649 struct sk_buff *nskb;
650 if (aphy == NULL)
651 continue;
652 nskb = skb_copy(skb, GFP_ATOMIC);
653 if (nskb)
654 __ieee80211_rx(aphy->hw, nskb,
655 &rx_status);
656 }
657 __ieee80211_rx(sc->hw, skb, &rx_status);
658 } else {
659 /* Deliver unicast frames based on receiver address */
660 __ieee80211_rx(ath_get_virt_hw(sc, hdr), skb,
661 &rx_status);
662 }
663
664 /* We will now give hardware our shiny new allocated skb */ 792 /* We will now give hardware our shiny new allocated skb */
665 bf->bf_mpdu = requeue_skb; 793 bf->bf_mpdu = requeue_skb;
666 bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data, 794 bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
@@ -672,6 +800,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
672 bf->bf_mpdu = NULL; 800 bf->bf_mpdu = NULL;
673 DPRINTF(sc, ATH_DBG_FATAL, 801 DPRINTF(sc, ATH_DBG_FATAL,
674 "dma_mapping_error() on RX\n"); 802 "dma_mapping_error() on RX\n");
803 ath_rx_send_to_mac80211(sc, skb, &rx_status);
675 break; 804 break;
676 } 805 }
677 bf->bf_dmacontext = bf->bf_buf_addr; 806 bf->bf_dmacontext = bf->bf_buf_addr;
@@ -687,11 +816,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
687 sc->rx.rxotherant = 0; 816 sc->rx.rxotherant = 0;
688 } 817 }
689 818
690 if (ieee80211_is_beacon(fc) && 819 if (unlikely(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
691 (sc->sc_flags & SC_OP_WAIT_FOR_BEACON)) { 820 SC_OP_WAIT_FOR_PSPOLL_DATA)))
692 sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; 821 ath_rx_ps(sc, skb);
693 ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); 822
694 } 823 ath_rx_send_to_mac80211(sc, skb, &rx_status);
824
695requeue: 825requeue:
696 list_move_tail(&bf->list, &sc->rx.rxbuf); 826 list_move_tail(&bf->list, &sc->rx.rxbuf);
697 ath_rx_buf_link(sc, bf); 827 ath_rx_buf_link(sc, bf);