aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
diff options
context:
space:
mode:
authorStanislaw Gruszka <sgruszka@redhat.com>2011-03-04 11:51:49 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-03-04 14:06:50 -0500
commit466a19a003f3b45a755bc85f967c21da947f9a00 (patch)
treeca346e832982a54da9751b411322113c35e2d897 /drivers/net/wireless/iwlwifi/iwl-agn-lib.c
parent9d468d2269b64222a706f52b965998ee64d0b4bf (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.c235
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 */
999static 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
1005static 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
1064static 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). */
1104void 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. */
1224void 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
1233static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, 998static 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,