mirror of
git://nv-tegra.nvidia.com/kernel/nvethernetrm.git
synced 2025-12-22 17:34:29 +03:00
nvethernetrm: Honor budget for processing tx completions
Issue: osi_process_tx_completions is run in the BH for
processing Tx done irq. This function always loops
till the Tx status for all packets that are Tx'd so
far is processed.
1) The NAPI budget for this Tx completions handler is
not honored.
2) The variable 'processed' is expected to keep track
of Tx'd packets. Currently it is counting Tx'd descriptors.
There can be multiple Tx descriptors consumed for one packet.
Fix: 1) Add budget parameter to osi_process_tx_completions() API.
2) Break out of loop in this API if packets to process
exceeds budget
3) Increment the processed count variable only after checking
last descriptor for a packet.
Bug 2756439
Change-Id: Id538343f6853881ea41109b8b46c8d0e82dce98a
Signed-off-by: Srinivas Ramachandran <srinivasra@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2237822
Reviewed-by: Bhadram Varka <vbhadram@nvidia.com>
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: svc-mobile-misra <svc-mobile-misra@nvidia.com>
Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com>
Reviewed-by: Praveen Mallaiah <pmallaiah@nvidia.com>
Tested-by: Praveen Mallaiah <pmallaiah@nvidia.com>
Reviewed-by: Narayan Reddy <narayanr@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
7f08b4ae29
commit
7b0fa905ab
@@ -615,6 +615,7 @@ void osi_hw_transmit(struct osi_dma_priv_data *osi, unsigned int chan);
|
|||||||
*
|
*
|
||||||
* @param[in] osi: OSI private data structure.
|
* @param[in] osi: OSI private data structure.
|
||||||
* @param[in] chan: Channel number on which Tx complete need to be done.
|
* @param[in] chan: Channel number on which Tx complete need to be done.
|
||||||
|
* @param[in] budget: Threshold for reading the packets at a time.
|
||||||
*
|
*
|
||||||
* @note
|
* @note
|
||||||
* 1) MAC needs to be out of reset and proper clocks need to be configured.
|
* 1) MAC needs to be out of reset and proper clocks need to be configured.
|
||||||
@@ -624,7 +625,7 @@ void osi_hw_transmit(struct osi_dma_priv_data *osi, unsigned int chan);
|
|||||||
* @returns Number of decriptors (buffers) proccessed.
|
* @returns Number of decriptors (buffers) proccessed.
|
||||||
*/
|
*/
|
||||||
int osi_process_tx_completions(struct osi_dma_priv_data *osi,
|
int osi_process_tx_completions(struct osi_dma_priv_data *osi,
|
||||||
unsigned int chan);
|
unsigned int chan, int budget);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief osi_process_rx_completions - Read data from rx channel descriptors
|
* @brief osi_process_rx_completions - Read data from rx channel descriptors
|
||||||
|
|||||||
@@ -277,6 +277,24 @@ int osi_process_rx_completions(struct osi_dma_priv_data *osi,
|
|||||||
return received;
|
return received;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief inc_tx_pkt_stats - Increment Tx packet count Stats
|
||||||
|
*
|
||||||
|
* Algorithm: This routine will be invoked by OSI layer internally to increment
|
||||||
|
* stats for successfully transmitted packets on certain DMA channel.
|
||||||
|
*
|
||||||
|
* @param[in] osi: Pointer to OSI DMA private data structure.
|
||||||
|
* @param[in] chan: DMA channel number for which stats should be incremented.
|
||||||
|
*/
|
||||||
|
static inline void inc_tx_pkt_stats(struct osi_dma_priv_data *osi,
|
||||||
|
unsigned int chan)
|
||||||
|
{
|
||||||
|
osi->dstats.q_tx_pkt_n[chan] =
|
||||||
|
osi_update_stats_counter(osi->dstats.q_tx_pkt_n[chan], 1UL);
|
||||||
|
osi->dstats.tx_pkt_n =
|
||||||
|
osi_update_stats_counter(osi->dstats.tx_pkt_n, 1UL);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get_tx_err_stats - Detect Errors from Tx Status
|
* @brief get_tx_err_stats - Detect Errors from Tx Status
|
||||||
*
|
*
|
||||||
@@ -407,7 +425,7 @@ int osi_clear_rx_pkt_err_stats(struct osi_dma_priv_data *osi_dma)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int osi_process_tx_completions(struct osi_dma_priv_data *osi,
|
int osi_process_tx_completions(struct osi_dma_priv_data *osi,
|
||||||
unsigned int chan)
|
unsigned int chan, int budget)
|
||||||
{
|
{
|
||||||
struct osi_tx_ring *tx_ring = osi->tx_ring[chan];
|
struct osi_tx_ring *tx_ring = osi->tx_ring[chan];
|
||||||
struct osi_txdone_pkt_cx *txdone_pkt_cx = &tx_ring->txdone_pkt_cx;
|
struct osi_txdone_pkt_cx *txdone_pkt_cx = &tx_ring->txdone_pkt_cx;
|
||||||
@@ -421,7 +439,8 @@ int osi_process_tx_completions(struct osi_dma_priv_data *osi,
|
|||||||
osi->dstats.tx_clean_n[chan] =
|
osi->dstats.tx_clean_n[chan] =
|
||||||
osi_update_stats_counter(osi->dstats.tx_clean_n[chan], 1U);
|
osi_update_stats_counter(osi->dstats.tx_clean_n[chan], 1U);
|
||||||
|
|
||||||
while (entry != tx_ring->cur_tx_idx && entry < TX_DESC_CNT) {
|
while (entry != tx_ring->cur_tx_idx && entry < TX_DESC_CNT &&
|
||||||
|
processed < budget) {
|
||||||
osi_memset(txdone_pkt_cx, 0U, sizeof(*txdone_pkt_cx));
|
osi_memset(txdone_pkt_cx, 0U, sizeof(*txdone_pkt_cx));
|
||||||
|
|
||||||
tx_desc = tx_ring->tx_desc + entry;
|
tx_desc = tx_ring->tx_desc + entry;
|
||||||
@@ -437,6 +456,12 @@ int osi_process_tx_completions(struct osi_dma_priv_data *osi,
|
|||||||
txdone_pkt_cx->flags |= OSI_TXDONE_CX_ERROR;
|
txdone_pkt_cx->flags |= OSI_TXDONE_CX_ERROR;
|
||||||
/* fill packet error stats */
|
/* fill packet error stats */
|
||||||
get_tx_err_stats(tx_desc, osi->pkt_err_stats);
|
get_tx_err_stats(tx_desc, osi->pkt_err_stats);
|
||||||
|
} else {
|
||||||
|
inc_tx_pkt_stats(osi, chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processed < INT_MAX) {
|
||||||
|
processed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,9 +507,6 @@ int osi_process_tx_completions(struct osi_dma_priv_data *osi,
|
|||||||
tx_swcx->buf_phy_addr = 0;
|
tx_swcx->buf_phy_addr = 0;
|
||||||
tx_swcx->is_paged_buf = 0;
|
tx_swcx->is_paged_buf = 0;
|
||||||
INCR_TX_DESC_INDEX(entry, 1U);
|
INCR_TX_DESC_INDEX(entry, 1U);
|
||||||
if (processed < INT_MAX) {
|
|
||||||
processed++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't wait to update tx_ring->clean-idx. It will
|
/* Don't wait to update tx_ring->clean-idx. It will
|
||||||
* be used by OSD layer to determine the num. of available
|
* be used by OSD layer to determine the num. of available
|
||||||
@@ -492,11 +514,6 @@ int osi_process_tx_completions(struct osi_dma_priv_data *osi,
|
|||||||
* wake the corresponding transmit queue in OS layer.
|
* wake the corresponding transmit queue in OS layer.
|
||||||
*/
|
*/
|
||||||
tx_ring->clean_idx = entry;
|
tx_ring->clean_idx = entry;
|
||||||
osi->dstats.q_tx_pkt_n[chan] =
|
|
||||||
osi_update_stats_counter(osi->dstats.q_tx_pkt_n[chan],
|
|
||||||
1UL);
|
|
||||||
osi->dstats.tx_pkt_n =
|
|
||||||
osi_update_stats_counter(osi->dstats.tx_pkt_n, 1UL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return processed;
|
return processed;
|
||||||
|
|||||||
Reference in New Issue
Block a user