kernel-fxtec-pro1x/drivers/serial
Lawrence Rust 47d3904fe4 8250: Fix tcsetattr to avoid ioctl(TIOCMIWAIT) hang
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 & fix:

/* gcc miwait.c -o miwait -l pthread */
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <linux/serial.h>

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 < 0)
    return fprintf( stderr, "Error(%d) opening %s: %s\n", errno, kszDev, strerror( errno)), 1;

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

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

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

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

  for (;;)
    sleep( 1);
  }

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

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

    if ( ioctl( s_fd, TIOCGICOUNT, &cnt) < 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 > 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 <lawrence@softsystem.co.uk>

Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-11-11 10:51:35 -08:00
..
cpm_uart of/device: Replace struct of_device with struct platform_device 2010-08-06 09:25:50 -06:00
jsm jsm: Remove the uart port on errors 2010-10-22 10:20:10 -07:00
8250.c 8250: Fix tcsetattr to avoid ioctl(TIOCMIWAIT) hang 2010-11-11 10:51:35 -08:00
8250.h
8250_accent.c
8250_acorn.c
8250_boca.c
8250_early.c serial: print early console device address in hex 2010-08-23 18:17:20 -07:00
8250_exar_st16c554.c
8250_fourport.c
8250_gsc.c include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h 2010-03-30 22:02:32 +09:00
8250_hp300.c include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h 2010-03-30 22:02:32 +09:00
8250_hub6.c
8250_mca.c
8250_pci.c SERIAL: blacklist si3052 chip 2010-11-09 15:03:07 -08:00
8250_pnp.c serial: 8250_pnp - add Fujitsu Wacom device 2010-04-30 09:20:34 -07:00
21285.c tty: serial - fix tty back references in termios 2010-08-10 13:47:41 -07:00
68328serial.c 68328serial: check return value of copy_*_user() instead of access_ok() 2010-08-23 18:17:22 -07:00
68328serial.h arch/m68knommu: Removing dead 68328_SERIAL_UART2 config option 2010-10-21 10:17:29 +10:00
68360serial.c tty: icount changeover for other main devices 2010-10-22 10:20:05 -07:00
altera_jtaguart.c serial: Add driver for the Altera JTAG UART 2010-05-21 09:34:30 -07:00
altera_uart.c altera_uart: Don't use plain integer as NULL pointer 2010-10-22 10:20:09 -07:00
amba-pl010.c serial: amba-pl010: fix set_ldisc 2010-09-20 16:30:00 -07:00
amba-pl011.c ARM: Fix section build warnings for AMBA drivers 2010-07-27 10:48:43 +01:00
apbuart.c of/device: Replace struct of_device with struct platform_device 2010-08-06 09:25:50 -06:00
apbuart.h
atmel_serial.c serial: general fixes in the serial_rs485 structure 2010-08-10 13:47:45 -07:00
bcm63xx_uart.c serial: bcm63xx_uart: allow more than one uart to be registered. 2010-03-02 14:43:19 -08:00
bfin_5xx.c drivers/serial/bfin_5xx.c: Fix line continuation defects 2010-11-09 15:03:06 -08:00
bfin_sport_uart.c Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial 2010-10-24 13:41:39 -07:00
bfin_sport_uart.h Update broken web addresses in the kernel. 2010-10-18 11:03:14 +02:00
clps711x.c
crisv10.c CRIS: Fix RS485 delay handling. 2010-10-28 12:13:27 +02:00
crisv10.h
dz.c
dz.h
icom.c tty: Fix up char drivers request_room usage 2010-03-02 14:43:22 -08:00
icom.h
imx.c serial/imx: check that the buffer is non-empty before sending it out 2010-10-22 10:20:10 -07:00
ioc3_serial.c Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6 2010-10-21 14:27:18 -07:00
ioc4_serial.c tty: serial - fix tty back references in termios 2010-08-10 13:47:41 -07:00
ip22zilog.c
ip22zilog.h
Kconfig Merge branch 'omap-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6 2010-10-25 13:46:56 -07:00
kgdboc.c kdb,kgdb: fix sparse fixups 2010-10-22 15:34:12 -05:00
m32r_sio.c
m32r_sio.h
m32r_sio_reg.h
Makefile serial: Add OMAP high-speed UART driver 2010-09-29 12:43:02 -07:00
max3100.c tty: serial - fix tty back references in termios 2010-08-10 13:47:41 -07:00
max3107-aava.c serial: max3107: Abstract out the platform specific bits 2010-08-10 13:47:44 -07:00
max3107.c serial: max3107: Fix memory leaks when returning on error 2010-10-22 10:20:03 -07:00
max3107.h serial: max3107: Fix gpiolib support 2010-08-10 13:47:46 -07:00
mcf.c serial: mcf: don't take spinlocks in already protected functions 2010-08-10 13:47:45 -07:00
mfd.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6 2010-10-22 19:59:04 -07:00
mpc52xx_uart.c powerpc/5200: mpc52xx_uart.c: Add of_node_put to avoid memory leak 2010-09-08 13:54:48 -06:00
mpsc.c powerpc/mpsc: Set the port device in the mpsc serial driver 2010-04-07 14:12:36 +10:00
mrst_max3110.c serial: mrst_max3110: Make the IRQ option runtime 2010-10-22 10:20:03 -07:00
mrst_max3110.h serial: mrst_max3110: some code cleanup 2010-10-22 10:20:03 -07:00
msm_serial.c msm_serial: fix serial on trout 2010-06-04 13:37:16 -07:00
msm_serial.h msm_serial: fix serial on trout 2010-06-04 13:37:16 -07:00
mux.c include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h 2010-03-30 22:02:32 +09:00
netx-serial.c
nwpserial.c of/device: Replace struct of_device with struct platform_device 2010-08-06 09:25:50 -06:00
of_serial.c powerpc, of_serial: Endianness issues setting up the serial ports 2010-10-07 17:21:15 -06:00
omap-serial.c serial: omap-serial: fix signess error 2010-10-12 13:22:42 -07:00
pmac_zilog.c powerpc/macio: Fix probing of macio devices by using the right of match table 2010-06-02 17:50:38 +10:00
pmac_zilog.h pmac-zilog: add platform driver 2010-02-27 18:31:02 +01:00
pnx8xxx_uart.c
pxa.c include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h 2010-03-30 22:02:32 +09:00
s3c24a0.c
s3c2400.c
s3c2410.c
s3c2412.c
s3c2440.c
s3c6400.c
s5pv210.c ARM: S5PV310: Add serial port support 2010-08-05 18:32:42 +09:00
sa1100.c
samsung.c ARM: S5P64X0: Add UART serial support for S5P6450 2010-10-18 18:33:04 +09:00
samsung.h
sb1250-duart.c
sc26xx.c
serial_core.c tty: Make tiocgicount a handler 2010-10-22 10:20:04 -07:00
serial_cs.c serial_cs: drop spurious flush_scheduled_work() call 2010-10-16 11:07:07 +02:00
serial_ks8695.c ARM: 6030/1: KS8695: enable console 2010-04-23 10:01:56 +01:00
serial_lh7a40x.c
serial_txx9.c
sh-sci.c Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 2010-05-31 13:14:26 +09:00
sh-sci.h Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 2010-08-16 13:32:24 +09:00
sn_console.c Input: sysrq - drop tty argument form handle_sysrq() 2010-08-21 00:34:45 -07:00
suncore.c sparc: Really fix "console=" for serial consoles. 2010-08-16 12:26:09 -07:00
suncore.h
sunhv.c of/device: Replace struct of_device with struct platform_device 2010-08-06 09:25:50 -06:00
sunsab.c of/device: Replace struct of_device with struct platform_device 2010-08-06 09:25:50 -06:00
sunsab.h
sunsu.c of/device: Replace struct of_device with struct platform_device 2010-08-06 09:25:50 -06:00
sunzilog.c of/device: Replace struct of_device with struct platform_device 2010-08-06 09:25:50 -06:00
sunzilog.h
timbuart.c timbuart: use __devinit and __devexit macros for probe and remove 2010-08-10 13:47:45 -07:00
timbuart.h
uartlite.c Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial 2010-10-24 13:41:39 -07:00
ucc_uart.c of/device: Replace struct of_device with struct platform_device 2010-08-06 09:25:50 -06:00
vr41xx_siu.c
zs.c
zs.h