diff mbox

stmmac: disable tx coalescing

Message ID 20161205122711.GA30774@amd
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Pavel Machek Dec. 5, 2016, 12:27 p.m. UTC
Tx coalescing in stmmac is broken in more than one way, so disable it
for now.
    
First, low-res timers have resolution down to one per second. It is
not acceptable to delay transmits for 40msec, and certainly not
acceptable to delay them for 1000msec.
    
Second, the logic is wrong:
    
    if (likely(priv->tx_coal_frames > priv->tx_count_frames))
     	mod_timer(&priv->txtimer,
     	          STMMAC_COAL_TIMER(priv->tx_coal_timer));
    ...
    
doing tx_clean() after set number of packets, or set time after the
first packet is transmitted would make sense. But that's not what the
code does. As long as packets are being transmitted, you move the
timer into the future.. so that finally you run out of the place, then
wait for timer (!) and only then you do the cleaning.

Third, tx_cleanup is not safe to call from interrupt (tx_lock is not
irqsave), but that's exactly what coalescing code does.

Signed-off-by: Pavel Machek <pavel@denx.de>

---

This is stable candidate, afaict. It is broken in 4.4, too.

Comments

Pavel Machek Dec. 11, 2016, 7:07 p.m. UTC | #1
Hi!

David, ping? Can I get you to apply this one?

As you noticed, tx coalescing is completely broken in that driver, and
not easy to repair. This is simplest way to disable it. It can still
be re-enabled from userspace, so code can be fixed in future.

Best regards,
								Pavel

> 
> Tx coalescing in stmmac is broken in more than one way, so disable it
> for now.
>     
> First, low-res timers have resolution down to one per second. It is
> not acceptable to delay transmits for 40msec, and certainly not
> acceptable to delay them for 1000msec.
>     
> Second, the logic is wrong:
>     
>     if (likely(priv->tx_coal_frames > priv->tx_count_frames))
>      	mod_timer(&priv->txtimer,
>      	          STMMAC_COAL_TIMER(priv->tx_coal_timer));
>     ...
>     
> doing tx_clean() after set number of packets, or set time after the
> first packet is transmitted would make sense. But that's not what the
> code does. As long as packets are being transmitted, you move the
> timer into the future.. so that finally you run out of the place, then
> wait for timer (!) and only then you do the cleaning.
> 
> Third, tx_cleanup is not safe to call from interrupt (tx_lock is not
> irqsave), but that's exactly what coalescing code does.
> 
> Signed-off-by: Pavel Machek <pavel@denx.de>
> 
> ---
> 
> This is stable candidate, afaict. It is broken in 4.4, too.
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
> index 3ced2e1..32ce148 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/common.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
> @@ -244,11 +244,11 @@ struct stmmac_extra_stats {
>  /* Max/Min RI Watchdog Timer count value */
>  #define MAX_DMA_RIWT		0xff
>  #define MIN_DMA_RIWT		0x20
> -/* Tx coalesce parameters */
> +/* Tx coalesce parameters. Set STMMAC_TX_FRAMES to 0 to disable coalescing. */
>  #define STMMAC_COAL_TX_TIMER	40000
>  #define STMMAC_MAX_COAL_TX_TICK	100000
>  #define STMMAC_TX_MAX_FRAMES	256
> -#define STMMAC_TX_FRAMES	64
> +#define STMMAC_TX_FRAMES	0
>  
>  /* Rx IPC status */
>  enum rx_frame_status {
>
David Miller Dec. 11, 2016, 7:31 p.m. UTC | #2
From: Pavel Machek <pavel@ucw.cz>
Date: Sun, 11 Dec 2016 20:07:50 +0100

> David, ping? Can I get you to apply this one?
> 
> As you noticed, tx coalescing is completely broken in that driver, and
> not easy to repair. This is simplest way to disable it. It can still
> be re-enabled from userspace, so code can be fixed in future.

Sorry I'm not applying this, I want you and the driver maintainer
to reach a real solution.
Pavel Machek Dec. 11, 2016, 7:57 p.m. UTC | #3
On Sun 2016-12-11 14:31:13, David Miller wrote:
> From: Pavel Machek <pavel@ucw.cz>
> Date: Sun, 11 Dec 2016 20:07:50 +0100
> 
> > David, ping? Can I get you to apply this one?
> > 
> > As you noticed, tx coalescing is completely broken in that driver, and
> > not easy to repair. This is simplest way to disable it. It can still
> > be re-enabled from userspace, so code can be fixed in future.
> 
> Sorry I'm not applying this, I want you and the driver maintainer
> to reach a real solution.

This is what you said about this driver:

# > 4.9-rc6 still has the delays. With the
# >
# > #define STMMAC_COAL_TX_TIMER 1000
# > #define STMMAC_TX_MAX_FRAMES 2
# >
# > settings, delays go away, and driver still works. (It fails fairly
# > fast in 4.4). Good news. But the question still is: what is going on
# > there?
# 
# 256 packets looks way too large for being a trigger for aborting the
# TX coalescing timer.
# 
# Looking more deeply into this, the driver is using non-highres timers
# to implement the TX coalescing.  This simply cannot work.
# 
# 1 HZ, which is the lowest granularity of non-highres timers in the
# kernel, is variable as well as already too large of a delay for
# effective TX coalescing.
# 
# I seriously think that the TX coalescing support should be ripped out
# or disabled entirely until it is implemented properly in this driver.

I'm doing just that -- disabling it entirely until it is done
properly.

Unfortunately, maintainer does not think delays are huge problem. So I
need your help here.

Thanks,									
									Pavel
diff mbox

Patch

diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 3ced2e1..32ce148 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -244,11 +244,11 @@  struct stmmac_extra_stats {
 /* Max/Min RI Watchdog Timer count value */
 #define MAX_DMA_RIWT		0xff
 #define MIN_DMA_RIWT		0x20
-/* Tx coalesce parameters */
+/* Tx coalesce parameters. Set STMMAC_TX_FRAMES to 0 to disable coalescing. */
 #define STMMAC_COAL_TX_TIMER	40000
 #define STMMAC_MAX_COAL_TX_TICK	100000
 #define STMMAC_TX_MAX_FRAMES	256
-#define STMMAC_TX_FRAMES	64
+#define STMMAC_TX_FRAMES	0
 
 /* Rx IPC status */
 enum rx_frame_status {