dect
/
linux-2.6
Archived
13
0
Fork 0

Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (68 commits)
  U6715 16550A serial driver support
  Char: nozomi, set tty->driver_data appropriately
  Char: nozomi, fix tty->count counting
  serial: max3107: Fix gpiolib support
  hsu: call PCI pm hooks in suspend/resume function
  hsu: some code cleanup
  hsu: add a periodic timer to check dma rx channel
  hsu: driver for Medfield High Speed UART device
  mxser: remove unnesesary NULL check
  serial: add support for OX16PCI958 card
  serial: 68328serial.c: remove dead (ALMA_ANS | DRAGONIXVZ | M68EZ328ADS)
  timbuart: use __devinit and __devexit macros for probe and remove
  serial: MMIO32 support for 8250_early.c
  serial: mcf: don't take spinlocks in already protected functions
  serial: general fixes in the serial_rs485 structure
  serial: fix missing bit coverage of ASYNC_FLAGS
  serial: "altera_uart: simplify altera_uart_console_putc()" checkpatch fixes
  serial: crisv10: formatting of pointers in printk()
  vt: Fix warning: statement with no effect due to vt_kern.h
  tty_io: remove casts from void*
  ...
This commit is contained in:
Linus Torvalds 2010-08-10 15:03:42 -07:00
commit fc385c3132
112 changed files with 5503 additions and 652 deletions

View File

@ -681,8 +681,11 @@ and is between 256 and 4096 characters. It is defined in the file
earlycon= [KNL] Output early console device and options.
uart[8250],io,<addr>[,options]
uart[8250],mmio,<addr>[,options]
uart[8250],mmio32,<addr>[,options]
Start an early, polled-mode console on the 8250/16550
UART at the specified I/O port or MMIO address.
MMIO inter-register address stride is either 8bit (mmio)
or 32bit (mmio32).
The options are the same as for ttyS, above.
earlyprintk= [X86,SH,BLACKFIN]

View File

@ -80,6 +80,7 @@
# define TIOCPKT_START 8
# define TIOCPKT_NOSTOP 16
# define TIOCPKT_DOSTOP 32
# define TIOCPKT_IOCTL 64
#define TIOCNOTTY 0x5422
@ -91,6 +92,7 @@
#define TIOCGSID 0x5429 /* Return the session ID of FD */
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define TIOCSERCONFIG 0x5453
#define TIOCSERGWILD 0x5454
@ -106,7 +108,5 @@
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
#endif /* _ASM_ALPHA_IOCTLS_H */

View File

@ -180,6 +180,7 @@ struct ktermios {
#define FLUSHO 0x00800000
#define PENDIN 0x20000000
#define IEXTEN 0x00000400
#define EXTPROC 0x10000000
/* Values for the ACTION argument to `tcflow'. */
#define TCOOFF 0

View File

@ -52,6 +52,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define TIOCGRS485 0x542E
#define TIOCSRS485 0x542F
@ -81,6 +82,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
#define TIOCPKT_IOCTL 64
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

View File

@ -177,6 +177,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
#define EXTPROC 0200000
/* tcflow() and TCXONC use these */
#define TCOOFF 0

View File

@ -53,6 +53,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define TIOCGRS485 0x542E
#define TIOCSRS485 0x542F
@ -72,8 +73,6 @@
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
#define FIOQSIZE 0x5460
/* Used for packet mode */
@ -84,6 +83,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
#define TIOCPKT_IOCTL 64
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

View File

@ -175,6 +175,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
#define EXTPROC 0200000
/* tcflow() and TCXONC use these */
#define TCOOFF 0

View File

@ -54,6 +54,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
@ -70,8 +71,6 @@
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
#define FIOQSIZE 0x5460
#define TIOCSERSETRS485 0x5461 /* enable rs-485 (deprecated) */
@ -87,6 +86,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
#define TIOCPKT_IOCTL 64
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

View File

@ -214,6 +214,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
#define EXTPROC 0200000
/* tcflow() and TCXONC use these */
#define TCOOFF 0

View File

@ -53,6 +53,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
@ -79,6 +80,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
#define TIOCPKT_IOCTL 64
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

View File

@ -180,6 +180,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
#define EXTPROC 0200000
/* tcflow() and TCXONC use these */

View File

@ -53,6 +53,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
@ -79,6 +80,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
#define TIOCPKT_IOCTL 64
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

View File

@ -179,6 +179,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
#define EXTPROC 0200000
/* tcflow() and TCXONC use these */

View File

@ -59,6 +59,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
@ -75,8 +76,6 @@
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
#define FIOQSIZE 0x5460
/* Used for packet mode */
@ -87,6 +86,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
#define TIOCPKT_IOCTL 64
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

View File

@ -187,6 +187,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
#define EXTPROC 0200000
/* tcflow() and TCXONC use these */
#define TCOOFF 0

View File

@ -53,6 +53,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define FIONCLEX 0x5450
#define FIOCLEX 0x5451
@ -69,8 +70,6 @@
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
#define FIOQSIZE 0x5460
/* Used for packet mode */
@ -81,6 +80,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
#define TIOCPKT_IOCTL 64
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

View File

@ -179,6 +179,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
#define EXTPROC 0200000
/* tcflow() and TCXONC use these */
#define TCOOFF 0

View File

@ -52,6 +52,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
@ -78,6 +79,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
#define TIOCPKT_IOCTL 64
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

View File

@ -179,6 +179,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
#define EXTPROC 0200000
/* tcflow() and TCXONC use these */

View File

@ -41,7 +41,7 @@
#define TIOCPKT_START 0x08 /* start output */
#define TIOCPKT_NOSTOP 0x10 /* no more ^S, ^Q */
#define TIOCPKT_DOSTOP 0x20 /* now do ^S ^Q */
/* #define TIOCPKT_IOCTL 0x40 state change of pty driver */
#define TIOCPKT_IOCTL 0x40 /* state change of pty driver */
#define TIOCSWINSZ _IOW('t', 103, struct winsize) /* set window size */
#define TIOCGWINSZ _IOR('t', 104, struct winsize) /* get window size */
#define TIOCNOTTY 0x5471 /* void tty association */
@ -83,6 +83,7 @@
#define TCSETSF2 _IOW('T', 0x2D, struct termios2)
#define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */
#define TIOCSIG _IOW('T', 0x36, int) /* Generate signal on Pty slave */
/* I hope the range from 0x5480 on is free ... */
#define TIOCSCTTY 0x5480 /* become controlling tty */
@ -103,7 +104,5 @@
#define TIOCSERSETMULTI 0x5490 /* Set multiport config */
#define TIOCMIWAIT 0x5491 /* wait for a change on serial input line(s) */
#define TIOCGICOUNT 0x5492 /* read serial port inline interrupt counts */
#define TIOCGHAYESESP 0x5493 /* Get Hayes ESP configuration */
#define TIOCSHAYESESP 0x5494 /* Set Hayes ESP configuration */
#endif /* __ASM_IOCTLS_H */

View File

@ -203,6 +203,7 @@ struct ktermios {
#define PENDIN 0040000 /* Retype pending input (state). */
#define TOSTOP 0100000 /* Send SIGTTOU for background output. */
#define ITOSTOP TOSTOP
#define EXTPROC 0200000 /* External processing on pty */
/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

View File

@ -54,6 +54,7 @@
#define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number
* (of pty-mux device) */
#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */
#define TIOCSIG _IOW('T', 0x36, int) /* Generate signal on Pty slave */
#define FIONCLEX 0x5450
#define FIOCLEX 0x5451
@ -70,8 +71,6 @@
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
#define FIOQSIZE 0x5460
/* Used for packet mode */
@ -82,6 +81,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
#define TIOCPKT_IOCTL 64
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

View File

@ -180,6 +180,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
#define EXTPROC 0200000
/* tcflow() and TCXONC use these */
#define TCOOFF 0

View File

@ -52,6 +52,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
@ -68,8 +69,6 @@
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
#define FIOQSIZE 0x5460 /* Get exact space used by quota */
#define TIOCSTART 0x5461
@ -84,6 +83,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
#define TIOCPKT_IOCTL 64
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

View File

@ -180,6 +180,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
#define EXTPROC 0200000
/* tcflow() and TCXONC use these */
#define TCOOFF 0

View File

@ -80,6 +80,7 @@
# define TIOCPKT_START 8
# define TIOCPKT_NOSTOP 16
# define TIOCPKT_DOSTOP 32
# define TIOCPKT_IOCTL 64
#define TIOCNOTTY 0x5422
@ -93,6 +94,7 @@
#define TIOCSRS485 0x542f
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define TIOCSERCONFIG 0x5453
#define TIOCSERGWILD 0x5454

View File

@ -189,6 +189,7 @@ struct ktermios {
#define FLUSHO 0x00800000
#define PENDIN 0x20000000
#define IEXTEN 0x00000400
#define EXTPROC 0x10000000
/* Values for the ACTION argument to `tcflow'. */
#define TCOOFF 0

View File

@ -60,6 +60,7 @@
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451
@ -86,6 +87,7 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
#define TIOCPKT_IOCTL 64
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */

View File

@ -69,6 +69,7 @@
# define TIOCPKT_START 8
# define TIOCPKT_NOSTOP 16
# define TIOCPKT_DOSTOP 32
# define TIOCPKT_IOCTL 64
#define TIOCNOTTY _IO('T', 34) /* 0x5422 */
@ -84,6 +85,7 @@
#define TCSETSF2 _IOW('T', 45, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define TIOCSERCONFIG _IO('T', 83) /* 0x5453 */
#define TIOCSERGWILD _IOR('T', 84, int) /* 0x5454 */

View File

@ -80,6 +80,7 @@
/* Get minor device of a pty master's FD -- Solaris equiv is ISPTM */
#define TIOCGPTN _IOR('t', 134, unsigned int) /* Get Pty Number */
#define TIOCSPTLCK _IOW('t', 135, int) /* Lock/unlock PTY */
#define TIOCSIG _IOW('t', 136, int) /* Generate signal on Pty slave */
/* Little f */
#define FIOCLEX _IO('f', 1)
@ -132,5 +133,6 @@
#define TIOCPKT_START 8
#define TIOCPKT_NOSTOP 16
#define TIOCPKT_DOSTOP 32
#define TIOCPKT_IOCTL 64
#endif /* !(_ASM_SPARC_IOCTLS_H) */

View File

@ -225,6 +225,7 @@ struct ktermios {
#define FLUSHO 0x00002000
#define PENDIN 0x00004000
#define IEXTEN 0x00008000
#define EXTPROC 0x00010000
/* modem lines */
#define TIOCM_LE 0x001

View File

@ -81,6 +81,7 @@
# define TIOCPKT_START 8
# define TIOCPKT_NOSTOP 16
# define TIOCPKT_DOSTOP 32
# define TIOCPKT_IOCTL 64
#define TIOCNOTTY _IO('T', 34)
@ -97,6 +98,7 @@
#define TCSETSF2 _IOW('T', 45, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define TIOCSERCONFIG _IO('T', 83)
#define TIOCSERGWILD _IOR('T', 84, int)

View File

@ -196,6 +196,7 @@ struct ktermios {
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
#define EXTPROC 0200000
/* tcflow() and TCXONC use these */

View File

@ -9,6 +9,7 @@ FONTMAPFILE = cp437.uni
obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o
obj-y += tty_mutex.o
obj-$(CONFIG_LEGACY_PTYS) += pty.o
obj-$(CONFIG_UNIX98_PTYS) += pty.o
obj-y += misc.o

View File

@ -1072,7 +1072,7 @@ static int get_serial_info(struct async_struct * info,
if (!retinfo)
return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
lock_kernel();
tty_lock();
tmp.type = state->type;
tmp.line = state->line;
tmp.port = state->port;
@ -1083,7 +1083,7 @@ static int get_serial_info(struct async_struct * info,
tmp.close_delay = state->close_delay;
tmp.closing_wait = state->closing_wait;
tmp.custom_divisor = state->custom_divisor;
unlock_kernel();
tty_unlock();
if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
return -EFAULT;
return 0;
@ -1100,14 +1100,14 @@ static int set_serial_info(struct async_struct * info,
if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
return -EFAULT;
lock_kernel();
tty_lock();
state = info->state;
old_state = *state;
change_irq = new_serial.irq != state->irq;
change_port = (new_serial.port != state->port);
if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) {
unlock_kernel();
tty_unlock();
return -EINVAL;
}
@ -1127,7 +1127,7 @@ static int set_serial_info(struct async_struct * info,
}
if (new_serial.baud_base < 9600) {
unlock_kernel();
tty_unlock();
return -EINVAL;
}
@ -1163,7 +1163,7 @@ check_and_exit:
}
} else
retval = startup(info);
unlock_kernel();
tty_unlock();
return retval;
}
@ -1528,6 +1528,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
{
struct async_struct * info = tty->driver_data;
unsigned long orig_jiffies, char_time;
int tty_was_locked = tty_locked();
int lsr;
if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent"))
@ -1538,7 +1539,12 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
orig_jiffies = jiffies;
lock_kernel();
/*
* tty_wait_until_sent is called from lots of places,
* with or without the BTM.
*/
if (!tty_was_locked)
tty_lock();
/*
* Set the check interval to be 1/5 of the estimated time to
* send a single character, and make it at least 1. The check
@ -1579,7 +1585,8 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
break;
}
__set_current_state(TASK_RUNNING);
unlock_kernel();
if (!tty_was_locked)
tty_unlock();
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
#endif
@ -1703,7 +1710,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
printk("block_til_ready blocking: ttys%d, count = %d\n",
info->line, state->count);
#endif
tty_unlock();
schedule();
tty_lock();
}
__set_current_state(TASK_RUNNING);
remove_wait_queue(&info->open_wait, &wait);

View File

@ -67,15 +67,15 @@ static void set_led(char state)
static int briq_panel_open(struct inode *ino, struct file *filep)
{
lock_kernel();
tty_lock();
/* enforce single access, vfd_is_open is protected by BKL */
if (vfd_is_open) {
unlock_kernel();
tty_unlock();
return -EBUSY;
}
vfd_is_open = 1;
unlock_kernel();
tty_unlock();
return 0;
}

View File

@ -65,7 +65,6 @@
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/smp_lock.h>
#include <linux/major.h>
#include <linux/string.h>
#include <linux/fcntl.h>
@ -1608,7 +1607,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
* If the port is the middle of closing, bail out now
*/
if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
wait_event_interruptible(info->port.close_wait,
wait_event_interruptible_tty(info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
}
@ -1655,7 +1654,6 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
return; /* Just in case.... */
orig_jiffies = jiffies;
lock_kernel();
/*
* Set the check interval to be 1/5 of the estimated time to
* send a single character, and make it at least 1. The check
@ -1702,7 +1700,6 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
}
/* Run one more char cycle */
msleep_interruptible(jiffies_to_msecs(char_time * 5));
unlock_kernel();
#ifdef CY_DEBUG_WAIT_UNTIL_SENT
printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies);
#endif
@ -1959,7 +1956,6 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
int char_count;
__u32 tx_put, tx_get, tx_bufsize;
lock_kernel();
tx_get = readl(&buf_ctrl->tx_get);
tx_put = readl(&buf_ctrl->tx_put);
tx_bufsize = readl(&buf_ctrl->tx_bufsize);
@ -1971,7 +1967,6 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
info->line, info->xmit_cnt + char_count);
#endif
unlock_kernel();
return info->xmit_cnt + char_count;
}
#endif /* Z_EXT_CHARS_IN_BUFFER */
@ -2359,17 +2354,22 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
struct serial_struct __user *new_info)
{
struct serial_struct new_serial;
int ret;
if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
return -EFAULT;
mutex_lock(&info->port.mutex);
if (!capable(CAP_SYS_ADMIN)) {
if (new_serial.close_delay != info->port.close_delay ||
new_serial.baud_base != info->baud ||
(new_serial.flags & ASYNC_FLAGS &
~ASYNC_USR_MASK) !=
(info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))
{
mutex_unlock(&info->port.mutex);
return -EPERM;
}
info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) |
(new_serial.flags & ASYNC_USR_MASK);
info->baud = new_serial.baud_base;
@ -2392,10 +2392,12 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
check_and_exit:
if (info->port.flags & ASYNC_INITIALIZED) {
cy_set_line_char(info, tty);
return 0;
ret = 0;
} else {
return cy_startup(info, tty);
ret = cy_startup(info, tty);
}
mutex_unlock(&info->port.mutex);
return ret;
} /* set_serial_info */
/*
@ -2438,7 +2440,6 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
card = info->card;
lock_kernel();
if (!cy_is_Z(card)) {
unsigned long flags;
int channel = info->line - card->first_line;
@ -2478,7 +2479,6 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
((lstatus & C_RS_CTS) ? TIOCM_CTS : 0);
}
end:
unlock_kernel();
return result;
} /* cy_tiomget */
@ -2696,7 +2696,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n",
info->line, cmd, arg);
#endif
lock_kernel();
switch (cmd) {
case CYGETMON:
@ -2817,7 +2816,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
default:
ret_val = -ENOIOCTLCMD;
}
unlock_kernel();
#ifdef CY_DEBUG_OTHER
printk(KERN_DEBUG "cyc:cy_ioctl done\n");

View File

@ -36,7 +36,7 @@
#include <linux/ctype.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/uaccess.h>
@ -2105,7 +2105,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file,
break;
case DIGI_SETAW:
case DIGI_SETAF:
lock_kernel();
if (cmd == DIGI_SETAW) {
/* Setup an event to indicate when the transmit
buffer empties */
@ -2118,7 +2117,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file,
if (tty->ldisc->ops->flush_buffer)
tty->ldisc->ops->flush_buffer(tty);
}
unlock_kernel();
/* Fall Thru */
case DIGI_SETA:
if (copy_from_user(&ch->digiext, argp, sizeof(digi_t)))

View File

@ -1486,7 +1486,9 @@ ip2_open( PTTY tty, struct file *pFile )
if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) {
if ( pCh->flags & ASYNC_CLOSING ) {
tty_unlock();
schedule();
tty_lock();
}
if ( tty_hung_up_p(pFile) ) {
set_current_state( TASK_RUNNING );
@ -1548,7 +1550,9 @@ ip2_open( PTTY tty, struct file *pFile )
rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS);
break;
}
tty_unlock();
schedule();
tty_lock();
}
set_current_state( TASK_RUNNING );
remove_wait_queue(&pCh->open_wait, &wait);

View File

