diff --git a/include/osi_dma.h b/include/osi_dma.h index 0b80ba4..59cf44b 100644 --- a/include/osi_dma.h +++ b/include/osi_dma.h @@ -750,6 +750,8 @@ int osi_process_tx_completions(struct osi_dma_priv_data *osi, * @param[in] osi: OSI private data structure. * @param[in] chan: Rx DMA channel number * @param[in] budget: Threshould for reading the packets at a time. + * @param[in] more_data_avail: Pointer to more data available flag. OSI fills + * this flag if more rx packets available to read(1) or not(0). * * @note * 1) MAC needs to be out of reset and proper clocks need to be configured. @@ -759,7 +761,8 @@ int osi_process_tx_completions(struct osi_dma_priv_data *osi, * @returns Number of decriptors (buffers) proccessed. */ int osi_process_rx_completions(struct osi_dma_priv_data *osi, - unsigned int chan, int budget); + unsigned int chan, int budget, + unsigned int *more_data_avail); /** * @brief osi_hw_dma_init - Initialize DMA diff --git a/osi/dma/osi_dma_txrx.c b/osi/dma/osi_dma_txrx.c index 3a35619..d97bb1e 100644 --- a/osi/dma/osi_dma_txrx.c +++ b/osi/dma/osi_dma_txrx.c @@ -234,7 +234,8 @@ static inline void get_rx_err_stats(struct osi_rx_desc *rx_desc, } int osi_process_rx_completions(struct osi_dma_priv_data *osi, - unsigned int chan, int budget) + unsigned int chan, int budget, + unsigned int *more_data_avail) { struct osi_rx_ring *rx_ring = osi->rx_ring[chan]; struct osi_rx_pkt_cx *rx_pkt_cx = &rx_ring->rx_pkt_cx; @@ -245,10 +246,13 @@ int osi_process_rx_completions(struct osi_dma_priv_data *osi, int received = 0; int ret = 0; - if (rx_ring->cur_rx_idx >= RX_DESC_CNT) { + if (rx_ring->cur_rx_idx >= RX_DESC_CNT || more_data_avail == OSI_NULL) { return -1; } + /* Reset flag to indicate if more Rx frames available to OSD layer */ + *more_data_avail = OSI_NONE; + while (received < budget) { osi_memset(rx_pkt_cx, 0U, sizeof(*rx_pkt_cx)); rx_desc = rx_ring->rx_desc + rx_ring->cur_rx_idx; @@ -332,6 +336,23 @@ int osi_process_rx_completions(struct osi_dma_priv_data *osi, osi->dstats.rx_pkt_n = osi_update_stats_counter(osi->dstats.rx_pkt_n, 1UL); received++; + + /* If budget is done, check if HW ring still has unprocessed + * Rx packets, so that the OSD layer can decide to schedule + * this function again. + */ + if (received == budget) { + rx_desc = rx_ring->rx_desc + rx_ring->cur_rx_idx; + rx_swcx = rx_ring->rx_swcx + rx_ring->cur_rx_idx; + if (((rx_swcx->flags & OSI_RX_SWCX_PROCESSED) != + OSI_RX_SWCX_PROCESSED) && + ((rx_desc->rdes3 & RDES3_OWN) != RDES3_OWN)) { + /* Next desciptor has owned by SW + * So set more data avail flag here. + */ + *more_data_avail = OSI_ENABLE; + } + } } return received;