TTY/Serial driver update for 3.10-rc1

Here's the big tty/serial driver merge request for 3.10-rc1
 
 Once again, Jiri has a number of TTY driver fixes and cleanups, and
 Peter Hurley came through with a bunch of ldisc fixes that resolve a
 number of reported issues.  There are some other serial driver cleanups
 as well.
 
 All of these have been in the linux-next tree for a while.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.19 (GNU/Linux)
 
 iEYEABECAAYFAlF+nSMACgkQMUfUDdst+ymy9QCfRmYn0MC0W+Q1D3Spz87gVsuo
 cqEAniu1BEkYZpjAz7ZlIN07Ao0jbQOR
 =Osu/
 -----END PGP SIGNATURE-----

Merge tag 'tty-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty/serial driver update from Greg Kroah-Hartman:
 "Here's the big tty/serial driver merge request for 3.10-rc1

  Once again, Jiri has a number of TTY driver fixes and cleanups, and
  Peter Hurley came through with a bunch of ldisc fixes that resolve a
  number of reported issues.  There are some other serial driver
  cleanups as well.

  All of these have been in the linux-next tree for a while"

* tag 'tty-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (117 commits)
  tty/serial/sirf: fix MODULE_DEVICE_TABLE
  serial: mxs: drop superfluous {get|put}_device
  serial: mxs: fix buffer overflow
  ARM: PL011: add support for extended FIFO-size of PL011-r1p5
  serial_core.c: add put_device() after device_find_child()
  tty: Fix unsafe bit ops in tty_throttle_safe/unthrottle_safe
  serial: sccnxp: Replace pdata.init/exit with regulator API
  serial: sccnxp: Do not override device name
  TTY: pty, fix compilation warning
  TTY: rocket, fix compilation warning
  TTY: ircomm: fix DTR being raised on hang up
  TTY: synclinkmp: fix DTR being raised on hang up
  TTY: synclink_gt: fix DTR being raised on hang up
  TTY: synclink: fix DTR being raised on hang up
  serial: 8250_dw: Fix the stub for dw8250_probe_acpi()
  serial: 8250_dw: Convert to devm_ioremap()
  serial: 8250_dw: Set port capabilities based on CPR register
  serial: 8250_dw: Let ACPI code extract the DMA client info
  serial: 8250_dw: Support clk framework also with ACPI
  serial: 8250_dw: Enable runtime PM
  ...
This commit is contained in:
Linus Torvalds 2013-04-29 12:16:17 -07:00
commit 507ffe4f38
92 changed files with 1678 additions and 1619 deletions

View 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:

View 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;

View 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, \

View 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>

View 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,
};

View 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);
}

View 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;
}

View 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 {

View 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 ***/

View 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;
}
}

View 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) {

View 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)
{

View 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:

View 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:

View 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);

View 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

View 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

View 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)

View 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)

View 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)

View 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:

View 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;
}

View 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:

View File

@ -1732,7 +1732,6 @@ 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]);
for (i = 0; i < NL_NUM_OF_PRIORITIES; i++)

View 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);

View 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);

View 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:

View 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,29 +218,11 @@ 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);
}
/**
* 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).
*
* Locking: ctrl_lock, read_lock.
*/
static void n_tty_flush_buffer(struct tty_struct *tty)
static void n_tty_packet_mode_flush(struct tty_struct *tty)
{
unsigned long flags;
/* clear everything and unthrottle the driver */
reset_buffer_flags(tty);
if (!tty->link)
return;
spin_lock_irqsave(&tty->ctrl_lock, flags);
if (tty->link->packet) {
@ -261,6 +232,26 @@ static void n_tty_flush_buffer(struct tty_struct *tty)
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
}
/**
* n_tty_flush_buffer - clean input queue
* @tty: terminal device
*
* 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)
{
reset_buffer_flags(tty->disc_data);
n_tty_set_room(tty);
if (tty->link)
n_tty_packet_mode_flush(tty);
}
/**
* n_tty_chars_in_buffer - report available bytes
* @tty: tty device
@ -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 (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) {
if (is_ignored(SIGTTIN) ||
is_current_pgrp_orphaned())
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;

View 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)

View File

@ -405,15 +405,8 @@ err:
return retval;
}
/* this is called once with whichever end is closed last */
static void pty_unix98_shutdown(struct tty_struct *tty)
{
devpts_kill_index(tty->driver_data, tty->index);
}
static void pty_cleanup(struct tty_struct *tty)
{
tty->port->itty = NULL;
tty_port_put(tty->port);
}
@ -627,6 +620,12 @@ static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
{
}
/* this is called once with whichever end is closed last */
static void pty_unix98_shutdown(struct tty_struct *tty)
{
devpts_kill_index(tty->driver_data, tty->index);
}
static const struct tty_operations ptm_unix98_ops = {
.lookup = ptm_unix98_lookup,
.install = pty_unix98_install,

View 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,16 +1106,13 @@ 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);
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:
@ -2527,6 +2519,7 @@ static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
return (CtlP->NumAiop);
}
#ifdef CONFIG_PCI
/***************************************************************************
Function: sPCIInitController
Purpose: Initialization of controller global registers and controller
@ -2647,6 +2640,26 @@ static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
return (CtlP->NumAiop);
}
/* Resets the speaker controller on RocketModem II and III devices */
static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model)
{
ByteIO_t addr;
/* RocketModem II speaker control is at the 8th port location of offset 0x40 */
if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) {
addr = CtlP->AiopIO[0] + 0x4F;
sOutB(addr, 0);
}
/* RocketModem III speaker control is at the 1st port location of offset 0x80 */
if ((model == MODEL_UPCI_RM3_8PORT)
|| (model == MODEL_UPCI_RM3_4PORT)) {
addr = CtlP->AiopIO[0] + 0x88;
sOutB(addr, 0);
}
}
#endif
/***************************************************************************
Function: sReadAiopID
Purpose: Read the AIOP idenfication number directly from an AIOP.
@ -3136,25 +3149,6 @@ static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on)
sOutB(addr + chan, 0); /* apply or remove reset */
}
/* Resets the speaker controller on RocketModem II and III devices */
static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model)
{
ByteIO_t addr;
/* RocketModem II speaker control is at the 8th port location of offset 0x40 */
if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) {
addr = CtlP->AiopIO[0] + 0x4F;
sOutB(addr, 0);
}
/* RocketModem III speaker control is at the 1st port location of offset 0x80 */
if ((model == MODEL_UPCI_RM3_8PORT)
|| (model == MODEL_UPCI_RM3_4PORT)) {
addr = CtlP->AiopIO[0] + 0x88;
sOutB(addr, 0);
}
}
/* Returns the line number given the controller (board), aiop and channel number */
static unsigned char GetLineNumber(int ctrl, int aiop, int ch)
{

View 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);
}
}

View 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

View 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;

View 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;
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.c copy the remaining data.
* If RCVR FIFO trigger level was not reached, complete the
* transfer and let 8250_core copy the remaining data.
*/
if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT) {
dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie,
&state);
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;
/* 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;

View 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)
@ -57,6 +56,7 @@
struct dw8250_data {
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;
if (!p->uartclk)
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;
}
up->dma = devm_kzalloc(p->dev, sizeof(*up->dma), GFP_KERNEL);
if (!up->dma)
return -ENOMEM;
/* 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->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);

View 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
@ -72,32 +73,44 @@
/* There is by now at least one vendor with differing details, so handle it */
struct vendor_data {
unsigned int ifls;
unsigned int fifosize;
unsigned int lcrh_tx;
unsigned int lcrh_rx;
bool oversampling;
bool dma_threshold;
bool cts_event_workaround;
unsigned int (*get_fifosize)(unsigned int periphid);
};
static unsigned int get_fifosize_arm(unsigned int periphid)
{
unsigned int rev = (periphid >> 20) & 0xf;
return rev < 3 ? 16 : 32;
}
static struct vendor_data vendor_arm = {
.ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
.fifosize = 16,
.lcrh_tx = UART011_LCRH,
.lcrh_rx = UART011_LCRH,
.oversampling = false,
.dma_threshold = false,
.cts_event_workaround = false,
.get_fifosize = get_fifosize_arm,
};
static unsigned int get_fifosize_st(unsigned int periphid)
{
return 64;
}
static struct vendor_data vendor_st = {
.ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
.fifosize = 64,
.lcrh_tx = ST_UART011_LCRH_TX,
.lcrh_rx = ST_UART011_LCRH_RX,
.oversampling = true,
.dma_threshold = true,
.cts_event_workaround = true,
.get_fifosize = get_fifosize_st,
};
static struct uart_amba_port *amba_ports[UART_NR];
@ -117,6 +130,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 +242,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 +261,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 +322,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 +746,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 +777,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 +920,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 +1033,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 +1078,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 +1094,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 +1205,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 +1293,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 +1679,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);
@ -2010,7 +2145,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
uap->lcrh_rx = vendor->lcrh_rx;
uap->lcrh_tx = vendor->lcrh_tx;
uap->old_cr = 0;
uap->fifosize = vendor->fifosize;
uap->fifosize = vendor->get_fifosize(dev->periphid);
uap->port.dev = &dev->dev;
uap->port.mapbase = dev->res.start;
uap->port.membase = base;

