<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux.git/drivers/serial/8250.c, branch master</title>
<subtitle>Linux kernel source tree</subtitle>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/'/>
<entry>
<title>tty: move drivers/serial/ to drivers/tty/serial/</title>
<updated>2011-01-13T20:10:18+00:00</updated>
<author>
<name>Greg Kroah-Hartman</name>
<email>gregkh@suse.de</email>
</author>
<published>2011-01-13T20:10:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=ab4382d27412e7e3e7c936e8d50d8888dfac3df8'/>
<id>ab4382d27412e7e3e7c936e8d50d8888dfac3df8</id>
<content type='text'>
The serial drivers are really just tty drivers, so move them to
drivers/tty/ to make things a bit neater overall.

This is part of the tty/serial driver movement proceedure as proposed by
Arnd Bergmann and approved by everyone involved a number of months ago.

Cc: Arnd Bergmann &lt;arnd@arndb.de&gt;
Cc: Alan Cox &lt;alan@lxorguk.ukuu.org.uk&gt;
Cc: Geert Uytterhoeven &lt;geert@linux-m68k.org&gt;
Cc: Rogier Wolff &lt;R.E.Wolff@bitwizard.nl&gt;
Cc: Michael H. Warfield &lt;mhw@wittsend.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The serial drivers are really just tty drivers, so move them to
drivers/tty/ to make things a bit neater overall.

This is part of the tty/serial driver movement proceedure as proposed by
Arnd Bergmann and approved by everyone involved a number of months ago.

Cc: Arnd Bergmann &lt;arnd@arndb.de&gt;
Cc: Alan Cox &lt;alan@lxorguk.ukuu.org.uk&gt;
Cc: Geert Uytterhoeven &lt;geert@linux-m68k.org&gt;
Cc: Rogier Wolff &lt;R.E.Wolff@bitwizard.nl&gt;
Cc: Michael H. Warfield &lt;mhw@wittsend.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Merge branch 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6</title>
<updated>2011-01-07T22:39:20+00:00</updated>
<author>
<name>Linus Torvalds</name>
<email>torvalds@linux-foundation.org</email>
</author>
<published>2011-01-07T22:39:20+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=56b85f32d530d09d6805488ad00775d4e0e3baab'/>
<id>56b85f32d530d09d6805488ad00775d4e0e3baab</id>
<content type='text'>
* 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (36 commits)
  serial: apbuart: Fixup apbuart_console_init()
  TTY: Add tty ioctl to figure device node of the system console.
  tty: add 'active' sysfs attribute to tty0 and console device
  drivers: serial: apbuart: Handle OF failures gracefully
  Serial: Avoid unbalanced IRQ wake disable during resume
  tty: fix typos/errors in tty_driver.h comments
  pch_uart : fix warnings for 64bit compile
  8250: fix uninitialized FIFOs
  ip2: fix compiler warning on ip2main_pci_tbl
  specialix: fix compiler warning on specialix_pci_tbl
  rocket: fix compiler warning on rocket_pci_ids
  8250: add a UPIO_DWAPB32 for 32 bit accesses
  8250: use container_of() instead of casting
  serial: omap-serial: Add support for kernel debugger
  serial: fix pch_uart kconfig &amp; build
  drivers: char: hvc: add arm JTAG DCC console support
  RS485 documentation: add 16C950 UART description
  serial: ifx6x60: fix memory leak
  serial: ifx6x60: free IRQ on error
  Serial: EG20T: add PCH_UART driver
  ...

