Merge 3.9-rc7 intp tty-next
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 15 Apr 2013 02:13:28 +0000 (19:13 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 15 Apr 2013 02:13:28 +0000 (19:13 -0700)
We want the fixes here.

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
87 files changed:
Documentation/devicetree/bindings/tty/serial/of-serial.txt
arch/arm/mach-s3c24xx/clock-s3c2440.c
arch/arm/mach-s3c24xx/common.c
arch/arm/plat-samsung/include/plat/regs-serial.h
arch/ia64/hp/sim/simserial.c
arch/um/drivers/chan_kern.c
arch/um/drivers/line.c
drivers/isdn/capi/capi.c
drivers/isdn/gigaset/interface.c
drivers/isdn/i4l/isdn_tty.c
drivers/mmc/card/sdio_uart.c
drivers/net/caif/caif_serial.c
drivers/net/ppp/ppp_async.c
drivers/net/ppp/ppp_synctty.c
drivers/net/usb/hso.c
drivers/s390/char/sclp_tty.c
drivers/s390/char/sclp_vt220.c
drivers/staging/fwserial/fwserial.c
drivers/staging/serqt_usb2/serqt_usb2.c
drivers/tty/amiserial.c
drivers/tty/cyclades.c
drivers/tty/ehv_bytechan.c
drivers/tty/hvc/hvsi.c
drivers/tty/ipwireless/hardware.c
drivers/tty/moxa.c
drivers/tty/mxser.c
drivers/tty/n_gsm.c
drivers/tty/n_tty.c
drivers/tty/nozomi.c
drivers/tty/pty.c
drivers/tty/rocket.c
drivers/tty/serial/68328serial.c
drivers/tty/serial/8250/8250.h
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_dma.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/amba-pl011.c
drivers/tty/serial/arc_uart.c
drivers/tty/serial/bfin_uart.c
drivers/tty/serial/crisv10.c
drivers/tty/serial/crisv10.h
drivers/tty/serial/icom.c
drivers/tty/serial/ifx6x60.c
drivers/tty/serial/jsm/jsm_tty.c
drivers/tty/serial/max3100.c
drivers/tty/serial/max310x.c
drivers/tty/serial/mrst_max3110.c
drivers/tty/serial/msm_serial_hs.c
drivers/tty/serial/msm_smd_tty.c
drivers/tty/serial/of_serial.c
drivers/tty/serial/pch_uart.c
drivers/tty/serial/samsung.c
drivers/tty/serial/samsung.h
drivers/tty/serial/serial-tegra.c
drivers/tty/serial/sh-sci.h
drivers/tty/serial/sunsab.c
drivers/tty/serial/sunzilog.c
drivers/tty/serial/vt8500_serial.c
drivers/tty/serial/xilinx_uartps.c
drivers/tty/synclink.c
drivers/tty/synclink_gt.c
drivers/tty/synclinkmp.c
drivers/tty/sysrq.c
drivers/tty/tty_buffer.c
drivers/tty/tty_io.c
drivers/tty/tty_ioctl.c
drivers/tty/tty_ldisc.c
drivers/tty/tty_port.c
drivers/tty/vt/consolemap.c
drivers/usb/class/cdc-acm.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/option.c
drivers/usb/serial/quatech2.c
drivers/usb/serial/sierra.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb-serial.c
include/linux/amba/serial.h
include/linux/serial_s3c.h [new file with mode: 0644]
include/linux/tty.h
include/linux/tty_ldisc.h
net/irda/ircomm/ircomm_tty.c
net/irda/ircomm/ircomm_tty_attach.c

index 8f01cb190f25686747873ab54eaa53652c9b35bc..1928a3e83cd0413262de68c036242cb0b92b08fa 100644 (file)
@@ -33,6 +33,10 @@ Optional properties:
   RTAS and should not be registered.
 - no-loopback-test: set to indicate that the port does not implements loopback
   test mode
+- fifo-size: the fifo size of the UART.
+- auto-flow-control: one way to enable automatic flow control support. The
+  driver is allowed to detect support for the capability even without this
+  property.
 
 Example:
 
index 04b87ec9253705de029446e49749a3a83302b828..1069b56808265b5efaf9877b9ed6a1b7dc5ea833 100644 (file)
@@ -123,6 +123,11 @@ static struct clk s3c2440_clk_ac97 = {
        .ctrlbit        = S3C2440_CLKCON_AC97,
 };
 
+#define S3C24XX_VA_UART0      (S3C_VA_UART)
+#define S3C24XX_VA_UART1      (S3C_VA_UART + 0x4000 )
+#define S3C24XX_VA_UART2      (S3C_VA_UART + 0x8000 )
+#define S3C24XX_VA_UART3      (S3C_VA_UART + 0xC000 )
+
 static unsigned long  s3c2440_fclk_n_getrate(struct clk *clk)
 {
        unsigned long ucon0, ucon1, ucon2, divisor;
index 6bcf87f65f9e41c7cb86dfd064495eb3a76820af..92e609440c571f25d51c77ae351756beb5f73b8d 100644 (file)
@@ -239,6 +239,11 @@ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
 
 /* Serial port registrations */
 
+#define S3C2410_PA_UART0      (S3C24XX_PA_UART)
+#define S3C2410_PA_UART1      (S3C24XX_PA_UART + 0x4000 )
+#define S3C2410_PA_UART2      (S3C24XX_PA_UART + 0x8000 )
+#define S3C2443_PA_UART3      (S3C24XX_PA_UART + 0xC000 )
+
 static struct resource s3c2410_uart0_resource[] = {
        [0] = DEFINE_RES_MEM(S3C2410_PA_UART0, SZ_16K),
        [1] = DEFINE_RES_NAMED(IRQ_S3CUART_RX0, \
index 29c26a818842c41a679b09ec71bd9489e61f0c11..f05f2afa440db8bdbf1a84fa0d64d13d2e292e77 100644 (file)
@@ -1,281 +1 @@
-/* arch/arm/plat-samsung/include/plat/regs-serial.h
- *
- *  From linux/include/asm-arm/hardware/serial_s3c2410.h
- *
- *  Internal header file for Samsung S3C2410 serial ports (UART0-2)
- *
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *
- *  Additional defines, Copyright 2003 Simtec Electronics (linux@simtec.co.uk)
- *
- *  Adapted from:
- *
- *  Internal header file for MX1ADS serial ports (UART1 & 2)
- *
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#ifndef __ASM_ARM_REGS_SERIAL_H
-#define __ASM_ARM_REGS_SERIAL_H
-
-#define S3C24XX_VA_UART0      (S3C_VA_UART)
-#define S3C24XX_VA_UART1      (S3C_VA_UART + 0x4000 )
-#define S3C24XX_VA_UART2      (S3C_VA_UART + 0x8000 )
-#define S3C24XX_VA_UART3      (S3C_VA_UART + 0xC000 )
-
-#define S3C2410_PA_UART0      (S3C24XX_PA_UART)
-#define S3C2410_PA_UART1      (S3C24XX_PA_UART + 0x4000 )
-#define S3C2410_PA_UART2      (S3C24XX_PA_UART + 0x8000 )
-#define S3C2443_PA_UART3      (S3C24XX_PA_UART + 0xC000 )
-
-#define S3C2410_URXH     (0x24)
-#define S3C2410_UTXH     (0x20)
-#define S3C2410_ULCON    (0x00)
-#define S3C2410_UCON     (0x04)
-#define S3C2410_UFCON    (0x08)
-#define S3C2410_UMCON    (0x0C)
-#define S3C2410_UBRDIV   (0x28)
-#define S3C2410_UTRSTAT          (0x10)
-#define S3C2410_UERSTAT          (0x14)
-#define S3C2410_UFSTAT   (0x18)
-#define S3C2410_UMSTAT   (0x1C)
-
-#define S3C2410_LCON_CFGMASK     ((0xF<<3)|(0x3))
-
-#define S3C2410_LCON_CS5         (0x0)
-#define S3C2410_LCON_CS6         (0x1)
-#define S3C2410_LCON_CS7         (0x2)
-#define S3C2410_LCON_CS8         (0x3)
-#define S3C2410_LCON_CSMASK      (0x3)
-
-#define S3C2410_LCON_PNONE       (0x0)
-#define S3C2410_LCON_PEVEN       (0x5 << 3)
-#define S3C2410_LCON_PODD        (0x4 << 3)
-#define S3C2410_LCON_PMASK       (0x7 << 3)
-
-#define S3C2410_LCON_STOPB       (1<<2)
-#define S3C2410_LCON_IRM          (1<<6)
-
-#define S3C2440_UCON_CLKMASK     (3<<10)
-#define S3C2440_UCON_CLKSHIFT    (10)
-#define S3C2440_UCON_PCLK        (0<<10)
-#define S3C2440_UCON_UCLK        (1<<10)
-#define S3C2440_UCON_PCLK2       (2<<10)
-#define S3C2440_UCON_FCLK        (3<<10)
-#define S3C2443_UCON_EPLL        (3<<10)
-
-#define S3C6400_UCON_CLKMASK   (3<<10)
-#define S3C6400_UCON_CLKSHIFT  (10)
-#define S3C6400_UCON_PCLK      (0<<10)
-#define S3C6400_UCON_PCLK2     (2<<10)
-#define S3C6400_UCON_UCLK0     (1<<10)
-#define S3C6400_UCON_UCLK1     (3<<10)
-
-#define S3C2440_UCON2_FCLK_EN    (1<<15)
-#define S3C2440_UCON0_DIVMASK    (15 << 12)
-#define S3C2440_UCON1_DIVMASK    (15 << 12)
-#define S3C2440_UCON2_DIVMASK    (7 << 12)
-#define S3C2440_UCON_DIVSHIFT    (12)
-
-#define S3C2412_UCON_CLKMASK   (3<<10)
-#define S3C2412_UCON_CLKSHIFT  (10)
-#define S3C2412_UCON_UCLK      (1<<10)
-#define S3C2412_UCON_USYSCLK   (3<<10)
-#define S3C2412_UCON_PCLK      (0<<10)
-#define S3C2412_UCON_PCLK2     (2<<10)
-
-#define S3C2410_UCON_CLKMASK   (1 << 10)
-#define S3C2410_UCON_CLKSHIFT  (10)
-#define S3C2410_UCON_UCLK        (1<<10)
-#define S3C2410_UCON_SBREAK      (1<<4)
-
-#define S3C2410_UCON_TXILEVEL    (1<<9)
-#define S3C2410_UCON_RXILEVEL    (1<<8)
-#define S3C2410_UCON_TXIRQMODE   (1<<2)
-#define S3C2410_UCON_RXIRQMODE   (1<<0)
-#define S3C2410_UCON_RXFIFO_TOI          (1<<7)
-#define S3C2443_UCON_RXERR_IRQEN  (1<<6)
-#define S3C2443_UCON_LOOPBACK    (1<<5)
-
-#define S3C2410_UCON_DEFAULT     (S3C2410_UCON_TXILEVEL  | \
-                                  S3C2410_UCON_RXILEVEL  | \
-                                  S3C2410_UCON_TXIRQMODE | \
-                                  S3C2410_UCON_RXIRQMODE | \
-                                  S3C2410_UCON_RXFIFO_TOI)
-
-#define S3C2410_UFCON_FIFOMODE   (1<<0)
-#define S3C2410_UFCON_TXTRIG0    (0<<6)
-#define S3C2410_UFCON_RXTRIG8    (1<<4)
-#define S3C2410_UFCON_RXTRIG12   (2<<4)
-
-/* S3C2440 FIFO trigger levels */
-#define S3C2440_UFCON_RXTRIG1    (0<<4)
-#define S3C2440_UFCON_RXTRIG8    (1<<4)
-#define S3C2440_UFCON_RXTRIG16   (2<<4)
-#define S3C2440_UFCON_RXTRIG32   (3<<4)
-
-#define S3C2440_UFCON_TXTRIG0    (0<<6)
-#define S3C2440_UFCON_TXTRIG16   (1<<6)
-#define S3C2440_UFCON_TXTRIG32   (2<<6)
-#define S3C2440_UFCON_TXTRIG48   (3<<6)
-
-#define S3C2410_UFCON_RESETBOTH          (3<<1)
-#define S3C2410_UFCON_RESETTX    (1<<2)
-#define S3C2410_UFCON_RESETRX    (1<<1)
-
-#define S3C2410_UFCON_DEFAULT    (S3C2410_UFCON_FIFOMODE | \
-                                  S3C2410_UFCON_TXTRIG0  | \
-                                  S3C2410_UFCON_RXTRIG8 )
-
-#define        S3C2410_UMCOM_AFC         (1<<4)
-#define        S3C2410_UMCOM_RTS_LOW     (1<<0)
-
-#define S3C2412_UMCON_AFC_63   (0<<5)          /* same as s3c2443 */
-#define S3C2412_UMCON_AFC_56   (1<<5)
-#define S3C2412_UMCON_AFC_48   (2<<5)
-#define S3C2412_UMCON_AFC_40   (3<<5)
-#define S3C2412_UMCON_AFC_32   (4<<5)
-#define S3C2412_UMCON_AFC_24   (5<<5)
-#define S3C2412_UMCON_AFC_16   (6<<5)
-#define S3C2412_UMCON_AFC_8    (7<<5)
-
-#define S3C2410_UFSTAT_TXFULL    (1<<9)
-#define S3C2410_UFSTAT_RXFULL    (1<<8)
-#define S3C2410_UFSTAT_TXMASK    (15<<4)
-#define S3C2410_UFSTAT_TXSHIFT   (4)
-#define S3C2410_UFSTAT_RXMASK    (15<<0)
-#define S3C2410_UFSTAT_RXSHIFT   (0)
-
-/* UFSTAT S3C2443 same as S3C2440 */
-#define S3C2440_UFSTAT_TXFULL    (1<<14)
-#define S3C2440_UFSTAT_RXFULL    (1<<6)
-#define S3C2440_UFSTAT_TXSHIFT   (8)
-#define S3C2440_UFSTAT_RXSHIFT   (0)
-#define S3C2440_UFSTAT_TXMASK    (63<<8)
-#define S3C2440_UFSTAT_RXMASK    (63)
-
-#define S3C2410_UTRSTAT_TXE      (1<<2)
-#define S3C2410_UTRSTAT_TXFE     (1<<1)
-#define S3C2410_UTRSTAT_RXDR     (1<<0)
-
-#define S3C2410_UERSTAT_OVERRUN          (1<<0)
-#define S3C2410_UERSTAT_FRAME    (1<<2)
-#define S3C2410_UERSTAT_BREAK    (1<<3)
-#define S3C2443_UERSTAT_PARITY   (1<<1)
-
-#define S3C2410_UERSTAT_ANY      (S3C2410_UERSTAT_OVERRUN | \
-                                  S3C2410_UERSTAT_FRAME | \
-                                  S3C2410_UERSTAT_BREAK)
-
-#define S3C2410_UMSTAT_CTS       (1<<0)
-#define S3C2410_UMSTAT_DeltaCTS          (1<<2)
-
-#define S3C2443_DIVSLOT                  (0x2C)
-
-/* S3C64XX interrupt registers. */
-#define S3C64XX_UINTP          0x30
-#define S3C64XX_UINTSP         0x34
-#define S3C64XX_UINTM          0x38
-
-#define S3C64XX_UINTM_RXD      (0)
-#define S3C64XX_UINTM_TXD      (2)
-#define S3C64XX_UINTM_RXD_MSK  (1 << S3C64XX_UINTM_RXD)
-#define S3C64XX_UINTM_TXD_MSK  (1 << S3C64XX_UINTM_TXD)
-
-/* Following are specific to S5PV210 */
-#define S5PV210_UCON_CLKMASK   (1<<10)
-#define S5PV210_UCON_CLKSHIFT  (10)
-#define S5PV210_UCON_PCLK      (0<<10)
-#define S5PV210_UCON_UCLK      (1<<10)
-
-#define S5PV210_UFCON_TXTRIG0  (0<<8)
-#define S5PV210_UFCON_TXTRIG4  (1<<8)
-#define S5PV210_UFCON_TXTRIG8  (2<<8)
-#define S5PV210_UFCON_TXTRIG16 (3<<8)
-#define S5PV210_UFCON_TXTRIG32 (4<<8)
-#define S5PV210_UFCON_TXTRIG64 (5<<8)
-#define S5PV210_UFCON_TXTRIG128 (6<<8)
-#define S5PV210_UFCON_TXTRIG256 (7<<8)
-
-#define S5PV210_UFCON_RXTRIG1  (0<<4)
-#define S5PV210_UFCON_RXTRIG4  (1<<4)
-#define S5PV210_UFCON_RXTRIG8  (2<<4)
-#define S5PV210_UFCON_RXTRIG16 (3<<4)
-#define S5PV210_UFCON_RXTRIG32 (4<<4)
-#define S5PV210_UFCON_RXTRIG64 (5<<4)
-#define S5PV210_UFCON_RXTRIG128        (6<<4)
-#define S5PV210_UFCON_RXTRIG256        (7<<4)
-
-#define S5PV210_UFSTAT_TXFULL  (1<<24)
-#define S5PV210_UFSTAT_RXFULL  (1<<8)
-#define S5PV210_UFSTAT_TXMASK  (255<<16)
-#define S5PV210_UFSTAT_TXSHIFT (16)
-#define S5PV210_UFSTAT_RXMASK  (255<<0)
-#define S5PV210_UFSTAT_RXSHIFT (0)
-
-#define S3C2410_UCON_CLKSEL0   (1 << 0)
-#define S3C2410_UCON_CLKSEL1   (1 << 1)
-#define S3C2410_UCON_CLKSEL2   (1 << 2)
-#define S3C2410_UCON_CLKSEL3   (1 << 3)
-
-/* Default values for s5pv210 UCON and UFCON uart registers */
-#define S5PV210_UCON_DEFAULT   (S3C2410_UCON_TXILEVEL |        \
-                                S3C2410_UCON_RXILEVEL |        \
-                                S3C2410_UCON_TXIRQMODE |       \
-                                S3C2410_UCON_RXIRQMODE |       \
-                                S3C2410_UCON_RXFIFO_TOI |      \
-                                S3C2443_UCON_RXERR_IRQEN)
-
-#define S5PV210_UFCON_DEFAULT  (S3C2410_UFCON_FIFOMODE |       \
-                                S5PV210_UFCON_TXTRIG4 |        \
-                                S5PV210_UFCON_RXTRIG4)
-
-#ifndef __ASSEMBLY__
-
-/* configuration structure for per-machine configurations for the
- * serial port
- *
- * the pointer is setup by the machine specific initialisation from the
- * arch/arm/mach-s3c2410/ directory.
-*/
-
-struct s3c2410_uartcfg {
-       unsigned char      hwport;       /* hardware port number */
-       unsigned char      unused;
-       unsigned short     flags;
-       upf_t              uart_flags;   /* default uart flags */
-       unsigned int       clk_sel;
-
-       unsigned int       has_fracval;
-
-       unsigned long      ucon;         /* value of ucon for port */
-       unsigned long      ulcon;        /* value of ulcon for port */
-       unsigned long      ufcon;        /* value of ufcon for port */
-};
-
-/* s3c24xx_uart_devs
- *
- * this is exported from the core as we cannot use driver_register(),
- * or platform_add_device() before the console_initcall()
-*/
-
-extern struct platform_device *s3c24xx_uart_devs[4];
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __ASM_ARM_REGS_SERIAL_H */
-
+#include <linux/serial_s3c.h>
index da2f319fb71dd4aee116018b2340460eb28f4cfb..e70cadec7ce68feaa895108254b5d776227b97b9 100644 (file)
@@ -142,8 +142,7 @@ static void transmit_chars(struct tty_struct *tty, struct serial_state *info,
                goto out;
        }
 
-       if (info->xmit.head == info->xmit.tail || tty->stopped ||
-                       tty->hw_stopped) {
+       if (info->xmit.head == info->xmit.tail || tty->stopped) {
 #ifdef SIMSERIAL_DEBUG
                printk("transmit_chars: head=%d, tail=%d, stopped=%d\n",
                       info->xmit.head, info->xmit.tail, tty->stopped);
@@ -181,7 +180,7 @@ static void rs_flush_chars(struct tty_struct *tty)
        struct serial_state *info = tty->driver_data;
 
        if (info->xmit.head == info->xmit.tail || tty->stopped ||
-                       tty->hw_stopped || !info->xmit.buf)
+                       !info->xmit.buf)
                return;
 
        transmit_chars(tty, info, NULL);
@@ -217,7 +216,7 @@ static int rs_write(struct tty_struct * tty,
         * Hey, we transmit directly from here in our case
         */
        if (CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) &&
-                       !tty->stopped && !tty->hw_stopped)
+                       !tty->stopped)
                transmit_chars(tty, info, NULL);
 
        return ret;
@@ -325,14 +324,6 @@ static int rs_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
 
 #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
 
-static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-       /* Handle turning off CRTSCTS */
-       if ((old_termios->c_cflag & CRTSCTS) &&
-           !(tty->termios.c_cflag & CRTSCTS)) {
-               tty->hw_stopped = 0;
-       }
-}
 /*
  * This routine will shutdown a serial port; interrupts are disabled, and
  * DTR is dropped if the hangup on close termio flag is on.
@@ -481,7 +472,6 @@ static const struct tty_operations hp_ops = {
        .throttle = rs_throttle,
        .unthrottle = rs_unthrottle,
        .send_xchar = rs_send_xchar,
-       .set_termios = rs_set_termios,
        .hangup = rs_hangup,
        .proc_fops = &rs_proc_fops,
 };
index 80b47cb71e0a85e7ea1a10626f7a1e0efe8e5225..acbe6c67afbaa1efe09952b9c1987b17b5afa58b 100644 (file)
@@ -568,11 +568,7 @@ void chan_interrupt(struct line *line, int irq)
                reactivate_fd(chan->fd, irq);
        if (err == -EIO) {
                if (chan->primary) {
-                       struct tty_struct *tty = tty_port_tty_get(&line->port);
-                       if (tty != NULL) {
-                               tty_hangup(tty);
-                               tty_kref_put(tty);
-                       }
+                       tty_port_tty_hangup(&line->port, false);
                        if (line->chan_out != chan)
                                close_one_chan(line->chan_out, 1);
                }
index be541cf69fd282cea191a3580e851549f25c39e0..8035145f043b4f5ffbb9b8ffe26572b390184fc9 100644 (file)
@@ -248,7 +248,6 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
 {
        struct chan *chan = data;
        struct line *line = chan->line;
-       struct tty_struct *tty;
        int err;
 
        /*
@@ -267,12 +266,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
        }
        spin_unlock(&line->lock);
 
-       tty = tty_port_tty_get(&line->port);
-       if (tty == NULL)
-               return IRQ_NONE;
-
-       tty_wakeup(tty);
-       tty_kref_put(tty);
+       tty_port_tty_wakeup(&line->port);
 
        return IRQ_HANDLED;
 }
index 89562a845f6aee86af1bb5bd54f1ceef228eb2c8..ac6f72b455d174fa97c317bce1475946de7a83eb 100644 (file)
@@ -569,7 +569,6 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
 {
        struct capidev *cdev = ap->private;
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
-       struct tty_struct *tty;
        struct capiminor *mp;
        u16 datahandle;
        struct capincci *np;
@@ -627,11 +626,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
                         CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4 + 2));
                kfree_skb(skb);
                capiminor_del_ack(mp, datahandle);
-               tty = tty_port_tty_get(&mp->port);
-               if (tty) {
-                       tty_wakeup(tty);
-                       tty_kref_put(tty);
-               }
+               tty_port_tty_wakeup(&mp->port);
                handle_minor_send(mp);
 
        } else {
index e2b539675b665d72aa1fe183cd9f0a61ad0262c2..600c79b030cdb68ddfb2fefd4cd53b6d10433511 100644 (file)
@@ -487,12 +487,8 @@ static const struct tty_operations if_ops = {
 static void if_wake(unsigned long data)
 {
        struct cardstate *cs = (struct cardstate *)data;
-       struct tty_struct *tty = tty_port_tty_get(&cs->port);
 
-       if (tty) {
-               tty_wakeup(tty);
-               tty_kref_put(tty);
-       }
+       tty_port_tty_wakeup(&cs->port);
 }
 
 /*** interface to common ***/
index ebaebdf30f98dce768d187a7e471ab6455604bd3..b72afd81a7bb9928a8e32f3eb1b21f60e4791863 100644 (file)
@@ -1472,9 +1472,6 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
                    tty->termios.c_ospeed == old_termios->c_ospeed)
                        return;
                isdn_tty_change_speed(info);
-               if ((old_termios->c_cflag & CRTSCTS) &&
-                   !(tty->termios.c_cflag & CRTSCTS))
-                       tty->hw_stopped = 0;
        }
 }
 
index c931dfe6a59cb80ac893d3d2754eac7b9a07301d..f093cea0d0600797cc1574c6f85a25dac5c128fc 100644 (file)
@@ -134,7 +134,6 @@ static void sdio_uart_port_put(struct sdio_uart_port *port)
 static void sdio_uart_port_remove(struct sdio_uart_port *port)
 {
        struct sdio_func *func;
-       struct tty_struct *tty;
 
        BUG_ON(sdio_uart_table[port->index] != port);
 
@@ -155,12 +154,8 @@ static void sdio_uart_port_remove(struct sdio_uart_port *port)
        sdio_claim_host(func);
        port->func = NULL;
        mutex_unlock(&port->func_lock);
-       tty = tty_port_tty_get(&port->port);
        /* tty_hangup is async so is this safe as is ?? */
-       if (tty) {
-               tty_hangup(tty);
-               tty_kref_put(tty);
-       }
+       tty_port_tty_hangup(&port->port, false);
        mutex_unlock(&port->port.mutex);
        sdio_release_irq(func);
        sdio_disable_func(func);
@@ -492,11 +487,7 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
                        wake_up_interruptible(&port->port.open_wait);
                else {
                        /* DCD drop - hang up if tty attached */
-                       tty = tty_port_tty_get(&port->port);
-                       if (tty) {
-                               tty_hangup(tty);
-                               tty_kref_put(tty);
-                       }
+                       tty_port_tty_hangup(&port->port, false);
                }
        }
        if (status & UART_MSR_DCTS) {
index 666891a9a2482b37f8dec4bc98195fceb4039c31..be90debc7cd1b7ff01c6250ada519bba6dedbaf2 100644 (file)
@@ -88,11 +88,9 @@ static inline void update_tty_status(struct ser_device *ser)
 {
        ser->tty_status =
                ser->tty->stopped << 5 |
-               ser->tty->hw_stopped << 4 |
                ser->tty->flow_stopped << 3 |
                ser->tty->packet << 2 |
-               ser->tty->port->low_latency << 1 |
-               ser->tty->warned;
+               ser->tty->port->low_latency << 1;
 }
 static inline void debugfs_init(struct ser_device *ser, struct tty_struct *tty)
 {
index a031f6b456b4d90d0d356bc49ad330eca6570c1b..9c889e0303dd1f079c301c9a008fa8a0a094e90b 100644 (file)
@@ -314,7 +314,7 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
                /* flush our buffers and the serial port's buffer */
                if (arg == TCIOFLUSH || arg == TCOFLUSH)
                        ppp_async_flush_output(ap);
-               err = tty_perform_flush(tty, arg);
+               err = n_tty_ioctl_helper(tty, file, cmd, arg);
                break;
 
        case FIONREAD:
index 1a12033d2efafa83d2d118ead1a80262f961a441..bdf3b13a71a83991117b1d843e77f1de2d1aa415 100644 (file)
@@ -355,7 +355,7 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
                /* flush our buffers and the serial port's buffer */
                if (arg == TCIOFLUSH || arg == TCOFLUSH)
                        ppp_sync_flush_output(ap);
-               err = tty_perform_flush(tty, arg);
+               err = n_tty_ioctl_helper(tty, file, cmd, arg);
                break;
 
        case FIONREAD:
index e2dd3249b6bd3632d3d1750f2e992bea13f0178f..cba1d46e672e4cde205fbbd36fb79275cd1ecc53 100644 (file)
@@ -1925,7 +1925,6 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb)
 {
        struct hso_serial *serial = urb->context;
        int status = urb->status;
-       struct tty_struct *tty;
 
        /* sanity check */
        if (!serial) {
@@ -1941,11 +1940,7 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb)
                return;
        }
        hso_put_activity(serial->parent);
-       tty = tty_port_tty_get(&serial->port);
-       if (tty) {
-               tty_wakeup(tty);
-               tty_kref_put(tty);
-       }
+       tty_port_tty_wakeup(&serial->port);
        hso_kick_transmit(serial);
 
        D1(" ");
@@ -2008,12 +2003,8 @@ static void ctrl_callback(struct urb *urb)
                put_rxbuf_data_and_resubmit_ctrl_urb(serial);
                spin_unlock(&serial->serial_lock);
        } else {
-               struct tty_struct *tty = tty_port_tty_get(&serial->port);
                hso_put_activity(serial->parent);
-               if (tty) {
-                       tty_wakeup(tty);
-                       tty_kref_put(tty);
-               }
+               tty_port_tty_wakeup(&serial->port);
                /* response to a write command */
                hso_kick_transmit(serial);
        }
@@ -3133,18 +3124,13 @@ static void hso_serial_ref_free(struct kref *ref)
 static void hso_free_interface(struct usb_interface *interface)
 {
        struct hso_serial *hso_dev;
-       struct tty_struct *tty;
        int i;
 
        for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) {
                if (serial_table[i] &&
                    (serial_table[i]->interface == interface)) {
                        hso_dev = dev2ser(serial_table[i]);
-                       tty = tty_port_tty_get(&hso_dev->port);
-                       if (tty) {
-                               tty_hangup(tty);
-                               tty_kref_put(tty);
-                       }
+                       tty_port_tty_hangup(&hso_dev->port, false);
                        mutex_lock(&hso_dev->parent->mutex);
                        hso_dev->parent->usb_gone = 1;
                        mutex_unlock(&hso_dev->parent->mutex);
index 14b4cb8abcc8ffb41c6c56121c97bca90616ea11..7ed7a59878165bf8ef265e3fae90ee4b10017827 100644 (file)
@@ -107,7 +107,6 @@ sclp_tty_write_room (struct tty_struct *tty)
 static void
 sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc)
 {
-       struct tty_struct *tty;
        unsigned long flags;
        void *page;
 
@@ -125,12 +124,8 @@ sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc)
                                            struct sclp_buffer, list);
                spin_unlock_irqrestore(&sclp_tty_lock, flags);
        } while (buffer && sclp_emit_buffer(buffer, sclp_ttybuf_callback));