View 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
*/

View 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,

View 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;

View 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 */

View 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;

View 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
};

View 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;

View 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);

View 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);

View 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)

View 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);

View 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)

View File

@ -883,7 +883,7 @@ auart_console_write(struct console *co, const char *str, unsigned int count)
unsigned int old_ctrl0, old_ctrl2;
unsigned int to = 1000;
if (co->index > MXS_AUART_PORTS || co->index < 0)
if (co->index >= MXS_AUART_PORTS || co->index < 0)
return;
s = auart_port[co->index];
@ -1103,7 +1103,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
s->port.fifosize = 16;
s->port.uartclk = clk_get_rate(s->clk);
s->port.type = PORT_IMX;
s->port.dev = s->dev = get_device(&pdev->dev);
s->port.dev = s->dev = &pdev->dev;
s->ctrl = 0;
@ -1134,7 +1134,6 @@ out_free_irq:
auart_port[pdev->id] = NULL;
free_irq(s->irq, s);
out_free_clk:
put_device(s->dev);
clk_put(s->clk);
out_free:
kfree(s);
@ -1150,7 +1149,6 @@ static int mxs_auart_remove(struct platform_device *pdev)
auart_port[pdev->id] = NULL;
put_device(s->dev);
clk_put(s->clk);
free_irq(s->irq, s);
kfree(s);

View 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;
}

View 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,

View 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>
@ -46,10 +47,9 @@
#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;

View 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 *);

View File

@ -27,6 +27,7 @@
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/platform_data/serial-sccnxp.h>
#include <linux/regulator/consumer.h>
#define SCCNXP_NAME "uart-sccnxp"
#define SCCNXP_MAJOR 204
@ -131,6 +132,8 @@ struct sccnxp_port {
struct timer_list timer;
struct sccnxp_pdata pdata;
struct regulator *regulator;
};
static inline u8 sccnxp_raw_read(void __iomem *base, u8 reg, u8 shift)
@ -789,8 +792,6 @@ static int sccnxp_probe(struct platform_device *pdev)
return -EADDRNOTAVAIL;
}
dev_set_name(&pdev->dev, SCCNXP_NAME);
s = devm_kzalloc(&pdev->dev, sizeof(struct sccnxp_port), GFP_KERNEL);
if (!s) {
dev_err(&pdev->dev, "Error allocating port structure\n");
@ -918,6 +919,16 @@ static int sccnxp_probe(struct platform_device *pdev)
goto err_out;
}
s->regulator = devm_regulator_get(&pdev->dev, "VCC");
if (!IS_ERR(s->regulator)) {
ret = regulator_enable(s->regulator);
if (ret) {
dev_err(&pdev->dev,
"Failed to enable regulator: %i\n", ret);
return ret;
}
}
membase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(membase)) {
ret = PTR_ERR(membase);
@ -967,10 +978,6 @@ static int sccnxp_probe(struct platform_device *pdev)
s->imr = 0;
sccnxp_write(&s->port[0], SCCNXP_IMR_REG, 0);
/* Board specific configure */
if (s->pdata.init)
s->pdata.init();
if (!s->poll) {
ret = devm_request_threaded_irq(&pdev->dev, s->irq, NULL,
sccnxp_ist,
@ -1011,8 +1018,8 @@ static int sccnxp_remove(struct platform_device *pdev)
uart_unregister_driver(&s->uart);
platform_set_drvdata(pdev, NULL);
if (s->pdata.exit)
s->pdata.exit();
if (!IS_ERR(s->regulator))
return regulator_disable(s->regulator);
return 0;
}

View 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)) {

View File

@ -1941,6 +1941,8 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
mutex_unlock(&port->mutex);
return 0;
}
put_device(tty_dev);
if (console_suspend_enabled || !uart_console(uport))
uport->suspended = 1;
@ -2006,9 +2008,11 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
disable_irq_wake(uport->irq);
uport->irq_wake = 0;
}
put_device(tty_dev);
mutex_unlock(&port->mutex);
return 0;
}
put_device(tty_dev);
uport->suspended = 0;
/*

View 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)

View File

@ -758,7 +758,7 @@ static struct of_device_id sirfsoc_uart_ids[] = {
{ .compatible = "sirf,marco-uart", },
{}
};
MODULE_DEVICE_TABLE(of, sirfsoc_serial_of_match);
MODULE_DEVICE_TABLE(of, sirfsoc_uart_ids);
static struct platform_driver sirfsoc_uart_driver = {
.probe = sirfsoc_uart_probe,

View 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 &&

View 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 ||

View 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)) {

View 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;
}

View 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);

View 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);

View 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);

View 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,
};

View 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);
}
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 */
/* 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);
}
spin_unlock_irqrestore(&buf->lock, flags);
tty_ldisc_deref(disc);

View 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 (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);
if (!on_exit)
kill_pgrp(tty_pgrp, SIGCONT, on_exit);
put_pid(tty_pgrp);
}
}
tty_kref_put(tty);
} else if (on_exit) {
struct pid *old_pgrp;
spin_lock_irq(&current->sighand->siglock);
@ -1358,9 +1405,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;
}
@ -1477,6 +1522,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
@ -1562,6 +1618,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);
@ -1791,12 +1848,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

View 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)
{
struct tty_ldisc *ld;
int retval = tty_check_change(tty);
if (retval)
return retval;
ld = tty_ldisc_ref_wait(tty);
/* Caller guarantees ldisc reference is held */
static int __tty_perform_flush(struct tty_struct *tty, unsigned long arg)
{
struct tty_ldisc *ld = tty->ldisc;
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);

