Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
Linus Torvalds [Sat, 23 Oct 2010 02:59:04 +0000 (19:59 -0700)]
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (49 commits)
  serial8250: ratelimit "too much work" error
  serial: bfin_sport_uart: speed up sport RX sample rate to be 3% faster
  serial: abstraction for 8250 legacy ports
  serial/imx: check that the buffer is non-empty before sending it out
  serial: mfd: add more baud rates support
  jsm: Remove the uart port on errors
  Alchemy: Add UART PM methods.
  8250: allow platforms to override PM hook.
  altera_uart: Don't use plain integer as NULL pointer
  altera_uart: Fix missing prototype for registering an early console
  altera_uart: Fixup type usage of port flags
  altera_uart: Make it possible to use Altera UART and 8250 ports together
  altera_uart: Add support for different address strides
  altera_uart: Add support for getting mapbase and IRQ from resources
  altera_uart: Add support for polling mode (IRQ-less)
  serial: Factor out uart_poll_timeout() from 8250 driver
  serial: mark the 8250 driver as maintained
  serial: 8250: Don't delay after transmitter is ready.
  tty: MAINTAINERS: add drivers/serial/jsm/ as maintained driver
  vcs: invoke the vt update callback when /dev/vcs* is written to
  ...

66 files changed:
Documentation/devices.txt
Documentation/filesystems/proc.txt
MAINTAINERS
arch/arm/include/asm/ioctls.h
arch/avr32/include/asm/ioctls.h
arch/cris/include/asm/ioctls.h
arch/frv/include/asm/ioctls.h
arch/h8300/include/asm/ioctls.h
arch/ia64/hp/sim/simserial.c
arch/ia64/include/asm/ioctls.h
arch/m32r/include/asm/ioctls.h
arch/mips/alchemy/common/platform.c
arch/mips/alchemy/common/power.c
arch/mn10300/include/asm/ioctls.h
arch/s390/include/asm/ioctls.h
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/amiserial.c
drivers/char/cyclades.c
drivers/char/ip2/ip2main.c
drivers/char/mxser.c
drivers/char/nozomi.c
drivers/char/pcmcia/synclink_cs.c
drivers/char/pty.c
drivers/char/synclink.c
drivers/char/synclink_gt.c
drivers/char/synclinkmp.c
drivers/char/tty_io.c
drivers/char/ttyprintk.c [new file with mode: 0644]
drivers/char/vc_screen.c
drivers/char/vt.c
drivers/input/serio/serport.c
drivers/net/usb/hso.c
drivers/serial/68360serial.c
drivers/serial/8250.c
drivers/serial/Kconfig
drivers/serial/altera_uart.c
drivers/serial/bfin_sport_uart.c
drivers/serial/imx.c
drivers/serial/jsm/jsm_driver.c
drivers/serial/max3107.c
drivers/serial/mfd.c
drivers/serial/mrst_max3110.c
drivers/serial/mrst_max3110.h
drivers/serial/serial_core.c
drivers/serial/uartlite.c
drivers/usb/serial/ark3116.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/io_tables.h
drivers/usb/serial/io_ti.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/ssu100.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb-serial.c
fs/proc/proc_tty.c
include/asm-generic/ioctls.h
include/linux/altera_uart.h
include/linux/selection.h
include/linux/serial_8250.h
include/linux/serial_core.h
include/linux/tty.h
include/linux/tty_driver.h
include/linux/usb/serial.h
net/bluetooth/rfcomm/tty.c

index d0d1df6..6a08fd7 100644 (file)
@@ -239,6 +239,7 @@ Your cooperation is appreciated.
                  0 = /dev/tty          Current TTY device
                  1 = /dev/console      System console
                  2 = /dev/ptmx         PTY master multiplex
+                 3 = /dev/ttyprintk    User messages via printk TTY device
                 64 = /dev/cua0         Callout device for ttyS0
                    ...
                255 = /dev/cua191       Callout device for ttyS191
index a6aca87..98223a6 100644 (file)
@@ -1075,6 +1075,7 @@ Table 1-11: Files in /proc/tty
  drivers       list of drivers and their usage                
  ldiscs        registered line disciplines                    
  driver/serial usage statistic and status of single tty lines 
+ consoles      registered system console lines
 ..............................................................................
 
 To see  which  tty's  are  currently in use, you can simply look into the file
@@ -1093,6 +1094,37 @@ To see  which  tty's  are  currently in use, you can simply look into the file
   /dev/tty             /dev/tty        5       0 system:/dev/tty 
   unknown              /dev/tty        4    1-63 console 
 
+To see which character device lines are currently used for the system console
+/dev/console, you may simply look into the file /proc/tty/consoles:
+
+  > cat /proc/tty/consoles
+  tty0                 -WU (ECp)       4:7
+  ttyS0                -W- (Ep)        4:64
+
+The columns are:
+
+  device               name of the device
+  operations           R = can do read operations
+                       W = can do write operations
+                       U = can do unblank
+  flags                E = it is enabled
+                       C = it is prefered console
+                       B = it is primary boot console
+                       p = it is used for printk buffer
+                       b = it is not a TTY but a Braille device
+                       a = it is safe to use when cpu is offline
+                       * = it is standard input of the reading process
+  major:minor          major and minor number of the device separated by a colon
+
+If the reading process holds /dev/console open at the regular standard input
+stream the active device will be marked by an asterisk:
+
+  > cat /proc/tty/consoles < /dev/console
+  tty0                 -WU (ECp*)      4:7
+  ttyS0                -W- (Ep)        4:64
+  > tty
+  /dev/pts/3
+
 
 1.8 Miscellaneous kernel statistics in /proc/stat
 -------------------------------------------------
index fd19b54..060e32a 100644 (file)
@@ -157,9 +157,11 @@ S: Maintained
 F:     drivers/net/r8169.c
 
 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
+M:     Greg Kroah-Hartman <gregkh@suse.de>
 L:     linux-serial@vger.kernel.org
 W:     http://serial.sourceforge.net
-S:     Orphan
+S:     Maintained
+T:     quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
 F:     drivers/serial/8250*
 F:     include/linux/serial_8250.h
 
@@ -3353,6 +3355,12 @@ F:       fs/jbd*/
 F:     include/linux/ext*jbd*.h
 F:     include/linux/jbd*.h
 
+JSM Neo PCI based serial card
+M:     Breno Leitao <leitao@linux.vnet.ibm.com>
+L:     linux-serial@vger.kernel.org
+S:     Maintained
+F:     drivers/serial/jsm/
+
 K8TEMP HARDWARE MONITORING DRIVER
 M:     Rudolf Marek <r.marek@assembler.cz>
 L:     lm-sensors@lm-sensors.org
index 0b30894..9c96298 100644 (file)
@@ -1,89 +1,8 @@
 #ifndef __ASM_ARM_IOCTLS_H
 #define __ASM_ARM_IOCTLS_H
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS         0x5401
-#define TCSETS         0x5402
-#define TCSETSW                0x5403
-#define TCSETSF                0x5404
-#define TCGETA         0x5405
-#define TCSETA         0x5406
-#define TCSETAW                0x5407
-#define TCSETAF                0x5408
-#define TCSBRK         0x5409
-#define TCXONC         0x540A
-#define TCFLSH         0x540B
-#define TIOCEXCL       0x540C
-#define TIOCNXCL       0x540D
-#define TIOCSCTTY      0x540E
-#define TIOCGPGRP      0x540F
-#define TIOCSPGRP      0x5410
-#define TIOCOUTQ       0x5411
-#define TIOCSTI                0x5412
-#define TIOCGWINSZ     0x5413
-#define TIOCSWINSZ     0x5414
-#define TIOCMGET       0x5415
-#define TIOCMBIS       0x5416
-#define TIOCMBIC       0x5417
-#define TIOCMSET       0x5418
-#define TIOCGSOFTCAR   0x5419
-#define TIOCSSOFTCAR   0x541A
-#define FIONREAD       0x541B
-#define TIOCINQ                FIONREAD
-#define TIOCLINUX      0x541C
-#define TIOCCONS       0x541D
-#define TIOCGSERIAL    0x541E
-#define TIOCSSERIAL    0x541F
-#define TIOCPKT                0x5420
-#define FIONBIO                0x5421
-#define TIOCNOTTY      0x5422
-#define TIOCSETD       0x5423
-#define TIOCGETD       0x5424
-#define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK       0x5427  /* BSD compatibility */
-#define TIOCCBRK       0x5428  /* BSD compatibility */
-#define TIOCGSID       0x5429  /* Return the session ID of FD */
-#define TCGETS2                _IOR('T',0x2A, struct termios2)
-#define TCSETS2                _IOW('T',0x2B, struct termios2)
-#define TCSETSW2       _IOW('T',0x2C, struct termios2)
-#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
-
-#define FIONCLEX       0x5450  /* these numbers need to be adjusted. */
-#define FIOCLEX                0x5451
-#define FIOASYNC       0x5452
-#define TIOCSERCONFIG  0x5453
-#define TIOCSERGWILD   0x5454
-#define TIOCSERSWILD   0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
 #define FIOQSIZE       0x545E
 
-/* Used for packet mode */
-#define TIOCPKT_DATA            0
-#define TIOCPKT_FLUSHREAD       1
-#define TIOCPKT_FLUSHWRITE      2
-#define TIOCPKT_STOP            4
-#define TIOCPKT_START           8
-#define TIOCPKT_NOSTOP         16
-#define TIOCPKT_DOSTOP         32
-#define TIOCPKT_IOCTL          64
-
-#define TIOCSER_TEMT   0x01    /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif
index b7dd324..909cf66 100644 (file)
@@ -1,90 +1,6 @@
 #ifndef __ASM_AVR32_IOCTLS_H
 #define __ASM_AVR32_IOCTLS_H
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS         0x5401
-#define TCSETS         0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */
-#define TCSETSW                0x5403
-#define TCSETSF                0x5404
-#define TCGETA         0x5405
-#define TCSETA         0x5406
-#define TCSETAW                0x5407
-#define TCSETAF                0x5408
-#define TCSBRK         0x5409
-#define TCXONC         0x540A
-#define TCFLSH         0x540B
-#define TIOCEXCL       0x540C
-#define TIOCNXCL       0x540D
-#define TIOCSCTTY      0x540E
-#define TIOCGPGRP      0x540F
-#define TIOCSPGRP      0x5410
-#define TIOCOUTQ       0x5411
-#define TIOCSTI                0x5412
-#define TIOCGWINSZ     0x5413
-#define TIOCSWINSZ     0x5414
-#define TIOCMGET       0x5415
-#define TIOCMBIS       0x5416
-#define TIOCMBIC       0x5417
-#define TIOCMSET       0x5418
-#define TIOCGSOFTCAR   0x5419
-#define TIOCSSOFTCAR   0x541A
-#define FIONREAD       0x541B
-#define TIOCINQ                FIONREAD
-#define TIOCLINUX      0x541C
-#define TIOCCONS       0x541D
-#define TIOCGSERIAL    0x541E
-#define TIOCSSERIAL    0x541F
-#define TIOCPKT                0x5420
-#define FIONBIO                0x5421
-#define TIOCNOTTY      0x5422
-#define TIOCSETD       0x5423
-#define TIOCGETD       0x5424
-#define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
-/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
-#define TIOCSBRK       0x5427  /* BSD compatibility */
-#define TIOCCBRK       0x5428  /* BSD compatibility */
-#define TIOCGSID       0x5429  /* Return the session ID of FD */
-#define TCGETS2                _IOR('T',0x2A, struct termios2)
-#define TCSETS2                _IOW('T',0x2B, struct termios2)
-#define TCSETSW2       _IOW('T',0x2C, struct termios2)
-#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
-
-#define FIONCLEX       0x5450
-#define FIOCLEX                0x5451
-#define FIOASYNC       0x5452
-#define TIOCSERCONFIG  0x5453
-#define TIOCSERGWILD   0x5454
-#define TIOCSERSWILD   0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
-#define FIOQSIZE       0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA            0
-#define TIOCPKT_FLUSHREAD       1
-#define TIOCPKT_FLUSHWRITE      2
-#define TIOCPKT_STOP            4
-#define TIOCPKT_START           8
-#define TIOCPKT_NOSTOP         16
-#define TIOCPKT_DOSTOP         32
-#define TIOCPKT_IOCTL          64
-
-#define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* __ASM_AVR32_IOCTLS_H */
index c9129ed..488fbb3 100644 (file)
@@ -1,93 +1,11 @@
 #ifndef __ARCH_CRIS_IOCTLS_H__
 #define __ARCH_CRIS_IOCTLS_H__
 
-/* verbatim copy of asm-i386/ioctls.h */
-
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS         0x5401
-#define TCSETS         0x5402
-#define TCSETSW                0x5403
-#define TCSETSF                0x5404
-#define TCGETA         0x5405
-#define TCSETA         0x5406
-#define TCSETAW                0x5407
-#define TCSETAF                0x5408
-#define TCSBRK         0x5409
-#define TCXONC         0x540A
-#define TCFLSH         0x540B
-#define TIOCEXCL       0x540C
-#define TIOCNXCL       0x540D
-#define TIOCSCTTY      0x540E
-#define TIOCGPGRP      0x540F
-#define TIOCSPGRP      0x5410
-#define TIOCOUTQ       0x5411
-#define TIOCSTI                0x5412
-#define TIOCGWINSZ     0x5413
-#define TIOCSWINSZ     0x5414
-#define TIOCMGET       0x5415
-#define TIOCMBIS       0x5416
-#define TIOCMBIC       0x5417
-#define TIOCMSET       0x5418
-#define TIOCGSOFTCAR   0x5419
-#define TIOCSSOFTCAR   0x541A
-#define FIONREAD       0x541B
-#define TIOCINQ                FIONREAD
-#define TIOCLINUX      0x541C
-#define TIOCCONS       0x541D
-#define TIOCGSERIAL    0x541E
-#define TIOCSSERIAL    0x541F
-#define TIOCPKT                0x5420
-#define FIONBIO                0x5421
-#define TIOCNOTTY      0x5422
-#define TIOCSETD       0x5423
-#define TIOCGETD       0x5424
-#define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK       0x5427  /* BSD compatibility */
-#define TIOCCBRK       0x5428  /* BSD compatibility */
-#define TIOCGSID       0x5429  /* Return the session ID of FD */
-#define TCGETS2                _IOR('T',0x2A, struct termios2)
-#define TCSETS2                _IOW('T',0x2B, struct termios2)
-#define TCSETSW2       _IOW('T',0x2C, struct termios2)
-#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
-#define FIOASYNC       0x5452
-#define TIOCSERCONFIG  0x5453
-#define TIOCSERGWILD   0x5454
-#define TIOCSERSWILD   0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
 #define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
-#define FIOQSIZE       0x5460
-
 #define TIOCSERSETRS485        0x5461  /* enable rs-485 (deprecated) */
 #define TIOCSERWRRS485 0x5462  /* write rs-485 */
 #define TIOCSRS485     0x5463  /* enable rs-485 */
-#define TIOCGRS485     0x542E  /* get rs-485 */
-
-/* Used for packet mode */
-#define TIOCPKT_DATA            0
-#define TIOCPKT_FLUSHREAD       1
-#define TIOCPKT_FLUSHWRITE      2
-#define TIOCPKT_STOP            4
-#define TIOCPKT_START           8
-#define TIOCPKT_NOSTOP         16
-#define TIOCPKT_DOSTOP         32
-#define TIOCPKT_IOCTL          64
 
-#define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif
index a993e37..2f9fb43 100644 (file)
@@ -1,88 +1,10 @@
 #ifndef __ASM_IOCTLS_H__
 #define __ASM_IOCTLS_H__
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS         0x5401
-#define TCSETS         0x5402
-#define TCSETSW                0x5403
-#define TCSETSF                0x5404
-#define TCGETA         0x5405
-#define TCSETA         0x5406
-#define TCSETAW                0x5407
-#define TCSETAF                0x5408
-#define TCSBRK         0x5409
-#define TCXONC         0x540A
-#define TCFLSH         0x540B
-#define TIOCEXCL       0x540C
-#define TIOCNXCL       0x540D
-#define TIOCSCTTY      0x540E
-#define TIOCGPGRP      0x540F
-#define TIOCSPGRP      0x5410
-#define TIOCOUTQ       0x5411
-#define TIOCSTI                0x5412
-#define TIOCGWINSZ     0x5413
-#define TIOCSWINSZ     0x5414
-#define TIOCMGET       0x5415
-#define TIOCMBIS       0x5416
-#define TIOCMBIC       0x5417
-#define TIOCMSET       0x5418
-#define TIOCGSOFTCAR   0x5419
-#define TIOCSSOFTCAR   0x541A
-#define FIONREAD       0x541B
-#define TIOCINQ                FIONREAD
-#define TIOCLINUX      0x541C
-#define TIOCCONS       0x541D
-#define TIOCGSERIAL    0x541E
-#define TIOCSSERIAL    0x541F
-#define TIOCPKT                0x5420
-#define FIONBIO                0x5421
-#define TIOCNOTTY      0x5422
-#define TIOCSETD       0x5423
-#define TIOCGETD       0x5424
-#define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
 #define TIOCTTYGSTRUCT 0x5426  /* For debugging only */
-#define TIOCSBRK       0x5427  /* BSD compatibility */
-#define TIOCCBRK       0x5428  /* BSD compatibility */
-#define TIOCGSID       0x5429  /* Return the session ID of FD */
-#define TCGETS2                _IOR('T',0x2A, struct termios2)
-#define TCSETS2                _IOW('T',0x2B, struct termios2)
-#define TCSETSW2       _IOW('T',0x2C, struct termios2)
-#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
-#define FIOASYNC       0x5452
-#define TIOCSERCONFIG  0x5453
-#define TIOCSERGWILD   0x5454
-#define TIOCSERSWILD   0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
 #define FIOQSIZE       0x545E
 
-/* Used for packet mode */
-#define TIOCPKT_DATA            0
-#define TIOCPKT_FLUSHREAD       1
-#define TIOCPKT_FLUSHWRITE      2
-#define TIOCPKT_STOP            4
-#define TIOCPKT_START           8
-#define TIOCPKT_NOSTOP         16
-#define TIOCPKT_DOSTOP         32
-#define TIOCPKT_IOCTL          64
-
-#define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* __ASM_IOCTLS_H__ */
 
index b6b249f..30eaed2 100644 (file)
@@ -1,87 +1,8 @@
 #ifndef __ARCH_H8300_IOCTLS_H__
 #define __ARCH_H8300_IOCTLS_H__
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS         0x5401
-#define TCSETS         0x5402
-#define TCSETSW                0x5403
-#define TCSETSF                0x5404
-#define TCGETA         0x5405
-#define TCSETA         0x5406
-#define TCSETAW                0x5407
-#define TCSETAF                0x5408
-#define TCSBRK         0x5409
-#define TCXONC         0x540A
-#define TCFLSH         0x540B
-#define TIOCEXCL       0x540C
-#define TIOCNXCL       0x540D
-#define TIOCSCTTY      0x540E
-#define TIOCGPGRP      0x540F
-#define TIOCSPGRP      0x5410
-#define TIOCOUTQ       0x5411
-#define TIOCSTI                0x5412
-#define TIOCGWINSZ     0x5413
-#define TIOCSWINSZ     0x5414
-#define TIOCMGET       0x5415
-#define TIOCMBIS       0x5416
-#define TIOCMBIC       0x5417
-#define TIOCMSET       0x5418
-#define TIOCGSOFTCAR   0x5419
-#define TIOCSSOFTCAR   0x541A
-#define FIONREAD       0x541B
-#define TIOCINQ                FIONREAD
-#define TIOCLINUX      0x541C
-#define TIOCCONS       0x541D
-#define TIOCGSERIAL    0x541E
-#define TIOCSSERIAL    0x541F
-#define TIOCPKT                0x5420
-#define FIONBIO                0x5421
-#define TIOCNOTTY      0x5422
-#define TIOCSETD       0x5423
-#define TIOCGETD       0x5424
-#define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
-#define TIOCTTYGSTRUCT 0x5426  /* For debugging only */
-#define TIOCSBRK       0x5427  /* BSD compatibility */
-#define TIOCCBRK       0x5428  /* BSD compatibility */
-#define TIOCGSID       0x5429  /* Return the session ID of FD */
-#define TCGETS2                _IOR('T',0x2A, struct termios2)
-#define TCSETS2                _IOW('T',0x2B, struct termios2)
-#define TCSETSW2       _IOW('T',0x2C, struct termios2)
-#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
-#define FIOASYNC       0x5452
-#define TIOCSERCONFIG  0x5453
-#define TIOCSERGWILD   0x5454
-#define TIOCSERSWILD   0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
 #define FIOQSIZE       0x545E
 
-/* Used for packet mode */
-#define TIOCPKT_DATA            0
-#define TIOCPKT_FLUSHREAD       1
-#define TIOCPKT_FLUSHWRITE      2
-#define TIOCPKT_STOP            4
-#define TIOCPKT_START           8
-#define TIOCPKT_NOSTOP         16
-#define TIOCPKT_DOSTOP         32
-#define TIOCPKT_IOCTL          64
-
-#define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* __ARCH_H8300_IOCTLS_H__ */
index 1e8d71a..13633da 100644 (file)
@@ -395,7 +395,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
 {
        if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
            (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
-           (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+           (cmd != TIOCMIWAIT)) {
                if (tty->flags & (1 << TTY_IO_ERROR))
                    return -EIO;
        }
@@ -433,16 +433,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
                case TIOCMIWAIT:
                        printk(KERN_INFO "rs_ioctl: TIOCMIWAIT: called\n");
                        return 0;
-               /*
-                * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-                * Return: write counters to the user passed counter struct
-                * NB: both 1->0 and 0->1 transitions are counted except for
-                *     RI where only 0->1 is counted.
-                */
-               case TIOCGICOUNT:
-                       printk(KERN_INFO "rs_ioctl: TIOCGICOUNT called\n");
-                       return 0;
-
                case TIOCSERGWILD:
                case TIOCSERSWILD:
                        /* "setserial -W" is called in Debian boot */
index b79c385..f3aab55 100644 (file)
@@ -1,93 +1,6 @@
 #ifndef _ASM_IA64_IOCTLS_H
 #define _ASM_IA64_IOCTLS_H
 
-/*
- * Based on <asm-i386/ioctls.h>
- *
- * Modified 1998, 1999, 2002
- *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS         0x5401
-#define TCSETS         0x5402  /* Clashes with SNDCTL_TMR_START sound ioctl */
-#define TCSETSW                0x5403
-#define TCSETSF                0x5404
-#define TCGETA         0x5405
-#define TCSETA         0x5406
-#define TCSETAW                0x5407
-#define TCSETAF                0x5408
-#define TCSBRK         0x5409
-#define TCXONC         0x540A
-#define TCFLSH         0x540B
-#define TIOCEXCL       0x540C
-#define TIOCNXCL       0x540D
-#define TIOCSCTTY      0x540E
-#define TIOCGPGRP      0x540F
-#define TIOCSPGRP      0x5410
-#define TIOCOUTQ       0x5411
-#define TIOCSTI                0x5412
-#define TIOCGWINSZ     0x5413
-#define TIOCSWINSZ     0x5414
-#define TIOCMGET       0x5415
-#define TIOCMBIS       0x5416
-#define TIOCMBIC       0x5417
-#define TIOCMSET       0x5418
-#define TIOCGSOFTCAR   0x5419
-#define TIOCSSOFTCAR   0x541A
-#define FIONREAD       0x541B
-#define TIOCINQ                FIONREAD
-#define TIOCLINUX      0x541C
-#define TIOCCONS       0x541D
-#define TIOCGSERIAL    0x541E
-#define TIOCSSERIAL    0x541F
-#define TIOCPKT                0x5420
-#define FIONBIO                0x5421
-#define TIOCNOTTY      0x5422
-#define TIOCSETD       0x5423
-#define TIOCGETD       0x5424
-#define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK       0x5427  /* BSD compatibility */
-#define TIOCCBRK       0x5428  /* BSD compatibility */
-#define TIOCGSID       0x5429  /* Return the session ID of FD */
-#define TCGETS2                _IOR('T',0x2A, struct termios2)
-#define TCSETS2                _IOW('T',0x2B, struct termios2)
-#define TCSETSW2       _IOW('T',0x2C, struct termios2)
-#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
-#define FIOASYNC       0x5452
-#define TIOCSERCONFIG  0x5453
-#define TIOCSERGWILD   0x5454
-#define TIOCSERSWILD   0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
-#define FIOQSIZE       0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA            0
-#define TIOCPKT_FLUSHREAD       1
-#define TIOCPKT_FLUSHWRITE      2
-#define TIOCPKT_STOP            4
-#define TIOCPKT_START           8
-#define TIOCPKT_NOSTOP         16
-#define TIOCPKT_DOSTOP         32
-#define TIOCPKT_IOCTL          64
-
-#define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* _ASM_IA64_IOCTLS_H */
index 6628806..349bf87 100644 (file)
@@ -1,87 +1,6 @@
 #ifndef __ARCH_M32R_IOCTLS_H__
 #define __ARCH_M32R_IOCTLS_H__
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS         0x5401
-#define TCSETS         0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */
-#define TCSETSW                0x5403
-#define TCSETSF                0x5404
-#define TCGETA         0x5405
-#define TCSETA         0x5406
-#define TCSETAW                0x5407
-#define TCSETAF                0x5408
-#define TCSBRK         0x5409
-#define TCXONC         0x540A
-#define TCFLSH         0x540B
-#define TIOCEXCL       0x540C
-#define TIOCNXCL       0x540D
-#define TIOCSCTTY      0x540E
-#define TIOCGPGRP      0x540F
-#define TIOCSPGRP      0x5410
-#define TIOCOUTQ       0x5411
-#define TIOCSTI                0x5412
-#define TIOCGWINSZ     0x5413
-#define TIOCSWINSZ     0x5414
-#define TIOCMGET       0x5415
-#define TIOCMBIS       0x5416
-#define TIOCMBIC       0x5417
-#define TIOCMSET       0x5418
-#define TIOCGSOFTCAR   0x5419
-#define TIOCSSOFTCAR   0x541A
-#define FIONREAD       0x541B
-#define TIOCINQ                FIONREAD
-#define TIOCLINUX      0x541C
-#define TIOCCONS       0x541D
-#define TIOCGSERIAL    0x541E
-#define TIOCSSERIAL    0x541F
-#define TIOCPKT                0x5420
-#define FIONBIO                0x5421
-#define TIOCNOTTY      0x5422
-#define TIOCSETD       0x5423
-#define TIOCGETD       0x5424
-#define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
-/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
-#define TIOCSBRK       0x5427  /* BSD compatibility */
-#define TIOCCBRK       0x5428  /* BSD compatibility */
-#define TIOCGSID       0x5429  /* Return the session ID of FD */
-#define TCGETS2                _IOR('T',0x2A, struct termios2)
-#define TCSETS2                _IOW('T',0x2B, struct termios2)
-#define TCSETSW2       _IOW('T',0x2C, struct termios2)
-#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
-#define FIOASYNC       0x5452
-#define TIOCSERCONFIG  0x5453
-#define TIOCSERGWILD   0x5454
-#define TIOCSERSWILD   0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
-#define FIOQSIZE       0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA            0
-#define TIOCPKT_FLUSHREAD       1
-#define TIOCPKT_FLUSHWRITE      2
-#define TIOCPKT_STOP            4
-#define TIOCPKT_START           8
-#define TIOCPKT_NOSTOP         16
-#define TIOCPKT_DOSTOP         32
-#define TIOCPKT_IOCTL          64
-
-#define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* __ARCH_M32R_IOCTLS_H__ */
index 1dc55ee..3691630 100644 (file)
 
 #include <prom.h>
 
+static void alchemy_8250_pm(struct uart_port *port, unsigned int state,
+                           unsigned int old_state)
+{
+       switch (state) {
+       case 0:
+               if ((__raw_readl(port->membase + UART_MOD_CNTRL) & 3) != 3) {
+                       /* power-on sequence as suggested in the databooks */
+                       __raw_writel(0, port->membase + UART_MOD_CNTRL);
+                       wmb();
+                       __raw_writel(1, port->membase + UART_MOD_CNTRL);
+                       wmb();
+               }
+               __raw_writel(3, port->membase + UART_MOD_CNTRL); /* full on */
+               wmb();
+               serial8250_do_pm(port, state, old_state);
+               break;
+       case 3:         /* power off */
+               serial8250_do_pm(port, state, old_state);
+               __raw_writel(0, port->membase + UART_MOD_CNTRL);
+               wmb();
+               break;
+       default:
+               serial8250_do_pm(port, state, old_state);
+               break;
+       }
+}
+
 #define PORT(_base, _irq)                                      \
        {                                                       \
                .mapbase        = _base,                        \
@@ -33,6 +60,7 @@
                .flags          = UPF_SKIP_TEST | UPF_IOREMAP | \
                                  UPF_FIXED_TYPE,               \
                .type           = PORT_16550A,                  \
+               .pm             = alchemy_8250_pm,              \
        }
 
 static struct plat_serial8250_port au1x00_uart_data[] = {
index 5ef06a1..e5916a5 100644 (file)
  * We only have to save/restore registers that aren't otherwise
  * done as part of a driver pm_* function.
  */
-static unsigned int sleep_uart0_inten;
-static unsigned int sleep_uart0_fifoctl;
-static unsigned int sleep_uart0_linectl;
-static unsigned int sleep_uart0_clkdiv;
-static unsigned int sleep_uart0_enable;
 static unsigned int sleep_usb[2];
 static unsigned int sleep_sys_clocks[5];
 static unsigned int sleep_sys_pinfunc;
@@ -62,22 +57,6 @@ static unsigned int sleep_static_memctlr[4][3];
 
 static void save_core_regs(void)
 {
-       extern void save_au1xxx_intctl(void);
-       extern void pm_eth0_shutdown(void);
-
-       /*
-        * Do the serial ports.....these really should be a pm_*
-        * registered function by the driver......but of course the
-        * standard serial driver doesn't understand our Au1xxx
-        * unique registers.
-        */
-       sleep_uart0_inten = au_readl(UART0_ADDR + UART_IER);
-       sleep_uart0_fifoctl = au_readl(UART0_ADDR + UART_FCR);
-       sleep_uart0_linectl = au_readl(UART0_ADDR + UART_LCR);
-       sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK);
-       sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL);
-       au_sync();
-
 #ifndef CONFIG_SOC_AU1200
        /* Shutdown USB host/device. */
        sleep_usb[0] = au_readl(USB_HOST_CONFIG);
@@ -175,20 +154,6 @@ static void restore_core_regs(void)
        au_writel(sleep_static_memctlr[3][0], MEM_STCFG3);
        au_writel(sleep_static_memctlr[3][1], MEM_STTIME3);
        au_writel(sleep_static_memctlr[3][2], MEM_STADDR3);
-
-       /*
-        * Enable the UART if it was enabled before sleep.
-        * I guess I should define module control bits........
-        */
-       if (sleep_uart0_enable & 0x02) {
-               au_writel(0, UART0_ADDR + UART_MOD_CNTRL); au_sync();
-               au_writel(1, UART0_ADDR + UART_MOD_CNTRL); au_sync();
-               au_writel(3, UART0_ADDR + UART_MOD_CNTRL); au_sync();
-               au_writel(sleep_uart0_inten, UART0_ADDR + UART_IER); au_sync();
-               au_writel(sleep_uart0_fifoctl, UART0_ADDR + UART_FCR); au_sync();
-               au_writel(sleep_uart0_linectl, UART0_ADDR + UART_LCR); au_sync();
-               au_writel(sleep_uart0_clkdiv, UART0_ADDR + UART_CLK); au_sync();
-       }
 }
 
 void au_sleep(void)
index cb8cf19..0212f4b 100644 (file)
@@ -1,88 +1,6 @@
 #ifndef _ASM_IOCTLS_H
 #define _ASM_IOCTLS_H
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS         0x5401
-#define TCSETS         0x5402
-#define TCSETSW                0x5403
-#define TCSETSF                0x5404
-#define TCGETA         0x5405
-#define TCSETA         0x5406
-#define TCSETAW                0x5407
-#define TCSETAF                0x5408
-#define TCSBRK         0x5409
-#define TCXONC         0x540A
-#define TCFLSH         0x540B
-#define TIOCEXCL       0x540C
-#define TIOCNXCL       0x540D
-#define TIOCSCTTY      0x540E
-#define TIOCGPGRP      0x540F
-#define TIOCSPGRP      0x5410
-#define TIOCOUTQ       0x5411
-#define TIOCSTI                0x5412
-#define TIOCGWINSZ     0x5413
-#define TIOCSWINSZ     0x5414
-#define TIOCMGET       0x5415
-#define TIOCMBIS       0x5416
-#define TIOCMBIC       0x5417
-#define TIOCMSET       0x5418
-#define TIOCGSOFTCAR   0x5419
-#define TIOCSSOFTCAR   0x541A
-#define FIONREAD       0x541B
-#define TIOCINQ                FIONREAD
-#define TIOCLINUX      0x541C
-#define TIOCCONS       0x541D
-#define TIOCGSERIAL    0x541E
-#define TIOCSSERIAL    0x541F
-#define TIOCPKT                0x5420
-#define FIONBIO                0x5421
-#define TIOCNOTTY      0x5422
-#define TIOCSETD       0x5423
-#define TIOCGETD       0x5424
-#define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
-/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
-#define TIOCSBRK       0x5427  /* BSD compatibility */
-#define TIOCCBRK       0x5428  /* BSD compatibility */
-#define TIOCGSID       0x5429  /* Return the session ID of FD */
-#define TCGETS2                _IOR('T', 0x2A, struct termios2)
-#define TCSETS2                _IOW('T', 0x2B, struct termios2)
-#define TCSETSW2       _IOW('T', 0x2C, struct termios2)
-#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
-#define FIOASYNC       0x5452
-#define TIOCSERCONFIG  0x5453
-#define TIOCSERGWILD   0x5454
-#define TIOCSERSWILD   0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
-#define FIOQSIZE       0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA            0
-#define TIOCPKT_FLUSHREAD       1
-#define TIOCPKT_FLUSHWRITE      2
-#define TIOCPKT_STOP            4
-#define TIOCPKT_START           8
-#define TIOCPKT_NOSTOP         16
-#define TIOCPKT_DOSTOP         32
-#define TIOCPKT_IOCTL          64
-
-#define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* _ASM_IOCTLS_H */
index 2f3d873..960a4c1 100644 (file)
@@ -1,94 +1,8 @@
-/*
- *  include/asm-s390/ioctls.h
- *
- *  S390 version
- *
- *  Derived from "include/asm-i386/ioctls.h"
- */
-
 #ifndef __ARCH_S390_IOCTLS_H__
 #define __ARCH_S390_IOCTLS_H__
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS         0x5401
-#define TCSETS         0x5402
-#define TCSETSW                0x5403
-#define TCSETSF                0x5404
-#define TCGETA         0x5405
-#define TCSETA         0x5406
-#define TCSETAW                0x5407
-#define TCSETAF                0x5408
-#define TCSBRK         0x5409
-#define TCXONC         0x540A
-#define TCFLSH         0x540B
-#define TIOCEXCL       0x540C
-#define TIOCNXCL       0x540D
-#define TIOCSCTTY      0x540E
-#define TIOCGPGRP      0x540F
-#define TIOCSPGRP      0x5410
-#define TIOCOUTQ       0x5411
-#define TIOCSTI                0x5412
-#define TIOCGWINSZ     0x5413
-#define TIOCSWINSZ     0x5414
-#define TIOCMGET       0x5415
-#define TIOCMBIS       0x5416
-#define TIOCMBIC       0x5417
-#define TIOCMSET       0x5418
-#define TIOCGSOFTCAR   0x5419
-#define TIOCSSOFTCAR   0x541A
-#define FIONREAD       0x541B
-#define TIOCINQ                FIONREAD
-#define TIOCLINUX      0x541C
-#define TIOCCONS       0x541D
-#define TIOCGSERIAL    0x541E
-#define TIOCSSERIAL    0x541F
-#define TIOCPKT                0x5420
-#define FIONBIO                0x5421
-#define TIOCNOTTY      0x5422
-#define TIOCSETD       0x5423
-#define TIOCGETD       0x5424
-#define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK       0x5427  /* BSD compatibility */
-#define TIOCCBRK       0x5428  /* BSD compatibility */
-#define TIOCGSID       0x5429  /* Return the session ID of FD */
-#define TCGETS2                _IOR('T',0x2A, struct termios2)
-#define TCSETS2                _IOW('T',0x2B, struct termios2)
-#define TCSETSW2       _IOW('T',0x2C, struct termios2)
-#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
-#define FIOASYNC       0x5452
-#define TIOCSERCONFIG  0x5453
-#define TIOCSERGWILD   0x5454
-#define TIOCSERSWILD   0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
 #define FIOQSIZE       0x545E
 
-/* Used for packet mode */
-#define TIOCPKT_DATA            0
-#define TIOCPKT_FLUSHREAD       1
-#define TIOCPKT_FLUSHWRITE      2
-#define TIOCPKT_STOP            4
-#define TIOCPKT_START           8
-#define TIOCPKT_NOSTOP         16
-#define TIOCPKT_DOSTOP         32
-#define TIOCPKT_IOCTL          64
-
-#define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif
index 3d44ec7..43d3395 100644 (file)
@@ -493,6 +493,21 @@ config LEGACY_PTY_COUNT
          When not in use, each legacy PTY occupies 12 bytes on 32-bit
          architectures and 24 bytes on 64-bit architectures.
 
+config TTY_PRINTK
+       bool "TTY driver to output user messages via printk"
+       depends on EMBEDDED
+       default n
+       ---help---
+         If you say Y here, the support for writing user messages (i.e.
+         console messages) via printk is available.
+
+         The feature is useful to inline user messages with kernel
+         messages.
+         In order to use this feature, you should output user messages
+         to /dev/ttyprintk or redirect console to this TTY.
+
+         If unsure, say N.
+
 config BRIQ_PANEL
        tristate 'Total Impact briQ front panel driver'
        depends on PPC_CHRP
index dc96416..3a9c014 100644 (file)
@@ -12,6 +12,7 @@ obj-y  += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o t
 obj-y                          += tty_mutex.o
 obj-$(CONFIG_LEGACY_PTYS)      += pty.o
 obj-$(CONFIG_UNIX98_PTYS)      += pty.o
+obj-$(CONFIG_TTY_PRINTK)       += ttyprintk.o
 obj-y                          += misc.o
 obj-$(CONFIG_VT)               += vt_ioctl.o vc_screen.o selection.o keyboard.o
 obj-$(CONFIG_BFIN_JTAG_COMM)   += bfin_jtag_comm.o
index a11c8c9..b0a7046 100644 (file)
@@ -1263,6 +1263,36 @@ static int rs_break(struct tty_struct *tty, int break_state)
        return 0;
 }
 
+/*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ *     RI where only 0->1 is counted.
+ */
+static int rs_get_icount(struct tty_struct *tty,
+                               struct serial_icounter_struct *icount)
+{
+       struct async_struct *info = tty->driver_data;
+       struct async_icount cnow;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       cnow = info->state->icount;
+       local_irq_restore(flags);
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+       icount->rx = cnow.rx;
+       icount->tx = cnow.tx;
+       icount->frame = cnow.frame;
+       icount->overrun = cnow.overrun;
+       icount->parity = cnow.parity;
+       icount->brk = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
+
+       return 0;
+}
 
 static int rs_ioctl(struct tty_struct *tty, struct file * file,
                    unsigned int cmd, unsigned long arg)
@@ -1332,31 +1362,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
                        }
                        /* NOTREACHED */
 
-               /* 
-                * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-                * Return: write counters to the user passed counter struct
-                * NB: both 1->0 and 0->1 transitions are counted except for
-                *     RI where only 0->1 is counted.
-                */
-               case TIOCGICOUNT:
-                       local_irq_save(flags);
-                       cnow = info->state->icount;
-                       local_irq_restore(flags);
-                       icount.cts = cnow.cts;
-                       icount.dsr = cnow.dsr;
-                       icount.rng = cnow.rng;
-                       icount.dcd = cnow.dcd;
-                       icount.rx = cnow.rx;
-                       icount.tx = cnow.tx;
-                       icount.frame = cnow.frame;
-                       icount.overrun = cnow.overrun;
-                       icount.parity = cnow.parity;
-                       icount.brk = cnow.brk;
-                       icount.buf_overrun = cnow.buf_overrun;
-
-                       if (copy_to_user(argp, &icount, sizeof(icount)))
-                               return -EFAULT;
-                       return 0;
                case TIOCSERGWILD:
                case TIOCSERSWILD:
                        /* "setserial -W" is called in Debian boot */
@@ -1958,6 +1963,7 @@ static const struct tty_operations serial_ops = {
        .wait_until_sent = rs_wait_until_sent,
        .tiocmget = rs_tiocmget,
        .tiocmset = rs_tiocmset,
+       .get_icount = rs_get_icount,
        .proc_fops = &rs_proc_fops,
 };
 
index 27aad94..4f152c2 100644 (file)
@@ -2790,29 +2790,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
                 * NB: both 1->0 and 0->1 transitions are counted except for
                 *     RI where only 0->1 is counted.
                 */
-       case TIOCGICOUNT: {
-               struct serial_icounter_struct sic = { };
-
-               spin_lock_irqsave(&info->card->card_lock, flags);
-               cnow = info->icount;
-               spin_unlock_irqrestore(&info->card->card_lock, flags);
-
-               sic.cts = cnow.cts;
-               sic.dsr = cnow.dsr;
-               sic.rng = cnow.rng;
-               sic.dcd = cnow.dcd;
-               sic.rx = cnow.rx;
-               sic.tx = cnow.tx;
-               sic.frame = cnow.frame;
-               sic.overrun = cnow.overrun;
-               sic.parity = cnow.parity;
-               sic.brk = cnow.brk;
-               sic.buf_overrun = cnow.buf_overrun;
-
-               if (copy_to_user(argp, &sic, sizeof(sic)))
-                       ret_val = -EFAULT;
-               break;
-       }
        default:
                ret_val = -ENOIOCTLCMD;
        }
@@ -2823,6 +2800,31 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
        return ret_val;
 }                              /* cy_ioctl */
 