@ -124,7 +124,6 @@
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/serial.h>
#include <linux/smp_lock.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
@ -872,7 +871,6 @@ static struct tty_port *isicom_find_port(struct tty_struct *tty)
static int isicom_open(struct tty_struct *tty, struct file *filp)
{
struct isi_port *port;
struct isi_board *card;
struct tty_port *tport;
tport = isicom_find_port(tty);
@ -1118,8 +1116,7 @@ static int isicom_set_serial_info(struct tty_struct *tty,
if (copy_from_user(&newinfo, info, sizeof(newinfo)))
return -EFAULT;
lock_kernel();
mutex_lock(&port->port.mutex);
reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) !=
(newinfo.flags & ASYNC_SPD_MASK));
@ -1128,7 +1125,7 @@ static int isicom_set_serial_info(struct tty_struct *tty,
(newinfo.closing_wait != port->port.closing_wait) ||
((newinfo.flags & ~ASYNC_USR_MASK) !=
(port->port.flags & ~ASYNC_USR_MASK))) {
unlock_kernel();
mutex_unlock(&port->port.mutex);
return -EPERM;
}
port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
@ -1145,7 +1142,7 @@ static int isicom_set_serial_info(struct tty_struct *tty,
isicom_config_port(tty);
spin_unlock_irqrestore(&port->card->card_lock, flags);
}
unlock_kernel();
mutex_unlock(&port->port.mutex);
return 0;
}
@ -1154,7 +1151,7 @@ static int isicom_get_serial_info(struct isi_port *port,
{
struct serial_struct out_info;
lock_kernel();
mutex_lock(&port->port.mutex);
memset(&out_info, 0, sizeof(out_info));
/* out_info.type = ? */
out_info.line = port - isi_ports;
@ -1164,7 +1161,7 @@ static int isicom_get_serial_info(struct isi_port *port,
/* out_info.baud_base = ? */
out_info.close_delay = port->port.close_delay;
out_info.closing_wait = port->port.closing_wait;
unlock_kernel();
mutex_unlock(&port->port.mutex);
if (copy_to_user(info, &out_info, sizeof(out_info)))
return -EFAULT;
return 0;

View File

@ -203,9 +203,9 @@ static int stli_shared;
* the board has been detected, and whether it is actually running a slave
* or not.
*/
#define BST_FOUND 0x1
#define BST_STARTED 0x2
#define BST_PROBED 0x4
#define BST_FOUND 0
#define BST_STARTED 1
#define BST_PROBED 2
/*
* Define the set of port state flags. These are marked for internal
@ -816,7 +816,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
brdp = stli_brds[brdnr];
if (brdp == NULL)
return -ENODEV;
if ((brdp->state & BST_STARTED) == 0)
if (!test_bit(BST_STARTED, &brdp->state))
return -ENODEV;
portnr = MINOR2PORT(minordev);
if (portnr > brdp->nrports)
@ -954,7 +954,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned l
* order of opens and closes may not be preserved across shared
* memory, so we must wait until it is complete.
*/
wait_event_interruptible(portp->raw_wait,
wait_event_interruptible_tty(portp->raw_wait,
!test_bit(ST_CLOSING, &portp->state));
if (signal_pending(current)) {
return -ERESTARTSYS;
@ -989,7 +989,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned l
set_bit(ST_OPENING, &portp->state);
spin_unlock_irqrestore(&brd_lock, flags);
wait_event_interruptible(portp->raw_wait,
wait_event_interruptible_tty(portp->raw_wait,
!test_bit(ST_OPENING, &portp->state));
if (signal_pending(current))
rc = -ERESTARTSYS;
@ -1020,7 +1020,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned
* occurs on this port.
*/
if (wait) {
wait_event_interruptible(portp->raw_wait,
wait_event_interruptible_tty(portp->raw_wait,
!test_bit(ST_CLOSING, &portp->state));
if (signal_pending(current)) {
return -ERESTARTSYS;
@ -1052,7 +1052,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned
* to come back.
*/
rc = 0;
wait_event_interruptible(portp->raw_wait,
wait_event_interruptible_tty(portp->raw_wait,
!test_bit(ST_CLOSING, &portp->state));
if (signal_pending(current))
rc = -ERESTARTSYS;
@ -1073,6 +1073,10 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned
static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
{
/*
* no need for wait_event_tty because clearing ST_CMDING cannot block
* on BTM
*/
wait_event_interruptible(portp->raw_wait,
!test_bit(ST_CMDING, &portp->state));
if (signal_pending(current))
@ -1846,7 +1850,7 @@ static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stlip
rc = stli_portcmdstats(NULL, portp);
uart = "UNKNOWN";
if (brdp->state & BST_STARTED) {
if (test_bit(BST_STARTED, &brdp->state)) {
switch (stli_comstats.hwid) {
case 0: uart = "2681"; break;
case 1: uart = "SC26198"; break;
@ -1855,7 +1859,7 @@ static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stlip
}
seq_printf(m, "%d: uart:%s ", portnr, uart);
if ((brdp->state & BST_STARTED) && (rc >= 0)) {
if (test_bit(BST_STARTED, &brdp->state) && rc >= 0) {
char sep;
seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal,
@ -2355,7 +2359,7 @@ static void stli_poll(unsigned long arg)
brdp = stli_brds[brdnr];
if (brdp == NULL)
continue;
if ((brdp->state & BST_STARTED) == 0)
if (!test_bit(BST_STARTED, &brdp->state))
continue;
spin_lock(&brd_lock);
@ -3140,7 +3144,7 @@ static int stli_initecp(struct stlibrd *brdp)
}
brdp->state |= BST_FOUND;
set_bit(BST_FOUND, &brdp->state);
return 0;
err_unmap:
iounmap(brdp->membase);
@ -3297,7 +3301,7 @@ static int stli_initonb(struct stlibrd *brdp)
brdp->panels[0] = brdp->nrports;
brdp->state |= BST_FOUND;
set_bit(BST_FOUND, &brdp->state);
return 0;
err_unmap:
iounmap(brdp->membase);
@ -3407,7 +3411,7 @@ stli_donestartup:
spin_unlock_irqrestore(&brd_lock, flags);
if (rc == 0)
brdp->state |= BST_STARTED;
set_bit(BST_STARTED, &brdp->state);
if (! stli_timeron) {
stli_timeron++;
@ -3710,7 +3714,7 @@ static int __devinit stli_pciprobe(struct pci_dev *pdev,
if (retval)
goto err_null;
brdp->state |= BST_PROBED;
set_bit(BST_PROBED, &brdp->state);
pci_set_drvdata(pdev, brdp);
EBRDENABLE(brdp);
@ -3841,7 +3845,7 @@ static int __init stli_initbrds(void)
brdp = stli_brds[i];
if (brdp == NULL)
continue;
if (brdp->state & BST_FOUND) {
if (test_bit(BST_FOUND, &brdp->state)) {
EBRDENABLE(brdp);
brdp->enable = NULL;
brdp->disable = NULL;
@ -4011,6 +4015,7 @@ static int stli_getbrdstats(combrd_t __user *bp)
return -ENODEV;
memset(&stli_brdstats, 0, sizeof(combrd_t));
stli_brdstats.brd = brdp->brdnr;
stli_brdstats.type = brdp->brdtype;
stli_brdstats.hwid = 0;
@ -4076,10 +4081,13 @@ static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp)
if (brdp == NULL)
return -ENODEV;
if (brdp->state & BST_STARTED) {
mutex_lock(&portp->port.mutex);
if (test_bit(BST_STARTED, &brdp->state)) {
if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS,
&stli_cdkstats, sizeof(asystats_t), 1)) < 0)
&stli_cdkstats, sizeof(asystats_t), 1)) < 0) {
mutex_unlock(&portp->port.mutex);
return rc;
}
} else {
memset(&stli_cdkstats, 0, sizeof(asystats_t));
}
@ -4124,6 +4132,7 @@ static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp)
stli_comstats.modem = stli_cdkstats.dcdcnt;
stli_comstats.hwid = stli_cdkstats.hwid;
stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals);
mutex_unlock(&portp->port.mutex);
return 0;
}
@ -4186,15 +4195,20 @@ static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp)
if (!brdp)
return -ENODEV;
if (brdp->state & BST_STARTED) {
if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0)
mutex_lock(&portp->port.mutex);
if (test_bit(BST_STARTED, &brdp->state)) {
if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0) {
mutex_unlock(&portp->port.mutex);
return rc;
}
}
memset(&stli_comstats, 0, sizeof(comstats_t));
stli_comstats.brd = portp->brdnr;
stli_comstats.panel = portp->panelnr;
stli_comstats.port = portp->portnr;
mutex_unlock(&portp->port.mutex);
if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t)))
return -EFAULT;
@ -4266,8 +4280,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
done = 0;
rc = 0;
lock_kernel();
switch (cmd) {
case COM_GETPORTSTATS:
rc = stli_getportstats(NULL, NULL, argp);
@ -4290,8 +4302,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
done++;
break;
}
unlock_kernel();
if (done)
return rc;
@ -4308,8 +4318,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
if (brdp->state == 0)
return -ENODEV;
lock_kernel();
switch (cmd) {
case STL_BINTR:
EBRDINTR(brdp);
@ -4318,10 +4326,10 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
rc = stli_startbrd(brdp);
break;
case STL_BSTOP:
brdp->state &= ~BST_STARTED;
clear_bit(BST_STARTED, &brdp->state);
break;
case STL_BRESET:
brdp->state &= ~BST_STARTED;
clear_bit(BST_STARTED, &brdp->state);
EBRDRESET(brdp);
if (stli_shared == 0) {
if (brdp->reenable != NULL)
@ -4332,7 +4340,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
rc = -ENOIOCTLCMD;
break;
}
unlock_kernel();
return rc;
}
@ -4378,7 +4385,8 @@ static void istallion_cleanup_isa(void)
unsigned int j;
for (j = 0; (j < stli_nrbrds); j++) {
if ((brdp = stli_brds[j]) == NULL || (brdp->state & BST_PROBED))
if ((brdp = stli_brds[j]) == NULL ||
test_bit(BST_PROBED, &brdp->state))
continue;
stli_cleanup_ports(brdp);

View File

@ -299,7 +299,7 @@ int kbd_rate(struct kbd_repeat *rep)
*/
static void put_queue(struct vc_data *vc, int ch)
{
struct tty_struct *tty = vc->vc_tty;
struct tty_struct *tty = vc->port.tty;
if (tty) {
tty_insert_flip_char(tty, ch, 0);
@ -309,7 +309,7 @@ static void put_queue(struct vc_data *vc, int ch)
static void puts_queue(struct vc_data *vc, char *cp)
{
struct tty_struct *tty = vc->vc_tty;
struct tty_struct *tty = vc->port.tty;
if (!tty)
return;
@ -485,7 +485,7 @@ static void fn_show_ptregs(struct vc_data *vc)
static void fn_hold(struct vc_data *vc)
{
struct tty_struct *tty = vc->vc_tty;
struct tty_struct *tty = vc->port.tty;
if (rep || !tty)
return;
@ -563,7 +563,7 @@ static void fn_inc_console(struct vc_data *vc)
static void fn_send_intr(struct vc_data *vc)
{
struct tty_struct *tty = vc->vc_tty;
struct tty_struct *tty = vc->port.tty;
if (!tty)
return;
@ -1162,7 +1162,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down };
int rc;
tty = vc->vc_tty;
tty = vc->port.tty;
if (tty && (!tty->driver_data)) {
/* No driver data? Strange. Okay we fix it then. */

View File

@ -2193,7 +2193,7 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port
port->mon_data.up_txcnt += (cnt - port->xmit_cnt);
port->icount.tx += (cnt - port->xmit_cnt);
if (port->xmit_cnt < WAKEUP_CHARS && tty)
if (port->xmit_cnt < WAKEUP_CHARS)
tty_wakeup(tty);
if (port->xmit_cnt <= 0) {

View File

@ -43,7 +43,6 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/timer.h>
#include <linux/ctype.h>
#include <linux/mm.h>
#include <linux/string.h>

View File

@ -598,18 +598,18 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
return -EFAULT;
}
lock_kernel();
tty_lock();
for (;;) {
if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
unlock_kernel();
tty_unlock();
return -EIO;
}
n_hdlc = tty2n_hdlc (tty);
if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC ||
tty != n_hdlc->tty) {
unlock_kernel();
tty_unlock();
return 0;
}
@ -619,13 +619,13 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
/* no data */
if (file->f_flags & O_NONBLOCK) {
unlock_kernel();
tty_unlock();
return -EAGAIN;
}
interruptible_sleep_on (&tty->read_wait);
if (signal_pending(current)) {
unlock_kernel();
tty_unlock();
return -EINTR;
}
}
@ -648,7 +648,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
kfree(rbuf);
else
n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf);
unlock_kernel();
tty_unlock();
return ret;
} /* end of n_hdlc_tty_read() */
@ -691,7 +691,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
count = maxframe;
}
lock_kernel();
tty_lock();
add_wait_queue(&tty->write_wait, &wait);
set_current_state(TASK_INTERRUPTIBLE);
@ -731,7 +731,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf);
n_hdlc_send_frames(n_hdlc,tty);
}
unlock_kernel();
tty_unlock();
return error;
} /* end of n_hdlc_tty_write() */

View File

@ -1067,7 +1067,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
TRACE_L("read()");
lock_kernel();
tty_lock();
pClient = findClient(pInfo, task_pid(current));
if (pClient) {
@ -1079,7 +1079,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
goto unlock;
}
/* block until there is a message: */
wait_event_interruptible(pInfo->read_wait,
wait_event_interruptible_tty(pInfo->read_wait,
(pMsg = remove_msg(pInfo, pClient)));
}
@ -1109,7 +1109,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
}
ret = -EPERM;
unlock:
unlock_kernel();
tty_unlock();
return ret;
}
@ -1158,7 +1158,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
pHeader->locks = 0;
pHeader->owner = NULL;
lock_kernel();
tty_lock();
pClient = findClient(pInfo, task_pid(current));
if (pClient) {
@ -1177,7 +1177,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
add_tx_queue(pInfo, pHeader);
trigger_transmit(pInfo);
unlock_kernel();
tty_unlock();
return 0;
}

View File

@ -1102,6 +1102,11 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
if (I_IUCLC(tty) && L_IEXTEN(tty))
c = tolower(c);
if (L_EXTPROC(tty)) {
put_tty_queue(c, tty);
return;
}
if (tty->stopped && !tty->flow_stopped && I_IXON(tty) &&
I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) &&
c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty)) {
@ -1409,7 +1414,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
n_tty_set_room(tty);
if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) {
if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) ||
L_EXTPROC(tty)) {
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
if (waitqueue_active(&tty->read_wait))
wake_up_interruptible(&tty->read_wait);
@ -1585,7 +1591,7 @@ static int n_tty_open(struct tty_struct *tty)
static inline int input_available_p(struct tty_struct *tty, int amt)
{
tty_flush_to_ldisc(tty);
if (tty->icanon) {
if (tty->icanon && !L_EXTPROC(tty)) {
if (tty->canon_data)
return 1;
} else if (tty->read_cnt >= (amt ? amt : 1))
@ -1632,6 +1638,11 @@ static int copy_from_read_buf(struct tty_struct *tty,
spin_lock_irqsave(&tty->read_lock, flags);
tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
tty->read_cnt -= n;
/* Turn single EOF into zero-length read */
if (L_EXTPROC(tty) && tty->icanon && n == 1) {
if (!tty->read_cnt && (*b)[n-1] == EOF_CHAR(tty))
n--;
}
spin_unlock_irqrestore(&tty->read_lock, flags);
*b += n;
*nr -= n;
@ -1812,7 +1823,7 @@ do_it_again:
nr--;
}
if (tty->icanon) {
if (tty->icanon && !L_EXTPROC(tty)) {
/* N.B. avoid overrun if nr == 0 */
while (nr && tty->read_cnt) {
int eol;

View File

@ -1611,6 +1611,8 @@ static int ntty_install(struct tty_driver *driver, struct tty_struct *tty)
ret = tty_init_termios(tty);
if (ret == 0) {
tty_driver_kref_get(driver);
tty->count++;
tty->driver_data = port;
driver->ttys[tty->index] = tty;
}
return ret;
@ -1639,7 +1641,7 @@ static int ntty_activate(struct tty_port *tport, struct tty_struct *tty)
static int ntty_open(struct tty_struct *tty, struct file *filp)
{
struct port *port = get_port_by_tty(tty);
struct port *port = tty->driver_data;
return tty_port_open(&port->port, tty, filp);
}

View File

@ -62,7 +62,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
if (tty->driver == ptm_driver)
devpts_pty_kill(tty->link);
#endif
tty_unlock();
tty_vhangup(tty->link);
tty_lock();
}
}
@ -171,6 +173,23 @@ static int pty_set_lock(struct tty_struct *tty, int __user *arg)
return 0;
}
/* Send a signal to the slave */
static int pty_signal(struct tty_struct *tty, int sig)
{
unsigned long flags;
struct pid *pgrp;
if (tty->link) {
spin_lock_irqsave(&tty->link->ctrl_lock, flags);
pgrp = get_pid(tty->link->pgrp);
spin_unlock_irqrestore(&tty->link->ctrl_lock, flags);
kill_pgrp(pgrp, sig, 1);
put_pid(pgrp);
}
return 0;
}
static void pty_flush_buffer(struct tty_struct *tty)
{
struct tty_struct *to = tty->link;
@ -321,6 +340,8 @@ static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file,
switch (cmd) {
case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
return pty_set_lock(tty, (int __user *) arg);
case TIOCSIG: /* Send signal to other side of pty */
return pty_signal(tty, (int) arg);
}
return -ENOIOCTLCMD;
}
@ -476,6 +497,8 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
return pty_set_lock(tty, (int __user *)arg);
case TIOCGPTN: /* Get PT Number */
return put_user(tty->index, (unsigned int __user *)arg);
case TIOCSIG: /* Send signal to other side of pty */
return pty_signal(tty, (int) arg);
}
return -ENOIOCTLCMD;
@ -626,7 +649,7 @@ static const struct tty_operations pty_unix98_ops = {
* allocated_ptys_lock handles the list of free pty numbers
*/
static int __ptmx_open(struct inode *inode, struct file *filp)
static int ptmx_open(struct inode *inode, struct file *filp)
{
struct tty_struct *tty;
int retval;
@ -635,11 +658,14 @@ static int __ptmx_open(struct inode *inode, struct file *filp)
nonseekable_open(inode, filp);
/* find a device that is not in use. */
tty_lock();
index = devpts_new_index(inode);
tty_unlock();
if (index < 0)
return index;
mutex_lock(&tty_mutex);
tty_lock();
tty = tty_init_dev(ptm_driver, index, 1);
mutex_unlock(&tty_mutex);
@ -657,26 +683,21 @@ static int __ptmx_open(struct inode *inode, struct file *filp)
goto out1;
retval = ptm_driver->ops->open(tty, filp);
if (!retval)
return 0;
if (retval)
goto out2;
out1:
tty_unlock();
return retval;
out2:
tty_unlock();
tty_release(inode, filp);
return retval;
out:
devpts_kill_index(inode, index);
tty_unlock();
return retval;
}
static int ptmx_open(struct inode *inode, struct file *filp)
{
int ret;
lock_kernel();
ret = __ptmx_open(inode, filp);
unlock_kernel();
return ret;
}
static struct file_operations ptmx_fops;
static void __init unix98_pty_init(void)

View File

@ -47,7 +47,6 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/tty_flip.h>
#include <linux/smp_lock.h>
#include <linux/spinlock.h>
#include <linux/device.h>
@ -1184,6 +1183,7 @@ static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port,
if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
return -EFAULT;
mutex_lock(&port->port.mutex);
change_speed = ((port->port.flags & ASYNC_SPD_MASK) !=
(tmp.flags & ASYNC_SPD_MASK));
@ -1191,8 +1191,10 @@ static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port,
if ((tmp.close_delay != port->port.close_delay) ||
(tmp.closing_wait != port->port.closing_wait) ||
((tmp.flags & ~ASYNC_USR_MASK) !=
(port->port.flags & ~ASYNC_USR_MASK)))
(port->port.flags & ~ASYNC_USR_MASK))) {
mutex_unlock(&port->port.mutex);
return -EPERM;
}
port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
(tmp.flags & ASYNC_USR_MASK));
} else {
@ -1208,6 +1210,7 @@ static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port,
rc_change_speed(tty, bp, port);
spin_unlock_irqrestore(&riscom_lock, flags);
}
mutex_unlock(&port->port.mutex);
return 0;
}
@ -1220,12 +1223,15 @@ static int rc_get_serial_info(struct riscom_port *port,
memset(&tmp, 0, sizeof(tmp));
tmp.type = PORT_CIRRUS;
tmp.line = port - rc_port;
mutex_lock(&port->port.mutex);
tmp.port = bp->base;
tmp.irq = bp->irq;
tmp.flags = port->port.flags;
tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC;
tmp.close_delay = port->port.close_delay * HZ/100;
tmp.closing_wait = port->port.closing_wait * HZ/100;
mutex_unlock(&port->port.mutex);
tmp.xmit_fifo_size = CD180_NFIFO;
return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0;
}
@ -1242,14 +1248,10 @@ static int rc_ioctl(struct tty_struct *tty, struct file *filp,
switch (cmd) {
case TIOCGSERIAL:
lock_kernel();
retval = rc_get_serial_info(port, argp);
unlock_kernel();
break;
case TIOCSSERIAL:
lock_kernel();
retval = rc_set_serial_info(tty, port, argp);
unlock_kernel();
break;
default:
retval = -ENOIOCTLCMD;

View File

@ -73,7 +73,6 @@
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/smp_lock.h>
#include <linux/string.h>
#include <linux/fcntl.h>
#include <linux/ptrace.h>
@ -1017,6 +1016,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp)
if (tty_port_close_start(port, tty, filp) == 0)
return;
mutex_lock(&port->mutex);
cp = &info->channel;
/*
* Before we drop DTR, make sure the UART transmitter
@ -1060,9 +1060,13 @@ static void rp_close(struct tty_struct *tty, struct file *filp)
info->xmit_buf = NULL;
}
}
spin_lock_irq(&port->lock);
info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE);
tty->closing = 0;
spin_unlock_irq(&port->lock);
mutex_unlock(&port->mutex);
tty_port_tty_set(port, NULL);
wake_up_interruptible(&port->close_wait);
complete_all(&info->close_wait);
atomic_dec(&rp_num_ports_open);
@ -1210,11 +1214,13 @@ static int get_config(struct r_port *info, struct rocket_config __user *retinfo)
if (!retinfo)
return -EFAULT;
memset(&tmp, 0, sizeof (tmp));
mutex_lock(&info->port.mutex);
tmp.line = info->line;
tmp.flags = info->flags;
tmp.close_delay = info->port.close_delay;
tmp.closing_wait = info->port.closing_wait;
tmp.port = rcktpt_io_addr[(info->line >> 5) & 3];
mutex_unlock(&info->port.mutex);
if (copy_to_user(retinfo, &tmp, sizeof (*retinfo)))
return -EFAULT;
@ -1229,10 +1235,13 @@ static int set_config(struct tty_struct *tty, struct r_port *info,
if (copy_from_user(&new_serial, new_info, sizeof (new_serial)))
return -EFAULT;
mutex_lock(&info->port.mutex);
if (!capable(CAP_SYS_ADMIN))
{
if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK))
if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) {
mutex_unlock(&info->port.mutex);
return -EPERM;
}
info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK));
configure_r_port(tty, info, NULL);
return 0;
@ -1250,6 +1259,7 @@ static int set_config(struct tty_struct *tty, struct r_port *info,
tty->alt_speed = 230400;
if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
tty->alt_speed = 460800;
mutex_unlock(&info->port.mutex);
configure_r_port(tty, info, NULL);
return 0;
@ -1325,8 +1335,6 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file,
if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl"))
return -ENXIO;
lock_kernel();
switch (cmd) {
case RCKP_GET_STRUCT:
if (copy_to_user(argp, info, sizeof (struct r_port)))
@ -1350,7 +1358,6 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file,
default:
ret = -ENOIOCTLCMD;
}
unlock_kernel();
return ret;
}
@ -1471,7 +1478,6 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
jiffies);
printk(KERN_INFO "cps=%d...\n", info->cps);
#endif
lock_kernel();
while (1) {
txcnt = sGetTxCnt(cp);
if (!txcnt) {
@ -1499,7 +1505,6 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
break;
}
__set_current_state(TASK_RUNNING);
unlock_kernel();
#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
#endif
@ -1512,6 +1517,7 @@ static void rp_hangup(struct tty_struct *tty)
{
CHANNEL_t *cp;
struct r_port *info = tty->driver_data;
unsigned long flags;
if (rocket_paranoia_check(info, "rp_hangup"))
return;
@ -1520,11 +1526,15 @@ static void rp_hangup(struct tty_struct *tty)
printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line);
#endif
rp_flush_buffer(tty);
if (info->port.flags & ASYNC_CLOSING)
spin_lock_irqsave(&info->port.lock, flags);
if (info->port.flags & ASYNC_CLOSING) {
spin_unlock_irqrestore(&info->port.lock, flags);
return;
}
if (info->port.count)
atomic_dec(&rp_num_ports_open);
clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
spin_unlock_irqrestore(&info->port.lock, flags);
tty_port_hangup(&info->port);
@ -1535,7 +1545,7 @@ static void rp_hangup(struct tty_struct *tty)
sDisCTSFlowCtl(cp);
sDisTxSoftFlowCtl(cp);
sClrTxXOFF(cp);
info->port.flags &= ~ASYNC_INITIALIZED;
clear_bit(ASYNCB_INITIALIZED, &info->port.flags);
wake_up_interruptible(&info->port.open_wait);
}

View File

@ -26,6 +26,7 @@
#include <linux/selection.h>
#include <linux/tiocl.h>
#include <linux/console.h>
#include <linux/smp_lock.h>
/* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */
#define isspace(c) ((c) == ' ')
@ -312,12 +313,20 @@ int paste_selection(struct tty_struct *tty)
struct tty_ldisc *ld;
DECLARE_WAITQUEUE(wait, current);
/* always called with BTM from vt_ioctl */
WARN_ON(!tty_locked());
acquire_console_sem();
poke_blanked_console();
release_console_sem();
ld = tty_ldisc_ref_wait(tty);
ld = tty_ldisc_ref(tty);
if (!ld) {
tty_unlock();
ld = tty_ldisc_ref_wait(tty);
tty_lock();
}
add_wait_queue(&vc->paste_wait, &wait);
while (sel_buffer && sel_buffer_lth > pasted) {
set_current_state(TASK_INTERRUPTIBLE);

View File

@ -1505,7 +1505,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */
#endif
lock_kernel();
tty_lock();
switch (cmd) {
case CYGETMON:
@ -1561,7 +1561,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
default:
ret_val = -ENOIOCTLCMD;
}
unlock_kernel();
tty_unlock();
#ifdef SERIAL_DEBUG_OTHER
printk("cy_ioctl done\n");
@ -1786,7 +1786,9 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
tty->name, info->count);
/**/
#endif
schedule();
tty_unlock();
schedule();
tty_lock();
}
__set_current_state(TASK_RUNNING);
remove_wait_queue(&info->open_wait, &wait);

View File

@ -1365,7 +1365,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
retval = -ERESTARTSYS;
break;
}
tty_unlock();
schedule();
tty_lock();
}
set_current_state(TASK_RUNNING);
@ -1863,8 +1865,7 @@ static int sx_set_serial_info(struct specialix_port *port,
return -EFAULT;
}
lock_kernel();
mutex_lock(&port->port.mutex);
change_speed = ((port->port.flags & ASYNC_SPD_MASK) !=
(tmp.flags & ASYNC_SPD_MASK));
change_speed |= (tmp.custom_divisor != port->custom_divisor);
@ -1875,7 +1876,7 @@ static int sx_set_serial_info(struct specialix_port *port,
((tmp.flags & ~ASYNC_USR_MASK) !=
(port->port.flags & ~ASYNC_USR_MASK))) {
func_exit();
unlock_kernel();
mutex_unlock(&port->port.mutex);
return -EPERM;
}
port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
@ -1892,7 +1893,7 @@ static int sx_set_serial_info(struct specialix_port *port,
sx_change_speed(bp, port);
func_exit();
unlock_kernel();
mutex_unlock(&port->port.mutex);
return 0;
}
@ -1906,7 +1907,7 @@ static int sx_get_serial_info(struct specialix_port *port,
func_enter();
memset(&tmp, 0, sizeof(tmp));
lock_kernel();
mutex_lock(&port->port.mutex);
tmp.type = PORT_CIRRUS;
tmp.line = port - sx_port;
tmp.port = bp->base;
@ -1917,7 +1918,7 @@ static int sx_get_serial_info(struct specialix_port *port,
tmp.closing_wait = port->port.closing_wait * HZ/100;
tmp.custom_divisor = port->custom_divisor;
tmp.xmit_fifo_size = CD186x_NFIFO;
unlock_kernel();
mutex_unlock(&port->port.mutex);
if (copy_to_user(retinfo, &tmp, sizeof(tmp))) {
func_exit();
return -EFAULT;

View File

@ -807,7 +807,6 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
timeout = HZ;
tend = jiffies + timeout;
lock_kernel();
while (stl_datastate(portp)) {
if (signal_pending(current))
break;
@ -815,7 +814,6 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
if (time_after_eq(jiffies, tend))
break;
}
unlock_kernel();
}
/*****************************************************************************/
@ -1029,6 +1027,8 @@ static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
memset(&sio, 0, sizeof(struct serial_struct));
mutex_lock(&portp->port.mutex);
sio.line = portp->portnr;
sio.port = portp->ioaddr;
sio.flags = portp->port.flags;
@ -1048,6 +1048,7 @@ static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
brdp = stl_brds[portp->brdnr];
if (brdp != NULL)
sio.irq = brdp->irq;
mutex_unlock(&portp->port.mutex);
return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
}
@ -1069,12 +1070,15 @@ static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp
if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
return -EFAULT;
mutex_lock(&portp->port.mutex);
if (!capable(CAP_SYS_ADMIN)) {
if ((sio.baud_base != portp->baud_base) ||
(sio.close_delay != portp->close_delay) ||
((sio.flags & ~ASYNC_USR_MASK) !=
(portp->port.flags & ~ASYNC_USR_MASK)))
(portp->port.flags & ~ASYNC_USR_MASK))) {
mutex_unlock(&portp->port.mutex);
return -EPERM;
}
}
portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
@ -1083,6 +1087,7 @@ static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp
portp->close_delay = sio.close_delay;
portp->closing_wait = sio.closing_wait;
portp->custom_divisor = sio.custom_divisor;
mutex_unlock(&portp->port.mutex);
stl_setport(portp, tty->termios);
return 0;
}
@ -1147,8 +1152,6 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
rc = 0;
lock_kernel();
switch (cmd) {
case TIOCGSERIAL:
rc = stl_getserial(portp, argp);
@ -1173,7 +1176,6 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
rc = -ENOIOCTLCMD;
break;
}
unlock_kernel();
return rc;
}
@ -2327,6 +2329,7 @@ static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comst
return -ENODEV;
}
mutex_lock(&portp->port.mutex);
portp->stats.state = portp->istate;
portp->stats.flags = portp->port.flags;
portp->stats.hwid = portp->hwid;
@ -2358,6 +2361,7 @@ static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comst
(STL_TXBUFSIZE - (tail - head));
portp->stats.signals = (unsigned long) stl_getsignals(portp);
mutex_unlock(&portp->port.mutex);
return copy_to_user(cp, &portp->stats,
sizeof(comstats_t)) ? -EFAULT : 0;
@ -2382,10 +2386,12 @@ static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
return -ENODEV;
}
mutex_lock(&portp->port.mutex);
memset(&portp->stats, 0, sizeof(comstats_t));
portp->stats.brd = portp->brdnr;
portp->stats.panel = portp->panelnr;
portp->stats.port = portp->portnr;
mutex_unlock(&portp->port.mutex);
return copy_to_user(cp, &portp->stats,
sizeof(comstats_t)) ? -EFAULT : 0;
}
@ -2451,7 +2457,6 @@ static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
return -ENODEV;
rc = 0;
lock_kernel();
switch (cmd) {
case COM_GETPORTSTATS:
rc = stl_getportstats(NULL, NULL, argp);
@ -2472,7 +2477,6 @@ static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
rc = -ENOIOCTLCMD;
break;
}
unlock_kernel();
return rc;
}