-       /* check if the tty needs a wake up call */
-       tty = tty_port_tty_get(&sclp_port);
-       if (tty != NULL) {
-               tty_wakeup(tty);
-               tty_kref_put(tty);
-       }
+
+       tty_port_tty_wakeup(&sclp_port);
 }
 
 static inline void
index 6c92f62623be4623cd7c950b6ab21d7d3c870be9..5aaaa2ec8df44f4547c70b9f80d5c628c6d9d591 100644 (file)
@@ -114,7 +114,6 @@ static struct sclp_register sclp_vt220_register = {
 static void
 sclp_vt220_process_queue(struct sclp_vt220_request *request)
 {
-       struct tty_struct *tty;
        unsigned long flags;
        void *page;
 
@@ -139,12 +138,7 @@ sclp_vt220_process_queue(struct sclp_vt220_request *request)
        } while (__sclp_vt220_emit(request));
        if (request == NULL && sclp_vt220_flush_later)
                sclp_vt220_emit_current();
-       /* Check if the tty needs a wake up call */
-       tty = tty_port_tty_get(&sclp_vt220_port);
-       if (tty) {
-               tty_wakeup(tty);
-               tty_kref_put(tty);
-       }
+       tty_port_tty_wakeup(&sclp_vt220_port);
 }
 
 #define SCLP_BUFFER_MAX_RETRY          1
index 5a6fb44f38a8ae22a2d6d8d8786b3788dc7f9f07..5c64e3a35b281dad02bac6b10d68529423cfaeb2 100644 (file)
@@ -744,7 +744,6 @@ static void fwtty_tx_complete(struct fw_card *card, int rcode,
                              struct fwtty_transaction *txn)
 {
        struct fwtty_port *port = txn->port;
-       struct tty_struct *tty;
        int len;
 
        fwtty_dbg(port, "rcode: %d", rcode);
@@ -769,13 +768,8 @@ static void fwtty_tx_complete(struct fw_card *card, int rcode,
                port->stats.dropped += txn->dma_pended.len;
        }
 
-       if (len < WAKEUP_CHARS) {
-               tty = tty_port_tty_get(&port->port);
-               if (tty) {
-                       tty_wakeup(tty);
-                       tty_kref_put(tty);
-               }
-       }
+       if (len < WAKEUP_CHARS)
+               tty_port_tty_wakeup(&port->port);
 }
 
 static int fwtty_tx(struct fwtty_port *port, bool drain)
index b1bb1a6abe8177eeab930d4963fecca11516df57..8a6e5ea476e1cf59f123742372bcb6a8a10425eb 100644 (file)
@@ -264,7 +264,6 @@ static void ProcessRxChar(struct usb_serial_port *port, unsigned char data)
 
 static void qt_write_bulk_callback(struct urb *urb)
 {
-       struct tty_struct *tty;
        int status;
        struct quatech_port *quatech_port;
 
@@ -278,11 +277,7 @@ static void qt_write_bulk_callback(struct urb *urb)
 
        quatech_port = urb->context;
 
-       tty = tty_port_tty_get(&quatech_port->port->port);
-
-       if (tty)
-               tty_wakeup(tty);
-       tty_kref_put(tty);
+       tty_port_tty_wakeup(&quatech_port->port->port);
 }
 
 static void qt_interrupt_callback(struct urb *urb)
index fc700342d43fa7cdea3999d6aea8da6fc0a5638a..083710e02367de4186a457084979eef639bf6566 100644 (file)
@@ -1798,19 +1798,7 @@ static struct platform_driver amiga_serial_driver = {
        },
 };
 
-static int __init amiga_serial_init(void)
-{
-       return platform_driver_probe(&amiga_serial_driver, amiga_serial_probe);
-}
-
-module_init(amiga_serial_init);
-
-static void __exit amiga_serial_exit(void)
-{
-       platform_driver_unregister(&amiga_serial_driver);
-}
-
-module_exit(amiga_serial_exit);
+module_platform_driver_probe(amiga_serial_driver, amiga_serial_probe);
 
 
 #if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE)
index 345bd0e0884ef73439be07a4d81741bd7a78732e..33f83fee9faec6be78206ebbc4aeee5ba1702fc8 100644 (file)
@@ -1124,14 +1124,8 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
                                        readl(&info->u.cyz.ch_ctrl->rs_status);
                                if (dcd & C_RS_DCD)
                                        wake_up_interruptible(&info->port.open_wait);
-                               else {
-                                       struct tty_struct *tty;
-                                       tty = tty_port_tty_get(&info->port);
-                                       if (tty) {
-                                               tty_hangup(tty);
-                                               tty_kref_put(tty);
-                                       }
-                               }
+                               else
+                                       tty_port_tty_hangup(&info->port, false);
                        }
                        break;
                case C_CM_MCTS:
index ed92622b8949dcdd3338388e213b67241110d3e1..6d0c27cd03da2676b91bfef307482a83be765697 100644 (file)
@@ -472,13 +472,9 @@ static void ehv_bc_tx_dequeue(struct ehv_bc_data *bc)
 static irqreturn_t ehv_bc_tty_tx_isr(int irq, void *data)
 {
        struct ehv_bc_data *bc = data;
-       struct tty_struct *ttys = tty_port_tty_get(&bc->port);
 
        ehv_bc_tx_dequeue(bc);
-       if (ttys) {
-               tty_wakeup(ttys);
-               tty_kref_put(ttys);
-       }
+       tty_port_tty_wakeup(&bc->port);
 
        return IRQ_HANDLED;
 }
index ef95a154854abc9622999df1f5248e683e3d85d5..41901997c0d62802b6ae0c165e87eca49c7be372 100644 (file)
@@ -861,7 +861,6 @@ static void hvsi_write_worker(struct work_struct *work)
 {
        struct hvsi_struct *hp =
                container_of(work, struct hvsi_struct, writer.work);
-       struct tty_struct *tty;
        unsigned long flags;
 #ifdef DEBUG
        static long start_j = 0;
@@ -895,11 +894,7 @@ static void hvsi_write_worker(struct work_struct *work)
                start_j = 0;
 #endif /* DEBUG */
                wake_up_all(&hp->emptyq);
-               tty = tty_port_tty_get(&hp->port);
-               if (tty) {
-                       tty_wakeup(tty);
-                       tty_kref_put(tty);
-               }
+               tty_port_tty_wakeup(&hp->port);
        }
 
 out:
index 97a511f4185df58d0dbe06db372b020d1890c5cb..2c14842541dd74e7d05115f2d114567b902f84a0 100644 (file)
@@ -1732,8 +1732,7 @@ void ipwireless_hardware_free(struct ipw_hardware *hw)
        flush_work(&hw->work_rx);
 
        for (i = 0; i < NL_NUM_OF_ADDRESSES; i++)
-               if (hw->packet_assembler[i] != NULL)
-                       kfree(hw->packet_assembler[i]);
+               kfree(hw->packet_assembler[i]);
 
        for (i = 0; i < NL_NUM_OF_PRIORITIES; i++)
                list_for_each_entry_safe(tp, tq, &hw->tx_queue[i], queue) {
index adeac255e526879c1d0e02ba9a747115970a1842..1deaca4674e4405fb925a50fbd289f3b9b5c74b6 100644 (file)
@@ -913,16 +913,12 @@ static void moxa_board_deinit(struct moxa_board_conf *brd)
 
        /* pci hot-un-plug support */
        for (a = 0; a < brd->numPorts; a++)
-               if (brd->ports[a].port.flags & ASYNC_INITIALIZED) {
-                       struct tty_struct *tty = tty_port_tty_get(
-                                               &brd->ports[a].port);
-                       if (tty) {
-                               tty_hangup(tty);
-                               tty_kref_put(tty);
-                       }
-               }
+               if (brd->ports[a].port.flags & ASYNC_INITIALIZED)
+                       tty_port_tty_hangup(&brd->ports[a].port, false);
+
        for (a = 0; a < MAX_PORTS_PER_BOARD; a++)
                tty_port_destroy(&brd->ports[a].port);
+
        while (1) {
                opened = 0;
                for (a = 0; a < brd->numPorts; a++)
@@ -1365,7 +1361,6 @@ static void moxa_hangup(struct tty_struct *tty)
 
 static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
 {
-       struct tty_struct *tty;
        unsigned long flags;
        dcd = !!dcd;
 
@@ -1373,10 +1368,8 @@ static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
        if (dcd != p->DCDState) {
                p->DCDState = dcd;
                spin_unlock_irqrestore(&p->port.lock, flags);
-               tty = tty_port_tty_get(&p->port);
-               if (tty && !C_CLOCAL(tty) && !dcd)
-                       tty_hangup(tty);
-               tty_kref_put(tty);
+               if (!dcd)
+                       tty_port_tty_hangup(&p->port, true);
        }
        else
                spin_unlock_irqrestore(&p->port.lock, flags);
index 302909ccf18383831e5f6091f167be354b4db989..71d6eb2c93b1c6335ba123cc9ac3c17a2af0d805 100644 (file)
@@ -1084,6 +1084,10 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
        mutex_lock(&port->mutex);
        mxser_close_port(port);
        mxser_flush_buffer(tty);
+       if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
+               if (C_HUPCL(tty))
+                       tty_port_lower_dtr_rts(port);
+       }
        mxser_shutdown_port(port);
        clear_bit(ASYNCB_INITIALIZED, &port->flags);
        mutex_unlock(&port->mutex);
index 4a43ef5d7962c9b043dc047ac16a5207f656bfa7..642239015b46bbe9e18844f186a31296a343d5f9 100644 (file)
@@ -1418,11 +1418,7 @@ static void gsm_dlci_close(struct gsm_dlci *dlci)
                pr_debug("DLCI %d goes closed.\n", dlci->addr);
        dlci->state = DLCI_CLOSED;
        if (dlci->addr != 0) {
-               struct tty_struct  *tty = tty_port_tty_get(&dlci->port);
-               if (tty) {
-                       tty_hangup(tty);
-                       tty_kref_put(tty);
-               }
+               tty_port_tty_hangup(&dlci->port, false);
                kfifo_reset(dlci->fifo);
        } else
                dlci->gsm->dead = 1;
@@ -2968,6 +2964,10 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp)
        if (tty_port_close_start(&dlci->port, tty, filp) == 0)
                goto out;
        gsm_dlci_begin_close(dlci);
+       if (test_bit(ASYNCB_INITIALIZED, &dlci->port.flags)) {
+               if (C_HUPCL(tty))
+                       tty_port_lower_dtr_rts(&dlci->port);
+       }
        tty_port_close_end(&dlci->port, tty);
        tty_port_tty_set(&dlci->port, NULL);
 out:
index 05e72bea9b07d87e31c69e291844428cb642d4be..d655416087b7099d7639923c7c0a478c72a5afbe 100644 (file)
@@ -153,6 +153,12 @@ static void n_tty_set_room(struct tty_struct *tty)
        if (left && !old_left) {
                WARN_RATELIMIT(tty->port->itty == NULL,
                                "scheduling with invalid itty\n");
+               /* see if ldisc has been killed - if so, this means that
+                * even though the ldisc has been halted and ->buf.work
+                * cancelled, ->buf.work is about to be rescheduled
+                */
+               WARN_RATELIMIT(test_bit(TTY_LDISC_HALTED, &tty->flags),
+                              "scheduling buffer work for halted ldisc\n");
                schedule_work(&tty->port->buf.work);
        }
 }
@@ -188,35 +194,18 @@ static void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
        raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
 }
 
-/**
- *     check_unthrottle        -       allow new receive data
- *     @tty; tty device
- *
- *     Check whether to call the driver unthrottle functions
- *
- *     Can sleep, may be called under the atomic_read_lock mutex but
- *     this is not guaranteed.
- */
-static void check_unthrottle(struct tty_struct *tty)
-{
-       if (tty->count)
-               tty_unthrottle(tty);
-}
-
 /**
  *     reset_buffer_flags      -       reset buffer state
  *     @tty: terminal to reset
  *
- *     Reset the read buffer counters, clear the flags,
- *     and make sure the driver is unthrottled. Called
- *     from n_tty_open() and n_tty_flush_buffer().
+ *     Reset the read buffer counters and clear the flags.
+ *     Called from n_tty_open() and n_tty_flush_buffer().
  *
  *     Locking: tty_read_lock for read fields.
  */
 
-static void reset_buffer_flags(struct tty_struct *tty)
+static void reset_buffer_flags(struct n_tty_data *ldata)
 {
-       struct n_tty_data *ldata = tty->disc_data;
        unsigned long flags;
 
        raw_spin_lock_irqsave(&ldata->read_lock, flags);
@@ -229,36 +218,38 @@ static void reset_buffer_flags(struct tty_struct *tty)
 
        ldata->canon_head = ldata->canon_data = ldata->erasing = 0;
        bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
-       n_tty_set_room(tty);
+}
+
+static void n_tty_packet_mode_flush(struct tty_struct *tty)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&tty->ctrl_lock, flags);
+       if (tty->link->packet) {
+               tty->ctrl_status |= TIOCPKT_FLUSHREAD;
+               wake_up_interruptible(&tty->link->read_wait);
+       }
+       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 }
 
 /**
  *     n_tty_flush_buffer      -       clean input queue
  *     @tty:   terminal device
  *
- *     Flush the input buffer. Called when the line discipline is
- *     being closed, when the tty layer wants the buffer flushed (eg
- *     at hangup) or when the N_TTY line discipline internally has to
- *     clean the pending queue (for example some signals).
+ *     Flush the input buffer. Called when the tty layer wants the
+ *     buffer flushed (eg at hangup) or when the N_TTY line discipline
+ *     internally has to clean the pending queue (for example some signals).
  *
  *     Locking: ctrl_lock, read_lock.
  */
 
 static void n_tty_flush_buffer(struct tty_struct *tty)
 {
-       unsigned long flags;
-       /* clear everything and unthrottle the driver */
-       reset_buffer_flags(tty);
-
-       if (!tty->link)
-               return;
+       reset_buffer_flags(tty->disc_data);
+       n_tty_set_room(tty);
 
-       spin_lock_irqsave(&tty->ctrl_lock, flags);
-       if (tty->link->packet) {
-               tty->ctrl_status |= TIOCPKT_FLUSHREAD;
-               wake_up_interruptible(&tty->link->read_wait);
-       }
-       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+       if (tty->link)
+               n_tty_packet_mode_flush(tty);
 }
 
 /**
@@ -1032,23 +1023,19 @@ static void eraser(unsigned char c, struct tty_struct *tty)
  *     isig            -       handle the ISIG optio
  *     @sig: signal
  *     @tty: terminal
- *     @flush: force flush
  *
- *     Called when a signal is being sent due to terminal input. This
- *     may caus terminal flushing to take place according to the termios
- *     settings and character used. Called from the driver receive_buf
- *     path so serialized.
+ *     Called when a signal is being sent due to terminal input.
+ *     Called from the driver receive_buf path so serialized.
  *
- *     Locking: ctrl_lock, read_lock (both via flush buffer)
+ *     Locking: ctrl_lock
  */
 
-static inline void isig(int sig, struct tty_struct *tty, int flush)
+static inline void isig(int sig, struct tty_struct *tty)
 {
-       if (tty->pgrp)
-               kill_pgrp(tty->pgrp, sig, 1);
-       if (flush || !L_NOFLSH(tty)) {
-               n_tty_flush_buffer(tty);
-               tty_driver_flush_buffer(tty);
+       struct pid *tty_pgrp = tty_get_pgrp(tty);
+       if (tty_pgrp) {
+               kill_pgrp(tty_pgrp, sig, 1);
+               put_pid(tty_pgrp);
        }
 }
 
@@ -1069,7 +1056,11 @@ static inline void n_tty_receive_break(struct tty_struct *tty)
        if (I_IGNBRK(tty))
                return;
        if (I_BRKINT(tty)) {
-               isig(SIGINT, tty, 1);
+               isig(SIGINT, tty);
+               if (!L_NOFLSH(tty)) {
+                       n_tty_flush_buffer(tty);
+                       tty_driver_flush_buffer(tty);
+               }
                return;
        }
        if (I_PARMRK(tty)) {
@@ -1236,11 +1227,6 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
                signal = SIGTSTP;
                if (c == SUSP_CHAR(tty)) {
 send_signal:
-                       /*
-                        * Note that we do not use isig() here because we want
-                        * the order to be:
-                        * 1) flush, 2) echo, 3) signal
-                        */
                        if (!L_NOFLSH(tty)) {
                                n_tty_flush_buffer(tty);
                                tty_driver_flush_buffer(tty);
@@ -1251,8 +1237,7 @@ send_signal:
                                echo_char(c, tty);
                                process_echoes(tty);
                        }
-                       if (tty->pgrp)
-                               kill_pgrp(tty->pgrp, signal, 1);
+                       isig(signal, tty);
                        return;
                }
        }
@@ -1483,14 +1468,14 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
         * mode.  We don't want to throttle the driver if we're in
         * canonical mode and don't have a newline yet!
         */
-       if (tty->receive_room < TTY_THRESHOLD_THROTTLE)
-               tty_throttle(tty);
-
-        /* FIXME: there is a tiny race here if the receive room check runs
-           before the other work executes and empties the buffer (upping
-           the receiving room and unthrottling. We then throttle and get
-           stuck. This has been observed and traced down by Vincent Pillet/
-           We need to address this when we sort out out the rx path locking */
+       while (1) {
+               tty_set_flow_change(tty, TTY_THROTTLE_SAFE);
+               if (tty->receive_room >= TTY_THRESHOLD_THROTTLE)
+                       break;
+               if (!tty_throttle_safe(tty))
+                       break;
+       }
+       __tty_set_flow_change(tty, 0);
 }
 
 int is_ignored(int sig)
@@ -1607,7 +1592,9 @@ static void n_tty_close(struct tty_struct *tty)
 {
        struct n_tty_data *ldata = tty->disc_data;
 
-       n_tty_flush_buffer(tty);
+       if (tty->link)
+               n_tty_packet_mode_flush(tty);
+
        kfree(ldata->read_buf);
        kfree(ldata->echo_buf);
        kfree(ldata);
@@ -1645,12 +1632,14 @@ static int n_tty_open(struct tty_struct *tty)
                goto err_free_bufs;
 
        tty->disc_data = ldata;
-       reset_buffer_flags(tty);
-       tty_unthrottle(tty);
+       reset_buffer_flags(tty->disc_data);
        ldata->column = 0;
-       n_tty_set_termios(tty, NULL);
        tty->minimum_to_wake = 1;
        tty->closing = 0;
+       /* indicate buffer work may resume */
+       clear_bit(TTY_LDISC_HALTED, &tty->flags);
+       n_tty_set_termios(tty, NULL);
+       tty_unthrottle(tty);
 
        return 0;
 err_free_bufs:
@@ -1740,10 +1729,9 @@ extern ssize_t redirected_tty_write(struct file *, const char __user *,
  *     and if appropriate send any needed signals and return a negative
  *     error code if action should be taken.
  *
- *     FIXME:
- *     Locking: None - redirected write test is safe, testing
- *     current->signal should possibly lock current->sighand
- *     pgrp locking ?
+ *     Locking: redirected write test is safe
+ *              current->signal->tty check is safe
+ *              ctrl_lock to safely reference tty->pgrp
  */
 
 static int job_control(struct tty_struct *tty, struct file *file)
@@ -1753,19 +1741,22 @@ static int job_control(struct tty_struct *tty, struct file *file)
        /* NOTE: not yet done after every sleep pending a thorough
           check of the logic of this change. -- jlc */
        /* don't stop on /dev/console */
-       if (file->f_op->write != redirected_tty_write &&
-           current->signal->tty == tty) {
-               if (!tty->pgrp)
-                       printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
-               else if (task_pgrp(current) != tty->pgrp) {
-                       if (is_ignored(SIGTTIN) ||
-                           is_current_pgrp_orphaned())
-                               return -EIO;
-                       kill_pgrp(task_pgrp(current), SIGTTIN, 1);
-                       set_thread_flag(TIF_SIGPENDING);
-                       return -ERESTARTSYS;
-               }
+       if (file->f_op->write == redirected_tty_write ||
+           current->signal->tty != tty)
+               return 0;
+
+       spin_lock_irq(&tty->ctrl_lock);
+       if (!tty->pgrp)
+               printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
+       else if (task_pgrp(current) != tty->pgrp) {
+               spin_unlock_irq(&tty->ctrl_lock);
+               if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned())
+                       return -EIO;
+               kill_pgrp(task_pgrp(current), SIGTTIN, 1);
+               set_thread_flag(TIF_SIGPENDING);
+               return -ERESTARTSYS;
        }
+       spin_unlock_irq(&tty->ctrl_lock);
        return 0;
 }
 
@@ -1959,10 +1950,17 @@ do_it_again:
                 * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode,
                 * we won't get any more characters.
                 */
-               if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) {
+               while (1) {
+                       tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE);
+                       if (n_tty_chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE)
+                               break;
+                       if (!tty->count)
+                               break;
                        n_tty_set_room(tty);
-                       check_unthrottle(tty);
+                       if (!tty_unthrottle_safe(tty))
+                               break;
                }
+               __tty_set_flow_change(tty, 0);
 
                if (b - buf >= minimum)
                        break;
index 2dff19796157b8ffc9c7c8bfe4aa3806b362c814..d6080c3831ef98b72d8269dc3750f58f6d55bfba 100644 (file)
@@ -791,7 +791,6 @@ static int send_data(enum port_type index, struct nozomi *dc)
        const u8 toggle = port->toggle_ul;
        void __iomem *addr = port->ul_addr[toggle];
        const u32 ul_size = port->ul_size[toggle];
-       struct tty_struct *tty = tty_port_tty_get(&port->port);
 
        /* Get data from tty and place in buf for now */
        size = kfifo_out(&port->fifo_ul, dc->send_buf,
@@ -799,7 +798,6 @@ static int send_data(enum port_type index, struct nozomi *dc)
 
        if (size == 0) {
                DBG4("No more data to send, disable link:");
-               tty_kref_put(tty);
                return 0;
        }
 
@@ -809,10 +807,8 @@ static int send_data(enum port_type index, struct nozomi *dc)
        write_mem32(addr, (u32 *) &size, 4);
        write_mem32(addr + 4, (u32 *) dc->send_buf, size);
 
-       if (tty)
-               tty_wakeup(tty);
+       tty_port_tty_wakeup(&port->port);
 
-       tty_kref_put(tty);
        return 1;
 }
 
@@ -1505,12 +1501,9 @@ static void tty_exit(struct nozomi *dc)
 
        DBG1(" ");
 
-       for (i = 0; i < MAX_PORT; ++i) {
-               struct tty_struct *tty = tty_port_tty_get(&dc->port[i].port);
-               if (tty && list_empty(&tty->hangup_work.entry))
-                       tty_hangup(tty);
-               tty_kref_put(tty);
-       }
+       for (i = 0; i < MAX_PORT; ++i)
+               tty_port_tty_hangup(&dc->port[i].port, false);
+
        /* Racy below - surely should wait for scheduled work to be done or
           complete off a hangup method ? */
        while (dc->open_ttys)
index c24b4db243b97fb97721730c6b5a7f57c2966ace..71e456aa63678a26869a99bb3abb9771529426c3 100644 (file)
@@ -413,7 +413,6 @@ static void pty_unix98_shutdown(struct tty_struct *tty)
 
 static void pty_cleanup(struct tty_struct *tty)
 {
-       tty->port->itty = NULL;
        tty_port_put(tty->port);
 }
 
index 1d270034bfc33e78a2665f61edfdec6caba8097e..f5abc28888217924629182c3943b0d270948e951 100644 (file)
@@ -449,7 +449,7 @@ static void rp_do_transmit(struct r_port *info)
 
        /*  Loop sending data to FIFO until done or FIFO full */
        while (1) {
-               if (tty->stopped || tty->hw_stopped)
+               if (tty->stopped)
                        break;
                c = min(info->xmit_fifo_room, info->xmit_cnt);
                c = min(c, XMIT_BUF_SIZE - info->xmit_tail);
@@ -521,15 +521,10 @@ static void rp_handle_port(struct r_port *info)
                       (ChanStatus & CD_ACT) ? "on" : "off");
 #endif
                if (!(ChanStatus & CD_ACT) && info->cd_status) {
-                       struct tty_struct *tty;
 #ifdef ROCKET_DEBUG_HANGUP
                        printk(KERN_INFO "CD drop, calling hangup.\n");
 #endif
-                       tty = tty_port_tty_get(&info->port);
-                       if (tty) {
-                               tty_hangup(tty);
-                               tty_kref_put(tty);
-                       }
+                       tty_port_tty_hangup(&info->port, false);
                }
                info->cd_status = (ChanStatus & CD_ACT) ? 1 : 0;
                wake_up_interruptible(&info->port.open_wait);
@@ -1111,15 +1106,12 @@ static void rp_set_termios(struct tty_struct *tty,
 
        /* Handle transition away from B0 status */
        if (!(old_termios->c_cflag & CBAUD) && (tty->termios.c_cflag & CBAUD)) {
-               if (!tty->hw_stopped || !(tty->termios.c_cflag & CRTSCTS))
-                       sSetRTS(cp);
+               sSetRTS(cp);
                sSetDTR(cp);
        }
 
-       if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios.c_cflag & CRTSCTS)) {
-               tty->hw_stopped = 0;
+       if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios.c_cflag & CRTSCTS))
                rp_start(tty);
-       }
 }
 
 static int rp_break(struct tty_struct *tty, int break_state)
@@ -1575,10 +1567,10 @@ static int rp_put_char(struct tty_struct *tty, unsigned char ch)
        spin_lock_irqsave(&info->slock, flags);
        cp = &info->channel;
 
-       if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0)
+       if (!tty->stopped && info->xmit_fifo_room == 0)
                info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
 
-       if (tty->stopped || tty->hw_stopped || info->xmit_fifo_room == 0 || info->xmit_cnt != 0) {
+       if (tty->stopped || info->xmit_fifo_room == 0 || info->xmit_cnt != 0) {
                info->xmit_buf[info->xmit_head++] = ch;
                info->xmit_head &= XMIT_BUF_SIZE - 1;
                info->xmit_cnt++;
@@ -1619,14 +1611,14 @@ static int rp_write(struct tty_struct *tty,
 #endif
        cp = &info->channel;
 
-       if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room < count)
+       if (!tty->stopped && info->xmit_fifo_room < count)
                info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
 
         /*
         *  If the write queue for the port is empty, and there is FIFO space, stuff bytes 
         *  into FIFO.  Use the write queue for temp storage.
          */
-       if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) {
+       if (!tty->stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) {
                c = min(count, info->xmit_fifo_room);
                b = buf;
 
@@ -1674,7 +1666,7 @@ static int rp_write(struct tty_struct *tty,
                retval += c;
        }
 
-       if ((retval > 0) && !tty->stopped && !tty->hw_stopped)
+       if ((retval > 0) && !tty->stopped)
                set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
        
 end:
index 49399470794d642b96a78d1dc537c60bbb49339c..ef2e08e9b5901fdd9267a66896da10f829f931ac 100644 (file)
@@ -630,8 +630,7 @@ static void rs_flush_chars(struct tty_struct *tty)
        /* Enable transmitter */
        local_irq_save(flags);
 
-       if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-                       !info->xmit_buf) {
+       if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf) {
                local_irq_restore(flags);
                return;
        }
@@ -697,7 +696,7 @@ static int rs_write(struct tty_struct * tty,
                total += c;
        }
 
-       if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
+       if (info->xmit_cnt && !tty->stopped) {
                /* Enable transmitter */
                local_irq_disable();            
 #ifndef USE_INTS
@@ -978,10 +977,8 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
        change_speed(info, tty);
 
        if ((old_termios->c_cflag & CRTSCTS) &&
-           !(tty->termios.c_cflag & CRTSCTS)) {
-               tty->hw_stopped = 0;
+           !(tty->termios.c_cflag & CRTSCTS))
                rs_start(tty);
-       }
        
 }
 
index 34eb676916fe372e43a948895b512bc5ca51ed09..1ebf8538b4fa8aa31eacd34bc9c8cb2c2159770f 100644 (file)
@@ -117,13 +117,6 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value)
  * is cleared, the machine locks up with endless interrupts.
  */
 #define ALPHA_KLUDGE_MCR  (UART_MCR_OUT2 | UART_MCR_OUT1)
-#elif defined(CONFIG_SBC8560)
-/*
- * WindRiver did something similarly broken on their SBC8560 board. The
- * UART tristates its IRQ output while OUT2 is clear, but they pulled
- * the interrupt line _up_ instead of down, so if we register the IRQ
- * while the UART is in that state, we die in an IRQ storm. */
-#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2)
 #else
 #define ALPHA_KLUDGE_MCR 0
 #endif
index 35f9c96aada9c9f6d31238accab3ddd7887ed2fb..46528d57be72b710513a65ad2494ae839774981a 100644 (file)
@@ -2755,7 +2755,7 @@ static void __init serial8250_isa_init_ports(void)
        if (nr_uarts > UART_NR)
                nr_uarts = UART_NR;
 