+static int cy_get_icount(struct tty_struct *tty,
+                               struct serial_icounter_struct *sic)
+{
+       struct cyclades_port *info = tty->driver_data;
+       struct cyclades_icount cnow;    /* Used to snapshot */
+       unsigned long flags;
+
+       spin_lock_irqsave(&info->card->card_lock, flags);
+       cnow = info->icount;
+       spin_unlock_irqrestore(&info->card->card_lock, flags);
+
+       sic->cts = cnow.cts;
+       sic->dsr = cnow.dsr;
+       sic->rng = cnow.rng;
+       sic->dcd = cnow.dcd;
+       sic->rx = cnow.rx;
+       sic->tx = cnow.tx;
+       sic->frame = cnow.frame;
+       sic->overrun = cnow.overrun;
+       sic->parity = cnow.parity;
+       sic->brk = cnow.brk;
+       sic->buf_overrun = cnow.buf_overrun;
+       return 0;
+}
+
 /*
  * This routine allows the tty driver to be notified when
  * device's termios settings have changed.  Note that a
@@ -4084,6 +4086,7 @@ static const struct tty_operations cy_ops = {
        .wait_until_sent = cy_wait_until_sent,
        .tiocmget = cy_tiocmget,
        .tiocmset = cy_tiocmset,
+       .get_icount = cy_get_icount,
        .proc_fops = &cyclades_proc_fops,
 };
 
index 64a439c..fcd02ba 100644 (file)
@@ -184,6 +184,8 @@ static void ip2_hangup(PTTY);
 static int  ip2_tiocmget(struct tty_struct *tty, struct file *file);
 static int  ip2_tiocmset(struct tty_struct *tty, struct file *file,
                         unsigned int set, unsigned int clear);
+static int ip2_get_icount(struct tty_struct *tty,
+               struct serial_icounter_struct *icount);
 
 static void set_irq(int, int);
 static void ip2_interrupt_bh(struct work_struct *work);
@@ -456,6 +458,7 @@ static const struct tty_operations ip2_ops = {
        .hangup          = ip2_hangup,
        .tiocmget        = ip2_tiocmget,
        .tiocmset        = ip2_tiocmset,
+       .get_icount      = ip2_get_icount,
        .proc_fops       = &ip2_proc_fops,
 };
 
@@ -2130,7 +2133,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
        i2ChanStrPtr pCh = DevTable[tty->index];
        i2eBordStrPtr pB;
        struct async_icount cprev, cnow;        /* kernel counter temps */
-       struct serial_icounter_struct __user *p_cuser;
        int rc = 0;
        unsigned long flags;
        void __user *argp = (void __user *)arg;
@@ -2299,34 +2301,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
                break;
 
        /*
-        * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-        * Return: write counters to the user passed counter struct
-        * NB: both 1->0 and 0->1 transitions are counted except for RI where
-        * only 0->1 is counted. The controller is quite capable of counting
-        * both, but this done to preserve compatibility with the standard
-        * serial driver.
-        */
-       case TIOCGICOUNT:
-               ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
-
-               write_lock_irqsave(&pB->read_fifo_spinlock, flags);
-               cnow = pCh->icount;
-               write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
-               p_cuser = argp;
-               rc = put_user(cnow.cts, &p_cuser->cts);
-               rc = put_user(cnow.dsr, &p_cuser->dsr);
-               rc = put_user(cnow.rng, &p_cuser->rng);
-               rc = put_user(cnow.dcd, &p_cuser->dcd);
-               rc = put_user(cnow.rx, &p_cuser->rx);
-               rc = put_user(cnow.tx, &p_cuser->tx);
-               rc = put_user(cnow.frame, &p_cuser->frame);
-               rc = put_user(cnow.overrun, &p_cuser->overrun);
-               rc = put_user(cnow.parity, &p_cuser->parity);
-               rc = put_user(cnow.brk, &p_cuser->brk);
-               rc = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
-               break;
-
-       /*
         * The rest are not supported by this driver. By returning -ENOIOCTLCMD they
         * will be passed to the line discipline for it to handle.
         */
@@ -2350,6 +2324,46 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
        return rc;
 }
 
+static int ip2_get_icount(struct tty_struct *tty,
+               struct serial_icounter_struct *icount)
+{
+       i2ChanStrPtr pCh = DevTable[tty->index];
+       i2eBordStrPtr pB;
+       struct async_icount cnow;       /* kernel counter temp */
+       unsigned long flags;
+
+       if ( pCh == NULL )
+               return -ENODEV;
+
+       pB = pCh->pMyBord;
+
+       /*
+        * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+        * Return: write counters to the user passed counter struct
+        * NB: both 1->0 and 0->1 transitions are counted except for RI where
+        * only 0->1 is counted. The controller is quite capable of counting
+        * both, but this done to preserve compatibility with the standard
+        * serial driver.
+        */
+
+       write_lock_irqsave(&pB->read_fifo_spinlock, flags);
+       cnow = pCh->icount;
+       write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
+
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+       icount->rx = cnow.rx;
+       icount->tx = cnow.tx;
+       icount->frame = cnow.frame;
+       icount->overrun = cnow.overrun;
+       icount->parity = cnow.parity;
+       icount->brk = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
+       return 0;
+}
+
 /******************************************************************************/
 /* Function:   GetSerialInfo()                                                */
 /* Parameters: Pointer to channel structure                                   */
index 3fc89da..463df27 100644 (file)
@@ -1700,7 +1700,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
                return 0;
        }
 
-       if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT &&
+       if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT &&
                        test_bit(TTY_IO_ERROR, &tty->flags))
                return -EIO;
 
@@ -1730,32 +1730,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
 
                return wait_event_interruptible(info->port.delta_msr_wait,
                                mxser_cflags_changed(info, arg, &cnow));
-       /*
-        * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-        * Return: write counters to the user passed counter struct
-        * NB: both 1->0 and 0->1 transitions are counted except for
-        *     RI where only 0->1 is counted.
-        */
-       case TIOCGICOUNT: {
-               struct serial_icounter_struct icnt = { 0 };
-               spin_lock_irqsave(&info->slock, flags);
-               cnow = info->icount;
-               spin_unlock_irqrestore(&info->slock, flags);
-
-               icnt.frame = cnow.frame;
-               icnt.brk = cnow.brk;
-               icnt.overrun = cnow.overrun;
-               icnt.buf_overrun = cnow.buf_overrun;
-               icnt.parity = cnow.parity;
-               icnt.rx = cnow.rx;
-               icnt.tx = cnow.tx;
-               icnt.cts = cnow.cts;
-               icnt.dsr = cnow.dsr;
-               icnt.rng = cnow.rng;
-               icnt.dcd = cnow.dcd;
-
-               return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0;
-       }
        case MOXA_HighSpeedOn:
                return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
        case MOXA_SDS_RSTICOUNTER:
@@ -1828,6 +1802,39 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
        return 0;
 }
 
+       /*
+        * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+        * Return: write counters to the user passed counter struct
+        * NB: both 1->0 and 0->1 transitions are counted except for
+        *     RI where only 0->1 is counted.
+        */
+
+static int mxser_get_icount(struct tty_struct *tty,
+               struct serial_icounter_struct *icount)
+
+{
+       struct mxser_port *info = tty->driver_data;
+       struct async_icount cnow;
+       unsigned long flags;
+
+       spin_lock_irqsave(&info->slock, flags);
+       cnow = info->icount;
+       spin_unlock_irqrestore(&info->slock, flags);
+
+       icount->frame = cnow.frame;
+       icount->brk = cnow.brk;
+       icount->overrun = cnow.overrun;
+       icount->buf_overrun = cnow.buf_overrun;
+       icount->parity = cnow.parity;
+       icount->rx = cnow.rx;
+       icount->tx = cnow.tx;
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+       return 0;
+}
+
 static void mxser_stoprx(struct tty_struct *tty)
 {
        struct mxser_port *info = tty->driver_data;
@@ -2326,6 +2333,7 @@ static const struct tty_operations mxser_ops = {
        .wait_until_sent = mxser_wait_until_sent,
        .tiocmget = mxser_tiocmget,
        .tiocmset = mxser_tiocmset,
+       .get_icount = mxser_get_icount,
 };
 
 struct tty_port_operations mxser_port_ops = {
@@ -2339,20 +2347,11 @@ struct tty_port_operations mxser_port_ops = {
  * The MOXA Smartio/Industio serial driver boot-time initialization code!
  */
 
-static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev,
-               unsigned int irq)
+static void mxser_release_ISA_res(struct mxser_board *brd)
 {
-       if (irq)
-               free_irq(brd->irq, brd);
-       if (pdev != NULL) {     /* PCI */
-#ifdef CONFIG_PCI
-               pci_release_region(pdev, 2);
-               pci_release_region(pdev, 3);
-#endif
-       } else {
-               release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
-               release_region(brd->vector, 1);
-       }
+       free_irq(brd->irq, brd);
+       release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
+       release_region(brd->vector, 1);
 }
 
 static int __devinit mxser_initbrd(struct mxser_board *brd,
@@ -2397,13 +2396,11 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
 
        retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser",
                        brd);
-       if (retval) {
+       if (retval)
                printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
                        "conflict with another device.\n",
                        brd->info->name, brd->irq);
-               /* We hold resources, we need to release them. */
-               mxser_release_res(brd, pdev, 0);
-       }
+
        return retval;
 }
 
@@ -2555,7 +2552,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
        ioaddress = pci_resource_start(pdev, 2);
        retval = pci_request_region(pdev, 2, "mxser(IO)");
        if (retval)
-               goto err;
+               goto err_dis;
 
        brd->info = &mxser_cards[ent->driver_data];
        for (i = 0; i < brd->info->nports; i++)
@@ -2565,7 +2562,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
        ioaddress = pci_resource_start(pdev, 3);
        retval = pci_request_region(pdev, 3, "mxser(vector)");
        if (retval)
-               goto err_relio;
+               goto err_zero;
        brd->vector = ioaddress;
 
        /* irq */
@@ -2608,7 +2605,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
        /* mxser_initbrd will hook ISR. */
        retval = mxser_initbrd(brd, pdev);
        if (retval)
-               goto err_null;
+               goto err_rel3;
 
        for (i = 0; i < brd->info->nports; i++)
                tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
@@ -2616,10 +2613,13 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
        pci_set_drvdata(pdev, brd);
 
        return 0;
-err_relio:
-       pci_release_region(pdev, 2);
-err_null:
+err_rel3:
+       pci_release_region(pdev, 3);
+err_zero:
        brd->info = NULL;
+       pci_release_region(pdev, 2);
+err_dis:
+       pci_disable_device(pdev);
 err:
        return retval;
 #else
@@ -2629,14 +2629,19 @@ err:
 
 static void __devexit mxser_remove(struct pci_dev *pdev)
 {
+#ifdef CONFIG_PCI
        struct mxser_board *brd = pci_get_drvdata(pdev);
        unsigned int i;
 
        for (i = 0; i < brd->info->nports; i++)
                tty_unregister_device(mxvar_sdriver, brd->idx + i);
 
-       mxser_release_res(brd, pdev, 1);
+       free_irq(pdev->irq, brd);
+       pci_release_region(pdev, 2);
+       pci_release_region(pdev, 3);
+       pci_disable_device(pdev);
        brd->info = NULL;
+#endif
 }
 
 static struct pci_driver mxser_driver = {
@@ -2741,7 +2746,7 @@ static void __exit mxser_module_exit(void)
 
        for (i = 0; i < MXSER_BOARDS; i++)
                if (mxser_boards[i].info != NULL)
-                       mxser_release_res(&mxser_boards[i], NULL, 1);
+                       mxser_release_ISA_res(&mxser_boards[i]);
 }
 
 module_init(mxser_module_init);
index 817169c..dd3f9b1 100644 (file)
@@ -1804,24 +1804,24 @@ static int ntty_cflags_changed(struct port *port, unsigned long flags,
        return ret;
 }
 
-static int ntty_ioctl_tiocgicount(struct port *port, void __user *argp)
+static int ntty_tiocgicount(struct tty_struct *tty,
+                               struct serial_icounter_struct *icount)
 {
+       struct port *port = tty->driver_data;
        const struct async_icount cnow = port->tty_icount;
-       struct serial_icounter_struct icount;
-
-       icount.cts = cnow.cts;
-       icount.dsr = cnow.dsr;
-       icount.rng = cnow.rng;
-       icount.dcd = cnow.dcd;
-       icount.rx = cnow.rx;
-       icount.tx = cnow.tx;
-       icount.frame = cnow.frame;
-       icount.overrun = cnow.overrun;
-       icount.parity = cnow.parity;
-       icount.brk = cnow.brk;
-       icount.buf_overrun = cnow.buf_overrun;
-
-       return copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0;
+
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+       icount->rx = cnow.rx;
+       icount->tx = cnow.tx;
+       icount->frame = cnow.frame;
+       icount->overrun = cnow.overrun;
+       icount->parity = cnow.parity;
+       icount->brk = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
+       return 0;
 }
 
 static int ntty_ioctl(struct tty_struct *tty, struct file *file,
@@ -1840,9 +1840,7 @@ static int ntty_ioctl(struct tty_struct *tty, struct file *file,
                rval = wait_event_interruptible(port->tty_wait,
                                ntty_cflags_changed(port, arg, &cprev));
                break;
-       } case TIOCGICOUNT:
-               rval = ntty_ioctl_tiocgicount(port, argp);
-               break;
+       }
        default:
                DBG1("ERR: 0x%08X, %d", cmd, cmd);
                break;
@@ -1922,6 +1920,7 @@ static const struct tty_operations tty_ops = {
        .chars_in_buffer = ntty_chars_in_buffer,
        .tiocmget = ntty_tiocmget,
        .tiocmset = ntty_tiocmset,
+       .get_icount = ntty_tiocgicount,
        .install = ntty_install,
        .cleanup = ntty_cleanup,
 };
index be18100..bfc10f8 100644 (file)
@@ -2191,6 +2191,32 @@ static int mgslpc_break(struct tty_struct *tty, int break_state)
        return 0;
 }
 
+static int mgslpc_get_icount(struct tty_struct *tty,
+                               struct serial_icounter_struct *icount)
+{
+       MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
+       struct mgsl_icount cnow;        /* kernel counter temps */
+       unsigned long flags;
+
+       spin_lock_irqsave(&info->lock,flags);
+       cnow = info->icount;
+       spin_unlock_irqrestore(&info->lock,flags);
+
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+       icount->rx = cnow.rx;
+       icount->tx = cnow.tx;
+       icount->frame = cnow.frame;
+       icount->overrun = cnow.overrun;
+       icount->parity = cnow.parity;
+       icount->brk = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
+
+       return 0;
+}
+
 /* Service an IOCTL request
  *
  * Arguments:
@@ -2206,11 +2232,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
                        unsigned int cmd, unsigned long arg)
 {
        MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
-       int error;
-       struct mgsl_icount cnow;        /* kernel counter temps */
-       struct serial_icounter_struct __user *p_cuser;  /* user space */
        void __user *argp = (void __user *)arg;
-       unsigned long flags;
 
        if (debug_level >= DEBUG_LEVEL_INFO)
                printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
@@ -2220,7 +2242,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
                return -ENODEV;
 
        if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-           (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+           (cmd != TIOCMIWAIT)) {
                if (tty->flags & (1 << TTY_IO_ERROR))
                    return -EIO;
        }
@@ -2250,34 +2272,6 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
                return wait_events(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;
-               PUT_USER(error,cnow.cts, &p_cuser->cts);
-               if (error) return error;
-               PUT_USER(error,cnow.dsr, &p_cuser->dsr);
-               if (error) return error;
-               PUT_USER(error,cnow.rng, &p_cuser->rng);
-               if (error) return error;
-               PUT_USER(error,cnow.dcd, &p_cuser->dcd);
-               if (error) return error;
-               PUT_USER(error,cnow.rx, &p_cuser->rx);
-               if (error) return error;
-               PUT_USER(error,cnow.tx, &p_cuser->tx);
-               if (error) return error;
-               PUT_USER(error,cnow.frame, &p_cuser->frame);
-               if (error) return error;
-               PUT_USER(error,cnow.overrun, &p_cuser->overrun);
-               if (error) return error;
-               PUT_USER(error,cnow.parity, &p_cuser->parity);
-               if (error) return error;
-               PUT_USER(error,cnow.brk, &p_cuser->brk);
-               if (error) return error;
-               PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
-               if (error) return error;
-               return 0;
        default:
                return -ENOIOCTLCMD;
        }
index c350d01..923a485 100644 (file)
@@ -676,7 +676,9 @@ static int ptmx_open(struct inode *inode, struct file *filp)
 
        set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
 
-       tty_add_file(tty, filp);
+       retval = tty_add_file(tty, filp);
+       if (retval)
+               goto out;
 
        retval = devpts_pty_new(inode, tty->link);
        if (retval)
index a2a5800..3a6824f 100644 (file)
@@ -2925,6 +2925,38 @@ static int mgsl_break(struct tty_struct *tty, int break_state)
        
 }      /* end of mgsl_break() */
 
+/*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ *     RI where only 0->1 is counted.
+ */
+static int msgl_get_icount(struct tty_struct *tty,
+                               struct serial_icounter_struct *icount)
+
+{
+       struct mgsl_struct * info = tty->driver_data;
+       struct mgsl_icount cnow;        /* kernel counter temps */
+       unsigned long flags;
+
+       spin_lock_irqsave(&info->irq_spinlock,flags);
+       cnow = info->icount;
+       spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+       icount->rx = cnow.rx;
+       icount->tx = cnow.tx;
+       icount->frame = cnow.frame;
+       icount->overrun = cnow.overrun;
+       icount->parity = cnow.parity;
+       icount->brk = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
+       return 0;
+}
+
 /* mgsl_ioctl()        Service an IOCTL request
  *     
  * Arguments:
@@ -2949,7 +2981,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
                return -ENODEV;
 
        if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-           (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+           (cmd != TIOCMIWAIT)) {
                if (tty->flags & (1 << TTY_IO_ERROR))
                    return -EIO;
        }
@@ -2959,11 +2991,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
 
 static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
 {
-       int error;
-       struct mgsl_icount cnow;        /* kernel counter temps */
        void __user *argp = (void __user *)arg;
-       struct serial_icounter_struct __user *p_cuser;  /* user space */
-       unsigned long flags;
        
        switch (cmd) {
                case MGSL_IOCGPARAMS:
@@ -2992,40 +3020,6 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne
                case TIOCMIWAIT:
                        return modem_input_wait(info,(int)arg);
 
-               /* 
-                * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-                * Return: write counters to the user passed counter struct
-                * NB: both 1->0 and 0->1 transitions are counted except for
-                *     RI where only 0->1 is counted.
-                */
-               case TIOCGICOUNT:
-                       spin_lock_irqsave(&info->irq_spinlock,flags);
-                       cnow = info->icount;
-                       spin_unlock_irqrestore(&info->irq_spinlock,flags);
-                       p_cuser = argp;
-                       PUT_USER(error,cnow.cts, &p_cuser->cts);
-                       if (error) return error;
-                       PUT_USER(error,cnow.dsr, &p_cuser->dsr);
-                       if (error) return error;
-                       PUT_USER(error,cnow.rng, &p_cuser->rng);
-                       if (error) return error;
-                       PUT_USER(error,cnow.dcd, &p_cuser->dcd);
-                       if (error) return error;
-                       PUT_USER(error,cnow.rx, &p_cuser->rx);
-                       if (error) return error;
-                       PUT_USER(error,cnow.tx, &p_cuser->tx);
-                       if (error) return error;
-                       PUT_USER(error,cnow.frame, &p_cuser->frame);
-                       if (error) return error;
-                       PUT_USER(error,cnow.overrun, &p_cuser->overrun);
-                       if (error) return error;
-                       PUT_USER(error,cnow.parity, &p_cuser->parity);
-                       if (error) return error;
-                       PUT_USER(error,cnow.brk, &p_cuser->brk);
-                       if (error) return error;
-                       PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
-                       if (error) return error;
-                       return 0;
                default:
                        return -ENOIOCTLCMD;
        }
@@ -4328,6 +4322,7 @@ static const struct tty_operations mgsl_ops = {
        .hangup = mgsl_hangup,
        .tiocmget = tiocmget,
        .tiocmset = tiocmset,
+       .get_icount = msgl_get_icount,
        .proc_fops = &mgsl_proc_fops,
 };
 
index e63b830..1746d91 100644 (file)
@@ -1032,9 +1032,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
                 unsigned int cmd, unsigned long arg)
 {
        struct slgt_info *info = tty->driver_data;
-       struct mgsl_icount cnow;        /* kernel counter temps */
-       struct serial_icounter_struct __user *p_cuser;  /* user space */
-       unsigned long flags;
        void __user *argp = (void __user *)arg;
        int ret;
 
@@ -1043,7 +1040,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
        DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
 
        if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-           (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+           (cmd != TIOCMIWAIT)) {
                if (tty->flags & (1 << TTY_IO_ERROR))
                    return -EIO;
        }
@@ -1053,24 +1050,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
                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:
@@ -1117,6 +1096,33 @@ static int ioctl(struct tty_struct *tty, struct file *file,
        return ret;
 }
 
+static int get_icount(struct tty_struct *tty,
+                               struct serial_icounter_struct *icount)
+
+{
+       struct slgt_info *info = tty->driver_data;
+       struct mgsl_icount cnow;        /* kernel counter temps */
+       unsigned long flags;
+
+       spin_lock_irqsave(&info->lock,flags);
+       cnow = info->icount;
+       spin_unlock_irqrestore(&info->lock,flags);
+
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+       icount->rx = cnow.rx;
+       icount->tx = cnow.tx;
+       icount->frame = cnow.frame;
+       icount->overrun = cnow.overrun;
+       icount->parity = cnow.parity;
+       icount->brk = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
+
+       return 0;
+}
+
 /*
  * support for 32 bit ioctl calls on 64 bit systems
  */
@@ -1206,10 +1212,6 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file,
        case MGSL_IOCSGPIO:
        case MGSL_IOCGGPIO:
        case MGSL_IOCWAITGPIO:
-       case TIOCGICOUNT:
-               rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg)));
-               break;
-
        case MGSL_IOCSTXIDLE:
        case MGSL_IOCTXENABLE:
        case MGSL_IOCRXENABLE:
@@ -3642,6 +3644,7 @@ static const struct tty_operations ops = {
        .hangup = hangup,
        .tiocmget = tiocmget,
        .tiocmset = tiocmset,
+       .get_icount = get_icount,
        .proc_fops = &synclink_gt_proc_fops,
 };
 
