All of lore.kernel.org
 help / color / mirror / Atom feed
From: Neil Armstrong <narmstrong@baylibre.com>
To: Jose Abreu <Jose.Abreu@synopsys.com>, netdev@vger.kernel.org
Cc: Jerome Brunet <jbrunet@baylibre.com>,
	Martin Blumenstingl <martin.blumenstingl@googlemail.com>,
	"David S. Miller" <davem@davemloft.net>,
	Joao Pinto <Joao.Pinto@synopsys.com>,
	Giuseppe Cavallaro <peppe.cavallaro@st.com>,
	Alexandre Torgue <alexandre.torgue@st.com>
Subject: Re: [net-next, v2, 1/2] net: stmmac: Rework coalesce timer and fix multi-queue races
Date: Mon, 10 Sep 2018 13:43:04 +0200	[thread overview]
Message-ID: <ff2f8f89-134e-b7f8-1a40-d87f371be303@baylibre.com> (raw)
In-Reply-To: <c54230d2dc7e2740c039e0f5e8f306a7544bbe5e.1536570319.git.joabreu@synopsys.com>

Hi Jose,

On 10/09/2018 11:14, Jose Abreu wrote:
> This follows David Miller advice and tries to fix coalesce timer in
> multi-queue scenarios.
> 
> We are now using per-queue coalesce values and per-queue TX timer.
> 
> Coalesce timer default values was changed to 1ms and the coalesce frames
> to 25.
> 
> Tested in B2B setup between XGMAC2 and GMAC5.
> 
> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> Cc: Jerome Brunet <jbrunet@baylibre.com>
> Cc: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
> Cc: David S. Miller <davem@davemloft.net>
> Cc: Joao Pinto <jpinto@synopsys.com>
> Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
> Cc: Alexandre Torgue <alexandre.torgue@st.com>
> ---
> Jerome,

Jerome is in holidays...

> 
> Can you please test if this one is okay ?


I tested this patch on top of 4.18.7 with the previous patch (4ae0169fd1b3) reverted.

The TX or RX stopped a few seconds after iperf3 started :
(iperf3 is running in server mode on the Amlogic A113D board)

