summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-01-12 11:21:52 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2022-01-12 11:21:52 -0800
commit342465f5337f7bd5b8bd3b6f939ac12b620cbb43 (patch)
treeaa116708ffedd73d6f1311489265e7b98225315f
parent22ef12195e13c5ec58320dbf99ef85059a2c0820 (diff)
parent93a770b7e16772530196674ffc79bb13fa927dc6 (diff)
downloadlinux-342465f5337f7bd5b8bd3b6f939ac12b620cbb43.tar.bz2
Merge tag 'tty-5.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver updates from Greg KH: "Here is the big set of tty/serial driver updates for 5.17-rc1. Nothing major in here, just lots of good updates and fixes, including: - more tty core cleanups from Jiri as well as mxser driver cleanups. This is the majority of the core diffstat - tty documentation updates from Jiri - platform_get_irq() updates - various serial driver updates for new features and hardware - fifo usage for 8250 console, reducing cpu load a lot - LED fix for keyboards, long-time bugfix that went through many revisions - minor cleanups All have been in linux-next for a while with no reported problems" * tag 'tty-5.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (119 commits) serial: core: Keep mctrl register state and cached copy in sync serial: stm32: correct loop for dma error handling serial: stm32: fix flow control transfer in DMA mode serial: stm32: rework TX DMA state condition serial: stm32: move tx dma terminate DMA to shutdown serial: pl011: Drop redundant DTR/RTS preservation on close/open serial: pl011: Drop CR register reset on set_termios serial: pl010: Drop CR register reset on set_termios serial: liteuart: fix MODULE_ALIAS serial: 8250_bcm7271: Fix return error code in case of dma_alloc_coherent() failure Revert "serdev: BREAK/FRAME/PARITY/OVERRUN notification prototype V2" tty: goldfish: Use platform_get_irq() to get the interrupt serdev: BREAK/FRAME/PARITY/OVERRUN notification prototype V2 tty: serial: meson: Drop the legacy compatible strings and clock code serial: pmac_zilog: Use platform_get_irq() to get the interrupt serial: bcm63xx: Use platform_get_irq() to get the interrupt serial: ar933x: Use platform_get_irq() to get the interrupt serial: vt8500: Use platform_get_irq() to get the interrupt serial: altera_jtaguart: Use platform_get_irq_optional() to get the interrupt serial: pxa: Use platform_get_irq() to get the interrupt ...
-rw-r--r--Documentation/devicetree/bindings/serial/amlogic,meson-uart.yaml2
-rw-r--r--Documentation/devicetree/bindings/serial/fsl-lpuart.yaml8
-rw-r--r--Documentation/devicetree/bindings/serial/renesas,sci.yaml48
-rw-r--r--Documentation/devicetree/bindings/serial/renesas,scif.yaml15
-rw-r--r--Documentation/driver-api/serial/index.rst1
-rw-r--r--Documentation/driver-api/serial/n_gsm.rst8
-rw-r--r--Documentation/driver-api/serial/tty.rst328
-rw-r--r--Documentation/index.rst1
-rw-r--r--Documentation/tty/index.rst63
-rw-r--r--Documentation/tty/n_tty.rst22
-rw-r--r--Documentation/tty/tty_buffer.rst46
-rw-r--r--Documentation/tty/tty_driver.rst128
-rw-r--r--Documentation/tty/tty_internals.rst31
-rw-r--r--Documentation/tty/tty_ldisc.rst85
-rw-r--r--Documentation/tty/tty_port.rst70
-rw-r--r--Documentation/tty/tty_struct.rst81
-rw-r--r--arch/alpha/kernel/srmcons.c2
-rw-r--r--arch/arm/include/debug/pl01x.S7
-rw-r--r--drivers/accessibility/speakup/spk_ttyio.c4
-rw-r--r--drivers/bluetooth/hci_ldisc.c5
-rw-r--r--drivers/input/serio/serport.c5
-rw-r--r--drivers/net/can/slcan.c4
-rw-r--r--drivers/net/hamradio/6pack.c4
-rw-r--r--drivers/net/hamradio/mkiss.c4
-rw-r--r--drivers/net/ppp/ppp_async.c3
-rw-r--r--drivers/net/ppp/ppp_synctty.c3
-rw-r--r--drivers/net/slip/slip.c4
-rw-r--r--drivers/s390/char/keyboard.h4
-rw-r--r--drivers/tty/goldfish.c12
-rw-r--r--drivers/tty/mips_ejtag_fdc.c22
-rw-r--r--drivers/tty/moxa.c4
-rw-r--r--drivers/tty/mxser.c306
-rw-r--r--drivers/tty/n_gsm.c11
-rw-r--r--drivers/tty/n_hdlc.c5
-rw-r--r--drivers/tty/n_tty.c692
-rw-r--r--drivers/tty/serial/8250/8250.h12
-rw-r--r--drivers/tty/serial/8250/8250_alpha.c21
-rw-r--r--drivers/tty/serial/8250/8250_bcm7271.c23
-rw-r--r--drivers/tty/serial/8250/8250_core.c9
-rw-r--r--drivers/tty/serial/8250/8250_pci.c407
-rw-r--r--drivers/tty/serial/8250/8250_pericom.c214
-rw-r--r--drivers/tty/serial/8250/8250_port.c65
-rw-r--r--drivers/tty/serial/8250/Kconfig8
-rw-r--r--drivers/tty/serial/8250/Makefile3
-rw-r--r--drivers/tty/serial/Kconfig2
-rw-r--r--drivers/tty/serial/altera_jtaguart.c11
-rw-r--r--drivers/tty/serial/altera_uart.c9
-rw-r--r--drivers/tty/serial/amba-pl010.c3
-rw-r--r--drivers/tty/serial/amba-pl011.c73
-rw-r--r--drivers/tty/serial/ar933x_uart.c12
-rw-r--r--drivers/tty/serial/atmel_serial.c16
-rw-r--r--drivers/tty/serial/bcm63xx_uart.c10
-rw-r--r--drivers/tty/serial/fsl_lpuart.c12
-rw-r--r--drivers/tty/serial/imx.c13
-rw-r--r--drivers/tty/serial/lantiq.c34
-rw-r--r--drivers/tty/serial/liteuart.c2
-rw-r--r--drivers/tty/serial/lpc32xx_hs.c2
-rw-r--r--drivers/tty/serial/meson_uart.c45
-rw-r--r--drivers/tty/serial/pmac_zilog.c12
-rw-r--r--drivers/tty/serial/pxa.c12
-rw-r--r--drivers/tty/serial/samsung_tty.c78
-rw-r--r--drivers/tty/serial/serial_core.c19
-rw-r--r--drivers/tty/serial/sh-sci.c91
-rw-r--r--drivers/tty/serial/stm32-usart.c74
-rw-r--r--drivers/tty/serial/stm32-usart.h2
-rw-r--r--drivers/tty/serial/sunsu.c3
-rw-r--r--drivers/tty/serial/uartlite.c2
-rw-r--r--drivers/tty/serial/vt8500_serial.c12
-rw-r--r--drivers/tty/tty_buffer.c279
-rw-r--r--drivers/tty/tty_io.c921
-rw-r--r--drivers/tty/tty_ldisc.c292
-rw-r--r--drivers/tty/tty_ldsem.c2
-rw-r--r--drivers/tty/tty_port.c223
-rw-r--r--drivers/tty/vt/keyboard.c18
-rw-r--r--drivers/tty/vt/vt.c2
-rw-r--r--drivers/usb/class/cdc-acm.c4
-rw-r--r--include/linux/amba/bus.h6
-rw-r--r--include/linux/pci_ids.h18
-rw-r--r--include/linux/serial_8250.h2
-rw-r--r--include/linux/serial_s3c.h9
-rw-r--r--include/linux/tty.h153
-rw-r--r--include/linux/tty_driver.h572
-rw-r--r--include/linux/tty_flip.h1
-rw-r--r--include/linux/tty_ldisc.h287
-rw-r--r--include/linux/tty_port.h131
-rw-r--r--net/nfc/nci/uart.c5
86 files changed, 3294 insertions, 2980 deletions
diff --git a/Documentation/devicetree/bindings/serial/amlogic,meson-uart.yaml b/Documentation/devicetree/bindings/serial/amlogic,meson-uart.yaml
index 7487aa6ef849..72e8868db3e0 100644
--- a/Documentation/devicetree/bindings/serial/amlogic,meson-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/amlogic,meson-uart.yaml
@@ -29,6 +29,7 @@ properties:
- amlogic,meson8-uart
- amlogic,meson8b-uart
- amlogic,meson-gx-uart
+ - amlogic,meson-s4-uart
- const: amlogic,meson-ao-uart
- description: Everything-Else power domain UART controller
enum:
@@ -36,6 +37,7 @@ properties:
- amlogic,meson8-uart
- amlogic,meson8b-uart
- amlogic,meson-gx-uart
+ - amlogic,meson-s4-uart
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml b/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml
index a90c971b4f1f..6e04e3848261 100644
--- a/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml
+++ b/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml
@@ -21,9 +21,15 @@ properties:
- fsl,ls1028a-lpuart
- fsl,imx7ulp-lpuart
- fsl,imx8qm-lpuart
+ - fsl,imxrt1050-lpuart
- items:
- - const: fsl,imx8qxp-lpuart
+ - enum:
+ - fsl,imx8qxp-lpuart
+ - fsl,imx8ulp-lpuart
- const: fsl,imx7ulp-lpuart
+ - items:
+ - const: fsl,imx8qm-lpuart
+ - const: fsl,imx8qxp-lpuart
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/serial/renesas,sci.yaml b/Documentation/devicetree/bindings/serial/renesas,sci.yaml
index 22ed2f0b1dc3..8dda4e10e09d 100644
--- a/Documentation/devicetree/bindings/serial/renesas,sci.yaml
+++ b/Documentation/devicetree/bindings/serial/renesas,sci.yaml
@@ -14,7 +14,15 @@ allOf:
properties:
compatible:
- const: renesas,sci
+ oneOf:
+ - items:
+ - enum:
+ - renesas,r9a07g044-sci # RZ/G2{L,LC}
+ - renesas,r9a07g054-sci # RZ/V2L
+ - const: renesas,sci # generic SCI compatible UART
+
+ - items:
+ - const: renesas,sci # generic SCI compatible UART
reg:
maxItems: 1
@@ -54,18 +62,46 @@ required:
- clocks
- clock-names
+if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - renesas,r9a07g044-sci
+ - renesas,r9a07g054-sci
+then:
+ properties:
+ resets:
+ maxItems: 1
+
+ power-domains:
+ maxItems: 1
+
+ required:
+ - resets
+ - power-domains
+
unevaluatedProperties: false
examples:
- |
+ #include <dt-bindings/clock/r9a07g044-cpg.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
aliases {
serial0 = &sci0;
};
- sci0: serial@ffff78 {
- compatible = "renesas,sci";
- reg = <0xffff78 8>;
- interrupts = <88 0>, <89 0>, <90 0>, <91 0>;
- clocks = <&fclk>;
+ sci0: serial@1004d000 {
+ compatible = "renesas,r9a07g044-sci", "renesas,sci";
+ reg = <0x1004d000 0x400>;
+ interrupts = <GIC_SPI 405 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 406 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 407 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 408 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "eri", "rxi", "txi", "tei";
+ clocks = <&cpg CPG_MOD R9A07G044_SCI0_CLKP>;
clock-names = "fck";
+ power-domains = <&cpg>;
+ resets = <&cpg R9A07G044_SCI0_RST>;
};
diff --git a/Documentation/devicetree/bindings/serial/renesas,scif.yaml b/Documentation/devicetree/bindings/serial/renesas,scif.yaml
index 6b8731f7f2fb..ba5d3e0acc63 100644
--- a/Documentation/devicetree/bindings/serial/renesas,scif.yaml
+++ b/Documentation/devicetree/bindings/serial/renesas,scif.yaml
@@ -66,7 +66,19 @@ properties:
- items:
- enum:
+ - renesas,scif-r8a779f0 # R-Car S4-8
+ - const: renesas,rcar-gen4-scif # R-Car Gen4
+ - const: renesas,scif # generic SCIF compatible UART
+
+ - items:
+ - enum:
- renesas,scif-r9a07g044 # RZ/G2{L,LC}
+ - renesas,scif-r9a07g054 # RZ/V2L
+
+ - items:
+ - enum:
+ - renesas,scif-r9a07g054 # RZ/V2L
+ - const: renesas,scif-r9a07g044 # RZ/G2{L,LC} fallback for RZ/V2L
reg:
maxItems: 1
@@ -153,6 +165,9 @@ if:
enum:
- renesas,rcar-gen2-scif
- renesas,rcar-gen3-scif
+ - renesas,rcar-gen4-scif
+ - renesas,scif-r9a07g044
+ - renesas,scif-r9a07g054
then:
required:
- resets
diff --git a/Documentation/driver-api/serial/index.rst b/Documentation/driver-api/serial/index.rst
index 8f7d7af3b90b..7eb21a695fc3 100644
--- a/Documentation/driver-api/serial/index.rst
+++ b/Documentation/driver-api/serial/index.rst
@@ -9,7 +9,6 @@ Support for Serial devices
driver
- tty
Serial drivers
==============
diff --git a/Documentation/driver-api/serial/n_gsm.rst b/Documentation/driver-api/serial/n_gsm.rst
index 8fe723ab9c67..49956509ad73 100644
--- a/Documentation/driver-api/serial/n_gsm.rst
+++ b/Documentation/driver-api/serial/n_gsm.rst
@@ -18,9 +18,12 @@ How to use it
1.1 initialize the modem in 0710 mux mode (usually AT+CMUX= command) through
its serial port. Depending on the modem used, you can pass more or less
parameters to this command.
+
1.2 switch the serial line to using the n_gsm line discipline by using
TIOCSETD ioctl.
+
1.3 configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl.
+
1.4 obtain base gsmtty number for the used serial port.
Major parts of the initialization program :
@@ -95,10 +98,13 @@ Major parts of the initialization program :
2.1 receive string "AT+CMUX= command" through its serial port,initialize
mux mode config
+
2.2 switch the serial line to using the n_gsm line discipline by using
TIOCSETD ioctl.
+
2.3 configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl.
-2.4 obtain base gsmtty number for the used serial port,
+
+2.4 obtain base gsmtty number for the used serial port::
#include <stdio.h>
#include <stdint.h>
diff --git a/Documentation/driver-api/serial/tty.rst b/Documentation/driver-api/serial/tty.rst
deleted file mode 100644
index 4b709f392713..000000000000
--- a/Documentation/driver-api/serial/tty.rst
+++ /dev/null
@@ -1,328 +0,0 @@
-=================
-The Lockronomicon
-=================
-
-Your guide to the ancient and twisted locking policies of the tty layer and
-the warped logic behind them. Beware all ye who read on.
-
-
-Line Discipline
----------------
-
-Line disciplines are registered with tty_register_ldisc() passing the
-discipline number and the ldisc structure. At the point of registration the
-discipline must be ready to use and it is possible it will get used before
-the call returns success. If the call returns an error then it won't get
-called. Do not re-use ldisc numbers as they are part of the userspace ABI
-and writing over an existing ldisc will cause demons to eat your computer.
-After the return the ldisc data has been copied so you may free your own
-copy of the structure. You must not re-register over the top of the line
-discipline even with the same data or your computer again will be eaten by
-demons.
-
-In order to remove a line discipline call tty_unregister_ldisc().
-In ancient times this always worked. In modern times the function will
-return -EBUSY if the ldisc is currently in use. Since the ldisc referencing
-code manages the module counts this should not usually be a concern.
-
-Heed this warning: the reference count field of the registered copies of the
-tty_ldisc structure in the ldisc table counts the number of lines using this
-discipline. The reference count of the tty_ldisc structure within a tty
-counts the number of active users of the ldisc at this instant. In effect it
-counts the number of threads of execution within an ldisc method (plus those
-about to enter and exit although this detail matters not).
-
-Line Discipline Methods
------------------------
-
-TTY side interfaces
-^^^^^^^^^^^^^^^^^^^
-
-======================= =======================================================
-open() Called when the line discipline is attached to
- the terminal. No other call into the line
- discipline for this tty will occur until it
- completes successfully. Should initialize any
- state needed by the ldisc, and set receive_room
- in the tty_struct to the maximum amount of data
- the line discipline is willing to accept from the
- driver with a single call to receive_buf().
- Returning an error will prevent the ldisc from
- being attached. Can sleep.
-
-close() This is called on a terminal when the line
- discipline is being unplugged. At the point of
- execution no further users will enter the
- ldisc code for this tty. Can sleep.
-
-hangup() Called when the tty line is hung up.
- The line discipline should cease I/O to the tty.
- No further calls into the ldisc code will occur.
- Can sleep.
-
-read() (optional) A process requests reading data from
- the line. Multiple read calls may occur in parallel
- and the ldisc must deal with serialization issues.
- If not defined, the process will receive an EIO
- error. May sleep.
-
-write() (optional) A process requests writing data to the
- line. Multiple write calls are serialized by the
- tty layer for the ldisc. If not defined, the
- process will receive an EIO error. May sleep.
-
-flush_buffer() (optional) May be called at any point between
- open and close, and instructs the line discipline
- to empty its input buffer.
-
-set_termios() (optional) Called on termios structure changes.
- The caller passes the old termios data and the
- current data is in the tty. Called under the
- termios semaphore so allowed to sleep. Serialized
- against itself only.
-
-poll() (optional) Check the status for the poll/select
- calls. Multiple poll calls may occur in parallel.
- May sleep.
-
-ioctl() (optional) Called when an ioctl is handed to the
- tty layer that might be for the ldisc. Multiple
- ioctl calls may occur in parallel. May sleep.
-
-compat_ioctl() (optional) Called when a 32 bit ioctl is handed
- to the tty layer that might be for the ldisc.
- Multiple ioctl calls may occur in parallel.
- May sleep.
-======================= =======================================================
-
-Driver Side Interfaces
-^^^^^^^^^^^^^^^^^^^^^^
-
-======================= =======================================================
-receive_buf() (optional) Called by the low-level driver to hand
- a buffer of received bytes to the ldisc for
- processing. The number of bytes is guaranteed not
- to exceed the current value of tty->receive_room.
- All bytes must be processed.
-
-receive_buf2() (optional) Called by the low-level driver to hand
- a buffer of received bytes to the ldisc for
- processing. Returns the number of bytes processed.
-
- If both receive_buf() and receive_buf2() are
- defined, receive_buf2() should be preferred.
-
-write_wakeup() May be called at any point between open and close.
- The TTY_DO_WRITE_WAKEUP flag indicates if a call
- is needed but always races versus calls. Thus the
- ldisc must be careful about setting order and to
- handle unexpected calls. Must not sleep.
-
- The driver is forbidden from calling this directly
- from the ->write call from the ldisc as the ldisc
- is permitted to call the driver write method from
- this function. In such a situation defer it.
-
-dcd_change() Report to the tty line the current DCD pin status
- changes and the relative timestamp. The timestamp
- cannot be NULL.
-======================= =======================================================
-
-
-Driver Access
-^^^^^^^^^^^^^
-
-Line discipline methods can call the following methods of the underlying
-hardware driver through the function pointers within the tty->driver
-structure:
-
-======================= =======================================================
-write() Write a block of characters to the tty device.
- Returns the number of characters accepted. The
- character buffer passed to this method is already
- in kernel space.
-
-put_char() Queues a character for writing to the tty device.
- If there is no room in the queue, the character is
- ignored.
-
-flush_chars() (Optional) If defined, must be called after
- queueing characters with put_char() in order to
- start transmission.
-
-write_room() Returns the numbers of characters the tty driver
- will accept for queueing to be written.
-
-ioctl() Invoke device specific ioctl.
- Expects data pointers to refer to userspace.
- Returns ENOIOCTLCMD for unrecognized ioctl numbers.
-
-set_termios() Notify the tty driver that the device's termios
- settings have changed. New settings are in
- tty->termios. Previous settings should be passed in
- the "old" argument.
-
- The API is defined such that the driver should return
- the actual modes selected. This means that the
- driver function is responsible for modifying any
- bits in the request it cannot fulfill to indicate
- the actual modes being used. A device with no
- hardware capability for change (e.g. a USB dongle or
- virtual port) can provide NULL for this method.
-
-throttle() Notify the tty driver that input buffers for the
- line discipline are close to full, and it should
- somehow signal that no more characters should be
- sent to the tty.
-
-unthrottle() Notify the tty driver that characters can now be
- sent to the tty without fear of overrunning the
- input buffers of the line disciplines.
-
-stop() Ask the tty driver to stop outputting characters
- to the tty device.
-
-start() Ask the tty driver to resume sending characters
- to the tty device.
-
-hangup() Ask the tty driver to hang up the tty device.
-
-break_ctl() (Optional) Ask the tty driver to turn on or off
- BREAK status on the RS-232 port. If state is -1,
- then the BREAK status should be turned on; if
- state is 0, then BREAK should be turned off.
- If this routine is not implemented, use ioctls
- TIOCSBRK / TIOCCBRK instead.
-
-wait_until_sent() Waits until the device has written out all of the
- characters in its transmitter FIFO.
-
-send_xchar() Send a high-priority XON/XOFF character to the device.
-======================= =======================================================
-
-
-Flags
-^^^^^
-
-Line discipline methods have access to tty->flags field containing the
-following interesting flags:
-
-======================= =======================================================
-TTY_THROTTLED Driver input is throttled. The ldisc should call
- tty->driver->unthrottle() in order to resume
- reception when it is ready to process more data.
-
-TTY_DO_WRITE_WAKEUP If set, causes the driver to call the ldisc's
- write_wakeup() method in order to resume
- transmission when it can accept more data
- to transmit.
-
-TTY_IO_ERROR If set, causes all subsequent userspace read/write
- calls on the tty to fail, returning -EIO.
-
-TTY_OTHER_CLOSED Device is a pty and the other side has closed.
-
-TTY_NO_WRITE_SPLIT Prevent driver from splitting up writes into
- smaller chunks.
-======================= =======================================================
-
-
-Locking
-^^^^^^^
-
-Callers to the line discipline functions from the tty layer are required to
-take line discipline locks. The same is true of calls from the driver side
-but not yet enforced.
-
-Three calls are now provided::
-
- ldisc = tty_ldisc_ref(tty);
-
-takes a handle to the line discipline in the tty and returns it. If no ldisc
-is currently attached or the ldisc is being closed and re-opened at this
-point then NULL is returned. While this handle is held the ldisc will not
-change or go away::
-
- tty_ldisc_deref(ldisc)
-
-Returns the ldisc reference and allows the ldisc to be closed. Returning the
-reference takes away your right to call the ldisc functions until you take
-a new reference::
-
- ldisc = tty_ldisc_ref_wait(tty);
-
-Performs the same function as tty_ldisc_ref except that it will wait for an
-ldisc change to complete and then return a reference to the new ldisc.
-
-While these functions are slightly slower than the old code they should have
-minimal impact as most receive logic uses the flip buffers and they only
-need to take a reference when they push bits up through the driver.
-
-A caution: The ldisc->open(), ldisc->close() and driver->set_ldisc
-functions are called with the ldisc unavailable. Thus tty_ldisc_ref will
-fail in this situation if used within these functions. Ldisc and driver
-code calling its own functions must be careful in this case.
-
-
-Driver Interface
-----------------
-
-======================= =======================================================
-open() Called when a device is opened. May sleep
-
-close() Called when a device is closed. At the point of
- return from this call the driver must make no
- further ldisc calls of any kind. May sleep
-
-write() Called to write bytes to the device. May not
- sleep. May occur in parallel in special cases.
- Because this includes panic paths drivers generally
- shouldn't try and do clever locking here.
-
-put_char() Stuff a single character onto the queue. The
- driver is guaranteed following up calls to
- flush_chars.
-
-flush_chars() Ask the kernel to write put_char queue
-
-write_room() Return the number of characters that can be stuffed
- into the port buffers without overflow (or less).
- The ldisc is responsible for being intelligent
- about multi-threading of write_room/write calls
-
-ioctl() Called when an ioctl may be for the driver
-
-set_termios() Called on termios change, serialized against
- itself by a semaphore. May sleep.
-
-set_ldisc() Notifier for discipline change. At the point this
- is done the discipline is not yet usable. Can now
- sleep (I think)
-
-throttle() Called by the ldisc to ask the driver to do flow
- control. Serialization including with unthrottle
- is the job of the ldisc layer.
-
-unthrottle() Called by the ldisc to ask the driver to stop flow
- control.
-
-stop() Ldisc notifier to the driver to stop output. As with
- throttle the serializations with start() are down
- to the ldisc layer.
-
-start() Ldisc notifier to the driver to start output.
-
-hangup() Ask the tty driver to cause a hangup initiated
- from the host side. [Can sleep ??]
-
-break_ctl() Send RS232 break. Can sleep. Can get called in
- parallel, driver must serialize (for now), and
- with write calls.
-
-wait_until_sent() Wait for characters to exit the hardware queue
- of the driver. Can sleep
-
-send_xchar() Send XON/XOFF and if possible jump the queue with
- it in order to get fast flow control responses.
- Cannot sleep ??
-======================= =======================================================
diff --git a/Documentation/index.rst b/Documentation/index.rst
index 54ce34fd6fbd..2b4de3926858 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -137,6 +137,7 @@ needed).
misc-devices/index
scheduler/index
mhi/index
+ tty/index
Architecture-agnostic documentation
-----------------------------------
diff --git a/Documentation/tty/index.rst b/Documentation/tty/index.rst
new file mode 100644
index 000000000000..21ea0cb21e55
--- /dev/null
+++ b/Documentation/tty/index.rst
@@ -0,0 +1,63 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===
+TTY
+===
+
+Teletypewriter (TTY) layer takes care of all those serial devices. Including
+the virtual ones like pseudoterminal (PTY).
+
+TTY structures
+==============
+
+There are several major TTY structures. Every TTY device in a system has a
+corresponding struct tty_port. These devices are maintained by a TTY driver
+which is struct tty_driver. This structure describes the driver but also
+contains a reference to operations which could be performed on the TTYs. It is
+struct tty_operations. Then, upon open, a struct tty_struct is allocated and
+lives until the final close. During this time, several callbacks from struct
+tty_operations are invoked by the TTY layer.
+
+Every character received by the kernel (both from devices and users) is passed
+through a preselected :doc:`tty_ldisc` (in
+short ldisc; in C, struct tty_ldisc_ops). Its task is to transform characters
+as defined by a particular ldisc or by user too. The default one is n_tty,
+implementing echoes, signal handling, jobs control, special characters
+processing, and more. The transformed characters are passed further to
+user/device, depending on the source.
+
+In-detail description of the named TTY structures is in separate documents:
+
+.. toctree::
+ :maxdepth: 2
+
+ tty_driver
+ tty_port
+ tty_struct
+ tty_ldisc
+ tty_buffer
+ n_tty
+ tty_internals
+
+Writing TTY Driver
+==================
+
+Before one starts writing a TTY driver, they must consider
+:doc:`Serial <../driver-api/serial/driver>` and :doc:`USB Serial
+<../usb/usb-serial>` layers
+first. Drivers for serial devices can often use one of these specific layers to
+implement a serial driver. Only special devices should be handled directly by
+the TTY Layer. If you are about to write such a driver, read on.
+
+A *typical* sequence a TTY driver performs is as follows:
+
+#. Allocate and register a TTY driver (module init)
+#. Create and register TTY devices as they are probed (probe function)
+#. Handle TTY operations and events like interrupts (TTY core invokes the
+ former, the device the latter)
+#. Remove devices as they are going away (remove function)
+#. Unregister and free the TTY driver (module exit)
+
+Steps regarding driver, i.e. 1., 3., and 5. are described in detail in
+:doc:`tty_driver`. For the other two (devices handling), look into
+:doc:`tty_port`.
diff --git a/Documentation/tty/n_tty.rst b/Documentation/tty/n_tty.rst
new file mode 100644
index 000000000000..15b70faee72d
--- /dev/null
+++ b/Documentation/tty/n_tty.rst
@@ -0,0 +1,22 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=====
+N_TTY
+=====
+
+.. contents:: :local:
+
+The default (and fallback) :doc:`TTY line discipline <tty_ldisc>`. It tries to
+handle characters as per POSIX.
+
+External Functions
+==================
+
+.. kernel-doc:: drivers/tty/n_tty.c
+ :export:
+
+Internal Functions
+==================
+
+.. kernel-doc:: drivers/tty/n_tty.c
+ :internal:
diff --git a/Documentation/tty/tty_buffer.rst b/Documentation/tty/tty_buffer.rst
new file mode 100644
index 000000000000..a39d4781e0d2
--- /dev/null
+++ b/Documentation/tty/tty_buffer.rst
@@ -0,0 +1,46 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==========
+TTY Buffer
+==========
+
+.. contents:: :local:
+
+Here, we document functions for taking care of tty buffer and their flipping.
+Drivers are supposed to fill the buffer by one of those functions below and
+then flip the buffer, so that the data are passed to :doc:`line discipline
+<tty_ldisc>` for further processing.
+
+Flip Buffer Management
+======================
+
+.. kernel-doc:: drivers/tty/tty_buffer.c
+ :identifiers: tty_prepare_flip_string tty_insert_flip_string_fixed_flag
+ tty_insert_flip_string_flags __tty_insert_flip_char
+ tty_flip_buffer_push tty_ldisc_receive_buf
+
+----
+
+Other Functions
+===============
+
+.. kernel-doc:: drivers/tty/tty_buffer.c
+ :identifiers: tty_buffer_space_avail tty_buffer_set_limit
+
+----
+
+Buffer Locking
+==============
+
+These are used only in special circumstances. Avoid them.
+
+.. kernel-doc:: drivers/tty/tty_buffer.c
+ :identifiers: tty_buffer_lock_exclusive tty_buffer_unlock_exclusive
+
+----
+
+Internal Functions
+==================
+
+.. kernel-doc:: drivers/tty/tty_buffer.c
+ :internal:
diff --git a/Documentation/tty/tty_driver.rst b/Documentation/tty/tty_driver.rst
new file mode 100644
index 000000000000..cc529f863406
--- /dev/null
+++ b/Documentation/tty/tty_driver.rst
@@ -0,0 +1,128 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=============================
+TTY Driver and TTY Operations
+=============================
+
+.. contents:: :local:
+
+Allocation
+==========
+
+The first thing a driver needs to do is to allocate a struct tty_driver. This
+is done by tty_alloc_driver() (or __tty_alloc_driver()). Next, the newly
+allocated structure is filled with information. See `TTY Driver Reference`_ at
+the end of this document on what actually shall be filled in.
+
+The allocation routines expect a number of devices the driver can handle at
+most and flags. Flags are those starting ``TTY_DRIVER_`` listed and described
+in `TTY Driver Flags`_ below.
+
+When the driver is about to be freed, tty_driver_kref_put() is called on that.
+It will decrements the reference count and if it reaches zero, the driver is
+freed.
+
+For reference, both allocation and deallocation functions are explained here in
+detail:
+
+.. kernel-doc:: drivers/tty/tty_io.c
+ :identifiers: __tty_alloc_driver tty_driver_kref_put
+
+TTY Driver Flags
+----------------
+
+Here comes the documentation of flags accepted by tty_alloc_driver() (or
+__tty_alloc_driver()):
+
+.. kernel-doc:: include/linux/tty_driver.h
+ :doc: TTY Driver Flags
+
+----
+
+Registration
+============
+
+When a struct tty_driver is allocated and filled in, it can be registered using
+tty_register_driver(). It is recommended to pass ``TTY_DRIVER_DYNAMIC_DEV`` in
+flags of tty_alloc_driver(). If it is not passed, *all* devices are also
+registered during tty_register_driver() and the following paragraph of
+registering devices can be skipped for such drivers. However, the struct
+tty_port part in `Registering Devices`_ is still relevant there.
+
+.. kernel-doc:: drivers/tty/tty_io.c
+ :identifiers: tty_register_driver tty_unregister_driver
+
+Registering Devices
+-------------------
+
+Every TTY device shall be backed by a struct tty_port. Usually, TTY drivers
+embed tty_port into device's private structures. Further details about handling
+tty_port can be found in :doc:`tty_port`. The driver is also recommended to use
+tty_port's reference counting by tty_port_get() and tty_port_put(). The final
+put is supposed to free the tty_port including the device's private struct.
+
+Unless ``TTY_DRIVER_DYNAMIC_DEV`` was passed as flags to tty_alloc_driver(),
+TTY driver is supposed to register every device discovered in the system
+(the latter is preferred). This is performed by tty_register_device(). Or by
+tty_register_device_attr() if the driver wants to expose some information
+through struct attribute_group. Both of them register ``index``'th device and
+upon return, the device can be opened. There are also preferred tty_port
+variants described in `Linking Devices to Ports`_ later. It is up to driver to
+manage free indices and choosing the right one. The TTY layer only refuses to
+register more devices than passed to tty_alloc_driver().
+
+When the device is opened, the TTY layer allocates struct tty_struct and starts
+calling operations from :c:member:`tty_driver.ops`, see `TTY Operations
+Reference`_.
+
+The registration routines are documented as follows:
+
+.. kernel-doc:: drivers/tty/tty_io.c
+ :identifiers: tty_register_device tty_register_device_attr
+ tty_unregister_device
+
+----
+
+Linking Devices to Ports
+------------------------
+As stated earlier, every TTY device shall have a struct tty_port assigned to
+it. It must be known to the TTY layer at :c:member:`tty_driver.ops.install()`
+at latest. There are few helpers to *link* the two. Ideally, the driver uses
+tty_port_register_device() or tty_port_register_device_attr() instead of
+tty_register_device() and tty_register_device_attr() at the registration time.
+This way, the driver needs not care about linking later on.
+
+If that is not possible, the driver still can link the tty_port to a specific
+index *before* the actual registration by tty_port_link_device(). If it still
+does not fit, tty_port_install() can be used from the
+:c:member:`tty_driver.ops.install` hook as a last resort. The last one is
+dedicated mostly for in-memory devices like PTY where tty_ports are allocated
+on demand.
+
+The linking routines are documented here:
+
+.. kernel-doc:: drivers/tty/tty_port.c
+ :identifiers: tty_port_link_device tty_port_register_device
+ tty_port_register_device_attr
+
+----
+
+TTY Driver Reference
+====================
+
+All members of struct tty_driver are documented here. The required members are
+noted at the end. struct tty_operations are documented next.
+
+.. kernel-doc:: include/linux/tty_driver.h
+ :identifiers: tty_driver
+
+----
+
+TTY Operations Reference
+========================
+
+When a TTY is registered, these driver hooks can be invoked by the TTY layer:
+
+.. kernel-doc:: include/linux/tty_driver.h
+ :identifiers: tty_operations
+
diff --git a/Documentation/tty/tty_internals.rst b/Documentation/tty/tty_internals.rst
new file mode 100644
index 000000000000..d0d415820300
--- /dev/null
+++ b/Documentation/tty/tty_internals.rst
@@ -0,0 +1,31 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=============
+TTY Internals
+=============
+
+.. contents:: :local:
+
+Kopen
+=====
+
+These functions serve for opening a TTY from the kernelspace:
+
+.. kernel-doc:: drivers/tty/tty_io.c
+ :identifiers: tty_kopen_exclusive tty_kopen_shared tty_kclose
+
+----
+
+Exported Internal Functions
+===========================
+
+.. kernel-doc:: drivers/tty/tty_io.c
+ :identifiers: tty_release_struct tty_dev_name_to_number tty_get_icount
+
+----
+
+Internal Functions
+==================
+
+.. kernel-doc:: drivers/tty/tty_io.c
+ :internal:
diff --git a/Documentation/tty/tty_ldisc.rst b/Documentation/tty/tty_ldisc.rst
new file mode 100644
index 000000000000..5144751be804
--- /dev/null
+++ b/Documentation/tty/tty_ldisc.rst
@@ -0,0 +1,85 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===================
+TTY Line Discipline
+===================
+
+.. contents:: :local:
+
+TTY line discipline process all incoming and outgoing character from/to a tty
+device. The default line discipline is :doc:`N_TTY <n_tty>`. It is also a
+fallback if establishing any other discipline for a tty fails. If even N_TTY
+fails, N_NULL takes over. That never fails, but also does not process any
+characters -- it throws them away.
+
+Registration
+============
+
+Line disciplines are registered with tty_register_ldisc() passing the ldisc
+structure. At the point of registration the discipline must be ready to use and
+it is possible it will get used before the call returns success. If the call
+returns an error then it won’t get called. Do not re-use ldisc numbers as they
+are part of the userspace ABI and writing over an existing ldisc will cause
+demons to eat your computer. You must not re-register over the top of the line
+discipline even with the same data or your computer again will be eaten by
+demons. In order to remove a line discipline call tty_unregister_ldisc().
+
+Heed this warning: the reference count field of the registered copies of the
+tty_ldisc structure in the ldisc table counts the number of lines using this
+discipline. The reference count of the tty_ldisc structure within a tty counts
+the number of active users of the ldisc at this instant. In effect it counts
+the number of threads of execution within an ldisc method (plus those about to
+enter and exit although this detail matters not).
+
+.. kernel-doc:: drivers/tty/tty_ldisc.c
+ :identifiers: tty_register_ldisc tty_unregister_ldisc
+
+Other Functions
+===============
+
+.. kernel-doc:: drivers/tty/tty_ldisc.c
+ :identifiers: tty_set_ldisc tty_ldisc_flush
+
+Line Discipline Operations Reference
+====================================
+
+.. kernel-doc:: include/linux/tty_ldisc.h
+ :identifiers: tty_ldisc_ops
+
+Driver Access
+=============
+
+Line discipline methods can call the methods of the underlying hardware driver.
+These are documented as a part of struct tty_operations.
+
+TTY Flags
+=========
+
+Line discipline methods have access to :c:member:`tty_struct.flags` field. See
+:doc:`tty_struct`.
+
+Locking
+=======
+
+Callers to the line discipline functions from the tty layer are required to
+take line discipline locks. The same is true of calls from the driver side
+but not yet enforced.
+
+.. kernel-doc:: drivers/tty/tty_ldisc.c
+ :identifiers: tty_ldisc_ref_wait tty_ldisc_ref tty_ldisc_deref
+
+While these functions are slightly slower than the old code they should have
+minimal impact as most receive logic uses the flip buffers and they only
+need to take a reference when they push bits up through the driver.
+
+A caution: The :c:member:`tty_ldisc_ops.open()`,
+:c:member:`tty_ldisc_ops.close()` and :c:member:`tty_driver.set_ldisc()`
+functions are called with the ldisc unavailable. Thus tty_ldisc_ref() will fail
+in this situation if used within these functions. Ldisc and driver code
+calling its own functions must be careful in this case.
+
+Internal Functions
+==================
+
+.. kernel-doc:: drivers/tty/tty_ldisc.c
+ :internal:
diff --git a/Documentation/tty/tty_port.rst b/Documentation/tty/tty_port.rst
new file mode 100644
index 000000000000..5cb90e954fcf
--- /dev/null
+++ b/Documentation/tty/tty_port.rst
@@ -0,0 +1,70 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+========
+TTY Port
+========
+
+.. contents:: :local:
+
+The TTY drivers are advised to use struct tty_port helpers as much as possible.
+If the drivers implement :c:member:`tty_port.ops.activate()` and
+:c:member:`tty_port.ops.shutdown()`, they can use tty_port_open(),
+tty_port_close(), and tty_port_hangup() in respective
+:c:member:`tty_struct.ops` hooks.
+
+The reference and details are contained in the `TTY Port Reference`_ and `TTY
+Port Operations Reference`_ sections at the bottom.
+
+TTY Port Functions
+==================
+
+Init & Destroy
+--------------
+
+.. kernel-doc:: drivers/tty/tty_port.c
+ :identifiers: tty_port_init tty_port_destroy
+ tty_port_get tty_port_put
+
+Open/Close/Hangup Helpers
+-------------------------
+
+.. kernel-doc:: drivers/tty/tty_port.c
+ :identifiers: tty_port_install tty_port_open tty_port_block_til_ready
+ tty_port_close tty_port_close_start tty_port_close_end tty_port_hangup
+ tty_port_shutdown
+
+TTY Refcounting
+---------------
+
+.. kernel-doc:: drivers/tty/tty_port.c
+ :identifiers: tty_port_tty_get tty_port_tty_set
+
+TTY Helpers
+-----------
+
+.. kernel-doc:: drivers/tty/tty_port.c
+ :identifiers: tty_port_tty_hangup tty_port_tty_wakeup
+
+
+Modem Signals
+-------------
+
+.. kernel-doc:: drivers/tty/tty_port.c
+ :identifiers: tty_port_carrier_raised tty_port_raise_dtr_rts
+ tty_port_lower_dtr_rts
+
+----
+
+TTY Port Reference
+==================
+
+.. kernel-doc:: include/linux/tty_port.h
+ :identifiers: tty_port
+
+----
+
+TTY Port Operations Reference
+=============================
+
+.. kernel-doc:: include/linux/tty_port.h
+ :identifiers: tty_port_operations
diff --git a/Documentation/tty/tty_struct.rst b/Documentation/tty/tty_struct.rst
new file mode 100644
index 000000000000..c72f5a4293b2
--- /dev/null
+++ b/Documentation/tty/tty_struct.rst
@@ -0,0 +1,81 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==========
+TTY Struct
+==========
+
+.. contents:: :local:
+
+struct tty_struct is allocated by the TTY layer upon the first open of the TTY
+device and released after the last close. The TTY layer passes this structure
+to most of struct tty_operation's hooks. Members of tty_struct are documented
+in `TTY Struct Reference`_ at the bottom.
+
+Initialization
+==============
+
+.. kernel-doc:: drivers/tty/tty_io.c
+ :identifiers: tty_init_termios
+
+Name
+====
+
+.. kernel-doc:: drivers/tty/tty_io.c
+ :identifiers: tty_name
+
+Reference counting
+==================
+
+.. kernel-doc:: include/linux/tty.h
+ :identifiers: tty_kref_get
+
+.. kernel-doc:: drivers/tty/tty_io.c
+ :identifiers: tty_kref_put
+
+Install
+=======
+
+.. kernel-doc:: drivers/tty/tty_io.c
+ :identifiers: tty_standard_install
+
+Read & Write
+============
+
+.. kernel-doc:: drivers/tty/tty_io.c
+ :identifiers: tty_put_char
+
+Start & Stop
+============
+
+.. kernel-doc:: drivers/tty/tty_io.c
+ :identifiers: start_tty stop_tty
+
+Wakeup
+======
+
+.. kernel-doc:: drivers/tty/tty_io.c
+ :identifiers: tty_wakeup
+
+Hangup
+======
+
+.. kernel-doc:: drivers/tty/tty_io.c
+ :identifiers: tty_hangup tty_vhangup tty_hung_up_p
+
+Misc
+====
+
+.. kernel-doc:: drivers/tty/tty_io.c
+ :identifiers: tty_do_resize
+
+TTY Struct Flags
+================
+
+.. kernel-doc:: include/linux/tty.h
+ :doc: TTY Struct Flags
+
+TTY Struct Reference
+====================
+
+.. kernel-doc:: include/linux/tty.h
+ :identifiers: tty_struct
diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c
index 90635ef5dafa..6dc952b0df4a 100644
--- a/arch/alpha/kernel/srmcons.c
+++ b/arch/alpha/kernel/srmcons.c
@@ -59,7 +59,7 @@ srmcons_do_receive_chars(struct tty_port *port)
} while((result.bits.status & 1) && (++loops < 10));
if (count)
- tty_schedule_flip(port);
+ tty_flip_buffer_push(port);
return count;
}
diff --git a/arch/arm/include/debug/pl01x.S b/arch/arm/include/debug/pl01x.S
index 0c7bfa4c10db..c7e02d0628bf 100644
--- a/arch/arm/include/debug/pl01x.S
+++ b/arch/arm/include/debug/pl01x.S
@@ -8,13 +8,6 @@
*/
#include <linux/amba/serial.h>
-#ifdef CONFIG_DEBUG_ZTE_ZX
-#undef UART01x_DR
-#undef UART01x_FR
-#define UART01x_DR 0x04
-#define UART01x_FR 0x14
-#endif
-
#ifdef CONFIG_DEBUG_UART_PHYS
.macro addruart, rp, rv, tmp
ldr \rp, =CONFIG_DEBUG_UART_PHYS
diff --git a/drivers/accessibility/speakup/spk_ttyio.c b/drivers/accessibility/speakup/spk_ttyio.c
index 0d1f397cd896..08cf8a17754b 100644
--- a/drivers/accessibility/speakup/spk_ttyio.c
+++ b/drivers/accessibility/speakup/spk_ttyio.c
@@ -88,7 +88,7 @@ static int spk_ttyio_receive_buf2(struct tty_struct *tty,
}
if (!ldisc_data->buf_free)
- /* ttyio_in will tty_schedule_flip */
+ /* ttyio_in will tty_flip_buffer_push */
return 0;
/* Make sure the consumer has read buf before we have seen
@@ -312,7 +312,7 @@ static unsigned char ttyio_in(struct spk_synth *in_synth, int timeout)
mb();
ldisc_data->buf_free = true;
/* Let TTY push more characters */
- tty_schedule_flip(tty->port);
+ tty_flip_buffer_push(tty->port);
return rv;
}
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index ecdf8e034351..f537673ede17 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -739,14 +739,13 @@ static int hci_uart_set_flags(struct hci_uart *hu, unsigned long flags)
* Arguments:
*
* tty pointer to tty instance data
- * file pointer to open file object for device
* cmd IOCTL command code
* arg argument for IOCTL call (cmd dependent)
*
* Return Value: Command dependent
*/
-static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int hci_uart_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
+ unsigned long arg)
{
struct hci_uart *hu = tty->disc_data;
int err = 0;
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 17eb8f2aa48d..669a728095b8 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -207,8 +207,8 @@ static void serport_set_type(struct tty_struct *tty, unsigned long type)
* serport_ldisc_ioctl() allows to set the port protocol, and device ID
*/
-static int serport_ldisc_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int serport_ldisc_ioctl(struct tty_struct *tty, unsigned int cmd,
+ unsigned long arg)
{
if (cmd == SPIOCSTYPE) {
unsigned long type;
@@ -226,7 +226,6 @@ static int serport_ldisc_ioctl(struct tty_struct *tty, struct file *file,
#ifdef CONFIG_COMPAT
#define COMPAT_SPIOCSTYPE _IOW('q', 0x01, compat_ulong_t)
static int serport_ldisc_compat_ioctl(struct tty_struct *tty,
- struct file *file,
unsigned int cmd, unsigned long arg)
{
if (cmd == COMPAT_SPIOCSTYPE) {
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index d4c7ce998a34..27783fbf011f 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -673,8 +673,8 @@ static void slcan_hangup(struct tty_struct *tty)
}
/* Perform I/O control on an active SLCAN channel. */
-static int slcan_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int slcan_ioctl(struct tty_struct *tty, unsigned int cmd,
+ unsigned long arg)
{
struct slcan *sl = (struct slcan *) tty->disc_data;
unsigned int tmp;
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 8a19a06b505d..b1fc153125d9 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -681,8 +681,8 @@ static void sixpack_close(struct tty_struct *tty)
}
/* Perform I/O control on an active 6pack channel. */
-static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int sixpack_ioctl(struct tty_struct *tty, unsigned int cmd,
+ unsigned long arg)
{
struct sixpack *sp = sp_get(tty);
struct net_device *dev;
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index edde9c3ae12b..c251e04ae047 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -806,8 +806,8 @@ static void mkiss_close(struct tty_struct *tty)
}
/* Perform I/O control on an active ax25 channel. */
-static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int mkiss_ioctl(struct tty_struct *tty, unsigned int cmd,
+ unsigned long arg)
{
struct mkiss *ax = mkiss_get(tty);
struct net_device *dev;
diff --git a/drivers/net/ppp/ppp_async.c b/drivers/net/ppp/ppp_async.c
index f4429b93a9c8..15a179631903 100644
--- a/drivers/net/ppp/ppp_async.c
+++ b/drivers/net/ppp/ppp_async.c
@@ -281,8 +281,7 @@ ppp_asynctty_write(struct tty_struct *tty, struct file *file,
*/
static int
-ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
+ppp_asynctty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
{
struct asyncppp *ap = ap_get(tty);
int err, val;
diff --git a/drivers/net/ppp/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c
index b3a71b409a80..18283b7b94bc 100644
--- a/drivers/net/ppp/ppp_synctty.c
+++ b/drivers/net/ppp/ppp_synctty.c
@@ -274,8 +274,7 @@ ppp_sync_write(struct tty_struct *tty, struct file *file,
}
static int
-ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
+ppp_synctty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
{
struct syncppp *ap = sp_get(tty);
int __user *p = (int __user *)arg;
diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
index 9f3b4c1aa5ce..98f586f910fb 100644
--- a/drivers/net/slip/slip.c
+++ b/drivers/net/slip/slip.c
@@ -1072,8 +1072,8 @@ static void slip_unesc6(struct slip *sl, unsigned char s)
#endif /* CONFIG_SLIP_MODE_SLIP6 */
/* Perform I/O control on an active SLIP channel. */
-static int slip_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int slip_ioctl(struct tty_struct *tty, unsigned int cmd,
+ unsigned long arg)
{
struct slip *sl = tty->disc_data;
unsigned int tmp;
diff --git a/drivers/s390/char/keyboard.h b/drivers/s390/char/keyboard.h
index c467589c7f45..c06d399b9b1f 100644
--- a/drivers/s390/char/keyboard.h
+++ b/drivers/s390/char/keyboard.h
@@ -56,7 +56,7 @@ static inline void
kbd_put_queue(struct tty_port *port, int ch)
{
tty_insert_flip_char(port, ch, 0);
- tty_schedule_flip(port);
+ tty_flip_buffer_push(port);
}
static inline void
@@ -64,5 +64,5 @@ kbd_puts_queue(struct tty_port *port, char *cp)
{
while (*cp)
tty_insert_flip_char(port, *cp++, 0);
- tty_schedule_flip(port);
+ tty_flip_buffer_push(port);
}
diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c
index d24af649a8bb..5ed19a9857ad 100644
--- a/drivers/tty/goldfish.c
+++ b/drivers/tty/goldfish.c
@@ -151,7 +151,7 @@ static irqreturn_t goldfish_tty_interrupt(int irq, void *dev_id)
address = (unsigned long)(void *)buf;
goldfish_tty_rw(qtty, address, count, 0);
- tty_schedule_flip(&qtty->port);
+ tty_flip_buffer_push(&qtty->port);
return IRQ_HANDLED;
}
@@ -298,7 +298,7 @@ static int goldfish_tty_probe(struct platform_device *pdev)
struct resource *r;
struct device *ttydev;
void __iomem *base;
- u32 irq;
+ int irq;
unsigned int line;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -313,14 +313,12 @@ static int goldfish_tty_probe(struct platform_device *pdev)
return -ENOMEM;
}
- r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!r) {
- pr_err("goldfish_tty: No IRQ resource available!\n");
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = irq;
goto err_unmap;
}
- irq = r->start;
-
mutex_lock(&goldfish_tty_lock);
if (pdev->id == PLATFORM_DEVID_NONE)
diff --git a/drivers/tty/mips_ejtag_fdc.c b/drivers/tty/mips_ejtag_fdc.c
index 02c10a968de1..31dceb5039b5 100644
--- a/drivers/tty/mips_ejtag_fdc.c
+++ b/drivers/tty/mips_ejtag_fdc.c
@@ -955,19 +955,18 @@ static int mips_ejtag_fdc_tty_probe(struct mips_cdmm_device *dev)
mips_ejtag_fdc_con.tty_drv = driver;
init_waitqueue_head(&priv->waitqueue);
- priv->thread = kthread_create(mips_ejtag_fdc_put, priv, priv->fdc_name);
- if (IS_ERR(priv->thread)) {
- ret = PTR_ERR(priv->thread);
- dev_err(priv->dev, "Couldn't create kthread (%d)\n", ret);
- goto err_destroy_ports;
- }
/*
* Bind the writer thread to the right CPU so it can't migrate.
* The channels are per-CPU and we want all channel I/O to be on a
* single predictable CPU.
*/
- kthread_bind(priv->thread, dev->cpu);
- wake_up_process(priv->thread);
+ priv->thread = kthread_run_on_cpu(mips_ejtag_fdc_put, priv,
+ dev->cpu, "ttyFDC/%u");
+ if (IS_ERR(priv->thread)) {
+ ret = PTR_ERR(priv->thread);
+ dev_err(priv->dev, "Couldn't create kthread (%d)\n", ret);
+ goto err_destroy_ports;
+ }
/* Look for an FDC IRQ */
priv->irq = get_c0_fdc_int();
@@ -1095,15 +1094,14 @@ static int mips_ejtag_fdc_tty_cpu_up(struct mips_cdmm_device *dev)
}
/* Restart the kthread */
- priv->thread = kthread_create(mips_ejtag_fdc_put, priv, priv->fdc_name);
+ /* Bind it back to the right CPU and set it off */
+ priv->thread = kthread_run_on_cpu(mips_ejtag_fdc_put, priv,
+ dev->cpu, "ttyFDC/%u");
if (IS_ERR(priv->thread)) {
ret = PTR_ERR(priv->thread);
dev_err(priv->dev, "Couldn't re-create kthread (%d)\n", ret);
goto out;
}
- /* Bind it back to the right CPU and set it off */
- kthread_bind(priv->thread, dev->cpu);
- wake_up_process(priv->thread);
out:
return ret;
}
diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
index e37683e25055..f3c72ab1476c 100644
--- a/drivers/tty/moxa.c
+++ b/drivers/tty/moxa.c
@@ -1683,7 +1683,7 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
if (inited && !tty_throttled(tty) &&
MoxaPortRxQueue(p) > 0) { /* RX */
MoxaPortReadData(p);
- tty_schedule_flip(&p->port);
+ tty_flip_buffer_push(&p->port);
}
} else {
clear_bit(EMPTYWAIT, &p->statusflags);
@@ -1708,7 +1708,7 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
if (tty && (intr & IntrBreak) && !I_IGNBRK(tty)) { /* BREAK */
tty_insert_flip_char(&p->port, 0, TTY_BREAK);
- tty_schedule_flip(&p->port);
+ tty_flip_buffer_push(&p->port);
}
if (intr & IntrLine)
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
index 93a95a135a71..c858aff721c4 100644
--- a/drivers/tty/mxser.c
+++ b/drivers/tty/mxser.c
@@ -159,14 +159,32 @@
#define MXSER_BAUD_BASE 921600
#define MXSER_CUSTOM_DIVISOR (MXSER_BAUD_BASE * 16)
-#define PCI_DEVICE_ID_POS104UL 0x1044
-#define PCI_DEVICE_ID_CB108 0x1080
-#define PCI_DEVICE_ID_CP102UF 0x1023
-#define PCI_DEVICE_ID_CP112UL 0x1120
-#define PCI_DEVICE_ID_CB114 0x1142
-#define PCI_DEVICE_ID_CP114UL 0x1143
-#define PCI_DEVICE_ID_CB134I 0x1341
-#define PCI_DEVICE_ID_CP138U 0x1380
+#define PCI_DEVICE_ID_MOXA_RC7000 0x0001
+#define PCI_DEVICE_ID_MOXA_CP102 0x1020
+#define PCI_DEVICE_ID_MOXA_CP102UL 0x1021
+#define PCI_DEVICE_ID_MOXA_CP102U 0x1022
+#define PCI_DEVICE_ID_MOXA_CP102UF 0x1023
+#define PCI_DEVICE_ID_MOXA_C104 0x1040
+#define PCI_DEVICE_ID_MOXA_CP104U 0x1041
+#define PCI_DEVICE_ID_MOXA_CP104JU 0x1042
+#define PCI_DEVICE_ID_MOXA_CP104EL 0x1043
+#define PCI_DEVICE_ID_MOXA_POS104UL 0x1044
+#define PCI_DEVICE_ID_MOXA_CB108 0x1080
+#define PCI_DEVICE_ID_MOXA_CP112UL 0x1120
+#define PCI_DEVICE_ID_MOXA_CT114 0x1140
+#define PCI_DEVICE_ID_MOXA_CP114 0x1141
+#define PCI_DEVICE_ID_MOXA_CB114 0x1142
+#define PCI_DEVICE_ID_MOXA_CP114UL 0x1143
+#define PCI_DEVICE_ID_MOXA_CP118U 0x1180
+#define PCI_DEVICE_ID_MOXA_CP118EL 0x1181
+#define PCI_DEVICE_ID_MOXA_CP132 0x1320
+#define PCI_DEVICE_ID_MOXA_CP132U 0x1321
+#define PCI_DEVICE_ID_MOXA_CP134U 0x1340
+#define PCI_DEVICE_ID_MOXA_CB134I 0x1341
+#define PCI_DEVICE_ID_MOXA_CP138U 0x1380
+#define PCI_DEVICE_ID_MOXA_C168 0x1680
+#define PCI_DEVICE_ID_MOXA_CP168U 0x1681
+#define PCI_DEVICE_ID_MOXA_CP168EL 0x1682
#define MXSER_NPORTS(ddata) ((ddata) & 0xffU)
#define MXSER_HIGHBAUD 0x0100
@@ -194,32 +212,32 @@ static const struct {
/* driver_data correspond to the lines in the structure above
see also ISA probe function before you change something */
static const struct pci_device_id mxser_pcibrds[] = {
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C168), .driver_data = 8 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C104), .driver_data = 4 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132), .driver_data = 2 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP114), .driver_data = 4 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CT114), .driver_data = 4 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102), .driver_data = 2 | MXSER_HIGHBAUD },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104U), .driver_data = 4 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168U), .driver_data = 8 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132U), .driver_data = 2 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP134U), .driver_data = 4 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104JU),.driver_data = 4 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_RC7000), .driver_data = 8 }, /* RC7000 */
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118U), .driver_data = 8 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102UL),.driver_data = 2 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102U), .driver_data = 2 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118EL),.driver_data = 8 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168EL),.driver_data = 8 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104EL),.driver_data = 4 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB108), .driver_data = 8 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB114), .driver_data = 4 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB134I), .driver_data = 4 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U), .driver_data = 8 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL), .driver_data = 4 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL), .driver_data = 4 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF), .driver_data = 2 },
- { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP112UL), .driver_data = 2 },
+ { PCI_DEVICE_DATA(MOXA, C168, 8) },
+ { PCI_DEVICE_DATA(MOXA, C104, 4) },
+ { PCI_DEVICE_DATA(MOXA, CP132, 2) },
+ { PCI_DEVICE_DATA(MOXA, CP114, 4) },
+ { PCI_DEVICE_DATA(MOXA, CT114, 4) },
+ { PCI_DEVICE_DATA(MOXA, CP102, 2 | MXSER_HIGHBAUD) },
+ { PCI_DEVICE_DATA(MOXA, CP104U, 4) },
+ { PCI_DEVICE_DATA(MOXA, CP168U, 8) },
+ { PCI_DEVICE_DATA(MOXA, CP132U, 2) },
+ { PCI_DEVICE_DATA(MOXA, CP134U, 4) },
+ { PCI_DEVICE_DATA(MOXA, CP104JU, 4) },
+ { PCI_DEVICE_DATA(MOXA, RC7000, 8) }, /* RC7000 */
+ { PCI_DEVICE_DATA(MOXA, CP118U, 8) },
+ { PCI_DEVICE_DATA(MOXA, CP102UL, 2) },
+ { PCI_DEVICE_DATA(MOXA, CP102U, 2) },
+ { PCI_DEVICE_DATA(MOXA, CP118EL, 8) },
+ { PCI_DEVICE_DATA(MOXA, CP168EL, 8) },
+ { PCI_DEVICE_DATA(MOXA, CP104EL, 4) },
+ { PCI_DEVICE_DATA(MOXA, CB108, 8) },
+ { PCI_DEVICE_DATA(MOXA, CB114, 4) },
+ { PCI_DEVICE_DATA(MOXA, CB134I, 4) },
+ { PCI_DEVICE_DATA(MOXA, CP138U, 8) },
+ { PCI_DEVICE_DATA(MOXA, POS104UL, 4) },
+ { PCI_DEVICE_DATA(MOXA, CP114UL, 4) },
+ { PCI_DEVICE_DATA(MOXA, CP102UF, 2) },
+ { PCI_DEVICE_DATA(MOXA, CP112UL, 2) },
{ }
};
MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
@@ -251,8 +269,6 @@ struct mxser_port {
u8 MCR; /* Modem control register */
u8 FCR; /* FIFO control register */
- bool ldisc_stop_rx;
-
struct async_icount icount; /* kernel counters for 4 input interrupts */
unsigned int timeout;
@@ -262,7 +278,6 @@ struct mxser_port {
unsigned int xmit_head;
unsigned int xmit_tail;
unsigned int xmit_cnt;
- int closing;
spinlock_t slock;
};
@@ -684,27 +699,34 @@ static void mxser_change_speed(struct tty_struct *tty, struct ktermios *old_term
outb(cval, info->ioaddr + UART_LCR);
}
-static void mxser_check_modem_status(struct tty_struct *tty,
- struct mxser_port *port, int status)
+static u8 mxser_check_modem_status(struct tty_struct *tty,
+ struct mxser_port *port)
{
+ u8 msr = inb(port->ioaddr + UART_MSR);
+
+ if (!(msr & UART_MSR_ANY_DELTA))
+ return msr;
+
/* update input line counters */
- if (status & UART_MSR_TERI)
+ if (msr & UART_MSR_TERI)
port->icount.rng++;
- if (status & UART_MSR_DDSR)
+ if (msr & UART_MSR_DDSR)
port->icount.dsr++;
- if (status & UART_MSR_DDCD)
+ if (msr & UART_MSR_DDCD)
port->icount.dcd++;
- if (status & UART_MSR_DCTS)
+ if (msr & UART_MSR_DCTS)
port->icount.cts++;
wake_up_interruptible(&port->port.delta_msr_wait);
- if (tty_port_check_carrier(&port->port) && (status & UART_MSR_DDCD)) {
- if (status & UART_MSR_DCD)
+ if (tty_port_check_carrier(&port->port) && (msr & UART_MSR_DDCD)) {
+ if (msr & UART_MSR_DCD)
wake_up_interruptible(&port->port.open_wait);
}
if (tty_port_cts_enabled(&port->port))
- mxser_handle_cts(tty, port, status);
+ mxser_handle_cts(tty, port, msr);
+
+ return msr;
}
static void mxser_disable_and_clear_FIFO(struct mxser_port *info)
@@ -802,6 +824,20 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
}
/*
+ * To stop accepting input, we disable the receive line status interrupts, and
+ * tell the interrupt driver to stop checking the data ready bit in the line
+ * status register.
+ */
+static void mxser_stop_rx(struct mxser_port *info)
+{
+ info->IER &= ~UART_IER_RLSI;
+ if (info->board->must_hwid)
+ info->IER &= ~MOXA_MUST_RECV_ISR;
+
+ outb(info->IER, info->ioaddr + UART_IER);
+}
+
+/*
* This routine will shutdown a serial port
*/
static void mxser_shutdown_port(struct tty_port *port)
@@ -811,6 +847,8 @@ static void mxser_shutdown_port(struct tty_port *port)
spin_lock_irqsave(&info->slock, flags);
+ mxser_stop_rx(info);
+
/*
* clear delta_msr_wait queue to avoid mem leaks: we may free the irq
* here so the queue might never be waken up
@@ -874,64 +912,9 @@ static void mxser_flush_buffer(struct tty_struct *tty)
tty_wakeup(tty);
}
-
-static void mxser_close_port(struct tty_port *port)
-{
- struct mxser_port *info = container_of(port, struct mxser_port, port);
- unsigned long timeout;
- /*
- * At this point we stop accepting input. To do this, we
- * disable the receive line status interrupts, and tell the
- * interrupt driver to stop checking the data ready bit in the
- * line status register.
- */
- info->IER &= ~UART_IER_RLSI;
- if (info->board->must_hwid)
- info->IER &= ~MOXA_MUST_RECV_ISR;
-
- outb(info->IER, info->ioaddr + UART_IER);
- /*
- * Before we drop DTR, make sure the UART transmitter
- * has completely drained; this is especially
- * important if there is a transmit FIFO!
- */
- timeout = jiffies + HZ;
- while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) {
- schedule_timeout_interruptible(5);
- if (time_after(jiffies, timeout))
- break;
- }
-}
-
-/*
- * This routine is called when the serial port gets closed. First, we
- * wait for the last remaining data to be sent. Then, we unlink its
- * async structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- */
static void mxser_close(struct tty_struct *tty, struct file *filp)
{
- struct mxser_port *info = tty->driver_data;
- struct tty_port *port = &info->port;
-
- if (info == NULL)
- return;
- if (tty_port_close_start(port, tty, filp) == 0)
- return;
- info->closing = 1;
- mutex_lock(&port->mutex);
- mxser_close_port(port);
- mxser_flush_buffer(tty);
- if (tty_port_initialized(port) && C_HUPCL(tty))
- tty_port_lower_dtr_rts(port);
- mxser_shutdown_port(port);
- tty_port_set_initialized(port, 0);
- mutex_unlock(&port->mutex);
- info->closing = 0;
- /* Right now the tty_port set is done outside of the close_end helper
- as we don't yet have everyone using refcounts */
- tty_port_close_end(port, tty);
- tty_port_tty_set(port, NULL);
+ tty_port_close(tty->port, tty, filp);
}
static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count)
@@ -940,9 +923,6 @@ static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int cou
struct mxser_port *info = tty->driver_data;
unsigned long flags;
- if (!info->port.xmit_buf)
- return 0;
-
while (1) {
c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
SERIAL_XMIT_SIZE - info->xmit_head));
@@ -973,9 +953,6 @@ static int mxser_put_char(struct tty_struct *tty, unsigned char ch)
struct mxser_port *info = tty->driver_data;
unsigned long flags;
- if (!info->port.xmit_buf)
- return 0;
-
if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
return 0;
@@ -993,7 +970,7 @@ static void mxser_flush_chars(struct tty_struct *tty)
{
struct mxser_port *info = tty->driver_data;
- if (!info->xmit_cnt || tty->flow.stopped || !info->port.xmit_buf ||
+ if (!info->xmit_cnt || tty->flow.stopped ||
(tty->hw_stopped && !mxser_16550A_or_MUST(info)))
return;
@@ -1153,25 +1130,24 @@ static int mxser_get_lsr_info(struct mxser_port *info,
static int mxser_tiocmget(struct tty_struct *tty)
{
struct mxser_port *info = tty->driver_data;
- unsigned char control, status;
+ unsigned char control;
unsigned long flags;
+ u8 msr;
if (tty_io_error(tty))
return -EIO;
spin_lock_irqsave(&info->slock, flags);
control = info->MCR;
- status = inb(info->ioaddr + UART_MSR);
- if (status & UART_MSR_ANY_DELTA)
- mxser_check_modem_status(tty, info, status);
+ msr = mxser_check_modem_status(tty, info);
spin_unlock_irqrestore(&info->slock, flags);
return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
- ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) |
- ((status & UART_MSR_RI) ? TIOCM_RNG : 0) |
- ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) |
- ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
+ ((msr & UART_MSR_DCD) ? TIOCM_CAR : 0) |
+ ((msr & UART_MSR_RI) ? TIOCM_RNG : 0) |
+ ((msr & UART_MSR_DSR) ? TIOCM_DSR : 0) |
+ ((msr & UART_MSR_CTS) ? TIOCM_CTS : 0);
}
static int mxser_tiocmset(struct tty_struct *tty,
@@ -1326,11 +1302,14 @@ static int mxser_get_icount(struct tty_struct *tty,
return 0;
}
-static void mxser_stoprx(struct tty_struct *tty)
+/*
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ */
+static void mxser_throttle(struct tty_struct *tty)
{
struct mxser_port *info = tty->driver_data;
- info->ldisc_stop_rx = true;
if (I_IXOFF(tty)) {
if (info->board->must_hwid) {
info->IER &= ~MOXA_MUST_RECV_ISR;
@@ -1349,21 +1328,11 @@ static void mxser_stoprx(struct tty_struct *tty)
}
}
-/*
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- */
-static void mxser_throttle(struct tty_struct *tty)
-{
- mxser_stoprx(tty);
-}
-
static void mxser_unthrottle(struct tty_struct *tty)
{
struct mxser_port *info = tty->driver_data;
/* startrx */
- info->ldisc_stop_rx = false;
if (I_IXOFF(tty)) {
if (info->x_char)
info->x_char = 0;
@@ -1409,7 +1378,7 @@ static void mxser_start(struct tty_struct *tty)
unsigned long flags;
spin_lock_irqsave(&info->slock, flags);
- if (info->xmit_cnt && info->port.xmit_buf)
+ if (info->xmit_cnt)
__mxser_start_tx(info);
spin_unlock_irqrestore(&info->slock, flags);
}
@@ -1442,15 +1411,25 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi
}
}
+static bool mxser_tx_empty(struct mxser_port *info)
+{
+ unsigned long flags;
+ u8 lsr;
+
+ spin_lock_irqsave(&info->slock, flags);
+ lsr = inb(info->ioaddr + UART_LSR);
+ spin_unlock_irqrestore(&info->slock, flags);
+
+ return !(lsr & UART_LSR_TEMT);
+}
+
/*
* mxser_wait_until_sent() --- wait until the transmitter is empty
*/
static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
{
struct mxser_port *info = tty->driver_data;
- unsigned long orig_jiffies, char_time;
- unsigned long flags;
- int lsr;
+ unsigned long expire, char_time;
if (info->type == PORT_UNKNOWN)
return;
@@ -1458,7 +1437,6 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
if (info->xmit_fifo_size == 0)
return; /* Just in case.... */
- orig_jiffies = jiffies;
/*
* Set the check interval to be 1/5 of the estimated time to
* send a single character, and make it at least 1. The check
@@ -1473,6 +1451,9 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
char_time = 1;
if (timeout && timeout < char_time)
char_time = timeout;
+
+ char_time = jiffies_to_msecs(char_time);
+
/*
* If the transmitter hasn't cleared in twice the approximate
* amount of time to send the entire FIFO, it probably won't
@@ -1485,18 +1466,15 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
if (!timeout || timeout > 2 * info->timeout)
timeout = 2 * info->timeout;
- spin_lock_irqsave(&info->slock, flags);
- while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) {
- spin_unlock_irqrestore(&info->slock, flags);
- schedule_timeout_interruptible(char_time);
- spin_lock_irqsave(&info->slock, flags);
+ expire = jiffies + timeout;
+
+ while (mxser_tx_empty(info)) {
+ msleep_interruptible(char_time);
if (signal_pending(current))
break;
- if (timeout && time_after(jiffies, orig_jiffies + timeout))
+ if (time_after(jiffies, expire))
break;
}
- spin_unlock_irqrestore(&info->slock, flags);
- set_current_state(TASK_RUNNING);
}
/*
@@ -1531,8 +1509,7 @@ static int mxser_rs_break(struct tty_struct *tty, int break_state)
return 0;
}
-static bool mxser_receive_chars_new(struct tty_struct *tty,
- struct mxser_port *port, u8 status)
+static bool mxser_receive_chars_new(struct mxser_port *port, u8 status)
{
enum mxser_must_hwid hwid = port->board->must_hwid;
u8 gdl;
@@ -1546,12 +1523,10 @@ static bool mxser_receive_chars_new(struct tty_struct *tty,
if (hwid == MOXA_MUST_MU150_HWID)
gdl &= MOXA_MUST_GDL_MASK;
- if (gdl >= tty->receive_room && !port->ldisc_stop_rx)
- mxser_stoprx(tty);
-
while (gdl--) {
u8 ch = inb(port->ioaddr + UART_RX);
- tty_insert_flip_char(&port->port, ch, 0);
+ if (!tty_insert_flip_char(&port->port, ch, 0))
+ port->icount.buf_overrun++;
}
return true;
@@ -1561,10 +1536,8 @@ static u8 mxser_receive_chars_old(struct tty_struct *tty,
struct mxser_port *port, u8 status)
{
enum mxser_must_hwid hwid = port->board->must_hwid;
- int recv_room = tty->receive_room;
int ignored = 0;
int max = 256;
- int cnt = 0;
u8 ch;
do {
@@ -1599,14 +1572,10 @@ static u8 mxser_receive_chars_old(struct tty_struct *tty,
port->icount.overrun++;
}
}
- tty_insert_flip_char(&port->port, ch, flag);
- cnt++;
- if (cnt >= recv_room) {
- if (!port->ldisc_stop_rx)
- mxser_stoprx(tty);
+ if (!tty_insert_flip_char(&port->port, ch, flag)) {
+ port->icount.buf_overrun++;
break;
}
-
}
if (hwid)
@@ -1621,10 +1590,7 @@ static u8 mxser_receive_chars_old(struct tty_struct *tty,
static u8 mxser_receive_chars(struct tty_struct *tty,
struct mxser_port *port, u8 status)
{
- if (tty->receive_room == 0 && !port->ldisc_stop_rx)
- mxser_stoprx(tty);
-
- if (!mxser_receive_chars_new(tty, port, status))
+ if (!mxser_receive_chars_new(port, status))
status = mxser_receive_chars_old(tty, port, status);
tty_flip_buffer_push(&port->port);
@@ -1634,7 +1600,7 @@ static u8 mxser_receive_chars(struct tty_struct *tty,
static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port)
{
- int count, cnt;
+ int count;
if (port->x_char) {
outb(port->x_char, port->ioaddr + UART_TX);
@@ -1643,27 +1609,22 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port
return;
}
- if (port->port.xmit_buf == NULL)
- return;
-
if (!port->xmit_cnt || tty->flow.stopped ||
(tty->hw_stopped && !mxser_16550A_or_MUST(port))) {
__mxser_stop_tx(port);
return;
}
- cnt = port->xmit_cnt;
count = port->xmit_fifo_size;
do {
outb(port->port.xmit_buf[port->xmit_tail++],
port->ioaddr + UART_TX);
- port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1);
+ port->xmit_tail &= SERIAL_XMIT_SIZE - 1;
+ port->icount.tx++;
if (!--port->xmit_cnt)
break;
} while (--count > 0);
- port->icount.tx += (cnt - port->xmit_cnt);
-
if (port->xmit_cnt < WAKEUP_CHARS)
tty_wakeup(tty);
@@ -1674,7 +1635,7 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port
static bool mxser_port_isr(struct mxser_port *port)
{
struct tty_struct *tty;
- u8 iir, msr, status;
+ u8 iir, status;
bool error = false;
iir = inb(port->ioaddr + UART_IIR);
@@ -1683,7 +1644,7 @@ static bool mxser_port_isr(struct mxser_port *port)
iir &= MOXA_MUST_IIR_MASK;
tty = tty_port_tty_get(&port->port);
- if (!tty || port->closing || !tty_port_initialized(&port->port)) {
+ if (!tty) {
status = inb(port->ioaddr + UART_LSR);
outb(port->FCR | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
port->ioaddr + UART_FCR);
@@ -1707,9 +1668,7 @@ static bool mxser_port_isr(struct mxser_port *port)
status = mxser_receive_chars(tty, port, status);
}
- msr = inb(port->ioaddr + UART_MSR);
- if (msr & UART_MSR_ANY_DELTA)
- mxser_check_modem_status(tty, port, msr);
+ mxser_check_modem_status(tty, port);
if (port->board->must_hwid) {
if (iir == 0x02 && (status & UART_LSR_THRE))
@@ -1836,7 +1795,6 @@ static void mxser_initbrd(struct mxser_board *brd, bool high_baud)
tty_port_init(&info->port);
info->port.ops = &mxser_port_ops;
info->board = brd;
- info->ldisc_stop_rx = false;
/* Enhance mode enabled here */
if (brd->must_hwid != MOXA_OTHER_UART)
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 0b96b14bbfe1..ba27b274c967 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -2074,8 +2074,6 @@ static void gsm1_receive(struct gsm_mux *gsm, unsigned char c)
/**
* gsm_error - handle tty error
* @gsm: ldisc data
- * @data: byte received (may be invalid)
- * @flag: error received
*
* Handle an error in the receipt of data for a frame. Currently we just
* go back to hunting for a SOF.
@@ -2083,8 +2081,7 @@ static void gsm1_receive(struct gsm_mux *gsm, unsigned char c)
* FIXME: better diagnostics ?
*/
-static void gsm_error(struct gsm_mux *gsm,
- unsigned char data, unsigned char flag)
+static void gsm_error(struct gsm_mux *gsm)
{
gsm->state = GSM_SEARCH;
gsm->io_error++;
@@ -2504,7 +2501,7 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
case TTY_BREAK:
case TTY_PARITY:
case TTY_FRAME:
- gsm_error(gsm, *cp, flags);
+ gsm_error(gsm);
break;
default:
WARN_ONCE(1, "%s: unknown flag %d\n",
@@ -2690,8 +2687,8 @@ static __poll_t gsmld_poll(struct tty_struct *tty, struct file *file,
return mask;
}
-static int gsmld_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int gsmld_ioctl(struct tty_struct *tty, unsigned int cmd,
+ unsigned long arg)
{
struct gsm_config c;
struct gsm_mux *gsm = tty->disc_data;
diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c
index 23ba1fc99df8..94c1ec2dd754 100644
--- a/drivers/tty/n_hdlc.c
+++ b/drivers/tty/n_hdlc.c
@@ -593,14 +593,13 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
/**
* n_hdlc_tty_ioctl - process IOCTL system call for the tty device.
* @tty: pointer to tty instance data
- * @file: pointer to open file object for device
* @cmd: IOCTL command code
* @arg: argument for IOCTL call (cmd dependent)
*
* Returns command dependent result.
*/
-static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int n_hdlc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
+ unsigned long arg)
{
struct n_hdlc *n_hdlc = tty->disc_data;
int error = 0;
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 5be6d02dc690..a38fd65e39ab 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -186,17 +186,16 @@ static void tty_copy(struct tty_struct *tty, void *to, size_t tail, size_t n)
}
/**
- * n_tty_kick_worker - start input worker (if required)
- * @tty: terminal
+ * n_tty_kick_worker - start input worker (if required)
+ * @tty: terminal
*
- * Re-schedules the flip buffer work if it may have stopped
+ * Re-schedules the flip buffer work if it may have stopped.
*
- * Caller holds exclusive termios_rwsem
- * or
- * n_tty_read()/consumer path:
- * holds non-exclusive termios_rwsem
+ * Locking:
+ * * Caller holds exclusive %termios_rwsem, or
+ * * n_tty_read()/consumer path:
+ * holds non-exclusive %termios_rwsem
*/
-
static void n_tty_kick_worker(struct tty_struct *tty)
{
struct n_tty_data *ldata = tty->disc_data;
@@ -230,14 +229,12 @@ static ssize_t chars_in_buffer(struct tty_struct *tty)
}
/**
- * n_tty_write_wakeup - asynchronous I/O notifier
- * @tty: tty device
+ * n_tty_write_wakeup - asynchronous I/O notifier
+ * @tty: tty device
*
- * Required for the ptys, serial driver etc. since processes
- * that attach themselves to the master and rely on ASYNC
- * IO must be woken up
+ * Required for the ptys, serial driver etc. since processes that attach
+ * themselves to the master and rely on ASYNC IO must be woken up.
*/
-
static void n_tty_write_wakeup(struct tty_struct *tty)
{
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
@@ -300,16 +297,16 @@ static void n_tty_check_unthrottle(struct tty_struct *tty)
}
/**
- * put_tty_queue - add character to tty
- * @c: character
- * @ldata: n_tty data
+ * put_tty_queue - add character to tty
+ * @c: character
+ * @ldata: n_tty data
*
- * Add a character to the tty read_buf queue.
+ * Add a character to the tty read_buf queue.
*
- * n_tty_receive_buf()/producer path:
- * caller holds non-exclusive termios_rwsem
+ * Locking:
+ * * n_tty_receive_buf()/producer path:
+ * caller holds non-exclusive %termios_rwsem
*/
-
static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
{
*read_buf_addr(ldata, ldata->read_head) = c;
@@ -317,16 +314,16 @@ static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
}
/**
- * reset_buffer_flags - reset buffer state
- * @ldata: line disc data to reset
+ * reset_buffer_flags - reset buffer state
+ * @ldata: line disc data to reset
*
- * Reset the read buffer counters and clear the flags.
- * Called from n_tty_open() and n_tty_flush_buffer().
+ * Reset the read buffer counters and clear the flags. Called from
+ * n_tty_open() and n_tty_flush_buffer().
*
- * Locking: caller holds exclusive termios_rwsem
- * (or locking is not required)
+ * Locking:
+ * * caller holds exclusive %termios_rwsem, or
+ * * (locking is not required)
*/
-
static void reset_buffer_flags(struct n_tty_data *ldata)
{
ldata->read_head = ldata->canon_head = ldata->read_tail = 0;
@@ -351,19 +348,18 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty)
}
/**
- * n_tty_flush_buffer - clean input queue
- * @tty: terminal device
+ * n_tty_flush_buffer - clean input queue
+ * @tty: terminal device
*
- * Flush the input buffer. Called when the tty layer wants the
- * buffer flushed (eg at hangup) or when the N_TTY line discipline
- * internally has to clean the pending queue (for example some signals).
+ * Flush the input buffer. Called when the tty layer wants the buffer flushed
+ * (eg at hangup) or when the %N_TTY line discipline internally has to clean
+ * the pending queue (for example some signals).
*
- * Holds termios_rwsem to exclude producer/consumer while
- * buffer indices are reset.
+ * Holds %termios_rwsem to exclude producer/consumer while buffer indices are
+ * reset.
*
- * Locking: ctrl.lock, exclusive termios_rwsem
+ * Locking: %ctrl.lock, exclusive %termios_rwsem
*/
-
static void n_tty_flush_buffer(struct tty_struct *tty)
{
down_write(&tty->termios_rwsem);
@@ -376,55 +372,50 @@ static void n_tty_flush_buffer(struct tty_struct *tty)
}
/**
- * is_utf8_continuation - utf8 multibyte check
- * @c: byte to check
+ * is_utf8_continuation - utf8 multibyte check
+ * @c: byte to check
*
- * Returns true if the utf8 character 'c' is a multibyte continuation
- * character. We use this to correctly compute the on screen size
- * of the character when printing
+ * Returns: true if the utf8 character @c is a multibyte continuation
+ * character. We use this to correctly compute the on-screen size of the
+ * character when printing.
*/
-
static inline int is_utf8_continuation(unsigned char c)
{
return (c & 0xc0) == 0x80;
}
/**
- * is_continuation - multibyte check
- * @c: byte to check
- * @tty: terminal device
+ * is_continuation - multibyte check
+ * @c: byte to check
+ * @tty: terminal device
*
- * Returns true if the utf8 character 'c' is a multibyte continuation
- * character and the terminal is in unicode mode.
+ * Returns: true if the utf8 character @c is a multibyte continuation character
+ * and the terminal is in unicode mode.
*/
-
static inline int is_continuation(unsigned char c, struct tty_struct *tty)
{
return I_IUTF8(tty) && is_utf8_continuation(c);
}
/**
- * do_output_char - output one character
- * @c: character (or partial unicode symbol)
- * @tty: terminal device
- * @space: space available in tty driver write buffer
+ * do_output_char - output one character
+ * @c: character (or partial unicode symbol)
+ * @tty: terminal device
+ * @space: space available in tty driver write buffer
*
- * This is a helper function that handles one output character
- * (including special characters like TAB, CR, LF, etc.),
- * doing OPOST processing and putting the results in the
- * tty driver's write buffer.
+ * This is a helper function that handles one output character (including
+ * special characters like TAB, CR, LF, etc.), doing OPOST processing and
+ * putting the results in the tty driver's write buffer.
*
- * Note that Linux currently ignores TABDLY, CRDLY, VTDLY, FFDLY
- * and NLDLY. They simply aren't relevant in the world today.
- * If you ever need them, add them here.
+ * Note that Linux currently ignores TABDLY, CRDLY, VTDLY, FFDLY and NLDLY.
+ * They simply aren't relevant in the world today. If you ever need them, add
+ * them here.
*
- * Returns the number of bytes of buffer space used or -1 if
- * no space left.
+ * Returns: the number of bytes of buffer space used or -1 if no space left.
*
- * Locking: should be called under the output_lock to protect
- * the column state and space left in the buffer
+ * Locking: should be called under the %output_lock to protect the column state
+ * and space left in the buffer.
*/
-
static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
{
struct n_tty_data *ldata = tty->disc_data;
@@ -487,19 +478,18 @@ static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
}
/**
- * process_output - output post processor
- * @c: character (or partial unicode symbol)
- * @tty: terminal device
+ * process_output - output post processor
+ * @c: character (or partial unicode symbol)
+ * @tty: terminal device
*
- * Output one character with OPOST processing.
- * Returns -1 when the output device is full and the character
- * must be retried.
+ * Output one character with OPOST processing.
*
- * Locking: output_lock to protect column state and space left
- * (also, this is called from n_tty_write under the
- * tty layer write lock)
+ * Returns: -1 when the output device is full and the character must be
+ * retried.
+ *
+ * Locking: %output_lock to protect column state and space left (also, this is
+ *called from n_tty_write() under the tty layer write lock).
*/
-
static int process_output(unsigned char c, struct tty_struct *tty)
{
struct n_tty_data *ldata = tty->disc_data;
@@ -518,24 +508,23 @@ static int process_output(unsigned char c, struct tty_struct *tty)
}
/**
- * process_output_block - block post processor
- * @tty: terminal device
- * @buf: character buffer
- * @nr: number of bytes to output
- *
- * Output a block of characters with OPOST processing.
- * Returns the number of characters output.
- *
- * This path is used to speed up block console writes, among other
- * things when processing blocks of output data. It handles only
- * the simple cases normally found and helps to generate blocks of
- * symbols for the console driver and thus improve performance.
- *
- * Locking: output_lock to protect column state and space left
- * (also, this is called from n_tty_write under the
- * tty layer write lock)
+ * process_output_block - block post processor
+ * @tty: terminal device
+ * @buf: character buffer
+ * @nr: number of bytes to output
+ *
+ * Output a block of characters with OPOST processing.
+ *
+ * This path is used to speed up block console writes, among other things when
+ * processing blocks of output data. It handles only the simple cases normally
+ * found and helps to generate blocks of symbols for the console driver and
+ * thus improve performance.
+ *
+ * Returns: the number of characters output.
+ *
+ * Locking: %output_lock to protect column state and space left (also, this is
+ * called from n_tty_write() under the tty layer write lock).
*/
-
static ssize_t process_output_block(struct tty_struct *tty,
const unsigned char *buf, unsigned int nr)
{
@@ -596,30 +585,27 @@ break_out:
}
/**
- * process_echoes - write pending echo characters
- * @tty: terminal device
+ * __process_echoes - write pending echo characters
+ * @tty: terminal device
*
- * Write previously buffered echo (and other ldisc-generated)
- * characters to the tty.
+ * Write previously buffered echo (and other ldisc-generated) characters to the
+ * tty.
*
- * Characters generated by the ldisc (including echoes) need to
- * be buffered because the driver's write buffer can fill during
- * heavy program output. Echoing straight to the driver will
- * often fail under these conditions, causing lost characters and
- * resulting mismatches of ldisc state information.
+ * Characters generated by the ldisc (including echoes) need to be buffered
+ * because the driver's write buffer can fill during heavy program output.
+ * Echoing straight to the driver will often fail under these conditions,
+ * causing lost characters and resulting mismatches of ldisc state information.
*
- * Since the ldisc state must represent the characters actually sent
- * to the driver at the time of the write, operations like certain
- * changes in column state are also saved in the buffer and executed
- * here.
+ * Since the ldisc state must represent the characters actually sent to the
+ * driver at the time of the write, operations like certain changes in column
+ * state are also saved in the buffer and executed here.
*
- * A circular fifo buffer is used so that the most recent characters
- * are prioritized. Also, when control characters are echoed with a
- * prefixed "^", the pair is treated atomically and thus not separated.
+ * A circular fifo buffer is used so that the most recent characters are
+ * prioritized. Also, when control characters are echoed with a prefixed "^",
+ * the pair is treated atomically and thus not separated.
*
- * Locking: callers must hold output_lock
+ * Locking: callers must hold %output_lock.
*/
-
static size_t __process_echoes(struct tty_struct *tty)
{
struct n_tty_data *ldata = tty->disc_data;
@@ -828,13 +814,12 @@ static void flush_echoes(struct tty_struct *tty)
}
/**
- * add_echo_byte - add a byte to the echo buffer
- * @c: unicode byte to echo
- * @ldata: n_tty data
+ * add_echo_byte - add a byte to the echo buffer
+ * @c: unicode byte to echo
+ * @ldata: n_tty data
*
- * Add a character or operation byte to the echo buffer.
+ * Add a character or operation byte to the echo buffer.
*/
-
static inline void add_echo_byte(unsigned char c, struct n_tty_data *ldata)
{
*echo_buf_addr(ldata, ldata->echo_head) = c;
@@ -843,12 +828,11 @@ static inline void add_echo_byte(unsigned char c, struct n_tty_data *ldata)
}
/**
- * echo_move_back_col - add operation to move back a column
- * @ldata: n_tty data
+ * echo_move_back_col - add operation to move back a column
+ * @ldata: n_tty data
*
- * Add an operation to the echo buffer to move back one column.
+ * Add an operation to the echo buffer to move back one column.
*/
-
static void echo_move_back_col(struct n_tty_data *ldata)
{
add_echo_byte(ECHO_OP_START, ldata);
@@ -856,13 +840,12 @@ static void echo_move_back_col(struct n_tty_data *ldata)
}
/**
- * echo_set_canon_col - add operation to set the canon column
- * @ldata: n_tty data
+ * echo_set_canon_col - add operation to set the canon column
+ * @ldata: n_tty data
*
- * Add an operation to the echo buffer to set the canon column
- * to the current column.
+ * Add an operation to the echo buffer to set the canon column to the current
+ * column.
*/
-
static void echo_set_canon_col(struct n_tty_data *ldata)
{
add_echo_byte(ECHO_OP_START, ldata);
@@ -870,20 +853,18 @@ static void echo_set_canon_col(struct n_tty_data *ldata)
}
/**
- * echo_erase_tab - add operation to erase a tab
- * @num_chars: number of character columns already used
- * @after_tab: true if num_chars starts after a previous tab
- * @ldata: n_tty data
- *
- * Add an operation to the echo buffer to erase a tab.
- *
- * Called by the eraser function, which knows how many character
- * columns have been used since either a previous tab or the start
- * of input. This information will be used later, along with
- * canon column (if applicable), to go back the correct number
- * of columns.
+ * echo_erase_tab - add operation to erase a tab
+ * @num_chars: number of character columns already used
+ * @after_tab: true if num_chars starts after a previous tab
+ * @ldata: n_tty data
+ *
+ * Add an operation to the echo buffer to erase a tab.
+ *
+ * Called by the eraser function, which knows how many character columns have
+ * been used since either a previous tab or the start of input. This
+ * information will be used later, along with canon column (if applicable), to
+ * go back the correct number of columns.
*/
-
static void echo_erase_tab(unsigned int num_chars, int after_tab,
struct n_tty_data *ldata)
{
@@ -901,16 +882,15 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab,
}
/**
- * echo_char_raw - echo a character raw
- * @c: unicode byte to echo
- * @ldata: line disc data
+ * echo_char_raw - echo a character raw
+ * @c: unicode byte to echo
+ * @ldata: line disc data
*
- * Echo user input back onto the screen. This must be called only when
- * L_ECHO(tty) is true. Called from the driver receive_buf path.
+ * Echo user input back onto the screen. This must be called only when
+ * L_ECHO(tty) is true. Called from the &tty_driver.receive_buf() path.
*
- * This variant does not treat control characters specially.
+ * This variant does not treat control characters specially.
*/
-
static void echo_char_raw(unsigned char c, struct n_tty_data *ldata)
{
if (c == ECHO_OP_START) {
@@ -922,17 +902,16 @@ static void echo_char_raw(unsigned char c, struct n_tty_data *ldata)
}
/**
- * echo_char - echo a character
- * @c: unicode byte to echo
- * @tty: terminal device
+ * echo_char - echo a character
+ * @c: unicode byte to echo
+ * @tty: terminal device
*
- * Echo user input back onto the screen. This must be called only when
- * L_ECHO(tty) is true. Called from the driver receive_buf path.
+ * Echo user input back onto the screen. This must be called only when
+ * L_ECHO(tty) is true. Called from the &tty_driver.receive_buf() path.
*
- * This variant tags control characters to be echoed as "^X"
- * (where X is the letter representing the control char).
+ * This variant tags control characters to be echoed as "^X" (where X is the
+ * letter representing the control char).
*/
-
static void echo_char(unsigned char c, struct tty_struct *tty)
{
struct n_tty_data *ldata = tty->disc_data;
@@ -948,10 +927,9 @@ static void echo_char(unsigned char c, struct tty_struct *tty)
}
/**
- * finish_erasing - complete erase
- * @ldata: n_tty data
+ * finish_erasing - complete erase
+ * @ldata: n_tty data
*/
-
static inline void finish_erasing(struct n_tty_data *ldata)
{
if (ldata->erasing) {
@@ -961,18 +939,17 @@ static inline void finish_erasing(struct n_tty_data *ldata)
}
/**
- * eraser - handle erase function
- * @c: character input
- * @tty: terminal device
+ * eraser - handle erase function
+ * @c: character input
+ * @tty: terminal device
*
- * Perform erase and necessary output when an erase character is
- * present in the stream from the driver layer. Handles the complexities
- * of UTF-8 multibyte symbols.
+ * Perform erase and necessary output when an erase character is present in the
+ * stream from the driver layer. Handles the complexities of UTF-8 multibyte
+ * symbols.
*
- * n_tty_receive_buf()/producer path:
- * caller holds non-exclusive termios_rwsem
+ * Locking: n_tty_receive_buf()/producer path:
+ * caller holds non-exclusive %termios_rwsem
*/
-
static void eraser(unsigned char c, struct tty_struct *tty)
{
struct n_tty_data *ldata = tty->disc_data;
@@ -1091,20 +1068,6 @@ static void eraser(unsigned char c, struct tty_struct *tty)
finish_erasing(ldata);
}
-/**
- * isig - handle the ISIG optio
- * @sig: signal
- * @tty: terminal
- *
- * Called when a signal is being sent due to terminal input.
- * Called from the driver receive_buf path so serialized.
- *
- * Performs input and output flush if !NOFLSH. In this context, the echo
- * buffer is 'output'. The signal is processed first to alert any current
- * readers or writers to discontinue and exit their i/o loops.
- *
- * Locking: ctrl.lock
- */
static void __isig(int sig, struct tty_struct *tty)
{
@@ -1115,6 +1078,20 @@ static void __isig(int sig, struct tty_struct *tty)
}
}
+/**
+ * isig - handle the ISIG optio
+ * @sig: signal
+ * @tty: terminal
+ *
+ * Called when a signal is being sent due to terminal input. Called from the
+ * &tty_driver.receive_buf() path, so serialized.
+ *
+ * Performs input and output flush if !NOFLSH. In this context, the echo
+ * buffer is 'output'. The signal is processed first to alert any current
+ * readers or writers to discontinue and exit their i/o loops.
+ *
+ * Locking: %ctrl.lock
+ */
static void isig(int sig, struct tty_struct *tty)
{
struct n_tty_data *ldata = tty->disc_data;
@@ -1151,18 +1128,17 @@ static void isig(int sig, struct tty_struct *tty)
}
/**
- * n_tty_receive_break - handle break
- * @tty: terminal
+ * n_tty_receive_break - handle break
+ * @tty: terminal
*
- * An RS232 break event has been hit in the incoming bitstream. This
- * can cause a variety of events depending upon the termios settings.
+ * An RS232 break event has been hit in the incoming bitstream. This can cause
+ * a variety of events depending upon the termios settings.
*
- * n_tty_receive_buf()/producer path:
- * caller holds non-exclusive termios_rwsem
+ * Locking: n_tty_receive_buf()/producer path:
+ * caller holds non-exclusive termios_rwsem
*
- * Note: may get exclusive termios_rwsem if flushing input buffer
+ * Note: may get exclusive %termios_rwsem if flushing input buffer
*/
-
static void n_tty_receive_break(struct tty_struct *tty)
{
struct n_tty_data *ldata = tty->disc_data;
@@ -1181,18 +1157,15 @@ static void n_tty_receive_break(struct tty_struct *tty)
}
/**
- * n_tty_receive_overrun - handle overrun reporting
- * @tty: terminal
+ * n_tty_receive_overrun - handle overrun reporting
+ * @tty: terminal
*
- * Data arrived faster than we could process it. While the tty
- * driver has flagged this the bits that were missed are gone
- * forever.
+ * Data arrived faster than we could process it. While the tty driver has
+ * flagged this the bits that were missed are gone forever.
*
- * Called from the receive_buf path so single threaded. Does not
- * need locking as num_overrun and overrun_time are function
- * private.
+ * Called from the receive_buf path so single threaded. Does not need locking
+ * as num_overrun and overrun_time are function private.
*/
-
static void n_tty_receive_overrun(struct tty_struct *tty)
{
struct n_tty_data *ldata = tty->disc_data;
@@ -1207,15 +1180,15 @@ static void n_tty_receive_overrun(struct tty_struct *tty)
}
/**
- * n_tty_receive_parity_error - error notifier
- * @tty: terminal device
- * @c: character
+ * n_tty_receive_parity_error - error notifier
+ * @tty: terminal device
+ * @c: character
*
- * Process a parity error and queue the right data to indicate
- * the error case if necessary.
+ * Process a parity error and queue the right data to indicate the error case
+ * if necessary.
*
- * n_tty_receive_buf()/producer path:
- * caller holds non-exclusive termios_rwsem
+ * Locking: n_tty_receive_buf()/producer path:
+ * caller holds non-exclusive %termios_rwsem
*/
static void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c)
{
@@ -1247,19 +1220,6 @@ n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c)
process_echoes(tty);
}
-/**
- * n_tty_receive_char - perform processing
- * @tty: terminal device
- * @c: character
- *
- * Process an individual character of input received from the driver.
- * This is serialized with respect to itself by the rules for the
- * driver above.
- *
- * n_tty_receive_buf()/producer path:
- * caller holds non-exclusive termios_rwsem
- * publishes canon_head if canonical mode is active
- */
static void n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
{
struct n_tty_data *ldata = tty->disc_data;
@@ -1394,6 +1354,18 @@ handle_newline:
put_tty_queue(c, ldata);
}
+/**
+ * n_tty_receive_char - perform processing
+ * @tty: terminal device
+ * @c: character
+ *
+ * Process an individual character of input received from the driver. This is
+ * serialized with respect to itself by the rules for the driver above.
+ *
+ * Locking: n_tty_receive_buf()/producer path:
+ * caller holds non-exclusive %termios_rwsem
+ * publishes canon_head if canonical mode is active
+ */
static void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
{
struct n_tty_data *ldata = tty->disc_data;
@@ -1594,38 +1566,37 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp,
}
/**
- * n_tty_receive_buf_common - process input
- * @tty: device to receive input
- * @cp: input chars
- * @fp: flags for each char (if NULL, all chars are TTY_NORMAL)
- * @count: number of input chars in @cp
- * @flow: enable flow control
- *
- * Called by the terminal driver when a block of characters has
- * been received. This function must be called from soft contexts
- * not from interrupt context. The driver is responsible for making
- * calls one at a time and in order (or using flush_to_ldisc)
- *
- * Returns the # of input chars from @cp which were processed.
- *
- * In canonical mode, the maximum line length is 4096 chars (including
- * the line termination char); lines longer than 4096 chars are
- * truncated. After 4095 chars, input data is still processed but
- * not stored. Overflow processing ensures the tty can always
- * receive more input until at least one line can be read.
- *
- * In non-canonical mode, the read buffer will only accept 4095 chars;
- * this provides the necessary space for a newline char if the input
- * mode is switched to canonical.
- *
- * Note it is possible for the read buffer to _contain_ 4096 chars
- * in non-canonical mode: the read buffer could already contain the
- * maximum canon line of 4096 chars when the mode is switched to
- * non-canonical.
- *
- * n_tty_receive_buf()/producer path:
- * claims non-exclusive termios_rwsem
- * publishes commit_head or canon_head
+ * n_tty_receive_buf_common - process input
+ * @tty: device to receive input
+ * @cp: input chars
+ * @fp: flags for each char (if %NULL, all chars are %TTY_NORMAL)
+ * @count: number of input chars in @cp
+ * @flow: enable flow control
+ *
+ * Called by the terminal driver when a block of characters has been received.
+ * This function must be called from soft contexts not from interrupt context.
+ * The driver is responsible for making calls one at a time and in order (or
+ * using flush_to_ldisc()).
+ *
+ * Returns: the # of input chars from @cp which were processed.
+ *
+ * In canonical mode, the maximum line length is 4096 chars (including the line
+ * termination char); lines longer than 4096 chars are truncated. After 4095
+ * chars, input data is still processed but not stored. Overflow processing
+ * ensures the tty can always receive more input until at least one line can be
+ * read.
+ *
+ * In non-canonical mode, the read buffer will only accept 4095 chars; this
+ * provides the necessary space for a newline char if the input mode is
+ * switched to canonical.
+ *
+ * Note it is possible for the read buffer to _contain_ 4096 chars in
+ * non-canonical mode: the read buffer could already contain the maximum canon
+ * line of 4096 chars when the mode is switched to non-canonical.
+ *
+ * Locking: n_tty_receive_buf()/producer path:
+ * claims non-exclusive %termios_rwsem
+ * publishes commit_head or canon_head
*/
static int
n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp,
@@ -1710,19 +1681,17 @@ static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp,
}
/**
- * n_tty_set_termios - termios data changed
- * @tty: terminal
- * @old: previous data
+ * n_tty_set_termios - termios data changed
+ * @tty: terminal
+ * @old: previous data
*
- * Called by the tty layer when the user changes termios flags so
- * that the line discipline can plan ahead. This function cannot sleep
- * and is protected from re-entry by the tty layer. The user is
- * guaranteed that this function will not be re-entered or in progress
- * when the ldisc is closed.
+ * Called by the tty layer when the user changes termios flags so that the line
+ * discipline can plan ahead. This function cannot sleep and is protected from
+ * re-entry by the tty layer. The user is guaranteed that this function will
+ * not be re-entered or in progress when the ldisc is closed.
*
- * Locking: Caller holds tty->termios_rwsem
+ * Locking: Caller holds @tty->termios_rwsem
*/
-
static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
{
struct n_tty_data *ldata = tty->disc_data;
@@ -1808,15 +1777,13 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
}
/**
- * n_tty_close - close the ldisc for this tty
- * @tty: device
+ * n_tty_close - close the ldisc for this tty
+ * @tty: device
*
- * Called from the terminal layer when this line discipline is
- * being shut down, either because of a close or becsuse of a
- * discipline change. The function will not be called while other
- * ldisc methods are in progress.
+ * Called from the terminal layer when this line discipline is being shut down,
+ * either because of a close or becsuse of a discipline change. The function
+ * will not be called while other ldisc methods are in progress.
*/
-
static void n_tty_close(struct tty_struct *tty)
{
struct n_tty_data *ldata = tty->disc_data;
@@ -1831,15 +1798,13 @@ static void n_tty_close(struct tty_struct *tty)
}
/**
- * n_tty_open - open an ldisc
- * @tty: terminal to open
+ * n_tty_open - open an ldisc
+ * @tty: terminal to open
*
- * Called when this line discipline is being attached to the
- * terminal device. Can sleep. Called serialized so that no
- * other events will occur in parallel. No further open will occur
- * until a close.
+ * Called when this line discipline is being attached to the terminal device.
+ * Can sleep. Called serialized so that no other events will occur in parallel.
+ * No further open will occur until a close.
*/
-
static int n_tty_open(struct tty_struct *tty)
{
struct n_tty_data *ldata;
@@ -1874,24 +1839,23 @@ static inline int input_available_p(struct tty_struct *tty, int poll)
}
/**
- * copy_from_read_buf - copy read data directly
- * @tty: terminal device
- * @kbp: data
- * @nr: size of data
- *
- * Helper function to speed up n_tty_read. It is only called when
- * ICANON is off; it copies characters straight from the tty queue.
+ * copy_from_read_buf - copy read data directly
+ * @tty: terminal device
+ * @kbp: data
+ * @nr: size of data
*
- * Called under the ldata->atomic_read_lock sem
+ * Helper function to speed up n_tty_read(). It is only called when %ICANON is
+ * off; it copies characters straight from the tty queue.
*
- * Returns true if it successfully copied data, but there is still
- * more data to be had.
+ * Returns: true if it successfully copied data, but there is still more data
+ * to be had.
*
- * n_tty_read()/consumer path:
- * caller holds non-exclusive termios_rwsem
+ * Locking:
+ * * called under the @ldata->atomic_read_lock sem
+ * * n_tty_read()/consumer path:
+ * caller holds non-exclusive %termios_rwsem;
* read_tail published
*/
-
static bool copy_from_read_buf(struct tty_struct *tty,
unsigned char **kbp,
size_t *nr)
@@ -1926,28 +1890,27 @@ static bool copy_from_read_buf(struct tty_struct *tty,
}
/**
- * canon_copy_from_read_buf - copy read data in canonical mode
- * @tty: terminal device
- * @kbp: data
- * @nr: size of data
- *
- * Helper function for n_tty_read. It is only called when ICANON is on;
- * it copies one line of input up to and including the line-delimiting
- * character into the result buffer.
- *
- * NB: When termios is changed from non-canonical to canonical mode and
- * the read buffer contains data, n_tty_set_termios() simulates an EOF
- * push (as if C-d were input) _without_ the DISABLED_CHAR in the buffer.
- * This causes data already processed as input to be immediately available
- * as input although a newline has not been received.
- *
- * Called under the atomic_read_lock mutex
- *
- * n_tty_read()/consumer path:
- * caller holds non-exclusive termios_rwsem
- * read_tail published
+ * canon_copy_from_read_buf - copy read data in canonical mode
+ * @tty: terminal device
+ * @kbp: data
+ * @nr: size of data
+ *
+ * Helper function for n_tty_read(). It is only called when %ICANON is on; it
+ * copies one line of input up to and including the line-delimiting character
+ * into the result buffer.
+ *
+ * Note: When termios is changed from non-canonical to canonical mode and the
+ * read buffer contains data, n_tty_set_termios() simulates an EOF push (as if
+ * C-d were input) _without_ the %DISABLED_CHAR in the buffer. This causes data
+ * already processed as input to be immediately available as input although a
+ * newline has not been received.
+ *
+ * Locking:
+ * * called under the %atomic_read_lock mutex
+ * * n_tty_read()/consumer path:
+ * caller holds non-exclusive %termios_rwsem;
+ * read_tail published
*/
-
static bool canon_copy_from_read_buf(struct tty_struct *tty,
unsigned char **kbp,
size_t *nr)
@@ -2015,19 +1978,19 @@ static bool canon_copy_from_read_buf(struct tty_struct *tty,
}
/**
- * job_control - check job control
- * @tty: tty
- * @file: file handle
- *
- * Perform job control management checks on this file/tty descriptor
- * and if appropriate send any needed signals and return a negative
- * error code if action should be taken.
- *
- * Locking: redirected write test is safe
- * current->signal->tty check is safe
- * ctrl.lock to safely reference tty->ctrl.pgrp
+ * job_control - check job control
+ * @tty: tty
+ * @file: file handle
+ *
+ * Perform job control management checks on this @file/@tty descriptor and if
+ * appropriate send any needed signals and return a negative error code if
+ * action should be taken.
+ *
+ * Locking:
+ * * redirected write test is safe
+ * * current->signal->tty check is safe
+ * * ctrl.lock to safely reference @tty->ctrl.pgrp
*/
-
static int job_control(struct tty_struct *tty, struct file *file)
{
/* Job control check -- must be done at start and after
@@ -2043,24 +2006,25 @@ static int job_control(struct tty_struct *tty, struct file *file)
/**
- * n_tty_read - read function for tty
- * @tty: tty device
- * @file: file object
- * @buf: userspace buffer pointer
- * @nr: size of I/O
- *
- * Perform reads for the line discipline. We are guaranteed that the
- * line discipline will not be closed under us but we may get multiple
- * parallel readers and must handle this ourselves. We may also get
- * a hangup. Always called in user context, may sleep.
- *
- * This code must be sure never to sleep through a hangup.
- *
- * n_tty_read()/consumer path:
- * claims non-exclusive termios_rwsem
- * publishes read_tail
+ * n_tty_read - read function for tty
+ * @tty: tty device
+ * @file: file object
+ * @kbuf: kernelspace buffer pointer
+ * @nr: size of I/O
+ * @cookie: if non-%NULL, this is a continuation read
+ * @offset: where to continue reading from (unused in n_tty)
+ *
+ * Perform reads for the line discipline. We are guaranteed that the line
+ * discipline will not be closed under us but we may get multiple parallel
+ * readers and must handle this ourselves. We may also get a hangup. Always
+ * called in user context, may sleep.
+ *
+ * This code must be sure never to sleep through a hangup.
+ *
+ * Locking: n_tty_read()/consumer path:
+ * claims non-exclusive termios_rwsem;
+ * publishes read_tail
*/
-
static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
unsigned char *kbuf, size_t nr,
void **cookie, unsigned long offset)
@@ -2232,25 +2196,23 @@ more_to_be_read:
}
/**
- * n_tty_write - write function for tty
- * @tty: tty device
- * @file: file object
- * @buf: userspace buffer pointer
- * @nr: size of I/O
- *
- * Write function of the terminal device. This is serialized with
- * respect to other write callers but not to termios changes, reads
- * and other such events. Since the receive code will echo characters,
- * thus calling driver write methods, the output_lock is used in
- * the output processing functions called here as well as in the
- * echo processing function to protect the column state and space
- * left in the buffer.
- *
- * This code must be sure never to sleep through a hangup.
- *
- * Locking: output_lock to protect column state and space left
- * (note that the process_output*() functions take this
- * lock themselves)
+ * n_tty_write - write function for tty
+ * @tty: tty device
+ * @file: file object
+ * @buf: userspace buffer pointer
+ * @nr: size of I/O
+ *
+ * Write function of the terminal device. This is serialized with respect to
+ * other write callers but not to termios changes, reads and other such events.
+ * Since the receive code will echo characters, thus calling driver write
+ * methods, the %output_lock is used in the output processing functions called
+ * here as well as in the echo processing function to protect the column state
+ * and space left in the buffer.
+ *
+ * This code must be sure never to sleep through a hangup.
+ *
+ * Locking: output_lock to protect column state and space left
+ * (note that the process_output*() functions take this lock themselves)
*/
static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
@@ -2341,19 +2303,19 @@ break_out:
}
/**
- * n_tty_poll - poll method for N_TTY
- * @tty: terminal device
- * @file: file accessing it
- * @wait: poll table
+ * n_tty_poll - poll method for N_TTY
+ * @tty: terminal device
+ * @file: file accessing it
+ * @wait: poll table
+ *
+ * Called when the line discipline is asked to poll() for data or for special
+ * events. This code is not serialized with respect to other events save
+ * open/close.
*
- * Called when the line discipline is asked to poll() for data or
- * for special events. This code is not serialized with respect to
- * other events save open/close.
+ * This code must be sure never to sleep through a hangup.
*
- * This code must be sure never to sleep through a hangup.
- * Called without the kernel lock held - fine
+ * Locking: called without the kernel lock held -- fine.
*/
-
static __poll_t n_tty_poll(struct tty_struct *tty, struct file *file,
poll_table *wait)
{
@@ -2400,8 +2362,8 @@ static unsigned long inq_canon(struct n_tty_data *ldata)
return nr;
}
-static int n_tty_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int n_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
+ unsigned long arg)
{
struct n_tty_data *ldata = tty->disc_data;
int retval;
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 6473361525d1..db784ace25d8 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -241,16 +241,8 @@ static inline int serial8250_in_MCR(struct uart_8250_port *up)
return mctrl;
}
-#if defined(__alpha__) && !defined(CONFIG_PCI)
-/*
- * Digital did something really horribly wrong with the OUT1 and OUT2
- * lines on at least some ALPHA's. The failure mode is that if either
- * is cleared, the machine locks up with endless interrupts.
- */
-#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1)
-#else
-#define ALPHA_KLUDGE_MCR 0
-#endif
+bool alpha_jensen(void);
+void alpha_jensen_set_mctrl(struct uart_port *port, unsigned int mctrl);
#ifdef CONFIG_SERIAL_8250_PNP
int serial8250_pnp_init(void);
diff --git a/drivers/tty/serial/8250/8250_alpha.c b/drivers/tty/serial/8250/8250_alpha.c
new file mode 100644
index 000000000000..58e70328aa4d
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_alpha.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <asm/machvec.h>
+#include "8250.h"
+
+bool alpha_jensen(void)
+{
+ return !strcmp(alpha_mv.vector_name, "Jensen");
+}
+
+void alpha_jensen_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ /*
+ * Digital did something really horribly wrong with the OUT1 and OUT2
+ * lines on Alpha Jensen. The failure mode is that if either is
+ * cleared, the machine locks up with endless interrupts.
+ */
+ mctrl |= TIOCM_OUT1 | TIOCM_OUT2;
+
+ serial8250_do_set_mctrl(port, mctrl);
+}
diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c
index 5163d60756b7..9b878d023dac 100644
--- a/drivers/tty/serial/8250/8250_bcm7271.c
+++ b/drivers/tty/serial/8250/8250_bcm7271.c
@@ -941,7 +941,7 @@ static int brcmuart_probe(struct platform_device *pdev)
struct brcmuart_priv *priv;
struct clk *baud_mux_clk;
struct uart_8250_port up;
- struct resource *irq;
+ int irq;
void __iomem *membase = NULL;
resource_size_t mapbase = 0;
u32 clk_rate = 0;
@@ -952,11 +952,9 @@ static int brcmuart_probe(struct platform_device *pdev)
"uart", "dma_rx", "dma_tx", "dma_intr2", "dma_arb"
};
- irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!irq) {
- dev_err(dev, "missing irq\n");
- return -EINVAL;
- }
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
priv = devm_kzalloc(dev, sizeof(struct brcmuart_priv),
GFP_KERNEL);
if (!priv)
@@ -1044,7 +1042,7 @@ static int brcmuart_probe(struct platform_device *pdev)
up.port.dev = dev;
up.port.mapbase = mapbase;
up.port.membase = membase;
- up.port.irq = irq->start;
+ up.port.irq = irq;
up.port.handle_irq = brcmuart_handle_irq;
up.port.regshift = 2;
up.port.iotype = of_device_is_big_endian(np) ?
@@ -1076,14 +1074,18 @@ static int brcmuart_probe(struct platform_device *pdev)
priv->rx_bufs = dma_alloc_coherent(dev,
priv->rx_size,
&priv->rx_addr, GFP_KERNEL);
- if (!priv->rx_bufs)
+ if (!priv->rx_bufs) {
+ ret = -ENOMEM;
goto err;
+ }
priv->tx_size = UART_XMIT_SIZE;
priv->tx_buf = dma_alloc_coherent(dev,
priv->tx_size,
&priv->tx_addr, GFP_KERNEL);
- if (!priv->tx_buf)
+ if (!priv->tx_buf) {
+ ret = -ENOMEM;
goto err;
+ }
}
ret = serial8250_register_8250_port(&up);
@@ -1097,6 +1099,7 @@ static int brcmuart_probe(struct platform_device *pdev)
if (priv->dma_enabled) {
dma_irq = platform_get_irq_byname(pdev, "dma");
if (dma_irq < 0) {
+ ret = dma_irq;
dev_err(dev, "no IRQ resource info\n");
goto err1;
}
@@ -1116,7 +1119,7 @@ err1:
err:
brcmuart_free_bufs(dev, priv);
brcmuart_arbitration(priv, 0);
- return -ENODEV;
+ return ret;
}
static int brcmuart_remove(struct platform_device *pdev)
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 1ce193daea7f..01d30f6ed8fb 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -509,11 +509,10 @@ static void __init serial8250_isa_init_ports(void)
up->ops = &univ8250_driver_ops;
- /*
- * ALPHA_KLUDGE_MCR needs to be killed.
- */
- up->mcr_mask = ~ALPHA_KLUDGE_MCR;
- up->mcr_force = ALPHA_KLUDGE_MCR;
+ if (IS_ENABLED(CONFIG_ALPHA_JENSEN) ||
+ (IS_ENABLED(CONFIG_ALPHA_GENERIC) && alpha_jensen()))
+ port->set_mctrl = alpha_jensen_set_mctrl;
+
serial8250_set_defaults(up);
}
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 60f8fffdfd77..e8b5469e9dfa 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1278,7 +1278,7 @@ static int pci_quatech_init(struct pci_dev *dev)
outl(inl(base + 0x38) | 0x00002000, base + 0x38);
tmp = inl(base + 0x3c);
outl(tmp | 0x01000000, base + 0x3c);
- outl(tmp &= ~0x01000000, base + 0x3c);
+ outl(tmp & ~0x01000000, base + 0x3c);
}
}
return 0;
@@ -1318,89 +1318,6 @@ static int pci_default_setup(struct serial_private *priv,
return setup_port(priv, port, bar, offset, board->reg_shift);
}
-static void
-pericom_do_set_divisor(struct uart_port *port, unsigned int baud,
- unsigned int quot, unsigned int quot_frac)
-{
- int scr;
- int lcr;
-
- for (scr = 16; scr > 4; scr--) {
- unsigned int maxrate = port->uartclk / scr;
- unsigned int divisor = max(maxrate / baud, 1U);
- int delta = maxrate / divisor - baud;
-
- if (baud > maxrate + baud / 50)
- continue;
-
- if (delta > baud / 50)
- divisor++;
-
- if (divisor > 0xffff)
- continue;
-
- /* Update delta due to possible divisor change */
- delta = maxrate / divisor - baud;
- if (abs(delta) < baud / 50) {
- lcr = serial_port_in(port, UART_LCR);
- serial_port_out(port, UART_LCR, lcr | 0x80);
- serial_port_out(port, UART_DLL, divisor & 0xff);
- serial_port_out(port, UART_DLM, divisor >> 8 & 0xff);
- serial_port_out(port, 2, 16 - scr);
- serial_port_out(port, UART_LCR, lcr);
- return;
- }
- }
-}
-static int pci_pericom_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_8250_port *port, int idx)
-{
- unsigned int bar, offset = board->first_offset, maxnr;
-
- bar = FL_GET_BASE(board->flags);
- if (board->flags & FL_BASE_BARS)
- bar += idx;
- else
- offset += idx * board->uart_offset;
-
-
- maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >>
- (board->reg_shift + 3);
-
- if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
- return 1;
-
- port->port.set_divisor = pericom_do_set_divisor;
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
-
-static int pci_pericom_setup_four_at_eight(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_8250_port *port, int idx)
-{
- unsigned int bar, offset = board->first_offset, maxnr;
-
- bar = FL_GET_BASE(board->flags);
- if (board->flags & FL_BASE_BARS)
- bar += idx;
- else
- offset += idx * board->uart_offset;
-
- if (idx==3)
- offset = 0x38;
-
- maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >>
- (board->reg_shift + 3);
-
- if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
- return 1;
-
- port->port.set_divisor = pericom_do_set_divisor;
-
- return setup_port(priv, port, bar, offset, board->reg_shift);
-}
static int
ce4100_serial_setup(struct serial_private *priv,
@@ -1886,42 +1803,6 @@ pci_moxa_setup(struct serial_private *priv,
#define PCIE_DEVICE_ID_WCH_CH384_8S 0x3853
#define PCIE_DEVICE_ID_WCH_CH382_2S 0x3253
-#define PCI_VENDOR_ID_ACCESIO 0x494f
-#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SDB 0x1051
-#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2S 0x1053
-#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB 0x105C
-#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S 0x105E
-#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_2DB 0x1091
-#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_2 0x1093
-#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB 0x1099
-#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4 0x109B
-#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SMDB 0x10D1
-#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2SM 0x10D3
-#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB 0x10DA
-#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM 0x10DC
-#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_1 0x1108
-#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_2 0x1110
-#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_2 0x1111
-#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4 0x1118
-#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4 0x1119
-#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2S 0x1152
-#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S 0x115A
-#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_2 0x1190
-#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_2 0x1191
-#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4 0x1198
-#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4 0x1199
-#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2SM 0x11D0
-#define PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4 0x105A
-#define PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4 0x105B
-#define PCI_DEVICE_ID_ACCESIO_PCIE_COM422_8 0x106A
-#define PCI_DEVICE_ID_ACCESIO_PCIE_COM485_8 0x106B
-#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4 0x1098
-#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_8 0x10A9
-#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM 0x10D9
-#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_8SM 0x10E9
-#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM 0x11D8
-
-
#define PCI_DEVICE_ID_MOXA_CP102E 0x1024
#define PCI_DEVICE_ID_MOXA_CP102EL 0x1025
#define PCI_DEVICE_ID_MOXA_CP104EL_A 0x1045
@@ -2199,16 +2080,6 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
.exit = pci_plx9050_exit,
},
/*
- * Pericom (Only 7954 - It have a offset jump for port 4)
- */
- {
- .vendor = PCI_VENDOR_ID_PERICOM,
- .device = PCI_DEVICE_ID_PERICOM_PI7C9X7954,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup_four_at_eight,
- },
- /*
* PLX
*/
{
@@ -2238,125 +2109,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
.setup = pci_default_setup,
.exit = pci_plx9050_exit,
},
- {
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup_four_at_eight,
- },
- {
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup_four_at_eight,
- },
- {
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup_four_at_eight,
- },
- {
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup_four_at_eight,
- },
- {
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup_four_at_eight,
- },
- {
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup_four_at_eight,
- },
- {
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup_four_at_eight,
- },
- {
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup_four_at_eight,
- },
- {
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup_four_at_eight,
- },
- {
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup_four_at_eight,
- },
- {
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup_four_at_eight,
- },
- {
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup_four_at_eight,
- },
- {
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup_four_at_eight,
- },
- {
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup_four_at_eight,
- },
- {
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup_four_at_eight,
- },
- {
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup_four_at_eight,
- },
- {
- .vendor = PCI_VENDOR_ID_ACCESIO,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
- }, /*
+ /*
* SBS Technologies, Inc., PMC-OCTALPRO 232
*/
{
@@ -2948,10 +2701,6 @@ enum pci_board_num_t {
pbn_wch382_2,
pbn_wch384_4,
pbn_wch384_8,
- pbn_pericom_PI7C9X7951,
- pbn_pericom_PI7C9X7952,
- pbn_pericom_PI7C9X7954,
- pbn_pericom_PI7C9X7958,
pbn_sunix_pci_1s,
pbn_sunix_pci_2s,
pbn_sunix_pci_4s,
@@ -3696,33 +3445,6 @@ static struct pciserial_board pci_boards[] = {
.uart_offset = 8,
.first_offset = 0x00,
},
- /*
- * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
- */
- [pbn_pericom_PI7C9X7951] = {
- .flags = FL_BASE0,
- .num_ports = 1,
- .base_baud = 921600,
- .uart_offset = 0x8,
- },
- [pbn_pericom_PI7C9X7952] = {
- .flags = FL_BASE0,
- .num_ports = 2,
- .base_baud = 921600,
- .uart_offset = 0x8,
- },
- [pbn_pericom_PI7C9X7954] = {
- .flags = FL_BASE0,
- .num_ports = 4,
- .base_baud = 921600,
- .uart_offset = 0x8,
- },
- [pbn_pericom_PI7C9X7958] = {
- .flags = FL_BASE0,
- .num_ports = 8,
- .base_baud = 921600,
- .uart_offset = 0x8,
- },
[pbn_sunix_pci_1s] = {
.num_ports = 1,
.base_baud = 921600,
@@ -3834,6 +3556,10 @@ static const struct pci_device_id blacklist[] = {
{ PCI_VDEVICE(EXAR, PCI_ANY_ID), },
{ PCI_VDEVICE(COMMTECH, PCI_ANY_ID), },
+ /* Pericom devices */
+ { PCI_VDEVICE(PERICOM, PCI_ANY_ID), },
+ { PCI_VDEVICE(ACCESSIO, PCI_ANY_ID), },
+
/* End of the black list */
{ }
};
@@ -5028,127 +4754,6 @@ static const struct pci_device_id serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b3_8_115200 },
/*
- * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
- */
- { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7951,
- PCI_ANY_ID, PCI_ANY_ID,
- 0,
- 0, pbn_pericom_PI7C9X7951 },
- { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7952,
- PCI_ANY_ID, PCI_ANY_ID,
- 0,
- 0, pbn_pericom_PI7C9X7952 },
- { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7954,
- PCI_ANY_ID, PCI_ANY_ID,
- 0,
- 0, pbn_pericom_PI7C9X7954 },
- { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7958,
- PCI_ANY_ID, PCI_ANY_ID,
- 0,
- 0, pbn_pericom_PI7C9X7958 },
- /*
- * ACCES I/O Products quad
- */
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SDB,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7952 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2S,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7952 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_2DB,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7952 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7952 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SMDB,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7952 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2SM,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7952 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_1,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7951 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7952 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7952 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2S,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7952 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7952 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7952 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2SM,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7952 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM422_8,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7958 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM485_8,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7958 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_8,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7958 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_8SM,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7958 },
- { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- pbn_pericom_PI7C9X7954 },
- /*
* Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
*/
{ PCI_VENDOR_ID_TOPIC, PCI_DEVICE_ID_TOPIC_TP560,
diff --git a/drivers/tty/serial/8250/8250_pericom.c b/drivers/tty/serial/8250/8250_pericom.c
new file mode 100644
index 000000000000..025b055363c3
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_pericom.c
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Driver for Pericom UART */
+
+#include <linux/bits.h>
+#include <linux/module.h>
+#include <linux/overflow.h>
+#include <linux/pci.h>
+
+#include "8250.h"
+
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SDB 0x1051
+#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2S 0x1053
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_4 0x105a
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_4 0x105b
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SDB 0x105c
+#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4S 0x105e
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_8 0x106a
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_8 0x106b
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_2DB 0x1091
+#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_2 0x1093
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4 0x1098
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4DB 0x1099
+#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_4 0x109b
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_8 0x10a9
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SMDB 0x10d1
+#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2SM 0x10d3
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SM 0x10d9
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SMDB 0x10da
+#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4SM 0x10dc
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_8SM 0x10e9
+#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_1 0x1108
+#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_2 0x1110
+#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_2 0x1111
+#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_4 0x1118
+#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_4 0x1119
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2S 0x1152
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4S 0x115a
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_2 0x1190
+#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_2 0x1191
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_4 0x1198
+#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_4 0x1199
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2SM 0x11d0
+#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4SM 0x11d8
+
+struct pericom8250 {
+ void __iomem *virt;
+ unsigned int nr;
+ int line[];
+};
+
+static void pericom_do_set_divisor(struct uart_port *port, unsigned int baud,
+ unsigned int quot, unsigned int quot_frac)
+{
+ int scr;
+
+ for (scr = 16; scr > 4; scr--) {
+ unsigned int maxrate = port->uartclk / scr;
+ unsigned int divisor = max(maxrate / baud, 1U);
+ int delta = maxrate / divisor - baud;
+
+ if (baud > maxrate + baud / 50)
+ continue;
+
+ if (delta > baud / 50)
+ divisor++;
+
+ if (divisor > 0xffff)
+ continue;
+
+ /* Update delta due to possible divisor change */
+ delta = maxrate / divisor - baud;
+ if (abs(delta) < baud / 50) {
+ struct uart_8250_port *up = up_to_u8250p(port);
+ int lcr = serial_port_in(port, UART_LCR);
+
+ serial_port_out(port, UART_LCR, lcr | 0x80);
+ serial_dl_write(up, divisor);
+ serial_port_out(port, 2, 16 - scr);
+ serial_port_out(port, UART_LCR, lcr);
+ return;
+ }
+ }
+}
+
+static int pericom8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ unsigned int nr, i, bar = 0, maxnr;
+ struct pericom8250 *pericom;
+ struct uart_8250_port uart;
+ int ret;
+
+ ret = pcim_enable_device(pdev);
+ if (ret)
+ return ret;
+
+ maxnr = pci_resource_len(pdev, bar) >> 3;
+
+ if (pdev->vendor == PCI_VENDOR_ID_PERICOM)
+ nr = pdev->device & 0x0f;
+ else if (pdev->vendor == PCI_VENDOR_ID_ACCESSIO)
+ nr = BIT(((pdev->device & 0x38) >> 3) - 1);
+ else
+ nr = 1;
+
+ pericom = devm_kzalloc(&pdev->dev, struct_size(pericom, line, nr), GFP_KERNEL);
+ if (!pericom)
+ return -ENOMEM;
+
+ pericom->virt = pcim_iomap(pdev, bar, 0);
+ if (!pericom->virt)
+ return -ENOMEM;
+
+ memset(&uart, 0, sizeof(uart));
+
+ uart.port.dev = &pdev->dev;
+ uart.port.irq = pdev->irq;
+ uart.port.private_data = pericom;
+ uart.port.iotype = UPIO_PORT;
+ uart.port.uartclk = 921600 * 16;
+ uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ | UPF_MAGIC_MULTIPLIER;
+ uart.port.set_divisor = pericom_do_set_divisor;
+ for (i = 0; i < nr && i < maxnr; i++) {
+ unsigned int offset = (i == 3 && nr == 4) ? 0x38 : i * 0x8;
+
+ uart.port.iobase = pci_resource_start(pdev, bar) + offset;
+
+ dev_dbg(&pdev->dev, "Setup PCI port: port %lx, irq %d, type %d\n",
+ uart.port.iobase, uart.port.irq, uart.port.iotype);
+
+ pericom->line[i] = serial8250_register_8250_port(&uart);
+ if (pericom->line[i] < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't register serial port %lx, irq %d, type %d, error %d\n",
+ uart.port.iobase, uart.port.irq,
+ uart.port.iotype, pericom->line[i]);
+ break;
+ }
+ }
+ pericom->nr = i;
+
+ pci_set_drvdata(pdev, pericom);
+ return 0;
+}
+
+static void pericom8250_remove(struct pci_dev *pdev)
+{
+ struct pericom8250 *pericom = pci_get_drvdata(pdev);
+ unsigned int i;
+
+ for (i = 0; i < pericom->nr; i++)
+ serial8250_unregister_port(pericom->line[i]);
+}
+
+static const struct pci_device_id pericom8250_pci_ids[] = {
+ /*
+ * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
+ * (Only 7954 has an offset jump for port 4)
+ */
+ { PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7951) },
+ { PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7952) },
+ { PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7954) },
+ { PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7958) },
+
+ /*
+ * ACCES I/O Products quad
+ * (Only 7954 has an offset jump for port 4)
+ */
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SDB) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2S) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_4) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_4) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SDB) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4S) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_8) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_8) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_2DB) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_2) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4DB) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_4) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_8) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SMDB) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2SM) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SM) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SMDB) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4SM) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_8SM) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_1) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_2) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_2) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_4) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_4) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2S) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4S) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_2) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_2) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_4) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_4) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2SM) },
+ { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4SM) },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, pericom8250_pci_ids);
+
+static struct pci_driver pericom8250_pci_driver = {
+ .name = "8250_pericom",
+ .id_table = pericom8250_pci_ids,
+ .probe = pericom8250_probe,
+ .remove = pericom8250_remove,
+};
+module_pci_driver(pericom8250_pci_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Pericom UART driver");
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 46e2079ad1aa..2abb3de11a48 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -2026,7 +2026,7 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
mcr = serial8250_TIOCM_to_MCR(mctrl);
- mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
+ mcr |= up->mcr;
serial8250_out_MCR(up, mcr);
}
@@ -2056,10 +2056,7 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
serial8250_rpm_put(up);
}
-/*
- * Wait for transmitter & holding register to empty
- */
-static void wait_for_xmitr(struct uart_8250_port *up, int bits)
+static void wait_for_lsr(struct uart_8250_port *up, int bits)
{
unsigned int status, tmout = 10000;
@@ -2076,6 +2073,16 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits)
udelay(1);
touch_nmi_watchdog();
}
+}
+
+/*
+ * Wait for transmitter & holding register to empty
+ */
+static void wait_for_xmitr(struct uart_8250_port *up, int bits)
+{
+ unsigned int tmout;
+
+ wait_for_lsr(up, bits);
/* Wait up to 1s for flow control if necessary */
if (up->port.flags & UPF_CONS_FLOW) {
@@ -3092,7 +3099,7 @@ static ssize_t rx_trig_bytes_show(struct device *dev,
if (rxtrig_bytes < 0)
return rxtrig_bytes;
- return snprintf(buf, PAGE_SIZE, "%d\n", rxtrig_bytes);
+ return sysfs_emit(buf, "%d\n", rxtrig_bytes);
}
static int do_set_rxtrig(struct tty_port *port, unsigned char bytes)
@@ -3326,6 +3333,35 @@ static void serial8250_console_restore(struct uart_8250_port *up)
}
/*
+ * Print a string to the serial port using the device FIFO
+ *
+ * It sends fifosize bytes and then waits for the fifo
+ * to get empty.
+ */
+static void serial8250_console_fifo_write(struct uart_8250_port *up,
+ const char *s, unsigned int count)
+{
+ int i;
+ const char *end = s + count;
+ unsigned int fifosize = up->port.fifosize;
+ bool cr_sent = false;
+
+ while (s != end) {
+ wait_for_lsr(up, UART_LSR_THRE);
+
+ for (i = 0; i < fifosize && s != end; ++i) {
+ if (*s == '\n' && !cr_sent) {
+ serial_out(up, UART_TX, '\r');
+ cr_sent = true;
+ } else {
+ serial_out(up, UART_TX, *s++);
+ cr_sent = false;
+ }
+ }
+ }
+}
+
+/*
* Print a string to the serial port trying not to disturb
* any possible real use of the port...
*
@@ -3340,7 +3376,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
struct uart_8250_em485 *em485 = up->em485;
struct uart_port *port = &up->port;
unsigned long flags;
- unsigned int ier;
+ unsigned int ier, use_fifo;
int locked = 1;
touch_nmi_watchdog();
@@ -3372,7 +3408,20 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
mdelay(port->rs485.delay_rts_before_send);
}
- uart_console_write(port, s, count, serial8250_console_putchar);
+ use_fifo = (up->capabilities & UART_CAP_FIFO) &&
+ port->fifosize > 1 &&
+ (serial_port_in(port, UART_FCR) & UART_FCR_ENABLE_FIFO) &&
+ /*
+ * After we put a data in the fifo, the controller will send
+ * it regardless of the CTS state. Therefore, only use fifo
+ * if we don't use control flow.
+ */
+ !(up->port.flags & UPF_CONS_FLOW);
+
+ if (likely(use_fifo))
+ serial8250_console_fifo_write(up, s, count);
+ else
+ uart_console_write(port, s, count, serial8250_console_putchar);
/*
* Finally, wait for transmitter to become empty
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 8cd11aa63ed5..9d415a38cc71 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -498,6 +498,14 @@ config SERIAL_8250_MID
present on the UART found on Intel Medfield SOC and various other
Intel platforms.
+config SERIAL_8250_PERICOM
+ tristate "Support for Pericom and Acces I/O serial ports"
+ default SERIAL_8250
+ depends on SERIAL_8250 && PCI
+ help
+ Selecting this option will enable handling of the extra features
+ present on the Pericom and Acces I/O UARTs.
+
config SERIAL_8250_PXA
tristate "PXA serial port support"
depends on SERIAL_8250
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index b9bcd73c8997..bee908f99ea0 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -5,6 +5,8 @@
obj-$(CONFIG_SERIAL_8250) += 8250.o 8250_base.o
8250-y := 8250_core.o
+8250-$(CONFIG_ALPHA_GENERIC) += 8250_alpha.o
+8250-$(CONFIG_ALPHA_JENSEN) += 8250_alpha.o
8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
8250_base-y := 8250_port.o
8250_base-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o
@@ -36,6 +38,7 @@ obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o
obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o
obj-$(CONFIG_SERIAL_8250_LPSS) += 8250_lpss.o
obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o
+obj-$(CONFIG_SERIAL_8250_PERICOM) += 8250_pericom.o
obj-$(CONFIG_SERIAL_8250_PXA) += 8250_pxa.o
obj-$(CONFIG_SERIAL_8250_TEGRA) += 8250_tegra.o
obj-$(CONFIG_SERIAL_8250_BCM7271) += 8250_bcm7271.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index fc543ac97c13..0e5ccb25bdb1 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -263,7 +263,7 @@ config SERIAL_SAMSUNG_UARTS
config SERIAL_SAMSUNG_CONSOLE
bool "Support for console on Samsung SoC serial port"
- depends on SERIAL_SAMSUNG=y
+ depends on SERIAL_SAMSUNG
select SERIAL_CORE_CONSOLE
select SERIAL_EARLYCON
help
diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c
index 23c4e0e79694..37bffe406b18 100644
--- a/drivers/tty/serial/altera_jtaguart.c
+++ b/drivers/tty/serial/altera_jtaguart.c
@@ -418,8 +418,9 @@ static int altera_jtaguart_probe(struct platform_device *pdev)
struct altera_jtaguart_platform_uart *platp =
dev_get_platdata(&pdev->dev);
struct uart_port *port;
- struct resource *res_irq, *res_mem;
+ struct resource *res_mem;
int i = pdev->id;
+ int irq;
/* -1 emphasizes that the platform must have one port, no .N suffix */
if (i == -1)
@@ -438,9 +439,11 @@ static int altera_jtaguart_probe(struct platform_device *pdev)
else
return -ENODEV;
- res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (res_irq)
- port->irq = res_irq->start;
+ irq = platform_get_irq_optional(pdev, 0);
+ if (irq < 0 && irq != -ENXIO)
+ return irq;
+ if (irq > 0)
+ port->irq = irq;
else if (platp)
port->irq = platp->irq;
else
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index 7c5f4e966b59..64a352b40197 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -553,7 +553,6 @@ static int altera_uart_probe(struct platform_device *pdev)
struct altera_uart_platform_uart *platp = dev_get_platdata(&pdev->dev);
struct uart_port *port;
struct resource *res_mem;
- struct resource *res_irq;
int i = pdev->id;
int ret;
@@ -577,9 +576,11 @@ static int altera_uart_probe(struct platform_device *pdev)
else
return -EINVAL;
- res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (res_irq)
- port->irq = res_irq->start;
+ ret = platform_get_irq_optional(pdev, 0);
+ if (ret < 0 && ret != -ENXIO)
+ return ret;
+ if (ret > 0)
+ port->irq = ret;
else if (platp)
port->irq = platp->irq;
diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c
index e744b953ca34..47654073123d 100644
--- a/drivers/tty/serial/amba-pl010.c
+++ b/drivers/tty/serial/amba-pl010.c
@@ -446,14 +446,11 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios,
if ((termios->c_cflag & CREAD) == 0)
uap->port.ignore_status_mask |= UART_DUMMY_RSR_RX;
- /* first, disable everything */
old_cr = readb(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE;
if (UART_ENABLE_MS(port, termios->c_cflag))
old_cr |= UART010_CR_MSIE;
- writel(0, uap->port.membase + UART010_CR);
-
/* Set baud rate */
quot -= 1;
writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM);
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 52518a606c06..1f1df46242f9 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -188,38 +188,6 @@ static struct vendor_data vendor_st = {
.get_fifosize = get_fifosize_st,
};
-static const u16 pl011_zte_offsets[REG_ARRAY_SIZE] = {
- [REG_DR] = ZX_UART011_DR,
- [REG_FR] = ZX_UART011_FR,
- [REG_LCRH_RX] = ZX_UART011_LCRH,
- [REG_LCRH_TX] = ZX_UART011_LCRH,
- [REG_IBRD] = ZX_UART011_IBRD,
- [REG_FBRD] = ZX_UART011_FBRD,
- [REG_CR] = ZX_UART011_CR,
- [REG_IFLS] = ZX_UART011_IFLS,
- [REG_IMSC] = ZX_UART011_IMSC,
- [REG_RIS] = ZX_UART011_RIS,
- [REG_MIS] = ZX_UART011_MIS,
- [REG_ICR] = ZX_UART011_ICR,
- [REG_DMACR] = ZX_UART011_DMACR,
-};
-
-static unsigned int get_fifosize_zte(struct amba_device *dev)
-{
- return 16;
-}
-
-static struct vendor_data vendor_zte = {
- .reg_offset = pl011_zte_offsets,
- .access_32b = true,
- .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
- .fr_busy = ZX_UART01x_FR_BUSY,
- .fr_dsr = ZX_UART01x_FR_DSR,
- .fr_cts = ZX_UART01x_FR_CTS,
- .fr_ri = ZX_UART011_FR_RI,
- .get_fifosize = get_fifosize_zte,
-};
-
/* Deals with DMA transactions */
struct pl011_sgbuf {
@@ -262,7 +230,6 @@ struct uart_amba_port {
unsigned int im; /* interrupt mask */
unsigned int old_status;
unsigned int fifosize; /* vendor-specific */
- unsigned int old_cr; /* state during shutdown */
unsigned int fixed_baud; /* vendor-set fixed baud rate */
char type[12];
bool rs485_tx_started;
@@ -1837,8 +1804,8 @@ static int pl011_startup(struct uart_port *port)
spin_lock_irq(&uap->port.lock);
- /* restore RTS and DTR */
- cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
+ cr = pl011_read(uap, REG_CR);
+ cr &= UART011_CR_RTS | UART011_CR_DTR;
cr |= UART01x_CR_UARTEN | UART011_CR_RXE;
if (port->rs485.flags & SER_RS485_ENABLED) {
@@ -1915,7 +1882,6 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
uap->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS);
spin_lock_irq(&uap->port.lock);
cr = pl011_read(uap, REG_CR);
- uap->old_cr = cr;
cr &= UART011_CR_RTS | UART011_CR_DTR;
cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
pl011_write(cr, uap, REG_CR);
@@ -2105,9 +2071,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
if (port->rs485.flags & SER_RS485_ENABLED)
termios->c_cflag &= ~CRTSCTS;
- /* first, disable everything */
old_cr = pl011_read(uap, REG_CR);
- pl011_write(0, uap, REG_CR);
if (termios->c_cflag & CRTSCTS) {
if (old_cr & UART011_CR_RTS)
@@ -2184,31 +2148,12 @@ static const char *pl011_type(struct uart_port *port)
}
/*
- * Release the memory region(s) being used by 'port'
- */
-static void pl011_release_port(struct uart_port *port)
-{
- release_mem_region(port->mapbase, SZ_4K);
-}
-
-/*
- * Request the memory region(s) being used by 'port'
- */
-static int pl011_request_port(struct uart_port *port)
-{
- return request_mem_region(port->mapbase, SZ_4K, "uart-pl011")
- != NULL ? 0 : -EBUSY;
-}
-
-/*
* Configure/autoconfigure the port.
*/
static void pl011_config_port(struct uart_port *port, int flags)
{
- if (flags & UART_CONFIG_TYPE) {
+ if (flags & UART_CONFIG_TYPE)
port->type = PORT_AMBA;
- pl011_request_port(port);
- }
}
/*
@@ -2223,6 +2168,8 @@ static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser)
ret = -EINVAL;
if (ser->baud_base < 9600)
ret = -EINVAL;
+ if (port->mapbase != (unsigned long) ser->iomem_base)
+ ret = -EINVAL;
return ret;
}
@@ -2275,8 +2222,6 @@ static const struct uart_ops amba_pl011_pops = {
.flush_buffer = pl011_dma_flush_buffer,
.set_termios = pl011_set_termios,
.type = pl011_type,
- .release_port = pl011_release_port,
- .request_port = pl011_request_port,
.config_port = pl011_config_port,
.verify_port = pl011_verify_port,
#ifdef CONFIG_CONSOLE_POLL
@@ -2306,8 +2251,6 @@ static const struct uart_ops sbsa_uart_pops = {
.shutdown = sbsa_uart_shutdown,
.set_termios = sbsa_uart_set_termios,
.type = pl011_type,
- .release_port = pl011_release_port,
- .request_port = pl011_request_port,
.config_port = pl011_config_port,
.verify_port = pl011_verify_port,
#ifdef CONFIG_CONSOLE_POLL
@@ -2754,7 +2697,6 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap,
index = pl011_probe_dt_alias(index, dev);
- uap->old_cr = 0;
uap->port.dev = dev;
uap->port.mapbase = mmiobase->start;
uap->port.membase = base;
@@ -2975,11 +2917,6 @@ static const struct amba_id pl011_ids[] = {
.mask = 0x00ffffff,
.data = &vendor_st,
},
- {
- .id = AMBA_LINUX_ID(0x00, 0x1, 0xffe),
- .mask = 0x00ffffff,
- .data = &vendor_zte,
- },
{ 0, 0 },
};
diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c
index 4379ca4842ae..8cabe50c4a33 100644
--- a/drivers/tty/serial/ar933x_uart.c
+++ b/drivers/tty/serial/ar933x_uart.c
@@ -707,11 +707,11 @@ static int ar933x_uart_probe(struct platform_device *pdev)
struct ar933x_uart_port *up;
struct uart_port *port;
struct resource *mem_res;
- struct resource *irq_res;
struct device_node *np;
unsigned int baud;
int id;
int ret;
+ int irq;
np = pdev->dev.of_node;
if (IS_ENABLED(CONFIG_OF) && np) {
@@ -730,11 +730,9 @@ static int ar933x_uart_probe(struct platform_device *pdev)
if (id >= CONFIG_SERIAL_AR933X_NR_UARTS)
return -EINVAL;
- irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!irq_res) {
- dev_err(&pdev->dev, "no IRQ resource\n");
- return -EINVAL;
- }
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
up = devm_kzalloc(&pdev->dev, sizeof(struct ar933x_uart_port),
GFP_KERNEL);
@@ -766,7 +764,7 @@ static int ar933x_uart_probe(struct platform_device *pdev)
port->mapbase = mem_res->start;
port->line = id;
- port->irq = irq_res->start;
+ port->irq = irq;
port->dev = &pdev->dev;
port->type = PORT_AR933X;
port->iotype = UPIO_MEM32;
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 2c99a47a2535..c370eddc651b 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -1004,6 +1004,13 @@ static void atmel_tx_dma(struct uart_port *port)
desc->callback = atmel_complete_tx_dma;
desc->callback_param = atmel_port;
atmel_port->cookie_tx = dmaengine_submit(desc);
+ if (dma_submit_error(atmel_port->cookie_tx)) {
+ dev_err(port->dev, "dma_submit_error %d\n",
+ atmel_port->cookie_tx);
+ return;
+ }
+
+ dma_async_issue_pending(chan);
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
@@ -1258,6 +1265,13 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
desc->callback_param = port;
atmel_port->desc_rx = desc;
atmel_port->cookie_rx = dmaengine_submit(desc);
+ if (dma_submit_error(atmel_port->cookie_rx)) {
+ dev_err(port->dev, "dma_submit_error %d\n",
+ atmel_port->cookie_rx);
+ goto chan_err;
+ }
+
+ dma_async_issue_pending(atmel_port->chan_rx);
return 0;
@@ -2479,7 +2493,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
port->fifosize = 1;
port->dev = &pdev->dev;
port->mapbase = mpdev->resource[0].start;
- port->irq = mpdev->resource[1].start;
+ port->irq = platform_get_irq(mpdev, 0);
port->rs485_config = atmel_config_rs485;
port->iso7816_config = atmel_config_iso7816;
port->membase = NULL;
diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c
index 5fb0e84f7fd1..6471a54b616b 100644
--- a/drivers/tty/serial/bcm63xx_uart.c
+++ b/drivers/tty/serial/bcm63xx_uart.c
@@ -804,7 +804,7 @@ static struct uart_driver bcm_uart_driver = {
*/
static int bcm_uart_probe(struct platform_device *pdev)
{
- struct resource *res_mem, *res_irq;
+ struct resource *res_mem;
struct uart_port *port;
struct clk *clk;
int ret;
@@ -833,9 +833,10 @@ static int bcm_uart_probe(struct platform_device *pdev)
if (IS_ERR(port->membase))
return PTR_ERR(port->membase);
- res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res_irq)
- return -ENODEV;
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0)
+ return ret;
+ port->irq = ret;
clk = clk_get(&pdev->dev, "refclk");
if (IS_ERR(clk) && pdev->dev.of_node)
@@ -845,7 +846,6 @@ static int bcm_uart_probe(struct platform_device *pdev)
return -ENODEV;
port->iotype = UPIO_MEM;
- port->irq = res_irq->start;
port->ops = &bcm_uart_ops;
port->flags = UPF_BOOT_AUTOCONF;
port->dev = &pdev->dev;
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index ac5112def40d..ce3e26144689 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -247,6 +247,7 @@ enum lpuart_type {
LS1028A_LPUART,
IMX7ULP_LPUART,
IMX8QXP_LPUART,
+ IMXRT1050_LPUART,
};
struct lpuart_port {
@@ -310,6 +311,11 @@ static struct lpuart_soc_data imx8qxp_data = {
.iotype = UPIO_MEM32,
.reg_off = IMX_REG_OFF,
};
+static struct lpuart_soc_data imxrt1050_data = {
+ .devtype = IMXRT1050_LPUART,
+ .iotype = UPIO_MEM32,
+ .reg_off = IMX_REG_OFF,
+};
static const struct of_device_id lpuart_dt_ids[] = {
{ .compatible = "fsl,vf610-lpuart", .data = &vf_data, },
@@ -317,6 +323,7 @@ static const struct of_device_id lpuart_dt_ids[] = {
{ .compatible = "fsl,ls1028a-lpuart", .data = &ls1028a_data, },
{ .compatible = "fsl,imx7ulp-lpuart", .data = &imx7ulp_data, },
{ .compatible = "fsl,imx8qxp-lpuart", .data = &imx8qxp_data, },
+ { .compatible = "fsl,imxrt1050-lpuart", .data = &imxrt1050_data},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
@@ -1793,8 +1800,8 @@ static void lpuart_dma_shutdown(struct lpuart_port *sport)
}
if (sport->lpuart_dma_tx_use) {
- if (wait_event_interruptible(sport->dma_wait,
- !sport->dma_tx_in_progress) != false) {
+ if (wait_event_interruptible_timeout(sport->dma_wait,
+ !sport->dma_tx_in_progress, msecs_to_jiffies(300)) <= 0) {
sport->dma_tx_in_progress = false;
dmaengine_terminate_all(sport->dma_tx_chan);
}
@@ -2626,6 +2633,7 @@ OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup
OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1028a-lpuart", ls1028a_early_console_setup);
OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup);
OF_EARLYCON_DECLARE(lpuart32, "fsl,imx8qxp-lpuart", lpuart32_imx_early_console_setup);
+OF_EARLYCON_DECLARE(lpuart32, "fsl,imxrt1050-lpuart", lpuart32_imx_early_console_setup);
EARLYCON_DECLARE(lpuart, lpuart_early_console_setup);
EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup);
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 90f82e6c54e4..df8a0c8b8b29 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -486,18 +486,21 @@ static void imx_uart_stop_tx(struct uart_port *port)
static void imx_uart_stop_rx(struct uart_port *port)
{
struct imx_port *sport = (struct imx_port *)port;
- u32 ucr1, ucr2;
+ u32 ucr1, ucr2, ucr4;
ucr1 = imx_uart_readl(sport, UCR1);
ucr2 = imx_uart_readl(sport, UCR2);
+ ucr4 = imx_uart_readl(sport, UCR4);
if (sport->dma_is_enabled) {
ucr1 &= ~(UCR1_RXDMAEN | UCR1_ATDMAEN);
} else {
ucr1 &= ~UCR1_RRDYEN;
ucr2 &= ~UCR2_ATEN;
+ ucr4 &= ~UCR4_OREN;
}
imx_uart_writel(sport, ucr1, UCR1);
+ imx_uart_writel(sport, ucr4, UCR4);
ucr2 &= ~UCR2_RXEN;
imx_uart_writel(sport, ucr2, UCR2);
@@ -1544,7 +1547,7 @@ static void imx_uart_shutdown(struct uart_port *port)
imx_uart_writel(sport, ucr1, UCR1);
ucr4 = imx_uart_readl(sport, UCR4);
- ucr4 &= ~(UCR4_OREN | UCR4_TCEN);
+ ucr4 &= ~UCR4_TCEN;
imx_uart_writel(sport, ucr4, UCR4);
spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -2482,10 +2485,12 @@ static void imx_uart_enable_wakeup(struct imx_port *sport, bool on)
if (sport->have_rtscts) {
u32 ucr1 = imx_uart_readl(sport, UCR1);
- if (on)
+ if (on) {
+ imx_uart_writel(sport, USR1_RTSD, USR1);
ucr1 |= UCR1_RTSDEN;
- else
+ } else {
ucr1 &= ~UCR1_RTSDEN;
+ }
imx_uart_writel(sport, ucr1, UCR1);
}
}
diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
index 497b334bc845..3e324d3f0a6d 100644
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -16,8 +16,6 @@
#include <linux/ioport.h>
#include <linux/lantiq.h>
#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
@@ -728,19 +726,23 @@ static struct uart_driver lqasc_reg = {
static int fetch_irq_lantiq(struct device *dev, struct ltq_uart_port *ltq_port)
{
struct uart_port *port = &ltq_port->port;
- struct resource irqres[3];
- int ret;
-
- ret = of_irq_to_resource_table(dev->of_node, irqres, 3);
- if (ret != 3) {
- dev_err(dev,
- "failed to get IRQs for serial port\n");
- return -ENODEV;
- }
- ltq_port->tx_irq = irqres[0].start;
- ltq_port->rx_irq = irqres[1].start;
- ltq_port->err_irq = irqres[2].start;
- port->irq = irqres[0].start;
+ struct platform_device *pdev = to_platform_device(dev);
+ int irq;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+ ltq_port->tx_irq = irq;
+ irq = platform_get_irq(pdev, 1);
+ if (irq < 0)
+ return irq;
+ ltq_port->rx_irq = irq;
+ irq = platform_get_irq(pdev, 2);
+ if (irq < 0)
+ return irq;
+ ltq_port->err_irq = irq;
+
+ port->irq = ltq_port->tx_irq;
return 0;
}
@@ -793,7 +795,7 @@ static int fetch_irq_intel(struct device *dev, struct ltq_uart_port *ltq_port)
struct uart_port *port = &ltq_port->port;
int ret;
- ret = of_irq_get(dev->of_node, 0);
+ ret = platform_get_irq(to_platform_device(dev), 0);
if (ret < 0) {
dev_err(dev, "failed to fetch IRQ for serial port\n");
return ret;
diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c
index 2941659e5274..7f74bf7bdcff 100644
--- a/drivers/tty/serial/liteuart.c
+++ b/drivers/tty/serial/liteuart.c
@@ -436,4 +436,4 @@ module_exit(liteuart_exit);
MODULE_AUTHOR("Antmicro <www.antmicro.com>");
MODULE_DESCRIPTION("LiteUART serial driver");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform: liteuart");
+MODULE_ALIAS("platform:liteuart");
diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
index b199d7859961..07c4161eb4cc 100644
--- a/drivers/tty/serial/lpc32xx_hs.c
+++ b/drivers/tty/serial/lpc32xx_hs.c
@@ -341,7 +341,7 @@ static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id)
LPC32XX_HSUART_IIR(port->membase));
port->icount.overrun++;
tty_insert_flip_char(tport, 0, TTY_OVERRUN);
- tty_schedule_flip(tport);
+ tty_flip_buffer_push(tport);
}
/* Data received? */
diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c
index efee3935917f..45e00d928253 100644
--- a/drivers/tty/serial/meson_uart.c
+++ b/drivers/tty/serial/meson_uart.c
@@ -622,10 +622,7 @@ meson_serial_early_console_setup(struct earlycon_device *device, const char *opt
device->con->write = meson_serial_early_console_write;
return 0;
}
-/* Legacy bindings, should be removed when no more used */
-OF_EARLYCON_DECLARE(meson, "amlogic,meson-uart",
- meson_serial_early_console_setup);
-/* Stable bindings */
+
OF_EARLYCON_DECLARE(meson, "amlogic,meson-ao-uart",
meson_serial_early_console_setup);
@@ -668,25 +665,6 @@ static inline struct clk *meson_uart_probe_clock(struct device *dev,
return clk;
}
-/*
- * This function gets clocks in the legacy non-stable DT bindings.
- * This code will be remove once all the platforms switch to the
- * new DT bindings.
- */
-static int meson_uart_probe_clocks_legacy(struct platform_device *pdev,
- struct uart_port *port)
-{
- struct clk *clk = NULL;
-
- clk = meson_uart_probe_clock(&pdev->dev, NULL);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
-
- port->uartclk = clk_get_rate(clk);
-
- return 0;
-}
-
static int meson_uart_probe_clocks(struct platform_device *pdev,
struct uart_port *port)
{
@@ -713,10 +691,11 @@ static int meson_uart_probe_clocks(struct platform_device *pdev,
static int meson_uart_probe(struct platform_device *pdev)
{
- struct resource *res_mem, *res_irq;
+ struct resource *res_mem;
struct uart_port *port;
u32 fifosize = 64; /* Default is 64, 128 for EE UART_0 */
int ret = 0;
+ int irq;
if (pdev->dev.of_node)
pdev->id = of_alias_get_id(pdev->dev.of_node, "serial");
@@ -739,9 +718,9 @@ static int meson_uart_probe(struct platform_device *pdev)
if (!res_mem)
return -ENODEV;
- res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res_irq)
- return -ENODEV;
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
of_property_read_u32(pdev->dev.of_node, "fifo-size", &fifosize);
@@ -754,19 +733,14 @@ static int meson_uart_probe(struct platform_device *pdev)
if (!port)
return -ENOMEM;
- /* Use legacy way until all platforms switch to new bindings */
- if (of_device_is_compatible(pdev->dev.of_node, "amlogic,meson-uart"))
- ret = meson_uart_probe_clocks_legacy(pdev, port);
- else
- ret = meson_uart_probe_clocks(pdev, port);
-
+ ret = meson_uart_probe_clocks(pdev, port);
if (ret)
return ret;
port->iotype = UPIO_MEM;
port->mapbase = res_mem->start;
port->mapsize = resource_size(res_mem);
- port->irq = res_irq->start;
+ port->irq = irq;
port->flags = UPF_BOOT_AUTOCONF | UPF_LOW_LATENCY;
port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MESON_CONSOLE);
port->dev = &pdev->dev;
@@ -804,9 +778,6 @@ static int meson_uart_remove(struct platform_device *pdev)
}
static const struct of_device_id meson_uart_dt_match[] = {
- /* Legacy bindings, should be removed when no more used */
- { .compatible = "amlogic,meson-uart" },
- /* Stable bindings */
{ .compatible = "amlogic,meson6-uart" },
{ .compatible = "amlogic,meson8-uart" },
{ .compatible = "amlogic,meson8b-uart" },
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c
index 12ce150b0ad4..5359236b32d6 100644
--- a/drivers/tty/serial/pmac_zilog.c
+++ b/drivers/tty/serial/pmac_zilog.c
@@ -1702,17 +1702,21 @@ extern struct platform_device scc_a_pdev, scc_b_pdev;
static int __init pmz_init_port(struct uart_pmac_port *uap)
{
- struct resource *r_ports, *r_irq;
+ struct resource *r_ports;
+ int irq;
r_ports = platform_get_resource(uap->pdev, IORESOURCE_MEM, 0);
- r_irq = platform_get_resource(uap->pdev, IORESOURCE_IRQ, 0);
- if (!r_ports || !r_irq)
+ if (!r_ports)
return -ENODEV;
+ irq = platform_get_irq(uap->pdev, 0);
+ if (irq < 0)
+ return irq;
+
uap->port.mapbase = r_ports->start;
uap->port.membase = (unsigned char __iomem *) r_ports->start;
uap->port.iotype = UPIO_MEM;
- uap->port.irq = r_irq->start;
+ uap->port.irq = irq;
uap->port.uartclk = ZS_CLOCK;
uap->port.fifosize = 1;
uap->port.ops = &pmz_pops;
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 41319ef96fa6..30b099746a75 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -842,14 +842,18 @@ static int serial_pxa_probe_dt(struct platform_device *pdev,
static int serial_pxa_probe(struct platform_device *dev)
{
struct uart_pxa_port *sport;
- struct resource *mmres, *irqres;
+ struct resource *mmres;
int ret;
+ int irq;
mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
- irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
- if (!mmres || !irqres)
+ if (!mmres)
return -ENODEV;
+ irq = platform_get_irq(dev, 0);
+ if (irq < 0)
+ return irq;
+
sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
if (!sport)
return -ENOMEM;
@@ -869,7 +873,7 @@ static int serial_pxa_probe(struct platform_device *dev)
sport->port.type = PORT_PXA;
sport->port.iotype = UPIO_MEM;
sport->port.mapbase = mmres->start;
- sport->port.irq = irqres->start;
+ sport->port.irq = irq;
sport->port.fifosize = 64;
sport->port.ops = &serial_pxa_pops;
sport->port.dev = &dev->dev;
diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c
index ca084c10d0bb..d002a4e48ed9 100644
--- a/drivers/tty/serial/samsung_tty.c
+++ b/drivers/tty/serial/samsung_tty.c
@@ -65,7 +65,6 @@ enum s3c24xx_port_type {
struct s3c24xx_uart_info {
char *name;
enum s3c24xx_port_type type;
- bool has_usi;
unsigned int port_type;
unsigned int fifosize;
unsigned long rx_fifomask;
@@ -1357,28 +1356,6 @@ static int apple_s5l_serial_startup(struct uart_port *port)
return ret;
}
-static void exynos_usi_init(struct uart_port *port)
-{
- struct s3c24xx_uart_port *ourport = to_ourport(port);
- struct s3c24xx_uart_info *info = ourport->info;
- unsigned int val;
-
- if (!info->has_usi)
- return;
-
- /* Clear the software reset of USI block (it's set at startup) */
- val = rd_regl(port, USI_CON);
- val &= ~USI_CON_RESET_MASK;
- wr_regl(port, USI_CON, val);
- udelay(1);
-
- /* Continuously provide the clock to USI IP w/o gating (for Rx mode) */
- val = rd_regl(port, USI_OPTION);
- val &= ~USI_OPTION_HWACG_MASK;
- val |= USI_OPTION_HWACG_CLKREQ_ON;
- wr_regl(port, USI_OPTION, val);
-}
-
/* power power management control */
static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
@@ -1405,8 +1382,6 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
if (!IS_ERR(ourport->baudclk))
clk_prepare_enable(ourport->baudclk);
-
- exynos_usi_init(port);
break;
default:
dev_err(port->dev, "s3c24xx_serial: unknown pm %d\n", level);
@@ -1740,15 +1715,21 @@ s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
static struct console s3c24xx_serial_console;
-static int __init s3c24xx_serial_console_init(void)
+static void __init s3c24xx_serial_register_console(void)
{
register_console(&s3c24xx_serial_console);
- return 0;
}
-console_initcall(s3c24xx_serial_console_init);
+
+static void s3c24xx_serial_unregister_console(void)
+{
+ if (s3c24xx_serial_console.flags & CON_ENABLED)
+ unregister_console(&s3c24xx_serial_console);
+}
#define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console
#else
+static inline void s3c24xx_serial_register_console(void) { }
+static inline void s3c24xx_serial_unregister_console(void) { }
#define S3C24XX_SERIAL_CONSOLE NULL
#endif
@@ -2130,8 +2111,6 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
if (ret)
pr_warn("uart: failed to enable baudclk\n");
- exynos_usi_init(port);
-
/* Keep all interrupts masked and cleared */
switch (ourport->info->type) {
case TYPE_S3C6400:
@@ -2521,7 +2500,8 @@ s3c24xx_serial_console_write(struct console *co, const char *s,
uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);
}
-static void __init
+/* Shouldn't be __init, as it can be instantiated from other module */
+static void
s3c24xx_serial_get_options(struct uart_port *port, int *baud,
int *parity, int *bits)
{
@@ -2584,7 +2564,8 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
}
}
-static int __init
+/* Shouldn't be __init, as it can be instantiated from other module */
+static int
s3c24xx_serial_console_setup(struct console *co, char *options)
{
struct uart_port *port;
@@ -2780,11 +2761,10 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
#endif
#if defined(CONFIG_ARCH_EXYNOS)
-#define EXYNOS_COMMON_SERIAL_DRV_DATA(_has_usi) \
+#define EXYNOS_COMMON_SERIAL_DRV_DATA() \
.info = &(struct s3c24xx_uart_info) { \
.name = "Samsung Exynos UART", \
.type = TYPE_S3C6400, \
- .has_usi = _has_usi, \
.port_type = PORT_S3C6400, \
.has_divslot = 1, \
.rx_fifomask = S5PV210_UFSTAT_RXMASK, \
@@ -2805,17 +2785,17 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
} \
static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
- EXYNOS_COMMON_SERIAL_DRV_DATA(false),
+ EXYNOS_COMMON_SERIAL_DRV_DATA(),
.fifosize = { 256, 64, 16, 16 },
};
static struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = {
- EXYNOS_COMMON_SERIAL_DRV_DATA(false),
+ EXYNOS_COMMON_SERIAL_DRV_DATA(),
.fifosize = { 64, 256, 16, 256 },
};
static struct s3c24xx_serial_drv_data exynos850_serial_drv_data = {
- EXYNOS_COMMON_SERIAL_DRV_DATA(true),
+ EXYNOS_COMMON_SERIAL_DRV_DATA(),
.fifosize = { 256, 64, 64, 64 },
};
@@ -2926,7 +2906,29 @@ static struct platform_driver samsung_serial_driver = {
},
};
-module_platform_driver(samsung_serial_driver);
+static int __init samsung_serial_init(void)
+{
+ int ret;
+
+ s3c24xx_serial_register_console();
+
+ ret = platform_driver_register(&samsung_serial_driver);
+ if (ret) {
+ s3c24xx_serial_unregister_console();
+ return ret;
+ }
+
+ return 0;
+}
+
+static void __exit samsung_serial_exit(void)
+{
+ platform_driver_unregister(&samsung_serial_driver);
+ s3c24xx_serial_unregister_console();
+}
+
+module_init(samsung_serial_init);
+module_exit(samsung_serial_exit);
#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
/*
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 61e3dd0222af..dc40c4155356 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -162,7 +162,7 @@ static void uart_port_dtr_rts(struct uart_port *uport, int raise)
int RTS_after_send = !!(uport->rs485.flags & SER_RS485_RTS_AFTER_SEND);
if (raise) {
- if (rs485_on && !RTS_after_send) {
+ if (rs485_on && RTS_after_send) {
uart_set_mctrl(uport, TIOCM_DTR);
uart_clear_mctrl(uport, TIOCM_RTS);
} else {
@@ -171,7 +171,7 @@ static void uart_port_dtr_rts(struct uart_port *uport, int raise)
} else {
unsigned int clear = TIOCM_DTR;
- clear |= (!rs485_on || !RTS_after_send) ? TIOCM_RTS : 0;
+ clear |= (!rs485_on || RTS_after_send) ? TIOCM_RTS : 0;
uart_clear_mctrl(uport, clear);
}
}
@@ -1701,17 +1701,13 @@ static void uart_port_shutdown(struct tty_port *port)
*/
wake_up_interruptible(&port->delta_msr_wait);
- /*
- * Free the IRQ and disable the port.
- */
- if (uport)
+ if (uport) {
+ /* Free the IRQ and disable the port. */
uport->ops->shutdown(uport);
- /*
- * Ensure that the IRQ handler isn't running on another CPU.
- */
- if (uport)
+ /* Ensure that the IRQ handler isn't running on another CPU. */
synchronize_irq(uport->irq);
+ }
}
static int uart_carrier_raised(struct tty_port *port)
@@ -2393,7 +2389,8 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
* We probably don't need a spinlock around this, but
*/
spin_lock_irqsave(&port->lock, flags);
- port->ops->set_mctrl(port, port->mctrl & TIOCM_DTR);
+ port->mctrl &= TIOCM_DTR;
+ port->ops->set_mctrl(port, port->mctrl);
spin_unlock_irqrestore(&port->lock, flags);
/*
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 89ee43061d3a..968967d722d4 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -37,6 +37,7 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/reset.h>
#include <linux/scatterlist.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
@@ -895,11 +896,9 @@ static void sci_receive_chars(struct uart_port *port)
if (status & SCxSR_FER(port)) {
flag = TTY_FRAME;
port->icount.frame++;
- dev_notice(port->dev, "frame error\n");
} else if (status & SCxSR_PER(port)) {
flag = TTY_PARITY;
port->icount.parity++;
- dev_notice(port->dev, "parity error\n");
} else
flag = TTY_NORMAL;
@@ -939,8 +938,6 @@ static int sci_handle_errors(struct uart_port *port)
/* overrun error */
if (tty_insert_flip_char(tport, 0, TTY_OVERRUN))
copied++;
-
- dev_notice(port->dev, "overrun error\n");
}
if (status & SCxSR_FER(port)) {
@@ -949,8 +946,6 @@ static int sci_handle_errors(struct uart_port *port)
if (tty_insert_flip_char(tport, 0, TTY_FRAME))
copied++;
-
- dev_notice(port->dev, "frame error\n");
}
if (status & SCxSR_PER(port)) {
@@ -959,8 +954,6 @@ static int sci_handle_errors(struct uart_port *port)
if (tty_insert_flip_char(tport, 0, TTY_PARITY))
copied++;
-
- dev_notice(port->dev, "parity error\n");
}
if (copied)
@@ -990,8 +983,6 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
tty_insert_flip_char(tport, 0, TTY_OVERRUN);
tty_flip_buffer_push(tport);
-
- dev_dbg(port->dev, "overrun error\n");
copied++;
}
@@ -1013,8 +1004,6 @@ static int sci_handle_breaks(struct uart_port *port)
/* Notify of BREAK */
if (tty_insert_flip_char(tport, 0, TTY_BREAK))
copied++;
-
- dev_dbg(port->dev, "BREAK detected\n");
}
if (copied)
@@ -2778,44 +2767,29 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev)
clk_names[SCI_SCK] = "hsck";
for (i = 0; i < SCI_NUM_CLKS; i++) {
- clk = devm_clk_get(dev, clk_names[i]);
- if (PTR_ERR(clk) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
-
- if (IS_ERR(clk) && i == SCI_FCK) {
- /*
- * "fck" used to be called "sci_ick", and we need to
- * maintain DT backward compatibility.
- */
- clk = devm_clk_get(dev, "sci_ick");
- if (PTR_ERR(clk) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
-
- if (!IS_ERR(clk))
- goto found;
+ clk = devm_clk_get_optional(dev, clk_names[i]);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+ if (!clk && i == SCI_FCK) {
/*
* Not all SH platforms declare a clock lookup entry
* for SCI devices, in which case we need to get the
* global "peripheral_clk" clock.
*/
clk = devm_clk_get(dev, "peripheral_clk");
- if (!IS_ERR(clk))
- goto found;
-
- dev_err(dev, "failed to get %s (%ld)\n", clk_names[i],
- PTR_ERR(clk));
- return PTR_ERR(clk);
+ if (IS_ERR(clk))
+ return dev_err_probe(dev, PTR_ERR(clk),
+ "failed to get %s\n",
+ clk_names[i]);
}
-found:
- if (IS_ERR(clk))
- dev_dbg(dev, "failed to get %s (%ld)\n", clk_names[i],
- PTR_ERR(clk));
+ if (!clk)
+ dev_dbg(dev, "failed to get %s\n", clk_names[i]);
else
dev_dbg(dev, "clk %s is %pC rate %lu\n", clk_names[i],
clk, clk_get_rate(clk));
- sci_port->clks[i] = IS_ERR(clk) ? NULL : clk;
+ sci_port->clks[i] = clk;
}
return 0;
}
@@ -3180,6 +3154,9 @@ static const struct of_device_id of_sci_match[] = {
}, {
.compatible = "renesas,rcar-gen3-scif",
.data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_BRG_REGTYPE),
+ }, {
+ .compatible = "renesas,rcar-gen4-scif",
+ .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_BRG_REGTYPE),
},
/* Generic types */
{
@@ -3203,23 +3180,47 @@ static const struct of_device_id of_sci_match[] = {
};
MODULE_DEVICE_TABLE(of, of_sci_match);
+static void sci_reset_control_assert(void *data)
+{
+ reset_control_assert(data);
+}
+
static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev,
unsigned int *dev_id)
{
struct device_node *np = pdev->dev.of_node;
+ struct reset_control *rstc;
struct plat_sci_port *p;
struct sci_port *sp;
const void *data;
- int id;
+ int id, ret;
if (!IS_ENABLED(CONFIG_OF) || !np)
- return NULL;
+ return ERR_PTR(-EINVAL);
data = of_device_get_match_data(&pdev->dev);
+ rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(rstc))
+ return ERR_PTR(dev_err_probe(&pdev->dev, PTR_ERR(rstc),
+ "failed to get reset ctrl\n"));
+
+ ret = reset_control_deassert(rstc);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to deassert reset %d\n", ret);
+ return ERR_PTR(ret);
+ }
+
+ ret = devm_add_action_or_reset(&pdev->dev, sci_reset_control_assert, rstc);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register assert devm action, %d\n",
+ ret);
+ return ERR_PTR(ret);
+ }
+
p = devm_kzalloc(&pdev->dev, sizeof(struct plat_sci_port), GFP_KERNEL);
if (!p)
- return NULL;
+ return ERR_PTR(-ENOMEM);
/* Get the line number from the aliases node. */
id = of_alias_get_id(np, "serial");
@@ -3227,11 +3228,11 @@ static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev,
id = ffz(sci_ports_in_use);
if (id < 0) {
dev_err(&pdev->dev, "failed to get alias id (%d)\n", id);
- return NULL;
+ return ERR_PTR(-EINVAL);
}
if (id >= ARRAY_SIZE(sci_ports)) {
dev_err(&pdev->dev, "serial%d out of range\n", id);
- return NULL;
+ return ERR_PTR(-EINVAL);
}
sp = &sci_ports[id];
@@ -3318,8 +3319,8 @@ static int sci_probe(struct platform_device *dev)
if (dev->dev.of_node) {
p = sci_parse_dt(dev, &dev_id);
- if (p == NULL)
- return -EINVAL;
+ if (IS_ERR(p))
+ return PTR_ERR(p);
} else {
p = dev->dev.platform_data;
if (p == NULL) {
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 3244e7f6818c..1f89ab0e49ac 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -365,6 +365,31 @@ static unsigned int stm32_usart_receive_chars(struct uart_port *port, bool force
return size;
}
+static void stm32_usart_tx_dma_terminate(struct stm32_port *stm32_port)
+{
+ dmaengine_terminate_async(stm32_port->tx_ch);
+ stm32_port->tx_dma_busy = false;
+}
+
+static bool stm32_usart_tx_dma_started(struct stm32_port *stm32_port)
+{
+ /*
+ * We cannot use the function "dmaengine_tx_status" to know the
+ * status of DMA. This function does not show if the "dma complete"
+ * callback of the DMA transaction has been called. So we prefer
+ * to use "tx_dma_busy" flag to prevent dual DMA transaction at the
+ * same time.
+ */
+ return stm32_port->tx_dma_busy;
+}
+
+static bool stm32_usart_tx_dma_enabled(struct stm32_port *stm32_port)
+{
+ const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+
+ return !!(readl_relaxed(stm32_port->port.membase + ofs->cr3) & USART_CR3_DMAT);
+}
+
static void stm32_usart_tx_dma_complete(void *arg)
{
struct uart_port *port = arg;
@@ -372,9 +397,8 @@ static void stm32_usart_tx_dma_complete(void *arg)
const struct stm32_usart_offsets *ofs = &stm32port->info->ofs;
unsigned long flags;
- dmaengine_terminate_async(stm32port->tx_ch);
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
- stm32port->tx_dma_busy = false;
+ stm32_usart_tx_dma_terminate(stm32port);
/* Let's see if we have pending data to send */
spin_lock_irqsave(&port->lock, flags);
@@ -428,10 +452,8 @@ static void stm32_usart_transmit_chars_pio(struct uart_port *port)
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
struct circ_buf *xmit = &port->state->xmit;
- if (stm32_port->tx_dma_busy) {
+ if (stm32_usart_tx_dma_enabled(stm32_port))
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
- stm32_port->tx_dma_busy = false;
- }
while (!uart_circ_empty(xmit)) {
/* Check that TDR is empty before filling FIFO */
@@ -455,12 +477,13 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port)
const struct stm32_usart_offsets *ofs = &stm32port->info->ofs;
struct circ_buf *xmit = &port->state->xmit;
struct dma_async_tx_descriptor *desc = NULL;
- unsigned int count, i;
+ unsigned int count;
- if (stm32port->tx_dma_busy)
+ if (stm32_usart_tx_dma_started(stm32port)) {
+ if (!stm32_usart_tx_dma_enabled(stm32port))
+ stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT);
return;
-
- stm32port->tx_dma_busy = true;
+ }
count = uart_circ_chars_pending(xmit);
@@ -491,13 +514,21 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port)
if (!desc)
goto fallback_err;
+ /*
+ * Set "tx_dma_busy" flag. This flag will be released when
+ * dmaengine_terminate_async will be called. This flag helps
+ * transmit_chars_dma not to start another DMA transaction
+ * if the callback of the previous is not yet called.
+ */
+ stm32port->tx_dma_busy = true;
+
desc->callback = stm32_usart_tx_dma_complete;
desc->callback_param = port;
/* Push current DMA TX transaction in the pending queue */
if (dma_submit_error(dmaengine_submit(desc))) {
/* dma no yet started, safe to free resources */
- dmaengine_terminate_async(stm32port->tx_ch);
+ stm32_usart_tx_dma_terminate(stm32port);
goto fallback_err;
}
@@ -511,8 +542,7 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port)
return;
fallback_err:
- for (i = count; i > 0; i--)
- stm32_usart_transmit_chars_pio(port);
+ stm32_usart_transmit_chars_pio(port);
}
static void stm32_usart_transmit_chars(struct uart_port *port)
@@ -522,12 +552,13 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
struct circ_buf *xmit = &port->state->xmit;
if (port->x_char) {
- if (stm32_port->tx_dma_busy)
+ if (stm32_usart_tx_dma_started(stm32_port) &&
+ stm32_usart_tx_dma_enabled(stm32_port))
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
writel_relaxed(port->x_char, port->membase + ofs->tdr);
port->x_char = 0;
port->icount.tx++;
- if (stm32_port->tx_dma_busy)
+ if (stm32_usart_tx_dma_started(stm32_port))
stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT);
return;
}
@@ -675,8 +706,11 @@ static void stm32_usart_stop_tx(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
struct serial_rs485 *rs485conf = &port->rs485;
+ const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
stm32_usart_tx_interrupt_disable(port);
+ if (stm32_usart_tx_dma_started(stm32_port) && stm32_usart_tx_dma_enabled(stm32_port))
+ stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
if (rs485conf->flags & SER_RS485_ENABLED) {
if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
@@ -719,9 +753,8 @@ static void stm32_usart_flush_buffer(struct uart_port *port)
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
if (stm32_port->tx_ch) {
- dmaengine_terminate_async(stm32_port->tx_ch);
+ stm32_usart_tx_dma_terminate(stm32_port);
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
- stm32_port->tx_dma_busy = false;
}
}
@@ -883,6 +916,12 @@ static void stm32_usart_shutdown(struct uart_port *port)
u32 val, isr;
int ret;
+ if (stm32_usart_tx_dma_enabled(stm32_port))
+ stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
+
+ if (stm32_usart_tx_dma_started(stm32_port))
+ stm32_usart_tx_dma_terminate(stm32_port);
+
/* Disable modem control interrupts */
stm32_usart_disable_ms(port);
@@ -1419,8 +1458,6 @@ static int stm32_usart_of_dma_tx_probe(struct stm32_port *stm32port,
struct dma_slave_config config;
int ret;
- stm32port->tx_dma_busy = false;
-
stm32port->tx_buf = dma_alloc_coherent(dev, TX_BUF_L,
&stm32port->tx_dma_buf,
GFP_KERNEL);
@@ -1570,7 +1607,6 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
writel_relaxed(cr3, port->membase + ofs->cr3);
if (stm32_port->tx_ch) {
- dmaengine_terminate_async(stm32_port->tx_ch);
stm32_usart_of_dma_tx_remove(stm32_port, pdev);
dma_release_channel(stm32_port->tx_ch);
}
diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h
index e23916bfbb60..feab952aec16 100644
--- a/drivers/tty/serial/stm32-usart.h
+++ b/drivers/tty/serial/stm32-usart.h
@@ -264,7 +264,7 @@ struct stm32_port {
u32 cr1_irq; /* USART_CR1_RXNEIE or RTOIE */
u32 cr3_irq; /* USART_CR3_RXFTIE */
int last_res;
- bool tx_dma_busy; /* dma tx busy */
+ bool tx_dma_busy; /* dma tx transaction in progress */
bool throttled; /* port throttled */
bool hw_flow_control;
bool swap; /* swap RX & TX pins */
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
index 425a016f9db7..98b2f4fb9a99 100644
--- a/drivers/tty/serial/sunsu.c
+++ b/drivers/tty/serial/sunsu.c
@@ -127,7 +127,8 @@ static void serial_out(struct uart_sunsu_port *up, int offset, int value)
* gate outputs a logical one. Since we use level triggered interrupts
* we have lockup and watchdog reset. We cannot mask IRQ because
* keyboard shares IRQ with us (Word has it as Bob Smelik's design).
- * This problem is similar to what Alpha people suffer, see serial.c.
+ * This problem is similar to what Alpha people suffer, see
+ * 8250_alpha.c.
*/
if (offset == UART_MCR)
value |= UART_MCR_OUT2;
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index d3d9566e5dbd..e1fa52d31474 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -626,7 +626,7 @@ static struct uart_driver ulite_uart_driver = {
*
* Returns: 0 on success, <0 otherwise
*/
-static int ulite_assign(struct device *dev, int id, u32 base, int irq,
+static int ulite_assign(struct device *dev, int id, phys_addr_t base, int irq,
struct uartlite_data *pdata)
{
struct uart_port *port;
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
index e15b2bf69904..9adfe3dc970f 100644
--- a/drivers/tty/serial/vt8500_serial.c
+++ b/drivers/tty/serial/vt8500_serial.c
@@ -621,21 +621,25 @@ static const struct of_device_id wmt_dt_ids[] = {
static int vt8500_serial_probe(struct platform_device *pdev)
{
struct vt8500_port *vt8500_port;
- struct resource *mmres, *irqres;
+ struct resource *mmres;
struct device_node *np = pdev->dev.of_node;
const unsigned int *flags;
int ret;
int port;
+ int irq;
flags = of_device_get_match_data(&pdev->dev);
if (!flags)
return -EINVAL;
mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!mmres || !irqres)
+ if (!mmres)
return -ENODEV;
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
if (np) {
port = of_alias_get_id(np, "serial");
if (port >= VT8500_MAX_PORTS)
@@ -688,7 +692,7 @@ static int vt8500_serial_probe(struct platform_device *pdev)
vt8500_port->uart.type = PORT_VT8500;
vt8500_port->uart.iotype = UPIO_MEM;
vt8500_port->uart.mapbase = mmres->start;
- vt8500_port->uart.irq = irqres->start;
+ vt8500_port->uart.irq = irq;
vt8500_port->uart.fifosize = 16;
vt8500_port->uart.ops = &vt8500_uart_pops;
vt8500_port->uart.line = port;
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 6c7e65b1d9a1..646510476c30 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -39,20 +39,15 @@
#define TTY_BUFFER_PAGE (((PAGE_SIZE - sizeof(struct tty_buffer)) / 2) & ~0xFF)
/**
- * tty_buffer_lock_exclusive - gain exclusive access to buffer
- * tty_buffer_unlock_exclusive - release exclusive access
+ * tty_buffer_lock_exclusive - gain exclusive access to buffer
+ * @port: tty port owning the flip buffer
*
- * @port: tty port owning the flip buffer
+ * Guarantees safe use of the &tty_ldisc_ops.receive_buf() method by excluding
+ * the buffer work and any pending flush from using the flip buffer. Data can
+ * continue to be added concurrently to the flip buffer from the driver side.
*
- * Guarantees safe use of the line discipline's receive_buf() method by
- * excluding the buffer work and any pending flush from using the flip
- * buffer. Data can continue to be added concurrently to the flip buffer
- * from the driver side.
- *
- * On release, the buffer work is restarted if there is data in the
- * flip buffer
+ * See also tty_buffer_unlock_exclusive().
*/
-
void tty_buffer_lock_exclusive(struct tty_port *port)
{
struct tty_bufhead *buf = &port->buf;
@@ -62,6 +57,14 @@ void tty_buffer_lock_exclusive(struct tty_port *port)
}
EXPORT_SYMBOL_GPL(tty_buffer_lock_exclusive);
+/**
+ * tty_buffer_unlock_exclusive - release exclusive access
+ * @port: tty port owning the flip buffer
+ *
+ * The buffer work is restarted if there is data in the flip buffer.
+ *
+ * See also tty_buffer_lock_exclusive().
+ */
void tty_buffer_unlock_exclusive(struct tty_port *port)
{
struct tty_bufhead *buf = &port->buf;
@@ -77,17 +80,16 @@ void tty_buffer_unlock_exclusive(struct tty_port *port)
EXPORT_SYMBOL_GPL(tty_buffer_unlock_exclusive);
/**
- * tty_buffer_space_avail - return unused buffer space
- * @port: tty port owning the flip buffer
+ * tty_buffer_space_avail - return unused buffer space
+ * @port: tty port owning the flip buffer
*
- * Returns the # of bytes which can be written by the driver without
- * reaching the buffer limit.
+ * Returns: the # of bytes which can be written by the driver without reaching
+ * the buffer limit.
*
- * Note: this does not guarantee that memory is available to write
- * the returned # of bytes (use tty_prepare_flip_string_xxx() to
- * pre-allocate if memory guarantee is required).
+ * Note: this does not guarantee that memory is available to write the returned
+ * # of bytes (use tty_prepare_flip_string() to pre-allocate if memory
+ * guarantee is required).
*/
-
unsigned int tty_buffer_space_avail(struct tty_port *port)
{
int space = port->buf.mem_limit - atomic_read(&port->buf.mem_used);
@@ -107,13 +109,12 @@ static void tty_buffer_reset(struct tty_buffer *p, size_t size)
}
/**
- * tty_buffer_free_all - free buffers used by a tty
- * @port: tty port to free from
+ * tty_buffer_free_all - free buffers used by a tty
+ * @port: tty port to free from
*
- * Remove all the buffers pending on a tty whether queued with data
- * or in the free ring. Must be called when the tty is no longer in use
+ * Remove all the buffers pending on a tty whether queued with data or in the
+ * free ring. Must be called when the tty is no longer in use.
*/
-
void tty_buffer_free_all(struct tty_port *port)
{
struct tty_bufhead *buf = &port->buf;
@@ -142,17 +143,17 @@ void tty_buffer_free_all(struct tty_port *port)
}
/**
- * tty_buffer_alloc - allocate a tty buffer
- * @port: tty port
- * @size: desired size (characters)
- *
- * Allocate a new tty buffer to hold the desired number of characters.
- * We round our buffers off in 256 character chunks to get better
- * allocation behaviour.
- * Return NULL if out of memory or the allocation would exceed the
- * per device queue
+ * tty_buffer_alloc - allocate a tty buffer
+ * @port: tty port
+ * @size: desired size (characters)
+ *
+ * Allocate a new tty buffer to hold the desired number of characters. We
+ * round our buffers off in 256 character chunks to get better allocation
+ * behaviour.
+ *
+ * Returns: %NULL if out of memory or the allocation would exceed the per
+ * device queue.
*/
-
static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size)
{
struct llist_node *free;
@@ -185,14 +186,13 @@ found:
}
/**
- * tty_buffer_free - free a tty buffer
- * @port: tty port owning the buffer
- * @b: the buffer to free
+ * tty_buffer_free - free a tty buffer
+ * @port: tty port owning the buffer
+ * @b: the buffer to free
*
- * Free a tty buffer, or add it to the free list according to our
- * internal strategy
+ * Free a tty buffer, or add it to the free list according to our internal
+ * strategy.
*/
-
static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b)
{
struct tty_bufhead *buf = &port->buf;
@@ -207,17 +207,15 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b)
}
/**
- * tty_buffer_flush - flush full tty buffers
- * @tty: tty to flush
- * @ld: optional ldisc ptr (must be referenced)
+ * tty_buffer_flush - flush full tty buffers
+ * @tty: tty to flush
+ * @ld: optional ldisc ptr (must be referenced)
*
- * flush all the buffers containing receive data. If ld != NULL,
- * flush the ldisc input buffer.
+ * Flush all the buffers containing receive data. If @ld != %NULL, flush the
+ * ldisc input buffer.
*
- * Locking: takes buffer lock to ensure single-threaded flip buffer
- * 'consumer'
+ * Locking: takes buffer lock to ensure single-threaded flip buffer 'consumer'.
*/
-
void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld)
{
struct tty_port *port = tty->port;
@@ -244,17 +242,18 @@ void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld)
}
/**
- * __tty_buffer_request_room - grow tty buffer if needed
- * @port: tty port
- * @size: size desired
- * @flags: buffer flags if new buffer allocated (default = 0)
+ * __tty_buffer_request_room - grow tty buffer if needed
+ * @port: tty port
+ * @size: size desired
+ * @flags: buffer flags if new buffer allocated (default = 0)
+ *
+ * Make at least @size bytes of linear space available for the tty buffer.
*
- * Make at least size bytes of linear space available for the tty
- * buffer. If we fail return the size we managed to find.
+ * Will change over to a new buffer if the current buffer is encoded as
+ * %TTY_NORMAL (so has no flags buffer) and the new buffer requires a flags
+ * buffer.
*
- * Will change over to a new buffer if the current buffer is encoded as
- * TTY_NORMAL (so has no flags buffer) and the new buffer requires
- * a flags buffer.
+ * Returns: the size we managed to find.
*/
static int __tty_buffer_request_room(struct tty_port *port, size_t size,
int flags)
@@ -300,16 +299,17 @@ int tty_buffer_request_room(struct tty_port *port, size_t size)
EXPORT_SYMBOL_GPL(tty_buffer_request_room);
/**
- * tty_insert_flip_string_fixed_flag - Add characters to the tty buffer
- * @port: tty port
- * @chars: characters
- * @flag: flag value for each character
- * @size: size
- *
- * Queue a series of bytes to the tty buffering. All the characters
- * passed are marked with the supplied flag. Returns the number added.
+ * tty_insert_flip_string_fixed_flag - add characters to the tty buffer
+ * @port: tty port
+ * @chars: characters
+ * @flag: flag value for each character
+ * @size: size
+ *
+ * Queue a series of bytes to the tty buffering. All the characters passed are
+ * marked with the supplied flag.
+ *
+ * Returns: the number added.
*/
-
int tty_insert_flip_string_fixed_flag(struct tty_port *port,
const unsigned char *chars, char flag, size_t size)
{
@@ -338,17 +338,17 @@ int tty_insert_flip_string_fixed_flag(struct tty_port *port,
EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag);
/**
- * tty_insert_flip_string_flags - Add characters to the tty buffer
- * @port: tty port
- * @chars: characters
- * @flags: flag bytes
- * @size: size
- *
- * Queue a series of bytes to the tty buffering. For each character
- * the flags array indicates the status of the character. Returns the
- * number added.
+ * tty_insert_flip_string_flags - add characters to the tty buffer
+ * @port: tty port
+ * @chars: characters
+ * @flags: flag bytes
+ * @size: size
+ *
+ * Queue a series of bytes to the tty buffering. For each character the flags
+ * array indicates the status of the character.
+ *
+ * Returns: the number added.
*/
-
int tty_insert_flip_string_flags(struct tty_port *port,
const unsigned char *chars, const char *flags, size_t size)
{
@@ -376,13 +376,13 @@ int tty_insert_flip_string_flags(struct tty_port *port,
EXPORT_SYMBOL(tty_insert_flip_string_flags);
/**
- * __tty_insert_flip_char - Add one character to the tty buffer
- * @port: tty port
- * @ch: character
- * @flag: flag byte
+ * __tty_insert_flip_char - add one character to the tty buffer
+ * @port: tty port
+ * @ch: character
+ * @flag: flag byte
*
- * Queue a single byte to the tty buffering, with an optional flag.
- * This is the slow path of tty_insert_flip_char.
+ * Queue a single byte @ch to the tty buffering, with an optional flag. This is
+ * the slow path of tty_insert_flip_char().
*/
int __tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag)
{
@@ -402,39 +402,19 @@ int __tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag)
EXPORT_SYMBOL(__tty_insert_flip_char);
/**
- * tty_schedule_flip - push characters to ldisc
- * @port: tty port to push from
+ * tty_prepare_flip_string - make room for characters
+ * @port: tty port
+ * @chars: return pointer for character write area
+ * @size: desired size
*
- * Takes any pending buffers and transfers their ownership to the
- * ldisc side of the queue. It then schedules those characters for
- * processing by the line discipline.
- */
-
-void tty_schedule_flip(struct tty_port *port)
-{
- struct tty_bufhead *buf = &port->buf;
-
- /* paired w/ acquire in flush_to_ldisc(); ensures
- * flush_to_ldisc() sees buffer data.
- */
- smp_store_release(&buf->tail->commit, buf->tail->used);
- queue_work(system_unbound_wq, &buf->work);
-}
-EXPORT_SYMBOL(tty_schedule_flip);
-
-/**
- * tty_prepare_flip_string - make room for characters
- * @port: tty port
- * @chars: return pointer for character write area
- * @size: desired size
- *
- * Prepare a block of space in the buffer for data. Returns the length
- * available and buffer pointer to the space which is now allocated and
- * accounted for as ready for normal characters. This is used for drivers
- * that need their own block copy routines into the buffer. There is no
- * guarantee the buffer is a DMA target!
+ * Prepare a block of space in the buffer for data.
+ *
+ * This is used for drivers that need their own block copy routines into the
+ * buffer. There is no guarantee the buffer is a DMA target!
+ *
+ * Returns: the length available and buffer pointer (@chars) to the space which
+ * is now allocated and accounted for as ready for normal characters.
*/
-
int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars,
size_t size)
{
@@ -453,16 +433,16 @@ int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars,
EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
/**
- * tty_ldisc_receive_buf - forward data to line discipline
- * @ld: line discipline to process input
- * @p: char buffer
- * @f: TTY_* flags buffer
- * @count: number of bytes to process
+ * tty_ldisc_receive_buf - forward data to line discipline
+ * @ld: line discipline to process input
+ * @p: char buffer
+ * @f: %TTY_NORMAL, %TTY_BREAK, etc. flags buffer
+ * @count: number of bytes to process
*
- * Callers other than flush_to_ldisc() need to exclude the kworker
- * from concurrent use of the line discipline, see paste_selection().
+ * Callers other than flush_to_ldisc() need to exclude the kworker from
+ * concurrent use of the line discipline, see paste_selection().
*
- * Returns the number of bytes processed
+ * Returns: the number of bytes processed.
*/
int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p,
const char *f, int count)
@@ -495,18 +475,16 @@ receive_buf(struct tty_port *port, struct tty_buffer *head, int count)
}
/**
- * flush_to_ldisc
- * @work: tty structure passed from work queue.
+ * flush_to_ldisc - flush data from buffer to ldisc
+ * @work: tty structure passed from work queue.
*
- * This routine is called out of the software interrupt to flush data
- * from the buffer chain to the line discipline.
+ * This routine is called out of the software interrupt to flush data from the
+ * buffer chain to the line discipline.
*
- * The receive_buf method is single threaded for each tty instance.
+ * The receive_buf() method is single threaded for each tty instance.
*
- * Locking: takes buffer lock to ensure single-threaded flip buffer
- * 'consumer'
+ * Locking: takes buffer lock to ensure single-threaded flip buffer 'consumer'.
*/
-
static void flush_to_ldisc(struct work_struct *work)
{
struct tty_port *port = container_of(work, struct tty_port, buf.work);
@@ -554,30 +532,35 @@ static void flush_to_ldisc(struct work_struct *work)
}
/**
- * tty_flip_buffer_push - terminal
- * @port: tty port to push
+ * tty_flip_buffer_push - push terminal buffers
+ * @port: tty port to push
*
- * Queue a push of the terminal flip buffers to the line discipline.
- * Can be called from IRQ/atomic context.
+ * Queue a push of the terminal flip buffers to the line discipline. Can be
+ * called from IRQ/atomic context.
*
- * In the event of the queue being busy for flipping the work will be
- * held off and retried later.
+ * In the event of the queue being busy for flipping the work will be held off
+ * and retried later.
*/
-
void tty_flip_buffer_push(struct tty_port *port)
{
- tty_schedule_flip(port);
+ struct tty_bufhead *buf = &port->buf;
+
+ /*
+ * Paired w/ acquire in flush_to_ldisc(); ensures flush_to_ldisc() sees
+ * buffer data.
+ */
+ smp_store_release(&buf->tail->commit, buf->tail->used);
+ queue_work(system_unbound_wq, &buf->work);
}
EXPORT_SYMBOL(tty_flip_buffer_push);
/**
- * tty_buffer_init - prepare a tty buffer structure
- * @port: tty port to initialise
+ * tty_buffer_init - prepare a tty buffer structure
+ * @port: tty port to initialise
*
- * Set up the initial state of the buffer management for a tty device.
- * Must be called before the other tty buffer functions are used.
+ * Set up the initial state of the buffer management for a tty device. Must be
+ * called before the other tty buffer functions are used.
*/
-
void tty_buffer_init(struct tty_port *port)
{
struct tty_bufhead *buf = &port->buf;
@@ -594,14 +577,14 @@ void tty_buffer_init(struct tty_port *port)
}
/**
- * tty_buffer_set_limit - change the tty buffer memory limit
- * @port: tty port to change
- * @limit: memory limit to set
+ * tty_buffer_set_limit - change the tty buffer memory limit
+ * @port: tty port to change
+ * @limit: memory limit to set
*
- * Change the tty buffer memory limit.
- * Must be called before the other tty buffer functions are used.
+ * Change the tty buffer memory limit.
+ *
+ * Must be called before the other tty buffer functions are used.
*/
-
int tty_buffer_set_limit(struct tty_port *port, int limit)
{
if (limit < MIN_TTYB_SIZE)
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 6616d4a0d41d..7e8b3bd59c7b 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -158,19 +158,18 @@ static int tty_fasync(int fd, struct file *filp, int on);
static void release_tty(struct tty_struct *tty, int idx);
/**
- * free_tty_struct - free a disused tty
- * @tty: tty struct to free
+ * free_tty_struct - free a disused tty
+ * @tty: tty struct to free
*
- * Free the write buffers, tty queue and tty memory itself.
+ * Free the write buffers, tty queue and tty memory itself.
*
- * Locking: none. Must be called after tty is definitely unused
+ * Locking: none. Must be called after tty is definitely unused
*/
-
static void free_tty_struct(struct tty_struct *tty)
{
tty_ldisc_deinit(tty);
put_device(tty->dev);
- kfree(tty->write_buf);
+ kvfree(tty->write_buf);
tty->magic = 0xDEADDEAD;
kfree(tty);
}
@@ -206,8 +205,9 @@ void tty_add_file(struct tty_struct *tty, struct file *file)
spin_unlock(&tty->files_lock);
}
-/*
+/**
* tty_free_file - free file->private_data
+ * @file: to free private_data of
*
* This shall be used only for fail path handling when tty_add_file was not
* called yet.
@@ -233,15 +233,14 @@ static void tty_del_file(struct file *file)
}
/**
- * tty_name - return tty naming
- * @tty: tty structure
+ * tty_name - return tty naming
+ * @tty: tty structure
*
- * Convert a tty structure into a name. The name reflects the kernel
- * naming policy and if udev is in use may not reflect user space
+ * Convert a tty structure into a name. The name reflects the kernel naming
+ * policy and if udev is in use may not reflect user space
*
- * Locking: none
+ * Locking: none
*/
-
const char *tty_name(const struct tty_struct *tty)
{
if (!tty) /* Hmm. NULL pointer. That's fun. */
@@ -303,16 +302,15 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
}
/**
- * get_tty_driver - find device of a tty
- * @device: device identifier
- * @index: returns the index of the tty
+ * get_tty_driver - find device of a tty
+ * @device: device identifier
+ * @index: returns the index of the tty
*
- * This routine returns a tty driver structure, given a device number
- * and also passes back the index number.
+ * This routine returns a tty driver structure, given a device number and also
+ * passes back the index number.
*
- * Locking: caller must hold tty_mutex
+ * Locking: caller must hold tty_mutex
*/
-
static struct tty_driver *get_tty_driver(dev_t device, int *index)
{
struct tty_driver *p;
@@ -329,17 +327,17 @@ static struct tty_driver *get_tty_driver(dev_t device, int *index)
}
/**
- * tty_dev_name_to_number - return dev_t for device name
- * @name: user space name of device under /dev
- * @number: pointer to dev_t that this function will populate
+ * tty_dev_name_to_number - return dev_t for device name
+ * @name: user space name of device under /dev
+ * @number: pointer to dev_t that this function will populate
*
- * This function converts device names like ttyS0 or ttyUSB1 into dev_t
- * like (4, 64) or (188, 1). If no corresponding driver is registered then
- * the function returns -ENODEV.
+ * This function converts device names like ttyS0 or ttyUSB1 into dev_t like
+ * (4, 64) or (188, 1). If no corresponding driver is registered then the
+ * function returns -%ENODEV.
*
- * Locking: this acquires tty_mutex to protect the tty_drivers list from
- * being modified while we are traversing it, and makes sure to
- * release it before exiting.
+ * Locking: this acquires tty_mutex to protect the tty_drivers list from
+ * being modified while we are traversing it, and makes sure to
+ * release it before exiting.
*/
int tty_dev_name_to_number(const char *name, dev_t *number)
{
@@ -381,13 +379,12 @@ EXPORT_SYMBOL_GPL(tty_dev_name_to_number);
#ifdef CONFIG_CONSOLE_POLL
/**
- * tty_find_polling_driver - find device of a polled tty
- * @name: name string to match
- * @line: pointer to resulting tty line nr
+ * tty_find_polling_driver - find device of a polled tty
+ * @name: name string to match
+ * @line: pointer to resulting tty line nr
*
- * This routine returns a tty driver structure, given a name
- * and the condition that the tty driver is capable of polled
- * operation.
+ * This routine returns a tty driver structure, given a name and the condition
+ * that the tty driver is capable of polled operation.
*/
struct tty_driver *tty_find_polling_driver(char *name, int *line)
{
@@ -515,14 +512,13 @@ static DEFINE_SPINLOCK(redirect_lock);
static struct file *redirect;
/**
- * tty_wakeup - request more data
- * @tty: terminal
+ * tty_wakeup - request more data
+ * @tty: terminal
*
- * Internal and external helper for wakeups of tty. This function
- * informs the line discipline if present that the driver is ready
- * to receive more output data.
+ * Internal and external helper for wakeups of tty. This function informs the
+ * line discipline if present that the driver is ready to receive more output
+ * data.
*/
-
void tty_wakeup(struct tty_struct *tty)
{
struct tty_ldisc *ld;
@@ -540,11 +536,11 @@ void tty_wakeup(struct tty_struct *tty)
EXPORT_SYMBOL_GPL(tty_wakeup);
/**
- * tty_release_redirect - Release a redirect on a pty if present
- * @tty: tty device
+ * tty_release_redirect - Release a redirect on a pty if present
+ * @tty: tty device
*
- * This is available to the pty code so if the master closes, if the
- * slave is a redirect it can release the redirect.
+ * This is available to the pty code so if the master closes, if the slave is a
+ * redirect it can release the redirect.
*/
static struct file *tty_release_redirect(struct tty_struct *tty)
{
@@ -561,27 +557,29 @@ static struct file *tty_release_redirect(struct tty_struct *tty)
}
/**
- * __tty_hangup - actual handler for hangup events
- * @tty: tty device
- * @exit_session: if non-zero, signal all foreground group processes
+ * __tty_hangup - actual handler for hangup events
+ * @tty: tty device
+ * @exit_session: if non-zero, signal all foreground group processes
+ *
+ * This can be called by a "kworker" kernel thread. That is process synchronous
+ * but doesn't hold any locks, so we need to make sure we have the appropriate
+ * locks for what we're doing.
+ *
+ * The hangup event clears any pending redirections onto the hung up device. It
+ * ensures future writes will error and it does the needed line discipline
+ * hangup and signal delivery. The tty object itself remains intact.
+ *
+ * Locking:
+ * * BTM
*
- * This can be called by a "kworker" kernel thread. That is process
- * synchronous but doesn't hold any locks, so we need to make sure we
- * have the appropriate locks for what we're doing.
+ * * redirect lock for undoing redirection
+ * * file list lock for manipulating list of ttys
+ * * tty_ldiscs_lock from called functions
+ * * termios_rwsem resetting termios data
+ * * tasklist_lock to walk task list for hangup event
*
- * The hangup event clears any pending redirections onto the hung up
- * device. It ensures future writes will error and it does the needed
- * line discipline hangup and signal delivery. The tty object itself
- * remains intact.
+ * * ->siglock to protect ->signal/->sighand
*
- * Locking:
- * BTM
- * redirect lock for undoing redirection
- * file list lock for manipulating list of ttys
- * tty_ldiscs_lock from called functions
- * termios_rwsem resetting termios data
- * tasklist_lock to walk task list for hangup event
- * ->siglock to protect ->signal/->sighand
*/
static void __tty_hangup(struct tty_struct *tty, int exit_session)
{
@@ -682,13 +680,12 @@ static void do_tty_hangup(struct work_struct *work)
}
/**
- * tty_hangup - trigger a hangup event
- * @tty: tty to hangup
+ * tty_hangup - trigger a hangup event
+ * @tty: tty to hangup
*
- * A carrier loss (virtual or otherwise) has occurred on this like
- * schedule a hangup sequence to run after this event.
+ * A carrier loss (virtual or otherwise) has occurred on @tty. Schedule a
+ * hangup sequence to run after this event.
*/
-
void tty_hangup(struct tty_struct *tty)
{
tty_debug_hangup(tty, "hangup\n");
@@ -697,14 +694,13 @@ void tty_hangup(struct tty_struct *tty)
EXPORT_SYMBOL(tty_hangup);
/**
- * tty_vhangup - process vhangup
- * @tty: tty to hangup
+ * tty_vhangup - process vhangup
+ * @tty: tty to hangup
*
- * The user has asked via system call for the terminal to be hung up.
- * We do this synchronously so that when the syscall returns the process
- * is complete. That guarantee is necessary for security reasons.
+ * The user has asked via system call for the terminal to be hung up. We do
+ * this synchronously so that when the syscall returns the process is complete.
+ * That guarantee is necessary for security reasons.
*/
-
void tty_vhangup(struct tty_struct *tty)
{
tty_debug_hangup(tty, "vhangup\n");
@@ -714,11 +710,10 @@ EXPORT_SYMBOL(tty_vhangup);
/**
- * tty_vhangup_self - process vhangup for own ctty
+ * tty_vhangup_self - process vhangup for own ctty
*
- * Perform a vhangup on the current controlling tty
+ * Perform a vhangup on the current controlling tty
*/
-
void tty_vhangup_self(void)
{
struct tty_struct *tty;
@@ -731,16 +726,15 @@ void tty_vhangup_self(void)
}
/**
- * tty_vhangup_session - hangup session leader exit
- * @tty: tty to hangup
+ * tty_vhangup_session - hangup session leader exit
+ * @tty: tty to hangup
*
- * The session leader is exiting and hanging up its controlling terminal.
- * Every process in the foreground process group is signalled SIGHUP.
+ * The session leader is exiting and hanging up its controlling terminal.
+ * Every process in the foreground process group is signalled %SIGHUP.
*
- * We do this synchronously so that when the syscall returns the process
- * is complete. That guarantee is necessary for security reasons.
+ * We do this synchronously so that when the syscall returns the process is
+ * complete. That guarantee is necessary for security reasons.
*/
-
void tty_vhangup_session(struct tty_struct *tty)
{
tty_debug_hangup(tty, "session hangup\n");
@@ -748,13 +742,11 @@ void tty_vhangup_session(struct tty_struct *tty)
}
/**
- * tty_hung_up_p - was tty hung up
- * @filp: file pointer of tty
+ * tty_hung_up_p - was tty hung up
+ * @filp: file pointer of tty
*
- * Return true if the tty has been subject to a vhangup or a carrier
- * loss
+ * Return: true if the tty has been subject to a vhangup or a carrier loss
*/
-
int tty_hung_up_p(struct file *filp)
{
return (filp && filp->f_op == &hung_up_tty_fops);
@@ -771,20 +763,18 @@ void __stop_tty(struct tty_struct *tty)
}
/**
- * stop_tty - propagate flow control
- * @tty: tty to stop
+ * stop_tty - propagate flow control
+ * @tty: tty to stop
*
- * Perform flow control to the driver. May be called
- * on an already stopped device and will not re-call the driver
- * method.
+ * Perform flow control to the driver. May be called on an already stopped
+ * device and will not re-call the &tty_driver->stop() method.
*
- * This functionality is used by both the line disciplines for
- * halting incoming flow and by the driver. It may therefore be
- * called from any context, may be under the tty atomic_write_lock
- * but not always.
+ * This functionality is used by both the line disciplines for halting incoming
+ * flow and by the driver. It may therefore be called from any context, may be
+ * under the tty %atomic_write_lock but not always.
*
- * Locking:
- * flow.lock
+ * Locking:
+ * flow.lock
*/
void stop_tty(struct tty_struct *tty)
{
@@ -807,15 +797,15 @@ void __start_tty(struct tty_struct *tty)
}
/**
- * start_tty - propagate flow control
- * @tty: tty to start
+ * start_tty - propagate flow control
+ * @tty: tty to start
*
- * Start a tty that has been stopped if at all possible. If this
- * tty was previous stopped and is now being started, the driver
- * start method is invoked and the line discipline woken.
+ * Start a tty that has been stopped if at all possible. If @tty was previously
+ * stopped and is now being started, the &tty_driver->start() method is invoked
+ * and the line discipline woken.
*
- * Locking:
- * flow.lock
+ * Locking:
+ * flow.lock
*/
void start_tty(struct tty_struct *tty)
{
@@ -908,18 +898,17 @@ static int iterate_tty_read(struct tty_ldisc *ld, struct tty_struct *tty,
/**
- * tty_read - read method for tty device files
- * @iocb: kernel I/O control block
- * @to: destination for the data read
+ * tty_read - read method for tty device files
+ * @iocb: kernel I/O control block
+ * @to: destination for the data read
*
- * Perform the read system call function on this terminal device. Checks
- * for hung up devices before calling the line discipline method.
+ * Perform the read system call function on this terminal device. Checks
+ * for hung up devices before calling the line discipline method.
*
- * Locking:
- * Locks the line discipline internally while needed. Multiple
- * read calls may be outstanding in parallel.
+ * Locking:
+ * Locks the line discipline internally while needed. Multiple read calls
+ * may be outstanding in parallel.
*/
-
static ssize_t tty_read(struct kiocb *iocb, struct iov_iter *to)
{
int i;
@@ -997,9 +986,6 @@ static inline ssize_t do_tty_write(
* layer has problems with bigger chunks. It will
* claim to be able to handle more characters than
* it actually does.
- *
- * FIXME: This can probably go away now except that 64K chunks
- * are too likely to fail unless switched to vmalloc...
*/
chunk = 2048;
if (test_bit(TTY_NO_WRITE_SPLIT, &tty->flags))
@@ -1014,12 +1000,12 @@ static inline ssize_t do_tty_write(
if (chunk < 1024)
chunk = 1024;
- buf_chunk = kmalloc(chunk, GFP_KERNEL);
+ buf_chunk = kvmalloc(chunk, GFP_KERNEL | __GFP_RETRY_MAYFAIL);
if (!buf_chunk) {
ret = -ENOMEM;
goto out;
}
- kfree(tty->write_buf);
+ kvfree(tty->write_buf);
tty->write_cnt = chunk;
tty->write_buf = buf_chunk;
}
@@ -1069,13 +1055,12 @@ out:
* @tty: the destination tty_struct
* @msg: the message to write
*
- * This is used for messages that need to be redirected to a specific tty.
- * We don't put it into the syslog queue right now maybe in the future if
- * really needed.
+ * This is used for messages that need to be redirected to a specific tty. We
+ * don't put it into the syslog queue right now maybe in the future if really
+ * needed.
*
* We must still hold the BTM and test the CLOSING flag for the moment.
*/
-
void tty_write_message(struct tty_struct *tty, char *msg)
{
if (tty) {
@@ -1113,18 +1098,18 @@ static ssize_t file_tty_write(struct file *file, struct kiocb *iocb, struct iov_
}
/**
- * tty_write - write method for tty device file
- * @iocb: kernel I/O control block
- * @from: iov_iter with data to write
+ * tty_write - write method for tty device file
+ * @iocb: kernel I/O control block
+ * @from: iov_iter with data to write
*
- * Write data to a tty device via the line discipline.
+ * Write data to a tty device via the line discipline.
*
- * Locking:
- * Locks the line discipline as required
- * Writes to the tty driver are serialized by the atomic_write_lock
- * and are then processed in chunks to the device. The line
- * discipline write method will not be invoked in parallel for
- * each device.
+ * Locking:
+ * Locks the line discipline as required
+ * Writes to the tty driver are serialized by the atomic_write_lock
+ * and are then processed in chunks to the device. The line
+ * discipline write method will not be invoked in parallel for
+ * each device.
*/
static ssize_t tty_write(struct kiocb *iocb, struct iov_iter *from)
{
@@ -1154,14 +1139,15 @@ ssize_t redirected_tty_write(struct kiocb *iocb, struct iov_iter *iter)
return tty_write(iocb, iter);
}
-/*
- * tty_send_xchar - send priority character
+/**
+ * tty_send_xchar - send priority character
+ * @tty: the tty to send to
+ * @ch: xchar to send
*
- * Send a high priority character to the tty even if stopped
+ * Send a high priority character to the tty even if stopped.
*
- * Locking: none for xchar method, write ordering for write method.
+ * Locking: none for xchar method, write ordering for write method.
*/
-
int tty_send_xchar(struct tty_struct *tty, char ch)
{
bool was_stopped = tty->flow.stopped;
@@ -1188,15 +1174,15 @@ int tty_send_xchar(struct tty_struct *tty, char ch)
}
/**
- * pty_line_name - generate name for a pty
- * @driver: the tty driver in use
- * @index: the minor number
- * @p: output buffer of at least 6 bytes
+ * pty_line_name - generate name for a pty
+ * @driver: the tty driver in use
+ * @index: the minor number
+ * @p: output buffer of at least 6 bytes
*
- * Generate a name from a driver reference and write it to the output
- * buffer.
+ * Generate a name from a @driver reference and write it to the output buffer
+ * @p.
*
- * Locking: None
+ * Locking: None
*/
static void pty_line_name(struct tty_driver *driver, int index, char *p)
{
@@ -1209,15 +1195,15 @@ static void pty_line_name(struct tty_driver *driver, int index, char *p)
}
/**
- * tty_line_name - generate name for a tty
- * @driver: the tty driver in use
- * @index: the minor number
- * @p: output buffer of at least 7 bytes
+ * tty_line_name - generate name for a tty
+ * @driver: the tty driver in use
+ * @index: the minor number
+ * @p: output buffer of at least 7 bytes
*
- * Generate a name from a driver reference and write it to the output
- * buffer.
+ * Generate a name from a @driver reference and write it to the output buffer
+ * @p.
*
- * Locking: None
+ * Locking: None
*/
static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p)
{
@@ -1229,15 +1215,15 @@ static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p)
}
/**
- * tty_driver_lookup_tty() - find an existing tty, if any
- * @driver: the driver for the tty
- * @file: file object
- * @idx: the minor number
+ * tty_driver_lookup_tty() - find an existing tty, if any
+ * @driver: the driver for the tty
+ * @file: file object
+ * @idx: the minor number
*
- * Return the tty, if found. If not found, return NULL or ERR_PTR() if the
- * driver lookup() method returns an error.
+ * Return: the tty, if found. If not found, return %NULL or ERR_PTR() if the
+ * driver lookup() method returns an error.
*
- * Locking: tty_mutex must be held. If the tty is found, bump the tty kref.
+ * Locking: tty_mutex must be held. If the tty is found, bump the tty kref.
*/
static struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver,
struct file *file, int idx)
@@ -1258,13 +1244,12 @@ static struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver,
}
/**
- * tty_init_termios - helper for termios setup
- * @tty: the tty to set up
+ * tty_init_termios - helper for termios setup
+ * @tty: the tty to set up
*
- * Initialise the termios structure for this tty. This runs under
- * the tty_mutex currently so we can be relaxed about ordering.
+ * Initialise the termios structure for this tty. This runs under the
+ * %tty_mutex currently so we can be relaxed about ordering.
*/
-
void tty_init_termios(struct tty_struct *tty)
{
struct ktermios *tp;
@@ -1287,6 +1272,14 @@ void tty_init_termios(struct tty_struct *tty)
}
EXPORT_SYMBOL_GPL(tty_init_termios);
+/**
+ * tty_standard_install - usual tty->ops->install
+ * @driver: the driver for the tty
+ * @tty: the tty
+ *
+ * If the @driver overrides @tty->ops->install, it still can call this function
+ * to perform the standard install operations.
+ */
int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty)
{
tty_init_termios(tty);
@@ -1298,16 +1291,15 @@ int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty)
EXPORT_SYMBOL_GPL(tty_standard_install);
/**
- * tty_driver_install_tty() - install a tty entry in the driver
- * @driver: the driver for the tty
- * @tty: the tty
+ * tty_driver_install_tty() - install a tty entry in the driver
+ * @driver: the driver for the tty
+ * @tty: the tty
*
- * Install a tty object into the driver tables. The tty->index field
- * will be set by the time this is called. This method is responsible
- * for ensuring any need additional structures are allocated and
- * configured.
+ * Install a tty object into the driver tables. The @tty->index field will be
+ * set by the time this is called. This method is responsible for ensuring any
+ * need additional structures are allocated and configured.
*
- * Locking: tty_mutex for now
+ * Locking: tty_mutex for now
*/
static int tty_driver_install_tty(struct tty_driver *driver,
struct tty_struct *tty)
@@ -1317,14 +1309,14 @@ static int tty_driver_install_tty(struct tty_driver *driver,
}
/**
- * tty_driver_remove_tty() - remove a tty from the driver tables
- * @driver: the driver for the tty
- * @tty: tty to remove
+ * tty_driver_remove_tty() - remove a tty from the driver tables
+ * @driver: the driver for the tty
+ * @tty: tty to remove
*
- * Remvoe a tty object from the driver tables. The tty->index field
- * will be set by the time this is called.
+ * Remove a tty object from the driver tables. The tty->index field will be set
+ * by the time this is called.
*
- * Locking: tty_mutex for now
+ * Locking: tty_mutex for now
*/
static void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *tty)
{
@@ -1335,13 +1327,13 @@ static void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *
}
/**
- * tty_reopen() - fast re-open of an open tty
- * @tty: the tty to open
+ * tty_reopen() - fast re-open of an open tty
+ * @tty: the tty to open
*
- * Return 0 on success, -errno on error.
- * Re-opens on master ptys are not allowed and return -EIO.
+ * Re-opens on master ptys are not allowed and return -%EIO.
*
- * Locking: Caller must hold tty_lock
+ * Locking: Caller must hold tty_lock
+ * Return: 0 on success, -errno on error.
*/
static int tty_reopen(struct tty_struct *tty)
{
@@ -1379,30 +1371,28 @@ static int tty_reopen(struct tty_struct *tty)
}
/**
- * tty_init_dev - initialise a tty device
- * @driver: tty driver we are opening a device on
- * @idx: device index
+ * tty_init_dev - initialise a tty device
+ * @driver: tty driver we are opening a device on
+ * @idx: device index
*
- * Prepare a tty device. This may not be a "new" clean device but
- * could also be an active device. The pty drivers require special
- * handling because of this.
+ * Prepare a tty device. This may not be a "new" clean device but could also be
+ * an active device. The pty drivers require special handling because of this.
*
- * Locking:
- * The function is called under the tty_mutex, which
- * protects us from the tty struct or driver itself going away.
+ * Locking:
+ * The function is called under the tty_mutex, which protects us from the
+ * tty struct or driver itself going away.
*
- * On exit the tty device has the line discipline attached and
- * a reference count of 1. If a pair was created for pty/tty use
- * and the other was a pty master then it too has a reference count of 1.
+ * On exit the tty device has the line discipline attached and a reference
+ * count of 1. If a pair was created for pty/tty use and the other was a pty
+ * master then it too has a reference count of 1.
*
- * WSH 06/09/97: Rewritten to remove races and properly clean up after a
- * failed open. The new code protects the open with a mutex, so it's
- * really quite straightforward. The mutex locking can probably be
- * relaxed for the (most common) case of reopening a tty.
+ * WSH 06/09/97: Rewritten to remove races and properly clean up after a failed
+ * open. The new code protects the open with a mutex, so it's really quite
+ * straightforward. The mutex locking can probably be relaxed for the (most
+ * common) case of reopening a tty.
*
- * Return: returned tty structure
+ * Return: new tty structure
*/
-
struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
{
struct tty_struct *tty;
@@ -1503,10 +1493,10 @@ void tty_save_termios(struct tty_struct *tty)
EXPORT_SYMBOL_GPL(tty_save_termios);
/**
- * tty_flush_works - flush all works of a tty/pty pair
- * @tty: tty device to flush works for (or either end of a pty pair)
+ * tty_flush_works - flush all works of a tty/pty pair
+ * @tty: tty device to flush works for (or either end of a pty pair)
*
- * Sync flush all works belonging to @tty (and the 'other' tty).
+ * Sync flush all works belonging to @tty (and the 'other' tty).
*/
static void tty_flush_works(struct tty_struct *tty)
{
@@ -1519,19 +1509,19 @@ static void tty_flush_works(struct tty_struct *tty)
}
/**
- * release_one_tty - release tty structure memory
- * @work: work of tty we are obliterating
+ * release_one_tty - release tty structure memory
+ * @work: work of tty we are obliterating
*
- * Releases memory associated with a tty structure, and clears out the
- * driver table slots. This function is called when a device is no longer
- * in use. It also gets called when setup of a device fails.
+ * Releases memory associated with a tty structure, and clears out the
+ * driver table slots. This function is called when a device is no longer
+ * in use. It also gets called when setup of a device fails.
*
- * Locking:
- * takes the file list lock internally when working on the list
- * of ttys that the driver keeps.
+ * Locking:
+ * takes the file list lock internally when working on the list of ttys
+ * that the driver keeps.
*
- * This method gets called from a work queue so that the driver private
- * cleanup ops can sleep (needed for USB at least)
+ * This method gets called from a work queue so that the driver private
+ * cleanup ops can sleep (needed for USB at least)
*/
static void release_one_tty(struct work_struct *work)
{
@@ -1568,13 +1558,12 @@ static void queue_release_one_tty(struct kref *kref)
}
/**
- * tty_kref_put - release a tty kref
- * @tty: tty device
+ * tty_kref_put - release a tty kref
+ * @tty: tty device
*
- * Release a reference to a tty device and if need be let the kref
- * layer destruct the object for us
+ * Release a reference to the @tty device and if need be let the kref layer
+ * destruct the object for us.
*/
-
void tty_kref_put(struct tty_struct *tty)
{
if (tty)
@@ -1583,18 +1572,17 @@ void tty_kref_put(struct tty_struct *tty)
EXPORT_SYMBOL(tty_kref_put);
/**
- * release_tty - release tty structure memory
- * @tty: tty device release
- * @idx: index of the tty device release
+ * release_tty - release tty structure memory
+ * @tty: tty device release
+ * @idx: index of the tty device release
*
- * Release both @tty and a possible linked partner (think pty pair),
- * and decrement the refcount of the backing module.
- *
- * Locking:
- * tty_mutex
- * takes the file list lock internally when working on the list
- * of ttys that the driver keeps.
+ * Release both @tty and a possible linked partner (think pty pair),
+ * and decrement the refcount of the backing module.
*
+ * Locking:
+ * tty_mutex
+ * takes the file list lock internally when working on the list of ttys
+ * that the driver keeps.
*/
static void release_tty(struct tty_struct *tty, int idx)
{
@@ -1619,12 +1607,12 @@ static void release_tty(struct tty_struct *tty, int idx)
}
/**
- * tty_release_checks - check a tty before real release
- * @tty: tty to check
- * @idx: index of the tty
+ * tty_release_checks - check a tty before real release
+ * @tty: tty to check
+ * @idx: index of the tty
*
- * Performs some paranoid checking before true release of the @tty.
- * This is a no-op unless TTY_PARANOIA_CHECK is defined.
+ * Performs some paranoid checking before true release of the @tty. This is a
+ * no-op unless %TTY_PARANOIA_CHECK is defined.
*/
static int tty_release_checks(struct tty_struct *tty, int idx)
{
@@ -1661,12 +1649,12 @@ static int tty_release_checks(struct tty_struct *tty, int idx)
}
/**
- * tty_kclose - closes tty opened by tty_kopen
- * @tty: tty device
+ * tty_kclose - closes tty opened by tty_kopen
+ * @tty: tty device
*
- * Performs the final steps to release and free a tty device. It is the
- * same as tty_release_struct except that it also resets TTY_PORT_KOPENED
- * flag on tty->port.
+ * Performs the final steps to release and free a tty device. It is the same as
+ * tty_release_struct() except that it also resets %TTY_PORT_KOPENED flag on
+ * @tty->port.
*/
void tty_kclose(struct tty_struct *tty)
{
@@ -1691,12 +1679,12 @@ void tty_kclose(struct tty_struct *tty)
EXPORT_SYMBOL_GPL(tty_kclose);
/**
- * tty_release_struct - release a tty struct
- * @tty: tty device
- * @idx: index of the tty
+ * tty_release_struct - release a tty struct
+ * @tty: tty device
+ * @idx: index of the tty
*
- * Performs the final steps to release and free a tty device. It is
- * roughly the reverse of tty_init_dev.
+ * Performs the final steps to release and free a tty device. It is roughly the
+ * reverse of tty_init_dev().
*/
void tty_release_struct(struct tty_struct *tty, int idx)
{
@@ -1720,24 +1708,23 @@ void tty_release_struct(struct tty_struct *tty, int idx)
EXPORT_SYMBOL_GPL(tty_release_struct);
/**
- * tty_release - vfs callback for close
- * @inode: inode of tty
- * @filp: file pointer for handle to tty
+ * tty_release - vfs callback for close
+ * @inode: inode of tty
+ * @filp: file pointer for handle to tty
*
- * Called the last time each file handle is closed that references
- * this tty. There may however be several such references.
+ * Called the last time each file handle is closed that references this tty.
+ * There may however be several such references.
*
- * Locking:
- * Takes bkl. See tty_release_dev
+ * Locking:
+ * Takes BKL. See tty_release_dev().
*
- * Even releasing the tty structures is a tricky business.. We have
- * to be very careful that the structures are all released at the
- * same time, as interrupts might otherwise get the wrong pointers.
+ * Even releasing the tty structures is a tricky business. We have to be very
+ * careful that the structures are all released at the same time, as interrupts
+ * might otherwise get the wrong pointers.
*
* WSH 09/09/97: rewritten to avoid some nasty race conditions that could
* lead to double frees or releasing memory still in use.
*/
-
int tty_release(struct inode *inode, struct file *filp)
{
struct tty_struct *tty = file_tty(filp);
@@ -1880,15 +1867,15 @@ int tty_release(struct inode *inode, struct file *filp)
}
/**
- * tty_open_current_tty - get locked tty of current task
- * @device: device number
- * @filp: file pointer to tty
- * @return: locked tty of the current task iff @device is /dev/tty
+ * tty_open_current_tty - get locked tty of current task
+ * @device: device number
+ * @filp: file pointer to tty
+ * @return: locked tty of the current task iff @device is /dev/tty
*
- * Performs a re-open of the current task's controlling tty.
+ * Performs a re-open of the current task's controlling tty.
*
- * We cannot return driver and index like for the other nodes because
- * devpts will not work then. It expects inodes to be from devpts FS.
+ * We cannot return driver and index like for the other nodes because devpts
+ * will not work then. It expects inodes to be from devpts FS.
*/
static struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp)
{
@@ -1916,16 +1903,17 @@ static struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp)
}
/**
- * tty_lookup_driver - lookup a tty driver for a given device file
- * @device: device number
- * @filp: file pointer to tty
- * @index: index for the device in the @return driver
- * @return: driver for this inode (with increased refcount)
+ * tty_lookup_driver - lookup a tty driver for a given device file
+ * @device: device number
+ * @filp: file pointer to tty
+ * @index: index for the device in the @return driver
+ *
+ * If returned value is not erroneous, the caller is responsible to decrement
+ * the refcount by tty_driver_kref_put().
*
- * If @return is not erroneous, the caller is responsible to decrement the
- * refcount by tty_driver_kref_put.
+ * Locking: %tty_mutex protects get_tty_driver()
*
- * Locking: tty_mutex protects get_tty_driver
+ * Return: driver for this inode (with increased refcount)
*/
static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp,
int *index)
@@ -2001,19 +1989,18 @@ out:
}
/**
- * tty_kopen_exclusive - open a tty device for kernel
- * @device: dev_t of device to open
+ * tty_kopen_exclusive - open a tty device for kernel
+ * @device: dev_t of device to open
*
- * Opens tty exclusively for kernel. Performs the driver lookup,
- * makes sure it's not already opened and performs the first-time
- * tty initialization.
+ * Opens tty exclusively for kernel. Performs the driver lookup, makes sure
+ * it's not already opened and performs the first-time tty initialization.
*
- * Returns the locked initialized &tty_struct
+ * Claims the global %tty_mutex to serialize:
+ * * concurrent first-time tty initialization
+ * * concurrent tty driver removal w/ lookup
+ * * concurrent tty removal from driver table
*
- * Claims the global tty_mutex to serialize:
- * - concurrent first-time tty initialization
- * - concurrent tty driver removal w/ lookup
- * - concurrent tty removal from driver table
+ * Return: the locked initialized &tty_struct
*/
struct tty_struct *tty_kopen_exclusive(dev_t device)
{
@@ -2022,13 +2009,13 @@ struct tty_struct *tty_kopen_exclusive(dev_t device)
EXPORT_SYMBOL_GPL(tty_kopen_exclusive);
/**
- * tty_kopen_shared - open a tty device for shared in-kernel use
- * @device: dev_t of device to open
+ * tty_kopen_shared - open a tty device for shared in-kernel use
+ * @device: dev_t of device to open
*
- * Opens an already existing tty for in-kernel use. Compared to
- * tty_kopen_exclusive() above it doesn't ensure to be the only user.
+ * Opens an already existing tty for in-kernel use. Compared to
+ * tty_kopen_exclusive() above it doesn't ensure to be the only user.
*
- * Locking is identical to tty_kopen() above.
+ * Locking: identical to tty_kopen() above.
*/
struct tty_struct *tty_kopen_shared(dev_t device)
{
@@ -2037,19 +2024,20 @@ struct tty_struct *tty_kopen_shared(dev_t device)
EXPORT_SYMBOL_GPL(tty_kopen_shared);
/**
- * tty_open_by_driver - open a tty device
- * @device: dev_t of device to open
- * @filp: file pointer to tty
+ * tty_open_by_driver - open a tty device
+ * @device: dev_t of device to open
+ * @filp: file pointer to tty
*
- * Performs the driver lookup, checks for a reopen, or otherwise
- * performs the first-time tty initialization.
+ * Performs the driver lookup, checks for a reopen, or otherwise performs the
+ * first-time tty initialization.
*
- * Returns the locked initialized or re-opened &tty_struct
*
- * Claims the global tty_mutex to serialize:
- * - concurrent first-time tty initialization
- * - concurrent tty driver removal w/ lookup
- * - concurrent tty removal from driver table
+ * Claims the global tty_mutex to serialize:
+ * * concurrent first-time tty initialization
+ * * concurrent tty driver removal w/ lookup
+ * * concurrent tty removal from driver table
+ *
+ * Return: the locked initialized or re-opened &tty_struct
*/
static struct tty_struct *tty_open_by_driver(dev_t device,
struct file *filp)
@@ -2104,29 +2092,28 @@ out:
}
/**
- * tty_open - open a tty device
- * @inode: inode of device file
- * @filp: file pointer to tty
+ * tty_open - open a tty device
+ * @inode: inode of device file
+ * @filp: file pointer to tty
*
- * tty_open and tty_release keep up the tty count that contains the
- * number of opens done on a tty. We cannot use the inode-count, as
- * different inodes might point to the same tty.
+ * tty_open() and tty_release() keep up the tty count that contains the number
+ * of opens done on a tty. We cannot use the inode-count, as different inodes
+ * might point to the same tty.
*
- * Open-counting is needed for pty masters, as well as for keeping
- * track of serial lines: DTR is dropped when the last close happens.
- * (This is not done solely through tty->count, now. - Ted 1/27/92)
+ * Open-counting is needed for pty masters, as well as for keeping track of
+ * serial lines: DTR is dropped when the last close happens.
+ * (This is not done solely through tty->count, now. - Ted 1/27/92)
*
- * The termios state of a pty is reset on first open so that
- * settings don't persist across reuse.
+ * The termios state of a pty is reset on the first open so that settings don't
+ * persist across reuse.
*
- * Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev.
- * tty->count should protect the rest.
- * ->siglock protects ->signal/->sighand
+ * Locking:
+ * * %tty_mutex protects tty, tty_lookup_driver() and tty_init_dev().
+ * * @tty->count should protect the rest.
+ * * ->siglock protects ->signal/->sighand
*
- * Note: the tty_unlock/lock cases without a ref are only safe due to
- * tty_mutex
+ * Note: the tty_unlock/lock cases without a ref are only safe due to %tty_mutex
*/
-
static int tty_open(struct inode *inode, struct file *filp)
{
struct tty_struct *tty;
@@ -2198,19 +2185,17 @@ retry_open:
}
-
/**
- * tty_poll - check tty status
- * @filp: file being polled
- * @wait: poll wait structures to update
+ * tty_poll - check tty status
+ * @filp: file being polled
+ * @wait: poll wait structures to update
*
- * Call the line discipline polling method to obtain the poll
- * status of the device.
+ * Call the line discipline polling method to obtain the poll status of the
+ * device.
*
- * Locking: locks called line discipline but ldisc poll method
- * may be re-entered freely by other callers.
+ * Locking: locks called line discipline but ldisc poll method may be
+ * re-entered freely by other callers.
*/
-
static __poll_t tty_poll(struct file *filp, poll_table *wait)
{
struct tty_struct *tty = file_tty(filp);
@@ -2278,20 +2263,18 @@ static int tty_fasync(int fd, struct file *filp, int on)
}
/**
- * tiocsti - fake input character
- * @tty: tty to fake input into
- * @p: pointer to character
+ * tiocsti - fake input character
+ * @tty: tty to fake input into
+ * @p: pointer to character
*
- * Fake input to a tty device. Does the necessary locking and
- * input management.
+ * Fake input to a tty device. Does the necessary locking and input management.
*
- * FIXME: does not honour flow control ??
+ * FIXME: does not honour flow control ??
*
- * Locking:
- * Called functions take tty_ldiscs_lock
- * current->signal->tty check is safe without locks
+ * Locking:
+ * * Called functions take tty_ldiscs_lock
+ * * current->signal->tty check is safe without locks
*/
-
static int tiocsti(struct tty_struct *tty, char __user *p)
{
char ch, mbz = 0;
@@ -2314,16 +2297,15 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
}
/**
- * tiocgwinsz - implement window query ioctl
- * @tty: tty
- * @arg: user buffer for result
+ * tiocgwinsz - implement window query ioctl
+ * @tty: tty
+ * @arg: user buffer for result
*
- * Copies the kernel idea of the window size into the user buffer.
+ * Copies the kernel idea of the window size into the user buffer.
*
- * Locking: tty->winsize_mutex is taken to ensure the winsize data
- * is consistent.
+ * Locking: @tty->winsize_mutex is taken to ensure the winsize data is
+ * consistent.
*/
-
static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg)
{
int err;
@@ -2336,14 +2318,13 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg)
}
/**
- * tty_do_resize - resize event
- * @tty: tty being resized
- * @ws: new dimensions
+ * tty_do_resize - resize event
+ * @tty: tty being resized
+ * @ws: new dimensions
*
- * Update the termios variables and send the necessary signals to
- * peform a terminal resize correctly
+ * Update the termios variables and send the necessary signals to peform a
+ * terminal resize correctly.
*/
-
int tty_do_resize(struct tty_struct *tty, struct winsize *ws)
{
struct pid *pgrp;
@@ -2367,20 +2348,19 @@ done:
EXPORT_SYMBOL(tty_do_resize);
/**
- * tiocswinsz - implement window size set ioctl
- * @tty: tty side of tty
- * @arg: user buffer for result
+ * tiocswinsz - implement window size set ioctl
+ * @tty: tty side of tty
+ * @arg: user buffer for result
*
- * Copies the user idea of the window size to the kernel. Traditionally
- * this is just advisory information but for the Linux console it
- * actually has driver level meaning and triggers a VC resize.
+ * Copies the user idea of the window size to the kernel. Traditionally this is
+ * just advisory information but for the Linux console it actually has driver
+ * level meaning and triggers a VC resize.
*
- * Locking:
- * Driver dependent. The default do_resize method takes the
- * tty termios mutex and ctrl.lock. The console takes its own lock
- * then calls into the default method.
+ * Locking:
+ * Driver dependent. The default do_resize method takes the tty termios
+ * mutex and ctrl.lock. The console takes its own lock then calls into the
+ * default method.
*/
-
static int tiocswinsz(struct tty_struct *tty, struct winsize __user *arg)
{
struct winsize tmp_ws;
@@ -2395,14 +2375,13 @@ static int tiocswinsz(struct tty_struct *tty, struct winsize __user *arg)
}
/**
- * tioccons - allow admin to move logical console
- * @file: the file to become console
+ * tioccons - allow admin to move logical console
+ * @file: the file to become console
*
- * Allow the administrator to move the redirected console device
+ * Allow the administrator to move the redirected console device.
*
- * Locking: uses redirect_lock to guard the redirect information
+ * Locking: uses redirect_lock to guard the redirect information
*/
-
static int tioccons(struct file *file)
{
if (!capable(CAP_SYS_ADMIN))
@@ -2435,15 +2414,14 @@ static int tioccons(struct file *file)
}
/**
- * tiocsetd - set line discipline
- * @tty: tty device
- * @p: pointer to user data
+ * tiocsetd - set line discipline
+ * @tty: tty device
+ * @p: pointer to user data
*
- * Set the line discipline according to user request.
+ * Set the line discipline according to user request.
*
- * Locking: see tty_set_ldisc, this function is just a helper
+ * Locking: see tty_set_ldisc(), this function is just a helper
*/
-
static int tiocsetd(struct tty_struct *tty, int __user *p)
{
int disc;
@@ -2458,16 +2436,15 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
}
/**
- * tiocgetd - get line discipline
- * @tty: tty device
- * @p: pointer to user data
+ * tiocgetd - get line discipline
+ * @tty: tty device
+ * @p: pointer to user data
*
- * Retrieves the line discipline id directly from the ldisc.
+ * Retrieves the line discipline id directly from the ldisc.
*
- * Locking: waits for ldisc reference (in case the line discipline
- * is changing or the tty is being hungup)
+ * Locking: waits for ldisc reference (in case the line discipline is changing
+ * or the @tty is being hungup)
*/
-
static int tiocgetd(struct tty_struct *tty, int __user *p)
{
struct tty_ldisc *ld;
@@ -2482,18 +2459,16 @@ static int tiocgetd(struct tty_struct *tty, int __user *p)
}
/**
- * send_break - performed time break
- * @tty: device to break on
- * @duration: timeout in mS
- *
- * Perform a timed break on hardware that lacks its own driver level
- * timed break functionality.
+ * send_break - performed time break
+ * @tty: device to break on
+ * @duration: timeout in mS
*
- * Locking:
- * atomic_write_lock serializes
+ * Perform a timed break on hardware that lacks its own driver level timed
+ * break functionality.
*
+ * Locking:
+ * @tty->atomic_write_lock serializes
*/
-
static int send_break(struct tty_struct *tty, unsigned int duration)
{
int retval;
@@ -2522,16 +2497,15 @@ out:
}
/**
- * tty_tiocmget - get modem status
- * @tty: tty device
- * @p: pointer to result
+ * tty_tiocmget - get modem status
+ * @tty: tty device
+ * @p: pointer to result
*
- * Obtain the modem status bits from the tty driver if the feature
- * is supported. Return -ENOTTY if it is not available.
+ * Obtain the modem status bits from the tty driver if the feature is
+ * supported. Return -%ENOTTY if it is not available.
*
- * Locking: none (up to the driver)
+ * Locking: none (up to the driver)
*/
-
static int tty_tiocmget(struct tty_struct *tty, int __user *p)
{
int retval = -ENOTTY;
@@ -2546,17 +2520,16 @@ static int tty_tiocmget(struct tty_struct *tty, int __user *p)
}
/**
- * tty_tiocmset - set modem status
- * @tty: tty device
- * @cmd: command - clear bits, set bits or set all
- * @p: pointer to desired bits
+ * tty_tiocmset - set modem status
+ * @tty: tty device
+ * @cmd: command - clear bits, set bits or set all
+ * @p: pointer to desired bits
*
- * Set the modem status bits from the tty driver if the feature
- * is supported. Return -ENOTTY if it is not available.
+ * Set the modem status bits from the tty driver if the feature
+ * is supported. Return -%ENOTTY if it is not available.
*
- * Locking: none (up to the driver)
+ * Locking: none (up to the driver)
*/
-
static int tty_tiocmset(struct tty_struct *tty, unsigned int cmd,
unsigned __user *p)
{
@@ -2588,13 +2561,13 @@ static int tty_tiocmset(struct tty_struct *tty, unsigned int cmd,
}
/**
- * tty_get_icount - get tty statistics
- * @tty: tty device
- * @icount: output parameter
+ * tty_get_icount - get tty statistics
+ * @tty: tty device
+ * @icount: output parameter
*
- * Gets a copy of the tty's icount statistics.
+ * Gets a copy of the @tty's icount statistics.
*
- * Locking: none (up to the driver)
+ * Locking: none (up to the driver)
*/
int tty_get_icount(struct tty_struct *tty,
struct serial_icounter_struct *icount)
@@ -2811,7 +2784,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return hung_up_tty_ioctl(file, cmd, arg);
retval = -EINVAL;
if (ld->ops->ioctl) {
- retval = ld->ops->ioctl(tty, file, cmd, arg);
+ retval = ld->ops->ioctl(tty, cmd, arg);
if (retval == -ENOIOCTLCMD)
retval = -ENOTTY;
}
@@ -2990,10 +2963,10 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
if (!ld)
return hung_up_tty_compat_ioctl(file, cmd, arg);
if (ld->ops->compat_ioctl)
- retval = ld->ops->compat_ioctl(tty, file, cmd, arg);
+ retval = ld->ops->compat_ioctl(tty, cmd, arg);
if (retval == -ENOIOCTLCMD && ld->ops->ioctl)
- retval = ld->ops->ioctl(tty, file,
- (unsigned long)compat_ptr(cmd), arg);
+ retval = ld->ops->ioctl(tty, (unsigned long)compat_ptr(cmd),
+ arg);
tty_ldisc_deref(ld);
return retval;
@@ -3028,17 +3001,11 @@ static int this_tty(const void *t, struct file *file, unsigned fd)
*/
void __do_SAK(struct tty_struct *tty)
{
-#ifdef TTY_SOFT_SAK
- tty_hangup(tty);
-#else
struct task_struct *g, *p;
struct pid *session;
- int i;
+ int i;
unsigned long flags;
- if (!tty)
- return;
-
spin_lock_irqsave(&tty->ctrl.lock, flags);
session = get_pid(tty->ctrl.session);
spin_unlock_irqrestore(&tty->ctrl.lock, flags);
@@ -3060,7 +3027,8 @@ void __do_SAK(struct tty_struct *tty)
if (p->signal->tty == tty) {
tty_notice(tty, "SAK: killed process %d (%s): by controlling tty\n",
task_pid_nr(p), p->comm);
- group_send_sig_info(SIGKILL, SEND_SIG_PRIV, p, PIDTYPE_SID);
+ group_send_sig_info(SIGKILL, SEND_SIG_PRIV, p,
+ PIDTYPE_SID);
continue;
}
task_lock(p);
@@ -3068,13 +3036,13 @@ void __do_SAK(struct tty_struct *tty)
if (i != 0) {
tty_notice(tty, "SAK: killed process %d (%s): by fd#%d\n",
task_pid_nr(p), p->comm, i - 1);
- group_send_sig_info(SIGKILL, SEND_SIG_PRIV, p, PIDTYPE_SID);
+ group_send_sig_info(SIGKILL, SEND_SIG_PRIV, p,
+ PIDTYPE_SID);
}
task_unlock(p);
} while_each_thread(g, p);
read_unlock(&tasklist_lock);
put_pid(session);
-#endif
}
static void do_SAK_work(struct work_struct *work)
@@ -3107,14 +3075,15 @@ static struct device *tty_get_device(struct tty_struct *tty)
}
-/*
- * alloc_tty_struct
+/**
+ * alloc_tty_struct - allocate a new tty
+ * @driver: driver which will handle the returned tty
+ * @idx: minor of the tty
*
- * This subroutine allocates and initializes a tty structure.
+ * This subroutine allocates and initializes a tty structure.
*
- * Locking: none - tty in question is not exposed at this point
+ * Locking: none - @tty in question is not exposed at this point
*/
-
struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx)
{
struct tty_struct *tty;
@@ -3156,17 +3125,18 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx)
}
/**
- * tty_put_char - write one character to a tty
- * @tty: tty
- * @ch: character
+ * tty_put_char - write one character to a tty
+ * @tty: tty
+ * @ch: character to write
+ *
+ * Write one byte to the @tty using the provided @tty->ops->put_char() method
+ * if present.
*
- * Write one byte to the tty using the provided put_char method
- * if present. Returns the number of characters successfully output.
+ * Note: the specific put_char operation in the driver layer may go
+ * away soon. Don't call it directly, use this method
*
- * Note: the specific put_char operation in the driver layer may go
- * away soon. Don't call it directly, use this method
+ * Return: the number of characters successfully output.
*/
-
int tty_put_char(struct tty_struct *tty, unsigned char ch)
{
if (tty->ops->put_char)
@@ -3195,24 +3165,23 @@ static int tty_cdev_add(struct tty_driver *driver, dev_t dev,
}
/**
- * tty_register_device - register a tty device
- * @driver: the tty driver that describes the tty device
- * @index: the index in the tty driver for this tty device
- * @device: a struct device that is associated with this tty device.
- * This field is optional, if there is no known struct device
- * for this tty device it can be set to NULL safely.
+ * tty_register_device - register a tty device
+ * @driver: the tty driver that describes the tty device
+ * @index: the index in the tty driver for this tty device
+ * @device: a struct device that is associated with this tty device.
+ * This field is optional, if there is no known struct device
+ * for this tty device it can be set to NULL safely.
*
- * Returns a pointer to the struct device for this tty device
- * (or ERR_PTR(-EFOO) on error).
+ * This call is required to be made to register an individual tty device
+ * if the tty driver's flags have the %TTY_DRIVER_DYNAMIC_DEV bit set. If
+ * that bit is not set, this function should not be called by a tty
+ * driver.
*
- * This call is required to be made to register an individual tty device
- * if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If
- * that bit is not set, this function should not be called by a tty
- * driver.
+ * Locking: ??
*
- * Locking: ??
+ * Return: A pointer to the struct device for this tty device (or
+ * ERR_PTR(-EFOO) on error).
*/
-
struct device *tty_register_device(struct tty_driver *driver, unsigned index,
struct device *device)
{
@@ -3227,24 +3196,23 @@ static void tty_device_create_release(struct device *dev)
}
/**
- * tty_register_device_attr - register a tty device
- * @driver: the tty driver that describes the tty device
- * @index: the index in the tty driver for this tty device
- * @device: a struct device that is associated with this tty device.
- * This field is optional, if there is no known struct device
- * for this tty device it can be set to NULL safely.
- * @drvdata: Driver data to be set to device.
- * @attr_grp: Attribute group to be set on device.
+ * tty_register_device_attr - register a tty device
+ * @driver: the tty driver that describes the tty device
+ * @index: the index in the tty driver for this tty device
+ * @device: a struct device that is associated with this tty device.
+ * This field is optional, if there is no known struct device
+ * for this tty device it can be set to %NULL safely.
+ * @drvdata: Driver data to be set to device.
+ * @attr_grp: Attribute group to be set on device.
*
- * Returns a pointer to the struct device for this tty device
- * (or ERR_PTR(-EFOO) on error).
+ * This call is required to be made to register an individual tty device if the
+ * tty driver's flags have the %TTY_DRIVER_DYNAMIC_DEV bit set. If that bit is
+ * not set, this function should not be called by a tty driver.
*
- * This call is required to be made to register an individual tty device
- * if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If
- * that bit is not set, this function should not be called by a tty
- * driver.
+ * Locking: ??
*
- * Locking: ??
+ * Return: A pointer to the struct device for this tty device (or
+ * ERR_PTR(-EFOO) on error).
*/
struct device *tty_register_device_attr(struct tty_driver *driver,
unsigned index, struct device *device,
@@ -3317,16 +3285,15 @@ err_put:
EXPORT_SYMBOL_GPL(tty_register_device_attr);
/**
- * tty_unregister_device - unregister a tty device
- * @driver: the tty driver that describes the tty device
- * @index: the index in the tty driver for this tty device
+ * tty_unregister_device - unregister a tty device
+ * @driver: the tty driver that describes the tty device
+ * @index: the index in the tty driver for this tty device
*
- * If a tty device is registered with a call to tty_register_device() then
- * this function must be called when the tty device is gone.
+ * If a tty device is registered with a call to tty_register_device() then
+ * this function must be called when the tty device is gone.
*
- * Locking: ??
+ * Locking: ??
*/
-
void tty_unregister_device(struct tty_driver *driver, unsigned index)
{
device_destroy(tty_class,
@@ -3342,10 +3309,10 @@ EXPORT_SYMBOL(tty_unregister_device);
* __tty_alloc_driver -- allocate tty driver
* @lines: count of lines this driver can handle at most
* @owner: module which is responsible for this driver
- * @flags: some of TTY_DRIVER_* flags, will be set in driver->flags
+ * @flags: some of %TTY_DRIVER_ flags, will be set in driver->flags
*
* This should not be called directly, some of the provided macros should be
- * used instead. Use IS_ERR and friends on @retval.
+ * used instead. Use IS_ERR() and friends on @retval.
*/
struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner,
unsigned long flags)
@@ -3432,13 +3399,22 @@ static void destruct_tty_driver(struct kref *kref)
kfree(driver);
}
+/**
+ * tty_driver_kref_put -- drop a reference to a tty driver
+ * @driver: driver of which to drop the reference
+ *
+ * The final put will destroy and free up the driver.
+ */
void tty_driver_kref_put(struct tty_driver *driver)
{
kref_put(&driver->kref, destruct_tty_driver);
}
EXPORT_SYMBOL(tty_driver_kref_put);
-/*
+/**
+ * tty_register_driver -- register a tty driver
+ * @driver: driver to register
+ *
* Called by a tty driver to register itself.
*/
int tty_register_driver(struct tty_driver *driver)
@@ -3500,7 +3476,10 @@ err:
}
EXPORT_SYMBOL(tty_register_driver);
-/*
+/**
+ * tty_unregister_driver -- unregister a tty driver
+ * @driver: driver to unregister
+ *
* Called by a tty driver to unregister itself.
*/
void tty_unregister_driver(struct tty_driver *driver)
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 3e4e0b20b4bb..776d8a62f77c 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -47,17 +47,14 @@ static DEFINE_RAW_SPINLOCK(tty_ldiscs_lock);
static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
/**
- * tty_register_ldisc - install a line discipline
- * @new_ldisc: pointer to the ldisc object
+ * tty_register_ldisc - install a line discipline
+ * @new_ldisc: pointer to the ldisc object
*
- * Installs a new line discipline into the kernel. The discipline
- * is set up as unreferenced and then made available to the kernel
- * from this point onwards.
+ * Installs a new line discipline into the kernel. The discipline is set up as
+ * unreferenced and then made available to the kernel from this point onwards.
*
- * Locking:
- * takes tty_ldiscs_lock to guard against ldisc races
+ * Locking: takes %tty_ldiscs_lock to guard against ldisc races
*/
-
int tty_register_ldisc(struct tty_ldisc_ops *new_ldisc)
{
unsigned long flags;
@@ -75,14 +72,13 @@ int tty_register_ldisc(struct tty_ldisc_ops *new_ldisc)
EXPORT_SYMBOL(tty_register_ldisc);
/**
- * tty_unregister_ldisc - unload a line discipline
- * @ldisc: ldisc number
+ * tty_unregister_ldisc - unload a line discipline
+ * @ldisc: ldisc number
*
- * Remove a line discipline from the kernel providing it is not
- * currently in use.
+ * Remove a line discipline from the kernel providing it is not currently in
+ * use.
*
- * Locking:
- * takes tty_ldiscs_lock to guard against ldisc races
+ * Locking: takes %tty_ldiscs_lock to guard against ldisc races
*/
void tty_unregister_ldisc(struct tty_ldisc_ops *ldisc)
@@ -122,27 +118,25 @@ static void put_ldops(struct tty_ldisc_ops *ldops)
}
static int tty_ldisc_autoload = IS_BUILTIN(CONFIG_LDISC_AUTOLOAD);
+
/**
- * tty_ldisc_get - take a reference to an ldisc
- * @tty: tty device
- * @disc: ldisc number
- *
- * Takes a reference to a line discipline. Deals with refcounts and
- * module locking counts.
- *
- * Returns: -EINVAL if the discipline index is not [N_TTY..NR_LDISCS] or
- * if the discipline is not registered
- * -EAGAIN if request_module() failed to load or register the
- * discipline
- * -ENOMEM if allocation failure
- *
- * Otherwise, returns a pointer to the discipline and bumps the
- * ref count
- *
- * Locking:
- * takes tty_ldiscs_lock to guard against ldisc races
+ * tty_ldisc_get - take a reference to an ldisc
+ * @tty: tty device
+ * @disc: ldisc number
+ *
+ * Takes a reference to a line discipline. Deals with refcounts and module
+ * locking counts. If the discipline is not available, its module loaded, if
+ * possible.
+ *
+ * Returns:
+ * * -%EINVAL if the discipline index is not [%N_TTY .. %NR_LDISCS] or if the
+ * discipline is not registered
+ * * -%EAGAIN if request_module() failed to load or register the discipline
+ * * -%ENOMEM if allocation failure
+ * * Otherwise, returns a pointer to the discipline and bumps the ref count
+ *
+ * Locking: takes %tty_ldiscs_lock to guard against ldisc races
*/
-
static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
{
struct tty_ldisc *ld;
@@ -176,10 +170,11 @@ static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
return ld;
}
-/*
- * tty_ldisc_put - release the ldisc
+/**
+ * tty_ldisc_put - release the ldisc
+ * @ld: lisdsc to release
*
- * Complement of tty_ldisc_get().
+ * Complement of tty_ldisc_get().
*/
static void tty_ldisc_put(struct tty_ldisc *ld)
{
@@ -226,25 +221,22 @@ const struct seq_operations tty_ldiscs_seq_ops = {
};
/**
- * tty_ldisc_ref_wait - wait for the tty ldisc
- * @tty: tty device
+ * tty_ldisc_ref_wait - wait for the tty ldisc
+ * @tty: tty device
*
- * Dereference the line discipline for the terminal and take a
- * reference to it. If the line discipline is in flux then
- * wait patiently until it changes.
+ * Dereference the line discipline for the terminal and take a reference to it.
+ * If the line discipline is in flux then wait patiently until it changes.
*
- * Returns: NULL if the tty has been hungup and not re-opened with
- * a new file descriptor, otherwise valid ldisc reference
+ * Returns: %NULL if the tty has been hungup and not re-opened with a new file
+ * descriptor, otherwise valid ldisc reference
*
- * Note 1: Must not be called from an IRQ/timer context. The caller
- * must also be careful not to hold other locks that will deadlock
- * against a discipline change, such as an existing ldisc reference
- * (which we check for)
+ * Note 1: Must not be called from an IRQ/timer context. The caller must also
+ * be careful not to hold other locks that will deadlock against a discipline
+ * change, such as an existing ldisc reference (which we check for).
*
- * Note 2: a file_operations routine (read/poll/write) should use this
- * function to wait for any ldisc lifetime events to finish.
+ * Note 2: a file_operations routine (read/poll/write) should use this function
+ * to wait for any ldisc lifetime events to finish.
*/
-
struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
{
struct tty_ldisc *ld;
@@ -258,14 +250,13 @@ struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
/**
- * tty_ldisc_ref - get the tty ldisc
- * @tty: tty device
+ * tty_ldisc_ref - get the tty ldisc
+ * @tty: tty device
*
- * Dereference the line discipline for the terminal and take a
- * reference to it. If the line discipline is in flux then
- * return NULL. Can be called from IRQ and timer functions.
+ * Dereference the line discipline for the terminal and take a reference to it.
+ * If the line discipline is in flux then return %NULL. Can be called from IRQ
+ * and timer functions.
*/
-
struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
{
struct tty_ldisc *ld = NULL;
@@ -280,13 +271,12 @@ struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
EXPORT_SYMBOL_GPL(tty_ldisc_ref);
/**
- * tty_ldisc_deref - free a tty ldisc reference
- * @ld: reference to free up
+ * tty_ldisc_deref - free a tty ldisc reference
+ * @ld: reference to free up
*
- * Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
- * be called in IRQ context.
+ * Undoes the effect of tty_ldisc_ref() or tty_ldisc_ref_wait(). May be called
+ * in IRQ context.
*/
-
void tty_ldisc_deref(struct tty_ldisc *ld)
{
ldsem_up_read(&ld->tty->ldisc_sem);
@@ -386,13 +376,12 @@ static void tty_ldisc_unlock_pair(struct tty_struct *tty,
}
/**
- * tty_ldisc_flush - flush line discipline queue
- * @tty: tty
+ * tty_ldisc_flush - flush line discipline queue
+ * @tty: tty to flush ldisc for
*
- * Flush the line discipline queue (if any) and the tty flip buffers
- * for this tty.
+ * Flush the line discipline queue (if any) and the tty flip buffers for this
+ * @tty.
*/
-
void tty_ldisc_flush(struct tty_struct *tty)
{
struct tty_ldisc *ld = tty_ldisc_ref(tty);
@@ -404,21 +393,18 @@ void tty_ldisc_flush(struct tty_struct *tty)
EXPORT_SYMBOL_GPL(tty_ldisc_flush);
/**
- * tty_set_termios_ldisc - set ldisc field
- * @tty: tty structure
- * @disc: line discipline number
+ * tty_set_termios_ldisc - set ldisc field
+ * @tty: tty structure
+ * @disc: line discipline number
*
- * This is probably overkill for real world processors but
- * they are not on hot paths so a little discipline won't do
- * any harm.
+ * This is probably overkill for real world processors but they are not on hot
+ * paths so a little discipline won't do any harm.
*
- * The line discipline-related tty_struct fields are reset to
- * prevent the ldisc driver from re-using stale information for
- * the new ldisc instance.
+ * The line discipline-related tty_struct fields are reset to prevent the ldisc
+ * driver from re-using stale information for the new ldisc instance.
*
- * Locking: takes termios_rwsem
+ * Locking: takes termios_rwsem
*/
-
static void tty_set_termios_ldisc(struct tty_struct *tty, int disc)
{
down_write(&tty->termios_rwsem);
@@ -430,16 +416,14 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int disc)
}
/**
- * tty_ldisc_open - open a line discipline
- * @tty: tty we are opening the ldisc on
- * @ld: discipline to open
+ * tty_ldisc_open - open a line discipline
+ * @tty: tty we are opening the ldisc on
+ * @ld: discipline to open
*
- * A helper opening method. Also a convenient debugging and check
- * point.
+ * A helper opening method. Also a convenient debugging and check point.
*
- * Locking: always called with BTM already held.
+ * Locking: always called with BTM already held.
*/
-
static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
{
WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags));
@@ -457,14 +441,12 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
}
/**
- * tty_ldisc_close - close a line discipline
- * @tty: tty we are opening the ldisc on
- * @ld: discipline to close
+ * tty_ldisc_close - close a line discipline
+ * @tty: tty we are opening the ldisc on
+ * @ld: discipline to close
*
- * A helper close method. Also a convenient debugging and check
- * point.
+ * A helper close method. Also a convenient debugging and check point.
*/
-
static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
{
lockdep_assert_held_write(&tty->ldisc_sem);
@@ -476,14 +458,13 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
}
/**
- * tty_ldisc_failto - helper for ldisc failback
- * @tty: tty to open the ldisc on
- * @ld: ldisc we are trying to fail back to
+ * tty_ldisc_failto - helper for ldisc failback
+ * @tty: tty to open the ldisc on
+ * @ld: ldisc we are trying to fail back to
*
- * Helper to try and recover a tty when switching back to the old
- * ldisc fails and we need something attached.
+ * Helper to try and recover a tty when switching back to the old ldisc fails
+ * and we need something attached.
*/
-
static int tty_ldisc_failto(struct tty_struct *tty, int ld)
{
struct tty_ldisc *disc = tty_ldisc_get(tty, ld);
@@ -501,14 +482,13 @@ static int tty_ldisc_failto(struct tty_struct *tty, int ld)
}
/**
- * tty_ldisc_restore - helper for tty ldisc change
- * @tty: tty to recover
- * @old: previous ldisc
+ * tty_ldisc_restore - helper for tty ldisc change
+ * @tty: tty to recover
+ * @old: previous ldisc
*
- * Restore the previous line discipline or N_TTY when a line discipline
- * change fails due to an open error
+ * Restore the previous line discipline or %N_TTY when a line discipline change
+ * fails due to an open error
*/
-
static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
{
/* There is an outstanding reference here so this is safe */
@@ -528,16 +508,15 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
}
/**
- * tty_set_ldisc - set line discipline
- * @tty: the terminal to set
- * @disc: the line discipline number
- *
- * Set the discipline of a tty line. Must be called from a process
- * context. The ldisc change logic has to protect itself against any
- * overlapping ldisc change (including on the other end of pty pairs),
- * the close of one side of a tty/pty pair, and eventually hangup.
+ * tty_set_ldisc - set line discipline
+ * @tty: the terminal to set
+ * @disc: the line discipline number
+ *
+ * Set the discipline of a tty line. Must be called from a process context. The
+ * ldisc change logic has to protect itself against any overlapping ldisc
+ * change (including on the other end of pty pairs), the close of one side of a
+ * tty/pty pair, and eventually hangup.
*/
-
int tty_set_ldisc(struct tty_struct *tty, int disc)
{
int retval;
@@ -613,10 +592,10 @@ err:
EXPORT_SYMBOL_GPL(tty_set_ldisc);
/**
- * tty_ldisc_kill - teardown ldisc
- * @tty: tty being released
+ * tty_ldisc_kill - teardown ldisc
+ * @tty: tty being released
*
- * Perform final close of the ldisc and reset tty->ldisc
+ * Perform final close of the ldisc and reset @tty->ldisc
*/
static void tty_ldisc_kill(struct tty_struct *tty)
{
@@ -633,12 +612,11 @@ static void tty_ldisc_kill(struct tty_struct *tty)
}
/**
- * tty_reset_termios - reset terminal state
- * @tty: tty to reset
+ * tty_reset_termios - reset terminal state
+ * @tty: tty to reset
*
- * Restore a terminal to the driver default state.
+ * Restore a terminal to the driver default state.
*/
-
static void tty_reset_termios(struct tty_struct *tty)
{
down_write(&tty->termios_rwsem);
@@ -650,19 +628,17 @@ static void tty_reset_termios(struct tty_struct *tty)
/**
- * tty_ldisc_reinit - reinitialise the tty ldisc
- * @tty: tty to reinit
- * @disc: line discipline to reinitialize
+ * tty_ldisc_reinit - reinitialise the tty ldisc
+ * @tty: tty to reinit
+ * @disc: line discipline to reinitialize
*
- * Completely reinitialize the line discipline state, by closing the
- * current instance, if there is one, and opening a new instance. If
- * an error occurs opening the new non-N_TTY instance, the instance
- * is dropped and tty->ldisc reset to NULL. The caller can then retry
- * with N_TTY instead.
+ * Completely reinitialize the line discipline state, by closing the current
+ * instance, if there is one, and opening a new instance. If an error occurs
+ * opening the new non-%N_TTY instance, the instance is dropped and @tty->ldisc
+ * reset to %NULL. The caller can then retry with %N_TTY instead.
*
- * Returns 0 if successful, otherwise error code < 0
+ * Returns: 0 if successful, otherwise error code < 0
*/
-
int tty_ldisc_reinit(struct tty_struct *tty, int disc)
{
struct tty_ldisc *ld;
@@ -692,21 +668,20 @@ int tty_ldisc_reinit(struct tty_struct *tty, int disc)
}
/**
- * tty_ldisc_hangup - hangup ldisc reset
- * @tty: tty being hung up
- * @reinit: whether to re-initialise the tty
+ * tty_ldisc_hangup - hangup ldisc reset
+ * @tty: tty being hung up
+ * @reinit: whether to re-initialise the tty
*
- * Some tty devices reset their termios when they receive a hangup
- * event. In that situation we must also switch back to N_TTY properly
- * before we reset the termios data.
+ * Some tty devices reset their termios when they receive a hangup event. In
+ * that situation we must also switch back to %N_TTY properly before we reset
+ * the termios data.
*
- * Locking: We can take the ldisc mutex as the rest of the code is
- * careful to allow for this.
+ * Locking: We can take the ldisc mutex as the rest of the code is careful to
+ * allow for this.
*
- * In the pty pair case this occurs in the close() path of the
- * tty itself so we must be careful about locking rules.
+ * In the pty pair case this occurs in the close() path of the tty itself so we
+ * must be careful about locking rules.
*/
-
void tty_ldisc_hangup(struct tty_struct *tty, bool reinit)
{
struct tty_ldisc *ld;
@@ -752,15 +727,14 @@ void tty_ldisc_hangup(struct tty_struct *tty, bool reinit)
}
/**
- * tty_ldisc_setup - open line discipline
- * @tty: tty being shut down
- * @o_tty: pair tty for pty/tty pairs
+ * tty_ldisc_setup - open line discipline
+ * @tty: tty being shut down
+ * @o_tty: pair tty for pty/tty pairs
*
- * Called during the initial open of a tty/pty pair in order to set up the
- * line disciplines and bind them to the tty. This has no locking issues
- * as the device isn't yet active.
+ * Called during the initial open of a tty/pty pair in order to set up the line
+ * disciplines and bind them to the @tty. This has no locking issues as the
+ * device isn't yet active.
*/
-
int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
{
int retval = tty_ldisc_open(tty, tty->ldisc);
@@ -783,13 +757,12 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
}
/**
- * tty_ldisc_release - release line discipline
- * @tty: tty being shut down (or one end of pty pair)
+ * tty_ldisc_release - release line discipline
+ * @tty: tty being shut down (or one end of pty pair)
*
- * Called during the final close of a tty or a pty pair in order to shut
- * down the line discpline layer. On exit, each tty's ldisc is NULL.
+ * Called during the final close of a tty or a pty pair in order to shut down
+ * the line discpline layer. On exit, each tty's ldisc is %NULL.
*/
-
void tty_ldisc_release(struct tty_struct *tty)
{
struct tty_struct *o_tty = tty->link;
@@ -814,13 +787,12 @@ void tty_ldisc_release(struct tty_struct *tty)
}
/**
- * tty_ldisc_init - ldisc setup for new tty
- * @tty: tty being allocated
+ * tty_ldisc_init - ldisc setup for new tty
+ * @tty: tty being allocated
*
- * Set up the line discipline objects for a newly allocated tty. Note that
- * the tty structure is not completely set up when this call is made.
+ * Set up the line discipline objects for a newly allocated tty. Note that the
+ * tty structure is not completely set up when this call is made.
*/
-
int tty_ldisc_init(struct tty_struct *tty)
{
struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY);
@@ -832,11 +804,11 @@ int tty_ldisc_init(struct tty_struct *tty)
}
/**
- * tty_ldisc_deinit - ldisc cleanup for new tty
- * @tty: tty that was allocated recently
+ * tty_ldisc_deinit - ldisc cleanup for new tty
+ * @tty: tty that was allocated recently
*
- * The tty structure must not becompletely set up (tty_ldisc_setup) when
- * this call is made.
+ * The tty structure must not be completely set up (tty_ldisc_setup()) when
+ * this call is made.
*/
void tty_ldisc_deinit(struct tty_struct *tty)
{
diff --git a/drivers/tty/tty_ldsem.c b/drivers/tty/tty_ldsem.c
index ce8291053af3..3be428c16260 100644
--- a/drivers/tty/tty_ldsem.c
+++ b/drivers/tty/tty_ldsem.c
@@ -163,7 +163,7 @@ down_read_failed(struct ld_semaphore *sem, long count, long timeout)
/*
* Try to reverse the lock attempt but if the count has changed
- * so that reversing fails, check if there are are no waiters,
+ * so that reversing fails, check if there are no waiters,
* and early-out if not
*/
do {
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index 2f1061a9d926..7709ce655f44 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -59,6 +59,15 @@ const struct tty_port_client_operations tty_port_default_client_ops = {
};
EXPORT_SYMBOL_GPL(tty_port_default_client_ops);
+/**
+ * tty_port_init -- initialize tty_port
+ * @port: tty_port to initialize
+ *
+ * Initializes the state of struct tty_port. When a port was initialized using
+ * this function, one has to destroy the port by tty_port_destroy(). Either
+ * indirectly by using &tty_port refcounting (tty_port_put()) or directly if
+ * refcounting is not used.
+ */
void tty_port_init(struct tty_port *port)
{
memset(port, 0, sizeof(*port));
@@ -82,9 +91,9 @@ EXPORT_SYMBOL(tty_port_init);
* @index: index of the tty
*
* Provide the tty layer with a link from a tty (specified by @index) to a
- * tty_port (@port). Use this only if neither tty_port_register_device nor
- * tty_port_install is used in the driver. If used, this has to be called before
- * tty_register_driver.
+ * tty_port (@port). Use this only if neither tty_port_register_device() nor
+ * tty_port_install() is used in the driver. If used, this has to be called
+ * before tty_register_driver().
*/
void tty_port_link_device(struct tty_port *port,
struct tty_driver *driver, unsigned index)
@@ -102,9 +111,9 @@ EXPORT_SYMBOL_GPL(tty_port_link_device);
* @index: index of the tty
* @device: parent if exists, otherwise NULL
*
- * It is the same as tty_register_device except the provided @port is linked to
- * a concrete tty specified by @index. Use this or tty_port_install (or both).
- * Call tty_port_link_device as a last resort.
+ * It is the same as tty_register_device() except the provided @port is linked
+ * to a concrete tty specified by @index. Use this or tty_port_install() (or
+ * both). Call tty_port_link_device() as a last resort.
*/
struct device *tty_port_register_device(struct tty_port *port,
struct tty_driver *driver, unsigned index,
@@ -123,9 +132,9 @@ EXPORT_SYMBOL_GPL(tty_port_register_device);
* @drvdata: Driver data to be set to device.
* @attr_grp: Attribute group to be set on device.
*
- * It is the same as tty_register_device_attr except the provided @port is
- * linked to a concrete tty specified by @index. Use this or tty_port_install
- * (or both). Call tty_port_link_device as a last resort.
+ * It is the same as tty_register_device_attr() except the provided @port is
+ * linked to a concrete tty specified by @index. Use this or tty_port_install()
+ * (or both). Call tty_port_link_device() as a last resort.
*/
struct device *tty_port_register_device_attr(struct tty_port *port,
struct tty_driver *driver, unsigned index,
@@ -240,9 +249,9 @@ EXPORT_SYMBOL(tty_port_free_xmit_buf);
* tty_port_destroy -- destroy inited port
* @port: tty port to be destroyed
*
- * When a port was initialized using tty_port_init, one has to destroy the
- * port by this function. Either indirectly by using tty_port refcounting
- * (tty_port_put) or directly if refcounting is not used.
+ * When a port was initialized using tty_port_init(), one has to destroy the
+ * port by this function. Either indirectly by using &tty_port refcounting
+ * (tty_port_put()) or directly if refcounting is not used.
*/
void tty_port_destroy(struct tty_port *port)
{
@@ -267,6 +276,13 @@ static void tty_port_destructor(struct kref *kref)
kfree(port);
}
+/**
+ * tty_port_put -- drop a reference to tty_port
+ * @port: port to drop a reference of (can be NULL)
+ *
+ * The final put will destroy and free up the @port using
+ * @port->ops->destruct() hook, or using kfree() if not provided.
+ */
void tty_port_put(struct tty_port *port)
{
if (port)
@@ -275,11 +291,11 @@ void tty_port_put(struct tty_port *port)
EXPORT_SYMBOL(tty_port_put);
/**
- * tty_port_tty_get - get a tty reference
- * @port: tty port
+ * tty_port_tty_get - get a tty reference
+ * @port: tty port
*
- * Return a refcount protected tty instance or NULL if the port is not
- * associated with a tty (eg due to close or hangup)
+ * Return a refcount protected tty instance or %NULL if the port is not
+ * associated with a tty (eg due to close or hangup).
*/
struct tty_struct *tty_port_tty_get(struct tty_port *port)
{
@@ -294,12 +310,12 @@ struct tty_struct *tty_port_tty_get(struct tty_port *port)
EXPORT_SYMBOL(tty_port_tty_get);
/**
- * tty_port_tty_set - set the tty of a port
- * @port: tty port
- * @tty: the tty
+ * tty_port_tty_set - set the tty of a port
+ * @port: tty port
+ * @tty: the tty
*
- * Associate the port and tty pair. Manages any internal refcounts.
- * Pass NULL to deassociate a port
+ * Associate the port and tty pair. Manages any internal refcounts. Pass %NULL
+ * to deassociate a port.
*/
void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
{
@@ -312,6 +328,16 @@ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
}
EXPORT_SYMBOL(tty_port_tty_set);
+/**
+ * tty_port_shutdown - internal helper to shutdown the device
+ * @port: tty port to be shut down
+ * @tty: the associated tty
+ *
+ * It is used by tty_port_hangup() and tty_port_close(). Its task is to
+ * shutdown the device if it was initialized (note consoles remain
+ * functioning). It lowers DTR/RTS (if @tty has HUPCL set) and invokes
+ * @port->ops->shutdown().
+ */
static void tty_port_shutdown(struct tty_port *port, struct tty_struct *tty)
{
mutex_lock(&port->mutex);
@@ -335,13 +361,13 @@ out:
}
/**
- * tty_port_hangup - hangup helper
- * @port: tty port
+ * tty_port_hangup - hangup helper
+ * @port: tty port
*
- * Perform port level tty hangup flag and count changes. Drop the tty
- * reference.
+ * Perform port level tty hangup flag and count changes. Drop the tty
+ * reference.
*
- * Caller holds tty lock.
+ * Caller holds tty lock.
*/
void tty_port_hangup(struct tty_port *port)
{
@@ -365,9 +391,8 @@ EXPORT_SYMBOL(tty_port_hangup);
/**
* tty_port_tty_hangup - helper to hang up a tty
- *
* @port: tty port
- * @check_clocal: hang only ttys with CLOCAL unset?
+ * @check_clocal: hang only ttys with %CLOCAL unset?
*/
void tty_port_tty_hangup(struct tty_port *port, bool check_clocal)
{
@@ -381,7 +406,6 @@ EXPORT_SYMBOL_GPL(tty_port_tty_hangup);
/**
* tty_port_tty_wakeup - helper to wake up a tty
- *
* @port: tty port
*/
void tty_port_tty_wakeup(struct tty_port *port)
@@ -391,12 +415,12 @@ void tty_port_tty_wakeup(struct tty_port *port)
EXPORT_SYMBOL_GPL(tty_port_tty_wakeup);
/**
- * tty_port_carrier_raised - carrier raised check
- * @port: tty port
+ * tty_port_carrier_raised - carrier raised check
+ * @port: tty port
*
- * Wrapper for the carrier detect logic. For the moment this is used
- * to hide some internal details. This will eventually become entirely
- * internal to the tty port.
+ * Wrapper for the carrier detect logic. For the moment this is used
+ * to hide some internal details. This will eventually become entirely
+ * internal to the tty port.
*/
int tty_port_carrier_raised(struct tty_port *port)
{
@@ -407,12 +431,12 @@ int tty_port_carrier_raised(struct tty_port *port)
EXPORT_SYMBOL(tty_port_carrier_raised);
/**
- * tty_port_raise_dtr_rts - Raise DTR/RTS
- * @port: tty port
+ * tty_port_raise_dtr_rts - Raise DTR/RTS
+ * @port: tty port
*
- * Wrapper for the DTR/RTS raise logic. For the moment this is used
- * to hide some internal details. This will eventually become entirely
- * internal to the tty port.
+ * Wrapper for the DTR/RTS raise logic. For the moment this is used to hide
+ * some internal details. This will eventually become entirely internal to the
+ * tty port.
*/
void tty_port_raise_dtr_rts(struct tty_port *port)
{
@@ -422,12 +446,12 @@ void tty_port_raise_dtr_rts(struct tty_port *port)
EXPORT_SYMBOL(tty_port_raise_dtr_rts);
/**
- * tty_port_lower_dtr_rts - Lower DTR/RTS
- * @port: tty port
+ * tty_port_lower_dtr_rts - Lower DTR/RTS
+ * @port: tty port
*
- * Wrapper for the DTR/RTS raise logic. For the moment this is used
- * to hide some internal details. This will eventually become entirely
- * internal to the tty port.
+ * Wrapper for the DTR/RTS raise logic. For the moment this is used to hide
+ * some internal details. This will eventually become entirely internal to the
+ * tty port.
*/
void tty_port_lower_dtr_rts(struct tty_port *port)
{
@@ -437,28 +461,29 @@ void tty_port_lower_dtr_rts(struct tty_port *port)
EXPORT_SYMBOL(tty_port_lower_dtr_rts);
/**
- * tty_port_block_til_ready - Waiting logic for tty open
- * @port: the tty port being opened
- * @tty: the tty device being bound
- * @filp: the file pointer of the opener or NULL
- *
- * Implement the core POSIX/SuS tty behaviour when opening a tty device.
- * Handles:
- * - hangup (both before and during)
- * - non blocking open
- * - rts/dtr/dcd
- * - signals
- * - port flags and counts
- *
- * The passed tty_port must implement the carrier_raised method if it can
- * do carrier detect and the dtr_rts method if it supports software
- * management of these lines. Note that the dtr/rts raise is done each
- * iteration as a hangup may have previously dropped them while we wait.
- *
- * Caller holds tty lock.
- *
- * NB: May drop and reacquire tty lock when blocking, so tty and tty_port
- * may have changed state (eg., may have been hung up).
+ * tty_port_block_til_ready - Waiting logic for tty open
+ * @port: the tty port being opened
+ * @tty: the tty device being bound
+ * @filp: the file pointer of the opener or %NULL
+ *
+ * Implement the core POSIX/SuS tty behaviour when opening a tty device.
+ * Handles:
+ *
+ * - hangup (both before and during)
+ * - non blocking open
+ * - rts/dtr/dcd
+ * - signals
+ * - port flags and counts
+ *
+ * The passed @port must implement the @port->ops->carrier_raised method if it
+ * can do carrier detect and the @port->ops->dtr_rts method if it supports
+ * software management of these lines. Note that the dtr/rts raise is done each
+ * iteration as a hangup may have previously dropped them while we wait.
+ *
+ * Caller holds tty lock.
+ *
+ * Note: May drop and reacquire tty lock when blocking, so @tty and @port may
+ * have changed state (eg., may have been hung up).
*/
int tty_port_block_til_ready(struct tty_port *port,
struct tty_struct *tty, struct file *filp)
@@ -560,7 +585,21 @@ static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty)
schedule_timeout_interruptible(timeout);
}
-/* Caller holds tty lock. */
+/**
+ * tty_port_close_start - helper for tty->ops->close, part 1/2
+ * @port: tty_port of the device
+ * @tty: tty being closed
+ * @filp: passed file pointer
+ *
+ * Decrements and checks open count. Flushes the port if this is the last
+ * close. That means, dropping the data from the outpu buffer on the device and
+ * waiting for sending logic to finish. The rest of close handling is performed
+ * in tty_port_close_end().
+ *
+ * Locking: Caller holds tty lock.
+ *
+ * Return: 1 if this is the last close, otherwise 0
+ */
int tty_port_close_start(struct tty_port *port,
struct tty_struct *tty, struct file *filp)
{
@@ -606,7 +645,17 @@ int tty_port_close_start(struct tty_port *port,
}
EXPORT_SYMBOL(tty_port_close_start);
-/* Caller holds tty lock */
+/**
+ * tty_port_close_end - helper for tty->ops->close, part 2/2
+ * @port: tty_port of the device
+ * @tty: tty being closed
+ *
+ * This is a continuation of the first part: tty_port_close_start(). This
+ * should be called after turning off the device. It flushes the data from the
+ * line discipline and delays the close by @port->close_delay.
+ *
+ * Locking: Caller holds tty lock.
+ */
void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
{
unsigned long flags;
@@ -628,10 +677,18 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
}
EXPORT_SYMBOL(tty_port_close_end);
-/*
- * tty_port_close
+/**
+ * tty_port_close - generic tty->ops->close handler
+ * @port: tty_port of the device
+ * @tty: tty being closed
+ * @filp: passed file pointer
+ *
+ * It is a generic helper to be used in driver's @tty->ops->close. It wraps a
+ * sequence of tty_port_close_start(), tty_port_shutdown(), and
+ * tty_port_close_end(). The latter two are called only if this is the last
+ * close. See the respective functions for the details.
*
- * Caller holds tty lock
+ * Locking: Caller holds tty lock
*/
void tty_port_close(struct tty_port *port, struct tty_struct *tty,
struct file *filp)
@@ -652,9 +709,9 @@ EXPORT_SYMBOL(tty_port_close);
* @driver: tty_driver for this device
* @tty: tty to be installed
*
- * It is the same as tty_standard_install except the provided @port is linked
- * to a concrete tty specified by @tty. Use this or tty_port_register_device
- * (or both). Call tty_port_link_device as a last resort.
+ * It is the same as tty_standard_install() except the provided @port is linked
+ * to a concrete tty specified by @tty. Use this or tty_port_register_device()
+ * (or both). Call tty_port_link_device() as a last resort.
*/
int tty_port_install(struct tty_port *port, struct tty_driver *driver,
struct tty_struct *tty)
@@ -664,13 +721,21 @@ int tty_port_install(struct tty_port *port, struct tty_driver *driver,
}
EXPORT_SYMBOL_GPL(tty_port_install);
-/*
- * tty_port_open
+/**
+ * tty_port_open - generic tty->ops->open handler
+ * @port: tty_port of the device
+ * @tty: tty to be opened
+ * @filp: passed file pointer
*
- * Caller holds tty lock.
+ * It is a generic helper to be used in driver's @tty->ops->open. It activates
+ * the devices using @port->ops->activate if not active already. And waits for
+ * the device to be ready using tty_port_block_til_ready() (e.g. raises
+ * DTR/CTS and waits for carrier).
+ *
+ * Locking: Caller holds tty lock.
*
- * NB: may drop and reacquire tty lock (in tty_port_block_til_ready()) so
- * tty and tty_port may have changed state (eg., may be hung up now)
+ * Note: may drop and reacquire tty lock (in tty_port_block_til_ready()) so
+ * @tty and @port may have changed state (eg., may be hung up now).
*/
int tty_port_open(struct tty_port *port, struct tty_struct *tty,
struct file *filp)
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index c7fbbcdcc346..be8313cdbac3 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -153,6 +153,7 @@ static int shift_state = 0;
static unsigned int ledstate = -1U; /* undefined */
static unsigned char ledioctl;
+static bool vt_switch;
/*
* Notifier list for console keyboard events
@@ -324,13 +325,13 @@ int kbd_rate(struct kbd_repeat *rpt)
static void put_queue(struct vc_data *vc, int ch)
{
tty_insert_flip_char(&vc->port, ch, 0);
- tty_schedule_flip(&vc->port);
+ tty_flip_buffer_push(&vc->port);
}
static void puts_queue(struct vc_data *vc, const char *cp)
{
tty_insert_flip_string(&vc->port, cp, strlen(cp));
- tty_schedule_flip(&vc->port);
+ tty_flip_buffer_push(&vc->port);
}
static void applkey(struct vc_data *vc, int key, char mode)
@@ -414,6 +415,12 @@ void vt_set_leds_compute_shiftstate(void)
{
unsigned long flags;
+ /*
+ * When VT is switched, the keyboard led needs to be set once.
+ * Ensure that after the switch is completed, the state of the
+ * keyboard LED is consistent with the state of the keyboard lock.
+ */
+ vt_switch = true;
set_leds();
spin_lock_irqsave(&kbd_event_lock, flags);
@@ -584,7 +591,7 @@ static void fn_inc_console(struct vc_data *vc)
static void fn_send_intr(struct vc_data *vc)
{
tty_insert_flip_char(&vc->port, 0, TTY_BREAK);
- tty_schedule_flip(&vc->port);
+ tty_flip_buffer_push(&vc->port);
}
static void fn_scroll_forw(struct vc_data *vc)
@@ -1255,6 +1262,11 @@ static void kbd_bh(struct tasklet_struct *unused)
leds |= (unsigned int)kbd->lockstate << 8;
spin_unlock_irqrestore(&led_lock, flags);
+ if (vt_switch) {
+ ledstate = ~leds;
+ vt_switch = false;
+ }
+
if (leds != ledstate) {
kbd_propagate_led_state(ledstate, leds);
ledstate = leds;
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 7359c3e80d63..f8c87c4d7399 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -1833,7 +1833,7 @@ static void csi_m(struct vc_data *vc)
static void respond_string(const char *p, size_t len, struct tty_port *port)
{
tty_insert_flip_string(port, p, len);
- tty_schedule_flip(port);
+ tty_flip_buffer_push(port);
}
static void cursor_report(struct vc_data *vc, struct tty_struct *tty)
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index b3ce7338cb6b..9b9aea24d58c 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -685,10 +685,6 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
if (retval)
goto error_get_interface;
- /*
- * FIXME: Why do we need this? Allocating 64K of physically contiguous
- * memory is really nasty...
- */
set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);
acm->control->needs_remote_wakeup = 1;
diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h
index edfcf7a14dcd..6c7f47846971 100644
--- a/include/linux/amba/bus.h
+++ b/include/linux/amba/bus.h
@@ -90,14 +90,8 @@ enum amba_vendor {
AMBA_VENDOR_ST = 0x80,
AMBA_VENDOR_QCOM = 0x51,
AMBA_VENDOR_LSI = 0xb6,
- AMBA_VENDOR_LINUX = 0xfe, /* This value is not official */
};
-/* This is used to generate pseudo-ID for AMBA device */
-#define AMBA_LINUX_ID(conf, rev, part) \
- (((conf) & 0xff) << 24 | ((rev) & 0xf) << 20 | \
- AMBA_VENDOR_LINUX << 12 | ((part) & 0xfff))
-
extern struct bus_type amba_bustype;
#define to_amba_device(d) container_of(d, struct amba_device, dev)
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index b5248f27910e..86678588d191 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1965,24 +1965,6 @@
#define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003
#define PCI_VENDOR_ID_MOXA 0x1393
-#define PCI_DEVICE_ID_MOXA_RC7000 0x0001
-#define PCI_DEVICE_ID_MOXA_CP102 0x1020
-#define PCI_DEVICE_ID_MOXA_CP102UL 0x1021
-#define PCI_DEVICE_ID_MOXA_CP102U 0x1022
-#define PCI_DEVICE_ID_MOXA_C104 0x1040
-#define PCI_DEVICE_ID_MOXA_CP104U 0x1041
-#define PCI_DEVICE_ID_MOXA_CP104JU 0x1042
-#define PCI_DEVICE_ID_MOXA_CP104EL 0x1043
-#define PCI_DEVICE_ID_MOXA_CT114 0x1140
-#define PCI_DEVICE_ID_MOXA_CP114 0x1141
-#define PCI_DEVICE_ID_MOXA_CP118U 0x1180
-#define PCI_DEVICE_ID_MOXA_CP118EL 0x1181
-#define PCI_DEVICE_ID_MOXA_CP132 0x1320
-#define PCI_DEVICE_ID_MOXA_CP132U 0x1321
-#define PCI_DEVICE_ID_MOXA_CP134U 0x1340
-#define PCI_DEVICE_ID_MOXA_C168 0x1680
-#define PCI_DEVICE_ID_MOXA_CP168U 0x1681
-#define PCI_DEVICE_ID_MOXA_CP168EL 0x1682
#define PCI_DEVICE_ID_MOXA_CP204J 0x2040
#define PCI_DEVICE_ID_MOXA_C218 0x2180
#define PCI_DEVICE_ID_MOXA_C320 0x3200
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 5db211f43b29..ff84a3ed10ea 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -104,8 +104,6 @@ struct uart_8250_port {
unsigned char ier;
unsigned char lcr;
unsigned char mcr;
- unsigned char mcr_mask; /* mask of user bits */
- unsigned char mcr_force; /* mask of forced bits */
unsigned char cur_iotype; /* Running I/O type */
unsigned int rpm_tx_active;
unsigned char canary; /* non-zero during system sleep
diff --git a/include/linux/serial_s3c.h b/include/linux/serial_s3c.h
index cf0de4a86640..f6c3323fc4c5 100644
--- a/include/linux/serial_s3c.h
+++ b/include/linux/serial_s3c.h
@@ -27,15 +27,6 @@
#define S3C2410_UERSTAT (0x14)
#define S3C2410_UFSTAT (0x18)
#define S3C2410_UMSTAT (0x1C)
-#define USI_CON (0xC4)
-#define USI_OPTION (0xC8)
-
-#define USI_CON_RESET (1<<0)
-#define USI_CON_RESET_MASK (1<<0)
-
-#define USI_OPTION_HWACG_CLKREQ_ON (1<<1)
-#define USI_OPTION_HWACG_CLKSTOP_ON (1<<2)
-#define USI_OPTION_HWACG_MASK (3<<1)
#define S3C2410_LCON_CFGMASK ((0xF<<3)|(0x3))
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 5dbd7c5afac7..7b0a5d478ef6 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -122,33 +122,84 @@ struct tty_operations;
/**
* struct tty_struct - state associated with a tty while open
*
- * @flow.lock: lock for flow members
- * @flow.stopped: tty stopped/started by tty_stop/tty_start
- * @flow.tco_stopped: tty stopped/started by TCOOFF/TCOON ioctls (it has
- * precedense over @flow.stopped)
+ * @magic: magic value set early in @alloc_tty_struct to %TTY_MAGIC, for
+ * debugging purposes
+ * @kref: reference counting by tty_kref_get() and tty_kref_put(), reaching zero
+ * frees the structure
+ * @dev: class device or %NULL (e.g. ptys, serdev)
+ * @driver: &struct tty_driver operating this tty
+ * @ops: &struct tty_operations of @driver for this tty (open, close, etc.)
+ * @index: index of this tty (e.g. to construct @name like tty12)
+ * @ldisc_sem: protects line discipline changes (@ldisc) -- lock tty not pty
+ * @ldisc: the current line discipline for this tty (n_tty by default)
+ * @atomic_write_lock: protects against concurrent writers, i.e. locks
+ * @write_cnt, @write_buf and similar
+ * @legacy_mutex: leftover from history (BKL -> BTM -> @legacy_mutex),
+ * protecting several operations on this tty
+ * @throttle_mutex: protects against concurrent tty_throttle_safe() and
+ * tty_unthrottle_safe() (but not tty_unthrottle())
+ * @termios_rwsem: protects @termios and @termios_locked
+ * @winsize_mutex: protects @winsize
+ * @termios: termios for the current tty, copied from/to @driver.termios
+ * @termios_locked: locked termios (by %TIOCGLCKTRMIOS and %TIOCSLCKTRMIOS
+ * ioctls)
+ * @name: name of the tty constructed by tty_line_name() (e.g. ttyS3)
+ * @flags: bitwise OR of %TTY_THROTTLED, %TTY_IO_ERROR, ...
+ * @count: count of open processes, reaching zero cancels all the work for
+ * this tty and drops a @kref too (but does not free this tty)
+ * @winsize: size of the terminal "window" (cf. @winsize_mutex)
+ * @flow: flow settings grouped together, see also @flow.unused
+ * @flow.lock: lock for @flow members
+ * @flow.stopped: tty stopped/started by stop_tty()/start_tty()
+ * @flow.tco_stopped: tty stopped/started by %TCOOFF/%TCOON ioctls (it has
+ * precedence over @flow.stopped)
* @flow.unused: alignment for Alpha, so that no members other than @flow.* are
* modified by the same 64b word store. The @flow's __aligned is
* there for the very same reason.
- * @ctrl.lock: lock for ctrl members
+ * @ctrl: control settings grouped together, see also @ctrl.unused
+ * @ctrl.lock: lock for @ctrl members
* @ctrl.pgrp: process group of this tty (setpgrp(2))
* @ctrl.session: session of this tty (setsid(2)). Writes are protected by both
- * @ctrl.lock and legacy mutex, readers must use at least one of
+ * @ctrl.lock and @legacy_mutex, readers must use at least one of
* them.
- * @ctrl.pktstatus: packet mode status (bitwise OR of TIOCPKT_* constants)
+ * @ctrl.pktstatus: packet mode status (bitwise OR of %TIOCPKT_ constants)
* @ctrl.packet: packet mode enabled
+ * @ctrl.unused: alignment for Alpha, see @flow.unused for explanation
+ * @hw_stopped: not controlled by the tty layer, under @driver's control for CTS
+ * handling
+ * @receive_room: bytes permitted to feed to @ldisc without any being lost
+ * @flow_change: controls behavior of throttling, see tty_throttle_safe() and
+ * tty_unthrottle_safe()
+ * @link: link to another pty (master -> slave and vice versa)
+ * @fasync: state for %O_ASYNC (for %SIGIO); managed by fasync_helper()
+ * @write_wait: concurrent writers are waiting in this queue until they are
+ * allowed to write
+ * @read_wait: readers wait for data in this queue
+ * @hangup_work: normally a work to perform a hangup (do_tty_hangup()); while
+ * freeing the tty, (re)used to release_one_tty()
+ * @disc_data: pointer to @ldisc's private data (e.g. to &struct n_tty_data)
+ * @driver_data: pointer to @driver's private data (e.g. &struct uart_state)
+ * @files_lock: protects @tty_files list
+ * @tty_files: list of (re)openers of this tty (i.e. linked &struct
+ * tty_file_private)
+ * @closing: when set during close, n_tty processes only START & STOP chars
+ * @write_buf: temporary buffer used during tty_write() to copy user data to
+ * @write_cnt: count of bytes written in tty_write() to @write_buf
+ * @SAK_work: if the tty has a pending do_SAK, it is queued here
+ * @port: persistent storage for this device (i.e. &struct tty_port)
*
* All of the state associated with a tty while the tty is open. Persistent
- * storage for tty devices is referenced here as @port in struct tty_port.
+ * storage for tty devices is referenced here as @port and is documented in
+ * &struct tty_port.
*/
struct tty_struct {
int magic;
struct kref kref;
- struct device *dev; /* class device or NULL (e.g. ptys, serdev) */
+ struct device *dev;
struct tty_driver *driver;
const struct tty_operations *ops;
int index;
- /* Protects ldisc changes: Lock tty not pty */
struct ld_semaphore ldisc_sem;
struct tty_ldisc *ldisc;
@@ -157,12 +208,11 @@ struct tty_struct {
struct mutex throttle_mutex;
struct rw_semaphore termios_rwsem;
struct mutex winsize_mutex;
- /* Termios values are protected by the termios rwsem */
struct ktermios termios, termios_locked;
char name[64];
unsigned long flags;
int count;
- struct winsize winsize; /* winsize_mutex */
+ struct winsize winsize;
struct {
spinlock_t lock;
@@ -181,7 +231,7 @@ struct tty_struct {
} __aligned(sizeof(unsigned long)) ctrl;
int hw_stopped;
- unsigned int receive_room; /* Bytes free for queue */
+ unsigned int receive_room;
int flow_change;
struct tty_struct *link;
@@ -191,7 +241,7 @@ struct tty_struct {
struct work_struct hangup_work;
void *disc_data;
void *driver_data;
- spinlock_t files_lock; /* protects tty_files list */
+ spinlock_t files_lock;
struct list_head tty_files;
#define N_TTY_BUF_SIZE 4096
@@ -199,7 +249,6 @@ struct tty_struct {
int closing;
unsigned char *write_buf;
int write_cnt;
- /* If the tty has a pending do_SAK, queue it here - akpm */
struct work_struct SAK_work;
struct tty_port *port;
} __randomize_layout;
@@ -214,26 +263,72 @@ struct tty_file_private {
/* tty magic number */
#define TTY_MAGIC 0x5401
-/*
- * These bits are used in the flags field of the tty structure.
+/**
+ * DOC: TTY Struct Flags
+ *
+ * These bits are used in the :c:member:`tty_struct.flags` field.
*
* So that interrupts won't be able to mess up the queues,
* copy_to_cooked must be atomic with respect to itself, as must
* tty->write. Thus, you must use the inline functions set_bit() and
* clear_bit() to make things atomic.
+ *
+ * TTY_THROTTLED
+ * Driver input is throttled. The ldisc should call
+ * :c:member:`tty_driver.unthrottle()` in order to resume reception when
+ * it is ready to process more data (at threshold min).
+ *
+ * TTY_IO_ERROR
+ * If set, causes all subsequent userspace read/write calls on the tty to
+ * fail, returning -%EIO. (May be no ldisc too.)
+ *
+ * TTY_OTHER_CLOSED
+ * Device is a pty and the other side has closed.
+ *
+ * TTY_EXCLUSIVE
+ * Exclusive open mode (a single opener).
+ *
+ * TTY_DO_WRITE_WAKEUP
+ * If set, causes the driver to call the
+ * :c:member:`tty_ldisc_ops.write_wakeup()` method in order to resume
+ * transmission when it can accept more data to transmit.
+ *
+ * TTY_LDISC_OPEN
+ * Indicates that a line discipline is open. For debugging purposes only.
+ *
+ * TTY_PTY_LOCK
+ * A flag private to pty code to implement %TIOCSPTLCK/%TIOCGPTLCK logic.
+ *
+ * TTY_NO_WRITE_SPLIT
+ * Prevent driver from splitting up writes into smaller chunks (preserve
+ * write boundaries to driver).
+ *
+ * TTY_HUPPED
+ * The TTY was hung up. This is set post :c:member:`tty_driver.hangup()`.
+ *
+ * TTY_HUPPING
+ * The TTY is in the process of hanging up to abort potential readers.
+ *
+ * TTY_LDISC_CHANGING
+ * Line discipline for this TTY is being changed. I/O should not block
+ * when this is set. Use tty_io_nonblock() to check.
+ *
+ * TTY_LDISC_HALTED
+ * Line discipline for this TTY was stopped. No work should be queued to
+ * this ldisc.
*/
-#define TTY_THROTTLED 0 /* Call unthrottle() at threshold min */
-#define TTY_IO_ERROR 1 /* Cause an I/O error (may be no ldisc too) */
-#define TTY_OTHER_CLOSED 2 /* Other side (if any) has closed */
-#define TTY_EXCLUSIVE 3 /* Exclusive open mode */
-#define TTY_DO_WRITE_WAKEUP 5 /* Call write_wakeup after queuing new */
-#define TTY_LDISC_OPEN 11 /* Line discipline is open */
-#define TTY_PTY_LOCK 16 /* pty private */
-#define TTY_NO_WRITE_SPLIT 17 /* Preserve write boundaries to driver */
-#define TTY_HUPPED 18 /* Post driver->hangup() */
-#define TTY_HUPPING 19 /* Hangup in progress */
-#define TTY_LDISC_CHANGING 20 /* Change pending - non-block IO */
-#define TTY_LDISC_HALTED 22 /* Line discipline is halted */
+#define TTY_THROTTLED 0
+#define TTY_IO_ERROR 1
+#define TTY_OTHER_CLOSED 2
+#define TTY_EXCLUSIVE 3
+#define TTY_DO_WRITE_WAKEUP 5
+#define TTY_LDISC_OPEN 11
+#define TTY_PTY_LOCK 16
+#define TTY_NO_WRITE_SPLIT 17
+#define TTY_HUPPED 18
+#define TTY_HUPPING 19
+#define TTY_LDISC_CHANGING 20
+#define TTY_LDISC_HALTED 22
static inline bool tty_io_nonblock(struct tty_struct *tty, struct file *file)
{
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index 795b94ccdeb6..4841d8069c07 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -2,248 +2,350 @@
#ifndef _LINUX_TTY_DRIVER_H
#define _LINUX_TTY_DRIVER_H
-/*
- * This structure defines the interface between the low-level tty
- * driver and the tty routines. The following routines can be
- * defined; unless noted otherwise, they are optional, and can be
- * filled in with a null pointer.
+#include <linux/export.h>
+#include <linux/fs.h>
+#include <linux/kref.h>
+#include <linux/list.h>
+#include <linux/cdev.h>
+#include <linux/termios.h>
+#include <linux/seq_file.h>
+
+struct tty_struct;
+struct tty_driver;
+struct serial_icounter_struct;
+struct serial_struct;
+
+/**
+ * struct tty_operations -- interface between driver and tty
+ *
+ * @lookup: ``struct tty_struct *()(struct tty_driver *self, struct file *,
+ * int idx)``
*
- * struct tty_struct * (*lookup)(struct tty_driver *self, struct file *, int idx)
+ * Return the tty device corresponding to @idx, %NULL if there is not
+ * one currently in use and an %ERR_PTR value on error. Called under
+ * %tty_mutex (for now!)
*
- * Return the tty device corresponding to idx, NULL if there is not
- * one currently in use and an ERR_PTR value on error. Called under
- * tty_mutex (for now!)
+ * Optional method. Default behaviour is to use the @self->ttys array.
*
- * Optional method. Default behaviour is to use the ttys array
+ * @install: ``int ()(struct tty_driver *self, struct tty_struct *tty)``
*
- * int (*install)(struct tty_driver *self, struct tty_struct *tty)
+ * Install a new @tty into the @self's internal tables. Used in
+ * conjunction with @lookup and @remove methods.
*
- * Install a new tty into the tty driver internal tables. Used in
- * conjunction with lookup and remove methods.
+ * Optional method. Default behaviour is to use the @self->ttys array.
*
- * Optional method. Default behaviour is to use the ttys array
+ * @remove: ``void ()(struct tty_driver *self, struct tty_struct *tty)``
*
- * void (*remove)(struct tty_driver *self, struct tty_struct *tty)
+ * Remove a closed @tty from the @self's internal tables. Used in
+ * conjunction with @lookup and @remove methods.
*
- * Remove a closed tty from the tty driver internal tables. Used in
- * conjunction with lookup and remove methods.
+ * Optional method. Default behaviour is to use the @self->ttys array.
*
- * Optional method. Default behaviour is to use the ttys array
+ * @open: ``int ()(struct tty_struct *tty, struct file *)``
*
- * int (*open)(struct tty_struct * tty, struct file * filp);
+ * This routine is called when a particular @tty device is opened. This
+ * routine is mandatory; if this routine is not filled in, the attempted
+ * open will fail with %ENODEV.
*
- * This routine is called when a particular tty device is opened.
- * This routine is mandatory; if this routine is not filled in,
- * the attempted open will fail with ENODEV.
+ * Required method. Called with tty lock held. May sleep.
*
- * Required method. Called with tty lock held.
+ * @close: ``void ()(struct tty_struct *tty, struct file *)``
*
- * void (*close)(struct tty_struct * tty, struct file * filp);
+ * This routine is called when a particular @tty device is closed. At the
+ * point of return from this call the driver must make no further ldisc
+ * calls of any kind.
*
- * This routine is called when a particular tty device is closed.
- * Note: called even if the corresponding open() failed.
+ * Remark: called even if the corresponding @open() failed.
*
- * Required method. Called with tty lock held.
+ * Required method. Called with tty lock held. May sleep.
*
- * void (*shutdown)(struct tty_struct * tty);
+ * @shutdown: ``void ()(struct tty_struct *tty)``
*
- * This routine is called under the tty lock when a particular tty device
- * is closed for the last time. It executes before the tty resources
- * are freed so may execute while another function holds a tty kref.
+ * This routine is called under the tty lock when a particular @tty device
+ * is closed for the last time. It executes before the @tty resources
+ * are freed so may execute while another function holds a @tty kref.
*
- * void (*cleanup)(struct tty_struct * tty);
+ * @cleanup: ``void ()(struct tty_struct *tty)``
*
- * This routine is called asynchronously when a particular tty device
+ * This routine is called asynchronously when a particular @tty device
* is closed for the last time freeing up the resources. This is
* actually the second part of shutdown for routines that might sleep.
*
+ * @write: ``int ()(struct tty_struct *tty, const unsigned char *buf,
+ * int count)``
*
- * int (*write)(struct tty_struct * tty,
- * const unsigned char *buf, int count);
- *
- * This routine is called by the kernel to write a series of
- * characters to the tty device. The characters may come from
- * user space or kernel space. This routine will return the
+ * This routine is called by the kernel to write a series (@count) of
+ * characters (@buf) to the @tty device. The characters may come from
+ * user space or kernel space. This routine will return the
* number of characters actually accepted for writing.
*
- * Optional: Required for writable devices.
+ * May occur in parallel in special cases. Because this includes panic
+ * paths drivers generally shouldn't try and do clever locking here.
*
- * int (*put_char)(struct tty_struct *tty, unsigned char ch);
+ * Optional: Required for writable devices. May not sleep.
*
- * This routine is called by the kernel to write a single
- * character to the tty device. If the kernel uses this routine,
- * it must call the flush_chars() routine (if defined) when it is
- * done stuffing characters into the driver. If there is no room
- * in the queue, the character is ignored.
+ * @put_char: ``int ()(struct tty_struct *tty, unsigned char ch)``
*
- * Optional: Kernel will use the write method if not provided.
+ * This routine is called by the kernel to write a single character @ch to
+ * the @tty device. If the kernel uses this routine, it must call the
+ * @flush_chars() routine (if defined) when it is done stuffing characters
+ * into the driver. If there is no room in the queue, the character is
+ * ignored.
*
- * Note: Do not call this function directly, call tty_put_char
+ * Optional: Kernel will use the @write method if not provided. Do not
+ * call this function directly, call tty_put_char().
*
- * void (*flush_chars)(struct tty_struct *tty);
+ * @flush_chars: ``void ()(struct tty_struct *tty)``
*
- * This routine is called by the kernel after it has written a
- * series of characters to the tty device using put_char().
+ * This routine is called by the kernel after it has written a
+ * series of characters to the tty device using @put_char().
*
- * Optional:
+ * Optional. Do not call this function directly, call
+ * tty_driver_flush_chars().
*
- * Note: Do not call this function directly, call tty_driver_flush_chars
- *
- * unsigned int (*write_room)(struct tty_struct *tty);
+ * @write_room: ``unsigned int ()(struct tty_struct *tty)``
*
- * This routine returns the numbers of characters the tty driver
- * will accept for queuing to be written. This number is subject
- * to change as output buffers get emptied, or if the output flow
+ * This routine returns the numbers of characters the @tty driver
+ * will accept for queuing to be written. This number is subject
+ * to change as output buffers get emptied, or if the output flow
* control is acted.
*
- * Required if write method is provided else not needed.
+ * The ldisc is responsible for being intelligent about multi-threading of
+ * write_room/write calls
+ *
+ * Required if @write method is provided else not needed. Do not call this
+ * function directly, call tty_write_room()
+ *
+ * @chars_in_buffer: ``unsigned int ()(struct tty_struct *tty)``
+ *
+ * This routine returns the number of characters in the device private
+ * output queue. Used in tty_wait_until_sent() and for poll()
+ * implementation.
*
- * Note: Do not call this function directly, call tty_write_room
- *
- * int (*ioctl)(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
+ * Optional: if not provided, it is assumed there is no queue on the
+ * device. Do not call this function directly, call tty_chars_in_buffer().
*
- * This routine allows the tty driver to implement
- * device-specific ioctls. If the ioctl number passed in cmd
- * is not recognized by the driver, it should return ENOIOCTLCMD.
+ * @ioctl: ``int ()(struct tty_struct *tty, unsigned int cmd,
+ * unsigned long arg)``
*
- * Optional
+ * This routine allows the @tty driver to implement device-specific
+ * ioctls. If the ioctl number passed in @cmd is not recognized by the
+ * driver, it should return %ENOIOCTLCMD.
*
- * long (*compat_ioctl)(struct tty_struct *tty,,
- * unsigned int cmd, unsigned long arg);
+ * Optional.
*
- * implement ioctl processing for 32 bit process on 64 bit system
+ * @compat_ioctl: ``long ()(struct tty_struct *tty, unsigned int cmd,
+ * unsigned long arg)``
*
- * Optional
- *
- * void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
+ * Implement ioctl processing for 32 bit process on 64 bit system.
*
- * This routine allows the tty driver to be notified when
- * device's termios settings have changed.
+ * Optional.
*
- * Optional: Called under the termios lock
+ * @set_termios: ``void ()(struct tty_struct *tty, struct ktermios *old)``
*
+ * This routine allows the @tty driver to be notified when device's
+ * termios settings have changed. New settings are in @tty->termios.
+ * Previous settings are passed in the @old argument.
*
- * void (*set_ldisc)(struct tty_struct *tty);
+ * The API is defined such that the driver should return the actual modes
+ * selected. This means that the driver is responsible for modifying any
+ * bits in @tty->termios it cannot fulfill to indicate the actual modes
+ * being used.
*
- * This routine allows the tty driver to be notified when the
- * device's termios settings have changed.
+ * Optional. Called under the @tty->termios_rwsem. May sleep.
*
- * Optional: Called under BKL (currently)
- *
- * void (*throttle)(struct tty_struct * tty);
+ * @set_ldisc: ``void ()(struct tty_struct *tty)``
*
- * This routine notifies the tty driver that input buffers for
- * the line discipline are close to full, and it should somehow
- * signal that no more characters should be sent to the tty.
+ * This routine allows the @tty driver to be notified when the device's
+ * line discipline is being changed. At the point this is done the
+ * discipline is not yet usable.
*
- * Optional: Always invoke via tty_throttle_safe(), called under the
- * termios lock.
- *
- * void (*unthrottle)(struct tty_struct * tty);
+ * Optional. Called under the @tty->ldisc_sem and @tty->termios_rwsem.
*
- * This routine notifies the tty drivers that it should signals
- * that characters can now be sent to the tty without fear of
- * overrunning the input buffers of the line disciplines.
- *
- * Optional: Always invoke via tty_unthrottle(), called under the
- * termios lock.
+ * @throttle: ``void ()(struct tty_struct *tty)``
*
- * void (*stop)(struct tty_struct *tty);
+ * This routine notifies the @tty driver that input buffers for the line
+ * discipline are close to full, and it should somehow signal that no more
+ * characters should be sent to the @tty.
*
- * This routine notifies the tty driver that it should stop
- * outputting characters to the tty device.
+ * Serialization including with @unthrottle() is the job of the ldisc
+ * layer.
*
- * Called with ->flow.lock held. Serialized with start() method.
+ * Optional: Always invoke via tty_throttle_safe(). Called under the
+ * @tty->termios_rwsem.
*
- * Optional:
+ * @unthrottle: ``void ()(struct tty_struct *tty)``
*
- * Note: Call stop_tty not this method.
- *
- * void (*start)(struct tty_struct *tty);
+ * This routine notifies the @tty driver that it should signal that
+ * characters can now be sent to the @tty without fear of overrunning the
+ * input buffers of the line disciplines.
*
- * This routine notifies the tty driver that it resume sending
+ * Optional. Always invoke via tty_unthrottle(). Called under the
+ * @tty->termios_rwsem.
+ *
+ * @stop: ``void ()(struct tty_struct *tty)``
+ *
+ * This routine notifies the @tty driver that it should stop outputting
* characters to the tty device.
*
- * Called with ->flow.lock held. Serialized with stop() method.
+ * Called with @tty->flow.lock held. Serialized with @start() method.
+ *
+ * Optional. Always invoke via stop_tty().
+ *
+ * @start: ``void ()(struct tty_struct *tty)``
+ *
+ * This routine notifies the @tty driver that it resumed sending
+ * characters to the @tty device.
+ *
+ * Called with @tty->flow.lock held. Serialized with stop() method.
+ *
+ * Optional. Always invoke via start_tty().
+ *
+ * @hangup: ``void ()(struct tty_struct *tty)``
+ *
+ * This routine notifies the @tty driver that it should hang up the @tty
+ * device.
*
- * Optional:
+ * Optional. Called with tty lock held.
*
- * Note: Call start_tty not this method.
- *
- * void (*hangup)(struct tty_struct *tty);
+ * @break_ctl: ``int ()(struct tty_struct *tty, int state)``
*
- * This routine notifies the tty driver that it should hang up the
- * tty device.
+ * This optional routine requests the @tty driver to turn on or off BREAK
+ * status on the RS-232 port. If @state is -1, then the BREAK status
+ * should be turned on; if @state is 0, then BREAK should be turned off.
*
- * Optional:
+ * If this routine is implemented, the high-level tty driver will handle
+ * the following ioctls: %TCSBRK, %TCSBRKP, %TIOCSBRK, %TIOCCBRK.
*
- * Called with tty lock held.
+ * If the driver sets %TTY_DRIVER_HARDWARE_BREAK in tty_alloc_driver(),
+ * then the interface will also be called with actual times and the
+ * hardware is expected to do the delay work itself. 0 and -1 are still
+ * used for on/off.
*
- * int (*break_ctl)(struct tty_struct *tty, int state);
+ * Optional: Required for %TCSBRK/%BRKP/etc. handling. May sleep.
*
- * This optional routine requests the tty driver to turn on or
- * off BREAK status on the RS-232 port. If state is -1,
- * then the BREAK status should be turned on; if state is 0, then
- * BREAK should be turned off.
+ * @flush_buffer: ``void ()(struct tty_struct *tty)``
*
- * If this routine is implemented, the high-level tty driver will
- * handle the following ioctls: TCSBRK, TCSBRKP, TIOCSBRK,
- * TIOCCBRK.
+ * This routine discards device private output buffer. Invoked on close,
+ * hangup, to implement %TCOFLUSH ioctl and similar.
*
- * If the driver sets TTY_DRIVER_HARDWARE_BREAK then the interface
- * will also be called with actual times and the hardware is expected
- * to do the delay work itself. 0 and -1 are still used for on/off.
+ * Optional: if not provided, it is assumed there is no queue on the
+ * device. Do not call this function directly, call
+ * tty_driver_flush_buffer().
*
- * Optional: Required for TCSBRK/BRKP/etc handling.
+ * @wait_until_sent: ``void ()(struct tty_struct *tty, int timeout)``
*
- * void (*wait_until_sent)(struct tty_struct *tty, int timeout);
- *
- * This routine waits until the device has written out all of the
- * characters in its transmitter FIFO.
+ * This routine waits until the device has written out all of the
+ * characters in its transmitter FIFO. Or until @timeout (in jiffies) is
+ * reached.
*
- * Optional: If not provided the device is assumed to have no FIFO
+ * Optional: If not provided, the device is assumed to have no FIFO.
+ * Usually correct to invoke via tty_wait_until_sent(). May sleep.
*
- * Note: Usually correct to call tty_wait_until_sent
+ * @send_xchar: ``void ()(struct tty_struct *tty, char ch)``
*
- * void (*send_xchar)(struct tty_struct *tty, char ch);
+ * This routine is used to send a high-priority XON/XOFF character (@ch)
+ * to the @tty device.
*
- * This routine is used to send a high-priority XON/XOFF
- * character to the device.
+ * Optional: If not provided, then the @write method is called under
+ * the @tty->atomic_write_lock to keep it serialized with the ldisc.
*
- * Optional: If not provided then the write method is called under
- * the atomic write lock to keep it serialized with the ldisc.
+ * @tiocmget: ``int ()(struct tty_struct *tty)``
*
- * int (*resize)(struct tty_struct *tty, struct winsize *ws)
+ * This routine is used to obtain the modem status bits from the @tty
+ * driver.
*
- * Called when a termios request is issued which changes the
- * requested terminal geometry.
+ * Optional: If not provided, then %ENOTTY is returned from the %TIOCMGET
+ * ioctl. Do not call this function directly, call tty_tiocmget().
+ *
+ * @tiocmset: ``int ()(struct tty_struct *tty,
+ * unsigned int set, unsigned int clear)``
+ *
+ * This routine is used to set the modem status bits to the @tty driver.
+ * First, @clear bits should be cleared, then @set bits set.
+ *
+ * Optional: If not provided, then %ENOTTY is returned from the %TIOCMSET
+ * ioctl. Do not call this function directly, call tty_tiocmset().
+ *
+ * @resize: ``int ()(struct tty_struct *tty, struct winsize *ws)``
+ *
+ * Called when a termios request is issued which changes the requested
+ * terminal geometry to @ws.
*
* Optional: the default action is to update the termios structure
* without error. This is usually the correct behaviour. Drivers should
- * not force errors here if they are not resizable objects (eg a serial
+ * not force errors here if they are not resizable objects (e.g. a serial
* line). See tty_do_resize() if you need to wrap the standard method
- * in your own logic - the usual case.
+ * in your own logic -- the usual case.
+ *
+ * @get_icount: ``int ()(struct tty_struct *tty,
+ * struct serial_icounter *icount)``
+ *
+ * Called when the @tty device receives a %TIOCGICOUNT ioctl. Passed a
+ * kernel structure @icount to complete.
+ *
+ * Optional: called only if provided, otherwise %ENOTTY will be returned.
*
- * int (*get_icount)(struct tty_struct *tty, struct serial_icounter *icount);
+ * @get_serial: ``int ()(struct tty_struct *tty, struct serial_struct *p)``
*
- * Called when the device receives a TIOCGICOUNT ioctl. Passed a kernel
- * structure to complete. This method is optional and will only be called
- * if provided (otherwise ENOTTY will be returned).
+ * Called when the @tty device receives a %TIOCGSERIAL ioctl. Passed a
+ * kernel structure @p (&struct serial_struct) to complete.
+ *
+ * Optional: called only if provided, otherwise %ENOTTY will be returned.
+ * Do not call this function directly, call tty_tiocgserial().
+ *
+ * @set_serial: ``int ()(struct tty_struct *tty, struct serial_struct *p)``
+ *
+ * Called when the @tty device receives a %TIOCSSERIAL ioctl. Passed a
+ * kernel structure @p (&struct serial_struct) to set the values from.
+ *
+ * Optional: called only if provided, otherwise %ENOTTY will be returned.
+ * Do not call this function directly, call tty_tiocsserial().
+ *
+ * @show_fdinfo: ``void ()(struct tty_struct *tty, struct seq_file *m)``
+ *
+ * Called when the @tty device file descriptor receives a fdinfo request
+ * from VFS (to show in /proc/<pid>/fdinfo/). @m should be filled with
+ * information.
+ *
+ * Optional: called only if provided, otherwise nothing is written to @m.
+ * Do not call this function directly, call tty_show_fdinfo().
+ *
+ * @poll_init: ``int ()(struct tty_driver *driver, int line, char *options)``
+ *
+ * kgdboc support (Documentation/dev-tools/kgdb.rst). This routine is
+ * called to initialize the HW for later use by calling @poll_get_char or
+ * @poll_put_char.
+ *
+ * Optional: called only if provided, otherwise skipped as a non-polling
+ * driver.
+ *
+ * @poll_get_char: ``int ()(struct tty_driver *driver, int line)``
+ *
+ * kgdboc support (see @poll_init). @driver should read a character from a
+ * tty identified by @line and return it.
+ *
+ * Optional: called only if @poll_init provided.
+ *
+ * @poll_put_char: ``void ()(struct tty_driver *driver, int line, char ch)``
+ *
+ * kgdboc support (see @poll_init). @driver should write character @ch to
+ * a tty identified by @line.
+ *
+ * Optional: called only if @poll_init provided.
+ *
+ * @proc_show: ``int ()(struct seq_file *m, void *driver)``
+ *
+ * Driver @driver (cast to &struct tty_driver) can show additional info in
+ * /proc/tty/driver/<driver_name>. It is enough to fill in the information
+ * into @m.
+ *
+ * Optional: called only if provided, otherwise no /proc entry created.
+ *
+ * This structure defines the interface between the low-level tty driver and
+ * the tty routines. These routines can be defined. Unless noted otherwise,
+ * they are optional, and can be filled in with a %NULL pointer.
*/
-
-#include <linux/export.h>
-#include <linux/fs.h>
-#include <linux/kref.h>
-#include <linux/list.h>
-#include <linux/cdev.h>
-#include <linux/termios.h>
-#include <linux/seq_file.h>
-
-struct tty_struct;
-struct tty_driver;
-struct serial_icounter_struct;
-struct serial_struct;
-
struct tty_operations {
struct tty_struct * (*lookup)(struct tty_driver *driver,
struct file *filp, int idx);
@@ -288,26 +390,64 @@ struct tty_operations {
int (*poll_get_char)(struct tty_driver *driver, int line);
void (*poll_put_char)(struct tty_driver *driver, int line, char ch);
#endif
- int (*proc_show)(struct seq_file *, void *);
+ int (*proc_show)(struct seq_file *m, void *driver);
} __randomize_layout;
+/**
+ * struct tty_driver -- driver for TTY devices
+ *
+ * @magic: set to %TTY_DRIVER_MAGIC in __tty_alloc_driver()
+ * @kref: reference counting. Reaching zero frees all the internals and the
+ * driver.
+ * @cdevs: allocated/registered character /dev devices
+ * @owner: modules owning this driver. Used drivers cannot be rmmod'ed.
+ * Automatically set by tty_alloc_driver().
+ * @driver_name: name of the driver used in /proc/tty
+ * @name: used for constructing /dev node name
+ * @name_base: used as a number base for constructing /dev node name
+ * @major: major /dev device number (zero for autoassignment)
+ * @minor_start: the first minor /dev device number
+ * @num: number of devices allocated
+ * @type: type of tty driver (%TTY_DRIVER_TYPE_)
+ * @subtype: subtype of tty driver (%SYSTEM_TYPE_, %PTY_TYPE_, %SERIAL_TYPE_)
+ * @init_termios: termios to set to each tty initially (e.g. %tty_std_termios)
+ * @flags: tty driver flags (%TTY_DRIVER_)
+ * @proc_entry: proc fs entry, used internally
+ * @other: driver of the linked tty; only used for the PTY driver
+ * @ttys: array of active &struct tty_struct, set by tty_standard_install()
+ * @ports: array of &struct tty_port; can be set during initialization by
+ * tty_port_link_device() and similar
+ * @termios: storage for termios at each TTY close for the next open
+ * @driver_state: pointer to driver's arbitrary data
+ * @ops: driver hooks for TTYs. Set them using tty_set_operations(). Use &struct
+ * tty_port helpers in them as much as possible.
+ * @tty_drivers: used internally to link tty_drivers together
+ *
+ * The usual handling of &struct tty_driver is to allocate it by
+ * tty_alloc_driver(), set up all the necessary members, and register it by
+ * tty_register_driver(). At last, the driver is torn down by calling
+ * tty_unregister_driver() followed by tty_driver_kref_put().
+ *
+ * The fields required to be set before calling tty_register_driver() include
+ * @driver_name, @name, @type, @subtype, @init_termios, and @ops.
+ */
struct tty_driver {
- int magic; /* magic number for this structure */
- struct kref kref; /* Reference management */
+ int magic;
+ struct kref kref;
struct cdev **cdevs;
struct module *owner;
const char *driver_name;
const char *name;
- int name_base; /* offset of printed name */
- int major; /* major device number */
- int minor_start; /* start of minor device number */
- unsigned int num; /* number of devices allocated */
- short type; /* type of tty driver */
- short subtype; /* subtype of tty driver */
- struct ktermios init_termios; /* Initial termios */
- unsigned long flags; /* tty driver flags */
- struct proc_dir_entry *proc_entry; /* /proc fs entry */
- struct tty_driver *other; /* only used for the PTY driver */
+ int name_base;
+ int major;
+ int minor_start;
+ unsigned int num;
+ short type;
+ short subtype;
+ struct ktermios init_termios;
+ unsigned long flags;
+ struct proc_dir_entry *proc_entry;
+ struct tty_driver *other;
/*
* Pointer to the tty data structures
@@ -352,49 +492,53 @@ static inline void tty_set_operations(struct tty_driver *driver,
/* tty driver magic number */
#define TTY_DRIVER_MAGIC 0x5402
-/*
- * tty driver flags
- *
- * TTY_DRIVER_RESET_TERMIOS --- requests the tty layer to reset the
- * termios setting when the last process has closed the device.
- * Used for PTY's, in particular.
- *
- * TTY_DRIVER_REAL_RAW --- if set, indicates that the driver will
- * guarantee never to set any special character handling
- * flags if ((IGNBRK || (!BRKINT && !PARMRK)) && (IGNPAR ||
- * !INPCK)). That is, if there is no reason for the driver to
- * send notifications of parity and break characters up to the
- * line driver, it won't do so. This allows the line driver to
- * optimize for this case if this flag is set. (Note that there
- * is also a promise, if the above case is true, not to signal
- * overruns, either.)
- *
- * TTY_DRIVER_DYNAMIC_DEV --- if set, the individual tty devices need
- * to be registered with a call to tty_register_device() when the
- * device is found in the system and unregistered with a call to
- * tty_unregister_device() so the devices will be show up
- * properly in sysfs. If not set, driver->num entries will be
- * created by the tty core in sysfs when tty_register_driver() is
- * called. This is to be used by drivers that have tty devices
- * that can appear and disappear while the main tty driver is
- * registered with the tty core.
- *
- * TTY_DRIVER_DEVPTS_MEM -- don't use the standard arrays, instead
- * use dynamic memory keyed through the devpts filesystem. This
- * is only applicable to the pty driver.
- *
- * TTY_DRIVER_HARDWARE_BREAK -- hardware handles break signals. Pass
- * the requested timeout to the caller instead of using a simple
- * on/off interface.
- *
- * TTY_DRIVER_DYNAMIC_ALLOC -- do not allocate structures which are
- * needed per line for this driver as it would waste memory.
- * The driver will take care.
- *
- * TTY_DRIVER_UNNUMBERED_NODE -- do not create numbered /dev nodes. In
- * other words create /dev/ttyprintk and not /dev/ttyprintk0.
- * Applicable only when a driver for a single tty device is
- * being allocated.
+/**
+ * DOC: TTY Driver Flags
+ *
+ * TTY_DRIVER_RESET_TERMIOS
+ * Requests the tty layer to reset the termios setting when the last
+ * process has closed the device. Used for PTYs, in particular.
+ *
+ * TTY_DRIVER_REAL_RAW
+ * Indicates that the driver will guarantee not to set any special
+ * character handling flags if this is set for the tty:
+ *
+ * ``(IGNBRK || (!BRKINT && !PARMRK)) && (IGNPAR || !INPCK)``
+ *
+ * That is, if there is no reason for the driver to
+ * send notifications of parity and break characters up to the line
+ * driver, it won't do so. This allows the line driver to optimize for
+ * this case if this flag is set. (Note that there is also a promise, if
+ * the above case is true, not to signal overruns, either.)
+ *
+ * TTY_DRIVER_DYNAMIC_DEV
+ * The individual tty devices need to be registered with a call to
+ * tty_register_device() when the device is found in the system and
+ * unregistered with a call to tty_unregister_device() so the devices will
+ * be show up properly in sysfs. If not set, all &tty_driver.num entries
+ * will be created by the tty core in sysfs when tty_register_driver() is
+ * called. This is to be used by drivers that have tty devices that can
+ * appear and disappear while the main tty driver is registered with the
+ * tty core.
+ *
+ * TTY_DRIVER_DEVPTS_MEM
+ * Don't use the standard arrays (&tty_driver.ttys and
+ * &tty_driver.termios), instead use dynamic memory keyed through the
+ * devpts filesystem. This is only applicable to the PTY driver.
+ *
+ * TTY_DRIVER_HARDWARE_BREAK
+ * Hardware handles break signals. Pass the requested timeout to the
+ * &tty_operations.break_ctl instead of using a simple on/off interface.
+ *
+ * TTY_DRIVER_DYNAMIC_ALLOC
+ * Do not allocate structures which are needed per line for this driver
+ * (&tty_driver.ports) as it would waste memory. The driver will take
+ * care. This is only applicable to the PTY driver.
+ *
+ * TTY_DRIVER_UNNUMBERED_NODE
+ * Do not create numbered ``/dev`` nodes. For example, create
+ * ``/dev/ttyprintk`` and not ``/dev/ttyprintk0``. Applicable only when a
+ * driver for a single tty device is being allocated.
*/
#define TTY_DRIVER_INSTALLED 0x0001
#define TTY_DRIVER_RESET_TERMIOS 0x0002
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
index 9916acb5de49..483d41cbcbb7 100644
--- a/include/linux/tty_flip.h
+++ b/include/linux/tty_flip.h
@@ -17,7 +17,6 @@ int tty_insert_flip_string_fixed_flag(struct tty_port *port,
int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars,
size_t size);
void tty_flip_buffer_push(struct tty_port *port);
-void tty_schedule_flip(struct tty_port *port);
int __tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag);
static inline int tty_insert_flip_char(struct tty_port *port,
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index b85d84fb5f49..e85002b56752 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -4,127 +4,6 @@
struct tty_struct;
-/*
- * This structure defines the interface between the tty line discipline
- * implementation and the tty routines. The following routines can be
- * defined; unless noted otherwise, they are optional, and can be
- * filled in with a null pointer.
- *
- * int (*open)(struct tty_struct *);
- *
- * This function is called when the line discipline is associated
- * with the tty. The line discipline can use this as an
- * opportunity to initialize any state needed by the ldisc routines.
- *
- * void (*close)(struct tty_struct *);
- *
- * This function is called when the line discipline is being
- * shutdown, either because the tty is being closed or because
- * the tty is being changed to use a new line discipline
- *
- * void (*flush_buffer)(struct tty_struct *tty);
- *
- * This function instructs the line discipline to clear its
- * buffers of any input characters it may have queued to be
- * delivered to the user mode process.
- *
- * ssize_t (*read)(struct tty_struct * tty, struct file * file,
- * unsigned char * buf, size_t nr);
- *
- * This function is called when the user requests to read from
- * the tty. The line discipline will return whatever characters
- * it has buffered up for the user. If this function is not
- * defined, the user will receive an EIO error.
- *
- * ssize_t (*write)(struct tty_struct * tty, struct file * file,
- * const unsigned char * buf, size_t nr);
- *
- * This function is called when the user requests to write to the
- * tty. The line discipline will deliver the characters to the
- * low-level tty device for transmission, optionally performing
- * some processing on the characters first. If this function is
- * not defined, the user will receive an EIO error.
- *
- * int (*ioctl)(struct tty_struct * tty, struct file * file,
- * unsigned int cmd, unsigned long arg);
- *
- * This function is called when the user requests an ioctl which
- * is not handled by the tty layer or the low-level tty driver.
- * It is intended for ioctls which affect line discpline
- * operation. Note that the search order for ioctls is (1) tty
- * layer, (2) tty low-level driver, (3) line discpline. So a
- * low-level driver can "grab" an ioctl request before the line
- * discpline has a chance to see it.
- *
- * int (*compat_ioctl)(struct tty_struct * tty, struct file * file,
- * unsigned int cmd, unsigned long arg);
- *
- * Process ioctl calls from 32-bit process on 64-bit system
- *
- * NOTE: only ioctls that are neither "pointer to compatible
- * structure" nor tty-generic. Something private that takes
- * an integer or a pointer to wordsize-sensitive structure
- * belongs here, but most of ldiscs will happily leave
- * it NULL.
- *
- * void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
- *
- * This function notifies the line discpline that a change has
- * been made to the termios structure.
- *
- * int (*poll)(struct tty_struct * tty, struct file * file,
- * poll_table *wait);
- *
- * This function is called when a user attempts to select/poll on a
- * tty device. It is solely the responsibility of the line
- * discipline to handle poll requests.
- *
- * void (*receive_buf)(struct tty_struct *, const unsigned char *cp,
- * char *fp, int count);
- *
- * This function is called by the low-level tty driver to send
- * characters received by the hardware to the line discpline for
- * processing. <cp> is a pointer to the buffer of input
- * character received by the device. <fp> is a pointer to a
- * pointer of flag bytes which indicate whether a character was
- * received with a parity error, etc. <fp> may be NULL to indicate
- * all data received is TTY_NORMAL.
- *
- * void (*write_wakeup)(struct tty_struct *);
- *
- * This function is called by the low-level tty driver to signal
- * that line discpline should try to send more characters to the
- * low-level driver for transmission. If the line discpline does
- * not have any more data to send, it can just return. If the line
- * discipline does have some data to send, please arise a tasklet
- * or workqueue to do the real data transfer. Do not send data in
- * this hook, it may leads to a deadlock.
- *
- * int (*hangup)(struct tty_struct *)
- *
- * Called on a hangup. Tells the discipline that it should
- * cease I/O to the tty driver. Can sleep. The driver should
- * seek to perform this action quickly but should wait until
- * any pending driver I/O is completed.
- *
- * void (*dcd_change)(struct tty_struct *tty, unsigned int status)
- *
- * Tells the discipline that the DCD pin has changed its status.
- * Used exclusively by the N_PPS (Pulse-Per-Second) line discipline.
- *
- * int (*receive_buf2)(struct tty_struct *, const unsigned char *cp,
- * char *fp, int count);
- *
- * This function is called by the low-level tty driver to send
- * characters received by the hardware to the line discpline for
- * processing. <cp> is a pointer to the buffer of input
- * character received by the device. <fp> is a pointer to a
- * pointer of flag bytes which indicate whether a character was
- * received with a parity error, etc. <fp> may be NULL to indicate
- * all data received is TTY_NORMAL.
- * If assigned, prefer this function for automatic flow control.
- */
-
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/atomic.h>
@@ -176,7 +55,147 @@ int ldsem_down_write_nested(struct ld_semaphore *sem, int subclass,
ldsem_down_write(sem, timeout)
#endif
-
+/**
+ * struct tty_ldisc_ops - ldisc operations
+ *
+ * @name: name of this ldisc rendered in /proc/tty/ldiscs
+ * @num: ``N_*`` number (%N_TTY, %N_HDLC, ...) reserved to this ldisc
+ *
+ * @open: [TTY] ``int ()(struct tty_struct *tty)``
+ *
+ * This function is called when the line discipline is associated with the
+ * @tty. No other call into the line discipline for this tty will occur
+ * until it completes successfully. It should initialize any state needed
+ * by the ldisc, and set @tty->receive_room to the maximum amount of data
+ * the line discipline is willing to accept from the driver with a single
+ * call to @receive_buf(). Returning an error will prevent the ldisc from
+ * being attached.
+ *
+ * Can sleep.
+ *
+ * @close: [TTY] ``void ()(struct tty_struct *tty)``
+ *
+ * This function is called when the line discipline is being shutdown,
+ * either because the @tty is being closed or because the @tty is being
+ * changed to use a new line discipline. At the point of execution no
+ * further users will enter the ldisc code for this tty.
+ *
+ * Can sleep.
+ *
+ * @flush_buffer: [TTY] ``void ()(struct tty_struct *tty)``
+ *
+ * This function instructs the line discipline to clear its buffers of any
+ * input characters it may have queued to be delivered to the user mode
+ * process. It may be called at any point between open and close.
+ *
+ * @read: [TTY] ``ssize_t ()(struct tty_struct *tty, struct file *file,
+ * unsigned char *buf, size_t nr)``
+ *
+ * This function is called when the user requests to read from the @tty.
+ * The line discipline will return whatever characters it has buffered up
+ * for the user. If this function is not defined, the user will receive
+ * an %EIO error. Multiple read calls may occur in parallel and the ldisc
+ * must deal with serialization issues.
+ *
+ * Can sleep.
+ *
+ * @write: [TTY] ``ssize_t ()(struct tty_struct *tty, struct file *file,
+ * const unsigned char *buf, size_t nr)``
+ *
+ * This function is called when the user requests to write to the @tty.
+ * The line discipline will deliver the characters to the low-level tty
+ * device for transmission, optionally performing some processing on the
+ * characters first. If this function is not defined, the user will
+ * receive an %EIO error.
+ *
+ * Can sleep.
+ *
+ * @ioctl: [TTY] ``int ()(struct tty_struct *tty, unsigned int cmd,
+ * unsigned long arg)``
+ *
+ * This function is called when the user requests an ioctl which is not
+ * handled by the tty layer or the low-level tty driver. It is intended
+ * for ioctls which affect line discpline operation. Note that the search
+ * order for ioctls is (1) tty layer, (2) tty low-level driver, (3) line
+ * discpline. So a low-level driver can "grab" an ioctl request before
+ * the line discpline has a chance to see it.
+ *
+ * @compat_ioctl: [TTY] ``int ()(struct tty_struct *tty, unsigned int cmd,
+ * unsigned long arg)``
+ *
+ * Process ioctl calls from 32-bit process on 64-bit system.
+ *
+ * Note that only ioctls that are neither "pointer to compatible
+ * structure" nor tty-generic. Something private that takes an integer or
+ * a pointer to wordsize-sensitive structure belongs here, but most of
+ * ldiscs will happily leave it %NULL.
+ *
+ * @set_termios: [TTY] ``void ()(struct tty_struct *tty, struct ktermios *old)``
+ *
+ * This function notifies the line discpline that a change has been made
+ * to the termios structure.
+ *
+ * @poll: [TTY] ``int ()(struct tty_struct *tty, struct file *file,
+ * struct poll_table_struct *wait)``
+ *
+ * This function is called when a user attempts to select/poll on a @tty
+ * device. It is solely the responsibility of the line discipline to
+ * handle poll requests.
+ *
+ * @hangup: [TTY] ``void ()(struct tty_struct *tty)``
+ *
+ * Called on a hangup. Tells the discipline that it should cease I/O to
+ * the tty driver. The driver should seek to perform this action quickly
+ * but should wait until any pending driver I/O is completed. No further
+ * calls into the ldisc code will occur.
+ *
+ * Can sleep.
+ *
+ * @receive_buf: [DRV] ``void ()(struct tty_struct *tty,
+ * const unsigned char *cp, const char *fp, int count)``
+ *
+ * This function is called by the low-level tty driver to send characters
+ * received by the hardware to the line discpline for processing. @cp is
+ * a pointer to the buffer of input character received by the device. @fp
+ * is a pointer to an array of flag bytes which indicate whether a
+ * character was received with a parity error, etc. @fp may be %NULL to
+ * indicate all data received is %TTY_NORMAL.
+ *
+ * @write_wakeup: [DRV] ``void ()(struct tty_struct *tty)``
+ *
+ * This function is called by the low-level tty driver to signal that line
+ * discpline should try to send more characters to the low-level driver
+ * for transmission. If the line discpline does not have any more data to
+ * send, it can just return. If the line discipline does have some data to
+ * send, please arise a tasklet or workqueue to do the real data transfer.
+ * Do not send data in this hook, it may lead to a deadlock.
+ *
+ * @dcd_change: [DRV] ``void ()(struct tty_struct *tty, unsigned int status)``
+ *
+ * Tells the discipline that the DCD pin has changed its status. Used
+ * exclusively by the %N_PPS (Pulse-Per-Second) line discipline.
+ *
+ * @receive_buf2: [DRV] ``int ()(struct tty_struct *tty,
+ * const unsigned char *cp, const char *fp, int count)``
+ *
+ * This function is called by the low-level tty driver to send characters
+ * received by the hardware to the line discpline for processing. @cp is a
+ * pointer to the buffer of input character received by the device. @fp
+ * is a pointer to an array of flag bytes which indicate whether a
+ * character was received with a parity error, etc. @fp may be %NULL to
+ * indicate all data received is %TTY_NORMAL. If assigned, prefer this
+ * function for automatic flow control.
+ *
+ * @owner: module containting this ldisc (for reference counting)
+ *
+ * This structure defines the interface between the tty line discipline
+ * implementation and the tty routines. The above routines can be defined.
+ * Unless noted otherwise, they are optional, and can be filled in with a %NULL
+ * pointer.
+ *
+ * Hooks marked [TTY] are invoked from the TTY core, the [DRV] ones from the
+ * tty_driver side.
+ */
struct tty_ldisc_ops {
char *name;
int num;
@@ -184,31 +203,31 @@ struct tty_ldisc_ops {
/*
* The following routines are called from above.
*/
- int (*open)(struct tty_struct *);
- void (*close)(struct tty_struct *);
+ int (*open)(struct tty_struct *tty);
+ void (*close)(struct tty_struct *tty);
void (*flush_buffer)(struct tty_struct *tty);
ssize_t (*read)(struct tty_struct *tty, struct file *file,
unsigned char *buf, size_t nr,
void **cookie, unsigned long offset);
ssize_t (*write)(struct tty_struct *tty, struct file *file,
const unsigned char *buf, size_t nr);
- int (*ioctl)(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg);
- int (*compat_ioctl)(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg);
+ int (*ioctl)(struct tty_struct *tty, unsigned int cmd,
+ unsigned long arg);
+ int (*compat_ioctl)(struct tty_struct *tty, unsigned int cmd,
+ unsigned long arg);
void (*set_termios)(struct tty_struct *tty, struct ktermios *old);
- __poll_t (*poll)(struct tty_struct *, struct file *,
- struct poll_table_struct *);
+ __poll_t (*poll)(struct tty_struct *tty, struct file *file,
+ struct poll_table_struct *wait);
void (*hangup)(struct tty_struct *tty);
/*
* The following routines are called from below.
*/
- void (*receive_buf)(struct tty_struct *, const unsigned char *cp,
+ void (*receive_buf)(struct tty_struct *tty, const unsigned char *cp,
const char *fp, int count);
- void (*write_wakeup)(struct tty_struct *);
- void (*dcd_change)(struct tty_struct *, unsigned int);
- int (*receive_buf2)(struct tty_struct *, const unsigned char *cp,
+ void (*write_wakeup)(struct tty_struct *tty);
+ void (*dcd_change)(struct tty_struct *tty, unsigned int status);
+ int (*receive_buf2)(struct tty_struct *tty, const unsigned char *cp,
const char *fp, int count);
struct module *owner;
diff --git a/include/linux/tty_port.h b/include/linux/tty_port.h
index 6e86e9e118b6..d3ea9ed0b98e 100644
--- a/include/linux/tty_port.h
+++ b/include/linux/tty_port.h
@@ -7,37 +7,33 @@
#include <linux/tty_buffer.h>
#include <linux/wait.h>
-/*
- * Port level information. Each device keeps its own port level information
- * so provide a common structure for those ports wanting to use common support
- * routines.
- *
- * The tty port has a different lifetime to the tty so must be kept apart.
- * In addition be careful as tty -> port mappings are valid for the life
- * of the tty object but in many cases port -> tty mappings are valid only
- * until a hangup so don't use the wrong path.
- */
-
struct attribute_group;
struct tty_driver;
struct tty_port;
struct tty_struct;
+/**
+ * struct tty_port_operations -- operations on tty_port
+ * @carrier_raised: return 1 if the carrier is raised on @port
+ * @dtr_rts: raise the DTR line if @raise is nonzero, otherwise lower DTR
+ * @shutdown: called when the last close completes or a hangup finishes IFF the
+ * port was initialized. Do not use to free resources. Turn off the device
+ * only. Called under the port mutex to serialize against @activate and
+ * @shutdown.
+ * @activate: called under the port mutex from tty_port_open(), serialized using
+ * the port mutex. Supposed to turn on the device.
+ *
+ * FIXME: long term getting the tty argument *out* of this would be good
+ * for consoles.
+ *
+ * @destruct: called on the final put of a port. Free resources, possibly incl.
+ * the port itself.
+ */
struct tty_port_operations {
- /* Return 1 if the carrier is raised */
int (*carrier_raised)(struct tty_port *port);
- /* Control the DTR line */
void (*dtr_rts)(struct tty_port *port, int raise);
- /* Called when the last close completes or a hangup finishes
- IFF the port was initialized. Do not use to free resources. Called
- under the port mutex to serialize against activate/shutdowns */
void (*shutdown)(struct tty_port *port);
- /* Called under the port mutex from tty_port_open, serialized using
- the port mutex */
- /* FIXME: long term getting the tty argument *out* of this would be
- good for consoles */
int (*activate)(struct tty_port *port, struct tty_struct *tty);
- /* Called on the final put of a port */
void (*destruct)(struct tty_port *port);
};
@@ -48,30 +44,77 @@ struct tty_port_client_operations {
extern const struct tty_port_client_operations tty_port_default_client_ops;
+/**
+ * struct tty_port -- port level information
+ *
+ * @buf: buffer for this port, locked internally
+ * @tty: back pointer to &struct tty_struct, valid only if the tty is open. Use
+ * tty_port_tty_get() to obtain it (and tty_kref_put() to release).
+ * @itty: internal back pointer to &struct tty_struct. Avoid this. It should be
+ * eliminated in the long term.
+ * @ops: tty port operations (like activate, shutdown), see &struct
+ * tty_port_operations
+ * @client_ops: tty port client operations (like receive_buf, write_wakeup).
+ * By default, tty_port_default_client_ops is used.
+ * @lock: lock protecting @tty
+ * @blocked_open: # of procs waiting for open in tty_port_block_til_ready()
+ * @count: usage count
+ * @open_wait: open waiters queue (waiting e.g. for a carrier)
+ * @delta_msr_wait: modem status change queue (waiting for MSR changes)
+ * @flags: user TTY flags (%ASYNC_)
+ * @iflags: internal flags (%TTY_PORT_)
+ * @console: when set, the port is a console
+ * @mutex: locking, for open, shutdown and other port operations
+ * @buf_mutex: @xmit_buf alloc lock
+ * @xmit_buf: optional xmit buffer used by some drivers
+ * @close_delay: delay in jiffies to wait when closing the port
+ * @closing_wait: delay in jiffies for output to be sent before closing
+ * @drain_delay: set to zero if no pure time based drain is needed else set to
+ * size of fifo
+ * @kref: references counter. Reaching zero calls @ops->destruct() if non-%NULL
+ * or frees the port otherwise.
+ * @client_data: pointer to private data, for @client_ops
+ *
+ * Each device keeps its own port level information. &struct tty_port was
+ * introduced as a common structure for such information. As every TTY device
+ * shall have a backing tty_port structure, every driver can use these members.
+ *
+ * The tty port has a different lifetime to the tty so must be kept apart.
+ * In addition be careful as tty -> port mappings are valid for the life
+ * of the tty object but in many cases port -> tty mappings are valid only
+ * until a hangup so don't use the wrong path.
+ *
+ * Tty port shall be initialized by tty_port_init() and shut down either by
+ * tty_port_destroy() (refcounting not used), or tty_port_put() (refcounting).
+ *
+ * There is a lot of helpers around &struct tty_port too. To name the most
+ * significant ones: tty_port_open(), tty_port_close() (or
+ * tty_port_close_start() and tty_port_close_end() separately if need be), and
+ * tty_port_hangup(). These call @ops->activate() and @ops->shutdown() as
+ * needed.
+ */
struct tty_port {
- struct tty_bufhead buf; /* Locked internally */
- struct tty_struct *tty; /* Back pointer */
- struct tty_struct *itty; /* internal back ptr */
- const struct tty_port_operations *ops; /* Port operations */
- const struct tty_port_client_operations *client_ops; /* Port client operations */
- spinlock_t lock; /* Lock protecting tty field */
- int blocked_open; /* Waiting to open */
- int count; /* Usage count */
- wait_queue_head_t open_wait; /* Open waiters */
- wait_queue_head_t delta_msr_wait; /* Modem status change */
- unsigned long flags; /* User TTY flags ASYNC_ */
- unsigned long iflags; /* Internal flags TTY_PORT_ */
- unsigned char console:1; /* port is a console */
- struct mutex mutex; /* Locking */
- struct mutex buf_mutex; /* Buffer alloc lock */
- unsigned char *xmit_buf; /* Optional buffer */
- unsigned int close_delay; /* Close port delay */
- unsigned int closing_wait; /* Delay for output */
- int drain_delay; /* Set to zero if no pure time
- based drain is needed else
- set to size of fifo */
- struct kref kref; /* Ref counter */
- void *client_data;
+ struct tty_bufhead buf;
+ struct tty_struct *tty;
+ struct tty_struct *itty;
+ const struct tty_port_operations *ops;
+ const struct tty_port_client_operations *client_ops;
+ spinlock_t lock;
+ int blocked_open;
+ int count;
+ wait_queue_head_t open_wait;
+ wait_queue_head_t delta_msr_wait;
+ unsigned long flags;
+ unsigned long iflags;
+ unsigned char console:1;
+ struct mutex mutex;
+ struct mutex buf_mutex;
+ unsigned char *xmit_buf;
+ unsigned int close_delay;
+ unsigned int closing_wait;
+ int drain_delay;
+ struct kref kref;
+ void *client_data;
};
/* tty_port::iflags bits -- use atomic bit ops */
diff --git a/net/nfc/nci/uart.c b/net/nfc/nci/uart.c
index c027c76d493c..cc8fa9e36159 100644
--- a/net/nfc/nci/uart.c
+++ b/net/nfc/nci/uart.c
@@ -317,14 +317,13 @@ static void nci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
* Arguments:
*
* tty pointer to tty instance data
- * file pointer to open file object for device
* cmd IOCTL command code
* arg argument for IOCTL call (cmd dependent)
*
* Return Value: Command dependent
*/
-static int nci_uart_tty_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int nci_uart_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
+ unsigned long arg)
{
struct nci_uart *nu = (void *)tty->disc_data;
int err = 0;