--- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -85,6 +85,12 @@ static bool ath11k_dp_rx_h_attn_msdu_don __le32_to_cpu(desc->attention.info2)); } +static bool ath11k_dp_rx_h_attn_first_mpdu(struct hal_rx_desc *desc) +{ + return !!FIELD_GET(RX_ATTENTION_INFO1_FIRST_MPDU, + __le32_to_cpu(desc->attention.info1)); +} + static bool ath11k_dp_rx_h_attn_l4_cksum_fail(struct hal_rx_desc *desc) { return !!FIELD_GET(RX_ATTENTION_INFO1_TCP_UDP_CKSUM_FAIL, @@ -1683,6 +1689,50 @@ static struct sk_buff *ath11k_dp_rx_get_ return NULL; } +static void ath11k_dp_dump_msdu_info(struct ath11k *ar, struct hal_rx_desc *rx_desc, + struct ath11k_skb_rxcb *rxcb) +{ + bool ip_csum_fail, l4_csum_fail, is_decrypted; + u32 decap_format, err_bitmap, l2_hdr_offset; + bool mpdu_len_err, msdu_done, first_mpdu; + enum hal_encrypt_type enctype; + u8 *hdr_status; + u16 msdu_len; + int i; + + hdr_status = ath11k_dp_rx_h_80211_hdr(rx_desc); + msdu_len = ath11k_dp_rx_h_msdu_start_msdu_len(rx_desc); + rxcb->is_first_msdu = ath11k_dp_rx_h_msdu_end_first_msdu(rx_desc); + rxcb->is_last_msdu = ath11k_dp_rx_h_msdu_end_last_msdu(rx_desc); + + if (rxcb->is_first_msdu) { + decap_format = ath11k_dp_rxdesc_get_decap_format(rx_desc); + mpdu_len_err = !!ath11k_dp_rxdesc_get_mpdulen_err(rx_desc); + first_mpdu = ath11k_dp_rx_h_attn_first_mpdu(rx_desc); + } + + ip_csum_fail = ath11k_dp_rx_h_attn_ip_cksum_fail(rx_desc); + l4_csum_fail = ath11k_dp_rx_h_attn_l4_cksum_fail(rx_desc); + is_decrypted = ath11k_dp_rx_h_attn_is_decrypted(rx_desc); + enctype = ath11k_dp_rx_h_mpdu_start_enctype(rx_desc); + err_bitmap = ath11k_dp_rx_h_attn_mpdu_err(rx_desc); + + if (rxcb->is_last_msdu) { + msdu_done = ath11k_dp_rx_h_attn_msdu_done(rx_desc); + l2_hdr_offset = ath11k_dp_rx_h_msdu_end_l3pad(rx_desc); + } + + ath11k_info(ar->ab, "first msdu %d last msdu %d msdu len %u decap format %u mpdu_len_err %d first_mpdu %d ip_csum_fail %d l4_csum_fail %d decrypte %d encryption type %u error bitmap %u msdu_done %d l2_hdr_offset %u\n", + rxcb->is_first_msdu, rxcb->is_last_msdu, msdu_len, decap_format, + mpdu_len_err, first_mpdu, ip_csum_fail, l4_csum_fail, + is_decrypted, enctype, err_bitmap, msdu_done, l2_hdr_offset); + ath11k_info(ar->ab, "hdr status : "); + for (i = 0; i < HAL_RX_DESC_HDR_STATUS_LEN; i++) + ath11k_info(ar->ab, "0x%x ", hdr_status[i]); + + ath11k_info(ar->ab, "\n"); +} + static void ath11k_dp_rx_h_csum_offload(struct sk_buff *msdu) { struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); @@ -2282,6 +2332,13 @@ static int ath11k_dp_rx_process_msdu(str rxcb->rx_desc = rx_desc; msdu_len = ath11k_dp_rx_h_msdu_start_msdu_len(rx_desc); l3_pad_bytes = ath11k_dp_rx_h_msdu_end_l3pad(lrx_desc); + if ((msdu_len + HAL_RX_DESC_SIZE) > DP_RX_BUFFER_SIZE) { + ath11k_warn(ar->ab, "invalid msdu len %u\n", msdu_len); + ath11k_dbg_dump(ar->ab, ATH11K_DBG_DATA, NULL, "", rxcb->rx_desc, + sizeof(struct hal_rx_desc)); + ath11k_dp_dump_msdu_info(ar, rxcb->rx_desc, rxcb); + goto free_out; + } if (rxcb->is_frag) { skb_pull(msdu, HAL_RX_DESC_SIZE); @@ -3426,6 +3483,15 @@ ath11k_dp_process_rx_err_buf(struct ath1 rx_desc = (struct hal_rx_desc *)msdu->data; msdu_len = ath11k_dp_rx_h_msdu_start_msdu_len(rx_desc); + if ((msdu_len + HAL_RX_DESC_SIZE) > DP_RX_BUFFER_SIZE) { + ath11k_warn(ar->ab, "invalid msdu len %u\n", msdu_len); + ath11k_dbg_dump(ar->ab, ATH11K_DBG_DATA, NULL, "", rx_desc, + sizeof(struct hal_rx_desc)); + ath11k_dp_dump_msdu_info(ar, rx_desc, rxcb); + dev_kfree_skb_any(msdu); + goto exit; + } + skb_put(msdu, HAL_RX_DESC_SIZE + msdu_len); if (ath11k_dp_rx_frag_h_mpdu(ar, msdu, ring_desc)) {