diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/htt_rx.c')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/htt_rx.c | 136 |
1 files changed, 74 insertions, 62 deletions
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 4ca19f93b021..a994a4f9dc1a 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c | |||
@@ -655,14 +655,12 @@ static const u8 rx_legacy_rate_idx[] = { | |||
655 | 5, /* 0x0F - 9Mbps */ | 655 | 5, /* 0x0F - 9Mbps */ |
656 | }; | 656 | }; |
657 | 657 | ||
658 | static void ath10k_htt_rx_h_rates(struct ath10k *ar, struct htt_rx_info *info, | 658 | static void ath10k_htt_rx_h_rates(struct ath10k *ar, |
659 | enum ieee80211_band band, | 659 | enum ieee80211_band band, |
660 | u8 info0, u32 info1, u32 info2, | ||
660 | struct ieee80211_rx_status *status) | 661 | struct ieee80211_rx_status *status) |
661 | { | 662 | { |
662 | u8 cck, rate, rate_idx, bw, sgi, mcs, nss; | 663 | u8 cck, rate, rate_idx, bw, sgi, mcs, nss; |
663 | u8 info0 = info->rate.info0; | ||
664 | u32 info1 = info->rate.info1; | ||
665 | u32 info2 = info->rate.info2; | ||
666 | u8 preamble = 0; | 664 | u8 preamble = 0; |
667 | 665 | ||
668 | /* Check if valid fields */ | 666 | /* Check if valid fields */ |
@@ -749,6 +747,27 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, struct htt_rx_info *info, | |||
749 | } | 747 | } |
750 | } | 748 | } |
751 | 749 | ||
750 | static void ath10k_htt_rx_h_protected(struct ath10k_htt *htt, | ||
751 | struct htt_rx_info *info, | ||
752 | enum htt_rx_mpdu_encrypt_type enctype) | ||
753 | { | ||
754 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)info->skb->data; | ||
755 | |||
756 | |||
757 | if (enctype == HTT_RX_MPDU_ENCRYPT_NONE) { | ||
758 | info->rx_status.flag &= ~(RX_FLAG_DECRYPTED | | ||
759 | RX_FLAG_IV_STRIPPED | | ||
760 | RX_FLAG_MMIC_STRIPPED); | ||
761 | return; | ||
762 | } | ||
763 | |||
764 | info->rx_status.flag |= RX_FLAG_DECRYPTED | | ||
765 | RX_FLAG_IV_STRIPPED | | ||
766 | RX_FLAG_MMIC_STRIPPED; | ||
767 | hdr->frame_control = __cpu_to_le16(__le16_to_cpu(hdr->frame_control) & | ||
768 | ~IEEE80211_FCTL_PROTECTED); | ||
769 | } | ||
770 | |||
752 | static bool ath10k_htt_rx_h_channel(struct ath10k *ar, | 771 | static bool ath10k_htt_rx_h_channel(struct ath10k *ar, |
753 | struct ieee80211_rx_status *status) | 772 | struct ieee80211_rx_status *status) |
754 | { | 773 | { |
@@ -772,38 +791,10 @@ static bool ath10k_htt_rx_h_channel(struct ath10k *ar, | |||
772 | static void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info) | 791 | static void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info) |
773 | { | 792 | { |
774 | struct ieee80211_rx_status *status; | 793 | struct ieee80211_rx_status *status; |
775 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)info->skb->data; | ||
776 | 794 | ||
777 | status = IEEE80211_SKB_RXCB(info->skb); | 795 | status = IEEE80211_SKB_RXCB(info->skb); |
778 | memcpy(status, &info->rx_status, sizeof(*status)); | 796 | memcpy(status, &info->rx_status, sizeof(*status)); |
779 | 797 | ||
780 | if (info->encrypt_type != HTT_RX_MPDU_ENCRYPT_NONE) { | ||
781 | status->flag |= RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED | | ||
782 | RX_FLAG_MMIC_STRIPPED; | ||
783 | hdr->frame_control = __cpu_to_le16( | ||
784 | __le16_to_cpu(hdr->frame_control) & | ||
785 | ~IEEE80211_FCTL_PROTECTED); | ||
786 | } | ||
787 | |||
788 | if (info->mic_err) | ||
789 | status->flag |= RX_FLAG_MMIC_ERROR; | ||
790 | |||
791 | if (info->fcs_err) | ||
792 | status->flag |= RX_FLAG_FAILED_FCS_CRC; | ||
793 | |||
794 | if (info->amsdu_more) | ||
795 | status->flag |= RX_FLAG_AMSDU_MORE; | ||
796 | |||
797 | status->signal = info->signal; | ||
798 | |||
799 | ath10k_htt_rx_h_rates(ar, info, status->band, status); | ||
800 | |||
801 | if (info->rate.info0 & HTT_RX_INDICATION_INFO0_END_VALID) { | ||
802 | /* TSF available only in 32-bit */ | ||
803 | status->mactime = info->tsf & 0xffffffff; | ||
804 | status->flag |= RX_FLAG_MACTIME_END; | ||
805 | } | ||
806 | |||
807 | ath10k_dbg(ATH10K_DBG_DATA, | 798 | ath10k_dbg(ATH10K_DBG_DATA, |
808 | "rx skb %p len %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i\n", | 799 | "rx skb %p len %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i\n", |
809 | info->skb, | 800 | info->skb, |
@@ -817,7 +808,8 @@ static void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info) | |||
817 | status->rate_idx, | 808 | status->rate_idx, |
818 | status->vht_nss, | 809 | status->vht_nss, |
819 | status->freq, | 810 | status->freq, |
820 | status->band, status->flag, info->fcs_err); | 811 | status->band, status->flag, |
812 | !!(status->flag & RX_FLAG_FAILED_FCS_CRC)); | ||
821 | ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ", | 813 | ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ", |
822 | info->skb->data, info->skb->len); | 814 | info->skb->data, info->skb->len); |
823 | 815 | ||
@@ -917,12 +909,14 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, | |||
917 | } | 909 | } |
918 | 910 | ||
919 | info->skb = skb; | 911 | info->skb = skb; |
920 | info->encrypt_type = enctype; | 912 | ath10k_htt_rx_h_protected(htt, info, enctype); |
921 | skb = skb->next; | 913 | skb = skb->next; |
922 | info->skb->next = NULL; | 914 | info->skb->next = NULL; |
923 | 915 | ||
924 | if (skb) | 916 | if (skb) |
925 | info->amsdu_more = true; | 917 | info->rx_status.flag |= RX_FLAG_AMSDU_MORE; |
918 | else | ||
919 | info->rx_status.flag &= ~RX_FLAG_AMSDU_MORE; | ||
926 | 920 | ||
927 | ath10k_process_rx(htt->ar, info); | 921 | ath10k_process_rx(htt->ar, info); |
928 | } | 922 | } |
@@ -997,7 +991,7 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt, struct htt_rx_info *info) | |||
997 | } | 991 | } |
998 | 992 | ||
999 | info->skb = skb; | 993 | info->skb = skb; |
1000 | info->encrypt_type = enctype; | 994 | ath10k_htt_rx_h_protected(htt, info, enctype); |
1001 | 995 | ||
1002 | ath10k_process_rx(htt->ar, info); | 996 | ath10k_process_rx(htt->ar, info); |
1003 | } | 997 | } |
@@ -1142,11 +1136,9 @@ static int ath10k_unchain_msdu(struct sk_buff *msdu_head) | |||
1142 | 1136 | ||
1143 | static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt, | 1137 | static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt, |
1144 | struct sk_buff *head, | 1138 | struct sk_buff *head, |
1145 | struct htt_rx_info *info, | 1139 | enum htt_rx_mpdu_status status, |
1146 | bool channel_set) | 1140 | bool channel_set) |
1147 | { | 1141 | { |
1148 | enum htt_rx_mpdu_status status = info->status; | ||
1149 | |||
1150 | if (!head) { | 1142 | if (!head) { |
1151 | ath10k_warn("htt rx no data!\n"); | 1143 | ath10k_warn("htt rx no data!\n"); |
1152 | return false; | 1144 | return false; |
@@ -1200,11 +1192,12 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
1200 | { | 1192 | { |
1201 | struct htt_rx_info info; | 1193 | struct htt_rx_info info; |
1202 | struct htt_rx_indication_mpdu_range *mpdu_ranges; | 1194 | struct htt_rx_indication_mpdu_range *mpdu_ranges; |
1195 | enum htt_rx_mpdu_status status; | ||
1203 | struct ieee80211_hdr *hdr; | 1196 | struct ieee80211_hdr *hdr; |
1204 | int num_mpdu_ranges; | 1197 | int num_mpdu_ranges; |
1205 | int fw_desc_len; | 1198 | int fw_desc_len; |
1206 | u8 *fw_desc; | 1199 | u8 *fw_desc; |
1207 | bool channel_set; | 1200 | bool channel_set, fcs_err, mic_err; |
1208 | int i, j; | 1201 | int i, j; |
1209 | 1202 | ||
1210 | lockdep_assert_held(&htt->rx_ring.lock); | 1203 | lockdep_assert_held(&htt->rx_ring.lock); |
@@ -1219,15 +1212,25 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
1219 | mpdu_ranges = htt_rx_ind_get_mpdu_ranges(rx); | 1212 | mpdu_ranges = htt_rx_ind_get_mpdu_ranges(rx); |
1220 | 1213 | ||
1221 | /* Fill this once, while this is per-ppdu */ | 1214 | /* Fill this once, while this is per-ppdu */ |
1222 | info.signal = ATH10K_DEFAULT_NOISE_FLOOR; | 1215 | info.rx_status.signal = ATH10K_DEFAULT_NOISE_FLOOR; |
1223 | info.signal += rx->ppdu.combined_rssi; | 1216 | info.rx_status.signal += rx->ppdu.combined_rssi; |
1217 | |||
1218 | if (rx->ppdu.info0 & HTT_RX_INDICATION_INFO0_END_VALID) { | ||
1219 | /* TSF available only in 32-bit */ | ||
1220 | info.rx_status.mactime = | ||
1221 | __le32_to_cpu(rx->ppdu.tsf) & 0xffffffff; | ||
1222 | info.rx_status.flag |= RX_FLAG_MACTIME_END; | ||
1223 | } | ||
1224 | 1224 | ||
1225 | channel_set = ath10k_htt_rx_h_channel(htt->ar, &info.rx_status); | 1225 | channel_set = ath10k_htt_rx_h_channel(htt->ar, &info.rx_status); |
1226 | 1226 | ||
1227 | info.rate.info0 = rx->ppdu.info0; | 1227 | if (channel_set) { |
1228 | info.rate.info1 = __le32_to_cpu(rx->ppdu.info1); | 1228 | ath10k_htt_rx_h_rates(htt->ar, info.rx_status.band, |
1229 | info.rate.info2 = __le32_to_cpu(rx->ppdu.info2); | 1229 | rx->ppdu.info0, |
1230 | info.tsf = __le32_to_cpu(rx->ppdu.tsf); | 1230 | __le32_to_cpu(rx->ppdu.info1), |
1231 | __le32_to_cpu(rx->ppdu.info2), | ||
1232 | &info.rx_status); | ||
1233 | } | ||
1231 | 1234 | ||
1232 | ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt rx ind: ", | 1235 | ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt rx ind: ", |
1233 | rx, sizeof(*rx) + | 1236 | rx, sizeof(*rx) + |
@@ -1235,7 +1238,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
1235 | num_mpdu_ranges)); | 1238 | num_mpdu_ranges)); |
1236 | 1239 | ||
1237 | for (i = 0; i < num_mpdu_ranges; i++) { | 1240 | for (i = 0; i < num_mpdu_ranges; i++) { |
1238 | info.status = mpdu_ranges[i].mpdu_range_status; | 1241 | status = mpdu_ranges[i].mpdu_range_status; |
1239 | 1242 | ||
1240 | for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) { | 1243 | for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) { |
1241 | struct sk_buff *msdu_head, *msdu_tail; | 1244 | struct sk_buff *msdu_head, *msdu_tail; |
@@ -1250,7 +1253,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
1250 | &msdu_tail); | 1253 | &msdu_tail); |
1251 | 1254 | ||
1252 | if (!ath10k_htt_rx_amsdu_allowed(htt, msdu_head, | 1255 | if (!ath10k_htt_rx_amsdu_allowed(htt, msdu_head, |
1253 | &info, | 1256 | status, |
1254 | channel_set)) { | 1257 | channel_set)) { |
1255 | ath10k_htt_rx_free_msdu_chain(msdu_head); | 1258 | ath10k_htt_rx_free_msdu_chain(msdu_head); |
1256 | continue; | 1259 | continue; |
@@ -1263,14 +1266,24 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
1263 | } | 1266 | } |
1264 | 1267 | ||
1265 | info.skb = msdu_head; | 1268 | info.skb = msdu_head; |
1266 | info.fcs_err = ath10k_htt_rx_has_fcs_err(msdu_head); | ||
1267 | info.mic_err = ath10k_htt_rx_has_mic_err(msdu_head); | ||
1268 | 1269 | ||
1269 | if (info.fcs_err) | 1270 | fcs_err = ath10k_htt_rx_has_fcs_err(msdu_head); |
1271 | if (fcs_err) | ||
1272 | info.rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; | ||
1273 | else | ||
1274 | info.rx_status.flag &= ~RX_FLAG_FAILED_FCS_CRC; | ||
1275 | |||
1276 | mic_err = ath10k_htt_rx_has_mic_err(msdu_head); | ||
1277 | if (mic_err) | ||
1278 | info.rx_status.flag |= RX_FLAG_MMIC_ERROR; | ||
1279 | else | ||
1280 | info.rx_status.flag &= ~RX_FLAG_MMIC_ERROR; | ||
1281 | |||
1282 | if (fcs_err) | ||
1270 | ath10k_dbg(ATH10K_DBG_HTT, | 1283 | ath10k_dbg(ATH10K_DBG_HTT, |
1271 | "htt rx has FCS err\n"); | 1284 | "htt rx has FCS err\n"); |
1272 | 1285 | ||
1273 | if (info.mic_err) | 1286 | if (mic_err) |
1274 | ath10k_dbg(ATH10K_DBG_HTT, | 1287 | ath10k_dbg(ATH10K_DBG_HTT, |
1275 | "htt rx has MIC err\n"); | 1288 | "htt rx has MIC err\n"); |
1276 | 1289 | ||
@@ -1290,6 +1303,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, | |||
1290 | struct htt_rx_fragment_indication *frag) | 1303 | struct htt_rx_fragment_indication *frag) |
1291 | { | 1304 | { |
1292 | struct sk_buff *msdu_head, *msdu_tail; | 1305 | struct sk_buff *msdu_head, *msdu_tail; |
1306 | enum htt_rx_mpdu_encrypt_type enctype; | ||
1293 | struct htt_rx_desc *rxd; | 1307 | struct htt_rx_desc *rxd; |
1294 | enum rx_msdu_decap_format fmt; | 1308 | enum rx_msdu_decap_format fmt; |
1295 | struct htt_rx_info info = {}; | 1309 | struct htt_rx_info info = {}; |
@@ -1343,15 +1357,13 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, | |||
1343 | } | 1357 | } |
1344 | 1358 | ||
1345 | info.skb = msdu_head; | 1359 | info.skb = msdu_head; |
1346 | info.status = HTT_RX_IND_MPDU_STATUS_OK; | 1360 | enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), |
1347 | info.encrypt_type = MS(__le32_to_cpu(rxd->mpdu_start.info0), | 1361 | RX_MPDU_START_INFO0_ENCRYPT_TYPE); |
1348 | RX_MPDU_START_INFO0_ENCRYPT_TYPE); | 1362 | ath10k_htt_rx_h_protected(htt, &info, enctype); |
1349 | info.skb->ip_summed = ath10k_htt_rx_get_csum_state(info.skb); | 1363 | info.skb->ip_summed = ath10k_htt_rx_get_csum_state(info.skb); |
1350 | 1364 | ||
1351 | if (tkip_mic_err) { | 1365 | if (tkip_mic_err) |
1352 | ath10k_warn("tkip mic error\n"); | 1366 | ath10k_warn("tkip mic error\n"); |
1353 | info.status = HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR; | ||
1354 | } | ||
1355 | 1367 | ||
1356 | if (decrypt_err) { | 1368 | if (decrypt_err) { |
1357 | ath10k_warn("decryption err in fragmented rx\n"); | 1369 | ath10k_warn("decryption err in fragmented rx\n"); |
@@ -1359,9 +1371,9 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, | |||
1359 | goto end; | 1371 | goto end; |
1360 | } | 1372 | } |
1361 | 1373 | ||
1362 | if (info.encrypt_type != HTT_RX_MPDU_ENCRYPT_NONE) { | 1374 | if (enctype != HTT_RX_MPDU_ENCRYPT_NONE) { |
1363 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1375 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1364 | paramlen = ath10k_htt_rx_crypto_param_len(info.encrypt_type); | 1376 | paramlen = ath10k_htt_rx_crypto_param_len(enctype); |
1365 | 1377 | ||
1366 | /* It is more efficient to move the header than the payload */ | 1378 | /* It is more efficient to move the header than the payload */ |
1367 | memmove((void *)info.skb->data + paramlen, | 1379 | memmove((void *)info.skb->data + paramlen, |
@@ -1375,11 +1387,11 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, | |||
1375 | trim = 4; | 1387 | trim = 4; |
1376 | 1388 | ||
1377 | /* remove crypto trailer */ | 1389 | /* remove crypto trailer */ |
1378 | trim += ath10k_htt_rx_crypto_tail_len(info.encrypt_type); | 1390 | trim += ath10k_htt_rx_crypto_tail_len(enctype); |
1379 | 1391 | ||
1380 | /* last fragment of TKIP frags has MIC */ | 1392 | /* last fragment of TKIP frags has MIC */ |
1381 | if (!ieee80211_has_morefrags(hdr->frame_control) && | 1393 | if (!ieee80211_has_morefrags(hdr->frame_control) && |
1382 | info.encrypt_type == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) | 1394 | enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) |
1383 | trim += 8; | 1395 | trim += 8; |
1384 | 1396 | ||
1385 | if (trim > info.skb->len) { | 1397 | if (trim > info.skb->len) { |