Queued TTY Patches
Subsystems (19)
cover Queued TTY Patches
This is the patch stack waiting for 2.6.28 to open. The patches start with various queued bug fixes then move on to tackle the first stage of making the tty layer sane. These patches have been in linux-next.
The main thrust is to begin using krefs and refcounts to kill races and make the locking saner. At this point we still have BKL users but will hopefully change bit by bit.
Alan
---
Adrian Bunk (1):
coldfire: scheduled SERIAL_COLDFIRE removal
Akinobu Mita (1):
ip2: avoid add_timer with pending timer
Alan Cox (43):
ftdi: A few errors are err() that should be debug which causes much spewage
applicom: Fix an unchecked user ioctl range and an error return
hso: net driver using tty without locking
tty: Minor tidyups and document fixes for n_tty
tty: Remove lots of NULL checks
tty: fix up gigaset a bit
tty: some ICANON magic is in the wrong places
tty: simplify ktermios allocation
pty: simplify unix98 allocation
pty: Fix allocation failure double free
pty: Coding style and polish
tty: extract the pty init time special cases
tty: Finish fixing up the init_dev interface to use ERR_PTR
tty: More driver operations
tty: kref the tty driver object
tty: Clean up the tty_init_dev changes further
tty: Remove more special casing and out of place code
tty: shutdown method
vt: remove bogus lock dropping
pty: If the administrator creates a device for a ptmx slave we should not error
tty: Fix abusers of current->sighand->tty
tty: Redo current tty locking
tty: the vhangup syscall is racy
mxser: Switch to kref tty
stallion: Use krefs
tty: kref usage for isicom and moxa
tty: usb-serial krefs
tty: Move tty_write_message out of kernel/printk
tty: Make get_current_tty use a kref
tty: compare the tty winsize
tty: Termios locking - sort out real_tty confusions and lock reads
tty: Add termiox
tty: ipw need reworking
tty: Cris has a nice RS485 ioctl so we should steal it
tty: use krefs to protect driver module counts
tty: Add a kref count
pps: Reserve a line discipline number for PPS
tty: Split tty_port into its own file
tty: split the buffering from tty_io
uml: small cleanups and note bugs to be dealt with by uml authors...
tty: move tioclinux from a special case
8250: Remove NR_IRQ usage
epca: call tty_port_init
Andrew Morton (1):
serial-make-uart_ports-ioport-unsigned-long-fix
David Miller (2):
serial: allow 8250 to be used on sparc
serial: Make uart_port's ioport "unsigned long".
David S. Miller (1):
serial: fix device name reporting when minor space is shared between drivers
Graf Yang (1):
Blackfin Serial Driver: Fix bug - ircp fails on sir over Blackfin UART
Jason Wessel (2):
usb: fix pl2303 initialization
tty: tty_io.c shadows sparse fix
Jiri Slaby (6):
Char: sx, fix io unmapping
Char: cyclades. remove bogus iomap
ip2, init/deinit cleanup
ip2, fix sparse warnings
ip2, cleanup globals
Char: merge ip2main and ip2base
Julia Lawall (2):
drivers/char/hvc_console.c: adjust call to put_tty_driver drivers/serial/crisv10.c: add missing put_tty_driver
Mike Frysinger (3):
Blackfin Serial Driver: move common variables out of serial headers and into the serial driver Blackfin Serial Driver: trim trailing whitespace -- no functional changes Blackfin Serial Driver: use __initdata for data, not __init
Miloslav Trmac (1):
audit: Handle embedded NUL in TTY input auditing
Sonic Zhang (4):
Blackfin Serial Driver: Fix bug - request UART2/3 peripheral mapped interrupts in PIO mode Blackfin Serial Driver: Fix bug - Don't call tx_stop in tx_transfer. Blackfin Serial Driver: Remove useless stop
Blackfin Serial Driver: Fix bug - should suspend/resume/remove all uart ports.
Stephen Rothwell (1):
tty: Fallout from tty-move-canon-specials
Sukadev Bhattiprolu (6):
Simplify devpts_pty_kill
Simplify devpts_pty_new()
Simplify devpts_get_tty()
Add an instance parameter devpts interfaces Move tty lookup/reopen to caller
tty: Move parts of tty_init_dev into new functions
\\\"Will Newton\\\ (1):
8250: remove a few inlines of dubious value
Documentation/feature-removal-schedule.txt | 8 arch/blackfin/kernel/bfin_dma_5xx.c | 13 .../mach-bf527/include/mach/bfin_serial_5xx.h | 6 .../mach-bf533/include/mach/bfin_serial_5xx.h | 4 .../mach-bf537/include/mach/bfin_serial_5xx.h | 6 .../mach-bf548/include/mach/bfin_serial_5xx.h | 6 .../mach-bf561/include/mach/bfin_serial_5xx.h | 4 arch/sparc/include/asm/serial.h | 6 arch/um/drivers/line.c | 2 drivers/bluetooth/hci_ldisc.c | 2 drivers/char/Kconfig | 4 drivers/char/Makefile | 2 drivers/char/amiserial.c | 6 drivers/char/applicom.c | 6 drivers/char/cyclades.c | 21 drivers/char/epca.c | 5 drivers/char/generic_serial.c | 21 drivers/char/hvc_console.c | 4 drivers/char/ip2/Makefile | 2 drivers/char/ip2/i2ellis.c | 32 drivers/char/ip2/i2ellis.h | 2 drivers/char/ip2/ip2base.c | 108 - drivers/char/ip2/ip2main.c | 550 +++--- drivers/char/isicom.c | 61 - drivers/char/istallion.c | 113 + drivers/char/moxa.c | 61 - drivers/char/mxser.c | 193 +- drivers/char/n_hdlc.c | 2 drivers/char/n_r3964.c | 9 drivers/char/n_tty.c | 99 + drivers/char/pcmcia/ipwireless/tty.c | 19 drivers/char/pty.c | 335 +++ drivers/char/stallion.c | 139 + drivers/char/sx.c | 4 drivers/char/tty_audit.c | 2 drivers/char/tty_buffer.c | 511 +++++ drivers/char/tty_io.c | 1380 ++++---------- drivers/char/tty_ioctl.c | 212 ++ drivers/char/tty_port.c | 96 + drivers/char/vt.c | 84 - drivers/char/vt_ioctl.c | 2 drivers/isdn/capi/capi.c | 2 drivers/isdn/gigaset/ser-gigaset.c | 27 drivers/net/usb/hso.c | 46 drivers/net/wan/Kconfig | 2 drivers/s390/char/fs3270.c | 3 drivers/serial/68328serial.c | 11 drivers/serial/8250.c | 123 + drivers/serial/Kconfig | 17 drivers/serial/Makefile | 16 drivers/serial/bfin_5xx.c | 123 + drivers/serial/crisv10.c | 5 drivers/serial/mcfserial.c | 1965 -------------------- drivers/serial/mcfserial.h | 74 - drivers/serial/serial_core.c | 12 drivers/usb/serial/aircable.c | 15 drivers/usb/serial/belkin_sa.c | 3 drivers/usb/serial/console.c | 8 drivers/usb/serial/cyberjack.c | 3 drivers/usb/serial/cypress_m8.c | 5 drivers/usb/serial/digi_acceleport.c | 19 drivers/usb/serial/empeg.c | 8 drivers/usb/serial/ftdi_sio.c | 25 drivers/usb/serial/garmin_gps.c | 3 drivers/usb/serial/generic.c | 3 drivers/usb/serial/io_edgeport.c | 43 drivers/usb/serial/io_ti.c | 26 drivers/usb/serial/ipaq.c | 3 drivers/usb/serial/ipw.c | 3 drivers/usb/serial/ir-usb.c | 3 drivers/usb/serial/iuu_phoenix.c | 3 drivers/usb/serial/keyspan.c | 77 - drivers/usb/serial/keyspan_pda.c | 16 drivers/usb/serial/kl5kusb105.c | 3 drivers/usb/serial/kobil_sct.c | 3 drivers/usb/serial/mct_u232.c | 6 drivers/usb/serial/mos7720.c | 36 drivers/usb/serial/mos7840.c | 7 drivers/usb/serial/navman.c | 3 drivers/usb/serial/omninet.c | 10 drivers/usb/serial/option.c | 18 drivers/usb/serial/oti6858.c | 3 drivers/usb/serial/pl2303.c | 15 drivers/usb/serial/safe_serial.c | 11 drivers/usb/serial/sierra.c | 16 drivers/usb/serial/spcp8x5.c | 3 drivers/usb/serial/ti_usb_3410_5052.c | 44 drivers/usb/serial/usb-serial.c | 24 drivers/usb/serial/visor.c | 18 drivers/usb/serial/whiteheat.c | 8 fs/devpts/inode.c | 66 - fs/dquot.c | 6 fs/open.c | 3 include/asm-x86/ioctls.h | 6 include/linux/devpts_fs.h | 31 include/linux/serial.h | 16 include/linux/serial_core.h | 2 include/linux/termios.h | 15 include/linux/tty.h | 45 include/linux/tty_driver.h | 56 + include/linux/vt_kern.h | 2 kernel/acct.c | 2 kernel/auditsc.c | 9 kernel/fork.c | 5 kernel/printk.c | 16 kernel/sys.c | 4 security/selinux/hooks.c | 3 107 files changed, 2948 insertions(+), 4401 deletions(-) create mode 100644 arch/sparc/include/asm/serial.h delete mode 100644 drivers/char/ip2/ip2base.c create mode 100644 drivers/char/tty_buffer.c create mode 100644 drivers/char/tty_port.c delete mode 100644 drivers/serial/mcfserial.c delete mode 100644 drivers/serial/mcfserial.h
Signature · 1 line
Signature
PATCH 1/76 drivers/serial/crisv10.c: add missing put_tty_driver
From: Julia Lawall <[email protected]>
alloc_tty_driver is called at the beginning of the function containing the lines of code shown in the patch. Thus, put_tty_driver is needed before returning in the error handling code.
The semantic match that finds this problem is as follows:
(http://www.emn.fr/x-info/coccinelle/)
// <smpl>
@nr exists@
local idexpression x;
expression E,f;
position p1,p2,p3;
identifier l;
statement S;
@@
x = alloc_tty_driver@p1(...)
...
if (x == NULL) S
... when != E = x
when != put_tty_driver(x)
when != goto l;(
return \(0\|x\);
|
return@p3 ...;
)
@script:python@
p1 << nr.p1;
p3 << nr.p3;
@@
print "%s: call on line %s not freed or saved before return on line %s" % (p1[0].file,p1[0].line,p3[0].line) // </smpl>
---
drivers/serial/crisv10.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/serial/crisv10.c +2 -0
@@ -4419,6 +4419,7 @@ rs_init(void) rs485_pa_bit)) {printk (KERN_CRIT "ETRAX100LX serial: Could not allocate " "RS485 pin\n" ); +put_tty_driver (driver);return -EBUSY ; }#endif
@@ -4427,6 +4428,7 @@ rs_init(void) rs485_port_g_bit)) {printk (KERN_CRIT "ETRAX100LX serial: Could not allocate " "RS485 pin\n" ); +put_tty_driver (driver);return -EBUSY ; }#endif
PATCH 2/76 drivers/char/hvc_console.c: adjust call to put_tty_driver
In reply to Alan CoxFrom: Julia Lawall <[email protected]>
The call to put_tty_driver is out of place and is applied to the wrong argument.
The function enclosing the patched code calls alloc_tty_driver and stores the result in drv. Subsequently, there are two occurrences of error handling code, one making a goto to put_tty and one making a goto to stop_thread. At the point of the first one the assignment hvc_driver = drv has not yet been executed, and from inspecting the rest of the file it seems that hvc_driver would be NULL. Thus the current call to put_tty_driver is useless, and one applied to drv is needed. The goto stop_thread is in the error handling code for a call to tty_register_driver, but the error cases in tty_register_driver do not free its argument, so it should be done here. Thus, I have moved the put_tty label after the stop_thread label, so that put_tty_driver is called in both cases.
The semantic match that finds this problem is as follows:
(http://www.emn.fr/x-info/coccinelle/)
// <smpl>
@r exists@
local idexpression x;
expression E,f;
position p1,p2,p3;
identifier l;
statement S;
@@
x = alloc_tty_driver@p1(...)
...
if (x == NULL) S
... when != E = x
when != put_tty_driver(x)
goto@p2 l;
... when != E = x
when != f(...,x,...)
when any(
return \(0\|x\);
|
return@p3 ...;
)
@script:python@
p1 << r.p1;
p2 << r.p2;
p3 << r.p3;
@@
print "%s: call on line %s not freed or saved before return on line %s via line %s" % (p1[0].file,p1[0].line,p3[0].line,p2[0].line) // </smpl>
---
drivers/char/hvc_console.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/char/hvc_console.c +2 -2
@@ -819,11 +819,11 @@ static int hvc_init(void) hvc_driver = drv;return 0 ; -put_tty: -put_tty_driver (hvc_driver); stop_thread:kthread_stop (hvc_task); hvc_task =NULL ; +put_tty: +put_tty_driver (drv); out:return err; }
PATCH 3/76 coldfire: scheduled SERIAL_COLDFIRE removal
In reply to Alan CoxFrom: Adrian Bunk <[email protected]>
This patch contains the scheduled removal of the obsolete SERIAL_COLDFIRE driver.
---
Documentation/feature-removal-schedule.txt | 8 drivers/serial/Kconfig | 16 drivers/serial/Makefile | 1 drivers/serial/mcfserial.c | 1965 ---------------------------- drivers/serial/mcfserial.h | 74 - 5 files changed, 2 insertions(+), 2062 deletions(-) delete mode 100644 drivers/serial/mcfserial.c delete mode 100644 drivers/serial/mcfserial.h
Documentation/feature-removal-schedule.txt +0 -8
@@ -266,14 +266,6 @@ Who: Glauber Costa <[email protected]> --------------------------- -What: old style serial driver for ColdFire (CONFIG_SERIAL_COLDFIRE) -When: 2.6.28 -Why: This driver still uses the old interface and has been replaced - by CONFIG_SERIAL_MCF. -Who: Sebastian Siewior <[email protected]> - ---------------------------- - What: /sys/o2cb symlink When: January 2010 Why: /sys/fs/o2cb is the proper location for this information - /sys/o2cb
drivers/serial/Kconfig +2 -14
@@ -994,24 +994,12 @@ config SERIAL_68328_RTS_CTS bool "Support RTS/CTS on 68328 serial port" depends on SERIAL_68328 -config SERIAL_COLDFIRE - bool "ColdFire serial support (DEPRECATED)" - depends on COLDFIRE - help - This driver supports the built-in serial ports of the Motorola ColdFire - family of CPUs. - This driver is deprecated because it supports only the old interface - for serial drivers and features like magic keys are not working. - Please switch to the new style driver because this driver will be - removed soon. - config SERIAL_MCF - bool "Coldfire serial support (new style driver)" + bool "Coldfire serial support" depends on COLDFIRE select SERIAL_CORE help - This new serial driver supports the Freescale Coldfire serial ports - using the new serial driver subsystem. + This serial driver supports the Freescale Coldfire serial ports. config SERIAL_MCF_BAUDRATE int "Default baudrate for Coldfire serial ports"
drivers/serial/Makefile +0 -1
@@ -40,7 +40,6 @@ obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o obj-$(CONFIG_SERIAL_MUX) += mux.o obj-$(CONFIG_SERIAL_68328) += 68328serial.o obj-$(CONFIG_SERIAL_68360) += 68360serial.o -obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o obj-$(CONFIG_SERIAL_MCF) += mcf.o obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o
drivers/serial/mcfserial.c deleted +0 -1965
1,965 lines not on this page · raw message
drivers/serial/mcfserial.h deleted +0 -74
74 lines not on this page · raw message
PATCH 4/76 epca: call tty_port_init
In reply to Alan Cox---
drivers/char/epca.c | 5 +---- 1 files changed, 1 insertions(+), 4 deletions(-)
drivers/char/epca.c +1 -4
@@ -1376,6 +1376,7 @@ static void post_fep_init(unsigned int crd)unsigned long flags;u16 tseg, rseg; +tty_port_init (&ch->port); ch->brdchan = bc; ch->mailbox = gd;INIT_WORK (&ch->tqueue, do_softint);
@@ -1510,10 +1511,6 @@ static void post_fep_init(unsigned int crd) ch->fepstopca =0 ; ch->close_delay =50 ; - ch->port.count =0 ; - ch->port.blocked_open =0 ; -init_waitqueue_head (&ch->port.open_wait); -init_waitqueue_head (&ch->port.close_wait);spin_unlock_irqrestore (&epca_lock, flags); }
PATCH 5/76 8250: Remove NR_IRQ usage
In reply to Alan CoxThere are plans afoot to make the IRQ ranges dynamic. In that situation we don't want drivers having their own huge arrays for per IRQ data so use a hash
---
drivers/serial/68328serial.c | 11 +----- drivers/serial/8250.c | 74 +++++++++++++++++++++++++++++++++--------- 2 files changed, 60 insertions(+), 25 deletions(-)
drivers/serial/68328serial.c +2 -9
@@ -66,7 +66,6 @@#endif static struct m68k_serial m68k_soft[NR_PORTS ]; -struct m68k_serial *IRQ_ports[NR_IRQS ];static unsigned int uart_irqs[NR_PORTS ] =UART_IRQ_DEFNS ;
@@ -375,15 +374,11 @@ clear_and_return:*/ irqreturn_t rs_interrupt (int irq,void *dev_id) { -struct m68k_serial * info; +struct m68k_serial * info = dev_id;m68328_uart *uart;unsigned short rx;unsigned short tx; - info = IRQ_ports[irq]; -if (!info) -return IRQ_NONE ; - uart = &uart_addr[info->line]; rx = uart->urx.w;
@@ -1383,8 +1378,6 @@ rs68328_init(void) info->port, info->irq);printk (" is a builtin MC68328 UART\n" ); - IRQ_ports[info->irq] = info;/* waste of space */ -#ifdef CONFIG_M68VZ328 if (i >0 )PJSEL &=0xCF ;/* PSW enable second port output */
@@ -1393,7 +1386,7 @@ rs68328_init(void)if (request_irq (uart_irqs[i], rs_interrupt,IRQF_DISABLED , -"M68328_UART" ,NULL )) +"M68328_UART" , info))panic ("Unable to attach 68328 serial interrupt\n" ); }local_irq_restore (flags);
drivers/serial/8250.c +58 -16
139 lines not on this page · raw message
PATCH 6/76 Blackfin Serial Driver: use __initdata for data, not __init
In reply to Alan CoxFrom: Mike Frysinger <[email protected]>
---
drivers/serial/bfin_5xx.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/serial/bfin_5xx.c +1 -1
@@ -1056,7 +1056,7 @@ static __init void early_serial_write(struct console *con, const char *s, } } -static struct __init console bfin_early_serial_console = { +static struct __initdata console bfin_early_serial_console = { .name ="early_BFuart" , .write = early_serial_write, .device = uart_console_device,
PATCH 7/76 Blackfin Serial Driver: Fix bug - should suspend/resume/remove all uart ports.
In reply to Alan CoxFrom: Sonic Zhang <[email protected]>
---
drivers/serial/bfin_5xx.c | 39 ++++++++++++++++++++++----------------- 1 files changed, 22 insertions(+), 17 deletions(-)
drivers/serial/bfin_5xx.c +22 -17
@@ -1100,20 +1100,26 @@ static struct uart_driver bfin_serial_reg = {static int bfin_serial_suspend (struct platform_device *dev,pm_message_t state) { -struct bfin_serial_port *uart =platform_get_drvdata (dev); +int i; -if (uart) -uart_suspend_port (&bfin_serial_reg, &uart->port); +for (i =0 ; i < nr_ports; i++) { +if (bfin_serial_ports[i].port.dev != &dev->dev) +continue ; +uart_suspend_port (&bfin_serial_reg, &bfin_serial_ports[i].port); + }return 0 ; }static int bfin_serial_resume (struct platform_device *dev) { -struct bfin_serial_port *uart =platform_get_drvdata (dev); +int i; -if (uart) -uart_resume_port (&bfin_serial_reg, &uart->port); +for (i =0 ; i < nr_ports; i++) { +if (bfin_serial_ports[i].port.dev != &dev->dev) +continue ; +uart_resume_port (&bfin_serial_reg, &bfin_serial_ports[i].port); + }return 0 ; }
@@ -1133,27 +1139,26 @@ static int bfin_serial_probe(struct platform_device *dev)continue ; bfin_serial_ports[i].port.dev = &dev->dev;uart_add_one_port (&bfin_serial_reg, &bfin_serial_ports[i].port); -platform_set_drvdata (dev, &bfin_serial_ports[i]); } }return 0 ; } -static int bfin_serial_remove (struct platform_device *pdev) +static int bfin_serial_remove (struct platform_device *dev) { -struct bfin_serial_port *uart =platform_get_drvdata (pdev); - +int i; +for (i =0 ; i < nr_ports; i++) { +if (bfin_serial_ports[i].port.dev != &dev->dev) +continue ; +uart_remove_one_port (&bfin_serial_reg, &bfin_serial_ports[i].port); + bfin_serial_ports[i].port.dev =NULL ;#ifdef CONFIG_SERIAL_BFIN_CTSRTS -gpio_free (uart->cts_pin); -gpio_free (uart->rts_pin); +gpio_free (bfin_serial_ports[i].cts_pin); +gpio_free (bfin_serial_ports[i].rts_pin);#endif - -platform_set_drvdata (pdev,NULL ); - -if (uart) -uart_remove_one_port (&bfin_serial_reg, &uart->port); + }return 0 ; }
PATCH 8/76 Blackfin Serial Driver: trim trailing whitespace -- no functional changes
In reply to Alan CoxFrom: Mike Frysinger <[email protected]>
---
drivers/serial/bfin_5xx.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
drivers/serial/bfin_5xx.c +4 -4
@@ -1,7 +1,7 @@/* * Blackfin On-Chip Serial Driver * -* Copyright 2006-2007 Analog Devices Inc. +* Copyright 2006-2008 Analog Devices Inc. * * Enter bugs at http://blackfin.uclinux.org/ *
@@ -126,13 +126,13 @@ static int kgdb_entry_state;void kgdb_put_debug_char (int chr) {struct bfin_serial_port *uart; - +if (CONFIG_KGDB_UART_PORT <0 ||CONFIG_KGDB_UART_PORT >=BFIN_UART_NR_PORTS ) uart = &bfin_serial_ports[0 ];else uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT ]; - +while (!(UART_GET_LSR (uart) &THRE )) {SSYNC (); }
@@ -152,7 +152,7 @@ int kgdb_get_debug_char(void) uart = &bfin_serial_ports[0 ]; else uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT ]; - +while (!(UART_GET_LSR (uart) &DR )) {SSYNC (); }
PATCH 9/76 Blackfin Serial Driver: move common variables out of serial headers and into the serial driver
In reply to Alan CoxFrom: Mike Frysinger <[email protected]>
move common variables out of serial headers and into the serial driver and rename "nr_ports" to "nr_active_ports" so as to easily differentiat between BFIN_UART_NR_PORTS (the # of available) and nr_ports (the # of enabled)
---
.../mach-bf527/include/mach/bfin_serial_5xx.h | 3 --- .../mach-bf533/include/mach/bfin_serial_5xx.h | 2 -- .../mach-bf537/include/mach/bfin_serial_5xx.h | 3 --- .../mach-bf548/include/mach/bfin_serial_5xx.h | 3 --- .../mach-bf561/include/mach/bfin_serial_5xx.h | 2 -- drivers/serial/bfin_5xx.c | 17 ++++++++++------- 6 files changed, 10 insertions(+), 20 deletions(-)
arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h +0 -3
@@ -119,7 +119,6 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)bfin_write16 (uart->port.membase +OFFSET_LSR ,-1 ); } -struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS ];struct bfin_serial_res {unsigned long uart_base_addr;int uart_irq;
@@ -164,8 +163,6 @@ struct bfin_serial_res bfin_serial_resource[] = {#endif }; -int nr_ports =ARRAY_SIZE (bfin_serial_resource); -#define DRIVER_NAME "bfin-uart"static void bfin_serial_hw_init (struct bfin_serial_port *uart)
arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h +0 -2
@@ -111,7 +111,6 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)bfin_write16 (uart->port.membase +OFFSET_LSR ,-1 ); } -struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS ];struct bfin_serial_res {unsigned long uart_base_addr;int uart_irq;
@@ -142,7 +141,6 @@ struct bfin_serial_res bfin_serial_resource[] = {#define DRIVER_NAME "bfin-uart" -int nr_ports =BFIN_UART_NR_PORTS ;static void bfin_serial_hw_init (struct bfin_serial_port *uart) {
arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h +0 -3
@@ -119,7 +119,6 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)bfin_write16 (uart->port.membase +OFFSET_LSR ,-1 ); } -struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS ];struct bfin_serial_res {unsigned long uart_base_addr;int uart_irq;
@@ -164,8 +163,6 @@ struct bfin_serial_res bfin_serial_resource[] = {#endif }; -int nr_ports =ARRAY_SIZE (bfin_serial_resource); -#define DRIVER_NAME "bfin-uart"static void bfin_serial_hw_init (struct bfin_serial_port *uart)
arch/blackfin/mach-bf548/include/mach/bfin_serial_5xx.h +0 -3
@@ -105,7 +105,6 @@ struct bfin_serial_port {#endif }; -struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS ];struct bfin_serial_res {unsigned long uart_base_addr;int uart_irq;
@@ -170,8 +169,6 @@ struct bfin_serial_res bfin_serial_resource[] = {#endif }; -int nr_ports =ARRAY_SIZE (bfin_serial_resource); -#define DRIVER_NAME "bfin-uart"static void bfin_serial_hw_init (struct bfin_serial_port *uart)
arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h +0 -2
@@ -111,7 +111,6 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)bfin_write16 (uart->port.membase +OFFSET_LSR ,-1 ); } -struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS ];struct bfin_serial_res {unsigned long uart_base_addr;int uart_irq;
@@ -142,7 +141,6 @@ struct bfin_serial_res bfin_serial_resource[] = {#define DRIVER_NAME "bfin-uart" -int nr_ports =BFIN_UART_NR_PORTS ;static void bfin_serial_hw_init (struct bfin_serial_port *uart) {
drivers/serial/bfin_5xx.c +10 -7
@@ -42,6 +42,9 @@#define BFIN_SERIAL_MAJOR 204#define BFIN_SERIAL_MINOR 64 +static struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS ]; +static int nr_active_ports =ARRAY_SIZE (bfin_serial_resource); +/* * Setup for console. Argument comes from the menuconfig */
@@ -859,7 +862,7 @@ static void __init bfin_serial_init_ports(void)return ; first =0 ; -for (i =0 ; i < nr_ports; i++) { +for (i =0 ; i < nr_active_ports; i++) { bfin_serial_ports[i].port.uartclk =get_sclk (); bfin_serial_ports[i].port.ops = &bfin_serial_pops; bfin_serial_ports[i].port.line = i;
@@ -961,7 +964,7 @@ bfin_serial_console_setup(struct console *co, char *options)* if so, search for the first available port that does have * console support. */ -if (co->index ==-1 || co->index >= nr_ports) +if (co->index ==-1 || co->index >= nr_active_ports) co->index =0 ; uart = &bfin_serial_ports[co->index];
@@ -1072,7 +1075,7 @@ struct console __init *bfin_earlyserial_init(unsigned int port,struct bfin_serial_port *uart;struct ktermios t; -if (port ==-1 || port >= nr_ports) +if (port ==-1 || port >= nr_active_ports) port =0 ;bfin_serial_init_ports (); bfin_early_serial_console.index = port;
@@ -1102,7 +1105,7 @@ static int bfin_serial_suspend(struct platform_device *dev, pm_message_t state) {int i; -for (i =0 ; i < nr_ports; i++) { +for (i =0 ; i < nr_active_ports; i++) {if (bfin_serial_ports[i].port.dev != &dev->dev)continue ;uart_suspend_port (&bfin_serial_reg, &bfin_serial_ports[i].port);
@@ -1115,7 +1118,7 @@ static int bfin_serial_resume(struct platform_device *dev) {int i; -for (i =0 ; i < nr_ports; i++) { +for (i =0 ; i < nr_active_ports; i++) {if (bfin_serial_ports[i].port.dev != &dev->dev)continue ;uart_resume_port (&bfin_serial_reg, &bfin_serial_ports[i].port);
@@ -1134,7 +1137,7 @@ static int bfin_serial_probe(struct platform_device *dev)break ;if (i < dev->num_resources) { -for (i =0 ; i < nr_ports; i++, res++) { +for (i =0 ; i < nr_active_ports; i++, res++) {if (bfin_serial_ports[i].port.mapbase != res->start)continue ; bfin_serial_ports[i].port.dev = &dev->dev;
@@ -1149,7 +1152,7 @@ static int bfin_serial_remove(struct platform_device *dev) {int i; -for (i =0 ; i < nr_ports; i++) { +for (i =0 ; i < nr_active_ports; i++) {if (bfin_serial_ports[i].port.dev != &dev->dev)continue ;uart_remove_one_port (&bfin_serial_reg, &bfin_serial_ports[i].port);
PATCH 10/76 Blackfin Serial Driver: Remove useless stop
In reply to Alan CoxFrom: Sonic Zhang <[email protected]>
---
drivers/serial/bfin_5xx.c | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-)
drivers/serial/bfin_5xx.c +0 -3
@@ -320,9 +320,6 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart)if (uart_circ_chars_pending (xmit) <WAKEUP_CHARS )uart_write_wakeup (&uart->port); - -if (uart_circ_empty (xmit)) -bfin_serial_stop_tx (&uart->port); }static irqreturn_t bfin_serial_rx_int (int irq,void *dev_id)
PATCH 11/76 Blackfin Serial Driver: Fix bug - Don't call tx_stop in tx_transfer.
In reply to Alan CoxFrom: Sonic Zhang <[email protected]>
Disable irq and return immediately.
---
drivers/serial/bfin_5xx.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-)
drivers/serial/bfin_5xx.c +5 -1
@@ -301,7 +301,11 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart)bfin_serial_mctrl_check (uart);if (uart_circ_empty (xmit) ||uart_tx_stopped (&uart->port)) { -bfin_serial_stop_tx (&uart->port); +#ifdef CONFIG_BF54x +/* Clear TFI bit */ +UART_PUT_LSR (uart,TFI ); +#endif +UART_CLEAR_IER (uart,ETBEI );return ; }
PATCH 12/76 Blackfin Serial Driver: Fix bug - ircp fails on sir over Blackfin UART
In reply to Alan CoxFrom: Graf Yang <[email protected]>
We now use the sir_dev/irtty_sir/uart/bfin_serial drivers framework to monitor the TX status.
---
.../mach-bf527/include/mach/bfin_serial_5xx.h | 3 +++ .../mach-bf533/include/mach/bfin_serial_5xx.h | 2 ++ .../mach-bf537/include/mach/bfin_serial_5xx.h | 3 +++ .../mach-bf548/include/mach/bfin_serial_5xx.h | 3 +++ .../mach-bf561/include/mach/bfin_serial_5xx.h | 2 ++ drivers/serial/bfin_5xx.c | 4 ++++ 6 files changed, 17 insertions(+), 0 deletions(-)
arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h +3 -0
@@ -78,6 +78,9 @@# define CONFIG_UART1_RTS_PIN -1# endif #endif + +#define BFIN_UART_TX_FIFO_SIZE 2 +/* * The pin configuration is different from schematic */
arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h +2 -0
@@ -69,6 +69,8 @@# endif #endif +#define BFIN_UART_TX_FIFO_SIZE 2 +struct bfin_serial_port {struct uart_port port;unsigned int old_status;
arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h +3 -0
@@ -78,6 +78,9 @@# define CONFIG_UART1_RTS_PIN -1# endif #endif + +#define BFIN_UART_TX_FIFO_SIZE 2 +/* * The pin configuration is different from schematic */
arch/blackfin/mach-bf548/include/mach/bfin_serial_5xx.h +3 -0
@@ -82,6 +82,9 @@# define CONFIG_UART1_RTS_PIN -1# endif #endif + +#define BFIN_UART_TX_FIFO_SIZE 2 +/* * The pin configuration is different from schematic */
arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h +2 -0
@@ -69,6 +69,8 @@# endif #endif +#define BFIN_UART_TX_FIFO_SIZE 2 +struct bfin_serial_port {struct uart_port port;unsigned int old_status;
drivers/serial/bfin_5xx.c +4 -0
@@ -761,6 +761,9 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios, val |=UCEN ;UART_PUT_GCTL (uart, val); +/* Port speed changed, update the per-port timeout. */ +uart_update_timeout (port, termios->c_cflag, baud); +spin_unlock_irqrestore (&uart->port.lock, flags); }
@@ -865,6 +868,7 @@ static void __init bfin_serial_init_ports(void)for (i =0 ; i < nr_active_ports; i++) { bfin_serial_ports[i].port.uartclk =get_sclk (); + bfin_serial_ports[i].port.fifosize =BFIN_UART_TX_FIFO_SIZE ; bfin_serial_ports[i].port.ops = &bfin_serial_pops; bfin_serial_ports[i].port.line = i; bfin_serial_ports[i].port.iotype =UPIO_MEM ;
PATCH 13/76 Blackfin Serial Driver: Fix bug - request UART2/3 peripheral mapped interrupts in PIO mode
In reply to Alan CoxFrom: Sonic Zhang <[email protected]>
---
arch/blackfin/kernel/bfin_dma_5xx.c | 13 ++++----- drivers/serial/bfin_5xx.c | 50 +++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 7 deletions(-)
arch/blackfin/kernel/bfin_dma_5xx.c +6 -7
@@ -117,15 +117,14 @@ int request_dma(unsigned int channel, char *device_id)#ifdef CONFIG_BF54xif (channel >=CH_UART2_RX && channel <=CH_UART3_TX ) { -if (strncmp (device_id,"BFIN_UART" ,9 ) ==0 ) { - dma_ch[channel].regs->peripheral_map &=0x0FFF ; - dma_ch[channel].regs->peripheral_map |= +unsigned int per_map; + per_map = dma_ch[channel].regs->peripheral_map &0xFFF ; +if (strncmp (device_id,"BFIN_UART" ,9 ) ==0 ) + dma_ch[channel].regs->peripheral_map = per_map | ((channel -CH_UART2_RX +0xC )<<12 ); - }else { - dma_ch[channel].regs->peripheral_map &=0x0FFF ; - dma_ch[channel].regs->peripheral_map |= +else + dma_ch[channel].regs->peripheral_map = per_map | ((channel -CH_UART2_RX +0x6 )<<12 ); - } }#endif
drivers/serial/bfin_5xx.c +50 -0
62 lines not on this page · raw message
PATCH 14/76 tty: move tioclinux from a special case
In reply to Alan CoxRight now we have ifdefs and hooks in the core ioctl handler for TIOCLINUX and then test if its a console. This is brain dead. Instead call the tioclinux helper from the relevant driver ioctl methods.
---
drivers/char/tty_io.c | 4 ---- drivers/char/vt.c | 2 -- drivers/char/vt_ioctl.c | 2 ++ 3 files changed, 2 insertions(+), 6 deletions(-)
drivers/char/tty_io.c +0 -4
@@ -3026,10 +3026,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)return put_user (tty->ldisc.ops->num, (int __user *)p);case TIOCSETD :return tiocsetd (tty, p); -#ifdef CONFIG_VT -case TIOCLINUX : -return tioclinux (tty, arg); -#endif /* * Break handling */
drivers/char/vt.c +0 -2
@@ -2583,8 +2583,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)int lines;int ret; -if (tty->driver->type !=TTY_DRIVER_TYPE_CONSOLE ) -return -EINVAL ;if (current->signal->tty != tty && !capable (CAP_SYS_ADMIN ))return -EPERM ;if (get_user (type, p))
drivers/char/vt_ioctl.c +2 -0
@@ -395,6 +395,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, kbd = kbd_table + console;switch (cmd) { +case TIOCLINUX : +return tioclinux (tty, arg);case KIOCSOUND :if (!perm) goto eperm;
PATCH 15/76 uml: small cleanups and note bugs to be dealt with by uml authors...
In reply to Alan Cox---
arch/um/drivers/line.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
arch/um/drivers/line.c +2 -0
@@ -275,6 +275,8 @@ int line_ioctl(struct tty_struct *tty, struct file * file,case TIOCGLTC :case TIOCSLTC :#endif +/* Note: these are out of date as we now have TCGETS2 etc but this +whole lot should probably go away */ case TCGETS :case TCSETSF :case TCSETSW :
PATCH 16/76 Char: merge ip2main and ip2base
In reply to Alan CoxFrom: Jiri Slaby <[email protected]>
It's pretty useless to have one setup() function separated along with module_init() which only calls a function from ip2main anyway. Get rid of ip2base.
Remove also checks of always-true now.
---
drivers/char/ip2/Makefile | 2 - drivers/char/ip2/ip2base.c | 108 -------------------------------------------- drivers/char/ip2/ip2main.c | 92 +++++++++++++++++++++++++++++++------ 3 files changed, 77 insertions(+), 125 deletions(-) delete mode 100644 drivers/char/ip2/ip2base.c
drivers/char/ip2/Makefile +1 -1
@@ -4,5 +4,5 @@ obj-$(CONFIG_COMPUTONE) += ip2.o -ip2-objs := ip2base.o ip2main.o +ip2-objs := ip2main.o
drivers/char/ip2/ip2base.c deleted +0 -108
108 lines not on this page · raw message
drivers/char/ip2/ip2main.c +76 -16
140 lines not on this page · raw message
PATCH 17/76 ip2, cleanup globals
In reply to Alan CoxFrom: Jiri Slaby <[email protected]>
- do not init .bss zeroed data to zero again (by memset or explicit assignment)
- use char [] instead of char * for string constants
---
drivers/char/ip2/ip2main.c | 18 +++++++----------- 1 files changed, 7 insertions(+), 11 deletions(-)
drivers/char/ip2/ip2main.c +7 -11
@@ -150,12 +150,12 @@ static int ip2_read_proc(char *, char **, off_t, int, int *, void * );/*************/ /* String constants to identify ourselves */ -static char *pcName ="Computone IntelliPort Plus multiport driver" ; -static char *pcVersion ="1.2.14" ; +static const char pcName[] ="Computone IntelliPort Plus multiport driver" ; +static const char pcVersion[] ="1.2.14" ;/* String constants for port names */ -static char *pcDriver_name ="ip2" ; -static char *pcIpl ="ip2ipl" ; +static const char pcDriver_name[] ="ip2" ; +static const char pcIpl[] ="ip2ipl" ;/***********************/ /* Function Prototypes */
@@ -237,8 +237,8 @@ static const struct file_operations ip2_ipl = { .open = ip2_ipl_open, }; -static unsigned long irq_counter =0 ; -static unsigned long bh_counter =0 ; +static unsigned long irq_counter; +static unsigned long bh_counter;// Use immediate queue to service interrupts #define USE_IQI
@@ -286,7 +286,7 @@ MODULE_AUTHOR("Doug McNash");MODULE_DESCRIPTION ("Computone IntelliPort Plus Driver" );MODULE_LICENSE ("GPL" ); -static int poll_only =0 ; +static int poll_only;static int Eisa_irq;static int Eisa_slot;
@@ -615,10 +615,6 @@ static int ip2_loadmain(void)/* Initialise the iiEllis subsystem. */ iiEllisInit (); -/* Initialize arrays. */ -memset ( i2BoardPtrTable,0 ,sizeof i2BoardPtrTable ); -memset ( DevTable,0 ,sizeof DevTable ); -/* Initialise all the boards we can find (up to the maximum). */ for ( i =0 ; i <IP2_MAX_BOARDS ; ++i ) {switch ( ip2config.addr[i] ) {
PATCH 18/76 ip2, fix sparse warnings
In reply to Alan CoxFrom: Jiri Slaby <[email protected]>
---
drivers/char/ip2/ip2main.c | 14 +++++--------- 1 files changed, 5 insertions(+), 9 deletions(-)
drivers/char/ip2/ip2main.c +5 -9
@@ -375,9 +375,7 @@ have_requested_irq( char irq )/* handle subsequent installations of the driver. All memory allocated by the */ /* driver should be returned since it may be unloaded from memory. */ /******************************************************************************/ -#ifdef MODULE -void __exit -ip2_cleanup_module (void ) +static void __exit ip2_cleanup_module(void) {int err;int i;
@@ -431,7 +429,8 @@ ip2_cleanup_module(void) ip2config.pci_dev[i] = NULL; }#endif -if ((pB = i2BoardPtrTable[i]) !=0 ) { + pB = i2BoardPtrTable[i]; +if (pB !=NULL ) {kfree ( pB ); i2BoardPtrTable[i] =NULL ; }
@@ -448,7 +447,6 @@ ip2_cleanup_module(void)#endif }module_exit (ip2_cleanup_module); -#endif /* MODULE */ static const struct tty_operations ip2_ops = { .open = ip2_open,
@@ -1255,9 +1253,8 @@ ip2_polled_interrupt(void) {int i;i2eBordStrPtr pB; -const int irq =0 ; -ip2trace (ITRC_NO_PORT ,ITRC_INTR ,99 ,1 , irq ); +ip2trace (ITRC_NO_PORT ,ITRC_INTR ,99 ,1 ,0 );/* Service just the boards on the list using this irq */ for ( i =0 ; i < i2nBoards; ++i ) {
@@ -1266,9 +1263,8 @@ ip2_polled_interrupt(void)// Only process those boards which match our IRQ. // IRQ = 0 for polled boards, we won't poll "IRQ" boards -if ( pB && (pB->i2eUsingIrq == irq) ) { +if (pB && pB->i2eUsingIrq ==0 )ip2_irq_work (pB); - } } ++irq_counter;
PATCH 19/76 ip2, init/deinit cleanup
In reply to Alan CoxFrom: Jiri Slaby <[email protected]>
Cleanup of module_init/exit:
- mostly whitespace
- remove empty functions
- replace c++ comments
- remove useless prints (module loaded, unloaded)
- mark the calls as __exit and __init
- use break; and return; to save some indent levels after it
- note resource leakage
It's still mess, but now it's readable.
---
drivers/char/ip2/i2ellis.c | 32 --- drivers/char/ip2/i2ellis.h | 2 drivers/char/ip2/ip2main.c | 415 +++++++++++++++++++++----------------------- 3 files changed, 198 insertions(+), 251 deletions(-)
drivers/char/ip2/i2ellis.c +0 -32
@@ -69,38 +69,6 @@ static DEFINE_RWLOCK(Dl_spinlock);//======================================================= //****************************************************************************** -// Function: iiEllisInit() -// Parameters: None -// -// Returns: Nothing -// -// Description: -// -// This routine performs any required initialization of the iiEllis subsystem. -// -//****************************************************************************** -static void -iiEllisInit (void ) -{ -} - -//****************************************************************************** -// Function: iiEllisCleanup() -// Parameters: None -// -// Returns: Nothing -// -// Description: -// -// This routine performs any required cleanup of the iiEllis subsystem. -// -//****************************************************************************** -static void -iiEllisCleanup (void ) -{ -} - -//****************************************************************************** // Function: iiSetAddress(pB, address, delay) // Parameters: pB - pointer to the board structure // address - the purported I/O address of the board
drivers/char/ip2/i2ellis.h +0 -2
@@ -511,7 +511,6 @@ typedef void (*delayFunc_t)(unsigned int);// // Initialization of a board & structure is in four (five!) parts: // -// 0) iiEllisInit() - Initialize iiEllis subsystem. // 1) iiSetAddress() - Define the board address & delay function for a board. // 2) iiReset() - Reset the board (provided it exists) // -- Note you may do this to several boards --
@@ -523,7 +522,6 @@ typedef void (*delayFunc_t)(unsigned int);// loadware. To change loadware, you must begin again with step 2, resetting // the board again (step 1 not needed). -static void iiEllisInit (void );static int iiSetAddress (i2eBordStrPtr ,int ,delayFunc_t );static int iiReset (i2eBordStrPtr );static int iiResetDelay (i2eBordStrPtr );
drivers/char/ip2/ip2main.c +198 -217
585 lines not on this page · raw message
PATCH 20/76 ip2: avoid add_timer with pending timer
In reply to Alan CoxFrom: Akinobu Mita <[email protected]>
add_timer() is not suppose to be called when the timer is pending. ip2 driver attempts to avoid that condition by setting and resetting a flag (TimerOn) in timer function. But there is some gap between add_timer() and setting TimerOn.
This patch fix this problem by using mod_timer() and remove TimerOn which has been unnecessary by this change.
---
drivers/char/ip2/ip2main.c | 19 ++++--------------- 1 files changed, 4 insertions(+), 15 deletions(-)
drivers/char/ip2/ip2main.c +4 -15
@@ -249,7 +249,6 @@ static unsigned long bh_counter;*/ #define POLL_TIMEOUT (jiffies + 1) static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0); -static char TimerOn;#ifdef IP2DEBUG_TRACE /* Trace (debug) buffer data */
@@ -374,11 +373,7 @@ static void __exit ip2_cleanup_module(void)int err;int i; -/* Stop poll timer if we had one. */ -if (TimerOn) { -del_timer (&PollTimer); - TimerOn =0 ; - } +del_timer_sync (&PollTimer);/* Reset the boards we have. */ for (i =0 ; i <IP2_MAX_BOARDS ; i++)
@@ -774,10 +769,8 @@ static int __init ip2_loadmain(void) }if (ip2config.irq[i] ==CIR_POLL ) { retry: -if (!TimerOn) { - PollTimer.expires =POLL_TIMEOUT ; -add_timer (&PollTimer); - TimerOn =1 ; +if (!timer_pending (&PollTimer)) { +mod_timer (&PollTimer,POLL_TIMEOUT );printk (KERN_INFO "IP2: polling\n" ); } }else {
@@ -1283,16 +1276,12 @@ ip2_poll(unsigned long arg) {ip2trace (ITRC_NO_PORT ,ITRC_INTR ,100 ,0 ); - TimerOn =0 ;// it's the truth but not checked in service -// Just polled boards, IRQ = 0 will hit all non-interrupt boards. // It will NOT poll boards handled by hard interrupts. // The issue of queued BH interrupts is handled in ip2_interrupt(). ip2_polled_interrupt (); - PollTimer.expires =POLL_TIMEOUT ; -add_timer ( &PollTimer ); - TimerOn =1 ; +mod_timer (&PollTimer,POLL_TIMEOUT );ip2trace (ITRC_NO_PORT ,ITRC_INTR ,ITRC_RETURN ,0 ); }
PATCH 21/76 audit: Handle embedded NUL in TTY input auditing
In reply to Alan CoxFrom: Miloslav Trmac <[email protected]>
Data read from a TTY can contain an embedded NUL byte (e.g. after pressing Ctrl-2, or sent to a PTY). After the previous patch, the data would be logged only up to the first NUL.
This patch modifies the AUDIT_TTY record to always use the hexadecimal format, which does not terminate at the first NUL byte. The vast majority of recorded TTY input data will contain either ' ' or '\n', so the hexadecimal format would have been used anyway.
---
drivers/char/tty_audit.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/char/tty_audit.c +1 -1
@@ -93,7 +93,7 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,get_task_comm (name, tsk);audit_log_untrustedstring (ab, name);audit_log_format (ab," data=" ); -audit_log_n_untrustedstring (ab, buf->data, buf->valid); +audit_log_n_hex (ab, buf->data, buf->valid);audit_log_end (ab); } buf->valid =0 ;
PATCH 22/76 serial: Make uart_port's ioport "unsigned long".
In reply to Alan CoxFrom: David Miller <[email protected]>
Otherwise the top 32-bits of the resource value get chopped off on 64-bit systems, and the resulting I/O accesses go to random places.
Thanks to testing and debugging by Josip Rodin, which helped track this down.
---
include/linux/serial_core.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
include/linux/serial_core.h +1 -1
@@ -241,7 +241,7 @@ typedef unsigned int __bitwise__ upf_t;struct uart_port {spinlock_t lock;/* port lock */ -unsigned int iobase;/* in/out[bwl] */ +unsigned long iobase;/* in/out[bwl] */ unsigned char __iomem *membase;/* read/write[bwl] */ unsigned int irq;/* irq number */ unsigned int uartclk;/* base uart clock */
Re: [PATCH 22/76] serial: Make uart_port's ioport "unsigned long".
Quoted 21 lines · Alan Cox
From: David Miller <[email protected]>
Otherwise the top 32-bits of the resource value get chopped off on 64-bit systems, and the resulting I/O accesses go to random places.
Thanks to testing and debugging by Josip Rodin, which helped track this down.
Signed-off-by David S. Miller <[email protected]>Signed-off-by Alan Cox <[email protected]>---
include/linux/serial_core.h| 2 +-1 files changed, 1 insertions(+), 1 deletions(-)include/linux/serial_core.h +0
-0
include/linux/serial_core.h typedef unsigned int __bitwise__ upf_t; · line 244
Quoted 5 lines
include/linux/serial_core.h +1
-1@@ -241,7 +241,7 @@ typedef unsigned int __bitwise__ upf_t;struct uart_port {spinlock_t lock;/* port lock */ -unsigned int iobase;/* in/out[bwl] */ +unsigned long iobase;/* in/out[bwl] */
Does using resource_size_t make more sense here? There are 32-bit CPUs that have 64-bit address spaces. (Perhaps not that use iobase, but it might be cleaner in general.)
josh
PATCH 23/76 tty: split the buffering from tty_io
In reply to Alan CoxThe two are basically independent chunks of code so lets split them up for readability and sanity. It also makes the API boundaries much clearer.
---
drivers/char/Makefile | 2 drivers/char/tty_buffer.c | 511 +++++++++++++++++++++++++++++++++++++++++++++ drivers/char/tty_io.c | 502 -------------------------------------------- include/linux/tty.h | 3 4 files changed, 515 insertions(+), 503 deletions(-) create mode 100644 drivers/char/tty_buffer.c
drivers/char/Makefile +1 -1
@@ -7,7 +7,7 @@ # FONTMAPFILE = cp437.uni -obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o +obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o obj-$(CONFIG_LEGACY_PTYS) += pty.o obj-$(CONFIG_UNIX98_PTYS) += pty.o
drivers/char/tty_buffer.c new file +511 -0
511 lines not on this page · raw message
drivers/char/tty_io.c +0 -502
526 lines not on this page · raw message
include/linux/tty.h +3 -0
@@ -347,6 +347,9 @@ extern void __do_SAK(struct tty_struct *tty);extern void disassociate_ctty (int priv);extern void no_tty (void );extern void tty_flip_buffer_push (struct tty_struct *tty); +extern void tty_buffer_free_all (struct tty_struct *tty); +extern void tty_buffer_flush (struct tty_struct *tty); +extern void tty_buffer_init (struct tty_struct *tty);extern speed_t tty_get_baud_rate (struct tty_struct *tty);extern speed_t tty_termios_baud_rate (struct ktermios *termios);extern speed_t tty_termios_input_baud_rate (struct ktermios *termios);
PATCH 24/76 tty: Split tty_port into its own file
In reply to Alan CoxNot much in it yet but this will grow a lot
---
drivers/char/Makefile | 2 +- drivers/char/tty_io.c | 36 ------------------------------- drivers/char/tty_port.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 37 deletions(-) create mode 100644 drivers/char/tty_port.c
drivers/char/Makefile +1 -1
@@ -7,7 +7,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 +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_LEGACY_PTYS) += pty.o obj-$(CONFIG_UNIX98_PTYS) += pty.o
drivers/char/tty_io.c +0 -36
@@ -1139,42 +1139,6 @@ ssize_t redirected_tty_write(struct file *file, const char __user *buf,return tty_write (file, buf, count, ppos); } -void tty_port_init (struct tty_port *port) -{ -memset (port,0 ,sizeof (*port)); -init_waitqueue_head (&port->open_wait); -init_waitqueue_head (&port->close_wait); -mutex_init (&port->mutex); - port->close_delay = (50 *HZ ) /100 ; - port->closing_wait = (3000 *HZ ) /100 ; -} -EXPORT_SYMBOL (tty_port_init); - -int tty_port_alloc_xmit_buf (struct tty_port *port) -{ -/* We may sleep in get_zeroed_page() */ -mutex_lock (&port->mutex); -if (port->xmit_buf ==NULL ) - port->xmit_buf = (unsigned char *)get_zeroed_page (GFP_KERNEL ); -mutex_unlock (&port->mutex); -if (port->xmit_buf ==NULL ) -return -ENOMEM ; -return 0 ; -} -EXPORT_SYMBOL (tty_port_alloc_xmit_buf); - -void tty_port_free_xmit_buf (struct tty_port *port) -{ -mutex_lock (&port->mutex); -if (port->xmit_buf !=NULL ) { -free_page ((unsigned long )port->xmit_buf); - port->xmit_buf =NULL ; - } -mutex_unlock (&port->mutex); -} -EXPORT_SYMBOL (tty_port_free_xmit_buf); - -static char ptychar[] ="pqrstuvwxyzabcde" ;/**
drivers/char/tty_port.c new file +55 -0
55 lines not on this page · raw message
PATCH 25/76 pps: Reserve a line discipline number for PPS
In reply to Alan CoxAdd a new line discipline for "pulse per second" devices connected to a serial port.
---
include/linux/tty.h | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
include/linux/tty.h +2 -1
@@ -23,7 +23,7 @@*/ #define NR_UNIX98_PTY_DEFAULT 4096/* Default maximum for Unix98 ptys */ #define NR_UNIX98_PTY_MAX (1 << MINORBITS)/* Absolute limit */ -#define NR_LDISCS 18 +#define NR_LDISCS 19/* line disciplines */ #define N_TTY 0
@@ -45,6 +45,7 @@#define N_HCI 15/* Bluetooth HCI UART */ #define N_GIGASET_M101 16/* Siemens Gigaset M101 serial DECT adapter */ #define N_SLCAN 17/* Serial / USB serial CAN Adaptors */ +#define N_PPS 18/* Pulse per Second */ /* * This character is the same as _POSIX_VDISABLE: it cannot be used as
PATCH 26/76 tty: Add a kref count
In reply to Alan CoxIntroduce a kref to the tty structure and use it to protect the tty->signal tty references. For now we don't introduce it for anything else.
---
drivers/char/tty_io.c | 54 ++++++++++++++++++++++++++++++++++++++++++++----- include/linux/tty.h | 18 ++++++++++++++++ kernel/fork.c | 5 ++++- kernel/sys.c | 4 +--- 4 files changed, 71 insertions(+), 10 deletions(-)
drivers/char/tty_io.c +48 -6
@@ -559,6 +559,7 @@ static void do_tty_hangup(struct work_struct *work)struct tty_ldisc *ld;int closecount =0 , n;unsigned long flags; +int refs =0 ;if (!tty)return ;
@@ -625,8 +626,12 @@ static void do_tty_hangup(struct work_struct *work)if (tty->session) { do_each_pid_task(tty->session, PIDTYPE_SID, p) {spin_lock_irq (&p->sighand->siglock); -if (p->signal->tty == tty) +if (p->signal->tty == tty) { p->signal->tty =NULL ; +/* We defer the dereferences outside fo +the tasklist lock */ + refs++; + }if (!p->signal->leader) {spin_unlock_irq (&p->sighand->siglock);continue ;
@@ -652,6 +657,10 @@ static void do_tty_hangup(struct work_struct *work) tty->ctrl_status =0 ;spin_unlock_irqrestore (&tty->ctrl_lock, flags); +/* Account for the p->signal references we killed */ +while (refs--) +tty_kref_put (tty); +/* * If one of the devices matches a console pointer, we * cannot just call hangup() because that will cause
@@ -1424,6 +1433,7 @@ release_mem_out:/** * release_one_tty - release tty structure memory +* @kref: kref of tty we are obliterating * * Releases memory associated with a tty structure, and clears out the * driver table slots. This function is called when a device is no longer
@@ -1433,17 +1443,19 @@ release_mem_out:* tty_mutex - sometimes only * takes the file list lock internally when working on the list * of ttys that the driver keeps. -* FIXME: should we require tty_mutex is held here ?? */ -static void release_one_tty (struct tty_struct *tty,int idx) +static void release_one_tty (struct kref *kref) { + struct tty_struct *tty = container_of(kref, struct tty_struct, kref);int devpts = tty->driver->flags &TTY_DRIVER_DEVPTS_MEM ;struct ktermios *tp; +int idx = tty->index;if (!devpts) tty->driver->ttys[idx] =NULL ;if (tty->driver->flags &TTY_DRIVER_RESET_TERMIOS ) { +/* FIXME: Locking on ->termios array */ tp = tty->termios;if (!devpts) tty->driver->termios[idx] =NULL ;
@@ -1457,6 +1469,7 @@ static void release_one_tty(struct tty_struct *tty, int idx) tty->magic =0 ; +/* FIXME: locking on tty->driver->refcount */ tty->driver->refcount--;file_list_lock ();
@@ -1467,6 +1480,21 @@ static void release_one_tty(struct tty_struct *tty, int idx) }/** +* tty_kref_put - release a tty kref +* @tty: tty device +* +* Release a reference to a tty device and if need be let the kref +* layer destruct the object for us +*/ + +void tty_kref_put (struct tty_struct *tty) +{ +if (tty) +kref_put (&tty->kref, release_one_tty); +} +EXPORT_SYMBOL (tty_kref_put); + +/** * release_tty - release tty structure memory * * Release both @tty and a possible linked partner (think pty pair),
@@ -1477,14 +1505,20 @@ static void release_one_tty(struct tty_struct *tty, int idx)* takes the file list lock internally when working on the list * of ttys that the driver keeps. * FIXME: should we require tty_mutex is held here ?? +* +* FIXME: We want to defer the module put of the driver to the +* destructor. */ static void release_tty (struct tty_struct *tty,int idx) {struct tty_driver *driver = tty->driver; +/* This should always be true but check for the moment */ +WARN_ON (tty->index != idx); +if (tty->link) -release_one_tty (tty->link, idx); -release_one_tty (tty, idx); +tty_kref_put (tty->link); +tty_kref_put (tty);module_put (driver->owner); }
@@ -2798,6 +2832,7 @@ EXPORT_SYMBOL(do_SAK);static void initialize_tty_struct (struct tty_struct *tty) {memset (tty,0 ,sizeof (struct tty_struct )); +kref_init (&tty->kref); tty->magic =TTY_MAGIC ;tty_ldisc_init (tty); tty->session =NULL ;
@@ -3053,9 +3088,12 @@ EXPORT_SYMBOL(tty_devnum);void proc_clear_tty (struct task_struct *p) { +struct tty_struct *tty;spin_lock_irq (&p->sighand->siglock); + tty = p->signal->tty; p->signal->tty =NULL ;spin_unlock_irq (&p->sighand->siglock); +tty_kref_put (tty); }/* Called under the sighand lock */
@@ -3071,9 +3109,13 @@ static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) tty->pgrp =get_pid (task_pgrp (tsk));spin_unlock_irqrestore (&tty->ctrl_lock, flags); tty->session =get_pid (task_session (tsk)); +if (tsk->signal->tty) { +printk (KERN_DEBUG "tty not NULL!!\n" ); +tty_kref_put (tsk->signal->tty); + } }put_pid (tsk->signal->tty_old_pgrp); - tsk->signal->tty = tty; + tsk->signal->tty =tty_kref_get (tty); tsk->signal->tty_old_pgrp =NULL ; }
include/linux/tty.h +18 -0
@@ -209,6 +209,7 @@ struct tty_operations;struct tty_struct {int magic; +struct kref kref;struct tty_driver *driver;const struct tty_operations *ops;int index;
@@ -311,6 +312,23 @@ extern int kmsg_redirect;extern void console_init (void );extern int vcs_init (void ); +/** +* tty_kref_get - get a tty reference +* @tty: tty device +* +* Return a new reference to a tty object. The caller must hold +* sufficient locks/counts to ensure that their existing reference cannot +* go away +*/ + +extern inline struct tty_struct *tty_kref_get (struct tty_struct *tty) +{ +if (tty) +kref_get (&tty->kref); +return tty; +} +extern void tty_kref_put (struct tty_struct *tty); +extern int tty_paranoia_check (struct tty_struct *tty,struct inode *inode,const char *routine);extern char *tty_name (struct tty_struct *tty,char *buf);
kernel/fork.c +4 -1
@@ -802,6 +802,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) sig->leader =0 ;/* session leadership doesn't inherit */ sig->tty_old_pgrp =NULL ; + sig->tty =NULL ; sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero; sig->gtime = cputime_zero;
@@ -838,6 +839,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)void __cleanup_signal (struct signal_struct *sig) {exit_thread_group_keys (sig); +tty_kref_put (sig->tty);kmem_cache_free (signal_cachep, sig); }
@@ -1227,7 +1229,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, p->nsproxy->pid_ns->child_reaper = p; p->signal->leader_pid = pid; - p->signal->tty = current->signal->tty; +tty_kref_put (p->signal->tty); + p->signal->tty =tty_kref_get (current->signal->tty);set_task_pgrp (p,task_pgrp_nr (current));set_task_session (p,task_session_nr (current));attach_pid (p,PIDTYPE_PGID ,task_pgrp (current));
kernel/sys.c +1 -3
@@ -1060,9 +1060,7 @@ asmlinkage long sys_setsid(void) group_leader->signal->leader =1 ;__set_special_pids (sid); -spin_lock (&group_leader->sighand->siglock); - group_leader->signal->tty =NULL ; -spin_unlock (&group_leader->sighand->siglock); +proc_clear_tty (group_leader); err = session; out:
Re: [PATCH 26/76] tty: Add a kref count
Quoted 2 lines · Alan Cox
Introduce a kref to the tty structure and use it to protect the
tty->signaltty references. For now we don't introduce it for anything else.
[...]
Quoted 21 lines
kernel/fork.c +2
-0@@ -802,6 +802,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) sig->leader =0 ;/* session leadership doesn't inherit */ sig->tty_old_pgrp =NULL ; + sig->tty =NULL ; sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero; sig->gtime = cputime_zero;@@ -838,6 +839,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)void __cleanup_signal (struct signal_struct *sig) {exit_thread_group_keys (sig); +tty_kref_put (sig->tty);kmem_cache_free (signal_cachep, sig); }
kernel/fork.c static struct task_struct *copy_process(unsigned long clone_flags, · line 1236
Quoted 9 lines
kernel/fork.c +2
-1@@ -1227,7 +1229,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, p->nsproxy->pid_ns->child_reaper = p; p->signal->leader_pid = pid; - p->signal->tty = current->signal->tty; +tty_kref_put (p->signal->tty); + p->signal->tty =tty_kref_get (current->signal->tty);set_task_pgrp (p,task_pgrp_nr (current));set_task_session (p,task_session_nr (current));attach_pid (p,PIDTYPE_PGID ,task_pgrp (current));
I'm a bit puzzled by this 'tty_kref_put(p->signal->tty)'. AFAICS, this is a noop since we are not in the CLONE_THREAD case and hence p->signal->tty == NULL. So, is it to make the code look more consistent? If so, is it worth adding extra code and cycles for this (I doubt that gcc is able to optimize this away)? What kind of future changes should this code protect against?
Thanks,
Louis
Signature · 4 lines
Dr Louis Rilling Kerlabs Skype: louis.rilling Batiment Germanium Phone: (+33|0) 6 80 89 08 23 80 avenue des Buttes de Coesmes http://www.kerlabs.com/ 35700 Rennes
Re: [PATCH 26/76] tty: Add a kref count
Quoted 3 lines · Louis Rilling
I'm a bit puzzled by this '
tty_kref_put(p->signal->tty)'. AFAICS, this is a noop since we are not in theCLONE_THREADcase and hencep->signal->tty== NULL.
When I first did it I was seeing non NULL values, but since then I've added the initialisation
Quoted 3 lines
So, is it to make the code look more consistent? If so, is it worth adding extra code and cycles for this (I doubt that gcc is able to optimize this away)? What kind of future changes should this code protect against?
I'll take a look, you may well be right, and if so it can become a WARN_ON() instead.
PATCH 27/76 tty: use krefs to protect driver module counts
In reply to Alan CoxThe tty layer keeps driver module counts that are used so the driver knows when it can be unloaded. For obvious reasons we want to tie that to the refcounting properly.
At this point the driver side itself isn't refcounted nicely but we can do that later and kref the drivers.
---
drivers/char/tty_io.c | 17 +++++++++++------ 1 files changed, 11 insertions(+), 6 deletions(-)
drivers/char/tty_io.c +11 -6
@@ -1293,6 +1293,12 @@ static int init_dev(struct tty_driver *driver, int idx, o_tty =alloc_tty_struct ();if (!o_tty) goto free_mem_out; +if (!try_module_get (driver->other->owner)) { +/* This cannot in fact currently happen */ +free_tty_struct (o_tty); + o_tty =NULL ; + goto free_mem_out; + }initialize_tty_struct (o_tty); o_tty->driver = driver->other; o_tty->ops = driver->ops;
@@ -1411,8 +1417,10 @@ end_init:/* Release locally allocated memory ... nothing placed in slots */ free_mem_out:kfree (o_tp); -if (o_tty) +if (o_tty) { +module_put (o_tty->driver->owner);free_tty_struct (o_tty); + }kfree (ltp);kfree (tp);free_tty_struct (tty);
@@ -1447,6 +1455,7 @@ release_mem_out:static void release_one_tty (struct kref *kref) { struct tty_struct *tty = container_of(kref, struct tty_struct, kref); +struct tty_driver *driver = tty->driver;int devpts = tty->driver->flags &TTY_DRIVER_DEVPTS_MEM ;struct ktermios *tp;int idx = tty->index;
@@ -1471,6 +1480,7 @@ static void release_one_tty(struct kref *kref) tty->magic =0 ;/* FIXME: locking on tty->driver->refcount */ tty->driver->refcount--; +module_put (driver->owner);file_list_lock ();list_del_init (&tty->tty_files);
@@ -1506,20 +1516,15 @@ EXPORT_SYMBOL(tty_kref_put);* of ttys that the driver keeps. * FIXME: should we require tty_mutex is held here ?? * -* FIXME: We want to defer the module put of the driver to the -* destructor. */ static void release_tty (struct tty_struct *tty,int idx) { -struct tty_driver *driver = tty->driver; -/* This should always be true but check for the moment */ WARN_ON (tty->index != idx);if (tty->link)tty_kref_put (tty->link);tty_kref_put (tty); -module_put (driver->owner); }/*
PATCH 28/76 Char: cyclades. remove bogus iomap
In reply to Alan CoxFrom: Jiri Slaby <[email protected]>
readl/writel are not expected to accept iomap return value. Replace bogus mapping by standard ioremap.
---
drivers/char/cyclades.c | 21 ++++++++++++--------- 1 files changed, 12 insertions(+), 9 deletions(-)
drivers/char/cyclades.c +12 -9
@@ -4993,12 +4993,14 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { card_name ="Cyclom-Y" ; - addr0 =pci_iomap (pdev,0 , CyPCI_Yctl); + addr0 =ioremap_nocache (pci_resource_start (pdev,0 ), + CyPCI_Yctl);if (addr0 ==NULL ) {dev_err (&pdev->dev,"can't remap ctl region\n" ); goto err_reg; } - addr2 =pci_iomap (pdev,2 , CyPCI_Ywin); + addr2 =ioremap_nocache (pci_resource_start (pdev,2 ), + CyPCI_Ywin);if (addr2 ==NULL ) {dev_err (&pdev->dev,"can't remap base region\n" ); goto err_unmap;
@@ -5013,7 +5015,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) {struct RUNTIME_9060 __iomem *ctl_addr; - ctl_addr = addr0 =pci_iomap (pdev,0 , CyPCI_Zctl); + ctl_addr = addr0 =ioremap_nocache (pci_resource_start (pdev,0 ), + CyPCI_Zctl);if (addr0 ==NULL ) {dev_err (&pdev->dev,"can't remap ctl region\n" ); goto err_reg;
@@ -5026,8 +5029,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, mailbox = (u32 )readl (&ctl_addr->mail_box_0); - addr2 =pci_iomap (pdev,2 , mailbox ==ZE_V1 ? - CyPCI_Ze_win : CyPCI_Zwin); + addr2 =ioremap_nocache (pci_resource_start (pdev,2 ), + mailbox ==ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin);if (addr2 ==NULL ) {dev_err (&pdev->dev,"can't remap base region\n" ); goto err_unmap;
@@ -5159,9 +5162,9 @@ err_null: cy_card[card_no].base_addr =NULL ;free_irq (irq, &cy_card[card_no]); err_unmap: -pci_iounmap (pdev, addr0); +iounmap (addr0);if (addr2) -pci_iounmap (pdev, addr2); +iounmap (addr2); err_reg:pci_release_regions (pdev); err_dis:
@@ -5186,9 +5189,9 @@ static void __devexit cy_pci_remove(struct pci_dev *pdev)cy_writew (cinfo->ctl_addr +0x68 ,readw (cinfo->ctl_addr +0x68 ) & ~0x0900 ); -pci_iounmap (pdev, cinfo->base_addr); +iounmap (cinfo->base_addr);if (cinfo->ctl_addr) -pci_iounmap (pdev, cinfo->ctl_addr); +iounmap (cinfo->ctl_addr); if (cinfo->irq#ifndef CONFIG_CYZ_INTR && !IS_CYC_Z (*cinfo)
PATCH 29/76 Char: sx, fix io unmapping
In reply to Alan CoxFrom: Jiri Slaby <[email protected]>
board->base is increased for CF cards after mapping. Use board->base2 for unmapping the region, since it holds the original/correct address.
---
drivers/char/sx.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/char/sx.c +2 -2
@@ -2504,7 +2504,7 @@ static void __devexit sx_remove_card(struct sx_board *board,del_timer (&board->timer);if (pdev) {#ifdef CONFIG_PCI -pci_iounmap (pdev, board->base); +pci_iounmap (pdev, board->base2);pci_release_region (pdev,IS_CF_BOARD (board) ?3 :2 );#endif }else {
@@ -2703,7 +2703,7 @@ static int __devinit sx_pci_probe(struct pci_dev *pdev,return 0 ; err_unmap: -pci_iounmap (pdev, board->base); +pci_iounmap (pdev, board->base2); err_reg:pci_release_region (pdev, reg); err_flag:
PATCH 30/76 8250: remove a few inlines of dubious value
In reply to Alan CoxFrom: \\\"Will Newton\\\" <[email protected]>
Remove some inlines from various functions that are called once, are too big to inline, or are called only from slow path code. This saves around 300 bytes of code for me.
---
drivers/serial/8250.c | 9 ++++----- 1 files changed, 4 insertions(+), 5 deletions(-)
drivers/serial/8250.c +4 -5
@@ -540,7 +540,7 @@ static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)/* * FIFO support. */ -static inline void serial8250_clear_fifos (struct uart_8250_port *p) +static void serial8250_clear_fifos (struct uart_8250_port *p) {if (p->capabilities &UART_CAP_FIFO ) {serial_outp (p,UART_FCR ,UART_FCR_ENABLE_FIFO );
@@ -555,7 +555,7 @@ static inline void serial8250_clear_fifos(struct uart_8250_port *p)* capability" bit enabled. Note that on XR16C850s, we need to * reset LCR to write to IER. */ -static inline void serial8250_set_sleep (struct uart_8250_port *p,int sleep) +static void serial8250_set_sleep (struct uart_8250_port *p,int sleep) {if (p->capabilities &UART_CAP_SLEEP ) {if (p->capabilities &UART_CAP_EFR ) {
@@ -1428,8 +1428,7 @@ static unsigned int check_modem_status(struct uart_8250_port *up)/* * This handles the interrupt from one port. */ -static inline void -serial8250_handle_port (struct uart_8250_port *up) +static void serial8250_handle_port (struct uart_8250_port *up) {unsigned int status;unsigned long flags;
@@ -1764,7 +1763,7 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)/* * Wait for transmitter & holding register to empty */ -static inline void wait_for_xmitr (struct uart_8250_port *up,int bits) +static void wait_for_xmitr (struct uart_8250_port *up,int bits) {unsigned int status, tmout =10000 ;
PATCH 31/76 tty: Cris has a nice RS485 ioctl so we should steal it
In reply to Alan CoxJP Tosoni observed:
"About a RS485 ioctl: could you consider the attached files which are
already in the Linux kernel (in include/asm-cris). They define a TIOCSERSETRS485 (ioctl.h), and the data structure (rs485.h) with allows to specify timings. Sounds just like what we want ?"
and he's right: sort of. Rework the structure to use flag bits and make the time delay a fixed sized field so we don't get 32/64bit problems. Add the ioctls to x86 so that people know what to add to their platform of choice.
---
include/asm-x86/ioctls.h | 2 ++ include/linux/serial.h | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 0 deletions(-)
include/asm-x86/ioctls.h +2 -0
@@ -51,6 +51,8 @@#define TCSETS2 _IOW('T', 0x2B, struct termios2)#define TCSETSW2 _IOW('T', 0x2C, struct termios2)#define TCSETSF2 _IOW('T', 0x2D, struct termios2) +#define TIOCGRS485 0x542E +#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 */
include/linux/serial.h +16 -0
@@ -173,6 +173,22 @@ struct serial_icounter_struct {int reserved[9 ]; }; +/* +* Serial interface for controlling RS485 settings on chips with suitable +* support. Set with TIOCSRS485 and get with TIOCGRS485 if supported by your +* platform. The set function returns the new state, with any unsupported bits +* reverted appropriately. +*/ + +struct serial_rs485 { +__u32 flags;/* RS485 feature flags */ +#define SER_RS485_ENABLED (1 << 0) +#define SER_RS485_RTS_ON_SEND (1 << 1) +#define SER_RS485_RTS_AFTER_SEND (1 << 2) +__u32 delay_rts_before_send;/* Milliseconds */ +__u32 padding[6 ];/* Memory is cheap, new structs +are a royal PITA .. */ +};#ifdef __KERNEL__#include <linux/compiler.h>
PATCH 32/76 tty: ipw need reworking
In reply to Alan CoxThis came in via another tree and unfortunately is rather broken on the tty side. Comment the apparent locking problems for someone who knows the driver to look at.
Fix the termios and other ioctl handling. The driver was calling the wrong methods for what it wanted to do but the right ones existed so its a simple fix up.
---
drivers/char/pcmcia/ipwireless/tty.c | 19 ++++++++++--------- 1 files changed, 10 insertions(+), 9 deletions(-)
drivers/char/pcmcia/ipwireless/tty.c +10 -9
@@ -276,6 +276,7 @@ static int ipw_write_room(struct tty_struct *linux_tty)struct ipw_tty *tty = linux_tty->driver_data;int room; +/* FIXME: Exactly how is the tty object locked here .. */ if (!tty)return -ENODEV ;
@@ -397,6 +398,7 @@ static int set_control_lines(struct ipw_tty *tty, unsigned int set,static int ipw_tiocmget (struct tty_struct *linux_tty,struct file *file) {struct ipw_tty *tty = linux_tty->driver_data; +/* FIXME: Exactly how is the tty object locked here .. */ if (!tty)return -ENODEV ;
@@ -412,6 +414,7 @@ ipw_tiocmset(struct tty_struct *linux_tty, struct file *file, unsigned int set, unsigned int clear) {struct ipw_tty *tty = linux_tty->driver_data; +/* FIXME: Exactly how is the tty object locked here .. */ if (!tty)return -ENODEV ;
@@ -433,6 +436,8 @@ static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file,if (!tty->open_count)return -EINVAL ; +/* FIXME: Exactly how is the tty object locked here .. */ +switch (cmd) {case TIOCGSERIAL :return ipwireless_get_serial_info (tty, (void __user *) arg);
@@ -467,13 +472,6 @@ static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file, }return 0 ; -case TCGETS : -case TCGETA : -return n_tty_ioctl (linux_tty, file, cmd, arg); - -case TCFLSH : -return n_tty_ioctl (linux_tty, file, cmd, arg); -case FIONREAD : {int val =0 ;
@@ -482,10 +480,11 @@ static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file,return -EFAULT ; }return 0 ; +case TCFLSH : +return tty_perform_flush (linux_tty, arg); } } - -return -ENOIOCTLCMD ; +return tty_mode_ioctl (linux_tty, file, cmd , arg); } static int add_tty(dev_node_t *nodesp, int j,
@@ -588,6 +587,8 @@ void ipwireless_tty_free(struct ipw_tty *tty)tty_hangup (ttyj->linux_tty);/* Wait till the tty_hangup has completed */ flush_scheduled_work (); +/* FIXME: Exactly how is the tty object locked here +against a parallel ioctl etc */ mutex_lock (&ttyj->ipw_tty_mutex); }while (ttyj->open_count)
PATCH 33/76 tty: Add termiox
In reply to Alan CoxWe need a way to describe the various additional modes and flow control features that random weird hardware shows up and software such as wine wants to emulate as Windows supports them.
TCGETX/TCSETX and the termiox ioctl are a SYS5 extension that we might as well adopt. This patches adds the structures and the basic ioctl interfaces when the TCGETX etc defines are added for an architecture. Drivers wishing to use this stuff need to add new methods.
---
drivers/char/tty_ioctl.c | 58 ++++++++++++++++++++++++++++++++++++++++++++ include/asm-x86/ioctls.h | 4 +++ include/linux/termios.h | 15 +++++++++++ include/linux/tty.h | 1 + include/linux/tty_driver.h | 9 +++++++ 5 files changed, 87 insertions(+), 0 deletions(-)
drivers/char/tty_ioctl.c +58 -0
@@ -579,6 +579,50 @@ static int get_termio(struct tty_struct *tty, struct termio __user *termio)return 0 ; } + +#ifdef TCGETX + +/** +* set_termiox - set termiox fields if possible +* @tty: terminal +* @arg: termiox structure from user +* @opt: option flags for ioctl type +* +* Implement the device calling points for the SYS5 termiox ioctl +* interface in Linux +*/ + +static int set_termiox (struct tty_struct *tty,void __user *arg,int opt) +{ +struct termiox tnew; +struct tty_ldisc *ld; + +if (tty->termiox ==NULL ) +return -EINVAL ; +if (copy_from_user (&tnew, arg,sizeof (struct termiox ))) +return -EFAULT ; + + ld =tty_ldisc_ref (tty); +if (ld !=NULL ) { +if ((opt &TERMIOS_FLUSH ) && ld->ops->flush_buffer) + ld->ops->flush_buffer (tty); +tty_ldisc_deref (ld); + } +if (opt &TERMIOS_WAIT ) { +tty_wait_until_sent (tty,0 ); +if (signal_pending (current)) +return -EINTR ; + } + +mutex_lock (&tty->termios_mutex); +if (tty->ops->set_termiox) + tty->ops->set_termiox (tty, &tnew); +mutex_unlock (&tty->termios_mutex); +return 0 ; +} + +#endif +static unsigned long inq_canon (struct tty_struct *tty) {int nr, head, tail;
@@ -936,6 +980,20 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,return -EFAULT ;return 0 ;#endif +#ifdef TCGETX +case TCGETX : +if (real_tty->termiox ==NULL ) +return -EINVAL ; +if (copy_to_user (p, real_tty->termiox,sizeof (struct termiox ))) +return -EFAULT ; +return 0 ; +case TCSETX : +return set_termiox (real_tty, p,0 ); +case TCSETXW : +return set_termiox (real_tty, p,TERMIOS_WAIT ); +case TCSETXF : +return set_termiox (real_tty, p,TERMIOS_FLUSH ); +#endif case TIOCGSOFTCAR :/* FIXME: for correctness we may need to take the termios lock here - review */
include/asm-x86/ioctls.h +4 -0
@@ -56,6 +56,10 @@#define TIOCGPTN _IOR('T', 0x30, unsigned int)/* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T', 0x31, int)/* Lock/unlock Pty */ +#define TCGETX 0x5432/* SYS5 TCGETX compatibility */ +#define TCSETX 0x5433 +#define TCSETXF 0x5434 +#define TCSETXW 0x5435#define FIONCLEX 0x5450#define FIOCLEX 0x5451
include/linux/termios.h +15 -0
@@ -4,4 +4,19 @@#include <linux/types.h> #include <asm/termios.h> +#define NFF 5 + +struct termiox +{ +__u16 x_hflag; +__u16 x_cflag; +__u16 x_rflag[NFF ]; +__u16 x_sflag; +}; + +#define RTSXOFF 0x0001/* RTS flow control on input */ +#define CTSXON 0x0002/* CTS flow control on output */ +#define DTRXOFF 0x0004/* DTR flow control on input */ +#define DSRXON 0x0008/* DCD flow control on output */ +#endif
include/linux/tty.h +1 -0
@@ -219,6 +219,7 @@ struct tty_struct {spinlock_t ctrl_lock;/* Termios values are protected by the termios mutex */ struct ktermios *termios, *termios_locked; +struct termiox *termiox;/* May be NULL for unsupported */ char name[64 ];struct pid *pgrp;/* Protected by ctrl lock */ struct pid *session;
include/linux/tty_driver.h +9 -0
@@ -180,6 +180,14 @@* not force errors here if they are not resizable objects (eg a serial * line). See tty_do_resize() if you need to wrap the standard method * in your own logic - the usual case. +* +* void (*set_termiox)(struct tty_struct *tty, struct termiox *new); +* +* Called when the device receives a termiox based ioctl. Passes down +* the requested data from user space. This method will not be invoked +* unless the tty also has a valid tty->termiox pointer. +* +* Optional: Called under the termios lock */ #include <linux/fs.h>
@@ -220,6 +228,7 @@ struct tty_operations { unsigned int set, unsigned int clear);int (*resize)(struct tty_struct *tty,struct tty_struct *real_tty,struct winsize *ws); +int (*set_termiox)(struct tty_struct *tty,struct termiox *tnew);#ifdef CONFIG_CONSOLE_POLL int (*poll_init)(struct tty_driver *driver,int line,char *options);int (*poll_get_char)(struct tty_driver *driver,int line);
PATCH 34/76 tty: Termios locking - sort out real_tty confusions and lock reads
In reply to Alan CoxThis moves us towards sanity and should mean our termios locking is now complete and comprehensive.
---
drivers/char/tty_io.c | 2 +- drivers/char/tty_ioctl.c | 58 ++++++++++++++++++++++++++++++---------------- 2 files changed, 39 insertions(+), 21 deletions(-)
drivers/char/tty_io.c +1 -1
@@ -2605,7 +2605,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)case TIOCSTI :return tiocsti (tty, p);case TIOCGWINSZ : -return tiocgwinsz (tty, p); +return tiocgwinsz (real_tty, p);case TIOCSWINSZ :return tiocswinsz (tty, real_tty, p);case TIOCCONS :
drivers/char/tty_ioctl.c +38 -20
108 lines not on this page · raw message
PATCH 35/76 tty: compare the tty winsize
In reply to Alan CoxWe always use the real tty one for stuff so the pty one should not be compared. As we propogate window changes to both it doesn't currently matter but will when we tidy up the pty termios logic a bit more
---
drivers/char/tty_io.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/char/tty_io.c +1 -1
@@ -2133,7 +2133,7 @@ int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,/* For a PTY we need to lock the tty side */ mutex_lock (&real_tty->termios_mutex); -if (!memcmp (ws, &tty->winsize,sizeof (*ws))) +if (!memcmp (ws, &real_tty->winsize,sizeof (*ws))) goto done;/* Get the PID values and reference them so we can avoid holding the tty ctrl lock while sending signals */
PATCH 36/76 tty: Make get_current_tty use a kref
In reply to Alan CoxWe now return a kref covered tty reference. That ensures the tty structure doesn't go away when you have a return from get_current_tty. This is not enough to protect you from most of the resources being freed behind your back - yet.
[Updated to include fixes for SELinux problems found by Andrew Morton and
an s390 leak found while debugging the former]
---
drivers/char/tty_io.c | 10 ++++++---- drivers/s390/char/fs3270.c | 3 ++- fs/dquot.c | 6 +++--- security/selinux/hooks.c | 3 ++- 4 files changed, 13 insertions(+), 9 deletions(-)
drivers/char/tty_io.c +6 -4
@@ -786,12 +786,12 @@ void disassociate_ctty(int on_exit) tty =get_current_tty ();if (tty) { tty_pgrp =get_pid (tty->pgrp); -lock_kernel ();mutex_unlock (&tty_mutex); -/* XXX: here we race, there is nothing protecting tty */ +lock_kernel ();if (on_exit && tty->driver->type !=TTY_DRIVER_TYPE_PTY )tty_vhangup (tty);unlock_kernel (); +tty_kref_put (tty); }else if (on_exit) {struct pid *old_pgrp;spin_lock_irq (¤t->sighand->siglock);
@@ -819,7 +819,6 @@ void disassociate_ctty(int on_exit)spin_unlock_irq (¤t->sighand->siglock);mutex_lock (&tty_mutex); -/* It is possible that do_tty_hangup has free'd this tty */ tty =get_current_tty ();if (tty) {unsigned long flags;
@@ -829,6 +828,7 @@ void disassociate_ctty(int on_exit) tty->session =NULL ; tty->pgrp =NULL ;spin_unlock_irqrestore (&tty->ctrl_lock, flags); +tty_kref_put (tty); }else {#ifdef TTY_DEBUG_HANGUP printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
@@ -1806,6 +1806,8 @@ retry_open: index = tty->index; filp->f_flags |=O_NONBLOCK ;/* Don't let /dev/tty block */ /* noctty = 1; */ +/* FIXME: Should we take a driver reference ? */ +tty_kref_put (tty); goto got_driver; }#ifdef CONFIG_VT
@@ -3135,7 +3137,7 @@ struct tty_struct *get_current_tty(void) {struct tty_struct *tty;WARN_ON_ONCE (!mutex_is_locked (&tty_mutex)); - tty = current->signal->tty; + tty =tty_kref_get (current->signal->tty);/* * session->tty can be changed/cleared from under us, make sure we * issue the load. The obtained pointer, when not NULL, is valid as
drivers/s390/char/fs3270.c +2 -1
@@ -430,11 +430,12 @@ fs3270_open(struct inode *inode, struct file *filp)mutex_lock (&tty_mutex); tty =get_current_tty ();if (!tty || tty->driver->major !=IBM_TTY3270_MAJOR ) { -mutex_unlock (&tty_mutex); +tty_kref_put (tty); rc = -ENODEV ; goto out; } minor = tty->index +RAW3270_FIRSTMINOR ; +tty_kref_put (tty);mutex_unlock (&tty_mutex); }/* Check if some other program is already using fullscreen mode. */
fs/dquot.c +3 -3
@@ -897,8 +897,9 @@ static void print_warning(struct dquot *dquot, const int warntype)mutex_lock (&tty_mutex); tty =get_current_tty (); +mutex_unlock (&tty_mutex);if (!tty) - goto out_lock; +return ;tty_write_message (tty, dquot->dq_sb->s_id);if (warntype ==QUOTA_NL_ISOFTWARN || warntype ==QUOTA_NL_BSOFTWARN )tty_write_message (tty,": warning, " );
@@ -926,8 +927,7 @@ static void print_warning(struct dquot *dquot, const int warntype) break; }tty_write_message (tty, msg); -out_lock: -mutex_unlock (&tty_mutex); +tty_kref_put (tty); }#endif
security/selinux/hooks.c +2 -1
@@ -2122,6 +2122,7 @@ static inline void flush_unauthorized_files(struct files_struct *files)mutex_lock (&tty_mutex); tty =get_current_tty (); +mutex_unlock (&tty_mutex);if (tty) {file_list_lock (); file =list_entry (tty->tty_files.next,typeof (*file), f_u.fu_list);
@@ -2138,8 +2139,8 @@ static inline void flush_unauthorized_files(struct files_struct *files) } }file_list_unlock (); +tty_kref_put (tty); } -mutex_unlock (&tty_mutex);/* Reset controlling tty. */ if (drop_tty)no_tty ();
Re: [PATCH 36/76] tty: Make get_current_tty use a kref
Quoted 8 lines · Alan Cox
We now return a kref covered tty reference. That ensures the tty structure doesn't go away when you have a return from
get_current_tty. This is not enough to protect you from most of the resources being freed behind your back - yet.[Updated to include fixes for SELinux problems found by Andrew Morton and
an s390 leak found while debugging the former]
[...]
drivers/s390/char/fs3270.c fs3270_open(struct inode *inode, struct file *filp) · line 433
Quoted 10 lines
drivers/s390/char/fs3270.c +1
-1@@ -430,11 +430,12 @@ fs3270_open(struct inode *inode, struct file *filp)mutex_lock (&tty_mutex); tty =get_current_tty ();if (!tty || tty->driver->major !=IBM_TTY3270_MAJOR ) { -mutex_unlock (&tty_mutex); +tty_kref_put (tty);
Should'nt mutex_unlock() be kept?
Louis
Quoted 8 lines
drivers/s390/char/fs3270.c +1
-0rc = -ENODEV ; goto out; } minor = tty->index +RAW3270_FIRSTMINOR ; +tty_kref_put (tty);mutex_unlock (&tty_mutex); }/* Check if some other program is already using fullscreen mode. */
Signature · 4 lines
Dr Louis Rilling Kerlabs Skype: louis.rilling Batiment Germanium Phone: (+33|0) 6 80 89 08 23 80 avenue des Buttes de Coesmes http://www.kerlabs.com/ 35700 Rennes
Re: [PATCH 36/76] tty: Make get_current_tty use a kref
Quoted 6 lines · Louis Rilling
drivers/s390/char/fs3270.c fs3270_open(struct inode *inode, struct file *filp) · line 433
Quoted 4 lines
drivers/s390/char/fs3270.c +1
-1tty =get_current_tty ();if (!tty || tty->driver->major !=IBM_TTY3270_MAJOR ) { -mutex_unlock (&tty_mutex); +tty_kref_put (tty);Should'nt
mutex_unlock()be kept?
Yes.. although it gets fixed later but I will fix that as it will keep the code bisectable.
PATCH 37/76 tty: Move tty_write_message out of kernel/printk
In reply to Alan CoxThis is pure tty code so put it in the tty layer where it can be with the locking relevant material it uses
---
drivers/char/tty_io.c | 25 +++++++++++++++++++++++++ kernel/printk.c | 16 ---------------- 2 files changed, 25 insertions(+), 16 deletions(-)
drivers/char/tty_io.c +25 -0
@@ -1081,6 +1081,31 @@ out:return ret; } +/** +* tty_write_message - write a message to a certain tty, not just the console. +* @tty: the destination tty_struct +* @msg: the message to write +* +* This is used for messages that need to be redirected to a specific tty. +* We don't put it into the syslog queue right now maybe in the future if +* really needed. +* +* We must still hold the BKL and test the CLOSING flag for the moment. +*/ + +void tty_write_message (struct tty_struct *tty,char *msg) +{ +lock_kernel (); +if (tty) { +mutex_lock (&tty->atomic_write_lock); +if (tty->ops->write && !test_bit (TTY_CLOSING , &tty->flags)) + tty->ops->write (tty, msg,strlen (msg)); +tty_write_unlock (tty); + } +unlock_kernel (); +return ; +} +/** * tty_write - write method for tty device file
kernel/printk.c +0 -16
@@ -1291,22 +1291,6 @@ static int __init disable_boot_consoles(void) }late_initcall (disable_boot_consoles); -/** -* tty_write_message - write a message to a certain tty, not just the console. -* @tty: the destination tty_struct -* @msg: the message to write -* -* This is used for messages that need to be redirected to a specific tty. -* We don't put it into the syslog queue right now maybe in the future if -* really needed. -*/ -void tty_write_message (struct tty_struct *tty,char *msg) -{ -if (tty && tty->ops->write) - tty->ops->write (tty, msg,strlen (msg)); -return ; -} -#if definedCONFIG_PRINTK /*
PATCH 38/76 tty: usb-serial krefs
In reply to Alan CoxUse kref in the USB serial drivers so that we don't free tty structures from under the URB receive handlers as has historically been the case if you were unlucky. This also gives us a framework for general tty drivers to use tty_port objects and refcount.
Contains two err->dev_err changes merged together to fix clashes in the -next tree.
---
drivers/char/tty_port.c | 41 ++++++++++++++++++ drivers/usb/serial/aircable.c | 15 ++++-- drivers/usb/serial/belkin_sa.c | 3 + drivers/usb/serial/console.c | 8 ++- drivers/usb/serial/cyberjack.c | 3 + drivers/usb/serial/cypress_m8.c | 5 +- drivers/usb/serial/digi_acceleport.c | 19 ++++++-- drivers/usb/serial/empeg.c | 8 ++- drivers/usb/serial/ftdi_sio.c | 19 +++++--- drivers/usb/serial/garmin_gps.c | 3 + drivers/usb/serial/generic.c | 3 + drivers/usb/serial/io_edgeport.c | 43 ++++++++++++------ drivers/usb/serial/io_ti.c | 26 ++++++++--- drivers/usb/serial/ipaq.c | 3 + drivers/usb/serial/ipw.c | 3 + drivers/usb/serial/ir-usb.c | 3 + drivers/usb/serial/iuu_phoenix.c | 3 + drivers/usb/serial/keyspan.c | 77 +++++++++++++++++---------------- drivers/usb/serial/keyspan_pda.c | 16 ++++--- drivers/usb/serial/kl5kusb105.c | 3 + drivers/usb/serial/kobil_sct.c | 3 + drivers/usb/serial/mct_u232.c | 6 ++- drivers/usb/serial/mos7720.c | 36 ++------------- drivers/usb/serial/mos7840.c | 7 ++- drivers/usb/serial/navman.c | 3 + drivers/usb/serial/omninet.c | 10 +++- drivers/usb/serial/option.c | 18 +++++--- drivers/usb/serial/oti6858.c | 3 + drivers/usb/serial/pl2303.c | 4 +- drivers/usb/serial/safe_serial.c | 11 +++-- drivers/usb/serial/sierra.c | 16 ++++--- drivers/usb/serial/spcp8x5.c | 3 + drivers/usb/serial/ti_usb_3410_5052.c | 44 ++++++++++--------- drivers/usb/serial/usb-serial.c | 24 ++++++---- drivers/usb/serial/visor.c | 18 +++++--- drivers/usb/serial/whiteheat.c | 8 ++- include/linux/tty.h | 3 + 37 files changed, 313 insertions(+), 208 deletions(-)
drivers/char/tty_port.c +41 -0
@@ -23,6 +23,7 @@ void tty_port_init(struct tty_port *port)init_waitqueue_head (&port->open_wait);init_waitqueue_head (&port->close_wait);mutex_init (&port->mutex); +spin_lock_init (&port->lock); port->close_delay = (50 *HZ ) /100 ; port->closing_wait = (3000 *HZ ) /100 ; }
@@ -53,3 +54,43 @@ void tty_port_free_xmit_buf(struct tty_port *port)EXPORT_SYMBOL (tty_port_free_xmit_buf); +/** +* tty_port_tty_get - get a tty reference +* @port: tty port +* +* Return a refcount protected tty instance or NULL if the port is not +* associated with a tty (eg due to close or hangup) +*/ + +struct tty_struct *tty_port_tty_get (struct tty_port *port) +{ +unsigned long flags; +struct tty_struct *tty; + +spin_lock_irqsave (&port->lock, flags); + tty =tty_kref_get (port->tty); +spin_unlock_irqrestore (&port->lock, flags); +return tty; +} +EXPORT_SYMBOL (tty_port_tty_get); + +/** +* tty_port_tty_set - set the tty of a port +* @port: tty port +* @tty: the tty +* +* Associate the port and tty pair. Manages any internal refcounts. +* Pass NULL to deassociate a port +*/ + +void tty_port_tty_set (struct tty_port *port,struct tty_struct *tty) +{ +unsigned long flags; + +spin_lock_irqsave (&port->lock, flags); +if (port->tty) +tty_kref_put (port->tty); + port->tty = tty; +spin_unlock_irqrestore (&port->lock, flags); +} +EXPORT_SYMBOL (tty_port_tty_set);
drivers/usb/serial/aircable.c +9 -6
@@ -272,7 +272,7 @@ static void aircable_read(struct work_struct *work)* 64 bytes, to ensure I do not get throttled. * Ask USB mailing list for better aproach. */ - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (!tty) {schedule_work (&priv->rx_work);
@@ -283,12 +283,13 @@ static void aircable_read(struct work_struct *work) count =min (64 ,serial_buf_data_avail (priv->rx_buf));if (count <=0 ) -return ;/* We have finished sending everything. */ + goto out;/* We have finished sending everything. */ tty_prepare_flip_string (tty, &data, count);if (!data) { -err ("%s- kzalloc(%d) failed." , __func__, count); -return ; +dev_err (&port->dev,"%s- kzalloc(%d) failed." , + __func__, count); + goto out; }serial_buf_get (priv->rx_buf, data, count);
@@ -297,7 +298,8 @@ static void aircable_read(struct work_struct *work)if (serial_buf_data_avail (priv->rx_buf))schedule_work (&priv->rx_work); - +out: +tty_kref_put (tty);return ; }/* End of private methods */
@@ -495,7 +497,7 @@ static void aircable_read_bulk_callback(struct urb *urb)usb_serial_debug_data (debug, &port->dev, __func__, urb->actual_length, urb->transfer_buffer); - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (tty && urb->actual_length) {if (urb->actual_length <=2 ) {/* This is an incomplete package */
@@ -527,6 +529,7 @@ static void aircable_read_bulk_callback(struct urb *urb) }aircable_read (&priv->rx_work); } +tty_kref_put (tty);/* Schedule the next read _if_ we are still open */ if (port->port.count) {
drivers/usb/serial/belkin_sa.c +2 -1
@@ -322,7 +322,7 @@ static void belkin_sa_read_int_callback(struct urb *urb)* to look in to this before committing any code. */ if (priv->last_lsr &BELKIN_SA_LSR_ERR ) { - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);/* Overrun Error */ if (priv->last_lsr &BELKIN_SA_LSR_OE ) { }
@@ -335,6 +335,7 @@ static void belkin_sa_read_int_callback(struct urb *urb)/* Break Indicator */ if (priv->last_lsr &BELKIN_SA_LSR_BI ) { } + tty_kref_put(tty); }#endif spin_unlock_irqrestore (&priv->lock, flags);
drivers/usb/serial/console.c +4 -4
@@ -117,7 +117,7 @@ static int usb_console_setup(struct console *co, char *options) } port = serial->port[0 ]; - port->port.tty =NULL ; +tty_port_tty_set (&port->port,NULL ); info->port = port;
@@ -143,7 +143,7 @@ static int usb_console_setup(struct console *co, char *options) }memset (&dummy,0 ,sizeof (struct ktermios )); tty->termios = termios; - port->port.tty = tty; +tty_port_tty_set (&port->port, tty); }/* only call the device specific open if this
@@ -163,7 +163,7 @@ static int usb_console_setup(struct console *co, char *options)tty_termios_encode_baud_rate (termios, baud, baud); serial->type->set_termios (tty, port, &dummy); - port->port.tty =NULL ; +tty_port_tty_set (&port->port,NULL );kfree (termios);kfree (tty); }
@@ -176,7 +176,7 @@ out:return retval; free_termios:kfree (termios); - port->port.tty =NULL ; +tty_port_tty_set (&port->port,NULL ); free_tty:kfree (tty); reset_open_count:
drivers/usb/serial/cyberjack.c +2 -1
@@ -384,7 +384,7 @@ static void cyberjack_read_bulk_callback(struct urb *urb)return ; } - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (!tty) {dbg ("%s - ignoring since device not open\n" , __func__);return ;
@@ -394,6 +394,7 @@ static void cyberjack_read_bulk_callback(struct urb *urb)tty_insert_flip_string (tty, data, urb->actual_length);tty_flip_buffer_push (tty); } +tty_kref_put (tty);spin_lock (&priv->lock);
drivers/usb/serial/cypress_m8.c +3 -2
@@ -1286,7 +1286,7 @@ static void cypress_read_int_callback(struct urb *urb) }spin_unlock_irqrestore (&priv->lock, flags); - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (!tty) {dbg ("%s - bad tty pointer - exiting" , __func__);return ;
@@ -1362,7 +1362,7 @@ static void cypress_read_int_callback(struct urb *urb) data[i]);tty_insert_flip_char (tty, data[i], tty_flag); } -tty_flip_buffer_push (port->port.tty); +tty_flip_buffer_push (tty); }spin_lock_irqsave (&priv->lock, flags);
@@ -1371,6 +1371,7 @@ static void cypress_read_int_callback(struct urb *urb)spin_unlock_irqrestore (&priv->lock, flags); continue_read: +tty_kref_put (tty);/* Continue trying to always read... unless the port has closed. */
drivers/usb/serial/digi_acceleport.c +13 -6
@@ -604,7 +604,9 @@ static void digi_wakeup_write_lock(struct work_struct *work)static void digi_wakeup_write (struct usb_serial_port *port) { -tty_wakeup (port->port.tty); +struct tty_struct *tty =tty_port_tty_get (&port->port); +tty_wakeup (tty); +tty_kref_put (tty); }
@@ -1668,7 +1670,7 @@ static int digi_read_inb_callback(struct urb *urb) {struct usb_serial_port *port = urb->context; -struct tty_struct *tty = port->port.tty; +struct tty_struct *tty;struct digi_port *priv =usb_get_serial_port_data (port);int opcode = ((unsigned char *)urb->transfer_buffer)[0 ];int len = ((unsigned char *)urb->transfer_buffer)[1 ];
@@ -1692,6 +1694,7 @@ static int digi_read_inb_callback(struct urb *urb)return -1 ; } + tty =tty_port_tty_get (&port->port);spin_lock (&priv->dp_port_lock);/* check for throttle; if set, do not resubmit read urb */
@@ -1735,6 +1738,7 @@ static int digi_read_inb_callback(struct urb *urb) } }spin_unlock (&priv->dp_port_lock); +tty_kref_put (tty);if (opcode ==DIGI_CMD_RECEIVE_DISABLE )dbg ("%s: got RECEIVE_DISABLE" , __func__);
@@ -1760,6 +1764,7 @@ static int digi_read_oob_callback(struct urb *urb)struct usb_serial_port *port = urb->context;struct usb_serial *serial = port->serial; +struct tty_struct *tty;struct digi_port *priv =usb_get_serial_port_data (port);int opcode, line, status, val;int i;
@@ -1787,10 +1792,11 @@ static int digi_read_oob_callback(struct urb *urb)if (priv ==NULL )return -1 ; + tty =tty_port_tty_get (&port->port); rts =0 ;if (port->port.count) - rts = port->port.tty->termios->c_cflag &CRTSCTS ; - + rts = tty->termios->c_cflag &CRTSCTS ; +if (opcode ==DIGI_CMD_READ_INPUT_SIGNALS ) {spin_lock (&priv->dp_port_lock);/* convert from digi flags to termiox flags */
@@ -1798,14 +1804,14 @@ static int digi_read_oob_callback(struct urb *urb) priv->dp_modem_signals |=TIOCM_CTS ;/* port must be open to use tty struct */ if (rts) { - port->port.tty->hw_stopped =0 ; + tty->hw_stopped =0 ;digi_wakeup_write (port); } }else { priv->dp_modem_signals &= ~TIOCM_CTS ;/* port must be open to use tty struct */ if (rts) - port->port.tty->hw_stopped =1 ; + tty->hw_stopped =1 ; }if (val &DIGI_READ_INPUT_SIGNALS_DSR ) priv->dp_modem_signals |=TIOCM_DSR ;
@@ -1830,6 +1836,7 @@ static int digi_read_oob_callback(struct urb *urb) }else if (opcode ==DIGI_CMD_IFLUSH_FIFO ) {wake_up_interruptible (&priv->dp_flush_wait); } +tty_kref_put (tty); }return 0 ;
drivers/usb/serial/empeg.c +4 -4
@@ -33,9 +33,8 @@* Moved MOD_DEC_USE_COUNT to end of empeg_close(). * * (12/03/2000) gb -* Added port->port.tty->ldisc.set_termios(port->port.tty, NULL) to -* empeg_open(). This notifies the tty driver that the termios have -* changed. +* Added tty->ldisc.set_termios(port, tty, NULL) to empeg_open(). +* This notifies the tty driver that the termios have changed. * * (11/13/2000) gb * Moved tty->low_latency = 1 from empeg_read_bulk_callback() to
@@ -354,7 +353,7 @@ static void empeg_read_bulk_callback(struct urb *urb)usb_serial_debug_data (debug, &port->dev, __func__, urb->actual_length, data); - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (urb->actual_length) {tty_buffer_request_room (tty, urb->actual_length);
@@ -362,6 +361,7 @@ static void empeg_read_bulk_callback(struct urb *urb)tty_flip_buffer_push (tty); bytes_in += urb->actual_length; } +tty_kref_put (tty);/* Continue trying to always read */ usb_fill_bulk_urb(
drivers/usb/serial/ftdi_sio.c +11 -8
@@ -1808,7 +1808,7 @@ static void ftdi_read_bulk_callback(struct urb *urb)if (port->port.count <=0 )return ; - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (!tty) {dbg ("%s - bad tty pointer - exiting" , __func__);return ;
@@ -1817,7 +1817,7 @@ static void ftdi_read_bulk_callback(struct urb *urb) priv =usb_get_serial_port_data (port);if (!priv) {dbg ("%s - bad port private data pointer - exiting" , __func__); -return ; + goto out; }if (urb != port->read_urb)
@@ -1827,7 +1827,7 @@ static void ftdi_read_bulk_callback(struct urb *urb)/* This will happen at close every time so it is a dbg not an err */ dbg ("(this is ok on close) nonzero read bulk status received: %d" , status); -return ; + goto out; }/* count data bytes, but not status bytes */
@@ -1838,7 +1838,8 @@ static void ftdi_read_bulk_callback(struct urb *urb)spin_unlock_irqrestore (&priv->rx_lock, flags);ftdi_process_read (&priv->rx_work.work); - +out: +tty_kref_put (tty); }/* ftdi_read_bulk_callback */
@@ -1863,7 +1864,7 @@ static void ftdi_process_read(struct work_struct *work)if (port->port.count <=0 )return ; - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (!tty) {dbg ("%s - bad tty pointer - exiting" , __func__);return ;
@@ -1872,13 +1873,13 @@ static void ftdi_process_read(struct work_struct *work) priv =usb_get_serial_port_data (port);if (!priv) {dbg ("%s - bad port private data pointer - exiting" , __func__); -return ; + goto out; } urb = port->read_urb;if (!urb) {dbg ("%s - bad read_urb pointer - exiting" , __func__); -return ; + goto out; } data = urb->transfer_buffer;
@@ -2020,7 +2021,7 @@ static void ftdi_process_read(struct work_struct *work)schedule_delayed_work (&priv->rx_work,1 ); else dbg("%s - port is closed", __func__); -return ; + goto out; }/* urb is completely processed */
@@ -2041,6 +2042,8 @@ static void ftdi_process_read(struct work_struct *work)err ("%s - failed resubmitting read urb, error %d" , __func__, result); } +out: +tty_kref_put (tty); }/* ftdi_process_read */
drivers/usb/serial/garmin_gps.c +2 -1
@@ -276,7 +276,7 @@ static inline int isAbortTrfCmnd(const unsigned char *buf)static void send_to_tty (struct usb_serial_port *port,char *data,unsigned int actual_length) { -struct tty_struct *tty = port->port.tty; +struct tty_struct *tty =tty_port_tty_get (&port->port);if (tty && actual_length) {
@@ -287,6 +287,7 @@ static void send_to_tty(struct usb_serial_port *port,tty_insert_flip_string (tty, data, actual_length);tty_flip_buffer_push (tty); } +tty_kref_put (tty); }
drivers/usb/serial/generic.c +2 -1
@@ -330,7 +330,7 @@ static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags)static void flush_and_resubmit_read_urb (struct usb_serial_port *port) {struct urb *urb = port->read_urb; -struct tty_struct *tty = port->port.tty; +struct tty_struct *tty =tty_port_tty_get (&port->port);int room;/* Push data to tty */
@@ -341,6 +341,7 @@ static void flush_and_resubmit_read_urb(struct usb_serial_port *port)tty_flip_buffer_push (tty); } } +tty_kref_put (tty);resubmit_read_urb (port,GFP_ATOMIC ); }
drivers/usb/serial/io_edgeport.c +29 -14
105 lines not on this page · raw message
drivers/usb/serial/io_ti.c +19 -7
@@ -572,7 +572,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout, int flush) {int baud_rate; -struct tty_struct *tty = port->port->port.tty; +struct tty_struct *tty =tty_port_tty_get (&port->port->port);wait_queue_t wait;unsigned long flags;
@@ -599,6 +599,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,if (flush)edge_buf_clear (port->ep_out_buf);spin_unlock_irqrestore (&port->ep_lock, flags); +tty_kref_put (tty);/* wait for data to drain from the device */ timeout += jiffies;
@@ -1554,7 +1555,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)/* Save the new modem status */ edge_port->shadow_msr = msr &0xf0 ; - tty = edge_port->port->port.tty; + tty =tty_port_tty_get (&edge_port->port->port);/* handle CTS flow control */ if (tty &&C_CRTSCTS (tty)) {if (msr &EDGEPORT_MSR_CTS ) {
@@ -1564,6 +1565,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr) tty->hw_stopped =1 ; } } +tty_kref_put (tty);return ; }
@@ -1574,6 +1576,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,struct async_icount *icount;__u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR |LSR_PAR_ERR |LSR_FRM_ERR |LSR_BREAK )); +struct tty_struct *tty;dbg ("%s - %02x" , __func__, new_lsr);
@@ -1587,8 +1590,13 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data, new_lsr &= (__u8)(LSR_OVER_ERR |LSR_BREAK );/* Place LSR data byte into Rx buffer */ -if (lsr_data && edge_port->port->port.tty) -edge_tty_recv (&edge_port->port->dev, edge_port->port->port.tty, &data,1 ); +if (lsr_data) { + tty =tty_port_tty_get (&edge_port->port->port); +if (tty) { +edge_tty_recv (&edge_port->port->dev, tty, &data,1 ); +tty_kref_put (tty); + } + }/* update input line counters */ icount = &edge_port->icount;
@@ -1749,7 +1757,7 @@ static void edge_bulk_in_callback(struct urb *urb) ++data; } - tty = edge_port->port->port.tty; + tty =tty_port_tty_get (&edge_port->port->port);if (tty && urb->actual_length) {usb_serial_debug_data (debug, &edge_port->port->dev, __func__, urb->actual_length, data);
@@ -1761,6 +1769,7 @@ static void edge_bulk_in_callback(struct urb *urb) urb->actual_length); edge_port->icount.rx += urb->actual_length; } +tty_kref_put (tty); exit:/* continue read unless stopped */
@@ -1796,6 +1805,7 @@ static void edge_bulk_out_callback(struct urb *urb)struct usb_serial_port *port = urb->context;struct edgeport_port *edge_port =usb_get_serial_port_data (port);int status = urb->status; +struct tty_struct *tty;dbg ("%s - port %d" , __func__, port->number);
@@ -1818,7 +1828,9 @@ static void edge_bulk_out_callback(struct urb *urb) }/* send any buffered data */ -edge_send (port->port.tty); + tty =tty_port_tty_get (&port->port); +edge_send (tty); +tty_kref_put (tty); } static int edge_open(struct tty_struct *tty,
@@ -1876,7 +1888,7 @@ static int edge_open(struct tty_struct *tty,/* set up the port settings */ if (tty) -edge_set_termios (tty, port, port->port.tty->termios); +edge_set_termios (tty, port, tty->termios);/* open up the port */
drivers/usb/serial/ipaq.c +2 -1
@@ -764,13 +764,14 @@ static void ipaq_read_bulk_callback(struct urb *urb)usb_serial_debug_data (debug, &port->dev, __func__, urb->actual_length, data); - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (tty && urb->actual_length) {tty_buffer_request_room (tty, urb->actual_length);tty_insert_flip_string (tty, data, urb->actual_length);tty_flip_buffer_push (tty); bytes_in += urb->actual_length; } +tty_kref_put (tty);/* Continue trying to always read */ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
drivers/usb/serial/ipw.c +2 -1
@@ -170,12 +170,13 @@ static void ipw_read_bulk_callback(struct urb *urb)usb_serial_debug_data (debug, &port->dev, __func__, urb->actual_length, data); - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (tty && urb->actual_length) {tty_buffer_request_room (tty, urb->actual_length);tty_insert_flip_string (tty, data, urb->actual_length);tty_flip_buffer_push (tty); } +tty_kref_put (tty);/* Continue trying to always read */ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
drivers/usb/serial/ir-usb.c +2 -1
@@ -465,11 +465,12 @@ static void ir_read_bulk_callback(struct urb *urb) ir_baud = *data &0x0f ;usb_serial_debug_data (debug, &port->dev, __func__, urb->actual_length, data); - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (tty_buffer_request_room (tty, urb->actual_length -1 )) {tty_insert_flip_string (tty, data+1 , urb->actual_length -1 );tty_flip_buffer_push (tty); } +tty_kref_put (tty);/* * No break here.
drivers/usb/serial/iuu_phoenix.c +2 -1
@@ -629,13 +629,14 @@ static void read_buf_callback(struct urb *urb) }dbg ("%s - %i chars to write" , __func__, urb->actual_length); - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (data ==NULL )dbg ("%s - data is NULL !!!" , __func__);if (tty && urb->actual_length && data) {tty_insert_flip_string (tty, data, urb->actual_length);tty_flip_buffer_push (tty); } +tty_kref_put (tty);iuu_led_activity_on (urb); }
drivers/usb/serial/keyspan.c +40 -37
189 lines not on this page · raw message
drivers/usb/serial/keyspan_pda.c +10 -6
@@ -172,8 +172,9 @@ static void keyspan_pda_wakeup_write(struct work_struct *work)struct keyspan_pda_private *priv = container_of(work, struct keyspan_pda_private, wakeup_work);struct usb_serial_port *port = priv->port; - -tty_wakeup (port->port.tty); +struct tty_struct *tty =tty_port_tty_get (&port->port); +tty_wakeup (tty); +tty_kref_put (tty); }static void keyspan_pda_request_unthrottle (struct work_struct *work)
@@ -205,7 +206,7 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work)static void keyspan_pda_rx_interrupt (struct urb *urb) {struct usb_serial_port *port = urb->context; -struct tty_struct *tty = port->port.tty; +struct tty_struct *tty =tty_port_tty_get (&port->port);unsigned char *data = urb->transfer_buffer;int retval;int status = urb->status;
@@ -222,7 +223,7 @@ static void keyspan_pda_rx_interrupt(struct urb *urb)/* this urb is terminated, clean up */ dbg ("%s - urb shutting down with status: %d" , __func__, status); -return ; + goto out;default :dbg ("%s - nonzero urb status received: %d" , __func__, status);
@@ -261,8 +262,11 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) exit: retval =usb_submit_urb (urb,GFP_ATOMIC );if (retval) -err ("%s - usb_submit_urb failed with result %d" , - __func__, retval); +dev_err (&port->dev, +"%s - usb_submit_urb failed with result %d" , + __func__, retval); +out: +tty_kref_put (tty); }
drivers/usb/serial/kl5kusb105.c +2 -1
@@ -658,7 +658,7 @@ static void klsi_105_read_bulk_callback(struct urb *urb) }else {int bytes_sent = ((__u8 *) data)[0 ] + ((unsigned int ) ((__u8 *) data)[1 ] <<8 ); - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);/* we should immediately resubmit the URB, before attempting * to pass the data on to the tty layer. But that needs locking * against re-entry an then mixed-up data because of
@@ -679,6 +679,7 @@ static void klsi_105_read_bulk_callback(struct urb *urb)tty_buffer_request_room (tty, bytes_sent);tty_insert_flip_string (tty, data +2 , bytes_sent);tty_flip_buffer_push (tty); +tty_kref_put (tty);/* again lockless, but debug info only */ priv->bytes_in += bytes_sent;
drivers/usb/serial/kobil_sct.c +2 -1
@@ -383,7 +383,7 @@ static void kobil_read_int_callback(struct urb *urb)return ; } - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (urb->actual_length) {/* BEGIN DEBUG */
@@ -405,6 +405,7 @@ static void kobil_read_int_callback(struct urb *urb)tty_insert_flip_string (tty, data, urb->actual_length);tty_flip_buffer_push (tty); } +tty_kref_put (tty);/* someone sets the dev to 0 if the close method has been called */ port->interrupt_in_urb->dev = port->serial->dev;
drivers/usb/serial/mct_u232.c +4 -2
@@ -563,10 +563,11 @@ static void mct_u232_read_int_callback(struct urb *urb)* Work-a-round: handle the 'usual' bulk-in pipe here */ if (urb->transfer_buffer_length >2 ) { - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (urb->actual_length) {tty_insert_flip_string (tty, data, urb->actual_length);tty_flip_buffer_push (tty); +tty_kref_put (tty); } goto exit; }
@@ -591,7 +592,7 @@ static void mct_u232_read_int_callback(struct urb *urb)* to look in to this before committing any code. */ if (priv->last_lsr &MCT_U232_LSR_ERR ) { - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);/* Overrun Error */ if (priv->last_lsr &MCT_U232_LSR_OE ) { }
@@ -604,6 +605,7 @@ static void mct_u232_read_int_callback(struct urb *urb)/* Break Indicator */ if (priv->last_lsr &MCT_U232_LSR_BI ) { } + tty_kref_put(tty); }#endif spin_unlock_irqrestore (&priv->lock, flags);
drivers/usb/serial/mos7720.c +4 -32
@@ -216,12 +216,13 @@ static void mos7720_bulk_in_callback(struct urb *urb) data = urb->transfer_buffer; - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (tty && urb->actual_length) {tty_buffer_request_room (tty, urb->actual_length);tty_insert_flip_string (tty, data, urb->actual_length);tty_flip_buffer_push (tty); } +tty_kref_put (tty);if (!port->read_urb) {dbg ("URB KILLED !!!" );
@@ -262,10 +263,11 @@ static void mos7720_bulk_out_data_callback(struct urb *urb)dbg ("Entering ........." ); - tty = mos7720_port->port->port.tty; + tty =tty_port_tty_get (&mos7720_port->port->port);if (tty && mos7720_port->open)tty_wakeup (tty); +tty_kref_put (tty); }/*
@@ -1267,29 +1269,6 @@ static int get_lsr_info(struct tty_struct *tty,return 0 ; } -/* -* get_number_bytes_avail - get number of bytes available -* -* Purpose: Let user call ioctl to get the count of number of bytes available. -*/ -static int get_number_bytes_avail (struct moschip_port *mos7720_port, -unsigned int __user *value) -{ -unsigned int result =0 ; -struct tty_struct *tty = mos7720_port->port->port.tty; - -if (!tty) -return -ENOIOCTLCMD ; - - result = tty->read_cnt; - -dbg ("%s(%d) = %d" , __func__, mos7720_port->port->number, result); -if (copy_to_user (value, &result,sizeof (int ))) -return -EFAULT ; - -return -ENOIOCTLCMD ; -} -static int set_modem_info (struct moschip_port *mos7720_port,unsigned int cmd,unsigned int __user *value) {
@@ -1409,13 +1388,6 @@ static int mos7720_ioctl(struct tty_struct *tty, struct file *file,dbg ("%s - port %d, cmd = 0x%x" , __func__, port->number, cmd);switch (cmd) { -case TIOCINQ : -/* return number of bytes available */ -dbg ("%s (%d) TIOCINQ" , __func__, port->number); -return get_number_bytes_avail (mos7720_port, - (unsigned int __user *)arg); -break ; -case TIOCSERGETLSR :dbg ("%s (%d) TIOCSERGETLSR" , __func__, port->number); return get_lsr_info(tty, mos7720_port,
drivers/usb/serial/mos7840.c +4 -3
@@ -709,12 +709,13 @@ static void mos7840_bulk_in_callback(struct urb *urb)dbg ("%s" ,"Entering ........... \n" );if (urb->actual_length) { - tty = mos7840_port->port->port.tty; + tty =tty_port_tty_get (&mos7840_port->port->port);if (tty) {tty_buffer_request_room (tty, urb->actual_length);tty_insert_flip_string (tty, data, urb->actual_length);dbg (" %s \n" , data);tty_flip_buffer_push (tty); +tty_kref_put (tty); } mos7840_port->icount.rx += urb->actual_length;smp_wmb ();
@@ -773,10 +774,10 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)dbg ("%s \n" ,"Entering ........." ); - tty = mos7840_port->port->port.tty; - + tty =tty_port_tty_get (&mos7840_port->port->port);if (tty && mos7840_port->open)tty_wakeup (tty); +tty_kref_put (tty); }
drivers/usb/serial/navman.c +2 -1
@@ -64,12 +64,13 @@ static void navman_read_int_callback(struct urb *urb)usb_serial_debug_data (debug, &port->dev, __func__, urb->actual_length, data); - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (tty && urb->actual_length) {tty_buffer_request_room (tty, urb->actual_length);tty_insert_flip_string (tty, data, urb->actual_length);tty_flip_buffer_push (tty); } +tty_kref_put (tty); exit: result =usb_submit_urb (urb,GFP_ATOMIC );
drivers/usb/serial/omninet.c +6 -4
@@ -172,7 +172,7 @@ static int omninet_open(struct tty_struct *tty,dbg ("%s - port %d" , __func__, port->number); wport = serial->port[1 ]; - wport->port.tty = tty;/* FIXME */ +tty_port_tty_set (&wport->port, tty);/* Start reading from the device */ usb_fill_bulk_urb(port->read_urb, serial->dev,
@@ -229,9 +229,11 @@ static void omninet_read_bulk_callback(struct urb *urb) }if (urb->actual_length && header->oh_len) { -tty_insert_flip_string (port->port.tty, - data +OMNINET_DATAOFFSET , header->oh_len); -tty_flip_buffer_push (port->port.tty); +struct tty_struct *tty =tty_port_tty_get (&port->port); +tty_insert_flip_string (tty, data +OMNINET_DATAOFFSET , + header->oh_len); +tty_flip_buffer_push (tty); +tty_kref_put (tty); }/* Continue trying to always read */
drivers/usb/serial/option.c +11 -7
@@ -571,14 +571,14 @@ static void option_indat_callback(struct urb *urb)dbg ("%s: nonzero status: %d on endpoint %02x." , __func__, status, endpoint); }else { - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (urb->actual_length) {tty_buffer_request_room (tty, urb->actual_length);tty_insert_flip_string (tty, data, urb->actual_length);tty_flip_buffer_push (tty); - }else { + }else dbg ("%s: empty read urb received" , __func__); - } +tty_kref_put (tty);/* Resubmit urb so we continue receiving */ if (port->port.count && status != -ESHUTDOWN ) {
@@ -647,9 +647,13 @@ static void option_instat_callback(struct urb *urb) portdata->dsr_state = ((signals &0x02 ) ?1 :0 ); portdata->ri_state = ((signals &0x08 ) ?1 :0 ); -if (port->port.tty && !C_CLOCAL (port->port.tty) && - old_dcd_state && !portdata->dcd_state) -tty_hangup (port->port.tty); +if (old_dcd_state && !portdata->dcd_state) { +struct tty_struct *tty = +tty_port_tty_get (&port->port); +if (tty && !C_CLOCAL (tty)) +tty_hangup (tty); +tty_kref_put (tty); + } }else {dbg ("%s: type %x req %x" , __func__, req_pkt->bRequestType, req_pkt->bRequest);
@@ -793,7 +797,7 @@ static void option_close(struct tty_struct *tty,for (i =0 ; i <N_OUT_URB ; i++)usb_kill_urb (portdata->out_urbs[i]); } - port->port.tty =NULL ;/* FIXME */ +tty_port_tty_set (&port->port,NULL ); }/* Helper functions used by option_setup_urbs */
drivers/usb/serial/oti6858.c +2 -1
@@ -1002,11 +1002,12 @@ static void oti6858_read_bulk_callback(struct urb *urb)return ; } - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (tty !=NULL && urb->actual_length >0 ) {tty_insert_flip_string (tty, data, urb->actual_length);tty_flip_buffer_push (tty); } +tty_kref_put (tty);/* schedule the interrupt urb if we are still open */ if (port->port.count !=0 ) {
drivers/usb/serial/pl2303.c +2 -2
@@ -1057,7 +1057,7 @@ static void pl2303_read_bulk_callback(struct urb *urb) tty_flag =TTY_FRAME ;dbg ("%s - tty_flag = %d" , __func__, tty_flag); - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (tty && urb->actual_length) {tty_buffer_request_room (tty, urb->actual_length +1 );/* overrun is special, not associated with a char */
@@ -1067,7 +1067,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)tty_insert_flip_char (tty, data[i], tty_flag);tty_flip_buffer_push (tty); } - +tty_kref_put (tty);/* Schedule the next read _if_ we are still open */ if (port->port.count) { urb->dev = port->serial->dev;
drivers/usb/serial/safe_serial.c +7 -4
@@ -217,6 +217,7 @@ static void safe_read_bulk_callback(struct urb *urb)struct usb_serial_port *port = urb->context;unsigned char *data = urb->transfer_buffer;unsigned char length = urb->actual_length; +struct tty_struct *tty;int result;int status = urb->status;
@@ -242,6 +243,7 @@ static void safe_read_bulk_callback(struct urb *urb) printk("\n"); }#endif + tty =tty_port_tty_get (&port->port);if (safe) {__u16 fcs; fcs =fcs_compute10 (data, length,CRC10_INITFCS );
@@ -250,9 +252,9 @@ static void safe_read_bulk_callback(struct urb *urb)if (actual_length <= (length -2 )) {info ("%s - actual: %d" , __func__, actual_length); -tty_insert_flip_string (port->port.tty, +tty_insert_flip_string (tty, data, actual_length); -tty_flip_buffer_push (port->port.tty); +tty_flip_buffer_push (tty); }else {err ("%s - inconsistent lengths %d:%d" , __func__, actual_length, length);
@@ -261,9 +263,10 @@ static void safe_read_bulk_callback(struct urb *urb)err ("%s - bad CRC %x" , __func__, fcs); } }else { -tty_insert_flip_string (port->port.tty, data, length); -tty_flip_buffer_push (port->port.tty); +tty_insert_flip_string (tty, data, length); +tty_flip_buffer_push (tty); } +tty_kref_put (tty);/* Continue trying to always read */ usb_fill_bulk_urb(urb, port->serial->dev,
drivers/usb/serial/sierra.c +9 -7
@@ -440,14 +440,14 @@ static void sierra_indat_callback(struct urb *urb)dbg ("%s: nonzero status: %d on endpoint %02x." , __func__, status, endpoint); }else { - tty = port->port.tty;if (urb->actual_length) { + tty =tty_port_tty_get (&port->port);tty_buffer_request_room (tty, urb->actual_length);tty_insert_flip_string (tty, data, urb->actual_length);tty_flip_buffer_push (tty); - }else { +tty_kref_put (tty); + }else dbg ("%s: empty read urb received" , __func__); - }/* Resubmit urb so we continue receiving */ if (port->port.count && status != -ESHUTDOWN ) {
@@ -485,6 +485,7 @@ static void sierra_instat_callback(struct urb *urb)unsigned char signals = *((unsigned char *) urb->transfer_buffer +sizeof (struct usb_ctrlrequest )); +struct tty_struct *tty;dbg ("%s: signal x%x" , __func__, signals);
@@ -494,9 +495,11 @@ static void sierra_instat_callback(struct urb *urb) portdata->dsr_state = ((signals &0x02 ) ?1 :0 ); portdata->ri_state = ((signals &0x08 ) ?1 :0 ); -if (port->port.tty && !C_CLOCAL (port->port.tty) && + tty =tty_port_tty_get (&port->port); +if (tty && !C_CLOCAL (tty) && old_dcd_state && !portdata->dcd_state) -tty_hangup (port->port.tty); +tty_hangup (tty); +tty_kref_put (tty); }else {dbg ("%s: type %x req %x" , __func__, req_pkt->bRequestType, req_pkt->bRequest);
@@ -616,8 +619,7 @@ static void sierra_close(struct tty_struct *tty, }usb_kill_urb (port->interrupt_in_urb); - - port->port.tty =NULL ;/* FIXME */ +tty_port_tty_set (&port->port,NULL ); }static int sierra_startup (struct usb_serial *serial)
drivers/usb/serial/spcp8x5.c +2 -1
@@ -755,7 +755,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb) tty_flag =TTY_FRAME ;dev_dbg (&port->dev,"tty_flag = %d\n" , tty_flag); - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (tty && urb->actual_length) {tty_buffer_request_room (tty, urb->actual_length +1 );/* overrun is special, not associated with a char */
@@ -765,6 +765,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb)tty_insert_flip_char (tty, data[i], tty_flag);tty_flip_buffer_push (tty); } +tty_kref_put (tty);/* Schedule the next read _if_ we are still open */ if (port->port.count) {
drivers/usb/serial/ti_usb_3410_5052.c +23 -21
130 lines not on this page · raw message
drivers/usb/serial/usb-serial.c +15 -9
@@ -214,7 +214,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp)/* set up our port structure making the tty driver * remember our port object, and us it */ tty->driver_data = port; - port->port.tty = tty; +tty_port_tty_set (&port->port, tty);if (port->port.count ==1 ) {
@@ -246,7 +246,7 @@ bailout_module_put: bailout_mutex_unlock: port->port.count =0 ; tty->driver_data =NULL ; - port->port.tty =NULL ; +tty_port_tty_set (&port->port,NULL );mutex_unlock (&port->mutex); bailout_kref_put:usb_serial_put (serial);
@@ -276,10 +276,11 @@ static void serial_close(struct tty_struct *tty, struct file *filp) port->serial->type->close (tty, port, filp);if (port->port.count == (port->console?1 :0 )) { -if (port->port.tty) { -if (port->port.tty->driver_data) - port->port.tty->driver_data =NULL ; - port->port.tty =NULL ; +struct tty_struct *tty =tty_port_tty_get (&port->port); +if (tty) { +if (tty->driver_data) + tty->driver_data =NULL ; +tty_port_tty_set (&port->port,NULL ); } }
@@ -508,11 +509,12 @@ static void usb_serial_port_work(struct work_struct *work)if (!port)return ; - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (!tty)return ;tty_wakeup (tty); +tty_kref_put (tty); }static void port_release (struct device *dev)
@@ -819,6 +821,7 @@ int usb_serial_probe(struct usb_interface *interface, port =kzalloc (sizeof (struct usb_serial_port ),GFP_KERNEL );if (!port) goto probe_error; +tty_port_init (&port->port); port->serial = serial;spin_lock_init (&port->lock);mutex_init (&port->mutex);
@@ -1040,8 +1043,11 @@ void usb_serial_disconnect(struct usb_interface *interface)for (i =0 ; i < serial->num_ports; ++i) { port = serial->port[i];if (port) { -if (port->port.tty) -tty_hangup (port->port.tty); +struct tty_struct *tty =tty_port_tty_get (&port->port); +if (tty) { +tty_hangup (tty); +tty_kref_put (tty); + }kill_traffic (port); } }
drivers/usb/serial/visor.c +11 -7
@@ -499,7 +499,7 @@ static void visor_read_bulk_callback(struct urb *urb)int status = urb->status;struct tty_struct *tty;int result; -int available_room; +int available_room =0 ;dbg ("%s - port %d" , __func__, port->number);
@@ -512,13 +512,17 @@ static void visor_read_bulk_callback(struct urb *urb)usb_serial_debug_data (debug, &port->dev, __func__, urb->actual_length, data); - tty = port->port.tty; -if (tty && urb->actual_length) { - available_room =tty_buffer_request_room (tty, +if (urb->actual_length) { + tty =tty_port_tty_get (&port->port); +if (tty) { + available_room =tty_buffer_request_room (tty, urb->actual_length); -if (available_room) { -tty_insert_flip_string (tty, data, available_room); -tty_flip_buffer_push (tty); +if (available_room) { +tty_insert_flip_string (tty, data, + available_room); +tty_flip_buffer_push (tty); + } +tty_kref_put (tty); }spin_lock (&priv->lock); priv->bytes_in += available_room;
drivers/usb/serial/whiteheat.c +5 -3
@@ -1481,7 +1481,7 @@ static void rx_data_softint(struct work_struct *work)struct whiteheat_private *info = container_of(work, struct whiteheat_private, rx_work);struct usb_serial_port *port = info->port; -struct tty_struct *tty = port->port.tty; +struct tty_struct *tty =tty_port_tty_get (&port->port);struct whiteheat_urb_wrap *wrap;struct urb *urb;unsigned long flags;
@@ -1493,7 +1493,7 @@ static void rx_data_softint(struct work_struct *work)spin_lock_irqsave (&info->lock, flags);if (info->flags &THROTTLED ) {spin_unlock_irqrestore (&info->lock, flags); -return ; + goto out; }list_for_each_safe (tmp, tmp2, &info->rx_urb_q) {
@@ -1513,7 +1513,7 @@ static void rx_data_softint(struct work_struct *work)spin_unlock_irqrestore (&info->lock, flags);tty_flip_buffer_push (tty);schedule_work (&info->rx_work); -return ; + goto out; }tty_insert_flip_string (tty, urb->transfer_buffer, len); sent += len;
@@ -1536,6 +1536,8 @@ static void rx_data_softint(struct work_struct *work)if (sent)tty_flip_buffer_push (tty); +out: +tty_kref_put (tty); }
include/linux/tty.h +3 -0
@@ -182,6 +182,7 @@ struct signal_struct;struct tty_port {struct tty_struct *tty;/* Back pointer */ +spinlock_t lock;/* Lock protecting tty field */ int blocked_open;/* Waiting to open */ int count;/* Usage count */ wait_queue_head_t open_wait;/* Open waiters */
@@ -405,6 +406,8 @@ extern int tty_write_lock(struct tty_struct *tty, int ndelay);extern void tty_port_init (struct tty_port *port);extern int tty_port_alloc_xmit_buf (struct tty_port *port);extern void tty_port_free_xmit_buf (struct tty_port *port); +extern struct tty_struct *tty_port_tty_get (struct tty_port *port); +extern void tty_port_tty_set (struct tty_port *port,struct tty_struct *tty);extern int tty_register_ldisc (int disc,struct tty_ldisc_ops *new_ldisc);extern int tty_unregister_ldisc (int disc);
Re: [PATCH 38/76] tty: usb-serial krefs
Quoted 4 lines · Alan Cox
Use kref in the USB serial drivers so that we don't free tty structures from under the URB receive handlers as has historically been the case if you were unlucky. This also gives us a framework for general tty drivers to use
tty_portobjects and refcount.
Should we be calling kref_get() and kref_put() in interrupt context? Could we just get the reference in open and then put in close when we are done with it for each driver?
thanks,
greg k-h
Re: [PATCH 38/76] tty: usb-serial krefs
Quoted 3 lines · Greg KH
Should we be calling
kref_get()andkref_put()in interrupt context? Could we just get the reference in open and then put in close when we are done with it for each driver?
That depends how you handle hangups and interrupt synchronization. If you can be sure you will get no more interrupts before you drop the reference in close/hangup then yes that should be fine. In particular watch out for the fact that hangup/close/re-open can run pretty much in parallel with cases like
close called by user
interrupted by carrier drop causing hangup
in parallel another open begins and blocks waiting a close
(Obviously for hotplug some further care is needed on the unplug paths)
Right now USB serial doesn't actually address all those cases anyway I suspect. I wasn't going to attack that until I had a common tty_port and tty_port code to do all that work rather than trying to fix each group of drivers.
Alan
Greg KH
Acked-by Greg Kroah-HartmanRe: [PATCH 38/76] tty: usb-serial krefs
Quoted 14 lines · Alan Cox
Quoted 3 lines · Greg KH
Should we be calling
kref_get()andkref_put()in interrupt context? Could we just get the reference in open and then put in close when we are done with it for each driver?That depends how you handle hangups and interrupt synchronization. If you can be sure you will get no more interrupts before you drop the reference in close/hangup then yes that should be fine. In particular watch out for the fact that hangup/close/re-open can run pretty much in parallel with cases like
close called by user
interrupted by carrier drop causing hangup
Quoted 7 lines
in parallel another open begins and blocks waiting a close
(Obviously for hotplug some further care is needed on the unplug paths)
Right now USB serial doesn't actually address all those cases anyway I suspect. I wasn't going to attack that until I had a common
tty_portandtty_portcode to do all that work rather than trying to fix each group of drivers.
Ok, fair enough, we can do further refinement later. All of these changes look great to me, thanks for doing them. Feel free to put a:
on the usb-serial ones if you want it.
thanks,
greg k-h
PATCH 39/76 tty: kref usage for isicom and moxa
In reply to Alan CoxRather than blindly keep taking krefs we reorder the code in a few places to pass the tty down to the right place (which is important as from the user side it is not the case that tty == port->tty in all situations). For the irq and related paths use the krefs to stop the tty being freed under us.
---
drivers/char/isicom.c | 61 +++++++++++++++++++++++++------------------------ drivers/char/moxa.c | 61 +++++++++++++++++++++++++++++++------------------ 2 files changed, 69 insertions(+), 53 deletions(-)
drivers/char/isicom.c +31 -30
@@ -421,17 +421,16 @@ static void isicom_tx(unsigned long _data)if (retries >=100 ) goto unlock; + tty =tty_port_tty_get (&port->port); +if (tty ==NULL ) + goto put_unlock; +for (; count >0 ; count--, port++) {/* port not active or tx disabled to force flow control */ if (!(port->port.flags &ASYNC_INITIALIZED ) || !(port->status &ISI_TXOK ))continue ; - tty = port->port.tty; - -if (tty ==NULL ) -continue ; - txcount =min_t (short,TX_SIZE , port->xmit_cnt);if (txcount <=0 || tty->stopped || tty->hw_stopped)continue ;
@@ -489,6 +488,8 @@ static void isicom_tx(unsigned long _data)tty_wakeup (tty); } +put_unlock: +tty_kref_put (tty); unlock:spin_unlock_irqrestore (&isi_card[card].card_lock, flags);/* schedule another tx for hopefully in about 10ms */
@@ -547,7 +548,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)return IRQ_HANDLED ; } - tty = port->port.tty; + tty =tty_port_tty_get (&port->port);if (tty ==NULL ) { word_count = byte_count >>1 ;while (byte_count >1 ) {
@@ -588,7 +589,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) }if (port->port.flags &ASYNC_CTS_FLOW ) { -if (port->port.tty->hw_stopped) { +if (tty->hw_stopped) {if (header &ISI_CTS ) { port->port.tty->hw_stopped =0 ;/* start tx ing */
@@ -597,7 +598,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)tty_wakeup (tty); } }else if (!(header &ISI_CTS )) { - port->port.tty->hw_stopped =1 ; + tty->hw_stopped =1 ;/* stop tx ing */ port->status &= ~(ISI_TXOK |ISI_CTS ); }
@@ -660,24 +661,21 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) }outw (0x0000 , base+0x04 );/* enable interrupts */ spin_unlock (&card->card_lock); +tty_kref_put (tty);return IRQ_HANDLED ; } -static void isicom_config_port (struct isi_port *port) +static void isicom_config_port (struct tty_struct *tty) { +struct isi_port *port = tty->driver_data;struct isi_board *card = port->card; -struct tty_struct *tty;unsigned long baud;unsigned long base = card->base;u16 channel_setup, channel = port->channel, shift_count = card->shift_count;unsigned char flow_ctrl; - tty = port->port.tty; - -if (tty ==NULL ) -return ;/* FIXME: Switch to new tty baud API */ baud =C_BAUD (tty);if (baud &CBAUDEX ) {
@@ -690,7 +688,7 @@ static void isicom_config_port(struct isi_port *port)/* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */ if (baud <1 || baud >4 ) - port->port.tty->termios->c_cflag &= ~CBAUDEX ; + tty->termios->c_cflag &= ~CBAUDEX ;else baud +=15 ; }
@@ -797,8 +795,9 @@ static inline void isicom_setup_board(struct isi_board *bp)spin_unlock_irqrestore (&bp->card_lock, flags); } -static int isicom_setup_port (struct isi_port *port) +static int isicom_setup_port (struct tty_struct *tty) { +struct isi_port *port = tty->driver_data;struct isi_board *card = port->card;unsigned long flags;
@@ -808,8 +807,7 @@ static int isicom_setup_port(struct isi_port *port)return -ENOMEM ;spin_lock_irqsave (&card->card_lock, flags); -if (port->port.tty) -clear_bit (TTY_IO_ERROR , &port->port.tty->flags); +clear_bit (TTY_IO_ERROR , &tty->flags);if (port->port.count ==1 ) card->count++;
@@ -823,7 +821,7 @@ static int isicom_setup_port(struct isi_port *port)InterruptTheCard (card->base); } -isicom_config_port (port); +isicom_config_port (tty); port->port.flags |=ASYNC_INITIALIZED ;spin_unlock_irqrestore (&card->card_lock, flags);
@@ -934,8 +932,8 @@ static int isicom_open(struct tty_struct *tty, struct file *filp) port->port.count++; tty->driver_data = port; - port->port.tty = tty; - error =isicom_setup_port (port); +tty_port_tty_set (&port->port, tty); + error =isicom_setup_port (tty);if (error ==0 ) error =block_til_ready (tty, filp, port);return error;
@@ -955,15 +953,17 @@ static void isicom_shutdown_port(struct isi_port *port)struct isi_board *card = port->card;struct tty_struct *tty; - tty = port->port.tty; + tty =tty_port_tty_get (&port->port); -if (!(port->port.flags &ASYNC_INITIALIZED )) +if (!(port->port.flags &ASYNC_INITIALIZED )) { +tty_kref_put (tty);return ; + }tty_port_free_xmit_buf (&port->port); port->port.flags &= ~ASYNC_INITIALIZED ;/* 3rd October 2000 : Vinayak P Risbud */ - port->port.tty =NULL ; +tty_port_tty_set (&port->port,NULL );/*Fix done by Anil .S on 30-04-2001 remote login through isi port has dtr toggle problem
@@ -1243,9 +1243,10 @@ static int isicom_tiocmset(struct tty_struct *tty, struct file *file,return 0 ; } -static int isicom_set_serial_info (struct isi_port *port, -struct serial_struct __user *info) +static int isicom_set_serial_info (struct tty_struct *tty, +struct serial_struct __user *info) { +struct isi_port *port = tty->driver_data;struct serial_struct newinfo;int reconfig_port;
@@ -1276,7 +1277,7 @@ static int isicom_set_serial_info(struct isi_port *port,if (reconfig_port) {unsigned long flags;spin_lock_irqsave (&port->card->card_lock, flags); -isicom_config_port (port); +isicom_config_port (tty);spin_unlock_irqrestore (&port->card->card_lock, flags); }unlock_kernel ();
@@ -1318,7 +1319,7 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp,return isicom_get_serial_info (port, argp);case TIOCSSERIAL : -return isicom_set_serial_info (port, argp); +return isicom_set_serial_info (tty, argp);default :return -ENOIOCTLCMD ;
@@ -1341,7 +1342,7 @@ static void isicom_set_termios(struct tty_struct *tty,return ;spin_lock_irqsave (&port->card->card_lock, flags); -isicom_config_port (port); +isicom_config_port (tty);spin_unlock_irqrestore (&port->card->card_lock, flags); if ((old_termios->c_cflag & CRTSCTS) &&
@@ -1419,7 +1420,7 @@ static void isicom_hangup(struct tty_struct *tty) port->port.count =0 ; port->port.flags &= ~ASYNC_NORMAL_ACTIVE ; - port->port.tty =NULL ; +tty_port_tty_set (&port->port,NULL );wake_up_interruptible (&port->port.open_wait); }
drivers/char/moxa.c +38 -23
173 lines not on this page · raw message
PATCH 40/76 stallion: Use krefs
In reply to Alan CoxUse tty_port_init and krefs in the stallion drivers to protect us from devices going away underneath us. As with the other drives some rearranging is done to pass the tty structure down properly on the user side.
---
drivers/char/Kconfig | 4 +- drivers/char/istallion.c | 107 +++++++++++++++++++++++++--------------------- drivers/char/stallion.c | 105 ++++++++++++++++++++++++++++----------------- 3 files changed, 123 insertions(+), 93 deletions(-)
drivers/char/Kconfig +2 -2
@@ -350,7 +350,7 @@ config STALDRV config STALLION tristate "Stallion EasyIO or EC8/32 support" - depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI) + depends on STALDRV && (ISA || EISA || PCI) help If you have an EasyIO or EasyConnection 8/32 multiport Stallion card, then this is for you; say Y. Make sure to read
@@ -361,7 +361,7 @@ config STALLION config ISTALLION tristate "Stallion EC8/64, ONboard, Brumby support" - depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI) + depends on STALDRV && (ISA || EISA || PCI) help If you have an EasyConnection 8/64, ONboard, Brumby or Stallion serial multiport card, say Y here. Make sure to read
drivers/char/istallion.c +57 -50
321 lines not on this page · raw message
drivers/char/stallion.c +64 -41
331 lines not on this page · raw message
PATCH 41/76 mxser: Switch to kref tty
In reply to Alan Cox---
drivers/char/mxser.c | 192 +++++++++++++++++++++++++++----------------------- 1 files changed, 103 insertions(+), 89 deletions(-)
drivers/char/mxser.c +103 -89
@@ -610,15 +610,16 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,return 0 ; } -static int mxser_set_baud (struct mxser_port *info,long newspd) +static int mxser_set_baud (struct tty_struct *tty,long newspd) { +struct mxser_port *info = tty->driver_data;int quot =0 , baud;unsigned char cval; -if (!info->port.tty || !info->port.tty->termios) +if (!tty->termios)return -1 ; -if (!(info->ioaddr)) +if (!info->ioaddr)return -1 ;if (newspd > info->max_baud)
@@ -626,13 +627,13 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)if (newspd ==134 ) { quot =2 * info->baud_base /269 ; -tty_encode_baud_rate (info->port.tty,134 ,134 ); +tty_encode_baud_rate (tty,134 ,134 ); }else if (newspd) { quot = info->baud_base / newspd;if (quot ==0 ) quot =1 ; baud = info->baud_base/quot; -tty_encode_baud_rate (info->port.tty, baud, baud); +tty_encode_baud_rate (tty, baud, baud); }else { quot =0 ; }
@@ -658,7 +659,7 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)outb (cval, info->ioaddr +UART_LCR );/* reset DLAB */ #ifdef BOTHER -if (C_BAUD (info->port.tty) ==BOTHER ) { +if (C_BAUD (tty) ==BOTHER ) { quot = info->baud_base % newspd; quot *=8 ;if (quot % newspd > newspd /2 ) {
@@ -679,21 +680,22 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)* This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */ -static int mxser_change_speed (struct mxser_port *info, -struct ktermios *old_termios) +static int mxser_change_speed (struct tty_struct *tty, +struct ktermios *old_termios) { +struct mxser_port *info = tty->driver_data;unsigned cflag, cval, fcr;int ret =0 ;unsigned char status; -if (!info->port.tty || !info->port.tty->termios) +if (!tty->termios)return ret; - cflag = info->port.tty->termios->c_cflag; -if (!(info->ioaddr)) + cflag = tty->termios->c_cflag; +if (!info->ioaddr)return ret; -if (mxser_set_baud_method[info->port.tty->index] ==0 ) -mxser_set_baud (info,tty_get_baud_rate (info->port.tty)); +if (mxser_set_baud_method[tty->index] ==0 ) +mxser_set_baud (tty,tty_get_baud_rate (tty));/* byte size and parity */ switch (cflag &CSIZE ) {
@@ -762,9 +764,9 @@ static int mxser_change_speed(struct mxser_port *info, info->MCR |=UART_MCR_AFE ; }else { status =inb (info->ioaddr +UART_MSR ); -if (info->port.tty->hw_stopped) { +if (tty->hw_stopped) {if (status &UART_MSR_CTS ) { - info->port.tty->hw_stopped =0 ; + tty->hw_stopped =0 ;if (info->type !=PORT_16550A && !info->board->chip_flag) { outb(info->IER & ~UART_IER_THRI,
@@ -774,11 +776,11 @@ static int mxser_change_speed(struct mxser_port *info,outb (info->IER, info->ioaddr +UART_IER ); } -tty_wakeup (info->port.tty); +tty_wakeup (tty); } }else {if (!(status &UART_MSR_CTS )) { - info->port.tty->hw_stopped =1 ; + tty->hw_stopped =1 ;if ((info->type !=PORT_16550A ) && (!info->board->chip_flag)) { info->IER &= ~UART_IER_THRI ;
@@ -804,21 +806,21 @@ static int mxser_change_speed(struct mxser_port *info,* Set up parity check flag */ info->read_status_mask =UART_LSR_OE |UART_LSR_THRE |UART_LSR_DR ; -if (I_INPCK (info->port.tty)) +if (I_INPCK (tty)) info->read_status_mask |=UART_LSR_FE |UART_LSR_PE ; -if (I_BRKINT (info->port.tty) ||I_PARMRK (info->port.tty)) +if (I_BRKINT (tty) ||I_PARMRK (tty)) info->read_status_mask |=UART_LSR_BI ; info->ignore_status_mask =0 ; -if (I_IGNBRK (info->port.tty)) { +if (I_IGNBRK (tty)) { info->ignore_status_mask |=UART_LSR_BI ; info->read_status_mask |=UART_LSR_BI ;/* * If we're ignore parity and break indicators, ignore * overruns too. (For real raw support). */ -if (I_IGNPAR (info->port.tty)) { +if (I_IGNPAR (tty)) { info->ignore_status_mask |=UART_LSR_OE | UART_LSR_PE |
@@ -830,16 +832,16 @@ static int mxser_change_speed(struct mxser_port *info, } }if (info->board->chip_flag) { -mxser_set_must_xon1_value (info->ioaddr,START_CHAR (info->port.tty)); -mxser_set_must_xoff1_value (info->ioaddr,STOP_CHAR (info->port.tty)); -if (I_IXON (info->port.tty)) { +mxser_set_must_xon1_value (info->ioaddr,START_CHAR (tty)); +mxser_set_must_xoff1_value (info->ioaddr,STOP_CHAR (tty)); +if (I_IXON (tty)) {mxser_enable_must_rx_software_flow_control ( info->ioaddr); }else {mxser_disable_must_rx_software_flow_control ( info->ioaddr); } -if (I_IXOFF (info->port.tty)) { +if (I_IXOFF (tty)) {mxser_enable_must_tx_software_flow_control ( info->ioaddr); }else {
@@ -855,7 +857,8 @@ static int mxser_change_speed(struct mxser_port *info,return ret; } -static void mxser_check_modem_status (struct mxser_port *port,int status) +static void mxser_check_modem_status (struct tty_struct *tty, +struct mxser_port *port,int status) {/* update input line counters */ if (status &UART_MSR_TERI )
@@ -874,10 +877,11 @@ static void mxser_check_modem_status(struct mxser_port *port, int status)wake_up_interruptible (&port->port.open_wait); } + tty =tty_port_tty_get (&port->port);if (port->port.flags &ASYNC_CTS_FLOW ) { -if (port->port.tty->hw_stopped) { +if (tty->hw_stopped) {if (status &UART_MSR_CTS ) { - port->port.tty->hw_stopped =0 ; + tty->hw_stopped =0 ;if ((port->type !=PORT_16550A ) && (!port->board->chip_flag)) {
@@ -887,11 +891,11 @@ static void mxser_check_modem_status(struct mxser_port *port, int status)outb (port->IER, port->ioaddr +UART_IER ); } -tty_wakeup (port->port.tty); +tty_wakeup (tty); } }else {if (!(status &UART_MSR_CTS )) { - port->port.tty->hw_stopped =1 ; + tty->hw_stopped =1 ;if (port->type !=PORT_16550A && !port->board->chip_flag) { port->IER &= ~UART_IER_THRI ;
@@ -903,8 +907,9 @@ static void mxser_check_modem_status(struct mxser_port *port, int status) } } -static int mxser_startup (struct mxser_port *info) +static int mxser_startup (struct tty_struct *tty) { +struct mxser_port *info = tty->driver_data;unsigned long page;unsigned long flags;
@@ -921,8 +926,7 @@ static int mxser_startup(struct mxser_port *info) }if (!info->ioaddr || !info->type) { -if (info->port.tty) -set_bit (TTY_IO_ERROR , &info->port.tty->flags); +set_bit (TTY_IO_ERROR , &tty->flags);free_page (page);spin_unlock_irqrestore (&info->slock, flags);return 0 ;
@@ -952,8 +956,8 @@ static int mxser_startup(struct mxser_port *info)if (inb (info->ioaddr +UART_LSR ) ==0xff ) {spin_unlock_irqrestore (&info->slock, flags);if (capable (CAP_SYS_ADMIN )) { -if (info->port.tty) -set_bit (TTY_IO_ERROR , &info->port.tty->flags); +if (tty) +set_bit (TTY_IO_ERROR , &tty->flags);return 0 ; }else return -ENODEV ;
@@ -991,14 +995,13 @@ static int mxser_startup(struct mxser_port *info) (void )inb (info->ioaddr +UART_IIR ); (void )inb (info->ioaddr +UART_MSR ); -if (info->port.tty) -clear_bit (TTY_IO_ERROR , &info->port.tty->flags); +clear_bit (TTY_IO_ERROR , &tty->flags); info->xmit_cnt = info->xmit_head = info->xmit_tail =0 ;/* * and set the speed of the serial port */ -mxser_change_speed (info,NULL ); +mxser_change_speed (tty,NULL ); info->port.flags |=ASYNC_INITIALIZED ;spin_unlock_irqrestore (&info->slock, flags);
@@ -1009,8 +1012,9 @@ static int mxser_startup(struct mxser_port *info)* This routine will shutdown a serial port; interrupts maybe disabled, and * DTR is dropped if the hangup on close termio flag is on. */ -static void mxser_shutdown (struct mxser_port *info) +static void mxser_shutdown (struct tty_struct *tty) { +struct mxser_port *info = tty->driver_data;unsigned long flags;if (!(info->port.flags &ASYNC_INITIALIZED ))
@@ -1035,7 +1039,7 @@ static void mxser_shutdown(struct mxser_port *info) info->IER =0 ;outb (0x00 , info->ioaddr +UART_IER ); -if (!info->port.tty || (info->port.tty->termios->c_cflag &HUPCL )) +if (tty->termios->c_cflag &HUPCL ) info->MCR &= ~(UART_MCR_DTR |UART_MCR_RTS );outb (info->MCR, info->ioaddr +UART_MCR );
@@ -1051,8 +1055,7 @@ static void mxser_shutdown(struct mxser_port *info)/* read data port to reset things */ (void )inb (info->ioaddr +UART_RX ); -if (info->port.tty) -set_bit (TTY_IO_ERROR , &info->port.tty->flags); +set_bit (TTY_IO_ERROR , &tty->flags); info->port.flags &= ~ASYNC_INITIALIZED ;
@@ -1084,14 +1087,14 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)return -ENODEV ; tty->driver_data = info; - info->port.tty = tty; +tty_port_tty_set (&info->port, tty);/* * Start up serial port */ spin_lock_irqsave (&info->slock, flags); info->port.count++;spin_unlock_irqrestore (&info->slock, flags); - retval =mxser_startup (info); + retval =mxser_startup (tty);if (retval)return retval;
@@ -1209,13 +1212,13 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)break ; } } -mxser_shutdown (info); +mxser_shutdown (tty);mxser_flush_buffer (tty);tty_ldisc_flush (tty); tty->closing =0 ; - info->port.tty =NULL ; +tty_port_tty_set (&info->port,NULL );if (info->port.blocked_open) {if (info->port.close_delay)schedule_timeout_interruptible (info->port.close_delay);
@@ -1337,12 +1340,13 @@ static int mxser_chars_in_buffer(struct tty_struct *tty)* friends of mxser_ioctl() * ------------------------------------------------------------ */ -static int mxser_get_serial_info (struct mxser_port *info, +static int mxser_get_serial_info (struct tty_struct *tty,struct serial_struct __user *retinfo) { +struct mxser_port *info = tty->driver_data;struct serial_struct tmp = { .type = info->type, - .line = info->port.tty->index, + .line = tty->index, .port = info->ioaddr, .irq = info->board->irq, .flags = info->port.flags,
@@ -1357,9 +1361,10 @@ static int mxser_get_serial_info(struct mxser_port *info,return 0 ; } -static int mxser_set_serial_info (struct mxser_port *info, +static int mxser_set_serial_info (struct tty_struct *tty,struct serial_struct __user *new_info) { +struct mxser_port *info = tty->driver_data;struct serial_struct new_serial;speed_t baud;unsigned long sl_flags;
@@ -1393,14 +1398,14 @@ static int mxser_set_serial_info(struct mxser_port *info, (new_serial.flags & ASYNC_FLAGS)); info->port.close_delay = new_serial.close_delay *HZ /100 ; info->port.closing_wait = new_serial.closing_wait *HZ /100 ; - info->port.tty->low_latency = - (info->port.flags &ASYNC_LOW_LATENCY ) ?1 :0 ; + tty->low_latency = (info->port.flags &ASYNC_LOW_LATENCY ) + ?1 :0 ;if ((info->port.flags &ASYNC_SPD_MASK ) ==ASYNC_SPD_CUST && (new_serial.baud_base != info->baud_base || new_serial.custom_divisor != info->custom_divisor)) { baud = new_serial.baud_base / new_serial.custom_divisor; -tty_encode_baud_rate (info->port.tty, baud, baud); +tty_encode_baud_rate (tty, baud, baud); } }
@@ -1411,11 +1416,11 @@ static int mxser_set_serial_info(struct mxser_port *info,if (info->port.flags &ASYNC_INITIALIZED ) {if (flags != (info->port.flags &ASYNC_SPD_MASK )) {spin_lock_irqsave (&info->slock, sl_flags); -mxser_change_speed (info,NULL ); +mxser_change_speed (tty,NULL );spin_unlock_irqrestore (&info->slock, sl_flags); } }else - retval =mxser_startup (info); + retval =mxser_startup (tty);return retval; }
@@ -1461,7 +1466,7 @@ static int mxser_tiocmget(struct tty_struct *tty, struct file *file)spin_lock_irqsave (&info->slock, flags); status =inb (info->ioaddr +UART_MSR );if (status &UART_MSR_ANY_DELTA ) -mxser_check_modem_status (info, status); +mxser_check_modem_status (tty, info, status);spin_unlock_irqrestore (&info->slock, flags);return ((control &UART_MCR_RTS ) ?TIOCM_RTS :0 ) | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
@@ -1606,6 +1611,7 @@ static int __init mxser_read_register(int port, unsigned short *regs)static int mxser_ioctl_special (unsigned int cmd,void __user *argp) {struct mxser_port *port; +struct tty_struct *tty;int result, status;unsigned int i, j;int ret =0 ;
@@ -1643,12 +1649,14 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)if (!port->ioaddr) goto copy; + + tty =tty_port_tty_get (&port->port); -if (!port->port.tty || !port->port.tty->termios) +if (!tty || !tty->termios) ms.cflag = port->normal_termios.c_cflag;else - ms.cflag = port->port.tty->termios->c_cflag; - + ms.cflag = tty->termios->c_cflag; +tty_kref_put (tty); status =inb (port->ioaddr +UART_MSR );if (status &UART_MSR_DCD ) ms.dcd =1 ;
@@ -1704,15 +1712,18 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) me->up_txcnt[p] = port->mon_data.up_txcnt; me->modem_status[p] = port->mon_data.modem_status; - me->baudrate[p] =tty_get_baud_rate (port->port.tty); + tty =tty_port_tty_get (&port->port); -if (!port->port.tty || !port->port.tty->termios) { +if (!tty || !tty->termios) { cflag = port->normal_termios.c_cflag; iflag = port->normal_termios.c_iflag; + me->baudrate[p] =tty_termios_baud_rate (&port->normal_termios); }else { - cflag = port->port.tty->termios->c_cflag; - iflag = port->port.tty->termios->c_iflag; + cflag = tty->termios->c_cflag; + iflag = tty->termios->c_iflag; + me->baudrate[p] =tty_get_baud_rate (tty); } +tty_kref_put (tty); me->databits[p] = cflag &CSIZE ; me->stopbits[p] = cflag &CSTOPB ;
@@ -1822,12 +1833,12 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,switch (cmd) {case TIOCGSERIAL :lock_kernel (); - retval =mxser_get_serial_info (info, argp); + retval =mxser_get_serial_info (tty, argp);unlock_kernel ();return retval;case TIOCSSERIAL :lock_kernel (); - retval =mxser_set_serial_info (info, argp); + retval =mxser_set_serial_info (tty, argp);unlock_kernel ();return retval;case TIOCSERGETLSR :/* Get line status register */
@@ -1896,7 +1907,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,lock_kernel (); status =mxser_get_msr (info->ioaddr,1 , tty->index); -mxser_check_modem_status (info, status); +mxser_check_modem_status (tty, info, status); mcr =inb (info->ioaddr +UART_MCR );if (mcr &MOXA_MUST_MCR_XON_FLAG )
@@ -1909,7 +1920,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,else info->mon_data.hold_reason |=NPPI_NOTIFY_XOFFXENT ; -if (info->port.tty->hw_stopped) +if (tty->hw_stopped) info->mon_data.hold_reason |=NPPI_NOTIFY_CTSHOLD ;else info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD ;
@@ -1958,7 +1969,7 @@ static void mxser_stoprx(struct tty_struct *tty) } } -if (info->port.tty->termios->c_cflag &CRTSCTS ) { +if (tty->termios->c_cflag &CRTSCTS ) { info->MCR &= ~UART_MCR_RTS ;outb (info->MCR, info->ioaddr +UART_MCR ); }
@@ -1995,7 +2006,7 @@ static void mxser_unthrottle(struct tty_struct *tty) } } -if (info->port.tty->termios->c_cflag &CRTSCTS ) { +if (tty->termios->c_cflag &CRTSCTS ) { info->MCR |=UART_MCR_RTS ;outb (info->MCR, info->ioaddr +UART_MCR ); }
@@ -2040,7 +2051,7 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termiunsigned long flags;spin_lock_irqsave (&info->slock, flags); -mxser_change_speed (info, old_termios); +mxser_change_speed (tty, old_termios);spin_unlock_irqrestore (&info->slock, flags); if ((old_termios->c_cflag & CRTSCTS) &&
@@ -2138,10 +2149,10 @@ static void mxser_hangup(struct tty_struct *tty)struct mxser_port *info = tty->driver_data;mxser_flush_buffer (tty); -mxser_shutdown (info); +mxser_shutdown (tty); info->port.count =0 ; info->port.flags &= ~ASYNC_NORMAL_ACTIVE ; - info->port.tty =NULL ; +tty_port_tty_set (&info->port,NULL );wake_up_interruptible (&info->port.open_wait); }
@@ -2164,9 +2175,9 @@ static int mxser_rs_break(struct tty_struct *tty, int break_state)return 0 ; } -static void mxser_receive_chars (struct mxser_port *port,int *status) +static void mxser_receive_chars (struct tty_struct *tty, +struct mxser_port *port,int *status) { -struct tty_struct *tty = port->port.tty;unsigned char ch, gdl;int ignored =0 ;int cnt =0 ;
@@ -2174,9 +2185,8 @@ static void mxser_receive_chars(struct mxser_port *port, int *status)int max =256 ; recv_room = tty->receive_room; -if ((recv_room ==0 ) && (!port->ldisc_stop_rx)) +if (recv_room ==0 && !port->ldisc_stop_rx)mxser_stoprx (tty); -if (port->board->chip_flag !=MOXA_OTHER_UART ) {if (*status &UART_LSR_SPECIAL )
@@ -2253,7 +2263,7 @@ intr_old: }while (*status &UART_LSR_DR ); end_intr: - mxvar_log.rxcnt[port->port.tty->index] += cnt; + mxvar_log.rxcnt[tty->index] += cnt; port->mon_data.rxcnt += cnt; port->mon_data.up_rxcnt += cnt;
@@ -2267,14 +2277,14 @@ end_intr:spin_lock (&port->slock); } -static void mxser_transmit_chars (struct mxser_port *port) +static void mxser_transmit_chars (struct tty_struct *tty,struct mxser_port *port) {int count, cnt;if (port->x_char) {outb (port->x_char, port->ioaddr +UART_TX ); port->x_char =0 ; - mxvar_log.txcnt[port->port.tty->index]++; + mxvar_log.txcnt[tty->index]++; port->mon_data.txcnt++; port->mon_data.up_txcnt++; port->icount.tx++;
@@ -2284,8 +2294,8 @@ static void mxser_transmit_chars(struct mxser_port *port)if (port->port.xmit_buf ==NULL )return ; -if ((port->xmit_cnt <=0 ) || port->port.tty->stopped || - (port->port.tty->hw_stopped && +if (port->xmit_cnt <=0 || tty->stopped || + (tty->hw_stopped && (port->type !=PORT_16550A ) && (!port->board->chip_flag))) { port->IER &= ~UART_IER_THRI ;
@@ -2302,14 +2312,14 @@ static void mxser_transmit_chars(struct mxser_port *port)if (--port->xmit_cnt <=0 )break ; }while (--count >0 ); - mxvar_log.txcnt[port->port.tty->index] += (cnt - port->xmit_cnt); + mxvar_log.txcnt[tty->index] += (cnt - port->xmit_cnt); port->mon_data.txcnt += (cnt - port->xmit_cnt); port->mon_data.up_txcnt += (cnt - port->xmit_cnt); port->icount.tx += (cnt - port->xmit_cnt); -if (port->xmit_cnt <WAKEUP_CHARS ) -tty_wakeup (port->port.tty); +if (port->xmit_cnt <WAKEUP_CHARS && tty) +tty_wakeup (tty);if (port->xmit_cnt <=0 ) { port->IER &= ~UART_IER_THRI ;
@@ -2328,6 +2338,7 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)int max, irqbits, bits, msr;unsigned int int_cnt, pass_counter =0 ;int handled =IRQ_NONE ; +struct tty_struct *tty;for (i =0 ; i <MXSER_BOARDS ; i++)if (dev_id == &mxser_boards[i]) {
@@ -2360,13 +2371,15 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)if (iir &UART_IIR_NO_INT )break ; iir &=MOXA_MUST_IIR_MASK ; -if (!port->port.tty || + tty =tty_port_tty_get (&port->port); +if (!tty || (port->port.flags &ASYNC_CLOSING ) || !(port->port.flags &ASYNC_INITIALIZED )) { status =inb (port->ioaddr +UART_LSR );outb (0x27 , port->ioaddr +UART_FCR );inb (port->ioaddr +UART_MSR ); +tty_kref_put (tty);break ; }
@@ -2387,27 +2400,28 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) iir == MOXA_MUST_IIR_RDA || iir == MOXA_MUST_IIR_RTO || iir == MOXA_MUST_IIR_LSR) -mxser_receive_chars (port, +mxser_receive_chars (tty, port, &status); }else { status &= port->read_status_mask;if (status &UART_LSR_DR ) -mxser_receive_chars (port, +mxser_receive_chars (tty, port, &status); } msr =inb (port->ioaddr +UART_MSR );if (msr &UART_MSR_ANY_DELTA ) -mxser_check_modem_status (port, msr); +mxser_check_modem_status (tty, port, msr);if (port->board->chip_flag) {if (iir ==0x02 && (status &UART_LSR_THRE )) -mxser_transmit_chars (port); +mxser_transmit_chars (tty, port); }else {if (status &UART_LSR_THRE ) -mxser_transmit_chars (port); +mxser_transmit_chars (tty, port); } +tty_kref_put (tty); }while (int_cnt++ <MXSER_ISR_PASS_LIMIT );spin_unlock (&port->slock); }
PATCH 42/76 tty: the vhangup syscall is racy
In reply to Alan CoxWe now have the infrastructure to sort this out but rather than teaching the syscall tty lock rules we move the hard work into a tty helper
---
drivers/char/tty_io.c | 19 +++++++++++++++++++ fs/open.c | 3 +-- 2 files changed, 20 insertions(+), 2 deletions(-)
drivers/char/tty_io.c +19 -0
@@ -730,6 +730,25 @@ void tty_vhangup(struct tty_struct *tty)EXPORT_SYMBOL (tty_vhangup);/** +* tty_vhangup_self - process vhangup for own ctty +* +* Perform a vhangup on the current controlling tty +*/ + +void tty_vhangup_self (void ) +{ +struct tty_struct *tty; + +mutex_lock (&tty_mutex); + tty =get_current_tty (); +if (tty) { +tty_vhangup (tty); +tty_kref_put (tty); + } +mutex_unlock (&tty_mutex); +} + +/** * tty_hung_up_p - was tty hung up * @filp: file pointer of tty *
fs/open.c +1 -2
@@ -1141,8 +1141,7 @@ EXPORT_SYMBOL(sys_close);asmlinkage long sys_vhangup (void ) {if (capable (CAP_SYS_TTY_CONFIG )) { -/* XXX: this needs locking */ -tty_vhangup (current->signal->tty); +tty_vhangup_self ();return 0 ; }return -EPERM ;
PATCH 43/76 tty: Redo current tty locking
In reply to Alan CoxCurrently it is sometimes locked by the tty mutex and sometimes by the sighand lock. The latter is in fact correct and now we can hand back referenced objects we can fix this up without problems around sleeping functions.
---
drivers/char/tty_io.c | 18 ++++-------------- fs/dquot.c | 2 -- include/linux/tty.h | 1 + security/selinux/hooks.c | 2 -- 4 files changed, 5 insertions(+), 18 deletions(-)
drivers/char/tty_io.c +4 -14
@@ -739,13 +739,11 @@ void tty_vhangup_self(void) {struct tty_struct *tty; -mutex_lock (&tty_mutex); tty =get_current_tty ();if (tty) {tty_vhangup (tty);tty_kref_put (tty); } -mutex_unlock (&tty_mutex); }/**
@@ -801,11 +799,9 @@ void disassociate_ctty(int on_exit)struct pid *tty_pgrp =NULL ; -mutex_lock (&tty_mutex); tty =get_current_tty ();if (tty) { tty_pgrp =get_pid (tty->pgrp); -mutex_unlock (&tty_mutex);lock_kernel ();if (on_exit && tty->driver->type !=TTY_DRIVER_TYPE_PTY )tty_vhangup (tty);
@@ -822,7 +818,6 @@ void disassociate_ctty(int on_exit)kill_pgrp (old_pgrp,SIGCONT , on_exit);put_pid (old_pgrp); } -mutex_unlock (&tty_mutex);return ; }if (tty_pgrp) {
@@ -837,7 +832,6 @@ void disassociate_ctty(int on_exit) current->signal->tty_old_pgrp =NULL ;spin_unlock_irq (¤t->sighand->siglock); -mutex_lock (&tty_mutex); tty =get_current_tty ();if (tty) {unsigned long flags;
@@ -854,7 +848,6 @@ void disassociate_ctty(int on_exit) " = NULL", tty);#endif } -mutex_unlock (&tty_mutex);/* Now clear signal->tty under the lock */ read_lock (&tasklist_lock);
@@ -3180,14 +3173,11 @@ static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)struct tty_struct *get_current_tty (void ) {struct tty_struct *tty; -WARN_ON_ONCE (!mutex_is_locked (&tty_mutex)); +unsigned long flags; + +spin_lock_irqsave (¤t->sighand->siglock, flags); tty =tty_kref_get (current->signal->tty); -/* -* session->tty can be changed/cleared from under us, make sure we -* issue the load. The obtained pointer, when not NULL, is valid as -* long as we hold tty_mutex. -*/ -barrier (); +spin_unlock_irqrestore (¤t->sighand->siglock, flags);return tty; }EXPORT_SYMBOL_GPL (get_current_tty);
fs/dquot.c +0 -2
@@ -895,9 +895,7 @@ static void print_warning(struct dquot *dquot, const int warntype) warntype == QUOTA_NL_BSOFTBELOW || !need_print_warning(dquot))return ; -mutex_lock (&tty_mutex); tty =get_current_tty (); -mutex_unlock (&tty_mutex);if (!tty)return ;tty_write_message (tty, dquot->dq_sb->s_id);
include/linux/tty.h +1 -0
@@ -361,6 +361,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_self (void );extern void tty_unhangup (struct file *filp);extern int tty_hung_up_p (struct file *filp);extern void do_SAK (struct tty_struct *tty);
security/selinux/hooks.c +0 -2
@@ -2120,9 +2120,7 @@ static inline void flush_unauthorized_files(struct files_struct *files)long j =-1 ;int drop_tty =0 ; -mutex_lock (&tty_mutex); tty =get_current_tty (); -mutex_unlock (&tty_mutex);if (tty) {file_list_lock (); file =list_entry (tty->tty_files.next,typeof (*file), f_u.fu_list);
Re: [PATCH 43/76] tty: Redo current tty locking
Quoted 13 lines · Alan Cox
include/linux/tty.h +1
-0@@ -361,6 +361,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_self (void );extern void tty_unhangup (struct file *filp);extern int tty_hung_up_p (struct file *filp);extern void do_SAK (struct tty_struct *tty);
Quoted 1 line
From a pedantic pov shouldn't the above be part of patch 42 - where you
actually created tty_vhangup_self()?
DF
PATCH 44/76 tty: Fix abusers of current->sighand->tty
In reply to Alan CoxVarious people outside the tty layer still stick their noses in behind the scenes. We need to make sure they also obey the locking and referencing rules.
---
kernel/acct.c | 2 +- kernel/auditsc.c | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-)
kernel/acct.c +1 -1
@@ -548,7 +548,7 @@ static void do_acct_process(struct bsd_acct_struct *acct,#endif spin_lock_irq (¤t->sighand->siglock); - tty = current->signal->tty; + tty = current->signal->tty;/* Safe as we hold the siglock */ ac.ac_tty = tty ?old_encode_dev (tty_devnum (tty)) :0 ; ac.ac_utime =encode_comp_t (jiffies_to_AHZ (cputime_to_jiffies (pacct->ac_utime))); ac.ac_stime =encode_comp_t (jiffies_to_AHZ (cputime_to_jiffies (pacct->ac_stime)));
kernel/auditsc.c +4 -5
@@ -246,8 +246,8 @@ static int audit_match_perm(struct audit_context *ctx, int mask)unsigned n;if (unlikely (!ctx))return 0 ; - n = ctx->major; +switch (audit_classify_syscall (ctx->arch, n)) {case 0 :/* native */ if ((mask & AUDIT_PERM_WRITE) &&
@@ -1204,13 +1204,13 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts (context->return_valid==AUDITSC_SUCCESS )?"yes" :"no" , context->return_code); -mutex_lock (&tty_mutex); -read_lock (&tasklist_lock); +spin_lock_irq (&tsk->sighand->siglock);if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) tty = tsk->signal->tty->name;else tty ="(none)" ; -read_unlock (&tasklist_lock); +spin_unlock_irq (&tsk->sighand->siglock); +audit_log_format (ab," a0=%lx a1=%lx a2=%lx a3=%lx items=%d" " ppid=%d pid=%d auid=%u uid=%u gid=%u"
@@ -1230,7 +1230,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts context->egid, context->sgid, context->fsgid, tty, tsk->sessionid); -mutex_unlock (&tty_mutex);audit_log_task_info (ab, tsk);if (context->filterkey) {
PATCH 45/76 pty: If the administrator creates a device for a ptmx slave we should not error
In reply to Alan CoxThe open path for ptmx slaves is via the ptmx device. Opening them any other way is not allowed. Vegard Nossum found that previously this was not the case and mknod foo c 128 42; cat foo would produce nasty diagnostics
---
drivers/char/tty_io.c | 18 ++++++++++++------ 1 files changed, 12 insertions(+), 6 deletions(-)
drivers/char/tty_io.c +12 -6
@@ -1227,7 +1227,8 @@ static void tty_line_name(struct tty_driver *driver, int index, char *p)* init_dev - initialise a tty device * @driver: tty driver we are opening a device on * @idx: device index -* @tty: returned tty structure +* @ret_tty: returned tty structure +* @first_ok: ok to open a new device (used by ptmx) * * Prepare a tty device. This may not be a "new" clean device but * could also be an active device. The pty drivers require special
@@ -1248,7 +1249,7 @@ static void tty_line_name(struct tty_driver *driver, int index, char *p)*/ static int init_dev (struct tty_driver *driver,int idx, -struct tty_struct **ret_tty) +struct tty_struct **ret_tty,int first_ok) {struct tty_struct *tty, *o_tty;struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc;
@@ -1279,6 +1280,11 @@ static int init_dev(struct tty_driver *driver, int idx, }if (tty) goto fast_track; +if (driver->subtype ==PTY_TYPE_MASTER && + (driver->flags &TTY_DRIVER_DEVPTS_MEM ) && !first_ok) { + retval = -EIO ; + goto end_init; + }/* * First time open is complex, especially for PTY devices. * This code guarantees that either everything succeeds and the
@@ -1413,7 +1419,7 @@ static int init_dev(struct tty_driver *driver, int idx,if (retval) goto release_mem_out; - goto success; + goto success;/* * This fast open can be used if the tty is already open.
@@ -1795,7 +1801,7 @@ static void release_dev(struct file *filp) }/** -* tty_open - open a tty device +* __tty_open - open a tty device * @inode: inode of device file * @filp: file pointer to tty *
@@ -1874,7 +1880,7 @@ retry_open:return -ENODEV ; } got_driver: - retval =init_dev (driver, index, &tty); + retval =init_dev (driver, index, &tty,0 );mutex_unlock (&tty_mutex);if (retval)return retval;
@@ -1971,7 +1977,7 @@ static int __ptmx_open(struct inode *inode, struct file *filp)return index;mutex_lock (&tty_mutex); - retval =init_dev (ptm_driver, index, &tty); + retval =init_dev (ptm_driver, index, &tty,1 );mutex_unlock (&tty_mutex);if (retval)
PATCH 46/76 vt: remove bogus lock dropping
In reply to Alan CoxFor hysterical raisins the vt layer drops and retakes locks in the write method. This is a left over from the days when user/kernel data was passed directly to the tty not pre-buffered.
---
drivers/char/vt.c | 18 ------------------ 1 files changed, 0 insertions(+), 18 deletions(-)
drivers/char/vt.c +0 -18
@@ -2136,27 +2136,9 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int corelease_console_sem ();return 0 ; } -release_console_sem (); - orig_buf = buf; orig_count = count; -/* At this point 'buf' is guaranteed to be a kernel buffer -* and therefore no access to userspace (and therefore sleeping) -* will be needed. The con_buf_mtx serializes all tty based -* console rendering and vcs write/read operations. We hold -* the console spinlock during the entire write. -*/ - -acquire_console_sem (); - - vc = tty->driver_data; -if (vc ==NULL ) { -printk (KERN_ERR "vt: argh, driver_data _became_ NULL !\n" ); -release_console_sem (); - goto out; - } - himask = vc->vc_hi_font_mask; charmask = himask ?0x1ff :0xff ;
PATCH 47/76 tty: shutdown method
In reply to Alan CoxRight now there are various drivers that try to use tty->count to know when they get the final close. Aristeau Rozanski showed while debugging the vt sysfs race that this isn't entirely safe.
Instead of driver side tricks to work around this introduce a shutdown which is called when the tty is being destructed. This also means that the shutdown method is tied into the refcounting.
Use this to rework the console close/sysfs logic.
Remove lots of special case code from the tty core code. The pty code can now have a shutdown() method that replaces the special case hackery in the tree free up paths.
---
drivers/char/pty.c | 15 ++++++++++--- drivers/char/tty_io.c | 49 ++++++++++++++++++++++++++------------------ drivers/char/vt.c | 34 +++++++++++++++---------------- include/linux/tty.h | 3 ++- include/linux/tty_driver.h | 6 +++++ 5 files changed, 65 insertions(+), 42 deletions(-)
drivers/char/pty.c +11 -4
@@ -388,7 +388,14 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,return -ENOIOCTLCMD ; } -static const struct tty_operations pty_unix98_ops = { +static void pty_shutdown (struct tty_struct *tty) +{ +/* We have our own method as we don't use the tty index */ +kfree (tty->termios); +kfree (tty->termios_locked); +} + +static const struct tty_operations ptm_unix98_ops = { .open = pty_open, .close = pty_close, .write = pty_write,
@@ -397,10 +404,10 @@ static const struct tty_operations pty_unix98_ops = { .chars_in_buffer = pty_chars_in_buffer, .unthrottle = pty_unthrottle, .set_termios = pty_set_termios, - .ioctl = pty_unix98_ioctl + .ioctl = pty_unix98_ioctl, + .shutdown = pty_shutdown }; -static void __init unix98_pty_init (void ) { ptm_driver =alloc_tty_driver (NR_UNIX98_PTY_MAX );
@@ -427,7 +434,7 @@ static void __init unix98_pty_init(void) ptm_driver->flags =TTY_DRIVER_RESET_TERMIOS |TTY_DRIVER_REAL_RAW |TTY_DRIVER_DYNAMIC_DEV |TTY_DRIVER_DEVPTS_MEM ; ptm_driver->other = pts_driver; -tty_set_operations (ptm_driver, &pty_unix98_ops); +tty_set_operations (ptm_driver, &ptm_unix98_ops); pts_driver->owner =THIS_MODULE ; pts_driver->driver_name ="pty_slave" ;
drivers/char/tty_io.c +29 -20
62 lines not on this page · raw message
drivers/char/vt.c +17 -17
@@ -2758,6 +2758,12 @@ static int con_open(struct tty_struct *tty, struct file *filp) ret =vc_allocate (currcons);if (ret ==0 ) {struct vc_data *vc = vc_cons[currcons].d; + +/* Still being freed */ +if (vc->vc_tty) { +release_console_sem (); +return -ERESTARTSYS ; + } tty->driver_data = vc; vc->vc_tty = tty;
@@ -2787,25 +2793,18 @@ static int con_open(struct tty_struct *tty, struct file *filp)*/ static void con_close (struct tty_struct *tty,struct file *filp) { -mutex_lock (&tty_mutex); -acquire_console_sem (); -if (tty && tty->count ==1 ) { -struct vc_data *vc = tty->driver_data; +/* Nothing to do - we defer to shutdown */ +} -if (vc) - vc->vc_tty =NULL ; - tty->driver_data =NULL ; -vcs_remove_sysfs (tty); -release_console_sem (); -mutex_unlock (&tty_mutex); -/* -* tty_mutex is released, but we still hold BKL, so there is -* still exclusion against init_dev() -*/ -return ; - } +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 ; +vcs_remove_sysfs (tty);release_console_sem (); -mutex_unlock (&tty_mutex); +tty_shutdown (tty); }static int default_italic_color =2 ;// green (ASCII)
@@ -2930,6 +2929,7 @@ static const struct tty_operations con_ops = { .throttle = con_throttle, .unthrottle = con_unthrottle, .resize = vt_resize, + .shutdown = con_shutdown };int __init vty_init (void )
include/linux/tty.h +2 -1
@@ -354,7 +354,8 @@ extern void tty_throttle(struct tty_struct *tty);extern void tty_unthrottle (struct tty_struct *tty);extern int tty_do_resize (struct tty_struct *tty,struct tty_struct *real_tty,struct winsize *ws); - +extern void tty_shutdown (struct tty_struct *tty); +extern void tty_free_termios (struct tty_struct *tty);extern int is_current_pgrp_orphaned (void );extern struct pid *tty_get_pgrp (struct tty_struct *tty);extern int is_ignored (int sig);
include/linux/tty_driver.h +6 -0
@@ -21,6 +21,11 @@* * Required method. * +* void (*shutdown)(struct tty_struct * tty); +* +* This routine is called when a particular tty device is closed for +* the last time freeing up the resources. +* * int (*write)(struct tty_struct * tty, * const unsigned char *buf, int count); *
@@ -200,6 +205,7 @@ struct tty_driver;struct tty_operations {int (*open)(struct tty_struct * tty,struct file * filp);void (*close)(struct tty_struct * tty,struct file * filp); +void (*shutdown)(struct tty_struct *tty);int (*write)(struct tty_struct * tty,const unsigned char *buf,int count);int (*put_char)(struct tty_struct *tty,unsigned char ch);
PATCH 48/76 tty: Remove more special casing and out of place code
In reply to Alan CoxCarry on pushing code out of tty_io when it belongs to other drivers. I'm not 100% happy with some of this and it will be worth revisiting some of the exports later when the restructuring work is done.
---
drivers/char/pty.c | 78 +++++++++++++++++++++ drivers/char/tty_io.c | 169 ++++++++++------------------------------------ drivers/char/tty_ioctl.c | 66 ++++++++++++++++-- drivers/char/vt.c | 30 ++++---- include/linux/tty.h | 6 ++ include/linux/vt_kern.h | 2 - 6 files changed, 195 insertions(+), 156 deletions(-)
drivers/char/pty.c +78 -0
@@ -23,6 +23,7 @@#include <linux/mm.h> #include <linux/init.h> #include <linux/sysctl.h> +#include <linux/device.h> #include <asm/uaccess.h> #include <asm/system.h>
@@ -332,6 +333,8 @@ int pty_limit = NR_UNIX98_PTY_DEFAULT;static int pty_limit_min =0 ;static int pty_limit_max =NR_UNIX98_PTY_MAX ; +static struct cdev ptmx_cdev; +static struct ctl_table pty_table[] = { { .ctl_name =PTY_MAX ,
@@ -408,6 +411,70 @@ static const struct tty_operations ptm_unix98_ops = { .shutdown = pty_shutdown }; + +/** +* ptmx_open - open a unix 98 pty master +* @inode: inode of device file +* @filp: file pointer to tty +* +* Allocate a unix98 pty master device from the ptmx driver. +* +* Locking: tty_mutex protects the init_dev work. tty->count should +* protect the rest. +* allocated_ptys_lock handles the list of free pty numbers +*/ + +static int __ptmx_open (struct inode *inode,struct file *filp) +{ +struct tty_struct *tty; +int retval; +int index; + +nonseekable_open (inode, filp); + +/* find a device that is not in use. */ + index =devpts_new_index (); +if (index <0 ) +return index; + +mutex_lock (&tty_mutex); + retval =tty_init_dev (ptm_driver, index, &tty,1 ); +mutex_unlock (&tty_mutex); + +if (retval) + goto out; + +set_bit (TTY_PTY_LOCK , &tty->flags);/* LOCK THE SLAVE */ + filp->private_data = tty; +file_move (filp, &tty->tty_files); + + retval =devpts_pty_new (tty->link); +if (retval) + goto out1; + + retval = ptm_driver->ops->open (tty, filp); +if (!retval) +return 0 ; +out1: +tty_release_dev (filp); +return retval; +out: +devpts_kill_index (index); +return retval; +} + +static int ptmx_open (struct inode *inode,struct file *filp) +{ +int ret; + +lock_kernel (); + ret =__ptmx_open (inode, filp); +unlock_kernel (); +return ret; +} + +static struct file_operations ptmx_fops; +static void __init unix98_pty_init (void ) { ptm_driver =alloc_tty_driver (NR_UNIX98_PTY_MAX );
@@ -459,7 +526,18 @@ static void __init unix98_pty_init(void) pty_table[1 ].data = &ptm_driver->refcount;register_sysctl_table (pty_root_table); + +/* Now create the /dev/ptmx special device */ +tty_default_fops (&ptmx_fops); + ptmx_fops.open = ptmx_open; + +cdev_init (&ptmx_cdev, &ptmx_fops); +if (cdev_add (&ptmx_cdev,MKDEV (TTYAUX_MAJOR ,2 ),1 ) || +register_chrdev_region (MKDEV (TTYAUX_MAJOR ,2 ),1 ,"/dev/ptmx" ) <0 ) +panic ("Couldn't register /dev/ptmx driver\n" ); + device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); } +#else static inline void unix98_pty_init (void ) { }#endif
drivers/char/tty_io.c +36 -133
365 lines not on this page · raw message
drivers/char/tty_ioctl.c +60 -6
131 lines not on this page · raw message
drivers/char/vt.c +14 -16
@@ -100,10 +100,10 @@#include <linux/font.h> #include <linux/bitops.h> #include <linux/notifier.h> - -#include <asm/io.h> +#include <linux/device.h> +#include <linux/io.h> #include <asm/system.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #define MAX_NR_CON_DRIVER 16
@@ -2352,8 +2352,6 @@ rescan_last_byte:FLUSH console_conditional_schedule ();release_console_sem (); - -out:notify_update (vc);return n;#undef FLUSH
@@ -2784,13 +2782,6 @@ static int con_open(struct tty_struct *tty, struct file *filp)return ret; } -/* -* We take tty_mutex in here to prevent another thread from coming in via init_dev -* and taking a ref against the tty while we're in the process of forgetting -* about it and cleaning things up. -* -* This is because vcs_remove_sysfs() can sleep and will drop the BKL. -*/ static void con_close (struct tty_struct *tty,struct file *filp) {/* Nothing to do - we defer to shutdown */
@@ -2932,8 +2923,16 @@ static const struct tty_operations con_ops = { .shutdown = con_shutdown }; -int __init vty_init (void ) +static struct cdev vc0_cdev; + +int __init vty_init (const struct file_operations *console_fops) { +cdev_init (&vc0_cdev, console_fops); +if (cdev_add (&vc0_cdev,MKDEV (TTY_MAJOR ,0 ),1 ) || +register_chrdev_region (MKDEV (TTY_MAJOR ,0 ),1 ,"/dev/vc/0" ) <0 ) +panic ("Couldn't register /dev/tty0 driver\n" ); +device_create (tty_class,NULL ,MKDEV (TTY_MAJOR ,0 ),NULL ,"tty0" ); +vcs_init (); console_driver =alloc_tty_driver (MAX_NR_CONSOLES );
@@ -2952,7 +2951,6 @@ int __init vty_init(void)tty_set_operations (console_driver, &con_ops);if (tty_register_driver (console_driver))panic ("Couldn't register console driver\n" ); -kbd_init ();console_map_init ();#ifdef CONFIG_PROM_CONSOLE
@@ -3446,7 +3444,7 @@ int register_con_driver(const struct consw *csw, int first, int last)if (retval) goto err; - con_driver->dev =device_create_drvdata (vtconsole_class,NULL , + con_driver->dev =device_create (vtconsole_class,NULL ,MKDEV (0 , con_driver->node),NULL ,"vtcon%i" , con_driver->node);
@@ -3557,7 +3555,7 @@ static int __init vtconsole_class_init(void)struct con_driver *con = ®istered_con_driver[i];if (con->con && !con->dev) { - con->dev =device_create_drvdata (vtconsole_class,NULL , + con->dev =device_create (vtconsole_class,NULL ,MKDEV (0 , con->node),NULL ,"vtcon%i" , con->node);
include/linux/tty.h +6 -0
@@ -314,6 +314,8 @@ extern int kmsg_redirect;extern void console_init (void );extern int vcs_init (void ); +extern struct class *tty_class; +/** * tty_kref_get - get a tty reference * @tty: tty device
@@ -398,6 +400,10 @@ extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);extern dev_t tty_devnum (struct tty_struct *tty);extern void proc_clear_tty (struct task_struct *p);extern struct tty_struct *get_current_tty (void ); +extern void tty_default_fops (struct file_operations *fops); +extern int tty_init_dev (struct tty_driver *driver,int idx, +struct tty_struct **ret_tty,int first_ok); +extern void tty_release_dev (struct file *filp);extern struct mutex tty_mutex;
include/linux/vt_kern.h +1 -1
@@ -96,7 +96,7 @@ void change_console(struct vc_data *new_vc);void reset_vc (struct vc_data *vc);extern int unbind_con_driver (const struct consw *csw,int first,int last,int deflt); -int vty_init (void ); +int vty_init (const struct file_operations *console_fops);/* * vc_screen.c shares this temporary buffer with the console write code so that
PATCH 49/76 tty: Move parts of tty_init_dev into new functions
In reply to Alan CoxFrom: Sukadev Bhattiprolu <[email protected]>
Move the 'find-tty' and 'fast-track-open' parts of init_dev() to separate functions.
---
drivers/char/tty_io.c | 139 +++++++++++++++++++++++++++++++------------------ 1 files changed, 87 insertions(+), 52 deletions(-)
drivers/char/tty_io.c +87 -52
@@ -1204,6 +1204,80 @@ static void tty_line_name(struct tty_driver *driver, int index, char *p)sprintf (p,"%s%d" , driver->name, index + driver->name_base); } +/* +* find_tty() - find an existing tty, if any +* @driver: the driver for the tty +* @idx: the minor number +* +* Return the tty, if found or ERR_PTR() otherwise. +* +* Locking: tty_mutex must be held. If tty is found, the mutex must +* be held until the 'fast-open' is also done. +*/ +struct tty_struct *find_tty (struct tty_driver *driver,int idx) +{ +struct tty_struct *tty; + +/* check whether we're reopening an existing tty */ +if (driver->flags &TTY_DRIVER_DEVPTS_MEM ) { + tty =devpts_get_tty (idx); +/* +* If we don't have a tty here on a slave open, it's because +* the master already started the close process and there's +* no relation between devpts file and tty anymore. +*/ +if (!tty && driver->subtype ==PTY_TYPE_SLAVE ) +return ERR_PTR (-EIO ); + +/* +* tty is safe on because we are called with tty_mutex held +* and release_dev() won't change tty->count or tty->flags +* without grabbing tty_mutex. +*/ +if (tty && driver->subtype ==PTY_TYPE_MASTER ) + tty = tty->link; + }else + tty = driver->ttys[idx]; +return tty; +} + +/* +* fast_tty_open() - fast re-open of an open tty +* @tty - the tty to open +* +* Return 0 on success, -errno on error. +* +* Locking: tty_mutex must be held from the time the tty was found +* till this open completes. +*/ +static int fast_tty_open (struct tty_struct *tty) +{ +struct tty_driver *driver = tty->driver; + +if (test_bit (TTY_CLOSING , &tty->flags)) +return -EIO ; + +if (driver->type ==TTY_DRIVER_TYPE_PTY && + driver->subtype ==PTY_TYPE_MASTER ) { +/* +* special case for PTY masters: only one open permitted, +* and the slave side open count is incremented as well. +*/ +if (tty->count) +return -EIO ; + + tty->link->count++; + } + tty->count++; + tty->driver = driver;/* N.B. why do this every time?? */ + +/* FIXME */ +if (!test_bit (TTY_LDISC , &tty->flags)) +printk (KERN_ERR "fast_tty_open: no ldisc\n" ); + +return 0 ; +} +/** * tty_init_dev - initialise a tty device * @driver: tty driver we are opening a device on
@@ -1238,29 +1312,21 @@ int tty_init_dev(struct tty_driver *driver, int idx,int retval =0 ;/* check whether we're reopening an existing tty */ -if (driver->flags &TTY_DRIVER_DEVPTS_MEM ) { - tty =devpts_get_tty (idx); -/* -* If we don't have a tty here on a slave open, it's because -* the master already started the close process and there's -* no relation between devpts file and tty anymore. -*/ -if (!tty && driver->subtype ==PTY_TYPE_SLAVE ) { - retval = -EIO ; - goto end_init; - } -/* -* It's safe from now on because tty_init_dev() is called with -* tty_mutex held and tty_release_dev() won't change tty->count -* or tty->flags without having to grab tty_mutex -*/ -if (tty && driver->subtype ==PTY_TYPE_MASTER ) - tty = tty->link; - }else { - tty = driver->ttys[idx]; + tty =find_tty (driver, idx); +if (IS_ERR (tty)) { + retval =PTR_ERR (tty); + goto end_init; + } + +if (tty) { + retval =fast_tty_open (tty); +if (retval) +return retval; + *ret_tty = tty; +return 0 ; } -if (tty) goto fast_track; +/* Check if pty master is being opened multiple times */ if (driver->subtype ==PTY_TYPE_MASTER && (driver->flags &TTY_DRIVER_DEVPTS_MEM ) && !first_ok) { retval = -EIO ;
@@ -1400,37 +1466,6 @@ int tty_init_dev(struct tty_driver *driver, int idx,if (retval) goto release_mem_out; - goto success; - -/* -* This fast open can be used if the tty is already open. -* No memory is allocated, and the only failures are from -* attempting to open a closing tty or attempting multiple -* opens on a pty master. -*/ -fast_track: -if (test_bit (TTY_CLOSING , &tty->flags)) { - retval = -EIO ; - goto end_init; - } -if (driver->type ==TTY_DRIVER_TYPE_PTY && - driver->subtype ==PTY_TYPE_MASTER ) { -/* -* special case for PTY masters: only one open permitted, -* and the slave side open count is incremented as well. -*/ -if (tty->count) { - retval = -EIO ; - goto end_init; - } - tty->link->count++; - } - tty->count++; - tty->driver = driver;/* N.B. why do this every time?? */ - -/* FIXME */ -if (!test_bit (TTY_LDISC , &tty->flags)) -printk (KERN_ERR "tty_init_dev but no ldisc\n" ); success: *ret_tty = tty;
PATCH 50/76 tty: Clean up the tty_init_dev changes further
In reply to Alan CoxFix up the naming, style and extract some bits of code into the driver specific code
---
drivers/char/pty.c | 49 +++++++++++++++++++++++++++++++++- drivers/char/tty_io.c | 64 +++++++++++++++++--------------------------- include/linux/tty_driver.h | 9 ++++++ 3 files changed, 81 insertions(+), 41 deletions(-)
drivers/char/pty.c +48 -1
@@ -391,6 +391,41 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,return -ENOIOCTLCMD ; } +/** +* ptm_unix98_lookup - find a pty master +* @driver: ptm driver +* @idx: tty index +* +* Look up a pty master device. Called under the tty_mutex for now. +* This provides our locking. +*/ + +static struct tty_struct *ptm_unix98_lookup (struct tty_driver *driver,int idx) +{ +struct tty_struct *tty =devpts_get_tty (idx); +if (tty) + tty = tty->link; +return tty; +} + +/** +* pts_unix98_lookup - find a pty slave +* @driver: pts driver +* @idx: tty index +* +* Look up a pty master device. Called under the tty_mutex for now. +* This provides our locking. +*/ + +static struct tty_struct *pts_unix98_lookup (struct tty_driver *driver,int idx) +{ +struct tty_struct *tty =devpts_get_tty (idx); +/* Master must be open before slave */ +if (!tty) +return ERR_PTR (-EIO ); +return tty; +} +static void pty_shutdown (struct tty_struct *tty) {/* We have our own method as we don't use the tty index */
@@ -399,6 +434,7 @@ static void pty_shutdown(struct tty_struct *tty) }static const struct tty_operations ptm_unix98_ops = { + .lookup = ptm_unix98_lookup, .open = pty_open, .close = pty_close, .write = pty_write,
@@ -411,6 +447,17 @@ static const struct tty_operations ptm_unix98_ops = { .shutdown = pty_shutdown }; +static const struct tty_operations pty_unix98_ops = { + .lookup = pts_unix98_lookup, + .open = pty_open, + .close = pty_close, + .write = pty_write, + .write_room = pty_write_room, + .flush_buffer = pty_flush_buffer, + .chars_in_buffer = pty_chars_in_buffer, + .unthrottle = pty_unthrottle, + .set_termios = pty_set_termios, +};/** * ptmx_open - open a unix 98 pty master
@@ -517,7 +564,7 @@ static void __init unix98_pty_init(void) pts_driver->flags =TTY_DRIVER_RESET_TERMIOS |TTY_DRIVER_REAL_RAW |TTY_DRIVER_DYNAMIC_DEV |TTY_DRIVER_DEVPTS_MEM ; pts_driver->other = ptm_driver; -tty_set_operations (pts_driver, &pty_ops); +tty_set_operations (pts_driver, &pty_unix98_ops);if (tty_register_driver (ptm_driver))panic ("Couldn't register Unix98 ptm driver" );
drivers/char/tty_io.c +24 -40
115 lines not on this page · raw message
include/linux/tty_driver.h +9 -0
@@ -7,6 +7,14 @@* defined; unless noted otherwise, they are optional, and can be * filled in with a null pointer. * +* struct tty_struct * (*lookup)(struct tty_driver *self, int idx) +* +* Return the tty device corresponding to idx, NULL if there is not +* one currently in use and an ERR_PTR value on error. Called under +* tty_mutex (for now!) +* +* Optional method. Default behaviour is to use the ttys array +* * int (*open)(struct tty_struct * tty, struct file * filp); * * This routine is called when a particular tty device is opened.
@@ -203,6 +211,7 @@ struct tty_struct;struct tty_driver ;struct tty_operations { +struct tty_struct * (*lookup)(struct tty_driver *driver,int idx);int (*open)(struct tty_struct * tty,struct file * filp);void (*close)(struct tty_struct * tty,struct file * filp);void (*shutdown)(struct tty_struct *tty);
PATCH 51/76 tty: kref the tty driver object
In reply to Alan Cox---
drivers/char/ip2/ip2main.c | 6 +- drivers/char/pty.c | 5 ++ drivers/char/tty_io.c | 110 ++++++++++++++++++++++++-------------------- drivers/net/wan/Kconfig | 2 - include/linux/tty_driver.h | 15 ++++-- 5 files changed, 80 insertions(+), 58 deletions(-)
drivers/char/ip2/ip2main.c +3 -3
@@ -264,8 +264,8 @@ static int tracewrap;/**********/ #if defined(MODULE ) && defined(IP2DEBUG_OPEN ) -#define DBG_CNT (s) printk(KERN_DEBUG "(%s): [%x] refc=%d, ttyc=%d, modc=%x -> %s\n", \ - tty->name,(pCh->flags),ip2_tty_driver->refcount, \ +#define DBG_CNT (s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \ + tty->name,(pCh->flags), \ tty->count,/*GET_USE_COUNT(module)*/0,s)#else #define DBG_CNT (s)
@@ -2893,7 +2893,7 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )case 13 :switch ( cmd ) {case 64 :/* Driver - ip2stat */ - rc =put_user (ip2_tty_driver->refcount, pIndex++ ); + rc =put_user (-1 , pIndex++ ); rc =put_user (irq_counter, pIndex++ ); rc =put_user (bh_counter, pIndex++ );break ;
drivers/char/pty.c +4 -1
@@ -571,8 +571,11 @@ static void __init unix98_pty_init(void)if (tty_register_driver (pts_driver))panic ("Couldn't register Unix98 pts driver" ); +/* FIXME: WTF */ +#if 0 pty_table[1 ].data = &ptm_driver->refcount; -register_sysctl_table (pty_root_table); +#endif +register_sysctl_table (pty_root_table);/* Now create the /dev/ptmx special device */ tty_default_fops (&ptmx_fops);
drivers/char/tty_io.c +61 -49
233 lines not on this page · raw message
drivers/net/wan/Kconfig +1 -1
@@ -205,7 +205,7 @@ config WANXL_BUILD_FIRMWARE config PC300 tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)" - depends on HDLC && PCI + depends on HDLC && PCI && BROKEN ---help--- Driver for the Cyclades-PC300 synchronous communication boards.
include/linux/tty_driver.h +11 -4
@@ -253,6 +253,7 @@ struct tty_operations {struct tty_driver {int magic;/* magic number for this structure */ +struct kref kref;/* Reference management */ struct cdev cdev;struct module *owner;const char *driver_name;
@@ -266,7 +267,6 @@ struct tty_driver {short subtype;/* subtype of tty driver */ struct ktermios init_termios;/* Initial termios */ int flags;/* tty driver flags */ -int refcount;/* for loadable tty drivers */ struct proc_dir_entry *proc_entry;/* /proc fs entry */ struct tty_driver *other;/* only used for the PTY driver */
@@ -288,12 +288,19 @@ struct tty_driver {extern struct list_head tty_drivers; -struct tty_driver *alloc_tty_driver (int lines); -void put_tty_driver (struct tty_driver *driver); -void tty_set_operations (struct tty_driver *driver, +extern struct tty_driver *alloc_tty_driver (int lines); +extern void put_tty_driver (struct tty_driver *driver); +extern void tty_set_operations (struct tty_driver *driver,const struct tty_operations *op);extern struct tty_driver *tty_find_polling_driver (char *name,int *line); +extern void tty_driver_kref_put (struct tty_driver *driver); +extern inline struct tty_driver *tty_driver_kref_get (struct tty_driver *d) +{ +kref_get (&d->kref); +return d; +} +/* tty driver magic number */ #define TTY_DRIVER_MAGIC 0x5402
PATCH 52/76 tty: More driver operations
In reply to Alan CoxWe have the lookup operation abstracted which is nice for pty cleanup but we really want to abstract the add/remove entries as well so that we can pull the pty code out of the tty core and create a clear defined interface for the tty driver table.
---
drivers/char/pty.c | 16 ++++++++++++ drivers/char/tty_io.c | 57 ++++++++++++++++++++++++++++++++++++-------- include/linux/tty_driver.h | 16 ++++++++++++ 3 files changed, 79 insertions(+), 10 deletions(-)
drivers/char/pty.c +16 -0
@@ -433,8 +433,22 @@ static void pty_shutdown(struct tty_struct *tty)kfree (tty->termios_locked); } +/* We have no need to install and remove our tty objects as devpts does all +the work for us */ + +static int pty_install (struct tty_driver *driver,struct tty_struct *tty) +{ +return 0 ; +} + +static void pty_remove (struct tty_driver *driver,struct tty_struct *tty) +{ +} +static const struct tty_operations ptm_unix98_ops = { .lookup = ptm_unix98_lookup, + .install = pty_install, + .remove = pty_remove, .open = pty_open, .close = pty_close, .write = pty_write,
@@ -449,6 +463,8 @@ static const struct tty_operations ptm_unix98_ops = {static const struct tty_operations pty_unix98_ops = { .lookup = pts_unix98_lookup, + .install = pty_install, + .remove = pty_remove, .open = pty_open, .close = pty_close, .write = pty_write,
drivers/char/tty_io.c +47 -10
98 lines not on this page · raw message
include/linux/tty_driver.h +16 -0
@@ -15,6 +15,20 @@* * Optional method. Default behaviour is to use the ttys array * +* int (*install)(struct tty_driver *self, struct tty_struct *tty) +* +* Install a new tty into the tty driver internal tables. Used in +* conjunction with lookup and remove methods. +* +* Optional method. Default behaviour is to use the ttys array +* +* void (*remove)(struct tty_driver *self, struct tty_struct *tty) +* +* Remove a closed tty from the tty driver internal tables. Used in +* conjunction with lookup and remove methods. +* +* Optional method. Default behaviour is to use the ttys array +* * int (*open)(struct tty_struct * tty, struct file * filp); * * This routine is called when a particular tty device is opened.
@@ -212,6 +226,8 @@ struct tty_driver;struct tty_operations {struct tty_struct * (*lookup)(struct tty_driver *driver,int idx); +int (*install)(struct tty_driver *driver,struct tty_struct *tty); +void (*remove)(struct tty_driver *driver,struct tty_struct *tty);int (*open)(struct tty_struct * tty,struct file * filp);void (*close)(struct tty_struct * tty,struct file * filp);void (*shutdown)(struct tty_struct *tty);
PATCH 53/76 tty: Finish fixing up the init_dev interface to use ERR_PTR
In reply to Alan CoxOriginal suggestion and proposal from Sukadev Bhattiprolu.
---
drivers/char/pty.c | 6 ++++-- drivers/char/tty_io.c | 52 ++++++++++++++++++++----------------------------- include/linux/tty.h | 4 ++-- 3 files changed, 27 insertions(+), 35 deletions(-)
drivers/char/pty.c +4 -2
@@ -501,11 +501,13 @@ static int __ptmx_open(struct inode *inode, struct file *filp)return index;mutex_lock (&tty_mutex); - retval =tty_init_dev (ptm_driver, index, &tty,1 ); + tty =tty_init_dev (ptm_driver, index,1 );mutex_unlock (&tty_mutex); -if (retval) +if (IS_ERR (tty)) { + retval =PTR_ERR (tty); goto out; + }set_bit (TTY_PTY_LOCK , &tty->flags);/* LOCK THE SLAVE */ filp->private_data = tty;
drivers/char/tty_io.c +21 -31
113 lines not on this page · raw message
include/linux/tty.h +2 -2
@@ -401,8 +401,8 @@ extern dev_t tty_devnum(struct tty_struct *tty);extern void proc_clear_tty (struct task_struct *p);extern struct tty_struct *get_current_tty (void );extern void tty_default_fops (struct file_operations *fops); -extern int tty_init_dev (struct tty_driver *driver,int idx, -struct tty_struct **ret_tty,int first_ok); +extern struct tty_struct *tty_init_dev (struct tty_driver *driver,int idx, +int first_ok);extern void tty_release_dev (struct file *filp);extern struct mutex tty_mutex;
PATCH 54/76 tty: extract the pty init time special cases
In reply to Alan CoxThe majority of the remaining init_dev code is pty special cases. We refactor this code into the driver->install method.
---
drivers/char/pty.c | 126 ++++++++++++++++++++++++++++--- drivers/char/tty_io.c | 198 +++++++++++++++++-------------------------------- include/linux/tty.h | 5 + 3 files changed, 187 insertions(+), 142 deletions(-)
drivers/char/pty.c +114 -12
@@ -227,7 +227,58 @@ static void pty_set_termios(struct tty_struct *tty, struct ktermios *old_termios tty->termios->c_cflag |= (CS8 |CREAD ); } +static int pty_install (struct tty_driver *driver,struct tty_struct *tty) +{ +struct tty_struct *o_tty; +int idx = tty->index; +int retval; + + o_tty =alloc_tty_struct (); +if (!o_tty) +return -ENOMEM ; +if (!try_module_get (driver->other->owner)) { +/* This cannot in fact currently happen */ +free_tty_struct (o_tty); +return -ENOMEM ; + } +initialize_tty_struct (o_tty, driver->other, idx); + +/* We always use new tty termios data so we can do this +the easy way .. */ + retval =tty_init_termios (tty); +if (retval) + goto free_mem_out; + + retval =tty_init_termios (o_tty); +if (retval) { +tty_free_termios (tty); + goto free_mem_out; + } + +/* +* Everything allocated ... set up the o_tty structure. +*/ + driver->other->ttys[idx] = o_tty; +tty_driver_kref_get (driver->other); +if (driver->subtype ==PTY_TYPE_MASTER ) + o_tty->count++; +/* Establish the links in both directions */ + tty->link = o_tty; + o_tty->link = tty; + +tty_driver_kref_get (driver); + tty->count++; + driver->ttys[idx] = tty; +return 0 ; +free_mem_out: +module_put (o_tty->driver->owner); +free_tty_struct (o_tty); +return -ENOMEM ; +} + +static const struct tty_operations pty_ops = { + .install = pty_install, .open = pty_open, .close = pty_close, .write = pty_write,
@@ -332,6 +383,7 @@ static inline void legacy_pty_init(void) { }int pty_limit =NR_UNIX98_PTY_DEFAULT ;static int pty_limit_min =0 ;static int pty_limit_max =NR_UNIX98_PTY_MAX ; +static int pty_count =0 ;static struct cdev ptmx_cdev;
@@ -351,6 +403,7 @@ static struct ctl_table pty_table[] = { .procname = "nr", .maxlen = sizeof(int), .mode = 0444, + .data = &pty_count, .proc_handler = &proc_dointvec, }, { .ctl_name = 0
@@ -426,7 +479,7 @@ static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver, int idx)return tty; } -static void pty_shutdown (struct tty_struct *tty) +static void pty_unix98_shutdown (struct tty_struct *tty) {/* We have our own method as we don't use the tty index */ kfree (tty->termios);
@@ -436,19 +489,71 @@ static void pty_shutdown(struct tty_struct *tty)/* We have no need to install and remove our tty objects as devpts does all the work for us */ -static int pty_install (struct tty_driver *driver,struct tty_struct *tty) +static int pty_unix98_install (struct tty_driver *driver,struct tty_struct *tty) { +struct tty_struct *o_tty; +int idx = tty->index; + + o_tty =alloc_tty_struct (); +if (!o_tty) +return -ENOMEM ; +if (!try_module_get (driver->other->owner)) { +/* This cannot in fact currently happen */ +free_tty_struct (o_tty); +return -ENOMEM ; + } +initialize_tty_struct (o_tty, driver->other, idx); + + tty->termios =kmalloc (sizeof (struct ktermios ),GFP_KERNEL ); +if (tty->termios ==NULL ) + goto free_mem_out; + *tty->termios = driver->init_termios; + tty->termios_locked =kzalloc (sizeof (struct ktermios ),GFP_KERNEL ); +if (tty->termios_locked ==NULL ) + goto free_mem_out; + o_tty->termios =kmalloc (sizeof (struct ktermios ),GFP_KERNEL ); +if (o_tty->termios ==NULL ) + goto free_mem_out; + *o_tty->termios = driver->other->init_termios; + o_tty->termios_locked =kzalloc (sizeof (struct ktermios ),GFP_KERNEL ); +if (o_tty->termios_locked ==NULL ) + goto free_mem_out; + +tty_driver_kref_get (driver->other); +if (driver->subtype ==PTY_TYPE_MASTER ) + o_tty->count++; +/* Establish the links in both directions */ + tty->link = o_tty; + o_tty->link = tty; +/* +* All structures have been allocated, so now we install them. +* Failures after this point use release_tty to clean up, so +* there's no need to null out the local pointers. +*/ +tty_driver_kref_get (driver); + tty->count++; + pty_count++;return 0 ; +free_mem_out: +kfree (o_tty->termios); +module_put (o_tty->driver->owner); +free_tty_struct (o_tty); +kfree (tty->termios_locked); +kfree (tty->termios); +free_tty_struct (tty); +module_put (driver->owner); +return -ENOMEM ; } -static void pty_remove (struct tty_driver *driver,struct tty_struct *tty) +static void pty_unix98_remove (struct tty_driver *driver,struct tty_struct *tty) { + pty_count--; }static const struct tty_operations ptm_unix98_ops = { .lookup = ptm_unix98_lookup, - .install = pty_install, - .remove = pty_remove, + .install = pty_unix98_install, + .remove = pty_unix98_remove, .open = pty_open, .close = pty_close, .write = pty_write,
@@ -458,13 +563,13 @@ static const struct tty_operations ptm_unix98_ops = { .unthrottle = pty_unthrottle, .set_termios = pty_set_termios, .ioctl = pty_unix98_ioctl, - .shutdown = pty_shutdown + .shutdown = pty_unix98_shutdown };static const struct tty_operations pty_unix98_ops = { .lookup = pts_unix98_lookup, - .install = pty_install, - .remove = pty_remove, + .install = pty_unix98_install, + .remove = pty_unix98_remove, .open = pty_open, .close = pty_close, .write = pty_write,
@@ -473,6 +578,7 @@ static const struct tty_operations pty_unix98_ops = { .chars_in_buffer = pty_chars_in_buffer, .unthrottle = pty_unthrottle, .set_termios = pty_set_termios, + .shutdown = pty_unix98_shutdown };/**
@@ -589,10 +695,6 @@ static void __init unix98_pty_init(void)if (tty_register_driver (pts_driver))panic ("Couldn't register Unix98 pts driver" ); -/* FIXME: WTF */ -#if 0 - pty_table[1 ].data = &ptm_driver->refcount; -#endif register_sysctl_table (pty_root_table);/* Now create the /dev/ptmx special device */
drivers/char/tty_io.c +68 -130
274 lines not on this page · raw message
include/linux/tty.h +5 -0
@@ -401,9 +401,14 @@ extern dev_t tty_devnum(struct tty_struct *tty);extern void proc_clear_tty (struct task_struct *p);extern struct tty_struct *get_current_tty (void );extern void tty_default_fops (struct file_operations *fops); +extern struct tty_struct *alloc_tty_struct (void ); +extern void free_tty_struct (struct tty_struct *tty); +extern void initialize_tty_struct (struct tty_struct *tty, +struct tty_driver *driver,int idx);extern struct tty_struct *tty_init_dev (struct tty_driver *driver,int idx,int first_ok);extern void tty_release_dev (struct file *filp); +extern int tty_init_termios (struct tty_struct *tty);extern struct mutex tty_mutex;
PATCH 55/76 Move tty lookup/reopen to caller
In reply to Alan CoxFrom: Sukadev Bhattiprolu <[email protected]>
Move tty_driver_lookup_tty() and tty_reopen() from tty_init_dev() into tty_open() (one of the two callers of tty_init_dev()). These calls are not really required in ptmx_open(), the other caller, since ptmx_open() would be setting up a new tty.
Changelog[v2]:
- remove the lookup and reopen calls from ptmx_open
- merge with recent changes to ttydev tree
---
drivers/char/tty_io.c | 31 ++++++++++++++++--------------- 1 files changed, 16 insertions(+), 15 deletions(-)
drivers/char/tty_io.c +16 -15
@@ -1376,19 +1376,6 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,struct tty_struct *tty;int retval; -/* check whether we're reopening an existing tty */ - tty =tty_driver_lookup_tty (driver, idx); - -if (IS_ERR (tty)) -return tty; - -if (tty) { - retval =tty_reopen (tty); -if (retval) -return ERR_PTR (retval); -return tty; - } -/* Check if pty master is being opened multiple times */ if (driver->subtype ==PTY_TYPE_MASTER && (driver->flags &TTY_DRIVER_DEVPTS_MEM ) && !first_ok)
@@ -1790,7 +1777,7 @@ void tty_release_dev(struct file *filp)static int __tty_open (struct inode *inode,struct file *filp) { -struct tty_struct *tty; +struct tty_struct *tty =NULL ;int noctty, retval;struct tty_driver *driver;int index;
@@ -1847,7 +1834,21 @@ retry_open:return -ENODEV ; } got_driver: - tty =tty_init_dev (driver, index,0 ); +if (!tty) { +/* check whether we're reopening an existing tty */ + tty =tty_driver_lookup_tty (driver, index); + +if (IS_ERR (tty)) +return PTR_ERR (tty); + } + +if (tty) { + retval =tty_reopen (tty); +if (retval) + tty =ERR_PTR (retval); + }else + tty =tty_init_dev (driver, index,0 ); +mutex_unlock (&tty_mutex);tty_driver_kref_put (driver);if (IS_ERR (tty))
PATCH 56/76 Add an instance parameter devpts interfaces
In reply to Alan CoxFrom: Sukadev Bhattiprolu <[email protected]>
Pass-in 'inode' or 'tty' parameter to devpts interfaces. With multiple devpts instances, these parameters will be used in subsequent patches to identify the instance of devpts mounted. The parameters also help simplify devpts implementation.
Changelog[v3]:
- minor changes due to merge with ttydev updates
- rename parameters to emphasize they are ptmx or pts inodes
- pass-in tty_struct * to devpts_pty_kill() (this will help cleanup the get_node() call in a subsequent patch)
---
drivers/char/pty.c | 18 ++++++++++-------- drivers/char/tty_io.c | 14 ++++++++------ fs/devpts/inode.c | 11 ++++++----- include/linux/devpts_fs.h | 31 +++++++++++++++++++++---------- include/linux/tty_driver.h | 3 ++- 5 files changed, 47 insertions(+), 30 deletions(-)
drivers/char/pty.c +10 -8
@@ -60,7 +60,7 @@ static void pty_close(struct tty_struct * tty, struct file * filp)set_bit (TTY_OTHER_CLOSED , &tty->flags);#ifdef CONFIG_UNIX98_PTYS if (tty->driver == ptm_driver) -devpts_pty_kill (tty->index); +devpts_pty_kill (tty->link);#endif tty_vhangup (tty->link); }
@@ -453,9 +453,10 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,* This provides our locking. */ -static struct tty_struct *ptm_unix98_lookup (struct tty_driver *driver,int idx) +static struct tty_struct *ptm_unix98_lookup (struct tty_driver *driver, +struct inode *ptm_inode,int idx) { -struct tty_struct *tty =devpts_get_tty (idx); +struct tty_struct *tty =devpts_get_tty (ptm_inode, idx);if (tty) tty = tty->link;return tty;
@@ -470,9 +471,10 @@ static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver, int idx)* This provides our locking. */ -static struct tty_struct *pts_unix98_lookup (struct tty_driver *driver,int idx) +static struct tty_struct *pts_unix98_lookup (struct tty_driver *driver, +struct inode *pts_inode,int idx) { -struct tty_struct *tty =devpts_get_tty (idx); +struct tty_struct *tty =devpts_get_tty (pts_inode, idx);/* Master must be open before slave */ if (!tty)return ERR_PTR (-EIO );
@@ -602,7 +604,7 @@ static int __ptmx_open(struct inode *inode, struct file *filp)nonseekable_open (inode, filp);/* find a device that is not in use. */ - index =devpts_new_index (); + index =devpts_new_index (inode);if (index <0 )return index;
@@ -619,7 +621,7 @@ static int __ptmx_open(struct inode *inode, struct file *filp) filp->private_data = tty;file_move (filp, &tty->tty_files); - retval =devpts_pty_new (tty->link); + retval =devpts_pty_new (inode, tty->link);if (retval) goto out1;
@@ -630,7 +632,7 @@ out1:tty_release_dev (filp);return retval; out: -devpts_kill_index (index); +devpts_kill_index (inode, index);return retval; }
drivers/char/tty_io.c +8 -6
@@ -1213,12 +1213,13 @@ static void tty_line_name(struct tty_driver *driver, int index, char *p)* be held until the 'fast-open' is also done. Will change once we * have refcounting in the driver and per driver locking */ -struct tty_struct *tty_driver_lookup_tty (struct tty_driver *driver,int idx) +struct tty_struct *tty_driver_lookup_tty (struct tty_driver *driver, +struct inode *inode,int idx) {struct tty_struct *tty;if (driver->ops->lookup) -return driver->ops->lookup (driver, idx); +return driver->ops->lookup (driver, inode, idx); tty = driver->ttys[idx];return tty;
@@ -1539,10 +1540,11 @@ void tty_release_dev(struct file *filp)int devpts;int idx;char buf[64 ]; +struct inode *inode; + inode = filp->f_path.dentry->d_inode; tty = (struct tty_struct *)filp->private_data; -if (tty_paranoia_check (tty, filp->f_path.dentry->d_inode, -"tty_release_dev" )) +if (tty_paranoia_check (tty, inode,"tty_release_dev" ))return ;check_tty_count (tty,"tty_release_dev" );
@@ -1751,7 +1753,7 @@ void tty_release_dev(struct file *filp)/* Make this pty number available for reallocation */ if (devpts) -devpts_kill_index (idx); +devpts_kill_index (inode, idx); }/**
@@ -1836,7 +1838,7 @@ retry_open: got_driver:if (!tty) {/* check whether we're reopening an existing tty */ - tty =tty_driver_lookup_tty (driver, index); + tty =tty_driver_lookup_tty (driver, inode, index);if (IS_ERR (tty))return PTR_ERR (tty);
fs/devpts/inode.c +6 -5
@@ -177,7 +177,7 @@ static struct dentry *get_node(int num)return lookup_one_len (s, root,sprintf (s,"%d" , num)); } -int devpts_new_index (void ) +int devpts_new_index (struct inode *ptmx_inode) {int index;int ida_ret;
@@ -205,14 +205,14 @@ retry:return index; } -void devpts_kill_index (int idx) +void devpts_kill_index (struct inode *ptmx_inode,int idx) {mutex_lock (&allocated_ptys_lock);ida_remove (&allocated_ptys, idx);mutex_unlock (&allocated_ptys_lock); } -int devpts_pty_new (struct tty_struct *tty) +int devpts_pty_new (struct inode *ptmx_inode,struct tty_struct *tty) {int number = tty->index;/* tty layer puts index from devpts_new_index() in here */ struct tty_driver *driver = tty->driver;
@@ -245,7 +245,7 @@ int devpts_pty_new(struct tty_struct *tty)return 0 ; } -struct tty_struct *devpts_get_tty (int number) +struct tty_struct *devpts_get_tty (struct inode *pts_inode,int number) {struct dentry *dentry =get_node (number);struct tty_struct *tty;
@@ -262,8 +262,9 @@ struct tty_struct *devpts_get_tty(int number)return tty; } -void devpts_pty_kill (int number) +void devpts_pty_kill (struct tty_struct *tty) { +int number = tty->index;struct dentry *dentry =get_node (number);if (!IS_ERR (dentry)) {
include/linux/devpts_fs.h +21 -10
@@ -17,20 +17,31 @@#ifdef CONFIG_UNIX98_PTYS -int devpts_new_index (void ); -void devpts_kill_index (int idx); -int devpts_pty_new (struct tty_struct *tty);/* mknod in devpts */ -struct tty_struct *devpts_get_tty (int number);/* get tty structure */ -void devpts_pty_kill (int number);/* unlink */ +int devpts_new_index (struct inode *ptmx_inode); +void devpts_kill_index (struct inode *ptmx_inode,int idx); +/* mknod in devpts */ +int devpts_pty_new (struct inode *ptmx_inode,struct tty_struct *tty); +/* get tty structure */ +struct tty_struct *devpts_get_tty (struct inode *pts_inode,int number); +/* unlink */ +void devpts_pty_kill (struct tty_struct *tty);#else /* Dummy stubs in the no-pty case */ -static inline int devpts_new_index (void ) {return -EINVAL ; } -static inline void devpts_kill_index (int idx) { } -static inline int devpts_pty_new (struct tty_struct *tty) {return -EINVAL ; } -static inline struct tty_struct *devpts_get_tty (int number) {return NULL ; } -static inline void devpts_pty_kill (int number) { } +static inline int devpts_new_index (struct inode *ptmx_inode) {return -EINVAL ; } +static inline void devpts_kill_index (struct inode *ptmx_inode,int idx) { } +static inline int devpts_pty_new (struct inode *ptmx_inode, +struct tty_struct *tty) +{ +return -EINVAL ; +} +static inline struct tty_struct *devpts_get_tty (struct inode *pts_inode, +int number) +{ +return NULL ; +} +static inline void devpts_pty_kill (struct tty_struct *tty) { }#endif
include/linux/tty_driver.h +2 -1
@@ -225,7 +225,8 @@ struct tty_struct;struct tty_driver ;struct tty_operations { -struct tty_struct * (*lookup)(struct tty_driver *driver,int idx); +struct tty_struct * (*lookup)(struct tty_driver *driver, +struct inode *inode,int idx);int (*install)(struct tty_driver *driver,struct tty_struct *tty);void (*remove)(struct tty_driver *driver,struct tty_struct *tty);int (*open)(struct tty_struct * tty,struct file * filp);
PATCH 57/76 Simplify devpts_get_tty()
In reply to Alan CoxFrom: Sukadev Bhattiprolu <[email protected]>
As pointed out by H. Peter Anvin, since the inode for the pty is known, we don't need to look it up.
---
fs/devpts/inode.c | 17 +++++------------ 1 files changed, 5 insertions(+), 12 deletions(-)
fs/devpts/inode.c +5 -12
@@ -27,6 +27,7 @@#define DEVPTS_SUPER_MAGIC 0x1cd1#define DEVPTS_DEFAULT_MODE 0600 +#define PTMX_MINOR 2extern int pty_limit;/* Config limit on Unix98 ptys */ static DEFINE_IDA (allocated_ptys);
@@ -247,19 +248,11 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty)struct tty_struct *devpts_get_tty (struct inode *pts_inode,int number) { -struct dentry *dentry =get_node (number); -struct tty_struct *tty; - - tty =NULL ; -if (!IS_ERR (dentry)) { -if (dentry->d_inode) - tty = dentry->d_inode->i_private; -dput (dentry); - } - -mutex_unlock (&devpts_root->d_inode->i_mutex); +BUG_ON (pts_inode->i_rdev ==MKDEV (TTYAUX_MAJOR ,PTMX_MINOR )); -return tty; +if (pts_inode->i_sb->s_magic ==DEVPTS_SUPER_MAGIC ) +return (struct tty_struct *)pts_inode->i_private; +return NULL ; }void devpts_pty_kill (struct tty_struct *tty)
PATCH 58/76 Simplify devpts_pty_new()
In reply to Alan CoxFrom: Sukadev Bhattiprolu <[email protected]>
devpts_pty_new() is called when setting up a new pty and would not will not have an existing dentry or inode for the pty. So don't bother looking for an existing dentry - just create a new one.
---
fs/devpts/inode.c | 11 ++++++++--- 1 files changed, 8 insertions(+), 3 deletions(-)
fs/devpts/inode.c +8 -3
@@ -220,6 +220,7 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty)dev_t device =MKDEV (driver->major, driver->minor_start+number);struct dentry *dentry;struct inode *inode =new_inode (devpts_mnt->mnt_sb); +char s[12 ];/* We're supposed to be given the slave end of a pty */ BUG_ON (driver->type !=TTY_DRIVER_TYPE_PTY );
@@ -235,9 +236,13 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty)init_special_inode (inode,S_IFCHR |config.mode, device); inode->i_private = tty; - dentry =get_node (number); -if (!IS_ERR (dentry) && !dentry->d_inode) { -d_instantiate (dentry, inode); +sprintf (s,"%d" , number); + +mutex_lock (&devpts_root->d_inode->i_mutex); + + dentry =d_alloc_name (devpts_root, s); +if (!IS_ERR (dentry)) { +d_add (dentry, inode);fsnotify_create (devpts_root->d_inode, dentry); }
PATCH 59/76 Simplify devpts_pty_kill
In reply to Alan CoxFrom: Sukadev Bhattiprolu <[email protected]>
When creating a new pty, save the pty's inode in the tty->driver_data. Use this inode in pty_kill() to identify the devpts instance. Since we now have the inode for the pty, we can skip get_node() lookup and remove the unused get_node().
TODO:
- check if the mutex_lock is needed in pty_kill().
---
fs/devpts/inode.c | 29 ++++++++++++----------------- 1 files changed, 12 insertions(+), 17 deletions(-)
fs/devpts/inode.c +12 -17
@@ -170,14 +170,6 @@ static struct file_system_type devpts_fs_type = {* to the System V naming convention */ -static struct dentry *get_node (int num) -{ -char s[12 ]; -struct dentry *root = devpts_root; -mutex_lock (&root->d_inode->i_mutex); -return lookup_one_len (s, root,sprintf (s,"%d" , num)); -} -int devpts_new_index (struct inode *ptmx_inode) {int index;
@@ -235,6 +227,7 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty) inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME ;init_special_inode (inode,S_IFCHR |config.mode, device); inode->i_private = tty; + tty->driver_data = inode;sprintf (s,"%d" , number);
@@ -262,18 +255,20 @@ struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number)void devpts_pty_kill (struct tty_struct *tty) { -int number = tty->index; -struct dentry *dentry =get_node (number); +struct inode *inode = tty->driver_data; +struct dentry *dentry; -if (!IS_ERR (dentry)) { -struct inode *inode = dentry->d_inode; -if (inode) { - inode->i_nlink--; -d_delete (dentry); -dput (dentry); - } +BUG_ON (inode->i_rdev ==MKDEV (TTYAUX_MAJOR ,PTMX_MINOR )); + +mutex_lock (&devpts_root->d_inode->i_mutex); + + dentry =d_find_alias (inode); +if (dentry && !IS_ERR (dentry)) { + inode->i_nlink--; +d_delete (dentry);dput (dentry); } +mutex_unlock (&devpts_root->d_inode->i_mutex); }
PATCH 60/76 pty: Coding style and polish
In reply to Alan CoxWe've done the heavy lifting now its time to mop up a bit
---
drivers/char/pty.c | 86 +++++++++++++++++++++++++++------------------------- 1 files changed, 44 insertions(+), 42 deletions(-)
drivers/char/pty.c +44 -42
@@ -8,10 +8,12 @@* Added TTY_DO_WRITE_WAKEUP to enable n_tty to send POLL_OUT to * waiting writers -- Sapan Bhatia <[email protected]> * -* +* When reading this code see also fs/devpts. In particular note that the +* driver_data field is used by the devpts side as a binding to the devpts +* inode. */ -#include <linux/module.h> /* For EXPORT_SYMBOL */ +#include <linux/module.h> #include <linux/errno.h> #include <linux/interrupt.h>
@@ -24,26 +26,24 @@#include <linux/init.h> #include <linux/sysctl.h> #include <linux/device.h> - -#include <asm/uaccess.h> -#include <asm/system.h> +#include <linux/uaccess.h> #include <linux/bitops.h> #include <linux/devpts_fs.h> +#include <asm/system.h> +/* These are global because they are accessed in tty_io.c */ #ifdef CONFIG_UNIX98_PTYS struct tty_driver *ptm_driver;static struct tty_driver *pts_driver;#endif -static void pty_close (struct tty_struct * tty,struct file * filp) +static void pty_close (struct tty_struct *tty,struct file *filp) { -if (!tty) -return ; -if (tty->driver->subtype ==PTY_TYPE_MASTER ) { -if (tty->count >1 ) -printk ("master pty_close: count = %d!!\n" , tty->count); - }else { +BUG_ON (!tty); +if (tty->driver->subtype ==PTY_TYPE_MASTER ) +WARN_ON (tty->count >1 ); +else {if (tty->count >2 )return ; }
@@ -70,13 +70,13 @@ static void pty_close(struct tty_struct * tty, struct file * filp)* The unthrottle routine is called by the line discipline to signal * that it can receive more characters. For PTY's, the TTY_THROTTLED * flag is always set, to force the line discipline to always call the -* unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE +* unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE * characters in the queue. This is necessary since each time this * happens, we need to wake up any sleeping processes that could be * (1) trying to send data to the pty, or (2) waiting in wait_until_sent() * for the pty buffer to be drained. */ -static void pty_unthrottle (struct tty_struct * tty) +static void pty_unthrottle (struct tty_struct *tty) {struct tty_struct *o_tty = tty->link;
@@ -88,7 +88,7 @@ static void pty_unthrottle(struct tty_struct * tty) }/* -* WSH 05/24/97: modified to +* WSH 05/24/97: modified to * (1) use space in tty->flip instead of a shared temp buffer * The flip buffers aren't being used for a pty, so there's lots * of space available. The buffer is protected by a per-pty
@@ -101,7 +101,8 @@ static void pty_unthrottle(struct tty_struct * tty)* not our partners. We can't just take the other one blindly without * risking deadlocks. */ -static int pty_write (struct tty_struct * tty,const unsigned char *buf,int count) +static int pty_write (struct tty_struct *tty,const unsigned char *buf, +int count) {struct tty_struct *to = tty->link;int c;
@@ -113,7 +114,7 @@ static int pty_write(struct tty_struct * tty, const unsigned char *buf, int counif (c > count) c = count; to->ldisc.ops->receive_buf (to, buf,NULL , c); - +return c; }
@@ -129,17 +130,17 @@ static int pty_write_room(struct tty_struct *tty)/* * WSH 05/24/97: Modified for asymmetric MASTER/SLAVE behavior -* The chars_in_buffer() value is used by the ldisc select() function +* The chars_in_buffer() value is used by the ldisc select() function * to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256). * The pty driver chars_in_buffer() Master/Slave must behave differently: * * The Master side needs to allow typed-ahead commands to accumulate * while being canonicalized, so we report "our buffer" as empty until * some threshold is reached, and then report the count. (Any count > -* WAKEUP_CHARS is regarded by select() as "full".) To avoid deadlock -* the count returned must be 0 if no canonical data is available to be +* WAKEUP_CHARS is regarded by select() as "full".) To avoid deadlock +* the count returned must be 0 if no canonical data is available to be * read. (The N_TTY ldisc.chars_in_buffer now knows this.) -* +* * The Slave side passes all characters in raw mode to the Master side's * buffer where they can be read immediately, so in this case we can * return the true count in the buffer.
@@ -156,21 +157,22 @@ static int pty_chars_in_buffer(struct tty_struct *tty)/* The ldisc must report 0 if no characters available to be read */ count = to->ldisc.ops->chars_in_buffer (to); -if (tty->driver->subtype ==PTY_TYPE_SLAVE )return count; +if (tty->driver->subtype ==PTY_TYPE_SLAVE ) +return count; -/* Master side driver ... if the other side's read buffer is less than +/* Master side driver ... if the other side's read buffer is less than * half full, return 0 to allow writers to proceed; otherwise return -* the count. This leaves a comfortable margin to avoid overflow, +* the count. This leaves a comfortable margin to avoid overflow, * and still allows half a buffer's worth of typed-ahead commands. */ -return ((count <N_TTY_BUF_SIZE /2 ) ?0 : count); +return (count <N_TTY_BUF_SIZE /2 ) ?0 : count; }/* Set the lock flag on a pty */ -static int pty_set_lock (struct tty_struct *tty,int __user * arg) +static int pty_set_lock (struct tty_struct *tty,int __user *arg) {int val; -if (get_user (val,arg)) +if (get_user (val, arg))return -EFAULT ;if (val)set_bit (TTY_PTY_LOCK , &tty->flags);
@@ -183,13 +185,13 @@ static void pty_flush_buffer(struct tty_struct *tty) {struct tty_struct *to = tty->link;unsigned long flags; - +if (!to)return ; - +if (to->ldisc.ops->flush_buffer) to->ldisc.ops->flush_buffer (to); - +if (to->packet) {spin_lock_irqsave (&tty->ctrl_lock, flags); tty->ctrl_status |=TIOCPKT_FLUSHWRITE ;
@@ -198,7 +200,7 @@ static void pty_flush_buffer(struct tty_struct *tty) } } -static int pty_open (struct tty_struct *tty,struct file * filp) +static int pty_open (struct tty_struct *tty,struct file *filp) {int retval = -ENODEV ;
@@ -221,10 +223,11 @@ out:return retval; } -static void pty_set_termios (struct tty_struct *tty,struct ktermios *old_termios) +static void pty_set_termios (struct tty_struct *tty, +struct ktermios *old_termios) { - tty->termios->c_cflag &= ~(CSIZE |PARENB ); - tty->termios->c_cflag |= (CS8 |CREAD ); + tty->termios->c_cflag &= ~(CSIZE |PARENB ); + tty->termios->c_cflag |= (CS8 |CREAD ); }static int pty_install (struct tty_driver *driver,struct tty_struct *tty)
@@ -254,7 +257,7 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty)tty_free_termios (tty); goto free_mem_out; } - +/* * Everything allocated ... set up the o_tty structure. */
@@ -381,9 +384,9 @@ static inline void legacy_pty_init(void) { }* Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly. */ int pty_limit =NR_UNIX98_PTY_DEFAULT ; -static int pty_limit_min =0 ; +static int pty_limit_min;static int pty_limit_max =NR_UNIX98_PTY_MAX ; -static int pty_count =0 ; +static int pty_count;static struct cdev ptmx_cdev;
@@ -537,11 +540,10 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) pty_count++;return 0 ; free_mem_out: -kfree (o_tty->termios); +pty_unix98_shutdown (o_tty);module_put (o_tty->driver->owner);free_tty_struct (o_tty); -kfree (tty->termios_locked); -kfree (tty->termios); +pty_unix98_shutdown (tty);free_tty_struct (tty);module_put (driver->owner);return -ENOMEM ;
@@ -691,13 +693,13 @@ static void __init unix98_pty_init(void)TTY_DRIVER_DYNAMIC_DEV |TTY_DRIVER_DEVPTS_MEM ; pts_driver->other = ptm_driver;tty_set_operations (pts_driver, &pty_unix98_ops); - +if (tty_register_driver (ptm_driver))panic ("Couldn't register Unix98 ptm driver" );if (tty_register_driver (pts_driver))panic ("Couldn't register Unix98 pts driver" ); -register_sysctl_table (pty_root_table); +register_sysctl_table (pty_root_table);/* Now create the /dev/ptmx special device */ tty_default_fops (&ptmx_fops);
PATCH 61/76 pty: Fix allocation failure double free
In reply to Alan CoxThe updating and moving around of the pty code added a bug where both the helper and caller free the main tty struct (the pty driver must free the o_tty pair itself however).
---
drivers/char/pty.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-)
drivers/char/pty.c +0 -2
@@ -544,8 +544,6 @@ free_mem_out:module_put (o_tty->driver->owner);free_tty_struct (o_tty);pty_unix98_shutdown (tty); -free_tty_struct (tty); -module_put (driver->owner);return -ENOMEM ; }
PATCH 62/76 pty: simplify unix98 allocation
In reply to Alan CoxWe need both termios and termios_locked so allocate them as one
---
drivers/char/pty.c | 18 +++++++----------- 1 files changed, 7 insertions(+), 11 deletions(-)
drivers/char/pty.c +7 -11
@@ -488,7 +488,6 @@ static void pty_unix98_shutdown(struct tty_struct *tty) {/* We have our own method as we don't use the tty index */ kfree (tty->termios); -kfree (tty->termios_locked); }/* We have no need to install and remove our tty objects as devpts does all
@@ -509,20 +508,17 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) }initialize_tty_struct (o_tty, driver->other, idx); - tty->termios =kmalloc (sizeof (struct ktermios ),GFP_KERNEL ); + tty->termios =kzalloc (sizeof (struct ktermios [2 ]),GFP_KERNEL );if (tty->termios ==NULL ) goto free_mem_out; *tty->termios = driver->init_termios; - tty->termios_locked =kzalloc (sizeof (struct ktermios ),GFP_KERNEL ); -if (tty->termios_locked ==NULL ) - goto free_mem_out; - o_tty->termios =kmalloc (sizeof (struct ktermios ),GFP_KERNEL ); + tty->termios_locked = tty->termios +1 ; + + o_tty->termios =kzalloc (sizeof (struct ktermios [2 ]),GFP_KERNEL );if (o_tty->termios ==NULL ) goto free_mem_out; *o_tty->termios = driver->other->init_termios; - o_tty->termios_locked =kzalloc (sizeof (struct ktermios ),GFP_KERNEL ); -if (o_tty->termios_locked ==NULL ) - goto free_mem_out; + o_tty->termios_locked = o_tty->termios +1 ;tty_driver_kref_get (driver->other);if (driver->subtype ==PTY_TYPE_MASTER )
@@ -540,10 +536,10 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) pty_count++;return 0 ; free_mem_out: -pty_unix98_shutdown (o_tty); +kfree (o_tty->termios);module_put (o_tty->driver->owner);free_tty_struct (o_tty); -pty_unix98_shutdown (tty); +kfree (tty->termios);return -ENOMEM ; }
PATCH 63/76 tty: simplify ktermios allocation
In reply to Alan CoxCopy the simplification from the pty unix98 special case to the generic one. This allows us to kill off driver->termios_locked entirely which is nice. We have to whack bits of the cris driver as it meddles in places it shouldn't providing its own arrays that were never used anyway.
---
drivers/char/tty_io.c | 46 +++++++--------------------------------------- drivers/serial/crisv10.c | 3 --- 2 files changed, 7 insertions(+), 42 deletions(-)
drivers/char/tty_io.c +7 -39
@@ -1235,27 +1235,20 @@ struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver,int tty_init_termios (struct tty_struct *tty) { -struct ktermios *tp, *ltp; +struct ktermios *tp;int idx = tty->index; tp = tty->driver->termios[idx]; - ltp = tty->driver->termios_locked[idx];if (tp ==NULL ) { -WARN_ON (ltp !=NULL ); - tp =kmalloc (sizeof (struct ktermios ),GFP_KERNEL ); - ltp =kzalloc (sizeof (struct ktermios ),GFP_KERNEL ); -if (tp ==NULL || ltp ==NULL ) { -kfree (tp); -kfree (ltp); + tp =kzalloc (sizeof (struct ktermios [2 ]),GFP_KERNEL ); +if (tp ==NULL )return -ENOMEM ; - }memcpy (tp, &tty->driver->init_termios,sizeof (struct ktermios )); tty->driver->termios[idx] = tp; - tty->driver->termios_locked[idx] = ltp; } tty->termios = tp; - tty->termios_locked = ltp; + tty->termios_locked = tp +1 ;/* Compatibility until drivers always set this */ tty->termios->c_ispeed =tty_termios_input_baud_rate (tty->termios);
@@ -1439,10 +1432,6 @@ void tty_free_termios(struct tty_struct *tty) tp = tty->termios; tty->driver->termios[idx] =NULL ;kfree (tp); - - tp = tty->termios_locked; - tty->driver->termios_locked[idx] =NULL ; -kfree (tp); } }EXPORT_SYMBOL (tty_free_termios);
@@ -1575,12 +1564,6 @@ void tty_release_dev(struct file *filp) idx, tty->name); return; } -if (tty->termios_locked != tty->driver->termios_locked[idx]) { -printk (KERN_DEBUG "tty_release_dev: driver.termios_locked[%d] not " -"termios_locked for (%s)\n" , - idx, tty->name); -return ; - } }#endif
@@ -1604,13 +1587,6 @@ void tty_release_dev(struct file *filp) idx, tty->name);return ; } -if (o_tty->termios_locked != - tty->driver->other->termios_locked[idx]) { -printk (KERN_DEBUG "tty_release_dev: other->termios_locked[" -"%d] not o_termios_locked for (%s)\n" , - idx, tty->name); -return ; - }if (o_tty->link != tty) {printk (KERN_DEBUG "tty_release_dev: bad pty pointers\n" );return ;
@@ -2930,18 +2906,13 @@ static void destruct_tty_driver(struct kref *kref) driver->termios[i] =NULL ;kfree (tp); } - tp = driver->termios_locked[i]; -if (tp) { - driver->termios_locked[i] =NULL ; -kfree (tp); - }if (!(driver->flags &TTY_DRIVER_DYNAMIC_DEV ))tty_unregister_device (driver, i); } p = driver->ttys;proc_tty_unregister_driver (driver); driver->ttys =NULL ; - driver->termios = driver->termios_locked =NULL ; + driver->termios =NULL ;kfree (p);cdev_del (&driver->cdev); }
@@ -2978,7 +2949,7 @@ int tty_register_driver(struct tty_driver *driver)void **p =NULL ;if (!(driver->flags &TTY_DRIVER_DEVPTS_MEM ) && driver->num) { - p =kzalloc (driver->num *3 *sizeof (void *),GFP_KERNEL ); + p =kzalloc (driver->num *2 *sizeof (void *),GFP_KERNEL );if (!p)return -ENOMEM ; }
@@ -3002,12 +2973,9 @@ int tty_register_driver(struct tty_driver *driver)if (p) { driver->ttys = (struct tty_struct **)p; driver->termios = (struct ktermios **)(p + driver->num); - driver->termios_locked = (struct ktermios **) - (p + driver->num *2 ); }else { driver->ttys =NULL ; driver->termios =NULL ; - driver->termios_locked =NULL ; }cdev_init (&driver->cdev, &tty_fops);
@@ -3016,7 +2984,7 @@ int tty_register_driver(struct tty_driver *driver)if (error) {unregister_chrdev_region (dev, driver->num); driver->ttys =NULL ; - driver->termios = driver->termios_locked =NULL ; + driver->termios =NULL ;kfree (p);return error; }
drivers/serial/crisv10.c +0 -3
@@ -457,7 +457,6 @@ static struct e100_serial rs_table[] = {#define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial))static struct ktermios *serial_termios[NR_PORTS ]; -static struct ktermios *serial_termios_locked[NR_PORTS ];#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER static struct fast_timer fast_timers[NR_PORTS ];#endif
@@ -4448,8 +4447,6 @@ rs_init(void) driver->init_termios.c_ispeed =115200 ; driver->init_termios.c_ospeed =115200 ; driver->flags =TTY_DRIVER_REAL_RAW |TTY_DRIVER_DYNAMIC_DEV ; - driver->termios = serial_termios; - driver->termios_locked = serial_termios_locked;tty_set_operations (driver, &rs_ops); serial_driver = driver;
PATCH 64/76 tty: some ICANON magic is in the wrong places
In reply to Alan CoxMove the set up on ldisc change into the ldisc
Move the INQ/OUTQ cases into the driver not in shared ioctl code where it gives bogus answers for other ldisc values
---
drivers/bluetooth/hci_ldisc.c | 2 +- drivers/char/n_hdlc.c | 2 +- drivers/char/n_tty.c | 53 +++++++++++++++++++++++++++++++++++++++-- drivers/char/tty_ioctl.c | 42 ++------------------------------ include/linux/tty.h | 2 +- 5 files changed, 56 insertions(+), 45 deletions(-)
drivers/bluetooth/hci_ldisc.c +1 -1
@@ -484,7 +484,7 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,return -EUNATCH ;default : - err =n_tty_ioctl (tty, file, cmd, arg); + err =n_tty_ioctl_helper (tty, file, cmd, arg);break ; };
drivers/char/n_hdlc.c +1 -1
@@ -764,7 +764,7 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,break ;default : - error =n_tty_ioctl (tty, file, cmd, arg); + error =n_tty_ioctl_helper (tty, file, cmd, arg);break ; }return error;
drivers/char/n_tty.c +51 -2
65 lines not on this page · raw message
drivers/char/tty_ioctl.c +2 -40
75 lines not on this page · raw message
include/linux/tty.h +1 -1
@@ -466,7 +466,7 @@ static inline void tty_audit_push_task(struct task_struct *tsk,#endif /* tty_ioctl.c */ -extern int n_tty_ioctl (struct tty_struct *tty,struct file *file, +extern int n_tty_ioctl_helper (struct tty_struct *tty,struct file *file,unsigned int cmd,unsigned long arg);/* serial.c */
PATCH 65/76 tty: Fallout from tty-move-canon-specials
In reply to Alan CoxFrom: Stephen Rothwell <[email protected]>
Hi Alan,
Today's linux-next build (x86_64 allmodconfig) failed like this:
/drivers/char/tty_ioctl.c: In function 'change_termios':drivers/isdn/capi/capi.c:1234: error: implicit declaration of function 'n_tty_ioctl' drivers/isdn/gigaset/ser-gigaset.c: In function 'gigaset_tty_ioctl':drivers/isdn/gigaset/ser-gigaset.c:648: error: implicit declaration of function 'n_tty_ioctl'
Introduced by commit 686b5e4aea05a80e370dc931b7f4a8d03c80da54 ("tty-move-canon-specials"). I added the following patch (which may not be correct).
--
Cheers,
Stephen Rothwell [email protected]
http://www.canb.auug.org.au/~sfr/
---
drivers/isdn/capi/capi.c | 2 +- drivers/isdn/gigaset/ser-gigaset.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
drivers/isdn/capi/capi.c +1 -1
@@ -1231,7 +1231,7 @@ static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,int error =0 ;switch (cmd) {default : - error =n_tty_ioctl (tty, file, cmd, arg); + error =n_tty_ioctl_helper (tty, file, cmd, arg);break ; }return error;
drivers/isdn/gigaset/ser-gigaset.c +2 -2
@@ -645,7 +645,7 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,case TCGETS :case TCGETA :/* pass through to underlying serial device */ - rc =n_tty_ioctl (tty, file, cmd, arg); + rc =n_tty_ioctl_helper (tty, file, cmd, arg);break ;case TCFLSH :
@@ -660,7 +660,7 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,break ; }/* flush the serial port's buffer */ - rc =n_tty_ioctl (tty, file, cmd, arg); + rc =n_tty_ioctl_helper (tty, file, cmd, arg);break ;case FIONREAD :
PATCH 66/76 tty: fix up gigaset a bit
In reply to Alan CoxStephen's fixes reminded me that gigaset is still rather broken so fix it up a bit
---
drivers/isdn/gigaset/ser-gigaset.c | 27 ++++++++++++--------------- 1 files changed, 12 insertions(+), 15 deletions(-)
drivers/isdn/gigaset/ser-gigaset.c +12 -15
@@ -571,6 +571,7 @@ gigaset_tty_close(struct tty_struct *tty) }/* prevent other callers from entering ldisc methods */ +/* FIXME: should use the tty state flags */ tty->disc_data =NULL ;if (!cs->hw.ser)
@@ -642,10 +643,11 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,return -ENXIO ;switch (cmd) { -case TCGETS : -case TCGETA : -/* pass through to underlying serial device */ - rc =n_tty_ioctl_helper (tty, file, cmd, arg); + +case FIONREAD : +/* unused, always return zero */ + val =0 ; + rc =put_user (val, p);break ;case TCFLSH :
@@ -659,20 +661,13 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,flush_send_queue (cs);break ; } -/* flush the serial port's buffer */ - rc =n_tty_ioctl_helper (tty, file, cmd, arg); -break ; - -case FIONREAD : -/* unused, always return zero */ - val =0 ; - rc =put_user (val, p); -break ; +/* Pass through */ default : - rc = -ENOIOCTLCMD ; +/* pass through to underlying serial device */ + rc =n_tty_ioctl_helper (tty, file, cmd, arg); +break ; } -cs_put (cs);return rc; }
@@ -680,6 +675,8 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,/* * Poll on the tty. * Unused, always return zero. +* +* FIXME: should probably return an exception - especially on hangup */ static unsigned int gigaset_tty_poll (struct tty_struct *tty,struct file *file,poll_table *wait)
PATCH 67/76 tty: Remove lots of NULL checks
In reply to Alan CoxMany tty drivers contain 'can't happen' checks against NULL pointers passed in by the tty layer. These have never been possible to occur. Even more importantly if they ever do occur we want to know as it would be a serious bug.
---
drivers/char/amiserial.c | 6 ------ drivers/char/generic_serial.c | 21 --------------------- drivers/char/istallion.c | 6 ------ drivers/char/mxser.c | 5 ----- drivers/char/n_r3964.c | 9 +-------- drivers/char/stallion.c | 34 ---------------------------------- 6 files changed, 1 insertions(+), 80 deletions(-)
drivers/char/amiserial.c +0 -6
@@ -837,9 +837,6 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch)struct async_struct *info;unsigned long flags; -if (!tty) -return 0 ; - info = tty->driver_data;if (serial_paranoia_check (info, tty->name,"rs_put_char" ))
@@ -892,9 +889,6 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int countstruct async_struct *info;unsigned long flags; -if (!tty) -return 0 ; - info = tty->driver_data;if (serial_paranoia_check (info, tty->name,"rs_write" ))
drivers/char/generic_serial.c +0 -21
@@ -54,8 +54,6 @@ int gs_put_char(struct tty_struct * tty, unsigned char ch)func_enter (); -if (!tty)return 0 ; - port = tty->driver_data;if (!port)return 0 ;
@@ -97,8 +95,6 @@ int gs_write(struct tty_struct * tty,func_enter (); -if (!tty)return 0 ; - port = tty->driver_data;if (!port)return 0 ;
@@ -185,7 +181,6 @@ static int gs_real_chars_in_buffer(struct tty_struct *tty)struct gs_port *port;func_enter (); -if (!tty)return 0 ; port = tty->driver_data;if (!port->rd)return 0 ;
@@ -274,8 +269,6 @@ void gs_flush_buffer(struct tty_struct *tty)func_enter (); -if (!tty)return ; - port = tty->driver_data;if (!port)return ;
@@ -296,8 +289,6 @@ void gs_flush_chars(struct tty_struct * tty)func_enter (); -if (!tty)return ; - port = tty->driver_data;if (!port)return ;
@@ -321,8 +312,6 @@ void gs_stop(struct tty_struct * tty)func_enter (); -if (!tty)return ; - port = tty->driver_data;if (!port)return ;
@@ -341,8 +330,6 @@ void gs_start(struct tty_struct * tty) {struct gs_port *port; -if (!tty)return ; - port = tty->driver_data;if (!port)return ;
@@ -393,8 +380,6 @@ void gs_hangup(struct tty_struct *tty)func_enter (); -if (!tty)return ; - port = tty->driver_data; tty = port->port.tty;if (!tty)
@@ -426,8 +411,6 @@ int gs_block_til_ready(void *port_, struct file * filp) tty = port->port.tty; -if (!tty)return 0 ; -gs_dprintk (GS_DEBUG_BTR ,"Entering gs_block_till_ready.\n" );/* * If the device is in the middle of being closed, then block
@@ -523,8 +506,6 @@ void gs_close(struct tty_struct * tty, struct file * filp)func_enter (); -if (!tty)return ; - port = (struct gs_port *) tty->driver_data;if (!port)return ;
@@ -621,8 +602,6 @@ void gs_set_termios (struct tty_struct * tty,func_enter (); -if (!tty)return ; - port = tty->driver_data;if (!port)return ;
drivers/char/istallion.c +0 -6
@@ -1375,8 +1375,6 @@ static void stli_flushchars(struct tty_struct *tty) stli_txcookrealsize =0 ; stli_txcooktty =NULL ; -if (tty ==NULL ) -return ;if (cooktty ==NULL )return ;if (tty != cooktty)
@@ -1732,8 +1730,6 @@ static void stli_settermios(struct tty_struct *tty, struct ktermios *old)struct ktermios *tiosp;asyport_t aport; -if (tty ==NULL ) -return ; portp = tty->driver_data;if (portp ==NULL )return ;
@@ -1938,8 +1934,6 @@ static void stli_waituntilsent(struct tty_struct *tty, int timeout)struct stliport *portp;unsigned long tend; -if (tty ==NULL ) -return ; portp = tty->driver_data;if (portp ==NULL )return ;
drivers/char/mxser.c +0 -5
@@ -616,9 +616,6 @@ static int mxser_set_baud(struct tty_struct *tty, long newspd)int quot =0 , baud;unsigned char cval; -if (!tty->termios) -return -1 ; -if (!info->ioaddr)return -1 ;
@@ -688,8 +685,6 @@ static int mxser_change_speed(struct tty_struct *tty,int ret =0 ;unsigned char status; -if (!tty->termios) -return ret; cflag = tty->termios->c_cflag;if (!info->ioaddr)return ret;
drivers/char/n_r3964.c +1 -8
@@ -372,15 +372,8 @@ static void remove_from_rx_queue(struct r3964_info *pInfo,static void put_char (struct r3964_info *pInfo,unsigned char ch) {struct tty_struct *tty = pInfo->tty; - -if (tty ==NULL ) -return ; -/* FIXME: put_char should not be called from an IRQ */ -if (tty->ops->put_char) { - tty->ops->put_char (tty, ch); - } - pInfo->bcc ^= ch; +tty_put_char (tty, ch); }static void flush (struct r3964_info *pInfo)
drivers/char/stallion.c +0 -34
@@ -849,8 +849,6 @@ static void stl_flushbuffer(struct tty_struct *tty)pr_debug ("stl_flushbuffer(tty=%p)\n" , tty); -if (tty ==NULL ) -return ; portp = tty->driver_data;if (portp ==NULL )return ;
@@ -868,8 +866,6 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)pr_debug ("stl_waituntilsent(tty=%p,timeout=%d)\n" , tty, timeout); -if (tty ==NULL ) -return ; portp = tty->driver_data;if (portp ==NULL )return ;
@@ -1036,8 +1032,6 @@ static int stl_putchar(struct tty_struct *tty, unsigned char ch)pr_debug ("stl_putchar(tty=%p,ch=%x)\n" , tty, ch); -if (tty ==NULL ) -return -EINVAL ; portp = tty->driver_data;if (portp ==NULL )return -EINVAL ;
@@ -1073,8 +1067,6 @@ static void stl_flushchars(struct tty_struct *tty)pr_debug ("stl_flushchars(tty=%p)\n" , tty); -if (tty ==NULL ) -return ; portp = tty->driver_data;if (portp ==NULL )return ;
@@ -1093,8 +1085,6 @@ static int stl_writeroom(struct tty_struct *tty)pr_debug ("stl_writeroom(tty=%p)\n" , tty); -if (tty ==NULL ) -return 0 ; portp = tty->driver_data;if (portp ==NULL )return 0 ;
@@ -1125,8 +1115,6 @@ static int stl_charsinbuffer(struct tty_struct *tty)pr_debug ("stl_charsinbuffer(tty=%p)\n" , tty); -if (tty ==NULL ) -return 0 ; portp = tty->driver_data;if (portp ==NULL )return 0 ;
@@ -1219,8 +1207,6 @@ static int stl_tiocmget(struct tty_struct *tty, struct file *file) {struct stlport *portp; -if (tty ==NULL ) -return -ENODEV ; portp = tty->driver_data;if (portp ==NULL )return -ENODEV ;
@@ -1236,8 +1222,6 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file,struct stlport *portp;int rts =-1 , dtr =-1 ; -if (tty ==NULL ) -return -ENODEV ; portp = tty->driver_data;if (portp ==NULL )return -ENODEV ;
@@ -1266,8 +1250,6 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmdpr_debug ("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n" , tty, file, cmd, arg); -if (tty ==NULL ) -return -ENODEV ; portp = tty->driver_data;if (portp ==NULL )return -ENODEV ;
@@ -1321,8 +1303,6 @@ static void stl_start(struct tty_struct *tty)pr_debug ("stl_start(tty=%p)\n" , tty); -if (tty ==NULL ) -return ; portp = tty->driver_data;if (portp ==NULL )return ;
@@ -1338,8 +1318,6 @@ static void stl_settermios(struct tty_struct *tty, struct ktermios *old)pr_debug ("stl_settermios(tty=%p,old=%p)\n" , tty, old); -if (tty ==NULL ) -return ; portp = tty->driver_data;if (portp ==NULL )return ;
@@ -1373,8 +1351,6 @@ static void stl_throttle(struct tty_struct *tty)pr_debug ("stl_throttle(tty=%p)\n" , tty); -if (tty ==NULL ) -return ; portp = tty->driver_data;if (portp ==NULL )return ;
@@ -1393,8 +1369,6 @@ static void stl_unthrottle(struct tty_struct *tty)pr_debug ("stl_unthrottle(tty=%p)\n" , tty); -if (tty ==NULL ) -return ; portp = tty->driver_data;if (portp ==NULL )return ;
@@ -1414,8 +1388,6 @@ static void stl_stop(struct tty_struct *tty)pr_debug ("stl_stop(tty=%p)\n" , tty); -if (tty ==NULL ) -return ; portp = tty->driver_data;if (portp ==NULL )return ;
@@ -1436,8 +1408,6 @@ static void stl_hangup(struct tty_struct *tty)pr_debug ("stl_hangup(tty=%p)\n" , tty); -if (tty ==NULL ) -return ; portp = tty->driver_data;if (portp ==NULL )return ;
@@ -1470,8 +1440,6 @@ static int stl_breakctl(struct tty_struct *tty, int state)pr_debug ("stl_breakctl(tty=%p,state=%d)\n" , tty, state); -if (tty ==NULL ) -return -EINVAL ; portp = tty->driver_data;if (portp ==NULL )return -EINVAL ;
@@ -1488,8 +1456,6 @@ static void stl_sendxchar(struct tty_struct *tty, char ch)pr_debug ("stl_sendxchar(tty=%p,ch=%x)\n" , tty, ch); -if (tty ==NULL ) -return ; portp = tty->driver_data;if (portp ==NULL )return ;
Re: [PATCH 67/76] tty: Remove lots of NULL checks
Quoted 12 lines · Alan Cox
Many tty drivers contain 'can't happen' checks against NULL pointers passed in by the tty layer. These have never been possible to occur. Even more importantly if they ever do occur we want to know as it would be a serious bug.
drivers/char/n_r3964.c +0
-0@@ -372,15 +372,8 @@ static void remove_from_rx_queue(struct r3964_info *pInfo,static void put_char (struct r3964_info *pInfo,unsigned char ch) {
drivers/char/n_r3964.c static void remove_from_rx_queue(struct r3964_info *pInfo, · line 383
Quoted 10 lines
drivers/char/n_r3964.c +0
-8struct tty_struct *tty = pInfo->tty; - -if (tty ==NULL ) -return ; -/* FIXME: put_char should not be called from an IRQ */ -if (tty->ops->put_char) { - tty->ops->put_char (tty, ch); - } - pInfo->bcc ^= ch;
^^^^^^^^^^^^^^^^
drivers/char/n_r3964.c static void remove_from_rx_queue(struct r3964_info *pInfo, · line 377
Quoted 2 lines
drivers/char/n_r3964.c +1
-0+tty_put_char (tty, ch); }
I have no idea what this `bcc' thingy does, but its removal just struck my eye...
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Re: [PATCH 67/76] tty: Remove lots of NULL checks
Quoted 2 lines
I have no idea what this `bcc' thingy does, but its removal just struck my eye...
Thanks - keeps a checksum byte per packet up to date if checksumming is in use so having the right value is a good idea.
Fixed
PATCH 68/76 tty: Minor tidyups and document fixes for n_tty
In reply to Alan CoxRemove/fix some bogus NULL checks, comment some locking etc
---
drivers/char/n_tty.c | 48 +++++++++++++++++++++++++++++++++++++----------- 1 files changed, 37 insertions(+), 11 deletions(-)
drivers/char/n_tty.c +37 -11
@@ -99,6 +99,7 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,static void n_tty_set_room (struct tty_struct *tty) { +/* tty->read_cnt is not read locked ? */ int left =N_TTY_BUF_SIZE - tty->read_cnt -1 ;/*
@@ -121,6 +122,16 @@ static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty) } } +/** +* put_tty_queue - add character to tty +* @c: character +* @tty: tty device +* +* Add a character to the tty read_buf queue. This is done under the +* read_lock to serialize character addition and also to protect us +* against parallel reads or flushes +*/ +static void put_tty_queue (unsigned char c,struct tty_struct *tty) {unsigned long flags;
@@ -137,14 +148,11 @@ static void put_tty_queue(unsigned char c, struct tty_struct *tty)* check_unthrottle - allow new receive data * @tty; tty device * -* Check whether to call the driver.unthrottle function. -* We test the TTY_THROTTLED bit first so that it always -* indicates the current state. The decision about whether -* it is worth allowing more input has been taken by the caller. +* Check whether to call the driver unthrottle functions +* * Can sleep, may be called under the atomic_read_lock mutex but * this is not guaranteed. */ -static void check_unthrottle (struct tty_struct *tty) {if (tty->count)
@@ -158,6 +166,8 @@ static void check_unthrottle(struct tty_struct *tty)* Reset the read buffer counters, clear the flags, * and make sure the driver is unthrottled. Called * from n_tty_open() and n_tty_flush_buffer(). +* +* Locking: tty_read_lock for read fields. */ static void reset_buffer_flags (struct tty_struct *tty) {
@@ -181,7 +191,7 @@ static void reset_buffer_flags(struct tty_struct *tty)* at hangup) or when the N_TTY line discipline internally has to * clean the pending queue (for example some signals). * -* Locking: ctrl_lock +* Locking: ctrl_lock, read_lock. */ static void n_tty_flush_buffer (struct tty_struct *tty)
@@ -207,6 +217,8 @@ static void n_tty_flush_buffer(struct tty_struct *tty)* * Report the number of characters buffered to be delivered to user * at this instant in time. +* +* Locking: read_lock */ static ssize_t n_tty_chars_in_buffer (struct tty_struct *tty)
@@ -410,6 +422,8 @@ break_out:* * Echo user input back onto the screen. This must be called only when * L_ECHO(tty) is true. Called from the driver receive_buf path. +* +* Relies on BKL for tty column locking */ static void echo_char (unsigned char c,struct tty_struct *tty)
@@ -422,6 +436,12 @@ static void echo_char(unsigned char c, struct tty_struct *tty)opost (c, tty); } +/** +* finsh_erasing - complete erase +* @tty: tty doing the erase +* +* Relies on BKL for tty column locking +*/ static inline void finish_erasing (struct tty_struct *tty) {if (tty->erasing) {
@@ -439,6 +459,8 @@ static inline void finish_erasing(struct tty_struct *tty)* Perform erase and necessary output when an erase character is * present in the stream from the driver layer. Handles the complexities * of UTF-8 multibyte symbols. +* +* Locking: read_lock for tty buffers, BKL for column/erasing state */ static void eraser (unsigned char c,struct tty_struct *tty)
@@ -447,6 +469,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)int head, seen_alnums, cnt;unsigned long flags; +/* FIXME: locking needed ? */ if (tty->read_head == tty->canon_head) {/* opost('\a', tty); */ /* what do you think? */ return ;
@@ -481,6 +504,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) } seen_alnums =0 ; +/* FIXME: Locking ?? */ while (tty->read_head != tty->canon_head) { head = tty->read_head;
@@ -583,6 +607,8 @@ static void eraser(unsigned char c, struct tty_struct *tty)* may caus terminal flushing to take place according to the termios * settings and character used. Called from the driver receive_buf * path so serialized. +* +* Locking: ctrl_lock, read_lock (both via flush buffer) */ static inline void isig (int sig,struct tty_struct *tty,int flush)
@@ -1007,6 +1033,8 @@ int is_ignored(int sig)* and is protected from re-entry by the tty layer. The user is * guaranteed that this function will not be re-entered or in progress * when the ldisc is closed. +* +* Locking: Caller holds tty->termios_mutex */ static void n_tty_set_termios (struct tty_struct *tty,struct ktermios *old)
@@ -1266,10 +1294,7 @@ static ssize_t read_chan(struct tty_struct *tty, struct file *file, do_it_again: -if (!tty->read_buf) { -printk (KERN_ERR "n_tty_read_chan: read_buf == NULL?!?\n" ); -return -EIO ; - } +BUG_ON (!tty->read_buf); c =job_control (tty, file);if (c <0 )
@@ -1589,7 +1614,7 @@ static unsigned long inq_canon(struct tty_struct *tty) {int nr, head, tail; -if (!tty->canon_data || !tty->read_buf) +if (!tty->canon_data)return 0 ; head = tty->canon_head; tail = tty->read_tail;
@@ -1613,6 +1638,7 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file,case TIOCOUTQ :return put_user (tty_chars_in_buffer (tty), (int __user *) arg);case TIOCINQ : +/* FIXME: Locking */ retval = tty->read_cnt;if (L_ICANON (tty)) retval =inq_canon (tty);
PATCH 69/76 hso: net driver using tty without locking
In reply to Alan CoxChecking tty == NULL doesn't help us unless we have a clear semantic for the locking of the tty object in the driver. Use the tty kref objects so that we can take references to the tty in the USB event handling paths.
---
drivers/net/usb/hso.c | 46 +++++++++++++++++++++++++++++++++++----------- 1 files changed, 35 insertions(+), 11 deletions(-)
drivers/net/usb/hso.c +35 -11
@@ -1028,14 +1028,14 @@ static void _hso_serial_set_termios(struct tty_struct *tty, termios->c_cflag |=CS8 ;/* character size 8 bits */ /* baud rate 115200 */ -tty_encode_baud_rate (serial->tty,115200 ,115200 ); +tty_encode_baud_rate (tty,115200 ,115200 );/* * Force low_latency on; otherwise the pushes are scheduled; * this is bad as it opens up the possibility of dropping bytes * on the floor. We don't want to drop bytes on the floor. :) */ - serial->tty->low_latency =1 ; + tty->low_latency =1 ;return ; }
@@ -1061,8 +1061,10 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)kref_get (&serial->parent->ref);/* setup */ +spin_lock_irq (&serial->serial_lock); tty->driver_data = serial; - serial->tty = tty; + serial->tty =tty_kref_get (tty); +spin_unlock_irq (&serial->serial_lock);/* check for port allready opened, if not set the termios */ serial->open_count++;
@@ -1111,10 +1113,13 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp)kref_put (&serial->parent->ref, hso_serial_ref_free);if (serial->open_count <=0 ) { serial->open_count =0 ; -if (serial->tty) { +spin_lock_irq (&serial->serial_lock); +if (serial->tty == tty) { serial->tty->driver_data =NULL ; serial->tty =NULL ; +tty_kref_put (tty); } +spin_unlock_irq (&serial->serial_lock);if (!usb_gone)hso_stop_serial_device (serial->parent); }
@@ -1457,6 +1462,7 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb) {struct hso_serial *serial = urb->context;int status = urb->status; +struct tty_struct *tty;/* sanity check */ if (!serial) {
@@ -1466,14 +1472,18 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb)spin_lock (&serial->serial_lock); serial->tx_urb_used =0 ; + tty =tty_kref_get (serial->tty);spin_unlock (&serial->serial_lock);if (status) {log_usb_status (status, __func__); +tty_kref_put (tty);return ; }hso_put_activity (serial->parent); -if (serial->tty) -tty_wakeup (serial->tty); +if (tty) { +tty_wakeup (tty); +tty_kref_put (tty); + }hso_kick_transmit (serial);D1 (" " );
@@ -1510,6 +1520,7 @@ static void ctrl_callback(struct urb *urb)struct hso_serial *serial = urb->context;struct usb_ctrlrequest *req;int status = urb->status; +struct tty_struct *tty;/* sanity check */ if (!serial)
@@ -1517,9 +1528,11 @@ static void ctrl_callback(struct urb *urb)spin_lock (&serial->serial_lock); serial->tx_urb_used =0 ; + tty =tty_kref_get (serial->tty);spin_unlock (&serial->serial_lock);if (status) {log_usb_status (status, __func__); +tty_kref_put (tty);return ; }
@@ -1544,17 +1557,18 @@ static void ctrl_callback(struct urb *urb)clear_bit (HSO_SERIAL_FLAG_RX_SENT , &serial->flags); }else {hso_put_activity (serial->parent); -if (serial->tty) -tty_wakeup (serial->tty); +if (tty) +tty_wakeup (tty);/* response to a write command */ hso_kick_transmit (serial); } +tty_kref_put (tty); }/* handle RX data for serial port */ static void put_rxbuf_data (struct urb *urb,struct hso_serial *serial) { -struct tty_struct *tty = serial->tty; +struct tty_struct *tty;/* Sanity check */ if (urb ==NULL || serial ==NULL ) {
@@ -1562,6 +1576,10 @@ static void put_rxbuf_data(struct urb *urb, struct hso_serial *serial)return ; } +spin_lock (&serial->serial_lock); + tty =tty_kref_get (serial->tty); +spin_unlock (&serial->serial_lock); +/* Push data to tty */ if (tty && urb->actual_length) {D1 ("data to push to tty" );
@@ -1569,6 +1587,7 @@ static void put_rxbuf_data(struct urb *urb, struct hso_serial *serial) urb->actual_length);tty_flip_buffer_push (tty); } +tty_kref_put (tty); }/* read callback for Diag and CS port */
@@ -2635,15 +2654,20 @@ static void hso_serial_ref_free(struct kref *ref)static void hso_free_interface (struct usb_interface *interface) {struct hso_serial *hso_dev; +struct tty_struct *tty;int i;for (i =0 ; i <HSO_SERIAL_TTY_MINORS ; i++) {if (serial_table[i] && (serial_table[i]->interface == interface)) { hso_dev =dev2ser (serial_table[i]); -if (hso_dev->tty) -tty_hangup (hso_dev->tty); +spin_lock_irq (&hso_dev->serial_lock); + tty =tty_kref_get (hso_dev->tty); +spin_unlock_irq (&hso_dev->serial_lock); +if (tty) +tty_hangup (tty);mutex_lock (&hso_dev->parent->mutex); +tty_kref_put (tty); hso_dev->parent->usb_gone =1 ;mutex_unlock (&hso_dev->parent->mutex);kref_put (&serial_table[i]->ref, hso_serial_ref_free);
PATCH 70/76 applicom: Fix an unchecked user ioctl range and an error return
In reply to Alan CoxCloses bug #11408 by checking the card index range for command 0 Fixes the ioctl to return ENOTTY which is correct for unknown ioctls
---
drivers/char/applicom.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-)
drivers/char/applicom.c +2 -4
@@ -712,8 +712,7 @@ static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un IndexCard = adgl->num_card-1 ; -if (cmd !=0 && cmd !=6 && - ((IndexCard >=MAX_BOARD ) || !apbs[IndexCard].RamIO)) { +if (cmd !=6 && ((IndexCard >=MAX_BOARD ) || !apbs[IndexCard].RamIO)) {static int warncount =10 ;if (warncount) {printk (KERN_WARNING "APPLICOM driver IOCTL, bad board number %d\n" ,(int )IndexCard+1 );
@@ -832,8 +831,7 @@ static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un }break ;default : -printk (KERN_INFO "APPLICOM driver ioctl, unknown function code %d\n" ,cmd) ; - ret = -EINVAL ; + ret = -ENOTTY ;break ; } Dummy =readb (apbs[IndexCard].RamIO +VERS );
PATCH 71/76 serial-make-uart_ports-ioport-unsigned-long-fix
In reply to Alan CoxFrom: Andrew Morton <[email protected]>
---
drivers/serial/serial_core.c | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-)
drivers/serial/serial_core.c +2 -3
@@ -2154,12 +2154,11 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)switch (port->iotype) {case UPIO_PORT : -snprintf (address,sizeof (address), -"I/O 0x%x" , port->iobase); +snprintf (address,sizeof (address),"I/O 0x%lx" , port->iobase);break ;case UPIO_HUB6 :snprintf (address,sizeof (address), -"I/O 0x%x offset 0x%x" , port->iobase, port->hub6); +"I/O 0x%lx offset 0x%x" , port->iobase, port->hub6);break ;case UPIO_MEM :case UPIO_MEM32 :
PATCH 72/76 serial: allow 8250 to be used on sparc
In reply to Alan CoxFrom: David Miller <[email protected]>
This requires three changes:
1) Remove !SPARC restriction in Kconfig.
2) Move Sparc specific serial drivers before 8250, so that serial console devices don't change names on us, even if 8250 finds devices.
3) Since the Sparc specific serial drivers try to use the same major/minor device namespace as 8250, some coordination is necessary. Use the sunserial_*() layer routines to allocate minor number space within TTY_MAJOR when CONFIG_SPARC.
This has no effect on other platforms.
Thanks to Josip Rodin for bringing up this issue and testing plus debugging various revisions of this patch.
---
arch/sparc/include/asm/serial.h | 6 ++++++ drivers/serial/8250.c | 18 +++++++++++++++++- drivers/serial/Kconfig | 1 - drivers/serial/Makefile | 15 ++++++++++----- 4 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 arch/sparc/include/asm/serial.h
arch/sparc/include/asm/serial.h new file +6 -0
@@ -0,0 +1,6 @@ +#ifndef __SPARC_SERIAL_H +#define __SPARC_SERIAL_H + +#define BASE_BAUD ( 1843200 / 16 ) + +#endif /* __SPARC_SERIAL_H */
drivers/serial/8250.c +17 -1
@@ -44,6 +44,10 @@#include "8250.h" +#ifdef CONFIG_SPARC +#include "suncore.h" +#endif +/* * Configuration: * share_irqs - whether we pass IRQF_SHARED to request_irq(). This option
@@ -2721,7 +2725,6 @@ static struct uart_driver serial8250_reg = { .dev_name = "ttyS", .major = TTY_MAJOR, .minor = 64, - .nr = UART_NR, .cons = SERIAL8250_CONSOLE, };
@@ -3003,7 +3006,12 @@ static int __init serial8250_init(void)"%d ports, IRQ sharing %sabled\n" , nr_uarts, share_irqs ? "en" : "dis"); +#ifdef CONFIG_SPARC + ret =sunserial_register_minors (&serial8250_reg,UART_NR ); +#else + serial8250_reg.nr =UART_NR ; ret =uart_register_driver (&serial8250_reg); +#endif if (ret) goto out;
@@ -3028,7 +3036,11 @@ static int __init serial8250_init(void) put_dev:platform_device_put (serial8250_isa_devs); unreg_uart_drv: +#ifdef CONFIG_SPARC +sunserial_unregister_minors (&serial8250_reg,UART_NR ); +#else uart_unregister_driver (&serial8250_reg); +#endif out:return ret; }
@@ -3047,7 +3059,11 @@ static void __exit serial8250_exit(void)platform_driver_unregister (&serial8250_isa_driver);platform_device_unregister (isa_dev); +#ifdef CONFIG_SPARC +sunserial_unregister_minors (&serial8250_reg,UART_NR ); +#else uart_unregister_driver (&serial8250_reg); +#endif }module_init (serial8250_init);
drivers/serial/Kconfig +0 -1
@@ -9,7 +9,6 @@ menu "Serial drivers" # The new 8250/16550 serial drivers config SERIAL_8250 tristate "8250/16550 and compatible serial support" - depends on (BROKEN || !SPARC) select SERIAL_CORE ---help--- This selects whether you want to include the driver for the standard
drivers/serial/Makefile +10 -5
@@ -4,6 +4,16 @@ obj-$(CONFIG_SERIAL_CORE) += serial_core.o obj-$(CONFIG_SERIAL_21285) += 21285.o + +# These Sparc drivers have to appear before others such as 8250 +# which share ttySx minor node space. Otherwise console device +# names change and other unplesantries. +obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o +obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o +obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o +obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o +obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o + obj-$(CONFIG_SERIAL_8250) += 8250.o obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
@@ -31,12 +41,7 @@ obj-$(CONFIG_SERIAL_S3C2400) += s3c2400.o obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o -obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o -obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o -obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o -obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o -obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o obj-$(CONFIG_SERIAL_MUX) += mux.o obj-$(CONFIG_SERIAL_68328) += 68328serial.o obj-$(CONFIG_SERIAL_68360) += 68360serial.o
PATCH 73/76 serial: fix device name reporting when minor space is shared between drivers
In reply to Alan CoxFrom: David S. Miller <[email protected]>
The multiple drivers share the minor space occupied by a particular major number, the actual index within the device name's space is indicated by the tty_driver->name_base + uart_port->line
Another usable formula is (uart_driver->minor - MINOR_BASE) + port->line
Use those to print the device names properly in such situations in serial_core.c and 8250.c
---
drivers/serial/8250.c | 22 +++++++++++++++------- drivers/serial/serial_core.c | 7 +++++-- 2 files changed, 20 insertions(+), 9 deletions(-)
drivers/serial/8250.c +15 -7
@@ -57,6 +57,13 @@ static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;static unsigned int nr_uarts =CONFIG_SERIAL_8250_RUNTIME_UARTS ; +static struct uart_driver serial8250_reg; + +static int serial_index (struct uart_port *port) +{ +return (serial8250_reg.minor -64 ) + port->line; +} +/* * Debugging. */
@@ -1001,7 +1008,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)return ;DEBUG_AUTOCONF ("ttyS%d: autoconf (0x%04x, 0x%p): " , - up->port.line, up->port.iobase, up->port.membase); +serial_index (&up->port), up->port.iobase, up->port.membase);/* * We really do need global IRQs disabled here - we're going to
@@ -1136,8 +1143,8 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)if (up->capabilities != uart_config[up->port.type].flags) {printk (KERN_WARNING "ttyS%d: detected caps %08x should be %08x\n" , - up->port.line, up->capabilities, - uart_config[up->port.type].flags); +serial_index (&up->port), up->capabilities, + uart_config[up->port.type].flags); } up->port.fifosize = uart_config[up->port.type].fifo_size;
@@ -1902,7 +1909,8 @@ static int serial8250_startup(struct uart_port *port)*/ if (!(up->port.flags &UPF_BUGGY_UART ) && (serial_inp (up,UART_LSR ) ==0xff )) { -printk ("ttyS%d: LSR safety check engaged!\n" , up->port.line); +printk (KERN_INFO "ttyS%d: LSR safety check engaged!\n" , +serial_index (&up->port));return -ENODEV ; }
@@ -1957,7 +1965,8 @@ static int serial8250_startup(struct uart_port *port)*/ if (!(iir1 &UART_IIR_NO_INT ) && (iir &UART_IIR_NO_INT )) { up->bugs |=UART_BUG_THRE ; -pr_debug ("ttyS%d - using backup timer\n" , port->line); +pr_debug ("ttyS%d - using backup timer\n" , +serial_index (port)); } }
@@ -2017,7 +2026,7 @@ static int serial8250_startup(struct uart_port *port)if (!(up->bugs &UART_BUG_TXEN )) { up->bugs |=UART_BUG_TXEN ;pr_debug ("ttyS%d - enabling bad tx status workarounds\n" , - port->line); +serial_index (port)); } }else { up->bugs &= ~UART_BUG_TXEN ;
@@ -2678,7 +2687,6 @@ static int serial8250_console_early_setup(void)return serial8250_find_port_for_earlycon (); } -static struct uart_driver serial8250_reg;static struct console serial8250_console = { .name ="ttyS" , .write = serial8250_console_write,
drivers/serial/serial_core.c +5 -2
@@ -2051,7 +2051,8 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)"transmitter\n" , port->dev ? port->dev->bus_id :"" , port->dev ?": " :"" , - drv->dev_name, port->line); + drv->dev_name, + drv->tty_driver->name_base + port->line); ops->shutdown (port); }
@@ -2176,7 +2177,9 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)printk (KERN_INFO "%s%s%s%d at %s (irq = %d) is a %s\n" , port->dev ? port->dev->bus_id :"" , port->dev ?": " :"" , - drv->dev_name, port->line, address, port->irq,uart_type (port)); + drv->dev_name, + drv->tty_driver->name_base + port->line, + address, port->irq,uart_type (port)); } static void
PATCH 74/76 tty: tty_io.c shadows sparse fix
In reply to Alan CoxFrom: Jason Wessel <[email protected]>
drivers/char/tty_io.c:1413:17: warning: symbol 'buf' shadows an earlier one drivers/char/tty_io.c:1379:20: originally declared here
---
drivers/char/tty_io.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
drivers/char/tty_io.c +4 -4
@@ -1026,19 +1026,19 @@ static inline ssize_t do_tty_write(/* write_buf/write_cnt is protected by the atomic_write_lock mutex */ if (tty->write_cnt < chunk) { -unsigned char *buf; +unsigned char *buf_chunk;if (chunk <1024 ) chunk =1024 ; - buf =kmalloc (chunk,GFP_KERNEL ); -if (!buf) { + buf_chunk =kmalloc (chunk,GFP_KERNEL ); +if (!buf_chunk) { ret = -ENOMEM ; goto out; }kfree (tty->write_buf); tty->write_cnt = chunk; - tty->write_buf = buf; + tty->write_buf = buf_chunk; }/* Do the write .. */
PATCH 75/76 usb: fix pl2303 initialization
In reply to Alan CoxFrom: Jason Wessel <[email protected]>
This patch removes the private check for the termios_initialized for the pl2303 usb driver. It forced the baud to 9600 on the first call to pl2303_set_termios()
Based on the tty changes in the 2.6.27 kernel, the termios passed to the *_set_termios functions is always populated the first time.
This means there is no need to privately initialize the settings the first time, and doing so will not allow the use of the kernel parameter "console=ttyUSB0,115200" as an example.
---
drivers/usb/serial/pl2303.c | 11 ----------- 1 files changed, 0 insertions(+), 11 deletions(-)
drivers/usb/serial/pl2303.c +0 -11
@@ -154,7 +154,6 @@ struct pl2303_private {wait_queue_head_t delta_msr_wait;u8 line_control;u8 line_status; -u8 termios_initialized;enum pl2303_type type; };
@@ -526,16 +525,6 @@ static void pl2303_set_termios(struct tty_struct *tty,dbg ("%s - port %d" , __func__, port->number); -spin_lock_irqsave (&priv->lock, flags); -if (!priv->termios_initialized) { - *(tty->termios) = tty_std_termios; - tty->termios->c_cflag =B9600 |CS8 |CREAD |HUPCL |CLOCAL ; - tty->termios->c_ispeed =9600 ; - tty->termios->c_ospeed =9600 ; - priv->termios_initialized =1 ; - } -spin_unlock_irqrestore (&priv->lock, flags); -/* The PL2303 is reported to lose bytes if you change serial settings even to the same values as before. Thus we actually need to filter in this specific case */
PATCH 76/76 ftdi: A few errors are err() that should be debug which causes much spewage
In reply to Alan CoxFixes #10783
---
drivers/usb/serial/ftdi_sio.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
drivers/usb/serial/ftdi_sio.c +3 -3
@@ -860,7 +860,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set,kfree (buf);if (rv <0 ) { - err("%s Error from MODEM_CTRL urb: DTR %s, RTS %s", + dbg("%s Error from MODEM_CTRL urb: DTR %s, RTS %s", __func__, (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged",
@@ -2259,7 +2259,7 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)0 ,0 , buf, 1, WDR_TIMEOUT);if (ret <0 ) { -err ("%s Could not get modem status of device - err: %d" , __func__, +dbg ("%s Could not get modem status of device - err: %d" , __func__, ret);return ret; }
@@ -2278,7 +2278,7 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)0 , priv->interface, buf, 2, WDR_TIMEOUT);if (ret <0 ) { -err ("%s Could not get modem status of device - err: %d" , __func__, +dbg ("%s Could not get modem status of device - err: %d" , __func__, ret);return ret; }