Fixed up conflicts in drivers/serial/apbuart.c with evil merge that
makes the code look fairly sane (unlike either side).
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
* 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (36 commits)
  serial: apbuart: Fixup apbuart_console_init()
  TTY: Add tty ioctl to figure device node of the system console.
  tty: add 'active' sysfs attribute to tty0 and console device
  drivers: serial: apbuart: Handle OF failures gracefully
  Serial: Avoid unbalanced IRQ wake disable during resume
  tty: fix typos/errors in tty_driver.h comments
  pch_uart : fix warnings for 64bit compile
  8250: fix uninitialized FIFOs
  ip2: fix compiler warning on ip2main_pci_tbl
  specialix: fix compiler warning on specialix_pci_tbl
  rocket: fix compiler warning on rocket_pci_ids
  8250: add a UPIO_DWAPB32 for 32 bit accesses
  8250: use container_of() instead of casting
  serial: omap-serial: Add support for kernel debugger
  serial: fix pch_uart kconfig &amp; build
  drivers: char: hvc: add arm JTAG DCC console support
  RS485 documentation: add 16C950 UART description
  serial: ifx6x60: fix memory leak
  serial: ifx6x60: free IRQ on error
  Serial: EG20T: add PCH_UART driver
  ...

Fixed up conflicts in drivers/serial/apbuart.c with evil merge that
makes the code look fairly sane (unlike either side).
</pre>
</div>
</content>
</entry>
<entry>
<title>8250: fix uninitialized FIFOs</title>
<updated>2010-12-10T23:22:25+00:00</updated>
<author>
<name>Ondrej Puzman</name>
<email>puzman@gmail.com</email>
</author>
<published>2010-12-04T20:17:38+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=e4f05af136016958f52455da3070ca6622439b10'/>
<id>e4f05af136016958f52455da3070ca6622439b10</id>
<content type='text'>
I have found a bug in 8250.c driver which causes that 16550A uart FIFOs
are not turned on during initialization if they are manually configured
by setserial. UART is then working only as plain 16450 without FIFOs. On
systems with higher interrupt latency this causes buffer overruns and
loss of received data when using higher communication speeds.

I'm working for a company which produces industrial computers. These
devices typically contain high number (8 or more) of traditional 16550A
uarts - we use TL16C554A chips, but that is not much relevant. UARTs are
connected to the CPU by ISA bus (Celeron based devices) or LPC bus (Atom
based devices).

In the Linux the UARTs are using standard 8250.c driver and are
initialized using setserial command:
setserial /dev/ttyS4 uart 16550A port 0x3E0 irq 10 baud_base 115200

This executes the UART initialization through serial8250_startup()
function. At the beginning of the function up-&gt;capabilities is
initialized from uart_config:
 up-&gt;capabilities = uart_config[up-&gt;port.type].flags;
Please note that neither up-&gt;port.fifosize nor up-&gt;tx_loadsz is
initialized here!!