index e56caf7..2f9eb4b 100644 (file)
@@ -1258,10 +1258,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
                 unsigned int cmd, unsigned long arg)
 {
        SLMP_INFO *info = tty->driver_data;
-       int error;
-       struct mgsl_icount cnow;        /* kernel counter temps */
-       struct serial_icounter_struct __user *p_cuser;  /* user space */
-       unsigned long flags;
        void __user *argp = (void __user *)arg;
 
        if (debug_level >= DEBUG_LEVEL_INFO)
@@ -1272,7 +1268,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
                return -ENODEV;
 
        if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-           (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+           (cmd != TIOCMIWAIT)) {
                if (tty->flags & (1 << TTY_IO_ERROR))
                    return -EIO;
        }
@@ -1310,40 +1306,38 @@ static int ioctl(struct tty_struct *tty, struct file *file,
                 * NB: both 1->0 and 0->1 transitions are counted except for
                 *     RI where only 0->1 is counted.
                 */
-       case TIOCGICOUNT:
-               spin_lock_irqsave(&info->lock,flags);
-               cnow = info->icount;
-               spin_unlock_irqrestore(&info->lock,flags);
-               p_cuser = argp;
-               PUT_USER(error,cnow.cts, &p_cuser->cts);
-               if (error) return error;
-               PUT_USER(error,cnow.dsr, &p_cuser->dsr);
-               if (error) return error;
-               PUT_USER(error,cnow.rng, &p_cuser->rng);
-               if (error) return error;
-               PUT_USER(error,cnow.dcd, &p_cuser->dcd);
-               if (error) return error;
-               PUT_USER(error,cnow.rx, &p_cuser->rx);
-               if (error) return error;
-               PUT_USER(error,cnow.tx, &p_cuser->tx);
-               if (error) return error;
-               PUT_USER(error,cnow.frame, &p_cuser->frame);
-               if (error) return error;
-               PUT_USER(error,cnow.overrun, &p_cuser->overrun);
-               if (error) return error;
-               PUT_USER(error,cnow.parity, &p_cuser->parity);
-               if (error) return error;
-               PUT_USER(error,cnow.brk, &p_cuser->brk);
-               if (error) return error;
-               PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
-               if (error) return error;
-               return 0;
        default:
                return -ENOIOCTLCMD;
        }
        return 0;
 }
 
+static int get_icount(struct tty_struct *tty,
+                               struct serial_icounter_struct *icount)
+{
+       SLMP_INFO *info = tty->driver_data;
+       struct mgsl_icount cnow;        /* kernel counter temps */
+       unsigned long flags;
+
+       spin_lock_irqsave(&info->lock,flags);
+       cnow = info->icount;
+       spin_unlock_irqrestore(&info->lock,flags);
+
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+       icount->rx = cnow.rx;
+       icount->tx = cnow.tx;
+       icount->frame = cnow.frame;
+       icount->overrun = cnow.overrun;
+       icount->parity = cnow.parity;
+       icount->brk = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
+
+       return 0;
+}
+
 /*
  * /proc fs routines....
  */
@@ -3909,6 +3903,7 @@ static const struct tty_operations ops = {
        .hangup = hangup,
        .tiocmget = tiocmget,
        .tiocmset = tiocmset,
+       .get_icount = get_icount,
        .proc_fops = &synclinkmp_proc_fops,
 };
 
index 613c852..c05c5af 100644 (file)
@@ -96,6 +96,7 @@
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/seq_file.h>
+#include <linux/serial.h>
 
 #include <linux/uaccess.h>
 #include <asm/system.h>
@@ -183,6 +184,8 @@ struct tty_struct *alloc_tty_struct(void)
 
 void free_tty_struct(struct tty_struct *tty)
 {
+       if (tty->dev)
+               put_device(tty->dev);
        kfree(tty->write_buf);
        tty_buffer_free_all(tty);
        kfree(tty);
@@ -194,12 +197,13 @@ static inline struct tty_struct *file_tty(struct file *file)
 }
 
 /* Associate a new file with the tty structure */
-void tty_add_file(struct tty_struct *tty, struct file *file)
+int tty_add_file(struct tty_struct *tty, struct file *file)
 {
        struct tty_file_private *priv;
 
-       /* XXX: must implement proper error handling in callers */
-       priv = kmalloc(sizeof(*priv), GFP_KERNEL|__GFP_NOFAIL);
+       priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
 
        priv->tty = tty;
        priv->file = file;
@@ -208,6 +212,8 @@ void tty_add_file(struct tty_struct *tty, struct file *file)
        spin_lock(&tty_files_lock);
        list_add(&priv->list, &tty->tty_files);
        spin_unlock(&tty_files_lock);
+
+       return 0;
 }
 
 /* Delete file from its tty */
@@ -1875,7 +1881,11 @@ got_driver:
                return PTR_ERR(tty);
        }
 
-       tty_add_file(tty, filp);
+       retval = tty_add_file(tty, filp);
+       if (retval) {
+               tty_unlock();
+               return retval;
+       }
 
        check_tty_count(tty, "tty_open");
        if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
@@ -2502,6 +2512,20 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
        return tty->ops->tiocmset(tty, file, set, clear);
 }
 
+static int tty_tiocgicount(struct tty_struct *tty, void __user *arg)
+{
+       int retval = -EINVAL;
+       struct serial_icounter_struct icount;
+       memset(&icount, 0, sizeof(icount));
+       if (tty->ops->get_icount)
+               retval = tty->ops->get_icount(tty, &icount);
+       if (retval != 0)
+               return retval;
+       if (copy_to_user(arg, &icount, sizeof(icount)))
+               return -EFAULT;
+       return 0;
+}
+
 struct tty_struct *tty_pair_get_tty(struct tty_struct *tty)
 {
        if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
@@ -2622,6 +2646,12 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case TIOCMBIC:
        case TIOCMBIS:
                return tty_tiocmset(tty, file, cmd, p);
+       case TIOCGICOUNT:
+               retval = tty_tiocgicount(tty, p);
+               /* For the moment allow fall through to the old method */
+               if (retval != -EINVAL)
+                       return retval;
+               break;
        case TCFLSH:
                switch (arg) {
                case TCIFLUSH:
@@ -2783,6 +2813,20 @@ void do_SAK(struct tty_struct *tty)
 
 EXPORT_SYMBOL(do_SAK);
 
+static int dev_match_devt(struct device *dev, void *data)
+{
+       dev_t *devt = data;
+       return dev->devt == *devt;
+}
+
+/* Must put_device() after it's unused! */
+static struct device *tty_get_device(struct tty_struct *tty)
+{
+       dev_t devt = tty_devnum(tty);
+       return class_find_device(tty_class, NULL, &devt, dev_match_devt);
+}
+
+
 /**
  *     initialize_tty_struct
  *     @tty: tty to initialize
@@ -2823,6 +2867,7 @@ void initialize_tty_struct(struct tty_struct *tty,
        tty->ops = driver->ops;
        tty->index = idx;
        tty_line_name(driver, idx, tty->name);
+       tty->dev = tty_get_device(tty);
 }
 
 /**
@@ -2980,6 +3025,7 @@ int tty_register_driver(struct tty_driver *driver)
        int i;
        dev_t dev;
        void **p = NULL;
+       struct device *d;
 
        if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
                p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL);
@@ -3027,12 +3073,31 @@ int tty_register_driver(struct tty_driver *driver)
        mutex_unlock(&tty_mutex);
 
        if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) {
-               for (i = 0; i < driver->num; i++)
-                   tty_register_device(driver, i, NULL);
+               for (i = 0; i < driver->num; i++) {
+                       d = tty_register_device(driver, i, NULL);
+                       if (IS_ERR(d)) {
+                               error = PTR_ERR(d);
+                               goto err;
+                       }
+               }
        }
        proc_tty_register_driver(driver);
        driver->flags |= TTY_DRIVER_INSTALLED;
        return 0;
+
+err:
+       for (i--; i >= 0; i--)
+               tty_unregister_device(driver, i);
+
+       mutex_lock(&tty_mutex);
+       list_del(&driver->tty_drivers);
+       mutex_unlock(&tty_mutex);
+
+       unregister_chrdev_region(dev, driver->num);
+       driver->ttys = NULL;
+       driver->termios = NULL;
+       kfree(p);
+       return error;
 }
 
 EXPORT_SYMBOL(tty_register_driver);
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
new file mode 100644 (file)
index 0000000..c40c161
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ *  linux/drivers/char/ttyprintk.c
+ *
+ *  Copyright (C) 2010  Samo Pogacnik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the smems of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+/*
+ * This pseudo device allows user to make printk messages. It is possible
+ * to store "console" messages inline with kernel messages for better analyses
+ * of the boot process, for example.
+ */
+
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+
+struct ttyprintk_port {
+       struct tty_port port;
+       struct mutex port_write_mutex;
+};
+
+static struct ttyprintk_port tpk_port;
+
+/*
+ * Our simple preformatting supports transparent output of (time-stamped)
+ * printk messages (also suitable for logging service):
+ * - any cr is replaced by nl
+ * - adds a ttyprintk source tag in front of each line
+ * - too long message is fragmeted, with '\'nl between fragments
+ * - TPK_STR_SIZE isn't really the write_room limiting factor, bcause
+ *   it is emptied on the fly during preformatting.
+ */
+#define TPK_STR_SIZE 508 /* should be bigger then max expected line length */
+#define TPK_MAX_ROOM 4096 /* we could assume 4K for instance */
+static const char *tpk_tag = "[U] "; /* U for User */
+static int tpk_curr;
+
+static int tpk_printk(const unsigned char *buf, int count)
+{
+       static char tmp[TPK_STR_SIZE + 4];
+       int i = tpk_curr;
+
+       if (buf == NULL) {
+               /* flush tmp[] */
+               if (tpk_curr > 0) {
+                       /* non nl or cr terminated message - add nl */
+                       tmp[tpk_curr + 0] = '\n';
+                       tmp[tpk_curr + 1] = '\0';
+                       printk(KERN_INFO "%s%s", tpk_tag, tmp);
+                       tpk_curr = 0;
+               }
+               return i;
+       }
+
+       for (i = 0; i < count; i++) {
+               tmp[tpk_curr] = buf[i];
+               if (tpk_curr < TPK_STR_SIZE) {
+                       switch (buf[i]) {
+                       case '\r':
+                               /* replace cr with nl */
+                               tmp[tpk_curr + 0] = '\n';
+                               tmp[tpk_curr + 1] = '\0';
+                               printk(KERN_INFO "%s%s", tpk_tag, tmp);
+                               tpk_curr = 0;
+                               if (buf[i + 1] == '\n')
+                                       i++;
+                               break;
+                       case '\n':
+                               tmp[tpk_curr + 1] = '\0';
+                               printk(KERN_INFO "%s%s", tpk_tag, tmp);
+                               tpk_curr = 0;
+                               break;
+                       default:
+                               tpk_curr++;
+                       }
+               } else {
+                       /* end of tmp buffer reached: cut the message in two */
+                       tmp[tpk_curr + 1] = '\\';
+                       tmp[tpk_curr + 2] = '\n';
+                       tmp[tpk_curr + 3] = '\0';
+                       printk(KERN_INFO "%s%s", tpk_tag, tmp);
+                       tpk_curr = 0;
+               }
+       }
+
+       return count;
+}
+
+/*
+ * TTY operations open function.
+ */
+static int tpk_open(struct tty_struct *tty, struct file *filp)
+{
+       tty->driver_data = &tpk_port;
+
+       return tty_port_open(&tpk_port.port, tty, filp);
+}
+
+/*
+ * TTY operations close function.
+ */
+static void tpk_close(struct tty_struct *tty, struct file *filp)
+{
+       struct ttyprintk_port *tpkp = tty->driver_data;
+
+       mutex_lock(&tpkp->port_write_mutex);
+       /* flush tpk_printk buffer */
+       tpk_printk(NULL, 0);
+       mutex_unlock(&tpkp->port_write_mutex);
+
+       tty_port_close(&tpkp->port, tty, filp);
+}
+
+/*
+ * TTY operations write function.
+ */
+static int tpk_write(struct tty_struct *tty,
+               const unsigned char *buf, int count)
+{
+       struct ttyprintk_port *tpkp = tty->driver_data;
+       int ret;
+
+
+       /* exclusive use of tpk_printk within this tty */
+       mutex_lock(&tpkp->port_write_mutex);
+       ret = tpk_printk(buf, count);
+       mutex_unlock(&tpkp->port_write_mutex);
+
+       return ret;
+}
+
+/*
+ * TTY operations write_room function.
+ */
+static int tpk_write_room(struct tty_struct *tty)
+{
+       return TPK_MAX_ROOM;
+}
+
+/*
+ * TTY operations ioctl function.
+ */
+static int tpk_ioctl(struct tty_struct *tty, struct file *file,
+                       unsigned int cmd, unsigned long arg)
+{
+       struct ttyprintk_port *tpkp = tty->driver_data;
+
+       if (!tpkp)
+               return -EINVAL;
+
+       switch (cmd) {
+       /* Stop TIOCCONS */
+       case TIOCCONS:
+               return -EOPNOTSUPP;
+       default:
+               return -ENOIOCTLCMD;
+       }
+       return 0;
+}
+
+static const struct tty_operations ttyprintk_ops = {
+       .open = tpk_open,
+       .close = tpk_close,
+       .write = tpk_write,
+       .write_room = tpk_write_room,
+       .ioctl = tpk_ioctl,
+};
+
+struct tty_port_operations null_ops = { };
+
+static struct tty_driver *ttyprintk_driver;
+
+static int __init ttyprintk_init(void)
+{
+       int ret = -ENOMEM;
+       void *rp;
+
+       ttyprintk_driver = alloc_tty_driver(1);
+       if (!ttyprintk_driver)
+               return ret;
+
+       ttyprintk_driver->owner = THIS_MODULE;
+       ttyprintk_driver->driver_name = "ttyprintk";
+       ttyprintk_driver->name = "ttyprintk";
+       ttyprintk_driver->major = TTYAUX_MAJOR;
+       ttyprintk_driver->minor_start = 3;
+       ttyprintk_driver->num = 1;
+       ttyprintk_driver->type = TTY_DRIVER_TYPE_CONSOLE;
+       ttyprintk_driver->init_termios = tty_std_termios;
+       ttyprintk_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET;
+       ttyprintk_driver->flags = TTY_DRIVER_RESET_TERMIOS |
+               TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+       tty_set_operations(ttyprintk_driver, &ttyprintk_ops);
+
+       ret = tty_register_driver(ttyprintk_driver);
+       if (ret < 0) {
+               printk(KERN_ERR "Couldn't register ttyprintk driver\n");
+               goto error;
+       }
+
+       /* create our unnumbered device */
+       rp = device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 3), NULL,
+                               ttyprintk_driver->name);
+       if (IS_ERR(rp)) {
+               printk(KERN_ERR "Couldn't create ttyprintk device\n");
+               ret = PTR_ERR(rp);
+               goto error;
+       }
+
+       tty_port_init(&tpk_port.port);
+       tpk_port.port.ops = &null_ops;
+       mutex_init(&tpk_port.port_write_mutex);
+
+       return 0;
+
+error:
+       put_tty_driver(ttyprintk_driver);
+       ttyprintk_driver = NULL;
+       return ret;
+}
+module_init(ttyprintk_init);
index bcce46c..273ab44 100644 (file)
 #include <linux/console.h>
 #include <linux/device.h>
 #include <linux/smp_lock.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/notifier.h>
 
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 #undef addr
 #define HEADER_SIZE    4
 
+struct vcs_poll_data {
+       struct notifier_block notifier;
+       unsigned int cons_num;
+       bool seen_last_update;
+       wait_queue_head_t waitq;
+       struct fasync_struct *fasync;
+};
+
+static int
+vcs_notifier(struct notifier_block *nb, unsigned long code, void *_param)
+{
+       struct vt_notifier_param *param = _param;
+       struct vc_data *vc = param->vc;
+       struct vcs_poll_data *poll =
+               container_of(nb, struct vcs_poll_data, notifier);
+       int currcons = poll->cons_num;
+
+       if (code != VT_UPDATE)
+               return NOTIFY_DONE;
+
+       if (currcons == 0)
+               currcons = fg_console;
+       else
+               currcons--;
+       if (currcons != vc->vc_num)
+               return NOTIFY_DONE;
+
+       poll->seen_last_update = false;
+       wake_up_interruptible(&poll->waitq);
+       kill_fasync(&poll->fasync, SIGIO, POLL_IN);
+       return NOTIFY_OK;
+}
+
+static void
+vcs_poll_data_free(struct vcs_poll_data *poll)
+{
+       unregister_vt_notifier(&poll->notifier);
+       kfree(poll);
+}
+
+static struct vcs_poll_data *
+vcs_poll_data_get(struct file *file)
+{
+       struct vcs_poll_data *poll = file->private_data;
+
+       if (poll)
+               return poll;
+
+       poll = kzalloc(sizeof(*poll), GFP_KERNEL);
+       if (!poll)
+               return NULL;
+       poll->cons_num = iminor(file->f_path.dentry->d_inode) & 127;
+       init_waitqueue_head(&poll->waitq);
+       poll->notifier.notifier_call = vcs_notifier;
+       if (register_vt_notifier(&poll->notifier) != 0) {
+               kfree(poll);
+               return NULL;
+       }
+
+       /*
+        * This code may be called either through ->poll() or ->fasync().
+        * If we have two threads using the same file descriptor, they could
+        * both enter this function, both notice that the structure hasn't
+        * been allocated yet and go ahead allocating it in parallel, but
+        * only one of them must survive and be shared otherwise we'd leak
+        * memory with a dangling notifier callback.
+        */
+       spin_lock(&file->f_lock);
+       if (!file->private_data) {
+               file->private_data = poll;
+       } else {
+               /* someone else raced ahead of us */
+               vcs_poll_data_free(poll);
+               poll = file->private_data;
+       }
+       spin_unlock(&file->f_lock);
+
+       return poll;
+}
+
 static int
 vcs_size(struct inode *inode)
 {
@@ -102,6 +188,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
        struct inode *inode = file->f_path.dentry->d_inode;
        unsigned int currcons = iminor(inode);
        struct vc_data *vc;
+       struct vcs_poll_data *poll;
        long pos;
        long viewed, attr, read;
        int col, maxcol;
@@ -134,6 +221,9 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
        ret = -EINVAL;
        if (pos < 0)
                goto unlock_out;
+       poll = file->private_data;
+       if (count && poll)
+               poll->seen_last_update = true;
        read = 0;
        ret = 0;
        while (count) {
@@ -448,6 +538,8 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
        }
        *ppos += written;
        ret = written;
+       if (written)
+               vcs_scr_updated(vc);
 
 unlock_out:
        release_console_sem();
@@ -457,6 +549,37 @@ unlock_out:
        return ret;
 }
 
+static unsigned int
+vcs_poll(struct file *file, poll_table *wait)
+{
+       struct vcs_poll_data *poll = vcs_poll_data_get(file);
+       int ret = 0;
+
+       if (poll) {
+               poll_wait(file, &poll->waitq, wait);
+               if (!poll->seen_last_update)
+                       ret = POLLIN | POLLRDNORM;
+       }
+       return ret;
+}
+
+static int
+vcs_fasync(int fd, struct file *file, int on)
+{
+       struct vcs_poll_data *poll = file->private_data;
+
+       if (!poll) {
+               /* don't allocate anything if all we want is disable fasync */
+               if (!on)
+                       return 0;
+               poll = vcs_poll_data_get(file);
+               if (!poll)
+                       return -ENOMEM;
+       }
+
+       return fasync_helper(fd, file, on, &poll->fasync);
+}
+
 static int
 vcs_open(struct inode *inode, struct file *filp)
 {
@@ -470,11 +593,23 @@ vcs_open(struct inode *inode, struct file *filp)
        return ret;
 }
 
+static int vcs_release(struct inode *inode, struct file *file)
+{
+       struct vcs_poll_data *poll = file->private_data;
+
+       if (poll)
+               vcs_poll_data_free(poll);
+       return 0;
+}
+
 static const struct file_operations vcs_fops = {
        .llseek         = vcs_lseek,
        .read           = vcs_read,
        .write          = vcs_write,
+       .poll           = vcs_poll,
+       .fasync         = vcs_fasync,
        .open           = vcs_open,
+       .release        = vcs_release,
 };
 
 static struct class *vc_class;
index 281aada..a8ec48e 100644 (file)
@@ -4182,6 +4182,11 @@ void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org)
        }
 }
 
+void vcs_scr_updated(struct vc_data *vc)
+{
+       notify_update(vc);
+}
+
 /*
  *     Visible symbols for modules
  */
index 6d34511..6e362de 100644 (file)
@@ -165,6 +165,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
        serio->open = serport_serio_open;
        serio->close = serport_serio_close;
        serio->port_data = serport;
+       serio->dev.parent = tty->dev;
 
        serio_register_port(serport->serio);
        printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
index 1cd752f..b8e9572 100644 (file)
@@ -1645,11 +1645,11 @@ hso_wait_modem_status(struct hso_serial *serial, unsigned long arg)
  * NB: both 1->0 and 0->1 transitions are counted except for
  *     RI where only 0->1 is counted.
  */