-       for (i = 0; i < nr_uarts; i++) {
+       for (i = 0; i < UART_NR; i++) {
                struct uart_8250_port *up = &serial8250_ports[i];
                struct uart_port *port = &up->port;
 
@@ -2916,7 +2916,7 @@ static int __init serial8250_console_setup(struct console *co, char *options)
         * if so, search for the first available port that does have
         * console support.
         */
-       if (co->index >= nr_uarts)
+       if (co->index >= UART_NR)
                co->index = 0;
        port = &serial8250_ports[co->index].port;
        if (!port->iobase && !port->membase)
@@ -2957,7 +2957,7 @@ int serial8250_find_port(struct uart_port *p)
        int line;
        struct uart_port *port;
 
-       for (line = 0; line < nr_uarts; line++) {
+       for (line = 0; line < UART_NR; line++) {
                port = &serial8250_ports[line].port;
                if (uart_match_port(p, port))
                        return line;
@@ -3110,7 +3110,7 @@ static int serial8250_remove(struct platform_device *dev)
 {
        int i;
 
-       for (i = 0; i < nr_uarts; i++) {
+       for (i = 0; i < UART_NR; i++) {
                struct uart_8250_port *up = &serial8250_ports[i];
 
                if (up->port.dev == &dev->dev)
@@ -3178,7 +3178,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
        /*
         * First, find a port entry which matches.
         */
-       for (i = 0; i < nr_uarts; i++)
+       for (i = 0; i < UART_NR; i++)
                if (uart_match_port(&serial8250_ports[i].port, port))
                        return &serial8250_ports[i];
 
@@ -3187,7 +3187,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
         * free entry.  We look for one which hasn't been previously
         * used (indicated by zero iobase).
         */
-       for (i = 0; i < nr_uarts; i++)
+       for (i = 0; i < UART_NR; i++)
                if (serial8250_ports[i].port.type == PORT_UNKNOWN &&
                    serial8250_ports[i].port.iobase == 0)
                        return &serial8250_ports[i];
@@ -3196,7 +3196,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
         * That also failed.  Last resort is to find any entry which
         * doesn't have a real port associated with it.
         */
-       for (i = 0; i < nr_uarts; i++)
+       for (i = 0; i < UART_NR; i++)
                if (serial8250_ports[i].port.type == PORT_UNKNOWN)
                        return &serial8250_ports[i];
 
@@ -3247,6 +3247,10 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
                uart->tx_loadsz         = up->tx_loadsz;
                uart->capabilities      = up->capabilities;
 
+               /* Take tx_loadsz from fifosize if it wasn't set separately */
+               if (uart->port.fifosize && !uart->tx_loadsz)
+                       uart->tx_loadsz = uart->port.fifosize;
+
                if (up->port.dev)
                        uart->port.dev = up->port.dev;
 
index b9f7fd28112e3aba78a4f595520769baf8e538d4..7046769608d403501158a044fd109203f0e0531f 100644 (file)
@@ -33,10 +33,8 @@ static void __dma_tx_complete(void *param)
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
                uart_write_wakeup(&p->port);
 
-       if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) {
+       if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port))
                serial8250_tx_dma(p);
-               uart_write_wakeup(&p->port);
-       }
 }
 
 static void __dma_rx_complete(void *param)
@@ -67,12 +65,11 @@ int serial8250_tx_dma(struct uart_8250_port *p)
        struct circ_buf                 *xmit = &p->port.state->xmit;
        struct dma_async_tx_descriptor  *desc;
 
-       if (dma->tx_running)
-               return -EBUSY;
+       if (uart_tx_stopped(&p->port) || dma->tx_running ||
+           uart_circ_empty(xmit))
+               return 0;
 
        dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
-       if (!dma->tx_size)
-               return -EINVAL;
 
        desc = dmaengine_prep_slave_single(dma->txchan,
                                           dma->tx_addr + xmit->tail,
@@ -104,20 +101,29 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
        struct dma_tx_state             state;
        int                             dma_status;
 
-       /*
-        * If RCVR FIFO trigger level was not reached, complete the transfer and
-        * let 8250.c copy the remaining data.
-        */
-       if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT) {
-               dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie,
-                                               &state);
+       dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
+
+       switch (iir & 0x3f) {
+       case UART_IIR_RLSI:
+               /* 8250_core handles errors and break interrupts */
+               return -EIO;
+       case UART_IIR_RX_TIMEOUT:
+               /*
+                * If RCVR FIFO trigger level was not reached, complete the
+                * transfer and let 8250_core copy the remaining data.
+                */
                if (dma_status == DMA_IN_PROGRESS) {
                        dmaengine_pause(dma->rxchan);
                        __dma_rx_complete(p);
                }
                return -ETIMEDOUT;
+       default:
+               break;
        }
 
+       if (dma_status)
+               return 0;
+
        desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
                                           dma->rx_size, DMA_DEV_TO_MEM,
                                           DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
@@ -143,21 +149,31 @@ int serial8250_request_dma(struct uart_8250_port *p)
        struct uart_8250_dma    *dma = p->dma;
        dma_cap_mask_t          mask;
 
-       dma->rxconf.src_addr = p->port.mapbase + UART_RX;
-       dma->txconf.dst_addr = p->port.mapbase + UART_TX;
+       /* Default slave configuration parameters */
+       dma->rxconf.direction           = DMA_DEV_TO_MEM;
+       dma->rxconf.src_addr_width      = DMA_SLAVE_BUSWIDTH_1_BYTE;
+       dma->rxconf.src_addr            = p->port.mapbase + UART_RX;
+
+       dma->txconf.direction           = DMA_MEM_TO_DEV;
+       dma->txconf.dst_addr_width      = DMA_SLAVE_BUSWIDTH_1_BYTE;
+       dma->txconf.dst_addr            = p->port.mapbase + UART_TX;
 
        dma_cap_zero(mask);
        dma_cap_set(DMA_SLAVE, mask);
 
        /* Get a channel for RX */
-       dma->rxchan = dma_request_channel(mask, dma->fn, dma->rx_param);
+       dma->rxchan = dma_request_slave_channel_compat(mask,
+                                                      dma->fn, dma->rx_param,
+                                                      p->port.dev, "rx");
        if (!dma->rxchan)
                return -ENODEV;
 
        dmaengine_slave_config(dma->rxchan, &dma->rxconf);
 
        /* Get a channel for TX */
-       dma->txchan = dma_request_channel(mask, dma->fn, dma->tx_param);
+       dma->txchan = dma_request_slave_channel_compat(mask,
+                                                      dma->fn, dma->tx_param,
+                                                      p->port.dev, "tx");
        if (!dma->txchan) {
                dma_release_channel(dma->rxchan);
                return -ENODEV;
index db0e66f6dd0e3a4458521546cfb11cdc0fccf0dc..beaa283f5cc6f75c24484b11beb73704f25a6ccd 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
 
 #include "8250.h"
 
@@ -34,9 +36,6 @@
 #define DW_UART_CPR    0xf4 /* Component Parameter Register */
 #define DW_UART_UCV    0xf8 /* UART Component Version */
 
-/* Intel Low Power Subsystem specific */
-#define LPSS_PRV_CLOCK_PARAMS 0x800
-
 /* Component Parameter Register bits */
 #define DW_UART_CPR_ABP_DATA_WIDTH     (3 << 0)
 #define DW_UART_CPR_AFCE_MODE          (1 << 4)
@@ -55,8 +54,9 @@
 
 
 struct dw8250_data {
-       int     last_lcr;
-       int     line;
+       int             last_lcr;
+       int             line;
+       struct clk      *clk;
 };
 
 static void dw8250_serial_out(struct uart_port *p, int offset, int value)
@@ -113,6 +113,18 @@ static int dw8250_handle_irq(struct uart_port *p)
        return 0;
 }
 
+static void
+dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
+{
+       if (!state)
+               pm_runtime_get_sync(port->dev);
+
+       serial8250_do_pm(port, state, old);
+
+       if (state)
+               pm_runtime_put_sync_suspend(port->dev);
+}
+
 static int dw8250_probe_of(struct uart_port *p)
 {
        struct device_node      *np = p->dev->of_node;
@@ -136,8 +148,13 @@ static int dw8250_probe_of(struct uart_port *p)
        if (!of_property_read_u32(np, "reg-shift", &val))
                p->regshift = val;
 
+       /* clock got configured through clk api, all done */
+       if (p->uartclk)
+               return 0;
+
+       /* try to find out clock frequency from DT as fallback */
        if (of_property_read_u32(np, "clock-frequency", &val)) {
-               dev_err(p->dev, "no clock-frequency property set\n");
+               dev_err(p->dev, "clk or clock-frequency not defined\n");
                return -EINVAL;
        }
        p->uartclk = val;
@@ -146,67 +163,10 @@ static int dw8250_probe_of(struct uart_port *p)
 }
 
 #ifdef CONFIG_ACPI
-static bool dw8250_acpi_dma_filter(struct dma_chan *chan, void *parm)
-{
-       return chan->chan_id == *(int *)parm;
-}
-
-static acpi_status
-dw8250_acpi_walk_resource(struct acpi_resource *res, void *data)
-{
-       struct uart_port                *p = data;
-       struct uart_8250_port           *port;
-       struct uart_8250_dma            *dma;
-       struct acpi_resource_fixed_dma  *fixed_dma;
-       struct dma_slave_config         *slave;
-
-       port = container_of(p, struct uart_8250_port, port);
-
-       switch (res->type) {
-       case ACPI_RESOURCE_TYPE_FIXED_DMA:
-               fixed_dma = &res->data.fixed_dma;
-
-               /* TX comes first */
-               if (!port->dma) {
-                       dma = devm_kzalloc(p->dev, sizeof(*dma), GFP_KERNEL);
-                       if (!dma)
-                               return AE_NO_MEMORY;
-
-                       port->dma = dma;
-                       slave = &dma->txconf;
-
-                       slave->direction        = DMA_MEM_TO_DEV;
-                       slave->dst_addr_width   = DMA_SLAVE_BUSWIDTH_1_BYTE;
-                       slave->slave_id         = fixed_dma->request_lines;
-                       slave->dst_maxburst     = port->tx_loadsz / 4;
-
-                       dma->tx_chan_id         = fixed_dma->channels;
-                       dma->tx_param           = &dma->tx_chan_id;
-                       dma->fn                 = dw8250_acpi_dma_filter;
-               } else {
-                       dma = port->dma;
-                       slave = &dma->rxconf;
-
-                       slave->direction        = DMA_DEV_TO_MEM;
-                       slave->src_addr_width   = DMA_SLAVE_BUSWIDTH_1_BYTE;
-                       slave->slave_id         = fixed_dma->request_lines;
-                       slave->src_maxburst     = p->fifosize / 4;
-
-                       dma->rx_chan_id         = fixed_dma->channels;
-                       dma->rx_param           = &dma->rx_chan_id;
-               }
-
-               break;
-       }
-
-       return AE_OK;
-}
-
-static int dw8250_probe_acpi(struct uart_port *p)
+static int dw8250_probe_acpi(struct uart_8250_port *up)
 {
        const struct acpi_device_id *id;
-       acpi_status status;
-       u32 reg;
+       struct uart_port *p = &up->port;
 
        id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev);
        if (!id)
@@ -216,26 +176,21 @@ static int dw8250_probe_acpi(struct uart_port *p)
        p->serial_in = dw8250_serial_in32;
        p->serial_out = dw8250_serial_out32;
        p->regshift = 2;
-       p->uartclk = (unsigned int)id->driver_data;
 
-       status = acpi_walk_resources(ACPI_HANDLE(p->dev), METHOD_NAME__CRS,
-                                    dw8250_acpi_walk_resource, p);
-       if (ACPI_FAILURE(status)) {
-               dev_err_ratelimited(p->dev, "%s failed \"%s\"\n", __func__,
-                                   acpi_format_exception(status));
-               return -ENODEV;
-       }
+       if (!p->uartclk)
+               p->uartclk = (unsigned int)id->driver_data;
 
-       /* Fix Haswell issue where the clocks do not get enabled */
-       if (!strcmp(id->id, "INT33C4") || !strcmp(id->id, "INT33C5")) {
-               reg = readl(p->membase + LPSS_PRV_CLOCK_PARAMS);
-               writel(reg | 1, p->membase + LPSS_PRV_CLOCK_PARAMS);
-       }
+       up->dma = devm_kzalloc(p->dev, sizeof(*up->dma), GFP_KERNEL);
+       if (!up->dma)
+               return -ENOMEM;
+
+       up->dma->rxconf.src_maxburst = p->fifosize / 4;
+       up->dma->txconf.dst_maxburst = p->fifosize / 4;
 
        return 0;
 }
 #else
-static inline int dw8250_probe_acpi(struct uart_port *p)
+static inline int dw8250_probe_acpi(struct uart_8250_port *up)
 {
        return -ENODEV;
 }
@@ -266,7 +221,11 @@ static void dw8250_setup_port(struct uart_8250_port *up)
                p->flags |= UPF_FIXED_TYPE;
                p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
                up->tx_loadsz = p->fifosize;
+               up->capabilities = UART_CAP_FIFO;
        }
+
+       if (reg & DW_UART_CPR_AFCE_MODE)
+               up->capabilities |= UART_CAP_AFE;
 }
 
 static int dw8250_probe(struct platform_device *pdev)
@@ -286,17 +245,30 @@ static int dw8250_probe(struct platform_device *pdev)
        uart.port.mapbase = regs->start;
        uart.port.irq = irq->start;
        uart.port.handle_irq = dw8250_handle_irq;
+       uart.port.pm = dw8250_do_pm;
        uart.port.type = PORT_8250;
        uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
        uart.port.dev = &pdev->dev;
 
-       uart.port.membase = ioremap(regs->start, resource_size(regs));
+       uart.port.membase = devm_ioremap(&pdev->dev, regs->start,
+                                        resource_size(regs));
        if (!uart.port.membase)
                return -ENOMEM;
 
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       data->clk = devm_clk_get(&pdev->dev, NULL);
+       if (!IS_ERR(data->clk)) {
+               clk_prepare_enable(data->clk);
+               uart.port.uartclk = clk_get_rate(data->clk);
+       }
+
        uart.port.iotype = UPIO_MEM;
        uart.port.serial_in = dw8250_serial_in;
        uart.port.serial_out = dw8250_serial_out;
+       uart.port.private_data = data;
 
        dw8250_setup_port(&uart);
 
@@ -305,25 +277,22 @@ static int dw8250_probe(struct platform_device *pdev)
                if (err)
                        return err;
        } else if (ACPI_HANDLE(&pdev->dev)) {
-               err = dw8250_probe_acpi(&uart.port);
+               err = dw8250_probe_acpi(&uart);
                if (err)
                        return err;
        } else {
                return -ENODEV;
        }
 
-       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       uart.port.private_data = data;
-
        data->line = serial8250_register_8250_port(&uart);
        if (data->line < 0)
                return data->line;
 
        platform_set_drvdata(pdev, data);
 
+       pm_runtime_set_active(&pdev->dev);
+       pm_runtime_enable(&pdev->dev);
+
        return 0;
 }
 
@@ -331,34 +300,64 @@ static int dw8250_remove(struct platform_device *pdev)
 {
        struct dw8250_data *data = platform_get_drvdata(pdev);
 
+       pm_runtime_get_sync(&pdev->dev);
+
        serial8250_unregister_port(data->line);
 
+       if (!IS_ERR(data->clk))
+               clk_disable_unprepare(data->clk);
+
+       pm_runtime_disable(&pdev->dev);
+       pm_runtime_put_noidle(&pdev->dev);
+
        return 0;
 }
 
 #ifdef CONFIG_PM
-static int dw8250_suspend(struct platform_device *pdev, pm_message_t state)
+static int dw8250_suspend(struct device *dev)
 {
-       struct dw8250_data *data = platform_get_drvdata(pdev);
+       struct dw8250_data *data = dev_get_drvdata(dev);
 
        serial8250_suspend_port(data->line);
 
        return 0;
 }
 
-static int dw8250_resume(struct platform_device *pdev)
+static int dw8250_resume(struct device *dev)
 {
-       struct dw8250_data *data = platform_get_drvdata(pdev);
+       struct dw8250_data *data = dev_get_drvdata(dev);
 
        serial8250_resume_port(data->line);
 
        return 0;
 }
-#else
-#define dw8250_suspend NULL
-#define dw8250_resume NULL
 #endif /* CONFIG_PM */
 
+#ifdef CONFIG_PM_RUNTIME
+static int dw8250_runtime_suspend(struct device *dev)
+{
+       struct dw8250_data *data = dev_get_drvdata(dev);
+
+       clk_disable_unprepare(data->clk);
+
+       return 0;
+}
+
+static int dw8250_runtime_resume(struct device *dev)
+{
+       struct dw8250_data *data = dev_get_drvdata(dev);
+
+       clk_prepare_enable(data->clk);
+
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops dw8250_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(dw8250_suspend, dw8250_resume)
+       SET_RUNTIME_PM_OPS(dw8250_runtime_suspend, dw8250_runtime_resume, NULL)
+};
+
 static const struct of_device_id dw8250_of_match[] = {
        { .compatible = "snps,dw-apb-uart" },
        { /* Sentinel */ }
@@ -366,8 +365,8 @@ static const struct of_device_id dw8250_of_match[] = {
 MODULE_DEVICE_TABLE(of, dw8250_of_match);
 
 static const struct acpi_device_id dw8250_acpi_match[] = {
-       { "INT33C4", 100000000 },
-       { "INT33C5", 100000000 },
+       { "INT33C4", 0 },
+       { "INT33C5", 0 },
        { },
 };
 MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
@@ -376,13 +375,12 @@ static struct platform_driver dw8250_platform_driver = {
        .driver = {
                .name           = "dw-apb-uart",
                .owner          = THIS_MODULE,
+               .pm             = &dw8250_pm_ops,
                .of_match_table = dw8250_of_match,
                .acpi_match_table = ACPI_PTR(dw8250_acpi_match),
        },
        .probe                  = dw8250_probe,
        .remove                 = dw8250_remove,
-       .suspend                = dw8250_suspend,
-       .resume                 = dw8250_resume,
 };
 
 module_platform_driver(dw8250_platform_driver);
index 3ea5408fcbeb07e236f04ea11c961058e032cb3a..6cf861efb2afaf3ef5639cb2077ff40092f7529d 100644 (file)
@@ -29,6 +29,7 @@
  * and hooked into this driver.
  */
 
+
 #if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
 #endif
@@ -117,6 +118,12 @@ struct pl011_dmarx_data {
        struct pl011_sgbuf      sgbuf_b;
        dma_cookie_t            cookie;
        bool                    running;
+       struct timer_list       timer;
+       unsigned int last_residue;
+       unsigned long last_jiffies;
+       bool auto_poll_rate;
+       unsigned int poll_rate;
+       unsigned int poll_timeout;
 };
 
 struct pl011_dmatx_data {
@@ -223,16 +230,18 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)
 static int pl011_sgbuf_init(struct dma_chan *chan, struct pl011_sgbuf *sg,
        enum dma_data_direction dir)
 {
-       sg->buf = kmalloc(PL011_DMA_BUFFER_SIZE, GFP_KERNEL);
+       dma_addr_t dma_addr;
+
+       sg->buf = dma_alloc_coherent(chan->device->dev,
+               PL011_DMA_BUFFER_SIZE, &dma_addr, GFP_KERNEL);
        if (!sg->buf)
                return -ENOMEM;
 
-       sg_init_one(&sg->sg, sg->buf, PL011_DMA_BUFFER_SIZE);
+       sg_init_table(&sg->sg, 1);
+       sg_set_page(&sg->sg, phys_to_page(dma_addr),
+               PL011_DMA_BUFFER_SIZE, offset_in_page(dma_addr));
+       sg_dma_address(&sg->sg) = dma_addr;
 
-       if (dma_map_sg(chan->device->dev, &sg->sg, 1, dir) != 1) {
-               kfree(sg->buf);
-               return -EINVAL;
-       }
        return 0;
 }
 
@@ -240,8 +249,9 @@ static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg,
        enum dma_data_direction dir)
 {
        if (sg->buf) {
-               dma_unmap_sg(chan->device->dev, &sg->sg, 1, dir);
-               kfree(sg->buf);
+               dma_free_coherent(chan->device->dev,
+                       PL011_DMA_BUFFER_SIZE, sg->buf,
+                       sg_dma_address(&sg->sg));
        }
 }
 
@@ -300,6 +310,29 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
                dmaengine_slave_config(chan, &rx_conf);
                uap->dmarx.chan = chan;
 
+               if (plat->dma_rx_poll_enable) {
+                       /* Set poll rate if specified. */
+                       if (plat->dma_rx_poll_rate) {
+                               uap->dmarx.auto_poll_rate = false;
+                               uap->dmarx.poll_rate = plat->dma_rx_poll_rate;
+                       } else {
+                               /*
+                                * 100 ms defaults to poll rate if not
+                                * specified. This will be adjusted with
+                                * the baud rate at set_termios.
+                                */
+                               uap->dmarx.auto_poll_rate = true;
+                               uap->dmarx.poll_rate =  100;
+                       }
+                       /* 3 secs defaults poll_timeout if not specified. */
+                       if (plat->dma_rx_poll_timeout)
+                               uap->dmarx.poll_timeout =
+                                       plat->dma_rx_poll_timeout;
+                       else
+                               uap->dmarx.poll_timeout = 3000;
+               } else
+                       uap->dmarx.auto_poll_rate = false;
+
                dev_info(uap->port.dev, "DMA channel RX %s\n",
                         dma_chan_name(uap->dmarx.chan));
        }
@@ -701,24 +734,30 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
        struct tty_port *port = &uap->port.state->port;
        struct pl011_sgbuf *sgbuf = use_buf_b ?
                &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a;
-       struct device *dev = uap->dmarx.chan->device->dev;
        int dma_count = 0;
        u32 fifotaken = 0; /* only used for vdbg() */
 
-       /* Pick everything from the DMA first */
+       struct pl011_dmarx_data *dmarx = &uap->dmarx;
+       int dmataken = 0;
+
+       if (uap->dmarx.poll_rate) {
+               /* The data can be taken by polling */
+               dmataken = sgbuf->sg.length - dmarx->last_residue;
+               /* Recalculate the pending size */
+               if (pending >= dmataken)
+                       pending -= dmataken;
+       }
+
+       /* Pick the remain data from the DMA */
        if (pending) {
-               /* Sync in buffer */
-               dma_sync_sg_for_cpu(dev, &sgbuf->sg, 1, DMA_FROM_DEVICE);
 
                /*
                 * First take all chars in the DMA pipe, then look in the FIFO.
                 * Note that tty_insert_flip_buf() tries to take as many chars
                 * as it can.
                 */
-               dma_count = tty_insert_flip_string(port, sgbuf->buf, pending);
-
-               /* Return buffer to device */
-               dma_sync_sg_for_device(dev, &sgbuf->sg, 1, DMA_FROM_DEVICE);
+               dma_count = tty_insert_flip_string(port, sgbuf->buf + dmataken,
+                               pending);
 
                uap->port.icount.rx += dma_count;
                if (dma_count < pending)
@@ -726,6 +765,10 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
                                 "couldn't insert all characters (TTY is full?)\n");
        }
 
+       /* Reset the last_residue for Rx DMA poll */
+       if (uap->dmarx.poll_rate)
+               dmarx->last_residue = sgbuf->sg.length;
+
        /*
         * Only continue with trying to read the FIFO if all DMA chars have
         * been taken first.
@@ -865,6 +908,57 @@ static inline void pl011_dma_rx_stop(struct uart_amba_port *uap)
        writew(uap->dmacr, uap->port.membase + UART011_DMACR);
 }
 
+/*
+ * Timer handler for Rx DMA polling.
+ * Every polling, It checks the residue in the dma buffer and transfer
+ * data to the tty. Also, last_residue is updated for the next polling.
+ */
+static void pl011_dma_rx_poll(unsigned long args)
+{
+       struct uart_amba_port *uap = (struct uart_amba_port *)args;
+       struct tty_port *port = &uap->port.state->port;
+       struct pl011_dmarx_data *dmarx = &uap->dmarx;
+       struct dma_chan *rxchan = uap->dmarx.chan;
+       unsigned long flags = 0;
+       unsigned int dmataken = 0;
+       unsigned int size = 0;
+       struct pl011_sgbuf *sgbuf;
+       int dma_count;
+       struct dma_tx_state state;
+
+       sgbuf = dmarx->use_buf_b ? &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a;
+       rxchan->device->device_tx_status(rxchan, dmarx->cookie, &state);
+       if (likely(state.residue < dmarx->last_residue)) {
+               dmataken = sgbuf->sg.length - dmarx->last_residue;
+               size = dmarx->last_residue - state.residue;
+               dma_count = tty_insert_flip_string(port, sgbuf->buf + dmataken,
+                               size);
+               if (dma_count == size)
+                       dmarx->last_residue =  state.residue;
+               dmarx->last_jiffies = jiffies;
+       }
+       tty_flip_buffer_push(port);
+
+       /*
+        * If no data is received in poll_timeout, the driver will fall back
+        * to interrupt mode. We will retrigger DMA at the first interrupt.
+        */
+       if (jiffies_to_msecs(jiffies - dmarx->last_jiffies)
+                       > uap->dmarx.poll_timeout) {
+
+               spin_lock_irqsave(&uap->port.lock, flags);
+               pl011_dma_rx_stop(uap);
+               spin_unlock_irqrestore(&uap->port.lock, flags);
+
+               uap->dmarx.running = false;
+               dmaengine_terminate_all(rxchan);
+               del_timer(&uap->dmarx.timer);
+       } else {
+               mod_timer(&uap->dmarx.timer,
+                       jiffies + msecs_to_jiffies(uap->dmarx.poll_rate));
+       }
+}
+
 static void pl011_dma_startup(struct uart_amba_port *uap)
 {
        int ret;
@@ -927,6 +1021,16 @@ skip_rx:
                if (pl011_dma_rx_trigger_dma(uap))
                        dev_dbg(uap->port.dev, "could not trigger initial "
                                "RX DMA job, fall back to interrupt mode\n");
+               if (uap->dmarx.poll_rate) {
+                       init_timer(&(uap->dmarx.timer));
+                       uap->dmarx.timer.function = pl011_dma_rx_poll;
+                       uap->dmarx.timer.data = (unsigned long)uap;
+                       mod_timer(&uap->dmarx.timer,
+                               jiffies +
+                               msecs_to_jiffies(uap->dmarx.poll_rate));
+                       uap->dmarx.last_residue = PL011_DMA_BUFFER_SIZE;
+                       uap->dmarx.last_jiffies = jiffies;
+               }
        }
 }
 
@@ -962,6 +1066,8 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
                /* Clean up the RX DMA */
                pl011_sgbuf_free(uap->dmarx.chan, &uap->dmarx.sgbuf_a, DMA_FROM_DEVICE);
                pl011_sgbuf_free(uap->dmarx.chan, &uap->dmarx.sgbuf_b, DMA_FROM_DEVICE);
+               if (uap->dmarx.poll_rate)
+                       del_timer_sync(&uap->dmarx.timer);
                uap->using_rx_dma = false;
        }
 }
@@ -976,7 +1082,6 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
        return uap->using_rx_dma && uap->dmarx.running;
 }
 
-
 #else
 /* Blank functions if the DMA engine is not available */
 static inline void pl011_dma_probe(struct uart_amba_port *uap)
@@ -1088,8 +1193,20 @@ static void pl011_rx_chars(struct uart_amba_port *uap)
                        dev_dbg(uap->port.dev, "could not trigger RX DMA job "
                                "fall back to interrupt mode again\n");
                        uap->im |= UART011_RXIM;
-               } else
+               } else {
                        uap->im &= ~UART011_RXIM;
+#ifdef CONFIG_DMA_ENGINE
+                       /* Start Rx DMA poll */
+                       if (uap->dmarx.poll_rate) {
+                               uap->dmarx.last_jiffies = jiffies;
+                               uap->dmarx.last_residue = PL011_DMA_BUFFER_SIZE;
+                               mod_timer(&uap->dmarx.timer,
+                                       jiffies +
+                                       msecs_to_jiffies(uap->dmarx.poll_rate));
+                       }
+#endif
+               }
+
                writew(uap->im, uap->port.membase + UART011_IMSC);
        }
        spin_lock(&uap->port.lock);
@@ -1164,7 +1281,6 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
        unsigned int dummy_read;
 
        spin_lock_irqsave(&uap->port.lock, flags);
-
        status = readw(uap->port.membase + UART011_MIS);
        if (status) {
                do {
@@ -1551,6 +1667,13 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
         */
        baud = uart_get_baud_rate(port, termios, old, 0,
                                  port->uartclk / clkdiv);
+#ifdef CONFIG_DMA_ENGINE
+       /*
+        * Adjust RX DMA polling rate with baud rate if not specified.
+        */
+       if (uap->dmarx.auto_poll_rate)
+               uap->dmarx.poll_rate = DIV_ROUND_UP(10000000, baud);
+#endif
 
        if (baud > port->uartclk/16)
                quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud);
index d97e194b6bc5cff768d63cd0c4a3357363f1e8f2..cbf1d155b7b2a8c80ef782443edbf77c0e7f5595 100644 (file)
@@ -162,7 +162,7 @@ static unsigned int arc_serial_tx_empty(struct uart_port *port)
 /*
  * Driver internal routine, used by both tty(serial core) as well as tx-isr
  *  -Called under spinlock in either cases
- *  -also tty->stopped / tty->hw_stopped has already been checked
+ *  -also tty->stopped has already been checked
  *     = by uart_start( ) before calling us
  *     = tx_ist checks that too before calling
  */
index 12dceda9db3390d64a13022a639a973c9d653286..26a3be7ced7d92df93616f2a50363970a93de67b 100644 (file)
@@ -1011,24 +1011,6 @@ static int bfin_serial_poll_get_char(struct uart_port *port)
 }
 #endif
 
