[PATCH 2/2] tty: serial: OMAP: transmit FIFO threshold interrupts don't wake the chip

Paul Walmsley paul at pwsan.com
Mon Jan 23 04:49:37 EST 2012


On Mon, 23 Jan 2012, Govindraj wrote:

> On Sat, Jan 21, 2012 at 12:57 PM, Paul Walmsley <paul at pwsan.com> wrote:
> > It seems that when the transmit FIFO threshold is reached on OMAP
> > UARTs, it does not result in a PRCM wakeup.  This appears to be a
> > silicon bug.  This means that if the MPU powerdomain is in a low-power
> > state, the MPU will not be awakened to refill the FIFO until the next
> > interrupt from another device.
> >
> > The best solution, at least for the short term, would be for the OMAP
> > serial driver to call a OMAP subarchitecture function to prevent the
> > MPU powerdomain from entering a low power state while the FIFO has
> > data to transmit.  However, we no longer have a clean way to do this,
> > since patches that add platform_data function pointers have been
> > deprecated by the OMAP maintainer.  So we attempt to work around this
> > as well.  The workarounds depend on the setting of CONFIG_CPU_IDLE.
> >
> > When CONFIG_CPU_IDLE=n, the driver will now only transmit one byte at
> > a time.  This causes the transmit FIFO threshold interrupt to stay
> > active until there is no more data to be sent.  Thus, the MPU
> > powerdomain stays on during transmits.  Aside from that energy
> > consumption penalty, each transmitted byte results in a huge number of
> > UART interrupts -- about five per byte.  This wastes CPU time and is
> > quite inefficient, but is probably the most expedient workaround in
> > this case.
> >
> > When CONFIG_CPU_IDLE=y, there is a slightly more direct workaround:
> > the PM QoS constraint can be abused to keep the MPU powerdomain on.
> > This results in a normal number of interrupts, but, similar to the
> > above workaround, wastes power by preventing the MPU from entering
> > WFI.
> >
> > Future patches are planned for the 3.4 merge window to implement more
> > efficient, but also more disruptive, workarounds to these problems.
> >
> 
> With these two patches number of interrupts seems to increase by 24x
> after boot up.

If you re-read the patch description that you quoted above, you'll see 
that this behavior was clearly mentioned:

> > When CONFIG_CPU_IDLE=n, the driver will now only transmit one byte at
> > a time.  This causes the transmit FIFO threshold interrupt to stay
> > active until there is no more data to be sent.  Thus, the MPU
> > powerdomain stays on during transmits.  Aside from that energy
> > consumption penalty, each transmitted byte results in a huge number of
> > UART interrupts -- about five per byte.  This wastes CPU time and is
> > quite inefficient, but is probably the most expedient workaround in
> > this case.

> / # cat /proc/interrupts | grep "UART2"
>  74:       3902      INTC  OMAP UART2
> / #
> [...]
> 
> without these two patches + cpu_idle enabled

You should compare apples to apples.  The omap-serial.c without these two 
patches is unusable as a console when CONFIG_CPU_IDLE=n; there are long 
lags between transmit FIFO drains.  CONFIG_CPU_IDLE is the setting in the 
standard omap2plus_defconfig.

I guess it was never tested with that standard config?  Or were the
v3.3 omap-serial patch series submitted with this bug known?

> [...]
> 
> / #
> / # cat /proc/interrupts | grep "UART2"
>  74:        158      INTC  OMAP UART2
> / #

The only reason why the driver 'works' when CONFIG_CPU_IDLE=y is because 
the omap-serial.c RX path wakeup latency constraint calculation is broken.  
It adds a 1 microsecond latency constraint to the CPU, when it should be 
adding a ~ 1100 microsecond latency constraint to the CPU.  (Well, ~ 5500 
microsecond, but that's another issue.)

And this keeps the CPU from entering a low-power state not just during 
transmits, but during the entire time the driver is active for the console 
UART.

> I am using beagle xm and 3.3rc1
> 
> Looks like there are far two many uart irqs which
> keeps the mpu busy and thus preventing uart sluggishness.

Yes, that's known behavior, as described in the quoted patch description.  
It's not clear why the number of interrupts is ~5x the number of 
transmitted bytes, rather than say 2x the number of transmitted bytes.  
But the IRQ handler in omap-serial.c is also a mess, so that may have 
something to do with it.

Do you have a better workaround for the CONFIG_CPU_IDLE=n case that 
is acceptable for the -rc series?  If so, perhaps you can post it?


- Paul


More information about the linux-arm-kernel mailing list