-static int hso_get_count(struct hso_serial *serial,
-                         struct serial_icounter_struct __user *icnt)
+static int hso_get_count(struct tty_struct *tty,
+                 struct serial_icounter_struct *icount)
 {
-       struct serial_icounter_struct icount;
        struct uart_icount cnow;
+       struct hso_serial *serial = get_serial_by_tty(tty);
        struct hso_tiocmget  *tiocmget = serial->tiocmget;
 
        memset(&icount, 0, sizeof(struct serial_icounter_struct));
@@ -1660,19 +1660,19 @@ static int hso_get_count(struct hso_serial *serial,
        memcpy(&cnow, &tiocmget->icount, sizeof(struct uart_icount));
        spin_unlock_irq(&serial->serial_lock);
 
-       icount.cts         = cnow.cts;
-       icount.dsr         = cnow.dsr;
-       icount.rng         = cnow.rng;
-       icount.dcd         = cnow.dcd;
-       icount.rx          = cnow.rx;
-       icount.tx          = cnow.tx;
-       icount.frame       = cnow.frame;
-       icount.overrun     = cnow.overrun;
-       icount.parity      = cnow.parity;
-       icount.brk         = cnow.brk;
-       icount.buf_overrun = cnow.buf_overrun;
+       icount->cts         = cnow.cts;
+       icount->dsr         = cnow.dsr;
+       icount->rng         = cnow.rng;
+       icount->dcd         = cnow.dcd;
+       icount->rx          = cnow.rx;
+       icount->tx          = cnow.tx;
+       icount->frame       = cnow.frame;
+       icount->overrun     = cnow.overrun;
+       icount->parity      = cnow.parity;
+       icount->brk         = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
 
-       return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
+       return 0;
 }
 
 
@@ -1764,10 +1764,6 @@ static int hso_serial_ioctl(struct tty_struct *tty, struct file *file,
        case TIOCMIWAIT:
                ret = hso_wait_modem_status(serial, arg);
                break;
-
-       case TIOCGICOUNT:
-               ret = hso_get_count(serial, uarg);
-               break;
        default:
                ret = -ENOIOCTLCMD;
                break;
@@ -3300,6 +3296,7 @@ static const struct tty_operations hso_serial_ops = {
        .chars_in_buffer = hso_serial_chars_in_buffer,
        .tiocmget = hso_serial_tiocmget,
        .tiocmset = hso_serial_tiocmset,
+       .get_icount = hso_get_count,
        .unthrottle = hso_unthrottle
 };
 
index 0dff3bb..88b1335 100644 (file)
@@ -1381,6 +1381,30 @@ static void send_break(ser_info_t *info, unsigned int duration)
 }
 
 
+/*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ *     RI where only 0->1 is counted.
+ */
+static int rs_360_get_icount(struct tty_struct *tty,
+                               struct serial_icounter_struct *icount)
+{
+       ser_info_t *info = (ser_info_t *)tty->driver_data;
+       struct async_icount cnow;
+
+       local_irq_disable();
+       cnow = info->state->icount;
+       local_irq_enable();
+
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+
+       return 0;
+}
+
 static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
                    unsigned int cmd, unsigned long arg)
 {
@@ -1394,7 +1418,7 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
        if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
                return -ENODEV;
 
-       if ((cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+       if (cmd != TIOCMIWAIT) {
                if (tty->flags & (1 << TTY_IO_ERROR))
                    return -EIO;
        }
@@ -1477,31 +1501,6 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
                        return 0;
 #endif
 
-               /* 
-                * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-                * Return: write counters to the user passed counter struct
-                * NB: both 1->0 and 0->1 transitions are counted except for
-                *     RI where only 0->1 is counted.
-                */
-               case TIOCGICOUNT:
-                       local_irq_disable();
-                       cnow = info->state->icount;
-                       local_irq_enable();
-                       p_cuser = (struct serial_icounter_struct *) arg;
-/*                     error = put_user(cnow.cts, &p_cuser->cts); */
-/*                     if (error) return error; */
-/*                     error = put_user(cnow.dsr, &p_cuser->dsr); */
-/*                     if (error) return error; */
-/*                     error = put_user(cnow.rng, &p_cuser->rng); */
-/*                     if (error) return error; */
-/*                     error = put_user(cnow.dcd, &p_cuser->dcd); */
-/*                     if (error) return error; */
-
-                       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);
-                       return 0;
 
                default:
                        return -ENOIOCTLCMD;
index 24110f6..167c4a6 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/tty.h>
+#include <linux/ratelimit.h>
 #include <linux/tty_flip.h>
 #include <linux/serial_reg.h>
 #include <linux/serial_core.h>
@@ -154,12 +155,6 @@ struct uart_8250_port {
        unsigned char           lsr_saved_flags;
 #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
        unsigned char           msr_saved_flags;
-
-       /*
-        * We provide a per-port pm hook.
-        */
-       void                    (*pm)(struct uart_port *port,
-                                     unsigned int state, unsigned int old);
 };
 
 struct irq_info {
@@ -1606,8 +1601,8 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
 
                if (l == i->head && pass_counter++ > PASS_LIMIT) {
                        /* If we hit this, we're dead. */
-                       printk(KERN_ERR "serial8250: too much work for "
-                               "irq%d\n", irq);
+                       printk_ratelimited(KERN_ERR
+                               "serial8250: too much work for irq%d\n", irq);
                        break;
                }
        } while (l != end);
@@ -1722,12 +1717,6 @@ static void serial_unlink_irq_chain(struct uart_8250_port *up)
        mutex_unlock(&hash_mutex);
 }
 
-/* Base timer interval for polling */
-static inline int poll_timeout(int timeout)
-{
-       return timeout > 6 ? (timeout / 2 - 2) : 1;
-}
-
 /*
  * This function is used to handle ports that do not have an
  * interrupt.  This doesn't work very well for 16450's, but gives
@@ -1742,7 +1731,7 @@ static void serial8250_timeout(unsigned long data)
        iir = serial_in(up, UART_IIR);
        if (!(iir & UART_IIR_NO_INT))
                serial8250_handle_port(up);
-       mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
+       mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port));
 }
 
 static void serial8250_backup_timeout(unsigned long data)
@@ -1787,7 +1776,7 @@ static void serial8250_backup_timeout(unsigned long data)
 
        /* Standard timer interval plus 0.2s to keep the port running */
        mod_timer(&up->timer,
-               jiffies + poll_timeout(up->port.timeout) + HZ / 5);
+               jiffies + uart_poll_timeout(&up->port) + HZ / 5);
 }
 
 static unsigned int serial8250_tx_empty(struct uart_port *port)
@@ -1867,15 +1856,17 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits)
        unsigned int status, tmout = 10000;
 
        /* Wait up to 10ms for the character(s) to be sent. */
-       do {
+       for (;;) {
                status = serial_in(up, UART_LSR);
 
                up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
 
+               if ((status & bits) == bits)
+                       break;
                if (--tmout == 0)
                        break;
                udelay(1);
-       } while ((status & bits) != bits);
+       }
 
        /* Wait up to 1s for flow control if necessary */
        if (up->port.flags & UPF_CONS_FLOW) {
@@ -2069,7 +2060,7 @@ static int serial8250_startup(struct uart_port *port)
                up->timer.function = serial8250_backup_timeout;
                up->timer.data = (unsigned long)up;
                mod_timer(&up->timer, jiffies +
-                         poll_timeout(up->port.timeout) + HZ / 5);
+                       uart_poll_timeout(port) + HZ / 5);
        }
 
        /*
@@ -2079,7 +2070,7 @@ static int serial8250_startup(struct uart_port *port)
         */
        if (!is_real_interrupt(up->port.irq)) {
                up->timer.data = (unsigned long)up;
-               mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
+               mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
        } else {
                retval = serial_link_irq_chain(up);
                if (retval)
@@ -2440,16 +2431,24 @@ serial8250_set_ldisc(struct uart_port *port, int new)
                port->flags &= ~UPF_HARDPPS_CD;
 }
 
-static void
-serial8250_pm(struct uart_port *port, unsigned int state,
-             unsigned int oldstate)
+
+void serial8250_do_pm(struct uart_port *port, unsigned int state,
+                     unsigned int oldstate)
 {
        struct uart_8250_port *p = (struct uart_8250_port *)port;
 
        serial8250_set_sleep(p, state != 0);
+}
+EXPORT_SYMBOL(serial8250_do_pm);
 
-       if (p->pm)
-               p->pm(port, state, oldstate);
+static void
+serial8250_pm(struct uart_port *port, unsigned int state,
+             unsigned int oldstate)
+{
+       if (port->pm)
+               port->pm(port, state, oldstate);
+       else
+               serial8250_do_pm(port, state, oldstate);
 }
 
 static unsigned int serial8250_port_size(struct uart_8250_port *pt)
@@ -2674,6 +2673,16 @@ static struct uart_ops serial8250_pops = {
 
 static struct uart_8250_port serial8250_ports[UART_NR];
 
+static void (*serial8250_isa_config)(int port, struct uart_port *up,
+       unsigned short *capabilities);
+
+void serial8250_set_isa_configurator(
+       void (*v)(int port, struct uart_port *up, unsigned short *capabilities))
+{
+       serial8250_isa_config = v;
+}
+EXPORT_SYMBOL(serial8250_set_isa_configurator);
+
 static void __init serial8250_isa_init_ports(void)
 {
        struct uart_8250_port *up;
@@ -2719,6 +2728,9 @@ static void __init serial8250_isa_init_ports(void)
                up->port.regshift = old_serial_port[i].iomem_reg_shift;
                set_io_from_upio(&up->port);
                up->port.irqflags |= irqflag;
+               if (serial8250_isa_config != NULL)
+                       serial8250_isa_config(i, &up->port, &up->capabilities);
+
        }
 }
 
@@ -3010,6 +3022,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
                port.serial_in          = p->serial_in;
                port.serial_out         = p->serial_out;
                port.set_termios        = p->set_termios;
+               port.pm                 = p->pm;
                port.dev                = &dev->dev;
                port.irqflags           |= irqflag;
                ret = serial8250_register_port(&port);
@@ -3176,6 +3189,12 @@ int serial8250_register_port(struct uart_port *port)
                /*  Possibly override set_termios call */
                if (port->set_termios)
                        uart->port.set_termios = port->set_termios;
+               if (port->pm)
+                       uart->port.pm = port->pm;
+
+               if (serial8250_isa_config != NULL)
+                       serial8250_isa_config(0, &uart->port,
+                                       &uart->capabilities);
 
                ret = uart_add_one_port(&serial8250_reg, &uart->port);
                if (ret == 0)
index 3198c53..9278164 100644 (file)
@@ -718,13 +718,6 @@ config SERIAL_MRST_MAX3110
          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
index f8d8a00..7212162 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/console.h>
@@ -27,6 +28,8 @@
 #include <linux/altera_uart.h>
 
 #define DRV_NAME "altera_uart"
+#define SERIAL_ALTERA_MAJOR 204
+#define SERIAL_ALTERA_MINOR 213
 
 /*
  * Altera UART register definitions according to the Nios UART datasheet:
  */
 struct altera_uart {
        struct uart_port port;
+       struct timer_list tmr;
        unsigned int sigs;      /* Local copy of line sigs */
        unsigned short imr;     /* Local IMR mirror */
 };
 
+static u32 altera_uart_readl(struct uart_port *port, int reg)
+{
+       struct altera_uart_platform_uart *platp = port->private_data;
+
+       return readl(port->membase + (reg << platp->bus_shift));
+}
+
+static void altera_uart_writel(struct uart_port *port, u32 dat, int reg)
+{
+       struct altera_uart_platform_uart *platp = port->private_data;
+
+       writel(dat, port->membase + (reg << platp->bus_shift));
+}
+
 static unsigned int altera_uart_tx_empty(struct uart_port *port)
 {
-       return (readl(port->membase + ALTERA_UART_STATUS_REG) &
+       return (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
                ALTERA_UART_STATUS_TMT_MSK) ? TIOCSER_TEMT : 0;
 }
 
@@ -91,8 +109,7 @@ static unsigned int altera_uart_get_mctrl(struct uart_port *port)
        struct altera_uart *pp = container_of(port, struct altera_uart, port);
        unsigned int sigs;
 
-       sigs =
-           (readl(port->membase + ALTERA_UART_STATUS_REG) &
+       sigs = (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
             ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0;
        sigs |= (pp->sigs & TIOCM_RTS);
 
@@ -108,7 +125,7 @@ static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs)
                pp->imr |= ALTERA_UART_CONTROL_RTS_MSK;
        else
                pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK;
-       writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+       altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
 }
 
 static void altera_uart_start_tx(struct uart_port *port)
@@ -116,7 +133,7 @@ static void altera_uart_start_tx(struct uart_port *port)
        struct altera_uart *pp = container_of(port, struct altera_uart, port);
 
        pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK;
-       writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+       altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
 }
 
 static void altera_uart_stop_tx(struct uart_port *port)
@@ -124,7 +141,7 @@ static void altera_uart_stop_tx(struct uart_port *port)
        struct altera_uart *pp = container_of(port, struct altera_uart, port);
 
        pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
-       writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+       altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
 }
 
 static void altera_uart_stop_rx(struct uart_port *port)
@@ -132,7 +149,7 @@ static void altera_uart_stop_rx(struct uart_port *port)
        struct altera_uart *pp = container_of(port, struct altera_uart, port);
 
        pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK;
-       writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+       altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
 }
 
 static void altera_uart_break_ctl(struct uart_port *port, int break_state)
@@ -145,7 +162,7 @@ static void altera_uart_break_ctl(struct uart_port *port, int break_state)
                pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK;
        else
                pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK;
-       writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+       altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
        spin_unlock_irqrestore(&port->lock, flags);
 }
 
@@ -168,7 +185,8 @@ static void altera_uart_set_termios(struct uart_port *port,
        tty_termios_encode_baud_rate(termios, baud, baud);
 
        spin_lock_irqsave(&port->lock, flags);
-       writel(baudclk, port->membase + ALTERA_UART_DIVISOR_REG);
+       uart_update_timeout(port, termios->c_cflag, baud);
+       altera_uart_writel(port, baudclk, ALTERA_UART_DIVISOR_REG);
        spin_unlock_irqrestore(&port->lock, flags);
 }
 
@@ -178,14 +196,15 @@ static void altera_uart_rx_chars(struct altera_uart *pp)
        unsigned char ch, flag;
        unsigned short status;
 
-       while ((status = readl(port->membase + ALTERA_UART_STATUS_REG)) &
+       while ((status = altera_uart_readl(port, ALTERA_UART_STATUS_REG)) &
               ALTERA_UART_STATUS_RRDY_MSK) {
-               ch = readl(port->membase + ALTERA_UART_RXDATA_REG);
+               ch = altera_uart_readl(port, ALTERA_UART_RXDATA_REG);
                flag = TTY_NORMAL;
                port->icount.rx++;
 
                if (status & ALTERA_UART_STATUS_E_MSK) {
-                       writel(status, port->membase + ALTERA_UART_STATUS_REG);
+                       altera_uart_writel(port, status,
+                                          ALTERA_UART_STATUS_REG);
 
                        if (status & ALTERA_UART_STATUS_BRK_MSK) {
                                port->icount.brk++;
@@ -225,18 +244,18 @@ static void altera_uart_tx_chars(struct altera_uart *pp)
 
        if (port->x_char) {
                /* Send special char - probably flow control */
-               writel(port->x_char, port->membase + ALTERA_UART_TXDATA_REG);
+               altera_uart_writel(port, port->x_char, ALTERA_UART_TXDATA_REG);
                port->x_char = 0;
                port->icount.tx++;
                return;
        }
 
-       while (readl(port->membase + ALTERA_UART_STATUS_REG) &
+       while (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
               ALTERA_UART_STATUS_TRDY_MSK) {
                if (xmit->head == xmit->tail)
                        break;
-               writel(xmit->buf[xmit->tail],
-                      port->membase + ALTERA_UART_TXDATA_REG);
+               altera_uart_writel(port, xmit->buf[xmit->tail],
+                      ALTERA_UART_TXDATA_REG);
                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
                port->icount.tx++;
        }
@@ -246,7 +265,7 @@ static void altera_uart_tx_chars(struct altera_uart *pp)
 
        if (xmit->head == xmit->tail) {
                pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
-               writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+               altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
        }
 }
 
@@ -256,7 +275,7 @@ static irqreturn_t altera_uart_interrupt(int irq, void *data)
        struct altera_uart *pp = container_of(port, struct altera_uart, port);
        unsigned int isr;
 
-       isr = readl(port->membase + ALTERA_UART_STATUS_REG) & pp->imr;
+       isr = altera_uart_readl(port, ALTERA_UART_STATUS_REG) & pp->imr;
 
        spin_lock(&port->lock);
        if (isr & ALTERA_UART_STATUS_RRDY_MSK)
@@ -268,14 +287,23 @@ static irqreturn_t altera_uart_interrupt(int irq, void *data)
        return IRQ_RETVAL(isr);
 }
 
+static void altera_uart_timer(unsigned long data)
+{
+       struct uart_port *port = (void *)data;
+       struct altera_uart *pp = container_of(port, struct altera_uart, port);
+
+       altera_uart_interrupt(0, port);
+       mod_timer(&pp->tmr, jiffies + uart_poll_timeout(port));
+}
+
 static void altera_uart_config_port(struct uart_port *port, int flags)
 {
        port->type = PORT_ALTERA_UART;
 
        /* Clear mask, so no surprise interrupts. */
-       writel(0, port->membase + ALTERA_UART_CONTROL_REG);
+       altera_uart_writel(port, 0, ALTERA_UART_CONTROL_REG);
        /* Clear status register */
-       writel(0, port->membase + ALTERA_UART_STATUS_REG);
+       altera_uart_writel(port, 0, ALTERA_UART_STATUS_REG);
 }
 
 static int altera_uart_startup(struct uart_port *port)
@@ -284,6 +312,12 @@ static int altera_uart_startup(struct uart_port *port)
        unsigned long flags;
        int ret;
 
+       if (!port->irq) {
+               setup_timer(&pp->tmr, altera_uart_timer, (unsigned long)port);
+               mod_timer(&pp->tmr, jiffies + uart_poll_timeout(port));
+               return 0;
+       }
+
        ret = request_irq(port->irq, altera_uart_interrupt, IRQF_DISABLED,
                        DRV_NAME, port);
        if (ret) {
@@ -316,7 +350,10 @@ static void altera_uart_shutdown(struct uart_port *port)
 
        spin_unlock_irqrestore(&port->lock, flags);
 
-       free_irq(port->irq, port);
+       if (port->irq)
+               free_irq(port->irq, port);
+       else
+               del_timer_sync(&pp->tmr);
 }
 
 static const char *altera_uart_type(struct uart_port *port)
@@ -384,8 +421,9 @@ int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp)
                port->iotype = SERIAL_IO_MEM;
                port->irq = platp[i].irq;
                port->uartclk = platp[i].uartclk;
-               port->flags = ASYNC_BOOT_AUTOCONF;
+               port->flags = UPF_BOOT_AUTOCONF;
                port->ops = &altera_uart_ops;
+               port->private_data = platp;
        }
 
        return 0;
@@ -393,7 +431,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) &
+       while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
                 ALTERA_UART_STATUS_TRDY_MSK))
                cpu_relax();
 
@@ -423,7 +461,7 @@ static int __init altera_uart_console_setup(struct console *co, char *options)
        if (co->index < 0 || co->index >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
                return -EINVAL;
        port = &altera_uart_ports[co->index].port;
-       if (port->membase == 0)
+       if (!port->membase)
                return -ENODEV;
 
        if (options)
@@ -435,7 +473,7 @@ static int __init altera_uart_console_setup(struct console *co, char *options)
 static struct uart_driver altera_uart_driver;
 
 static struct console altera_uart_console = {
-       .name   = "ttyS",
+       .name   = "ttyAL",
        .write  = altera_uart_console_write,
        .device = uart_console_device,
        .setup  = altera_uart_console_setup,
@@ -466,9 +504,9 @@ console_initcall(altera_uart_console_init);
 static struct uart_driver altera_uart_driver = {
        .owner          = THIS_MODULE,
        .driver_name    = DRV_NAME,
-       .dev_name       = "ttyS",
-       .major          = TTY_MAJOR,
-       .minor          = 64,
+       .dev_name       = "ttyAL",
+       .major          = SERIAL_ALTERA_MAJOR,
+       .minor          = SERIAL_ALTERA_MINOR,
        .nr             = CONFIG_SERIAL_ALTERA_UART_MAXPORTS,
        .cons           = ALTERA_UART_CONSOLE,
 };
@@ -477,38 +515,55 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
 {
        struct altera_uart_platform_uart *platp = pdev->dev.platform_data;
        struct uart_port *port;
-       int i;
+       struct resource *res_mem;
+       struct resource *res_irq;
+       int i = pdev->id;
 
-       for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) {
-               port = &altera_uart_ports[i].port;
+       /* -1 emphasizes that the platform must have one port, no .N suffix */
+       if (i == -1)
+               i = 0;
 
-               port->line = i;
-               port->type = PORT_ALTERA_UART;
-               port->mapbase = platp[i].mapbase;
-               port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE);
-               port->iotype = SERIAL_IO_MEM;
-               port->irq = platp[i].irq;
-               port->uartclk = platp[i].uartclk;
-               port->ops = &altera_uart_ops;
-               port->flags = ASYNC_BOOT_AUTOCONF;
+       if (i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
+               return -EINVAL;
 
-               uart_add_one_port(&altera_uart_driver, port);
-       }
+       port = &altera_uart_ports[i].port;
+
+       res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res_mem)
+               port->mapbase = res_mem->start;
+       else if (platp->mapbase)
+               port->mapbase = platp->mapbase;
+       else
+               return -EINVAL;
+
+       res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (res_irq)
+               port->irq = res_irq->start;
+       else if (platp->irq)
+               port->irq = platp->irq;
+
+       port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE);
+       if (!port->membase)
+               return -ENOMEM;
+
+       port->line = i;
+       port->type = PORT_ALTERA_UART;
+       port->iotype = SERIAL_IO_MEM;
+       port->uartclk = platp->uartclk;
+       port->ops = &altera_uart_ops;
+       port->flags = UPF_BOOT_AUTOCONF;
+       port->private_data = platp;
+
+       uart_add_one_port(&altera_uart_driver, port);
 
        return 0;
 }
 
 static int __devexit altera_uart_remove(struct platform_device *pdev)
 {
-       struct uart_port *port;
-       int i;
-
-       for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS; i++) {
-               port = &altera_uart_ports[i].port;
-               if (port)
-                       uart_remove_one_port(&altera_uart_driver, port);
-       }
+       struct uart_port *port = &altera_uart_ports[pdev->id].port;
 