Later in the same function serial8250_clear_fifos() is called and
disables FIFOs. The above comment says that they will be reenabled in
set_termios (they won't ...)

After serial8250_startup() the serial8250_set_termios() is called. In
this function the following check fails because up-&gt;port.fifosize is
zero because it is not initialized correctly.

        if (up-&gt;capabilities &amp; UART_CAP_FIFO &amp;&amp; up-&gt;port.fifosize &gt; 1) {
                if (baud &lt; 2400)
                        fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
                else
                        fcr = uart_config[up-&gt;port.type].fcr;
        }

fcr variable remains zero and in the end the FCR register is set to zero
which results in disabled FIFOs even if the UART type is 16550A. This is
also true for other types of UARTs with FIFOs.

If the UART is autoconfigured via 'setserial /dev/ttySx autoconfig' then
port.fifosize and tx_loadsz are initialized correctly in the
autoconfig() function and the UART is working correctly then.

I checked the source codes and I can say that this bug is present in
2.6.x series of kernels for a couple of years. Namely I can confirm its
presence in 2.6.16.57, 2.6.32.24 and 2.6.36.1 (tested all of them on our
hardware).

I think it was not noticed before because not many people use manually
configured non PNP UARTs on ISA/LPC bus these days. Also the data loss
caused by buffer overruns occures only if  IRQ latency is higher then
time needed to receive one character on given communication speed.
For example our hardware looses received characters only if the UARTs
are connected throught LPC bus with SERIRQ (serial IRQ transport) and
not if they are connected to ISA bus because LPC SERIRQ has higher
interrupt latency then parallel ISA interupt lines.

Here is the patch to correct the bug created against 2.6.36.1:

Signed-off-by: Ondrej Puzman &lt;puzman@gmail.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
I have found a bug in 8250.c driver which causes that 16550A uart FIFOs
are not turned on during initialization if they are manually configured
by setserial. UART is then working only as plain 16450 without FIFOs. On
systems with higher interrupt latency this causes buffer overruns and
loss of received data when using higher communication speeds.

I'm working for a company which produces industrial computers. These
devices typically contain high number (8 or more) of traditional 16550A
uarts - we use TL16C554A chips, but that is not much relevant. UARTs are
connected to the CPU by ISA bus (Celeron based devices) or LPC bus (Atom
based devices).

In the Linux the UARTs are using standard 8250.c driver and are
initialized using setserial command:
setserial /dev/ttyS4 uart 16550A port 0x3E0 irq 10 baud_base 115200

This executes the UART initialization through serial8250_startup()
function. At the beginning of the function up-&gt;capabilities is
initialized from uart_config:
 up-&gt;capabilities = uart_config[up-&gt;port.type].flags;
Please note that neither up-&gt;port.fifosize nor up-&gt;tx_loadsz is
initialized here!!

Later in the same function serial8250_clear_fifos() is called and
disables FIFOs. The above comment says that they will be reenabled in
set_termios (they won't ...)

After serial8250_startup() the serial8250_set_termios() is called. In
this function the following check fails because up-&gt;port.fifosize is
zero because it is not initialized correctly.

        if (up-&gt;capabilities &amp; UART_CAP_FIFO &amp;&amp; up-&gt;port.fifosize &gt; 1) {
                if (baud &lt; 2400)
                        fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
                else
                        fcr = uart_config[up-&gt;port.type].fcr;
        }

fcr variable remains zero and in the end the FCR register is set to zero
which results in disabled FIFOs even if the UART type is 16550A. This is
also true for other types of UARTs with FIFOs.

If the UART is autoconfigured via 'setserial /dev/ttySx autoconfig' then
port.fifosize and tx_loadsz are initialized correctly in the
autoconfig() function and the UART is working correctly then.

I checked the source codes and I can say that this bug is present in
2.6.x series of kernels for a couple of years. Namely I can confirm its
presence in 2.6.16.57, 2.6.32.24 and 2.6.36.1 (tested all of them on our
hardware).

I think it was not noticed before because not many people use manually
configured non PNP UARTs on ISA/LPC bus these days. Also the data loss
caused by buffer overruns occures only if  IRQ latency is higher then
time needed to receive one character on given communication speed.
For example our hardware looses received characters only if the UARTs
are connected throught LPC bus with SERIRQ (serial IRQ transport) and
not if they are connected to ISA bus because LPC SERIRQ has higher
interrupt latency then parallel ISA interupt lines.

Here is the patch to correct the bug created against 2.6.36.1:

Signed-off-by: Ondrej Puzman &lt;puzman@gmail.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>8250: add a UPIO_DWAPB32 for 32 bit accesses</title>
<updated>2010-12-10T23:19:38+00:00</updated>
<author>
<name>Jamie Iles</name>
<email>jamie@jamieiles.com</email>
</author>
<published>2010-12-01T23:39:36+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=a3ae0fc34f58e7163b7724feb3d77aa4603f0dc3'/>
<id>a3ae0fc34f58e7163b7724feb3d77aa4603f0dc3</id>
<content type='text'>
Some platforms contain a Synopsys DesignWare APB UART that is attached
to a 32-bit APB bus where sub-word accesses are not allowed. Add a new
IO type (UPIO_DWAPB32) that performs 32 bit acccesses to the UART.

v2:
	- don't test for 32 bit in the output fast path, provide a
	  separate dwabp32_serial_out() function. Refactor
	  dwabp_serial_out() so that we can reuse the LCR saving
	  code.
v3:
	- rebased on top of "8250: use container_of() instead of
	  casting"

Signed-off-by: Jamie Iles &lt;jamie@jamieiles.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Some platforms contain a Synopsys DesignWare APB UART that is attached
to a 32-bit APB bus where sub-word accesses are not allowed. Add a new
IO type (UPIO_DWAPB32) that performs 32 bit acccesses to the UART.

v2:
	- don't test for 32 bit in the output fast path, provide a
	  separate dwabp32_serial_out() function. Refactor
	  dwabp_serial_out() so that we can reuse the LCR saving
	  code.
v3:
	- rebased on top of "8250: use container_of() instead of
	  casting"

Signed-off-by: Jamie Iles &lt;jamie@jamieiles.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>8250: use container_of() instead of casting</title>
<updated>2010-12-10T23:19:37+00:00</updated>
<author>
<name>Jamie Iles</name>
<email>jamie@jamieiles.com</email>
</author>
<published>2010-12-01T23:39:35+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=49d5741be27aa90301b89bf254972b355ed9c8ee'/>
<id>49d5741be27aa90301b89bf254972b355ed9c8ee</id>
<content type='text'>
The 8250 driver structure uart_8250_port took advantage of the fact
that the struct uart_port was the first member of its structure and
used an explicit cast to convert to the derived class. Replace the
explicit casts with container_of() for safety and clarity.

Signed-off-by: Jamie Iles &lt;jamie@jamieiles.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The 8250 driver structure uart_8250_port took advantage of the fact
that the struct uart_port was the first member of its structure and
used an explicit cast to convert to the derived class. Replace the
explicit casts with container_of() for safety and clarity.

Signed-off-by: Jamie Iles &lt;jamie@jamieiles.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Merge branch 'devel-omap-irq' into omap-for-linus</title>
<updated>2010-12-10T17:44:39+00:00</updated>
<author>
<name>Tony Lindgren</name>
<email>tony@atomide.com</email>
</author>
<published>2010-12-10T17:44:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=67b738ef32df7ec429004866d2a739a3775894d2'/>
<id>67b738ef32df7ec429004866d2a739a3775894d2</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>omap: Serial: Define register access modes in LCR</title>
<updated>2010-11-30T22:11:49+00:00</updated>
<author>
<name>Andrei Emeltchenko</name>
<email>andrei.emeltchenko@nokia.com</email>
</author>
<published>2010-11-30T22:11:49+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=662b083a87a3489f3f19c6e0651c1b99b0de5df0'/>
<id>662b083a87a3489f3f19c6e0651c1b99b0de5df0</id>
<content type='text'>
Access to some registers depends on register access mode
Three different modes are available for OMAP (at least)
• Operational mode     LCR_REG[7] = 0x0
• Configuration mode A LCR_REG[7] = 0x1 and LCR_REG[7:0]! = 0xBF
• Configuration mode B LCR_REG[7] = 0x1 and LCR_REG[7:0]  = 0xBF

Define access modes and remove redefinitions and magic numbers
in serial drivers (and later in bluetooth driver).

Signed-off-by: Andrei Emeltchenko &lt;andrei.emeltchenko@nokia.com&gt;
Acked-by: Govindraj.R &lt;govindraj.raja@ti.com&gt;
Acked-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;
Signed-off-by: Tony Lindgren &lt;tony@atomide.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Access to some registers depends on register access mode
Three different modes are available for OMAP (at least)
• Operational mode     LCR_REG[7] = 0x0
• Configuration mode A LCR_REG[7] = 0x1 and LCR_REG[7:0]! = 0xBF
• Configuration mode B LCR_REG[7] = 0x1 and LCR_REG[7:0]  = 0xBF

Define access modes and remove redefinitions and magic numbers
in serial drivers (and later in bluetooth driver).

Signed-off-by: Andrei Emeltchenko &lt;andrei.emeltchenko@nokia.com&gt;
Acked-by: Govindraj.R &lt;govindraj.raja@ti.com&gt;
Acked-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;
Signed-off-by: Tony Lindgren &lt;tony@atomide.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>serial8250: Mark console as CON_ANYTIME</title>
<updated>2010-11-16T21:29:54+00:00</updated>
<author>
<name>Peter Zijlstra</name>
<email>peterz@infradead.org</email>
</author>
<published>2010-11-15T20:11:12+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=a80c49dbb6cd389fd5b0d79f850b56322475d00b'/>
<id>a80c49dbb6cd389fd5b0d79f850b56322475d00b</id>
<content type='text'>
While trying to debug a cpu-hotplug issue I noticed printk() stopped
working once the cpu got marked offline, since the 8250 serial console
doesn't have any per-cpu resources the CON_ANYTIME bit is the safe and
documented way to make it work again.

Signed-off-by: Peter Zijlstra &lt;a.p.zijlstra@chello.nl&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
While trying to debug a cpu-hotplug issue I noticed printk() stopped
working once the cpu got marked offline, since the 8250 serial console
doesn't have any per-cpu resources the CON_ANYTIME bit is the safe and
documented way to make it work again.

Signed-off-by: Peter Zijlstra &lt;a.p.zijlstra@chello.nl&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Revert "8250: Fix tcsetattr to avoid ioctl(TIOCMIWAIT) hang"</title>
<updated>2010-11-13T17:59:19+00:00</updated>
<author>
<name>Ingo Molnar</name>
<email>mingo@elte.hu</email>
</author>
<published>2010-11-13T15:21:58+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=f8b372a11cc102b9a0dcc6ac2bd10f0b6b2755a9'/>
<id>f8b372a11cc102b9a0dcc6ac2bd10f0b6b2755a9</id>
<content type='text'>
This reverts commit 47d3904fe40d62deee8cd46e79ca784e7a548acd.

Crashes any x86 serial console bootup:

  Console: colour VGA+ 80x25
  BUG: unable to handle kernel NULL pointer dereference at 0000000000000158
  IP: [&lt;ffffffff811ebcb4&gt;] serial8250_do_set_termios+0x1d4/0x430
  ...

Signed-off-by: Ingo Molnar &lt;mingo@elte.hu&gt;
Cc: Greg KH &lt;gregkh@suse.de&gt;
Cc: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Cc: Alan Cox &lt;alan@lxorguk.ukuu.org.uk&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This reverts commit 47d3904fe40d62deee8cd46e79ca784e7a548acd.

Crashes any x86 serial console bootup:

  Console: colour VGA+ 80x25
  BUG: unable to handle kernel NULL pointer dereference at 0000000000000158
  IP: [&lt;ffffffff811ebcb4&gt;] serial8250_do_set_termios+0x1d4/0x430
  ...

Signed-off-by: Ingo Molnar &lt;mingo@elte.hu&gt;
Cc: Greg KH &lt;gregkh@suse.de&gt;
Cc: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Cc: Alan Cox &lt;alan@lxorguk.ukuu.org.uk&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>8250: Fix tcsetattr to avoid ioctl(TIOCMIWAIT) hang</title>
<updated>2010-11-11T18:51:35+00:00</updated>
<author>
<name>Lawrence Rust</name>
<email>lvr@softsystem.co.uk</email>
</author>
<published>2010-10-27T12:41:02+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=47d3904fe40d62deee8cd46e79ca784e7a548acd'/>
<id>47d3904fe40d62deee8cd46e79ca784e7a548acd</id>
<content type='text'>
Calling tcsetattr prevents any thread(s) currently suspended in ioctl
TIOCMIWAIT for the same device from ever resuming.

If a thread is suspended inside a call to ioctl TIOCMIWAIT, waiting for
a modem status change, then the 8250 driver enables modem status
interrupts (MSI).  The device interrupt service routine resumes the
suspended thread(s) on the next MSI.

If while the thread(s) are suspended, another thread calls tcsetattr
then the 8250 driver disables MSI (unless CTS/RTS handshaking is
enabled) thus preventing the suspended thread(s) from ever being
resumed.

This patch only disables MSI in tcsetattr handling if there are no
suspended threads.

Program to demonstrate bug &amp; fix:

/* gcc miwait.c -o miwait -l pthread */
#include &lt;stdio.h&gt;
#include &lt;errno.h&gt;
#include &lt;unistd.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;pthread.h&gt;
#include &lt;termios.h&gt;
#include &lt;sys/ioctl.h&gt;
#include &lt;linux/serial.h&gt;

static void* monitor( void* pv);
static int s_fd;

int main( void)
  {
  const char kszDev[] = "/dev/ttyS0";
  pthread_t t;
  struct termios tio;

  s_fd = open( kszDev, O_RDWR | O_NONBLOCK);
  if ( s_fd &lt; 0)
    return fprintf( stderr, "Error(%d) opening %s: %s\n", errno, kszDev, strerror( errno)), 1;

  pthread_create( &amp;t, NULL, &amp;monitor, NULL);

  /* Modem status changes seen here */
  puts( "Main: awaiting status changes");
  sleep( 5);

  tcgetattr( s_fd, &amp;tio);
  tio.c_cflag ^= CSTOPB;

  /* But not after here */
  puts( "Main: tcsetattr called");
  tcsetattr( s_fd, TCSANOW, &amp;tio);

  for (;;)
    sleep( 1);
  }

static void* monitor( void* pv)
  {
  (void)pv;
  for(;;)
    {
    unsigned uModem;
    struct serial_icounter_struct cnt;

    if ( ioctl( s_fd, TIOCMGET, &amp;uModem) &lt; 0)
      fprintf( stderr, "Error(%d) in TIOCMGET: %s\n", errno, strerror( errno));
    printf( "Modem status:%s%s%s%s%s%s\n",
      (uModem &amp; TIOCM_RTS) ? " RTS" : "",
      (uModem &amp; TIOCM_DTR) ? " DTR" : "",
      (uModem &amp; TIOCM_CTS) ? " CTS" : "",
      (uModem &amp; TIOCM_DSR) ? " DSR" : "",
      (uModem &amp; TIOCM_CD) ? " CD" : "",
      (uModem &amp; TIOCM_RI) ? " RI" : ""
    );

    if ( ioctl( s_fd, TIOCGICOUNT, &amp;cnt) &lt; 0)
      fprintf( stderr, "Error(%d) in TIOCGICOUNT: %s\n", errno, strerror( errno));
    printf( "Irqs: CTS:%d DSR:%d RNG:%d DCD:%d Rx:%d Tx:%d Frame:%d Orun:%d Par:%d Brk:%d Oflow:%d\n",
      cnt.cts, cnt.dsr, cnt.rng, cnt.dcd,
      cnt.rx, cnt.tx, cnt.frame, cnt.overrun, cnt.parity,
      cnt.brk, cnt.buf_overrun
    );

    fputs( "Waiting...", stdout), fflush( stdout);
    if ( 0 &gt; ioctl( s_fd, TIOCMIWAIT, (unsigned long)(TIOCM_CAR | TIOCM_RNG | TIOCM_DSR | TIOCM_CTS)))
      fprintf( stderr, "\nError(%d) in TIOCMIWAIT: %s\n", errno, strerror( errno));
    fputs( "\n", stdout);
    }
  return NULL;
  }

Signed-off by Lawrence Rust &lt;lawrence@softsystem.co.uk&gt;

Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Calling tcsetattr prevents any thread(s) currently suspended in ioctl
TIOCMIWAIT for the same device from ever resuming.

If a thread is suspended inside a call to ioctl TIOCMIWAIT, waiting for
a modem status change, then the 8250 driver enables modem status
interrupts (MSI).  The device interrupt service routine resumes the
suspended thread(s) on the next MSI.

If while the thread(s) are suspended, another thread calls tcsetattr
then the 8250 driver disables MSI (unless CTS/RTS handshaking is
enabled) thus preventing the suspended thread(s) from ever being
resumed.

This patch only disables MSI in tcsetattr handling if there are no
suspended threads.

Program to demonstrate bug &amp; fix:

/* gcc miwait.c -o miwait -l pthread */
#include &lt;stdio.h&gt;
#include &lt;errno.h&gt;
#include &lt;unistd.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;pthread.h&gt;
#include &lt;termios.h&gt;
#include &lt;sys/ioctl.h&gt;
#include &lt;linux/serial.h&gt;

static void* monitor( void* pv);
static int s_fd;

int main( void)
  {
  const char kszDev[] = "/dev/ttyS0";
  pthread_t t;
  struct termios tio;

  s_fd = open( kszDev, O_RDWR | O_NONBLOCK);
  if ( s_fd &lt; 0)
    return fprintf( stderr, "Error(%d) opening %s: %s\n", errno, kszDev, strerror( errno)), 1;

  pthread_create( &amp;t, NULL, &amp;monitor, NULL);

  /* Modem status changes seen here */
  puts( "Main: awaiting status changes");
  sleep( 5);

  tcgetattr( s_fd, &amp;tio);
  tio.c_cflag ^= CSTOPB;

  /* But not after here */
  puts( "Main: tcsetattr called");
  tcsetattr( s_fd, TCSANOW, &amp;tio);

  for (;;)
    sleep( 1);
  }

static void* monitor( void* pv)
  {
  (void)pv;
  for(;;)
    {
    unsigned uModem;
    struct serial_icounter_struct cnt;

    if ( ioctl( s_fd, TIOCMGET, &amp;uModem) &lt; 0)
      fprintf( stderr, "Error(%d) in TIOCMGET: %s\n", errno, strerror( errno));
    printf( "Modem status:%s%s%s%s%s%s\n",
      (uModem &amp; TIOCM_RTS) ? " RTS" : "",
      (uModem &amp; TIOCM_DTR) ? " DTR" : "",
      (uModem &amp; TIOCM_CTS) ? " CTS" : "",
      (uModem &amp; TIOCM_DSR) ? " DSR" : "",
      (uModem &amp; TIOCM_CD) ? " CD" : "",
      (uModem &amp; TIOCM_RI) ? " RI" : ""
    );

    if ( ioctl( s_fd, TIOCGICOUNT, &amp;cnt) &lt; 0)
      fprintf( stderr, "Error(%d) in TIOCGICOUNT: %s\n", errno, strerror( errno));
    printf( "Irqs: CTS:%d DSR:%d RNG:%d DCD:%d Rx:%d Tx:%d Frame:%d Orun:%d Par:%d Brk:%d Oflow:%d\n",
      cnt.cts, cnt.dsr, cnt.rng, cnt.dcd,
      cnt.rx, cnt.tx, cnt.frame, cnt.overrun, cnt.parity,
      cnt.brk, cnt.buf_overrun
    );

    fputs( "Waiting...", stdout), fflush( stdout);
    if ( 0 &gt; ioctl( s_fd, TIOCMIWAIT, (unsigned long)(TIOCM_CAR | TIOCM_RNG | TIOCM_DSR | TIOCM_CTS)))
      fprintf( stderr, "\nError(%d) in TIOCMIWAIT: %s\n", errno, strerror( errno));
    fputs( "\n", stdout);
    }
  return NULL;
  }

Signed-off by Lawrence Rust &lt;lawrence@softsystem.co.uk&gt;

Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;
</pre>
</div>
</content>
</entry>
</feed>
