Pull tty / serial updates from Greg KH: "Here is the big set of tty/serial driver updates for 6.4-rc1. Nothing major, just lots of tiny, constant, forward development. This includes: - obligatory n_gsm updates and feature additions - 8250_em driver updates - sh-sci driver updates - dts cleanups and updates - general cleanups and improvements by Ilpo and Jiri - other small serial driver core fixes and driver updates All of these have been in linux-next for a while with no reported problems" * tag 'tty-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (87 commits) n_gsm: Use array_index_nospec() with index that comes from userspace tty: vt: drop checks for undefined VT_SINGLE_DRIVER tty: vt: distribute EXPORT_SYMBOL() tty: vt: simplify some cases in tioclinux() tty: vt: reformat tioclinux() tty: serial: sh-sci: Fix end of transmission on SCI tty: serial: sh-sci: Add support for tx end interrupt handling tty: serial: sh-sci: Fix TE setting on SCI IP tty: serial: sh-sci: Add RZ/G2L SCIFA DMA rx support tty: serial: sh-sci: Add RZ/G2L SCIFA DMA tx support serial: max310x: fix IO data corruption in batched operations serial: core: Disable uart_start() on uart_remove_one_port() serial: 8250: Reinit port->pm on port specific driver unbind serial: 8250: Add missing wakeup event reporting tty: serial: fsl_lpuart: use UARTMODIR register bits for lpuart32 platform tty: serial: fsl_lpuart: adjust buffer length to the intended size serial: fix TIOCSRS485 locking serial: make SiFive serial drivers depend on ARCH_ symbols tty: synclink_gt: don't allocate and pass dummy flags tty: serial: simplify qcom_geni_serial_send_chunk_fifo() ...
Unified · Split
| @@ -33,8 +33,11 @@ The format of this option is:: · 32 unmodified lines | ||
| 33 | 33 | 9600n8. The maximum baudrate is 115200. |
| 34 | 34 | |
| 35 | 35 | You can specify multiple console= options on the kernel command line. |
| 36 | −Output will appear on all of them. The last device will be used when | |
| 37 | −you open ``/dev/console``. So, for example:: | |
| 36 | + | |
| 37 | +The behavior is well defined when each device type is mentioned only once. | |
| 38 | +In this case, the output will appear on all requested consoles. And | |
| 39 | +the last device will be used when you open ``/dev/console``. | |
| 40 | +So, for example:: | |
| 38 | 41 | |
| 39 | 42 | console=ttyS1,9600 console=tty0 |
| 40 | 43 | |
| @@ -42,7 +45,34 @@ defines that opening ``/dev/console`` will get you the current foreground · 1 unmodified line | ||
| 42 | 45 | virtual console, and kernel messages will appear on both the VGA |
| 43 | 46 | console and the 2nd serial port (ttyS1 or COM2) at 9600 baud. |
| 44 | 47 | |
| 45 | −Note that you can only define one console per device type (serial, video). | |
| 48 | +The behavior is more complicated when the same device type is defined more | |
| 49 | +times. In this case, there are the following two rules: | |
| 50 | + | |
| 51 | +1. The output will appear only on the first device of each defined type. | |
| 52 | + | |
| 53 | +2. ``/dev/console`` will be associated with the first registered device. | |
| 54 | + Where the registration order depends on how kernel initializes various | |
| 55 | + subsystems. | |
| 56 | + | |
| 57 | + This rule is used also when the last console= parameter is not used | |
| 58 | + for other reasons. For example, because of a typo or because | |
| 59 | + the hardware is not available. | |
| 60 | + | |
| 61 | +The result might be surprising. For example, the following two command | |
| 62 | +lines have the same result: | |
| 63 | + | |
| 64 | + console=ttyS1,9600 console=tty0 console=tty1 | |
| 65 | + console=tty0 console=ttyS1,9600 console=tty1 | |
| 66 | + | |
| 67 | +The kernel messages are printed only on ``tty0`` and ``ttyS1``. And | |
| 68 | +``/dev/console`` gets associated with ``tty0``. It is because kernel | |
| 69 | +tries to register graphical consoles before serial ones. It does it | |
| 70 | +because of the default behavior when no console device is specified, | |
| 71 | +see below. | |
| 72 | + | |
| 73 | +Note that the last ``console=tty1`` parameter still makes a difference. | |
| 74 | +The kernel command line is used also by systemd. It would use the last | |
| 75 | +defined ``tty1`` as the login console. | |
| 46 | 76 | |
| 47 | 77 | If no console device is specified, the first device found capable of |
| 48 | 78 | acting as a system console will be used. At this time, the system |
| @@ -2,8 +2,8 @@ · 1 unmodified line | ||
| 2 | 2 | # Copyright 2019 BayLibre, SAS |
| 3 | 3 | %YAML 1.2 |
| 4 | 4 | --- |
| 5 | −$id: "http://devicetree.org/schemas/serial/amlogic,meson-uart.yaml#" | |
| 6 | −$schema: "http://devicetree.org/meta-schemas/core.yaml#" | |
| 5 | +$id: http://devicetree.org/schemas/serial/amlogic,meson-uart.yaml# | |
| 6 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 7 | 7 | |
| 8 | 8 | title: Amlogic Meson SoC UART Serial Interface |
| 9 | 9 | |
| @@ -34,6 +34,11 @@ properties: · 24 unmodified lines | ||
| 34 | 34 | - amlogic,meson-gx-uart |
| 35 | 35 | - amlogic,meson-s4-uart |
| 36 | 36 | - const: amlogic,meson-ao-uart |
| 37 | + - description: Always-on power domain UART controller on G12A SoCs | |
| 38 | + items: | |
| 39 | + - const: amlogic,meson-g12a-uart | |
| 40 | + - const: amlogic,meson-gx-uart | |
| 41 | + - const: amlogic,meson-ao-uart | |
| 37 | 42 | - description: Everything-Else power domain UART controller |
| 38 | 43 | enum: |
| 39 | 44 | - amlogic,meson6-uart |
| @@ -41,6 +46,10 @@ properties: · 1 unmodified line | ||
| 41 | 46 | - amlogic,meson8b-uart |
| 42 | 47 | - amlogic,meson-gx-uart |
| 43 | 48 | - amlogic,meson-s4-uart |
| 49 | + - description: Everything-Else power domain UART controller on G12A SoCs | |
| 50 | + items: | |
| 51 | + - const: amlogic,meson-g12a-uart | |
| 52 | + - const: amlogic,meson-gx-uart | |
| 44 | 53 | |
| 45 | 54 | reg: |
| 46 | 55 | maxItems: 1 |
| @@ -49,6 +49,24 @@ properties: · 48 unmodified lines | ||
| 49 | 49 | reg: |
| 50 | 50 | maxItems: 1 |
| 51 | 51 | |
| 52 | + clocks: | |
| 53 | + maxItems: 2 | |
| 54 | + | |
| 55 | + clock-names: | |
| 56 | + items: | |
| 57 | + - const: ipg | |
| 58 | + - const: per | |
| 59 | + | |
| 60 | + dmas: | |
| 61 | + items: | |
| 62 | + - description: DMA controller phandle and request line for RX | |
| 63 | + - description: DMA controller phandle and request line for TX | |
| 64 | + | |
| 65 | + dma-names: | |
| 66 | + items: | |
| 67 | + - const: rx | |
| 68 | + - const: tx | |
| 69 | + | |
| 52 | 70 | interrupts: |
| 53 | 71 | maxItems: 1 |
| 54 | 72 | |
| @@ -86,12 +104,16 @@ properties: · 31 unmodified lines | ||
| 86 | 104 | required: |
| 87 | 105 | - compatible |
| 88 | 106 | - reg |
| 107 | + - clocks | |
| 108 | + - clock-names | |
| 89 | 109 | - interrupts |
| 90 | 110 | |
| 91 | 111 | unevaluatedProperties: false |
| 92 | 112 | |
| 93 | 113 | examples: |
| 94 | 114 | - | |
| 115 | + #include <dt-bindings/clock/imx5-clock.h> | |
| 116 | + | |
| 95 | 117 | aliases { |
| 96 | 118 | serial0 = &uart1; |
| 97 | 119 | }; |
| @@ -100,6 +122,11 @@ examples: · 2 unmodified lines | ||
| 100 | 122 | compatible = "fsl,imx51-uart", "fsl,imx21-uart"; |
| 101 | 123 | reg = <0x73fbc000 0x4000>; |
| 102 | 124 | interrupts = <31>; |
| 125 | + clocks = <&clks IMX5_CLK_UART1_IPG_GATE>, | |
| 126 | + <&clks IMX5_CLK_UART1_PER_GATE>; | |
| 127 | + clock-names = "ipg", "per"; | |
| 128 | + dmas = <&sdma 18 4 1>, <&sdma 19 4 2>; | |
| 129 | + dma-names = "rx", "tx"; | |
| 103 | 130 | uart-has-rtscts; |
| 104 | 131 | fsl,dte-mode; |
| 105 | 132 | }; |
| @@ -65,6 +65,9 @@ properties: · 64 unmodified lines | ||
| 65 | 65 | - const: rx |
| 66 | 66 | - const: tx |
| 67 | 67 | |
| 68 | + power-domains: | |
| 69 | + maxItems: 1 | |
| 70 | + | |
| 68 | 71 | required: |
| 69 | 72 | - compatible |
| 70 | 73 | - reg |
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
| 2 | 2 | %YAML 1.2 |
| 3 | 3 | --- |
| 4 | −$id: "http://devicetree.org/schemas/serial/qcom,serial-geni-qcom.yaml#" | |
| 5 | −$schema: "http://devicetree.org/meta-schemas/core.yaml#" | |
| 4 | +$id: http://devicetree.org/schemas/serial/qcom,serial-geni-qcom.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | 6 | |
| 7 | 7 | title: Qualcomm Geni based QUP UART interface |
| 8 | 8 | |
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
| 2 | 2 | %YAML 1.2 |
| 3 | 3 | --- |
| 4 | −$id: "http://devicetree.org/schemas/serial/renesas,em-uart.yaml#" | |
| 5 | −$schema: "http://devicetree.org/meta-schemas/core.yaml#" | |
| 4 | +$id: http://devicetree.org/schemas/serial/renesas,em-uart.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | 6 | |
| 7 | 7 | title: Renesas EMMA Mobile UART Interface |
| 8 | 8 | |
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
| 2 | 2 | %YAML 1.2 |
| 3 | 3 | --- |
| 4 | −$id: "http://devicetree.org/schemas/serial/renesas,hscif.yaml#" | |
| 5 | −$schema: "http://devicetree.org/meta-schemas/core.yaml#" | |
| 4 | +$id: http://devicetree.org/schemas/serial/renesas,hscif.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | 6 | |
| 7 | 7 | title: Renesas High Speed Serial Communication Interface with FIFO (HSCIF) |
| 8 | 8 | |
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
| 2 | 2 | %YAML 1.2 |
| 3 | 3 | --- |
| 4 | −$id: "http://devicetree.org/schemas/serial/renesas,sci.yaml#" | |
| 5 | −$schema: "http://devicetree.org/meta-schemas/core.yaml#" | |
| 4 | +$id: http://devicetree.org/schemas/serial/renesas,sci.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | 6 | |
| 7 | 7 | title: Renesas Serial Communication Interface |
| 8 | 8 | |
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
| 2 | 2 | %YAML 1.2 |
| 3 | 3 | --- |
| 4 | −$id: "http://devicetree.org/schemas/serial/renesas,scif.yaml#" | |
| 5 | −$schema: "http://devicetree.org/meta-schemas/core.yaml#" | |
| 4 | +$id: http://devicetree.org/schemas/serial/renesas,scif.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | 6 | |
| 7 | 7 | title: Renesas Serial Communication Interface with FIFO (SCIF) |
| 8 | 8 | |
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
| 2 | 2 | %YAML 1.2 |
| 3 | 3 | --- |
| 4 | −$id: "http://devicetree.org/schemas/serial/renesas,scifa.yaml#" | |
| 5 | −$schema: "http://devicetree.org/meta-schemas/core.yaml#" | |
| 4 | +$id: http://devicetree.org/schemas/serial/renesas,scifa.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | 6 | |
| 7 | 7 | title: Renesas Serial Communications Interface with FIFO A (SCIFA) |
| 8 | 8 | |
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
| 2 | 2 | %YAML 1.2 |
| 3 | 3 | --- |
| 4 | −$id: "http://devicetree.org/schemas/serial/renesas,scifb.yaml#" | |
| 5 | −$schema: "http://devicetree.org/meta-schemas/core.yaml#" | |
| 4 | +$id: http://devicetree.org/schemas/serial/renesas,scifb.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | 6 | |
| 7 | 7 | title: Renesas Serial Communications Interface with FIFO B (SCIFB) |
| 8 | 8 | |
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
| 2 | 2 | %YAML 1.2 |
| 3 | 3 | --- |
| 4 | −$id: "http://devicetree.org/schemas/serial/serial.yaml#" | |
| 5 | −$schema: "http://devicetree.org/meta-schemas/core.yaml#" | |
| 4 | +$id: http://devicetree.org/schemas/serial/serial.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | 6 | |
| 7 | 7 | title: Serial Interface Generic |
| 8 | 8 | |
| @@ -68,12 +68,12 @@ properties: · 67 unmodified lines | ||
| 68 | 68 | - const: apb_pclk |
| 69 | 69 | |
| 70 | 70 | dmas: |
| 71 | − minItems: 2 | |
| 71 | + maxItems: 2 | |
| 72 | 72 | |
| 73 | 73 | dma-names: |
| 74 | 74 | items: |
| 75 | − - const: rx | |
| 76 | 75 | - const: tx |
| 76 | + - const: rx | |
| 77 | 77 | |
| 78 | 78 | snps,uart-16550-compatible: |
| 79 | 79 | description: reflects the value of UART_16550_COMPATIBLE configuration |
| @@ -2,8 +2,8 @@ · 1 unmodified line | ||
| 2 | 2 | # Copyright 2019 Unisoc Inc. |
| 3 | 3 | %YAML 1.2 |
| 4 | 4 | --- |
| 5 | −$id: "http://devicetree.org/schemas/serial/sprd-uart.yaml#" | |
| 6 | −$schema: "http://devicetree.org/meta-schemas/core.yaml#" | |
| 5 | +$id: http://devicetree.org/schemas/serial/sprd-uart.yaml# | |
| 6 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 7 | 7 | |
| 8 | 8 | title: Spreadtrum serial UART |
| 9 | 9 | |
| @@ -2,8 +2,8 @@ · 1 unmodified line | ||
| 2 | 2 | # Copyright (C) Sunplus Co., Ltd. 2021 |
| 3 | 3 | %YAML 1.2 |
| 4 | 4 | --- |
| 5 | −$id: "http://devicetree.org/schemas/serial/sunplus,sp7021-uart.yaml#" | |
| 6 | −$schema: "http://devicetree.org/meta-schemas/core.yaml#" | |
| 5 | +$id: http://devicetree.org/schemas/serial/sunplus,sp7021-uart.yaml# | |
| 6 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 7 | 7 | |
| 8 | 8 | title: Sunplus SoC SP7021 UART Controller |
| 9 | 9 | |
| @@ -29,6 +29,8 @@ Config Initiator · 28 unmodified lines | ||
| 29 | 29 | |
| 30 | 30 | #. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl. |
| 31 | 31 | |
| 32 | +#. Configure DLCs using ``GSMIOC_GETCONF_DLCI``/``GSMIOC_SETCONF_DLCI`` ioctl for non-defaults. | |
| 33 | + | |
| 32 | 34 | #. Obtain base gsmtty number for the used serial port. |
| 33 | 35 | |
| 34 | 36 | Major parts of the initialization program |
| @@ -45,6 +47,7 @@ Config Initiator · 10 unmodified lines | ||
| 45 | 47 | int ldisc = N_GSM0710; |
| 46 | 48 | struct gsm_config c; |
| 47 | 49 | struct gsm_config_ext ce; |
| 50 | + struct gsm_dlci_config dc; | |
| 48 | 51 | struct termios configuration; |
| 49 | 52 | uint32_t first; |
| 50 | 53 | |
| @@ -81,6 +84,13 @@ Config Initiator · 30 unmodified lines | ||
| 81 | 84 | c.mtu = 127; |
| 82 | 85 | /* set the new configuration */ |
| 83 | 86 | ioctl(fd, GSMIOC_SETCONF, &c); |
| 87 | + /* get DLC 1 configuration */ | |
| 88 | + dc.channel = 1; | |
| 89 | + ioctl(fd, GSMIOC_GETCONF_DLCI, &dc); | |
| 90 | + /* the first user channel gets a higher priority */ | |
| 91 | + dc.priority = 1; | |
| 92 | + /* set the new DLC 1 specific configuration */ | |
| 93 | + ioctl(fd, GSMIOC_SETCONF_DLCI, &dc); | |
| 84 | 94 | /* get first gsmtty device node */ |
| 85 | 95 | ioctl(fd, GSMIOC_GETFIRST, &first); |
| 86 | 96 | printf("first muxed line: /dev/gsmtty%i\n", first); |
| @@ -120,6 +130,8 @@ Config Requester · 33 unmodified lines | ||
| 120 | 130 | |
| 121 | 131 | #. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl. |
| 122 | 132 | |
| 133 | +#. Configure DLCs using ``GSMIOC_GETCONF_DLCI``/``GSMIOC_SETCONF_DLCI`` ioctl for non-defaults. | |
| 134 | + | |
| 123 | 135 | #. Obtain base gsmtty number for the used serial port:: |
| 124 | 136 | |
| 125 | 137 | #include <stdio.h> |
| @@ -132,6 +144,7 @@ Config Requester · 6 unmodified lines | ||
| 132 | 144 | int ldisc = N_GSM0710; |
| 133 | 145 | struct gsm_config c; |
| 134 | 146 | struct gsm_config_ext ce; |
| 147 | + struct gsm_dlci_config dc; | |
| 135 | 148 | struct termios configuration; |
| 136 | 149 | uint32_t first; |
| 137 | 150 | |
| @@ -161,6 +174,13 @@ Config Requester · 23 unmodified lines | ||
| 161 | 174 | c.mtu = 127; |
| 162 | 175 | /* set the new configuration */ |
| 163 | 176 | ioctl(fd, GSMIOC_SETCONF, &c); |
| 177 | + /* get DLC 1 configuration */ | |
| 178 | + dc.channel = 1; | |
| 179 | + ioctl(fd, GSMIOC_GETCONF_DLCI, &dc); | |
| 180 | + /* the first user channel gets a higher priority */ | |
| 181 | + dc.priority = 1; | |
| 182 | + /* set the new DLC 1 specific configuration */ | |
| 183 | + ioctl(fd, GSMIOC_SETCONF_DLCI, &dc); | |
| 164 | 184 | /* get first gsmtty device node */ |
| 165 | 185 | ioctl(fd, GSMIOC_GETFIRST, &first); |
| 166 | 186 | printf("first muxed line: /dev/gsmtty%i\n", first); |
| @@ -2045,7 +2045,8 @@ · 2044 unmodified lines | ||
| 2045 | 2045 | }; |
| 2046 | 2046 | |
| 2047 | 2047 | uart_AO: serial@3000 { |
| 2048 | − compatible = "amlogic,meson-gx-uart", | |
| 2048 | + compatible = "amlogic,meson-g12a-uart", | |
| 2049 | + "amlogic,meson-gx-uart", | |
| 2049 | 2050 | "amlogic,meson-ao-uart"; |
| 2050 | 2051 | reg = <0x0 0x3000 0x0 0x18>; |
| 2051 | 2052 | interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>; |
| @@ -2055,7 +2056,8 @@ · 3 unmodified lines | ||
| 2055 | 2056 | }; |
| 2056 | 2057 | |
| 2057 | 2058 | uart_AO_B: serial@4000 { |
| 2058 | − compatible = "amlogic,meson-gx-uart", | |
| 2059 | + compatible = "amlogic,meson-g12a-uart", | |
| 2060 | + "amlogic,meson-gx-uart", | |
| 2059 | 2061 | "amlogic,meson-ao-uart"; |
| 2060 | 2062 | reg = <0x0 0x4000 0x0 0x18>; |
| 2061 | 2063 | interrupts = <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>; |
| @@ -2292,7 +2294,8 @@ · 230 unmodified lines | ||
| 2292 | 2294 | }; |
| 2293 | 2295 | |
| 2294 | 2296 | uart_C: serial@22000 { |
| 2295 | − compatible = "amlogic,meson-gx-uart"; | |
| 2297 | + compatible = "amlogic,meson-g12a-uart", | |
| 2298 | + "amlogic,meson-gx-uart"; | |
| 2296 | 2299 | reg = <0x0 0x22000 0x0 0x18>; |
| 2297 | 2300 | interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>; |
| 2298 | 2301 | clocks = <&xtal>, <&clkc CLKID_UART2>, <&xtal>; |
| @@ -2301,7 +2304,8 @@ · 2 unmodified lines | ||
| 2301 | 2304 | }; |
| 2302 | 2305 | |
| 2303 | 2306 | uart_B: serial@23000 { |
| 2304 | − compatible = "amlogic,meson-gx-uart"; | |
| 2307 | + compatible = "amlogic,meson-g12a-uart", | |
| 2308 | + "amlogic,meson-gx-uart"; | |
| 2305 | 2309 | reg = <0x0 0x23000 0x0 0x18>; |
| 2306 | 2310 | interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>; |
| 2307 | 2311 | clocks = <&xtal>, <&clkc CLKID_UART1>, <&xtal>; |
| @@ -2310,7 +2314,8 @@ · 2 unmodified lines | ||
| 2310 | 2314 | }; |
| 2311 | 2315 | |
| 2312 | 2316 | uart_A: serial@24000 { |
| 2313 | − compatible = "amlogic,meson-gx-uart"; | |
| 2317 | + compatible = "amlogic,meson-g12a-uart", | |
| 2318 | + "amlogic,meson-gx-uart"; | |
| 2314 | 2319 | reg = <0x0 0x24000 0x0 0x18>; |
| 2315 | 2320 | interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>; |
| 2316 | 2321 | clocks = <&xtal>, <&clkc CLKID_UART0>, <&xtal>; |
| @@ -1060,7 +1060,7 @@ static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty) · 1059 unmodified lines | ||
| 1060 | 1060 | if (info->serial_signals & SerialSignal_CTS) { |
| 1061 | 1061 | if (debug_level >= DEBUG_LEVEL_ISR) |
| 1062 | 1062 | printk("CTS tx start..."); |
| 1063 | − tty->hw_stopped = 0; | |
| 1063 | + tty->hw_stopped = false; | |
| 1064 | 1064 | tx_start(info, tty); |
| 1065 | 1065 | info->pending_bh |= BH_TRANSMIT; |
| 1066 | 1066 | return; |
| @@ -1069,7 +1069,7 @@ static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty) · 2 unmodified lines | ||
| 1069 | 1069 | if (!(info->serial_signals & SerialSignal_CTS)) { |
| 1070 | 1070 | if (debug_level >= DEBUG_LEVEL_ISR) |
| 1071 | 1071 | printk("CTS tx stop..."); |
| 1072 | − tty->hw_stopped = 1; | |
| 1072 | + tty->hw_stopped = true; | |
| 1073 | 1073 | tx_stop(info); |
| 1074 | 1074 | } |
| 1075 | 1075 | } |
| @@ -2312,7 +2312,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, · 1236 unmodified lines | ||
| 2312 | 2312 | |
| 2313 | 2313 | /* Handle turning off CRTSCTS */ |
| 2314 | 2314 | if (old_termios->c_cflag & CRTSCTS && !C_CRTSCTS(tty)) { |
| 2315 | − tty->hw_stopped = 0; | |
| 2315 | + tty->hw_stopped = false; | |
| 2316 | 2316 | tx_release(tty); |
| 2317 | 2317 | } |
| 2318 | 2318 | } |
| @@ -478,13 +478,13 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port) · 477 unmodified lines | ||
| 478 | 478 | int cts = (status & UART_MSR_CTS); |
| 479 | 479 | if (tty->hw_stopped) { |
| 480 | 480 | if (cts) { |
| 481 | − tty->hw_stopped = 0; | |
| 481 | + tty->hw_stopped = false; | |
| 482 | 482 | sdio_uart_start_tx(port); |
| 483 | 483 | tty_wakeup(tty); |
| 484 | 484 | } |
| 485 | 485 | } else { |
| 486 | 486 | if (!cts) { |
| 487 | − tty->hw_stopped = 1; | |
| 487 | + tty->hw_stopped = true; | |
| 488 | 488 | sdio_uart_stop_tx(port); |
| 489 | 489 | } |
| 490 | 490 | } |
| @@ -633,7 +633,7 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) · 142 unmodified lines | ||
| 633 | 633 | |
| 634 | 634 | if (C_CRTSCTS(tty)) |
| 635 | 635 | if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) |
| 636 | − tty->hw_stopped = 1; | |
| 636 | + tty->hw_stopped = true; | |
| 637 | 637 | |
| 638 | 638 | clear_bit(TTY_IO_ERROR, &tty->flags); |
| 639 | 639 | |
| @@ -882,14 +882,14 @@ static void sdio_uart_set_termios(struct tty_struct *tty, · 242 unmodified lines | ||
| 882 | 882 | |
| 883 | 883 | /* Handle turning off CRTSCTS */ |
| 884 | 884 | if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) { |
| 885 | − tty->hw_stopped = 0; | |
| 885 | + tty->hw_stopped = false; | |
| 886 | 886 | sdio_uart_start_tx(port); |
| 887 | 887 | } |
| 888 | 888 | |
| 889 | 889 | /* Handle turning on CRTSCTS */ |
| 890 | 890 | if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { |
| 891 | 891 | if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) { |
| 892 | − tty->hw_stopped = 1; | |
| 892 | + tty->hw_stopped = true; | |
| 893 | 893 | sdio_uart_stop_tx(port); |
| 894 | 894 | } |
| 895 | 895 | } |
| @@ -160,7 +160,7 @@ config LEGACY_TIOCSTI · 159 unmodified lines | ||
| 160 | 160 | a dangerous legacy operation, and can be disabled on most |
| 161 | 161 | systems. |
| 162 | 162 | |
| 163 | − Say 'Y here only if you have confirmed that your system's | |
| 163 | + Say Y here only if you have confirmed that your system's | |
| 164 | 164 | userspace depends on this functionality to continue operating |
| 165 | 165 | normally. |
| 166 | 166 | |
| @@ -347,7 +347,7 @@ static void check_modem_status(struct serial_state *info) · 346 unmodified lines | ||
| 347 | 347 | #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) |
| 348 | 348 | printk("CTS tx start..."); |
| 349 | 349 | #endif |
| 350 | − port->tty->hw_stopped = 0; | |
| 350 | + port->tty->hw_stopped = false; | |
| 351 | 351 | info->IER |= UART_IER_THRI; |
| 352 | 352 | amiga_custom.intena = IF_SETCLR | IF_TBE; |
| 353 | 353 | mb(); |
| @@ -362,7 +362,7 @@ static void check_modem_status(struct serial_state *info) · 8 unmodified lines | ||
| 362 | 362 | #if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) |
| 363 | 363 | printk("CTS tx stop..."); |
| 364 | 364 | #endif |
| 365 | − port->tty->hw_stopped = 1; | |
| 365 | + port->tty->hw_stopped = true; | |
| 366 | 366 | info->IER &= ~UART_IER_THRI; |
| 367 | 367 | /* disable Tx interrupt and remove any pending interrupts */ |
| 368 | 368 | amiga_custom.intena = IF_TBE; |
| @@ -1197,7 +1197,7 @@ static void rs_set_termios(struct tty_struct *tty, const struct ktermios *old_te · 828 unmodified lines | ||
| 1197 | 1197 | |
| 1198 | 1198 | /* Handle turning off CRTSCTS */ |
| 1199 | 1199 | if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { |
| 1200 | − tty->hw_stopped = 0; | |
| 1200 | + tty->hw_stopped = false; | |
| 1201 | 1201 | rs_start(tty); |
| 1202 | 1202 | } |
| 1203 | 1203 | |
| @@ -553,7 +553,7 @@ static void mxser_handle_cts(struct tty_struct *tty, struct mxser_port *info, · 552 unmodified lines | ||
| 553 | 553 | |
| 554 | 554 | if (tty->hw_stopped) { |
| 555 | 555 | if (cts) { |
| 556 | − tty->hw_stopped = 0; | |
| 556 | + tty->hw_stopped = false; | |
| 557 | 557 | |
| 558 | 558 | if (!mxser_16550A_or_MUST(info)) |
| 559 | 559 | __mxser_start_tx(info); |
| @@ -563,7 +563,7 @@ static void mxser_handle_cts(struct tty_struct *tty, struct mxser_port *info, · 3 unmodified lines | ||
| 563 | 563 | } else if (cts) |
| 564 | 564 | return; |
| 565 | 565 | |
| 566 | − tty->hw_stopped = 1; | |
| 566 | + tty->hw_stopped = true; | |
| 567 | 567 | if (!mxser_16550A_or_MUST(info)) |
| 568 | 568 | __mxser_stop_tx(info); |
| 569 | 569 | } |
| @@ -1361,7 +1361,7 @@ static void mxser_set_termios(struct tty_struct *tty, · 791 unmodified lines | ||
| 1361 | 1361 | spin_unlock_irqrestore(&info->slock, flags); |
| 1362 | 1362 | |
| 1363 | 1363 | if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { |
| 1364 | − tty->hw_stopped = 0; | |
| 1364 | + tty->hw_stopped = false; | |
| 1365 | 1365 | mxser_start(tty); |
| 1366 | 1366 | } |
| 1367 | 1367 | |
| @@ -42,6 +42,7 @@ · 41 unmodified lines | ||
| 42 | 42 | #include <linux/ctype.h> |
| 43 | 43 | #include <linux/mm.h> |
| 44 | 44 | #include <linux/math.h> |
| 45 | +#include <linux/nospec.h> | |
| 45 | 46 | #include <linux/string.h> |
| 46 | 47 | #include <linux/slab.h> |
| 47 | 48 | #include <linux/poll.h> |
| @@ -128,6 +129,7 @@ struct gsm_msg { · 80 unmodified lines | ||
| 128 | 129 | |
| 129 | 130 | enum gsm_dlci_state { |
| 130 | 131 | DLCI_CLOSED, |
| 132 | + DLCI_WAITING_CONFIG, /* Waiting for DLCI configuration from user */ | |
| 131 | 133 | DLCI_CONFIGURE, /* Sending PN (for adaption > 1) */ |
| 132 | 134 | DLCI_OPENING, /* Sending SABM not seen UA */ |
| 133 | 135 | DLCI_OPEN, /* SABM/UA complete */ |
| @@ -330,6 +332,7 @@ struct gsm_mux { · 196 unmodified lines | ||
| 330 | 332 | unsigned int t3; /* Power wake-up timer in seconds. */ |
| 331 | 333 | int n2; /* Retry count */ |
| 332 | 334 | u8 k; /* Window size */ |
| 335 | + bool wait_config; /* Wait for configuration by ioctl before DLCI open */ | |
| 333 | 336 | u32 keep_alive; /* Control channel keep-alive in 10ms */ |
| 334 | 337 | |
| 335 | 338 | /* Statistics (not currently exposed) */ |
| @@ -451,6 +454,7 @@ static int gsm_modem_update(struct gsm_dlci *dlci, u8 brk); · 115 unmodified lines | ||
| 451 | 454 | static struct gsm_msg *gsm_data_alloc(struct gsm_mux *gsm, u8 addr, int len, |
| 452 | 455 | u8 ctrl); |
| 453 | 456 | static int gsm_send_packet(struct gsm_mux *gsm, struct gsm_msg *msg); |
| 457 | +static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr); | |
| 454 | 458 | static void gsmld_write_trigger(struct gsm_mux *gsm); |
| 455 | 459 | static void gsmld_write_task(struct work_struct *work); |
| 456 | 460 | |
| @@ -2280,6 +2284,7 @@ static void gsm_dlci_begin_open(struct gsm_dlci *dlci) · 1823 unmodified lines | ||
| 2280 | 2284 | |
| 2281 | 2285 | switch (dlci->state) { |
| 2282 | 2286 | case DLCI_CLOSED: |
| 2287 | + case DLCI_WAITING_CONFIG: | |
| 2283 | 2288 | case DLCI_CLOSING: |
| 2284 | 2289 | dlci->retries = gsm->n2; |
| 2285 | 2290 | if (!need_pn) { |
| @@ -2311,6 +2316,7 @@ static void gsm_dlci_set_opening(struct gsm_dlci *dlci) · 25 unmodified lines | ||
| 2311 | 2316 | { |
| 2312 | 2317 | switch (dlci->state) { |
| 2313 | 2318 | case DLCI_CLOSED: |
| 2319 | + case DLCI_WAITING_CONFIG: | |
| 2314 | 2320 | case DLCI_CLOSING: |
| 2315 | 2321 | dlci->state = DLCI_OPENING; |
| 2316 | 2322 | break; |
| @@ -2319,6 +2325,24 @@ static void gsm_dlci_set_opening(struct gsm_dlci *dlci) · 2 unmodified lines | ||
| 2319 | 2325 | } |
| 2320 | 2326 | } |
| 2321 | 2327 | |
| 2328 | +/** | |
| 2329 | + * gsm_dlci_set_wait_config - wait for channel configuration | |
| 2330 | + * @dlci: DLCI to configure | |
| 2331 | + * | |
| 2332 | + * Wait for a DLCI configuration from the application. | |
| 2333 | + */ | |
| 2334 | +static void gsm_dlci_set_wait_config(struct gsm_dlci *dlci) | |
| 2335 | +{ | |
| 2336 | + switch (dlci->state) { | |
| 2337 | + case DLCI_CLOSED: | |
| 2338 | + case DLCI_CLOSING: | |
| 2339 | + dlci->state = DLCI_WAITING_CONFIG; | |
| 2340 | + break; | |
| 2341 | + default: | |
| 2342 | + break; | |
| 2343 | + } | |
| 2344 | +} | |
| 2345 | + | |
| 2322 | 2346 | /** |
| 2323 | 2347 | * gsm_dlci_begin_close - start channel open procedure |
| 2324 | 2348 | * @dlci: DLCI to open |
| @@ -2453,6 +2477,128 @@ static void gsm_kick_timer(struct timer_list *t) · 128 unmodified lines | ||
| 2453 | 2477 | pr_info("%s TX queue stalled\n", __func__); |
| 2454 | 2478 | } |
| 2455 | 2479 | |
| 2480 | +/** | |
| 2481 | + * gsm_dlci_copy_config_values - copy DLCI configuration | |
| 2482 | + * @dlci: source DLCI | |
| 2483 | + * @dc: configuration structure to fill | |
| 2484 | + */ | |
| 2485 | +static void gsm_dlci_copy_config_values(struct gsm_dlci *dlci, struct gsm_dlci_config *dc) | |
| 2486 | +{ | |
| 2487 | + memset(dc, 0, sizeof(*dc)); | |
| 2488 | + dc->channel = (u32)dlci->addr; | |
| 2489 | + dc->adaption = (u32)dlci->adaption; | |
| 2490 | + dc->mtu = (u32)dlci->mtu; | |
| 2491 | + dc->priority = (u32)dlci->prio; | |
| 2492 | + if (dlci->ftype == UIH) | |
| 2493 | + dc->i = 1; | |
| 2494 | + else | |
| 2495 | + dc->i = 2; | |
| 2496 | + dc->k = (u32)dlci->k; | |
| 2497 | +} | |
| 2498 | + | |
| 2499 | +/** | |
| 2500 | + * gsm_dlci_config - configure DLCI from configuration | |
| 2501 | + * @dlci: DLCI to configure | |
| 2502 | + * @dc: DLCI configuration | |
| 2503 | + * @open: open DLCI after configuration? | |
| 2504 | + */ | |
| 2505 | +static int gsm_dlci_config(struct gsm_dlci *dlci, struct gsm_dlci_config *dc, int open) | |
| 2506 | +{ | |
| 2507 | + struct gsm_mux *gsm; | |
| 2508 | + bool need_restart = false; | |
| 2509 | + bool need_open = false; | |
| 2510 | + unsigned int i; | |
| 2511 | + | |
| 2512 | + /* | |
| 2513 | + * Check that userspace doesn't put stuff in here to prevent breakages | |
| 2514 | + * in the future. | |
| 2515 | + */ | |
| 2516 | + for (i = 0; i < ARRAY_SIZE(dc->reserved); i++) | |
| 2517 | + if (dc->reserved[i]) | |
| 2518 | + return -EINVAL; | |
| 2519 | + | |
| 2520 | + if (!dlci) | |
| 2521 | + return -EINVAL; | |
| 2522 | + gsm = dlci->gsm; | |
| 2523 | + | |
| 2524 | + /* Stuff we don't support yet - I frame transport */ | |
| 2525 | + if (dc->adaption != 1 && dc->adaption != 2) | |
| 2526 | + return -EOPNOTSUPP; | |
| 2527 | + if (dc->mtu > MAX_MTU || dc->mtu < MIN_MTU || dc->mtu > gsm->mru) | |
| 2528 | + return -EINVAL; | |
| 2529 | + if (dc->priority >= 64) | |
| 2530 | + return -EINVAL; | |
| 2531 | + if (dc->i == 0 || dc->i > 2) /* UIH and UI only */ | |
| 2532 | + return -EINVAL; | |
| 2533 | + if (dc->k > 7) | |
| 2534 | + return -EINVAL; | |
| 2535 | + | |
| 2536 | + /* | |
| 2537 | + * See what is needed for reconfiguration | |
| 2538 | + */ | |
| 2539 | + /* Framing fields */ | |
| 2540 | + if (dc->adaption != dlci->adaption) | |
| 2541 | + need_restart = true; | |
| 2542 | + if (dc->mtu != dlci->mtu) | |
| 2543 | + need_restart = true; | |
| 2544 | + if (dc->i != dlci->ftype) | |
| 2545 | + need_restart = true; | |
| 2546 | + /* Requires care */ | |
| 2547 | + if (dc->priority != dlci->prio) | |
| 2548 | + need_restart = true; | |
| 2549 | + | |
| 2550 | + if ((open && gsm->wait_config) || need_restart) | |
| 2551 | + need_open = true; | |
| 2552 | + if (dlci->state == DLCI_WAITING_CONFIG) { | |
| 2553 | + need_restart = false; | |
| 2554 | + need_open = true; | |
| 2555 | + } | |
| 2556 | + | |
| 2557 | + /* | |
| 2558 | + * Close down what is needed, restart and initiate the new | |
| 2559 | + * configuration. | |
| 2560 | + */ | |
| 2561 | + if (need_restart) { | |
| 2562 | + gsm_dlci_begin_close(dlci); | |
| 2563 | + wait_event_interruptible(gsm->event, dlci->state == DLCI_CLOSED); | |
| 2564 | + if (signal_pending(current)) | |
| 2565 | + return -EINTR; | |
| 2566 | + } | |
| 2567 | + /* | |
| 2568 | + * Setup the new configuration values | |
| 2569 | + */ | |
| 2570 | + dlci->adaption = (int)dc->adaption; | |
| 2571 | + | |
| 2572 | + if (dc->mtu) | |
| 2573 | + dlci->mtu = (unsigned int)dc->mtu; | |
| 2574 | + else | |
| 2575 | + dlci->mtu = gsm->mtu; | |
| 2576 | + | |
| 2577 | + if (dc->priority) | |
| 2578 | + dlci->prio = (u8)dc->priority; | |
| 2579 | + else | |
| 2580 | + dlci->prio = roundup(dlci->addr + 1, 8) - 1; | |
| 2581 | + | |
| 2582 | + if (dc->i == 1) | |
| 2583 | + dlci->ftype = UIH; | |
| 2584 | + else if (dc->i == 2) | |
| 2585 | + dlci->ftype = UI; | |
| 2586 | + | |
| 2587 | + if (dc->k) | |
| 2588 | + dlci->k = (u8)dc->k; | |
| 2589 | + else | |
| 2590 | + dlci->k = gsm->k; | |
| 2591 | + | |
| 2592 | + if (need_open) { | |
| 2593 | + if (gsm->initiator) | |
| 2594 | + gsm_dlci_begin_open(dlci); | |
| 2595 | + else | |
| 2596 | + gsm_dlci_set_opening(dlci); | |
| 2597 | + } | |
| 2598 | + | |
| 2599 | + return 0; | |
| 2600 | +} | |
| 2601 | + | |
| 2456 | 2602 | /* |
| 2457 | 2603 | * Allocate/Free DLCI channels |
| 2458 | 2604 | */ |
| @@ -3078,6 +3224,7 @@ static struct gsm_mux *gsm_alloc_mux(void) · 619 unmodified lines | ||
| 3078 | 3224 | gsm->mru = 64; /* Default to encoding 1 so these should be 64 */ |
| 3079 | 3225 | gsm->mtu = 64; |
| 3080 | 3226 | gsm->dead = true; /* Avoid early tty opens */ |
| 3227 | + gsm->wait_config = false; /* Disabled */ | |
| 3081 | 3228 | gsm->keep_alive = 0; /* Disabled */ |
| 3082 | 3229 | |
| 3083 | 3230 | /* Store the instance to the mux array or abort if no space is |
| @@ -3130,8 +3277,8 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c) · 46 unmodified lines | ||
| 3130 | 3277 | int need_close = 0; |
| 3131 | 3278 | int need_restart = 0; |
| 3132 | 3279 | |
| 3133 | − /* Stuff we don't support yet - UI or I frame transport, windowing */ | |
| 3134 | − if ((c->adaption != 1 && c->adaption != 2) || c->k) | |
| 3280 | + /* Stuff we don't support yet - UI or I frame transport */ | |
| 3281 | + if (c->adaption != 1 && c->adaption != 2) | |
| 3135 | 3282 | return -EOPNOTSUPP; |
| 3136 | 3283 | /* Check the MRU/MTU range looks sane */ |
| 3137 | 3284 | if (c->mru < MIN_MTU || c->mtu < MIN_MTU) |
| @@ -3218,6 +3365,7 @@ static void gsm_copy_config_ext_values(struct gsm_mux *gsm, · 80 unmodified lines | ||
| 3218 | 3365 | struct gsm_config_ext *ce) |
| 3219 | 3366 | { |
| 3220 | 3367 | memset(ce, 0, sizeof(*ce)); |
| 3368 | + ce->wait_config = gsm->wait_config ? 1 : 0; | |
| 3221 | 3369 | ce->keep_alive = gsm->keep_alive; |
| 3222 | 3370 | } |
| 3223 | 3371 | |
| @@ -3233,7 +3381,12 @@ static int gsm_config_ext(struct gsm_mux *gsm, struct gsm_config_ext *ce) · 9 unmodified lines | ||
| 3233 | 3381 | if (ce->reserved[i]) |
| 3234 | 3382 | return -EINVAL; |
| 3235 | 3383 | |
| 3384 | + /* | |
| 3385 | + * Setup the new configuration values | |
| 3386 | + */ | |
| 3387 | + gsm->wait_config = ce->wait_config ? true : false; | |
| 3236 | 3388 | gsm->keep_alive = ce->keep_alive; |
| 3389 | + | |
| 3237 | 3390 | return 0; |
| 3238 | 3391 | } |
| 3239 | 3392 | |
| @@ -3433,9 +3586,16 @@ static int gsmld_open(struct tty_struct *tty) · 193 unmodified lines | ||
| 3433 | 3586 | tty->receive_room = 65536; |
| 3434 | 3587 | |
| 3435 | 3588 | /* Attach the initial passive connection */ |
| 3436 | − gsm->encoding = GSM_ADV_OPT; | |
| 3437 | 3589 | gsmld_attach_gsm(tty, gsm); |
| 3438 | 3590 | |
| 3591 | + /* The mux will not be activated yet, we wait for correct | |
| 3592 | + * configuration first. | |
| 3593 | + */ | |
| 3594 | + if (gsm->encoding == GSM_BASIC_OPT) | |
| 3595 | + gsm->receive = gsm0_receive; | |
| 3596 | + else | |
| 3597 | + gsm->receive = gsm1_receive; | |
| 3598 | + | |
| 3439 | 3599 | return 0; |
| 3440 | 3600 | } |
| 3441 | 3601 | |
| @@ -3556,8 +3716,10 @@ static int gsmld_ioctl(struct tty_struct *tty, unsigned int cmd, · 114 unmodified lines | ||
| 3556 | 3716 | { |
| 3557 | 3717 | struct gsm_config c; |
| 3558 | 3718 | struct gsm_config_ext ce; |
| 3719 | + struct gsm_dlci_config dc; | |
| 3559 | 3720 | struct gsm_mux *gsm = tty->disc_data; |
| 3560 | − unsigned int base; | |
| 3721 | + unsigned int base, addr; | |
| 3722 | + struct gsm_dlci *dlci; | |
| 3561 | 3723 | |
| 3562 | 3724 | switch (cmd) { |
| 3563 | 3725 | case GSMIOC_GETCONF: |
| @@ -3581,6 +3743,35 @@ static int gsmld_ioctl(struct tty_struct *tty, unsigned int cmd, · 17 unmodified lines | ||
| 3581 | 3743 | if (copy_from_user(&ce, (void __user *)arg, sizeof(ce))) |
| 3582 | 3744 | return -EFAULT; |
| 3583 | 3745 | return gsm_config_ext(gsm, &ce); |
| 3746 | + case GSMIOC_GETCONF_DLCI: | |
| 3747 | + if (copy_from_user(&dc, (void __user *)arg, sizeof(dc))) | |
| 3748 | + return -EFAULT; | |
| 3749 | + if (dc.channel == 0 || dc.channel >= NUM_DLCI) | |
| 3750 | + return -EINVAL; | |
| 3751 | + addr = array_index_nospec(dc.channel, NUM_DLCI); | |
| 3752 | + dlci = gsm->dlci[addr]; | |
| 3753 | + if (!dlci) { | |
| 3754 | + dlci = gsm_dlci_alloc(gsm, addr); | |
| 3755 | + if (!dlci) | |
| 3756 | + return -ENOMEM; | |
| 3757 | + } | |
| 3758 | + gsm_dlci_copy_config_values(dlci, &dc); | |
| 3759 | + if (copy_to_user((void __user *)arg, &dc, sizeof(dc))) | |
| 3760 | + return -EFAULT; | |
| 3761 | + return 0; | |
| 3762 | + case GSMIOC_SETCONF_DLCI: | |
| 3763 | + if (copy_from_user(&dc, (void __user *)arg, sizeof(dc))) | |
| 3764 | + return -EFAULT; | |
| 3765 | + if (dc.channel == 0 || dc.channel >= NUM_DLCI) | |
| 3766 | + return -EINVAL; | |
| 3767 | + addr = array_index_nospec(dc.channel, NUM_DLCI); | |
| 3768 | + dlci = gsm->dlci[addr]; | |
| 3769 | + if (!dlci) { | |
| 3770 | + dlci = gsm_dlci_alloc(gsm, addr); | |
| 3771 | + if (!dlci) | |
| 3772 | + return -ENOMEM; | |
| 3773 | + } | |
| 3774 | + return gsm_dlci_config(dlci, &dc, 0); | |
| 3584 | 3775 | default: |
| 3585 | 3776 | return n_tty_ioctl_helper(tty, cmd, arg); |
| 3586 | 3777 | } |
| @@ -4008,7 +4199,6 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp) · 421 unmodified lines | ||
| 4008 | 4199 | { |
| 4009 | 4200 | struct gsm_dlci *dlci = tty->driver_data; |
| 4010 | 4201 | struct tty_port *port = &dlci->port; |
| 4011 | − struct gsm_mux *gsm = dlci->gsm; | |
| 4012 | 4202 | |
| 4013 | 4203 | port->count++; |
| 4014 | 4204 | tty_port_tty_set(port, tty); |
| @@ -4018,10 +4208,15 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp) · 3 unmodified lines | ||
| 4018 | 4208 | a DM straight back. This is ok as that will have caused a hangup */ |
| 4019 | 4209 | tty_port_set_initialized(port, true); |
| 4020 | 4210 | /* Start sending off SABM messages */ |
| 4021 | − if (gsm->initiator) | |
| 4022 | − gsm_dlci_begin_open(dlci); | |
| 4023 | − else | |
| 4024 | − gsm_dlci_set_opening(dlci); | |
| 4211 | + if (!dlci->gsm->wait_config) { | |
| 4212 | + /* Start sending off SABM messages */ | |
| 4213 | + if (dlci->gsm->initiator) | |
| 4214 | + gsm_dlci_begin_open(dlci); | |
| 4215 | + else | |
| 4216 | + gsm_dlci_set_opening(dlci); | |
| 4217 | + } else { | |
| 4218 | + gsm_dlci_set_wait_config(dlci); | |
| 4219 | + } | |
| 4025 | 4220 | /* And wait for virtual carrier */ |
| 4026 | 4221 | return tty_port_block_til_ready(port, tty, filp); |
| 4027 | 4222 | } |
| @@ -4142,6 +4337,7 @@ static int gsmtty_ioctl(struct tty_struct *tty, · 114 unmodified lines | ||
| 4142 | 4337 | { |
| 4143 | 4338 | struct gsm_dlci *dlci = tty->driver_data; |
| 4144 | 4339 | struct gsm_netconfig nc; |
| 4340 | + struct gsm_dlci_config dc; | |
| 4145 | 4341 | int index; |
| 4146 | 4342 | |
| 4147 | 4343 | if (dlci->state == DLCI_CLOSED) |
| @@ -4165,6 +4361,23 @@ static int gsmtty_ioctl(struct tty_struct *tty, · 17 unmodified lines | ||
| 4165 | 4361 | gsm_destroy_network(dlci); |
| 4166 | 4362 | mutex_unlock(&dlci->mutex); |
| 4167 | 4363 | return 0; |
| 4364 | + case GSMIOC_GETCONF_DLCI: | |
| 4365 | + if (copy_from_user(&dc, (void __user *)arg, sizeof(dc))) | |
| 4366 | + return -EFAULT; | |
| 4367 | + if (dc.channel != dlci->addr) | |
| 4368 | + return -EPERM; | |
| 4369 | + gsm_dlci_copy_config_values(dlci, &dc); | |
| 4370 | + if (copy_to_user((void __user *)arg, &dc, sizeof(dc))) | |
| 4371 | + return -EFAULT; | |
| 4372 | + return 0; | |
| 4373 | + case GSMIOC_SETCONF_DLCI: | |
| 4374 | + if (copy_from_user(&dc, (void __user *)arg, sizeof(dc))) | |
| 4375 | + return -EFAULT; | |
| 4376 | + if (dc.channel >= NUM_DLCI) | |
| 4377 | + return -EINVAL; | |
| 4378 | + if (dc.channel != 0 && dc.channel != dlci->addr) | |
| 4379 | + return -EPERM; | |
| 4380 | + return gsm_dlci_config(dlci, &dc, 1); | |
| 4168 | 4381 | case TIOCMIWAIT: |
| 4169 | 4382 | return gsm_wait_modem_change(dlci, (u32)arg); |
| 4170 | 4383 | default: |
| @@ -28,27 +28,26 @@ · 27 unmodified lines | ||
| 28 | 28 | * EAGAIN |
| 29 | 29 | */ |
| 30 | 30 | |
| 31 | −#include <linux/types.h> | |
| 32 | −#include <linux/major.h> | |
| 31 | +#include <linux/bitmap.h> | |
| 32 | +#include <linux/bitops.h> | |
| 33 | +#include <linux/ctype.h> | |
| 33 | 34 | #include <linux/errno.h> |
| 34 | −#include <linux/signal.h> | |
| 35 | +#include <linux/export.h> | |
| 35 | 36 | #include <linux/fcntl.h> |
| 37 | +#include <linux/file.h> | |
| 38 | +#include <linux/jiffies.h> | |
| 39 | +#include <linux/math.h> | |
| 40 | +#include <linux/poll.h> | |
| 41 | +#include <linux/ratelimit.h> | |
| 36 | 42 | #include <linux/sched.h> |
| 37 | −#include <linux/interrupt.h> | |
| 38 | −#include <linux/tty.h> | |
| 39 | −#include <linux/timer.h> | |
| 40 | −#include <linux/ctype.h> | |
| 41 | −#include <linux/mm.h> | |
| 42 | −#include <linux/string.h> | |
| 43 | +#include <linux/signal.h> | |
| 43 | 44 | #include <linux/slab.h> |
| 44 | −#include <linux/poll.h> | |
| 45 | −#include <linux/bitops.h> | |
| 46 | −#include <linux/audit.h> | |
| 47 | −#include <linux/file.h> | |
| 45 | +#include <linux/string.h> | |
| 46 | +#include <linux/tty.h> | |
| 47 | +#include <linux/types.h> | |
| 48 | 48 | #include <linux/uaccess.h> |
| 49 | −#include <linux/module.h> | |
| 50 | −#include <linux/ratelimit.h> | |
| 51 | 49 | #include <linux/vmalloc.h> |
| 50 | + | |
| 52 | 51 | #include "tty.h" |
| 53 | 52 | |
| 54 | 53 | /* |
| @@ -625,7 +624,7 @@ static size_t __process_echoes(struct tty_struct *tty) · 570 unmodified lines | ||
| 625 | 624 | c = echo_buf(ldata, tail); |
| 626 | 625 | if (c == ECHO_OP_START) { |
| 627 | 626 | unsigned char op; |
| 628 | − int no_space_left = 0; | |
| 627 | + bool space_left = true; | |
| 629 | 628 | |
| 630 | 629 | /* |
| 631 | 630 | * Since add_echo_byte() is called without holding |
| @@ -664,7 +663,7 @@ static size_t __process_echoes(struct tty_struct *tty) · 32 unmodified lines | ||
| 664 | 663 | num_bs = 8 - (num_chars & 7); |
| 665 | 664 | |
| 666 | 665 | if (num_bs > space) { |
| 667 | − no_space_left = 1; | |
| 666 | + space_left = false; | |
| 668 | 667 | break; |
| 669 | 668 | } |
| 670 | 669 | space -= num_bs; |
| @@ -690,7 +689,7 @@ static size_t __process_echoes(struct tty_struct *tty) · 19 unmodified lines | ||
| 690 | 689 | case ECHO_OP_START: |
| 691 | 690 | /* This is an escaped echo op start code */ |
| 692 | 691 | if (!space) { |
| 693 | − no_space_left = 1; | |
| 692 | + space_left = false; | |
| 694 | 693 | break; |
| 695 | 694 | } |
| 696 | 695 | tty_put_char(tty, ECHO_OP_START); |
| @@ -710,7 +709,7 @@ static size_t __process_echoes(struct tty_struct *tty) · 13 unmodified lines | ||
| 710 | 709 | * |
| 711 | 710 | */ |
| 712 | 711 | if (space < 2) { |
| 713 | − no_space_left = 1; | |
| 712 | + space_left = false; | |
| 714 | 713 | break; |
| 715 | 714 | } |
| 716 | 715 | tty_put_char(tty, '^'); |
| @@ -720,7 +719,7 @@ static size_t __process_echoes(struct tty_struct *tty) · 3 unmodified lines | ||
| 720 | 719 | tail += 2; |
| 721 | 720 | } |
| 722 | 721 | |
| 723 | − if (no_space_left) | |
| 722 | + if (!space_left) | |
| 724 | 723 | break; |
| 725 | 724 | } else { |
| 726 | 725 | if (O_OPOST(tty)) { |
| @@ -1177,7 +1176,7 @@ static void n_tty_receive_overrun(struct tty_struct *tty) · 450 unmodified lines | ||
| 1177 | 1176 | |
| 1178 | 1177 | ldata->num_overrun++; |
| 1179 | 1178 | if (time_after(jiffies, ldata->overrun_time + HZ) || |
| 1180 | − time_after(ldata->overrun_time, jiffies)) { | |
| 1179 | + time_after(ldata->overrun_time, jiffies)) { | |
| 1181 | 1180 | tty_warn(tty, "%d input overrun(s)\n", ldata->num_overrun); |
| 1182 | 1181 | ldata->overrun_time = jiffies; |
| 1183 | 1182 | ldata->num_overrun = 0; |
| @@ -1691,7 +1690,7 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, · 507 unmodified lines | ||
| 1691 | 1690 | |
| 1692 | 1691 | room = N_TTY_BUF_SIZE - (ldata->read_head - tail); |
| 1693 | 1692 | if (I_PARMRK(tty)) |
| 1694 | − room = (room + 2) / 3; | |
| 1693 | + room = DIV_ROUND_UP(room, 3); | |
| 1695 | 1694 | room--; |
| 1696 | 1695 | if (room <= 0) { |
| 1697 | 1696 | overflow = ldata->icanon && ldata->canon_head == tail; |
| @@ -365,6 +365,13 @@ static inline void serial8250_do_prepare_rx_dma(struct uart_8250_port *p) · 364 unmodified lines | ||
| 365 | 365 | if (dma->prepare_rx_dma) |
| 366 | 366 | dma->prepare_rx_dma(p); |
| 367 | 367 | } |
| 368 | + | |
| 369 | +static inline bool serial8250_tx_dma_running(struct uart_8250_port *p) | |
| 370 | +{ | |
| 371 | + struct uart_8250_dma *dma = p->dma; | |
| 372 | + | |
| 373 | + return dma && dma->tx_running; | |
| 374 | +} | |
| 368 | 375 | #else |
| 369 | 376 | static inline int serial8250_tx_dma(struct uart_8250_port *p) |
| 370 | 377 | { |
| @@ -380,6 +387,11 @@ static inline int serial8250_request_dma(struct uart_8250_port *p) · 9 unmodified lines | ||
| 380 | 387 | return -1; |
| 381 | 388 | } |
| 382 | 389 | static inline void serial8250_release_dma(struct uart_8250_port *p) { } |
| 390 | + | |
| 391 | +static inline bool serial8250_tx_dma_running(struct uart_8250_port *p) | |
| 392 | +{ | |
| 393 | + return false; | |
| 394 | +} | |
| 383 | 395 | #endif |
| 384 | 396 | |
| 385 | 397 | static inline int ns16550a_goto_highspeed(struct uart_8250_port *up) |
| @@ -1014,14 +1014,16 @@ static int brcmuart_probe(struct platform_device *pdev) · 1013 unmodified lines | ||
| 1014 | 1014 | /* See if a Baud clock has been specified */ |
| 1015 | 1015 | baud_mux_clk = of_clk_get_by_name(np, "sw_baud"); |
| 1016 | 1016 | if (IS_ERR(baud_mux_clk)) { |
| 1017 | − if (PTR_ERR(baud_mux_clk) == -EPROBE_DEFER) | |
| 1018 | − return -EPROBE_DEFER; | |
| 1017 | + if (PTR_ERR(baud_mux_clk) == -EPROBE_DEFER) { | |
| 1018 | + ret = -EPROBE_DEFER; | |
| 1019 | + goto release_dma; | |
| 1020 | + } | |
| 1019 | 1021 | dev_dbg(dev, "BAUD MUX clock not specified\n"); |
| 1020 | 1022 | } else { |
| 1021 | 1023 | dev_dbg(dev, "BAUD MUX clock found\n"); |
| 1022 | 1024 | ret = clk_prepare_enable(baud_mux_clk); |
| 1023 | 1025 | if (ret) |
| 1024 | − return ret; | |
| 1026 | + goto release_dma; | |
| 1025 | 1027 | priv->baud_mux_clk = baud_mux_clk; |
| 1026 | 1028 | init_real_clk_rates(dev, priv); |
| 1027 | 1029 | clk_rate = priv->default_mux_rate; |
| @@ -1029,7 +1031,8 @@ static int brcmuart_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 1029 | 1031 | |
| 1030 | 1032 | if (clk_rate == 0) { |
| 1031 | 1033 | dev_err(dev, "clock-frequency or clk not defined\n"); |
| 1032 | − return -EINVAL; | |
| 1034 | + ret = -EINVAL; | |
| 1035 | + goto release_dma; | |
| 1033 | 1036 | } |
| 1034 | 1037 | |
| 1035 | 1038 | dev_dbg(dev, "DMA is %senabled\n", priv->dma_enabled ? "" : "not "); |
| @@ -1116,7 +1119,9 @@ err1: · 80 unmodified lines | ||
| 1116 | 1119 | serial8250_unregister_port(priv->line); |
| 1117 | 1120 | err: |
| 1118 | 1121 | brcmuart_free_bufs(dev, priv); |
| 1119 | − brcmuart_arbitration(priv, 0); | |
| 1122 | +release_dma: | |
| 1123 | + if (priv->dma_enabled) | |
| 1124 | + brcmuart_arbitration(priv, 0); | |
| 1120 | 1125 | return ret; |
| 1121 | 1126 | } |
| 1122 | 1127 | |
| @@ -1128,7 +1133,8 @@ static int brcmuart_remove(struct platform_device *pdev) · 5 unmodified lines | ||
| 1128 | 1133 | hrtimer_cancel(&priv->hrt); |
| 1129 | 1134 | serial8250_unregister_port(priv->line); |
| 1130 | 1135 | brcmuart_free_bufs(&pdev->dev, priv); |
| 1131 | − brcmuart_arbitration(priv, 0); | |
| 1136 | + if (priv->dma_enabled) | |
| 1137 | + brcmuart_arbitration(priv, 0); | |
| 1132 | 1138 | return 0; |
| 1133 | 1139 | } |
| 1134 | 1140 | |
| @@ -1158,6 +1158,7 @@ void serial8250_unregister_port(int line) · 1157 unmodified lines | ||
| 1158 | 1158 | uart->port.type = PORT_UNKNOWN; |
| 1159 | 1159 | uart->port.dev = &serial8250_isa_devs->dev; |
| 1160 | 1160 | uart->capabilities = 0; |
| 1161 | + serial8250_init_port(uart); | |
| 1161 | 1162 | serial8250_apply_quirks(uart); |
| 1162 | 1163 | uart_add_one_port(&serial8250_reg, &uart->port); |
| 1163 | 1164 | } else { |
| @@ -13,36 +13,49 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/serial_reg.h> |
| 14 | 14 | #include <linux/platform_device.h> |
| 15 | 15 | #include <linux/clk.h> |
| 16 | −#include <linux/slab.h> | |
| 17 | 16 | |
| 18 | 17 | #include "8250.h" |
| 19 | 18 | |
| 20 | 19 | #define UART_DLL_EM 9 |
| 21 | 20 | #define UART_DLM_EM 10 |
| 21 | +#define UART_HCR0_EM 11 | |
| 22 | + | |
| 23 | +/* | |
| 24 | + * A high value for UART_FCR_EM avoids overlapping with existing UART_* | |
| 25 | + * register defines. UART_FCR_EM_HW is the real HW register offset. | |
| 26 | + */ | |
| 27 | +#define UART_FCR_EM 0x10003 | |
| 28 | +#define UART_FCR_EM_HW 3 | |
| 29 | + | |
| 30 | +#define UART_HCR0_EM_SW_RESET BIT(7) /* SW Reset */ | |
| 22 | 31 | |
| 23 | 32 | struct serial8250_em_priv { |
| 24 | − struct clk *sclk; | |
| 25 | 33 | int line; |
| 26 | 34 | }; |
| 27 | 35 | |
| 28 | −static void serial8250_em_serial_out(struct uart_port *p, int offset, int value) | |
| 36 | +static void serial8250_em_serial_out_helper(struct uart_port *p, int offset, | |
| 37 | + int value) | |
| 29 | 38 | { |
| 30 | 39 | switch (offset) { |
| 31 | 40 | case UART_TX: /* TX @ 0x00 */ |
| 32 | 41 | writeb(value, p->membase); |
| 33 | 42 | break; |
| 34 | − case UART_FCR: /* FCR @ 0x0c (+1) */ | |
| 35 | 43 | case UART_LCR: /* LCR @ 0x10 (+1) */ |
| 36 | 44 | case UART_MCR: /* MCR @ 0x14 (+1) */ |
| 37 | 45 | case UART_SCR: /* SCR @ 0x20 (+1) */ |
| 38 | 46 | writel(value, p->membase + ((offset + 1) << 2)); |
| 39 | 47 | break; |
| 48 | + case UART_FCR_EM: | |
| 49 | + writel(value, p->membase + (UART_FCR_EM_HW << 2)); | |
| 50 | + break; | |
| 40 | 51 | case UART_IER: /* IER @ 0x04 */ |
| 41 | 52 | value &= 0x0f; /* only 4 valid bits - not Xscale */ |
| 42 | 53 | fallthrough; |
| 43 | 54 | case UART_DLL_EM: /* DLL @ 0x24 (+9) */ |
| 44 | 55 | case UART_DLM_EM: /* DLM @ 0x28 (+9) */ |
| 56 | + case UART_HCR0_EM: /* HCR0 @ 0x2c */ | |
| 45 | 57 | writel(value, p->membase + (offset << 2)); |
| 58 | + break; | |
| 46 | 59 | } |
| 47 | 60 | } |
| 48 | 61 | |
| @@ -51,20 +64,81 @@ static unsigned int serial8250_em_serial_in(struct uart_port *p, int offset) · 2 unmodified lines | ||
| 51 | 64 | switch (offset) { |
| 52 | 65 | case UART_RX: /* RX @ 0x00 */ |
| 53 | 66 | return readb(p->membase); |
| 67 | + case UART_LCR: /* LCR @ 0x10 (+1) */ | |
| 54 | 68 | case UART_MCR: /* MCR @ 0x14 (+1) */ |
| 55 | 69 | case UART_LSR: /* LSR @ 0x18 (+1) */ |
| 56 | 70 | case UART_MSR: /* MSR @ 0x1c (+1) */ |
| 57 | 71 | case UART_SCR: /* SCR @ 0x20 (+1) */ |
| 58 | 72 | return readl(p->membase + ((offset + 1) << 2)); |
| 73 | + case UART_FCR_EM: | |
| 74 | + return readl(p->membase + (UART_FCR_EM_HW << 2)); | |
| 59 | 75 | case UART_IER: /* IER @ 0x04 */ |
| 60 | 76 | case UART_IIR: /* IIR @ 0x08 */ |
| 61 | 77 | case UART_DLL_EM: /* DLL @ 0x24 (+9) */ |
| 62 | 78 | case UART_DLM_EM: /* DLM @ 0x28 (+9) */ |
| 79 | + case UART_HCR0_EM: /* HCR0 @ 0x2c */ | |
| 63 | 80 | return readl(p->membase + (offset << 2)); |
| 64 | 81 | } |
| 65 | 82 | return 0; |
| 66 | 83 | } |
| 67 | 84 | |
| 85 | +static void serial8250_em_reg_update(struct uart_port *p, int off, int value) | |
| 86 | +{ | |
| 87 | + unsigned int ier, fcr, lcr, mcr, hcr0; | |
| 88 | + | |
| 89 | + ier = serial8250_em_serial_in(p, UART_IER); | |
| 90 | + fcr = serial8250_em_serial_in(p, UART_FCR_EM); | |
| 91 | + lcr = serial8250_em_serial_in(p, UART_LCR); | |
| 92 | + mcr = serial8250_em_serial_in(p, UART_MCR); | |
| 93 | + hcr0 = serial8250_em_serial_in(p, UART_HCR0_EM); | |
| 94 | + | |
| 95 | + serial8250_em_serial_out_helper(p, UART_FCR_EM, fcr | | |
| 96 | + UART_FCR_CLEAR_RCVR | | |
| 97 | + UART_FCR_CLEAR_XMIT); | |
| 98 | + serial8250_em_serial_out_helper(p, UART_HCR0_EM, hcr0 | | |
| 99 | + UART_HCR0_EM_SW_RESET); | |
| 100 | + serial8250_em_serial_out_helper(p, UART_HCR0_EM, hcr0 & | |
| 101 | + ~UART_HCR0_EM_SW_RESET); | |
| 102 | + | |
| 103 | + switch (off) { | |
| 104 | + case UART_FCR_EM: | |
| 105 | + fcr = value; | |
| 106 | + break; | |
| 107 | + case UART_LCR: | |
| 108 | + lcr = value; | |
| 109 | + break; | |
| 110 | + case UART_MCR: | |
| 111 | + mcr = value; | |
| 112 | + break; | |
| 113 | + } | |
| 114 | + | |
| 115 | + serial8250_em_serial_out_helper(p, UART_IER, ier); | |
| 116 | + serial8250_em_serial_out_helper(p, UART_FCR_EM, fcr); | |
| 117 | + serial8250_em_serial_out_helper(p, UART_MCR, mcr); | |
| 118 | + serial8250_em_serial_out_helper(p, UART_LCR, lcr); | |
| 119 | + serial8250_em_serial_out_helper(p, UART_HCR0_EM, hcr0); | |
| 120 | +} | |
| 121 | + | |
| 122 | +static void serial8250_em_serial_out(struct uart_port *p, int offset, int value) | |
| 123 | +{ | |
| 124 | + switch (offset) { | |
| 125 | + case UART_TX: | |
| 126 | + case UART_SCR: | |
| 127 | + case UART_IER: | |
| 128 | + case UART_DLL_EM: | |
| 129 | + case UART_DLM_EM: | |
| 130 | + serial8250_em_serial_out_helper(p, offset, value); | |
| 131 | + break; | |
| 132 | + case UART_FCR: | |
| 133 | + serial8250_em_reg_update(p, UART_FCR_EM, value); | |
| 134 | + break; | |
| 135 | + case UART_LCR: | |
| 136 | + case UART_MCR: | |
| 137 | + serial8250_em_reg_update(p, offset, value); | |
| 138 | + break; | |
| 139 | + } | |
| 140 | +} | |
| 141 | + | |
| 68 | 142 | static int serial8250_em_serial_dl_read(struct uart_8250_port *up) |
| 69 | 143 | { |
| 70 | 144 | return serial_in(up, UART_DLL_EM) | serial_in(up, UART_DLM_EM) << 8; |
| @@ -79,8 +153,10 @@ static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value) · 8 unmodified lines | ||
| 79 | 153 | static int serial8250_em_probe(struct platform_device *pdev) |
| 80 | 154 | { |
| 81 | 155 | struct serial8250_em_priv *priv; |
| 156 | + struct device *dev = &pdev->dev; | |
| 82 | 157 | struct uart_8250_port up; |
| 83 | 158 | struct resource *regs; |
| 159 | + struct clk *sclk; | |
| 84 | 160 | int irq, ret; |
| 85 | 161 | |
| 86 | 162 | irq = platform_get_irq(pdev, 0); |
| @@ -88,31 +164,26 @@ static int serial8250_em_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 88 | 164 | return irq; |
| 89 | 165 | |
| 90 | 166 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 91 | − if (!regs) { | |
| 92 | − dev_err(&pdev->dev, "missing registers\n"); | |
| 93 | − return -EINVAL; | |
| 94 | − } | |
| 167 | + if (!regs) | |
| 168 | + return dev_err_probe(dev, -EINVAL, "missing registers\n"); | |
| 95 | 169 | |
| 96 | − priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | |
| 170 | + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | |
| 97 | 171 | if (!priv) |
| 98 | 172 | return -ENOMEM; |
| 99 | 173 | |
| 100 | − priv->sclk = devm_clk_get(&pdev->dev, "sclk"); | |
| 101 | − if (IS_ERR(priv->sclk)) { | |
| 102 | − dev_err(&pdev->dev, "unable to get clock\n"); | |
| 103 | − return PTR_ERR(priv->sclk); | |
| 104 | − } | |
| 174 | + sclk = devm_clk_get_enabled(dev, "sclk"); | |
| 175 | + if (IS_ERR(sclk)) | |
| 176 | + return dev_err_probe(dev, PTR_ERR(sclk), "unable to get clock\n"); | |
| 105 | 177 | |
| 106 | 178 | memset(&up, 0, sizeof(up)); |
| 107 | 179 | up.port.mapbase = regs->start; |
| 108 | 180 | up.port.irq = irq; |
| 109 | 181 | up.port.type = PORT_16750; |
| 110 | 182 | up.port.flags = UPF_FIXED_PORT | UPF_IOREMAP | UPF_FIXED_TYPE; |
| 111 | − up.port.dev = &pdev->dev; | |
| 183 | + up.port.dev = dev; | |
| 112 | 184 | up.port.private_data = priv; |
| 113 | 185 | |
| 114 | − clk_prepare_enable(priv->sclk); | |
| 115 | − up.port.uartclk = clk_get_rate(priv->sclk); | |
| 186 | + up.port.uartclk = clk_get_rate(sclk); | |
| 116 | 187 | |
| 117 | 188 | up.port.iotype = UPIO_MEM32; |
| 118 | 189 | up.port.serial_in = serial8250_em_serial_in; |
| @@ -121,11 +192,8 @@ static int serial8250_em_probe(struct platform_device *pdev) · 2 unmodified lines | ||
| 121 | 192 | up.dl_write = serial8250_em_serial_dl_write; |
| 122 | 193 | |
| 123 | 194 | ret = serial8250_register_8250_port(&up); |
| 124 | − if (ret < 0) { | |
| 125 | − dev_err(&pdev->dev, "unable to register 8250 port\n"); | |
| 126 | − clk_disable_unprepare(priv->sclk); | |
| 127 | − return ret; | |
| 128 | − } | |
| 195 | + if (ret < 0) | |
| 196 | + return dev_err_probe(dev, ret, "unable to register 8250 port\n"); | |
| 129 | 197 | |
| 130 | 198 | priv->line = ret; |
| 131 | 199 | platform_set_drvdata(pdev, priv); |
| @@ -137,7 +205,6 @@ static int serial8250_em_remove(struct platform_device *pdev) · 5 unmodified lines | ||
| 137 | 205 | struct serial8250_em_priv *priv = platform_get_drvdata(pdev); |
| 138 | 206 | |
| 139 | 207 | serial8250_unregister_port(priv->line); |
| 140 | − clk_disable_unprepare(priv->sclk); | |
| 141 | 208 | return 0; |
| 142 | 209 | } |
| 143 | 210 | |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/moduleparam.h> |
| 16 | 16 | #include <linux/ioport.h> |
| 17 | 17 | #include <linux/init.h> |
| 18 | +#include <linux/irq.h> | |
| 18 | 19 | #include <linux/console.h> |
| 19 | 20 | #include <linux/gpio/consumer.h> |
| 20 | 21 | #include <linux/sysrq.h> |
| @@ -1932,6 +1933,7 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) · 1911 unmodified lines | ||
| 1932 | 1933 | int serial8250_handle_irq(struct uart_port *port, unsigned int iir) |
| 1933 | 1934 | { |
| 1934 | 1935 | struct uart_8250_port *up = up_to_u8250p(port); |
| 1936 | + struct tty_port *tport = &port->state->port; | |
| 1935 | 1937 | bool skip_rx = false; |
| 1936 | 1938 | unsigned long flags; |
| 1937 | 1939 | u16 status; |
| @@ -1957,6 +1959,8 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) · 19 unmodified lines | ||
| 1957 | 1959 | skip_rx = true; |
| 1958 | 1960 | |
| 1959 | 1961 | if (status & (UART_LSR_DR | UART_LSR_BI) && !skip_rx) { |
| 1962 | + if (irqd_is_wakeup_set(irq_get_irq_data(port->irq))) | |
| 1963 | + pm_wakeup_event(tport->tty->dev, 0); | |
| 1960 | 1964 | if (!up->dma || handle_rx_dma(up, iir)) |
| 1961 | 1965 | status = serial8250_rx_chars(up, status); |
| 1962 | 1966 | } |
| @@ -2016,18 +2020,19 @@ static int serial8250_tx_threshold_handle_irq(struct uart_port *port) · 53 unmodified lines | ||
| 2016 | 2020 | static unsigned int serial8250_tx_empty(struct uart_port *port) |
| 2017 | 2021 | { |
| 2018 | 2022 | struct uart_8250_port *up = up_to_u8250p(port); |
| 2023 | + unsigned int result = 0; | |
| 2019 | 2024 | unsigned long flags; |
| 2020 | − u16 lsr; | |
| 2021 | 2025 | |
| 2022 | 2026 | serial8250_rpm_get(up); |
| 2023 | 2027 | |
| 2024 | 2028 | spin_lock_irqsave(&port->lock, flags); |
| 2025 | − lsr = serial_lsr_in(up); | |
| 2029 | + if (!serial8250_tx_dma_running(up) && uart_lsr_tx_empty(serial_lsr_in(up))) | |
| 2030 | + result = TIOCSER_TEMT; | |
| 2026 | 2031 | spin_unlock_irqrestore(&port->lock, flags); |
| 2027 | 2032 | |
| 2028 | 2033 | serial8250_rpm_put(up); |
| 2029 | 2034 | |
| 2030 | − return uart_lsr_tx_empty(lsr) ? TIOCSER_TEMT : 0; | |
| 2035 | + return result; | |
| 2031 | 2036 | } |
| 2032 | 2037 | |
| 2033 | 2038 | unsigned int serial8250_do_get_mctrl(struct uart_port *port) |
| @@ -248,13 +248,6 @@ config SERIAL_SAMSUNG · 247 unmodified lines | ||
| 248 | 248 | |
| 249 | 249 | Choose Y/M here only if you build for such SoC. |
| 250 | 250 | |
| 251 | −config SERIAL_SAMSUNG_UARTS_4 | |
| 252 | − bool | |
| 253 | − depends on SERIAL_SAMSUNG | |
| 254 | − default y | |
| 255 | − help | |
| 256 | − Internal node for the common case of 4 Samsung compatible UARTs | |
| 257 | − | |
| 258 | 251 | config SERIAL_SAMSUNG_UARTS |
| 259 | 252 | int |
| 260 | 253 | depends on SERIAL_SAMSUNG |
| @@ -958,7 +951,7 @@ config SERIAL_OMAP_CONSOLE · 697 unmodified lines | ||
| 958 | 951 | config SERIAL_SIFIVE |
| 959 | 952 | tristate "SiFive UART support" |
| 960 | 953 | depends on OF |
| 961 | − default SOC_SIFIVE || SOC_CANAAN | |
| 954 | + default ARCH_SIFIVE || ARCH_CANAAN | |
| 962 | 955 | select SERIAL_CORE |
| 963 | 956 | help |
| 964 | 957 | Select this option if you are building a kernel for a device that |
| @@ -968,7 +961,7 @@ config SERIAL_SIFIVE · 3 unmodified lines | ||
| 968 | 961 | config SERIAL_SIFIVE_CONSOLE |
| 969 | 962 | bool "Console on SiFive UART" |
| 970 | 963 | depends on SERIAL_SIFIVE=y |
| 971 | − default SOC_SIFIVE || SOC_CANAAN | |
| 964 | + default ARCH_SIFIVE || ARCH_CANAAN | |
| 972 | 965 | select SERIAL_CORE_CONSOLE |
| 973 | 966 | select SERIAL_EARLYCON |
| 974 | 967 | help |
| @@ -596,6 +596,40 @@ static int bcm_uart_verify_port(struct uart_port *port, · 595 unmodified lines | ||
| 596 | 596 | return 0; |
| 597 | 597 | } |
| 598 | 598 | |
| 599 | +#ifdef CONFIG_CONSOLE_POLL | |
| 600 | +/* | |
| 601 | + * return true when outstanding tx equals fifo size | |
| 602 | + */ | |
| 603 | +static bool bcm_uart_tx_full(struct uart_port *port) | |
| 604 | +{ | |
| 605 | + unsigned int val; | |
| 606 | + | |
| 607 | + val = bcm_uart_readl(port, UART_MCTL_REG); | |
| 608 | + val = (val & UART_MCTL_TXFIFOFILL_MASK) >> UART_MCTL_TXFIFOFILL_SHIFT; | |
| 609 | + return !(port->fifosize - val); | |
| 610 | +} | |
| 611 | + | |
| 612 | +static int bcm_uart_poll_get_char(struct uart_port *port) | |
| 613 | +{ | |
| 614 | + unsigned int iestat; | |
| 615 | + | |
| 616 | + iestat = bcm_uart_readl(port, UART_IR_REG); | |
| 617 | + if (!(iestat & UART_IR_STAT(UART_IR_RXNOTEMPTY))) | |
| 618 | + return NO_POLL_CHAR; | |
| 619 | + | |
| 620 | + return bcm_uart_readl(port, UART_FIFO_REG); | |
| 621 | +} | |
| 622 | + | |
| 623 | +static void bcm_uart_poll_put_char(struct uart_port *port, unsigned char c) | |
| 624 | +{ | |
| 625 | + while (bcm_uart_tx_full(port)) { | |
| 626 | + cpu_relax(); | |
| 627 | + } | |
| 628 | + | |
| 629 | + bcm_uart_writel(port, c, UART_FIFO_REG); | |
| 630 | +} | |
| 631 | +#endif | |
| 632 | + | |
| 599 | 633 | /* serial core callbacks */ |
| 600 | 634 | static const struct uart_ops bcm_uart_ops = { |
| 601 | 635 | .tx_empty = bcm_uart_tx_empty, |
| @@ -614,6 +648,10 @@ static const struct uart_ops bcm_uart_ops = { · 12 unmodified lines | ||
| 614 | 648 | .request_port = bcm_uart_request_port, |
| 615 | 649 | .config_port = bcm_uart_config_port, |
| 616 | 650 | .verify_port = bcm_uart_verify_port, |
| 651 | +#ifdef CONFIG_CONSOLE_POLL | |
| 652 | + .poll_get_char = bcm_uart_poll_get_char, | |
| 653 | + .poll_put_char = bcm_uart_poll_put_char, | |
| 654 | +#endif | |
| 617 | 655 | }; |
| 618 | 656 | |
| 619 | 657 | |
| @@ -678,15 +678,14 @@ static int cpm_uart_tx_pump(struct uart_port *port) · 677 unmodified lines | ||
| 678 | 678 | /* Pick next descriptor and fill from buffer */ |
| 679 | 679 | bdp = pinfo->tx_cur; |
| 680 | 680 | |
| 681 | − while (!(in_be16(&bdp->cbd_sc) & BD_SC_READY) && | |
| 682 | − xmit->tail != xmit->head) { | |
| 681 | + while (!(in_be16(&bdp->cbd_sc) & BD_SC_READY) && !uart_circ_empty(xmit)) { | |
| 683 | 682 | count = 0; |
| 684 | 683 | p = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo); |
| 685 | 684 | while (count < pinfo->tx_fifosize) { |
| 686 | 685 | *p++ = xmit->buf[xmit->tail]; |
| 687 | 686 | uart_xmit_advance(port, 1); |
| 688 | 687 | count++; |
| 689 | − if (xmit->head == xmit->tail) | |
| 688 | + if (uart_circ_empty(xmit)) | |
| 690 | 689 | break; |
| 691 | 690 | } |
| 692 | 691 | out_be16(&bdp->cbd_datlen, count); |
| @@ -1296,7 +1296,7 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport) · 1295 unmodified lines | ||
| 1296 | 1296 | * 10ms at any baud rate. |
| 1297 | 1297 | */ |
| 1298 | 1298 | sport->rx_dma_rng_buf_len = (DMA_RX_TIMEOUT * baud / bits / 1000) * 2; |
| 1299 | − sport->rx_dma_rng_buf_len = (1 << (fls(sport->rx_dma_rng_buf_len) - 1)); | |
| 1299 | + sport->rx_dma_rng_buf_len = (1 << fls(sport->rx_dma_rng_buf_len)); | |
| 1300 | 1300 | if (sport->rx_dma_rng_buf_len < 16) |
| 1301 | 1301 | sport->rx_dma_rng_buf_len = 16; |
| 1302 | 1302 | |
| @@ -1406,12 +1406,12 @@ static int lpuart32_config_rs485(struct uart_port *port, struct ktermios *termio · 103 unmodified lines | ||
| 1406 | 1406 | struct lpuart_port, port); |
| 1407 | 1407 | |
| 1408 | 1408 | unsigned long modem = lpuart32_read(&sport->port, UARTMODIR) |
| 1409 | − & ~(UARTMODEM_TXRTSPOL | UARTMODEM_TXRTSE); | |
| 1409 | + & ~(UARTMODIR_TXRTSPOL | UARTMODIR_TXRTSE); | |
| 1410 | 1410 | lpuart32_write(&sport->port, modem, UARTMODIR); |
| 1411 | 1411 | |
| 1412 | 1412 | if (rs485->flags & SER_RS485_ENABLED) { |
| 1413 | 1413 | /* Enable auto RS-485 RTS mode */ |
| 1414 | − modem |= UARTMODEM_TXRTSE; | |
| 1414 | + modem |= UARTMODIR_TXRTSE; | |
| 1415 | 1415 | |
| 1416 | 1416 | /* |
| 1417 | 1417 | * The hardware defaults to RTS logic HIGH while transfer. |
| @@ -1420,9 +1420,9 @@ static int lpuart32_config_rs485(struct uart_port *port, struct ktermios *termio · 2 unmodified lines | ||
| 1420 | 1420 | * Note: UART is assumed to be active high. |
| 1421 | 1421 | */ |
| 1422 | 1422 | if (rs485->flags & SER_RS485_RTS_ON_SEND) |
| 1423 | − modem |= UARTMODEM_TXRTSPOL; | |
| 1423 | + modem |= UARTMODIR_TXRTSPOL; | |
| 1424 | 1424 | else if (rs485->flags & SER_RS485_RTS_AFTER_SEND) |
| 1425 | − modem &= ~UARTMODEM_TXRTSPOL; | |
| 1425 | + modem &= ~UARTMODIR_TXRTSPOL; | |
| 1426 | 1426 | } |
| 1427 | 1427 | |
| 1428 | 1428 | lpuart32_write(&sport->port, modem, UARTMODIR); |
| @@ -289,20 +289,6 @@ static inline int imx_uart_is_imx1(struct imx_port *sport) · 288 unmodified lines | ||
| 289 | 289 | return sport->devdata->devtype == IMX1_UART; |
| 290 | 290 | } |
| 291 | 291 | |
| 292 | −static inline int imx_uart_is_imx21(struct imx_port *sport) | |
| 293 | −{ | |
| 294 | − return sport->devdata->devtype == IMX21_UART; | |
| 295 | −} | |
| 296 | − | |
| 297 | −static inline int imx_uart_is_imx53(struct imx_port *sport) | |
| 298 | −{ | |
| 299 | − return sport->devdata->devtype == IMX53_UART; | |
| 300 | −} | |
| 301 | − | |
| 302 | −static inline int imx_uart_is_imx6q(struct imx_port *sport) | |
| 303 | −{ | |
| 304 | − return sport->devdata->devtype == IMX6Q_UART; | |
| 305 | −} | |
| 306 | 292 | /* |
| 307 | 293 | * Save and restore functions for UCR1, UCR2 and UCR3 registers |
| 308 | 294 | */ |
| @@ -1808,9 +1794,7 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios, · 1499 unmodified lines | ||
| 1808 | 1794 | |
| 1809 | 1795 | static const char *imx_uart_type(struct uart_port *port) |
| 1810 | 1796 | { |
| 1811 | − struct imx_port *sport = (struct imx_port *)port; | |
| 1812 | − | |
| 1813 | − return sport->port.type == PORT_IMX ? "IMX" : NULL; | |
| 1797 | + return port->type == PORT_IMX ? "IMX" : NULL; | |
| 1814 | 1798 | } |
| 1815 | 1799 | |
| 1816 | 1800 | /* |
| @@ -1818,10 +1802,8 @@ static const char *imx_uart_type(struct uart_port *port) · 1 unmodified line | ||
| 1818 | 1802 | */ |
| 1819 | 1803 | static void imx_uart_config_port(struct uart_port *port, int flags) |
| 1820 | 1804 | { |
| 1821 | − struct imx_port *sport = (struct imx_port *)port; | |
| 1822 | − | |
| 1823 | 1805 | if (flags & UART_CONFIG_TYPE) |
| 1824 | − sport->port.type = PORT_IMX; | |
| 1806 | + port->type = PORT_IMX; | |
| 1825 | 1807 | } |
| 1826 | 1808 | |
| 1827 | 1809 | /* |
| @@ -1832,20 +1814,19 @@ static void imx_uart_config_port(struct uart_port *port, int flags) · 4 unmodified lines | ||
| 1832 | 1814 | static int |
| 1833 | 1815 | imx_uart_verify_port(struct uart_port *port, struct serial_struct *ser) |
| 1834 | 1816 | { |
| 1835 | − struct imx_port *sport = (struct imx_port *)port; | |
| 1836 | 1817 | int ret = 0; |
| 1837 | 1818 | |
| 1838 | 1819 | if (ser->type != PORT_UNKNOWN && ser->type != PORT_IMX) |
| 1839 | 1820 | ret = -EINVAL; |
| 1840 | − if (sport->port.irq != ser->irq) | |
| 1821 | + if (port->irq != ser->irq) | |
| 1841 | 1822 | ret = -EINVAL; |
| 1842 | 1823 | if (ser->io_type != UPIO_MEM) |
| 1843 | 1824 | ret = -EINVAL; |
| 1844 | − if (sport->port.uartclk / 16 != ser->baud_base) | |
| 1825 | + if (port->uartclk / 16 != ser->baud_base) | |
| 1845 | 1826 | ret = -EINVAL; |
| 1846 | − if (sport->port.mapbase != (unsigned long)ser->iomem_base) | |
| 1827 | + if (port->mapbase != (unsigned long)ser->iomem_base) | |
| 1847 | 1828 | ret = -EINVAL; |
| 1848 | − if (sport->port.iobase != ser->port) | |
| 1829 | + if (port->iobase != ser->port) | |
| 1849 | 1830 | ret = -EINVAL; |
| 1850 | 1831 | if (ser->hub6 != 0) |
| 1851 | 1832 | ret = -EINVAL; |
| @@ -2262,21 +2243,16 @@ static int imx_uart_probe(struct platform_device *pdev) · 410 unmodified lines | ||
| 2262 | 2243 | } |
| 2263 | 2244 | sport->port.line = ret; |
| 2264 | 2245 | |
| 2265 | − if (of_get_property(np, "uart-has-rtscts", NULL) || | |
| 2266 | − of_get_property(np, "fsl,uart-has-rtscts", NULL) /* deprecated */) | |
| 2267 | − sport->have_rtscts = 1; | |
| 2246 | + sport->have_rtscts = of_property_read_bool(np, "uart-has-rtscts") || | |
| 2247 | + of_property_read_bool(np, "fsl,uart-has-rtscts"); /* deprecated */ | |
| 2268 | 2248 | |
| 2269 | − if (of_get_property(np, "fsl,dte-mode", NULL)) | |
| 2270 | − sport->dte_mode = 1; | |
| 2249 | + sport->dte_mode = of_property_read_bool(np, "fsl,dte-mode"); | |
| 2271 | 2250 | |
| 2272 | − if (of_get_property(np, "rts-gpios", NULL)) | |
| 2273 | − sport->have_rtsgpio = 1; | |
| 2251 | + sport->have_rtsgpio = of_property_present(np, "rts-gpios"); | |
| 2274 | 2252 | |
| 2275 | − if (of_get_property(np, "fsl,inverted-tx", NULL)) | |
| 2276 | − sport->inverted_tx = 1; | |
| 2253 | + sport->inverted_tx = of_property_read_bool(np, "fsl,inverted-tx"); | |
| 2277 | 2254 | |
| 2278 | − if (of_get_property(np, "fsl,inverted-rx", NULL)) | |
| 2279 | − sport->inverted_rx = 1; | |
| 2255 | + sport->inverted_rx = of_property_read_bool(np, "fsl,inverted-rx"); | |
| 2280 | 2256 | |
| 2281 | 2257 | if (!of_property_read_u32_array(np, "fsl,dma-info", dma_buf_conf, 2)) { |
| 2282 | 2258 | sport->rx_period_length = dma_buf_conf[0]; |
| @@ -525,6 +525,11 @@ static bool max310x_reg_precious(struct device *dev, unsigned int reg) · 524 unmodified lines | ||
| 525 | 525 | return false; |
| 526 | 526 | } |
| 527 | 527 | |
| 528 | +static bool max310x_reg_noinc(struct device *dev, unsigned int reg) | |
| 529 | +{ | |
| 530 | + return reg == MAX310X_RHR_REG; | |
| 531 | +} | |
| 532 | + | |
| 528 | 533 | static int max310x_set_baud(struct uart_port *port, int baud) |
| 529 | 534 | { |
| 530 | 535 | unsigned int mode = 0, div = 0, frac = 0, c = 0, F = 0; |
| @@ -651,14 +656,14 @@ static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned int · 120 unmodified lines | ||
| 651 | 656 | { |
| 652 | 657 | struct max310x_one *one = to_max310x_port(port); |
| 653 | 658 | |
| 654 | − regmap_raw_write(one->regmap, MAX310X_THR_REG, txbuf, len); | |
| 659 | + regmap_noinc_write(one->regmap, MAX310X_THR_REG, txbuf, len); | |
| 655 | 660 | } |
| 656 | 661 | |
| 657 | 662 | static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned int len) |
| 658 | 663 | { |
| 659 | 664 | struct max310x_one *one = to_max310x_port(port); |
| 660 | 665 | |
| 661 | − regmap_raw_read(one->regmap, MAX310X_RHR_REG, rxbuf, len); | |
| 666 | + regmap_noinc_read(one->regmap, MAX310X_RHR_REG, rxbuf, len); | |
| 662 | 667 | } |
| 663 | 668 | |
| 664 | 669 | static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen) |
| @@ -1468,6 +1473,10 @@ static struct regmap_config regcfg = { · 803 unmodified lines | ||
| 1468 | 1473 | .writeable_reg = max310x_reg_writeable, |
| 1469 | 1474 | .volatile_reg = max310x_reg_volatile, |
| 1470 | 1475 | .precious_reg = max310x_reg_precious, |
| 1476 | + .writeable_noinc_reg = max310x_reg_noinc, | |
| 1477 | + .readable_noinc_reg = max310x_reg_noinc, | |
| 1478 | + .max_raw_read = MAX310X_FIFO_SIZE, | |
| 1479 | + .max_raw_write = MAX310X_FIFO_SIZE, | |
| 1471 | 1480 | }; |
| 1472 | 1481 | |
| 1473 | 1482 | #ifdef CONFIG_SPI_MASTER |
| @@ -1553,6 +1562,10 @@ static struct regmap_config regcfg_i2c = { · 79 unmodified lines | ||
| 1553 | 1562 | .volatile_reg = max310x_reg_volatile, |
| 1554 | 1563 | .precious_reg = max310x_reg_precious, |
| 1555 | 1564 | .max_register = MAX310X_I2C_REVID_EXTREG, |
| 1565 | + .writeable_noinc_reg = max310x_reg_noinc, | |
| 1566 | + .readable_noinc_reg = max310x_reg_noinc, | |
| 1567 | + .max_raw_read = MAX310X_FIFO_SIZE, | |
| 1568 | + .max_raw_write = MAX310X_FIFO_SIZE, | |
| 1556 | 1569 | }; |
| 1557 | 1570 | |
| 1558 | 1571 | static const struct max310x_if_cfg max310x_i2c_if_cfg = { |
| @@ -779,7 +779,7 @@ static int meson_uart_remove(struct platform_device *pdev) · 778 unmodified lines | ||
| 779 | 779 | return 0; |
| 780 | 780 | } |
| 781 | 781 | |
| 782 | −static struct meson_uart_data s4_uart_data = { | |
| 782 | +static struct meson_uart_data meson_g12a_uart_data = { | |
| 783 | 783 | .has_xtal_div2 = true, |
| 784 | 784 | }; |
| 785 | 785 | |
| @@ -788,9 +788,13 @@ static const struct of_device_id meson_uart_dt_match[] = { · 2 unmodified lines | ||
| 788 | 788 | { .compatible = "amlogic,meson8-uart" }, |
| 789 | 789 | { .compatible = "amlogic,meson8b-uart" }, |
| 790 | 790 | { .compatible = "amlogic,meson-gx-uart" }, |
| 791 | + { | |
| 792 | + .compatible = "amlogic,meson-g12a-uart", | |
| 793 | + .data = (void *)&meson_g12a_uart_data, | |
| 794 | + }, | |
| 791 | 795 | { |
| 792 | 796 | .compatible = "amlogic,meson-s4-uart", |
| 793 | − .data = (void *)&s4_uart_data, | |
| 797 | + .data = (void *)&meson_g12a_uart_data, | |
| 794 | 798 | }, |
| 795 | 799 | { /* sentinel */ }, |
| 796 | 800 | }; |
| @@ -1587,8 +1587,8 @@ static int mxs_auart_probe(struct platform_device *pdev) · 1586 unmodified lines | ||
| 1587 | 1587 | } |
| 1588 | 1588 | s->port.line = ret; |
| 1589 | 1589 | |
| 1590 | − if (of_get_property(np, "uart-has-rtscts", NULL) || | |
| 1591 | − of_get_property(np, "fsl,uart-has-rtscts", NULL) /* deprecated */) | |
| 1590 | + if (of_property_read_bool(np, "uart-has-rtscts") || | |
| 1591 | + of_property_read_bool(np, "fsl,uart-has-rtscts") /* deprecated */) | |
| 1592 | 1592 | set_bit(MXS_AUART_RTSCTS, &s->flags); |
| 1593 | 1593 | |
| 1594 | 1594 | if (s->port.line >= ARRAY_SIZE(auart_port)) { |
| @@ -854,21 +854,19 @@ static void qcom_geni_serial_stop_tx(struct uart_port *uport) · 853 unmodified lines | ||
| 854 | 854 | } |
| 855 | 855 | |
| 856 | 856 | static void qcom_geni_serial_send_chunk_fifo(struct uart_port *uport, |
| 857 | − unsigned int chunk) | |
| 857 | + unsigned int remaining) | |
| 858 | 858 | { |
| 859 | 859 | struct qcom_geni_serial_port *port = to_dev_port(uport); |
| 860 | 860 | struct circ_buf *xmit = &uport->state->xmit; |
| 861 | − unsigned int tx_bytes, c, remaining = chunk; | |
| 861 | + unsigned int tx_bytes; | |
| 862 | 862 | u8 buf[BYTES_PER_FIFO_WORD]; |
| 863 | 863 | |
| 864 | 864 | while (remaining) { |
| 865 | 865 | memset(buf, 0, sizeof(buf)); |
| 866 | 866 | tx_bytes = min(remaining, BYTES_PER_FIFO_WORD); |
| 867 | 867 | |
| 868 | − for (c = 0; c < tx_bytes ; c++) { | |
| 869 | − buf[c] = xmit->buf[xmit->tail]; | |
| 870 | − uart_xmit_advance(uport, 1); | |
| 871 | − } | |
| 868 | + memcpy(buf, &xmit->buf[xmit->tail], tx_bytes); | |
| 869 | + uart_xmit_advance(uport, tx_bytes); | |
| 872 | 870 | |
| 873 | 871 | iowrite32_rep(uport->membase + SE_GENI_TX_FIFOn, buf, 1); |
| 874 | 872 | |
| @@ -1535,6 +1533,7 @@ static const struct uart_ops qcom_geni_console_pops = { · 660 unmodified lines | ||
| 1535 | 1533 | #ifdef CONFIG_CONSOLE_POLL |
| 1536 | 1534 | .poll_get_char = qcom_geni_serial_get_char, |
| 1537 | 1535 | .poll_put_char = qcom_geni_serial_poll_put_char, |
| 1536 | + .poll_init = qcom_geni_serial_port_setup, | |
| 1538 | 1537 | #endif |
| 1539 | 1538 | .pm = qcom_geni_serial_pm, |
| 1540 | 1539 | }; |
| @@ -41,7 +41,7 @@ · 40 unmodified lines | ||
| 41 | 41 | #include <asm/sibyte/swarm.h> |
| 42 | 42 | |
| 43 | 43 | |
| 44 | −#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) | |
| 44 | +#if defined(CONFIG_SIBYTE_BCM1x80) | |
| 45 | 45 | #include <asm/sibyte/bcm1480_regs.h> |
| 46 | 46 | #include <asm/sibyte/bcm1480_int.h> |
| 47 | 47 | |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/init.h> |
| 16 | 16 | #include <linux/console.h> |
| 17 | 17 | #include <linux/gpio/consumer.h> |
| 18 | +#include <linux/kernel.h> | |
| 18 | 19 | #include <linux/of.h> |
| 19 | 20 | #include <linux/proc_fs.h> |
| 20 | 21 | #include <linux/seq_file.h> |
| @@ -48,9 +49,6 @@ static struct lock_class_key port_lock_key; · 27 unmodified lines | ||
| 48 | 49 | */ |
| 49 | 50 | #define RS485_MAX_RTS_DELAY 100 /* msecs */ |
| 50 | 51 | |
| 51 | −static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, | |
| 52 | − const struct ktermios *old_termios); | |
| 53 | −static void uart_wait_until_sent(struct tty_struct *tty, int timeout); | |
| 54 | 52 | static void uart_change_pm(struct uart_state *state, |
| 55 | 53 | enum uart_pm_state pm_state); |
| 56 | 54 | |
| @@ -137,7 +135,7 @@ static void __uart_start(struct tty_struct *tty) · 80 unmodified lines | ||
| 137 | 135 | struct uart_state *state = tty->driver_data; |
| 138 | 136 | struct uart_port *port = state->uart_port; |
| 139 | 137 | |
| 140 | − if (port && !uart_tx_stopped(port)) | |
| 138 | + if (port && !(port->flags & UPF_DEAD) && !uart_tx_stopped(port)) | |
| 141 | 139 | port->ops->start_tx(port); |
| 142 | 140 | } |
| 143 | 141 | |
| @@ -177,6 +175,51 @@ static void uart_port_dtr_rts(struct uart_port *uport, bool active) · 33 unmodified lines | ||
| 177 | 175 | uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); |
| 178 | 176 | } |
| 179 | 177 | |
| 178 | +/* Caller holds port mutex */ | |
| 179 | +static void uart_change_line_settings(struct tty_struct *tty, struct uart_state *state, | |
| 180 | + const struct ktermios *old_termios) | |
| 181 | +{ | |
| 182 | + struct uart_port *uport = uart_port_check(state); | |
| 183 | + struct ktermios *termios; | |
| 184 | + bool old_hw_stopped; | |
| 185 | + | |
| 186 | + /* | |
| 187 | + * If we have no tty, termios, or the port does not exist, | |
| 188 | + * then we can't set the parameters for this port. | |
| 189 | + */ | |
| 190 | + if (!tty || uport->type == PORT_UNKNOWN) | |
| 191 | + return; | |
| 192 | + | |
| 193 | + termios = &tty->termios; | |
| 194 | + uport->ops->set_termios(uport, termios, old_termios); | |
| 195 | + | |
| 196 | + /* | |
| 197 | + * Set modem status enables based on termios cflag | |
| 198 | + */ | |
| 199 | + spin_lock_irq(&uport->lock); | |
| 200 | + if (termios->c_cflag & CRTSCTS) | |
| 201 | + uport->status |= UPSTAT_CTS_ENABLE; | |
| 202 | + else | |
| 203 | + uport->status &= ~UPSTAT_CTS_ENABLE; | |
| 204 | + | |
| 205 | + if (termios->c_cflag & CLOCAL) | |
| 206 | + uport->status &= ~UPSTAT_DCD_ENABLE; | |
| 207 | + else | |
| 208 | + uport->status |= UPSTAT_DCD_ENABLE; | |
| 209 | + | |
| 210 | + /* reset sw-assisted CTS flow control based on (possibly) new mode */ | |
| 211 | + old_hw_stopped = uport->hw_stopped; | |
| 212 | + uport->hw_stopped = uart_softcts_mode(uport) && | |
| 213 | + !(uport->ops->get_mctrl(uport) & TIOCM_CTS); | |
| 214 | + if (uport->hw_stopped != old_hw_stopped) { | |
| 215 | + if (!old_hw_stopped) | |
| 216 | + uport->ops->stop_tx(uport); | |
| 217 | + else | |
| 218 | + __uart_start(tty); | |
| 219 | + } | |
| 220 | + spin_unlock_irq(&uport->lock); | |
| 221 | +} | |
| 222 | + | |
| 180 | 223 | /* |
| 181 | 224 | * Startup the port. This will be called once per open. All calls |
| 182 | 225 | * will be serialised by the per-port mutex. |
| @@ -232,7 +275,7 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, · 49 unmodified lines | ||
| 232 | 275 | /* |
| 233 | 276 | * Initialise the hardware port settings. |
| 234 | 277 | */ |
| 235 | − uart_change_speed(tty, state, NULL); | |
| 278 | + uart_change_line_settings(tty, state, NULL); | |
| 236 | 279 | |
| 237 | 280 | /* |
| 238 | 281 | * Setup the RTS and DTR signals once the |
| @@ -485,52 +528,6 @@ uart_get_divisor(struct uart_port *port, unsigned int baud) · 246 unmodified lines | ||
| 485 | 528 | } |
| 486 | 529 | EXPORT_SYMBOL(uart_get_divisor); |
| 487 | 530 | |
| 488 | −/* Caller holds port mutex */ | |
| 489 | −static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, | |
| 490 | − const struct ktermios *old_termios) | |
| 491 | −{ | |
| 492 | − struct uart_port *uport = uart_port_check(state); | |
| 493 | − struct ktermios *termios; | |
| 494 | − int hw_stopped; | |
| 495 | − | |
| 496 | − /* | |
| 497 | − * If we have no tty, termios, or the port does not exist, | |
| 498 | − * then we can't set the parameters for this port. | |
| 499 | − */ | |
| 500 | − if (!tty || uport->type == PORT_UNKNOWN) | |
| 501 | − return; | |
| 502 | − | |
| 503 | − termios = &tty->termios; | |
| 504 | − uport->ops->set_termios(uport, termios, old_termios); | |
| 505 | − | |
| 506 | − /* | |
| 507 | − * Set modem status enables based on termios cflag | |
| 508 | − */ | |
| 509 | − spin_lock_irq(&uport->lock); | |
| 510 | − if (termios->c_cflag & CRTSCTS) | |
| 511 | − uport->status |= UPSTAT_CTS_ENABLE; | |
| 512 | − else | |
| 513 | − uport->status &= ~UPSTAT_CTS_ENABLE; | |
| 514 | − | |
| 515 | − if (termios->c_cflag & CLOCAL) | |
| 516 | − uport->status &= ~UPSTAT_DCD_ENABLE; | |
| 517 | − else | |
| 518 | − uport->status |= UPSTAT_DCD_ENABLE; | |
| 519 | − | |
| 520 | − /* reset sw-assisted CTS flow control based on (possibly) new mode */ | |
| 521 | − hw_stopped = uport->hw_stopped; | |
| 522 | − uport->hw_stopped = uart_softcts_mode(uport) && | |
| 523 | − !(uport->ops->get_mctrl(uport) & TIOCM_CTS); | |
| 524 | − if (uport->hw_stopped) { | |
| 525 | − if (!hw_stopped) | |
| 526 | − uport->ops->stop_tx(uport); | |
| 527 | − } else { | |
| 528 | − if (hw_stopped) | |
| 529 | − __uart_start(tty); | |
| 530 | − } | |
| 531 | − spin_unlock_irq(&uport->lock); | |
| 532 | −} | |
| 533 | − | |
| 534 | 531 | static int uart_put_char(struct tty_struct *tty, unsigned char c) |
| 535 | 532 | { |
| 536 | 533 | struct uart_state *state = tty->driver_data; |
| @@ -994,7 +991,7 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port, · 457 unmodified lines | ||
| 994 | 991 | current->comm, |
| 995 | 992 | tty_name(port->tty)); |
| 996 | 993 | } |
| 997 | − uart_change_speed(tty, state, NULL); | |
| 994 | + uart_change_line_settings(tty, state, NULL); | |
| 998 | 995 | } |
| 999 | 996 | } else { |
| 1000 | 997 | retval = uart_startup(tty, state, true); |
| @@ -1491,7 +1488,7 @@ static int uart_set_iso7816_config(struct uart_port *port, · 490 unmodified lines | ||
| 1491 | 1488 | * There are 5 words reserved for future use. Check that userspace |
| 1492 | 1489 | * doesn't put stuff in there to prevent breakages in the future. |
| 1493 | 1490 | */ |
| 1494 | − for (i = 0; i < 5; i++) | |
| 1491 | + for (i = 0; i < ARRAY_SIZE(iso7816.reserved); i++) | |
| 1495 | 1492 | if (iso7816.reserved[i]) |
| 1496 | 1493 | return -EINVAL; |
| 1497 | 1494 | |
| @@ -1552,7 +1549,7 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) · 54 unmodified lines | ||
| 1552 | 1549 | goto out; |
| 1553 | 1550 | |
| 1554 | 1551 | /* rs485_config requires more locking than others */ |
| 1555 | − if (cmd == TIOCGRS485) | |
| 1552 | + if (cmd == TIOCSRS485) | |
| 1556 | 1553 | down_write(&tty->termios_rwsem); |
| 1557 | 1554 | |
| 1558 | 1555 | mutex_lock(&port->mutex); |
| @@ -1595,7 +1592,7 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) · 36 unmodified lines | ||
| 1595 | 1592 | } |
| 1596 | 1593 | out_up: |
| 1597 | 1594 | mutex_unlock(&port->mutex); |
| 1598 | − if (cmd == TIOCGRS485) | |
| 1595 | + if (cmd == TIOCSRS485) | |
| 1599 | 1596 | up_write(&tty->termios_rwsem); |
| 1600 | 1597 | out: |
| 1601 | 1598 | return ret; |
| @@ -1656,15 +1653,15 @@ static void uart_set_termios(struct tty_struct *tty, · 54 unmodified lines | ||
| 1656 | 1653 | goto out; |
| 1657 | 1654 | } |
| 1658 | 1655 | |
| 1659 | − uart_change_speed(tty, state, old_termios); | |
| 1656 | + uart_change_line_settings(tty, state, old_termios); | |
| 1660 | 1657 | /* reload cflag from termios; port driver may have overridden flags */ |
| 1661 | 1658 | cflag = tty->termios.c_cflag; |
| 1662 | 1659 | |
| 1663 | 1660 | /* Handle transition to B0 status */ |
| 1664 | − if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) | |
| 1661 | + if (((old_termios->c_cflag & CBAUD) != B0) && ((cflag & CBAUD) == B0)) | |
| 1665 | 1662 | uart_clear_mctrl(uport, TIOCM_RTS | TIOCM_DTR); |
| 1666 | 1663 | /* Handle transition away from B0 status */ |
| 1667 | − else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { | |
| 1664 | + else if (((old_termios->c_cflag & CBAUD) == B0) && ((cflag & CBAUD) != B0)) { | |
| 1668 | 1665 | unsigned int mask = TIOCM_DTR; |
| 1669 | 1666 | |
| 1670 | 1667 | if (!(cflag & CRTSCTS) || !tty_throttled(tty)) |
| @@ -2452,7 +2449,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) · 781 unmodified lines | ||
| 2452 | 2449 | ret = ops->startup(uport); |
| 2453 | 2450 | if (ret == 0) { |
| 2454 | 2451 | if (tty) |
| 2455 | − uart_change_speed(tty, state, NULL); | |
| 2452 | + uart_change_line_settings(tty, state, NULL); | |
| 2456 | 2453 | spin_lock_irq(&uport->lock); |
| 2457 | 2454 | if (!(uport->rs485.flags & SER_RS485_ENABLED)) |
| 2458 | 2455 | ops->set_mctrl(uport, uport->mctrl); |
| @@ -2593,6 +2590,7 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options) · 134 unmodified lines | ||
| 2593 | 2590 | { |
| 2594 | 2591 | struct uart_driver *drv = driver->driver_state; |
| 2595 | 2592 | struct uart_state *state = drv->state + line; |
| 2593 | + enum uart_pm_state pm_state; | |
| 2596 | 2594 | struct tty_port *tport; |
| 2597 | 2595 | struct uart_port *port; |
| 2598 | 2596 | int baud = 9600; |
| @@ -2610,6 +2608,9 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options) · 11 unmodified lines | ||
| 2610 | 2608 | goto out; |
| 2611 | 2609 | } |
| 2612 | 2610 | |
| 2611 | + pm_state = state->pm_state; | |
| 2612 | + uart_change_pm(state, UART_PM_STATE_ON); | |
| 2613 | + | |
| 2613 | 2614 | if (port->ops->poll_init) { |
| 2614 | 2615 | /* |
| 2615 | 2616 | * We don't set initialized as we only initialized the hw, |
| @@ -2626,6 +2627,8 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options) · 10 unmodified lines | ||
| 2626 | 2627 | console_list_unlock(); |
| 2627 | 2628 | } |
| 2628 | 2629 | out: |
| 2630 | + if (ret) | |
| 2631 | + uart_change_pm(state, pm_state); | |
| 2629 | 2632 | mutex_unlock(&tport->mutex); |
| 2630 | 2633 | return ret; |
| 2631 | 2634 | } |
| @@ -3305,13 +3308,13 @@ void uart_handle_cts_change(struct uart_port *uport, bool active) · 673 unmodified lines | ||
| 3305 | 3308 | if (uart_softcts_mode(uport)) { |
| 3306 | 3309 | if (uport->hw_stopped) { |
| 3307 | 3310 | if (active) { |
| 3308 | − uport->hw_stopped = 0; | |
| 3311 | + uport->hw_stopped = false; | |
| 3309 | 3312 | uport->ops->start_tx(uport); |
| 3310 | 3313 | uart_write_wakeup(uport); |
| 3311 | 3314 | } |
| 3312 | 3315 | } else { |
| 3313 | 3316 | if (!active) { |
| 3314 | − uport->hw_stopped = 1; | |
| 3317 | + uport->hw_stopped = true; | |
| 3315 | 3318 | uport->ops->stop_tx(uport); |
| 3316 | 3319 | } |
| 3317 | 3320 | } |
| @@ -588,14 +588,28 @@ static void sci_start_tx(struct uart_port *port) · 587 unmodified lines | ||
| 588 | 588 | |
| 589 | 589 | if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) && |
| 590 | 590 | dma_submit_error(s->cookie_tx)) { |
| 591 | + if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) | |
| 592 | + /* Switch irq from SCIF to DMA */ | |
| 593 | + disable_irq(s->irqs[SCIx_TXI_IRQ]); | |
| 594 | + | |
| 591 | 595 | s->cookie_tx = 0; |
| 592 | 596 | schedule_work(&s->work_tx); |
| 593 | 597 | } |
| 594 | 598 | #endif |
| 595 | 599 | |
| 596 | − if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) { | |
| 600 | + if (!s->chan_tx || s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE || | |
| 601 | + port->type == PORT_SCIFA || port->type == PORT_SCIFB) { | |
| 597 | 602 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ |
| 598 | 603 | ctrl = serial_port_in(port, SCSCR); |
| 604 | + | |
| 605 | + /* | |
| 606 | + * For SCI, TE (transmit enable) must be set after setting TIE | |
| 607 | + * (transmit interrupt enable) or in the same instruction to start | |
| 608 | + * the transmit process. | |
| 609 | + */ | |
| 610 | + if (port->type == PORT_SCI) | |
| 611 | + ctrl |= SCSCR_TE; | |
| 612 | + | |
| 599 | 613 | serial_port_out(port, SCSCR, ctrl | SCSCR_TIE); |
| 600 | 614 | } |
| 601 | 615 | } |
| @@ -833,6 +847,11 @@ static void sci_transmit_chars(struct uart_port *port) · 231 unmodified lines | ||
| 833 | 847 | } else if (!uart_circ_empty(xmit) && !stopped) { |
| 834 | 848 | c = xmit->buf[xmit->tail]; |
| 835 | 849 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
| 850 | + } else if (port->type == PORT_SCI && uart_circ_empty(xmit)) { | |
| 851 | + ctrl = serial_port_in(port, SCSCR); | |
| 852 | + ctrl &= ~SCSCR_TE; | |
| 853 | + serial_port_out(port, SCSCR, ctrl); | |
| 854 | + return; | |
| 836 | 855 | } else { |
| 837 | 856 | break; |
| 838 | 857 | } |
| @@ -846,9 +865,16 @@ static void sci_transmit_chars(struct uart_port *port) · 7 unmodified lines | ||
| 846 | 865 | |
| 847 | 866 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
| 848 | 867 | uart_write_wakeup(port); |
| 849 | − if (uart_circ_empty(xmit)) | |
| 850 | − sci_stop_tx(port); | |
| 868 | + if (uart_circ_empty(xmit)) { | |
| 869 | + if (port->type == PORT_SCI) { | |
| 870 | + ctrl = serial_port_in(port, SCSCR); | |
| 871 | + ctrl &= ~SCSCR_TIE; | |
| 872 | + ctrl |= SCSCR_TEIE; | |
| 873 | + serial_port_out(port, SCSCR, ctrl); | |
| 874 | + } | |
| 851 | 875 | |
| 876 | + sci_stop_tx(port); | |
| 877 | + } | |
| 852 | 878 | } |
| 853 | 879 | |
| 854 | 880 | static void sci_receive_chars(struct uart_port *port) |
| @@ -1192,9 +1218,15 @@ static void sci_dma_tx_complete(void *arg) · 337 unmodified lines | ||
| 1192 | 1218 | schedule_work(&s->work_tx); |
| 1193 | 1219 | } else { |
| 1194 | 1220 | s->cookie_tx = -EINVAL; |
| 1195 | − if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { | |
| 1221 | + if (port->type == PORT_SCIFA || port->type == PORT_SCIFB || | |
| 1222 | + s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) { | |
| 1196 | 1223 | u16 ctrl = serial_port_in(port, SCSCR); |
| 1197 | 1224 | serial_port_out(port, SCSCR, ctrl & ~SCSCR_TIE); |
| 1225 | + if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) { | |
| 1226 | + /* Switch irq from DMA to SCIF */ | |
| 1227 | + dmaengine_pause(s->chan_tx_saved); | |
| 1228 | + enable_irq(s->irqs[SCIx_TXI_IRQ]); | |
| 1229 | + } | |
| 1198 | 1230 | } |
| 1199 | 1231 | } |
| 1200 | 1232 | |
| @@ -1266,9 +1298,13 @@ static void sci_dma_rx_reenable_irq(struct sci_port *s) · 65 unmodified lines | ||
| 1266 | 1298 | |
| 1267 | 1299 | /* Direct new serial port interrupts back to CPU */ |
| 1268 | 1300 | scr = serial_port_in(port, SCSCR); |
| 1269 | − if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { | |
| 1270 | − scr &= ~SCSCR_RDRQE; | |
| 1301 | + if (port->type == PORT_SCIFA || port->type == PORT_SCIFB || | |
| 1302 | + s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) { | |
| 1271 | 1303 | enable_irq(s->irqs[SCIx_RXI_IRQ]); |
| 1304 | + if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) | |
| 1305 | + scif_set_rtrg(port, s->rx_trigger); | |
| 1306 | + else | |
| 1307 | + scr &= ~SCSCR_RDRQE; | |
| 1272 | 1308 | } |
| 1273 | 1309 | serial_port_out(port, SCSCR, scr | SCSCR_RIE); |
| 1274 | 1310 | } |
| @@ -1505,7 +1541,8 @@ static enum hrtimer_restart sci_dma_rx_timer_fn(struct hrtimer *t) · 230 unmodified lines | ||
| 1505 | 1541 | tty_flip_buffer_push(&port->state->port); |
| 1506 | 1542 | } |
| 1507 | 1543 | |
| 1508 | − if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) | |
| 1544 | + if (port->type == PORT_SCIFA || port->type == PORT_SCIFB || | |
| 1545 | + s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) | |
| 1509 | 1546 | sci_dma_rx_submit(s, true); |
| 1510 | 1547 | |
| 1511 | 1548 | sci_dma_rx_reenable_irq(s); |
| @@ -1531,15 +1568,12 @@ static struct dma_chan *sci_request_dma_chan(struct uart_port *port, · 19 unmodified lines | ||
| 1531 | 1568 | |
| 1532 | 1569 | memset(&cfg, 0, sizeof(cfg)); |
| 1533 | 1570 | cfg.direction = dir; |
| 1534 | − if (dir == DMA_MEM_TO_DEV) { | |
| 1535 | − cfg.dst_addr = port->mapbase + | |
| 1536 | − (sci_getreg(port, SCxTDR)->offset << port->regshift); | |
| 1537 | − cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | |
| 1538 | − } else { | |
| 1539 | − cfg.src_addr = port->mapbase + | |
| 1540 | − (sci_getreg(port, SCxRDR)->offset << port->regshift); | |
| 1541 | − cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | |
| 1542 | − } | |
| 1571 | + cfg.dst_addr = port->mapbase + | |
| 1572 | + (sci_getreg(port, SCxTDR)->offset << port->regshift); | |
| 1573 | + cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | |
| 1574 | + cfg.src_addr = port->mapbase + | |
| 1575 | + (sci_getreg(port, SCxRDR)->offset << port->regshift); | |
| 1576 | + cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | |
| 1543 | 1577 | |
| 1544 | 1578 | ret = dmaengine_slave_config(chan, &cfg); |
| 1545 | 1579 | if (ret) { |
| @@ -1574,7 +1608,7 @@ static void sci_request_dma(struct uart_port *port) · 28 unmodified lines | ||
| 1574 | 1608 | * Don't request a dma channel if no channel was specified |
| 1575 | 1609 | * in the device tree. |
| 1576 | 1610 | */ |
| 1577 | − if (!of_find_property(port->dev->of_node, "dmas", NULL)) | |
| 1611 | + if (!of_property_present(port->dev->of_node, "dmas")) | |
| 1578 | 1612 | return; |
| 1579 | 1613 | |
| 1580 | 1614 | chan = sci_request_dma_chan(port, DMA_MEM_TO_DEV); |
| @@ -1632,7 +1666,8 @@ static void sci_request_dma(struct uart_port *port) · 51 unmodified lines | ||
| 1632 | 1666 | |
| 1633 | 1667 | s->chan_rx_saved = s->chan_rx = chan; |
| 1634 | 1668 | |
| 1635 | − if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) | |
| 1669 | + if (port->type == PORT_SCIFA || port->type == PORT_SCIFB || | |
| 1670 | + s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) | |
| 1636 | 1671 | sci_dma_rx_submit(s, false); |
| 1637 | 1672 | } |
| 1638 | 1673 | } |
| @@ -1685,9 +1720,15 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) · 46 unmodified lines | ||
| 1685 | 1720 | u16 ssr = serial_port_in(port, SCxSR); |
| 1686 | 1721 | |
| 1687 | 1722 | /* Disable future Rx interrupts */ |
| 1688 | − if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { | |
| 1689 | − disable_irq_nosync(irq); | |
| 1690 | − scr |= SCSCR_RDRQE; | |
| 1723 | + if (port->type == PORT_SCIFA || port->type == PORT_SCIFB || | |
| 1724 | + s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) { | |
| 1725 | + disable_irq_nosync(s->irqs[SCIx_RXI_IRQ]); | |
| 1726 | + if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) { | |
| 1727 | + scif_set_rtrg(port, 1); | |
| 1728 | + scr |= SCSCR_RIE; | |
| 1729 | + } else { | |
| 1730 | + scr |= SCSCR_RDRQE; | |
| 1731 | + } | |
| 1691 | 1732 | } else { |
| 1692 | 1733 | if (sci_dma_rx_submit(s, false) < 0) |
| 1693 | 1734 | goto handle_pio; |
| @@ -1737,6 +1778,24 @@ static irqreturn_t sci_tx_interrupt(int irq, void *ptr) · 43 unmodified lines | ||
| 1737 | 1778 | return IRQ_HANDLED; |
| 1738 | 1779 | } |
| 1739 | 1780 | |
| 1781 | +static irqreturn_t sci_tx_end_interrupt(int irq, void *ptr) | |
| 1782 | +{ | |
| 1783 | + struct uart_port *port = ptr; | |
| 1784 | + unsigned long flags; | |
| 1785 | + unsigned short ctrl; | |
| 1786 | + | |
| 1787 | + if (port->type != PORT_SCI) | |
| 1788 | + return sci_tx_interrupt(irq, ptr); | |
| 1789 | + | |
| 1790 | + spin_lock_irqsave(&port->lock, flags); | |
| 1791 | + ctrl = serial_port_in(port, SCSCR); | |
| 1792 | + ctrl &= ~(SCSCR_TE | SCSCR_TEIE); | |
| 1793 | + serial_port_out(port, SCSCR, ctrl); | |
| 1794 | + spin_unlock_irqrestore(&port->lock, flags); | |
| 1795 | + | |
| 1796 | + return IRQ_HANDLED; | |
| 1797 | +} | |
| 1798 | + | |
| 1740 | 1799 | static irqreturn_t sci_br_interrupt(int irq, void *ptr) |
| 1741 | 1800 | { |
| 1742 | 1801 | struct uart_port *port = ptr; |
| @@ -1873,7 +1932,7 @@ static const struct sci_irq_desc { · 130 unmodified lines | ||
| 1873 | 1932 | |
| 1874 | 1933 | [SCIx_TEI_IRQ] = { |
| 1875 | 1934 | .desc = "tx end", |
| 1876 | − .handler = sci_tx_interrupt, | |
| 1935 | + .handler = sci_tx_end_interrupt, | |
| 1877 | 1936 | }, |
| 1878 | 1937 | |
| 1879 | 1938 | /* |
| @@ -2580,8 +2639,14 @@ done: · 700 unmodified lines | ||
| 2580 | 2639 | sci_set_mctrl(port, port->mctrl); |
| 2581 | 2640 | } |
| 2582 | 2641 | |
| 2583 | − scr_val |= SCSCR_RE | SCSCR_TE | | |
| 2584 | − (s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)); | |
| 2642 | + /* | |
| 2643 | + * For SCI, TE (transmit enable) must be set after setting TIE | |
| 2644 | + * (transmit interrupt enable) or in the same instruction to | |
| 2645 | + * start the transmitting process. So skip setting TE here for SCI. | |
| 2646 | + */ | |
| 2647 | + if (port->type != PORT_SCI) | |
| 2648 | + scr_val |= SCSCR_TE; | |
| 2649 | + scr_val |= SCSCR_RE | (s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)); | |
| 2585 | 2650 | serial_port_out(port, SCSCR, scr_val | s->hscif_tot); |
| 2586 | 2651 | if ((srr + 1 == 5) && |
| 2587 | 2652 | (port->type == PORT_SCIFA || port->type == PORT_SCIFB)) { |
| @@ -3149,7 +3214,7 @@ static int sci_remove(struct platform_device *dev) · 561 unmodified lines | ||
| 3149 | 3214 | #define SCI_OF_TYPE(data) ((unsigned long)(data) >> 16) |
| 3150 | 3215 | #define SCI_OF_REGTYPE(data) ((unsigned long)(data) & 0xffff) |
| 3151 | 3216 | |
| 3152 | −static const struct of_device_id of_sci_match[] = { | |
| 3217 | +static const struct of_device_id of_sci_match[] __maybe_unused = { | |
| 3153 | 3218 | /* SoC-specific types */ |
| 3154 | 3219 | { |
| 3155 | 3220 | .compatible = "renesas,scif-r7s72100", |
| @@ -59,6 +59,9 @@ enum { · 58 unmodified lines | ||
| 59 | 59 | #define SCSMR_SRC_19 0x0600 /* Sampling rate 1/19 */ |
| 60 | 60 | #define SCSMR_SRC_27 0x0700 /* Sampling rate 1/27 */ |
| 61 | 61 | |
| 62 | +/* Serial Control Register, SCI only bits */ | |
| 63 | +#define SCSCR_TEIE BIT(2) /* Transmit End Interrupt Enable */ | |
| 64 | + | |
| 62 | 65 | /* Serial Control Register, SCIFA/SCIFB only bits */ |
| 63 | 66 | #define SCSCR_TDRQE BIT(15) /* Tx Data Transfer Request Enable */ |
| 64 | 67 | #define SCSCR_RDRQE BIT(14) /* Rx Data Transfer Request Enable */ |
| @@ -1250,7 +1250,7 @@ static struct platform_driver sprd_platform_driver = { · 1249 unmodified lines | ||
| 1250 | 1250 | .remove = sprd_remove, |
| 1251 | 1251 | .driver = { |
| 1252 | 1252 | .name = "sprd_serial", |
| 1253 | − .of_match_table = of_match_ptr(serial_ids), | |
| 1253 | + .of_match_table = serial_ids, | |
| 1254 | 1254 | .pm = &sprd_pm_ops, |
| 1255 | 1255 | }, |
| 1256 | 1256 | }; |
| @@ -693,8 +693,9 @@ static void stm32_usart_transmit_chars(struct uart_port *port) · 692 unmodified lines | ||
| 693 | 693 | int ret; |
| 694 | 694 | |
| 695 | 695 | if (!stm32_port->hw_flow_control && |
| 696 | − port->rs485.flags & SER_RS485_ENABLED) { | |
| 697 | − stm32_port->txdone = false; | |
| 696 | + port->rs485.flags & SER_RS485_ENABLED && | |
| 697 | + (port->x_char || | |
| 698 | + !(uart_circ_empty(xmit) || uart_tx_stopped(port)))) { | |
| 698 | 699 | stm32_usart_tc_interrupt_disable(port); |
| 699 | 700 | stm32_usart_rs485_rts_enable(port); |
| 700 | 701 | } |
| @@ -743,7 +744,6 @@ static void stm32_usart_transmit_chars(struct uart_port *port) · 42 unmodified lines | ||
| 743 | 744 | stm32_usart_tx_interrupt_disable(port); |
| 744 | 745 | if (!stm32_port->hw_flow_control && |
| 745 | 746 | port->rs485.flags & SER_RS485_ENABLED) { |
| 746 | − stm32_port->txdone = true; | |
| 747 | 747 | stm32_usart_tc_interrupt_enable(port); |
| 748 | 748 | } |
| 749 | 749 | } |
| @@ -203,7 +203,6 @@ struct stm32_port { · 202 unmodified lines | ||
| 203 | 203 | bool hw_flow_control; |
| 204 | 204 | bool swap; /* swap RX & TX pins */ |
| 205 | 205 | bool fifoen; |
| 206 | − bool txdone; | |
| 207 | 206 | int rxftcfg; /* RX FIFO threshold CFG */ |
| 208 | 207 | int txftcfg; /* TX FIFO threshold CFG */ |
| 209 | 208 | bool wakeup_src; |
| @@ -1403,7 +1403,7 @@ static int zs_probe(struct platform_device *op) · 1402 unmodified lines | ||
| 1403 | 1403 | int keyboard_mouse = 0; |
| 1404 | 1404 | int err; |
| 1405 | 1405 | |
| 1406 | − if (of_find_property(op->dev.of_node, "keyboard", NULL)) | |
| 1406 | + if (of_property_present(op->dev.of_node, "keyboard")) | |
| 1407 | 1407 | keyboard_mouse = 1; |
| 1408 | 1408 | |
| 1409 | 1409 | /* uarts must come before keyboards/mice */ |
| @@ -1553,7 +1553,7 @@ static int __init sunzilog_init(void) · 143 unmodified lines | ||
| 1553 | 1553 | |
| 1554 | 1554 | for_each_node_by_name(dp, "zs") { |
| 1555 | 1555 | num_sunzilog++; |
| 1556 | − if (of_find_property(dp, "keyboard", NULL)) | |
| 1556 | + if (of_property_present(dp, "keyboard")) | |
| 1557 | 1557 | num_keybms++; |
| 1558 | 1558 | } |
| 1559 | 1559 | |
| @@ -366,15 +366,14 @@ static int qe_uart_tx_pump(struct uart_qe_port *qe_port) · 365 unmodified lines | ||
| 366 | 366 | /* Pick next descriptor and fill from buffer */ |
| 367 | 367 | bdp = qe_port->tx_cur; |
| 368 | 368 | |
| 369 | − while (!(ioread16be(&bdp->status) & BD_SC_READY) && | |
| 370 | − (xmit->tail != xmit->head)) { | |
| 369 | + while (!(ioread16be(&bdp->status) & BD_SC_READY) && !uart_circ_empty(xmit)) { | |
| 371 | 370 | count = 0; |
| 372 | 371 | p = qe2cpu_addr(be32_to_cpu(bdp->buf), qe_port); |
| 373 | 372 | while (count < qe_port->tx_fifosize) { |
| 374 | 373 | *p++ = xmit->buf[xmit->tail]; |
| 375 | 374 | uart_xmit_advance(port, 1); |
| 376 | 375 | count++; |
| 377 | − if (xmit->head == xmit->tail) | |
| 376 | + if (uart_circ_empty(xmit)) | |
| 378 | 377 | break; |
| 379 | 378 | } |
| 380 | 379 | |
| @@ -1179,7 +1178,7 @@ static int soft_uart_init(struct platform_device *ofdev) · 798 unmodified lines | ||
| 1179 | 1178 | struct qe_firmware_info *qe_fw_info; |
| 1180 | 1179 | int ret; |
| 1181 | 1180 | |
| 1182 | − if (of_find_property(np, "soft-uart", NULL)) { | |
| 1181 | + if (of_property_read_bool(np, "soft-uart")) { | |
| 1183 | 1182 | dev_dbg(&ofdev->dev, "using Soft-UART mode\n"); |
| 1184 | 1183 | soft_uart = 1; |
| 1185 | 1184 | } else { |
| @@ -287,7 +287,6 @@ struct slgt_info { · 286 unmodified lines | ||
| 287 | 287 | unsigned char *tx_buf; |
| 288 | 288 | int tx_count; |
| 289 | 289 | |
| 290 | − char *flag_buf; | |
| 291 | 290 | bool drop_rts_on_tx_done; |
| 292 | 291 | struct _input_signal_events input_signal_events; |
| 293 | 292 | |
| @@ -730,7 +729,7 @@ static void set_termios(struct tty_struct *tty, · 436 unmodified lines | ||
| 730 | 729 | |
| 731 | 730 | /* Handle turning off CRTSCTS */ |
| 732 | 731 | if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { |
| 733 | − tty->hw_stopped = 0; | |
| 732 | + tty->hw_stopped = false; | |
| 734 | 733 | tx_release(tty); |
| 735 | 734 | } |
| 736 | 735 | } |
| @@ -1953,13 +1952,13 @@ static void cts_change(struct slgt_info *info, unsigned short status) · 1216 unmodified lines | ||
| 1953 | 1952 | if (info->port.tty) { |
| 1954 | 1953 | if (info->port.tty->hw_stopped) { |
| 1955 | 1954 | if (info->signals & SerialSignal_CTS) { |
| 1956 | − info->port.tty->hw_stopped = 0; | |
| 1955 | + info->port.tty->hw_stopped = false; | |
| 1957 | 1956 | info->pending_bh |= BH_TRANSMIT; |
| 1958 | 1957 | return; |
| 1959 | 1958 | } |
| 1960 | 1959 | } else { |
| 1961 | 1960 | if (!(info->signals & SerialSignal_CTS)) |
| 1962 | − info->port.tty->hw_stopped = 1; | |
| 1961 | + info->port.tty->hw_stopped = true; | |
| 1963 | 1962 | } |
| 1964 | 1963 | } |
| 1965 | 1964 | } |
| @@ -3244,13 +3243,7 @@ static int alloc_tmp_rbuf(struct slgt_info *info) · 1278 unmodified lines | ||
| 3244 | 3243 | info->tmp_rbuf = kmalloc(info->max_frame_size + 5, GFP_KERNEL); |
| 3245 | 3244 | if (info->tmp_rbuf == NULL) |
| 3246 | 3245 | return -ENOMEM; |
| 3247 | − /* unused flag buffer to satisfy receive_buf calling interface */ | |
| 3248 | − info->flag_buf = kzalloc(info->max_frame_size + 5, GFP_KERNEL); | |
| 3249 | − if (!info->flag_buf) { | |
| 3250 | − kfree(info->tmp_rbuf); | |
| 3251 | − info->tmp_rbuf = NULL; | |
| 3252 | − return -ENOMEM; | |
| 3253 | − } | |
| 3246 | + | |
| 3254 | 3247 | return 0; |
| 3255 | 3248 | } |
| 3256 | 3249 | |
| @@ -3258,8 +3251,6 @@ static void free_tmp_rbuf(struct slgt_info *info) · 1 unmodified line | ||
| 3258 | 3251 | { |
| 3259 | 3252 | kfree(info->tmp_rbuf); |
| 3260 | 3253 | info->tmp_rbuf = NULL; |
| 3261 | − kfree(info->flag_buf); | |
| 3262 | − info->flag_buf = NULL; | |
| 3263 | 3254 | } |
| 3264 | 3255 | |
| 3265 | 3256 | /* |
| @@ -4657,7 +4648,8 @@ check_again: · 1391 unmodified lines | ||
| 4657 | 4648 | hdlcdev_rx(info,info->tmp_rbuf, framesize); |
| 4658 | 4649 | else |
| 4659 | 4650 | #endif |
| 4660 | − ldisc_receive_buf(tty, info->tmp_rbuf, info->flag_buf, framesize); | |
| 4651 | + ldisc_receive_buf(tty, info->tmp_rbuf, NULL, | |
| 4652 | + framesize); | |
| 4661 | 4653 | } |
| 4662 | 4654 | } |
| 4663 | 4655 | free_rbufs(info, start, end); |
| @@ -4691,8 +4683,8 @@ static bool rx_get_buf(struct slgt_info *info) · 27 unmodified lines | ||
| 4691 | 4683 | DBGDATA(info, info->rbufs[i].buf, count, "rx"); |
| 4692 | 4684 | DBGINFO(("rx_get_buf size=%d\n", count)); |
| 4693 | 4685 | if (count) |
| 4694 | − ldisc_receive_buf(info->port.tty, info->rbufs[i].buf, | |
| 4695 | − info->flag_buf, count); | |
| 4686 | + ldisc_receive_buf(info->port.tty, info->rbufs[i].buf, NULL, | |
| 4687 | + count); | |
| 4696 | 4688 | free_rbufs(info, i, i); |
| 4697 | 4689 | return true; |
| 4698 | 4690 | } |
| @@ -62,6 +62,8 @@ int __tty_check_change(struct tty_struct *tty, int sig); · 61 unmodified lines | ||
| 62 | 62 | int tty_check_change(struct tty_struct *tty); |
| 63 | 63 | void __stop_tty(struct tty_struct *tty); |
| 64 | 64 | void __start_tty(struct tty_struct *tty); |
| 65 | +void tty_write_unlock(struct tty_struct *tty); | |
| 66 | +int tty_write_lock(struct tty_struct *tty, int ndelay); | |
| 65 | 67 | void tty_vhangup_session(struct tty_struct *tty); |
| 66 | 68 | void tty_open_proc_set_tty(struct file *filp, struct tty_struct *tty); |
| 67 | 69 | int tty_signal_session_leader(struct tty_struct *tty, int exit_session); |
| @@ -933,13 +933,13 @@ static ssize_t tty_read(struct kiocb *iocb, struct iov_iter *to) · 932 unmodified lines | ||
| 933 | 933 | return i; |
| 934 | 934 | } |
| 935 | 935 | |
| 936 | −static void tty_write_unlock(struct tty_struct *tty) | |
| 936 | +void tty_write_unlock(struct tty_struct *tty) | |
| 937 | 937 | { |
| 938 | 938 | mutex_unlock(&tty->atomic_write_lock); |
| 939 | 939 | wake_up_interruptible_poll(&tty->write_wait, EPOLLOUT); |
| 940 | 940 | } |
| 941 | 941 | |
| 942 | −static int tty_write_lock(struct tty_struct *tty, int ndelay) | |
| 942 | +int tty_write_lock(struct tty_struct *tty, int ndelay) | |
| 943 | 943 | { |
| 944 | 944 | if (!mutex_trylock(&tty->atomic_write_lock)) { |
| 945 | 945 | if (ndelay) |
| @@ -3614,31 +3614,13 @@ static struct ctl_table tty_table[] = { · 2668 unmodified lines | ||
| 3614 | 3614 | { } |
| 3615 | 3615 | }; |
| 3616 | 3616 | |
| 3617 | −static struct ctl_table tty_dir_table[] = { | |
| 3618 | − { | |
| 3619 | − .procname = "tty", | |
| 3620 | − .mode = 0555, | |
| 3621 | − .child = tty_table, | |
| 3622 | − }, | |
| 3623 | − { } | |
| 3624 | −}; | |
| 3625 | − | |
| 3626 | −static struct ctl_table tty_root_table[] = { | |
| 3627 | − { | |
| 3628 | − .procname = "dev", | |
| 3629 | − .mode = 0555, | |
| 3630 | − .child = tty_dir_table, | |
| 3631 | − }, | |
| 3632 | − { } | |
| 3633 | −}; | |
| 3634 | − | |
| 3635 | 3617 | /* |
| 3636 | 3618 | * Ok, now we can initialize the rest of the tty devices and can count |
| 3637 | 3619 | * on memory allocations, interrupts etc.. |
| 3638 | 3620 | */ |
| 3639 | 3621 | int __init tty_init(void) |
| 3640 | 3622 | { |
| 3641 | − register_sysctl_table(tty_root_table); | |
| 3623 | + register_sysctl_init("dev/tty", tty_table); | |
| 3642 | 3624 | cdev_init(&tty_cdev, &tty_fops); |
| 3643 | 3625 | if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || |
| 3644 | 3626 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | * discipline handling modules (like SLIP). |
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | +#include <linux/bits.h> | |
| 10 | 11 | #include <linux/types.h> |
| 11 | 12 | #include <linux/termios.h> |
| 12 | 13 | #include <linux/errno.h> |
| @@ -40,10 +41,10 @@ · 27 unmodified lines | ||
| 40 | 41 | /* |
| 41 | 42 | * Internal flag options for termios setting behavior |
| 42 | 43 | */ |
| 43 | −#define TERMIOS_FLUSH 1 | |
| 44 | −#define TERMIOS_WAIT 2 | |
| 45 | −#define TERMIOS_TERMIO 4 | |
| 46 | −#define TERMIOS_OLD 8 | |
| 44 | +#define TERMIOS_FLUSH BIT(0) | |
| 45 | +#define TERMIOS_WAIT BIT(1) | |
| 46 | +#define TERMIOS_TERMIO BIT(2) | |
| 47 | +#define TERMIOS_OLD BIT(3) | |
| 47 | 48 | |
| 48 | 49 | |
| 49 | 50 | /** |
| @@ -500,21 +501,42 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt) · 450 unmodified lines | ||
| 500 | 501 | tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios); |
| 501 | 502 | tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios); |
| 502 | 503 | |
| 503 | − ld = tty_ldisc_ref(tty); | |
| 504 | + if (opt & (TERMIOS_FLUSH|TERMIOS_WAIT)) { | |
| 505 | +retry_write_wait: | |
| 506 | + retval = wait_event_interruptible(tty->write_wait, !tty_chars_in_buffer(tty)); | |
| 507 | + if (retval < 0) | |
| 508 | + return retval; | |
| 504 | 509 | |
| 505 | − if (ld != NULL) { | |
| 506 | − if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer) | |
| 507 | − ld->ops->flush_buffer(tty); | |
| 508 | − tty_ldisc_deref(ld); | |
| 509 | − } | |
| 510 | + if (tty_write_lock(tty, 0) < 0) | |
| 511 | + goto retry_write_wait; | |
| 510 | 512 | |
| 511 | − if (opt & TERMIOS_WAIT) { | |
| 512 | − tty_wait_until_sent(tty, 0); | |
| 513 | − if (signal_pending(current)) | |
| 514 | − return -ERESTARTSYS; | |
| 515 | − } | |
| 513 | + /* Racing writer? */ | |
| 514 | + if (tty_chars_in_buffer(tty)) { | |
| 515 | + tty_write_unlock(tty); | |
| 516 | + goto retry_write_wait; | |
| 517 | + } | |
| 516 | 518 | |
| 517 | − tty_set_termios(tty, &tmp_termios); | |
| 519 | + ld = tty_ldisc_ref(tty); | |
| 520 | + if (ld != NULL) { | |
| 521 | + if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer) | |
| 522 | + ld->ops->flush_buffer(tty); | |
| 523 | + tty_ldisc_deref(ld); | |
| 524 | + } | |
| 525 | + | |
| 526 | + if ((opt & TERMIOS_WAIT) && tty->ops->wait_until_sent) { | |
| 527 | + tty->ops->wait_until_sent(tty, 0); | |
| 528 | + if (signal_pending(current)) { | |
| 529 | + tty_write_unlock(tty); | |
| 530 | + return -ERESTARTSYS; | |
| 531 | + } | |
| 532 | + } | |
| 533 | + | |
| 534 | + tty_set_termios(tty, &tmp_termios); | |
| 535 | + | |
| 536 | + tty_write_unlock(tty); | |
| 537 | + } else { | |
| 538 | + tty_set_termios(tty, &tmp_termios); | |
| 539 | + } | |
| 518 | 540 | |
| 519 | 541 | /* FIXME: Arguably if tmp_termios == tty->termios AND the |
| 520 | 542 | actual requested termios was not tmp_termios then we may |
| @@ -58,7 +58,6 @@ static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; · 57 unmodified lines | ||
| 58 | 58 | int tty_register_ldisc(struct tty_ldisc_ops *new_ldisc) |
| 59 | 59 | { |
| 60 | 60 | unsigned long flags; |
| 61 | − int ret = 0; | |
| 62 | 61 | |
| 63 | 62 | if (new_ldisc->num < N_TTY || new_ldisc->num >= NR_LDISCS) |
| 64 | 63 | return -EINVAL; |
| @@ -67,7 +66,7 @@ int tty_register_ldisc(struct tty_ldisc_ops *new_ldisc) · 2 unmodified lines | ||
| 67 | 66 | tty_ldiscs[new_ldisc->num] = new_ldisc; |
| 68 | 67 | raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); |
| 69 | 68 | |
| 70 | − return ret; | |
| 69 | + return 0; | |
| 71 | 70 | } |
| 72 | 71 | EXPORT_SYMBOL(tty_register_ldisc); |
| 73 | 72 | |
| @@ -135,10 +135,9 @@ const struct consw *conswitchp; · 134 unmodified lines | ||
| 135 | 135 | #define DEFAULT_CURSOR_BLINK_MS 200 |
| 136 | 136 | |
| 137 | 137 | struct vc vc_cons [MAX_NR_CONSOLES]; |
| 138 | +EXPORT_SYMBOL(vc_cons); | |
| 138 | 139 | |
| 139 | −#ifndef VT_SINGLE_DRIVER | |
| 140 | 140 | static const struct consw *con_driver_map[MAX_NR_CONSOLES]; |
| 141 | −#endif | |
| 142 | 141 | |
| 143 | 142 | static int con_open(struct tty_struct *, struct file *); |
| 144 | 143 | static void vc_init(struct vc_data *vc, unsigned int rows, |
| @@ -162,6 +161,7 @@ int default_utf8 = true; · 17 unmodified lines | ||
| 162 | 161 | module_param(default_utf8, int, S_IRUGO | S_IWUSR); |
| 163 | 162 | int global_cursor_default = -1; |
| 164 | 163 | module_param(global_cursor_default, int, S_IRUGO | S_IWUSR); |
| 164 | +EXPORT_SYMBOL(global_cursor_default); | |
| 165 | 165 | |
| 166 | 166 | static int cur_default = CUR_UNDERLINE; |
| 167 | 167 | module_param(cur_default, int, S_IRUGO | S_IWUSR); |
| @@ -174,6 +174,7 @@ static int ignore_poke; · 6 unmodified lines | ||
| 174 | 174 | |
| 175 | 175 | int do_poke_blanked_console; |
| 176 | 176 | int console_blanked; |
| 177 | +EXPORT_SYMBOL(console_blanked); | |
| 177 | 178 | |
| 178 | 179 | static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */ |
| 179 | 180 | static int vesa_off_interval; |
| @@ -190,8 +191,10 @@ static DECLARE_WORK(con_driver_unregister_work, con_driver_unregister_callback); · 10 unmodified lines | ||
| 190 | 191 | * saved_* variants are for save/restore around kernel debugger enter/leave |
| 191 | 192 | */ |
| 192 | 193 | int fg_console; |
| 194 | +EXPORT_SYMBOL(fg_console); | |
| 193 | 195 | int last_console; |
| 194 | 196 | int want_console = -1; |
| 197 | + | |
| 195 | 198 | static int saved_fg_console; |
| 196 | 199 | static int saved_last_console; |
| 197 | 200 | static int saved_want_console; |
| @@ -223,6 +226,7 @@ static int scrollback_delta; · 25 unmodified lines | ||
| 223 | 226 | * the console on our behalf. |
| 224 | 227 | */ |
| 225 | 228 | int (*console_blank_hook)(int); |
| 229 | +EXPORT_SYMBOL(console_blank_hook); | |
| 226 | 230 | |
| 227 | 231 | static DEFINE_TIMER(console_timer, blank_screen_t); |
| 228 | 232 | static int blank_state; |
| @@ -639,6 +643,7 @@ void update_region(struct vc_data *vc, unsigned long start, int count) · 410 unmodified lines | ||
| 639 | 643 | set_cursor(vc); |
| 640 | 644 | } |
| 641 | 645 | } |
| 646 | +EXPORT_SYMBOL(update_region); | |
| 642 | 647 | |
| 643 | 648 | /* Structure of attributes is hardware-dependent */ |
| 644 | 649 | |
| @@ -984,6 +989,7 @@ void redraw_screen(struct vc_data *vc, int is_switch) · 339 unmodified lines | ||
| 984 | 989 | notify_update(vc); |
| 985 | 990 | } |
| 986 | 991 | } |
| 992 | +EXPORT_SYMBOL(redraw_screen); | |
| 987 | 993 | |
| 988 | 994 | /* |
| 989 | 995 | * Allocation, freeing and resizing of VTs. |
| @@ -1000,10 +1006,10 @@ static void visual_init(struct vc_data *vc, int num, int init) · 10 unmodified lines | ||
| 1000 | 1006 | if (vc->vc_sw) |
| 1001 | 1007 | module_put(vc->vc_sw->owner); |
| 1002 | 1008 | vc->vc_sw = conswitchp; |
| 1003 | −#ifndef VT_SINGLE_DRIVER | |
| 1009 | + | |
| 1004 | 1010 | if (con_driver_map[num]) |
| 1005 | 1011 | vc->vc_sw = con_driver_map[num]; |
| 1006 | −#endif | |
| 1012 | + | |
| 1007 | 1013 | __module_get(vc->vc_sw->owner); |
| 1008 | 1014 | vc->vc_num = num; |
| 1009 | 1015 | vc->vc_display_fg = &master_display_fg; |
| @@ -1305,6 +1311,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) · 295 unmodified lines | ||
| 1305 | 1311 | { |
| 1306 | 1312 | return vc_do_resize(vc->port.tty, vc, cols, rows); |
| 1307 | 1313 | } |
| 1314 | +EXPORT_SYMBOL(vc_resize); | |
| 1308 | 1315 | |
| 1309 | 1316 | /** |
| 1310 | 1317 | * vt_resize - resize a VT |
| @@ -1368,6 +1375,7 @@ enum { EPecma = 0, EPdec, EPeq, EPgt, EPlt}; · 57 unmodified lines | ||
| 1368 | 1375 | |
| 1369 | 1376 | const unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7, |
| 1370 | 1377 | 8,12,10,14, 9,13,11,15 }; |
| 1378 | +EXPORT_SYMBOL(color_table); | |
| 1371 | 1379 | |
| 1372 | 1380 | /* the default colour table, for VGA+ colour systems */ |
| 1373 | 1381 | unsigned char default_red[] = { |
| @@ -1375,18 +1383,21 @@ unsigned char default_red[] = { · 1 unmodified line | ||
| 1375 | 1383 | 0x55, 0xff, 0x55, 0xff, 0x55, 0xff, 0x55, 0xff |
| 1376 | 1384 | }; |
| 1377 | 1385 | module_param_array(default_red, byte, NULL, S_IRUGO | S_IWUSR); |
| 1386 | +EXPORT_SYMBOL(default_red); | |
| 1378 | 1387 | |
| 1379 | 1388 | unsigned char default_grn[] = { |
| 1380 | 1389 | 0x00, 0x00, 0xaa, 0x55, 0x00, 0x00, 0xaa, 0xaa, |
| 1381 | 1390 | 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff |
| 1382 | 1391 | }; |
| 1383 | 1392 | module_param_array(default_grn, byte, NULL, S_IRUGO | S_IWUSR); |
| 1393 | +EXPORT_SYMBOL(default_grn); | |
| 1384 | 1394 | |
| 1385 | 1395 | unsigned char default_blu[] = { |
| 1386 | 1396 | 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, |
| 1387 | 1397 | 0x55, 0x55, 0x55, 0x55, 0xff, 0xff, 0xff, 0xff |
| 1388 | 1398 | }; |
| 1389 | 1399 | module_param_array(default_blu, byte, NULL, S_IRUGO | S_IWUSR); |
| 1400 | +EXPORT_SYMBOL(default_blu); | |
| 1390 | 1401 | |
| 1391 | 1402 | /* |
| 1392 | 1403 | * gotoxy() must verify all boundaries, because the arguments |
| @@ -3143,93 +3154,84 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) · 1750 unmodified lines | ||
| 3143 | 3154 | return -EFAULT; |
| 3144 | 3155 | ret = 0; |
| 3145 | 3156 | |
| 3146 | − switch (type) | |
| 3147 | − { | |
| 3148 | − case TIOCL_SETSEL: | |
| 3149 | − ret = set_selection_user((struct tiocl_selection | |
| 3150 | − __user *)(p+1), tty); | |
| 3151 | − break; | |
| 3152 | − case TIOCL_PASTESEL: | |
| 3153 | − ret = paste_selection(tty); | |
| 3154 | − break; | |
| 3155 | − case TIOCL_UNBLANKSCREEN: | |
| 3156 | − console_lock(); | |
| 3157 | − unblank_screen(); | |
| 3158 | − console_unlock(); | |
| 3159 | − break; | |
| 3160 | − case TIOCL_SELLOADLUT: | |
| 3161 | − console_lock(); | |
| 3162 | − ret = sel_loadlut(p); | |
| 3163 | − console_unlock(); | |
| 3164 | − break; | |
| 3165 | − case TIOCL_GETSHIFTSTATE: | |
| 3157 | + switch (type) { | |
| 3158 | + case TIOCL_SETSEL: | |
| 3159 | + return set_selection_user((struct tiocl_selection | |
| 3160 | + __user *)(p+1), tty); | |
| 3161 | + case TIOCL_PASTESEL: | |
| 3162 | + return paste_selection(tty); | |
| 3163 | + case TIOCL_UNBLANKSCREEN: | |
| 3164 | + console_lock(); | |
| 3165 | + unblank_screen(); | |
| 3166 | + console_unlock(); | |
| 3167 | + break; | |
| 3168 | + case TIOCL_SELLOADLUT: | |
| 3169 | + console_lock(); | |
| 3170 | + ret = sel_loadlut(p); | |
| 3171 | + console_unlock(); | |
| 3172 | + break; | |
| 3173 | + case TIOCL_GETSHIFTSTATE: | |
| 3174 | + /* | |
| 3175 | + * Make it possible to react to Shift+Mousebutton. Note that | |
| 3176 | + * 'shift_state' is an undocumented kernel-internal variable; | |
| 3177 | + * programs not closely related to the kernel should not use | |
| 3178 | + * this. | |
| 3179 | + */ | |
| 3180 | + data = vt_get_shift_state(); | |
| 3181 | + return put_user(data, p); | |
| 3182 | + case TIOCL_GETMOUSEREPORTING: | |
| 3183 | + console_lock(); /* May be overkill */ | |
| 3184 | + data = mouse_reporting(); | |
| 3185 | + console_unlock(); | |
| 3186 | + return put_user(data, p); | |
| 3187 | + case TIOCL_SETVESABLANK: | |
| 3188 | + console_lock(); | |
| 3189 | + ret = set_vesa_blanking(p); | |
| 3190 | + console_unlock(); | |
| 3191 | + break; | |
| 3192 | + case TIOCL_GETKMSGREDIRECT: | |
| 3193 | + data = vt_get_kmsg_redirect(); | |
| 3194 | + return put_user(data, p); | |
| 3195 | + case TIOCL_SETKMSGREDIRECT: | |
| 3196 | + if (!capable(CAP_SYS_ADMIN)) | |
| 3197 | + return -EPERM; | |
| 3166 | 3198 | |
| 3167 | − /* | |
| 3168 | − * Make it possible to react to Shift+Mousebutton. | |
| 3169 | − * Note that 'shift_state' is an undocumented | |
| 3170 | − * kernel-internal variable; programs not closely | |
| 3171 | − * related to the kernel should not use this. | |
| 3172 | − */ | |
| 3173 | − data = vt_get_shift_state(); | |
| 3174 | − ret = put_user(data, p); | |
| 3175 | − break; | |
| 3176 | − case TIOCL_GETMOUSEREPORTING: | |
| 3177 | − console_lock(); /* May be overkill */ | |
| 3178 | − data = mouse_reporting(); | |
| 3179 | − console_unlock(); | |
| 3180 | − ret = put_user(data, p); | |
| 3181 | − break; | |
| 3182 | − case TIOCL_SETVESABLANK: | |
| 3183 | − console_lock(); | |
| 3184 | − ret = set_vesa_blanking(p); | |
| 3185 | − console_unlock(); | |
| 3186 | − break; | |
| 3187 | − case TIOCL_GETKMSGREDIRECT: | |
| 3188 | − data = vt_get_kmsg_redirect(); | |
| 3189 | − ret = put_user(data, p); | |
| 3190 | − break; | |
| 3191 | − case TIOCL_SETKMSGREDIRECT: | |
| 3192 | − if (!capable(CAP_SYS_ADMIN)) { | |
| 3193 | − ret = -EPERM; | |
| 3194 | − } else { | |
| 3195 | − if (get_user(data, p+1)) | |
| 3196 | − ret = -EFAULT; | |
| 3197 | − else | |
| 3198 | − vt_kmsg_redirect(data); | |
| 3199 | − } | |
| 3200 | − break; | |
| 3201 | − case TIOCL_GETFGCONSOLE: | |
| 3202 | − /* No locking needed as this is a transiently | |
| 3203 | − correct return anyway if the caller hasn't | |
| 3204 | − disabled switching */ | |
| 3205 | − ret = fg_console; | |
| 3206 | − break; | |
| 3207 | − case TIOCL_SCROLLCONSOLE: | |
| 3208 | − if (get_user(lines, (s32 __user *)(p+4))) { | |
| 3209 | − ret = -EFAULT; | |
| 3210 | − } else { | |
| 3211 | − /* Need the console lock here. Note that lots | |
| 3212 | − of other calls need fixing before the lock | |
| 3213 | − is actually useful ! */ | |
| 3214 | − console_lock(); | |
| 3215 | − scrollfront(vc_cons[fg_console].d, lines); | |
| 3216 | − console_unlock(); | |
| 3217 | − ret = 0; | |
| 3218 | − } | |
| 3219 | − break; | |
| 3220 | − case TIOCL_BLANKSCREEN: /* until explicitly unblanked, not only poked */ | |
| 3221 | − console_lock(); | |
| 3222 | − ignore_poke = 1; | |
| 3223 | − do_blank_screen(0); | |
| 3224 | − console_unlock(); | |
| 3225 | − break; | |
| 3226 | − case TIOCL_BLANKEDSCREEN: | |
| 3227 | − ret = console_blanked; | |
| 3228 | − break; | |
| 3229 | − default: | |
| 3230 | − ret = -EINVAL; | |
| 3231 | − break; | |
| 3199 | + if (get_user(data, p+1)) | |
| 3200 | + return -EFAULT; | |
| 3201 | + | |
| 3202 | + vt_kmsg_redirect(data); | |
| 3203 | + | |
| 3204 | + break; | |
| 3205 | + case TIOCL_GETFGCONSOLE: | |
| 3206 | + /* | |
| 3207 | + * No locking needed as this is a transiently correct return | |
| 3208 | + * anyway if the caller hasn't disabled switching. | |
| 3209 | + */ | |
| 3210 | + return fg_console; | |
| 3211 | + case TIOCL_SCROLLCONSOLE: | |
| 3212 | + if (get_user(lines, (s32 __user *)(p+4))) | |
| 3213 | + return -EFAULT; | |
| 3214 | + | |
| 3215 | + /* | |
| 3216 | + * Needs the console lock here. Note that lots of other calls | |
| 3217 | + * need fixing before the lock is actually useful! | |
| 3218 | + */ | |
| 3219 | + console_lock(); | |
| 3220 | + scrollfront(vc_cons[fg_console].d, lines); | |
| 3221 | + console_unlock(); | |
| 3222 | + break; | |
| 3223 | + case TIOCL_BLANKSCREEN: /* until explicitly unblanked, not only poked */ | |
| 3224 | + console_lock(); | |
| 3225 | + ignore_poke = 1; | |
| 3226 | + do_blank_screen(0); | |
| 3227 | + console_unlock(); | |
| 3228 | + break; | |
| 3229 | + case TIOCL_BLANKEDSCREEN: | |
| 3230 | + return console_blanked; | |
| 3231 | + default: | |
| 3232 | + return -EINVAL; | |
| 3232 | 3233 | } |
| 3234 | + | |
| 3233 | 3235 | return ret; |
| 3234 | 3236 | } |
| 3235 | 3237 | |
| @@ -3571,8 +3573,6 @@ int __init vty_init(const struct file_operations *console_fops) · 335 unmodified lines | ||
| 3571 | 3573 | return 0; |
| 3572 | 3574 | } |
| 3573 | 3575 | |
| 3574 | −#ifndef VT_SINGLE_DRIVER | |
| 3575 | − | |
| 3576 | 3576 | static struct class *vtconsole_class; |
| 3577 | 3577 | |
| 3578 | 3578 | static int do_bind_con_driver(const struct consw *csw, int first, int last, |
| @@ -4236,6 +4236,7 @@ void give_up_console(const struct consw *csw) · 657 unmodified lines | ||
| 4236 | 4236 | do_unregister_con_driver(csw); |
| 4237 | 4237 | console_unlock(); |
| 4238 | 4238 | } |
| 4239 | +EXPORT_SYMBOL(give_up_console); | |
| 4239 | 4240 | |
| 4240 | 4241 | static int __init vtconsole_class_init(void) |
| 4241 | 4242 | { |
| @@ -4273,8 +4274,6 @@ static int __init vtconsole_class_init(void) · 31 unmodified lines | ||
| 4273 | 4274 | } |
| 4274 | 4275 | postcore_initcall(vtconsole_class_init); |
| 4275 | 4276 | |
| 4276 | −#endif | |
| 4277 | − | |
| 4278 | 4277 | /* |
| 4279 | 4278 | * Screen blanking |
| 4280 | 4279 | */ |
| @@ -4792,23 +4791,3 @@ void vc_scrolldelta_helper(struct vc_data *c, int lines, · 511 unmodified lines | ||
| 4792 | 4791 | c->vc_visible_origin = ubase + (from + from_off) % wrap; |
| 4793 | 4792 | } |
| 4794 | 4793 | EXPORT_SYMBOL_GPL(vc_scrolldelta_helper); |
| 4795 | − | |
| 4796 | −/* | |
| 4797 | − * Visible symbols for modules | |
| 4798 | − */ | |
| 4799 | − | |
| 4800 | −EXPORT_SYMBOL(color_table); | |
| 4801 | −EXPORT_SYMBOL(default_red); | |
| 4802 | −EXPORT_SYMBOL(default_grn); | |
| 4803 | −EXPORT_SYMBOL(default_blu); | |
| 4804 | −EXPORT_SYMBOL(update_region); | |
| 4805 | −EXPORT_SYMBOL(redraw_screen); | |
| 4806 | −EXPORT_SYMBOL(vc_resize); | |
| 4807 | −EXPORT_SYMBOL(fg_console); | |
| 4808 | −EXPORT_SYMBOL(console_blank_hook); | |
| 4809 | −EXPORT_SYMBOL(console_blanked); | |
| 4810 | −EXPORT_SYMBOL(vc_cons); | |
| 4811 | −EXPORT_SYMBOL(global_cursor_default); | |
| 4812 | −#ifndef VT_SINGLE_DRIVER | |
| 4813 | −EXPORT_SYMBOL(give_up_console); | |
| 4814 | −#endif | |
| @@ -18,16 +18,16 @@ struct plat_serial8250_port { · 17 unmodified lines | ||
| 18 | 18 | unsigned long iobase; /* io base address */ |
| 19 | 19 | void __iomem *membase; /* ioremap cookie or NULL */ |
| 20 | 20 | resource_size_t mapbase; /* resource base */ |
| 21 | + unsigned int uartclk; /* UART clock rate */ | |
| 21 | 22 | unsigned int irq; /* interrupt number */ |
| 22 | 23 | unsigned long irqflags; /* request_irq flags */ |
| 23 | − unsigned int uartclk; /* UART clock rate */ | |
| 24 | 24 | void *private_data; |
| 25 | 25 | unsigned char regshift; /* register shift */ |
| 26 | 26 | unsigned char iotype; /* UPIO_* */ |
| 27 | 27 | unsigned char hub6; |
| 28 | 28 | unsigned char has_sysrq; /* supports magic SysRq */ |
| 29 | − upf_t flags; /* UPF_* flags */ | |
| 30 | 29 | unsigned int type; /* If UPF_FIXED_TYPE */ |
| 30 | + upf_t flags; /* UPF_* flags */ | |
| 31 | 31 | unsigned int (*serial_in)(struct uart_port *, int); |
| 32 | 32 | void (*serial_out)(struct uart_port *, int, int); |
| 33 | 33 | void (*set_termios)(struct uart_port *, |
| @@ -151,26 +151,22 @@ void serial8250_unregister_port(int line); · 117 unmodified lines | ||
| 151 | 151 | void serial8250_suspend_port(int line); |
| 152 | 152 | void serial8250_resume_port(int line); |
| 153 | 153 | |
| 154 | −extern int early_serial_setup(struct uart_port *port); | |
| 155 | − | |
| 156 | −extern int early_serial8250_setup(struct earlycon_device *device, | |
| 157 | − const char *options); | |
| 158 | −extern void serial8250_update_uartclk(struct uart_port *port, | |
| 159 | − unsigned int uartclk); | |
| 160 | −extern void serial8250_do_set_termios(struct uart_port *port, | |
| 161 | − struct ktermios *termios, const struct ktermios *old); | |
| 162 | −extern void serial8250_do_set_ldisc(struct uart_port *port, | |
| 163 | − struct ktermios *termios); | |
| 164 | −extern unsigned int serial8250_do_get_mctrl(struct uart_port *port); | |
| 165 | −extern int serial8250_do_startup(struct uart_port *port); | |
| 166 | −extern void serial8250_do_shutdown(struct uart_port *port); | |
| 167 | −extern void serial8250_do_pm(struct uart_port *port, unsigned int state, | |
| 168 | − unsigned int oldstate); | |
| 169 | −extern void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl); | |
| 170 | −extern void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, | |
| 171 | − unsigned int quot, | |
| 172 | − unsigned int quot_frac); | |
| 173 | −extern int fsl8250_handle_irq(struct uart_port *port); | |
| 154 | +int early_serial_setup(struct uart_port *port); | |
| 155 | +int early_serial8250_setup(struct earlycon_device *device, const char *options); | |
| 156 | + | |
| 157 | +void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk); | |
| 158 | +void serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, | |
| 159 | + const struct ktermios *old); | |
| 160 | +void serial8250_do_set_ldisc(struct uart_port *port, struct ktermios *termios); | |
| 161 | +unsigned int serial8250_do_get_mctrl(struct uart_port *port); | |
| 162 | +int serial8250_do_startup(struct uart_port *port); | |
| 163 | +void serial8250_do_shutdown(struct uart_port *port); | |
| 164 | +void serial8250_do_pm(struct uart_port *port, unsigned int state, | |
| 165 | + unsigned int oldstate); | |
| 166 | +void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl); | |
| 167 | +void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, | |
| 168 | + unsigned int quot, unsigned int quot_frac); | |
| 169 | +int fsl8250_handle_irq(struct uart_port *port); | |
| 174 | 170 | int serial8250_handle_irq(struct uart_port *port, unsigned int iir); |
| 175 | 171 | u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr); |
| 176 | 172 | void serial8250_read_char(struct uart_8250_port *up, u16 lsr); |
| @@ -183,9 +179,8 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, · 6 unmodified lines | ||
| 183 | 179 | int serial8250_console_setup(struct uart_port *port, char *options, bool probe); |
| 184 | 180 | int serial8250_console_exit(struct uart_port *port); |
| 185 | 181 | |
| 186 | −extern void serial8250_set_isa_configurator(void (*v) | |
| 187 | − (int port, struct uart_port *up, | |
| 188 | − u32 *capabilities)); | |
| 182 | +void serial8250_set_isa_configurator(void (*v)(int port, struct uart_port *up, | |
| 183 | + u32 *capabilities)); | |
| 189 | 184 | |
| 190 | 185 | #ifdef CONFIG_SERIAL_8250_RT288X |
| 191 | 186 | unsigned int au_serial_in(struct uart_port *p, int offset); |
| @@ -553,7 +553,7 @@ struct uart_port { · 552 unmodified lines | ||
| 553 | 553 | #define UPSTAT_AUTOXOFF ((__force upstat_t) (1 << 4)) |
| 554 | 554 | #define UPSTAT_SYNC_FIFO ((__force upstat_t) (1 << 5)) |
| 555 | 555 | |
| 556 | − int hw_stopped; /* sw-assisted CTS flow state */ | |
| 556 | + bool hw_stopped; /* sw-assisted CTS flow state */ | |
| 557 | 557 | unsigned int mctrl; /* current modem ctrl settings */ |
| 558 | 558 | unsigned int frame_time; /* frame timing in ns */ |
| 559 | 559 | unsigned int type; /* port type */ |
| @@ -812,9 +812,8 @@ extern const struct earlycon_id __earlycon_table_end[]; · 252 unmodified lines | ||
| 812 | 812 | |
| 813 | 813 | #define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn) |
| 814 | 814 | |
| 815 | −extern int of_setup_earlycon(const struct earlycon_id *match, | |
| 816 | − unsigned long node, | |
| 817 | − const char *options); | |
| 815 | +int of_setup_earlycon(const struct earlycon_id *match, unsigned long node, | |
| 816 | + const char *options); | |
| 818 | 817 | |
| 819 | 818 | #ifdef CONFIG_SERIAL_EARLYCON |
| 820 | 819 | extern bool earlycon_acpi_spcr_enable __initdata; |
| @@ -897,11 +896,11 @@ static inline bool uart_softcts_mode(struct uart_port *uport) · 76 unmodified lines | ||
| 897 | 896 | * The following are helper functions for the low level drivers. |
| 898 | 897 | */ |
| 899 | 898 | |
| 900 | −extern void uart_handle_dcd_change(struct uart_port *uport, bool active); | |
| 901 | −extern void uart_handle_cts_change(struct uart_port *uport, bool active); | |
| 899 | +void uart_handle_dcd_change(struct uart_port *uport, bool active); | |
| 900 | +void uart_handle_cts_change(struct uart_port *uport, bool active); | |
| 902 | 901 | |
| 903 | −extern void uart_insert_char(struct uart_port *port, unsigned int status, | |
| 904 | − unsigned int overrun, unsigned int ch, unsigned int flag); | |
| 902 | +void uart_insert_char(struct uart_port *port, unsigned int status, | |
| 903 | + unsigned int overrun, unsigned int ch, unsigned int flag); | |
| 905 | 904 | |
| 906 | 905 | void uart_xchar_out(struct uart_port *uport, int offset); |
| 907 | 906 | |
| @@ -227,7 +227,7 @@ struct tty_struct { · 226 unmodified lines | ||
| 227 | 227 | unsigned long unused[0]; |
| 228 | 228 | } __aligned(sizeof(unsigned long)) ctrl; |
| 229 | 229 | |
| 230 | − int hw_stopped; | |
| 230 | + bool hw_stopped; | |
| 231 | 231 | unsigned int receive_room; |
| 232 | 232 | int flow_change; |
| 233 | 233 | |
| @@ -43,10 +43,25 @@ struct gsm_config_ext { · 42 unmodified lines | ||
| 43 | 43 | __u32 keep_alive; /* Control channel keep-alive in 1/100th of a |
| 44 | 44 | * second (0 to disable) |
| 45 | 45 | */ |
| 46 | − __u32 reserved[7]; /* For future use, must be initialized to zero */ | |
| 46 | + __u32 wait_config; /* Wait for DLCI config before opening virtual link? */ | |
| 47 | + __u32 reserved[6]; /* For future use, must be initialized to zero */ | |
| 47 | 48 | }; |
| 48 | 49 | |
| 49 | 50 | #define GSMIOC_GETCONF_EXT _IOR('G', 5, struct gsm_config_ext) |
| 50 | 51 | #define GSMIOC_SETCONF_EXT _IOW('G', 6, struct gsm_config_ext) |
| 51 | 52 | |
| 53 | +/* Set channel accordingly before calling GSMIOC_GETCONF_DLCI. */ | |
| 54 | +struct gsm_dlci_config { | |
| 55 | + __u32 channel; /* DLCI (0 for the associated DLCI) */ | |
| 56 | + __u32 adaption; /* Convergence layer type */ | |
| 57 | + __u32 mtu; /* Maximum transfer unit */ | |
| 58 | + __u32 priority; /* Priority (0 for default value) */ | |
| 59 | + __u32 i; /* Frame type (1 = UIH, 2 = UI) */ | |
| 60 | + __u32 k; /* Window size (0 for default value) */ | |
| 61 | + __u32 reserved[8]; /* For future use, must be initialized to zero */ | |
| 62 | +}; | |
| 63 | + | |
| 64 | +#define GSMIOC_GETCONF_DLCI _IOWR('G', 7, struct gsm_dlci_config) | |
| 65 | +#define GSMIOC_SETCONF_DLCI _IOW('G', 8, struct gsm_dlci_config) | |
| 66 | + | |
| 52 | 67 | #endif |