+       uart_remove_one_port(&altera_uart_driver, port);
        return 0;
 }
 
@@ -550,3 +605,4 @@ MODULE_DESCRIPTION("Altera UART driver");
 MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_ALTERA_MAJOR);
index 5318dd3..6f1b51e 100644 (file)
@@ -131,7 +131,12 @@ static int sport_uart_setup(struct sport_uart_port *up, int size, int baud_rate)
        pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up));
 
        tclkdiv = sclk / (2 * baud_rate) - 1;
-       rclkdiv = sclk / (2 * baud_rate * 2) - 1;
+       /* The actual uart baud rate of devices vary between +/-2%. The sport
+        * RX sample rate should be faster than the double of the worst case,
+        * otherwise, wrong data are received. So, set sport RX clock to be
+        * 3% faster.
+        */
+       rclkdiv = sclk / (2 * baud_rate * 2 * 97 / 100) - 1;
        SPORT_PUT_TCLKDIV(up, tclkdiv);
        SPORT_PUT_RCLKDIV(up, rclkdiv);
        SSYNC();
index 66ecc7a..dfcf4b1 100644 (file)
@@ -327,14 +327,13 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
 {
        struct circ_buf *xmit = &sport->port.state->xmit;
 
-       while (!(readl(sport->port.membase + UTS) & UTS_TXFULL)) {
+       while (!uart_circ_empty(xmit) &&
+                       !(readl(sport->port.membase + UTS) & UTS_TXFULL)) {
                /* send xmit->buf[xmit->tail]
                 * out the port here */
                writel(xmit->buf[xmit->tail], sport->port.membase + URTX0);
                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
                sport->port.icount.tx++;
-               if (uart_circ_empty(xmit))
-                       break;
        }
 
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
index eaf5450..18f5484 100644 (file)
@@ -172,13 +172,15 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device
                        jsm_uart_port_init here! */
                dev_err(&pdev->dev, "memory allocation for flipbuf failed\n");
                rc = -ENOMEM;
-               goto out_free_irq;
+               goto out_free_uart;
        }
 
        pci_set_drvdata(pdev, brd);
        pci_save_state(pdev);
 
        return 0;
+ out_free_uart:
+       jsm_remove_uart_port(brd);
  out_free_irq:
        jsm_remove_uart_port(brd);
        free_irq(brd->irq, brd);
index 67283c1..910870e 100644 (file)
@@ -986,12 +986,14 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
        s->rxbuf = kzalloc(sizeof(u16) * (MAX3107_RX_FIFO_SIZE+2), GFP_KERNEL);
        if (!s->rxbuf) {
                pr_err("Allocating RX buffer failed\n");
-               return -ENOMEM;
+               retval = -ENOMEM;
+               goto err_free4;
        }
        s->rxstr = kzalloc(sizeof(u8) * MAX3107_RX_FIFO_SIZE, GFP_KERNEL);
        if (!s->rxstr) {
                pr_err("Allocating RX buffer failed\n");
-               return -ENOMEM;
+               retval = -ENOMEM;
+               goto err_free3;
        }
        /* SPI Tx buffer
         * SPI transfer buffer
@@ -1002,7 +1004,8 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
        s->txbuf = kzalloc(sizeof(u16) * MAX3107_TX_FIFO_SIZE + 3, GFP_KERNEL);
        if (!s->txbuf) {
                pr_err("Allocating TX buffer failed\n");
-               return -ENOMEM;
+               retval = -ENOMEM;
+               goto err_free2;
        }
        /* Initialize shared data lock */
        spin_lock_init(&s->data_lock);
@@ -1021,13 +1024,15 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
        buf[0] = MAX3107_REVID_REG;
        if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
                dev_err(&s->spi->dev, "SPI transfer for REVID read failed\n");
-               return -EIO;
+               retval = -EIO;
+               goto err_free1;
        }
        if ((buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID1 &&
                (buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID2) {
                dev_err(&s->spi->dev, "REVID %x does not match\n",
                                (buf[0] & MAX3107_SPI_RX_DATA_MASK));
-               return -ENODEV;
+               retval = -ENODEV;
+               goto err_free1;
        }
 
        /* Disable all interrupts */
@@ -1047,7 +1052,8 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
        /* Perform SPI transfer */
        if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
                dev_err(&s->spi->dev, "SPI transfer for init failed\n");
-               return -EIO;
+               retval = -EIO;
+               goto err_free1;
        }
 
        /* Register UART driver */
@@ -1055,7 +1061,7 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
                retval = uart_register_driver(&max3107_uart_driver);
                if (retval) {
                        dev_err(&s->spi->dev, "Registering UART driver failed\n");
-                       return retval;
+                       goto err_free1;
                }
                driver_registered = 1;
        }
@@ -1074,13 +1080,13 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
        retval = uart_add_one_port(&max3107_uart_driver, &s->port);
        if (retval < 0) {
                dev_err(&s->spi->dev, "Adding UART port failed\n");
-               return retval;
+               goto err_free1;
        }
 
        if (pdata->configure) {
                retval = pdata->configure(s);
                if (retval < 0)
-                       return retval;
+                       goto err_free1;
        }
 
        /* Go to suspend mode */
@@ -1088,6 +1094,16 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
                pdata->hw_suspend(s, 1);
 
        return 0;
+
+err_free1:
+       kfree(s->txbuf);
+err_free2:
+       kfree(s->rxstr);
+err_free3:
+       kfree(s->rxbuf);
+err_free4:
+       kfree(s);
+       return retval;
 }
 EXPORT_SYMBOL_GPL(max3107_probe);
 
index dc0967f..5fc699e 100644 (file)
@@ -172,6 +172,9 @@ static ssize_t port_show_regs(struct file *file, char __user *user_buf,
        len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
                        "DIV: \t\t0x%08x\n", serial_in(up, UART_DIV));
 
+       if (len > HSU_REGS_BUFSIZE)
+               len = HSU_REGS_BUFSIZE;
+
        ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);
        kfree(buf);
        return ret;
@@ -219,6 +222,9 @@ static ssize_t dma_show_regs(struct file *file, char __user *user_buf,
        len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
                        "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3TSR));
 
+       if (len > HSU_REGS_BUFSIZE)
+               len = HSU_REGS_BUFSIZE;
+
        ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);
        kfree(buf);
        return ret;
@@ -925,39 +931,52 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,
                cval |= UART_LCR_EPAR;
 
        /*
+        * The base clk is 50Mhz, and the baud rate come from:
+        *      baud = 50M * MUL / (DIV * PS * DLAB)
+        *
         * For those basic low baud rate we can get the direct
-        * scalar from 2746800, like 115200 = 2746800/24, for those
-        * higher baud rate, we have to handle them case by case,
-        * but DIV reg is never touched as its default value 0x3d09
+        * scalar from 2746800, like 115200 = 2746800/24. For those
+        * higher baud rate, we handle them case by case, mainly by
+        * adjusting the MUL/PS registers, and DIV register is kept
+        * as default value 0x3d09 to make things simple
         */
        baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
-       quot = uart_get_divisor(port, baud);
 
+       quot = 1;
        switch (baud) {
        case 3500000:
                mul = 0x3345;
                ps = 0xC;
-               quot = 1;
+               break;
+       case 3000000:
+               mul = 0x2EE0;
                break;
        case 2500000:
                mul = 0x2710;
-               ps = 0x10;
-               quot = 1;
                break;
-       case 18432000:
+       case 2000000:
+               mul = 0x1F40;
+               break;
+       case 1843200:
                mul = 0x2400;
-               ps = 0x10;
-               quot = 1;
                break;
        case 1500000:
-               mul = 0x1D4C;
-               ps = 0xc;
-               quot = 1;
+               mul = 0x1770;
+               break;
+       case 1000000:
+               mul = 0xFA0;
+               break;
+       case 500000:
+               mul = 0x7D0;
                break;
        default:
-               ;
+               /* Use uart_get_divisor to get quot for other baud rates */
+               quot = 0;
        }
 
+       if (!quot)
+               quot = uart_get_divisor(port, baud);
+
        if ((up->port.uartclk / quot) < (2400 * 16))
                fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_1B;
        else if ((up->port.uartclk / quot) < (230400 * 16))
index 51c15f5..b62857b 100644 (file)
@@ -1,7 +1,7 @@
 /*
- *  max3110.c - spi uart protocol driver for Maxim 3110 on Moorestown
+ *  mrst_max3110.c - spi uart protocol driver for Maxim 3110
  *
- *  Copyright (C) Intel 2008 Feng Tang <feng.tang@intel.com>
+ * Copyright (c) 2008-2010, Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
 #include <linux/irq.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"
 
@@ -56,7 +51,7 @@
 struct uart_max3110 {
        struct uart_port port;
        struct spi_device *spi;
-       char *name;
+       char name[24];
 
        wait_queue_head_t wq;
        struct task_struct *main_thread;
@@ -67,35 +62,30 @@ struct uart_max3110 {
        u16 cur_conf;
        u8 clock;
        u8 parity, word_7bits;
+       u16 irq;
 
        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 struct uart_max3110 *pmax;
+
 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);
+static int max3110_read_multi(struct uart_max3110 *max, u8 *buf);
+static void max3110_con_receive(struct uart_max3110 *max);
 
-int max3110_write_then_read(struct uart_max3110 *max,
-               const u8 *txbuf, u8 *rxbuf, unsigned len, int always_fast)
+static int max3110_write_then_read(struct uart_max3110 *max,
+               const void *txbuf, void *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;
@@ -104,7 +94,7 @@ int max3110_write_then_read(struct uart_max3110 *max,
        spi_message_add_tail(&x, &message);
 
        if (always_fast)
-               x.speed_hz = 3125000;
+               x.speed_hz = spi->max_speed_hz;
        else if (max->baud)
                x.speed_hz = max->baud;
 
@@ -113,58 +103,80 @@ int max3110_write_then_read(struct uart_max3110 *max,
        return ret;
 }
 
-/* Write a u16 to the device, and return one u16 read back */
-int max3110_out(struct uart_max3110 *max, const u16 out)
+/* Write a 16b word to the device */
+static int max3110_out(struct uart_max3110 *max, const u16 out)
 {
-       u16 tmp;
+       void *buf;
+       u16 *obuf, *ibuf;
+       u8  ch;
        int ret;
 
-       ret = max3110_write_then_read(max, (u8 *)&out, (u8 *)&tmp, 2, 1);
-       if (ret)
-               return ret;
+       buf = kzalloc(8, GFP_KERNEL | GFP_DMA);
+       if (!buf)
+               return -ENOMEM;
+
+       obuf = buf;
+       ibuf = buf + 4;
+       *obuf = out;
+       ret = max3110_write_then_read(max, obuf, ibuf, 2, 1);
+       if (ret) {
+               pr_warning(PR_FMT "%s(): get err msg %d when sending 0x%x\n",
+                               __func__, ret, out);
+               goto exit;
+       }
 
        /* If some valid data is read back */
-       if (tmp & MAX3110_READ_DATA_AVAILABLE)
-               receive_char(max, (tmp & 0xff));
+       if (*ibuf & MAX3110_READ_DATA_AVAILABLE) {
+               ch = *ibuf & 0xff;
+               receive_chars(max, &ch, 1);
+       }
 
+exit:
+       kfree(buf);
        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
+ * need any delay like flushing character out.
+ *
+ * Return how many valide bytes are read back
  */
-static int max3110_read_multi(struct uart_max3110 *max, int len, u8 *buf)
+static int max3110_read_multi(struct uart_max3110 *max, u8 *rxbuf)
 {
-       u16 out[MAX_READ_LEN], in[MAX_READ_LEN];
-       u8 *pbuf, valid_str[MAX_READ_LEN];
-       int i, j, bytelen;
+       void *buf;
+       u16 *obuf, *ibuf;
+       u8 *pbuf, valid_str[M3110_RX_FIFO_DEPTH];
+       int i, j, blen;
 
-       if (len > MAX_READ_LEN) {
-               pr_err(PR_FMT "read len %d is too large\n", len);
+       blen = M3110_RX_FIFO_DEPTH * sizeof(u16);
+       buf = kzalloc(blen * 2, GFP_KERNEL | GFP_DMA);
+       if (!buf) {
+               pr_warning(PR_FMT "%s(): fail to alloc dma buffer\n", __func__);
                return 0;
        }
 
-       bytelen = len * 2;
-       memset(out, 0, bytelen);
-       memset(in, 0, bytelen);
+       /* tx/rx always have the same length */
+       obuf = buf;
+       ibuf = buf + blen;
 
-       if (max3110_write_then_read(max, (u8 *)out, (u8 *)in, bytelen, 1))
+       if (max3110_write_then_read(max, obuf, ibuf, blen, 1)) {
+               kfree(buf);
                return 0;
+       }
 
-       /* If caller don't provide a buffer, then handle received char */
-       pbuf = buf ? buf : valid_str;
+       /* If caller doesn't provide a buffer, then handle received char */
+       pbuf = rxbuf ? rxbuf : valid_str;
 
-       for (i = 0, j = 0; i < len; i++) {
-               if (in[i] & MAX3110_READ_DATA_AVAILABLE)
-                       pbuf[j++] = (u8)(in[i] & 0xff);
+       for (i = 0, j = 0; i < M3110_RX_FIFO_DEPTH; i++) {
+               if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE)
+                       pbuf[j++] = ibuf[i] & 0xff;
        }
 
        if (j && (pbuf == valid_str))
                receive_chars(max, valid_str, j);
 
+       kfree(buf);
        return j;
 }
 
@@ -178,10 +190,6 @@ static void serial_m3110_con_putchar(struct uart_port *port, int ch)
                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);
 }
 
 /*
@@ -197,6 +205,9 @@ static void serial_m3110_con_write(struct console *co,
                return;
 
        uart_console_write(&pmax->port, s, count, serial_m3110_con_putchar);
+
+       if (!test_and_set_bit(CON_TX_NEEDED, &pmax->uart_flags))
+               wake_up_process(pmax->main_thread);
 }
 
 static int __init
@@ -210,6 +221,9 @@ serial_m3110_con_setup(struct console *co, char *options)
 
        pr_info(PR_FMT "setting up console\n");
 
+       if (co->index == -1)
+               co->index = 0;
+
        if (!max) {
                pr_err(PR_FMT "pmax is NULL, return");
                return -ENODEV;
@@ -240,8 +254,6 @@ static struct console serial_m3110_console = {
        .data           = &serial_m3110_reg,
 };
 
-#define MRST_CONSOLE   (&serial_m3110_console)
-
 static unsigned int serial_m3110_tx_empty(struct uart_port *port)
 {
        return 1;
@@ -259,32 +271,44 @@ static void serial_m3110_stop_rx(struct uart_port *port)
 }
 
 #define WORDS_PER_XFER 128
-static inline void send_circ_buf(struct uart_max3110 *max,
+static 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];
+       void *buf;
+       u16 *obuf, *ibuf;
        u8 valid_str[WORDS_PER_XFER];
-       int i, j;
+       int i, j, len, blen, dma_size, left, ret = 0;
+
+
+       dma_size = WORDS_PER_XFER * sizeof(u16) * 2;
+       buf = kzalloc(dma_size, GFP_KERNEL | GFP_DMA);
+       if (!buf)
+               return;
+       obuf = buf;
+       ibuf = buf + dma_size/2;
 
        while (!uart_circ_empty(xmit)) {
                left = uart_circ_chars_pending(xmit);
                while (left) {
-                       len = (left >= WORDS_PER_XFER) ? WORDS_PER_XFER : left;
+                       len = min(left, WORDS_PER_XFER);
+                       blen = len * sizeof(u16);
+                       memset(ibuf, 0, blen);
 
-                       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);
+
+                       /* Fail to send msg to console is not very critical */
+                       ret = max3110_write_then_read(max, obuf, ibuf, blen, 0);
+                       if (ret)
+                               pr_warning(PR_FMT "%s(): get err msg %d\n",
+                                               __func__, ret);
 
                        for (i = 0, j = 0; i < len; i++) {
                                if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE)
-                                       valid_str[j++] = (u8)(ibuf[i] & 0xff);
+                                       valid_str[j++] = ibuf[i] & 0xff;
                        }
 
                        if (j)
@@ -294,6 +318,8 @@ static inline void send_circ_buf(struct uart_max3110 *max,
                        left -= len;
                }
        }
+
+       kfree(buf);
 }
 
 static void transmit_char(struct uart_max3110 *max)
@@ -313,8 +339,10 @@ static void transmit_char(struct uart_max3110 *max)
                serial_m3110_stop_tx(port);
 }
 
-/* This will be called by uart_write() and tty_write, can't
- * go to sleep */
+/*
+ * 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 =
@@ -336,7 +364,7 @@ static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len)
 
        tty = port->state->port.tty;
        if (!tty)
-               return; /* receive some char before the tty is opened */
+               return;
 
        while (len) {
                usable = tty_buffer_request_room(tty, len);
@@ -344,32 +372,37 @@ static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len)
                        tty_insert_flip_string(tty, str, usable);
                        str += usable;
                        port->icount.rx += usable;
-                       tty_flip_buffer_push(tty);
                }
                len -= usable;
        }
+       tty_flip_buffer_push(tty);
 }
 
-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)
+/*
+ * This routine will be used in read_thread or RX IRQ handling,
+ * it will first do one round buffer read(8 words), if there is some
+ * valid RX data, will try to read 5 more rounds till all data
+ * is read out.
+ *
+ * Use stack space as data buffer to save some system load, and chose
+ * 504 Btyes as a threadhold to do a bulk push to upper tty layer when
+ * receiving bulk data, a much bigger buffer may cause stack overflow
+ */
+static void max3110_con_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);
+               num = max3110_read_multi(max, pbuf);
 
                if (num) {
-                       loop = 10;
+                       loop = 5;
                        pbuf += num;
                        total += num;
 
-                       if (total >= 500) {
+                       if (total >= 504) {
                                receive_chars(max, recv_buf, total);
                                pbuf = recv_buf;
                                total = 0;
@@ -397,7 +430,7 @@ static int max3110_main_thread(void *_max)
                mutex_lock(&max->thread_mutex);
 
                if (test_and_clear_bit(BIT_IRQ_PENDING, &max->uart_flags))
-                       max3110_console_receive(max);
+                       max3110_con_receive(max);
 
                /* first handle console output */
                if (test_and_clear_bit(CON_TX_NEEDED, &max->uart_flags))
@@ -414,7 +447,6 @@ static int max3110_main_thread(void *_max)
        return ret;
 }
 
-#ifdef CONFIG_MRST_MAX3110_IRQ
 static irqreturn_t serial_m3110_irq(int irq, void *dev_id)
 {
        struct uart_max3110 *max = dev_id;
@@ -426,7 +458,7 @@ static irqreturn_t serial_m3110_irq(int irq, void *dev_id)
 
        return IRQ_HANDLED;
 }
-#else
+
 /* if don't use RX IRQ, then need a thread to polling read */
 static int max3110_read_thread(void *_max)
 {
@@ -434,9 +466,14 @@ static int max3110_read_thread(void *_max)
 
        pr_info(PR_FMT "start read thread\n");
        do {
-               mutex_lock(&max->thread_mutex);
-               max3110_console_receive(max);
-               mutex_unlock(&max->thread_mutex);
+               /*
+                * If can't acquire the mutex, it means the main thread
+                * is running which will also perform the rx job
+                */
+               if (mutex_trylock(&max->thread_mutex)) {
+                       max3110_con_receive(max);
+                       mutex_unlock(&max->thread_mutex);
+               }
 
                set_current_state(TASK_INTERRUPTIBLE);
                schedule_timeout(HZ / 20);
@@ -444,7 +481,6 @@ static int max3110_read_thread(void *_max)
 
        return 0;
 }
-#endif
 
 static int serial_m3110_startup(struct uart_port *port)
 {
@@ -453,33 +489,54 @@ static int serial_m3110_startup(struct uart_port *port)
        u16 config = 0;
        int ret = 0;
 
-       if (port->line != 0)
+       if (port->line != 0) {
                pr_err(PR_FMT "uart port startup failed\n");
+               return -1;
+       }
 
-       /* firstly disable all IRQ and config it to 115200, 8n1 */
+       /* 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,
+       if (max->irq) {
+               max->read_thread = NULL;
+               ret = request_irq(max->irq, serial_m3110_irq,
                                IRQ_TYPE_EDGE_FALLING, "max3110", max);
-       if (ret)
-               return ret;
+               if (ret) {
+                       max->irq = 0;
+                       pr_err(PR_FMT "unable to allocate IRQ, polling\n");
+               }  else {
+                       /* Enable RX IRQ only */
+                       config |= WC_RXA_IRQ_ENABLE;
+               }
+       }
 
-       /* 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
+       if (max->irq == 0) {
+               /* If IRQ is disabled, start a read thread for input data */
+               max->read_thread =
+                       kthread_run(max3110_read_thread, max, "max3110_read");
+               if (IS_ERR(max->read_thread)) {
+                       ret = PTR_ERR(max->read_thread);
+                       max->read_thread = NULL;
+                       pr_err(PR_FMT "Can't create read thread!\n");
+                       return ret;
+               }
+       }
+
+       ret = max3110_out(max, config);
+       if (ret) {
+               if (max->irq)
+                       free_irq(max->irq, max);
+               if (max->read_thread)
+                       kthread_stop(max->read_thread);
+               max->read_thread = NULL;
+               return ret;
+       }
 
        max->cur_conf = config;
        return 0;
@@ -496,9 +553,8 @@ static void serial_m3110_shutdown(struct uart_port *port)
                max->read_thread = NULL;
        }
 
