diff --git a/hif/src/ce/ce_service_srng.c b/hif/src/ce/ce_service_srng.c index 6fb9ed2bc45b..7ba93309b30f 100644 --- a/hif/src/ce/ce_service_srng.c +++ b/hif/src/ce/ce_service_srng.c @@ -417,7 +417,7 @@ ce_completed_recv_next_nolock_srng(struct CE_state *CE_state, unsigned int nentries_mask = dest_ring->nentries_mask; unsigned int sw_index = dest_ring->sw_index; struct hif_softc *scn = CE_state->scn; - struct ce_srng_dest_status_desc *dest_status; + struct ce_srng_dest_status_desc *dest_status = NULL; int nbytes; struct ce_srng_dest_status_desc dest_status_info; @@ -426,13 +426,13 @@ ce_completed_recv_next_nolock_srng(struct CE_state *CE_state, goto done; } - dest_status = hal_srng_dst_get_next(scn->hal_soc, - status_ring->srng_ctx); - + dest_status = hal_srng_dst_peek(scn->hal_soc, status_ring->srng_ctx); if (!dest_status) { status = QDF_STATUS_E_FAILURE; + hal_srng_access_end_reap(scn->hal_soc, status_ring->srng_ctx); goto done; } + /* * By copying the dest_desc_info element to local memory, we could * avoid extra memory read from non-cachable memory. @@ -440,16 +440,28 @@ ce_completed_recv_next_nolock_srng(struct CE_state *CE_state, dest_status_info = *dest_status; nbytes = dest_status_info.nbytes; if (nbytes == 0) { + uint32_t hp, tp; + /* * This closes a relatively unusual race where the Host * sees the updated DRRI before the update to the * corresponding descriptor has completed. We treat this * as a descriptor that is not yet done. */ + hal_get_sw_hptp(scn->hal_soc, status_ring->srng_ctx, + &hp, &tp); + hif_info("No data to reap, hp %d tp %d", hp, tp); status = QDF_STATUS_E_FAILURE; + hal_srng_access_end_reap(scn->hal_soc, status_ring->srng_ctx); goto done; } + /* + * Move the tail pointer since nbytes is non-zero and + * this entry is processed. + */ + hal_srng_dst_get_next(scn->hal_soc, status_ring->srng_ctx); + dest_status->nbytes = 0; *nbytesp = nbytes; @@ -474,25 +486,22 @@ ce_completed_recv_next_nolock_srng(struct CE_state *CE_state, dest_ring->sw_index = sw_index; status = QDF_STATUS_SUCCESS; -done: hal_srng_access_end(scn->hal_soc, status_ring->srng_ctx); + hif_record_ce_srng_desc_event(scn, CE_state->id, + HIF_CE_DEST_RING_BUFFER_REAP, + NULL, + dest_ring-> + per_transfer_context[sw_index], + dest_ring->sw_index, nbytes, + dest_ring->srng_ctx); - if (status == QDF_STATUS_SUCCESS) { - hif_record_ce_srng_desc_event(scn, CE_state->id, - HIF_CE_DEST_RING_BUFFER_REAP, - NULL, - dest_ring-> - per_transfer_context[sw_index], - dest_ring->sw_index, nbytes, - dest_ring->srng_ctx); - - hif_record_ce_srng_desc_event(scn, CE_state->id, - HIF_CE_DEST_STATUS_RING_REAP, - (union ce_srng_desc *)dest_status, - NULL, - -1, 0, - status_ring->srng_ctx); - } +done: + hif_record_ce_srng_desc_event(scn, CE_state->id, + HIF_CE_DEST_STATUS_RING_REAP, + (union ce_srng_desc *)dest_status, + NULL, + -1, 0, + status_ring->srng_ctx); return status; }