diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 242 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 178 | ||||
-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-dev.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rx.c | 665 |
7 files changed, 570 insertions, 613 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index fd142bee9189..25fccf9a3001 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -533,9 +533,10 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) | |||
533 | 533 | ||
534 | void iwlagn_temperature(struct iwl_priv *priv) | 534 | void iwlagn_temperature(struct iwl_priv *priv) |
535 | { | 535 | { |
536 | /* store temperature from statistics (in Celsius) */ | 536 | /* store temperature from correct statistics (in Celsius) */ |
537 | priv->temperature = | 537 | priv->temperature = le32_to_cpu((iwl_bt_statistics(priv)) ? |
538 | le32_to_cpu(priv->_agn.statistics.general.common.temperature); | 538 | priv->_agn.statistics_bt.general.common.temperature : |
539 | priv->_agn.statistics.general.common.temperature); | ||
539 | iwl_tt_handler(priv); | 540 | iwl_tt_handler(priv); |
540 | } | 541 | } |
541 | 542 | ||
@@ -994,241 +995,6 @@ int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) | |||
994 | return -1; | 995 | return -1; |
995 | } | 996 | } |
996 | 997 | ||
997 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
998 | static inline int iwlagn_calc_rssi(struct iwl_priv *priv, | ||
999 | struct iwl_rx_phy_res *rx_resp) | ||
1000 | { | ||
1001 | return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); | ||
1002 | } | ||
1003 | |||
1004 | static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | ||
1005 | { | ||
1006 | u32 decrypt_out = 0; | ||
1007 | |||
1008 | if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == | ||
1009 | RX_RES_STATUS_STATION_FOUND) | ||
1010 | decrypt_out |= (RX_RES_STATUS_STATION_FOUND | | ||
1011 | RX_RES_STATUS_NO_STATION_INFO_MISMATCH); | ||
1012 | |||
1013 | decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); | ||
1014 | |||
1015 | /* packet was not encrypted */ | ||
1016 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
1017 | RX_RES_STATUS_SEC_TYPE_NONE) | ||
1018 | return decrypt_out; | ||
1019 | |||
1020 | /* packet was encrypted with unknown alg */ | ||
1021 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
1022 | RX_RES_STATUS_SEC_TYPE_ERR) | ||
1023 | return decrypt_out; | ||
1024 | |||
1025 | /* decryption was not done in HW */ | ||
1026 | if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != | ||
1027 | RX_MPDU_RES_STATUS_DEC_DONE_MSK) | ||
1028 | return decrypt_out; | ||
1029 | |||
1030 | switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
1031 | |||
1032 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
1033 | /* alg is CCM: check MIC only */ | ||
1034 | if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) | ||
1035 | /* Bad MIC */ | ||
1036 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
1037 | else | ||
1038 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
1039 | |||
1040 | break; | ||
1041 | |||
1042 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
1043 | if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { | ||
1044 | /* Bad TTAK */ | ||
1045 | decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; | ||
1046 | break; | ||
1047 | } | ||
1048 | /* fall through if TTAK OK */ | ||
1049 | default: | ||
1050 | if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) | ||
1051 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
1052 | else | ||
1053 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
1054 | break; | ||
1055 | } | ||
1056 | |||
1057 | IWL_DEBUG_RX(priv, "decrypt_in:0x%x decrypt_out = 0x%x\n", | ||
1058 | decrypt_in, decrypt_out); | ||
1059 | |||
1060 | return decrypt_out; | ||
1061 | } | ||
1062 | |||
1063 | static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv, | ||
1064 | struct ieee80211_hdr *hdr, | ||
1065 | u16 len, | ||
1066 | u32 ampdu_status, | ||
1067 | struct iwl_rx_mem_buffer *rxb, | ||
1068 | struct ieee80211_rx_status *stats) | ||
1069 | { | ||
1070 | struct sk_buff *skb; | ||
1071 | __le16 fc = hdr->frame_control; | ||
1072 | |||
1073 | /* We only process data packets if the interface is open */ | ||
1074 | if (unlikely(!priv->is_open)) { | ||
1075 | IWL_DEBUG_DROP_LIMIT(priv, | ||
1076 | "Dropping packet while interface is not open.\n"); | ||
1077 | return; | ||
1078 | } | ||
1079 | |||
1080 | /* In case of HW accelerated crypto and bad decryption, drop */ | ||
1081 | if (!priv->cfg->mod_params->sw_crypto && | ||
1082 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | ||
1083 | return; | ||
1084 | |||
1085 | skb = dev_alloc_skb(128); | ||
1086 | if (!skb) { | ||
1087 | IWL_ERR(priv, "dev_alloc_skb failed\n"); | ||
1088 | return; | ||
1089 | } | ||
1090 | |||
1091 | skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); | ||
1092 | |||
1093 | iwl_update_stats(priv, false, fc, len); | ||
1094 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | ||
1095 | |||
1096 | ieee80211_rx(priv->hw, skb); | ||
1097 | priv->alloc_rxb_page--; | ||
1098 | rxb->page = NULL; | ||
1099 | } | ||
1100 | |||
1101 | /* Called for REPLY_RX (legacy ABG frames), or | ||
1102 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ | ||
1103 | void iwlagn_rx_reply_rx(struct iwl_priv *priv, | ||
1104 | struct iwl_rx_mem_buffer *rxb) | ||
1105 | { | ||
1106 | struct ieee80211_hdr *header; | ||
1107 | struct ieee80211_rx_status rx_status; | ||
1108 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1109 | struct iwl_rx_phy_res *phy_res; | ||
1110 | __le32 rx_pkt_status; | ||
1111 | struct iwl_rx_mpdu_res_start *amsdu; | ||
1112 | u32 len; | ||
1113 | u32 ampdu_status; | ||
1114 | u32 rate_n_flags; | ||
1115 | |||
1116 | /** | ||
1117 | * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently. | ||
1118 | * REPLY_RX: physical layer info is in this buffer | ||
1119 | * REPLY_RX_MPDU_CMD: physical layer info was sent in separate | ||
1120 | * command and cached in priv->last_phy_res | ||
1121 | * | ||
1122 | * Here we set up local variables depending on which command is | ||
1123 | * received. | ||
1124 | */ | ||
1125 | if (pkt->hdr.cmd == REPLY_RX) { | ||
1126 | phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; | ||
1127 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) | ||
1128 | + phy_res->cfg_phy_cnt); | ||
1129 | |||
1130 | len = le16_to_cpu(phy_res->byte_count); | ||
1131 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) + | ||
1132 | phy_res->cfg_phy_cnt + len); | ||
1133 | ampdu_status = le32_to_cpu(rx_pkt_status); | ||
1134 | } else { | ||
1135 | if (!priv->_agn.last_phy_res_valid) { | ||
1136 | IWL_ERR(priv, "MPDU frame without cached PHY data\n"); | ||
1137 | return; | ||
1138 | } | ||
1139 | phy_res = &priv->_agn.last_phy_res; | ||
1140 | amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw; | ||
1141 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); | ||
1142 | len = le16_to_cpu(amsdu->byte_count); | ||
1143 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); | ||
1144 | ampdu_status = iwlagn_translate_rx_status(priv, | ||
1145 | le32_to_cpu(rx_pkt_status)); | ||
1146 | } | ||
1147 | |||
1148 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { | ||
1149 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", | ||
1150 | phy_res->cfg_phy_cnt); | ||
1151 | return; | ||
1152 | } | ||
1153 | |||
1154 | if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || | ||
1155 | !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | ||
1156 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", | ||
1157 | le32_to_cpu(rx_pkt_status)); | ||
1158 | return; | ||
1159 | } | ||
1160 | |||
1161 | /* This will be used in several places later */ | ||
1162 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
1163 | |||
1164 | /* rx_status carries information about the packet to mac80211 */ | ||
1165 | rx_status.mactime = le64_to_cpu(phy_res->timestamp); | ||
1166 | rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
1167 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
1168 | rx_status.freq = | ||
1169 | ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel), | ||
1170 | rx_status.band); | ||
1171 | rx_status.rate_idx = | ||
1172 | iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); | ||
1173 | rx_status.flag = 0; | ||
1174 | |||
1175 | /* TSF isn't reliable. In order to allow smooth user experience, | ||
1176 | * this W/A doesn't propagate it to the mac80211 */ | ||
1177 | /*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/ | ||
1178 | |||
1179 | priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); | ||
1180 | |||
1181 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | ||
1182 | rx_status.signal = iwlagn_calc_rssi(priv, phy_res); | ||
1183 | |||
1184 | iwl_dbg_log_rx_data_frame(priv, len, header); | ||
1185 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n", | ||
1186 | rx_status.signal, (unsigned long long)rx_status.mactime); | ||
1187 | |||
1188 | /* | ||
1189 | * "antenna number" | ||
1190 | * | ||
1191 | * It seems that the antenna field in the phy flags value | ||
1192 | * is actually a bit field. This is undefined by radiotap, | ||
1193 | * it wants an actual antenna number but I always get "7" | ||
1194 | * for most legacy frames I receive indicating that the | ||
1195 | * same frame was received on all three RX chains. | ||
1196 | * | ||
1197 | * I think this field should be removed in favor of a | ||
1198 | * new 802.11n radiotap field "RX chains" that is defined | ||
1199 | * as a bitmask. | ||
1200 | */ | ||
1201 | rx_status.antenna = | ||
1202 | (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) | ||
1203 | >> RX_RES_PHY_FLAGS_ANTENNA_POS; | ||
1204 | |||
1205 | /* set the preamble flag if appropriate */ | ||
1206 | if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) | ||
1207 | rx_status.flag |= RX_FLAG_SHORTPRE; | ||
1208 | |||
1209 | /* Set up the HT phy flags */ | ||
1210 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
1211 | rx_status.flag |= RX_FLAG_HT; | ||
1212 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
1213 | rx_status.flag |= RX_FLAG_40MHZ; | ||
1214 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
1215 | rx_status.flag |= RX_FLAG_SHORT_GI; | ||
1216 | |||
1217 | iwlagn_pass_packet_to_mac80211(priv, header, len, ampdu_status, | ||
1218 | rxb, &rx_status); | ||
1219 | } | ||
1220 | |||
1221 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). | ||
1222 | * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ | ||
1223 | void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, | ||
1224 | struct iwl_rx_mem_buffer *rxb) | ||
1225 | { | ||
1226 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1227 | priv->_agn.last_phy_res_valid = true; | ||
1228 | memcpy(&priv->_agn.last_phy_res, pkt->u.raw, | ||
1229 | sizeof(struct iwl_rx_phy_res)); | ||
1230 | } | ||
1231 | |||
1232 | 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, |
1233 | struct ieee80211_vif *vif, | 999 | struct ieee80211_vif *vif, |
1234 | 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 f189bbe78fa6..e0cd3e27a0d9 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 |
@@ -3913,6 +3737,8 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3913 | priv->force_reset[IWL_FW_RESET].reset_duration = | 3737 | priv->force_reset[IWL_FW_RESET].reset_duration = |
3914 | IWL_DELAY_NEXT_FORCE_FW_RELOAD; | 3738 | IWL_DELAY_NEXT_FORCE_FW_RELOAD; |
3915 | 3739 | ||
3740 | priv->rx_statistics_jiffies = jiffies; | ||
3741 | |||
3916 | /* Choose which receivers/antennas to use */ | 3742 | /* Choose which receivers/antennas to use */ |
3917 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 3743 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
3918 | priv->cfg->ops->hcmd->set_rxon_chain(priv, | 3744 | priv->cfg->ops->hcmd->set_rxon_chain(priv, |
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-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 58165c769cf1..6a41deba6863 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -1261,8 +1261,8 @@ struct iwl_priv { | |||
1261 | /* track IBSS manager (last beacon) status */ | 1261 | /* track IBSS manager (last beacon) status */ |
1262 | u32 ibss_manager; | 1262 | u32 ibss_manager; |
1263 | 1263 | ||
1264 | /* storing the jiffies when the plcp error rate is received */ | 1264 | /* jiffies when last recovery from statistics was performed */ |
1265 | unsigned long plcp_jiffies; | 1265 | unsigned long rx_statistics_jiffies; |
1266 | 1266 | ||
1267 | /* force reset */ | 1267 | /* force reset */ |
1268 | struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; | 1268 | struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 566e2d979ce3..6f9a2fa04763 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | #include <linux/etherdevice.h> | 30 | #include <linux/etherdevice.h> |
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/sched.h> | ||
32 | #include <net/mac80211.h> | 33 | #include <net/mac80211.h> |
33 | #include <asm/unaligned.h> | 34 | #include <asm/unaligned.h> |
34 | #include "iwl-eeprom.h" | 35 | #include "iwl-eeprom.h" |
@@ -38,7 +39,14 @@ | |||
38 | #include "iwl-io.h" | 39 | #include "iwl-io.h" |
39 | #include "iwl-helpers.h" | 40 | #include "iwl-helpers.h" |
40 | #include "iwl-agn-calib.h" | 41 | #include "iwl-agn-calib.h" |
41 | /************************** RX-FUNCTIONS ****************************/ | 42 | #include "iwl-agn.h" |
43 | |||
44 | /****************************************************************************** | ||
45 | * | ||
46 | * RX path functions | ||
47 | * | ||
48 | ******************************************************************************/ | ||
49 | |||
42 | /* | 50 | /* |
43 | * Rx theory of operation | 51 | * Rx theory of operation |
44 | * | 52 | * |
@@ -211,7 +219,104 @@ err_bd: | |||
211 | return -ENOMEM; | 219 | return -ENOMEM; |
212 | } | 220 | } |
213 | 221 | ||
214 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | 222 | /****************************************************************************** |
223 | * | ||
224 | * Generic RX handler implementations | ||
225 | * | ||
226 | ******************************************************************************/ | ||
227 | |||
228 | static void iwl_rx_reply_alive(struct iwl_priv *priv, | ||
229 | struct iwl_rx_mem_buffer *rxb) | ||
230 | { | ||
231 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
232 | struct iwl_alive_resp *palive; | ||
233 | struct delayed_work *pwork; | ||
234 | |||
235 | palive = &pkt->u.alive_frame; | ||
236 | |||
237 | IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision " | ||
238 | "0x%01X 0x%01X\n", | ||
239 | palive->is_valid, palive->ver_type, | ||
240 | palive->ver_subtype); | ||
241 | |||
242 | if (palive->ver_subtype == INITIALIZE_SUBTYPE) { | ||
243 | IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); | ||
244 | memcpy(&priv->card_alive_init, | ||
245 | &pkt->u.alive_frame, | ||
246 | sizeof(struct iwl_init_alive_resp)); | ||
247 | pwork = &priv->init_alive_start; | ||
248 | } else { | ||
249 | IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); | ||
250 | memcpy(&priv->card_alive, &pkt->u.alive_frame, | ||
251 | sizeof(struct iwl_alive_resp)); | ||
252 | pwork = &priv->alive_start; | ||
253 | } | ||
254 | |||
255 | /* We delay the ALIVE response by 5ms to | ||
256 | * give the HW RF Kill time to activate... */ | ||
257 | if (palive->is_valid == UCODE_VALID_OK) | ||
258 | queue_delayed_work(priv->workqueue, pwork, | ||
259 | msecs_to_jiffies(5)); | ||
260 | else { | ||
261 | IWL_WARN(priv, "%s uCode did not respond OK.\n", | ||
262 | (palive->ver_subtype == INITIALIZE_SUBTYPE) ? | ||
263 | "init" : "runtime"); | ||
264 | /* | ||
265 | * If fail to load init uCode, | ||
266 | * let's try to load the init uCode again. | ||
267 | * We should not get into this situation, but if it | ||
268 | * does happen, we should not move on and loading "runtime" | ||
269 | * without proper calibrate the device. | ||
270 | */ | ||
271 | if (palive->ver_subtype == INITIALIZE_SUBTYPE) | ||
272 | priv->ucode_type = UCODE_NONE; | ||
273 | queue_work(priv->workqueue, &priv->restart); | ||
274 | } | ||
275 | } | ||
276 | |||
277 | static void iwl_rx_reply_error(struct iwl_priv *priv, | ||
278 | struct iwl_rx_mem_buffer *rxb) | ||
279 | { | ||
280 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
281 | |||
282 | IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) " | ||
283 | "seq 0x%04X ser 0x%08X\n", | ||
284 | le32_to_cpu(pkt->u.err_resp.error_type), | ||
285 | get_cmd_string(pkt->u.err_resp.cmd_id), | ||
286 | pkt->u.err_resp.cmd_id, | ||
287 | le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num), | ||
288 | le32_to_cpu(pkt->u.err_resp.error_info)); | ||
289 | } | ||
290 | |||
291 | static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | ||
292 | { | ||
293 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
294 | struct iwl_csa_notification *csa = &(pkt->u.csa_notif); | ||
295 | /* | ||
296 | * MULTI-FIXME | ||
297 | * See iwl_mac_channel_switch. | ||
298 | */ | ||
299 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
300 | struct iwl_rxon_cmd *rxon = (void *)&ctx->active; | ||
301 | |||
302 | if (priv->switch_rxon.switch_in_progress) { | ||
303 | if (!le32_to_cpu(csa->status) && | ||
304 | (csa->channel == priv->switch_rxon.channel)) { | ||
305 | rxon->channel = csa->channel; | ||
306 | ctx->staging.channel = csa->channel; | ||
307 | IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", | ||
308 | le16_to_cpu(csa->channel)); | ||
309 | iwl_chswitch_done(priv, true); | ||
310 | } else { | ||
311 | IWL_ERR(priv, "CSA notif (fail) : channel %d\n", | ||
312 | le16_to_cpu(csa->channel)); | ||
313 | iwl_chswitch_done(priv, false); | ||
314 | } | ||
315 | } | ||
316 | } | ||
317 | |||
318 | |||
319 | static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | ||
215 | struct iwl_rx_mem_buffer *rxb) | 320 | struct iwl_rx_mem_buffer *rxb) |
216 | { | 321 | { |
217 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 322 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
@@ -227,6 +332,52 @@ void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | |||
227 | priv->measurement_status |= MEASUREMENT_READY; | 332 | priv->measurement_status |= MEASUREMENT_READY; |
228 | } | 333 | } |
229 | 334 | ||
335 | static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, | ||
336 | struct iwl_rx_mem_buffer *rxb) | ||
337 | { | ||
338 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
339 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
340 | struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif); | ||
341 | IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n", | ||
342 | sleep->pm_sleep_mode, sleep->pm_wakeup_src); | ||
343 | #endif | ||
344 | } | ||
345 | |||
346 | static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, | ||
347 | struct iwl_rx_mem_buffer *rxb) | ||
348 | { | ||
349 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
350 | u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
351 | IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " | ||
352 | "notification for %s:\n", len, | ||
353 | get_cmd_string(pkt->hdr.cmd)); | ||
354 | iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len); | ||
355 | } | ||
356 | |||
357 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, | ||
358 | struct iwl_rx_mem_buffer *rxb) | ||
359 | { | ||
360 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
361 | struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw; | ||
362 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
363 | u16 status = le16_to_cpu(beacon->beacon_notify_hdr.status.status); | ||
364 | u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); | ||
365 | |||
366 | IWL_DEBUG_RX(priv, "beacon status %#x, retries:%d ibssmgr:%d " | ||
367 | "tsf:0x%.8x%.8x rate:%d\n", | ||
368 | status & TX_STATUS_MSK, | ||
369 | beacon->beacon_notify_hdr.failure_frame, | ||
370 | le32_to_cpu(beacon->ibss_mgr_status), | ||
371 | le32_to_cpu(beacon->high_tsf), | ||
372 | le32_to_cpu(beacon->low_tsf), rate); | ||
373 | #endif | ||
374 | |||
375 | priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); | ||
376 | |||
377 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
378 | queue_work(priv->workqueue, &priv->beacon_update); | ||
379 | } | ||
380 | |||
230 | /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ | 381 | /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ |
231 | #define ACK_CNT_RATIO (50) | 382 | #define ACK_CNT_RATIO (50) |
232 | #define BA_TIMEOUT_CNT (5) | 383 | #define BA_TIMEOUT_CNT (5) |
@@ -298,92 +449,72 @@ 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 | 449 | * When the plcp error is exceeding the thresholds, reset the radio |
299 | * to improve the throughput. | 450 | * to improve the throughput. |
300 | */ | 451 | */ |
301 | static bool iwl_good_plcp_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt) | 452 | static bool iwl_good_plcp_health(struct iwl_priv *priv, |
453 | struct iwl_rx_packet *pkt, unsigned int msecs) | ||
302 | { | 454 | { |
303 | bool rc = true; | 455 | int delta; |
304 | int combined_plcp_delta; | 456 | int threshold = priv->cfg->base_params->plcp_delta_threshold; |
305 | unsigned int plcp_msec; | ||
306 | unsigned long plcp_received_jiffies; | ||
307 | 457 | ||
308 | if (priv->cfg->base_params->plcp_delta_threshold == | 458 | if (threshold == IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) { |
309 | IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) { | ||
310 | IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n"); | 459 | IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n"); |
311 | return rc; | 460 | return true; |
312 | } | 461 | } |
313 | 462 | ||
314 | /* | 463 | if (iwl_bt_statistics(priv)) { |
315 | * check for plcp_err and trigger radio reset if it exceeds | 464 | struct statistics_rx_bt *cur, *old; |
316 | * the plcp error threshold plcp_delta. | ||
317 | */ | ||
318 | plcp_received_jiffies = jiffies; | ||
319 | plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies - | ||
320 | (long) priv->plcp_jiffies); | ||
321 | priv->plcp_jiffies = plcp_received_jiffies; | ||
322 | /* | ||
323 | * check to make sure plcp_msec is not 0 to prevent division | ||
324 | * by zero. | ||
325 | */ | ||
326 | if (plcp_msec) { | ||
327 | struct statistics_rx_phy *ofdm; | ||
328 | struct statistics_rx_ht_phy *ofdm_ht; | ||
329 | |||
330 | if (iwl_bt_statistics(priv)) { | ||
331 | ofdm = &pkt->u.stats_bt.rx.ofdm; | ||
332 | ofdm_ht = &pkt->u.stats_bt.rx.ofdm_ht; | ||
333 | combined_plcp_delta = | ||
334 | (le32_to_cpu(ofdm->plcp_err) - | ||
335 | le32_to_cpu(priv->_agn.statistics_bt. | ||
336 | rx.ofdm.plcp_err)) + | ||
337 | (le32_to_cpu(ofdm_ht->plcp_err) - | ||
338 | le32_to_cpu(priv->_agn.statistics_bt. | ||
339 | rx.ofdm_ht.plcp_err)); | ||
340 | } else { | ||
341 | ofdm = &pkt->u.stats.rx.ofdm; | ||
342 | ofdm_ht = &pkt->u.stats.rx.ofdm_ht; | ||
343 | combined_plcp_delta = | ||
344 | (le32_to_cpu(ofdm->plcp_err) - | ||
345 | le32_to_cpu(priv->_agn.statistics. | ||
346 | rx.ofdm.plcp_err)) + | ||
347 | (le32_to_cpu(ofdm_ht->plcp_err) - | ||
348 | le32_to_cpu(priv->_agn.statistics. | ||
349 | rx.ofdm_ht.plcp_err)); | ||
350 | } | ||
351 | 465 | ||
352 | if ((combined_plcp_delta > 0) && | 466 | cur = &pkt->u.stats_bt.rx; |
353 | ((combined_plcp_delta * 100) / plcp_msec) > | 467 | old = &priv->_agn.statistics_bt.rx; |
354 | priv->cfg->base_params->plcp_delta_threshold) { | 468 | |
355 | /* | 469 | delta = le32_to_cpu(cur->ofdm.plcp_err) - |
356 | * if plcp_err exceed the threshold, | 470 | le32_to_cpu(old->ofdm.plcp_err) + |
357 | * the following data is printed in csv format: | 471 | le32_to_cpu(cur->ofdm_ht.plcp_err) - |
358 | * Text: plcp_err exceeded %d, | 472 | le32_to_cpu(old->ofdm_ht.plcp_err); |
359 | * Received ofdm.plcp_err, | 473 | } else { |
360 | * Current ofdm.plcp_err, | 474 | struct statistics_rx *cur, *old; |
361 | * Received ofdm_ht.plcp_err, | 475 | |
362 | * Current ofdm_ht.plcp_err, | 476 | cur = &pkt->u.stats.rx; |
363 | * combined_plcp_delta, | 477 | old = &priv->_agn.statistics.rx; |
364 | * plcp_msec | 478 | |
365 | */ | 479 | delta = le32_to_cpu(cur->ofdm.plcp_err) - |
366 | IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " | 480 | le32_to_cpu(old->ofdm.plcp_err) + |
367 | "%u, %u, %u, %u, %d, %u mSecs\n", | 481 | le32_to_cpu(cur->ofdm_ht.plcp_err) - |
368 | priv->cfg->base_params->plcp_delta_threshold, | 482 | le32_to_cpu(old->ofdm_ht.plcp_err); |
369 | le32_to_cpu(ofdm->plcp_err), | ||
370 | le32_to_cpu(ofdm->plcp_err), | ||
371 | le32_to_cpu(ofdm_ht->plcp_err), | ||
372 | le32_to_cpu(ofdm_ht->plcp_err), | ||
373 | combined_plcp_delta, plcp_msec); | ||
374 | |||
375 | rc = false; | ||
376 | } | ||
377 | } | 483 | } |
378 | return rc; | 484 | |
485 | /* Can be negative if firmware reseted statistics */ | ||
486 | if (delta <= 0) | ||
487 | return true; | ||
488 | |||
489 | if ((delta * 100 / msecs) > threshold) { | ||
490 | IWL_DEBUG_RADIO(priv, | ||
491 | "plcp health threshold %u delta %d msecs %u\n", | ||
492 | threshold, delta, msecs); | ||
493 | return false; | ||
494 | } | ||
495 | |||
496 | return true; | ||
379 | } | 497 | } |
380 | 498 | ||
381 | static void iwl_recover_from_statistics(struct iwl_priv *priv, struct iwl_rx_packet *pkt) | 499 | static void iwl_recover_from_statistics(struct iwl_priv *priv, |
500 | struct iwl_rx_packet *pkt) | ||
382 | { | 501 | { |
383 | const struct iwl_mod_params *mod_params = priv->cfg->mod_params; | 502 | const struct iwl_mod_params *mod_params = priv->cfg->mod_params; |
503 | unsigned int msecs; | ||
504 | unsigned long stamp; | ||
384 | 505 | ||
385 | if (test_bit(STATUS_EXIT_PENDING, &priv->status) || | 506 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
386 | !iwl_is_any_associated(priv)) | 507 | return; |
508 | |||
509 | stamp = jiffies; | ||
510 | msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies); | ||
511 | |||
512 | /* Only gather statistics and update time stamp when not associated */ | ||
513 | if (!iwl_is_any_associated(priv)) | ||
514 | goto out; | ||
515 | |||
516 | /* Do not check/recover when do not have enough statistics data */ | ||
517 | if (msecs < 99) | ||
387 | return; | 518 | return; |
388 | 519 | ||
389 | if (mod_params->ack_check && !iwl_good_ack_health(priv, pkt)) { | 520 | if (mod_params->ack_check && !iwl_good_ack_health(priv, pkt)) { |
@@ -392,8 +523,18 @@ static void iwl_recover_from_statistics(struct iwl_priv *priv, struct iwl_rx_pac | |||
392 | return; | 523 | return; |
393 | } | 524 | } |
394 | 525 | ||
395 | if (mod_params->plcp_check && !iwl_good_plcp_health(priv, pkt)) | 526 | if (mod_params->plcp_check && !iwl_good_plcp_health(priv, pkt, msecs)) |
396 | iwl_force_reset(priv, IWL_RF_RESET, false); | 527 | iwl_force_reset(priv, IWL_RF_RESET, false); |
528 | |||
529 | out: | ||
530 | if (iwl_bt_statistics(priv)) | ||
531 | memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt, | ||
532 | sizeof(priv->_agn.statistics_bt)); | ||
533 | else | ||
534 | memcpy(&priv->_agn.statistics, &pkt->u.stats, | ||
535 | sizeof(priv->_agn.statistics)); | ||
536 | |||
537 | priv->rx_statistics_jiffies = stamp; | ||
397 | } | 538 | } |
398 | 539 | ||
399 | /* Calculate noise level, based on measurements during network silence just | 540 | /* Calculate noise level, based on measurements during network silence just |
@@ -442,7 +583,6 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) | |||
442 | last_rx_noise); | 583 | last_rx_noise); |
443 | } | 584 | } |
444 | 585 | ||
445 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
446 | /* | 586 | /* |
447 | * based on the assumption of all statistics counter are in DWORD | 587 | * based on the assumption of all statistics counter are in DWORD |
448 | * FIXME: This function is for debugging, do not deal with | 588 | * FIXME: This function is for debugging, do not deal with |
@@ -451,6 +591,7 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) | |||
451 | static void iwl_accumulative_statistics(struct iwl_priv *priv, | 591 | static void iwl_accumulative_statistics(struct iwl_priv *priv, |
452 | __le32 *stats) | 592 | __le32 *stats) |
453 | { | 593 | { |
594 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
454 | int i, size; | 595 | int i, size; |
455 | __le32 *prev_stats; | 596 | __le32 *prev_stats; |
456 | u32 *accum_stats; | 597 | u32 *accum_stats; |
@@ -498,14 +639,13 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, | |||
498 | accum_tx->tx_power.ant_a = tx->tx_power.ant_a; | 639 | accum_tx->tx_power.ant_a = tx->tx_power.ant_a; |
499 | accum_tx->tx_power.ant_b = tx->tx_power.ant_b; | 640 | accum_tx->tx_power.ant_b = tx->tx_power.ant_b; |
500 | accum_tx->tx_power.ant_c = tx->tx_power.ant_c; | 641 | accum_tx->tx_power.ant_c = tx->tx_power.ant_c; |
501 | } | ||
502 | #endif | 642 | #endif |
643 | } | ||
503 | 644 | ||
504 | #define REG_RECALIB_PERIOD (60) | 645 | 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) | 646 | struct iwl_rx_mem_buffer *rxb) |
508 | { | 647 | { |
648 | const int reg_recalib_period = 60; | ||
509 | int change; | 649 | int change; |
510 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 650 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
511 | 651 | ||
@@ -522,10 +662,8 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
522 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != | 662 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != |
523 | (pkt->u.stats_bt.flag & | 663 | (pkt->u.stats_bt.flag & |
524 | STATISTICS_REPLY_FLG_HT40_MODE_MSK))); | 664 | STATISTICS_REPLY_FLG_HT40_MODE_MSK))); |
525 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
526 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats_bt); | ||
527 | #endif | ||
528 | 665 | ||
666 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats_bt); | ||
529 | } else { | 667 | } else { |
530 | IWL_DEBUG_RX(priv, | 668 | IWL_DEBUG_RX(priv, |
531 | "Statistics notification received (%d vs %d).\n", | 669 | "Statistics notification received (%d vs %d).\n", |
@@ -539,29 +677,20 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
539 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != | 677 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != |
540 | (pkt->u.stats.flag & | 678 | (pkt->u.stats.flag & |
541 | STATISTICS_REPLY_FLG_HT40_MODE_MSK))); | 679 | STATISTICS_REPLY_FLG_HT40_MODE_MSK))); |
542 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
543 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); | ||
544 | #endif | ||
545 | 680 | ||
681 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); | ||
546 | } | 682 | } |
547 | 683 | ||
548 | iwl_recover_from_statistics(priv, pkt); | 684 | iwl_recover_from_statistics(priv, pkt); |
549 | 685 | ||
550 | if (iwl_bt_statistics(priv)) | ||
551 | memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt, | ||
552 | sizeof(priv->_agn.statistics_bt)); | ||
553 | else | ||
554 | memcpy(&priv->_agn.statistics, &pkt->u.stats, | ||
555 | sizeof(priv->_agn.statistics)); | ||
556 | |||
557 | set_bit(STATUS_STATISTICS, &priv->status); | 686 | set_bit(STATUS_STATISTICS, &priv->status); |
558 | 687 | ||
559 | /* Reschedule the statistics timer to occur in | 688 | /* Reschedule the statistics timer to occur in |
560 | * REG_RECALIB_PERIOD seconds to ensure we get a | 689 | * reg_recalib_period seconds to ensure we get a |
561 | * thermal update even if the uCode doesn't give | 690 | * thermal update even if the uCode doesn't give |
562 | * us one */ | 691 | * us one */ |
563 | mod_timer(&priv->statistics_periodic, jiffies + | 692 | mod_timer(&priv->statistics_periodic, jiffies + |
564 | msecs_to_jiffies(REG_RECALIB_PERIOD * 1000)); | 693 | msecs_to_jiffies(reg_recalib_period * 1000)); |
565 | 694 | ||
566 | if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && | 695 | if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && |
567 | (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { | 696 | (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { |
@@ -572,8 +701,8 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
572 | priv->cfg->ops->lib->temp_ops.temperature(priv); | 701 | priv->cfg->ops->lib->temp_ops.temperature(priv); |
573 | } | 702 | } |
574 | 703 | ||
575 | void iwl_reply_statistics(struct iwl_priv *priv, | 704 | static void iwl_rx_reply_statistics(struct iwl_priv *priv, |
576 | struct iwl_rx_mem_buffer *rxb) | 705 | struct iwl_rx_mem_buffer *rxb) |
577 | { | 706 | { |
578 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 707 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
579 | 708 | ||
@@ -597,8 +726,61 @@ void iwl_reply_statistics(struct iwl_priv *priv, | |||
597 | iwl_rx_statistics(priv, rxb); | 726 | iwl_rx_statistics(priv, rxb); |
598 | } | 727 | } |
599 | 728 | ||
600 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | 729 | /* Handle notification from uCode that card's power state is changing |
601 | struct iwl_rx_mem_buffer *rxb) | 730 | * due to software, hardware, or critical temperature RFKILL */ |
731 | static void iwl_rx_card_state_notif(struct iwl_priv *priv, | ||
732 | struct iwl_rx_mem_buffer *rxb) | ||
733 | { | ||
734 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
735 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); | ||
736 | unsigned long status = priv->status; | ||
737 | |||
738 | IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n", | ||
739 | (flags & HW_CARD_DISABLED) ? "Kill" : "On", | ||
740 | (flags & SW_CARD_DISABLED) ? "Kill" : "On", | ||
741 | (flags & CT_CARD_DISABLED) ? | ||
742 | "Reached" : "Not reached"); | ||
743 | |||
744 | if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | | ||
745 | CT_CARD_DISABLED)) { | ||
746 | |||
747 | iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, | ||
748 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | ||
749 | |||
750 | iwl_write_direct32(priv, HBUS_TARG_MBX_C, | ||
751 | HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); | ||
752 | |||
753 | if (!(flags & RXON_CARD_DISABLED)) { | ||
754 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, | ||
755 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | ||
756 | iwl_write_direct32(priv, HBUS_TARG_MBX_C, | ||
757 | HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); | ||
758 | } | ||
759 | if (flags & CT_CARD_DISABLED) | ||
760 | iwl_tt_enter_ct_kill(priv); | ||
761 | } | ||
762 | if (!(flags & CT_CARD_DISABLED)) | ||
763 | iwl_tt_exit_ct_kill(priv); | ||
764 | |||
765 | if (flags & HW_CARD_DISABLED) | ||
766 | set_bit(STATUS_RF_KILL_HW, &priv->status); | ||
767 | else | ||
768 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | ||
769 | |||
770 | |||
771 | if (!(flags & RXON_CARD_DISABLED)) | ||
772 | iwl_scan_cancel(priv); | ||
773 | |||
774 | if ((test_bit(STATUS_RF_KILL_HW, &status) != | ||
775 | test_bit(STATUS_RF_KILL_HW, &priv->status))) | ||
776 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, | ||
777 | test_bit(STATUS_RF_KILL_HW, &priv->status)); | ||
778 | else | ||
779 | wake_up_interruptible(&priv->wait_command_queue); | ||
780 | } | ||
781 | |||
782 | static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | ||
783 | struct iwl_rx_mem_buffer *rxb) | ||
602 | 784 | ||
603 | { | 785 | { |
604 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 786 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
@@ -618,13 +800,25 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | |||
618 | } | 800 | } |
619 | } | 801 | } |
620 | 802 | ||
803 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). | ||
804 | * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ | ||
805 | static void iwl_rx_reply_rx_phy(struct iwl_priv *priv, | ||
806 | struct iwl_rx_mem_buffer *rxb) | ||
807 | { | ||
808 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
809 | |||
810 | priv->_agn.last_phy_res_valid = true; | ||
811 | memcpy(&priv->_agn.last_phy_res, pkt->u.raw, | ||
812 | sizeof(struct iwl_rx_phy_res)); | ||
813 | } | ||
814 | |||
621 | /* | 815 | /* |
622 | * returns non-zero if packet should be dropped | 816 | * returns non-zero if packet should be dropped |
623 | */ | 817 | */ |
624 | int iwl_set_decrypted_flag(struct iwl_priv *priv, | 818 | static int iwl_set_decrypted_flag(struct iwl_priv *priv, |
625 | struct ieee80211_hdr *hdr, | 819 | struct ieee80211_hdr *hdr, |
626 | u32 decrypt_res, | 820 | u32 decrypt_res, |
627 | struct ieee80211_rx_status *stats) | 821 | struct ieee80211_rx_status *stats) |
628 | { | 822 | { |
629 | u16 fc = le16_to_cpu(hdr->frame_control); | 823 | u16 fc = le16_to_cpu(hdr->frame_control); |
630 | 824 | ||
@@ -669,3 +863,264 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, | |||
669 | } | 863 | } |
670 | return 0; | 864 | return 0; |
671 | } | 865 | } |
866 | |||
867 | static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, | ||
868 | struct ieee80211_hdr *hdr, | ||
869 | u16 len, | ||
870 | u32 ampdu_status, | ||
871 | struct iwl_rx_mem_buffer *rxb, | ||
872 | struct ieee80211_rx_status *stats) | ||
873 | { | ||
874 | struct sk_buff *skb; | ||
875 | __le16 fc = hdr->frame_control; | ||
876 | |||
877 | /* We only process data packets if the interface is open */ | ||
878 | if (unlikely(!priv->is_open)) { | ||
879 | IWL_DEBUG_DROP_LIMIT(priv, | ||
880 | "Dropping packet while interface is not open.\n"); | ||
881 | return; | ||
882 | } | ||
883 | |||
884 | /* In case of HW accelerated crypto and bad decryption, drop */ | ||
885 | if (!priv->cfg->mod_params->sw_crypto && | ||
886 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | ||
887 | return; | ||
888 | |||
889 | skb = dev_alloc_skb(128); | ||
890 | if (!skb) { | ||
891 | IWL_ERR(priv, "dev_alloc_skb failed\n"); | ||
892 | return; | ||
893 | } | ||
894 | |||
895 | skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); | ||
896 | |||
897 | iwl_update_stats(priv, false, fc, len); | ||
898 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | ||
899 | |||
900 | ieee80211_rx(priv->hw, skb); | ||
901 | priv->alloc_rxb_page--; | ||
902 | rxb->page = NULL; | ||
903 | } | ||
904 | |||
905 | static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | ||
906 | { | ||
907 | u32 decrypt_out = 0; | ||
908 | |||
909 | if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == | ||
910 | RX_RES_STATUS_STATION_FOUND) | ||
911 | decrypt_out |= (RX_RES_STATUS_STATION_FOUND | | ||
912 | RX_RES_STATUS_NO_STATION_INFO_MISMATCH); | ||
913 | |||
914 | decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); | ||
915 | |||
916 | /* packet was not encrypted */ | ||
917 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
918 | RX_RES_STATUS_SEC_TYPE_NONE) | ||
919 | return decrypt_out; | ||
920 | |||
921 | /* packet was encrypted with unknown alg */ | ||
922 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
923 | RX_RES_STATUS_SEC_TYPE_ERR) | ||
924 | return decrypt_out; | ||
925 | |||
926 | /* decryption was not done in HW */ | ||
927 | if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != | ||
928 | RX_MPDU_RES_STATUS_DEC_DONE_MSK) | ||
929 | return decrypt_out; | ||
930 | |||
931 | switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
932 | |||
933 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
934 | /* alg is CCM: check MIC only */ | ||
935 | if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) | ||
936 | /* Bad MIC */ | ||
937 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
938 | else | ||
939 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
940 | |||
941 | break; | ||
942 | |||
943 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
944 | if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { | ||
945 | /* Bad TTAK */ | ||
946 | decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; | ||
947 | break; | ||
948 | } | ||
949 | /* fall through if TTAK OK */ | ||
950 | default: | ||
951 | if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) | ||
952 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
953 | else | ||
954 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
955 | break; | ||
956 | } | ||
957 | |||
958 | IWL_DEBUG_RX(priv, "decrypt_in:0x%x decrypt_out = 0x%x\n", | ||
959 | decrypt_in, decrypt_out); | ||
960 | |||
961 | return decrypt_out; | ||
962 | } | ||
963 | |||
964 | /* Called for REPLY_RX (legacy ABG frames), or | ||
965 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ | ||
966 | static void iwl_rx_reply_rx(struct iwl_priv *priv, | ||
967 | struct iwl_rx_mem_buffer *rxb) | ||
968 | { | ||
969 | struct ieee80211_hdr *header; | ||
970 | struct ieee80211_rx_status rx_status; | ||
971 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
972 | struct iwl_rx_phy_res *phy_res; | ||
973 | __le32 rx_pkt_status; | ||
974 | struct iwl_rx_mpdu_res_start *amsdu; | ||
975 | u32 len; | ||
976 | u32 ampdu_status; | ||
977 | u32 rate_n_flags; | ||
978 | |||
979 | /** | ||
980 | * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently. | ||
981 | * REPLY_RX: physical layer info is in this buffer | ||
982 | * REPLY_RX_MPDU_CMD: physical layer info was sent in separate | ||
983 | * command and cached in priv->last_phy_res | ||
984 | * | ||
985 | * Here we set up local variables depending on which command is | ||
986 | * received. | ||
987 | */ | ||
988 | if (pkt->hdr.cmd == REPLY_RX) { | ||
989 | phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; | ||
990 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) | ||
991 | + phy_res->cfg_phy_cnt); | ||
992 | |||
993 | len = le16_to_cpu(phy_res->byte_count); | ||
994 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) + | ||
995 | phy_res->cfg_phy_cnt + len); | ||
996 | ampdu_status = le32_to_cpu(rx_pkt_status); | ||
997 | } else { | ||
998 | if (!priv->_agn.last_phy_res_valid) { | ||
999 | IWL_ERR(priv, "MPDU frame without cached PHY data\n"); | ||
1000 | return; | ||
1001 | } | ||
1002 | phy_res = &priv->_agn.last_phy_res; | ||
1003 | amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw; | ||
1004 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); | ||
1005 | len = le16_to_cpu(amsdu->byte_count); | ||
1006 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); | ||
1007 | ampdu_status = iwl_translate_rx_status(priv, | ||
1008 | le32_to_cpu(rx_pkt_status)); | ||
1009 | } | ||
1010 | |||
1011 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { | ||
1012 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", | ||
1013 | phy_res->cfg_phy_cnt); | ||
1014 | return; | ||
1015 | } | ||
1016 | |||
1017 | if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || | ||
1018 | !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | ||
1019 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", | ||
1020 | le32_to_cpu(rx_pkt_status)); | ||
1021 | return; | ||
1022 | } | ||
1023 | |||
1024 | /* This will be used in several places later */ | ||
1025 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
1026 | |||
1027 | /* rx_status carries information about the packet to mac80211 */ | ||
1028 | rx_status.mactime = le64_to_cpu(phy_res->timestamp); | ||
1029 | rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
1030 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
1031 | rx_status.freq = | ||
1032 | ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel), | ||
1033 | rx_status.band); | ||
1034 | rx_status.rate_idx = | ||
1035 | iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); | ||
1036 | rx_status.flag = 0; | ||
1037 | |||
1038 | /* TSF isn't reliable. In order to allow smooth user experience, | ||
1039 | * this W/A doesn't propagate it to the mac80211 */ | ||
1040 | /*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/ | ||
1041 | |||
1042 | priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); | ||
1043 | |||
1044 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | ||
1045 | rx_status.signal = priv->cfg->ops->utils->calc_rssi(priv, phy_res); | ||
1046 | |||
1047 | iwl_dbg_log_rx_data_frame(priv, len, header); | ||
1048 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n", | ||
1049 | rx_status.signal, (unsigned long long)rx_status.mactime); | ||
1050 | |||
1051 | /* | ||
1052 | * "antenna number" | ||
1053 | * | ||
1054 | * It seems that the antenna field in the phy flags value | ||
1055 | * is actually a bit field. This is undefined by radiotap, | ||
1056 | * it wants an actual antenna number but I always get "7" | ||
1057 | * for most legacy frames I receive indicating that the | ||
1058 | * same frame was received on all three RX chains. | ||
1059 | * | ||
1060 | * I think this field should be removed in favor of a | ||
1061 | * new 802.11n radiotap field "RX chains" that is defined | ||
1062 | * as a bitmask. | ||
1063 | */ | ||
1064 | rx_status.antenna = | ||
1065 | (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) | ||
1066 | >> RX_RES_PHY_FLAGS_ANTENNA_POS; | ||
1067 | |||
1068 | /* set the preamble flag if appropriate */ | ||
1069 | if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) | ||
1070 | rx_status.flag |= RX_FLAG_SHORTPRE; | ||
1071 | |||
1072 | /* Set up the HT phy flags */ | ||
1073 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
1074 | rx_status.flag |= RX_FLAG_HT; | ||
1075 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
1076 | rx_status.flag |= RX_FLAG_40MHZ; | ||
1077 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
1078 | rx_status.flag |= RX_FLAG_SHORT_GI; | ||
1079 | |||
1080 | iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, | ||
1081 | rxb, &rx_status); | ||
1082 | } | ||
1083 | |||
1084 | /** | ||
1085 | * iwl_setup_rx_handlers - Initialize Rx handler callbacks | ||
1086 | * | ||
1087 | * Setup the RX handlers for each of the reply types sent from the uCode | ||
1088 | * to the host. | ||
1089 | */ | ||
1090 | void iwl_setup_rx_handlers(struct iwl_priv *priv) | ||
1091 | { | ||
1092 | void (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | ||
1093 | |||
1094 | handlers = priv->rx_handlers; | ||
1095 | |||
1096 | handlers[REPLY_ALIVE] = iwl_rx_reply_alive; | ||
1097 | handlers[REPLY_ERROR] = iwl_rx_reply_error; | ||
1098 | handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; | ||
1099 | handlers[SPECTRUM_MEASURE_NOTIFICATION] = iwl_rx_spectrum_measure_notif; | ||
1100 | handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; | ||
1101 | handlers[PM_DEBUG_STATISTIC_NOTIFIC] = iwl_rx_pm_debug_statistics_notif; | ||
1102 | handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif; | ||
1103 | |||
1104 | /* | ||
1105 | * The same handler is used for both the REPLY to a discrete | ||
1106 | * statistics request from the host as well as for the periodic | ||
1107 | * statistics notifications (after received beacons) from the uCode. | ||
1108 | */ | ||
1109 | handlers[REPLY_STATISTICS_CMD] = iwl_rx_reply_statistics; | ||
1110 | handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; | ||
1111 | |||
1112 | iwl_setup_rx_scan_handlers(priv); | ||
1113 | |||
1114 | handlers[CARD_STATE_NOTIFICATION] = iwl_rx_card_state_notif; | ||
1115 | handlers[MISSED_BEACONS_NOTIFICATION] = iwl_rx_missed_beacon_notif; | ||
1116 | |||
1117 | /* Rx handlers */ | ||
1118 | handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy; | ||
1119 | handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx; | ||
1120 | |||
1121 | /* block ack */ | ||
1122 | handlers[REPLY_COMPRESSED_BA] = iwlagn_rx_reply_compressed_ba; | ||
1123 | |||
1124 | /* Set up hardware specific Rx handlers */ | ||
1125 | priv->cfg->ops->lib->rx_handler_setup(priv); | ||
1126 | } | ||