-#ifdef CONFIG_MRST_MAX3110_IRQ
-       free_irq(max->irq, max);
-#endif
+       if (max->irq)
+               free_irq(max->irq, max);
 
        /* Disable interrupts from this port */
        config = WC_TAG | WC_SW_SHDI;
@@ -516,8 +572,7 @@ static int serial_m3110_request_port(struct uart_port *port)
 
 static void serial_m3110_config_port(struct uart_port *port, int flags)
 {
-       /* give it fake type */
-       port->type = PORT_PXA;
+       port->type = PORT_MAX3100;
 }
 
 static int
@@ -552,6 +607,9 @@ serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios,
                new_conf |= WC_7BIT_WORD;
                break;
        default:
+               /* We only support CS7 & CS8 */
+               termios->c_cflag &= ~CSIZE;
+               termios->c_cflag |= CS8;
        case CS8:
                cval = UART_LCR_WLEN8;
                new_conf |= WC_8BIT_WORD;
@@ -560,7 +618,7 @@ serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios,
 
        baud = uart_get_baud_rate(port, termios, old, 0, 230400);
 
-       /* first calc the div for 1.8MHZ clock case */
+       /* First calc the div for 1.8MHZ clock case */
        switch (baud) {
        case 300:
                clk_div = WC_BAUD_DR384;
@@ -596,7 +654,7 @@ serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios,
                if (max->clock & MAX3110_HIGH_CLK)
                        break;
        default:
-               /* pick the previous baud rate */
+               /* 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);
@@ -604,15 +662,21 @@ serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios,
 
        if (max->clock & MAX3110_HIGH_CLK) {
                clk_div += 1;
-               /* high clk version max3110 doesn't support B300 */
-               if (baud == 300)
+               /* High clk version max3110 doesn't support B300 */
+               if (baud == 300) {
                        baud = 600;
+                       clk_div = WC_BAUD_DR384;
+               }
                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 (unlikely(termios->c_cflag & CMSPAR))
+               termios->c_cflag &= ~CMSPAR;
+
        if (termios->c_cflag & CSTOPB)
                new_conf |= WC_2_STOPBITS;
        else
@@ -632,13 +696,14 @@ serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios,
 
        new_conf |= WC_TAG;
        if (new_conf != max->cur_conf) {
-               max3110_out(max, new_conf);
-               max->cur_conf = new_conf;
-               max->baud = baud;
+               if (!max3110_out(max, new_conf)) {
+                       max->cur_conf = new_conf;
+                       max->baud = baud;
+               }
        }
 }
 
-/* don't handle hw handshaking */
+/* Don't handle hw handshaking */
 static unsigned int serial_m3110_get_mctrl(struct uart_port *port)
 {
        return TIOCM_DSR | TIOCM_CAR | TIOCM_DSR;
@@ -672,7 +737,7 @@ struct uart_ops serial_m3110_ops = {
        .break_ctl      = serial_m3110_break_ctl,
        .startup        = serial_m3110_startup,
        .shutdown       = serial_m3110_shutdown,
-       .set_termios    = serial_m3110_set_termios,     /* must have */
+       .set_termios    = serial_m3110_set_termios,
        .pm             = serial_m3110_pm,
        .type           = serial_m3110_type,
        .release_port   = serial_m3110_release_port,
@@ -688,52 +753,60 @@ static struct uart_driver serial_m3110_reg = {
        .major          = TTY_MAJOR,
        .minor          = 64,
        .nr             = 1,
-       .cons           = MRST_CONSOLE,
+       .cons           = &serial_m3110_console,
 };
 
+#ifdef CONFIG_PM
 static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state)
 {
+       struct uart_max3110 *max = spi_get_drvdata(spi);
+
+       disable_irq(max->irq);
+       uart_suspend_port(&serial_m3110_reg, &max->port);
+       max3110_out(max, max->cur_conf | WC_SW_SHDI);
        return 0;
 }
 
 static int serial_m3110_resume(struct spi_device *spi)
 {
+       struct uart_max3110 *max = spi_get_drvdata(spi);
+
+       max3110_out(max, max->cur_conf);
+       uart_resume_port(&serial_m3110_reg, &max->port);
+       enable_irq(max->irq);
        return 0;
 }
+#else
+#define serial_m3110_suspend   NULL
+#define serial_m3110_resume    NULL
+#endif
 
-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)
+static int __devinit serial_m3110_probe(struct spi_device *spi)
 {
        struct uart_max3110 *max;
-       int ret;
-       unsigned char *buffer;
+       void *buffer;
        u16 res;
+       int ret = 0;
+
        max = kzalloc(sizeof(*max), GFP_KERNEL);
        if (!max)
                return -ENOMEM;
 
-       /* set spi info */
-       spi->mode = SPI_MODE_0;
+       /* Set spi info */
        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.type = PORT_MAX3100;
+       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 */
+       strcpy(max->name, spi->modalias);
        max->irq = (u16)spi->irq;
 
        mutex_init(&max->thread_mutex);
@@ -755,13 +828,15 @@ static int serial_m3110_probe(struct spi_device *spi)
                ret = -ENODEV;
                goto err_get_page;
        }
-       buffer = (unsigned char *)__get_free_page(GFP_KERNEL);
+
+       buffer = (void *)__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->con_xmit.buf = buffer;
+       max->con_xmit.head = 0;
+       max->con_xmit.tail = 0;
 
        max->main_thread = kthread_run(max3110_main_thread,
                                        max, "max3110_main");
@@ -770,8 +845,10 @@ static int serial_m3110_probe(struct spi_device *spi)
                goto err_kthread;
        }
 
+       spi_set_drvdata(spi, max);
        pmax = max;
-       /* give membase a psudo value to pass serial_core's check */
+
+       /* 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);
 
@@ -780,19 +857,17 @@ static int serial_m3110_probe(struct spi_device *spi)
 err_kthread:
        free_page((unsigned long)buffer);
 err_get_page:
-       pmax = NULL;
        kfree(max);
        return ret;
 }
 
-static int max3110_remove(struct spi_device *dev)
+static int __devexit serial_m3110_remove(struct spi_device *dev)
 {
-       struct uart_max3110 *max = pmax;
+       struct uart_max3110 *max = spi_get_drvdata(dev);
 
-       if (!pmax)
+       if (!max)
                return 0;
 
-       pmax = NULL;
        uart_remove_one_port(&serial_m3110_reg, &max->port);
 
        free_page((unsigned long)max->con_xmit.buf);
@@ -811,13 +886,12 @@ static struct spi_driver uart_max3110_driver = {
                        .owner  = THIS_MODULE,
        },
        .probe          = serial_m3110_probe,
-       .remove         = __devexit_p(max3110_remove),
+       .remove         = __devexit_p(serial_m3110_remove),
        .suspend        = serial_m3110_suspend,
        .resume         = serial_m3110_resume,
 };
 
-
-int __init serial_m3110_init(void)
+static int __init serial_m3110_init(void)
 {
        int ret = 0;
 
@@ -832,7 +906,7 @@ int __init serial_m3110_init(void)
        return ret;
 }
 
-void __exit serial_m3110_exit(void)
+static void __exit serial_m3110_exit(void)
 {
        spi_unregister_driver(&uart_max3110_driver);
        uart_unregister_driver(&serial_m3110_reg);
@@ -841,5 +915,5 @@ void __exit serial_m3110_exit(void)
 module_init(serial_m3110_init);
 module_exit(serial_m3110_exit);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("max3110-uart");
index 363478a..d1ef43a 100644 (file)
@@ -56,4 +56,5 @@
 #define WC_BAUD_DR192          (0xE)
 #define WC_BAUD_DR384          (0xF)
 
+#define M3110_RX_FIFO_DEPTH    8
 #endif
index cd85112..c4ea146 100644 (file)
@@ -1074,10 +1074,10 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg)
  * NB: both 1->0 and 0->1 transitions are counted except for
  *     RI where only 0->1 is counted.
  */
-static int uart_get_count(struct uart_state *state,
-                         struct serial_icounter_struct __user *icnt)
+static int uart_get_icount(struct tty_struct *tty,
+                         struct serial_icounter_struct *icount)
 {
-       struct serial_icounter_struct icount;
+       struct uart_state *state = tty->driver_data;
        struct uart_icount cnow;
        struct uart_port *uport = state->uart_port;
 
@@ -1085,19 +1085,19 @@ static int uart_get_count(struct uart_state *state,
        memcpy(&cnow, &uport->icount, sizeof(struct uart_icount));
        spin_unlock_irq(&uport->lock);
 
-       icount.cts         = cnow.cts;
-       icount.dsr         = cnow.dsr;
-       icount.rng         = cnow.rng;
-       icount.dcd         = cnow.dcd;
-       icount.rx          = cnow.rx;
-       icount.tx          = cnow.tx;
-       icount.frame       = cnow.frame;
-       icount.overrun     = cnow.overrun;
-       icount.parity      = cnow.parity;
-       icount.brk         = cnow.brk;
-       icount.buf_overrun = cnow.buf_overrun;
+       icount->cts         = cnow.cts;
+       icount->dsr         = cnow.dsr;
+       icount->rng         = cnow.rng;
+       icount->dcd         = cnow.dcd;
+       icount->rx          = cnow.rx;
+       icount->tx          = cnow.tx;
+       icount->frame       = cnow.frame;
+       icount->overrun     = cnow.overrun;
+       icount->parity      = cnow.parity;
+       icount->brk         = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
 
-       return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
+       return 0;
 }
 
 /*
@@ -1150,10 +1150,6 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
        case TIOCMIWAIT:
                ret = uart_wait_modem_status(state, arg);
                break;
-
-       case TIOCGICOUNT:
-               ret = uart_get_count(state, uarg);
-               break;
        }
 
        if (ret != -ENOIOCTLCMD)
@@ -2065,7 +2061,19 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
        /*
         * Re-enable the console device after suspending.
         */
-       if (uart_console(uport)) {
+       if (console_suspend_enabled && uart_console(uport)) {
+               /*
+                * First try to use the console cflag setting.
+                */
+               memset(&termios, 0, sizeof(struct ktermios));
+               termios.c_cflag = uport->cons->cflag;
+
+               /*
+                * If that's unset, use the tty termios setting.
+                */
+               if (port->tty && port->tty->termios && termios.c_cflag == 0)
+                       termios = *(port->tty->termios);
+
                uart_change_pm(state, 0);
                uport->ops->set_termios(uport, &termios, NULL);
                console_start(uport->cons);
@@ -2283,6 +2291,7 @@ static const struct tty_operations uart_ops = {
 #endif
        .tiocmget       = uart_tiocmget,
        .tiocmset       = uart_tiocmset,
+       .get_icount     = uart_get_icount,
 #ifdef CONFIG_CONSOLE_POLL
        .poll_init      = uart_poll_init,
        .poll_get_char  = uart_poll_get_char,
index 9b03d7b..c4bf54b 100644 (file)
@@ -322,6 +322,26 @@ static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser)
        return -EINVAL;
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+static int ulite_get_poll_char(struct uart_port *port)
+{
+       if (!(ioread32be(port->membase + ULITE_STATUS)
+                                               & ULITE_STATUS_RXVALID))
+               return NO_POLL_CHAR;
+
+       return ioread32be(port->membase + ULITE_RX);
+}
+
+static void ulite_put_poll_char(struct uart_port *port, unsigned char ch)
+{
+       while (ioread32be(port->membase + ULITE_STATUS) & ULITE_STATUS_TXFULL)
+               cpu_relax();
+
+       /* write char to device */
+       iowrite32be(ch, port->membase + ULITE_TX);
+}
+#endif
+
 static struct uart_ops ulite_ops = {
        .tx_empty       = ulite_tx_empty,
        .set_mctrl      = ulite_set_mctrl,
@@ -338,7 +358,11 @@ static struct uart_ops ulite_ops = {
        .release_port   = ulite_release_port,
        .request_port   = ulite_request_port,
        .config_port    = ulite_config_port,
-       .verify_port    = ulite_verify_port
+       .verify_port    = ulite_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+       .poll_get_char  = ulite_get_poll_char,
+       .poll_put_char  = ulite_put_poll_char,
+#endif
 };
 
 /* ---------------------------------------------------------------------
index 4e41a2a..8f1d4fb 100644 (file)
@@ -411,6 +411,26 @@ err_out:
        return result;
 }
 
+static int ark3116_get_icount(struct tty_struct *tty,
+                                       struct serial_icounter_struct *icount)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       struct ark3116_private *priv = usb_get_serial_port_data(port);
+       struct async_icount cnow = priv->icount;
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+       icount->rx = cnow.rx;
+       icount->tx = cnow.tx;
+       icount->frame = cnow.frame;
+       icount->overrun = cnow.overrun;
+       icount->parity = cnow.parity;
+       icount->brk = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
+       return 0;
+}
+
 static int ark3116_ioctl(struct tty_struct *tty, struct file *file,
                         unsigned int cmd, unsigned long arg)
 {
@@ -460,25 +480,6 @@ static int ark3116_ioctl(struct tty_struct *tty, struct file *file,
                                return 0;
                }
                break;
-       case TIOCGICOUNT: {
-               struct serial_icounter_struct icount;
-               struct async_icount cnow = priv->icount;
-               memset(&icount, 0, sizeof(icount));
-               icount.cts = cnow.cts;
-               icount.dsr = cnow.dsr;
-               icount.rng = cnow.rng;
-               icount.dcd = cnow.dcd;
-               icount.rx = cnow.rx;
-               icount.tx = cnow.tx;
-               icount.frame = cnow.frame;
-               icount.overrun = cnow.overrun;
-               icount.parity = cnow.parity;
-               icount.brk = cnow.brk;
-               icount.buf_overrun = cnow.buf_overrun;
-               if (copy_to_user(user_arg, &icount, sizeof(icount)))
-                       return -EFAULT;
-               return 0;
-       }
        }
 
        return -ENOIOCTLCMD;
@@ -736,6 +737,7 @@ static struct usb_serial_driver ark3116_device = {
        .ioctl =                ark3116_ioctl,
        .tiocmget =             ark3116_tiocmget,
        .tiocmset =             ark3116_tiocmset,
+       .get_icount =           ark3116_get_icount,
        .open =                 ark3116_open,
        .close =                ark3116_close,
        .break_ctl =            ark3116_break_ctl,
index 97cc87d..891c20e 100644 (file)
@@ -2168,6 +2168,7 @@ static int ftdi_ioctl(struct tty_struct *tty, struct file *file,
         * - mask passed in arg for lines of interest
         *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
         * Caller should use TIOCGICOUNT to see which one it was.
+        * (except that the driver doesn't support it !)
         *
         * This code is borrowed from linux/drivers/char/serial.c
         */
index 76e6fb3..a0ab78a 100644 (file)
@@ -222,6 +222,8 @@ static void edge_break(struct tty_struct *tty, int break_state);
 static int  edge_tiocmget(struct tty_struct *tty, struct file *file);
 static int  edge_tiocmset(struct tty_struct *tty, struct file *file,
                                        unsigned int set, unsigned int clear);
+static int  edge_get_icount(struct tty_struct *tty,
+                               struct serial_icounter_struct *icount);
 static int  edge_startup(struct usb_serial *serial);
 static void edge_disconnect(struct usb_serial *serial);
 static void edge_release(struct usb_serial *serial);
@@ -1624,6 +1626,31 @@ static int edge_tiocmget(struct tty_struct *tty, struct file *file)
        return result;
 }
 
+static int edge_get_icount(struct tty_struct *tty,
+                               struct serial_icounter_struct *icount)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+       struct async_icount cnow;
+       cnow = edge_port->icount;
+
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+       icount->rx = cnow.rx;
+       icount->tx = cnow.tx;
+       icount->frame = cnow.frame;
+       icount->overrun = cnow.overrun;
+       icount->parity = cnow.parity;
+       icount->brk = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
+
+       dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d",
+                       __func__,  port->number, icount->rx, icount->tx);
+       return 0;
+}
+
 static int get_serial_info(struct edgeport_port *edge_port,
                                struct serial_struct __user *retinfo)
 {
@@ -1650,7 +1677,6 @@ static int get_serial_info(struct edgeport_port *edge_port,
 }
 
 
-
 /*****************************************************************************
  * SerialIoctl
  *     this function handles any ioctl calls to the driver
@@ -1663,7 +1689,6 @@ static int edge_ioctl(struct tty_struct *tty, struct file *file,
        struct edgeport_port *edge_port = usb_get_serial_port_data(port);
        struct async_icount cnow;
        struct async_icount cprev;
-       struct serial_icounter_struct icount;
 
        dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
 
@@ -1702,26 +1727,6 @@ static int edge_ioctl(struct tty_struct *tty, struct file *file,
                /* NOTREACHED */
                break;
 
-       case TIOCGICOUNT:
-               cnow = edge_port->icount;
-               memset(&icount, 0, sizeof(icount));
-               icount.cts = cnow.cts;
-               icount.dsr = cnow.dsr;
-               icount.rng = cnow.rng;
-               icount.dcd = cnow.dcd;
-               icount.rx = cnow.rx;
-               icount.tx = cnow.tx;
-               icount.frame = cnow.frame;
-               icount.overrun = cnow.overrun;
-               icount.parity = cnow.parity;
-               icount.brk = cnow.brk;
-               icount.buf_overrun = cnow.buf_overrun;
-
-               dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d",
-                               __func__,  port->number, icount.rx, icount.tx);
-               if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
-                       return -EFAULT;
-               return 0;
        }
        return -ENOIOCTLCMD;
 }
index feb56a4..6ab2a3f 100644 (file)
@@ -123,6 +123,7 @@ static struct usb_serial_driver edgeport_2port_device = {
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
        .tiocmset               = edge_tiocmset,
+       .get_icount             = edge_get_icount,
        .write                  = edge_write,
        .write_room             = edge_write_room,
        .chars_in_buffer        = edge_chars_in_buffer,
@@ -152,6 +153,7 @@ static struct usb_serial_driver edgeport_4port_device = {
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
        .tiocmset               = edge_tiocmset,
+       .get_icount             = edge_get_icount,
        .write                  = edge_write,
        .write_room             = edge_write_room,
        .chars_in_buffer        = edge_chars_in_buffer,
@@ -181,6 +183,7 @@ static struct usb_serial_driver edgeport_8port_device = {
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
        .tiocmset               = edge_tiocmset,
+       .get_icount             = edge_get_icount,
        .write                  = edge_write,
        .write_room             = edge_write_room,
        .chars_in_buffer        = edge_chars_in_buffer,
@@ -209,6 +212,7 @@ static struct usb_serial_driver epic_device = {
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
        .tiocmset               = edge_tiocmset,
+       .get_icount             = edge_get_icount,
        .write                  = edge_write,
        .write_room             = edge_write_room,
        .chars_in_buffer        = edge_chars_in_buffer,
index a7cfc59..4dad27a 100644 (file)
@@ -2510,6 +2510,27 @@ static int edge_tiocmget(struct tty_struct *tty, struct file *file)
        return result;
 }
 
+static int edge_get_icount(struct tty_struct *tty,
+                               struct serial_icounter_struct *icount)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+       struct async_icount *ic = &edge_port->icount;
+
+       icount->cts = ic->cts;
+       icount->dsr = ic->dsr;
+       icount->rng = ic->rng;
+       icount->dcd = ic->dcd;
+       icount->tx = ic->tx;
+        icount->rx = ic->rx;
+        icount->frame = ic->frame;
+        icount->parity = ic->parity;
+        icount->overrun = ic->overrun;
+        icount->brk = ic->brk;
+        icount->buf_overrun = ic->buf_overrun;
+       return 0;
+}
+
 static int get_serial_info(struct edgeport_port *edge_port,
                                struct serial_struct __user *retinfo)
 {
@@ -2572,13 +2593,6 @@ static int edge_ioctl(struct tty_struct *tty, struct file *file,
                }
                /* not reached */
                break;
-       case TIOCGICOUNT:
-               dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
-                    port->number, edge_port->icount.rx, edge_port->icount.tx);
-               if (copy_to_user((void __user *)arg, &edge_port->icount,
-                               sizeof(edge_port->icount)))
-                       return -EFAULT;
-               return 0;
        }
        return -ENOIOCTLCMD;
 }