View File

@ -1699,7 +1699,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
lock_kernel();
tty_lock();
sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
@ -1848,7 +1848,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
break;
}
out:
unlock_kernel();
tty_unlock();
func_exit();
return rc;
}
@ -1859,7 +1859,7 @@ static int sx_break(struct tty_struct *tty, int flag)
int rv;
func_enter();
lock_kernel();
tty_lock();
if (flag)
rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK);
@ -1868,7 +1868,7 @@ static int sx_break(struct tty_struct *tty, int flag)
if (rv != 1)
printk(KERN_ERR "sx: couldn't send break (%x).\n",
read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
unlock_kernel();
tty_unlock();
func_exit();
return 0;
}
@ -1909,7 +1909,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp,
/* func_enter2(); */
rc = 0;
lock_kernel();
tty_lock();
switch (cmd) {
case TIOCGSERIAL:
rc = gs_getserial(&port->gs, argp);
@ -1921,7 +1921,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp,
rc = -ENOIOCTLCMD;
break;
}
unlock_kernel();
tty_unlock();
/* func_exit(); */
return rc;

View File

@ -81,7 +81,6 @@
#include <linux/mm.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/vmalloc.h>
@ -2436,7 +2435,9 @@ static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount __user *
if (!user_icount) {
memset(&info->icount, 0, sizeof(info->icount));
} else {
mutex_lock(&info->port.mutex);
COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
mutex_unlock(&info->port.mutex);
if (err)
return -EFAULT;
}
@ -2461,7 +2462,9 @@ static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS __user *user_p
printk("%s(%d):mgsl_get_params(%s)\n",
__FILE__,__LINE__, info->device_name);
mutex_lock(&info->port.mutex);
COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS));
mutex_unlock(&info->port.mutex);
if (err) {
if ( debug_level >= DEBUG_LEVEL_INFO )
printk( "%s(%d):mgsl_get_params(%s) user buffer copy failed\n",
@ -2501,11 +2504,13 @@ static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS __user *new_pa
return -EFAULT;
}
mutex_lock(&info->port.mutex);
spin_lock_irqsave(&info->irq_spinlock,flags);
memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS));
spin_unlock_irqrestore(&info->irq_spinlock,flags);
mgsl_change_params(info);
mutex_unlock(&info->port.mutex);
return 0;
@ -2935,7 +2940,6 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
struct mgsl_struct * info = tty->driver_data;
int ret;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
@ -2950,10 +2954,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
return -EIO;
}
lock_kernel();
ret = mgsl_ioctl_common(info, cmd, arg);
unlock_kernel();
return ret;
return mgsl_ioctl_common(info, cmd, arg);
}
static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
@ -3109,12 +3110,14 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp)
if (tty_port_close_start(&info->port, tty, filp) == 0)
goto cleanup;
mutex_lock(&info->port.mutex);
if (info->port.flags & ASYNC_INITIALIZED)
mgsl_wait_until_sent(tty, info->timeout);
mgsl_flush_buffer(tty);
tty_ldisc_flush(tty);
shutdown(info);
mutex_unlock(&info->port.mutex);
tty_port_close_end(&info->port, tty);
info->port.tty = NULL;
@ -3162,7 +3165,6 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)
* Note: use tight timings here to satisfy the NIST-PCTS.
*/
lock_kernel();
if ( info->params.data_rate ) {
char_time = info->timeout/(32 * 5);
if (!char_time)
@ -3192,7 +3194,6 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)
break;
}
}
unlock_kernel();
exit:
if (debug_level >= DEBUG_LEVEL_INFO)
@ -3348,7 +3349,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
printk("%s(%d):block_til_ready blocking on %s count=%d\n",
__FILE__,__LINE__, tty->driver->name, port->count );
tty_unlock();
schedule();
tty_lock();
}
set_current_state(TASK_RUNNING);

View File

@ -40,8 +40,8 @@
#define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt
#define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt
#define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label))
//#define DBGTBUF(info) dump_tbufs(info)
//#define DBGRBUF(info) dump_rbufs(info)
/*#define DBGTBUF(info) dump_tbufs(info)*/
/*#define DBGRBUF(info) dump_rbufs(info)*/
#include <linux/module.h>
@ -62,7 +62,6 @@
#include <linux/mm.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/netdevice.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
@ -676,12 +675,14 @@ static int open(struct tty_struct *tty, struct file *filp)
goto cleanup;
}
mutex_lock(&info->port.mutex);
info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
spin_lock_irqsave(&info->netlock, flags);
if (info->netcount) {
retval = -EBUSY;
spin_unlock_irqrestore(&info->netlock, flags);
mutex_unlock(&info->port.mutex);
goto cleanup;
}
info->port.count++;
@ -693,7 +694,7 @@ static int open(struct tty_struct *tty, struct file *filp)
if (retval < 0)
goto cleanup;
}
mutex_unlock(&info->port.mutex);
retval = block_til_ready(tty, filp, info);
if (retval) {
DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval));
@ -725,12 +726,14 @@ static void close(struct tty_struct *tty, struct file *filp)
if (tty_port_close_start(&info->port, tty, filp) == 0)
goto cleanup;
mutex_lock(&info->port.mutex);
if (info->port.flags & ASYNC_INITIALIZED)
wait_until_sent(tty, info->timeout);
flush_buffer(tty);
tty_ldisc_flush(tty);
shutdown(info);
mutex_unlock(&info->port.mutex);
tty_port_close_end(&info->port, tty);
info->port.tty = NULL;
@ -741,17 +744,23 @@ cleanup:
static void hangup(struct tty_struct *tty)
{
struct slgt_info *info = tty->driver_data;
unsigned long flags;
if (sanity_check(info, tty->name, "hangup"))
return;
DBGINFO(("%s hangup\n", info->device_name));
flush_buffer(tty);
mutex_lock(&info->port.mutex);
shutdown(info);
spin_lock_irqsave(&info->port.lock, flags);
info->port.count = 0;
info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
info->port.tty = NULL;
spin_unlock_irqrestore(&info->port.lock, flags);
mutex_unlock(&info->port.mutex);
wake_up_interruptible(&info->port.open_wait);
}
@ -901,8 +910,6 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
* Note: use tight timings here to satisfy the NIST-PCTS.
*/
lock_kernel();
if (info->params.data_rate) {
char_time = info->timeout/(32 * 5);
if (!char_time)
@ -920,8 +927,6 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
if (timeout && time_after(jiffies, orig_jiffies + timeout))
break;
}
unlock_kernel();
exit:
DBGINFO(("%s wait_until_sent exit\n", info->device_name));
}
@ -1041,8 +1046,37 @@ static int ioctl(struct tty_struct *tty, struct file *file,
return -EIO;
}
lock_kernel();
switch (cmd) {
case MGSL_IOCWAITEVENT:
return wait_mgsl_event(info, argp);
case TIOCMIWAIT:
return modem_input_wait(info,(int)arg);
case TIOCGICOUNT:
spin_lock_irqsave(&info->lock,flags);
cnow = info->icount;
spin_unlock_irqrestore(&info->lock,flags);
p_cuser = argp;
if (put_user(cnow.cts, &p_cuser->cts) ||
put_user(cnow.dsr, &p_cuser->dsr) ||
put_user(cnow.rng, &p_cuser->rng) ||
put_user(cnow.dcd, &p_cuser->dcd) ||
put_user(cnow.rx, &p_cuser->rx) ||
put_user(cnow.tx, &p_cuser->tx) ||
put_user(cnow.frame, &p_cuser->frame) ||
put_user(cnow.overrun, &p_cuser->overrun) ||
put_user(cnow.parity, &p_cuser->parity) ||
put_user(cnow.brk, &p_cuser->brk) ||
put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
return -EFAULT;
return 0;
case MGSL_IOCSGPIO:
return set_gpio(info, argp);
case MGSL_IOCGGPIO:
return get_gpio(info, argp);
case MGSL_IOCWAITGPIO:
return wait_gpio(info, argp);
}
mutex_lock(&info->port.mutex);
switch (cmd) {
case MGSL_IOCGPARAMS:
ret = get_params(info, argp);
@ -1068,50 +1102,16 @@ static int ioctl(struct tty_struct *tty, struct file *file,
case MGSL_IOCGSTATS:
ret = get_stats(info, argp);
break;
case MGSL_IOCWAITEVENT:
ret = wait_mgsl_event(info, argp);
break;
case TIOCMIWAIT:
ret = modem_input_wait(info,(int)arg);
break;
case MGSL_IOCGIF:
ret = get_interface(info, argp);
break;
case MGSL_IOCSIF:
ret = set_interface(info,(int)arg);
break;
case MGSL_IOCSGPIO:
ret = set_gpio(info, argp);
break;
case MGSL_IOCGGPIO:
ret = get_gpio(info, argp);
break;
case MGSL_IOCWAITGPIO:
ret = wait_gpio(info, argp);
break;
case TIOCGICOUNT:
spin_lock_irqsave(&info->lock,flags);
cnow = info->icount;
spin_unlock_irqrestore(&info->lock,flags);
p_cuser = argp;
if (put_user(cnow.cts, &p_cuser->cts) ||
put_user(cnow.dsr, &p_cuser->dsr) ||
put_user(cnow.rng, &p_cuser->rng) ||
put_user(cnow.dcd, &p_cuser->dcd) ||
put_user(cnow.rx, &p_cuser->rx) ||
put_user(cnow.tx, &p_cuser->tx) ||
put_user(cnow.frame, &p_cuser->frame) ||
put_user(cnow.overrun, &p_cuser->overrun) ||
put_user(cnow.parity, &p_cuser->parity) ||
put_user(cnow.brk, &p_cuser->brk) ||
put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
ret = -EFAULT;
ret = 0;
break;
default:
ret = -ENOIOCTLCMD;
}
unlock_kernel();
mutex_unlock(&info->port.mutex);
return ret;
}
@ -3244,7 +3244,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
}
DBGINFO(("%s block_til_ready wait\n", tty->driver->name));
tty_unlock();
schedule();
tty_lock();
}
set_current_state(TASK_RUNNING);

View File

@ -52,7 +52,6 @@
#include <linux/mm.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/netdevice.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
@ -813,13 +812,15 @@ static void close(struct tty_struct *tty, struct file *filp)
if (tty_port_close_start(&info->port, tty, filp) == 0)
goto cleanup;
mutex_lock(&info->port.mutex);
if (info->port.flags & ASYNC_INITIALIZED)
wait_until_sent(tty, info->timeout);
flush_buffer(tty);
tty_ldisc_flush(tty);
shutdown(info);
mutex_unlock(&info->port.mutex);
tty_port_close_end(&info->port, tty);
info->port.tty = NULL;
@ -835,6 +836,7 @@ cleanup:
static void hangup(struct tty_struct *tty)
{
SLMP_INFO *info = tty->driver_data;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s hangup()\n",
@ -843,12 +845,16 @@ static void hangup(struct tty_struct *tty)
if (sanity_check(info, tty->name, "hangup"))
return;
mutex_lock(&info->port.mutex);
flush_buffer(tty);
shutdown(info);
spin_lock_irqsave(&info->port.lock, flags);
info->port.count = 0;
info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
info->port.tty = NULL;
spin_unlock_irqrestore(&info->port.lock, flags);
mutex_unlock(&info->port.mutex);
wake_up_interruptible(&info->port.open_wait);
}
@ -1062,9 +1068,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
if (sanity_check(info, tty->name, "wait_until_sent"))
return;
lock_kernel();
if (!(info->port.flags & ASYNC_INITIALIZED))
if (!test_bit(ASYNCB_INITIALIZED, &info->port.flags))
goto exit;
orig_jiffies = jiffies;
@ -1094,8 +1098,10 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
break;
}
} else {
//TODO: determine if there is something similar to USC16C32
// TXSTATUS_ALL_SENT status
/*
* TODO: determine if there is something similar to USC16C32
* TXSTATUS_ALL_SENT status
*/
while ( info->tx_active && info->tx_enabled) {
msleep_interruptible(jiffies_to_msecs(char_time));
if (signal_pending(current))
@ -1106,7 +1112,6 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
}
exit:
unlock_kernel();
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s wait_until_sent() exit\n",
__FILE__,__LINE__, info->device_name );
@ -1122,7 +1127,6 @@ static int write_room(struct tty_struct *tty)
if (sanity_check(info, tty->name, "write_room"))
return 0;
lock_kernel();
if (info->params.mode == MGSL_MODE_HDLC) {
ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE;
} else {
@ -1130,7 +1134,6 @@ static int write_room(struct tty_struct *tty)
if (ret < 0)
ret = 0;
}
unlock_kernel();
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s write_room()=%d\n",
@ -1251,7 +1254,7 @@ static void tx_release(struct tty_struct *tty)
*
* Return Value: 0 if success, otherwise error code
*/
static int do_ioctl(struct tty_struct *tty, struct file *file,
static int ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
SLMP_INFO *info = tty->driver_data;
@ -1341,16 +1344,6 @@ static int do_ioctl(struct tty_struct *tty, struct file *file,
return 0;
}
static int ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
int ret;
lock_kernel();
ret = do_ioctl(tty, file, cmd, arg);
unlock_kernel();
return ret;
}
/*
* /proc fs routines....
*/
@ -2883,7 +2876,9 @@ static int get_stats(SLMP_INFO * info, struct mgsl_icount __user *user_icount)
if (!user_icount) {
memset(&info->icount, 0, sizeof(info->icount));
} else {
mutex_lock(&info->port.mutex);
COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
mutex_unlock(&info->port.mutex);
if (err)
return -EFAULT;
}
@ -2898,7 +2893,9 @@ static int get_params(SLMP_INFO * info, MGSL_PARAMS __user *user_params)
printk("%s(%d):%s get_params()\n",
__FILE__,__LINE__, info->device_name);
mutex_lock(&info->port.mutex);
COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS));
mutex_unlock(&info->port.mutex);
if (err) {
if ( debug_level >= DEBUG_LEVEL_INFO )
printk( "%s(%d):%s get_params() user buffer copy failed\n",
@ -2926,11 +2923,13 @@ static int set_params(SLMP_INFO * info, MGSL_PARAMS __user *new_params)
return -EFAULT;
}
mutex_lock(&info->port.mutex);
spin_lock_irqsave(&info->lock,flags);
memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS));
spin_unlock_irqrestore(&info->lock,flags);
change_params(info);
mutex_unlock(&info->port.mutex);
return 0;
}
@ -3366,7 +3365,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
printk("%s(%d):%s block_til_ready() count=%d\n",
__FILE__,__LINE__, tty->driver->name, port->count );
tty_unlock();
schedule();
tty_lock();
}
set_current_state(TASK_RUNNING);

View File

@ -149,6 +149,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
#else
#define tty_compat_ioctl NULL
#endif
static int __tty_fasync(int fd, struct file *filp, int on);
static int tty_fasync(int fd, struct file *filp, int on);
static void release_tty(struct tty_struct *tty, int idx);
static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
@ -470,7 +471,7 @@ void tty_wakeup(struct tty_struct *tty)
EXPORT_SYMBOL_GPL(tty_wakeup);
/**
* do_tty_hangup - actual handler for hangup events
* __tty_hangup - actual handler for hangup events
* @work: tty device
*
* This can be called by the "eventd" kernel thread. That is process
@ -483,7 +484,7 @@ EXPORT_SYMBOL_GPL(tty_wakeup);
* remains intact.
*
* Locking:
* BKL
* BTM
* redirect lock for undoing redirection
* file list lock for manipulating list of ttys
* tty_ldisc_lock from called functions
@ -491,10 +492,8 @@ EXPORT_SYMBOL_GPL(tty_wakeup);
* tasklist_lock to walk task list for hangup event
* ->siglock to protect ->signal/->sighand
*/
static void do_tty_hangup(struct work_struct *work)
void __tty_hangup(struct tty_struct *tty)
{
struct tty_struct *tty =
container_of(work, struct tty_struct, hangup_work);
struct file *cons_filp = NULL;
struct file *filp, *f = NULL;
struct task_struct *p;
@ -513,9 +512,12 @@ static void do_tty_hangup(struct work_struct *work)
}
spin_unlock(&redirect_lock);
/* inuse_filps is protected by the single kernel lock */
lock_kernel();
check_tty_count(tty, "do_tty_hangup");
tty_lock();
/* inuse_filps is protected by the single tty lock,
this really needs to change if we want to flush the
workqueue with the lock held */
check_tty_count(tty, "tty_hangup");
file_list_lock();
/* This breaks for file handles being sent over AF_UNIX sockets ? */
@ -525,7 +527,7 @@ static void do_tty_hangup(struct work_struct *work)
if (filp->f_op->write != tty_write)
continue;
closecount++;
tty_fasync(-1, filp, 0); /* can't block */
__tty_fasync(-1, filp, 0); /* can't block */
filp->f_op = &hung_up_tty_fops;
}
file_list_unlock();
@ -594,11 +596,21 @@ static void do_tty_hangup(struct work_struct *work)
*/
set_bit(TTY_HUPPED, &tty->flags);
tty_ldisc_enable(tty);
unlock_kernel();
tty_unlock();
if (f)
fput(f);
}
static void do_tty_hangup(struct work_struct *work)
{
struct tty_struct *tty =
container_of(work, struct tty_struct, hangup_work);
__tty_hangup(tty);
}
/**
* tty_hangup - trigger a hangup event
* @tty: tty to hangup
@ -634,11 +646,12 @@ void tty_vhangup(struct tty_struct *tty)
printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf));
#endif
do_tty_hangup(&tty->hangup_work);
__tty_hangup(tty);
}
EXPORT_SYMBOL(tty_vhangup);
/**
* tty_vhangup_self - process vhangup for own ctty
*
@ -696,7 +709,8 @@ static void session_clear_tty(struct pid *session)
* exiting; it is 0 if called by the ioctl TIOCNOTTY.
*
* Locking:
* BKL is taken for hysterical raisins
* BTM is taken for hysterical raisins, and held when
* called from no_tty().
* tty_mutex is taken to protect tty
* ->siglock is taken to protect ->signal/->sighand
* tasklist_lock is taken to walk process list for sessions
@ -714,10 +728,10 @@ void disassociate_ctty(int on_exit)
tty = get_current_tty();
if (tty) {
tty_pgrp = get_pid(tty->pgrp);
lock_kernel();
if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
tty_vhangup(tty);
unlock_kernel();
if (on_exit) {
if (tty->driver->type != TTY_DRIVER_TYPE_PTY)
tty_vhangup(tty);
}
tty_kref_put(tty);
} else if (on_exit) {
struct pid *old_pgrp;
@ -774,9 +788,9 @@ void disassociate_ctty(int on_exit)
void no_tty(void)
{
struct task_struct *tsk = current;
lock_kernel();
tty_lock();
disassociate_ctty(0);
unlock_kernel();
tty_unlock();
proc_clear_tty(tsk);
}
@ -879,7 +893,7 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
struct inode *inode;
struct tty_ldisc *ld;
tty = (struct tty_struct *)file->private_data;
tty = file->private_data;
inode = file->f_path.dentry->d_inode;
if (tty_paranoia_check(tty, inode, "tty_read"))
return -EIO;
@ -1013,19 +1027,19 @@ out:
* We don't put it into the syslog queue right now maybe in the future if
* really needed.
*
* We must still hold the BKL and test the CLOSING flag for the moment.
* We must still hold the BTM and test the CLOSING flag for the moment.
*/
void tty_write_message(struct tty_struct *tty, char *msg)
{
if (tty) {
mutex_lock(&tty->atomic_write_lock);
lock_kernel();
tty_lock();
if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) {
unlock_kernel();
tty_unlock();
tty->ops->write(tty, msg, strlen(msg));
} else
unlock_kernel();
tty_unlock();
tty_write_unlock(tty);
}
return;
@ -1056,7 +1070,7 @@ static ssize_t tty_write(struct file *file, const char __user *buf,
ssize_t ret;
struct tty_ldisc *ld;
tty = (struct tty_struct *)file->private_data;
tty = file->private_data;
if (tty_paranoia_check(tty, inode, "tty_write"))
return -EIO;
if (!tty || !tty->ops->write ||
@ -1208,18 +1222,14 @@ static int tty_driver_install_tty(struct tty_driver *driver,
int ret;
if (driver->ops->install) {
lock_kernel();
ret = driver->ops->install(driver, tty);
unlock_kernel();
return ret;
}
if (tty_init_termios(tty) == 0) {
lock_kernel();
tty_driver_kref_get(driver);
tty->count++;
driver->ttys[idx] = tty;
unlock_kernel();
return 0;
}
return -ENOMEM;
@ -1312,14 +1322,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
struct tty_struct *tty;
int retval;
lock_kernel();
/* Check if pty master is being opened multiple times */
if (driver->subtype == PTY_TYPE_MASTER &&
(driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) {
unlock_kernel();
return ERR_PTR(-EIO);
}
unlock_kernel();
/*
* First time open is complex, especially for PTY devices.
@ -1363,9 +1370,7 @@ release_mem_out:
if (printk_ratelimit())
printk(KERN_INFO "tty_init_dev: ldisc open failed, "
"clearing slot %d\n", idx);
lock_kernel();
release_tty(tty, idx);
unlock_kernel();
return ERR_PTR(retval);
}
@ -1508,14 +1513,14 @@ int tty_release(struct inode *inode, struct file *filp)
int idx;
char buf[64];
tty = (struct tty_struct *)filp->private_data;
tty = filp->private_data;
if (tty_paranoia_check(tty, inode, "tty_release_dev"))
return 0;
lock_kernel();
tty_lock();
check_tty_count(tty, "tty_release_dev");
tty_fasync(-1, filp, 0);
__tty_fasync(-1, filp, 0);
idx = tty->index;
pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
@ -1527,18 +1532,18 @@ int tty_release(struct inode *inode, struct file *filp)
if (idx < 0 || idx >= tty->driver->num) {
printk(KERN_DEBUG "tty_release_dev: bad idx when trying to "
"free (%s)\n", tty->name);
unlock_kernel();
tty_unlock();
return 0;
}
if (!devpts) {
if (tty != tty->driver->ttys[idx]) {
unlock_kernel();
tty_unlock();
printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty "
"for (%s)\n", idx, tty->name);
return 0;
}
if (tty->termios != tty->driver->termios[idx]) {
unlock_kernel();
tty_unlock();
printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios "
"for (%s)\n",
idx, tty->name);
@ -1556,21 +1561,21 @@ int tty_release(struct inode *inode, struct file *filp)
if (tty->driver->other &&
!(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
if (o_tty != tty->driver->other->ttys[idx]) {
unlock_kernel();
tty_unlock();
printk(KERN_DEBUG "tty_release_dev: other->table[%d] "
"not o_tty for (%s)\n",
idx, tty->name);
return 0 ;
}
if (o_tty->termios != tty->driver->other->termios[idx]) {
unlock_kernel();
tty_unlock();
printk(KERN_DEBUG "tty_release_dev: other->termios[%d] "
"not o_termios for (%s)\n",
idx, tty->name);
return 0;
}
if (o_tty->link != tty) {
unlock_kernel();
tty_unlock();
printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n");
return 0;
}
@ -1579,7 +1584,7 @@ int tty_release(struct inode *inode, struct file *filp)
if (tty->ops->close)
tty->ops->close(tty, filp);
unlock_kernel();
tty_unlock();
/*
* Sanity check: if tty->count is going to zero, there shouldn't be
* any waiters on tty->read_wait or tty->write_wait. We test the
@ -1602,7 +1607,7 @@ int tty_release(struct inode *inode, struct file *filp)
opens on /dev/tty */
mutex_lock(&tty_mutex);
lock_kernel();
tty_lock();
tty_closing = tty->count <= 1;
o_tty_closing = o_tty &&
(o_tty->count <= (pty_master ? 1 : 0));
@ -1633,7 +1638,7 @@ int tty_release(struct inode *inode, struct file *filp)
printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue "
"active!\n", tty_name(tty, buf));
unlock_kernel();
tty_unlock();
mutex_unlock(&tty_mutex);
schedule();
}
@ -1698,7 +1703,7 @@ int tty_release(struct inode *inode, struct file *filp)
/* check whether both sides are closing ... */
if (!tty_closing || (o_tty && !o_tty_closing)) {
unlock_kernel();
tty_unlock();
return 0;
}
@ -1718,7 +1723,7 @@ int tty_release(struct inode *inode, struct file *filp)
/* Make this pty number available for reallocation */
if (devpts)
devpts_kill_index(inode, idx);
unlock_kernel();
tty_unlock();
return 0;
}
@ -1760,12 +1765,12 @@ retry_open:
retval = 0;
mutex_lock(&tty_mutex);
lock_kernel();
tty_lock();
if (device == MKDEV(TTYAUX_MAJOR, 0)) {
tty = get_current_tty();
if (!tty) {
unlock_kernel();
tty_unlock();
mutex_unlock(&tty_mutex);
return -ENXIO;
}
@ -1797,14 +1802,14 @@ retry_open:
goto got_driver;
}
}
unlock_kernel();
tty_unlock();
mutex_unlock(&tty_mutex);
return -ENODEV;
}
driver = get_tty_driver(device, &index);
if (!driver) {
unlock_kernel();
tty_unlock();
mutex_unlock(&tty_mutex);
return -ENODEV;
}
@ -1814,7 +1819,7 @@ got_driver:
tty = tty_driver_lookup_tty(driver, inode, index);
if (IS_ERR(tty)) {
unlock_kernel();
tty_unlock();
mutex_unlock(&tty_mutex);
return PTR_ERR(tty);
}
@ -1830,7 +1835,7 @@ got_driver:
mutex_unlock(&tty_mutex);
tty_driver_kref_put(driver);
if (IS_ERR(tty)) {
unlock_kernel();
tty_unlock();
return PTR_ERR(tty);
}
@ -1860,29 +1865,29 @@ got_driver:
printk(KERN_DEBUG "error %d in opening %s...", retval,
tty->name);
#endif
tty_unlock(); /* need to call tty_release without BTM */
tty_release(inode, filp);
if (retval != -ERESTARTSYS) {
unlock_kernel();
if (retval != -ERESTARTSYS)
return retval;
}
if (signal_pending(current)) {
unlock_kernel();
if (signal_pending(current))
return retval;
}
schedule();
/*
* Need to reset f_op in case a hangup happened.
*/
tty_lock();
if (filp->f_op == &hung_up_tty_fops)
filp->f_op = &tty_fops;
unlock_kernel();
tty_unlock();
goto retry_open;
}
unlock_kernel();
tty_unlock();
mutex_lock(&tty_mutex);
lock_kernel();
tty_lock();
spin_lock_irq(&current->sighand->siglock);
if (!noctty &&
current->signal->leader &&
@ -1890,7 +1895,7 @@ got_driver:
tty->session == NULL)
__proc_set_tty(current, tty);
spin_unlock_irq(&current->sighand->siglock);
unlock_kernel();
tty_unlock();
mutex_unlock(&tty_mutex);
return 0;
}
@ -1915,7 +1920,7 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait)
struct tty_ldisc *ld;
int ret = 0;
tty = (struct tty_struct *)filp->private_data;
tty = filp->private_data;
if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll"))
return 0;
@ -1926,14 +1931,13 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait)
return ret;
}
static int tty_fasync(int fd, struct file *filp, int on)
static int __tty_fasync(int fd, struct file *filp, int on)
{
struct tty_struct *tty;
unsigned long flags;
int retval = 0;
lock_kernel();
tty = (struct tty_struct *)filp->private_data;
tty = filp->private_data;
if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync"))
goto out;
@ -1966,7 +1970,15 @@ static int tty_fasync(int fd, struct file *filp, int on)
}
retval = 0;
out:
unlock_kernel();
return retval;
}
static int tty_fasync(int fd, struct file *filp, int on)
{
int retval;
tty_lock();
retval = __tty_fasync(fd, filp, on);
tty_unlock();
return retval;
}
@ -2485,7 +2497,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct tty_ldisc *ld;
struct inode *inode = file->f_dentry->d_inode;
tty = (struct tty_struct *)file->private_data;
tty = file->private_data;
if (tty_paranoia_check(tty, inode, "tty_ioctl"))
return -EINVAL;

