From 1cb78177e6431fa77a7e5d377436e55876813e8b Mon Sep 17 00:00:00 2001 From: Jinwei Chen Date: Tue, 12 Feb 2019 12:36:10 +0800 Subject: [PATCH] qcacmn: Fix REO entry potential overwrite issue Host SW should not update the cached TP pointer to HW register before current cached TP REO entry finishes processing, otherwise there is risk if HW HP catches up to this cached TP, but HW TP value has been updated to (cached TP + one entry size) now, this TP REO entry might be overwritten. Refine it and only update TP pointer to HW when entry processing has done. Change-Id: I54df3247745717855a67649f440c606c518efd61 CRs-Fixed: 2391658 --- dp/wifi3.0/dp_rx.c | 20 +++++++++++--------- hal/wifi3.0/hal_api.h | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 832db113dd..6b64ac73bf 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -1396,6 +1396,7 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, qdf_nbuf_t deliver_list_head = NULL; qdf_nbuf_t deliver_list_tail = NULL; int32_t tid = 0; + uint32_t dst_num_valid = 0; DP_HIST_INIT(); /* Debug -- Remove later */ @@ -1443,16 +1444,17 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, * complete mpdu in one reap. */ if (qdf_unlikely(!ring_desc)) { - hal_srng_access_start_unlocked(hal_soc, hal_ring); - ring_desc = hal_srng_dst_get_next(hal_soc, hal_ring); - if (!ring_desc) + dst_num_valid = hal_srng_dst_num_valid(hal_soc, + hal_ring, + true); + if (dst_num_valid) { + DP_STATS_INC(soc, rx.hp_oos, 1); + hal_srng_access_end_unlocked(hal_soc, + hal_ring); + continue; + } else { break; - DP_STATS_INC(soc, rx.hp_oos, 1); - /* - * update TP here in case loop takes long, - * then the ring is easily full. - */ - hal_srng_access_end_unlocked(hal_soc, hal_ring); + } } error = HAL_RX_ERROR_STATUS_GET(ring_desc); diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 3d759a885f..b241761fd4 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -651,7 +651,7 @@ static inline uint32_t hal_srng_dst_num_valid(void *hal_soc, void *hal_ring, uint32_t tp = srng->u.dst_ring.tp; if (sync_hw_ptr) { - hp = *(srng->u.dst_ring.hp_addr); + hp = *(volatile uint32_t *)(srng->u.dst_ring.hp_addr); srng->u.dst_ring.cached_hp = hp; } else { hp = srng->u.dst_ring.cached_hp;