diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-11 18:34:40 -0500 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-11 18:34:40 -0500 | 
| commit | 0f4974c439dd7826c85bae4e6a8088ce2db0f498 (patch) | |
| tree | fdabc7d9bb7d7bc49aad547c0aac3a633ce01f09 | |
| parent | 3126c136bc30225d7a43af741778aa50e95e467a (diff) | |
| parent | 36ba782e9674cdc29ec7003757df0b375e99fa96 (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (58 commits)
  tty: split the lock up a bit further
  tty: Move the leader test in disassociate
  tty: Push the bkl down a bit in the hangup code
  tty: Push the lock down further into the ldisc code
  tty: push the BKL down into the handlers a bit
  tty: moxa: split open lock
  tty: moxa: Kill the use of lock_kernel
  tty: moxa: Fix modem op locking
  tty: moxa: Kill off the throttle method
  tty: moxa: Locking clean up
  tty: moxa: rework the locking a bit
  tty: moxa: Use more tty_port ops
  tty: isicom: fix deadlock on shutdown
  tty: mxser: Use the new locking rules to fix setserial properly
  tty: mxser: use the tty_port_open method
  tty: isicom: sort out the board init logic
  tty: isicom: switch to the new tty_port_open helper
  tty: tty_port: Add a kref object to the tty port
  tty: istallion: tty port open/close methods
  tty: stallion: Convert to the tty_port_open/close methods
  ...
36 files changed, 921 insertions, 3820 deletions
| diff --git a/Documentation/serial/hayes-esp.txt b/Documentation/serial/hayes-esp.txt deleted file mode 100644 index 09b5d5856758..000000000000 --- a/Documentation/serial/hayes-esp.txt +++ /dev/null | |||
| @@ -1,154 +0,0 @@ | |||
| 1 | HAYES ESP DRIVER VERSION 2.1 | ||
| 2 | |||
| 3 | A big thanks to the people at Hayes, especially Alan Adamson. Their support | ||
| 4 | has enabled me to provide enhancements to the driver. | ||
| 5 | |||
| 6 | Please report your experiences with this driver to me (arobinso@nyx.net). I | ||
| 7 | am looking for both positive and negative feedback. | ||
| 8 | |||
| 9 | *** IMPORTANT CHANGES FOR 2.1 *** | ||
| 10 | Support for PIO mode. Five situations will cause PIO mode to be used: | ||
| 11 | 1) A multiport card is detected. PIO mode will always be used. (8 port cards | ||
| 12 | do not support DMA). | ||
| 13 | 2) The DMA channel is set to an invalid value (anything other than 1 or 3). | ||
| 14 | 3) The DMA buffer/channel could not be allocated. The port will revert to PIO | ||
| 15 | mode until it is reopened. | ||
| 16 | 4) Less than a specified number of bytes need to be transferred to/from the | ||
| 17 | FIFOs. PIO mode will be used for that transfer only. | ||
| 18 | 5) A port needs to do a DMA transfer and another port is already using the | ||
| 19 | DMA channel. PIO mode will be used for that transfer only. | ||
| 20 | |||
| 21 | Since the Hayes ESP seems to conflict with other cards (notably sound cards) | ||
| 22 | when using DMA, DMA is turned off by default. To use DMA, it must be turned | ||
| 23 | on explicitly, either with the "dma=" option described below or with | ||
| 24 | setserial. A multiport card can be forced into DMA mode by using setserial; | ||
| 25 | however, most multiport cards don't support DMA. | ||
| 26 | |||
| 27 | The latest version of setserial allows the enhanced configuration of the ESP | ||
| 28 | card to be viewed and modified. | ||
| 29 | *** | ||
| 30 | |||
| 31 | This package contains the files needed to compile a module to support the Hayes | ||
| 32 | ESP card. The drivers are basically a modified version of the serial drivers. | ||
| 33 | |||
| 34 | Features: | ||
| 35 | |||
| 36 | - Uses the enhanced mode of the ESP card, allowing a wider range of | ||
| 37 | interrupts and features than compatibility mode | ||
| 38 | - Uses DMA and 16 bit PIO mode to transfer data to and from the ESP's FIFOs, | ||
| 39 | reducing CPU load | ||
| 40 | - Supports primary and secondary ports | ||
| 41 | |||
| 42 | |||
| 43 | If the driver is compiled as a module, the IRQs to use can be specified by | ||
| 44 | using the irq= option. The format is: | ||
| 45 | |||
| 46 | irq=[0x100],[0x140],[0x180],[0x200],[0x240],[0x280],[0x300],[0x380] | ||
| 47 | |||
| 48 | The address in brackets is the base address of the card. The IRQ of | ||
| 49 | nonexistent cards can be set to 0. If an IRQ of a card that does exist is set | ||
| 50 | to 0, the driver will attempt to guess at the correct IRQ. For example, to set | ||
| 51 | the IRQ of the card at address 0x300 to 12, the insmod command would be: | ||
| 52 | |||
| 53 | insmod esp irq=0,0,0,0,0,0,12,0 | ||
| 54 | |||
| 55 | The custom divisor can be set by using the divisor= option. The format is the | ||
| 56 | same as for the irq= option. Each divisor value is a series of hex digits, | ||
| 57 | with each digit representing the divisor to use for a corresponding port. The | ||
| 58 | divisor value is constructed RIGHT TO LEFT. Specifying a nonzero divisor value | ||
| 59 | will automatically set the spd_cust flag. To calculate the divisor to use for | ||
| 60 | a certain baud rate, divide the port's base baud (generally 921600) by the | ||
| 61 | desired rate. For example, to set the divisor of the primary port at 0x300 to | ||
| 62 | 4 and the divisor of the secondary port at 0x308 to 8, the insmod command would | ||
| 63 | be: | ||
| 64 | |||
| 65 | insmod esp divisor=0,0,0,0,0,0,0x84,0 | ||
| 66 | |||
| 67 | The dma= option can be used to set the DMA channel. The channel can be either | ||
| 68 | 1 or 3. Specifying any other value will force the driver to use PIO mode. | ||
| 69 | For example, to set the DMA channel to 3, the insmod command would be: | ||
| 70 | |||
| 71 | insmod esp dma=3 | ||
| 72 | |||
| 73 | The rx_trigger= and tx_trigger= options can be used to set the FIFO trigger | ||
| 74 | levels. They specify when the ESP card should send an interrupt. Larger | ||
| 75 | values will decrease the number of interrupts; however, a value too high may | ||
| 76 | result in data loss. Valid values are 1 through 1023, with 768 being the | ||
| 77 | default. For example, to set the receive trigger level to 512 bytes and the | ||
| 78 | transmit trigger level to 700 bytes, the insmod command would be: | ||
| 79 | |||
| 80 | insmod esp rx_trigger=512 tx_trigger=700 | ||
| 81 | |||
| 82 | The flow_off= and flow_on= options can be used to set the hardware flow off/ | ||
| 83 | flow on levels. The flow on level must be lower than the flow off level, and | ||
| 84 | the flow off level should be higher than rx_trigger. Valid values are 1 | ||
| 85 | through 1023, with 1016 being the default flow off level and 944 being the | ||
| 86 | default flow on level. For example, to set the flow off level to 1000 bytes | ||
| 87 | and the flow on level to 935 bytes, the insmod command would be: | ||
| 88 | |||
| 89 | insmod esp flow_off=1000 flow_on=935 | ||
| 90 | |||
| 91 | The rx_timeout= option can be used to set the receive timeout value. This | ||
| 92 | value indicates how long after receiving the last character that the ESP card | ||
| 93 | should wait before signalling an interrupt. Valid values are 0 though 255, | ||
| 94 | with 128 being the default. A value too high will increase latency, and a | ||
| 95 | value too low will cause unnecessary interrupts. For example, to set the | ||
| 96 | receive timeout to 255, the insmod command would be: | ||
| 97 | |||
| 98 | insmod esp rx_timeout=255 | ||
| 99 | |||
| 100 | The pio_threshold= option sets the threshold (in number of characters) for | ||
| 101 | using PIO mode instead of DMA mode. For example, if this value is 32, | ||
| 102 | transfers of 32 bytes or less will always use PIO mode. | ||
| 103 | |||
| 104 | insmod esp pio_threshold=32 | ||
| 105 | |||
| 106 | Multiple options can be listed on the insmod command line by separating each | ||
| 107 | option with a space. For example: | ||
| 108 | |||
| 109 | insmod esp dma=3 trigger=512 | ||
| 110 | |||
| 111 | The esp module can be automatically loaded when needed. To cause this to | ||
| 112 | happen, add the following lines to /etc/modprobe.conf (replacing the last line | ||
| 113 | with options for your configuration): | ||
| 114 | |||
| 115 | alias char-major-57 esp | ||
| 116 | alias char-major-58 esp | ||
| 117 | options esp irq=0,0,0,0,0,0,3,0 divisor=0,0,0,0,0,0,0x4,0 | ||
| 118 | |||
| 119 | You may also need to run 'depmod -a'. | ||
| 120 | |||
| 121 | Devices must be created manually. To create the devices, note the output from | ||
| 122 | the module after it is inserted. The output will appear in the location where | ||
| 123 | kernel messages usually appear (usually /var/adm/messages). Create two devices | ||
| 124 | for each 'tty' mentioned, one with major of 57 and the other with major of 58. | ||
| 125 | The minor number should be the same as the tty number reported. The commands | ||
| 126 | would be (replace ? with the tty number): | ||
| 127 | |||
| 128 | mknod /dev/ttyP? c 57 ? | ||
| 129 | mknod /dev/cup? c 58 ? | ||
| 130 | |||
| 131 | For example, if the following line appears: | ||
| 132 | |||
| 133 | Oct 24 18:17:23 techno kernel: ttyP8 at 0x0140 (irq = 3) is an ESP primary port | ||
| 134 | |||
| 135 | ...two devices should be created: | ||
| 136 | |||
| 137 | mknod /dev/ttyP8 c 57 8 | ||
| 138 | mknod /dev/cup8 c 58 8 | ||
| 139 | |||
| 140 | You may need to set the permissions on the devices: | ||
| 141 | |||
| 142 | chmod 666 /dev/ttyP* | ||
| 143 | chmod 666 /dev/cup* | ||
| 144 | |||
| 145 | The ESP module and the serial module should not conflict (they can be used at | ||
| 146 | the same time). After the ESP module has been loaded the ports on the ESP card | ||
| 147 | will no longer be accessible by the serial driver. | ||
| 148 | |||
| 149 | If I/O errors are experienced when accessing the port, check for IRQ and DMA | ||
| 150 | conflicts ('cat /proc/interrupts' and 'cat /proc/dma' for a list of IRQs and | ||
| 151 | DMAs currently in use). | ||
| 152 | |||
| 153 | Enjoy! | ||
| 154 | Andrew J. Robinson <arobinso@nyx.net> | ||
| diff --git a/Documentation/serial/tty.txt b/Documentation/serial/tty.txt index 8e65c4498c52..5e5349a4fcd2 100644 --- a/Documentation/serial/tty.txt +++ b/Documentation/serial/tty.txt | |||
| @@ -42,7 +42,8 @@ TTY side interfaces: | |||
| 42 | open() - Called when the line discipline is attached to | 42 | open() - Called when the line discipline is attached to | 
| 43 | the terminal. No other call into the line | 43 | the terminal. No other call into the line | 
| 44 | discipline for this tty will occur until it | 44 | discipline for this tty will occur until it | 
| 45 | completes successfully. Can sleep. | 45 | completes successfully. Returning an error will | 
| 46 | prevent the ldisc from being attached. Can sleep. | ||
| 46 | 47 | ||
| 47 | close() - This is called on a terminal when the line | 48 | close() - This is called on a terminal when the line | 
| 48 | discipline is being unplugged. At the point of | 49 | discipline is being unplugged. At the point of | 
| @@ -52,7 +53,7 @@ close() - This is called on a terminal when the line | |||
| 52 | hangup() - Called when the tty line is hung up. | 53 | hangup() - Called when the tty line is hung up. | 
| 53 | The line discipline should cease I/O to the tty. | 54 | The line discipline should cease I/O to the tty. | 
| 54 | No further calls into the ldisc code will occur. | 55 | No further calls into the ldisc code will occur. | 
| 55 | Can sleep. | 56 | The return value is ignored. Can sleep. | 
| 56 | 57 | ||
| 57 | write() - A process is writing data through the line | 58 | write() - A process is writing data through the line | 
| 58 | discipline. Multiple write calls are serialized | 59 | discipline. Multiple write calls are serialized | 
| @@ -83,6 +84,10 @@ ioctl() - Called when an ioctl is handed to the tty layer | |||
| 83 | that might be for the ldisc. Multiple ioctl calls | 84 | that might be for the ldisc. Multiple ioctl calls | 
| 84 | may occur in parallel. May sleep. | 85 | may occur in parallel. May sleep. | 
| 85 | 86 | ||
| 87 | compat_ioctl() - Called when a 32 bit ioctl is handed to the tty layer | ||
| 88 | that might be for the ldisc. Multiple ioctl calls | ||
| 89 | may occur in parallel. May sleep. | ||
| 90 | |||
| 86 | Driver Side Interfaces: | 91 | Driver Side Interfaces: | 
| 87 | 92 | ||
| 88 | receive_buf() - Hand buffers of bytes from the driver to the ldisc | 93 | receive_buf() - Hand buffers of bytes from the driver to the ldisc | 
| diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index 4c559cf7da2d..e60a1f57022f 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c | |||
| @@ -196,7 +196,7 @@ static const struct file_operations rs_proc_fops = { | |||
| 196 | .release = single_release, | 196 | .release = single_release, | 
| 197 | }; | 197 | }; | 
| 198 | 198 | ||
| 199 | static struct tty_operations serial_ops = { | 199 | static const struct tty_operations serial_ops = { | 
| 200 | .open = rs_open, | 200 | .open = rs_open, | 
| 201 | .close = rs_close, | 201 | .close = rs_close, | 
| 202 | .write = rs_write, | 202 | .write = rs_write, | 
| diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 6aad99ec4e0f..6f31c9472100 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
| @@ -201,19 +201,6 @@ config DIGIEPCA | |||
| 201 | To compile this driver as a module, choose M here: the | 201 | To compile this driver as a module, choose M here: the | 
| 202 | module will be called epca. | 202 | module will be called epca. | 
| 203 | 203 | ||
| 204 | config ESPSERIAL | ||
| 205 | tristate "Hayes ESP serial port support" | ||
| 206 | depends on SERIAL_NONSTANDARD && ISA && ISA_DMA_API && BROKEN | ||
| 207 | help | ||
| 208 | This is a driver which supports Hayes ESP serial ports. Both single | ||
| 209 | port cards and multiport cards are supported. Make sure to read | ||
| 210 | <file:Documentation/hayes-esp.txt>. | ||
| 211 | |||
| 212 | To compile this driver as a module, choose M here: the | ||
| 213 | module will be called esp. | ||
| 214 | |||
| 215 | If unsure, say N. | ||
| 216 | |||
| 217 | config MOXA_INTELLIO | 204 | config MOXA_INTELLIO | 
| 218 | tristate "Moxa Intellio support" | 205 | tristate "Moxa Intellio support" | 
| 219 | depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) | 206 | depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) | 
| diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 19a79dd79eee..f957edf7e45d 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
| @@ -18,7 +18,6 @@ obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o | |||
| 18 | obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o | 18 | obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o | 
| 19 | obj-$(CONFIG_AUDIT) += tty_audit.o | 19 | obj-$(CONFIG_AUDIT) += tty_audit.o | 
| 20 | obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o | 20 | obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o | 
| 21 | obj-$(CONFIG_ESPSERIAL) += esp.o | ||
| 22 | obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o | 21 | obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o | 
| 23 | obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o | 22 | obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o | 
| 24 | obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o | 23 | obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o | 
| diff --git a/drivers/char/bfin_jtag_comm.c b/drivers/char/bfin_jtag_comm.c index 1d7c34c73b20..2628c7415ea8 100644 --- a/drivers/char/bfin_jtag_comm.c +++ b/drivers/char/bfin_jtag_comm.c | |||
| @@ -226,7 +226,7 @@ bfin_jc_wait_until_sent(struct tty_struct *tty, int timeout) | |||
| 226 | } | 226 | } | 
| 227 | } | 227 | } | 
| 228 | 228 | ||
| 229 | static struct tty_operations bfin_jc_ops = { | 229 | static const struct tty_operations bfin_jc_ops = { | 
| 230 | .open = bfin_jc_open, | 230 | .open = bfin_jc_open, | 
| 231 | .close = bfin_jc_close, | 231 | .close = bfin_jc_close, | 
| 232 | .write = bfin_jc_write, | 232 | .write = bfin_jc_write, | 
| diff --git a/drivers/char/epca.c b/drivers/char/epca.c index dde5134713e2..17b044a71e02 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
| @@ -935,7 +935,7 @@ static int info_open(struct tty_struct *tty, struct file *filp) | |||
| 935 | return 0; | 935 | return 0; | 
| 936 | } | 936 | } | 
| 937 | 937 | ||
| 938 | static struct tty_operations info_ops = { | 938 | static const struct tty_operations info_ops = { | 
| 939 | .open = info_open, | 939 | .open = info_open, | 
| 940 | .ioctl = info_ioctl, | 940 | .ioctl = info_ioctl, | 
| 941 | }; | 941 | }; | 
| diff --git a/drivers/char/esp.c b/drivers/char/esp.c deleted file mode 100644 index b19d43cd9542..000000000000 --- a/drivers/char/esp.c +++ /dev/null | |||
| @@ -1,2533 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * esp.c - driver for Hayes ESP serial cards | ||
| 3 | * | ||
| 4 | * --- Notices from serial.c, upon which this driver is based --- | ||
| 5 | * | ||
| 6 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
| 7 | * | ||
| 8 | * Extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92. Now | ||
| 9 | * much more extensible to support other serial cards based on the | ||
| 10 | * 16450/16550A UART's. Added support for the AST FourPort and the | ||
| 11 | * Accent Async board. | ||
| 12 | * | ||
| 13 | * set_serial_info fixed to set the flags, custom divisor, and uart | ||
| 14 | * type fields. Fix suggested by Michael K. Johnson 12/12/92. | ||
| 15 | * | ||
| 16 | * 11/95: TIOCMIWAIT, TIOCGICOUNT by Angelo Haritsis <ah@doc.ic.ac.uk> | ||
| 17 | * | ||
| 18 | * 03/96: Modularised by Angelo Haritsis <ah@doc.ic.ac.uk> | ||
| 19 | * | ||
| 20 | * rs_set_termios fixed to look also for changes of the input | ||
| 21 | * flags INPCK, BRKINT, PARMRK, IGNPAR and IGNBRK. | ||
| 22 | * Bernd Anhäupl 05/17/96. | ||
| 23 | * | ||
| 24 | * --- End of notices from serial.c --- | ||
| 25 | * | ||
| 26 | * Support for the ESP serial card by Andrew J. Robinson | ||
| 27 | * <arobinso@nyx.net> (Card detection routine taken from a patch | ||
| 28 | * by Dennis J. Boylan). Patches to allow use with 2.1.x contributed | ||
| 29 | * by Chris Faylor. | ||
| 30 | * | ||
| 31 | * Most recent changes: (Andrew J. Robinson) | ||
| 32 | * Support for PIO mode. This allows the driver to work properly with | ||
| 33 | * multiport cards. | ||
| 34 | * | ||
| 35 | * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - | ||
| 36 | * several cleanups, use module_init/module_exit, etc | ||
| 37 | * | ||
| 38 | * This module exports the following rs232 io functions: | ||
| 39 | * | ||
| 40 | * int espserial_init(void); | ||
| 41 | */ | ||
| 42 | |||
| 43 | #include <linux/module.h> | ||
| 44 | #include <linux/errno.h> | ||
| 45 | #include <linux/signal.h> | ||
| 46 | #include <linux/sched.h> | ||
| 47 | #include <linux/interrupt.h> | ||
| 48 | #include <linux/tty.h> | ||
| 49 | #include <linux/tty_flip.h> | ||
| 50 | #include <linux/serial.h> | ||
| 51 | #include <linux/serialP.h> | ||
| 52 | #include <linux/serial_reg.h> | ||
| 53 | #include <linux/major.h> | ||
| 54 | #include <linux/string.h> | ||
| 55 | #include <linux/fcntl.h> | ||
| 56 | #include <linux/ptrace.h> | ||
| 57 | #include <linux/ioport.h> | ||
| 58 | #include <linux/mm.h> | ||
| 59 | #include <linux/init.h> | ||
| 60 | #include <linux/delay.h> | ||
| 61 | #include <linux/bitops.h> | ||
| 62 | |||
| 63 | #include <asm/system.h> | ||
| 64 | #include <linux/io.h> | ||
| 65 | |||
| 66 | #include <asm/dma.h> | ||
| 67 | #include <linux/slab.h> | ||
| 68 | #include <linux/uaccess.h> | ||
| 69 | |||
| 70 | #include <linux/hayesesp.h> | ||
| 71 | |||
| 72 | #define NR_PORTS 64 /* maximum number of ports */ | ||
| 73 | #define NR_PRIMARY 8 /* maximum number of primary ports */ | ||
| 74 | #define REGION_SIZE 8 /* size of io region to request */ | ||
| 75 | |||
| 76 | /* The following variables can be set by giving module options */ | ||
| 77 | static int irq[NR_PRIMARY]; /* IRQ for each base port */ | ||
| 78 | static unsigned int divisor[NR_PRIMARY]; /* custom divisor for each port */ | ||
| 79 | static unsigned int dma = ESP_DMA_CHANNEL; /* DMA channel */ | ||
| 80 | static unsigned int rx_trigger = ESP_RX_TRIGGER; | ||
| 81 | static unsigned int tx_trigger = ESP_TX_TRIGGER; | ||
| 82 | static unsigned int flow_off = ESP_FLOW_OFF; | ||
| 83 | static unsigned int flow_on = ESP_FLOW_ON; | ||
| 84 | static unsigned int rx_timeout = ESP_RX_TMOUT; | ||
| 85 | static unsigned int pio_threshold = ESP_PIO_THRESHOLD; | ||
| 86 | |||
| 87 | MODULE_LICENSE("GPL"); | ||
| 88 | |||
| 89 | module_param_array(irq, int, NULL, 0); | ||
| 90 | module_param_array(divisor, uint, NULL, 0); | ||
| 91 | module_param(dma, uint, 0); | ||
| 92 | module_param(rx_trigger, uint, 0); | ||
| 93 | module_param(tx_trigger, uint, 0); | ||
| 94 | module_param(flow_off, uint, 0); | ||
| 95 | module_param(flow_on, uint, 0); | ||
| 96 | module_param(rx_timeout, uint, 0); | ||
| 97 | module_param(pio_threshold, uint, 0); | ||
| 98 | |||
| 99 | /* END */ | ||
| 100 | |||
| 101 | static char *dma_buffer; | ||
| 102 | static int dma_bytes; | ||
| 103 | static struct esp_pio_buffer *free_pio_buf; | ||
| 104 | |||
| 105 | #define DMA_BUFFER_SZ 1024 | ||
| 106 | |||
| 107 | #define WAKEUP_CHARS 1024 | ||
| 108 | |||
| 109 | static char serial_name[] __initdata = "ESP serial driver"; | ||
| 110 | static char serial_version[] __initdata = "2.2"; | ||
| 111 | |||
| 112 | static struct tty_driver *esp_driver; | ||
| 113 | |||
| 114 | /* | ||
| 115 | * Serial driver configuration section. Here are the various options: | ||
| 116 | * | ||
| 117 | * SERIAL_PARANOIA_CHECK | ||
| 118 | * Check the magic number for the esp_structure where | ||
| 119 | * ever possible. | ||
| 120 | */ | ||
| 121 | |||
| 122 | #undef SERIAL_PARANOIA_CHECK | ||
| 123 | #define SERIAL_DO_RESTART | ||
| 124 | |||
| 125 | #undef SERIAL_DEBUG_INTR | ||
| 126 | #undef SERIAL_DEBUG_OPEN | ||
| 127 | #undef SERIAL_DEBUG_FLOW | ||
| 128 | |||
| 129 | #if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) | ||
| 130 | #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \ | ||
| 131 | tty->name, info->port.flags, \ | ||
| 132 | serial_driver.refcount, \ | ||
| 133 | info->port.count, tty->count, s) | ||
| 134 | #else | ||
| 135 | #define DBG_CNT(s) | ||
| 136 | #endif | ||
| 137 | |||
| 138 | static struct esp_struct *ports; | ||
| 139 | |||
| 140 | static void change_speed(struct esp_struct *info); | ||
| 141 | static void rs_wait_until_sent(struct tty_struct *, int); | ||
| 142 | |||
| 143 | /* | ||
| 144 | * The ESP card has a clock rate of 14.7456 MHz (that is, 2**ESPC_SCALE | ||
| 145 | * times the normal 1.8432 Mhz clock of most serial boards). | ||
| 146 | */ | ||
| 147 | #define BASE_BAUD ((1843200 / 16) * (1 << ESPC_SCALE)) | ||
| 148 | |||
| 149 | /* Standard COM flags (except for COM4, because of the 8514 problem) */ | ||
| 150 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) | ||
| 151 | |||
| 152 | static inline int serial_paranoia_check(struct esp_struct *info, | ||
| 153 | char *name, const char *routine) | ||
| 154 | { | ||
| 155 | #ifdef SERIAL_PARANOIA_CHECK | ||
| 156 | static const char badmagic[] = KERN_WARNING | ||
| 157 | "Warning: bad magic number for serial struct (%s) in %s\n"; | ||
| 158 | static const char badinfo[] = KERN_WARNING | ||
| 159 | "Warning: null esp_struct for (%s) in %s\n"; | ||
| 160 | |||
| 161 | if (!info) { | ||
| 162 | printk(badinfo, name, routine); | ||
| 163 | return 1; | ||
| 164 | } | ||
| 165 | if (info->magic != ESP_MAGIC) { | ||
| 166 | printk(badmagic, name, routine); | ||
| 167 | return 1; | ||
| 168 | } | ||
| 169 | #endif | ||
| 170 | return 0; | ||
| 171 | } | ||
| 172 | |||
| 173 | static inline unsigned int serial_in(struct esp_struct *info, int offset) | ||
| 174 | { | ||
| 175 | return inb(info->io_port + offset); | ||
| 176 | } | ||
| 177 | |||
| 178 | static inline void serial_out(struct esp_struct *info, int offset, | ||
| 179 | unsigned char value) | ||
| 180 | { | ||
| 181 | outb(value, info->io_port+offset); | ||
| 182 | } | ||
| 183 | |||
| 184 | /* | ||
| 185 | * ------------------------------------------------------------ | ||
| 186 | * rs_stop() and rs_start() | ||
| 187 | * | ||
| 188 | * This routines are called before setting or resetting tty->stopped. | ||
| 189 | * They enable or disable transmitter interrupts, as necessary. | ||
| 190 | * ------------------------------------------------------------ | ||
| 191 | */ | ||
| 192 | static void rs_stop(struct tty_struct *tty) | ||
| 193 | { | ||
| 194 | struct esp_struct *info = tty->driver_data; | ||
| 195 | unsigned long flags; | ||
| 196 | |||
| 197 | if (serial_paranoia_check(info, tty->name, "rs_stop")) | ||
| 198 | return; | ||
| 199 | |||
| 200 | spin_lock_irqsave(&info->lock, flags); | ||
| 201 | if (info->IER & UART_IER_THRI) { | ||
| 202 | info->IER &= ~UART_IER_THRI; | ||
| 203 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
| 204 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
| 205 | } | ||
| 206 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 207 | } | ||
| 208 | |||
| 209 | static void rs_start(struct tty_struct *tty) | ||
| 210 | { | ||
| 211 | struct esp_struct *info = tty->driver_data; | ||
| 212 | unsigned long flags; | ||
| 213 | |||
| 214 | if (serial_paranoia_check(info, tty->name, "rs_start")) | ||
| 215 | return; | ||
| 216 | |||
| 217 | spin_lock_irqsave(&info->lock, flags); | ||
| 218 | if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) { | ||
| 219 | info->IER |= UART_IER_THRI; | ||
| 220 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
| 221 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
| 222 | } | ||
| 223 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 224 | } | ||
| 225 | |||
| 226 | /* | ||
| 227 | * ---------------------------------------------------------------------- | ||
| 228 | * | ||
| 229 | * Here starts the interrupt handling routines. All of the following | ||
| 230 | * subroutines are declared as inline and are folded into | ||
| 231 | * rs_interrupt(). They were separated out for readability's sake. | ||
| 232 | * | ||
| 233 | * Note: rs_interrupt() is a "fast" interrupt, which means that it | ||
| 234 | * runs with interrupts turned off. People who may want to modify | ||
| 235 | * rs_interrupt() should try to keep the interrupt handler as fast as | ||
| 236 | * possible. After you are done making modifications, it is not a bad | ||
| 237 | * idea to do: | ||
| 238 | * | ||
| 239 | * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c | ||
| 240 | * | ||
| 241 | * and look at the resulting assemble code in serial.s. | ||
| 242 | * | ||
| 243 | * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 | ||
| 244 | * ----------------------------------------------------------------------- | ||
| 245 | */ | ||
| 246 | |||
| 247 | static DEFINE_SPINLOCK(pio_lock); | ||
| 248 | |||
| 249 | static inline struct esp_pio_buffer *get_pio_buffer(void) | ||
| 250 | { | ||
| 251 | struct esp_pio_buffer *buf; | ||
| 252 | unsigned long flags; | ||
| 253 | |||
| 254 | spin_lock_irqsave(&pio_lock, flags); | ||
| 255 | if (free_pio_buf) { | ||
| 256 | buf = free_pio_buf; | ||
| 257 | free_pio_buf = buf->next; | ||
| 258 | } else { | ||
| 259 | buf = kmalloc(sizeof(struct esp_pio_buffer), GFP_ATOMIC); | ||
| 260 | } | ||
| 261 | spin_unlock_irqrestore(&pio_lock, flags); | ||
| 262 | return buf; | ||
| 263 | } | ||
| 264 | |||
| 265 | static inline void release_pio_buffer(struct esp_pio_buffer *buf) | ||
| 266 | { | ||
| 267 | unsigned long flags; | ||
| 268 | spin_lock_irqsave(&pio_lock, flags); | ||
| 269 | buf->next = free_pio_buf; | ||
| 270 | free_pio_buf = buf; | ||
| 271 | spin_unlock_irqrestore(&pio_lock, flags); | ||
| 272 | } | ||
| 273 | |||
| 274 | static inline void receive_chars_pio(struct esp_struct *info, int num_bytes) | ||
| 275 | { | ||
| 276 | struct tty_struct *tty = info->port.tty; | ||
| 277 | int i; | ||
| 278 | struct esp_pio_buffer *pio_buf; | ||
| 279 | struct esp_pio_buffer *err_buf; | ||
| 280 | unsigned char status_mask; | ||
| 281 | |||
| 282 | pio_buf = get_pio_buffer(); | ||
| 283 | |||
| 284 | if (!pio_buf) | ||
| 285 | return; | ||
| 286 | |||
| 287 | err_buf = get_pio_buffer(); | ||
| 288 | |||
| 289 | if (!err_buf) { | ||
| 290 | release_pio_buffer(pio_buf); | ||
| 291 | return; | ||
| 292 | } | ||
| 293 | |||
| 294 | status_mask = (info->read_status_mask >> 2) & 0x07; | ||
| 295 | |||
| 296 | for (i = 0; i < num_bytes - 1; i += 2) { | ||
| 297 | *((unsigned short *)(pio_buf->data + i)) = | ||
| 298 | inw(info->io_port + UART_ESI_RX); | ||
| 299 | err_buf->data[i] = serial_in(info, UART_ESI_RWS); | ||
| 300 | err_buf->data[i + 1] = (err_buf->data[i] >> 3) & status_mask; | ||
| 301 | err_buf->data[i] &= status_mask; | ||
| 302 | } | ||
| 303 | |||
| 304 | if (num_bytes & 0x0001) { | ||
| 305 | pio_buf->data[num_bytes - 1] = serial_in(info, UART_ESI_RX); | ||
| 306 | err_buf->data[num_bytes - 1] = | ||
| 307 | (serial_in(info, UART_ESI_RWS) >> 3) & status_mask; | ||
| 308 | } | ||
| 309 | |||
| 310 | /* make sure everything is still ok since interrupts were enabled */ | ||
| 311 | tty = info->port.tty; | ||
| 312 | |||
| 313 | if (!tty) { | ||
| 314 | release_pio_buffer(pio_buf); | ||
| 315 | release_pio_buffer(err_buf); | ||
| 316 | info->stat_flags &= ~ESP_STAT_RX_TIMEOUT; | ||
| 317 | return; | ||
| 318 | } | ||
| 319 | |||
| 320 | status_mask = (info->ignore_status_mask >> 2) & 0x07; | ||
| 321 | |||
| 322 | for (i = 0; i < num_bytes; i++) { | ||
| 323 | if (!(err_buf->data[i] & status_mask)) { | ||
| 324 | int flag = 0; | ||
| 325 | |||
| 326 | if (err_buf->data[i] & 0x04) { | ||
| 327 | flag = TTY_BREAK; | ||
| 328 | if (info->port.flags & ASYNC_SAK) | ||
| 329 | do_SAK(tty); | ||
| 330 | } else if (err_buf->data[i] & 0x02) | ||
| 331 | flag = TTY_FRAME; | ||
| 332 | else if (err_buf->data[i] & 0x01) | ||
| 333 | flag = TTY_PARITY; | ||
| 334 | tty_insert_flip_char(tty, pio_buf->data[i], flag); | ||
| 335 | } | ||
| 336 | } | ||
| 337 | |||
| 338 | tty_schedule_flip(tty); | ||
| 339 | |||
| 340 | info->stat_flags &= ~ESP_STAT_RX_TIMEOUT; | ||
| 341 | release_pio_buffer(pio_buf); | ||
| 342 | release_pio_buffer(err_buf); | ||
| 343 | } | ||
| 344 | |||
| 345 | static void program_isa_dma(int dma, int dir, unsigned long addr, int len) | ||
| 346 | { | ||
| 347 | unsigned long flags; | ||
| 348 | |||
| 349 | flags = claim_dma_lock(); | ||
| 350 | disable_dma(dma); | ||
| 351 | clear_dma_ff(dma); | ||
| 352 | set_dma_mode(dma, dir); | ||
| 353 | set_dma_addr(dma, addr); | ||
| 354 | set_dma_count(dma, len); | ||
| 355 | enable_dma(dma); | ||
| 356 | release_dma_lock(flags); | ||
| 357 | } | ||
| 358 | |||
| 359 | static void receive_chars_dma(struct esp_struct *info, int num_bytes) | ||
| 360 | { | ||
| 361 | info->stat_flags &= ~ESP_STAT_RX_TIMEOUT; | ||
| 362 | dma_bytes = num_bytes; | ||
| 363 | info->stat_flags |= ESP_STAT_DMA_RX; | ||
| 364 | |||
| 365 | program_isa_dma(dma, DMA_MODE_READ, isa_virt_to_bus(dma_buffer), | ||
| 366 | dma_bytes); | ||
| 367 | serial_out(info, UART_ESI_CMD1, ESI_START_DMA_RX); | ||
| 368 | } | ||
| 369 | |||
| 370 | static inline void receive_chars_dma_done(struct esp_struct *info, | ||
| 371 | int status) | ||
| 372 | { | ||
| 373 | struct tty_struct *tty = info->port.tty; | ||
| 374 | int num_bytes; | ||
| 375 | unsigned long flags; | ||
| 376 | |||
| 377 | flags = claim_dma_lock(); | ||
| 378 | disable_dma(dma); | ||
| 379 | clear_dma_ff(dma); | ||
| 380 | |||
| 381 | info->stat_flags &= ~ESP_STAT_DMA_RX; | ||
| 382 | num_bytes = dma_bytes - get_dma_residue(dma); | ||
| 383 | release_dma_lock(flags); | ||
| 384 | |||
| 385 | info->icount.rx += num_bytes; | ||
| 386 | |||
| 387 | if (num_bytes > 0) { | ||
| 388 | tty_insert_flip_string(tty, dma_buffer, num_bytes - 1); | ||
| 389 | |||
| 390 | status &= (0x1c & info->read_status_mask); | ||
| 391 | |||
| 392 | /* Is the status significant or do we throw the last byte ? */ | ||
| 393 | if (!(status & info->ignore_status_mask)) { | ||
| 394 | int statflag = 0; | ||
| 395 | |||
| 396 | if (status & 0x10) { | ||
| 397 | statflag = TTY_BREAK; | ||
| 398 | (info->icount.brk)++; | ||
| 399 | if (info->port.flags & ASYNC_SAK) | ||
| 400 | do_SAK(tty); | ||
| 401 | } else if (status & 0x08) { | ||
| 402 | statflag = TTY_FRAME; | ||
| 403 | info->icount.frame++; | ||
| 404 | } else if (status & 0x04) { | ||
| 405 | statflag = TTY_PARITY; | ||
| 406 | info->icount.parity++; | ||
| 407 | } | ||
| 408 | tty_insert_flip_char(tty, dma_buffer[num_bytes - 1], | ||
| 409 | statflag); | ||
| 410 | } | ||
| 411 | tty_schedule_flip(tty); | ||
| 412 | } | ||
| 413 | |||
| 414 | if (dma_bytes != num_bytes) { | ||
| 415 | num_bytes = dma_bytes - num_bytes; | ||
| 416 | dma_bytes = 0; | ||
| 417 | receive_chars_dma(info, num_bytes); | ||
| 418 | } else | ||
| 419 | dma_bytes = 0; | ||
| 420 | } | ||
| 421 | |||
| 422 | /* Caller must hold info->lock */ | ||
| 423 | |||
| 424 | static inline void transmit_chars_pio(struct esp_struct *info, | ||
| 425 | int space_avail) | ||
| 426 | { | ||
| 427 | int i; | ||
| 428 | struct esp_pio_buffer *pio_buf; | ||
| 429 | |||
| 430 | pio_buf = get_pio_buffer(); | ||
| 431 | |||
| 432 | if (!pio_buf) | ||
| 433 | return; | ||
| 434 | |||
| 435 | while (space_avail && info->xmit_cnt) { | ||
| 436 | if (info->xmit_tail + space_avail <= ESP_XMIT_SIZE) { | ||
| 437 | memcpy(pio_buf->data, | ||
| 438 | &(info->xmit_buf[info->xmit_tail]), | ||
| 439 | space_avail); | ||
| 440 | } else { | ||
| 441 | i = ESP_XMIT_SIZE - info->xmit_tail; | ||
| 442 | memcpy(pio_buf->data, | ||
| 443 | &(info->xmit_buf[info->xmit_tail]), i); | ||
| 444 | memcpy(&(pio_buf->data[i]), info->xmit_buf, | ||
| 445 | space_avail - i); | ||
| 446 | } | ||
| 447 | |||
| 448 | info->xmit_cnt -= space_avail; | ||
| 449 | info->xmit_tail = (info->xmit_tail + space_avail) & | ||
| 450 | (ESP_XMIT_SIZE - 1); | ||
| 451 | |||
| 452 | for (i = 0; i < space_avail - 1; i += 2) { | ||
| 453 | outw(*((unsigned short *)(pio_buf->data + i)), | ||
| 454 | info->io_port + UART_ESI_TX); | ||
| 455 | } | ||
| 456 | |||
| 457 | if (space_avail & 0x0001) | ||
| 458 | serial_out(info, UART_ESI_TX, | ||
| 459 | pio_buf->data[space_avail - 1]); | ||
| 460 | |||
| 461 | if (info->xmit_cnt) { | ||
| 462 | serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); | ||
| 463 | serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL); | ||
| 464 | space_avail = serial_in(info, UART_ESI_STAT1) << 8; | ||
| 465 | space_avail |= serial_in(info, UART_ESI_STAT2); | ||
| 466 | |||
| 467 | if (space_avail > info->xmit_cnt) | ||
| 468 | space_avail = info->xmit_cnt; | ||
| 469 | } | ||
| 470 | } | ||
| 471 | |||
| 472 | if (info->xmit_cnt < WAKEUP_CHARS) { | ||
| 473 | if (info->port.tty) | ||
| 474 | tty_wakeup(info->port.tty); | ||
| 475 | |||
| 476 | #ifdef SERIAL_DEBUG_INTR | ||
| 477 | printk("THRE..."); | ||
| 478 | #endif | ||
| 479 | |||
| 480 | if (info->xmit_cnt <= 0) { | ||
| 481 | info->IER &= ~UART_IER_THRI; | ||
| 482 | serial_out(info, UART_ESI_CMD1, | ||
| 483 | ESI_SET_SRV_MASK); | ||
| 484 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
| 485 | } | ||
| 486 | } | ||
| 487 | |||
| 488 | release_pio_buffer(pio_buf); | ||
| 489 | } | ||
| 490 | |||
| 491 | /* Caller must hold info->lock */ | ||
| 492 | static inline void transmit_chars_dma(struct esp_struct *info, int num_bytes) | ||
| 493 | { | ||
| 494 | dma_bytes = num_bytes; | ||
| 495 | |||
| 496 | if (info->xmit_tail + dma_bytes <= ESP_XMIT_SIZE) { | ||
| 497 | memcpy(dma_buffer, &(info->xmit_buf[info->xmit_tail]), | ||
| 498 | dma_bytes); | ||
| 499 | } else { | ||
| 500 | int i = ESP_XMIT_SIZE - info->xmit_tail; | ||
| 501 | memcpy(dma_buffer, &(info->xmit_buf[info->xmit_tail]), | ||
| 502 | i); | ||
| 503 | memcpy(&(dma_buffer[i]), info->xmit_buf, dma_bytes - i); | ||
| 504 | } | ||
| 505 | |||
| 506 | info->xmit_cnt -= dma_bytes; | ||
| 507 | info->xmit_tail = (info->xmit_tail + dma_bytes) & (ESP_XMIT_SIZE - 1); | ||
| 508 | |||
| 509 | if (info->xmit_cnt < WAKEUP_CHARS) { | ||
| 510 | if (info->port.tty) | ||
| 511 | tty_wakeup(info->port.tty); | ||
| 512 | |||
| 513 | #ifdef SERIAL_DEBUG_INTR | ||
| 514 | printk("THRE..."); | ||
| 515 | #endif | ||
| 516 | |||
| 517 | if (info->xmit_cnt <= 0) { | ||
| 518 | info->IER &= ~UART_IER_THRI; | ||
| 519 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
| 520 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
| 521 | } | ||
| 522 | } | ||
| 523 | |||
| 524 | info->stat_flags |= ESP_STAT_DMA_TX; | ||
| 525 | |||
| 526 | program_isa_dma(dma, DMA_MODE_WRITE, isa_virt_to_bus(dma_buffer), | ||
| 527 | dma_bytes); | ||
| 528 | serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX); | ||
| 529 | } | ||
| 530 | |||
| 531 | static inline void transmit_chars_dma_done(struct esp_struct *info) | ||
| 532 | { | ||
| 533 | int num_bytes; | ||
| 534 | unsigned long flags; | ||
| 535 | |||
| 536 | flags = claim_dma_lock(); | ||
| 537 | disable_dma(dma); | ||
| 538 | clear_dma_ff(dma); | ||
| 539 | |||
| 540 | num_bytes = dma_bytes - get_dma_residue(dma); | ||
| 541 | info->icount.tx += dma_bytes; | ||
| 542 | release_dma_lock(flags); | ||
| 543 | |||
| 544 | if (dma_bytes != num_bytes) { | ||
| 545 | dma_bytes -= num_bytes; | ||
| 546 | memmove(dma_buffer, dma_buffer + num_bytes, dma_bytes); | ||
| 547 | |||
| 548 | program_isa_dma(dma, DMA_MODE_WRITE, | ||
| 549 | isa_virt_to_bus(dma_buffer), dma_bytes); | ||
| 550 | |||
| 551 | serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX); | ||
| 552 | } else { | ||
| 553 | dma_bytes = 0; | ||
| 554 | info->stat_flags &= ~ESP_STAT_DMA_TX; | ||
| 555 | } | ||
| 556 | } | ||
| 557 | |||
| 558 | static void check_modem_status(struct esp_struct *info) | ||
| 559 | { | ||
| 560 | int status; | ||
| 561 | |||
| 562 | serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT); | ||
| 563 | status = serial_in(info, UART_ESI_STAT2); | ||
| 564 | |||
| 565 | if (status & UART_MSR_ANY_DELTA) { | ||
| 566 | /* update input line counters */ | ||
| 567 | if (status & UART_MSR_TERI) | ||
| 568 | info->icount.rng++; | ||
| 569 | if (status & UART_MSR_DDSR) | ||
| 570 | info->icount.dsr++; | ||
| 571 | if (status & UART_MSR_DDCD) | ||
| 572 | info->icount.dcd++; | ||
| 573 | if (status & UART_MSR_DCTS) | ||
| 574 | info->icount.cts++; | ||
| 575 | wake_up_interruptible(&info->port.delta_msr_wait); | ||
| 576 | } | ||
| 577 | |||
| 578 | if ((info->port.flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { | ||
| 579 | #if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) | ||
| 580 | printk("ttys%d CD now %s...", info->line, | ||
| 581 | (status & UART_MSR_DCD) ? "on" : "off"); | ||
| 582 | #endif | ||
| 583 | if (status & UART_MSR_DCD) | ||
| 584 | wake_up_interruptible(&info->port.open_wait); | ||
| 585 | else { | ||
| 586 | #ifdef SERIAL_DEBUG_OPEN | ||
| 587 | printk("scheduling hangup..."); | ||
| 588 | #endif | ||
| 589 | tty_hangup(info->port.tty); | ||
| 590 | } | ||
| 591 | } | ||
| 592 | } | ||
| 593 | |||
| 594 | /* | ||
| 595 | * This is the serial driver's interrupt routine | ||
| 596 | */ | ||
| 597 | static irqreturn_t rs_interrupt_single(int irq, void *dev_id) | ||
| 598 | { | ||
| 599 | struct esp_struct *info; | ||
| 600 | unsigned err_status; | ||
| 601 | unsigned int scratch; | ||
| 602 | |||
| 603 | #ifdef SERIAL_DEBUG_INTR | ||
| 604 | printk("rs_interrupt_single(%d)...", irq); | ||
| 605 | #endif | ||
| 606 | info = (struct esp_struct *)dev_id; | ||
| 607 | err_status = 0; | ||
| 608 | scratch = serial_in(info, UART_ESI_SID); | ||
| 609 | |||
| 610 | spin_lock(&info->lock); | ||
| 611 | |||
| 612 | if (!info->port.tty) { | ||
| 613 | spin_unlock(&info->lock); | ||
| 614 | return IRQ_NONE; | ||
| 615 | } | ||
| 616 | |||
| 617 | if (scratch & 0x04) { /* error */ | ||
| 618 | serial_out(info, UART_ESI_CMD1, ESI_GET_ERR_STAT); | ||
| 619 | err_status = serial_in(info, UART_ESI_STAT1); | ||
| 620 | serial_in(info, UART_ESI_STAT2); | ||
| 621 | |||
| 622 | if (err_status & 0x01) | ||
| 623 | info->stat_flags |= ESP_STAT_RX_TIMEOUT; | ||
| 624 | |||
| 625 | if (err_status & 0x20) /* UART status */ | ||
| 626 | check_modem_status(info); | ||
| 627 | |||
| 628 | if (err_status & 0x80) /* Start break */ | ||
| 629 | wake_up_interruptible(&info->break_wait); | ||
| 630 | } | ||
| 631 | |||
| 632 | if ((scratch & 0x88) || /* DMA completed or timed out */ | ||
| 633 | (err_status & 0x1c) /* receive error */) { | ||
| 634 | if (info->stat_flags & ESP_STAT_DMA_RX) | ||
| 635 | receive_chars_dma_done(info, err_status); | ||
| 636 | else if (info->stat_flags & ESP_STAT_DMA_TX) | ||
| 637 | transmit_chars_dma_done(info); | ||
| 638 | } | ||
| 639 | |||
| 640 | if (!(info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) && | ||
| 641 | ((scratch & 0x01) || (info->stat_flags & ESP_STAT_RX_TIMEOUT)) && | ||
| 642 | (info->IER & UART_IER_RDI)) { | ||
| 643 | int num_bytes; | ||
| 644 | |||
| 645 | serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); | ||
| 646 | serial_out(info, UART_ESI_CMD1, ESI_GET_RX_AVAIL); | ||
| 647 | num_bytes = serial_in(info, UART_ESI_STAT1) << 8; | ||
| 648 | num_bytes |= serial_in(info, UART_ESI_STAT2); | ||
| 649 | |||
| 650 | num_bytes = tty_buffer_request_room(info->port.tty, num_bytes); | ||
| 651 | |||
| 652 | if (num_bytes) { | ||
| 653 | if (dma_bytes || | ||
| 654 | (info->stat_flags & ESP_STAT_USE_PIO) || | ||
| 655 | (num_bytes <= info->config.pio_threshold)) | ||
| 656 | receive_chars_pio(info, num_bytes); | ||
| 657 | else | ||
| 658 | receive_chars_dma(info, num_bytes); | ||
| 659 | } | ||
| 660 | } | ||
| 661 | |||
| 662 | if (!(info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) && | ||
| 663 | (scratch & 0x02) && (info->IER & UART_IER_THRI)) { | ||
| 664 | if ((info->xmit_cnt <= 0) || info->port.tty->stopped) { | ||
| 665 | info->IER &= ~UART_IER_THRI; | ||
| 666 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
| 667 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
| 668 | } else { | ||
| 669 | int num_bytes; | ||
| 670 | |||
| 671 | serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); | ||
| 672 | serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL); | ||
| 673 | num_bytes = serial_in(info, UART_ESI_STAT1) << 8; | ||
| 674 | num_bytes |= serial_in(info, UART_ESI_STAT2); | ||
| 675 | |||
| 676 | if (num_bytes > info->xmit_cnt) | ||
| 677 | num_bytes = info->xmit_cnt; | ||
| 678 | |||
| 679 | if (num_bytes) { | ||
| 680 | if (dma_bytes || | ||
| 681 | (info->stat_flags & ESP_STAT_USE_PIO) || | ||
| 682 | (num_bytes <= info->config.pio_threshold)) | ||
| 683 | transmit_chars_pio(info, num_bytes); | ||
| 684 | else | ||
| 685 | transmit_chars_dma(info, num_bytes); | ||
| 686 | } | ||
| 687 | } | ||
| 688 | } | ||
| 689 | |||
| 690 | info->last_active = jiffies; | ||
| 691 | |||
| 692 | #ifdef SERIAL_DEBUG_INTR | ||
| 693 | printk("end.\n"); | ||
| 694 | #endif | ||
| 695 | spin_unlock(&info->lock); | ||
| 696 | return IRQ_HANDLED; | ||
| 697 | } | ||
| 698 | |||
| 699 | /* | ||
| 700 | * ------------------------------------------------------------------- | ||
| 701 | * Here ends the serial interrupt routines. | ||
| 702 | * ------------------------------------------------------------------- | ||
| 703 | */ | ||
| 704 | |||
| 705 | /* | ||
| 706 | * --------------------------------------------------------------- | ||
| 707 | * Low level utility subroutines for the serial driver: routines to | ||
| 708 | * figure out the appropriate timeout for an interrupt chain, routines | ||
| 709 | * to initialize and startup a serial port, and routines to shutdown a | ||
| 710 | * serial port. Useful stuff like that. | ||
| 711 | * | ||
| 712 | * Caller should hold lock | ||
| 713 | * --------------------------------------------------------------- | ||
| 714 | */ | ||
| 715 | |||
| 716 | static void esp_basic_init(struct esp_struct *info) | ||
| 717 | { | ||
| 718 | /* put ESPC in enhanced mode */ | ||
| 719 | serial_out(info, UART_ESI_CMD1, ESI_SET_MODE); | ||
| 720 | |||
| 721 | if (info->stat_flags & ESP_STAT_NEVER_DMA) | ||
| 722 | serial_out(info, UART_ESI_CMD2, 0x01); | ||
| 723 | else | ||
| 724 | serial_out(info, UART_ESI_CMD2, 0x31); | ||
| 725 | |||
| 726 | /* disable interrupts for now */ | ||
| 727 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
| 728 | serial_out(info, UART_ESI_CMD2, 0x00); | ||
| 729 | |||
| 730 | /* set interrupt and DMA channel */ | ||
| 731 | serial_out(info, UART_ESI_CMD1, ESI_SET_IRQ); | ||
| 732 | |||
| 733 | if (info->stat_flags & ESP_STAT_NEVER_DMA) | ||
| 734 | serial_out(info, UART_ESI_CMD2, 0x01); | ||
| 735 | else | ||
| 736 | serial_out(info, UART_ESI_CMD2, (dma << 4) | 0x01); | ||
| 737 | |||
| 738 | serial_out(info, UART_ESI_CMD1, ESI_SET_ENH_IRQ); | ||
| 739 | |||
| 740 | if (info->line % 8) /* secondary port */ | ||
| 741 | serial_out(info, UART_ESI_CMD2, 0x0d); /* shared */ | ||
| 742 | else if (info->irq == 9) | ||
| 743 | serial_out(info, UART_ESI_CMD2, 0x02); | ||
| 744 | else | ||
| 745 | serial_out(info, UART_ESI_CMD2, info->irq); | ||
| 746 | |||
| 747 | /* set error status mask (check this) */ | ||
| 748 | serial_out(info, UART_ESI_CMD1, ESI_SET_ERR_MASK); | ||
| 749 | |||
| 750 | if (info->stat_flags & ESP_STAT_NEVER_DMA) | ||
| 751 | serial_out(info, UART_ESI_CMD2, 0xa1); | ||
| 752 | else | ||
| 753 | serial_out(info, UART_ESI_CMD2, 0xbd); | ||
| 754 | |||
| 755 | serial_out(info, UART_ESI_CMD2, 0x00); | ||
| 756 | |||
| 757 | /* set DMA timeout */ | ||
| 758 | serial_out(info, UART_ESI_CMD1, ESI_SET_DMA_TMOUT); | ||
| 759 | serial_out(info, UART_ESI_CMD2, 0xff); | ||
| 760 | |||
| 761 | /* set FIFO trigger levels */ | ||
| 762 | serial_out(info, UART_ESI_CMD1, ESI_SET_TRIGGER); | ||
| 763 | serial_out(info, UART_ESI_CMD2, info->config.rx_trigger >> 8); | ||
| 764 | serial_out(info, UART_ESI_CMD2, info->config.rx_trigger); | ||
| 765 | serial_out(info, UART_ESI_CMD2, info->config.tx_trigger >> 8); | ||
| 766 | serial_out(info, UART_ESI_CMD2, info->config.tx_trigger); | ||
| 767 | |||
| 768 | /* Set clock scaling and wait states */ | ||
| 769 | serial_out(info, UART_ESI_CMD1, ESI_SET_PRESCALAR); | ||
| 770 | serial_out(info, UART_ESI_CMD2, 0x04 | ESPC_SCALE); | ||
| 771 | |||
| 772 | /* set reinterrupt pacing */ | ||
| 773 | serial_out(info, UART_ESI_CMD1, ESI_SET_REINTR); | ||
| 774 | serial_out(info, UART_ESI_CMD2, 0xff); | ||
| 775 | } | ||
| 776 | |||
| 777 | static int startup(struct esp_struct *info) | ||
| 778 | { | ||
| 779 | unsigned long flags; | ||
| 780 | int retval = 0; | ||
| 781 | unsigned int num_chars; | ||
| 782 | |||
| 783 | spin_lock_irqsave(&info->lock, flags); | ||
| 784 | |||
| 785 | if (info->port.flags & ASYNC_INITIALIZED) | ||
| 786 | goto out; | ||
| 787 | |||
| 788 | if (!info->xmit_buf) { | ||
| 789 | info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_ATOMIC); | ||
| 790 | retval = -ENOMEM; | ||
| 791 | if (!info->xmit_buf) | ||
| 792 | goto out; | ||
| 793 | } | ||
| 794 | |||
| 795 | #ifdef SERIAL_DEBUG_OPEN | ||
| 796 | printk(KERN_DEBUG "starting up ttys%d (irq %d)...", | ||
| 797 | info->line, info->irq); | ||
| 798 | #endif | ||
| 799 | |||
| 800 | /* Flush the RX buffer. Using the ESI flush command may cause */ | ||
| 801 | /* wild interrupts, so read all the data instead. */ | ||
| 802 | |||
| 803 | serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); | ||
| 804 | serial_out(info, UART_ESI_CMD1, ESI_GET_RX_AVAIL); | ||
| 805 | num_chars = serial_in(info, UART_ESI_STAT1) << 8; | ||
| 806 | num_chars |= serial_in(info, UART_ESI_STAT2); | ||
| 807 | |||
| 808 | while (num_chars > 1) { | ||
| 809 | inw(info->io_port + UART_ESI_RX); | ||
| 810 | num_chars -= 2; | ||
| 811 | } | ||
| 812 | |||
| 813 | if (num_chars) | ||
| 814 | serial_in(info, UART_ESI_RX); | ||
| 815 | |||
| 816 | /* set receive character timeout */ | ||
| 817 | serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT); | ||
| 818 | serial_out(info, UART_ESI_CMD2, info->config.rx_timeout); | ||
| 819 | |||
| 820 | /* clear all flags except the "never DMA" flag */ | ||
| 821 | info->stat_flags &= ESP_STAT_NEVER_DMA; | ||
| 822 | |||
| 823 | if (info->stat_flags & ESP_STAT_NEVER_DMA) | ||
| 824 | info->stat_flags |= ESP_STAT_USE_PIO; | ||
| 825 | |||
| 826 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 827 | |||
| 828 | /* | ||
| 829 | * Allocate the IRQ | ||
| 830 | */ | ||
| 831 | |||
| 832 | retval = request_irq(info->irq, rs_interrupt_single, IRQF_SHARED, | ||
| 833 | "esp serial", info); | ||
| 834 | |||
| 835 | if (retval) { | ||
| 836 | if (capable(CAP_SYS_ADMIN)) { | ||
| 837 | if (info->port.tty) | ||
| 838 | set_bit(TTY_IO_ERROR, | ||
| 839 | &info->port.tty->flags); | ||
| 840 | retval = 0; | ||
| 841 | } | ||
| 842 | goto out_unlocked; | ||
| 843 | } | ||
| 844 | |||
| 845 | if (!(info->stat_flags & ESP_STAT_USE_PIO) && !dma_buffer) { | ||
| 846 | dma_buffer = (char *)__get_dma_pages( | ||
| 847 | GFP_KERNEL, get_order(DMA_BUFFER_SZ)); | ||
| 848 | |||
| 849 | /* use PIO mode if DMA buf/chan cannot be allocated */ | ||
| 850 | if (!dma_buffer) | ||
| 851 | info->stat_flags |= ESP_STAT_USE_PIO; | ||
| 852 | else if (request_dma(dma, "esp serial")) { | ||
| 853 | free_pages((unsigned long)dma_buffer, | ||
| 854 | get_order(DMA_BUFFER_SZ)); | ||
| 855 | dma_buffer = NULL; | ||
| 856 | info->stat_flags |= ESP_STAT_USE_PIO; | ||
| 857 | } | ||
| 858 | |||
| 859 | } | ||
| 860 | |||
| 861 | info->MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2; | ||
| 862 | |||
| 863 | spin_lock_irqsave(&info->lock, flags); | ||
| 864 | serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); | ||
| 865 | serial_out(info, UART_ESI_CMD2, UART_MCR); | ||
| 866 | serial_out(info, UART_ESI_CMD2, info->MCR); | ||
| 867 | |||
| 868 | /* | ||
| 869 | * Finally, enable interrupts | ||
| 870 | */ | ||
| 871 | /* info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; */ | ||
| 872 | info->IER = UART_IER_RLSI | UART_IER_RDI | UART_IER_DMA_TMOUT | | ||
| 873 | UART_IER_DMA_TC; | ||
| 874 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
| 875 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
| 876 | |||
| 877 | if (info->port.tty) | ||
| 878 | clear_bit(TTY_IO_ERROR, &info->port.tty->flags); | ||
| 879 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | ||
| 880 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 881 | |||
| 882 | /* | ||
| 883 | * Set up the tty->alt_speed kludge | ||
| 884 | */ | ||
| 885 | if (info->port.tty) { | ||
| 886 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) | ||
| 887 | info->port.tty->alt_speed = 57600; | ||
| 888 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | ||
| 889 | info->port.tty->alt_speed = 115200; | ||
| 890 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) | ||
| 891 | info->port.tty->alt_speed = 230400; | ||
| 892 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) | ||
| 893 | info->port.tty->alt_speed = 460800; | ||
| 894 | } | ||
| 895 | |||
| 896 | /* | ||
| 897 | * set the speed of the serial port | ||
| 898 | */ | ||
| 899 | change_speed(info); | ||
| 900 | info->port.flags |= ASYNC_INITIALIZED; | ||
| 901 | return 0; | ||
| 902 | |||
| 903 | out: | ||
| 904 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 905 | out_unlocked: | ||
| 906 | return retval; | ||
| 907 | } | ||
| 908 | |||
| 909 | /* | ||
| 910 | * This routine will shutdown a serial port; interrupts are disabled, and | ||
| 911 | * DTR is dropped if the hangup on close termio flag is on. | ||
| 912 | */ | ||
| 913 | static void shutdown(struct esp_struct *info) | ||
| 914 | { | ||
| 915 | unsigned long flags, f; | ||
| 916 | |||
| 917 | if (!(info->port.flags & ASYNC_INITIALIZED)) | ||
| 918 | return; | ||
| 919 | |||
| 920 | #ifdef SERIAL_DEBUG_OPEN | ||
| 921 | printk("Shutting down serial port %d (irq %d)....", info->line, | ||
| 922 | info->irq); | ||
| 923 | #endif | ||
| 924 | |||
| 925 | spin_lock_irqsave(&info->lock, flags); | ||
| 926 | /* | ||
| 927 | * clear delta_msr_wait queue to avoid mem leaks: we may free the irq | ||
| 928 | * here so the queue might never be waken up | ||
| 929 | */ | ||
| 930 | wake_up_interruptible(&info->port.delta_msr_wait); | ||
| 931 | wake_up_interruptible(&info->break_wait); | ||
| 932 | |||
| 933 | /* stop a DMA transfer on the port being closed */ | ||
| 934 | /* DMA lock is higher priority always */ | ||
| 935 | if (info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) { | ||
| 936 | f = claim_dma_lock(); | ||
| 937 | disable_dma(dma); | ||
| 938 | clear_dma_ff(dma); | ||
| 939 | release_dma_lock(f); | ||
| 940 | |||
| 941 | dma_bytes = 0; | ||
| 942 | } | ||
| 943 | |||
| 944 | /* | ||
| 945 | * Free the IRQ | ||
| 946 | */ | ||
| 947 | free_irq(info->irq, info); | ||
| 948 | |||
| 949 | if (dma_buffer) { | ||
| 950 | struct esp_struct *current_port = ports; | ||
| 951 | |||
| 952 | while (current_port) { | ||
| 953 | if ((current_port != info) && | ||
| 954 | (current_port->port.flags & ASYNC_INITIALIZED)) | ||
| 955 | break; | ||
| 956 | |||
| 957 | current_port = current_port->next_port; | ||
| 958 | } | ||
| 959 | |||
| 960 | if (!current_port) { | ||
| 961 | free_dma(dma); | ||
| 962 | free_pages((unsigned long)dma_buffer, | ||
| 963 | get_order(DMA_BUFFER_SZ)); | ||
| 964 | dma_buffer = NULL; | ||
| 965 | } | ||
| 966 | } | ||
| 967 | |||
| 968 | if (info->xmit_buf) { | ||
| 969 | free_page((unsigned long) info->xmit_buf); | ||
| 970 | info->xmit_buf = NULL; | ||
| 971 | } | ||
| 972 | |||
| 973 | info->IER = 0; | ||
| 974 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
| 975 | serial_out(info, UART_ESI_CMD2, 0x00); | ||
| 976 | |||
| 977 | if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) | ||
| 978 | info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); | ||
| 979 | |||
| 980 | info->MCR &= ~UART_MCR_OUT2; | ||
| 981 | serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); | ||
| 982 | serial_out(info, UART_ESI_CMD2, UART_MCR); | ||
| 983 | serial_out(info, UART_ESI_CMD2, info->MCR); | ||
| 984 | |||
| 985 | if (info->port.tty) | ||
| 986 | set_bit(TTY_IO_ERROR, &info->port.tty->flags); | ||
| 987 | |||
| 988 | info->port.flags &= ~ASYNC_INITIALIZED; | ||
| 989 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 990 | } | ||
| 991 | |||
| 992 | /* | ||
| 993 | * This routine is called to set the UART divisor registers to match | ||
| 994 | * the specified baud rate for a serial port. | ||
| 995 | */ | ||
| 996 | static void change_speed(struct esp_struct *info) | ||
| 997 | { | ||
| 998 | unsigned short port; | ||
| 999 | int quot = 0; | ||
| 1000 | unsigned cflag, cval; | ||
| 1001 | int baud, bits; | ||
| 1002 | unsigned char flow1 = 0, flow2 = 0; | ||
| 1003 | unsigned long flags; | ||
| 1004 | |||
| 1005 | if (!info->port.tty || !info->port.tty->termios) | ||
| 1006 | return; | ||
| 1007 | cflag = info->port.tty->termios->c_cflag; | ||
| 1008 | port = info->io_port; | ||
| 1009 | |||
| 1010 | /* byte size and parity */ | ||
| 1011 | switch (cflag & CSIZE) { | ||
| 1012 | case CS5: cval = 0x00; bits = 7; break; | ||
| 1013 | case CS6: cval = 0x01; bits = 8; break; | ||
| 1014 | case CS7: cval = 0x02; bits = 9; break; | ||
| 1015 | case CS8: cval = 0x03; bits = 10; break; | ||
| 1016 | default: cval = 0x00; bits = 7; break; | ||
| 1017 | } | ||
| 1018 | if (cflag & CSTOPB) { | ||
| 1019 | cval |= 0x04; | ||
| 1020 | bits++; | ||
| 1021 | } | ||
| 1022 | if (cflag & PARENB) { | ||
| 1023 | cval |= UART_LCR_PARITY; | ||
| 1024 | bits++; | ||
| 1025 | } | ||
| 1026 | if (!(cflag & PARODD)) | ||
| 1027 | cval |= UART_LCR_EPAR; | ||
| 1028 | #ifdef CMSPAR | ||
| 1029 | if (cflag & CMSPAR) | ||
| 1030 | cval |= UART_LCR_SPAR; | ||
| 1031 | #endif | ||
| 1032 | baud = tty_get_baud_rate(info->port.tty); | ||
| 1033 | if (baud == 38400 && | ||
| 1034 | ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) | ||
| 1035 | quot = info->custom_divisor; | ||
| 1036 | else { | ||
| 1037 | if (baud == 134) /* Special case since 134 is really 134.5 */ | ||
| 1038 | quot = (2*BASE_BAUD / 269); | ||
| 1039 | else if (baud) | ||
| 1040 | quot = BASE_BAUD / baud; | ||
| 1041 | } | ||
| 1042 | /* If the quotient is ever zero, default to 9600 bps */ | ||
| 1043 | if (!quot) | ||
| 1044 | quot = BASE_BAUD / 9600; | ||
| 1045 | |||
| 1046 | if (baud) { | ||
| 1047 | /* Actual rate */ | ||
| 1048 | baud = BASE_BAUD/quot; | ||
| 1049 | tty_encode_baud_rate(info->port.tty, baud, baud); | ||
| 1050 | } | ||
| 1051 | info->timeout = ((1024 * HZ * bits * quot) / BASE_BAUD) + (HZ / 50); | ||
| 1052 | |||
| 1053 | /* CTS flow control flag and modem status interrupts */ | ||
| 1054 | /* info->IER &= ~UART_IER_MSI; */ | ||
| 1055 | if (cflag & CRTSCTS) { | ||
| 1056 | info->port.flags |= ASYNC_CTS_FLOW; | ||
| 1057 | /* info->IER |= UART_IER_MSI; */ | ||
| 1058 | flow1 = 0x04; | ||
| 1059 | flow2 = 0x10; | ||
| 1060 | } else | ||
| 1061 | info->port.flags &= ~ASYNC_CTS_FLOW; | ||
| 1062 | if (cflag & CLOCAL) | ||
| 1063 | info->port.flags &= ~ASYNC_CHECK_CD; | ||
| 1064 | else | ||
| 1065 | info->port.flags |= ASYNC_CHECK_CD; | ||
| 1066 | |||
| 1067 | /* | ||
| 1068 | * Set up parity check flag | ||
| 1069 | */ | ||
| 1070 | info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; | ||
| 1071 | if (I_INPCK(info->port.tty)) | ||
| 1072 | info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; | ||
| 1073 | if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty)) | ||
| 1074 | info->read_status_mask |= UART_LSR_BI; | ||
| 1075 | |||
| 1076 | info->ignore_status_mask = 0; | ||
| 1077 | #if 0 | ||
| 1078 | /* This should be safe, but for some broken bits of hardware... */ | ||
| 1079 | if (I_IGNPAR(info->port.tty)) { | ||
| 1080 | info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; | ||
| 1081 | info->read_status_mask |= UART_LSR_PE | UART_LSR_FE; | ||
| 1082 | } | ||
| 1083 | #endif | ||
| 1084 | if (I_IGNBRK(info->port.tty)) { | ||
| 1085 | info->ignore_status_mask |= UART_LSR_BI; | ||
| 1086 | info->read_status_mask |= UART_LSR_BI; | ||
| 1087 | /* | ||
| 1088 | * If we're ignore parity and break indicators, ignore | ||
| 1089 | * overruns too. (For real raw support). | ||
| 1090 | */ | ||
| 1091 | if (I_IGNPAR(info->port.tty)) { | ||
| 1092 | info->ignore_status_mask |= UART_LSR_OE | \ | ||
| 1093 | UART_LSR_PE | UART_LSR_FE; | ||
| 1094 | info->read_status_mask |= UART_LSR_OE | \ | ||
| 1095 | UART_LSR_PE | UART_LSR_FE; | ||
| 1096 | } | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | if (I_IXOFF(info->port.tty)) | ||
| 1100 | flow1 |= 0x81; | ||
| 1101 | |||
| 1102 | spin_lock_irqsave(&info->lock, flags); | ||
| 1103 | /* set baud */ | ||
| 1104 | serial_out(info, UART_ESI_CMD1, ESI_SET_BAUD); | ||
| 1105 | serial_out(info, UART_ESI_CMD2, quot >> 8); | ||
| 1106 | serial_out(info, UART_ESI_CMD2, quot & 0xff); | ||
| 1107 | |||
| 1108 | /* set data bits, parity, etc. */ | ||
| 1109 | serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); | ||
| 1110 | serial_out(info, UART_ESI_CMD2, UART_LCR); | ||
| 1111 | serial_out(info, UART_ESI_CMD2, cval); | ||
| 1112 | |||
| 1113 | /* Enable flow control */ | ||
| 1114 | serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_CNTL); | ||
| 1115 | serial_out(info, UART_ESI_CMD2, flow1); | ||
| 1116 | serial_out(info, UART_ESI_CMD2, flow2); | ||
| 1117 | |||
| 1118 | /* set flow control characters (XON/XOFF only) */ | ||
| 1119 | if (I_IXOFF(info->port.tty)) { | ||
| 1120 | serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_CHARS); | ||
| 1121 | serial_out(info, UART_ESI_CMD2, START_CHAR(info->port.tty)); | ||
| 1122 | serial_out(info, UART_ESI_CMD2, STOP_CHAR(info->port.tty)); | ||
| 1123 | serial_out(info, UART_ESI_CMD2, 0x10); | ||
| 1124 | serial_out(info, UART_ESI_CMD2, 0x21); | ||
| 1125 | switch (cflag & CSIZE) { | ||
| 1126 | case CS5: | ||
| 1127 | serial_out(info, UART_ESI_CMD2, 0x1f); | ||
| 1128 | break; | ||
| 1129 | case CS6: | ||
| 1130 | serial_out(info, UART_ESI_CMD2, 0x3f); | ||
| 1131 | break; | ||
| 1132 | case CS7: | ||
| 1133 | case CS8: | ||
| 1134 | serial_out(info, UART_ESI_CMD2, 0x7f); | ||
| 1135 | break; | ||
| 1136 | default: | ||
| 1137 | serial_out(info, UART_ESI_CMD2, 0xff); | ||
| 1138 | break; | ||
| 1139 | } | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | /* Set high/low water */ | ||
| 1143 | serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_LVL); | ||
| 1144 | serial_out(info, UART_ESI_CMD2, info->config.flow_off >> 8); | ||
| 1145 | serial_out(info, UART_ESI_CMD2, info->config.flow_off); | ||
| 1146 | serial_out(info, UART_ESI_CMD2, info->config.flow_on >> 8); | ||
| 1147 | serial_out(info, UART_ESI_CMD2, info->config.flow_on); | ||
| 1148 | |||
| 1149 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | static int rs_put_char(struct tty_struct *tty, unsigned char ch) | ||
| 1153 | { | ||
| 1154 | struct esp_struct *info = tty->driver_data; | ||
| 1155 | unsigned long flags; | ||
| 1156 | int ret = 0; | ||
| 1157 | |||
| 1158 | if (serial_paranoia_check(info, tty->name, "rs_put_char")) | ||
| 1159 | return 0; | ||
| 1160 | |||
| 1161 | if (!info->xmit_buf) | ||
| 1162 | return 0; | ||
| 1163 | |||
| 1164 | spin_lock_irqsave(&info->lock, flags); | ||
| 1165 | if (info->xmit_cnt < ESP_XMIT_SIZE - 1) { | ||
| 1166 | info->xmit_buf[info->xmit_head++] = ch; | ||
| 1167 | info->xmit_head &= ESP_XMIT_SIZE-1; | ||
| 1168 | info->xmit_cnt++; | ||
| 1169 | ret = 1; | ||
| 1170 | } | ||
| 1171 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1172 | return ret; | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | static void rs_flush_chars(struct tty_struct *tty) | ||
| 1176 | { | ||
| 1177 | struct esp_struct *info = tty->driver_data; | ||
| 1178 | unsigned long flags; | ||
| 1179 | |||
| 1180 | if (serial_paranoia_check(info, tty->name, "rs_flush_chars")) | ||
| 1181 | return; | ||
| 1182 | |||
| 1183 | spin_lock_irqsave(&info->lock, flags); | ||
| 1184 | |||
| 1185 | if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf) | ||
| 1186 | goto out; | ||
| 1187 | |||
| 1188 | if (!(info->IER & UART_IER_THRI)) { | ||
| 1189 | info->IER |= UART_IER_THRI; | ||
| 1190 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
| 1191 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
| 1192 | } | ||
| 1193 | out: | ||
| 1194 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | static int rs_write(struct tty_struct *tty, | ||
| 1198 | const unsigned char *buf, int count) | ||
| 1199 | { | ||
| 1200 | int c, t, ret = 0; | ||
| 1201 | struct esp_struct *info = tty->driver_data; | ||
| 1202 | unsigned long flags; | ||
| 1203 | |||
| 1204 | if (serial_paranoia_check(info, tty->name, "rs_write")) | ||
| 1205 | return 0; | ||
| 1206 | |||
| 1207 | if (!info->xmit_buf) | ||
| 1208 | return 0; | ||
| 1209 | |||
| 1210 | while (1) { | ||
| 1211 | /* Thanks to R. Wolff for suggesting how to do this with */ | ||
| 1212 | /* interrupts enabled */ | ||
| 1213 | |||
| 1214 | c = count; | ||
| 1215 | t = ESP_XMIT_SIZE - info->xmit_cnt - 1; | ||
| 1216 | |||
| 1217 | if (t < c) | ||
| 1218 | c = t; | ||
| 1219 | |||
| 1220 | t = ESP_XMIT_SIZE - info->xmit_head; | ||
| 1221 | |||
| 1222 | if (t < c) | ||
| 1223 | c = t; | ||
| 1224 | |||
| 1225 | if (c <= 0) | ||
| 1226 | break; | ||
| 1227 | |||
| 1228 | memcpy(info->xmit_buf + info->xmit_head, buf, c); | ||
| 1229 | |||
| 1230 | info->xmit_head = (info->xmit_head + c) & (ESP_XMIT_SIZE-1); | ||
| 1231 | info->xmit_cnt += c; | ||
| 1232 | buf += c; | ||
| 1233 | count -= c; | ||
| 1234 | ret += c; | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | spin_lock_irqsave(&info->lock, flags); | ||
| 1238 | |||
| 1239 | if (info->xmit_cnt && !tty->stopped && !(info->IER & UART_IER_THRI)) { | ||
| 1240 | info->IER |= UART_IER_THRI; | ||
| 1241 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
| 1242 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1246 | return ret; | ||
| 1247 | } | ||
| 1248 | |||
| 1249 | static int rs_write_room(struct tty_struct *tty) | ||
| 1250 | { | ||
| 1251 | struct esp_struct *info = tty->driver_data; | ||
| 1252 | int ret; | ||
| 1253 | unsigned long flags; | ||
| 1254 | |||
| 1255 | if (serial_paranoia_check(info, tty->name, "rs_write_room")) | ||
| 1256 | return 0; | ||
| 1257 | |||
| 1258 | spin_lock_irqsave(&info->lock, flags); | ||
| 1259 | |||
| 1260 | ret = ESP_XMIT_SIZE - info->xmit_cnt - 1; | ||
| 1261 | if (ret < 0) | ||
| 1262 | ret = 0; | ||
| 1263 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1264 | return ret; | ||
| 1265 | } | ||
| 1266 | |||
| 1267 | static int rs_chars_in_buffer(struct tty_struct *tty) | ||
| 1268 | { | ||
| 1269 | struct esp_struct *info = tty->driver_data; | ||
| 1270 | |||
| 1271 | if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) | ||
| 1272 | return 0; | ||
| 1273 | return info->xmit_cnt; | ||
| 1274 | } | ||
| 1275 | |||
| 1276 | static void rs_flush_buffer(struct tty_struct *tty) | ||
| 1277 | { | ||
| 1278 | struct esp_struct *info = tty->driver_data; | ||
| 1279 | unsigned long flags; | ||
| 1280 | |||
| 1281 | if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) | ||
| 1282 | return; | ||
| 1283 | spin_lock_irqsave(&info->lock, flags); | ||
| 1284 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | ||
| 1285 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1286 | tty_wakeup(tty); | ||
| 1287 | } | ||
| 1288 | |||
| 1289 | /* | ||
| 1290 | * ------------------------------------------------------------ | ||
| 1291 | * rs_throttle() | ||
| 1292 | * | ||
| 1293 | * This routine is called by the upper-layer tty layer to signal that | ||
| 1294 | * incoming characters should be throttled. | ||
| 1295 | * ------------------------------------------------------------ | ||
| 1296 | */ | ||
| 1297 | static void rs_throttle(struct tty_struct *tty) | ||
| 1298 | { | ||
| 1299 | struct esp_struct *info = tty->driver_data; | ||
| 1300 | unsigned long flags; | ||
| 1301 | #ifdef SERIAL_DEBUG_THROTTLE | ||
| 1302 | char buf[64]; | ||
| 1303 | |||
| 1304 | printk("throttle %s: %d....\n", tty_name(tty, buf), | ||
| 1305 | tty_chars_in_buffer(tty)); | ||
| 1306 | #endif | ||
| 1307 | |||
| 1308 | if (serial_paranoia_check(info, tty->name, "rs_throttle")) | ||
| 1309 | return; | ||
| 1310 | |||
| 1311 | spin_lock_irqsave(&info->lock, flags); | ||
| 1312 | info->IER &= ~UART_IER_RDI; | ||
| 1313 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
| 1314 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
| 1315 | serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT); | ||
| 1316 | serial_out(info, UART_ESI_CMD2, 0x00); | ||
| 1317 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1318 | } | ||
| 1319 | |||
| 1320 | static void rs_unthrottle(struct tty_struct *tty) | ||
| 1321 | { | ||
| 1322 | struct esp_struct *info = tty->driver_data; | ||
| 1323 | unsigned long flags; | ||
| 1324 | #ifdef SERIAL_DEBUG_THROTTLE | ||
| 1325 | char buf[64]; | ||
| 1326 | |||
| 1327 | printk(KERN_DEBUG "unthrottle %s: %d....\n", tty_name(tty, buf), | ||
| 1328 | tty_chars_in_buffer(tty)); | ||
| 1329 | #endif | ||
| 1330 | |||
| 1331 | if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) | ||
| 1332 | return; | ||
| 1333 | |||
| 1334 | spin_lock_irqsave(&info->lock, flags); | ||
| 1335 | info->IER |= UART_IER_RDI; | ||
| 1336 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
| 1337 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
| 1338 | serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT); | ||
| 1339 | serial_out(info, UART_ESI_CMD2, info->config.rx_timeout); | ||
| 1340 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | /* | ||
| 1344 | * ------------------------------------------------------------ | ||
| 1345 | * rs_ioctl() and friends | ||
| 1346 | * ------------------------------------------------------------ | ||
| 1347 | */ | ||
| 1348 | |||
| 1349 | static int get_serial_info(struct esp_struct *info, | ||
| 1350 | struct serial_struct __user *retinfo) | ||
| 1351 | { | ||
| 1352 | struct serial_struct tmp; | ||
| 1353 | |||
| 1354 | lock_kernel(); | ||
| 1355 | memset(&tmp, 0, sizeof(tmp)); | ||
| 1356 | tmp.type = PORT_16550A; | ||
| 1357 | tmp.line = info->line; | ||
| 1358 | tmp.port = info->io_port; | ||
| 1359 | tmp.irq = info->irq; | ||
| 1360 | tmp.flags = info->port.flags; | ||
| 1361 | tmp.xmit_fifo_size = 1024; | ||
| 1362 | tmp.baud_base = BASE_BAUD; | ||
| 1363 | tmp.close_delay = info->close_delay; | ||
| 1364 | tmp.closing_wait = info->closing_wait; | ||
| 1365 | tmp.custom_divisor = info->custom_divisor; | ||
| 1366 | tmp.hub6 = 0; | ||
| 1367 | unlock_kernel(); | ||
| 1368 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) | ||
| 1369 | return -EFAULT; | ||
| 1370 | return 0; | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | static int get_esp_config(struct esp_struct *info, | ||
| 1374 | struct hayes_esp_config __user *retinfo) | ||
| 1375 | { | ||
| 1376 | struct hayes_esp_config tmp; | ||
| 1377 | |||
| 1378 | if (!retinfo) | ||
| 1379 | return -EFAULT; | ||
| 1380 | |||
| 1381 | memset(&tmp, 0, sizeof(tmp)); | ||
| 1382 | lock_kernel(); | ||
| 1383 | tmp.rx_timeout = info->config.rx_timeout; | ||
| 1384 | tmp.rx_trigger = info->config.rx_trigger; | ||
| 1385 | tmp.tx_trigger = info->config.tx_trigger; | ||
| 1386 | tmp.flow_off = info->config.flow_off; | ||
| 1387 | tmp.flow_on = info->config.flow_on; | ||
| 1388 | tmp.pio_threshold = info->config.pio_threshold; | ||
| 1389 | tmp.dma_channel = (info->stat_flags & ESP_STAT_NEVER_DMA ? 0 : dma); | ||
| 1390 | unlock_kernel(); | ||
| 1391 | |||
| 1392 | return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; | ||
| 1393 | } | ||
| 1394 | |||
| 1395 | static int set_serial_info(struct esp_struct *info, | ||
| 1396 | struct serial_struct __user *new_info) | ||
| 1397 | { | ||
| 1398 | struct serial_struct new_serial; | ||
| 1399 | struct esp_struct old_info; | ||
| 1400 | unsigned int change_irq; | ||
| 1401 | int retval = 0; | ||
| 1402 | struct esp_struct *current_async; | ||
| 1403 | |||
| 1404 | if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) | ||
| 1405 | return -EFAULT; | ||
| 1406 | old_info = *info; | ||
| 1407 | |||
| 1408 | if ((new_serial.type != PORT_16550A) || | ||
| 1409 | (new_serial.hub6) || | ||
| 1410 | (info->io_port != new_serial.port) || | ||
| 1411 | (new_serial.baud_base != BASE_BAUD) || | ||
| 1412 | (new_serial.irq > 15) || | ||
| 1413 | (new_serial.irq < 2) || | ||
| 1414 | (new_serial.irq == 6) || | ||
| 1415 | (new_serial.irq == 8) || | ||
| 1416 | (new_serial.irq == 13)) | ||
| 1417 | return -EINVAL; | ||
| 1418 | |||
| 1419 | change_irq = new_serial.irq != info->irq; | ||
| 1420 | |||
| 1421 | if (change_irq && (info->line % 8)) | ||
| 1422 | return -EINVAL; | ||
| 1423 | |||
| 1424 | if (!capable(CAP_SYS_ADMIN)) { | ||
| 1425 | if (change_irq || | ||
| 1426 | (new_serial.close_delay != info->close_delay) || | ||
| 1427 | ((new_serial.flags & ~ASYNC_USR_MASK) != | ||
| 1428 | (info->port.flags & ~ASYNC_USR_MASK))) | ||
| 1429 | return -EPERM; | ||
| 1430 | info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) | | ||
| 1431 | (new_serial.flags & ASYNC_USR_MASK)); | ||
| 1432 | info->custom_divisor = new_serial.custom_divisor; | ||
| 1433 | } else { | ||
| 1434 | if (new_serial.irq == 2) | ||
| 1435 | new_serial.irq = 9; | ||
| 1436 | |||
| 1437 | if (change_irq) { | ||
| 1438 | current_async = ports; | ||
| 1439 | |||
| 1440 | while (current_async) { | ||
| 1441 | if ((current_async->line >= info->line) && | ||
| 1442 | (current_async->line < (info->line + 8))) { | ||
| 1443 | if (current_async == info) { | ||
| 1444 | if (current_async->port.count > 1) | ||
| 1445 | return -EBUSY; | ||
| 1446 | } else if (current_async->port.count) | ||
| 1447 | return -EBUSY; | ||
| 1448 | } | ||
| 1449 | |||
| 1450 | current_async = current_async->next_port; | ||
| 1451 | } | ||
| 1452 | } | ||
| 1453 | |||
| 1454 | /* | ||
| 1455 | * OK, past this point, all the error checking has been done. | ||
| 1456 | * At this point, we start making changes..... | ||
| 1457 | */ | ||
| 1458 | |||
| 1459 | info->port.flags = ((info->port.flags & ~ASYNC_FLAGS) | | ||
| 1460 | (new_serial.flags & ASYNC_FLAGS)); | ||
| 1461 | info->custom_divisor = new_serial.custom_divisor; | ||
| 1462 | info->close_delay = new_serial.close_delay * HZ/100; | ||
| 1463 | info->closing_wait = new_serial.closing_wait * HZ/100; | ||
| 1464 | |||
| 1465 | if (change_irq) { | ||
| 1466 | /* | ||
| 1467 | * We need to shutdown the serial port at the old | ||
| 1468 | * port/irq combination. | ||
| 1469 | */ | ||
| 1470 | shutdown(info); | ||
| 1471 | |||
| 1472 | current_async = ports; | ||
| 1473 | |||
| 1474 | while (current_async) { | ||
| 1475 | if ((current_async->line >= info->line) && | ||
| 1476 | (current_async->line < (info->line + 8))) | ||
| 1477 | current_async->irq = new_serial.irq; | ||
| 1478 | |||
| 1479 | current_async = current_async->next_port; | ||
| 1480 | } | ||
| 1481 | |||
| 1482 | serial_out(info, UART_ESI_CMD1, ESI_SET_ENH_IRQ); | ||
| 1483 | if (info->irq == 9) | ||
| 1484 | serial_out(info, UART_ESI_CMD2, 0x02); | ||
| 1485 | else | ||
| 1486 | serial_out(info, UART_ESI_CMD2, info->irq); | ||
| 1487 | } | ||
| 1488 | } | ||
| 1489 | |||
| 1490 | if (info->port.flags & ASYNC_INITIALIZED) { | ||
| 1491 | if (((old_info.port.flags & ASYNC_SPD_MASK) != | ||
| 1492 | (info->port.flags & ASYNC_SPD_MASK)) || | ||
| 1493 | (old_info.custom_divisor != info->custom_divisor)) { | ||
| 1494 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) | ||
| 1495 | info->port.tty->alt_speed = 57600; | ||
| 1496 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | ||
| 1497 | info->port.tty->alt_speed = 115200; | ||
| 1498 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) | ||
| 1499 | info->port.tty->alt_speed = 230400; | ||
| 1500 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) | ||
| 1501 | info->port.tty->alt_speed = 460800; | ||
| 1502 | change_speed(info); | ||
| 1503 | } | ||
| 1504 | } else | ||
| 1505 | retval = startup(info); | ||
| 1506 | |||
| 1507 | return retval; | ||
| 1508 | } | ||
| 1509 | |||
| 1510 | static int set_esp_config(struct esp_struct *info, | ||
| 1511 | struct hayes_esp_config __user *new_info) | ||
| 1512 | { | ||
| 1513 | struct hayes_esp_config new_config; | ||
| 1514 | unsigned int change_dma; | ||
| 1515 | int retval = 0; | ||
| 1516 | struct esp_struct *current_async; | ||
| 1517 | unsigned long flags; | ||
| 1518 | |||
| 1519 | /* Perhaps a non-sysadmin user should be able to do some of these */ | ||
| 1520 | /* operations. I haven't decided yet. */ | ||
| 1521 | |||
| 1522 | if (!capable(CAP_SYS_ADMIN)) | ||
| 1523 | return -EPERM; | ||
| 1524 | |||
| 1525 | if (copy_from_user(&new_config, new_info, sizeof(new_config))) | ||
| 1526 | return -EFAULT; | ||
| 1527 | |||
| 1528 | if ((new_config.flow_on >= new_config.flow_off) || | ||
| 1529 | (new_config.rx_trigger < 1) || | ||
| 1530 | (new_config.tx_trigger < 1) || | ||
| 1531 | (new_config.flow_off < 1) || | ||
| 1532 | (new_config.flow_on < 1) || | ||
| 1533 | (new_config.rx_trigger > 1023) || | ||
| 1534 | (new_config.tx_trigger > 1023) || | ||
| 1535 | (new_config.flow_off > 1023) || | ||
| 1536 | (new_config.flow_on > 1023) || | ||
| 1537 | (new_config.pio_threshold < 0) || | ||
| 1538 | (new_config.pio_threshold > 1024)) | ||
| 1539 | return -EINVAL; | ||
| 1540 | |||
| 1541 | if ((new_config.dma_channel != 1) && (new_config.dma_channel != 3)) | ||
| 1542 | new_config.dma_channel = 0; | ||
| 1543 | |||
| 1544 | if (info->stat_flags & ESP_STAT_NEVER_DMA) | ||
| 1545 | change_dma = new_config.dma_channel; | ||
| 1546 | else | ||
| 1547 | change_dma = (new_config.dma_channel != dma); | ||
| 1548 | |||
| 1549 | if (change_dma) { | ||
| 1550 | if (new_config.dma_channel) { | ||
| 1551 | /* PIO mode to DMA mode transition OR */ | ||
| 1552 | /* change current DMA channel */ | ||
| 1553 | current_async = ports; | ||
| 1554 | |||
| 1555 | while (current_async) { | ||
| 1556 | if (current_async == info) { | ||
| 1557 | if (current_async->port.count > 1) | ||
| 1558 | return -EBUSY; | ||
| 1559 | } else if (current_async->port.count) | ||
| 1560 | return -EBUSY; | ||
| 1561 | |||
| 1562 | current_async = current_async->next_port; | ||
| 1563 | } | ||
| 1564 | |||
| 1565 | shutdown(info); | ||
| 1566 | dma = new_config.dma_channel; | ||
| 1567 | info->stat_flags &= ~ESP_STAT_NEVER_DMA; | ||
| 1568 | |||
| 1569 | /* all ports must use the same DMA channel */ | ||
| 1570 | |||
| 1571 | spin_lock_irqsave(&info->lock, flags); | ||
| 1572 | current_async = ports; | ||
| 1573 | |||
| 1574 | while (current_async) { | ||
| 1575 | esp_basic_init(current_async); | ||
| 1576 | current_async = current_async->next_port; | ||
| 1577 | } | ||
| 1578 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1579 | } else { | ||
| 1580 | /* DMA mode to PIO mode only */ | ||
| 1581 | if (info->port.count > 1) | ||
| 1582 | return -EBUSY; | ||
| 1583 | |||
| 1584 | shutdown(info); | ||
| 1585 | spin_lock_irqsave(&info->lock, flags); | ||
| 1586 | info->stat_flags |= ESP_STAT_NEVER_DMA; | ||
| 1587 | esp_basic_init(info); | ||
| 1588 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1589 | } | ||
| 1590 | } | ||
| 1591 | |||
| 1592 | info->config.pio_threshold = new_config.pio_threshold; | ||
| 1593 | |||
| 1594 | if ((new_config.flow_off != info->config.flow_off) || | ||
| 1595 | (new_config.flow_on != info->config.flow_on)) { | ||
| 1596 | info->config.flow_off = new_config.flow_off; | ||
| 1597 | info->config.flow_on = new_config.flow_on; | ||
| 1598 | |||
| 1599 | spin_lock_irqsave(&info->lock, flags); | ||
| 1600 | serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_LVL); | ||
| 1601 | serial_out(info, UART_ESI_CMD2, new_config.flow_off >> 8); | ||
| 1602 | serial_out(info, UART_ESI_CMD2, new_config.flow_off); | ||
| 1603 | serial_out(info, UART_ESI_CMD2, new_config.flow_on >> 8); | ||
| 1604 | serial_out(info, UART_ESI_CMD2, new_config.flow_on); | ||
| 1605 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1606 | } | ||
| 1607 | |||
| 1608 | if ((new_config.rx_trigger != info->config.rx_trigger) || | ||
| 1609 | (new_config.tx_trigger != info->config.tx_trigger)) { | ||
| 1610 | info->config.rx_trigger = new_config.rx_trigger; | ||
| 1611 | info->config.tx_trigger = new_config.tx_trigger; | ||
| 1612 | spin_lock_irqsave(&info->lock, flags); | ||
| 1613 | serial_out(info, UART_ESI_CMD1, ESI_SET_TRIGGER); | ||
| 1614 | serial_out(info, UART_ESI_CMD2, | ||
| 1615 | new_config.rx_trigger >> 8); | ||
| 1616 | serial_out(info, UART_ESI_CMD2, new_config.rx_trigger); | ||
| 1617 | serial_out(info, UART_ESI_CMD2, | ||
| 1618 | new_config.tx_trigger >> 8); | ||
| 1619 | serial_out(info, UART_ESI_CMD2, new_config.tx_trigger); | ||
| 1620 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1621 | } | ||
| 1622 | |||
| 1623 | if (new_config.rx_timeout != info->config.rx_timeout) { | ||
| 1624 | info->config.rx_timeout = new_config.rx_timeout; | ||
| 1625 | spin_lock_irqsave(&info->lock, flags); | ||
| 1626 | |||
| 1627 | if (info->IER & UART_IER_RDI) { | ||
| 1628 | serial_out(info, UART_ESI_CMD1, | ||
| 1629 | ESI_SET_RX_TIMEOUT); | ||
| 1630 | serial_out(info, UART_ESI_CMD2, | ||
| 1631 | new_config.rx_timeout); | ||
| 1632 | } | ||
| 1633 | |||
| 1634 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1635 | } | ||
| 1636 | |||
| 1637 | if (!(info->port.flags & ASYNC_INITIALIZED)) | ||
| 1638 | retval = startup(info); | ||
| 1639 | |||
| 1640 | return retval; | ||
| 1641 | } | ||
| 1642 | |||
| 1643 | /* | ||
| 1644 | * get_lsr_info - get line status register info | ||
| 1645 | * | ||
| 1646 | * Purpose: Let user call ioctl() to get info when the UART physically | ||
| 1647 | * is emptied. On bus types like RS485, the transmitter must | ||
| 1648 | * release the bus after transmitting. This must be done when | ||
| 1649 | * the transmit shift register is empty, not be done when the | ||
| 1650 | * transmit holding register is empty. This functionality | ||
| 1651 | * allows an RS485 driver to be written in user space. | ||
| 1652 | */ | ||
| 1653 | static int get_lsr_info(struct esp_struct *info, unsigned int __user *value) | ||
| 1654 | { | ||
| 1655 | unsigned char status; | ||
| 1656 | unsigned int result; | ||
| 1657 | unsigned long flags; | ||
| 1658 | |||
| 1659 | spin_lock_irqsave(&info->lock, flags); | ||
| 1660 | serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT); | ||
| 1661 | status = serial_in(info, UART_ESI_STAT1); | ||
| 1662 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1663 | result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); | ||
| 1664 | return put_user(result, value); | ||
| 1665 | } | ||
| 1666 | |||
| 1667 | |||
| 1668 | static int esp_tiocmget(struct tty_struct *tty, struct file *file) | ||
| 1669 | { | ||
| 1670 | struct esp_struct *info = tty->driver_data; | ||
| 1671 | unsigned char control, status; | ||
| 1672 | unsigned long flags; | ||
| 1673 | |||
| 1674 | if (serial_paranoia_check(info, tty->name, __func__)) | ||
| 1675 | return -ENODEV; | ||
| 1676 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
| 1677 | return -EIO; | ||
| 1678 | |||
| 1679 | control = info->MCR; | ||
| 1680 | |||
| 1681 | spin_lock_irqsave(&info->lock, flags); | ||
| 1682 | serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT); | ||
| 1683 | status = serial_in(info, UART_ESI_STAT2); | ||
| 1684 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1685 | |||
| 1686 | return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | ||
| 1687 | | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | ||
| 1688 | | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | ||
| 1689 | | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | ||
| 1690 | | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | ||
| 1691 | | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); | ||
| 1692 | } | ||
| 1693 | |||
| 1694 | static int esp_tiocmset(struct tty_struct *tty, struct file *file, | ||
| 1695 | unsigned int set, unsigned int clear) | ||
| 1696 | { | ||
| 1697 | struct esp_struct *info = tty->driver_data; | ||
| 1698 | unsigned long flags; | ||
| 1699 | |||
| 1700 | if (serial_paranoia_check(info, tty->name, __func__)) | ||
| 1701 | return -ENODEV; | ||
| 1702 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
| 1703 | return -EIO; | ||
| 1704 | |||
| 1705 | spin_lock_irqsave(&info->lock, flags); | ||
| 1706 | |||
| 1707 | if (set & TIOCM_RTS) | ||
| 1708 | info->MCR |= UART_MCR_RTS; | ||
| 1709 | if (set & TIOCM_DTR) | ||
| 1710 | info->MCR |= UART_MCR_DTR; | ||
| 1711 | |||
| 1712 | if (clear & TIOCM_RTS) | ||
| 1713 | info->MCR &= ~UART_MCR_RTS; | ||
| 1714 | if (clear & TIOCM_DTR) | ||
| 1715 | info->MCR &= ~UART_MCR_DTR; | ||
| 1716 | |||
| 1717 | serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); | ||
| 1718 | serial_out(info, UART_ESI_CMD2, UART_MCR); | ||
| 1719 | serial_out(info, UART_ESI_CMD2, info->MCR); | ||
| 1720 | |||
| 1721 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1722 | return 0; | ||
| 1723 | } | ||
| 1724 | |||
| 1725 | /* | ||
| 1726 | * rs_break() --- routine which turns the break handling on or off | ||
| 1727 | */ | ||
| 1728 | static int esp_break(struct tty_struct *tty, int break_state) | ||
| 1729 | { | ||
| 1730 | struct esp_struct *info = tty->driver_data; | ||
| 1731 | unsigned long flags; | ||
| 1732 | |||
| 1733 | if (serial_paranoia_check(info, tty->name, "esp_break")) | ||
| 1734 | return -EINVAL; | ||
| 1735 | |||
| 1736 | if (break_state == -1) { | ||
| 1737 | spin_lock_irqsave(&info->lock, flags); | ||
| 1738 | serial_out(info, UART_ESI_CMD1, ESI_ISSUE_BREAK); | ||
| 1739 | serial_out(info, UART_ESI_CMD2, 0x01); | ||
| 1740 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1741 | |||
| 1742 | /* FIXME - new style wait needed here */ | ||
| 1743 | interruptible_sleep_on(&info->break_wait); | ||
| 1744 | } else { | ||
| 1745 | spin_lock_irqsave(&info->lock, flags); | ||
| 1746 | serial_out(info, UART_ESI_CMD1, ESI_ISSUE_BREAK); | ||
| 1747 | serial_out(info, UART_ESI_CMD2, 0x00); | ||
| 1748 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1749 | } | ||
| 1750 | return 0; | ||
| 1751 | } | ||
| 1752 | |||
| 1753 | static int rs_ioctl(struct tty_struct *tty, struct file *file, | ||
| 1754 | unsigned int cmd, unsigned long arg) | ||
| 1755 | { | ||
| 1756 | struct esp_struct *info = tty->driver_data; | ||
| 1757 | struct async_icount cprev, cnow; /* kernel counter temps */ | ||
| 1758 | struct serial_icounter_struct __user *p_cuser; /* user space */ | ||
| 1759 | void __user *argp = (void __user *)arg; | ||
| 1760 | unsigned long flags; | ||
| 1761 | int ret; | ||
| 1762 | |||
| 1763 | if (serial_paranoia_check(info, tty->name, "rs_ioctl")) | ||
| 1764 | return -ENODEV; | ||
| 1765 | |||
| 1766 | if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && | ||
| 1767 | (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && | ||
| 1768 | (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT) && | ||
| 1769 | (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT) && | ||
| 1770 | (cmd != TIOCGHAYESESP) && (cmd != TIOCSHAYESESP)) { | ||
| 1771 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
| 1772 | return -EIO; | ||
| 1773 | } | ||
| 1774 | |||
| 1775 | switch (cmd) { | ||
| 1776 | case TIOCGSERIAL: | ||
| 1777 | return get_serial_info(info, argp); | ||
| 1778 | case TIOCSSERIAL: | ||
| 1779 | lock_kernel(); | ||
| 1780 | ret = set_serial_info(info, argp); | ||
| 1781 | unlock_kernel(); | ||
| 1782 | return ret; | ||
| 1783 | case TIOCSERGWILD: | ||
| 1784 | return put_user(0L, (unsigned long __user *)argp); | ||
| 1785 | case TIOCSERGETLSR: /* Get line status register */ | ||
| 1786 | return get_lsr_info(info, argp); | ||
| 1787 | case TIOCSERSWILD: | ||
| 1788 | if (!capable(CAP_SYS_ADMIN)) | ||
| 1789 | return -EPERM; | ||
| 1790 | return 0; | ||
| 1791 | /* | ||
| 1792 | * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change | ||
| 1793 | * - mask passed in arg for lines of interest | ||
| 1794 | * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) | ||
| 1795 | * Caller should use TIOCGICOUNT to see which one it was | ||
| 1796 | */ | ||
| 1797 | case TIOCMIWAIT: | ||
| 1798 | spin_lock_irqsave(&info->lock, flags); | ||
| 1799 | cprev = info->icount; /* note the counters on entry */ | ||
| 1800 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1801 | while (1) { | ||
| 1802 | /* FIXME: convert to new style wakeup */ | ||
| 1803 | interruptible_sleep_on(&info->port.delta_msr_wait); | ||
| 1804 | /* see if a signal did it */ | ||
| 1805 | if (signal_pending(current)) | ||
| 1806 | return -ERESTARTSYS; | ||
| 1807 | spin_lock_irqsave(&info->lock, flags); | ||
| 1808 | cnow = info->icount; /* atomic copy */ | ||
| 1809 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1810 | if (cnow.rng == cprev.rng && | ||
| 1811 | cnow.dsr == cprev.dsr && | ||
| 1812 | cnow.dcd == cprev.dcd && | ||
| 1813 | cnow.cts == cprev.cts) | ||
| 1814 | return -EIO; /* no change => error */ | ||
| 1815 | if (((arg & TIOCM_RNG) && | ||
| 1816 | (cnow.rng != cprev.rng)) || | ||
| 1817 | ((arg & TIOCM_DSR) && | ||
| 1818 | (cnow.dsr != cprev.dsr)) || | ||
| 1819 | ((arg & TIOCM_CD) && | ||
| 1820 | (cnow.dcd != cprev.dcd)) || | ||
| 1821 | ((arg & TIOCM_CTS) && | ||
| 1822 | (cnow.cts != cprev.cts))) { | ||
| 1823 | return 0; | ||
| 1824 | } | ||
| 1825 | cprev = cnow; | ||
| 1826 | } | ||
| 1827 | /* NOTREACHED */ | ||
| 1828 | /* | ||
| 1829 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) | ||
| 1830 | * Return: write counters to the user passed counter struct | ||
| 1831 | * NB: both 1->0 and 0->1 transitions are counted except for | ||
| 1832 | * RI where only 0->1 is counted. | ||
| 1833 | */ | ||
| 1834 | case TIOCGICOUNT: | ||
| 1835 | spin_lock_irqsave(&info->lock, flags); | ||
| 1836 | cnow = info->icount; | ||
| 1837 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1838 | p_cuser = argp; | ||
| 1839 | if (put_user(cnow.cts, &p_cuser->cts) || | ||
| 1840 | put_user(cnow.dsr, &p_cuser->dsr) || | ||
| 1841 | put_user(cnow.rng, &p_cuser->rng) || | ||
| 1842 | put_user(cnow.dcd, &p_cuser->dcd)) | ||
| 1843 | return -EFAULT; | ||
| 1844 | return 0; | ||
| 1845 | case TIOCGHAYESESP: | ||
| 1846 | return get_esp_config(info, argp); | ||
| 1847 | case TIOCSHAYESESP: | ||
| 1848 | lock_kernel(); | ||
| 1849 | ret = set_esp_config(info, argp); | ||
| 1850 | unlock_kernel(); | ||
| 1851 | return ret; | ||
| 1852 | default: | ||
| 1853 | return -ENOIOCTLCMD; | ||
| 1854 | } | ||
| 1855 | return 0; | ||
| 1856 | } | ||
| 1857 | |||
| 1858 | static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | ||
| 1859 | { | ||
| 1860 | struct esp_struct *info = tty->driver_data; | ||
| 1861 | unsigned long flags; | ||
| 1862 | |||
| 1863 | change_speed(info); | ||
| 1864 | |||
| 1865 | spin_lock_irqsave(&info->lock, flags); | ||
| 1866 | |||
| 1867 | /* Handle transition to B0 status */ | ||
| 1868 | if ((old_termios->c_cflag & CBAUD) && | ||
| 1869 | !(tty->termios->c_cflag & CBAUD)) { | ||
| 1870 | info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); | ||
| 1871 | serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); | ||
| 1872 | serial_out(info, UART_ESI_CMD2, UART_MCR); | ||
| 1873 | serial_out(info, UART_ESI_CMD2, info->MCR); | ||
| 1874 | } | ||
| 1875 | |||
| 1876 | /* Handle transition away from B0 status */ | ||
| 1877 | if (!(old_termios->c_cflag & CBAUD) && | ||
| 1878 | (tty->termios->c_cflag & CBAUD)) { | ||
| 1879 | info->MCR |= (UART_MCR_DTR | UART_MCR_RTS); | ||
| 1880 | serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); | ||
| 1881 | serial_out(info, UART_ESI_CMD2, UART_MCR); | ||
| 1882 | serial_out(info, UART_ESI_CMD2, info->MCR); | ||
| 1883 | } | ||
| 1884 | |||
| 1885 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1886 | |||
| 1887 | /* Handle turning of CRTSCTS */ | ||
| 1888 | if ((old_termios->c_cflag & CRTSCTS) && | ||
| 1889 | !(tty->termios->c_cflag & CRTSCTS)) { | ||
| 1890 | rs_start(tty); | ||
| 1891 | } | ||
| 1892 | } | ||
| 1893 | |||
| 1894 | /* | ||
| 1895 | * ------------------------------------------------------------ | ||
| 1896 | * rs_close() | ||
| 1897 | * | ||
| 1898 | * This routine is called when the serial port gets closed. First, we | ||
| 1899 | * wait for the last remaining data to be sent. Then, we unlink its | ||
| 1900 | * async structure from the interrupt chain if necessary, and we free | ||
| 1901 | * that IRQ if nothing is left in the chain. | ||
| 1902 | * ------------------------------------------------------------ | ||
| 1903 | */ | ||
| 1904 | static void rs_close(struct tty_struct *tty, struct file *filp) | ||
| 1905 | { | ||
| 1906 | struct esp_struct *info = tty->driver_data; | ||
| 1907 | unsigned long flags; | ||
| 1908 | |||
| 1909 | if (!info || serial_paranoia_check(info, tty->name, "rs_close")) | ||
| 1910 | return; | ||
| 1911 | |||
| 1912 | spin_lock_irqsave(&info->lock, flags); | ||
| 1913 | |||
| 1914 | if (tty_hung_up_p(filp)) { | ||
| 1915 | DBG_CNT("before DEC-hung"); | ||
| 1916 | goto out; | ||
| 1917 | } | ||
| 1918 | |||
| 1919 | #ifdef SERIAL_DEBUG_OPEN | ||
| 1920 | printk(KERN_DEBUG "rs_close ttys%d, count = %d\n", | ||
| 1921 | info->line, info->port.count); | ||
| 1922 | #endif | ||
| 1923 | if (tty->count == 1 && info->port.count != 1) { | ||
| 1924 | /* | ||
| 1925 | * Uh, oh. tty->count is 1, which means that the tty | ||
| 1926 | * structure will be freed. Info->count should always | ||
| 1927 | * be one in these conditions. If it's greater than | ||
| 1928 | * one, we've got real problems, since it means the | ||
| 1929 | * serial port won't be shutdown. | ||
| 1930 | */ | ||
| 1931 | printk(KERN_DEBUG "rs_close: bad serial port count; tty->count is 1, info->port.count is %d\n", info->port.count); | ||
| 1932 | info->port.count = 1; | ||
| 1933 | } | ||
| 1934 | if (--info->port.count < 0) { | ||
| 1935 | printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n", | ||
| 1936 | info->line, info->port.count); | ||
| 1937 | info->port.count = 0; | ||
| 1938 | } | ||
| 1939 | if (info->port.count) { | ||
| 1940 | DBG_CNT("before DEC-2"); | ||
| 1941 | goto out; | ||
| 1942 | } | ||
| 1943 | info->port.flags |= ASYNC_CLOSING; | ||
| 1944 | |||
| 1945 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1946 | /* | ||
| 1947 | * Now we wait for the transmit buffer to clear; and we notify | ||
| 1948 | * the line discipline to only process XON/XOFF characters. | ||
| 1949 | */ | ||
| 1950 | tty->closing = 1; | ||
| 1951 | if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
| 1952 | tty_wait_until_sent(tty, info->closing_wait); | ||
| 1953 | /* | ||
| 1954 | * At this point we stop accepting input. To do this, we | ||
| 1955 | * disable the receive line status interrupts, and tell the | ||
| 1956 | * interrupt driver to stop checking the data ready bit in the | ||
| 1957 | * line status register. | ||
| 1958 | */ | ||
| 1959 | /* info->IER &= ~UART_IER_RLSI; */ | ||
| 1960 | info->IER &= ~UART_IER_RDI; | ||
| 1961 | info->read_status_mask &= ~UART_LSR_DR; | ||
| 1962 | if (info->port.flags & ASYNC_INITIALIZED) { | ||
| 1963 | |||
| 1964 | spin_lock_irqsave(&info->lock, flags); | ||
| 1965 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
| 1966 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
| 1967 | |||
| 1968 | /* disable receive timeout */ | ||
| 1969 | serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT); | ||
| 1970 | serial_out(info, UART_ESI_CMD2, 0x00); | ||
| 1971 | |||
| 1972 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1973 | |||
| 1974 | /* | ||
| 1975 | * Before we drop DTR, make sure the UART transmitter | ||
| 1976 | * has completely drained; this is especially | ||
| 1977 | * important if there is a transmit FIFO! | ||
| 1978 | */ | ||
| 1979 | rs_wait_until_sent(tty, info->timeout); | ||
| 1980 | } | ||
| 1981 | shutdown(info); | ||
| 1982 | rs_flush_buffer(tty); | ||
| 1983 | tty_ldisc_flush(tty); | ||
| 1984 | tty->closing = 0; | ||
| 1985 | info->port.tty = NULL; | ||
| 1986 | |||
| 1987 | if (info->port.blocked_open) { | ||
| 1988 | if (info->close_delay) | ||
| 1989 | msleep_interruptible(jiffies_to_msecs(info->close_delay)); | ||
| 1990 | wake_up_interruptible(&info->port.open_wait); | ||
| 1991 | } | ||
| 1992 | info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
| 1993 | wake_up_interruptible(&info->port.close_wait); | ||
| 1994 | return; | ||
| 1995 | |||
| 1996 | out: | ||
| 1997 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 1998 | } | ||
| 1999 | |||
| 2000 | static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | ||
| 2001 | { | ||
| 2002 | struct esp_struct *info = tty->driver_data; | ||
| 2003 | unsigned long orig_jiffies, char_time; | ||
| 2004 | unsigned long flags; | ||
| 2005 | |||
| 2006 | if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) | ||
| 2007 | return; | ||
| 2008 | |||
| 2009 | orig_jiffies = jiffies; | ||
| 2010 | char_time = ((info->timeout - HZ / 50) / 1024) / 5; | ||
| 2011 | |||
| 2012 | if (!char_time) | ||
| 2013 | char_time = 1; | ||
| 2014 | |||
| 2015 | spin_lock_irqsave(&info->lock, flags); | ||
| 2016 | serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); | ||
| 2017 | serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL); | ||
| 2018 | |||
| 2019 | while ((serial_in(info, UART_ESI_STAT1) != 0x03) || | ||
| 2020 | (serial_in(info, UART_ESI_STAT2) != 0xff)) { | ||
| 2021 | |||
| 2022 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 2023 | msleep_interruptible(jiffies_to_msecs(char_time)); | ||
| 2024 | |||
| 2025 | if (signal_pending(current)) | ||
| 2026 | return; | ||
| 2027 | |||
| 2028 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) | ||
| 2029 | return; | ||
| 2030 | |||
| 2031 | spin_lock_irqsave(&info->lock, flags); | ||
| 2032 | serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); | ||
| 2033 | serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL); | ||
| 2034 | } | ||
| 2035 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 2036 | set_current_state(TASK_RUNNING); | ||
| 2037 | } | ||
| 2038 | |||
| 2039 | /* | ||
| 2040 | * esp_hangup() --- called by tty_hangup() when a hangup is signaled. | ||
| 2041 | */ | ||
| 2042 | static void esp_hangup(struct tty_struct *tty) | ||
| 2043 | { | ||
| 2044 | struct esp_struct *info = tty->driver_data; | ||
| 2045 | |||
| 2046 | if (serial_paranoia_check(info, tty->name, "esp_hangup")) | ||
| 2047 | return; | ||
| 2048 | |||
| 2049 | rs_flush_buffer(tty); | ||
| 2050 | shutdown(info); | ||
| 2051 | info->port.count = 0; | ||
| 2052 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; | ||
| 2053 | info->port.tty = NULL; | ||
| 2054 | wake_up_interruptible(&info->port.open_wait); | ||
| 2055 | } | ||
| 2056 | |||
| 2057 | static int esp_carrier_raised(struct tty_port *port) | ||
| 2058 | { | ||
| 2059 | struct esp_struct *info = container_of(port, struct esp_struct, port); | ||
| 2060 | serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT); | ||
| 2061 | if (serial_in(info, UART_ESI_STAT2) & UART_MSR_DCD) | ||
| 2062 | return 1; | ||
| 2063 | return 0; | ||
| 2064 | } | ||
| 2065 | |||
| 2066 | /* | ||
| 2067 | * ------------------------------------------------------------ | ||
| 2068 | * esp_open() and friends | ||
| 2069 | * ------------------------------------------------------------ | ||
| 2070 | */ | ||
| 2071 | static int block_til_ready(struct tty_struct *tty, struct file *filp, | ||
| 2072 | struct esp_struct *info) | ||
| 2073 | { | ||
| 2074 | DECLARE_WAITQUEUE(wait, current); | ||
| 2075 | int retval; | ||
| 2076 | int do_clocal = 0; | ||
| 2077 | unsigned long flags; | ||
| 2078 | int cd; | ||
| 2079 | struct tty_port *port = &info->port; | ||
| 2080 | |||
| 2081 | /* | ||
| 2082 | * If the device is in the middle of being closed, then block | ||
| 2083 | * until it's done, and then try again. | ||
| 2084 | */ | ||
| 2085 | if (tty_hung_up_p(filp) || | ||
| 2086 | (port->flags & ASYNC_CLOSING)) { | ||
| 2087 | if (port->flags & ASYNC_CLOSING) | ||
| 2088 | interruptible_sleep_on(&port->close_wait); | ||
| 2089 | #ifdef SERIAL_DO_RESTART | ||
| 2090 | if (port->flags & ASYNC_HUP_NOTIFY) | ||
| 2091 | return -EAGAIN; | ||
| 2092 | else | ||
| 2093 | return -ERESTARTSYS; | ||
| 2094 | #else | ||
| 2095 | return -EAGAIN; | ||
| 2096 | #endif | ||
| 2097 | } | ||
| 2098 | |||
| 2099 | /* | ||
| 2100 | * If non-blocking mode is set, or the port is not enabled, | ||
| 2101 | * then make the check up front and then exit. | ||
| 2102 | */ | ||
| 2103 | if ((filp->f_flags & O_NONBLOCK) || | ||
| 2104 | (tty->flags & (1 << TTY_IO_ERROR))) { | ||
| 2105 | port->flags |= ASYNC_NORMAL_ACTIVE; | ||
| 2106 | return 0; | ||
| 2107 | } | ||
| 2108 | |||
| 2109 | if (tty->termios->c_cflag & CLOCAL) | ||
| 2110 | do_clocal = 1; | ||
| 2111 | |||
| 2112 | /* | ||
| 2113 | * Block waiting for the carrier detect and the line to become | ||
| 2114 | * free (i.e., not in use by the callout). While we are in | ||
| 2115 | * this loop, port->count is dropped by one, so that | ||
| 2116 | * rs_close() knows when to free things. We restore it upon | ||
| 2117 | * exit, either normal or abnormal. | ||
| 2118 | */ | ||
| 2119 | retval = 0; | ||
| 2120 | add_wait_queue(&port->open_wait, &wait); | ||
| 2121 | #ifdef SERIAL_DEBUG_OPEN | ||
| 2122 | printk(KERN_DEBUG "block_til_ready before block: ttys%d, count = %d\n", | ||
| 2123 | info->line, port->count); | ||
| 2124 | #endif | ||
| 2125 | spin_lock_irqsave(&info->lock, flags); | ||
| 2126 | if (!tty_hung_up_p(filp)) | ||
| 2127 | port->count--; | ||
| 2128 | port->blocked_open++; | ||
| 2129 | while (1) { | ||
| 2130 | if ((tty->termios->c_cflag & CBAUD)) { | ||
| 2131 | unsigned int scratch; | ||
| 2132 | |||
| 2133 | serial_out(info, UART_ESI_CMD1, ESI_READ_UART); | ||
| 2134 | serial_out(info, UART_ESI_CMD2, UART_MCR); | ||
| 2135 | scratch = serial_in(info, UART_ESI_STAT1); | ||
| 2136 | serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); | ||
| 2137 | serial_out(info, UART_ESI_CMD2, UART_MCR); | ||
| 2138 | serial_out(info, UART_ESI_CMD2, | ||
| 2139 | scratch | UART_MCR_DTR | UART_MCR_RTS); | ||
| 2140 | } | ||
| 2141 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 2142 | if (tty_hung_up_p(filp) || | ||
| 2143 | !(port->flags & ASYNC_INITIALIZED)) { | ||
| 2144 | #ifdef SERIAL_DO_RESTART | ||
| 2145 | if (port->flags & ASYNC_HUP_NOTIFY) | ||
| 2146 | retval = -EAGAIN; | ||
| 2147 | else | ||
| 2148 | retval = -ERESTARTSYS; | ||
| 2149 | #else | ||
| 2150 | retval = -EAGAIN; | ||
| 2151 | #endif | ||
| 2152 | break; | ||
| 2153 | } | ||
| 2154 | |||
| 2155 | cd = tty_port_carrier_raised(port); | ||
| 2156 | |||
| 2157 | if (!(port->flags & ASYNC_CLOSING) && | ||
| 2158 | (do_clocal)) | ||
| 2159 | break; | ||
| 2160 | if (signal_pending(current)) { | ||
| 2161 | retval = -ERESTARTSYS; | ||
| 2162 | break; | ||
| 2163 | } | ||
| 2164 | #ifdef SERIAL_DEBUG_OPEN | ||
| 2165 | printk(KERN_DEBUG "block_til_ready blocking: ttys%d, count = %d\n", | ||
| 2166 | info->line, port->count); | ||
| 2167 | #endif | ||
| 2168 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 2169 | schedule(); | ||
| 2170 | spin_lock_irqsave(&info->lock, flags); | ||
| 2171 | } | ||
| 2172 | set_current_state(TASK_RUNNING); | ||
| 2173 | remove_wait_queue(&port->open_wait, &wait); | ||
| 2174 | if (!tty_hung_up_p(filp)) | ||
| 2175 | port->count++; | ||
| 2176 | port->blocked_open--; | ||
| 2177 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 2178 | #ifdef SERIAL_DEBUG_OPEN | ||
| 2179 | printk(KERN_DEBUG "block_til_ready after blocking: ttys%d, count = %d\n", | ||
| 2180 | info->line, port->count); | ||
| 2181 | #endif | ||
| 2182 | if (retval) | ||
| 2183 | return retval; | ||
| 2184 | port->flags |= ASYNC_NORMAL_ACTIVE; | ||
| 2185 | return 0; | ||
| 2186 | } | ||
| 2187 | |||
| 2188 | /* | ||
| 2189 | * This routine is called whenever a serial port is opened. It | ||
| 2190 | * enables interrupts for a serial port, linking in its async structure into | ||
| 2191 | * the IRQ chain. It also performs the serial-specific | ||
| 2192 | * initialization for the tty structure. | ||
| 2193 | */ | ||
| 2194 | static int esp_open(struct tty_struct *tty, struct file *filp) | ||
| 2195 | { | ||
| 2196 | struct esp_struct *info; | ||
| 2197 | int retval, line; | ||
| 2198 | unsigned long flags; | ||
| 2199 | |||
| 2200 | line = tty->index; | ||
| 2201 | if ((line < 0) || (line >= NR_PORTS)) | ||
| 2202 | return -ENODEV; | ||
| 2203 | |||
| 2204 | /* find the port in the chain */ | ||
| 2205 | |||
| 2206 | info = ports; | ||
| 2207 | |||
| 2208 | while (info && (info->line != line)) | ||
| 2209 | info = info->next_port; | ||
| 2210 | |||
| 2211 | if (!info) { | ||
| 2212 | serial_paranoia_check(info, tty->name, "esp_open"); | ||
| 2213 | return -ENODEV; | ||
| 2214 | } | ||
| 2215 | |||
| 2216 | #ifdef SERIAL_DEBUG_OPEN | ||
| 2217 | printk(KERN_DEBUG "esp_open %s, count = %d\n", tty->name, info->port.count); | ||
| 2218 | #endif | ||
| 2219 | spin_lock_irqsave(&info->lock, flags); | ||
| 2220 | info->port.count++; | ||
| 2221 | tty->driver_data = info; | ||
| 2222 | info->port.tty = tty; | ||
| 2223 | |||
| 2224 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 2225 | |||
| 2226 | /* | ||
| 2227 | * Start up serial port | ||
| 2228 | */ | ||
| 2229 | retval = startup(info); | ||
| 2230 | if (retval) | ||
| 2231 | return retval; | ||
| 2232 | |||
| 2233 | retval = block_til_ready(tty, filp, info); | ||
| 2234 | if (retval) { | ||
| 2235 | #ifdef SERIAL_DEBUG_OPEN | ||
| 2236 | printk(KERN_DEBUG "esp_open returning after block_til_ready with %d\n", | ||
| 2237 | retval); | ||
| 2238 | #endif | ||
| 2239 | return retval; | ||
| 2240 | } | ||
| 2241 | #ifdef SERIAL_DEBUG_OPEN | ||
| 2242 | printk(KERN_DEBUG "esp_open %s successful...", tty->name); | ||
| 2243 | #endif | ||
| 2244 | return 0; | ||
| 2245 | } | ||
| 2246 | |||
| 2247 | /* | ||
| 2248 | * --------------------------------------------------------------------- | ||
| 2249 | * espserial_init() and friends | ||
| 2250 | * | ||
| 2251 | * espserial_init() is called at boot-time to initialize the serial driver. | ||
| 2252 | * --------------------------------------------------------------------- | ||
| 2253 | */ | ||
| 2254 | |||
| 2255 | /* | ||
| 2256 | * This routine prints out the appropriate serial driver version | ||
| 2257 | * number, and identifies which options were configured into this | ||
| 2258 | * driver. | ||
| 2259 | */ | ||
| 2260 | |||
| 2261 | static void __init show_serial_version(void) | ||
| 2262 | { | ||
| 2263 | printk(KERN_INFO "%s version %s (DMA %u)\n", | ||
| 2264 | serial_name, serial_version, dma); | ||
| 2265 | } | ||
| 2266 | |||
| 2267 | /* | ||
| 2268 | * This routine is called by espserial_init() to initialize a specific serial | ||
| 2269 | * port. | ||
| 2270 | */ | ||
| 2271 | static int autoconfig(struct esp_struct *info) | ||
| 2272 | { | ||
| 2273 | int port_detected = 0; | ||
| 2274 | unsigned long flags; | ||
| 2275 | |||
| 2276 | if (!request_region(info->io_port, REGION_SIZE, "esp serial")) | ||
| 2277 | return -EIO; | ||
| 2278 | |||
| 2279 | spin_lock_irqsave(&info->lock, flags); | ||
| 2280 | /* | ||
| 2281 | * Check for ESP card | ||
| 2282 | */ | ||
| 2283 | |||
| 2284 | if (serial_in(info, UART_ESI_BASE) == 0xf3) { | ||
| 2285 | serial_out(info, UART_ESI_CMD1, 0x00); | ||
| 2286 | serial_out(info, UART_ESI_CMD1, 0x01); | ||
| 2287 | |||
| 2288 | if ((serial_in(info, UART_ESI_STAT2) & 0x70) == 0x20) { | ||
| 2289 | port_detected = 1; | ||
| 2290 | |||
| 2291 | if (!(info->irq)) { | ||
| 2292 | serial_out(info, UART_ESI_CMD1, 0x02); | ||
| 2293 | |||
| 2294 | if (serial_in(info, UART_ESI_STAT1) & 0x01) | ||
| 2295 | info->irq = 3; | ||
| 2296 | else | ||
| 2297 | info->irq = 4; | ||
| 2298 | } | ||
| 2299 | |||
| 2300 | |||
| 2301 | /* put card in enhanced mode */ | ||
| 2302 | /* this prevents access through */ | ||
| 2303 | /* the "old" IO ports */ | ||
| 2304 | esp_basic_init(info); | ||
| 2305 | |||
| 2306 | /* clear out MCR */ | ||
| 2307 | serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); | ||
| 2308 | serial_out(info, UART_ESI_CMD2, UART_MCR); | ||
| 2309 | serial_out(info, UART_ESI_CMD2, 0x00); | ||
| 2310 | } | ||
| 2311 | } | ||
| 2312 | if (!port_detected) | ||
| 2313 | release_region(info->io_port, REGION_SIZE); | ||
| 2314 | |||
| 2315 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 2316 | return (port_detected); | ||
| 2317 | } | ||
| 2318 | |||
| 2319 | static const struct tty_operations esp_ops = { | ||
| 2320 | .open = esp_open, | ||
| 2321 | .close = rs_close, | ||
| 2322 | .write = rs_write, | ||
| 2323 | .put_char = rs_put_char, | ||
| 2324 | .flush_chars = rs_flush_chars, | ||
| 2325 | .write_room = rs_write_room, | ||
| 2326 | .chars_in_buffer = rs_chars_in_buffer, | ||
| 2327 | .flush_buffer = rs_flush_buffer, | ||
| 2328 | .ioctl = rs_ioctl, | ||
| 2329 | .throttle = rs_throttle, | ||
| 2330 | .unthrottle = rs_unthrottle, | ||
| 2331 | .set_termios = rs_set_termios, | ||
| 2332 | .stop = rs_stop, | ||
| 2333 | .start = rs_start, | ||
| 2334 | .hangup = esp_hangup, | ||
| 2335 | .break_ctl = esp_break, | ||
| 2336 | .wait_until_sent = rs_wait_until_sent, | ||
| 2337 | .tiocmget = esp_tiocmget, | ||
| 2338 | .tiocmset = esp_tiocmset, | ||
| 2339 | }; | ||
| 2340 | |||
| 2341 | static const struct tty_port_operations esp_port_ops = { | ||
| 2342 | .esp_carrier_raised, | ||
| 2343 | }; | ||
| 2344 | |||
| 2345 | /* | ||
| 2346 | * The serial driver boot-time initialization code! | ||
| 2347 | */ | ||
| 2348 | static int __init espserial_init(void) | ||
| 2349 | { | ||
| 2350 | int i, offset; | ||
| 2351 | struct esp_struct *info; | ||
| 2352 | struct esp_struct *last_primary = NULL; | ||
| 2353 | int esp[] = { 0x100, 0x140, 0x180, 0x200, 0x240, 0x280, 0x300, 0x380 }; | ||
| 2354 | |||
| 2355 | esp_driver = alloc_tty_driver(NR_PORTS); | ||
| 2356 | if (!esp_driver) | ||
| 2357 | return -ENOMEM; | ||
| 2358 | |||
| 2359 | for (i = 0; i < NR_PRIMARY; i++) { | ||
| 2360 | if (irq[i] != 0) { | ||
| 2361 | if ((irq[i] < 2) || (irq[i] > 15) || (irq[i] == 6) || | ||
| 2362 | (irq[i] == 8) || (irq[i] == 13)) | ||
| 2363 | irq[i] = 0; | ||
| 2364 | else if (irq[i] == 2) | ||
| 2365 | irq[i] = 9; | ||
| 2366 | } | ||
| 2367 | } | ||
| 2368 | |||
| 2369 | if ((dma != 1) && (dma != 3)) | ||
| 2370 | dma = 0; | ||
| 2371 | |||
| 2372 | if ((rx_trigger < 1) || (rx_trigger > 1023)) | ||
| 2373 | rx_trigger = 768; | ||
| 2374 | |||
| 2375 | if ((tx_trigger < 1) || (tx_trigger > 1023)) | ||
| 2376 | tx_trigger = 768; | ||
| 2377 | |||
| 2378 | if ((flow_off < 1) || (flow_off > 1023)) | ||
| 2379 | flow_off = 1016; | ||
| 2380 | |||
| 2381 | if ((flow_on < 1) || (flow_on > 1023)) | ||
| 2382 | flow_on = 944; | ||
| 2383 | |||
| 2384 | if ((rx_timeout < 0) || (rx_timeout > 255)) | ||
| 2385 | rx_timeout = 128; | ||
| 2386 | |||
| 2387 | if (flow_on >= flow_off) | ||
| 2388 | flow_on = flow_off - 1; | ||
| 2389 | |||
| 2390 | show_serial_version(); | ||
| 2391 | |||
| 2392 | /* Initialize the tty_driver structure */ | ||
| 2393 | |||
| 2394 | esp_driver->owner = THIS_MODULE; | ||
| 2395 | esp_driver->name = "ttyP"; | ||
| 2396 | esp_driver->major = ESP_IN_MAJOR; | ||
| 2397 | esp_driver->minor_start = 0; | ||
| 2398 | esp_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
| 2399 | esp_driver->subtype = SERIAL_TYPE_NORMAL; | ||
| 2400 | esp_driver->init_termios = tty_std_termios; | ||
| 2401 | esp_driver->init_termios.c_cflag = | ||
| 2402 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; | ||
| 2403 | esp_driver->init_termios.c_ispeed = 9600; | ||
| 2404 | esp_driver->init_termios.c_ospeed = 9600; | ||
| 2405 | esp_driver->flags = TTY_DRIVER_REAL_RAW; | ||
| 2406 | tty_set_operations(esp_driver, &esp_ops); | ||
| 2407 | if (tty_register_driver(esp_driver)) { | ||
| 2408 | printk(KERN_ERR "Couldn't register esp serial driver"); | ||
| 2409 | put_tty_driver(esp_driver); | ||
| 2410 | return 1; | ||
| 2411 | } | ||
| 2412 | |||
| 2413 | info = kzalloc(sizeof(struct esp_struct), GFP_KERNEL); | ||
| 2414 | |||
| 2415 | if (!info) { | ||
| 2416 | printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n"); | ||
| 2417 | tty_unregister_driver(esp_driver); | ||
| 2418 | put_tty_driver(esp_driver); | ||
| 2419 | return 1; | ||
| 2420 | } | ||
| 2421 | |||
| 2422 | spin_lock_init(&info->lock); | ||
| 2423 | /* rx_trigger, tx_trigger are needed by autoconfig */ | ||
| 2424 | info->config.rx_trigger = rx_trigger; | ||
| 2425 | info->config.tx_trigger = tx_trigger; | ||
| 2426 | |||
| 2427 | i = 0; | ||
| 2428 | offset = 0; | ||
| 2429 | |||
| 2430 | do { | ||
| 2431 | tty_port_init(&info->port); | ||
| 2432 | info->port.ops = &esp_port_ops; | ||
| 2433 | info->io_port = esp[i] + offset; | ||
| 2434 | info->irq = irq[i]; | ||
| 2435 | info->line = (i * 8) + (offset / 8); | ||
| 2436 | |||
| 2437 | if (!autoconfig(info)) { | ||
| 2438 | i++; | ||
| 2439 | offset = 0; | ||
| 2440 | continue; | ||
| 2441 | } | ||
| 2442 | |||
| 2443 | info->custom_divisor = (divisor[i] >> (offset / 2)) & 0xf; | ||
| 2444 | info->port.flags = STD_COM_FLAGS; | ||
| 2445 | if (info->custom_divisor) | ||
| 2446 | info->port.flags |= ASYNC_SPD_CUST; | ||
| 2447 | info->magic = ESP_MAGIC; | ||
| 2448 | info->close_delay = 5*HZ/10; | ||
| 2449 | info->closing_wait = 30*HZ; | ||
| 2450 | info->config.rx_timeout = rx_timeout; | ||
| 2451 | info->config.flow_on = flow_on; | ||
| 2452 | info->config.flow_off = flow_off; | ||
| 2453 | info->config.pio_threshold = pio_threshold; | ||
| 2454 | info->next_port = ports; | ||
| 2455 | init_waitqueue_head(&info->break_wait); | ||
| 2456 | ports = info; | ||
| 2457 | printk(KERN_INFO "ttyP%d at 0x%04x (irq = %d) is an ESP ", | ||
| 2458 | info->line, info->io_port, info->irq); | ||
| 2459 | |||
| 2460 | if (info->line % 8) { | ||
| 2461 | printk("secondary port\n"); | ||
| 2462 | /* 8 port cards can't do DMA */ | ||
| 2463 | info->stat_flags |= ESP_STAT_NEVER_DMA; | ||
| 2464 | |||
| 2465 | if (last_primary) | ||
| 2466 | last_primary->stat_flags |= ESP_STAT_NEVER_DMA; | ||
| 2467 | } else { | ||
| 2468 | printk("primary port\n"); | ||
| 2469 | last_primary = info; | ||
| 2470 | irq[i] = info->irq; | ||
| 2471 | } | ||
| 2472 | |||
| 2473 | if (!dma) | ||
| 2474 | info->stat_flags |= ESP_STAT_NEVER_DMA; | ||
| 2475 | |||
| 2476 | info = kzalloc(sizeof(struct esp_struct), GFP_KERNEL); | ||
| 2477 | if (!info) { | ||
| 2478 | printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n"); | ||
| 2479 | /* allow use of the already detected ports */ | ||
| 2480 | return 0; | ||
| 2481 | } | ||
| 2482 | |||
| 2483 | spin_lock_init(&info->lock); | ||
| 2484 | /* rx_trigger, tx_trigger are needed by autoconfig */ | ||
| 2485 | info->config.rx_trigger = rx_trigger; | ||
| 2486 | info->config.tx_trigger = tx_trigger; | ||
| 2487 | |||
| 2488 | if (offset == 56) { | ||
| 2489 | i++; | ||
| 2490 | offset = 0; | ||
| 2491 | } else { | ||
| 2492 | offset += 8; | ||
| 2493 | } | ||
| 2494 | } while (i < NR_PRIMARY); | ||
| 2495 | |||
| 2496 | /* free the last port memory allocation */ | ||
| 2497 | kfree(info); | ||
| 2498 | |||
| 2499 | return 0; | ||
| 2500 | } | ||
| 2501 | |||
| 2502 | static void __exit espserial_exit(void) | ||
| 2503 | { | ||
| 2504 | int e1; | ||
| 2505 | struct esp_struct *temp_async; | ||
| 2506 | struct esp_pio_buffer *pio_buf; | ||
| 2507 | |||
| 2508 | e1 = tty_unregister_driver(esp_driver); | ||
| 2509 | if (e1) | ||
| 2510 | printk(KERN_ERR "esp: failed to unregister driver (%d)\n", e1); | ||
| 2511 | put_tty_driver(esp_driver); | ||
| 2512 | |||
| 2513 | while (ports) { | ||
| 2514 | if (ports->io_port) | ||
| 2515 | release_region(ports->io_port, REGION_SIZE); | ||
| 2516 | temp_async = ports->next_port; | ||
| 2517 | kfree(ports); | ||
| 2518 | ports = temp_async; | ||
| 2519 | } | ||
| 2520 | |||
| 2521 | if (dma_buffer) | ||
| 2522 | free_pages((unsigned long)dma_buffer, | ||
| 2523 | get_order(DMA_BUFFER_SZ)); | ||
| 2524 | |||
| 2525 | while (free_pio_buf) { | ||
| 2526 | pio_buf = free_pio_buf->next; | ||
| 2527 | kfree(free_pio_buf); | ||
| 2528 | free_pio_buf = pio_buf; | ||
| 2529 | } | ||
| 2530 | } | ||
| 2531 | |||
| 2532 | module_init(espserial_init); | ||
| 2533 | module_exit(espserial_exit); | ||
| diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 426bfdd7f3e0..300d5bd6cd06 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
| @@ -793,35 +793,30 @@ static inline void isicom_setup_board(struct isi_board *bp) | |||
| 793 | { | 793 | { | 
| 794 | int channel; | 794 | int channel; | 
| 795 | struct isi_port *port; | 795 | struct isi_port *port; | 
| 796 | unsigned long flags; | ||
| 797 | 796 | ||
| 798 | spin_lock_irqsave(&bp->card_lock, flags); | 797 | bp->count++; | 
| 799 | if (bp->status & BOARD_ACTIVE) { | 798 | if (!(bp->status & BOARD_INIT)) { | 
| 800 | spin_unlock_irqrestore(&bp->card_lock, flags); | 799 | port = bp->ports; | 
| 801 | return; | 800 | for (channel = 0; channel < bp->port_count; channel++, port++) | 
| 801 | drop_dtr_rts(port); | ||
| 802 | } | 802 | } | 
| 803 | port = bp->ports; | 803 | bp->status |= BOARD_ACTIVE | BOARD_INIT; | 
| 804 | bp->status |= BOARD_ACTIVE; | ||
| 805 | for (channel = 0; channel < bp->port_count; channel++, port++) | ||
| 806 | drop_dtr_rts(port); | ||
| 807 | spin_unlock_irqrestore(&bp->card_lock, flags); | ||
| 808 | } | 804 | } | 
| 809 | 805 | ||
| 810 | static int isicom_setup_port(struct tty_struct *tty) | 806 | /* Activate and thus setup board are protected from races against shutdown | 
| 807 | by the tty_port mutex */ | ||
| 808 | |||
| 809 | static int isicom_activate(struct tty_port *tport, struct tty_struct *tty) | ||
| 811 | { | 810 | { | 
| 812 | struct isi_port *port = tty->driver_data; | 811 | struct isi_port *port = container_of(tport, struct isi_port, port); | 
| 813 | struct isi_board *card = port->card; | 812 | struct isi_board *card = port->card; | 
| 814 | unsigned long flags; | 813 | unsigned long flags; | 
| 815 | 814 | ||
| 816 | if (port->port.flags & ASYNC_INITIALIZED) | 815 | if (tty_port_alloc_xmit_buf(tport) < 0) | 
| 817 | return 0; | ||
| 818 | if (tty_port_alloc_xmit_buf(&port->port) < 0) | ||
| 819 | return -ENOMEM; | 816 | return -ENOMEM; | 
| 820 | 817 | ||
| 821 | spin_lock_irqsave(&card->card_lock, flags); | 818 | spin_lock_irqsave(&card->card_lock, flags); | 
| 822 | clear_bit(TTY_IO_ERROR, &tty->flags); | 819 | isicom_setup_board(card); | 
| 823 | if (port->port.count == 1) | ||
| 824 | card->count++; | ||
| 825 | 820 | ||
| 826 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; | 821 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; | 
| 827 | 822 | ||
| @@ -832,9 +827,7 @@ static int isicom_setup_port(struct tty_struct *tty) | |||
| 832 | outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base); | 827 | outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base); | 
| 833 | InterruptTheCard(card->base); | 828 | InterruptTheCard(card->base); | 
| 834 | } | 829 | } | 
| 835 | |||
| 836 | isicom_config_port(tty); | 830 | isicom_config_port(tty); | 
| 837 | port->port.flags |= ASYNC_INITIALIZED; | ||
| 838 | spin_unlock_irqrestore(&card->card_lock, flags); | 831 | spin_unlock_irqrestore(&card->card_lock, flags); | 
| 839 | 832 | ||
| 840 | return 0; | 833 | return 0; | 
| @@ -871,85 +864,37 @@ static struct tty_port *isicom_find_port(struct tty_struct *tty) | |||
| 871 | 864 | ||
| 872 | return &port->port; | 865 | return &port->port; | 
| 873 | } | 866 | } | 
| 874 | 867 | ||
| 875 | static int isicom_open(struct tty_struct *tty, struct file *filp) | 868 | static int isicom_open(struct tty_struct *tty, struct file *filp) | 
| 876 | { | 869 | { | 
| 877 | struct isi_port *port; | 870 | struct isi_port *port; | 
| 878 | struct isi_board *card; | 871 | struct isi_board *card; | 
| 879 | struct tty_port *tport; | 872 | struct tty_port *tport; | 
| 880 | int error = 0; | ||
| 881 | 873 | ||
| 882 | tport = isicom_find_port(tty); | 874 | tport = isicom_find_port(tty); | 
| 883 | if (tport == NULL) | 875 | if (tport == NULL) | 
| 884 | return -ENODEV; | 876 | return -ENODEV; | 
| 885 | port = container_of(tport, struct isi_port, port); | 877 | port = container_of(tport, struct isi_port, port); | 
| 886 | card = &isi_card[BOARD(tty->index)]; | 878 | card = &isi_card[BOARD(tty->index)]; | 
| 887 | isicom_setup_board(card); | ||
| 888 | 879 | ||
| 889 | /* FIXME: locking on port.count etc */ | 880 | return tty_port_open(tport, tty, filp); | 
| 890 | port->port.count++; | ||
| 891 | tty->driver_data = port; | ||
| 892 | tty_port_tty_set(&port->port, tty); | ||
| 893 | /* FIXME: Locking on Initialized flag */ | ||
| 894 | if (!test_bit(ASYNCB_INITIALIZED, &tport->flags)) | ||
| 895 | error = isicom_setup_port(tty); | ||
| 896 | if (error == 0) | ||
| 897 | error = tty_port_block_til_ready(&port->port, tty, filp); | ||
| 898 | return error; | ||
| 899 | } | 881 | } | 
| 900 | 882 | ||
| 901 | /* close et all */ | 883 | /* close et all */ | 
| 902 | 884 | ||
| 903 | static inline void isicom_shutdown_board(struct isi_board *bp) | ||
| 904 | { | ||
| 905 | if (bp->status & BOARD_ACTIVE) | ||
| 906 | bp->status &= ~BOARD_ACTIVE; | ||
| 907 | } | ||
| 908 | |||
| 909 | /* card->lock HAS to be held */ | 885 | /* card->lock HAS to be held */ | 
| 910 | static void isicom_shutdown_port(struct isi_port *port) | 886 | static void isicom_shutdown_port(struct isi_port *port) | 
| 911 | { | 887 | { | 
| 912 | struct isi_board *card = port->card; | 888 | struct isi_board *card = port->card; | 
| 913 | struct tty_struct *tty; | ||
| 914 | |||
| 915 | tty = tty_port_tty_get(&port->port); | ||
| 916 | |||
| 917 | if (!(port->port.flags & ASYNC_INITIALIZED)) { | ||
| 918 | tty_kref_put(tty); | ||
| 919 | return; | ||
| 920 | } | ||
| 921 | |||
| 922 | tty_port_free_xmit_buf(&port->port); | ||
| 923 | port->port.flags &= ~ASYNC_INITIALIZED; | ||
| 924 | /* 3rd October 2000 : Vinayak P Risbud */ | ||
| 925 | tty_port_tty_set(&port->port, NULL); | ||
| 926 | |||
| 927 | /*Fix done by Anil .S on 30-04-2001 | ||
| 928 | remote login through isi port has dtr toggle problem | ||
| 929 | due to which the carrier drops before the password prompt | ||
| 930 | appears on the remote end. Now we drop the dtr only if the | ||
| 931 | HUPCL(Hangup on close) flag is set for the tty*/ | ||
| 932 | |||
| 933 | if (C_HUPCL(tty)) | ||
| 934 | /* drop dtr on this port */ | ||
| 935 | drop_dtr(port); | ||
| 936 | |||
| 937 | /* any other port uninits */ | ||
| 938 | if (tty) | ||
| 939 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
| 940 | 889 | ||
| 941 | if (--card->count < 0) { | 890 | if (--card->count < 0) { | 
| 942 | pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n", | 891 | pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n", | 
| 943 | card->base, card->count); | 892 | card->base, card->count); | 
| 944 | card->count = 0; | 893 | card->count = 0; | 
| 945 | } | 894 | } | 
| 946 | 895 | /* last port was closed, shutdown that board too */ | |
| 947 | /* last port was closed, shutdown that boad too */ | 896 | if (!card->count) | 
| 948 | if (C_HUPCL(tty)) { | 897 | card->status &= BOARD_ACTIVE; | 
| 949 | if (!card->count) | ||
| 950 | isicom_shutdown_board(card); | ||
| 951 | } | ||
| 952 | tty_kref_put(tty); | ||
| 953 | } | 898 | } | 
| 954 | 899 | ||
| 955 | static void isicom_flush_buffer(struct tty_struct *tty) | 900 | static void isicom_flush_buffer(struct tty_struct *tty) | 
| @@ -968,7 +913,7 @@ static void isicom_flush_buffer(struct tty_struct *tty) | |||
| 968 | tty_wakeup(tty); | 913 | tty_wakeup(tty); | 
| 969 | } | 914 | } | 
| 970 | 915 | ||
| 971 | static void isicom_close_port(struct tty_port *port) | 916 | static void isicom_shutdown(struct tty_port *port) | 
| 972 | { | 917 | { | 
| 973 | struct isi_port *ip = container_of(port, struct isi_port, port); | 918 | struct isi_port *ip = container_of(port, struct isi_port, port); | 
| 974 | struct isi_board *card = ip->card; | 919 | struct isi_board *card = ip->card; | 
| @@ -977,12 +922,11 @@ static void isicom_close_port(struct tty_port *port) | |||
| 977 | /* indicate to the card that no more data can be received | 922 | /* indicate to the card that no more data can be received | 
| 978 | on this port */ | 923 | on this port */ | 
| 979 | spin_lock_irqsave(&card->card_lock, flags); | 924 | spin_lock_irqsave(&card->card_lock, flags); | 
| 980 | if (port->flags & ASYNC_INITIALIZED) { | 925 | card->port_status &= ~(1 << ip->channel); | 
| 981 | card->port_status &= ~(1 << ip->channel); | 926 | outw(card->port_status, card->base + 0x02); | 
| 982 | outw(card->port_status, card->base + 0x02); | ||
| 983 | } | ||
| 984 | isicom_shutdown_port(ip); | 927 | isicom_shutdown_port(ip); | 
| 985 | spin_unlock_irqrestore(&card->card_lock, flags); | 928 | spin_unlock_irqrestore(&card->card_lock, flags); | 
| 929 | tty_port_free_xmit_buf(port); | ||
| 986 | } | 930 | } | 
| 987 | 931 | ||
| 988 | static void isicom_close(struct tty_struct *tty, struct file *filp) | 932 | static void isicom_close(struct tty_struct *tty, struct file *filp) | 
| @@ -991,12 +935,7 @@ static void isicom_close(struct tty_struct *tty, struct file *filp) | |||
| 991 | struct tty_port *port = &ip->port; | 935 | struct tty_port *port = &ip->port; | 
| 992 | if (isicom_paranoia_check(ip, tty->name, "isicom_close")) | 936 | if (isicom_paranoia_check(ip, tty->name, "isicom_close")) | 
| 993 | return; | 937 | return; | 
| 994 | 938 | tty_port_close(port, tty, filp); | |
| 995 | if (tty_port_close_start(port, tty, filp) == 0) | ||
| 996 | return; | ||
| 997 | isicom_close_port(port); | ||
| 998 | isicom_flush_buffer(tty); | ||
| 999 | tty_port_close_end(port, tty); | ||
| 1000 | } | 939 | } | 
| 1001 | 940 | ||
| 1002 | /* write et all */ | 941 | /* write et all */ | 
| @@ -1326,15 +1265,9 @@ static void isicom_start(struct tty_struct *tty) | |||
| 1326 | static void isicom_hangup(struct tty_struct *tty) | 1265 | static void isicom_hangup(struct tty_struct *tty) | 
| 1327 | { | 1266 | { | 
| 1328 | struct isi_port *port = tty->driver_data; | 1267 | struct isi_port *port = tty->driver_data; | 
| 1329 | unsigned long flags; | ||
| 1330 | 1268 | ||
| 1331 | if (isicom_paranoia_check(port, tty->name, "isicom_hangup")) | 1269 | if (isicom_paranoia_check(port, tty->name, "isicom_hangup")) | 
| 1332 | return; | 1270 | return; | 
| 1333 | |||
| 1334 | spin_lock_irqsave(&port->card->card_lock, flags); | ||
| 1335 | isicom_shutdown_port(port); | ||
| 1336 | spin_unlock_irqrestore(&port->card->card_lock, flags); | ||
| 1337 | |||
| 1338 | tty_port_hangup(&port->port); | 1271 | tty_port_hangup(&port->port); | 
| 1339 | } | 1272 | } | 
| 1340 | 1273 | ||
| @@ -1367,6 +1300,8 @@ static const struct tty_operations isicom_ops = { | |||
| 1367 | static const struct tty_port_operations isicom_port_ops = { | 1300 | static const struct tty_port_operations isicom_port_ops = { | 
| 1368 | .carrier_raised = isicom_carrier_raised, | 1301 | .carrier_raised = isicom_carrier_raised, | 
| 1369 | .dtr_rts = isicom_dtr_rts, | 1302 | .dtr_rts = isicom_dtr_rts, | 
| 1303 | .activate = isicom_activate, | ||
| 1304 | .shutdown = isicom_shutdown, | ||
| 1370 | }; | 1305 | }; | 
| 1371 | 1306 | ||
| 1372 | static int __devinit reset_card(struct pci_dev *pdev, | 1307 | static int __devinit reset_card(struct pci_dev *pdev, | 
| diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 402838f4083e..4cd6c527ee41 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
| @@ -213,7 +213,6 @@ static int stli_shared; | |||
| 213 | * with the slave. Most of them need to be updated atomically, so always | 213 | * with the slave. Most of them need to be updated atomically, so always | 
| 214 | * use the bit setting operations (unless protected by cli/sti). | 214 | * use the bit setting operations (unless protected by cli/sti). | 
| 215 | */ | 215 | */ | 
| 216 | #define ST_INITIALIZING 1 | ||
| 217 | #define ST_OPENING 2 | 216 | #define ST_OPENING 2 | 
| 218 | #define ST_CLOSING 3 | 217 | #define ST_CLOSING 3 | 
| 219 | #define ST_CMDING 4 | 218 | #define ST_CMDING 4 | 
| @@ -621,7 +620,7 @@ static int stli_brdinit(struct stlibrd *brdp); | |||
| 621 | static int stli_startbrd(struct stlibrd *brdp); | 620 | static int stli_startbrd(struct stlibrd *brdp); | 
| 622 | static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp); | 621 | static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp); | 
| 623 | static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp); | 622 | static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp); | 
| 624 | static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); | 623 | static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg); | 
| 625 | static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp); | 624 | static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp); | 
| 626 | static void stli_poll(unsigned long arg); | 625 | static void stli_poll(unsigned long arg); | 
| 627 | static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp); | 626 | static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp); | 
| @@ -704,7 +703,7 @@ static const struct file_operations stli_fsiomem = { | |||
| 704 | .owner = THIS_MODULE, | 703 | .owner = THIS_MODULE, | 
| 705 | .read = stli_memread, | 704 | .read = stli_memread, | 
| 706 | .write = stli_memwrite, | 705 | .write = stli_memwrite, | 
| 707 | .ioctl = stli_memioctl, | 706 | .unlocked_ioctl = stli_memioctl, | 
| 708 | }; | 707 | }; | 
| 709 | 708 | ||
| 710 | /*****************************************************************************/ | 709 | /*****************************************************************************/ | 
| @@ -783,13 +782,32 @@ static int stli_parsebrd(struct stlconf *confp, char **argp) | |||
| 783 | 782 | ||
| 784 | /*****************************************************************************/ | 783 | /*****************************************************************************/ | 
| 785 | 784 | ||
| 785 | /* | ||
| 786 | * On the first open of the device setup the port hardware, and | ||
| 787 | * initialize the per port data structure. Since initializing the port | ||
| 788 | * requires several commands to the board we will need to wait for any | ||
| 789 | * other open that is already initializing the port. | ||
| 790 | * | ||
| 791 | * Locking: protected by the port mutex. | ||
| 792 | */ | ||
| 793 | |||
| 794 | static int stli_activate(struct tty_port *port, struct tty_struct *tty) | ||
| 795 | { | ||
| 796 | struct stliport *portp = container_of(port, struct stliport, port); | ||
| 797 | struct stlibrd *brdp = stli_brds[portp->brdnr]; | ||
| 798 | int rc; | ||
| 799 | |||
| 800 | if ((rc = stli_initopen(tty, brdp, portp)) >= 0) | ||
| 801 | clear_bit(TTY_IO_ERROR, &tty->flags); | ||
| 802 | wake_up_interruptible(&portp->raw_wait); | ||
| 803 | return rc; | ||
| 804 | } | ||
| 805 | |||
| 786 | static int stli_open(struct tty_struct *tty, struct file *filp) | 806 | static int stli_open(struct tty_struct *tty, struct file *filp) | 
| 787 | { | 807 | { | 
| 788 | struct stlibrd *brdp; | 808 | struct stlibrd *brdp; | 
| 789 | struct stliport *portp; | 809 | struct stliport *portp; | 
| 790 | struct tty_port *port; | ||
| 791 | unsigned int minordev, brdnr, portnr; | 810 | unsigned int minordev, brdnr, portnr; | 
| 792 | int rc; | ||
| 793 | 811 | ||
| 794 | minordev = tty->index; | 812 | minordev = tty->index; | 
| 795 | brdnr = MINOR2BRD(minordev); | 813 | brdnr = MINOR2BRD(minordev); | 
| @@ -809,95 +827,56 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
| 809 | return -ENODEV; | 827 | return -ENODEV; | 
| 810 | if (portp->devnr < 1) | 828 | if (portp->devnr < 1) | 
| 811 | return -ENODEV; | 829 | return -ENODEV; | 
| 812 | port = &portp->port; | 830 | return tty_port_open(&portp->port, tty, filp); | 
| 813 | |||
| 814 | /* | ||
| 815 | * On the first open of the device setup the port hardware, and | ||
| 816 | * initialize the per port data structure. Since initializing the port | ||
| 817 | * requires several commands to the board we will need to wait for any | ||
| 818 | * other open that is already initializing the port. | ||
| 819 | * | ||
| 820 | * Review - locking | ||
| 821 | */ | ||
| 822 | tty_port_tty_set(port, tty); | ||
| 823 | tty->driver_data = portp; | ||
| 824 | port->count++; | ||
| 825 | |||
| 826 | wait_event_interruptible(portp->raw_wait, | ||
| 827 | !test_bit(ST_INITIALIZING, &portp->state)); | ||
| 828 | if (signal_pending(current)) | ||
| 829 | return -ERESTARTSYS; | ||
| 830 | |||
| 831 | if ((portp->port.flags & ASYNC_INITIALIZED) == 0) { | ||
| 832 | set_bit(ST_INITIALIZING, &portp->state); | ||
| 833 | if ((rc = stli_initopen(tty, brdp, portp)) >= 0) { | ||
| 834 | /* Locking */ | ||
| 835 | port->flags |= ASYNC_INITIALIZED; | ||
| 836 | clear_bit(TTY_IO_ERROR, &tty->flags); | ||
| 837 | } | ||
| 838 | clear_bit(ST_INITIALIZING, &portp->state); | ||
| 839 | wake_up_interruptible(&portp->raw_wait); | ||
| 840 | if (rc < 0) | ||
| 841 | return rc; | ||
| 842 | } | ||
| 843 | return tty_port_block_til_ready(&portp->port, tty, filp); | ||
| 844 | } | 831 | } | 
| 845 | 832 | ||
| 833 | |||
| 846 | /*****************************************************************************/ | 834 | /*****************************************************************************/ | 
| 847 | 835 | ||
| 848 | static void stli_close(struct tty_struct *tty, struct file *filp) | 836 | static void stli_shutdown(struct tty_port *port) | 
| 849 | { | 837 | { | 
| 850 | struct stlibrd *brdp; | 838 | struct stlibrd *brdp; | 
| 851 | struct stliport *portp; | 839 | unsigned long ftype; | 
| 852 | struct tty_port *port; | ||
| 853 | unsigned long flags; | 840 | unsigned long flags; | 
| 841 | struct stliport *portp = container_of(port, struct stliport, port); | ||
| 854 | 842 | ||
| 855 | portp = tty->driver_data; | 843 | if (portp->brdnr >= stli_nrbrds) | 
| 856 | if (portp == NULL) | ||
| 857 | return; | 844 | return; | 
| 858 | port = &portp->port; | 845 | brdp = stli_brds[portp->brdnr]; | 
| 859 | 846 | if (brdp == NULL) | |
| 860 | if (tty_port_close_start(port, tty, filp) == 0) | ||
| 861 | return; | 847 | return; | 
| 862 | 848 | ||
| 863 | /* | 849 | /* | 
| 864 | * May want to wait for data to drain before closing. The BUSY flag | 850 | * May want to wait for data to drain before closing. The BUSY | 
| 865 | * keeps track of whether we are still transmitting or not. It is | 851 | * flag keeps track of whether we are still transmitting or not. | 
| 866 | * updated by messages from the slave - indicating when all chars | 852 | * It is updated by messages from the slave - indicating when all | 
| 867 | * really have drained. | 853 | * chars really have drained. | 
| 868 | */ | 854 | */ | 
| 869 | spin_lock_irqsave(&stli_lock, flags); | ||
| 870 | if (tty == stli_txcooktty) | ||
| 871 | stli_flushchars(tty); | ||
| 872 | spin_unlock_irqrestore(&stli_lock, flags); | ||
| 873 | |||
| 874 | /* We end up doing this twice for the moment. This needs looking at | ||
| 875 | eventually. Note we still use portp->closing_wait as a result */ | ||
| 876 | if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
| 877 | tty_wait_until_sent(tty, portp->closing_wait); | ||
| 878 | 855 | ||
| 879 | /* FIXME: port locking here needs attending to */ | 856 | if (!test_bit(ST_CLOSING, &portp->state)) | 
| 880 | port->flags &= ~ASYNC_INITIALIZED; | 857 | stli_rawclose(brdp, portp, 0, 0); | 
| 881 | 858 | ||
| 882 | brdp = stli_brds[portp->brdnr]; | 859 | spin_lock_irqsave(&stli_lock, flags); | 
| 883 | stli_rawclose(brdp, portp, 0, 0); | ||
| 884 | if (tty->termios->c_cflag & HUPCL) { | ||
| 885 | stli_mkasysigs(&portp->asig, 0, 0); | ||
| 886 | if (test_bit(ST_CMDING, &portp->state)) | ||
| 887 | set_bit(ST_DOSIGS, &portp->state); | ||
| 888 | else | ||
| 889 | stli_sendcmd(brdp, portp, A_SETSIGNALS, &portp->asig, | ||
| 890 | sizeof(asysigs_t), 0); | ||
| 891 | } | ||
| 892 | clear_bit(ST_TXBUSY, &portp->state); | 860 | clear_bit(ST_TXBUSY, &portp->state); | 
| 893 | clear_bit(ST_RXSTOP, &portp->state); | 861 | clear_bit(ST_RXSTOP, &portp->state); | 
| 894 | set_bit(TTY_IO_ERROR, &tty->flags); | 862 | spin_unlock_irqrestore(&stli_lock, flags); | 
| 895 | tty_ldisc_flush(tty); | ||
| 896 | set_bit(ST_DOFLUSHRX, &portp->state); | ||
| 897 | stli_flushbuffer(tty); | ||
| 898 | 863 | ||
| 899 | tty_port_close_end(port, tty); | 864 | ftype = FLUSHTX | FLUSHRX; | 
| 900 | tty_port_tty_set(port, NULL); | 865 | stli_cmdwait(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0); | 
| 866 | } | ||
| 867 | |||
| 868 | static void stli_close(struct tty_struct *tty, struct file *filp) | ||
| 869 | { | ||
| 870 | struct stliport *portp = tty->driver_data; | ||
| 871 | unsigned long flags; | ||
| 872 | if (portp == NULL) | ||
| 873 | return; | ||
| 874 | spin_lock_irqsave(&stli_lock, flags); | ||
| 875 | /* Flush any internal buffering out first */ | ||
| 876 | if (tty == stli_txcooktty) | ||
| 877 | stli_flushchars(tty); | ||
| 878 | spin_unlock_irqrestore(&stli_lock, flags); | ||
| 879 | tty_port_close(&portp->port, tty, filp); | ||
| 901 | } | 880 | } | 
| 902 | 881 | ||
| 903 | /*****************************************************************************/ | 882 | /*****************************************************************************/ | 
| @@ -1724,6 +1703,7 @@ static void stli_start(struct tty_struct *tty) | |||
| 1724 | 1703 | ||
| 1725 | /*****************************************************************************/ | 1704 | /*****************************************************************************/ | 
| 1726 | 1705 | ||
| 1706 | |||
| 1727 | /* | 1707 | /* | 
| 1728 | * Hangup this port. This is pretty much like closing the port, only | 1708 | * Hangup this port. This is pretty much like closing the port, only | 
| 1729 | * a little more brutal. No waiting for data to drain. Shutdown the | 1709 | * a little more brutal. No waiting for data to drain. Shutdown the | 
| @@ -1733,47 +1713,8 @@ static void stli_start(struct tty_struct *tty) | |||
| 1733 | 1713 | ||
| 1734 | static void stli_hangup(struct tty_struct *tty) | 1714 | static void stli_hangup(struct tty_struct *tty) | 
| 1735 | { | 1715 | { | 
| 1736 | struct stliport *portp; | 1716 | struct stliport *portp = tty->driver_data; | 
| 1737 | struct stlibrd *brdp; | 1717 | tty_port_hangup(&portp->port); | 
| 1738 | struct tty_port *port; | ||
| 1739 | unsigned long flags; | ||
| 1740 | |||
| 1741 | portp = tty->driver_data; | ||
| 1742 | if (portp == NULL) | ||
| 1743 | return; | ||
| 1744 | if (portp->brdnr >= stli_nrbrds) | ||
| 1745 | return; | ||
| 1746 | brdp = stli_brds[portp->brdnr]; | ||
| 1747 | if (brdp == NULL) | ||
| 1748 | return; | ||
| 1749 | port = &portp->port; | ||
| 1750 | |||
| 1751 | spin_lock_irqsave(&port->lock, flags); | ||
| 1752 | port->flags &= ~ASYNC_INITIALIZED; | ||
| 1753 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 1754 | |||
| 1755 | if (!test_bit(ST_CLOSING, &portp->state)) | ||
| 1756 | stli_rawclose(brdp, portp, 0, 0); | ||
| 1757 | |||
| 1758 | spin_lock_irqsave(&stli_lock, flags); | ||
| 1759 | if (tty->termios->c_cflag & HUPCL) { | ||
| 1760 | stli_mkasysigs(&portp->asig, 0, 0); | ||
| 1761 | if (test_bit(ST_CMDING, &portp->state)) { | ||
| 1762 | set_bit(ST_DOSIGS, &portp->state); | ||
| 1763 | set_bit(ST_DOFLUSHTX, &portp->state); | ||
| 1764 | set_bit(ST_DOFLUSHRX, &portp->state); | ||
| 1765 | } else { | ||
| 1766 | stli_sendcmd(brdp, portp, A_SETSIGNALSF, | ||
| 1767 | &portp->asig, sizeof(asysigs_t), 0); | ||
| 1768 | } | ||
| 1769 | } | ||
| 1770 | |||
| 1771 | clear_bit(ST_TXBUSY, &portp->state); | ||
| 1772 | clear_bit(ST_RXSTOP, &portp->state); | ||
| 1773 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
| 1774 | spin_unlock_irqrestore(&stli_lock, flags); | ||
| 1775 | |||
| 1776 | tty_port_hangup(port); | ||
| 1777 | } | 1718 | } | 
| 1778 | 1719 | ||
| 1779 | /*****************************************************************************/ | 1720 | /*****************************************************************************/ | 
| @@ -4311,7 +4252,7 @@ static int stli_getbrdstruct(struct stlibrd __user *arg) | |||
| 4311 | * reset it, and start/stop it. | 4252 | * reset it, and start/stop it. | 
| 4312 | */ | 4253 | */ | 
| 4313 | 4254 | ||
| 4314 | static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg) | 4255 | static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | 
| 4315 | { | 4256 | { | 
| 4316 | struct stlibrd *brdp; | 4257 | struct stlibrd *brdp; | 
| 4317 | int brdnr, rc, done; | 4258 | int brdnr, rc, done; | 
| @@ -4356,7 +4297,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un | |||
| 4356 | * Now handle the board specific ioctls. These all depend on the | 4297 | * Now handle the board specific ioctls. These all depend on the | 
| 4357 | * minor number of the device they were called from. | 4298 | * minor number of the device they were called from. | 
| 4358 | */ | 4299 | */ | 
| 4359 | brdnr = iminor(ip); | 4300 | brdnr = iminor(fp->f_dentry->d_inode); | 
| 4360 | if (brdnr >= STL_MAXBRDS) | 4301 | if (brdnr >= STL_MAXBRDS) | 
| 4361 | return -ENODEV; | 4302 | return -ENODEV; | 
| 4362 | brdp = stli_brds[brdnr]; | 4303 | brdp = stli_brds[brdnr]; | 
| @@ -4420,6 +4361,8 @@ static const struct tty_operations stli_ops = { | |||
| 4420 | static const struct tty_port_operations stli_port_ops = { | 4361 | static const struct tty_port_operations stli_port_ops = { | 
| 4421 | .carrier_raised = stli_carrier_raised, | 4362 | .carrier_raised = stli_carrier_raised, | 
| 4422 | .dtr_rts = stli_dtr_rts, | 4363 | .dtr_rts = stli_dtr_rts, | 
| 4364 | .activate = stli_activate, | ||
| 4365 | .shutdown = stli_shutdown, | ||
| 4423 | }; | 4366 | }; | 
| 4424 | 4367 | ||
| 4425 | /*****************************************************************************/ | 4368 | /*****************************************************************************/ | 
| diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index dd0083bbb64a..63ee3bbc1ce4 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #include <linux/tty.h> | 34 | #include <linux/tty.h> | 
| 35 | #include <linux/tty_flip.h> | 35 | #include <linux/tty_flip.h> | 
| 36 | #include <linux/major.h> | 36 | #include <linux/major.h> | 
| 37 | #include <linux/smp_lock.h> | ||
| 38 | #include <linux/string.h> | 37 | #include <linux/string.h> | 
| 39 | #include <linux/fcntl.h> | 38 | #include <linux/fcntl.h> | 
| 40 | #include <linux/ptrace.h> | 39 | #include <linux/ptrace.h> | 
| @@ -139,7 +138,7 @@ struct moxa_port { | |||
| 139 | int cflag; | 138 | int cflag; | 
| 140 | unsigned long statusflags; | 139 | unsigned long statusflags; | 
| 141 | 140 | ||
| 142 | u8 DCDState; | 141 | u8 DCDState; /* Protected by the port lock */ | 
| 143 | u8 lineCtrl; | 142 | u8 lineCtrl; | 
| 144 | u8 lowChkFlag; | 143 | u8 lowChkFlag; | 
| 145 | }; | 144 | }; | 
| @@ -151,10 +150,9 @@ struct mon_str { | |||
| 151 | }; | 150 | }; | 
| 152 | 151 | ||
| 153 | /* statusflags */ | 152 | /* statusflags */ | 
| 154 | #define TXSTOPPED 0x1 | 153 | #define TXSTOPPED 1 | 
| 155 | #define LOWWAIT 0x2 | 154 | #define LOWWAIT 2 | 
| 156 | #define EMPTYWAIT 0x4 | 155 | #define EMPTYWAIT 3 | 
| 157 | #define THROTTLE 0x8 | ||
| 158 | 156 | ||
| 159 | #define SERIAL_DO_RESTART | 157 | #define SERIAL_DO_RESTART | 
| 160 | 158 | ||
| @@ -165,6 +163,7 @@ static struct mon_str moxaLog; | |||
| 165 | static unsigned int moxaFuncTout = HZ / 2; | 163 | static unsigned int moxaFuncTout = HZ / 2; | 
| 166 | static unsigned int moxaLowWaterChk; | 164 | static unsigned int moxaLowWaterChk; | 
| 167 | static DEFINE_MUTEX(moxa_openlock); | 165 | static DEFINE_MUTEX(moxa_openlock); | 
| 166 | static DEFINE_SPINLOCK(moxa_lock); | ||
| 168 | /* Variables for insmod */ | 167 | /* Variables for insmod */ | 
| 169 | #ifdef MODULE | 168 | #ifdef MODULE | 
| 170 | static unsigned long baseaddr[MAX_BOARDS]; | 169 | static unsigned long baseaddr[MAX_BOARDS]; | 
| @@ -194,8 +193,6 @@ static int moxa_write(struct tty_struct *, const unsigned char *, int); | |||
| 194 | static int moxa_write_room(struct tty_struct *); | 193 | static int moxa_write_room(struct tty_struct *); | 
| 195 | static void moxa_flush_buffer(struct tty_struct *); | 194 | static void moxa_flush_buffer(struct tty_struct *); | 
| 196 | static int moxa_chars_in_buffer(struct tty_struct *); | 195 | static int moxa_chars_in_buffer(struct tty_struct *); | 
| 197 | static void moxa_throttle(struct tty_struct *); | ||
| 198 | static void moxa_unthrottle(struct tty_struct *); | ||
| 199 | static void moxa_set_termios(struct tty_struct *, struct ktermios *); | 196 | static void moxa_set_termios(struct tty_struct *, struct ktermios *); | 
| 200 | static void moxa_stop(struct tty_struct *); | 197 | static void moxa_stop(struct tty_struct *); | 
| 201 | static void moxa_start(struct tty_struct *); | 198 | static void moxa_start(struct tty_struct *); | 
| @@ -205,9 +202,9 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file, | |||
| 205 | unsigned int set, unsigned int clear); | 202 | unsigned int set, unsigned int clear); | 
| 206 | static void moxa_poll(unsigned long); | 203 | static void moxa_poll(unsigned long); | 
| 207 | static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); | 204 | static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); | 
| 208 | static void moxa_setup_empty_event(struct tty_struct *); | 205 | static void moxa_shutdown(struct tty_port *); | 
| 209 | static void moxa_shut_down(struct tty_struct *); | ||
| 210 | static int moxa_carrier_raised(struct tty_port *); | 206 | static int moxa_carrier_raised(struct tty_port *); | 
| 207 | static void moxa_dtr_rts(struct tty_port *, int); | ||
| 211 | /* | 208 | /* | 
| 212 | * moxa board interface functions: | 209 | * moxa board interface functions: | 
| 213 | */ | 210 | */ | 
| @@ -234,6 +231,8 @@ static void MoxaSetFifo(struct moxa_port *port, int enable); | |||
| 234 | * I/O functions | 231 | * I/O functions | 
| 235 | */ | 232 | */ | 
| 236 | 233 | ||
| 234 | static DEFINE_SPINLOCK(moxafunc_lock); | ||
| 235 | |||
| 237 | static void moxa_wait_finish(void __iomem *ofsAddr) | 236 | static void moxa_wait_finish(void __iomem *ofsAddr) | 
| 238 | { | 237 | { | 
| 239 | unsigned long end = jiffies + moxaFuncTout; | 238 | unsigned long end = jiffies + moxaFuncTout; | 
| @@ -247,9 +246,25 @@ static void moxa_wait_finish(void __iomem *ofsAddr) | |||
| 247 | 246 | ||
| 248 | static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg) | 247 | static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg) | 
| 249 | { | 248 | { | 
| 249 | unsigned long flags; | ||
| 250 | spin_lock_irqsave(&moxafunc_lock, flags); | ||
| 250 | writew(arg, ofsAddr + FuncArg); | 251 | writew(arg, ofsAddr + FuncArg); | 
| 251 | writew(cmd, ofsAddr + FuncCode); | 252 | writew(cmd, ofsAddr + FuncCode); | 
| 252 | moxa_wait_finish(ofsAddr); | 253 | moxa_wait_finish(ofsAddr); | 
| 254 | spin_unlock_irqrestore(&moxafunc_lock, flags); | ||
| 255 | } | ||
| 256 | |||
| 257 | static int moxafuncret(void __iomem *ofsAddr, u16 cmd, u16 arg) | ||
| 258 | { | ||
| 259 | unsigned long flags; | ||
| 260 | u16 ret; | ||
| 261 | spin_lock_irqsave(&moxafunc_lock, flags); | ||
| 262 | writew(arg, ofsAddr + FuncArg); | ||
| 263 | writew(cmd, ofsAddr + FuncCode); | ||
| 264 | moxa_wait_finish(ofsAddr); | ||
| 265 | ret = readw(ofsAddr + FuncArg); | ||
| 266 | spin_unlock_irqrestore(&moxafunc_lock, flags); | ||
| 267 | return ret; | ||
| 253 | } | 268 | } | 
| 254 | 269 | ||
| 255 | static void moxa_low_water_check(void __iomem *ofsAddr) | 270 | static void moxa_low_water_check(void __iomem *ofsAddr) | 
| @@ -299,22 +314,20 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, | |||
| 299 | struct moxa_port *p; | 314 | struct moxa_port *p; | 
| 300 | unsigned int i, j; | 315 | unsigned int i, j; | 
| 301 | 316 | ||
| 302 | mutex_lock(&moxa_openlock); | ||
| 303 | for (i = 0; i < MAX_BOARDS; i++) { | 317 | for (i = 0; i < MAX_BOARDS; i++) { | 
| 304 | p = moxa_boards[i].ports; | 318 | p = moxa_boards[i].ports; | 
| 305 | for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { | 319 | for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { | 
| 306 | memset(&tmp, 0, sizeof(tmp)); | 320 | memset(&tmp, 0, sizeof(tmp)); | 
| 321 | spin_lock_bh(&moxa_lock); | ||
| 307 | if (moxa_boards[i].ready) { | 322 | if (moxa_boards[i].ready) { | 
| 308 | tmp.inq = MoxaPortRxQueue(p); | 323 | tmp.inq = MoxaPortRxQueue(p); | 
| 309 | tmp.outq = MoxaPortTxQueue(p); | 324 | tmp.outq = MoxaPortTxQueue(p); | 
| 310 | } | 325 | } | 
| 311 | if (copy_to_user(argm, &tmp, sizeof(tmp))) { | 326 | spin_unlock_bh(&moxa_lock); | 
| 312 | mutex_unlock(&moxa_openlock); | 327 | if (copy_to_user(argm, &tmp, sizeof(tmp))) | 
| 313 | return -EFAULT; | 328 | return -EFAULT; | 
| 314 | } | ||
| 315 | } | 329 | } | 
| 316 | } | 330 | } | 
| 317 | mutex_unlock(&moxa_openlock); | ||
| 318 | break; | 331 | break; | 
| 319 | } case MOXA_GET_OQUEUE: | 332 | } case MOXA_GET_OQUEUE: | 
| 320 | status = MoxaPortTxQueue(ch); | 333 | status = MoxaPortTxQueue(ch); | 
| @@ -330,16 +343,20 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, | |||
| 330 | struct moxa_port *p; | 343 | struct moxa_port *p; | 
| 331 | unsigned int i, j; | 344 | unsigned int i, j; | 
| 332 | 345 | ||
| 333 | mutex_lock(&moxa_openlock); | ||
| 334 | for (i = 0; i < MAX_BOARDS; i++) { | 346 | for (i = 0; i < MAX_BOARDS; i++) { | 
| 335 | p = moxa_boards[i].ports; | 347 | p = moxa_boards[i].ports; | 
| 336 | for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { | 348 | for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { | 
| 337 | struct tty_struct *ttyp; | 349 | struct tty_struct *ttyp; | 
| 338 | memset(&tmp, 0, sizeof(tmp)); | 350 | memset(&tmp, 0, sizeof(tmp)); | 
| 339 | if (!moxa_boards[i].ready) | 351 | spin_lock_bh(&moxa_lock); | 
| 352 | if (!moxa_boards[i].ready) { | ||
| 353 | spin_unlock_bh(&moxa_lock); | ||
| 340 | goto copy; | 354 | goto copy; | 
| 355 | } | ||
| 341 | 356 | ||
| 342 | status = MoxaPortLineStatus(p); | 357 | status = MoxaPortLineStatus(p); | 
| 358 | spin_unlock_bh(&moxa_lock); | ||
| 359 | |||
| 343 | if (status & 1) | 360 | if (status & 1) | 
| 344 | tmp.cts = 1; | 361 | tmp.cts = 1; | 
| 345 | if (status & 2) | 362 | if (status & 2) | 
| @@ -354,24 +371,21 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, | |||
| 354 | tmp.cflag = ttyp->termios->c_cflag; | 371 | tmp.cflag = ttyp->termios->c_cflag; | 
| 355 | tty_kref_put(tty); | 372 | tty_kref_put(tty); | 
| 356 | copy: | 373 | copy: | 
| 357 | if (copy_to_user(argm, &tmp, sizeof(tmp))) { | 374 | if (copy_to_user(argm, &tmp, sizeof(tmp))) | 
| 358 | mutex_unlock(&moxa_openlock); | ||
| 359 | return -EFAULT; | 375 | return -EFAULT; | 
| 360 | } | ||
| 361 | } | 376 | } | 
| 362 | } | 377 | } | 
| 363 | mutex_unlock(&moxa_openlock); | ||
| 364 | break; | 378 | break; | 
| 365 | } | 379 | } | 
| 366 | case TIOCGSERIAL: | 380 | case TIOCGSERIAL: | 
| 367 | mutex_lock(&moxa_openlock); | 381 | mutex_lock(&ch->port.mutex); | 
| 368 | ret = moxa_get_serial_info(ch, argp); | 382 | ret = moxa_get_serial_info(ch, argp); | 
| 369 | mutex_unlock(&moxa_openlock); | 383 | mutex_unlock(&ch->port.mutex); | 
| 370 | break; | 384 | break; | 
| 371 | case TIOCSSERIAL: | 385 | case TIOCSSERIAL: | 
| 372 | mutex_lock(&moxa_openlock); | 386 | mutex_lock(&ch->port.mutex); | 
| 373 | ret = moxa_set_serial_info(ch, argp); | 387 | ret = moxa_set_serial_info(ch, argp); | 
| 374 | mutex_unlock(&moxa_openlock); | 388 | mutex_unlock(&ch->port.mutex); | 
| 375 | break; | 389 | break; | 
| 376 | default: | 390 | default: | 
| 377 | ret = -ENOIOCTLCMD; | 391 | ret = -ENOIOCTLCMD; | 
| @@ -396,8 +410,6 @@ static const struct tty_operations moxa_ops = { | |||
| 396 | .flush_buffer = moxa_flush_buffer, | 410 | .flush_buffer = moxa_flush_buffer, | 
| 397 | .chars_in_buffer = moxa_chars_in_buffer, | 411 | .chars_in_buffer = moxa_chars_in_buffer, | 
| 398 | .ioctl = moxa_ioctl, | 412 | .ioctl = moxa_ioctl, | 
| 399 | .throttle = moxa_throttle, | ||
| 400 | .unthrottle = moxa_unthrottle, | ||
| 401 | .set_termios = moxa_set_termios, | 413 | .set_termios = moxa_set_termios, | 
| 402 | .stop = moxa_stop, | 414 | .stop = moxa_stop, | 
| 403 | .start = moxa_start, | 415 | .start = moxa_start, | 
| @@ -409,11 +421,12 @@ static const struct tty_operations moxa_ops = { | |||
| 409 | 421 | ||
| 410 | static const struct tty_port_operations moxa_port_ops = { | 422 | static const struct tty_port_operations moxa_port_ops = { | 
| 411 | .carrier_raised = moxa_carrier_raised, | 423 | .carrier_raised = moxa_carrier_raised, | 
| 424 | .dtr_rts = moxa_dtr_rts, | ||
| 425 | .shutdown = moxa_shutdown, | ||
| 412 | }; | 426 | }; | 
| 413 | 427 | ||
| 414 | static struct tty_driver *moxaDriver; | 428 | static struct tty_driver *moxaDriver; | 
| 415 | static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); | 429 | static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); | 
| 416 | static DEFINE_SPINLOCK(moxa_lock); | ||
| 417 | 430 | ||
| 418 | /* | 431 | /* | 
| 419 | * HW init | 432 | * HW init | 
| @@ -1112,14 +1125,12 @@ static void __exit moxa_exit(void) | |||
| 1112 | module_init(moxa_init); | 1125 | module_init(moxa_init); | 
| 1113 | module_exit(moxa_exit); | 1126 | module_exit(moxa_exit); | 
| 1114 | 1127 | ||
| 1115 | static void moxa_close_port(struct tty_struct *tty) | 1128 | static void moxa_shutdown(struct tty_port *port) | 
| 1116 | { | 1129 | { | 
| 1117 | struct moxa_port *ch = tty->driver_data; | 1130 | struct moxa_port *ch = container_of(port, struct moxa_port, port); | 
| 1118 | moxa_shut_down(tty); | 1131 | MoxaPortDisable(ch); | 
| 1119 | MoxaPortFlushData(ch, 2); | 1132 | MoxaPortFlushData(ch, 2); | 
| 1120 | ch->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 1133 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); | 
| 1121 | tty->driver_data = NULL; | ||
| 1122 | tty_port_tty_set(&ch->port, NULL); | ||
| 1123 | } | 1134 | } | 
| 1124 | 1135 | ||
| 1125 | static int moxa_carrier_raised(struct tty_port *port) | 1136 | static int moxa_carrier_raised(struct tty_port *port) | 
| @@ -1127,45 +1138,19 @@ static int moxa_carrier_raised(struct tty_port *port) | |||
| 1127 | struct moxa_port *ch = container_of(port, struct moxa_port, port); | 1138 | struct moxa_port *ch = container_of(port, struct moxa_port, port); | 
| 1128 | int dcd; | 1139 | int dcd; | 
| 1129 | 1140 | ||
| 1130 | spin_lock_bh(&moxa_lock); | 1141 | spin_lock_irq(&port->lock); | 
| 1131 | dcd = ch->DCDState; | 1142 | dcd = ch->DCDState; | 
| 1132 | spin_unlock_bh(&moxa_lock); | 1143 | spin_unlock_irq(&port->lock); | 
| 1133 | return dcd; | 1144 | return dcd; | 
| 1134 | } | 1145 | } | 
| 1135 | 1146 | ||
| 1136 | static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, | 1147 | static void moxa_dtr_rts(struct tty_port *port, int onoff) | 
| 1137 | struct moxa_port *ch) | ||
| 1138 | { | 1148 | { | 
| 1139 | struct tty_port *port = &ch->port; | 1149 | struct moxa_port *ch = container_of(port, struct moxa_port, port); | 
| 1140 | DEFINE_WAIT(wait); | 1150 | MoxaPortLineCtrl(ch, onoff, onoff); | 
| 1141 | int retval = 0; | ||
| 1142 | u8 dcd; | ||
| 1143 | |||
| 1144 | while (1) { | ||
| 1145 | prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE); | ||
| 1146 | if (tty_hung_up_p(filp)) { | ||
| 1147 | #ifdef SERIAL_DO_RESTART | ||
| 1148 | retval = -ERESTARTSYS; | ||
| 1149 | #else | ||
| 1150 | retval = -EAGAIN; | ||
| 1151 | #endif | ||
| 1152 | break; | ||
| 1153 | } | ||
| 1154 | dcd = tty_port_carrier_raised(port); | ||
| 1155 | if (dcd) | ||
| 1156 | break; | ||
| 1157 | |||
| 1158 | if (signal_pending(current)) { | ||
| 1159 | retval = -ERESTARTSYS; | ||
| 1160 | break; | ||
| 1161 | } | ||
| 1162 | schedule(); | ||
| 1163 | } | ||
| 1164 | finish_wait(&port->open_wait, &wait); | ||
| 1165 | |||
| 1166 | return retval; | ||
| 1167 | } | 1151 | } | 
| 1168 | 1152 | ||
| 1153 | |||
| 1169 | static int moxa_open(struct tty_struct *tty, struct file *filp) | 1154 | static int moxa_open(struct tty_struct *tty, struct file *filp) | 
| 1170 | { | 1155 | { | 
| 1171 | struct moxa_board_conf *brd; | 1156 | struct moxa_board_conf *brd; | 
| @@ -1194,6 +1179,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) | |||
| 1194 | ch->port.count++; | 1179 | ch->port.count++; | 
| 1195 | tty->driver_data = ch; | 1180 | tty->driver_data = ch; | 
| 1196 | tty_port_tty_set(&ch->port, tty); | 1181 | tty_port_tty_set(&ch->port, tty); | 
| 1182 | mutex_lock(&ch->port.mutex); | ||
| 1197 | if (!(ch->port.flags & ASYNC_INITIALIZED)) { | 1183 | if (!(ch->port.flags & ASYNC_INITIALIZED)) { | 
| 1198 | ch->statusflags = 0; | 1184 | ch->statusflags = 0; | 
| 1199 | moxa_set_tty_param(tty, tty->termios); | 1185 | moxa_set_tty_param(tty, tty->termios); | 
| @@ -1202,58 +1188,20 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) | |||
| 1202 | MoxaSetFifo(ch, ch->type == PORT_16550A); | 1188 | MoxaSetFifo(ch, ch->type == PORT_16550A); | 
| 1203 | ch->port.flags |= ASYNC_INITIALIZED; | 1189 | ch->port.flags |= ASYNC_INITIALIZED; | 
| 1204 | } | 1190 | } | 
| 1191 | mutex_unlock(&ch->port.mutex); | ||
| 1205 | mutex_unlock(&moxa_openlock); | 1192 | mutex_unlock(&moxa_openlock); | 
| 1206 | 1193 | ||
| 1207 | retval = 0; | 1194 | retval = tty_port_block_til_ready(&ch->port, tty, filp); | 
| 1208 | if (!(filp->f_flags & O_NONBLOCK) && !C_CLOCAL(tty)) | 1195 | if (retval == 0) | 
| 1209 | retval = moxa_block_till_ready(tty, filp, ch); | 1196 | set_bit(ASYNCB_NORMAL_ACTIVE, &ch->port.flags); | 
| 1210 | mutex_lock(&moxa_openlock); | ||
| 1211 | if (retval) { | ||
| 1212 | if (ch->port.count) /* 0 means already hung up... */ | ||
| 1213 | if (--ch->port.count == 0) | ||
| 1214 | moxa_close_port(tty); | ||
| 1215 | } else | ||
| 1216 | ch->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
| 1217 | mutex_unlock(&moxa_openlock); | ||
| 1218 | |||
| 1219 | return retval; | 1197 | return retval; | 
| 1220 | } | 1198 | } | 
| 1221 | 1199 | ||
| 1222 | static void moxa_close(struct tty_struct *tty, struct file *filp) | 1200 | static void moxa_close(struct tty_struct *tty, struct file *filp) | 
| 1223 | { | 1201 | { | 
| 1224 | struct moxa_port *ch; | 1202 | struct moxa_port *ch = tty->driver_data; | 
| 1225 | int port; | ||
| 1226 | |||
| 1227 | port = tty->index; | ||
| 1228 | if (port == MAX_PORTS || tty_hung_up_p(filp)) | ||
| 1229 | return; | ||
| 1230 | |||
| 1231 | mutex_lock(&moxa_openlock); | ||
| 1232 | ch = tty->driver_data; | ||
| 1233 | if (ch == NULL) | ||
| 1234 | goto unlock; | ||
| 1235 | if (tty->count == 1 && ch->port.count != 1) { | ||
| 1236 | printk(KERN_WARNING "moxa_close: bad serial port count; " | ||
| 1237 | "tty->count is 1, ch->port.count is %d\n", ch->port.count); | ||
| 1238 | ch->port.count = 1; | ||
| 1239 | } | ||
| 1240 | if (--ch->port.count < 0) { | ||
| 1241 | printk(KERN_WARNING "moxa_close: bad serial port count, " | ||
| 1242 | "device=%s\n", tty->name); | ||
| 1243 | ch->port.count = 0; | ||
| 1244 | } | ||
| 1245 | if (ch->port.count) | ||
| 1246 | goto unlock; | ||
| 1247 | |||
| 1248 | ch->cflag = tty->termios->c_cflag; | 1203 | ch->cflag = tty->termios->c_cflag; | 
| 1249 | if (ch->port.flags & ASYNC_INITIALIZED) { | 1204 | tty_port_close(&ch->port, tty, filp); | 
| 1250 | moxa_setup_empty_event(tty); | ||
| 1251 | tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */ | ||
| 1252 | } | ||
| 1253 | |||
| 1254 | moxa_close_port(tty); | ||
| 1255 | unlock: | ||
| 1256 | mutex_unlock(&moxa_openlock); | ||
| 1257 | } | 1205 | } | 
| 1258 | 1206 | ||
| 1259 | static int moxa_write(struct tty_struct *tty, | 1207 | static int moxa_write(struct tty_struct *tty, | 
| @@ -1269,7 +1217,7 @@ static int moxa_write(struct tty_struct *tty, | |||
| 1269 | len = MoxaPortWriteData(tty, buf, count); | 1217 | len = MoxaPortWriteData(tty, buf, count); | 
| 1270 | spin_unlock_bh(&moxa_lock); | 1218 | spin_unlock_bh(&moxa_lock); | 
| 1271 | 1219 | ||
| 1272 | ch->statusflags |= LOWWAIT; | 1220 | set_bit(LOWWAIT, &ch->statusflags); | 
| 1273 | return len; | 1221 | return len; | 
| 1274 | } | 1222 | } | 
| 1275 | 1223 | ||
| @@ -1300,40 +1248,21 @@ static int moxa_chars_in_buffer(struct tty_struct *tty) | |||
| 1300 | struct moxa_port *ch = tty->driver_data; | 1248 | struct moxa_port *ch = tty->driver_data; | 
| 1301 | int chars; | 1249 | int chars; | 
| 1302 | 1250 | ||
| 1303 | /* | ||
| 1304 | * Sigh...I have to check if driver_data is NULL here, because | ||
| 1305 | * if an open() fails, the TTY subsystem eventually calls | ||
| 1306 | * tty_wait_until_sent(), which calls the driver's chars_in_buffer() | ||
| 1307 | * routine. And since the open() failed, we return 0 here. TDJ | ||
| 1308 | */ | ||
| 1309 | if (ch == NULL) | ||
| 1310 | return 0; | ||
| 1311 | lock_kernel(); | ||
| 1312 | chars = MoxaPortTxQueue(ch); | 1251 | chars = MoxaPortTxQueue(ch); | 
| 1313 | if (chars) { | 1252 | if (chars) | 
| 1314 | /* | 1253 | /* | 
| 1315 | * Make it possible to wakeup anything waiting for output | 1254 | * Make it possible to wakeup anything waiting for output | 
| 1316 | * in tty_ioctl.c, etc. | 1255 | * in tty_ioctl.c, etc. | 
| 1317 | */ | 1256 | */ | 
| 1318 | if (!(ch->statusflags & EMPTYWAIT)) | 1257 | set_bit(EMPTYWAIT, &ch->statusflags); | 
| 1319 | moxa_setup_empty_event(tty); | ||
| 1320 | } | ||
| 1321 | unlock_kernel(); | ||
| 1322 | return chars; | 1258 | return chars; | 
| 1323 | } | 1259 | } | 
| 1324 | 1260 | ||
| 1325 | static int moxa_tiocmget(struct tty_struct *tty, struct file *file) | 1261 | static int moxa_tiocmget(struct tty_struct *tty, struct file *file) | 
| 1326 | { | 1262 | { | 
| 1327 | struct moxa_port *ch; | 1263 | struct moxa_port *ch = tty->driver_data; | 
| 1328 | int flag = 0, dtr, rts; | 1264 | int flag = 0, dtr, rts; | 
| 1329 | 1265 | ||
| 1330 | mutex_lock(&moxa_openlock); | ||
| 1331 | ch = tty->driver_data; | ||
| 1332 | if (!ch) { | ||
| 1333 | mutex_unlock(&moxa_openlock); | ||
| 1334 | return -EINVAL; | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | MoxaPortGetLineOut(ch, &dtr, &rts); | 1266 | MoxaPortGetLineOut(ch, &dtr, &rts); | 
| 1338 | if (dtr) | 1267 | if (dtr) | 
| 1339 | flag |= TIOCM_DTR; | 1268 | flag |= TIOCM_DTR; | 
| @@ -1346,7 +1275,6 @@ static int moxa_tiocmget(struct tty_struct *tty, struct file *file) | |||
| 1346 | flag |= TIOCM_DSR; | 1275 | flag |= TIOCM_DSR; | 
| 1347 | if (dtr & 4) | 1276 | if (dtr & 4) | 
| 1348 | flag |= TIOCM_CD; | 1277 | flag |= TIOCM_CD; | 
| 1349 | mutex_unlock(&moxa_openlock); | ||
| 1350 | return flag; | 1278 | return flag; | 
| 1351 | } | 1279 | } | 
| 1352 | 1280 | ||
| @@ -1379,20 +1307,6 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file, | |||
| 1379 | return 0; | 1307 | return 0; | 
| 1380 | } | 1308 | } | 
| 1381 | 1309 | ||
| 1382 | static void moxa_throttle(struct tty_struct *tty) | ||
| 1383 | { | ||
| 1384 | struct moxa_port *ch = tty->driver_data; | ||
| 1385 | |||
| 1386 | ch->statusflags |= THROTTLE; | ||
| 1387 | } | ||
| 1388 | |||
| 1389 | static void moxa_unthrottle(struct tty_struct *tty) | ||
| 1390 | { | ||
| 1391 | struct moxa_port *ch = tty->driver_data; | ||
| 1392 | |||
| 1393 | ch->statusflags &= ~THROTTLE; | ||
| 1394 | } | ||
| 1395 | |||
| 1396 | static void moxa_set_termios(struct tty_struct *tty, | 1310 | static void moxa_set_termios(struct tty_struct *tty, | 
| 1397 | struct ktermios *old_termios) | 1311 | struct ktermios *old_termios) | 
| 1398 | { | 1312 | { | 
| @@ -1412,7 +1326,7 @@ static void moxa_stop(struct tty_struct *tty) | |||
| 1412 | if (ch == NULL) | 1326 | if (ch == NULL) | 
| 1413 | return; | 1327 | return; | 
| 1414 | MoxaPortTxDisable(ch); | 1328 | MoxaPortTxDisable(ch); | 
| 1415 | ch->statusflags |= TXSTOPPED; | 1329 | set_bit(TXSTOPPED, &ch->statusflags); | 
| 1416 | } | 1330 | } | 
| 1417 | 1331 | ||
| 1418 | 1332 | ||
| @@ -1427,38 +1341,32 @@ static void moxa_start(struct tty_struct *tty) | |||
| 1427 | return; | 1341 | return; | 
| 1428 | 1342 | ||
| 1429 | MoxaPortTxEnable(ch); | 1343 | MoxaPortTxEnable(ch); | 
| 1430 | ch->statusflags &= ~TXSTOPPED; | 1344 | clear_bit(TXSTOPPED, &ch->statusflags); | 
| 1431 | } | 1345 | } | 
| 1432 | 1346 | ||
| 1433 | static void moxa_hangup(struct tty_struct *tty) | 1347 | static void moxa_hangup(struct tty_struct *tty) | 
| 1434 | { | 1348 | { | 
| 1435 | struct moxa_port *ch; | 1349 | struct moxa_port *ch = tty->driver_data; | 
| 1436 | 1350 | tty_port_hangup(&ch->port); | |
| 1437 | mutex_lock(&moxa_openlock); | ||
| 1438 | ch = tty->driver_data; | ||
| 1439 | if (ch == NULL) { | ||
| 1440 | mutex_unlock(&moxa_openlock); | ||
| 1441 | return; | ||
| 1442 | } | ||
| 1443 | ch->port.count = 0; | ||
| 1444 | moxa_close_port(tty); | ||
| 1445 | mutex_unlock(&moxa_openlock); | ||
| 1446 | |||
| 1447 | wake_up_interruptible(&ch->port.open_wait); | ||
| 1448 | } | 1351 | } | 
| 1449 | 1352 | ||
| 1450 | static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) | 1353 | static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) | 
| 1451 | { | 1354 | { | 
| 1452 | struct tty_struct *tty; | 1355 | struct tty_struct *tty; | 
| 1356 | unsigned long flags; | ||
| 1453 | dcd = !!dcd; | 1357 | dcd = !!dcd; | 
| 1454 | 1358 | ||
| 1359 | spin_lock_irqsave(&p->port.lock, flags); | ||
| 1455 | if (dcd != p->DCDState) { | 1360 | if (dcd != p->DCDState) { | 
| 1361 | p->DCDState = dcd; | ||
| 1362 | spin_unlock_irqrestore(&p->port.lock, flags); | ||
| 1456 | tty = tty_port_tty_get(&p->port); | 1363 | tty = tty_port_tty_get(&p->port); | 
| 1457 | if (tty && C_CLOCAL(tty) && !dcd) | 1364 | if (tty && C_CLOCAL(tty) && !dcd) | 
| 1458 | tty_hangup(tty); | 1365 | tty_hangup(tty); | 
| 1459 | tty_kref_put(tty); | 1366 | tty_kref_put(tty); | 
| 1460 | } | 1367 | } | 
| 1461 | p->DCDState = dcd; | 1368 | else | 
| 1369 | spin_unlock_irqrestore(&p->port.lock, flags); | ||
| 1462 | } | 1370 | } | 
| 1463 | 1371 | ||
| 1464 | static int moxa_poll_port(struct moxa_port *p, unsigned int handle, | 1372 | static int moxa_poll_port(struct moxa_port *p, unsigned int handle, | 
| @@ -1470,24 +1378,24 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle, | |||
| 1470 | u16 intr; | 1378 | u16 intr; | 
| 1471 | 1379 | ||
| 1472 | if (tty) { | 1380 | if (tty) { | 
| 1473 | if ((p->statusflags & EMPTYWAIT) && | 1381 | if (test_bit(EMPTYWAIT, &p->statusflags) && | 
| 1474 | MoxaPortTxQueue(p) == 0) { | 1382 | MoxaPortTxQueue(p) == 0) { | 
| 1475 | p->statusflags &= ~EMPTYWAIT; | 1383 | clear_bit(EMPTYWAIT, &p->statusflags); | 
| 1476 | tty_wakeup(tty); | 1384 | tty_wakeup(tty); | 
| 1477 | } | 1385 | } | 
| 1478 | if ((p->statusflags & LOWWAIT) && !tty->stopped && | 1386 | if (test_bit(LOWWAIT, &p->statusflags) && !tty->stopped && | 
| 1479 | MoxaPortTxQueue(p) <= WAKEUP_CHARS) { | 1387 | MoxaPortTxQueue(p) <= WAKEUP_CHARS) { | 
| 1480 | p->statusflags &= ~LOWWAIT; | 1388 | clear_bit(LOWWAIT, &p->statusflags); | 
| 1481 | tty_wakeup(tty); | 1389 | tty_wakeup(tty); | 
| 1482 | } | 1390 | } | 
| 1483 | 1391 | ||
| 1484 | if (inited && !(p->statusflags & THROTTLE) && | 1392 | if (inited && !test_bit(TTY_THROTTLED, &tty->flags) && | 
| 1485 | MoxaPortRxQueue(p) > 0) { /* RX */ | 1393 | MoxaPortRxQueue(p) > 0) { /* RX */ | 
| 1486 | MoxaPortReadData(p); | 1394 | MoxaPortReadData(p); | 
| 1487 | tty_schedule_flip(tty); | 1395 | tty_schedule_flip(tty); | 
| 1488 | } | 1396 | } | 
| 1489 | } else { | 1397 | } else { | 
| 1490 | p->statusflags &= ~EMPTYWAIT; | 1398 | clear_bit(EMPTYWAIT, &p->statusflags); | 
| 1491 | MoxaPortFlushData(p, 0); /* flush RX */ | 1399 | MoxaPortFlushData(p, 0); /* flush RX */ | 
| 1492 | } | 1400 | } | 
| 1493 | 1401 | ||
| @@ -1588,35 +1496,6 @@ static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_term | |||
| 1588 | tty_encode_baud_rate(tty, baud, baud); | 1496 | tty_encode_baud_rate(tty, baud, baud); | 
| 1589 | } | 1497 | } | 
| 1590 | 1498 | ||
| 1591 | static void moxa_setup_empty_event(struct tty_struct *tty) | ||
| 1592 | { | ||
| 1593 | struct moxa_port *ch = tty->driver_data; | ||
| 1594 | |||
| 1595 | spin_lock_bh(&moxa_lock); | ||
| 1596 | ch->statusflags |= EMPTYWAIT; | ||
| 1597 | spin_unlock_bh(&moxa_lock); | ||
| 1598 | } | ||
| 1599 | |||
| 1600 | static void moxa_shut_down(struct tty_struct *tty) | ||
| 1601 | { | ||
| 1602 | struct moxa_port *ch = tty->driver_data; | ||
| 1603 | |||
| 1604 | if (!(ch->port.flags & ASYNC_INITIALIZED)) | ||
| 1605 | return; | ||
| 1606 | |||
| 1607 | MoxaPortDisable(ch); | ||
| 1608 | |||
| 1609 | /* | ||
| 1610 | * If we're a modem control device and HUPCL is on, drop RTS & DTR. | ||
| 1611 | */ | ||
| 1612 | if (C_HUPCL(tty)) | ||
| 1613 | MoxaPortLineCtrl(ch, 0, 0); | ||
| 1614 | |||
| 1615 | spin_lock_bh(&moxa_lock); | ||
| 1616 | ch->port.flags &= ~ASYNC_INITIALIZED; | ||
| 1617 | spin_unlock_bh(&moxa_lock); | ||
| 1618 | } | ||
| 1619 | |||
| 1620 | /***************************************************************************** | 1499 | /***************************************************************************** | 
| 1621 | * Driver level functions: * | 1500 | * Driver level functions: * | 
| 1622 | *****************************************************************************/ | 1501 | *****************************************************************************/ | 
| @@ -1918,10 +1797,12 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio, | |||
| 1918 | baud = MoxaPortSetBaud(port, baud); | 1797 | baud = MoxaPortSetBaud(port, baud); | 
| 1919 | 1798 | ||
| 1920 | if (termio->c_iflag & (IXON | IXOFF | IXANY)) { | 1799 | if (termio->c_iflag & (IXON | IXOFF | IXANY)) { | 
| 1800 | spin_lock_irq(&moxafunc_lock); | ||
| 1921 | writeb(termio->c_cc[VSTART], ofsAddr + FuncArg); | 1801 | writeb(termio->c_cc[VSTART], ofsAddr + FuncArg); | 
| 1922 | writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1); | 1802 | writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1); | 
| 1923 | writeb(FC_SetXonXoff, ofsAddr + FuncCode); | 1803 | writeb(FC_SetXonXoff, ofsAddr + FuncCode); | 
| 1924 | moxa_wait_finish(ofsAddr); | 1804 | moxa_wait_finish(ofsAddr); | 
| 1805 | spin_unlock_irq(&moxafunc_lock); | ||
| 1925 | 1806 | ||
| 1926 | } | 1807 | } | 
| 1927 | return baud; | 1808 | return baud; | 
| @@ -1974,18 +1855,14 @@ static int MoxaPortLineStatus(struct moxa_port *port) | |||
| 1974 | int val; | 1855 | int val; | 
| 1975 | 1856 | ||
| 1976 | ofsAddr = port->tableAddr; | 1857 | ofsAddr = port->tableAddr; | 
| 1977 | if (MOXA_IS_320(port->board)) { | 1858 | if (MOXA_IS_320(port->board)) | 
| 1978 | moxafunc(ofsAddr, FC_LineStatus, 0); | 1859 | val = moxafuncret(ofsAddr, FC_LineStatus, 0); | 
| 1979 | val = readw(ofsAddr + FuncArg); | 1860 | else | 
| 1980 | } else { | ||
| 1981 | val = readw(ofsAddr + FlagStat) >> 4; | 1861 | val = readw(ofsAddr + FlagStat) >> 4; | 
| 1982 | } | ||
| 1983 | val &= 0x0B; | 1862 | val &= 0x0B; | 
| 1984 | if (val & 8) | 1863 | if (val & 8) | 
| 1985 | val |= 4; | 1864 | val |= 4; | 
| 1986 | spin_lock_bh(&moxa_lock); | ||
| 1987 | moxa_new_dcdstate(port, val & 8); | 1865 | moxa_new_dcdstate(port, val & 8); | 
| 1988 | spin_unlock_bh(&moxa_lock); | ||
| 1989 | val &= 7; | 1866 | val &= 7; | 
| 1990 | return val; | 1867 | return val; | 
| 1991 | } | 1868 | } | 
| diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 5e28d39b9e81..3d923065d9a2 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
| @@ -23,7 +23,6 @@ | |||
| 23 | #include <linux/errno.h> | 23 | #include <linux/errno.h> | 
| 24 | #include <linux/signal.h> | 24 | #include <linux/signal.h> | 
| 25 | #include <linux/sched.h> | 25 | #include <linux/sched.h> | 
| 26 | #include <linux/smp_lock.h> | ||
| 27 | #include <linux/timer.h> | 26 | #include <linux/timer.h> | 
| 28 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> | 
| 29 | #include <linux/tty.h> | 28 | #include <linux/tty.h> | 
| @@ -856,9 +855,9 @@ static void mxser_check_modem_status(struct tty_struct *tty, | |||
| 856 | } | 855 | } | 
| 857 | } | 856 | } | 
| 858 | 857 | ||
| 859 | static int mxser_startup(struct tty_struct *tty) | 858 | static int mxser_activate(struct tty_port *port, struct tty_struct *tty) | 
| 860 | { | 859 | { | 
| 861 | struct mxser_port *info = tty->driver_data; | 860 | struct mxser_port *info = container_of(port, struct mxser_port, port); | 
| 862 | unsigned long page; | 861 | unsigned long page; | 
| 863 | unsigned long flags; | 862 | unsigned long flags; | 
| 864 | 863 | ||
| @@ -868,22 +867,13 @@ static int mxser_startup(struct tty_struct *tty) | |||
| 868 | 867 | ||
| 869 | spin_lock_irqsave(&info->slock, flags); | 868 | spin_lock_irqsave(&info->slock, flags); | 
| 870 | 869 | ||
| 871 | if (info->port.flags & ASYNC_INITIALIZED) { | ||
| 872 | free_page(page); | ||
| 873 | spin_unlock_irqrestore(&info->slock, flags); | ||
| 874 | return 0; | ||
| 875 | } | ||
| 876 | |||
| 877 | if (!info->ioaddr || !info->type) { | 870 | if (!info->ioaddr || !info->type) { | 
| 878 | set_bit(TTY_IO_ERROR, &tty->flags); | 871 | set_bit(TTY_IO_ERROR, &tty->flags); | 
| 879 | free_page(page); | 872 | free_page(page); | 
| 880 | spin_unlock_irqrestore(&info->slock, flags); | 873 | spin_unlock_irqrestore(&info->slock, flags); | 
| 881 | return 0; | 874 | return 0; | 
| 882 | } | 875 | } | 
| 883 | if (info->port.xmit_buf) | 876 | info->port.xmit_buf = (unsigned char *) page; | 
| 884 | free_page(page); | ||
| 885 | else | ||
| 886 | info->port.xmit_buf = (unsigned char *) page; | ||
| 887 | 877 | ||
| 888 | /* | 878 | /* | 
| 889 | * Clear the FIFO buffers and disable them | 879 | * Clear the FIFO buffers and disable them | 
| @@ -951,24 +941,19 @@ static int mxser_startup(struct tty_struct *tty) | |||
| 951 | * and set the speed of the serial port | 941 | * and set the speed of the serial port | 
| 952 | */ | 942 | */ | 
| 953 | mxser_change_speed(tty, NULL); | 943 | mxser_change_speed(tty, NULL); | 
| 954 | info->port.flags |= ASYNC_INITIALIZED; | ||
| 955 | spin_unlock_irqrestore(&info->slock, flags); | 944 | spin_unlock_irqrestore(&info->slock, flags); | 
| 956 | 945 | ||
| 957 | return 0; | 946 | return 0; | 
| 958 | } | 947 | } | 
| 959 | 948 | ||
| 960 | /* | 949 | /* | 
| 961 | * This routine will shutdown a serial port; interrupts maybe disabled, and | 950 | * This routine will shutdown a serial port | 
| 962 | * DTR is dropped if the hangup on close termio flag is on. | ||
| 963 | */ | 951 | */ | 
| 964 | static void mxser_shutdown(struct tty_struct *tty) | 952 | static void mxser_shutdown_port(struct tty_port *port) | 
| 965 | { | 953 | { | 
| 966 | struct mxser_port *info = tty->driver_data; | 954 | struct mxser_port *info = container_of(port, struct mxser_port, port); | 
| 967 | unsigned long flags; | 955 | unsigned long flags; | 
| 968 | 956 | ||
| 969 | if (!(info->port.flags & ASYNC_INITIALIZED)) | ||
| 970 | return; | ||
| 971 | |||
| 972 | spin_lock_irqsave(&info->slock, flags); | 957 | spin_lock_irqsave(&info->slock, flags); | 
| 973 | 958 | ||
| 974 | /* | 959 | /* | 
| @@ -978,7 +963,7 @@ static void mxser_shutdown(struct tty_struct *tty) | |||
| 978 | wake_up_interruptible(&info->port.delta_msr_wait); | 963 | wake_up_interruptible(&info->port.delta_msr_wait); | 
| 979 | 964 | ||
| 980 | /* | 965 | /* | 
| 981 | * Free the IRQ, if necessary | 966 | * Free the xmit buffer, if necessary | 
| 982 | */ | 967 | */ | 
| 983 | if (info->port.xmit_buf) { | 968 | if (info->port.xmit_buf) { | 
| 984 | free_page((unsigned long) info->port.xmit_buf); | 969 | free_page((unsigned long) info->port.xmit_buf); | 
| @@ -988,10 +973,6 @@ static void mxser_shutdown(struct tty_struct *tty) | |||
| 988 | info->IER = 0; | 973 | info->IER = 0; | 
| 989 | outb(0x00, info->ioaddr + UART_IER); | 974 | outb(0x00, info->ioaddr + UART_IER); | 
| 990 | 975 | ||
| 991 | if (tty->termios->c_cflag & HUPCL) | ||
| 992 | info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS); | ||
| 993 | outb(info->MCR, info->ioaddr + UART_MCR); | ||
| 994 | |||
| 995 | /* clear Rx/Tx FIFO's */ | 976 | /* clear Rx/Tx FIFO's */ | 
| 996 | if (info->board->chip_flag) | 977 | if (info->board->chip_flag) | 
| 997 | outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | | 978 | outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | | 
| @@ -1004,9 +985,6 @@ static void mxser_shutdown(struct tty_struct *tty) | |||
| 1004 | /* read data port to reset things */ | 985 | /* read data port to reset things */ | 
| 1005 | (void) inb(info->ioaddr + UART_RX); | 986 | (void) inb(info->ioaddr + UART_RX); | 
| 1006 | 987 | ||
| 1007 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
| 1008 | |||
| 1009 | info->port.flags &= ~ASYNC_INITIALIZED; | ||
| 1010 | 988 | ||
| 1011 | if (info->board->chip_flag) | 989 | if (info->board->chip_flag) | 
| 1012 | SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr); | 990 | SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr); | 
| @@ -1023,8 +1001,7 @@ static void mxser_shutdown(struct tty_struct *tty) | |||
| 1023 | static int mxser_open(struct tty_struct *tty, struct file *filp) | 1001 | static int mxser_open(struct tty_struct *tty, struct file *filp) | 
| 1024 | { | 1002 | { | 
| 1025 | struct mxser_port *info; | 1003 | struct mxser_port *info; | 
| 1026 | unsigned long flags; | 1004 | int line; | 
| 1027 | int retval, line; | ||
| 1028 | 1005 | ||
| 1029 | line = tty->index; | 1006 | line = tty->index; | 
| 1030 | if (line == MXSER_PORTS) | 1007 | if (line == MXSER_PORTS) | 
| @@ -1035,23 +1012,7 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) | |||
| 1035 | if (!info->ioaddr) | 1012 | if (!info->ioaddr) | 
| 1036 | return -ENODEV; | 1013 | return -ENODEV; | 
| 1037 | 1014 | ||
| 1038 | tty->driver_data = info; | 1015 | return tty_port_open(&info->port, tty, filp); | 
| 1039 | tty_port_tty_set(&info->port, tty); | ||
| 1040 | /* | ||
| 1041 | * Start up serial port | ||
| 1042 | */ | ||
| 1043 | spin_lock_irqsave(&info->port.lock, flags); | ||
| 1044 | info->port.count++; | ||
| 1045 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
| 1046 | retval = mxser_startup(tty); | ||
| 1047 | if (retval) | ||
| 1048 | return retval; | ||
| 1049 | |||
| 1050 | retval = tty_port_block_til_ready(&info->port, tty, filp); | ||
| 1051 | if (retval) | ||
| 1052 | return retval; | ||
| 1053 | |||
| 1054 | return 0; | ||
| 1055 | } | 1016 | } | 
| 1056 | 1017 | ||
| 1057 | static void mxser_flush_buffer(struct tty_struct *tty) | 1018 | static void mxser_flush_buffer(struct tty_struct *tty) | 
| @@ -1075,19 +1036,11 @@ static void mxser_flush_buffer(struct tty_struct *tty) | |||
| 1075 | } | 1036 | } | 
| 1076 | 1037 | ||
| 1077 | 1038 | ||
| 1078 | static void mxser_close_port(struct tty_struct *tty, struct tty_port *port) | 1039 | static void mxser_close_port(struct tty_port *port) | 
| 1079 | { | 1040 | { | 
| 1080 | struct mxser_port *info = container_of(port, struct mxser_port, port); | 1041 | struct mxser_port *info = container_of(port, struct mxser_port, port); | 
| 1081 | unsigned long timeout; | 1042 | unsigned long timeout; | 
| 1082 | /* | 1043 | /* | 
| 1083 | * Save the termios structure, since this port may have | ||
| 1084 | * separate termios for callout and dialin. | ||
| 1085 | * | ||
| 1086 | * FIXME: Can this go ? | ||
| 1087 | */ | ||
| 1088 | if (port->flags & ASYNC_NORMAL_ACTIVE) | ||
| 1089 | info->normal_termios = *tty->termios; | ||
| 1090 | /* | ||
| 1091 | * At this point we stop accepting input. To do this, we | 1044 | * At this point we stop accepting input. To do this, we | 
| 1092 | * disable the receive line status interrupts, and tell the | 1045 | * disable the receive line status interrupts, and tell the | 
| 1093 | * interrupt driver to stop checking the data ready bit in the | 1046 | * interrupt driver to stop checking the data ready bit in the | 
| @@ -1097,22 +1050,18 @@ static void mxser_close_port(struct tty_struct *tty, struct tty_port *port) | |||
| 1097 | if (info->board->chip_flag) | 1050 | if (info->board->chip_flag) | 
| 1098 | info->IER &= ~MOXA_MUST_RECV_ISR; | 1051 | info->IER &= ~MOXA_MUST_RECV_ISR; | 
| 1099 | 1052 | ||
| 1100 | if (port->flags & ASYNC_INITIALIZED) { | 1053 | outb(info->IER, info->ioaddr + UART_IER); | 
| 1101 | outb(info->IER, info->ioaddr + UART_IER); | 1054 | /* | 
| 1102 | /* | 1055 | * Before we drop DTR, make sure the UART transmitter | 
| 1103 | * Before we drop DTR, make sure the UART transmitter | 1056 | * has completely drained; this is especially | 
| 1104 | * has completely drained; this is especially | 1057 | * important if there is a transmit FIFO! | 
| 1105 | * important if there is a transmit FIFO! | 1058 | */ | 
| 1106 | */ | 1059 | timeout = jiffies + HZ; | 
| 1107 | timeout = jiffies + HZ; | 1060 | while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) { | 
| 1108 | while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) { | 1061 | schedule_timeout_interruptible(5); | 
| 1109 | schedule_timeout_interruptible(5); | 1062 | if (time_after(jiffies, timeout)) | 
| 1110 | if (time_after(jiffies, timeout)) | 1063 | break; | 
| 1111 | break; | ||
| 1112 | } | ||
| 1113 | } | 1064 | } | 
| 1114 | mxser_shutdown(tty); | ||
| 1115 | |||
| 1116 | } | 1065 | } | 
| 1117 | 1066 | ||
| 1118 | /* | 1067 | /* | 
| @@ -1130,8 +1079,12 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) | |||
| 1130 | return; | 1079 | return; | 
| 1131 | if (tty_port_close_start(port, tty, filp) == 0) | 1080 | if (tty_port_close_start(port, tty, filp) == 0) | 
| 1132 | return; | 1081 | return; | 
| 1133 | mxser_close_port(tty, port); | 1082 | mutex_lock(&port->mutex); | 
| 1083 | mxser_close_port(port); | ||
| 1134 | mxser_flush_buffer(tty); | 1084 | mxser_flush_buffer(tty); | 
| 1085 | mxser_shutdown_port(port); | ||
| 1086 | clear_bit(ASYNCB_INITIALIZED, &port->flags); | ||
| 1087 | mutex_unlock(&port->mutex); | ||
| 1135 | /* Right now the tty_port set is done outside of the close_end helper | 1088 | /* Right now the tty_port set is done outside of the close_end helper | 
| 1136 | as we don't yet have everyone using refcounts */ | 1089 | as we don't yet have everyone using refcounts */ | 
| 1137 | tty_port_close_end(port, tty); | 1090 | tty_port_close_end(port, tty); | 
| @@ -1275,6 +1228,7 @@ static int mxser_set_serial_info(struct tty_struct *tty, | |||
| 1275 | struct serial_struct __user *new_info) | 1228 | struct serial_struct __user *new_info) | 
| 1276 | { | 1229 | { | 
| 1277 | struct mxser_port *info = tty->driver_data; | 1230 | struct mxser_port *info = tty->driver_data; | 
| 1231 | struct tty_port *port = &info->port; | ||
| 1278 | struct serial_struct new_serial; | 1232 | struct serial_struct new_serial; | 
| 1279 | speed_t baud; | 1233 | speed_t baud; | 
| 1280 | unsigned long sl_flags; | 1234 | unsigned long sl_flags; | 
| @@ -1290,7 +1244,7 @@ static int mxser_set_serial_info(struct tty_struct *tty, | |||
| 1290 | new_serial.port != info->ioaddr) | 1244 | new_serial.port != info->ioaddr) | 
| 1291 | return -EINVAL; | 1245 | return -EINVAL; | 
| 1292 | 1246 | ||
| 1293 | flags = info->port.flags & ASYNC_SPD_MASK; | 1247 | flags = port->flags & ASYNC_SPD_MASK; | 
| 1294 | 1248 | ||
| 1295 | if (!capable(CAP_SYS_ADMIN)) { | 1249 | if (!capable(CAP_SYS_ADMIN)) { | 
| 1296 | if ((new_serial.baud_base != info->baud_base) || | 1250 | if ((new_serial.baud_base != info->baud_base) || | 
| @@ -1304,16 +1258,17 @@ static int mxser_set_serial_info(struct tty_struct *tty, | |||
| 1304 | * OK, past this point, all the error checking has been done. | 1258 | * OK, past this point, all the error checking has been done. | 
| 1305 | * At this point, we start making changes..... | 1259 | * At this point, we start making changes..... | 
| 1306 | */ | 1260 | */ | 
| 1307 | info->port.flags = ((info->port.flags & ~ASYNC_FLAGS) | | 1261 | port->flags = ((port->flags & ~ASYNC_FLAGS) | | 
| 1308 | (new_serial.flags & ASYNC_FLAGS)); | 1262 | (new_serial.flags & ASYNC_FLAGS)); | 
| 1309 | info->port.close_delay = new_serial.close_delay * HZ / 100; | 1263 | port->close_delay = new_serial.close_delay * HZ / 100; | 
| 1310 | info->port.closing_wait = new_serial.closing_wait * HZ / 100; | 1264 | port->closing_wait = new_serial.closing_wait * HZ / 100; | 
| 1311 | tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) | 1265 | tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 
| 1312 | ? 1 : 0; | 1266 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && | 
| 1313 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && | ||
| 1314 | (new_serial.baud_base != info->baud_base || | 1267 | (new_serial.baud_base != info->baud_base || | 
| 1315 | new_serial.custom_divisor != | 1268 | new_serial.custom_divisor != | 
| 1316 | info->custom_divisor)) { | 1269 | info->custom_divisor)) { | 
| 1270 | if (new_serial.custom_divisor == 0) | ||
| 1271 | return -EINVAL; | ||
| 1317 | baud = new_serial.baud_base / new_serial.custom_divisor; | 1272 | baud = new_serial.baud_base / new_serial.custom_divisor; | 
| 1318 | tty_encode_baud_rate(tty, baud, baud); | 1273 | tty_encode_baud_rate(tty, baud, baud); | 
| 1319 | } | 1274 | } | 
| @@ -1323,15 +1278,17 @@ static int mxser_set_serial_info(struct tty_struct *tty, | |||
| 1323 | 1278 | ||
| 1324 | process_txrx_fifo(info); | 1279 | process_txrx_fifo(info); | 
| 1325 | 1280 | ||
| 1326 | if (info->port.flags & ASYNC_INITIALIZED) { | 1281 | if (test_bit(ASYNCB_INITIALIZED, &port->flags)) { | 
| 1327 | if (flags != (info->port.flags & ASYNC_SPD_MASK)) { | 1282 | if (flags != (port->flags & ASYNC_SPD_MASK)) { | 
| 1328 | spin_lock_irqsave(&info->slock, sl_flags); | 1283 | spin_lock_irqsave(&info->slock, sl_flags); | 
| 1329 | mxser_change_speed(tty, NULL); | 1284 | mxser_change_speed(tty, NULL); | 
| 1330 | spin_unlock_irqrestore(&info->slock, sl_flags); | 1285 | spin_unlock_irqrestore(&info->slock, sl_flags); | 
| 1331 | } | 1286 | } | 
| 1332 | } else | 1287 | } else { | 
| 1333 | retval = mxser_startup(tty); | 1288 | retval = mxser_activate(port, tty); | 
| 1334 | 1289 | if (retval == 0) | |
| 1290 | set_bit(ASYNCB_INITIALIZED, &port->flags); | ||
| 1291 | } | ||
| 1335 | return retval; | 1292 | return retval; | 
| 1336 | } | 1293 | } | 
| 1337 | 1294 | ||
| @@ -1520,7 +1477,8 @@ static int __init mxser_read_register(int port, unsigned short *regs) | |||
| 1520 | 1477 | ||
| 1521 | static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | 1478 | static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | 
| 1522 | { | 1479 | { | 
| 1523 | struct mxser_port *port; | 1480 | struct mxser_port *ip; | 
| 1481 | struct tty_port *port; | ||
| 1524 | struct tty_struct *tty; | 1482 | struct tty_struct *tty; | 
| 1525 | int result, status; | 1483 | int result, status; | 
| 1526 | unsigned int i, j; | 1484 | unsigned int i, j; | 
| @@ -1536,38 +1494,39 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
| 1536 | 1494 | ||
| 1537 | case MOXA_CHKPORTENABLE: | 1495 | case MOXA_CHKPORTENABLE: | 
| 1538 | result = 0; | 1496 | result = 0; | 
| 1539 | lock_kernel(); | ||
| 1540 | for (i = 0; i < MXSER_BOARDS; i++) | 1497 | for (i = 0; i < MXSER_BOARDS; i++) | 
| 1541 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) | 1498 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) | 
| 1542 | if (mxser_boards[i].ports[j].ioaddr) | 1499 | if (mxser_boards[i].ports[j].ioaddr) | 
| 1543 | result |= (1 << i); | 1500 | result |= (1 << i); | 
| 1544 | unlock_kernel(); | ||
| 1545 | return put_user(result, (unsigned long __user *)argp); | 1501 | return put_user(result, (unsigned long __user *)argp); | 
| 1546 | case MOXA_GETDATACOUNT: | 1502 | case MOXA_GETDATACOUNT: | 
| 1547 | lock_kernel(); | 1503 | /* The receive side is locked by port->slock but it isn't | 
| 1504 | clear that an exact snapshot is worth copying here */ | ||
| 1548 | if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) | 1505 | if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) | 
| 1549 | ret = -EFAULT; | 1506 | ret = -EFAULT; | 
| 1550 | unlock_kernel(); | ||
| 1551 | return ret; | 1507 | return ret; | 
| 1552 | case MOXA_GETMSTATUS: { | 1508 | case MOXA_GETMSTATUS: { | 
| 1553 | struct mxser_mstatus ms, __user *msu = argp; | 1509 | struct mxser_mstatus ms, __user *msu = argp; | 
| 1554 | lock_kernel(); | ||
| 1555 | for (i = 0; i < MXSER_BOARDS; i++) | 1510 | for (i = 0; i < MXSER_BOARDS; i++) | 
| 1556 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { | 1511 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { | 
| 1557 | port = &mxser_boards[i].ports[j]; | 1512 | ip = &mxser_boards[i].ports[j]; | 
| 1513 | port = &ip->port; | ||
| 1558 | memset(&ms, 0, sizeof(ms)); | 1514 | memset(&ms, 0, sizeof(ms)); | 
| 1559 | 1515 | ||
| 1560 | if (!port->ioaddr) | 1516 | mutex_lock(&port->mutex); | 
| 1517 | if (!ip->ioaddr) | ||
| 1561 | goto copy; | 1518 | goto copy; | 
| 1562 | 1519 | ||
| 1563 | tty = tty_port_tty_get(&port->port); | 1520 | tty = tty_port_tty_get(port); | 
| 1564 | 1521 | ||
| 1565 | if (!tty || !tty->termios) | 1522 | if (!tty || !tty->termios) | 
| 1566 | ms.cflag = port->normal_termios.c_cflag; | 1523 | ms.cflag = ip->normal_termios.c_cflag; | 
| 1567 | else | 1524 | else | 
| 1568 | ms.cflag = tty->termios->c_cflag; | 1525 | ms.cflag = tty->termios->c_cflag; | 
| 1569 | tty_kref_put(tty); | 1526 | tty_kref_put(tty); | 
| 1570 | status = inb(port->ioaddr + UART_MSR); | 1527 | spin_lock_irq(&ip->slock); | 
| 1528 | status = inb(ip->ioaddr + UART_MSR); | ||
| 1529 | spin_unlock_irq(&ip->slock); | ||
| 1571 | if (status & UART_MSR_DCD) | 1530 | if (status & UART_MSR_DCD) | 
| 1572 | ms.dcd = 1; | 1531 | ms.dcd = 1; | 
| 1573 | if (status & UART_MSR_DSR) | 1532 | if (status & UART_MSR_DSR) | 
| @@ -1575,13 +1534,11 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
| 1575 | if (status & UART_MSR_CTS) | 1534 | if (status & UART_MSR_CTS) | 
| 1576 | ms.cts = 1; | 1535 | ms.cts = 1; | 
| 1577 | copy: | 1536 | copy: | 
| 1578 | if (copy_to_user(msu, &ms, sizeof(ms))) { | 1537 | mutex_unlock(&port->mutex); | 
| 1579 | unlock_kernel(); | 1538 | if (copy_to_user(msu, &ms, sizeof(ms))) | 
| 1580 | return -EFAULT; | 1539 | return -EFAULT; | 
| 1581 | } | ||
| 1582 | msu++; | 1540 | msu++; | 
| 1583 | } | 1541 | } | 
| 1584 | unlock_kernel(); | ||
| 1585 | return 0; | 1542 | return 0; | 
| 1586 | } | 1543 | } | 
| 1587 | case MOXA_ASPP_MON_EXT: { | 1544 | case MOXA_ASPP_MON_EXT: { | 
| @@ -1593,41 +1550,48 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
| 1593 | if (!me) | 1550 | if (!me) | 
| 1594 | return -ENOMEM; | 1551 | return -ENOMEM; | 
| 1595 | 1552 | ||
| 1596 | lock_kernel(); | ||
| 1597 | for (i = 0, p = 0; i < MXSER_BOARDS; i++) { | 1553 | for (i = 0, p = 0; i < MXSER_BOARDS; i++) { | 
| 1598 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) { | 1554 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) { | 
| 1599 | if (p >= ARRAY_SIZE(me->rx_cnt)) { | 1555 | if (p >= ARRAY_SIZE(me->rx_cnt)) { | 
| 1600 | i = MXSER_BOARDS; | 1556 | i = MXSER_BOARDS; | 
| 1601 | break; | 1557 | break; | 
| 1602 | } | 1558 | } | 
| 1603 | port = &mxser_boards[i].ports[j]; | 1559 | ip = &mxser_boards[i].ports[j]; | 
| 1604 | if (!port->ioaddr) | 1560 | port = &ip->port; | 
| 1561 | |||
| 1562 | mutex_lock(&port->mutex); | ||
| 1563 | if (!ip->ioaddr) { | ||
| 1564 | mutex_unlock(&port->mutex); | ||
| 1605 | continue; | 1565 | continue; | 
| 1566 | } | ||
| 1606 | 1567 | ||
| 1607 | status = mxser_get_msr(port->ioaddr, 0, p); | 1568 | spin_lock_irq(&ip->slock); | 
| 1569 | status = mxser_get_msr(ip->ioaddr, 0, p); | ||
| 1608 | 1570 | ||
| 1609 | if (status & UART_MSR_TERI) | 1571 | if (status & UART_MSR_TERI) | 
| 1610 | port->icount.rng++; | 1572 | ip->icount.rng++; | 
| 1611 | if (status & UART_MSR_DDSR) | 1573 | if (status & UART_MSR_DDSR) | 
| 1612 | port->icount.dsr++; | 1574 | ip->icount.dsr++; | 
| 1613 | if (status & UART_MSR_DDCD) | 1575 | if (status & UART_MSR_DDCD) | 
| 1614 | port->icount.dcd++; | 1576 | ip->icount.dcd++; | 
| 1615 | if (status & UART_MSR_DCTS) | 1577 | if (status & UART_MSR_DCTS) | 
| 1616 | port->icount.cts++; | 1578 | ip->icount.cts++; | 
| 1617 | 1579 | ||
| 1618 | port->mon_data.modem_status = status; | 1580 | ip->mon_data.modem_status = status; | 
| 1619 | me->rx_cnt[p] = port->mon_data.rxcnt; | 1581 | me->rx_cnt[p] = ip->mon_data.rxcnt; | 
| 1620 | me->tx_cnt[p] = port->mon_data.txcnt; | 1582 | me->tx_cnt[p] = ip->mon_data.txcnt; | 
| 1621 | me->up_rxcnt[p] = port->mon_data.up_rxcnt; | 1583 | me->up_rxcnt[p] = ip->mon_data.up_rxcnt; | 
| 1622 | me->up_txcnt[p] = port->mon_data.up_txcnt; | 1584 | me->up_txcnt[p] = ip->mon_data.up_txcnt; | 
| 1623 | me->modem_status[p] = | 1585 | me->modem_status[p] = | 
| 1624 | port->mon_data.modem_status; | 1586 | ip->mon_data.modem_status; | 
| 1625 | tty = tty_port_tty_get(&port->port); | 1587 | spin_unlock_irq(&ip->slock); | 
| 1588 | |||
| 1589 | tty = tty_port_tty_get(&ip->port); | ||
| 1626 | 1590 | ||
| 1627 | if (!tty || !tty->termios) { | 1591 | if (!tty || !tty->termios) { | 
| 1628 | cflag = port->normal_termios.c_cflag; | 1592 | cflag = ip->normal_termios.c_cflag; | 
| 1629 | iflag = port->normal_termios.c_iflag; | 1593 | iflag = ip->normal_termios.c_iflag; | 
| 1630 | me->baudrate[p] = tty_termios_baud_rate(&port->normal_termios); | 1594 | me->baudrate[p] = tty_termios_baud_rate(&ip->normal_termios); | 
| 1631 | } else { | 1595 | } else { | 
| 1632 | cflag = tty->termios->c_cflag; | 1596 | cflag = tty->termios->c_cflag; | 
| 1633 | iflag = tty->termios->c_iflag; | 1597 | iflag = tty->termios->c_iflag; | 
| @@ -1646,16 +1610,15 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
| 1646 | if (iflag & (IXON | IXOFF)) | 1610 | if (iflag & (IXON | IXOFF)) | 
| 1647 | me->flowctrl[p] |= 0x0C; | 1611 | me->flowctrl[p] |= 0x0C; | 
| 1648 | 1612 | ||
| 1649 | if (port->type == PORT_16550A) | 1613 | if (ip->type == PORT_16550A) | 
| 1650 | me->fifo[p] = 1; | 1614 | me->fifo[p] = 1; | 
| 1651 | 1615 | ||
| 1652 | opmode = inb(port->opmode_ioaddr) >> | 1616 | opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2); | 
| 1653 | ((p % 4) * 2); | ||
| 1654 | opmode &= OP_MODE_MASK; | 1617 | opmode &= OP_MODE_MASK; | 
| 1655 | me->iftype[p] = opmode; | 1618 | me->iftype[p] = opmode; | 
| 1619 | mutex_unlock(&port->mutex); | ||
| 1656 | } | 1620 | } | 
| 1657 | } | 1621 | } | 
| 1658 | unlock_kernel(); | ||
| 1659 | if (copy_to_user(argp, me, sizeof(*me))) | 1622 | if (copy_to_user(argp, me, sizeof(*me))) | 
| 1660 | ret = -EFAULT; | 1623 | ret = -EFAULT; | 
| 1661 | kfree(me); | 1624 | kfree(me); | 
| @@ -1692,6 +1655,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
| 1692 | unsigned int cmd, unsigned long arg) | 1655 | unsigned int cmd, unsigned long arg) | 
| 1693 | { | 1656 | { | 
| 1694 | struct mxser_port *info = tty->driver_data; | 1657 | struct mxser_port *info = tty->driver_data; | 
| 1658 | struct tty_port *port = &info->port; | ||
| 1695 | struct async_icount cnow; | 1659 | struct async_icount cnow; | 
| 1696 | unsigned long flags; | 1660 | unsigned long flags; | 
| 1697 | void __user *argp = (void __user *)arg; | 1661 | void __user *argp = (void __user *)arg; | 
| @@ -1716,20 +1680,20 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
| 1716 | opmode != RS422_MODE && | 1680 | opmode != RS422_MODE && | 
| 1717 | opmode != RS485_4WIRE_MODE) | 1681 | opmode != RS485_4WIRE_MODE) | 
| 1718 | return -EFAULT; | 1682 | return -EFAULT; | 
| 1719 | lock_kernel(); | ||
| 1720 | mask = ModeMask[p]; | 1683 | mask = ModeMask[p]; | 
| 1721 | shiftbit = p * 2; | 1684 | shiftbit = p * 2; | 
| 1685 | spin_lock_irq(&info->slock); | ||
| 1722 | val = inb(info->opmode_ioaddr); | 1686 | val = inb(info->opmode_ioaddr); | 
| 1723 | val &= mask; | 1687 | val &= mask; | 
| 1724 | val |= (opmode << shiftbit); | 1688 | val |= (opmode << shiftbit); | 
| 1725 | outb(val, info->opmode_ioaddr); | 1689 | outb(val, info->opmode_ioaddr); | 
| 1726 | unlock_kernel(); | 1690 | spin_unlock_irq(&info->slock); | 
| 1727 | } else { | 1691 | } else { | 
| 1728 | lock_kernel(); | ||
| 1729 | shiftbit = p * 2; | 1692 | shiftbit = p * 2; | 
| 1693 | spin_lock_irq(&info->slock); | ||
| 1730 | opmode = inb(info->opmode_ioaddr) >> shiftbit; | 1694 | opmode = inb(info->opmode_ioaddr) >> shiftbit; | 
| 1695 | spin_unlock_irq(&info->slock); | ||
| 1731 | opmode &= OP_MODE_MASK; | 1696 | opmode &= OP_MODE_MASK; | 
| 1732 | unlock_kernel(); | ||
| 1733 | if (put_user(opmode, (int __user *)argp)) | 1697 | if (put_user(opmode, (int __user *)argp)) | 
| 1734 | return -EFAULT; | 1698 | return -EFAULT; | 
| 1735 | } | 1699 | } | 
| @@ -1742,14 +1706,14 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
| 1742 | 1706 | ||
| 1743 | switch (cmd) { | 1707 | switch (cmd) { | 
| 1744 | case TIOCGSERIAL: | 1708 | case TIOCGSERIAL: | 
| 1745 | lock_kernel(); | 1709 | mutex_lock(&port->mutex); | 
| 1746 | retval = mxser_get_serial_info(tty, argp); | 1710 | retval = mxser_get_serial_info(tty, argp); | 
| 1747 | unlock_kernel(); | 1711 | mutex_unlock(&port->mutex); | 
| 1748 | return retval; | 1712 | return retval; | 
| 1749 | case TIOCSSERIAL: | 1713 | case TIOCSSERIAL: | 
| 1750 | lock_kernel(); | 1714 | mutex_lock(&port->mutex); | 
| 1751 | retval = mxser_set_serial_info(tty, argp); | 1715 | retval = mxser_set_serial_info(tty, argp); | 
| 1752 | unlock_kernel(); | 1716 | mutex_unlock(&port->mutex); | 
| 1753 | return retval; | 1717 | return retval; | 
| 1754 | case TIOCSERGETLSR: /* Get line status register */ | 1718 | case TIOCSERGETLSR: /* Get line status register */ | 
| 1755 | return mxser_get_lsr_info(info, argp); | 1719 | return mxser_get_lsr_info(info, argp); | 
| @@ -1795,31 +1759,33 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
| 1795 | case MOXA_HighSpeedOn: | 1759 | case MOXA_HighSpeedOn: | 
| 1796 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); | 1760 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); | 
| 1797 | case MOXA_SDS_RSTICOUNTER: | 1761 | case MOXA_SDS_RSTICOUNTER: | 
| 1798 | lock_kernel(); | 1762 | spin_lock_irq(&info->slock); | 
| 1799 | info->mon_data.rxcnt = 0; | 1763 | info->mon_data.rxcnt = 0; | 
| 1800 | info->mon_data.txcnt = 0; | 1764 | info->mon_data.txcnt = 0; | 
| 1801 | unlock_kernel(); | 1765 | spin_unlock_irq(&info->slock); | 
| 1802 | return 0; | 1766 | return 0; | 
| 1803 | 1767 | ||
| 1804 | case MOXA_ASPP_OQUEUE:{ | 1768 | case MOXA_ASPP_OQUEUE:{ | 
| 1805 | int len, lsr; | 1769 | int len, lsr; | 
| 1806 | 1770 | ||
| 1807 | lock_kernel(); | ||
| 1808 | len = mxser_chars_in_buffer(tty); | 1771 | len = mxser_chars_in_buffer(tty); | 
| 1772 | spin_lock(&info->slock); | ||
| 1809 | lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE; | 1773 | lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE; | 
| 1774 | spin_unlock_irq(&info->slock); | ||
| 1810 | len += (lsr ? 0 : 1); | 1775 | len += (lsr ? 0 : 1); | 
| 1811 | unlock_kernel(); | ||
| 1812 | 1776 | ||
| 1813 | return put_user(len, (int __user *)argp); | 1777 | return put_user(len, (int __user *)argp); | 
| 1814 | } | 1778 | } | 
| 1815 | case MOXA_ASPP_MON: { | 1779 | case MOXA_ASPP_MON: { | 
| 1816 | int mcr, status; | 1780 | int mcr, status; | 
| 1817 | 1781 | ||
| 1818 | lock_kernel(); | 1782 | spin_lock(&info->slock); | 
| 1819 | status = mxser_get_msr(info->ioaddr, 1, tty->index); | 1783 | status = mxser_get_msr(info->ioaddr, 1, tty->index); | 
| 1820 | mxser_check_modem_status(tty, info, status); | 1784 | mxser_check_modem_status(tty, info, status); | 
| 1821 | 1785 | ||
| 1822 | mcr = inb(info->ioaddr + UART_MCR); | 1786 | mcr = inb(info->ioaddr + UART_MCR); | 
| 1787 | spin_unlock(&info->slock); | ||
| 1788 | |||
| 1823 | if (mcr & MOXA_MUST_MCR_XON_FLAG) | 1789 | if (mcr & MOXA_MUST_MCR_XON_FLAG) | 
| 1824 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; | 1790 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; | 
| 1825 | else | 1791 | else | 
| @@ -1834,7 +1800,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
| 1834 | info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; | 1800 | info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; | 
| 1835 | else | 1801 | else | 
| 1836 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; | 1802 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; | 
| 1837 | unlock_kernel(); | 1803 | |
| 1838 | if (copy_to_user(argp, &info->mon_data, | 1804 | if (copy_to_user(argp, &info->mon_data, | 
| 1839 | sizeof(struct mxser_mon))) | 1805 | sizeof(struct mxser_mon))) | 
| 1840 | return -EFAULT; | 1806 | return -EFAULT; | 
| @@ -1993,6 +1959,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) | |||
| 1993 | { | 1959 | { | 
| 1994 | struct mxser_port *info = tty->driver_data; | 1960 | struct mxser_port *info = tty->driver_data; | 
| 1995 | unsigned long orig_jiffies, char_time; | 1961 | unsigned long orig_jiffies, char_time; | 
| 1962 | unsigned long flags; | ||
| 1996 | int lsr; | 1963 | int lsr; | 
| 1997 | 1964 | ||
| 1998 | if (info->type == PORT_UNKNOWN) | 1965 | if (info->type == PORT_UNKNOWN) | 
| @@ -2032,19 +1999,21 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) | |||
| 2032 | timeout, char_time); | 1999 | timeout, char_time); | 
| 2033 | printk("jiff=%lu...", jiffies); | 2000 | printk("jiff=%lu...", jiffies); | 
| 2034 | #endif | 2001 | #endif | 
| 2035 | lock_kernel(); | 2002 | spin_lock_irqsave(&info->slock, flags); | 
| 2036 | while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { | 2003 | while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { | 
| 2037 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 2004 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 
| 2038 | printk("lsr = %d (jiff=%lu)...", lsr, jiffies); | 2005 | printk("lsr = %d (jiff=%lu)...", lsr, jiffies); | 
| 2039 | #endif | 2006 | #endif | 
| 2007 | spin_unlock_irqrestore(&info->slock, flags); | ||
| 2040 | schedule_timeout_interruptible(char_time); | 2008 | schedule_timeout_interruptible(char_time); | 
| 2009 | spin_lock_irqsave(&info->slock, flags); | ||
| 2041 | if (signal_pending(current)) | 2010 | if (signal_pending(current)) | 
| 2042 | break; | 2011 | break; | 
| 2043 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) | 2012 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) | 
| 2044 | break; | 2013 | break; | 
| 2045 | } | 2014 | } | 
| 2015 | spin_unlock_irqrestore(&info->slock, flags); | ||
| 2046 | set_current_state(TASK_RUNNING); | 2016 | set_current_state(TASK_RUNNING); | 
| 2047 | unlock_kernel(); | ||
| 2048 | 2017 | ||
| 2049 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 2018 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 
| 2050 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); | 2019 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); | 
| @@ -2059,7 +2028,6 @@ static void mxser_hangup(struct tty_struct *tty) | |||
| 2059 | struct mxser_port *info = tty->driver_data; | 2028 | struct mxser_port *info = tty->driver_data; | 
| 2060 | 2029 | ||
| 2061 | mxser_flush_buffer(tty); | 2030 | mxser_flush_buffer(tty); | 
| 2062 | mxser_shutdown(tty); | ||
| 2063 | tty_port_hangup(&info->port); | 2031 | tty_port_hangup(&info->port); | 
| 2064 | } | 2032 | } | 
| 2065 | 2033 | ||
| @@ -2363,6 +2331,8 @@ static const struct tty_operations mxser_ops = { | |||
| 2363 | struct tty_port_operations mxser_port_ops = { | 2331 | struct tty_port_operations mxser_port_ops = { | 
| 2364 | .carrier_raised = mxser_carrier_raised, | 2332 | .carrier_raised = mxser_carrier_raised, | 
| 2365 | .dtr_rts = mxser_dtr_rts, | 2333 | .dtr_rts = mxser_dtr_rts, | 
| 2334 | .activate = mxser_activate, | ||
| 2335 | .shutdown = mxser_shutdown_port, | ||
| 2366 | }; | 2336 | }; | 
| 2367 | 2337 | ||
| 2368 | /* | 2338 | /* | 
| diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c index 674b3ab3587d..2bb7874a6899 100644 --- a/drivers/char/pcmcia/ipwireless/tty.c +++ b/drivers/char/pcmcia/ipwireless/tty.c | |||
| @@ -603,7 +603,7 @@ void ipwireless_tty_free(struct ipw_tty *tty) | |||
| 603 | } | 603 | } | 
| 604 | } | 604 | } | 
| 605 | 605 | ||
| 606 | static struct tty_operations tty_ops = { | 606 | static const struct tty_operations tty_ops = { | 
| 607 | .open = ipw_open, | 607 | .open = ipw_open, | 
| 608 | .close = ipw_close, | 608 | .close = ipw_close, | 
| 609 | .hangup = ipw_hangup, | 609 | .hangup = ipw_hangup, | 
| diff --git a/drivers/char/pty.c b/drivers/char/pty.c index d86c0bc05c1c..385c44b3034f 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
| @@ -659,7 +659,7 @@ static int __ptmx_open(struct inode *inode, struct file *filp) | |||
| 659 | if (!retval) | 659 | if (!retval) | 
| 660 | return 0; | 660 | return 0; | 
| 661 | out1: | 661 | out1: | 
| 662 | tty_release_dev(filp); | 662 | tty_release(inode, filp); | 
| 663 | return retval; | 663 | return retval; | 
| 664 | out: | 664 | out: | 
| 665 | devpts_kill_index(inode, index); | 665 | devpts_kill_index(inode, index); | 
| diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 3cfa22d469e0..0a8d1e56c993 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
| @@ -793,26 +793,21 @@ static void rc_change_speed(struct tty_struct *tty, struct riscom_board *bp, | |||
| 793 | } | 793 | } | 
| 794 | 794 | ||
| 795 | /* Must be called with interrupts enabled */ | 795 | /* Must be called with interrupts enabled */ | 
| 796 | static int rc_setup_port(struct tty_struct *tty, struct riscom_board *bp, | 796 | static int rc_activate_port(struct tty_port *port, struct tty_struct *tty) | 
| 797 | struct riscom_port *port) | ||
| 798 | { | 797 | { | 
| 798 | struct riscom_port *rp = container_of(port, struct riscom_port, port); | ||
| 799 | struct riscom_board *bp = port_Board(rp); | ||
| 799 | unsigned long flags; | 800 | unsigned long flags; | 
| 800 | 801 | ||
| 801 | if (port->port.flags & ASYNC_INITIALIZED) | 802 | if (tty_port_alloc_xmit_buf(port) < 0) | 
| 802 | return 0; | ||
| 803 | |||
| 804 | if (tty_port_alloc_xmit_buf(&port->port) < 0) | ||
| 805 | return -ENOMEM; | 803 | return -ENOMEM; | 
| 806 | 804 | ||
| 807 | spin_lock_irqsave(&riscom_lock, flags); | 805 | spin_lock_irqsave(&riscom_lock, flags); | 
| 808 | 806 | ||
| 809 | clear_bit(TTY_IO_ERROR, &tty->flags); | 807 | clear_bit(TTY_IO_ERROR, &tty->flags); | 
| 810 | if (port->port.count == 1) | 808 | bp->count++; | 
| 811 | bp->count++; | 809 | rp->xmit_cnt = rp->xmit_head = rp->xmit_tail = 0; | 
| 812 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; | 810 | rc_change_speed(tty, bp, rp); | 
| 813 | rc_change_speed(tty, bp, port); | ||
| 814 | port->port.flags |= ASYNC_INITIALIZED; | ||
| 815 | |||
| 816 | spin_unlock_irqrestore(&riscom_lock, flags); | 811 | spin_unlock_irqrestore(&riscom_lock, flags); | 
| 817 | return 0; | 812 | return 0; | 
| 818 | } | 813 | } | 
| @@ -821,9 +816,6 @@ static int rc_setup_port(struct tty_struct *tty, struct riscom_board *bp, | |||
| 821 | static void rc_shutdown_port(struct tty_struct *tty, | 816 | static void rc_shutdown_port(struct tty_struct *tty, | 
| 822 | struct riscom_board *bp, struct riscom_port *port) | 817 | struct riscom_board *bp, struct riscom_port *port) | 
| 823 | { | 818 | { | 
| 824 | if (!(port->port.flags & ASYNC_INITIALIZED)) | ||
| 825 | return; | ||
| 826 | |||
| 827 | #ifdef RC_REPORT_OVERRUN | 819 | #ifdef RC_REPORT_OVERRUN | 
| 828 | printk(KERN_INFO "rc%d: port %d: Total %ld overruns were detected.\n", | 820 | printk(KERN_INFO "rc%d: port %d: Total %ld overruns were detected.\n", | 
| 829 | board_No(bp), port_No(port), port->overrun); | 821 | board_No(bp), port_No(port), port->overrun); | 
| @@ -840,11 +832,6 @@ static void rc_shutdown_port(struct tty_struct *tty, | |||
| 840 | } | 832 | } | 
| 841 | #endif | 833 | #endif | 
| 842 | tty_port_free_xmit_buf(&port->port); | 834 | tty_port_free_xmit_buf(&port->port); | 
| 843 | if (C_HUPCL(tty)) { | ||
| 844 | /* Drop DTR */ | ||
| 845 | bp->DTR |= (1u << port_No(port)); | ||
| 846 | rc_out(bp, RC_DTR, bp->DTR); | ||
| 847 | } | ||
| 848 | 835 | ||
| 849 | /* Select port */ | 836 | /* Select port */ | 
| 850 | rc_out(bp, CD180_CAR, port_No(port)); | 837 | rc_out(bp, CD180_CAR, port_No(port)); | 
| @@ -856,7 +843,6 @@ static void rc_shutdown_port(struct tty_struct *tty, | |||
| 856 | rc_out(bp, CD180_IER, port->IER); | 843 | rc_out(bp, CD180_IER, port->IER); | 
| 857 | 844 | ||
| 858 | set_bit(TTY_IO_ERROR, &tty->flags); | 845 | set_bit(TTY_IO_ERROR, &tty->flags); | 
| 859 | port->port.flags &= ~ASYNC_INITIALIZED; | ||
| 860 | 846 | ||
| 861 | if (--bp->count < 0) { | 847 | if (--bp->count < 0) { | 
| 862 | printk(KERN_INFO "rc%d: rc_shutdown_port: " | 848 | printk(KERN_INFO "rc%d: rc_shutdown_port: " | 
| @@ -889,6 +875,20 @@ static int carrier_raised(struct tty_port *port) | |||
| 889 | return CD; | 875 | return CD; | 
| 890 | } | 876 | } | 
| 891 | 877 | ||
| 878 | static void dtr_rts(struct tty_port *port, int onoff) | ||
| 879 | { | ||
| 880 | struct riscom_port *p = container_of(port, struct riscom_port, port); | ||
| 881 | struct riscom_board *bp = port_Board(p); | ||
| 882 | unsigned long flags; | ||
| 883 | |||
| 884 | spin_lock_irqsave(&riscom_lock, flags); | ||
| 885 | bp->DTR &= ~(1u << port_No(p)); | ||
| 886 | if (onoff == 0) | ||
| 887 | bp->DTR |= (1u << port_No(p)); | ||
| 888 | rc_out(bp, RC_DTR, bp->DTR); | ||
| 889 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
| 890 | } | ||
| 891 | |||
| 892 | static int rc_open(struct tty_struct *tty, struct file *filp) | 892 | static int rc_open(struct tty_struct *tty, struct file *filp) | 
| 893 | { | 893 | { | 
| 894 | int board; | 894 | int board; | 
| @@ -909,14 +909,7 @@ static int rc_open(struct tty_struct *tty, struct file *filp) | |||
| 909 | if (error) | 909 | if (error) | 
| 910 | return error; | 910 | return error; | 
| 911 | 911 | ||
| 912 | port->port.count++; | 912 | return tty_port_open(&port->port, tty, filp); | 
| 913 | tty->driver_data = port; | ||
| 914 | tty_port_tty_set(&port->port, tty); | ||
| 915 | |||
| 916 | error = rc_setup_port(tty, bp, port); | ||
| 917 | if (error == 0) | ||
| 918 | error = tty_port_block_til_ready(&port->port, tty, filp); | ||
| 919 | return error; | ||
| 920 | } | 913 | } | 
| 921 | 914 | ||
| 922 | static void rc_flush_buffer(struct tty_struct *tty) | 915 | static void rc_flush_buffer(struct tty_struct *tty) | 
| @@ -950,24 +943,23 @@ static void rc_close_port(struct tty_port *port) | |||
| 950 | 943 | ||
| 951 | spin_lock_irqsave(&riscom_lock, flags); | 944 | spin_lock_irqsave(&riscom_lock, flags); | 
| 952 | rp->IER &= ~IER_RXD; | 945 | rp->IER &= ~IER_RXD; | 
| 953 | if (port->flags & ASYNC_INITIALIZED) { | 946 | |
| 954 | rp->IER &= ~IER_TXRDY; | 947 | rp->IER &= ~IER_TXRDY; | 
| 955 | rp->IER |= IER_TXEMPTY; | 948 | rp->IER |= IER_TXEMPTY; | 
| 956 | rc_out(bp, CD180_CAR, port_No(rp)); | 949 | rc_out(bp, CD180_CAR, port_No(rp)); | 
| 957 | rc_out(bp, CD180_IER, rp->IER); | 950 | rc_out(bp, CD180_IER, rp->IER); | 
| 958 | /* | 951 | /* | 
| 959 | * Before we drop DTR, make sure the UART transmitter | 952 | * Before we drop DTR, make sure the UART transmitter | 
| 960 | * has completely drained; this is especially | 953 | * has completely drained; this is especially | 
| 961 | * important if there is a transmit FIFO! | 954 | * important if there is a transmit FIFO! | 
| 962 | */ | 955 | */ | 
| 963 | timeout = jiffies + HZ; | 956 | timeout = jiffies + HZ; | 
| 964 | while (rp->IER & IER_TXEMPTY) { | 957 | while (rp->IER & IER_TXEMPTY) { | 
| 965 | spin_unlock_irqrestore(&riscom_lock, flags); | 958 | spin_unlock_irqrestore(&riscom_lock, flags); | 
| 966 | msleep_interruptible(jiffies_to_msecs(rp->timeout)); | 959 | msleep_interruptible(jiffies_to_msecs(rp->timeout)); | 
| 967 | spin_lock_irqsave(&riscom_lock, flags); | 960 | spin_lock_irqsave(&riscom_lock, flags); | 
| 968 | if (time_after(jiffies, timeout)) | 961 | if (time_after(jiffies, timeout)) | 
| 969 | break; | 962 | break; | 
| 970 | } | ||
| 971 | } | 963 | } | 
| 972 | rc_shutdown_port(port->tty, bp, rp); | 964 | rc_shutdown_port(port->tty, bp, rp); | 
| 973 | spin_unlock_irqrestore(&riscom_lock, flags); | 965 | spin_unlock_irqrestore(&riscom_lock, flags); | 
| @@ -1354,7 +1346,6 @@ static void rc_hangup(struct tty_struct *tty) | |||
| 1354 | if (rc_paranoia_check(port, tty->name, "rc_hangup")) | 1346 | if (rc_paranoia_check(port, tty->name, "rc_hangup")) | 
| 1355 | return; | 1347 | return; | 
| 1356 | 1348 | ||
| 1357 | rc_shutdown_port(tty, port_Board(port), port); | ||
| 1358 | tty_port_hangup(&port->port); | 1349 | tty_port_hangup(&port->port); | 
| 1359 | } | 1350 | } | 
| 1360 | 1351 | ||
| @@ -1401,7 +1392,9 @@ static const struct tty_operations riscom_ops = { | |||
| 1401 | 1392 | ||
| 1402 | static const struct tty_port_operations riscom_port_ops = { | 1393 | static const struct tty_port_operations riscom_port_ops = { | 
| 1403 | .carrier_raised = carrier_raised, | 1394 | .carrier_raised = carrier_raised, | 
| 1395 | .dtr_rts = dtr_rts, | ||
| 1404 | .shutdown = rc_close_port, | 1396 | .shutdown = rc_close_port, | 
| 1397 | .activate = rc_activate_port, | ||
| 1405 | }; | 1398 | }; | 
| 1406 | 1399 | ||
| 1407 | 1400 | ||
| diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index db6dcfa35ba0..0e511d61f544 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
| @@ -407,7 +407,7 @@ static unsigned int stl_baudrates[] = { | |||
| 407 | * Declare all those functions in this driver! | 407 | * Declare all those functions in this driver! | 
| 408 | */ | 408 | */ | 
| 409 | 409 | ||
| 410 | static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); | 410 | static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg); | 
| 411 | static int stl_brdinit(struct stlbrd *brdp); | 411 | static int stl_brdinit(struct stlbrd *brdp); | 
| 412 | static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp); | 412 | static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp); | 
| 413 | static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); | 413 | static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); | 
| @@ -607,7 +607,7 @@ static unsigned int sc26198_baudtable[] = { | |||
| 607 | */ | 607 | */ | 
| 608 | static const struct file_operations stl_fsiomem = { | 608 | static const struct file_operations stl_fsiomem = { | 
| 609 | .owner = THIS_MODULE, | 609 | .owner = THIS_MODULE, | 
| 610 | .ioctl = stl_memioctl, | 610 | .unlocked_ioctl = stl_memioctl, | 
| 611 | }; | 611 | }; | 
| 612 | 612 | ||
| 613 | static struct class *stallion_class; | 613 | static struct class *stallion_class; | 
| @@ -702,6 +702,24 @@ static struct stlbrd *stl_allocbrd(void) | |||
| 702 | 702 | ||
| 703 | /*****************************************************************************/ | 703 | /*****************************************************************************/ | 
| 704 | 704 | ||
| 705 | static int stl_activate(struct tty_port *port, struct tty_struct *tty) | ||
| 706 | { | ||
| 707 | struct stlport *portp = container_of(port, struct stlport, port); | ||
| 708 | if (!portp->tx.buf) { | ||
| 709 | portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); | ||
| 710 | if (!portp->tx.buf) | ||
| 711 | return -ENOMEM; | ||
| 712 | portp->tx.head = portp->tx.buf; | ||
| 713 | portp->tx.tail = portp->tx.buf; | ||
| 714 | } | ||
| 715 | stl_setport(portp, tty->termios); | ||
| 716 | portp->sigs = stl_getsignals(portp); | ||
| 717 | stl_setsignals(portp, 1, 1); | ||
| 718 | stl_enablerxtx(portp, 1, 1); | ||
| 719 | stl_startrxtx(portp, 1, 0); | ||
| 720 | return 0; | ||
| 721 | } | ||
| 722 | |||
| 705 | static int stl_open(struct tty_struct *tty, struct file *filp) | 723 | static int stl_open(struct tty_struct *tty, struct file *filp) | 
| 706 | { | 724 | { | 
| 707 | struct stlport *portp; | 725 | struct stlport *portp; | 
| @@ -737,32 +755,8 @@ static int stl_open(struct tty_struct *tty, struct file *filp) | |||
| 737 | if (portp == NULL) | 755 | if (portp == NULL) | 
| 738 | return -ENODEV; | 756 | return -ENODEV; | 
| 739 | port = &portp->port; | 757 | port = &portp->port; | 
| 758 | return tty_port_open(&portp->port, tty, filp); | ||
| 740 | 759 | ||
| 741 | /* | ||
| 742 | * On the first open of the device setup the port hardware, and | ||
| 743 | * initialize the per port data structure. | ||
| 744 | */ | ||
| 745 | tty_port_tty_set(port, tty); | ||
| 746 | tty->driver_data = portp; | ||
| 747 | port->count++; | ||
| 748 | |||
| 749 | if ((port->flags & ASYNC_INITIALIZED) == 0) { | ||
| 750 | if (!portp->tx.buf) { | ||
| 751 | portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); | ||
| 752 | if (!portp->tx.buf) | ||
| 753 | return -ENOMEM; | ||
| 754 | portp->tx.head = portp->tx.buf; | ||
| 755 | portp->tx.tail = portp->tx.buf; | ||
| 756 | } | ||
| 757 | stl_setport(portp, tty->termios); | ||
| 758 | portp->sigs = stl_getsignals(portp); | ||
| 759 | stl_setsignals(portp, 1, 1); | ||
| 760 | stl_enablerxtx(portp, 1, 1); | ||
| 761 | stl_startrxtx(portp, 1, 0); | ||
| 762 | clear_bit(TTY_IO_ERROR, &tty->flags); | ||
| 763 | port->flags |= ASYNC_INITIALIZED; | ||
| 764 | } | ||
| 765 | return tty_port_block_til_ready(port, tty, filp); | ||
| 766 | } | 760 | } | 
| 767 | 761 | ||
| 768 | /*****************************************************************************/ | 762 | /*****************************************************************************/ | 
| @@ -826,38 +820,12 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout) | |||
| 826 | 820 | ||
| 827 | /*****************************************************************************/ | 821 | /*****************************************************************************/ | 
| 828 | 822 | ||
| 829 | static void stl_close(struct tty_struct *tty, struct file *filp) | 823 | static void stl_shutdown(struct tty_port *port) | 
| 830 | { | 824 | { | 
| 831 | struct stlport *portp; | 825 | struct stlport *portp = container_of(port, struct stlport, port); | 
| 832 | struct tty_port *port; | ||
| 833 | unsigned long flags; | ||
| 834 | |||
| 835 | pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); | ||
| 836 | |||
| 837 | portp = tty->driver_data; | ||
| 838 | BUG_ON(portp == NULL); | ||
| 839 | |||
| 840 | port = &portp->port; | ||
| 841 | |||
| 842 | if (tty_port_close_start(port, tty, filp) == 0) | ||
| 843 | return; | ||
| 844 | /* | ||
| 845 | * May want to wait for any data to drain before closing. The BUSY | ||
| 846 | * flag keeps track of whether we are still sending or not - it is | ||
| 847 | * very accurate for the cd1400, not quite so for the sc26198. | ||
| 848 | * (The sc26198 has no "end-of-data" interrupt only empty FIFO) | ||
| 849 | */ | ||
| 850 | stl_waituntilsent(tty, (HZ / 2)); | ||
| 851 | |||
| 852 | spin_lock_irqsave(&port->lock, flags); | ||
| 853 | portp->port.flags &= ~ASYNC_INITIALIZED; | ||
| 854 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 855 | |||
| 856 | stl_disableintrs(portp); | 826 | stl_disableintrs(portp); | 
| 857 | if (tty->termios->c_cflag & HUPCL) | ||
| 858 | stl_setsignals(portp, 0, 0); | ||
| 859 | stl_enablerxtx(portp, 0, 0); | 827 | stl_enablerxtx(portp, 0, 0); | 
| 860 | stl_flushbuffer(tty); | 828 | stl_flush(portp); | 
| 861 | portp->istate = 0; | 829 | portp->istate = 0; | 
| 862 | if (portp->tx.buf != NULL) { | 830 | if (portp->tx.buf != NULL) { | 
| 863 | kfree(portp->tx.buf); | 831 | kfree(portp->tx.buf); | 
| @@ -865,9 +833,16 @@ static void stl_close(struct tty_struct *tty, struct file *filp) | |||
| 865 | portp->tx.head = NULL; | 833 | portp->tx.head = NULL; | 
| 866 | portp->tx.tail = NULL; | 834 | portp->tx.tail = NULL; | 
| 867 | } | 835 | } | 
| 836 | } | ||
| 837 | |||
| 838 | static void stl_close(struct tty_struct *tty, struct file *filp) | ||
| 839 | { | ||
| 840 | struct stlport*portp; | ||
| 841 | pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); | ||
| 868 | 842 | ||
| 869 | tty_port_close_end(port, tty); | 843 | portp = tty->driver_data; | 
| 870 | tty_port_tty_set(port, NULL); | 844 | BUG_ON(portp == NULL); | 
| 845 | tty_port_close(&portp->port, tty, filp); | ||
| 871 | } | 846 | } | 
| 872 | 847 | ||
| 873 | /*****************************************************************************/ | 848 | /*****************************************************************************/ | 
| @@ -1314,35 +1289,12 @@ static void stl_stop(struct tty_struct *tty) | |||
| 1314 | 1289 | ||
| 1315 | static void stl_hangup(struct tty_struct *tty) | 1290 | static void stl_hangup(struct tty_struct *tty) | 
| 1316 | { | 1291 | { | 
| 1317 | struct stlport *portp; | 1292 | struct stlport *portp = tty->driver_data; | 
| 1318 | struct tty_port *port; | ||
| 1319 | unsigned long flags; | ||
| 1320 | |||
| 1321 | pr_debug("stl_hangup(tty=%p)\n", tty); | 1293 | pr_debug("stl_hangup(tty=%p)\n", tty); | 
| 1322 | 1294 | ||
| 1323 | portp = tty->driver_data; | ||
| 1324 | if (portp == NULL) | 1295 | if (portp == NULL) | 
| 1325 | return; | 1296 | return; | 
| 1326 | port = &portp->port; | 1297 | tty_port_hangup(&portp->port); | 
| 1327 | |||
| 1328 | spin_lock_irqsave(&port->lock, flags); | ||
| 1329 | port->flags &= ~ASYNC_INITIALIZED; | ||
| 1330 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 1331 | |||
| 1332 | stl_disableintrs(portp); | ||
| 1333 | if (tty->termios->c_cflag & HUPCL) | ||
| 1334 | stl_setsignals(portp, 0, 0); | ||
| 1335 | stl_enablerxtx(portp, 0, 0); | ||
| 1336 | stl_flushbuffer(tty); | ||
| 1337 | portp->istate = 0; | ||
| 1338 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
| 1339 | if (portp->tx.buf != NULL) { | ||
| 1340 | kfree(portp->tx.buf); | ||
| 1341 | portp->tx.buf = NULL; | ||
| 1342 | portp->tx.head = NULL; | ||
| 1343 | portp->tx.tail = NULL; | ||
| 1344 | } | ||
| 1345 | tty_port_hangup(port); | ||
| 1346 | } | 1298 | } | 
| 1347 | 1299 | ||
| 1348 | /*****************************************************************************/ | 1300 | /*****************************************************************************/ | 
| @@ -2486,18 +2438,19 @@ static int stl_getbrdstruct(struct stlbrd __user *arg) | |||
| 2486 | * collection. | 2438 | * collection. | 
| 2487 | */ | 2439 | */ | 
| 2488 | 2440 | ||
| 2489 | static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg) | 2441 | static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | 
| 2490 | { | 2442 | { | 
| 2491 | int brdnr, rc; | 2443 | int brdnr, rc; | 
| 2492 | void __user *argp = (void __user *)arg; | 2444 | void __user *argp = (void __user *)arg; | 
| 2493 | 2445 | ||
| 2494 | pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg); | 2446 | pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg); | 
| 2495 | 2447 | ||
| 2496 | brdnr = iminor(ip); | 2448 | brdnr = iminor(fp->f_dentry->d_inode); | 
| 2497 | if (brdnr >= STL_MAXBRDS) | 2449 | if (brdnr >= STL_MAXBRDS) | 
| 2498 | return -ENODEV; | 2450 | return -ENODEV; | 
| 2499 | rc = 0; | 2451 | rc = 0; | 
| 2500 | 2452 | ||
| 2453 | lock_kernel(); | ||
| 2501 | switch (cmd) { | 2454 | switch (cmd) { | 
| 2502 | case COM_GETPORTSTATS: | 2455 | case COM_GETPORTSTATS: | 
| 2503 | rc = stl_getportstats(NULL, NULL, argp); | 2456 | rc = stl_getportstats(NULL, NULL, argp); | 
| @@ -2518,7 +2471,7 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns | |||
| 2518 | rc = -ENOIOCTLCMD; | 2471 | rc = -ENOIOCTLCMD; | 
| 2519 | break; | 2472 | break; | 
| 2520 | } | 2473 | } | 
| 2521 | 2474 | unlock_kernel(); | |
| 2522 | return rc; | 2475 | return rc; | 
| 2523 | } | 2476 | } | 
| 2524 | 2477 | ||
| @@ -2549,6 +2502,8 @@ static const struct tty_operations stl_ops = { | |||
| 2549 | static const struct tty_port_operations stl_port_ops = { | 2502 | static const struct tty_port_operations stl_port_ops = { | 
| 2550 | .carrier_raised = stl_carrier_raised, | 2503 | .carrier_raised = stl_carrier_raised, | 
| 2551 | .dtr_rts = stl_dtr_rts, | 2504 | .dtr_rts = stl_dtr_rts, | 
| 2505 | .activate = stl_activate, | ||
| 2506 | .shutdown = stl_shutdown, | ||
| 2552 | }; | 2507 | }; | 
| 2553 | 2508 | ||
| 2554 | /*****************************************************************************/ | 2509 | /*****************************************************************************/ | 
| diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 59499ee0fe6a..684f0e0b175e 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
| @@ -142,7 +142,6 @@ ssize_t redirected_tty_write(struct file *, const char __user *, | |||
| 142 | size_t, loff_t *); | 142 | size_t, loff_t *); | 
| 143 | static unsigned int tty_poll(struct file *, poll_table *); | 143 | static unsigned int tty_poll(struct file *, poll_table *); | 
| 144 | static int tty_open(struct inode *, struct file *); | 144 | static int tty_open(struct inode *, struct file *); | 
| 145 | static int tty_release(struct inode *, struct file *); | ||
| 146 | long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg); | 145 | long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg); | 
| 147 | #ifdef CONFIG_COMPAT | 146 | #ifdef CONFIG_COMPAT | 
| 148 | static long tty_compat_ioctl(struct file *file, unsigned int cmd, | 147 | static long tty_compat_ioctl(struct file *file, unsigned int cmd, | 
| @@ -506,8 +505,6 @@ static void do_tty_hangup(struct work_struct *work) | |||
| 506 | if (!tty) | 505 | if (!tty) | 
| 507 | return; | 506 | return; | 
| 508 | 507 | ||
| 509 | /* inuse_filps is protected by the single kernel lock */ | ||
| 510 | lock_kernel(); | ||
| 511 | 508 | ||
| 512 | spin_lock(&redirect_lock); | 509 | spin_lock(&redirect_lock); | 
| 513 | if (redirect && redirect->private_data == tty) { | 510 | if (redirect && redirect->private_data == tty) { | 
| @@ -516,7 +513,11 @@ static void do_tty_hangup(struct work_struct *work) | |||
| 516 | } | 513 | } | 
| 517 | spin_unlock(&redirect_lock); | 514 | spin_unlock(&redirect_lock); | 
| 518 | 515 | ||
| 516 | /* inuse_filps is protected by the single kernel lock */ | ||
| 517 | lock_kernel(); | ||
| 519 | check_tty_count(tty, "do_tty_hangup"); | 518 | check_tty_count(tty, "do_tty_hangup"); | 
| 519 | unlock_kernel(); | ||
| 520 | |||
| 520 | file_list_lock(); | 521 | file_list_lock(); | 
| 521 | /* This breaks for file handles being sent over AF_UNIX sockets ? */ | 522 | /* This breaks for file handles being sent over AF_UNIX sockets ? */ | 
| 522 | list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) { | 523 | list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) { | 
| @@ -530,6 +531,7 @@ static void do_tty_hangup(struct work_struct *work) | |||
| 530 | } | 531 | } | 
| 531 | file_list_unlock(); | 532 | file_list_unlock(); | 
| 532 | 533 | ||
| 534 | lock_kernel(); | ||
| 533 | tty_ldisc_hangup(tty); | 535 | tty_ldisc_hangup(tty); | 
| 534 | 536 | ||
| 535 | read_lock(&tasklist_lock); | 537 | read_lock(&tasklist_lock); | 
| @@ -708,6 +710,8 @@ void disassociate_ctty(int on_exit) | |||
| 708 | struct tty_struct *tty; | 710 | struct tty_struct *tty; | 
| 709 | struct pid *tty_pgrp = NULL; | 711 | struct pid *tty_pgrp = NULL; | 
| 710 | 712 | ||
| 713 | if (!current->signal->leader) | ||
| 714 | return; | ||
| 711 | 715 | ||
| 712 | tty = get_current_tty(); | 716 | tty = get_current_tty(); | 
| 713 | if (tty) { | 717 | if (tty) { | 
| @@ -773,8 +777,7 @@ void no_tty(void) | |||
| 773 | { | 777 | { | 
| 774 | struct task_struct *tsk = current; | 778 | struct task_struct *tsk = current; | 
| 775 | lock_kernel(); | 779 | lock_kernel(); | 
| 776 | if (tsk->signal->leader) | 780 | disassociate_ctty(0); | 
| 777 | disassociate_ctty(0); | ||
| 778 | unlock_kernel(); | 781 | unlock_kernel(); | 
| 779 | proc_clear_tty(tsk); | 782 | proc_clear_tty(tsk); | 
| 780 | } | 783 | } | 
| @@ -1017,14 +1020,16 @@ out: | |||
| 1017 | 1020 | ||
| 1018 | void tty_write_message(struct tty_struct *tty, char *msg) | 1021 | void tty_write_message(struct tty_struct *tty, char *msg) | 
| 1019 | { | 1022 | { | 
| 1020 | lock_kernel(); | ||
| 1021 | if (tty) { | 1023 | if (tty) { | 
| 1022 | mutex_lock(&tty->atomic_write_lock); | 1024 | mutex_lock(&tty->atomic_write_lock); | 
| 1023 | if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) | 1025 | lock_kernel(); | 
| 1026 | if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { | ||
| 1027 | unlock_kernel(); | ||
| 1024 | tty->ops->write(tty, msg, strlen(msg)); | 1028 | tty->ops->write(tty, msg, strlen(msg)); | 
| 1029 | } else | ||
| 1030 | unlock_kernel(); | ||
| 1025 | tty_write_unlock(tty); | 1031 | tty_write_unlock(tty); | 
| 1026 | } | 1032 | } | 
| 1027 | unlock_kernel(); | ||
| 1028 | return; | 1033 | return; | 
| 1029 | } | 1034 | } | 
| 1030 | 1035 | ||
| @@ -1202,14 +1207,21 @@ static int tty_driver_install_tty(struct tty_driver *driver, | |||
| 1202 | struct tty_struct *tty) | 1207 | struct tty_struct *tty) | 
| 1203 | { | 1208 | { | 
| 1204 | int idx = tty->index; | 1209 | int idx = tty->index; | 
| 1210 | int ret; | ||
| 1205 | 1211 | ||
| 1206 | if (driver->ops->install) | 1212 | if (driver->ops->install) { | 
| 1207 | return driver->ops->install(driver, tty); | 1213 | lock_kernel(); | 
| 1214 | ret = driver->ops->install(driver, tty); | ||
| 1215 | unlock_kernel(); | ||
| 1216 | return ret; | ||
| 1217 | } | ||
| 1208 | 1218 | ||
| 1209 | if (tty_init_termios(tty) == 0) { | 1219 | if (tty_init_termios(tty) == 0) { | 
| 1220 | lock_kernel(); | ||
| 1210 | tty_driver_kref_get(driver); | 1221 | tty_driver_kref_get(driver); | 
| 1211 | tty->count++; | 1222 | tty->count++; | 
| 1212 | driver->ttys[idx] = tty; | 1223 | driver->ttys[idx] = tty; | 
| 1224 | unlock_kernel(); | ||
| 1213 | return 0; | 1225 | return 0; | 
| 1214 | } | 1226 | } | 
| 1215 | return -ENOMEM; | 1227 | return -ENOMEM; | 
| @@ -1302,10 +1314,14 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | |||
| 1302 | struct tty_struct *tty; | 1314 | struct tty_struct *tty; | 
| 1303 | int retval; | 1315 | int retval; | 
| 1304 | 1316 | ||
| 1317 | lock_kernel(); | ||
| 1305 | /* Check if pty master is being opened multiple times */ | 1318 | /* Check if pty master is being opened multiple times */ | 
| 1306 | if (driver->subtype == PTY_TYPE_MASTER && | 1319 | if (driver->subtype == PTY_TYPE_MASTER && | 
| 1307 | (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) | 1320 | (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) { | 
| 1321 | unlock_kernel(); | ||
| 1308 | return ERR_PTR(-EIO); | 1322 | return ERR_PTR(-EIO); | 
| 1323 | } | ||
| 1324 | unlock_kernel(); | ||
| 1309 | 1325 | ||
| 1310 | /* | 1326 | /* | 
| 1311 | * First time open is complex, especially for PTY devices. | 1327 | * First time open is complex, especially for PTY devices. | 
| @@ -1335,7 +1351,6 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | |||
| 1335 | * If we fail here just call release_tty to clean up. No need | 1351 | * If we fail here just call release_tty to clean up. No need | 
| 1336 | * to decrement the use counts, as release_tty doesn't care. | 1352 | * to decrement the use counts, as release_tty doesn't care. | 
| 1337 | */ | 1353 | */ | 
| 1338 | |||
| 1339 | retval = tty_ldisc_setup(tty, tty->link); | 1354 | retval = tty_ldisc_setup(tty, tty->link); | 
| 1340 | if (retval) | 1355 | if (retval) | 
| 1341 | goto release_mem_out; | 1356 | goto release_mem_out; | 
| @@ -1350,7 +1365,9 @@ release_mem_out: | |||
| 1350 | if (printk_ratelimit()) | 1365 | if (printk_ratelimit()) | 
| 1351 | printk(KERN_INFO "tty_init_dev: ldisc open failed, " | 1366 | printk(KERN_INFO "tty_init_dev: ldisc open failed, " | 
| 1352 | "clearing slot %d\n", idx); | 1367 | "clearing slot %d\n", idx); | 
| 1368 | lock_kernel(); | ||
| 1353 | release_tty(tty, idx); | 1369 | release_tty(tty, idx); | 
| 1370 | unlock_kernel(); | ||
| 1354 | return ERR_PTR(retval); | 1371 | return ERR_PTR(retval); | 
| 1355 | } | 1372 | } | 
| 1356 | 1373 | ||
| @@ -1464,7 +1481,17 @@ static void release_tty(struct tty_struct *tty, int idx) | |||
| 1464 | tty_kref_put(tty); | 1481 | tty_kref_put(tty); | 
| 1465 | } | 1482 | } | 
| 1466 | 1483 | ||
| 1467 | /* | 1484 | /** | 
| 1485 | * tty_release - vfs callback for close | ||
| 1486 | * @inode: inode of tty | ||
| 1487 | * @filp: file pointer for handle to tty | ||
| 1488 | * | ||
| 1489 | * Called the last time each file handle is closed that references | ||
| 1490 | * this tty. There may however be several such references. | ||
| 1491 | * | ||
| 1492 | * Locking: | ||
| 1493 | * Takes bkl. See tty_release_dev | ||
| 1494 | * | ||
| 1468 | * Even releasing the tty structures is a tricky business.. We have | 1495 | * Even releasing the tty structures is a tricky business.. We have | 
| 1469 | * to be very careful that the structures are all released at the | 1496 | * to be very careful that the structures are all released at the | 
| 1470 | * same time, as interrupts might otherwise get the wrong pointers. | 1497 | * same time, as interrupts might otherwise get the wrong pointers. | 
| @@ -1472,20 +1499,20 @@ static void release_tty(struct tty_struct *tty, int idx) | |||
| 1472 | * WSH 09/09/97: rewritten to avoid some nasty race conditions that could | 1499 | * WSH 09/09/97: rewritten to avoid some nasty race conditions that could | 
| 1473 | * lead to double frees or releasing memory still in use. | 1500 | * lead to double frees or releasing memory still in use. | 
| 1474 | */ | 1501 | */ | 
| 1475 | void tty_release_dev(struct file *filp) | 1502 | |
| 1503 | int tty_release(struct inode *inode, struct file *filp) | ||
| 1476 | { | 1504 | { | 
| 1477 | struct tty_struct *tty, *o_tty; | 1505 | struct tty_struct *tty, *o_tty; | 
| 1478 | int pty_master, tty_closing, o_tty_closing, do_sleep; | 1506 | int pty_master, tty_closing, o_tty_closing, do_sleep; | 
| 1479 | int devpts; | 1507 | int devpts; | 
| 1480 | int idx; | 1508 | int idx; | 
| 1481 | char buf[64]; | 1509 | char buf[64]; | 
| 1482 | struct inode *inode; | ||
| 1483 | 1510 | ||
| 1484 | inode = filp->f_path.dentry->d_inode; | ||
| 1485 | tty = (struct tty_struct *)filp->private_data; | 1511 | tty = (struct tty_struct *)filp->private_data; | 
| 1486 | if (tty_paranoia_check(tty, inode, "tty_release_dev")) | 1512 | if (tty_paranoia_check(tty, inode, "tty_release_dev")) | 
| 1487 | return; | 1513 | return 0; | 
| 1488 | 1514 | ||
| 1515 | lock_kernel(); | ||
| 1489 | check_tty_count(tty, "tty_release_dev"); | 1516 | check_tty_count(tty, "tty_release_dev"); | 
| 1490 | 1517 | ||
| 1491 | tty_fasync(-1, filp, 0); | 1518 | tty_fasync(-1, filp, 0); | 
| @@ -1500,19 +1527,22 @@ void tty_release_dev(struct file *filp) | |||
| 1500 | if (idx < 0 || idx >= tty->driver->num) { | 1527 | if (idx < 0 || idx >= tty->driver->num) { | 
| 1501 | printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " | 1528 | printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " | 
| 1502 | "free (%s)\n", tty->name); | 1529 | "free (%s)\n", tty->name); | 
| 1503 | return; | 1530 | unlock_kernel(); | 
| 1531 | return 0; | ||
| 1504 | } | 1532 | } | 
| 1505 | if (!devpts) { | 1533 | if (!devpts) { | 
| 1506 | if (tty != tty->driver->ttys[idx]) { | 1534 | if (tty != tty->driver->ttys[idx]) { | 
| 1535 | unlock_kernel(); | ||
| 1507 | printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " | 1536 | printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " | 
| 1508 | "for (%s)\n", idx, tty->name); | 1537 | "for (%s)\n", idx, tty->name); | 
| 1509 | return; | 1538 | return 0; | 
| 1510 | } | 1539 | } | 
| 1511 | if (tty->termios != tty->driver->termios[idx]) { | 1540 | if (tty->termios != tty->driver->termios[idx]) { | 
| 1541 | unlock_kernel(); | ||
| 1512 | printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " | 1542 | printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " | 
| 1513 | "for (%s)\n", | 1543 | "for (%s)\n", | 
| 1514 | idx, tty->name); | 1544 | idx, tty->name); | 
| 1515 | return; | 1545 | return 0; | 
| 1516 | } | 1546 | } | 
| 1517 | } | 1547 | } | 
| 1518 | #endif | 1548 | #endif | 
| @@ -1526,26 +1556,30 @@ void tty_release_dev(struct file *filp) | |||
| 1526 | if (tty->driver->other && | 1556 | if (tty->driver->other && | 
| 1527 | !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { | 1557 | !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { | 
| 1528 | if (o_tty != tty->driver->other->ttys[idx]) { | 1558 | if (o_tty != tty->driver->other->ttys[idx]) { | 
| 1559 | unlock_kernel(); | ||
| 1529 | printk(KERN_DEBUG "tty_release_dev: other->table[%d] " | 1560 | printk(KERN_DEBUG "tty_release_dev: other->table[%d] " | 
| 1530 | "not o_tty for (%s)\n", | 1561 | "not o_tty for (%s)\n", | 
| 1531 | idx, tty->name); | 1562 | idx, tty->name); | 
| 1532 | return; | 1563 | return 0 ; | 
| 1533 | } | 1564 | } | 
| 1534 | if (o_tty->termios != tty->driver->other->termios[idx]) { | 1565 | if (o_tty->termios != tty->driver->other->termios[idx]) { | 
| 1566 | unlock_kernel(); | ||
| 1535 | printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " | 1567 | printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " | 
| 1536 | "not o_termios for (%s)\n", | 1568 | "not o_termios for (%s)\n", | 
| 1537 | idx, tty->name); | 1569 | idx, tty->name); | 
| 1538 | return; | 1570 | return 0; | 
| 1539 | } | 1571 | } | 
| 1540 | if (o_tty->link != tty) { | 1572 | if (o_tty->link != tty) { | 
| 1573 | unlock_kernel(); | ||
| 1541 | printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); | 1574 | printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); | 
| 1542 | return; | 1575 | return 0; | 
| 1543 | } | 1576 | } | 
| 1544 | } | 1577 | } | 
| 1545 | #endif | 1578 | #endif | 
| 1546 | if (tty->ops->close) | 1579 | if (tty->ops->close) | 
| 1547 | tty->ops->close(tty, filp); | 1580 | tty->ops->close(tty, filp); | 
| 1548 | 1581 | ||
| 1582 | unlock_kernel(); | ||
| 1549 | /* | 1583 | /* | 
| 1550 | * Sanity check: if tty->count is going to zero, there shouldn't be | 1584 | * Sanity check: if tty->count is going to zero, there shouldn't be | 
| 1551 | * any waiters on tty->read_wait or tty->write_wait. We test the | 1585 | * any waiters on tty->read_wait or tty->write_wait. We test the | 
| @@ -1568,6 +1602,7 @@ void tty_release_dev(struct file *filp) | |||
| 1568 | opens on /dev/tty */ | 1602 | opens on /dev/tty */ | 
| 1569 | 1603 | ||
| 1570 | mutex_lock(&tty_mutex); | 1604 | mutex_lock(&tty_mutex); | 
| 1605 | lock_kernel(); | ||
| 1571 | tty_closing = tty->count <= 1; | 1606 | tty_closing = tty->count <= 1; | 
| 1572 | o_tty_closing = o_tty && | 1607 | o_tty_closing = o_tty && | 
| 1573 | (o_tty->count <= (pty_master ? 1 : 0)); | 1608 | (o_tty->count <= (pty_master ? 1 : 0)); | 
| @@ -1598,6 +1633,7 @@ void tty_release_dev(struct file *filp) | |||
| 1598 | 1633 | ||
| 1599 | printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " | 1634 | printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " | 
| 1600 | "active!\n", tty_name(tty, buf)); | 1635 | "active!\n", tty_name(tty, buf)); | 
| 1636 | unlock_kernel(); | ||
| 1601 | mutex_unlock(&tty_mutex); | 1637 | mutex_unlock(&tty_mutex); | 
| 1602 | schedule(); | 1638 | schedule(); | 
| 1603 | } | 1639 | } | 
| @@ -1661,8 +1697,10 @@ void tty_release_dev(struct file *filp) | |||
| 1661 | mutex_unlock(&tty_mutex); | 1697 | mutex_unlock(&tty_mutex); | 
| 1662 | 1698 | ||
| 1663 | /* check whether both sides are closing ... */ | 1699 | /* check whether both sides are closing ... */ | 
| 1664 | if (!tty_closing || (o_tty && !o_tty_closing)) | 1700 | if (!tty_closing || (o_tty && !o_tty_closing)) { | 
| 1665 | return; | 1701 | unlock_kernel(); | 
| 1702 | return 0; | ||
| 1703 | } | ||
| 1666 | 1704 | ||
| 1667 | #ifdef TTY_DEBUG_HANGUP | 1705 | #ifdef TTY_DEBUG_HANGUP | 
| 1668 | printk(KERN_DEBUG "freeing tty structure..."); | 1706 | printk(KERN_DEBUG "freeing tty structure..."); | 
| @@ -1680,10 +1718,12 @@ void tty_release_dev(struct file *filp) | |||
| 1680 | /* Make this pty number available for reallocation */ | 1718 | /* Make this pty number available for reallocation */ | 
| 1681 | if (devpts) | 1719 | if (devpts) | 
| 1682 | devpts_kill_index(inode, idx); | 1720 | devpts_kill_index(inode, idx); | 
| 1721 | unlock_kernel(); | ||
| 1722 | return 0; | ||
| 1683 | } | 1723 | } | 
| 1684 | 1724 | ||
| 1685 | /** | 1725 | /** | 
| 1686 | * __tty_open - open a tty device | 1726 | * tty_open - open a tty device | 
| 1687 | * @inode: inode of device file | 1727 | * @inode: inode of device file | 
| 1688 | * @filp: file pointer to tty | 1728 | * @filp: file pointer to tty | 
| 1689 | * | 1729 | * | 
| @@ -1703,7 +1743,7 @@ void tty_release_dev(struct file *filp) | |||
| 1703 | * ->siglock protects ->signal/->sighand | 1743 | * ->siglock protects ->signal/->sighand | 
| 1704 | */ | 1744 | */ | 
| 1705 | 1745 | ||
| 1706 | static int __tty_open(struct inode *inode, struct file *filp) | 1746 | static int tty_open(struct inode *inode, struct file *filp) | 
| 1707 | { | 1747 | { | 
| 1708 | struct tty_struct *tty = NULL; | 1748 | struct tty_struct *tty = NULL; | 
| 1709 | int noctty, retval; | 1749 | int noctty, retval; | 
| @@ -1720,10 +1760,12 @@ retry_open: | |||
| 1720 | retval = 0; | 1760 | retval = 0; | 
| 1721 | 1761 | ||
| 1722 | mutex_lock(&tty_mutex); | 1762 | mutex_lock(&tty_mutex); | 
| 1763 | lock_kernel(); | ||
| 1723 | 1764 | ||
| 1724 | if (device == MKDEV(TTYAUX_MAJOR, 0)) { | 1765 | if (device == MKDEV(TTYAUX_MAJOR, 0)) { | 
| 1725 | tty = get_current_tty(); | 1766 | tty = get_current_tty(); | 
| 1726 | if (!tty) { | 1767 | if (!tty) { | 
| 1768 | unlock_kernel(); | ||
| 1727 | mutex_unlock(&tty_mutex); | 1769 | mutex_unlock(&tty_mutex); | 
| 1728 | return -ENXIO; | 1770 | return -ENXIO; | 
| 1729 | } | 1771 | } | 
| @@ -1755,12 +1797,14 @@ retry_open: | |||
| 1755 | goto got_driver; | 1797 | goto got_driver; | 
| 1756 | } | 1798 | } | 
| 1757 | } | 1799 | } | 
| 1800 | unlock_kernel(); | ||
| 1758 | mutex_unlock(&tty_mutex); | 1801 | mutex_unlock(&tty_mutex); | 
| 1759 | return -ENODEV; | 1802 | return -ENODEV; | 
| 1760 | } | 1803 | } | 
| 1761 | 1804 | ||
| 1762 | driver = get_tty_driver(device, &index); | 1805 | driver = get_tty_driver(device, &index); | 
| 1763 | if (!driver) { | 1806 | if (!driver) { | 
| 1807 | unlock_kernel(); | ||
| 1764 | mutex_unlock(&tty_mutex); | 1808 | mutex_unlock(&tty_mutex); | 
| 1765 | return -ENODEV; | 1809 | return -ENODEV; | 
| 1766 | } | 1810 | } | 
| @@ -1770,6 +1814,7 @@ got_driver: | |||
| 1770 | tty = tty_driver_lookup_tty(driver, inode, index); | 1814 | tty = tty_driver_lookup_tty(driver, inode, index); | 
| 1771 | 1815 | ||
| 1772 | if (IS_ERR(tty)) { | 1816 | if (IS_ERR(tty)) { | 
| 1817 | unlock_kernel(); | ||
| 1773 | mutex_unlock(&tty_mutex); | 1818 | mutex_unlock(&tty_mutex); | 
| 1774 | return PTR_ERR(tty); | 1819 | return PTR_ERR(tty); | 
| 1775 | } | 1820 | } | 
| @@ -1784,8 +1829,10 @@ got_driver: | |||
| 1784 | 1829 | ||
| 1785 | mutex_unlock(&tty_mutex); | 1830 | mutex_unlock(&tty_mutex); | 
| 1786 | tty_driver_kref_put(driver); | 1831 | tty_driver_kref_put(driver); | 
| 1787 | if (IS_ERR(tty)) | 1832 | if (IS_ERR(tty)) { | 
| 1833 | unlock_kernel(); | ||
| 1788 | return PTR_ERR(tty); | 1834 | return PTR_ERR(tty); | 
| 1835 | } | ||
| 1789 | 1836 | ||
| 1790 | filp->private_data = tty; | 1837 | filp->private_data = tty; | 
| 1791 | file_move(filp, &tty->tty_files); | 1838 | file_move(filp, &tty->tty_files); | 
| @@ -1813,11 +1860,15 @@ got_driver: | |||
| 1813 | printk(KERN_DEBUG "error %d in opening %s...", retval, | 1860 | printk(KERN_DEBUG "error %d in opening %s...", retval, | 
| 1814 | tty->name); | 1861 | tty->name); | 
| 1815 | #endif | 1862 | #endif | 
| 1816 | tty_release_dev(filp); | 1863 | tty_release(inode, filp); | 
| 1817 | if (retval != -ERESTARTSYS) | 1864 | if (retval != -ERESTARTSYS) { | 
| 1865 | unlock_kernel(); | ||
| 1818 | return retval; | 1866 | return retval; | 
| 1819 | if (signal_pending(current)) | 1867 | } | 
| 1868 | if (signal_pending(current)) { | ||
| 1869 | unlock_kernel(); | ||
| 1820 | return retval; | 1870 | return retval; | 
| 1871 | } | ||
| 1821 | schedule(); | 1872 | schedule(); | 
| 1822 | /* | 1873 | /* | 
| 1823 | * Need to reset f_op in case a hangup happened. | 1874 | * Need to reset f_op in case a hangup happened. | 
| @@ -1826,8 +1877,11 @@ got_driver: | |||
| 1826 | filp->f_op = &tty_fops; | 1877 | filp->f_op = &tty_fops; | 
| 1827 | goto retry_open; | 1878 | goto retry_open; | 
| 1828 | } | 1879 | } | 
| 1880 | unlock_kernel(); | ||
| 1881 | |||
| 1829 | 1882 | ||
| 1830 | mutex_lock(&tty_mutex); | 1883 | mutex_lock(&tty_mutex); | 
| 1884 | lock_kernel(); | ||
| 1831 | spin_lock_irq(¤t->sighand->siglock); | 1885 | spin_lock_irq(¤t->sighand->siglock); | 
| 1832 | if (!noctty && | 1886 | if (!noctty && | 
| 1833 | current->signal->leader && | 1887 | current->signal->leader && | 
| @@ -1835,43 +1889,12 @@ got_driver: | |||
| 1835 | tty->session == NULL) | 1889 | tty->session == NULL) | 
| 1836 | __proc_set_tty(current, tty); | 1890 | __proc_set_tty(current, tty); | 
| 1837 | spin_unlock_irq(¤t->sighand->siglock); | 1891 | spin_unlock_irq(¤t->sighand->siglock); | 
| 1892 | unlock_kernel(); | ||
| 1838 | mutex_unlock(&tty_mutex); | 1893 | mutex_unlock(&tty_mutex); | 
| 1839 | return 0; | 1894 | return 0; | 
| 1840 | } | 1895 | } | 
| 1841 | 1896 | ||
| 1842 | /* BKL pushdown: scary code avoidance wrapper */ | ||
| 1843 | static int tty_open(struct inode *inode, struct file *filp) | ||
| 1844 | { | ||
| 1845 | int ret; | ||
| 1846 | |||
| 1847 | lock_kernel(); | ||
| 1848 | ret = __tty_open(inode, filp); | ||
| 1849 | unlock_kernel(); | ||
| 1850 | return ret; | ||
| 1851 | } | ||
| 1852 | |||
| 1853 | |||
| 1854 | |||
| 1855 | |||
| 1856 | /** | ||
| 1857 | * tty_release - vfs callback for close | ||
| 1858 | * @inode: inode of tty | ||
| 1859 | * @filp: file pointer for handle to tty | ||
| 1860 | * | ||
| 1861 | * Called the last time each file handle is closed that references | ||
| 1862 | * this tty. There may however be several such references. | ||
| 1863 | * | ||
| 1864 | * Locking: | ||
| 1865 | * Takes bkl. See tty_release_dev | ||
| 1866 | */ | ||
| 1867 | 1897 | ||
| 1868 | static int tty_release(struct inode *inode, struct file *filp) | ||
| 1869 | { | ||
| 1870 | lock_kernel(); | ||
| 1871 | tty_release_dev(filp); | ||
| 1872 | unlock_kernel(); | ||
| 1873 | return 0; | ||
| 1874 | } | ||
| 1875 | 1898 | ||
| 1876 | /** | 1899 | /** | 
| 1877 | * tty_poll - check tty status | 1900 | * tty_poll - check tty status | 
| @@ -2317,9 +2340,7 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) | |||
| 2317 | if (get_user(ldisc, p)) | 2340 | if (get_user(ldisc, p)) | 
| 2318 | return -EFAULT; | 2341 | return -EFAULT; | 
| 2319 | 2342 | ||
| 2320 | lock_kernel(); | ||
| 2321 | ret = tty_set_ldisc(tty, ldisc); | 2343 | ret = tty_set_ldisc(tty, ldisc); | 
| 2322 | unlock_kernel(); | ||
| 2323 | 2344 | ||
| 2324 | return ret; | 2345 | return ret; | 
| 2325 | } | 2346 | } | 
| diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index feb55075819b..3f653f7d849f 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c | |||
| @@ -34,6 +34,8 @@ | |||
| 34 | #include <linux/vt_kern.h> | 34 | #include <linux/vt_kern.h> | 
| 35 | #include <linux/selection.h> | 35 | #include <linux/selection.h> | 
| 36 | 36 | ||
| 37 | #include <linux/smp_lock.h> /* For the moment */ | ||
| 38 | |||
| 37 | #include <linux/kmod.h> | 39 | #include <linux/kmod.h> | 
| 38 | #include <linux/nsproxy.h> | 40 | #include <linux/nsproxy.h> | 
| 39 | 41 | ||
| @@ -443,8 +445,14 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | |||
| 443 | static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) | 445 | static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) | 
| 444 | { | 446 | { | 
| 445 | WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); | 447 | WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); | 
| 446 | if (ld->ops->open) | 448 | if (ld->ops->open) { | 
| 447 | return ld->ops->open(tty); | 449 | int ret; | 
| 450 | /* BKL here locks verus a hangup event */ | ||
| 451 | lock_kernel(); | ||
| 452 | ret = ld->ops->open(tty); | ||
| 453 | unlock_kernel(); | ||
| 454 | return ret; | ||
| 455 | } | ||
| 448 | return 0; | 456 | return 0; | 
| 449 | } | 457 | } | 
| 450 | 458 | ||
| @@ -545,6 +553,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 545 | if (IS_ERR(new_ldisc)) | 553 | if (IS_ERR(new_ldisc)) | 
| 546 | return PTR_ERR(new_ldisc); | 554 | return PTR_ERR(new_ldisc); | 
| 547 | 555 | ||
| 556 | lock_kernel(); | ||
| 548 | /* | 557 | /* | 
| 549 | * We need to look at the tty locking here for pty/tty pairs | 558 | * We need to look at the tty locking here for pty/tty pairs | 
| 550 | * when both sides try to change in parallel. | 559 | * when both sides try to change in parallel. | 
| @@ -558,10 +567,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 558 | */ | 567 | */ | 
| 559 | 568 | ||
| 560 | if (tty->ldisc->ops->num == ldisc) { | 569 | if (tty->ldisc->ops->num == ldisc) { | 
| 570 | unlock_kernel(); | ||
| 561 | tty_ldisc_put(new_ldisc); | 571 | tty_ldisc_put(new_ldisc); | 
| 562 | return 0; | 572 | return 0; | 
| 563 | } | 573 | } | 
| 564 | 574 | ||
| 575 | unlock_kernel(); | ||
| 565 | /* | 576 | /* | 
| 566 | * Problem: What do we do if this blocks ? | 577 | * Problem: What do we do if this blocks ? | 
| 567 | * We could deadlock here | 578 | * We could deadlock here | 
| @@ -582,6 +593,9 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 582 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); | 593 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); | 
| 583 | mutex_lock(&tty->ldisc_mutex); | 594 | mutex_lock(&tty->ldisc_mutex); | 
| 584 | } | 595 | } | 
| 596 | |||
| 597 | lock_kernel(); | ||
| 598 | |||
| 585 | set_bit(TTY_LDISC_CHANGING, &tty->flags); | 599 | set_bit(TTY_LDISC_CHANGING, &tty->flags); | 
| 586 | 600 | ||
| 587 | /* | 601 | /* | 
| @@ -592,6 +606,8 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 592 | tty->receive_room = 0; | 606 | tty->receive_room = 0; | 
| 593 | 607 | ||
| 594 | o_ldisc = tty->ldisc; | 608 | o_ldisc = tty->ldisc; | 
| 609 | |||
| 610 | unlock_kernel(); | ||
| 595 | /* | 611 | /* | 
| 596 | * Make sure we don't change while someone holds a | 612 | * Make sure we don't change while someone holds a | 
| 597 | * reference to the line discipline. The TTY_LDISC bit | 613 | * reference to the line discipline. The TTY_LDISC bit | 
| @@ -617,12 +633,14 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 617 | flush_scheduled_work(); | 633 | flush_scheduled_work(); | 
| 618 | 634 | ||
| 619 | mutex_lock(&tty->ldisc_mutex); | 635 | mutex_lock(&tty->ldisc_mutex); | 
| 636 | lock_kernel(); | ||
| 620 | if (test_bit(TTY_HUPPED, &tty->flags)) { | 637 | if (test_bit(TTY_HUPPED, &tty->flags)) { | 
| 621 | /* We were raced by the hangup method. It will have stomped | 638 | /* We were raced by the hangup method. It will have stomped | 
| 622 | the ldisc data and closed the ldisc down */ | 639 | the ldisc data and closed the ldisc down */ | 
| 623 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | 640 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | 
| 624 | mutex_unlock(&tty->ldisc_mutex); | 641 | mutex_unlock(&tty->ldisc_mutex); | 
| 625 | tty_ldisc_put(new_ldisc); | 642 | tty_ldisc_put(new_ldisc); | 
| 643 | unlock_kernel(); | ||
| 626 | return -EIO; | 644 | return -EIO; | 
| 627 | } | 645 | } | 
| 628 | 646 | ||
| @@ -664,6 +682,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 664 | if (o_work) | 682 | if (o_work) | 
| 665 | schedule_delayed_work(&o_tty->buf.work, 1); | 683 | schedule_delayed_work(&o_tty->buf.work, 1); | 
| 666 | mutex_unlock(&tty->ldisc_mutex); | 684 | mutex_unlock(&tty->ldisc_mutex); | 
| 685 | unlock_kernel(); | ||
| 667 | return retval; | 686 | return retval; | 
| 668 | } | 687 | } | 
| 669 | 688 | ||
| diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index c63f3d33914a..be492dd66437 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c | |||
| @@ -25,19 +25,21 @@ void tty_port_init(struct tty_port *port) | |||
| 25 | init_waitqueue_head(&port->close_wait); | 25 | init_waitqueue_head(&port->close_wait); | 
| 26 | init_waitqueue_head(&port->delta_msr_wait); | 26 | init_waitqueue_head(&port->delta_msr_wait); | 
| 27 | mutex_init(&port->mutex); | 27 | mutex_init(&port->mutex); | 
| 28 | mutex_init(&port->buf_mutex); | ||
| 28 | spin_lock_init(&port->lock); | 29 | spin_lock_init(&port->lock); | 
| 29 | port->close_delay = (50 * HZ) / 100; | 30 | port->close_delay = (50 * HZ) / 100; | 
| 30 | port->closing_wait = (3000 * HZ) / 100; | 31 | port->closing_wait = (3000 * HZ) / 100; | 
| 32 | kref_init(&port->kref); | ||
| 31 | } | 33 | } | 
| 32 | EXPORT_SYMBOL(tty_port_init); | 34 | EXPORT_SYMBOL(tty_port_init); | 
| 33 | 35 | ||
| 34 | int tty_port_alloc_xmit_buf(struct tty_port *port) | 36 | int tty_port_alloc_xmit_buf(struct tty_port *port) | 
| 35 | { | 37 | { | 
| 36 | /* We may sleep in get_zeroed_page() */ | 38 | /* We may sleep in get_zeroed_page() */ | 
| 37 | mutex_lock(&port->mutex); | 39 | mutex_lock(&port->buf_mutex); | 
| 38 | if (port->xmit_buf == NULL) | 40 | if (port->xmit_buf == NULL) | 
| 39 | port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); | 41 | port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); | 
| 40 | mutex_unlock(&port->mutex); | 42 | mutex_unlock(&port->buf_mutex); | 
| 41 | if (port->xmit_buf == NULL) | 43 | if (port->xmit_buf == NULL) | 
| 42 | return -ENOMEM; | 44 | return -ENOMEM; | 
| 43 | return 0; | 45 | return 0; | 
| @@ -46,15 +48,32 @@ EXPORT_SYMBOL(tty_port_alloc_xmit_buf); | |||
| 46 | 48 | ||
| 47 | void tty_port_free_xmit_buf(struct tty_port *port) | 49 | void tty_port_free_xmit_buf(struct tty_port *port) | 
| 48 | { | 50 | { | 
| 49 | mutex_lock(&port->mutex); | 51 | mutex_lock(&port->buf_mutex); | 
| 50 | if (port->xmit_buf != NULL) { | 52 | if (port->xmit_buf != NULL) { | 
| 51 | free_page((unsigned long)port->xmit_buf); | 53 | free_page((unsigned long)port->xmit_buf); | 
| 52 | port->xmit_buf = NULL; | 54 | port->xmit_buf = NULL; | 
| 53 | } | 55 | } | 
| 54 | mutex_unlock(&port->mutex); | 56 | mutex_unlock(&port->buf_mutex); | 
| 55 | } | 57 | } | 
| 56 | EXPORT_SYMBOL(tty_port_free_xmit_buf); | 58 | EXPORT_SYMBOL(tty_port_free_xmit_buf); | 
| 57 | 59 | ||
| 60 | static void tty_port_destructor(struct kref *kref) | ||
| 61 | { | ||
| 62 | struct tty_port *port = container_of(kref, struct tty_port, kref); | ||
| 63 | if (port->xmit_buf) | ||
| 64 | free_page((unsigned long)port->xmit_buf); | ||
| 65 | if (port->ops->destruct) | ||
| 66 | port->ops->destruct(port); | ||
| 67 | else | ||
| 68 | kfree(port); | ||
| 69 | } | ||
| 70 | |||
| 71 | void tty_port_put(struct tty_port *port) | ||
| 72 | { | ||
| 73 | if (port) | ||
| 74 | kref_put(&port->kref, tty_port_destructor); | ||
| 75 | } | ||
| 76 | EXPORT_SYMBOL(tty_port_put); | ||
| 58 | 77 | ||
| 59 | /** | 78 | /** | 
| 60 | * tty_port_tty_get - get a tty reference | 79 | * tty_port_tty_get - get a tty reference | 
| @@ -99,10 +118,11 @@ EXPORT_SYMBOL(tty_port_tty_set); | |||
| 99 | 118 | ||
| 100 | static void tty_port_shutdown(struct tty_port *port) | 119 | static void tty_port_shutdown(struct tty_port *port) | 
| 101 | { | 120 | { | 
| 121 | mutex_lock(&port->mutex); | ||
| 102 | if (port->ops->shutdown && | 122 | if (port->ops->shutdown && | 
| 103 | test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) | 123 | test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) | 
| 104 | port->ops->shutdown(port); | 124 | port->ops->shutdown(port); | 
| 105 | 125 | mutex_unlock(&port->mutex); | |
| 106 | } | 126 | } | 
| 107 | 127 | ||
| 108 | /** | 128 | /** | 
| @@ -120,8 +140,10 @@ void tty_port_hangup(struct tty_port *port) | |||
| 120 | spin_lock_irqsave(&port->lock, flags); | 140 | spin_lock_irqsave(&port->lock, flags); | 
| 121 | port->count = 0; | 141 | port->count = 0; | 
| 122 | port->flags &= ~ASYNC_NORMAL_ACTIVE; | 142 | port->flags &= ~ASYNC_NORMAL_ACTIVE; | 
| 123 | if (port->tty) | 143 | if (port->tty) { | 
| 144 | set_bit(TTY_IO_ERROR, &port->tty->flags); | ||
| 124 | tty_kref_put(port->tty); | 145 | tty_kref_put(port->tty); | 
| 146 | } | ||
| 125 | port->tty = NULL; | 147 | port->tty = NULL; | 
| 126 | spin_unlock_irqrestore(&port->lock, flags); | 148 | spin_unlock_irqrestore(&port->lock, flags); | 
| 127 | wake_up_interruptible(&port->open_wait); | 149 | wake_up_interruptible(&port->open_wait); | 
| @@ -198,7 +220,7 @@ EXPORT_SYMBOL(tty_port_lower_dtr_rts); | |||
| 198 | * management of these lines. Note that the dtr/rts raise is done each | 220 | * management of these lines. Note that the dtr/rts raise is done each | 
| 199 | * iteration as a hangup may have previously dropped them while we wait. | 221 | * iteration as a hangup may have previously dropped them while we wait. | 
| 200 | */ | 222 | */ | 
| 201 | 223 | ||
| 202 | int tty_port_block_til_ready(struct tty_port *port, | 224 | int tty_port_block_til_ready(struct tty_port *port, | 
| 203 | struct tty_struct *tty, struct file *filp) | 225 | struct tty_struct *tty, struct file *filp) | 
| 204 | { | 226 | { | 
| @@ -253,7 +275,8 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
| 253 | tty_port_raise_dtr_rts(port); | 275 | tty_port_raise_dtr_rts(port); | 
| 254 | 276 | ||
| 255 | prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE); | 277 | prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE); | 
| 256 | /* Check for a hangup or uninitialised port. Return accordingly */ | 278 | /* Check for a hangup or uninitialised port. | 
| 279 | Return accordingly */ | ||
| 257 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { | 280 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { | 
| 258 | if (port->flags & ASYNC_HUP_NOTIFY) | 281 | if (port->flags & ASYNC_HUP_NOTIFY) | 
| 259 | retval = -EAGAIN; | 282 | retval = -EAGAIN; | 
| @@ -285,11 +308,11 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
| 285 | port->flags |= ASYNC_NORMAL_ACTIVE; | 308 | port->flags |= ASYNC_NORMAL_ACTIVE; | 
| 286 | spin_unlock_irqrestore(&port->lock, flags); | 309 | spin_unlock_irqrestore(&port->lock, flags); | 
| 287 | return retval; | 310 | return retval; | 
| 288 | |||
| 289 | } | 311 | } | 
| 290 | EXPORT_SYMBOL(tty_port_block_til_ready); | 312 | EXPORT_SYMBOL(tty_port_block_til_ready); | 
| 291 | 313 | ||
| 292 | int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct file *filp) | 314 | int tty_port_close_start(struct tty_port *port, | 
| 315 | struct tty_struct *tty, struct file *filp) | ||
| 293 | { | 316 | { | 
| 294 | unsigned long flags; | 317 | unsigned long flags; | 
| 295 | 318 | ||
| @@ -299,7 +322,7 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f | |||
| 299 | return 0; | 322 | return 0; | 
| 300 | } | 323 | } | 
| 301 | 324 | ||
| 302 | if( tty->count == 1 && port->count != 1) { | 325 | if (tty->count == 1 && port->count != 1) { | 
| 303 | printk(KERN_WARNING | 326 | printk(KERN_WARNING | 
| 304 | "tty_port_close_start: tty->count = 1 port count = %d.\n", | 327 | "tty_port_close_start: tty->count = 1 port count = %d.\n", | 
| 305 | port->count); | 328 | port->count); | 
| @@ -331,12 +354,20 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f | |||
| 331 | long timeout; | 354 | long timeout; | 
| 332 | 355 | ||
| 333 | if (bps > 1200) | 356 | if (bps > 1200) | 
| 334 | timeout = max_t(long, (HZ * 10 * port->drain_delay) / bps, | 357 | timeout = max_t(long, | 
| 335 | HZ / 10); | 358 | (HZ * 10 * port->drain_delay) / bps, HZ / 10); | 
| 336 | else | 359 | else | 
| 337 | timeout = 2 * HZ; | 360 | timeout = 2 * HZ; | 
| 338 | schedule_timeout_interruptible(timeout); | 361 | schedule_timeout_interruptible(timeout); | 
| 339 | } | 362 | } | 
| 363 | /* Flush the ldisc buffering */ | ||
| 364 | tty_ldisc_flush(tty); | ||
| 365 | |||
| 366 | /* Drop DTR/RTS if HUPCL is set. This causes any attached modem to | ||
| 367 | hang up the line */ | ||
| 368 | if (tty->termios->c_cflag & HUPCL) | ||
| 369 | tty_port_lower_dtr_rts(port); | ||
| 370 | |||
| 340 | /* Don't call port->drop for the last reference. Callers will want | 371 | /* Don't call port->drop for the last reference. Callers will want | 
| 341 | to drop the last active reference in ->shutdown() or the tty | 372 | to drop the last active reference in ->shutdown() or the tty | 
| 342 | shutdown path */ | 373 | shutdown path */ | 
| @@ -348,11 +379,6 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty) | |||
| 348 | { | 379 | { | 
| 349 | unsigned long flags; | 380 | unsigned long flags; | 
| 350 | 381 | ||
| 351 | tty_ldisc_flush(tty); | ||
| 352 | |||
| 353 | if (tty->termios->c_cflag & HUPCL) | ||
| 354 | tty_port_lower_dtr_rts(port); | ||
| 355 | |||
| 356 | spin_lock_irqsave(&port->lock, flags); | 382 | spin_lock_irqsave(&port->lock, flags); | 
| 357 | tty->closing = 0; | 383 | tty->closing = 0; | 
| 358 | 384 | ||
| @@ -377,7 +403,42 @@ void tty_port_close(struct tty_port *port, struct tty_struct *tty, | |||
| 377 | if (tty_port_close_start(port, tty, filp) == 0) | 403 | if (tty_port_close_start(port, tty, filp) == 0) | 
| 378 | return; | 404 | return; | 
| 379 | tty_port_shutdown(port); | 405 | tty_port_shutdown(port); | 
| 406 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
| 380 | tty_port_close_end(port, tty); | 407 | tty_port_close_end(port, tty); | 
| 381 | tty_port_tty_set(port, NULL); | 408 | tty_port_tty_set(port, NULL); | 
| 382 | } | 409 | } | 
| 383 | EXPORT_SYMBOL(tty_port_close); | 410 | EXPORT_SYMBOL(tty_port_close); | 
| 411 | |||
| 412 | int tty_port_open(struct tty_port *port, struct tty_struct *tty, | ||
| 413 | struct file *filp) | ||
| 414 | { | ||
| 415 | spin_lock_irq(&port->lock); | ||
| 416 | if (!tty_hung_up_p(filp)) | ||
| 417 | ++port->count; | ||
| 418 | spin_unlock_irq(&port->lock); | ||
| 419 | tty_port_tty_set(port, tty); | ||
| 420 | |||
| 421 | /* | ||
| 422 | * Do the device-specific open only if the hardware isn't | ||
| 423 | * already initialized. Serialize open and shutdown using the | ||
| 424 | * port mutex. | ||
| 425 | */ | ||
| 426 | |||
| 427 | mutex_lock(&port->mutex); | ||
| 428 | |||
| 429 | if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) { | ||
| 430 | clear_bit(TTY_IO_ERROR, &tty->flags); | ||
| 431 | if (port->ops->activate) { | ||
| 432 | int retval = port->ops->activate(port, tty); | ||
| 433 | if (retval) { | ||
| 434 | mutex_unlock(&port->mutex); | ||
| 435 | return retval; | ||
| 436 | } | ||
| 437 | } | ||
| 438 | set_bit(ASYNCB_INITIALIZED, &port->flags); | ||
| 439 | } | ||
| 440 | mutex_unlock(&port->mutex); | ||
| 441 | return tty_port_block_til_ready(port, tty, filp); | ||
| 442 | } | ||
| 443 | |||
| 444 | EXPORT_SYMBOL(tty_port_open); | ||
| diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index b8e7c5ae981e..f53755533e7e 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/module.h> | 29 | #include <linux/module.h> | 
| 30 | #include <linux/init.h> | 30 | #include <linux/init.h> | 
| 31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> | 
| 32 | #include <linux/sched.h> | ||
| 32 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> | 
| 33 | #include <linux/seq_file.h> | 34 | #include <linux/seq_file.h> | 
| 34 | #include <linux/serial_reg.h> | 35 | #include <linux/serial_reg.h> | 
| @@ -73,11 +74,10 @@ struct uart_icount { | |||
| 73 | }; | 74 | }; | 
| 74 | 75 | ||
| 75 | struct sdio_uart_port { | 76 | struct sdio_uart_port { | 
| 77 | struct tty_port port; | ||
| 76 | struct kref kref; | 78 | struct kref kref; | 
| 77 | struct tty_struct *tty; | 79 | struct tty_struct *tty; | 
| 78 | unsigned int index; | 80 | unsigned int index; | 
| 79 | unsigned int opened; | ||
| 80 | struct mutex open_lock; | ||
| 81 | struct sdio_func *func; | 81 | struct sdio_func *func; | 
| 82 | struct mutex func_lock; | 82 | struct mutex func_lock; | 
| 83 | struct task_struct *in_sdio_uart_irq; | 83 | struct task_struct *in_sdio_uart_irq; | 
| @@ -87,6 +87,7 @@ struct sdio_uart_port { | |||
| 87 | struct uart_icount icount; | 87 | struct uart_icount icount; | 
| 88 | unsigned int uartclk; | 88 | unsigned int uartclk; | 
| 89 | unsigned int mctrl; | 89 | unsigned int mctrl; | 
| 90 | unsigned int rx_mctrl; | ||
| 90 | unsigned int read_status_mask; | 91 | unsigned int read_status_mask; | 
| 91 | unsigned int ignore_status_mask; | 92 | unsigned int ignore_status_mask; | 
| 92 | unsigned char x_char; | 93 | unsigned char x_char; | 
| @@ -102,7 +103,6 @@ static int sdio_uart_add_port(struct sdio_uart_port *port) | |||
| 102 | int index, ret = -EBUSY; | 103 | int index, ret = -EBUSY; | 
| 103 | 104 | ||
| 104 | kref_init(&port->kref); | 105 | kref_init(&port->kref); | 
| 105 | mutex_init(&port->open_lock); | ||
| 106 | mutex_init(&port->func_lock); | 106 | mutex_init(&port->func_lock); | 
| 107 | spin_lock_init(&port->write_lock); | 107 | spin_lock_init(&port->write_lock); | 
| 108 | 108 | ||
| @@ -151,6 +151,7 @@ static void sdio_uart_port_put(struct sdio_uart_port *port) | |||
| 151 | static void sdio_uart_port_remove(struct sdio_uart_port *port) | 151 | static void sdio_uart_port_remove(struct sdio_uart_port *port) | 
| 152 | { | 152 | { | 
| 153 | struct sdio_func *func; | 153 | struct sdio_func *func; | 
| 154 | struct tty_struct *tty; | ||
| 154 | 155 | ||
| 155 | BUG_ON(sdio_uart_table[port->index] != port); | 156 | BUG_ON(sdio_uart_table[port->index] != port); | 
| 156 | 157 | ||
| @@ -165,15 +166,19 @@ static void sdio_uart_port_remove(struct sdio_uart_port *port) | |||
| 165 | * give up on that port ASAP. | 166 | * give up on that port ASAP. | 
| 166 | * Beware: the lock ordering is critical. | 167 | * Beware: the lock ordering is critical. | 
| 167 | */ | 168 | */ | 
| 168 | mutex_lock(&port->open_lock); | 169 | mutex_lock(&port->port.mutex); | 
| 169 | mutex_lock(&port->func_lock); | 170 | mutex_lock(&port->func_lock); | 
| 170 | func = port->func; | 171 | func = port->func; | 
| 171 | sdio_claim_host(func); | 172 | sdio_claim_host(func); | 
| 172 | port->func = NULL; | 173 | port->func = NULL; | 
| 173 | mutex_unlock(&port->func_lock); | 174 | mutex_unlock(&port->func_lock); | 
| 174 | if (port->opened) | 175 | tty = tty_port_tty_get(&port->port); | 
| 175 | tty_hangup(port->tty); | 176 | /* tty_hangup is async so is this safe as is ?? */ | 
| 176 | mutex_unlock(&port->open_lock); | 177 | if (tty) { | 
| 178 | tty_hangup(tty); | ||
| 179 | tty_kref_put(tty); | ||
| 180 | } | ||
| 181 | mutex_unlock(&port->port.mutex); | ||
| 177 | sdio_release_irq(func); | 182 | sdio_release_irq(func); | 
| 178 | sdio_disable_func(func); | 183 | sdio_disable_func(func); | 
| 179 | sdio_release_host(func); | 184 | sdio_release_host(func); | 
| @@ -217,6 +222,8 @@ static unsigned int sdio_uart_get_mctrl(struct sdio_uart_port *port) | |||
| 217 | unsigned char status; | 222 | unsigned char status; | 
| 218 | unsigned int ret; | 223 | unsigned int ret; | 
| 219 | 224 | ||
| 225 | /* FIXME: What stops this losing the delta bits and breaking | ||
| 226 | sdio_uart_check_modem_status ? */ | ||
| 220 | status = sdio_in(port, UART_MSR); | 227 | status = sdio_in(port, UART_MSR); | 
| 221 | 228 | ||
| 222 | ret = 0; | 229 | ret = 0; | 
| @@ -391,7 +398,7 @@ static void sdio_uart_stop_rx(struct sdio_uart_port *port) | |||
| 391 | static void sdio_uart_receive_chars(struct sdio_uart_port *port, | 398 | static void sdio_uart_receive_chars(struct sdio_uart_port *port, | 
| 392 | unsigned int *status) | 399 | unsigned int *status) | 
| 393 | { | 400 | { | 
| 394 | struct tty_struct *tty = port->tty; | 401 | struct tty_struct *tty = tty_port_tty_get(&port->port); | 
| 395 | unsigned int ch, flag; | 402 | unsigned int ch, flag; | 
| 396 | int max_count = 256; | 403 | int max_count = 256; | 
| 397 | 404 | ||
| @@ -428,24 +435,30 @@ static void sdio_uart_receive_chars(struct sdio_uart_port *port, | |||
| 428 | } | 435 | } | 
| 429 | 436 | ||
| 430 | if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0) | 437 | if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0) | 
| 431 | tty_insert_flip_char(tty, ch, flag); | 438 | if (tty) | 
| 439 | tty_insert_flip_char(tty, ch, flag); | ||
| 432 | 440 | ||
| 433 | /* | 441 | /* | 
| 434 | * Overrun is special. Since it's reported immediately, | 442 | * Overrun is special. Since it's reported immediately, | 
| 435 | * it doesn't affect the current character. | 443 | * it doesn't affect the current character. | 
| 436 | */ | 444 | */ | 
| 437 | if (*status & ~port->ignore_status_mask & UART_LSR_OE) | 445 | if (*status & ~port->ignore_status_mask & UART_LSR_OE) | 
| 438 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | 446 | if (tty) | 
| 447 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
| 439 | 448 | ||
| 440 | *status = sdio_in(port, UART_LSR); | 449 | *status = sdio_in(port, UART_LSR); | 
| 441 | } while ((*status & UART_LSR_DR) && (max_count-- > 0)); | 450 | } while ((*status & UART_LSR_DR) && (max_count-- > 0)); | 
| 442 | tty_flip_buffer_push(tty); | 451 | if (tty) { | 
| 452 | tty_flip_buffer_push(tty); | ||
| 453 | tty_kref_put(tty); | ||
| 454 | } | ||
| 443 | } | 455 | } | 
| 444 | 456 | ||
| 445 | static void sdio_uart_transmit_chars(struct sdio_uart_port *port) | 457 | static void sdio_uart_transmit_chars(struct sdio_uart_port *port) | 
| 446 | { | 458 | { | 
| 447 | struct circ_buf *xmit = &port->xmit; | 459 | struct circ_buf *xmit = &port->xmit; | 
| 448 | int count; | 460 | int count; | 
| 461 | struct tty_struct *tty; | ||
| 449 | 462 | ||
| 450 | if (port->x_char) { | 463 | if (port->x_char) { | 
| 451 | sdio_out(port, UART_TX, port->x_char); | 464 | sdio_out(port, UART_TX, port->x_char); | 
| @@ -453,8 +466,13 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port) | |||
| 453 | port->x_char = 0; | 466 | port->x_char = 0; | 
| 454 | return; | 467 | return; | 
| 455 | } | 468 | } | 
| 456 | if (circ_empty(xmit) || port->tty->stopped || port->tty->hw_stopped) { | 469 | |
| 470 | tty = tty_port_tty_get(&port->port); | ||
| 471 | |||
| 472 | if (tty == NULL || circ_empty(xmit) || | ||
| 473 | tty->stopped || tty->hw_stopped) { | ||
| 457 | sdio_uart_stop_tx(port); | 474 | sdio_uart_stop_tx(port); | 
| 475 | tty_kref_put(tty); | ||
| 458 | return; | 476 | return; | 
| 459 | } | 477 | } | 
| 460 | 478 | ||
| @@ -468,15 +486,17 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port) | |||
| 468 | } while (--count > 0); | 486 | } while (--count > 0); | 
| 469 | 487 | ||
| 470 | if (circ_chars_pending(xmit) < WAKEUP_CHARS) | 488 | if (circ_chars_pending(xmit) < WAKEUP_CHARS) | 
| 471 | tty_wakeup(port->tty); | 489 | tty_wakeup(tty); | 
| 472 | 490 | ||
| 473 | if (circ_empty(xmit)) | 491 | if (circ_empty(xmit)) | 
| 474 | sdio_uart_stop_tx(port); | 492 | sdio_uart_stop_tx(port); | 
| 493 | tty_kref_put(tty); | ||
| 475 | } | 494 | } | 
| 476 | 495 | ||
| 477 | static void sdio_uart_check_modem_status(struct sdio_uart_port *port) | 496 | static void sdio_uart_check_modem_status(struct sdio_uart_port *port) | 
| 478 | { | 497 | { | 
| 479 | int status; | 498 | int status; | 
| 499 | struct tty_struct *tty; | ||
| 480 | 500 | ||
| 481 | status = sdio_in(port, UART_MSR); | 501 | status = sdio_in(port, UART_MSR); | 
| 482 | 502 | ||
| @@ -487,25 +507,39 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port) | |||
| 487 | port->icount.rng++; | 507 | port->icount.rng++; | 
| 488 | if (status & UART_MSR_DDSR) | 508 | if (status & UART_MSR_DDSR) | 
| 489 | port->icount.dsr++; | 509 | port->icount.dsr++; | 
| 490 | if (status & UART_MSR_DDCD) | 510 | if (status & UART_MSR_DDCD) { | 
| 491 | port->icount.dcd++; | 511 | port->icount.dcd++; | 
| 512 | /* DCD raise - wake for open */ | ||
| 513 | if (status & UART_MSR_DCD) | ||
| 514 | wake_up_interruptible(&port->port.open_wait); | ||
| 515 | else { | ||
| 516 | /* DCD drop - hang up if tty attached */ | ||
| 517 | tty = tty_port_tty_get(&port->port); | ||
| 518 | if (tty) { | ||
| 519 | tty_hangup(tty); | ||
| 520 | tty_kref_put(tty); | ||
| 521 | } | ||
| 522 | } | ||
| 523 | } | ||
| 492 | if (status & UART_MSR_DCTS) { | 524 | if (status & UART_MSR_DCTS) { | 
| 493 | port->icount.cts++; | 525 | port->icount.cts++; | 
| 494 | if (port->tty->termios->c_cflag & CRTSCTS) { | 526 | tty = tty_port_tty_get(&port->port); | 
| 527 | if (tty && (tty->termios->c_cflag & CRTSCTS)) { | ||
| 495 | int cts = (status & UART_MSR_CTS); | 528 | int cts = (status & UART_MSR_CTS); | 
| 496 | if (port->tty->hw_stopped) { | 529 | if (tty->hw_stopped) { | 
| 497 | if (cts) { | 530 | if (cts) { | 
| 498 | port->tty->hw_stopped = 0; | 531 | tty->hw_stopped = 0; | 
| 499 | sdio_uart_start_tx(port); | 532 | sdio_uart_start_tx(port); | 
| 500 | tty_wakeup(port->tty); | 533 | tty_wakeup(tty); | 
| 501 | } | 534 | } | 
| 502 | } else { | 535 | } else { | 
| 503 | if (!cts) { | 536 | if (!cts) { | 
| 504 | port->tty->hw_stopped = 1; | 537 | tty->hw_stopped = 1; | 
| 505 | sdio_uart_stop_tx(port); | 538 | sdio_uart_stop_tx(port); | 
| 506 | } | 539 | } | 
| 507 | } | 540 | } | 
| 508 | } | 541 | } | 
| 542 | tty_kref_put(tty); | ||
| 509 | } | 543 | } | 
| 510 | } | 544 | } | 
| 511 | 545 | ||
| @@ -542,8 +576,62 @@ static void sdio_uart_irq(struct sdio_func *func) | |||
| 542 | port->in_sdio_uart_irq = NULL; | 576 | port->in_sdio_uart_irq = NULL; | 
| 543 | } | 577 | } | 
| 544 | 578 | ||
| 545 | static int sdio_uart_startup(struct sdio_uart_port *port) | 579 | static int uart_carrier_raised(struct tty_port *tport) | 
| 580 | { | ||
| 581 | struct sdio_uart_port *port = | ||
| 582 | container_of(tport, struct sdio_uart_port, port); | ||
| 583 | unsigned int ret = sdio_uart_claim_func(port); | ||
| 584 | if (ret) /* Missing hardware shoudn't block for carrier */ | ||
| 585 | return 1; | ||
| 586 | ret = sdio_uart_get_mctrl(port); | ||
| 587 | sdio_uart_release_func(port); | ||
| 588 | if (ret & TIOCM_CAR) | ||
| 589 | return 1; | ||
| 590 | return 0; | ||
| 591 | } | ||
| 592 | |||
| 593 | /** | ||
| 594 | * uart_dtr_rts - port helper to set uart signals | ||
| 595 | * @tport: tty port to be updated | ||
| 596 | * @onoff: set to turn on DTR/RTS | ||
| 597 | * | ||
| 598 | * Called by the tty port helpers when the modem signals need to be | ||
| 599 | * adjusted during an open, close and hangup. | ||
| 600 | */ | ||
| 601 | |||
| 602 | static void uart_dtr_rts(struct tty_port *tport, int onoff) | ||
| 603 | { | ||
| 604 | struct sdio_uart_port *port = | ||
| 605 | container_of(tport, struct sdio_uart_port, port); | ||
| 606 | int ret = sdio_uart_claim_func(port); | ||
| 607 | if (ret) | ||
| 608 | return; | ||
| 609 | if (onoff == 0) | ||
| 610 | sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
| 611 | else | ||
| 612 | sdio_uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
| 613 | sdio_uart_release_func(port); | ||
| 614 | } | ||
| 615 | |||
| 616 | /** | ||
| 617 | * sdio_uart_activate - start up hardware | ||
| 618 | * @tport: tty port to activate | ||
| 619 | * @tty: tty bound to this port | ||
| 620 | * | ||
| 621 | * Activate a tty port. The port locking guarantees us this will be | ||
| 622 | * run exactly once per set of opens, and if successful will see the | ||
| 623 | * shutdown method run exactly once to match. Start up and shutdown are | ||
| 624 | * protected from each other by the internal locking and will not run | ||
| 625 | * at the same time even during a hangup event. | ||
| 626 | * | ||
| 627 | * If we successfully start up the port we take an extra kref as we | ||
| 628 | * will keep it around until shutdown when the kref is dropped. | ||
| 629 | */ | ||
| 630 | |||
| 631 | static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) | ||
| 546 | { | 632 | { | 
| 633 | struct sdio_uart_port *port = | ||
| 634 | container_of(tport, struct sdio_uart_port, port); | ||
| 547 | unsigned long page; | 635 | unsigned long page; | 
| 548 | int ret; | 636 | int ret; | 
| 549 | 637 | ||
| @@ -551,7 +639,7 @@ static int sdio_uart_startup(struct sdio_uart_port *port) | |||
| 551 | * Set the TTY IO error marker - we will only clear this | 639 | * Set the TTY IO error marker - we will only clear this | 
| 552 | * once we have successfully opened the port. | 640 | * once we have successfully opened the port. | 
| 553 | */ | 641 | */ | 
| 554 | set_bit(TTY_IO_ERROR, &port->tty->flags); | 642 | set_bit(TTY_IO_ERROR, &tty->flags); | 
| 555 | 643 | ||
| 556 | /* Initialise and allocate the transmit buffer. */ | 644 | /* Initialise and allocate the transmit buffer. */ | 
| 557 | page = __get_free_page(GFP_KERNEL); | 645 | page = __get_free_page(GFP_KERNEL); | 
| @@ -592,19 +680,19 @@ static int sdio_uart_startup(struct sdio_uart_port *port) | |||
| 592 | */ | 680 | */ | 
| 593 | sdio_out(port, UART_LCR, UART_LCR_WLEN8); | 681 | sdio_out(port, UART_LCR, UART_LCR_WLEN8); | 
| 594 | 682 | ||
| 595 | port->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE; | 683 | port->ier = UART_IER_RLSI|UART_IER_RDI|UART_IER_RTOIE|UART_IER_UUE; | 
| 596 | port->mctrl = TIOCM_OUT2; | 684 | port->mctrl = TIOCM_OUT2; | 
| 597 | 685 | ||
| 598 | sdio_uart_change_speed(port, port->tty->termios, NULL); | 686 | sdio_uart_change_speed(port, tty->termios, NULL); | 
| 599 | 687 | ||
| 600 | if (port->tty->termios->c_cflag & CBAUD) | 688 | if (tty->termios->c_cflag & CBAUD) | 
| 601 | sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); | 689 | sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); | 
| 602 | 690 | ||
| 603 | if (port->tty->termios->c_cflag & CRTSCTS) | 691 | if (tty->termios->c_cflag & CRTSCTS) | 
| 604 | if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) | 692 | if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) | 
| 605 | port->tty->hw_stopped = 1; | 693 | tty->hw_stopped = 1; | 
| 606 | 694 | ||
| 607 | clear_bit(TTY_IO_ERROR, &port->tty->flags); | 695 | clear_bit(TTY_IO_ERROR, &tty->flags); | 
| 608 | 696 | ||
| 609 | /* Kick the IRQ handler once while we're still holding the host lock */ | 697 | /* Kick the IRQ handler once while we're still holding the host lock */ | 
| 610 | sdio_uart_irq(port->func); | 698 | sdio_uart_irq(port->func); | 
| @@ -621,8 +709,20 @@ err1: | |||
| 621 | return ret; | 709 | return ret; | 
| 622 | } | 710 | } | 
| 623 | 711 | ||
| 624 | static void sdio_uart_shutdown(struct sdio_uart_port *port) | 712 | /** | 
| 713 | * sdio_uart_shutdown - stop hardware | ||
| 714 | * @tport: tty port to shut down | ||
| 715 | * | ||
| 716 | * Deactivate a tty port. The port locking guarantees us this will be | ||
| 717 | * run only if a successful matching activate already ran. The two are | ||
| 718 | * protected from each other by the internal locking and will not run | ||
| 719 | * at the same time even during a hangup event. | ||
| 720 | */ | ||
| 721 | |||
| 722 | static void sdio_uart_shutdown(struct tty_port *tport) | ||
| 625 | { | 723 | { | 
| 724 | struct sdio_uart_port *port = | ||
| 725 | container_of(tport, struct sdio_uart_port, port); | ||
| 626 | int ret; | 726 | int ret; | 
| 627 | 727 | ||
| 628 | ret = sdio_uart_claim_func(port); | 728 | ret = sdio_uart_claim_func(port); | 
| @@ -631,12 +731,6 @@ static void sdio_uart_shutdown(struct sdio_uart_port *port) | |||
| 631 | 731 | ||
| 632 | sdio_uart_stop_rx(port); | 732 | sdio_uart_stop_rx(port); | 
| 633 | 733 | ||
| 634 | /* TODO: wait here for TX FIFO to drain */ | ||
| 635 | |||
| 636 | /* Turn off DTR and RTS early. */ | ||
| 637 | if (port->tty->termios->c_cflag & HUPCL) | ||
| 638 | sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
| 639 | |||
| 640 | /* Disable interrupts from this port */ | 734 | /* Disable interrupts from this port */ | 
| 641 | sdio_release_irq(port->func); | 735 | sdio_release_irq(port->func); | 
| 642 | port->ier = 0; | 736 | port->ier = 0; | 
| @@ -661,77 +755,70 @@ skip: | |||
| 661 | free_page((unsigned long)port->xmit.buf); | 755 | free_page((unsigned long)port->xmit.buf); | 
| 662 | } | 756 | } | 
| 663 | 757 | ||
| 664 | static int sdio_uart_open(struct tty_struct *tty, struct file *filp) | 758 | /** | 
| 759 | * sdio_uart_install - install method | ||
| 760 | * @driver: the driver in use (sdio_uart in our case) | ||
| 761 | * @tty: the tty being bound | ||
| 762 | * | ||
| 763 | * Look up and bind the tty and the driver together. Initialize | ||
| 764 | * any needed private data (in our case the termios) | ||
| 765 | */ | ||
| 766 | |||
| 767 | static int sdio_uart_install(struct tty_driver *driver, struct tty_struct *tty) | ||
| 665 | { | 768 | { | 
| 666 | struct sdio_uart_port *port; | 769 | int idx = tty->index; | 
| 667 | int ret; | 770 | struct sdio_uart_port *port = sdio_uart_port_get(idx); | 
| 771 | int ret = tty_init_termios(tty); | ||
| 772 | |||
| 773 | if (ret == 0) { | ||
| 774 | tty_driver_kref_get(driver); | ||
| 775 | tty->count++; | ||
| 776 | /* This is the ref sdio_uart_port get provided */ | ||
| 777 | tty->driver_data = port; | ||
| 778 | driver->ttys[idx] = tty; | ||
| 779 | } else | ||
| 780 | sdio_uart_port_put(port); | ||
| 781 | return ret; | ||
| 782 | } | ||
| 668 | 783 | ||
| 669 | port = sdio_uart_port_get(tty->index); | 784 | /** | 
| 670 | if (!port) | 785 | * sdio_uart_cleanup - called on the last tty kref drop | 
| 671 | return -ENODEV; | 786 | * @tty: the tty being destroyed | 
| 787 | * | ||
| 788 | * Called asynchronously when the last reference to the tty is dropped. | ||
| 789 | * We cannot destroy the tty->driver_data port kref until this point | ||
| 790 | */ | ||
| 672 | 791 | ||
| 673 | mutex_lock(&port->open_lock); | 792 | static void sdio_uart_cleanup(struct tty_struct *tty) | 
| 793 | { | ||
| 794 | struct sdio_uart_port *port = tty->driver_data; | ||
| 795 | tty->driver_data = NULL; /* Bug trap */ | ||
| 796 | sdio_uart_port_put(port); | ||
| 797 | } | ||
| 674 | 798 | ||
| 675 | /* | 799 | /* | 
| 676 | * Make sure not to mess up with a dead port | 800 | * Open/close/hangup is now entirely boilerplate | 
| 677 | * which has not been closed yet. | 801 | */ | 
| 678 | */ | ||
| 679 | if (tty->driver_data && tty->driver_data != port) { | ||
| 680 | mutex_unlock(&port->open_lock); | ||
| 681 | sdio_uart_port_put(port); | ||
| 682 | return -EBUSY; | ||
| 683 | } | ||
| 684 | 802 | ||
| 685 | if (!port->opened) { | 803 | static int sdio_uart_open(struct tty_struct *tty, struct file *filp) | 
| 686 | tty->driver_data = port; | 804 | { | 
| 687 | port->tty = tty; | 805 | struct sdio_uart_port *port = tty->driver_data; | 
| 688 | ret = sdio_uart_startup(port); | 806 | return tty_port_open(&port->port, tty, filp); | 
| 689 | if (ret) { | ||
| 690 | tty->driver_data = NULL; | ||
| 691 | port->tty = NULL; | ||
| 692 | mutex_unlock(&port->open_lock); | ||
| 693 | sdio_uart_port_put(port); | ||
| 694 | return ret; | ||
| 695 | } | ||
| 696 | } | ||
| 697 | port->opened++; | ||
| 698 | mutex_unlock(&port->open_lock); | ||
| 699 | return 0; | ||
| 700 | } | 807 | } | 
| 701 | 808 | ||
| 702 | static void sdio_uart_close(struct tty_struct *tty, struct file * filp) | 809 | static void sdio_uart_close(struct tty_struct *tty, struct file * filp) | 
| 703 | { | 810 | { | 
| 704 | struct sdio_uart_port *port = tty->driver_data; | 811 | struct sdio_uart_port *port = tty->driver_data; | 
| 812 | tty_port_close(&port->port, tty, filp); | ||
| 813 | } | ||
| 705 | 814 | ||
| 706 | if (!port) | 815 | static void sdio_uart_hangup(struct tty_struct *tty) | 
| 707 | return; | 816 | { | 
| 708 | 817 | struct sdio_uart_port *port = tty->driver_data; | |
| 709 | mutex_lock(&port->open_lock); | 818 | tty_port_hangup(&port->port); | 
| 710 | BUG_ON(!port->opened); | ||
| 711 | |||
| 712 | /* | ||
| 713 | * This is messy. The tty layer calls us even when open() | ||
| 714 | * returned an error. Ignore this close request if tty->count | ||
| 715 | * is larger than port->count. | ||
| 716 | */ | ||
| 717 | if (tty->count > port->opened) { | ||
| 718 | mutex_unlock(&port->open_lock); | ||
| 719 | return; | ||
| 720 | } | ||
| 721 | |||
| 722 | if (--port->opened == 0) { | ||
| 723 | tty->closing = 1; | ||
| 724 | sdio_uart_shutdown(port); | ||
| 725 | tty_ldisc_flush(tty); | ||
| 726 | port->tty = NULL; | ||
| 727 | tty->driver_data = NULL; | ||
| 728 | tty->closing = 0; | ||
| 729 | } | ||
| 730 | mutex_unlock(&port->open_lock); | ||
| 731 | sdio_uart_port_put(port); | ||
| 732 | } | 819 | } | 
| 733 | 820 | ||
| 734 | static int sdio_uart_write(struct tty_struct * tty, const unsigned char *buf, | 821 | static int sdio_uart_write(struct tty_struct *tty, const unsigned char *buf, | 
| 735 | int count) | 822 | int count) | 
| 736 | { | 823 | { | 
| 737 | struct sdio_uart_port *port = tty->driver_data; | 824 | struct sdio_uart_port *port = tty->driver_data; | 
| @@ -756,7 +843,7 @@ static int sdio_uart_write(struct tty_struct * tty, const unsigned char *buf, | |||
| 756 | } | 843 | } | 
| 757 | spin_unlock(&port->write_lock); | 844 | spin_unlock(&port->write_lock); | 
| 758 | 845 | ||
| 759 | if ( !(port->ier & UART_IER_THRI)) { | 846 | if (!(port->ier & UART_IER_THRI)) { | 
| 760 | int err = sdio_uart_claim_func(port); | 847 | int err = sdio_uart_claim_func(port); | 
| 761 | if (!err) { | 848 | if (!err) { | 
| 762 | sdio_uart_start_tx(port); | 849 | sdio_uart_start_tx(port); | 
| @@ -843,17 +930,12 @@ static void sdio_uart_unthrottle(struct tty_struct *tty) | |||
| 843 | sdio_uart_release_func(port); | 930 | sdio_uart_release_func(port); | 
| 844 | } | 931 | } | 
| 845 | 932 | ||
| 846 | static void sdio_uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | 933 | static void sdio_uart_set_termios(struct tty_struct *tty, | 
| 934 | struct ktermios *old_termios) | ||
| 847 | { | 935 | { | 
| 848 | struct sdio_uart_port *port = tty->driver_data; | 936 | struct sdio_uart_port *port = tty->driver_data; | 
| 849 | unsigned int cflag = tty->termios->c_cflag; | 937 | unsigned int cflag = tty->termios->c_cflag; | 
| 850 | 938 | ||
| 851 | #define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) | ||
| 852 | |||
| 853 | if ((cflag ^ old_termios->c_cflag) == 0 && | ||
| 854 | RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) | ||
| 855 | return; | ||
| 856 | |||
| 857 | if (sdio_uart_claim_func(port) != 0) | 939 | if (sdio_uart_claim_func(port) != 0) | 
| 858 | return; | 940 | return; | 
| 859 | 941 | ||
| @@ -928,7 +1010,7 @@ static int sdio_uart_tiocmset(struct tty_struct *tty, struct file *file, | |||
| 928 | int result; | 1010 | int result; | 
| 929 | 1011 | ||
| 930 | result = sdio_uart_claim_func(port); | 1012 | result = sdio_uart_claim_func(port); | 
| 931 | if(!result) { | 1013 | if (!result) { | 
| 932 | sdio_uart_update_mctrl(port, set, clear); | 1014 | sdio_uart_update_mctrl(port, set, clear); | 
| 933 | sdio_uart_release_func(port); | 1015 | sdio_uart_release_func(port); | 
| 934 | } | 1016 | } | 
| @@ -946,7 +1028,7 @@ static int sdio_uart_proc_show(struct seq_file *m, void *v) | |||
| 946 | struct sdio_uart_port *port = sdio_uart_port_get(i); | 1028 | struct sdio_uart_port *port = sdio_uart_port_get(i); | 
| 947 | if (port) { | 1029 | if (port) { | 
| 948 | seq_printf(m, "%d: uart:SDIO", i); | 1030 | seq_printf(m, "%d: uart:SDIO", i); | 
| 949 | if(capable(CAP_SYS_ADMIN)) { | 1031 | if (capable(CAP_SYS_ADMIN)) { | 
| 950 | seq_printf(m, " tx:%d rx:%d", | 1032 | seq_printf(m, " tx:%d rx:%d", | 
| 951 | port->icount.tx, port->icount.rx); | 1033 | port->icount.tx, port->icount.rx); | 
| 952 | if (port->icount.frame) | 1034 | if (port->icount.frame) | 
| @@ -994,6 +1076,13 @@ static const struct file_operations sdio_uart_proc_fops = { | |||
| 994 | .release = single_release, | 1076 | .release = single_release, | 
| 995 | }; | 1077 | }; | 
| 996 | 1078 | ||
| 1079 | static const struct tty_port_operations sdio_uart_port_ops = { | ||
| 1080 | .dtr_rts = uart_dtr_rts, | ||
| 1081 | .carrier_raised = uart_carrier_raised, | ||
| 1082 | .shutdown = sdio_uart_shutdown, | ||
| 1083 | .activate = sdio_uart_activate, | ||
| 1084 | }; | ||
| 1085 | |||
| 997 | static const struct tty_operations sdio_uart_ops = { | 1086 | static const struct tty_operations sdio_uart_ops = { | 
| 998 | .open = sdio_uart_open, | 1087 | .open = sdio_uart_open, | 
| 999 | .close = sdio_uart_close, | 1088 | .close = sdio_uart_close, | 
| @@ -1004,9 +1093,12 @@ static const struct tty_operations sdio_uart_ops = { | |||
| 1004 | .throttle = sdio_uart_throttle, | 1093 | .throttle = sdio_uart_throttle, | 
| 1005 | .unthrottle = sdio_uart_unthrottle, | 1094 | .unthrottle = sdio_uart_unthrottle, | 
| 1006 | .set_termios = sdio_uart_set_termios, | 1095 | .set_termios = sdio_uart_set_termios, | 
| 1096 | .hangup = sdio_uart_hangup, | ||
| 1007 | .break_ctl = sdio_uart_break_ctl, | 1097 | .break_ctl = sdio_uart_break_ctl, | 
| 1008 | .tiocmget = sdio_uart_tiocmget, | 1098 | .tiocmget = sdio_uart_tiocmget, | 
| 1009 | .tiocmset = sdio_uart_tiocmset, | 1099 | .tiocmset = sdio_uart_tiocmset, | 
| 1100 | .install = sdio_uart_install, | ||
| 1101 | .cleanup = sdio_uart_cleanup, | ||
| 1010 | .proc_fops = &sdio_uart_proc_fops, | 1102 | .proc_fops = &sdio_uart_proc_fops, | 
| 1011 | }; | 1103 | }; | 
| 1012 | 1104 | ||
| @@ -1043,7 +1135,7 @@ static int sdio_uart_probe(struct sdio_func *func, | |||
| 1043 | } | 1135 | } | 
| 1044 | if (!tpl) { | 1136 | if (!tpl) { | 
| 1045 | printk(KERN_WARNING | 1137 | printk(KERN_WARNING | 
| 1046 | "%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n", | 1138 | "%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n", | 
| 1047 | sdio_func_id(func)); | 1139 | sdio_func_id(func)); | 
| 1048 | kfree(port); | 1140 | kfree(port); | 
| 1049 | return -EINVAL; | 1141 | return -EINVAL; | 
| @@ -1068,13 +1160,16 @@ static int sdio_uart_probe(struct sdio_func *func, | |||
| 1068 | 1160 | ||
| 1069 | port->func = func; | 1161 | port->func = func; | 
| 1070 | sdio_set_drvdata(func, port); | 1162 | sdio_set_drvdata(func, port); | 
| 1163 | tty_port_init(&port->port); | ||
| 1164 | port->port.ops = &sdio_uart_port_ops; | ||
| 1071 | 1165 | ||
| 1072 | ret = sdio_uart_add_port(port); | 1166 | ret = sdio_uart_add_port(port); | 
| 1073 | if (ret) { | 1167 | if (ret) { | 
| 1074 | kfree(port); | 1168 | kfree(port); | 
| 1075 | } else { | 1169 | } else { | 
| 1076 | struct device *dev; | 1170 | struct device *dev; | 
| 1077 | dev = tty_register_device(sdio_uart_tty_driver, port->index, &func->dev); | 1171 | dev = tty_register_device(sdio_uart_tty_driver, | 
| 1172 | port->index, &func->dev); | ||
| 1078 | if (IS_ERR(dev)) { | 1173 | if (IS_ERR(dev)) { | 
| 1079 | sdio_uart_port_remove(port); | 1174 | sdio_uart_port_remove(port); | 
| 1080 | ret = PTR_ERR(dev); | 1175 | ret = PTR_ERR(dev); | 
| diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 737b4c960971..c3e37c8e7e26 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
| @@ -1339,14 +1339,12 @@ static void serial8250_start_tx(struct uart_port *port) | |||
| 1339 | serial_out(up, UART_IER, up->ier); | 1339 | serial_out(up, UART_IER, up->ier); | 
| 1340 | 1340 | ||
| 1341 | if (up->bugs & UART_BUG_TXEN) { | 1341 | if (up->bugs & UART_BUG_TXEN) { | 
| 1342 | unsigned char lsr, iir; | 1342 | unsigned char lsr; | 
| 1343 | lsr = serial_in(up, UART_LSR); | 1343 | lsr = serial_in(up, UART_LSR); | 
| 1344 | up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; | 1344 | up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; | 
| 1345 | iir = serial_in(up, UART_IIR) & 0x0f; | ||
| 1346 | if ((up->port.type == PORT_RM9000) ? | 1345 | if ((up->port.type == PORT_RM9000) ? | 
| 1347 | (lsr & UART_LSR_THRE && | 1346 | (lsr & UART_LSR_THRE) : | 
| 1348 | (iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) : | 1347 | (lsr & UART_LSR_TEMT)) | 
| 1349 | (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT)) | ||
| 1350 | transmit_chars(up); | 1348 | transmit_chars(up); | 
| 1351 | } | 1349 | } | 
| 1352 | } | 1350 | } | 
| @@ -2646,7 +2644,7 @@ static void __init serial8250_isa_init_ports(void) | |||
| 2646 | { | 2644 | { | 
| 2647 | struct uart_8250_port *up; | 2645 | struct uart_8250_port *up; | 
| 2648 | static int first = 1; | 2646 | static int first = 1; | 
| 2649 | int i; | 2647 | int i, irqflag = 0; | 
| 2650 | 2648 | ||
| 2651 | if (!first) | 2649 | if (!first) | 
| 2652 | return; | 2650 | return; | 
| @@ -2670,6 +2668,9 @@ static void __init serial8250_isa_init_ports(void) | |||
| 2670 | up->port.ops = &serial8250_pops; | 2668 | up->port.ops = &serial8250_pops; | 
| 2671 | } | 2669 | } | 
| 2672 | 2670 | ||
| 2671 | if (share_irqs) | ||
| 2672 | irqflag = IRQF_SHARED; | ||
| 2673 | |||
| 2673 | for (i = 0, up = serial8250_ports; | 2674 | for (i = 0, up = serial8250_ports; | 
| 2674 | i < ARRAY_SIZE(old_serial_port) && i < nr_uarts; | 2675 | i < ARRAY_SIZE(old_serial_port) && i < nr_uarts; | 
| 2675 | i++, up++) { | 2676 | i++, up++) { | 
| @@ -2683,8 +2684,7 @@ static void __init serial8250_isa_init_ports(void) | |||
| 2683 | up->port.iotype = old_serial_port[i].io_type; | 2684 | up->port.iotype = old_serial_port[i].io_type; | 
| 2684 | up->port.regshift = old_serial_port[i].iomem_reg_shift; | 2685 | up->port.regshift = old_serial_port[i].iomem_reg_shift; | 
| 2685 | set_io_from_upio(&up->port); | 2686 | set_io_from_upio(&up->port); | 
| 2686 | if (share_irqs) | 2687 | up->port.irqflags |= irqflag; | 
| 2687 | up->port.irqflags |= IRQF_SHARED; | ||
| 2688 | } | 2688 | } | 
| 2689 | } | 2689 | } | 
| 2690 | 2690 | ||
| @@ -2940,10 +2940,13 @@ static int __devinit serial8250_probe(struct platform_device *dev) | |||
| 2940 | { | 2940 | { | 
| 2941 | struct plat_serial8250_port *p = dev->dev.platform_data; | 2941 | struct plat_serial8250_port *p = dev->dev.platform_data; | 
| 2942 | struct uart_port port; | 2942 | struct uart_port port; | 
| 2943 | int ret, i; | 2943 | int ret, i, irqflag = 0; | 
| 2944 | 2944 | ||
| 2945 | memset(&port, 0, sizeof(struct uart_port)); | 2945 | memset(&port, 0, sizeof(struct uart_port)); | 
| 2946 | 2946 | ||
| 2947 | if (share_irqs) | ||
| 2948 | irqflag = IRQF_SHARED; | ||
| 2949 | |||
| 2947 | for (i = 0; p && p->flags != 0; p++, i++) { | 2950 | for (i = 0; p && p->flags != 0; p++, i++) { | 
| 2948 | port.iobase = p->iobase; | 2951 | port.iobase = p->iobase; | 
| 2949 | port.membase = p->membase; | 2952 | port.membase = p->membase; | 
| @@ -2960,8 +2963,7 @@ static int __devinit serial8250_probe(struct platform_device *dev) | |||
| 2960 | port.serial_in = p->serial_in; | 2963 | port.serial_in = p->serial_in; | 
| 2961 | port.serial_out = p->serial_out; | 2964 | port.serial_out = p->serial_out; | 
| 2962 | port.dev = &dev->dev; | 2965 | port.dev = &dev->dev; | 
| 2963 | if (share_irqs) | 2966 | port.irqflags |= irqflag; | 
| 2964 | port.irqflags |= IRQF_SHARED; | ||
| 2965 | ret = serial8250_register_port(&port); | 2967 | ret = serial8250_register_port(&port); | 
| 2966 | if (ret < 0) { | 2968 | if (ret < 0) { | 
| 2967 | dev_err(&dev->dev, "unable to register port at index %d " | 2969 | dev_err(&dev->dev, "unable to register port at index %d " | 
| diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h index 4e5f3bde0461..38a509c684cd 100644 --- a/drivers/serial/jsm/jsm.h +++ b/drivers/serial/jsm/jsm.h | |||
| @@ -138,7 +138,6 @@ struct jsm_board | |||
| 138 | u32 nasync; /* Number of ports on card */ | 138 | u32 nasync; /* Number of ports on card */ | 
| 139 | 139 | ||
| 140 | u32 irq; /* Interrupt request number */ | 140 | u32 irq; /* Interrupt request number */ | 
| 141 | u64 intr_count; /* Count of interrupts */ | ||
| 142 | 141 | ||
| 143 | u64 membase; /* Start of base memory of the card */ | 142 | u64 membase; /* Start of base memory of the card */ | 
| 144 | u64 membase_end; /* End of base memory of the card */ | 143 | u64 membase_end; /* End of base memory of the card */ | 
| @@ -206,8 +205,6 @@ struct jsm_channel { | |||
| 206 | 205 | ||
| 207 | u64 ch_close_delay; /* How long we should drop RTS/DTR for */ | 206 | u64 ch_close_delay; /* How long we should drop RTS/DTR for */ | 
| 208 | 207 | ||
| 209 | u64 ch_cpstime; /* Time for CPS calculations */ | ||
| 210 | |||
| 211 | tcflag_t ch_c_iflag; /* channel iflags */ | 208 | tcflag_t ch_c_iflag; /* channel iflags */ | 
| 212 | tcflag_t ch_c_cflag; /* channel cflags */ | 209 | tcflag_t ch_c_cflag; /* channel cflags */ | 
| 213 | tcflag_t ch_c_oflag; /* channel oflags */ | 210 | tcflag_t ch_c_oflag; /* channel oflags */ | 
| @@ -215,11 +212,6 @@ struct jsm_channel { | |||
| 215 | u8 ch_stopc; /* Stop character */ | 212 | u8 ch_stopc; /* Stop character */ | 
| 216 | u8 ch_startc; /* Start character */ | 213 | u8 ch_startc; /* Start character */ | 
| 217 | 214 | ||
| 218 | u32 ch_old_baud; /* Cache of the current baud */ | ||
| 219 | u32 ch_custom_speed;/* Custom baud, if set */ | ||
| 220 | |||
| 221 | u32 ch_wopen; /* Waiting for open process cnt */ | ||
| 222 | |||
| 223 | u8 ch_mostat; /* FEP output modem status */ | 215 | u8 ch_mostat; /* FEP output modem status */ | 
| 224 | u8 ch_mistat; /* FEP input modem status */ | 216 | u8 ch_mistat; /* FEP input modem status */ | 
| 225 | 217 | ||
| diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c index b3604aa322a4..108c3e0471fd 100644 --- a/drivers/serial/jsm/jsm_driver.c +++ b/drivers/serial/jsm/jsm_driver.c | |||
| @@ -48,6 +48,17 @@ struct uart_driver jsm_uart_driver = { | |||
| 48 | .nr = NR_PORTS, | 48 | .nr = NR_PORTS, | 
| 49 | }; | 49 | }; | 
| 50 | 50 | ||
| 51 | static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev, | ||
| 52 | pci_channel_state_t state); | ||
| 53 | static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev); | ||
| 54 | static void jsm_io_resume(struct pci_dev *pdev); | ||
| 55 | |||
| 56 | static struct pci_error_handlers jsm_err_handler = { | ||
| 57 | .error_detected = jsm_io_error_detected, | ||
| 58 | .slot_reset = jsm_io_slot_reset, | ||
| 59 | .resume = jsm_io_resume, | ||
| 60 | }; | ||
| 61 | |||
| 51 | int jsm_debug; | 62 | int jsm_debug; | 
| 52 | module_param(jsm_debug, int, 0); | 63 | module_param(jsm_debug, int, 0); | 
| 53 | MODULE_PARM_DESC(jsm_debug, "Driver debugging level"); | 64 | MODULE_PARM_DESC(jsm_debug, "Driver debugging level"); | 
| @@ -123,7 +134,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device | |||
| 123 | } | 134 | } | 
| 124 | 135 | ||
| 125 | rc = request_irq(brd->irq, brd->bd_ops->intr, | 136 | rc = request_irq(brd->irq, brd->bd_ops->intr, | 
| 126 | IRQF_DISABLED|IRQF_SHARED, "JSM", brd); | 137 | IRQF_SHARED, "JSM", brd); | 
| 127 | if (rc) { | 138 | if (rc) { | 
| 128 | printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq); | 139 | printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq); | 
| 129 | goto out_iounmap; | 140 | goto out_iounmap; | 
| @@ -164,6 +175,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device | |||
| 164 | } | 175 | } | 
| 165 | 176 | ||
| 166 | pci_set_drvdata(pdev, brd); | 177 | pci_set_drvdata(pdev, brd); | 
| 178 | pci_save_state(pdev); | ||
| 167 | 179 | ||
| 168 | return 0; | 180 | return 0; | 
| 169 | out_free_irq: | 181 | out_free_irq: | 
| @@ -222,8 +234,42 @@ static struct pci_driver jsm_driver = { | |||
| 222 | .id_table = jsm_pci_tbl, | 234 | .id_table = jsm_pci_tbl, | 
| 223 | .probe = jsm_probe_one, | 235 | .probe = jsm_probe_one, | 
| 224 | .remove = __devexit_p(jsm_remove_one), | 236 | .remove = __devexit_p(jsm_remove_one), | 
| 237 | .err_handler = &jsm_err_handler, | ||
| 225 | }; | 238 | }; | 
| 226 | 239 | ||
| 240 | static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev, | ||
| 241 | pci_channel_state_t state) | ||
| 242 | { | ||
| 243 | struct jsm_board *brd = pci_get_drvdata(pdev); | ||
| 244 | |||
| 245 | jsm_remove_uart_port(brd); | ||
| 246 | |||
| 247 | return PCI_ERS_RESULT_NEED_RESET; | ||
| 248 | } | ||
| 249 | |||
| 250 | static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev) | ||
| 251 | { | ||
| 252 | int rc; | ||
| 253 | |||
| 254 | rc = pci_enable_device(pdev); | ||
| 255 | |||
| 256 | if (rc) | ||
| 257 | return PCI_ERS_RESULT_DISCONNECT; | ||
| 258 | |||
| 259 | pci_set_master(pdev); | ||
| 260 | |||
| 261 | return PCI_ERS_RESULT_RECOVERED; | ||
| 262 | } | ||
| 263 | |||
| 264 | static void jsm_io_resume(struct pci_dev *pdev) | ||
| 265 | { | ||
| 266 | struct jsm_board *brd = pci_get_drvdata(pdev); | ||
| 267 | |||
| 268 | pci_restore_state(pdev); | ||
| 269 | |||
| 270 | jsm_uart_port_init(brd); | ||
| 271 | } | ||
| 272 | |||
| 227 | static int __init jsm_init_module(void) | 273 | static int __init jsm_init_module(void) | 
| 228 | { | 274 | { | 
| 229 | int rc; | 275 | int rc; | 
| diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c index b4b124e4828f..7960d9633c15 100644 --- a/drivers/serial/jsm/jsm_neo.c +++ b/drivers/serial/jsm/jsm_neo.c | |||
| @@ -954,13 +954,8 @@ static void neo_param(struct jsm_channel *ch) | |||
| 954 | ch->ch_flags |= (CH_BAUD0); | 954 | ch->ch_flags |= (CH_BAUD0); | 
| 955 | ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR); | 955 | ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR); | 
| 956 | neo_assert_modem_signals(ch); | 956 | neo_assert_modem_signals(ch); | 
| 957 | ch->ch_old_baud = 0; | ||
| 958 | return; | 957 | return; | 
| 959 | 958 | ||
| 960 | } else if (ch->ch_custom_speed) { | ||
| 961 | baud = ch->ch_custom_speed; | ||
| 962 | if (ch->ch_flags & CH_BAUD0) | ||
| 963 | ch->ch_flags &= ~(CH_BAUD0); | ||
| 964 | } else { | 959 | } else { | 
| 965 | int i; | 960 | int i; | 
| 966 | unsigned int cflag; | 961 | unsigned int cflag; | 
| @@ -1045,7 +1040,6 @@ static void neo_param(struct jsm_channel *ch) | |||
| 1045 | quot = ch->ch_bd->bd_dividend / baud; | 1040 | quot = ch->ch_bd->bd_dividend / baud; | 
| 1046 | 1041 | ||
| 1047 | if (quot != 0) { | 1042 | if (quot != 0) { | 
| 1048 | ch->ch_old_baud = baud; | ||
| 1049 | writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr); | 1043 | writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr); | 
| 1050 | writeb((quot & 0xff), &ch->ch_neo_uart->txrx); | 1044 | writeb((quot & 0xff), &ch->ch_neo_uart->txrx); | 
| 1051 | writeb((quot >> 8), &ch->ch_neo_uart->ier); | 1045 | writeb((quot >> 8), &ch->ch_neo_uart->ier); | 
| @@ -1123,8 +1117,6 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) | |||
| 1123 | unsigned long lock_flags2; | 1117 | unsigned long lock_flags2; | 
| 1124 | int outofloop_count = 0; | 1118 | int outofloop_count = 0; | 
| 1125 | 1119 | ||
| 1126 | brd->intr_count++; | ||
| 1127 | |||
| 1128 | /* Lock out the slow poller from running on this board. */ | 1120 | /* Lock out the slow poller from running on this board. */ | 
| 1129 | spin_lock_irqsave(&brd->bd_intr_lock, lock_flags); | 1121 | spin_lock_irqsave(&brd->bd_intr_lock, lock_flags); | 
| 1130 | 1122 | ||
| diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 7439c0373620..cd95e215550d 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c | |||
| @@ -296,8 +296,6 @@ static void jsm_tty_close(struct uart_port *port) | |||
| 296 | bd->bd_ops->assert_modem_signals(channel); | 296 | bd->bd_ops->assert_modem_signals(channel); | 
| 297 | } | 297 | } | 
| 298 | 298 | ||
| 299 | channel->ch_old_baud = 0; | ||
| 300 | |||
| 301 | /* Turn off UART interrupts for this port */ | 299 | /* Turn off UART interrupts for this port */ | 
| 302 | channel->ch_bd->bd_ops->uart_off(channel); | 300 | channel->ch_bd->bd_ops->uart_off(channel); | 
| 303 | 301 | ||
| @@ -432,7 +430,7 @@ int __devinit jsm_tty_init(struct jsm_board *brd) | |||
| 432 | return 0; | 430 | return 0; | 
| 433 | } | 431 | } | 
| 434 | 432 | ||
| 435 | int __devinit jsm_uart_port_init(struct jsm_board *brd) | 433 | int jsm_uart_port_init(struct jsm_board *brd) | 
| 436 | { | 434 | { | 
| 437 | int i; | 435 | int i; | 
| 438 | unsigned int line; | 436 | unsigned int line; | 
| @@ -472,7 +470,7 @@ int __devinit jsm_uart_port_init(struct jsm_board *brd) | |||
| 472 | if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port)) | 470 | if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port)) | 
| 473 | printk(KERN_INFO "jsm: add device failed\n"); | 471 | printk(KERN_INFO "jsm: add device failed\n"); | 
| 474 | else | 472 | else | 
| 475 | printk(KERN_INFO "Added device \n"); | 473 | printk(KERN_INFO "jsm: Port %d added\n", i); | 
| 476 | } | 474 | } | 
| 477 | 475 | ||
| 478 | jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n"); | 476 | jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n"); | 
| diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index b8629d74f6a2..4a821046baae 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c | |||
| @@ -438,6 +438,7 @@ serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 438 | unsigned char cval, fcr = 0; | 438 | unsigned char cval, fcr = 0; | 
| 439 | unsigned long flags; | 439 | unsigned long flags; | 
| 440 | unsigned int baud, quot; | 440 | unsigned int baud, quot; | 
| 441 | unsigned int dll; | ||
| 441 | 442 | ||
| 442 | switch (termios->c_cflag & CSIZE) { | 443 | switch (termios->c_cflag & CSIZE) { | 
| 443 | case CS5: | 444 | case CS5: | 
| @@ -534,10 +535,18 @@ serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 534 | else | 535 | else | 
| 535 | up->mcr &= ~UART_MCR_AFE; | 536 | up->mcr &= ~UART_MCR_AFE; | 
| 536 | 537 | ||
| 537 | serial_out(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ | 538 | serial_out(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ | 
| 538 | serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ | 539 | serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ | 
| 540 | |||
| 541 | /* | ||
| 542 | * work around Errata #75 according to Intel(R) PXA27x Processor Family | ||
| 543 | * Specification Update (Nov 2005) | ||
| 544 | */ | ||
| 545 | dll = serial_in(up, UART_DLL); | ||
| 546 | WARN_ON(dll != (quot & 0xff)); | ||
| 547 | |||
| 539 | serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ | 548 | serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ | 
| 540 | serial_out(up, UART_LCR, cval); /* reset DLAB */ | 549 | serial_out(up, UART_LCR, cval); /* reset DLAB */ | 
| 541 | up->lcr = cval; /* Save LCR */ | 550 | up->lcr = cval; /* Save LCR */ | 
| 542 | serial_pxa_set_mctrl(&up->port, up->port.mctrl); | 551 | serial_pxa_set_mctrl(&up->port, up->port.mctrl); | 
| 543 | serial_out(up, UART_FCR, fcr); | 552 | serial_out(up, UART_FCR, fcr); | 
| diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index dcc72444e8e7..047530b285bb 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
| @@ -342,11 +342,11 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, | |||
| 342 | 342 | ||
| 343 | if (flags == UPF_SPD_HI) | 343 | if (flags == UPF_SPD_HI) | 
| 344 | altbaud = 57600; | 344 | altbaud = 57600; | 
| 345 | if (flags == UPF_SPD_VHI) | 345 | else if (flags == UPF_SPD_VHI) | 
| 346 | altbaud = 115200; | 346 | altbaud = 115200; | 
| 347 | if (flags == UPF_SPD_SHI) | 347 | else if (flags == UPF_SPD_SHI) | 
| 348 | altbaud = 230400; | 348 | altbaud = 230400; | 
| 349 | if (flags == UPF_SPD_WARP) | 349 | else if (flags == UPF_SPD_WARP) | 
| 350 | altbaud = 460800; | 350 | altbaud = 460800; | 
| 351 | 351 | ||
| 352 | for (try = 0; try < 2; try++) { | 352 | for (try = 0; try < 2; try++) { | 
| @@ -1217,9 +1217,8 @@ static void uart_set_termios(struct tty_struct *tty, | |||
| 1217 | /* Handle transition to B0 status */ | 1217 | /* Handle transition to B0 status */ | 
| 1218 | if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) | 1218 | if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) | 
| 1219 | uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR); | 1219 | uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR); | 
| 1220 | |||
| 1221 | /* Handle transition away from B0 status */ | 1220 | /* Handle transition away from B0 status */ | 
| 1222 | if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { | 1221 | else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { | 
| 1223 | unsigned int mask = TIOCM_DTR; | 1222 | unsigned int mask = TIOCM_DTR; | 
| 1224 | if (!(cflag & CRTSCTS) || | 1223 | if (!(cflag & CRTSCTS) || | 
| 1225 | !test_bit(TTY_THROTTLED, &tty->flags)) | 1224 | !test_bit(TTY_THROTTLED, &tty->flags)) | 
| @@ -1234,9 +1233,8 @@ static void uart_set_termios(struct tty_struct *tty, | |||
| 1234 | __uart_start(tty); | 1233 | __uart_start(tty); | 
| 1235 | spin_unlock_irqrestore(&state->uart_port->lock, flags); | 1234 | spin_unlock_irqrestore(&state->uart_port->lock, flags); | 
| 1236 | } | 1235 | } | 
| 1237 | |||
| 1238 | /* Handle turning on CRTSCTS */ | 1236 | /* Handle turning on CRTSCTS */ | 
| 1239 | if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { | 1237 | else if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { | 
| 1240 | spin_lock_irqsave(&state->uart_port->lock, flags); | 1238 | spin_lock_irqsave(&state->uart_port->lock, flags); | 
| 1241 | if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) { | 1239 | if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) { | 
| 1242 | tty->hw_stopped = 1; | 1240 | tty->hw_stopped = 1; | 
| @@ -2344,7 +2342,7 @@ static const struct tty_operations uart_ops = { | |||
| 2344 | */ | 2342 | */ | 
| 2345 | int uart_register_driver(struct uart_driver *drv) | 2343 | int uart_register_driver(struct uart_driver *drv) | 
| 2346 | { | 2344 | { | 
| 2347 | struct tty_driver *normal = NULL; | 2345 | struct tty_driver *normal; | 
| 2348 | int i, retval; | 2346 | int i, retval; | 
| 2349 | 2347 | ||
| 2350 | BUG_ON(drv->state); | 2348 | BUG_ON(drv->state); | 
| @@ -2354,13 +2352,12 @@ int uart_register_driver(struct uart_driver *drv) | |||
| 2354 | * we have a large number of ports to handle. | 2352 | * we have a large number of ports to handle. | 
| 2355 | */ | 2353 | */ | 
| 2356 | drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL); | 2354 | drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL); | 
| 2357 | retval = -ENOMEM; | ||
| 2358 | if (!drv->state) | 2355 | if (!drv->state) | 
| 2359 | goto out; | 2356 | goto out; | 
| 2360 | 2357 | ||
| 2361 | normal = alloc_tty_driver(drv->nr); | 2358 | normal = alloc_tty_driver(drv->nr); | 
| 2362 | if (!normal) | 2359 | if (!normal) | 
| 2363 | goto out; | 2360 | goto out_kfree; | 
| 2364 | 2361 | ||
| 2365 | drv->tty_driver = normal; | 2362 | drv->tty_driver = normal; | 
| 2366 | 2363 | ||
| @@ -2393,12 +2390,14 @@ int uart_register_driver(struct uart_driver *drv) | |||
| 2393 | } | 2390 | } | 
| 2394 | 2391 | ||
| 2395 | retval = tty_register_driver(normal); | 2392 | retval = tty_register_driver(normal); | 
| 2396 | out: | 2393 | if (retval >= 0) | 
| 2397 | if (retval < 0) { | 2394 | return retval; | 
| 2398 | put_tty_driver(normal); | 2395 | |
| 2399 | kfree(drv->state); | 2396 | put_tty_driver(normal); | 
| 2400 | } | 2397 | out_kfree: | 
| 2401 | return retval; | 2398 | kfree(drv->state); | 
| 2399 | out: | ||
| 2400 | return -ENOMEM; | ||
| 2402 | } | 2401 | } | 
| 2403 | 2402 | ||
| 2404 | /** | 2403 | /** | 
| diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 80f59b6350cb..4cdb975caa89 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c | |||
| @@ -501,12 +501,13 @@ static int opticon_resume(struct usb_interface *intf) | |||
| 501 | struct usb_serial_port *port = serial->port[0]; | 501 | struct usb_serial_port *port = serial->port[0]; | 
| 502 | int result; | 502 | int result; | 
| 503 | 503 | ||
| 504 | mutex_lock(&port->mutex); | 504 | mutex_lock(&port->port.mutex); | 
| 505 | if (port->port.count) | 505 | /* This is protected by the port mutex against close/open */ | 
| 506 | if (test_bit(ASYNCB_INITIALIZED, &port->port.flags)) | ||
| 506 | result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO); | 507 | result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO); | 
| 507 | else | 508 | else | 
| 508 | result = 0; | 509 | result = 0; | 
| 509 | mutex_unlock(&port->mutex); | 510 | mutex_unlock(&port->port.mutex); | 
| 510 | return result; | 511 | return result; | 
| 511 | } | 512 | } | 
| 512 | 513 | ||
| diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index bd3fa7ff15b1..4543f359be75 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
| @@ -247,96 +247,66 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) | |||
| 247 | return retval; | 247 | return retval; | 
| 248 | } | 248 | } | 
| 249 | 249 | ||
| 250 | static int serial_open(struct tty_struct *tty, struct file *filp) | 250 | static int serial_activate(struct tty_port *tport, struct tty_struct *tty) | 
| 251 | { | 251 | { | 
| 252 | struct usb_serial_port *port = tty->driver_data; | 252 | struct usb_serial_port *port = | 
| 253 | container_of(tport, struct usb_serial_port, port); | ||
| 253 | struct usb_serial *serial = port->serial; | 254 | struct usb_serial *serial = port->serial; | 
| 254 | int retval; | 255 | int retval; | 
| 255 | 256 | ||
| 256 | dbg("%s - port %d", __func__, port->number); | 257 | mutex_lock(&serial->disc_mutex); | 
| 257 | 258 | if (serial->disconnected) | |
| 258 | spin_lock_irq(&port->port.lock); | 259 | retval = -ENODEV; | 
| 259 | if (!tty_hung_up_p(filp)) | 260 | else | 
| 260 | ++port->port.count; | 261 | retval = port->serial->type->open(tty, port); | 
| 261 | spin_unlock_irq(&port->port.lock); | 262 | mutex_unlock(&serial->disc_mutex); | 
| 262 | tty_port_tty_set(&port->port, tty); | 263 | return retval; | 
| 264 | } | ||
| 263 | 265 | ||
| 264 | /* Do the device-specific open only if the hardware isn't | 266 | static int serial_open(struct tty_struct *tty, struct file *filp) | 
| 265 | * already initialized. | 267 | { | 
| 266 | */ | 268 | struct usb_serial_port *port = tty->driver_data; | 
| 267 | if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) { | ||
| 268 | if (mutex_lock_interruptible(&port->mutex)) | ||
| 269 | return -ERESTARTSYS; | ||
| 270 | mutex_lock(&serial->disc_mutex); | ||
| 271 | if (serial->disconnected) | ||
| 272 | retval = -ENODEV; | ||
| 273 | else | ||
| 274 | retval = port->serial->type->open(tty, port); | ||
| 275 | mutex_unlock(&serial->disc_mutex); | ||
| 276 | mutex_unlock(&port->mutex); | ||
| 277 | if (retval) | ||
| 278 | return retval; | ||
| 279 | set_bit(ASYNCB_INITIALIZED, &port->port.flags); | ||
| 280 | } | ||
| 281 | 269 | ||
| 282 | /* Now do the correct tty layer semantics */ | 270 | dbg("%s - port %d", __func__, port->number); | 
| 283 | retval = tty_port_block_til_ready(&port->port, tty, filp); | 271 | return tty_port_open(&port->port, tty, filp); | 
| 284 | return retval; | ||
| 285 | } | 272 | } | 
| 286 | 273 | ||
| 287 | /** | 274 | /** | 
| 288 | * serial_down - shut down hardware | 275 | * serial_down - shut down hardware | 
| 289 | * @port: port to shut down | 276 | * @tport: tty port to shut down | 
| 290 | * | 277 | * | 
| 291 | * Shut down a USB serial port unless it is the console. We never | 278 | * Shut down a USB serial port unless it is the console. We never | 
| 292 | * shut down the console hardware as it will always be in use. | 279 | * shut down the console hardware as it will always be in use. Serialized | 
| 280 | * against activate by the tport mutex and kept to matching open/close pairs | ||
| 281 | * of calls by the ASYNCB_INITIALIZED flag. | ||
| 293 | */ | 282 | */ | 
| 294 | static void serial_down(struct usb_serial_port *port) | 283 | static void serial_down(struct tty_port *tport) | 
| 295 | { | 284 | { | 
| 285 | struct usb_serial_port *port = | ||
| 286 | container_of(tport, struct usb_serial_port, port); | ||
| 296 | struct usb_serial_driver *drv = port->serial->type; | 287 | struct usb_serial_driver *drv = port->serial->type; | 
| 297 | |||
| 298 | /* | 288 | /* | 
| 299 | * The console is magical. Do not hang up the console hardware | 289 | * The console is magical. Do not hang up the console hardware | 
| 300 | * or there will be tears. | 290 | * or there will be tears. | 
| 301 | */ | 291 | */ | 
| 302 | if (port->console) | 292 | if (port->console) | 
| 303 | return; | 293 | return; | 
| 304 | |||
| 305 | /* Don't call the close method if the hardware hasn't been | ||
| 306 | * initialized. | ||
| 307 | */ | ||
| 308 | if (!test_and_clear_bit(ASYNCB_INITIALIZED, &port->port.flags)) | ||
| 309 | return; | ||
| 310 | |||
| 311 | mutex_lock(&port->mutex); | ||
| 312 | if (drv->close) | 294 | if (drv->close) | 
| 313 | drv->close(port); | 295 | drv->close(port); | 
| 314 | mutex_unlock(&port->mutex); | ||
| 315 | } | 296 | } | 
| 316 | 297 | ||
| 317 | static void serial_hangup(struct tty_struct *tty) | 298 | static void serial_hangup(struct tty_struct *tty) | 
| 318 | { | 299 | { | 
| 319 | struct usb_serial_port *port = tty->driver_data; | 300 | struct usb_serial_port *port = tty->driver_data; | 
| 320 | |||
| 321 | dbg("%s - port %d", __func__, port->number); | 301 | dbg("%s - port %d", __func__, port->number); | 
| 322 | |||
| 323 | serial_down(port); | ||
| 324 | tty_port_hangup(&port->port); | 302 | tty_port_hangup(&port->port); | 
| 325 | } | 303 | } | 
| 326 | 304 | ||
| 327 | static void serial_close(struct tty_struct *tty, struct file *filp) | 305 | static void serial_close(struct tty_struct *tty, struct file *filp) | 
| 328 | { | 306 | { | 
| 329 | struct usb_serial_port *port = tty->driver_data; | 307 | struct usb_serial_port *port = tty->driver_data; | 
| 330 | |||
| 331 | dbg("%s - port %d", __func__, port->number); | 308 | dbg("%s - port %d", __func__, port->number); | 
| 332 | 309 | tty_port_close(&port->port, tty, filp); | |
| 333 | if (tty_hung_up_p(filp)) | ||
| 334 | return; | ||
| 335 | if (tty_port_close_start(&port->port, tty, filp) == 0) | ||
| 336 | return; | ||
| 337 | serial_down(port); | ||
| 338 | tty_port_close_end(&port->port, tty); | ||
| 339 | tty_port_tty_set(&port->port, NULL); | ||
| 340 | } | 310 | } | 
| 341 | 311 | ||
| 342 | /** | 312 | /** | 
| @@ -725,6 +695,8 @@ static void serial_dtr_rts(struct tty_port *port, int on) | |||
| 725 | static const struct tty_port_operations serial_port_ops = { | 695 | static const struct tty_port_operations serial_port_ops = { | 
| 726 | .carrier_raised = serial_carrier_raised, | 696 | .carrier_raised = serial_carrier_raised, | 
| 727 | .dtr_rts = serial_dtr_rts, | 697 | .dtr_rts = serial_dtr_rts, | 
| 698 | .activate = serial_activate, | ||
| 699 | .shutdown = serial_down, | ||
| 728 | }; | 700 | }; | 
| 729 | 701 | ||
| 730 | int usb_serial_probe(struct usb_interface *interface, | 702 | int usb_serial_probe(struct usb_interface *interface, | 
| @@ -923,7 +895,8 @@ int usb_serial_probe(struct usb_interface *interface, | |||
| 923 | port->port.ops = &serial_port_ops; | 895 | port->port.ops = &serial_port_ops; | 
| 924 | port->serial = serial; | 896 | port->serial = serial; | 
| 925 | spin_lock_init(&port->lock); | 897 | spin_lock_init(&port->lock); | 
| 926 | mutex_init(&port->mutex); | 898 | /* Keep this for private driver use for the moment but | 
| 899 | should probably go away */ | ||
| 927 | INIT_WORK(&port->work, usb_serial_port_work); | 900 | INIT_WORK(&port->work, usb_serial_port_work); | 
| 928 | serial->port[i] = port; | 901 | serial->port[i] = port; | 
| 929 | port->dev.parent = &interface->dev; | 902 | port->dev.parent = &interface->dev; | 
| diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index d5f8c96964be..8882ecc0f1bf 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c | |||
| @@ -517,11 +517,23 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty) | |||
| 517 | 517 | ||
| 518 | struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number) | 518 | struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number) | 
| 519 | { | 519 | { | 
| 520 | struct dentry *dentry; | ||
| 521 | struct tty_struct *tty; | ||
| 522 | |||
| 520 | BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR)); | 523 | BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR)); | 
| 521 | 524 | ||
| 525 | /* Ensure dentry has not been deleted by devpts_pty_kill() */ | ||
| 526 | dentry = d_find_alias(pts_inode); | ||
| 527 | if (!dentry) | ||
| 528 | return NULL; | ||
| 529 | |||
| 530 | tty = NULL; | ||
| 522 | if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC) | 531 | if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC) | 
| 523 | return (struct tty_struct *)pts_inode->i_private; | 532 | tty = (struct tty_struct *)pts_inode->i_private; | 
| 524 | return NULL; | 533 | |
| 534 | dput(dentry); | ||
| 535 | |||
| 536 | return tty; | ||
| 525 | } | 537 | } | 
| 526 | 538 | ||
| 527 | void devpts_pty_kill(struct tty_struct *tty) | 539 | void devpts_pty_kill(struct tty_struct *tty) | 
| diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 5a5385749e16..f72914db2a11 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild | |||
| @@ -214,7 +214,6 @@ unifdef-y += futex.h | |||
| 214 | unifdef-y += fs.h | 214 | unifdef-y += fs.h | 
| 215 | unifdef-y += gameport.h | 215 | unifdef-y += gameport.h | 
| 216 | unifdef-y += generic_serial.h | 216 | unifdef-y += generic_serial.h | 
| 217 | unifdef-y += hayesesp.h | ||
| 218 | unifdef-y += hdlcdrv.h | 217 | unifdef-y += hdlcdrv.h | 
| 219 | unifdef-y += hdlc.h | 218 | unifdef-y += hdlc.h | 
| 220 | unifdef-y += hdreg.h | 219 | unifdef-y += hdreg.h | 
| diff --git a/include/linux/hayesesp.h b/include/linux/hayesesp.h deleted file mode 100644 index 92b08cfe4a75..000000000000 --- a/include/linux/hayesesp.h +++ /dev/null | |||
| @@ -1,114 +0,0 @@ | |||
| 1 | #ifndef HAYESESP_H | ||
| 2 | #define HAYESESP_H | ||
| 3 | |||
| 4 | struct hayes_esp_config { | ||
| 5 | short flow_on; | ||
| 6 | short flow_off; | ||
| 7 | short rx_trigger; | ||
| 8 | short tx_trigger; | ||
| 9 | short pio_threshold; | ||
| 10 | unsigned char rx_timeout; | ||
| 11 | char dma_channel; | ||
| 12 | }; | ||
| 13 | |||
| 14 | #ifdef __KERNEL__ | ||
| 15 | |||
| 16 | #define ESP_DMA_CHANNEL 0 | ||
| 17 | #define ESP_RX_TRIGGER 768 | ||
| 18 | #define ESP_TX_TRIGGER 768 | ||
| 19 | #define ESP_FLOW_OFF 1016 | ||
| 20 | #define ESP_FLOW_ON 944 | ||
| 21 | #define ESP_RX_TMOUT 128 | ||
| 22 | #define ESP_PIO_THRESHOLD 32 | ||
| 23 | |||
| 24 | #define ESP_IN_MAJOR 57 /* major dev # for dial in */ | ||
| 25 | #define ESP_OUT_MAJOR 58 /* major dev # for dial out */ | ||
| 26 | #define ESPC_SCALE 3 | ||
| 27 | #define UART_ESI_BASE 0x00 | ||
| 28 | #define UART_ESI_SID 0x01 | ||
| 29 | #define UART_ESI_RX 0x02 | ||
| 30 | #define UART_ESI_TX 0x02 | ||
| 31 | #define UART_ESI_CMD1 0x04 | ||
| 32 | #define UART_ESI_CMD2 0x05 | ||
| 33 | #define UART_ESI_STAT1 0x04 | ||
| 34 | #define UART_ESI_STAT2 0x05 | ||
| 35 | #define UART_ESI_RWS 0x07 | ||
| 36 | |||
| 37 | #define UART_IER_DMA_TMOUT 0x80 | ||
| 38 | #define UART_IER_DMA_TC 0x08 | ||
| 39 | |||
| 40 | #define ESI_SET_IRQ 0x04 | ||
| 41 | #define ESI_SET_DMA_TMOUT 0x05 | ||
| 42 | #define ESI_SET_SRV_MASK 0x06 | ||
| 43 | #define ESI_SET_ERR_MASK 0x07 | ||
| 44 | #define ESI_SET_FLOW_CNTL 0x08 | ||
| 45 | #define ESI_SET_FLOW_CHARS 0x09 | ||
| 46 | #define ESI_SET_FLOW_LVL 0x0a | ||
| 47 | #define ESI_SET_TRIGGER 0x0b | ||
| 48 | #define ESI_SET_RX_TIMEOUT 0x0c | ||
| 49 | #define ESI_SET_FLOW_TMOUT 0x0d | ||
| 50 | #define ESI_WRITE_UART 0x0e | ||
| 51 | #define ESI_READ_UART 0x0f | ||
| 52 | #define ESI_SET_MODE 0x10 | ||
| 53 | #define ESI_GET_ERR_STAT 0x12 | ||
| 54 | #define ESI_GET_UART_STAT 0x13 | ||
| 55 | #define ESI_GET_RX_AVAIL 0x14 | ||
| 56 | #define ESI_GET_TX_AVAIL 0x15 | ||
| 57 | #define ESI_START_DMA_RX 0x16 | ||
| 58 | #define ESI_START_DMA_TX 0x17 | ||
| 59 | #define ESI_ISSUE_BREAK 0x1a | ||
| 60 | #define ESI_FLUSH_RX 0x1b | ||
| 61 | #define ESI_FLUSH_TX 0x1c | ||
| 62 | #define ESI_SET_BAUD 0x1d | ||
| 63 | #define ESI_SET_ENH_IRQ 0x1f | ||
| 64 | #define ESI_SET_REINTR 0x20 | ||
| 65 | #define ESI_SET_PRESCALAR 0x23 | ||
| 66 | #define ESI_NO_COMMAND 0xff | ||
| 67 | |||
| 68 | #define ESP_STAT_RX_TIMEOUT 0x01 | ||
| 69 | #define ESP_STAT_DMA_RX 0x02 | ||
| 70 | #define ESP_STAT_DMA_TX 0x04 | ||
| 71 | #define ESP_STAT_NEVER_DMA 0x08 | ||
| 72 | #define ESP_STAT_USE_PIO 0x10 | ||
| 73 | |||
| 74 | #define ESP_MAGIC 0x53ee | ||
| 75 | #define ESP_XMIT_SIZE 4096 | ||
| 76 | |||
| 77 | struct esp_struct { | ||
| 78 | int magic; | ||
| 79 | struct tty_port port; | ||
| 80 | spinlock_t lock; | ||
| 81 | int io_port; | ||
| 82 | int irq; | ||
| 83 | int read_status_mask; | ||
| 84 | int ignore_status_mask; | ||
| 85 | int timeout; | ||
| 86 | int stat_flags; | ||
| 87 | int custom_divisor; | ||
| 88 | int close_delay; | ||
| 89 | unsigned short closing_wait; | ||
| 90 | unsigned short closing_wait2; | ||
| 91 | int IER; /* Interrupt Enable Register */ | ||
| 92 | int MCR; /* Modem control register */ | ||
| 93 | unsigned long last_active; | ||
| 94 | int line; | ||
| 95 | unsigned char *xmit_buf; | ||
| 96 | int xmit_head; | ||
| 97 | int xmit_tail; | ||
| 98 | int xmit_cnt; | ||
| 99 | wait_queue_head_t break_wait; | ||
| 100 | struct async_icount icount; /* kernel counters for the 4 input interrupts */ | ||
| 101 | struct hayes_esp_config config; /* port configuration */ | ||
| 102 | struct esp_struct *next_port; /* For the linked list */ | ||
| 103 | }; | ||
| 104 | |||
| 105 | struct esp_pio_buffer { | ||
| 106 | unsigned char data[1024]; | ||
| 107 | struct esp_pio_buffer *next; | ||
| 108 | }; | ||
| 109 | |||
| 110 | #endif /* __KERNEL__ */ | ||
| 111 | |||
| 112 | |||
| 113 | #endif /* ESP_H */ | ||
| 114 | |||
| diff --git a/include/linux/isicom.h b/include/linux/isicom.h index bbd42197298f..b92e05650639 100644 --- a/include/linux/isicom.h +++ b/include/linux/isicom.h | |||
| @@ -67,6 +67,7 @@ | |||
| 67 | 67 | ||
| 68 | #define FIRMWARE_LOADED 0x0001 | 68 | #define FIRMWARE_LOADED 0x0001 | 
| 69 | #define BOARD_ACTIVE 0x0002 | 69 | #define BOARD_ACTIVE 0x0002 | 
| 70 | #define BOARD_INIT 0x0004 | ||
| 70 | 71 | ||
| 71 | /* isi_port status bitmap */ | 72 | /* isi_port status bitmap */ | 
| 72 | 73 | ||
| diff --git a/include/linux/tty.h b/include/linux/tty.h index f0f43d08d8b8..405a9035fe40 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
| @@ -190,9 +190,17 @@ struct tty_port_operations { | |||
| 190 | /* Control the DTR line */ | 190 | /* Control the DTR line */ | 
| 191 | void (*dtr_rts)(struct tty_port *port, int raise); | 191 | void (*dtr_rts)(struct tty_port *port, int raise); | 
| 192 | /* Called when the last close completes or a hangup finishes | 192 | /* Called when the last close completes or a hangup finishes | 
| 193 | IFF the port was initialized. Do not use to free resources */ | 193 | IFF the port was initialized. Do not use to free resources. Called | 
| 194 | under the port mutex to serialize against activate/shutdowns */ | ||
| 194 | void (*shutdown)(struct tty_port *port); | 195 | void (*shutdown)(struct tty_port *port); | 
| 195 | void (*drop)(struct tty_port *port); | 196 | void (*drop)(struct tty_port *port); | 
| 197 | /* Called under the port mutex from tty_port_open, serialized using | ||
| 198 | the port mutex */ | ||
| 199 | /* FIXME: long term getting the tty argument *out* of this would be | ||
| 200 | good for consoles */ | ||
| 201 | int (*activate)(struct tty_port *port, struct tty_struct *tty); | ||
| 202 | /* Called on the final put of a port */ | ||
| 203 | void (*destruct)(struct tty_port *port); | ||
| 196 | }; | 204 | }; | 
| 197 | 205 | ||
| 198 | struct tty_port { | 206 | struct tty_port { | 
| @@ -206,12 +214,14 @@ struct tty_port { | |||
| 206 | wait_queue_head_t delta_msr_wait; /* Modem status change */ | 214 | wait_queue_head_t delta_msr_wait; /* Modem status change */ | 
| 207 | unsigned long flags; /* TTY flags ASY_*/ | 215 | unsigned long flags; /* TTY flags ASY_*/ | 
| 208 | struct mutex mutex; /* Locking */ | 216 | struct mutex mutex; /* Locking */ | 
| 217 | struct mutex buf_mutex; /* Buffer alloc lock */ | ||
| 209 | unsigned char *xmit_buf; /* Optional buffer */ | 218 | unsigned char *xmit_buf; /* Optional buffer */ | 
| 210 | unsigned int close_delay; /* Close port delay */ | 219 | unsigned int close_delay; /* Close port delay */ | 
| 211 | unsigned int closing_wait; /* Delay for output */ | 220 | unsigned int closing_wait; /* Delay for output */ | 
| 212 | int drain_delay; /* Set to zero if no pure time | 221 | int drain_delay; /* Set to zero if no pure time | 
| 213 | based drain is needed else | 222 | based drain is needed else | 
| 214 | set to size of fifo */ | 223 | set to size of fifo */ | 
| 224 | struct kref kref; /* Ref counter */ | ||
| 215 | }; | 225 | }; | 
| 216 | 226 | ||
| 217 | /* | 227 | /* | 
| @@ -439,7 +449,7 @@ extern void initialize_tty_struct(struct tty_struct *tty, | |||
| 439 | struct tty_driver *driver, int idx); | 449 | struct tty_driver *driver, int idx); | 
| 440 | extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | 450 | extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | 
| 441 | int first_ok); | 451 | int first_ok); | 
| 442 | extern void tty_release_dev(struct file *filp); | 452 | extern int tty_release(struct inode *inode, struct file *filp); | 
| 443 | extern int tty_init_termios(struct tty_struct *tty); | 453 | extern int tty_init_termios(struct tty_struct *tty); | 
| 444 | 454 | ||
| 445 | extern struct tty_struct *tty_pair_get_tty(struct tty_struct *tty); | 455 | extern struct tty_struct *tty_pair_get_tty(struct tty_struct *tty); | 
| @@ -454,6 +464,15 @@ extern int tty_write_lock(struct tty_struct *tty, int ndelay); | |||
| 454 | extern void tty_port_init(struct tty_port *port); | 464 | extern void tty_port_init(struct tty_port *port); | 
| 455 | extern int tty_port_alloc_xmit_buf(struct tty_port *port); | 465 | extern int tty_port_alloc_xmit_buf(struct tty_port *port); | 
| 456 | extern void tty_port_free_xmit_buf(struct tty_port *port); | 466 | extern void tty_port_free_xmit_buf(struct tty_port *port); | 
| 467 | extern void tty_port_put(struct tty_port *port); | ||
| 468 | |||
| 469 | extern inline struct tty_port *tty_port_get(struct tty_port *port) | ||
| 470 | { | ||
| 471 | if (port) | ||
| 472 | kref_get(&port->kref); | ||
| 473 | return port; | ||
| 474 | } | ||
| 475 | |||
| 457 | extern struct tty_struct *tty_port_tty_get(struct tty_port *port); | 476 | extern struct tty_struct *tty_port_tty_get(struct tty_port *port); | 
| 458 | extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty); | 477 | extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty); | 
| 459 | extern int tty_port_carrier_raised(struct tty_port *port); | 478 | extern int tty_port_carrier_raised(struct tty_port *port); | 
| @@ -467,6 +486,8 @@ extern int tty_port_close_start(struct tty_port *port, | |||
| 467 | extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty); | 486 | extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty); | 
| 468 | extern void tty_port_close(struct tty_port *port, | 487 | extern void tty_port_close(struct tty_port *port, | 
| 469 | struct tty_struct *tty, struct file *filp); | 488 | struct tty_struct *tty, struct file *filp); | 
| 489 | extern int tty_port_open(struct tty_port *port, | ||
| 490 | struct tty_struct *tty, struct file *filp); | ||
| 470 | extern inline int tty_port_users(struct tty_port *port) | 491 | extern inline int tty_port_users(struct tty_port *port) | 
| 471 | { | 492 | { | 
| 472 | return port->count + port->blocked_open; | 493 | return port->count + port->blocked_open; | 
| diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index ce911ebf91e8..acf6e457c04b 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h | |||
| @@ -39,8 +39,6 @@ enum port_dev_state { | |||
| 39 | * @serial: pointer back to the struct usb_serial owner of this port. | 39 | * @serial: pointer back to the struct usb_serial owner of this port. | 
| 40 | * @port: pointer to the corresponding tty_port for this port. | 40 | * @port: pointer to the corresponding tty_port for this port. | 
| 41 | * @lock: spinlock to grab when updating portions of this structure. | 41 | * @lock: spinlock to grab when updating portions of this structure. | 
| 42 | * @mutex: mutex used to synchronize serial_open() and serial_close() | ||
| 43 | * access for this port. | ||
| 44 | * @number: the number of the port (the minor number). | 42 | * @number: the number of the port (the minor number). | 
| 45 | * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. | 43 | * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. | 
| 46 | * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. | 44 | * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. | 
| @@ -77,7 +75,6 @@ struct usb_serial_port { | |||
| 77 | struct usb_serial *serial; | 75 | struct usb_serial *serial; | 
| 78 | struct tty_port port; | 76 | struct tty_port port; | 
| 79 | spinlock_t lock; | 77 | spinlock_t lock; | 
| 80 | struct mutex mutex; | ||
| 81 | unsigned char number; | 78 | unsigned char number; | 
| 82 | 79 | ||
| 83 | unsigned char *interrupt_in_buffer; | 80 | unsigned char *interrupt_in_buffer; | 
| diff --git a/kernel/exit.c b/kernel/exit.c index 1143012951e9..6f50ef55a6f3 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
| @@ -971,7 +971,7 @@ NORET_TYPE void do_exit(long code) | |||
| 971 | exit_thread(); | 971 | exit_thread(); | 
| 972 | cgroup_exit(tsk, 1); | 972 | cgroup_exit(tsk, 1); | 
| 973 | 973 | ||
| 974 | if (group_dead && tsk->signal->leader) | 974 | if (group_dead) | 
| 975 | disassociate_ctty(1); | 975 | disassociate_ctty(1); | 
| 976 | 976 | ||
| 977 | module_put(task_thread_info(tsk)->exec_domain->module); | 977 | module_put(task_thread_info(tsk)->exec_domain->module); | 