-#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
-       defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
-static void bfin_kgdboc_port_shutdown(struct uart_port *port)
-{
-       if (kgdboc_break_enabled) {
-               kgdboc_break_enabled = 0;
-               bfin_serial_shutdown(port);
-       }
-}
-
-static int bfin_kgdboc_port_startup(struct uart_port *port)
-{
-       kgdboc_port_line = port->line;
-       kgdboc_break_enabled = !bfin_serial_startup(port);
-       return 0;
-}
-#endif
-
 static struct uart_ops bfin_serial_pops = {
        .tx_empty       = bfin_serial_tx_empty,
        .set_mctrl      = bfin_serial_set_mctrl,
@@ -1047,11 +1029,6 @@ static struct uart_ops bfin_serial_pops = {
        .request_port   = bfin_serial_request_port,
        .config_port    = bfin_serial_config_port,
        .verify_port    = bfin_serial_verify_port,
-#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
-       defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
-       .kgdboc_port_startup    = bfin_kgdboc_port_startup,
-       .kgdboc_port_shutdown   = bfin_kgdboc_port_shutdown,
-#endif
 #ifdef CONFIG_CONSOLE_POLL
        .poll_put_char  = bfin_serial_poll_put_char,
        .poll_get_char  = bfin_serial_poll_get_char,
index 5f37c31e32bc848678c89f0147cfc00ee5441461..477f22f773fc3c17b5dd2732a45c6fce4d955725 100644 (file)
@@ -169,7 +169,6 @@ static int get_lsr_info(struct e100_serial *info, unsigned int *value);
 
 
 #define DEF_BAUD 115200   /* 115.2 kbit/s */
-#define STD_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
 #define DEF_RX 0x20  /* or SERIAL_CTRL_W >> 8 */
 /* Default value of tx_ctrl register: has txd(bit 7)=1 (idle) as default */
 #define DEF_TX 0x80  /* or SERIAL_CTRL_B */
@@ -246,7 +245,6 @@ static struct e100_serial rs_table[] = {
          .ifirstadr   = R_DMA_CH7_FIRST,
          .icmdadr     = R_DMA_CH7_CMD,
          .idescradr   = R_DMA_CH7_DESCR,
-         .flags       = STD_FLAGS,
          .rx_ctrl     = DEF_RX,
          .tx_ctrl     = DEF_TX,
          .iseteop     = 2,
@@ -300,7 +298,6 @@ static struct e100_serial rs_table[] = {
          .ifirstadr   = R_DMA_CH9_FIRST,
          .icmdadr     = R_DMA_CH9_CMD,
          .idescradr   = R_DMA_CH9_DESCR,
-         .flags       = STD_FLAGS,
          .rx_ctrl     = DEF_RX,
          .tx_ctrl     = DEF_TX,
          .iseteop     = 3,
@@ -356,7 +353,6 @@ static struct e100_serial rs_table[] = {
          .ifirstadr   = R_DMA_CH3_FIRST,
          .icmdadr     = R_DMA_CH3_CMD,
          .idescradr   = R_DMA_CH3_DESCR,
-         .flags       = STD_FLAGS,
          .rx_ctrl     = DEF_RX,
          .tx_ctrl     = DEF_TX,
          .iseteop     = 0,
@@ -410,7 +406,6 @@ static struct e100_serial rs_table[] = {
          .ifirstadr   = R_DMA_CH5_FIRST,
          .icmdadr     = R_DMA_CH5_CMD,
          .idescradr   = R_DMA_CH5_DESCR,
-         .flags       = STD_FLAGS,
          .rx_ctrl     = DEF_RX,
          .tx_ctrl     = DEF_TX,
          .iseteop     = 1,
@@ -2263,8 +2258,7 @@ TODO: The break will be delayed until an F or V character is received.
 
 */
 
-static
-struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info)
+static void handle_ser_rx_interrupt_no_dma(struct e100_serial *info)
 {
        unsigned long data_read;
 
@@ -2370,10 +2364,9 @@ more_data:
        }
 
        tty_flip_buffer_push(&info->port);
-       return info;
 }
 
-static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info)
+static void handle_ser_rx_interrupt(struct e100_serial *info)
 {
        unsigned char rstat;
 
@@ -2382,7 +2375,8 @@ static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info)
 #endif
 /*     DEBUG_LOG(info->line, "ser_interrupt stat %03X\n", rstat | (i << 8)); */
        if (!info->uses_dma_in) {
-               return handle_ser_rx_interrupt_no_dma(info);
+               handle_ser_rx_interrupt_no_dma(info);
+               return;
        }
        /* DMA is used */
        rstat = info->ioport[REG_STATUS];
@@ -2489,7 +2483,6 @@ static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info)
        /* Restarting the DMA never hurts */
        *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart);
        START_FLUSH_FAST_TIMER(info, "ser_int");
-       return info;
 } /* handle_ser_rx_interrupt */
 
 static void handle_ser_tx_interrupt(struct e100_serial *info)
@@ -2534,8 +2527,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info)
        }
        /* Normal char-by-char interrupt */
        if (info->xmit.head == info->xmit.tail
-           || info->port.tty->stopped
-           || info->port.tty->hw_stopped) {
+           || info->port.tty->stopped) {
                DFLOW(DEBUG_LOG(info->line, "tx_int: stopped %i\n",
                                info->port.tty->stopped));
                e100_disable_serial_tx_ready_irq(info);
@@ -2722,7 +2714,7 @@ startup(struct e100_serial * info)
 
        /* if it was already initialized, skip this */
 
-       if (info->flags & ASYNC_INITIALIZED) {
+       if (info->port.flags & ASYNC_INITIALIZED) {
                local_irq_restore(flags);
                free_page(xmit_page);
                return 0;
@@ -2847,7 +2839,7 @@ startup(struct e100_serial * info)
 
 #endif /* CONFIG_SVINTO_SIM */
 
-       info->flags |= ASYNC_INITIALIZED;
+       info->port.flags |= ASYNC_INITIALIZED;
 
        local_irq_restore(flags);
        return 0;
@@ -2892,7 +2884,7 @@ shutdown(struct e100_serial * info)
 
 #endif /* CONFIG_SVINTO_SIM */
 
-       if (!(info->flags & ASYNC_INITIALIZED))
+       if (!(info->port.flags & ASYNC_INITIALIZED))
                return;
 
 #ifdef SERIAL_DEBUG_OPEN
@@ -2923,7 +2915,7 @@ shutdown(struct e100_serial * info)
        if (info->port.tty)
                set_bit(TTY_IO_ERROR, &info->port.tty->flags);
 
-       info->flags &= ~ASYNC_INITIALIZED;
+       info->port.flags &= ~ASYNC_INITIALIZED;
        local_irq_restore(flags);
 }
 
@@ -2948,7 +2940,7 @@ change_speed(struct e100_serial *info)
        /* possibly, the tx/rx should be disabled first to do this safely */
 
        /* change baud-rate and write it to the hardware */
-       if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) {
+       if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) {
                /* Special baudrate */
                u32 mask = 0xFF << (info->line*8); /* Each port has 8 bits */
                unsigned long alt_source =
@@ -3098,7 +3090,6 @@ rs_flush_chars(struct tty_struct *tty)
        if (info->tr_running ||
            info->xmit.head == info->xmit.tail ||
            tty->stopped ||
-           tty->hw_stopped ||
            !info->xmit.buf)
                return;
 
@@ -3176,7 +3167,6 @@ static int rs_raw_write(struct tty_struct *tty,
 
        if (info->xmit.head != info->xmit.tail &&
            !tty->stopped &&
-           !tty->hw_stopped &&
            !info->tr_running) {
                start_transmit(info);
        }
@@ -3400,10 +3390,10 @@ get_serial_info(struct e100_serial * info,
        tmp.line = info->line;
        tmp.port = (int)info->ioport;
        tmp.irq = info->irq;
-       tmp.flags = info->flags;
+       tmp.flags = info->port.flags;
        tmp.baud_base = info->baud_base;
-       tmp.close_delay = info->close_delay;
-       tmp.closing_wait = info->closing_wait;
+       tmp.close_delay = info->port.close_delay;
+       tmp.closing_wait = info->port.closing_wait;
        tmp.custom_divisor = info->custom_divisor;
        if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
                return -EFAULT;
@@ -3425,16 +3415,16 @@ set_serial_info(struct e100_serial *info,
 
        if (!capable(CAP_SYS_ADMIN)) {
                if ((new_serial.type != info->type) ||
-                   (new_serial.close_delay != info->close_delay) ||
+                   (new_serial.close_delay != info->port.close_delay) ||
                    ((new_serial.flags & ~ASYNC_USR_MASK) !=
-                    (info->flags & ~ASYNC_USR_MASK)))
+                    (info->port.flags & ~ASYNC_USR_MASK)))
                        return -EPERM;
-               info->flags = ((info->flags & ~ASYNC_USR_MASK) |
+               info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) |
                               (new_serial.flags & ASYNC_USR_MASK));
                goto check_and_exit;
        }
 
-       if (info->count > 1)
+       if (info->port.count > 1)
                return -EBUSY;
 
        /*
@@ -3443,16 +3433,16 @@ set_serial_info(struct e100_serial *info,
         */
 
        info->baud_base = new_serial.baud_base;
-       info->flags = ((info->flags & ~ASYNC_FLAGS) |
+       info->port.flags = ((info->port.flags & ~ASYNC_FLAGS) |
                       (new_serial.flags & ASYNC_FLAGS));
        info->custom_divisor = new_serial.custom_divisor;
        info->type = new_serial.type;
-       info->close_delay = new_serial.close_delay;
-       info->closing_wait = new_serial.closing_wait;
-       info->port.low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+       info->port.close_delay = new_serial.close_delay;
+       info->port.closing_wait = new_serial.closing_wait;
+       info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
  check_and_exit:
-       if (info->flags & ASYNC_INITIALIZED) {
+       if (info->port.flags & ASYNC_INITIALIZED) {
                change_speed(info);
        } else
                retval = startup(info);
@@ -3733,10 +3723,8 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 
        /* Handle turning off CRTSCTS */
        if ((old_termios->c_cflag & CRTSCTS) &&
-           !(tty->termios.c_cflag & CRTSCTS)) {
-               tty->hw_stopped = 0;
+           !(tty->termios.c_cflag & CRTSCTS))
                rs_start(tty);
-       }
 
 }
 
@@ -3772,7 +3760,7 @@ rs_close(struct tty_struct *tty, struct file * filp)
        printk("[%d] rs_close ttyS%d, count = %d\n", current->pid,
               info->line, info->count);
 #endif
-       if ((tty->count == 1) && (info->count != 1)) {
+       if ((tty->count == 1) && (info->port.count != 1)) {
                /*
                 * Uh, oh.  tty->count is 1, which means that the tty
                 * structure will be freed.  Info->count should always
@@ -3782,32 +3770,32 @@ rs_close(struct tty_struct *tty, struct file * filp)
                 */
                printk(KERN_ERR
                       "rs_close: bad serial port count; tty->count is 1, "
-                      "info->count is %d\n", info->count);
-               info->count = 1;
+                      "info->count is %d\n", info->port.count);
+               info->port.count = 1;
        }
-       if (--info->count < 0) {
+       if (--info->port.count < 0) {
                printk(KERN_ERR "rs_close: bad serial port count for ttyS%d: %d\n",
-                      info->line, info->count);
-               info->count = 0;
+                      info->line, info->port.count);
+               info->port.count = 0;
        }
-       if (info->count) {
+       if (info->port.count) {
                local_irq_restore(flags);
                return;
        }
-       info->flags |= ASYNC_CLOSING;
+       info->port.flags |= ASYNC_CLOSING;
        /*
         * Save the termios structure, since this port may have
         * separate termios for callout and dialin.
         */
-       if (info->flags & ASYNC_NORMAL_ACTIVE)
+       if (info->port.flags & ASYNC_NORMAL_ACTIVE)
                info->normal_termios = tty->termios;
        /*
         * Now we wait for the transmit buffer to clear; and we notify
         * the line discipline to only process XON/XOFF characters.
         */
        tty->closing = 1;
-       if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-               tty_wait_until_sent(tty, info->closing_wait);
+       if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
+               tty_wait_until_sent(tty, info->port.closing_wait);
        /*
         * At this point we stop accepting input.  To do this, we
         * disable the serial receiver and the DMA receive interrupt.
@@ -3820,7 +3808,7 @@ rs_close(struct tty_struct *tty, struct file * filp)
        e100_disable_rx(info);
        e100_disable_rx_irq(info);
 
-       if (info->flags & ASYNC_INITIALIZED) {
+       if (info->port.flags & ASYNC_INITIALIZED) {
                /*
                 * Before we drop DTR, make sure the UART transmitter
                 * has completely drained; this is especially
@@ -3836,13 +3824,13 @@ rs_close(struct tty_struct *tty, struct file * filp)
        tty->closing = 0;
        info->event = 0;
        info->port.tty = NULL;
-       if (info->blocked_open) {
-               if (info->close_delay)
-                       schedule_timeout_interruptible(info->close_delay);
-               wake_up_interruptible(&info->open_wait);
+       if (info->port.blocked_open) {
+               if (info->port.close_delay)
+                       schedule_timeout_interruptible(info->port.close_delay);
+               wake_up_interruptible(&info->port.open_wait);
        }
-       info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-       wake_up_interruptible(&info->close_wait);
+       info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
+       wake_up_interruptible(&info->port.close_wait);
        local_irq_restore(flags);
 
        /* port closed */
@@ -3935,10 +3923,10 @@ rs_hangup(struct tty_struct *tty)
        rs_flush_buffer(tty);
        shutdown(info);
        info->event = 0;
-       info->count = 0;
-       info->flags &= ~ASYNC_NORMAL_ACTIVE;
+       info->port.count = 0;
+       info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
        info->port.tty = NULL;
-       wake_up_interruptible(&info->open_wait);
+       wake_up_interruptible(&info->port.open_wait);
 }
 
 /*
@@ -3960,11 +3948,11 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
         * until it's done, and then try again.
         */
        if (tty_hung_up_p(filp) ||
-           (info->flags & ASYNC_CLOSING)) {
-               wait_event_interruptible_tty(tty, info->close_wait,
-                       !(info->flags & ASYNC_CLOSING));
+           (info->port.flags & ASYNC_CLOSING)) {
+               wait_event_interruptible_tty(tty, info->port.close_wait,
+                       !(info->port.flags & ASYNC_CLOSING));
 #ifdef SERIAL_DO_RESTART
-               if (info->flags & ASYNC_HUP_NOTIFY)
+               if (info->port.flags & ASYNC_HUP_NOTIFY)
                        return -EAGAIN;
                else
                        return -ERESTARTSYS;
@@ -3979,7 +3967,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
         */
        if ((filp->f_flags & O_NONBLOCK) ||
            (tty->flags & (1 << TTY_IO_ERROR))) {
-               info->flags |= ASYNC_NORMAL_ACTIVE;
+               info->port.flags |= ASYNC_NORMAL_ACTIVE;
                return 0;
        }
 
@@ -3990,23 +3978,23 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
        /*
         * Block waiting for the carrier detect and the line to become
         * free (i.e., not in use by the callout).  While we are in
-        * this loop, info->count is dropped by one, so that
+        * this loop, info->port.count is dropped by one, so that
         * rs_close() knows when to free things.  We restore it upon
         * exit, either normal or abnormal.
         */
        retval = 0;
-       add_wait_queue(&info->open_wait, &wait);
+       add_wait_queue(&info->port.open_wait, &wait);
 #ifdef SERIAL_DEBUG_OPEN
        printk("block_til_ready before block: ttyS%d, count = %d\n",
-              info->line, info->count);
+              info->line, info->port.count);
 #endif
        local_irq_save(flags);
        if (!tty_hung_up_p(filp)) {
                extra_count++;
-               info->count--;
+               info->port.count--;
        }
        local_irq_restore(flags);
-       info->blocked_open++;
+       info->port.blocked_open++;
        while (1) {
                local_irq_save(flags);
                /* assert RTS and DTR */
@@ -4015,9 +4003,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
                local_irq_restore(flags);
                set_current_state(TASK_INTERRUPTIBLE);
                if (tty_hung_up_p(filp) ||
-                   !(info->flags & ASYNC_INITIALIZED)) {
+                   !(info->port.flags & ASYNC_INITIALIZED)) {
 #ifdef SERIAL_DO_RESTART
-                       if (info->flags & ASYNC_HUP_NOTIFY)
+                       if (info->port.flags & ASYNC_HUP_NOTIFY)
                                retval = -EAGAIN;
                        else
                                retval = -ERESTARTSYS;
@@ -4026,7 +4014,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 #endif
                        break;
                }
-               if (!(info->flags & ASYNC_CLOSING) && do_clocal)
+               if (!(info->port.flags & ASYNC_CLOSING) && do_clocal)
                        /* && (do_clocal || DCD_IS_ASSERTED) */
                        break;
                if (signal_pending(current)) {
@@ -4035,24 +4023,24 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
                }
 #ifdef SERIAL_DEBUG_OPEN
                printk("block_til_ready blocking: ttyS%d, count = %d\n",
-                      info->line, info->count);
+                      info->line, info->port.count);
 #endif
                tty_unlock(tty);
                schedule();
                tty_lock(tty);
        }
        set_current_state(TASK_RUNNING);
-       remove_wait_queue(&info->open_wait, &wait);
+       remove_wait_queue(&info->port.open_wait, &wait);
        if (extra_count)
-               info->count++;
-       info->blocked_open--;
+               info->port.count++;
+       info->port.blocked_open--;
 #ifdef SERIAL_DEBUG_OPEN
        printk("block_til_ready after blocking: ttyS%d, count = %d\n",
-              info->line, info->count);
+              info->line, info->port.count);
 #endif
        if (retval)
                return retval;
-       info->flags |= ASYNC_NORMAL_ACTIVE;
+       info->port.flags |= ASYNC_NORMAL_ACTIVE;
        return 0;
 }
 
@@ -4086,24 +4074,24 @@ rs_open(struct tty_struct *tty, struct file * filp)
 
 #ifdef SERIAL_DEBUG_OPEN
         printk("[%d] rs_open %s, count = %d\n", current->pid, tty->name,
-              info->count);
+              info->port.count);
 #endif
 
-       info->count++;
+       info->port.count++;
        tty->driver_data = info;
        info->port.tty = tty;
 
