From 5de0a567c020479d89953038eee9192d417349be Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:53:47 +0200 Subject: TTY: deprecate linux/generic_serial.h Since nobody in the kernel includes that file, let us remove the structs visible to the kernel. However since the userspace sees the file, it still may include that. hence deprecate the use of the header by an added cpp #warning. We should remove the file completely after a couple of years. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- include/linux/generic_serial.h | 64 ++---------------------------------------- 1 file changed, 2 insertions(+), 62 deletions(-) (limited to 'include/linux') diff --git a/include/linux/generic_serial.h b/include/linux/generic_serial.h index fadff28505b..79b3eb37243 100644 --- a/include/linux/generic_serial.h +++ b/include/linux/generic_serial.h @@ -4,7 +4,6 @@ * Copyright (C) 1998 R.E.Wolff@BitWizard.nl * * written for the SX serial driver. - * Contains the code that should be shared over all the serial drivers. * * Version 0.1 -- December, 1998. */ @@ -12,45 +11,8 @@ #ifndef GENERIC_SERIAL_H #define GENERIC_SERIAL_H -#ifdef __KERNEL__ -#include -#include - -struct real_driver { - void (*disable_tx_interrupts) (void *); - void (*enable_tx_interrupts) (void *); - void (*disable_rx_interrupts) (void *); - void (*enable_rx_interrupts) (void *); - void (*shutdown_port) (void*); - int (*set_real_termios) (void*); - int (*chars_in_buffer) (void*); - void (*close) (void*); - void (*hungup) (void*); - void (*getserial) (void*, struct serial_struct *sp); -}; - - - -struct gs_port { - int magic; - struct tty_port port; - unsigned char *xmit_buf; - int xmit_head; - int xmit_tail; - int xmit_cnt; - struct mutex port_write_mutex; - unsigned long event; - unsigned short closing_wait; - int close_delay; - struct real_driver *rd; - int wakeup_chars; - int baud_base; - int baud; - int custom_divisor; - spinlock_t driver_lock; -}; - -#endif /* __KERNEL__ */ +#warning Use of this header is deprecated. +#warning Since nobody sets the constants defined here for you, you should not, in any case, use them. Including the header is thus pointless. /* Flags */ /* Warning: serial.h defines some ASYNC_ flags, they say they are "only" @@ -60,8 +22,6 @@ struct gs_port { #define GS_RX_INTEN 0x00400000 #define GS_ACTIVE 0x00200000 - - #define GS_TYPE_NORMAL 1 #define GS_DEBUG_FLUSH 0x00000001 @@ -72,24 +32,4 @@ struct gs_port { #define GS_DEBUG_FLOW 0x00000020 #define GS_DEBUG_WRITE 0x00000040 -#ifdef __KERNEL__ -int gs_put_char(struct tty_struct *tty, unsigned char ch); -int gs_write(struct tty_struct *tty, - const unsigned char *buf, int count); -int gs_write_room(struct tty_struct *tty); -int gs_chars_in_buffer(struct tty_struct *tty); -void gs_flush_buffer(struct tty_struct *tty); -void gs_flush_chars(struct tty_struct *tty); -void gs_stop(struct tty_struct *tty); -void gs_start(struct tty_struct *tty); -void gs_hangup(struct tty_struct *tty); -int gs_block_til_ready(void *port, struct file *filp); -void gs_close(struct tty_struct *tty, struct file *filp); -void gs_set_termios (struct tty_struct * tty, - struct ktermios * old_termios); -int gs_init_port(struct gs_port *port); -int gs_setserial(struct gs_port *port, struct serial_struct __user *sp); -int gs_getserial(struct gs_port *port, struct serial_struct __user *sp); -void gs_got_break(struct gs_port *port); -#endif /* __KERNEL__ */ #endif -- cgit v1.2.3-70-g09d2 From 05eb48be91e6675c225b5f86c88ecbb83152119c Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:53:49 +0200 Subject: TTY: isdn, remove callout I wonder how this survived there during the whole 2.6 series until now :D. Callouts are not used for a decade, so let us remove it also from isdn. This means removal of ISDN_ASYNC_CALLOUT_ACTIVE which is never raised in info->flags and callout_termios which are never used. This will help us to get rid of ISDN_ASYNC_* flags and use ASYNC ones from serial.h. And then we will switch to tty_port. Signed-off-by: Jiri Slaby Cc: Karsten Keil Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/i4l/isdn_tty.c | 32 ++++++-------------------------- include/linux/isdn.h | 3 --- 2 files changed, 6 insertions(+), 29 deletions(-) (limited to 'include/linux') diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 1d701cd6031..27f70923c22 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1504,18 +1504,11 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * */ if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { - if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) - return -EBUSY; info->flags |= ISDN_ASYNC_NORMAL_ACTIVE; return 0; } - if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) { - if (info->normal_termios.c_cflag & CLOCAL) - do_clocal = 1; - } else { - if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; - } + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; /* * Block waiting for the carrier detect and the line to become * free (i.e., not in use by the callout). While we are in @@ -1546,8 +1539,7 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * #endif break; } - if (!(info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) && - !(info->flags & ISDN_ASYNC_CLOSING) && + if (!(info->flags & ISDN_ASYNC_CLOSING) && (do_clocal || (info->msr & UART_MSR_DCD))) { break; } @@ -1670,14 +1662,6 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) return; } info->flags |= ISDN_ASYNC_CLOSING; - /* - * Save the termios structure, since this port may have - * separate termios for callout and dialin. - */ - if (info->flags & ISDN_ASYNC_NORMAL_ACTIVE) - info->normal_termios = *tty->termios; - if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) - info->callout_termios = *tty->termios; tty->closing = 1; /* @@ -1731,7 +1715,7 @@ isdn_tty_hangup(struct tty_struct *tty) return; isdn_tty_shutdown(info); info->count = 0; - info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE); + info->flags &= ~ISDN_ASYNC_NORMAL_ACTIVE; info->tty = NULL; wake_up_interruptible(&info->open_wait); } @@ -2116,8 +2100,7 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup) return (wret == 2) ? 3 : 0; } -#define TTY_IS_ACTIVE(info) \ - (info->flags & (ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE)) +#define TTY_IS_ACTIVE(info) (info->flags & ISDN_ASYNC_NORMAL_ACTIVE) int isdn_tty_stat_callback(int i, isdn_ctrl *c) @@ -2628,11 +2611,8 @@ isdn_tty_modem_result(int code, modem_info *info) if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) { return; } - if ((info->flags & ISDN_ASYNC_CHECK_CD) && - (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) && - (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) { + if (info->flags & ISDN_ASYNC_CHECK_CD) tty_hangup(info->tty); - } } } diff --git a/include/linux/isdn.h b/include/linux/isdn.h index 292f27a793d..d13b76df34b 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -393,7 +393,6 @@ typedef struct isdn_net_dev_s { #define ISDN_ASYNC_MAGIC 0x49344C01 /* for paranoia-checking */ #define ISDN_ASYNC_INITIALIZED 0x80000000 /* port was initialized */ -#define ISDN_ASYNC_CALLOUT_ACTIVE 0x40000000 /* Call out device active */ #define ISDN_ASYNC_NORMAL_ACTIVE 0x20000000 /* Normal device active */ #define ISDN_ASYNC_CLOSING 0x08000000 /* Serial port is closing */ #define ISDN_ASYNC_CTS_FLOW 0x04000000 /* Do CTS flow control */ @@ -498,8 +497,6 @@ typedef struct modem_info { #endif struct tty_struct *tty; /* Pointer to corresponding tty */ atemu emu; /* AT-emulator data */ - struct ktermios normal_termios; /* For saving termios structs */ - struct ktermios callout_termios; wait_queue_head_t open_wait, close_wait; spinlock_t readlock; } modem_info; -- cgit v1.2.3-70-g09d2 From 6776a2f07924192fd168bdceb1a00d10630edb4d Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:53:50 +0200 Subject: TTY: isdn, remove ISDN_ASYNC_* flags They are the same as TTY ones. So there is no need to redefine them. Remove ISDN_ASYNC_* and use only ASYNC_*. Except the MAGIC number, of course. While we are there, remove also the SERIAL_TYPE flags which are unused. Perhaps we should move the ASYNC flags from serial.h to tty.h given they are used by the tty layer and tty drivers, not only serial? Signed-off-by: Jiri Slaby Cc: Karsten Keil Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/i4l/isdn_tty.c | 59 +++++++++++++++++++++++---------------------- include/linux/isdn.h | 12 --------- 2 files changed, 30 insertions(+), 41 deletions(-) (limited to 'include/linux') diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 27f70923c22..bcf4bbe693b 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -11,6 +11,7 @@ #undef ISDN_TTY_STAT_DEBUG #include +#include /* ASYNC_* flags */ #include #include #include @@ -1036,20 +1037,20 @@ isdn_tty_change_speed(modem_info *info) /* CTS flow control flag and modem status interrupts */ if (cflag & CRTSCTS) { - info->flags |= ISDN_ASYNC_CTS_FLOW; + info->flags |= ASYNC_CTS_FLOW; } else - info->flags &= ~ISDN_ASYNC_CTS_FLOW; + info->flags &= ~ASYNC_CTS_FLOW; if (cflag & CLOCAL) - info->flags &= ~ISDN_ASYNC_CHECK_CD; + info->flags &= ~ASYNC_CHECK_CD; else { - info->flags |= ISDN_ASYNC_CHECK_CD; + info->flags |= ASYNC_CHECK_CD; } } static int isdn_tty_startup(modem_info *info) { - if (info->flags & ISDN_ASYNC_INITIALIZED) + if (info->flags & ASYNC_INITIALIZED) return 0; isdn_lock_drivers(); #ifdef ISDN_DEBUG_MODEM_OPEN @@ -1066,7 +1067,7 @@ isdn_tty_startup(modem_info *info) */ isdn_tty_change_speed(info); - info->flags |= ISDN_ASYNC_INITIALIZED; + info->flags |= ASYNC_INITIALIZED; info->msr |= (UART_MSR_DSR | UART_MSR_CTS); info->send_outstanding = 0; return 0; @@ -1079,7 +1080,7 @@ isdn_tty_startup(modem_info *info) static void isdn_tty_shutdown(modem_info *info) { - if (!(info->flags & ISDN_ASYNC_INITIALIZED)) + if (!(info->flags & ASYNC_INITIALIZED)) return; #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "Shutting down isdnmodem port %d ....\n", info->line); @@ -1099,7 +1100,7 @@ isdn_tty_shutdown(modem_info *info) if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); - info->flags &= ~ISDN_ASYNC_INITIALIZED; + info->flags &= ~ASYNC_INITIALIZED; } /* isdn_tty_write() is the main send-routine. It is called from the upper @@ -1486,11 +1487,11 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * * until it's done, and then try again. */ if (tty_hung_up_p(filp) || - (info->flags & ISDN_ASYNC_CLOSING)) { - if (info->flags & ISDN_ASYNC_CLOSING) + (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) interruptible_sleep_on(&info->close_wait); #ifdef MODEM_DO_RESTART - if (info->flags & ISDN_ASYNC_HUP_NOTIFY) + if (info->flags & ASYNC_HUP_NOTIFY) return -EAGAIN; else return -ERESTARTSYS; @@ -1504,7 +1505,7 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * */ if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { - info->flags |= ISDN_ASYNC_NORMAL_ACTIVE; + info->flags |= ASYNC_NORMAL_ACTIVE; return 0; } if (tty->termios->c_cflag & CLOCAL) @@ -1528,9 +1529,9 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * while (1) { set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || - !(info->flags & ISDN_ASYNC_INITIALIZED)) { + !(info->flags & ASYNC_INITIALIZED)) { #ifdef MODEM_DO_RESTART - if (info->flags & ISDN_ASYNC_HUP_NOTIFY) + if (info->flags & ASYNC_HUP_NOTIFY) retval = -EAGAIN; else retval = -ERESTARTSYS; @@ -1539,7 +1540,7 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * #endif break; } - if (!(info->flags & ISDN_ASYNC_CLOSING) && + if (!(info->flags & ASYNC_CLOSING) && (do_clocal || (info->msr & UART_MSR_DCD))) { break; } @@ -1564,7 +1565,7 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * #endif if (retval) return retval; - info->flags |= ISDN_ASYNC_NORMAL_ACTIVE; + info->flags |= ASYNC_NORMAL_ACTIVE; return 0; } @@ -1661,7 +1662,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) module_put(info->owner); return; } - info->flags |= ISDN_ASYNC_CLOSING; + info->flags |= ASYNC_CLOSING; tty->closing = 1; /* @@ -1670,7 +1671,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) * interrupt driver to stop checking the data ready bit in the * line status register. */ - if (info->flags & ISDN_ASYNC_INITIALIZED) { + if (info->flags & ASYNC_INITIALIZED) { tty_wait_until_sent_from_close(tty, 3000); /* 30 seconds timeout */ /* * Before we drop DTR, make sure the UART transmitter @@ -1696,7 +1697,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) msleep_interruptible(500); wake_up_interruptible(&info->open_wait); } - info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CLOSING); + info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_close normal exit\n"); @@ -1715,7 +1716,7 @@ isdn_tty_hangup(struct tty_struct *tty) return; isdn_tty_shutdown(info); info->count = 0; - info->flags &= ~ISDN_ASYNC_NORMAL_ACTIVE; + info->flags &= ~ASYNC_NORMAL_ACTIVE; info->tty = NULL; wake_up_interruptible(&info->open_wait); } @@ -2061,7 +2062,7 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup) #endif if ( #ifndef FIX_FILE_TRANSFER - (info->flags & ISDN_ASYNC_NORMAL_ACTIVE) && + (info->flags & ASYNC_NORMAL_ACTIVE) && #endif (info->isdn_driver == -1) && (info->isdn_channel == -1) && @@ -2100,7 +2101,7 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup) return (wret == 2) ? 3 : 0; } -#define TTY_IS_ACTIVE(info) (info->flags & ISDN_ASYNC_NORMAL_ACTIVE) +#define TTY_IS_ACTIVE(info) (info->flags & ASYNC_NORMAL_ACTIVE) int isdn_tty_stat_callback(int i, isdn_ctrl *c) @@ -2319,7 +2320,7 @@ isdn_tty_at_cout(char *msg, modem_info *info) spin_lock_irqsave(&info->readlock, flags); tty = info->tty; - if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) { + if ((info->flags & ASYNC_CLOSING) || (!tty)) { spin_unlock_irqrestore(&info->readlock, flags); return; } @@ -2469,15 +2470,15 @@ isdn_tty_modem_result(int code, modem_info *info) case RESULT_NO_CARRIER: #ifdef ISDN_DEBUG_MODEM_HUP printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n", - (info->flags & ISDN_ASYNC_CLOSING), + (info->flags & ASYNC_CLOSING), (!info->tty)); #endif m->mdmreg[REG_RINGCNT] = 0; del_timer(&info->nc_timer); info->ncarrier = 0; - if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) { + if ((info->flags & ASYNC_CLOSING) || (!info->tty)) return; - } + #ifdef CONFIG_ISDN_AUDIO if (info->vonline & 1) { #ifdef ISDN_DEBUG_MODEM_VOICE @@ -2608,10 +2609,10 @@ isdn_tty_modem_result(int code, modem_info *info) } } if (code == RESULT_NO_CARRIER) { - if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) { + if ((info->flags & ASYNC_CLOSING) || (!info->tty)) return; - } - if (info->flags & ISDN_ASYNC_CHECK_CD) + + if (info->flags & ASYNC_CHECK_CD) tty_hangup(info->tty); } } diff --git a/include/linux/isdn.h b/include/linux/isdn.h index d13b76df34b..1b4b4c1846c 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -392,20 +392,8 @@ typedef struct isdn_net_dev_s { /*======================= Start of ISDN-tty stuff ===========================*/ #define ISDN_ASYNC_MAGIC 0x49344C01 /* for paranoia-checking */ -#define ISDN_ASYNC_INITIALIZED 0x80000000 /* port was initialized */ -#define ISDN_ASYNC_NORMAL_ACTIVE 0x20000000 /* Normal device active */ -#define ISDN_ASYNC_CLOSING 0x08000000 /* Serial port is closing */ -#define ISDN_ASYNC_CTS_FLOW 0x04000000 /* Do CTS flow control */ -#define ISDN_ASYNC_CHECK_CD 0x02000000 /* i.e., CLOCAL */ -#define ISDN_ASYNC_HUP_NOTIFY 0x0001 /* Notify tty on hangups/closes */ -#define ISDN_ASYNC_SESSION_LOCKOUT 0x0100 /* Lock cua opens on session */ -#define ISDN_ASYNC_PGRP_LOCKOUT 0x0200 /* Lock cua opens on pgrp */ -#define ISDN_ASYNC_CALLOUT_NOHUP 0x0400 /* No hangup for cui */ -#define ISDN_ASYNC_SPLIT_TERMIOS 0x0008 /* Sep. termios for dialin/out */ #define ISDN_SERIAL_XMIT_SIZE 1024 /* Default bufsize for write */ #define ISDN_SERIAL_XMIT_MAX 4000 /* Maximum bufsize for write */ -#define ISDN_SERIAL_TYPE_NORMAL 1 -#define ISDN_SERIAL_TYPE_CALLOUT 2 #ifdef CONFIG_ISDN_AUDIO /* For using sk_buffs with audio we need some private variables -- cgit v1.2.3-70-g09d2 From ce93d33cf45db9893cfc725a2b470da15bfe4435 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:53:51 +0200 Subject: TTY: isdn, do not play with module refcounts The module which called allocate_tty_driver is already refcounted by the TTY layer automatically. And since THIS_MODULE is isdn_tty and it allocated the tty_driver, there is no need to do the counts in isdn's tty->ops->open/close. Signed-off-by: Jiri Slaby Cc: Karsten Keil Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/i4l/isdn_tty.c | 11 ----------- include/linux/isdn.h | 1 - 2 files changed, 12 deletions(-) (limited to 'include/linux') diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index bcf4bbe693b..1ff307276d2 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1584,10 +1584,6 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp) info = &dev->mdm.info[tty->index]; if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open")) return -ENODEV; - if (!try_module_get(info->owner)) { - printk(KERN_WARNING "%s: cannot reserve module\n", __func__); - return -ENODEV; - } #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name, info->count); @@ -1603,7 +1599,6 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp) #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_open return after startup\n"); #endif - module_put(info->owner); return retval; } retval = isdn_tty_block_til_ready(tty, filp, info); @@ -1611,7 +1606,6 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp) #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_open return after isdn_tty_block_til_ready \n"); #endif - module_put(info->owner); return retval; } #ifdef ISDN_DEBUG_MODEM_OPEN @@ -1659,7 +1653,6 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_close after info->count != 0\n"); #endif - module_put(info->owner); return; } info->flags |= ASYNC_CLOSING; @@ -1692,7 +1685,6 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) info->tty = NULL; info->ncarrier = 0; tty->closing = 0; - module_put(info->owner); if (info->blocked_open) { msleep_interruptible(500); wake_up_interruptible(&info->open_wait); @@ -1879,9 +1871,6 @@ isdn_tty_modem_init(void) retval = -ENOMEM; goto err_unregister; } -#endif -#ifdef MODULE - info->owner = THIS_MODULE; #endif spin_lock_init(&info->readlock); sprintf(info->last_cause, "0000"); diff --git a/include/linux/isdn.h b/include/linux/isdn.h index 1b4b4c1846c..66d9d71e003 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -435,7 +435,6 @@ typedef struct atemu { /* Private data (similar to async_struct in ) */ typedef struct modem_info { int magic; - struct module *owner; int flags; /* defined in tty.h */ int x_char; /* xon/xoff character */ int mcr; /* Modem control register */ -- cgit v1.2.3-70-g09d2 From ed722ead61e3776cbcda3805bb872ff2b856d3b9 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:53:53 +0200 Subject: TTY: isdn, remove unused members from modem_info session and pgrp are unused. Prune them. Signed-off-by: Jiri Slaby Cc: Karsten Keil Signed-off-by: Greg Kroah-Hartman --- include/linux/isdn.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/isdn.h b/include/linux/isdn.h index 66d9d71e003..63af3208004 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -443,8 +443,6 @@ typedef struct modem_info { int line; int count; /* # of fd on device */ int blocked_open; /* # of blocked opens */ - long session; /* Session of opening process */ - long pgrp; /* pgrp of opening process */ int online; /* 1 = B-Channel is up, drop data */ /* 2 = B-Channel is up, deliver d.*/ int dialing; /* Dial in progress or ATA */ -- cgit v1.2.3-70-g09d2 From 48decc1c743fa4eb5ba5dd3f556e7fcbefe65440 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:53:54 +0200 Subject: TTY: isdn, add tty_port And use tty_port->flags now. Other members will follow. Signed-off-by: Jiri Slaby Cc: Karsten Keil Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/i4l/isdn_tty.c | 60 +++++++++++++++++++++++---------------------- include/linux/isdn.h | 3 ++- 2 files changed, 33 insertions(+), 30 deletions(-) (limited to 'include/linux') diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 74b05188c18..8ba526dc98b 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1046,20 +1046,20 @@ isdn_tty_change_speed(modem_info *info) /* CTS flow control flag and modem status interrupts */ if (cflag & CRTSCTS) { - info->flags |= ASYNC_CTS_FLOW; + info->port.flags |= ASYNC_CTS_FLOW; } else - info->flags &= ~ASYNC_CTS_FLOW; + info->port.flags &= ~ASYNC_CTS_FLOW; if (cflag & CLOCAL) - info->flags &= ~ASYNC_CHECK_CD; + info->port.flags &= ~ASYNC_CHECK_CD; else { - info->flags |= ASYNC_CHECK_CD; + info->port.flags |= ASYNC_CHECK_CD; } } static int isdn_tty_startup(modem_info *info) { - if (info->flags & ASYNC_INITIALIZED) + if (info->port.flags & ASYNC_INITIALIZED) return 0; isdn_lock_drivers(); #ifdef ISDN_DEBUG_MODEM_OPEN @@ -1076,7 +1076,7 @@ isdn_tty_startup(modem_info *info) */ isdn_tty_change_speed(info); - info->flags |= ASYNC_INITIALIZED; + info->port.flags |= ASYNC_INITIALIZED; info->msr |= (UART_MSR_DSR | UART_MSR_CTS); info->send_outstanding = 0; return 0; @@ -1089,7 +1089,7 @@ isdn_tty_startup(modem_info *info) static void isdn_tty_shutdown(modem_info *info) { - if (!(info->flags & ASYNC_INITIALIZED)) + if (!(info->port.flags & ASYNC_INITIALIZED)) return; #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "Shutting down isdnmodem port %d ....\n", info->line); @@ -1109,7 +1109,7 @@ isdn_tty_shutdown(modem_info *info) if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); - info->flags &= ~ASYNC_INITIALIZED; + info->port.flags &= ~ASYNC_INITIALIZED; } /* isdn_tty_write() is the main send-routine. It is called from the upper @@ -1496,11 +1496,11 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * * until it's done, and then try again. */ if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) + (info->port.flags & ASYNC_CLOSING)) { + if (info->port.flags & ASYNC_CLOSING) interruptible_sleep_on(&info->close_wait); #ifdef MODEM_DO_RESTART - if (info->flags & ASYNC_HUP_NOTIFY) + if (info->port.flags & ASYNC_HUP_NOTIFY) return -EAGAIN; else return -ERESTARTSYS; @@ -1514,7 +1514,7 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * */ 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; } if (tty->termios->c_cflag & CLOCAL) @@ -1538,9 +1538,9 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * while (1) { set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || - !(info->flags & ASYNC_INITIALIZED)) { + !(info->port.flags & ASYNC_INITIALIZED)) { #ifdef MODEM_DO_RESTART - if (info->flags & ASYNC_HUP_NOTIFY) + if (info->port.flags & ASYNC_HUP_NOTIFY) retval = -EAGAIN; else retval = -ERESTARTSYS; @@ -1549,7 +1549,7 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * #endif break; } - if (!(info->flags & ASYNC_CLOSING) && + if (!(info->port.flags & ASYNC_CLOSING) && (do_clocal || (info->msr & UART_MSR_DCD))) { break; } @@ -1574,7 +1574,7 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * #endif if (retval) return retval; - info->flags |= ASYNC_NORMAL_ACTIVE; + info->port.flags |= ASYNC_NORMAL_ACTIVE; return 0; } @@ -1600,6 +1600,7 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp) info->count++; tty->driver_data = info; info->tty = tty; + tty->port = &info->port; /* * Start up serial port */ @@ -1664,7 +1665,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) #endif return; } - info->flags |= ASYNC_CLOSING; + info->port.flags |= ASYNC_CLOSING; tty->closing = 1; /* @@ -1673,7 +1674,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) * interrupt driver to stop checking the data ready bit in the * line status register. */ - if (info->flags & ASYNC_INITIALIZED) { + if (info->port.flags & ASYNC_INITIALIZED) { tty_wait_until_sent_from_close(tty, 3000); /* 30 seconds timeout */ /* * Before we drop DTR, make sure the UART transmitter @@ -1698,7 +1699,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) msleep_interruptible(500); wake_up_interruptible(&info->open_wait); } - info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); + info->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_close normal exit\n"); @@ -1717,7 +1718,7 @@ isdn_tty_hangup(struct tty_struct *tty) return; isdn_tty_shutdown(info); info->count = 0; - info->flags &= ~ASYNC_NORMAL_ACTIVE; + info->port.flags &= ~ASYNC_NORMAL_ACTIVE; info->tty = NULL; wake_up_interruptible(&info->open_wait); } @@ -1881,6 +1882,7 @@ isdn_tty_modem_init(void) goto err_unregister; } #endif + tty_port_init(&info->port); spin_lock_init(&info->readlock); sprintf(info->last_cause, "0000"); sprintf(info->last_num, "none"); @@ -2055,12 +2057,12 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup) #ifdef ISDN_DEBUG_MODEM_ICALL printk(KERN_DEBUG "m_fi: match1 wret=%d\n", wret); printk(KERN_DEBUG "m_fi: idx=%d flags=%08lx drv=%d ch=%d usg=%d\n", idx, - info->flags, info->isdn_driver, info->isdn_channel, - dev->usage[idx]); + info->port.flags, info->isdn_driver, + info->isdn_channel, dev->usage[idx]); #endif if ( #ifndef FIX_FILE_TRANSFER - (info->flags & ASYNC_NORMAL_ACTIVE) && + (info->port.flags & ASYNC_NORMAL_ACTIVE) && #endif (info->isdn_driver == -1) && (info->isdn_channel == -1) && @@ -2099,7 +2101,7 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup) return (wret == 2) ? 3 : 0; } -#define TTY_IS_ACTIVE(info) (info->flags & ASYNC_NORMAL_ACTIVE) +#define TTY_IS_ACTIVE(info) (info->port.flags & ASYNC_NORMAL_ACTIVE) int isdn_tty_stat_callback(int i, isdn_ctrl *c) @@ -2318,7 +2320,7 @@ isdn_tty_at_cout(char *msg, modem_info *info) spin_lock_irqsave(&info->readlock, flags); tty = info->tty; - if ((info->flags & ASYNC_CLOSING) || (!tty)) { + if ((info->port.flags & ASYNC_CLOSING) || (!tty)) { spin_unlock_irqrestore(&info->readlock, flags); return; } @@ -2468,13 +2470,13 @@ isdn_tty_modem_result(int code, modem_info *info) case RESULT_NO_CARRIER: #ifdef ISDN_DEBUG_MODEM_HUP printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n", - (info->flags & ASYNC_CLOSING), + (info->port.flags & ASYNC_CLOSING), (!info->tty)); #endif m->mdmreg[REG_RINGCNT] = 0; del_timer(&info->nc_timer); info->ncarrier = 0; - if ((info->flags & ASYNC_CLOSING) || (!info->tty)) + if ((info->port.flags & ASYNC_CLOSING) || (!info->tty)) return; #ifdef CONFIG_ISDN_AUDIO @@ -2607,10 +2609,10 @@ isdn_tty_modem_result(int code, modem_info *info) } } if (code == RESULT_NO_CARRIER) { - if ((info->flags & ASYNC_CLOSING) || (!info->tty)) + if ((info->port.flags & ASYNC_CLOSING) || (!info->tty)) return; - if (info->flags & ASYNC_CHECK_CD) + if (info->port.flags & ASYNC_CHECK_CD) tty_hangup(info->tty); } } diff --git a/include/linux/isdn.h b/include/linux/isdn.h index 63af3208004..bb710414f27 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -15,6 +15,7 @@ #define __ISDN_H__ #include +#include #define ISDN_MAX_DRIVERS 32 #define ISDN_MAX_CHANNELS 64 @@ -435,7 +436,7 @@ typedef struct atemu { /* Private data (similar to async_struct in ) */ typedef struct modem_info { int magic; - int flags; /* defined in tty.h */ + struct tty_port port; int x_char; /* xon/xoff character */ int mcr; /* Modem control register */ int msr; /* Modem status register */ -- cgit v1.2.3-70-g09d2 From c6e92b63d711c12ffb47f4dbb53902b7f26032e7 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:53:55 +0200 Subject: TTY: isdn, use open/close_wait from tty_port Hmm, the isdn ones were initialized twice. Signed-off-by: Jiri Slaby Cc: Karsten Keil Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/i4l/isdn_common.c | 2 -- drivers/isdn/i4l/isdn_tty.c | 16 +++++++--------- include/linux/isdn.h | 1 - 3 files changed, 7 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index d9f5524593f..2ffa0b73332 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -2327,8 +2327,6 @@ static int __init isdn_init(void) dev->chanmap[i] = -1; dev->m_idx[i] = -1; strcpy(dev->num[i], "???"); - init_waitqueue_head(&dev->mdm.info[i].open_wait); - init_waitqueue_head(&dev->mdm.info[i].close_wait); } if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) { printk(KERN_WARNING "isdn: Could not register control devices\n"); diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 8ba526dc98b..33764d052e1 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1498,7 +1498,7 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { if (info->port.flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); + interruptible_sleep_on(&info->port.close_wait); #ifdef MODEM_DO_RESTART if (info->port.flags & ASYNC_HUP_NOTIFY) return -EAGAIN; @@ -1527,7 +1527,7 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * * exit, either normal or abnormal. */ retval = 0; - add_wait_queue(&info->open_wait, &wait); + add_wait_queue(&info->port.open_wait, &wait); #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_block_til_ready before block: ttyi%d, count = %d\n", info->line, info->count); @@ -1564,7 +1564,7 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * schedule(); } current->state = TASK_RUNNING; - remove_wait_queue(&info->open_wait, &wait); + remove_wait_queue(&info->port.open_wait, &wait); if (!tty_hung_up_p(filp)) info->count++; info->blocked_open--; @@ -1697,10 +1697,10 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) tty->closing = 0; if (info->blocked_open) { msleep_interruptible(500); - wake_up_interruptible(&info->open_wait); + wake_up_interruptible(&info->port.open_wait); } info->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); + wake_up_interruptible(&info->port.close_wait); #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_close normal exit\n"); #endif @@ -1720,7 +1720,7 @@ isdn_tty_hangup(struct tty_struct *tty) info->count = 0; info->port.flags &= ~ASYNC_NORMAL_ACTIVE; info->tty = NULL; - wake_up_interruptible(&info->open_wait); + wake_up_interruptible(&info->port.open_wait); } /* This routine initializes all emulator-data. @@ -1898,8 +1898,6 @@ isdn_tty_modem_init(void) info->x_char = 0; info->count = 0; info->blocked_open = 0; - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); info->isdn_driver = -1; info->isdn_channel = -1; info->drv_index = -1; @@ -2194,7 +2192,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c) */ if (info->blocked_open && (info->emu.mdmreg[REG_DCD] & BIT_DCD)) { - wake_up_interruptible(&info->open_wait); + wake_up_interruptible(&info->port.open_wait); } /* Schedule CONNECT-Message to any tty diff --git a/include/linux/isdn.h b/include/linux/isdn.h index bb710414f27..c3ddf208190 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -483,7 +483,6 @@ typedef struct modem_info { #endif struct tty_struct *tty; /* Pointer to corresponding tty */ atemu emu; /* AT-emulator data */ - wait_queue_head_t open_wait, close_wait; spinlock_t readlock; } modem_info; -- cgit v1.2.3-70-g09d2 From 1b05f030a90569d9617d0fe42910f9e5c8cc59ec Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:53:56 +0200 Subject: TTY: isdn, use counts from tty_port blocked_open and count this time. Signed-off-by: Jiri Slaby Cc: Karsten Keil Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/i4l/isdn_tty.c | 43 +++++++++++++++++++++---------------------- include/linux/isdn.h | 2 -- 2 files changed, 21 insertions(+), 24 deletions(-) (limited to 'include/linux') diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 33764d052e1..c81a725fde7 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1533,8 +1533,8 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * info->line, info->count); #endif if (!(tty_hung_up_p(filp))) - info->count--; - info->blocked_open++; + info->port.count--; + info->port.blocked_open++; while (1) { set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || @@ -1559,18 +1559,18 @@ isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * } #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_block_til_ready blocking: ttyi%d, count = %d\n", - info->line, info->count); + info->line, info->port.count); #endif schedule(); } current->state = TASK_RUNNING; remove_wait_queue(&info->port.open_wait, &wait); if (!tty_hung_up_p(filp)) - info->count++; - info->blocked_open--; + info->port.count++; + info->port.blocked_open--; #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_block_til_ready after blocking: ttyi%d, count = %d\n", - info->line, info->count); + info->line, info->port.count); #endif if (retval) return retval; @@ -1595,9 +1595,9 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp) return -ENODEV; #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name, - info->count); + info->port.count); #endif - info->count++; + info->port.count++; tty->driver_data = info; info->tty = tty; tty->port = &info->port; @@ -1642,7 +1642,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) #endif return; } - 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 @@ -1651,15 +1651,15 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) * serial port won't be shutdown. */ printk(KERN_ERR "isdn_tty_close: bad 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 "isdn_tty_close: bad port count for ttyi%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) { #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_close after info->count != 0\n"); #endif @@ -1695,7 +1695,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) info->tty = NULL; info->ncarrier = 0; tty->closing = 0; - if (info->blocked_open) { + if (info->port.blocked_open) { msleep_interruptible(500); wake_up_interruptible(&info->port.open_wait); } @@ -1717,7 +1717,7 @@ isdn_tty_hangup(struct tty_struct *tty) if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_hangup")) return; isdn_tty_shutdown(info); - info->count = 0; + info->port.count = 0; info->port.flags &= ~ASYNC_NORMAL_ACTIVE; info->tty = NULL; wake_up_interruptible(&info->port.open_wait); @@ -1896,8 +1896,6 @@ isdn_tty_modem_init(void) info->line = i; info->tty = NULL; info->x_char = 0; - info->count = 0; - info->blocked_open = 0; info->isdn_driver = -1; info->isdn_channel = -1; info->drv_index = -1; @@ -2047,7 +2045,7 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup) for (i = 0; i < ISDN_MAX_CHANNELS; i++) { modem_info *info = &dev->mdm.info[i]; - if (info->count == 0) + if (info->port.count == 0) continue; if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) && /* SI1 is matching */ (info->emu.mdmreg[REG_SI2] == si2)) { /* SI2 is matching */ @@ -2190,7 +2188,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c) * for incoming call of this device when * DCD follow the state of incoming carrier */ - if (info->blocked_open && + if (info->port.blocked_open && (info->emu.mdmreg[REG_DCD] & BIT_DCD)) { wake_up_interruptible(&info->port.open_wait); } @@ -2200,7 +2198,8 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c) * set DCD-bit of its modem-status. */ if (TTY_IS_ACTIVE(info) || - (info->blocked_open && (info->emu.mdmreg[REG_DCD] & BIT_DCD))) { + (info->port.blocked_open && + (info->emu.mdmreg[REG_DCD] & BIT_DCD))) { info->msr |= UART_MSR_DCD; info->emu.charge = 0; if (info->dialing & 0xf) diff --git a/include/linux/isdn.h b/include/linux/isdn.h index c3ddf208190..a4b71fe20a6 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -442,8 +442,6 @@ typedef struct modem_info { int msr; /* Modem status register */ int lsr; /* Line status register */ int line; - int count; /* # of fd on device */ - int blocked_open; /* # of blocked opens */ int online; /* 1 = B-Channel is up, drop data */ /* 2 = B-Channel is up, deliver d.*/ int dialing; /* Dial in progress or ATA */ -- cgit v1.2.3-70-g09d2 From ba43294d51ac6491e60c2fc33a974a9a1002dfed Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:53:57 +0200 Subject: TTY: isdn, use tty from tty_port No recounting this time, just a plain switch. Signed-off-by: Jiri Slaby Cc: Karsten Keil Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/i4l/isdn_tty.c | 41 ++++++++++++++++++++--------------------- include/linux/isdn.h | 1 - 2 files changed, 20 insertions(+), 22 deletions(-) (limited to 'include/linux') diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index c81a725fde7..869885620c9 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -68,7 +68,7 @@ isdn_tty_try_read(modem_info *info, struct sk_buff *skb) if (!info->online) return 0; - tty = info->tty; + tty = info->port.tty; if (!tty) return 0; @@ -144,7 +144,7 @@ isdn_tty_readmodem(void) if ((info->vonline & 1) && (info->emu.vpar[1])) isdn_audio_eval_silence(info); #endif - tty = info->tty; + tty = info->port.tty; if (tty) { if (info->mcr & UART_MCR_RTS) { /* CISCO AsyncPPP Hack */ @@ -300,7 +300,7 @@ isdn_tty_tint(modem_info *info) len = skb->len; if ((slen = isdn_writebuf_skb_stub(info->isdn_driver, info->isdn_channel, 1, skb)) == len) { - struct tty_struct *tty = info->tty; + struct tty_struct *tty = info->port.tty; info->send_outstanding++; info->msr &= ~UART_MSR_CTS; info->lsr &= ~UART_LSR_TEMT; @@ -705,7 +705,7 @@ isdn_tty_modem_hup(modem_info *info, int local) printk(KERN_DEBUG "Mhup ttyI%d\n", info->line); #endif info->rcvsched = 0; - isdn_tty_flush_buffer(info->tty); + isdn_tty_flush_buffer(info->port.tty); if (info->online) { info->last_lhup = local; info->online = 0; @@ -1008,15 +1008,15 @@ isdn_tty_change_speed(modem_info *info) quot; int i; - if (!info->tty || !info->tty->termios) + if (!info->port.tty || !info->port.tty->termios) return; - cflag = info->tty->termios->c_cflag; + cflag = info->port.tty->termios->c_cflag; quot = i = cflag & CBAUD; if (i & CBAUDEX) { i &= ~CBAUDEX; if (i < 1 || i > 2) - info->tty->termios->c_cflag &= ~CBAUDEX; + info->port.tty->termios->c_cflag &= ~CBAUDEX; else i += 15; } @@ -1069,8 +1069,8 @@ isdn_tty_startup(modem_info *info) * Now, initialize the UART */ info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2; - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->port.tty) + clear_bit(TTY_IO_ERROR, &info->port.tty->flags); /* * and set the speed of the serial port */ @@ -1096,7 +1096,7 @@ isdn_tty_shutdown(modem_info *info) #endif isdn_unlock_drivers(); info->msr &= ~UART_MSR_RI; - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { + if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) { info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS); if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) { isdn_tty_modem_reset_regs(info, 0); @@ -1106,8 +1106,8 @@ isdn_tty_shutdown(modem_info *info) isdn_tty_modem_hup(info, 1); } } - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->port.tty) + set_bit(TTY_IO_ERROR, &info->port.tty->flags); info->port.flags &= ~ASYNC_INITIALIZED; } @@ -1599,7 +1599,7 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp) #endif info->port.count++; tty->driver_data = info; - info->tty = tty; + info->port.tty = tty; tty->port = &info->port; /* * Start up serial port @@ -1692,7 +1692,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) isdn_tty_shutdown(info); isdn_tty_flush_buffer(tty); tty_ldisc_flush(tty); - info->tty = NULL; + info->port.tty = NULL; info->ncarrier = 0; tty->closing = 0; if (info->port.blocked_open) { @@ -1719,7 +1719,7 @@ isdn_tty_hangup(struct tty_struct *tty) isdn_tty_shutdown(info); info->port.count = 0; info->port.flags &= ~ASYNC_NORMAL_ACTIVE; - info->tty = NULL; + info->port.tty = NULL; wake_up_interruptible(&info->port.open_wait); } @@ -1894,7 +1894,6 @@ isdn_tty_modem_init(void) isdn_tty_modem_reset_regs(info, 1); info->magic = ISDN_ASYNC_MAGIC; info->line = i; - info->tty = NULL; info->x_char = 0; info->isdn_driver = -1; info->isdn_channel = -1; @@ -2316,7 +2315,7 @@ isdn_tty_at_cout(char *msg, modem_info *info) l = strlen(msg); spin_lock_irqsave(&info->readlock, flags); - tty = info->tty; + tty = info->port.tty; if ((info->port.flags & ASYNC_CLOSING) || (!tty)) { spin_unlock_irqrestore(&info->readlock, flags); return; @@ -2468,12 +2467,12 @@ isdn_tty_modem_result(int code, modem_info *info) #ifdef ISDN_DEBUG_MODEM_HUP printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n", (info->port.flags & ASYNC_CLOSING), - (!info->tty)); + (!info->port.tty)); #endif m->mdmreg[REG_RINGCNT] = 0; del_timer(&info->nc_timer); info->ncarrier = 0; - if ((info->port.flags & ASYNC_CLOSING) || (!info->tty)) + if ((info->port.flags & ASYNC_CLOSING) || (!info->port.tty)) return; #ifdef CONFIG_ISDN_AUDIO @@ -2606,11 +2605,11 @@ isdn_tty_modem_result(int code, modem_info *info) } } if (code == RESULT_NO_CARRIER) { - if ((info->port.flags & ASYNC_CLOSING) || (!info->tty)) + if ((info->port.flags & ASYNC_CLOSING) || (!info->port.tty)) return; if (info->port.flags & ASYNC_CHECK_CD) - tty_hangup(info->tty); + tty_hangup(info->port.tty); } } diff --git a/include/linux/isdn.h b/include/linux/isdn.h index a4b71fe20a6..95883ac5a2f 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -479,7 +479,6 @@ typedef struct modem_info { struct T30_s *fax; /* T30 Fax Group 3 data/interface */ int faxonline; /* Fax-channel status */ #endif - struct tty_struct *tty; /* Pointer to corresponding tty */ atemu emu; /* AT-emulator data */ spinlock_t readlock; } modem_info; -- cgit v1.2.3-70-g09d2 From 82e46b31908244678a6e7404c4204dd3f6fea9f0 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:53:58 +0200 Subject: TTY: isdn, use xmit_buf from tty_port Signed-off-by: Jiri Slaby Cc: Karsten Keil Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/i4l/isdn_tty.c | 16 +++++++++------- include/linux/isdn.h | 1 - 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 869885620c9..dfb83e68bd8 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -333,7 +333,7 @@ isdn_tty_countDLE(unsigned char *buf, int len) static int isdn_tty_handleDLEdown(modem_info *info, atemu *m, int len) { - unsigned char *p = &info->xmit_buf[info->xmit_count]; + unsigned char *p = &info->port.xmit_buf[info->xmit_count]; int count = 0; while (len > 0) { @@ -477,7 +477,7 @@ isdn_tty_senddown(modem_info *info) return; } skb_reserve(skb, skb_res); - memcpy(skb_put(skb, buflen), info->xmit_buf, buflen); + memcpy(skb_put(skb, buflen), info->port.xmit_buf, buflen); info->xmit_count = 0; #ifdef CONFIG_ISDN_AUDIO if (info->vonline & 2) { @@ -1152,7 +1152,7 @@ isdn_tty_write(struct tty_struct *tty, const u_char *buf, int count) isdn_tty_check_esc(buf, m->mdmreg[REG_ESC], c, &(m->pluscount), &(m->lastplus)); - memcpy(&(info->xmit_buf[info->xmit_count]), buf, c); + memcpy(&info->port.xmit_buf[info->xmit_count], buf, c); #ifdef CONFIG_ISDN_AUDIO if (info->vonline) { int cc = isdn_tty_handleDLEdown(info, m, c); @@ -1906,13 +1906,15 @@ isdn_tty_modem_init(void) #ifdef CONFIG_ISDN_AUDIO skb_queue_head_init(&info->dtmf_queue); #endif - if (!(info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5, GFP_KERNEL))) { + info->port.xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5, + GFP_KERNEL); + if (!info->port.xmit_buf) { printk(KERN_ERR "Could not allocate modem xmit-buffer\n"); retval = -ENOMEM; goto err_unregister; } /* Make room for T.70 header */ - info->xmit_buf += 4; + info->port.xmit_buf += 4; } return 0; err_unregister: @@ -1921,7 +1923,7 @@ err_unregister: #ifdef CONFIG_ISDN_TTY_FAX kfree(info->fax); #endif - kfree(info->xmit_buf - 4); + kfree(info->port.xmit_buf - 4); } tty_unregister_driver(m->tty_modem); err: @@ -1942,7 +1944,7 @@ isdn_tty_exit(void) #ifdef CONFIG_ISDN_TTY_FAX kfree(info->fax); #endif - kfree(info->xmit_buf - 4); + kfree(info->port.xmit_buf - 4); } tty_unregister_driver(dev->mdm.tty_modem); put_tty_driver(dev->mdm.tty_modem); diff --git a/include/linux/isdn.h b/include/linux/isdn.h index 95883ac5a2f..215c41602af 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -461,7 +461,6 @@ typedef struct modem_info { int send_outstanding;/* # of outstanding send-requests */ int xmit_size; /* max. # of chars in xmit_buf */ int xmit_count; /* # of chars in xmit_buf */ - unsigned char *xmit_buf; /* transmit buffer */ struct sk_buff_head xmit_queue; /* transmit queue */ atomic_t xmit_lock; /* Semaphore for isdn_tty_write */ #ifdef CONFIG_ISDN_AUDIO -- cgit v1.2.3-70-g09d2 From bf03f65b7967df5807ddef7b99f8a41d4c94fc70 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 10 Apr 2012 14:10:53 -0700 Subject: tegra, serial8250: add ->handle_break() uart_port op The "KT" serial port has another use case for a "received break" quirk, so before adding another special case to the 8250 core take this opportunity to push such quirks out of the core and into a uart_port op. Stephen says: "If the callback function is to no longer live in 8250.c itself, arch/arm/mach-tegra/devices.c isn't logically a good place to put it, and that file will be going away once we get rid of all the board files and move solely to device tree." ...so since 8250_pci.c houses all the quirks for pci serial devices this quirk is similarly housed in of_serial.c. Once the open firmware conversion completes the infrastructure details (include/linux/of_serial.h, and the export) can all be removed to make this self contained to of_serial.c. Cc: Nhan H Mai Cc: Colin Cross Cc: Olof Johansson [stephen: kill CONFIG_SERIAL_TEGRA in favor just using CONFIG_ARCH_TEGRA] Cc: Grant Likely Acked-by: Arnd Bergmann Acked-by: Sudhakar Mamillapalli Reported-by: Alan Cox Acked-by: Alan Cox Signed-off-by: Dan Williams Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-tegra/board-harmony.c | 2 ++ arch/arm/mach-tegra/board-paz00.c | 3 +++ arch/arm/mach-tegra/board-seaboard.c | 2 ++ arch/arm/mach-tegra/board-trimslice.c | 2 ++ drivers/tty/serial/8250/8250.c | 34 +++------------------------------- drivers/tty/serial/of_serial.c | 26 ++++++++++++++++++++++++++ include/linux/of_serial.h | 17 +++++++++++++++++ include/linux/serial_8250.h | 1 + include/linux/serial_core.h | 5 +++++ 9 files changed, 61 insertions(+), 31 deletions(-) create mode 100644 include/linux/of_serial.h (limited to 'include/linux') diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c index c00aadb01e0..222182e0022 100644 --- a/arch/arm/mach-tegra/board-harmony.c +++ b/arch/arm/mach-tegra/board-harmony.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = { .irq = INT_UARTD, .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, .type = PORT_TEGRA, + .handle_break = tegra_serial_handle_break, .iotype = UPIO_MEM, .regshift = 2, .uartclk = 216000000, diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c index 330afdfa247..d0735c70d68 100644 --- a/arch/arm/mach-tegra/board-paz00.c +++ b/arch/arm/mach-tegra/board-paz00.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = { .irq = INT_UARTA, .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, .type = PORT_TEGRA, + .handle_break = tegra_serial_handle_break, .iotype = UPIO_MEM, .regshift = 2, .uartclk = 216000000, @@ -65,6 +67,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = { .irq = INT_UARTC, .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, .type = PORT_TEGRA, + .handle_break = tegra_serial_handle_break, .iotype = UPIO_MEM, .regshift = 2, .uartclk = 216000000, diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c index d669847f048..5b687b8258c 100644 --- a/arch/arm/mach-tegra/board-seaboard.c +++ b/arch/arm/mach-tegra/board-seaboard.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = { /* Memory and IRQ filled in before registration */ .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, .type = PORT_TEGRA, + .handle_break = tegra_serial_handle_break, .iotype = UPIO_MEM, .regshift = 2, .uartclk = 216000000, diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c index cd52820a3e3..f7358586b52 100644 --- a/arch/arm/mach-tegra/board-trimslice.c +++ b/arch/arm/mach-tegra/board-trimslice.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = { .irq = INT_UARTA, .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, .type = PORT_TEGRA, + .handle_break = tegra_serial_handle_break, .iotype = UPIO_MEM, .regshift = 2, .uartclk = 216000000, diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index 5b149b466ec..dffd623b797 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -1331,27 +1331,6 @@ static void serial8250_enable_ms(struct uart_port *port) serial_port_out(port, UART_IER, up->ier); } -/* - * Clear the Tegra rx fifo after a break - * - * FIXME: This needs to become a port specific callback once we have a - * framework for this - */ -static void clear_rx_fifo(struct uart_8250_port *up) -{ - unsigned int status, tmout = 10000; - do { - status = serial_in(up, UART_LSR); - if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) - status = serial_in(up, UART_RX); - else - break; - if (--tmout == 0) - break; - udelay(1); - } while (1); -} - /* * serial8250_rx_chars: processes according to the passed in LSR * value, and returns the remaining LSR bits not handled @@ -1386,19 +1365,9 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) up->lsr_saved_flags = 0; if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { - /* - * For statistics only - */ if (lsr & UART_LSR_BI) { lsr &= ~(UART_LSR_FE | UART_LSR_PE); port->icount.brk++; - /* - * If tegra port then clear the rx fifo to - * accept another break/character. - */ - if (port->type == PORT_TEGRA) - clear_rx_fifo(up); - /* * We do the SysRQ and SAK checking * here because otherwise the break @@ -3037,6 +3006,7 @@ static int __devinit serial8250_probe(struct platform_device *dev) port.serial_in = p->serial_in; port.serial_out = p->serial_out; port.handle_irq = p->handle_irq; + port.handle_break = p->handle_break; port.set_termios = p->set_termios; port.pm = p->pm; port.dev = &dev->dev; @@ -3209,6 +3179,8 @@ int serial8250_register_port(struct uart_port *port) uart->port.set_termios = port->set_termios; if (port->pm) uart->port.pm = port->pm; + if (port->handle_break) + uart->port.handle_break = port->handle_break; if (serial8250_isa_config != NULL) serial8250_isa_config(0, &uart->port, diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index e8c9cee07d0..5410c063726 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -12,10 +12,13 @@ #include #include #include +#include #include #include +#include #include #include +#include #include #include @@ -24,6 +27,26 @@ struct of_serial_info { int line; }; +#ifdef CONFIG_ARCH_TEGRA +void tegra_serial_handle_break(struct uart_port *p) +{ + unsigned int status, tmout = 10000; + + do { + status = p->serial_in(p, UART_LSR); + if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) + status = p->serial_in(p, UART_RX); + else + break; + if (--tmout == 0) + break; + udelay(1); + } while (1); +} +/* FIXME remove this export when tegra finishes conversion to open firmware */ +EXPORT_SYMBOL_GPL(tegra_serial_handle_break); +#endif + /* * Fill a struct uart_port for a given device node */ @@ -84,6 +107,9 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev, | UPF_FIXED_PORT | UPF_FIXED_TYPE; port->dev = &ofdev->dev; + if (type == PORT_TEGRA) + port->handle_break = tegra_serial_handle_break; + return 0; } diff --git a/include/linux/of_serial.h b/include/linux/of_serial.h new file mode 100644 index 00000000000..4a73ed80b4c --- /dev/null +++ b/include/linux/of_serial.h @@ -0,0 +1,17 @@ +#ifndef __LINUX_OF_SERIAL_H +#define __LINUX_OF_SERIAL_H + +/* + * FIXME remove this file when tegra finishes conversion to open firmware, + * expectation is that all quirks will then be self-contained in + * drivers/tty/serial/of_serial.c. + */ +#ifdef CONFIG_ARCH_TEGRA +extern void tegra_serial_handle_break(struct uart_port *port); +#else +static inline void tegra_serial_handle_break(struct uart_port *port) +{ +} +#endif + +#endif /* __LINUX_OF_SERIAL */ diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 8f012f8ac8e..a522fd977aa 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -38,6 +38,7 @@ struct plat_serial8250_port { int (*handle_irq)(struct uart_port *); void (*pm)(struct uart_port *, unsigned int state, unsigned old); + void (*handle_break)(struct uart_port *); }; /* diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index f51bf2e70c6..0dd752f3039 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -310,6 +310,7 @@ struct uart_port { int (*handle_irq)(struct uart_port *); void (*pm)(struct uart_port *, unsigned int state, unsigned int old); + void (*handle_break)(struct uart_port *); unsigned int irq; /* irq number */ unsigned long irqflags; /* irq flags */ unsigned int uartclk; /* base uart clock */ @@ -533,6 +534,10 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) static inline int uart_handle_break(struct uart_port *port) { struct uart_state *state = port->state; + + if (port->handle_break) + port->handle_break(port); + #ifdef SUPPORT_SYSRQ if (port->cons && port->cons->index == port->line) { if (!port->sysrq) { -- cgit v1.2.3-70-g09d2 From 5d1a33fa5573702394a4d09a9872f3f930c06d58 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 24 Apr 2012 11:06:06 +0100 Subject: vt: push the tty_lock down into the map handling When we do this it becomes clear the lock we should be holding is the vc lock, and in fact many of our other helpers are properly invoked this way. We don't at this point guarantee not to race the keyboard code but the results of that appear harmless and that was true before we started as well. We now have no users of tty_lock in the console driver... Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/consolemap.c | 123 ++++++++++++++++++++++++++++++++------------ drivers/tty/vt/vt_ioctl.c | 25 ++------- include/linux/vt_kern.h | 1 - 3 files changed, 96 insertions(+), 53 deletions(-) (limited to 'include/linux') diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c index 8308fc7cdc2..2aaa0c22840 100644 --- a/drivers/tty/vt/consolemap.c +++ b/drivers/tty/vt/consolemap.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -312,6 +313,7 @@ int con_set_trans_old(unsigned char __user * arg) if (!access_ok(VERIFY_READ, arg, E_TABSZ)) return -EFAULT; + console_lock(); for (i=0; ivc_uni_pagedir_loc; - if (p && p->readonly) return -EIO; + if (p && p->readonly) + return -EIO; + if (!p || --p->refcount) { q = kzalloc(sizeof(*p), GFP_KERNEL); if (!q) { - if (p) p->refcount++; + if (p) + p->refcount++; return -ENOMEM; } q->refcount=1; @@ -511,23 +525,43 @@ int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui) return 0; } +int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui) +{ + int ret; + console_lock(); + ret = con_do_clear_unimap(vc, ui); + console_unlock(); + return ret; +} + int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) { int err = 0, err1, i; struct uni_pagedir *p, *q; + console_lock(); + /* Save original vc_unipagdir_loc in case we allocate a new one */ p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; - if (p->readonly) return -EIO; + if (p->readonly) { + console_unlock(); + return -EIO; + } - if (!ct) return 0; + if (!ct) { + console_unlock(); + return 0; + } if (p->refcount > 1) { int j, k; u16 **p1, *p2, l; - err1 = con_clear_unimap(vc, NULL); - if (err1) return err1; + err1 = con_do_clear_unimap(vc, NULL); + if (err1) { + console_unlock(); + return err1; + } /* * Since refcount was > 1, con_clear_unimap() allocated a @@ -558,7 +592,8 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) *vc->vc_uni_pagedir_loc = (unsigned long)p; con_release_unimap(q); kfree(q); - return err1; + console_unlock(); + return err1; } } } else { @@ -592,21 +627,30 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) /* * Merge with fontmaps of any other virtual consoles. */ - if (con_unify_unimap(vc, p)) + if (con_unify_unimap(vc, p)) { + console_unlock(); return err; + } for (i = 0; i <= 3; i++) set_inverse_transl(vc, p, i); /* Update inverse translations */ set_inverse_trans_unicode(vc, p); - + + console_unlock(); return err; } -/* Loads the unimap for the hardware font, as defined in uni_hash.tbl. - The representation used was the most compact I could come up - with. This routine is executed at sys_setup time, and when the - PIO_FONTRESET ioctl is called. */ - +/** + * con_set_default_unimap - set default unicode map + * @vc: the console we are updating + * + * Loads the unimap for the hardware font, as defined in uni_hash.tbl. + * The representation used was the most compact I could come up + * with. This routine is executed at video setup, and when the + * PIO_FONTRESET ioctl is called. + * + * The caller must hold the console lock + */ int con_set_default_unimap(struct vc_data *vc) { int i, j, err = 0, err1; @@ -617,6 +661,7 @@ int con_set_default_unimap(struct vc_data *vc) p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; if (p == dflt) return 0; + dflt->refcount++; *vc->vc_uni_pagedir_loc = (unsigned long)dflt; if (p && !--p->refcount) { @@ -628,8 +673,9 @@ int con_set_default_unimap(struct vc_data *vc) /* The default font is always 256 characters */ - err = con_clear_unimap(vc, NULL); - if (err) return err; + err = con_do_clear_unimap(vc, NULL); + if (err) + return err; p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; q = dfont_unitable; @@ -654,6 +700,13 @@ int con_set_default_unimap(struct vc_data *vc) } EXPORT_SYMBOL(con_set_default_unimap); +/** + * con_copy_unimap - copy unimap between two vts + * @dst_vc: target + * @src_vt: source + * + * The caller must hold the console lock when invoking this method + */ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc) { struct uni_pagedir *q; @@ -668,13 +721,23 @@ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc) *dst_vc->vc_uni_pagedir_loc = (long)q; return 0; } +EXPORT_SYMBOL(con_copy_unimap); +/** + * con_get_unimap - get the unicode map + * @vc: the console to read from + * + * Read the console unicode data for this console. Called from the ioctl + * handlers. + */ int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list) { int i, j, k, ect; u16 **p1, *p2; struct uni_pagedir *p; + console_lock(); + ect = 0; if (*vc->vc_uni_pagedir_loc) { p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; @@ -694,22 +757,19 @@ int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct uni } } __put_user(ect, uct); + console_unlock(); return ((ect <= ct) ? 0 : -ENOMEM); } -void con_protect_unimap(struct vc_data *vc, int rdonly) -{ - struct uni_pagedir *p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; - - if (p) - p->readonly = rdonly; -} - /* * Always use USER_MAP. These functions are used by the keyboard, * which shouldn't be affected by G0/G1 switching, etc. * If the user map still contains default values, i.e. the * direct-to-font mapping, then assume user is using Latin1. + * + * FIXME: at some point we need to decide if we want to lock the table + * update element itself via the keyboard_event_lock for consistency with the + * keyboard driver as well as the consoles */ /* may be called during an interrupt */ u32 conv_8bit_to_uni(unsigned char c) @@ -777,4 +837,3 @@ console_map_init(void) con_set_default_unimap(vc_cons[i].d); } -EXPORT_SYMBOL(con_copy_unimap); diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index ede2ef18d2f..64618547be1 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -910,7 +910,9 @@ int vt_ioctl(struct tty_struct *tty, ret = con_font_op(vc_cons[fg_console].d, &op); if (ret) break; + console_lock(); con_set_default_unimap(vc_cons[fg_console].d); + console_unlock(); break; } #endif @@ -934,33 +936,23 @@ int vt_ioctl(struct tty_struct *tty, case PIO_SCRNMAP: if (!perm) ret = -EPERM; - else { - tty_lock(); + else ret = con_set_trans_old(up); - tty_unlock(); - } break; case GIO_SCRNMAP: - tty_lock(); ret = con_get_trans_old(up); - tty_unlock(); break; case PIO_UNISCRNMAP: if (!perm) ret = -EPERM; - else { - tty_lock(); + else ret = con_set_trans_new(up); - tty_unlock(); - } break; case GIO_UNISCRNMAP: - tty_lock(); ret = con_get_trans_new(up); - tty_unlock(); break; case PIO_UNIMAPCLR: @@ -970,19 +962,14 @@ int vt_ioctl(struct tty_struct *tty, ret = copy_from_user(&ui, up, sizeof(struct unimapinit)); if (ret) ret = -EFAULT; - else { - tty_lock(); + else con_clear_unimap(vc, &ui); - tty_unlock(); - } break; } case PIO_UNIMAP: case GIO_UNIMAP: - tty_lock(); ret = do_unimap_ioctl(cmd, up, perm, vc); - tty_unlock(); break; case VT_LOCKSWITCH: @@ -1196,9 +1183,7 @@ long vt_compat_ioctl(struct tty_struct *tty, case PIO_UNIMAP: case GIO_UNIMAP: - tty_lock(); ret = compat_unimap_ioctl(cmd, up, perm, vc); - tty_unlock(); break; /* diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index e33d77f15bd..50ae7d0c279 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h @@ -70,7 +70,6 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list); int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list); int con_set_default_unimap(struct vc_data *vc); void con_free_unimap(struct vc_data *vc); -void con_protect_unimap(struct vc_data *vc, int rdonly); int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc); #define vc_translate(vc, c) ((vc)->vc_translate[(c) | \ -- cgit v1.2.3-70-g09d2 From f73fa05b90eb8c0dd3230c364cf1107f4f8f3848 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 2 May 2012 21:47:27 +0900 Subject: serial8250: Introduce serial8250_register_8250_port() Introduce yet another 8250 registration function. This time it is serial8250_register_8250_port() and it allows us to register 8250 hardware instances using struct uart_8250_port. The new function makes it possible to register 8250 hardware that makes use of 8250 specific callbacks such as ->dl_read() and ->dl_write(). Signed-off-by: Magnus Damm Acked-by: Arnd Bergmann Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.c | 91 +++++++++++++++++++++++++++--------------- include/linux/serial_8250.h | 1 + 2 files changed, 60 insertions(+), 32 deletions(-) (limited to 'include/linux') diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index 662188d6cdd..47d061b9ad4 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -3112,7 +3112,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port * } /** - * serial8250_register_port - register a serial port + * serial8250_register_8250_port - register a serial port * @port: serial port template * * Configure the serial port specified by the request. If the @@ -3124,52 +3124,56 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port * * * On success the port is ready to use and the line number is returned. */ -int serial8250_register_port(struct uart_port *port) +int serial8250_register_8250_port(struct uart_8250_port *up) { struct uart_8250_port *uart; int ret = -ENOSPC; - if (port->uartclk == 0) + if (up->port.uartclk == 0) return -EINVAL; mutex_lock(&serial_mutex); - uart = serial8250_find_match_or_unused(port); + uart = serial8250_find_match_or_unused(&up->port); if (uart) { uart_remove_one_port(&serial8250_reg, &uart->port); - uart->port.iobase = port->iobase; - uart->port.membase = port->membase; - uart->port.irq = port->irq; - uart->port.irqflags = port->irqflags; - uart->port.uartclk = port->uartclk; - uart->port.fifosize = port->fifosize; - uart->port.regshift = port->regshift; - uart->port.iotype = port->iotype; - uart->port.flags = port->flags | UPF_BOOT_AUTOCONF; - uart->port.mapbase = port->mapbase; - uart->port.private_data = port->private_data; - if (port->dev) - uart->port.dev = port->dev; - - if (port->flags & UPF_FIXED_TYPE) - serial8250_init_fixed_type_port(uart, port->type); + uart->port.iobase = up->port.iobase; + uart->port.membase = up->port.membase; + uart->port.irq = up->port.irq; + uart->port.irqflags = up->port.irqflags; + uart->port.uartclk = up->port.uartclk; + uart->port.fifosize = up->port.fifosize; + uart->port.regshift = up->port.regshift; + uart->port.iotype = up->port.iotype; + uart->port.flags = up->port.flags | UPF_BOOT_AUTOCONF; + uart->port.mapbase = up->port.mapbase; + uart->port.private_data = up->port.private_data; + if (up->port.dev) + uart->port.dev = up->port.dev; + + if (up->port.flags & UPF_FIXED_TYPE) + serial8250_init_fixed_type_port(uart, up->port.type); set_io_from_upio(&uart->port); /* Possibly override default I/O functions. */ - if (port->serial_in) - uart->port.serial_in = port->serial_in; - if (port->serial_out) - uart->port.serial_out = port->serial_out; - if (port->handle_irq) - uart->port.handle_irq = port->handle_irq; + if (up->port.serial_in) + uart->port.serial_in = up->port.serial_in; + if (up->port.serial_out) + uart->port.serial_out = up->port.serial_out; + if (up->port.handle_irq) + uart->port.handle_irq = up->port.handle_irq; /* Possibly override set_termios call */ - if (port->set_termios) - uart->port.set_termios = port->set_termios; - if (port->pm) - uart->port.pm = port->pm; - if (port->handle_break) - uart->port.handle_break = port->handle_break; + if (up->port.set_termios) + uart->port.set_termios = up->port.set_termios; + if (up->port.pm) + uart->port.pm = up->port.pm; + if (up->port.handle_break) + uart->port.handle_break = up->port.handle_break; + if (up->dl_read) + uart->dl_read = up->dl_read; + if (up->dl_write) + uart->dl_write = up->dl_write; if (serial8250_isa_config != NULL) serial8250_isa_config(0, &uart->port, @@ -3183,6 +3187,29 @@ int serial8250_register_port(struct uart_port *port) return ret; } +EXPORT_SYMBOL(serial8250_register_8250_port); + +/** + * serial8250_register_port - register a serial port + * @port: serial port template + * + * Configure the serial port specified by the request. If the + * port exists and is in use, it is hung up and unregistered + * first. + * + * The port is then probed and if necessary the IRQ is autodetected + * If this fails an error is returned. + * + * On success the port is ready to use and the line number is returned. + */ +int serial8250_register_port(struct uart_port *port) +{ + struct uart_8250_port up; + + memset(&up, 0, sizeof(up)); + memcpy(&up.port, port, sizeof(*port)); + return serial8250_register_8250_port(&up); +} EXPORT_SYMBOL(serial8250_register_port); /** diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index a522fd977aa..10dbce5205a 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -69,6 +69,7 @@ enum { struct uart_port; struct uart_8250_port; +int serial8250_register_8250_port(struct uart_8250_port *); int serial8250_register_port(struct uart_port *); void serial8250_unregister_port(int line); void serial8250_suspend_port(int line); -- cgit v1.2.3-70-g09d2 From d29f3ef39be4eec0362b985305fc526d9be318cf Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 3 May 2012 22:24:08 +0100 Subject: tty_lock: Localise the lock In each remaining case the tty_lock is associated with a specific tty. This means we can now lock on a per tty basis. We do need tty_lock_pair() for the pty case. Uglier but still a step in the right direction. [fixed up calls in 3 missing drivers - gregkh] Signed-off-by: Alan Cox Acked-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/serial/68360serial.c | 4 +-- drivers/tty/amiserial.c | 12 +++---- drivers/tty/cyclades.c | 2 +- drivers/tty/n_r3964.c | 11 +++--- drivers/tty/pty.c | 23 +++++++------ drivers/tty/serial/crisv10.c | 4 +-- drivers/tty/synclink.c | 4 +-- drivers/tty/synclink_gt.c | 4 +-- drivers/tty/synclinkmp.c | 4 +-- drivers/tty/tty_io.c | 67 +++++++++++++++++++++--------------- drivers/tty/tty_ldisc.c | 30 ++++++++-------- drivers/tty/tty_mutex.c | 60 ++++++++++++++++++++++++-------- drivers/tty/tty_port.c | 6 ++-- include/linux/tty.h | 23 ++++++++----- net/bluetooth/rfcomm/tty.c | 4 +-- 15 files changed, 155 insertions(+), 103 deletions(-) (limited to 'include/linux') diff --git a/drivers/staging/serial/68360serial.c b/drivers/staging/serial/68360serial.c index daf0b1d0dc2..23ee50e25e4 100644 --- a/drivers/staging/serial/68360serial.c +++ b/drivers/staging/serial/68360serial.c @@ -1859,9 +1859,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, printk("block_til_ready blocking: ttys%d, count = %d\n", info->line, state->count); #endif - tty_unlock(); + tty_unlock(tty); schedule(); - tty_lock(); + tty_lock(tty); } current->state = TASK_RUNNING; remove_wait_queue(&info->open_wait, &wait); diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 6cc4358f68c..b88a65c4924 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -1033,7 +1033,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state, if (!retinfo) return -EFAULT; memset(&tmp, 0, sizeof(tmp)); - tty_lock(); + tty_lock(tty); tmp.line = tty->index; tmp.port = state->port; tmp.flags = state->tport.flags; @@ -1042,7 +1042,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state, tmp.close_delay = state->tport.close_delay; tmp.closing_wait = state->tport.closing_wait; tmp.custom_divisor = state->custom_divisor; - tty_unlock(); + tty_unlock(tty); if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) return -EFAULT; return 0; @@ -1059,12 +1059,12 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) return -EFAULT; - tty_lock(); + tty_lock(tty); change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) || new_serial.custom_divisor != state->custom_divisor; if (new_serial.irq || new_serial.port != state->port || new_serial.xmit_fifo_size != state->xmit_fifo_size) { - tty_unlock(); + tty_unlock(tty); return -EINVAL; } @@ -1084,7 +1084,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, } if (new_serial.baud_base < 9600) { - tty_unlock(); + tty_unlock(tty); return -EINVAL; } @@ -1116,7 +1116,7 @@ check_and_exit: } } else retval = startup(tty, state); - tty_unlock(); + tty_unlock(tty); return retval; } diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index e61cabdd69d..6984e1a2686 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -1599,7 +1599,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp) * If the port is the middle of closing, bail out now */ if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { - wait_event_interruptible_tty(info->port.close_wait, + wait_event_interruptible_tty(tty, info->port.close_wait, !(info->port.flags & ASYNC_CLOSING)); return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; } diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c index 5c6c31459a2..656ad93bbc9 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c @@ -1065,7 +1065,8 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, TRACE_L("read()"); - tty_lock(); + /* FIXME: should use a private lock */ + tty_lock(tty); pClient = findClient(pInfo, task_pid(current)); if (pClient) { @@ -1077,7 +1078,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, goto unlock; } /* block until there is a message: */ - wait_event_interruptible_tty(pInfo->read_wait, + wait_event_interruptible_tty(tty, pInfo->read_wait, (pMsg = remove_msg(pInfo, pClient))); } @@ -1107,7 +1108,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, } ret = -EPERM; unlock: - tty_unlock(); + tty_unlock(tty); return ret; } @@ -1156,7 +1157,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, pHeader->locks = 0; pHeader->owner = NULL; - tty_lock(); + tty_lock(tty); pClient = findClient(pInfo, task_pid(current)); if (pClient) { @@ -1175,7 +1176,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, add_tx_queue(pInfo, pHeader); trigger_transmit(pInfo); - tty_unlock(); + tty_unlock(tty); return 0; } diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 5505ffc91da..d6fa8429f3f 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -47,6 +47,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp) wake_up_interruptible(&tty->read_wait); wake_up_interruptible(&tty->write_wait); tty->packet = 0; + /* Review - krefs on tty_link ?? */ if (!tty->link) return; tty->link->packet = 0; @@ -62,9 +63,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp) mutex_unlock(&devpts_mutex); } #endif - tty_unlock(); tty_vhangup(tty->link); - tty_lock(); } } @@ -622,26 +621,29 @@ static int ptmx_open(struct inode *inode, struct file *filp) return retval; /* find a device that is not in use. */ - tty_lock(); + mutex_lock(&devpts_mutex); index = devpts_new_index(inode); - tty_unlock(); if (index < 0) { retval = index; goto err_file; } + mutex_unlock(&devpts_mutex); + mutex_lock(&tty_mutex); mutex_lock(&devpts_mutex); tty = tty_init_dev(ptm_driver, index); - mutex_unlock(&devpts_mutex); - tty_lock(); - mutex_unlock(&tty_mutex); if (IS_ERR(tty)) { retval = PTR_ERR(tty); goto out; } + /* The tty returned here is locked so we can safely + drop the mutex */ + mutex_unlock(&devpts_mutex); + mutex_unlock(&tty_mutex); + set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ tty_add_file(tty, filp); @@ -654,16 +656,17 @@ static int ptmx_open(struct inode *inode, struct file *filp) if (retval) goto err_release; - tty_unlock(); + tty_unlock(tty); return 0; err_release: - tty_unlock(); + tty_unlock(tty); tty_release(inode, filp); return retval; out: + mutex_unlock(&tty_mutex); devpts_kill_index(inode, index); - tty_unlock(); err_file: + mutex_unlock(&devpts_mutex); tty_free_file(filp); return retval; } diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index 80b6b1b1f72..b431a5164f4 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -4052,9 +4052,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp, printk("block_til_ready blocking: ttyS%d, count = %d\n", info->line, info->count); #endif - tty_unlock(); + tty_unlock(tty); schedule(); - tty_lock(); + tty_lock(tty); } set_current_state(TASK_RUNNING); remove_wait_queue(&info->open_wait, &wait); diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index 593d40ad0a6..5ed0daae656 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c @@ -3338,9 +3338,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, printk("%s(%d):block_til_ready blocking on %s count=%d\n", __FILE__,__LINE__, tty->driver->name, port->count ); - tty_unlock(); + tty_unlock(tty); schedule(); - tty_lock(); + tty_lock(tty); } set_current_state(TASK_RUNNING); diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index aa1debf97cc..45b43f11ca3 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -3336,9 +3336,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, } DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); - tty_unlock(); + tty_unlock(tty); schedule(); - tty_lock(); + tty_lock(tty); } set_current_state(TASK_RUNNING); diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index a3dddc12d2f..4a1e4f07765 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c @@ -3357,9 +3357,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, printk("%s(%d):%s block_til_ready() count=%d\n", __FILE__,__LINE__, tty->driver->name, port->count ); - tty_unlock(); + tty_unlock(tty); schedule(); - tty_lock(); + tty_lock(tty); } set_current_state(TASK_RUNNING); diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index b425c79675a..9e930c009bf 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -185,6 +185,7 @@ void free_tty_struct(struct tty_struct *tty) put_device(tty->dev); kfree(tty->write_buf); tty_buffer_free_all(tty); + tty->magic = 0xDEADDEAD; kfree(tty); } @@ -573,7 +574,7 @@ void __tty_hangup(struct tty_struct *tty) } spin_unlock(&redirect_lock); - tty_lock(); + tty_lock(tty); /* some functions below drop BTM, so we need this bit */ set_bit(TTY_HUPPING, &tty->flags); @@ -666,7 +667,7 @@ void __tty_hangup(struct tty_struct *tty) clear_bit(TTY_HUPPING, &tty->flags); tty_ldisc_enable(tty); - tty_unlock(); + tty_unlock(tty); if (f) fput(f); @@ -1103,12 +1104,12 @@ void tty_write_message(struct tty_struct *tty, char *msg) { if (tty) { mutex_lock(&tty->atomic_write_lock); - tty_lock(); + tty_lock(tty); if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { - tty_unlock(); + tty_unlock(tty); tty->ops->write(tty, msg, strlen(msg)); } else - tty_unlock(); + tty_unlock(tty); tty_write_unlock(tty); } return; @@ -1403,6 +1404,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) } initialize_tty_struct(tty, driver, idx); + tty_lock(tty); retval = tty_driver_install_tty(driver, tty); if (retval < 0) goto err_deinit_tty; @@ -1415,9 +1417,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) retval = tty_ldisc_setup(tty, tty->link); if (retval) goto err_release_tty; + /* Return the tty locked so that it cannot vanish under the caller */ return tty; err_deinit_tty: + tty_unlock(tty); deinitialize_tty_struct(tty); free_tty_struct(tty); err_module_put: @@ -1426,6 +1430,7 @@ err_module_put: /* call the tty release_tty routine to clean out this slot */ err_release_tty: + tty_unlock(tty); printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, " "clearing slot %d\n", idx); release_tty(tty, idx); @@ -1628,7 +1633,7 @@ int tty_release(struct inode *inode, struct file *filp) if (tty_paranoia_check(tty, inode, __func__)) return 0; - tty_lock(); + tty_lock(tty); check_tty_count(tty, __func__); __tty_fasync(-1, filp, 0); @@ -1637,10 +1642,11 @@ int tty_release(struct inode *inode, struct file *filp) pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->driver->subtype == PTY_TYPE_MASTER); devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; + /* Review: parallel close */ o_tty = tty->link; if (tty_release_checks(tty, o_tty, idx)) { - tty_unlock(); + tty_unlock(tty); return 0; } @@ -1652,7 +1658,7 @@ int tty_release(struct inode *inode, struct file *filp) if (tty->ops->close) tty->ops->close(tty, filp); - tty_unlock(); + tty_unlock(tty); /* * Sanity check: if tty->count is going to zero, there shouldn't be * any waiters on tty->read_wait or tty->write_wait. We test the @@ -1675,7 +1681,7 @@ int tty_release(struct inode *inode, struct file *filp) opens on /dev/tty */ mutex_lock(&tty_mutex); - tty_lock(); + tty_lock_pair(tty, o_tty); tty_closing = tty->count <= 1; o_tty_closing = o_tty && (o_tty->count <= (pty_master ? 1 : 0)); @@ -1706,7 +1712,7 @@ int tty_release(struct inode *inode, struct file *filp) printk(KERN_WARNING "%s: %s: read/write wait queue active!\n", __func__, tty_name(tty, buf)); - tty_unlock(); + tty_unlock_pair(tty, o_tty); mutex_unlock(&tty_mutex); schedule(); } @@ -1769,7 +1775,7 @@ int tty_release(struct inode *inode, struct file *filp) /* check whether both sides are closing ... */ if (!tty_closing || (o_tty && !o_tty_closing)) { - tty_unlock(); + tty_unlock_pair(tty, o_tty); return 0; } @@ -1782,14 +1788,16 @@ int tty_release(struct inode *inode, struct file *filp) tty_ldisc_release(tty, o_tty); /* * The release_tty function takes care of the details of clearing - * the slots and preserving the termios structure. + * the slots and preserving the termios structure. The tty_unlock_pair + * should be safe as we keep a kref while the tty is locked (so the + * unlock never unlocks a freed tty). */ release_tty(tty, idx); + tty_unlock_pair(tty, o_tty); /* Make this pty number available for reallocation */ if (devpts) devpts_kill_index(inode, idx); - tty_unlock(); return 0; } @@ -1893,6 +1901,9 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, * Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev. * tty->count should protect the rest. * ->siglock protects ->signal/->sighand + * + * Note: the tty_unlock/lock cases without a ref are only safe due to + * tty_mutex */ static int tty_open(struct inode *inode, struct file *filp) @@ -1916,8 +1927,7 @@ retry_open: retval = 0; mutex_lock(&tty_mutex); - tty_lock(); - + /* This is protected by the tty_mutex */ tty = tty_open_current_tty(device, filp); if (IS_ERR(tty)) { retval = PTR_ERR(tty); @@ -1938,17 +1948,19 @@ retry_open: } if (tty) { + tty_lock(tty); retval = tty_reopen(tty); - if (retval) + if (retval < 0) { + tty_unlock(tty); tty = ERR_PTR(retval); - } else + } + } else /* Returns with the tty_lock held for now */ tty = tty_init_dev(driver, index); mutex_unlock(&tty_mutex); if (driver) tty_driver_kref_put(driver); if (IS_ERR(tty)) { - tty_unlock(); retval = PTR_ERR(tty); goto err_file; } @@ -1977,7 +1989,7 @@ retry_open: printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__, retval, tty->name); #endif - tty_unlock(); /* need to call tty_release without BTM */ + tty_unlock(tty); /* need to call tty_release without BTM */ tty_release(inode, filp); if (retval != -ERESTARTSYS) return retval; @@ -1989,17 +2001,15 @@ retry_open: /* * Need to reset f_op in case a hangup happened. */ - tty_lock(); if (filp->f_op == &hung_up_tty_fops) filp->f_op = &tty_fops; - tty_unlock(); goto retry_open; } - tty_unlock(); + tty_unlock(tty); mutex_lock(&tty_mutex); - tty_lock(); + tty_lock(tty); spin_lock_irq(¤t->sighand->siglock); if (!noctty && current->signal->leader && @@ -2007,11 +2017,10 @@ retry_open: tty->session == NULL) __proc_set_tty(current, tty); spin_unlock_irq(¤t->sighand->siglock); - tty_unlock(); + tty_unlock(tty); mutex_unlock(&tty_mutex); return 0; err_unlock: - tty_unlock(); mutex_unlock(&tty_mutex); /* after locks to avoid deadlock */ if (!IS_ERR_OR_NULL(driver)) @@ -2094,10 +2103,13 @@ out: static int tty_fasync(int fd, struct file *filp, int on) { + struct tty_struct *tty = file_tty(filp); int retval; - tty_lock(); + + tty_lock(tty); retval = __tty_fasync(fd, filp, on); - tty_unlock(); + tty_unlock(tty); + return retval; } @@ -2934,6 +2946,7 @@ void initialize_tty_struct(struct tty_struct *tty, tty->pgrp = NULL; tty->overrun_time = jiffies; tty_buffer_init(tty); + mutex_init(&tty->legacy_mutex); mutex_init(&tty->termios_mutex); mutex_init(&tty->ldisc_mutex); init_waitqueue_head(&tty->write_wait); diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 24b95db75d8..fa65cde395a 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -567,7 +567,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (IS_ERR(new_ldisc)) return PTR_ERR(new_ldisc); - tty_lock(); + tty_lock(tty); /* * We need to look at the tty locking here for pty/tty pairs * when both sides try to change in parallel. @@ -581,12 +581,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) */ if (tty->ldisc->ops->num == ldisc) { - tty_unlock(); + tty_unlock(tty); tty_ldisc_put(new_ldisc); return 0; } - tty_unlock(); + tty_unlock(tty); /* * Problem: What do we do if this blocks ? * We could deadlock here @@ -594,7 +594,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) tty_wait_until_sent(tty, 0); - tty_lock(); + tty_lock(tty); mutex_lock(&tty->ldisc_mutex); /* @@ -604,10 +604,10 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { mutex_unlock(&tty->ldisc_mutex); - tty_unlock(); + tty_unlock(tty); wait_event(tty_ldisc_wait, test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); - tty_lock(); + tty_lock(tty); mutex_lock(&tty->ldisc_mutex); } @@ -622,7 +622,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) o_ldisc = tty->ldisc; - tty_unlock(); + tty_unlock(tty); /* * Make sure we don't change while someone holds a * reference to the line discipline. The TTY_LDISC bit @@ -649,7 +649,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) retval = tty_ldisc_wait_idle(tty, 5 * HZ); - tty_lock(); + tty_lock(tty); mutex_lock(&tty->ldisc_mutex); /* handle wait idle failure locked */ @@ -664,7 +664,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) clear_bit(TTY_LDISC_CHANGING, &tty->flags); mutex_unlock(&tty->ldisc_mutex); tty_ldisc_put(new_ldisc); - tty_unlock(); + tty_unlock(tty); return -EIO; } @@ -707,7 +707,7 @@ enable: if (o_work) schedule_work(&o_tty->buf.work); mutex_unlock(&tty->ldisc_mutex); - tty_unlock(); + tty_unlock(tty); return retval; } @@ -815,11 +815,11 @@ void tty_ldisc_hangup(struct tty_struct *tty) * need to wait for another function taking the BTM */ clear_bit(TTY_LDISC, &tty->flags); - tty_unlock(); + tty_unlock(tty); cancel_work_sync(&tty->buf.work); mutex_unlock(&tty->ldisc_mutex); retry: - tty_lock(); + tty_lock(tty); mutex_lock(&tty->ldisc_mutex); /* At this point we have a closed ldisc and we want to @@ -830,7 +830,7 @@ retry: if (atomic_read(&tty->ldisc->users) != 1) { char cur_n[TASK_COMM_LEN], tty_n[64]; long timeout = 3 * HZ; - tty_unlock(); + tty_unlock(tty); while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) { timeout = MAX_SCHEDULE_TIMEOUT; @@ -911,10 +911,10 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) * race with the set_ldisc code path. */ - tty_unlock(); + tty_unlock(tty); tty_ldisc_halt(tty); tty_ldisc_flush_works(tty); - tty_lock(); + tty_lock(tty); mutex_lock(&tty->ldisc_mutex); /* diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c index 9ff986c32a2..69adc80c98c 100644 --- a/drivers/tty/tty_mutex.c +++ b/drivers/tty/tty_mutex.c @@ -4,29 +4,59 @@ #include #include -/* - * The 'big tty mutex' - * - * This mutex is taken and released by tty_lock() and tty_unlock(), - * replacing the older big kernel lock. - * It can no longer be taken recursively, and does not get - * released implicitly while sleeping. - * - * Don't use in new code. - */ -static DEFINE_MUTEX(big_tty_mutex); +/* Legacy tty mutex glue */ /* * Getting the big tty mutex. */ -void __lockfunc tty_lock(void) + +void __lockfunc tty_lock(struct tty_struct *tty) { - mutex_lock(&big_tty_mutex); + if (tty->magic != TTY_MAGIC) { + printk(KERN_ERR "L Bad %p\n", tty); + WARN_ON(1); + return; + } + tty_kref_get(tty); + mutex_lock(&tty->legacy_mutex); } EXPORT_SYMBOL(tty_lock); -void __lockfunc tty_unlock(void) +void __lockfunc tty_unlock(struct tty_struct *tty) { - mutex_unlock(&big_tty_mutex); + if (tty->magic != TTY_MAGIC) { + printk(KERN_ERR "U Bad %p\n", tty); + WARN_ON(1); + return; + } + mutex_unlock(&tty->legacy_mutex); + tty_kref_put(tty); } EXPORT_SYMBOL(tty_unlock); + +/* + * Getting the big tty mutex for a pair of ttys with lock ordering + * On a non pty/tty pair tty2 can be NULL which is just fine. + */ +void __lockfunc tty_lock_pair(struct tty_struct *tty, + struct tty_struct *tty2) +{ + if (tty < tty2) { + tty_lock(tty); + tty_lock(tty2); + } else { + if (tty2 && tty2 != tty) + tty_lock(tty2); + tty_lock(tty); + } +} +EXPORT_SYMBOL(tty_lock_pair); + +void __lockfunc tty_unlock_pair(struct tty_struct *tty, + struct tty_struct *tty2) +{ + tty_unlock(tty); + if (tty2 && tty2 != tty) + tty_unlock(tty2); +} +EXPORT_SYMBOL(tty_unlock_pair); diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index bf6e238146a..d9cca95a545 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -230,7 +230,7 @@ int tty_port_block_til_ready(struct tty_port *port, /* block if port is in the process of being closed */ if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { - wait_event_interruptible_tty(port->close_wait, + wait_event_interruptible_tty(tty, port->close_wait, !(port->flags & ASYNC_CLOSING)); if (port->flags & ASYNC_HUP_NOTIFY) return -EAGAIN; @@ -296,9 +296,9 @@ int tty_port_block_til_ready(struct tty_port *port, retval = -ERESTARTSYS; break; } - tty_unlock(); + tty_unlock(tty); schedule(); - tty_lock(); + tty_lock(tty); } finish_wait(&port->open_wait, &wait); diff --git a/include/linux/tty.h b/include/linux/tty.h index 9f47ab540f6..4990ef2b1fb 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -268,6 +268,7 @@ struct tty_struct { struct mutex ldisc_mutex; struct tty_ldisc *ldisc; + struct mutex legacy_mutex; struct mutex termios_mutex; spinlock_t ctrl_lock; /* Termios values are protected by the termios mutex */ @@ -605,8 +606,12 @@ extern long vt_compat_ioctl(struct tty_struct *tty, /* tty_mutex.c */ /* functions for preparation of BKL removal */ -extern void __lockfunc tty_lock(void) __acquires(tty_lock); -extern void __lockfunc tty_unlock(void) __releases(tty_lock); +extern void __lockfunc tty_lock(struct tty_struct *tty); +extern void __lockfunc tty_unlock(struct tty_struct *tty); +extern void __lockfunc tty_lock_pair(struct tty_struct *tty, + struct tty_struct *tty2); +extern void __lockfunc tty_unlock_pair(struct tty_struct *tty, + struct tty_struct *tty2); /* * this shall be called only from where BTM is held (like close) @@ -621,9 +626,9 @@ extern void __lockfunc tty_unlock(void) __releases(tty_lock); static inline void tty_wait_until_sent_from_close(struct tty_struct *tty, long timeout) { - tty_unlock(); /* tty->ops->close holds the BTM, drop it while waiting */ + tty_unlock(tty); /* tty->ops->close holds the BTM, drop it while waiting */ tty_wait_until_sent(tty, timeout); - tty_lock(); + tty_lock(tty); } /* @@ -638,16 +643,16 @@ static inline void tty_wait_until_sent_from_close(struct tty_struct *tty, * * Do not use in new code. */ -#define wait_event_interruptible_tty(wq, condition) \ +#define wait_event_interruptible_tty(tty, wq, condition) \ ({ \ int __ret = 0; \ if (!(condition)) { \ - __wait_event_interruptible_tty(wq, condition, __ret); \ + __wait_event_interruptible_tty(tty, wq, condition, __ret); \ } \ __ret; \ }) -#define __wait_event_interruptible_tty(wq, condition, ret) \ +#define __wait_event_interruptible_tty(tty, wq, condition, ret) \ do { \ DEFINE_WAIT(__wait); \ \ @@ -656,9 +661,9 @@ do { \ if (condition) \ break; \ if (!signal_pending(current)) { \ - tty_unlock(); \ + tty_unlock(tty); \ schedule(); \ - tty_lock(); \ + tty_lock(tty); \ continue; \ } \ ret = -ERESTARTSYS; \ diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index d1820ff14ae..aa5d73b786a 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -710,9 +710,9 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) break; } - tty_unlock(); + tty_unlock(tty); schedule(); - tty_lock(); + tty_lock(tty); } set_current_state(TASK_RUNNING); remove_wait_queue(&dev->wait, &wait); -- cgit v1.2.3-70-g09d2 From 1541f845d123a48fbca3cee32b2963b3fb3da83a Mon Sep 17 00:00:00 2001 From: Ivo Sieben Date: Thu, 3 May 2012 14:37:43 +0200 Subject: tty: move global ldisc idle waitqueue to the individual ldisc The global wait_queue that is used for line discipline idle handling is moved to a separate wait_queue for each line instance. This prevents unnecessary blocking on one line, because of idle handling on another line. Signed-off-by: Ivo Sieben Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 7 ++++--- include/linux/tty_ldisc.h | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index fa65cde395a..173a9000a6c 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -28,7 +28,6 @@ static DEFINE_SPINLOCK(tty_ldisc_lock); static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); -static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_idle); /* Line disc dispatch table */ static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; @@ -65,7 +64,7 @@ static void put_ldisc(struct tty_ldisc *ld) return; } local_irq_restore(flags); - wake_up(&tty_ldisc_idle); + wake_up(&ld->wq_idle); } /** @@ -200,6 +199,8 @@ static struct tty_ldisc *tty_ldisc_get(int disc) ld->ops = ldops; atomic_set(&ld->users, 1); + init_waitqueue_head(&ld->wq_idle); + return ld; } @@ -538,7 +539,7 @@ static void tty_ldisc_flush_works(struct tty_struct *tty) static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout) { long ret; - ret = wait_event_timeout(tty_ldisc_idle, + ret = wait_event_timeout(tty->ldisc->wq_idle, atomic_read(&tty->ldisc->users) == 1, timeout); return ret > 0 ? 0 : -EBUSY; } diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index ff7dc08696a..fb79dd8d153 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -110,6 +110,7 @@ #include #include #include +#include struct tty_ldisc_ops { int magic; @@ -154,6 +155,7 @@ struct tty_ldisc_ops { struct tty_ldisc { struct tty_ldisc_ops *ops; atomic_t users; + wait_queue_head_t wq_idle; }; #define TTY_LDISC_MAGIC 0x5403 -- cgit v1.2.3-70-g09d2