View File

@ -517,19 +517,25 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
/* See if packet mode change of state. */
if (tty->link && tty->link->packet) {
int extproc = (old_termios.c_lflag & EXTPROC) |
(tty->termios->c_lflag & EXTPROC);
int old_flow = ((old_termios.c_iflag & IXON) &&
(old_termios.c_cc[VSTOP] == '\023') &&
(old_termios.c_cc[VSTART] == '\021'));
int new_flow = (I_IXON(tty) &&
STOP_CHAR(tty) == '\023' &&
START_CHAR(tty) == '\021');
if (old_flow != new_flow) {
if ((old_flow != new_flow) || extproc) {
spin_lock_irqsave(&tty->ctrl_lock, flags);
tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
if (new_flow)
tty->ctrl_status |= TIOCPKT_DOSTOP;
else
tty->ctrl_status |= TIOCPKT_NOSTOP;
if (old_flow != new_flow) {
tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
if (new_flow)
tty->ctrl_status |= TIOCPKT_DOSTOP;
else
tty->ctrl_status |= TIOCPKT_NOSTOP;
}
if (extproc)
tty->ctrl_status |= TIOCPKT_IOCTL;
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
wake_up_interruptible(&tty->link->read_wait);
}

View File

@ -440,6 +440,8 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
*
* A helper opening method. Also a convenient debugging and check
* point.
*
* Locking: always called with BTM already held.
*/
static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
@ -447,10 +449,9 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags));
if (ld->ops->open) {
int ret;
/* BKL here locks verus a hangup event */
lock_kernel();
/* BTM here locks versus a hangup event */
WARN_ON(!tty_locked());
ret = ld->ops->open(tty);
unlock_kernel();
return ret;
}
return 0;
@ -553,7 +554,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
if (IS_ERR(new_ldisc))
return PTR_ERR(new_ldisc);
lock_kernel();
tty_lock();
/*
* We need to look at the tty locking here for pty/tty pairs
* when both sides try to change in parallel.
@ -567,12 +568,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
*/
if (tty->ldisc->ops->num == ldisc) {
unlock_kernel();
tty_unlock();
tty_ldisc_put(new_ldisc);
return 0;
}
unlock_kernel();
tty_unlock();
/*
* Problem: What do we do if this blocks ?
* We could deadlock here
@ -580,6 +581,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
tty_wait_until_sent(tty, 0);
tty_lock();
mutex_lock(&tty->ldisc_mutex);
/*
@ -589,13 +591,13 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) {
mutex_unlock(&tty->ldisc_mutex);
tty_unlock();
wait_event(tty_ldisc_wait,
test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0);
tty_lock();
mutex_lock(&tty->ldisc_mutex);
}
lock_kernel();
set_bit(TTY_LDISC_CHANGING, &tty->flags);
/*
@ -607,7 +609,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
o_ldisc = tty->ldisc;
unlock_kernel();
tty_unlock();
/*
* Make sure we don't change while someone holds a
* reference to the line discipline. The TTY_LDISC bit
@ -632,15 +634,15 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
flush_scheduled_work();
tty_lock();
mutex_lock(&tty->ldisc_mutex);
lock_kernel();
if (test_bit(TTY_HUPPED, &tty->flags)) {
/* We were raced by the hangup method. It will have stomped
the ldisc data and closed the ldisc down */
clear_bit(TTY_LDISC_CHANGING, &tty->flags);
mutex_unlock(&tty->ldisc_mutex);
tty_ldisc_put(new_ldisc);
unlock_kernel();
tty_unlock();
return -EIO;
}
@ -682,7 +684,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
if (o_work)
schedule_delayed_work(&o_tty->buf.work, 1);
mutex_unlock(&tty->ldisc_mutex);
unlock_kernel();
tty_unlock();
return retval;
}
@ -780,7 +782,20 @@ void tty_ldisc_hangup(struct tty_struct *tty)
* Avoid racing set_ldisc or tty_ldisc_release
*/
mutex_lock(&tty->ldisc_mutex);
tty_ldisc_halt(tty);
/*
* this is like tty_ldisc_halt, but we need to give up
* the BTM before calling cancel_delayed_work_sync,
* which may need to wait for another function taking the BTM
*/
clear_bit(TTY_LDISC, &tty->flags);
tty_unlock();
cancel_delayed_work_sync(&tty->buf.work);
mutex_unlock(&tty->ldisc_mutex);
tty_lock();
mutex_lock(&tty->ldisc_mutex);
/* At this point we have a closed ldisc and we want to
reopen it. We could defer this to the next open but
it means auditing a lot of other paths so this is
@ -851,8 +866,10 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
* race with the set_ldisc code path.
*/
tty_unlock();
tty_ldisc_halt(tty);
flush_scheduled_work();
tty_lock();
mutex_lock(&tty->ldisc_mutex);
/*

47
drivers/char/tty_mutex.c Normal file
View File

@ -0,0 +1,47 @@
/*
* drivers/char/tty_lock.c
*/
#include <linux/tty.h>
#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/semaphore.h>
#include <linux/sched.h>
/*
* The 'big tty mutex'
*
* This mutex is taken and released by tty_lock() and tty_unlock(),
* replacing the older big kernel lock.
* It can no longer be taken recursively, and does not get
* released implicitly while sleeping.
*
* Don't use in new code.
*/
static DEFINE_MUTEX(big_tty_mutex);
struct task_struct *__big_tty_mutex_owner;
EXPORT_SYMBOL_GPL(__big_tty_mutex_owner);
/*
* Getting the big tty mutex.
*/
void __lockfunc tty_lock(void)
{
struct task_struct *task = current;
WARN_ON(__big_tty_mutex_owner == task);
mutex_lock(&big_tty_mutex);
__big_tty_mutex_owner = task;
}
EXPORT_SYMBOL(tty_lock);
void __lockfunc tty_unlock(void)
{
struct task_struct *task = current;
WARN_ON(__big_tty_mutex_owner != task);
__big_tty_mutex_owner = NULL;
mutex_unlock(&big_tty_mutex);
}
EXPORT_SYMBOL(tty_unlock);

View File

@ -231,7 +231,7 @@ int tty_port_block_til_ready(struct tty_port *port,
/* block if port is in the process of being closed */
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
wait_event_interruptible(port->close_wait,
wait_event_interruptible_tty(port->close_wait,
!(port->flags & ASYNC_CLOSING));
if (port->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
@ -294,7 +294,9 @@ int tty_port_block_til_ready(struct tty_port *port,
retval = -ERESTARTSYS;
break;
}
tty_unlock();
schedule();
tty_lock();
}
finish_wait(&port->open_wait, &wait);

View File

@ -463,10 +463,10 @@ vcs_open(struct inode *inode, struct file *filp)
unsigned int currcons = iminor(inode) & 127;
int ret = 0;
lock_kernel();
tty_lock();
if(currcons && !vc_cons_allocated(currcons-1))
ret = -ENXIO;
unlock_kernel();
tty_unlock();
return ret;
}

View File

@ -105,6 +105,7 @@
#include <asm/system.h>
#include <linux/uaccess.h>
#include <linux/kdb.h>
#include <linux/ctype.h>
#define MAX_NR_CON_DRIVER 16
@ -286,8 +287,12 @@ static inline unsigned short *screenpos(struct vc_data *vc, int offset, int view
return p;
}
/* Called from the keyboard irq path.. */
static inline void scrolldelta(int lines)
{
/* FIXME */
/* scrolldelta needs some kind of consistency lock, but the BKL was
and still is not protecting versus the scheduled back end */
scrollback_delta += lines;
schedule_console_callback();
}
@ -704,7 +709,10 @@ void redraw_screen(struct vc_data *vc, int is_switch)
update_attr(vc);
clear_buffer_attributes(vc);
}
if (update && vc->vc_mode != KD_GRAPHICS)
/* Forcibly update if we're panicing */
if ((update && vc->vc_mode != KD_GRAPHICS) ||
vt_force_oops_output(vc))
do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
}
set_cursor(vc);
@ -742,6 +750,7 @@ static void visual_init(struct vc_data *vc, int num, int init)
vc->vc_hi_font_mask = 0;
vc->vc_complement_mask = 0;
vc->vc_can_do_color = 0;
vc->vc_panic_force_write = false;
vc->vc_sw->con_init(vc, init);
if (!vc->vc_complement_mask)
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
@ -774,6 +783,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
if (!vc)
return -ENOMEM;
vc_cons[currcons].d = vc;
tty_port_init(&vc->port);
INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
visual_init(vc, currcons, 1);
if (!*vc->vc_uni_pagedir_loc)
@ -963,12 +973,12 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
* Resize a virtual console as seen from the console end of things. We
* use the common vc_do_resize methods to update the structures. The
* caller must hold the console sem to protect console internals and
* vc->vc_tty
* vc->port.tty
*/
int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows)
{
return vc_do_resize(vc->vc_tty, vc, cols, rows);
return vc_do_resize(vc->port.tty, vc, cols, rows);
}
/**
@ -1796,8 +1806,8 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
vc->vc_state = ESnormal;
return;
case ESpalette:
if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
vc->vc_par[vc->vc_npar++] = (c > '9' ? (c & 0xDF) - 'A' + 10 : c - '0');
if (isxdigit(c)) {
vc->vc_par[vc->vc_npar++] = hex_to_bin(c);
if (vc->vc_npar == 7) {
int i = vc->vc_par[0] * 3, j = 1;
vc->vc_palette[i] = 16 * vc->vc_par[j++];
@ -2505,7 +2515,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
goto quit;
}
if (vc->vc_mode != KD_TEXT)
if (vc->vc_mode != KD_TEXT && !vt_force_oops_output(vc))
goto quit;
/* undraw cursor first */
@ -2611,8 +2621,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
return -EFAULT;
ret = 0;
lock_kernel();
switch (type)
{
case TIOCL_SETSEL:
@ -2687,7 +2695,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
ret = -EINVAL;
break;
}
unlock_kernel();
return ret;
}
@ -2800,12 +2807,12 @@ static int con_open(struct tty_struct *tty, struct file *filp)
struct vc_data *vc = vc_cons[currcons].d;
/* Still being freed */
if (vc->vc_tty) {
if (vc->port.tty) {
release_console_sem();
return -ERESTARTSYS;
}
tty->driver_data = vc;
vc->vc_tty = tty;
vc->port.tty = tty;
if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
tty->winsize.ws_row = vc_cons[currcons].d->vc_rows;
@ -2833,7 +2840,7 @@ static void con_shutdown(struct tty_struct *tty)
struct vc_data *vc = tty->driver_data;
BUG_ON(vc == NULL);
acquire_console_sem();
vc->vc_tty = NULL;
vc->port.tty = NULL;
release_console_sem();
tty_shutdown(tty);
}
@ -2915,6 +2922,7 @@ static int __init con_init(void)
for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT);
INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
tty_port_init(&vc->port);
visual_init(vc, currcons, 1);
vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
vc_init(vc, vc->vc_rows, vc->vc_cols,
@ -3783,7 +3791,8 @@ void do_unblank_screen(int leaving_gfx)
return;
}
vc = vc_cons[fg_console].d;
if (vc->vc_mode != KD_TEXT)
/* Try to unblank in oops case too */
if (vc->vc_mode != KD_TEXT && !vt_force_oops_output(vc))
return; /* but leave console_blanked != 0 */
if (blankinterval) {
@ -3792,7 +3801,7 @@ void do_unblank_screen(int leaving_gfx)
}
console_blanked = 0;
if (vc->vc_sw->con_blank(vc, 0, leaving_gfx))
if (vc->vc_sw->con_blank(vc, 0, leaving_gfx) || vt_force_oops_output(vc))
/* Low-level driver cannot restore -> do it ourselves */
update_screen(vc);
if (console_blank_hook)

View File

@ -133,7 +133,7 @@ static void vt_event_wait(struct vt_event_wait *vw)
list_add(&vw->list, &vt_events);
spin_unlock_irqrestore(&vt_event_lock, flags);
/* Wait for it to pass */
wait_event_interruptible(vt_event_waitqueue, vw->done);
wait_event_interruptible_tty(vt_event_waitqueue, vw->done);
/* Dequeue it */
spin_lock_irqsave(&vt_event_lock, flags);
list_del(&vw->list);
@ -509,7 +509,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
console = vc->vc_num;
lock_kernel();
tty_lock();
if (!vc_cons_allocated(console)) { /* impossible? */
ret = -ENOIOCTLCMD;
@ -1336,7 +1336,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
ret = -ENOIOCTLCMD;
}
out:
unlock_kernel();
tty_unlock();
return ret;
eperm:
ret = -EPERM;
@ -1369,7 +1369,7 @@ void vc_SAK(struct work_struct *work)
acquire_console_sem();
vc = vc_con->d;
if (vc) {
tty = vc->vc_tty;
tty = vc->port.tty;
/*
* SAK should also work in all raw modes and reset
* them properly.
@ -1503,7 +1503,7 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file,
console = vc->vc_num;
lock_kernel();
tty_lock();
if (!vc_cons_allocated(console)) { /* impossible? */
ret = -ENOIOCTLCMD;
@ -1571,11 +1571,11 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file,
goto fallback;
}
out:
unlock_kernel();
tty_unlock();
return ret;
fallback:
unlock_kernel();
tty_unlock();
return vt_ioctl(tty, file, cmd, arg);
}
@ -1761,10 +1761,13 @@ int vt_move_to_console(unsigned int vt, int alloc)
return -EIO;
}
release_console_sem();
tty_lock();
if (vt_waitactive(vt + 1)) {
pr_debug("Suspend: Can't switch VCs.");
tty_unlock();
return -EINTR;
}
tty_unlock();
return prev;
}

View File

@ -130,7 +130,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
strcpy(info->fix.id, "inteldrmfb");
info->flags = FBINFO_DEFAULT;
info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
info->fbops = &intelfb_ops;
/* setup aperture base/size for vesafb takeover */
@ -148,8 +148,6 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset;
info->fix.smem_len = size;
info->flags = FBINFO_DEFAULT;
info->screen_base = ioremap_wc(dev->agp->base + obj_priv->gtt_offset,
size);
if (!info->screen_base) {

View File

@ -250,6 +250,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
FBINFO_HWACCEL_FILLRECT |
FBINFO_HWACCEL_IMAGEBLIT;
info->flags |= FBINFO_CAN_FORCE_OUTPUT;
info->fbops = &nouveau_fbcon_ops;
info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset -
dev_priv->vm_vram_base;

View File

@ -224,7 +224,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
info->flags = FBINFO_DEFAULT;
info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
info->fbops = &radeonfb_ops;
tmp = radeon_bo_gpu_offset(rbo) - rdev->mc.vram_start;

View File

@ -216,7 +216,7 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
unsigned long flags;
unsigned int baud, quot, h_lcr;
unsigned int baud, quot, h_lcr, b;
/*
* We don't support modem control lines.
@ -234,12 +234,8 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios,
*/
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
quot = uart_get_divisor(port, baud);
if (port->state && port->state->port.tty) {
struct tty_struct *tty = port->state->port.tty;
unsigned int b = port->uartclk / (16 * quot);
tty_encode_baud_rate(tty, b, b);
}
b = port->uartclk / (16 * quot);
tty_termios_encode_baud_rate(termios, b, b);
switch (termios->c_cflag & CSIZE) {
case CS5:

View File

@ -78,10 +78,6 @@ struct m68k_serial *m68k_consinfo = 0;
#define M68K_CLOCK (16667000) /* FIXME: 16MHz is likely wrong */
#ifdef CONFIG_CONSOLE
extern wait_queue_head_t keypress_wait;
#endif
struct tty_driver *serial_driver;
/* number of characters left in xmit buffer before we ask for more */
@ -102,19 +98,13 @@ static void change_speed(struct m68k_serial *info);
* Setup for console. Argument comes from the boot command line.
*/
#if defined(CONFIG_M68EZ328ADS) || defined(CONFIG_ALMA_ANS) || defined(CONFIG_DRAGONIXVZ)
#define CONSOLE_BAUD_RATE 115200
#define DEFAULT_CBAUD B115200
#else
/* (es) */
/* note: this is messy, but it works, again, perhaps defined somewhere else?*/
#ifdef CONFIG_M68VZ328
#define CONSOLE_BAUD_RATE 19200
#define DEFAULT_CBAUD B19200
#endif
/* (/es) */
/* note: this is messy, but it works, again, perhaps defined somewhere else?*/
#ifdef CONFIG_M68VZ328
#define CONSOLE_BAUD_RATE 19200
#define DEFAULT_CBAUD B19200
#endif
#ifndef CONSOLE_BAUD_RATE
#define CONSOLE_BAUD_RATE 9600
#define DEFAULT_CBAUD B9600
@ -300,10 +290,6 @@ static void receive_chars(struct m68k_serial *info, unsigned short rx)
return;
#endif /* CONFIG_MAGIC_SYSRQ */
}
/* It is a 'keyboard interrupt' ;-) */
#ifdef CONFIG_CONSOLE
wake_up(&keypress_wait);
#endif
}
if(!tty)
@ -1243,7 +1229,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
retval = -ERESTARTSYS;
break;
}
tty_unlock();
schedule();
tty_lock();
}
current->state = TASK_RUNNING;
remove_wait_queue(&info->open_wait, &wait);

View File

@ -1705,7 +1705,6 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)
printk("jiff=%lu...", jiffies);
#endif
lock_kernel();
/* We go through the loop at least once because we can't tell
* exactly when the last character exits the shifter. There can
* be at least two characters waiting to be sent after the buffers
@ -1734,7 +1733,6 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)
bdp--;
} while (bdp->status & BD_SC_READY);
current->state = TASK_RUNNING;
unlock_kernel();
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
#endif
@ -1862,7 +1860,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
printk("block_til_ready blocking: ttys%d, count = %d\n",
info->line, state->count);
#endif
tty_unlock();
schedule();
tty_lock();
}
current->state = TASK_RUNNING;
remove_wait_queue(&info->open_wait, &wait);

View File

@ -241,7 +241,7 @@ static const struct serial8250_config uart_config[] = {
.fifo_size = 128,
.tx_loadsz = 128,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO,
.flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
},
[PORT_16654] = {
.name = "ST16654",
@ -300,6 +300,13 @@ static const struct serial8250_config uart_config[] = {
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
.flags = UART_CAP_FIFO | UART_CAP_AFE,
},
[PORT_U6_16550A] = {
.name = "U6_16550A",
.fifo_size = 64,
.tx_loadsz = 64,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_AFE,
},
};
#if defined(CONFIG_MIPS_ALCHEMY)
@ -1070,6 +1077,15 @@ static void autoconfig_16550a(struct uart_8250_port *up)
DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
}
serial_outp(up, UART_IER, iersave);
/*
* We distinguish between 16550A and U6 16550A by counting
* how many bytes are in the FIFO.
*/
if (up->port.type == PORT_16550A && size_fifo(up) == 64) {
up->port.type = PORT_U6_16550A;
up->capabilities |= UART_CAP_AFE;
}
}
/*
@ -2224,9 +2240,9 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int
return quot;
}
static void
serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
void
serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
unsigned char cval, fcr = 0;
@ -2402,16 +2418,22 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
if (tty_termios_baud_rate(termios))
tty_termios_encode_baud_rate(termios, baud, baud);
}
EXPORT_SYMBOL(serial8250_do_set_termios);
static void
serial8250_set_ldisc(struct uart_port *port)
serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
int line = port->line;
if (port->set_termios)
port->set_termios(port, termios, old);
else
serial8250_do_set_termios(port, termios, old);
}
if (line >= port->state->port.tty->driver->num)
return;
if (port->state->port.tty->ldisc->ops->num == N_PPS) {
static void
serial8250_set_ldisc(struct uart_port *port, int new)
{
if (new == N_PPS) {
port->flags |= UPF_HARDPPS_CD;
serial8250_enable_ms(port);
} else
@ -2987,6 +3009,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
port.type = p->type;
port.serial_in = p->serial_in;
port.serial_out = p->serial_out;
port.set_termios = p->set_termios;
port.dev = &dev->dev;
port.irqflags |= irqflag;
ret = serial8250_register_port(&port);
@ -3150,6 +3173,9 @@ int serial8250_register_port(struct uart_port *port)
uart->port.serial_in = port->serial_in;
if (port->serial_out)
uart->port.serial_out = port->serial_out;
/* Possibly override set_termios call */
if (port->set_termios)
uart->port.set_termios = port->set_termios;
ret = uart_add_one_port(&serial8250_reg, &uart->port);
if (ret == 0)

