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 | |
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>
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 235 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 176 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.h | 13 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 63 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 18 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rx.c | 523 |
6 files changed, 500 insertions, 528 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, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c96d4ad5def0..6b6f2d88be16 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -424,60 +424,6 @@ int iwl_hw_tx_queue_init(struct iwl_priv *priv, | |||
424 | return 0; | 424 | return 0; |
425 | } | 425 | } |
426 | 426 | ||
427 | /****************************************************************************** | ||
428 | * | ||
429 | * Generic RX handler implementations | ||
430 | * | ||
431 | ******************************************************************************/ | ||
432 | static void iwl_rx_reply_alive(struct iwl_priv *priv, | ||
433 | struct iwl_rx_mem_buffer *rxb) | ||
434 | { | ||
435 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
436 | struct iwl_alive_resp *palive; | ||
437 | struct delayed_work *pwork; | ||
438 | |||
439 | palive = &pkt->u.alive_frame; | ||
440 | |||
441 | IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision " | ||
442 | "0x%01X 0x%01X\n", | ||
443 | palive->is_valid, palive->ver_type, | ||
444 | palive->ver_subtype); | ||
445 | |||
446 | if (palive->ver_subtype == INITIALIZE_SUBTYPE) { | ||
447 | IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); | ||
448 | memcpy(&priv->card_alive_init, | ||
449 | &pkt->u.alive_frame, | ||
450 | sizeof(struct iwl_init_alive_resp)); | ||
451 | pwork = &priv->init_alive_start; | ||
452 | } else { | ||
453 | IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); | ||
454 | memcpy(&priv->card_alive, &pkt->u.alive_frame, | ||
455 | sizeof(struct iwl_alive_resp)); | ||
456 | pwork = &priv->alive_start; | ||
457 | } | ||
458 | |||
459 | /* We delay the ALIVE response by 5ms to | ||
460 | * give the HW RF Kill time to activate... */ | ||
461 | if (palive->is_valid == UCODE_VALID_OK) | ||
462 | queue_delayed_work(priv->workqueue, pwork, | ||
463 | msecs_to_jiffies(5)); | ||
464 | else { | ||
465 | IWL_WARN(priv, "%s uCode did not respond OK.\n", | ||
466 | (palive->ver_subtype == INITIALIZE_SUBTYPE) ? | ||
467 | "init" : "runtime"); | ||
468 | /* | ||
469 | * If fail to load init uCode, | ||
470 | * let's try to load the init uCode again. | ||
471 | * We should not get into this situation, but if it | ||
472 | * does happen, we should not move on and loading "runtime" | ||
473 | * without proper calibrate the device. | ||
474 | */ | ||
475 | if (palive->ver_subtype == INITIALIZE_SUBTYPE) | ||
476 | priv->ucode_type = UCODE_NONE; | ||
477 | queue_work(priv->workqueue, &priv->restart); | ||
478 | } | ||
479 | } | ||
480 | |||
481 | static void iwl_bg_beacon_update(struct work_struct *work) | 427 | static void iwl_bg_beacon_update(struct work_struct *work) |
482 | { | 428 | { |
483 | struct iwl_priv *priv = | 429 | struct iwl_priv *priv = |
@@ -712,83 +658,6 @@ static void iwl_bg_ucode_trace(unsigned long data) | |||
712 | } | 658 | } |
713 | } | 659 | } |
714 | 660 | ||
715 | static void iwlagn_rx_beacon_notif(struct iwl_priv *priv, | ||
716 | struct iwl_rx_mem_buffer *rxb) | ||
717 | { | ||
718 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
719 | struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw; | ||
720 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
721 | u16 status = le16_to_cpu(beacon->beacon_notify_hdr.status.status); | ||
722 | u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); | ||
723 | |||
724 | IWL_DEBUG_RX(priv, "beacon status %#x, retries:%d ibssmgr:%d " | ||
725 | "tsf:0x%.8x%.8x rate:%d\n", | ||
726 | status & TX_STATUS_MSK, | ||
727 | beacon->beacon_notify_hdr.failure_frame, | ||
728 | le32_to_cpu(beacon->ibss_mgr_status), | ||
729 | le32_to_cpu(beacon->high_tsf), | ||
730 | le32_to_cpu(beacon->low_tsf), rate); | ||
731 | #endif | ||
732 | |||
733 | priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); | ||
734 | |||
735 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
736 | queue_work(priv->workqueue, &priv->beacon_update); | ||
737 | } | ||
738 | |||
739 | /* Handle notification from uCode that card's power state is changing | ||
740 | * due to software, hardware, or critical temperature RFKILL */ | ||
741 | static void iwl_rx_card_state_notif(struct iwl_priv *priv, | ||
742 | struct iwl_rx_mem_buffer *rxb) | ||
743 | { | ||
744 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
745 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); | ||
746 | unsigned long status = priv->status; | ||
747 | |||
748 | IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n", | ||
749 | (flags & HW_CARD_DISABLED) ? "Kill" : "On", | ||
750 | (flags & SW_CARD_DISABLED) ? "Kill" : "On", | ||
751 | (flags & CT_CARD_DISABLED) ? | ||
752 | "Reached" : "Not reached"); | ||
753 | |||
754 | if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | | ||
755 | CT_CARD_DISABLED)) { | ||
756 | |||
757 | iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, | ||
758 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | ||
759 | |||
760 | iwl_write_direct32(priv, HBUS_TARG_MBX_C, | ||
761 | HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); | ||
762 | |||
763 | if (!(flags & RXON_CARD_DISABLED)) { | ||
764 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, | ||
765 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | ||
766 | iwl_write_direct32(priv, HBUS_TARG_MBX_C, | ||
767 | HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); | ||
768 | } | ||
769 | if (flags & CT_CARD_DISABLED) | ||
770 | iwl_tt_enter_ct_kill(priv); | ||
771 | } | ||
772 | if (!(flags & CT_CARD_DISABLED)) | ||
773 | iwl_tt_exit_ct_kill(priv); | ||
774 | |||
775 | if (flags & HW_CARD_DISABLED) | ||
776 | set_bit(STATUS_RF_KILL_HW, &priv->status); | ||
777 | else | ||
778 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | ||
779 | |||
780 | |||
781 | if (!(flags & RXON_CARD_DISABLED)) | ||
782 | iwl_scan_cancel(priv); | ||
783 | |||
784 | if ((test_bit(STATUS_RF_KILL_HW, &status) != | ||
785 | test_bit(STATUS_RF_KILL_HW, &priv->status))) | ||
786 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, | ||
787 | test_bit(STATUS_RF_KILL_HW, &priv->status)); | ||
788 | else | ||
789 | wake_up_interruptible(&priv->wait_command_queue); | ||
790 | } | ||
791 | |||
792 | static void iwl_bg_tx_flush(struct work_struct *work) | 661 | static void iwl_bg_tx_flush(struct work_struct *work) |
793 | { | 662 | { |
794 | struct iwl_priv *priv = | 663 | struct iwl_priv *priv = |
@@ -808,51 +677,6 @@ static void iwl_bg_tx_flush(struct work_struct *work) | |||
808 | } | 677 | } |
809 | 678 | ||
810 | /** | 679 | /** |
811 | * iwl_setup_rx_handlers - Initialize Rx handler callbacks | ||
812 | * | ||
813 | * Setup the RX handlers for each of the reply types sent from the uCode | ||
814 | * to the host. | ||
815 | * | ||
816 | * This function chains into the hardware specific files for them to setup | ||
817 | * any hardware specific handlers as well. | ||
818 | */ | ||
819 | static void iwl_setup_rx_handlers(struct iwl_priv *priv) | ||
820 | { | ||
821 | priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive; | ||
822 | priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; | ||
823 | priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; | ||
824 | priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] = | ||
825 | iwl_rx_spectrum_measure_notif; | ||
826 | priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; | ||
827 | priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = | ||
828 | iwl_rx_pm_debug_statistics_notif; | ||
829 | priv->rx_handlers[BEACON_NOTIFICATION] = iwlagn_rx_beacon_notif; | ||
830 | |||
831 | /* | ||
832 | * The same handler is used for both the REPLY to a discrete | ||
833 | * statistics request from the host as well as for the periodic | ||
834 | * statistics notifications (after received beacons) from the uCode. | ||
835 | */ | ||
836 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_reply_statistics; | ||
837 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; | ||
838 | |||
839 | iwl_setup_rx_scan_handlers(priv); | ||
840 | |||
841 | /* status change handler */ | ||
842 | priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl_rx_card_state_notif; | ||
843 | |||
844 | priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] = | ||
845 | iwl_rx_missed_beacon_notif; | ||
846 | /* Rx handlers */ | ||
847 | priv->rx_handlers[REPLY_RX_PHY_CMD] = iwlagn_rx_reply_rx_phy; | ||
848 | priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwlagn_rx_reply_rx; | ||
849 | /* block ack */ | ||
850 | priv->rx_handlers[REPLY_COMPRESSED_BA] = iwlagn_rx_reply_compressed_ba; | ||
851 | /* Set up hardware specific Rx handlers */ | ||
852 | priv->cfg->ops->lib->rx_handler_setup(priv); | ||
853 | } | ||
854 | |||
855 | /** | ||
856 | * iwl_rx_handle - Main entry function for receiving responses from uCode | 680 | * iwl_rx_handle - Main entry function for receiving responses from uCode |
857 | * | 681 | * |
858 | * Uses the priv->rx_handlers callback function array to invoke | 682 | * Uses the priv->rx_handlers callback function array to invoke |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index b5a169be48e2..20f8e4188994 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -190,10 +190,7 @@ void iwlagn_rx_replenish_now(struct iwl_priv *priv); | |||
190 | void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 190 | void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
191 | int iwlagn_rxq_stop(struct iwl_priv *priv); | 191 | int iwlagn_rxq_stop(struct iwl_priv *priv); |
192 | int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); | 192 | int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); |
193 | void iwlagn_rx_reply_rx(struct iwl_priv *priv, | 193 | void iwl_setup_rx_handlers(struct iwl_priv *priv); |
194 | struct iwl_rx_mem_buffer *rxb); | ||
195 | void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, | ||
196 | struct iwl_rx_mem_buffer *rxb); | ||
197 | 194 | ||
198 | /* tx */ | 195 | /* tx */ |
199 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 196 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
@@ -243,14 +240,6 @@ static inline bool iwl_is_tx_success(u32 status) | |||
243 | 240 | ||
244 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid); | 241 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid); |
245 | 242 | ||
246 | /* rx */ | ||
247 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | ||
248 | struct iwl_rx_mem_buffer *rxb); | ||
249 | void iwl_rx_statistics(struct iwl_priv *priv, | ||
250 | struct iwl_rx_mem_buffer *rxb); | ||
251 | void iwl_reply_statistics(struct iwl_priv *priv, | ||
252 | struct iwl_rx_mem_buffer *rxb); | ||
253 | |||
254 | /* scan */ | 243 | /* scan */ |
255 | int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); | 244 | int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); |
256 | void iwlagn_post_scan(struct iwl_priv *priv); | 245 | void iwlagn_post_scan(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 4bd342060254..6c30fa652e27 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -869,33 +869,6 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) | |||
869 | } | 869 | } |
870 | } | 870 | } |
871 | 871 | ||
872 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | ||
873 | { | ||
874 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
875 | struct iwl_csa_notification *csa = &(pkt->u.csa_notif); | ||
876 | /* | ||
877 | * MULTI-FIXME | ||
878 | * See iwl_mac_channel_switch. | ||
879 | */ | ||
880 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
881 | struct iwl_rxon_cmd *rxon = (void *)&ctx->active; | ||
882 | |||
883 | if (priv->switch_rxon.switch_in_progress) { | ||
884 | if (!le32_to_cpu(csa->status) && | ||
885 | (csa->channel == priv->switch_rxon.channel)) { | ||
886 | rxon->channel = csa->channel; | ||
887 | ctx->staging.channel = csa->channel; | ||
888 | IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", | ||
889 | le16_to_cpu(csa->channel)); | ||
890 | iwl_chswitch_done(priv, true); | ||
891 | } else { | ||
892 | IWL_ERR(priv, "CSA notif (fail) : channel %d\n", | ||
893 | le16_to_cpu(csa->channel)); | ||
894 | iwl_chswitch_done(priv, false); | ||
895 | } | ||
896 | } | ||
897 | } | ||
898 | |||
899 | #ifdef CONFIG_IWLWIFI_DEBUG | 872 | #ifdef CONFIG_IWLWIFI_DEBUG |
900 | void iwl_print_rx_config_cmd(struct iwl_priv *priv, | 873 | void iwl_print_rx_config_cmd(struct iwl_priv *priv, |
901 | struct iwl_rxon_context *ctx) | 874 | struct iwl_rxon_context *ctx) |
@@ -1245,42 +1218,6 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) | |||
1245 | &statistics_cmd); | 1218 | &statistics_cmd); |
1246 | } | 1219 | } |
1247 | 1220 | ||
1248 | void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, | ||
1249 | struct iwl_rx_mem_buffer *rxb) | ||
1250 | { | ||
1251 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1252 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1253 | struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif); | ||
1254 | IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n", | ||
1255 | sleep->pm_sleep_mode, sleep->pm_wakeup_src); | ||
1256 | #endif | ||
1257 | } | ||
1258 | |||
1259 | void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, | ||
1260 | struct iwl_rx_mem_buffer *rxb) | ||
1261 | { | ||
1262 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1263 | u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
1264 | IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " | ||
1265 | "notification for %s:\n", len, | ||
1266 | get_cmd_string(pkt->hdr.cmd)); | ||
1267 | iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len); | ||
1268 | } | ||
1269 | |||
1270 | void iwl_rx_reply_error(struct iwl_priv *priv, | ||
1271 | struct iwl_rx_mem_buffer *rxb) | ||
1272 | { | ||
1273 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1274 | |||
1275 | IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) " | ||
1276 | "seq 0x%04X ser 0x%08X\n", | ||
1277 | le32_to_cpu(pkt->u.err_resp.error_type), | ||
1278 | get_cmd_string(pkt->u.err_resp.cmd_id), | ||
1279 | pkt->u.err_resp.cmd_id, | ||
1280 | le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num), | ||
1281 | le32_to_cpu(pkt->u.err_resp.error_info)); | ||
1282 | } | ||
1283 | |||
1284 | void iwl_clear_isr_stats(struct iwl_priv *priv) | 1221 | void iwl_clear_isr_stats(struct iwl_priv *priv) |
1285 | { | 1222 | { |
1286 | memset(&priv->isr_stats, 0, sizeof(priv->isr_stats)); | 1223 | memset(&priv->isr_stats, 0, sizeof(priv->isr_stats)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index d47f3a87fce4..af47750f8985 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -441,10 +441,6 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | |||
441 | void iwl_connection_init_rx_config(struct iwl_priv *priv, | 441 | void iwl_connection_init_rx_config(struct iwl_priv *priv, |
442 | struct iwl_rxon_context *ctx); | 442 | struct iwl_rxon_context *ctx); |
443 | void iwl_set_rate(struct iwl_priv *priv); | 443 | void iwl_set_rate(struct iwl_priv *priv); |
444 | int iwl_set_decrypted_flag(struct iwl_priv *priv, | ||
445 | struct ieee80211_hdr *hdr, | ||
446 | u32 decrypt_res, | ||
447 | struct ieee80211_rx_status *stats); | ||
448 | void iwl_irq_handle_error(struct iwl_priv *priv); | 444 | void iwl_irq_handle_error(struct iwl_priv *priv); |
449 | int iwl_mac_add_interface(struct ieee80211_hw *hw, | 445 | int iwl_mac_add_interface(struct ieee80211_hw *hw, |
450 | struct ieee80211_vif *vif); | 446 | struct ieee80211_vif *vif); |
@@ -493,15 +489,6 @@ static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx, | |||
493 | { | 489 | { |
494 | } | 490 | } |
495 | #endif | 491 | #endif |
496 | /***************************************************** | ||
497 | * RX handlers. | ||
498 | * **************************************************/ | ||
499 | void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, | ||
500 | struct iwl_rx_mem_buffer *rxb); | ||
501 | void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, | ||
502 | struct iwl_rx_mem_buffer *rxb); | ||
503 | void iwl_rx_reply_error(struct iwl_priv *priv, | ||
504 | struct iwl_rx_mem_buffer *rxb); | ||
505 | 492 | ||
506 | /***************************************************** | 493 | /***************************************************** |
507 | * RX | 494 | * RX |
@@ -513,11 +500,8 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, | |||
513 | struct iwl_rx_queue *q); | 500 | struct iwl_rx_queue *q); |
514 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); | 501 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); |
515 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | 502 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); |
516 | /* Handlers */ | 503 | |
517 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | ||
518 | struct iwl_rx_mem_buffer *rxb); | ||
519 | void iwl_chswitch_done(struct iwl_priv *priv, bool is_success); | 504 | void iwl_chswitch_done(struct iwl_priv *priv, bool is_success); |
520 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | ||
521 | 505 | ||
522 | /* TX helpers */ | 506 | /* TX helpers */ |
523 | 507 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 566e2d979ce3..8dc129499b90 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -38,7 +38,14 @@ | |||
38 | #include "iwl-io.h" | 38 | #include "iwl-io.h" |
39 | #include "iwl-helpers.h" | 39 | #include "iwl-helpers.h" |
40 | #include "iwl-agn-calib.h" | 40 | #include "iwl-agn-calib.h" |
41 | /************************** RX-FUNCTIONS ****************************/ | 41 | #include "iwl-agn.h" |
42 | |||
43 | /****************************************************************************** | ||
44 | * | ||
45 | * RX path functions | ||
46 | * | ||
47 | ******************************************************************************/ | ||
48 | |||
42 | /* | 49 | /* |
43 | * Rx theory of operation | 50 | * Rx theory of operation |
44 | * | 51 | * |
@@ -211,7 +218,104 @@ err_bd: | |||
211 | return -ENOMEM; | 218 | return -ENOMEM; |
212 | } | 219 | } |
213 | 220 | ||
214 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | 221 | /****************************************************************************** |
222 | * | ||
223 | * Generic RX handler implementations | ||
224 | * | ||
225 | ******************************************************************************/ | ||
226 | |||
227 | static void iwl_rx_reply_alive(struct iwl_priv *priv, | ||
228 | struct iwl_rx_mem_buffer *rxb) | ||
229 | { | ||
230 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
231 | struct iwl_alive_resp *palive; | ||
232 | struct delayed_work *pwork; | ||
233 | |||
234 | palive = &pkt->u.alive_frame; | ||
235 | |||
236 | IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision " | ||
237 | "0x%01X 0x%01X\n", | ||
238 | palive->is_valid, palive->ver_type, | ||
239 | palive->ver_subtype); | ||
240 | |||
241 | if (palive->ver_subtype == INITIALIZE_SUBTYPE) { | ||
242 | IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); | ||
243 | memcpy(&priv->card_alive_init, | ||
244 | &pkt->u.alive_frame, | ||
245 | sizeof(struct iwl_init_alive_resp)); | ||
246 | pwork = &priv->init_alive_start; | ||
247 | } else { | ||
248 | IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); | ||
249 | memcpy(&priv->card_alive, &pkt->u.alive_frame, | ||
250 | sizeof(struct iwl_alive_resp)); | ||
251 | pwork = &priv->alive_start; | ||
252 | } | ||
253 | |||
254 | /* We delay the ALIVE response by 5ms to | ||
255 | * give the HW RF Kill time to activate... */ | ||
256 | if (palive->is_valid == UCODE_VALID_OK) | ||
257 | queue_delayed_work(priv->workqueue, pwork, | ||
258 | msecs_to_jiffies(5)); | ||
259 | else { | ||
260 | IWL_WARN(priv, "%s uCode did not respond OK.\n", | ||
261 | (palive->ver_subtype == INITIALIZE_SUBTYPE) ? | ||
262 | "init" : "runtime"); | ||
263 | /* | ||
264 | * If fail to load init uCode, | ||
265 | * let's try to load the init uCode again. | ||
266 | * We should not get into this situation, but if it | ||
267 | * does happen, we should not move on and loading "runtime" | ||
268 | * without proper calibrate the device. | ||
269 | */ | ||
270 | if (palive->ver_subtype == INITIALIZE_SUBTYPE) | ||
271 | priv->ucode_type = UCODE_NONE; | ||
272 | queue_work(priv->workqueue, &priv->restart); | ||
273 | } | ||
274 | } | ||
275 | |||
276 | static void iwl_rx_reply_error(struct iwl_priv *priv, | ||
277 | struct iwl_rx_mem_buffer *rxb) | ||
278 | { | ||
279 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
280 | |||
281 | IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) " | ||
282 | "seq 0x%04X ser 0x%08X\n", | ||
283 | le32_to_cpu(pkt->u.err_resp.error_type), | ||
284 | get_cmd_string(pkt->u.err_resp.cmd_id), | ||
285 | pkt->u.err_resp.cmd_id, | ||
286 | le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num), | ||
287 | le32_to_cpu(pkt->u.err_resp.error_info)); | ||
288 | } | ||
289 | |||
290 | static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | ||
291 | { | ||
292 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
293 | struct iwl_csa_notification *csa = &(pkt->u.csa_notif); | ||
294 | /* | ||
295 | * MULTI-FIXME | ||
296 | * See iwl_mac_channel_switch. | ||
297 | */ | ||
298 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
299 | struct iwl_rxon_cmd *rxon = (void *)&ctx->active; | ||
300 | |||
301 | if (priv->switch_rxon.switch_in_progress) { | ||
302 | if (!le32_to_cpu(csa->status) && | ||
303 | (csa->channel == priv->switch_rxon.channel)) { | ||
304 | rxon->channel = csa->channel; | ||
305 | ctx->staging.channel = csa->channel; | ||
306 | IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", | ||
307 | le16_to_cpu(csa->channel)); | ||
308 | iwl_chswitch_done(priv, true); | ||
309 | } else { | ||
310 | IWL_ERR(priv, "CSA notif (fail) : channel %d\n", | ||
311 | le16_to_cpu(csa->channel)); | ||
312 | iwl_chswitch_done(priv, false); | ||
313 | } | ||
314 | } | ||
315 | } | ||
316 | |||
317 | |||
318 | static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | ||
215 | struct iwl_rx_mem_buffer *rxb) | 319 | struct iwl_rx_mem_buffer *rxb) |
216 | { | 320 | { |
217 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 321 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
@@ -227,6 +331,52 @@ void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | |||
227 | priv->measurement_status |= MEASUREMENT_READY; | 331 | priv->measurement_status |= MEASUREMENT_READY; |
228 | } | 332 | } |
229 | 333 | ||
334 | static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, | ||
335 | struct iwl_rx_mem_buffer *rxb) | ||
336 | { | ||
337 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
338 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
339 | struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif); | ||
340 | IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n", | ||
341 | sleep->pm_sleep_mode, sleep->pm_wakeup_src); | ||
342 | #endif | ||
343 | } | ||
344 | |||
345 | static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, | ||
346 | struct iwl_rx_mem_buffer *rxb) | ||
347 | { | ||
348 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
349 | u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
350 | IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " | ||
351 | "notification for %s:\n", len, | ||
352 | get_cmd_string(pkt->hdr.cmd)); | ||
353 | iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len); | ||
354 | } | ||
355 | |||
356 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, | ||
357 | struct iwl_rx_mem_buffer *rxb) | ||
358 | { | ||
359 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
360 | struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw; | ||
361 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
362 | u16 status = le16_to_cpu(beacon->beacon_notify_hdr.status.status); | ||
363 | u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); | ||
364 | |||
365 | IWL_DEBUG_RX(priv, "beacon status %#x, retries:%d ibssmgr:%d " | ||
366 | "tsf:0x%.8x%.8x rate:%d\n", | ||
367 | status & TX_STATUS_MSK, | ||
368 | beacon->beacon_notify_hdr.failure_frame, | ||
369 | le32_to_cpu(beacon->ibss_mgr_status), | ||
370 | le32_to_cpu(beacon->high_tsf), | ||
371 | le32_to_cpu(beacon->low_tsf), rate); | ||
372 | #endif | ||
373 | |||
374 | priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); | ||
375 | |||
376 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
377 | queue_work(priv->workqueue, &priv->beacon_update); | ||
378 | } | ||
379 | |||
230 | /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ | 380 | /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ |
231 | #define ACK_CNT_RATIO (50) | 381 | #define ACK_CNT_RATIO (50) |
232 | #define BA_TIMEOUT_CNT (5) | 382 | #define BA_TIMEOUT_CNT (5) |
@@ -298,7 +448,8 @@ static bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt | |||
298 | * When the plcp error is exceeding the thresholds, reset the radio | 448 | * When the plcp error is exceeding the thresholds, reset the radio |
299 | * to improve the throughput. | 449 | * to improve the throughput. |
300 | */ | 450 | */ |
301 | static bool iwl_good_plcp_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt) | 451 | static bool iwl_good_plcp_health(struct iwl_priv *priv, |
452 | struct iwl_rx_packet *pkt) | ||
302 | { | 453 | { |
303 | bool rc = true; | 454 | bool rc = true; |
304 | int combined_plcp_delta; | 455 | int combined_plcp_delta; |
@@ -378,7 +529,8 @@ static bool iwl_good_plcp_health(struct iwl_priv *priv, struct iwl_rx_packet *pk | |||
378 | return rc; | 529 | return rc; |
379 | } | 530 | } |
380 | 531 | ||
381 | static void iwl_recover_from_statistics(struct iwl_priv *priv, struct iwl_rx_packet *pkt) | 532 | static void iwl_recover_from_statistics(struct iwl_priv *priv, |
533 | struct iwl_rx_packet *pkt) | ||
382 | { | 534 | { |
383 | const struct iwl_mod_params *mod_params = priv->cfg->mod_params; | 535 | const struct iwl_mod_params *mod_params = priv->cfg->mod_params; |
384 | 536 | ||
@@ -442,7 +594,6 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) | |||
442 | last_rx_noise); | 594 | last_rx_noise); |
443 | } | 595 | } |
444 | 596 | ||
445 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
446 | /* | 597 | /* |
447 | * based on the assumption of all statistics counter are in DWORD | 598 | * based on the assumption of all statistics counter are in DWORD |
448 | * FIXME: This function is for debugging, do not deal with | 599 | * FIXME: This function is for debugging, do not deal with |
@@ -451,6 +602,7 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) | |||
451 | static void iwl_accumulative_statistics(struct iwl_priv *priv, | 602 | static void iwl_accumulative_statistics(struct iwl_priv *priv, |
452 | __le32 *stats) | 603 | __le32 *stats) |
453 | { | 604 | { |
605 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
454 | int i, size; | 606 | int i, size; |
455 | __le32 *prev_stats; | 607 | __le32 *prev_stats; |
456 | u32 *accum_stats; | 608 | u32 *accum_stats; |
@@ -498,14 +650,13 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, | |||
498 | accum_tx->tx_power.ant_a = tx->tx_power.ant_a; | 650 | accum_tx->tx_power.ant_a = tx->tx_power.ant_a; |
499 | accum_tx->tx_power.ant_b = tx->tx_power.ant_b; | 651 | accum_tx->tx_power.ant_b = tx->tx_power.ant_b; |
500 | accum_tx->tx_power.ant_c = tx->tx_power.ant_c; | 652 | accum_tx->tx_power.ant_c = tx->tx_power.ant_c; |
501 | } | ||
502 | #endif | 653 | #endif |
654 | } | ||
503 | 655 | ||
504 | #define REG_RECALIB_PERIOD (60) | 656 | static void iwl_rx_statistics(struct iwl_priv *priv, |
505 | |||
506 | void iwl_rx_statistics(struct iwl_priv *priv, | ||
507 | struct iwl_rx_mem_buffer *rxb) | 657 | struct iwl_rx_mem_buffer *rxb) |
508 | { | 658 | { |
659 | const int reg_recalib_period = 60; | ||
509 | int change; | 660 | int change; |
510 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 661 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
511 | 662 | ||
@@ -522,10 +673,8 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
522 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != | 673 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != |
523 | (pkt->u.stats_bt.flag & | 674 | (pkt->u.stats_bt.flag & |
524 | STATISTICS_REPLY_FLG_HT40_MODE_MSK))); | 675 | STATISTICS_REPLY_FLG_HT40_MODE_MSK))); |
525 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
526 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats_bt); | ||
527 | #endif | ||
528 | 676 | ||
677 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats_bt); | ||
529 | } else { | 678 | } else { |
530 | IWL_DEBUG_RX(priv, | 679 | IWL_DEBUG_RX(priv, |
531 | "Statistics notification received (%d vs %d).\n", | 680 | "Statistics notification received (%d vs %d).\n", |
@@ -539,10 +688,8 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
539 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != | 688 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != |
540 | (pkt->u.stats.flag & | 689 | (pkt->u.stats.flag & |
541 | STATISTICS_REPLY_FLG_HT40_MODE_MSK))); | 690 | STATISTICS_REPLY_FLG_HT40_MODE_MSK))); |
542 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
543 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); | ||
544 | #endif | ||
545 | 691 | ||
692 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); | ||
546 | } | 693 | } |
547 | 694 | ||
548 | iwl_recover_from_statistics(priv, pkt); | 695 | iwl_recover_from_statistics(priv, pkt); |
@@ -557,11 +704,11 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
557 | set_bit(STATUS_STATISTICS, &priv->status); | 704 | set_bit(STATUS_STATISTICS, &priv->status); |
558 | 705 | ||
559 | /* Reschedule the statistics timer to occur in | 706 | /* Reschedule the statistics timer to occur in |
560 | * REG_RECALIB_PERIOD seconds to ensure we get a | 707 | * reg_recalib_period seconds to ensure we get a |
561 | * thermal update even if the uCode doesn't give | 708 | * thermal update even if the uCode doesn't give |
562 | * us one */ | 709 | * us one */ |
563 | mod_timer(&priv->statistics_periodic, jiffies + | 710 | mod_timer(&priv->statistics_periodic, jiffies + |
564 | msecs_to_jiffies(REG_RECALIB_PERIOD * 1000)); | 711 | msecs_to_jiffies(reg_recalib_period * 1000)); |
565 | 712 | ||
566 | if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && | 713 | if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && |
567 | (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { | 714 | (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { |
@@ -572,8 +719,8 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
572 | priv->cfg->ops->lib->temp_ops.temperature(priv); | 719 | priv->cfg->ops->lib->temp_ops.temperature(priv); |
573 | } | 720 | } |
574 | 721 | ||
575 | void iwl_reply_statistics(struct iwl_priv *priv, | 722 | static void iwl_rx_reply_statistics(struct iwl_priv *priv, |
576 | struct iwl_rx_mem_buffer *rxb) | 723 | struct iwl_rx_mem_buffer *rxb) |
577 | { | 724 | { |
578 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 725 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
579 | 726 | ||
@@ -597,8 +744,61 @@ void iwl_reply_statistics(struct iwl_priv *priv, | |||
597 | iwl_rx_statistics(priv, rxb); | 744 | iwl_rx_statistics(priv, rxb); |
598 | } | 745 | } |
599 | 746 | ||
600 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | 747 | /* Handle notification from uCode that card's power state is changing |
601 | struct iwl_rx_mem_buffer *rxb) | 748 | * due to software, hardware, or critical temperature RFKILL */ |
749 | static void iwl_rx_card_state_notif(struct iwl_priv *priv, | ||
750 | struct iwl_rx_mem_buffer *rxb) | ||
751 | { | ||
752 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
753 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); | ||
754 | unsigned long status = priv->status; | ||
755 | |||
756 | IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n", | ||
757 | (flags & HW_CARD_DISABLED) ? "Kill" : "On", | ||
758 | (flags & SW_CARD_DISABLED) ? "Kill" : "On", | ||
759 | (flags & CT_CARD_DISABLED) ? | ||
760 | "Reached" : "Not reached"); | ||
761 | |||
762 | if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | | ||
763 | CT_CARD_DISABLED)) { | ||
764 | |||
765 | iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, | ||
766 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | ||
767 | |||
768 | iwl_write_direct32(priv, HBUS_TARG_MBX_C, | ||
769 | HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); | ||
770 | |||
771 | if (!(flags & RXON_CARD_DISABLED)) { | ||
772 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, | ||
773 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | ||
774 | iwl_write_direct32(priv, HBUS_TARG_MBX_C, | ||
775 | HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); | ||
776 | } | ||
777 | if (flags & CT_CARD_DISABLED) | ||
778 | iwl_tt_enter_ct_kill(priv); | ||
779 | } | ||
780 | if (!(flags & CT_CARD_DISABLED)) | ||
781 | iwl_tt_exit_ct_kill(priv); | ||
782 | |||
783 | if (flags & HW_CARD_DISABLED) | ||
784 | set_bit(STATUS_RF_KILL_HW, &priv->status); | ||
785 | else | ||
786 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | ||
787 | |||
788 | |||
789 | if (!(flags & RXON_CARD_DISABLED)) | ||
790 | iwl_scan_cancel(priv); | ||
791 | |||
792 | if ((test_bit(STATUS_RF_KILL_HW, &status) != | ||
793 | test_bit(STATUS_RF_KILL_HW, &priv->status))) | ||
794 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, | ||
795 | test_bit(STATUS_RF_KILL_HW, &priv->status)); | ||
796 | else | ||
797 | wake_up_interruptible(&priv->wait_command_queue); | ||
798 | } | ||
799 | |||
800 | static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | ||
801 | struct iwl_rx_mem_buffer *rxb) | ||
602 | 802 | ||
603 | { | 803 | { |
604 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 804 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
@@ -618,13 +818,25 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | |||
618 | } | 818 | } |
619 | } | 819 | } |
620 | 820 | ||
821 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). | ||
822 | * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ | ||
823 | static void iwl_rx_reply_rx_phy(struct iwl_priv *priv, | ||
824 | struct iwl_rx_mem_buffer *rxb) | ||
825 | { | ||
826 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
827 | |||
828 | priv->_agn.last_phy_res_valid = true; | ||
829 | memcpy(&priv->_agn.last_phy_res, pkt->u.raw, | ||
830 | sizeof(struct iwl_rx_phy_res)); | ||
831 | } | ||
832 | |||
621 | /* | 833 | /* |
622 | * returns non-zero if packet should be dropped | 834 | * returns non-zero if packet should be dropped |
623 | */ | 835 | */ |
624 | int iwl_set_decrypted_flag(struct iwl_priv *priv, | 836 | static int iwl_set_decrypted_flag(struct iwl_priv *priv, |
625 | struct ieee80211_hdr *hdr, | 837 | struct ieee80211_hdr *hdr, |
626 | u32 decrypt_res, | 838 | u32 decrypt_res, |
627 | struct ieee80211_rx_status *stats) | 839 | struct ieee80211_rx_status *stats) |
628 | { | 840 | { |
629 | u16 fc = le16_to_cpu(hdr->frame_control); | 841 | u16 fc = le16_to_cpu(hdr->frame_control); |
630 | 842 | ||
@@ -669,3 +881,264 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, | |||
669 | } | 881 | } |
670 | return 0; | 882 | return 0; |
671 | } | 883 | } |
884 | |||
885 | static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, | ||
886 | struct ieee80211_hdr *hdr, | ||
887 | u16 len, | ||
888 | u32 ampdu_status, | ||
889 | struct iwl_rx_mem_buffer *rxb, | ||
890 | struct ieee80211_rx_status *stats) | ||
891 | { | ||
892 | struct sk_buff *skb; | ||
893 | __le16 fc = hdr->frame_control; | ||
894 | |||
895 | /* We only process data packets if the interface is open */ | ||
896 | if (unlikely(!priv->is_open)) { | ||
897 | IWL_DEBUG_DROP_LIMIT(priv, | ||
898 | "Dropping packet while interface is not open.\n"); | ||
899 | return; | ||
900 | } | ||
901 | |||
902 | /* In case of HW accelerated crypto and bad decryption, drop */ | ||
903 | if (!priv->cfg->mod_params->sw_crypto && | ||
904 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | ||
905 | return; | ||
906 | |||
907 | skb = dev_alloc_skb(128); | ||
908 | if (!skb) { | ||
909 | IWL_ERR(priv, "dev_alloc_skb failed\n"); | ||
910 | return; | ||
911 | } | ||
912 | |||
913 | skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); | ||
914 | |||
915 | iwl_update_stats(priv, false, fc, len); | ||
916 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | ||
917 | |||
918 | ieee80211_rx(priv->hw, skb); | ||
919 | priv->alloc_rxb_page--; | ||
920 | rxb->page = NULL; | ||
921 | } | ||
922 | |||
923 | static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | ||
924 | { | ||
925 | u32 decrypt_out = 0; | ||
926 | |||
927 | if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == | ||
928 | RX_RES_STATUS_STATION_FOUND) | ||
929 | decrypt_out |= (RX_RES_STATUS_STATION_FOUND | | ||
930 | RX_RES_STATUS_NO_STATION_INFO_MISMATCH); | ||
931 | |||
932 | decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); | ||
933 | |||
934 | /* packet was not encrypted */ | ||
935 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
936 | RX_RES_STATUS_SEC_TYPE_NONE) | ||
937 | return decrypt_out; | ||
938 | |||
939 | /* packet was encrypted with unknown alg */ | ||
940 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
941 | RX_RES_STATUS_SEC_TYPE_ERR) | ||
942 | return decrypt_out; | ||
943 | |||
944 | /* decryption was not done in HW */ | ||
945 | if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != | ||
946 | RX_MPDU_RES_STATUS_DEC_DONE_MSK) | ||
947 | return decrypt_out; | ||
948 | |||
949 | switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
950 | |||
951 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
952 | /* alg is CCM: check MIC only */ | ||
953 | if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) | ||
954 | /* Bad MIC */ | ||
955 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
956 | else | ||
957 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
958 | |||
959 | break; | ||
960 | |||
961 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
962 | if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { | ||
963 | /* Bad TTAK */ | ||
964 | decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; | ||
965 | break; | ||
966 | } | ||
967 | /* fall through if TTAK OK */ | ||
968 | default: | ||
969 | if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) | ||
970 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
971 | else | ||
972 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
973 | break; | ||
974 | } | ||
975 | |||
976 | IWL_DEBUG_RX(priv, "decrypt_in:0x%x decrypt_out = 0x%x\n", | ||
977 | decrypt_in, decrypt_out); | ||
978 | |||
979 | return decrypt_out; | ||
980 | } | ||
981 | |||
982 | /* Called for REPLY_RX (legacy ABG frames), or | ||
983 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ | ||
984 | static void iwl_rx_reply_rx(struct iwl_priv *priv, | ||
985 | struct iwl_rx_mem_buffer *rxb) | ||
986 | { | ||
987 | struct ieee80211_hdr *header; | ||
988 | struct ieee80211_rx_status rx_status; | ||
989 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
990 | struct iwl_rx_phy_res *phy_res; | ||
991 | __le32 rx_pkt_status; | ||
992 | struct iwl_rx_mpdu_res_start *amsdu; | ||
993 | u32 len; | ||
994 | u32 ampdu_status; | ||
995 | u32 rate_n_flags; | ||
996 | |||
997 | /** | ||
998 | * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently. | ||
999 | * REPLY_RX: physical layer info is in this buffer | ||
1000 | * REPLY_RX_MPDU_CMD: physical layer info was sent in separate | ||
1001 | * command and cached in priv->last_phy_res | ||
1002 | * | ||
1003 | * Here we set up local variables depending on which command is | ||
1004 | * received. | ||
1005 | */ | ||
1006 | if (pkt->hdr.cmd == REPLY_RX) { | ||
1007 | phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; | ||
1008 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) | ||
1009 | + phy_res->cfg_phy_cnt); | ||
1010 | |||
1011 | len = le16_to_cpu(phy_res->byte_count); | ||
1012 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) + | ||
1013 | phy_res->cfg_phy_cnt + len); | ||
1014 | ampdu_status = le32_to_cpu(rx_pkt_status); | ||
1015 | } else { | ||
1016 | if (!priv->_agn.last_phy_res_valid) { | ||
1017 | IWL_ERR(priv, "MPDU frame without cached PHY data\n"); | ||
1018 | return; | ||
1019 | } | ||
1020 | phy_res = &priv->_agn.last_phy_res; | ||
1021 | amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw; | ||
1022 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); | ||
1023 | len = le16_to_cpu(amsdu->byte_count); | ||
1024 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); | ||
1025 | ampdu_status = iwl_translate_rx_status(priv, | ||
1026 | le32_to_cpu(rx_pkt_status)); | ||
1027 | } | ||
1028 | |||
1029 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { | ||
1030 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", | ||
1031 | phy_res->cfg_phy_cnt); | ||
1032 | return; | ||
1033 | } | ||
1034 | |||
1035 | if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || | ||
1036 | !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | ||
1037 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", | ||
1038 | le32_to_cpu(rx_pkt_status)); | ||
1039 | return; | ||
1040 | } | ||
1041 | |||
1042 | /* This will be used in several places later */ | ||
1043 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
1044 | |||
1045 | /* rx_status carries information about the packet to mac80211 */ | ||
1046 | rx_status.mactime = le64_to_cpu(phy_res->timestamp); | ||
1047 | rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
1048 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
1049 | rx_status.freq = | ||
1050 | ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel), | ||
1051 | rx_status.band); | ||
1052 | rx_status.rate_idx = | ||
1053 | iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); | ||
1054 | rx_status.flag = 0; | ||
1055 | |||
1056 | /* TSF isn't reliable. In order to allow smooth user experience, | ||
1057 | * this W/A doesn't propagate it to the mac80211 */ | ||
1058 | /*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/ | ||
1059 | |||
1060 | priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); | ||
1061 | |||
1062 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | ||
1063 | rx_status.signal = priv->cfg->ops->utils->calc_rssi(priv, phy_res); | ||
1064 | |||
1065 | iwl_dbg_log_rx_data_frame(priv, len, header); | ||
1066 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n", | ||
1067 | rx_status.signal, (unsigned long long)rx_status.mactime); | ||
1068 | |||
1069 | /* | ||
1070 | * "antenna number" | ||
1071 | * | ||
1072 | * It seems that the antenna field in the phy flags value | ||
1073 | * is actually a bit field. This is undefined by radiotap, | ||
1074 | * it wants an actual antenna number but I always get "7" | ||
1075 | * for most legacy frames I receive indicating that the | ||
1076 | * same frame was received on all three RX chains. | ||
1077 | * | ||
1078 | * I think this field should be removed in favor of a | ||
1079 | * new 802.11n radiotap field "RX chains" that is defined | ||
1080 | * as a bitmask. | ||
1081 | */ | ||
1082 | rx_status.antenna = | ||
1083 | (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) | ||
1084 | >> RX_RES_PHY_FLAGS_ANTENNA_POS; | ||
1085 | |||
1086 | /* set the preamble flag if appropriate */ | ||
1087 | if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) | ||
1088 | rx_status.flag |= RX_FLAG_SHORTPRE; | ||
1089 | |||
1090 | /* Set up the HT phy flags */ | ||
1091 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
1092 | rx_status.flag |= RX_FLAG_HT; | ||
1093 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
1094 | rx_status.flag |= RX_FLAG_40MHZ; | ||
1095 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
1096 | rx_status.flag |= RX_FLAG_SHORT_GI; | ||
1097 | |||
1098 | iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, | ||
1099 | rxb, &rx_status); | ||
1100 | } | ||
1101 | |||
1102 | /** | ||
1103 | * iwl_setup_rx_handlers - Initialize Rx handler callbacks | ||
1104 | * | ||
1105 | * Setup the RX handlers for each of the reply types sent from the uCode | ||
1106 | * to the host. | ||
1107 | */ | ||
1108 | void iwl_setup_rx_handlers(struct iwl_priv *priv) | ||
1109 | { | ||
1110 | void (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | ||
1111 | |||
1112 | handlers = priv->rx_handlers; | ||
1113 | |||
1114 | handlers[REPLY_ALIVE] = iwl_rx_reply_alive; | ||
1115 | handlers[REPLY_ERROR] = iwl_rx_reply_error; | ||
1116 | handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; | ||
1117 | handlers[SPECTRUM_MEASURE_NOTIFICATION] = iwl_rx_spectrum_measure_notif; | ||
1118 | handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; | ||
1119 | handlers[PM_DEBUG_STATISTIC_NOTIFIC] = iwl_rx_pm_debug_statistics_notif; | ||
1120 | handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif; | ||
1121 | |||
1122 | /* | ||
1123 | * The same handler is used for both the REPLY to a discrete | ||
1124 | * statistics request from the host as well as for the periodic | ||
1125 | * statistics notifications (after received beacons) from the uCode. | ||
1126 | */ | ||
1127 | handlers[REPLY_STATISTICS_CMD] = iwl_rx_reply_statistics; | ||
1128 | handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; | ||
1129 | |||
1130 | iwl_setup_rx_scan_handlers(priv); | ||
1131 | |||
1132 | handlers[CARD_STATE_NOTIFICATION] = iwl_rx_card_state_notif; | ||
1133 | handlers[MISSED_BEACONS_NOTIFICATION] = iwl_rx_missed_beacon_notif; | ||
1134 | |||
1135 | /* Rx handlers */ | ||
1136 | handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy; | ||
1137 | handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx; | ||
1138 | |||
1139 | /* block ack */ | ||
1140 | handlers[REPLY_COMPRESSED_BA] = iwlagn_rx_reply_compressed_ba; | ||
1141 | |||
1142 | /* Set up hardware specific Rx handlers */ | ||
1143 | priv->cfg->ops->lib->rx_handler_setup(priv); | ||
1144 | } | ||