mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-09 07:23:14 +00:00
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:
commit
fc385c3132
@ -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]
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -180,6 +180,7 @@ struct ktermios {
|
||||
#define FLUSHO 0010000
|
||||
#define PENDIN 0040000
|
||||
#define IEXTEN 0100000
|
||||
#define EXTPROC 0200000
|
||||
|
||||
|
||||
/* tcflow() and TCXONC use these */
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -179,6 +179,7 @@ struct ktermios {
|
||||
#define FLUSHO 0010000
|
||||
#define PENDIN 0040000
|
||||
#define IEXTEN 0100000
|
||||
#define EXTPROC 0200000
|
||||
|
||||
|
||||
/* tcflow() and TCXONC use these */
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -179,6 +179,7 @@ struct ktermios {
|
||||
#define FLUSHO 0010000
|
||||
#define PENDIN 0040000
|
||||
#define IEXTEN 0100000
|
||||
#define EXTPROC 0200000
|
||||
|
||||
|
||||
/* tcflow() and TCXONC use these */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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) */
|
||||
|
@ -225,6 +225,7 @@ struct ktermios {
|
||||
#define FLUSHO 0x00002000
|
||||
#define PENDIN 0x00004000
|
||||
#define IEXTEN 0x00008000
|
||||
#define EXTPROC 0x00010000
|
||||
|
||||
/* modem lines */
|
||||
#define TIOCM_LE 0x001
|
||||
|
@ -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)
|
||||
|
@ -196,6 +196,7 @@ struct ktermios {
|
||||
#define FLUSHO 0010000
|
||||
#define PENDIN 0040000
|
||||
#define IEXTEN 0100000
|
||||
#define EXTPROC 0200000
|
||||
|
||||
/* tcflow() and TCXONC use these */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 @@ static int set_serial_info(struct async_struct * info,
|
||||
}
|
||||
} 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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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)))
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 @@ static int stli_startbrd(struct stlibrd *brdp)
|
||||
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);
|
||||
|
@ -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. */
|
||||
|
@ -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) {
|
||||
|
@ -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>
|
||||
|
@ -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() */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
|
||||
nr--;
|
||||
}
|
||||
|
||||
if (tty->icanon) {
|
||||
if (tty->icanon && !L_EXTPROC(tty)) {
|
||||
/* N.B. avoid overrun if nr == 0 */
|
||||
while (nr && tty->read_cnt) {
|
||||
int eol;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 @@ static void close(struct tty_struct *tty, struct file *filp)
|
||||
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);
|
||||
|
@ -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 @@ static void close(struct tty_struct *tty, struct file *filp)
|
||||
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);
|
||||
|
@ -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 @@ static inline ssize_t do_tty_write(
|
||||
* 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 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
|
||||
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 @@ static int tty_open(struct inode *inode, struct file *filp)
|
||||
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 @@ static int tty_open(struct inode *inode, struct file *filp)
|
||||
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 @@ static int tty_open(struct inode *inode, struct file *filp)
|
||||
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 @@ static int tty_open(struct inode *inode, struct file *filp)
|
||||
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 @@ static int tty_open(struct inode *inode, struct file *filp)
|
||||
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(¤t->sighand->siglock);
|
||||
if (!noctty &&
|
||||
current->signal->leader &&
|
||||
@ -1890,7 +1895,7 @@ static int tty_open(struct inode *inode, struct file *filp)
|
||||
tty->session == NULL)
|
||||
__proc_set_tty(current, tty);
|
||||
spin_unlock_irq(¤t->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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
47
drivers/char/tty_mutex.c
Normal 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);
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
||||
|
344
drivers/serial/max3107-aava.c
Normal file
344
drivers/serial/max3107-aava.c
Normal 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
1197
drivers/serial/max3107.c
Normal file
File diff suppressed because it is too large
Load Diff
441
drivers/serial/max3107.h
Normal file
441
drivers/serial/max3107.h
Normal 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 */
|
@ -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
1498
drivers/serial/mfd.c
Normal file
File diff suppressed because it is too large
Load Diff
844
drivers/serial/mrst_max3110.c
Normal file
844
drivers/serial/mrst_max3110.c
Normal 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");
|
59
drivers/serial/mrst_max3110.h
Normal file
59
drivers/serial/mrst_max3110.h
Normal 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
|
@ -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,
|
||||
|
@ -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 @@ static int timbuart_probe(struct platform_device *dev)
|
||||
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),
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user