View File

@ -20,6 +20,17 @@
#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,15 +333,24 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref);
void tty_ldisc_deref(struct tty_ldisc *ld)
{
put_ldisc(ld);
unsigned long flags;
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);
static inline void tty_ldisc_put(struct tty_ldisc *ld)
{
put_ldisc(ld);
}
/**
* tty_ldisc_enable - allow ldisc use
* @tty: terminal to activate ldisc on
@ -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,39 +488,6 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
}
}
/**
* tty_ldisc_halt - shut down the line discipline
* @tty: tty device
*
* 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.
*
* 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)
{
clear_bit(TTY_LDISC, &tty->flags);
return cancel_work_sync(&tty->port->buf.work);
}
/**
* 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);
}
/**
* tty_ldisc_wait_idle - wait for the ldisc to become idle
* @tty: tty to wait for
@ -546,6 +504,85 @@ static int tty_ldisc_wait_idle(struct tty_struct *tty, long 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 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, struct tty_struct *o_tty,
long timeout)
{
int retval;
clear_bit(TTY_LDISC, &tty->flags);
if (o_tty)
clear_bit(TTY_LDISC, &o_tty->flags);
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_hangup_halt - halt the line discipline for hangup
* @tty: tty being hung up
*
* 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 bool tty_ldisc_hangup_halt(struct tty_struct *tty)
{
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;
}
/**
* tty_set_ldisc - set line discipline
* @tty: the terminal to set
@ -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)
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);
if (tty_ldisc_hangup_halt(tty)) {
/* 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
/* 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 (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 (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)

View 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);
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 (test_bit(ASYNCB_INITIALIZED, &port->flags) &&
port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
if (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 (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);

View 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);

View 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);
}

View 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;

View 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;

View 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);

View 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)

View 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);
}
/*

View 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);
}

View 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);

View 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,8 +660,6 @@ void qt2_process_read_urb(struct urb *urb)
__func__);
break;
}
if (port_priv->is_open)
tty_flip_buffer_push(&port->port);
newport = *(ch + 3);
@ -709,7 +703,6 @@ 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);
}
@ -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,

View 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,

View 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;
}

View 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)

View 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);
};

View File

@ -86,10 +86,6 @@ struct sccnxp_pdata {
const u32 mctrl_cfg[SCCNXP_MAX_UARTS];
/* Timer value for polling mode (usecs) */
const unsigned int poll_time_us;
/* Called during startup */
void (*init)(void);
/* Called before finish */
void (*exit)(void);
};
#endif

260
include/linux/serial_s3c.h Normal file
View File

@ -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 */

View 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 */

View 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);

View 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: