TTY patches for 2.6.36
Subsystems (28)
PATCH 1/1 TTY patches for 2.6.36
Here's the tty patches for the .36 merge window.
This contains the big BKL removal of the tty layer, which has been worked on now for a long time by Alan and Arnd. Other than that, there's a few new serial drivers, and minor changes around the tty area.
Please pull from:
master.kernel.org:/pub/scm/linux/kernel/git/gregkh/tty-2.6.git/
These patches have been in the linux-next tree and -mm for a while now.
Patches will be sent to the linux-kernel mailing list, if anyone wants to see them.
thanks,
greg k-h
------------
Documentation/kernel-parameters.txt | 3 + arch/alpha/include/asm/ioctls.h | 4 +- arch/alpha/include/asm/termbits.h | 1 + arch/arm/include/asm/ioctls.h | 2 + arch/arm/include/asm/termbits.h | 1 + arch/avr32/include/asm/ioctls.h | 4 +- arch/avr32/include/asm/termbits.h | 1 + arch/cris/include/asm/ioctls.h | 4 +- arch/cris/include/asm/termbits.h | 1 + arch/frv/include/asm/ioctls.h | 2 + arch/frv/include/asm/termbits.h | 1 + arch/h8300/include/asm/ioctls.h | 2 + arch/h8300/include/asm/termbits.h | 1 + arch/ia64/include/asm/ioctls.h | 4 +- arch/ia64/include/asm/termbits.h | 1 + arch/m32r/include/asm/ioctls.h | 4 +- arch/m32r/include/asm/termbits.h | 1 + arch/m68k/include/asm/ioctls.h | 2 + arch/m68k/include/asm/termbits.h | 1 + arch/mips/include/asm/ioctls.h | 5 +- arch/mips/include/asm/termbits.h | 1 + arch/mn10300/include/asm/ioctls.h | 4 +- arch/mn10300/include/asm/termbits.h | 1 + arch/parisc/include/asm/ioctls.h | 4 +- arch/parisc/include/asm/termbits.h | 1 + arch/powerpc/include/asm/ioctls.h | 2 + arch/powerpc/include/asm/termbits.h | 1 + arch/s390/include/asm/ioctls.h | 2 + arch/sh/include/asm/ioctls.h | 2 + arch/sparc/include/asm/ioctls.h | 2 + arch/sparc/include/asm/termbits.h | 1 + arch/xtensa/include/asm/ioctls.h | 2 + arch/xtensa/include/asm/termbits.h | 1 + drivers/char/Makefile | 1 + drivers/char/amiserial.c | 25 +- drivers/char/briq_panel.c | 6 +- drivers/char/cyclades.c | 22 +- drivers/char/epca.c | 4 +- drivers/char/ip2/ip2main.c | 4 + drivers/char/isicom.c | 13 +- drivers/char/istallion.c | 68 +- drivers/char/keyboard.c | 10 +- drivers/char/mxser.c | 2 +- drivers/char/n_gsm.c | 1 - drivers/char/n_hdlc.c | 16 +- drivers/char/n_r3964.c | 10 +- drivers/char/n_tty.c | 17 +- drivers/char/nozomi.c | 4 +- drivers/char/pty.c | 47 +- drivers/char/riscom8.c | 14 +- drivers/char/rocket.c | 28 +- drivers/char/selection.c | 13 +- drivers/char/serial167.c | 8 +- drivers/char/specialix.c | 13 +- drivers/char/stallion.c | 20 +- drivers/char/sx.c | 12 +- drivers/char/synclink.c | 21 +- drivers/char/synclink_gt.c | 92 +- drivers/char/synclinkmp.c | 43 +- drivers/char/tty_io.c | 150 ++-- drivers/char/tty_ioctl.c | 18 +- drivers/char/tty_ldisc.c | 43 +- drivers/char/tty_mutex.c | 47 + drivers/char/tty_port.c | 4 +- drivers/char/vc_screen.c | 4 +- drivers/char/vt.c | 37 +- drivers/char/vt_ioctl.c | 17 +- drivers/gpu/drm/i915/intel_fb.c | 4 +- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 1 + drivers/gpu/drm/radeon/radeon_fb.c | 2 +- drivers/serial/21285.c | 10 +- drivers/serial/68328serial.c | 26 +- drivers/serial/68360serial.c | 4 +- drivers/serial/8250.c | 11 +- drivers/serial/8250_early.c | 57 +- drivers/serial/8250_pci.c | 13 + drivers/serial/Kconfig | 44 + drivers/serial/Makefile | 4 + drivers/serial/altera_uart.c | 2 +- drivers/serial/atmel_serial.c | 11 +- drivers/serial/bfin_5xx.c | 7 +- drivers/serial/crisv10.c | 12 +- drivers/serial/imx.c | 10 +- drivers/serial/ioc3_serial.c | 9 +- drivers/serial/ioc4_serial.c | 9 +- drivers/serial/max3100.c | 7 +- drivers/serial/max3107-aava.c | 344 +++++++ drivers/serial/max3107.c | 1197 ++++++++++++++++++++++++ drivers/serial/max3107.h | 441 +++++++++ drivers/serial/mcf.c | 31 +- drivers/serial/mfd.c | 1498 +++++++++++++++++++++++++++++++ drivers/serial/mrst_max3110.c | 844 +++++++++++++++++ drivers/serial/mrst_max3110.h | 59 ++ drivers/serial/serial_core.c | 288 +++---- drivers/serial/timbuart.c | 6 +- drivers/usb/class/cdc-acm.c | 12 +- drivers/usb/serial/digi_acceleport.c | 14 +- drivers/video/console/fbcon.c | 4 +- drivers/video/console/vgacon.c | 2 - fs/compat_ioctl.c | 1 + include/asm-generic/ioctls.h | 8 +- include/asm-generic/termbits.h | 1 + include/linux/console_struct.h | 4 +- include/linux/fb.h | 4 + include/linux/istallion.h | 2 +- include/linux/serial.h | 6 +- include/linux/serial_core.h | 8 +- include/linux/serial_mfd.h | 47 + include/linux/serial_reg.h | 16 + include/linux/tty.h | 68 ++ include/linux/vt_kern.h | 64 ++- lib/Kconfig.debug | 10 + 112 files changed, 5481 insertions(+), 644 deletions(-) create mode 100644 drivers/char/tty_mutex.c create mode 100644 drivers/serial/max3107-aava.c create mode 100644 drivers/serial/max3107.c create mode 100644 drivers/serial/max3107.h create mode 100644 drivers/serial/mfd.c create mode 100644 drivers/serial/mrst_max3110.c create mode 100644 drivers/serial/mrst_max3110.h create mode 100644 include/linux/serial_mfd.h
---------------
Alan Cox (23):
stallion: prune lock_kernel calls
istallion: use bit ops for the board flags
riscom8: kill use of lock_kernel
isicom: kill off the BKL
rocket: kill BKL
synclink: kill the big kernel lock
cyclades: Kill off BKL usage
epca: Kill the big kernel lock
specialix: Kill the BKL
tty: Fix the digi acceleport driver NULL checks
synclink: reworking locking a bit
tty: serial - fix various misuses/mishandlings of port->tty
tty: serial - fix tty back references in termios
tty: serial - fix tty referencing in set_ldisc
vc: Locking clean up
tty: Make vt's have a tty_port
tty: Move the vt_tty field from the vc_data into the standard tty_port
serial: Change the wait for carrier locking
serial: add port helpers
serial: trim locking on the helpers
serial: Use block_til_ready helper
serial: max3107: Abstract out the platform specific bits
serial: max3107: Fix gpiolib support
Andrea Gelmini (1):
n_gsm.c: removed duplicated #includes
Andrew Morton (1):
serial: "altera_uart: simplify altera_uart_console_putc()" checkpatch fixes
Andy Shevchenko (1):
vt: clean up the code - use kernel library
Arjan van de Ven (2):
serial: replace open coded mutex with a real mutex in mrst_max3110.c
serial: fix wakup races in the mrst_max3110 driver
Arnd Bergmann (13):
serial: fix termios settings in open
tty: replace BKL with a new tty_lock
tty: never hold BTM while getting tty_mutex
tty: fix console_sem lock order
cdc-acm: remove dead code
tty: introduce wait_event_interruptible_tty
tty: reorder ldisc locking
tty: untangle locking of wait_until_sent
tty: remove tty_lock_nested
tty: implement BTM as mutex instead of BKL
tty: release BTM while sleeping in block_til_ready 8250: fix set_ldisc operation
tty: avoid recursive BTM in pty_close
Christoph Egger (2):
serial: There's no config CONSOLE
serial: 68328serial.c: remove dead (ALMA_ANS | DRAGONIXVZ | M68EZ328ADS)
Claudio Scordino (1):
serial: general fixes in the serial_rs485 structure
Feng Tang (5):
mrst_max3110: add UART driver for Max3110 on Moorestown
hsu: driver for Medfield High Speed UART device
hsu: add a periodic timer to check dma rx channel
hsu: some code cleanup
hsu: call PCI pm hooks in suspend/resume function
Greg Kroah-Hartman (1):
tty: remove remaining Hayes ESP ioctls
Jeff Dike (1):
tty: Remove Hayes ESP ioctls
Jesse Barnes (1):
vt/console: try harder to print output when panicing
Jiri Slaby (2):
Char: nozomi, fix tty->count counting
Char: nozomi, set tty->driver_data appropriatelyJohn Villalovos (1):
serial: fix missing bit coverage of ASYNC_FLAGS
Kevin Winchester (1):
vt: Fix warning: statement with no effect due to vt_kern.h
Kulikov Vasiliy (3):
tty_io: remove casts from void*
serial: crisv10: formatting of pointers in printk()
mxser: remove unnesesary NULL check
Lytochkin Boris (1):
serial: add support for OX16PCI958 card
Richard Röjfors (1):
timbuart: use __devinit and __devexit macros for probe and remove
Samium Gromoff (1):
serial: MMIO32 support for 8250_early.c
Yegor Yefremov (1):
serial: add UART_CAP_EFR and UART_CAP_SLEEP flags to 16C950 UARTs definition
Yury Georgievskiy (1):
serial: mcf: don't take spinlocks in already protected functions
[email protected] (1):
tty: Add EXTPROC support for LINEMODE
jianwei.yang (2):
max3110 sanity check a register
serial: max3107: introduce a max3107 driver
PATCH 1/67 n_gsm.c: removed duplicated #includes
From: Andrea Gelmini <[email protected]>
drivers/char/n_gsm.c: linux/timer.h is included more than once.
--- drivers/char/n_gsm.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
drivers/char/n_gsm.c +0 -1
@@ -43,7 +43,6 @@#include <linux/sched.h> #include <linux/interrupt.h> #include <linux/tty.h> -#include <linux/timer.h> #include <linux/ctype.h> #include <linux/mm.h> #include <linux/string.h>
Signature · 1 line
1.7.2
PATCH 2/67 serial: There's no config CONSOLE
In reply to Greg KHFrom: Christoph Egger <[email protected]>
as there's no config CONSOLE (never has been as far as I can tell) and noone has ever missed that piece of code, it should be safe to remove it making the kernel a tiny bit less complex.
--- drivers/serial/68328serial.c | 8 -------- 1 files changed, 0 insertions(+), 8 deletions(-)
drivers/serial/68328serial.c +0 -8
@@ -78,10 +78,6 @@ struct m68k_serial *m68k_consinfo = 0;#define M68K_CLOCK (16667000)/* FIXME: 16MHz is likely wrong */ -#ifdef CONFIG_CONSOLE -extern wait_queue_head_t keypress_wait; -#endif -struct tty_driver *serial_driver;/* number of characters left in xmit buffer before we ask for more */
@@ -300,10 +296,6 @@ static void receive_chars(struct m68k_serial *info, unsigned short rx)return ;#endif /* CONFIG_MAGIC_SYSRQ */ } -/* It is a 'keyboard interrupt' ;-) */ -#ifdef CONFIG_CONSOLE -wake_up (&keypress_wait); -#endif }if (!tty)
Signature · 1 line
1.7.2
PATCH 3/67 vt: clean up the code - use kernel library
In reply to Greg KHFrom: Andy Shevchenko <[email protected]>
--- drivers/char/vt.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
drivers/char/vt.c +3 -2
@@ -104,6 +104,7 @@#include <linux/io.h> #include <asm/system.h> #include <linux/uaccess.h> +#include <linux/ctype.h> #define MAX_NR_CON_DRIVER 16
@@ -1789,8 +1790,8 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) vc->vc_state = ESnormal;return ;case ESpalette: -if ( (c>='0' &&c<='9' ) || (c>='A' &&c<='F' ) || (c>='a' &&c<='f' ) ) { - vc->vc_par[vc->vc_npar++] = (c >'9' ? (c &0xDF ) -'A' +10 : c -'0' ); +if (isxdigit (c)) { + vc->vc_par[vc->vc_npar++] =hex_to_bin (c);if (vc->vc_npar ==7 ) {int i = vc->vc_par[0 ] *3 , j =1 ; vc->vc_palette[i] =16 * vc->vc_par[j++];
Signature · 1 line
1.7.2
PATCH 4/67 serial: add UART_CAP_EFR and UART_CAP_SLEEP flags to 16C950 UARTs definition
In reply to Greg KHFrom: Yegor Yefremov <[email protected]>
Adding UART_CAP_EFR and UART_CAP_SLEEP flags will enable sleep mode and automatic CTS flow control for 16C950 UARTs. It will also avoid capabilities detection warning like this:
"ttyS0: detected caps 00000700 should be 00000100"
--- drivers/serial/8250.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/serial/8250.c +1 -1
@@ -241,7 +241,7 @@ static const struct serial8250_config uart_config[] = { .fifo_size = 128, .tx_loadsz = 128, .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - .flags = UART_CAP_FIFO, + .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, }, [PORT_16654] = { .name = "ST16654",
Signature · 1 line
1.7.2
PATCH 5/67 mrst_max3110: add UART driver for Max3110 on Moorestown
In reply to Greg KHFrom: Feng Tang <[email protected]>
This driver enable the max3110 device, it can be used as a system console. the IRQ needs be enabled if user want a better performance. MRST max3110 works in 3.684MHz clock, which supports 230400 as its maximum rate.
--- drivers/serial/Kconfig | 17 + drivers/serial/Makefile | 1 + drivers/serial/mrst_max3110.c | 844 +++++++++++++++++++++++++++++++++++++++++ drivers/serial/mrst_max3110.h | 59 +++ 4 files changed, 921 insertions(+), 0 deletions(-) create mode 100644 drivers/serial/mrst_max3110.c create mode 100644 drivers/serial/mrst_max3110.h
drivers/serial/Kconfig +17 -0
@@ -690,6 +690,23 @@ config SERIAL_SA1100_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) +config SERIAL_MRST_MAX3110 + tristate "SPI UART driver for Max3110" + depends on SPI_DW_PCI + select SERIAL_CORE + select SERIAL_CORE_CONSOLE + help + This is the UART protocol driver for the MAX3110 device on + the Intel Moorestown platform. On other systems use the max3100 + driver. + +config MRST_MAX3110_IRQ + boolean "Enable GPIO IRQ for Max3110 over Moorestown" + default n + depends on SERIAL_MRST_MAX3110 && GPIO_LANGWELL + help + This has to be enabled after Moorestown GPIO driver is loaded + config SERIAL_BFIN tristate "Blackfin serial port support" depends on BLACKFIN
drivers/serial/Makefile +1 -0
@@ -84,3 +84,4 @@ obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o +obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o
drivers/serial/mrst_max3110.c new file +844 -0
844 lines not on this page · raw message
drivers/serial/mrst_max3110.h new file +59 -0
59 lines not on this page · raw message
Signature · 1 line
1.7.2
PATCH 6/67 max3110 sanity check a register
In reply to Greg KHFrom: jianwei.yang <[email protected]>
MAX3111 is the SPI/UART IC installed on the MRST SPI Port Card as a serial debug goal, and the SPI Port Card will be frequently mounted and unmounted from the main board by developers depending whether debug serial is required or not.
As the MAX3111 has no subvendor or product id registers available, the patch will try to access one register to decide if this IC is present or not.
--- drivers/serial/mrst_max3110.c | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-)
drivers/serial/mrst_max3110.c +11 -2
@@ -721,7 +721,7 @@ static int serial_m3110_probe(struct spi_device *spi)struct uart_max3110 *max;int ret;unsigned char *buffer; - +u16 res; max =kzalloc (sizeof (*max),GFP_KERNEL );if (!max)return -ENOMEM ;
@@ -753,7 +753,16 @@ static int serial_m3110_probe(struct spi_device *spi) max->cur_conf =0 ;atomic_set (&max->irq_pending,0 ); - +/* Check if reading configuration register returns something sane */ + + res =RC_TAG ; + ret =max3110_write_then_read (max, (u8 *)&res, (u8 *)&res,2 ,0 ); +if (ret <0 || res ==0 || res ==0xffff ) { +printk (KERN_ERR "MAX3111 deemed not present (conf reg %04x)" , + res); + ret = -ENODEV ; + goto err_get_page; + } buffer = (unsigned char *)__get_free_page (GFP_KERNEL );if (!buffer) { ret = -ENOMEM ;
Signature · 1 line
1.7.2
PATCH 7/67 serial: replace open coded mutex with a real mutex in mrst_max3110.c
In reply to Greg KHFrom: Arjan van de Ven <[email protected]>
The mrst_max3110.c driver uses an open coded, non atomic variable to create exclusion between two of its worker threads. More than that, while the main thread does a proper set-work-clear sequence, the other thread only does a test, with the result that no actual exclusion is happening.
this patch replaces this open coded variable with a proper mutex
in addition, the 'lock' spinlock is removed from the per adapter structure, the lock was only ever initialized but never used
--- drivers/serial/mrst_max3110.c | 15 ++++++++------- 1 files changed, 8 insertions(+), 7 deletions(-)
drivers/serial/mrst_max3110.c +8 -7
@@ -56,8 +56,7 @@ struct uart_max3110 {wait_queue_head_t wq;struct task_struct *main_thread;struct task_struct *read_thread; -int mthread_up; -spinlock_t lock; +struct mutex thread_mutex;;u32 baud;u16 cur_conf;
@@ -397,7 +396,8 @@ static int max3110_main_thread(void *_max)atomic_read (&max->con_tx_need) || atomic_read(&max->uart_tx_need)) || kthread_should_stop()); - max->mthread_up =1 ; + +mutex_lock (&max->thread_mutex);#ifdef CONFIG_MRST_MAX3110_IRQ if (atomic_read (&max->irq_pending)) {
@@ -417,7 +417,7 @@ static int max3110_main_thread(void *_max)transmit_char (max);atomic_set (&max->uart_tx_need,0 ); } - max->mthread_up =0 ; +mutex_unlock (&max->thread_mutex); }while (!kthread_should_stop ());return ret;
@@ -444,8 +444,9 @@ static int max3110_read_thread(void *_max)pr_info (PR_FMT "start read thread\n" ); do { - if (!max->mthread_up) - max3110_console_receive(max); + mutex_lock(&max->thread_mutex); + max3110_console_receive(max); + mutex_unlock(&max->thread_mutex); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ / 20);
@@ -745,7 +746,7 @@ static int serial_m3110_probe(struct spi_device *spi) max->name = spi->modalias;/* use spi name as the name */ max->irq = (u16 )spi->irq; -spin_lock_init (&max->lock); +mutex_init (&max->thread_mutex); max->word_7bits =0 ; max->parity =0 ;
Signature · 1 line
1.7.2
PATCH 8/67 serial: fix wakup races in the mrst_max3110 driver
In reply to Greg KHFrom: Arjan van de Ven <[email protected]>
The mrst_max3110 driver had a set of unsafe wakeup sequences along the following line:
if (!atomic_read(&foo)) {
atomic_set(&foo, 1);
wake_up(worker_thread);
}
and the worker thread would do
if (atomic_read(&foo)) {
do_work();
atomic_set(&foo, 0);
}
which can result in various missed wakups due to test-then-set races, as well as due to clear-after-work instead of clear-before-work.
This patch fixes these races by using the proper bit test-and-set operations, and by doing clear-before-work.
--- drivers/serial/mrst_max3110.c | 46 ++++++++++++++++------------------------- 1 files changed, 18 insertions(+), 28 deletions(-)
drivers/serial/mrst_max3110.c +18 -28
@@ -48,6 +48,10 @@#define PR_FMT "mrst_max3110: " +#define UART_TX_NEEDED 1 +#define CON_TX_NEEDED 2 +#define BIT_IRQ_PENDING 3 +struct uart_max3110 {struct uart_port port;struct spi_device *spi;
@@ -63,15 +67,13 @@ struct uart_max3110 {u8 clock;u8 parity, word_7bits; -atomic_t uart_tx_need; +unsigned long uart_flags;/* console related */ struct circ_buf con_xmit; -atomic_t con_tx_need;/* irq related */ u16 irq; -atomic_t irq_pending; };/* global data structure, may need be removed */
@@ -176,10 +178,9 @@ static void serial_m3110_con_putchar(struct uart_port *port, int ch) xmit->head = (xmit->head +1 ) & (PAGE_SIZE -1 ); } -if (!atomic_read (&max->con_tx_need)) { -atomic_set (&max->con_tx_need,1 ); + +if (!test_and_set_bit (CON_TX_NEEDED , &max->uart_flags))wake_up_process (max->main_thread); - } }/*
@@ -318,10 +319,8 @@ static void serial_m3110_start_tx(struct uart_port *port)struct uart_max3110 *max = container_of(port, struct uart_max3110, port); -if (!atomic_read (&max->uart_tx_need)) { -atomic_set (&max->uart_tx_need,1 ); +if (!test_and_set_bit (UART_TX_NEEDED , &max->uart_flags))wake_up_process (max->main_thread); - } }static void receive_chars (struct uart_max3110 *max,unsigned char *str,int len)
@@ -392,32 +391,23 @@ static int max3110_main_thread(void *_max)pr_info (PR_FMT "start main thread\n" );do { -wait_event_interruptible (*wq, (atomic_read (&max->irq_pending) || -atomic_read (&max->con_tx_need) || -atomic_read (&max->uart_tx_need)) || -kthread_should_stop ()); +wait_event_interruptible (*wq, max->uart_flags ||kthread_should_stop ());mutex_lock (&max->thread_mutex); -#ifdef CONFIG_MRST_MAX3110_IRQ -if (atomic_read (&max->irq_pending)) { +if (test_and_clear_bit (BIT_IRQ_PENDING , &max->uart_flags))max3110_console_receive (max); -atomic_set (&max->irq_pending,0 ); - } -#endif /* first handle console output */ -if (atomic_read (&max->con_tx_need)) { +if (test_and_clear_bit (CON_TX_NEEDED , &max->uart_flags))send_circ_buf (max, xmit); -atomic_set (&max->con_tx_need,0 ); - }/* handle uart output */ -if (atomic_read (&max->uart_tx_need)) { +if (test_and_clear_bit (UART_TX_NEEDED , &max->uart_flags))transmit_char (max); -atomic_set (&max->uart_tx_need,0 ); - } +mutex_unlock (&max->thread_mutex); + }while (!kthread_should_stop ());return ret;
@@ -430,10 +420,9 @@ static irqreturn_t serial_m3110_irq(int irq, void *dev_id)/* max3110's irq is a falling edge, not level triggered, * so no need to disable the irq */ -if (!atomic_read (&max->irq_pending)) { -atomic_inc (&max->irq_pending); +if (!test_and_set_bit (BIT_IRQ_PENDING , &max->uart_flags))wake_up_process (max->main_thread); - } + return IRQ_HANDLED; }#else
@@ -753,7 +742,8 @@ static int serial_m3110_probe(struct spi_device *spi) max->baud =0 ; max->cur_conf =0 ; -atomic_set (&max->irq_pending,0 ); + max->uart_flags =0 ; +/* Check if reading configuration register returns something sane */ res =RC_TAG ;
Signature · 1 line
1.7.2
PATCH 9/67 tty: Remove Hayes ESP ioctls
In reply to Greg KHFrom: Jeff Dike <[email protected]>
Remove Hayes ESP ioctls
The Hayes ESP driver has been removed from the tree:
commit f53a2ade0bb9f2a81f473e6469155172a96b7c38 ("tty: esp: remove broken driver")
so its ioctls aren't needed any more.
--- include/asm-generic/ioctls.h | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-)
include/asm-generic/ioctls.h +2 -4
@@ -87,12 +87,10 @@#define TIOCGICOUNT 0x545D/* read serial port inline interrupt counts */ /* -* some architectures define FIOQSIZE as 0x545E, which is used for -* TIOCGHAYESESP on others +* Some arches already define FIOQSIZE due to a historical +* conflict with a Hayes modem-specific ioctl value. */ #ifndef FIOQSIZE -# define TIOCGHAYESESP 0x545E/* Get Hayes ESP configuration */ -# define TIOCSHAYESESP 0x545F/* Set Hayes ESP configuration */ # define FIOQSIZE 0x5460#endif
Signature · 1 line
1.7.2
PATCH 10/67 tty: remove remaining Hayes ESP ioctls
In reply to Greg KHAs Jeff Dike pointed out, the Hayes ESP driver was removed in commit f53a2ade0bb9f2a81f473e6469155172a96b7c38, so these ioctl definitions should also be removed. This cleans up the remaining arch-specific locations of this ioctl value.
Thanks to Arnd for pointing these out.
--- arch/alpha/include/asm/ioctls.h | 2 -- arch/avr32/include/asm/ioctls.h | 2 -- arch/cris/include/asm/ioctls.h | 2 -- arch/ia64/include/asm/ioctls.h | 2 -- arch/m32r/include/asm/ioctls.h | 2 -- arch/mips/include/asm/ioctls.h | 2 -- arch/mn10300/include/asm/ioctls.h | 2 -- arch/parisc/include/asm/ioctls.h | 2 -- 8 files changed, 0 insertions(+), 16 deletions(-)
arch/alpha/include/asm/ioctls.h +0 -2
@@ -106,7 +106,5 @@#define TIOCMIWAIT 0x545C/* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D/* read serial port inline interrupt counts */ -#define TIOCGHAYESESP 0x545E/* Get Hayes ESP configuration */ -#define TIOCSHAYESESP 0x545F/* Set Hayes ESP configuration */ #endif /* _ASM_ALPHA_IOCTLS_H */
arch/avr32/include/asm/ioctls.h +0 -2
@@ -72,8 +72,6 @@#define TIOCMIWAIT 0x545C/* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D/* read serial port inline interrupt counts */ -#define TIOCGHAYESESP 0x545E/* Get Hayes ESP configuration */ -#define TIOCSHAYESESP 0x545F/* Set Hayes ESP configuration */ #define FIOQSIZE 0x5460/* Used for packet mode */
arch/cris/include/asm/ioctls.h +0 -2
@@ -70,8 +70,6 @@#define TIOCMIWAIT 0x545C/* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D/* read serial port inline interrupt counts */ -#define TIOCGHAYESESP 0x545E/* Get Hayes ESP configuration */ -#define TIOCSHAYESESP 0x545F/* Set Hayes ESP configuration */ #define FIOQSIZE 0x5460#define TIOCSERSETRS485 0x5461/* enable rs-485 (deprecated) */
arch/ia64/include/asm/ioctls.h +0 -2
@@ -75,8 +75,6 @@#define TIOCMIWAIT 0x545C/* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D/* read serial port inline interrupt counts */ -#define TIOCGHAYESESP 0x545E/* Get Hayes ESP configuration */ -#define TIOCSHAYESESP 0x545F/* Set Hayes ESP configuration */ #define FIOQSIZE 0x5460/* Used for packet mode */
arch/m32r/include/asm/ioctls.h +0 -2
@@ -69,8 +69,6 @@#define TIOCMIWAIT 0x545C/* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D/* read serial port inline interrupt counts */ -#define TIOCGHAYESESP 0x545E/* Get Hayes ESP configuration */ -#define TIOCSHAYESESP 0x545F/* Set Hayes ESP configuration */ #define FIOQSIZE 0x5460/* Used for packet mode */
arch/mips/include/asm/ioctls.h +0 -2
@@ -103,7 +103,5 @@#define TIOCSERSETMULTI 0x5490/* Set multiport config */ #define TIOCMIWAIT 0x5491/* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x5492/* read serial port inline interrupt counts */ -#define TIOCGHAYESESP 0x5493/* Get Hayes ESP configuration */ -#define TIOCSHAYESESP 0x5494/* Set Hayes ESP configuration */ #endif /* __ASM_IOCTLS_H */
arch/mn10300/include/asm/ioctls.h +0 -2
@@ -70,8 +70,6 @@#define TIOCMIWAIT 0x545C/* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D/* read serial port inline interrupt counts */ -#define TIOCGHAYESESP 0x545E/* Get Hayes ESP configuration */ -#define TIOCSHAYESESP 0x545F/* Set Hayes ESP configuration */ #define FIOQSIZE 0x5460/* Used for packet mode */
arch/parisc/include/asm/ioctls.h +0 -2
@@ -68,8 +68,6 @@#define TIOCMIWAIT 0x545C/* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D/* read serial port inline interrupt counts */ -#define TIOCGHAYESESP 0x545E/* Get Hayes ESP configuration */ -#define TIOCSHAYESESP 0x545F/* Set Hayes ESP configuration */ #define FIOQSIZE 0x5460/* Get exact space used by quota */ #define TIOCSTART 0x5461
Signature · 1 line
1.7.2
PATCH 11/67 tty: Add EXTPROC support for LINEMODE
In reply to Greg KHFrom: [email protected] <[email protected]>
This patch is against the 2.6.34 source.
Paraphrased from the 1989 BSD patch by David Borman @ cray.com:
These are the changes needed for the kernel to support LINEMODE in the server.
There is a new bit in the termios local flag word, EXTPROC. When this bit is set, several aspects of the terminal driver are disabled. Input line editing, character echo, and mapping of signals are all disabled. This allows the telnetd to turn off these functions when in linemode, but still keep track of what state the user wants the terminal to be in.
New ioctl:
TIOCSIG Generate a signal to processes in the
current process group of the pty.
There is a new mode for packet driver, the TIOCPKT_IOCTL bit. When packet mode is turned on in the pty, and the EXTPROC bit is set, then whenever the state of the pty is changed, the next read on the master side of the pty will have the TIOCPKT_IOCTL bit set. This allows the process on the server side of the pty to know when the state of the terminal has changed; it can then issue the appropriate ioctl to retrieve the new state.
Since the original BSD patches accompanied the source code for telnet I've left that reference here, but obviously the feature is useful for any remote terminal protocol, including ssh.
The corresponding feature has existed in the BSD tty driver since 1989. For historical reference, a good copy of the relevant files can be found here:
http://anonsvn.mit.edu/viewvc/krb5/trunk/src/appl/telnet/?pathrev=17741
--- arch/alpha/include/asm/ioctls.h | 2 ++ arch/alpha/include/asm/termbits.h | 1 + arch/arm/include/asm/ioctls.h | 2 ++ arch/arm/include/asm/termbits.h | 1 + arch/avr32/include/asm/ioctls.h | 2 ++ arch/avr32/include/asm/termbits.h | 1 + arch/cris/include/asm/ioctls.h | 2 ++ arch/cris/include/asm/termbits.h | 1 + arch/frv/include/asm/ioctls.h | 2 ++ arch/frv/include/asm/termbits.h | 1 + arch/h8300/include/asm/ioctls.h | 2 ++ arch/h8300/include/asm/termbits.h | 1 + arch/ia64/include/asm/ioctls.h | 2 ++ arch/ia64/include/asm/termbits.h | 1 + arch/m32r/include/asm/ioctls.h | 2 ++ arch/m32r/include/asm/termbits.h | 1 + arch/m68k/include/asm/ioctls.h | 2 ++ arch/m68k/include/asm/termbits.h | 1 + arch/mips/include/asm/ioctls.h | 3 ++- arch/mips/include/asm/termbits.h | 1 + arch/mn10300/include/asm/ioctls.h | 2 ++ arch/mn10300/include/asm/termbits.h | 1 + arch/parisc/include/asm/ioctls.h | 2 ++ arch/parisc/include/asm/termbits.h | 1 + arch/powerpc/include/asm/ioctls.h | 2 ++ arch/powerpc/include/asm/termbits.h | 1 + arch/s390/include/asm/ioctls.h | 2 ++ arch/sh/include/asm/ioctls.h | 2 ++ arch/sparc/include/asm/ioctls.h | 2 ++ arch/sparc/include/asm/termbits.h | 1 + arch/xtensa/include/asm/ioctls.h | 2 ++ arch/xtensa/include/asm/termbits.h | 1 + drivers/char/n_tty.c | 17 ++++++++++++++--- drivers/char/pty.c | 21 +++++++++++++++++++++ drivers/char/tty_ioctl.c | 18 ++++++++++++------ fs/compat_ioctl.c | 1 + include/asm-generic/ioctls.h | 2 ++ include/asm-generic/termbits.h | 1 + include/linux/tty.h | 1 + 39 files changed, 101 insertions(+), 10 deletions(-)
arch/alpha/include/asm/ioctls.h +2 -0
@@ -80,6 +80,7 @@# define TIOCPKT_START 8# define TIOCPKT_NOSTOP 16# define TIOCPKT_DOSTOP 32 +# define TIOCPKT_IOCTL 64#define TIOCNOTTY 0x5422
@@ -91,6 +92,7 @@#define TIOCGSID 0x5429/* Return the session ID of FD */ #define TIOCGPTN _IOR('T',0x30, unsigned int)/* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int)/* Lock/unlock Pty */ +#define TIOCSIG _IOW('T',0x36, int)/* Generate signal on Pty slave */ #define TIOCSERCONFIG 0x5453#define TIOCSERGWILD 0x5454
arch/alpha/include/asm/termbits.h +1 -0
@@ -180,6 +180,7 @@ struct ktermios {#define FLUSHO 0x00800000#define PENDIN 0x20000000#define IEXTEN 0x00000400 +#define EXTPROC 0x10000000/* Values for the ACTION argument to `tcflow'. */ #define TCOOFF 0
arch/arm/include/asm/ioctls.h +2 -0
@@ -52,6 +52,7 @@#define TCSETSF2 _IOW('T',0x2D, struct termios2)#define TIOCGPTN _IOR('T',0x30, unsigned int)/* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int)/* Lock/unlock Pty */ +#define TIOCSIG _IOW('T',0x36, int)/* Generate signal on Pty slave */ #define TIOCGRS485 0x542E#define TIOCSRS485 0x542F
@@ -81,6 +82,7 @@#define TIOCPKT_START 8#define TIOCPKT_NOSTOP 16#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64#define TIOCSER_TEMT 0x01/* Transmitter physically empty */
arch/arm/include/asm/termbits.h +1 -0
@@ -177,6 +177,7 @@ struct ktermios {#define FLUSHO 0010000#define PENDIN 0040000#define IEXTEN 0100000 +#define EXTPROC 0200000/* tcflow() and TCXONC use these */ #define TCOOFF 0
arch/avr32/include/asm/ioctls.h +2 -0
@@ -53,6 +53,7 @@#define TCSETSF2 _IOW('T',0x2D, struct termios2)#define TIOCGPTN _IOR('T',0x30, unsigned int)/* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int)/* Lock/unlock Pty */ +#define TIOCSIG _IOW('T',0x36, int)/* Generate signal on Pty slave */ #define TIOCGRS485 0x542E#define TIOCSRS485 0x542F
@@ -82,6 +83,7 @@#define TIOCPKT_START 8#define TIOCPKT_NOSTOP 16#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64#define TIOCSER_TEMT 0x01/* Transmitter physically empty */
arch/avr32/include/asm/termbits.h +1 -0
@@ -175,6 +175,7 @@ struct ktermios {#define FLUSHO 0010000#define PENDIN 0040000#define IEXTEN 0100000 +#define EXTPROC 0200000/* tcflow() and TCXONC use these */ #define TCOOFF 0
arch/cris/include/asm/ioctls.h +2 -0
@@ -54,6 +54,7 @@#define TCSETSF2 _IOW('T',0x2D, struct termios2)#define TIOCGPTN _IOR('T',0x30, unsigned int)/* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int)/* Lock/unlock Pty */ +#define TIOCSIG _IOW('T',0x36, int)/* Generate signal on Pty slave */ #define FIONCLEX 0x5450/* these numbers need to be adjusted. */ #define FIOCLEX 0x5451
@@ -84,6 +85,7 @@#define TIOCPKT_START 8#define TIOCPKT_NOSTOP 16#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64#define TIOCSER_TEMT 0x01/* Transmitter physically empty */
arch/cris/include/asm/termbits.h +1 -0
@@ -214,6 +214,7 @@ struct ktermios {#define FLUSHO 0010000#define PENDIN 0040000#define IEXTEN 0100000 +#define EXTPROC 0200000/* tcflow() and TCXONC use these */ #define TCOOFF 0
arch/frv/include/asm/ioctls.h +2 -0
@@ -53,6 +53,7 @@#define TCSETSF2 _IOW('T',0x2D, struct termios2)#define TIOCGPTN _IOR('T',0x30, unsigned int)/* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int)/* Lock/unlock Pty */ +#define TIOCSIG _IOW('T',0x36, int)/* Generate signal on Pty slave */ #define FIONCLEX 0x5450/* these numbers need to be adjusted. */ #define FIOCLEX 0x5451
@@ -79,6 +80,7 @@#define TIOCPKT_START 8#define TIOCPKT_NOSTOP 16#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64#define TIOCSER_TEMT 0x01/* Transmitter physically empty */
arch/frv/include/asm/termbits.h +1 -0
@@ -180,6 +180,7 @@ struct ktermios {#define FLUSHO 0010000#define PENDIN 0040000#define IEXTEN 0100000 +#define EXTPROC 0200000/* tcflow() and TCXONC use these */
arch/h8300/include/asm/ioctls.h +2 -0
@@ -53,6 +53,7 @@#define TCSETSF2 _IOW('T',0x2D, struct termios2)#define TIOCGPTN _IOR('T',0x30, unsigned int)/* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int)/* Lock/unlock Pty */ +#define TIOCSIG _IOW('T',0x36, int)/* Generate signal on Pty slave */ #define FIONCLEX 0x5450/* these numbers need to be adjusted. */ #define FIOCLEX 0x5451
@@ -79,6 +80,7 @@#define TIOCPKT_START 8#define TIOCPKT_NOSTOP 16#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64#define TIOCSER_TEMT 0x01/* Transmitter physically empty */
arch/h8300/include/asm/termbits.h +1 -0
@@ -179,6 +179,7 @@ struct ktermios {#define FLUSHO 0010000#define PENDIN 0040000#define IEXTEN 0100000 +#define EXTPROC 0200000/* tcflow() and TCXONC use these */
arch/ia64/include/asm/ioctls.h +2 -0
@@ -59,6 +59,7 @@#define TCSETSF2 _IOW('T',0x2D, struct termios2)#define TIOCGPTN _IOR('T',0x30, unsigned int)/* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int)/* Lock/unlock Pty */ +#define TIOCSIG _IOW('T',0x36, int)/* Generate signal on Pty slave */ #define FIONCLEX 0x5450/* these numbers need to be adjusted. */ #define FIOCLEX 0x5451
@@ -85,6 +86,7 @@#define TIOCPKT_START 8#define TIOCPKT_NOSTOP 16#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64#define TIOCSER_TEMT 0x01/* Transmitter physically empty */
arch/ia64/include/asm/termbits.h +1 -0
@@ -187,6 +187,7 @@ struct ktermios {#define FLUSHO 0010000#define PENDIN 0040000#define IEXTEN 0100000 +#define EXTPROC 0200000/* tcflow() and TCXONC use these */ #define TCOOFF 0
arch/m32r/include/asm/ioctls.h +2 -0
@@ -53,6 +53,7 @@#define TCSETSF2 _IOW('T',0x2D, struct termios2)#define TIOCGPTN _IOR('T',0x30, unsigned int)/* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int)/* Lock/unlock Pty */ +#define TIOCSIG _IOW('T',0x36, int)/* Generate signal on Pty slave */ #define FIONCLEX 0x5450#define FIOCLEX 0x5451
@@ -79,6 +80,7 @@#define TIOCPKT_START 8#define TIOCPKT_NOSTOP 16#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64#define TIOCSER_TEMT 0x01/* Transmitter physically empty */
arch/m32r/include/asm/termbits.h +1 -0
@@ -179,6 +179,7 @@ struct ktermios {#define FLUSHO 0010000#define PENDIN 0040000#define IEXTEN 0100000 +#define EXTPROC 0200000/* tcflow() and TCXONC use these */ #define TCOOFF 0
arch/m68k/include/asm/ioctls.h +2 -0
@@ -52,6 +52,7 @@#define TCSETSF2 _IOW('T',0x2D, struct termios2)#define TIOCGPTN _IOR('T',0x30, unsigned int)/* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int)/* Lock/unlock Pty */ +#define TIOCSIG _IOW('T',0x36, int)/* Generate signal on Pty slave */ #define FIONCLEX 0x5450/* these numbers need to be adjusted. */ #define FIOCLEX 0x5451
@@ -78,6 +79,7 @@#define TIOCPKT_START 8#define TIOCPKT_NOSTOP 16#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64#define TIOCSER_TEMT 0x01/* Transmitter physically empty */
arch/m68k/include/asm/termbits.h +1 -0
@@ -179,6 +179,7 @@ struct ktermios {#define FLUSHO 0010000#define PENDIN 0040000#define IEXTEN 0100000 +#define EXTPROC 0200000/* tcflow() and TCXONC use these */
arch/mips/include/asm/ioctls.h +2 -1
@@ -41,7 +41,7 @@#define TIOCPKT_START 0x08/* start output */ #define TIOCPKT_NOSTOP 0x10/* no more ^S, ^Q */ #define TIOCPKT_DOSTOP 0x20/* now do ^S ^Q */ -/* #define TIOCPKT_IOCTL 0x40 state change of pty driver */ +#define TIOCPKT_IOCTL 0x40/* state change of pty driver */ #define TIOCSWINSZ _IOW('t', 103, struct winsize)/* set window size */ #define TIOCGWINSZ _IOR('t', 104, struct winsize)/* get window size */ #define TIOCNOTTY 0x5471/* void tty association */
@@ -83,6 +83,7 @@#define TCSETSF2 _IOW('T', 0x2D, struct termios2)#define TIOCGPTN _IOR('T', 0x30, unsigned int)/* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T', 0x31, int)/* Lock/unlock Pty */ +#define TIOCSIG _IOW('T', 0x36, int)/* Generate signal on Pty slave */ /* I hope the range from 0x5480 on is free ... */ #define TIOCSCTTY 0x5480/* become controlling tty */
arch/mips/include/asm/termbits.h +1 -0
@@ -203,6 +203,7 @@ struct ktermios {#define PENDIN 0040000/* Retype pending input (state). */ #define TOSTOP 0100000/* Send SIGTTOU for background output. */ #define ITOSTOP TOSTOP +#define EXTPROC 0200000/* External processing on pty */ /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ #define TIOCSER_TEMT 0x01/* Transmitter physically empty */
arch/mn10300/include/asm/ioctls.h +2 -0
@@ -54,6 +54,7 @@#define TIOCGPTN _IOR('T', 0x30, unsigned int)/* Get Pty Number * (of pty-mux device) */ #define TIOCSPTLCK _IOW('T', 0x31, int)/* Lock/unlock Pty */ +#define TIOCSIG _IOW('T', 0x36, int)/* Generate signal on Pty slave */ #define FIONCLEX 0x5450#define FIOCLEX 0x5451
@@ -80,6 +81,7 @@#define TIOCPKT_START 8#define TIOCPKT_NOSTOP 16#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64#define TIOCSER_TEMT 0x01/* Transmitter physically empty */
arch/mn10300/include/asm/termbits.h +1 -0
@@ -180,6 +180,7 @@ struct ktermios {#define FLUSHO 0010000#define PENDIN 0040000#define IEXTEN 0100000 +#define EXTPROC 0200000/* tcflow() and TCXONC use these */ #define TCOOFF 0
arch/parisc/include/asm/ioctls.h +2 -0
@@ -52,6 +52,7 @@#define TCSETSF2 _IOW('T',0x2D, struct termios2)#define TIOCGPTN _IOR('T',0x30, unsigned int)/* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int)/* Lock/unlock Pty */ +#define TIOCSIG _IOW('T',0x36, int)/* Generate signal on Pty slave */ #define FIONCLEX 0x5450/* these numbers need to be adjusted. */ #define FIOCLEX 0x5451
@@ -82,6 +83,7 @@#define TIOCPKT_START 8#define TIOCPKT_NOSTOP 16#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64#define TIOCSER_TEMT 0x01/* Transmitter physically empty */
arch/parisc/include/asm/termbits.h +1 -0
@@ -180,6 +180,7 @@ struct ktermios {#define FLUSHO 0010000#define PENDIN 0040000#define IEXTEN 0100000 +#define EXTPROC 0200000/* tcflow() and TCXONC use these */ #define TCOOFF 0
arch/powerpc/include/asm/ioctls.h +2 -0
@@ -80,6 +80,7 @@# define TIOCPKT_START 8# define TIOCPKT_NOSTOP 16# define TIOCPKT_DOSTOP 32 +# define TIOCPKT_IOCTL 64#define TIOCNOTTY 0x5422
@@ -93,6 +94,7 @@#define TIOCSRS485 0x542f#define TIOCGPTN _IOR('T',0x30, unsigned int)/* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int)/* Lock/unlock Pty */ +#define TIOCSIG _IOW('T',0x36, int)/* Generate signal on Pty slave */ #define TIOCSERCONFIG 0x5453#define TIOCSERGWILD 0x5454
arch/powerpc/include/asm/termbits.h +1 -0
@@ -189,6 +189,7 @@ struct ktermios {#define FLUSHO 0x00800000#define PENDIN 0x20000000#define IEXTEN 0x00000400 +#define EXTPROC 0x10000000/* Values for the ACTION argument to `tcflow'. */ #define TCOOFF 0
arch/s390/include/asm/ioctls.h +2 -0
@@ -60,6 +60,7 @@#define TCSETSF2 _IOW('T',0x2D, struct termios2)#define TIOCGPTN _IOR('T',0x30, unsigned int)/* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int)/* Lock/unlock Pty */ +#define TIOCSIG _IOW('T',0x36, int)/* Generate signal on Pty slave */ #define FIONCLEX 0x5450/* these numbers need to be adjusted. */ #define FIOCLEX 0x5451
@@ -86,6 +87,7 @@#define TIOCPKT_START 8#define TIOCPKT_NOSTOP 16#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64#define TIOCSER_TEMT 0x01/* Transmitter physically empty */
arch/sh/include/asm/ioctls.h +2 -0
@@ -69,6 +69,7 @@# define TIOCPKT_START 8# define TIOCPKT_NOSTOP 16# define TIOCPKT_DOSTOP 32 +# define TIOCPKT_IOCTL 64#define TIOCNOTTY _IO('T', 34)/* 0x5422 */
@@ -84,6 +85,7 @@#define TCSETSF2 _IOW('T', 45, struct termios2)#define TIOCGPTN _IOR('T',0x30, unsigned int)/* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int)/* Lock/unlock Pty */ +#define TIOCSIG _IOW('T',0x36, int)/* Generate signal on Pty slave */ #define TIOCSERCONFIG _IO('T', 83)/* 0x5453 */ #define TIOCSERGWILD _IOR('T', 84, int)/* 0x5454 */
arch/sparc/include/asm/ioctls.h +2 -0
@@ -80,6 +80,7 @@/* Get minor device of a pty master's FD -- Solaris equiv is ISPTM */ #define TIOCGPTN _IOR('t', 134, unsigned int)/* Get Pty Number */ #define TIOCSPTLCK _IOW('t', 135, int)/* Lock/unlock PTY */ +#define TIOCSIG _IOW('t', 136, int)/* Generate signal on Pty slave */ /* Little f */ #define FIOCLEX _IO('f', 1)
@@ -132,5 +133,6 @@#define TIOCPKT_START 8#define TIOCPKT_NOSTOP 16#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64#endif /* !(_ASM_SPARC_IOCTLS_H) */
arch/sparc/include/asm/termbits.h +1 -0
@@ -225,6 +225,7 @@ struct ktermios {#define FLUSHO 0x00002000#define PENDIN 0x00004000#define IEXTEN 0x00008000 +#define EXTPROC 0x00010000/* modem lines */ #define TIOCM_LE 0x001
arch/xtensa/include/asm/ioctls.h +2 -0
@@ -81,6 +81,7 @@# define TIOCPKT_START 8# define TIOCPKT_NOSTOP 16# define TIOCPKT_DOSTOP 32 +# define TIOCPKT_IOCTL 64#define TIOCNOTTY _IO('T', 34)
@@ -97,6 +98,7 @@#define TCSETSF2 _IOW('T', 45, struct termios2)#define TIOCGPTN _IOR('T',0x30, unsigned int)/* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int)/* Lock/unlock Pty */ +#define TIOCSIG _IOW('T',0x36, int)/* Generate signal on Pty slave */ #define TIOCSERCONFIG _IO('T', 83)#define TIOCSERGWILD _IOR('T', 84, int)
arch/xtensa/include/asm/termbits.h +1 -0
@@ -196,6 +196,7 @@ struct ktermios {#define FLUSHO 0010000#define PENDIN 0040000#define IEXTEN 0100000 +#define EXTPROC 0200000/* tcflow() and TCXONC use these */
drivers/char/n_tty.c +14 -3
@@ -1102,6 +1102,11 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)if (I_IUCLC (tty) &&L_IEXTEN (tty)) c =tolower (c); +if (L_EXTPROC (tty)) { +put_tty_queue (c, tty); +return ; + } +if (tty->stopped && !tty->flow_stopped &&I_IXON (tty) &&I_IXANY (tty) && c !=START_CHAR (tty) && c !=STOP_CHAR (tty) && c !=INTR_CHAR (tty) && c !=QUIT_CHAR (tty) && c !=SUSP_CHAR (tty)) {
@@ -1409,7 +1414,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,n_tty_set_room (tty); -if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) { +if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) || +L_EXTPROC (tty)) {kill_fasync (&tty->fasync,SIGIO ,POLL_IN );if (waitqueue_active (&tty->read_wait))wake_up_interruptible (&tty->read_wait);
@@ -1585,7 +1591,7 @@ static int n_tty_open(struct tty_struct *tty)static inline int input_available_p (struct tty_struct *tty,int amt) {tty_flush_to_ldisc (tty); -if (tty->icanon) { +if (tty->icanon && !L_EXTPROC (tty)) {if (tty->canon_data)return 1 ; }else if (tty->read_cnt >= (amt ? amt :1 ))
@@ -1632,6 +1638,11 @@ static int copy_from_read_buf(struct tty_struct *tty,spin_lock_irqsave (&tty->read_lock, flags); tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE -1 ); tty->read_cnt -= n; +/* Turn single EOF into zero-length read */ +if (L_EXTPROC (tty) && tty->icanon && n ==1 ) { +if (!tty->read_cnt && (*b)[n-1 ] ==EOF_CHAR (tty)) + n--; + }spin_unlock_irqrestore (&tty->read_lock, flags); *b += n; *nr -= n;
@@ -1812,7 +1823,7 @@ do_it_again: nr--; } -if (tty->icanon) { +if (tty->icanon && !L_EXTPROC (tty)) {/* N.B. avoid overrun if nr == 0 */ while (nr && tty->read_cnt) {int eol;
drivers/char/pty.c +21 -0
@@ -171,6 +171,23 @@ static int pty_set_lock(struct tty_struct *tty, int __user *arg)return 0 ; } +/* Send a signal to the slave */ +static int pty_signal (struct tty_struct *tty,int sig) +{ +unsigned long flags; +struct pid *pgrp; + +if (tty->link) { +spin_lock_irqsave (&tty->link->ctrl_lock, flags); + pgrp =get_pid (tty->link->pgrp); +spin_unlock_irqrestore (&tty->link->ctrl_lock, flags); + +kill_pgrp (pgrp, sig,1 ); +put_pid (pgrp); + } +return 0 ; +} +static void pty_flush_buffer (struct tty_struct *tty) {struct tty_struct *to = tty->link;
@@ -321,6 +338,8 @@ static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file,switch (cmd) {case TIOCSPTLCK :/* Set PT Lock (disallow slave open) */ return pty_set_lock (tty, (int __user *) arg); +case TIOCSIG :/* Send signal to other side of pty */ +return pty_signal (tty, (int ) arg); }return -ENOIOCTLCMD ; }
@@ -476,6 +495,8 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,return pty_set_lock (tty, (int __user *)arg);case TIOCGPTN :/* Get PT Number */ return put_user (tty->index, (unsigned int __user *)arg); +case TIOCSIG :/* Send signal to other side of pty */ +return pty_signal (tty, (int ) arg); }return -ENOIOCTLCMD ;
drivers/char/tty_ioctl.c +12 -6
@@ -517,19 +517,25 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)/* See if packet mode change of state. */ if (tty->link && tty->link->packet) { +int extproc = (old_termios.c_lflag &EXTPROC ) | + (tty->termios->c_lflag &EXTPROC );int old_flow = ((old_termios.c_iflag &IXON ) && (old_termios.c_cc[VSTOP ] =='\023' ) && (old_termios.c_cc[VSTART ] =='\021' ));int new_flow = (I_IXON (tty) &&STOP_CHAR (tty) =='\023' &&START_CHAR (tty) =='\021' ); -if (old_flow != new_flow) { +if ((old_flow != new_flow) || extproc) {spin_lock_irqsave (&tty->ctrl_lock, flags); - tty->ctrl_status &= ~(TIOCPKT_DOSTOP |TIOCPKT_NOSTOP ); -if (new_flow) - tty->ctrl_status |=TIOCPKT_DOSTOP ; -else - tty->ctrl_status |=TIOCPKT_NOSTOP ; +if (old_flow != new_flow) { + tty->ctrl_status &= ~(TIOCPKT_DOSTOP |TIOCPKT_NOSTOP ); +if (new_flow) + tty->ctrl_status |=TIOCPKT_DOSTOP ; +else + tty->ctrl_status |=TIOCPKT_NOSTOP ; + } +if (extproc) + tty->ctrl_status |=TIOCPKT_IOCTL ;spin_unlock_irqrestore (&tty->ctrl_lock, flags);wake_up_interruptible (&tty->link->read_wait); }
fs/compat_ioctl.c +1 -0
@@ -969,6 +969,7 @@ COMPATIBLE_IOCTL(TIOCGPGRP) COMPATIBLE_IOCTL(TIOCGPTN) COMPATIBLE_IOCTL(TIOCSPTLCK) COMPATIBLE_IOCTL(TIOCSERGETLSR) +COMPATIBLE_IOCTL(TIOCSIG) #ifdef TCGETS2 COMPATIBLE_IOCTL(TCGETS2) COMPATIBLE_IOCTL(TCSETS2)
include/asm-generic/ioctls.h +2 -0
@@ -69,6 +69,7 @@#define TCSETX 0x5433#define TCSETXF 0x5434#define TCSETXW 0x5435 +#define TIOCSIG _IOW('T', 0x36, int)/* pty: generate signal */ #define FIONCLEX 0x5450#define FIOCLEX 0x5451
@@ -102,6 +103,7 @@#define TIOCPKT_START 8#define TIOCPKT_NOSTOP 16#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64#define TIOCSER_TEMT 0x01/* Transmitter physically empty */
include/asm-generic/termbits.h +1 -0
@@ -178,6 +178,7 @@ struct ktermios {#define FLUSHO 0010000#define PENDIN 0040000#define IEXTEN 0100000 +#define EXTPROC 0200000/* tcflow() and TCXONC use these */ #define TCOOFF 0
include/linux/tty.h +1 -0
@@ -179,6 +179,7 @@ struct tty_bufhead {#define L_FLUSHO (tty) _L_FLAG((tty), FLUSHO)#define L_PENDIN (tty) _L_FLAG((tty), PENDIN)#define L_IEXTEN (tty) _L_FLAG((tty), IEXTEN) +#define L_EXTPROC (tty) _L_FLAG((tty), EXTPROC)struct device ;struct signal_struct ;
Signature · 1 line
1.7.2
PATCH 12/67 vt/console: try harder to print output when panicing
In reply to Greg KHFrom: Jesse Barnes <[email protected]>
Jesse's initial patch commit said:
"At panic time (i.e. when oops_in_progress is set) we should try a bit harder to update the screen and make sure output gets to the VT, since some drivers are capable of flipping back to it.
So make sure we try to unblank and update the display if called from a panic context."
I've enhanced this to add a flag to the vc that console layer can set to indicate they want this behaviour to occur. This also adds support to fbcon for that flag and adds an fb flag for drivers to indicate they want to use the support. It enables this for KMS drivers.
--- drivers/char/vt.c | 13 +++++++++---- drivers/gpu/drm/i915/intel_fb.c | 4 +--- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 1 + drivers/gpu/drm/radeon/radeon_fb.c | 2 +- drivers/video/console/fbcon.c | 4 +++- include/linux/console_struct.h | 1 + include/linux/fb.h | 4 ++++ include/linux/vt_kern.h | 7 +++++++ 8 files changed, 27 insertions(+), 9 deletions(-)
drivers/char/vt.c +9 -4
@@ -699,7 +699,10 @@ void redraw_screen(struct vc_data *vc, int is_switch)update_attr (vc);clear_buffer_attributes (vc); } -if (update && vc->vc_mode !=KD_GRAPHICS ) + +/* Forcibly update if we're panicing */ +if ((update && vc->vc_mode !=KD_GRAPHICS ) || +vt_force_oops_output (vc))do_update_region (vc, vc->vc_origin, vc->vc_screenbuf_size /2 ); }set_cursor (vc);
@@ -737,6 +740,7 @@ static void visual_init(struct vc_data *vc, int num, int init) vc->vc_hi_font_mask =0 ; vc->vc_complement_mask =0 ; vc->vc_can_do_color =0 ; + vc->vc_panic_force_write = false; vc->vc_sw->con_init (vc, init);if (!vc->vc_complement_mask) vc->vc_complement_mask = vc->vc_can_do_color ?0x7700 :0x0800 ;
@@ -2499,7 +2503,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) goto quit; } -if (vc->vc_mode !=KD_TEXT ) +if (vc->vc_mode !=KD_TEXT && !vt_force_oops_output (vc)) goto quit;/* undraw cursor first */
@@ -3704,7 +3708,8 @@ void do_unblank_screen(int leaving_gfx)return ; } vc = vc_cons[fg_console].d; -if (vc->vc_mode !=KD_TEXT ) +/* Try to unblank in oops case too */ +if (vc->vc_mode !=KD_TEXT && !vt_force_oops_output (vc))return ;/* but leave console_blanked != 0 */ if (blankinterval) {
@@ -3713,7 +3718,7 @@ void do_unblank_screen(int leaving_gfx) } console_blanked =0 ; -if (vc->vc_sw->con_blank (vc,0 , leaving_gfx)) +if (vc->vc_sw->con_blank (vc,0 , leaving_gfx) ||vt_force_oops_output (vc))/* Low-level driver cannot restore -> do it ourselves */ update_screen (vc);if (console_blank_hook)
drivers/gpu/drm/i915/intel_fb.c +1 -3
@@ -128,7 +128,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev,strcpy (info->fix.id,"inteldrmfb" ); - info->flags =FBINFO_DEFAULT ; + info->flags =FBINFO_DEFAULT |FBINFO_CAN_FORCE_OUTPUT ; info->fbops = &intelfb_ops;/* setup aperture base/size for vesafb takeover */
@@ -146,8 +146,6 @@ static int intelfb_create(struct intel_fbdev *ifbdev, info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset; info->fix.smem_len = size; - info->flags =FBINFO_DEFAULT ; - info->screen_base =ioremap_wc (dev->agp->base + obj_priv->gtt_offset, size);if (!info->screen_base) {
drivers/gpu/drm/nouveau/nouveau_fbcon.c +1 -0
@@ -250,6 +250,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, info->flags =FBINFO_DEFAULT |FBINFO_HWACCEL_COPYAREA |FBINFO_HWACCEL_FILLRECT |FBINFO_HWACCEL_IMAGEBLIT ; + info->flags |=FBINFO_CAN_FORCE_OUTPUT ; info->fbops = &nouveau_fbcon_ops; info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset - dev_priv->vm_vram_base;
drivers/gpu/drm/radeon/radeon_fb.c +1 -1
@@ -224,7 +224,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,drm_fb_helper_fill_fix (info, fb->pitch, fb->depth); - info->flags =FBINFO_DEFAULT ; + info->flags =FBINFO_DEFAULT |FBINFO_CAN_FORCE_OUTPUT ; info->fbops = &radeonfb_ops; tmp =radeon_bo_gpu_offset (rbo) - rdev->mc.vram_start;
drivers/video/console/fbcon.c +3 -1
@@ -283,7 +283,8 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)struct fbcon_ops *ops = info->fbcon_par;return (info->state !=FBINFO_STATE_RUNNING || - vc->vc_mode !=KD_TEXT || ops->graphics); + vc->vc_mode !=KD_TEXT || ops->graphics) && + !vt_force_oops_output (vc); } static inline int get_color(struct vc_data *vc, struct fb_info *info,
@@ -1073,6 +1074,7 @@ static void fbcon_init(struct vc_data *vc, int init)if (p->userfont) charcnt =FNTCHARCNT (p->fontdata); + vc->vc_panic_force_write = !!(info->flags &FBINFO_CAN_FORCE_OUTPUT ); vc->vc_can_do_color = (fb_get_color_depth (&info->var, &info->fix)!=1 ); vc->vc_complement_mask = vc->vc_can_do_color ?0x7700 :0x0800 ;if (charcnt ==256 ) {
include/linux/console_struct.h +1 -0
@@ -105,6 +105,7 @@ struct vc_data {struct vc_data **vc_display_fg;/* [!] Ptr to var holding fg console for this display */ unsigned long vc_uni_pagedir;unsigned long *vc_uni_pagedir_loc;/* [!] Location of uni_pagedir variable for this console */ +bool vc_panic_force_write;/* when oops/panic this VC can accept forced output/blanking */ /* additional information is in vt_kern.h */ };
include/linux/fb.h +4 -0
@@ -812,6 +812,10 @@ struct fb_tile_ops {*/ #define FBINFO_BE_MATH 0x100000 +/* report to the VT layer that this fb driver can accept forced console +output like oopses */ +#define FBINFO_CAN_FORCE_OUTPUT 0x200000 +struct fb_info {int node;int flags;
include/linux/vt_kern.h +7 -0
@@ -100,6 +100,13 @@ extern int unbind_con_driver(const struct consw *csw, int first, int last, int deflt);int vty_init (const struct file_operations *console_fops); +static inline bool vt_force_oops_output (struct vc_data *vc) +{ +if (oops_in_progress && vc->vc_panic_force_write) +return true; +return false; +} +/* * vc_screen.c shares this temporary buffer with the console write code so that * we can easily avoid touching user space while holding the console spinlock.
Signature · 1 line
1.7.2
PATCH 13/67 stallion: prune lock_kernel calls
In reply to Greg KHFrom: Alan Cox <[email protected]>
Remove unneeded tty layer lock kernel bits. Relock the needed bits using the port mutex. The istallion still has brd state races but those are not new or introduced by the removal of the lock_kernel logic.
--- drivers/char/istallion.c | 22 +++++++++++++--------- drivers/char/stallion.c | 20 ++++++++++++-------- 2 files changed, 25 insertions(+), 17 deletions(-)
drivers/char/istallion.c +13 -9
@@ -14,6 +14,7 @@* the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * +* FIXME: brdp->state needs proper locking. */ /*****************************************************************************/
@@ -4011,6 +4012,7 @@ static int stli_getbrdstats(combrd_t __user *bp)return -ENODEV ;memset (&stli_brdstats,0 ,sizeof (combrd_t)); + stli_brdstats.brd = brdp->brdnr; stli_brdstats.type = brdp->brdtype; stli_brdstats.hwid =0 ;
@@ -4076,10 +4078,13 @@ static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp)if (brdp ==NULL )return -ENODEV ; +mutex_lock (&portp->port.mutex);if (brdp->state &BST_STARTED ) {if ((rc =stli_cmdwait (brdp, portp,A_GETSTATS , - &stli_cdkstats,sizeof (asystats_t),1 )) <0 ) + &stli_cdkstats,sizeof (asystats_t),1 )) <0 ) { +mutex_unlock (&portp->port.mutex);return rc; + } }else {memset (&stli_cdkstats,0 ,sizeof (asystats_t)); }
@@ -4124,6 +4129,7 @@ static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp) stli_comstats.modem = stli_cdkstats.dcdcnt; stli_comstats.hwid = stli_cdkstats.hwid; stli_comstats.signals =stli_mktiocm (stli_cdkstats.signals); +mutex_unlock (&portp->port.mutex);return 0 ; }
@@ -4186,15 +4192,20 @@ static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp)if (!brdp)return -ENODEV ; +mutex_lock (&portp->port.mutex); +if (brdp->state &BST_STARTED ) { -if ((rc =stli_cmdwait (brdp, portp,A_CLEARSTATS ,NULL ,0 ,0 )) <0 ) +if ((rc =stli_cmdwait (brdp, portp,A_CLEARSTATS ,NULL ,0 ,0 )) <0 ) { +mutex_unlock (&portp->port.mutex);return rc; + } }memset (&stli_comstats,0 ,sizeof (comstats_t)); stli_comstats.brd = portp->brdnr; stli_comstats.panel = portp->panelnr; stli_comstats.port = portp->portnr; +mutex_unlock (&portp->port.mutex);if (copy_to_user (cp, &stli_comstats,sizeof (comstats_t)))return -EFAULT ;
@@ -4266,8 +4277,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) done =0 ; rc =0 ; -lock_kernel (); -switch (cmd) {case COM_GETPORTSTATS : rc =stli_getportstats (NULL ,NULL , argp);
@@ -4290,8 +4299,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) done++;break ; } -unlock_kernel (); -if (done)return rc;
@@ -4308,8 +4315,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)if (brdp->state ==0 )return -ENODEV ; -lock_kernel (); -switch (cmd) {case STL_BINTR :EBRDINTR (brdp);
@@ -4332,7 +4337,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) rc = -ENOIOCTLCMD ;break ; } -unlock_kernel ();return rc; }
drivers/char/stallion.c +12 -8
@@ -807,7 +807,6 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout) timeout =HZ ; tend = jiffies + timeout; -lock_kernel ();while (stl_datastate (portp)) {if (signal_pending (current))break ;
@@ -815,7 +814,6 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)if (time_after_eq (jiffies, tend))break ; } -unlock_kernel (); }/*****************************************************************************/
@@ -1029,6 +1027,8 @@ static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)pr_debug ("stl_getserial(portp=%p,sp=%p)\n" , portp, sp);memset (&sio,0 ,sizeof (struct serial_struct )); + +mutex_lock (&portp->port.mutex); sio.line = portp->portnr; sio.port = portp->ioaddr; sio.flags = portp->port.flags;
@@ -1048,6 +1048,7 @@ static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp) brdp = stl_brds[portp->brdnr];if (brdp !=NULL ) sio.irq = brdp->irq; +mutex_unlock (&portp->port.mutex);return copy_to_user (sp, &sio,sizeof (struct serial_struct )) ? -EFAULT :0 ; }
@@ -1069,12 +1070,15 @@ static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *spif (copy_from_user (&sio, sp,sizeof (struct serial_struct )))return -EFAULT ; +mutex_lock (&portp->port.mutex);if (!capable (CAP_SYS_ADMIN )) {if ((sio.baud_base != portp->baud_base) || (sio.close_delay != portp->close_delay) || ((sio.flags & ~ASYNC_USR_MASK ) != - (portp->port.flags & ~ASYNC_USR_MASK ))) + (portp->port.flags & ~ASYNC_USR_MASK ))) { +mutex_unlock (&portp->port.mutex);return -EPERM ; + } } portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
@@ -1083,6 +1087,7 @@ static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp portp->close_delay = sio.close_delay; portp->closing_wait = sio.closing_wait; portp->custom_divisor = sio.custom_divisor; +mutex_unlock (&portp->port.mutex);stl_setport (portp, tty->termios);return 0 ; }
@@ -1147,8 +1152,6 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd rc =0 ; -lock_kernel (); -switch (cmd) {case TIOCGSERIAL : rc =stl_getserial (portp, argp);
@@ -1173,7 +1176,6 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd rc = -ENOIOCTLCMD ;break ; } -unlock_kernel ();return rc; }
@@ -2327,6 +2329,7 @@ static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstreturn -ENODEV ; } +mutex_lock (&portp->port.mutex); portp->stats.state = portp->istate; portp->stats.flags = portp->port.flags; portp->stats.hwid = portp->hwid;
@@ -2358,6 +2361,7 @@ static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comst (STL_TXBUFSIZE - (tail - head)); portp->stats.signals = (unsigned long )stl_getsignals (portp); +mutex_unlock (&portp->port.mutex);return copy_to_user (cp, &portp->stats,sizeof (comstats_t)) ? -EFAULT :0 ;
@@ -2382,10 +2386,12 @@ static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)return -ENODEV ; } +mutex_lock (&portp->port.mutex);memset (&portp->stats,0 ,sizeof (comstats_t)); portp->stats.brd = portp->brdnr; portp->stats.panel = portp->panelnr; portp->stats.port = portp->portnr; +mutex_unlock (&portp->port.mutex);return copy_to_user (cp, &portp->stats,sizeof (comstats_t)) ? -EFAULT :0 ; }
@@ -2451,7 +2457,6 @@ static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)return -ENODEV ; rc =0 ; -lock_kernel ();switch (cmd) {case COM_GETPORTSTATS : rc =stl_getportstats (NULL ,NULL , argp);
@@ -2472,7 +2477,6 @@ static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) rc = -ENOIOCTLCMD ;break ; } -unlock_kernel ();return rc; }
Signature · 1 line
1.7.2
PATCH 14/67 istallion: use bit ops for the board flags
In reply to Greg KHFrom: Alan Cox <[email protected]>
This lets us avoid problems with races on the flag changes
--- drivers/char/istallion.c | 36 ++++++++++++++++++------------------ include/linux/istallion.h | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-)
drivers/char/istallion.c +18 -18
@@ -14,7 +14,6 @@* the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * -* FIXME: brdp->state needs proper locking. */ /*****************************************************************************/
@@ -204,9 +203,9 @@ static int stli_shared;* the board has been detected, and whether it is actually running a slave * or not. */ -#define BST_FOUND 0x1 -#define BST_STARTED 0x2 -#define BST_PROBED 0x4 +#define BST_FOUND 0 +#define BST_STARTED 1 +#define BST_PROBED 2/* * Define the set of port state flags. These are marked for internal
@@ -817,7 +816,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp) brdp = stli_brds[brdnr];if (brdp ==NULL )return -ENODEV ; -if ((brdp->state &BST_STARTED ) ==0 ) +if (!test_bit (BST_STARTED , &brdp->state))return -ENODEV ; portnr =MINOR2PORT (minordev);if (portnr > brdp->nrports)
@@ -1847,7 +1846,7 @@ static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stlip rc =stli_portcmdstats (NULL , portp); uart ="UNKNOWN" ; -if (brdp->state &BST_STARTED ) { +if (test_bit (BST_STARTED , &brdp->state)) {switch (stli_comstats.hwid) {case 0 : uart ="2681" ;break ;case 1 : uart ="SC26198" ;break ;
@@ -1856,7 +1855,7 @@ static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stlip }seq_printf (m,"%d: uart:%s " , portnr, uart); -if ((brdp->state &BST_STARTED ) && (rc >=0 )) { +if (test_bit (BST_STARTED , &brdp->state) && rc >=0 ) {char sep; seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal,
@@ -2356,7 +2355,7 @@ static void stli_poll(unsigned long arg) brdp = stli_brds[brdnr];if (brdp ==NULL )continue ; -if ((brdp->state &BST_STARTED ) ==0 ) +if (!test_bit (BST_STARTED , &brdp->state))continue ;spin_lock (&brd_lock);
@@ -3141,7 +3140,7 @@ static int stli_initecp(struct stlibrd *brdp) } - brdp->state |=BST_FOUND ; +set_bit (BST_FOUND , &brdp->state);return 0 ; err_unmap:iounmap (brdp->membase);
@@ -3298,7 +3297,7 @@ static int stli_initonb(struct stlibrd *brdp) brdp->panels[0 ] = brdp->nrports; - brdp->state |=BST_FOUND ; +set_bit (BST_FOUND , &brdp->state);return 0 ; err_unmap:iounmap (brdp->membase);
@@ -3408,7 +3407,7 @@ stli_donestartup:spin_unlock_irqrestore (&brd_lock, flags);if (rc ==0 ) - brdp->state |=BST_STARTED ; +set_bit (BST_STARTED , &brdp->state);if (! stli_timeron) { stli_timeron++;
@@ -3711,7 +3710,7 @@ static int __devinit stli_pciprobe(struct pci_dev *pdev,if (retval) goto err_null; - brdp->state |=BST_PROBED ; +set_bit (BST_PROBED , &brdp->state);pci_set_drvdata (pdev, brdp);EBRDENABLE (brdp);
@@ -3842,7 +3841,7 @@ static int __init stli_initbrds(void) brdp = stli_brds[i];if (brdp ==NULL )continue ; -if (brdp->state &BST_FOUND ) { +if (test_bit (BST_FOUND , &brdp->state)) {EBRDENABLE (brdp); brdp->enable =NULL ; brdp->disable =NULL ;
@@ -4079,7 +4078,7 @@ static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp)return -ENODEV ;mutex_lock (&portp->port.mutex); -if (brdp->state &BST_STARTED ) { +if (test_bit (BST_STARTED , &brdp->state)) {if ((rc =stli_cmdwait (brdp, portp,A_GETSTATS , &stli_cdkstats,sizeof (asystats_t),1 )) <0 ) {mutex_unlock (&portp->port.mutex);
@@ -4194,7 +4193,7 @@ static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp)mutex_lock (&portp->port.mutex); -if (brdp->state &BST_STARTED ) { +if (test_bit (BST_STARTED , &brdp->state)) {if ((rc =stli_cmdwait (brdp, portp,A_CLEARSTATS ,NULL ,0 ,0 )) <0 ) {mutex_unlock (&portp->port.mutex);return rc;
@@ -4323,10 +4322,10 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) rc =stli_startbrd (brdp);break ;case STL_BSTOP : - brdp->state &= ~BST_STARTED ; +clear_bit (BST_STARTED , &brdp->state);break ;case STL_BRESET : - brdp->state &= ~BST_STARTED ; +clear_bit (BST_STARTED , &brdp->state);EBRDRESET (brdp);if (stli_shared ==0 ) {if (brdp->reenable !=NULL )
@@ -4382,7 +4381,8 @@ static void istallion_cleanup_isa(void)unsigned int j;for (j =0 ; (j < stli_nrbrds); j++) { -if ((brdp = stli_brds[j]) ==NULL || (brdp->state &BST_PROBED )) +if ((brdp = stli_brds[j]) ==NULL || +test_bit (BST_PROBED , &brdp->state))continue ;stli_cleanup_ports (brdp);
include/linux/istallion.h +1 -1
@@ -86,7 +86,7 @@ struct stlibrd {unsigned long magic;unsigned int brdnr;unsigned int brdtype; -unsigned int state; +unsigned long state;unsigned int nrpanels;unsigned int nrports;unsigned int nrdevs;
Signature · 1 line
1.7.2
PATCH 15/67 riscom8: kill use of lock_kernel
In reply to Greg KHFrom: Alan Cox <[email protected]>
The riscom8 board uses lock_kernel to protect bits of the port setting ioctl logic. We can use the port mutex for this as the logic is internal and will also lock set versus open (a locking property that has been lost somewhere along the way)
--- drivers/char/riscom8.c | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-)
drivers/char/riscom8.c +8 -6
@@ -47,7 +47,6 @@#include <linux/init.h> #include <linux/delay.h> #include <linux/tty_flip.h> -#include <linux/smp_lock.h> #include <linux/spinlock.h> #include <linux/device.h>
@@ -1184,6 +1183,7 @@ static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port,if (copy_from_user (&tmp, newinfo,sizeof (tmp)))return -EFAULT ; +mutex_lock (&port->port.mutex); change_speed = ((port->port.flags &ASYNC_SPD_MASK ) != (tmp.flags &ASYNC_SPD_MASK ));
@@ -1191,8 +1191,10 @@ static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port,if ((tmp.close_delay != port->port.close_delay) || (tmp.closing_wait != port->port.closing_wait) || ((tmp.flags & ~ASYNC_USR_MASK ) != - (port->port.flags & ~ASYNC_USR_MASK ))) + (port->port.flags & ~ASYNC_USR_MASK ))) { +mutex_unlock (&port->port.mutex);return -EPERM ; + } port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK ) | (tmp.flags &ASYNC_USR_MASK )); }else {
@@ -1208,6 +1210,7 @@ static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port,rc_change_speed (tty, bp, port);spin_unlock_irqrestore (&riscom_lock, flags); } +mutex_unlock (&port->port.mutex);return 0 ; }
@@ -1220,12 +1223,15 @@ static int rc_get_serial_info(struct riscom_port *port,memset (&tmp,0 ,sizeof (tmp)); tmp.type =PORT_CIRRUS ; tmp.line = port - rc_port; + +mutex_lock (&port->port.mutex); tmp.port = bp->base; tmp.irq = bp->irq; tmp.flags = port->port.flags; tmp.baud_base = (RC_OSCFREQ +CD180_TPC /2 ) /CD180_TPC ; tmp.close_delay = port->port.close_delay *HZ /100 ; tmp.closing_wait = port->port.closing_wait *HZ /100 ; +mutex_unlock (&port->port.mutex); tmp.xmit_fifo_size =CD180_NFIFO ;return copy_to_user (retinfo, &tmp,sizeof (tmp)) ? -EFAULT :0 ; }
@@ -1242,14 +1248,10 @@ static int rc_ioctl(struct tty_struct *tty, struct file *filp,switch (cmd) {case TIOCGSERIAL : -lock_kernel (); retval =rc_get_serial_info (port, argp); -unlock_kernel ();break ;case TIOCSSERIAL : -lock_kernel (); retval =rc_set_serial_info (tty, port, argp); -unlock_kernel ();break ;default : retval = -ENOIOCTLCMD ;
Signature · 1 line
1.7.2
PATCH 16/67 isicom: kill off the BKL
In reply to Greg KHFrom: Alan Cox <[email protected]>
As with the others we can use the port mutex to get the needed locking properties and fix the race with open.
--- drivers/char/isicom.c | 13 +++++-------- 1 files changed, 5 insertions(+), 8 deletions(-)
drivers/char/isicom.c +5 -8
@@ -124,7 +124,6 @@#include <linux/fs.h> #include <linux/sched.h> #include <linux/serial.h> -#include <linux/smp_lock.h> #include <linux/mm.h> #include <linux/interrupt.h> #include <linux/timer.h>
@@ -872,7 +871,6 @@ static struct tty_port *isicom_find_port(struct tty_struct *tty)static int isicom_open (struct tty_struct *tty,struct file *filp) {struct isi_port *port; -struct isi_board *card;struct tty_port *tport; tport =isicom_find_port (tty);
@@ -1118,8 +1116,7 @@ static int isicom_set_serial_info(struct tty_struct *tty,if (copy_from_user (&newinfo, info,sizeof (newinfo)))return -EFAULT ; -lock_kernel (); - +mutex_lock (&port->port.mutex); reconfig_port = ((port->port.flags &ASYNC_SPD_MASK ) != (newinfo.flags &ASYNC_SPD_MASK ));
@@ -1128,7 +1125,7 @@ static int isicom_set_serial_info(struct tty_struct *tty, (newinfo.closing_wait != port->port.closing_wait) || ((newinfo.flags & ~ASYNC_USR_MASK) != (port->port.flags & ~ASYNC_USR_MASK))) { -unlock_kernel (); +mutex_unlock (&port->port.mutex);return -EPERM ; } port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
@@ -1145,7 +1142,7 @@ static int isicom_set_serial_info(struct tty_struct *tty,isicom_config_port (tty);spin_unlock_irqrestore (&port->card->card_lock, flags); } -unlock_kernel (); +mutex_unlock (&port->port.mutex);return 0 ; }
@@ -1154,7 +1151,7 @@ static int isicom_get_serial_info(struct isi_port *port, {struct serial_struct out_info; -lock_kernel (); +mutex_lock (&port->port.mutex);memset (&out_info,0 ,sizeof (out_info));/* out_info.type = ? */ out_info.line = port - isi_ports;
@@ -1164,7 +1161,7 @@ static int isicom_get_serial_info(struct isi_port *port,/* out_info.baud_base = ? */ out_info.close_delay = port->port.close_delay; out_info.closing_wait = port->port.closing_wait; -unlock_kernel (); +mutex_unlock (&port->port.mutex);if (copy_to_user (info, &out_info,sizeof (out_info)))return -EFAULT ;return 0 ;
Signature · 1 line
1.7.2
PATCH 17/67 rocket: kill BKL
In reply to Greg KHFrom: Alan Cox <[email protected]>
We can use the port mutex for this and also for the hangup path so removing the problematic use of the hangup mutex in this driver. Fix up the locking on the various port flags while we are at it.
Ultimately this driver needs to be using tty_port_ helpers which would sort this out far better.
--- drivers/char/rocket.c | 28 +++++++++++++++++++--------- 1 files changed, 19 insertions(+), 9 deletions(-)
drivers/char/rocket.c +19 -9
@@ -73,7 +73,6 @@#include <linux/tty_driver.h> #include <linux/tty_flip.h> #include <linux/serial.h> -#include <linux/smp_lock.h> #include <linux/string.h> #include <linux/fcntl.h> #include <linux/ptrace.h>
@@ -1017,6 +1016,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp)if (tty_port_close_start (port, tty, filp) ==0 )return ; +mutex_lock (&port->mutex); cp = &info->channel;/* * Before we drop DTR, make sure the UART transmitter
@@ -1060,9 +1060,13 @@ static void rp_close(struct tty_struct *tty, struct file *filp) info->xmit_buf =NULL ; } } +spin_lock_irq (&port->lock); info->port.flags &= ~(ASYNC_INITIALIZED |ASYNC_CLOSING |ASYNC_NORMAL_ACTIVE ); tty->closing =0 ; +spin_unlock_irq (&port->lock); +mutex_unlock (&port->mutex);tty_port_tty_set (port,NULL ); +wake_up_interruptible (&port->close_wait);complete_all (&info->close_wait);atomic_dec (&rp_num_ports_open);
@@ -1210,11 +1214,13 @@ static int get_config(struct r_port *info, struct rocket_config __user *retinfo)if (!retinfo)return -EFAULT ;memset (&tmp,0 ,sizeof (tmp)); +mutex_lock (&info->port.mutex); tmp.line = info->line; tmp.flags = info->flags; tmp.close_delay = info->port.close_delay; tmp.closing_wait = info->port.closing_wait; tmp.port = rcktpt_io_addr[(info->line >>5 ) &3 ]; +mutex_unlock (&info->port.mutex);if (copy_to_user (retinfo, &tmp,sizeof (*retinfo)))return -EFAULT ;
@@ -1229,10 +1235,13 @@ static int set_config(struct tty_struct *tty, struct r_port *info,if (copy_from_user (&new_serial, new_info,sizeof (new_serial)))return -EFAULT ; +mutex_lock (&info->port.mutex);if (!capable (CAP_SYS_ADMIN )) { -if ((new_serial.flags & ~ROCKET_USR_MASK ) != (info->flags & ~ROCKET_USR_MASK )) +if ((new_serial.flags & ~ROCKET_USR_MASK ) != (info->flags & ~ROCKET_USR_MASK )) { +mutex_unlock (&info->port.mutex);return -EPERM ; + } info->flags = ((info->flags & ~ROCKET_USR_MASK ) | (new_serial.flags &ROCKET_USR_MASK ));configure_r_port (tty, info,NULL );return 0 ;
@@ -1250,6 +1259,7 @@ static int set_config(struct tty_struct *tty, struct r_port *info, tty->alt_speed =230400 ;if ((info->flags &ROCKET_SPD_MASK ) ==ROCKET_SPD_WARP ) tty->alt_speed =460800 ; +mutex_unlock (&info->port.mutex);configure_r_port (tty, info,NULL );return 0 ;
@@ -1325,8 +1335,6 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file,if (cmd !=RCKP_GET_PORTS &&rocket_paranoia_check (info,"rp_ioctl" ))return -ENXIO ; -lock_kernel (); -switch (cmd) {case RCKP_GET_STRUCT :if (copy_to_user (argp, info,sizeof (struct r_port )))
@@ -1350,7 +1358,6 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file,default : ret = -ENOIOCTLCMD ; } -unlock_kernel ();return ret; }
@@ -1471,7 +1478,6 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout) jiffies);printk (KERN_INFO "cps=%d...\n" , info->cps);#endif -lock_kernel ();while (1 ) { txcnt =sGetTxCnt (cp);if (!txcnt) {
@@ -1499,7 +1505,6 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout)break ; }__set_current_state (TASK_RUNNING ); -unlock_kernel ();#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT printk (KERN_INFO "txcnt = %d (jiff=%lu)...done\n" , txcnt, jiffies);#endif
@@ -1512,6 +1517,7 @@ static void rp_hangup(struct tty_struct *tty) {CHANNEL_t *cp;struct r_port *info = tty->driver_data; +unsigned long flags;if (rocket_paranoia_check (info,"rp_hangup" ))return ;
@@ -1520,11 +1526,15 @@ static void rp_hangup(struct tty_struct *tty)printk (KERN_INFO "rp_hangup of ttyR%d...\n" , info->line);#endif rp_flush_buffer (tty); -if (info->port.flags &ASYNC_CLOSING ) +spin_lock_irqsave (&info->port.lock, flags); +if (info->port.flags &ASYNC_CLOSING ) { +spin_unlock_irqrestore (&info->port.lock, flags);return ; + }if (info->port.count)atomic_dec (&rp_num_ports_open);clear_bit ((info->aiop *8 ) + info->chan, (void *) &xmit_flags[info->board]); +spin_unlock_irqrestore (&info->port.lock, flags);tty_port_hangup (&info->port);
@@ -1535,7 +1545,7 @@ static void rp_hangup(struct tty_struct *tty)sDisCTSFlowCtl (cp);sDisTxSoftFlowCtl (cp);sClrTxXOFF (cp); - info->port.flags &= ~ASYNC_INITIALIZED ; +clear_bit (ASYNCB_INITIALIZED , &info->port.flags);wake_up_interruptible (&info->port.open_wait); }
Signature · 1 line
1.7.2
PATCH 18/67 synclink: kill the big kernel lock
In reply to Greg KHFrom: Alan Cox <[email protected]>
We don't need it while waiting and we can lock the ioctls using the port mutex. While at it eliminate use of the hangup mutex and switch to the port mutex.
--- drivers/char/synclink.c | 19 ++++++----- drivers/char/synclink_gt.c | 78 +++++++++++++++++++------------------------- drivers/char/synclinkmp.c | 32 +++++++----------- 3 files changed, 56 insertions(+), 73 deletions(-)
drivers/char/synclink.c +10 -9
@@ -81,7 +81,6 @@#include <linux/mm.h> #include <linux/seq_file.h> #include <linux/slab.h> -#include <linux/smp_lock.h> #include <linux/delay.h> #include <linux/netdevice.h> #include <linux/vmalloc.h>
@@ -2436,7 +2435,9 @@ static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount __user *if (!user_icount) {memset (&info->icount,0 ,sizeof (info->icount)); }else { +mutex_lock (&info->port.mutex);COPY_TO_USER (err, user_icount, &info->icount,sizeof (struct mgsl_icount )); +mutex_unlock (&info->port.mutex);if (err)return -EFAULT ; }
@@ -2461,7 +2462,9 @@ static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS __user *user_pprintk ("%s(%d):mgsl_get_params(%s)\n" , __FILE__,__LINE__, info->device_name); +mutex_lock (&info->port.mutex);COPY_TO_USER (err,user_params, &info->params,sizeof (MGSL_PARAMS )); +mutex_unlock (&info->port.mutex);if (err) {if ( debug_level >=DEBUG_LEVEL_INFO ) printk( "%s(%d):mgsl_get_params(%s) user buffer copy failed\n",
@@ -2501,11 +2504,13 @@ static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS __user *new_pareturn -EFAULT ; } +mutex_lock (&info->port.mutex);spin_lock_irqsave (&info->irq_spinlock,flags);memcpy (&info->params,&tmp_params,sizeof (MGSL_PARAMS ));spin_unlock_irqrestore (&info->irq_spinlock,flags);mgsl_change_params (info); +mutex_unlock (&info->port.mutex);return 0 ;
@@ -2935,7 +2940,6 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) {struct mgsl_struct * info = tty->driver_data; -int ret;if (debug_level >=DEBUG_LEVEL_INFO ) printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
@@ -2950,10 +2954,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,return -EIO ; } -lock_kernel (); - ret =mgsl_ioctl_common (info, cmd, arg); -unlock_kernel (); -return ret; +return mgsl_ioctl_common (info, cmd, arg); }static int mgsl_ioctl_common (struct mgsl_struct *info,unsigned int cmd,unsigned long arg)
@@ -3109,12 +3110,14 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp)if (tty_port_close_start (&info->port, tty, filp) ==0 ) goto cleanup; - + +mutex_lock (&info->port.mutex);if (info->port.flags &ASYNC_INITIALIZED )mgsl_wait_until_sent (tty, info->timeout);mgsl_flush_buffer (tty);tty_ldisc_flush (tty);shutdown (info); +mutex_unlock (&info->port.mutex);tty_port_close_end (&info->port, tty); info->port.tty =NULL ;
@@ -3162,7 +3165,6 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)* Note: use tight timings here to satisfy the NIST-PCTS. */ -lock_kernel ();if ( info->params.data_rate ) { char_time = info->timeout/(32 *5 );if (!char_time)
@@ -3192,7 +3194,6 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)break ; } } -unlock_kernel (); exit:if (debug_level >=DEBUG_LEVEL_INFO )
drivers/char/synclink_gt.c +34 -44
123 lines not on this page · raw message
drivers/char/synclinkmp.c +12 -20
@@ -52,7 +52,6 @@#include <linux/mm.h> #include <linux/seq_file.h> #include <linux/slab.h> -#include <linux/smp_lock.h> #include <linux/netdevice.h> #include <linux/vmalloc.h> #include <linux/init.h>
@@ -1062,9 +1061,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)if (sanity_check (info, tty->name,"wait_until_sent" ))return ; -lock_kernel (); - -if (!(info->port.flags &ASYNC_INITIALIZED )) +if (!test_bit (ASYNCB_INITIALIZED , &info->port.flags)) goto exit; orig_jiffies = jiffies;
@@ -1094,8 +1091,10 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)break ; } }else { -//TODO: determine if there is something similar to USC16C32 -// TXSTATUS_ALL_SENT status +/* +* TODO: determine if there is something similar to USC16C32 +* TXSTATUS_ALL_SENT status +*/ while ( info->tx_active && info->tx_enabled) {msleep_interruptible (jiffies_to_msecs (char_time));if (signal_pending (current))
@@ -1106,7 +1105,6 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) } exit: -unlock_kernel ();if (debug_level >=DEBUG_LEVEL_INFO )printk ("%s(%d):%s wait_until_sent() exit\n" , __FILE__,__LINE__, info->device_name );
@@ -1122,7 +1120,6 @@ static int write_room(struct tty_struct *tty)if (sanity_check (info, tty->name,"write_room" ))return 0 ; -lock_kernel ();if (info->params.mode ==MGSL_MODE_HDLC ) { ret = (info->tx_active) ?0 :HDLC_MAX_FRAME_SIZE ; }else {
@@ -1130,7 +1127,6 @@ static int write_room(struct tty_struct *tty)if (ret <0 ) ret =0 ; } -unlock_kernel ();if (debug_level >=DEBUG_LEVEL_INFO ) printk("%s(%d):%s write_room()=%d\n",
@@ -1251,7 +1247,7 @@ static void tx_release(struct tty_struct *tty)* * Return Value: 0 if success, otherwise error code */ -static int do_ioctl (struct tty_struct *tty,struct file *file, +static int ioctl (struct tty_struct *tty,struct file *file,unsigned int cmd,unsigned long arg) {SLMP_INFO *info = tty->driver_data;
@@ -1341,16 +1337,6 @@ static int do_ioctl(struct tty_struct *tty, struct file *file,return 0 ; } -static int ioctl (struct tty_struct *tty,struct file *file, -unsigned int cmd,unsigned long arg) -{ -int ret; -lock_kernel (); - ret =do_ioctl (tty, file, cmd, arg); -unlock_kernel (); -return ret; -} -/* * /proc fs routines.... */
@@ -2883,7 +2869,9 @@ static int get_stats(SLMP_INFO * info, struct mgsl_icount __user *user_icount)if (!user_icount) {memset (&info->icount,0 ,sizeof (info->icount)); }else { +mutex_lock (&info->port.mutex);COPY_TO_USER (err, user_icount, &info->icount,sizeof (struct mgsl_icount )); +mutex_unlock (&info->port.mutex);if (err)return -EFAULT ; }
@@ -2898,7 +2886,9 @@ static int get_params(SLMP_INFO * info, MGSL_PARAMS __user *user_params)printk ("%s(%d):%s get_params()\n" , __FILE__,__LINE__, info->device_name); +mutex_lock (&info->port.mutex);COPY_TO_USER (err,user_params, &info->params,sizeof (MGSL_PARAMS )); +mutex_unlock (&info->port.mutex);if (err) {if ( debug_level >=DEBUG_LEVEL_INFO ) printk( "%s(%d):%s get_params() user buffer copy failed\n",
@@ -2926,11 +2916,13 @@ static int set_params(SLMP_INFO * info, MGSL_PARAMS __user *new_params)return -EFAULT ; } +mutex_lock (&info->port.mutex);spin_lock_irqsave (&info->lock,flags);memcpy (&info->params,&tmp_params,sizeof (MGSL_PARAMS ));spin_unlock_irqrestore (&info->lock,flags);change_params (info); +mutex_unlock (&info->port.mutex);return 0 ; }
Signature · 1 line
1.7.2
PATCH 19/67 cyclades: Kill off BKL usage
In reply to Greg KHFrom: Alan Cox <[email protected]>
Use the port mutext for config setting, the rest is locked sufficiently anyway that the BKL makes no odds.
--- drivers/char/cyclades.c | 20 +++++++++----------- 1 files changed, 9 insertions(+), 11 deletions(-)
drivers/char/cyclades.c +9 -11
@@ -65,7 +65,6 @@#include <linux/tty.h> #include <linux/tty_flip.h> #include <linux/serial.h> -#include <linux/smp_lock.h> #include <linux/major.h> #include <linux/string.h> #include <linux/fcntl.h>
@@ -1655,7 +1654,6 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)return ;/* Just in case.... */ orig_jiffies = jiffies; -lock_kernel ();/* * Set the check interval to be 1/5 of the estimated time to * send a single character, and make it at least 1. The check
@@ -1702,7 +1700,6 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) }/* Run one more char cycle */ msleep_interruptible (jiffies_to_msecs (char_time *5 )); -unlock_kernel ();#ifdef CY_DEBUG_WAIT_UNTIL_SENT printk (KERN_DEBUG "Clean (jiff=%lu)...done\n" , jiffies);#endif
@@ -1959,7 +1956,6 @@ static int cy_chars_in_buffer(struct tty_struct *tty)int char_count;__u32 tx_put, tx_get, tx_bufsize; -lock_kernel (); tx_get =readl (&buf_ctrl->tx_get); tx_put =readl (&buf_ctrl->tx_put); tx_bufsize =readl (&buf_ctrl->tx_bufsize);
@@ -1971,7 +1967,6 @@ static int cy_chars_in_buffer(struct tty_struct *tty)printk (KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n" , info->line, info->xmit_cnt + char_count);#endif -unlock_kernel (); return info->xmit_cnt + char_count; }#endif /* Z_EXT_CHARS_IN_BUFFER */
@@ -2359,17 +2354,22 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty, struct serial_struct __user *new_info) {struct serial_struct new_serial; +int ret;if (copy_from_user (&new_serial, new_info,sizeof (new_serial)))return -EFAULT ; +mutex_lock (&info->port.mutex);if (!capable (CAP_SYS_ADMIN )) {if (new_serial.close_delay != info->port.close_delay || new_serial.baud_base != info->baud || (new_serial.flags &ASYNC_FLAGS & ~ASYNC_USR_MASK ) != (info->port.flags &ASYNC_FLAGS & ~ASYNC_USR_MASK )) + { +mutex_unlock (&info->port.mutex);return -EPERM ; + } info->port.flags = (info->port.flags & ~ASYNC_USR_MASK ) | (new_serial.flags &ASYNC_USR_MASK ); info->baud = new_serial.baud_base;
@@ -2392,10 +2392,12 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty, check_and_exit:if (info->port.flags &ASYNC_INITIALIZED ) {cy_set_line_char (info, tty); -return 0 ; + ret =0 ; }else { -return cy_startup (info, tty); + ret =cy_startup (info, tty); } +mutex_unlock (&info->port.mutex); +return ret; }/* set_serial_info */ /*
@@ -2438,7 +2440,6 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) card = info->card; -lock_kernel ();if (!cy_is_Z (card)) {unsigned long flags;int channel = info->line - card->first_line;
@@ -2478,7 +2479,6 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) ((lstatus &C_RS_CTS ) ?TIOCM_CTS :0 ); } end: -unlock_kernel ();return result; }/* cy_tiomget */
@@ -2696,7 +2696,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file,printk (KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n" , info->line, cmd, arg);#endif -lock_kernel ();switch (cmd) {case CYGETMON :
@@ -2817,7 +2816,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file,default : ret_val = -ENOIOCTLCMD ; } -unlock_kernel ();#ifdef CY_DEBUG_OTHER printk (KERN_DEBUG "cyc:cy_ioctl done\n" );
Signature · 1 line
1.7.2
PATCH 20/67 epca: Kill the big kernel lock
In reply to Greg KHFrom: Alan Cox <[email protected]>
The lock is no longer needed for wait until sent paths so this can go
--- drivers/char/epca.c | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-)
drivers/char/epca.c +1 -3
@@ -36,7 +36,7 @@#include <linux/ctype.h> #include <linux/tty.h> #include <linux/tty_flip.h> -#include <linux/smp_lock.h> +#include <linux/slab.h> #include <linux/ioport.h> #include <linux/interrupt.h> #include <linux/uaccess.h>
@@ -2105,7 +2105,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file,break ;case DIGI_SETAW :case DIGI_SETAF : -lock_kernel ();if (cmd ==DIGI_SETAW ) {/* Setup an event to indicate when the transmit buffer empties */
@@ -2118,7 +2117,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file,if (tty->ldisc->ops->flush_buffer) tty->ldisc->ops->flush_buffer (tty); } -unlock_kernel ();/* Fall Thru */ case DIGI_SETA :if (copy_from_user (&ch->digiext, argp,sizeof (digi_t)))
Signature · 1 line
1.7.2
PATCH 21/67 specialix: Kill the BKL
In reply to Greg KHFrom: Alan Cox <[email protected]>
Use the port mutex instead
--- drivers/char/specialix.c | 11 +++++------ 1 files changed, 5 insertions(+), 6 deletions(-)
drivers/char/specialix.c +5 -6
@@ -1863,8 +1863,7 @@ static int sx_set_serial_info(struct specialix_port *port,return -EFAULT ; } -lock_kernel (); - +mutex_lock (&port->port.mutex); change_speed = ((port->port.flags &ASYNC_SPD_MASK ) != (tmp.flags &ASYNC_SPD_MASK )); change_speed |= (tmp.custom_divisor != port->custom_divisor);
@@ -1875,7 +1874,7 @@ static int sx_set_serial_info(struct specialix_port *port, ((tmp.flags & ~ASYNC_USR_MASK) != (port->port.flags & ~ASYNC_USR_MASK))) {func_exit (); -unlock_kernel (); +mutex_unlock (&port->port.mutex);return -EPERM ; } port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
@@ -1892,7 +1891,7 @@ static int sx_set_serial_info(struct specialix_port *port,sx_change_speed (bp, port);func_exit (); -unlock_kernel (); +mutex_unlock (&port->port.mutex);return 0 ; }
@@ -1906,7 +1905,7 @@ static int sx_get_serial_info(struct specialix_port *port,func_enter ();memset (&tmp,0 ,sizeof (tmp)); -lock_kernel (); +mutex_lock (&port->port.mutex); tmp.type =PORT_CIRRUS ; tmp.line = port - sx_port; tmp.port = bp->base;
@@ -1917,7 +1916,7 @@ static int sx_get_serial_info(struct specialix_port *port, tmp.closing_wait = port->port.closing_wait *HZ /100 ; tmp.custom_divisor = port->custom_divisor; tmp.xmit_fifo_size = CD186x_NFIFO; -unlock_kernel (); +mutex_unlock (&port->port.mutex);if (copy_to_user (retinfo, &tmp,sizeof (tmp))) {func_exit ();return -EFAULT ;
Signature · 1 line
1.7.2
PATCH 22/67 tty: Fix the digi acceleport driver NULL checks
In reply to Greg KHFrom: Alan Cox <[email protected]>
This now refcounts but doesn't actually check the reference was obtained in all the places it should.
--- drivers/usb/serial/digi_acceleport.c | 14 +++++++++----- 1 files changed, 9 insertions(+), 5 deletions(-)
drivers/usb/serial/digi_acceleport.c +9 -5
@@ -609,8 +609,10 @@ static void digi_wakeup_write_lock(struct work_struct *work)static void digi_wakeup_write (struct usb_serial_port *port) {struct tty_struct *tty =tty_port_tty_get (&port->port); -tty_wakeup (tty); -tty_kref_put (tty); +if (tty) { +tty_wakeup (tty); +tty_kref_put (tty); + } }
@@ -1682,7 +1684,7 @@ static int digi_read_inb_callback(struct urb *urb) priv->dp_throttle_restart =1 ;/* receive data */ -if (opcode ==DIGI_CMD_RECEIVE_DATA ) { +if (tty && opcode ==DIGI_CMD_RECEIVE_DATA ) {/* get flag from port_status */ flag =0 ;
@@ -1763,10 +1765,12 @@ static int digi_read_oob_callback(struct urb *urb)return -1 ; tty =tty_port_tty_get (&port->port); + rts =0 ; - rts = tty->termios->c_cflag &CRTSCTS ; +if (tty) + rts = tty->termios->c_cflag &CRTSCTS ; -if (opcode ==DIGI_CMD_READ_INPUT_SIGNALS ) { +if (tty && opcode ==DIGI_CMD_READ_INPUT_SIGNALS ) {spin_lock (&priv->dp_port_lock);/* convert from digi flags to termiox flags */ if (val &DIGI_READ_INPUT_SIGNALS_CTS ) {
Signature · 1 line
1.7.2
PATCH 23/67 synclink: reworking locking a bit
In reply to Greg KHFrom: Alan Cox <[email protected]>
Use the port mutex and port lock to fix the various races. The locking still isn't totally consistent but its better than before. Wants switching to the port helpers.
--- drivers/char/synclink_gt.c | 12 +++++++++++- drivers/char/synclinkmp.c | 9 ++++++++- 2 files changed, 19 insertions(+), 2 deletions(-)
drivers/char/synclink_gt.c +11 -1
@@ -675,12 +675,14 @@ static int open(struct tty_struct *tty, struct file *filp) goto cleanup; } +mutex_lock (&info->port.mutex); info->port.tty->low_latency = (info->port.flags &ASYNC_LOW_LATENCY ) ?1 :0 ;spin_lock_irqsave (&info->netlock, flags);if (info->netcount) { retval = -EBUSY ;spin_unlock_irqrestore (&info->netlock, flags); +mutex_unlock (&info->port.mutex); goto cleanup; } info->port.count++;
@@ -692,7 +694,7 @@ static int open(struct tty_struct *tty, struct file *filp)if (retval <0 ) goto cleanup; } - +mutex_unlock (&info->port.mutex); retval =block_til_ready (tty, filp, info);if (retval) {DBGINFO (("%s block_til_ready rc=%d\n" , info->device_name, retval));
@@ -724,12 +726,14 @@ static void close(struct tty_struct *tty, struct file *filp)if (tty_port_close_start (&info->port, tty, filp) ==0 ) goto cleanup; +mutex_lock (&info->port.mutex);if (info->port.flags &ASYNC_INITIALIZED )wait_until_sent (tty, info->timeout);flush_buffer (tty);tty_ldisc_flush (tty);shutdown (info); +mutex_unlock (&info->port.mutex);tty_port_close_end (&info->port, tty); info->port.tty =NULL ;
@@ -740,17 +744,23 @@ cleanup:static void hangup (struct tty_struct *tty) {struct slgt_info *info = tty->driver_data; +unsigned long flags;if (sanity_check (info, tty->name,"hangup" ))return ;DBGINFO (("%s hangup\n" , info->device_name));flush_buffer (tty); + +mutex_lock (&info->port.mutex);shutdown (info); +spin_lock_irqsave (&info->port.lock, flags); info->port.count =0 ; info->port.flags &= ~ASYNC_NORMAL_ACTIVE ; info->port.tty =NULL ; +spin_unlock_irqrestore (&info->port.lock, flags); +mutex_unlock (&info->port.mutex);wake_up_interruptible (&info->port.open_wait); }
drivers/char/synclinkmp.c +8 -1
@@ -812,13 +812,15 @@ static void close(struct tty_struct *tty, struct file *filp)if (tty_port_close_start (&info->port, tty, filp) ==0 ) goto cleanup; - + +mutex_lock (&info->port.mutex);if (info->port.flags &ASYNC_INITIALIZED )wait_until_sent (tty, info->timeout);flush_buffer (tty);tty_ldisc_flush (tty);shutdown (info); +mutex_unlock (&info->port.mutex);tty_port_close_end (&info->port, tty); info->port.tty =NULL ;
@@ -834,6 +836,7 @@ cleanup:static void hangup (struct tty_struct *tty) {SLMP_INFO *info = tty->driver_data; +unsigned long flags;if (debug_level >=DEBUG_LEVEL_INFO ) printk("%s(%d):%s hangup()\n",
@@ -842,12 +845,16 @@ static void hangup(struct tty_struct *tty)if (sanity_check (info, tty->name,"hangup" ))return ; +mutex_lock (&info->port.mutex);flush_buffer (tty);shutdown (info); +spin_lock_irqsave (&info->port.lock, flags); info->port.count =0 ; info->port.flags &= ~ASYNC_NORMAL_ACTIVE ; info->port.tty =NULL ; +spin_unlock_irqrestore (&info->port.lock, flags); +mutex_unlock (&info->port.mutex);wake_up_interruptible (&info->port.open_wait); }
Signature · 1 line
1.7.2
PATCH 24/67 tty: serial - fix various misuses/mishandlings of port->tty
In reply to Greg KHFrom: Alan Cox <[email protected]>
Make it robust against hang up events. In most cases we can do this simply by passing the right things in the first place.
--- drivers/serial/serial_core.c | 109 +++++++++++++++++++++++------------------- 1 files changed, 60 insertions(+), 49 deletions(-)
drivers/serial/serial_core.c +60 -49
@@ -58,7 +58,7 @@ static struct lock_class_key port_lock_key;#define uart_console (port) (0)#endif -static void uart_change_speed (struct uart_state *state, +static void uart_change_speed (struct tty_struct *tty,struct uart_state *state,struct ktermios *old_termios);static void uart_wait_until_sent (struct tty_struct *tty,int timeout);static void uart_change_pm (struct uart_state *state,int pm_state);
@@ -137,7 +137,7 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)* Startup the port. This will be called once per open. All calls * will be serialised by the per-port mutex. */ -static int uart_startup (struct uart_state *state,int init_hw) +static int uart_startup (struct tty_struct *tty,struct uart_state *state,int init_hw) {struct uart_port *uport = state->uart_port;struct tty_port *port = &state->port;
@@ -152,7 +152,7 @@ static int uart_startup(struct uart_state *state, int init_hw)* once we have successfully opened the port. Also set * up the tty->alt_speed kludge */ -set_bit (TTY_IO_ERROR , &port->tty->flags); +set_bit (TTY_IO_ERROR , &tty->flags);if (uport->type ==PORT_UNKNOWN )return 0 ;
@@ -177,26 +177,26 @@ static int uart_startup(struct uart_state *state, int init_hw)/* * Initialise the hardware port settings. */ -uart_change_speed (state,NULL ); +uart_change_speed (tty, state,NULL );/* * Setup the RTS and DTR signals once the * port is open and ready to respond. */ -if (port->tty->termios->c_cflag &CBAUD ) +if (tty->termios->c_cflag &CBAUD )uart_set_mctrl (uport,TIOCM_RTS |TIOCM_DTR ); }if (port->flags &ASYNC_CTS_FLOW ) {spin_lock_irq (&uport->lock);if (!(uport->ops->get_mctrl (uport) &TIOCM_CTS )) - port->tty->hw_stopped =1 ; + tty->hw_stopped =1 ;spin_unlock_irq (&uport->lock); }set_bit (ASYNCB_INITIALIZED , &port->flags); -clear_bit (TTY_IO_ERROR , &port->tty->flags); +clear_bit (TTY_IO_ERROR , &tty->flags); }if (retval &&capable (CAP_SYS_ADMIN ))
@@ -210,11 +210,10 @@ static int uart_startup(struct uart_state *state, int init_hw)* DTR is dropped if the hangup on close termio flag is on. Calls to * uart_shutdown are serialised by the per-port semaphore. */ -static void uart_shutdown (struct uart_state *state) +static void uart_shutdown (struct tty_struct *tty,struct uart_state *state) {struct uart_port *uport = state->uart_port;struct tty_port *port = &state->port; -struct tty_struct *tty = port->tty;/* * Set the TTY IO error marker
@@ -430,11 +429,10 @@ uart_get_divisor(struct uart_port *port, unsigned int baud)EXPORT_SYMBOL (uart_get_divisor);/* FIXME: Consistent locking policy */ -static void -uart_change_speed (struct uart_state *state,struct ktermios *old_termios) +static void uart_change_speed (struct tty_struct *tty,struct uart_state *state, +struct ktermios *old_termios) {struct tty_port *port = &state->port; -struct tty_struct *tty = port->tty;struct uart_port *uport = state->uart_port;struct ktermios *termios;
@@ -463,8 +461,8 @@ uart_change_speed(struct uart_state *state, struct ktermios *old_termios) uport->ops->set_termios (uport, termios, old_termios); } -static inline int -__uart_put_char (struct uart_port *port,struct circ_buf *circ,unsigned char c) +static inline int __uart_put_char (struct uart_port *port, +struct circ_buf *circ,unsigned char c) {unsigned long flags;int ret =0 ;
@@ -494,8 +492,8 @@ static void uart_flush_chars(struct tty_struct *tty)uart_start (tty); } -static int -uart_write (struct tty_struct *tty,const unsigned char *buf,int count) +static int uart_write (struct tty_struct *tty, +const unsigned char *buf,int count) {struct uart_state *state = tty->driver_data;struct uart_port *port;
@@ -675,7 +673,7 @@ static int uart_get_info(struct uart_state *state,return 0 ; } -static int uart_set_info (struct uart_state *state, +static int uart_set_info (struct tty_struct *tty,struct uart_state *state,struct serial_struct __user *newinfo) {struct serial_struct new_serial;
@@ -770,7 +768,7 @@ static int uart_set_info(struct uart_state *state,* We need to shutdown the serial port at the old * port/type/irq combination. */ -uart_shutdown (state); +uart_shutdown (tty, state); }if (change_port) {
@@ -869,25 +867,27 @@ static int uart_set_info(struct uart_state *state,"is deprecated.\n" , current->comm, tty_name(port->tty, buf)); } -uart_change_speed (state,NULL ); +uart_change_speed (tty, state,NULL ); } }else - retval =uart_startup (state,1 ); + retval =uart_startup (tty, state,1 ); exit:mutex_unlock (&port->mutex);return retval; } - -/* -* uart_get_lsr_info - get line status register info. -* Note: uart_ioctl protects us against hangups. +/** +* uart_get_lsr_info - get line status register info +* @tty: tty associated with the UART +* @state: UART being queried +* @value: returned modem value +* +* Note: uart_ioctl protects us against hangups. */ -static int uart_get_lsr_info (struct uart_state *state, -unsigned int __user *value) +static int uart_get_lsr_info (struct tty_struct *tty, +struct uart_state *state,unsigned int __user *value) {struct uart_port *uport = state->uart_port; -struct tty_port *port = &state->port;unsigned int result; result = uport->ops->tx_empty (uport);
@@ -900,7 +900,7 @@ static int uart_get_lsr_info(struct uart_state *state,*/ if (uport->x_char || ((uart_circ_chars_pending (&state->xmit) >0 ) && - !port->tty->stopped && !port->tty->hw_stopped)) + !tty->stopped && !tty->hw_stopped)) result &= ~TIOCSER_TEMT ;return put_user (result, value);
@@ -961,7 +961,7 @@ static int uart_break_ctl(struct tty_struct *tty, int break_state)return 0 ; } -static int uart_do_autoconfig (struct uart_state *state) +static int uart_do_autoconfig (struct tty_struct *tty,struct uart_state *state) {struct uart_port *uport = state->uart_port;struct tty_port *port = &state->port;
@@ -980,7 +980,7 @@ static int uart_do_autoconfig(struct uart_state *state) ret = -EBUSY ;if (tty_port_users (port) ==1 ) { -uart_shutdown (state); +uart_shutdown (tty, state);/* * If we already have a port type configured,
@@ -999,7 +999,7 @@ static int uart_do_autoconfig(struct uart_state *state)*/ uport->ops->config_port (uport, flags); - ret =uart_startup (state,1 ); + ret =uart_startup (tty, state,1 ); }mutex_unlock (&port->mutex);return ret;
@@ -1122,11 +1122,11 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,break ;case TIOCSSERIAL : - ret =uart_set_info (state, uarg); + ret =uart_set_info (tty, state, uarg);break ;case TIOCSERCONFIG : - ret =uart_do_autoconfig (state); + ret =uart_do_autoconfig (tty, state);break ;case TIOCSERGWILD :/* obsolete */
@@ -1172,7 +1172,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,*/ switch (cmd) {case TIOCSERGETLSR :/* Get line status register */ - ret =uart_get_lsr_info (state, uarg); + ret =uart_get_lsr_info (tty, state, uarg);break ;default : {
@@ -1219,7 +1219,7 @@ static void uart_set_termios(struct tty_struct *tty,return ; } -uart_change_speed (state, old_termios); +uart_change_speed (tty, state, old_termios);/* Handle transition to B0 status */ if ((old_termios->c_cflag &CBAUD ) && !(cflag &CBAUD ))
@@ -1335,7 +1335,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)uart_wait_until_sent (tty, uport->timeout); } -uart_shutdown (state); +uart_shutdown (tty, state);uart_flush_buffer (tty);tty_ldisc_flush (tty);
@@ -1436,7 +1436,7 @@ static void uart_hangup(struct tty_struct *tty)mutex_lock (&port->mutex);if (port->flags &ASYNC_NORMAL_ACTIVE ) {uart_flush_buffer (tty); -uart_shutdown (state); +uart_shutdown (tty, state); port->count =0 ;clear_bit (ASYNCB_NORMAL_ACTIVE , &port->flags);tty_port_tty_set (port,NULL );
@@ -1446,15 +1446,19 @@ static void uart_hangup(struct tty_struct *tty)mutex_unlock (&port->mutex); } -/* -* Copy across the serial console cflag setting into the termios settings -* for the initial open of the port. This allows continuity between the -* kernel settings, and the settings init adopts when it opens the port -* for the first time. +/** +* uart_update_termios - update the terminal hw settings +* @tty: tty associated with UART +* @state: UART to update +* +* Copy across the serial console cflag setting into the termios settings +* for the initial open of the port. This allows continuity between the +* kernel settings, and the settings init adopts when it opens the port +* for the first time. */ -static void uart_update_termios (struct uart_state *state) +static void uart_update_termios (struct tty_struct *tty, +struct uart_state *state) { -struct tty_struct *tty = state->port.tty;struct uart_port *port = state->uart_port;if (uart_console (port) && port->cons->cflag) {
@@ -1471,7 +1475,7 @@ static void uart_update_termios(struct uart_state *state)/* * Make termios settings take effect. */ -uart_change_speed (state,NULL ); +uart_change_speed (tty, state,NULL );/* * And finally enable the RTS and DTR signals.
@@ -1668,7 +1672,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp)/* * Start up the serial port. */ - retval =uart_startup (state,0 ); + retval =uart_startup (tty, state,0 );/* * If we succeeded, wait until the port is ready.
@@ -1683,7 +1687,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp)if (retval ==0 && !(port->flags &ASYNC_NORMAL_ACTIVE )) {set_bit (ASYNCB_NORMAL_ACTIVE , &port->flags); -uart_update_termios (state); +uart_update_termios (tty, state); } fail:
@@ -2010,9 +2014,13 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)struct tty_port *port = &state->port;struct device *tty_dev;struct uart_match match = {uport, drv}; +struct tty_struct *tty;mutex_lock (&port->mutex); +/* Must be inside the mutex lock until we convert to tty_port */ + tty = port->tty; + tty_dev =device_find_child (uport->dev, &match, serial_match_port);if (device_may_wakeup (tty_dev)) {enable_irq_wake (uport->irq);
@@ -2105,9 +2113,12 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) ops->set_mctrl (uport,0 );spin_unlock_irq (&uport->lock);if (console_suspend_enabled || !uart_console (uport)) { +/* Protected by port mutex for now */ +struct tty_struct *tty = port->tty; ret = ops->startup (uport);if (ret ==0 ) { -uart_change_speed (state,NULL ); +if (tty) +uart_change_speed (tty, state,NULL );spin_lock_irq (&uport->lock); ops->set_mctrl (uport, uport->mctrl); ops->start_tx (uport);
@@ -2119,7 +2130,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)* Clear the "initialized" flag so we won't try * to call the low level drivers shutdown method. */ -uart_shutdown (state); +uart_shutdown (tty, state); } }
Signature · 1 line
1.7.2
PATCH 25/67 tty: serial - fix tty back references in termios
In reply to Greg KHFrom: Alan Cox <[email protected]>
One or two drivers go poking back into the tty from the termios setting routine in unsafe ways. We don't need to pass the tty down because the [ab]users are just using it to get at things they can get at anyway.
This leaves low_latency setting to sort out along with set_ldisc use.
--- drivers/serial/21285.c | 10 +++------- drivers/serial/imx.c | 10 ++++------ drivers/serial/ioc3_serial.c | 9 +++++---- drivers/serial/ioc4_serial.c | 9 +++++---- drivers/serial/max3100.c | 7 ++----- 5 files changed, 19 insertions(+), 26 deletions(-)
drivers/serial/21285.c +3 -7
@@ -216,7 +216,7 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) {unsigned long flags; -unsigned int baud, quot, h_lcr; +unsigned int baud, quot, h_lcr, b;/* * We don't support modem control lines.
@@ -234,12 +234,8 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios,*/ baud =uart_get_baud_rate (port, termios, old,0 , port->uartclk/16 ); quot =uart_get_divisor (port, baud); - -if (port->state && port->state->port.tty) { -struct tty_struct *tty = port->state->port.tty; -unsigned int b = port->uartclk / (16 * quot); -tty_encode_baud_rate (tty, b, b); - } + b = port->uartclk / (16 * quot); +tty_termios_encode_baud_rate (termios, b, b);switch (termios->c_cflag &CSIZE ) {case CS5 :
drivers/serial/imx.c +4 -6
@@ -909,13 +909,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,rational_best_approximation (16 * div * baud, sport->port.uartclk,1 <<16 ,1 <<16 , &num, &denom); -if (port->state && port->state->port.tty) { - tdiv64 = sport->port.uartclk; - tdiv64 *= num; -do_div (tdiv64, denom *16 * div); -tty_encode_baud_rate (sport->port.state->port.tty, + tdiv64 = sport->port.uartclk; + tdiv64 *= num; +do_div (tdiv64, denom *16 * div); +tty_termios_encode_baud_rate (termios, (speed_t )tdiv64, (speed_t )tdiv64); - } num -=1 ; denom -=1 ;
drivers/serial/ioc3_serial.c +5 -4
@@ -954,12 +954,13 @@ ioc3_change_speed(struct uart_port *the_port, struct ktermios *new_termios, struct ktermios *old_termios) { struct ioc3_port *port = get_ioc3_port(the_port); -unsigned int cflag; +unsigned int cflag, iflag;int baud;int new_parity =0 , new_parity_enable =0 , new_stop =0 , new_data =8 ;struct uart_state *state = the_port->state; cflag = new_termios->c_cflag; + iflag = new_termios->c_iflag;switch (cflag &CSIZE ) {case CS5 :
@@ -1000,12 +1001,12 @@ ioc3_change_speed(struct uart_port *the_port, state->port.tty->low_latency =1 ; -if (I_IGNPAR (state->port.tty)) +if (iflag &IGNPAR ) the_port->ignore_status_mask &= ~(N_PARITY_ERROR |N_FRAMING_ERROR ); -if (I_IGNBRK (state->port.tty)) { +if (iflag &IGNBRK ) { the_port->ignore_status_mask &= ~N_BREAK ; -if (I_IGNPAR (state->port.tty)) +if (iflag &IGNPAR ) the_port->ignore_status_mask &= ~N_OVERRUN_ERROR ; }if (!(cflag &CREAD )) {
drivers/serial/ioc4_serial.c +5 -4
@@ -1685,11 +1685,12 @@ ioc4_change_speed(struct uart_port *the_port, {struct ioc4_port *port =get_ioc4_port (the_port,0 );int baud, bits; -unsigned cflag; +unsigned cflag, iflag;int new_parity =0 , new_parity_enable =0 , new_stop =0 , new_data =8 ;struct uart_state *state = the_port->state; cflag = new_termios->c_cflag; + iflag = new_termios->c_iflag;switch (cflag &CSIZE ) {case CS5 :
@@ -1741,12 +1742,12 @@ ioc4_change_speed(struct uart_port *the_port, state->port.tty->low_latency =1 ; -if (I_IGNPAR (state->port.tty)) +if (iflag &IGNPAR ) the_port->ignore_status_mask &= ~(N_PARITY_ERROR |N_FRAMING_ERROR ); -if (I_IGNBRK (state->port.tty)) { +if (iflag &IGNBRK ) { the_port->ignore_status_mask &= ~N_BREAK ; -if (I_IGNPAR (state->port.tty)) +if (iflag &IGNPAR ) the_port->ignore_status_mask &= ~N_OVERRUN_ERROR ; }if (!(cflag &CREAD )) {
drivers/serial/max3100.c +2 -5
@@ -430,17 +430,14 @@ max3100_set_termios(struct uart_port *port, struct ktermios *termios,int baud =0 ;unsigned cflag;u32 param_new, param_mask, parity =0 ; -struct tty_struct *tty = s->port.state->port.tty;dev_dbg (&s->spi->dev,"%s\n" , __func__); -if (!tty) -return ; cflag = termios->c_cflag; param_new =0 ; param_mask =0 ; - baud =tty_get_baud_rate (tty); + baud =tty_termios_baud_rate (termios); param_new = s->conf &MAX3100_BAUD ;switch (baud) {case 300 :
@@ -485,7 +482,7 @@ max3100_set_termios(struct uart_port *port, struct ktermios *termios,default : baud = s->baud; } -tty_encode_baud_rate (tty, baud, baud); +tty_termios_encode_baud_rate (termios, baud, baud); s->baud = baud; param_mask |=MAX3100_BAUD ;
Signature · 1 line
1.7.2
PATCH 26/67 tty: serial - fix tty referencing in set_ldisc
In reply to Greg KHFrom: Alan Cox <[email protected]>
Pass down the ldisc number so that the drivers don't have to peek into the tty object themselves. This lets us get rid of another case of back referencing port to tty which we don't want (because of races versus hangup/close).
--- drivers/serial/bfin_5xx.c | 7 ++----- drivers/serial/serial_core.c | 2 +- include/linux/serial_core.h | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-)
drivers/serial/bfin_5xx.c +2 -5
@@ -957,15 +957,12 @@ bfin_serial_verify_port(struct uart_port *port, struct serial_struct *ser)* Enable the IrDA function if tty->ldisc.num is N_IRDA. * In other cases, disable IrDA function. */ -static void bfin_serial_set_ldisc (struct uart_port *port) +static void bfin_serial_set_ldisc (struct uart_port *port,int ld) {int line = port->line;unsigned short val; -if (line >= port->state->port.tty->driver->num) -return ; - -switch (port->state->port.tty->termios->c_line) { +switch (ld) {case N_IRDA : val =UART_GET_GCTL (&bfin_serial_ports[line]); val |= (IREN |RPOLC );
drivers/serial/serial_core.c +1 -1
@@ -1194,7 +1194,7 @@ static void uart_set_ldisc(struct tty_struct *tty)struct uart_port *uport = state->uart_port;if (uport->ops->set_ldisc) - uport->ops->set_ldisc (uport); + uport->ops->set_ldisc (uport, tty->termios->c_line); } static void uart_set_termios(struct tty_struct *tty,
include/linux/serial_core.h +1 -1
@@ -220,7 +220,7 @@ struct uart_ops {void (*flush_buffer)(struct uart_port *);void (*set_termios)(struct uart_port *,struct ktermios *new,struct ktermios *old); -void (*set_ldisc)(struct uart_port *); +void (*set_ldisc)(struct uart_port *,int new);void (*pm)(struct uart_port *,unsigned int state,unsigned int oldstate);int (*set_wake)(struct uart_port *,unsigned int state);
Signature · 1 line
1.7.2
PATCH 27/67 vc: Locking clean up
In reply to Greg KHFrom: Alan Cox <[email protected]>
The virtual console layer uses the BKL for various things that don't really need it. Clean them out.
--- drivers/char/selection.c | 4 ++++ drivers/char/vt.c | 7 ++++--- 2 files changed, 8 insertions(+), 3 deletions(-)
drivers/char/selection.c +4 -0
@@ -26,6 +26,7 @@#include <linux/selection.h> #include <linux/tiocl.h> #include <linux/console.h> +#include <linux/smp_lock.h> /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */ #define isspace (c) ((c) == ' ')
@@ -312,6 +313,8 @@ int paste_selection(struct tty_struct *tty)struct tty_ldisc *ld;DECLARE_WAITQUEUE (wait, current); +lock_kernel (); +acquire_console_sem ();poke_blanked_console ();release_console_sem ();
@@ -335,5 +338,6 @@ int paste_selection(struct tty_struct *tty)__set_current_state (TASK_RUNNING );tty_ldisc_deref (ld); +unlock_kernel ();return 0 ; }
drivers/char/vt.c +4 -3
@@ -281,8 +281,12 @@ static inline unsigned short *screenpos(struct vc_data *vc, int offset, int viewreturn p; } +/* Called from the keyboard irq path.. */ static inline void scrolldelta (int lines) { +/* FIXME */ +/* scrolldelta needs some kind of consistency lock, but the BKL was +and still is not protecting versus the scheduled back end */ scrollback_delta += lines;schedule_console_callback (); }
@@ -2609,8 +2613,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)return -EFAULT ; ret =0 ; -lock_kernel (); -switch (type) {case TIOCL_SETSEL :
@@ -2685,7 +2687,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) ret = -EINVAL ;break ; } -unlock_kernel ();return ret; }
Signature · 1 line
1.7.2
PATCH 28/67 tty: Make vt's have a tty_port
In reply to Greg KHFrom: Alan Cox <[email protected]>
The vt layer isn't safely handling reference counts to tty object on the input side. Add a tty port structure to the vt layer in order to implement this using the standard helpers.
--- drivers/char/vt.c | 2 ++ include/linux/console_struct.h | 2 ++ 2 files changed, 4 insertions(+), 0 deletions(-)
drivers/char/vt.c +2 -0
@@ -777,6 +777,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */if (!vc)return -ENOMEM ; vc_cons[currcons].d = vc; +tty_port_init (&vc->port);INIT_WORK (&vc_cons[currcons].SAK_work, vc_SAK);visual_init (vc, currcons,1 );if (!*vc->vc_uni_pagedir_loc)
@@ -2914,6 +2915,7 @@ static int __init con_init(void)for (currcons =0 ; currcons <MIN_NR_CONSOLES ; currcons++) { vc_cons[currcons].d = vc =kzalloc (sizeof (struct vc_data ),GFP_NOWAIT );INIT_WORK (&vc_cons[currcons].SAK_work, vc_SAK); +tty_port_init (&vc->port);visual_init (vc, currcons,1 ); vc->vc_screenbuf =kzalloc (vc->vc_screenbuf_size,GFP_NOWAIT ); vc_init(vc, vc->vc_rows, vc->vc_cols,
include/linux/console_struct.h +2 -0
@@ -21,6 +21,8 @@ struct vt_struct;#define NPAR 16struct vc_data { +struct tty_port port;/* Upper level data */ +unsigned short vc_num;/* Console number */ unsigned int vc_cols;/* [#] Console size */ unsigned int vc_rows;
Signature · 1 line
1.7.2
PATCH 29/67 tty: Move the vt_tty field from the vc_data into the standard tty_port
In reply to Greg KHFrom: Alan Cox <[email protected]>
This takes all the tty references through the expected interface points so we can refcount them.
--- drivers/char/keyboard.c | 10 +++++----- drivers/char/vt.c | 10 +++++----- drivers/char/vt_ioctl.c | 2 +- include/linux/console_struct.h | 1 - 4 files changed, 11 insertions(+), 12 deletions(-)
drivers/char/keyboard.c +5 -5
@@ -299,7 +299,7 @@ int kbd_rate(struct kbd_repeat *rep)*/ static void put_queue (struct vc_data *vc,int ch) { -struct tty_struct *tty = vc->vc_tty; +struct tty_struct *tty = vc->port.tty;if (tty) {tty_insert_flip_char (tty, ch,0 );
@@ -309,7 +309,7 @@ static void put_queue(struct vc_data *vc, int ch)static void puts_queue (struct vc_data *vc,char *cp) { -struct tty_struct *tty = vc->vc_tty; +struct tty_struct *tty = vc->port.tty;if (!tty)return ;
@@ -485,7 +485,7 @@ static void fn_show_ptregs(struct vc_data *vc)static void fn_hold (struct vc_data *vc) { -struct tty_struct *tty = vc->vc_tty; +struct tty_struct *tty = vc->port.tty;if (rep || !tty)return ;
@@ -563,7 +563,7 @@ static void fn_inc_console(struct vc_data *vc)static void fn_send_intr (struct vc_data *vc) { -struct tty_struct *tty = vc->vc_tty; +struct tty_struct *tty = vc->port.tty;if (!tty)return ;
@@ -1162,7 +1162,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down };int rc; - tty = vc->vc_tty; + tty = vc->port.tty;if (tty && (!tty->driver_data)) {/* No driver data? Strange. Okay we fix it then. */
drivers/char/vt.c +5 -5
@@ -966,12 +966,12 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,* Resize a virtual console as seen from the console end of things. We * use the common vc_do_resize methods to update the structures. The * caller must hold the console sem to protect console internals and -* vc->vc_tty +* vc->port.tty */ int vc_resize (struct vc_data *vc,unsigned int cols,unsigned int rows) { -return vc_do_resize (vc->vc_tty, vc, cols, rows); +return vc_do_resize (vc->port.tty, vc, cols, rows); }/**
@@ -2800,12 +2800,12 @@ static int con_open(struct tty_struct *tty, struct file *filp)struct vc_data *vc = vc_cons[currcons].d;/* Still being freed */ -if (vc->vc_tty) { +if (vc->port.tty) {release_console_sem ();return -ERESTARTSYS ; } tty->driver_data = vc; - vc->vc_tty = tty; + vc->port.tty = tty;if (!tty->winsize.ws_row && !tty->winsize.ws_col) { tty->winsize.ws_row = vc_cons[currcons].d->vc_rows;
@@ -2833,7 +2833,7 @@ static void con_shutdown(struct tty_struct *tty)struct vc_data *vc = tty->driver_data;BUG_ON (vc ==NULL );acquire_console_sem (); - vc->vc_tty =NULL ; + vc->port.tty =NULL ;release_console_sem ();tty_shutdown (tty); }
drivers/char/vt_ioctl.c +1 -1
@@ -1369,7 +1369,7 @@ void vc_SAK(struct work_struct *work)acquire_console_sem (); vc = vc_con->d;if (vc) { - tty = vc->vc_tty; + tty = vc->port.tty;/* * SAK should also work in all raw modes and reset * them properly.
include/linux/console_struct.h +0 -1
@@ -58,7 +58,6 @@ struct vc_data {/* VT terminal data */ unsigned int vc_state;/* Escape sequence parser state */ unsigned int vc_npar,vc_par[NPAR ];/* Parameters of current escape sequence */ -struct tty_struct *vc_tty;/* TTY we are attached to */ /* data for manual vt switching */ struct vt_mode vt_mode;struct pid *vt_pid;
Signature · 1 line
1.7.2
PATCH 30/67 serial: Change the wait for carrier locking
In reply to Greg KHFrom: Alan Cox <[email protected]>
We want to push the lock/unlock into the helper functions so that we can prepare to move to using the tty_port helper. The expansion initially comes out a bit ugly but its worth the temporary expansion IMHO just so we can produce a nice testable series of changes.
--- drivers/serial/serial_core.c | 44 +++++++++++++++++++++++++++++++++-------- 1 files changed, 35 insertions(+), 9 deletions(-)
drivers/serial/serial_core.c +35 -9
@@ -1272,6 +1272,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)struct uart_state *state = tty->driver_data;struct tty_port *port;struct uart_port *uport; +unsigned long flags;BUG_ON (!kernel_locked ());
@@ -1284,9 +1285,12 @@ static void uart_close(struct tty_struct *tty, struct file *filp)pr_debug ("uart_close(%d) called\n" , uport->line);mutex_lock (&port->mutex); +spin_lock_irqsave (&port->lock, flags); -if (tty_hung_up_p (filp)) +if (tty_hung_up_p (filp)) { +spin_unlock_irqrestore (&port->lock, flags); goto done; + }if ((tty->count ==1 ) && (port->count !=1 )) {/*
@@ -1305,8 +1309,10 @@ static void uart_close(struct tty_struct *tty, struct file *filp) tty->name, port->count); port->count =0 ; } -if (port->count) +if (port->count) { +spin_unlock_irqrestore (&port->lock, flags); goto done; + }/* * Now we wait for the transmit buffer to clear; and we notify
@@ -1314,6 +1320,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)* setting tty->closing. */ tty->closing =1 ; +spin_unlock_irqrestore (&port->lock, flags);if (port->closing_wait !=ASYNC_CLOSING_WAIT_NONE )tty_wait_until_sent (tty,msecs_to_jiffies (port->closing_wait));
@@ -1340,20 +1347,26 @@ static void uart_close(struct tty_struct *tty, struct file *filp)tty_ldisc_flush (tty); - tty->closing =0 ;tty_port_tty_set (port,NULL ); +spin_lock_irqsave (&port->lock, flags); + tty->closing =0 ;if (port->blocked_open) { +spin_unlock_irqrestore (&port->lock, flags);if (port->close_delay)msleep_interruptible (port->close_delay); +spin_lock_irqsave (&port->lock, flags); }else if (!uart_console (uport)) { +spin_unlock_irqrestore (&port->lock, flags);uart_change_pm (state,3 ); +spin_lock_irqsave (&port->lock, flags); }/* * Wake up anyone trying to open this port. */ clear_bit (ASYNCB_NORMAL_ACTIVE , &port->flags); +spin_unlock_irqrestore (&port->lock, flags);wake_up_interruptible (&port->open_wait); done:
@@ -1429,6 +1442,7 @@ static void uart_hangup(struct tty_struct *tty) {struct uart_state *state = tty->driver_data;struct tty_port *port = &state->port; +unsigned long flags;BUG_ON (!kernel_locked ());pr_debug ("uart_hangup(%d)\n" , state->uart_port->line);
@@ -1437,8 +1451,10 @@ static void uart_hangup(struct tty_struct *tty)if (port->flags &ASYNC_NORMAL_ACTIVE ) {uart_flush_buffer (tty);uart_shutdown (tty, state); +spin_lock_irqsave (&port->lock, flags); port->count =0 ;clear_bit (ASYNCB_NORMAL_ACTIVE , &port->flags); +spin_unlock_irqrestore (&port->lock, flags);tty_port_tty_set (port,NULL );wake_up_interruptible (&port->open_wait);wake_up_interruptible (&port->delta_msr_wait);
@@ -1496,9 +1512,13 @@ uart_block_til_ready(struct file *filp, struct uart_state *state)struct uart_port *uport = state->uart_port;struct tty_port *port = &state->port;unsigned int mctrl; +unsigned long flags; +spin_lock_irqsave (&port->lock, flags); +if (!tty_hung_up_p (filp)) + port->count--; port->blocked_open++; - port->count--; +spin_unlock_irqrestore (&port->lock, flags);add_wait_queue (&port->open_wait, &wait);while (1 ) {
@@ -1535,23 +1555,26 @@ uart_block_til_ready(struct file *filp, struct uart_state *state)* not set RTS here - we want to make sure we catch * the data from the modem. */ -if (port->tty->termios->c_cflag &CBAUD ) +if (port->tty->termios->c_cflag &CBAUD ) { +mutex_lock (&port->mutex);uart_set_mctrl (uport,TIOCM_DTR ); +mutex_unlock (&port->mutex); + }/* * and wait for the carrier to indicate that the * modem is ready for us. */ +mutex_lock (&port->mutex);spin_lock_irq (&uport->lock); uport->ops->enable_ms (uport); mctrl = uport->ops->get_mctrl (uport);spin_unlock_irq (&uport->lock); +mutex_unlock (&port->mutex);if (mctrl &TIOCM_CAR )break ; -mutex_unlock (&port->mutex);schedule (); -mutex_lock (&port->mutex);if (signal_pending (current))break ;
@@ -1559,8 +1582,11 @@ uart_block_til_ready(struct file *filp, struct uart_state *state)set_current_state (TASK_RUNNING );remove_wait_queue (&port->open_wait, &wait); - port->count++; +spin_lock_irqsave (&port->lock, flags); +if (!tty_hung_up_p (filp)) + port->count++; port->blocked_open--; +spin_unlock_irqrestore (&port->lock, flags);if (signal_pending (current))return -ERESTARTSYS ;
@@ -1677,9 +1703,9 @@ static int uart_open(struct tty_struct *tty, struct file *filp)/* * If we succeeded, wait until the port is ready. */ +mutex_unlock (&port->mutex);if (retval ==0 ) retval =uart_block_til_ready (filp, state); -mutex_unlock (&port->mutex);/* * If this is the first open to succeed, adjust things to suit.
Signature · 1 line
1.7.2
PATCH 31/67 serial: add port helpers
In reply to Greg KHFrom: Alan Cox <[email protected]>
We can make this the same as the ones that will be needed by the tty_port helper logic that we want to move to but still call them from the existing code base.
--- drivers/serial/serial_core.c | 51 ++++++++++++++++++++++++++++++----------- 1 files changed, 37 insertions(+), 14 deletions(-)
drivers/serial/serial_core.c +37 -14
@@ -1501,6 +1501,34 @@ static void uart_update_termios(struct tty_struct *tty, } } +static int uart_carrier_raised (struct tty_port *port) +{ + struct uart_state *state = container_of(port, struct uart_state, port); +struct uart_port *uport = state->uart_port; +int mctrl; +mutex_lock (&port->mutex); +spin_lock_irq (&uport->lock); + uport->ops->enable_ms (uport); + mctrl = uport->ops->get_mctrl (uport); +spin_unlock_irq (&uport->lock); +mutex_unlock (&port->mutex); +if (mctrl &TIOCM_CAR ) +return 1 ; +return 0 ; +} + +static void uart_dtr_rts (struct tty_port *port,int onoff) +{ + struct uart_state *state = container_of(port, struct uart_state, port); +struct uart_port *uport = state->uart_port; +mutex_lock (&port->mutex); +if (onoff) +uart_set_mctrl (uport,TIOCM_DTR |TIOCM_RTS ); +else +uart_clear_mctrl (uport,TIOCM_DTR |TIOCM_RTS ); +mutex_unlock (&port->mutex); +} +/* * Block the open until the port is ready. We must be called with * the per-port semaphore held.
@@ -1509,9 +1537,7 @@ static int uart_block_til_ready(struct file *filp, struct uart_state *state) {DECLARE_WAITQUEUE (wait, current); -struct uart_port *uport = state->uart_port;struct tty_port *port = &state->port; -unsigned int mctrl;unsigned long flags;spin_lock_irqsave (&port->lock, flags);
@@ -1555,23 +1581,14 @@ uart_block_til_ready(struct file *filp, struct uart_state *state)* not set RTS here - we want to make sure we catch * the data from the modem. */ -if (port->tty->termios->c_cflag &CBAUD ) { -mutex_lock (&port->mutex); -uart_set_mctrl (uport,TIOCM_DTR ); -mutex_unlock (&port->mutex); - } +if (port->tty->termios->c_cflag &CBAUD ) +tty_port_raise_dtr_rts (port);/* * and wait for the carrier to indicate that the * modem is ready for us. */ -mutex_lock (&port->mutex); -spin_lock_irq (&uport->lock); - uport->ops->enable_ms (uport); - mctrl = uport->ops->get_mctrl (uport); -spin_unlock_irq (&uport->lock); -mutex_unlock (&port->mutex); -if (mctrl &TIOCM_CAR ) +if (tty_port_carrier_raised (port))break ;schedule ();
@@ -2349,6 +2366,11 @@ static const struct tty_operations uart_ops = {#endif }; +static const struct tty_port_operations uart_port_ops = { + .carrier_raised = uart_carrier_raised, + .dtr_rts = uart_dtr_rts, +}; +/** * uart_register_driver - register a driver with the uart core layer * @drv: low level driver structure
@@ -2405,6 +2427,7 @@ int uart_register_driver(struct uart_driver *drv)struct tty_port *port = &state->port;tty_port_init (port); + port->ops = &uart_port_ops; port->close_delay =500 ;/* .5 seconds */ port->closing_wait =30000 ;/* 30 seconds */ tasklet_init(&state->tlet, uart_tasklet_action,
Signature · 1 line
1.7.2
PATCH 32/67 serial: trim locking on the helpers
In reply to Greg KHFrom: Alan Cox <[email protected]>
The port mutex protects port->tty, but these paths never need to walk from port->tty. They do need the low level lock as the API expects that but they already also take it.
Thus we can drop the extra mutex lock calls here.
--- drivers/serial/serial_core.c | 5 +---- 1 files changed, 1 insertions(+), 4 deletions(-)
drivers/serial/serial_core.c +1 -4
@@ -1506,12 +1506,10 @@ static int uart_carrier_raised(struct tty_port *port) struct uart_state *state = container_of(port, struct uart_state, port);struct uart_port *uport = state->uart_port;int mctrl; -mutex_lock (&port->mutex);spin_lock_irq (&uport->lock); uport->ops->enable_ms (uport); mctrl = uport->ops->get_mctrl (uport);spin_unlock_irq (&uport->lock); -mutex_unlock (&port->mutex);if (mctrl &TIOCM_CAR )return 1 ;return 0 ;
@@ -1521,12 +1519,11 @@ static void uart_dtr_rts(struct tty_port *port, int onoff) { struct uart_state *state = container_of(port, struct uart_state, port);struct uart_port *uport = state->uart_port; -mutex_lock (&port->mutex); +if (onoff)uart_set_mctrl (uport,TIOCM_DTR |TIOCM_RTS );else uart_clear_mctrl (uport,TIOCM_DTR |TIOCM_RTS ); -mutex_unlock (&port->mutex); }/*
Signature · 1 line
1.7.2
PATCH 33/67 serial: Use block_til_ready helper
In reply to Greg KHFrom: Alan Cox <[email protected]>
Our code now rather closely resembles the helper, so switch to it.
--- drivers/serial/serial_core.c | 87 +----------------------------------------- 1 files changed, 1 insertions(+), 86 deletions(-)
drivers/serial/serial_core.c +1 -86
@@ -1526,91 +1526,6 @@ static void uart_dtr_rts(struct tty_port *port, int onoff)uart_clear_mctrl (uport,TIOCM_DTR |TIOCM_RTS ); } -/* -* Block the open until the port is ready. We must be called with -* the per-port semaphore held. -*/ -static int -uart_block_til_ready (struct file *filp,struct uart_state *state) -{ -DECLARE_WAITQUEUE (wait, current); -struct tty_port *port = &state->port; -unsigned long flags; - -spin_lock_irqsave (&port->lock, flags); -if (!tty_hung_up_p (filp)) - port->count--; - port->blocked_open++; -spin_unlock_irqrestore (&port->lock, flags); - -add_wait_queue (&port->open_wait, &wait); -while (1 ) { -set_current_state (TASK_INTERRUPTIBLE ); - -/* -* If we have been hung up, tell userspace/restart open. -*/ -if (tty_hung_up_p (filp) || port->tty ==NULL ) -break ; - -/* -* If the port has been closed, tell userspace/restart open. -*/ -if (!(port->flags &ASYNC_INITIALIZED )) -break ; - -/* -* If non-blocking mode is set, or CLOCAL mode is set, -* we don't want to wait for the modem status lines to -* indicate that the port is ready. -* -* Also, if the port is not enabled/configured, we want -* to allow the open to succeed here. Note that we will -* have set TTY_IO_ERROR for a non-existant port. -*/ -if ((filp->f_flags &O_NONBLOCK ) || - (port->tty->termios->c_cflag &CLOCAL ) || - (port->tty->flags & (1 <<TTY_IO_ERROR ))) -break ; - -/* -* Set DTR to allow modem to know we're waiting. Do -* not set RTS here - we want to make sure we catch -* the data from the modem. -*/ -if (port->tty->termios->c_cflag &CBAUD ) -tty_port_raise_dtr_rts (port); - -/* -* and wait for the carrier to indicate that the -* modem is ready for us. -*/ -if (tty_port_carrier_raised (port)) -break ; - -schedule (); - -if (signal_pending (current)) -break ; - } -set_current_state (TASK_RUNNING ); -remove_wait_queue (&port->open_wait, &wait); - -spin_lock_irqsave (&port->lock, flags); -if (!tty_hung_up_p (filp)) - port->count++; - port->blocked_open--; -spin_unlock_irqrestore (&port->lock, flags); - -if (signal_pending (current)) -return -ERESTARTSYS ; - -if (!port->tty ||tty_hung_up_p (filp)) -return -EAGAIN ; - -return 0 ; -} -static struct uart_state *uart_get (struct uart_driver *drv,int line) {struct uart_state *state;
@@ -1719,7 +1634,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp)*/ mutex_unlock (&port->mutex);if (retval ==0 ) - retval =uart_block_til_ready (filp, state); + retval =tty_port_block_til_ready (port, tty, filp);/* * If this is the first open to succeed, adjust things to suit.
Signature · 1 line
1.7.2
PATCH 34/67 serial: fix termios settings in open
In reply to Greg KHFrom: Arnd Bergmann <[email protected]>
Move termios initialization in open into uart_dtr_rts to make sure it always gets called when necessary. Based on a suggestion from Alan Cox.
Alan writes:
Ok this sort of makes sense. Something isn't getting initialised and both getty and minicom will do a termios set which is sorting it out. This is occurring because the generic block_til_ready sets ASYNCB_NORMAL_ACTIVE so the termios updating gets skipped.
This patch should cure it and then we can think about doing it more elegantly by getting the serial layer to use tty_port_open, kfifo and the like and removing the tons of repeated crap in all the drivers.
--- drivers/serial/serial_core.c | 19 +++++++++---------- 1 files changed, 9 insertions(+), 10 deletions(-)
drivers/serial/serial_core.c +9 -10
@@ -1520,8 +1520,16 @@ static void uart_dtr_rts(struct tty_port *port, int onoff) struct uart_state *state = container_of(port, struct uart_state, port);struct uart_port *uport = state->uart_port; -if (onoff) +if (onoff) {uart_set_mctrl (uport,TIOCM_DTR |TIOCM_RTS ); + +/* +* If this is the first open to succeed, +* adjust things to suit. +*/ +if (!test_and_set_bit (ASYNCB_NORMAL_ACTIVE , &port->flags)) +uart_update_termios (port->tty, state); + }else uart_clear_mctrl (uport,TIOCM_DTR |TIOCM_RTS ); }
@@ -1636,15 +1644,6 @@ static int uart_open(struct tty_struct *tty, struct file *filp)if (retval ==0 ) retval =tty_port_block_til_ready (port, tty, filp); -/* -* If this is the first open to succeed, adjust things to suit. -*/ -if (retval ==0 && !(port->flags &ASYNC_NORMAL_ACTIVE )) { -set_bit (ASYNCB_NORMAL_ACTIVE , &port->flags); - -uart_update_termios (tty, state); - } - fail:return retval; }
Signature · 1 line
1.7.2
PATCH 35/67 tty: replace BKL with a new tty_lock
In reply to Greg KHFrom: Arnd Bergmann <[email protected]>
As a preparation for replacing the big kernel lock in the TTY layer, wrap all the callers in new macros tty_lock, tty_lock_nested and tty_unlock.
--- drivers/char/amiserial.c | 16 +++--- drivers/char/briq_panel.c | 6 +- drivers/char/n_hdlc.c | 16 +++--- drivers/char/n_r3964.c | 8 ++-- drivers/char/pty.c | 4 +- drivers/char/selection.c | 4 +- drivers/char/serial167.c | 4 +- drivers/char/sx.c | 12 ++-- drivers/char/tty_io.c | 115 ++++++++++++++++++++++------------------ drivers/char/tty_ldisc.c | 24 +++++---- drivers/char/vc_screen.c | 4 +- drivers/char/vt_ioctl.c | 10 ++-- drivers/serial/68360serial.c | 4 +- drivers/serial/crisv10.c | 4 +- drivers/serial/serial_core.c | 10 ++-- drivers/video/console/vgacon.c | 4 +- include/linux/tty.h | 31 +++++++++++ 17 files changed, 161 insertions(+), 115 deletions(-)
drivers/char/amiserial.c +8 -8
@@ -1072,7 +1072,7 @@ static int get_serial_info(struct async_struct * info,if (!retinfo)return -EFAULT ;memset (&tmp,0 ,sizeof (tmp)); -lock_kernel (); +tty_lock (); tmp.type = state->type; tmp.line = state->line; tmp.port = state->port;
@@ -1083,7 +1083,7 @@ static int get_serial_info(struct async_struct * info, tmp.close_delay = state->close_delay; tmp.closing_wait = state->closing_wait; tmp.custom_divisor = state->custom_divisor; -unlock_kernel (); +tty_unlock ();if (copy_to_user (retinfo,&tmp,sizeof (*retinfo)))return -EFAULT ;return 0 ;
@@ -1100,14 +1100,14 @@ static int set_serial_info(struct async_struct * info,if (copy_from_user (&new_serial,new_info,sizeof (new_serial)))return -EFAULT ; -lock_kernel (); +tty_lock (); state = info->state; old_state = *state; change_irq = new_serial.irq != state->irq; change_port = (new_serial.port != state->port);if (change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) { -unlock_kernel (); +tty_unlock ();return -EINVAL ; }
@@ -1127,7 +1127,7 @@ static int set_serial_info(struct async_struct * info, }if (new_serial.baud_base <9600 ) { -unlock_kernel (); +tty_unlock ();return -EINVAL ; }
@@ -1163,7 +1163,7 @@ check_and_exit: } }else retval =startup (info); -unlock_kernel (); +tty_unlock ();return retval; }
@@ -1538,7 +1538,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) orig_jiffies = jiffies; -lock_kernel (); +tty_lock_nested ();/* tty_wait_until_sent is called from lots of places */ /* * Set the check interval to be 1/5 of the estimated time to * send a single character, and make it at least 1. The check
@@ -1579,7 +1579,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)break ; }__set_current_state (TASK_RUNNING ); -unlock_kernel (); +tty_unlock ();#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT printk ("lsr = %d (jiff=%lu)...done\n" , lsr, jiffies);#endif
drivers/char/briq_panel.c +3 -3
@@ -67,15 +67,15 @@ static void set_led(char state)static int briq_panel_open (struct inode *ino,struct file *filep) { -lock_kernel (); +tty_lock ();/* enforce single access, vfd_is_open is protected by BKL */ if (vfd_is_open) { -unlock_kernel (); +tty_unlock ();return -EBUSY ; } vfd_is_open =1 ; -unlock_kernel (); +tty_unlock ();return 0 ; }
drivers/char/n_hdlc.c +8 -8
@@ -598,18 +598,18 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,return -EFAULT ; } -lock_kernel (); +tty_lock ();for (;;) {if (test_bit (TTY_OTHER_CLOSED , &tty->flags)) { -unlock_kernel (); +tty_unlock ();return -EIO ; } n_hdlc =tty2n_hdlc (tty);if (!n_hdlc || n_hdlc->magic !=HDLC_MAGIC || tty != n_hdlc->tty) { -unlock_kernel (); +tty_unlock ();return 0 ; }
@@ -619,13 +619,13 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,/* no data */ if (file->f_flags &O_NONBLOCK ) { -unlock_kernel (); +tty_unlock ();return -EAGAIN ; }interruptible_sleep_on (&tty->read_wait);if (signal_pending (current)) { -unlock_kernel (); +tty_unlock ();return -EINTR ; } }
@@ -648,7 +648,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,kfree (rbuf); else n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf); -unlock_kernel (); +tty_unlock ();return ret; }/* end of n_hdlc_tty_read() */
@@ -691,7 +691,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, count = maxframe; } -lock_kernel (); +tty_lock ();add_wait_queue (&tty->write_wait, &wait);set_current_state (TASK_INTERRUPTIBLE );
@@ -731,7 +731,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,n_hdlc_buf_put (&n_hdlc->tx_buf_list,tbuf);n_hdlc_send_frames (n_hdlc,tty); } -unlock_kernel (); +tty_unlock ();return error; }/* end of n_hdlc_tty_write() */
drivers/char/n_r3964.c +4 -4
@@ -1067,7 +1067,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,TRACE_L ("read()" ); -lock_kernel (); +tty_lock (); pClient =findClient (pInfo,task_pid (current));if (pClient) {
@@ -1109,7 +1109,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, } ret = -EPERM ; unlock: -unlock_kernel (); +tty_unlock ();return ret; }
@@ -1158,7 +1158,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, pHeader->locks =0 ; pHeader->owner =NULL ; -lock_kernel (); +tty_lock (); pClient =findClient (pInfo,task_pid (current));if (pClient) {
@@ -1177,7 +1177,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,add_tx_queue (pInfo, pHeader);trigger_transmit (pInfo); -unlock_kernel (); +tty_unlock ();return 0 ; }
drivers/char/pty.c +2 -2
@@ -692,9 +692,9 @@ static int ptmx_open(struct inode *inode, struct file *filp) {int ret; -lock_kernel (); +tty_lock (); ret =__ptmx_open (inode, filp); -unlock_kernel (); +tty_unlock ();return ret; }
drivers/char/selection.c +2 -2
@@ -313,7 +313,7 @@ int paste_selection(struct tty_struct *tty)struct tty_ldisc *ld;DECLARE_WAITQUEUE (wait, current); -lock_kernel (); +tty_lock_nested ();/* always called with BTM from vt_ioctl */ acquire_console_sem ();poke_blanked_console ();
@@ -338,6 +338,6 @@ int paste_selection(struct tty_struct *tty)__set_current_state (TASK_RUNNING );tty_ldisc_deref (ld); -unlock_kernel (); +tty_unlock ();return 0 ; }
drivers/char/serial167.c +2 -2
@@ -1505,7 +1505,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,printk ("cy_ioctl %s, cmd = %x arg = %lx\n" , tty->name, cmd, arg);/* */ #endif -lock_kernel (); +tty_lock ();switch (cmd) {case CYGETMON :
@@ -1561,7 +1561,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,default : ret_val = -ENOIOCTLCMD ; } -unlock_kernel (); +tty_unlock ();#ifdef SERIAL_DEBUG_OTHER printk ("cy_ioctl done\n" );
drivers/char/sx.c +6 -6
@@ -1699,7 +1699,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,if (!capable (CAP_SYS_RAWIO ))return -EPERM ; -lock_kernel (); +tty_lock ();sx_dprintk (SX_DEBUG_FIRMWARE ,"IOCTL %x: %lx\n" , cmd, arg);
@@ -1848,7 +1848,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,break ; } out: -unlock_kernel (); +tty_unlock ();func_exit ();return rc; }
@@ -1859,7 +1859,7 @@ static int sx_break(struct tty_struct *tty, int flag)int rv;func_enter (); -lock_kernel (); +tty_lock ();if (flag) rv =sx_send_command (port,HS_START ,-1 ,HS_IDLE_BREAK );
@@ -1868,7 +1868,7 @@ static int sx_break(struct tty_struct *tty, int flag)if (rv !=1 )printk (KERN_ERR "sx: couldn't send break (%x).\n" ,read_sx_byte (port->board,CHAN_OFFSET (port, hi_hstat))); -unlock_kernel (); +tty_unlock ();func_exit ();return 0 ; }
@@ -1909,7 +1909,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp,/* func_enter2(); */ rc =0 ; -lock_kernel (); +tty_lock ();switch (cmd) {case TIOCGSERIAL : rc =gs_getserial (&port->gs, argp);
@@ -1921,7 +1921,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp, rc = -ENOIOCTLCMD ;break ; } -unlock_kernel (); +tty_unlock ();/* func_exit(); */ return rc;
drivers/char/tty_io.c +64 -51
361 lines not on this page · raw message
drivers/char/tty_ldisc.c +13 -11
@@ -440,6 +440,8 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num)* * A helper opening method. Also a convenient debugging and check * point. +* +* Locking: always called with BTM already held. */ static int tty_ldisc_open (struct tty_struct *tty,struct tty_ldisc *ld)
@@ -447,10 +449,10 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)WARN_ON (test_and_set_bit (TTY_LDISC_OPEN , &tty->flags));if (ld->ops->open) {int ret; -/* BKL here locks verus a hangup event */ -lock_kernel (); +/* BTM here locks versus a hangup event */ +tty_lock_nested ();/* always held here already */ ret = ld->ops->open (tty); -unlock_kernel (); +tty_unlock ();return ret; }return 0 ;
@@ -553,7 +555,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)if (IS_ERR (new_ldisc))return PTR_ERR (new_ldisc); -lock_kernel (); +tty_lock ();/* * We need to look at the tty locking here for pty/tty pairs * when both sides try to change in parallel.
@@ -567,12 +569,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)*/ if (tty->ldisc->ops->num == ldisc) { -unlock_kernel (); +tty_unlock ();tty_ldisc_put (new_ldisc);return 0 ; } -unlock_kernel (); +tty_unlock ();/* * Problem: What do we do if this blocks ? * We could deadlock here
@@ -594,7 +596,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)mutex_lock (&tty->ldisc_mutex); } -lock_kernel (); +tty_lock ();set_bit (TTY_LDISC_CHANGING , &tty->flags);
@@ -607,7 +609,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) o_ldisc = tty->ldisc; -unlock_kernel (); +tty_unlock ();/* * Make sure we don't change while someone holds a * reference to the line discipline. The TTY_LDISC bit
@@ -633,14 +635,14 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)flush_scheduled_work ();mutex_lock (&tty->ldisc_mutex); -lock_kernel (); +tty_lock ();if (test_bit (TTY_HUPPED , &tty->flags)) {/* We were raced by the hangup method. It will have stomped the ldisc data and closed the ldisc down */ clear_bit (TTY_LDISC_CHANGING , &tty->flags);mutex_unlock (&tty->ldisc_mutex);tty_ldisc_put (new_ldisc); -unlock_kernel (); +tty_unlock ();return -EIO ; }
@@ -682,7 +684,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)if (o_work)schedule_delayed_work (&o_tty->buf.work,1 );mutex_unlock (&tty->ldisc_mutex); -unlock_kernel (); +tty_unlock ();return retval; }
drivers/char/vc_screen.c +2 -2
@@ -463,10 +463,10 @@ vcs_open(struct inode *inode, struct file *filp)unsigned int currcons =iminor (inode) &127 ;int ret =0 ; -lock_kernel (); +tty_lock ();if (currcons && !vc_cons_allocated (currcons-1 )) ret = -ENXIO ; -unlock_kernel (); +tty_unlock ();return ret; }
drivers/char/vt_ioctl.c +5 -5
@@ -509,7 +509,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, console = vc->vc_num; -lock_kernel (); +tty_lock ();if (!vc_cons_allocated (console)) {/* impossible? */ ret = -ENOIOCTLCMD ;
@@ -1336,7 +1336,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ret = -ENOIOCTLCMD ; } out: -unlock_kernel (); +tty_unlock ();return ret; eperm: ret = -EPERM ;
@@ -1503,7 +1503,7 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file, console = vc->vc_num; -lock_kernel (); +tty_lock ();if (!vc_cons_allocated (console)) {/* impossible? */ ret = -ENOIOCTLCMD ;
@@ -1571,11 +1571,11 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file, goto fallback; } out: -unlock_kernel (); +tty_unlock ();return ret; fallback: -unlock_kernel (); +tty_unlock ();return vt_ioctl (tty, file, cmd, arg); }
drivers/serial/68360serial.c +2 -2
@@ -1705,7 +1705,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)printk ("jiff=%lu..." , jiffies);#endif -lock_kernel (); +tty_lock_nested ();/* always held already since we come from ->close */ /* We go through the loop at least once because we can't tell * exactly when the last character exits the shifter. There can * be at least two characters waiting to be sent after the buffers
@@ -1734,7 +1734,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout) bdp--; }while (bdp->status &BD_SC_READY ); current->state =TASK_RUNNING ; -unlock_kernel (); +tty_unlock ();#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT printk ("lsr = %d (jiff=%lu)...done\n" , lsr, jiffies);#endif
drivers/serial/crisv10.c +2 -2
@@ -3924,7 +3924,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)* Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k) */ -lock_kernel (); +tty_lock_nested ();/* locked already when coming from close */ orig_jiffies = jiffies; while (info->xmit.head != info->xmit.tail || /* More in send queue */ (*info->ostatusadr & 0x007f) || /* more in FIFO */
@@ -3941,7 +3941,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) curr_time_usec - info->last_tx_active_usec; }set_current_state (TASK_RUNNING ); -unlock_kernel (); +tty_unlock (); }/*
drivers/serial/serial_core.c +5 -5
@@ -1274,7 +1274,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)struct uart_port *uport;unsigned long flags; -BUG_ON (!kernel_locked ()); +BUG_ON (!tty_locked ());if (!state)return ;
@@ -1382,7 +1382,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)if (port->type ==PORT_UNKNOWN || port->fifosize ==0 )return ; -lock_kernel (); +tty_lock_nested ();/* already locked when coming from close */ /* * Set the check interval to be 1/5 of the estimated time to
@@ -1429,7 +1429,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)break ; }set_current_state (TASK_RUNNING );/* might not be needed */ -unlock_kernel (); +tty_unlock (); }/*
@@ -1444,7 +1444,7 @@ static void uart_hangup(struct tty_struct *tty)struct tty_port *port = &state->port;unsigned long flags; -BUG_ON (!kernel_locked ()); +BUG_ON (!tty_locked ());pr_debug ("uart_hangup(%d)\n" , state->uart_port->line);mutex_lock (&port->mutex);
@@ -1578,7 +1578,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp)struct tty_port *port;int retval, line = tty->index; -BUG_ON (!kernel_locked ()); +BUG_ON (!tty_locked ());pr_debug ("uart_open(%d) called\n" , line);/*
drivers/video/console/vgacon.c +2 -2
@@ -1108,7 +1108,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) charmap +=4 * cmapsz;#endif -unlock_kernel (); +tty_unlock ();spin_lock_irq (&vga_lock);/* First, the Sequencer */ vga_wseq (state->vgabase,VGA_SEQ_RESET ,0x1 );
@@ -1192,7 +1192,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)vga_wattr (state->vgabase,VGA_AR_ENABLE_DISPLAY ,0 ); }spin_unlock_irq (&vga_lock); -lock_kernel (); +tty_lock ();return 0 ; }
include/linux/tty.h +31 -0
@@ -13,6 +13,7 @@#include <linux/tty_driver.h> #include <linux/tty_ldisc.h> #include <linux/mutex.h> +#include <linux/smp_lock.h> #include <asm/system.h>
@@ -573,5 +574,35 @@ extern int vt_ioctl(struct tty_struct *tty, struct file *file,extern long vt_compat_ioctl (struct tty_struct *tty,struct file * file,unsigned int cmd,unsigned long arg); +/* functions for preparation of BKL removal */ + +/* +* tty_lock_nested get the tty_lock while potentially holding it +* +* The Big TTY Mutex is a recursive lock, meaning you can take it +* from a thread that is already holding it. +* This is bad for a number of reasons, so tty_lock_nested should +* really be used as rarely as possible. If a code location can +* be shown to never get called with this held already, it should +* use tty_lock() instead. +*/ +static inline void __lockfunc tty_lock_nested(void) __acquires(kernel_lock) +{ +lock_kernel (); +} +static inline void tty_lock (void )__acquires (kernel_lock) +{ +#ifdef CONFIG_LOCK_KERNEL +/* kernel_locked is 1 for !CONFIG_LOCK_KERNEL */ +WARN_ON (kernel_locked ()); +#endif +lock_kernel (); +} +static inline void tty_unlock (void )__releases (kernel_lock) +{ +unlock_kernel (); +} +#define tty_locked () (kernel_locked()) +#endif /* __KERNEL__ */ #endif
Signature · 1 line
1.7.2
PATCH 36/67 tty: never hold BTM while getting tty_mutex
In reply to Greg KHFrom: Arnd Bergmann <[email protected]>
tty_mutex is never taken with the BTM held, except for two corner cases that are worked around here. We give up the BTM before calling tty_release() in the error path of tty_open().
Similarly, we reorder the locking in ptmx_open() to get tty_mutex before the BTM.
--- drivers/char/pty.c | 24 +++++++++++------------- drivers/char/tty_io.c | 12 ++++++------ 2 files changed, 17 insertions(+), 19 deletions(-)
drivers/char/pty.c +11 -13
@@ -647,7 +647,7 @@ static const struct tty_operations pty_unix98_ops = {* allocated_ptys_lock handles the list of free pty numbers */ -static int __ptmx_open (struct inode *inode,struct file *filp) +static int ptmx_open (struct inode *inode,struct file *filp) {struct tty_struct *tty;int retval;
@@ -656,11 +656,14 @@ static int __ptmx_open(struct inode *inode, struct file *filp)nonseekable_open (inode, filp);/* find a device that is not in use. */ +tty_lock (); index =devpts_new_index (inode); +tty_unlock ();if (index <0 )return index;mutex_lock (&tty_mutex); +tty_lock (); tty =tty_init_dev (ptm_driver, index,1 );mutex_unlock (&tty_mutex);
@@ -678,24 +681,19 @@ static int __ptmx_open(struct inode *inode, struct file *filp) goto out1; retval = ptm_driver->ops->open (tty, filp); -if (!retval) -return 0 ; +if (retval) + goto out2; out1: +tty_unlock (); +return retval; +out2: +tty_unlock ();tty_release (inode, filp);return retval; out:devpts_kill_index (inode, index); -return retval; -} - -static int ptmx_open (struct inode *inode,struct file *filp) -{ -int ret; - -tty_lock (); - ret =__ptmx_open (inode, filp);tty_unlock (); -return ret; +return retval; }static struct file_operations ptmx_fops;
drivers/char/tty_io.c +6 -6
@@ -1866,19 +1866,19 @@ got_driver:printk (KERN_DEBUG "error %d in opening %s..." , retval, tty->name);#endif +tty_unlock ();/* need to call tty_release without BTM */ tty_release (inode, filp); -if (retval != -ERESTARTSYS ) { -tty_unlock (); +if (retval != -ERESTARTSYS )return retval; - } -if (signal_pending (current)) { -tty_unlock (); + +if (signal_pending (current))return retval; - } +schedule ();/* * 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 ();
Signature · 1 line
1.7.2
PATCH 37/67 tty: fix console_sem lock order
In reply to Greg KHFrom: Arnd Bergmann <[email protected]>
vgacon_do_font_op releases and reacquires the BTM while holding console_sem. This violates the rule that BTM has to be the outer lock whenever we hold both.
There does not seem to be any reason to give up the BTM here, so just stop doing that.
--- drivers/video/console/vgacon.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-)
drivers/video/console/vgacon.c +0 -2
@@ -1108,7 +1108,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) charmap +=4 * cmapsz;#endif -tty_unlock ();spin_lock_irq (&vga_lock);/* First, the Sequencer */ vga_wseq (state->vgabase,VGA_SEQ_RESET ,0x1 );
@@ -1192,7 +1191,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)vga_wattr (state->vgabase,VGA_AR_ENABLE_DISPLAY ,0 ); }spin_unlock_irq (&vga_lock); -tty_lock ();return 0 ; }
Signature · 1 line
1.7.2
PATCH 38/67 cdc-acm: remove dead code
In reply to Greg KHFrom: Arnd Bergmann <[email protected]>
The wait_event_interruptible_timeout in acm_port_down is never reached. Remove it to avoid possible deadlocks with the big tty mutex if someone were to start using the blocking version of acm_port_down.
--- drivers/usb/class/cdc-acm.c | 12 +++--------- 1 files changed, 3 insertions(+), 9 deletions(-)
drivers/usb/class/cdc-acm.c +3 -9
@@ -636,19 +636,13 @@ static void acm_tty_unregister(struct acm *acm)static int acm_tty_chars_in_buffer (struct tty_struct *tty); -static void acm_port_down (struct acm *acm,int drain) +static void acm_port_down (struct acm *acm) {int i, nr = acm->rx_buflimit;mutex_lock (&open_mutex);if (acm->dev) {usb_autopm_get_interface (acm->control);acm_set_control (acm, acm->ctrlout =0 ); -/* try letting the last writes drain naturally */ -if (drain) { -wait_event_interruptible_timeout (acm->drain_wait, - (ACM_NW ==acm_wb_is_avail (acm)) || !acm->dev, -ACM_CLOSE_TIMEOUT *HZ ); - }usb_kill_urb (acm->ctrlurb);for (i =0 ; i <ACM_NW ; i++)usb_kill_urb (acm->wb[i].urb);
@@ -664,7 +658,7 @@ static void acm_tty_hangup(struct tty_struct *tty) {struct acm *acm = tty->driver_data;tty_port_hangup (&acm->port); -acm_port_down (acm,0 ); +acm_port_down (acm); }static void acm_tty_close (struct tty_struct *tty,struct file *filp)
@@ -685,7 +679,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)mutex_unlock (&open_mutex);return ; } -acm_port_down (acm,0 ); +acm_port_down (acm);tty_port_close_end (&acm->port, tty);tty_port_tty_set (&acm->port,NULL ); }
Signature · 1 line
1.7.2
PATCH 39/67 tty: introduce wait_event_interruptible_tty
In reply to Greg KHFrom: Arnd Bergmann <[email protected]>
Calling wait_event_interruptible implicitly releases the BKL when it sleeps, but we need to do this explcitly when we have converted it to a mutex.
--- drivers/char/cyclades.c | 2 +- drivers/char/istallion.c | 12 ++++++++---- drivers/char/n_r3964.c | 2 +- drivers/char/tty_port.c | 2 +- drivers/char/vt_ioctl.c | 5 ++++- drivers/serial/crisv10.c | 4 ++-- include/linux/tty.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 59 insertions(+), 10 deletions(-)
drivers/char/cyclades.c +1 -1
@@ -1607,7 +1607,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 (info->port.close_wait, +wait_event_interruptible_tty (info->port.close_wait, !(info->port.flags &ASYNC_CLOSING ));return (info->port.flags &ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS ; }
drivers/char/istallion.c +8 -4
@@ -954,7 +954,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned l* order of opens and closes may not be preserved across shared * memory, so we must wait until it is complete. */ -wait_event_interruptible (portp->raw_wait, +wait_event_interruptible_tty (portp->raw_wait, !test_bit (ST_CLOSING , &portp->state));if (signal_pending (current)) {return -ERESTARTSYS ;
@@ -989,7 +989,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned lset_bit (ST_OPENING , &portp->state);spin_unlock_irqrestore (&brd_lock, flags); -wait_event_interruptible (portp->raw_wait, +wait_event_interruptible_tty (portp->raw_wait, !test_bit (ST_OPENING , &portp->state));if (signal_pending (current)) rc = -ERESTARTSYS ;
@@ -1020,7 +1020,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned* occurs on this port. */ if (wait) { -wait_event_interruptible (portp->raw_wait, +wait_event_interruptible_tty (portp->raw_wait, !test_bit (ST_CLOSING , &portp->state));if (signal_pending (current)) {return -ERESTARTSYS ;
@@ -1052,7 +1052,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned* to come back. */ rc =0 ; -wait_event_interruptible (portp->raw_wait, +wait_event_interruptible_tty (portp->raw_wait, !test_bit (ST_CLOSING , &portp->state));if (signal_pending (current)) rc = -ERESTARTSYS ;
@@ -1073,6 +1073,10 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsignedstatic int stli_cmdwait (struct stlibrd *brdp,struct stliport *portp,unsigned long cmd,void *arg,int size,int copyback) { +/* +* no need for wait_event_tty because clearing ST_CMDING cannot block +* on BTM +*/ wait_event_interruptible (portp->raw_wait, !test_bit (ST_CMDING , &portp->state));if (signal_pending (current))
drivers/char/n_r3964.c +1 -1
@@ -1079,7 +1079,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, goto unlock; }/* block until there is a message: */ -wait_event_interruptible (pInfo->read_wait, +wait_event_interruptible_tty (pInfo->read_wait, (pMsg =remove_msg (pInfo, pClient))); }
drivers/char/tty_port.c +1 -1
@@ -231,7 +231,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 (port->close_wait, +wait_event_interruptible_tty (port->close_wait, !(port->flags &ASYNC_CLOSING ));if (port->flags &ASYNC_HUP_NOTIFY )return -EAGAIN ;
drivers/char/vt_ioctl.c +4 -1
@@ -133,7 +133,7 @@ static void vt_event_wait(struct vt_event_wait *vw)list_add (&vw->list, &vt_events);spin_unlock_irqrestore (&vt_event_lock, flags);/* Wait for it to pass */ -wait_event_interruptible (vt_event_waitqueue, vw->done); +wait_event_interruptible_tty (vt_event_waitqueue, vw->done);/* Dequeue it */ spin_lock_irqsave (&vt_event_lock, flags);list_del (&vw->list);
@@ -1761,10 +1761,13 @@ int vt_move_to_console(unsigned int vt, int alloc)return -EIO ; }release_console_sem (); +tty_lock ();if (vt_waitactive (vt +1 )) {pr_debug ("Suspend: Can't switch VCs." ); +tty_unlock ();return -EINTR ; } +tty_unlock ();return prev; }
drivers/serial/crisv10.c +2 -2
@@ -3981,7 +3981,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,*/ if (tty_hung_up_p (filp) || (info->flags &ASYNC_CLOSING )) { -wait_event_interruptible (info->close_wait, +wait_event_interruptible_tty (info->close_wait, !(info->flags &ASYNC_CLOSING ));#ifdef SERIAL_DO_RESTART if (info->flags &ASYNC_HUP_NOTIFY )
@@ -4139,7 +4139,7 @@ rs_open(struct tty_struct *tty, struct file * filp)*/ if (tty_hung_up_p (filp) || (info->flags &ASYNC_CLOSING )) { -wait_event_interruptible (info->close_wait, +wait_event_interruptible_tty (info->close_wait, !(info->flags &ASYNC_CLOSING ));#ifdef SERIAL_DO_RESTART return ((info->flags & ASYNC_HUP_NOTIFY) ?
include/linux/tty.h +42 -0
47 lines not on this page · raw message
Signature · 1 line
1.7.2
PATCH 40/67 tty: reorder ldisc locking
In reply to Greg KHFrom: Arnd Bergmann <[email protected]>
We need to release the BTM in paste_selection() when sleeping in tty_ldisc_ref_wait to avoid deadlocks with tty_ldisc_enable.
In tty_set_ldisc, we now always grab the BTM before taking the ldisc_mutex in order to avoid AB-BA deadlocks between the two.
tty_ldisc_halt potentially blocks on a workqueue function that takes the BTM, so we must release the BTM before calling it.
--- drivers/char/selection.c | 9 +++++++-- drivers/char/tty_ldisc.c | 24 ++++++++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-)
drivers/char/selection.c +7 -2
@@ -319,8 +319,13 @@ int paste_selection(struct tty_struct *tty)poke_blanked_console ();release_console_sem (); - ld =tty_ldisc_ref_wait (tty); - + ld =tty_ldisc_ref (tty); +if (!ld) { +tty_unlock (); + ld =tty_ldisc_ref_wait (tty); +tty_lock (); + } +add_wait_queue (&vc->paste_wait, &wait);while (sel_buffer && sel_buffer_lth > pasted) {set_current_state (TASK_INTERRUPTIBLE );
drivers/char/tty_ldisc.c +20 -4
@@ -582,6 +582,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)tty_wait_until_sent (tty,0 ); +tty_lock ();mutex_lock (&tty->ldisc_mutex);/*
@@ -591,13 +592,13 @@ 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 ();wait_event (tty_ldisc_wait,test_bit (TTY_LDISC_CHANGING , &tty->flags) ==0 ); +tty_lock ();mutex_lock (&tty->ldisc_mutex); } -tty_lock (); -set_bit (TTY_LDISC_CHANGING , &tty->flags);/*
@@ -634,8 +635,8 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)flush_scheduled_work (); -mutex_lock (&tty->ldisc_mutex);tty_lock (); +mutex_lock (&tty->ldisc_mutex);if (test_bit (TTY_HUPPED , &tty->flags)) {/* We were raced by the hangup method. It will have stomped the ldisc data and closed the ldisc down */
@@ -782,7 +783,20 @@ void tty_ldisc_hangup(struct tty_struct *tty)* Avoid racing set_ldisc or tty_ldisc_release */ mutex_lock (&tty->ldisc_mutex); -tty_ldisc_halt (tty); + +/* +* this is like tty_ldisc_halt, but we need to give up +* the BTM before calling cancel_delayed_work_sync, +* which may need to wait for another function taking the BTM +*/ +clear_bit (TTY_LDISC , &tty->flags); +tty_unlock (); +cancel_delayed_work_sync (&tty->buf.work); +mutex_unlock (&tty->ldisc_mutex); + +tty_lock (); +mutex_lock (&tty->ldisc_mutex); +/* At this point we have a closed ldisc and we want to reopen it. We could defer this to the next open but it means auditing a lot of other paths so this is
@@ -853,8 +867,10 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)* race with the set_ldisc code path. */ +tty_unlock ();tty_ldisc_halt (tty);flush_scheduled_work (); +tty_lock ();mutex_lock (&tty->ldisc_mutex);/*
Signature · 1 line
1.7.2
PATCH 41/67 tty: untangle locking of wait_until_sent
In reply to Greg KHFrom: Arnd Bergmann <[email protected]>
Some wait_until_sent versions require the big tty mutex, others don't and some callers of wait_until_sent already hold it while other don't. That leads to recursive use of the BTM in these functions, which we're trying to get rid of.
This turns all cleans up the locking there so that the driver's wait_until_sent function never takes the BTM itself if it is already called with that lock held.
--- drivers/char/amiserial.c | 11 +++++++++-- drivers/serial/68360serial.c | 2 -- drivers/serial/crisv10.c | 2 -- drivers/serial/serial_core.c | 31 ++++++++++++++++++++++--------- 4 files changed, 31 insertions(+), 15 deletions(-)
drivers/char/amiserial.c +9 -2
@@ -1528,6 +1528,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) {struct async_struct * info = tty->driver_data;unsigned long orig_jiffies, char_time; +int tty_was_locked =tty_locked ();int lsr;if (serial_paranoia_check (info, tty->name,"rs_wait_until_sent" ))
@@ -1538,7 +1539,12 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) orig_jiffies = jiffies; -tty_lock_nested ();/* tty_wait_until_sent is called from lots of places */ +/* +* tty_wait_until_sent is called from lots of places, +* with or without the BTM. +*/ +if (!tty_was_locked) +tty_lock ();/* * Set the check interval to be 1/5 of the estimated time to * send a single character, and make it at least 1. The check
@@ -1579,7 +1585,8 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)break ; }__set_current_state (TASK_RUNNING ); -tty_unlock (); +if (!tty_was_locked) +tty_unlock ();#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT printk ("lsr = %d (jiff=%lu)...done\n" , lsr, jiffies);#endif
drivers/serial/68360serial.c +0 -2
@@ -1705,7 +1705,6 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)printk ("jiff=%lu..." , jiffies);#endif -tty_lock_nested ();/* always held already since we come from ->close */ /* We go through the loop at least once because we can't tell * exactly when the last character exits the shifter. There can * be at least two characters waiting to be sent after the buffers
@@ -1734,7 +1733,6 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout) bdp--; }while (bdp->status &BD_SC_READY ); current->state =TASK_RUNNING ; -tty_unlock ();#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT printk ("lsr = %d (jiff=%lu)...done\n" , lsr, jiffies);#endif
drivers/serial/crisv10.c +0 -2
@@ -3924,7 +3924,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)* Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k) */ -tty_lock_nested ();/* locked already when coming from close */ orig_jiffies = jiffies; while (info->xmit.head != info->xmit.tail || /* More in send queue */ (*info->ostatusadr & 0x007f) || /* more in FIFO */
@@ -3941,7 +3940,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) curr_time_usec - info->last_tx_active_usec; }set_current_state (TASK_RUNNING ); -tty_unlock (); }/*
drivers/serial/serial_core.c +22 -9
@@ -60,7 +60,7 @@ static struct lock_class_key port_lock_key;static void uart_change_speed (struct tty_struct *tty,struct uart_state *state,struct ktermios *old_termios); -static void uart_wait_until_sent (struct tty_struct *tty,int timeout); +static void __uart_wait_until_sent (struct uart_port *port,int timeout);static void uart_change_pm (struct uart_state *state,int pm_state);/*
@@ -1322,8 +1322,16 @@ static void uart_close(struct tty_struct *tty, struct file *filp) tty->closing =1 ;spin_unlock_irqrestore (&port->lock, flags); -if (port->closing_wait !=ASYNC_CLOSING_WAIT_NONE ) -tty_wait_until_sent (tty,msecs_to_jiffies (port->closing_wait)); +if (port->closing_wait !=ASYNC_CLOSING_WAIT_NONE ) { +/* +* hack: open-coded tty_wait_until_sent to avoid +* recursive tty_lock +*/ +long timeout =msecs_to_jiffies (port->closing_wait); +if (wait_event_interruptible_timeout (tty->write_wait, + !tty_chars_in_buffer (tty), timeout) >=0 ) +__uart_wait_until_sent (uport, timeout); + }/* * At this point, we stop accepting input. To do this, we
@@ -1339,7 +1347,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)* has completely drained; this is especially * important if there is a transmit FIFO! */ -uart_wait_until_sent (tty, uport->timeout); +__uart_wait_until_sent (uport, uport->timeout); }uart_shutdown (tty, state);
@@ -1373,17 +1381,13 @@ done:mutex_unlock (&port->mutex); } -static void uart_wait_until_sent (struct tty_struct *tty,int timeout) +static void __uart_wait_until_sent (struct uart_port *port,int timeout) { -struct uart_state *state = tty->driver_data; -struct uart_port *port = state->uart_port;unsigned long char_time, expire;if (port->type ==PORT_UNKNOWN || port->fifosize ==0 )return ; -tty_lock_nested ();/* already locked when coming from close */ -/* * Set the check interval to be 1/5 of the estimated time to * send a single character, and make it at least 1. The check
@@ -1429,6 +1433,15 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)break ; }set_current_state (TASK_RUNNING );/* might not be needed */ +} + +static void uart_wait_until_sent (struct tty_struct *tty,int timeout) +{ +struct uart_state *state = tty->driver_data; +struct uart_port *port = state->uart_port; + +tty_lock (); +__uart_wait_until_sent (port, timeout);tty_unlock (); }
Signature · 1 line
1.7.2
PATCH 42/67 tty: remove tty_lock_nested
In reply to Greg KHFrom: Arnd Bergmann <[email protected]>
This changes all remaining users of tty_lock_nested to be non-recursive, which lets us kill this function. As a consequence, we won't need to keep the lock count any more, which allows more simplifications later.
--- drivers/char/pty.c | 2 +- drivers/char/selection.c | 4 ++-- drivers/char/tty_io.c | 41 ++++++++++++++++++++--------------------- drivers/char/tty_ldisc.c | 3 +-- include/linux/tty.h | 16 +--------------- 5 files changed, 25 insertions(+), 41 deletions(-)
drivers/char/pty.c +1 -1
@@ -62,7 +62,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)if (tty->driver == ptm_driver)devpts_pty_kill (tty->link);#endif -tty_vhangup (tty->link); +tty_vhangup_locked (tty->link); } }
drivers/char/selection.c +2 -2
@@ -313,7 +313,8 @@ int paste_selection(struct tty_struct *tty)struct tty_ldisc *ld;DECLARE_WAITQUEUE (wait, current); -tty_lock_nested ();/* always called with BTM from vt_ioctl */ +/* always called with BTM from vt_ioctl */ +WARN_ON (!tty_locked ());acquire_console_sem ();poke_blanked_console ();
@@ -343,6 +344,5 @@ int paste_selection(struct tty_struct *tty)__set_current_state (TASK_RUNNING );tty_ldisc_deref (ld); -tty_unlock ();return 0 ; }
drivers/char/tty_io.c +20 -21
108 lines not on this page · raw message
drivers/char/tty_ldisc.c +1 -2
@@ -450,9 +450,8 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)if (ld->ops->open) {int ret;/* BTM here locks versus a hangup event */ -tty_lock_nested ();/* always held here already */ +WARN_ON (!tty_locked ()); ret = ld->ops->open (tty); -tty_unlock ();return ret; }return 0 ;
include/linux/tty.h +1 -15
@@ -417,6 +417,7 @@ extern int is_ignored(int sig);extern int tty_signal (int sig,struct tty_struct *tty);extern void tty_hangup (struct tty_struct *tty);extern void tty_vhangup (struct tty_struct *tty); +extern void tty_vhangup_locked (struct tty_struct *tty);extern void tty_vhangup_self (void );extern void tty_unhangup (struct file *filp);extern int tty_hung_up_p (struct file *filp);
@@ -575,21 +576,6 @@ extern long vt_compat_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg);/* functions for preparation of BKL removal */ - -/* -* tty_lock_nested get the tty_lock while potentially holding it -* -* The Big TTY Mutex is a recursive lock, meaning you can take it -* from a thread that is already holding it. -* This is bad for a number of reasons, so tty_lock_nested should -* really be used as rarely as possible. If a code location can -* be shown to never get called with this held already, it should -* use tty_lock() instead. -*/ -static inline void __lockfunc tty_lock_nested(void) __acquires(kernel_lock) -{ -lock_kernel (); -}static inline void tty_lock (void )__acquires (kernel_lock) {#ifdef CONFIG_LOCK_KERNEL
Signature · 1 line
1.7.2
PATCH 43/67 tty: implement BTM as mutex instead of BKL
In reply to Greg KHFrom: Arnd Bergmann <[email protected]>
The tty locking now follows the rules for mutexes, so we can replace the BKL usage with a new subsystem wide mutex.
This patch for now makes the new behaviour an optional experimental feature that can be enabled for testing purposes.
Using a regular mutex here will change the behaviour when blocked on the BTM from spinning to sleeping, but that should not be visible to the user.
Using the mutex also means that all the BTM is now covered by lockdep.
--- drivers/char/Makefile | 1 + drivers/char/tty_mutex.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/tty.h | 8 +++++++ lib/Kconfig.debug | 10 +++++++++ 4 files changed, 66 insertions(+), 0 deletions(-) create mode 100644 drivers/char/tty_mutex.c
drivers/char/Makefile +1 -0
@@ -9,6 +9,7 @@ FONTMAPFILE = cp437.uni obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o +obj-$(CONFIG_TTY_MUTEX) += tty_mutex.o obj-$(CONFIG_LEGACY_PTYS) += pty.o obj-$(CONFIG_UNIX98_PTYS) += pty.o obj-y += misc.o
drivers/char/tty_mutex.c new file +47 -0
47 lines not on this page · raw message
include/linux/tty.h +8 -0
@@ -575,7 +575,14 @@ extern int vt_ioctl(struct tty_struct *tty, struct file *file,extern long vt_compat_ioctl (struct tty_struct *tty,struct file * file,unsigned int cmd,unsigned long arg); +/* tty_mutex.c */ /* functions for preparation of BKL removal */ +#ifdef CONFIG_TTY_MUTEX +extern void __lockfunc tty_lock(void) __acquires(tty_lock); +extern void __lockfunc tty_unlock(void) __releases(tty_lock); +extern struct task_struct *__big_tty_mutex_owner; +#define tty_locked () (current == __big_tty_mutex_owner) +#else static inline void tty_lock (void )__acquires (kernel_lock) {#ifdef CONFIG_LOCK_KERNEL
@@ -589,6 +596,7 @@ static inline void tty_unlock(void) __releases(kernel_lock) unlock_kernel(); }#define tty_locked () (kernel_locked()) +#endif /* * wait_event_interruptible_tty -- wait for a condition with the tty lock held
lib/Kconfig.debug +10 -0
@@ -428,6 +428,16 @@ config RT_MUTEX_TESTER help This option enables a rt-mutex tester. +config TTY_MUTEX + bool "Use a mutex instead of BKL for TTY locking" + depends on EXPERIMENTAL && SMP + help + The TTY subsystem traditionally depends on the big kernel lock + for serialization. Saying Y here replaces the BKL with the Big + TTY Mutex (BTM). + Building a kernel without the BKL is only possible with TTY_MUTEX + enabled. + config DEBUG_SPINLOCK bool "Spinlock and rw-lock debugging: basic checks" depends on DEBUG_KERNEL
Signature · 1 line
1.7.2
Arnd Bergmann
maintainerPATCH 1/1 tty: implement BTM as mutex instead of BKL
The tty locking now follows the rules for mutexes, so we can replace the BKL usage with a new subsystem wide mutex.
Using a regular mutex here will change the behaviour when blocked on the BTM from spinning to sleeping, but that should not be visible to the user.
Using the mutex also means that all the BTM is now covered by lockdep.
drivers/char/Makefile +1 -0
@@ -9,6 +9,7 @@ FONTMAPFILE = cp437.uni obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o +obj-y += tty_mutex.o obj-$(CONFIG_LEGACY_PTYS) += pty.o obj-$(CONFIG_UNIX98_PTYS) += pty.o obj-y += misc.o
drivers/char/tty_mutex.c new file +47 -0
47 lines not on this page · raw message
include/linux/tty.h +5 -13
@@ -575,20 +575,12 @@ extern int vt_ioctl(struct tty_struct *tty, struct file *file,extern long vt_compat_ioctl (struct tty_struct *tty,struct file * file,unsigned int cmd,unsigned long arg); +/* tty_mutex.c */ /* functions for preparation of BKL removal */ -static inline void tty_lock (void )__acquires (kernel_lock) -{ -#ifdef CONFIG_LOCK_KERNEL -/* kernel_locked is 1 for !CONFIG_LOCK_KERNEL */ -WARN_ON (kernel_locked ()); -#endif -lock_kernel (); -} -static inline void tty_unlock (void )__releases (kernel_lock) -{ -unlock_kernel (); -} -#define tty_locked () (kernel_locked()) +extern void __lockfunc tty_lock(void) __acquires(tty_lock); +extern void __lockfunc tty_unlock(void) __releases(tty_lock); +extern struct task_struct *__big_tty_mutex_owner; +#define tty_locked () (current == __big_tty_mutex_owner)/* * wait_event_interruptible_tty -- wait for a condition with the tty lock held
PATCH 44/67 tty: release BTM while sleeping in block_til_ready
In reply to Greg KHFrom: Arnd Bergmann <[email protected]>
Most tty drivers may block while opening a device. Since this possibly depends on another thread closing it first and both threads may need the BTM, we need to release it here.
--- drivers/char/amiserial.c | 2 ++ drivers/char/ip2/ip2main.c | 4 ++++ drivers/char/serial167.c | 4 +++- drivers/char/specialix.c | 2 ++ drivers/char/synclink.c | 2 ++ drivers/char/synclink_gt.c | 2 ++ drivers/char/synclinkmp.c | 2 ++ drivers/char/tty_port.c | 2 ++ drivers/serial/68328serial.c | 2 ++ drivers/serial/68360serial.c | 2 ++ drivers/serial/crisv10.c | 2 ++ 11 files changed, 25 insertions(+), 1 deletions(-)
drivers/char/amiserial.c +2 -0
@@ -1710,7 +1710,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 ();schedule (); +tty_lock (); }__set_current_state (TASK_RUNNING );remove_wait_queue (&info->open_wait, &wait);
drivers/char/ip2/ip2main.c +4 -0
@@ -1486,7 +1486,9 @@ ip2_open( PTTY tty, struct file *pFile )if (tty_hung_up_p (pFile) || ( pCh->flags &ASYNC_CLOSING )) {if ( pCh->flags &ASYNC_CLOSING ) { +tty_unlock ();schedule (); +tty_lock (); }if (tty_hung_up_p (pFile) ) {set_current_state (TASK_RUNNING );
@@ -1548,7 +1550,9 @@ ip2_open( PTTY tty, struct file *pFile ) rc = (( pCh->flags &ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS );break ; } +tty_unlock ();schedule (); +tty_lock (); }set_current_state (TASK_RUNNING );remove_wait_queue (&pCh->open_wait, &wait);
drivers/char/serial167.c +3 -1
@@ -1786,7 +1786,9 @@ block_til_ready(struct tty_struct *tty, struct file *filp, tty->name, info->count);/**/ #endif -schedule (); +tty_unlock (); +schedule (); +tty_lock (); }__set_current_state (TASK_RUNNING );remove_wait_queue (&info->open_wait, &wait);
drivers/char/specialix.c +2 -0
@@ -1365,7 +1365,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, retval = -ERESTARTSYS ;break ; } +tty_unlock ();schedule (); +tty_lock (); }set_current_state (TASK_RUNNING );
drivers/char/synclink.c +2 -0
@@ -3349,7 +3349,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 ();schedule (); +tty_lock (); }set_current_state (TASK_RUNNING );
drivers/char/synclink_gt.c +2 -0
@@ -3244,7 +3244,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 ();schedule (); +tty_lock (); }set_current_state (TASK_RUNNING );
drivers/char/synclinkmp.c +2 -0
@@ -3365,7 +3365,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 ();schedule (); +tty_lock (); }set_current_state (TASK_RUNNING );
drivers/char/tty_port.c +2 -0
@@ -294,7 +294,9 @@ int tty_port_block_til_ready(struct tty_port *port, retval = -ERESTARTSYS ;break ; } +tty_unlock ();schedule (); +tty_lock (); }finish_wait (&port->open_wait, &wait);
drivers/serial/68328serial.c +2 -0
@@ -1235,7 +1235,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, retval = -ERESTARTSYS ;break ; } +tty_unlock ();schedule (); +tty_lock (); } current->state =TASK_RUNNING ;remove_wait_queue (&info->open_wait, &wait);
drivers/serial/68360serial.c +2 -0
@@ -1860,7 +1860,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 ();schedule (); +tty_lock (); } current->state =TASK_RUNNING ;remove_wait_queue (&info->open_wait, &wait);
drivers/serial/crisv10.c +2 -0
@@ -4055,7 +4055,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 ();schedule (); +tty_lock (); }set_current_state (TASK_RUNNING );remove_wait_queue (&info->open_wait, &wait);
Signature · 1 line
1.7.2
PATCH 45/67 8250: fix set_ldisc operation
In reply to Greg KHFrom: Arnd Bergmann <[email protected]>
The ldisc number now gets passed into ->set_ldisc.
--- drivers/serial/8250.c | 9 ++------- 1 files changed, 2 insertions(+), 7 deletions(-)
drivers/serial/8250.c +2 -7
@@ -2404,14 +2404,9 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, }static void -serial8250_set_ldisc (struct uart_port *port) +serial8250_set_ldisc (struct uart_port *port,int new) { -int line = port->line; - -if (line >= port->state->port.tty->driver->num) -return ; - -if (port->state->port.tty->ldisc->ops->num ==N_PPS ) { +if (new ==N_PPS ) { port->flags |=UPF_HARDPPS_CD ;serial8250_enable_ms (port); }else
Signature · 1 line
1.7.2
PATCH 46/67 tty: avoid recursive BTM in pty_close
In reply to Greg KHFrom: Arnd Bergmann <[email protected]>
When the console has been redirected, a hangup of the tty will cause tty_release to be called under the big tty_mutex, which leads to a deadlock because hangup is also called under the BTM.
This moves the BTM deeper into the tty_hangup function so we can close the redirected tty without holding the BTM. In case of pty, we now need to drop the BTM before calling tty_vhangup.
--- drivers/char/pty.c | 4 +++- drivers/char/tty_io.c | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-)
drivers/char/pty.c +3 -1
@@ -62,7 +62,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp)if (tty->driver == ptm_driver)devpts_pty_kill (tty->link);#endif -tty_vhangup_locked (tty->link); +tty_unlock (); +tty_vhangup (tty->link); +tty_lock (); } }
drivers/char/tty_io.c +12 -12
@@ -471,7 +471,7 @@ void tty_wakeup(struct tty_struct *tty)EXPORT_SYMBOL_GPL (tty_wakeup);/** -* do_tty_hangup - actual handler for hangup events +* __tty_hangup - actual handler for hangup events * @work: tty device * * This can be called by the "eventd" kernel thread. That is process
@@ -492,7 +492,7 @@ EXPORT_SYMBOL_GPL(tty_wakeup);* tasklist_lock to walk task list for hangup event * ->siglock to protect ->signal/->sighand */ -void tty_vhangup_locked (struct tty_struct *tty) +void __tty_hangup (struct tty_struct *tty) {struct file *cons_filp =NULL ;struct file *filp, *f =NULL ;
@@ -512,10 +512,12 @@ void tty_vhangup_locked(struct tty_struct *tty) }spin_unlock (&redirect_lock); +tty_lock (); +/* inuse_filps is protected by the single tty lock, this really needs to change if we want to flush the workqueue with the lock held */ -check_tty_count (tty,"do_tty_hangup" ); +check_tty_count (tty,"tty_hangup" );file_list_lock ();/* This breaks for file handles being sent over AF_UNIX sockets ? */
@@ -594,6 +596,9 @@ void tty_vhangup_locked(struct tty_struct *tty)*/ set_bit (TTY_HUPPED , &tty->flags);tty_ldisc_enable (tty); + +tty_unlock (); +if (f)fput (f); }
@@ -603,9 +608,7 @@ static void do_tty_hangup(struct work_struct *work)struct tty_struct *tty = container_of(work, struct tty_struct, hangup_work); -tty_lock (); -tty_vhangup_locked (tty); -tty_unlock (); +__tty_hangup (tty); }/**
@@ -643,13 +646,12 @@ void tty_vhangup(struct tty_struct *tty)printk (KERN_DEBUG "%s vhangup...\n" ,tty_name (tty, buf));#endif -tty_lock (); -tty_vhangup_locked (tty); -tty_unlock (); +__tty_hangup (tty); }EXPORT_SYMBOL (tty_vhangup); +/** * tty_vhangup_self - process vhangup for own ctty *
@@ -727,10 +729,8 @@ void disassociate_ctty(int on_exit)if (tty) { tty_pgrp =get_pid (tty->pgrp);if (on_exit) { -tty_lock ();if (tty->driver->type !=TTY_DRIVER_TYPE_PTY ) -tty_vhangup_locked (tty); -tty_unlock (); +tty_vhangup (tty); }tty_kref_put (tty); }else if (on_exit) {
Signature · 1 line
1.7.2
PATCH 47/67 serial: max3107: introduce a max3107 driver
In reply to Greg KHFrom: jianwei.yang <[email protected]>
This device is used by some of the Intel MID platforms. It's not similar enough to the MAX3100 to use the same driver.
At this point the driver is specific to the platform and not generalised. We will fix that later.
--- drivers/serial/Kconfig | 8 + drivers/serial/Makefile | 1 + drivers/serial/max3107.c | 1442 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/serial/max3107.h | 358 ++++++++++++ 4 files changed, 1809 insertions(+), 0 deletions(-) create mode 100644 drivers/serial/max3107.c create mode 100644 drivers/serial/max3107.h
drivers/serial/Kconfig +8 -0
@@ -542,6 +542,14 @@ config SERIAL_S5PV210 help Serial port support for Samsung's S5P Family of SoC's +config SERIAL_MAX3107 + tristate "MAX3107 support" + depends on SPI && GPIOLIB + select SERIAL_CORE + default y + help + MAX3107 chip support + config SERIAL_MAX3100 tristate "MAX3100 support" depends on SPI
drivers/serial/Makefile +1 -0
@@ -46,6 +46,7 @@ obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o obj-$(CONFIG_SERIAL_MAX3100) += max3100.o +obj-$(CONFIG_SERIAL_MAX3107) += max3107.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o obj-$(CONFIG_SERIAL_MUX) += mux.o obj-$(CONFIG_SERIAL_68328) += 68328serial.o
drivers/serial/max3107.c new file +1442 -0
1,442 lines not on this page · raw message
drivers/serial/max3107.h new file +358 -0
358 lines not on this page · raw message
Signature · 1 line
1.7.2
PATCH 48/67 serial: max3107: Abstract out the platform specific bits
In reply to Greg KHFrom: Alan Cox <[email protected]>
At the moment there is only one platform type supported and there is is hard wired, but with these changes the infrastructure is now there for anyone else to provide methods for their hardware.
--- drivers/serial/Kconfig | 21 ++- drivers/serial/Makefile | 1 + drivers/serial/max3107-aava.c | 344 ++++++++++++++++++++++++++++++++++ drivers/serial/max3107.c | 413 +++++++++-------------------------------- drivers/serial/max3107.h | 85 ++++++++- include/linux/serial_core.h | 4 + 6 files changed, 531 insertions(+), 337 deletions(-) create mode 100644 drivers/serial/max3107-aava.c
drivers/serial/Kconfig +15 -6
@@ -542,20 +542,29 @@ config SERIAL_S5PV210 help Serial port support for Samsung's S5P Family of SoC's + +config SERIAL_MAX3100 + tristate "MAX3100 support" + depends on SPI + select SERIAL_CORE + help + MAX3100 chip support + config SERIAL_MAX3107 tristate "MAX3107 support" - depends on SPI && GPIOLIB + depends on SPI select SERIAL_CORE - default y help MAX3107 chip support -config SERIAL_MAX3100 - tristate "MAX3100 support" - depends on SPI +config SERIAL_MAX3107_AAVA + tristate "MAX3107 AAVA platform support" + depends on X86_MRST && SERIAL_MAX3107 && GPIOLIB select SERIAL_CORE help - MAX3100 chip support + Support for the MAX3107 chip configuration found on the AAVA + platform. Includes the extra initialisation and GPIO support + neded for this device. config SERIAL_DZ bool "DECstation DZ serial driver"
drivers/serial/Makefile +1 -0
@@ -47,6 +47,7 @@ obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o obj-$(CONFIG_SERIAL_MAX3100) += max3100.o obj-$(CONFIG_SERIAL_MAX3107) += max3107.o +obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o obj-$(CONFIG_SERIAL_MUX) += mux.o obj-$(CONFIG_SERIAL_68328) += 68328serial.o
drivers/serial/max3107-aava.c new file +344 -0
344 lines not on this page · raw message
drivers/serial/max3107.c +84 -329
602 lines not on this page · raw message
drivers/serial/max3107.h +83 -2
95 lines not on this page · raw message
include/linux/serial_core.h +4 -0
@@ -186,6 +186,10 @@#define PORT_ALTERA_JTAGUART 91#define PORT_ALTERA_UART 92 +/* MAX3107 */ +#define PORT_MAX3107 94 + +#ifdef __KERNEL__#include <linux/compiler.h>
Signature · 1 line
1.7.2
PATCH 49/67 tty_io: remove casts from void*
In reply to Greg KHFrom: Kulikov Vasiliy <[email protected]>
Remove unnesessary casts from void*.
--- drivers/char/tty_io.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-)
drivers/char/tty_io.c +6 -6
@@ -893,7 +893,7 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,struct inode *inode;struct tty_ldisc *ld; - tty = (struct tty_struct *)file->private_data; + tty = file->private_data; inode = file->f_path.dentry->d_inode;if (tty_paranoia_check (tty, inode,"tty_read" ))return -EIO ;
@@ -1070,7 +1070,7 @@ static ssize_t tty_write(struct file *file, const char __user *buf,ssize_t ret;struct tty_ldisc *ld; - tty = (struct tty_struct *)file->private_data; + tty = file->private_data;if (tty_paranoia_check (tty, inode,"tty_write" ))return -EIO ; if (!tty || !tty->ops->write ||
@@ -1513,7 +1513,7 @@ int tty_release(struct inode *inode, struct file *filp)int idx;char buf[64 ]; - tty = (struct tty_struct *)filp->private_data; + tty = filp->private_data;if (tty_paranoia_check (tty, inode,"tty_release_dev" ))return 0 ;
@@ -1920,7 +1920,7 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait)struct tty_ldisc *ld;int ret =0 ; - tty = (struct tty_struct *)filp->private_data; + tty = filp->private_data;if (tty_paranoia_check (tty, filp->f_path.dentry->d_inode,"tty_poll" ))return 0 ;
@@ -1937,7 +1937,7 @@ static int __tty_fasync(int fd, struct file *filp, int on)unsigned long flags;int retval =0 ; - tty = (struct tty_struct *)filp->private_data; + tty = filp->private_data;if (tty_paranoia_check (tty, filp->f_path.dentry->d_inode,"tty_fasync" )) goto out;
@@ -2497,7 +2497,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)struct tty_ldisc *ld;struct inode *inode = file->f_dentry->d_inode; - tty = (struct tty_struct *)file->private_data; + tty = file->private_data;if (tty_paranoia_check (tty, inode,"tty_ioctl" ))return -EINVAL ;
Signature · 1 line
1.7.2
PATCH 50/67 vt: Fix warning: statement with no effect due to vt_kern.h
In reply to Greg KHFrom: Kevin Winchester <[email protected]>
Using:
gcc (GCC) 4.5.0 20100610 (prerelease)
with CONFIG_CONSOLE_TRANSLATIONS=n, the following warnings are seen:
drivers/char/vt_ioctl.c: In function ‘vt_ioctl’:
drivers/char/vt_ioctl.c:1309:4: warning: statement with no effect drivers/char/vt.c: In function ‘vc_allocate’:
drivers/char/vt.c:774:3: warning: statement with no effect drivers/video/console/vgacon.c: In function ‘vgacon_init’:
drivers/video/console/vgacon.c:587:3: warning: statement with no effect drivers/video/console/vgacon.c: In function ‘vgacon_deinit’:
drivers/video/console/vgacon.c:606:2: warning: statement with no effect drivers/video/console/fbcon.c: In function ‘fbcon_init’:
drivers/video/console/fbcon.c:1087:3: warning: statement with no effect drivers/video/console/fbcon.c:1089:3: warning: statement with no effect drivers/video/console/fbcon.c: In function ‘fbcon_set_disp’:
drivers/video/console/fbcon.c:1369:3: warning: statement with no effect drivers/video/console/fbcon.c:1371:3: warning: statement with no effect
This is because several functions in include/linux/vt_kern.h are defined to (0). Convert them to static inline functions to silence the warnings and gain a bit of type safety.
--- include/linux/vt_kern.h | 57 +++++++++++++++++++++++++++++++++++++--------- 1 files changed, 46 insertions(+), 11 deletions(-)
include/linux/vt_kern.h +46 -11
@@ -76,17 +76,52 @@ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc);#define vc_translate (vc, c) ((vc)->vc_translate[(c) | \ ((vc)->vc_toggle_meta ? 0x80 : 0)])#else -#define con_set_trans_old (arg) (0) -#define con_get_trans_old (arg) (-EINVAL) -#define con_set_trans_new (arg) (0) -#define con_get_trans_new (arg) (-EINVAL) -#define con_clear_unimap (vc, ui) (0) -#define con_set_unimap (vc, ct, list) (0) -#define con_set_default_unimap (vc) (0) -#define con_copy_unimap (d, s) (0) -#define con_get_unimap (vc, ct, uct, list) (-EINVAL) -#define con_free_unimap (vc) do { ; } while (0) -#define con_protect_unimap (vc, rdonly) do { ; } while (0) +static inline int con_set_trans_old (unsigned char __user *table) +{ +return 0 ; +} +static inline int con_get_trans_old (unsigned char __user *table) +{ +return -EINVAL ; +} +static inline int con_set_trans_new (unsigned short __user *table) +{ +return 0 ; +} +static inline int con_get_trans_new (unsigned short __user *table) +{ +return -EINVAL ; +} +static inline int con_clear_unimap (struct vc_data *vc,struct unimapinit *ui) +{ +return 0 ; +} +static inline +int con_set_unimap (struct vc_data *vc,ushort ct,struct unipair __user *list) +{ +return 0 ; +} +static inline +int con_get_unimap (struct vc_data *vc,ushort ct,ushort __user *uct, +struct unipair __user *list) +{ +return -EINVAL ; +} +static inline int con_set_default_unimap (struct vc_data *vc) +{ +return 0 ; +} +static inline void con_free_unimap (struct vc_data *vc) +{ +} +static inline void con_protect_unimap (struct vc_data *vc,int rdonly) +{ +} +static inline +int con_copy_unimap (struct vc_data *dst_vc,struct vc_data *src_vc) +{ +return 0 ; +}#define vc_translate (vc, c) (c)#endif
Signature · 1 line
1.7.2
PATCH 51/67 serial: crisv10: formatting of pointers in printk()
In reply to Greg KHFrom: Kulikov Vasiliy <[email protected]>
Use %p instead of %08x in printk().
--- drivers/serial/crisv10.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/serial/crisv10.c +2 -2
@@ -4522,8 +4522,8 @@ static int __init rs_init(void)INIT_WORK (&info->work, do_softint);if (info->enabled) { -printk (KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n" , - serial_driver->name, info->line, (unsigned int )info->ioport); +printk (KERN_INFO "%s%d at %p is a builtin UART with DMA\n" , + serial_driver->name, info->line, info->ioport); } }#ifdef CONFIG_ETRAX_FAST_TIMER
Signature · 1 line
1.7.2
PATCH 52/67 serial: "altera_uart: simplify altera_uart_console_putc()" checkpatch fixes
In reply to Greg KHFrom: Andrew Morton <[email protected]>
ERROR: code indent should use tabs where possible
#32: FILE: drivers/serial/altera_uart.c:397:
+^I ALTERA_UART_STATUS_TRDY_MSK))$
total: 1 errors, 0 warnings, 39 lines checked
./patches/altera_uart-simplify-altera_uart_console_putc.patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Please run checkpatch prior to sending patches
This fix got lost when someone merged "altera_uart: simplify altera_uart_console_putc()". Please don't lose fixes. Please don't write of mere patches which have trivial checkpatch errors.
--- drivers/serial/altera_uart.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/serial/altera_uart.c +1 -1
@@ -394,7 +394,7 @@ int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp)static void altera_uart_console_putc (struct uart_port *port,const char c) {while (!(readl (port->membase +ALTERA_UART_STATUS_REG ) & -ALTERA_UART_STATUS_TRDY_MSK )) +ALTERA_UART_STATUS_TRDY_MSK ))cpu_relax ();writel (c, port->membase +ALTERA_UART_TXDATA_REG );
Signature · 1 line
1.7.2
PATCH 53/67 serial: fix missing bit coverage of ASYNC_FLAGS
In reply to Greg KHFrom: John Villalovos <[email protected]>
It seems that currently ASYNC_FLAGS is one bit short of covering all the bits of the ASYNC user flags. In particular it does not cover the ASYNC_AUTOPROBE bit.
ASYNCB_LAST_USER and ASYNCB_AUTOPROBE are both equal to 15.
Therefore:ASYNC_AUTOPROBE = 1000 0000 0000 0000ASYNC_FLAGS = 0111 1111 1111 1111
So ASYNC_FLAGS is not covering the ASYNC_AUTOPROBE bit.
This patch fixes the issue and with the patch the values will be:ASYNC_AUTOPROBE = 1000 0000 0000 0000ASYNC_FLAGS = 1111 1111 1111 1111
As a side note, doing a "git grep" I didn't find any use of ASYNC_AUTOPROBE or ASYNCB_AUTOPROBE in the kernel, besides this include file.
--- include/linux/serial.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
include/linux/serial.h +1 -1
@@ -151,7 +151,7 @@ struct serial_uart_config {#define ASYNC_BUGGY_UART (1U << ASYNCB_BUGGY_UART)#define ASYNC_AUTOPROBE (1U << ASYNCB_AUTOPROBE) -#define ASYNC_FLAGS ((1U << ASYNCB_LAST_USER) - 1) +#define ASYNC_FLAGS ((1U << (ASYNCB_LAST_USER + 1)) - 1)#define ASYNC_USR_MASK (ASYNC_SPD_HI|ASYNC_SPD_VHI| \ ASYNC_CALLOUT_NOHUP|ASYNC_SPD_SHI|ASYNC_LOW_LATENCY)#define ASYNC_SPD_CUST (ASYNC_SPD_HI|ASYNC_SPD_VHI)
Signature · 1 line
1.7.2
PATCH 54/67 serial: general fixes in the serial_rs485 structure
In reply to Greg KHFrom: Claudio Scordino <[email protected]>
Fix several issues related to the RS485 interface:
- It adds the flag SER_RS485_RTS_BEFORE_SEND that was missing from the serial_rs485 structure (even if "delay_rts_before_send" was existing)
- It adds a further "delay_rts_after_send" field for those drivers that can have a delay after send (e.g., atmel_serial)
- It fixes the usage of the structure in the atmel_serial driver (where "delay_rts_before_send" should be used instead of "delay_rts_after_send").
--- drivers/serial/atmel_serial.c | 11 ++++++++--- include/linux/serial.h | 4 +++- 2 files changed, 11 insertions(+), 4 deletions(-)
drivers/serial/atmel_serial.c +8 -3
@@ -217,7 +217,8 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)if (rs485conf->flags &SER_RS485_ENABLED ) {dev_dbg (port->dev,"Setting UART to RS485\n" ); atmel_port->tx_done_mask =ATMEL_US_TXEMPTY ; -UART_PUT_TTGR (port, rs485conf->delay_rts_before_send); +if (rs485conf->flags &SER_RS485_RTS_AFTER_SEND ) +UART_PUT_TTGR (port, rs485conf->delay_rts_after_send); mode |=ATMEL_US_USMODE_RS485 ; }else {dev_dbg (port->dev,"Setting UART to RS232\n" );
@@ -292,7 +293,9 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)if (atmel_port->rs485.flags &SER_RS485_ENABLED ) {dev_dbg (port->dev,"Setting UART to RS485\n" ); -UART_PUT_TTGR (port, atmel_port->rs485.delay_rts_before_send); +if (atmel_port->rs485.flags &SER_RS485_RTS_AFTER_SEND ) +UART_PUT_TTGR (port, + atmel_port->rs485.delay_rts_after_send); mode |=ATMEL_US_USMODE_RS485 ; }else {dev_dbg (port->dev,"Setting UART to RS232\n" );
@@ -1211,7 +1214,9 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,if (atmel_port->rs485.flags &SER_RS485_ENABLED ) {dev_dbg (port->dev,"Setting UART to RS485\n" ); -UART_PUT_TTGR (port, atmel_port->rs485.delay_rts_before_send); +if (atmel_port->rs485.flags &SER_RS485_RTS_AFTER_SEND ) +UART_PUT_TTGR (port, + atmel_port->rs485.delay_rts_after_send); mode |=ATMEL_US_USMODE_RS485 ; }else {dev_dbg (port->dev,"Setting UART to RS232\n" );
include/linux/serial.h +3 -1
@@ -210,8 +210,10 @@ struct serial_rs485 {#define SER_RS485_ENABLED (1 << 0)#define SER_RS485_RTS_ON_SEND (1 << 1)#define SER_RS485_RTS_AFTER_SEND (1 << 2) +#define SER_RS485_RTS_BEFORE_SEND (1 << 3)__u32 delay_rts_before_send;/* Milliseconds */ -__u32 padding[6 ];/* Memory is cheap, new structs +__u32 delay_rts_after_send;/* Milliseconds */ +__u32 padding[5 ];/* Memory is cheap, new structs are a royal PITA .. */ };
Signature · 1 line
1.7.2
PATCH 55/67 serial: mcf: don't take spinlocks in already protected functions
In reply to Greg KHFrom: Yury Georgievskiy <[email protected]>
Don't take the port spinlock in uart functions where the serial core already takes care of locking/unlocking them.
The code would actually lock up on architectures where spinlocks are implemented.
Also protect calling mcf_rx_chars/mcf_tx_chars in the interrupt handler by the port spinlock and use IRQ_RETVAL to return from isr.
--- drivers/serial/mcf.c | 31 +++++++++++++------------------ 1 files changed, 13 insertions(+), 18 deletions(-)
drivers/serial/mcf.c +13 -18
@@ -70,16 +70,14 @@ static unsigned int mcf_tx_empty(struct uart_port *port)static unsigned int mcf_get_mctrl (struct uart_port *port) { struct mcf_uart *pp = container_of(port, struct mcf_uart, port); -unsigned long flags;unsigned int sigs; -spin_lock_irqsave (&port->lock, flags); sigs = (readb (port->membase +MCFUART_UIPR ) &MCFUART_UIPR_CTS ) ?0 :TIOCM_CTS ; sigs |= (pp->sigs &TIOCM_RTS ); sigs |= (mcf_getppdcd (port->line) ?TIOCM_CD :0 ); sigs |= (mcf_getppdtr (port->line) ?TIOCM_DTR :0 ); -spin_unlock_irqrestore (&port->lock, flags); +return sigs; }
@@ -88,16 +86,13 @@ static unsigned int mcf_get_mctrl(struct uart_port *port)static void mcf_set_mctrl (struct uart_port *port,unsigned int sigs) { struct mcf_uart *pp = container_of(port, struct mcf_uart, port); -unsigned long flags; -spin_lock_irqsave (&port->lock, flags); pp->sigs = sigs;mcf_setppdtr (port->line, (sigs &TIOCM_DTR ));if (sigs &TIOCM_RTS )writeb (MCFUART_UOP_RTS , port->membase +MCFUART_UOP1 );else writeb (MCFUART_UOP_RTS , port->membase +MCFUART_UOP0 ); -spin_unlock_irqrestore (&port->lock, flags); }/****************************************************************************/
@@ -105,12 +100,9 @@ static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs)static void mcf_start_tx (struct uart_port *port) { struct mcf_uart *pp = container_of(port, struct mcf_uart, port); -unsigned long flags; -spin_lock_irqsave (&port->lock, flags); pp->imr |=MCFUART_UIR_TXREADY ;writeb (pp->imr, port->membase +MCFUART_UIMR ); -spin_unlock_irqrestore (&port->lock, flags); }/****************************************************************************/
@@ -118,12 +110,9 @@ static void mcf_start_tx(struct uart_port *port)static void mcf_stop_tx (struct uart_port *port) { struct mcf_uart *pp = container_of(port, struct mcf_uart, port); -unsigned long flags; -spin_lock_irqsave (&port->lock, flags); pp->imr &= ~MCFUART_UIR_TXREADY ;writeb (pp->imr, port->membase +MCFUART_UIMR ); -spin_unlock_irqrestore (&port->lock, flags); }/****************************************************************************/
@@ -131,12 +120,9 @@ static void mcf_stop_tx(struct uart_port *port)static void mcf_stop_rx (struct uart_port *port) { struct mcf_uart *pp = container_of(port, struct mcf_uart, port); -unsigned long flags; -spin_lock_irqsave (&port->lock, flags); pp->imr &= ~MCFUART_UIR_RXREADY ;writeb (pp->imr, port->membase +MCFUART_UIMR ); -spin_unlock_irqrestore (&port->lock, flags); }/****************************************************************************/
@@ -366,13 +352,22 @@ static irqreturn_t mcf_interrupt(int irq, void *data)struct uart_port *port = data; struct mcf_uart *pp = container_of(port, struct mcf_uart, port);unsigned int isr; +irqreturn_t ret =IRQ_NONE ; isr =readb (port->membase +MCFUART_UISR ) & pp->imr; -if (isr &MCFUART_UIR_RXREADY ) + +spin_lock (&port->lock); +if (isr &MCFUART_UIR_RXREADY ) {mcf_rx_chars (pp); -if (isr &MCFUART_UIR_TXREADY ) + ret =IRQ_HANDLED ; + } +if (isr &MCFUART_UIR_TXREADY ) {mcf_tx_chars (pp); -return IRQ_HANDLED ; + ret =IRQ_HANDLED ; + } +spin_unlock (&port->lock); + +return ret; }/****************************************************************************/
Signature · 1 line
1.7.2
PATCH 56/67 serial: MMIO32 support for 8250_early.c
In reply to Greg KHFrom: Samium Gromoff <[email protected]>
Provide MMIO32 support in 8250_early (aka earlycon)
--- Documentation/kernel-parameters.txt | 3 ++ drivers/serial/8250_early.c | 57 +++++++++++++++++++++++++--------- 2 files changed, 45 insertions(+), 15 deletions(-)
Documentation/kernel-parameters.txt +3 -0
@@ -687,8 +687,11 @@ and is between 256 and 4096 characters. It is defined in the file earlycon= [KNL] Output early console device and options. uart[8250],io,<addr>[,options] uart[8250],mmio,<addr>[,options] + uart[8250],mmio32,<addr>[,options] Start an early, polled-mode console on the 8250/16550 UART at the specified I/O port or MMIO address. + MMIO inter-register address stride is either 8bit (mmio) + or 32bit (mmio32). The options are the same as for ttyS, above. earlyprintk= [X86,SH,BLACKFIN]
drivers/serial/8250_early.c +42 -15
106 lines not on this page · raw message
Signature · 1 line
1.7.2
PATCH 57/67 timbuart: use __devinit and __devexit macros for probe and remove
In reply to Greg KHFrom: Richard Röjfors <[email protected]>
Move the probe and remove functions to the devinit and devexit sections.
--- drivers/serial/timbuart.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
drivers/serial/timbuart.c +3 -3
@@ -423,7 +423,7 @@ static struct uart_driver timbuart_driver = { .nr = 1 }; -static int timbuart_probe (struct platform_device *dev) +static int __devinit timbuart_probe (struct platform_device *dev) {int err, irq;struct timbuart_port *uart;
@@ -489,7 +489,7 @@ err_mem:return err; } -static int timbuart_remove (struct platform_device *dev) +static int __devexit timbuart_remove(struct platform_device *dev) {struct timbuart_port *uart =platform_get_drvdata (dev);
@@ -507,7 +507,7 @@ static struct platform_driver timbuart_platform_driver = { .owner = THIS_MODULE, }, .probe = timbuart_probe, - .remove = timbuart_remove, + .remove = __devexit_p(timbuart_remove), };/*--------------------------------------------------------------------------*/
Signature · 1 line
1.7.2
PATCH 58/67 serial: 68328serial.c: remove dead (ALMA_ANS | DRAGONIXVZ | M68EZ328ADS)
In reply to Greg KHFrom: Christoph Egger <[email protected]>
(ALMA_ANS | DRAGONIXVZ | M68EZ328ADS) doesn't exist in Kconfig, therefore remove all references to it from the source code.
--- drivers/serial/68328serial.c | 16 +++++----------- 1 files changed, 5 insertions(+), 11 deletions(-)
drivers/serial/68328serial.c +5 -11
@@ -98,19 +98,13 @@ static void change_speed(struct m68k_serial *info);* Setup for console. Argument comes from the boot command line. */ -#if defined(CONFIG_M68EZ328ADS ) || defined(CONFIG_ALMA_ANS ) || defined(CONFIG_DRAGONIXVZ ) -#define CONSOLE_BAUD_RATE 115200 -#define DEFAULT_CBAUD B115200 -#else -/* (es) */ -/* note: this is messy, but it works, again, perhaps defined somewhere else?*/ -#ifdef CONFIG_M68VZ328 -#define CONSOLE_BAUD_RATE 19200 -#define DEFAULT_CBAUD B19200 -#endif -/* (/es) */ +/* note: this is messy, but it works, again, perhaps defined somewhere else?*/ +#ifdef CONFIG_M68VZ328 +#define CONSOLE_BAUD_RATE 19200 +#define DEFAULT_CBAUD B19200#endif +#ifndef CONSOLE_BAUD_RATE #define CONSOLE_BAUD_RATE 9600#define DEFAULT_CBAUD B9600
Signature · 1 line
1.7.2
PATCH 59/67 serial: add support for OX16PCI958 card
In reply to Greg KHFrom: Lytochkin Boris <[email protected]>
--- drivers/serial/8250_pci.c | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-)
drivers/serial/8250_pci.c +13 -0
@@ -994,6 +994,7 @@ static int skip_tx_en_setup(struct serial_private *priv,#define PCI_DEVICE_ID_TITAN_800E 0xA014#define PCI_DEVICE_ID_TITAN_200EI 0xA016#define PCI_DEVICE_ID_TITAN_200EISI 0xA017 +#define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538/* Unknown vendors/cards - this should not be in linux/pci_ids.h */ #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
@@ -1542,6 +1543,8 @@ enum pci_board_num_t { pbn_b2_4_921600, pbn_b2_8_921600, + pbn_b2_8_1152000, + pbn_b2_bt_1_115200, pbn_b2_bt_2_115200, pbn_b2_bt_4_115200,
@@ -1960,6 +1963,13 @@ static struct pciserial_board pci_boards[] __devinitdata = { .uart_offset = 8, }, + [pbn_b2_8_1152000] = { + .flags = FL_BASE2, + .num_ports = 8, + .base_baud = 1152000, + .uart_offset = 8, + }, + [pbn_b2_bt_1_115200] = { .flags = FL_BASE2|FL_BASE_BARS, .num_ports = 1,
@@ -2875,6 +2885,9 @@ static struct pci_device_id serial_pci_tbl[] = { {PCI_VENDOR_ID_OXSEMI ,PCI_DEVICE_ID_OXSEMI_16PCI952 ,PCI_ANY_ID ,PCI_ANY_ID ,0 ,0 , pbn_b0_bt_2_921600 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI958, +PCI_ANY_ID ,PCI_ANY_ID ,0 ,0 , + pbn_b2_8_1152000 },/* * Oxford Semiconductor Inc. Tornado PCI express device range.
Signature · 1 line
1.7.2
PATCH 60/67 mxser: remove unnesesary NULL check
In reply to Greg KHFrom: Kulikov Vasiliy <[email protected]>
mxser_transmit_chars(tty, port) is called only from mxser_interrupt(). NULL check is performed in mxser_interrupt() so it is redundant here.
--- drivers/char/mxser.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/char/mxser.c +1 -1
@@ -2193,7 +2193,7 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port port->mon_data.up_txcnt += (cnt - port->xmit_cnt); port->icount.tx += (cnt - port->xmit_cnt); -if (port->xmit_cnt <WAKEUP_CHARS && tty) +if (port->xmit_cnt <WAKEUP_CHARS )tty_wakeup (tty);if (port->xmit_cnt <=0 ) {
Signature · 1 line
1.7.2
PATCH 61/67 hsu: driver for Medfield High Speed UART device
In reply to Greg KHFrom: Feng Tang <[email protected]>
This is a PCI & UART driver, which suppors both PIO and DMA mode UART operation. It has 3 identical UART ports and one internal DMA controller.
Current FW will export 4 pci devices for hsu: 3 uart ports and 1 dma controller, each has one IRQ line. And we need to discuss the device model, one PCI device covering whole HSU should be a better model, but there is a problem of how to export the 4 IRQs info
Current driver set the highest baud rate to 2746800bps, which is easy to scale down to 115200/230400.... To suport higher baud rate, we need add special process, change DLAB/DLH/PS/DIV/MUL registers all together.
921600 is the highest baud rate that has been tested with Bluetooth modem connected to HSU port 0. Will test more when there is right BT firmware.
Current version contains several work around for A0's Silicon bugs
--- drivers/serial/Kconfig | 10 + drivers/serial/Makefile | 1 + drivers/serial/mfd.c | 1488 +++++++++++++++++++++++++++++++++++++++++++ include/linux/serial_core.h | 2 + include/linux/serial_mfd.h | 47 ++ include/linux/serial_reg.h | 16 + 6 files changed, 1564 insertions(+), 0 deletions(-) create mode 100644 drivers/serial/mfd.c create mode 100644 include/linux/serial_mfd.h
drivers/serial/Kconfig +10 -0
@@ -724,6 +724,16 @@ config MRST_MAX3110_IRQ help This has to be enabled after Moorestown GPIO driver is loaded +config SERIAL_MFD_HSU + tristate "Medfield High Speed UART support" + depends on PCI + select SERIAL_CORE + +config SERIAL_MFD_HSU_CONSOLE + boolean "Medfile HSU serial console support" + depends on SERIAL_MFD_HSU=y + select SERIAL_CORE_CONSOLE + config SERIAL_BFIN tristate "Blackfin serial port support" depends on BLACKFIN
drivers/serial/Makefile +1 -0
@@ -87,3 +87,4 @@ obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o +obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o
drivers/serial/mfd.c new file +1488 -0
1,488 lines not on this page · raw message
include/linux/serial_core.h +2 -0
@@ -189,6 +189,8 @@/* MAX3107 */ #define PORT_MAX3107 94 +/* High Speed UART for Medfield */ +#define PORT_MFD 95#ifdef __KERNEL__
include/linux/serial_mfd.h new file +47 -0
47 lines not on this page · raw message
include/linux/serial_reg.h +16 -0
@@ -221,8 +221,24 @@#define UART_FCR_PXAR16 0x80/* receive FIFO threshold = 16 */ #define UART_FCR_PXAR32 0xc0/* receive FIFO threshold = 32 */ +/* +* Intel MID on-chip HSU (High Speed UART) defined bits +*/ +#define UART_FCR_HSU_64_1B 0x00/* receive FIFO treshold = 1 */ +#define UART_FCR_HSU_64_16B 0x40/* receive FIFO treshold = 16 */ +#define UART_FCR_HSU_64_32B 0x80/* receive FIFO treshold = 32 */ +#define UART_FCR_HSU_64_56B 0xc0/* receive FIFO treshold = 56 */ + +#define UART_FCR_HSU_16_1B 0x00/* receive FIFO treshold = 1 */ +#define UART_FCR_HSU_16_4B 0x40/* receive FIFO treshold = 4 */ +#define UART_FCR_HSU_16_8B 0x80/* receive FIFO treshold = 8 */ +#define UART_FCR_HSU_16_14B 0xc0/* receive FIFO treshold = 14 */ +#define UART_FCR_HSU_64B_FIFO 0x20/* chose 64 bytes FIFO */ +#define UART_FCR_HSU_16B_FIFO 0x00/* chose 16 bytes FIFO */ +#define UART_FCR_HALF_EMPT_TXI 0x00/* trigger TX_EMPT IRQ for half empty */ +#define UART_FCR_FULL_EMPT_TXI 0x08/* trigger TX_EMPT IRQ for full empty */ /* * These register definitions are for the 16C950
Signature · 1 line
1.7.2
PATCH 62/67 hsu: add a periodic timer to check dma rx channel
In reply to Greg KHFrom: Feng Tang <[email protected]>
A general problem for uart rx dma channel is you never know when and how much data will be received, so usually preset it a DMA descriptor with a big size, and rely on DMA RX timeout IRQ to know there is some data in rx channel.
For a RX data size of multiple of MOTSR, there will be no timeout IRQ issued, thus OS will never be notified about that.
This is a work around for that, current timer frequency is 5 times per second, it should vary according to the baud rate
When future silicon version fix the problem, this workaround need be removed
--- drivers/serial/mfd.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 47 insertions(+), 3 deletions(-)
drivers/serial/mfd.c +47 -3
@@ -64,6 +64,8 @@#define mfd_readl (obj, offset) readl(obj->reg + offset)#define mfd_writel (obj, offset, val) writel(val, obj->reg + offset) +#define HSU_DMA_TIMEOUT_CHECK_FREQ (HZ/10) +struct hsu_dma_buffer {u8 *buf;dma_addr_t dma_addr;
@@ -75,7 +77,8 @@ struct hsu_dma_chan {u32 id;u32 dirt;/* to or from device */ struct uart_hsu_port *uport; -void __iomem *reg; +void __iomem *reg; +struct timer_list rx_timer;/* only needed by RX channel */ };struct uart_hsu_port {
@@ -377,6 +380,8 @@ void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf | (0x1 << 24) /* timeout bit, see HSU Errata 1 */ );chan_writel (rxc,HSU_CH_CR ,0x3 ); + +mod_timer (&rxc->rx_timer, jiffies +HSU_DMA_TIMEOUT_CHECK_FREQ ); }/* Protected by spin_lock_irqsave(port->lock) */
@@ -437,8 +442,13 @@ void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts)/* We can use 2 ways to calc the actual transfer len */ count =chan_readl (chan,HSU_CH_D0SAR ) - dbuf->dma_addr; -if (!count) +if (!count) { +/* restart the channel before we leave */ +chan_writel (chan,HSU_CH_CR ,0x3 );return ; + } + +del_timer (&chan->rx_timer);dma_sync_single_for_cpu (port->dev, dbuf->dma_addr, dbuf->dma_size,DMA_FROM_DEVICE );
@@ -463,9 +473,12 @@ void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts) | (0x1 << 16) | (0x1 <<24 )/* timeout bit, see HSU Errata 1 */ ); +tty_flip_buffer_push (tty); +chan_writel (chan,HSU_CH_CR ,0x3 ); + chan->rx_timer.expires = jiffies +HSU_DMA_TIMEOUT_CHECK_FREQ ; +add_timer (&chan->rx_timer); -tty_flip_buffer_push (tty); }static void serial_hsu_stop_rx (struct uart_port *port)
@@ -893,6 +906,8 @@ static void serial_hsu_shutdown(struct uart_port *port) container_of(port, struct uart_hsu_port, port);unsigned long flags; +del_timer_sync (&up->rxc->rx_timer); +/* Disable interrupts from this port */ up->ier =0 ;serial_out (up,UART_IER ,0 );
@@ -1348,6 +1363,28 @@ err_disable:return ret; } +static void hsu_dma_rx_timeout (unsigned long data) +{ +struct hsu_dma_chan *chan = (void *)data; +struct uart_hsu_port *up = chan->uport; +struct hsu_dma_buffer *dbuf = &up->rxbuf; +int count =0 ; +unsigned long flags; + +spin_lock_irqsave (&up->port.lock, flags); + + count =chan_readl (chan,HSU_CH_D0SAR ) - dbuf->dma_addr; + +if (!count) { +mod_timer (&chan->rx_timer, jiffies +HSU_DMA_TIMEOUT_CHECK_FREQ ); + goto exit; + } + +hsu_dma_rx (up,0 ); +exit: +spin_unlock_irqrestore (&up->port.lock, flags); +} +static void hsu_global_init (void ) {struct hsu_port *hsu;
@@ -1409,6 +1446,13 @@ static void hsu_global_init(void) dchan->uport = &hsu->port[i/2 ]; dchan->reg = hsu->reg +HSU_DMA_CHANS_REG_OFFSET + i *HSU_DMA_CHANS_REG_LENGTH ; + +/* Work around for RX */ +if (dchan->dirt ==DMA_FROM_DEVICE ) { +init_timer (&dchan->rx_timer); + dchan->rx_timer.function = hsu_dma_rx_timeout; + dchan->rx_timer.data = (unsigned long )dchan; + } dchan++; }
Signature · 1 line
1.7.2
PATCH 63/67 hsu: some code cleanup
In reply to Greg KHFrom: Feng Tang <[email protected]>
Major changes are:
* refine the comments in the driver
* remove unused member from structure "hsu_port"
* extended spin_lock protoction for dma mode in port_irq()
--- drivers/serial/mfd.c | 85 +++++++++++-------------------------------------- 1 files changed, 19 insertions(+), 66 deletions(-)
drivers/serial/mfd.c +19 -66
@@ -3,7 +3,7 @@* * Refer pxa.c, 8250.c and some other drivers in drivers/serial/ * -* (C) Copyright 2009 Intel Corporation +* (C) Copyright 2010 Intel Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License
@@ -11,30 +11,16 @@* of the License. */ -/* Notes: -* 1. there should be 2 types of register access method, one for -* UART ports, the other for the general purpose registers -* -* 2. It used to have a Irda port, but was defeatured recently -* -* 3. Based on the info from HSU MAS, 0/1 channel are assigned to -* port0, 2/3 chan to port 1, 4/5 chan to port 3. Even number -* chan will be read, odd chan for write -* -* 4. HUS supports both the 64B and 16B FIFO version, but this driver -* will only use 64B version +* 1. DMA channel allocation: 0/1 channel are assigned to port 0, +* 2/3 chan to port 1, 4/5 chan to port 3. Even number chans +* are used for RX, odd chans for TX * -* 5. In A0 stepping, UART will not support TX half empty flag, thus -* need add a #ifdef judgement +* 2. In A0 stepping, UART will not support TX half empty flag * -* 6. One more bug for A0, the loopback mode won't support AFC -* auto-flow control -* -* 7. HSU has some special FCR control bits, we add it to serial_reg.h -* -* 8. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always asserted, -* only when the HW is reset the DDCD and DDSR will be triggered +* 3. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always +* asserted, only when the HW is reset the DDCD and DDSR will +* be triggered */ #include <linux/module.h>
@@ -75,7 +61,7 @@ struct hsu_dma_buffer {struct hsu_dma_chan {u32 id; -u32 dirt;/* to or from device */ +enum dma_data_direction dirt;struct uart_hsu_port *uport;void __iomem *reg;struct timer_list rx_timer;/* only needed by RX channel */
@@ -102,8 +88,6 @@ struct uart_hsu_port {/* Top level data structure of HSU */ struct hsu_port { -struct pci_device *pdev; -void __iomem *reg;unsigned long paddr;unsigned long iolen;
@@ -112,23 +96,9 @@ struct hsu_port {struct uart_hsu_port port[3 ];struct hsu_dma_chan chans[10 ]; -#ifdef CONFIG_DEBUG_FS struct dentry *debugfs; -#endif }; -static inline void hexdump (char *str,u8 *addr,int cnt) -{ -int i; - -for (i =0 ; i < cnt; i +=8 ) { -printk ("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x" , - addr[i], addr[i+1 ], addr[i+2 ], addr[i+3 ], - addr[i+4 ], addr[i+5 ], addr[i+6 ], addr[i+7 ]); -printk ("\n" ); - } -} -static inline unsigned int serial_in (struct uart_hsu_port *up,int offset) {unsigned int val;
@@ -353,9 +323,6 @@ void hsu_dma_tx(struct uart_hsu_port *up) | (0x1 << 8) | (0x1 <<16 ) | (0x1 << 24)); - -WARN (chan_readl (up->txc,HSU_CH_CR ) &0x1 , -"TX channel has already be started!!\n" ); up->dma_tx_on =1 ;chan_writel (up->txc,HSU_CH_CR ,0x1 ); }
@@ -367,7 +334,6 @@ void hsu_dma_tx(struct uart_hsu_port *up)/* The buffer is already cache coherent */ void hsu_dma_start_rx_chan (struct hsu_dma_chan *rxc,struct hsu_dma_buffer *dbuf) { -/* Need start RX dma channel here */ dbuf->ofs =0 ;chan_writel (rxc,HSU_CH_BSR ,32 );
@@ -426,35 +392,32 @@ void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts)return ;/* -* first need to know how many is already transferred, +* First need to know how many is already transferred, * then check if its a timeout DMA irq, and return * the trail bytes out, push them up and reenable the -* channel, better to use 2 descriptors at the same time +* channel */ -/* timeout IRQ, need wait some time, see Errata 2 */ +/* Timeout IRQ, need wait some time, see Errata 2 */ if (int_sts &0xf00 )udelay (2 );/* Stop the channel */ chan_writel (chan,HSU_CH_CR ,0x0 ); -/* We can use 2 ways to calc the actual transfer len */ count =chan_readl (chan,HSU_CH_D0SAR ) - dbuf->dma_addr; -if (!count) { -/* restart the channel before we leave */ +/* Restart the channel before we leave */ chan_writel (chan,HSU_CH_CR ,0x3 );return ; } -del_timer (&chan->rx_timer);dma_sync_single_for_cpu (port->dev, dbuf->dma_addr, dbuf->dma_size,DMA_FROM_DEVICE );/* -* head will only wrap around when we recycle +* Head will only wrap around when we recycle * the DMA buffer, and when that happens, we * explicitly set tail to 0. So head will * always be greater than tail.
@@ -496,10 +459,6 @@ static void serial_hsu_stop_rx(struct uart_port *port) } } -/* -* if there is error flag, should we just reset the FIFO or keeps -* working on it -*/ static inline void receive_chars (struct uart_hsu_port *up,int *status) {struct tty_struct *tty = up->port.state->port.tty;
@@ -571,7 +530,6 @@ static void transmit_chars(struct uart_hsu_port *up) {struct circ_buf *xmit = &up->port.state->xmit;int count; -int i =0 ;/* for debug use */ if (up->port.x_char) {serial_out (up,UART_TX , up->port.x_char);
@@ -592,13 +550,11 @@ static void transmit_chars(struct uart_hsu_port *up)* into it won't clear the EMPT bit, so we may need be cautious * by useing a shorter buffer */ -/* count = up->port.fifosize; */ count = up->port.fifosize -4 ;#endif do { serial_out(up, UART_TX, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - i++; up->port.icount.tx++; if (uart_circ_empty(xmit))
@@ -628,7 +584,7 @@ static inline void check_modem_status(struct uart_hsu_port *up)/* We may only get DDCD when HW init and reset */ if (status &UART_MSR_DDCD )uart_handle_dcd_change (&up->port, status &UART_MSR_DCD ); -/* will start/stop_tx accordingly */ +/* Will start/stop_tx accordingly */ if (status &UART_MSR_DCTS )uart_handle_cts_change (&up->port, status &UART_MSR_CTS );
@@ -647,6 +603,7 @@ static irqreturn_t port_irq(int irq, void *dev_id)if (unlikely (!up->running))return IRQ_NONE ; +spin_lock_irqsave (&up->port.lock, flags);if (up->use_dma) { lsr =serial_in (up,UART_LSR ); if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE |
@@ -655,10 +612,10 @@ static irqreturn_t port_irq(int irq, void *dev_id)"Got lsr irq while using DMA, lsr = 0x%2x\n" , lsr);check_modem_status (up); +spin_unlock_irqrestore (&up->port.lock, flags);return IRQ_HANDLED ; } -spin_lock_irqsave (&up->port.lock, flags); iir =serial_in (up,UART_IIR );if (iir &UART_IIR_NO_INT ) {spin_unlock_irqrestore (&up->port.lock, flags);
@@ -666,9 +623,9 @@ static irqreturn_t port_irq(int irq, void *dev_id) } lsr =serial_in (up,UART_LSR ); -if (lsr &UART_LSR_DR )receive_chars (up, &lsr); +check_modem_status (up);/* lsr will be renewed during the receive_chars */ if (lsr &UART_LSR_THRE )
@@ -701,7 +658,6 @@ static inline void dma_chan_irq(struct hsu_dma_chan *chan)/* Tx channel */ if (chan->dirt ==DMA_TO_DEVICE ) { -/* dma for irq should be done */ chan_writel (chan,HSU_CH_CR ,0x0 ); up->dma_tx_on =0 ;hsu_dma_tx (up);
@@ -851,7 +807,6 @@ static int serial_hsu_startup(struct uart_port *port)spin_unlock_irqrestore (&up->port.lock, flags);/* DMA init */ -/* When use DMA, TX/RX's FIFO and IRQ should be disabled */ if (up->use_dma) {struct hsu_dma_buffer *dbuf;struct circ_buf *xmit = &port->state->xmit;
@@ -1090,11 +1045,9 @@ static int serial_hsu_request_port(struct uart_port *port)static void serial_hsu_config_port (struct uart_port *port,int flags) { -#if 0 struct uart_hsu_port *up = container_of(port, struct uart_hsu_port, port); up->port.type =PORT_MFD ; -#endif } static int
@@ -1426,7 +1379,7 @@ static void hsu_global_init(void) uport->port.ops = &serial_hsu_pops; uport->port.line = i; uport->port.flags =UPF_IOREMAP ; -/* make the maxim support rate to 2746800 bps */ +/* set the scalable maxim support rate to 2746800 bps */ uport->port.uartclk =115200 *24 *16 ; uport->running =0 ;
Signature · 1 line
1.7.2
PATCH 64/67 hsu: call PCI pm hooks in suspend/resume function
In reply to Greg KHFrom: Feng Tang <[email protected]>
Also add check for dma controller or the uart ports.
--- drivers/serial/mfd.c | 31 ++++++++++++++++++++++--------- 1 files changed, 22 insertions(+), 9 deletions(-)
drivers/serial/mfd.c +22 -9
@@ -1217,25 +1217,38 @@ static struct uart_driver serial_hsu_reg = {#ifdef CONFIG_PM static int serial_hsu_suspend (struct pci_dev *pdev,pm_message_t state) { +void *priv =pci_get_drvdata (pdev);struct uart_hsu_port *up; - up =pci_get_drvdata (pdev); -if (!up) -return 0 ; - -uart_suspend_port (&serial_hsu_reg, &up->port); +/* Make sure this is not the internal dma controller */ +if (priv && (pdev->device !=0x081E )) { + up = priv; +uart_suspend_port (&serial_hsu_reg, &up->port); + } +pci_save_state (pdev); +pci_set_power_state (pdev,pci_choose_state (pdev, state));return 0 ; }static int serial_hsu_resume (struct pci_dev *pdev) { +void *priv =pci_get_drvdata (pdev);struct uart_hsu_port *up; +int ret; - up =pci_get_drvdata (pdev); -if (!up) -return 0 ; -uart_resume_port (&serial_hsu_reg, &up->port); +pci_set_power_state (pdev,PCI_D0 ); +pci_restore_state (pdev); + + ret =pci_enable_device (pdev); +if (ret) +dev_warn (&pdev->dev, +"HSU: can't re-enable device, try to continue\n" ); + +if (priv && (pdev->device !=0x081E )) { + up = priv; +uart_resume_port (&serial_hsu_reg, &up->port); + }return 0 ; }#else
Signature · 1 line
1.7.2
PATCH 65/67 serial: max3107: Fix gpiolib support
In reply to Greg KHFrom: Alan Cox <[email protected]>
Because of the way gpiolib works we actually need to ifdef this in our header file
--- drivers/serial/max3107.h | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/serial/max3107.h +2 -0
@@ -368,8 +368,10 @@ struct max3107_port {/* SPI device structure */ struct spi_device *spi; +#if defined(CONFIG_GPIOLIB )/* GPIO chip stucture */ struct gpio_chip chip; +#endif /* Workqueue that does all the magic */ struct workqueue_struct *workqueue;
Signature · 1 line
1.7.2
Quoted 3 lines · Greg KH
This contains the big BKL removal of the tty layer, which has been worked on now for a long time by Alan and Arnd.
Umm. No it doesn't.
It contains some crazy "BKL or mutex" choice layer, and the MUTEX choice is disabled unless you have EXPERIMENTAL set (and not the default even if it is set - but quite frankly, that doesn't matter, because asking about it is so fundamentally wrong in the first place that the whole default choice is totally meaningless).
That's just total and utter crud. Having a conditional BKL is _worse_ than just having the BKL. It's crazy. It's stupid, it limits testing, and it's pure idiocy. Whoever thought that was a good idea was not thinking at all.
Either the locking fixes are improvements, or they aren't. If they are improvements, they should be unconditionally enabled, and the old locking should have been removed. And if they aren't, it shouldn't have been merged at all. The timid kind of "let the user choose" choice is STUPID.
Dammit, if the developer doesn't know which one is better, how the hell is a user supposed to know? Answer: he isn't. Making it a config option is fundamentally wrong. Config options that ask questions that users cannot answer are WRONG. Really.
I'm not pulling crazy sh*t like this. The _only_ thing that kconfig option does is basically mean that it doesn't get the kind of coverage in testing that it needs to get, and it confuses everybody. Not to mention having two totally different code-paths where there should be only one.
Do do the highlander thing on that crud. Cut it off at the head, and make sure it never ever comes back to life.
Linus
Quoted 3 lines · Linus Torvalds
Do do the highlander thing on that crud. Cut it off at the head, and make sure it never ever comes back to life.
Arnd and Alan, I'll drop the BKL portion of this patch series and regenerate something to get the other tty patches to Linus.
Care to redo the patch series and just drop the BKL for good?
thanks,
greg k-h
Quoted 7 lines · On Fri, 6 Aug 2010 11:51:47 -0700 Greg KH <[email protected]> wrote:
Quoted 3 lines · Linus Torvalds
Do do the highlander thing on that crud. Cut it off at the head, and make sure it never ever comes back to life.
Arnd and Alan, I'll drop the BKL portion of this patch series and regenerate something to get the other tty patches to Linus.
Wouldn't it make more sense to simply turn it on as Linus suggested ?
Alan
Quoted 5 lines · Alan Cox
Quoted 2 lines · On Fri, 6 Aug 2010 11:51:47 -0700 Greg KH <[email protected]> wrote:
Quoted 1 line · Linus Torvalds
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
Do do the highlander thing on that crud. Cut it off at the head, and make sure it never ever comes back to life.
Arnd and Alan, I'll drop the BKL portion of this patch series and regenerate something to get the other tty patches to Linus.
Wouldn't it make more sense to simply turn it on as Linus suggested ?
That's fine with me, and drop the option entirely? Arnd, any objection to that?
thanks,
greg k-h
Quoted 2 lines · Alan Cox
Wouldn't it make more sense to simply turn it on as Linus suggested ?
I really do want the whole "there can be only one" highlander part.
Go all Christopher Lambert on it, and cut it off at the head so that it cannot resurface even by mistake. IOW, remove the config option entirely, and remove the #ifdef's that switch between the BKL and mutex case.
Otherwise somebody will enable the BKL code, and we'll miss the testing for that case. And getting testing is what the whole merge window is all about.
I also don't want the BKL to show up in grep, even if the config option for it were to be impossible to enable. If we've gotten far enough that we can get rid of the BKL in the tty layer, we really should get rid of it. Not leave it in some zombie limbo state.
Linus
Arnd Bergmann
maintainerQuoted 4 lines · On Friday 06 August 2010 21:38:36 Linus Torvalds wrote:
I also don't want the BKL to show up in grep, even if the config option for it were to be impossible to enable. If we've gotten far enough that we can get rid of the BKL in the tty layer, we really should get rid of it. Not leave it in some zombie limbo state.
Ok, I've sent the replacement patch that does this, and I'm much happier with the outcome.
If you apply this version, the only stronghold left for the BKL will be fs/lockd, everything else that's left is either simple to fix or highly obscure.
Arnd
Quoted 4 lines · Arnd Bergmann
If you apply this version, the only stronghold left for the BKL will be fs/lockd, everything else that's left is either simple to fix or highly obscure.
Didn't we have patches for fs/lockd/ too? Or am I just confused with the fs/locks.c patches?
Linus
Arnd Bergmann
maintainerQuoted 8 lines · On Friday 06 August 2010 22:11:46 Linus Torvalds wrote:
Quoted 4 lines · Arnd Bergmann
If you apply this version, the only stronghold left for the BKL will be fs/lockd, everything else that's left is either simple to fix or highly obscure.
Didn't we have patches for
fs/lockd/too? Or am I just confused with thefs/locks.cpatches?
I had a ten-year old patch from Willy that takes care of fs/locks.c, but we can't apply that without also taking care of fs/lockd.
I first didn't realize this when I sent that patch.
Arnd
Quoted 6 lines · Arnd Bergmann
Quoted 4 lines · On Friday 06 August 2010 21:38:36 Linus Torvalds wrote:
I also don't want the BKL to show up in grep, even if the config option for it were to be impossible to enable. If we've gotten far enough that we can get rid of the BKL in the tty layer, we really should get rid of it. Not leave it in some zombie limbo state.
Quoted 6 lines
Ok, I've sent the replacement patch that does this, and I'm much happier with the outcome.
If you apply this version, the only stronghold left for the BKL will be fs/lockd, everything else that's left is either simple to fix or highly obscure.
Ok, I got that one now, and am building the tree to test here before sending to Linus.
thanks,
greg k-h
Quoted 10 lines · Greg KH
Quoted 9 lines · Arnd Bergmann
Quoted 4 lines · On Friday 06 August 2010 21:38:36 Linus Torvalds wrote:
I also don't want the BKL to show up in grep, even if the config option for it were to be impossible to enable. If we've gotten far enough that we can get rid of the BKL in the tty layer, we really should get rid of it. Not leave it in some zombie limbo state.
Ok, I've sent the replacement patch that does this, and I'm much happier with the outcome.
Quoted 6 lines
Quoted 3 lines
If you apply this version, the only stronghold left for the BKL will be fs/lockd, everything else that's left is either simple to fix or highly obscure.
Ok, I got that one now, and am building the tree to test here before sending to Linus.
I have been looking at the proposed change to the TTY locking here. The conversion of the BKL into a real non-preemptable lock for the TTY layer has had an interesting semantic change on racing open/closes on the same TTY. Prior to the changes we would:
- grab the BLK and tty_mutex
- mark the device TTY_CLOSING
- drop the tty_mutex
- call device shutdown
- prevent the device from being found
- drop the BKL
The use of the BLK to cover the device shutdown has an interesting effect. Where the shutdown processing is simple the lock is maintained and the whole processing is atomic with respect to racing opens and closes, such that an open would never see TTY_CLOSING. For any shutdown processing which resulted in a sleep then the BKL would be implicitly dropped and reaquired allowing any racing opens to continue and triggering an open failure errno=EIO, something POSIX at least hints at as reasonable. As shutdown can include hardware interactions this seems like appropriate behaviour, and cirtinly the git log documents this as expected and desirable semantics.
With the new locking the BTM is held in place of the BKL, which effectivly means throughout open and close processing, which effectively means _all_ TTY open/closes are serialised throughout regardless of the length of the shutdown processing. The EIO appears to be no longer returnable.
Is this change in semantics expected? If not, it is likely something which could be addressed separately after merging, as long as we are aware.
-apw
Arnd Bergmann
maintainerQuoted 9 lines · Andy Whitcroft
With the new locking the BTM is held in place of the BKL, which effectivly means throughout open and close processing, which effectively means all TTY open/closes are serialised throughout regardless of the length of the shutdown processing. The EIO appears to be no longer returnable.
Is this change in semantics expected? If not, it is likely something which could be addressed separately after merging, as long as we are aware.
I audited (or tried to) all code that is able to sleep while holding the BTM. In the cases that looked like they might sleep long, I added explicit tty_unlock()/tty_lock() pairs around the sleeping code.
Code that potentially sleeps but should not do so for an indefinite time (e.g. kmalloc(GFP_KERNEL)), I did not do this and still hold the BKL.
This means the code shifted to holding the BTM more often than it used to hold the BKL, but for cases where we wait on user or hardware interaction, it should still behave as it used to. If you found a place where this is not true, that is probably an oversight and we should add explicit tty_unlock() statements around it.
The problem is that we cannot easily give up the BTM while already holding tty_port->mutex, tty_port->buf_mutex, console_semaphore, tty->termios_mutex or tty->atomic_write_lock, which would give an AB-BA deadlock without the autorelease semantics of the BKL. Similarly, any wait_event or flush_work_queue potentially has the same problem (besides the fact that it can self-deadlock what it waits for tried to take the BTM). Auditing all these was the bulk of the work for the conversion.
I did not specifically audit for the case where tty_open() returns -EIO, but I'd hope that it would be covered by the method I used for the conversion.
Arnd
Quoted 5 lines
With the new locking the BTM is held in place of the BKL, which effectivly means throughout open and close processing, which effectively means _all_ TTY open/closes are serialised throughout regardless of the length of the shutdown processing. The EIO appears to be no longer returnable.
The specific case of waiting for queues to empty could be a slow one and probably wants to addressed nicely. The other causes like memory allocator waits are probably actually better the new way. What exactly is an application supposed to do when it gets a -EIO on open, how does it decide when to try again, when does it retry, how many aps get it right ?
In fact I don't think its unreasonable to treat an open without O_NDELAY that blocks on a close flushing output from buffers as correct - unless there is some specific POSIX reason why we cannot.
I'd venture we'd effective fix/hide/cover over a huge range of extremely obscure and near untestable app failure cases/bugs by doing this.
Alan
Quoted 5 lines · Alan Cox
Quoted 5 lines
With the new locking the BTM is held in place of the BKL, which effectivly means throughout open and close processing, which effectively means _all_ TTY open/closes are serialised throughout regardless of the length of the shutdown processing. The EIO appears to be no longer returnable.
Arnd, thanks for your clear explanation. I see now you have actually addressed the long waits in the main.
Quoted 5 lines
The specific case of waiting for queues to empty could be a slow one and probably wants to addressed nicely. The other causes like memory allocator waits are probably actually better the new way. What exactly is an application supposed to do when it gets a
-EIOon open, how does it decide when to try again, when does it retry, how many aps get it right ?
I know to my cost they break. For me, console_sem is one where we commonly trigger this behaviour (before these changes), so affecting bog standard VTs.
Quoted 6 lines
In fact I don't think its unreasonable to treat an open without
O_NDELAYthat blocks on a close flushing output from buffers as correct - unless there is some specific POSIX reason why we cannot.I'd venture we'd effective fix/hide/cover over a huge range of extremely obscure and near untestable app failure cases/bugs by doing this.
Yes that is very likely. That the longer waits are picked out and release BTM seems a completely sane approach and covers my query completely.
-apw
Arnd Bergmann
maintainerQuoted 10 lines · On Friday 06 August 2010 20:51:47 Greg KH wrote:
Quoted 3 lines · Linus Torvalds
Do do the highlander thing on that crud. Cut it off at the head, and make sure it never ever comes back to life.
Arnd and Alan, I'll drop the BKL portion of this patch series and regenerate something to get the other tty patches to Linus.
Care to redo the patch series and just drop the BKL for good?
I'm sending you a new version of patch 43, everything else should just remain the same AFAICT. I've given it a quick sniff test and it still works the same way as the kernel I've been running for the past months with CONFIG_TTY_MUTEX enabled.
Arnd