aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-rx.c
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2008-06-30 05:23:09 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-06-30 17:37:40 -0400
commit1781a07fbe9cce3dc1697288a5edd260ea7edc02 (patch)
treebe06e824b69af8d43edfeab2c78a353f0bf7f8ce /drivers/net/wireless/iwlwifi/iwl-rx.c
parent37deb2a0baf1bb540b723cc8a3972b42ff2daac6 (diff)
iwlwifi: move RX handlers to iwl-rx.c
This patch moves RX handlers to iwl-rx.c Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-rx.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c853
1 files changed, 853 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index b3ca1375c01a..e0d3e2dd1d82 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -27,6 +27,7 @@
27 * 27 *
28 *****************************************************************************/ 28 *****************************************************************************/
29 29
30#include <linux/etherdevice.h>
30#include <net/mac80211.h> 31#include <net/mac80211.h>
31#include "iwl-eeprom.h" 32#include "iwl-eeprom.h"
32#include "iwl-dev.h" 33#include "iwl-dev.h"
@@ -541,3 +542,855 @@ void iwl_rx_statistics(struct iwl_priv *priv,
541 priv->cfg->ops->lib->temperature(priv, &pkt->u.stats); 542 priv->cfg->ops->lib->temperature(priv, &pkt->u.stats);
542} 543}
543EXPORT_SYMBOL(iwl_rx_statistics); 544EXPORT_SYMBOL(iwl_rx_statistics);
545
546#define PERFECT_RSSI (-20) /* dBm */
547#define WORST_RSSI (-95) /* dBm */
548#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)
549
550/* Calculate an indication of rx signal quality (a percentage, not dBm!).
551 * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
552 * about formulas used below. */
553static int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm)
554{
555 int sig_qual;
556 int degradation = PERFECT_RSSI - rssi_dbm;
557
558 /* If we get a noise measurement, use signal-to-noise ratio (SNR)
559 * as indicator; formula is (signal dbm - noise dbm).
560 * SNR at or above 40 is a great signal (100%).
561 * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
562 * Weakest usable signal is usually 10 - 15 dB SNR. */
563 if (noise_dbm) {
564 if (rssi_dbm - noise_dbm >= 40)
565 return 100;
566 else if (rssi_dbm < noise_dbm)
567 return 0;
568 sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;
569
570 /* Else use just the signal level.
571 * This formula is a least squares fit of data points collected and
572 * compared with a reference system that had a percentage (%) display
573 * for signal quality. */
574 } else
575 sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
576 (15 * RSSI_RANGE + 62 * degradation)) /
577 (RSSI_RANGE * RSSI_RANGE);
578
579 if (sig_qual > 100)
580 sig_qual = 100;
581 else if (sig_qual < 1)
582 sig_qual = 0;
583
584 return sig_qual;
585}
586
587#ifdef CONFIG_IWLWIFI_DEBUG
588
589/**
590 * iwl_dbg_report_frame - dump frame to syslog during debug sessions
591 *
592 * You may hack this function to show different aspects of received frames,
593 * including selective frame dumps.
594 * group100 parameter selects whether to show 1 out of 100 good frames.
595 *
596 * TODO: This was originally written for 3945, need to audit for
597 * proper operation with 4965.
598 */
599static void iwl_dbg_report_frame(struct iwl_priv *priv,
600 struct iwl_rx_packet *pkt,
601 struct ieee80211_hdr *header, int group100)
602{
603 u32 to_us;
604 u32 print_summary = 0;
605 u32 print_dump = 0; /* set to 1 to dump all frames' contents */
606 u32 hundred = 0;
607 u32 dataframe = 0;
608 __le16 fc;
609 u16 seq_ctl;
610 u16 channel;
611 u16 phy_flags;
612 int rate_sym;
613 u16 length;
614 u16 status;
615 u16 bcn_tmr;
616 u32 tsf_low;
617 u64 tsf;
618 u8 rssi;
619 u8 agc;
620 u16 sig_avg;
621 u16 noise_diff;
622 struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
623 struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
624 struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt);
625 u8 *data = IWL_RX_DATA(pkt);
626
627 if (likely(!(priv->debug_level & IWL_DL_RX)))
628 return;
629
630 /* MAC header */
631 fc = header->frame_control;
632 seq_ctl = le16_to_cpu(header->seq_ctrl);
633
634 /* metadata */
635 channel = le16_to_cpu(rx_hdr->channel);
636 phy_flags = le16_to_cpu(rx_hdr->phy_flags);
637 rate_sym = rx_hdr->rate;
638 length = le16_to_cpu(rx_hdr->len);
639
640 /* end-of-frame status and timestamp */
641 status = le32_to_cpu(rx_end->status);
642 bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
643 tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
644 tsf = le64_to_cpu(rx_end->timestamp);
645
646 /* signal statistics */
647 rssi = rx_stats->rssi;
648 agc = rx_stats->agc;
649 sig_avg = le16_to_cpu(rx_stats->sig_avg);
650 noise_diff = le16_to_cpu(rx_stats->noise_diff);
651
652 to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
653
654 /* if data frame is to us and all is good,
655 * (optionally) print summary for only 1 out of every 100 */
656 if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) ==
657 cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
658 dataframe = 1;
659 if (!group100)
660 print_summary = 1; /* print each frame */
661 else if (priv->framecnt_to_us < 100) {
662 priv->framecnt_to_us++;
663 print_summary = 0;
664 } else {
665 priv->framecnt_to_us = 0;
666 print_summary = 1;
667 hundred = 1;
668 }
669 } else {
670 /* print summary for all other frames */
671 print_summary = 1;
672 }
673
674 if (print_summary) {
675 char *title;
676 int rate_idx;
677 u32 bitrate;
678
679 if (hundred)
680 title = "100Frames";
681 else if (ieee80211_has_retry(fc))
682 title = "Retry";
683 else if (ieee80211_is_assoc_resp(fc))
684 title = "AscRsp";
685 else if (ieee80211_is_reassoc_resp(fc))
686 title = "RasRsp";
687 else if (ieee80211_is_probe_resp(fc)) {
688 title = "PrbRsp";
689 print_dump = 1; /* dump frame contents */
690 } else if (ieee80211_is_beacon(fc)) {
691 title = "Beacon";
692 print_dump = 1; /* dump frame contents */
693 } else if (ieee80211_is_atim(fc))
694 title = "ATIM";
695 else if (ieee80211_is_auth(fc))
696 title = "Auth";
697 else if (ieee80211_is_deauth(fc))
698 title = "DeAuth";
699 else if (ieee80211_is_disassoc(fc))
700 title = "DisAssoc";
701 else
702 title = "Frame";
703
704 rate_idx = iwl_hwrate_to_plcp_idx(rate_sym);
705 if (unlikely(rate_idx == -1))
706 bitrate = 0;
707 else
708 bitrate = iwl_rates[rate_idx].ieee / 2;
709
710 /* print frame summary.
711 * MAC addresses show just the last byte (for brevity),
712 * but you can hack it to show more, if you'd like to. */
713 if (dataframe)
714 IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
715 "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
716 title, le16_to_cpu(fc), header->addr1[5],
717 length, rssi, channel, bitrate);
718 else {
719 /* src/dst addresses assume managed mode */
720 IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
721 "src=0x%02x, rssi=%u, tim=%lu usec, "
722 "phy=0x%02x, chnl=%d\n",
723 title, le16_to_cpu(fc), header->addr1[5],
724 header->addr3[5], rssi,
725 tsf_low - priv->scan_start_tsf,
726 phy_flags, channel);
727 }
728 }
729 if (print_dump)
730 iwl_print_hex_dump(priv, IWL_DL_RX, data, length);
731}
732#else
733static inline void iwl_dbg_report_frame(struct iwl_priv *priv,
734 struct iwl_rx_packet *pkt,
735 struct ieee80211_hdr *header,
736 int group100)
737{
738}
739#endif
740
741static void iwl_add_radiotap(struct iwl_priv *priv,
742 struct sk_buff *skb,
743 struct iwl4965_rx_phy_res *rx_start,
744 struct ieee80211_rx_status *stats,
745 u32 ampdu_status)
746{
747 s8 signal = stats->signal;
748 s8 noise = 0;
749 int rate = stats->rate_idx;
750 u64 tsf = stats->mactime;
751 __le16 antenna;
752 __le16 phy_flags_hw = rx_start->phy_flags;
753 struct iwl4965_rt_rx_hdr {
754 struct ieee80211_radiotap_header rt_hdr;
755 __le64 rt_tsf; /* TSF */
756 u8 rt_flags; /* radiotap packet flags */
757 u8 rt_rate; /* rate in 500kb/s */
758 __le16 rt_channelMHz; /* channel in MHz */
759 __le16 rt_chbitmask; /* channel bitfield */
760 s8 rt_dbmsignal; /* signal in dBm, kluged to signed */
761 s8 rt_dbmnoise;
762 u8 rt_antenna; /* antenna number */
763 } __attribute__ ((packed)) *iwl4965_rt;
764
765 /* TODO: We won't have enough headroom for HT frames. Fix it later. */
766 if (skb_headroom(skb) < sizeof(*iwl4965_rt)) {
767 if (net_ratelimit())
768 printk(KERN_ERR "not enough headroom [%d] for "
769 "radiotap head [%zd]\n",
770 skb_headroom(skb), sizeof(*iwl4965_rt));
771 return;
772 }
773
774 /* put radiotap header in front of 802.11 header and data */
775 iwl4965_rt = (void *)skb_push(skb, sizeof(*iwl4965_rt));
776
777 /* initialise radiotap header */
778 iwl4965_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
779 iwl4965_rt->rt_hdr.it_pad = 0;
780
781 /* total header + data */
782 put_unaligned(cpu_to_le16(sizeof(*iwl4965_rt)),
783 &iwl4965_rt->rt_hdr.it_len);
784
785 /* Indicate all the fields we add to the radiotap header */
786 put_unaligned(cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
787 (1 << IEEE80211_RADIOTAP_FLAGS) |
788 (1 << IEEE80211_RADIOTAP_RATE) |
789 (1 << IEEE80211_RADIOTAP_CHANNEL) |
790 (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
791 (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
792 (1 << IEEE80211_RADIOTAP_ANTENNA)),
793 &iwl4965_rt->rt_hdr.it_present);
794
795 /* Zero the flags, we'll add to them as we go */
796 iwl4965_rt->rt_flags = 0;
797
798 put_unaligned(cpu_to_le64(tsf), &iwl4965_rt->rt_tsf);
799
800 iwl4965_rt->rt_dbmsignal = signal;
801 iwl4965_rt->rt_dbmnoise = noise;
802
803 /* Convert the channel frequency and set the flags */
804 put_unaligned(cpu_to_le16(stats->freq), &iwl4965_rt->rt_channelMHz);
805 if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
806 put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM |
807 IEEE80211_CHAN_5GHZ),
808 &iwl4965_rt->rt_chbitmask);
809 else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
810 put_unaligned(cpu_to_le16(IEEE80211_CHAN_CCK |
811 IEEE80211_CHAN_2GHZ),
812 &iwl4965_rt->rt_chbitmask);
813 else /* 802.11g */
814 put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM |
815 IEEE80211_CHAN_2GHZ),
816 &iwl4965_rt->rt_chbitmask);
817
818 if (rate == -1)
819 iwl4965_rt->rt_rate = 0;
820 else
821 iwl4965_rt->rt_rate = iwl_rates[rate].ieee;
822
823 /*
824 * "antenna number"
825 *
826 * It seems that the antenna field in the phy flags value
827 * is actually a bitfield. This is undefined by radiotap,
828 * it wants an actual antenna number but I always get "7"
829 * for most legacy frames I receive indicating that the
830 * same frame was received on all three RX chains.
831 *
832 * I think this field should be removed in favour of a
833 * new 802.11n radiotap field "RX chains" that is defined
834 * as a bitmask.
835 */
836 antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK;
837 iwl4965_rt->rt_antenna = le16_to_cpu(antenna) >> 4;
838
839 /* set the preamble flag if appropriate */
840 if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
841 iwl4965_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
842
843 stats->flag |= RX_FLAG_RADIOTAP;
844}
845
846static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len)
847{
848 /* 0 - mgmt, 1 - cnt, 2 - data */
849 int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
850 priv->rx_stats[idx].cnt++;
851 priv->rx_stats[idx].bytes += len;
852}
853
854/*
855 * returns non-zero if packet should be dropped
856 */
857static int iwl_set_decrypted_flag(struct iwl_priv *priv,
858 struct ieee80211_hdr *hdr,
859 u32 decrypt_res,
860 struct ieee80211_rx_status *stats)
861{
862 u16 fc = le16_to_cpu(hdr->frame_control);
863
864 if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK)
865 return 0;
866
867 if (!(fc & IEEE80211_FCTL_PROTECTED))
868 return 0;
869
870 IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res);
871 switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) {
872 case RX_RES_STATUS_SEC_TYPE_TKIP:
873 /* The uCode has got a bad phase 1 Key, pushes the packet.
874 * Decryption will be done in SW. */
875 if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
876 RX_RES_STATUS_BAD_KEY_TTAK)
877 break;
878
879 case RX_RES_STATUS_SEC_TYPE_WEP:
880 if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
881 RX_RES_STATUS_BAD_ICV_MIC) {
882 /* bad ICV, the packet is destroyed since the
883 * decryption is inplace, drop it */
884 IWL_DEBUG_RX("Packet destroyed\n");
885 return -1;
886 }
887 case RX_RES_STATUS_SEC_TYPE_CCMP:
888 if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
889 RX_RES_STATUS_DECRYPT_OK) {
890 IWL_DEBUG_RX("hw decrypt successfully!!!\n");
891 stats->flag |= RX_FLAG_DECRYPTED;
892 }
893 break;
894
895 default:
896 break;
897 }
898 return 0;
899}
900
901static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
902{
903 u32 decrypt_out = 0;
904
905 if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) ==
906 RX_RES_STATUS_STATION_FOUND)
907 decrypt_out |= (RX_RES_STATUS_STATION_FOUND |
908 RX_RES_STATUS_NO_STATION_INFO_MISMATCH);
909
910 decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK);
911
912 /* packet was not encrypted */
913 if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
914 RX_RES_STATUS_SEC_TYPE_NONE)
915 return decrypt_out;
916
917 /* packet was encrypted with unknown alg */
918 if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
919 RX_RES_STATUS_SEC_TYPE_ERR)
920 return decrypt_out;
921
922 /* decryption was not done in HW */
923 if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) !=
924 RX_MPDU_RES_STATUS_DEC_DONE_MSK)
925 return decrypt_out;
926
927 switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) {
928
929 case RX_RES_STATUS_SEC_TYPE_CCMP:
930 /* alg is CCM: check MIC only */
931 if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK))
932 /* Bad MIC */
933 decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
934 else
935 decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
936
937 break;
938
939 case RX_RES_STATUS_SEC_TYPE_TKIP:
940 if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) {
941 /* Bad TTAK */
942 decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
943 break;
944 }
945 /* fall through if TTAK OK */
946 default:
947 if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
948 decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
949 else
950 decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
951 break;
952 };
953
954 IWL_DEBUG_RX("decrypt_in:0x%x decrypt_out = 0x%x\n",
955 decrypt_in, decrypt_out);
956
957 return decrypt_out;
958}
959
960static void iwl_handle_data_packet(struct iwl_priv *priv, int is_data,
961 int include_phy,
962 struct iwl_rx_mem_buffer *rxb,
963 struct ieee80211_rx_status *stats)
964{
965 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
966 struct iwl4965_rx_phy_res *rx_start = (include_phy) ?
967 (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) : NULL;
968 struct ieee80211_hdr *hdr;
969 u16 len;
970 __le32 *rx_end;
971 unsigned int skblen;
972 u32 ampdu_status;
973 u32 ampdu_status_legacy;
974
975 if (!include_phy && priv->last_phy_res[0])
976 rx_start = (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1];
977
978 if (!rx_start) {
979 IWL_ERROR("MPDU frame without a PHY data\n");
980 return;
981 }
982 if (include_phy) {
983 hdr = (struct ieee80211_hdr *)((u8 *) &rx_start[1] +
984 rx_start->cfg_phy_cnt);
985
986 len = le16_to_cpu(rx_start->byte_count);
987
988 rx_end = (__le32 *) ((u8 *) &pkt->u.raw[0] +
989 sizeof(struct iwl4965_rx_phy_res) +
990 rx_start->cfg_phy_cnt + len);
991
992 } else {
993 struct iwl4965_rx_mpdu_res_start *amsdu =
994 (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw;
995
996 hdr = (struct ieee80211_hdr *)(pkt->u.raw +
997 sizeof(struct iwl4965_rx_mpdu_res_start));
998 len = le16_to_cpu(amsdu->byte_count);
999 rx_start->byte_count = amsdu->byte_count;
1000 rx_end = (__le32 *) (((u8 *) hdr) + len);
1001 }
1002 /* In monitor mode allow 802.11 ACk frames (10 bytes) */
1003 if (len > priv->hw_params.max_pkt_size ||
1004 len < ((priv->iw_mode == IEEE80211_IF_TYPE_MNTR) ? 10 : 16)) {
1005 IWL_WARNING("byte count out of range [16,4K] : %d\n", len);
1006 return;
1007 }
1008
1009 ampdu_status = le32_to_cpu(*rx_end);
1010 skblen = ((u8 *) rx_end - (u8 *) &pkt->u.raw[0]) + sizeof(u32);
1011
1012 if (!include_phy) {
1013 /* New status scheme, need to translate */
1014 ampdu_status_legacy = ampdu_status;
1015 ampdu_status = iwl_translate_rx_status(priv, ampdu_status);
1016 }
1017
1018 /* start from MAC */
1019 skb_reserve(rxb->skb, (void *)hdr - (void *)pkt);
1020 skb_put(rxb->skb, len); /* end where data ends */
1021
1022 /* We only process data packets if the interface is open */
1023 if (unlikely(!priv->is_open)) {
1024 IWL_DEBUG_DROP_LIMIT
1025 ("Dropping packet while interface is not open.\n");
1026 return;
1027 }
1028
1029 stats->flag = 0;
1030 hdr = (struct ieee80211_hdr *)rxb->skb->data;
1031
1032 /* in case of HW accelerated crypto and bad decryption, drop */
1033 if (!priv->hw_params.sw_crypto &&
1034 iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
1035 return;
1036
1037 if (priv->add_radiotap)
1038 iwl_add_radiotap(priv, rxb->skb, rx_start, stats, ampdu_status);
1039
1040 iwl_update_rx_stats(priv, le16_to_cpu(hdr->frame_control), len);
1041 ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
1042 priv->alloc_rxb_skb--;
1043 rxb->skb = NULL;
1044}
1045
1046/* Calc max signal level (dBm) among 3 possible receivers */
1047static int iwl_calc_rssi(struct iwl_priv *priv,
1048 struct iwl4965_rx_phy_res *rx_resp)
1049{
1050 /* data from PHY/DSP regarding signal strength, etc.,
1051 * contents are always there, not configurable by host. */
1052 struct iwl4965_rx_non_cfg_phy *ncphy =
1053 (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy;
1054 u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL_AGC_DB_MASK)
1055 >> IWL_AGC_DB_POS;
1056
1057 u32 valid_antennae =
1058 (le16_to_cpu(rx_resp->phy_flags) & RX_PHY_FLAGS_ANTENNAE_MASK)
1059 >> RX_PHY_FLAGS_ANTENNAE_OFFSET;
1060 u8 max_rssi = 0;
1061 u32 i;
1062
1063 /* Find max rssi among 3 possible receivers.
1064 * These values are measured by the digital signal processor (DSP).
1065 * They should stay fairly constant even as the signal strength varies,
1066 * if the radio's automatic gain control (AGC) is working right.
1067 * AGC value (see below) will provide the "interesting" info. */
1068 for (i = 0; i < 3; i++)
1069 if (valid_antennae & (1 << i))
1070 max_rssi = max(ncphy->rssi_info[i << 1], max_rssi);
1071
1072 IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n",
1073 ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4],
1074 max_rssi, agc);
1075
1076 /* dBm = max_rssi dB - agc dB - constant.
1077 * Higher AGC (higher radio gain) means lower signal. */
1078 return max_rssi - agc - IWL_RSSI_OFFSET;
1079}
1080
1081static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
1082{
1083 unsigned long flags;
1084
1085 spin_lock_irqsave(&priv->sta_lock, flags);
1086 priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
1087 priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
1088 priv->stations[sta_id].sta.sta.modify_mask = 0;
1089 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
1090 spin_unlock_irqrestore(&priv->sta_lock, flags);
1091
1092 iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
1093}
1094
1095static void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr)
1096{
1097 /* FIXME: need locking over ps_status ??? */
1098 u8 sta_id = iwl_find_station(priv, addr);
1099
1100 if (sta_id != IWL_INVALID_STATION) {
1101 u8 sta_awake = priv->stations[sta_id].
1102 ps_status == STA_PS_STATUS_WAKE;
1103
1104 if (sta_awake && ps_bit)
1105 priv->stations[sta_id].ps_status = STA_PS_STATUS_SLEEP;
1106 else if (!sta_awake && !ps_bit) {
1107 iwl_sta_modify_ps_wake(priv, sta_id);
1108 priv->stations[sta_id].ps_status = STA_PS_STATUS_WAKE;
1109 }
1110 }
1111}
1112
1113#define IWL_PACKET_RETRY_TIME HZ
1114
1115static int iwl_is_duplicate_packet(struct iwl_priv *priv,
1116 struct ieee80211_hdr *header)
1117{
1118 u16 sc = le16_to_cpu(header->seq_ctrl);
1119 u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
1120 u16 frag = sc & IEEE80211_SCTL_FRAG;
1121 u16 *last_seq, *last_frag;
1122 unsigned long *last_time;
1123
1124 switch (priv->iw_mode) {
1125 case IEEE80211_IF_TYPE_IBSS:{
1126 struct list_head *p;
1127 struct iwl4965_ibss_seq *entry = NULL;
1128 u8 *mac = header->addr2;
1129 int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1);
1130
1131 __list_for_each(p, &priv->ibss_mac_hash[index]) {
1132 entry = list_entry(p, struct iwl4965_ibss_seq, list);
1133 if (!compare_ether_addr(entry->mac, mac))
1134 break;
1135 }
1136 if (p == &priv->ibss_mac_hash[index]) {
1137 entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
1138 if (!entry) {
1139 IWL_ERROR("Cannot malloc new mac entry\n");
1140 return 0;
1141 }
1142 memcpy(entry->mac, mac, ETH_ALEN);
1143 entry->seq_num = seq;
1144 entry->frag_num = frag;
1145 entry->packet_time = jiffies;
1146 list_add(&entry->list, &priv->ibss_mac_hash[index]);
1147 return 0;
1148 }
1149 last_seq = &entry->seq_num;
1150 last_frag = &entry->frag_num;
1151 last_time = &entry->packet_time;
1152 break;
1153 }
1154 case IEEE80211_IF_TYPE_STA:
1155 last_seq = &priv->last_seq_num;
1156 last_frag = &priv->last_frag_num;
1157 last_time = &priv->last_packet_time;
1158 break;
1159 default:
1160 return 0;
1161 }
1162 if ((*last_seq == seq) &&
1163 time_after(*last_time + IWL_PACKET_RETRY_TIME, jiffies)) {
1164 if (*last_frag == frag)
1165 goto drop;
1166 if (*last_frag + 1 != frag)
1167 /* out-of-order fragment */
1168 goto drop;
1169 } else
1170 *last_seq = seq;
1171
1172 *last_frag = frag;
1173 *last_time = jiffies;
1174 return 0;
1175
1176 drop:
1177 return 1;
1178}
1179
1180static int iwl_is_network_packet(struct iwl_priv *priv,
1181 struct ieee80211_hdr *header)
1182{
1183 /* Filter incoming packets to determine if they are targeted toward
1184 * this network, discarding packets coming from ourselves */
1185 switch (priv->iw_mode) {
1186 case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */
1187 /* packets from our adapter are dropped (echo) */
1188 if (!compare_ether_addr(header->addr2, priv->mac_addr))
1189 return 0;
1190 /* {broad,multi}cast packets to our IBSS go through */
1191 if (is_multicast_ether_addr(header->addr1))
1192 return !compare_ether_addr(header->addr3, priv->bssid);
1193 /* packets to our adapter go through */
1194 return !compare_ether_addr(header->addr1, priv->mac_addr);
1195 case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */
1196 /* packets from our adapter are dropped (echo) */
1197 if (!compare_ether_addr(header->addr3, priv->mac_addr))
1198 return 0;
1199 /* {broad,multi}cast packets to our BSS go through */
1200 if (is_multicast_ether_addr(header->addr1))
1201 return !compare_ether_addr(header->addr2, priv->bssid);
1202 /* packets to our adapter go through */
1203 return !compare_ether_addr(header->addr1, priv->mac_addr);
1204 default:
1205 break;
1206 }
1207
1208 return 1;
1209}
1210
1211/* Called for REPLY_RX (legacy ABG frames), or
1212 * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
1213void iwl_rx_reply_rx(struct iwl_priv *priv,
1214 struct iwl_rx_mem_buffer *rxb)
1215{
1216 struct ieee80211_hdr *header;
1217 struct ieee80211_rx_status rx_status;
1218 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
1219 /* Use phy data (Rx signal strength, etc.) contained within
1220 * this rx packet for legacy frames,
1221 * or phy data cached from REPLY_RX_PHY_CMD for HT frames. */
1222 int include_phy = (pkt->hdr.cmd == REPLY_RX);
1223 struct iwl4965_rx_phy_res *rx_start = (include_phy) ?
1224 (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) :
1225 (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1];
1226 __le32 *rx_end;
1227 unsigned int len = 0;
1228 u16 fc;
1229 u8 network_packet;
1230
1231 rx_status.mactime = le64_to_cpu(rx_start->timestamp);
1232 rx_status.freq =
1233 ieee80211_channel_to_frequency(le16_to_cpu(rx_start->channel));
1234 rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
1235 IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
1236 rx_status.rate_idx =
1237 iwl_hwrate_to_plcp_idx(le32_to_cpu(rx_start->rate_n_flags));
1238 if (rx_status.band == IEEE80211_BAND_5GHZ)
1239 rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
1240
1241 rx_status.antenna = 0;
1242 rx_status.flag = 0;
1243
1244 if ((unlikely(rx_start->cfg_phy_cnt > 20))) {
1245 IWL_DEBUG_DROP("dsp size out of range [0,20]: %d/n",
1246 rx_start->cfg_phy_cnt);
1247 return;
1248 }
1249
1250 if (!include_phy) {
1251 if (priv->last_phy_res[0])
1252 rx_start = (struct iwl4965_rx_phy_res *)
1253 &priv->last_phy_res[1];
1254 else
1255 rx_start = NULL;
1256 }
1257
1258 if (!rx_start) {
1259 IWL_ERROR("MPDU frame without a PHY data\n");
1260 return;
1261 }
1262
1263 if (include_phy) {
1264 header = (struct ieee80211_hdr *)((u8 *) &rx_start[1]
1265 + rx_start->cfg_phy_cnt);
1266
1267 len = le16_to_cpu(rx_start->byte_count);
1268 rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt +
1269 sizeof(struct iwl4965_rx_phy_res) + len);
1270 } else {
1271 struct iwl4965_rx_mpdu_res_start *amsdu =
1272 (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw;
1273
1274 header = (void *)(pkt->u.raw +
1275 sizeof(struct iwl4965_rx_mpdu_res_start));
1276 len = le16_to_cpu(amsdu->byte_count);
1277 rx_end = (__le32 *) (pkt->u.raw +
1278 sizeof(struct iwl4965_rx_mpdu_res_start) + len);
1279 }
1280
1281 if (!(*rx_end & RX_RES_STATUS_NO_CRC32_ERROR) ||
1282 !(*rx_end & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
1283 IWL_DEBUG_RX("Bad CRC or FIFO: 0x%08X.\n",
1284 le32_to_cpu(*rx_end));
1285 return;
1286 }
1287
1288 priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp);
1289
1290 /* Find max signal strength (dBm) among 3 antenna/receiver chains */
1291 rx_status.signal = iwl_calc_rssi(priv, rx_start);
1292
1293 /* Meaningful noise values are available only from beacon statistics,
1294 * which are gathered only when associated, and indicate noise
1295 * only for the associated network channel ...
1296 * Ignore these noise values while scanning (other channels) */
1297 if (iwl_is_associated(priv) &&
1298 !test_bit(STATUS_SCANNING, &priv->status)) {
1299 rx_status.noise = priv->last_rx_noise;
1300 rx_status.qual = iwl_calc_sig_qual(rx_status.signal,
1301 rx_status.noise);
1302 } else {
1303 rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
1304 rx_status.qual = iwl_calc_sig_qual(rx_status.signal, 0);
1305 }
1306
1307 /* Reset beacon noise level if not associated. */
1308 if (!iwl_is_associated(priv))
1309 priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
1310
1311 /* Set "1" to report good data frames in groups of 100 */
1312 /* FIXME: need to optimze the call: */
1313 iwl_dbg_report_frame(priv, pkt, header, 1);
1314
1315 IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n",
1316 rx_status.signal, rx_status.noise, rx_status.signal,
1317 (unsigned long long)rx_status.mactime);
1318
1319
1320 if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
1321 iwl_handle_data_packet(priv, 1, include_phy,
1322 rxb, &rx_status);
1323 return;
1324 }
1325
1326 network_packet = iwl_is_network_packet(priv, header);
1327 if (network_packet) {
1328 priv->last_rx_rssi = rx_status.signal;
1329 priv->last_beacon_time = priv->ucode_beacon_time;
1330 priv->last_tsf = le64_to_cpu(rx_start->timestamp);
1331 }
1332
1333 fc = le16_to_cpu(header->frame_control);
1334 switch (fc & IEEE80211_FCTL_FTYPE) {
1335 case IEEE80211_FTYPE_MGMT:
1336 if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
1337 iwl_update_ps_mode(priv, fc & IEEE80211_FCTL_PM,
1338 header->addr2);
1339 iwl_handle_data_packet(priv, 0, include_phy, rxb, &rx_status);
1340 break;
1341
1342 case IEEE80211_FTYPE_CTL:
1343 switch (fc & IEEE80211_FCTL_STYPE) {
1344 case IEEE80211_STYPE_BACK_REQ:
1345 IWL_DEBUG_HT("IEEE80211_STYPE_BACK_REQ arrived\n");
1346 iwl_handle_data_packet(priv, 0, include_phy,
1347 rxb, &rx_status);
1348 break;
1349 default:
1350 break;
1351 }
1352 break;
1353
1354 case IEEE80211_FTYPE_DATA: {
1355 DECLARE_MAC_BUF(mac1);
1356 DECLARE_MAC_BUF(mac2);
1357 DECLARE_MAC_BUF(mac3);
1358
1359 if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
1360 iwl_update_ps_mode(priv, fc & IEEE80211_FCTL_PM,
1361 header->addr2);
1362
1363 if (unlikely(!network_packet))
1364 IWL_DEBUG_DROP("Dropping (non network): "
1365 "%s, %s, %s\n",
1366 print_mac(mac1, header->addr1),
1367 print_mac(mac2, header->addr2),
1368 print_mac(mac3, header->addr3));
1369 else if (unlikely(iwl_is_duplicate_packet(priv, header)))
1370 IWL_DEBUG_DROP("Dropping (dup): %s, %s, %s\n",
1371 print_mac(mac1, header->addr1),
1372 print_mac(mac2, header->addr2),
1373 print_mac(mac3, header->addr3));
1374 else
1375 iwl_handle_data_packet(priv, 1, include_phy, rxb,
1376 &rx_status);
1377 break;
1378 }
1379 default:
1380 break;
1381
1382 }
1383}
1384EXPORT_SYMBOL(iwl_rx_reply_rx);
1385
1386/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
1387 * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
1388void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
1389 struct iwl_rx_mem_buffer *rxb)
1390{
1391 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
1392 priv->last_phy_res[0] = 1;
1393 memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
1394 sizeof(struct iwl4965_rx_phy_res));
1395}
1396EXPORT_SYMBOL(iwl_rx_reply_rx_phy);