View File

@ -19,9 +19,11 @@
* The user can specify the device directly, e.g.,
* earlycon=uart8250,io,0x3f8,9600n8
* earlycon=uart8250,mmio,0xff5e0000,115200n8
* earlycon=uart8250,mmio32,0xff5e0000,115200n8
* or
* console=uart8250,io,0x3f8,9600n8
* console=uart8250,mmio,0xff5e0000,115200n8
* console=uart8250,mmio32,0xff5e0000,115200n8
*/
#include <linux/tty.h>
@ -48,18 +50,31 @@ static struct early_serial8250_device early_device;
static unsigned int __init serial_in(struct uart_port *port, int offset)
{
if (port->iotype == UPIO_MEM)
switch (port->iotype) {
case UPIO_MEM:
return readb(port->membase + offset);
else
case UPIO_MEM32:
return readl(port->membase + (offset << 2));
case UPIO_PORT:
return inb(port->iobase + offset);
default:
return 0;
}
}
static void __init serial_out(struct uart_port *port, int offset, int value)
{
if (port->iotype == UPIO_MEM)
switch (port->iotype) {
case UPIO_MEM:
writeb(value, port->membase + offset);
else
break;
case UPIO_MEM32:
writel(value, port->membase + (offset << 2));
break;
case UPIO_PORT:
outb(value, port->iobase + offset);
break;
}
}
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
@ -137,15 +152,21 @@ static int __init parse_options(struct early_serial8250_device *device,
char *options)
{
struct uart_port *port = &device->port;
int mmio, length;
int mmio, mmio32, length;
if (!options)
return -ENODEV;
port->uartclk = BASE_BAUD * 16;
if (!strncmp(options, "mmio,", 5)) {
port->iotype = UPIO_MEM;
port->mapbase = simple_strtoul(options + 5, &options, 0);
mmio = !strncmp(options, "mmio,", 5);
mmio32 = !strncmp(options, "mmio32,", 7);
if (mmio || mmio32) {
port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32);
port->mapbase = simple_strtoul(options + (mmio ? 5 : 7),
&options, 0);
if (mmio32)
port->regshift = 2;
#ifdef CONFIG_FIX_EARLYCON_MEM
set_fixmap_nocache(FIX_EARLYCON_MEM_BASE,
port->mapbase & PAGE_MASK);
@ -157,11 +178,10 @@ static int __init parse_options(struct early_serial8250_device *device,
if (!port->membase) {
printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n",
__func__,
(unsigned long long)port->mapbase);
(unsigned long long) port->mapbase);
return -ENOMEM;
}
#endif
mmio = 1;
} else if (!strncmp(options, "io,", 3)) {
port->iotype = UPIO_PORT;
port->iobase = simple_strtoul(options + 3, &options, 0);
@ -181,11 +201,18 @@ static int __init parse_options(struct early_serial8250_device *device,
device->baud);
}
printk(KERN_INFO "Early serial console at %s 0x%llx (options '%s')\n",
mmio ? "MMIO" : "I/O port",
mmio ? (unsigned long long) port->mapbase
: (unsigned long long) port->iobase,
device->options);
if (mmio || mmio32)
printk(KERN_INFO
"Early serial console at MMIO%s 0x%llu (options '%s')\n",
mmio32 ? "32" : "",
(unsigned long long)port->mapbase,
device->options);
else
printk(KERN_INFO
"Early serial console at I/O port 0x%lu (options '%s')\n",
port->iobase,
device->options);
return 0;
}

View File

