Using last device file to access 8250 uart causes transfer issues

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello linux-serial.


I have been experiencing some strangeness using the 8250 Linux uart
driver on a legacy ISA based embedded platform in an attempt to upgrade
an older Linux 2.6.37 based system to a more recent kernel. A number of
kernel releases has been tested including 4.6.0-rc6 (see complete list
below) that all behave similarly.

The hardware consist of an Axiomtek AX12260 SoM [1] on top of a custom
i/o board containing three SC16C2550B [2] dual uarts. The uarts are
connected to the SoM's ISA bus (via PC/104 connector) with fixed irq/io
configuration (no irq sharing) as follows.

Uart    io      irq
------------------
UART1A  0x03f8   4
UART1B  0x02f8   3
UART2A  0x03e8   7
UART2B  0x02e8   5
UART3A  0x02f0  10
UART3B  0x03e0  11

Also the uart oscillators are 3.6864MHz (double of the standard/normal
1.8432MHz).

Booting the kernel six uarts are reported/detected (NR_UARTS=6, see
dmesg/config below) and the first four are autoconf'ed to correct io but
2A+2B with incorrect irq consistent with defaults in asm/serial.h [3].
Correct io/irq/baud_base are set from user-space using setserial,
mapping the uarts to device files ttyS0-ttyS5 in the above order and
doubling baud_base to 230400.

The serial ports that use device files ttyS0-4 behave as expected, but
the last port (UART3B on /dev/ttyS5) does not work. Meaning I am unable
to communicate with the gsm modem connected to it.

This definitely has a "off-by-one" feel to it and I tried a simple
CONFIG_SERIAL_8250_NR_UARTS=7 but that yields no difference. However,
after much debugging and testing I have determined that by remapping
io/irq on the device file using setserial I am able to bring UART3B into
a functional state by accessing it through a device file other than
ttyS5. And additionally, anyone of the other uarts configured to use the
device file /dev/ttyS5 stops working.

