On my test platform (B2020/STiH416) the serial port issues bad characters
during the initial message avalanche as the console comes up. The problem
also occurs when dense(ish) I/O is done using the polled I/O interface.
The problem is fixed for me by using the FIFO half-empty bit rather than
FIFO full bit. Note that using the half-empty bit causes the FIFO to be
managed in a similar way to interrupt based I/O (i.e. where the hardware
gets best test coverage).
Running the FIFO half full will have no impact (good or bad) on console
performance. The UART will still remain fully saturated and the busy-wait
until the FIFO is empty in asc_console_write() will complete at the same
time.
Signed-off-by: Daniel Thompson <daniel.thompson(a)linaro.org>
---
drivers/tty/serial/st-asc.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c
index dd3a96e..c7f61ac 100644
--- a/drivers/tty/serial/st-asc.c
+++ b/drivers/tty/serial/st-asc.c
@@ -194,9 +194,9 @@ static inline u32 asc_txfifo_is_empty(struct uart_port *port)
return asc_in(port, ASC_STA) & ASC_STA_TE;
}
-static inline int asc_txfifo_is_full(struct uart_port *port)
+static inline u32 asc_txfifo_is_half_empty(struct uart_port *port)
{
- return asc_in(port, ASC_STA) & ASC_STA_TF;
+ return asc_in(port, ASC_STA) & ASC_STA_THE;
}
static inline const char *asc_port_name(struct uart_port *port)
@@ -628,7 +628,7 @@ static int asc_get_poll_char(struct uart_port *port)
static void asc_put_poll_char(struct uart_port *port, unsigned char c)
{
- while (asc_txfifo_is_full(port))
+ while (!asc_txfifo_is_half_empty(port))
cpu_relax();
asc_out(port, ASC_TXBUF, c);
}
@@ -783,7 +783,7 @@ static void asc_console_putchar(struct uart_port *port, int ch)
unsigned int timeout = 1000000;
/* Wait for upto 1 second in case flow control is stopping us. */
- while (--timeout && asc_txfifo_is_full(port))
+ while (--timeout && !asc_txfifo_is_half_empty(port))
udelay(1);
asc_out(port, ASC_TXBUF, ch);
--
1.9.0
Dear Linaro term:
this is my system status:
kernel version: 3.10
kernel/user space split: 1G/3G
system memory: 2GB
lowmem/vmalloc: 760MB/240MB
CMA reverse: 512MB
If CMA is placed in the lowmem area, it is working fine; when i move it
to high zone, it working abnomaly:
<1>[ 647.755598] Unhandled fault: imprecise external abort (0x1c06) at
0x76429000
<0>[ 647.755621] Internal error: : 1c06 [#1] PREEMPT SMP ARM
<4>[ 647.755633] Modules linked in:
<4>[ 647.755648] CPU: 1 PID: 162 Comm: Binder_1 Not tainted 3.10.0 #48
<4>[ 647.755676] task: d6ac3700 ti: c576e000 task.ti: c576e000
<4>[ 647.755700] PC is at __memzero+0x28/0x80
<4>[ 647.755710] LR is at 0x0
<4>[ 647.755720] pc : [<c0250fa8>] lr : [<00000000>] psr: 20030013
<4>[ 0.000000] sp : c576fdd4 ip : 00000000 fp : 00b40000
<4>[ 647.755742] r10: 00000000 r9 : c0c18000 r8 : bff87000
<4>[ 647.755755] r7 : 00b38000 r6 : c1490100 r5 : c1490000 r4 : 00b40000
<4>[ 647.755768] r3 : 00000000 r2 : 00000000 r1 : 00000e80 r0 : bff87150
<4>[ 647.755783] Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment
user
<4>[ 647.755799] Control: 10c5387d Table: 0560406a DAC: 00000015
Hi Thomas,
As suggested by you (https://lkml.org/lkml/2014/5/10/86), here is an attempt to
implement first two steps for fixing the bigger problem.
This patchset is about adding ->set_dev_mode() to struct clock_event_device with
return type 'int'. To achieve that return type of clockevents_set_mode() is also
changed to propagate failures.
Let me know if this is what you wanted to see or I screwed up again :(
I will then start updating drivers one by one (100 drivers AFAICT). I will try to
fix them in separate patches and will post them together in a single patchset.
And because the number is going to be over 100, let me know how do you want me
to send that..
Viresh Kumar (2):
clockevents: return 'int' from clockevents_set_mode()
clockevents: add ->set_dev_mode() to struct clock_event_device
arch/arm/common/bL_switcher.c | 5 +++--
include/linux/clockchips.h | 7 +++++--
kernel/time/clockevents.c | 34 +++++++++++++++++++++++++---------
kernel/time/tick-broadcast.c | 25 ++++++++++++++++---------
kernel/time/tick-common.c | 6 +++---
kernel/time/tick-oneshot.c | 6 +++---
kernel/time/timer_list.c | 9 +++++++--
7 files changed, 62 insertions(+), 30 deletions(-)
--
2.0.0.rc2
This happened for me during my NO_HZ_FULL testing on isolated CPU, but may
happen otherwise as well.
When the last htimer of a CPU is cancelled (For example: for NO_HZ_FULL when
expires == KTIME_MAX), we do not SHUTDOWN the event device. And because of that
we will get interrupted unnecessarily on the isolated core as event device will
interrupt as per the last value it is configured with.
The implementation of event device's driver may make it worse. For example:
drivers/clocksource/arm_arch_timer.c disables the event device only on
SHUTDOWN/UNUSED requests in set-mode. Otherwise, it will keep giving interrupts
at tick interval even if hrtimer_interrupt() didn't reprogram tick (When expires
== KTIME_MAX). And so we will keep getting interrupt every few milliseconds. To
confirm this I added a small hack in hrtimer.c [1] and got these results [2] as
soon as the CPU got isolated with NO_HZ_FULL and cpusets.
Probably the right solution to fix this is to disable the event device for such
cases, i.e. expires == KTIME_MAX and restart it later when required. This will
get rid of unnecessary interruption which can be avoided.
Tested over 3.15-rc4 on ARM Exynos5250 (Dual A15) board.
NOTE: Current implementation of NO_HZ_FULL has a limitation of 1 second and so
we might never end up cancelling sched_timer. I was using Kevin's debug patch:
https://lkml.org/lkml/2013/12/17/649, with which I am able to get expires to
KTIME_MAX and so ended up cancelling hrtimer.
[1] http://pastebin.com/MhDdawVd
[2] http://pastebin.com/5U5FBbTW
Viresh Kumar (2):
hrtimer: reprogram event for expires=KTIME_MAX in
hrtimer_force_reprogram()
tick: SHUTDOWN event-dev if no events are required for KTIME_MAX
include/linux/clockchips.h | 1 +
kernel/hrtimer.c | 3 +--
kernel/time/tick-oneshot.c | 14 +++++++++++++-
3 files changed, 15 insertions(+), 3 deletions(-)
--
2.0.0.rc2