-       info->port.low_latency = !!(info->flags & ASYNC_LOW_LATENCY);
+       info->port.low_latency = !!(info->port.flags & ASYNC_LOW_LATENCY);
 
        /*
         * If the port is in the middle of closing, bail out now
         */
        if (tty_hung_up_p(filp) ||
-           (info->flags & ASYNC_CLOSING)) {
-               wait_event_interruptible_tty(tty, info->close_wait,
-                       !(info->flags & ASYNC_CLOSING));
+           (info->port.flags & ASYNC_CLOSING)) {
+               wait_event_interruptible_tty(tty, info->port.close_wait,
+                       !(info->port.flags & ASYNC_CLOSING));
 #ifdef SERIAL_DO_RESTART
-               return ((info->flags & ASYNC_HUP_NOTIFY) ?
+               return ((info->port.flags & ASYNC_HUP_NOTIFY) ?
                        -EAGAIN : -ERESTARTSYS);
 #else
                return -EAGAIN;
@@ -4113,7 +4101,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
        /*
         * If DMA is enabled try to allocate the irq's.
         */
-       if (info->count == 1) {
+       if (info->port.count == 1) {
                allocated_resources = 1;
                if (info->dma_in_enabled) {
                        if (request_irq(info->dma_in_irq_nbr,
@@ -4186,7 +4174,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
                if (allocated_resources)
                        deinit_port(info);
 
-               /* FIXME Decrease count info->count here too? */
+               /* FIXME Decrease count info->port.count here too? */
                return retval;
        }
 
@@ -4203,7 +4191,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
                return retval;
        }
 
-       if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
+       if ((info->port.count == 1) && (info->port.flags & ASYNC_SPLIT_TERMIOS)) {
                tty->termios = info->normal_termios;
                change_speed(info);
        }
@@ -4256,9 +4244,6 @@ static void seq_line_info(struct seq_file *m, struct e100_serial *info)
                if (info->port.tty->stopped)
                        seq_printf(m, " stopped:%i",
                                   (int)info->port.tty->stopped);
-               if (info->port.tty->hw_stopped)
-                       seq_printf(m, " hw_stopped:%i",
-                                  (int)info->port.tty->hw_stopped);
        }
 
        {
@@ -4455,16 +4440,9 @@ static int __init rs_init(void)
                info->forced_eop = 0;
                info->baud_base = DEF_BAUD_BASE;
                info->custom_divisor = 0;
-               info->flags = 0;
-               info->close_delay = 5*HZ/10;
-               info->closing_wait = 30*HZ;
                info->x_char = 0;
                info->event = 0;
-               info->count = 0;
-               info->blocked_open = 0;
                info->normal_termios = driver->init_termios;
-               init_waitqueue_head(&info->open_wait);
-               init_waitqueue_head(&info->close_wait);
                info->xmit.buf = NULL;
                info->xmit.tail = info->xmit.head = 0;
                info->first_recv_buffer = info->last_recv_buffer = NULL;
index ea0beb46a10d1ae40eb43737d1696a4d7df70576..7599014ae03fb2266adceb1dc25c010d22601296 100644 (file)
@@ -53,8 +53,6 @@ struct e100_serial {
        volatile u8 *icmdadr;           /* adr to R_DMA_CHx_CMD */
        volatile u32 *idescradr;        /* adr to R_DMA_CHx_DESCR */
 
-       int flags;      /* defined in tty.h */
-
        u8 rx_ctrl;     /* shadow for R_SERIALx_REC_CTRL */
        u8 tx_ctrl;     /* shadow for R_SERIALx_TR_CTRL */
        u8 iseteop;     /* bit number for R_SET_EOP for the input dma */
@@ -88,19 +86,10 @@ struct e100_serial {
 
        volatile int            tr_running; /* 1 if output is running */
 
-       struct tty_struct       *tty;
-       int                     read_status_mask;
-       int                     ignore_status_mask;
        int                     x_char; /* xon/xoff character */
-       int                     close_delay;
-       unsigned short          closing_wait;
-       unsigned short          closing_wait2;
        unsigned long           event;
-       unsigned long           last_active;
        int                     line;
        int                     type;  /* PORT_ETRAX */
-       int                     count;      /* # of fd on device */
-       int                     blocked_open; /* # of blocked opens */
        struct circ_buf         xmit;
        struct etrax_recv_buffer *first_recv_buffer;
        struct etrax_recv_buffer *last_recv_buffer;
@@ -110,9 +99,6 @@ struct e100_serial {
        struct work_struct      work;
        struct async_icount     icount;   /* error-statistics etc.*/
        struct ktermios         normal_termios;
-       struct ktermios         callout_termios;
-       wait_queue_head_t       open_wait;
-       wait_queue_head_t       close_wait;
 
        unsigned long char_time_usec;       /* The time for 1 char, in usecs */
        unsigned long flush_time_usec;      /* How often we should flush */
index bc9e6b017b05c24a99f61a13ed78f123c0ccf13d..18ed5aebb166da78f9f10e8f163191e9f97bbc49 100644 (file)
@@ -1415,8 +1415,7 @@ static int icom_alloc_adapter(struct icom_adapter
        struct icom_adapter *cur_adapter_entry;
        struct list_head *tmp;
 
-       icom_adapter = (struct icom_adapter *)
-           kzalloc(sizeof(struct icom_adapter), GFP_KERNEL);
+       icom_adapter = kzalloc(sizeof(struct icom_adapter), GFP_KERNEL);
 
        if (!icom_adapter) {
                return -ENOMEM;
index 68d7ce997ede999fce550d0b6d1ccd6d0e9032be..8b1534c424afc38eb022d26d7ba70b25e6b722d4 100644 (file)
@@ -269,23 +269,6 @@ static void mrdy_assert(struct ifx_spi_device *ifx_dev)
        mrdy_set_high(ifx_dev);
 }
 
-/**
- *     ifx_spi_hangup          -       hang up an IFX device
- *     @ifx_dev: our SPI device
- *
- *     Hang up the tty attached to the IFX device if one is currently
- *     open. If not take no action
- */
-static void ifx_spi_ttyhangup(struct ifx_spi_device *ifx_dev)
-{
-       struct tty_port *pport = &ifx_dev->tty_port;
-       struct tty_struct *tty = tty_port_tty_get(pport);
-       if (tty) {
-               tty_hangup(tty);
-               tty_kref_put(tty);
-       }
-}
-
 /**
  *     ifx_spi_timeout         -       SPI timeout
  *     @arg: our SPI device
@@ -298,7 +281,7 @@ static void ifx_spi_timeout(unsigned long arg)
        struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *)arg;
 
        dev_warn(&ifx_dev->spi_dev->dev, "*** SPI Timeout ***");
-       ifx_spi_ttyhangup(ifx_dev);
+       tty_port_tty_hangup(&ifx_dev->tty_port, false);
        mrdy_set_low(ifx_dev);
        clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
 }
@@ -442,25 +425,6 @@ static void ifx_spi_setup_spi_header(unsigned char *txbuffer, int tx_count,
        txbuffer[1] |= (more << IFX_SPI_MORE_BIT) & IFX_SPI_MORE_MASK;
 }
 
-/**
- *     ifx_spi_wakeup_serial   -       SPI space made
- *     @port_data: our SPI device
- *
- *     We have emptied the FIFO enough that we want to get more data
- *     queued into it. Poke the line discipline via tty_wakeup so that
- *     it will feed us more bits
- */
-static void ifx_spi_wakeup_serial(struct ifx_spi_device *ifx_dev)
-{
-       struct tty_struct *tty;
-
-       tty = tty_port_tty_get(&ifx_dev->tty_port);
-       if (!tty)
-               return;
-       tty_wakeup(tty);
-       tty_kref_put(tty);
-}
-
 /**
  *     ifx_spi_prepare_tx_buffer       -       prepare transmit frame
  *     @ifx_dev: our SPI device
@@ -506,7 +470,7 @@ static int ifx_spi_prepare_tx_buffer(struct ifx_spi_device *ifx_dev)
                        tx_count += temp_count;
                        if (temp_count == queue_length)
                                /* poke port to get more data */
-                               ifx_spi_wakeup_serial(ifx_dev);
+                               tty_port_tty_wakeup(&ifx_dev->tty_port);
                        else /* more data in port, use next SPI message */
                                ifx_dev->spi_more = 1;
                }
@@ -683,8 +647,6 @@ static void ifx_spi_insert_flip_string(struct ifx_spi_device *ifx_dev,
 static void ifx_spi_complete(void *ctx)
 {
        struct ifx_spi_device *ifx_dev = ctx;
-       struct tty_struct *tty;
-       struct tty_ldisc *ldisc = NULL;
        int length;
        int actual_length;
        unsigned char more;
@@ -762,15 +724,7 @@ complete_exit:
                         */
                        ifx_spi_power_state_clear(ifx_dev,
                                                  IFX_SPI_POWER_DATA_PENDING);
-                       tty = tty_port_tty_get(&ifx_dev->tty_port);
-                       if (tty) {
-                               ldisc = tty_ldisc_ref(tty);
-                               if (ldisc) {
-                                       ldisc->ops->write_wakeup(tty);
-                                       tty_ldisc_deref(ldisc);
-                               }
-                               tty_kref_put(tty);
-                       }
+                       tty_port_tty_wakeup(&ifx_dev->tty_port);
                }
        }
 }
@@ -962,7 +916,7 @@ static irqreturn_t ifx_spi_reset_interrupt(int irq, void *dev)
                set_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state);
                if (!solreset) {
                        /* unsolicited reset  */
-                       ifx_spi_ttyhangup(ifx_dev);
+                       tty_port_tty_hangup(&ifx_dev->tty_port, false);
                }
        } else {
                /* exited reset */
@@ -1324,30 +1278,6 @@ static void ifx_spi_spi_shutdown(struct spi_device *spi)
  * no hardware to save state for
  */
 
-/**
- *     ifx_spi_spi_suspend     -       suspend SPI on system suspend
- *     @dev: device being suspended
- *
- *     Suspend the SPI side. No action needed on Intel MID platforms, may
- *     need extending for other systems.
- */
-static int ifx_spi_spi_suspend(struct spi_device *spi, pm_message_t msg)
-{
-       return 0;
-}
-
-/**
- *     ifx_spi_spi_resume      -       resume SPI side on system resume
- *     @dev: device being suspended
- *
- *     Suspend the SPI side. No action needed on Intel MID platforms, may
- *     need extending for other systems.
- */
-static int ifx_spi_spi_resume(struct spi_device *spi)
-{
-       return 0;
-}
-
 /**
  *     ifx_spi_pm_suspend      -       suspend modem on system suspend
  *     @dev: device being suspended
@@ -1437,8 +1367,6 @@ static struct spi_driver ifx_spi_driver = {
        .probe = ifx_spi_spi_probe,
        .shutdown = ifx_spi_spi_shutdown,
        .remove = ifx_spi_spi_remove,
-       .suspend = ifx_spi_spi_suspend,
-       .resume = ifx_spi_spi_resume,
        .id_table = ifx_id_table
 };
 
index 00f250ae14c55b49c990dd9c24eabc33353c4973..27bb75070c965867efb6f04a4345322d399c8ca5 100644 (file)
@@ -596,12 +596,6 @@ void jsm_input(struct jsm_channel *ch)
 
        jsm_dbg(READ, &ch->ch_bd->pci_dev, "start 2\n");
 
-       if (data_len <= 0) {
-               spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-               jsm_dbg(READ, &ch->ch_bd->pci_dev, "jsm_input 1\n");
-               return;
-       }
-
        len = tty_buffer_request_room(port, data_len);
        n = len;
 
index 32517d4bceab2b5cbecd1861b36ecd32b770e500..35866d5872ad1c82bdc487909cd359a84dabb790 100644 (file)
@@ -778,7 +778,7 @@ static int max3100_probe(struct spi_device *spi)
        max3100s[i]->spi = spi;
        max3100s[i]->irq = spi->irq;
        spin_lock_init(&max3100s[i]->conf_lock);
-       dev_set_drvdata(&spi->dev, max3100s[i]);
+       spi_set_drvdata(spi, max3100s[i]);
        pdata = spi->dev.platform_data;
        max3100s[i]->crystal = pdata->crystal;
        max3100s[i]->loopback = pdata->loopback;
@@ -819,7 +819,7 @@ static int max3100_probe(struct spi_device *spi)
 
 static int max3100_remove(struct spi_device *spi)
 {
-       struct max3100_port *s = dev_get_drvdata(&spi->dev);
+       struct max3100_port *s = spi_get_drvdata(spi);
        int i;
 
        mutex_lock(&max3100s_lock);
@@ -849,11 +849,11 @@ static int max3100_remove(struct spi_device *spi)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 
-static int max3100_suspend(struct spi_device *spi, pm_message_t state)
+static int max3100_suspend(struct device *dev)
 {
-       struct max3100_port *s = dev_get_drvdata(&spi->dev);
+       struct max3100_port *s = dev_get_drvdata(dev);
 
        dev_dbg(&s->spi->dev, "%s\n", __func__);
 
@@ -874,9 +874,9 @@ static int max3100_suspend(struct spi_device *spi, pm_message_t state)
        return 0;
 }
 
-static int max3100_resume(struct spi_device *spi)
+static int max3100_resume(struct device *dev)
 {
-       struct max3100_port *s = dev_get_drvdata(&spi->dev);
+       struct max3100_port *s = dev_get_drvdata(dev);
 
        dev_dbg(&s->spi->dev, "%s\n", __func__);
 
@@ -894,21 +894,21 @@ static int max3100_resume(struct spi_device *spi)
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(max3100_pm_ops, max3100_suspend, max3100_resume);
+#define MAX3100_PM_OPS (&max3100_pm_ops)
+
 #else
-#define max3100_suspend NULL
-#define max3100_resume  NULL
+#define MAX3100_PM_OPS NULL
 #endif
 
 static struct spi_driver max3100_driver = {
        .driver = {
                .name           = "max3100",
                .owner          = THIS_MODULE,
+               .pm             = MAX3100_PM_OPS,
        },
-
        .probe          = max3100_probe,
        .remove         = max3100_remove,
-       .suspend        = max3100_suspend,
-       .resume         = max3100_resume,
 };
 
 module_spi_driver(max3100_driver);
index 0c2422cb04ea780bec20b0ed04cc2362df42c3cd..8941e64189425a4b41e6ce00d7b9f0a75ab022d0 100644 (file)
@@ -881,12 +881,14 @@ static struct uart_ops max310x_ops = {
        .verify_port    = max310x_verify_port,
 };
 
-static int max310x_suspend(struct spi_device *spi, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+
+static int max310x_suspend(struct device *dev)
 {
        int ret;
-       struct max310x_port *s = dev_get_drvdata(&spi->dev);
+       struct max310x_port *s = dev_get_drvdata(dev);
 
-       dev_dbg(&spi->dev, "Suspend\n");
+       dev_dbg(dev, "Suspend\n");
 
        ret = uart_suspend_port(&s->uart, &s->port);
 
@@ -905,11 +907,11 @@ static int max310x_suspend(struct spi_device *spi, pm_message_t state)
        return ret;
 }
 
-static int max310x_resume(struct spi_device *spi)
+static int max310x_resume(struct device *dev)
 {
-       struct max310x_port *s = dev_get_drvdata(&spi->dev);
+       struct max310x_port *s = dev_get_drvdata(dev);
 
-       dev_dbg(&spi->dev, "Resume\n");
+       dev_dbg(dev, "Resume\n");
 
        if (s->pdata->suspend)
                s->pdata->suspend(0);
@@ -928,6 +930,13 @@ static int max310x_resume(struct spi_device *spi)
        return uart_resume_port(&s->uart, &s->port);
 }
 
+static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume);
+#define MAX310X_PM_OPS (&max310x_pm_ops)
+
+#else
+#define MAX310X_PM_OPS NULL
+#endif
+
 #ifdef CONFIG_GPIOLIB
 static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
@@ -1242,11 +1251,10 @@ static struct spi_driver max310x_driver = {
        .driver = {
                .name   = "max310x",
                .owner  = THIS_MODULE,
+               .pm     = MAX310X_PM_OPS,
        },
        .probe          = max310x_probe,
        .remove         = max310x_remove,
-       .suspend        = max310x_suspend,
-       .resume         = max310x_resume,
        .id_table       = max310x_id_table,
 };
 module_spi_driver(max310x_driver);
index f641c232beca99137cff5739ccb4b008ea881574..9b6ef20420c0134b7da133193e332737421a7070 100644 (file)
@@ -743,9 +743,10 @@ static struct uart_driver serial_m3110_reg = {
        .cons           = &serial_m3110_console,
 };
 
-#ifdef CONFIG_PM
-static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int serial_m3110_suspend(struct device *dev)
 {
+       struct spi_device *spi = to_spi_device(dev);
        struct uart_max3110 *max = spi_get_drvdata(spi);
 
        disable_irq(max->irq);
@@ -754,8 +755,9 @@ static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state)
        return 0;
 }
 
-static int serial_m3110_resume(struct spi_device *spi)
+static int serial_m3110_resume(struct device *dev)
 {
+       struct spi_device *spi = to_spi_device(dev);
        struct uart_max3110 *max = spi_get_drvdata(spi);
 
        max3110_out(max, max->cur_conf);
@@ -763,9 +765,13 @@ static int serial_m3110_resume(struct spi_device *spi)
        enable_irq(max->irq);
        return 0;
 }
+
+static SIMPLE_DEV_PM_OPS(serial_m3110_pm_ops, serial_m3110_suspend,
+                       serial_m3110_resume);
+#define SERIAL_M3110_PM_OPS (&serial_m3110_pm_ops)
+
 #else
-#define serial_m3110_suspend   NULL
-#define serial_m3110_resume    NULL
+#define SERIAL_M3110_PM_OPS NULL
 #endif
 
 static int serial_m3110_probe(struct spi_device *spi)
@@ -872,11 +878,10 @@ static struct spi_driver uart_max3110_driver = {
        .driver = {
                        .name   = "spi_max3111",
                        .owner  = THIS_MODULE,
+                       .pm     = SERIAL_M3110_PM_OPS,
        },
        .probe          = serial_m3110_probe,
        .remove         = serial_m3110_remove,
-       .suspend        = serial_m3110_suspend,
-       .resume         = serial_m3110_resume,
 };
 
 static int __init serial_m3110_init(void)
index 4a942c78347e43e930bec1f1ee67c6854432180b..4ca2f64861e6ce531546f996a5a1bf3718af0344 100644 (file)
@@ -907,7 +907,6 @@ static void msm_hs_dmov_rx_callback(struct msm_dmov_cmd *cmd_ptr,
        unsigned int error_f = 0;
        unsigned long flags;
        unsigned int flush;
-       struct tty_struct *tty;
        struct tty_port *port;
        struct uart_port *uport;
        struct msm_hs_port *msm_uport;
@@ -919,7 +918,6 @@ static void msm_hs_dmov_rx_callback(struct msm_dmov_cmd *cmd_ptr,
        clk_enable(msm_uport->clk);
 
        port = &uport->state->port;
-       tty = port->tty;
 
        msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE);
 
index e722ff163d91ec420b3a5a82028a6d568169c550..1238ac370bff64b9b2c5da4f92e938ff78190b43 100644 (file)
@@ -90,13 +90,13 @@ static void smd_tty_notify(void *priv, unsigned event)
 
 static int smd_tty_port_activate(struct tty_port *tport, struct tty_struct *tty)
 {
+       struct smd_tty_info *info = container_of(tport, struct smd_tty_info,
+                       port);
        int i, res = 0;
-       int n = tty->index;
        const char *name = NULL;
-       struct smd_tty_info *info = smd_tty + n;
 
        for (i = 0; i < smd_tty_channels_len; i++) {
-               if (smd_tty_channels[i].id == n) {
+               if (smd_tty_channels[i].id == tty->index) {
                        name = smd_tty_channels[i].name;
                        break;
                }
@@ -117,17 +117,13 @@ static int smd_tty_port_activate(struct tty_port *tport, struct tty_struct *tty)
 
 static void smd_tty_port_shutdown(struct tty_port *tport)
 {
-       struct smd_tty_info *info;
-       struct tty_struct *tty = tty_port_tty_get(tport);
+       struct smd_tty_info *info = container_of(tport, struct smd_tty_info,
+                       port);
 
-       info = tty->driver_data;
        if (info->ch) {
                smd_close(info->ch);
                info->ch = 0;
        }
-
-       tty->driver_data = 0;
-       tty_kref_put(tty);
 }
 
 static int smd_tty_open(struct tty_struct *tty, struct file *f)
index b025d54382754456efbb021e466079727381bcba..39c7ea4cb14fb9e95fbc920d86010f39db2aa691 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/serial_core.h>
-#include <linux/serial_8250.h>
 #include <linux/serial_reg.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -22,6 +21,8 @@
 #include <linux/nwpserial.h>
 #include <linux/clk.h>
 
+#include "8250/8250.h"
+
 struct of_serial_info {
        struct clk *clk;
        int type;
@@ -97,6 +98,10 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
        if (of_property_read_u32(np, "reg-shift", &prop) == 0)
                port->regshift = prop;
 
+       /* Check for fifo size */
+       if (of_property_read_u32(np, "fifo-size", &prop) == 0)
+               port->fifosize = prop;
+
        port->irq = irq_of_parse_and_map(np, 0);
        port->iotype = UPIO_MEM;
        if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
@@ -167,11 +172,17 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 #ifdef CONFIG_SERIAL_8250
        case PORT_8250 ... PORT_MAX_8250:
        {
-               /* For now the of bindings don't support the extra
-                  8250 specific bits */
                struct uart_8250_port port8250;
                memset(&port8250, 0, sizeof(port8250));
                port8250.port = port;
+
+               if (port.fifosize)
+                       port8250.capabilities = UART_CAP_FIFO;
+
+               if (of_property_read_bool(ofdev->dev.of_node,
+                                         "auto-flow-control"))
+                       port8250.capabilities |= UART_CAP_AFE;
+
                ret = serial8250_register_8250_port(&port8250);
                break;
        }
index 7a6c989924b3e955d738abaa7049011d12d64c69..21a7e179edf36a2ef476553159000e7eef81c913 100644 (file)
@@ -1493,29 +1493,6 @@ static int pch_uart_verify_port(struct uart_port *port,
        return 0;
 }
 
-static struct uart_ops pch_uart_ops = {
-       .tx_empty = pch_uart_tx_empty,
-       .set_mctrl = pch_uart_set_mctrl,
-       .get_mctrl = pch_uart_get_mctrl,
-       .stop_tx = pch_uart_stop_tx,
-       .start_tx = pch_uart_start_tx,
-       .stop_rx = pch_uart_stop_rx,
-       .enable_ms = pch_uart_enable_ms,
-       .break_ctl = pch_uart_break_ctl,
-       .startup = pch_uart_startup,
-       .shutdown = pch_uart_shutdown,
-       .set_termios = pch_uart_set_termios,
-/*     .pm             = pch_uart_pm,          Not supported yet */
-/*     .set_wake       = pch_uart_set_wake,    Not supported yet */
-       .type = pch_uart_type,
-       .release_port = pch_uart_release_port,
-       .request_port = pch_uart_request_port,
-       .config_port = pch_uart_config_port,
-       .verify_port = pch_uart_verify_port
-};
-
-#ifdef CONFIG_SERIAL_PCH_UART_CONSOLE
-
 /*
  *     Wait for transmitter & holding register to empty
  */
@@ -1547,6 +1524,84 @@ static void wait_for_xmitr(struct eg20t_port *up, int bits)
        }
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+/*
+ * Console polling routines for communicate via uart while
+ * in an interrupt or debug context.
+ */
+static int pch_uart_get_poll_char(struct uart_port *port)
+{
+       struct eg20t_port *priv =
+               container_of(port, struct eg20t_port, port);
+       u8 lsr = ioread8(priv->membase + UART_LSR);
+
+       if (!(lsr & UART_LSR_DR))
+               return NO_POLL_CHAR;
+
+       return ioread8(priv->membase + PCH_UART_RBR);
+}
+
+
+static void pch_uart_put_poll_char(struct uart_port *port,
+                        unsigned char c)
+{
+       unsigned int ier;
+       struct eg20t_port *priv =
+               container_of(port, struct eg20t_port, port);
+
+       /*
+        * First save the IER then disable the interrupts
+        */
+       ier = ioread8(priv->membase + UART_IER);
+       pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT);
+
+       wait_for_xmitr(priv, UART_LSR_THRE);
+       /*
+        * Send the character out.
+        * If a LF, also do CR...
+        */
+       iowrite8(c, priv->membase + PCH_UART_THR);
+       if (c == 10) {
+               wait_for_xmitr(priv, UART_LSR_THRE);
+               iowrite8(13, priv->membase + PCH_UART_THR);
+       }
+
+       /*
+        * Finally, wait for transmitter to become empty
+        * and restore the IER
+        */
+       wait_for_xmitr(priv, BOTH_EMPTY);
+       iowrite8(ier, priv->membase + UART_IER);
+}
+#endif /* CONFIG_CONSOLE_POLL */
+
+static struct uart_ops pch_uart_ops = {
+       .tx_empty = pch_uart_tx_empty,
+       .set_mctrl = pch_uart_set_mctrl,
+       .get_mctrl = pch_uart_get_mctrl,
+       .stop_tx = pch_uart_stop_tx,
+       .start_tx = pch_uart_start_tx,
+       .stop_rx = pch_uart_stop_rx,
+       .enable_ms = pch_uart_enable_ms,
+       .break_ctl = pch_uart_break_ctl,
+       .startup = pch_uart_startup,
+       .shutdown = pch_uart_shutdown,
+       .set_termios = pch_uart_set_termios,
+/*     .pm             = pch_uart_pm,          Not supported yet */
+/*     .set_wake       = pch_uart_set_wake,    Not supported yet */
+       .type = pch_uart_type,
+       .release_port = pch_uart_release_port,
+       .request_port = pch_uart_request_port,
+       .config_port = pch_uart_config_port,
+       .verify_port = pch_uart_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+       .poll_get_char = pch_uart_get_poll_char,
+       .poll_put_char = pch_uart_put_poll_char,
+#endif
+};
+
+#ifdef CONFIG_SERIAL_PCH_UART_CONSOLE
+
 static void pch_console_putchar(struct uart_port *port, int ch)
 {
        struct eg20t_port *priv =
@@ -1655,7 +1710,7 @@ static struct console pch_console = {
 #define PCH_CONSOLE    (&pch_console)
 #else
 #define PCH_CONSOLE    NULL
-#endif
+#endif /* CONFIG_SERIAL_PCH_UART_CONSOLE */
 
 static struct uart_driver pch_uart_driver = {
        .owner = THIS_MODULE,
index 2769a38d15b68db5ecf040c17dd3c5fb33226168..074b9194144fdefa1e09536a96626129624a64e0 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
+#include <linux/serial_s3c.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/cpufreq.h>
 
 #include <asm/irq.h>
 
-#include <mach/hardware.h>
-
-#include <plat/regs-serial.h>
+#ifdef CONFIG_SAMSUNG_CLOCK
 #include <plat/clock.h>
+#endif
 
 #include "samsung.h"
 
@@ -446,6 +446,8 @@ static void s3c24xx_serial_shutdown(struct uart_port *port)
 
        /* Clear pending interrupts and mask all interrupts */
        if (s3c24xx_serial_has_interrupt_mask(port)) {
+               free_irq(port->irq, ourport);
+
                wr_regl(port, S3C64XX_UINTP, 0xf);
                wr_regl(port, S3C64XX_UINTM, 0xf);
        }
@@ -505,6 +507,8 @@ static int s3c64xx_serial_startup(struct uart_port *port)
        dbg("s3c64xx_serial_startup: port=%p (%08lx,%p)\n",
            port->mapbase, port->membase);
 
+       wr_regl(port, S3C64XX_UINTM, 0xf);
+
        ret = request_irq(port->irq, s3c64xx_serial_handle_irq, IRQF_SHARED,
                          s3c24xx_serial_portname(port), ourport);
        if (ret) {
@@ -894,7 +898,7 @@ console_initcall(s3c24xx_serial_console_init);
 #define S3C24XX_SERIAL_CONSOLE NULL
 #endif
 
-#ifdef CONFIG_CONSOLE_POLL
+#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
 static int s3c24xx_serial_get_poll_char(struct uart_port *port);
 static void s3c24xx_serial_put_poll_char(struct uart_port *port,
                         unsigned char c);
@@ -918,7 +922,7 @@ static struct uart_ops s3c24xx_serial_ops = {
        .request_port   = s3c24xx_serial_request_port,
        .config_port    = s3c24xx_serial_config_port,
        .verify_port    = s3c24xx_serial_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
+#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
        .poll_get_char = s3c24xx_serial_get_poll_char,
        .poll_put_char = s3c24xx_serial_put_poll_char,
 #endif
@@ -1179,6 +1183,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
        return 0;
 }
 
+#ifdef CONFIG_SAMSUNG_CLOCK
 static ssize_t s3c24xx_serial_show_clksrc(struct device *dev,
                                          struct device_attribute *attr,
                                          char *buf)
@@ -1194,7 +1199,7 @@ static ssize_t s3c24xx_serial_show_clksrc(struct device *dev,
 }
 
 static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL);
-
+#endif
 
 /* Device driver serial port probe */
 
@@ -1252,9 +1257,11 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
        uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
        platform_set_drvdata(pdev, &ourport->port);
 
+#ifdef CONFIG_SAMSUNG_CLOCK
        ret = device_create_file(&pdev->dev, &dev_attr_clock_source);
        if (ret < 0)
                dev_err(&pdev->dev, "failed to add clock source attr.\n");
+#endif
 
        ret = s3c24xx_serial_cpufreq_register(ourport);
        if (ret < 0)
@@ -1272,7 +1279,9 @@ static int s3c24xx_serial_remove(struct platform_device *dev)
 
        if (port) {
                s3c24xx_serial_cpufreq_deregister(to_ourport(port));
+#ifdef CONFIG_SAMSUNG_CLOCK
                device_remove_file(&dev->dev, &dev_attr_clock_source);
+#endif
                uart_remove_one_port(&s3c24xx_uart_drv, port);
        }
 
@@ -1307,9 +1316,29 @@ static int s3c24xx_serial_resume(struct device *dev)
        return 0;
 }
 
+static int s3c24xx_serial_resume_noirq(struct device *dev)
+{
+       struct uart_port *port = s3c24xx_dev_to_port(dev);
+
+       if (port) {
+               /* restore IRQ mask */
+               if (s3c24xx_serial_has_interrupt_mask(port)) {
+                       unsigned int uintm = 0xf;
+                       if (tx_enabled(port))
+                               uintm &= ~S3C64XX_UINTM_TXD_MSK;
+                       if (rx_enabled(port))
+                               uintm &= ~S3C64XX_UINTM_RXD_MSK;
+                       wr_regl(port, S3C64XX_UINTM, uintm);
+               }
+       }
+
+       return 0;
+}
+
 static const struct dev_pm_ops s3c24xx_serial_pm_ops = {
        .suspend = s3c24xx_serial_suspend,
        .resume = s3c24xx_serial_resume,
+       .resume_noirq = s3c24xx_serial_resume_noirq,
 };
 #define SERIAL_SAMSUNG_PM_OPS  (&s3c24xx_serial_pm_ops)
 
@@ -1343,6 +1372,13 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
        return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0;
 }
 
+static bool
+s3c24xx_port_configured(unsigned int ucon)
+{
+       /* consider the serial port configured if the tx/rx mode set */
+       return (ucon & 0xf) != 0;
+}
+
 #ifdef CONFIG_CONSOLE_POLL
 /*
  * Console polling routines for writing and reading from the uart while
@@ -1365,6 +1401,11 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port,
                unsigned char c)
 {
        unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
+       unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
+
+       /* not possible to xmit on unconfigured port */
+       if (!s3c24xx_port_configured(ucon))
+               return;
 
        while (!s3c24xx_serial_console_txrdy(port, ufcon))
                cpu_relax();
@@ -1377,6 +1418,12 @@ static void
 s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
 {
        unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
+       unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
+
+       /* not possible to xmit on unconfigured port */
+       if (!s3c24xx_port_configured(ucon))
+               return;
+
        while (!s3c24xx_serial_console_txrdy(port, ufcon))
                barrier();
        wr_regb(cons_uart, S3C2410_UTXH, ch);
@@ -1409,9 +1456,7 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
            "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n",
            port, ulcon, ucon, ubrdiv);
 
-       if ((ucon & 0xf) != 0) {
-               /* consider the serial port configured if the tx/rx mode set */
-
+       if (s3c24xx_port_configured(ucon)) {
                switch (ulcon & S3C2410_LCON_CSMASK) {
                case S3C2410_LCON_CS5:
                        *bits = 5;
index 1a4bca3e41797583e1fb4fca5d90b58c8676bffe..00a499ecd385c78cec95fbe92f0eebd2cfce956b 100644 (file)
@@ -76,7 +76,9 @@ struct s3c24xx_uart_port {
 #define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg))
 #define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg))
 
-#ifdef CONFIG_SERIAL_SAMSUNG_DEBUG
+#if defined(CONFIG_SERIAL_SAMSUNG_DEBUG) && \
+    defined(CONFIG_DEBUG_LL) && \
+    !defined(MODULE)
 
 extern void printascii(const char *);
 
index 372de8ade76a2fce2451874360b093c6f1ee5a75..9799d043a9bd8e0a9e8d6142f47caf85eceee484 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmapool.h>
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/module.h>
@@ -1301,11 +1302,9 @@ static int tegra_uart_probe(struct platform_device *pdev)
        }
 
        u->mapbase = resource->start;
-       u->membase = devm_request_and_ioremap(&pdev->dev, resource);
-       if (!u->membase) {
-               dev_err(&pdev->dev, "memregion/iomap address req failed\n");
-               return -EADDRNOTAVAIL;
-       }
+       u->membase = devm_ioremap_resource(&pdev->dev, resource);
+       if (IS_ERR(u->membase))
+               return PTR_ERR(u->membase);
 
        tup->uart_clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(tup->uart_clk)) {
index 4c22a1529aac7c2304aeb15b302a6c9021c1174d..5aca7364634c10f35c6dcb88d2ff100f9f3c84be 100644 (file)
@@ -15,8 +15,6 @@
     defined(CONFIG_CPU_SUBTYPE_SH7720) || \
     defined(CONFIG_CPU_SUBTYPE_SH7721) || \
     defined(CONFIG_ARCH_SH73A0) || \
-    defined(CONFIG_ARCH_SH7367) || \
-    defined(CONFIG_ARCH_SH7377) || \
     defined(CONFIG_ARCH_SH7372) || \
     defined(CONFIG_ARCH_R8A7740)
 
index 8de2213664e0c8bd655fcd2ce5d19d6cd23de05b..a422c8b55a47b427b34ec09a3bda5b563ea6d8a0 100644 (file)
@@ -203,7 +203,7 @@ receive_chars(struct uart_sunsab_port *up,
                                flag = TTY_FRAME;
                }
 
-               if (uart_handle_sysrq_char(&up->port, ch))
+               if (uart_handle_sysrq_char(&up->port, ch) || !port)
                        continue;
 
                if ((stat->sreg.isr0 & (up->port.ignore_status_mask & 0xff)) == 0 &&
index 27669ff3d4463b0c023f7eb1120b8ed96792e39f..813ef8eb8effaa5b6b2d9116dc3c2a4c43cba4f5 100644 (file)
@@ -388,7 +388,7 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
                        else if (r1 & CRC_ERR)
                                flag = TTY_FRAME;
                }
-               if (uart_handle_sysrq_char(&up->port, ch))
+               if (uart_handle_sysrq_char(&up->port, ch) || !port)
                        continue;
 
                if (up->port.ignore_status_mask == 0xff ||
index 705240e6c4ec1714fb0c367e9f226eb23d705464..1a8bc2275ea4f190e9d994cb7e3786069f168a7e 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
+#include <linux/err.h>
 
 /*
  * UART Register offsets
@@ -585,9 +586,9 @@ static int vt8500_serial_probe(struct platform_device *pdev)
        if (!vt8500_port)
                return -ENOMEM;
 
-       vt8500_port->uart.membase = devm_request_and_ioremap(&pdev->dev, mmres);
-       if (!vt8500_port->uart.membase)
-               return -EADDRNOTAVAIL;
+       vt8500_port->uart.membase = devm_ioremap_resource(&pdev->dev, mmres);
+       if (IS_ERR(vt8500_port->uart.membase))
+               return PTR_ERR(vt8500_port->uart.membase);
 
        vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0);
        if (IS_ERR(vt8500_port->clk)) {
index f36bbba1ac8b9070cc7cefafb8a33265a7872253..4e5c77834c50fc6586848f9b292b81456b481da6 100644 (file)
@@ -585,9 +585,6 @@ static int xuartps_startup(struct uart_port *port)
        xuartps_writel(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY |
                XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN |
                XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT, XUARTPS_IER_OFFSET);
-       xuartps_writel(~(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY |
-               XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN |
-               XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT), XUARTPS_IDR_OFFSET);
 
        return retval;
 }
index 8983276aa35e9bf46b1eec4d9e9e45d39d82ef33..8eaf1ab8addb1d30faae7b93a28e532fad6a1cf6 100644 (file)
@@ -1058,9 +1058,6 @@ static void mgsl_bh_handler(struct work_struct *work)
                container_of(work, struct mgsl_struct, task);
        int action;
 
-       if (!info)
-               return;
-               
        if ( debug_level >= DEBUG_LEVEL_BH )
                printk( "%s(%d):mgsl_bh_handler(%s) entry\n",
                        __FILE__,__LINE__,info->device_name);
@@ -3311,7 +3308,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
        port->blocked_open++;
        
        while (1) {
-               if (tty->termios.c_cflag & CBAUD)
+               if (C_BAUD(tty) && test_bit(ASYNCB_INITIALIZED, &port->flags))
                        tty_port_raise_dtr_rts(port);
                
                set_current_state(TASK_INTERRUPTIBLE);
index aa9eece35c3b922240249f10481733a20de0ad6a..1abf946463f664522d1721a1537a4fdba9d45c25 100644 (file)
@@ -3308,7 +3308,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
        port->blocked_open++;
 
        while (1) {
-               if ((tty->termios.c_cflag & CBAUD))
+               if (C_BAUD(tty) && test_bit(ASYNCB_INITIALIZED, &port->flags))
                        tty_port_raise_dtr_rts(port);
 
                set_current_state(TASK_INTERRUPTIBLE);
index 6d5780cf1d57a1c6882f8302f7d0dea8710b7145..ff171384ea5256cabcf018c3a3dc839279f71392 100644 (file)
@@ -3329,7 +3329,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
        port->blocked_open++;
 
        while (1) {
-               if (tty->termios.c_cflag & CBAUD)
+               if (C_BAUD(tty) && test_bit(ASYNCB_INITIALIZED, &port->flags))
                        tty_port_raise_dtr_rts(port);
 
                set_current_state(TASK_INTERRUPTIBLE);
index 3687f0cad6421c01c4e0e62d2345165c80765dc9..0a0de333c765992615326a66a5862116a3b00cb7 100644 (file)
@@ -101,7 +101,7 @@ static void sysrq_handle_SAK(int key)
 }
 static struct sysrq_key_op sysrq_SAK_op = {
        .handler        = sysrq_handle_SAK,
-       .help_msg       = "saK",
+       .help_msg       = "sak(k)",
        .action_msg     = "SAK",
        .enable_mask    = SYSRQ_ENABLE_KEYBOARD,
 };
@@ -117,7 +117,7 @@ static void sysrq_handle_unraw(int key)
 
 static struct sysrq_key_op sysrq_unraw_op = {
        .handler        = sysrq_handle_unraw,
-       .help_msg       = "unRaw",
+       .help_msg       = "unraw(r)",
        .action_msg     = "Keyboard mode set to system default",
        .enable_mask    = SYSRQ_ENABLE_KEYBOARD,
 };
@@ -135,7 +135,7 @@ static void sysrq_handle_crash(int key)
 }
 static struct sysrq_key_op sysrq_crash_op = {
        .handler        = sysrq_handle_crash,
-       .help_msg       = "Crash",
+       .help_msg       = "crash(c)",
        .action_msg     = "Trigger a crash",
        .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
@@ -148,7 +148,7 @@ static void sysrq_handle_reboot(int key)
 }
 static struct sysrq_key_op sysrq_reboot_op = {
        .handler        = sysrq_handle_reboot,
-       .help_msg       = "reBoot",
+       .help_msg       = "reboot(b)",
        .action_msg     = "Resetting",
        .enable_mask    = SYSRQ_ENABLE_BOOT,
 };
@@ -159,7 +159,7 @@ static void sysrq_handle_sync(int key)
 }
 static struct sysrq_key_op sysrq_sync_op = {
        .handler        = sysrq_handle_sync,
-       .help_msg       = "Sync",
+       .help_msg       = "sync(s)",
        .action_msg     = "Emergency Sync",
        .enable_mask    = SYSRQ_ENABLE_SYNC,
 };
@@ -171,7 +171,7 @@ static void sysrq_handle_show_timers(int key)
 
 static struct sysrq_key_op sysrq_show_timers_op = {
        .handler        = sysrq_handle_show_timers,
-       .help_msg       = "show-all-timers(Q)",
+       .help_msg       = "show-all-timers(q)",
        .action_msg     = "Show clockevent devices & pending hrtimers (no others)",
 };
 
@@ -181,7 +181,7 @@ static void sysrq_handle_mountro(int key)
 }
 static struct sysrq_key_op sysrq_mountro_op = {
        .handler        = sysrq_handle_mountro,
-       .help_msg       = "Unmount",
+       .help_msg       = "unmount(u)",
        .action_msg     = "Emergency Remount R/O",
        .enable_mask    = SYSRQ_ENABLE_REMOUNT,
 };
@@ -194,7 +194,7 @@ static void sysrq_handle_showlocks(int key)
 
 static struct sysrq_key_op sysrq_showlocks_op = {
        .handler        = sysrq_handle_showlocks,
-       .help_msg       = "show-all-locks(D)",
+       .help_msg       = "show-all-locks(d)",
        .action_msg     = "Show Locks Held",
 };
 #else
@@ -245,7 +245,7 @@ static void sysrq_handle_showallcpus(int key)
 
 static struct sysrq_key_op sysrq_showallcpus_op = {
        .handler        = sysrq_handle_showallcpus,
-       .help_msg       = "show-backtrace-all-active-cpus(L)",
+       .help_msg       = "show-backtrace-all-active-cpus(l)",
        .action_msg     = "Show backtrace of all active CPUs",
        .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
@@ -260,7 +260,7 @@ static void sysrq_handle_showregs(int key)
 }
 static struct sysrq_key_op sysrq_showregs_op = {
        .handler        = sysrq_handle_showregs,
-       .help_msg       = "show-registers(P)",
+       .help_msg       = "show-registers(p)",
        .action_msg     = "Show Regs",
        .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
@@ -271,7 +271,7 @@ static void sysrq_handle_showstate(int key)
 }
 static struct sysrq_key_op sysrq_showstate_op = {
        .handler        = sysrq_handle_showstate,
-       .help_msg       = "show-task-states(T)",
+       .help_msg       = "show-task-states(t)",
        .action_msg     = "Show State",
        .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
@@ -282,7 +282,7 @@ static void sysrq_handle_showstate_blocked(int key)
 }
 static struct sysrq_key_op sysrq_showstate_blocked_op = {
        .handler        = sysrq_handle_showstate_blocked,
-       .help_msg       = "show-blocked-tasks(W)",
+       .help_msg       = "show-blocked-tasks(w)",
        .action_msg     = "Show Blocked State",
        .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
@@ -296,7 +296,7 @@ static void sysrq_ftrace_dump(int key)
 }
 static struct sysrq_key_op sysrq_ftrace_dump_op = {
        .handler        = sysrq_ftrace_dump,
-       .help_msg       = "dump-ftrace-buffer(Z)",
+       .help_msg       = "dump-ftrace-buffer(z)",
        .action_msg     = "Dump ftrace buffer",
        .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
@@ -310,7 +310,7 @@ static void sysrq_handle_showmem(int key)
 }
 static struct sysrq_key_op sysrq_showmem_op = {
        .handler        = sysrq_handle_showmem,
-       .help_msg       = "show-memory-usage(M)",
+       .help_msg       = "show-memory-usage(m)",
        .action_msg     = "Show Memory",
        .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
@@ -341,7 +341,7 @@ static void sysrq_handle_term(int key)
 }
 static struct sysrq_key_op sysrq_term_op = {
        .handler        = sysrq_handle_term,
-       .help_msg       = "terminate-all-tasks(E)",
+       .help_msg       = "terminate-all-tasks(e)",
        .action_msg     = "Terminate All Tasks",
        .enable_mask    = SYSRQ_ENABLE_SIGNAL,
 };
@@ -360,7 +360,7 @@ static void sysrq_handle_moom(int key)
 }
 static struct sysrq_key_op sysrq_moom_op = {
        .handler        = sysrq_handle_moom,
-       .help_msg       = "memory-full-oom-kill(F)",
+       .help_msg       = "memory-full-oom-kill(f)",
        .action_msg     = "Manual OOM execution",
        .enable_mask    = SYSRQ_ENABLE_SIGNAL,
 };
@@ -372,7 +372,7 @@ static void sysrq_handle_thaw(int key)
 }
 static struct sysrq_key_op sysrq_thaw_op = {
        .handler        = sysrq_handle_thaw,
-       .help_msg       = "thaw-filesystems(J)",
+       .help_msg       = "thaw-filesystems(j)",
        .action_msg     = "Emergency Thaw of all frozen filesystems",
        .enable_mask    = SYSRQ_ENABLE_SIGNAL,
 };
@@ -385,7 +385,7 @@ static void sysrq_handle_kill(int key)
 }
 static struct sysrq_key_op sysrq_kill_op = {
        .handler        = sysrq_handle_kill,
-       .help_msg       = "kill-all-tasks(I)",
+       .help_msg       = "kill-all-tasks(i)",
        .action_msg     = "Kill All Tasks",
        .enable_mask    = SYSRQ_ENABLE_SIGNAL,
 };
@@ -396,7 +396,7 @@ static void sysrq_handle_unrt(int key)
 }
 static struct sysrq_key_op sysrq_unrt_op = {
        .handler        = sysrq_handle_unrt,
-       .help_msg       = "nice-all-RT-tasks(N)",
+       .help_msg       = "nice-all-RT-tasks(n)",
        .action_msg     = "Nice All RT Tasks",
        .enable_mask    = SYSRQ_ENABLE_RTNICE,
 };
index 578aa7594b11febce9cf50b6f5863bc8a34dfe8c..9121c1f7aeefef4b029501b114a5799f3195ca15 100644 (file)
@@ -449,11 +449,6 @@ static void flush_to_ldisc(struct work_struct *work)
                                tty_buffer_free(port, head);
                                continue;
                        }
-                       /* Ldisc or user is trying to flush the buffers
-                          we are feeding to the ldisc, stop feeding the
-                          line discipline as we want to empty the queue */
-                       if (test_bit(TTYP_FLUSHPENDING, &port->iflags))
-                               break;
                        if (!tty->receive_room)
                                break;
                        if (count > tty->receive_room)
@@ -465,17 +460,20 @@ static void flush_to_ldisc(struct work_struct *work)
                        disc->ops->receive_buf(tty, char_buf,
                                                        flag_buf, count);
                        spin_lock_irqsave(&buf->lock, flags);
+                       /* Ldisc or user is trying to flush the buffers.
+                          We may have a deferred request to flush the
+                          input buffer, if so pull the chain under the lock
+                          and empty the queue */
+                       if (test_bit(TTYP_FLUSHPENDING, &port->iflags)) {
+                               __tty_buffer_flush(port);
+                               clear_bit(TTYP_FLUSHPENDING, &port->iflags);
+                               wake_up(&tty->read_wait);
+                               break;
+                       }
                }
                clear_bit(TTYP_FLUSHING, &port->iflags);
        }
 
-       /* We may have a deferred request to flush the input buffer,
-          if so pull the chain under the lock and empty the queue */
-       if (test_bit(TTYP_FLUSHPENDING, &port->iflags)) {
-               __tty_buffer_flush(port);
-               clear_bit(TTYP_FLUSHPENDING, &port->iflags);
-               wake_up(&tty->read_wait);
-       }
        spin_unlock_irqrestore(&buf->lock, flags);
 
        tty_ldisc_deref(disc);
index 05400acbc456f1e9e888972e5c73c5c4f634d71c..cbf5a5040908c62258447994204949759d79755d 100644 (file)
@@ -532,6 +532,60 @@ void tty_wakeup(struct tty_struct *tty)
 
 EXPORT_SYMBOL_GPL(tty_wakeup);
 
+/**
+ *     tty_signal_session_leader       - sends SIGHUP to session leader
+ *     @tty            controlling tty
+ *     @exit_session   if non-zero, signal all foreground group processes
+ *
+ *     Send SIGHUP and SIGCONT to the session leader and its process group.
+ *     Optionally, signal all processes in the foreground process group.
+ *
+ *     Returns the number of processes in the session with this tty
+ *     as their controlling terminal. This value is used to drop
+ *     tty references for those processes.
+ */
+static int tty_signal_session_leader(struct tty_struct *tty, int exit_session)
+{
+       struct task_struct *p;
+       int refs = 0;
+       struct pid *tty_pgrp = NULL;
+
+       read_lock(&tasklist_lock);
+       if (tty->session) {
+               do_each_pid_task(tty->session, PIDTYPE_SID, p) {
+                       spin_lock_irq(&p->sighand->siglock);
+                       if (p->signal->tty == tty) {
+                               p->signal->tty = NULL;
+                               /* We defer the dereferences outside fo
+                                  the tasklist lock */
+                               refs++;
+                       }
+                       if (!p->signal->leader) {
+                               spin_unlock_irq(&p->sighand->siglock);
+                               continue;
+                       }
+                       __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
+                       __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
+                       put_pid(p->signal->tty_old_pgrp);  /* A noop */
+                       spin_lock(&tty->ctrl_lock);
+                       tty_pgrp = get_pid(tty->pgrp);
+                       if (tty->pgrp)
+                               p->signal->tty_old_pgrp = get_pid(tty->pgrp);
+                       spin_unlock(&tty->ctrl_lock);
+                       spin_unlock_irq(&p->sighand->siglock);
+               } while_each_pid_task(tty->session, PIDTYPE_SID, p);
+       }
+       read_unlock(&tasklist_lock);
+
+       if (tty_pgrp) {
+               if (exit_session)
+                       kill_pgrp(tty_pgrp, SIGHUP, exit_session);
+               put_pid(tty_pgrp);
+       }
+
+       return refs;
+}
+
 /**
  *     __tty_hangup            -       actual handler for hangup events
  *     @work: tty device
@@ -554,15 +608,13 @@ EXPORT_SYMBOL_GPL(tty_wakeup);
  *               tasklist_lock to walk task list for hangup event
  *                 ->siglock to protect ->signal/->sighand
  */
-static void __tty_hangup(struct tty_struct *tty)
+static void __tty_hangup(struct tty_struct *tty, int exit_session)
 {
        struct file *cons_filp = NULL;
        struct file *filp, *f = NULL;
-       struct task_struct *p;
        struct tty_file_private *priv;
        int    closecount = 0, n;
-       unsigned long flags;
-       int refs = 0;
+       int refs;
 
        if (!tty)
                return;
@@ -599,39 +651,18 @@ static void __tty_hangup(struct tty_struct *tty)
        }
        spin_unlock(&tty_files_lock);
 
+       refs = tty_signal_session_leader(tty, exit_session);
+       /* Account for the p->signal references we killed */
+       while (refs--)
+               tty_kref_put(tty);
+
        /*
         * it drops BTM and thus races with reopen
         * we protect the race by TTY_HUPPING
         */
        tty_ldisc_hangup(tty);
 
-       read_lock(&tasklist_lock);
-       if (tty->session) {
-               do_each_pid_task(tty->session, PIDTYPE_SID, p) {
-                       spin_lock_irq(&p->sighand->siglock);
-                       if (p->signal->tty == tty) {
-                               p->signal->tty = NULL;
-                               /* We defer the dereferences outside fo
-                                  the tasklist lock */
-                               refs++;
-                       }
-                       if (!p->signal->leader) {
-                               spin_unlock_irq(&p->sighand->siglock);
-                               continue;
-                       }
-                       __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
-                       __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
-                       put_pid(p->signal->tty_old_pgrp);  /* A noop */
-                       spin_lock_irqsave(&tty->ctrl_lock, flags);
-                       if (tty->pgrp)
-                               p->signal->tty_old_pgrp = get_pid(tty->pgrp);
-                       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-                       spin_unlock_irq(&p->sighand->siglock);
-               } while_each_pid_task(tty->session, PIDTYPE_SID, p);
-       }
-       read_unlock(&tasklist_lock);
-
-       spin_lock_irqsave(&tty->ctrl_lock, flags);
+       spin_lock_irq(&tty->ctrl_lock);
        clear_bit(TTY_THROTTLED, &tty->flags);
        clear_bit(TTY_PUSH, &tty->flags);
        clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
@@ -640,11 +671,7 @@ static void __tty_hangup(struct tty_struct *tty)
        tty->session = NULL;
        tty->pgrp = NULL;
        tty->ctrl_status = 0;
-       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-
-       /* Account for the p->signal references we killed */
-       while (refs--)
-               tty_kref_put(tty);
+       spin_unlock_irq(&tty->ctrl_lock);
 
        /*
         * If one of the devices matches a console pointer, we
@@ -666,7 +693,6 @@ static void __tty_hangup(struct tty_struct *tty)
         */
        set_bit(TTY_HUPPED, &tty->flags);
        clear_bit(TTY_HUPPING, &tty->flags);
-       tty_ldisc_enable(tty);
 
        tty_unlock(tty);
 
@@ -679,7 +705,7 @@ static void do_tty_hangup(struct work_struct *work)
        struct tty_struct *tty =
                container_of(work, struct tty_struct, hangup_work);
 
-       __tty_hangup(tty);
+       __tty_hangup(tty, 0);
 }
 
 /**
@@ -717,7 +743,7 @@ void tty_vhangup(struct tty_struct *tty)
 
        printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf));
 #endif
-       __tty_hangup(tty);
+       __tty_hangup(tty, 0);
 }
 
 EXPORT_SYMBOL(tty_vhangup);
@@ -740,6 +766,27 @@ void tty_vhangup_self(void)
        }
 }
 
+/**
+ *     tty_vhangup_session             -       hangup session leader exit
+ *     @tty: tty to hangup
+ *
+ *     The session leader is exiting and hanging up its controlling terminal.
+ *     Every process in the foreground process group is signalled SIGHUP.
+ *
+ *     We do this synchronously so that when the syscall returns the process
+ *     is complete. That guarantee is necessary for security reasons.
+ */
+
+static void tty_vhangup_session(struct tty_struct *tty)
+{
+#ifdef TTY_DEBUG_HANGUP
+       char    buf[64];
+
+       printk(KERN_DEBUG "%s vhangup session...\n", tty_name(tty, buf));
+#endif
+       __tty_hangup(tty, 1);
+}
+
 /**
  *     tty_hung_up_p           -       was tty hung up
  *     @filp: file pointer of tty
@@ -797,18 +844,18 @@ void disassociate_ctty(int on_exit)
 
        tty = get_current_tty();
        if (tty) {
-               struct pid *tty_pgrp = get_pid(tty->pgrp);
-               if (on_exit) {
-                       if (tty->driver->type != TTY_DRIVER_TYPE_PTY)
-                               tty_vhangup(tty);
-               }
-               tty_kref_put(tty);
-               if (tty_pgrp) {
-                       kill_pgrp(tty_pgrp, SIGHUP, on_exit);
-                       if (!on_exit)
+               if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) {
+                       tty_vhangup_session(tty);
+               } else {
+                       struct pid *tty_pgrp = tty_get_pgrp(tty);
+                       if (tty_pgrp) {
+                               kill_pgrp(tty_pgrp, SIGHUP, on_exit);
                                kill_pgrp(tty_pgrp, SIGCONT, on_exit);
-                       put_pid(tty_pgrp);
+                               put_pid(tty_pgrp);
+                       }
                }
+               tty_kref_put(tty);
+
        } else if (on_exit) {
                struct pid *old_pgrp;
                spin_lock_irq(&current->sighand->siglock);
@@ -1344,9 +1391,7 @@ static int tty_reopen(struct tty_struct *tty)
        }
        tty->count++;
 
-       mutex_lock(&tty->ldisc_mutex);
        WARN_ON(!test_bit(TTY_LDISC, &tty->flags));
-       mutex_unlock(&tty->ldisc_mutex);
 
        return 0;
 }
@@ -1463,6 +1508,17 @@ void tty_free_termios(struct tty_struct *tty)
 }
 EXPORT_SYMBOL(tty_free_termios);
 
+/**
+ *     tty_flush_works         -       flush all works of a tty
+ *     @tty: tty device to flush works for
+ *
+ *     Sync flush all works belonging to @tty.
+ */
+static void tty_flush_works(struct tty_struct *tty)
+{
+       flush_work(&tty->SAK_work);
+       flush_work(&tty->hangup_work);
+}
 
 /**
  *     release_one_tty         -       release tty structure memory
@@ -1548,6 +1604,7 @@ static void release_tty(struct tty_struct *tty, int idx)
        tty_free_termios(tty);
        tty_driver_remove_tty(tty->driver, tty);
        tty->port->itty = NULL;
+       cancel_work_sync(&tty->port->buf.work);
 
        if (tty->link)
                tty_kref_put(tty->link);
@@ -1777,12 +1834,21 @@ int tty_release(struct inode *inode, struct file *filp)
                return 0;
 
 #ifdef TTY_DEBUG_HANGUP
-       printk(KERN_DEBUG "%s: freeing tty structure...\n", __func__);
+       printk(KERN_DEBUG "%s: %s: final close\n", __func__, tty_name(tty, buf));
 #endif
        /*
         * Ask the line discipline code to release its structures
         */
        tty_ldisc_release(tty, o_tty);
+
+       /* Wait for pending work before tty destruction commmences */
+       tty_flush_works(tty);
+       if (o_tty)
+               tty_flush_works(o_tty);
+
+#ifdef TTY_DEBUG_HANGUP
+       printk(KERN_DEBUG "%s: %s: freeing structure...\n", __func__, tty_name(tty, buf));
+#endif
        /*
         * The release_tty function takes care of the details of clearing
         * the slots and preserving the termios structure. The tty_unlock_pair
index d58b92cc187cc21b05229ee9cdd7e936519fffb8..d119034877decb4402c1f2bad5b87e896a20943e 100644 (file)
@@ -106,6 +106,7 @@ void tty_throttle(struct tty_struct *tty)
        if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
            tty->ops->throttle)
                tty->ops->throttle(tty);
+       tty->flow_change = 0;
        mutex_unlock(&tty->termios_mutex);
 }
 EXPORT_SYMBOL(tty_throttle);
@@ -129,10 +130,73 @@ void tty_unthrottle(struct tty_struct *tty)
        if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
            tty->ops->unthrottle)
                tty->ops->unthrottle(tty);
+       tty->flow_change = 0;
        mutex_unlock(&tty->termios_mutex);
 }
 EXPORT_SYMBOL(tty_unthrottle);
 
+/**
+ *     tty_throttle_safe       -       flow control
+ *     @tty: terminal
+ *
+ *     Similar to tty_throttle() but will only attempt throttle
+ *     if tty->flow_change is TTY_THROTTLE_SAFE. Prevents an accidental
+ *     throttle due to race conditions when throttling is conditional
+ *     on factors evaluated prior to throttling.
+ *
+ *     Returns 0 if tty is throttled (or was already throttled)
+ */
+
+int tty_throttle_safe(struct tty_struct *tty)
+{
+       int ret = 0;
+
+       mutex_lock(&tty->termios_mutex);
+       if (!test_bit(TTY_THROTTLED, &tty->flags)) {
+               if (tty->flow_change != TTY_THROTTLE_SAFE)
+                       ret = 1;
+               else {
+                       __set_bit(TTY_THROTTLED, &tty->flags);
+                       if (tty->ops->throttle)
+                               tty->ops->throttle(tty);
+               }
+       }
+       mutex_unlock(&tty->termios_mutex);
+
+       return ret;
+}
+
+/**
+ *     tty_unthrottle_safe     -       flow control
+ *     @tty: terminal
+ *
+ *     Similar to tty_unthrottle() but will only attempt unthrottle
+ *     if tty->flow_change is TTY_UNTHROTTLE_SAFE. Prevents an accidental
+ *     unthrottle due to race conditions when unthrottling is conditional
+ *     on factors evaluated prior to unthrottling.
+ *
+ *     Returns 0 if tty is unthrottled (or was already unthrottled)
+ */
+
+int tty_unthrottle_safe(struct tty_struct *tty)
+{
+       int ret = 0;
+
+       mutex_lock(&tty->termios_mutex);
+       if (test_bit(TTY_THROTTLED, &tty->flags)) {
+               if (tty->flow_change != TTY_UNTHROTTLE_SAFE)
+                       ret = 1;
+               else {
+                       __clear_bit(TTY_THROTTLED, &tty->flags);
+                       if (tty->ops->unthrottle)
+                               tty->ops->unthrottle(tty);
+               }
+       }
+       mutex_unlock(&tty->termios_mutex);
+
+       return ret;
+}
+
 /**
  *     tty_wait_until_sent     -       wait for I/O to finish
  *     @tty: tty we are waiting for
@@ -414,34 +478,6 @@ void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
 }
 EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
 
-/**
- *     tty_get_baud_rate       -       get tty bit rates
- *     @tty: tty to query
- *
- *     Returns the baud rate as an integer for this terminal. The
- *     termios lock must be held by the caller and the terminal bit
- *     flags may be updated.
- *
- *     Locking: none
- */
-
-speed_t tty_get_baud_rate(struct tty_struct *tty)
-{
-       speed_t baud = tty_termios_baud_rate(&tty->termios);
-
-       if (baud == 38400 && tty->alt_speed) {
-               if (!tty->warned) {
-                       printk(KERN_WARNING "Use of setserial/setrocket to "
-                                           "set SPD_* flags is deprecated\n");
-                       tty->warned = 1;
-               }
-               baud = tty->alt_speed;
-       }
-
-       return baud;
-}
-EXPORT_SYMBOL(tty_get_baud_rate);
-
 /**
  *     tty_termios_copy_hw     -       copy hardware settings
  *     @new: New termios
@@ -1086,14 +1122,12 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
 }
 EXPORT_SYMBOL_GPL(tty_mode_ioctl);
 
-int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
+
+/* Caller guarantees ldisc reference is held */
+static int __tty_perform_flush(struct tty_struct *tty, unsigned long arg)
 {
-       struct tty_ldisc *ld;
-       int retval = tty_check_change(tty);
-       if (retval)
-               return retval;
+       struct tty_ldisc *ld = tty->ldisc;
 
-       ld = tty_ldisc_ref_wait(tty);
        switch (arg) {
        case TCIFLUSH:
                if (ld && ld->ops->flush_buffer) {
@@ -1111,12 +1145,24 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
                tty_driver_flush_buffer(tty);
                break;
        default:
-               tty_ldisc_deref(ld);
                return -EINVAL;
        }
-       tty_ldisc_deref(ld);
        return 0;
 }
+
+int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
+{
+       struct tty_ldisc *ld;
+       int retval = tty_check_change(tty);
+       if (retval)
+               return retval;
+
+       ld = tty_ldisc_ref_wait(tty);
+       retval = __tty_perform_flush(tty, arg);
+       if (ld)
+               tty_ldisc_deref(ld);
+       return retval;
+}
 EXPORT_SYMBOL_GPL(tty_perform_flush);
 
 int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
@@ -1155,7 +1201,7 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
                }
                return 0;
        case TCFLSH:
-               return tty_perform_flush(tty, arg);
+               return __tty_perform_flush(tty, arg);
        default:
                /* Try the mode commands */
                return tty_mode_ioctl(tty, file, cmd, arg);
index d794087c327e5b6ed85c647a66bb19114973aad3..1afe192bef6a7e8a795c91a3cf38a26615b6f2a1 100644 (file)
 #include <linux/uaccess.h>
 #include <linux/ratelimit.h>
 
+#undef LDISC_DEBUG_HANGUP
+
+#ifdef LDISC_DEBUG_HANGUP
+#define tty_ldisc_debug(tty, f, args...) ({                                   \
+       char __b[64];                                                          \
+       printk(KERN_DEBUG "%s: %s: " f, __func__, tty_name(tty, __b), ##args); \
+})
+#else
+#define tty_ldisc_debug(tty, f, args...)
+#endif
+
 /*
  *     This guards the refcounted line discipline lists. The lock
  *     must be taken with irqs off because there are hangup path
@@ -31,44 +42,6 @@ static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
 /* Line disc dispatch table */
 static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
 
-static inline struct tty_ldisc *get_ldisc(struct tty_ldisc *ld)
-{
-       if (ld)
-               atomic_inc(&ld->users);
-       return ld;
-}
-
-static void put_ldisc(struct tty_ldisc *ld)
-{
-       unsigned long flags;
-
-       if (WARN_ON_ONCE(!ld))
-               return;
-
-       /*
-        * If this is the last user, free the ldisc, and
-        * release the ldisc ops.
-        *
-        * We really want an "atomic_dec_and_raw_lock_irqsave()",
-        * but we don't have it, so this does it by hand.
-        */
-       raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
-       if (atomic_dec_and_test(&ld->users)) {
-               struct tty_ldisc_ops *ldo = ld->ops;
-
-               ldo->refcount--;
-               module_put(ldo->owner);
-               raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-
-               kfree(ld);
-               return;
-       }
-       raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-
-       if (waitqueue_active(&ld->wq_idle))
-               wake_up(&ld->wq_idle);
-}
-
 /**
  *     tty_register_ldisc      -       install a line discipline
  *     @disc: ldisc number
@@ -206,6 +179,29 @@ static struct tty_ldisc *tty_ldisc_get(int disc)
        return ld;
 }
 
+/**
+ *     tty_ldisc_put           -       release the ldisc
+ *
+ *     Complement of tty_ldisc_get().
+ */
+static inline void tty_ldisc_put(struct tty_ldisc *ld)
+{
+       unsigned long flags;
+
+       if (WARN_ON_ONCE(!ld))
+               return;
+
+       raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
+
+       /* unreleased reader reference(s) will cause this WARN */
+       WARN_ON(!atomic_dec_and_test(&ld->users));
+
+       ld->ops->refcount--;
+       module_put(ld->ops->owner);
+       kfree(ld);
+       raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+}
+
 static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
 {
        return (*pos < NR_LDISCS) ? pos : NULL;
@@ -254,24 +250,6 @@ const struct file_operations tty_ldiscs_proc_fops = {
        .release        = seq_release,
 };
 
-/**
- *     tty_ldisc_assign        -       set ldisc on a tty
- *     @tty: tty to assign
- *     @ld: line discipline
- *
- *     Install an instance of a line discipline into a tty structure. The
- *     ldisc must have a reference count above zero to ensure it remains.
- *     The tty instance refcount starts at zero.
- *
- *     Locking:
- *             Caller must hold references
- */
-
-static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
-{
-       tty->ldisc = ld;
-}
-
 /**
  *     tty_ldisc_try           -       internal helper
  *     @tty: the tty
@@ -289,10 +267,13 @@ static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty)
        unsigned long flags;
        struct tty_ldisc *ld;
 
+       /* FIXME: this allows reference acquire after TTY_LDISC is cleared */
        raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
        ld = NULL;
-       if (test_bit(TTY_LDISC, &tty->flags))
-               ld = get_ldisc(tty->ldisc);
+       if (test_bit(TTY_LDISC, &tty->flags) && tty->ldisc) {
+               ld = tty->ldisc;
+               atomic_inc(&ld->users);
+       }
        raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
        return ld;
 }
@@ -352,14 +333,23 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref);
 
 void tty_ldisc_deref(struct tty_ldisc *ld)
 {
-       put_ldisc(ld);
-}
-EXPORT_SYMBOL_GPL(tty_ldisc_deref);
+       unsigned long flags;
 
-static inline void tty_ldisc_put(struct tty_ldisc *ld)
-{
-       put_ldisc(ld);
+       if (WARN_ON_ONCE(!ld))
+               return;
+
+       raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
+       /*
+        * WARNs if one-too-many reader references were released
+        * - the last reference must be released with tty_ldisc_put
+        */
+       WARN_ON(atomic_dec_and_test(&ld->users));
+       raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+       if (waitqueue_active(&ld->wq_idle))
+               wake_up(&ld->wq_idle);
 }
+EXPORT_SYMBOL_GPL(tty_ldisc_deref);
 
 /**
  *     tty_ldisc_enable        -       allow ldisc use
@@ -373,8 +363,9 @@ static inline void tty_ldisc_put(struct tty_ldisc *ld)
  *     Clearing directly is allowed.
  */
 
-void tty_ldisc_enable(struct tty_struct *tty)
+static void tty_ldisc_enable(struct tty_struct *tty)
 {
+       clear_bit(TTY_LDISC_HALTED, &tty->flags);
        set_bit(TTY_LDISC, &tty->flags);
        clear_bit(TTY_LDISC_CHANGING, &tty->flags);
        wake_up(&tty_ldisc_wait);
@@ -479,7 +470,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
        /* There is an outstanding reference here so this is safe */
        old = tty_ldisc_get(old->ops->num);
        WARN_ON(IS_ERR(old));
-       tty_ldisc_assign(tty, old);
+       tty->ldisc = old;
        tty_set_termios_ldisc(tty, old->ops->num);
        if (tty_ldisc_open(tty, old) < 0) {
                tty_ldisc_put(old);
@@ -487,7 +478,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
                new_ldisc = tty_ldisc_get(N_TTY);
                if (IS_ERR(new_ldisc))
                        panic("n_tty: get");
-               tty_ldisc_assign(tty, new_ldisc);
+               tty->ldisc = new_ldisc;
                tty_set_termios_ldisc(tty, N_TTY);
                r = tty_ldisc_open(tty, new_ldisc);
                if (r < 0)
@@ -497,53 +488,99 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
        }
 }
 
+/**
+ *     tty_ldisc_wait_idle     -       wait for the ldisc to become idle
+ *     @tty: tty to wait for
+ *     @timeout: for how long to wait at most
+ *
+ *     Wait for the line discipline to become idle. The discipline must
+ *     have been halted for this to guarantee it remains idle.
+ */
+static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout)
+{
+       long ret;
+       ret = wait_event_timeout(tty->ldisc->wq_idle,
+                       atomic_read(&tty->ldisc->users) == 1, timeout);
+       return ret > 0 ? 0 : -EBUSY;
+}
+
 /**
  *     tty_ldisc_halt          -       shut down the line discipline
  *     @tty: tty device
+ *     @o_tty: paired pty device (can be NULL)
+ *     @timeout: # of jiffies to wait for ldisc refs to be released
  *
- *     Shut down the line discipline and work queue for this tty device.
- *     The TTY_LDISC flag being cleared ensures no further references can
- *     be obtained while the delayed work queue halt ensures that no more
- *     data is fed to the ldisc.
+ *     Shut down the line discipline and work queue for this tty device and
+ *     its paired pty (if exists). Clearing the TTY_LDISC flag ensures
+ *     no further references can be obtained, while waiting for existing
+ *     references to be released ensures no more data is fed to the ldisc.
  *
  *     You need to do a 'flush_scheduled_work()' (outside the ldisc_mutex)
  *     in order to make sure any currently executing ldisc work is also
  *     flushed.
  */
 
-static int tty_ldisc_halt(struct tty_struct *tty)
+static int tty_ldisc_halt(struct tty_struct *tty, struct tty_struct *o_tty,
+                         long timeout)
 {
+       int retval;
+
        clear_bit(TTY_LDISC, &tty->flags);
-       return cancel_work_sync(&tty->port->buf.work);
-}
+       if (o_tty)
+               clear_bit(TTY_LDISC, &o_tty->flags);
 
-/**
- *     tty_ldisc_flush_works   -       flush all works of a tty
- *     @tty: tty device to flush works for
- *
- *     Sync flush all works belonging to @tty.
- */
-static void tty_ldisc_flush_works(struct tty_struct *tty)
-{
-       flush_work(&tty->hangup_work);
-       flush_work(&tty->SAK_work);
-       flush_work(&tty->port->buf.work);
+       retval = tty_ldisc_wait_idle(tty, timeout);
+       if (!retval && o_tty)
+               retval = tty_ldisc_wait_idle(o_tty, timeout);
+       if (retval)
+               return retval;
+
+       set_bit(TTY_LDISC_HALTED, &tty->flags);
+       if (o_tty)
+               set_bit(TTY_LDISC_HALTED, &o_tty->flags);
+
+       return 0;
 }
 
 /**
- *     tty_ldisc_wait_idle     -       wait for the ldisc to become idle
- *     @tty: tty to wait for
- *     @timeout: for how long to wait at most
+ *     tty_ldisc_hangup_halt - halt the line discipline for hangup
+ *     @tty: tty being hung up
  *
- *     Wait for the line discipline to become idle. The discipline must
- *     have been halted for this to guarantee it remains idle.
+ *     Shut down the line discipline and work queue for the tty device
+ *     being hungup. Clear the TTY_LDISC flag to ensure no further
+ *     references can be obtained and wait for remaining references to be
+ *     released to ensure no more data is fed to this ldisc.
+ *     Caller must hold legacy and ->ldisc_mutex.
+ *
+ *     NB: tty_set_ldisc() is prevented from changing the ldisc concurrently
+ *     with this function by checking the TTY_HUPPING flag.
  */
-static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout)
+static bool tty_ldisc_hangup_halt(struct tty_struct *tty)
 {
-       long ret;
-       ret = wait_event_timeout(tty->ldisc->wq_idle,
-                       atomic_read(&tty->ldisc->users) == 1, timeout);
-       return ret > 0 ? 0 : -EBUSY;
+       char cur_n[TASK_COMM_LEN], tty_n[64];
+       long timeout = 3 * HZ;
+
+       clear_bit(TTY_LDISC, &tty->flags);
+
+       if (tty->ldisc) {       /* Not yet closed */
+               tty_unlock(tty);
+
+               while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
+                       timeout = MAX_SCHEDULE_TIMEOUT;
+                       printk_ratelimited(KERN_WARNING
+                               "%s: waiting (%s) for %s took too long, but we keep waiting...\n",
+                               __func__, get_task_comm(cur_n, current),
+                               tty_name(tty, tty_n));
+               }
+
+               set_bit(TTY_LDISC_HALTED, &tty->flags);
+
+               /* must reacquire both locks and preserve lock order */
+               mutex_unlock(&tty->ldisc_mutex);
+               tty_lock(tty);
+               mutex_lock(&tty->ldisc_mutex);
+       }
+       return !!tty->ldisc;
 }
 
 /**
@@ -563,7 +600,6 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 {
        int retval;
        struct tty_ldisc *o_ldisc, *new_ldisc;
-       int work, o_work = 0;
        struct tty_struct *o_tty;
 
        new_ldisc = tty_ldisc_get(ldisc);
@@ -589,15 +625,6 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
                return 0;
        }
 
-       tty_unlock(tty);
-       /*
-        *      Problem: What do we do if this blocks ?
-        *      We could deadlock here
-        */
-
-       tty_wait_until_sent(tty, 0);
-
-       tty_lock(tty);
        mutex_lock(&tty->ldisc_mutex);
 
        /*
@@ -637,20 +664,16 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
         *      parallel to the change and re-referencing the tty.
         */
 
-       work = tty_ldisc_halt(tty);
-       if (o_tty)
-               o_work = tty_ldisc_halt(o_tty);
+       retval = tty_ldisc_halt(tty, o_tty, 5 * HZ);
 
        /*
-        * Wait for ->hangup_work and ->buf.work handlers to terminate.
+        * Wait for hangup to complete, if pending.
         * We must drop the mutex here in case a hangup is also in process.
         */
 
        mutex_unlock(&tty->ldisc_mutex);
 
-       tty_ldisc_flush_works(tty);
-
-       retval = tty_ldisc_wait_idle(tty, 5 * HZ);
+       flush_work(&tty->hangup_work);
 
        tty_lock(tty);
        mutex_lock(&tty->ldisc_mutex);
@@ -675,7 +698,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
        tty_ldisc_close(tty, o_ldisc);
 
        /* Now set up the new line discipline. */
-       tty_ldisc_assign(tty, new_ldisc);
+       tty->ldisc = new_ldisc;
        tty_set_termios_ldisc(tty, ldisc);
 
        retval = tty_ldisc_open(tty, new_ldisc);
@@ -705,10 +728,10 @@ enable:
 
        /* Restart the work queue in case no characters kick it off. Safe if
           already running */
-       if (work)
-               schedule_work(&tty->port->buf.work);
-       if (o_work)
+       schedule_work(&tty->port->buf.work);
+       if (o_tty)
                schedule_work(&o_tty->port->buf.work);
+
        mutex_unlock(&tty->ldisc_mutex);
        tty_unlock(tty);
        return retval;
@@ -749,11 +772,10 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
 
        tty_ldisc_close(tty, tty->ldisc);
        tty_ldisc_put(tty->ldisc);
-       tty->ldisc = NULL;
        /*
         *      Switch the line discipline back
         */
-       tty_ldisc_assign(tty, ld);
+       tty->ldisc = ld;
        tty_set_termios_ldisc(tty, ldisc);
 
        return 0;
@@ -780,6 +802,8 @@ void tty_ldisc_hangup(struct tty_struct *tty)
        int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS;
        int err = 0;
 
+       tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
+
        /*
         * FIXME! What are the locking issues here? This may me overdoing
         * things... This question is especially important now that we've
@@ -812,40 +836,12 @@ void tty_ldisc_hangup(struct tty_struct *tty)
         */
        mutex_lock(&tty->ldisc_mutex);
 
-       /*
-        * this is like tty_ldisc_halt, but we need to give up
-        * the BTM before calling cancel_work_sync, which may
-        * need to wait for another function taking the BTM
-        */
-       clear_bit(TTY_LDISC, &tty->flags);
-       tty_unlock(tty);
-       cancel_work_sync(&tty->port->buf.work);
-       mutex_unlock(&tty->ldisc_mutex);
-retry:
-       tty_lock(tty);
-       mutex_lock(&tty->ldisc_mutex);
-
-       /* At this point we have a closed ldisc and we want to
-          reopen it. We could defer this to the next open but
-          it means auditing a lot of other paths so this is
-          a FIXME */
-       if (tty->ldisc) {       /* Not yet closed */
-               if (atomic_read(&tty->ldisc->users) != 1) {
-                       char cur_n[TASK_COMM_LEN], tty_n[64];
-                       long timeout = 3 * HZ;
-                       tty_unlock(tty);
-
-                       while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
-                               timeout = MAX_SCHEDULE_TIMEOUT;
-                               printk_ratelimited(KERN_WARNING
-                                       "%s: waiting (%s) for %s took too long, but we keep waiting...\n",
-                                       __func__, get_task_comm(cur_n, current),
-                                       tty_name(tty, tty_n));
-                       }
-                       mutex_unlock(&tty->ldisc_mutex);
-                       goto retry;
-               }
+       if (tty_ldisc_hangup_halt(tty)) {
 
+               /* At this point we have a halted ldisc; we want to close it and
+                  reopen a new ldisc. We could defer the reopen to the next
+                  open but it means auditing a lot of other paths so this is
+                  a FIXME */
                if (reset == 0) {
 
                        if (!tty_ldisc_reinit(tty, tty->termios.c_line))
@@ -864,6 +860,8 @@ retry:
        mutex_unlock(&tty->ldisc_mutex);
        if (reset)
                tty_reset_termios(tty);
+
+       tty_ldisc_debug(tty, "re-opened ldisc: %p\n", tty->ldisc);
 }
 
 /**
@@ -899,11 +897,6 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
 
 static void tty_ldisc_kill(struct tty_struct *tty)
 {
-       /* There cannot be users from userspace now. But there still might be
-        * drivers holding a reference via tty_ldisc_ref. Do not steal them the
-        * ldisc until they are done. */
-       tty_ldisc_wait_idle(tty, MAX_SCHEDULE_TIMEOUT);
-
        mutex_lock(&tty->ldisc_mutex);
        /*
         * Now kill off the ldisc
@@ -931,18 +924,13 @@ static void tty_ldisc_kill(struct tty_struct *tty)
 void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
 {
        /*
-        * Prevent flush_to_ldisc() from rescheduling the work for later.  Then
-        * kill any delayed work. As this is the final close it does not
-        * race with the set_ldisc code path.
+        * Shutdown this line discipline. As this is the final close,
+        * it does not race with the set_ldisc code path.
         */
 
-       tty_ldisc_halt(tty);
-       if (o_tty)
-               tty_ldisc_halt(o_tty);
+       tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
 
-       tty_ldisc_flush_works(tty);
-       if (o_tty)
-               tty_ldisc_flush_works(o_tty);
+       tty_ldisc_halt(tty, o_tty, MAX_SCHEDULE_TIMEOUT);
 
        tty_lock_pair(tty, o_tty);
        /* This will need doing differently if we need to lock */
@@ -953,6 +941,8 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
        tty_unlock_pair(tty, o_tty);
        /* And the memory resources remaining (buffers, termios) will be
           disposed of when the kref hits zero */
+
+       tty_ldisc_debug(tty, "ldisc closed\n");
 }
 
 /**
@@ -968,7 +958,7 @@ void tty_ldisc_init(struct tty_struct *tty)
        struct tty_ldisc *ld = tty_ldisc_get(N_TTY);
        if (IS_ERR(ld))
                panic("n_tty: init_tty");
-       tty_ldisc_assign(tty, ld);
+       tty->ldisc = ld;
 }
 
 /**
@@ -980,8 +970,8 @@ void tty_ldisc_init(struct tty_struct *tty)
  */
 void tty_ldisc_deinit(struct tty_struct *tty)
 {
-       put_ldisc(tty->ldisc);
-       tty_ldisc_assign(tty, NULL);
+       tty_ldisc_put(tty->ldisc);
+       tty->ldisc = NULL;
 }
 
 void tty_ldisc_begin(void)
index b7ff59d3db88f85d5f37027e2adf44d036c1e0a2..121aeb9393e1172e75fe5972a7c4b8ab4640557f 100644 (file)
@@ -132,6 +132,7 @@ EXPORT_SYMBOL(tty_port_free_xmit_buf);
  */
 void tty_port_destroy(struct tty_port *port)
 {
+       cancel_work_sync(&port->buf.work);
        tty_buffer_free_all(port);
 }
 EXPORT_SYMBOL(tty_port_destroy);
@@ -196,12 +197,24 @@ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
 }
 EXPORT_SYMBOL(tty_port_tty_set);
 