Below are kernel logs with the 8250 driver's DEBUG_INTR enabled [4] when
attempting to communicate with the modem through UART3B configured to
use device files ttyS1 and ttyS5 respectively (full kernel info below).
The tests were done by writing an AT NOP command to the device using
"echo at >/dev/ttyS*" and monitoring the modem's echo and "OK" response
in another shell using "cat /dev/ttyS*" (the modem is by default in
autobaud mode so baudrate shouldn't matter).
Using ttyS1 I see the echo and response on the shell as expected but
using ttyS5 nothing is received:

--- interrupt test
** ttyS5  (no response)
May 17 11:20:14 ax12260 user.warn kernel:
serial8250_interrupt(11)...status = 60...THRE...end.
May 17 11:20:14 ax12260 user.warn kernel:
serial8250_interrupt(11)...status = 20...end.
May 17 11:20:28 ax12260 user.warn kernel: serial8250_interrupt(11)...end.

** ttyS1  (echo + response received)
May 17 11:17:40 ax12260 user.warn kernel:
serial8250_interrupt(11)...status = 60...THRE...end.
May 17 11:17:40 ax12260 user.warn kernel:
serial8250_interrupt(11)...status = 20...end.
May 17 11:17:40 ax12260 user.warn kernel:
serial8250_interrupt(11)...status = 61...end.
May 17 11:17:40 ax12260 user.warn kernel:
serial8250_interrupt(11)...status = 60...THRE...end.
May 17 11:17:40 ax12260 user.warn kernel:
serial8250_interrupt(11)...status = 1...end.
May 17 11:17:40 ax12260 user.warn kernel:
serial8250_interrupt(11)...status = 20...THRE...end.
May 17 11:18:56 ax12260 user.warn kernel: serial8250_interrupt(11)...end.
---

The "status" value above refer to the contents of the LSR register in
serial8250_handle_irq() [5] as described at [6], chapter 7.7, p. 22-23. Thus
0x01 is LSR[0]=Receive data ready
0x20 is LSR[5]=THR empty (THRE)
0x40 is LSR[6]=THR and TSR empty

As can be seen, transmit interrupts are generated and bytes seem to be
transmitted in both cases. But somehow no Receive data ready interrupts
are handled by serial8250_handle_irq() at all when using ttyS5 as device
file.

My first thought was that receive interrupts could somehow be cancelled
by generic interrupt handling before being handed over to serial8250.
But writing this post also gave me a hunch that it might be caused by
the baud_base not being respected when using ttyS5.
As far as I can see that might create the same scenario; bytes going out
(with wrong timing), and uart discarding received bytes because of
seemingly incorrect timing (if the other end responds to the unexpected
baudrate at all). Inspecting the baud_base values reported by setserial
for ttyS0-5 there is no indication that 5 should behave differently.

Anybody who can see flaws in my tests or reasoning? Or are having deeper
insight than me into the serial stack to be able to confirm/reject that
there could be problems with baud_base in unusual configurations like
the one outline here?

I think my next step will be to do some measurements on tx to test the
wrong effective baud_base theory. Haven't done measurements before
because signals to the gsm modem is not very accessible, but now that I
am able to recreate the error on the other uarts I have a lot more
options of finding accessible test points.


-- 
Thanks & regards,
Mikkel


[1]
http://www.axiomtek.com/Default.aspx?MenuId=Products&FunctionId=ProductView&ItemId=567

[2]
http://www.nxp.com/products/interface-and-connectivity/wired-connectivity/uarts/two-channel/5-v-3.3-v-and-2.5-v-dual-uart-5-mbit-s-max.-with-16-byte-fifos:SC16C2550B

[3] http://lxr.free-electrons.com/source/arch/x86/include/asm/serial.h?v=4.1

[4]
http://lxr.free-electrons.com/source/drivers/tty/serial/8250/8250_core.c?v=4.1#L77

[5]
http://lxr.free-electrons.com/source/drivers/tty/serial/8250/8250_core.c?v=4.1#L1631

[6] http://www.nxp.com/documents/data_sheet/SC16C2550B.pdf


--- tested and failing kernels
3.19 (yocto-kernel, 3.19 (LTSI))
4.1.22-yocto-standard (yocto-kernel, 4.1)
4.6.0-rc6-yocto-standard (yocto-kernel-dev)
---

--- interrupt debug kernel information
root@ax12260:~# uname -a
Linux ax12260 4.1.22-yocto-standard #1 SMP PREEMPT Tue May 10 15:03:38
CEST 2016 i586 GNU/Linux

root@ax12260:~# cat /var/log/dmesg |grep 8250 -A1 -B1
io scheduler cfq registered (default)
Serial: 8250/16550 driver, 6 ports, IRQ sharing disabled
ttyS0: autoconf (0x03f8, 0x (null)): iir1=6 iir2=6 iir=3 type=16550A
serial8250: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
ttyS1: autoconf (0x02f8, 0x (null)): iir1=6 iir2=6 iir=3 type=16550A
serial8250: ttyS1 at I/O 0x2f8 (irq = 3, base_baud = 115200) is a 16550A
ttyS2: autoconf (0x03e8, 0x (null)): iir1=6 iir2=6 iir=3 type=16550A
serial8250: ttyS2 at I/O 0x3e8 (irq = 4, base_baud = 115200) is a 16550A
ttyS3: autoconf (0x02e8, 0x (null)): iir1=6 iir2=6 iir=3 type=16550A
serial8250: ttyS3 at I/O 0x2e8 (irq = 3, base_baud = 115200) is a 16550A
Linux agpgart interface v0.103

root@ax12260:~# zcat /proc/config.gz |grep 8250
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
CONFIG_SERIAL_8250_PNP=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=6
CONFIG_SERIAL_8250_RUNTIME_UARTS=6
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
# CONFIG_SERIAL_8250_SHARE_IRQ is not set
# CONFIG_SERIAL_8250_DETECT_IRQ is not set
# CONFIG_SERIAL_8250_RSA is not set
# CONFIG_SERIAL_8250_DW is not set
# CONFIG_SERIAL_8250_FINTEK is not set
# Non-8250 serial port support
---


Attachment: signature.asc
Description: OpenPGP digital signature


[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux