diff options
author | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2010-03-17 16:34:36 -0400 |
---|---|---|
committer | Reinette Chatre <reinette.chatre@intel.com> | 2010-03-25 14:19:54 -0400 |
commit | 8d801080dd8d28bf7d85cacba131f18b7653ee49 (patch) | |
tree | dbc76a2a17d979695dfdfde95698c4eb72c95cfe /drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |
parent | 54b81550dd674466fe7d01629d2aab015c545a1e (diff) |
iwlwifi: more clean up to move agn only rx functions from iwlcore to iwlagn
Move more functions only used by agn driver from iwlcore to iwlagn.
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-lib.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 436 |
1 files changed, 433 insertions, 3 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 3117382cfd48..226862d3d5ac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -26,7 +26,7 @@ | |||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | 26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
27 | * | 27 | * |
28 | *****************************************************************************/ | 28 | *****************************************************************************/ |
29 | 29 | #include <linux/etherdevice.h> | |
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
@@ -80,7 +80,7 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, | |||
80 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 80 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
81 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | 81 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
82 | info->flags |= iwl_tx_status_to_mac80211(status); | 82 | info->flags |= iwl_tx_status_to_mac80211(status); |
83 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); | 83 | iwlagn_hwrate_to_tx_control(priv, rate_n_flags, info); |
84 | 84 | ||
85 | /* FIXME: code repetition end */ | 85 | /* FIXME: code repetition end */ |
86 | 86 | ||
@@ -225,7 +225,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, | |||
225 | 225 | ||
226 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 226 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
227 | info->flags |= iwl_tx_status_to_mac80211(status); | 227 | info->flags |= iwl_tx_status_to_mac80211(status); |
228 | iwl_hwrate_to_tx_control(priv, | 228 | iwlagn_hwrate_to_tx_control(priv, |
229 | le32_to_cpu(tx_resp->rate_n_flags), | 229 | le32_to_cpu(tx_resp->rate_n_flags), |
230 | info); | 230 | info); |
231 | 231 | ||
@@ -709,3 +709,433 @@ int iwlagn_rxq_stop(struct iwl_priv *priv) | |||
709 | 709 | ||
710 | return 0; | 710 | return 0; |
711 | } | 711 | } |
712 | |||
713 | int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) | ||
714 | { | ||
715 | int idx = 0; | ||
716 | int band_offset = 0; | ||
717 | |||
718 | /* HT rate format: mac80211 wants an MCS number, which is just LSB */ | ||
719 | if (rate_n_flags & RATE_MCS_HT_MSK) { | ||
720 | idx = (rate_n_flags & 0xff); | ||
721 | return idx; | ||
722 | /* Legacy rate format, search for match in table */ | ||
723 | } else { | ||
724 | if (band == IEEE80211_BAND_5GHZ) | ||
725 | band_offset = IWL_FIRST_OFDM_RATE; | ||
726 | for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++) | ||
727 | if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) | ||
728 | return idx - band_offset; | ||
729 | } | ||
730 | |||
731 | return -1; | ||
732 | } | ||
733 | |||
734 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
735 | static inline int iwlagn_calc_rssi(struct iwl_priv *priv, | ||
736 | struct iwl_rx_phy_res *rx_resp) | ||
737 | { | ||
738 | return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); | ||
739 | } | ||
740 | |||
741 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
742 | /** | ||
743 | * iwlagn_dbg_report_frame - dump frame to syslog during debug sessions | ||
744 | * | ||
745 | * You may hack this function to show different aspects of received frames, | ||
746 | * including selective frame dumps. | ||
747 | * group100 parameter selects whether to show 1 out of 100 good data frames. | ||
748 | * All beacon and probe response frames are printed. | ||
749 | */ | ||
750 | static void iwlagn_dbg_report_frame(struct iwl_priv *priv, | ||
751 | struct iwl_rx_phy_res *phy_res, u16 length, | ||
752 | struct ieee80211_hdr *header, int group100) | ||
753 | { | ||
754 | u32 to_us; | ||
755 | u32 print_summary = 0; | ||
756 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
757 | u32 hundred = 0; | ||
758 | u32 dataframe = 0; | ||
759 | __le16 fc; | ||
760 | u16 seq_ctl; | ||
761 | u16 channel; | ||
762 | u16 phy_flags; | ||
763 | u32 rate_n_flags; | ||
764 | u32 tsf_low; | ||
765 | int rssi; | ||
766 | |||
767 | if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX))) | ||
768 | return; | ||
769 | |||
770 | /* MAC header */ | ||
771 | fc = header->frame_control; | ||
772 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
773 | |||
774 | /* metadata */ | ||
775 | channel = le16_to_cpu(phy_res->channel); | ||
776 | phy_flags = le16_to_cpu(phy_res->phy_flags); | ||
777 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
778 | |||
779 | /* signal statistics */ | ||
780 | rssi = iwlagn_calc_rssi(priv, phy_res); | ||
781 | tsf_low = le64_to_cpu(phy_res->timestamp) & 0x0ffffffff; | ||
782 | |||
783 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
784 | |||
785 | /* if data frame is to us and all is good, | ||
786 | * (optionally) print summary for only 1 out of every 100 */ | ||
787 | if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == | ||
788 | cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
789 | dataframe = 1; | ||
790 | if (!group100) | ||
791 | print_summary = 1; /* print each frame */ | ||
792 | else if (priv->framecnt_to_us < 100) { | ||
793 | priv->framecnt_to_us++; | ||
794 | print_summary = 0; | ||
795 | } else { | ||
796 | priv->framecnt_to_us = 0; | ||
797 | print_summary = 1; | ||
798 | hundred = 1; | ||
799 | } | ||
800 | } else { | ||
801 | /* print summary for all other frames */ | ||
802 | print_summary = 1; | ||
803 | } | ||
804 | |||
805 | if (print_summary) { | ||
806 | char *title; | ||
807 | int rate_idx; | ||
808 | u32 bitrate; | ||
809 | |||
810 | if (hundred) | ||
811 | title = "100Frames"; | ||
812 | else if (ieee80211_has_retry(fc)) | ||
813 | title = "Retry"; | ||
814 | else if (ieee80211_is_assoc_resp(fc)) | ||
815 | title = "AscRsp"; | ||
816 | else if (ieee80211_is_reassoc_resp(fc)) | ||
817 | title = "RasRsp"; | ||
818 | else if (ieee80211_is_probe_resp(fc)) { | ||
819 | title = "PrbRsp"; | ||
820 | print_dump = 1; /* dump frame contents */ | ||
821 | } else if (ieee80211_is_beacon(fc)) { | ||
822 | title = "Beacon"; | ||
823 | print_dump = 1; /* dump frame contents */ | ||
824 | } else if (ieee80211_is_atim(fc)) | ||
825 | title = "ATIM"; | ||
826 | else if (ieee80211_is_auth(fc)) | ||
827 | title = "Auth"; | ||
828 | else if (ieee80211_is_deauth(fc)) | ||
829 | title = "DeAuth"; | ||
830 | else if (ieee80211_is_disassoc(fc)) | ||
831 | title = "DisAssoc"; | ||
832 | else | ||
833 | title = "Frame"; | ||
834 | |||
835 | rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); | ||
836 | if (unlikely((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT))) { | ||
837 | bitrate = 0; | ||
838 | WARN_ON_ONCE(1); | ||
839 | } else { | ||
840 | bitrate = iwl_rates[rate_idx].ieee / 2; | ||
841 | } | ||
842 | |||
843 | /* print frame summary. | ||
844 | * MAC addresses show just the last byte (for brevity), | ||
845 | * but you can hack it to show more, if you'd like to. */ | ||
846 | if (dataframe) | ||
847 | IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " | ||
848 | "len=%u, rssi=%d, chnl=%d, rate=%u, \n", | ||
849 | title, le16_to_cpu(fc), header->addr1[5], | ||
850 | length, rssi, channel, bitrate); | ||
851 | else { | ||
852 | /* src/dst addresses assume managed mode */ | ||
853 | IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, src=0x%02x, " | ||
854 | "len=%u, rssi=%d, tim=%lu usec, " | ||
855 | "phy=0x%02x, chnl=%d\n", | ||
856 | title, le16_to_cpu(fc), header->addr1[5], | ||
857 | header->addr3[5], length, rssi, | ||
858 | tsf_low - priv->scan_start_tsf, | ||
859 | phy_flags, channel); | ||
860 | } | ||
861 | } | ||
862 | if (print_dump) | ||
863 | iwl_print_hex_dump(priv, IWL_DL_RX, header, length); | ||
864 | } | ||
865 | #endif | ||
866 | |||
867 | static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | ||
868 | { | ||
869 | u32 decrypt_out = 0; | ||
870 | |||
871 | if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == | ||
872 | RX_RES_STATUS_STATION_FOUND) | ||
873 | decrypt_out |= (RX_RES_STATUS_STATION_FOUND | | ||
874 | RX_RES_STATUS_NO_STATION_INFO_MISMATCH); | ||
875 | |||
876 | decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); | ||
877 | |||
878 | /* packet was not encrypted */ | ||
879 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
880 | RX_RES_STATUS_SEC_TYPE_NONE) | ||
881 | return decrypt_out; | ||
882 | |||
883 | /* packet was encrypted with unknown alg */ | ||
884 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
885 | RX_RES_STATUS_SEC_TYPE_ERR) | ||
886 | return decrypt_out; | ||
887 | |||
888 | /* decryption was not done in HW */ | ||
889 | if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != | ||
890 | RX_MPDU_RES_STATUS_DEC_DONE_MSK) | ||
891 | return decrypt_out; | ||
892 | |||
893 | switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
894 | |||
895 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
896 | /* alg is CCM: check MIC only */ | ||
897 | if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) | ||
898 | /* Bad MIC */ | ||
899 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
900 | else | ||
901 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
902 | |||
903 | break; | ||
904 | |||
905 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
906 | if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { | ||
907 | /* Bad TTAK */ | ||
908 | decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; | ||
909 | break; | ||
910 | } | ||
911 | /* fall through if TTAK OK */ | ||
912 | default: | ||
913 | if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) | ||
914 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
915 | else | ||
916 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
917 | break; | ||
918 | }; | ||
919 | |||
920 | IWL_DEBUG_RX(priv, "decrypt_in:0x%x decrypt_out = 0x%x\n", | ||
921 | decrypt_in, decrypt_out); | ||
922 | |||
923 | return decrypt_out; | ||
924 | } | ||
925 | |||
926 | static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv, | ||
927 | struct ieee80211_hdr *hdr, | ||
928 | u16 len, | ||
929 | u32 ampdu_status, | ||
930 | struct iwl_rx_mem_buffer *rxb, | ||
931 | struct ieee80211_rx_status *stats) | ||
932 | { | ||
933 | struct sk_buff *skb; | ||
934 | int ret = 0; | ||
935 | __le16 fc = hdr->frame_control; | ||
936 | |||
937 | /* We only process data packets if the interface is open */ | ||
938 | if (unlikely(!priv->is_open)) { | ||
939 | IWL_DEBUG_DROP_LIMIT(priv, | ||
940 | "Dropping packet while interface is not open.\n"); | ||
941 | return; | ||
942 | } | ||
943 | |||
944 | /* In case of HW accelerated crypto and bad decryption, drop */ | ||
945 | if (!priv->cfg->mod_params->sw_crypto && | ||
946 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | ||
947 | return; | ||
948 | |||
949 | skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC); | ||
950 | if (!skb) { | ||
951 | IWL_ERR(priv, "alloc_skb failed\n"); | ||
952 | return; | ||
953 | } | ||
954 | |||
955 | skb_reserve(skb, IWL_LINK_HDR_MAX); | ||
956 | skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); | ||
957 | |||
958 | /* mac80211 currently doesn't support paged SKB. Convert it to | ||
959 | * linear SKB for management frame and data frame requires | ||
960 | * software decryption or software defragementation. */ | ||
961 | if (ieee80211_is_mgmt(fc) || | ||
962 | ieee80211_has_protected(fc) || | ||
963 | ieee80211_has_morefrags(fc) || | ||
964 | le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG || | ||
965 | (ieee80211_is_data_qos(fc) && | ||
966 | *ieee80211_get_qos_ctl(hdr) & | ||
967 | IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)) | ||
968 | ret = skb_linearize(skb); | ||
969 | else | ||
970 | ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ? | ||
971 | 0 : -ENOMEM; | ||
972 | |||
973 | if (ret) { | ||
974 | kfree_skb(skb); | ||
975 | goto out; | ||
976 | } | ||
977 | |||
978 | /* | ||
979 | * XXX: We cannot touch the page and its virtual memory (hdr) after | ||
980 | * here. It might have already been freed by the above skb change. | ||
981 | */ | ||
982 | |||
983 | iwl_update_stats(priv, false, fc, len); | ||
984 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | ||
985 | |||
986 | ieee80211_rx(priv->hw, skb); | ||
987 | out: | ||
988 | priv->alloc_rxb_page--; | ||
989 | rxb->page = NULL; | ||
990 | } | ||
991 | |||
992 | /* Called for REPLY_RX (legacy ABG frames), or | ||
993 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ | ||
994 | void iwlagn_rx_reply_rx(struct iwl_priv *priv, | ||
995 | struct iwl_rx_mem_buffer *rxb) | ||
996 | { | ||
997 | struct ieee80211_hdr *header; | ||
998 | struct ieee80211_rx_status rx_status; | ||
999 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1000 | struct iwl_rx_phy_res *phy_res; | ||
1001 | __le32 rx_pkt_status; | ||
1002 | struct iwl4965_rx_mpdu_res_start *amsdu; | ||
1003 | u32 len; | ||
1004 | u32 ampdu_status; | ||
1005 | u32 rate_n_flags; | ||
1006 | |||
1007 | /** | ||
1008 | * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently. | ||
1009 | * REPLY_RX: physical layer info is in this buffer | ||
1010 | * REPLY_RX_MPDU_CMD: physical layer info was sent in separate | ||
1011 | * command and cached in priv->last_phy_res | ||
1012 | * | ||
1013 | * Here we set up local variables depending on which command is | ||
1014 | * received. | ||
1015 | */ | ||
1016 | if (pkt->hdr.cmd == REPLY_RX) { | ||
1017 | phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; | ||
1018 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) | ||
1019 | + phy_res->cfg_phy_cnt); | ||
1020 | |||
1021 | len = le16_to_cpu(phy_res->byte_count); | ||
1022 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) + | ||
1023 | phy_res->cfg_phy_cnt + len); | ||
1024 | ampdu_status = le32_to_cpu(rx_pkt_status); | ||
1025 | } else { | ||
1026 | if (!priv->last_phy_res[0]) { | ||
1027 | IWL_ERR(priv, "MPDU frame without cached PHY data\n"); | ||
1028 | return; | ||
1029 | } | ||
1030 | phy_res = (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; | ||
1031 | amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | ||
1032 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); | ||
1033 | len = le16_to_cpu(amsdu->byte_count); | ||
1034 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); | ||
1035 | ampdu_status = iwlagn_translate_rx_status(priv, | ||
1036 | le32_to_cpu(rx_pkt_status)); | ||
1037 | } | ||
1038 | |||
1039 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { | ||
1040 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", | ||
1041 | phy_res->cfg_phy_cnt); | ||
1042 | return; | ||
1043 | } | ||
1044 | |||
1045 | if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || | ||
1046 | !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | ||
1047 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", | ||
1048 | le32_to_cpu(rx_pkt_status)); | ||
1049 | return; | ||
1050 | } | ||
1051 | |||
1052 | /* This will be used in several places later */ | ||
1053 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
1054 | |||
1055 | /* rx_status carries information about the packet to mac80211 */ | ||
1056 | rx_status.mactime = le64_to_cpu(phy_res->timestamp); | ||
1057 | rx_status.freq = | ||
1058 | ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel)); | ||
1059 | rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
1060 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
1061 | rx_status.rate_idx = | ||
1062 | iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); | ||
1063 | rx_status.flag = 0; | ||
1064 | |||
1065 | /* TSF isn't reliable. In order to allow smooth user experience, | ||
1066 | * this W/A doesn't propagate it to the mac80211 */ | ||
1067 | /*rx_status.flag |= RX_FLAG_TSFT;*/ | ||
1068 | |||
1069 | priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); | ||
1070 | |||
1071 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | ||
1072 | rx_status.signal = iwlagn_calc_rssi(priv, phy_res); | ||
1073 | |||
1074 | /* Meaningful noise values are available only from beacon statistics, | ||
1075 | * which are gathered only when associated, and indicate noise | ||
1076 | * only for the associated network channel ... | ||
1077 | * Ignore these noise values while scanning (other channels) */ | ||
1078 | if (iwl_is_associated(priv) && | ||
1079 | !test_bit(STATUS_SCANNING, &priv->status)) { | ||
1080 | rx_status.noise = priv->last_rx_noise; | ||
1081 | } else { | ||
1082 | rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
1083 | } | ||
1084 | |||
1085 | /* Reset beacon noise level if not associated. */ | ||
1086 | if (!iwl_is_associated(priv)) | ||
1087 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
1088 | |||
1089 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1090 | /* Set "1" to report good data frames in groups of 100 */ | ||
1091 | if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX)) | ||
1092 | iwlagn_dbg_report_frame(priv, phy_res, len, header, 1); | ||
1093 | #endif | ||
1094 | iwl_dbg_log_rx_data_frame(priv, len, header); | ||
1095 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, TSF %llu\n", | ||
1096 | rx_status.signal, rx_status.noise, | ||
1097 | (unsigned long long)rx_status.mactime); | ||
1098 | |||
1099 | /* | ||
1100 | * "antenna number" | ||
1101 | * | ||
1102 | * It seems that the antenna field in the phy flags value | ||
1103 | * is actually a bit field. This is undefined by radiotap, | ||
1104 | * it wants an actual antenna number but I always get "7" | ||
1105 | * for most legacy frames I receive indicating that the | ||
1106 | * same frame was received on all three RX chains. | ||
1107 | * | ||
1108 | * I think this field should be removed in favor of a | ||
1109 | * new 802.11n radiotap field "RX chains" that is defined | ||
1110 | * as a bitmask. | ||
1111 | */ | ||
1112 | rx_status.antenna = | ||
1113 | (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) | ||
1114 | >> RX_RES_PHY_FLAGS_ANTENNA_POS; | ||
1115 | |||
1116 | /* set the preamble flag if appropriate */ | ||
1117 | if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) | ||
1118 | rx_status.flag |= RX_FLAG_SHORTPRE; | ||
1119 | |||
1120 | /* Set up the HT phy flags */ | ||
1121 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
1122 | rx_status.flag |= RX_FLAG_HT; | ||
1123 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
1124 | rx_status.flag |= RX_FLAG_40MHZ; | ||
1125 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
1126 | rx_status.flag |= RX_FLAG_SHORT_GI; | ||
1127 | |||
1128 | iwlagn_pass_packet_to_mac80211(priv, header, len, ampdu_status, | ||
1129 | rxb, &rx_status); | ||
1130 | } | ||
1131 | |||
1132 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). | ||
1133 | * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ | ||
1134 | void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, | ||
1135 | struct iwl_rx_mem_buffer *rxb) | ||
1136 | { | ||
1137 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1138 | priv->last_phy_res[0] = 1; | ||
1139 | memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), | ||
1140 | sizeof(struct iwl_rx_phy_res)); | ||
1141 | } | ||