diff options
author | Stanislaw Gruszka <sgruszka@redhat.com> | 2011-03-04 11:51:49 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-03-04 14:06:50 -0500 |
commit | 466a19a003f3b45a755bc85f967c21da947f9a00 (patch) | |
tree | ca346e832982a54da9751b411322113c35e2d897 /drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |
parent | 9d468d2269b64222a706f52b965998ee64d0b4bf (diff) |
iwlwifi: move rx handlers code to iwl-rx.c
Put generic rx_handlers (except iwlagn_rx_reply_compressed_ba) to
iwl-rx.c . Make functions static and change prefix from iwlagn_ to
iwl_ . Beautify iwl_setup_rx_handlers and do some other minor coding
style changes.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Acked-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-lib.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 235 |
1 files changed, 0 insertions, 235 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 87a9fd8e41eb..25fccf9a3001 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -995,241 +995,6 @@ int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) | |||
995 | return -1; | 995 | return -1; |
996 | } | 996 | } |
997 | 997 | ||
998 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
999 | static inline int iwlagn_calc_rssi(struct iwl_priv *priv, | ||
1000 | struct iwl_rx_phy_res *rx_resp) | ||
1001 | { | ||
1002 | return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); | ||
1003 | } | ||
1004 | |||
1005 | static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | ||
1006 | { | ||
1007 | u32 decrypt_out = 0; | ||
1008 | |||
1009 | if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == | ||
1010 | RX_RES_STATUS_STATION_FOUND) | ||
1011 | decrypt_out |= (RX_RES_STATUS_STATION_FOUND | | ||
1012 | RX_RES_STATUS_NO_STATION_INFO_MISMATCH); | ||
1013 | |||
1014 | decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); | ||
1015 | |||
1016 | /* packet was not encrypted */ | ||
1017 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
1018 | RX_RES_STATUS_SEC_TYPE_NONE) | ||
1019 | return decrypt_out; | ||
1020 | |||
1021 | /* packet was encrypted with unknown alg */ | ||
1022 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
1023 | RX_RES_STATUS_SEC_TYPE_ERR) | ||
1024 | return decrypt_out; | ||
1025 | |||
1026 | /* decryption was not done in HW */ | ||
1027 | if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != | ||
1028 | RX_MPDU_RES_STATUS_DEC_DONE_MSK) | ||
1029 | return decrypt_out; | ||
1030 | |||
1031 | switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
1032 | |||
1033 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
1034 | /* alg is CCM: check MIC only */ | ||
1035 | if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) | ||
1036 | /* Bad MIC */ | ||
1037 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
1038 | else | ||
1039 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
1040 | |||
1041 | break; | ||
1042 | |||
1043 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
1044 | if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { | ||
1045 | /* Bad TTAK */ | ||
1046 | decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; | ||
1047 | break; | ||
1048 | } | ||
1049 | /* fall through if TTAK OK */ | ||
1050 | default: | ||
1051 | if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) | ||
1052 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
1053 | else | ||
1054 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
1055 | break; | ||
1056 | } | ||
1057 | |||
1058 | IWL_DEBUG_RX(priv, "decrypt_in:0x%x decrypt_out = 0x%x\n", | ||
1059 | decrypt_in, decrypt_out); | ||
1060 | |||
1061 | return decrypt_out; | ||
1062 | } | ||
1063 | |||
1064 | static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv, | ||
1065 | struct ieee80211_hdr *hdr, | ||
1066 | u16 len, | ||
1067 | u32 ampdu_status, | ||
1068 | struct iwl_rx_mem_buffer *rxb, | ||
1069 | struct ieee80211_rx_status *stats) | ||
1070 | { | ||
1071 | struct sk_buff *skb; | ||
1072 | __le16 fc = hdr->frame_control; | ||
1073 | |||
1074 | /* We only process data packets if the interface is open */ | ||
1075 | if (unlikely(!priv->is_open)) { | ||
1076 | IWL_DEBUG_DROP_LIMIT(priv, | ||
1077 | "Dropping packet while interface is not open.\n"); | ||
1078 | return; | ||
1079 | } | ||
1080 | |||
1081 | /* In case of HW accelerated crypto and bad decryption, drop */ | ||
1082 | if (!priv->cfg->mod_params->sw_crypto && | ||
1083 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | ||
1084 | return; | ||
1085 | |||
1086 | skb = dev_alloc_skb(128); | ||
1087 | if (!skb) { | ||
1088 | IWL_ERR(priv, "dev_alloc_skb failed\n"); | ||
1089 | return; | ||
1090 | } | ||
1091 | |||
1092 | skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); | ||
1093 | |||
1094 | iwl_update_stats(priv, false, fc, len); | ||
1095 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | ||
1096 | |||
1097 | ieee80211_rx(priv->hw, skb); | ||
1098 | priv->alloc_rxb_page--; | ||
1099 | rxb->page = NULL; | ||
1100 | } | ||
1101 | |||
1102 | /* Called for REPLY_RX (legacy ABG frames), or | ||
1103 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ | ||
1104 | void iwlagn_rx_reply_rx(struct iwl_priv *priv, | ||
1105 | struct iwl_rx_mem_buffer *rxb) | ||
1106 | { | ||
1107 | struct ieee80211_hdr *header; | ||
1108 | struct ieee80211_rx_status rx_status; | ||
1109 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1110 | struct iwl_rx_phy_res *phy_res; | ||
1111 | __le32 rx_pkt_status; | ||
1112 | struct iwl_rx_mpdu_res_start *amsdu; | ||
1113 | u32 len; | ||
1114 | u32 ampdu_status; | ||
1115 | u32 rate_n_flags; | ||
1116 | |||
1117 | /** | ||
1118 | * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently. | ||
1119 | * REPLY_RX: physical layer info is in this buffer | ||
1120 | * REPLY_RX_MPDU_CMD: physical layer info was sent in separate | ||
1121 | * command and cached in priv->last_phy_res | ||
1122 | * | ||
1123 | * Here we set up local variables depending on which command is | ||
1124 | * received. | ||
1125 | */ | ||
1126 | if (pkt->hdr.cmd == REPLY_RX) { | ||
1127 | phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; | ||
1128 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) | ||
1129 | + phy_res->cfg_phy_cnt); | ||
1130 | |||
1131 | len = le16_to_cpu(phy_res->byte_count); | ||
1132 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) + | ||
1133 | phy_res->cfg_phy_cnt + len); | ||
1134 | ampdu_status = le32_to_cpu(rx_pkt_status); | ||
1135 | } else { | ||
1136 | if (!priv->_agn.last_phy_res_valid) { | ||
1137 | IWL_ERR(priv, "MPDU frame without cached PHY data\n"); | ||
1138 | return; | ||
1139 | } | ||
1140 | phy_res = &priv->_agn.last_phy_res; | ||
1141 | amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw; | ||
1142 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); | ||
1143 | len = le16_to_cpu(amsdu->byte_count); | ||
1144 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); | ||
1145 | ampdu_status = iwlagn_translate_rx_status(priv, | ||
1146 | le32_to_cpu(rx_pkt_status)); | ||
1147 | } | ||
1148 | |||
1149 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { | ||
1150 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", | ||
1151 | phy_res->cfg_phy_cnt); | ||
1152 | return; | ||
1153 | } | ||
1154 | |||
1155 | if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || | ||
1156 | !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | ||
1157 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", | ||
1158 | le32_to_cpu(rx_pkt_status)); | ||
1159 | return; | ||
1160 | } | ||
1161 | |||
1162 | /* This will be used in several places later */ | ||
1163 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
1164 | |||
1165 | /* rx_status carries information about the packet to mac80211 */ | ||
1166 | rx_status.mactime = le64_to_cpu(phy_res->timestamp); | ||
1167 | rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
1168 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
1169 | rx_status.freq = | ||
1170 | ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel), | ||
1171 | rx_status.band); | ||
1172 | rx_status.rate_idx = | ||
1173 | iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); | ||
1174 | rx_status.flag = 0; | ||
1175 | |||
1176 | /* TSF isn't reliable. In order to allow smooth user experience, | ||
1177 | * this W/A doesn't propagate it to the mac80211 */ | ||
1178 | /*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/ | ||
1179 | |||
1180 | priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); | ||
1181 | |||
1182 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | ||
1183 | rx_status.signal = iwlagn_calc_rssi(priv, phy_res); | ||
1184 | |||
1185 | iwl_dbg_log_rx_data_frame(priv, len, header); | ||
1186 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n", | ||
1187 | rx_status.signal, (unsigned long long)rx_status.mactime); | ||
1188 | |||
1189 | /* | ||
1190 | * "antenna number" | ||
1191 | * | ||
1192 | * It seems that the antenna field in the phy flags value | ||
1193 | * is actually a bit field. This is undefined by radiotap, | ||
1194 | * it wants an actual antenna number but I always get "7" | ||
1195 | * for most legacy frames I receive indicating that the | ||
1196 | * same frame was received on all three RX chains. | ||
1197 | * | ||
1198 | * I think this field should be removed in favor of a | ||
1199 | * new 802.11n radiotap field "RX chains" that is defined | ||
1200 | * as a bitmask. | ||
1201 | */ | ||
1202 | rx_status.antenna = | ||
1203 | (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) | ||
1204 | >> RX_RES_PHY_FLAGS_ANTENNA_POS; | ||
1205 | |||
1206 | /* set the preamble flag if appropriate */ | ||
1207 | if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) | ||
1208 | rx_status.flag |= RX_FLAG_SHORTPRE; | ||
1209 | |||
1210 | /* Set up the HT phy flags */ | ||
1211 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
1212 | rx_status.flag |= RX_FLAG_HT; | ||
1213 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
1214 | rx_status.flag |= RX_FLAG_40MHZ; | ||
1215 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
1216 | rx_status.flag |= RX_FLAG_SHORT_GI; | ||
1217 | |||
1218 | iwlagn_pass_packet_to_mac80211(priv, header, len, ampdu_status, | ||
1219 | rxb, &rx_status); | ||
1220 | } | ||
1221 | |||
1222 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). | ||
1223 | * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ | ||
1224 | void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, | ||
1225 | struct iwl_rx_mem_buffer *rxb) | ||
1226 | { | ||
1227 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1228 | priv->_agn.last_phy_res_valid = true; | ||
1229 | memcpy(&priv->_agn.last_phy_res, pkt->u.raw, | ||
1230 | sizeof(struct iwl_rx_phy_res)); | ||
1231 | } | ||
1232 | |||
1233 | static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, | 998 | static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, |
1234 | struct ieee80211_vif *vif, | 999 | struct ieee80211_vif *vif, |
1235 | enum ieee80211_band band, | 1000 | enum ieee80211_band band, |