@ -994,6 +994,7 @@ static int skip_tx_en_setup(struct serial_private *priv,
#define PCI_DEVICE_ID_TITAN_800E 0xA014
#define PCI_DEVICE_ID_TITAN_200EI 0xA016
#define PCI_DEVICE_ID_TITAN_200EISI 0xA017
#define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
@ -1542,6 +1543,8 @@ enum pci_board_num_t {
pbn_b2_4_921600,
pbn_b2_8_921600,
pbn_b2_8_1152000,
pbn_b2_bt_1_115200,
pbn_b2_bt_2_115200,
pbn_b2_bt_4_115200,
@ -1960,6 +1963,13 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.uart_offset = 8,
},
[pbn_b2_8_1152000] = {
.flags = FL_BASE2,
.num_ports = 8,
.base_baud = 1152000,
.uart_offset = 8,
},
[pbn_b2_bt_1_115200] = {
.flags = FL_BASE2|FL_BASE_BARS,
.num_ports = 1,
@ -2875,6 +2885,9 @@ static struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_bt_2_921600 },
{ PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI958,
PCI_ANY_ID , PCI_ANY_ID, 0, 0,
pbn_b2_8_1152000 },
/*
* Oxford Semiconductor Inc. Tornado PCI express device range.

View File

@ -542,6 +542,7 @@ config SERIAL_S5PV210
help
Serial port support for Samsung's S5P Family of SoC's
config SERIAL_MAX3100
tristate "MAX3100 support"
depends on SPI
@ -549,6 +550,22 @@ config SERIAL_MAX3100
help
MAX3100 chip support
config SERIAL_MAX3107
tristate "MAX3107 support"
depends on SPI
select SERIAL_CORE
help
MAX3107 chip support
config SERIAL_MAX3107_AAVA
tristate "MAX3107 AAVA platform support"
depends on X86_MRST && SERIAL_MAX3107 && GPIOLIB
select SERIAL_CORE
help
Support for the MAX3107 chip configuration found on the AAVA
platform. Includes the extra initialisation and GPIO support
neded for this device.
config SERIAL_DZ
bool "DECstation DZ serial driver"
depends on MACH_DECSTATION && 32BIT
@ -690,6 +707,33 @@ config SERIAL_SA1100_CONSOLE
your boot loader (lilo or loadlin) about how to pass options to the
kernel at boot time.)
config SERIAL_MRST_MAX3110
tristate "SPI UART driver for Max3110"
depends on SPI_DW_PCI
select SERIAL_CORE
select SERIAL_CORE_CONSOLE
help
This is the UART protocol driver for the MAX3110 device on
the Intel Moorestown platform. On other systems use the max3100
driver.
config MRST_MAX3110_IRQ
boolean "Enable GPIO IRQ for Max3110 over Moorestown"
default n
depends on SERIAL_MRST_MAX3110 && GPIO_LANGWELL
help
This has to be enabled after Moorestown GPIO driver is loaded
config SERIAL_MFD_HSU
tristate "Medfield High Speed UART support"
depends on PCI
select SERIAL_CORE
config SERIAL_MFD_HSU_CONSOLE
boolean "Medfile HSU serial console support"
depends on SERIAL_MFD_HSU=y
select SERIAL_CORE_CONSOLE
config SERIAL_BFIN
tristate "Blackfin serial port support"
depends on BLACKFIN

View File

@ -46,6 +46,8 @@ obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o
obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o
obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
obj-$(CONFIG_SERIAL_MAX3107) += max3107.o
obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o
obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
obj-$(CONFIG_SERIAL_MUX) += mux.o
obj-$(CONFIG_SERIAL_68328) += 68328serial.o
@ -84,3 +86,5 @@ obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o
obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o
obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o
obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o

View File

@ -394,7 +394,7 @@ int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp)
static void altera_uart_console_putc(struct uart_port *port, const char c)
{
while (!(readl(port->membase + ALTERA_UART_STATUS_REG) &
ALTERA_UART_STATUS_TRDY_MSK))
ALTERA_UART_STATUS_TRDY_MSK))
cpu_relax();
writel(c, port->membase + ALTERA_UART_TXDATA_REG);

View File

@ -217,7 +217,8 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
if (rs485conf->flags & SER_RS485_ENABLED) {
dev_dbg(port->dev, "Setting UART to RS485\n");
atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
UART_PUT_TTGR(port, rs485conf->delay_rts_before_send);
if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
mode |= ATMEL_US_USMODE_RS485;
} else {
dev_dbg(port->dev, "Setting UART to RS232\n");
@ -292,7 +293,9 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
dev_dbg(port->dev, "Setting UART to RS485\n");
UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send);
if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
UART_PUT_TTGR(port,
atmel_port->rs485.delay_rts_after_send);
mode |= ATMEL_US_USMODE_RS485;
} else {
dev_dbg(port->dev, "Setting UART to RS232\n");
@ -1211,7 +1214,9 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
dev_dbg(port->dev, "Setting UART to RS485\n");
UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send);
if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
UART_PUT_TTGR(port,
atmel_port->rs485.delay_rts_after_send);
mode |= ATMEL_US_USMODE_RS485;
} else {
dev_dbg(port->dev, "Setting UART to RS232\n");

View File

@ -957,15 +957,12 @@ bfin_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
* Enable the IrDA function if tty->ldisc.num is N_IRDA.
* In other cases, disable IrDA function.
*/
static void bfin_serial_set_ldisc(struct uart_port *port)
static void bfin_serial_set_ldisc(struct uart_port *port, int ld)
{
int line = port->line;
unsigned short val;
if (line >= port->state->port.tty->driver->num)
return;
switch (port->state->port.tty->termios->c_line) {
switch (ld) {
case N_IRDA:
val = UART_GET_GCTL(&bfin_serial_ports[line]);
val |= (IREN | RPOLC);

View File

@ -3935,7 +3935,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
* Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO
* R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k)
*/
lock_kernel();
orig_jiffies = jiffies;
while (info->xmit.head != info->xmit.tail || /* More in send queue */
(*info->ostatusadr & 0x007f) || /* more in FIFO */
@ -3952,7 +3951,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
curr_time_usec - info->last_tx_active_usec;
}
set_current_state(TASK_RUNNING);
unlock_kernel();
}
/*
@ -3992,7 +3990,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
wait_event_interruptible(info->close_wait,
wait_event_interruptible_tty(info->close_wait,
!(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
if (info->flags & ASYNC_HUP_NOTIFY)
@ -4068,7 +4066,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
printk("block_til_ready blocking: ttyS%d, count = %d\n",
info->line, info->count);
#endif
tty_unlock();
schedule();
tty_lock();
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&info->open_wait, &wait);
@ -4150,7 +4150,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
wait_event_interruptible(info->close_wait,
wait_event_interruptible_tty(info->close_wait,
!(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
return ((info->flags & ASYNC_HUP_NOTIFY) ?
@ -4533,8 +4533,8 @@ static int __init rs_init(void)
INIT_WORK(&info->work, do_softint);
if (info->enabled) {
printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n",
serial_driver->name, info->line, (unsigned int)info->ioport);
printk(KERN_INFO "%s%d at %p is a builtin UART with DMA\n",
serial_driver->name, info->line, info->ioport);
}
}
#ifdef CONFIG_ETRAX_FAST_TIMER

View File

@ -909,13 +909,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
rational_best_approximation(16 * div * baud, sport->port.uartclk,
1 << 16, 1 << 16, &num, &denom);
if (port->state && port->state->port.tty) {
tdiv64 = sport->port.uartclk;
tdiv64 *= num;
do_div(tdiv64, denom * 16 * div);
tty_encode_baud_rate(sport->port.state->port.tty,
tdiv64 = sport->port.uartclk;
tdiv64 *= num;
do_div(tdiv64, denom * 16 * div);
tty_termios_encode_baud_rate(termios,
(speed_t)tdiv64, (speed_t)tdiv64);
}
num -= 1;
denom -= 1;

View File

@ -954,12 +954,13 @@ ioc3_change_speed(struct uart_port *the_port,
struct ktermios *new_termios, struct ktermios *old_termios)
{
struct ioc3_port *port = get_ioc3_port(the_port);
unsigned int cflag;
unsigned int cflag, iflag;
int baud;
int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8;
struct uart_state *state = the_port->state;
cflag = new_termios->c_cflag;
iflag = new_termios->c_iflag;
switch (cflag & CSIZE) {
case CS5:
@ -1000,12 +1001,12 @@ ioc3_change_speed(struct uart_port *the_port,
state->port.tty->low_latency = 1;
if (I_IGNPAR(state->port.tty))
if (iflag & IGNPAR)
the_port->ignore_status_mask &= ~(N_PARITY_ERROR
| N_FRAMING_ERROR);
if (I_IGNBRK(state->port.tty)) {
if (iflag & IGNBRK) {
the_port->ignore_status_mask &= ~N_BREAK;
if (I_IGNPAR(state->port.tty))
if (iflag & IGNPAR)
the_port->ignore_status_mask &= ~N_OVERRUN_ERROR;
}
if (!(cflag & CREAD)) {

View File

@ -1685,11 +1685,12 @@ ioc4_change_speed(struct uart_port *the_port,
{
struct ioc4_port *port = get_ioc4_port(the_port, 0);
int baud, bits;
unsigned cflag;
unsigned cflag, iflag;
int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8;
struct uart_state *state = the_port->state;
cflag = new_termios->c_cflag;
iflag = new_termios->c_iflag;
switch (cflag & CSIZE) {
case CS5:
@ -1741,12 +1742,12 @@ ioc4_change_speed(struct uart_port *the_port,
state->port.tty->low_latency = 1;
if (I_IGNPAR(state->port.tty))
if (iflag & IGNPAR)
the_port->ignore_status_mask &= ~(N_PARITY_ERROR
| N_FRAMING_ERROR);
if (I_IGNBRK(state->port.tty)) {
if (iflag & IGNBRK) {
the_port->ignore_status_mask &= ~N_BREAK;
if (I_IGNPAR(state->port.tty))
if (iflag & IGNPAR)
the_port->ignore_status_mask &= ~N_OVERRUN_ERROR;
}
if (!(cflag & CREAD)) {

View File

@ -430,17 +430,14 @@ max3100_set_termios(struct uart_port *port, struct ktermios *termios,
int baud = 0;
unsigned cflag;
u32 param_new, param_mask, parity = 0;
struct tty_struct *tty = s->port.state->port.tty;
dev_dbg(&s->spi->dev, "%s\n", __func__);
if (!tty)
return;
cflag = termios->c_cflag;
param_new = 0;
param_mask = 0;
baud = tty_get_baud_rate(tty);
baud = tty_termios_baud_rate(termios);
param_new = s->conf & MAX3100_BAUD;
switch (baud) {
case 300:
@ -485,7 +482,7 @@ max3100_set_termios(struct uart_port *port, struct ktermios *termios,
default:
baud = s->baud;
}
tty_encode_baud_rate(tty, baud, baud);
tty_termios_encode_baud_rate(termios, baud, baud);
s->baud = baud;
param_mask |= MAX3100_BAUD;

View File

@ -0,0 +1,344 @@
/*
* max3107.c - spi uart protocol driver for Maxim 3107
* Based on max3100.c
* by Christian Pellegrin <chripell@evolware.org>
* and max3110.c
* by Feng Tang <feng.tang@intel.com>
*
* Copyright (C) Aavamobile 2009
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*/
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/spi/spi.h>
#include <linux/freezer.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/sfi.h>
#include <asm/mrst.h>
#include "max3107.h"
/* GPIO direction to input function */
static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
{
struct max3107_port *s = container_of(chip, struct max3107_port, chip);
u16 buf[1]; /* Buffer for SPI transfer */
if (offset >= MAX3107_GPIO_COUNT) {
dev_err(&s->spi->dev, "Invalid GPIO\n");
return -EINVAL;
}
/* Read current GPIO configuration register */
buf[0] = MAX3107_GPIOCFG_REG;
/* Perform SPI transfer */
if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n");
return -EIO;
}
buf[0] &= MAX3107_SPI_RX_DATA_MASK;
/* Set GPIO to input */
buf[0] &= ~(0x0001 << offset);
/* Write new GPIO configuration register value */
buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
/* Perform SPI transfer */
if (max3107_rw(s, (u8 *)buf, NULL, 2)) {
dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n");
return -EIO;
}
return 0;
}
/* GPIO direction to output function */
static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset,
int value)
{
struct max3107_port *s = container_of(chip, struct max3107_port, chip);
u16 buf[2]; /* Buffer for SPI transfers */
if (offset >= MAX3107_GPIO_COUNT) {
dev_err(&s->spi->dev, "Invalid GPIO\n");
return -EINVAL;
}
/* Read current GPIO configuration and data registers */
buf[0] = MAX3107_GPIOCFG_REG;
buf[1] = MAX3107_GPIODATA_REG;
/* Perform SPI transfer */
if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
dev_err(&s->spi->dev, "SPI transfer gpio failed\n");
return -EIO;
}
buf[0] &= MAX3107_SPI_RX_DATA_MASK;
buf[1] &= MAX3107_SPI_RX_DATA_MASK;
/* Set GPIO to output */
buf[0] |= (0x0001 << offset);
/* Set value */
if (value)
buf[1] |= (0x0001 << offset);
else
buf[1] &= ~(0x0001 << offset);
/* Write new GPIO configuration and data register values */
buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
/* Perform SPI transfer */
if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
dev_err(&s->spi->dev,
"SPI transfer for GPIO conf data w failed\n");
return -EIO;
}
return 0;
}
/* GPIO value query function */
static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct max3107_port *s = container_of(chip, struct max3107_port, chip);
u16 buf[1]; /* Buffer for SPI transfer */
if (offset >= MAX3107_GPIO_COUNT) {
dev_err(&s->spi->dev, "Invalid GPIO\n");
return -EINVAL;
}
/* Read current GPIO data register */
buf[0] = MAX3107_GPIODATA_REG;
/* Perform SPI transfer */
if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n");
return -EIO;
}
buf[0] &= MAX3107_SPI_RX_DATA_MASK;
/* Return value */
return buf[0] & (0x0001 << offset);
}
/* GPIO value set function */
static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct max3107_port *s = container_of(chip, struct max3107_port, chip);
u16 buf[2]; /* Buffer for SPI transfers */
if (offset >= MAX3107_GPIO_COUNT) {
dev_err(&s->spi->dev, "Invalid GPIO\n");
return;
}
/* Read current GPIO configuration registers*/
buf[0] = MAX3107_GPIODATA_REG;
buf[1] = MAX3107_GPIOCFG_REG;
/* Perform SPI transfer */
if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
dev_err(&s->spi->dev,
"SPI transfer for GPIO data and config read failed\n");
return;
}
buf[0] &= MAX3107_SPI_RX_DATA_MASK;
buf[1] &= MAX3107_SPI_RX_DATA_MASK;
if (!(buf[1] & (0x0001 << offset))) {
/* Configured as input, can't set value */
dev_warn(&s->spi->dev,
"Trying to set value for input GPIO\n");
return;
}
/* Set value */
if (value)
buf[0] |= (0x0001 << offset);
else
buf[0] &= ~(0x0001 << offset);
/* Write new GPIO data register value */
buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
/* Perform SPI transfer */
if (max3107_rw(s, (u8 *)buf, NULL, 2))
dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n");
}
/* GPIO chip data */
static struct gpio_chip max3107_gpio_chip = {
.owner = THIS_MODULE,
.direction_input = max3107_gpio_direction_in,
.direction_output = max3107_gpio_direction_out,
.get = max3107_gpio_get,
.set = max3107_gpio_set,
.can_sleep = 1,
.base = MAX3107_GPIO_BASE,
.ngpio = MAX3107_GPIO_COUNT,
};
/**
* max3107_aava_reset - reset on AAVA systems
* @spi: The SPI device we are probing
*
* Reset the device ready for probing.
*/
static int max3107_aava_reset(struct spi_device *spi)
{
/* Reset the chip */
if (gpio_request(MAX3107_RESET_GPIO, "max3107")) {
pr_err("Requesting RESET GPIO failed\n");
return -EIO;
}
if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) {
pr_err("Setting RESET GPIO to 0 failed\n");
gpio_free(MAX3107_RESET_GPIO);
return -EIO;
}
msleep(MAX3107_RESET_DELAY);
if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) {
pr_err("Setting RESET GPIO to 1 failed\n");
gpio_free(MAX3107_RESET_GPIO);
return -EIO;
}
gpio_free(MAX3107_RESET_GPIO);
msleep(MAX3107_WAKEUP_DELAY);
return 0;
}
static int max3107_aava_configure(struct max3107_port *s)
{
int retval;
/* Initialize GPIO chip data */
s->chip = max3107_gpio_chip;
s->chip.label = s->spi->modalias;
s->chip.dev = &s->spi->dev;
/* Add GPIO chip */
retval = gpiochip_add(&s->chip);
if (retval) {
dev_err(&s->spi->dev, "Adding GPIO chip failed\n");
return retval;
}
/* Temporary fix for EV2 boot problems, set modem reset to 0 */
max3107_gpio_direction_out(&s->chip, 3, 0);
return 0;
}
#if 0
/* This will get enabled once we have the board stuff merged for this
specific case */
static const struct baud_table brg13_ext[] = {
{ 300, MAX3107_BRG13_B300 },
{ 600, MAX3107_BRG13_B600 },
{ 1200, MAX3107_BRG13_B1200 },
{ 2400, MAX3107_BRG13_B2400 },
{ 4800, MAX3107_BRG13_B4800 },
{ 9600, MAX3107_BRG13_B9600 },
{ 19200, MAX3107_BRG13_B19200 },
{ 57600, MAX3107_BRG13_B57600 },
{ 115200, MAX3107_BRG13_B115200 },
{ 230400, MAX3107_BRG13_B230400 },
{ 460800, MAX3107_BRG13_B460800 },
{ 921600, MAX3107_BRG13_B921600 },
{ 0, 0 }
};
static void max3107_aava_init(struct max3107_port *s)
{
/*override for AAVA SC specific*/
if (mrst_platform_id() == MRST_PLATFORM_AAVA_SC) {
if (get_koski_build_id() <= KOSKI_EV2)
if (s->ext_clk) {
s->brg_cfg = MAX3107_BRG13_B9600;
s->baud_tbl = (struct baud_table *)brg13_ext;
}
}
}
#endif
static int __devexit max3107_aava_remove(struct spi_device *spi)
{
struct max3107_port *s = dev_get_drvdata(&spi->dev);
/* Remove GPIO chip */
if (gpiochip_remove(&s->chip))
dev_warn(&spi->dev, "Removing GPIO chip failed\n");
/* Then do the default remove */
return max3107_remove(spi);
}
/* Platform data */
static struct max3107_plat aava_plat_data = {
.loopback = 0,
.ext_clk = 1,
/* .init = max3107_aava_init, */
.configure = max3107_aava_configure,
.hw_suspend = max3107_hw_susp,
.polled_mode = 0,
.poll_time = 0,
};
static int __devinit max3107_probe_aava(struct spi_device *spi)
{
int err = max3107_aava_reset(spi);
if (err < 0)
return err;
return max3107_probe(spi, &aava_plat_data);
}
/* Spi driver data */
static struct spi_driver max3107_driver = {
.driver = {
.name = "aava-max3107",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = max3107_probe_aava,
.remove = __devexit_p(max3107_aava_remove),
.suspend = max3107_suspend,
.resume = max3107_resume,
};
/* Driver init function */
static int __init max3107_init(void)
{
return spi_register_driver(&max3107_driver);
}
/* Driver exit function */
static void __exit max3107_exit(void)
{
spi_unregister_driver(&max3107_driver);
}
module_init(max3107_init);
module_exit(max3107_exit);
MODULE_DESCRIPTION("MAX3107 driver");
MODULE_AUTHOR("Aavamobile");
MODULE_ALIAS("aava-max3107-spi");
MODULE_LICENSE("GPL v2");

1197
drivers/serial/max3107.c Normal file

File diff suppressed because it is too large Load Diff

441
drivers/serial/max3107.h Normal file
View File

@ -0,0 +1,441 @@
/*
* max3107.h - spi uart protocol driver header for Maxim 3107
*
* Copyright (C) Aavamobile 2009
* Based on serial_max3100.h by Christian Pellegrin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef _MAX3107_H
#define _MAX3107_H
/* Serial error status definitions */
#define MAX3107_PARITY_ERROR 1
#define MAX3107_FRAME_ERROR 2
#define MAX3107_OVERRUN_ERROR 4
#define MAX3107_ALL_ERRORS (MAX3107_PARITY_ERROR | \
MAX3107_FRAME_ERROR | \
MAX3107_OVERRUN_ERROR)
/* GPIO definitions */
#define MAX3107_GPIO_BASE 88
#define MAX3107_GPIO_COUNT 4
/* GPIO connected to chip's reset pin */
#define MAX3107_RESET_GPIO 87
/* Chip reset delay */
#define MAX3107_RESET_DELAY 10
/* Chip wakeup delay */
#define MAX3107_WAKEUP_DELAY 50
/* Sleep mode definitions */
#define MAX3107_DISABLE_FORCED_SLEEP 0
#define MAX3107_ENABLE_FORCED_SLEEP 1
#define MAX3107_DISABLE_AUTOSLEEP 2
#define MAX3107_ENABLE_AUTOSLEEP 3
/* Definitions for register access with SPI transfers
*
* SPI transfer format:
*
* Master to slave bits xzzzzzzzyyyyyyyy
* Slave to master bits aaaaaaaabbbbbbbb
*
* where:
* x = 0 for reads, 1 for writes
* z = register address
* y = new register value if write, 0 if read
* a = unspecified
* b = register value if read, unspecified if write
*/
/* SPI speed */
#define MAX3107_SPI_SPEED (3125000 * 2)
/* Write bit */
#define MAX3107_WRITE_BIT (1 << 15)
/* SPI TX data mask */
#define MAX3107_SPI_RX_DATA_MASK (0x00ff)
/* SPI RX data mask */
#define MAX3107_SPI_TX_DATA_MASK (0x00ff)
/* Register access masks */
#define MAX3107_RHR_REG (0x0000) /* RX FIFO */
#define MAX3107_THR_REG (0x0000) /* TX FIFO */
#define MAX3107_IRQEN_REG (0x0100) /* IRQ enable */
#define MAX3107_IRQSTS_REG (0x0200) /* IRQ status */
#define MAX3107_LSR_IRQEN_REG (0x0300) /* LSR IRQ enable */
#define MAX3107_LSR_IRQSTS_REG (0x0400) /* LSR IRQ status */
#define MAX3107_SPCHR_IRQEN_REG (0x0500) /* Special char IRQ enable */
#define MAX3107_SPCHR_IRQSTS_REG (0x0600) /* Special char IRQ status */
#define MAX3107_STS_IRQEN_REG (0x0700) /* Status IRQ enable */
#define MAX3107_STS_IRQSTS_REG (0x0800) /* Status IRQ status */
#define MAX3107_MODE1_REG (0x0900) /* MODE1 */
#define MAX3107_MODE2_REG (0x0a00) /* MODE2 */
#define MAX3107_LCR_REG (0x0b00) /* LCR */
#define MAX3107_RXTO_REG (0x0c00) /* RX timeout */
#define MAX3107_HDPIXDELAY_REG (0x0d00) /* Auto transceiver delays */
#define MAX3107_IRDA_REG (0x0e00) /* IRDA settings */
#define MAX3107_FLOWLVL_REG (0x0f00) /* Flow control levels */
#define MAX3107_FIFOTRIGLVL_REG (0x1000) /* FIFO IRQ trigger levels */
#define MAX3107_TXFIFOLVL_REG (0x1100) /* TX FIFO level */
#define MAX3107_RXFIFOLVL_REG (0x1200) /* RX FIFO level */
#define MAX3107_FLOWCTRL_REG (0x1300) /* Flow control */
#define MAX3107_XON1_REG (0x1400) /* XON1 character */
#define MAX3107_XON2_REG (0x1500) /* XON2 character */
#define MAX3107_XOFF1_REG (0x1600) /* XOFF1 character */
#define MAX3107_XOFF2_REG (0x1700) /* XOFF2 character */
#define MAX3107_GPIOCFG_REG (0x1800) /* GPIO config */
#define MAX3107_GPIODATA_REG (0x1900) /* GPIO data */
#define MAX3107_PLLCFG_REG (0x1a00) /* PLL config */
#define MAX3107_BRGCFG_REG (0x1b00) /* Baud rate generator conf */
#define MAX3107_BRGDIVLSB_REG (0x1c00) /* Baud rate divisor LSB */
#define MAX3107_BRGDIVMSB_REG (0x1d00) /* Baud rate divisor MSB */
#define MAX3107_CLKSRC_REG (0x1e00) /* Clock source */
#define MAX3107_REVID_REG (0x1f00) /* Revision identification */
/* IRQ register bits */
#define MAX3107_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */
#define MAX3107_IRQ_SPCHR_BIT (1 << 1) /* Special char interrupt */
#define MAX3107_IRQ_STS_BIT (1 << 2) /* Status interrupt */
#define MAX3107_IRQ_RXFIFO_BIT (1 << 3) /* RX FIFO interrupt */
#define MAX3107_IRQ_TXFIFO_BIT (1 << 4) /* TX FIFO interrupt */
#define MAX3107_IRQ_TXEMPTY_BIT (1 << 5) /* TX FIFO empty interrupt */
#define MAX3107_IRQ_RXEMPTY_BIT (1 << 6) /* RX FIFO empty interrupt */
#define MAX3107_IRQ_CTS_BIT (1 << 7) /* CTS interrupt */
/* LSR register bits */
#define MAX3107_LSR_RXTO_BIT (1 << 0) /* RX timeout */
#define MAX3107_LSR_RXOVR_BIT (1 << 1) /* RX overrun */
#define MAX3107_LSR_RXPAR_BIT (1 << 2) /* RX parity error */
#define MAX3107_LSR_FRERR_BIT (1 << 3) /* Frame error */
#define MAX3107_LSR_RXBRK_BIT (1 << 4) /* RX break */
#define MAX3107_LSR_RXNOISE_BIT (1 << 5) /* RX noise */
#define MAX3107_LSR_UNDEF6_BIT (1 << 6) /* Undefined/not used */
#define MAX3107_LSR_CTS_BIT (1 << 7) /* CTS pin state */
/* Special character register bits */
#define MAX3107_SPCHR_XON1_BIT (1 << 0) /* XON1 character */
#define MAX3107_SPCHR_XON2_BIT (1 << 1) /* XON2 character */
#define MAX3107_SPCHR_XOFF1_BIT (1 << 2) /* XOFF1 character */
#define MAX3107_SPCHR_XOFF2_BIT (1 << 3) /* XOFF2 character */
#define MAX3107_SPCHR_BREAK_BIT (1 << 4) /* RX break */
#define MAX3107_SPCHR_MULTIDROP_BIT (1 << 5) /* 9-bit multidrop addr char */
#define MAX3107_SPCHR_UNDEF6_BIT (1 << 6) /* Undefined/not used */
#define MAX3107_SPCHR_UNDEF7_BIT (1 << 7) /* Undefined/not used */
/* Status register bits */
#define MAX3107_STS_GPIO0_BIT (1 << 0) /* GPIO 0 interrupt */
#define MAX3107_STS_GPIO1_BIT (1 << 1) /* GPIO 1 interrupt */
#define MAX3107_STS_GPIO2_BIT (1 << 2) /* GPIO 2 interrupt */
#define MAX3107_STS_GPIO3_BIT (1 << 3) /* GPIO 3 interrupt */
#define MAX3107_STS_UNDEF4_BIT (1 << 4) /* Undefined/not used */
#define MAX3107_STS_CLKREADY_BIT (1 << 5) /* Clock ready */
#define MAX3107_STS_SLEEP_BIT (1 << 6) /* Sleep interrupt */
#define MAX3107_STS_UNDEF7_BIT (1 << 7) /* Undefined/not used */
/* MODE1 register bits */
#define MAX3107_MODE1_RXDIS_BIT (1 << 0) /* RX disable */
#define MAX3107_MODE1_TXDIS_BIT (1 << 1) /* TX disable */
#define MAX3107_MODE1_TXHIZ_BIT (1 << 2) /* TX pin three-state */
#define MAX3107_MODE1_RTSHIZ_BIT (1 << 3) /* RTS pin three-state */
#define MAX3107_MODE1_TRNSCVCTRL_BIT (1 << 4) /* Transceiver ctrl enable */
#define MAX3107_MODE1_FORCESLEEP_BIT (1 << 5) /* Force sleep mode */
#define MAX3107_MODE1_AUTOSLEEP_BIT (1 << 6) /* Auto sleep enable */
#define MAX3107_MODE1_IRQSEL_BIT (1 << 7) /* IRQ pin enable */
/* MODE2 register bits */
#define MAX3107_MODE2_RST_BIT (1 << 0) /* Chip reset */
#define MAX3107_MODE2_FIFORST_BIT (1 << 1) /* FIFO reset */
#define MAX3107_MODE2_RXTRIGINV_BIT (1 << 2) /* RX FIFO INT invert */
#define MAX3107_MODE2_RXEMPTINV_BIT (1 << 3) /* RX FIFO empty INT invert */
#define MAX3107_MODE2_SPCHR_BIT (1 << 4) /* Special chr detect enable */
#define MAX3107_MODE2_LOOPBACK_BIT (1 << 5) /* Internal loopback enable */
#define MAX3107_MODE2_MULTIDROP_BIT (1 << 6) /* 9-bit multidrop enable */
#define MAX3107_MODE2_ECHOSUPR_BIT (1 << 7) /* ECHO suppression enable */
/* LCR register bits */
#define MAX3107_LCR_LENGTH0_BIT (1 << 0) /* Word length bit 0 */
#define MAX3107_LCR_LENGTH1_BIT (1 << 1) /* Word length bit 1
*
* Word length bits table:
* 00 -> 5 bit words
* 01 -> 6 bit words
* 10 -> 7 bit words
* 11 -> 8 bit words
*/
#define MAX3107_LCR_STOPLEN_BIT (1 << 2) /* STOP length bit
*
* STOP length bit table:
* 0 -> 1 stop bit
* 1 -> 1-1.5 stop bits if
* word length is 5,
* 2 stop bits otherwise
*/
#define MAX3107_LCR_PARITY_BIT (1 << 3) /* Parity bit enable */
#define MAX3107_LCR_EVENPARITY_BIT (1 << 4) /* Even parity bit enable */
#define MAX3107_LCR_FORCEPARITY_BIT (1 << 5) /* 9-bit multidrop parity */
#define MAX3107_LCR_TXBREAK_BIT (1 << 6) /* TX break enable */
#define MAX3107_LCR_RTS_BIT (1 << 7) /* RTS pin control */
#define MAX3107_LCR_WORD_LEN_5 (0x0000)
#define MAX3107_LCR_WORD_LEN_6 (0x0001)
#define MAX3107_LCR_WORD_LEN_7 (0x0002)
#define MAX3107_LCR_WORD_LEN_8 (0x0003)
/* IRDA register bits */
#define MAX3107_IRDA_IRDAEN_BIT (1 << 0) /* IRDA mode enable */
#define MAX3107_IRDA_SIR_BIT (1 << 1) /* SIR mode enable */
#define MAX3107_IRDA_SHORTIR_BIT (1 << 2) /* Short SIR mode enable */
#define MAX3107_IRDA_MIR_BIT (1 << 3) /* MIR mode enable */
#define MAX3107_IRDA_RXINV_BIT (1 << 4) /* RX logic inversion enable */
#define MAX3107_IRDA_TXINV_BIT (1 << 5) /* TX logic inversion enable */
#define MAX3107_IRDA_UNDEF6_BIT (1 << 6) /* Undefined/not used */
#define MAX3107_IRDA_UNDEF7_BIT (1 << 7) /* Undefined/not used */
/* Flow control trigger level register masks */
#define MAX3107_FLOWLVL_HALT_MASK (0x000f) /* Flow control halt level */
#define MAX3107_FLOWLVL_RES_MASK (0x00f0) /* Flow control resume level */
#define MAX3107_FLOWLVL_HALT(words) ((words/8) & 0x000f)
#define MAX3107_FLOWLVL_RES(words) (((words/8) & 0x000f) << 4)
/* FIFO interrupt trigger level register masks */
#define MAX3107_FIFOTRIGLVL_TX_MASK (0x000f) /* TX FIFO trigger level */
#define MAX3107_FIFOTRIGLVL_RX_MASK (0x00f0) /* RX FIFO trigger level */
#define MAX3107_FIFOTRIGLVL_TX(words) ((words/8) & 0x000f)
#define MAX3107_FIFOTRIGLVL_RX(words) (((words/8) & 0x000f) << 4)
/* Flow control register bits */
#define MAX3107_FLOWCTRL_AUTORTS_BIT (1 << 0) /* Auto RTS flow ctrl enable */
#define MAX3107_FLOWCTRL_AUTOCTS_BIT (1 << 1) /* Auto CTS flow ctrl enable */
#define MAX3107_FLOWCTRL_GPIADDR_BIT (1 << 2) /* Enables that GPIO inputs
* are used in conjunction with
* XOFF2 for definition of
* special character */
#define MAX3107_FLOWCTRL_SWFLOWEN_BIT (1 << 3) /* Auto SW flow ctrl enable */
#define MAX3107_FLOWCTRL_SWFLOW0_BIT (1 << 4) /* SWFLOW bit 0 */
#define MAX3107_FLOWCTRL_SWFLOW1_BIT (1 << 5) /* SWFLOW bit 1
*
* SWFLOW bits 1 & 0 table:
* 00 -> no transmitter flow
* control
* 01 -> receiver compares
* XON2 and XOFF2
* and controls
* transmitter
* 10 -> receiver compares
* XON1 and XOFF1
* and controls
* transmitter
* 11 -> receiver compares
* XON1, XON2, XOFF1 and
* XOFF2 and controls
* transmitter
*/
#define MAX3107_FLOWCTRL_SWFLOW2_BIT (1 << 6) /* SWFLOW bit 2 */
#define MAX3107_FLOWCTRL_SWFLOW3_BIT (1 << 7) /* SWFLOW bit 3
*
* SWFLOW bits 3 & 2 table:
* 00 -> no received flow
* control
* 01 -> transmitter generates
* XON2 and XOFF2
* 10 -> transmitter generates
* XON1 and XOFF1
* 11 -> transmitter generates
* XON1, XON2, XOFF1 and
* XOFF2
*/
/* GPIO configuration register bits */
#define MAX3107_GPIOCFG_GP0OUT_BIT (1 << 0) /* GPIO 0 output enable */
#define MAX3107_GPIOCFG_GP1OUT_BIT (1 << 1) /* GPIO 1 output enable */
#define MAX3107_GPIOCFG_GP2OUT_BIT (1 << 2) /* GPIO 2 output enable */
#define MAX3107_GPIOCFG_GP3OUT_BIT (1 << 3) /* GPIO 3 output enable */
#define MAX3107_GPIOCFG_GP0OD_BIT (1 << 4) /* GPIO 0 open-drain enable */
#define MAX3107_GPIOCFG_GP1OD_BIT (1 << 5) /* GPIO 1 open-drain enable */
#define MAX3107_GPIOCFG_GP2OD_BIT (1 << 6) /* GPIO 2 open-drain enable */
#define MAX3107_GPIOCFG_GP3OD_BIT (1 << 7) /* GPIO 3 open-drain enable */
/* GPIO DATA register bits */
#define MAX3107_GPIODATA_GP0OUT_BIT (1 << 0) /* GPIO 0 output value */
#define MAX3107_GPIODATA_GP1OUT_BIT (1 << 1) /* GPIO 1 output value */
#define MAX3107_GPIODATA_GP2OUT_BIT (1 << 2) /* GPIO 2 output value */
#define MAX3107_GPIODATA_GP3OUT_BIT (1 << 3) /* GPIO 3 output value */
#define MAX3107_GPIODATA_GP0IN_BIT (1 << 4) /* GPIO 0 input value */
#define MAX3107_GPIODATA_GP1IN_BIT (1 << 5) /* GPIO 1 input value */
#define MAX3107_GPIODATA_GP2IN_BIT (1 << 6) /* GPIO 2 input value */
#define MAX3107_GPIODATA_GP3IN_BIT (1 << 7) /* GPIO 3 input value */
/* PLL configuration register masks */
#define MAX3107_PLLCFG_PREDIV_MASK (0x003f) /* PLL predivision value */
#define MAX3107_PLLCFG_PLLFACTOR_MASK (0x00c0) /* PLL multiplication factor */
/* Baud rate generator configuration register masks and bits */
#define MAX3107_BRGCFG_FRACT_MASK (0x000f) /* Fractional portion of
* Baud rate generator divisor
*/
#define MAX3107_BRGCFG_2XMODE_BIT (1 << 4) /* Double baud rate */
#define MAX3107_BRGCFG_4XMODE_BIT (1 << 5) /* Quadruple baud rate */
#define MAX3107_BRGCFG_UNDEF6_BIT (1 << 6) /* Undefined/not used */
#define MAX3107_BRGCFG_UNDEF7_BIT (1 << 7) /* Undefined/not used */
/* Clock source register bits */
#define MAX3107_CLKSRC_INTOSC_BIT (1 << 0) /* Internal osc enable */
#define MAX3107_CLKSRC_CRYST_BIT (1 << 1) /* Crystal osc enable */
#define MAX3107_CLKSRC_PLL_BIT (1 << 2) /* PLL enable */
#define MAX3107_CLKSRC_PLLBYP_BIT (1 << 3) /* PLL bypass */
#define MAX3107_CLKSRC_EXTCLK_BIT (1 << 4) /* External clock enable */
#define MAX3107_CLKSRC_UNDEF5_BIT (1 << 5) /* Undefined/not used */
#define MAX3107_CLKSRC_UNDEF6_BIT (1 << 6) /* Undefined/not used */
#define MAX3107_CLKSRC_CLK2RTS_BIT (1 << 7) /* Baud clk to RTS pin */
/* HW definitions */
#define MAX3107_RX_FIFO_SIZE 128
#define MAX3107_TX_FIFO_SIZE 128
#define MAX3107_REVID1 0x00a0
#define MAX3107_REVID2 0x00a1
/* Baud rate generator configuration values for external clock 13MHz */
#define MAX3107_BRG13_B300 (0x0A9400 | 0x05)
#define MAX3107_BRG13_B600 (0x054A00 | 0x03)
#define MAX3107_BRG13_B1200 (0x02A500 | 0x01)
#define MAX3107_BRG13_B2400 (0x015200 | 0x09)
#define MAX3107_BRG13_B4800 (0x00A900 | 0x04)
#define MAX3107_BRG13_B9600 (0x005400 | 0x0A)
#define MAX3107_BRG13_B19200 (0x002A00 | 0x05)
#define MAX3107_BRG13_B38400 (0x001500 | 0x03)
#define MAX3107_BRG13_B57600 (0x000E00 | 0x02)
#define MAX3107_BRG13_B115200 (0x000700 | 0x01)
#define MAX3107_BRG13_B230400 (0x000300 | 0x08)
#define MAX3107_BRG13_B460800 (0x000100 | 0x0c)
#define MAX3107_BRG13_B921600 (0x000100 | 0x1c)
/* Baud rate generator configuration values for external clock 26MHz */
#define MAX3107_BRG26_B300 (0x152800 | 0x0A)
#define MAX3107_BRG26_B600 (0x0A9400 | 0x05)
#define MAX3107_BRG26_B1200 (0x054A00 | 0x03)
#define MAX3107_BRG26_B2400 (0x02A500 | 0x01)
#define MAX3107_BRG26_B4800 (0x015200 | 0x09)
#define MAX3107_BRG26_B9600 (0x00A900 | 0x04)
#define MAX3107_BRG26_B19200 (0x005400 | 0x0A)
#define MAX3107_BRG26_B38400 (0x002A00 | 0x05)
#define MAX3107_BRG26_B57600 (0x001C00 | 0x03)
#define MAX3107_BRG26_B115200 (0x000E00 | 0x02)
#define MAX3107_BRG26_B230400 (0x000700 | 0x01)
#define MAX3107_BRG26_B460800 (0x000300 | 0x08)
#define MAX3107_BRG26_B921600 (0x000100 | 0x0C)
/* Baud rate generator configuration values for internal clock */
#define MAX3107_BRG13_IB300 (0x008000 | 0x00)
#define MAX3107_BRG13_IB600 (0x004000 | 0x00)
#define MAX3107_BRG13_IB1200 (0x002000 | 0x00)
#define MAX3107_BRG13_IB2400 (0x001000 | 0x00)
#define MAX3107_BRG13_IB4800 (0x000800 | 0x00)
#define MAX3107_BRG13_IB9600 (0x000400 | 0x00)
#define MAX3107_BRG13_IB19200 (0x000200 | 0x00)
#define MAX3107_BRG13_IB38400 (0x000100 | 0x00)
#define MAX3107_BRG13_IB57600 (0x000000 | 0x0B)
#define MAX3107_BRG13_IB115200 (0x000000 | 0x05)
#define MAX3107_BRG13_IB230400 (0x000000 | 0x03)
#define MAX3107_BRG13_IB460800 (0x000000 | 0x00)
#define MAX3107_BRG13_IB921600 (0x000000 | 0x00)
struct baud_table {
int baud;
u32 new_brg;
};
struct max3107_port {
/* UART port structure */
struct uart_port port;
/* SPI device structure */
struct spi_device *spi;
#if defined(CONFIG_GPIOLIB)
/* GPIO chip stucture */
struct gpio_chip chip;
#endif
/* Workqueue that does all the magic */
struct workqueue_struct *workqueue;
struct work_struct work;
/* Lock for shared data */
spinlock_t data_lock;
/* Device configuration */
int ext_clk; /* 1 if external clock used */
int loopback; /* Current loopback mode state */
int baud; /* Current baud rate */
/* State flags */
int suspended; /* Indicates suspend mode */
int tx_fifo_empty; /* Flag for TX FIFO state */
int rx_enabled; /* Flag for receiver state */
int tx_enabled; /* Flag for transmitter state */
u16 irqen_reg; /* Current IRQ enable register value */
/* Shared data */
u16 mode1_reg; /* Current mode1 register value*/
int mode1_commit; /* Flag for setting new mode1 register value */
u16 lcr_reg; /* Current LCR register value */
int lcr_commit; /* Flag for setting new LCR register value */
u32 brg_cfg; /* Current Baud rate generator config */
int brg_commit; /* Flag for setting new baud rate generator
* config
*/
struct baud_table *baud_tbl;
int handle_irq; /* Indicates that IRQ should be handled */
/* Rx buffer and str*/
u16 *rxbuf;
u8 *rxstr;
/* Tx buffer*/
u16 *txbuf;
struct max3107_plat *pdata; /* Platform data */
};
/* Platform data structure */
struct max3107_plat {
/* Loopback mode enable */
int loopback;
/* External clock enable */
int ext_clk;
/* Called during the register initialisation */
void (*init)(struct max3107_port *s);
/* Called when the port is found and configured */
int (*configure)(struct max3107_port *s);
/* HW suspend function */
void (*hw_suspend) (struct max3107_port *s, int suspend);
/* Polling mode enable */
int polled_mode;
/* Polling period if polling mode enabled */
int poll_time;
};
extern int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len);
extern void max3107_hw_susp(struct max3107_port *s, int suspend);
extern int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata);
extern int max3107_remove(struct spi_device *spi);
extern int max3107_suspend(struct spi_device *spi, pm_message_t state);
extern int max3107_resume(struct spi_device *spi);
#endif /* _LINUX_SERIAL_MAX3107_H */

View File