-static void tty_port_shutdown(struct tty_port *port)
+static void tty_port_shutdown(struct tty_port *port, struct tty_struct *tty)
 {
        mutex_lock(&port->mutex);
-       if (port->ops->shutdown && !port->console &&
-               test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
+       if (port->console)
+               goto out;
+
+       if (test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) {
+               /*
+                * Drop DTR/RTS if HUPCL is set. This causes any attached
+                * modem to hang up the line.
+                */
+               if (tty && C_HUPCL(tty))
+                       tty_port_lower_dtr_rts(port);
+
+               if (port->ops->shutdown)
                        port->ops->shutdown(port);
+       }
+out:
        mutex_unlock(&port->mutex);
 }
 
@@ -215,23 +228,57 @@ static void tty_port_shutdown(struct tty_port *port)
 
 void tty_port_hangup(struct tty_port *port)
 {
+       struct tty_struct *tty;
        unsigned long flags;
 
        spin_lock_irqsave(&port->lock, flags);
        port->count = 0;
        port->flags &= ~ASYNC_NORMAL_ACTIVE;
-       if (port->tty) {
-               set_bit(TTY_IO_ERROR, &port->tty->flags);
-               tty_kref_put(port->tty);
-       }
+       tty = port->tty;
+       if (tty)
+               set_bit(TTY_IO_ERROR, &tty->flags);
        port->tty = NULL;
        spin_unlock_irqrestore(&port->lock, flags);
+       tty_port_shutdown(port, tty);
+       tty_kref_put(tty);
        wake_up_interruptible(&port->open_wait);
        wake_up_interruptible(&port->delta_msr_wait);
-       tty_port_shutdown(port);
 }
 EXPORT_SYMBOL(tty_port_hangup);
 
+/**
+ * tty_port_tty_hangup - helper to hang up a tty
+ *
+ * @port: tty port
+ * @check_clocal: hang only ttys with CLOCAL unset?
+ */
+void tty_port_tty_hangup(struct tty_port *port, bool check_clocal)
+{
+       struct tty_struct *tty = tty_port_tty_get(port);
+
+       if (tty && (!check_clocal || !C_CLOCAL(tty))) {
+               tty_hangup(tty);
+               tty_kref_put(tty);
+       }
+}
+EXPORT_SYMBOL_GPL(tty_port_tty_hangup);
+
+/**
+ * tty_port_tty_wakeup - helper to wake up a tty
+ *
+ * @port: tty port
+ */
+void tty_port_tty_wakeup(struct tty_port *port)
+{
+       struct tty_struct *tty = tty_port_tty_get(port);
+
+       if (tty) {
+               tty_wakeup(tty);
+               tty_kref_put(tty);
+       }
+}
+EXPORT_SYMBOL_GPL(tty_port_tty_wakeup);
+
 /**
  *     tty_port_carrier_raised -       carrier raised check
  *     @port: tty port
@@ -350,7 +397,7 @@ int tty_port_block_til_ready(struct tty_port *port,
 
        while (1) {
                /* Indicate we are open */
-               if (tty->termios.c_cflag & CBAUD)
+               if (C_BAUD(tty) && test_bit(ASYNCB_INITIALIZED, &port->flags))
                        tty_port_raise_dtr_rts(port);
 
                prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
@@ -395,6 +442,20 @@ int tty_port_block_til_ready(struct tty_port *port,
 }
 EXPORT_SYMBOL(tty_port_block_til_ready);
 
+static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty)
+{
+       unsigned int bps = tty_get_baud_rate(tty);
+       long timeout;
+
+       if (bps > 1200) {
+               timeout = (HZ * 10 * port->drain_delay) / bps;
+               timeout = max_t(long, timeout, HZ / 10);
+       } else {
+               timeout = 2 * HZ;
+       }
+       schedule_timeout_interruptible(timeout);
+}
+
 int tty_port_close_start(struct tty_port *port,
                                struct tty_struct *tty, struct file *filp)
 {
@@ -427,31 +488,19 @@ int tty_port_close_start(struct tty_port *port,
        set_bit(ASYNCB_CLOSING, &port->flags);
        tty->closing = 1;
        spin_unlock_irqrestore(&port->lock, flags);
-       /* Don't block on a stalled port, just pull the chain */
-       if (tty->flow_stopped)
-               tty_driver_flush_buffer(tty);
-       if (test_bit(ASYNCB_INITIALIZED, &port->flags) &&
-                       port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-               tty_wait_until_sent_from_close(tty, port->closing_wait);
-       if (port->drain_delay) {
-               unsigned int bps = tty_get_baud_rate(tty);
-               long timeout;
-
-               if (bps > 1200)
-                       timeout = max_t(long,
-                               (HZ * 10 * port->drain_delay) / bps, HZ / 10);
-               else
-                       timeout = 2 * HZ;
-               schedule_timeout_interruptible(timeout);
+
+       if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
+               /* Don't block on a stalled port, just pull the chain */
+               if (tty->flow_stopped)
+                       tty_driver_flush_buffer(tty);
+               if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+                       tty_wait_until_sent_from_close(tty, port->closing_wait);
+               if (port->drain_delay)
+                       tty_port_drain_delay(port, tty);
        }
        /* Flush the ldisc buffering */
        tty_ldisc_flush(tty);
 
-       /* Drop DTR/RTS if HUPCL is set. This causes any attached modem to
-          hang up the line */
-       if (tty->termios.c_cflag & HUPCL)
-               tty_port_lower_dtr_rts(port);
-
        /* Don't call port->drop for the last reference. Callers will want
           to drop the last active reference in ->shutdown() or the tty
           shutdown path */
@@ -486,7 +535,7 @@ void tty_port_close(struct tty_port *port, struct tty_struct *tty,
 {
        if (tty_port_close_start(port, tty, filp) == 0)
                return;
-       tty_port_shutdown(port);
+       tty_port_shutdown(port, tty);
        set_bit(TTY_IO_ERROR, &tty->flags);
        tty_port_close_end(port, tty);
        tty_port_tty_set(port, NULL);
index 248381b30722723fcae93f8baab842520e6b57f8..2978ca596a7ff9179c4d4958eb99b9ed1863c4c6 100644 (file)
@@ -194,8 +194,7 @@ static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int
        q = p->inverse_translations[i];
 
        if (!q) {
-               q = p->inverse_translations[i] = (unsigned char *) 
-                       kmalloc(MAX_GLYPH, GFP_KERNEL);
+               q = p->inverse_translations[i] = kmalloc(MAX_GLYPH, GFP_KERNEL);
                if (!q) return;
        }
        memset(q, 0, MAX_GLYPH);
index 387dc6c8ad25b0d43a7d954ce71d877618fcb63d..c77f7ae48f1c1ed93260bea354e6c6b148a235f5 100644 (file)
@@ -292,7 +292,6 @@ static void acm_ctrl_irq(struct urb *urb)
 {
        struct acm *acm = urb->context;
        struct usb_cdc_notification *dr = urb->transfer_buffer;
-       struct tty_struct *tty;
        unsigned char *data;
        int newctrl;
        int retval;
@@ -327,17 +326,12 @@ static void acm_ctrl_irq(struct urb *urb)
                break;
 
        case USB_CDC_NOTIFY_SERIAL_STATE:
-               tty = tty_port_tty_get(&acm->port);
                newctrl = get_unaligned_le16(data);
 
-               if (tty) {
-                       if (!acm->clocal &&
-                               (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
-                               dev_dbg(&acm->control->dev,
-                                       "%s - calling hangup\n", __func__);
-                               tty_hangup(tty);
-                       }
-                       tty_kref_put(tty);
+               if (!acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
+                       dev_dbg(&acm->control->dev, "%s - calling hangup\n",
+                                       __func__);
+                       tty_port_tty_hangup(&acm->port, false);
                }
 
                acm->ctrlin = newctrl;
@@ -475,15 +469,10 @@ static void acm_write_bulk(struct urb *urb)
 static void acm_softint(struct work_struct *work)
 {
        struct acm *acm = container_of(work, struct acm, work);
-       struct tty_struct *tty;
 
        dev_vdbg(&acm->data->dev, "%s\n", __func__);
 
-       tty = tty_port_tty_get(&acm->port);
-       if (!tty)
-               return;
-       tty_wakeup(tty);
-       tty_kref_put(tty);
+       tty_port_tty_wakeup(&acm->port);
 }
 
 /*
@@ -1519,15 +1508,9 @@ err_out:
 static int acm_reset_resume(struct usb_interface *intf)
 {
        struct acm *acm = usb_get_intfdata(intf);
-       struct tty_struct *tty;
 
-       if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) {
-               tty = tty_port_tty_get(&acm->port);
-               if (tty) {
-                       tty_hangup(tty);
-                       tty_kref_put(tty);
-               }
-       }
+       if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags))
+               tty_port_tty_hangup(&acm->port, false);
 
        return acm_resume(intf);
 }
index ebe45fa0ed50a3722ed7feae0750558ffea7fdad..31191581060c94762c7265eb031e224ccb227713 100644 (file)
@@ -210,7 +210,6 @@ struct digi_port {
 
 /* Local Function Declarations */
 
-static void digi_wakeup_write(struct usb_serial_port *port);
 static void digi_wakeup_write_lock(struct work_struct *work);
 static int digi_write_oob_command(struct usb_serial_port *port,
        unsigned char *buf, int count, int interruptible);
@@ -374,20 +373,10 @@ static void digi_wakeup_write_lock(struct work_struct *work)
        unsigned long flags;
 
        spin_lock_irqsave(&priv->dp_port_lock, flags);
-       digi_wakeup_write(port);
+       tty_port_tty_wakeup(&port->port);
        spin_unlock_irqrestore(&priv->dp_port_lock, flags);
 }
 
-static void digi_wakeup_write(struct usb_serial_port *port)
-{
-       struct tty_struct *tty = tty_port_tty_get(&port->port);
-       if (tty) {
-               tty_wakeup(tty);
-               tty_kref_put(tty);
-       }
-}
-
-
 /*
  *  Digi Write OOB Command
  *
@@ -1044,7 +1033,7 @@ static void digi_write_bulk_callback(struct urb *urb)
                }
        }
        /* wake up processes sleeping on writes immediately */
-       digi_wakeup_write(port);
+       tty_port_tty_wakeup(&port->port);
        /* also queue up a wakeup at scheduler time, in case we */
        /* lost the race in write_chan(). */
        schedule_work(&priv->dp_wakeup_work);
@@ -1522,7 +1511,7 @@ static int digi_read_oob_callback(struct urb *urb)
                                /* port must be open to use tty struct */
                                if (rts) {
                                        tty->hw_stopped = 0;
-                                       digi_wakeup_write(port);
+                                       tty_port_tty_wakeup(&port->port);
                                }
                        } else {
                                priv->dp_modem_signals &= ~TIOCM_CTS;
index efd8b978128c1d86412322f0c37e9da32b00610a..cf0b0a2f7b564ee854fa95fd30ced39e8d1a3d60 100644 (file)
@@ -564,7 +564,6 @@ static void edge_interrupt_callback(struct urb *urb)
        struct device *dev;
        struct edgeport_port *edge_port;
        struct usb_serial_port *port;
-       struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
        int length = urb->actual_length;
        int bytes_avail;
@@ -643,12 +642,7 @@ static void edge_interrupt_callback(struct urb *urb)
 
                                        /* tell the tty driver that something
                                           has changed */
-                                       tty = tty_port_tty_get(
-                                               &edge_port->port->port);
-                                       if (tty) {
-                                               tty_wakeup(tty);
-                                               tty_kref_put(tty);
-                                       }
+                                       tty_port_tty_wakeup(&edge_port->port->port);
                                        /* Since we have more credit, check
                                           if more data can be sent */
                                        send_more_port_data(edge_serial,
@@ -737,7 +731,6 @@ static void edge_bulk_in_callback(struct urb *urb)
 static void edge_bulk_out_data_callback(struct urb *urb)
 {
        struct edgeport_port *edge_port = urb->context;
-       struct tty_struct *tty;
        int status = urb->status;
 
        if (status) {
@@ -746,14 +739,8 @@ static void edge_bulk_out_data_callback(struct urb *urb)
                        __func__, status);
        }
 
-       tty = tty_port_tty_get(&edge_port->port->port);
-
-       if (tty && edge_port->open) {
-               /* let the tty driver wakeup if it has a special
-                  write_wakeup function */
-               tty_wakeup(tty);
-       }
-       tty_kref_put(tty);
+       if (edge_port->open)
+               tty_port_tty_wakeup(&edge_port->port->port);
 
        /* Release the Write URB */
        edge_port->write_in_progress = false;
@@ -772,7 +759,6 @@ static void edge_bulk_out_data_callback(struct urb *urb)
 static void edge_bulk_out_cmd_callback(struct urb *urb)
 {
        struct edgeport_port *edge_port = urb->context;
-       struct tty_struct *tty;
        int status = urb->status;
 
        atomic_dec(&CmdUrbs);
@@ -793,13 +779,9 @@ static void edge_bulk_out_cmd_callback(struct urb *urb)
                return;
        }
 
-       /* Get pointer to tty */
-       tty = tty_port_tty_get(&edge_port->port->port);
-
        /* tell the tty driver that something has changed */
-       if (tty && edge_port->open)
-               tty_wakeup(tty);
-       tty_kref_put(tty);
+       if (edge_port->open)
+               tty_port_tty_wakeup(&edge_port->port->port);
 
        /* we have completed the command */
        edge_port->commandPending = false;
index 1fd1935c8316f525e5795c22fa0dada0093b6be9..b011478d2e5f43cffc8923f3264d69d9a4facceb 100644 (file)
@@ -378,7 +378,6 @@ static void usa26_instat_callback(struct urb *urb)
        struct usb_serial                       *serial;
        struct usb_serial_port                  *port;
        struct keyspan_port_private             *p_priv;
-       struct tty_struct                       *tty;
        int old_dcd_state, err;
        int status = urb->status;
 
@@ -421,12 +420,8 @@ static void        usa26_instat_callback(struct urb *urb)
        p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
        p_priv->ri_state = ((msg->ri) ? 1 : 0);
 
-       if (old_dcd_state != p_priv->dcd_state) {
-               tty = tty_port_tty_get(&port->port);
-               if (tty && !C_CLOCAL(tty))
-                       tty_hangup(tty);
-               tty_kref_put(tty);
-       }
+       if (old_dcd_state != p_priv->dcd_state)
+               tty_port_tty_hangup(&port->port, true);
 
        /* Resubmit urb so we continue receiving */
        err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -510,7 +505,6 @@ static void usa28_instat_callback(struct urb *urb)
        struct usb_serial                       *serial;
        struct usb_serial_port                  *port;
        struct keyspan_port_private             *p_priv;
-       struct tty_struct                       *tty;
        int old_dcd_state;
        int status = urb->status;
 
@@ -551,12 +545,8 @@ static void        usa28_instat_callback(struct urb *urb)
        p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
        p_priv->ri_state = ((msg->ri) ? 1 : 0);
 
-       if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
-               tty = tty_port_tty_get(&port->port);
-               if (tty && !C_CLOCAL(tty))
-                       tty_hangup(tty);
-               tty_kref_put(tty);
-       }
+       if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
+               tty_port_tty_hangup(&port->port, true);
 
                /* Resubmit urb so we continue receiving */
        err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -642,12 +632,8 @@ static void        usa49_instat_callback(struct urb *urb)
        p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
        p_priv->ri_state = ((msg->ri) ? 1 : 0);
 
-       if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
-               struct tty_struct *tty = tty_port_tty_get(&port->port);
-               if (tty && !C_CLOCAL(tty))
-                       tty_hangup(tty);
-               tty_kref_put(tty);
-       }
+       if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
+               tty_port_tty_hangup(&port->port, true);
 
        /* Resubmit urb so we continue receiving */
        err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -851,7 +837,6 @@ static void usa90_instat_callback(struct urb *urb)
        struct usb_serial                       *serial;
        struct usb_serial_port                  *port;
        struct keyspan_port_private             *p_priv;
-       struct tty_struct                       *tty;
        int old_dcd_state, err;
        int status = urb->status;
 
@@ -880,12 +865,8 @@ static void        usa90_instat_callback(struct urb *urb)
        p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
        p_priv->ri_state = ((msg->ri) ? 1 : 0);
 
-       if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
-               tty = tty_port_tty_get(&port->port);
-               if (tty && !C_CLOCAL(tty))
-                       tty_hangup(tty);
-               tty_kref_put(tty);
-       }
+       if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
+               tty_port_tty_hangup(&port->port, true);
 
        /* Resubmit urb so we continue receiving */
        err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -953,12 +934,8 @@ static void        usa67_instat_callback(struct urb *urb)
        p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
        p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
 
-       if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
-               struct tty_struct *tty = tty_port_tty_get(&port->port);
-               if (tty && !C_CLOCAL(tty))
-                       tty_hangup(tty);
-               tty_kref_put(tty);
-       }
+       if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
+               tty_port_tty_hangup(&port->port, true);
 
        /* Resubmit urb so we continue receiving */
        err = usb_submit_urb(urb, GFP_ATOMIC);
index 3b17d5d13dc86aa8fa9ebe8b6a290572c57a6323..2230223978ca731bef98ffb09b121ad974ff649f 100644 (file)
@@ -104,10 +104,8 @@ static void keyspan_pda_wakeup_write(struct work_struct *work)
        struct keyspan_pda_private *priv =
                container_of(work, struct keyspan_pda_private, wakeup_work);
        struct usb_serial_port *port = priv->port;
-       struct tty_struct *tty = tty_port_tty_get(&port->port);
-       if (tty)
-               tty_wakeup(tty);
-       tty_kref_put(tty);
+
+       tty_port_tty_wakeup(&port->port);
 }
 
 static void keyspan_pda_request_unthrottle(struct work_struct *work)
index e0ebec3b5d6ae077aa4ac0347e8a33470f8dc6c3..e956eae198fd6cfbb014fc727912953dee22d892 100644 (file)
@@ -932,7 +932,6 @@ static void mos7720_bulk_in_callback(struct urb *urb)
 static void mos7720_bulk_out_data_callback(struct urb *urb)
 {
        struct moschip_port *mos7720_port;
-       struct tty_struct *tty;
        int status = urb->status;
 
        if (status) {
@@ -946,11 +945,8 @@ static void mos7720_bulk_out_data_callback(struct urb *urb)
                return ;
        }
 
-       tty = tty_port_tty_get(&mos7720_port->port->port);
-
-       if (tty && mos7720_port->open)
-               tty_wakeup(tty);
-       tty_kref_put(tty);
+       if (mos7720_port->open)
+               tty_port_tty_wakeup(&mos7720_port->port->port);
 }
 
 /*
index b8051fa61911a54a23de8f9a1662518181b6c084..2be376a2e0e3883dbb1c0bc5059580c8a7fe915a 100644 (file)
@@ -816,7 +816,6 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
 {
        struct moschip_port *mos7840_port;
        struct usb_serial_port *port;
-       struct tty_struct *tty;
        int status = urb->status;
        int i;
 
@@ -839,10 +838,8 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
        if (mos7840_port_paranoia_check(port, __func__))
                return;
 
-       tty = tty_port_tty_get(&port->port);
-       if (tty && mos7840_port->open)
-               tty_wakeup(tty);
-       tty_kref_put(tty);
+       if (mos7840_port->open)
+               tty_port_tty_wakeup(&port->port);
 
 }
 
index 558adfc05007dbdf46f2dc9a5280579b3cdbdab2..09cd3967b8df777237d09819966350716cc2f7d0 100644 (file)
@@ -1537,13 +1537,8 @@ static void option_instat_callback(struct urb *urb)
                        portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
                        portdata->ri_state = ((signals & 0x08) ? 1 : 0);
 
-                       if (old_dcd_state && !portdata->dcd_state) {
-                               struct tty_struct *tty =
-                                               tty_port_tty_get(&port->port);
-                               if (tty && !C_CLOCAL(tty))
-                                       tty_hangup(tty);
-                               tty_kref_put(tty);
-                       }
+                       if (old_dcd_state && !portdata->dcd_state)
+                               tty_port_tty_hangup(&port->port, true);
                } else {
                        dev_dbg(dev, "%s: type %x req %x\n", __func__,
                                req_pkt->bRequestType, req_pkt->bRequest);
index 75f125ddb0c94136da28ebf5fa5d4e4200a0b410..ef3a7d5eaab4afa072daf8914b5db90040445fe6 100644 (file)
@@ -116,7 +116,6 @@ struct qt2_serial_private {
 };
 
 struct qt2_port_private {
-       bool is_open;
        u8   device_port;
 
        spinlock_t urb_lock;
@@ -397,7 +396,6 @@ static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port)
                return status;
        }
 
-       port_priv->is_open = true;
        port_priv->device_port = (u8) device_port;
 
        if (tty)
@@ -417,8 +415,6 @@ static void qt2_close(struct usb_serial_port *port)
        serial = port->serial;
        port_priv = usb_get_serial_port_data(port);
 
-       port_priv->is_open = false;
-
        spin_lock_irqsave(&port_priv->urb_lock, flags);
        usb_kill_urb(port_priv->write_urb);
        port_priv->urb_in_use = false;
@@ -664,9 +660,7 @@ void qt2_process_read_urb(struct urb *urb)
                                                 __func__);
                                        break;
                                }
-
-                               if (port_priv->is_open)
-                                       tty_flip_buffer_push(&port->port);
+                               tty_flip_buffer_push(&port->port);
 
                                newport = *(ch + 3);
 
@@ -709,8 +703,7 @@ void qt2_process_read_urb(struct urb *urb)
                tty_insert_flip_string(&port->port, ch, 1);
        }
 
-       if (port_priv->is_open)
-               tty_flip_buffer_push(&port->port);
+       tty_flip_buffer_push(&port->port);
 }
 
 static void qt2_write_bulk_callback(struct urb *urb)
@@ -910,12 +903,6 @@ static void qt2_break_ctl(struct tty_struct *tty, int break_state)
 
        port_priv = usb_get_serial_port_data(port);
 
-       if (!port_priv->is_open) {
-               dev_err(&port->dev,
-                       "%s - port is not open\n", __func__);
-               return;
-       }
-
        val = (break_state == -1) ? 1 : 0;
 
        status = qt2_control_msg(port->serial->dev, QT2_BREAK_CONTROL,
index c13f6e747748b31d16c0d087fa4f8b1953826285..d66148a17fe36548e019c0b8b7b60aa563548a1a 100644 (file)
@@ -628,7 +628,6 @@ static void sierra_instat_callback(struct urb *urb)
                        unsigned char signals = *((unsigned char *)
                                        urb->transfer_buffer +
                                        sizeof(struct usb_ctrlrequest));
-                       struct tty_struct *tty;
 
                        dev_dbg(&port->dev, "%s: signal x%x\n", __func__,
                                signals);
@@ -639,11 +638,8 @@ static void sierra_instat_callback(struct urb *urb)
                        portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
                        portdata->ri_state = ((signals & 0x08) ? 1 : 0);
 
-                       tty = tty_port_tty_get(&port->port);
-                       if (tty && !C_CLOCAL(tty) &&
-                                       old_dcd_state && !portdata->dcd_state)
-                               tty_hangup(tty);
-                       tty_kref_put(tty);
+                       if (old_dcd_state && !portdata->dcd_state)
+                               tty_port_tty_hangup(&port->port, true);
                } else {
                        dev_dbg(&port->dev, "%s: type %x req %x\n",
                                __func__, req_pkt->bRequestType,
index 73deb029fc05d3d9c9b728f1fae1616a8efee6e4..19a71a9eecf09130d196dc8131e00733c9e09f4e 100644 (file)
@@ -1229,7 +1229,6 @@ static void ti_send(struct ti_port *tport)
 {
        int count, result;
        struct usb_serial_port *port = tport->tp_port;
-       struct tty_struct *tty = tty_port_tty_get(&port->port); /* FIXME */
        unsigned long flags;
 
        spin_lock_irqsave(&tport->tp_lock, flags);
@@ -1270,14 +1269,12 @@ static void ti_send(struct ti_port *tport)
        }
 
        /* more room in the buffer for new writes, wakeup */
-       if (tty)
-               tty_wakeup(tty);
-       tty_kref_put(tty);
+       tty_port_tty_wakeup(&port->port);
+
        wake_up_interruptible(&tport->tp_write_wait);
        return;
 unlock:
        spin_unlock_irqrestore(&tport->tp_lock, flags);
-       tty_kref_put(tty);
        return;
 }
 
index 5d9b178484fdf805bfd9a6e264732d5082216088..650be17a68f20993b4cf24489eafed109afa08a7 100644 (file)
@@ -542,16 +542,8 @@ static void usb_serial_port_work(struct work_struct *work)
 {
        struct usb_serial_port *port =
                container_of(work, struct usb_serial_port, work);
-       struct tty_struct *tty;
 
-       tty = tty_port_tty_get(&port->port);
-       if (!tty)
-               return;
-
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
-
-       tty_wakeup(tty);
-       tty_kref_put(tty);
+       tty_port_tty_wakeup(&port->port);
 }
 
 static void kill_traffic(struct usb_serial_port *port)
index f612c783170f58d2d7913d55c8d804d4c60c568b..62d9303c283789baacfdc3e745d11bb2110431fe 100644 (file)
@@ -203,6 +203,9 @@ struct amba_pl011_data {
        bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
        void *dma_rx_param;
        void *dma_tx_param;
+       bool dma_rx_poll_enable;
+       unsigned int dma_rx_poll_rate;
+       unsigned int dma_rx_poll_timeout;
         void (*init) (void);
        void (*exit) (void);
 };
diff --git a/include/linux/serial_s3c.h b/include/linux/serial_s3c.h
new file mode 100644 (file)
index 0000000..907d9d1
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ *  Internal header file for Samsung S3C2410 serial ports (UART0-2)
+ *
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *
+ *  Additional defines, Copyright 2003 Simtec Electronics (linux@simtec.co.uk)
+ *
+ *  Adapted from:
+ *
+ *  Internal header file for MX1ADS serial ports (UART1 & 2)
+ *
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef __ASM_ARM_REGS_SERIAL_H
+#define __ASM_ARM_REGS_SERIAL_H
+
+#define S3C2410_URXH     (0x24)
+#define S3C2410_UTXH     (0x20)
+#define S3C2410_ULCON    (0x00)
+#define S3C2410_UCON     (0x04)
+#define S3C2410_UFCON    (0x08)
+#define S3C2410_UMCON    (0x0C)
+#define S3C2410_UBRDIV   (0x28)
+#define S3C2410_UTRSTAT          (0x10)
+#define S3C2410_UERSTAT          (0x14)
+#define S3C2410_UFSTAT   (0x18)
+#define S3C2410_UMSTAT   (0x1C)
+
+#define S3C2410_LCON_CFGMASK     ((0xF<<3)|(0x3))
+
+#define S3C2410_LCON_CS5         (0x0)
+#define S3C2410_LCON_CS6         (0x1)
+#define S3C2410_LCON_CS7         (0x2)
+#define S3C2410_LCON_CS8         (0x3)
+#define S3C2410_LCON_CSMASK      (0x3)
+
+#define S3C2410_LCON_PNONE       (0x0)
+#define S3C2410_LCON_PEVEN       (0x5 << 3)
+#define S3C2410_LCON_PODD        (0x4 << 3)
+#define S3C2410_LCON_PMASK       (0x7 << 3)
+
+#define S3C2410_LCON_STOPB       (1<<2)
+#define S3C2410_LCON_IRM          (1<<6)
+
+#define S3C2440_UCON_CLKMASK     (3<<10)
+#define S3C2440_UCON_CLKSHIFT    (10)
+#define S3C2440_UCON_PCLK        (0<<10)
+#define S3C2440_UCON_UCLK        (1<<10)
+#define S3C2440_UCON_PCLK2       (2<<10)
+#define S3C2440_UCON_FCLK        (3<<10)
+#define S3C2443_UCON_EPLL        (3<<10)
+
+#define S3C6400_UCON_CLKMASK   (3<<10)
+#define S3C6400_UCON_CLKSHIFT  (10)
+#define S3C6400_UCON_PCLK      (0<<10)
+#define S3C6400_UCON_PCLK2     (2<<10)
+#define S3C6400_UCON_UCLK0     (1<<10)
+#define S3C6400_UCON_UCLK1     (3<<10)
+
+#define S3C2440_UCON2_FCLK_EN    (1<<15)
+#define S3C2440_UCON0_DIVMASK    (15 << 12)
+#define S3C2440_UCON1_DIVMASK    (15 << 12)
+#define S3C2440_UCON2_DIVMASK    (7 << 12)
+#define S3C2440_UCON_DIVSHIFT    (12)
+
+#define S3C2412_UCON_CLKMASK   (3<<10)
+#define S3C2412_UCON_CLKSHIFT  (10)
+#define S3C2412_UCON_UCLK      (1<<10)
+#define S3C2412_UCON_USYSCLK   (3<<10)
+#define S3C2412_UCON_PCLK      (0<<10)
+#define S3C2412_UCON_PCLK2     (2<<10)
+
+#define S3C2410_UCON_CLKMASK   (1 << 10)
+#define S3C2410_UCON_CLKSHIFT  (10)
+#define S3C2410_UCON_UCLK        (1<<10)
+#define S3C2410_UCON_SBREAK      (1<<4)
+
+#define S3C2410_UCON_TXILEVEL    (1<<9)
+#define S3C2410_UCON_RXILEVEL    (1<<8)
+#define S3C2410_UCON_TXIRQMODE   (1<<2)
+#define S3C2410_UCON_RXIRQMODE   (1<<0)
+#define S3C2410_UCON_RXFIFO_TOI          (1<<7)
+#define S3C2443_UCON_RXERR_IRQEN  (1<<6)
+#define S3C2443_UCON_LOOPBACK    (1<<5)
+
+#define S3C2410_UCON_DEFAULT     (S3C2410_UCON_TXILEVEL  | \
+                                  S3C2410_UCON_RXILEVEL  | \
+                                  S3C2410_UCON_TXIRQMODE | \
+                                  S3C2410_UCON_RXIRQMODE | \
+                                  S3C2410_UCON_RXFIFO_TOI)
+
+#define S3C2410_UFCON_FIFOMODE   (1<<0)
+#define S3C2410_UFCON_TXTRIG0    (0<<6)
+#define S3C2410_UFCON_RXTRIG8    (1<<4)
+#define S3C2410_UFCON_RXTRIG12   (2<<4)
+
+/* S3C2440 FIFO trigger levels */
+#define S3C2440_UFCON_RXTRIG1    (0<<4)
+#define S3C2440_UFCON_RXTRIG8    (1<<4)
+#define S3C2440_UFCON_RXTRIG16   (2<<4)
+#define S3C2440_UFCON_RXTRIG32   (3<<4)
+
+#define S3C2440_UFCON_TXTRIG0    (0<<6)
+#define S3C2440_UFCON_TXTRIG16   (1<<6)
+#define S3C2440_UFCON_TXTRIG32   (2<<6)
+#define S3C2440_UFCON_TXTRIG48   (3<<6)
+
+#define S3C2410_UFCON_RESETBOTH          (3<<1)
+#define S3C2410_UFCON_RESETTX    (1<<2)
+#define S3C2410_UFCON_RESETRX    (1<<1)
+
+#define S3C2410_UFCON_DEFAULT    (S3C2410_UFCON_FIFOMODE | \
+                                  S3C2410_UFCON_TXTRIG0  | \
+                                  S3C2410_UFCON_RXTRIG8 )
+
+#define        S3C2410_UMCOM_AFC         (1<<4)
+#define        S3C2410_UMCOM_RTS_LOW     (1<<0)
+
+#define S3C2412_UMCON_AFC_63   (0<<5)          /* same as s3c2443 */
+#define S3C2412_UMCON_AFC_56   (1<<5)
+#define S3C2412_UMCON_AFC_48   (2<<5)
+#define S3C2412_UMCON_AFC_40   (3<<5)
+#define S3C2412_UMCON_AFC_32   (4<<5)
+#define S3C2412_UMCON_AFC_24   (5<<5)
+#define S3C2412_UMCON_AFC_16   (6<<5)
+#define S3C2412_UMCON_AFC_8    (7<<5)
+
+#define S3C2410_UFSTAT_TXFULL    (1<<9)
+#define S3C2410_UFSTAT_RXFULL    (1<<8)
+#define S3C2410_UFSTAT_TXMASK    (15<<4)
+#define S3C2410_UFSTAT_TXSHIFT   (4)
+#define S3C2410_UFSTAT_RXMASK    (15<<0)
+#define S3C2410_UFSTAT_RXSHIFT   (0)
+
+/* UFSTAT S3C2443 same as S3C2440 */
+#define S3C2440_UFSTAT_TXFULL    (1<<14)
+#define S3C2440_UFSTAT_RXFULL    (1<<6)
+#define S3C2440_UFSTAT_TXSHIFT   (8)
+#define S3C2440_UFSTAT_RXSHIFT   (0)
+#define S3C2440_UFSTAT_TXMASK    (63<<8)
+#define S3C2440_UFSTAT_RXMASK    (63)
+
+#define S3C2410_UTRSTAT_TXE      (1<<2)
+#define S3C2410_UTRSTAT_TXFE     (1<<1)
+#define S3C2410_UTRSTAT_RXDR     (1<<0)
+
+#define S3C2410_UERSTAT_OVERRUN          (1<<0)
+#define S3C2410_UERSTAT_FRAME    (1<<2)
+#define S3C2410_UERSTAT_BREAK    (1<<3)
+#define S3C2443_UERSTAT_PARITY   (1<<1)
+
+#define S3C2410_UERSTAT_ANY      (S3C2410_UERSTAT_OVERRUN | \
+                                  S3C2410_UERSTAT_FRAME | \
+                                  S3C2410_UERSTAT_BREAK)
+
+#define S3C2410_UMSTAT_CTS       (1<<0)
+#define S3C2410_UMSTAT_DeltaCTS          (1<<2)
+
+#define S3C2443_DIVSLOT                  (0x2C)
+
+/* S3C64XX interrupt registers. */
+#define S3C64XX_UINTP          0x30
+#define S3C64XX_UINTSP         0x34
+#define S3C64XX_UINTM          0x38
+
+#define S3C64XX_UINTM_RXD      (0)
+#define S3C64XX_UINTM_TXD      (2)
+#define S3C64XX_UINTM_RXD_MSK  (1 << S3C64XX_UINTM_RXD)
+#define S3C64XX_UINTM_TXD_MSK  (1 << S3C64XX_UINTM_TXD)
+
+/* Following are specific to S5PV210 */
+#define S5PV210_UCON_CLKMASK   (1<<10)
+#define S5PV210_UCON_CLKSHIFT  (10)
+#define S5PV210_UCON_PCLK      (0<<10)
+#define S5PV210_UCON_UCLK      (1<<10)
+
+#define S5PV210_UFCON_TXTRIG0  (0<<8)
+#define S5PV210_UFCON_TXTRIG4  (1<<8)
+#define S5PV210_UFCON_TXTRIG8  (2<<8)
+#define S5PV210_UFCON_TXTRIG16 (3<<8)
+#define S5PV210_UFCON_TXTRIG32 (4<<8)
+#define S5PV210_UFCON_TXTRIG64 (5<<8)
+#define S5PV210_UFCON_TXTRIG128 (6<<8)
+#define S5PV210_UFCON_TXTRIG256 (7<<8)
+
+#define S5PV210_UFCON_RXTRIG1  (0<<4)
+#define S5PV210_UFCON_RXTRIG4  (1<<4)
+#define S5PV210_UFCON_RXTRIG8  (2<<4)
+#define S5PV210_UFCON_RXTRIG16 (3<<4)
+#define S5PV210_UFCON_RXTRIG32 (4<<4)
+#define S5PV210_UFCON_RXTRIG64 (5<<4)
+#define S5PV210_UFCON_RXTRIG128        (6<<4)
+#define S5PV210_UFCON_RXTRIG256        (7<<4)
+
+#define S5PV210_UFSTAT_TXFULL  (1<<24)
+#define S5PV210_UFSTAT_RXFULL  (1<<8)
+#define S5PV210_UFSTAT_TXMASK  (255<<16)
+#define S5PV210_UFSTAT_TXSHIFT (16)
+#define S5PV210_UFSTAT_RXMASK  (255<<0)
+#define S5PV210_UFSTAT_RXSHIFT (0)
+
+#define S3C2410_UCON_CLKSEL0   (1 << 0)
+#define S3C2410_UCON_CLKSEL1   (1 << 1)
+#define S3C2410_UCON_CLKSEL2   (1 << 2)
+#define S3C2410_UCON_CLKSEL3   (1 << 3)
+
+/* Default values for s5pv210 UCON and UFCON uart registers */
+#define S5PV210_UCON_DEFAULT   (S3C2410_UCON_TXILEVEL |        \
+                                S3C2410_UCON_RXILEVEL |        \
+                                S3C2410_UCON_TXIRQMODE |       \
+                                S3C2410_UCON_RXIRQMODE |       \
+                                S3C2410_UCON_RXFIFO_TOI |      \
+                                S3C2443_UCON_RXERR_IRQEN)
+
+#define S5PV210_UFCON_DEFAULT  (S3C2410_UFCON_FIFOMODE |       \
+                                S5PV210_UFCON_TXTRIG4 |        \
+                                S5PV210_UFCON_RXTRIG4)
+
+#ifndef __ASSEMBLY__
+
+/* configuration structure for per-machine configurations for the
+ * serial port
+ *
+ * the pointer is setup by the machine specific initialisation from the
+ * arch/arm/mach-s3c2410/ directory.
+*/
+
+struct s3c2410_uartcfg {
+       unsigned char      hwport;       /* hardware port number */
+       unsigned char      unused;
+       unsigned short     flags;
+       upf_t              uart_flags;   /* default uart flags */
+       unsigned int       clk_sel;
+
+       unsigned int       has_fracval;
+
+       unsigned long      ucon;         /* value of ucon for port */
+       unsigned long      ulcon;        /* value of ulcon for port */
+       unsigned long      ufcon;        /* value of ufcon for port */
+};
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_ARM_REGS_SERIAL_H */
+
index c75d886b03078dce545a10ea83ac654e0a4335c4..367a9dfc4ea2464c35ffe8c773c5cb8f04e3df86 100644 (file)
@@ -255,9 +255,9 @@ struct tty_struct {
        int count;
        struct winsize winsize;         /* termios mutex */
        unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1;
-       unsigned char warned:1;
        unsigned char ctrl_status;      /* ctrl_lock */
        unsigned int receive_room;      /* Bytes free for queue */
+       int flow_change;
 
        struct tty_struct *link;
        struct fasync_struct *fasync;
@@ -315,9 +315,25 @@ struct tty_file_private {
 #define TTY_NO_WRITE_SPLIT     17      /* Preserve write boundaries to driver */
 #define TTY_HUPPED             18      /* Post driver->hangup() */
 #define TTY_HUPPING            21      /* ->hangup() in progress */
+#define TTY_LDISC_HALTED       22      /* Line discipline is halted */
 
 #define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
 
+/* Values for tty->flow_change */
+#define TTY_THROTTLE_SAFE 1
+#define TTY_UNTHROTTLE_SAFE 2
+
+static inline void __tty_set_flow_change(struct tty_struct *tty, int val)
+{
+       tty->flow_change = val;
+}
+
+static inline void tty_set_flow_change(struct tty_struct *tty, int val)
+{
+       tty->flow_change = val;
+       smp_mb();
+}
+
 #ifdef CONFIG_TTY
 extern void console_init(void);
 extern void tty_kref_put(struct tty_struct *tty);
@@ -400,6 +416,8 @@ extern int tty_write_room(struct tty_struct *tty);
 extern void tty_driver_flush_buffer(struct tty_struct *tty);
 extern void tty_throttle(struct tty_struct *tty);
 extern void tty_unthrottle(struct tty_struct *tty);
+extern int tty_throttle_safe(struct tty_struct *tty);
+extern int tty_unthrottle_safe(struct tty_struct *tty);
 extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws);
 extern void tty_driver_remove_tty(struct tty_driver *driver,
                                  struct tty_struct *tty);
@@ -419,13 +437,28 @@ extern void tty_flush_to_ldisc(struct tty_struct *tty);
 extern void tty_buffer_free_all(struct tty_port *port);
 extern void tty_buffer_flush(struct tty_struct *tty);
 extern void tty_buffer_init(struct tty_port *port);
-extern speed_t tty_get_baud_rate(struct tty_struct *tty);
 extern speed_t tty_termios_baud_rate(struct ktermios *termios);
 extern speed_t tty_termios_input_baud_rate(struct ktermios *termios);
 extern void tty_termios_encode_baud_rate(struct ktermios *termios,
                                                speed_t ibaud, speed_t obaud);
 extern void tty_encode_baud_rate(struct tty_struct *tty,
                                                speed_t ibaud, speed_t obaud);
+
+/**
+ *     tty_get_baud_rate       -       get tty bit rates
+ *     @tty: tty to query
+ *
+ *     Returns the baud rate as an integer for this terminal. The
+ *     termios lock must be held by the caller and the terminal bit
+ *     flags may be updated.
+ *
+ *     Locking: none
+ */
+static inline speed_t tty_get_baud_rate(struct tty_struct *tty)
+{
+       return tty_termios_baud_rate(&tty->termios);
+}
+
 extern void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old);
 extern int tty_termios_hw_change(struct ktermios *a, struct ktermios *b);
 extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt);