$ iperf3 -c 10.1.4.95
Connecting to host 10.1.4.95, port 5201
[  4] local 10.1.2.12 port 39906 connected to 10.1.4.95 port 5201
[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
[  4]   0.00-1.00   sec  56.2 MBytes   472 Mbits/sec    0    660 KBytes
[  4]   1.00-2.00   sec  56.2 MBytes   472 Mbits/sec    0    660 KBytes
[  4]   2.00-3.00   sec  38.8 MBytes   325 Mbits/sec    1   1.41 KBytes
[  4]   3.00-4.00   sec  0.00 Bytes  0.00 bits/sec    1   1.41 KBytes
[  4]   4.00-5.00   sec  0.00 Bytes  0.00 bits/sec    1   1.41 KBytes
^C[  4]   5.00-5.61   sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-5.61   sec   151 MBytes   226 Mbits/sec    3             sender
[  4]   0.00-5.61   sec  0.00 Bytes  0.00 bits/sec                  receiver
iperf3: interrupt - the client has terminated

$ iperf3 -c 10.1.4.95 -R
Connecting to host 10.1.4.95, port 5201
Reverse mode, remote host 10.1.4.95 is sending
[  4] local 10.1.2.12 port 39894 connected to 10.1.4.95 port 5201
[ ID] Interval           Transfer     Bandwidth
[  4]   0.00-1.00   sec  82.2 MBytes   690 Mbits/sec
[  4]   1.00-2.00   sec  82.6 MBytes   693 Mbits/sec
[  4]   2.00-3.00   sec  24.2 MBytes   203 Mbits/sec
[  4]   3.00-4.00   sec  0.00 Bytes  0.00 bits/sec
[  4]   4.00-5.00   sec  0.00 Bytes  0.00 bits/sec
^C[  4]   5.00-5.53   sec  0.00 Bytes  0.00 bits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth
[  4]   0.00-5.53   sec  0.00 Bytes  0.00 bits/sec                  sender
[  4]   0.00-5.53   sec   189 MBytes   287 Mbits/sec                  receiver
iperf3: interrupt - the client has terminated

These works for hours without this patch applied.

Neil

> 
> Thanks and Best Regards,
> Jose Miguel Abreu
> ---
>  drivers/net/ethernet/stmicro/stmmac/common.h      |   4 +-
>  drivers/net/ethernet/stmicro/stmmac/stmmac.h      |   6 +-
>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 207 ++++++++++++++--------
>  3 files changed, 135 insertions(+), 82 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
> index 1854f270ad66..b1b305f8f414 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/common.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
> @@ -258,10 +258,10 @@ struct stmmac_safety_stats {
>  #define MAX_DMA_RIWT		0xff
>  #define MIN_DMA_RIWT		0x20
>  /* Tx coalesce parameters */
> -#define STMMAC_COAL_TX_TIMER	40000
> +#define STMMAC_COAL_TX_TIMER	1000
>  #define STMMAC_MAX_COAL_TX_TICK	100000
>  #define STMMAC_TX_MAX_FRAMES	256
> -#define STMMAC_TX_FRAMES	64
> +#define STMMAC_TX_FRAMES	25
>  
>  /* Packets types */
>  enum packets_types {
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
> index c0a855b7ab3b..957030cfb833 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
> @@ -48,6 +48,9 @@ struct stmmac_tx_info {
>  
>  /* Frequently used values are kept adjacent for cache effect */
>  struct stmmac_tx_queue {
> +	u32 tx_count_frames;
> +	int tx_timer_active;
> +	struct timer_list txtimer;
>  	u32 queue_index;
>  	struct stmmac_priv *priv_data;
>  	struct dma_extended_desc *dma_etx ____cacheline_aligned_in_smp;
> @@ -59,6 +62,7 @@ struct stmmac_tx_queue {
>  	dma_addr_t dma_tx_phy;
>  	u32 tx_tail_addr;
>  	u32 mss;
> +	struct napi_struct napi ____cacheline_aligned_in_smp;
>  };
>  
>  struct stmmac_rx_queue {
> @@ -109,14 +113,12 @@ struct stmmac_pps_cfg {
>  
>  struct stmmac_priv {
>  	/* Frequently used values are kept adjacent for cache effect */
> -	u32 tx_count_frames;
>  	u32 tx_coal_frames;
>  	u32 tx_coal_timer;
>  
>  	int tx_coalesce;
>  	int hwts_tx_en;
>  	bool tx_path_in_lpi_mode;
> -	struct timer_list txtimer;
>  	bool tso;
>  
>  	unsigned int dma_buf_sz;
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 9f458bb16f2a..9809c2b319fe 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -148,6 +148,7 @@ static void stmmac_verify_args(void)
>  static void stmmac_disable_all_queues(struct stmmac_priv *priv)
>  {
>  	u32 rx_queues_cnt = priv->plat->rx_queues_to_use;
> +	u32 tx_queues_cnt = priv->plat->tx_queues_to_use;
>  	u32 queue;
>  
>  	for (queue = 0; queue < rx_queues_cnt; queue++) {
> @@ -155,6 +156,12 @@ static void stmmac_disable_all_queues(struct stmmac_priv *priv)
>  
>  		napi_disable(&rx_q->napi);
>  	}
> +
> +	for (queue = 0; queue < tx_queues_cnt; queue++) {
> +		struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
> +
> +		napi_disable(&tx_q->napi);
> +	}
>  }
>  
>  /**
> @@ -164,6 +171,7 @@ static void stmmac_disable_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 tx_queues_cnt = priv->plat->tx_queues_to_use;
>  	u32 queue;
>  
>  	for (queue = 0; queue < rx_queues_cnt; queue++) {
> @@ -171,6 +179,12 @@ static void stmmac_enable_all_queues(struct stmmac_priv *priv)
>  
>  		napi_enable(&rx_q->napi);
>  	}
> +
> +	for (queue = 0; queue < tx_queues_cnt; queue++) {
> +		struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
> +
> +		napi_enable(&tx_q->napi);
> +	}
>  }
>  
>  /**
> @@ -1843,7 +1857,8 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
>   * @queue: TX queue index
>   * 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 limit, u32 queue,
> +			   bool *more)
>  {
>  	struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
>  	unsigned int bytes_compl = 0, pkts_compl = 0;
> @@ -1851,10 +1866,13 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue)
>  
>  	netif_tx_lock(priv->dev);
>  
> +	if (more)
> +		*more = false;
> +
>  	priv->xstats.tx_clean++;
>  
>  	entry = tx_q->dirty_tx;
> -	while (entry != tx_q->cur_tx) {
> +	while ((entry != tx_q->cur_tx) && (pkts_compl < limit)) {
>  		struct sk_buff *skb = tx_q->tx_skbuff[entry];
>  		struct dma_desc *p;
>  		int status;
> @@ -1937,7 +1955,13 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue)
>  		stmmac_enable_eee_mode(priv);
>  		mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
>  	}
> +
> +	if (more && (tx_q->dirty_tx != tx_q->cur_tx))
> +		*more = true;
> +
>  	netif_tx_unlock(priv->dev);
> +
> +	return pkts_compl;
>  }
>  
>  /**
> @@ -2020,6 +2044,34 @@ static bool stmmac_safety_feat_interrupt(struct stmmac_priv *priv)
>  	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);
> +
> +	if ((status & handle_rx) && (chan < priv->plat->rx_queues_to_use)) {
> +		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);
> +		}
> +	} else {
> +		status &= ~handle_rx;
> +	}
> +
> +	if ((status & handle_tx) && (chan < priv->plat->tx_queues_to_use)) {
> +		struct stmmac_tx_queue *tx_q = &priv->tx_queue[chan];
> +
> +		if (likely(napi_schedule_prep(&tx_q->napi)))
> +			__napi_schedule(&tx_q->napi);
> +	} else {
> +		status &= ~handle_tx;
> +	}
> +
> +	return status;
> +}
> +
>  /**
>   * stmmac_dma_interrupt - DMA ISR
>   * @priv: driver private structure
> @@ -2034,57 +2086,14 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv)
>  	u32 channels_to_check = tx_channel_count > rx_channel_count ?
>  				tx_channel_count : rx_channel_count;
>  	u32 chan;
> -	bool poll_scheduled = false;
>  	int status[max_t(u32, MTL_MAX_TX_QUEUES, MTL_MAX_RX_QUEUES)];
>  
>  	/* Make sure we never check beyond our status buffer. */
>  	if (WARN_ON_ONCE(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++)
> -		status[chan] = stmmac_dma_interrupt_status(priv, priv->ioaddr,
> -				&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;
> -			}
> -		}
> -	}
> +		status[chan] = stmmac_napi_check(priv, chan);
>  
>  	for (chan = 0; chan < tx_channel_count; chan++) {
>  		if (unlikely(status[chan] & tx_hard_error_bump_tc)) {
> @@ -2241,13 +2250,11 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
>   */
>  static void stmmac_tx_timer(struct timer_list *t)
>  {
> -	struct stmmac_priv *priv = from_timer(priv, t, txtimer);
> -	u32 tx_queues_count = priv->plat->tx_queues_to_use;
> -	u32 queue;
> +	struct stmmac_tx_queue *tx_q = from_timer(tx_q, t, txtimer);
>  
> -	/* let's scan all the tx queues */
> -	for (queue = 0; queue < tx_queues_count; queue++)
> -		stmmac_tx_clean(priv, queue);
> +	if (likely(napi_schedule_prep(&tx_q->napi)))
> +		__napi_schedule(&tx_q->napi);
> +	tx_q->tx_timer_active = 0;
>  }
>  
>  /**
> @@ -2260,11 +2267,17 @@ static void stmmac_tx_timer(struct timer_list *t)
>   */
>  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_timer = STMMAC_COAL_TX_TIMER;
> -	timer_setup(&priv->txtimer, stmmac_tx_timer, 0);
> -	priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer);
> -	add_timer(&priv->txtimer);
> +
> +	for (chan = 0; chan < tx_channel_count; chan++) {
> +		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)
> @@ -2592,6 +2605,7 @@ static void stmmac_hw_teardown(struct net_device *dev)
>  static int stmmac_open(struct net_device *dev)
>  {
>  	struct stmmac_priv *priv = netdev_priv(dev);
> +	u32 chan;
>  	int ret;
>  
>  	stmmac_check_ether_addr(priv);
> @@ -2688,7 +2702,9 @@ static int stmmac_open(struct net_device *dev)
>  	if (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);
>  init_error:
>  	free_dma_desc_resources(priv);
> @@ -2708,6 +2724,7 @@ static int stmmac_open(struct net_device *dev)
>  static int stmmac_release(struct net_device *dev)
>  {
>  	struct stmmac_priv *priv = netdev_priv(dev);
> +	u32 chan;
>  
>  	if (priv->eee_enabled)
>  		del_timer_sync(&priv->eee_ctrl_timer);
> @@ -2722,7 +2739,8 @@ static int stmmac_release(struct net_device *dev)
>  
>  	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_irq(dev->irq, dev);
> @@ -2936,14 +2954,11 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
>  	priv->xstats.tx_tso_nfrags += nfrags;
>  
>  	/* Manage tx mitigation */
> -	priv->tx_count_frames += nfrags + 1;
> -	if (likely(priv->tx_coal_frames > priv->tx_count_frames)) {
> -		mod_timer(&priv->txtimer,
> -			  STMMAC_COAL_TIMER(priv->tx_coal_timer));
> -	} else {
> -		priv->tx_count_frames = 0;
> +	tx_q->tx_count_frames += nfrags + 1;
> +	if (priv->tx_coal_frames <= tx_q->tx_count_frames) {
>  		stmmac_set_tx_ic(priv, desc);
>  		priv->xstats.tx_set_ic_bit++;
> +		tx_q->tx_count_frames = 0;
>  	}
>  
>  	skb_tx_timestamp(skb);
> @@ -2994,6 +3009,12 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
>  
>  	stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue);
>  
> +	if (priv->tx_coal_timer && !tx_q->tx_timer_active) {
> +		tx_q->tx_timer_active = 1;
> +		mod_timer(&tx_q->txtimer,
> +				STMMAC_COAL_TIMER(priv->tx_coal_timer));
> +	}
> +
>  	return NETDEV_TX_OK;
>  
>  dma_map_err:
> @@ -3146,14 +3167,11 @@ 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.
>  	 */
> -	priv->tx_count_frames += nfrags + 1;
> -	if (likely(priv->tx_coal_frames > priv->tx_count_frames)) {
> -		mod_timer(&priv->txtimer,
> -			  STMMAC_COAL_TIMER(priv->tx_coal_timer));
> -	} else {
> -		priv->tx_count_frames = 0;
> +	tx_q->tx_count_frames += nfrags + 1;
> +	if (priv->tx_coal_frames <= tx_q->tx_count_frames) {
>  		stmmac_set_tx_ic(priv, desc);
>  		priv->xstats.tx_set_ic_bit++;
> +		tx_q->tx_count_frames = 0;
>  	}
>  
>  	skb_tx_timestamp(skb);
> @@ -3199,8 +3217,15 @@ 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);
>  
>  	stmmac_enable_dma_transmission(priv, priv->ioaddr);
> +
>  	stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue);
>  
> +	if (priv->tx_coal_timer && !tx_q->tx_timer_active) {
> +		tx_q->tx_timer_active = 1;
> +		mod_timer(&tx_q->txtimer,
> +				STMMAC_COAL_TIMER(priv->tx_coal_timer));
> +	}
> +
>  	return NETDEV_TX_OK;
>  
>  dma_map_err:
> @@ -3514,27 +3539,41 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
>   *  Description :
>   *  To look at the incoming frames and clear the tx resources.
>   */
> -static int stmmac_poll(struct napi_struct *napi, int budget)
> +static int stmmac_rx_poll(struct napi_struct *napi, int budget)
>  {
>  	struct stmmac_rx_queue *rx_q =
>  		container_of(napi, struct stmmac_rx_queue, napi);
>  	struct stmmac_priv *priv = rx_q->priv_data;
> -	u32 tx_count = priv->plat->tx_queues_to_use;
>  	u32 chan = rx_q->queue_index;
>  	int work_done = 0;
> -	u32 queue;
>  
>  	priv->xstats.napi_poll++;
>  
> -	/* check all the queues */
> -	for (queue = 0; queue < tx_count; queue++)
> -		stmmac_tx_clean(priv, queue);
> -
>  	work_done = stmmac_rx(priv, budget, rx_q->queue_index);
> +	if (work_done < budget && napi_complete_done(napi, work_done))
> +		stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
> +
> +	return work_done;
> +}
> +
> +static int stmmac_tx_poll(struct napi_struct *napi, int budget)
> +{
> +	struct stmmac_tx_queue *tx_q =
> +		container_of(napi, struct stmmac_tx_queue, napi);
> +	struct stmmac_priv *priv = tx_q->priv_data;
> +	u32 chan = tx_q->queue_index;
> +	int work_done = 0;
> +	bool more;
> +
> +	priv->xstats.napi_poll++;
> +
> +	work_done = stmmac_tx_clean(priv, budget, chan, &more);
>  	if (work_done < budget) {
>  		napi_complete_done(napi, work_done);
> -		stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
> +		if (more)
> +			napi_reschedule(napi);
>  	}
> +
>  	return work_done;
>  }
>  
> @@ -4325,10 +4364,17 @@ int stmmac_dvr_probe(struct device *device,
>  	for (queue = 0; queue < priv->plat->rx_queues_to_use; queue++) {
>  		struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
>  
> -		netif_napi_add(ndev, &rx_q->napi, stmmac_poll,
> +		netif_napi_add(ndev, &rx_q->napi, stmmac_rx_poll,
>  			       (8 * priv->plat->rx_queues_to_use));
>  	}
>  
> +	for (queue = 0; queue < priv->plat->tx_queues_to_use; queue++) {
> +		struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
> +
> +		netif_napi_add(ndev, &tx_q->napi, stmmac_tx_poll,
> +			       (8 * priv->plat->tx_queues_to_use));
> +	}
> +
>  	mutex_init(&priv->lock);
>  
>  	/* If a specific clk_csr value is passed from the platform
> @@ -4377,6 +4423,11 @@ int stmmac_dvr_probe(struct device *device,
>  
>  		netif_napi_del(&rx_q->napi);
>  	}
> +	for (queue = 0; queue < priv->plat->tx_queues_to_use; queue++) {
> +		struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
> +
> +		netif_napi_del(&tx_q->napi);
> +	}
>  error_hw_init:
>  	destroy_workqueue(priv->wq);
>  error_wq:
> 

  reply	other threads:[~2018-09-10 16:36 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-10  9:14 [PATCH net-next v2 0/2] net: stmmac: Coalesce and tail addr fixes Jose Abreu
2018-09-10  9:14 ` [PATCH net-next v2 1/2] net: stmmac: Rework coalesce timer and fix multi-queue races Jose Abreu
2018-09-10 11:43   ` Neil Armstrong [this message]
2018-09-10 12:52     ` [net-next, v2, " Jose Abreu
2018-09-10 12:55       ` Jose Abreu
2018-09-10 13:46         ` Neil Armstrong
2018-09-10 14:44           ` Jose Abreu
2018-09-10 15:49             ` Neil Armstrong
2018-09-10 16:21               ` Jose Abreu
2018-09-10 18:15                 ` Neil Armstrong
2018-09-11  8:17                   ` Jose Abreu
2018-09-12 13:50                     ` Neil Armstrong
2018-09-12 14:25                       ` Jose Abreu
2018-09-10 19:22   ` [PATCH net-next v2 " Florian Fainelli
2018-09-12 14:23     ` Jose Abreu
2018-09-18  7:02     ` Tal Gilboa
2018-09-10  9:14 ` [PATCH net-next v2 2/2] net: stmmac: Fixup the tail addr setting in xmit path Jose Abreu
2018-09-10 18:46   ` Florian Fainelli
2018-09-12 14:17     ` Jose Abreu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ff2f8f89-134e-b7f8-1a40-d87f371be303@baylibre.com \
    --to=narmstrong@baylibre.com \
    --cc=Joao.Pinto@synopsys.com \
    --cc=Jose.Abreu@synopsys.com \
    --cc=alexandre.torgue@st.com \
    --cc=davem@davemloft.net \
    --cc=jbrunet@baylibre.com \
    --cc=martin.blumenstingl@googlemail.com \
    --cc=netdev@vger.kernel.org \
    --cc=peppe.cavallaro@st.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.