mirror of
https://github.com/torvalds/linux.git
synced 2026-06-02 03:24:19 +02:00
Merge branch 'net-stmmac-fix-interrupt-coalescing'
Russell King says: ==================== net: stmmac: fix interrupt coalescing While cleaning up the descriptor handling, I noticed that the accounting of transmit "packets" for interrupt coalescing was buggy in that it takes the difference of the two indexes into the circular list of transmit discriptors and merely subtracts one from the other without regard for the indexes wrapping. This can result in a negative number or very large positive number which would have the effect of either reducing tx_q->tx_count_frames or making that very large. Either way, the result is numerically incorrect, and could trigger interrupts or not trigger interrupts when required. This series converts stmmac to use the circ_buf helpers, and then fixes this problem. ==================== Link: https://patch.msgid.link/aZ1o2dmfpeiubCik@shell.armlinux.org.uk Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
23a611b9b3
|
|
@ -14,6 +14,7 @@
|
|||
https://bugzilla.stlinux.com/
|
||||
*******************************************************************************/
|
||||
|
||||
#include <linux/circ_buf.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
|
@ -355,14 +356,9 @@ static void print_pkt(unsigned char *buf, int len)
|
|||
static inline u32 stmmac_tx_avail(struct stmmac_priv *priv, u32 queue)
|
||||
{
|
||||
struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue];
|
||||
u32 avail;
|
||||
|
||||
if (tx_q->dirty_tx > tx_q->cur_tx)
|
||||
avail = tx_q->dirty_tx - tx_q->cur_tx - 1;
|
||||
else
|
||||
avail = priv->dma_conf.dma_tx_size - tx_q->cur_tx + tx_q->dirty_tx - 1;
|
||||
|
||||
return avail;
|
||||
return CIRC_SPACE(tx_q->cur_tx, tx_q->dirty_tx,
|
||||
priv->dma_conf.dma_tx_size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -373,14 +369,9 @@ static inline u32 stmmac_tx_avail(struct stmmac_priv *priv, u32 queue)
|
|||
static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv, u32 queue)
|
||||
{
|
||||
struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue];
|
||||
u32 dirty;
|
||||
|
||||
if (rx_q->dirty_rx <= rx_q->cur_rx)
|
||||
dirty = rx_q->cur_rx - rx_q->dirty_rx;
|
||||
else
|
||||
dirty = priv->dma_conf.dma_rx_size - rx_q->dirty_rx + rx_q->cur_rx;
|
||||
|
||||
return dirty;
|
||||
return CIRC_CNT(rx_q->cur_rx, rx_q->dirty_rx,
|
||||
priv->dma_conf.dma_rx_size);
|
||||
}
|
||||
|
||||
static bool stmmac_eee_tx_busy(struct stmmac_priv *priv)
|
||||
|
|
@ -4525,7 +4516,8 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
tx_q->tx_skbuff_dma[tx_q->cur_tx].buf_type = STMMAC_TXBUF_T_SKB;
|
||||
|
||||
/* Manage tx mitigation */
|
||||
tx_packets = (tx_q->cur_tx + 1) - first_tx;
|
||||
tx_packets = CIRC_CNT(tx_q->cur_tx + 1, first_tx,
|
||||
priv->dma_conf.dma_tx_size);
|
||||
tx_q->tx_count_frames += tx_packets;
|
||||
|
||||
if ((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && priv->hwts_tx_en)
|
||||
|
|
@ -4584,8 +4576,8 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
/* If we only have one entry used, then the first entry is the last
|
||||
* segment.
|
||||
*/
|
||||
is_last_segment = ((tx_q->cur_tx - first_entry) &
|
||||
(priv->dma_conf.dma_tx_size - 1)) == 1;
|
||||
is_last_segment = CIRC_CNT(tx_q->cur_tx, first_entry,
|
||||
priv->dma_conf.dma_tx_size) == 1;
|
||||
|
||||
/* Complete the first descriptor before granting the DMA */
|
||||
stmmac_prepare_tso_tx_desc(priv, first, 1, proto_hdr_len, 0, 1,
|
||||
|
|
@ -4803,7 +4795,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
* This approach takes care about the fragments: desc is the first
|
||||
* element in case of no SG.
|
||||
*/
|
||||
tx_packets = (entry + 1) - first_tx;
|
||||
tx_packets = CIRC_CNT(entry + 1, first_tx, priv->dma_conf.dma_tx_size);
|
||||
tx_q->tx_count_frames += tx_packets;
|
||||
|
||||
if ((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && priv->hwts_tx_en)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user