@@ -502,6 +535,8 @@ extern int tty_port_carrier_raised(struct tty_port *port);
 extern void tty_port_raise_dtr_rts(struct tty_port *port);
 extern void tty_port_lower_dtr_rts(struct tty_port *port);
 extern void tty_port_hangup(struct tty_port *port);
+extern void tty_port_tty_hangup(struct tty_port *port, bool check_clocal);
+extern void tty_port_tty_wakeup(struct tty_port *port);
 extern int tty_port_block_til_ready(struct tty_port *port,
                                struct tty_struct *tty, struct file *filp);
 extern int tty_port_close_start(struct tty_port *port,
@@ -526,8 +561,6 @@ extern void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty);
 extern void tty_ldisc_init(struct tty_struct *tty);
 extern void tty_ldisc_deinit(struct tty_struct *tty);
 extern void tty_ldisc_begin(void);
-/* This last one is just for the tty layer internals and shouldn't be used elsewhere */
-extern void tty_ldisc_enable(struct tty_struct *tty);
 
 
 /* n_tty.c */
index 455a0d7bf2209665adc5c09bb8f4c2803edc3f49..58390c73df8b69ae146ce466af4e24ccadce2cdf 100644 (file)
@@ -9,89 +9,89 @@
  *
  * int (*open)(struct tty_struct *);
  *
