1d5c65159SKalle Valo // SPDX-License-Identifier: BSD-3-Clause-Clear 2d5c65159SKalle Valo /* 3d5c65159SKalle Valo * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. 4d5c65159SKalle Valo */ 5d5c65159SKalle Valo 6d5c65159SKalle Valo #include <linux/ieee80211.h> 7acc79d98SSriram R #include <linux/kernel.h> 8acc79d98SSriram R #include <linux/skbuff.h> 9243874c6SManikanta Pubbisetty #include <crypto/hash.h> 10d5c65159SKalle Valo #include "core.h" 11d5c65159SKalle Valo #include "debug.h" 12d5c65159SKalle Valo #include "hal_desc.h" 13d5c65159SKalle Valo #include "hw.h" 14d5c65159SKalle Valo #include "dp_rx.h" 15d5c65159SKalle Valo #include "hal_rx.h" 16d5c65159SKalle Valo #include "dp_tx.h" 17d5c65159SKalle Valo #include "peer.h" 18d5c65159SKalle Valo 19243874c6SManikanta Pubbisetty #define ATH11K_DP_RX_FRAGMENT_TIMEOUT_MS (2 * HZ) 20243874c6SManikanta Pubbisetty 21d5c65159SKalle Valo static u8 *ath11k_dp_rx_h_80211_hdr(struct hal_rx_desc *desc) 22d5c65159SKalle Valo { 23d5c65159SKalle Valo return desc->hdr_status; 24d5c65159SKalle Valo } 25d5c65159SKalle Valo 26d5c65159SKalle Valo static enum hal_encrypt_type ath11k_dp_rx_h_mpdu_start_enctype(struct hal_rx_desc *desc) 27d5c65159SKalle Valo { 28d5c65159SKalle Valo if (!(__le32_to_cpu(desc->mpdu_start.info1) & 29d5c65159SKalle Valo RX_MPDU_START_INFO1_ENCRYPT_INFO_VALID)) 30d5c65159SKalle Valo return HAL_ENCRYPT_TYPE_OPEN; 31d5c65159SKalle Valo 32d5c65159SKalle Valo return FIELD_GET(RX_MPDU_START_INFO2_ENC_TYPE, 33d5c65159SKalle Valo __le32_to_cpu(desc->mpdu_start.info2)); 34d5c65159SKalle Valo } 35d5c65159SKalle Valo 36243874c6SManikanta Pubbisetty static u8 ath11k_dp_rx_h_msdu_start_decap_type(struct hal_rx_desc *desc) 37d5c65159SKalle Valo { 38243874c6SManikanta Pubbisetty return FIELD_GET(RX_MSDU_START_INFO2_DECAP_FORMAT, 39243874c6SManikanta Pubbisetty __le32_to_cpu(desc->msdu_start.info2)); 40243874c6SManikanta Pubbisetty } 41243874c6SManikanta Pubbisetty 42acc79d98SSriram R static u8 ath11k_dp_rx_h_msdu_start_mesh_ctl_present(struct hal_rx_desc *desc) 43acc79d98SSriram R { 44acc79d98SSriram R return FIELD_GET(RX_MSDU_START_INFO2_MESH_CTRL_PRESENT, 45acc79d98SSriram R __le32_to_cpu(desc->msdu_start.info2)); 46acc79d98SSriram R } 47acc79d98SSriram R 48243874c6SManikanta Pubbisetty static bool ath11k_dp_rx_h_mpdu_start_seq_ctrl_valid(struct hal_rx_desc *desc) 49243874c6SManikanta Pubbisetty { 50243874c6SManikanta Pubbisetty return !!FIELD_GET(RX_MPDU_START_INFO1_MPDU_SEQ_CTRL_VALID, 51243874c6SManikanta Pubbisetty __le32_to_cpu(desc->mpdu_start.info1)); 52243874c6SManikanta Pubbisetty } 53243874c6SManikanta Pubbisetty 54243874c6SManikanta Pubbisetty static bool ath11k_dp_rx_h_mpdu_start_fc_valid(struct hal_rx_desc *desc) 55243874c6SManikanta Pubbisetty { 56243874c6SManikanta Pubbisetty return !!FIELD_GET(RX_MPDU_START_INFO1_MPDU_FCTRL_VALID, 57243874c6SManikanta Pubbisetty __le32_to_cpu(desc->mpdu_start.info1)); 58243874c6SManikanta Pubbisetty } 59243874c6SManikanta Pubbisetty 60243874c6SManikanta Pubbisetty static bool ath11k_dp_rx_h_mpdu_start_more_frags(struct sk_buff *skb) 61243874c6SManikanta Pubbisetty { 62243874c6SManikanta Pubbisetty struct ieee80211_hdr *hdr; 63243874c6SManikanta Pubbisetty 64243874c6SManikanta Pubbisetty hdr = (struct ieee80211_hdr *)(skb->data + HAL_RX_DESC_SIZE); 65243874c6SManikanta Pubbisetty return ieee80211_has_morefrags(hdr->frame_control); 66243874c6SManikanta Pubbisetty } 67243874c6SManikanta Pubbisetty 68243874c6SManikanta Pubbisetty static u16 ath11k_dp_rx_h_mpdu_start_frag_no(struct sk_buff *skb) 69243874c6SManikanta Pubbisetty { 70243874c6SManikanta Pubbisetty struct ieee80211_hdr *hdr; 71243874c6SManikanta Pubbisetty 72243874c6SManikanta Pubbisetty hdr = (struct ieee80211_hdr *)(skb->data + HAL_RX_DESC_SIZE); 73243874c6SManikanta Pubbisetty return le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; 74243874c6SManikanta Pubbisetty } 75243874c6SManikanta Pubbisetty 76243874c6SManikanta Pubbisetty static u16 ath11k_dp_rx_h_mpdu_start_seq_no(struct hal_rx_desc *desc) 77243874c6SManikanta Pubbisetty { 78243874c6SManikanta Pubbisetty return FIELD_GET(RX_MPDU_START_INFO1_MPDU_SEQ_NUM, 79243874c6SManikanta Pubbisetty __le32_to_cpu(desc->mpdu_start.info1)); 80d5c65159SKalle Valo } 81d5c65159SKalle Valo 82d5c65159SKalle Valo static bool ath11k_dp_rx_h_attn_msdu_done(struct hal_rx_desc *desc) 83d5c65159SKalle Valo { 84d5c65159SKalle Valo return !!FIELD_GET(RX_ATTENTION_INFO2_MSDU_DONE, 85d5c65159SKalle Valo __le32_to_cpu(desc->attention.info2)); 86d5c65159SKalle Valo } 87d5c65159SKalle Valo 88d5c65159SKalle Valo static bool ath11k_dp_rx_h_attn_l4_cksum_fail(struct hal_rx_desc *desc) 89d5c65159SKalle Valo { 90d5c65159SKalle Valo return !!FIELD_GET(RX_ATTENTION_INFO1_TCP_UDP_CKSUM_FAIL, 91d5c65159SKalle Valo __le32_to_cpu(desc->attention.info1)); 92d5c65159SKalle Valo } 93d5c65159SKalle Valo 94d5c65159SKalle Valo static bool ath11k_dp_rx_h_attn_ip_cksum_fail(struct hal_rx_desc *desc) 95d5c65159SKalle Valo { 96d5c65159SKalle Valo return !!FIELD_GET(RX_ATTENTION_INFO1_IP_CKSUM_FAIL, 97d5c65159SKalle Valo __le32_to_cpu(desc->attention.info1)); 98d5c65159SKalle Valo } 99d5c65159SKalle Valo 100d5c65159SKalle Valo static bool ath11k_dp_rx_h_attn_is_decrypted(struct hal_rx_desc *desc) 101d5c65159SKalle Valo { 102d5c65159SKalle Valo return (FIELD_GET(RX_ATTENTION_INFO2_DCRYPT_STATUS_CODE, 103d5c65159SKalle Valo __le32_to_cpu(desc->attention.info2)) == 104d5c65159SKalle Valo RX_DESC_DECRYPT_STATUS_CODE_OK); 105d5c65159SKalle Valo } 106d5c65159SKalle Valo 107d5c65159SKalle Valo static u32 ath11k_dp_rx_h_attn_mpdu_err(struct hal_rx_desc *desc) 108d5c65159SKalle Valo { 109d5c65159SKalle Valo u32 info = __le32_to_cpu(desc->attention.info1); 110d5c65159SKalle Valo u32 errmap = 0; 111d5c65159SKalle Valo 112d5c65159SKalle Valo if (info & RX_ATTENTION_INFO1_FCS_ERR) 113d5c65159SKalle Valo errmap |= DP_RX_MPDU_ERR_FCS; 114d5c65159SKalle Valo 115d5c65159SKalle Valo if (info & RX_ATTENTION_INFO1_DECRYPT_ERR) 116d5c65159SKalle Valo errmap |= DP_RX_MPDU_ERR_DECRYPT; 117d5c65159SKalle Valo 118d5c65159SKalle Valo if (info & RX_ATTENTION_INFO1_TKIP_MIC_ERR) 119d5c65159SKalle Valo errmap |= DP_RX_MPDU_ERR_TKIP_MIC; 120d5c65159SKalle Valo 121d5c65159SKalle Valo if (info & RX_ATTENTION_INFO1_A_MSDU_ERROR) 122d5c65159SKalle Valo errmap |= DP_RX_MPDU_ERR_AMSDU_ERR; 123d5c65159SKalle Valo 124d5c65159SKalle Valo if (info & RX_ATTENTION_INFO1_OVERFLOW_ERR) 125d5c65159SKalle Valo errmap |= DP_RX_MPDU_ERR_OVERFLOW; 126d5c65159SKalle Valo 127d5c65159SKalle Valo if (info & RX_ATTENTION_INFO1_MSDU_LEN_ERR) 128d5c65159SKalle Valo errmap |= DP_RX_MPDU_ERR_MSDU_LEN; 129d5c65159SKalle Valo 130d5c65159SKalle Valo if (info & RX_ATTENTION_INFO1_MPDU_LEN_ERR) 131d5c65159SKalle Valo errmap |= DP_RX_MPDU_ERR_MPDU_LEN; 132d5c65159SKalle Valo 133d5c65159SKalle Valo return errmap; 134d5c65159SKalle Valo } 135d5c65159SKalle Valo 136d5c65159SKalle Valo static u16 ath11k_dp_rx_h_msdu_start_msdu_len(struct hal_rx_desc *desc) 137d5c65159SKalle Valo { 138d5c65159SKalle Valo return FIELD_GET(RX_MSDU_START_INFO1_MSDU_LENGTH, 139d5c65159SKalle Valo __le32_to_cpu(desc->msdu_start.info1)); 140d5c65159SKalle Valo } 141d5c65159SKalle Valo 142d5c65159SKalle Valo static u8 ath11k_dp_rx_h_msdu_start_sgi(struct hal_rx_desc *desc) 143d5c65159SKalle Valo { 144d5c65159SKalle Valo return FIELD_GET(RX_MSDU_START_INFO3_SGI, 145d5c65159SKalle Valo __le32_to_cpu(desc->msdu_start.info3)); 146d5c65159SKalle Valo } 147d5c65159SKalle Valo 148d5c65159SKalle Valo static u8 ath11k_dp_rx_h_msdu_start_rate_mcs(struct hal_rx_desc *desc) 149d5c65159SKalle Valo { 150d5c65159SKalle Valo return FIELD_GET(RX_MSDU_START_INFO3_RATE_MCS, 151d5c65159SKalle Valo __le32_to_cpu(desc->msdu_start.info3)); 152d5c65159SKalle Valo } 153d5c65159SKalle Valo 154d5c65159SKalle Valo static u8 ath11k_dp_rx_h_msdu_start_rx_bw(struct hal_rx_desc *desc) 155d5c65159SKalle Valo { 156d5c65159SKalle Valo return FIELD_GET(RX_MSDU_START_INFO3_RECV_BW, 157d5c65159SKalle Valo __le32_to_cpu(desc->msdu_start.info3)); 158d5c65159SKalle Valo } 159d5c65159SKalle Valo 160d5c65159SKalle Valo static u32 ath11k_dp_rx_h_msdu_start_freq(struct hal_rx_desc *desc) 161d5c65159SKalle Valo { 162d5c65159SKalle Valo return __le32_to_cpu(desc->msdu_start.phy_meta_data); 163d5c65159SKalle Valo } 164d5c65159SKalle Valo 165d5c65159SKalle Valo static u8 ath11k_dp_rx_h_msdu_start_pkt_type(struct hal_rx_desc *desc) 166d5c65159SKalle Valo { 167d5c65159SKalle Valo return FIELD_GET(RX_MSDU_START_INFO3_PKT_TYPE, 168d5c65159SKalle Valo __le32_to_cpu(desc->msdu_start.info3)); 169d5c65159SKalle Valo } 170d5c65159SKalle Valo 171d5c65159SKalle Valo static u8 ath11k_dp_rx_h_msdu_start_nss(struct hal_rx_desc *desc) 172d5c65159SKalle Valo { 173d5c65159SKalle Valo u8 mimo_ss_bitmap = FIELD_GET(RX_MSDU_START_INFO3_MIMO_SS_BITMAP, 174d5c65159SKalle Valo __le32_to_cpu(desc->msdu_start.info3)); 175d5c65159SKalle Valo 176d5c65159SKalle Valo return hweight8(mimo_ss_bitmap); 177d5c65159SKalle Valo } 178d5c65159SKalle Valo 179243874c6SManikanta Pubbisetty static u8 ath11k_dp_rx_h_mpdu_start_tid(struct hal_rx_desc *desc) 180243874c6SManikanta Pubbisetty { 181243874c6SManikanta Pubbisetty return FIELD_GET(RX_MPDU_START_INFO2_TID, 182243874c6SManikanta Pubbisetty __le32_to_cpu(desc->mpdu_start.info2)); 183243874c6SManikanta Pubbisetty } 184243874c6SManikanta Pubbisetty 185243874c6SManikanta Pubbisetty static u16 ath11k_dp_rx_h_mpdu_start_peer_id(struct hal_rx_desc *desc) 186243874c6SManikanta Pubbisetty { 187243874c6SManikanta Pubbisetty return __le16_to_cpu(desc->mpdu_start.sw_peer_id); 188243874c6SManikanta Pubbisetty } 189243874c6SManikanta Pubbisetty 190d5c65159SKalle Valo static u8 ath11k_dp_rx_h_msdu_end_l3pad(struct hal_rx_desc *desc) 191d5c65159SKalle Valo { 192d5c65159SKalle Valo return FIELD_GET(RX_MSDU_END_INFO2_L3_HDR_PADDING, 193d5c65159SKalle Valo __le32_to_cpu(desc->msdu_end.info2)); 194d5c65159SKalle Valo } 195d5c65159SKalle Valo 196d5c65159SKalle Valo static bool ath11k_dp_rx_h_msdu_end_first_msdu(struct hal_rx_desc *desc) 197d5c65159SKalle Valo { 198d5c65159SKalle Valo return !!FIELD_GET(RX_MSDU_END_INFO2_FIRST_MSDU, 199d5c65159SKalle Valo __le32_to_cpu(desc->msdu_end.info2)); 200d5c65159SKalle Valo } 201d5c65159SKalle Valo 202d5c65159SKalle Valo static bool ath11k_dp_rx_h_msdu_end_last_msdu(struct hal_rx_desc *desc) 203d5c65159SKalle Valo { 204d5c65159SKalle Valo return !!FIELD_GET(RX_MSDU_END_INFO2_LAST_MSDU, 205d5c65159SKalle Valo __le32_to_cpu(desc->msdu_end.info2)); 206d5c65159SKalle Valo } 207d5c65159SKalle Valo 208d5c65159SKalle Valo static void ath11k_dp_rx_desc_end_tlv_copy(struct hal_rx_desc *fdesc, 209d5c65159SKalle Valo struct hal_rx_desc *ldesc) 210d5c65159SKalle Valo { 211d5c65159SKalle Valo memcpy((u8 *)&fdesc->msdu_end, (u8 *)&ldesc->msdu_end, 212d5c65159SKalle Valo sizeof(struct rx_msdu_end)); 213d5c65159SKalle Valo memcpy((u8 *)&fdesc->attention, (u8 *)&ldesc->attention, 214d5c65159SKalle Valo sizeof(struct rx_attention)); 215d5c65159SKalle Valo memcpy((u8 *)&fdesc->mpdu_end, (u8 *)&ldesc->mpdu_end, 216d5c65159SKalle Valo sizeof(struct rx_mpdu_end)); 217d5c65159SKalle Valo } 218d5c65159SKalle Valo 219d5c65159SKalle Valo static u32 ath11k_dp_rxdesc_get_mpdulen_err(struct hal_rx_desc *rx_desc) 220d5c65159SKalle Valo { 221d5c65159SKalle Valo struct rx_attention *rx_attn; 222d5c65159SKalle Valo 223d5c65159SKalle Valo rx_attn = &rx_desc->attention; 224d5c65159SKalle Valo 225d5c65159SKalle Valo return FIELD_GET(RX_ATTENTION_INFO1_MPDU_LEN_ERR, 226d5c65159SKalle Valo __le32_to_cpu(rx_attn->info1)); 227d5c65159SKalle Valo } 228d5c65159SKalle Valo 229d5c65159SKalle Valo static u32 ath11k_dp_rxdesc_get_decap_format(struct hal_rx_desc *rx_desc) 230d5c65159SKalle Valo { 231d5c65159SKalle Valo struct rx_msdu_start *rx_msdu_start; 232d5c65159SKalle Valo 233d5c65159SKalle Valo rx_msdu_start = &rx_desc->msdu_start; 234d5c65159SKalle Valo 235d5c65159SKalle Valo return FIELD_GET(RX_MSDU_START_INFO2_DECAP_FORMAT, 236d5c65159SKalle Valo __le32_to_cpu(rx_msdu_start->info2)); 237d5c65159SKalle Valo } 238d5c65159SKalle Valo 239d5c65159SKalle Valo static u8 *ath11k_dp_rxdesc_get_80211hdr(struct hal_rx_desc *rx_desc) 240d5c65159SKalle Valo { 241d5c65159SKalle Valo u8 *rx_pkt_hdr; 242d5c65159SKalle Valo 243d5c65159SKalle Valo rx_pkt_hdr = &rx_desc->msdu_payload[0]; 244d5c65159SKalle Valo 245d5c65159SKalle Valo return rx_pkt_hdr; 246d5c65159SKalle Valo } 247d5c65159SKalle Valo 248d5c65159SKalle Valo static bool ath11k_dp_rxdesc_mpdu_valid(struct hal_rx_desc *rx_desc) 249d5c65159SKalle Valo { 250d5c65159SKalle Valo u32 tlv_tag; 251d5c65159SKalle Valo 252d5c65159SKalle Valo tlv_tag = FIELD_GET(HAL_TLV_HDR_TAG, 253d5c65159SKalle Valo __le32_to_cpu(rx_desc->mpdu_start_tag)); 254d5c65159SKalle Valo 2558af40902SJason Yan return tlv_tag == HAL_RX_MPDU_START; 256d5c65159SKalle Valo } 257d5c65159SKalle Valo 258d5c65159SKalle Valo static u32 ath11k_dp_rxdesc_get_ppduid(struct hal_rx_desc *rx_desc) 259d5c65159SKalle Valo { 260d5c65159SKalle Valo return __le16_to_cpu(rx_desc->mpdu_start.phy_ppdu_id); 261d5c65159SKalle Valo } 262d5c65159SKalle Valo 263d5c65159SKalle Valo /* Returns number of Rx buffers replenished */ 264d5c65159SKalle Valo int ath11k_dp_rxbufs_replenish(struct ath11k_base *ab, int mac_id, 265d5c65159SKalle Valo struct dp_rxdma_ring *rx_ring, 266d5c65159SKalle Valo int req_entries, 267d5c65159SKalle Valo enum hal_rx_buf_return_buf_manager mgr, 268d5c65159SKalle Valo gfp_t gfp) 269d5c65159SKalle Valo { 270d5c65159SKalle Valo struct hal_srng *srng; 271d5c65159SKalle Valo u32 *desc; 272d5c65159SKalle Valo struct sk_buff *skb; 273d5c65159SKalle Valo int num_free; 274d5c65159SKalle Valo int num_remain; 275d5c65159SKalle Valo int buf_id; 276d5c65159SKalle Valo u32 cookie; 277d5c65159SKalle Valo dma_addr_t paddr; 278d5c65159SKalle Valo 279d5c65159SKalle Valo req_entries = min(req_entries, rx_ring->bufs_max); 280d5c65159SKalle Valo 281d5c65159SKalle Valo srng = &ab->hal.srng_list[rx_ring->refill_buf_ring.ring_id]; 282d5c65159SKalle Valo 283d5c65159SKalle Valo spin_lock_bh(&srng->lock); 284d5c65159SKalle Valo 285d5c65159SKalle Valo ath11k_hal_srng_access_begin(ab, srng); 286d5c65159SKalle Valo 287d5c65159SKalle Valo num_free = ath11k_hal_srng_src_num_free(ab, srng, true); 288d5c65159SKalle Valo if (!req_entries && (num_free > (rx_ring->bufs_max * 3) / 4)) 289d5c65159SKalle Valo req_entries = num_free; 290d5c65159SKalle Valo 291d5c65159SKalle Valo req_entries = min(num_free, req_entries); 292d5c65159SKalle Valo num_remain = req_entries; 293d5c65159SKalle Valo 294d5c65159SKalle Valo while (num_remain > 0) { 295d5c65159SKalle Valo skb = dev_alloc_skb(DP_RX_BUFFER_SIZE + 296d5c65159SKalle Valo DP_RX_BUFFER_ALIGN_SIZE); 297d5c65159SKalle Valo if (!skb) 298d5c65159SKalle Valo break; 299d5c65159SKalle Valo 300d5c65159SKalle Valo if (!IS_ALIGNED((unsigned long)skb->data, 301d5c65159SKalle Valo DP_RX_BUFFER_ALIGN_SIZE)) { 302d5c65159SKalle Valo skb_pull(skb, 303d5c65159SKalle Valo PTR_ALIGN(skb->data, DP_RX_BUFFER_ALIGN_SIZE) - 304d5c65159SKalle Valo skb->data); 305d5c65159SKalle Valo } 306d5c65159SKalle Valo 307d5c65159SKalle Valo paddr = dma_map_single(ab->dev, skb->data, 308d5c65159SKalle Valo skb->len + skb_tailroom(skb), 309d5c65159SKalle Valo DMA_FROM_DEVICE); 310d5c65159SKalle Valo if (dma_mapping_error(ab->dev, paddr)) 311d5c65159SKalle Valo goto fail_free_skb; 312d5c65159SKalle Valo 313d5c65159SKalle Valo spin_lock_bh(&rx_ring->idr_lock); 314d5c65159SKalle Valo buf_id = idr_alloc(&rx_ring->bufs_idr, skb, 0, 315d5c65159SKalle Valo rx_ring->bufs_max * 3, gfp); 316d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 317d5c65159SKalle Valo if (buf_id < 0) 318d5c65159SKalle Valo goto fail_dma_unmap; 319d5c65159SKalle Valo 320d5c65159SKalle Valo desc = ath11k_hal_srng_src_get_next_entry(ab, srng); 321d5c65159SKalle Valo if (!desc) 322d5c65159SKalle Valo goto fail_idr_remove; 323d5c65159SKalle Valo 324d5c65159SKalle Valo ATH11K_SKB_RXCB(skb)->paddr = paddr; 325d5c65159SKalle Valo 326d5c65159SKalle Valo cookie = FIELD_PREP(DP_RXDMA_BUF_COOKIE_PDEV_ID, mac_id) | 327d5c65159SKalle Valo FIELD_PREP(DP_RXDMA_BUF_COOKIE_BUF_ID, buf_id); 328d5c65159SKalle Valo 329d5c65159SKalle Valo num_remain--; 330d5c65159SKalle Valo 331d5c65159SKalle Valo ath11k_hal_rx_buf_addr_info_set(desc, paddr, cookie, mgr); 332d5c65159SKalle Valo } 333d5c65159SKalle Valo 334d5c65159SKalle Valo ath11k_hal_srng_access_end(ab, srng); 335d5c65159SKalle Valo 336d5c65159SKalle Valo spin_unlock_bh(&srng->lock); 337d5c65159SKalle Valo 338d5c65159SKalle Valo return req_entries - num_remain; 339d5c65159SKalle Valo 340d5c65159SKalle Valo fail_idr_remove: 341d5c65159SKalle Valo spin_lock_bh(&rx_ring->idr_lock); 342d5c65159SKalle Valo idr_remove(&rx_ring->bufs_idr, buf_id); 343d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 344d5c65159SKalle Valo fail_dma_unmap: 345d5c65159SKalle Valo dma_unmap_single(ab->dev, paddr, skb->len + skb_tailroom(skb), 346d5c65159SKalle Valo DMA_FROM_DEVICE); 347d5c65159SKalle Valo fail_free_skb: 348d5c65159SKalle Valo dev_kfree_skb_any(skb); 349d5c65159SKalle Valo 350d5c65159SKalle Valo ath11k_hal_srng_access_end(ab, srng); 351d5c65159SKalle Valo 352d5c65159SKalle Valo spin_unlock_bh(&srng->lock); 353d5c65159SKalle Valo 354d5c65159SKalle Valo return req_entries - num_remain; 355d5c65159SKalle Valo } 356d5c65159SKalle Valo 357d5c65159SKalle Valo static int ath11k_dp_rxdma_buf_ring_free(struct ath11k *ar, 358d5c65159SKalle Valo struct dp_rxdma_ring *rx_ring) 359d5c65159SKalle Valo { 360d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 361d5c65159SKalle Valo struct sk_buff *skb; 362d5c65159SKalle Valo int buf_id; 363d5c65159SKalle Valo 364d5c65159SKalle Valo spin_lock_bh(&rx_ring->idr_lock); 365d5c65159SKalle Valo idr_for_each_entry(&rx_ring->bufs_idr, skb, buf_id) { 366d5c65159SKalle Valo idr_remove(&rx_ring->bufs_idr, buf_id); 367d5c65159SKalle Valo /* TODO: Understand where internal driver does this dma_unmap of 368d5c65159SKalle Valo * of rxdma_buffer. 369d5c65159SKalle Valo */ 370d5c65159SKalle Valo dma_unmap_single(ar->ab->dev, ATH11K_SKB_RXCB(skb)->paddr, 371d5c65159SKalle Valo skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); 372d5c65159SKalle Valo dev_kfree_skb_any(skb); 373d5c65159SKalle Valo } 374d5c65159SKalle Valo 375d5c65159SKalle Valo idr_destroy(&rx_ring->bufs_idr); 376d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 377d5c65159SKalle Valo 378d5c65159SKalle Valo rx_ring = &dp->rx_mon_status_refill_ring; 379d5c65159SKalle Valo 380d5c65159SKalle Valo spin_lock_bh(&rx_ring->idr_lock); 381d5c65159SKalle Valo idr_for_each_entry(&rx_ring->bufs_idr, skb, buf_id) { 382d5c65159SKalle Valo idr_remove(&rx_ring->bufs_idr, buf_id); 383d5c65159SKalle Valo /* XXX: Understand where internal driver does this dma_unmap of 384d5c65159SKalle Valo * of rxdma_buffer. 385d5c65159SKalle Valo */ 386d5c65159SKalle Valo dma_unmap_single(ar->ab->dev, ATH11K_SKB_RXCB(skb)->paddr, 387d5c65159SKalle Valo skb->len + skb_tailroom(skb), DMA_BIDIRECTIONAL); 388d5c65159SKalle Valo dev_kfree_skb_any(skb); 389d5c65159SKalle Valo } 390d5c65159SKalle Valo 391d5c65159SKalle Valo idr_destroy(&rx_ring->bufs_idr); 392d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 393d5c65159SKalle Valo return 0; 394d5c65159SKalle Valo } 395d5c65159SKalle Valo 396d5c65159SKalle Valo static int ath11k_dp_rxdma_pdev_buf_free(struct ath11k *ar) 397d5c65159SKalle Valo { 398d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 399d5c65159SKalle Valo struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring; 400d5c65159SKalle Valo 401d5c65159SKalle Valo ath11k_dp_rxdma_buf_ring_free(ar, rx_ring); 402d5c65159SKalle Valo 403d5c65159SKalle Valo rx_ring = &dp->rxdma_mon_buf_ring; 404d5c65159SKalle Valo ath11k_dp_rxdma_buf_ring_free(ar, rx_ring); 405d5c65159SKalle Valo 406d5c65159SKalle Valo rx_ring = &dp->rx_mon_status_refill_ring; 407d5c65159SKalle Valo ath11k_dp_rxdma_buf_ring_free(ar, rx_ring); 408d5c65159SKalle Valo return 0; 409d5c65159SKalle Valo } 410d5c65159SKalle Valo 411d5c65159SKalle Valo static int ath11k_dp_rxdma_ring_buf_setup(struct ath11k *ar, 412d5c65159SKalle Valo struct dp_rxdma_ring *rx_ring, 413d5c65159SKalle Valo u32 ringtype) 414d5c65159SKalle Valo { 415d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 416d5c65159SKalle Valo int num_entries; 417d5c65159SKalle Valo 418d5c65159SKalle Valo num_entries = rx_ring->refill_buf_ring.size / 419f7eb4b04SKalle Valo ath11k_hal_srng_get_entrysize(ar->ab, ringtype); 420d5c65159SKalle Valo 421d5c65159SKalle Valo rx_ring->bufs_max = num_entries; 422d5c65159SKalle Valo ath11k_dp_rxbufs_replenish(ar->ab, dp->mac_id, rx_ring, num_entries, 423d5c65159SKalle Valo HAL_RX_BUF_RBM_SW3_BM, GFP_KERNEL); 424d5c65159SKalle Valo return 0; 425d5c65159SKalle Valo } 426d5c65159SKalle Valo 427d5c65159SKalle Valo static int ath11k_dp_rxdma_pdev_buf_setup(struct ath11k *ar) 428d5c65159SKalle Valo { 429d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 430d5c65159SKalle Valo struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring; 431d5c65159SKalle Valo 432d5c65159SKalle Valo ath11k_dp_rxdma_ring_buf_setup(ar, rx_ring, HAL_RXDMA_BUF); 433d5c65159SKalle Valo 434d5c65159SKalle Valo rx_ring = &dp->rxdma_mon_buf_ring; 435d5c65159SKalle Valo ath11k_dp_rxdma_ring_buf_setup(ar, rx_ring, HAL_RXDMA_MONITOR_BUF); 436d5c65159SKalle Valo 437d5c65159SKalle Valo rx_ring = &dp->rx_mon_status_refill_ring; 438d5c65159SKalle Valo ath11k_dp_rxdma_ring_buf_setup(ar, rx_ring, HAL_RXDMA_MONITOR_STATUS); 439d5c65159SKalle Valo 440d5c65159SKalle Valo return 0; 441d5c65159SKalle Valo } 442d5c65159SKalle Valo 443d5c65159SKalle Valo static void ath11k_dp_rx_pdev_srng_free(struct ath11k *ar) 444d5c65159SKalle Valo { 445d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 446d5c65159SKalle Valo 447d5c65159SKalle Valo ath11k_dp_srng_cleanup(ar->ab, &dp->rx_refill_buf_ring.refill_buf_ring); 448d5c65159SKalle Valo ath11k_dp_srng_cleanup(ar->ab, &dp->rxdma_err_dst_ring); 449d5c65159SKalle Valo ath11k_dp_srng_cleanup(ar->ab, &dp->rx_mon_status_refill_ring.refill_buf_ring); 450d5c65159SKalle Valo ath11k_dp_srng_cleanup(ar->ab, &dp->rxdma_mon_buf_ring.refill_buf_ring); 451d5c65159SKalle Valo } 452d5c65159SKalle Valo 4539c57d7e3SVasanthakumar Thiagarajan void ath11k_dp_pdev_reo_cleanup(struct ath11k_base *ab) 4549c57d7e3SVasanthakumar Thiagarajan { 455acc79d98SSriram R struct ath11k_dp *dp = &ab->dp; 4569c57d7e3SVasanthakumar Thiagarajan int i; 4579c57d7e3SVasanthakumar Thiagarajan 458acc79d98SSriram R for (i = 0; i < DP_REO_DST_RING_MAX; i++) 459acc79d98SSriram R ath11k_dp_srng_cleanup(ab, &dp->reo_dst_ring[i]); 4609c57d7e3SVasanthakumar Thiagarajan } 4619c57d7e3SVasanthakumar Thiagarajan 4629c57d7e3SVasanthakumar Thiagarajan int ath11k_dp_pdev_reo_setup(struct ath11k_base *ab) 4639c57d7e3SVasanthakumar Thiagarajan { 464acc79d98SSriram R struct ath11k_dp *dp = &ab->dp; 4659c57d7e3SVasanthakumar Thiagarajan int ret; 4669c57d7e3SVasanthakumar Thiagarajan int i; 4679c57d7e3SVasanthakumar Thiagarajan 468acc79d98SSriram R for (i = 0; i < DP_REO_DST_RING_MAX; i++) { 469acc79d98SSriram R ret = ath11k_dp_srng_setup(ab, &dp->reo_dst_ring[i], 470acc79d98SSriram R HAL_REO_DST, i, 0, 4719c57d7e3SVasanthakumar Thiagarajan DP_REO_DST_RING_SIZE); 4729c57d7e3SVasanthakumar Thiagarajan if (ret) { 473acc79d98SSriram R ath11k_warn(ab, "failed to setup reo_dst_ring\n"); 4749c57d7e3SVasanthakumar Thiagarajan goto err_reo_cleanup; 4759c57d7e3SVasanthakumar Thiagarajan } 4769c57d7e3SVasanthakumar Thiagarajan } 4779c57d7e3SVasanthakumar Thiagarajan 4789c57d7e3SVasanthakumar Thiagarajan return 0; 4799c57d7e3SVasanthakumar Thiagarajan 4809c57d7e3SVasanthakumar Thiagarajan err_reo_cleanup: 4819c57d7e3SVasanthakumar Thiagarajan ath11k_dp_pdev_reo_cleanup(ab); 4829c57d7e3SVasanthakumar Thiagarajan 4839c57d7e3SVasanthakumar Thiagarajan return ret; 4849c57d7e3SVasanthakumar Thiagarajan } 4859c57d7e3SVasanthakumar Thiagarajan 486d5c65159SKalle Valo static int ath11k_dp_rx_pdev_srng_alloc(struct ath11k *ar) 487d5c65159SKalle Valo { 488d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 489d5c65159SKalle Valo struct dp_srng *srng = NULL; 490d5c65159SKalle Valo int ret; 491d5c65159SKalle Valo 492d5c65159SKalle Valo ret = ath11k_dp_srng_setup(ar->ab, 493d5c65159SKalle Valo &dp->rx_refill_buf_ring.refill_buf_ring, 494d5c65159SKalle Valo HAL_RXDMA_BUF, 0, 495d5c65159SKalle Valo dp->mac_id, DP_RXDMA_BUF_RING_SIZE); 496d5c65159SKalle Valo if (ret) { 497d5c65159SKalle Valo ath11k_warn(ar->ab, "failed to setup rx_refill_buf_ring\n"); 498d5c65159SKalle Valo return ret; 499d5c65159SKalle Valo } 500d5c65159SKalle Valo 501d5c65159SKalle Valo ret = ath11k_dp_srng_setup(ar->ab, &dp->rxdma_err_dst_ring, 502d5c65159SKalle Valo HAL_RXDMA_DST, 0, dp->mac_id, 503d5c65159SKalle Valo DP_RXDMA_ERR_DST_RING_SIZE); 504d5c65159SKalle Valo if (ret) { 505d5c65159SKalle Valo ath11k_warn(ar->ab, "failed to setup rxdma_err_dst_ring\n"); 506d5c65159SKalle Valo return ret; 507d5c65159SKalle Valo } 508d5c65159SKalle Valo 509d5c65159SKalle Valo srng = &dp->rx_mon_status_refill_ring.refill_buf_ring; 510d5c65159SKalle Valo ret = ath11k_dp_srng_setup(ar->ab, 511d5c65159SKalle Valo srng, 512d5c65159SKalle Valo HAL_RXDMA_MONITOR_STATUS, 0, dp->mac_id, 513d5c65159SKalle Valo DP_RXDMA_MON_STATUS_RING_SIZE); 514d5c65159SKalle Valo if (ret) { 515d5c65159SKalle Valo ath11k_warn(ar->ab, 516d5c65159SKalle Valo "failed to setup rx_mon_status_refill_ring\n"); 517d5c65159SKalle Valo return ret; 518d5c65159SKalle Valo } 519d5c65159SKalle Valo ret = ath11k_dp_srng_setup(ar->ab, 520d5c65159SKalle Valo &dp->rxdma_mon_buf_ring.refill_buf_ring, 521d5c65159SKalle Valo HAL_RXDMA_MONITOR_BUF, 0, dp->mac_id, 522d5c65159SKalle Valo DP_RXDMA_MONITOR_BUF_RING_SIZE); 523d5c65159SKalle Valo if (ret) { 524d5c65159SKalle Valo ath11k_warn(ar->ab, 525d5c65159SKalle Valo "failed to setup HAL_RXDMA_MONITOR_BUF\n"); 526d5c65159SKalle Valo return ret; 527d5c65159SKalle Valo } 528d5c65159SKalle Valo 529d5c65159SKalle Valo ret = ath11k_dp_srng_setup(ar->ab, &dp->rxdma_mon_dst_ring, 530d5c65159SKalle Valo HAL_RXDMA_MONITOR_DST, 0, dp->mac_id, 531d5c65159SKalle Valo DP_RXDMA_MONITOR_DST_RING_SIZE); 532d5c65159SKalle Valo if (ret) { 533d5c65159SKalle Valo ath11k_warn(ar->ab, 534d5c65159SKalle Valo "failed to setup HAL_RXDMA_MONITOR_DST\n"); 535d5c65159SKalle Valo return ret; 536d5c65159SKalle Valo } 537d5c65159SKalle Valo 538d5c65159SKalle Valo ret = ath11k_dp_srng_setup(ar->ab, &dp->rxdma_mon_desc_ring, 539d5c65159SKalle Valo HAL_RXDMA_MONITOR_DESC, 0, dp->mac_id, 540d5c65159SKalle Valo DP_RXDMA_MONITOR_DESC_RING_SIZE); 541d5c65159SKalle Valo if (ret) { 542d5c65159SKalle Valo ath11k_warn(ar->ab, 543d5c65159SKalle Valo "failed to setup HAL_RXDMA_MONITOR_DESC\n"); 544d5c65159SKalle Valo return ret; 545d5c65159SKalle Valo } 546d5c65159SKalle Valo 547d5c65159SKalle Valo return 0; 548d5c65159SKalle Valo } 549d5c65159SKalle Valo 550d5c65159SKalle Valo void ath11k_dp_reo_cmd_list_cleanup(struct ath11k_base *ab) 551d5c65159SKalle Valo { 552d5c65159SKalle Valo struct ath11k_dp *dp = &ab->dp; 553d5c65159SKalle Valo struct dp_reo_cmd *cmd, *tmp; 554d5c65159SKalle Valo struct dp_reo_cache_flush_elem *cmd_cache, *tmp_cache; 555d5c65159SKalle Valo 556d5c65159SKalle Valo spin_lock_bh(&dp->reo_cmd_lock); 557d5c65159SKalle Valo list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) { 558d5c65159SKalle Valo list_del(&cmd->list); 559d5c65159SKalle Valo dma_unmap_single(ab->dev, cmd->data.paddr, 560d5c65159SKalle Valo cmd->data.size, DMA_BIDIRECTIONAL); 561d5c65159SKalle Valo kfree(cmd->data.vaddr); 562d5c65159SKalle Valo kfree(cmd); 563d5c65159SKalle Valo } 564d5c65159SKalle Valo 565d5c65159SKalle Valo list_for_each_entry_safe(cmd_cache, tmp_cache, 566d5c65159SKalle Valo &dp->reo_cmd_cache_flush_list, list) { 567d5c65159SKalle Valo list_del(&cmd_cache->list); 5685cb899ddSKarthikeyan Periyasamy dp->reo_cmd_cache_flush_count--; 569d5c65159SKalle Valo dma_unmap_single(ab->dev, cmd_cache->data.paddr, 570d5c65159SKalle Valo cmd_cache->data.size, DMA_BIDIRECTIONAL); 571d5c65159SKalle Valo kfree(cmd_cache->data.vaddr); 572d5c65159SKalle Valo kfree(cmd_cache); 573d5c65159SKalle Valo } 574d5c65159SKalle Valo spin_unlock_bh(&dp->reo_cmd_lock); 575d5c65159SKalle Valo } 576d5c65159SKalle Valo 577d5c65159SKalle Valo static void ath11k_dp_reo_cmd_free(struct ath11k_dp *dp, void *ctx, 578d5c65159SKalle Valo enum hal_reo_cmd_status status) 579d5c65159SKalle Valo { 580d5c65159SKalle Valo struct dp_rx_tid *rx_tid = ctx; 581d5c65159SKalle Valo 582d5c65159SKalle Valo if (status != HAL_REO_CMD_SUCCESS) 583d5c65159SKalle Valo ath11k_warn(dp->ab, "failed to flush rx tid hw desc, tid %d status %d\n", 584d5c65159SKalle Valo rx_tid->tid, status); 585d5c65159SKalle Valo 586d5c65159SKalle Valo dma_unmap_single(dp->ab->dev, rx_tid->paddr, rx_tid->size, 587d5c65159SKalle Valo DMA_BIDIRECTIONAL); 588d5c65159SKalle Valo kfree(rx_tid->vaddr); 589d5c65159SKalle Valo } 590d5c65159SKalle Valo 591d5c65159SKalle Valo static void ath11k_dp_reo_cache_flush(struct ath11k_base *ab, 592d5c65159SKalle Valo struct dp_rx_tid *rx_tid) 593d5c65159SKalle Valo { 594d5c65159SKalle Valo struct ath11k_hal_reo_cmd cmd = {0}; 595d5c65159SKalle Valo unsigned long tot_desc_sz, desc_sz; 596d5c65159SKalle Valo int ret; 597d5c65159SKalle Valo 598d5c65159SKalle Valo tot_desc_sz = rx_tid->size; 599d5c65159SKalle Valo desc_sz = ath11k_hal_reo_qdesc_size(0, HAL_DESC_REO_NON_QOS_TID); 600d5c65159SKalle Valo 601d5c65159SKalle Valo while (tot_desc_sz > desc_sz) { 602d5c65159SKalle Valo tot_desc_sz -= desc_sz; 603d5c65159SKalle Valo cmd.addr_lo = lower_32_bits(rx_tid->paddr + tot_desc_sz); 604d5c65159SKalle Valo cmd.addr_hi = upper_32_bits(rx_tid->paddr); 605d5c65159SKalle Valo ret = ath11k_dp_tx_send_reo_cmd(ab, rx_tid, 606d5c65159SKalle Valo HAL_REO_CMD_FLUSH_CACHE, &cmd, 607d5c65159SKalle Valo NULL); 608d5c65159SKalle Valo if (ret) 609d5c65159SKalle Valo ath11k_warn(ab, 610d5c65159SKalle Valo "failed to send HAL_REO_CMD_FLUSH_CACHE, tid %d (%d)\n", 611d5c65159SKalle Valo rx_tid->tid, ret); 612d5c65159SKalle Valo } 613d5c65159SKalle Valo 614d5c65159SKalle Valo memset(&cmd, 0, sizeof(cmd)); 615d5c65159SKalle Valo cmd.addr_lo = lower_32_bits(rx_tid->paddr); 616d5c65159SKalle Valo cmd.addr_hi = upper_32_bits(rx_tid->paddr); 617d5c65159SKalle Valo cmd.flag |= HAL_REO_CMD_FLG_NEED_STATUS; 618d5c65159SKalle Valo ret = ath11k_dp_tx_send_reo_cmd(ab, rx_tid, 619d5c65159SKalle Valo HAL_REO_CMD_FLUSH_CACHE, 620d5c65159SKalle Valo &cmd, ath11k_dp_reo_cmd_free); 621d5c65159SKalle Valo if (ret) { 622d5c65159SKalle Valo ath11k_err(ab, "failed to send HAL_REO_CMD_FLUSH_CACHE cmd, tid %d (%d)\n", 623d5c65159SKalle Valo rx_tid->tid, ret); 624d5c65159SKalle Valo dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, 625d5c65159SKalle Valo DMA_BIDIRECTIONAL); 626d5c65159SKalle Valo kfree(rx_tid->vaddr); 627d5c65159SKalle Valo } 628d5c65159SKalle Valo } 629d5c65159SKalle Valo 630d5c65159SKalle Valo static void ath11k_dp_rx_tid_del_func(struct ath11k_dp *dp, void *ctx, 631d5c65159SKalle Valo enum hal_reo_cmd_status status) 632d5c65159SKalle Valo { 633d5c65159SKalle Valo struct ath11k_base *ab = dp->ab; 634d5c65159SKalle Valo struct dp_rx_tid *rx_tid = ctx; 635d5c65159SKalle Valo struct dp_reo_cache_flush_elem *elem, *tmp; 636d5c65159SKalle Valo 637d5c65159SKalle Valo if (status == HAL_REO_CMD_DRAIN) { 638d5c65159SKalle Valo goto free_desc; 639d5c65159SKalle Valo } else if (status != HAL_REO_CMD_SUCCESS) { 640d5c65159SKalle Valo /* Shouldn't happen! Cleanup in case of other failure? */ 641d5c65159SKalle Valo ath11k_warn(ab, "failed to delete rx tid %d hw descriptor %d\n", 642d5c65159SKalle Valo rx_tid->tid, status); 643d5c65159SKalle Valo return; 644d5c65159SKalle Valo } 645d5c65159SKalle Valo 646d5c65159SKalle Valo elem = kzalloc(sizeof(*elem), GFP_ATOMIC); 647d5c65159SKalle Valo if (!elem) 648d5c65159SKalle Valo goto free_desc; 649d5c65159SKalle Valo 650d5c65159SKalle Valo elem->ts = jiffies; 651d5c65159SKalle Valo memcpy(&elem->data, rx_tid, sizeof(*rx_tid)); 652d5c65159SKalle Valo 653d5c65159SKalle Valo spin_lock_bh(&dp->reo_cmd_lock); 654d5c65159SKalle Valo list_add_tail(&elem->list, &dp->reo_cmd_cache_flush_list); 6555cb899ddSKarthikeyan Periyasamy dp->reo_cmd_cache_flush_count++; 656d5c65159SKalle Valo 657d5c65159SKalle Valo /* Flush and invalidate aged REO desc from HW cache */ 658d5c65159SKalle Valo list_for_each_entry_safe(elem, tmp, &dp->reo_cmd_cache_flush_list, 659d5c65159SKalle Valo list) { 6605cb899ddSKarthikeyan Periyasamy if (dp->reo_cmd_cache_flush_count > DP_REO_DESC_FREE_THRESHOLD || 6615cb899ddSKarthikeyan Periyasamy time_after(jiffies, elem->ts + 662d5c65159SKalle Valo msecs_to_jiffies(DP_REO_DESC_FREE_TIMEOUT_MS))) { 663d5c65159SKalle Valo list_del(&elem->list); 6645cb899ddSKarthikeyan Periyasamy dp->reo_cmd_cache_flush_count--; 665d5c65159SKalle Valo spin_unlock_bh(&dp->reo_cmd_lock); 666d5c65159SKalle Valo 667d5c65159SKalle Valo ath11k_dp_reo_cache_flush(ab, &elem->data); 668d5c65159SKalle Valo kfree(elem); 669d5c65159SKalle Valo spin_lock_bh(&dp->reo_cmd_lock); 670d5c65159SKalle Valo } 671d5c65159SKalle Valo } 672d5c65159SKalle Valo spin_unlock_bh(&dp->reo_cmd_lock); 673d5c65159SKalle Valo 674d5c65159SKalle Valo return; 675d5c65159SKalle Valo free_desc: 676d5c65159SKalle Valo dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, 677d5c65159SKalle Valo DMA_BIDIRECTIONAL); 678d5c65159SKalle Valo kfree(rx_tid->vaddr); 679d5c65159SKalle Valo } 680d5c65159SKalle Valo 681a36adf54SGovindaraj Saminathan void ath11k_peer_rx_tid_delete(struct ath11k *ar, 682d5c65159SKalle Valo struct ath11k_peer *peer, u8 tid) 683d5c65159SKalle Valo { 684d5c65159SKalle Valo struct ath11k_hal_reo_cmd cmd = {0}; 685d5c65159SKalle Valo struct dp_rx_tid *rx_tid = &peer->rx_tid[tid]; 686d5c65159SKalle Valo int ret; 687d5c65159SKalle Valo 688d5c65159SKalle Valo if (!rx_tid->active) 689d5c65159SKalle Valo return; 690d5c65159SKalle Valo 691d5c65159SKalle Valo cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS; 692d5c65159SKalle Valo cmd.addr_lo = lower_32_bits(rx_tid->paddr); 693d5c65159SKalle Valo cmd.addr_hi = upper_32_bits(rx_tid->paddr); 694d5c65159SKalle Valo cmd.upd0 |= HAL_REO_CMD_UPD0_VLD; 695d5c65159SKalle Valo ret = ath11k_dp_tx_send_reo_cmd(ar->ab, rx_tid, 696d5c65159SKalle Valo HAL_REO_CMD_UPDATE_RX_QUEUE, &cmd, 697d5c65159SKalle Valo ath11k_dp_rx_tid_del_func); 698d5c65159SKalle Valo if (ret) { 699d5c65159SKalle Valo ath11k_err(ar->ab, "failed to send HAL_REO_CMD_UPDATE_RX_QUEUE cmd, tid %d (%d)\n", 700d5c65159SKalle Valo tid, ret); 701d5c65159SKalle Valo dma_unmap_single(ar->ab->dev, rx_tid->paddr, rx_tid->size, 702d5c65159SKalle Valo DMA_BIDIRECTIONAL); 703d5c65159SKalle Valo kfree(rx_tid->vaddr); 704d5c65159SKalle Valo } 705d5c65159SKalle Valo 706d5c65159SKalle Valo rx_tid->active = false; 707d5c65159SKalle Valo } 708d5c65159SKalle Valo 709243874c6SManikanta Pubbisetty static int ath11k_dp_rx_link_desc_return(struct ath11k_base *ab, 710243874c6SManikanta Pubbisetty u32 *link_desc, 711243874c6SManikanta Pubbisetty enum hal_wbm_rel_bm_act action) 712243874c6SManikanta Pubbisetty { 713243874c6SManikanta Pubbisetty struct ath11k_dp *dp = &ab->dp; 714243874c6SManikanta Pubbisetty struct hal_srng *srng; 715243874c6SManikanta Pubbisetty u32 *desc; 716243874c6SManikanta Pubbisetty int ret = 0; 717243874c6SManikanta Pubbisetty 718243874c6SManikanta Pubbisetty srng = &ab->hal.srng_list[dp->wbm_desc_rel_ring.ring_id]; 719243874c6SManikanta Pubbisetty 720243874c6SManikanta Pubbisetty spin_lock_bh(&srng->lock); 721243874c6SManikanta Pubbisetty 722243874c6SManikanta Pubbisetty ath11k_hal_srng_access_begin(ab, srng); 723243874c6SManikanta Pubbisetty 724243874c6SManikanta Pubbisetty desc = ath11k_hal_srng_src_get_next_entry(ab, srng); 725243874c6SManikanta Pubbisetty if (!desc) { 726243874c6SManikanta Pubbisetty ret = -ENOBUFS; 727243874c6SManikanta Pubbisetty goto exit; 728243874c6SManikanta Pubbisetty } 729243874c6SManikanta Pubbisetty 730243874c6SManikanta Pubbisetty ath11k_hal_rx_msdu_link_desc_set(ab, (void *)desc, (void *)link_desc, 731243874c6SManikanta Pubbisetty action); 732243874c6SManikanta Pubbisetty 733243874c6SManikanta Pubbisetty exit: 734243874c6SManikanta Pubbisetty ath11k_hal_srng_access_end(ab, srng); 735243874c6SManikanta Pubbisetty 736243874c6SManikanta Pubbisetty spin_unlock_bh(&srng->lock); 737243874c6SManikanta Pubbisetty 738243874c6SManikanta Pubbisetty return ret; 739243874c6SManikanta Pubbisetty } 740243874c6SManikanta Pubbisetty 741243874c6SManikanta Pubbisetty static void ath11k_dp_rx_frags_cleanup(struct dp_rx_tid *rx_tid, bool rel_link_desc) 742243874c6SManikanta Pubbisetty { 743243874c6SManikanta Pubbisetty struct ath11k_base *ab = rx_tid->ab; 744243874c6SManikanta Pubbisetty 745243874c6SManikanta Pubbisetty lockdep_assert_held(&ab->base_lock); 746243874c6SManikanta Pubbisetty 747243874c6SManikanta Pubbisetty if (rx_tid->dst_ring_desc) { 748243874c6SManikanta Pubbisetty if (rel_link_desc) 749243874c6SManikanta Pubbisetty ath11k_dp_rx_link_desc_return(ab, (u32 *)rx_tid->dst_ring_desc, 750243874c6SManikanta Pubbisetty HAL_WBM_REL_BM_ACT_PUT_IN_IDLE); 751243874c6SManikanta Pubbisetty kfree(rx_tid->dst_ring_desc); 752243874c6SManikanta Pubbisetty rx_tid->dst_ring_desc = NULL; 753243874c6SManikanta Pubbisetty } 754243874c6SManikanta Pubbisetty 755243874c6SManikanta Pubbisetty rx_tid->cur_sn = 0; 756243874c6SManikanta Pubbisetty rx_tid->last_frag_no = 0; 757243874c6SManikanta Pubbisetty rx_tid->rx_frag_bitmap = 0; 758243874c6SManikanta Pubbisetty __skb_queue_purge(&rx_tid->rx_frags); 759243874c6SManikanta Pubbisetty } 760243874c6SManikanta Pubbisetty 761d5c65159SKalle Valo void ath11k_peer_rx_tid_cleanup(struct ath11k *ar, struct ath11k_peer *peer) 762d5c65159SKalle Valo { 763243874c6SManikanta Pubbisetty struct dp_rx_tid *rx_tid; 764d5c65159SKalle Valo int i; 765d5c65159SKalle Valo 766243874c6SManikanta Pubbisetty lockdep_assert_held(&ar->ab->base_lock); 767243874c6SManikanta Pubbisetty 768243874c6SManikanta Pubbisetty for (i = 0; i <= IEEE80211_NUM_TIDS; i++) { 769243874c6SManikanta Pubbisetty rx_tid = &peer->rx_tid[i]; 770243874c6SManikanta Pubbisetty 771d5c65159SKalle Valo ath11k_peer_rx_tid_delete(ar, peer, i); 772243874c6SManikanta Pubbisetty ath11k_dp_rx_frags_cleanup(rx_tid, true); 773243874c6SManikanta Pubbisetty 774243874c6SManikanta Pubbisetty spin_unlock_bh(&ar->ab->base_lock); 775243874c6SManikanta Pubbisetty del_timer_sync(&rx_tid->frag_timer); 776243874c6SManikanta Pubbisetty spin_lock_bh(&ar->ab->base_lock); 777243874c6SManikanta Pubbisetty } 778d5c65159SKalle Valo } 779d5c65159SKalle Valo 780d5c65159SKalle Valo static int ath11k_peer_rx_tid_reo_update(struct ath11k *ar, 781d5c65159SKalle Valo struct ath11k_peer *peer, 782d5c65159SKalle Valo struct dp_rx_tid *rx_tid, 783fe201947SVenkateswara Naralasetty u32 ba_win_sz, u16 ssn, 784fe201947SVenkateswara Naralasetty bool update_ssn) 785d5c65159SKalle Valo { 786d5c65159SKalle Valo struct ath11k_hal_reo_cmd cmd = {0}; 787d5c65159SKalle Valo int ret; 788d5c65159SKalle Valo 789d5c65159SKalle Valo cmd.addr_lo = lower_32_bits(rx_tid->paddr); 790d5c65159SKalle Valo cmd.addr_hi = upper_32_bits(rx_tid->paddr); 791d5c65159SKalle Valo cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS; 792fe201947SVenkateswara Naralasetty cmd.upd0 = HAL_REO_CMD_UPD0_BA_WINDOW_SIZE; 793d5c65159SKalle Valo cmd.ba_window_size = ba_win_sz; 794fe201947SVenkateswara Naralasetty 795fe201947SVenkateswara Naralasetty if (update_ssn) { 796fe201947SVenkateswara Naralasetty cmd.upd0 |= HAL_REO_CMD_UPD0_SSN; 797d5c65159SKalle Valo cmd.upd2 = FIELD_PREP(HAL_REO_CMD_UPD2_SSN, ssn); 798fe201947SVenkateswara Naralasetty } 799d5c65159SKalle Valo 800d5c65159SKalle Valo ret = ath11k_dp_tx_send_reo_cmd(ar->ab, rx_tid, 801d5c65159SKalle Valo HAL_REO_CMD_UPDATE_RX_QUEUE, &cmd, 802d5c65159SKalle Valo NULL); 803d5c65159SKalle Valo if (ret) { 804d5c65159SKalle Valo ath11k_warn(ar->ab, "failed to update rx tid queue, tid %d (%d)\n", 805d5c65159SKalle Valo rx_tid->tid, ret); 806d5c65159SKalle Valo return ret; 807d5c65159SKalle Valo } 808d5c65159SKalle Valo 809d5c65159SKalle Valo rx_tid->ba_win_sz = ba_win_sz; 810d5c65159SKalle Valo 811d5c65159SKalle Valo return 0; 812d5c65159SKalle Valo } 813d5c65159SKalle Valo 814d5c65159SKalle Valo static void ath11k_dp_rx_tid_mem_free(struct ath11k_base *ab, 815d5c65159SKalle Valo const u8 *peer_mac, int vdev_id, u8 tid) 816d5c65159SKalle Valo { 817d5c65159SKalle Valo struct ath11k_peer *peer; 818d5c65159SKalle Valo struct dp_rx_tid *rx_tid; 819d5c65159SKalle Valo 820d5c65159SKalle Valo spin_lock_bh(&ab->base_lock); 821d5c65159SKalle Valo 822d5c65159SKalle Valo peer = ath11k_peer_find(ab, vdev_id, peer_mac); 823d5c65159SKalle Valo if (!peer) { 824d5c65159SKalle Valo ath11k_warn(ab, "failed to find the peer to free up rx tid mem\n"); 825d5c65159SKalle Valo goto unlock_exit; 826d5c65159SKalle Valo } 827d5c65159SKalle Valo 828d5c65159SKalle Valo rx_tid = &peer->rx_tid[tid]; 829d5c65159SKalle Valo if (!rx_tid->active) 830d5c65159SKalle Valo goto unlock_exit; 831d5c65159SKalle Valo 832d5c65159SKalle Valo dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, 833d5c65159SKalle Valo DMA_BIDIRECTIONAL); 834d5c65159SKalle Valo kfree(rx_tid->vaddr); 835d5c65159SKalle Valo 836d5c65159SKalle Valo rx_tid->active = false; 837d5c65159SKalle Valo 838d5c65159SKalle Valo unlock_exit: 839d5c65159SKalle Valo spin_unlock_bh(&ab->base_lock); 840d5c65159SKalle Valo } 841d5c65159SKalle Valo 842d5c65159SKalle Valo int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id, 8431441b2f2SManikanta Pubbisetty u8 tid, u32 ba_win_sz, u16 ssn, 8441441b2f2SManikanta Pubbisetty enum hal_pn_type pn_type) 845d5c65159SKalle Valo { 846d5c65159SKalle Valo struct ath11k_base *ab = ar->ab; 847d5c65159SKalle Valo struct ath11k_peer *peer; 848d5c65159SKalle Valo struct dp_rx_tid *rx_tid; 849d5c65159SKalle Valo u32 hw_desc_sz; 850d5c65159SKalle Valo u32 *addr_aligned; 851d5c65159SKalle Valo void *vaddr; 852d5c65159SKalle Valo dma_addr_t paddr; 853d5c65159SKalle Valo int ret; 854d5c65159SKalle Valo 855d5c65159SKalle Valo spin_lock_bh(&ab->base_lock); 856d5c65159SKalle Valo 857d5c65159SKalle Valo peer = ath11k_peer_find(ab, vdev_id, peer_mac); 858d5c65159SKalle Valo if (!peer) { 859d5c65159SKalle Valo ath11k_warn(ab, "failed to find the peer to set up rx tid\n"); 860d5c65159SKalle Valo spin_unlock_bh(&ab->base_lock); 861d5c65159SKalle Valo return -ENOENT; 862d5c65159SKalle Valo } 863d5c65159SKalle Valo 864d5c65159SKalle Valo rx_tid = &peer->rx_tid[tid]; 865d5c65159SKalle Valo /* Update the tid queue if it is already setup */ 866d5c65159SKalle Valo if (rx_tid->active) { 867d5c65159SKalle Valo paddr = rx_tid->paddr; 868d5c65159SKalle Valo ret = ath11k_peer_rx_tid_reo_update(ar, peer, rx_tid, 869fe201947SVenkateswara Naralasetty ba_win_sz, ssn, true); 870d5c65159SKalle Valo spin_unlock_bh(&ab->base_lock); 871d5c65159SKalle Valo if (ret) { 872d5c65159SKalle Valo ath11k_warn(ab, "failed to update reo for rx tid %d\n", tid); 873d5c65159SKalle Valo return ret; 874d5c65159SKalle Valo } 875d5c65159SKalle Valo 876d5c65159SKalle Valo ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, 877d5c65159SKalle Valo peer_mac, paddr, 878d5c65159SKalle Valo tid, 1, ba_win_sz); 879d5c65159SKalle Valo if (ret) 880d5c65159SKalle Valo ath11k_warn(ab, "failed to send wmi command to update rx reorder queue, tid :%d (%d)\n", 881d5c65159SKalle Valo tid, ret); 882d5c65159SKalle Valo return ret; 883d5c65159SKalle Valo } 884d5c65159SKalle Valo 885d5c65159SKalle Valo rx_tid->tid = tid; 886d5c65159SKalle Valo 887d5c65159SKalle Valo rx_tid->ba_win_sz = ba_win_sz; 888d5c65159SKalle Valo 889d5c65159SKalle Valo /* TODO: Optimize the memory allocation for qos tid based on the 890d5c65159SKalle Valo * the actual BA window size in REO tid update path. 891d5c65159SKalle Valo */ 892d5c65159SKalle Valo if (tid == HAL_DESC_REO_NON_QOS_TID) 893d5c65159SKalle Valo hw_desc_sz = ath11k_hal_reo_qdesc_size(ba_win_sz, tid); 894d5c65159SKalle Valo else 895d5c65159SKalle Valo hw_desc_sz = ath11k_hal_reo_qdesc_size(DP_BA_WIN_SZ_MAX, tid); 896d5c65159SKalle Valo 89769c93f96SWei Yongjun vaddr = kzalloc(hw_desc_sz + HAL_LINK_DESC_ALIGN - 1, GFP_ATOMIC); 898d5c65159SKalle Valo if (!vaddr) { 899d5c65159SKalle Valo spin_unlock_bh(&ab->base_lock); 900d5c65159SKalle Valo return -ENOMEM; 901d5c65159SKalle Valo } 902d5c65159SKalle Valo 903d5c65159SKalle Valo addr_aligned = PTR_ALIGN(vaddr, HAL_LINK_DESC_ALIGN); 904d5c65159SKalle Valo 9051441b2f2SManikanta Pubbisetty ath11k_hal_reo_qdesc_setup(addr_aligned, tid, ba_win_sz, 9061441b2f2SManikanta Pubbisetty ssn, pn_type); 907d5c65159SKalle Valo 908d5c65159SKalle Valo paddr = dma_map_single(ab->dev, addr_aligned, hw_desc_sz, 909d5c65159SKalle Valo DMA_BIDIRECTIONAL); 910d5c65159SKalle Valo 911d5c65159SKalle Valo ret = dma_mapping_error(ab->dev, paddr); 912d5c65159SKalle Valo if (ret) { 913d5c65159SKalle Valo spin_unlock_bh(&ab->base_lock); 914d5c65159SKalle Valo goto err_mem_free; 915d5c65159SKalle Valo } 916d5c65159SKalle Valo 917d5c65159SKalle Valo rx_tid->vaddr = vaddr; 918d5c65159SKalle Valo rx_tid->paddr = paddr; 919d5c65159SKalle Valo rx_tid->size = hw_desc_sz; 920d5c65159SKalle Valo rx_tid->active = true; 921d5c65159SKalle Valo 922d5c65159SKalle Valo spin_unlock_bh(&ab->base_lock); 923d5c65159SKalle Valo 924d5c65159SKalle Valo ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac, 925d5c65159SKalle Valo paddr, tid, 1, ba_win_sz); 926d5c65159SKalle Valo if (ret) { 927d5c65159SKalle Valo ath11k_warn(ar->ab, "failed to setup rx reorder queue, tid :%d (%d)\n", 928d5c65159SKalle Valo tid, ret); 929d5c65159SKalle Valo ath11k_dp_rx_tid_mem_free(ab, peer_mac, vdev_id, tid); 930d5c65159SKalle Valo } 931d5c65159SKalle Valo 932d5c65159SKalle Valo return ret; 933d5c65159SKalle Valo 934d5c65159SKalle Valo err_mem_free: 935d5c65159SKalle Valo kfree(vaddr); 936d5c65159SKalle Valo 937d5c65159SKalle Valo return ret; 938d5c65159SKalle Valo } 939d5c65159SKalle Valo 940d5c65159SKalle Valo int ath11k_dp_rx_ampdu_start(struct ath11k *ar, 941d5c65159SKalle Valo struct ieee80211_ampdu_params *params) 942d5c65159SKalle Valo { 943d5c65159SKalle Valo struct ath11k_base *ab = ar->ab; 944d5c65159SKalle Valo struct ath11k_sta *arsta = (void *)params->sta->drv_priv; 945d5c65159SKalle Valo int vdev_id = arsta->arvif->vdev_id; 946d5c65159SKalle Valo int ret; 947d5c65159SKalle Valo 948d5c65159SKalle Valo ret = ath11k_peer_rx_tid_setup(ar, params->sta->addr, vdev_id, 949d5c65159SKalle Valo params->tid, params->buf_size, 9501441b2f2SManikanta Pubbisetty params->ssn, arsta->pn_type); 951d5c65159SKalle Valo if (ret) 952d5c65159SKalle Valo ath11k_warn(ab, "failed to setup rx tid %d\n", ret); 953d5c65159SKalle Valo 954d5c65159SKalle Valo return ret; 955d5c65159SKalle Valo } 956d5c65159SKalle Valo 957d5c65159SKalle Valo int ath11k_dp_rx_ampdu_stop(struct ath11k *ar, 958d5c65159SKalle Valo struct ieee80211_ampdu_params *params) 959d5c65159SKalle Valo { 960d5c65159SKalle Valo struct ath11k_base *ab = ar->ab; 961d5c65159SKalle Valo struct ath11k_peer *peer; 962d5c65159SKalle Valo struct ath11k_sta *arsta = (void *)params->sta->drv_priv; 963d5c65159SKalle Valo int vdev_id = arsta->arvif->vdev_id; 964d5c65159SKalle Valo dma_addr_t paddr; 965d5c65159SKalle Valo bool active; 966d5c65159SKalle Valo int ret; 967d5c65159SKalle Valo 968d5c65159SKalle Valo spin_lock_bh(&ab->base_lock); 969d5c65159SKalle Valo 970d5c65159SKalle Valo peer = ath11k_peer_find(ab, vdev_id, params->sta->addr); 971d5c65159SKalle Valo if (!peer) { 972d5c65159SKalle Valo ath11k_warn(ab, "failed to find the peer to stop rx aggregation\n"); 973d5c65159SKalle Valo spin_unlock_bh(&ab->base_lock); 974d5c65159SKalle Valo return -ENOENT; 975d5c65159SKalle Valo } 976d5c65159SKalle Valo 977d5c65159SKalle Valo paddr = peer->rx_tid[params->tid].paddr; 978d5c65159SKalle Valo active = peer->rx_tid[params->tid].active; 979d5c65159SKalle Valo 980fe201947SVenkateswara Naralasetty if (!active) { 981d5c65159SKalle Valo spin_unlock_bh(&ab->base_lock); 982d5c65159SKalle Valo return 0; 983fe201947SVenkateswara Naralasetty } 984fe201947SVenkateswara Naralasetty 985fe201947SVenkateswara Naralasetty ret = ath11k_peer_rx_tid_reo_update(ar, peer, peer->rx_tid, 1, 0, false); 986fe201947SVenkateswara Naralasetty spin_unlock_bh(&ab->base_lock); 987fe201947SVenkateswara Naralasetty if (ret) { 988fe201947SVenkateswara Naralasetty ath11k_warn(ab, "failed to update reo for rx tid %d: %d\n", 989fe201947SVenkateswara Naralasetty params->tid, ret); 990fe201947SVenkateswara Naralasetty return ret; 991fe201947SVenkateswara Naralasetty } 992d5c65159SKalle Valo 993d5c65159SKalle Valo ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, 994d5c65159SKalle Valo params->sta->addr, paddr, 995d5c65159SKalle Valo params->tid, 1, 1); 996d5c65159SKalle Valo if (ret) 997d5c65159SKalle Valo ath11k_warn(ab, "failed to send wmi to delete rx tid %d\n", 998d5c65159SKalle Valo ret); 999d5c65159SKalle Valo 1000d5c65159SKalle Valo return ret; 1001d5c65159SKalle Valo } 1002d5c65159SKalle Valo 10031441b2f2SManikanta Pubbisetty int ath11k_dp_peer_rx_pn_replay_config(struct ath11k_vif *arvif, 10041441b2f2SManikanta Pubbisetty const u8 *peer_addr, 10051441b2f2SManikanta Pubbisetty enum set_key_cmd key_cmd, 10061441b2f2SManikanta Pubbisetty struct ieee80211_key_conf *key) 10071441b2f2SManikanta Pubbisetty { 10081441b2f2SManikanta Pubbisetty struct ath11k *ar = arvif->ar; 10091441b2f2SManikanta Pubbisetty struct ath11k_base *ab = ar->ab; 10101441b2f2SManikanta Pubbisetty struct ath11k_hal_reo_cmd cmd = {0}; 10111441b2f2SManikanta Pubbisetty struct ath11k_peer *peer; 10121441b2f2SManikanta Pubbisetty struct dp_rx_tid *rx_tid; 10131441b2f2SManikanta Pubbisetty u8 tid; 10141441b2f2SManikanta Pubbisetty int ret = 0; 10151441b2f2SManikanta Pubbisetty 10161441b2f2SManikanta Pubbisetty /* NOTE: Enable PN/TSC replay check offload only for unicast frames. 10171441b2f2SManikanta Pubbisetty * We use mac80211 PN/TSC replay check functionality for bcast/mcast 10181441b2f2SManikanta Pubbisetty * for now. 10191441b2f2SManikanta Pubbisetty */ 10201441b2f2SManikanta Pubbisetty if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) 10211441b2f2SManikanta Pubbisetty return 0; 10221441b2f2SManikanta Pubbisetty 10231441b2f2SManikanta Pubbisetty cmd.flag |= HAL_REO_CMD_FLG_NEED_STATUS; 10241441b2f2SManikanta Pubbisetty cmd.upd0 |= HAL_REO_CMD_UPD0_PN | 10251441b2f2SManikanta Pubbisetty HAL_REO_CMD_UPD0_PN_SIZE | 10261441b2f2SManikanta Pubbisetty HAL_REO_CMD_UPD0_PN_VALID | 10271441b2f2SManikanta Pubbisetty HAL_REO_CMD_UPD0_PN_CHECK | 10281441b2f2SManikanta Pubbisetty HAL_REO_CMD_UPD0_SVLD; 10291441b2f2SManikanta Pubbisetty 10301441b2f2SManikanta Pubbisetty switch (key->cipher) { 10311441b2f2SManikanta Pubbisetty case WLAN_CIPHER_SUITE_TKIP: 10321441b2f2SManikanta Pubbisetty case WLAN_CIPHER_SUITE_CCMP: 10331441b2f2SManikanta Pubbisetty case WLAN_CIPHER_SUITE_CCMP_256: 10341441b2f2SManikanta Pubbisetty case WLAN_CIPHER_SUITE_GCMP: 10351441b2f2SManikanta Pubbisetty case WLAN_CIPHER_SUITE_GCMP_256: 10361441b2f2SManikanta Pubbisetty if (key_cmd == SET_KEY) { 10371441b2f2SManikanta Pubbisetty cmd.upd1 |= HAL_REO_CMD_UPD1_PN_CHECK; 10381441b2f2SManikanta Pubbisetty cmd.pn_size = 48; 10391441b2f2SManikanta Pubbisetty } 10401441b2f2SManikanta Pubbisetty break; 10411441b2f2SManikanta Pubbisetty default: 10421441b2f2SManikanta Pubbisetty break; 10431441b2f2SManikanta Pubbisetty } 10441441b2f2SManikanta Pubbisetty 10451441b2f2SManikanta Pubbisetty spin_lock_bh(&ab->base_lock); 10461441b2f2SManikanta Pubbisetty 10471441b2f2SManikanta Pubbisetty peer = ath11k_peer_find(ab, arvif->vdev_id, peer_addr); 10481441b2f2SManikanta Pubbisetty if (!peer) { 10491441b2f2SManikanta Pubbisetty ath11k_warn(ab, "failed to find the peer to configure pn replay detection\n"); 10501441b2f2SManikanta Pubbisetty spin_unlock_bh(&ab->base_lock); 10511441b2f2SManikanta Pubbisetty return -ENOENT; 10521441b2f2SManikanta Pubbisetty } 10531441b2f2SManikanta Pubbisetty 10541441b2f2SManikanta Pubbisetty for (tid = 0; tid <= IEEE80211_NUM_TIDS; tid++) { 10551441b2f2SManikanta Pubbisetty rx_tid = &peer->rx_tid[tid]; 10561441b2f2SManikanta Pubbisetty if (!rx_tid->active) 10571441b2f2SManikanta Pubbisetty continue; 10581441b2f2SManikanta Pubbisetty cmd.addr_lo = lower_32_bits(rx_tid->paddr); 10591441b2f2SManikanta Pubbisetty cmd.addr_hi = upper_32_bits(rx_tid->paddr); 10601441b2f2SManikanta Pubbisetty ret = ath11k_dp_tx_send_reo_cmd(ab, rx_tid, 10611441b2f2SManikanta Pubbisetty HAL_REO_CMD_UPDATE_RX_QUEUE, 10621441b2f2SManikanta Pubbisetty &cmd, NULL); 10631441b2f2SManikanta Pubbisetty if (ret) { 10641441b2f2SManikanta Pubbisetty ath11k_warn(ab, "failed to configure rx tid %d queue for pn replay detection %d\n", 10651441b2f2SManikanta Pubbisetty tid, ret); 10661441b2f2SManikanta Pubbisetty break; 10671441b2f2SManikanta Pubbisetty } 10681441b2f2SManikanta Pubbisetty } 10691441b2f2SManikanta Pubbisetty 10701441b2f2SManikanta Pubbisetty spin_unlock_bh(&ar->ab->base_lock); 10711441b2f2SManikanta Pubbisetty 10721441b2f2SManikanta Pubbisetty return ret; 10731441b2f2SManikanta Pubbisetty } 10741441b2f2SManikanta Pubbisetty 10751441b2f2SManikanta Pubbisetty static inline int ath11k_get_ppdu_user_index(struct htt_ppdu_stats *ppdu_stats, 1076d5c65159SKalle Valo u16 peer_id) 1077d5c65159SKalle Valo { 1078d5c65159SKalle Valo int i; 1079d5c65159SKalle Valo 1080d5c65159SKalle Valo for (i = 0; i < HTT_PPDU_STATS_MAX_USERS - 1; i++) { 1081d5c65159SKalle Valo if (ppdu_stats->user_stats[i].is_valid_peer_id) { 1082d5c65159SKalle Valo if (peer_id == ppdu_stats->user_stats[i].peer_id) 1083d5c65159SKalle Valo return i; 1084d5c65159SKalle Valo } else { 1085d5c65159SKalle Valo return i; 1086d5c65159SKalle Valo } 1087d5c65159SKalle Valo } 1088d5c65159SKalle Valo 1089d5c65159SKalle Valo return -EINVAL; 1090d5c65159SKalle Valo } 1091d5c65159SKalle Valo 1092d5c65159SKalle Valo static int ath11k_htt_tlv_ppdu_stats_parse(struct ath11k_base *ab, 1093d5c65159SKalle Valo u16 tag, u16 len, const void *ptr, 1094d5c65159SKalle Valo void *data) 1095d5c65159SKalle Valo { 1096d5c65159SKalle Valo struct htt_ppdu_stats_info *ppdu_info; 1097d5c65159SKalle Valo struct htt_ppdu_user_stats *user_stats; 1098d5c65159SKalle Valo int cur_user; 1099d5c65159SKalle Valo u16 peer_id; 1100d5c65159SKalle Valo 1101d5c65159SKalle Valo ppdu_info = (struct htt_ppdu_stats_info *)data; 1102d5c65159SKalle Valo 1103d5c65159SKalle Valo switch (tag) { 1104d5c65159SKalle Valo case HTT_PPDU_STATS_TAG_COMMON: 1105d5c65159SKalle Valo if (len < sizeof(struct htt_ppdu_stats_common)) { 1106d5c65159SKalle Valo ath11k_warn(ab, "Invalid len %d for the tag 0x%x\n", 1107d5c65159SKalle Valo len, tag); 1108d5c65159SKalle Valo return -EINVAL; 1109d5c65159SKalle Valo } 1110d5c65159SKalle Valo memcpy((void *)&ppdu_info->ppdu_stats.common, ptr, 1111d5c65159SKalle Valo sizeof(struct htt_ppdu_stats_common)); 1112d5c65159SKalle Valo break; 1113d5c65159SKalle Valo case HTT_PPDU_STATS_TAG_USR_RATE: 1114d5c65159SKalle Valo if (len < sizeof(struct htt_ppdu_stats_user_rate)) { 1115d5c65159SKalle Valo ath11k_warn(ab, "Invalid len %d for the tag 0x%x\n", 1116d5c65159SKalle Valo len, tag); 1117d5c65159SKalle Valo return -EINVAL; 1118d5c65159SKalle Valo } 1119d5c65159SKalle Valo 1120d5c65159SKalle Valo peer_id = ((struct htt_ppdu_stats_user_rate *)ptr)->sw_peer_id; 1121d5c65159SKalle Valo cur_user = ath11k_get_ppdu_user_index(&ppdu_info->ppdu_stats, 1122d5c65159SKalle Valo peer_id); 1123d5c65159SKalle Valo if (cur_user < 0) 1124d5c65159SKalle Valo return -EINVAL; 1125d5c65159SKalle Valo user_stats = &ppdu_info->ppdu_stats.user_stats[cur_user]; 1126d5c65159SKalle Valo user_stats->peer_id = peer_id; 1127d5c65159SKalle Valo user_stats->is_valid_peer_id = true; 1128d5c65159SKalle Valo memcpy((void *)&user_stats->rate, ptr, 1129d5c65159SKalle Valo sizeof(struct htt_ppdu_stats_user_rate)); 1130d5c65159SKalle Valo user_stats->tlv_flags |= BIT(tag); 1131d5c65159SKalle Valo break; 1132d5c65159SKalle Valo case HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON: 1133d5c65159SKalle Valo if (len < sizeof(struct htt_ppdu_stats_usr_cmpltn_cmn)) { 1134d5c65159SKalle Valo ath11k_warn(ab, "Invalid len %d for the tag 0x%x\n", 1135d5c65159SKalle Valo len, tag); 1136d5c65159SKalle Valo return -EINVAL; 1137d5c65159SKalle Valo } 1138d5c65159SKalle Valo 1139d5c65159SKalle Valo peer_id = ((struct htt_ppdu_stats_usr_cmpltn_cmn *)ptr)->sw_peer_id; 1140d5c65159SKalle Valo cur_user = ath11k_get_ppdu_user_index(&ppdu_info->ppdu_stats, 1141d5c65159SKalle Valo peer_id); 1142d5c65159SKalle Valo if (cur_user < 0) 1143d5c65159SKalle Valo return -EINVAL; 1144d5c65159SKalle Valo user_stats = &ppdu_info->ppdu_stats.user_stats[cur_user]; 1145d5c65159SKalle Valo user_stats->peer_id = peer_id; 1146d5c65159SKalle Valo user_stats->is_valid_peer_id = true; 1147d5c65159SKalle Valo memcpy((void *)&user_stats->cmpltn_cmn, ptr, 1148d5c65159SKalle Valo sizeof(struct htt_ppdu_stats_usr_cmpltn_cmn)); 1149d5c65159SKalle Valo user_stats->tlv_flags |= BIT(tag); 1150d5c65159SKalle Valo break; 1151d5c65159SKalle Valo case HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS: 1152d5c65159SKalle Valo if (len < 1153d5c65159SKalle Valo sizeof(struct htt_ppdu_stats_usr_cmpltn_ack_ba_status)) { 1154d5c65159SKalle Valo ath11k_warn(ab, "Invalid len %d for the tag 0x%x\n", 1155d5c65159SKalle Valo len, tag); 1156d5c65159SKalle Valo return -EINVAL; 1157d5c65159SKalle Valo } 1158d5c65159SKalle Valo 1159d5c65159SKalle Valo peer_id = 1160d5c65159SKalle Valo ((struct htt_ppdu_stats_usr_cmpltn_ack_ba_status *)ptr)->sw_peer_id; 1161d5c65159SKalle Valo cur_user = ath11k_get_ppdu_user_index(&ppdu_info->ppdu_stats, 1162d5c65159SKalle Valo peer_id); 1163d5c65159SKalle Valo if (cur_user < 0) 1164d5c65159SKalle Valo return -EINVAL; 1165d5c65159SKalle Valo user_stats = &ppdu_info->ppdu_stats.user_stats[cur_user]; 1166d5c65159SKalle Valo user_stats->peer_id = peer_id; 1167d5c65159SKalle Valo user_stats->is_valid_peer_id = true; 1168d5c65159SKalle Valo memcpy((void *)&user_stats->ack_ba, ptr, 1169d5c65159SKalle Valo sizeof(struct htt_ppdu_stats_usr_cmpltn_ack_ba_status)); 1170d5c65159SKalle Valo user_stats->tlv_flags |= BIT(tag); 1171d5c65159SKalle Valo break; 1172d5c65159SKalle Valo } 1173d5c65159SKalle Valo return 0; 1174d5c65159SKalle Valo } 1175d5c65159SKalle Valo 1176d5c65159SKalle Valo int ath11k_dp_htt_tlv_iter(struct ath11k_base *ab, const void *ptr, size_t len, 1177d5c65159SKalle Valo int (*iter)(struct ath11k_base *ar, u16 tag, u16 len, 1178d5c65159SKalle Valo const void *ptr, void *data), 1179d5c65159SKalle Valo void *data) 1180d5c65159SKalle Valo { 1181d5c65159SKalle Valo const struct htt_tlv *tlv; 1182d5c65159SKalle Valo const void *begin = ptr; 1183d5c65159SKalle Valo u16 tlv_tag, tlv_len; 1184d5c65159SKalle Valo int ret = -EINVAL; 1185d5c65159SKalle Valo 1186d5c65159SKalle Valo while (len > 0) { 1187d5c65159SKalle Valo if (len < sizeof(*tlv)) { 1188d5c65159SKalle Valo ath11k_err(ab, "htt tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n", 1189d5c65159SKalle Valo ptr - begin, len, sizeof(*tlv)); 1190d5c65159SKalle Valo return -EINVAL; 1191d5c65159SKalle Valo } 1192d5c65159SKalle Valo tlv = (struct htt_tlv *)ptr; 1193d5c65159SKalle Valo tlv_tag = FIELD_GET(HTT_TLV_TAG, tlv->header); 1194d5c65159SKalle Valo tlv_len = FIELD_GET(HTT_TLV_LEN, tlv->header); 1195d5c65159SKalle Valo ptr += sizeof(*tlv); 1196d5c65159SKalle Valo len -= sizeof(*tlv); 1197d5c65159SKalle Valo 1198d5c65159SKalle Valo if (tlv_len > len) { 1199d5c65159SKalle Valo ath11k_err(ab, "htt tlv parse failure of tag %hhu at byte %zd (%zu bytes left, %hhu expected)\n", 1200d5c65159SKalle Valo tlv_tag, ptr - begin, len, tlv_len); 1201d5c65159SKalle Valo return -EINVAL; 1202d5c65159SKalle Valo } 1203d5c65159SKalle Valo ret = iter(ab, tlv_tag, tlv_len, ptr, data); 1204d5c65159SKalle Valo if (ret == -ENOMEM) 1205d5c65159SKalle Valo return ret; 1206d5c65159SKalle Valo 1207d5c65159SKalle Valo ptr += tlv_len; 1208d5c65159SKalle Valo len -= tlv_len; 1209d5c65159SKalle Valo } 1210d5c65159SKalle Valo return 0; 1211d5c65159SKalle Valo } 1212d5c65159SKalle Valo 12136a0c3702SJohn Crispin static inline u32 ath11k_he_gi_to_nl80211_he_gi(u8 sgi) 12146a0c3702SJohn Crispin { 12156a0c3702SJohn Crispin u32 ret = 0; 12166a0c3702SJohn Crispin 12176a0c3702SJohn Crispin switch (sgi) { 12186a0c3702SJohn Crispin case RX_MSDU_START_SGI_0_8_US: 12196a0c3702SJohn Crispin ret = NL80211_RATE_INFO_HE_GI_0_8; 12206a0c3702SJohn Crispin break; 12216a0c3702SJohn Crispin case RX_MSDU_START_SGI_1_6_US: 12226a0c3702SJohn Crispin ret = NL80211_RATE_INFO_HE_GI_1_6; 12236a0c3702SJohn Crispin break; 12246a0c3702SJohn Crispin case RX_MSDU_START_SGI_3_2_US: 12256a0c3702SJohn Crispin ret = NL80211_RATE_INFO_HE_GI_3_2; 12266a0c3702SJohn Crispin break; 12276a0c3702SJohn Crispin } 12286a0c3702SJohn Crispin 12296a0c3702SJohn Crispin return ret; 12306a0c3702SJohn Crispin } 12316a0c3702SJohn Crispin 1232d5c65159SKalle Valo static void 1233d5c65159SKalle Valo ath11k_update_per_peer_tx_stats(struct ath11k *ar, 1234d5c65159SKalle Valo struct htt_ppdu_stats *ppdu_stats, u8 user) 1235d5c65159SKalle Valo { 1236d5c65159SKalle Valo struct ath11k_base *ab = ar->ab; 1237d5c65159SKalle Valo struct ath11k_peer *peer; 1238d5c65159SKalle Valo struct ieee80211_sta *sta; 1239d5c65159SKalle Valo struct ath11k_sta *arsta; 1240d5c65159SKalle Valo struct htt_ppdu_stats_user_rate *user_rate; 1241d5c65159SKalle Valo struct ath11k_per_peer_tx_stats *peer_stats = &ar->peer_tx_stats; 1242d5c65159SKalle Valo struct htt_ppdu_user_stats *usr_stats = &ppdu_stats->user_stats[user]; 1243d5c65159SKalle Valo struct htt_ppdu_stats_common *common = &ppdu_stats->common; 1244d5c65159SKalle Valo int ret; 12456a0c3702SJohn Crispin u8 flags, mcs, nss, bw, sgi, dcm, rate_idx = 0; 1246d5c65159SKalle Valo u32 succ_bytes = 0; 1247d5c65159SKalle Valo u16 rate = 0, succ_pkts = 0; 1248d5c65159SKalle Valo u32 tx_duration = 0; 1249b9269a07SVenkateswara Naralasetty u8 tid = HTT_PPDU_STATS_NON_QOS_TID; 1250d5c65159SKalle Valo bool is_ampdu = false; 1251d5c65159SKalle Valo 1252d5c65159SKalle Valo if (!usr_stats) 1253d5c65159SKalle Valo return; 1254d5c65159SKalle Valo 1255d5c65159SKalle Valo if (!(usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_RATE))) 1256d5c65159SKalle Valo return; 1257d5c65159SKalle Valo 1258d5c65159SKalle Valo if (usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON)) 1259d5c65159SKalle Valo is_ampdu = 1260d5c65159SKalle Valo HTT_USR_CMPLTN_IS_AMPDU(usr_stats->cmpltn_cmn.flags); 1261d5c65159SKalle Valo 1262d5c65159SKalle Valo if (usr_stats->tlv_flags & 1263d5c65159SKalle Valo BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS)) { 1264d5c65159SKalle Valo succ_bytes = usr_stats->ack_ba.success_bytes; 1265d5c65159SKalle Valo succ_pkts = FIELD_GET(HTT_PPDU_STATS_ACK_BA_INFO_NUM_MSDU_M, 1266d5c65159SKalle Valo usr_stats->ack_ba.info); 1267b9269a07SVenkateswara Naralasetty tid = FIELD_GET(HTT_PPDU_STATS_ACK_BA_INFO_TID_NUM, 1268b9269a07SVenkateswara Naralasetty usr_stats->ack_ba.info); 1269d5c65159SKalle Valo } 1270d5c65159SKalle Valo 1271d5c65159SKalle Valo if (common->fes_duration_us) 1272d5c65159SKalle Valo tx_duration = common->fes_duration_us; 1273d5c65159SKalle Valo 1274d5c65159SKalle Valo user_rate = &usr_stats->rate; 1275d5c65159SKalle Valo flags = HTT_USR_RATE_PREAMBLE(user_rate->rate_flags); 1276d5c65159SKalle Valo bw = HTT_USR_RATE_BW(user_rate->rate_flags) - 2; 1277d5c65159SKalle Valo nss = HTT_USR_RATE_NSS(user_rate->rate_flags) + 1; 1278d5c65159SKalle Valo mcs = HTT_USR_RATE_MCS(user_rate->rate_flags); 1279d5c65159SKalle Valo sgi = HTT_USR_RATE_GI(user_rate->rate_flags); 12806a0c3702SJohn Crispin dcm = HTT_USR_RATE_DCM(user_rate->rate_flags); 1281d5c65159SKalle Valo 1282d5c65159SKalle Valo /* Note: If host configured fixed rates and in some other special 1283d5c65159SKalle Valo * cases, the broadcast/management frames are sent in different rates. 1284d5c65159SKalle Valo * Firmware rate's control to be skipped for this? 1285d5c65159SKalle Valo */ 1286d5c65159SKalle Valo 12876a0c3702SJohn Crispin if (flags == WMI_RATE_PREAMBLE_HE && mcs > 11) { 12886a0c3702SJohn Crispin ath11k_warn(ab, "Invalid HE mcs %hhd peer stats", mcs); 12896a0c3702SJohn Crispin return; 12906a0c3702SJohn Crispin } 12916a0c3702SJohn Crispin 12926a0c3702SJohn Crispin if (flags == WMI_RATE_PREAMBLE_HE && mcs > ATH11K_HE_MCS_MAX) { 12936a0c3702SJohn Crispin ath11k_warn(ab, "Invalid HE mcs %hhd peer stats", mcs); 12946a0c3702SJohn Crispin return; 12956a0c3702SJohn Crispin } 12966a0c3702SJohn Crispin 12976a0c3702SJohn Crispin if (flags == WMI_RATE_PREAMBLE_VHT && mcs > ATH11K_VHT_MCS_MAX) { 1298d5c65159SKalle Valo ath11k_warn(ab, "Invalid VHT mcs %hhd peer stats", mcs); 1299d5c65159SKalle Valo return; 1300d5c65159SKalle Valo } 1301d5c65159SKalle Valo 13026a0c3702SJohn Crispin if (flags == WMI_RATE_PREAMBLE_HT && (mcs > ATH11K_HT_MCS_MAX || nss < 1)) { 1303d5c65159SKalle Valo ath11k_warn(ab, "Invalid HT mcs %hhd nss %hhd peer stats", 1304d5c65159SKalle Valo mcs, nss); 1305d5c65159SKalle Valo return; 1306d5c65159SKalle Valo } 1307d5c65159SKalle Valo 1308d5c65159SKalle Valo if (flags == WMI_RATE_PREAMBLE_CCK || flags == WMI_RATE_PREAMBLE_OFDM) { 1309d5c65159SKalle Valo ret = ath11k_mac_hw_ratecode_to_legacy_rate(mcs, 1310d5c65159SKalle Valo flags, 1311d5c65159SKalle Valo &rate_idx, 1312d5c65159SKalle Valo &rate); 1313d5c65159SKalle Valo if (ret < 0) 1314d5c65159SKalle Valo return; 1315d5c65159SKalle Valo } 1316d5c65159SKalle Valo 1317d5c65159SKalle Valo rcu_read_lock(); 1318d5c65159SKalle Valo spin_lock_bh(&ab->base_lock); 1319d5c65159SKalle Valo peer = ath11k_peer_find_by_id(ab, usr_stats->peer_id); 1320d5c65159SKalle Valo 1321d5c65159SKalle Valo if (!peer || !peer->sta) { 1322d5c65159SKalle Valo spin_unlock_bh(&ab->base_lock); 1323d5c65159SKalle Valo rcu_read_unlock(); 1324d5c65159SKalle Valo return; 1325d5c65159SKalle Valo } 1326d5c65159SKalle Valo 1327d5c65159SKalle Valo sta = peer->sta; 1328d5c65159SKalle Valo arsta = (struct ath11k_sta *)sta->drv_priv; 1329d5c65159SKalle Valo 1330d5c65159SKalle Valo memset(&arsta->txrate, 0, sizeof(arsta->txrate)); 1331d5c65159SKalle Valo 1332d5c65159SKalle Valo switch (flags) { 1333d5c65159SKalle Valo case WMI_RATE_PREAMBLE_OFDM: 1334d5c65159SKalle Valo arsta->txrate.legacy = rate; 1335d5c65159SKalle Valo break; 1336d5c65159SKalle Valo case WMI_RATE_PREAMBLE_CCK: 1337d5c65159SKalle Valo arsta->txrate.legacy = rate; 1338d5c65159SKalle Valo break; 1339d5c65159SKalle Valo case WMI_RATE_PREAMBLE_HT: 1340d5c65159SKalle Valo arsta->txrate.mcs = mcs + 8 * (nss - 1); 1341d5c65159SKalle Valo arsta->txrate.flags = RATE_INFO_FLAGS_MCS; 1342be43ce64SJohn Crispin if (sgi) 1343d5c65159SKalle Valo arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; 1344d5c65159SKalle Valo break; 1345d5c65159SKalle Valo case WMI_RATE_PREAMBLE_VHT: 1346d5c65159SKalle Valo arsta->txrate.mcs = mcs; 1347d5c65159SKalle Valo arsta->txrate.flags = RATE_INFO_FLAGS_VHT_MCS; 1348be43ce64SJohn Crispin if (sgi) 1349d5c65159SKalle Valo arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; 1350d5c65159SKalle Valo break; 13516a0c3702SJohn Crispin case WMI_RATE_PREAMBLE_HE: 13526a0c3702SJohn Crispin arsta->txrate.mcs = mcs; 13536a0c3702SJohn Crispin arsta->txrate.flags = RATE_INFO_FLAGS_HE_MCS; 13546a0c3702SJohn Crispin arsta->txrate.he_dcm = dcm; 13556a0c3702SJohn Crispin arsta->txrate.he_gi = ath11k_he_gi_to_nl80211_he_gi(sgi); 13566a0c3702SJohn Crispin arsta->txrate.he_ru_alloc = ath11k_he_ru_tones_to_nl80211_he_ru_alloc( 13576a0c3702SJohn Crispin (user_rate->ru_end - 13586a0c3702SJohn Crispin user_rate->ru_start) + 1); 13596a0c3702SJohn Crispin break; 1360d5c65159SKalle Valo } 1361d5c65159SKalle Valo 1362d5c65159SKalle Valo arsta->txrate.nss = nss; 136339e81c6aSTamizh chelvam arsta->txrate.bw = ath11k_mac_bw_to_mac80211_bw(bw); 1364a9e945eaSVenkateswara Naralasetty arsta->tx_duration += tx_duration; 1365d5c65159SKalle Valo memcpy(&arsta->last_txrate, &arsta->txrate, sizeof(struct rate_info)); 1366d5c65159SKalle Valo 1367b9269a07SVenkateswara Naralasetty /* PPDU stats reported for mgmt packet doesn't have valid tx bytes. 1368b9269a07SVenkateswara Naralasetty * So skip peer stats update for mgmt packets. 1369b9269a07SVenkateswara Naralasetty */ 1370b9269a07SVenkateswara Naralasetty if (tid < HTT_PPDU_STATS_NON_QOS_TID) { 1371d5c65159SKalle Valo memset(peer_stats, 0, sizeof(*peer_stats)); 1372d5c65159SKalle Valo peer_stats->succ_pkts = succ_pkts; 1373d5c65159SKalle Valo peer_stats->succ_bytes = succ_bytes; 1374d5c65159SKalle Valo peer_stats->is_ampdu = is_ampdu; 1375d5c65159SKalle Valo peer_stats->duration = tx_duration; 1376d5c65159SKalle Valo peer_stats->ba_fails = 1377d5c65159SKalle Valo HTT_USR_CMPLTN_LONG_RETRY(usr_stats->cmpltn_cmn.flags) + 1378d5c65159SKalle Valo HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags); 1379d5c65159SKalle Valo 1380d5c65159SKalle Valo if (ath11k_debug_is_extd_tx_stats_enabled(ar)) 1381d5c65159SKalle Valo ath11k_accumulate_per_peer_tx_stats(arsta, 1382d5c65159SKalle Valo peer_stats, rate_idx); 1383b9269a07SVenkateswara Naralasetty } 1384d5c65159SKalle Valo 1385d5c65159SKalle Valo spin_unlock_bh(&ab->base_lock); 1386d5c65159SKalle Valo rcu_read_unlock(); 1387d5c65159SKalle Valo } 1388d5c65159SKalle Valo 1389d5c65159SKalle Valo static void ath11k_htt_update_ppdu_stats(struct ath11k *ar, 1390d5c65159SKalle Valo struct htt_ppdu_stats *ppdu_stats) 1391d5c65159SKalle Valo { 1392d5c65159SKalle Valo u8 user; 1393d5c65159SKalle Valo 1394d5c65159SKalle Valo for (user = 0; user < HTT_PPDU_STATS_MAX_USERS - 1; user++) 1395d5c65159SKalle Valo ath11k_update_per_peer_tx_stats(ar, ppdu_stats, user); 1396d5c65159SKalle Valo } 1397d5c65159SKalle Valo 1398d5c65159SKalle Valo static 1399d5c65159SKalle Valo struct htt_ppdu_stats_info *ath11k_dp_htt_get_ppdu_desc(struct ath11k *ar, 1400d5c65159SKalle Valo u32 ppdu_id) 1401d5c65159SKalle Valo { 1402269663f1SDan Carpenter struct htt_ppdu_stats_info *ppdu_info; 1403d5c65159SKalle Valo 1404d5c65159SKalle Valo spin_lock_bh(&ar->data_lock); 1405d5c65159SKalle Valo if (!list_empty(&ar->ppdu_stats_info)) { 1406d5c65159SKalle Valo list_for_each_entry(ppdu_info, &ar->ppdu_stats_info, list) { 1407269663f1SDan Carpenter if (ppdu_info->ppdu_id == ppdu_id) { 1408d5c65159SKalle Valo spin_unlock_bh(&ar->data_lock); 1409d5c65159SKalle Valo return ppdu_info; 1410d5c65159SKalle Valo } 1411d5c65159SKalle Valo } 1412d5c65159SKalle Valo 1413d5c65159SKalle Valo if (ar->ppdu_stat_list_depth > HTT_PPDU_DESC_MAX_DEPTH) { 1414d5c65159SKalle Valo ppdu_info = list_first_entry(&ar->ppdu_stats_info, 1415d5c65159SKalle Valo typeof(*ppdu_info), list); 1416d5c65159SKalle Valo list_del(&ppdu_info->list); 1417d5c65159SKalle Valo ar->ppdu_stat_list_depth--; 1418d5c65159SKalle Valo ath11k_htt_update_ppdu_stats(ar, &ppdu_info->ppdu_stats); 1419d5c65159SKalle Valo kfree(ppdu_info); 1420d5c65159SKalle Valo } 1421d5c65159SKalle Valo } 1422d5c65159SKalle Valo spin_unlock_bh(&ar->data_lock); 1423d5c65159SKalle Valo 1424d5c65159SKalle Valo ppdu_info = kzalloc(sizeof(*ppdu_info), GFP_KERNEL); 1425d5c65159SKalle Valo if (!ppdu_info) 1426d5c65159SKalle Valo return NULL; 1427d5c65159SKalle Valo 1428d5c65159SKalle Valo spin_lock_bh(&ar->data_lock); 1429d5c65159SKalle Valo list_add_tail(&ppdu_info->list, &ar->ppdu_stats_info); 1430d5c65159SKalle Valo ar->ppdu_stat_list_depth++; 1431d5c65159SKalle Valo spin_unlock_bh(&ar->data_lock); 1432d5c65159SKalle Valo 1433d5c65159SKalle Valo return ppdu_info; 1434d5c65159SKalle Valo } 1435d5c65159SKalle Valo 1436d5c65159SKalle Valo static int ath11k_htt_pull_ppdu_stats(struct ath11k_base *ab, 1437d5c65159SKalle Valo struct sk_buff *skb) 1438d5c65159SKalle Valo { 1439d5c65159SKalle Valo struct ath11k_htt_ppdu_stats_msg *msg; 1440d5c65159SKalle Valo struct htt_ppdu_stats_info *ppdu_info; 1441d5c65159SKalle Valo struct ath11k *ar; 1442d5c65159SKalle Valo int ret; 1443d5c65159SKalle Valo u8 pdev_id; 1444d5c65159SKalle Valo u32 ppdu_id, len; 1445d5c65159SKalle Valo 1446d5c65159SKalle Valo msg = (struct ath11k_htt_ppdu_stats_msg *)skb->data; 1447d5c65159SKalle Valo len = FIELD_GET(HTT_T2H_PPDU_STATS_INFO_PAYLOAD_SIZE, msg->info); 1448d5c65159SKalle Valo pdev_id = FIELD_GET(HTT_T2H_PPDU_STATS_INFO_PDEV_ID, msg->info); 1449d5c65159SKalle Valo ppdu_id = msg->ppdu_id; 1450d5c65159SKalle Valo 1451d5c65159SKalle Valo rcu_read_lock(); 1452d5c65159SKalle Valo ar = ath11k_mac_get_ar_by_pdev_id(ab, pdev_id); 1453d5c65159SKalle Valo if (!ar) { 1454d5c65159SKalle Valo ret = -EINVAL; 1455d5c65159SKalle Valo goto exit; 1456d5c65159SKalle Valo } 1457d5c65159SKalle Valo 1458d5c65159SKalle Valo if (ath11k_debug_is_pktlog_lite_mode_enabled(ar)) 1459d5c65159SKalle Valo trace_ath11k_htt_ppdu_stats(ar, skb->data, len); 1460d5c65159SKalle Valo 1461d5c65159SKalle Valo ppdu_info = ath11k_dp_htt_get_ppdu_desc(ar, ppdu_id); 1462d5c65159SKalle Valo if (!ppdu_info) { 1463d5c65159SKalle Valo ret = -EINVAL; 1464d5c65159SKalle Valo goto exit; 1465d5c65159SKalle Valo } 1466d5c65159SKalle Valo 1467d5c65159SKalle Valo ppdu_info->ppdu_id = ppdu_id; 1468d5c65159SKalle Valo ret = ath11k_dp_htt_tlv_iter(ab, msg->data, len, 1469d5c65159SKalle Valo ath11k_htt_tlv_ppdu_stats_parse, 1470d5c65159SKalle Valo (void *)ppdu_info); 1471d5c65159SKalle Valo if (ret) { 1472d5c65159SKalle Valo ath11k_warn(ab, "Failed to parse tlv %d\n", ret); 1473d5c65159SKalle Valo goto exit; 1474d5c65159SKalle Valo } 1475d5c65159SKalle Valo 1476d5c65159SKalle Valo exit: 1477d5c65159SKalle Valo rcu_read_unlock(); 1478d5c65159SKalle Valo 1479d5c65159SKalle Valo return ret; 1480d5c65159SKalle Valo } 1481d5c65159SKalle Valo 1482d5c65159SKalle Valo static void ath11k_htt_pktlog(struct ath11k_base *ab, struct sk_buff *skb) 1483d5c65159SKalle Valo { 1484d5c65159SKalle Valo struct htt_pktlog_msg *data = (struct htt_pktlog_msg *)skb->data; 1485443d2ee7SAnilkumar Kolli struct ath_pktlog_hdr *hdr = (struct ath_pktlog_hdr *)data; 1486d5c65159SKalle Valo struct ath11k *ar; 1487d5c65159SKalle Valo u8 pdev_id; 1488d5c65159SKalle Valo 1489d5c65159SKalle Valo pdev_id = FIELD_GET(HTT_T2H_PPDU_STATS_INFO_PDEV_ID, data->hdr); 1490d0f390eaSAnilkumar Kolli ar = ath11k_mac_get_ar_by_pdev_id(ab, pdev_id); 1491d0f390eaSAnilkumar Kolli if (!ar) { 1492d0f390eaSAnilkumar Kolli ath11k_warn(ab, "invalid pdev id %d on htt pktlog\n", pdev_id); 1493d0f390eaSAnilkumar Kolli return; 1494d0f390eaSAnilkumar Kolli } 1495d5c65159SKalle Valo 149621c1b063SMaharaja Kennadyrajan trace_ath11k_htt_pktlog(ar, data->payload, hdr->size, 149721c1b063SMaharaja Kennadyrajan ar->ab->pktlog_defs_checksum); 1498d5c65159SKalle Valo } 1499d5c65159SKalle Valo 1500678e8414SSriram R static void ath11k_htt_backpressure_event_handler(struct ath11k_base *ab, 1501678e8414SSriram R struct sk_buff *skb) 1502678e8414SSriram R { 1503678e8414SSriram R u32 *data = (u32 *)skb->data; 150471fbc847SSriram R u8 pdev_id, ring_type, ring_id, pdev_idx; 1505678e8414SSriram R u16 hp, tp; 1506678e8414SSriram R u32 backpressure_time; 150771fbc847SSriram R struct ath11k_bp_stats *bp_stats; 1508678e8414SSriram R 1509678e8414SSriram R pdev_id = FIELD_GET(HTT_BACKPRESSURE_EVENT_PDEV_ID_M, *data); 1510678e8414SSriram R ring_type = FIELD_GET(HTT_BACKPRESSURE_EVENT_RING_TYPE_M, *data); 1511678e8414SSriram R ring_id = FIELD_GET(HTT_BACKPRESSURE_EVENT_RING_ID_M, *data); 1512678e8414SSriram R ++data; 1513678e8414SSriram R 1514678e8414SSriram R hp = FIELD_GET(HTT_BACKPRESSURE_EVENT_HP_M, *data); 1515678e8414SSriram R tp = FIELD_GET(HTT_BACKPRESSURE_EVENT_TP_M, *data); 1516678e8414SSriram R ++data; 1517678e8414SSriram R 1518678e8414SSriram R backpressure_time = *data; 1519678e8414SSriram R 1520678e8414SSriram R ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt backpressure event, pdev %d, ring type %d,ring id %d, hp %d tp %d, backpressure time %d\n", 1521678e8414SSriram R pdev_id, ring_type, ring_id, hp, tp, backpressure_time); 152271fbc847SSriram R 152371fbc847SSriram R if (ring_type == HTT_BACKPRESSURE_UMAC_RING_TYPE) { 152471fbc847SSriram R if (ring_id >= HTT_SW_UMAC_RING_IDX_MAX) 152571fbc847SSriram R return; 152671fbc847SSriram R 152771fbc847SSriram R bp_stats = &ab->soc_stats.bp_stats.umac_ring_bp_stats[ring_id]; 152871fbc847SSriram R } else if (ring_type == HTT_BACKPRESSURE_LMAC_RING_TYPE) { 152971fbc847SSriram R pdev_idx = DP_HW2SW_MACID(pdev_id); 153071fbc847SSriram R 153171fbc847SSriram R if (ring_id >= HTT_SW_LMAC_RING_IDX_MAX || pdev_idx >= MAX_RADIOS) 153271fbc847SSriram R return; 153371fbc847SSriram R 153471fbc847SSriram R bp_stats = &ab->soc_stats.bp_stats.lmac_ring_bp_stats[ring_id][pdev_idx]; 153571fbc847SSriram R } else { 153671fbc847SSriram R ath11k_warn(ab, "unknown ring type received in htt bp event %d\n", 153771fbc847SSriram R ring_type); 153871fbc847SSriram R return; 153971fbc847SSriram R } 154071fbc847SSriram R 154171fbc847SSriram R spin_lock_bh(&ab->base_lock); 154271fbc847SSriram R bp_stats->hp = hp; 154371fbc847SSriram R bp_stats->tp = tp; 154471fbc847SSriram R bp_stats->count++; 154571fbc847SSriram R bp_stats->jiffies = jiffies; 154671fbc847SSriram R spin_unlock_bh(&ab->base_lock); 1547678e8414SSriram R } 1548678e8414SSriram R 1549d5c65159SKalle Valo void ath11k_dp_htt_htc_t2h_msg_handler(struct ath11k_base *ab, 1550d5c65159SKalle Valo struct sk_buff *skb) 1551d5c65159SKalle Valo { 1552d5c65159SKalle Valo struct ath11k_dp *dp = &ab->dp; 1553d5c65159SKalle Valo struct htt_resp_msg *resp = (struct htt_resp_msg *)skb->data; 1554d5c65159SKalle Valo enum htt_t2h_msg_type type = FIELD_GET(HTT_T2H_MSG_TYPE, *(u32 *)resp); 1555d5c65159SKalle Valo u16 peer_id; 1556d5c65159SKalle Valo u8 vdev_id; 1557d5c65159SKalle Valo u8 mac_addr[ETH_ALEN]; 1558d5c65159SKalle Valo u16 peer_mac_h16; 1559d5c65159SKalle Valo u16 ast_hash; 1560d5c65159SKalle Valo 1561d5c65159SKalle Valo ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "dp_htt rx msg type :0x%0x\n", type); 1562d5c65159SKalle Valo 1563d5c65159SKalle Valo switch (type) { 1564d5c65159SKalle Valo case HTT_T2H_MSG_TYPE_VERSION_CONF: 1565d5c65159SKalle Valo dp->htt_tgt_ver_major = FIELD_GET(HTT_T2H_VERSION_CONF_MAJOR, 1566d5c65159SKalle Valo resp->version_msg.version); 1567d5c65159SKalle Valo dp->htt_tgt_ver_minor = FIELD_GET(HTT_T2H_VERSION_CONF_MINOR, 1568d5c65159SKalle Valo resp->version_msg.version); 1569d5c65159SKalle Valo complete(&dp->htt_tgt_version_received); 1570d5c65159SKalle Valo break; 1571d5c65159SKalle Valo case HTT_T2H_MSG_TYPE_PEER_MAP: 1572d5c65159SKalle Valo vdev_id = FIELD_GET(HTT_T2H_PEER_MAP_INFO_VDEV_ID, 1573d5c65159SKalle Valo resp->peer_map_ev.info); 1574d5c65159SKalle Valo peer_id = FIELD_GET(HTT_T2H_PEER_MAP_INFO_PEER_ID, 1575d5c65159SKalle Valo resp->peer_map_ev.info); 1576d5c65159SKalle Valo peer_mac_h16 = FIELD_GET(HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16, 1577d5c65159SKalle Valo resp->peer_map_ev.info1); 1578d5c65159SKalle Valo ath11k_dp_get_mac_addr(resp->peer_map_ev.mac_addr_l32, 1579d5c65159SKalle Valo peer_mac_h16, mac_addr); 1580d5c65159SKalle Valo ast_hash = FIELD_GET(HTT_T2H_PEER_MAP_INFO2_AST_HASH_VAL, 15810f37fbf4SAnilkumar Kolli resp->peer_map_ev.info2); 1582d5c65159SKalle Valo ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash); 1583d5c65159SKalle Valo break; 1584d5c65159SKalle Valo case HTT_T2H_MSG_TYPE_PEER_UNMAP: 1585d5c65159SKalle Valo peer_id = FIELD_GET(HTT_T2H_PEER_UNMAP_INFO_PEER_ID, 1586d5c65159SKalle Valo resp->peer_unmap_ev.info); 1587d5c65159SKalle Valo ath11k_peer_unmap_event(ab, peer_id); 1588d5c65159SKalle Valo break; 1589d5c65159SKalle Valo case HTT_T2H_MSG_TYPE_PPDU_STATS_IND: 1590d5c65159SKalle Valo ath11k_htt_pull_ppdu_stats(ab, skb); 1591d5c65159SKalle Valo break; 1592d5c65159SKalle Valo case HTT_T2H_MSG_TYPE_EXT_STATS_CONF: 1593d5c65159SKalle Valo ath11k_dbg_htt_ext_stats_handler(ab, skb); 1594d5c65159SKalle Valo break; 1595d5c65159SKalle Valo case HTT_T2H_MSG_TYPE_PKTLOG: 1596d5c65159SKalle Valo ath11k_htt_pktlog(ab, skb); 1597d5c65159SKalle Valo break; 1598678e8414SSriram R case HTT_T2H_MSG_TYPE_BKPRESSURE_EVENT_IND: 1599678e8414SSriram R ath11k_htt_backpressure_event_handler(ab, skb); 1600678e8414SSriram R break; 1601d5c65159SKalle Valo default: 1602d5c65159SKalle Valo ath11k_warn(ab, "htt event %d not handled\n", type); 1603d5c65159SKalle Valo break; 1604d5c65159SKalle Valo } 1605d5c65159SKalle Valo 1606d5c65159SKalle Valo dev_kfree_skb_any(skb); 1607d5c65159SKalle Valo } 1608d5c65159SKalle Valo 1609d5c65159SKalle Valo static int ath11k_dp_rx_msdu_coalesce(struct ath11k *ar, 1610d5c65159SKalle Valo struct sk_buff_head *msdu_list, 1611d5c65159SKalle Valo struct sk_buff *first, struct sk_buff *last, 1612d5c65159SKalle Valo u8 l3pad_bytes, int msdu_len) 1613d5c65159SKalle Valo { 1614d5c65159SKalle Valo struct sk_buff *skb; 1615d5c65159SKalle Valo struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(first); 1616d2f510faSSriram R int buf_first_hdr_len, buf_first_len; 1617d5c65159SKalle Valo struct hal_rx_desc *ldesc; 1618d5c65159SKalle Valo int space_extra; 1619d5c65159SKalle Valo int rem_len; 1620d5c65159SKalle Valo int buf_len; 1621d5c65159SKalle Valo 1622d2f510faSSriram R /* As the msdu is spread across multiple rx buffers, 1623d2f510faSSriram R * find the offset to the start of msdu for computing 1624d2f510faSSriram R * the length of the msdu in the first buffer. 1625d2f510faSSriram R */ 1626d2f510faSSriram R buf_first_hdr_len = HAL_RX_DESC_SIZE + l3pad_bytes; 1627d2f510faSSriram R buf_first_len = DP_RX_BUFFER_SIZE - buf_first_hdr_len; 1628d2f510faSSriram R 1629d2f510faSSriram R if (WARN_ON_ONCE(msdu_len <= buf_first_len)) { 1630d2f510faSSriram R skb_put(first, buf_first_hdr_len + msdu_len); 1631d2f510faSSriram R skb_pull(first, buf_first_hdr_len); 1632d5c65159SKalle Valo return 0; 1633d5c65159SKalle Valo } 1634d5c65159SKalle Valo 1635d5c65159SKalle Valo ldesc = (struct hal_rx_desc *)last->data; 1636d5c65159SKalle Valo rxcb->is_first_msdu = ath11k_dp_rx_h_msdu_end_first_msdu(ldesc); 1637d5c65159SKalle Valo rxcb->is_last_msdu = ath11k_dp_rx_h_msdu_end_last_msdu(ldesc); 1638d5c65159SKalle Valo 1639d5c65159SKalle Valo /* MSDU spans over multiple buffers because the length of the MSDU 1640d5c65159SKalle Valo * exceeds DP_RX_BUFFER_SIZE - HAL_RX_DESC_SIZE. So assume the data 1641d5c65159SKalle Valo * in the first buf is of length DP_RX_BUFFER_SIZE - HAL_RX_DESC_SIZE. 1642d5c65159SKalle Valo */ 1643d5c65159SKalle Valo skb_put(first, DP_RX_BUFFER_SIZE); 1644d2f510faSSriram R skb_pull(first, buf_first_hdr_len); 1645d5c65159SKalle Valo 164630679ec4SKarthikeyan Periyasamy /* When an MSDU spread over multiple buffers attention, MSDU_END and 164730679ec4SKarthikeyan Periyasamy * MPDU_END tlvs are valid only in the last buffer. Copy those tlvs. 164830679ec4SKarthikeyan Periyasamy */ 164930679ec4SKarthikeyan Periyasamy ath11k_dp_rx_desc_end_tlv_copy(rxcb->rx_desc, ldesc); 165030679ec4SKarthikeyan Periyasamy 1651d2f510faSSriram R space_extra = msdu_len - (buf_first_len + skb_tailroom(first)); 1652d5c65159SKalle Valo if (space_extra > 0 && 1653d5c65159SKalle Valo (pskb_expand_head(first, 0, space_extra, GFP_ATOMIC) < 0)) { 1654d5c65159SKalle Valo /* Free up all buffers of the MSDU */ 1655d5c65159SKalle Valo while ((skb = __skb_dequeue(msdu_list)) != NULL) { 1656d5c65159SKalle Valo rxcb = ATH11K_SKB_RXCB(skb); 1657d5c65159SKalle Valo if (!rxcb->is_continuation) { 1658d5c65159SKalle Valo dev_kfree_skb_any(skb); 1659d5c65159SKalle Valo break; 1660d5c65159SKalle Valo } 1661d5c65159SKalle Valo dev_kfree_skb_any(skb); 1662d5c65159SKalle Valo } 1663d5c65159SKalle Valo return -ENOMEM; 1664d5c65159SKalle Valo } 1665d5c65159SKalle Valo 1666d2f510faSSriram R rem_len = msdu_len - buf_first_len; 1667d5c65159SKalle Valo while ((skb = __skb_dequeue(msdu_list)) != NULL && rem_len > 0) { 1668d5c65159SKalle Valo rxcb = ATH11K_SKB_RXCB(skb); 1669d5c65159SKalle Valo if (rxcb->is_continuation) 1670d5c65159SKalle Valo buf_len = DP_RX_BUFFER_SIZE - HAL_RX_DESC_SIZE; 1671d5c65159SKalle Valo else 1672d5c65159SKalle Valo buf_len = rem_len; 1673d5c65159SKalle Valo 1674d5c65159SKalle Valo if (buf_len > (DP_RX_BUFFER_SIZE - HAL_RX_DESC_SIZE)) { 1675d5c65159SKalle Valo WARN_ON_ONCE(1); 1676d5c65159SKalle Valo dev_kfree_skb_any(skb); 1677d5c65159SKalle Valo return -EINVAL; 1678d5c65159SKalle Valo } 1679d5c65159SKalle Valo 1680d5c65159SKalle Valo skb_put(skb, buf_len + HAL_RX_DESC_SIZE); 1681d5c65159SKalle Valo skb_pull(skb, HAL_RX_DESC_SIZE); 1682d5c65159SKalle Valo skb_copy_from_linear_data(skb, skb_put(first, buf_len), 1683d5c65159SKalle Valo buf_len); 1684d5c65159SKalle Valo dev_kfree_skb_any(skb); 1685d5c65159SKalle Valo 1686d5c65159SKalle Valo rem_len -= buf_len; 1687d5c65159SKalle Valo if (!rxcb->is_continuation) 1688d5c65159SKalle Valo break; 1689d5c65159SKalle Valo } 1690d5c65159SKalle Valo 1691d5c65159SKalle Valo return 0; 1692d5c65159SKalle Valo } 1693d5c65159SKalle Valo 1694d5c65159SKalle Valo static struct sk_buff *ath11k_dp_rx_get_msdu_last_buf(struct sk_buff_head *msdu_list, 1695d5c65159SKalle Valo struct sk_buff *first) 1696d5c65159SKalle Valo { 1697d5c65159SKalle Valo struct sk_buff *skb; 1698d5c65159SKalle Valo struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(first); 1699d5c65159SKalle Valo 1700d5c65159SKalle Valo if (!rxcb->is_continuation) 1701d5c65159SKalle Valo return first; 1702d5c65159SKalle Valo 1703d5c65159SKalle Valo skb_queue_walk(msdu_list, skb) { 1704d5c65159SKalle Valo rxcb = ATH11K_SKB_RXCB(skb); 1705d5c65159SKalle Valo if (!rxcb->is_continuation) 1706d5c65159SKalle Valo return skb; 1707d5c65159SKalle Valo } 1708d5c65159SKalle Valo 1709d5c65159SKalle Valo return NULL; 1710d5c65159SKalle Valo } 1711d5c65159SKalle Valo 1712d5c65159SKalle Valo static void ath11k_dp_rx_h_csum_offload(struct sk_buff *msdu) 1713d5c65159SKalle Valo { 1714d5c65159SKalle Valo struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); 1715d5c65159SKalle Valo bool ip_csum_fail, l4_csum_fail; 1716d5c65159SKalle Valo 1717d5c65159SKalle Valo ip_csum_fail = ath11k_dp_rx_h_attn_ip_cksum_fail(rxcb->rx_desc); 1718d5c65159SKalle Valo l4_csum_fail = ath11k_dp_rx_h_attn_l4_cksum_fail(rxcb->rx_desc); 1719d5c65159SKalle Valo 1720d5c65159SKalle Valo msdu->ip_summed = (ip_csum_fail || l4_csum_fail) ? 1721d5c65159SKalle Valo CHECKSUM_NONE : CHECKSUM_UNNECESSARY; 1722d5c65159SKalle Valo } 1723d5c65159SKalle Valo 1724d5c65159SKalle Valo static int ath11k_dp_rx_crypto_mic_len(struct ath11k *ar, 1725d5c65159SKalle Valo enum hal_encrypt_type enctype) 1726d5c65159SKalle Valo { 1727d5c65159SKalle Valo switch (enctype) { 1728d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_OPEN: 1729d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_TKIP_NO_MIC: 1730d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_TKIP_MIC: 1731d5c65159SKalle Valo return 0; 1732d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_CCMP_128: 1733d5c65159SKalle Valo return IEEE80211_CCMP_MIC_LEN; 1734d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_CCMP_256: 1735d5c65159SKalle Valo return IEEE80211_CCMP_256_MIC_LEN; 1736d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_GCMP_128: 1737d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_AES_GCMP_256: 1738d5c65159SKalle Valo return IEEE80211_GCMP_MIC_LEN; 1739d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_WEP_40: 1740d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_WEP_104: 1741d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_WEP_128: 1742d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_WAPI_GCM_SM4: 1743d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_WAPI: 1744d5c65159SKalle Valo break; 1745d5c65159SKalle Valo } 1746d5c65159SKalle Valo 1747d5c65159SKalle Valo ath11k_warn(ar->ab, "unsupported encryption type %d for mic len\n", enctype); 1748d5c65159SKalle Valo return 0; 1749d5c65159SKalle Valo } 1750d5c65159SKalle Valo 1751d5c65159SKalle Valo static int ath11k_dp_rx_crypto_param_len(struct ath11k *ar, 1752d5c65159SKalle Valo enum hal_encrypt_type enctype) 1753d5c65159SKalle Valo { 1754d5c65159SKalle Valo switch (enctype) { 1755d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_OPEN: 1756d5c65159SKalle Valo return 0; 1757d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_TKIP_NO_MIC: 1758d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_TKIP_MIC: 1759d5c65159SKalle Valo return IEEE80211_TKIP_IV_LEN; 1760d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_CCMP_128: 1761d5c65159SKalle Valo return IEEE80211_CCMP_HDR_LEN; 1762d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_CCMP_256: 1763d5c65159SKalle Valo return IEEE80211_CCMP_256_HDR_LEN; 1764d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_GCMP_128: 1765d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_AES_GCMP_256: 1766d5c65159SKalle Valo return IEEE80211_GCMP_HDR_LEN; 1767d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_WEP_40: 1768d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_WEP_104: 1769d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_WEP_128: 1770d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_WAPI_GCM_SM4: 1771d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_WAPI: 1772d5c65159SKalle Valo break; 1773d5c65159SKalle Valo } 1774d5c65159SKalle Valo 1775d5c65159SKalle Valo ath11k_warn(ar->ab, "unsupported encryption type %d\n", enctype); 1776d5c65159SKalle Valo return 0; 1777d5c65159SKalle Valo } 1778d5c65159SKalle Valo 1779d5c65159SKalle Valo static int ath11k_dp_rx_crypto_icv_len(struct ath11k *ar, 1780d5c65159SKalle Valo enum hal_encrypt_type enctype) 1781d5c65159SKalle Valo { 1782d5c65159SKalle Valo switch (enctype) { 1783d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_OPEN: 1784d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_CCMP_128: 1785d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_CCMP_256: 1786d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_GCMP_128: 1787d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_AES_GCMP_256: 1788d5c65159SKalle Valo return 0; 1789d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_TKIP_NO_MIC: 1790d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_TKIP_MIC: 1791d5c65159SKalle Valo return IEEE80211_TKIP_ICV_LEN; 1792d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_WEP_40: 1793d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_WEP_104: 1794d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_WEP_128: 1795d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_WAPI_GCM_SM4: 1796d5c65159SKalle Valo case HAL_ENCRYPT_TYPE_WAPI: 1797d5c65159SKalle Valo break; 1798d5c65159SKalle Valo } 1799d5c65159SKalle Valo 1800d5c65159SKalle Valo ath11k_warn(ar->ab, "unsupported encryption type %d\n", enctype); 1801d5c65159SKalle Valo return 0; 1802d5c65159SKalle Valo } 1803d5c65159SKalle Valo 1804d5c65159SKalle Valo static void ath11k_dp_rx_h_undecap_nwifi(struct ath11k *ar, 1805d5c65159SKalle Valo struct sk_buff *msdu, 1806d5c65159SKalle Valo u8 *first_hdr, 1807d5c65159SKalle Valo enum hal_encrypt_type enctype, 1808d5c65159SKalle Valo struct ieee80211_rx_status *status) 1809d5c65159SKalle Valo { 1810acc79d98SSriram R struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); 1811acc79d98SSriram R u8 decap_hdr[DP_MAX_NWIFI_HDR_LEN]; 1812d5c65159SKalle Valo struct ieee80211_hdr *hdr; 1813d5c65159SKalle Valo size_t hdr_len; 1814d5c65159SKalle Valo u8 da[ETH_ALEN]; 1815d5c65159SKalle Valo u8 sa[ETH_ALEN]; 1816acc79d98SSriram R u16 qos_ctl = 0; 1817acc79d98SSriram R u8 *qos; 1818d5c65159SKalle Valo 1819acc79d98SSriram R /* copy SA & DA and pull decapped header */ 1820d5c65159SKalle Valo hdr = (struct ieee80211_hdr *)msdu->data; 1821acc79d98SSriram R hdr_len = ieee80211_hdrlen(hdr->frame_control); 1822d5c65159SKalle Valo ether_addr_copy(da, ieee80211_get_DA(hdr)); 1823d5c65159SKalle Valo ether_addr_copy(sa, ieee80211_get_SA(hdr)); 1824d5c65159SKalle Valo skb_pull(msdu, ieee80211_hdrlen(hdr->frame_control)); 1825d5c65159SKalle Valo 1826acc79d98SSriram R if (rxcb->is_first_msdu) { 1827acc79d98SSriram R /* original 802.11 header is valid for the first msdu 1828acc79d98SSriram R * hence we can reuse the same header 1829acc79d98SSriram R */ 1830d5c65159SKalle Valo hdr = (struct ieee80211_hdr *)first_hdr; 1831d5c65159SKalle Valo hdr_len = ieee80211_hdrlen(hdr->frame_control); 1832d5c65159SKalle Valo 1833acc79d98SSriram R /* Each A-MSDU subframe will be reported as a separate MSDU, 1834acc79d98SSriram R * so strip the A-MSDU bit from QoS Ctl. 1835acc79d98SSriram R */ 1836acc79d98SSriram R if (ieee80211_is_data_qos(hdr->frame_control)) { 1837acc79d98SSriram R qos = ieee80211_get_qos_ctl(hdr); 1838acc79d98SSriram R qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; 1839acc79d98SSriram R } 1840acc79d98SSriram R } else { 1841acc79d98SSriram R /* Rebuild qos header if this is a middle/last msdu */ 1842acc79d98SSriram R hdr->frame_control |= __cpu_to_le16(IEEE80211_STYPE_QOS_DATA); 1843acc79d98SSriram R 1844acc79d98SSriram R /* Reset the order bit as the HT_Control header is stripped */ 1845acc79d98SSriram R hdr->frame_control &= ~(__cpu_to_le16(IEEE80211_FCTL_ORDER)); 1846acc79d98SSriram R 1847acc79d98SSriram R qos_ctl = rxcb->tid; 1848acc79d98SSriram R 1849acc79d98SSriram R if (ath11k_dp_rx_h_msdu_start_mesh_ctl_present(rxcb->rx_desc)) 1850acc79d98SSriram R qos_ctl |= IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT; 1851acc79d98SSriram R 1852acc79d98SSriram R /* TODO Add other QoS ctl fields when required */ 1853acc79d98SSriram R 1854acc79d98SSriram R /* copy decap header before overwriting for reuse below */ 1855acc79d98SSriram R memcpy(decap_hdr, (uint8_t *)hdr, hdr_len); 1856acc79d98SSriram R } 1857acc79d98SSriram R 1858d5c65159SKalle Valo if (!(status->flag & RX_FLAG_IV_STRIPPED)) { 1859d5c65159SKalle Valo memcpy(skb_push(msdu, 1860d5c65159SKalle Valo ath11k_dp_rx_crypto_param_len(ar, enctype)), 1861d5c65159SKalle Valo (void *)hdr + hdr_len, 1862d5c65159SKalle Valo ath11k_dp_rx_crypto_param_len(ar, enctype)); 1863d5c65159SKalle Valo } 1864d5c65159SKalle Valo 1865acc79d98SSriram R if (!rxcb->is_first_msdu) { 1866acc79d98SSriram R memcpy(skb_push(msdu, 1867acc79d98SSriram R IEEE80211_QOS_CTL_LEN), &qos_ctl, 1868acc79d98SSriram R IEEE80211_QOS_CTL_LEN); 1869acc79d98SSriram R memcpy(skb_push(msdu, hdr_len), decap_hdr, hdr_len); 1870acc79d98SSriram R return; 1871acc79d98SSriram R } 1872acc79d98SSriram R 1873d5c65159SKalle Valo memcpy(skb_push(msdu, hdr_len), hdr, hdr_len); 1874d5c65159SKalle Valo 1875d5c65159SKalle Valo /* original 802.11 header has a different DA and in 1876d5c65159SKalle Valo * case of 4addr it may also have different SA 1877d5c65159SKalle Valo */ 1878d5c65159SKalle Valo hdr = (struct ieee80211_hdr *)msdu->data; 1879d5c65159SKalle Valo ether_addr_copy(ieee80211_get_DA(hdr), da); 1880d5c65159SKalle Valo ether_addr_copy(ieee80211_get_SA(hdr), sa); 1881d5c65159SKalle Valo } 1882d5c65159SKalle Valo 1883d5c65159SKalle Valo static void ath11k_dp_rx_h_undecap_raw(struct ath11k *ar, struct sk_buff *msdu, 1884d5c65159SKalle Valo enum hal_encrypt_type enctype, 1885d5c65159SKalle Valo struct ieee80211_rx_status *status, 1886d5c65159SKalle Valo bool decrypted) 1887d5c65159SKalle Valo { 1888d5c65159SKalle Valo struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); 1889d5c65159SKalle Valo struct ieee80211_hdr *hdr; 1890d5c65159SKalle Valo size_t hdr_len; 1891d5c65159SKalle Valo size_t crypto_len; 1892d5c65159SKalle Valo 1893d5c65159SKalle Valo if (!rxcb->is_first_msdu || 1894d5c65159SKalle Valo !(rxcb->is_first_msdu && rxcb->is_last_msdu)) { 1895d5c65159SKalle Valo WARN_ON_ONCE(1); 1896d5c65159SKalle Valo return; 1897d5c65159SKalle Valo } 1898d5c65159SKalle Valo 1899d5c65159SKalle Valo skb_trim(msdu, msdu->len - FCS_LEN); 1900d5c65159SKalle Valo 1901d5c65159SKalle Valo if (!decrypted) 1902d5c65159SKalle Valo return; 1903d5c65159SKalle Valo 1904d5c65159SKalle Valo hdr = (void *)msdu->data; 1905d5c65159SKalle Valo 1906d5c65159SKalle Valo /* Tail */ 1907d5c65159SKalle Valo if (status->flag & RX_FLAG_IV_STRIPPED) { 1908d5c65159SKalle Valo skb_trim(msdu, msdu->len - 1909d5c65159SKalle Valo ath11k_dp_rx_crypto_mic_len(ar, enctype)); 1910d5c65159SKalle Valo 1911d5c65159SKalle Valo skb_trim(msdu, msdu->len - 1912d5c65159SKalle Valo ath11k_dp_rx_crypto_icv_len(ar, enctype)); 1913d5c65159SKalle Valo } else { 1914d5c65159SKalle Valo /* MIC */ 1915d5c65159SKalle Valo if (status->flag & RX_FLAG_MIC_STRIPPED) 1916d5c65159SKalle Valo skb_trim(msdu, msdu->len - 1917d5c65159SKalle Valo ath11k_dp_rx_crypto_mic_len(ar, enctype)); 1918d5c65159SKalle Valo 1919d5c65159SKalle Valo /* ICV */ 1920d5c65159SKalle Valo if (status->flag & RX_FLAG_ICV_STRIPPED) 1921d5c65159SKalle Valo skb_trim(msdu, msdu->len - 1922d5c65159SKalle Valo ath11k_dp_rx_crypto_icv_len(ar, enctype)); 1923d5c65159SKalle Valo } 1924d5c65159SKalle Valo 1925d5c65159SKalle Valo /* MMIC */ 1926d5c65159SKalle Valo if ((status->flag & RX_FLAG_MMIC_STRIPPED) && 1927d5c65159SKalle Valo !ieee80211_has_morefrags(hdr->frame_control) && 1928d5c65159SKalle Valo enctype == HAL_ENCRYPT_TYPE_TKIP_MIC) 1929d5c65159SKalle Valo skb_trim(msdu, msdu->len - IEEE80211_CCMP_MIC_LEN); 1930d5c65159SKalle Valo 1931d5c65159SKalle Valo /* Head */ 1932d5c65159SKalle Valo if (status->flag & RX_FLAG_IV_STRIPPED) { 1933d5c65159SKalle Valo hdr_len = ieee80211_hdrlen(hdr->frame_control); 1934d5c65159SKalle Valo crypto_len = ath11k_dp_rx_crypto_param_len(ar, enctype); 1935d5c65159SKalle Valo 1936d5c65159SKalle Valo memmove((void *)msdu->data + crypto_len, 1937d5c65159SKalle Valo (void *)msdu->data, hdr_len); 1938d5c65159SKalle Valo skb_pull(msdu, crypto_len); 1939d5c65159SKalle Valo } 1940d5c65159SKalle Valo } 1941d5c65159SKalle Valo 1942d5c65159SKalle Valo static void *ath11k_dp_rx_h_find_rfc1042(struct ath11k *ar, 1943d5c65159SKalle Valo struct sk_buff *msdu, 1944d5c65159SKalle Valo enum hal_encrypt_type enctype) 1945d5c65159SKalle Valo { 1946d5c65159SKalle Valo struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); 1947d5c65159SKalle Valo struct ieee80211_hdr *hdr; 1948d5c65159SKalle Valo size_t hdr_len, crypto_len; 1949d5c65159SKalle Valo void *rfc1042; 1950d5c65159SKalle Valo bool is_amsdu; 1951d5c65159SKalle Valo 1952d5c65159SKalle Valo is_amsdu = !(rxcb->is_first_msdu && rxcb->is_last_msdu); 1953d5c65159SKalle Valo hdr = (struct ieee80211_hdr *)ath11k_dp_rx_h_80211_hdr(rxcb->rx_desc); 1954d5c65159SKalle Valo rfc1042 = hdr; 1955d5c65159SKalle Valo 1956d5c65159SKalle Valo if (rxcb->is_first_msdu) { 1957d5c65159SKalle Valo hdr_len = ieee80211_hdrlen(hdr->frame_control); 1958d5c65159SKalle Valo crypto_len = ath11k_dp_rx_crypto_param_len(ar, enctype); 1959d5c65159SKalle Valo 1960d5c65159SKalle Valo rfc1042 += hdr_len + crypto_len; 1961d5c65159SKalle Valo } 1962d5c65159SKalle Valo 1963d5c65159SKalle Valo if (is_amsdu) 1964d5c65159SKalle Valo rfc1042 += sizeof(struct ath11k_dp_amsdu_subframe_hdr); 1965d5c65159SKalle Valo 1966d5c65159SKalle Valo return rfc1042; 1967d5c65159SKalle Valo } 1968d5c65159SKalle Valo 1969d5c65159SKalle Valo static void ath11k_dp_rx_h_undecap_eth(struct ath11k *ar, 1970d5c65159SKalle Valo struct sk_buff *msdu, 1971d5c65159SKalle Valo u8 *first_hdr, 1972d5c65159SKalle Valo enum hal_encrypt_type enctype, 1973d5c65159SKalle Valo struct ieee80211_rx_status *status) 1974d5c65159SKalle Valo { 1975d5c65159SKalle Valo struct ieee80211_hdr *hdr; 1976d5c65159SKalle Valo struct ethhdr *eth; 1977d5c65159SKalle Valo size_t hdr_len; 1978d5c65159SKalle Valo u8 da[ETH_ALEN]; 1979d5c65159SKalle Valo u8 sa[ETH_ALEN]; 1980d5c65159SKalle Valo void *rfc1042; 1981d5c65159SKalle Valo 1982d5c65159SKalle Valo rfc1042 = ath11k_dp_rx_h_find_rfc1042(ar, msdu, enctype); 1983d5c65159SKalle Valo if (WARN_ON_ONCE(!rfc1042)) 1984d5c65159SKalle Valo return; 1985d5c65159SKalle Valo 1986d5c65159SKalle Valo /* pull decapped header and copy SA & DA */ 1987d5c65159SKalle Valo eth = (struct ethhdr *)msdu->data; 1988d5c65159SKalle Valo ether_addr_copy(da, eth->h_dest); 1989d5c65159SKalle Valo ether_addr_copy(sa, eth->h_source); 1990d5c65159SKalle Valo skb_pull(msdu, sizeof(struct ethhdr)); 1991d5c65159SKalle Valo 1992d5c65159SKalle Valo /* push rfc1042/llc/snap */ 1993d5c65159SKalle Valo memcpy(skb_push(msdu, sizeof(struct ath11k_dp_rfc1042_hdr)), rfc1042, 1994d5c65159SKalle Valo sizeof(struct ath11k_dp_rfc1042_hdr)); 1995d5c65159SKalle Valo 1996d5c65159SKalle Valo /* push original 802.11 header */ 1997d5c65159SKalle Valo hdr = (struct ieee80211_hdr *)first_hdr; 1998d5c65159SKalle Valo hdr_len = ieee80211_hdrlen(hdr->frame_control); 1999d5c65159SKalle Valo 2000d5c65159SKalle Valo if (!(status->flag & RX_FLAG_IV_STRIPPED)) { 2001d5c65159SKalle Valo memcpy(skb_push(msdu, 2002d5c65159SKalle Valo ath11k_dp_rx_crypto_param_len(ar, enctype)), 2003d5c65159SKalle Valo (void *)hdr + hdr_len, 2004d5c65159SKalle Valo ath11k_dp_rx_crypto_param_len(ar, enctype)); 2005d5c65159SKalle Valo } 2006d5c65159SKalle Valo 2007d5c65159SKalle Valo memcpy(skb_push(msdu, hdr_len), hdr, hdr_len); 2008d5c65159SKalle Valo 2009d5c65159SKalle Valo /* original 802.11 header has a different DA and in 2010d5c65159SKalle Valo * case of 4addr it may also have different SA 2011d5c65159SKalle Valo */ 2012d5c65159SKalle Valo hdr = (struct ieee80211_hdr *)msdu->data; 2013d5c65159SKalle Valo ether_addr_copy(ieee80211_get_DA(hdr), da); 2014d5c65159SKalle Valo ether_addr_copy(ieee80211_get_SA(hdr), sa); 2015d5c65159SKalle Valo } 2016d5c65159SKalle Valo 2017d5c65159SKalle Valo static void ath11k_dp_rx_h_undecap(struct ath11k *ar, struct sk_buff *msdu, 2018d5c65159SKalle Valo struct hal_rx_desc *rx_desc, 2019d5c65159SKalle Valo enum hal_encrypt_type enctype, 2020d5c65159SKalle Valo struct ieee80211_rx_status *status, 2021d5c65159SKalle Valo bool decrypted) 2022d5c65159SKalle Valo { 2023d5c65159SKalle Valo u8 *first_hdr; 2024d5c65159SKalle Valo u8 decap; 2025d5c65159SKalle Valo 2026d5c65159SKalle Valo first_hdr = ath11k_dp_rx_h_80211_hdr(rx_desc); 2027243874c6SManikanta Pubbisetty decap = ath11k_dp_rx_h_msdu_start_decap_type(rx_desc); 2028d5c65159SKalle Valo 2029d5c65159SKalle Valo switch (decap) { 2030d5c65159SKalle Valo case DP_RX_DECAP_TYPE_NATIVE_WIFI: 2031d5c65159SKalle Valo ath11k_dp_rx_h_undecap_nwifi(ar, msdu, first_hdr, 2032d5c65159SKalle Valo enctype, status); 2033d5c65159SKalle Valo break; 2034d5c65159SKalle Valo case DP_RX_DECAP_TYPE_RAW: 2035d5c65159SKalle Valo ath11k_dp_rx_h_undecap_raw(ar, msdu, enctype, status, 2036d5c65159SKalle Valo decrypted); 2037d5c65159SKalle Valo break; 2038d5c65159SKalle Valo case DP_RX_DECAP_TYPE_ETHERNET2_DIX: 2039acc79d98SSriram R /* TODO undecap support for middle/last msdu's of amsdu */ 2040d5c65159SKalle Valo ath11k_dp_rx_h_undecap_eth(ar, msdu, first_hdr, 2041d5c65159SKalle Valo enctype, status); 2042d5c65159SKalle Valo break; 2043d5c65159SKalle Valo case DP_RX_DECAP_TYPE_8023: 2044d5c65159SKalle Valo /* TODO: Handle undecap for these formats */ 2045d5c65159SKalle Valo break; 2046d5c65159SKalle Valo } 2047d5c65159SKalle Valo } 2048d5c65159SKalle Valo 2049d5c65159SKalle Valo static void ath11k_dp_rx_h_mpdu(struct ath11k *ar, 2050acc79d98SSriram R struct sk_buff *msdu, 2051d5c65159SKalle Valo struct hal_rx_desc *rx_desc, 2052d5c65159SKalle Valo struct ieee80211_rx_status *rx_status) 2053d5c65159SKalle Valo { 2054acc79d98SSriram R bool fill_crypto_hdr, mcast; 2055d5c65159SKalle Valo enum hal_encrypt_type enctype; 2056acc79d98SSriram R bool is_decrypted = false; 2057acc79d98SSriram R struct ieee80211_hdr *hdr; 2058acc79d98SSriram R struct ath11k_peer *peer; 2059d5c65159SKalle Valo u32 err_bitmap; 2060d5c65159SKalle Valo 2061acc79d98SSriram R hdr = (struct ieee80211_hdr *)msdu->data; 2062d5c65159SKalle Valo 20631441b2f2SManikanta Pubbisetty /* PN for multicast packets will be checked in mac80211 */ 2064acc79d98SSriram R 2065acc79d98SSriram R mcast = is_multicast_ether_addr(hdr->addr1); 2066acc79d98SSriram R fill_crypto_hdr = mcast; 20671441b2f2SManikanta Pubbisetty 2068d5c65159SKalle Valo is_decrypted = ath11k_dp_rx_h_attn_is_decrypted(rx_desc); 2069d5c65159SKalle Valo 2070acc79d98SSriram R spin_lock_bh(&ar->ab->base_lock); 2071acc79d98SSriram R peer = ath11k_peer_find_by_addr(ar->ab, hdr->addr2); 2072acc79d98SSriram R if (peer) { 2073acc79d98SSriram R if (mcast) 2074acc79d98SSriram R enctype = peer->sec_type_grp; 2075acc79d98SSriram R else 2076acc79d98SSriram R enctype = peer->sec_type; 2077acc79d98SSriram R } else { 2078acc79d98SSriram R enctype = HAL_ENCRYPT_TYPE_OPEN; 2079acc79d98SSriram R } 2080acc79d98SSriram R spin_unlock_bh(&ar->ab->base_lock); 2081d5c65159SKalle Valo 2082acc79d98SSriram R err_bitmap = ath11k_dp_rx_h_attn_mpdu_err(rx_desc); 2083d5c65159SKalle Valo 2084acc79d98SSriram R /* Clear per-MPDU flags while leaving per-PPDU flags intact */ 2085d5c65159SKalle Valo rx_status->flag &= ~(RX_FLAG_FAILED_FCS_CRC | 2086d5c65159SKalle Valo RX_FLAG_MMIC_ERROR | 2087d5c65159SKalle Valo RX_FLAG_DECRYPTED | 2088d5c65159SKalle Valo RX_FLAG_IV_STRIPPED | 2089d5c65159SKalle Valo RX_FLAG_MMIC_STRIPPED); 2090d5c65159SKalle Valo 2091d5c65159SKalle Valo if (err_bitmap & DP_RX_MPDU_ERR_FCS) 2092d5c65159SKalle Valo rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; 2093d5c65159SKalle Valo if (err_bitmap & DP_RX_MPDU_ERR_TKIP_MIC) 2094d5c65159SKalle Valo rx_status->flag |= RX_FLAG_MMIC_ERROR; 2095d5c65159SKalle Valo 20961441b2f2SManikanta Pubbisetty if (is_decrypted) { 20971441b2f2SManikanta Pubbisetty rx_status->flag |= RX_FLAG_DECRYPTED | RX_FLAG_MMIC_STRIPPED; 20981441b2f2SManikanta Pubbisetty 20991441b2f2SManikanta Pubbisetty if (fill_crypto_hdr) 21001441b2f2SManikanta Pubbisetty rx_status->flag |= RX_FLAG_MIC_STRIPPED | 21011441b2f2SManikanta Pubbisetty RX_FLAG_ICV_STRIPPED; 21021441b2f2SManikanta Pubbisetty else 21031441b2f2SManikanta Pubbisetty rx_status->flag |= RX_FLAG_IV_STRIPPED | 21041441b2f2SManikanta Pubbisetty RX_FLAG_PN_VALIDATED; 21051441b2f2SManikanta Pubbisetty } 2106d5c65159SKalle Valo 2107d5c65159SKalle Valo ath11k_dp_rx_h_csum_offload(msdu); 2108d5c65159SKalle Valo ath11k_dp_rx_h_undecap(ar, msdu, rx_desc, 2109d5c65159SKalle Valo enctype, rx_status, is_decrypted); 21101441b2f2SManikanta Pubbisetty 21111441b2f2SManikanta Pubbisetty if (!is_decrypted || fill_crypto_hdr) 2112acc79d98SSriram R return; 21131441b2f2SManikanta Pubbisetty 21141441b2f2SManikanta Pubbisetty hdr = (void *)msdu->data; 21151441b2f2SManikanta Pubbisetty hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED); 2116d5c65159SKalle Valo } 2117d5c65159SKalle Valo 2118d5c65159SKalle Valo static void ath11k_dp_rx_h_rate(struct ath11k *ar, struct hal_rx_desc *rx_desc, 2119d5c65159SKalle Valo struct ieee80211_rx_status *rx_status) 2120d5c65159SKalle Valo { 2121d5c65159SKalle Valo struct ieee80211_supported_band *sband; 2122d5c65159SKalle Valo enum rx_msdu_start_pkt_type pkt_type; 2123d5c65159SKalle Valo u8 bw; 2124d5c65159SKalle Valo u8 rate_mcs, nss; 2125d5c65159SKalle Valo u8 sgi; 2126d5c65159SKalle Valo bool is_cck; 2127d5c65159SKalle Valo 2128d5c65159SKalle Valo pkt_type = ath11k_dp_rx_h_msdu_start_pkt_type(rx_desc); 2129d5c65159SKalle Valo bw = ath11k_dp_rx_h_msdu_start_rx_bw(rx_desc); 2130d5c65159SKalle Valo rate_mcs = ath11k_dp_rx_h_msdu_start_rate_mcs(rx_desc); 2131d5c65159SKalle Valo nss = ath11k_dp_rx_h_msdu_start_nss(rx_desc); 2132d5c65159SKalle Valo sgi = ath11k_dp_rx_h_msdu_start_sgi(rx_desc); 2133d5c65159SKalle Valo 2134d5c65159SKalle Valo switch (pkt_type) { 2135d5c65159SKalle Valo case RX_MSDU_START_PKT_TYPE_11A: 2136d5c65159SKalle Valo case RX_MSDU_START_PKT_TYPE_11B: 2137d5c65159SKalle Valo is_cck = (pkt_type == RX_MSDU_START_PKT_TYPE_11B); 2138d5c65159SKalle Valo sband = &ar->mac.sbands[rx_status->band]; 2139d5c65159SKalle Valo rx_status->rate_idx = ath11k_mac_hw_rate_to_idx(sband, rate_mcs, 2140d5c65159SKalle Valo is_cck); 2141d5c65159SKalle Valo break; 2142d5c65159SKalle Valo case RX_MSDU_START_PKT_TYPE_11N: 2143d5c65159SKalle Valo rx_status->encoding = RX_ENC_HT; 2144d5c65159SKalle Valo if (rate_mcs > ATH11K_HT_MCS_MAX) { 2145d5c65159SKalle Valo ath11k_warn(ar->ab, 2146d5c65159SKalle Valo "Received with invalid mcs in HT mode %d\n", 2147d5c65159SKalle Valo rate_mcs); 2148d5c65159SKalle Valo break; 2149d5c65159SKalle Valo } 2150d5c65159SKalle Valo rx_status->rate_idx = rate_mcs + (8 * (nss - 1)); 2151d5c65159SKalle Valo if (sgi) 2152d5c65159SKalle Valo rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; 215339e81c6aSTamizh chelvam rx_status->bw = ath11k_mac_bw_to_mac80211_bw(bw); 2154d5c65159SKalle Valo break; 2155d5c65159SKalle Valo case RX_MSDU_START_PKT_TYPE_11AC: 2156d5c65159SKalle Valo rx_status->encoding = RX_ENC_VHT; 2157d5c65159SKalle Valo rx_status->rate_idx = rate_mcs; 2158d5c65159SKalle Valo if (rate_mcs > ATH11K_VHT_MCS_MAX) { 2159d5c65159SKalle Valo ath11k_warn(ar->ab, 2160d5c65159SKalle Valo "Received with invalid mcs in VHT mode %d\n", 2161d5c65159SKalle Valo rate_mcs); 2162d5c65159SKalle Valo break; 2163d5c65159SKalle Valo } 2164d5c65159SKalle Valo rx_status->nss = nss; 2165d5c65159SKalle Valo if (sgi) 2166d5c65159SKalle Valo rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; 216739e81c6aSTamizh chelvam rx_status->bw = ath11k_mac_bw_to_mac80211_bw(bw); 2168d5c65159SKalle Valo break; 2169d5c65159SKalle Valo case RX_MSDU_START_PKT_TYPE_11AX: 2170d5c65159SKalle Valo rx_status->rate_idx = rate_mcs; 2171d5c65159SKalle Valo if (rate_mcs > ATH11K_HE_MCS_MAX) { 2172d5c65159SKalle Valo ath11k_warn(ar->ab, 2173d5c65159SKalle Valo "Received with invalid mcs in HE mode %d\n", 2174d5c65159SKalle Valo rate_mcs); 2175d5c65159SKalle Valo break; 2176d5c65159SKalle Valo } 2177d5c65159SKalle Valo rx_status->encoding = RX_ENC_HE; 2178d5c65159SKalle Valo rx_status->nss = nss; 21796a0c3702SJohn Crispin rx_status->he_gi = ath11k_he_gi_to_nl80211_he_gi(sgi); 218039e81c6aSTamizh chelvam rx_status->bw = ath11k_mac_bw_to_mac80211_bw(bw); 2181d5c65159SKalle Valo break; 2182d5c65159SKalle Valo } 2183d5c65159SKalle Valo } 2184d5c65159SKalle Valo 2185d5c65159SKalle Valo static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc, 2186d5c65159SKalle Valo struct ieee80211_rx_status *rx_status) 2187d5c65159SKalle Valo { 2188d5c65159SKalle Valo u8 channel_num; 21895dcf42f8SPradeep Kumar Chitrapu u32 center_freq; 2190d5c65159SKalle Valo 2191d5c65159SKalle Valo rx_status->freq = 0; 2192d5c65159SKalle Valo rx_status->rate_idx = 0; 2193d5c65159SKalle Valo rx_status->nss = 0; 2194d5c65159SKalle Valo rx_status->encoding = RX_ENC_LEGACY; 2195d5c65159SKalle Valo rx_status->bw = RATE_INFO_BW_20; 2196d5c65159SKalle Valo 2197d5c65159SKalle Valo rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL; 2198d5c65159SKalle Valo 2199d5c65159SKalle Valo channel_num = ath11k_dp_rx_h_msdu_start_freq(rx_desc); 22005dcf42f8SPradeep Kumar Chitrapu center_freq = ath11k_dp_rx_h_msdu_start_freq(rx_desc) >> 16; 2201d5c65159SKalle Valo 22025dcf42f8SPradeep Kumar Chitrapu if (center_freq >= 5935 && center_freq <= 7105) { 22035dcf42f8SPradeep Kumar Chitrapu rx_status->band = NL80211_BAND_6GHZ; 22045dcf42f8SPradeep Kumar Chitrapu } else if (channel_num >= 1 && channel_num <= 14) { 2205d5c65159SKalle Valo rx_status->band = NL80211_BAND_2GHZ; 2206d5c65159SKalle Valo } else if (channel_num >= 36 && channel_num <= 173) { 2207d5c65159SKalle Valo rx_status->band = NL80211_BAND_5GHZ; 2208d5c65159SKalle Valo } else { 2209de06b2f7SVenkateswara Naralasetty spin_lock_bh(&ar->data_lock); 2210de06b2f7SVenkateswara Naralasetty rx_status->band = ar->rx_channel->band; 2211de06b2f7SVenkateswara Naralasetty channel_num = 2212de06b2f7SVenkateswara Naralasetty ieee80211_frequency_to_channel(ar->rx_channel->center_freq); 2213de06b2f7SVenkateswara Naralasetty spin_unlock_bh(&ar->data_lock); 2214de06b2f7SVenkateswara Naralasetty ath11k_dbg_dump(ar->ab, ATH11K_DBG_DATA, NULL, "rx_desc: ", 2215de06b2f7SVenkateswara Naralasetty rx_desc, sizeof(struct hal_rx_desc)); 2216d5c65159SKalle Valo } 2217d5c65159SKalle Valo 2218d5c65159SKalle Valo rx_status->freq = ieee80211_channel_to_frequency(channel_num, 2219d5c65159SKalle Valo rx_status->band); 2220d5c65159SKalle Valo 2221d5c65159SKalle Valo ath11k_dp_rx_h_rate(ar, rx_desc, rx_status); 2222d5c65159SKalle Valo } 2223d5c65159SKalle Valo 2224d5c65159SKalle Valo static char *ath11k_print_get_tid(struct ieee80211_hdr *hdr, char *out, 2225d5c65159SKalle Valo size_t size) 2226d5c65159SKalle Valo { 2227d5c65159SKalle Valo u8 *qc; 2228d5c65159SKalle Valo int tid; 2229d5c65159SKalle Valo 2230d5c65159SKalle Valo if (!ieee80211_is_data_qos(hdr->frame_control)) 2231d5c65159SKalle Valo return ""; 2232d5c65159SKalle Valo 2233d5c65159SKalle Valo qc = ieee80211_get_qos_ctl(hdr); 2234d5c65159SKalle Valo tid = *qc & IEEE80211_QOS_CTL_TID_MASK; 2235d5c65159SKalle Valo snprintf(out, size, "tid %d", tid); 2236d5c65159SKalle Valo 2237d5c65159SKalle Valo return out; 2238d5c65159SKalle Valo } 2239d5c65159SKalle Valo 2240d5c65159SKalle Valo static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *napi, 2241d5c65159SKalle Valo struct sk_buff *msdu) 2242d5c65159SKalle Valo { 2243e4eb7b5cSJohn Crispin static const struct ieee80211_radiotap_he known = { 224493634c61SJohn Crispin .data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN | 224593634c61SJohn Crispin IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN), 2246e4eb7b5cSJohn Crispin .data2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN), 2247e4eb7b5cSJohn Crispin }; 2248d5c65159SKalle Valo struct ieee80211_rx_status *status; 2249d5c65159SKalle Valo struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; 2250e4eb7b5cSJohn Crispin struct ieee80211_radiotap_he *he = NULL; 2251d5c65159SKalle Valo char tid[32]; 2252d5c65159SKalle Valo 2253d5c65159SKalle Valo status = IEEE80211_SKB_RXCB(msdu); 2254e4eb7b5cSJohn Crispin if (status->encoding == RX_ENC_HE) { 2255e4eb7b5cSJohn Crispin he = skb_push(msdu, sizeof(known)); 2256e4eb7b5cSJohn Crispin memcpy(he, &known, sizeof(known)); 2257e4eb7b5cSJohn Crispin status->flag |= RX_FLAG_RADIOTAP_HE; 2258e4eb7b5cSJohn Crispin } 2259d5c65159SKalle Valo 2260d5c65159SKalle Valo ath11k_dbg(ar->ab, ATH11K_DBG_DATA, 2261d5c65159SKalle Valo "rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", 2262d5c65159SKalle Valo msdu, 2263d5c65159SKalle Valo msdu->len, 2264d5c65159SKalle Valo ieee80211_get_SA(hdr), 2265d5c65159SKalle Valo ath11k_print_get_tid(hdr, tid, sizeof(tid)), 2266d5c65159SKalle Valo is_multicast_ether_addr(ieee80211_get_DA(hdr)) ? 2267d5c65159SKalle Valo "mcast" : "ucast", 2268d5c65159SKalle Valo (__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4, 2269d5c65159SKalle Valo (status->encoding == RX_ENC_LEGACY) ? "legacy" : "", 2270d5c65159SKalle Valo (status->encoding == RX_ENC_HT) ? "ht" : "", 2271d5c65159SKalle Valo (status->encoding == RX_ENC_VHT) ? "vht" : "", 2272d5c65159SKalle Valo (status->encoding == RX_ENC_HE) ? "he" : "", 2273d5c65159SKalle Valo (status->bw == RATE_INFO_BW_40) ? "40" : "", 2274d5c65159SKalle Valo (status->bw == RATE_INFO_BW_80) ? "80" : "", 2275d5c65159SKalle Valo (status->bw == RATE_INFO_BW_160) ? "160" : "", 2276d5c65159SKalle Valo status->enc_flags & RX_ENC_FLAG_SHORT_GI ? "sgi " : "", 2277d5c65159SKalle Valo status->rate_idx, 2278d5c65159SKalle Valo status->nss, 2279d5c65159SKalle Valo status->freq, 2280d5c65159SKalle Valo status->band, status->flag, 2281d5c65159SKalle Valo !!(status->flag & RX_FLAG_FAILED_FCS_CRC), 2282d5c65159SKalle Valo !!(status->flag & RX_FLAG_MMIC_ERROR), 2283d5c65159SKalle Valo !!(status->flag & RX_FLAG_AMSDU_MORE)); 2284d5c65159SKalle Valo 2285d5c65159SKalle Valo /* TODO: trace rx packet */ 2286d5c65159SKalle Valo 2287d5c65159SKalle Valo ieee80211_rx_napi(ar->hw, NULL, msdu, napi); 2288d5c65159SKalle Valo } 2289d5c65159SKalle Valo 2290acc79d98SSriram R static int ath11k_dp_rx_process_msdu(struct ath11k *ar, 2291acc79d98SSriram R struct sk_buff *msdu, 2292acc79d98SSriram R struct sk_buff_head *msdu_list) 2293d5c65159SKalle Valo { 2294acc79d98SSriram R struct hal_rx_desc *rx_desc, *lrx_desc; 2295acc79d98SSriram R struct ieee80211_rx_status rx_status = {0}; 2296d5c65159SKalle Valo struct ieee80211_rx_status *status; 2297acc79d98SSriram R struct ath11k_skb_rxcb *rxcb; 2298acc79d98SSriram R struct ieee80211_hdr *hdr; 2299acc79d98SSriram R struct sk_buff *last_buf; 2300acc79d98SSriram R u8 l3_pad_bytes; 2301d7d43782STamizh Chelvam u8 *hdr_status; 2302acc79d98SSriram R u16 msdu_len; 2303acc79d98SSriram R int ret; 2304d5c65159SKalle Valo 2305acc79d98SSriram R last_buf = ath11k_dp_rx_get_msdu_last_buf(msdu_list, msdu); 2306acc79d98SSriram R if (!last_buf) { 2307acc79d98SSriram R ath11k_warn(ar->ab, 2308acc79d98SSriram R "No valid Rx buffer to access Atten/MSDU_END/MPDU_END tlvs\n"); 2309acc79d98SSriram R ret = -EIO; 2310acc79d98SSriram R goto free_out; 2311d5c65159SKalle Valo } 2312acc79d98SSriram R 2313acc79d98SSriram R rx_desc = (struct hal_rx_desc *)msdu->data; 2314acc79d98SSriram R lrx_desc = (struct hal_rx_desc *)last_buf->data; 2315acc79d98SSriram R if (!ath11k_dp_rx_h_attn_msdu_done(lrx_desc)) { 2316acc79d98SSriram R ath11k_warn(ar->ab, "msdu_done bit in attention is not set\n"); 2317acc79d98SSriram R ret = -EIO; 2318acc79d98SSriram R goto free_out; 2319acc79d98SSriram R } 2320acc79d98SSriram R 2321acc79d98SSriram R rxcb = ATH11K_SKB_RXCB(msdu); 2322acc79d98SSriram R rxcb->rx_desc = rx_desc; 2323acc79d98SSriram R msdu_len = ath11k_dp_rx_h_msdu_start_msdu_len(rx_desc); 2324acc79d98SSriram R l3_pad_bytes = ath11k_dp_rx_h_msdu_end_l3pad(lrx_desc); 2325acc79d98SSriram R 2326acc79d98SSriram R if (rxcb->is_frag) { 2327acc79d98SSriram R skb_pull(msdu, HAL_RX_DESC_SIZE); 2328acc79d98SSriram R } else if (!rxcb->is_continuation) { 2329acc79d98SSriram R if ((msdu_len + HAL_RX_DESC_SIZE) > DP_RX_BUFFER_SIZE) { 2330d7d43782STamizh Chelvam hdr_status = ath11k_dp_rx_h_80211_hdr(rx_desc); 2331acc79d98SSriram R ret = -EINVAL; 2332acc79d98SSriram R ath11k_warn(ar->ab, "invalid msdu len %u\n", msdu_len); 2333d7d43782STamizh Chelvam ath11k_dbg_dump(ar->ab, ATH11K_DBG_DATA, NULL, "", hdr_status, 2334d7d43782STamizh Chelvam sizeof(struct ieee80211_hdr)); 2335d7d43782STamizh Chelvam ath11k_dbg_dump(ar->ab, ATH11K_DBG_DATA, NULL, "", rx_desc, 2336d7d43782STamizh Chelvam sizeof(struct hal_rx_desc)); 2337acc79d98SSriram R goto free_out; 2338acc79d98SSriram R } 2339acc79d98SSriram R skb_put(msdu, HAL_RX_DESC_SIZE + l3_pad_bytes + msdu_len); 2340acc79d98SSriram R skb_pull(msdu, HAL_RX_DESC_SIZE + l3_pad_bytes); 2341acc79d98SSriram R } else { 2342acc79d98SSriram R ret = ath11k_dp_rx_msdu_coalesce(ar, msdu_list, 2343acc79d98SSriram R msdu, last_buf, 2344acc79d98SSriram R l3_pad_bytes, msdu_len); 2345acc79d98SSriram R if (ret) { 2346acc79d98SSriram R ath11k_warn(ar->ab, 2347acc79d98SSriram R "failed to coalesce msdu rx buffer%d\n", ret); 2348acc79d98SSriram R goto free_out; 2349acc79d98SSriram R } 2350acc79d98SSriram R } 2351acc79d98SSriram R 2352acc79d98SSriram R hdr = (struct ieee80211_hdr *)msdu->data; 2353acc79d98SSriram R 2354acc79d98SSriram R /* Process only data frames */ 2355acc79d98SSriram R if (!ieee80211_is_data(hdr->frame_control)) 2356acc79d98SSriram R return -EINVAL; 2357acc79d98SSriram R 2358acc79d98SSriram R ath11k_dp_rx_h_ppdu(ar, rx_desc, &rx_status); 2359acc79d98SSriram R ath11k_dp_rx_h_mpdu(ar, msdu, rx_desc, &rx_status); 2360acc79d98SSriram R 2361acc79d98SSriram R rx_status.flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED; 2362d5c65159SKalle Valo 2363d5c65159SKalle Valo status = IEEE80211_SKB_RXCB(msdu); 2364acc79d98SSriram R *status = rx_status; 2365acc79d98SSriram R return 0; 2366acc79d98SSriram R 2367acc79d98SSriram R free_out: 2368acc79d98SSriram R return ret; 2369d5c65159SKalle Valo } 2370d5c65159SKalle Valo 2371acc79d98SSriram R static void ath11k_dp_rx_process_received_packets(struct ath11k_base *ab, 2372d5c65159SKalle Valo struct napi_struct *napi, 2373acc79d98SSriram R struct sk_buff_head *msdu_list, 2374acc79d98SSriram R int *quota, int ring_id) 2375d5c65159SKalle Valo { 2376acc79d98SSriram R struct ath11k_skb_rxcb *rxcb; 2377d5c65159SKalle Valo struct sk_buff *msdu; 2378acc79d98SSriram R struct ath11k *ar; 2379acc79d98SSriram R u8 mac_id; 2380acc79d98SSriram R int ret; 2381d5c65159SKalle Valo 2382acc79d98SSriram R if (skb_queue_empty(msdu_list)) 2383d5c65159SKalle Valo return; 2384d5c65159SKalle Valo 2385d5c65159SKalle Valo rcu_read_lock(); 2386d5c65159SKalle Valo 2387acc79d98SSriram R while (*quota && (msdu = __skb_dequeue(msdu_list))) { 2388acc79d98SSriram R rxcb = ATH11K_SKB_RXCB(msdu); 2389acc79d98SSriram R mac_id = rxcb->mac_id; 2390acc79d98SSriram R ar = ab->pdevs[mac_id].ar; 2391acc79d98SSriram R if (!rcu_dereference(ab->pdevs_active[mac_id])) { 2392acc79d98SSriram R dev_kfree_skb_any(msdu); 2393acc79d98SSriram R continue; 2394acc79d98SSriram R } 2395acc79d98SSriram R 2396acc79d98SSriram R if (test_bit(ATH11K_CAC_RUNNING, &ar->dev_flags)) { 2397acc79d98SSriram R dev_kfree_skb_any(msdu); 2398acc79d98SSriram R continue; 2399acc79d98SSriram R } 2400acc79d98SSriram R 2401acc79d98SSriram R ret = ath11k_dp_rx_process_msdu(ar, msdu, msdu_list); 2402acc79d98SSriram R if (ret) { 2403acc79d98SSriram R ath11k_dbg(ab, ATH11K_DBG_DATA, 2404acc79d98SSriram R "Unable to process msdu %d", ret); 2405d5c65159SKalle Valo dev_kfree_skb_any(msdu); 2406d5c65159SKalle Valo continue; 2407d5c65159SKalle Valo } 2408d5c65159SKalle Valo 2409d5c65159SKalle Valo ath11k_dp_rx_deliver_msdu(ar, napi, msdu); 2410d5c65159SKalle Valo (*quota)--; 2411d5c65159SKalle Valo } 2412acc79d98SSriram R 2413d5c65159SKalle Valo rcu_read_unlock(); 2414d5c65159SKalle Valo } 2415d5c65159SKalle Valo 2416acc79d98SSriram R int ath11k_dp_process_rx(struct ath11k_base *ab, int ring_id, 2417acc79d98SSriram R struct napi_struct *napi, int budget) 2418d5c65159SKalle Valo { 2419acc79d98SSriram R struct ath11k_dp *dp = &ab->dp; 2420acc79d98SSriram R struct dp_rxdma_ring *rx_ring; 2421acc79d98SSriram R int num_buffs_reaped[MAX_RADIOS] = {0}; 2422acc79d98SSriram R struct sk_buff_head msdu_list; 2423acc79d98SSriram R struct ath11k_skb_rxcb *rxcb; 2424acc79d98SSriram R int total_msdu_reaped = 0; 2425d5c65159SKalle Valo struct hal_srng *srng; 2426d5c65159SKalle Valo struct sk_buff *msdu; 2427d5c65159SKalle Valo int quota = budget; 2428d5c65159SKalle Valo bool done = false; 2429acc79d98SSriram R int buf_id, mac_id; 2430acc79d98SSriram R struct ath11k *ar; 2431acc79d98SSriram R u32 *rx_desc; 2432acc79d98SSriram R int i; 2433d5c65159SKalle Valo 2434d5c65159SKalle Valo __skb_queue_head_init(&msdu_list); 2435d5c65159SKalle Valo 2436acc79d98SSriram R srng = &ab->hal.srng_list[dp->reo_dst_ring[ring_id].ring_id]; 2437d5c65159SKalle Valo 2438d5c65159SKalle Valo spin_lock_bh(&srng->lock); 2439d5c65159SKalle Valo 2440d5c65159SKalle Valo ath11k_hal_srng_access_begin(ab, srng); 2441d5c65159SKalle Valo 2442d5c65159SKalle Valo try_again: 2443d5c65159SKalle Valo while ((rx_desc = ath11k_hal_srng_dst_get_next_entry(ab, srng))) { 24447395fb49SManikanta Pubbisetty struct hal_reo_dest_ring desc = *(struct hal_reo_dest_ring *)rx_desc; 2445293cb583SJohn Crispin enum hal_reo_dest_ring_push_reason push_reason; 2446293cb583SJohn Crispin u32 cookie; 2447d5c65159SKalle Valo 2448293cb583SJohn Crispin cookie = FIELD_GET(BUFFER_ADDR_INFO1_SW_COOKIE, 24497395fb49SManikanta Pubbisetty desc.buf_addr_info.info1); 2450d5c65159SKalle Valo buf_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_BUF_ID, 2451293cb583SJohn Crispin cookie); 2452acc79d98SSriram R mac_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_PDEV_ID, cookie); 2453acc79d98SSriram R 2454acc79d98SSriram R ar = ab->pdevs[mac_id].ar; 2455acc79d98SSriram R rx_ring = &ar->dp.rx_refill_buf_ring; 2456d5c65159SKalle Valo spin_lock_bh(&rx_ring->idr_lock); 2457d5c65159SKalle Valo msdu = idr_find(&rx_ring->bufs_idr, buf_id); 2458d5c65159SKalle Valo if (!msdu) { 2459d5c65159SKalle Valo ath11k_warn(ab, "frame rx with invalid buf_id %d\n", 2460d5c65159SKalle Valo buf_id); 2461d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 2462d5c65159SKalle Valo continue; 2463d5c65159SKalle Valo } 2464d5c65159SKalle Valo 2465d5c65159SKalle Valo idr_remove(&rx_ring->bufs_idr, buf_id); 2466d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 2467d5c65159SKalle Valo 2468d5c65159SKalle Valo rxcb = ATH11K_SKB_RXCB(msdu); 2469d5c65159SKalle Valo dma_unmap_single(ab->dev, rxcb->paddr, 2470d5c65159SKalle Valo msdu->len + skb_tailroom(msdu), 2471d5c65159SKalle Valo DMA_FROM_DEVICE); 2472d5c65159SKalle Valo 2473acc79d98SSriram R num_buffs_reaped[mac_id]++; 2474acc79d98SSriram R total_msdu_reaped++; 2475d5c65159SKalle Valo 2476293cb583SJohn Crispin push_reason = FIELD_GET(HAL_REO_DEST_RING_INFO0_PUSH_REASON, 24777395fb49SManikanta Pubbisetty desc.info0); 2478293cb583SJohn Crispin if (push_reason != 2479d5c65159SKalle Valo HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION) { 2480d5c65159SKalle Valo dev_kfree_skb_any(msdu); 2481acc79d98SSriram R ab->soc_stats.hal_reo_error[dp->reo_dst_ring[ring_id].ring_id]++; 2482d5c65159SKalle Valo continue; 2483d5c65159SKalle Valo } 2484d5c65159SKalle Valo 24857395fb49SManikanta Pubbisetty rxcb->is_first_msdu = !!(desc.rx_msdu_info.info0 & 2486293cb583SJohn Crispin RX_MSDU_DESC_INFO0_FIRST_MSDU_IN_MPDU); 24877395fb49SManikanta Pubbisetty rxcb->is_last_msdu = !!(desc.rx_msdu_info.info0 & 2488293cb583SJohn Crispin RX_MSDU_DESC_INFO0_LAST_MSDU_IN_MPDU); 24897395fb49SManikanta Pubbisetty rxcb->is_continuation = !!(desc.rx_msdu_info.info0 & 2490293cb583SJohn Crispin RX_MSDU_DESC_INFO0_MSDU_CONTINUATION); 2491d5c65159SKalle Valo rxcb->mac_id = mac_id; 2492acc79d98SSriram R rxcb->tid = FIELD_GET(HAL_REO_DEST_RING_INFO0_RX_QUEUE_NUM, 24937395fb49SManikanta Pubbisetty desc.info0); 2494acc79d98SSriram R 2495d5c65159SKalle Valo __skb_queue_tail(&msdu_list, msdu); 2496d5c65159SKalle Valo 2497acc79d98SSriram R if (total_msdu_reaped >= quota && !rxcb->is_continuation) { 2498d5c65159SKalle Valo done = true; 2499d5c65159SKalle Valo break; 2500d5c65159SKalle Valo } 2501d5c65159SKalle Valo } 2502d5c65159SKalle Valo 2503d5c65159SKalle Valo /* Hw might have updated the head pointer after we cached it. 2504d5c65159SKalle Valo * In this case, even though there are entries in the ring we'll 2505d5c65159SKalle Valo * get rx_desc NULL. Give the read another try with updated cached 2506d5c65159SKalle Valo * head pointer so that we can reap complete MPDU in the current 2507d5c65159SKalle Valo * rx processing. 2508d5c65159SKalle Valo */ 2509d5c65159SKalle Valo if (!done && ath11k_hal_srng_dst_num_free(ab, srng, true)) { 2510d5c65159SKalle Valo ath11k_hal_srng_access_end(ab, srng); 2511d5c65159SKalle Valo goto try_again; 2512d5c65159SKalle Valo } 2513d5c65159SKalle Valo 2514d5c65159SKalle Valo ath11k_hal_srng_access_end(ab, srng); 2515d5c65159SKalle Valo 2516d5c65159SKalle Valo spin_unlock_bh(&srng->lock); 2517d5c65159SKalle Valo 2518acc79d98SSriram R if (!total_msdu_reaped) 2519d5c65159SKalle Valo goto exit; 2520d5c65159SKalle Valo 2521acc79d98SSriram R for (i = 0; i < ab->num_radios; i++) { 2522acc79d98SSriram R if (!num_buffs_reaped[i]) 2523d5c65159SKalle Valo continue; 2524acc79d98SSriram R 2525acc79d98SSriram R ar = ab->pdevs[i].ar; 2526acc79d98SSriram R rx_ring = &ar->dp.rx_refill_buf_ring; 2527acc79d98SSriram R 2528acc79d98SSriram R ath11k_dp_rxbufs_replenish(ab, i, rx_ring, num_buffs_reaped[i], 2529acc79d98SSriram R HAL_RX_BUF_RBM_SW3_BM, GFP_ATOMIC); 2530d5c65159SKalle Valo } 2531d5c65159SKalle Valo 2532acc79d98SSriram R ath11k_dp_rx_process_received_packets(ab, napi, &msdu_list, 2533acc79d98SSriram R "a, ring_id); 2534d5c65159SKalle Valo 2535d5c65159SKalle Valo exit: 2536d5c65159SKalle Valo return budget - quota; 2537d5c65159SKalle Valo } 2538d5c65159SKalle Valo 2539d5c65159SKalle Valo static void ath11k_dp_rx_update_peer_stats(struct ath11k_sta *arsta, 2540d5c65159SKalle Valo struct hal_rx_mon_ppdu_info *ppdu_info) 2541d5c65159SKalle Valo { 2542d5c65159SKalle Valo struct ath11k_rx_peer_stats *rx_stats = arsta->rx_stats; 2543d5c65159SKalle Valo u32 num_msdu; 2544d5c65159SKalle Valo 2545d5c65159SKalle Valo if (!rx_stats) 2546d5c65159SKalle Valo return; 2547d5c65159SKalle Valo 2548d5c65159SKalle Valo num_msdu = ppdu_info->tcp_msdu_count + ppdu_info->tcp_ack_msdu_count + 2549d5c65159SKalle Valo ppdu_info->udp_msdu_count + ppdu_info->other_msdu_count; 2550d5c65159SKalle Valo 2551d5c65159SKalle Valo rx_stats->num_msdu += num_msdu; 2552d5c65159SKalle Valo rx_stats->tcp_msdu_count += ppdu_info->tcp_msdu_count + 2553d5c65159SKalle Valo ppdu_info->tcp_ack_msdu_count; 2554d5c65159SKalle Valo rx_stats->udp_msdu_count += ppdu_info->udp_msdu_count; 2555d5c65159SKalle Valo rx_stats->other_msdu_count += ppdu_info->other_msdu_count; 2556d5c65159SKalle Valo 2557d5c65159SKalle Valo if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11A || 2558d5c65159SKalle Valo ppdu_info->preamble_type == HAL_RX_PREAMBLE_11B) { 2559d5c65159SKalle Valo ppdu_info->nss = 1; 2560d5c65159SKalle Valo ppdu_info->mcs = HAL_RX_MAX_MCS; 2561d5c65159SKalle Valo ppdu_info->tid = IEEE80211_NUM_TIDS; 2562d5c65159SKalle Valo } 2563d5c65159SKalle Valo 2564d5c65159SKalle Valo if (ppdu_info->nss > 0 && ppdu_info->nss <= HAL_RX_MAX_NSS) 2565d5c65159SKalle Valo rx_stats->nss_count[ppdu_info->nss - 1] += num_msdu; 2566d5c65159SKalle Valo 2567d5c65159SKalle Valo if (ppdu_info->mcs <= HAL_RX_MAX_MCS) 2568d5c65159SKalle Valo rx_stats->mcs_count[ppdu_info->mcs] += num_msdu; 2569d5c65159SKalle Valo 2570d5c65159SKalle Valo if (ppdu_info->gi < HAL_RX_GI_MAX) 2571d5c65159SKalle Valo rx_stats->gi_count[ppdu_info->gi] += num_msdu; 2572d5c65159SKalle Valo 2573d5c65159SKalle Valo if (ppdu_info->bw < HAL_RX_BW_MAX) 2574d5c65159SKalle Valo rx_stats->bw_count[ppdu_info->bw] += num_msdu; 2575d5c65159SKalle Valo 2576d5c65159SKalle Valo if (ppdu_info->ldpc < HAL_RX_SU_MU_CODING_MAX) 2577d5c65159SKalle Valo rx_stats->coding_count[ppdu_info->ldpc] += num_msdu; 2578d5c65159SKalle Valo 2579d5c65159SKalle Valo if (ppdu_info->tid <= IEEE80211_NUM_TIDS) 2580d5c65159SKalle Valo rx_stats->tid_count[ppdu_info->tid] += num_msdu; 2581d5c65159SKalle Valo 2582d5c65159SKalle Valo if (ppdu_info->preamble_type < HAL_RX_PREAMBLE_MAX) 2583d5c65159SKalle Valo rx_stats->pream_cnt[ppdu_info->preamble_type] += num_msdu; 2584d5c65159SKalle Valo 2585d5c65159SKalle Valo if (ppdu_info->reception_type < HAL_RX_RECEPTION_TYPE_MAX) 2586d5c65159SKalle Valo rx_stats->reception_type[ppdu_info->reception_type] += num_msdu; 2587d5c65159SKalle Valo 2588d5c65159SKalle Valo if (ppdu_info->is_stbc) 2589d5c65159SKalle Valo rx_stats->stbc_count += num_msdu; 2590d5c65159SKalle Valo 2591d5c65159SKalle Valo if (ppdu_info->beamformed) 2592d5c65159SKalle Valo rx_stats->beamformed_count += num_msdu; 2593d5c65159SKalle Valo 2594d5c65159SKalle Valo if (ppdu_info->num_mpdu_fcs_ok > 1) 2595d5c65159SKalle Valo rx_stats->ampdu_msdu_count += num_msdu; 2596d5c65159SKalle Valo else 2597d5c65159SKalle Valo rx_stats->non_ampdu_msdu_count += num_msdu; 2598d5c65159SKalle Valo 2599d5c65159SKalle Valo rx_stats->num_mpdu_fcs_ok += ppdu_info->num_mpdu_fcs_ok; 2600d5c65159SKalle Valo rx_stats->num_mpdu_fcs_err += ppdu_info->num_mpdu_fcs_err; 26016a0c3702SJohn Crispin rx_stats->dcm_count += ppdu_info->dcm; 26026a0c3702SJohn Crispin rx_stats->ru_alloc_cnt[ppdu_info->ru_alloc] += num_msdu; 2603d5c65159SKalle Valo 2604d5c65159SKalle Valo arsta->rssi_comb = ppdu_info->rssi_comb; 2605d5c65159SKalle Valo rx_stats->rx_duration += ppdu_info->rx_duration; 2606d5c65159SKalle Valo arsta->rx_duration = rx_stats->rx_duration; 2607d5c65159SKalle Valo } 2608d5c65159SKalle Valo 2609d5c65159SKalle Valo static struct sk_buff *ath11k_dp_rx_alloc_mon_status_buf(struct ath11k_base *ab, 2610d5c65159SKalle Valo struct dp_rxdma_ring *rx_ring, 2611d5c65159SKalle Valo int *buf_id, gfp_t gfp) 2612d5c65159SKalle Valo { 2613d5c65159SKalle Valo struct sk_buff *skb; 2614d5c65159SKalle Valo dma_addr_t paddr; 2615d5c65159SKalle Valo 2616d5c65159SKalle Valo skb = dev_alloc_skb(DP_RX_BUFFER_SIZE + 2617d5c65159SKalle Valo DP_RX_BUFFER_ALIGN_SIZE); 2618d5c65159SKalle Valo 2619d5c65159SKalle Valo if (!skb) 2620d5c65159SKalle Valo goto fail_alloc_skb; 2621d5c65159SKalle Valo 2622d5c65159SKalle Valo if (!IS_ALIGNED((unsigned long)skb->data, 2623d5c65159SKalle Valo DP_RX_BUFFER_ALIGN_SIZE)) { 2624d5c65159SKalle Valo skb_pull(skb, PTR_ALIGN(skb->data, DP_RX_BUFFER_ALIGN_SIZE) - 2625d5c65159SKalle Valo skb->data); 2626d5c65159SKalle Valo } 2627d5c65159SKalle Valo 2628d5c65159SKalle Valo paddr = dma_map_single(ab->dev, skb->data, 2629d5c65159SKalle Valo skb->len + skb_tailroom(skb), 2630d5c65159SKalle Valo DMA_BIDIRECTIONAL); 2631d5c65159SKalle Valo if (unlikely(dma_mapping_error(ab->dev, paddr))) 2632d5c65159SKalle Valo goto fail_free_skb; 2633d5c65159SKalle Valo 2634d5c65159SKalle Valo spin_lock_bh(&rx_ring->idr_lock); 2635d5c65159SKalle Valo *buf_id = idr_alloc(&rx_ring->bufs_idr, skb, 0, 2636d5c65159SKalle Valo rx_ring->bufs_max, gfp); 2637d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 2638d5c65159SKalle Valo if (*buf_id < 0) 2639d5c65159SKalle Valo goto fail_dma_unmap; 2640d5c65159SKalle Valo 2641d5c65159SKalle Valo ATH11K_SKB_RXCB(skb)->paddr = paddr; 2642d5c65159SKalle Valo return skb; 2643d5c65159SKalle Valo 2644d5c65159SKalle Valo fail_dma_unmap: 2645d5c65159SKalle Valo dma_unmap_single(ab->dev, paddr, skb->len + skb_tailroom(skb), 2646d5c65159SKalle Valo DMA_BIDIRECTIONAL); 2647d5c65159SKalle Valo fail_free_skb: 2648d5c65159SKalle Valo dev_kfree_skb_any(skb); 2649d5c65159SKalle Valo fail_alloc_skb: 2650d5c65159SKalle Valo return NULL; 2651d5c65159SKalle Valo } 2652d5c65159SKalle Valo 2653d5c65159SKalle Valo int ath11k_dp_rx_mon_status_bufs_replenish(struct ath11k_base *ab, int mac_id, 2654d5c65159SKalle Valo struct dp_rxdma_ring *rx_ring, 2655d5c65159SKalle Valo int req_entries, 2656d5c65159SKalle Valo enum hal_rx_buf_return_buf_manager mgr, 2657d5c65159SKalle Valo gfp_t gfp) 2658d5c65159SKalle Valo { 2659d5c65159SKalle Valo struct hal_srng *srng; 2660d5c65159SKalle Valo u32 *desc; 2661d5c65159SKalle Valo struct sk_buff *skb; 2662d5c65159SKalle Valo int num_free; 2663d5c65159SKalle Valo int num_remain; 2664d5c65159SKalle Valo int buf_id; 2665d5c65159SKalle Valo u32 cookie; 2666d5c65159SKalle Valo dma_addr_t paddr; 2667d5c65159SKalle Valo 2668d5c65159SKalle Valo req_entries = min(req_entries, rx_ring->bufs_max); 2669d5c65159SKalle Valo 2670d5c65159SKalle Valo srng = &ab->hal.srng_list[rx_ring->refill_buf_ring.ring_id]; 2671d5c65159SKalle Valo 2672d5c65159SKalle Valo spin_lock_bh(&srng->lock); 2673d5c65159SKalle Valo 2674d5c65159SKalle Valo ath11k_hal_srng_access_begin(ab, srng); 2675d5c65159SKalle Valo 2676d5c65159SKalle Valo num_free = ath11k_hal_srng_src_num_free(ab, srng, true); 2677d5c65159SKalle Valo 2678d5c65159SKalle Valo req_entries = min(num_free, req_entries); 2679d5c65159SKalle Valo num_remain = req_entries; 2680d5c65159SKalle Valo 2681d5c65159SKalle Valo while (num_remain > 0) { 2682d5c65159SKalle Valo skb = ath11k_dp_rx_alloc_mon_status_buf(ab, rx_ring, 2683d5c65159SKalle Valo &buf_id, gfp); 2684d5c65159SKalle Valo if (!skb) 2685d5c65159SKalle Valo break; 2686d5c65159SKalle Valo paddr = ATH11K_SKB_RXCB(skb)->paddr; 2687d5c65159SKalle Valo 2688d5c65159SKalle Valo desc = ath11k_hal_srng_src_get_next_entry(ab, srng); 2689d5c65159SKalle Valo if (!desc) 2690d5c65159SKalle Valo goto fail_desc_get; 2691d5c65159SKalle Valo 2692d5c65159SKalle Valo cookie = FIELD_PREP(DP_RXDMA_BUF_COOKIE_PDEV_ID, mac_id) | 2693d5c65159SKalle Valo FIELD_PREP(DP_RXDMA_BUF_COOKIE_BUF_ID, buf_id); 2694d5c65159SKalle Valo 2695d5c65159SKalle Valo num_remain--; 2696d5c65159SKalle Valo 2697d5c65159SKalle Valo ath11k_hal_rx_buf_addr_info_set(desc, paddr, cookie, mgr); 2698d5c65159SKalle Valo } 2699d5c65159SKalle Valo 2700d5c65159SKalle Valo ath11k_hal_srng_access_end(ab, srng); 2701d5c65159SKalle Valo 2702d5c65159SKalle Valo spin_unlock_bh(&srng->lock); 2703d5c65159SKalle Valo 2704d5c65159SKalle Valo return req_entries - num_remain; 2705d5c65159SKalle Valo 2706d5c65159SKalle Valo fail_desc_get: 2707d5c65159SKalle Valo spin_lock_bh(&rx_ring->idr_lock); 2708d5c65159SKalle Valo idr_remove(&rx_ring->bufs_idr, buf_id); 2709d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 2710d5c65159SKalle Valo dma_unmap_single(ab->dev, paddr, skb->len + skb_tailroom(skb), 2711d5c65159SKalle Valo DMA_BIDIRECTIONAL); 2712d5c65159SKalle Valo dev_kfree_skb_any(skb); 2713d5c65159SKalle Valo ath11k_hal_srng_access_end(ab, srng); 2714d5c65159SKalle Valo spin_unlock_bh(&srng->lock); 2715d5c65159SKalle Valo 2716d5c65159SKalle Valo return req_entries - num_remain; 2717d5c65159SKalle Valo } 2718d5c65159SKalle Valo 2719d5c65159SKalle Valo static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id, 2720d5c65159SKalle Valo int *budget, struct sk_buff_head *skb_list) 2721d5c65159SKalle Valo { 2722d5c65159SKalle Valo struct ath11k *ar = ab->pdevs[mac_id].ar; 2723d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 2724d5c65159SKalle Valo struct dp_rxdma_ring *rx_ring = &dp->rx_mon_status_refill_ring; 2725d5c65159SKalle Valo struct hal_srng *srng; 2726d5c65159SKalle Valo void *rx_mon_status_desc; 2727d5c65159SKalle Valo struct sk_buff *skb; 2728d5c65159SKalle Valo struct ath11k_skb_rxcb *rxcb; 2729d5c65159SKalle Valo struct hal_tlv_hdr *tlv; 2730d5c65159SKalle Valo u32 cookie; 2731d5c65159SKalle Valo int buf_id; 2732d5c65159SKalle Valo dma_addr_t paddr; 2733d5c65159SKalle Valo u8 rbm; 2734d5c65159SKalle Valo int num_buffs_reaped = 0; 2735d5c65159SKalle Valo 2736d5c65159SKalle Valo srng = &ab->hal.srng_list[rx_ring->refill_buf_ring.ring_id]; 2737d5c65159SKalle Valo 2738d5c65159SKalle Valo spin_lock_bh(&srng->lock); 2739d5c65159SKalle Valo 2740d5c65159SKalle Valo ath11k_hal_srng_access_begin(ab, srng); 2741d5c65159SKalle Valo while (*budget) { 2742d5c65159SKalle Valo *budget -= 1; 2743d5c65159SKalle Valo rx_mon_status_desc = 2744d5c65159SKalle Valo ath11k_hal_srng_src_peek(ab, srng); 2745d5c65159SKalle Valo if (!rx_mon_status_desc) 2746d5c65159SKalle Valo break; 2747d5c65159SKalle Valo 2748d5c65159SKalle Valo ath11k_hal_rx_buf_addr_info_get(rx_mon_status_desc, &paddr, 2749d5c65159SKalle Valo &cookie, &rbm); 2750d5c65159SKalle Valo if (paddr) { 2751d5c65159SKalle Valo buf_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_BUF_ID, cookie); 2752d5c65159SKalle Valo 2753d5c65159SKalle Valo spin_lock_bh(&rx_ring->idr_lock); 2754d5c65159SKalle Valo skb = idr_find(&rx_ring->bufs_idr, buf_id); 2755d5c65159SKalle Valo if (!skb) { 2756d5c65159SKalle Valo ath11k_warn(ab, "rx monitor status with invalid buf_id %d\n", 2757d5c65159SKalle Valo buf_id); 2758d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 275932a2be49SMiles Hu goto move_next; 2760d5c65159SKalle Valo } 2761d5c65159SKalle Valo 2762d5c65159SKalle Valo idr_remove(&rx_ring->bufs_idr, buf_id); 2763d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 2764d5c65159SKalle Valo 2765d5c65159SKalle Valo rxcb = ATH11K_SKB_RXCB(skb); 2766d5c65159SKalle Valo 2767d5c65159SKalle Valo dma_sync_single_for_cpu(ab->dev, rxcb->paddr, 2768d5c65159SKalle Valo skb->len + skb_tailroom(skb), 2769d5c65159SKalle Valo DMA_FROM_DEVICE); 2770d5c65159SKalle Valo 2771d5c65159SKalle Valo dma_unmap_single(ab->dev, rxcb->paddr, 2772d5c65159SKalle Valo skb->len + skb_tailroom(skb), 2773d5c65159SKalle Valo DMA_BIDIRECTIONAL); 2774d5c65159SKalle Valo 2775d5c65159SKalle Valo tlv = (struct hal_tlv_hdr *)skb->data; 2776d5c65159SKalle Valo if (FIELD_GET(HAL_TLV_HDR_TAG, tlv->tl) != 2777d5c65159SKalle Valo HAL_RX_STATUS_BUFFER_DONE) { 277832a2be49SMiles Hu ath11k_warn(ab, "mon status DONE not set %lx\n", 277932a2be49SMiles Hu FIELD_GET(HAL_TLV_HDR_TAG, 278032a2be49SMiles Hu tlv->tl)); 278132a2be49SMiles Hu dev_kfree_skb_any(skb); 278232a2be49SMiles Hu goto move_next; 2783d5c65159SKalle Valo } 2784d5c65159SKalle Valo 2785d5c65159SKalle Valo __skb_queue_tail(skb_list, skb); 2786d5c65159SKalle Valo } 278732a2be49SMiles Hu move_next: 2788d5c65159SKalle Valo skb = ath11k_dp_rx_alloc_mon_status_buf(ab, rx_ring, 2789d5c65159SKalle Valo &buf_id, GFP_ATOMIC); 2790d5c65159SKalle Valo 2791d5c65159SKalle Valo if (!skb) { 2792d5c65159SKalle Valo ath11k_hal_rx_buf_addr_info_set(rx_mon_status_desc, 0, 0, 2793d5c65159SKalle Valo HAL_RX_BUF_RBM_SW3_BM); 2794d5c65159SKalle Valo num_buffs_reaped++; 2795d5c65159SKalle Valo break; 2796d5c65159SKalle Valo } 2797d5c65159SKalle Valo rxcb = ATH11K_SKB_RXCB(skb); 2798d5c65159SKalle Valo 2799d5c65159SKalle Valo cookie = FIELD_PREP(DP_RXDMA_BUF_COOKIE_PDEV_ID, mac_id) | 2800d5c65159SKalle Valo FIELD_PREP(DP_RXDMA_BUF_COOKIE_BUF_ID, buf_id); 2801d5c65159SKalle Valo 2802d5c65159SKalle Valo ath11k_hal_rx_buf_addr_info_set(rx_mon_status_desc, rxcb->paddr, 2803d5c65159SKalle Valo cookie, HAL_RX_BUF_RBM_SW3_BM); 2804d5c65159SKalle Valo ath11k_hal_srng_src_get_next_entry(ab, srng); 2805d5c65159SKalle Valo num_buffs_reaped++; 2806d5c65159SKalle Valo } 2807d5c65159SKalle Valo ath11k_hal_srng_access_end(ab, srng); 2808d5c65159SKalle Valo spin_unlock_bh(&srng->lock); 2809d5c65159SKalle Valo 2810d5c65159SKalle Valo return num_buffs_reaped; 2811d5c65159SKalle Valo } 2812d5c65159SKalle Valo 2813d5c65159SKalle Valo int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id, 2814d5c65159SKalle Valo struct napi_struct *napi, int budget) 2815d5c65159SKalle Valo { 2816d5c65159SKalle Valo struct ath11k *ar = ab->pdevs[mac_id].ar; 2817d5c65159SKalle Valo enum hal_rx_mon_status hal_status; 2818d5c65159SKalle Valo struct sk_buff *skb; 2819d5c65159SKalle Valo struct sk_buff_head skb_list; 2820d5c65159SKalle Valo struct hal_rx_mon_ppdu_info ppdu_info; 2821d5c65159SKalle Valo struct ath11k_peer *peer; 2822d5c65159SKalle Valo struct ath11k_sta *arsta; 2823d5c65159SKalle Valo int num_buffs_reaped = 0; 2824d5c65159SKalle Valo 2825d5c65159SKalle Valo __skb_queue_head_init(&skb_list); 2826d5c65159SKalle Valo 2827d5c65159SKalle Valo num_buffs_reaped = ath11k_dp_rx_reap_mon_status_ring(ab, mac_id, &budget, 2828d5c65159SKalle Valo &skb_list); 2829d5c65159SKalle Valo if (!num_buffs_reaped) 2830d5c65159SKalle Valo goto exit; 2831d5c65159SKalle Valo 2832d5c65159SKalle Valo while ((skb = __skb_dequeue(&skb_list))) { 2833d5c65159SKalle Valo memset(&ppdu_info, 0, sizeof(ppdu_info)); 2834d5c65159SKalle Valo ppdu_info.peer_id = HAL_INVALID_PEERID; 2835d5c65159SKalle Valo 2836d5c65159SKalle Valo if (ath11k_debug_is_pktlog_rx_stats_enabled(ar)) 2837d5c65159SKalle Valo trace_ath11k_htt_rxdesc(ar, skb->data, DP_RX_BUFFER_SIZE); 2838d5c65159SKalle Valo 2839d5c65159SKalle Valo hal_status = ath11k_hal_rx_parse_mon_status(ab, &ppdu_info, skb); 2840d5c65159SKalle Valo 2841d5c65159SKalle Valo if (ppdu_info.peer_id == HAL_INVALID_PEERID || 2842d5c65159SKalle Valo hal_status != HAL_RX_MON_STATUS_PPDU_DONE) { 2843d5c65159SKalle Valo dev_kfree_skb_any(skb); 2844d5c65159SKalle Valo continue; 2845d5c65159SKalle Valo } 2846d5c65159SKalle Valo 2847d5c65159SKalle Valo rcu_read_lock(); 2848d5c65159SKalle Valo spin_lock_bh(&ab->base_lock); 2849d5c65159SKalle Valo peer = ath11k_peer_find_by_id(ab, ppdu_info.peer_id); 2850d5c65159SKalle Valo 2851d5c65159SKalle Valo if (!peer || !peer->sta) { 28522dab7d22SJohn Crispin ath11k_dbg(ab, ATH11K_DBG_DATA, 28532dab7d22SJohn Crispin "failed to find the peer with peer_id %d\n", 2854d5c65159SKalle Valo ppdu_info.peer_id); 2855d5c65159SKalle Valo spin_unlock_bh(&ab->base_lock); 2856d5c65159SKalle Valo rcu_read_unlock(); 2857d5c65159SKalle Valo dev_kfree_skb_any(skb); 2858d5c65159SKalle Valo continue; 2859d5c65159SKalle Valo } 2860d5c65159SKalle Valo 2861d5c65159SKalle Valo arsta = (struct ath11k_sta *)peer->sta->drv_priv; 2862d5c65159SKalle Valo ath11k_dp_rx_update_peer_stats(arsta, &ppdu_info); 2863d5c65159SKalle Valo 2864d5c65159SKalle Valo if (ath11k_debug_is_pktlog_peer_valid(ar, peer->addr)) 2865d5c65159SKalle Valo trace_ath11k_htt_rxdesc(ar, skb->data, DP_RX_BUFFER_SIZE); 2866d5c65159SKalle Valo 2867d5c65159SKalle Valo spin_unlock_bh(&ab->base_lock); 2868d5c65159SKalle Valo rcu_read_unlock(); 2869d5c65159SKalle Valo 2870d5c65159SKalle Valo dev_kfree_skb_any(skb); 2871d5c65159SKalle Valo } 2872d5c65159SKalle Valo exit: 2873d5c65159SKalle Valo return num_buffs_reaped; 2874d5c65159SKalle Valo } 2875d5c65159SKalle Valo 2876243874c6SManikanta Pubbisetty static void ath11k_dp_rx_frag_timer(struct timer_list *timer) 2877d5c65159SKalle Valo { 2878243874c6SManikanta Pubbisetty struct dp_rx_tid *rx_tid = from_timer(rx_tid, timer, frag_timer); 2879d5c65159SKalle Valo 2880243874c6SManikanta Pubbisetty spin_lock_bh(&rx_tid->ab->base_lock); 2881243874c6SManikanta Pubbisetty if (rx_tid->last_frag_no && 2882243874c6SManikanta Pubbisetty rx_tid->rx_frag_bitmap == GENMASK(rx_tid->last_frag_no, 0)) { 2883243874c6SManikanta Pubbisetty spin_unlock_bh(&rx_tid->ab->base_lock); 2884243874c6SManikanta Pubbisetty return; 2885243874c6SManikanta Pubbisetty } 2886243874c6SManikanta Pubbisetty ath11k_dp_rx_frags_cleanup(rx_tid, true); 2887243874c6SManikanta Pubbisetty spin_unlock_bh(&rx_tid->ab->base_lock); 2888d5c65159SKalle Valo } 2889d5c65159SKalle Valo 2890243874c6SManikanta Pubbisetty int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id) 2891243874c6SManikanta Pubbisetty { 2892243874c6SManikanta Pubbisetty struct ath11k_base *ab = ar->ab; 2893243874c6SManikanta Pubbisetty struct crypto_shash *tfm; 2894243874c6SManikanta Pubbisetty struct ath11k_peer *peer; 2895243874c6SManikanta Pubbisetty struct dp_rx_tid *rx_tid; 2896243874c6SManikanta Pubbisetty int i; 2897d5c65159SKalle Valo 2898243874c6SManikanta Pubbisetty tfm = crypto_alloc_shash("michael_mic", 0, 0); 2899243874c6SManikanta Pubbisetty if (IS_ERR(tfm)) 2900243874c6SManikanta Pubbisetty return PTR_ERR(tfm); 2901d5c65159SKalle Valo 2902243874c6SManikanta Pubbisetty spin_lock_bh(&ab->base_lock); 2903d5c65159SKalle Valo 2904243874c6SManikanta Pubbisetty peer = ath11k_peer_find(ab, vdev_id, peer_mac); 2905243874c6SManikanta Pubbisetty if (!peer) { 2906243874c6SManikanta Pubbisetty ath11k_warn(ab, "failed to find the peer to set up fragment info\n"); 2907243874c6SManikanta Pubbisetty spin_unlock_bh(&ab->base_lock); 2908243874c6SManikanta Pubbisetty return -ENOENT; 2909243874c6SManikanta Pubbisetty } 2910243874c6SManikanta Pubbisetty 2911243874c6SManikanta Pubbisetty for (i = 0; i <= IEEE80211_NUM_TIDS; i++) { 2912243874c6SManikanta Pubbisetty rx_tid = &peer->rx_tid[i]; 2913243874c6SManikanta Pubbisetty rx_tid->ab = ab; 2914243874c6SManikanta Pubbisetty timer_setup(&rx_tid->frag_timer, ath11k_dp_rx_frag_timer, 0); 2915243874c6SManikanta Pubbisetty skb_queue_head_init(&rx_tid->rx_frags); 2916243874c6SManikanta Pubbisetty } 2917243874c6SManikanta Pubbisetty 2918243874c6SManikanta Pubbisetty peer->tfm_mmic = tfm; 2919243874c6SManikanta Pubbisetty spin_unlock_bh(&ab->base_lock); 2920243874c6SManikanta Pubbisetty 2921243874c6SManikanta Pubbisetty return 0; 2922243874c6SManikanta Pubbisetty } 2923243874c6SManikanta Pubbisetty 2924243874c6SManikanta Pubbisetty static int ath11k_dp_rx_h_michael_mic(struct crypto_shash *tfm, u8 *key, 2925243874c6SManikanta Pubbisetty struct ieee80211_hdr *hdr, u8 *data, 2926243874c6SManikanta Pubbisetty size_t data_len, u8 *mic) 2927243874c6SManikanta Pubbisetty { 2928243874c6SManikanta Pubbisetty SHASH_DESC_ON_STACK(desc, tfm); 2929243874c6SManikanta Pubbisetty u8 mic_hdr[16] = {0}; 2930243874c6SManikanta Pubbisetty u8 tid = 0; 2931243874c6SManikanta Pubbisetty int ret; 2932243874c6SManikanta Pubbisetty 2933243874c6SManikanta Pubbisetty if (!tfm) 2934243874c6SManikanta Pubbisetty return -EINVAL; 2935243874c6SManikanta Pubbisetty 2936243874c6SManikanta Pubbisetty desc->tfm = tfm; 2937243874c6SManikanta Pubbisetty 2938243874c6SManikanta Pubbisetty ret = crypto_shash_setkey(tfm, key, 8); 2939243874c6SManikanta Pubbisetty if (ret) 2940243874c6SManikanta Pubbisetty goto out; 2941243874c6SManikanta Pubbisetty 2942243874c6SManikanta Pubbisetty ret = crypto_shash_init(desc); 2943243874c6SManikanta Pubbisetty if (ret) 2944243874c6SManikanta Pubbisetty goto out; 2945243874c6SManikanta Pubbisetty 2946243874c6SManikanta Pubbisetty /* TKIP MIC header */ 2947243874c6SManikanta Pubbisetty memcpy(mic_hdr, ieee80211_get_DA(hdr), ETH_ALEN); 2948243874c6SManikanta Pubbisetty memcpy(mic_hdr + ETH_ALEN, ieee80211_get_SA(hdr), ETH_ALEN); 2949243874c6SManikanta Pubbisetty if (ieee80211_is_data_qos(hdr->frame_control)) 2950243874c6SManikanta Pubbisetty tid = ieee80211_get_tid(hdr); 2951243874c6SManikanta Pubbisetty mic_hdr[12] = tid; 2952243874c6SManikanta Pubbisetty 2953243874c6SManikanta Pubbisetty ret = crypto_shash_update(desc, mic_hdr, 16); 2954243874c6SManikanta Pubbisetty if (ret) 2955243874c6SManikanta Pubbisetty goto out; 2956243874c6SManikanta Pubbisetty ret = crypto_shash_update(desc, data, data_len); 2957243874c6SManikanta Pubbisetty if (ret) 2958243874c6SManikanta Pubbisetty goto out; 2959243874c6SManikanta Pubbisetty ret = crypto_shash_final(desc, mic); 2960243874c6SManikanta Pubbisetty out: 2961243874c6SManikanta Pubbisetty shash_desc_zero(desc); 2962d5c65159SKalle Valo return ret; 2963d5c65159SKalle Valo } 2964d5c65159SKalle Valo 2965243874c6SManikanta Pubbisetty static int ath11k_dp_rx_h_verify_tkip_mic(struct ath11k *ar, struct ath11k_peer *peer, 2966243874c6SManikanta Pubbisetty struct sk_buff *msdu) 2967d5c65159SKalle Valo { 2968243874c6SManikanta Pubbisetty struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)msdu->data; 2969243874c6SManikanta Pubbisetty struct ieee80211_rx_status *rxs = IEEE80211_SKB_RXCB(msdu); 2970243874c6SManikanta Pubbisetty struct ieee80211_key_conf *key_conf; 2971243874c6SManikanta Pubbisetty struct ieee80211_hdr *hdr; 2972243874c6SManikanta Pubbisetty u8 mic[IEEE80211_CCMP_MIC_LEN]; 2973243874c6SManikanta Pubbisetty int head_len, tail_len, ret; 2974243874c6SManikanta Pubbisetty size_t data_len; 2975243874c6SManikanta Pubbisetty u32 hdr_len; 2976243874c6SManikanta Pubbisetty u8 *key, *data; 2977243874c6SManikanta Pubbisetty u8 key_idx; 2978d5c65159SKalle Valo 2979243874c6SManikanta Pubbisetty if (ath11k_dp_rx_h_mpdu_start_enctype(rx_desc) != HAL_ENCRYPT_TYPE_TKIP_MIC) 2980243874c6SManikanta Pubbisetty return 0; 2981d5c65159SKalle Valo 2982243874c6SManikanta Pubbisetty hdr = (struct ieee80211_hdr *)(msdu->data + HAL_RX_DESC_SIZE); 2983243874c6SManikanta Pubbisetty hdr_len = ieee80211_hdrlen(hdr->frame_control); 2984243874c6SManikanta Pubbisetty head_len = hdr_len + HAL_RX_DESC_SIZE + IEEE80211_TKIP_IV_LEN; 2985243874c6SManikanta Pubbisetty tail_len = IEEE80211_CCMP_MIC_LEN + IEEE80211_TKIP_ICV_LEN + FCS_LEN; 2986d5c65159SKalle Valo 2987243874c6SManikanta Pubbisetty if (!is_multicast_ether_addr(hdr->addr1)) 2988243874c6SManikanta Pubbisetty key_idx = peer->ucast_keyidx; 2989243874c6SManikanta Pubbisetty else 2990243874c6SManikanta Pubbisetty key_idx = peer->mcast_keyidx; 2991d5c65159SKalle Valo 2992243874c6SManikanta Pubbisetty key_conf = peer->keys[key_idx]; 2993d5c65159SKalle Valo 2994243874c6SManikanta Pubbisetty data = msdu->data + head_len; 2995243874c6SManikanta Pubbisetty data_len = msdu->len - head_len - tail_len; 2996243874c6SManikanta Pubbisetty key = &key_conf->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]; 2997d5c65159SKalle Valo 2998243874c6SManikanta Pubbisetty ret = ath11k_dp_rx_h_michael_mic(peer->tfm_mmic, key, hdr, data, data_len, mic); 2999243874c6SManikanta Pubbisetty if (ret || memcmp(mic, data + data_len, IEEE80211_CCMP_MIC_LEN)) 3000243874c6SManikanta Pubbisetty goto mic_fail; 3001d5c65159SKalle Valo 3002243874c6SManikanta Pubbisetty return 0; 3003243874c6SManikanta Pubbisetty 3004243874c6SManikanta Pubbisetty mic_fail: 3005b7b527b9SJason Yan (ATH11K_SKB_RXCB(msdu))->is_first_msdu = true; 3006b7b527b9SJason Yan (ATH11K_SKB_RXCB(msdu))->is_last_msdu = true; 3007243874c6SManikanta Pubbisetty 3008243874c6SManikanta Pubbisetty rxs->flag |= RX_FLAG_MMIC_ERROR | RX_FLAG_MMIC_STRIPPED | 3009243874c6SManikanta Pubbisetty RX_FLAG_IV_STRIPPED | RX_FLAG_DECRYPTED; 3010243874c6SManikanta Pubbisetty skb_pull(msdu, HAL_RX_DESC_SIZE); 3011243874c6SManikanta Pubbisetty 3012243874c6SManikanta Pubbisetty ath11k_dp_rx_h_ppdu(ar, rx_desc, rxs); 3013243874c6SManikanta Pubbisetty ath11k_dp_rx_h_undecap(ar, msdu, rx_desc, 3014243874c6SManikanta Pubbisetty HAL_ENCRYPT_TYPE_TKIP_MIC, rxs, true); 3015243874c6SManikanta Pubbisetty ieee80211_rx(ar->hw, msdu); 3016243874c6SManikanta Pubbisetty return -EINVAL; 3017d5c65159SKalle Valo } 3018d5c65159SKalle Valo 3019243874c6SManikanta Pubbisetty static void ath11k_dp_rx_h_undecap_frag(struct ath11k *ar, struct sk_buff *msdu, 3020243874c6SManikanta Pubbisetty enum hal_encrypt_type enctype, u32 flags) 3021243874c6SManikanta Pubbisetty { 3022243874c6SManikanta Pubbisetty struct ieee80211_hdr *hdr; 3023243874c6SManikanta Pubbisetty size_t hdr_len; 3024243874c6SManikanta Pubbisetty size_t crypto_len; 3025d5c65159SKalle Valo 3026243874c6SManikanta Pubbisetty if (!flags) 3027243874c6SManikanta Pubbisetty return; 3028d5c65159SKalle Valo 3029243874c6SManikanta Pubbisetty hdr = (struct ieee80211_hdr *)(msdu->data + HAL_RX_DESC_SIZE); 3030243874c6SManikanta Pubbisetty 3031243874c6SManikanta Pubbisetty if (flags & RX_FLAG_MIC_STRIPPED) 3032d5c65159SKalle Valo skb_trim(msdu, msdu->len - 3033d5c65159SKalle Valo ath11k_dp_rx_crypto_mic_len(ar, enctype)); 3034243874c6SManikanta Pubbisetty 3035243874c6SManikanta Pubbisetty if (flags & RX_FLAG_ICV_STRIPPED) 3036243874c6SManikanta Pubbisetty skb_trim(msdu, msdu->len - 3037243874c6SManikanta Pubbisetty ath11k_dp_rx_crypto_icv_len(ar, enctype)); 3038243874c6SManikanta Pubbisetty 3039243874c6SManikanta Pubbisetty if (flags & RX_FLAG_IV_STRIPPED) { 3040243874c6SManikanta Pubbisetty hdr_len = ieee80211_hdrlen(hdr->frame_control); 3041243874c6SManikanta Pubbisetty crypto_len = ath11k_dp_rx_crypto_param_len(ar, enctype); 3042243874c6SManikanta Pubbisetty 3043243874c6SManikanta Pubbisetty memmove((void *)msdu->data + HAL_RX_DESC_SIZE + crypto_len, 3044243874c6SManikanta Pubbisetty (void *)msdu->data + HAL_RX_DESC_SIZE, hdr_len); 3045243874c6SManikanta Pubbisetty skb_pull(msdu, crypto_len); 3046d5c65159SKalle Valo } 3047d5c65159SKalle Valo } 3048d5c65159SKalle Valo 3049243874c6SManikanta Pubbisetty static int ath11k_dp_rx_h_defrag(struct ath11k *ar, 3050243874c6SManikanta Pubbisetty struct ath11k_peer *peer, 3051243874c6SManikanta Pubbisetty struct dp_rx_tid *rx_tid, 3052243874c6SManikanta Pubbisetty struct sk_buff **defrag_skb) 3053243874c6SManikanta Pubbisetty { 3054243874c6SManikanta Pubbisetty struct hal_rx_desc *rx_desc; 3055243874c6SManikanta Pubbisetty struct sk_buff *skb, *first_frag, *last_frag; 3056243874c6SManikanta Pubbisetty struct ieee80211_hdr *hdr; 3057243874c6SManikanta Pubbisetty enum hal_encrypt_type enctype; 3058243874c6SManikanta Pubbisetty bool is_decrypted = false; 3059243874c6SManikanta Pubbisetty int msdu_len = 0; 3060243874c6SManikanta Pubbisetty int extra_space; 3061243874c6SManikanta Pubbisetty u32 flags; 3062243874c6SManikanta Pubbisetty 3063243874c6SManikanta Pubbisetty first_frag = skb_peek(&rx_tid->rx_frags); 3064243874c6SManikanta Pubbisetty last_frag = skb_peek_tail(&rx_tid->rx_frags); 3065243874c6SManikanta Pubbisetty 3066243874c6SManikanta Pubbisetty skb_queue_walk(&rx_tid->rx_frags, skb) { 3067243874c6SManikanta Pubbisetty flags = 0; 3068243874c6SManikanta Pubbisetty rx_desc = (struct hal_rx_desc *)skb->data; 3069243874c6SManikanta Pubbisetty hdr = (struct ieee80211_hdr *)(skb->data + HAL_RX_DESC_SIZE); 3070243874c6SManikanta Pubbisetty 3071243874c6SManikanta Pubbisetty enctype = ath11k_dp_rx_h_mpdu_start_enctype(rx_desc); 3072243874c6SManikanta Pubbisetty if (enctype != HAL_ENCRYPT_TYPE_OPEN) 3073243874c6SManikanta Pubbisetty is_decrypted = ath11k_dp_rx_h_attn_is_decrypted(rx_desc); 3074243874c6SManikanta Pubbisetty 3075243874c6SManikanta Pubbisetty if (is_decrypted) { 3076243874c6SManikanta Pubbisetty if (skb != first_frag) 3077243874c6SManikanta Pubbisetty flags |= RX_FLAG_IV_STRIPPED; 3078243874c6SManikanta Pubbisetty if (skb != last_frag) 3079243874c6SManikanta Pubbisetty flags |= RX_FLAG_ICV_STRIPPED | 3080243874c6SManikanta Pubbisetty RX_FLAG_MIC_STRIPPED; 3081243874c6SManikanta Pubbisetty } 3082243874c6SManikanta Pubbisetty 3083243874c6SManikanta Pubbisetty /* RX fragments are always raw packets */ 3084243874c6SManikanta Pubbisetty if (skb != last_frag) 3085243874c6SManikanta Pubbisetty skb_trim(skb, skb->len - FCS_LEN); 3086243874c6SManikanta Pubbisetty ath11k_dp_rx_h_undecap_frag(ar, skb, enctype, flags); 3087243874c6SManikanta Pubbisetty 3088243874c6SManikanta Pubbisetty if (skb != first_frag) 3089243874c6SManikanta Pubbisetty skb_pull(skb, HAL_RX_DESC_SIZE + 3090243874c6SManikanta Pubbisetty ieee80211_hdrlen(hdr->frame_control)); 3091243874c6SManikanta Pubbisetty msdu_len += skb->len; 3092243874c6SManikanta Pubbisetty } 3093243874c6SManikanta Pubbisetty 3094243874c6SManikanta Pubbisetty extra_space = msdu_len - (DP_RX_BUFFER_SIZE + skb_tailroom(first_frag)); 3095243874c6SManikanta Pubbisetty if (extra_space > 0 && 3096243874c6SManikanta Pubbisetty (pskb_expand_head(first_frag, 0, extra_space, GFP_ATOMIC) < 0)) 3097243874c6SManikanta Pubbisetty return -ENOMEM; 3098243874c6SManikanta Pubbisetty 3099243874c6SManikanta Pubbisetty __skb_unlink(first_frag, &rx_tid->rx_frags); 3100243874c6SManikanta Pubbisetty while ((skb = __skb_dequeue(&rx_tid->rx_frags))) { 3101243874c6SManikanta Pubbisetty skb_put_data(first_frag, skb->data, skb->len); 3102243874c6SManikanta Pubbisetty dev_kfree_skb_any(skb); 3103243874c6SManikanta Pubbisetty } 3104243874c6SManikanta Pubbisetty 3105243874c6SManikanta Pubbisetty hdr = (struct ieee80211_hdr *)(first_frag->data + HAL_RX_DESC_SIZE); 3106243874c6SManikanta Pubbisetty hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); 3107243874c6SManikanta Pubbisetty ATH11K_SKB_RXCB(first_frag)->is_frag = 1; 3108243874c6SManikanta Pubbisetty 3109243874c6SManikanta Pubbisetty if (ath11k_dp_rx_h_verify_tkip_mic(ar, peer, first_frag)) 3110243874c6SManikanta Pubbisetty first_frag = NULL; 3111243874c6SManikanta Pubbisetty 3112243874c6SManikanta Pubbisetty *defrag_skb = first_frag; 3113243874c6SManikanta Pubbisetty return 0; 3114243874c6SManikanta Pubbisetty } 3115243874c6SManikanta Pubbisetty 3116243874c6SManikanta Pubbisetty static int ath11k_dp_rx_h_defrag_reo_reinject(struct ath11k *ar, struct dp_rx_tid *rx_tid, 3117243874c6SManikanta Pubbisetty struct sk_buff *defrag_skb) 3118243874c6SManikanta Pubbisetty { 3119243874c6SManikanta Pubbisetty struct ath11k_base *ab = ar->ab; 3120243874c6SManikanta Pubbisetty struct ath11k_pdev_dp *dp = &ar->dp; 3121243874c6SManikanta Pubbisetty struct dp_rxdma_ring *rx_refill_ring = &dp->rx_refill_buf_ring; 3122243874c6SManikanta Pubbisetty struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)defrag_skb->data; 3123243874c6SManikanta Pubbisetty struct hal_reo_entrance_ring *reo_ent_ring; 3124243874c6SManikanta Pubbisetty struct hal_reo_dest_ring *reo_dest_ring; 3125243874c6SManikanta Pubbisetty struct dp_link_desc_bank *link_desc_banks; 3126243874c6SManikanta Pubbisetty struct hal_rx_msdu_link *msdu_link; 3127243874c6SManikanta Pubbisetty struct hal_rx_msdu_details *msdu0; 3128243874c6SManikanta Pubbisetty struct hal_srng *srng; 3129243874c6SManikanta Pubbisetty dma_addr_t paddr; 3130243874c6SManikanta Pubbisetty u32 desc_bank, msdu_info, mpdu_info; 3131243874c6SManikanta Pubbisetty u32 dst_idx, cookie; 3132243874c6SManikanta Pubbisetty u32 *msdu_len_offset; 3133243874c6SManikanta Pubbisetty int ret, buf_id; 3134243874c6SManikanta Pubbisetty 3135243874c6SManikanta Pubbisetty link_desc_banks = ab->dp.link_desc_banks; 3136243874c6SManikanta Pubbisetty reo_dest_ring = rx_tid->dst_ring_desc; 3137243874c6SManikanta Pubbisetty 3138243874c6SManikanta Pubbisetty ath11k_hal_rx_reo_ent_paddr_get(ab, reo_dest_ring, &paddr, &desc_bank); 3139243874c6SManikanta Pubbisetty msdu_link = (struct hal_rx_msdu_link *)(link_desc_banks[desc_bank].vaddr + 3140243874c6SManikanta Pubbisetty (paddr - link_desc_banks[desc_bank].paddr)); 3141243874c6SManikanta Pubbisetty msdu0 = &msdu_link->msdu_link[0]; 3142243874c6SManikanta Pubbisetty dst_idx = FIELD_GET(RX_MSDU_DESC_INFO0_REO_DEST_IND, msdu0->rx_msdu_info.info0); 3143243874c6SManikanta Pubbisetty memset(msdu0, 0, sizeof(*msdu0)); 3144243874c6SManikanta Pubbisetty 3145243874c6SManikanta Pubbisetty msdu_info = FIELD_PREP(RX_MSDU_DESC_INFO0_FIRST_MSDU_IN_MPDU, 1) | 3146243874c6SManikanta Pubbisetty FIELD_PREP(RX_MSDU_DESC_INFO0_LAST_MSDU_IN_MPDU, 1) | 3147243874c6SManikanta Pubbisetty FIELD_PREP(RX_MSDU_DESC_INFO0_MSDU_CONTINUATION, 0) | 3148243874c6SManikanta Pubbisetty FIELD_PREP(RX_MSDU_DESC_INFO0_MSDU_LENGTH, 3149243874c6SManikanta Pubbisetty defrag_skb->len - HAL_RX_DESC_SIZE) | 3150243874c6SManikanta Pubbisetty FIELD_PREP(RX_MSDU_DESC_INFO0_REO_DEST_IND, dst_idx) | 3151243874c6SManikanta Pubbisetty FIELD_PREP(RX_MSDU_DESC_INFO0_VALID_SA, 1) | 3152243874c6SManikanta Pubbisetty FIELD_PREP(RX_MSDU_DESC_INFO0_VALID_DA, 1); 3153243874c6SManikanta Pubbisetty msdu0->rx_msdu_info.info0 = msdu_info; 3154243874c6SManikanta Pubbisetty 3155243874c6SManikanta Pubbisetty /* change msdu len in hal rx desc */ 3156243874c6SManikanta Pubbisetty msdu_len_offset = (u32 *)&rx_desc->msdu_start; 3157243874c6SManikanta Pubbisetty *msdu_len_offset &= ~(RX_MSDU_START_INFO1_MSDU_LENGTH); 3158243874c6SManikanta Pubbisetty *msdu_len_offset |= defrag_skb->len - HAL_RX_DESC_SIZE; 3159243874c6SManikanta Pubbisetty 3160243874c6SManikanta Pubbisetty paddr = dma_map_single(ab->dev, defrag_skb->data, 3161243874c6SManikanta Pubbisetty defrag_skb->len + skb_tailroom(defrag_skb), 3162243874c6SManikanta Pubbisetty DMA_FROM_DEVICE); 3163243874c6SManikanta Pubbisetty if (dma_mapping_error(ab->dev, paddr)) 3164243874c6SManikanta Pubbisetty return -ENOMEM; 3165243874c6SManikanta Pubbisetty 3166243874c6SManikanta Pubbisetty spin_lock_bh(&rx_refill_ring->idr_lock); 3167243874c6SManikanta Pubbisetty buf_id = idr_alloc(&rx_refill_ring->bufs_idr, defrag_skb, 0, 3168243874c6SManikanta Pubbisetty rx_refill_ring->bufs_max * 3, GFP_ATOMIC); 3169243874c6SManikanta Pubbisetty spin_unlock_bh(&rx_refill_ring->idr_lock); 3170243874c6SManikanta Pubbisetty if (buf_id < 0) { 3171243874c6SManikanta Pubbisetty ret = -ENOMEM; 3172243874c6SManikanta Pubbisetty goto err_unmap_dma; 3173243874c6SManikanta Pubbisetty } 3174243874c6SManikanta Pubbisetty 3175243874c6SManikanta Pubbisetty ATH11K_SKB_RXCB(defrag_skb)->paddr = paddr; 3176243874c6SManikanta Pubbisetty cookie = FIELD_PREP(DP_RXDMA_BUF_COOKIE_PDEV_ID, dp->mac_id) | 3177243874c6SManikanta Pubbisetty FIELD_PREP(DP_RXDMA_BUF_COOKIE_BUF_ID, buf_id); 3178243874c6SManikanta Pubbisetty 3179243874c6SManikanta Pubbisetty ath11k_hal_rx_buf_addr_info_set(msdu0, paddr, cookie, HAL_RX_BUF_RBM_SW3_BM); 3180243874c6SManikanta Pubbisetty 3181243874c6SManikanta Pubbisetty /* Fill mpdu details into reo entrace ring */ 3182243874c6SManikanta Pubbisetty srng = &ab->hal.srng_list[ab->dp.reo_reinject_ring.ring_id]; 3183243874c6SManikanta Pubbisetty 3184243874c6SManikanta Pubbisetty spin_lock_bh(&srng->lock); 3185243874c6SManikanta Pubbisetty ath11k_hal_srng_access_begin(ab, srng); 3186243874c6SManikanta Pubbisetty 3187243874c6SManikanta Pubbisetty reo_ent_ring = (struct hal_reo_entrance_ring *) 3188243874c6SManikanta Pubbisetty ath11k_hal_srng_src_get_next_entry(ab, srng); 3189243874c6SManikanta Pubbisetty if (!reo_ent_ring) { 3190243874c6SManikanta Pubbisetty ath11k_hal_srng_access_end(ab, srng); 3191243874c6SManikanta Pubbisetty spin_unlock_bh(&srng->lock); 3192243874c6SManikanta Pubbisetty ret = -ENOSPC; 3193243874c6SManikanta Pubbisetty goto err_free_idr; 3194243874c6SManikanta Pubbisetty } 3195243874c6SManikanta Pubbisetty memset(reo_ent_ring, 0, sizeof(*reo_ent_ring)); 3196243874c6SManikanta Pubbisetty 3197243874c6SManikanta Pubbisetty ath11k_hal_rx_reo_ent_paddr_get(ab, reo_dest_ring, &paddr, &desc_bank); 3198243874c6SManikanta Pubbisetty ath11k_hal_rx_buf_addr_info_set(reo_ent_ring, paddr, desc_bank, 3199243874c6SManikanta Pubbisetty HAL_RX_BUF_RBM_WBM_IDLE_DESC_LIST); 3200243874c6SManikanta Pubbisetty 3201243874c6SManikanta Pubbisetty mpdu_info = FIELD_PREP(RX_MPDU_DESC_INFO0_MSDU_COUNT, 1) | 3202243874c6SManikanta Pubbisetty FIELD_PREP(RX_MPDU_DESC_INFO0_SEQ_NUM, rx_tid->cur_sn) | 3203243874c6SManikanta Pubbisetty FIELD_PREP(RX_MPDU_DESC_INFO0_FRAG_FLAG, 0) | 3204243874c6SManikanta Pubbisetty FIELD_PREP(RX_MPDU_DESC_INFO0_VALID_SA, 1) | 3205243874c6SManikanta Pubbisetty FIELD_PREP(RX_MPDU_DESC_INFO0_VALID_DA, 1) | 3206243874c6SManikanta Pubbisetty FIELD_PREP(RX_MPDU_DESC_INFO0_RAW_MPDU, 1) | 3207243874c6SManikanta Pubbisetty FIELD_PREP(RX_MPDU_DESC_INFO0_VALID_PN, 1); 3208243874c6SManikanta Pubbisetty 3209243874c6SManikanta Pubbisetty reo_ent_ring->rx_mpdu_info.info0 = mpdu_info; 3210243874c6SManikanta Pubbisetty reo_ent_ring->rx_mpdu_info.meta_data = reo_dest_ring->rx_mpdu_info.meta_data; 3211243874c6SManikanta Pubbisetty reo_ent_ring->queue_addr_lo = reo_dest_ring->queue_addr_lo; 3212243874c6SManikanta Pubbisetty reo_ent_ring->info0 = FIELD_PREP(HAL_REO_ENTR_RING_INFO0_QUEUE_ADDR_HI, 3213243874c6SManikanta Pubbisetty FIELD_GET(HAL_REO_DEST_RING_INFO0_QUEUE_ADDR_HI, 3214243874c6SManikanta Pubbisetty reo_dest_ring->info0)) | 3215243874c6SManikanta Pubbisetty FIELD_PREP(HAL_REO_ENTR_RING_INFO0_DEST_IND, dst_idx); 3216243874c6SManikanta Pubbisetty ath11k_hal_srng_access_end(ab, srng); 3217243874c6SManikanta Pubbisetty spin_unlock_bh(&srng->lock); 3218243874c6SManikanta Pubbisetty 3219243874c6SManikanta Pubbisetty return 0; 3220243874c6SManikanta Pubbisetty 3221243874c6SManikanta Pubbisetty err_free_idr: 3222243874c6SManikanta Pubbisetty spin_lock_bh(&rx_refill_ring->idr_lock); 3223243874c6SManikanta Pubbisetty idr_remove(&rx_refill_ring->bufs_idr, buf_id); 3224243874c6SManikanta Pubbisetty spin_unlock_bh(&rx_refill_ring->idr_lock); 3225243874c6SManikanta Pubbisetty err_unmap_dma: 3226243874c6SManikanta Pubbisetty dma_unmap_single(ab->dev, paddr, defrag_skb->len + skb_tailroom(defrag_skb), 3227243874c6SManikanta Pubbisetty DMA_FROM_DEVICE); 3228243874c6SManikanta Pubbisetty return ret; 3229243874c6SManikanta Pubbisetty } 3230243874c6SManikanta Pubbisetty 3231243874c6SManikanta Pubbisetty static int ath11k_dp_rx_h_cmp_frags(struct sk_buff *a, struct sk_buff *b) 3232243874c6SManikanta Pubbisetty { 3233243874c6SManikanta Pubbisetty int frag1, frag2; 3234243874c6SManikanta Pubbisetty 3235243874c6SManikanta Pubbisetty frag1 = ath11k_dp_rx_h_mpdu_start_frag_no(a); 3236243874c6SManikanta Pubbisetty frag2 = ath11k_dp_rx_h_mpdu_start_frag_no(b); 3237243874c6SManikanta Pubbisetty 3238243874c6SManikanta Pubbisetty return frag1 - frag2; 3239243874c6SManikanta Pubbisetty } 3240243874c6SManikanta Pubbisetty 3241243874c6SManikanta Pubbisetty static void ath11k_dp_rx_h_sort_frags(struct sk_buff_head *frag_list, 3242243874c6SManikanta Pubbisetty struct sk_buff *cur_frag) 3243243874c6SManikanta Pubbisetty { 3244243874c6SManikanta Pubbisetty struct sk_buff *skb; 3245243874c6SManikanta Pubbisetty int cmp; 3246243874c6SManikanta Pubbisetty 3247243874c6SManikanta Pubbisetty skb_queue_walk(frag_list, skb) { 3248243874c6SManikanta Pubbisetty cmp = ath11k_dp_rx_h_cmp_frags(skb, cur_frag); 3249243874c6SManikanta Pubbisetty if (cmp < 0) 3250243874c6SManikanta Pubbisetty continue; 3251243874c6SManikanta Pubbisetty __skb_queue_before(frag_list, skb, cur_frag); 3252243874c6SManikanta Pubbisetty return; 3253243874c6SManikanta Pubbisetty } 3254243874c6SManikanta Pubbisetty __skb_queue_tail(frag_list, cur_frag); 3255243874c6SManikanta Pubbisetty } 3256243874c6SManikanta Pubbisetty 3257243874c6SManikanta Pubbisetty static u64 ath11k_dp_rx_h_get_pn(struct sk_buff *skb) 3258243874c6SManikanta Pubbisetty { 3259243874c6SManikanta Pubbisetty struct ieee80211_hdr *hdr; 3260243874c6SManikanta Pubbisetty u64 pn = 0; 3261243874c6SManikanta Pubbisetty u8 *ehdr; 3262243874c6SManikanta Pubbisetty 3263243874c6SManikanta Pubbisetty hdr = (struct ieee80211_hdr *)(skb->data + HAL_RX_DESC_SIZE); 3264243874c6SManikanta Pubbisetty ehdr = skb->data + HAL_RX_DESC_SIZE + ieee80211_hdrlen(hdr->frame_control); 3265243874c6SManikanta Pubbisetty 3266243874c6SManikanta Pubbisetty pn = ehdr[0]; 3267243874c6SManikanta Pubbisetty pn |= (u64)ehdr[1] << 8; 3268243874c6SManikanta Pubbisetty pn |= (u64)ehdr[4] << 16; 3269243874c6SManikanta Pubbisetty pn |= (u64)ehdr[5] << 24; 3270243874c6SManikanta Pubbisetty pn |= (u64)ehdr[6] << 32; 3271243874c6SManikanta Pubbisetty pn |= (u64)ehdr[7] << 40; 3272243874c6SManikanta Pubbisetty 3273243874c6SManikanta Pubbisetty return pn; 3274243874c6SManikanta Pubbisetty } 3275243874c6SManikanta Pubbisetty 3276243874c6SManikanta Pubbisetty static bool 3277243874c6SManikanta Pubbisetty ath11k_dp_rx_h_defrag_validate_incr_pn(struct ath11k *ar, struct dp_rx_tid *rx_tid) 3278243874c6SManikanta Pubbisetty { 3279243874c6SManikanta Pubbisetty enum hal_encrypt_type encrypt_type; 3280243874c6SManikanta Pubbisetty struct sk_buff *first_frag, *skb; 3281243874c6SManikanta Pubbisetty struct hal_rx_desc *desc; 3282243874c6SManikanta Pubbisetty u64 last_pn; 3283243874c6SManikanta Pubbisetty u64 cur_pn; 3284243874c6SManikanta Pubbisetty 3285243874c6SManikanta Pubbisetty first_frag = skb_peek(&rx_tid->rx_frags); 3286243874c6SManikanta Pubbisetty desc = (struct hal_rx_desc *)first_frag->data; 3287243874c6SManikanta Pubbisetty 3288243874c6SManikanta Pubbisetty encrypt_type = ath11k_dp_rx_h_mpdu_start_enctype(desc); 3289243874c6SManikanta Pubbisetty if (encrypt_type != HAL_ENCRYPT_TYPE_CCMP_128 && 3290243874c6SManikanta Pubbisetty encrypt_type != HAL_ENCRYPT_TYPE_CCMP_256 && 3291243874c6SManikanta Pubbisetty encrypt_type != HAL_ENCRYPT_TYPE_GCMP_128 && 3292243874c6SManikanta Pubbisetty encrypt_type != HAL_ENCRYPT_TYPE_AES_GCMP_256) 3293243874c6SManikanta Pubbisetty return true; 3294243874c6SManikanta Pubbisetty 3295243874c6SManikanta Pubbisetty last_pn = ath11k_dp_rx_h_get_pn(first_frag); 3296243874c6SManikanta Pubbisetty skb_queue_walk(&rx_tid->rx_frags, skb) { 3297243874c6SManikanta Pubbisetty if (skb == first_frag) 3298243874c6SManikanta Pubbisetty continue; 3299243874c6SManikanta Pubbisetty 3300243874c6SManikanta Pubbisetty cur_pn = ath11k_dp_rx_h_get_pn(skb); 3301243874c6SManikanta Pubbisetty if (cur_pn != last_pn + 1) 3302243874c6SManikanta Pubbisetty return false; 3303243874c6SManikanta Pubbisetty last_pn = cur_pn; 3304243874c6SManikanta Pubbisetty } 3305243874c6SManikanta Pubbisetty return true; 3306243874c6SManikanta Pubbisetty } 3307243874c6SManikanta Pubbisetty 3308243874c6SManikanta Pubbisetty static int ath11k_dp_rx_frag_h_mpdu(struct ath11k *ar, 3309243874c6SManikanta Pubbisetty struct sk_buff *msdu, 3310243874c6SManikanta Pubbisetty u32 *ring_desc) 3311243874c6SManikanta Pubbisetty { 3312243874c6SManikanta Pubbisetty struct ath11k_base *ab = ar->ab; 3313243874c6SManikanta Pubbisetty struct hal_rx_desc *rx_desc; 3314243874c6SManikanta Pubbisetty struct ath11k_peer *peer; 3315243874c6SManikanta Pubbisetty struct dp_rx_tid *rx_tid; 3316243874c6SManikanta Pubbisetty struct sk_buff *defrag_skb = NULL; 3317243874c6SManikanta Pubbisetty u32 peer_id; 3318243874c6SManikanta Pubbisetty u16 seqno, frag_no; 3319243874c6SManikanta Pubbisetty u8 tid; 3320243874c6SManikanta Pubbisetty int ret = 0; 3321243874c6SManikanta Pubbisetty bool more_frags; 3322243874c6SManikanta Pubbisetty 3323243874c6SManikanta Pubbisetty rx_desc = (struct hal_rx_desc *)msdu->data; 3324243874c6SManikanta Pubbisetty peer_id = ath11k_dp_rx_h_mpdu_start_peer_id(rx_desc); 3325243874c6SManikanta Pubbisetty tid = ath11k_dp_rx_h_mpdu_start_tid(rx_desc); 3326243874c6SManikanta Pubbisetty seqno = ath11k_dp_rx_h_mpdu_start_seq_no(rx_desc); 3327243874c6SManikanta Pubbisetty frag_no = ath11k_dp_rx_h_mpdu_start_frag_no(msdu); 3328243874c6SManikanta Pubbisetty more_frags = ath11k_dp_rx_h_mpdu_start_more_frags(msdu); 3329243874c6SManikanta Pubbisetty 3330243874c6SManikanta Pubbisetty if (!ath11k_dp_rx_h_mpdu_start_seq_ctrl_valid(rx_desc) || 3331243874c6SManikanta Pubbisetty !ath11k_dp_rx_h_mpdu_start_fc_valid(rx_desc) || 3332243874c6SManikanta Pubbisetty tid > IEEE80211_NUM_TIDS) 3333243874c6SManikanta Pubbisetty return -EINVAL; 3334243874c6SManikanta Pubbisetty 3335243874c6SManikanta Pubbisetty /* received unfragmented packet in reo 3336243874c6SManikanta Pubbisetty * exception ring, this shouldn't happen 3337243874c6SManikanta Pubbisetty * as these packets typically come from 3338243874c6SManikanta Pubbisetty * reo2sw srngs. 3339243874c6SManikanta Pubbisetty */ 3340243874c6SManikanta Pubbisetty if (WARN_ON_ONCE(!frag_no && !more_frags)) 3341243874c6SManikanta Pubbisetty return -EINVAL; 3342243874c6SManikanta Pubbisetty 3343243874c6SManikanta Pubbisetty spin_lock_bh(&ab->base_lock); 3344243874c6SManikanta Pubbisetty peer = ath11k_peer_find_by_id(ab, peer_id); 3345243874c6SManikanta Pubbisetty if (!peer) { 3346243874c6SManikanta Pubbisetty ath11k_warn(ab, "failed to find the peer to de-fragment received fragment peer_id %d\n", 3347243874c6SManikanta Pubbisetty peer_id); 3348243874c6SManikanta Pubbisetty ret = -ENOENT; 3349243874c6SManikanta Pubbisetty goto out_unlock; 3350243874c6SManikanta Pubbisetty } 3351243874c6SManikanta Pubbisetty rx_tid = &peer->rx_tid[tid]; 3352243874c6SManikanta Pubbisetty 3353243874c6SManikanta Pubbisetty if ((!skb_queue_empty(&rx_tid->rx_frags) && seqno != rx_tid->cur_sn) || 3354243874c6SManikanta Pubbisetty skb_queue_empty(&rx_tid->rx_frags)) { 3355243874c6SManikanta Pubbisetty /* Flush stored fragments and start a new sequence */ 3356243874c6SManikanta Pubbisetty ath11k_dp_rx_frags_cleanup(rx_tid, true); 3357243874c6SManikanta Pubbisetty rx_tid->cur_sn = seqno; 3358243874c6SManikanta Pubbisetty } 3359243874c6SManikanta Pubbisetty 3360243874c6SManikanta Pubbisetty if (rx_tid->rx_frag_bitmap & BIT(frag_no)) { 3361243874c6SManikanta Pubbisetty /* Fragment already present */ 3362243874c6SManikanta Pubbisetty ret = -EINVAL; 3363243874c6SManikanta Pubbisetty goto out_unlock; 3364243874c6SManikanta Pubbisetty } 3365243874c6SManikanta Pubbisetty 3366243874c6SManikanta Pubbisetty if (frag_no > __fls(rx_tid->rx_frag_bitmap)) 3367243874c6SManikanta Pubbisetty __skb_queue_tail(&rx_tid->rx_frags, msdu); 3368243874c6SManikanta Pubbisetty else 3369243874c6SManikanta Pubbisetty ath11k_dp_rx_h_sort_frags(&rx_tid->rx_frags, msdu); 3370243874c6SManikanta Pubbisetty 3371243874c6SManikanta Pubbisetty rx_tid->rx_frag_bitmap |= BIT(frag_no); 3372243874c6SManikanta Pubbisetty if (!more_frags) 3373243874c6SManikanta Pubbisetty rx_tid->last_frag_no = frag_no; 3374243874c6SManikanta Pubbisetty 3375243874c6SManikanta Pubbisetty if (frag_no == 0) { 3376243874c6SManikanta Pubbisetty rx_tid->dst_ring_desc = kmemdup(ring_desc, 3377243874c6SManikanta Pubbisetty sizeof(*rx_tid->dst_ring_desc), 3378243874c6SManikanta Pubbisetty GFP_ATOMIC); 3379243874c6SManikanta Pubbisetty if (!rx_tid->dst_ring_desc) { 3380243874c6SManikanta Pubbisetty ret = -ENOMEM; 3381243874c6SManikanta Pubbisetty goto out_unlock; 3382243874c6SManikanta Pubbisetty } 3383243874c6SManikanta Pubbisetty } else { 3384243874c6SManikanta Pubbisetty ath11k_dp_rx_link_desc_return(ab, ring_desc, 3385243874c6SManikanta Pubbisetty HAL_WBM_REL_BM_ACT_PUT_IN_IDLE); 3386243874c6SManikanta Pubbisetty } 3387243874c6SManikanta Pubbisetty 3388243874c6SManikanta Pubbisetty if (!rx_tid->last_frag_no || 3389243874c6SManikanta Pubbisetty rx_tid->rx_frag_bitmap != GENMASK(rx_tid->last_frag_no, 0)) { 3390243874c6SManikanta Pubbisetty mod_timer(&rx_tid->frag_timer, jiffies + 3391243874c6SManikanta Pubbisetty ATH11K_DP_RX_FRAGMENT_TIMEOUT_MS); 3392243874c6SManikanta Pubbisetty goto out_unlock; 3393243874c6SManikanta Pubbisetty } 3394243874c6SManikanta Pubbisetty 3395243874c6SManikanta Pubbisetty spin_unlock_bh(&ab->base_lock); 3396243874c6SManikanta Pubbisetty del_timer_sync(&rx_tid->frag_timer); 3397243874c6SManikanta Pubbisetty spin_lock_bh(&ab->base_lock); 3398243874c6SManikanta Pubbisetty 3399243874c6SManikanta Pubbisetty peer = ath11k_peer_find_by_id(ab, peer_id); 3400243874c6SManikanta Pubbisetty if (!peer) 3401243874c6SManikanta Pubbisetty goto err_frags_cleanup; 3402243874c6SManikanta Pubbisetty 3403243874c6SManikanta Pubbisetty if (!ath11k_dp_rx_h_defrag_validate_incr_pn(ar, rx_tid)) 3404243874c6SManikanta Pubbisetty goto err_frags_cleanup; 3405243874c6SManikanta Pubbisetty 3406243874c6SManikanta Pubbisetty if (ath11k_dp_rx_h_defrag(ar, peer, rx_tid, &defrag_skb)) 3407243874c6SManikanta Pubbisetty goto err_frags_cleanup; 3408243874c6SManikanta Pubbisetty 3409243874c6SManikanta Pubbisetty if (!defrag_skb) 3410243874c6SManikanta Pubbisetty goto err_frags_cleanup; 3411243874c6SManikanta Pubbisetty 3412243874c6SManikanta Pubbisetty if (ath11k_dp_rx_h_defrag_reo_reinject(ar, rx_tid, defrag_skb)) 3413243874c6SManikanta Pubbisetty goto err_frags_cleanup; 3414243874c6SManikanta Pubbisetty 3415243874c6SManikanta Pubbisetty ath11k_dp_rx_frags_cleanup(rx_tid, false); 3416243874c6SManikanta Pubbisetty goto out_unlock; 3417243874c6SManikanta Pubbisetty 3418243874c6SManikanta Pubbisetty err_frags_cleanup: 3419243874c6SManikanta Pubbisetty dev_kfree_skb_any(defrag_skb); 3420243874c6SManikanta Pubbisetty ath11k_dp_rx_frags_cleanup(rx_tid, true); 3421243874c6SManikanta Pubbisetty out_unlock: 3422243874c6SManikanta Pubbisetty spin_unlock_bh(&ab->base_lock); 3423243874c6SManikanta Pubbisetty return ret; 3424243874c6SManikanta Pubbisetty } 3425243874c6SManikanta Pubbisetty 3426d5c65159SKalle Valo static int 3427243874c6SManikanta Pubbisetty ath11k_dp_process_rx_err_buf(struct ath11k *ar, u32 *ring_desc, int buf_id, bool drop) 3428d5c65159SKalle Valo { 3429d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 3430d5c65159SKalle Valo struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring; 3431d5c65159SKalle Valo struct sk_buff *msdu; 3432d5c65159SKalle Valo struct ath11k_skb_rxcb *rxcb; 3433d5c65159SKalle Valo struct hal_rx_desc *rx_desc; 3434d7d43782STamizh Chelvam u8 *hdr_status; 3435d5c65159SKalle Valo u16 msdu_len; 3436d5c65159SKalle Valo 3437d5c65159SKalle Valo spin_lock_bh(&rx_ring->idr_lock); 3438d5c65159SKalle Valo msdu = idr_find(&rx_ring->bufs_idr, buf_id); 3439d5c65159SKalle Valo if (!msdu) { 3440d5c65159SKalle Valo ath11k_warn(ar->ab, "rx err buf with invalid buf_id %d\n", 3441d5c65159SKalle Valo buf_id); 3442d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 3443d5c65159SKalle Valo return -EINVAL; 3444d5c65159SKalle Valo } 3445d5c65159SKalle Valo 3446d5c65159SKalle Valo idr_remove(&rx_ring->bufs_idr, buf_id); 3447d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 3448d5c65159SKalle Valo 3449d5c65159SKalle Valo rxcb = ATH11K_SKB_RXCB(msdu); 3450d5c65159SKalle Valo dma_unmap_single(ar->ab->dev, rxcb->paddr, 3451d5c65159SKalle Valo msdu->len + skb_tailroom(msdu), 3452d5c65159SKalle Valo DMA_FROM_DEVICE); 3453d5c65159SKalle Valo 3454243874c6SManikanta Pubbisetty if (drop) { 3455d5c65159SKalle Valo dev_kfree_skb_any(msdu); 3456d5c65159SKalle Valo return 0; 3457d5c65159SKalle Valo } 3458d5c65159SKalle Valo 3459d5c65159SKalle Valo rcu_read_lock(); 3460d5c65159SKalle Valo if (!rcu_dereference(ar->ab->pdevs_active[ar->pdev_idx])) { 3461d5c65159SKalle Valo dev_kfree_skb_any(msdu); 3462d5c65159SKalle Valo goto exit; 3463d5c65159SKalle Valo } 3464d5c65159SKalle Valo 3465d5c65159SKalle Valo if (test_bit(ATH11K_CAC_RUNNING, &ar->dev_flags)) { 3466d5c65159SKalle Valo dev_kfree_skb_any(msdu); 3467d5c65159SKalle Valo goto exit; 3468d5c65159SKalle Valo } 3469d5c65159SKalle Valo 3470d5c65159SKalle Valo rx_desc = (struct hal_rx_desc *)msdu->data; 3471d5c65159SKalle Valo msdu_len = ath11k_dp_rx_h_msdu_start_msdu_len(rx_desc); 3472d7d43782STamizh Chelvam if ((msdu_len + HAL_RX_DESC_SIZE) > DP_RX_BUFFER_SIZE) { 3473d7d43782STamizh Chelvam hdr_status = ath11k_dp_rx_h_80211_hdr(rx_desc); 3474d7d43782STamizh Chelvam ath11k_warn(ar->ab, "invalid msdu leng %u", msdu_len); 3475d7d43782STamizh Chelvam ath11k_dbg_dump(ar->ab, ATH11K_DBG_DATA, NULL, "", hdr_status, 3476d7d43782STamizh Chelvam sizeof(struct ieee80211_hdr)); 3477d7d43782STamizh Chelvam ath11k_dbg_dump(ar->ab, ATH11K_DBG_DATA, NULL, "", rx_desc, 3478d7d43782STamizh Chelvam sizeof(struct hal_rx_desc)); 3479d7d43782STamizh Chelvam dev_kfree_skb_any(msdu); 3480d7d43782STamizh Chelvam goto exit; 3481d7d43782STamizh Chelvam } 3482d7d43782STamizh Chelvam 3483d5c65159SKalle Valo skb_put(msdu, HAL_RX_DESC_SIZE + msdu_len); 3484d5c65159SKalle Valo 3485243874c6SManikanta Pubbisetty if (ath11k_dp_rx_frag_h_mpdu(ar, msdu, ring_desc)) { 3486243874c6SManikanta Pubbisetty dev_kfree_skb_any(msdu); 3487243874c6SManikanta Pubbisetty ath11k_dp_rx_link_desc_return(ar->ab, ring_desc, 3488243874c6SManikanta Pubbisetty HAL_WBM_REL_BM_ACT_PUT_IN_IDLE); 3489243874c6SManikanta Pubbisetty } 3490d5c65159SKalle Valo exit: 3491d5c65159SKalle Valo rcu_read_unlock(); 3492d5c65159SKalle Valo return 0; 3493d5c65159SKalle Valo } 3494d5c65159SKalle Valo 3495d5c65159SKalle Valo int ath11k_dp_process_rx_err(struct ath11k_base *ab, struct napi_struct *napi, 3496d5c65159SKalle Valo int budget) 3497d5c65159SKalle Valo { 3498293cb583SJohn Crispin u32 msdu_cookies[HAL_NUM_RX_MSDUS_PER_LINK_DESC]; 3499d5c65159SKalle Valo struct dp_link_desc_bank *link_desc_banks; 3500d5c65159SKalle Valo enum hal_rx_buf_return_buf_manager rbm; 3501d5c65159SKalle Valo int tot_n_bufs_reaped, quota, ret, i; 3502d5c65159SKalle Valo int n_bufs_reaped[MAX_RADIOS] = {0}; 3503d5c65159SKalle Valo struct dp_rxdma_ring *rx_ring; 3504d5c65159SKalle Valo struct dp_srng *reo_except; 3505d5c65159SKalle Valo u32 desc_bank, num_msdus; 3506d5c65159SKalle Valo struct hal_srng *srng; 3507d5c65159SKalle Valo struct ath11k_dp *dp; 3508d5c65159SKalle Valo void *link_desc_va; 3509d5c65159SKalle Valo int buf_id, mac_id; 3510d5c65159SKalle Valo struct ath11k *ar; 3511d5c65159SKalle Valo dma_addr_t paddr; 3512d5c65159SKalle Valo u32 *desc; 3513d5c65159SKalle Valo bool is_frag; 3514243874c6SManikanta Pubbisetty u8 drop = 0; 3515d5c65159SKalle Valo 3516d5c65159SKalle Valo tot_n_bufs_reaped = 0; 3517d5c65159SKalle Valo quota = budget; 3518d5c65159SKalle Valo 3519d5c65159SKalle Valo dp = &ab->dp; 3520d5c65159SKalle Valo reo_except = &dp->reo_except_ring; 3521d5c65159SKalle Valo link_desc_banks = dp->link_desc_banks; 3522d5c65159SKalle Valo 3523d5c65159SKalle Valo srng = &ab->hal.srng_list[reo_except->ring_id]; 3524d5c65159SKalle Valo 3525d5c65159SKalle Valo spin_lock_bh(&srng->lock); 3526d5c65159SKalle Valo 3527d5c65159SKalle Valo ath11k_hal_srng_access_begin(ab, srng); 3528d5c65159SKalle Valo 3529d5c65159SKalle Valo while (budget && 3530d5c65159SKalle Valo (desc = ath11k_hal_srng_dst_get_next_entry(ab, srng))) { 3531293cb583SJohn Crispin struct hal_reo_dest_ring *reo_desc = (struct hal_reo_dest_ring *)desc; 3532293cb583SJohn Crispin 3533d5c65159SKalle Valo ab->soc_stats.err_ring_pkts++; 3534d5c65159SKalle Valo ret = ath11k_hal_desc_reo_parse_err(ab, desc, &paddr, 3535d5c65159SKalle Valo &desc_bank); 3536d5c65159SKalle Valo if (ret) { 3537d5c65159SKalle Valo ath11k_warn(ab, "failed to parse error reo desc %d\n", 3538d5c65159SKalle Valo ret); 3539d5c65159SKalle Valo continue; 3540d5c65159SKalle Valo } 3541d5c65159SKalle Valo link_desc_va = link_desc_banks[desc_bank].vaddr + 3542d5c65159SKalle Valo (paddr - link_desc_banks[desc_bank].paddr); 3543293cb583SJohn Crispin ath11k_hal_rx_msdu_link_info_get(link_desc_va, &num_msdus, msdu_cookies, 3544d5c65159SKalle Valo &rbm); 3545d5c65159SKalle Valo if (rbm != HAL_RX_BUF_RBM_WBM_IDLE_DESC_LIST && 3546d5c65159SKalle Valo rbm != HAL_RX_BUF_RBM_SW3_BM) { 3547d5c65159SKalle Valo ab->soc_stats.invalid_rbm++; 3548d5c65159SKalle Valo ath11k_warn(ab, "invalid return buffer manager %d\n", rbm); 3549d5c65159SKalle Valo ath11k_dp_rx_link_desc_return(ab, desc, 3550d5c65159SKalle Valo HAL_WBM_REL_BM_ACT_REL_MSDU); 3551d5c65159SKalle Valo continue; 3552d5c65159SKalle Valo } 3553d5c65159SKalle Valo 3554293cb583SJohn Crispin is_frag = !!(reo_desc->rx_mpdu_info.info0 & RX_MPDU_DESC_INFO0_FRAG_FLAG); 3555d5c65159SKalle Valo 3556243874c6SManikanta Pubbisetty /* Process only rx fragments with one msdu per link desc below, and drop 3557243874c6SManikanta Pubbisetty * msdu's indicated due to error reasons. 3558243874c6SManikanta Pubbisetty */ 3559243874c6SManikanta Pubbisetty if (!is_frag || num_msdus > 1) { 3560243874c6SManikanta Pubbisetty drop = 1; 3561d5c65159SKalle Valo /* Return the link desc back to wbm idle list */ 3562d5c65159SKalle Valo ath11k_dp_rx_link_desc_return(ab, desc, 3563d5c65159SKalle Valo HAL_WBM_REL_BM_ACT_PUT_IN_IDLE); 3564243874c6SManikanta Pubbisetty } 3565d5c65159SKalle Valo 3566d5c65159SKalle Valo for (i = 0; i < num_msdus; i++) { 3567d5c65159SKalle Valo buf_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_BUF_ID, 3568293cb583SJohn Crispin msdu_cookies[i]); 3569d5c65159SKalle Valo 3570d5c65159SKalle Valo mac_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_PDEV_ID, 3571293cb583SJohn Crispin msdu_cookies[i]); 3572d5c65159SKalle Valo 3573d5c65159SKalle Valo ar = ab->pdevs[mac_id].ar; 3574d5c65159SKalle Valo 3575243874c6SManikanta Pubbisetty if (!ath11k_dp_process_rx_err_buf(ar, desc, buf_id, drop)) { 3576d5c65159SKalle Valo n_bufs_reaped[mac_id]++; 3577d5c65159SKalle Valo tot_n_bufs_reaped++; 3578d5c65159SKalle Valo } 3579d5c65159SKalle Valo } 3580d5c65159SKalle Valo 3581d5c65159SKalle Valo if (tot_n_bufs_reaped >= quota) { 3582d5c65159SKalle Valo tot_n_bufs_reaped = quota; 3583d5c65159SKalle Valo goto exit; 3584d5c65159SKalle Valo } 3585d5c65159SKalle Valo 3586d5c65159SKalle Valo budget = quota - tot_n_bufs_reaped; 3587d5c65159SKalle Valo } 3588d5c65159SKalle Valo 3589d5c65159SKalle Valo exit: 3590d5c65159SKalle Valo ath11k_hal_srng_access_end(ab, srng); 3591d5c65159SKalle Valo 3592d5c65159SKalle Valo spin_unlock_bh(&srng->lock); 3593d5c65159SKalle Valo 3594d5c65159SKalle Valo for (i = 0; i < ab->num_radios; i++) { 3595d5c65159SKalle Valo if (!n_bufs_reaped[i]) 3596d5c65159SKalle Valo continue; 3597d5c65159SKalle Valo 3598d5c65159SKalle Valo ar = ab->pdevs[i].ar; 3599d5c65159SKalle Valo rx_ring = &ar->dp.rx_refill_buf_ring; 3600d5c65159SKalle Valo 3601d5c65159SKalle Valo ath11k_dp_rxbufs_replenish(ab, i, rx_ring, n_bufs_reaped[i], 3602d5c65159SKalle Valo HAL_RX_BUF_RBM_SW3_BM, GFP_ATOMIC); 3603d5c65159SKalle Valo } 3604d5c65159SKalle Valo 3605d5c65159SKalle Valo return tot_n_bufs_reaped; 3606d5c65159SKalle Valo } 3607d5c65159SKalle Valo 3608d5c65159SKalle Valo static void ath11k_dp_rx_null_q_desc_sg_drop(struct ath11k *ar, 3609d5c65159SKalle Valo int msdu_len, 3610d5c65159SKalle Valo struct sk_buff_head *msdu_list) 3611d5c65159SKalle Valo { 3612d5c65159SKalle Valo struct sk_buff *skb, *tmp; 3613d5c65159SKalle Valo struct ath11k_skb_rxcb *rxcb; 3614d5c65159SKalle Valo int n_buffs; 3615d5c65159SKalle Valo 3616d5c65159SKalle Valo n_buffs = DIV_ROUND_UP(msdu_len, 3617d5c65159SKalle Valo (DP_RX_BUFFER_SIZE - HAL_RX_DESC_SIZE)); 3618d5c65159SKalle Valo 3619d5c65159SKalle Valo skb_queue_walk_safe(msdu_list, skb, tmp) { 3620d5c65159SKalle Valo rxcb = ATH11K_SKB_RXCB(skb); 3621d5c65159SKalle Valo if (rxcb->err_rel_src == HAL_WBM_REL_SRC_MODULE_REO && 3622d5c65159SKalle Valo rxcb->err_code == HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO) { 3623d5c65159SKalle Valo if (!n_buffs) 3624d5c65159SKalle Valo break; 3625d5c65159SKalle Valo __skb_unlink(skb, msdu_list); 3626d5c65159SKalle Valo dev_kfree_skb_any(skb); 3627d5c65159SKalle Valo n_buffs--; 3628d5c65159SKalle Valo } 3629d5c65159SKalle Valo } 3630d5c65159SKalle Valo } 3631d5c65159SKalle Valo 3632d5c65159SKalle Valo static int ath11k_dp_rx_h_null_q_desc(struct ath11k *ar, struct sk_buff *msdu, 3633d5c65159SKalle Valo struct ieee80211_rx_status *status, 3634d5c65159SKalle Valo struct sk_buff_head *msdu_list) 3635d5c65159SKalle Valo { 3636d5c65159SKalle Valo u16 msdu_len; 3637d5c65159SKalle Valo struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data; 3638d5c65159SKalle Valo u8 l3pad_bytes; 3639d5c65159SKalle Valo struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); 3640d5c65159SKalle Valo 3641d5c65159SKalle Valo msdu_len = ath11k_dp_rx_h_msdu_start_msdu_len(desc); 3642d5c65159SKalle Valo 3643243874c6SManikanta Pubbisetty if (!rxcb->is_frag && ((msdu_len + HAL_RX_DESC_SIZE) > DP_RX_BUFFER_SIZE)) { 3644d5c65159SKalle Valo /* First buffer will be freed by the caller, so deduct it's length */ 3645d5c65159SKalle Valo msdu_len = msdu_len - (DP_RX_BUFFER_SIZE - HAL_RX_DESC_SIZE); 3646d5c65159SKalle Valo ath11k_dp_rx_null_q_desc_sg_drop(ar, msdu_len, msdu_list); 3647d5c65159SKalle Valo return -EINVAL; 3648d5c65159SKalle Valo } 3649d5c65159SKalle Valo 3650d5c65159SKalle Valo if (!ath11k_dp_rx_h_attn_msdu_done(desc)) { 3651d5c65159SKalle Valo ath11k_warn(ar->ab, 3652d5c65159SKalle Valo "msdu_done bit not set in null_q_des processing\n"); 3653d5c65159SKalle Valo __skb_queue_purge(msdu_list); 3654d5c65159SKalle Valo return -EIO; 3655d5c65159SKalle Valo } 3656d5c65159SKalle Valo 3657d5c65159SKalle Valo /* Handle NULL queue descriptor violations arising out a missing 3658d5c65159SKalle Valo * REO queue for a given peer or a given TID. This typically 3659d5c65159SKalle Valo * may happen if a packet is received on a QOS enabled TID before the 3660d5c65159SKalle Valo * ADDBA negotiation for that TID, when the TID queue is setup. Or 3661d5c65159SKalle Valo * it may also happen for MC/BC frames if they are not routed to the 3662d5c65159SKalle Valo * non-QOS TID queue, in the absence of any other default TID queue. 3663d5c65159SKalle Valo * This error can show up both in a REO destination or WBM release ring. 3664d5c65159SKalle Valo */ 3665d5c65159SKalle Valo 3666d5c65159SKalle Valo rxcb->is_first_msdu = ath11k_dp_rx_h_msdu_end_first_msdu(desc); 3667d5c65159SKalle Valo rxcb->is_last_msdu = ath11k_dp_rx_h_msdu_end_last_msdu(desc); 3668d5c65159SKalle Valo 3669243874c6SManikanta Pubbisetty if (rxcb->is_frag) { 3670243874c6SManikanta Pubbisetty skb_pull(msdu, HAL_RX_DESC_SIZE); 3671243874c6SManikanta Pubbisetty } else { 3672d5c65159SKalle Valo l3pad_bytes = ath11k_dp_rx_h_msdu_end_l3pad(desc); 3673d5c65159SKalle Valo 3674d5c65159SKalle Valo if ((HAL_RX_DESC_SIZE + l3pad_bytes + msdu_len) > DP_RX_BUFFER_SIZE) 3675d5c65159SKalle Valo return -EINVAL; 3676d5c65159SKalle Valo 3677d5c65159SKalle Valo skb_put(msdu, HAL_RX_DESC_SIZE + l3pad_bytes + msdu_len); 3678d5c65159SKalle Valo skb_pull(msdu, HAL_RX_DESC_SIZE + l3pad_bytes); 3679243874c6SManikanta Pubbisetty } 3680d5c65159SKalle Valo ath11k_dp_rx_h_ppdu(ar, desc, status); 3681d5c65159SKalle Valo 3682acc79d98SSriram R ath11k_dp_rx_h_mpdu(ar, msdu, desc, status); 3683d5c65159SKalle Valo 3684acc79d98SSriram R rxcb->tid = ath11k_dp_rx_h_mpdu_start_tid(desc); 3685d5c65159SKalle Valo 3686d5c65159SKalle Valo /* Please note that caller will having the access to msdu and completing 3687d5c65159SKalle Valo * rx with mac80211. Need not worry about cleaning up amsdu_list. 3688d5c65159SKalle Valo */ 3689d5c65159SKalle Valo 3690d5c65159SKalle Valo return 0; 3691d5c65159SKalle Valo } 3692d5c65159SKalle Valo 3693d5c65159SKalle Valo static bool ath11k_dp_rx_h_reo_err(struct ath11k *ar, struct sk_buff *msdu, 3694d5c65159SKalle Valo struct ieee80211_rx_status *status, 3695d5c65159SKalle Valo struct sk_buff_head *msdu_list) 3696d5c65159SKalle Valo { 3697d5c65159SKalle Valo struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); 3698d5c65159SKalle Valo bool drop = false; 3699d5c65159SKalle Valo 3700d5c65159SKalle Valo ar->ab->soc_stats.reo_error[rxcb->err_code]++; 3701d5c65159SKalle Valo 3702d5c65159SKalle Valo switch (rxcb->err_code) { 3703d5c65159SKalle Valo case HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO: 3704d5c65159SKalle Valo if (ath11k_dp_rx_h_null_q_desc(ar, msdu, status, msdu_list)) 3705d5c65159SKalle Valo drop = true; 3706d5c65159SKalle Valo break; 37071441b2f2SManikanta Pubbisetty case HAL_REO_DEST_RING_ERROR_CODE_PN_CHECK_FAILED: 37081441b2f2SManikanta Pubbisetty /* TODO: Do not drop PN failed packets in the driver; 37091441b2f2SManikanta Pubbisetty * instead, it is good to drop such packets in mac80211 37101441b2f2SManikanta Pubbisetty * after incrementing the replay counters. 37111441b2f2SManikanta Pubbisetty */ 37121441b2f2SManikanta Pubbisetty 37131441b2f2SManikanta Pubbisetty /* fall through */ 3714d5c65159SKalle Valo default: 3715d5c65159SKalle Valo /* TODO: Review other errors and process them to mac80211 3716d5c65159SKalle Valo * as appropriate. 3717d5c65159SKalle Valo */ 3718d5c65159SKalle Valo drop = true; 3719d5c65159SKalle Valo break; 3720d5c65159SKalle Valo } 3721d5c65159SKalle Valo 3722d5c65159SKalle Valo return drop; 3723d5c65159SKalle Valo } 3724d5c65159SKalle Valo 3725d5c65159SKalle Valo static void ath11k_dp_rx_h_tkip_mic_err(struct ath11k *ar, struct sk_buff *msdu, 3726d5c65159SKalle Valo struct ieee80211_rx_status *status) 3727d5c65159SKalle Valo { 3728d5c65159SKalle Valo u16 msdu_len; 3729d5c65159SKalle Valo struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data; 3730d5c65159SKalle Valo u8 l3pad_bytes; 3731d5c65159SKalle Valo struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); 3732d5c65159SKalle Valo 3733d5c65159SKalle Valo rxcb->is_first_msdu = ath11k_dp_rx_h_msdu_end_first_msdu(desc); 3734d5c65159SKalle Valo rxcb->is_last_msdu = ath11k_dp_rx_h_msdu_end_last_msdu(desc); 3735d5c65159SKalle Valo 3736d5c65159SKalle Valo l3pad_bytes = ath11k_dp_rx_h_msdu_end_l3pad(desc); 3737d5c65159SKalle Valo msdu_len = ath11k_dp_rx_h_msdu_start_msdu_len(desc); 3738d5c65159SKalle Valo skb_put(msdu, HAL_RX_DESC_SIZE + l3pad_bytes + msdu_len); 3739d5c65159SKalle Valo skb_pull(msdu, HAL_RX_DESC_SIZE + l3pad_bytes); 3740d5c65159SKalle Valo 3741d5c65159SKalle Valo ath11k_dp_rx_h_ppdu(ar, desc, status); 3742d5c65159SKalle Valo 3743d5c65159SKalle Valo status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR | 3744d5c65159SKalle Valo RX_FLAG_DECRYPTED); 3745d5c65159SKalle Valo 3746d5c65159SKalle Valo ath11k_dp_rx_h_undecap(ar, msdu, desc, 3747d5c65159SKalle Valo HAL_ENCRYPT_TYPE_TKIP_MIC, status, false); 3748d5c65159SKalle Valo } 3749d5c65159SKalle Valo 3750d5c65159SKalle Valo static bool ath11k_dp_rx_h_rxdma_err(struct ath11k *ar, struct sk_buff *msdu, 3751d5c65159SKalle Valo struct ieee80211_rx_status *status) 3752d5c65159SKalle Valo { 3753d5c65159SKalle Valo struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); 3754d5c65159SKalle Valo bool drop = false; 3755d5c65159SKalle Valo 3756d5c65159SKalle Valo ar->ab->soc_stats.rxdma_error[rxcb->err_code]++; 3757d5c65159SKalle Valo 3758d5c65159SKalle Valo switch (rxcb->err_code) { 3759d5c65159SKalle Valo case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR: 3760d5c65159SKalle Valo ath11k_dp_rx_h_tkip_mic_err(ar, msdu, status); 3761d5c65159SKalle Valo break; 3762d5c65159SKalle Valo default: 3763d5c65159SKalle Valo /* TODO: Review other rxdma error code to check if anything is 3764d5c65159SKalle Valo * worth reporting to mac80211 3765d5c65159SKalle Valo */ 3766d5c65159SKalle Valo drop = true; 3767d5c65159SKalle Valo break; 3768d5c65159SKalle Valo } 3769d5c65159SKalle Valo 3770d5c65159SKalle Valo return drop; 3771d5c65159SKalle Valo } 3772d5c65159SKalle Valo 3773d5c65159SKalle Valo static void ath11k_dp_rx_wbm_err(struct ath11k *ar, 3774d5c65159SKalle Valo struct napi_struct *napi, 3775d5c65159SKalle Valo struct sk_buff *msdu, 3776d5c65159SKalle Valo struct sk_buff_head *msdu_list) 3777d5c65159SKalle Valo { 3778d5c65159SKalle Valo struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); 3779d5c65159SKalle Valo struct ieee80211_rx_status rxs = {0}; 3780d5c65159SKalle Valo struct ieee80211_rx_status *status; 3781d5c65159SKalle Valo bool drop = true; 3782d5c65159SKalle Valo 3783d5c65159SKalle Valo switch (rxcb->err_rel_src) { 3784d5c65159SKalle Valo case HAL_WBM_REL_SRC_MODULE_REO: 3785d5c65159SKalle Valo drop = ath11k_dp_rx_h_reo_err(ar, msdu, &rxs, msdu_list); 3786d5c65159SKalle Valo break; 3787d5c65159SKalle Valo case HAL_WBM_REL_SRC_MODULE_RXDMA: 3788d5c65159SKalle Valo drop = ath11k_dp_rx_h_rxdma_err(ar, msdu, &rxs); 3789d5c65159SKalle Valo break; 3790d5c65159SKalle Valo default: 3791d5c65159SKalle Valo /* msdu will get freed */ 3792d5c65159SKalle Valo break; 3793d5c65159SKalle Valo } 3794d5c65159SKalle Valo 3795d5c65159SKalle Valo if (drop) { 3796d5c65159SKalle Valo dev_kfree_skb_any(msdu); 3797d5c65159SKalle Valo return; 3798d5c65159SKalle Valo } 3799d5c65159SKalle Valo 3800d5c65159SKalle Valo status = IEEE80211_SKB_RXCB(msdu); 3801d5c65159SKalle Valo *status = rxs; 3802d5c65159SKalle Valo 3803d5c65159SKalle Valo ath11k_dp_rx_deliver_msdu(ar, napi, msdu); 3804d5c65159SKalle Valo } 3805d5c65159SKalle Valo 3806d5c65159SKalle Valo int ath11k_dp_rx_process_wbm_err(struct ath11k_base *ab, 3807d5c65159SKalle Valo struct napi_struct *napi, int budget) 3808d5c65159SKalle Valo { 3809d5c65159SKalle Valo struct ath11k *ar; 3810d5c65159SKalle Valo struct ath11k_dp *dp = &ab->dp; 3811d5c65159SKalle Valo struct dp_rxdma_ring *rx_ring; 3812d5c65159SKalle Valo struct hal_rx_wbm_rel_info err_info; 3813d5c65159SKalle Valo struct hal_srng *srng; 3814d5c65159SKalle Valo struct sk_buff *msdu; 3815d5c65159SKalle Valo struct sk_buff_head msdu_list[MAX_RADIOS]; 3816d5c65159SKalle Valo struct ath11k_skb_rxcb *rxcb; 3817d5c65159SKalle Valo u32 *rx_desc; 3818d5c65159SKalle Valo int buf_id, mac_id; 3819d5c65159SKalle Valo int num_buffs_reaped[MAX_RADIOS] = {0}; 3820d5c65159SKalle Valo int total_num_buffs_reaped = 0; 3821d5c65159SKalle Valo int ret, i; 3822d5c65159SKalle Valo 3823b1cc29e9SAnilkumar Kolli for (i = 0; i < ab->num_radios; i++) 3824d5c65159SKalle Valo __skb_queue_head_init(&msdu_list[i]); 3825d5c65159SKalle Valo 3826d5c65159SKalle Valo srng = &ab->hal.srng_list[dp->rx_rel_ring.ring_id]; 3827d5c65159SKalle Valo 3828d5c65159SKalle Valo spin_lock_bh(&srng->lock); 3829d5c65159SKalle Valo 3830d5c65159SKalle Valo ath11k_hal_srng_access_begin(ab, srng); 3831d5c65159SKalle Valo 3832d5c65159SKalle Valo while (budget) { 3833d5c65159SKalle Valo rx_desc = ath11k_hal_srng_dst_get_next_entry(ab, srng); 3834d5c65159SKalle Valo if (!rx_desc) 3835d5c65159SKalle Valo break; 3836d5c65159SKalle Valo 3837d5c65159SKalle Valo ret = ath11k_hal_wbm_desc_parse_err(ab, rx_desc, &err_info); 3838d5c65159SKalle Valo if (ret) { 3839d5c65159SKalle Valo ath11k_warn(ab, 3840d5c65159SKalle Valo "failed to parse rx error in wbm_rel ring desc %d\n", 3841d5c65159SKalle Valo ret); 3842d5c65159SKalle Valo continue; 3843d5c65159SKalle Valo } 3844d5c65159SKalle Valo 3845d5c65159SKalle Valo buf_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_BUF_ID, err_info.cookie); 3846d5c65159SKalle Valo mac_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_PDEV_ID, err_info.cookie); 3847d5c65159SKalle Valo 3848d5c65159SKalle Valo ar = ab->pdevs[mac_id].ar; 3849d5c65159SKalle Valo rx_ring = &ar->dp.rx_refill_buf_ring; 3850d5c65159SKalle Valo 3851d5c65159SKalle Valo spin_lock_bh(&rx_ring->idr_lock); 3852d5c65159SKalle Valo msdu = idr_find(&rx_ring->bufs_idr, buf_id); 3853d5c65159SKalle Valo if (!msdu) { 3854d5c65159SKalle Valo ath11k_warn(ab, "frame rx with invalid buf_id %d pdev %d\n", 3855d5c65159SKalle Valo buf_id, mac_id); 3856d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 3857d5c65159SKalle Valo continue; 3858d5c65159SKalle Valo } 3859d5c65159SKalle Valo 3860d5c65159SKalle Valo idr_remove(&rx_ring->bufs_idr, buf_id); 3861d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 3862d5c65159SKalle Valo 3863d5c65159SKalle Valo rxcb = ATH11K_SKB_RXCB(msdu); 3864d5c65159SKalle Valo dma_unmap_single(ab->dev, rxcb->paddr, 3865d5c65159SKalle Valo msdu->len + skb_tailroom(msdu), 3866d5c65159SKalle Valo DMA_FROM_DEVICE); 3867d5c65159SKalle Valo 3868d5c65159SKalle Valo num_buffs_reaped[mac_id]++; 3869d5c65159SKalle Valo total_num_buffs_reaped++; 3870d5c65159SKalle Valo budget--; 3871d5c65159SKalle Valo 3872d5c65159SKalle Valo if (err_info.push_reason != 3873d5c65159SKalle Valo HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED) { 3874d5c65159SKalle Valo dev_kfree_skb_any(msdu); 3875d5c65159SKalle Valo continue; 3876d5c65159SKalle Valo } 3877d5c65159SKalle Valo 3878d5c65159SKalle Valo rxcb->err_rel_src = err_info.err_rel_src; 3879d5c65159SKalle Valo rxcb->err_code = err_info.err_code; 3880d5c65159SKalle Valo rxcb->rx_desc = (struct hal_rx_desc *)msdu->data; 3881d5c65159SKalle Valo __skb_queue_tail(&msdu_list[mac_id], msdu); 3882d5c65159SKalle Valo } 3883d5c65159SKalle Valo 3884d5c65159SKalle Valo ath11k_hal_srng_access_end(ab, srng); 3885d5c65159SKalle Valo 3886d5c65159SKalle Valo spin_unlock_bh(&srng->lock); 3887d5c65159SKalle Valo 3888d5c65159SKalle Valo if (!total_num_buffs_reaped) 3889d5c65159SKalle Valo goto done; 3890d5c65159SKalle Valo 3891d5c65159SKalle Valo for (i = 0; i < ab->num_radios; i++) { 3892d5c65159SKalle Valo if (!num_buffs_reaped[i]) 3893d5c65159SKalle Valo continue; 3894d5c65159SKalle Valo 3895d5c65159SKalle Valo ar = ab->pdevs[i].ar; 3896d5c65159SKalle Valo rx_ring = &ar->dp.rx_refill_buf_ring; 3897d5c65159SKalle Valo 3898d5c65159SKalle Valo ath11k_dp_rxbufs_replenish(ab, i, rx_ring, num_buffs_reaped[i], 3899d5c65159SKalle Valo HAL_RX_BUF_RBM_SW3_BM, GFP_ATOMIC); 3900d5c65159SKalle Valo } 3901d5c65159SKalle Valo 3902d5c65159SKalle Valo rcu_read_lock(); 3903d5c65159SKalle Valo for (i = 0; i < ab->num_radios; i++) { 3904d5c65159SKalle Valo if (!rcu_dereference(ab->pdevs_active[i])) { 3905d5c65159SKalle Valo __skb_queue_purge(&msdu_list[i]); 3906d5c65159SKalle Valo continue; 3907d5c65159SKalle Valo } 3908d5c65159SKalle Valo 3909d5c65159SKalle Valo ar = ab->pdevs[i].ar; 3910d5c65159SKalle Valo 3911d5c65159SKalle Valo if (test_bit(ATH11K_CAC_RUNNING, &ar->dev_flags)) { 3912d5c65159SKalle Valo __skb_queue_purge(&msdu_list[i]); 3913d5c65159SKalle Valo continue; 3914d5c65159SKalle Valo } 3915d5c65159SKalle Valo 3916d5c65159SKalle Valo while ((msdu = __skb_dequeue(&msdu_list[i])) != NULL) 3917d5c65159SKalle Valo ath11k_dp_rx_wbm_err(ar, napi, msdu, &msdu_list[i]); 3918d5c65159SKalle Valo } 3919d5c65159SKalle Valo rcu_read_unlock(); 3920d5c65159SKalle Valo done: 3921d5c65159SKalle Valo return total_num_buffs_reaped; 3922d5c65159SKalle Valo } 3923d5c65159SKalle Valo 3924d5c65159SKalle Valo int ath11k_dp_process_rxdma_err(struct ath11k_base *ab, int mac_id, int budget) 3925d5c65159SKalle Valo { 3926d5c65159SKalle Valo struct ath11k *ar = ab->pdevs[mac_id].ar; 3927d5c65159SKalle Valo struct dp_srng *err_ring = &ar->dp.rxdma_err_dst_ring; 3928d5c65159SKalle Valo struct dp_rxdma_ring *rx_ring = &ar->dp.rx_refill_buf_ring; 3929d5c65159SKalle Valo struct dp_link_desc_bank *link_desc_banks = ab->dp.link_desc_banks; 3930d5c65159SKalle Valo struct hal_srng *srng; 3931293cb583SJohn Crispin u32 msdu_cookies[HAL_NUM_RX_MSDUS_PER_LINK_DESC]; 3932d5c65159SKalle Valo enum hal_rx_buf_return_buf_manager rbm; 3933d5c65159SKalle Valo enum hal_reo_entr_rxdma_ecode rxdma_err_code; 3934d5c65159SKalle Valo struct ath11k_skb_rxcb *rxcb; 3935d5c65159SKalle Valo struct sk_buff *skb; 3936d5c65159SKalle Valo struct hal_reo_entrance_ring *entr_ring; 3937d5c65159SKalle Valo void *desc; 3938d5c65159SKalle Valo int num_buf_freed = 0; 3939d5c65159SKalle Valo int quota = budget; 3940d5c65159SKalle Valo dma_addr_t paddr; 3941d5c65159SKalle Valo u32 desc_bank; 3942d5c65159SKalle Valo void *link_desc_va; 3943d5c65159SKalle Valo int num_msdus; 3944d5c65159SKalle Valo int i; 3945d5c65159SKalle Valo int buf_id; 3946d5c65159SKalle Valo 3947d5c65159SKalle Valo srng = &ab->hal.srng_list[err_ring->ring_id]; 3948d5c65159SKalle Valo 3949d5c65159SKalle Valo spin_lock_bh(&srng->lock); 3950d5c65159SKalle Valo 3951d5c65159SKalle Valo ath11k_hal_srng_access_begin(ab, srng); 3952d5c65159SKalle Valo 3953d5c65159SKalle Valo while (quota-- && 3954d5c65159SKalle Valo (desc = ath11k_hal_srng_dst_get_next_entry(ab, srng))) { 3955d5c65159SKalle Valo ath11k_hal_rx_reo_ent_paddr_get(ab, desc, &paddr, &desc_bank); 3956d5c65159SKalle Valo 3957d5c65159SKalle Valo entr_ring = (struct hal_reo_entrance_ring *)desc; 3958d5c65159SKalle Valo rxdma_err_code = 3959d5c65159SKalle Valo FIELD_GET(HAL_REO_ENTR_RING_INFO1_RXDMA_ERROR_CODE, 3960d5c65159SKalle Valo entr_ring->info1); 3961d5c65159SKalle Valo ab->soc_stats.rxdma_error[rxdma_err_code]++; 3962d5c65159SKalle Valo 3963d5c65159SKalle Valo link_desc_va = link_desc_banks[desc_bank].vaddr + 3964d5c65159SKalle Valo (paddr - link_desc_banks[desc_bank].paddr); 3965293cb583SJohn Crispin ath11k_hal_rx_msdu_link_info_get(link_desc_va, &num_msdus, 3966293cb583SJohn Crispin msdu_cookies, &rbm); 3967d5c65159SKalle Valo 3968d5c65159SKalle Valo for (i = 0; i < num_msdus; i++) { 3969d5c65159SKalle Valo buf_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_BUF_ID, 3970293cb583SJohn Crispin msdu_cookies[i]); 3971d5c65159SKalle Valo 3972d5c65159SKalle Valo spin_lock_bh(&rx_ring->idr_lock); 3973d5c65159SKalle Valo skb = idr_find(&rx_ring->bufs_idr, buf_id); 3974d5c65159SKalle Valo if (!skb) { 3975d5c65159SKalle Valo ath11k_warn(ab, "rxdma error with invalid buf_id %d\n", 3976d5c65159SKalle Valo buf_id); 3977d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 3978d5c65159SKalle Valo continue; 3979d5c65159SKalle Valo } 3980d5c65159SKalle Valo 3981d5c65159SKalle Valo idr_remove(&rx_ring->bufs_idr, buf_id); 3982d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 3983d5c65159SKalle Valo 3984d5c65159SKalle Valo rxcb = ATH11K_SKB_RXCB(skb); 3985d5c65159SKalle Valo dma_unmap_single(ab->dev, rxcb->paddr, 3986d5c65159SKalle Valo skb->len + skb_tailroom(skb), 3987d5c65159SKalle Valo DMA_FROM_DEVICE); 3988d5c65159SKalle Valo dev_kfree_skb_any(skb); 3989d5c65159SKalle Valo 3990d5c65159SKalle Valo num_buf_freed++; 3991d5c65159SKalle Valo } 3992d5c65159SKalle Valo 3993d5c65159SKalle Valo ath11k_dp_rx_link_desc_return(ab, desc, 3994d5c65159SKalle Valo HAL_WBM_REL_BM_ACT_PUT_IN_IDLE); 3995d5c65159SKalle Valo } 3996d5c65159SKalle Valo 3997d5c65159SKalle Valo ath11k_hal_srng_access_end(ab, srng); 3998d5c65159SKalle Valo 3999d5c65159SKalle Valo spin_unlock_bh(&srng->lock); 4000d5c65159SKalle Valo 4001d5c65159SKalle Valo if (num_buf_freed) 4002d5c65159SKalle Valo ath11k_dp_rxbufs_replenish(ab, mac_id, rx_ring, num_buf_freed, 4003d5c65159SKalle Valo HAL_RX_BUF_RBM_SW3_BM, GFP_ATOMIC); 4004d5c65159SKalle Valo 4005d5c65159SKalle Valo return budget - quota; 4006d5c65159SKalle Valo } 4007d5c65159SKalle Valo 4008d5c65159SKalle Valo void ath11k_dp_process_reo_status(struct ath11k_base *ab) 4009d5c65159SKalle Valo { 4010d5c65159SKalle Valo struct ath11k_dp *dp = &ab->dp; 4011d5c65159SKalle Valo struct hal_srng *srng; 4012d5c65159SKalle Valo struct dp_reo_cmd *cmd, *tmp; 4013d5c65159SKalle Valo bool found = false; 4014d5c65159SKalle Valo u32 *reo_desc; 4015d5c65159SKalle Valo u16 tag; 4016d5c65159SKalle Valo struct hal_reo_status reo_status; 4017d5c65159SKalle Valo 4018d5c65159SKalle Valo srng = &ab->hal.srng_list[dp->reo_status_ring.ring_id]; 4019d5c65159SKalle Valo 4020d5c65159SKalle Valo memset(&reo_status, 0, sizeof(reo_status)); 4021d5c65159SKalle Valo 4022d5c65159SKalle Valo spin_lock_bh(&srng->lock); 4023d5c65159SKalle Valo 4024d5c65159SKalle Valo ath11k_hal_srng_access_begin(ab, srng); 4025d5c65159SKalle Valo 4026d5c65159SKalle Valo while ((reo_desc = ath11k_hal_srng_dst_get_next_entry(ab, srng))) { 4027d5c65159SKalle Valo tag = FIELD_GET(HAL_SRNG_TLV_HDR_TAG, *reo_desc); 4028d5c65159SKalle Valo 4029d5c65159SKalle Valo switch (tag) { 4030d5c65159SKalle Valo case HAL_REO_GET_QUEUE_STATS_STATUS: 4031d5c65159SKalle Valo ath11k_hal_reo_status_queue_stats(ab, reo_desc, 4032d5c65159SKalle Valo &reo_status); 4033d5c65159SKalle Valo break; 4034d5c65159SKalle Valo case HAL_REO_FLUSH_QUEUE_STATUS: 4035d5c65159SKalle Valo ath11k_hal_reo_flush_queue_status(ab, reo_desc, 4036d5c65159SKalle Valo &reo_status); 4037d5c65159SKalle Valo break; 4038d5c65159SKalle Valo case HAL_REO_FLUSH_CACHE_STATUS: 4039d5c65159SKalle Valo ath11k_hal_reo_flush_cache_status(ab, reo_desc, 4040d5c65159SKalle Valo &reo_status); 4041d5c65159SKalle Valo break; 4042d5c65159SKalle Valo case HAL_REO_UNBLOCK_CACHE_STATUS: 4043d5c65159SKalle Valo ath11k_hal_reo_unblk_cache_status(ab, reo_desc, 4044d5c65159SKalle Valo &reo_status); 4045d5c65159SKalle Valo break; 4046d5c65159SKalle Valo case HAL_REO_FLUSH_TIMEOUT_LIST_STATUS: 4047d5c65159SKalle Valo ath11k_hal_reo_flush_timeout_list_status(ab, reo_desc, 4048d5c65159SKalle Valo &reo_status); 4049d5c65159SKalle Valo break; 4050d5c65159SKalle Valo case HAL_REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS: 4051d5c65159SKalle Valo ath11k_hal_reo_desc_thresh_reached_status(ab, reo_desc, 4052d5c65159SKalle Valo &reo_status); 4053d5c65159SKalle Valo break; 4054d5c65159SKalle Valo case HAL_REO_UPDATE_RX_REO_QUEUE_STATUS: 4055d5c65159SKalle Valo ath11k_hal_reo_update_rx_reo_queue_status(ab, reo_desc, 4056d5c65159SKalle Valo &reo_status); 4057d5c65159SKalle Valo break; 4058d5c65159SKalle Valo default: 4059d5c65159SKalle Valo ath11k_warn(ab, "Unknown reo status type %d\n", tag); 4060d5c65159SKalle Valo continue; 4061d5c65159SKalle Valo } 4062d5c65159SKalle Valo 4063d5c65159SKalle Valo spin_lock_bh(&dp->reo_cmd_lock); 4064d5c65159SKalle Valo list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) { 4065d5c65159SKalle Valo if (reo_status.uniform_hdr.cmd_num == cmd->cmd_num) { 4066d5c65159SKalle Valo found = true; 4067d5c65159SKalle Valo list_del(&cmd->list); 4068d5c65159SKalle Valo break; 4069d5c65159SKalle Valo } 4070d5c65159SKalle Valo } 4071d5c65159SKalle Valo spin_unlock_bh(&dp->reo_cmd_lock); 4072d5c65159SKalle Valo 4073d5c65159SKalle Valo if (found) { 4074d5c65159SKalle Valo cmd->handler(dp, (void *)&cmd->data, 4075d5c65159SKalle Valo reo_status.uniform_hdr.cmd_status); 4076d5c65159SKalle Valo kfree(cmd); 4077d5c65159SKalle Valo } 4078d5c65159SKalle Valo 4079d5c65159SKalle Valo found = false; 4080d5c65159SKalle Valo } 4081d5c65159SKalle Valo 4082d5c65159SKalle Valo ath11k_hal_srng_access_end(ab, srng); 4083d5c65159SKalle Valo 4084d5c65159SKalle Valo spin_unlock_bh(&srng->lock); 4085d5c65159SKalle Valo } 4086d5c65159SKalle Valo 4087d5c65159SKalle Valo void ath11k_dp_rx_pdev_free(struct ath11k_base *ab, int mac_id) 4088d5c65159SKalle Valo { 4089d5c65159SKalle Valo struct ath11k *ar = ab->pdevs[mac_id].ar; 4090d5c65159SKalle Valo 4091d5c65159SKalle Valo ath11k_dp_rx_pdev_srng_free(ar); 4092d5c65159SKalle Valo ath11k_dp_rxdma_pdev_buf_free(ar); 4093d5c65159SKalle Valo } 4094d5c65159SKalle Valo 4095d5c65159SKalle Valo int ath11k_dp_rx_pdev_alloc(struct ath11k_base *ab, int mac_id) 4096d5c65159SKalle Valo { 4097d5c65159SKalle Valo struct ath11k *ar = ab->pdevs[mac_id].ar; 4098d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 4099d5c65159SKalle Valo u32 ring_id; 4100d5c65159SKalle Valo int ret; 4101d5c65159SKalle Valo 4102d5c65159SKalle Valo ret = ath11k_dp_rx_pdev_srng_alloc(ar); 4103d5c65159SKalle Valo if (ret) { 4104d5c65159SKalle Valo ath11k_warn(ab, "failed to setup rx srngs\n"); 4105d5c65159SKalle Valo return ret; 4106d5c65159SKalle Valo } 4107d5c65159SKalle Valo 4108d5c65159SKalle Valo ret = ath11k_dp_rxdma_pdev_buf_setup(ar); 4109d5c65159SKalle Valo if (ret) { 4110d5c65159SKalle Valo ath11k_warn(ab, "failed to setup rxdma ring\n"); 4111d5c65159SKalle Valo return ret; 4112d5c65159SKalle Valo } 4113d5c65159SKalle Valo 4114d5c65159SKalle Valo ring_id = dp->rx_refill_buf_ring.refill_buf_ring.ring_id; 4115d5c65159SKalle Valo ret = ath11k_dp_tx_htt_srng_setup(ab, ring_id, mac_id, HAL_RXDMA_BUF); 4116d5c65159SKalle Valo if (ret) { 4117d5c65159SKalle Valo ath11k_warn(ab, "failed to configure rx_refill_buf_ring %d\n", 4118d5c65159SKalle Valo ret); 4119d5c65159SKalle Valo return ret; 4120d5c65159SKalle Valo } 4121d5c65159SKalle Valo 4122d5c65159SKalle Valo ring_id = dp->rxdma_err_dst_ring.ring_id; 4123d5c65159SKalle Valo ret = ath11k_dp_tx_htt_srng_setup(ab, ring_id, mac_id, HAL_RXDMA_DST); 4124d5c65159SKalle Valo if (ret) { 4125d5c65159SKalle Valo ath11k_warn(ab, "failed to configure rxdma_err_dest_ring %d\n", 4126d5c65159SKalle Valo ret); 4127d5c65159SKalle Valo return ret; 4128d5c65159SKalle Valo } 4129d5c65159SKalle Valo 4130d5c65159SKalle Valo ring_id = dp->rxdma_mon_buf_ring.refill_buf_ring.ring_id; 4131d5c65159SKalle Valo ret = ath11k_dp_tx_htt_srng_setup(ab, ring_id, 4132d5c65159SKalle Valo mac_id, HAL_RXDMA_MONITOR_BUF); 4133d5c65159SKalle Valo if (ret) { 4134d5c65159SKalle Valo ath11k_warn(ab, "failed to configure rxdma_mon_buf_ring %d\n", 4135d5c65159SKalle Valo ret); 4136d5c65159SKalle Valo return ret; 4137d5c65159SKalle Valo } 4138d5c65159SKalle Valo ret = ath11k_dp_tx_htt_srng_setup(ab, 4139d5c65159SKalle Valo dp->rxdma_mon_dst_ring.ring_id, 4140d5c65159SKalle Valo mac_id, HAL_RXDMA_MONITOR_DST); 4141d5c65159SKalle Valo if (ret) { 4142d5c65159SKalle Valo ath11k_warn(ab, "failed to configure rxdma_mon_dst_ring %d\n", 4143d5c65159SKalle Valo ret); 4144d5c65159SKalle Valo return ret; 4145d5c65159SKalle Valo } 4146d5c65159SKalle Valo ret = ath11k_dp_tx_htt_srng_setup(ab, 4147d5c65159SKalle Valo dp->rxdma_mon_desc_ring.ring_id, 4148d5c65159SKalle Valo mac_id, HAL_RXDMA_MONITOR_DESC); 4149d5c65159SKalle Valo if (ret) { 4150d5c65159SKalle Valo ath11k_warn(ab, "failed to configure rxdma_mon_dst_ring %d\n", 4151d5c65159SKalle Valo ret); 4152d5c65159SKalle Valo return ret; 4153d5c65159SKalle Valo } 4154d5c65159SKalle Valo ring_id = dp->rx_mon_status_refill_ring.refill_buf_ring.ring_id; 4155d5c65159SKalle Valo ret = ath11k_dp_tx_htt_srng_setup(ab, ring_id, mac_id, 4156d5c65159SKalle Valo HAL_RXDMA_MONITOR_STATUS); 4157d5c65159SKalle Valo if (ret) { 4158d5c65159SKalle Valo ath11k_warn(ab, 4159d5c65159SKalle Valo "failed to configure mon_status_refill_ring %d\n", 4160d5c65159SKalle Valo ret); 4161d5c65159SKalle Valo return ret; 4162d5c65159SKalle Valo } 4163d5c65159SKalle Valo return 0; 4164d5c65159SKalle Valo } 4165d5c65159SKalle Valo 4166d5c65159SKalle Valo static void ath11k_dp_mon_set_frag_len(u32 *total_len, u32 *frag_len) 4167d5c65159SKalle Valo { 4168d5c65159SKalle Valo if (*total_len >= (DP_RX_BUFFER_SIZE - sizeof(struct hal_rx_desc))) { 4169d5c65159SKalle Valo *frag_len = DP_RX_BUFFER_SIZE - sizeof(struct hal_rx_desc); 4170d5c65159SKalle Valo *total_len -= *frag_len; 4171d5c65159SKalle Valo } else { 4172d5c65159SKalle Valo *frag_len = *total_len; 4173d5c65159SKalle Valo *total_len = 0; 4174d5c65159SKalle Valo } 4175d5c65159SKalle Valo } 4176d5c65159SKalle Valo 4177d5c65159SKalle Valo static 4178d5c65159SKalle Valo int ath11k_dp_rx_monitor_link_desc_return(struct ath11k *ar, 4179d5c65159SKalle Valo void *p_last_buf_addr_info, 4180d5c65159SKalle Valo u8 mac_id) 4181d5c65159SKalle Valo { 4182d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 4183d5c65159SKalle Valo struct dp_srng *dp_srng; 4184d5c65159SKalle Valo void *hal_srng; 4185d5c65159SKalle Valo void *src_srng_desc; 4186d5c65159SKalle Valo int ret = 0; 4187d5c65159SKalle Valo 4188d5c65159SKalle Valo dp_srng = &dp->rxdma_mon_desc_ring; 4189d5c65159SKalle Valo hal_srng = &ar->ab->hal.srng_list[dp_srng->ring_id]; 4190d5c65159SKalle Valo 4191d5c65159SKalle Valo ath11k_hal_srng_access_begin(ar->ab, hal_srng); 4192d5c65159SKalle Valo 4193d5c65159SKalle Valo src_srng_desc = ath11k_hal_srng_src_get_next_entry(ar->ab, hal_srng); 4194d5c65159SKalle Valo 4195d5c65159SKalle Valo if (src_srng_desc) { 4196d5c65159SKalle Valo struct ath11k_buffer_addr *src_desc = 4197d5c65159SKalle Valo (struct ath11k_buffer_addr *)src_srng_desc; 4198d5c65159SKalle Valo 4199d5c65159SKalle Valo *src_desc = *((struct ath11k_buffer_addr *)p_last_buf_addr_info); 4200d5c65159SKalle Valo } else { 4201d5c65159SKalle Valo ath11k_dbg(ar->ab, ATH11K_DBG_DATA, 4202d5c65159SKalle Valo "Monitor Link Desc Ring %d Full", mac_id); 4203d5c65159SKalle Valo ret = -ENOMEM; 4204d5c65159SKalle Valo } 4205d5c65159SKalle Valo 4206d5c65159SKalle Valo ath11k_hal_srng_access_end(ar->ab, hal_srng); 4207d5c65159SKalle Valo return ret; 4208d5c65159SKalle Valo } 4209d5c65159SKalle Valo 4210d5c65159SKalle Valo static 4211d5c65159SKalle Valo void ath11k_dp_rx_mon_next_link_desc_get(void *rx_msdu_link_desc, 4212d5c65159SKalle Valo dma_addr_t *paddr, u32 *sw_cookie, 4213d5c65159SKalle Valo void **pp_buf_addr_info) 4214d5c65159SKalle Valo { 4215d5c65159SKalle Valo struct hal_rx_msdu_link *msdu_link = 4216d5c65159SKalle Valo (struct hal_rx_msdu_link *)rx_msdu_link_desc; 4217d5c65159SKalle Valo struct ath11k_buffer_addr *buf_addr_info; 4218d5c65159SKalle Valo u8 rbm = 0; 4219d5c65159SKalle Valo 4220d5c65159SKalle Valo buf_addr_info = (struct ath11k_buffer_addr *)&msdu_link->buf_addr_info; 4221d5c65159SKalle Valo 4222d5c65159SKalle Valo ath11k_hal_rx_buf_addr_info_get(buf_addr_info, paddr, sw_cookie, &rbm); 4223d5c65159SKalle Valo 4224d5c65159SKalle Valo *pp_buf_addr_info = (void *)buf_addr_info; 4225d5c65159SKalle Valo } 4226d5c65159SKalle Valo 4227d5c65159SKalle Valo static int ath11k_dp_pkt_set_pktlen(struct sk_buff *skb, u32 len) 4228d5c65159SKalle Valo { 4229d5c65159SKalle Valo if (skb->len > len) { 4230d5c65159SKalle Valo skb_trim(skb, len); 4231d5c65159SKalle Valo } else { 4232d5c65159SKalle Valo if (skb_tailroom(skb) < len - skb->len) { 4233d5c65159SKalle Valo if ((pskb_expand_head(skb, 0, 4234d5c65159SKalle Valo len - skb->len - skb_tailroom(skb), 4235d5c65159SKalle Valo GFP_ATOMIC))) { 4236d5c65159SKalle Valo dev_kfree_skb_any(skb); 4237d5c65159SKalle Valo return -ENOMEM; 4238d5c65159SKalle Valo } 4239d5c65159SKalle Valo } 4240d5c65159SKalle Valo skb_put(skb, (len - skb->len)); 4241d5c65159SKalle Valo } 4242d5c65159SKalle Valo return 0; 4243d5c65159SKalle Valo } 4244d5c65159SKalle Valo 4245d5c65159SKalle Valo static void ath11k_hal_rx_msdu_list_get(struct ath11k *ar, 4246d5c65159SKalle Valo void *msdu_link_desc, 4247d5c65159SKalle Valo struct hal_rx_msdu_list *msdu_list, 4248d5c65159SKalle Valo u16 *num_msdus) 4249d5c65159SKalle Valo { 4250d5c65159SKalle Valo struct hal_rx_msdu_details *msdu_details = NULL; 4251d5c65159SKalle Valo struct rx_msdu_desc *msdu_desc_info = NULL; 4252d5c65159SKalle Valo struct hal_rx_msdu_link *msdu_link = NULL; 4253d5c65159SKalle Valo int i; 4254d5c65159SKalle Valo u32 last = FIELD_PREP(RX_MSDU_DESC_INFO0_LAST_MSDU_IN_MPDU, 1); 4255d5c65159SKalle Valo u32 first = FIELD_PREP(RX_MSDU_DESC_INFO0_FIRST_MSDU_IN_MPDU, 1); 4256d5c65159SKalle Valo u8 tmp = 0; 4257d5c65159SKalle Valo 4258d5c65159SKalle Valo msdu_link = (struct hal_rx_msdu_link *)msdu_link_desc; 4259d5c65159SKalle Valo msdu_details = &msdu_link->msdu_link[0]; 4260d5c65159SKalle Valo 4261d5c65159SKalle Valo for (i = 0; i < HAL_RX_NUM_MSDU_DESC; i++) { 4262d5c65159SKalle Valo if (FIELD_GET(BUFFER_ADDR_INFO0_ADDR, 4263d5c65159SKalle Valo msdu_details[i].buf_addr_info.info0) == 0) { 4264d5c65159SKalle Valo msdu_desc_info = &msdu_details[i - 1].rx_msdu_info; 4265d5c65159SKalle Valo msdu_desc_info->info0 |= last; 4266d5c65159SKalle Valo ; 4267d5c65159SKalle Valo break; 4268d5c65159SKalle Valo } 4269d5c65159SKalle Valo msdu_desc_info = &msdu_details[i].rx_msdu_info; 4270d5c65159SKalle Valo 4271d5c65159SKalle Valo if (!i) 4272d5c65159SKalle Valo msdu_desc_info->info0 |= first; 4273d5c65159SKalle Valo else if (i == (HAL_RX_NUM_MSDU_DESC - 1)) 4274d5c65159SKalle Valo msdu_desc_info->info0 |= last; 4275d5c65159SKalle Valo msdu_list->msdu_info[i].msdu_flags = msdu_desc_info->info0; 4276d5c65159SKalle Valo msdu_list->msdu_info[i].msdu_len = 4277d5c65159SKalle Valo HAL_RX_MSDU_PKT_LENGTH_GET(msdu_desc_info->info0); 4278d5c65159SKalle Valo msdu_list->sw_cookie[i] = 4279d5c65159SKalle Valo FIELD_GET(BUFFER_ADDR_INFO1_SW_COOKIE, 4280d5c65159SKalle Valo msdu_details[i].buf_addr_info.info1); 4281d5c65159SKalle Valo tmp = FIELD_GET(BUFFER_ADDR_INFO1_RET_BUF_MGR, 4282d5c65159SKalle Valo msdu_details[i].buf_addr_info.info1); 4283d5c65159SKalle Valo msdu_list->rbm[i] = tmp; 4284d5c65159SKalle Valo } 4285d5c65159SKalle Valo *num_msdus = i; 4286d5c65159SKalle Valo } 4287d5c65159SKalle Valo 4288d5c65159SKalle Valo static u32 ath11k_dp_rx_mon_comp_ppduid(u32 msdu_ppdu_id, u32 *ppdu_id, 4289d5c65159SKalle Valo u32 *rx_bufs_used) 4290d5c65159SKalle Valo { 4291d5c65159SKalle Valo u32 ret = 0; 4292d5c65159SKalle Valo 4293d5c65159SKalle Valo if ((*ppdu_id < msdu_ppdu_id) && 4294d5c65159SKalle Valo ((msdu_ppdu_id - *ppdu_id) < DP_NOT_PPDU_ID_WRAP_AROUND)) { 4295d5c65159SKalle Valo *ppdu_id = msdu_ppdu_id; 4296d5c65159SKalle Valo ret = msdu_ppdu_id; 4297d5c65159SKalle Valo } else if ((*ppdu_id > msdu_ppdu_id) && 4298d5c65159SKalle Valo ((*ppdu_id - msdu_ppdu_id) > DP_NOT_PPDU_ID_WRAP_AROUND)) { 4299d5c65159SKalle Valo /* mon_dst is behind than mon_status 4300d5c65159SKalle Valo * skip dst_ring and free it 4301d5c65159SKalle Valo */ 4302d5c65159SKalle Valo *rx_bufs_used += 1; 4303d5c65159SKalle Valo *ppdu_id = msdu_ppdu_id; 4304d5c65159SKalle Valo ret = msdu_ppdu_id; 4305d5c65159SKalle Valo } 4306d5c65159SKalle Valo return ret; 4307d5c65159SKalle Valo } 4308d5c65159SKalle Valo 4309d5c65159SKalle Valo static void ath11k_dp_mon_get_buf_len(struct hal_rx_msdu_desc_info *info, 4310d5c65159SKalle Valo bool *is_frag, u32 *total_len, 4311d5c65159SKalle Valo u32 *frag_len, u32 *msdu_cnt) 4312d5c65159SKalle Valo { 4313d5c65159SKalle Valo if (info->msdu_flags & RX_MSDU_DESC_INFO0_MSDU_CONTINUATION) { 4314d5c65159SKalle Valo if (!*is_frag) { 4315d5c65159SKalle Valo *total_len = info->msdu_len; 4316d5c65159SKalle Valo *is_frag = true; 4317d5c65159SKalle Valo } 4318d5c65159SKalle Valo ath11k_dp_mon_set_frag_len(total_len, 4319d5c65159SKalle Valo frag_len); 4320d5c65159SKalle Valo } else { 4321d5c65159SKalle Valo if (*is_frag) { 4322d5c65159SKalle Valo ath11k_dp_mon_set_frag_len(total_len, 4323d5c65159SKalle Valo frag_len); 4324d5c65159SKalle Valo } else { 4325d5c65159SKalle Valo *frag_len = info->msdu_len; 4326d5c65159SKalle Valo } 4327d5c65159SKalle Valo *is_frag = false; 4328d5c65159SKalle Valo *msdu_cnt -= 1; 4329d5c65159SKalle Valo } 4330d5c65159SKalle Valo } 4331d5c65159SKalle Valo 4332d5c65159SKalle Valo static u32 4333d5c65159SKalle Valo ath11k_dp_rx_mon_mpdu_pop(struct ath11k *ar, 4334d5c65159SKalle Valo void *ring_entry, struct sk_buff **head_msdu, 4335d5c65159SKalle Valo struct sk_buff **tail_msdu, u32 *npackets, 4336d5c65159SKalle Valo u32 *ppdu_id) 4337d5c65159SKalle Valo { 4338d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 4339d5c65159SKalle Valo struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data; 4340d5c65159SKalle Valo struct dp_rxdma_ring *rx_ring = &dp->rxdma_mon_buf_ring; 4341d5c65159SKalle Valo struct sk_buff *msdu = NULL, *last = NULL; 4342d5c65159SKalle Valo struct hal_rx_msdu_list msdu_list; 4343d5c65159SKalle Valo void *p_buf_addr_info, *p_last_buf_addr_info; 4344d5c65159SKalle Valo struct hal_rx_desc *rx_desc; 4345d5c65159SKalle Valo void *rx_msdu_link_desc; 4346d5c65159SKalle Valo dma_addr_t paddr; 4347d5c65159SKalle Valo u16 num_msdus = 0; 4348d5c65159SKalle Valo u32 rx_buf_size, rx_pkt_offset, sw_cookie; 4349d5c65159SKalle Valo u32 rx_bufs_used = 0, i = 0; 4350d5c65159SKalle Valo u32 msdu_ppdu_id = 0, msdu_cnt = 0; 4351d5c65159SKalle Valo u32 total_len = 0, frag_len = 0; 4352d5c65159SKalle Valo bool is_frag, is_first_msdu; 4353d5c65159SKalle Valo bool drop_mpdu = false; 4354d5c65159SKalle Valo struct ath11k_skb_rxcb *rxcb; 4355d5c65159SKalle Valo struct hal_reo_entrance_ring *ent_desc = 4356d5c65159SKalle Valo (struct hal_reo_entrance_ring *)ring_entry; 4357d5c65159SKalle Valo int buf_id; 4358d5c65159SKalle Valo 4359d5c65159SKalle Valo ath11k_hal_rx_reo_ent_buf_paddr_get(ring_entry, &paddr, 4360d5c65159SKalle Valo &sw_cookie, &p_last_buf_addr_info, 4361d5c65159SKalle Valo &msdu_cnt); 4362d5c65159SKalle Valo 4363d5c65159SKalle Valo if (FIELD_GET(HAL_REO_ENTR_RING_INFO1_RXDMA_PUSH_REASON, 4364d5c65159SKalle Valo ent_desc->info1) == 4365d5c65159SKalle Valo HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED) { 4366d5c65159SKalle Valo u8 rxdma_err = 4367d5c65159SKalle Valo FIELD_GET(HAL_REO_ENTR_RING_INFO1_RXDMA_ERROR_CODE, 4368d5c65159SKalle Valo ent_desc->info1); 4369d5c65159SKalle Valo if (rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_FLUSH_REQUEST_ERR || 4370d5c65159SKalle Valo rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_MPDU_LEN_ERR || 4371d5c65159SKalle Valo rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_OVERFLOW_ERR) { 4372d5c65159SKalle Valo drop_mpdu = true; 4373d5c65159SKalle Valo pmon->rx_mon_stats.dest_mpdu_drop++; 4374d5c65159SKalle Valo } 4375d5c65159SKalle Valo } 4376d5c65159SKalle Valo 4377d5c65159SKalle Valo is_frag = false; 4378d5c65159SKalle Valo is_first_msdu = true; 4379d5c65159SKalle Valo 4380d5c65159SKalle Valo do { 4381d5c65159SKalle Valo if (pmon->mon_last_linkdesc_paddr == paddr) { 4382d5c65159SKalle Valo pmon->rx_mon_stats.dup_mon_linkdesc_cnt++; 4383d5c65159SKalle Valo return rx_bufs_used; 4384d5c65159SKalle Valo } 4385d5c65159SKalle Valo 4386d5c65159SKalle Valo rx_msdu_link_desc = 4387d5c65159SKalle Valo (void *)pmon->link_desc_banks[sw_cookie].vaddr + 4388d5c65159SKalle Valo (paddr - pmon->link_desc_banks[sw_cookie].paddr); 4389d5c65159SKalle Valo 4390d5c65159SKalle Valo ath11k_hal_rx_msdu_list_get(ar, rx_msdu_link_desc, &msdu_list, 4391d5c65159SKalle Valo &num_msdus); 4392d5c65159SKalle Valo 4393d5c65159SKalle Valo for (i = 0; i < num_msdus; i++) { 4394d5c65159SKalle Valo u32 l2_hdr_offset; 4395d5c65159SKalle Valo 4396d5c65159SKalle Valo if (pmon->mon_last_buf_cookie == msdu_list.sw_cookie[i]) { 4397d5c65159SKalle Valo ath11k_dbg(ar->ab, ATH11K_DBG_DATA, 4398d5c65159SKalle Valo "i %d last_cookie %d is same\n", 4399d5c65159SKalle Valo i, pmon->mon_last_buf_cookie); 4400d5c65159SKalle Valo drop_mpdu = true; 4401d5c65159SKalle Valo pmon->rx_mon_stats.dup_mon_buf_cnt++; 4402d5c65159SKalle Valo continue; 4403d5c65159SKalle Valo } 4404d5c65159SKalle Valo buf_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_BUF_ID, 4405d5c65159SKalle Valo msdu_list.sw_cookie[i]); 4406d5c65159SKalle Valo 4407d5c65159SKalle Valo spin_lock_bh(&rx_ring->idr_lock); 4408d5c65159SKalle Valo msdu = idr_find(&rx_ring->bufs_idr, buf_id); 4409d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 4410d5c65159SKalle Valo if (!msdu) { 4411d5c65159SKalle Valo ath11k_dbg(ar->ab, ATH11K_DBG_DATA, 4412d5c65159SKalle Valo "msdu_pop: invalid buf_id %d\n", buf_id); 4413d5c65159SKalle Valo break; 4414d5c65159SKalle Valo } 4415d5c65159SKalle Valo rxcb = ATH11K_SKB_RXCB(msdu); 4416d5c65159SKalle Valo if (!rxcb->unmapped) { 4417d5c65159SKalle Valo dma_unmap_single(ar->ab->dev, rxcb->paddr, 4418d5c65159SKalle Valo msdu->len + 4419d5c65159SKalle Valo skb_tailroom(msdu), 4420d5c65159SKalle Valo DMA_FROM_DEVICE); 4421d5c65159SKalle Valo rxcb->unmapped = 1; 4422d5c65159SKalle Valo } 4423d5c65159SKalle Valo if (drop_mpdu) { 4424d5c65159SKalle Valo ath11k_dbg(ar->ab, ATH11K_DBG_DATA, 4425d5c65159SKalle Valo "i %d drop msdu %p *ppdu_id %x\n", 4426d5c65159SKalle Valo i, msdu, *ppdu_id); 4427d5c65159SKalle Valo dev_kfree_skb_any(msdu); 4428d5c65159SKalle Valo msdu = NULL; 4429d5c65159SKalle Valo goto next_msdu; 4430d5c65159SKalle Valo } 4431d5c65159SKalle Valo 4432d5c65159SKalle Valo rx_desc = (struct hal_rx_desc *)msdu->data; 4433d5c65159SKalle Valo 4434d5c65159SKalle Valo rx_pkt_offset = sizeof(struct hal_rx_desc); 4435d5c65159SKalle Valo l2_hdr_offset = ath11k_dp_rx_h_msdu_end_l3pad(rx_desc); 4436d5c65159SKalle Valo 4437d5c65159SKalle Valo if (is_first_msdu) { 4438d5c65159SKalle Valo if (!ath11k_dp_rxdesc_mpdu_valid(rx_desc)) { 4439d5c65159SKalle Valo drop_mpdu = true; 4440d5c65159SKalle Valo dev_kfree_skb_any(msdu); 4441d5c65159SKalle Valo msdu = NULL; 4442d5c65159SKalle Valo pmon->mon_last_linkdesc_paddr = paddr; 4443d5c65159SKalle Valo goto next_msdu; 4444d5c65159SKalle Valo } 4445d5c65159SKalle Valo 4446d5c65159SKalle Valo msdu_ppdu_id = 4447d5c65159SKalle Valo ath11k_dp_rxdesc_get_ppduid(rx_desc); 4448d5c65159SKalle Valo 4449d5c65159SKalle Valo if (ath11k_dp_rx_mon_comp_ppduid(msdu_ppdu_id, 4450d5c65159SKalle Valo ppdu_id, 44515e02bc73SMiles Hu &rx_bufs_used)) { 44525e02bc73SMiles Hu if (rx_bufs_used) { 44535e02bc73SMiles Hu drop_mpdu = true; 44545e02bc73SMiles Hu dev_kfree_skb_any(msdu); 44555e02bc73SMiles Hu msdu = NULL; 44565e02bc73SMiles Hu goto next_msdu; 44575e02bc73SMiles Hu } 4458d5c65159SKalle Valo return rx_bufs_used; 44595e02bc73SMiles Hu } 4460d5c65159SKalle Valo pmon->mon_last_linkdesc_paddr = paddr; 4461d5c65159SKalle Valo is_first_msdu = false; 4462d5c65159SKalle Valo } 4463d5c65159SKalle Valo ath11k_dp_mon_get_buf_len(&msdu_list.msdu_info[i], 4464d5c65159SKalle Valo &is_frag, &total_len, 4465d5c65159SKalle Valo &frag_len, &msdu_cnt); 4466d5c65159SKalle Valo rx_buf_size = rx_pkt_offset + l2_hdr_offset + frag_len; 4467d5c65159SKalle Valo 4468d5c65159SKalle Valo ath11k_dp_pkt_set_pktlen(msdu, rx_buf_size); 4469d5c65159SKalle Valo 4470d5c65159SKalle Valo if (!(*head_msdu)) 4471d5c65159SKalle Valo *head_msdu = msdu; 4472d5c65159SKalle Valo else if (last) 4473d5c65159SKalle Valo last->next = msdu; 4474d5c65159SKalle Valo 4475d5c65159SKalle Valo last = msdu; 4476d5c65159SKalle Valo next_msdu: 4477d5c65159SKalle Valo pmon->mon_last_buf_cookie = msdu_list.sw_cookie[i]; 4478d5c65159SKalle Valo rx_bufs_used++; 4479d5c65159SKalle Valo spin_lock_bh(&rx_ring->idr_lock); 4480d5c65159SKalle Valo idr_remove(&rx_ring->bufs_idr, buf_id); 4481d5c65159SKalle Valo spin_unlock_bh(&rx_ring->idr_lock); 4482d5c65159SKalle Valo } 4483d5c65159SKalle Valo 4484d5c65159SKalle Valo ath11k_dp_rx_mon_next_link_desc_get(rx_msdu_link_desc, &paddr, 4485d5c65159SKalle Valo &sw_cookie, 4486d5c65159SKalle Valo &p_buf_addr_info); 4487d5c65159SKalle Valo 4488d5c65159SKalle Valo if (ath11k_dp_rx_monitor_link_desc_return(ar, 4489d5c65159SKalle Valo p_last_buf_addr_info, 4490d5c65159SKalle Valo dp->mac_id)) 4491d5c65159SKalle Valo ath11k_dbg(ar->ab, ATH11K_DBG_DATA, 4492d5c65159SKalle Valo "dp_rx_monitor_link_desc_return failed"); 4493d5c65159SKalle Valo 4494d5c65159SKalle Valo p_last_buf_addr_info = p_buf_addr_info; 4495d5c65159SKalle Valo 4496d5c65159SKalle Valo } while (paddr && msdu_cnt); 4497d5c65159SKalle Valo 4498d5c65159SKalle Valo if (last) 4499d5c65159SKalle Valo last->next = NULL; 4500d5c65159SKalle Valo 4501d5c65159SKalle Valo *tail_msdu = msdu; 4502d5c65159SKalle Valo 4503d5c65159SKalle Valo if (msdu_cnt == 0) 4504d5c65159SKalle Valo *npackets = 1; 4505d5c65159SKalle Valo 4506d5c65159SKalle Valo return rx_bufs_used; 4507d5c65159SKalle Valo } 4508d5c65159SKalle Valo 4509d5c65159SKalle Valo static void ath11k_dp_rx_msdus_set_payload(struct sk_buff *msdu) 4510d5c65159SKalle Valo { 4511d5c65159SKalle Valo u32 rx_pkt_offset, l2_hdr_offset; 4512d5c65159SKalle Valo 4513d5c65159SKalle Valo rx_pkt_offset = sizeof(struct hal_rx_desc); 4514d5c65159SKalle Valo l2_hdr_offset = ath11k_dp_rx_h_msdu_end_l3pad((struct hal_rx_desc *)msdu->data); 4515d5c65159SKalle Valo skb_pull(msdu, rx_pkt_offset + l2_hdr_offset); 4516d5c65159SKalle Valo } 4517d5c65159SKalle Valo 4518d5c65159SKalle Valo static struct sk_buff * 4519d5c65159SKalle Valo ath11k_dp_rx_mon_merg_msdus(struct ath11k *ar, 4520d5c65159SKalle Valo u32 mac_id, struct sk_buff *head_msdu, 4521d5c65159SKalle Valo struct sk_buff *last_msdu, 4522d5c65159SKalle Valo struct ieee80211_rx_status *rxs) 4523d5c65159SKalle Valo { 4524d5c65159SKalle Valo struct sk_buff *msdu, *mpdu_buf, *prev_buf; 4525d5c65159SKalle Valo u32 decap_format, wifi_hdr_len; 4526d5c65159SKalle Valo struct hal_rx_desc *rx_desc; 4527d5c65159SKalle Valo char *hdr_desc; 4528d5c65159SKalle Valo u8 *dest; 4529d5c65159SKalle Valo struct ieee80211_hdr_3addr *wh; 4530d5c65159SKalle Valo 4531d5c65159SKalle Valo mpdu_buf = NULL; 4532d5c65159SKalle Valo 4533d5c65159SKalle Valo if (!head_msdu) 4534d5c65159SKalle Valo goto err_merge_fail; 4535d5c65159SKalle Valo 4536d5c65159SKalle Valo rx_desc = (struct hal_rx_desc *)head_msdu->data; 4537d5c65159SKalle Valo 4538d5c65159SKalle Valo if (ath11k_dp_rxdesc_get_mpdulen_err(rx_desc)) 4539d5c65159SKalle Valo return NULL; 4540d5c65159SKalle Valo 4541d5c65159SKalle Valo decap_format = ath11k_dp_rxdesc_get_decap_format(rx_desc); 4542d5c65159SKalle Valo 4543d5c65159SKalle Valo ath11k_dp_rx_h_ppdu(ar, rx_desc, rxs); 4544d5c65159SKalle Valo 4545d5c65159SKalle Valo if (decap_format == DP_RX_DECAP_TYPE_RAW) { 4546d5c65159SKalle Valo ath11k_dp_rx_msdus_set_payload(head_msdu); 4547d5c65159SKalle Valo 4548d5c65159SKalle Valo prev_buf = head_msdu; 4549d5c65159SKalle Valo msdu = head_msdu->next; 4550d5c65159SKalle Valo 4551d5c65159SKalle Valo while (msdu) { 4552d5c65159SKalle Valo ath11k_dp_rx_msdus_set_payload(msdu); 4553d5c65159SKalle Valo 4554d5c65159SKalle Valo prev_buf = msdu; 4555d5c65159SKalle Valo msdu = msdu->next; 4556d5c65159SKalle Valo } 4557d5c65159SKalle Valo 4558d5c65159SKalle Valo prev_buf->next = NULL; 4559d5c65159SKalle Valo 4560d5c65159SKalle Valo skb_trim(prev_buf, prev_buf->len - HAL_RX_FCS_LEN); 4561d5c65159SKalle Valo } else if (decap_format == DP_RX_DECAP_TYPE_NATIVE_WIFI) { 4562d5c65159SKalle Valo __le16 qos_field; 4563d5c65159SKalle Valo u8 qos_pkt = 0; 4564d5c65159SKalle Valo 4565d5c65159SKalle Valo rx_desc = (struct hal_rx_desc *)head_msdu->data; 4566d5c65159SKalle Valo hdr_desc = ath11k_dp_rxdesc_get_80211hdr(rx_desc); 4567d5c65159SKalle Valo 4568d5c65159SKalle Valo /* Base size */ 4569d5c65159SKalle Valo wifi_hdr_len = sizeof(struct ieee80211_hdr_3addr); 4570d5c65159SKalle Valo wh = (struct ieee80211_hdr_3addr *)hdr_desc; 4571d5c65159SKalle Valo 4572d5c65159SKalle Valo if (ieee80211_is_data_qos(wh->frame_control)) { 4573d5c65159SKalle Valo struct ieee80211_qos_hdr *qwh = 4574d5c65159SKalle Valo (struct ieee80211_qos_hdr *)hdr_desc; 4575d5c65159SKalle Valo 4576d5c65159SKalle Valo qos_field = qwh->qos_ctrl; 4577d5c65159SKalle Valo qos_pkt = 1; 4578d5c65159SKalle Valo } 4579d5c65159SKalle Valo msdu = head_msdu; 4580d5c65159SKalle Valo 4581d5c65159SKalle Valo while (msdu) { 4582d5c65159SKalle Valo rx_desc = (struct hal_rx_desc *)msdu->data; 4583d5c65159SKalle Valo hdr_desc = ath11k_dp_rxdesc_get_80211hdr(rx_desc); 4584d5c65159SKalle Valo 4585d5c65159SKalle Valo if (qos_pkt) { 4586d5c65159SKalle Valo dest = skb_push(msdu, sizeof(__le16)); 4587d5c65159SKalle Valo if (!dest) 4588d5c65159SKalle Valo goto err_merge_fail; 4589d5c65159SKalle Valo memcpy(dest, hdr_desc, wifi_hdr_len); 4590d5c65159SKalle Valo memcpy(dest + wifi_hdr_len, 4591d5c65159SKalle Valo (u8 *)&qos_field, sizeof(__le16)); 4592d5c65159SKalle Valo } 4593d5c65159SKalle Valo ath11k_dp_rx_msdus_set_payload(msdu); 4594d5c65159SKalle Valo prev_buf = msdu; 4595d5c65159SKalle Valo msdu = msdu->next; 4596d5c65159SKalle Valo } 4597d5c65159SKalle Valo dest = skb_put(prev_buf, HAL_RX_FCS_LEN); 4598d5c65159SKalle Valo if (!dest) 4599d5c65159SKalle Valo goto err_merge_fail; 4600d5c65159SKalle Valo 4601d5c65159SKalle Valo ath11k_dbg(ar->ab, ATH11K_DBG_DATA, 4602d5c65159SKalle Valo "mpdu_buf %pK mpdu_buf->len %u", 4603d5c65159SKalle Valo prev_buf, prev_buf->len); 4604d5c65159SKalle Valo } else { 4605d5c65159SKalle Valo ath11k_dbg(ar->ab, ATH11K_DBG_DATA, 4606d5c65159SKalle Valo "decap format %d is not supported!\n", 4607d5c65159SKalle Valo decap_format); 4608d5c65159SKalle Valo goto err_merge_fail; 4609d5c65159SKalle Valo } 4610d5c65159SKalle Valo 4611d5c65159SKalle Valo return head_msdu; 4612d5c65159SKalle Valo 4613d5c65159SKalle Valo err_merge_fail: 4614d5c65159SKalle Valo if (mpdu_buf && decap_format != DP_RX_DECAP_TYPE_RAW) { 4615d5c65159SKalle Valo ath11k_dbg(ar->ab, ATH11K_DBG_DATA, 4616d5c65159SKalle Valo "err_merge_fail mpdu_buf %pK", mpdu_buf); 4617d5c65159SKalle Valo /* Free the head buffer */ 4618d5c65159SKalle Valo dev_kfree_skb_any(mpdu_buf); 4619d5c65159SKalle Valo } 4620d5c65159SKalle Valo return NULL; 4621d5c65159SKalle Valo } 4622d5c65159SKalle Valo 4623d5c65159SKalle Valo static int ath11k_dp_rx_mon_deliver(struct ath11k *ar, u32 mac_id, 4624d5c65159SKalle Valo struct sk_buff *head_msdu, 4625d5c65159SKalle Valo struct sk_buff *tail_msdu, 4626d5c65159SKalle Valo struct napi_struct *napi) 4627d5c65159SKalle Valo { 4628d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 4629d5c65159SKalle Valo struct sk_buff *mon_skb, *skb_next, *header; 4630d5c65159SKalle Valo struct ieee80211_rx_status *rxs = &dp->rx_status, *status; 4631d5c65159SKalle Valo 4632d5c65159SKalle Valo mon_skb = ath11k_dp_rx_mon_merg_msdus(ar, mac_id, head_msdu, 4633d5c65159SKalle Valo tail_msdu, rxs); 4634d5c65159SKalle Valo 4635d5c65159SKalle Valo if (!mon_skb) 4636d5c65159SKalle Valo goto mon_deliver_fail; 4637d5c65159SKalle Valo 4638d5c65159SKalle Valo header = mon_skb; 4639d5c65159SKalle Valo 4640d5c65159SKalle Valo rxs->flag = 0; 4641d5c65159SKalle Valo do { 4642d5c65159SKalle Valo skb_next = mon_skb->next; 4643d5c65159SKalle Valo if (!skb_next) 4644d5c65159SKalle Valo rxs->flag &= ~RX_FLAG_AMSDU_MORE; 4645d5c65159SKalle Valo else 4646d5c65159SKalle Valo rxs->flag |= RX_FLAG_AMSDU_MORE; 4647d5c65159SKalle Valo 4648d5c65159SKalle Valo if (mon_skb == header) { 4649d5c65159SKalle Valo header = NULL; 4650d5c65159SKalle Valo rxs->flag &= ~RX_FLAG_ALLOW_SAME_PN; 4651d5c65159SKalle Valo } else { 4652d5c65159SKalle Valo rxs->flag |= RX_FLAG_ALLOW_SAME_PN; 4653d5c65159SKalle Valo } 4654d5c65159SKalle Valo rxs->flag |= RX_FLAG_ONLY_MONITOR; 4655d5c65159SKalle Valo 4656d5c65159SKalle Valo status = IEEE80211_SKB_RXCB(mon_skb); 4657d5c65159SKalle Valo *status = *rxs; 4658d5c65159SKalle Valo 4659d5c65159SKalle Valo ath11k_dp_rx_deliver_msdu(ar, napi, mon_skb); 4660d5c65159SKalle Valo mon_skb = skb_next; 46615e02bc73SMiles Hu } while (mon_skb); 4662d5c65159SKalle Valo rxs->flag = 0; 4663d5c65159SKalle Valo 4664d5c65159SKalle Valo return 0; 4665d5c65159SKalle Valo 4666d5c65159SKalle Valo mon_deliver_fail: 4667d5c65159SKalle Valo mon_skb = head_msdu; 4668d5c65159SKalle Valo while (mon_skb) { 4669d5c65159SKalle Valo skb_next = mon_skb->next; 4670d5c65159SKalle Valo dev_kfree_skb_any(mon_skb); 4671d5c65159SKalle Valo mon_skb = skb_next; 4672d5c65159SKalle Valo } 4673d5c65159SKalle Valo return -EINVAL; 4674d5c65159SKalle Valo } 4675d5c65159SKalle Valo 4676d5c65159SKalle Valo static void ath11k_dp_rx_mon_dest_process(struct ath11k *ar, u32 quota, 4677d5c65159SKalle Valo struct napi_struct *napi) 4678d5c65159SKalle Valo { 4679d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 4680d5c65159SKalle Valo struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data; 4681d5c65159SKalle Valo void *ring_entry; 4682d5c65159SKalle Valo void *mon_dst_srng; 4683d5c65159SKalle Valo u32 ppdu_id; 4684d5c65159SKalle Valo u32 rx_bufs_used; 4685d5c65159SKalle Valo struct ath11k_pdev_mon_stats *rx_mon_stats; 4686d5c65159SKalle Valo u32 npackets = 0; 4687d5c65159SKalle Valo 4688d5c65159SKalle Valo mon_dst_srng = &ar->ab->hal.srng_list[dp->rxdma_mon_dst_ring.ring_id]; 4689d5c65159SKalle Valo 4690d5c65159SKalle Valo if (!mon_dst_srng) { 4691d5c65159SKalle Valo ath11k_warn(ar->ab, 4692d5c65159SKalle Valo "HAL Monitor Destination Ring Init Failed -- %pK", 4693d5c65159SKalle Valo mon_dst_srng); 4694d5c65159SKalle Valo return; 4695d5c65159SKalle Valo } 4696d5c65159SKalle Valo 4697d5c65159SKalle Valo spin_lock_bh(&pmon->mon_lock); 4698d5c65159SKalle Valo 4699d5c65159SKalle Valo ath11k_hal_srng_access_begin(ar->ab, mon_dst_srng); 4700d5c65159SKalle Valo 4701d5c65159SKalle Valo ppdu_id = pmon->mon_ppdu_info.ppdu_id; 4702d5c65159SKalle Valo rx_bufs_used = 0; 4703d5c65159SKalle Valo rx_mon_stats = &pmon->rx_mon_stats; 4704d5c65159SKalle Valo 4705d5c65159SKalle Valo while ((ring_entry = ath11k_hal_srng_dst_peek(ar->ab, mon_dst_srng))) { 4706d5c65159SKalle Valo struct sk_buff *head_msdu, *tail_msdu; 4707d5c65159SKalle Valo 4708d5c65159SKalle Valo head_msdu = NULL; 4709d5c65159SKalle Valo tail_msdu = NULL; 4710d5c65159SKalle Valo 4711d5c65159SKalle Valo rx_bufs_used += ath11k_dp_rx_mon_mpdu_pop(ar, ring_entry, 4712d5c65159SKalle Valo &head_msdu, 4713d5c65159SKalle Valo &tail_msdu, 4714d5c65159SKalle Valo &npackets, &ppdu_id); 4715d5c65159SKalle Valo 4716d5c65159SKalle Valo if (ppdu_id != pmon->mon_ppdu_info.ppdu_id) { 4717d5c65159SKalle Valo pmon->mon_ppdu_status = DP_PPDU_STATUS_START; 4718d5c65159SKalle Valo ath11k_dbg(ar->ab, ATH11K_DBG_DATA, 4719d5c65159SKalle Valo "dest_rx: new ppdu_id %x != status ppdu_id %x", 4720d5c65159SKalle Valo ppdu_id, pmon->mon_ppdu_info.ppdu_id); 4721d5c65159SKalle Valo break; 4722d5c65159SKalle Valo } 4723d5c65159SKalle Valo if (head_msdu && tail_msdu) { 4724d5c65159SKalle Valo ath11k_dp_rx_mon_deliver(ar, dp->mac_id, head_msdu, 4725d5c65159SKalle Valo tail_msdu, napi); 4726d5c65159SKalle Valo rx_mon_stats->dest_mpdu_done++; 4727d5c65159SKalle Valo } 4728d5c65159SKalle Valo 4729d5c65159SKalle Valo ring_entry = ath11k_hal_srng_dst_get_next_entry(ar->ab, 4730d5c65159SKalle Valo mon_dst_srng); 4731d5c65159SKalle Valo } 4732d5c65159SKalle Valo ath11k_hal_srng_access_end(ar->ab, mon_dst_srng); 4733d5c65159SKalle Valo 4734d5c65159SKalle Valo spin_unlock_bh(&pmon->mon_lock); 4735d5c65159SKalle Valo 4736d5c65159SKalle Valo if (rx_bufs_used) { 4737d5c65159SKalle Valo rx_mon_stats->dest_ppdu_done++; 4738d5c65159SKalle Valo ath11k_dp_rxbufs_replenish(ar->ab, dp->mac_id, 4739d5c65159SKalle Valo &dp->rxdma_mon_buf_ring, 4740d5c65159SKalle Valo rx_bufs_used, 4741d5c65159SKalle Valo HAL_RX_BUF_RBM_SW3_BM, GFP_ATOMIC); 4742d5c65159SKalle Valo } 4743d5c65159SKalle Valo } 4744d5c65159SKalle Valo 4745d5c65159SKalle Valo static void ath11k_dp_rx_mon_status_process_tlv(struct ath11k *ar, 4746d5c65159SKalle Valo u32 quota, 4747d5c65159SKalle Valo struct napi_struct *napi) 4748d5c65159SKalle Valo { 4749d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 4750d5c65159SKalle Valo struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data; 4751d5c65159SKalle Valo struct hal_rx_mon_ppdu_info *ppdu_info; 4752d5c65159SKalle Valo struct sk_buff *status_skb; 4753d5c65159SKalle Valo u32 tlv_status = HAL_TLV_STATUS_BUF_DONE; 4754d5c65159SKalle Valo struct ath11k_pdev_mon_stats *rx_mon_stats; 4755d5c65159SKalle Valo 4756d5c65159SKalle Valo ppdu_info = &pmon->mon_ppdu_info; 4757d5c65159SKalle Valo rx_mon_stats = &pmon->rx_mon_stats; 4758d5c65159SKalle Valo 4759d5c65159SKalle Valo if (pmon->mon_ppdu_status != DP_PPDU_STATUS_START) 4760d5c65159SKalle Valo return; 4761d5c65159SKalle Valo 4762d5c65159SKalle Valo while (!skb_queue_empty(&pmon->rx_status_q)) { 4763d5c65159SKalle Valo status_skb = skb_dequeue(&pmon->rx_status_q); 4764d5c65159SKalle Valo 4765d5c65159SKalle Valo tlv_status = ath11k_hal_rx_parse_mon_status(ar->ab, ppdu_info, 4766d5c65159SKalle Valo status_skb); 4767d5c65159SKalle Valo if (tlv_status == HAL_TLV_STATUS_PPDU_DONE) { 4768d5c65159SKalle Valo rx_mon_stats->status_ppdu_done++; 4769d5c65159SKalle Valo pmon->mon_ppdu_status = DP_PPDU_STATUS_DONE; 4770d5c65159SKalle Valo ath11k_dp_rx_mon_dest_process(ar, quota, napi); 4771d5c65159SKalle Valo pmon->mon_ppdu_status = DP_PPDU_STATUS_START; 4772d5c65159SKalle Valo } 4773d5c65159SKalle Valo dev_kfree_skb_any(status_skb); 4774d5c65159SKalle Valo } 4775d5c65159SKalle Valo } 4776d5c65159SKalle Valo 4777d5c65159SKalle Valo static int ath11k_dp_mon_process_rx(struct ath11k_base *ab, int mac_id, 4778d5c65159SKalle Valo struct napi_struct *napi, int budget) 4779d5c65159SKalle Valo { 4780d5c65159SKalle Valo struct ath11k *ar = ab->pdevs[mac_id].ar; 4781d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 4782d5c65159SKalle Valo struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data; 4783d5c65159SKalle Valo int num_buffs_reaped = 0; 4784d5c65159SKalle Valo 4785d5c65159SKalle Valo num_buffs_reaped = ath11k_dp_rx_reap_mon_status_ring(ar->ab, dp->mac_id, &budget, 4786d5c65159SKalle Valo &pmon->rx_status_q); 4787d5c65159SKalle Valo if (num_buffs_reaped) 4788d5c65159SKalle Valo ath11k_dp_rx_mon_status_process_tlv(ar, budget, napi); 4789d5c65159SKalle Valo 4790d5c65159SKalle Valo return num_buffs_reaped; 4791d5c65159SKalle Valo } 4792d5c65159SKalle Valo 4793d5c65159SKalle Valo int ath11k_dp_rx_process_mon_rings(struct ath11k_base *ab, int mac_id, 4794d5c65159SKalle Valo struct napi_struct *napi, int budget) 4795d5c65159SKalle Valo { 4796d5c65159SKalle Valo struct ath11k *ar = ab->pdevs[mac_id].ar; 4797d5c65159SKalle Valo int ret = 0; 4798d5c65159SKalle Valo 4799d5c65159SKalle Valo if (test_bit(ATH11K_FLAG_MONITOR_ENABLED, &ar->monitor_flags)) 4800d5c65159SKalle Valo ret = ath11k_dp_mon_process_rx(ab, mac_id, napi, budget); 4801d5c65159SKalle Valo else 4802d5c65159SKalle Valo ret = ath11k_dp_rx_process_mon_status(ab, mac_id, napi, budget); 4803d5c65159SKalle Valo return ret; 4804d5c65159SKalle Valo } 4805d5c65159SKalle Valo 4806d5c65159SKalle Valo static int ath11k_dp_rx_pdev_mon_status_attach(struct ath11k *ar) 4807d5c65159SKalle Valo { 4808d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 4809d5c65159SKalle Valo struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data; 4810d5c65159SKalle Valo 4811d5c65159SKalle Valo skb_queue_head_init(&pmon->rx_status_q); 4812d5c65159SKalle Valo 4813d5c65159SKalle Valo pmon->mon_ppdu_status = DP_PPDU_STATUS_START; 4814d5c65159SKalle Valo 4815d5c65159SKalle Valo memset(&pmon->rx_mon_stats, 0, 4816d5c65159SKalle Valo sizeof(pmon->rx_mon_stats)); 4817d5c65159SKalle Valo return 0; 4818d5c65159SKalle Valo } 4819d5c65159SKalle Valo 4820d5c65159SKalle Valo int ath11k_dp_rx_pdev_mon_attach(struct ath11k *ar) 4821d5c65159SKalle Valo { 4822d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 4823d5c65159SKalle Valo struct ath11k_mon_data *pmon = &dp->mon_data; 4824d5c65159SKalle Valo struct hal_srng *mon_desc_srng = NULL; 4825d5c65159SKalle Valo struct dp_srng *dp_srng; 4826d5c65159SKalle Valo int ret = 0; 4827d5c65159SKalle Valo u32 n_link_desc = 0; 4828d5c65159SKalle Valo 4829d5c65159SKalle Valo ret = ath11k_dp_rx_pdev_mon_status_attach(ar); 4830d5c65159SKalle Valo if (ret) { 4831d5c65159SKalle Valo ath11k_warn(ar->ab, "pdev_mon_status_attach() failed"); 4832d5c65159SKalle Valo return ret; 4833d5c65159SKalle Valo } 4834d5c65159SKalle Valo 4835d5c65159SKalle Valo dp_srng = &dp->rxdma_mon_desc_ring; 4836d5c65159SKalle Valo n_link_desc = dp_srng->size / 4837f7eb4b04SKalle Valo ath11k_hal_srng_get_entrysize(ar->ab, HAL_RXDMA_MONITOR_DESC); 4838d5c65159SKalle Valo mon_desc_srng = 4839d5c65159SKalle Valo &ar->ab->hal.srng_list[dp->rxdma_mon_desc_ring.ring_id]; 4840d5c65159SKalle Valo 4841d5c65159SKalle Valo ret = ath11k_dp_link_desc_setup(ar->ab, pmon->link_desc_banks, 4842d5c65159SKalle Valo HAL_RXDMA_MONITOR_DESC, mon_desc_srng, 4843d5c65159SKalle Valo n_link_desc); 4844d5c65159SKalle Valo if (ret) { 4845d5c65159SKalle Valo ath11k_warn(ar->ab, "mon_link_desc_pool_setup() failed"); 4846d5c65159SKalle Valo return ret; 4847d5c65159SKalle Valo } 4848d5c65159SKalle Valo pmon->mon_last_linkdesc_paddr = 0; 4849d5c65159SKalle Valo pmon->mon_last_buf_cookie = DP_RX_DESC_COOKIE_MAX + 1; 4850d5c65159SKalle Valo spin_lock_init(&pmon->mon_lock); 4851d5c65159SKalle Valo return 0; 4852d5c65159SKalle Valo } 4853d5c65159SKalle Valo 4854d5c65159SKalle Valo static int ath11k_dp_mon_link_free(struct ath11k *ar) 4855d5c65159SKalle Valo { 4856d5c65159SKalle Valo struct ath11k_pdev_dp *dp = &ar->dp; 4857d5c65159SKalle Valo struct ath11k_mon_data *pmon = &dp->mon_data; 4858d5c65159SKalle Valo 4859d5c65159SKalle Valo ath11k_dp_link_desc_cleanup(ar->ab, pmon->link_desc_banks, 4860d5c65159SKalle Valo HAL_RXDMA_MONITOR_DESC, 4861d5c65159SKalle Valo &dp->rxdma_mon_desc_ring); 4862d5c65159SKalle Valo return 0; 4863d5c65159SKalle Valo } 4864d5c65159SKalle Valo 4865d5c65159SKalle Valo int ath11k_dp_rx_pdev_mon_detach(struct ath11k *ar) 4866d5c65159SKalle Valo { 4867d5c65159SKalle Valo ath11k_dp_mon_link_free(ar); 4868d5c65159SKalle Valo return 0; 4869d5c65159SKalle Valo } 4870