@ -70,16 +70,14 @@ static unsigned int mcf_tx_empty(struct uart_port *port)
static unsigned int mcf_get_mctrl(struct uart_port *port)
{
struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
unsigned long flags;
unsigned int sigs;
spin_lock_irqsave(&port->lock, flags);
sigs = (readb(port->membase + MCFUART_UIPR) & MCFUART_UIPR_CTS) ?
0 : TIOCM_CTS;
sigs |= (pp->sigs & TIOCM_RTS);
sigs |= (mcf_getppdcd(port->line) ? TIOCM_CD : 0);
sigs |= (mcf_getppdtr(port->line) ? TIOCM_DTR : 0);
spin_unlock_irqrestore(&port->lock, flags);
return sigs;
}
@ -88,16 +86,13 @@ static unsigned int mcf_get_mctrl(struct uart_port *port)
static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs)
{
struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
pp->sigs = sigs;
mcf_setppdtr(port->line, (sigs & TIOCM_DTR));
if (sigs & TIOCM_RTS)
writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1);
else
writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP0);
spin_unlock_irqrestore(&port->lock, flags);
}
/****************************************************************************/
@ -105,12 +100,9 @@ static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs)
static void mcf_start_tx(struct uart_port *port)
{
struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
pp->imr |= MCFUART_UIR_TXREADY;
writeb(pp->imr, port->membase + MCFUART_UIMR);
spin_unlock_irqrestore(&port->lock, flags);
}
/****************************************************************************/
@ -118,12 +110,9 @@ static void mcf_start_tx(struct uart_port *port)
static void mcf_stop_tx(struct uart_port *port)
{
struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
pp->imr &= ~MCFUART_UIR_TXREADY;
writeb(pp->imr, port->membase + MCFUART_UIMR);
spin_unlock_irqrestore(&port->lock, flags);
}
/****************************************************************************/
@ -131,12 +120,9 @@ static void mcf_stop_tx(struct uart_port *port)
static void mcf_stop_rx(struct uart_port *port)
{
struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
pp->imr &= ~MCFUART_UIR_RXREADY;
writeb(pp->imr, port->membase + MCFUART_UIMR);
spin_unlock_irqrestore(&port->lock, flags);
}
/****************************************************************************/
@ -366,13 +352,22 @@ static irqreturn_t mcf_interrupt(int irq, void *data)
struct uart_port *port = data;
struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
unsigned int isr;
irqreturn_t ret = IRQ_NONE;
isr = readb(port->membase + MCFUART_UISR) & pp->imr;
if (isr & MCFUART_UIR_RXREADY)
spin_lock(&port->lock);
if (isr & MCFUART_UIR_RXREADY) {
mcf_rx_chars(pp);
if (isr & MCFUART_UIR_TXREADY)
ret = IRQ_HANDLED;
}
if (isr & MCFUART_UIR_TXREADY) {
mcf_tx_chars(pp);
return IRQ_HANDLED;
ret = IRQ_HANDLED;
}
spin_unlock(&port->lock);
return ret;
}
/****************************************************************************/

