From a0f09eae1df8c03ce61dfa8a3d87336a92bfb9f9 Mon Sep 17 00:00:00 2001 From: Karunakar Dasineni Date: Mon, 21 Nov 2016 17:41:31 -0800 Subject: [PATCH] qcacmn: REO management changes Changes to use REO HW command/status interface to update/delete REO queues. Change-Id: I3500d45db021ef314b4d03fa878314d407ddfe65 --- dp/wifi3.0/dp_internal.h | 9 +++ dp/wifi3.0/dp_main.c | 5 ++ dp/wifi3.0/dp_peer.c | 171 +++++++++++++++++++++++++++++++-------- dp/wifi3.0/dp_rx_err.c | 21 +++++ dp/wifi3.0/dp_types.h | 1 + dp/wifi3.0/hal_rx.h | 69 ++++++++++++++++ hal/wifi3.0/hal_api.h | 61 ++++++++++---- 7 files changed, 290 insertions(+), 47 deletions(-) diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index a1273e7049..1f4b41442d 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -90,4 +90,13 @@ extern void dp_addba_responsesetup_wifi3(void *peer_handle, uint8_t tid, uint16_t *buffersize, uint16_t *batimeout); extern int dp_delba_process_wifi3(void *peer_handle, int tid, uint16_t reasoncode); + +extern int dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid, + uint32_t ba_window_size, uint32_t start_seq); + +extern QDF_STATUS dp_reo_send_cmd(struct dp_soc *soc, + enum hal_reo_cmd_type type, struct hal_reo_cmd_params *params, + void (*callback_fn), void *data); + +extern void dp_reo_status_ring_handler(struct dp_soc *soc); #endif /* #ifndef _DP_INTERNAL_H_ */ diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 71a2580f42..8e289158b6 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -140,6 +140,7 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) uint8_t rx_mask = int_ctx->rx_ring_mask; uint8_t rx_err_mask = int_ctx->rx_err_ring_mask; uint8_t rx_wbm_rel_mask = int_ctx->rx_wbm_rel_ring_mask; + uint8_t reo_status_mask = int_ctx->reo_status_ring_mask; /* Process Tx completion interrupts first to return back buffers */ if (tx_mask) { @@ -211,6 +212,9 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) } } + if (reo_status_mask) + dp_reo_status_ring_handler(soc); + budget_done: return dp_budget - budget; } @@ -255,6 +259,7 @@ static QDF_STATUS dp_soc_interrupt_attach(void *txrx_soc) soc->intr_ctx[i].rx_mon_ring_mask = 0xF; soc->intr_ctx[i].rx_err_ring_mask = 0x1; soc->intr_ctx[i].rx_wbm_rel_ring_mask = 0x1; + soc->intr_ctx[i].reo_status_ring_mask = 0x1; soc->intr_ctx[i].soc = soc; } diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 64cfd88b7c..f709c9039a 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -23,6 +23,7 @@ #include "dp_internal.h" #include "dp_peer.h" #include +#include /* Temporary definitions to be moved to wlan_cfg */ static inline uint32_t wlan_cfg_max_peer_id(void *wlan_cfg_ctx) @@ -401,6 +402,91 @@ dp_peer_find_detach(struct dp_soc *soc) dp_peer_find_hash_detach(soc); } +static void dp_rx_tid_stats_cb(struct dp_soc *soc, void *cb_ctxt, + union hal_reo_status *reo_status) +{ + struct dp_rx_tid *rx_tid = (struct dp_rx_tid *)cb_ctxt; + struct hal_reo_queue_status *queue_status = &(reo_status->queue_status); + + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%s: rx_tid: %d status: %d\n", __func__, + rx_tid->tid, queue_status->header.status); + + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "REO queue stats: \n" + "ssn: %d\n" + "curr_idx : %d\n" + "pn_31_0 : %08x\n" + "pn_63_32 : %08x\n" + "pn_95_64 : %08x\n" + "pn_127_96 : %08x\n" + "last_rx_enq_tstamp : %08x\n" + "last_rx_deq_tstamp : %08x\n" + "rx_bitmap_31_0 : %08x\n" + "rx_bitmap_63_32 : %08x\n" + "rx_bitmap_95_64 : %08x\n" + "rx_bitmap_127_96 : %08x\n" + "rx_bitmap_159_128 : %08x\n" + "rx_bitmap_191_160 : %08x\n" + "rx_bitmap_223_192 : %08x\n" + "rx_bitmap_255_224 : %08x\n" + "curr_mpdu_cnt : %d\n" + "curr_msdu_cnt : %d\n" + "fwd_timeout_cnt : %d\n" + "fwd_bar_cnt : %d\n" + "dup_cnt : %d\n" + "frms_in_order_cnt : %d\n" + "bar_rcvd_cnt : %d\n" + "mpdu_frms_cnt : %d\n" + "msdu_frms_cnt : %d\n" + "total_cnt : %d\n" + "late_recv_mpdu_cnt : %d\n" + "win_jump_2k : %d\n" + "hole_cnt : %d\n", + queue_status->ssn, queue_status->curr_idx, + queue_status->pn_31_0, queue_status->pn_63_32, + queue_status->pn_95_64, queue_status->pn_127_96, + queue_status->last_rx_enq_tstamp, + queue_status->last_rx_deq_tstamp, + queue_status->rx_bitmap_31_0, queue_status->rx_bitmap_63_32, + queue_status->rx_bitmap_95_64, queue_status->rx_bitmap_127_96, + queue_status->rx_bitmap_159_128, + queue_status->rx_bitmap_191_160, + queue_status->rx_bitmap_223_192, + queue_status->rx_bitmap_255_224, + queue_status->curr_mpdu_cnt, queue_status->curr_msdu_cnt, + queue_status->fwd_timeout_cnt, queue_status->fwd_bar_cnt, + queue_status->dup_cnt, queue_status->frms_in_order_cnt, + queue_status->bar_rcvd_cnt, queue_status->mpdu_frms_cnt, + queue_status->msdu_frms_cnt, queue_status->total_cnt, + queue_status->late_recv_mpdu_cnt, queue_status->win_jump_2k, + queue_status->hole_cnt); +} + +static void dp_rx_tid_update_cb(struct dp_soc *soc, void *cb_ctxt, + union hal_reo_status *reo_status) +{ + struct dp_rx_tid *rx_tid = (struct dp_rx_tid *)cb_ctxt; + struct hal_reo_cmd_params params; + + if (reo_status->queue_status.header.status) { + /* Should not happen normally. Just print error for now */ + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%s: Rx tid HW desc update failed(%d): tid %d\n", + __func__, + reo_status->rx_queue_status.header.status, + rx_tid->tid); + } + + qdf_mem_zero(¶ms, sizeof(params)); + + params.std.need_status = 1; + params.std.addr_lo = rx_tid->hw_qdesc_paddr & 0xffffffff; + params.std.addr_hi = (uint64_t)(rx_tid->hw_qdesc_paddr) >> 32; + + dp_reo_send_cmd(soc, CMD_GET_QUEUE_STATS, ¶ms, dp_rx_tid_stats_cb, rx_tid); +} + /* * dp_find_peer_by_addr - find peer instance by mac address * @dev: physical device instance @@ -442,7 +528,24 @@ void *dp_find_peer_by_addr(void *dev, uint8_t *peer_mac_addr, static int dp_rx_tid_update_wifi3(struct dp_peer *peer, int tid, uint32_t ba_window_size, uint32_t start_seq) { - /* TODO: Implement this once REO command API is available */ + struct dp_rx_tid *rx_tid = &peer->rx_tid[tid]; + struct dp_soc *soc = peer->vdev->pdev->soc; + struct hal_reo_cmd_params params; + + qdf_mem_zero(¶ms, sizeof(params)); + + params.std.need_status = 1; + params.std.addr_lo = rx_tid->hw_qdesc_paddr & 0xffffffff; + params.std.addr_hi = (uint64_t)(rx_tid->hw_qdesc_paddr) >> 32; + params.u.upd_queue_params.update_ba_window_size = 1; + params.u.upd_queue_params.ba_window_size = ba_window_size; + + if (start_seq < IEEE80211_SEQ_MAX) { + params.u.upd_queue_params.update_ssn = 1; + params.u.upd_queue_params.ssn = start_seq; + } + + dp_reo_send_cmd(soc, CMD_UPDATE_RX_REO_QUEUE, ¶ms, dp_rx_tid_update_cb, rx_tid); return 0; } @@ -455,7 +558,7 @@ static int dp_rx_tid_update_wifi3(struct dp_peer *peer, int tid, uint32_t * * Return: 0 on success, error code on failure */ -static int dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid, +int dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid, uint32_t ba_window_size, uint32_t start_seq) { struct dp_rx_tid *rx_tid = &peer->rx_tid[tid]; @@ -570,42 +673,34 @@ static int dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid, peer->vdev->vdev_id, peer->mac_addr.raw, rx_tid->hw_qdesc_paddr, tid, tid); - if (tid == DP_NON_QOS_TID) { - /* TODO: Setting up default queue - currently using - * same queue for BE and non-qos traffic till BA - * session is setup. Check if there are any HW - * restrictions and also if this can be done for - * all other TIDs - */ - soc->cdp_soc.ol_ops-> - peer_rx_reorder_queue_setup(soc->osif_soc, - peer->vdev->vdev_id, peer->mac_addr.raw, - rx_tid->hw_qdesc_paddr, 0, tid); - } } return 0; } -#ifdef notyet /* TBD: Enable this once REO command interface is available */ /* * Rx TID deletion callback to free memory allocated for HW queue descriptor */ -static void dp_rx_tid_delete_cb(struct dp_pdev *pdev, void *cb_ctxt, int status) +static void dp_rx_tid_delete_cb(struct dp_soc *soc, void *cb_ctxt, + union hal_reo_status *reo_status) { - struct dp_soc *soc = pdev->soc; struct dp_rx_tid *rx_tid = (struct dp_rx_tid *)cb_ctxt; - if (status) { + if (reo_status->rx_queue_status.header.status) { /* Should not happen normally. Just print error for now */ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, - "%s: Rx tid HW desc deletion failed: tid %d\n", - __func__, rx_tid->tid); + "%s: Rx tid HW desc deletion failed(%d): tid %d\n", + __func__, + reo_status->rx_queue_status.header.status, + rx_tid->tid); } + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "%s: rx_tid: %d status: %d\n", __func__, + rx_tid->tid, reo_status->rx_queue_status.header.status); qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, - rx_tid->hw_qdesc_alloc_size, - rx_tid->hw_qdesc_vaddr_unaligned, - rx_tid->hw_qdesc_paddr_unaligned, 0); + rx_tid->hw_qdesc_alloc_size, + rx_tid->hw_qdesc_vaddr_unaligned, + rx_tid->hw_qdesc_paddr_unaligned, 0); rx_tid->hw_qdesc_vaddr_unaligned = NULL; rx_tid->hw_qdesc_alloc_size = 0; @@ -620,17 +715,22 @@ static void dp_rx_tid_delete_cb(struct dp_pdev *pdev, void *cb_ctxt, int status) */ static int dp_rx_tid_delete_wifi3(struct dp_peer *peer, int tid) { - struct dp_rx_tid *rx_tid = peer->rx_tid[tid]; - dp_rx_tid_hw_update_valid(rx_tid->hw_qdesc_paddr, 0, + struct dp_rx_tid *rx_tid = &(peer->rx_tid[tid]); + struct dp_soc *soc = peer->vdev->pdev->soc; + struct hal_reo_cmd_params params; + + qdf_mem_zero(¶ms, sizeof(params)); + + params.std.need_status = 1; + params.std.addr_lo = rx_tid->hw_qdesc_paddr & 0xffffffff; + params.std.addr_hi = (uint64_t)(rx_tid->hw_qdesc_paddr) >> 32; + params.u.upd_queue_params.update_vld = 1; + params.u.upd_queue_params.vld = 0; + + dp_reo_send_cmd(soc, CMD_UPDATE_RX_REO_QUEUE, ¶ms, dp_rx_tid_delete_cb, (void *)rx_tid); return 0; } -#else -static int dp_rx_tid_delete_wifi3(struct dp_peer *peer, int tid) -{ - return 0; -} -#endif /* * dp_peer_rx_init() – Initialize receive TID state @@ -663,6 +763,12 @@ void dp_peer_rx_init(struct dp_pdev *pdev, struct dp_peer *peer) /* Setup default (non-qos) rx tid queue */ dp_rx_tid_setup_wifi3(peer, DP_NON_QOS_TID, 1, 0); + /* Setup rx tid queue for TID 0. + * Other queues will be setup on receiving first packet, which will cause + * NULL REO queue error + */ + dp_rx_tid_setup_wifi3(peer, 0, 1, 0); + /* * Set security defaults: no PN check, no security. The target may * send a HTT SEC_IND message to overwrite these defaults. @@ -680,10 +786,9 @@ void dp_peer_rx_init(struct dp_pdev *pdev, struct dp_peer *peer) void dp_peer_rx_cleanup(struct dp_vdev *vdev, struct dp_peer *peer) { int tid; - struct dp_rx_tid *rx_tid; uint32_t tid_delete_mask = 0; for (tid = 0; tid < DP_MAX_TIDS; tid++) { - if (rx_tid->hw_qdesc_vaddr_unaligned != NULL) { + if (peer->rx_tid[tid].hw_qdesc_vaddr_unaligned != NULL) { dp_rx_tid_delete_wifi3(peer, tid); tid_delete_mask |= (1 << tid); } diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index d67e200036..8322bb3384 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -19,9 +19,11 @@ #include "dp_types.h" #include "dp_rx.h" #include "dp_peer.h" +#include "dp_internal.h" #include "hal_api.h" #include "qdf_trace.h" #include "qdf_nbuf.h" +#include /** * dp_rx_cookie_2_link_desc_va() - Converts cookie to a virtual address of @@ -254,6 +256,9 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, void *ring_desc, qdf_nbuf_t nbuf; struct dp_pdev *pdev0; struct dp_vdev *vdev0; + uint32_t tid = 0; + uint16_t peer_id; + struct dp_peer *peer = NULL; rx_buf_cookie = HAL_RX_WBM_BUF_COOKIE_GET(ring_desc); @@ -300,6 +305,22 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, void *ring_desc, if (l2_hdr_offset) qdf_nbuf_pull_head(nbuf, l2_hdr_offset); + if (hal_rx_mpdu_start_mpdu_qos_control_valid_get( + rx_desc->rx_buf_start)) { + /* TODO: Assuming that qos_control_valid also indicates + * unicast. Should we check this? + */ + tid = hal_rx_mpdu_start_tid_get(rx_desc->rx_buf_start); + peer_id = hal_rx_mpdu_start_sw_peer_id_get( + rx_desc->rx_buf_start); + peer = dp_peer_find_by_id(soc, peer_id); + if (peer && + peer->rx_tid[tid].hw_qdesc_vaddr_unaligned == NULL) { + /* IEEE80211_SEQ_MAX indicates invalid start_seq */ + dp_rx_tid_setup_wifi3(peer, tid, 1, IEEE80211_SEQ_MAX); + } + } + pdev0 = soc->pdev_list[0];/* Hard code 0th elem */ if (pdev0) { diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 5ea57653ee..9d8ac9cecf 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -249,6 +249,7 @@ struct dp_intr { uint8_t rx_mon_ring_mask; /* Rx monitor ring mask (0-2) */ uint8_t rx_err_ring_mask; /* REO Exception Ring */ uint8_t rx_wbm_rel_ring_mask; /* WBM2SW Rx Release Ring */ + uint8_t reo_status_ring_mask; /* REO command response ring */ struct dp_soc *soc; /* Reference to SoC structure , to get DMA ring handles */ }; diff --git a/dp/wifi3.0/hal_rx.h b/dp/wifi3.0/hal_rx.h index 492b713f82..b0b9c294ce 100644 --- a/dp/wifi3.0/hal_rx.h +++ b/dp/wifi3.0/hal_rx.h @@ -631,6 +631,75 @@ hal_rx_msdu_start_msdu_len_get(uint8_t *buf) return msdu_len; } +/* + * Get qos_control_valid from RX_MPDU_START + */ +#define HAL_RX_MPDU_INFO_QOS_CONTROL_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_LSB)) + +static inline uint32_t +hal_rx_mpdu_start_mpdu_qos_control_valid_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; + uint32_t qos_control_valid; + + qos_control_valid = HAL_RX_MPDU_INFO_QOS_CONTROL_VALID_GET( + &(mpdu_start->rx_mpdu_info_details)); + + return qos_control_valid; +} + +/* + * Get tid from RX_MPDU_START + */ +#define HAL_RX_MPDU_INFO_TID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_3_TID_OFFSET)), \ + RX_MPDU_INFO_3_TID_MASK, \ + RX_MPDU_INFO_3_TID_LSB)) + +static inline uint32_t +hal_rx_mpdu_start_tid_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; + uint32_t tid; + + tid = HAL_RX_MPDU_INFO_TID_GET( + &(mpdu_start->rx_mpdu_info_details)); + + return tid; +} + +/* + * Get SW peer id from RX_MPDU_START + */ +#define HAL_RX_MPDU_INFO_SW_PEER_ID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_1_SW_PEER_ID_OFFSET)), \ + RX_MPDU_INFO_1_SW_PEER_ID_MASK, \ + RX_MPDU_INFO_1_SW_PEER_ID_LSB)) + +static inline uint32_t +hal_rx_mpdu_start_sw_peer_id_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; + uint32_t sw_peer_id; + + sw_peer_id = HAL_RX_MPDU_INFO_SW_PEER_ID_GET( + &(mpdu_start->rx_mpdu_info_details)); + + return sw_peer_id; +} + /******************************************************************************* * RX ERROR APIS ******************************************************************************/ diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 20652c50c7..130c81aeb4 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2017, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -210,15 +210,22 @@ static inline int hal_srng_access_start(void *hal_soc, void *hal_ring) static inline void *hal_srng_dst_get_next(void *hal_soc, void *hal_ring) { struct hal_srng *srng = (struct hal_srng *)hal_ring; - uint32_t *desc = &(srng->ring_base_vaddr[srng->u.dst_ring.tp]); + volatile uint32_t *desc = &(srng->ring_base_vaddr[srng->u.dst_ring.tp]); uint32_t desc_loop_cnt; desc_loop_cnt = (desc[srng->entry_size - 1] & SRNG_LOOP_CNT_MASK) >> SRNG_LOOP_CNT_LSB; if (srng->u.dst_ring.loop_cnt == desc_loop_cnt) { - srng->u.dst_ring.tp = (srng->u.dst_ring.tp + srng->entry_size) & - srng->ring_size_mask; + /* TODO: Using % is expensive, but we have to do this since + * size of some SRNG rings is not power of 2 (due to descriptor + * sizes). Need to create separate API for rings used + * per-packet, with sizes power of 2 (TCL2SW, REO2SW, + * SW2RXDMA and CE rings) + */ + srng->u.dst_ring.tp = (srng->u.dst_ring.tp + srng->entry_size) % + srng->ring_size; + srng->u.dst_ring.loop_cnt = (srng->u.dst_ring.loop_cnt + !srng->u.dst_ring.tp) & (SRNG_LOOP_CNT_MASK >> SRNG_LOOP_CNT_LSB); @@ -298,8 +305,15 @@ static inline void *hal_srng_src_reap_next(void *hal_soc, void *hal_ring) { struct hal_srng *srng = (struct hal_srng *)hal_ring; uint32_t *desc; - uint32_t next_reap_hp = (srng->u.src_ring.reap_hp + srng->entry_size) & - srng->ring_size_mask; + + /* TODO: Using % is expensive, but we have to do this since + * size of some SRNG rings is not power of 2 (due to descriptor + * sizes). Need to create separate API for rings used + * per-packet, with sizes power of 2 (TCL2SW, REO2SW, + * SW2RXDMA and CE rings) + */ + uint32_t next_reap_hp = (srng->u.src_ring.reap_hp + srng->entry_size) % + srng->ring_size; if (next_reap_hp != srng->u.src_ring.cached_tp) { desc = &(srng->ring_base_vaddr[next_reap_hp]); @@ -327,8 +341,9 @@ static inline void *hal_srng_src_get_next_reaped(void *hal_soc, void *hal_ring) if (srng->u.src_ring.hp != srng->u.src_ring.reap_hp) { desc = &(srng->ring_base_vaddr[srng->u.src_ring.hp]); - srng->u.src_ring.hp = (srng->u.src_ring.hp + srng->entry_size) & - srng->ring_size_mask; + srng->u.src_ring.hp = (srng->u.src_ring.hp + srng->entry_size) % + srng->ring_size; + return (void *)desc; } @@ -346,8 +361,14 @@ static inline void *hal_srng_src_get_next_reaped(void *hal_soc, void *hal_ring) static inline uint32_t hal_srng_src_done_val(void *hal_soc, void *hal_ring) { struct hal_srng *srng = (struct hal_srng *)hal_ring; - uint32_t next_reap_hp = (srng->u.src_ring.reap_hp + srng->entry_size) & - srng->ring_size_mask; + /* TODO: Using % is expensive, but we have to do this since + * size of some SRNG rings is not power of 2 (due to descriptor + * sizes). Need to create separate API for rings used + * per-packet, with sizes power of 2 (TCL2SW, REO2SW, + * SW2RXDMA and CE rings) + */ + uint32_t next_reap_hp = (srng->u.src_ring.reap_hp + srng->entry_size) % + srng->ring_size; if (next_reap_hp == srng->u.src_ring.cached_tp) return 0; @@ -371,8 +392,14 @@ static inline void *hal_srng_src_get_next(void *hal_soc, void *hal_ring) { struct hal_srng *srng = (struct hal_srng *)hal_ring; uint32_t *desc; - uint32_t next_hp = (srng->u.src_ring.hp + srng->entry_size) & - srng->ring_size_mask; + /* TODO: Using % is expensive, but we have to do this since + * size of some SRNG rings is not power of 2 (due to descriptor + * sizes). Need to create separate API for rings used + * per-packet, with sizes power of 2 (TCL2SW, REO2SW, + * SW2RXDMA and CE rings) + */ + uint32_t next_hp = (srng->u.src_ring.hp + srng->entry_size) % + srng->ring_size; if (next_hp != srng->u.src_ring.cached_tp) { desc = &(srng->ring_base_vaddr[srng->u.src_ring.hp]); @@ -403,8 +430,14 @@ static inline void *hal_srng_src_peek(void *hal_soc, void *hal_ring) struct hal_srng *srng = (struct hal_srng *)hal_ring; uint32_t *desc; - if (((srng->u.src_ring.hp + srng->entry_size) & - srng->ring_size_mask) != srng->u.src_ring.cached_tp) { + /* TODO: Using % is expensive, but we have to do this since + * size of some SRNG rings is not power of 2 (due to descriptor + * sizes). Need to create separate API for rings used + * per-packet, with sizes power of 2 (TCL2SW, REO2SW, + * SW2RXDMA and CE rings) + */ + if (((srng->u.src_ring.hp + srng->entry_size) % + srng->ring_size) != srng->u.src_ring.cached_tp) { desc = &(srng->ring_base_vaddr[srng->u.src_ring.hp]); return (void *)desc; }