Commit d2fde28c authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'tty-updates' from Alan

* tty-updates: (75 commits)
  serial_8250: support for Sealevel Systems Model 7803 COMM+8
  hso maintainers update patch
  hso modem detect fix patch against Alan Cox'es tty tree
  tty: Fix an ircomm warning and note another bug
  drivers/char/cyclades.c: cy_pci_probe: fix error path
  Serial: UART driver changes for Cavium OCTEON.
  Serial: Allow port type to be specified when calling serial8250_register_port.
  8250: Serial driver changes to support future Cavium OCTEON serial patches.
  8250: Don't clobber spinlocks.
  fix for tty-serial-move-port
  tty: We want the port object to be persistent
  __FUNCTION__ is gcc-specific, use __func__
  serial: RS485 ioctl structure uses __u32 include linux/types.h
  tty: Drop the lock_kernel in the private ioctl hook
  synclink_cs: Convert to tty_port
  tty: use port methods for the rocket driver
  tty: kref the rocket driver
  tty: make rocketport use standard port->flags
  tty: Redo the rocket driver locking
  tty: Make epca use the port helpers
  ...
parents 609e5b71 e65f0f82
To support containers, we now allow multiple instances of devpts filesystem,
such that indices of ptys allocated in one instance are independent of indices
allocated in other instances of devpts.
To preserve backward compatibility, this support for multiple instances is
enabled only if:
- CONFIG_DEVPTS_MULTIPLE_INSTANCES=y, and
- '-o newinstance' mount option is specified while mounting devpts
IOW, devpts now supports both single-instance and multi-instance semantics.
If CONFIG_DEVPTS_MULTIPLE_INSTANCES=n, there is no change in behavior and
this referred to as the "legacy" mode. In this mode, the new mount options
(-o newinstance and -o ptmxmode) will be ignored with a 'bogus option' message
on console.
If CONFIG_DEVPTS_MULTIPLE_INSTANCES=y and devpts is mounted without the
'newinstance' option (as in current start-up scripts) the new mount binds
to the initial kernel mount of devpts. This mode is referred to as the
'single-instance' mode and the current, single-instance semantics are
preserved, i.e PTYs are common across the system.
The only difference between this single-instance mode and the legacy mode
is the presence of new, '/dev/pts/ptmx' node with permissions 0000, which
can safely be ignored.
If CONFIG_DEVPTS_MULTIPLE_INSTANCES=y and 'newinstance' option is specified,
the mount is considered to be in the multi-instance mode and a new instance
of the devpts fs is created. Any ptys created in this instance are independent
of ptys in other instances of devpts. Like in the single-instance mode, the
/dev/pts/ptmx node is present. To effectively use the multi-instance mode,
open of /dev/ptmx must be a redirected to '/dev/pts/ptmx' using a symlink or
bind-mount.
Eg: A container startup script could do the following:
$ chmod 0666 /dev/pts/ptmx
$ rm /dev/ptmx
$ ln -s pts/ptmx /dev/ptmx
$ ns_exec -cm /bin/bash
# We are now in new container
$ umount /dev/pts
$ mount -t devpts -o newinstance lxcpts /dev/pts
$ sshd -p 1234
where 'ns_exec -cm /bin/bash' calls clone() with CLONE_NEWNS flag and execs
/bin/bash in the child process. A pty created by the sshd is not visible in
the original mount of /dev/pts.
User-space changes
------------------
In multi-instance mode (i.e '-o newinstance' mount option is specified at least
once), following user-space issues should be noted.
1. If -o newinstance mount option is never used, /dev/pts/ptmx can be ignored
and no change is needed to system-startup scripts.
2. To effectively use multi-instance mode (i.e -o newinstance is specified)
administrators or startup scripts should "redirect" open of /dev/ptmx to
/dev/pts/ptmx using either a bind mount or symlink.
$ mount -t devpts -o newinstance devpts /dev/pts
followed by either
$ rm /dev/ptmx
$ ln -s pts/ptmx /dev/ptmx
$ chmod 666 /dev/pts/ptmx
or
$ mount -o bind /dev/pts/ptmx /dev/ptmx
3. The '/dev/ptmx -> pts/ptmx' symlink is the preferred method since it
enables better error-reporting and treats both single-instance and
multi-instance mounts similarly.
But this method requires that system-startup scripts set the mode of
/dev/pts/ptmx correctly (default mode is 0000). The scripts can set the
mode by, either
- adding ptmxmode mount option to devpts entry in /etc/fstab, or
- using 'chmod 0666 /dev/pts/ptmx'
4. If multi-instance mode mount is needed for containers, but the system
startup scripts have not yet been updated, container-startup scripts
should bind mount /dev/ptmx to /dev/pts/ptmx to avoid breaking single-
instance mounts.
Or, in general, container-startup scripts should use:
mount -t devpts -o newinstance -o ptmxmode=0666 devpts /dev/pts
if [ ! -L /dev/ptmx ]; then
mount -o bind /dev/pts/ptmx /dev/ptmx
fi
When all devpts mounts are multi-instance, /dev/ptmx can permanently be
a symlink to pts/ptmx and the bind mount can be ignored.
5. A multi-instance mount that is not accompanied by the /dev/ptmx to
/dev/pts/ptmx redirection would result in an unusable/unreachable pty.
mount -t devpts -o newinstance lxcpts /dev/pts
immediately followed by:
open("/dev/ptmx")
would create a pty, say /dev/pts/7, in the initial kernel mount.
But /dev/pts/7 would be invisible in the new mount.
6. The permissions for /dev/pts/ptmx node should be specified when mounting
/dev/pts, using the '-o ptmxmode=%o' mount option (default is 0000).
mount -t devpts -o newinstance -o ptmxmode=0644 devpts /dev/pts
The permissions can be later be changed as usual with 'chmod'.
chmod 666 /dev/pts/ptmx
7. A mount of devpts without the 'newinstance' option results in binding to
initial kernel mount. This behavior while preserving legacy semantics,
does not provide strict isolation in a container environment. i.e by
mounting devpts without the 'newinstance' option, a container could
get visibility into the 'host' or root container's devpts.
To workaround this and have strict isolation, all mounts of devpts,
including the mount in the root container, should use the newinstance
option.
......@@ -2049,6 +2049,12 @@ M: mikulas@artax.karlin.mff.cuni.cz
W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
S: Maintained
HSO 3G Modem Driver (hso.c)
P: Denis Joseph Barrow
M: d.barow@option.com
W: http://www.pharscape.org
S: Maintained
HTCPEN TOUCHSCREEN DRIVER
P: Pau Oliva Fora
M: pof@eslack.org
......
......@@ -190,7 +190,7 @@ config DIGIEPCA
config ESPSERIAL
tristate "Hayes ESP serial port support"
depends on SERIAL_NONSTANDARD && ISA && ISA_DMA_API
depends on SERIAL_NONSTANDARD && ISA && ISA_DMA_API && BROKEN
help
This is a driver which supports Hayes ESP serial ports. Both single
port cards and multiport cards are supported. Make sure to read
......@@ -443,6 +443,17 @@ config UNIX98_PTYS
All modern Linux systems use the Unix98 ptys. Say Y unless
you're on an embedded system and want to conserve memory.
config DEVPTS_MULTIPLE_INSTANCES
bool "Support multiple instances of devpts"
depends on UNIX98_PTYS
default n
---help---
Enable support for multiple instances of devpts filesystem.
If you want to have isolated PTY namespaces (eg: in containers),
say Y here. Otherwise, say N. If enabled, each mount of devpts
filesystem with the '-o newinstance' option will create an
independent PTY namespace.
config LEGACY_PTYS
bool "Legacy (BSD) PTY support"
default y
......
......@@ -170,7 +170,7 @@ static __inline__ void rtsdtr_ctrl(int bits)
*/
static void rs_stop(struct tty_struct *tty)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
struct async_struct *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_stop"))
......@@ -190,7 +190,7 @@ static void rs_stop(struct tty_struct *tty)
static void rs_start(struct tty_struct *tty)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
struct async_struct *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_start"))
......@@ -861,7 +861,7 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch)
static void rs_flush_chars(struct tty_struct *tty)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
struct async_struct *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_flush_chars"))
......@@ -934,7 +934,7 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count
static int rs_write_room(struct tty_struct *tty)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
struct async_struct *info = tty->driver_data;
if (serial_paranoia_check(info, tty->name, "rs_write_room"))
return 0;
......@@ -943,7 +943,7 @@ static int rs_write_room(struct tty_struct *tty)
static int rs_chars_in_buffer(struct tty_struct *tty)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
struct async_struct *info = tty->driver_data;
if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer"))
return 0;
......@@ -952,7 +952,7 @@ static int rs_chars_in_buffer(struct tty_struct *tty)
static void rs_flush_buffer(struct tty_struct *tty)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
struct async_struct *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
......@@ -969,7 +969,7 @@ static void rs_flush_buffer(struct tty_struct *tty)
*/
static void rs_send_xchar(struct tty_struct *tty, char ch)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
struct async_struct *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_send_char"))
......@@ -1004,7 +1004,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch)
*/
static void rs_throttle(struct tty_struct * tty)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
struct async_struct *info = tty->driver_data;
unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
char buf[64];
......@@ -1029,7 +1029,7 @@ static void rs_throttle(struct tty_struct * tty)
static void rs_unthrottle(struct tty_struct * tty)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
struct async_struct *info = tty->driver_data;
unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
char buf[64];
......@@ -1194,7 +1194,7 @@ static int get_lsr_info(struct async_struct * info, unsigned int __user *value)
static int rs_tiocmget(struct tty_struct *tty, struct file *file)
{
struct async_struct * info = (struct async_struct *)tty->driver_data;
struct async_struct * info = tty->driver_data;
unsigned char control, status;
unsigned long flags;
......@@ -1217,7 +1217,7 @@ static int rs_tiocmget(struct tty_struct *tty, struct file *file)
static int rs_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
struct async_struct * info = (struct async_struct *)tty->driver_data;
struct async_struct * info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
......@@ -1244,7 +1244,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file,
*/
static int rs_break(struct tty_struct *tty, int break_state)
{
struct async_struct * info = (struct async_struct *)tty->driver_data;
struct async_struct * info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_break"))
......@@ -1264,7 +1264,7 @@ static int rs_break(struct tty_struct *tty, int break_state)
static int rs_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
struct async_struct * info = (struct async_struct *)tty->driver_data;
struct async_struct * info = tty->driver_data;
struct async_icount cprev, cnow; /* kernel counter temps */
struct serial_icounter_struct icount;
void __user *argp = (void __user *)arg;
......@@ -1368,7 +1368,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
struct async_struct *info = tty->driver_data;
unsigned long flags;
unsigned int cflag = tty->termios->c_cflag;
......@@ -1428,7 +1428,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
*/
static void rs_close(struct tty_struct *tty, struct file * filp)
{
struct async_struct * info = (struct async_struct *)tty->driver_data;
struct async_struct * info = tty->driver_data;
struct serial_state *state;
unsigned long flags;
......@@ -1523,7 +1523,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
*/
static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
{
struct async_struct * info = (struct async_struct *)tty->driver_data;
struct async_struct * info = tty->driver_data;
unsigned long orig_jiffies, char_time;
int lsr;
......@@ -1587,7 +1587,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
*/
static void rs_hangup(struct tty_struct *tty)
{
struct async_struct * info = (struct async_struct *)tty->driver_data;
struct async_struct * info = tty->driver_data;
struct serial_state *state = info->state;
if (serial_paranoia_check(info, tty->name, "rs_hangup"))
......
......@@ -5010,7 +5010,7 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
if (nchan == 0) {
dev_err(&pdev->dev, "Cyclom-Y PCI host card with no "
"Serial-Modules\n");
return -EIO;
goto err_unmap;
}
} else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) {
struct RUNTIME_9060 __iomem *ctl_addr;
......
This diff is collapsed.
......@@ -2054,6 +2054,15 @@ static void esp_hangup(struct tty_struct *tty)
wake_up_interruptible(&info->port.open_wait);
}
static int esp_carrier_raised(struct tty_port *port)
{
struct esp_struct *info = container_of(port, struct esp_struct, port);
serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
if (serial_in(info, UART_ESI_STAT2) & UART_MSR_DCD)
return 1;
return 0;
}
/*
* ------------------------------------------------------------
* esp_open() and friends
......@@ -2066,17 +2075,19 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
int retval;
int do_clocal = 0;
unsigned long flags;
int cd;
struct tty_port *port = &info->port;
/*
* If the device is in the middle of being closed, then block
* until it's done, and then try again.
*/
if (tty_hung_up_p(filp) ||
(info->port.flags & ASYNC_CLOSING)) {
if (info->port.flags & ASYNC_CLOSING)
interruptible_sleep_on(&info->port.close_wait);
(port->flags & ASYNC_CLOSING)) {
if (port->flags & ASYNC_CLOSING)
interruptible_sleep_on(&port->close_wait);
#ifdef SERIAL_DO_RESTART
if (info->port.flags & ASYNC_HUP_NOTIFY)
if (port->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
else
return -ERESTARTSYS;
......@@ -2091,7 +2102,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
*/
if ((filp->f_flags & O_NONBLOCK) ||
(tty->flags & (1 << TTY_IO_ERROR))) {
info->port.flags |= ASYNC_NORMAL_ACTIVE;
port->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
......@@ -2101,20 +2112,20 @@ static int 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->port.count is dropped by one, so that
* this loop, 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->port.open_wait, &wait);
add_wait_queue(&port->open_wait, &wait);
#ifdef SERIAL_DEBUG_OPEN
printk(KERN_DEBUG "block_til_ready before block: ttys%d, count = %d\n",
info->line, info->port.count);
info->line, port->count);
#endif
spin_lock_irqsave(&info->lock, flags);
if (!tty_hung_up_p(filp))
info->port.count--;
info->port.blocked_open++;
port->count--;
port->blocked_open++;
while (1) {
if ((tty->termios->c_cflag & CBAUD)) {
unsigned int scratch;
......@@ -2129,9 +2140,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
}
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->port.flags & ASYNC_INITIALIZED)) {
!(port->flags & ASYNC_INITIALIZED)) {
#ifdef SERIAL_DO_RESTART
if (info->port.flags & ASYNC_HUP_NOTIFY)
if (port->flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
else
retval = -ERESTARTSYS;
......@@ -2141,11 +2152,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
break;
}
serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
if (serial_in(info, UART_ESI_STAT2) & UART_MSR_DCD)
do_clocal = 1;
cd = tty_port_carrier_raised(port);
if (!(info->port.flags & ASYNC_CLOSING) &&
if (!(port->flags & ASYNC_CLOSING) &&
(do_clocal))
break;
if (signal_pending(current)) {
......@@ -2154,25 +2163,25 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
}
#ifdef SERIAL_DEBUG_OPEN
printk(KERN_DEBUG "block_til_ready blocking: ttys%d, count = %d\n",
info->line, info->port.count);
info->line, port->count);
#endif
spin_unlock_irqrestore(&info->lock, flags);
schedule();
spin_lock_irqsave(&info->lock, flags);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&info->port.open_wait, &wait);
remove_wait_queue(&port->open_wait, &wait);
if (!tty_hung_up_p(filp))
info->port.count++;
info->port.blocked_open--;
port->count++;
port->blocked_open--;
spin_unlock_irqrestore(&info->lock, flags);
#ifdef SERIAL_DEBUG_OPEN
printk(KERN_DEBUG "block_til_ready after blocking: ttys%d, count = %d\n",
info->line, info->port.count);
info->line, port->count);
#endif
if (retval)
return retval;
info->port.flags |= ASYNC_NORMAL_ACTIVE;
port->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
......@@ -2329,6 +2338,10 @@ static const struct tty_operations esp_ops = {
.tiocmset = esp_tiocmset,
};
static const struct tty_port_operations esp_port_ops = {
.esp_carrier_raised,
};
/*
* The serial driver boot-time initialization code!
*/
......@@ -2415,6 +2428,8 @@ static int __init espserial_init(void)
offset = 0;
do {
tty_port_init(&info->port);
info->port.ops = &esp_port_ops;
info->io_port = esp[i] + offset;
info->irq = irq[i];
info->line = (i * 8) + (offset / 8);
......@@ -2437,8 +2452,6 @@ static int __init espserial_init(void)
info->config.flow_off = flow_off;
info->config.pio_threshold = pio_threshold;
info->next_port = ports;
init_waitqueue_head(&info->port.open_wait);
init_waitqueue_head(&info->port.close_wait);
init_waitqueue_head(&info->delta_msr_wait);
init_waitqueue_head(&info->break_wait);
ports = info;
......
......@@ -376,7 +376,8 @@ static void gs_shutdown_port (struct gs_port *port)
void gs_hangup(struct tty_struct *tty)
{
struct gs_port *port;
struct gs_port *port;
unsigned long flags;
func_enter ();
......@@ -386,9 +387,11 @@ void gs_hangup(struct tty_struct *tty)
return;
gs_shutdown_port (port);
spin_lock_irqsave(&port->port.lock, flags);
port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|GS_ACTIVE);
port->port.tty = NULL;
port->port.count = 0;
spin_unlock_irqrestore(&port->port.lock, flags);
wake_up_interruptible(&port->port.open_wait);
func_exit ();
......@@ -397,7 +400,8 @@ void gs_hangup(struct tty_struct *tty)
int gs_block_til_ready(void *port_, struct file * filp)
{
struct gs_port *port = port_;
struct gs_port *gp = port_;
struct tty_port *port = &gp->port;
DECLARE_WAITQUEUE(wait, current);
int retval;
int do_clocal = 0;
......@@ -409,16 +413,16 @@ int gs_block_til_ready(void *port_, struct file * filp)
if (!port) return 0;
tty = port->port.tty;
tty = port->tty;
gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n");
/*
* If the device is in the middle of being closed, then block
* until it's done, and then try again.
*/
if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) {
interruptible_sleep_on(&port->port.close_wait);
if (port->port.flags & ASYNC_HUP_NOTIFY)
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
interruptible_sleep_on(&port->close_wait);
if (port->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
else
return -ERESTARTSYS;
......@@ -432,7 +436,7 @@ int gs_block_til_ready(void *port_, struct file * filp)
*/
if ((filp->f_flags & O_NONBLOCK) ||
(tty->flags & (1 << TTY_IO_ERROR))) {
port->port.flags |= ASYNC_NORMAL_ACTIVE;
port->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
......@@ -444,34 +448,34 @@ int gs_block_til_ready(void *port_, 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, port->port.count is dropped by one, so that
* this loop, 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(&port->port.open_wait, &wait);
add_wait_queue(&port->open_wait, &wait);
gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n");
spin_lock_irqsave(&port->driver_lock, flags);
spin_lock_irqsave(&port->lock, flags);
if (!tty_hung_up_p(filp)) {
port->port.count--;
port->count--;
}
spin_unlock_irqrestore(&port->driver_lock, flags);
port->port.blocked_open++;
port->blocked_open++;
spin_unlock_irqrestore(&port->lock, flags);
while (1) {
CD = port->rd->get_CD (port);
CD = tty_port_carrier_raised(port);
gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD);
set_current_state (TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(port->port.flags & ASYNC_INITIALIZED)) {
if (port->port.flags & ASYNC_HUP_NOTIFY)
!(port->flags & ASYNC_INITIALIZED)) {
if (port->flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
else
retval = -ERESTARTSYS;
break;
}
if (!(port->port.flags & ASYNC_CLOSING) &&
if (!(port->flags & ASYNC_CLOSING) &&
(do_clocal || CD))
break;
gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n",
......@@ -483,19 +487,20 @@ int gs_block_til_ready(void *port_, struct file * filp)
schedule();
}
gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n",
port->port.blocked_open);
port->blocked_open);
set_current_state (TASK_RUNNING);
remove_wait_queue(&port->port.open_wait, &wait);
remove_wait_queue(&port->open_wait, &wait);
spin_lock_irqsave(&port->lock, flags);
if (!tty_hung_up_p(filp)) {
port->port.count++;
port->count++;
}
port->port.blocked_open--;
if (retval)
return retval;
port->port.flags |= ASYNC_NORMAL_ACTIVE;
port->blocked_open--;
if (retval == 0)
port->flags |= ASYNC_NORMAL_ACTIVE;
spin_unlock_irqrestore(&port->lock, flags);
func_exit ();
return 0;
return retval;
}
......@@ -506,7 +511,7 @@ void gs_close(struct tty_struct * tty, struct file * filp)
func_enter ();
port = (struct gs_port *) tty->driver_data;
port = tty->driver_data;
if (!port) return;
......@@ -516,10 +521,10 @@ void gs_close(struct tty_struct * tty, struct file * filp)
port->port.tty = tty;
}
spin_lock_irqsave(&port->driver_lock, flags);
spin_lock_irqsave(&port->port.lock, flags);
if (tty_hung_up_p(filp)) {
spin_unlock_irqrestore(&port->driver_lock, flags);
spin_unlock_irqrestore(&port->port.lock, flags);
if (port->rd->hungup)
port->rd->hungup (port);
func_exit ();
......@@ -538,7 +543,7 @@ void gs_close(struct tty_struct * tty, struct file * filp)
if (port->port.count) {
gs_dprintk(GS_DEBUG_CLOSE, "gs_close port %p: count: %d\n", port, port->port.count);
spin_unlock_irqrestore(&port->driver_lock, flags);
spin_unlock_irqrestore(&port->port.lock, flags);
func_exit ();
return;
}
......@@ -559,8 +564,10 @@ void gs_close(struct tty_struct * tty, struct file * filp)
* line status register.
*/
spin_lock_irqsave(&port->driver_lock, flags);
port->rd->disable_rx_interrupts (port);
spin_unlock_irqrestore(&port->driver_lock, flags);
spin_unlock_irqrestore(&port->port.lock, flags);
/* close has no way of returning "EINTR", so discard return value */
if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
......@@ -573,20 +580,25 @@ void gs_close(struct tty_struct * tty, struct file * filp)
tty_ldisc_flush(tty);
tty->closing = 0;
spin_lock_irqsave(&port->driver_lock, flags);
port->event = 0;
port->rd->close (port);
port->rd->shutdown_port (port);
spin_unlock_irqrestore(&port->driver_lock, flags);
spin_lock_irqsave(&port->port.lock, flags);
port->port.tty = NULL;
if (port->port.blocked_open) {
if (port->close_delay) {
spin_unlock_irqrestore(&port->driver_lock, flags);
spin_unlock_irqrestore(&port->port.lock, flags);
msleep_interruptible(jiffies_to_msecs(port->close_delay));
spin_lock_irqsave(&port->driver_lock, flags);
spin_lock_irqsave(&port->port.lock, flags);
}
wake_up_interruptible(&port->port.open_wait);
}
port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING | ASYNC_INITIALIZED);
spin_unlock_irqrestore(&port->port.lock, flags);
wake_up_interruptible(&port->port.close_wait);
func_exit ();
......
......@@ -529,7 +529,7 @@ static void hvc_set_winsz(struct work_struct *work)
tty = tty_kref_get(hp->tty);
spin_unlock_irqrestore(&hp->lock, hvc_flags);
tty_do_resize(tty, tty, &ws);
tty_do_resize(tty, &ws);
tty_kref_put(tty);
}
......
......@@ -997,14 +997,14 @@ static void hvsi_write_worker(struct work_struct *work)
static int hvsi_write_room(struct tty_struct *tty)
{
struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
struct hvsi_struct *hp = tty->driver_data;
return N_OUTBUF - hp->n_outbuf;
}
static int hvsi_chars_in_buffer(struct tty_struct *tty)
{
struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
struct hvsi_struct *hp = tty->driver_data;
return hp->n_outbuf;
}
......@@ -1070,7 +1070,7 @@ static int hvsi_write(struct tty_struct *tty,
*/
static void hvsi_throttle(struct tty_struct *tty)
{
struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
struct hvsi_struct *hp = tty->driver_data;
pr_debug("%s\n", __func__);
......@@ -1079,7 +1079,7 @@ static void hvsi_throttle(struct tty_struct *tty)
static void hvsi_unthrottle(struct tty_struct *tty)
{
struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
struct hvsi_struct *hp = tty->driver_data;
unsigned long flags;
int shouldflip = 0;
......@@ -1100,7 +1100,7 @@ static void hvsi_unthrottle(struct tty_struct *tty)
static int hvsi_tiocmget(struct tty_struct *tty, struct file *file)
{
struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
struct hvsi_struct *hp = tty->driver_data;
hvsi_get_mctrl(hp);
return hp->mctrl;
......@@ -1109,7 +1109,7 @@ static int hvsi_tiocmget(struct tty_struct *tty, struct file *file)
static int hvsi_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
struct hvsi_struct *hp = tty->driver_data;
unsigned long flags;
uint16_t new_mctrl;
......
......@@ -328,11 +328,13 @@ static inline void drop_rts(struct isi_port *port)
}
/* card->lock MUST NOT be held */
static inline void raise_dtr_rts(struct isi_port *port)
static void isicom_raise_dtr_rts(struct tty_port *port)
{
struct isi_board *card = port->card;
struct isi_port *ip = container_of(port, struct isi_port, port);
struct isi_board *card = ip->card;
unsigned long base = card->base;
u16 channel = port->channel;
u16 channel = ip->channel;
if (!lock_card(card))
return;
......@@ -340,7 +342,7 @@ static inline void raise_dtr_rts(struct isi_port *port)
outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0f04, base);
InterruptTheCard(base);
port->status |= (ISI_DTR | ISI_RTS);
ip->status |= (ISI_DTR | ISI_RTS);
unlock_card(card);
}
......@@ -830,80 +832,10 @@ static int isicom_setup_port(struct tty_struct *tty)
return 0;
}
static int block_til_ready(struct tty_struct *tty, struct file *filp,
struct isi_port *port)
static int isicom_carrier_raised(struct tty_port *port)
{
struct isi_board *card = port->card;
int do_clocal = 0, retval;
unsigned long flags;
DECLARE_WAITQUEUE(wait, current);
/* block if port is in the process of being closed */
if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) {
pr_dbg("block_til_ready: close in progress.\n");
interruptible_sleep_on(&port->port.close_wait);
if (port->port.flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
else
return -ERESTARTSYS;
}
/* if non-blocking mode is set ... */
if ((filp->f_flags & O_NONBLOCK) ||
(tty->flags & (1 << TTY_IO_ERROR))) {
pr_dbg("block_til_ready: non-block mode.\n");
port->port.flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
if (C_CLOCAL(tty))
do_clocal = 1;
/* block waiting for DCD to be asserted, and while
callout dev is busy */
retval = 0;
add_wait_queue(&port->port.open_wait, &wait);
spin_lock_irqsave(&card->card_lock, flags);
if (!tty_hung_up_p(filp))
port->port.count--;
port->port.blocked_open++;
spin_unlock_irqrestore(&card->card_lock, flags);
while (1) {
raise_dtr_rts(port);
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) || !(port->port.flags & ASYNC_INITIALIZED)) {
if (port->port.flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
else
retval = -ERESTARTSYS;
break;
}
if (!(port->port.flags & ASYNC_CLOSING) &&
(do_clocal || (port->status & ISI_DCD))) {
break;
}
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
schedule();
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&port->port.open_wait, &wait);
spin_lock_irqsave(&card->card_lock, flags);
if (!tty_hung_up_p(filp))
port->port.count++;
port->port.blocked_open--;
spin_unlock_irqrestore(&card->card_lock, flags);
if (retval)
return retval;
port->port.flags |= ASYNC_NORMAL_ACTIVE;
return 0;
struct isi_port *ip = container_of(port, struct isi_port, port);
return (ip->status & ISI_DCD)?1 : 0;
}
static int isicom_open(struct tty_struct *tty, struct file *filp)
......@@ -932,12 +864,13 @@ static int isicom_open(struct tty_struct *tty, struct file *filp)
isicom_setup_board(card);
/* FIXME: locking on port.count etc */
port->port.count++;
tty->driver_data = port;
tty_port_tty_set(&port->port, tty);
error = isicom_setup_port(tty);
if (error == 0)
error = block_til_ready(tty, filp, port);
error = tty_port_block_til_ready(&port->port, tty, filp);
return error;
}
......@@ -1012,76 +945,30 @@ static void isicom_flush_buffer(struct tty_struct *tty)
static void isicom_close(struct tty_struct *tty, struct file *filp)
{
struct isi_port *port = tty->driver_data;
struct isi_port *ip = tty->driver_data;
struct tty_port *port = &ip->port;
struct isi_board *card;
unsigned long flags;
if (!port)
return;
card = port->card;
if (isicom_paranoia_check(port, tty->name, "isicom_close"))
return;
pr_dbg("Close start!!!.\n");
spin_lock_irqsave(&card->card_lock, flags);
if (tty_hung_up_p(filp)) {
spin_unlock_irqrestore(&card->card_lock, flags);
return;
}
if (tty->count == 1 && port->port.count != 1) {
printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port "
"count tty->count = 1 port count = %d.\n",
card->base, port->port.count);
port->port.count = 1;
}
if (--port->port.count < 0) {
printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port "
"count for channel%d = %d", card->base, port->channel,
port->port.count);
port->port.count = 0;
}
BUG_ON(!ip);
if (port->port.count) {
spin_unlock_irqrestore(&card->card_lock, flags);
card = ip->card;
if (isicom_paranoia_check(ip, tty->name, "isicom_close"))
return;
}
port->port.flags |= ASYNC_CLOSING;
tty->closing = 1;
spin_unlock_irqrestore(&card->card_lock, flags);
if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent(tty, port->port.closing_wait);
/* indicate to the card that no more data can be received
on this port */
spin_lock_irqsave(&card->card_lock, flags);
if (port->port.flags & ASYNC_INITIALIZED) {
card->port_status &= ~(1 << port->channel);
if (port->flags & ASYNC_INITIALIZED) {
card->port_status &= ~(1 << ip->channel);
outw(card->port_status, card->base + 0x02);
}
isicom_shutdown_port(port);
isicom_shutdown_port(ip);
spin_unlock_irqrestore(&card->card_lock, flags);
isicom_flush_buffer(tty);
tty_ldisc_flush(tty);
spin_lock_irqsave(&card->card_lock, flags);
tty->closing = 0;
if (port->port.blocked_open) {
spin_unlock_irqrestore(&card->card_lock, flags);
if (port->port.close_delay) {
pr_dbg("scheduling until time out.\n");
msleep_interruptible(
jiffies_to_msecs(port->port.close_delay));
}
spin_lock_irqsave(&card->card_lock, flags);
wake_up_interruptible(&port->port.open_wait);
}
port->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
wake_up_interruptible(&port->port.close_wait);
spin_unlock_irqrestore(&card->card_lock, flags);
tty_port_close_end(port, tty);
}
/* write et all */
......@@ -1420,10 +1307,7 @@ static void isicom_hangup(struct tty_struct *tty)
isicom_shutdown_port(port);
spin_unlock_irqrestore(&port->card->card_lock, flags);
port->port.count = 0;
port->port.flags &= ~ASYNC_NORMAL_ACTIVE;
tty_port_tty_set(&port->port, NULL);
wake_up_interruptible(&port->port.open_wait);
tty_port_hangup(&port->port);
}
......@@ -1452,6 +1336,11 @@ static const struct tty_operations isicom_ops = {
.break_ctl = isicom_send_break,
};
static const struct tty_port_operations isicom_port_ops = {
.carrier_raised = isicom_carrier_raised,
.raise_dtr_rts = isicom_raise_dtr_rts,
};
static int __devinit reset_card(struct pci_dev *pdev,
const unsigned int card, unsigned int *signature)
{
......@@ -1794,6 +1683,7 @@ static int __init isicom_init(void)
spin_lock_init(&isi_card[idx].card_lock);
for (channel = 0; channel < 16; channel++, port++) {
tty_port_init(&port->port);
port->port.ops = &isicom_port_ops;
port->magic = ISICOM_MAGIC;
port->card = &isi_card[idx];
port->channel = channel;
......
This diff is collapsed.
......@@ -206,6 +206,7 @@ static void moxa_poll(unsigned long);
static void moxa_set_tty_param(struct tty_struct *, struct ktermios *);
static void moxa_setup_empty_event(struct tty_struct *);
static void moxa_shut_down(struct tty_struct *);
static int moxa_carrier_raised(struct tty_port *);
/*
* moxa board interface functions:
*/
......@@ -405,6 +406,10 @@ static const struct tty_operations moxa_ops = {
.tiocmset = moxa_tiocmset,
};
static const struct tty_port_operations moxa_port_ops = {
.carrier_raised = moxa_carrier_raised,
};
static struct tty_driver *moxaDriver;
static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0);
static DEFINE_SPINLOCK(moxa_lock);
......@@ -826,6 +831,7 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) {
tty_port_init(&p->port);
p->port.ops = &moxa_port_ops;
p->type = PORT_16550A;
p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
}
......@@ -1115,15 +1121,27 @@ static void moxa_close_port(struct tty_struct *tty)
tty_port_tty_set(&ch->port, NULL);
}
static int moxa_carrier_raised(struct tty_port *port)
{
struct moxa_port *ch = container_of(port, struct moxa_port, port);
int dcd;
spin_lock_bh(&moxa_lock);
dcd = ch->DCDState;
spin_unlock_bh(&moxa_lock);
return dcd;
}
static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
struct moxa_port *ch)
{
struct tty_port *port = &ch->port;
DEFINE_WAIT(wait);
int retval = 0;
u8 dcd;
while (1) {
prepare_to_wait(&ch->port.open_wait, &wait, TASK_INTERRUPTIBLE);
prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp)) {
#ifdef SERIAL_DO_RESTART
retval = -ERESTARTSYS;
......@@ -1132,9 +1150,7 @@ static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
#endif
break;
}
spin_lock_bh(&moxa_lock);
dcd = ch->DCDState;
spin_unlock_bh(&moxa_lock);
dcd = tty_port_carrier_raised(port);
if (dcd)
break;
......@@ -1144,7 +1160,7 @@ static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
}
schedule();
}
finish_wait(&ch->port.open_wait, &wait);
finish_wait(&port->open_wait, &wait);
return retval;
}
......
......@@ -541,74 +541,21 @@ static unsigned char mxser_get_msr(int baseaddr, int mode, int port)
return status;
}
static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
struct mxser_port *port)
static int mxser_carrier_raised(struct tty_port *port)
{
DECLARE_WAITQUEUE(wait, current);
int retval;
int do_clocal = 0;
unsigned long flags;
/*
* If non-blocking mode is set, or the port is not enabled,
* then make the check up front and then exit.
*/
if ((filp->f_flags & O_NONBLOCK) ||
test_bit(TTY_IO_ERROR, &tty->flags)) {
port->port.flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
struct mxser_port *mp = container_of(port, struct mxser_port, port);
return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0;
}
if (tty->termios->c_cflag & CLOCAL)
do_clocal = 1;
static void mxser_raise_dtr_rts(struct tty_port *port)
{
struct mxser_port *mp = container_of(port, struct mxser_port, port);
unsigned long flags;
/*
* 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, port->port.count is dropped by one, so that
* mxser_close() knows when to free things. We restore it upon
* exit, either normal or abnormal.
*/
retval = 0;
add_wait_queue(&port->port.open_wait, &wait);
spin_lock_irqsave(&port->slock, flags);
if (!tty_hung_up_p(filp))
port->port.count--;
spin_unlock_irqrestore(&port->slock, flags);
port->port.blocked_open++;
while (1) {
spin_lock_irqsave(&port->slock, flags);
outb(inb(port->ioaddr + UART_MCR) |
UART_MCR_DTR | UART_MCR_RTS, port->ioaddr + UART_MCR);
spin_unlock_irqrestore(&port->slock, flags);
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) || !(port->port.flags & ASYNC_INITIALIZED)) {
if (port->port.flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
else
retval = -ERESTARTSYS;
break;
}
if (!(port->port.flags & ASYNC_CLOSING) &&
(do_clocal ||
(inb(port->ioaddr + UART_MSR) & UART_MSR_DCD)))
break;
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
schedule();
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&port->port.open_wait, &wait);
if (!tty_hung_up_p(filp))
port->port.count++;
port->port.blocked_open--;
if (retval)
return retval;
port->port.flags |= ASYNC_NORMAL_ACTIVE;
return 0;
spin_lock_irqsave(&mp->slock, flags);
outb(inb(mp->ioaddr + UART_MCR) |
UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR);
spin_unlock_irqrestore(&mp->slock, flags);
}
static int mxser_set_baud(struct tty_struct *tty, long newspd)
......@@ -1087,14 +1034,14 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
/*
* Start up serial port
*/
spin_lock_irqsave(&info->slock, flags);
spin_lock_irqsave(&info->port.lock, flags);
info->port.count++;
spin_unlock_irqrestore(&info->slock, flags);
spin_unlock_irqrestore(&info->port.lock, flags);
retval = mxser_startup(tty);
if (retval)
return retval;
retval = mxser_block_til_ready(tty, filp, info);
retval = tty_port_block_til_ready(&info->port, tty, filp);
if (retval)
return retval;
......@@ -1133,57 +1080,26 @@ static void mxser_flush_buffer(struct tty_struct *tty)
static void mxser_close(struct tty_struct *tty, struct file *filp)
{
struct mxser_port *info = tty->driver_data;
struct tty_port *port = &info->port;
unsigned long timeout;
unsigned long flags;
if (tty->index == MXSER_PORTS)
return;
if (!info)
return;
spin_lock_irqsave(&info->slock, flags);
if (tty_hung_up_p(filp)) {
spin_unlock_irqrestore(&info->slock, flags);
return;
}
if ((tty->count == 1) && (info->port.count != 1)) {
/*
* Uh, oh. tty->count is 1, which means that the tty
* structure will be freed. Info->port.count should always
* be one in these conditions. If it's greater than
* one, we've got real problems, since it means the
* serial port won't be shutdown.
*/
printk(KERN_ERR "mxser_close: bad serial port count; "
"tty->count is 1, info->port.count is %d\n", info->port.count);
info->port.count = 1;
}
if (--info->port.count < 0) {
printk(KERN_ERR "mxser_close: bad serial port count for "
"ttys%d: %d\n", tty->index, info->port.count);
info->port.count = 0;
}
if (info->port.count) {
spin_unlock_irqrestore(&info->slock, flags);
if (tty_port_close_start(port, tty, filp) == 0)
return;
}
info->port.flags |= ASYNC_CLOSING;
spin_unlock_irqrestore(&info->slock, flags);
/*
* Save the termios structure, since this port may have
* separate termios for callout and dialin.
*
* FIXME: Can this go ?
*/
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->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 receive line status interrupts, and tell the
......@@ -1209,19 +1125,12 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
}
}
mxser_shutdown(tty);
mxser_flush_buffer(tty);
tty_ldisc_flush(tty);
tty->closing = 0;
tty_port_tty_set(&info->port, NULL);
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->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
/* Right now the tty_port set is done outside of the close_end helper
as we don't yet have everyone using refcounts */
tty_port_close_end(port, tty);
tty_port_tty_set(port, NULL);
}
static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count)
......@@ -2146,10 +2055,7 @@ static void mxser_hangup(struct tty_struct *tty)
mxser_flush_buffer(tty);
mxser_shutdown(tty);
info->port.count = 0;
info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
tty_port_tty_set(&info->port, NULL);
wake_up_interruptible(&info->port.open_wait);
tty_port_hangup(&info->port);
}
/*
......@@ -2449,6 +2355,11 @@ static const struct tty_operations mxser_ops = {
.tiocmset = mxser_tiocmset,
};
struct tty_port_operations mxser_port_ops = {
.carrier_raised = mxser_carrier_raised,
.raise_dtr_rts = mxser_raise_dtr_rts,
};
/*
* The MOXA Smartio/Industio serial driver boot-time initialization code!
*/
......@@ -2482,6 +2393,7 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
for (i = 0; i < brd->info->nports; i++) {
info = &brd->ports[i];
tty_port_init(&info->port);
info->port.ops = &mxser_port_ops;
info->board = brd;
info->stop_rx = 0;
info->ldisc_stop_rx = 0;
......
......@@ -1003,7 +1003,7 @@ static int r3964_open(struct tty_struct *tty)
static void r3964_close(struct tty_struct *tty)
{
struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
struct r3964_info *pInfo = tty->disc_data;
struct r3964_client_info *pClient, *pNext;
struct r3964_message *pMsg;
struct r3964_block_header *pHeader, *pNextHeader;
......@@ -1058,7 +1058,7 @@ static void r3964_close(struct tty_struct *tty)
static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
unsigned char __user * buf, size_t nr)
{
struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
struct r3964_info *pInfo = tty->disc_data;
struct r3964_client_info *pClient;
struct r3964_message *pMsg;
struct r3964_client_message theMsg;
......@@ -1113,7 +1113,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
const unsigned char *data, size_t count)
{
struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
struct r3964_info *pInfo = tty->disc_data;
struct r3964_block_header *pHeader;
struct r3964_client_info *pClient;
unsigned char *new_data;
......@@ -1182,7 +1182,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
static int r3964_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
struct r3964_info *pInfo = tty->disc_data;
if (pInfo == NULL)
return -EINVAL;
switch (cmd) {
......@@ -1216,7 +1216,7 @@ static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old)
static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,
struct poll_table_struct *wait)
{
struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
struct r3964_info *pInfo = tty->disc_data;
struct r3964_client_info *pClient;
struct r3964_message *pMsg = NULL;
unsigned long flags;
......@@ -1241,7 +1241,7 @@ static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,
static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
char *fp, int count)
{
struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
struct r3964_info *pInfo = tty->disc_data;
const unsigned char *p;
char *f, flags = 0;
int i;
......
This diff is collapsed.
......@@ -353,6 +353,7 @@ struct ctrl_ul {
/* This holds all information that is needed regarding a port */
struct port {
struct tty_port port;
u8 update_flow_control;
struct ctrl_ul ctrl_ul;
struct ctrl_dl ctrl_dl;
......@@ -365,8 +366,6 @@ struct port {
u8 toggle_ul;
u16 token_dl;
struct tty_struct *tty;
int tty_open_count;
/* mutex to ensure one access patch to this port */
struct mutex tty_sem;
wait_queue_head_t tty_wait;
......@@ -788,14 +787,14 @@ static void disable_transmit_dl(enum port_type port, struct nozomi *dc)
* Return 1 - send buffer to card and ack.
* Return 0 - don't ack, don't send buffer to card.
*/
static int send_data(enum port_type index, const struct nozomi *dc)
static int send_data(enum port_type index, struct nozomi *dc)
{
u32 size = 0;
const struct port *port = &dc->port[index];
struct port *port = &dc->port[index];
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 = port->tty;
struct tty_struct *tty = tty_port_tty_get(&port->port);
/* Get data from tty and place in buf for now */
size = __kfifo_get(port->fifo_ul, dc->send_buf,
......@@ -803,6 +802,7 @@ static int send_data(enum port_type index, const struct nozomi *dc)
if (size == 0) {
DBG4("No more data to send, disable link:");
tty_kref_put(tty);
return 0;
}
......@@ -815,6 +815,7 @@ static int send_data(enum port_type index, const struct nozomi *dc)
if (tty)
tty_wakeup(tty);
tty_kref_put(tty);
return 1;
}
......@@ -826,7 +827,7 @@ static int receive_data(enum port_type index, struct nozomi *dc)
u32 offset = 4;
struct port *port = &dc->port[index];
void __iomem *addr = port->dl_addr[port->toggle_dl];
struct tty_struct *tty = port->tty;
struct tty_struct *tty = tty_port_tty_get(&port->port);
int i;
if (unlikely(!tty)) {
......@@ -870,7 +871,7 @@ static int receive_data(enum port_type index, struct nozomi *dc)
}
set_bit(index, &dc->flip);
tty_kref_put(tty);
return 1;
}
......@@ -1276,9 +1277,15 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id)
exit_handler:
spin_unlock(&dc->spin_mutex);
for (a = 0; a < NOZOMI_MAX_PORTS; a++)
if (test_and_clear_bit(a, &dc->flip))
tty_flip_buffer_push(dc->port[a].tty);
for (a = 0; a < NOZOMI_MAX_PORTS; a++) {
struct tty_struct *tty;
if (test_and_clear_bit(a, &dc->flip)) {
tty = tty_port_tty_get(&dc->port[a].port);
if (tty)
tty_flip_buffer_push(tty);
tty_kref_put(tty);
}
}
return IRQ_HANDLED;
none:
spin_unlock(&dc->spin_mutex);
......@@ -1453,12 +1460,10 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
for (i = 0; i < MAX_PORT; i++) {
mutex_init(&dc->port[i].tty_sem);
dc->port[i].tty_open_count = 0;
dc->port[i].tty = NULL;
tty_port_init(&dc->port[i].port);
tty_register_device(ntty_driver, dc->index_start + i,
&pdev->dev);
}
return 0;
err_free_sbuf:
......@@ -1482,14 +1487,16 @@ static void __devexit tty_exit(struct nozomi *dc)
flush_scheduled_work();
for (i = 0; i < MAX_PORT; ++i)
if (dc->port[i].tty && \
list_empty(&dc->port[i].tty->hangup_work.entry))
tty_hangup(dc->port[i].tty);
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);
}
/* Racy below - surely should wait for scheduled work to be done or
complete off a hangup method ? */
while (dc->open_ttys)
msleep(1);
for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
tty_unregister_device(ntty_driver, i);
}
......@@ -1579,23 +1586,22 @@ static int ntty_open(struct tty_struct *tty, struct file *file)
if (mutex_lock_interruptible(&port->tty_sem))
return -ERESTARTSYS;
port->tty_open_count++;
port->port.count++;
dc->open_ttys++;
/* Enable interrupt downlink for channel */
if (port->tty_open_count == 1) {
if (port->port.count == 1) {
/* FIXME: is this needed now ? */
tty->low_latency = 1;
tty->driver_data = port;
port->tty = tty;
tty_port_tty_set(&port->port, tty);
DBG1("open: %d", port->token_dl);
spin_lock_irqsave(&dc->spin_mutex, flags);
dc->last_ier = dc->last_ier | port->token_dl;
writew(dc->last_ier, dc->reg_ier);
spin_unlock_irqrestore(&dc->spin_mutex, flags);
}
mutex_unlock(&port->tty_sem);
return 0;
}
......@@ -1606,31 +1612,30 @@ static int ntty_open(struct tty_struct *tty, struct file *file)
static void ntty_close(struct tty_struct *tty, struct file *file)
{
struct nozomi *dc = get_dc_by_tty(tty);
struct port *port = tty->driver_data;
struct port *nport = tty->driver_data;
struct tty_port *port = &nport->port;
unsigned long flags;
if (!dc || !port)
if (!dc || !nport)
return;
if (mutex_lock_interruptible(&port->tty_sem))
return;
/* Users cannot interrupt a close */
mutex_lock(&nport->tty_sem);
if (!port->tty_open_count)
goto exit;
WARN_ON(!port->count);
dc->open_ttys--;
port->tty_open_count--;
port->count--;
tty_port_tty_set(port, NULL);
if (port->tty_open_count == 0) {
DBG1("close: %d", port->token_dl);
if (port->count == 0) {
DBG1("close: %d", nport->token_dl);
spin_lock_irqsave(&dc->spin_mutex, flags);
dc->last_ier &= ~(port->token_dl);
dc->last_ier &= ~(nport->token_dl);
writew(dc->last_ier, dc->reg_ier);
spin_unlock_irqrestore(&dc->spin_mutex, flags);
}
exit:
mutex_unlock(&port->tty_sem);
mutex_unlock(&nport->tty_sem);
}
/*
......@@ -1660,7 +1665,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
return -EAGAIN;
}
if (unlikely(!port->tty_open_count)) {
if (unlikely(!port->port.count)) {
DBG1(" ");
goto exit;
}
......@@ -1710,7 +1715,7 @@ static int ntty_write_room(struct tty_struct *tty)
if (!mutex_trylock(&port->tty_sem))
return 0;
if (!port->tty_open_count)
if (!port->port.count)
goto exit;
room = port->fifo_ul->size - __kfifo_len(port->fifo_ul);
......@@ -1866,7 +1871,7 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty)
goto exit_in_buffer;
}
if (unlikely(!port->tty_open_count)) {
if (unlikely(!port->port.count)) {
dev_err(&dc->pdev->dev, "No tty open?\n");
rval = -ENODEV;
goto exit_in_buffer;
......
This diff is collapsed.
......@@ -5,8 +5,6 @@
*
* Added support for a Unix98-style ptmx device.
* -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
* Added TTY_DO_WRITE_WAKEUP to enable n_tty to send POLL_OUT to
* waiting writers -- Sapan Bhatia <sapan@corewars.org>
*
* When reading this code see also fs/devpts. In particular note that the
* driver_data field is used by the devpts side as a binding to the devpts
......@@ -217,7 +215,6 @@ static int pty_open(struct tty_struct *tty, struct file *filp)
clear_bit(TTY_OTHER_CLOSED, &tty->link->flags);
set_bit(TTY_THROTTLED, &tty->flags);
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
retval = 0;
out:
return retval;
......@@ -230,6 +227,55 @@ static void pty_set_termios(struct tty_struct *tty,
tty->termios->c_cflag |= (CS8 | CREAD);
}
/**
* pty_do_resize - resize event
* @tty: tty being resized
* @real_tty: real tty (not the same as tty if using a pty/tty pair)
* @rows: rows (character)
* @cols: cols (character)
*
* Update the termios variables and send the neccessary signals to
* peform a terminal resize correctly
*/
int pty_resize(struct tty_struct *tty, struct winsize *ws)
{
struct pid *pgrp, *rpgrp;
unsigned long flags;
struct tty_struct *pty = tty->link;
/* For a PTY we need to lock the tty side */
mutex_lock(&tty->termios_mutex);
if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
goto done;
/* Get the PID values and reference them so we can
avoid holding the tty ctrl lock while sending signals.
We need to lock these individually however. */
spin_lock_irqsave(&tty->ctrl_lock, flags);
pgrp = get_pid(tty->pgrp);
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
spin_lock_irqsave(&pty->ctrl_lock, flags);
rpgrp = get_pid(pty->pgrp);
spin_unlock_irqrestore(&pty->ctrl_lock, flags);
if (pgrp)
kill_pgrp(pgrp, SIGWINCH, 1);
if (rpgrp != pgrp && rpgrp)
kill_pgrp(rpgrp, SIGWINCH, 1);
put_pid(pgrp);
put_pid(rpgrp);
tty->winsize = *ws;
pty->winsize = *ws; /* Never used so will go away soon */
done:
mutex_unlock(&tty->termios_mutex);
return 0;
}
static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct tty_struct *o_tty;
......@@ -290,6 +336,7 @@ static const struct tty_operations pty_ops = {
.chars_in_buffer = pty_chars_in_buffer,
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
.resize = pty_resize
};
/* Traditional BSD devices */
......@@ -319,6 +366,7 @@ static const struct tty_operations pty_ops_bsd = {
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
.ioctl = pty_bsd_ioctl,
.resize = pty_resize
};
static void __init legacy_pty_init(void)
......@@ -561,7 +609,8 @@ static const struct tty_operations ptm_unix98_ops = {
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
.ioctl = pty_unix98_ioctl,
.shutdown = pty_unix98_shutdown
.shutdown = pty_unix98_shutdown,
.resize = pty_resize
};
static const struct tty_operations pty_unix98_ops = {
......
......@@ -173,7 +173,7 @@ static void rio_disable_tx_interrupts(void *ptr);
static void rio_enable_tx_interrupts(void *ptr);
static void rio_disable_rx_interrupts(void *ptr);
static void rio_enable_rx_interrupts(void *ptr);
static int rio_get_CD(void *ptr);
static int rio_carrier_raised(struct tty_port *port);
static void rio_shutdown_port(void *ptr);
static int rio_set_real_termios(void *ptr);
static void rio_hungup(void *ptr);
......@@ -224,7 +224,6 @@ static struct real_driver rio_real_driver = {
rio_enable_tx_interrupts,
rio_disable_rx_interrupts,
rio_enable_rx_interrupts,
rio_get_CD,
rio_shutdown_port,
rio_set_real_termios,
rio_chars_in_buffer,
......@@ -476,9 +475,9 @@ static void rio_enable_rx_interrupts(void *ptr)
/* Jeez. Isn't this simple? */
static int rio_get_CD(void *ptr)
static int rio_carrier_raised(struct tty_port *port)
{
struct Port *PortP = ptr;
struct Port *PortP = container_of(port, struct Port, gs.port);
int rv;
func_enter();
......@@ -797,16 +796,9 @@ static int rio_init_drivers(void)
return 1;
}
static void *ckmalloc(int size)
{
void *p;
p = kzalloc(size, GFP_KERNEL);
return p;
}
static const struct tty_port_operations rio_port_ops = {
.carrier_raised = rio_carrier_raised,
};
static int rio_init_datastructures(void)
{
......@@ -826,33 +818,30 @@ static int rio_init_datastructures(void)
#define TMIO_SZ sizeof(struct termios *)
rio_dprintk(RIO_DEBUG_INIT, "getting : %Zd %Zd %Zd %Zd %Zd bytes\n", RI_SZ, RIO_HOSTS * HOST_SZ, RIO_PORTS * PORT_SZ, RIO_PORTS * TMIO_SZ, RIO_PORTS * TMIO_SZ);
if (!(p = ckmalloc(RI_SZ)))
if (!(p = kzalloc(RI_SZ, GFP_KERNEL)))
goto free0;
if (!(p->RIOHosts = ckmalloc(RIO_HOSTS * HOST_SZ)))
if (!(p->RIOHosts = kzalloc(RIO_HOSTS * HOST_SZ, GFP_KERNEL)))
goto free1;
if (!(p->RIOPortp = ckmalloc(RIO_PORTS * PORT_SZ)))
if (!(p->RIOPortp = kzalloc(RIO_PORTS * PORT_SZ, GFP_KERNEL)))
goto free2;
p->RIOConf = RIOConf;
rio_dprintk(RIO_DEBUG_INIT, "Got : %p %p %p\n", p, p->RIOHosts, p->RIOPortp);
#if 1
for (i = 0; i < RIO_PORTS; i++) {
port = p->RIOPortp[i] = ckmalloc(sizeof(struct Port));
port = p->RIOPortp[i] = kzalloc(sizeof(struct Port), GFP_KERNEL);
if (!port) {
goto free6;
}
rio_dprintk(RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped);
tty_port_init(&port->gs.port);
port->gs.port.ops = &rio_port_ops;
port->PortNum = i;
port->gs.magic = RIO_MAGIC;
port->gs.close_delay = HZ / 2;
port->gs.closing_wait = 30 * HZ;
port->gs.rd = &rio_real_driver;
spin_lock_init(&port->portSem);
/*
* Initializing wait queue
*/
init_waitqueue_head(&port->gs.port.open_wait);
init_waitqueue_head(&port->gs.port.close_wait);
}
#else
/* We could postpone initializing them to when they are configured. */
......
This diff is collapsed.
This diff is collapsed.
......@@ -39,7 +39,7 @@ struct rocket_version {
/*
* Rocketport flags
*/
#define ROCKET_CALLOUT_NOHUP 0x00000001
/*#define ROCKET_CALLOUT_NOHUP 0x00000001 */
#define ROCKET_FORCE_CD 0x00000002
#define ROCKET_HUP_NOTIFY 0x00000004
#define ROCKET_SPLIT_TERMIOS 0x00000008
......
......@@ -1162,11 +1162,6 @@ struct r_port {
/* number of characters left in xmit buffer before we ask for more */
#define WAKEUP_CHARS 256
/* Internal flags used only by the rocketport driver */
#define ROCKET_INITIALIZED 0x80000000 /* Port is active */
#define ROCKET_CLOSING 0x40000000 /* Serial port is closing */
#define ROCKET_NORMAL_ACTIVE 0x20000000 /* Normal port is active */
/*
* Assigned major numbers for the Comtrol Rocketport
*/
......
......@@ -306,7 +306,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
*/
int paste_selection(struct tty_struct *tty)
{
struct vc_data *vc = (struct vc_data *)tty->driver_data;
struct vc_data *vc = tty->driver_data;
int pasted = 0;
unsigned int count;
struct tty_ldisc *ld;
......
......@@ -122,7 +122,7 @@ static void a2232_disable_tx_interrupts(void *ptr);
static void a2232_enable_tx_interrupts(void *ptr);
static void a2232_disable_rx_interrupts(void *ptr);
static void a2232_enable_rx_interrupts(void *ptr);
static int a2232_get_CD(void *ptr);
static int a2232_carrier_raised(struct tty_port *port);
static void a2232_shutdown_port(void *ptr);
static int a2232_set_real_termios(void *ptr);
static int a2232_chars_in_buffer(void *ptr);
......@@ -148,7 +148,6 @@ static struct real_driver a2232_real_driver = {
a2232_enable_tx_interrupts,
a2232_disable_rx_interrupts,
a2232_enable_rx_interrupts,
a2232_get_CD,
a2232_shutdown_port,
a2232_set_real_termios,
a2232_chars_in_buffer,
......@@ -260,9 +259,10 @@ static void a2232_enable_rx_interrupts(void *ptr)
port->disable_rx = 0;
}
static int a2232_get_CD(void *ptr)
static int a2232_carrier_raised(struct tty_port *port)
{
return ((struct a2232_port *) ptr)->cd_status;
struct a2232_port *ap = container_of(port, struct a2232_port, gs.port);
return ap->cd_status;
}
static void a2232_shutdown_port(void *ptr)
......@@ -460,14 +460,14 @@ static void a2232_throttle(struct tty_struct *tty)
if switched on. So the only thing we can do at this
layer here is not taking any characters out of the
A2232 buffer any more. */
struct a2232_port *port = (struct a2232_port *) tty->driver_data;
struct a2232_port *port = tty->driver_data;
port->throttle_input = -1;
}
static void a2232_unthrottle(struct tty_struct *tty)
{
/* Unthrottle: dual to "throttle()" above. */
struct a2232_port *port = (struct a2232_port *) tty->driver_data;
struct a2232_port *port = tty->driver_data;
port->throttle_input = 0;
}
......@@ -638,6 +638,10 @@ int ch, err, n, p;
return IRQ_HANDLED;
}
static const struct tty_port_operations a2232_port_ops = {
.carrier_raised = a2232_carrier_raised,
};
static void a2232_init_portstructs(void)
{
struct a2232_port *port;
......@@ -645,6 +649,8 @@ static void a2232_init_portstructs(void)
for (i = 0; i < MAX_A2232_BOARDS*NUMLINES; i++) {
port = a2232_ports + i;
tty_port_init(&port->gs.port);
port->gs.port.ops = &a2232_port_ops;
port->which_a2232 = i/NUMLINES;
port->which_port_on_a2232 = i%NUMLINES;
port->disable_rx = port->throttle_input = port->cd_status = 0;
......@@ -652,11 +658,6 @@ static void a2232_init_portstructs(void)
port->gs.close_delay = HZ/2;
port->gs.closing_wait = 30 * HZ;
port->gs.rd = &a2232_real_driver;
#ifdef NEW_WRITE_LOCKING
mutex_init(&(port->gs.port_write_mutex));
#endif
init_waitqueue_head(&port->gs.port.open_wait);
init_waitqueue_head(&port->gs.port.close_wait);
}
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -366,7 +366,7 @@ do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_
int vt_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
struct vc_data *vc = (struct vc_data *)tty->driver_data;
struct vc_data *vc = tty->driver_data;
struct console_font_op op; /* used in multiple places here */
struct kbd_struct * kbd;
unsigned int console;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -272,7 +272,7 @@ static void jsm_tty_close(struct uart_port *port)
jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n");
bd = channel->ch_bd;
ts = channel->uart_port.info->port.tty->termios;
ts = port->info->port.tty->termios;
channel->ch_flags &= ~(CH_STOPI);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -878,6 +878,7 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
dbg("%sstate=%d", __func__, break_state);
/* LOCKING */
if (break_state)
lcr |= MCT_U232_SET_BREAK;
......
......@@ -721,10 +721,10 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
spin_lock_irqsave(&priv->lock, flags);
lcr = priv->last_lcr;
spin_unlock_irqrestore(&priv->lock, flags);
if (break_state)
lcr |= MCT_U232_SET_BREAK;
spin_unlock_irqrestore(&priv->lock, flags);
mct_u232_set_line_ctrl(serial, lcr);
} /* mct_u232_break_ctl */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment