GTA01 shared UART vs. flow control (bug #788)
werner at openmoko.org
Tue Jan 22 10:50:12 CET 2008
This is a discussion we're taking from bugzilla to the list, for
greater convenience. The whole background can be found here:
Here's a quick summary. I just stumbled into this one yesterday,
so please excuse (and correct) any misunderstandings.
GTA01 shares its 1st UART between the serial kernel console (i.e.,
the debug board) and the GSM modem. The UART signals are switched
between console and GSM with the GSM_EN line. GSM_EN (and another
signal, simulating the modem's "on" button), is controlled by
writing to /sys/bus/platform/devices/.../power_on
The GSM modem has hardware flow control but the console doesn't.
So what happens is that, if flow control is enabled and the UART
is switched to the serial console, the next printk will hang the
kernel, waiting for flow control to signal that data can be sent.
This state can be reached in various ways:
- if gsmd terminates without restoring the UART settings, and
then the UART is switched back to the console
- if flow control is turned on by accident, while the console is
active, e.g., if gsmd is started without switching first
There are generally two approaches: 1) symptom treatment, i.e.,
not making the kernel hang if the console is stuck, and 2) making
sure we don't enter the problematic configuration.
In the bugzilla thread, two patches have been submitted that try
to solve 2). One is fairly straightforward but misses the case
where flow control is enabled with GSM_EN set to the console. The
other one handles this case, but is complex and intrusive.
I've proposed a "just kill flow control" change that also misses
the scenario where flow control is turned on while GSM_EN selects
the serial console.
I think it's generally a sound principle that the kernel should
try to stay afloat if the serial console gets stuck for some
reason. So I'd like to see a solution for 1). I've outlined an
algorithm in bugzilla that would disable serial console output if
it is stuck for a prolonged time, and automatically re-enable it
if it becomes unstuck.
Solving 1) would ensure that the user can recover from the system
ending up in such an invalid state. (Provided the user is even
aware of the condition.)
I'm not sure if we even need to solve 2) if we have a decent
solution for 1). The main difficulty in solving 2) is that the
console switching code has to tweak the serial driver settings
and that the serial driver has to know the state of the console
switch, so that it can handle requests to enable or disable flow
Naturally, the generic S3C24xx serial driver has no provisions
for doing such things, which makes any patch trying to address
this fairly intrusive.
To me, this looks a bit similar to the dial-in/call-out serial
devices Unix used to feature in the past. There, you had two
logical serial devices that really shared the same physical port.
I'm not sure how hard it would be to put a GSM_EN-aware
"ttyGTA01gsm/ttyGTA01con" on top of ttySAC0, but if layering
serial drivers is a feasible approach, this may be quite clean.
Failing that, a way would have to be found to abstract
platform-specific handling of flow control out of the general
In the discussion, also the wish for more advanced features
appeared. They are a) preserving UART configuration state across
switches, and b) allowing printks through even if the UART is
switched to the GSM modem.
a) would basically correspond to the layered tty case above.
It gives nice semantics, but from a practical point of view, we
probably don't care that much - gsmd will take care of getting
its settings done anyway, and all the console wants is no flow
b) would be messy since switching to the serial console when a
random printk comes along would interrupt communication with the
GSM modem. Now, gsmd seems to have enough issues already if we
don't make things more interesting by adding sporadic data loss :)
Besides, there is always dmesg. Now, there's one case where I
can see a valid exception, and that would be fatal or near-fatal
errors. In that case, it would be reasonable to just flip the
UART over to the serial console and let the kernel utter its
final words. Of course, this should only happen if we actually
have the serial console enabled.
So, I seems to me we can solve all the practical issues by just
keeping the serial console from getting permanently stuck
irrespective of the cause, as outlined above. That should also be
a nice contribution to the platform-independent S3C4xx driver code.
As far as having a nice and clean way of switching between sets of
parameters is concerned, I'm not sure it's actually worth the
trouble. Getting this right promises to be hard work, and most of
the cases a proper solution would have to handle (bit rate ?)
aren't relevant in our scenario anyway.
Finally, I think a switch-on-panic feature would be useful.
If we agree on this course of action, I'd appreciate tested
patches :) I'm not doing much with GTA01 or GSM at the moment, so
I might very well miss some significant scenarios that should be
verified, so I'd rather leave this to someone who has a greater
itch to scratch ;-)
More information about the openmoko-kernel