From e33a5632b88588aa64569d7182f73046666ed86c Mon Sep 17 00:00:00 2001 From: Tallapragada Kalyan Date: Thu, 22 Feb 2018 20:33:15 +0530 Subject: [PATCH] qcacmn: add abstraction to update rx stats Add a new API to update the stats which will be called from dp_rx_process instead of updating stats directly from within the dp_rx_process function Change-Id: I13bdfd1606c3ceb2e38921ffa0cf3fe9f29c57ee CRs-Fixed: 2189088 --- dp/wifi3.0/dp_rx.c | 336 +++++++++++++++++++++----------------------- dp/wifi3.0/hal_rx.h | 27 ++++ 2 files changed, 189 insertions(+), 174 deletions(-) diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index f3ab90c78f3b..7fc8f7b9f0a6 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -994,6 +994,143 @@ static inline void dp_rx_deliver_to_stack(struct dp_vdev *vdev, } +/** + * dp_rx_cksum_offload() - set the nbuf checksum as defined by hardware. + * @nbuf: pointer to the first msdu of an amsdu. + * @rx_tlv_hdr: pointer to the start of RX TLV headers. + * + * The ipsumed field of the skb is set based on whether HW validated the + * IP/TCP/UDP checksum. + * + * Return: void + */ +static inline void dp_rx_cksum_offload(qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr) +{ + qdf_nbuf_rx_cksum_t cksum = {0}; + + if (qdf_likely(!hal_rx_attn_tcp_udp_cksum_fail_get(rx_tlv_hdr) && + !hal_rx_attn_ip_cksum_fail_get(rx_tlv_hdr))) { + cksum.l4_result = QDF_NBUF_RX_CKSUM_TCP_UDP_UNNECESSARY; + + qdf_nbuf_set_rx_cksum(nbuf, &cksum); + } +} + +/** + * dp_rx_msdu_stats_update() - update per msdu stats. + * @soc: core txrx main context + * @nbuf: pointer to the first msdu of an amsdu. + * @rx_tlv_hdr: pointer to the start of RX TLV headers. + * @peer: pointer to the peer object. + * @ring_id: reo dest ring number on which pkt is reaped. + * + * update all the per msdu stats for that nbuf. + * Return: void + */ +static void dp_rx_msdu_stats_update(struct dp_soc *soc, + qdf_nbuf_t nbuf, + uint8_t *rx_tlv_hdr, + struct dp_peer *peer, + uint8_t ring_id) +{ + bool is_ampdu, is_not_amsdu; + uint16_t peer_id; + uint32_t sgi, mcs, tid, nss, bw, reception_type, pkt_type; + struct dp_vdev *vdev = peer->vdev; + struct ether_header *eh; + bool is_broadcast = false; + + peer_id = DP_PEER_METADATA_PEER_ID_GET( + hal_rx_mpdu_peer_meta_data_get(rx_tlv_hdr)); + + is_not_amsdu = qdf_nbuf_is_rx_chfrag_start(nbuf) & + qdf_nbuf_is_rx_chfrag_end(nbuf); + + DP_STATS_INC_PKT(peer, rx.rcvd_reo[ring_id], 1, + hal_rx_msdu_start_msdu_len_get(rx_tlv_hdr)); + + DP_STATS_INCC(peer, rx.non_amsdu_cnt, 1, is_not_amsdu); + DP_STATS_INCC(peer, rx.amsdu_cnt, 1, !is_not_amsdu); + + DP_STATS_INCC_PKT(peer, rx.multicast, 1, qdf_nbuf_len(nbuf), + hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr)); + + /* + * currently we can return from here as we have similar stats + * updated at per ppdu level instead of msdu level + */ + if (!soc->process_rx_status) + return; + + is_ampdu = hal_rx_mpdu_info_ampdu_flag_get(rx_tlv_hdr); + DP_STATS_INCC(peer, rx.ampdu_cnt, 1, is_ampdu); + DP_STATS_INCC(peer, rx.non_ampdu_cnt, 1, !(is_ampdu)); + + sgi = hal_rx_msdu_start_sgi_get(rx_tlv_hdr); + mcs = hal_rx_msdu_start_rate_mcs_get(rx_tlv_hdr); + tid = hal_rx_mpdu_start_tid_get(rx_tlv_hdr); + bw = hal_rx_msdu_start_bw_get(rx_tlv_hdr); + reception_type = hal_rx_msdu_start_reception_type_get(rx_tlv_hdr); + nss = hal_rx_msdu_start_nss_get(rx_tlv_hdr); + pkt_type = hal_rx_msdu_start_get_pkt_type(rx_tlv_hdr); + + DP_STATS_INC(vdev->pdev, rx.bw[bw], 1); + DP_STATS_INC(vdev->pdev, rx.reception_type[reception_type], 1); + DP_STATS_INCC(vdev->pdev, rx.nss[nss], 1, + ((reception_type == REPT_MU_MIMO) || + (reception_type == REPT_MU_OFDMA_MIMO))); + DP_STATS_INC(peer, rx.sgi_count[sgi], 1); + DP_STATS_INCC(peer, rx.err.mic_err, 1, + hal_rx_mpdu_end_mic_err_get(rx_tlv_hdr)); + DP_STATS_INCC(peer, rx.err.decrypt_err, 1, + hal_rx_mpdu_end_decrypt_err_get(rx_tlv_hdr)); + + DP_STATS_INC(peer, rx.wme_ac_type[TID_TO_WME_AC(tid)], 1); + DP_STATS_INC(peer, rx.bw[bw], 1); + DP_STATS_INC(peer, rx.reception_type[reception_type], 1); + + DP_STATS_INCC(peer, rx.pkt_type[pkt_type].mcs_count[MAX_MCS], 1, + ((mcs >= MAX_MCS_11A) && (pkt_type == DOT11_A))); + DP_STATS_INCC(peer, rx.pkt_type[pkt_type].mcs_count[mcs], 1, + ((mcs <= MAX_MCS_11A) && (pkt_type == DOT11_A))); + DP_STATS_INCC(peer, rx.pkt_type[pkt_type].mcs_count[MAX_MCS], 1, + ((mcs >= MAX_MCS_11B) && (pkt_type == DOT11_B))); + DP_STATS_INCC(peer, rx.pkt_type[pkt_type].mcs_count[mcs], 1, + ((mcs <= MAX_MCS_11B) && (pkt_type == DOT11_B))); + DP_STATS_INCC(peer, rx.pkt_type[pkt_type].mcs_count[MAX_MCS], 1, + ((mcs >= MAX_MCS_11A) && (pkt_type == DOT11_N))); + DP_STATS_INCC(peer, rx.pkt_type[pkt_type].mcs_count[mcs], 1, + ((mcs <= MAX_MCS_11A) && (pkt_type == DOT11_N))); + DP_STATS_INCC(peer, rx.pkt_type[pkt_type].mcs_count[MAX_MCS], 1, + ((mcs >= MAX_MCS_11AC) && (pkt_type == DOT11_AC))); + DP_STATS_INCC(peer, rx.pkt_type[pkt_type].mcs_count[mcs], 1, + ((mcs <= MAX_MCS_11AC) && (pkt_type == DOT11_AC))); + DP_STATS_INCC(peer, rx.pkt_type[pkt_type].mcs_count[MAX_MCS], 1, + ((mcs >= MAX_MCS) && (pkt_type == DOT11_AX))); + DP_STATS_INCC(peer, rx.pkt_type[pkt_type].mcs_count[mcs], 1, + ((mcs <= MAX_MCS) && (pkt_type == DOT11_AX))); + + if (qdf_unlikely(hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr) && + (vdev->rx_decap_type == htt_cmn_pkt_type_ethernet))) { + eh = (struct ether_header *)qdf_nbuf_data(nbuf); + is_broadcast = + IEEE80211_IS_BROADCAST(eh->ether_dhost) ? true : false; + if (is_broadcast) + DP_STATS_INC_PKT(peer, rx.bcast, 1, qdf_nbuf_len(nbuf)); + } + + if ((soc->process_rx_status) && + hal_rx_attn_first_mpdu_get(rx_tlv_hdr)) { + if (soc->cdp_soc.ol_ops->update_dp_stats) { + soc->cdp_soc.ol_ops->update_dp_stats( + vdev->pdev->osif_pdev, + &peer->stats, + peer_id, + UPDATE_PEER_STATS); + } + } +} + #ifdef WDS_VENDOR_EXTENSION int dp_wds_rx_policy_check( uint8_t *rx_tlv_hdr, @@ -1119,18 +1256,14 @@ dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, uint32_t quota) uint32_t peer_mdata; uint8_t *rx_tlv_hdr; uint32_t rx_bufs_reaped[MAX_PDEV_CNT] = { 0 }; - uint32_t sgi, mcs, tid, nss, bw, reception_type, pkt_type; uint8_t mac_id = 0; - uint32_t ampdu_flag, amsdu_flag; struct dp_pdev *pdev; struct dp_srng *dp_rxdma_srng; struct rx_desc_pool *rx_desc_pool; - struct ether_header *eh; struct dp_soc *soc = int_ctx->soc; uint8_t ring_id = 0; uint8_t core_id = 0; bool is_first_frag = 0; - bool isBroadcast = 0; uint16_t mpdu_len = 0; qdf_nbuf_t head_frag_nbuf = NULL; qdf_nbuf_t frag_list_head = NULL; @@ -1151,7 +1284,6 @@ dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, uint32_t quota) qdf_assert(hal_soc); hif_pm_runtime_mark_last_busy(soc->osdev->dev); - sgi = mcs = tid = nss = bw = reception_type = pkt_type = 0; if (qdf_unlikely(hal_srng_access_start(hal_soc, hal_ring))) { @@ -1206,26 +1338,10 @@ dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, uint32_t quota) /* Get MPDU DESC info */ hal_rx_mpdu_desc_info_get(ring_desc, &mpdu_desc_info); - peer_id = DP_PEER_METADATA_PEER_ID_GET( - mpdu_desc_info.peer_meta_data); hal_rx_mpdu_peer_meta_data_set(qdf_nbuf_data(rx_desc->nbuf), mpdu_desc_info.peer_meta_data); - peer = dp_peer_find_by_id(soc, peer_id); - - vdev = dp_get_vdev_from_peer(soc, peer_id, peer, - mpdu_desc_info); - - if (!vdev) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_LOW, - FL("vdev is NULL")); - DP_STATS_INC(soc, rx.err.invalid_vdev, 1); - qdf_nbuf_free(rx_desc->nbuf); - goto fail; - - } - /* Get MSDU DESC info */ hal_rx_msdu_desc_info_get(ring_desc, &msdu_desc_info); @@ -1242,30 +1358,8 @@ dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, uint32_t quota) if (msdu_desc_info.msdu_flags & HAL_MSDU_F_LAST_MSDU_IN_MPDU) qdf_nbuf_set_rx_chfrag_end(rx_desc->nbuf, 1); - DP_STATS_INC_PKT(peer, rx.rcvd_reo[ring_id], 1, - qdf_nbuf_len(rx_desc->nbuf)); - - if (soc->process_rx_status) { - ampdu_flag = (mpdu_desc_info.mpdu_flags & - HAL_MPDU_F_AMPDU_FLAG); - - DP_STATS_INCC(peer, rx.ampdu_cnt, 1, ampdu_flag); - DP_STATS_INCC(peer, rx.non_ampdu_cnt, 1, !(ampdu_flag)); - } - - amsdu_flag = ((msdu_desc_info.msdu_flags & - HAL_MSDU_F_FIRST_MSDU_IN_MPDU) && - (msdu_desc_info.msdu_flags & - HAL_MSDU_F_LAST_MSDU_IN_MPDU)); - - DP_STATS_INCC(peer, rx.non_amsdu_cnt, 1, - amsdu_flag); - DP_STATS_INCC(peer, rx.amsdu_cnt, 1, - !(amsdu_flag)); - - DP_HIST_PACKET_COUNT_INC(vdev->pdev->pdev_id); DP_RX_LIST_APPEND(nbuf_head, nbuf_tail, rx_desc->nbuf); -fail: + /* * if continuation bit is set then we have MSDU spread * across multiple buffers, let us not decrement quota @@ -1307,15 +1401,35 @@ done: if (qdf_likely(peer != NULL)) vdev = NULL; + /* + * BIG loop where each nbuf is dequeued from global queue, + * processed and queued back on a per vdev basis. These nbufs + * are sent to stack as and when we run out of nbufs + * or a new nbuf dequeued from global queue has a different + * vdev when compared to previous nbuf. + */ nbuf = nbuf_head; while (nbuf) { next = nbuf->next; rx_tlv_hdr = qdf_nbuf_data(nbuf); + /* + * Check if DMA completed -- msdu_done is the last bit + * to be written + */ + if (qdf_unlikely(!hal_rx_attn_msdu_done_get(rx_tlv_hdr))) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("MSDU DONE failure")); + hal_rx_dump_pkt_tlvs(rx_tlv_hdr, QDF_TRACE_LEVEL_INFO); + qdf_assert(0); + } + peer_mdata = hal_rx_mpdu_peer_meta_data_get(rx_tlv_hdr); peer_id = DP_PEER_METADATA_PEER_ID_GET(peer_mdata); peer = dp_peer_find_by_id(soc, peer_id); + rx_bufs_used++; + if (deliver_list_head && peer && (vdev != peer->vdev)) { dp_rx_deliver_to_stack(vdev, peer, deliver_list_head); deliver_list_head = NULL; @@ -1337,21 +1451,7 @@ done: continue; } - /* - * Check if DMA completed -- msdu_done is the last bit - * to be written - */ - if (!hal_rx_attn_msdu_done_get(rx_tlv_hdr)) { - - QDF_TRACE(QDF_MODULE_ID_DP, - QDF_TRACE_LEVEL_ERROR, - FL("MSDU DONE failure")); - DP_STATS_INC(vdev->pdev, dropped.msdu_not_done, - 1); - hal_rx_dump_pkt_tlvs(rx_tlv_hdr, QDF_TRACE_LEVEL_INFO); - qdf_assert(0); - } - + DP_HIST_PACKET_COUNT_INC(vdev->pdev->pdev_id); /* * The below condition happens when an MSDU is spread * across multiple buffers. This can happen in two cases @@ -1390,7 +1490,7 @@ done: } if (!dp_wds_rx_policy_check(rx_tlv_hdr, vdev, peer, - hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr))) { + hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr))) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("Policy Check Drop pkt")); @@ -1414,8 +1514,6 @@ done: continue; } - pdev = vdev->pdev; - if (qdf_unlikely(peer && (peer->nawds_enabled == true) && (hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr)) && (hal_rx_get_mpdu_mac_ad4_valid(rx_tlv_hdr) == false))) { @@ -1426,91 +1524,9 @@ done: continue; } - if (qdf_likely( - !hal_rx_attn_tcp_udp_cksum_fail_get(rx_tlv_hdr) - && - !hal_rx_attn_ip_cksum_fail_get(rx_tlv_hdr))) { - qdf_nbuf_rx_cksum_t cksum = {0}; + dp_rx_cksum_offload(nbuf, rx_tlv_hdr); - cksum.l4_result = - QDF_NBUF_RX_CKSUM_TCP_UDP_UNNECESSARY; - - qdf_nbuf_set_rx_cksum(nbuf, &cksum); - } - - if (soc->process_rx_status) { - sgi = hal_rx_msdu_start_sgi_get(rx_tlv_hdr); - mcs = hal_rx_msdu_start_rate_mcs_get(rx_tlv_hdr); - tid = hal_rx_mpdu_start_tid_get(rx_tlv_hdr); - - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "%s: %d, SGI: %d, tid: %d", - __func__, __LINE__, sgi, tid); - - bw = hal_rx_msdu_start_bw_get(rx_tlv_hdr); - reception_type = hal_rx_msdu_start_reception_type_get( - rx_tlv_hdr); - nss = hal_rx_msdu_start_nss_get(rx_tlv_hdr); - pkt_type = hal_rx_msdu_start_get_pkt_type(rx_tlv_hdr); - - DP_STATS_INC(peer, rx.nss[nss], 1); - - DP_STATS_INCC(peer, rx.err.mic_err, 1, - hal_rx_mpdu_end_mic_err_get( - rx_tlv_hdr)); - - DP_STATS_INCC(peer, rx.err.decrypt_err, 1, - hal_rx_mpdu_end_decrypt_err_get( - rx_tlv_hdr)); - - DP_STATS_INC(peer, rx.reception_type[reception_type], - 1); - DP_STATS_INC(peer, rx.bw[bw], 1); - DP_STATS_INC(peer, rx.sgi_count[sgi], 1); - DP_STATS_INCC(peer, rx.pkt_type[pkt_type]. - mcs_count[MAX_MCS - 1], 1, - ((mcs >= MAX_MCS_11A) && - (pkt_type == DOT11_A))); - DP_STATS_INCC(peer, rx.pkt_type[pkt_type]. - mcs_count[mcs], 1, - ((mcs < MAX_MCS_11A) && - (pkt_type == DOT11_A))); - DP_STATS_INCC(peer, rx.pkt_type[pkt_type]. - mcs_count[MAX_MCS - 1], 1, - ((mcs >= MAX_MCS_11B) && - (pkt_type == DOT11_B))); - DP_STATS_INCC(peer, rx.pkt_type[pkt_type]. - mcs_count[mcs], 1, - ((mcs < MAX_MCS_11B) && - (pkt_type == DOT11_B))); - DP_STATS_INCC(peer, rx.pkt_type[pkt_type]. - mcs_count[MAX_MCS - 1], 1, - ((mcs >= MAX_MCS_11A) && - (pkt_type == DOT11_N))); - DP_STATS_INCC(peer, rx.pkt_type[pkt_type]. - mcs_count[mcs], 1, - ((mcs < MAX_MCS_11A) && - (pkt_type == DOT11_N))); - DP_STATS_INCC(peer, rx.pkt_type[pkt_type]. - mcs_count[MAX_MCS - 1], 1, - ((mcs >= MAX_MCS_11AC) && - (pkt_type == DOT11_AC))); - DP_STATS_INCC(peer, rx.pkt_type[pkt_type]. - mcs_count[mcs], 1, - ((mcs < MAX_MCS_11AC) && - (pkt_type == DOT11_AC))); - DP_STATS_INCC(peer, rx.pkt_type[pkt_type]. - mcs_count[MAX_MCS - 1], 1, - ((mcs >= (MAX_MCS - 1)) && - (pkt_type == DOT11_AX))); - DP_STATS_INCC(peer, rx.pkt_type[pkt_type]. - mcs_count[mcs], 1, - ((mcs < (MAX_MCS - 1)) && - (pkt_type == DOT11_AX))); - - DP_STATS_INC(peer, rx.wme_ac_type[TID_TO_WME_AC(tid)], - 1); - } + dp_rx_msdu_stats_update(soc, nbuf, rx_tlv_hdr, peer, ring_id); /* * HW structures call this L3 header padding -- @@ -1584,43 +1600,15 @@ done: } } - rx_bufs_used++; - dp_rx_lro(rx_tlv_hdr, peer, nbuf, int_ctx->lro_ctx); DP_RX_LIST_APPEND(deliver_list_head, deliver_list_tail, nbuf); - DP_STATS_INCC_PKT(peer, rx.multicast, 1, qdf_nbuf_len(nbuf), - hal_rx_msdu_end_da_is_mcbc_get( - rx_tlv_hdr)); - DP_STATS_INC_PKT(peer, rx.to_stack, 1, qdf_nbuf_len(nbuf)); - if (qdf_unlikely(hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr) && - (vdev->rx_decap_type == - htt_cmn_pkt_type_ethernet))) { - eh = (struct ether_header *)qdf_nbuf_data(nbuf); - isBroadcast = (IEEE80211_IS_BROADCAST - (eh->ether_dhost)) ? 1 : 0 ; - if (isBroadcast) { - DP_STATS_INC_PKT(peer, rx.bcast, 1, - qdf_nbuf_len(nbuf)); - } - } - - if ((soc->process_rx_status) && likely(peer) && - hal_rx_attn_first_mpdu_get(rx_tlv_hdr)) { - if (soc->cdp_soc.ol_ops->update_dp_stats) { - soc->cdp_soc.ol_ops->update_dp_stats( - vdev->pdev->osif_pdev, - &peer->stats, - peer_id, - UPDATE_PEER_STATS); - } - } nbuf = next; } diff --git a/dp/wifi3.0/hal_rx.h b/dp/wifi3.0/hal_rx.h index 3d286bdffe39..4b6d403f7937 100644 --- a/dp/wifi3.0/hal_rx.h +++ b/dp/wifi3.0/hal_rx.h @@ -827,6 +827,33 @@ hal_rx_mpdu_peer_meta_data_get(uint8_t *buf) return peer_meta_data; } +#define HAL_RX_MPDU_INFO_AMPDU_FLAG_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_12_AMPDU_FLAG_OFFSET)), \ + RX_MPDU_INFO_12_AMPDU_FLAG_MASK, \ + RX_MPDU_INFO_12_AMPDU_FLAG_LSB)) +/** + * hal_rx_mpdu_info_ampdu_flag_get(): get ampdu flag bit + * from rx mpdu info + * @buf: pointer to rx_pkt_tlvs + * + * Return: ampdu flag + */ +static inline bool +hal_rx_mpdu_info_ampdu_flag_get(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + bool ampdu_flag; + + ampdu_flag = HAL_RX_MPDU_INFO_AMPDU_FLAG_GET(mpdu_info); + + return ampdu_flag; +} + #define HAL_RX_MPDU_PEER_META_DATA_SET(_rx_mpdu_info, peer_mdata) \ ((*(((uint32_t *)_rx_mpdu_info) + \ (RX_MPDU_INFO_8_PEER_META_DATA_OFFSET >> 2))) = \