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
This commit is contained in:
Tallapragada Kalyan 2018-02-22 20:33:15 +05:30 • committed by nshrivas
commit e33a5632b8
2 changed files with 189 additions and 174 deletions

View file

@ -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;
}

View file

@ -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))) = \