- *     This function is called when the line discipline is associated
- *     with the tty.  The line discipline can use this as an
- *     opportunity to initialize any state needed by the ldisc routines.
- * 
+ *     This function is called when the line discipline is associated
+ *     with the tty.  The line discipline can use this as an
+ *     opportunity to initialize any state needed by the ldisc routines.
+ *
  * void        (*close)(struct tty_struct *);
  *
  *     This function is called when the line discipline is being
- *     shutdown, either because the tty is being closed or because
- *     the tty is being changed to use a new line discipline
- * 
+ *     shutdown, either because the tty is being closed or because
+ *     the tty is being changed to use a new line discipline
+ *
  * void        (*flush_buffer)(struct tty_struct *tty);
  *
- *     This function instructs the line discipline to clear its
- *     buffers of any input characters it may have queued to be
- *     delivered to the user mode process.
- * 
+ *     This function instructs the line discipline to clear its
+ *     buffers of any input characters it may have queued to be
+ *     delivered to the user mode process.
+ *
  * ssize_t (*chars_in_buffer)(struct tty_struct *tty);
  *
- *     This function returns the number of input characters the line
+ *     This function returns the number of input characters the line
  *     discipline may have queued up to be delivered to the user mode
  *     process.
- * 
+ *
  * ssize_t (*read)(struct tty_struct * tty, struct file * file,
  *                unsigned char * buf, size_t nr);
  *
- *     This function is called when the user requests to read from
- *     the tty.  The line discipline will return whatever characters
- *     it has buffered up for the user.  If this function is not
- *     defined, the user will receive an EIO error.
- * 
+ *     This function is called when the user requests to read from
+ *     the tty.  The line discipline will return whatever characters
+ *     it has buffered up for the user.  If this function is not
+ *     defined, the user will receive an EIO error.
+ *
  * ssize_t (*write)(struct tty_struct * tty, struct file * file,
- *                 const unsigned char * buf, size_t nr);
- *
- *     This function is called when the user requests to write to the
- *     tty.  The line discipline will deliver the characters to the
- *     low-level tty device for transmission, optionally performing
- *     some processing on the characters first.  If this function is
- *     not defined, the user will receive an EIO error.
- * 
+ *                 const unsigned char * buf, size_t nr);
+ *
+ *     This function is called when the user requests to write to the
+ *     tty.  The line discipline will deliver the characters to the
+ *     low-level tty device for transmission, optionally performing
+ *     some processing on the characters first.  If this function is
+ *     not defined, the user will receive an EIO error.
+ *
  * int (*ioctl)(struct tty_struct * tty, struct file * file,
- *              unsigned int cmd, unsigned long arg);
+ *              unsigned int cmd, unsigned long arg);
  *
  *     This function is called when the user requests an ioctl which
- *     is not handled by the tty layer or the low-level tty driver.
- *     It is intended for ioctls which affect line discpline
- *     operation.  Note that the search order for ioctls is (1) tty
- *     layer, (2) tty low-level driver, (3) line discpline.  So a
- *     low-level driver can "grab" an ioctl request before the line
- *     discpline has a chance to see it.
- * 
+ *     is not handled by the tty layer or the low-level tty driver.
+ *     It is intended for ioctls which affect line discpline
+ *     operation.  Note that the search order for ioctls is (1) tty
+ *     layer, (2) tty low-level driver, (3) line discpline.  So a
+ *     low-level driver can "grab" an ioctl request before the line
+ *     discpline has a chance to see it.
+ *
  * long        (*compat_ioctl)(struct tty_struct * tty, struct file * file,
- *                     unsigned int cmd, unsigned long arg);
+ *                     unsigned int cmd, unsigned long arg);
  *
- *      Process ioctl calls from 32-bit process on 64-bit system
+ *     Process ioctl calls from 32-bit process on 64-bit system
  *
  * void        (*set_termios)(struct tty_struct *tty, struct ktermios * old);
  *
- *     This function notifies the line discpline that a change has
- *     been made to the termios structure.
- * 
+ *     This function notifies the line discpline that a change has
+ *     been made to the termios structure.
+ *
  * int (*poll)(struct tty_struct * tty, struct file * file,
- *               poll_table *wait);
+ *               poll_table *wait);
  *
- *     This function is called when a user attempts to select/poll on a
- *     tty device.  It is solely the responsibility of the line
- *     discipline to handle poll requests.
+ *     This function is called when a user attempts to select/poll on a
+ *     tty device.  It is solely the responsibility of the line
+ *     discipline to handle poll requests.
  *
  * void        (*receive_buf)(struct tty_struct *, const unsigned char *cp,
- *                    char *fp, int count);
- *
- *     This function is called by the low-level tty driver to send
- *     characters received by the hardware to the line discpline for
- *     processing.  <cp> is a pointer to the buffer of input
- *     character received by the device.  <fp> is a pointer to a
- *     pointer of flag bytes which indicate whether a character was
- *     received with a parity error, etc.
- * 
+ *                    char *fp, int count);
+ *
+ *     This function is called by the low-level tty driver to send
+ *     characters received by the hardware to the line discpline for
+ *     processing.  <cp> is a pointer to the buffer of input
+ *     character received by the device.  <fp> is a pointer to a
+ *     pointer of flag bytes which indicate whether a character was
+ *     received with a parity error, etc.
+ *
  * void        (*write_wakeup)(struct tty_struct *);
  *
- *     This function is called by the low-level tty driver to signal
- *     that line discpline should try to send more characters to the
- *     low-level driver for transmission.  If the line discpline does
- *     not have any more data to send, it can just return.
+ *     This function is called by the low-level tty driver to signal
+ *     that line discpline should try to send more characters to the
+ *     low-level driver for transmission.  If the line discpline does
+ *     not have any more data to send, it can just return.
  *
  * int (*hangup)(struct tty_struct *)
  *
@@ -115,7 +115,7 @@ struct tty_ldisc_ops {
        char    *name;
        int     num;
        int     flags;
-       
+
        /*
         * The following routines are called from above.
         */
@@ -123,19 +123,19 @@ struct tty_ldisc_ops {
        void    (*close)(struct tty_struct *);
        void    (*flush_buffer)(struct tty_struct *tty);
        ssize_t (*chars_in_buffer)(struct tty_struct *tty);
-       ssize_t (*read)(struct tty_struct * tty, struct file * file,
-                       unsigned char __user * buf, size_t nr);
-       ssize_t (*write)(struct tty_struct * tty, struct file * file,
-                        const unsigned char * buf, size_t nr); 
-       int     (*ioctl)(struct tty_struct * tty, struct file * file,
+       ssize_t (*read)(struct tty_struct *tty, struct file *file,
+                       unsigned char __user *buf, size_t nr);
+       ssize_t (*write)(struct tty_struct *tty, struct file *file,
+                        const unsigned char *buf, size_t nr);
+       int     (*ioctl)(struct tty_struct *tty, struct file *file,
                         unsigned int cmd, unsigned long arg);
-       long    (*compat_ioctl)(struct tty_struct * tty, struct file * file,
+       long    (*compat_ioctl)(struct tty_struct *tty, struct file *file,
                                unsigned int cmd, unsigned long arg);
-       void    (*set_termios)(struct tty_struct *tty, struct ktermios * old);
+       void    (*set_termios)(struct tty_struct *tty, struct ktermios *old);
        unsigned int (*poll)(struct tty_struct *, struct file *,
                             struct poll_table_struct *);
        int     (*hangup)(struct tty_struct *tty);
-       
+
        /*
         * The following routines are called from below.
         */
@@ -145,7 +145,7 @@ struct tty_ldisc_ops {
        void    (*dcd_change)(struct tty_struct *, unsigned int);
 
        struct  module *owner;
-       
+
        int refcount;
 };
 
index 362ba47968e41de822122f9c215e012ba566cd59..41ac7938268be6ca07401bf0e9596c9e604444be 100644 (file)
@@ -328,7 +328,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
        spin_unlock_irqrestore(&port->lock, flags);
 
        while (1) {
-               if (tty->termios.c_cflag & CBAUD)
+               if (C_BAUD(tty) && test_bit(ASYNCB_INITIALIZED, &port->flags))
                        tty_port_raise_dtr_rts(port);
 
                set_current_state(TASK_INTERRUPTIBLE);
index edab393e0c82ec96bfd66dd662a888963761bab0..a2a508f5f2684e81ea69697e3e84ff69f2fe74da 100644 (file)
@@ -997,12 +997,8 @@ static int ircomm_tty_state_ready(struct ircomm_tty_cb *self,
                        self->settings.dce = IRCOMM_DELTA_CD;
                        ircomm_tty_check_modem_status(self);
                } else {
-                       struct tty_struct *tty = tty_port_tty_get(&self->port);
                        IRDA_DEBUG(0, "%s(), hanging up!\n", __func__ );
-                       if (tty) {
-                               tty_hangup(tty);
-                               tty_kref_put(tty);
-                       }
+                       tty_port_tty_hangup(&self->port, false);
                }
                break;
        default: