diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-rx.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rx.c | 95 |
1 files changed, 62 insertions, 33 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 2ee61031e207..bcd7f64683aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -130,8 +130,9 @@ const char *get_cmd_string(u8 cmd) | |||
130 | * | 130 | * |
131 | ******************************************************************************/ | 131 | ******************************************************************************/ |
132 | 132 | ||
133 | static void iwl_rx_reply_error(struct iwl_priv *priv, | 133 | static int iwl_rx_reply_error(struct iwl_priv *priv, |
134 | struct iwl_rx_mem_buffer *rxb) | 134 | struct iwl_rx_mem_buffer *rxb, |
135 | struct iwl_device_cmd *cmd) | ||
135 | { | 136 | { |
136 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 137 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
137 | 138 | ||
@@ -142,9 +143,11 @@ static void iwl_rx_reply_error(struct iwl_priv *priv, | |||
142 | pkt->u.err_resp.cmd_id, | 143 | pkt->u.err_resp.cmd_id, |
143 | le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num), | 144 | le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num), |
144 | le32_to_cpu(pkt->u.err_resp.error_info)); | 145 | le32_to_cpu(pkt->u.err_resp.error_info)); |
146 | return 0; | ||
145 | } | 147 | } |
146 | 148 | ||
147 | static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | 149 | static int iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, |
150 | struct iwl_device_cmd *cmd) | ||
148 | { | 151 | { |
149 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 152 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
150 | struct iwl_csa_notification *csa = &(pkt->u.csa_notif); | 153 | struct iwl_csa_notification *csa = &(pkt->u.csa_notif); |
@@ -156,7 +159,7 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
156 | struct iwl_rxon_cmd *rxon = (void *)&ctx->active; | 159 | struct iwl_rxon_cmd *rxon = (void *)&ctx->active; |
157 | 160 | ||
158 | if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status)) | 161 | if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status)) |
159 | return; | 162 | return 0; |
160 | 163 | ||
161 | if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) { | 164 | if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) { |
162 | rxon->channel = csa->channel; | 165 | rxon->channel = csa->channel; |
@@ -169,11 +172,13 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
169 | le16_to_cpu(csa->channel)); | 172 | le16_to_cpu(csa->channel)); |
170 | iwl_chswitch_done(priv, false); | 173 | iwl_chswitch_done(priv, false); |
171 | } | 174 | } |
175 | return 0; | ||
172 | } | 176 | } |
173 | 177 | ||
174 | 178 | ||
175 | static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | 179 | static int iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, |
176 | struct iwl_rx_mem_buffer *rxb) | 180 | struct iwl_rx_mem_buffer *rxb, |
181 | struct iwl_device_cmd *cmd) | ||
177 | { | 182 | { |
178 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 183 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
179 | struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); | 184 | struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); |
@@ -181,15 +186,17 @@ static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | |||
181 | if (!report->state) { | 186 | if (!report->state) { |
182 | IWL_DEBUG_11H(priv, | 187 | IWL_DEBUG_11H(priv, |
183 | "Spectrum Measure Notification: Start\n"); | 188 | "Spectrum Measure Notification: Start\n"); |
184 | return; | 189 | return 0; |
185 | } | 190 | } |
186 | 191 | ||
187 | memcpy(&priv->measure_report, report, sizeof(*report)); | 192 | memcpy(&priv->measure_report, report, sizeof(*report)); |
188 | priv->measurement_status |= MEASUREMENT_READY; | 193 | priv->measurement_status |= MEASUREMENT_READY; |
194 | return 0; | ||
189 | } | 195 | } |
190 | 196 | ||
191 | static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, | 197 | static int iwl_rx_pm_sleep_notif(struct iwl_priv *priv, |
192 | struct iwl_rx_mem_buffer *rxb) | 198 | struct iwl_rx_mem_buffer *rxb, |
199 | struct iwl_device_cmd *cmd) | ||
193 | { | 200 | { |
194 | #ifdef CONFIG_IWLWIFI_DEBUG | 201 | #ifdef CONFIG_IWLWIFI_DEBUG |
195 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 202 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
@@ -197,10 +204,12 @@ static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, | |||
197 | IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n", | 204 | IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n", |
198 | sleep->pm_sleep_mode, sleep->pm_wakeup_src); | 205 | sleep->pm_sleep_mode, sleep->pm_wakeup_src); |
199 | #endif | 206 | #endif |
207 | return 0; | ||
200 | } | 208 | } |
201 | 209 | ||
202 | static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, | 210 | static int iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, |
203 | struct iwl_rx_mem_buffer *rxb) | 211 | struct iwl_rx_mem_buffer *rxb, |
212 | struct iwl_device_cmd *cmd) | ||
204 | { | 213 | { |
205 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 214 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
206 | u32 __maybe_unused len = | 215 | u32 __maybe_unused len = |
@@ -209,10 +218,12 @@ static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, | |||
209 | "notification for %s:\n", len, | 218 | "notification for %s:\n", len, |
210 | get_cmd_string(pkt->hdr.cmd)); | 219 | get_cmd_string(pkt->hdr.cmd)); |
211 | iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len); | 220 | iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len); |
221 | return 0; | ||
212 | } | 222 | } |
213 | 223 | ||
214 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, | 224 | static int iwl_rx_beacon_notif(struct iwl_priv *priv, |
215 | struct iwl_rx_mem_buffer *rxb) | 225 | struct iwl_rx_mem_buffer *rxb, |
226 | struct iwl_device_cmd *cmd) | ||
216 | { | 227 | { |
217 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 228 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
218 | struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw; | 229 | struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw; |
@@ -233,6 +244,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, | |||
233 | 244 | ||
234 | if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) | 245 | if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) |
235 | queue_work(priv->shrd->workqueue, &priv->beacon_update); | 246 | queue_work(priv->shrd->workqueue, &priv->beacon_update); |
247 | return 0; | ||
236 | } | 248 | } |
237 | 249 | ||
238 | /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ | 250 | /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ |
@@ -475,8 +487,9 @@ iwl_accumulative_statistics(struct iwl_priv *priv, | |||
475 | } | 487 | } |
476 | #endif | 488 | #endif |
477 | 489 | ||
478 | static void iwl_rx_statistics(struct iwl_priv *priv, | 490 | static int iwl_rx_statistics(struct iwl_priv *priv, |
479 | struct iwl_rx_mem_buffer *rxb) | 491 | struct iwl_rx_mem_buffer *rxb, |
492 | struct iwl_device_cmd *cmd) | ||
480 | { | 493 | { |
481 | unsigned long stamp = jiffies; | 494 | unsigned long stamp = jiffies; |
482 | const int reg_recalib_period = 60; | 495 | const int reg_recalib_period = 60; |
@@ -530,7 +543,7 @@ static void iwl_rx_statistics(struct iwl_priv *priv, | |||
530 | WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n", | 543 | WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n", |
531 | len, sizeof(struct iwl_bt_notif_statistics), | 544 | len, sizeof(struct iwl_bt_notif_statistics), |
532 | sizeof(struct iwl_notif_statistics)); | 545 | sizeof(struct iwl_notif_statistics)); |
533 | return; | 546 | return 0; |
534 | } | 547 | } |
535 | 548 | ||
536 | change = common->temperature != priv->statistics.common.temperature || | 549 | change = common->temperature != priv->statistics.common.temperature || |
@@ -573,10 +586,12 @@ static void iwl_rx_statistics(struct iwl_priv *priv, | |||
573 | } | 586 | } |
574 | if (priv->cfg->lib->temperature && change) | 587 | if (priv->cfg->lib->temperature && change) |
575 | priv->cfg->lib->temperature(priv); | 588 | priv->cfg->lib->temperature(priv); |
589 | return 0; | ||
576 | } | 590 | } |
577 | 591 | ||
578 | static void iwl_rx_reply_statistics(struct iwl_priv *priv, | 592 | static int iwl_rx_reply_statistics(struct iwl_priv *priv, |
579 | struct iwl_rx_mem_buffer *rxb) | 593 | struct iwl_rx_mem_buffer *rxb, |
594 | struct iwl_device_cmd *cmd) | ||
580 | { | 595 | { |
581 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 596 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
582 | 597 | ||
@@ -591,13 +606,15 @@ static void iwl_rx_reply_statistics(struct iwl_priv *priv, | |||
591 | #endif | 606 | #endif |
592 | IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); | 607 | IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); |
593 | } | 608 | } |
594 | iwl_rx_statistics(priv, rxb); | 609 | iwl_rx_statistics(priv, rxb, cmd); |
610 | return 0; | ||
595 | } | 611 | } |
596 | 612 | ||
597 | /* Handle notification from uCode that card's power state is changing | 613 | /* Handle notification from uCode that card's power state is changing |
598 | * due to software, hardware, or critical temperature RFKILL */ | 614 | * due to software, hardware, or critical temperature RFKILL */ |
599 | static void iwl_rx_card_state_notif(struct iwl_priv *priv, | 615 | static int iwl_rx_card_state_notif(struct iwl_priv *priv, |
600 | struct iwl_rx_mem_buffer *rxb) | 616 | struct iwl_rx_mem_buffer *rxb, |
617 | struct iwl_device_cmd *cmd) | ||
601 | { | 618 | { |
602 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 619 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
603 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); | 620 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); |
@@ -645,10 +662,12 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, | |||
645 | test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); | 662 | test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); |
646 | else | 663 | else |
647 | wake_up(&priv->shrd->wait_command_queue); | 664 | wake_up(&priv->shrd->wait_command_queue); |
665 | return 0; | ||
648 | } | 666 | } |
649 | 667 | ||
650 | static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | 668 | static int iwl_rx_missed_beacon_notif(struct iwl_priv *priv, |
651 | struct iwl_rx_mem_buffer *rxb) | 669 | struct iwl_rx_mem_buffer *rxb, |
670 | struct iwl_device_cmd *cmd) | ||
652 | 671 | ||
653 | { | 672 | { |
654 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 673 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
@@ -666,18 +685,21 @@ static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | |||
666 | if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) | 685 | if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) |
667 | iwl_init_sensitivity(priv); | 686 | iwl_init_sensitivity(priv); |
668 | } | 687 | } |
688 | return 0; | ||
669 | } | 689 | } |
670 | 690 | ||
671 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). | 691 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). |
672 | * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ | 692 | * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ |
673 | static void iwl_rx_reply_rx_phy(struct iwl_priv *priv, | 693 | static int iwl_rx_reply_rx_phy(struct iwl_priv *priv, |
674 | struct iwl_rx_mem_buffer *rxb) | 694 | struct iwl_rx_mem_buffer *rxb, |
695 | struct iwl_device_cmd *cmd) | ||
675 | { | 696 | { |
676 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 697 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
677 | 698 | ||
678 | priv->last_phy_res_valid = true; | 699 | priv->last_phy_res_valid = true; |
679 | memcpy(&priv->last_phy_res, pkt->u.raw, | 700 | memcpy(&priv->last_phy_res, pkt->u.raw, |
680 | sizeof(struct iwl_rx_phy_res)); | 701 | sizeof(struct iwl_rx_phy_res)); |
702 | return 0; | ||
681 | } | 703 | } |
682 | 704 | ||
683 | /* | 705 | /* |
@@ -892,8 +914,9 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, | |||
892 | 914 | ||
893 | /* Called for REPLY_RX (legacy ABG frames), or | 915 | /* Called for REPLY_RX (legacy ABG frames), or |
894 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ | 916 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ |
895 | static void iwl_rx_reply_rx(struct iwl_priv *priv, | 917 | static int iwl_rx_reply_rx(struct iwl_priv *priv, |
896 | struct iwl_rx_mem_buffer *rxb) | 918 | struct iwl_rx_mem_buffer *rxb, |
919 | struct iwl_device_cmd *cmd) | ||
897 | { | 920 | { |
898 | struct ieee80211_hdr *header; | 921 | struct ieee80211_hdr *header; |
899 | struct ieee80211_rx_status rx_status; | 922 | struct ieee80211_rx_status rx_status; |
@@ -926,7 +949,7 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
926 | } else { | 949 | } else { |
927 | if (!priv->last_phy_res_valid) { | 950 | if (!priv->last_phy_res_valid) { |
928 | IWL_ERR(priv, "MPDU frame without cached PHY data\n"); | 951 | IWL_ERR(priv, "MPDU frame without cached PHY data\n"); |
929 | return; | 952 | return 0; |
930 | } | 953 | } |
931 | phy_res = &priv->last_phy_res; | 954 | phy_res = &priv->last_phy_res; |
932 | amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw; | 955 | amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw; |
@@ -940,14 +963,14 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
940 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { | 963 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { |
941 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", | 964 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", |
942 | phy_res->cfg_phy_cnt); | 965 | phy_res->cfg_phy_cnt); |
943 | return; | 966 | return 0; |
944 | } | 967 | } |
945 | 968 | ||
946 | if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || | 969 | if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || |
947 | !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | 970 | !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { |
948 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", | 971 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", |
949 | le32_to_cpu(rx_pkt_status)); | 972 | le32_to_cpu(rx_pkt_status)); |
950 | return; | 973 | return 0; |
951 | } | 974 | } |
952 | 975 | ||
953 | /* This will be used in several places later */ | 976 | /* This will be used in several places later */ |
@@ -1008,6 +1031,7 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
1008 | 1031 | ||
1009 | iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, | 1032 | iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, |
1010 | rxb, &rx_status); | 1033 | rxb, &rx_status); |
1034 | return 0; | ||
1011 | } | 1035 | } |
1012 | 1036 | ||
1013 | /** | 1037 | /** |
@@ -1018,7 +1042,8 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
1018 | */ | 1042 | */ |
1019 | void iwl_setup_rx_handlers(struct iwl_priv *priv) | 1043 | void iwl_setup_rx_handlers(struct iwl_priv *priv) |
1020 | { | 1044 | { |
1021 | void (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | 1045 | int (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, |
1046 | struct iwl_device_cmd *cmd); | ||
1022 | 1047 | ||
1023 | handlers = priv->rx_handlers; | 1048 | handlers = priv->rx_handlers; |
1024 | 1049 | ||
@@ -1028,6 +1053,7 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
1028 | handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; | 1053 | handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; |
1029 | handlers[PM_DEBUG_STATISTIC_NOTIFIC] = iwl_rx_pm_debug_statistics_notif; | 1054 | handlers[PM_DEBUG_STATISTIC_NOTIFIC] = iwl_rx_pm_debug_statistics_notif; |
1030 | handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif; | 1055 | handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif; |
1056 | handlers[REPLY_ADD_STA] = iwl_add_sta_callback; | ||
1031 | 1057 | ||
1032 | /* | 1058 | /* |
1033 | * The same handler is used for both the REPLY to a discrete | 1059 | * The same handler is used for both the REPLY to a discrete |
@@ -1065,9 +1091,11 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
1065 | 1091 | ||
1066 | } | 1092 | } |
1067 | 1093 | ||
1068 | void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | 1094 | int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, |
1095 | struct iwl_device_cmd *cmd) | ||
1069 | { | 1096 | { |
1070 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 1097 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
1098 | int err = 0; | ||
1071 | 1099 | ||
1072 | /* | 1100 | /* |
1073 | * Do the notification wait before RX handlers so | 1101 | * Do the notification wait before RX handlers so |
@@ -1102,11 +1130,12 @@ void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1102 | * rx_handlers table. See iwl_setup_rx_handlers() */ | 1130 | * rx_handlers table. See iwl_setup_rx_handlers() */ |
1103 | if (priv->rx_handlers[pkt->hdr.cmd]) { | 1131 | if (priv->rx_handlers[pkt->hdr.cmd]) { |
1104 | priv->rx_handlers_stats[pkt->hdr.cmd]++; | 1132 | priv->rx_handlers_stats[pkt->hdr.cmd]++; |
1105 | priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); | 1133 | err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd); |
1106 | } else { | 1134 | } else { |
1107 | /* No handling needed */ | 1135 | /* No handling needed */ |
1108 | IWL_DEBUG_RX(priv, | 1136 | IWL_DEBUG_RX(priv, |
1109 | "No handler needed for %s, 0x%02x\n", | 1137 | "No handler needed for %s, 0x%02x\n", |
1110 | get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); | 1138 | get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); |
1111 | } | 1139 | } |
1140 | return err; | ||
1112 | } | 1141 | } |