@@ -2758,6 +2772,7 @@ static struct usb_serial_driver edgeport_1port_device = {
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
        .tiocmset               = edge_tiocmset,
+       .get_icount             = edge_get_icount,
        .write                  = edge_write,
        .write_room             = edge_write_room,
        .chars_in_buffer        = edge_chars_in_buffer,
index aa66581..fd0b641 100644 (file)
@@ -1896,10 +1896,37 @@ static int mos7720_tiocmset(struct tty_struct *tty, struct file *file,
        return 0;
 }
 
+static int mos7720_get_icount(struct tty_struct *tty,
+                               struct serial_icounter_struct *icount)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       struct moschip_port *mos7720_port;
+       struct async_icount cnow;
+
+       mos7720_port = usb_get_serial_port_data(port);
+       cnow = mos7720_port->icount;
+
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+       icount->rx = cnow.rx;
+       icount->tx = cnow.tx;
+       icount->frame = cnow.frame;
+       icount->overrun = cnow.overrun;
+       icount->parity = cnow.parity;
+       icount->brk = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
+
+       dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
+               port->number, icount->rx, icount->tx);
+       return 0;
+}
+
 static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
                          unsigned int __user *value)
 {
-       unsigned int mcr ;
+       unsigned int mcr;
        unsigned int arg;
 
        struct usb_serial_port *port;
@@ -1973,7 +2000,6 @@ static int mos7720_ioctl(struct tty_struct *tty, struct file *file,
        struct moschip_port *mos7720_port;
        struct async_icount cnow;
        struct async_icount cprev;
-       struct serial_icounter_struct icount;
 
        mos7720_port = usb_get_serial_port_data(port);
        if (mos7720_port == NULL)
@@ -2021,29 +2047,6 @@ static int mos7720_ioctl(struct tty_struct *tty, struct file *file,
                }
                /* NOTREACHED */
                break;
-
-       case TIOCGICOUNT:
-               cnow = mos7720_port->icount;
-
-               memset(&icount, 0, sizeof(struct serial_icounter_struct));
-
-               icount.cts = cnow.cts;
-               icount.dsr = cnow.dsr;
-               icount.rng = cnow.rng;
-               icount.dcd = cnow.dcd;
-               icount.rx = cnow.rx;
-               icount.tx = cnow.tx;
-               icount.frame = cnow.frame;
-               icount.overrun = cnow.overrun;
-               icount.parity = cnow.parity;
-               icount.brk = cnow.brk;
-               icount.buf_overrun = cnow.buf_overrun;
-
-               dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
-                   port->number, icount.rx, icount.tx);
-               if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
-                       return -EFAULT;
-               return 0;
        }
 
        return -ENOIOCTLCMD;
@@ -2212,6 +2215,7 @@ static struct usb_serial_driver moschip7720_2port_driver = {
        .ioctl                  = mos7720_ioctl,
        .tiocmget               = mos7720_tiocmget,
        .tiocmset               = mos7720_tiocmset,
+       .get_icount             = mos7720_get_icount,
        .set_termios            = mos7720_set_termios,
        .write                  = mos7720_write,
        .write_room             = mos7720_write_room,
index 1a42bc2..93dad58 100644 (file)
@@ -2209,6 +2209,34 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
        return 0;
 }
 
+static int mos7840_get_icount(struct tty_struct *tty,
+                       struct serial_icounter_struct *icount)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       struct moschip_port *mos7840_port;
+       struct async_icount cnow;
+
+       mos7840_port = mos7840_get_port_private(port);
+       cnow = mos7840_port->icount;
+
+       smp_rmb();
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+       icount->rx = cnow.rx;
+       icount->tx = cnow.tx;
+       icount->frame = cnow.frame;
+       icount->overrun = cnow.overrun;
+       icount->parity = cnow.parity;
+       icount->brk = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
+
+       dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
+               port->number, icount->rx, icount->tx);
+       return 0;
+}
+
 /*****************************************************************************
  * SerialIoctl
  *     this function handles any ioctl calls to the driver
@@ -2223,7 +2251,6 @@ static int mos7840_ioctl(struct tty_struct *tty, struct file *file,
 
        struct async_icount cnow;
        struct async_icount cprev;
-       struct serial_icounter_struct icount;
 
        if (mos7840_port_paranoia_check(port, __func__)) {
                dbg("%s", "Invalid port");
@@ -2282,29 +2309,6 @@ static int mos7840_ioctl(struct tty_struct *tty, struct file *file,
                /* NOTREACHED */
                break;
 
-       case TIOCGICOUNT:
-               cnow = mos7840_port->icount;
-               smp_rmb();
-
-               memset(&icount, 0, sizeof(struct serial_icounter_struct));
-
-               icount.cts = cnow.cts;
-               icount.dsr = cnow.dsr;
-               icount.rng = cnow.rng;
-               icount.dcd = cnow.dcd;
-               icount.rx = cnow.rx;
-               icount.tx = cnow.tx;
-               icount.frame = cnow.frame;
-               icount.overrun = cnow.overrun;
-               icount.parity = cnow.parity;
-               icount.brk = cnow.brk;
-               icount.buf_overrun = cnow.buf_overrun;
-
-               dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
-                   port->number, icount.rx, icount.tx);
-               if (copy_to_user(argp, &icount, sizeof(icount)))
-                       return -EFAULT;
-               return 0;
        default:
                break;
        }
@@ -2674,6 +2678,7 @@ static struct usb_serial_driver moschip7840_4port_device = {
        .break_ctl = mos7840_break,
        .tiocmget = mos7840_tiocmget,
        .tiocmset = mos7840_tiocmset,
+       .get_icount = mos7840_get_icount,
        .attach = mos7840_startup,
        .disconnect = mos7840_disconnect,
        .release = mos7840_release,
index e986002..f5312dd 100644 (file)
@@ -416,12 +416,34 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
        return 0;
 }
 
+static int ssu100_get_icount(struct tty_struct *tty,
+                       struct serial_icounter_struct *icount)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       struct ssu100_port_private *priv = usb_get_serial_port_data(port);
+       struct async_icount cnow = priv->icount;
+
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+       icount->rx = cnow.rx;
+       icount->tx = cnow.tx;
+       icount->frame = cnow.frame;
+       icount->overrun = cnow.overrun;
+       icount->parity = cnow.parity;
+       icount->brk = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
+
+       return 0;
+}
+
+
+
 static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
                    unsigned int cmd, unsigned long arg)
 {
        struct usb_serial_port *port = tty->driver_data;
-       struct ssu100_port_private *priv = usb_get_serial_port_data(port);
-       void __user *user_arg = (void __user *)arg;
 
        dbg("%s cmd 0x%04x", __func__, cmd);
 
@@ -433,27 +455,6 @@ static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
        case TIOCMIWAIT:
                return wait_modem_info(port, arg);
 
-       case TIOCGICOUNT:
-       {
-               struct serial_icounter_struct icount;
-               struct async_icount cnow = priv->icount;
-               memset(&icount, 0, sizeof(icount));
-               icount.cts = cnow.cts;
-               icount.dsr = cnow.dsr;
-               icount.rng = cnow.rng;
-               icount.dcd = cnow.dcd;
-               icount.rx = cnow.rx;
-               icount.tx = cnow.tx;
-               icount.frame = cnow.frame;
-               icount.overrun = cnow.overrun;
-               icount.parity = cnow.parity;
-               icount.brk = cnow.brk;
-               icount.buf_overrun = cnow.buf_overrun;
-               if (copy_to_user(user_arg, &icount, sizeof(icount)))
-                       return -EFAULT;
-               return 0;
-       }
-
        default:
                break;
        }
@@ -726,6 +727,7 @@ static struct usb_serial_driver ssu100_device = {
        .process_read_urb    = ssu100_process_read_urb,
        .tiocmget            = ssu100_tiocmget,
        .tiocmset            = ssu100_tiocmset,
+       .get_icount          = ssu100_get_icount,
        .ioctl               = ssu100_ioctl,
        .set_termios         = ssu100_set_termios,
        .disconnect          = usb_serial_generic_disconnect,
index 90979a1..b2902f3 100644 (file)
@@ -108,6 +108,8 @@ static void ti_throttle(struct tty_struct *tty);
 static void ti_unthrottle(struct tty_struct *tty);
 static int ti_ioctl(struct tty_struct *tty, struct file *file,
                unsigned int cmd, unsigned long arg);
+static int ti_get_icount(struct tty_struct *tty,
+               struct serial_icounter_struct *icount);
 static void ti_set_termios(struct tty_struct *tty,
                struct usb_serial_port *port, struct ktermios *old_termios);
 static int ti_tiocmget(struct tty_struct *tty, struct file *file);
@@ -237,6 +239,7 @@ static struct usb_serial_driver ti_1port_device = {
        .set_termios            = ti_set_termios,
        .tiocmget               = ti_tiocmget,
        .tiocmset               = ti_tiocmset,
+       .get_icount             = ti_get_icount,
        .break_ctl              = ti_break,
        .read_int_callback      = ti_interrupt_callback,
        .read_bulk_callback     = ti_bulk_in_callback,
@@ -265,6 +268,7 @@ static struct usb_serial_driver ti_2port_device = {
        .set_termios            = ti_set_termios,
        .tiocmget               = ti_tiocmget,
        .tiocmset               = ti_tiocmset,
+       .get_icount             = ti_get_icount,
        .break_ctl              = ti_break,
        .read_int_callback      = ti_interrupt_callback,
        .read_bulk_callback     = ti_bulk_in_callback,
@@ -788,6 +792,31 @@ static void ti_unthrottle(struct tty_struct *tty)
        }
 }
 
+static int ti_get_icount(struct tty_struct *tty,
+               struct serial_icounter_struct *icount)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       struct ti_port *tport = usb_get_serial_port_data(port);
+       struct async_icount cnow = tport->tp_icount;
+
+       dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d",
+               __func__, port->number,
+               cnow.rx, cnow.tx);
+
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+       icount->rx = cnow.rx;
+       icount->tx = cnow.tx;
+       icount->frame = cnow.frame;
+       icount->overrun = cnow.overrun;
+       icount->parity = cnow.parity;
+       icount->brk = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
+
+       return 0;
+}
 
 static int ti_ioctl(struct tty_struct *tty, struct file *file,
        unsigned int cmd, unsigned long arg)
@@ -830,14 +859,6 @@ static int ti_ioctl(struct tty_struct *tty, struct file *file,
                        cprev = cnow;
                }
                break;
-       case TIOCGICOUNT:
-               dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d",
-                               __func__, port->number,
-                               tport->tp_icount.rx, tport->tp_icount.tx);
-               if (copy_to_user((void __user *)arg, &tport->tp_icount,
-                                       sizeof(tport->tp_icount)))
-                       return -EFAULT;
-               return 0;
        }
        return -ENOIOCTLCMD;
 }
index 7a2177c..e64da74 100644 (file)
@@ -519,6 +519,18 @@ static int serial_tiocmset(struct tty_struct *tty, struct file *file,
        return -EINVAL;
 }
 
+static int serial_get_icount(struct tty_struct *tty,
+                               struct serial_icounter_struct *icount)
+{
+       struct usb_serial_port *port = tty->driver_data;
+
+       dbg("%s - port %d", __func__, port->number);
+
+       if (port->serial->type->get_icount)
+               return port->serial->type->get_icount(tty, icount);
+       return -EINVAL;
+}
+
 /*
  * We would be calling tty_wakeup here, but unfortunately some line
  * disciplines have an annoying habit of calling tty->write from
@@ -1195,6 +1207,7 @@ static const struct tty_operations serial_ops = {
        .chars_in_buffer =      serial_chars_in_buffer,
        .tiocmget =             serial_tiocmget,
        .tiocmset =             serial_tiocmset,
+       .get_icount =           serial_get_icount,
        .cleanup =              serial_cleanup,
        .install =              serial_install,
        .proc_fops =            &serial_proc_fops,
index 83adcc8..dc44f94 100644 (file)
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/console.h>
 #include <linux/seq_file.h>
+#include <linux/fdtable.h>
 #include <linux/bitops.h>
 
 /*
@@ -137,6 +140,160 @@ static const struct file_operations proc_tty_drivers_operations = {
 };
 
 /*
+ * The device ID of file descriptor 0 of the current reading
+ * task if a character device...
+ */
+static dev_t current_dev;
+
+/*
+ * This is the handler for /proc/tty/consoles
+ */
+static int show_console_dev(struct seq_file *m, void *v)
+{
+       const struct tty_driver *driver;
+       struct console *con;
+       int index, len;
+       char flags[10];
+       dev_t dev;
+
+       if (v == SEQ_START_TOKEN)
+               return 0;
+       con = (struct console *)v;
+       if (!con)
+               return 0;
+       driver = con->device(con, &index);
+       if (!driver)
+               return 0;
+       dev = MKDEV(driver->major, driver->minor_start) + index;
+
+       index = 0;
+       if (con->flags & CON_ENABLED)
+               flags[index++] = 'E';
+       if (con->flags & CON_CONSDEV)
+               flags[index++] = 'C';
+       if (con->flags & CON_BOOT)
+               flags[index++] = 'B';
+       if (con->flags & CON_PRINTBUFFER)
+               flags[index++] = 'p';
+       if (con->flags & CON_BRL)
+               flags[index++] = 'b';
+       if (con->flags & CON_ANYTIME)
+               flags[index++] = 'a';
+       if (current_dev == dev)
+               flags[index++] = '*';
+       flags[index] = 0;
+
+       seq_printf(m, "%s%d%n", con->name, con->index, &len);
+       len = 21 - len;
+       if (len < 1)
+               len = 1;
+       seq_printf(m, "%*c", len, ' ');
+       seq_printf(m, "%c%c%c (%s)%n", con->read ? 'R' : '-',
+                       con->write ? 'W' : '-', con->unblank ? 'U' : '-',
+                       flags, &len);
+       len = 13 - len;
+       if (len < 1)
+               len = 1;
+       seq_printf(m, "%*c%4d:%d\n", len, ' ', MAJOR(dev), MINOR(dev));
+
+       return 0;
+}
+
+/* iterator for consoles */
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+       struct console *con;
+       loff_t off = 0;
+
+       if (*pos == 0)
+               return SEQ_START_TOKEN;
+
+       acquire_console_sem();
+       for (con = console_drivers; con; con = con->next) {
+               if (!con->device)
+                       continue;
+               if (++off == *pos)
+                       break;
+       }
+       release_console_sem();
+
+       return con;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       struct console *con;
+
+       acquire_console_sem();
+       if (v == SEQ_START_TOKEN)
+               con = console_drivers;
+       else
+               con = ((struct console *)v)->next;
+       for (; con; con = con->next) {
+               if (!con->device)
+                       continue;
+               ++*pos;
+               break;
+       }
+       release_console_sem();
+
+       return con;
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+static const struct seq_operations tty_consoles_op = {
+       .start  = c_start,
+       .next   = c_next,
+       .stop   = c_stop,
+       .show   = show_console_dev
+};
+
+/*
+ * Used for open /proc/tty/consoles. Before this detect
+ * the device ID of file descriptor 0 of the current
+ * reading task if a character device...
+ */
+static int tty_consoles_open(struct inode *inode, struct file *file)
+{
+       struct files_struct *curfiles;
+
+       current_dev = 0;
+       curfiles = get_files_struct(current);
+       if (curfiles) {
+               const struct file *curfp;
+               spin_lock(&curfiles->file_lock);
+               curfp = fcheck_files(curfiles, 0);
+               if (curfp && curfp->private_data) {
+                       const struct inode *inode;
+                       dget(curfp->f_dentry);
+                       inode = curfp->f_dentry->d_inode;
+                       if (S_ISCHR(inode->i_mode)) {
+                               struct tty_struct *tty;
+                               tty = (struct tty_struct *)curfp->private_data;
+                               if (tty && tty->magic == TTY_MAGIC) {
+                                       tty = tty_pair_get_tty(tty);
+                                       current_dev = tty_devnum(tty);
+                               }
+                       }
+                       dput(curfp->f_dentry);
+               }
+               spin_unlock(&curfiles->file_lock);
+               put_files_struct(curfiles);
+       }
+       return seq_open(file, &tty_consoles_op);
+}
+
+static const struct file_operations proc_tty_consoles_operations = {
+       .open           = tty_consoles_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+/*
  * This function is called by tty_register_driver() to handle
  * registering the driver's /proc handler into /proc/tty/driver/<foo>
  */
@@ -186,4 +343,5 @@ void __init proc_tty_init(void)
        proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR|S_IXUSR, NULL);
        proc_create("tty/ldiscs", 0, NULL, &tty_ldiscs_proc_fops);
        proc_create("tty/drivers", 0, NULL, &proc_tty_drivers_operations);
+       proc_create("tty/consoles", 0, NULL, &proc_tty_consoles_operations);
 }
index 8554cb6..a321665 100644 (file)
@@ -62,7 +62,9 @@
 #define TCSETSW2       _IOW('T', 0x2C, struct termios2)
 #define TCSETSF2       _IOW('T', 0x2D, struct termios2)
 #define TIOCGRS485     0x542E
+#ifndef TIOCSRS485
 #define TIOCSRS485     0x542F
+#endif
 #define TIOCGPTN       _IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK     _IOW('T', 0x31, int)  /* Lock/unlock Pty */
 #define TCGETX         0x5432 /* SYS5 TCGETX compatibility */
index 8d44106..a10a907 100644 (file)
@@ -5,10 +5,15 @@
 #ifndef        __ALTUART_H
 #define        __ALTUART_H
 
+#include <linux/init.h>
+
 struct altera_uart_platform_uart {
        unsigned long mapbase;  /* Physical address base */
        unsigned int irq;       /* Interrupt vector */
        unsigned int uartclk;   /* UART clock rate */
+       unsigned int bus_shift; /* Bus shift (address stride) */
 };
 
+int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp);
+
 #endif /* __ALTUART_H */
index 8cdaa11..85193aa 100644 (file)
@@ -39,5 +39,6 @@ extern void putconsxy(struct vc_data *vc, unsigned char *p);
 
 extern u16 vcs_scr_readw(struct vc_data *vc, const u16 *org);
 extern void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org);
+extern void vcs_scr_updated(struct vc_data *vc);
 
 #endif
index 7638dea..97f5b45 100644 (file)
@@ -35,6 +35,8 @@ struct plat_serial8250_port {
        void            (*set_termios)(struct uart_port *,
                                       struct ktermios *new,
                                       struct ktermios *old);
+       void            (*pm)(struct uart_port *, unsigned int state,
+                             unsigned old);
 };
 
 /*
@@ -76,5 +78,11 @@ extern int serial8250_find_port_for_earlycon(void);
 extern int setup_early_serial8250_console(char *cmdline);
 extern void serial8250_do_set_termios(struct uart_port *port,
                struct ktermios *termios, struct ktermios *old);
+extern void serial8250_do_pm(struct uart_port *port, unsigned int state,
+                            unsigned int oldstate);
+
+extern void serial8250_set_isa_configurator(void (*v)
+                                       (int port, struct uart_port *up,
+                                               unsigned short *capabilities));
 
 #endif
index 563e234..99e5994 100644 (file)
@@ -289,6 +289,8 @@ struct uart_port {
        void                    (*set_termios)(struct uart_port *,
                                               struct ktermios *new,
                                               struct ktermios *old);
+       void                    (*pm)(struct uart_port *, unsigned int state,
+                                     unsigned int old);
        unsigned int            irq;                    /* irq number */
        unsigned long           irqflags;               /* irq flags  */
        unsigned int            uartclk;                /* base uart clock */
@@ -411,6 +413,14 @@ unsigned int uart_get_baud_rate(struct uart_port *port, struct ktermios *termios
                                unsigned int max);
 unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud);
 
+/* Base timer interval for polling */
+static inline int uart_poll_timeout(struct uart_port *port)
+{
+       int timeout = port->timeout;
+
+       return timeout > 6 ? (timeout / 2 - 2) : 1;
+}
+
 /*
  * Console helpers.
  */
index 67d64e6..86be0cd 100644 (file)
@@ -256,6 +256,7 @@ struct tty_operations;
 struct tty_struct {
        int     magic;
        struct kref kref;
+       struct device *dev;
        struct tty_driver *driver;
        const struct tty_operations *ops;
        int index;
@@ -465,7 +466,7 @@ extern void proc_clear_tty(struct task_struct *p);
 extern struct tty_struct *get_current_tty(void);
 extern void tty_default_fops(struct file_operations *fops);
 extern struct tty_struct *alloc_tty_struct(void);
-extern void tty_add_file(struct tty_struct *tty, struct file *file);
+extern int tty_add_file(struct tty_struct *tty, struct file *file);
 extern void free_tty_struct(struct tty_struct *tty);
 extern void initialize_tty_struct(struct tty_struct *tty,
                struct tty_driver *driver, int idx);
index b086779..db2d227 100644 (file)
  *     unless the tty also has a valid tty->termiox pointer.
  *
  *     Optional: Called under the termios lock
+ *
+ * int (*get_icount)(struct tty_struct *tty, struct serial_icounter *icount);
+ *
+ *     Called when the device receives a TIOCGICOUNT ioctl. Passed a kernel
+ *     structure to complete. This method is optional and will only be called
+ *     if provided (otherwise EINVAL will be returned).
  */
 
 #include <linux/fs.h>
 
 struct tty_struct;
 struct tty_driver;
+struct serial_icounter_struct;
 
 struct tty_operations {
        struct tty_struct * (*lookup)(struct tty_driver *driver,
@@ -268,6 +275,8 @@ struct tty_operations {
                        unsigned int set, unsigned int clear);
        int (*resize)(struct tty_struct *tty, struct winsize *ws);
        int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew);
+       int (*get_icount)(struct tty_struct *tty,
+                               struct serial_icounter_struct *icount);
 #ifdef CONFIG_CONSOLE_POLL
        int (*poll_init)(struct tty_driver *driver, int line, char *options);
        int (*poll_get_char)(struct tty_driver *driver, int line);
index 55675b1..16d682f 100644 (file)
@@ -271,6 +271,8 @@ struct usb_serial_driver {
        int  (*tiocmget)(struct tty_struct *tty, struct file *file);
        int  (*tiocmset)(struct tty_struct *tty, struct file *file,
                         unsigned int set, unsigned int clear);
+       int  (*get_icount)(struct tty_struct *tty,
+                       struct serial_icounter_struct *icount);
        /* Called by the tty layer for port level work. There may or may not
           be an attached tty at this point */
        void (*dtr_rts)(struct usb_serial_port *port, int on);
index befc3a5..84c2a4d 100644 (file)
@@ -844,10 +844,6 @@ static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned
                BT_DBG("TIOCMIWAIT");
                break;
 
-       case TIOCGICOUNT:
-               BT_DBG("TIOCGICOUNT");
-               break;
-
        case TIOCGSERIAL:
                BT_ERR("TIOCGSERIAL is not supported");
                return -ENOIOCTLCMD;