Commit 87ebcffd authored by David S. Miller's avatar David S. Miller

Merge branch 'stmmac-Coalesce-and-tail-addr-fixes'

Jose Abreu says:

====================
net: stmmac: Coalesce and tail addr fixes

The fix for coalesce timer and a fix in tail address setting that impacts
XGMAC2 operation.

The series is:
Tested-by: default avatarJerome Brunet <jbrunet@baylibre.com>
	on a113 s400 board (single queue)
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5211da9c 0431100b
...@@ -258,10 +258,10 @@ struct stmmac_safety_stats { ...@@ -258,10 +258,10 @@ struct stmmac_safety_stats {
#define MAX_DMA_RIWT 0xff #define MAX_DMA_RIWT 0xff
#define MIN_DMA_RIWT 0x20 #define MIN_DMA_RIWT 0x20
/* Tx coalesce parameters */ /* Tx coalesce parameters */
#define STMMAC_COAL_TX_TIMER 40000 #define STMMAC_COAL_TX_TIMER 1000
#define STMMAC_MAX_COAL_TX_TICK 100000 #define STMMAC_MAX_COAL_TX_TICK 100000
#define STMMAC_TX_MAX_FRAMES 256 #define STMMAC_TX_MAX_FRAMES 256
#define STMMAC_TX_FRAMES 64 #define STMMAC_TX_FRAMES 25
/* Packets types */ /* Packets types */
enum packets_types { enum packets_types {
......
...@@ -48,6 +48,8 @@ struct stmmac_tx_info { ...@@ -48,6 +48,8 @@ struct stmmac_tx_info {
/* Frequently used values are kept adjacent for cache effect */ /* Frequently used values are kept adjacent for cache effect */
struct stmmac_tx_queue { struct stmmac_tx_queue {
u32 tx_count_frames;
struct timer_list txtimer;
u32 queue_index; u32 queue_index;
struct stmmac_priv *priv_data; struct stmmac_priv *priv_data;
struct dma_extended_desc *dma_etx ____cacheline_aligned_in_smp; struct dma_extended_desc *dma_etx ____cacheline_aligned_in_smp;
...@@ -73,7 +75,14 @@ struct stmmac_rx_queue { ...@@ -73,7 +75,14 @@ struct stmmac_rx_queue {
u32 rx_zeroc_thresh; u32 rx_zeroc_thresh;
dma_addr_t dma_rx_phy; dma_addr_t dma_rx_phy;
u32 rx_tail_addr; u32 rx_tail_addr;
};
struct stmmac_channel {
struct napi_struct napi ____cacheline_aligned_in_smp; struct napi_struct napi ____cacheline_aligned_in_smp;
struct stmmac_priv *priv_data;
u32 index;
int has_rx;
int has_tx;
}; };
struct stmmac_tc_entry { struct stmmac_tc_entry {
...@@ -109,14 +118,12 @@ struct stmmac_pps_cfg { ...@@ -109,14 +118,12 @@ struct stmmac_pps_cfg {
struct stmmac_priv { struct stmmac_priv {
/* Frequently used values are kept adjacent for cache effect */ /* Frequently used values are kept adjacent for cache effect */
u32 tx_count_frames;
u32 tx_coal_frames; u32 tx_coal_frames;
u32 tx_coal_timer; u32 tx_coal_timer;
int tx_coalesce; int tx_coalesce;
int hwts_tx_en; int hwts_tx_en;
bool tx_path_in_lpi_mode; bool tx_path_in_lpi_mode;
struct timer_list txtimer;
bool tso; bool tso;
unsigned int dma_buf_sz; unsigned int dma_buf_sz;
...@@ -137,6 +144,9 @@ struct stmmac_priv { ...@@ -137,6 +144,9 @@ struct stmmac_priv {
/* TX Queue */ /* TX Queue */
struct stmmac_tx_queue tx_queue[MTL_MAX_TX_QUEUES]; struct stmmac_tx_queue tx_queue[MTL_MAX_TX_QUEUES];
/* Generic channel for NAPI */
struct stmmac_channel channel[STMMAC_CH_MAX];
bool oldlink; bool oldlink;
int speed; int speed;
int oldduplex; int oldduplex;
......
...@@ -148,12 +148,14 @@ static void stmmac_verify_args(void) ...@@ -148,12 +148,14 @@ static void stmmac_verify_args(void)
static void stmmac_disable_all_queues(struct stmmac_priv *priv) static void stmmac_disable_all_queues(struct stmmac_priv *priv)
{ {
u32 rx_queues_cnt = priv->plat->rx_queues_to_use; u32 rx_queues_cnt = priv->plat->rx_queues_to_use;
u32 tx_queues_cnt = priv->plat->tx_queues_to_use;
u32 maxq = max(rx_queues_cnt, tx_queues_cnt);
u32 queue; u32 queue;
for (queue = 0; queue < rx_queues_cnt; queue++) { for (queue = 0; queue < maxq; queue++) {
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; struct stmmac_channel *ch = &priv->channel[queue];
napi_disable(&rx_q->napi); napi_disable(&ch->napi);
} }
} }
...@@ -164,12 +166,14 @@ static void stmmac_disable_all_queues(struct stmmac_priv *priv) ...@@ -164,12 +166,14 @@ static void stmmac_disable_all_queues(struct stmmac_priv *priv)
static void stmmac_enable_all_queues(struct stmmac_priv *priv) static void stmmac_enable_all_queues(struct stmmac_priv *priv)
{ {
u32 rx_queues_cnt = priv->plat->rx_queues_to_use; u32 rx_queues_cnt = priv->plat->rx_queues_to_use;
u32 tx_queues_cnt = priv->plat->tx_queues_to_use;
u32 maxq = max(rx_queues_cnt, tx_queues_cnt);
u32 queue; u32 queue;
for (queue = 0; queue < rx_queues_cnt; queue++) { for (queue = 0; queue < maxq; queue++) {
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; struct stmmac_channel *ch = &priv->channel[queue];
napi_enable(&rx_q->napi); napi_enable(&ch->napi);
} }
} }
...@@ -1843,18 +1847,18 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) ...@@ -1843,18 +1847,18 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
* @queue: TX queue index * @queue: TX queue index
* Description: it reclaims the transmit resources after transmission completes. * Description: it reclaims the transmit resources after transmission completes.
*/ */
static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue) static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue)
{ {
struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
unsigned int bytes_compl = 0, pkts_compl = 0; unsigned int bytes_compl = 0, pkts_compl = 0;
unsigned int entry; unsigned int entry, count = 0;
netif_tx_lock(priv->dev); __netif_tx_lock_bh(netdev_get_tx_queue(priv->dev, queue));
priv->xstats.tx_clean++; priv->xstats.tx_clean++;
entry = tx_q->dirty_tx; entry = tx_q->dirty_tx;
while (entry != tx_q->cur_tx) { while ((entry != tx_q->cur_tx) && (count < budget)) {
struct sk_buff *skb = tx_q->tx_skbuff[entry]; struct sk_buff *skb = tx_q->tx_skbuff[entry];
struct dma_desc *p; struct dma_desc *p;
int status; int status;
...@@ -1870,6 +1874,8 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue) ...@@ -1870,6 +1874,8 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue)
if (unlikely(status & tx_dma_own)) if (unlikely(status & tx_dma_own))
break; break;
count++;
/* Make sure descriptor fields are read after reading /* Make sure descriptor fields are read after reading
* the own bit. * the own bit.
*/ */
...@@ -1937,7 +1943,10 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue) ...@@ -1937,7 +1943,10 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue)
stmmac_enable_eee_mode(priv); stmmac_enable_eee_mode(priv);
mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer)); mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
} }
netif_tx_unlock(priv->dev);
__netif_tx_unlock_bh(netdev_get_tx_queue(priv->dev, queue));
return count;
} }
/** /**
...@@ -2020,6 +2029,33 @@ static bool stmmac_safety_feat_interrupt(struct stmmac_priv *priv) ...@@ -2020,6 +2029,33 @@ static bool stmmac_safety_feat_interrupt(struct stmmac_priv *priv)
return false; return false;
} }
static int stmmac_napi_check(struct stmmac_priv *priv, u32 chan)
{
int status = stmmac_dma_interrupt_status(priv, priv->ioaddr,
&priv->xstats, chan);
struct stmmac_channel *ch = &priv->channel[chan];
bool needs_work = false;
if ((status & handle_rx) && ch->has_rx) {
needs_work = true;
} else {
status &= ~handle_rx;
}
if ((status & handle_tx) && ch->has_tx) {
needs_work = true;
} else {
status &= ~handle_tx;
}
if (needs_work && napi_schedule_prep(&ch->napi)) {
stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
__napi_schedule(&ch->napi);
}
return status;
}
/** /**
* stmmac_dma_interrupt - DMA ISR * stmmac_dma_interrupt - DMA ISR
* @priv: driver private structure * @priv: driver private structure
...@@ -2034,57 +2070,14 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv) ...@@ -2034,57 +2070,14 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv)
u32 channels_to_check = tx_channel_count > rx_channel_count ? u32 channels_to_check = tx_channel_count > rx_channel_count ?
tx_channel_count : rx_channel_count; tx_channel_count : rx_channel_count;
u32 chan; u32 chan;
bool poll_scheduled = false;
int status[max_t(u32, MTL_MAX_TX_QUEUES, MTL_MAX_RX_QUEUES)]; int status[max_t(u32, MTL_MAX_TX_QUEUES, MTL_MAX_RX_QUEUES)];
/* Make sure we never check beyond our status buffer. */ /* Make sure we never check beyond our status buffer. */
if (WARN_ON_ONCE(channels_to_check > ARRAY_SIZE(status))) if (WARN_ON_ONCE(channels_to_check > ARRAY_SIZE(status)))
channels_to_check = ARRAY_SIZE(status); channels_to_check = ARRAY_SIZE(status);
/* Each DMA channel can be used for rx and tx simultaneously, yet
* napi_struct is embedded in struct stmmac_rx_queue rather than in a
* stmmac_channel struct.
* Because of this, stmmac_poll currently checks (and possibly wakes)
* all tx queues rather than just a single tx queue.
*/
for (chan = 0; chan < channels_to_check; chan++) for (chan = 0; chan < channels_to_check; chan++)
status[chan] = stmmac_dma_interrupt_status(priv, priv->ioaddr, status[chan] = stmmac_napi_check(priv, chan);
&priv->xstats, chan);
for (chan = 0; chan < rx_channel_count; chan++) {
if (likely(status[chan] & handle_rx)) {
struct stmmac_rx_queue *rx_q = &priv->rx_queue[chan];
if (likely(napi_schedule_prep(&rx_q->napi))) {
stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
__napi_schedule(&rx_q->napi);
poll_scheduled = true;
}
}
}
/* If we scheduled poll, we already know that tx queues will be checked.
* If we didn't schedule poll, see if any DMA channel (used by tx) has a
* completed transmission, if so, call stmmac_poll (once).
*/
if (!poll_scheduled) {
for (chan = 0; chan < tx_channel_count; chan++) {
if (status[chan] & handle_tx) {
/* It doesn't matter what rx queue we choose
* here. We use 0 since it always exists.
*/
struct stmmac_rx_queue *rx_q =
&priv->rx_queue[0];
if (likely(napi_schedule_prep(&rx_q->napi))) {
stmmac_disable_dma_irq(priv,
priv->ioaddr, chan);
__napi_schedule(&rx_q->napi);
}
break;
}
}
}
for (chan = 0; chan < tx_channel_count; chan++) { for (chan = 0; chan < tx_channel_count; chan++) {
if (unlikely(status[chan] & tx_hard_error_bump_tc)) { if (unlikely(status[chan] & tx_hard_error_bump_tc)) {
...@@ -2220,8 +2213,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv) ...@@ -2220,8 +2213,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
stmmac_init_tx_chan(priv, priv->ioaddr, priv->plat->dma_cfg, stmmac_init_tx_chan(priv, priv->ioaddr, priv->plat->dma_cfg,
tx_q->dma_tx_phy, chan); tx_q->dma_tx_phy, chan);
tx_q->tx_tail_addr = tx_q->dma_tx_phy + tx_q->tx_tail_addr = tx_q->dma_tx_phy;
(DMA_TX_SIZE * sizeof(struct dma_desc));
stmmac_set_tx_tail_ptr(priv, priv->ioaddr, stmmac_set_tx_tail_ptr(priv, priv->ioaddr,
tx_q->tx_tail_addr, chan); tx_q->tx_tail_addr, chan);
} }
...@@ -2233,6 +2225,13 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv) ...@@ -2233,6 +2225,13 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
return ret; return ret;
} }
static void stmmac_tx_timer_arm(struct stmmac_priv *priv, u32 queue)
{
struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
mod_timer(&tx_q->txtimer, STMMAC_COAL_TIMER(priv->tx_coal_timer));
}
/** /**
* stmmac_tx_timer - mitigation sw timer for tx. * stmmac_tx_timer - mitigation sw timer for tx.
* @data: data pointer * @data: data pointer
...@@ -2241,13 +2240,14 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv) ...@@ -2241,13 +2240,14 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
*/ */
static void stmmac_tx_timer(struct timer_list *t) static void stmmac_tx_timer(struct timer_list *t)
{ {
struct stmmac_priv *priv = from_timer(priv, t, txtimer); struct stmmac_tx_queue *tx_q = from_timer(tx_q, t, txtimer);
u32 tx_queues_count = priv->plat->tx_queues_to_use; struct stmmac_priv *priv = tx_q->priv_data;
u32 queue; struct stmmac_channel *ch;
ch = &priv->channel[tx_q->queue_index];
/* let's scan all the tx queues */ if (likely(napi_schedule_prep(&ch->napi)))
for (queue = 0; queue < tx_queues_count; queue++) __napi_schedule(&ch->napi);
stmmac_tx_clean(priv, queue);
} }
/** /**
...@@ -2260,11 +2260,17 @@ static void stmmac_tx_timer(struct timer_list *t) ...@@ -2260,11 +2260,17 @@ static void stmmac_tx_timer(struct timer_list *t)
*/ */
static void stmmac_init_tx_coalesce(struct stmmac_priv *priv) static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
{ {
u32 tx_channel_count = priv->plat->tx_queues_to_use;
u32 chan;
priv->tx_coal_frames = STMMAC_TX_FRAMES; priv->tx_coal_frames = STMMAC_TX_FRAMES;
priv->tx_coal_timer = STMMAC_COAL_TX_TIMER; priv->tx_coal_timer = STMMAC_COAL_TX_TIMER;
timer_setup(&priv->txtimer, stmmac_tx_timer, 0);
priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer); for (chan = 0; chan < tx_channel_count; chan++) {
add_timer(&priv->txtimer); struct stmmac_tx_queue *tx_q = &priv->tx_queue[chan];
timer_setup(&tx_q->txtimer, stmmac_tx_timer, 0);
}
} }
static void stmmac_set_rings_length(struct stmmac_priv *priv) static void stmmac_set_rings_length(struct stmmac_priv *priv)
...@@ -2592,6 +2598,7 @@ static void stmmac_hw_teardown(struct net_device *dev) ...@@ -2592,6 +2598,7 @@ static void stmmac_hw_teardown(struct net_device *dev)
static int stmmac_open(struct net_device *dev) static int stmmac_open(struct net_device *dev)
{ {
struct stmmac_priv *priv = netdev_priv(dev); struct stmmac_priv *priv = netdev_priv(dev);
u32 chan;
int ret; int ret;
stmmac_check_ether_addr(priv); stmmac_check_ether_addr(priv);
...@@ -2688,7 +2695,9 @@ static int stmmac_open(struct net_device *dev) ...@@ -2688,7 +2695,9 @@ static int stmmac_open(struct net_device *dev)
if (dev->phydev) if (dev->phydev)
phy_stop(dev->phydev); phy_stop(dev->phydev);
del_timer_sync(&priv->txtimer); for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
del_timer_sync(&priv->tx_queue[chan].txtimer);
stmmac_hw_teardown(dev); stmmac_hw_teardown(dev);
init_error: init_error:
free_dma_desc_resources(priv); free_dma_desc_resources(priv);
...@@ -2708,6 +2717,7 @@ static int stmmac_open(struct net_device *dev) ...@@ -2708,6 +2717,7 @@ static int stmmac_open(struct net_device *dev)
static int stmmac_release(struct net_device *dev) static int stmmac_release(struct net_device *dev)
{ {
struct stmmac_priv *priv = netdev_priv(dev); struct stmmac_priv *priv = netdev_priv(dev);
u32 chan;
if (priv->eee_enabled) if (priv->eee_enabled)
del_timer_sync(&priv->eee_ctrl_timer); del_timer_sync(&priv->eee_ctrl_timer);
...@@ -2722,7 +2732,8 @@ static int stmmac_release(struct net_device *dev) ...@@ -2722,7 +2732,8 @@ static int stmmac_release(struct net_device *dev)
stmmac_disable_all_queues(priv); stmmac_disable_all_queues(priv);
del_timer_sync(&priv->txtimer); for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
del_timer_sync(&priv->tx_queue[chan].txtimer);
/* Free the IRQ lines */ /* Free the IRQ lines */
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
...@@ -2936,14 +2947,13 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2936,14 +2947,13 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
priv->xstats.tx_tso_nfrags += nfrags; priv->xstats.tx_tso_nfrags += nfrags;
/* Manage tx mitigation */ /* Manage tx mitigation */
priv->tx_count_frames += nfrags + 1; tx_q->tx_count_frames += nfrags + 1;
if (likely(priv->tx_coal_frames > priv->tx_count_frames)) { if (priv->tx_coal_frames <= tx_q->tx_count_frames) {
mod_timer(&priv->txtimer,
STMMAC_COAL_TIMER(priv->tx_coal_timer));
} else {
priv->tx_count_frames = 0;
stmmac_set_tx_ic(priv, desc); stmmac_set_tx_ic(priv, desc);
priv->xstats.tx_set_ic_bit++; priv->xstats.tx_set_ic_bit++;
tx_q->tx_count_frames = 0;
} else {
stmmac_tx_timer_arm(priv, queue);
} }
skb_tx_timestamp(skb); skb_tx_timestamp(skb);
...@@ -2992,6 +3002,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2992,6 +3002,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len); netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len);
tx_q->tx_tail_addr = tx_q->dma_tx_phy + (tx_q->cur_tx * sizeof(*desc));
stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue); stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue);
return NETDEV_TX_OK; return NETDEV_TX_OK;
...@@ -3146,14 +3157,13 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -3146,14 +3157,13 @@ 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 * This approach takes care about the fragments: desc is the first
* element in case of no SG. * element in case of no SG.
*/ */
priv->tx_count_frames += nfrags + 1; tx_q->tx_count_frames += nfrags + 1;
if (likely(priv->tx_coal_frames > priv->tx_count_frames)) { if (priv->tx_coal_frames <= tx_q->tx_count_frames) {
mod_timer(&priv->txtimer,
STMMAC_COAL_TIMER(priv->tx_coal_timer));
} else {
priv->tx_count_frames = 0;
stmmac_set_tx_ic(priv, desc); stmmac_set_tx_ic(priv, desc);
priv->xstats.tx_set_ic_bit++; priv->xstats.tx_set_ic_bit++;
tx_q->tx_count_frames = 0;
} else {
stmmac_tx_timer_arm(priv, queue);
} }
skb_tx_timestamp(skb); skb_tx_timestamp(skb);
...@@ -3199,6 +3209,8 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -3199,6 +3209,8 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len); netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len);
stmmac_enable_dma_transmission(priv, priv->ioaddr); stmmac_enable_dma_transmission(priv, priv->ioaddr);
tx_q->tx_tail_addr = tx_q->dma_tx_phy + (tx_q->cur_tx * sizeof(*desc));
stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue); stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue);
return NETDEV_TX_OK; return NETDEV_TX_OK;
...@@ -3319,6 +3331,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue) ...@@ -3319,6 +3331,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
{ {
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
struct stmmac_channel *ch = &priv->channel[queue];
unsigned int entry = rx_q->cur_rx; unsigned int entry = rx_q->cur_rx;
int coe = priv->hw->rx_csum; int coe = priv->hw->rx_csum;
unsigned int next_entry; unsigned int next_entry;
...@@ -3491,7 +3504,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) ...@@ -3491,7 +3504,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
else else
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
napi_gro_receive(&rx_q->napi, skb); napi_gro_receive(&ch->napi, skb);
priv->dev->stats.rx_packets++; priv->dev->stats.rx_packets++;
priv->dev->stats.rx_bytes += frame_len; priv->dev->stats.rx_bytes += frame_len;
...@@ -3514,27 +3527,33 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) ...@@ -3514,27 +3527,33 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
* Description : * Description :
* To look at the incoming frames and clear the tx resources. * To look at the incoming frames and clear the tx resources.
*/ */
static int stmmac_poll(struct napi_struct *napi, int budget) static int stmmac_napi_poll(struct napi_struct *napi, int budget)
{ {
struct stmmac_rx_queue *rx_q = struct stmmac_channel *ch =
container_of(napi, struct stmmac_rx_queue, napi); container_of(napi, struct stmmac_channel, napi);
struct stmmac_priv *priv = rx_q->priv_data; struct stmmac_priv *priv = ch->priv_data;
u32 tx_count = priv->plat->tx_queues_to_use; int work_done = 0, work_rem = budget;
u32 chan = rx_q->queue_index; u32 chan = ch->index;
int work_done = 0;
u32 queue;
priv->xstats.napi_poll++; priv->xstats.napi_poll++;
/* check all the queues */ if (ch->has_tx) {
for (queue = 0; queue < tx_count; queue++) int done = stmmac_tx_clean(priv, work_rem, chan);
stmmac_tx_clean(priv, queue);
work_done = stmmac_rx(priv, budget, rx_q->queue_index); work_done += done;
if (work_done < budget) { work_rem -= done;
napi_complete_done(napi, work_done); }
stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
if (ch->has_rx) {
int done = stmmac_rx(priv, work_rem, chan);
work_done += done;
work_rem -= done;
} }
if (work_done < budget && napi_complete_done(napi, work_done))
stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
return work_done; return work_done;
} }
...@@ -4198,8 +4217,8 @@ int stmmac_dvr_probe(struct device *device, ...@@ -4198,8 +4217,8 @@ int stmmac_dvr_probe(struct device *device,
{ {
struct net_device *ndev = NULL; struct net_device *ndev = NULL;
struct stmmac_priv *priv; struct stmmac_priv *priv;
u32 queue, maxq;
int ret = 0; int ret = 0;
u32 queue;
ndev = alloc_etherdev_mqs(sizeof(struct stmmac_priv), ndev = alloc_etherdev_mqs(sizeof(struct stmmac_priv),
MTL_MAX_TX_QUEUES, MTL_MAX_TX_QUEUES,
...@@ -4322,11 +4341,22 @@ int stmmac_dvr_probe(struct device *device, ...@@ -4322,11 +4341,22 @@ int stmmac_dvr_probe(struct device *device,
"Enable RX Mitigation via HW Watchdog Timer\n"); "Enable RX Mitigation via HW Watchdog Timer\n");
} }
for (queue = 0; queue < priv->plat->rx_queues_to_use; queue++) { /* Setup channels NAPI */
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; maxq = max(priv->plat->rx_queues_to_use, priv->plat->tx_queues_to_use);
netif_napi_add(ndev, &rx_q->napi, stmmac_poll, for (queue = 0; queue < maxq; queue++) {
(8 * priv->plat->rx_queues_to_use)); struct stmmac_channel *ch = &priv->channel[queue];
ch->priv_data = priv;
ch->index = queue;
if (queue < priv->plat->rx_queues_to_use)
ch->has_rx = true;
if (queue < priv->plat->tx_queues_to_use)
ch->has_tx = true;
netif_napi_add(ndev, &ch->napi, stmmac_napi_poll,
NAPI_POLL_WEIGHT);
} }
mutex_init(&priv->lock); mutex_init(&priv->lock);
...@@ -4372,10 +4402,10 @@ int stmmac_dvr_probe(struct device *device, ...@@ -4372,10 +4402,10 @@ int stmmac_dvr_probe(struct device *device,
priv->hw->pcs != STMMAC_PCS_RTBI) priv->hw->pcs != STMMAC_PCS_RTBI)
stmmac_mdio_unregister(ndev); stmmac_mdio_unregister(ndev);
error_mdio_register: error_mdio_register:
for (queue = 0; queue < priv->plat->rx_queues_to_use; queue++) { for (queue = 0; queue < maxq; queue++) {
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; struct stmmac_channel *ch = &priv->channel[queue];
netif_napi_del(&rx_q->napi); netif_napi_del(&ch->napi);
} }
error_hw_init: error_hw_init:
destroy_workqueue(priv->wq); destroy_workqueue(priv->wq);
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#define MTL_MAX_RX_QUEUES 8 #define MTL_MAX_RX_QUEUES 8
#define MTL_MAX_TX_QUEUES 8 #define MTL_MAX_TX_QUEUES 8
#define STMMAC_CH_MAX 8
#define STMMAC_RX_COE_NONE 0 #define STMMAC_RX_COE_NONE 0
#define STMMAC_RX_COE_TYPE1 1 #define STMMAC_RX_COE_TYPE1 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment