From 28f1bf3f4e12dbaa460e78f5dad7fa1f61b23823 Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Mon, 13 Jul 2020 17:03:47 +0530 Subject: [PATCH] qcacmn: Invalidate ring desc cookie after processing Currently all the rx ring descriptor contents are left intact even after these entries are processed. This can, at times, lead to stale entries being processed, if the head pointer of any ring is updated before the updated contents of the ring descriptor gets reflected in the memory. This can lead to scenarios where the host driver reads a stale value of sw_cookie, and free/unmap a currently in-use buffer, thereby leading to the hardware accessing unmapped memory region. The sw_cookie is the integral part of al the rx ring processing. Hence we always mark the sw_cookie as invalid after dequeuing an entry from the REO2SW ring. Every time we check for the validity of the sw_cookie before we try to process an entry from REO2SW ring. if the invalid bit in the sw_cookie is set, we just skip this entry and move on to the next entry in the ring. Change-Id: I0e78fa662b8ba33e64687a4dee4d1a5875ddb4bf CRs-Fixed: 2730718 --- dp/wifi3.0/dp_rx.c | 3 +++ dp/wifi3.0/dp_rx.h | 18 ++++++++++++++++++ hal/wifi3.0/hal_rx.h | 28 ++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 71bf680d79..9873a2e3f6 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -2039,6 +2039,9 @@ more_data: } rx_buf_cookie = HAL_RX_REO_BUF_COOKIE_GET(ring_desc); + status = dp_rx_cookie_check_and_invalidate(ring_desc); + if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) + break; rx_desc = dp_rx_cookie_2_va_rxdma_buf(soc, rx_buf_cookie); status = dp_rx_desc_sanity(soc, hal_soc, hal_ring_hdl, diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index b09e23bedf..f452efd763 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -540,6 +540,24 @@ void *dp_rx_cookie_2_va_mon_status(struct dp_soc *soc, uint32_t cookie) } #endif /* RX_DESC_MULTI_PAGE_ALLOC */ +#ifdef DP_RX_DESC_COOKIE_INVALIDATE +static inline QDF_STATUS +dp_rx_cookie_check_and_invalidate(hal_ring_desc_t ring_desc) +{ + if (qdf_unlikely(HAL_RX_REO_BUF_COOKIE_INVALID_GET(ring_desc))) + return QDF_STATUS_E_FAILURE; + + HAL_RX_REO_BUF_COOKIE_INVALID_SET(ring_desc); + return QDF_STATUS_SUCCESS; +} +#else +static inline QDF_STATUS +dp_rx_cookie_check_and_invalidate(hal_ring_desc_t ring_desc) +{ + return QDF_STATUS_SUCCESS; +} +#endif + QDF_STATUS dp_rx_desc_pool_is_allocated(struct rx_desc_pool *rx_desc_pool); QDF_STATUS dp_rx_desc_pool_alloc(struct dp_soc *soc, uint32_t pool_size, diff --git a/hal/wifi3.0/hal_rx.h b/hal/wifi3.0/hal_rx.h index a9efc7fa4a..f39a480dc4 100644 --- a/hal/wifi3.0/hal_rx.h +++ b/hal/wifi3.0/hal_rx.h @@ -228,6 +228,24 @@ enum hal_rx_ret_buf_manager { (paddr_hi << BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_LSB) & \ BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_MASK) +#define HAL_RX_COOKIE_INVALID_MASK 0x80000000 + +/* + * macro to get the invalid bit for sw cookie + */ +#define HAL_RX_BUF_COOKIE_INVALID_GET(buff_addr_info) \ + ((*(((unsigned int *)buff_addr_info) + \ + (BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_OFFSET >> 2))) & \ + HAL_RX_COOKIE_INVALID_MASK) + +/* + * macro to set the invalid bit for sw cookie + */ +#define HAL_RX_BUF_COOKIE_INVALID_SET(buff_addr_info) \ + ((*(((unsigned int *)buff_addr_info) + \ + (BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_OFFSET >> 2))) |= \ + HAL_RX_COOKIE_INVALID_MASK) + /* * macro to set the cookie into the rxdma ring entry */ @@ -294,6 +312,16 @@ enum hal_rx_ret_buf_manager { (((struct reo_destination_ring *) \ reo_desc)->buf_or_link_desc_addr_info))) +#define HAL_RX_REO_BUF_COOKIE_INVALID_GET(reo_desc) \ + (HAL_RX_BUF_COOKIE_INVALID_GET(& \ + (((struct reo_destination_ring *) \ + reo_desc)->buf_or_link_desc_addr_info))) + +#define HAL_RX_REO_BUF_COOKIE_INVALID_SET(reo_desc) \ + (HAL_RX_BUF_COOKIE_INVALID_SET(& \ + (((struct reo_destination_ring *) \ + reo_desc)->buf_or_link_desc_addr_info))) + #define HAL_RX_REO_BUF_COOKIE_GET(reo_desc) \ (HAL_RX_BUF_COOKIE_GET(& \ (((struct reo_destination_ring *) \