1498
drivers/serial/mfd.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,844 @@
/*
* max3110.c - spi uart protocol driver for Maxim 3110 on Moorestown
*
* Copyright (C) Intel 2008 Feng Tang <feng.tang@intel.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* Note:
* 1. From Max3110 spec, the Rx FIFO has 8 words, while the Tx FIFO only has
* 1 word. If SPI master controller doesn't support sclk frequency change,
* then the char need be sent out one by one with some delay
*
* 2. Currently only RX availabe interrrupt is used, no need for waiting TXE
* interrupt for a low speed UART device
*/
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/platform_device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <asm/atomic.h>
#include <linux/spi/spi.h>
#include <linux/spi/dw_spi.h>
#include "mrst_max3110.h"
#define PR_FMT "mrst_max3110: "
#define UART_TX_NEEDED 1
#define CON_TX_NEEDED 2
#define BIT_IRQ_PENDING 3
struct uart_max3110 {
struct uart_port port;
struct spi_device *spi;
char *name;
wait_queue_head_t wq;
struct task_struct *main_thread;
struct task_struct *read_thread;
struct mutex thread_mutex;;
u32 baud;
u16 cur_conf;
u8 clock;
u8 parity, word_7bits;
unsigned long uart_flags;
/* console related */
struct circ_buf con_xmit;
/* irq related */
u16 irq;
};
/* global data structure, may need be removed */
struct uart_max3110 *pmax;
static inline void receive_char(struct uart_max3110 *max, u8 ch);
static void receive_chars(struct uart_max3110 *max,
unsigned char *str, int len);
static int max3110_read_multi(struct uart_max3110 *max, int len, u8 *buf);
static void max3110_console_receive(struct uart_max3110 *max);
int max3110_write_then_read(struct uart_max3110 *max,
const u8 *txbuf, u8 *rxbuf, unsigned len, int always_fast)
{
struct spi_device *spi = max->spi;
struct spi_message message;
struct spi_transfer x;
int ret;
if (!txbuf || !rxbuf)
return -EINVAL;
spi_message_init(&message);
memset(&x, 0, sizeof x);
x.len = len;
x.tx_buf = txbuf;
x.rx_buf = rxbuf;
spi_message_add_tail(&x, &message);
if (always_fast)
x.speed_hz = 3125000;
else if (max->baud)
x.speed_hz = max->baud;
/* Do the i/o */
ret = spi_sync(spi, &message);
return ret;
}
/* Write a u16 to the device, and return one u16 read back */
int max3110_out(struct uart_max3110 *max, const u16 out)
{
u16 tmp;
int ret;
ret = max3110_write_then_read(max, (u8 *)&out, (u8 *)&tmp, 2, 1);
if (ret)
return ret;
/* If some valid data is read back */
if (tmp & MAX3110_READ_DATA_AVAILABLE)
receive_char(max, (tmp & 0xff));
return ret;
}
#define MAX_READ_LEN 20
/*
* This is usually used to read data from SPIC RX FIFO, which doesn't
* need any delay like flushing character out. It returns how many
* valide bytes are read back
*/
static int max3110_read_multi(struct uart_max3110 *max, int len, u8 *buf)
{
u16 out[MAX_READ_LEN], in[MAX_READ_LEN];
u8 *pbuf, valid_str[MAX_READ_LEN];
int i, j, bytelen;
if (len > MAX_READ_LEN) {
pr_err(PR_FMT "read len %d is too large\n", len);
return 0;
}
bytelen = len * 2;
memset(out, 0, bytelen);
memset(in, 0, bytelen);
if (max3110_write_then_read(max, (u8 *)out, (u8 *)in, bytelen, 1))
return 0;
/* If caller don't provide a buffer, then handle received char */
pbuf = buf ? buf : valid_str;
for (i = 0, j = 0; i < len; i++) {
if (in[i] & MAX3110_READ_DATA_AVAILABLE)
pbuf[j++] = (u8)(in[i] & 0xff);
}
if (j && (pbuf == valid_str))
receive_chars(max, valid_str, j);
return j;
}
static void serial_m3110_con_putchar(struct uart_port *port, int ch)
{
struct uart_max3110 *max =
container_of(port, struct uart_max3110, port);
struct circ_buf *xmit = &max->con_xmit;
if (uart_circ_chars_free(xmit)) {
xmit->buf[xmit->head] = (char)ch;
xmit->head = (xmit->head + 1) & (PAGE_SIZE - 1);
}
if (!test_and_set_bit(CON_TX_NEEDED, &max->uart_flags))
wake_up_process(max->main_thread);
}
/*
* Print a string to the serial port trying not to disturb
* any possible real use of the port...
*
* The console_lock must be held when we get here.
*/
static void serial_m3110_con_write(struct console *co,
const char *s, unsigned int count)
{
if (!pmax)
return;
uart_console_write(&pmax->port, s, count, serial_m3110_con_putchar);
}
static int __init
serial_m3110_con_setup(struct console *co, char *options)
{
struct uart_max3110 *max = pmax;
int baud = 115200;
int bits = 8;
int parity = 'n';
int flow = 'n';
pr_info(PR_FMT "setting up console\n");
if (!max) {
pr_err(PR_FMT "pmax is NULL, return");
return -ENODEV;
}
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
return uart_set_options(&max->port, co, baud, parity, bits, flow);
}
static struct tty_driver *serial_m3110_con_device(struct console *co,
int *index)
{
struct uart_driver *p = co->data;
*index = co->index;
return p->tty_driver;
}
static struct uart_driver serial_m3110_reg;
static struct console serial_m3110_console = {
.name = "ttyS",
.write = serial_m3110_con_write,
.device = serial_m3110_con_device,
.setup = serial_m3110_con_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
.data = &serial_m3110_reg,
};
#define MRST_CONSOLE (&serial_m3110_console)
static unsigned int serial_m3110_tx_empty(struct uart_port *port)
{
return 1;
}
static void serial_m3110_stop_tx(struct uart_port *port)
{
return;
}
/* stop_rx will be called in spin_lock env */
static void serial_m3110_stop_rx(struct uart_port *port)
{
return;
}
#define WORDS_PER_XFER 128
static inline void send_circ_buf(struct uart_max3110 *max,
struct circ_buf *xmit)
{
int len, left = 0;
u16 obuf[WORDS_PER_XFER], ibuf[WORDS_PER_XFER];
u8 valid_str[WORDS_PER_XFER];
int i, j;
while (!uart_circ_empty(xmit)) {
left = uart_circ_chars_pending(xmit);
while (left) {
len = (left >= WORDS_PER_XFER) ? WORDS_PER_XFER : left;
memset(obuf, 0, len * 2);
memset(ibuf, 0, len * 2);
for (i = 0; i < len; i++) {
obuf[i] = (u8)xmit->buf[xmit->tail] | WD_TAG;
xmit->tail = (xmit->tail + 1) &
(UART_XMIT_SIZE - 1);
}
max3110_write_then_read(max, (u8 *)obuf,
(u8 *)ibuf, len * 2, 0);
for (i = 0, j = 0; i < len; i++) {
if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE)
valid_str[j++] = (u8)(ibuf[i] & 0xff);
}
if (j)
receive_chars(max, valid_str, j);
max->port.icount.tx += len;
left -= len;
}
}
}
static void transmit_char(struct uart_max3110 *max)
{
struct uart_port *port = &max->port;
struct circ_buf *xmit = &port->state->xmit;
if (uart_circ_empty(xmit) || uart_tx_stopped(port))
return;
send_circ_buf(max, xmit);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
serial_m3110_stop_tx(port);
}
/* This will be called by uart_write() and tty_write, can't
* go to sleep */
static void serial_m3110_start_tx(struct uart_port *port)
{
struct uart_max3110 *max =
container_of(port, struct uart_max3110, port);
if (!test_and_set_bit(UART_TX_NEEDED, &max->uart_flags))
wake_up_process(max->main_thread);
}
static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len)
{
struct uart_port *port = &max->port;
struct tty_struct *tty;
int usable;
/* If uart is not opened, just return */
if (!port->state)
return;
tty = port->state->port.tty;
if (!tty)
return; /* receive some char before the tty is opened */
while (len) {
usable = tty_buffer_request_room(tty, len);
if (usable) {
tty_insert_flip_string(tty, str, usable);
str += usable;
port->icount.rx += usable;
tty_flip_buffer_push(tty);
}
len -= usable;
}
}
static inline void receive_char(struct uart_max3110 *max, u8 ch)
{
receive_chars(max, &ch, 1);
}
static void max3110_console_receive(struct uart_max3110 *max)
{
int loop = 1, num, total = 0;
u8 recv_buf[512], *pbuf;
pbuf = recv_buf;
do {
num = max3110_read_multi(max, 8, pbuf);
if (num) {
loop = 10;
pbuf += num;
total += num;
if (total >= 500) {
receive_chars(max, recv_buf, total);
pbuf = recv_buf;
total = 0;
}
}
} while (--loop);
if (total)
receive_chars(max, recv_buf, total);
}
static int max3110_main_thread(void *_max)
{
struct uart_max3110 *max = _max;
wait_queue_head_t *wq = &max->wq;
int ret = 0;
struct circ_buf *xmit = &max->con_xmit;
init_waitqueue_head(wq);
pr_info(PR_FMT "start main thread\n");
do {
wait_event_interruptible(*wq, max->uart_flags || kthread_should_stop());
mutex_lock(&max->thread_mutex);
if (test_and_clear_bit(BIT_IRQ_PENDING, &max->uart_flags))
max3110_console_receive(max);
/* first handle console output */
if (test_and_clear_bit(CON_TX_NEEDED, &max->uart_flags))
send_circ_buf(max, xmit);
/* handle uart output */
if (test_and_clear_bit(UART_TX_NEEDED, &max->uart_flags))
transmit_char(max);
mutex_unlock(&max->thread_mutex);
} while (!kthread_should_stop());
return ret;
}
#ifdef CONFIG_MRST_MAX3110_IRQ
static irqreturn_t serial_m3110_irq(int irq, void *dev_id)
{
struct uart_max3110 *max = dev_id;
/* max3110's irq is a falling edge, not level triggered,
* so no need to disable the irq */
if (!test_and_set_bit(BIT_IRQ_PENDING, &max->uart_flags))
wake_up_process(max->main_thread);
return IRQ_HANDLED;
}
#else
/* if don't use RX IRQ, then need a thread to polling read */
static int max3110_read_thread(void *_max)
{
struct uart_max3110 *max = _max;
pr_info(PR_FMT "start read thread\n");
do {
mutex_lock(&max->thread_mutex);
max3110_console_receive(max);
mutex_unlock(&max->thread_mutex);
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ / 20);
} while (!kthread_should_stop());
return 0;
}
#endif
static int serial_m3110_startup(struct uart_port *port)
{
struct uart_max3110 *max =
container_of(port, struct uart_max3110, port);
u16 config = 0;
int ret = 0;
if (port->line != 0)
pr_err(PR_FMT "uart port startup failed\n");
/* firstly disable all IRQ and config it to 115200, 8n1 */
config = WC_TAG | WC_FIFO_ENABLE
| WC_1_STOPBITS
| WC_8BIT_WORD
| WC_BAUD_DR2;
ret = max3110_out(max, config);
/* as we use thread to handle tx/rx, need set low latency */
port->state->port.tty->low_latency = 1;
#ifdef CONFIG_MRST_MAX3110_IRQ
ret = request_irq(max->irq, serial_m3110_irq,
IRQ_TYPE_EDGE_FALLING, "max3110", max);
if (ret)
return ret;
/* enable RX IRQ only */
config |= WC_RXA_IRQ_ENABLE;
max3110_out(max, config);
#else
/* if IRQ is disabled, start a read thread for input data */
max->read_thread =
kthread_run(max3110_read_thread, max, "max3110_read");
#endif
max->cur_conf = config;
return 0;
}
static void serial_m3110_shutdown(struct uart_port *port)
{
struct uart_max3110 *max =
container_of(port, struct uart_max3110, port);
u16 config;
if (max->read_thread) {
kthread_stop(max->read_thread);
max->read_thread = NULL;
}
#ifdef CONFIG_MRST_MAX3110_IRQ
free_irq(max->irq, max);
#endif
/* Disable interrupts from this port */
config = WC_TAG | WC_SW_SHDI;
max3110_out(max, config);
}
static void serial_m3110_release_port(struct uart_port *port)
{
}
static int serial_m3110_request_port(struct uart_port *port)
{
return 0;
}
static void serial_m3110_config_port(struct uart_port *port, int flags)
{
/* give it fake type */
port->type = PORT_PXA;
}
static int
serial_m3110_verify_port(struct uart_port *port, struct serial_struct *ser)
{
/* we don't want the core code to modify any port params */
return -EINVAL;
}
static const char *serial_m3110_type(struct uart_port *port)
{
struct uart_max3110 *max =
container_of(port, struct uart_max3110, port);
return max->name;
}
static void
serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
struct uart_max3110 *max =
container_of(port, struct uart_max3110, port);
unsigned char cval;
unsigned int baud, parity = 0;
int clk_div = -1;
u16 new_conf = max->cur_conf;
switch (termios->c_cflag & CSIZE) {
case CS7:
cval = UART_LCR_WLEN7;
new_conf |= WC_7BIT_WORD;
break;
default:
case CS8:
cval = UART_LCR_WLEN8;
new_conf |= WC_8BIT_WORD;
break;
}
baud = uart_get_baud_rate(port, termios, old, 0, 230400);
/* first calc the div for 1.8MHZ clock case */
switch (baud) {
case 300:
clk_div = WC_BAUD_DR384;
break;
case 600:
clk_div = WC_BAUD_DR192;
break;
case 1200:
clk_div = WC_BAUD_DR96;
break;
case 2400:
clk_div = WC_BAUD_DR48;
break;
case 4800:
clk_div = WC_BAUD_DR24;
break;
case 9600:
clk_div = WC_BAUD_DR12;
break;
case 19200:
clk_div = WC_BAUD_DR6;
break;
case 38400:
clk_div = WC_BAUD_DR3;
break;
case 57600:
clk_div = WC_BAUD_DR2;
break;
case 115200:
clk_div = WC_BAUD_DR1;
break;
case 230400:
if (max->clock & MAX3110_HIGH_CLK)
break;
default:
/* pick the previous baud rate */
baud = max->baud;
clk_div = max->cur_conf & WC_BAUD_DIV_MASK;
tty_termios_encode_baud_rate(termios, baud, baud);
}
if (max->clock & MAX3110_HIGH_CLK) {
clk_div += 1;
/* high clk version max3110 doesn't support B300 */
if (baud == 300)
baud = 600;
if (baud == 230400)
clk_div = WC_BAUD_DR1;
tty_termios_encode_baud_rate(termios, baud, baud);
}
new_conf = (new_conf & ~WC_BAUD_DIV_MASK) | clk_div;
if (termios->c_cflag & CSTOPB)
new_conf |= WC_2_STOPBITS;
else
new_conf &= ~WC_2_STOPBITS;
if (termios->c_cflag & PARENB) {
new_conf |= WC_PARITY_ENABLE;
parity |= UART_LCR_PARITY;
} else
new_conf &= ~WC_PARITY_ENABLE;
if (!(termios->c_cflag & PARODD))
parity |= UART_LCR_EPAR;
max->parity = parity;
uart_update_timeout(port, termios->c_cflag, baud);
new_conf |= WC_TAG;
if (new_conf != max->cur_conf) {
max3110_out(max, new_conf);
max->cur_conf = new_conf;
max->baud = baud;
}
}
/* don't handle hw handshaking */
static unsigned int serial_m3110_get_mctrl(struct uart_port *port)
{
return TIOCM_DSR | TIOCM_CAR | TIOCM_DSR;
}
static void serial_m3110_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
}
static void serial_m3110_break_ctl(struct uart_port *port, int break_state)
{
}
static void serial_m3110_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
}
static void serial_m3110_enable_ms(struct uart_port *port)
{
}
struct uart_ops serial_m3110_ops = {
.tx_empty = serial_m3110_tx_empty,
.set_mctrl = serial_m3110_set_mctrl,
.get_mctrl = serial_m3110_get_mctrl,
.stop_tx = serial_m3110_stop_tx,
.start_tx = serial_m3110_start_tx,
.stop_rx = serial_m3110_stop_rx,
.enable_ms = serial_m3110_enable_ms,
.break_ctl = serial_m3110_break_ctl,
.startup = serial_m3110_startup,
.shutdown = serial_m3110_shutdown,
.set_termios = serial_m3110_set_termios, /* must have */
.pm = serial_m3110_pm,
.type = serial_m3110_type,
.release_port = serial_m3110_release_port,
.request_port = serial_m3110_request_port,
.config_port = serial_m3110_config_port,
.verify_port = serial_m3110_verify_port,
};
static struct uart_driver serial_m3110_reg = {
.owner = THIS_MODULE,
.driver_name = "MRST serial",
.dev_name = "ttyS",
.major = TTY_MAJOR,
.minor = 64,
.nr = 1,
.cons = MRST_CONSOLE,
};
static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state)
{
return 0;
}
static int serial_m3110_resume(struct spi_device *spi)
{
return 0;
}
static struct dw_spi_chip spi0_uart = {
.poll_mode = 1,
.enable_dma = 0,
.type = SPI_FRF_SPI,
};
static int serial_m3110_probe(struct spi_device *spi)
{
struct uart_max3110 *max;
int ret;
unsigned char *buffer;
u16 res;
max = kzalloc(sizeof(*max), GFP_KERNEL);
if (!max)
return -ENOMEM;
/* set spi info */
spi->mode = SPI_MODE_0;
spi->bits_per_word = 16;
max->clock = MAX3110_HIGH_CLK;
spi->controller_data = &spi0_uart;
spi_setup(spi);
max->port.type = PORT_PXA; /* need apply for a max3110 type */
max->port.fifosize = 2; /* only have 16b buffer */
max->port.ops = &serial_m3110_ops;
max->port.line = 0;
max->port.dev = &spi->dev;
max->port.uartclk = 115200;
max->spi = spi;
max->name = spi->modalias; /* use spi name as the name */
max->irq = (u16)spi->irq;
mutex_init(&max->thread_mutex);
max->word_7bits = 0;
max->parity = 0;
max->baud = 0;
max->cur_conf = 0;
max->uart_flags = 0;
/* Check if reading configuration register returns something sane */
res = RC_TAG;
ret = max3110_write_then_read(max, (u8 *)&res, (u8 *)&res, 2, 0);
if (ret < 0 || res == 0 || res == 0xffff) {
printk(KERN_ERR "MAX3111 deemed not present (conf reg %04x)",
res);
ret = -ENODEV;
goto err_get_page;
}
buffer = (unsigned char *)__get_free_page(GFP_KERNEL);
if (!buffer) {
ret = -ENOMEM;
goto err_get_page;
}
max->con_xmit.buf = (unsigned char *)buffer;
max->con_xmit.head = max->con_xmit.tail = 0;
max->main_thread = kthread_run(max3110_main_thread,
max, "max3110_main");
if (IS_ERR(max->main_thread)) {
ret = PTR_ERR(max->main_thread);
goto err_kthread;
}
pmax = max;
/* give membase a psudo value to pass serial_core's check */
max->port.membase = (void *)0xff110000;
uart_add_one_port(&serial_m3110_reg, &max->port);
return 0;
err_kthread:
free_page((unsigned long)buffer);
err_get_page:
pmax = NULL;
kfree(max);
return ret;
}
static int max3110_remove(struct spi_device *dev)
{
struct uart_max3110 *max = pmax;
if (!pmax)
return 0;
pmax = NULL;
uart_remove_one_port(&serial_m3110_reg, &max->port);
free_page((unsigned long)max->con_xmit.buf);
if (max->main_thread)
kthread_stop(max->main_thread);
kfree(max);
return 0;
}
static struct spi_driver uart_max3110_driver = {
.driver = {
.name = "spi_max3111",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = serial_m3110_probe,
.remove = __devexit_p(max3110_remove),
.suspend = serial_m3110_suspend,
.resume = serial_m3110_resume,
};
int __init serial_m3110_init(void)
{
int ret = 0;
ret = uart_register_driver(&serial_m3110_reg);
if (ret)
return ret;
ret = spi_register_driver(&uart_max3110_driver);
if (ret)
uart_unregister_driver(&serial_m3110_reg);
return ret;
}
void __exit serial_m3110_exit(void)
{
spi_unregister_driver(&uart_max3110_driver);
uart_unregister_driver(&serial_m3110_reg);
}
module_init(serial_m3110_init);
module_exit(serial_m3110_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("max3110-uart");

View File

@ -0,0 +1,59 @@
#ifndef _MRST_MAX3110_H
#define _MRST_MAX3110_H
#define MAX3110_HIGH_CLK 0x1 /* 3.6864 MHZ */
#define MAX3110_LOW_CLK 0x0 /* 1.8432 MHZ */
/* status bits for all 4 MAX3110 operate modes */
#define MAX3110_READ_DATA_AVAILABLE (1 << 15)
#define MAX3110_WRITE_BUF_EMPTY (1 << 14)
#define WC_TAG (3 << 14)
#define RC_TAG (1 << 14)
#define WD_TAG (2 << 14)
#define RD_TAG (0 << 14)
/* bits def for write configuration */
#define WC_FIFO_ENABLE_MASK (1 << 13)
#define WC_FIFO_ENABLE (0 << 13)
#define WC_SW_SHDI (1 << 12)
#define WC_IRQ_MASK (0xF << 8)
#define WC_TXE_IRQ_ENABLE (1 << 11) /* TX empty irq */
#define WC_RXA_IRQ_ENABLE (1 << 10) /* RX availabe irq */
#define WC_PAR_HIGH_IRQ_ENABLE (1 << 9)
#define WC_REC_ACT_IRQ_ENABLE (1 << 8)
#define WC_IRDA_ENABLE (1 << 7)
#define WC_STOPBITS_MASK (1 << 6)
#define WC_2_STOPBITS (1 << 6)
#define WC_1_STOPBITS (0 << 6)
#define WC_PARITY_ENABLE_MASK (1 << 5)
#define WC_PARITY_ENABLE (1 << 5)
#define WC_WORDLEN_MASK (1 << 4)
#define WC_7BIT_WORD (1 << 4)
#define WC_8BIT_WORD (0 << 4)
#define WC_BAUD_DIV_MASK (0xF)
#define WC_BAUD_DR1 (0x0)
#define WC_BAUD_DR2 (0x1)
#define WC_BAUD_DR4 (0x2)
#define WC_BAUD_DR8 (0x3)
#define WC_BAUD_DR16 (0x4)
#define WC_BAUD_DR32 (0x5)
#define WC_BAUD_DR64 (0x6)
#define WC_BAUD_DR128 (0x7)
#define WC_BAUD_DR3 (0x8)
#define WC_BAUD_DR6 (0x9)
#define WC_BAUD_DR12 (0xA)
#define WC_BAUD_DR24 (0xB)
#define WC_BAUD_DR48 (0xC)
#define WC_BAUD_DR96 (0xD)
#define WC_BAUD_DR192 (0xE)
#define WC_BAUD_DR384 (0xF)
#endif

View File

@ -58,9 +58,9 @@ static struct lock_class_key port_lock_key;
#define uart_console(port) (0)
#endif
static void uart_change_speed(struct uart_state *state,
static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
struct ktermios *old_termios);
static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
static void __uart_wait_until_sent(struct uart_port *port, int timeout);
static void uart_change_pm(struct uart_state *state, int pm_state);
/*
@ -137,7 +137,7 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)
* Startup the port. This will be called once per open. All calls
* will be serialised by the per-port mutex.
*/
static int uart_startup(struct uart_state *state, int init_hw)
static int uart_startup(struct tty_struct *tty, struct uart_state *state, int init_hw)
{
struct uart_port *uport = state->uart_port;
struct tty_port *port = &state->port;
@ -152,7 +152,7 @@ static int uart_startup(struct uart_state *state, int init_hw)
* once we have successfully opened the port. Also set
* up the tty->alt_speed kludge
*/
set_bit(TTY_IO_ERROR, &port->tty->flags);
set_bit(TTY_IO_ERROR, &tty->flags);
if (uport->type == PORT_UNKNOWN)
return 0;
@ -177,26 +177,26 @@ static int uart_startup(struct uart_state *state, int init_hw)
/*
* Initialise the hardware port settings.
*/
uart_change_speed(state, NULL);
uart_change_speed(tty, state, NULL);
/*
* Setup the RTS and DTR signals once the
* port is open and ready to respond.
*/
if (port->tty->termios->c_cflag & CBAUD)
if (tty->termios->c_cflag & CBAUD)
uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR);
}
if (port->flags & ASYNC_CTS_FLOW) {
spin_lock_irq(&uport->lock);
if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS))
port->tty->hw_stopped = 1;
tty->hw_stopped = 1;
spin_unlock_irq(&uport->lock);
}
set_bit(ASYNCB_INITIALIZED, &port->flags);
clear_bit(TTY_IO_ERROR, &port->tty->flags);
clear_bit(TTY_IO_ERROR, &tty->flags);
}
if (retval && capable(CAP_SYS_ADMIN))
@ -210,11 +210,10 @@ static int uart_startup(struct uart_state *state, int init_hw)
* DTR is dropped if the hangup on close termio flag is on. Calls to
* uart_shutdown are serialised by the per-port semaphore.
*/
static void uart_shutdown(struct uart_state *state)
static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
{
struct uart_port *uport = state->uart_port;
struct tty_port *port = &state->port;
struct tty_struct *tty = port->tty;
/*
* Set the TTY IO error marker
@ -430,11 +429,10 @@ uart_get_divisor(struct uart_port *port, unsigned int baud)
EXPORT_SYMBOL(uart_get_divisor);
/* FIXME: Consistent locking policy */
static void
uart_change_speed(struct uart_state *state, struct ktermios *old_termios)
static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
struct ktermios *old_termios)
{
struct tty_port *port = &state->port;
struct tty_struct *tty = port->tty;
struct uart_port *uport = state->uart_port;
struct ktermios *termios;
@ -463,8 +461,8 @@ uart_change_speed(struct uart_state *state, struct ktermios *old_termios)
uport->ops->set_termios(uport, termios, old_termios);
}
static inline int
__uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c)
static inline int __uart_put_char(struct uart_port *port,
struct circ_buf *circ, unsigned char c)
{
unsigned long flags;
int ret = 0;
@ -494,8 +492,8 @@ static void uart_flush_chars(struct tty_struct *tty)
uart_start(tty);
}
static int
uart_write(struct tty_struct *tty, const unsigned char *buf, int count)
static int uart_write(struct tty_struct *tty,
const unsigned char *buf, int count)
{
struct uart_state *state = tty->driver_data;
struct uart_port *port;
@ -675,7 +673,7 @@ static int uart_get_info(struct uart_state *state,
return 0;
}
static int uart_set_info(struct uart_state *state,
static int uart_set_info(struct tty_struct *tty, struct uart_state *state,
struct serial_struct __user *newinfo)
{
struct serial_struct new_serial;
@ -770,7 +768,7 @@ static int uart_set_info(struct uart_state *state,
* We need to shutdown the serial port at the old
* port/type/irq combination.
*/
uart_shutdown(state);
uart_shutdown(tty, state);
}
if (change_port) {
@ -869,25 +867,27 @@ static int uart_set_info(struct uart_state *state,
"is deprecated.\n", current->comm,
tty_name(port->tty, buf));
}
uart_change_speed(state, NULL);
uart_change_speed(tty, state, NULL);
}
} else
retval = uart_startup(state, 1);
retval = uart_startup(tty, state, 1);
exit:
mutex_unlock(&port->mutex);
return retval;
}
/*
* uart_get_lsr_info - get line status register info.
* Note: uart_ioctl protects us against hangups.
/**
* uart_get_lsr_info - get line status register info
* @tty: tty associated with the UART
* @state: UART being queried
* @value: returned modem value
*
* Note: uart_ioctl protects us against hangups.
*/
static int uart_get_lsr_info(struct uart_state *state,
unsigned int __user *value)
static int uart_get_lsr_info(struct tty_struct *tty,
struct uart_state *state, unsigned int __user *value)
{
struct uart_port *uport = state->uart_port;
struct tty_port *port = &state->port;
unsigned int result;
result = uport->ops->tx_empty(uport);
@ -900,7 +900,7 @@ static int uart_get_lsr_info(struct uart_state *state,
*/
if (uport->x_char ||
((uart_circ_chars_pending(&state->xmit) > 0) &&
!port->tty->stopped && !port->tty->hw_stopped))
!tty->stopped && !tty->hw_stopped))
result &= ~TIOCSER_TEMT;
return put_user(result, value);
@ -961,7 +961,7 @@ static int uart_break_ctl(struct tty_struct *tty, int break_state)
return 0;
}
static int uart_do_autoconfig(struct uart_state *state)
static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state)
{
struct uart_port *uport = state->uart_port;
struct tty_port *port = &state->port;
@ -980,7 +980,7 @@ static int uart_do_autoconfig(struct uart_state *state)
ret = -EBUSY;
if (tty_port_users(port) == 1) {
uart_shutdown(state);
uart_shutdown(tty, state);
/*
* If we already have a port type configured,
@ -999,7 +999,7 @@ static int uart_do_autoconfig(struct uart_state *state)
*/
uport->ops->config_port(uport, flags);
ret = uart_startup(state, 1);
ret = uart_startup(tty, state, 1);
}
mutex_unlock(&port->mutex);
return ret;
@ -1122,11 +1122,11 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
break;
case TIOCSSERIAL:
ret = uart_set_info(state, uarg);
ret = uart_set_info(tty, state, uarg);
break;
case TIOCSERCONFIG:
ret = uart_do_autoconfig(state);
ret = uart_do_autoconfig(tty, state);
break;
case TIOCSERGWILD: /* obsolete */
@ -1172,7 +1172,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
*/
switch (cmd) {
case TIOCSERGETLSR: /* Get line status register */
ret = uart_get_lsr_info(state, uarg);
ret = uart_get_lsr_info(tty, state, uarg);
break;
default: {
@ -1194,7 +1194,7 @@ static void uart_set_ldisc(struct tty_struct *tty)
struct uart_port *uport = state->uart_port;
if (uport->ops->set_ldisc)
uport->ops->set_ldisc(uport);
uport->ops->set_ldisc(uport, tty->termios->c_line);
}
static void uart_set_termios(struct tty_struct *tty,
@ -1219,7 +1219,7 @@ static void uart_set_termios(struct tty_struct *tty,
return;
}
uart_change_speed(state, old_termios);
uart_change_speed(tty, state, old_termios);
/* Handle transition to B0 status */
if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
@ -1272,8 +1272,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
struct uart_state *state = tty->driver_data;
struct tty_port *port;
struct uart_port *uport;
unsigned long flags;
BUG_ON(!kernel_locked());
BUG_ON(!tty_locked());
if (!state)
return;
@ -1284,9 +1285,12 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
pr_debug("uart_close(%d) called\n", uport->line);
mutex_lock(&port->mutex);
spin_lock_irqsave(&port->lock, flags);
if (tty_hung_up_p(filp))
if (tty_hung_up_p(filp)) {
spin_unlock_irqrestore(&port->lock, flags);
goto done;
}
if ((tty->count == 1) && (port->count != 1)) {
/*
@ -1305,8 +1309,10 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
tty->name, port->count);
port->count = 0;
}
if (port->count)
if (port->count) {
spin_unlock_irqrestore(&port->lock, flags);
goto done;
}
/*
* Now we wait for the transmit buffer to clear; and we notify
@ -1314,9 +1320,18 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
* setting tty->closing.
*/
tty->closing = 1;
spin_unlock_irqrestore(&port->lock, flags);
if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent(tty, msecs_to_jiffies(port->closing_wait));
if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) {
/*
* hack: open-coded tty_wait_until_sent to avoid
* recursive tty_lock
*/
long timeout = msecs_to_jiffies(port->closing_wait);
if (wait_event_interruptible_timeout(tty->write_wait,
!tty_chars_in_buffer(tty), timeout) >= 0)
__uart_wait_until_sent(uport, timeout);
}
/*
* At this point, we stop accepting input. To do this, we
@ -1332,45 +1347,47 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
* has completely drained; this is especially
* important if there is a transmit FIFO!
*/
uart_wait_until_sent(tty, uport->timeout);
__uart_wait_until_sent(uport, uport->timeout);
}
uart_shutdown(state);
uart_shutdown(tty, state);
uart_flush_buffer(tty);
tty_ldisc_flush(tty);
tty->closing = 0;
tty_port_tty_set(port, NULL);
spin_lock_irqsave(&port->lock, flags);
tty->closing = 0;
if (port->blocked_open) {
spin_unlock_irqrestore(&port->lock, flags);
if (port->close_delay)
msleep_interruptible(port->close_delay);
spin_lock_irqsave(&port->lock, flags);
} else if (!uart_console(uport)) {
spin_unlock_irqrestore(&port->lock, flags);
uart_change_pm(state, 3);
spin_lock_irqsave(&port->lock, flags);
}
/*
* Wake up anyone trying to open this port.
*/
clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
spin_unlock_irqrestore(&port->lock, flags);
wake_up_interruptible(&port->open_wait);
done:
mutex_unlock(&port->mutex);
}
static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
static void __uart_wait_until_sent(struct uart_port *port, int timeout)
{
struct uart_state *state = tty->driver_data;
struct uart_port *port = state->uart_port;
unsigned long char_time, expire;
if (port->type == PORT_UNKNOWN || port->fifosize == 0)
return;
lock_kernel();
/*
* Set the check interval to be 1/5 of the estimated time to
* send a single character, and make it at least 1. The check
@ -1416,7 +1433,16 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
break;
}
set_current_state(TASK_RUNNING); /* might not be needed */
unlock_kernel();
}
static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
{
struct uart_state *state = tty->driver_data;
struct uart_port *port = state->uart_port;
tty_lock();
__uart_wait_until_sent(port, timeout);
tty_unlock();
}
/*
@ -1429,16 +1455,19 @@ static void uart_hangup(struct tty_struct *tty)
{
struct uart_state *state = tty->driver_data;
struct tty_port *port = &state->port;
unsigned long flags;
BUG_ON(!kernel_locked());
BUG_ON(!tty_locked());
pr_debug("uart_hangup(%d)\n", state->uart_port->line);
mutex_lock(&port->mutex);
if (port->flags & ASYNC_NORMAL_ACTIVE) {
uart_flush_buffer(tty);
uart_shutdown(state);
uart_shutdown(tty, state);
spin_lock_irqsave(&port->lock, flags);
port->count = 0;
clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
spin_unlock_irqrestore(&port->lock, flags);
tty_port_tty_set(port, NULL);
wake_up_interruptible(&port->open_wait);
wake_up_interruptible(&port->delta_msr_wait);
@ -1446,15 +1475,19 @@ static void uart_hangup(struct tty_struct *tty)
mutex_unlock(&port->mutex);
}
/*
* Copy across the serial console cflag setting into the termios settings
* for the initial open of the port. This allows continuity between the
* kernel settings, and the settings init adopts when it opens the port
* for the first time.
/**
* uart_update_termios - update the terminal hw settings
* @tty: tty associated with UART
* @state: UART to update
*
* Copy across the serial console cflag setting into the termios settings
* for the initial open of the port. This allows continuity between the
* kernel settings, and the settings init adopts when it opens the port
* for the first time.
*/
static void uart_update_termios(struct uart_state *state)
static void uart_update_termios(struct tty_struct *tty,
struct uart_state *state)
{
struct tty_struct *tty = state->port.tty;
struct uart_port *port = state->uart_port;
if (uart_console(port) && port->cons->cflag) {
@ -1471,7 +1504,7 @@ static void uart_update_termios(struct uart_state *state)
/*
* Make termios settings take effect.
*/
uart_change_speed(state, NULL);
uart_change_speed(tty, state, NULL);
/*
* And finally enable the RTS and DTR signals.
@ -1481,92 +1514,39 @@ static void uart_update_termios(struct uart_state *state)
}
}
/*
* Block the open until the port is ready. We must be called with
* the per-port semaphore held.
*/
static int
uart_block_til_ready(struct file *filp, struct uart_state *state)
static int uart_carrier_raised(struct tty_port *port)
{
DECLARE_WAITQUEUE(wait, current);
struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport = state->uart_port;
struct tty_port *port = &state->port;
unsigned int mctrl;
port->blocked_open++;
port->count--;
add_wait_queue(&port->open_wait, &wait);
while (1) {
set_current_state(TASK_INTERRUPTIBLE);
/*
* If we have been hung up, tell userspace/restart open.
*/
if (tty_hung_up_p(filp) || port->tty == NULL)
break;
/*
* If the port has been closed, tell userspace/restart open.
*/
if (!(port->flags & ASYNC_INITIALIZED))
break;
/*
* If non-blocking mode is set, or CLOCAL mode is set,
* we don't want to wait for the modem status lines to
* indicate that the port is ready.
*
* Also, if the port is not enabled/configured, we want
* to allow the open to succeed here. Note that we will
* have set TTY_IO_ERROR for a non-existant port.
*/
if ((filp->f_flags & O_NONBLOCK) ||
(port->tty->termios->c_cflag & CLOCAL) ||
(port->tty->flags & (1 << TTY_IO_ERROR)))
break;
/*
* Set DTR to allow modem to know we're waiting. Do
* not set RTS here - we want to make sure we catch
* the data from the modem.
*/
if (port->tty->termios->c_cflag & CBAUD)
uart_set_mctrl(uport, TIOCM_DTR);
/*
* and wait for the carrier to indicate that the
* modem is ready for us.
*/
spin_lock_irq(&uport->lock);
uport->ops->enable_ms(uport);
mctrl = uport->ops->get_mctrl(uport);
spin_unlock_irq(&uport->lock);
if (mctrl & TIOCM_CAR)
break;
mutex_unlock(&port->mutex);
schedule();
mutex_lock(&port->mutex);
if (signal_pending(current))
break;
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&port->open_wait, &wait);
port->count++;
port->blocked_open--;
if (signal_pending(current))
return -ERESTARTSYS;
if (!port->tty || tty_hung_up_p(filp))
return -EAGAIN;
int mctrl;
spin_lock_irq(&uport->lock);
uport->ops->enable_ms(uport);
mctrl = uport->ops->get_mctrl(uport);
spin_unlock_irq(&uport->lock);
if (mctrl & TIOCM_CAR)
return 1;
return 0;
}
static void uart_dtr_rts(struct tty_port *port, int onoff)
{
struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport = state->uart_port;
if (onoff) {
uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
/*
* If this is the first open to succeed,
* adjust things to suit.
*/
if (!test_and_set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags))
uart_update_termios(port->tty, state);
}
else
uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
}
static struct uart_state *uart_get(struct uart_driver *drv, int line)
{
struct uart_state *state;
@ -1611,7 +1591,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
struct tty_port *port;
int retval, line = tty->index;
BUG_ON(!kernel_locked());
BUG_ON(!tty_locked());
pr_debug("uart_open(%d) called\n", line);
/*
@ -1668,23 +1648,14 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
/*
* Start up the serial port.
*/
retval = uart_startup(state, 0);
retval = uart_startup(tty, state, 0);
/*
* If we succeeded, wait until the port is ready.
*/
if (retval == 0)
retval = uart_block_til_ready(filp, state);
mutex_unlock(&port->mutex);
/*
* If this is the first open to succeed, adjust things to suit.
*/
if (retval == 0 && !(port->flags & ASYNC_NORMAL_ACTIVE)) {
set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
uart_update_termios(state);
}
if (retval == 0)
retval = tty_port_block_til_ready(port, tty, filp);
fail:
return retval;
@ -2010,9 +1981,13 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
struct tty_port *port = &state->port;
struct device *tty_dev;
struct uart_match match = {uport, drv};
struct tty_struct *tty;
mutex_lock(&port->mutex);
/* Must be inside the mutex lock until we convert to tty_port */
tty = port->tty;
tty_dev = device_find_child(uport->dev, &match, serial_match_port);
if (device_may_wakeup(tty_dev)) {
enable_irq_wake(uport->irq);
@ -2105,9 +2080,12 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
ops->set_mctrl(uport, 0);
spin_unlock_irq(&uport->lock);
if (console_suspend_enabled || !uart_console(uport)) {
/* Protected by port mutex for now */
struct tty_struct *tty = port->tty;
ret = ops->startup(uport);
if (ret == 0) {
uart_change_speed(state, NULL);
if (tty)
uart_change_speed(tty, state, NULL);
spin_lock_irq(&uport->lock);
ops->set_mctrl(uport, uport->mctrl);
ops->start_tx(uport);
@ -2119,7 +2097,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
* Clear the "initialized" flag so we won't try
* to call the low level drivers shutdown method.
*/
uart_shutdown(state);
uart_shutdown(tty, state);
}
}
@ -2312,6 +2290,11 @@ static const struct tty_operations uart_ops = {
#endif
};
static const struct tty_port_operations uart_port_ops = {
.carrier_raised = uart_carrier_raised,
.dtr_rts = uart_dtr_rts,
};
/**
* uart_register_driver - register a driver with the uart core layer
* @drv: low level driver structure
@ -2368,6 +2351,7 @@ int uart_register_driver(struct uart_driver *drv)
struct tty_port *port = &state->port;
tty_port_init(port);
port->ops = &uart_port_ops;
port->close_delay = 500; /* .5 seconds */
port->closing_wait = 30000; /* 30 seconds */
tasklet_init(&state->tlet, uart_tasklet_action,

View File

@ -423,7 +423,7 @@ static struct uart_driver timbuart_driver = {
.nr = 1
};
static int timbuart_probe(struct platform_device *dev)
static int __devinit timbuart_probe(struct platform_device *dev)
{
int err, irq;
struct timbuart_port *uart;
@ -489,7 +489,7 @@ err_mem:
return err;
}
static int timbuart_remove(struct platform_device *dev)
static int __devexit timbuart_remove(struct platform_device *dev)
{
struct timbuart_port *uart = platform_get_drvdata(dev);
@ -507,7 +507,7 @@ static struct platform_driver timbuart_platform_driver = {
.owner = THIS_MODULE,
},
.probe = timbuart_probe,
.remove = timbuart_remove,
.remove = __devexit_p(timbuart_remove),
};
/*--------------------------------------------------------------------------*/

View File

@ -636,19 +636,13 @@ static void acm_tty_unregister(struct acm *acm)
static int acm_tty_chars_in_buffer(struct tty_struct *tty);
static void acm_port_down(struct acm *acm, int drain)
static void acm_port_down(struct acm *acm)
{
int i, nr = acm->rx_buflimit;
mutex_lock(&open_mutex);
if (acm->dev) {
usb_autopm_get_interface(acm->control);
acm_set_control(acm, acm->ctrlout = 0);
/* try letting the last writes drain naturally */
if (drain) {
wait_event_interruptible_timeout(acm->drain_wait,
(ACM_NW == acm_wb_is_avail(acm)) || !acm->dev,
ACM_CLOSE_TIMEOUT * HZ);
}
usb_kill_urb(acm->ctrlurb);
for (i = 0; i < ACM_NW; i++)
usb_kill_urb(acm->wb[i].urb);
@ -664,7 +658,7 @@ static void acm_tty_hangup(struct tty_struct *tty)
{
struct acm *acm = tty->driver_data;
tty_port_hangup(&acm->port);
acm_port_down(acm, 0);
acm_port_down(acm);
}
static void acm_tty_close(struct tty_struct *tty, struct file *filp)
@ -685,7 +679,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
mutex_unlock(&open_mutex);
return;
}
acm_port_down(acm, 0);
acm_port_down(acm);
tty_port_close_end(&acm->port, tty);
tty_port_tty_set(&acm->port, NULL);
}

View File

@ -609,8 +609,10 @@ static void digi_wakeup_write_lock(struct work_struct *work)
static void digi_wakeup_write(struct usb_serial_port *port)
{
struct tty_struct *tty = tty_port_tty_get(&port->port);
tty_wakeup(tty);
tty_kref_put(tty);
if (tty) {
tty_wakeup(tty);
tty_kref_put(tty);
}
}
@ -1682,7 +1684,7 @@ static int digi_read_inb_callback(struct urb *urb)
priv->dp_throttle_restart = 1;
/* receive data */
if (opcode == DIGI_CMD_RECEIVE_DATA) {
if (tty && opcode == DIGI_CMD_RECEIVE_DATA) {
/* get flag from port_status */
flag = 0;
@ -1763,10 +1765,12 @@ static int digi_read_oob_callback(struct urb *urb)
return -1;
tty = tty_port_tty_get(&port->port);
rts = 0;
rts = tty->termios->c_cflag & CRTSCTS;
if (tty)
rts = tty->termios->c_cflag & CRTSCTS;
if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
if (tty && opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
spin_lock(&priv->dp_port_lock);
/* convert from digi flags to termiox flags */
if (val & DIGI_READ_INPUT_SIGNALS_CTS) {

View File

@ -283,7 +283,8 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
struct fbcon_ops *ops = info->fbcon_par;
return (info->state != FBINFO_STATE_RUNNING ||
vc->vc_mode != KD_TEXT || ops->graphics);
vc->vc_mode != KD_TEXT || ops->graphics) &&
!vt_force_oops_output(vc);
}
static inline int get_color(struct vc_data *vc, struct fb_info *info,
@ -1073,6 +1074,7 @@ static void fbcon_init(struct vc_data *vc, int init)
if (p->userfont)
charcnt = FNTCHARCNT(p->fontdata);
vc->vc_panic_force_write = !!(info->flags & FBINFO_CAN_FORCE_OUTPUT);
vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
if (charcnt == 256) {

View File

@ -1108,7 +1108,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
charmap += 4 * cmapsz;
#endif
unlock_kernel();
spin_lock_irq(&vga_lock);
/* First, the Sequencer */
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
@ -1192,7 +1191,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
}
spin_unlock_irq(&vga_lock);
lock_kernel();
return 0;
}

View File

@ -946,6 +946,7 @@ COMPATIBLE_IOCTL(TIOCGPGRP)
COMPATIBLE_IOCTL(TIOCGPTN)
COMPATIBLE_IOCTL(TIOCSPTLCK)
COMPATIBLE_IOCTL(TIOCSERGETLSR)
COMPATIBLE_IOCTL(TIOCSIG)
#ifdef TCGETS2
COMPATIBLE_IOCTL(TCGETS2)
COMPATIBLE_IOCTL(TCSETS2)

Some files were not shown because too many files have changed in this diff Show More