mirror of
https://github.com/torvalds/linux.git
synced 2024-12-26 21:02:19 +00:00
TTY/Serial changes for 6.4-rc1
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. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZEqB7w8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ylQuwCgwU9bGoihDtFsoFYUra/FKPPoC88Anj6t1a1f X5HZmADnwrFNNq/jP4vH =FeNF -----END PGP SIGNATURE----- Merge tag 'tty-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty 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() ...
This commit is contained in:
commit
b39667abcd
@ -33,8 +33,11 @@ The format of this option is::
|
||||
9600n8. The maximum baudrate is 115200.
|
||||
|
||||
You can specify multiple console= options on the kernel command line.
|
||||
Output will appear on all of them. The last device will be used when
|
||||
you open ``/dev/console``. So, for example::
|
||||
|
||||
The behavior is well defined when each device type is mentioned only once.
|
||||
In this case, the output will appear on all requested consoles. And
|
||||
the last device will be used when you open ``/dev/console``.
|
||||
So, for example::
|
||||
|
||||
console=ttyS1,9600 console=tty0
|
||||
|
||||
@ -42,7 +45,34 @@ defines that opening ``/dev/console`` will get you the current foreground
|
||||
virtual console, and kernel messages will appear on both the VGA
|
||||
console and the 2nd serial port (ttyS1 or COM2) at 9600 baud.
|
||||
|
||||
Note that you can only define one console per device type (serial, video).
|
||||
The behavior is more complicated when the same device type is defined more
|
||||
times. In this case, there are the following two rules:
|
||||
|
||||
1. The output will appear only on the first device of each defined type.
|
||||
|
||||
2. ``/dev/console`` will be associated with the first registered device.
|
||||
Where the registration order depends on how kernel initializes various
|
||||
subsystems.
|
||||
|
||||
This rule is used also when the last console= parameter is not used
|
||||
for other reasons. For example, because of a typo or because
|
||||
the hardware is not available.
|
||||
|
||||
The result might be surprising. For example, the following two command
|
||||
lines have the same result:
|
||||
|
||||
console=ttyS1,9600 console=tty0 console=tty1
|
||||
console=tty0 console=ttyS1,9600 console=tty1
|
||||
|
||||
The kernel messages are printed only on ``tty0`` and ``ttyS1``. And
|
||||
``/dev/console`` gets associated with ``tty0``. It is because kernel
|
||||
tries to register graphical consoles before serial ones. It does it
|
||||
because of the default behavior when no console device is specified,
|
||||
see below.
|
||||
|
||||
Note that the last ``console=tty1`` parameter still makes a difference.
|
||||
The kernel command line is used also by systemd. It would use the last
|
||||
defined ``tty1`` as the login console.
|
||||
|
||||
If no console device is specified, the first device found capable of
|
||||
acting as a system console will be used. At this time, the system
|
||||
|
@ -2,8 +2,8 @@
|
||||
# Copyright 2019 BayLibre, SAS
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/serial/amlogic,meson-uart.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
$id: http://devicetree.org/schemas/serial/amlogic,meson-uart.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Amlogic Meson SoC UART Serial Interface
|
||||
|
||||
@ -34,6 +34,11 @@ properties:
|
||||
- amlogic,meson-gx-uart
|
||||
- amlogic,meson-s4-uart
|
||||
- const: amlogic,meson-ao-uart
|
||||
- description: Always-on power domain UART controller on G12A SoCs
|
||||
items:
|
||||
- const: amlogic,meson-g12a-uart
|
||||
- const: amlogic,meson-gx-uart
|
||||
- const: amlogic,meson-ao-uart
|
||||
- description: Everything-Else power domain UART controller
|
||||
enum:
|
||||
- amlogic,meson6-uart
|
||||
@ -41,6 +46,10 @@ properties:
|
||||
- amlogic,meson8b-uart
|
||||
- amlogic,meson-gx-uart
|
||||
- amlogic,meson-s4-uart
|
||||
- description: Everything-Else power domain UART controller on G12A SoCs
|
||||
items:
|
||||
- const: amlogic,meson-g12a-uart
|
||||
- const: amlogic,meson-gx-uart
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -49,6 +49,24 @@ properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 2
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: ipg
|
||||
- const: per
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: DMA controller phandle and request line for RX
|
||||
- description: DMA controller phandle and request line for TX
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx
|
||||
- const: tx
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
@ -86,12 +104,16 @@ properties:
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/imx5-clock.h>
|
||||
|
||||
aliases {
|
||||
serial0 = &uart1;
|
||||
};
|
||||
@ -100,6 +122,11 @@ examples:
|
||||
compatible = "fsl,imx51-uart", "fsl,imx21-uart";
|
||||
reg = <0x73fbc000 0x4000>;
|
||||
interrupts = <31>;
|
||||
clocks = <&clks IMX5_CLK_UART1_IPG_GATE>,
|
||||
<&clks IMX5_CLK_UART1_PER_GATE>;
|
||||
clock-names = "ipg", "per";
|
||||
dmas = <&sdma 18 4 1>, <&sdma 19 4 2>;
|
||||
dma-names = "rx", "tx";
|
||||
uart-has-rtscts;
|
||||
fsl,dte-mode;
|
||||
};
|
||||
|
@ -65,6 +65,9 @@ properties:
|
||||
- const: rx
|
||||
- const: tx
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -1,8 +1,8 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/serial/qcom,serial-geni-qcom.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
$id: http://devicetree.org/schemas/serial/qcom,serial-geni-qcom.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Geni based QUP UART interface
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/serial/renesas,em-uart.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
$id: http://devicetree.org/schemas/serial/renesas,em-uart.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas EMMA Mobile UART Interface
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/serial/renesas,hscif.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
$id: http://devicetree.org/schemas/serial/renesas,hscif.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas High Speed Serial Communication Interface with FIFO (HSCIF)
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/serial/renesas,sci.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
$id: http://devicetree.org/schemas/serial/renesas,sci.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas Serial Communication Interface
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/serial/renesas,scif.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
$id: http://devicetree.org/schemas/serial/renesas,scif.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas Serial Communication Interface with FIFO (SCIF)
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/serial/renesas,scifa.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
$id: http://devicetree.org/schemas/serial/renesas,scifa.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas Serial Communications Interface with FIFO A (SCIFA)
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/serial/renesas,scifb.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
$id: http://devicetree.org/schemas/serial/renesas,scifb.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas Serial Communications Interface with FIFO B (SCIFB)
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/serial/serial.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
$id: http://devicetree.org/schemas/serial/serial.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Serial Interface Generic
|
||||
|
||||
|
@ -68,12 +68,12 @@ properties:
|
||||
- const: apb_pclk
|
||||
|
||||
dmas:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx
|
||||
- const: tx
|
||||
- const: rx
|
||||
|
||||
snps,uart-16550-compatible:
|
||||
description: reflects the value of UART_16550_COMPATIBLE configuration
|
||||
|
@ -2,8 +2,8 @@
|
||||
# Copyright 2019 Unisoc Inc.
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/serial/sprd-uart.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
$id: http://devicetree.org/schemas/serial/sprd-uart.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Spreadtrum serial UART
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
# Copyright (C) Sunplus Co., Ltd. 2021
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/serial/sunplus,sp7021-uart.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
$id: http://devicetree.org/schemas/serial/sunplus,sp7021-uart.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sunplus SoC SP7021 UART Controller
|
||||
|
||||
|
@ -29,6 +29,8 @@ Config Initiator
|
||||
|
||||
#. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl.
|
||||
|
||||
#. Configure DLCs using ``GSMIOC_GETCONF_DLCI``/``GSMIOC_SETCONF_DLCI`` ioctl for non-defaults.
|
||||
|
||||
#. Obtain base gsmtty number for the used serial port.
|
||||
|
||||
Major parts of the initialization program
|
||||
@ -45,6 +47,7 @@ Config Initiator
|
||||
int ldisc = N_GSM0710;
|
||||
struct gsm_config c;
|
||||
struct gsm_config_ext ce;
|
||||
struct gsm_dlci_config dc;
|
||||
struct termios configuration;
|
||||
uint32_t first;
|
||||
|
||||
@ -81,6 +84,13 @@ Config Initiator
|
||||
c.mtu = 127;
|
||||
/* set the new configuration */
|
||||
ioctl(fd, GSMIOC_SETCONF, &c);
|
||||
/* get DLC 1 configuration */
|
||||
dc.channel = 1;
|
||||
ioctl(fd, GSMIOC_GETCONF_DLCI, &dc);
|
||||
/* the first user channel gets a higher priority */
|
||||
dc.priority = 1;
|
||||
/* set the new DLC 1 specific configuration */
|
||||
ioctl(fd, GSMIOC_SETCONF_DLCI, &dc);
|
||||
/* get first gsmtty device node */
|
||||
ioctl(fd, GSMIOC_GETFIRST, &first);
|
||||
printf("first muxed line: /dev/gsmtty%i\n", first);
|
||||
@ -120,6 +130,8 @@ Config Requester
|
||||
|
||||
#. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl.
|
||||
|
||||
#. Configure DLCs using ``GSMIOC_GETCONF_DLCI``/``GSMIOC_SETCONF_DLCI`` ioctl for non-defaults.
|
||||
|
||||
#. Obtain base gsmtty number for the used serial port::
|
||||
|
||||
#include <stdio.h>
|
||||
@ -132,6 +144,7 @@ Config Requester
|
||||
int ldisc = N_GSM0710;
|
||||
struct gsm_config c;
|
||||
struct gsm_config_ext ce;
|
||||
struct gsm_dlci_config dc;
|
||||
struct termios configuration;
|
||||
uint32_t first;
|
||||
|
||||
@ -161,6 +174,13 @@ Config Requester
|
||||
c.mtu = 127;
|
||||
/* set the new configuration */
|
||||
ioctl(fd, GSMIOC_SETCONF, &c);
|
||||
/* get DLC 1 configuration */
|
||||
dc.channel = 1;
|
||||
ioctl(fd, GSMIOC_GETCONF_DLCI, &dc);
|
||||
/* the first user channel gets a higher priority */
|
||||
dc.priority = 1;
|
||||
/* set the new DLC 1 specific configuration */
|
||||
ioctl(fd, GSMIOC_SETCONF_DLCI, &dc);
|
||||
/* get first gsmtty device node */
|
||||
ioctl(fd, GSMIOC_GETFIRST, &first);
|
||||
printf("first muxed line: /dev/gsmtty%i\n", first);
|
||||
|
@ -2045,7 +2045,8 @@
|
||||
};
|
||||
|
||||
uart_AO: serial@3000 {
|
||||
compatible = "amlogic,meson-gx-uart",
|
||||
compatible = "amlogic,meson-g12a-uart",
|
||||
"amlogic,meson-gx-uart",
|
||||
"amlogic,meson-ao-uart";
|
||||
reg = <0x0 0x3000 0x0 0x18>;
|
||||
interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>;
|
||||
@ -2055,7 +2056,8 @@
|
||||
};
|
||||
|
||||
uart_AO_B: serial@4000 {
|
||||
compatible = "amlogic,meson-gx-uart",
|
||||
compatible = "amlogic,meson-g12a-uart",
|
||||
"amlogic,meson-gx-uart",
|
||||
"amlogic,meson-ao-uart";
|
||||
reg = <0x0 0x4000 0x0 0x18>;
|
||||
interrupts = <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>;
|
||||
@ -2292,7 +2294,8 @@
|
||||
};
|
||||
|
||||
uart_C: serial@22000 {
|
||||
compatible = "amlogic,meson-gx-uart";
|
||||
compatible = "amlogic,meson-g12a-uart",
|
||||
"amlogic,meson-gx-uart";
|
||||
reg = <0x0 0x22000 0x0 0x18>;
|
||||
interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
|
||||
clocks = <&xtal>, <&clkc CLKID_UART2>, <&xtal>;
|
||||
@ -2301,7 +2304,8 @@
|
||||
};
|
||||
|
||||
uart_B: serial@23000 {
|
||||
compatible = "amlogic,meson-gx-uart";
|
||||
compatible = "amlogic,meson-g12a-uart",
|
||||
"amlogic,meson-gx-uart";
|
||||
reg = <0x0 0x23000 0x0 0x18>;
|
||||
interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
|
||||
clocks = <&xtal>, <&clkc CLKID_UART1>, <&xtal>;
|
||||
@ -2310,7 +2314,8 @@
|
||||
};
|
||||
|
||||
uart_A: serial@24000 {
|
||||
compatible = "amlogic,meson-gx-uart";
|
||||
compatible = "amlogic,meson-g12a-uart",
|
||||
"amlogic,meson-gx-uart";
|
||||
reg = <0x0 0x24000 0x0 0x18>;
|
||||
interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
|
||||
clocks = <&xtal>, <&clkc CLKID_UART0>, <&xtal>;
|
||||
|
@ -1060,7 +1060,7 @@ static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty)
|
||||
if (info->serial_signals & SerialSignal_CTS) {
|
||||
if (debug_level >= DEBUG_LEVEL_ISR)
|
||||
printk("CTS tx start...");
|
||||
tty->hw_stopped = 0;
|
||||
tty->hw_stopped = false;
|
||||
tx_start(info, tty);
|
||||
info->pending_bh |= BH_TRANSMIT;
|
||||
return;
|
||||
@ -1069,7 +1069,7 @@ static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty)
|
||||
if (!(info->serial_signals & SerialSignal_CTS)) {
|
||||
if (debug_level >= DEBUG_LEVEL_ISR)
|
||||
printk("CTS tx stop...");
|
||||
tty->hw_stopped = 1;
|
||||
tty->hw_stopped = true;
|
||||
tx_stop(info);
|
||||
}
|
||||
}
|
||||
@ -2312,7 +2312,7 @@ static void mgslpc_set_termios(struct tty_struct *tty,
|
||||
|
||||
/* Handle turning off CRTSCTS */
|
||||
if (old_termios->c_cflag & CRTSCTS && !C_CRTSCTS(tty)) {
|
||||
tty->hw_stopped = 0;
|
||||
tty->hw_stopped = false;
|
||||
tx_release(tty);
|
||||
}
|
||||
}
|
||||
|
@ -478,13 +478,13 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
|
||||
int cts = (status & UART_MSR_CTS);
|
||||
if (tty->hw_stopped) {
|
||||
if (cts) {
|
||||
tty->hw_stopped = 0;
|
||||
tty->hw_stopped = false;
|
||||
sdio_uart_start_tx(port);
|
||||
tty_wakeup(tty);
|
||||
}
|
||||
} else {
|
||||
if (!cts) {
|
||||
tty->hw_stopped = 1;
|
||||
tty->hw_stopped = true;
|
||||
sdio_uart_stop_tx(port);
|
||||
}
|
||||
}
|
||||
@ -633,7 +633,7 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty)
|
||||
|
||||
if (C_CRTSCTS(tty))
|
||||
if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS))
|
||||
tty->hw_stopped = 1;
|
||||
tty->hw_stopped = true;
|
||||
|
||||
clear_bit(TTY_IO_ERROR, &tty->flags);
|
||||
|
||||
@ -882,14 +882,14 @@ static void sdio_uart_set_termios(struct tty_struct *tty,
|
||||
|
||||
/* Handle turning off CRTSCTS */
|
||||
if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
|
||||
tty->hw_stopped = 0;
|
||||
tty->hw_stopped = false;
|
||||
sdio_uart_start_tx(port);
|
||||
}
|
||||
|
||||
/* Handle turning on CRTSCTS */
|
||||
if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
|
||||
if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) {
|
||||
tty->hw_stopped = 1;
|
||||
tty->hw_stopped = true;
|
||||
sdio_uart_stop_tx(port);
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ config LEGACY_TIOCSTI
|
||||
a dangerous legacy operation, and can be disabled on most
|
||||
systems.
|
||||
|
||||
Say 'Y here only if you have confirmed that your system's
|
||||
Say Y here only if you have confirmed that your system's
|
||||
userspace depends on this functionality to continue operating
|
||||
normally.
|
||||
|
||||
|
@ -347,7 +347,7 @@ static void check_modem_status(struct serial_state *info)
|
||||
#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
|
||||
printk("CTS tx start...");
|
||||
#endif
|
||||
port->tty->hw_stopped = 0;
|
||||
port->tty->hw_stopped = false;
|
||||
info->IER |= UART_IER_THRI;
|
||||
amiga_custom.intena = IF_SETCLR | IF_TBE;
|
||||
mb();
|
||||
@ -362,7 +362,7 @@ static void check_modem_status(struct serial_state *info)
|
||||
#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
|
||||
printk("CTS tx stop...");
|
||||
#endif
|
||||
port->tty->hw_stopped = 1;
|
||||
port->tty->hw_stopped = true;
|
||||
info->IER &= ~UART_IER_THRI;
|
||||
/* disable Tx interrupt and remove any pending interrupts */
|
||||
amiga_custom.intena = IF_TBE;
|
||||
@ -1197,7 +1197,7 @@ static void rs_set_termios(struct tty_struct *tty, const struct ktermios *old_te
|
||||
|
||||
/* Handle turning off CRTSCTS */
|
||||
if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) {
|
||||
tty->hw_stopped = 0;
|
||||
tty->hw_stopped = false;
|
||||
rs_start(tty);
|
||||
}
|
||||
|
||||
|
@ -553,7 +553,7 @@ static void mxser_handle_cts(struct tty_struct *tty, struct mxser_port *info,
|
||||
|
||||
if (tty->hw_stopped) {
|
||||
if (cts) {
|
||||
tty->hw_stopped = 0;
|
||||
tty->hw_stopped = false;
|
||||
|
||||
if (!mxser_16550A_or_MUST(info))
|
||||
__mxser_start_tx(info);
|
||||
@ -563,7 +563,7 @@ static void mxser_handle_cts(struct tty_struct *tty, struct mxser_port *info,
|
||||
} else if (cts)
|
||||
return;
|
||||
|
||||
tty->hw_stopped = 1;
|
||||
tty->hw_stopped = true;
|
||||
if (!mxser_16550A_or_MUST(info))
|
||||
__mxser_stop_tx(info);
|
||||
}
|
||||
@ -1361,7 +1361,7 @@ static void mxser_set_termios(struct tty_struct *tty,
|
||||
spin_unlock_irqrestore(&info->slock, flags);
|
||||
|
||||
if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) {
|
||||
tty->hw_stopped = 0;
|
||||
tty->hw_stopped = false;
|
||||
mxser_start(tty);
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/poll.h>
|
||||
@ -128,6 +129,7 @@ struct gsm_msg {
|
||||
|
||||
enum gsm_dlci_state {
|
||||
DLCI_CLOSED,
|
||||
DLCI_WAITING_CONFIG, /* Waiting for DLCI configuration from user */
|
||||
DLCI_CONFIGURE, /* Sending PN (for adaption > 1) */
|
||||
DLCI_OPENING, /* Sending SABM not seen UA */
|
||||
DLCI_OPEN, /* SABM/UA complete */
|
||||
@ -330,6 +332,7 @@ struct gsm_mux {
|
||||
unsigned int t3; /* Power wake-up timer in seconds. */
|
||||
int n2; /* Retry count */
|
||||
u8 k; /* Window size */
|
||||
bool wait_config; /* Wait for configuration by ioctl before DLCI open */
|
||||
u32 keep_alive; /* Control channel keep-alive in 10ms */
|
||||
|
||||
/* Statistics (not currently exposed) */
|
||||
@ -451,6 +454,7 @@ static int gsm_modem_update(struct gsm_dlci *dlci, u8 brk);
|
||||
static struct gsm_msg *gsm_data_alloc(struct gsm_mux *gsm, u8 addr, int len,
|
||||
u8 ctrl);
|
||||
static int gsm_send_packet(struct gsm_mux *gsm, struct gsm_msg *msg);
|
||||
static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr);
|
||||
static void gsmld_write_trigger(struct gsm_mux *gsm);
|
||||
static void gsmld_write_task(struct work_struct *work);
|
||||
|
||||
@ -2280,6 +2284,7 @@ static void gsm_dlci_begin_open(struct gsm_dlci *dlci)
|
||||
|
||||
switch (dlci->state) {
|
||||
case DLCI_CLOSED:
|
||||
case DLCI_WAITING_CONFIG:
|
||||
case DLCI_CLOSING:
|
||||
dlci->retries = gsm->n2;
|
||||
if (!need_pn) {
|
||||
@ -2311,6 +2316,7 @@ static void gsm_dlci_set_opening(struct gsm_dlci *dlci)
|
||||
{
|
||||
switch (dlci->state) {
|
||||
case DLCI_CLOSED:
|
||||
case DLCI_WAITING_CONFIG:
|
||||
case DLCI_CLOSING:
|
||||
dlci->state = DLCI_OPENING;
|
||||
break;
|
||||
@ -2319,6 +2325,24 @@ static void gsm_dlci_set_opening(struct gsm_dlci *dlci)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gsm_dlci_set_wait_config - wait for channel configuration
|
||||
* @dlci: DLCI to configure
|
||||
*
|
||||
* Wait for a DLCI configuration from the application.
|
||||
*/
|
||||
static void gsm_dlci_set_wait_config(struct gsm_dlci *dlci)
|
||||
{
|
||||
switch (dlci->state) {
|
||||
case DLCI_CLOSED:
|
||||
case DLCI_CLOSING:
|
||||
dlci->state = DLCI_WAITING_CONFIG;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gsm_dlci_begin_close - start channel open procedure
|
||||
* @dlci: DLCI to open
|
||||
@ -2453,6 +2477,128 @@ static void gsm_kick_timer(struct timer_list *t)
|
||||
pr_info("%s TX queue stalled\n", __func__);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsm_dlci_copy_config_values - copy DLCI configuration
|
||||
* @dlci: source DLCI
|
||||
* @dc: configuration structure to fill
|
||||
*/
|
||||
static void gsm_dlci_copy_config_values(struct gsm_dlci *dlci, struct gsm_dlci_config *dc)
|
||||
{
|
||||
memset(dc, 0, sizeof(*dc));
|
||||
dc->channel = (u32)dlci->addr;
|
||||
dc->adaption = (u32)dlci->adaption;
|
||||
dc->mtu = (u32)dlci->mtu;
|
||||
dc->priority = (u32)dlci->prio;
|
||||
if (dlci->ftype == UIH)
|
||||
dc->i = 1;
|
||||
else
|
||||
dc->i = 2;
|
||||
dc->k = (u32)dlci->k;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsm_dlci_config - configure DLCI from configuration
|
||||
* @dlci: DLCI to configure
|
||||
* @dc: DLCI configuration
|
||||
* @open: open DLCI after configuration?
|
||||
*/
|
||||
static int gsm_dlci_config(struct gsm_dlci *dlci, struct gsm_dlci_config *dc, int open)
|
||||
{
|
||||
struct gsm_mux *gsm;
|
||||
bool need_restart = false;
|
||||
bool need_open = false;
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* Check that userspace doesn't put stuff in here to prevent breakages
|
||||
* in the future.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(dc->reserved); i++)
|
||||
if (dc->reserved[i])
|
||||
return -EINVAL;
|
||||
|
||||
if (!dlci)
|
||||
return -EINVAL;
|
||||
gsm = dlci->gsm;
|
||||
|
||||
/* Stuff we don't support yet - I frame transport */
|
||||
if (dc->adaption != 1 && dc->adaption != 2)
|
||||
return -EOPNOTSUPP;
|
||||
if (dc->mtu > MAX_MTU || dc->mtu < MIN_MTU || dc->mtu > gsm->mru)
|
||||
return -EINVAL;
|
||||
if (dc->priority >= 64)
|
||||
return -EINVAL;
|
||||
if (dc->i == 0 || dc->i > 2) /* UIH and UI only */
|
||||
return -EINVAL;
|
||||
if (dc->k > 7)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* See what is needed for reconfiguration
|
||||
*/
|
||||
/* Framing fields */
|
||||
if (dc->adaption != dlci->adaption)
|
||||
need_restart = true;
|
||||
if (dc->mtu != dlci->mtu)
|
||||
need_restart = true;
|
||||
if (dc->i != dlci->ftype)
|
||||
need_restart = true;
|
||||
/* Requires care */
|
||||
if (dc->priority != dlci->prio)
|
||||
need_restart = true;
|
||||
|
||||
if ((open && gsm->wait_config) || need_restart)
|
||||
need_open = true;
|
||||
if (dlci->state == DLCI_WAITING_CONFIG) {
|
||||
need_restart = false;
|
||||
need_open = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Close down what is needed, restart and initiate the new
|
||||
* configuration.
|
||||
*/
|
||||
if (need_restart) {
|
||||
gsm_dlci_begin_close(dlci);
|
||||
wait_event_interruptible(gsm->event, dlci->state == DLCI_CLOSED);
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
}
|
||||
/*
|
||||
* Setup the new configuration values
|
||||
*/
|
||||
dlci->adaption = (int)dc->adaption;
|
||||
|
||||
if (dc->mtu)
|
||||
dlci->mtu = (unsigned int)dc->mtu;
|
||||
else
|
||||
dlci->mtu = gsm->mtu;
|
||||
|
||||
if (dc->priority)
|
||||
dlci->prio = (u8)dc->priority;
|
||||
else
|
||||
dlci->prio = roundup(dlci->addr + 1, 8) - 1;
|
||||
|
||||
if (dc->i == 1)
|
||||
dlci->ftype = UIH;
|
||||
else if (dc->i == 2)
|
||||
dlci->ftype = UI;
|
||||
|
||||
if (dc->k)
|
||||
dlci->k = (u8)dc->k;
|
||||
else
|
||||
dlci->k = gsm->k;
|
||||
|
||||
if (need_open) {
|
||||
if (gsm->initiator)
|
||||
gsm_dlci_begin_open(dlci);
|
||||
else
|
||||
gsm_dlci_set_opening(dlci);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate/Free DLCI channels
|
||||
*/
|
||||
@ -3078,6 +3224,7 @@ static struct gsm_mux *gsm_alloc_mux(void)
|
||||
gsm->mru = 64; /* Default to encoding 1 so these should be 64 */
|
||||
gsm->mtu = 64;
|
||||
gsm->dead = true; /* Avoid early tty opens */
|
||||
gsm->wait_config = false; /* Disabled */
|
||||
gsm->keep_alive = 0; /* Disabled */
|
||||
|
||||
/* 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)
|
||||
int need_close = 0;
|
||||
int need_restart = 0;
|
||||
|
||||
/* Stuff we don't support yet - UI or I frame transport, windowing */
|
||||
if ((c->adaption != 1 && c->adaption != 2) || c->k)
|
||||
/* Stuff we don't support yet - UI or I frame transport */
|
||||
if (c->adaption != 1 && c->adaption != 2)
|
||||
return -EOPNOTSUPP;
|
||||
/* Check the MRU/MTU range looks sane */
|
||||
if (c->mru < MIN_MTU || c->mtu < MIN_MTU)
|
||||
@ -3218,6 +3365,7 @@ static void gsm_copy_config_ext_values(struct gsm_mux *gsm,
|
||||
struct gsm_config_ext *ce)
|
||||
{
|
||||
memset(ce, 0, sizeof(*ce));
|
||||
ce->wait_config = gsm->wait_config ? 1 : 0;
|
||||
ce->keep_alive = gsm->keep_alive;
|
||||
}
|
||||
|
||||
@ -3233,7 +3381,12 @@ static int gsm_config_ext(struct gsm_mux *gsm, struct gsm_config_ext *ce)
|
||||
if (ce->reserved[i])
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Setup the new configuration values
|
||||
*/
|
||||
gsm->wait_config = ce->wait_config ? true : false;
|
||||
gsm->keep_alive = ce->keep_alive;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3433,9 +3586,16 @@ static int gsmld_open(struct tty_struct *tty)
|
||||
tty->receive_room = 65536;
|
||||
|
||||
/* Attach the initial passive connection */
|
||||
gsm->encoding = GSM_ADV_OPT;
|
||||
gsmld_attach_gsm(tty, gsm);
|
||||
|
||||
/* The mux will not be activated yet, we wait for correct
|
||||
* configuration first.
|
||||
*/
|
||||
if (gsm->encoding == GSM_BASIC_OPT)
|
||||
gsm->receive = gsm0_receive;
|
||||
else
|
||||
gsm->receive = gsm1_receive;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3556,8 +3716,10 @@ static int gsmld_ioctl(struct tty_struct *tty, unsigned int cmd,
|
||||
{
|
||||
struct gsm_config c;
|
||||
struct gsm_config_ext ce;
|
||||
struct gsm_dlci_config dc;
|
||||
struct gsm_mux *gsm = tty->disc_data;
|
||||
unsigned int base;
|
||||
unsigned int base, addr;
|
||||
struct gsm_dlci *dlci;
|
||||
|
||||
switch (cmd) {
|
||||
case GSMIOC_GETCONF:
|
||||
@ -3581,6 +3743,35 @@ static int gsmld_ioctl(struct tty_struct *tty, unsigned int cmd,
|
||||
if (copy_from_user(&ce, (void __user *)arg, sizeof(ce)))
|
||||
return -EFAULT;
|
||||
return gsm_config_ext(gsm, &ce);
|
||||
case GSMIOC_GETCONF_DLCI:
|
||||
if (copy_from_user(&dc, (void __user *)arg, sizeof(dc)))
|
||||
return -EFAULT;
|
||||
if (dc.channel == 0 || dc.channel >= NUM_DLCI)
|
||||
return -EINVAL;
|
||||
addr = array_index_nospec(dc.channel, NUM_DLCI);
|
||||
dlci = gsm->dlci[addr];
|
||||
if (!dlci) {
|
||||
dlci = gsm_dlci_alloc(gsm, addr);
|
||||
if (!dlci)
|
||||
return -ENOMEM;
|
||||
}
|
||||
gsm_dlci_copy_config_values(dlci, &dc);
|
||||
if (copy_to_user((void __user *)arg, &dc, sizeof(dc)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
case GSMIOC_SETCONF_DLCI:
|
||||
if (copy_from_user(&dc, (void __user *)arg, sizeof(dc)))
|
||||
return -EFAULT;
|
||||
if (dc.channel == 0 || dc.channel >= NUM_DLCI)
|
||||
return -EINVAL;
|
||||
addr = array_index_nospec(dc.channel, NUM_DLCI);
|
||||
dlci = gsm->dlci[addr];
|
||||
if (!dlci) {
|
||||
dlci = gsm_dlci_alloc(gsm, addr);
|
||||
if (!dlci)
|
||||
return -ENOMEM;
|
||||
}
|
||||
return gsm_dlci_config(dlci, &dc, 0);
|
||||
default:
|
||||
return n_tty_ioctl_helper(tty, cmd, arg);
|
||||
}
|
||||
@ -4008,7 +4199,6 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
struct gsm_dlci *dlci = tty->driver_data;
|
||||
struct tty_port *port = &dlci->port;
|
||||
struct gsm_mux *gsm = dlci->gsm;
|
||||
|
||||
port->count++;
|
||||
tty_port_tty_set(port, tty);
|
||||
@ -4018,10 +4208,15 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)
|
||||
a DM straight back. This is ok as that will have caused a hangup */
|
||||
tty_port_set_initialized(port, true);
|
||||
/* Start sending off SABM messages */
|
||||
if (gsm->initiator)
|
||||
gsm_dlci_begin_open(dlci);
|
||||
else
|
||||
gsm_dlci_set_opening(dlci);
|
||||
if (!dlci->gsm->wait_config) {
|
||||
/* Start sending off SABM messages */
|
||||
if (dlci->gsm->initiator)
|
||||
gsm_dlci_begin_open(dlci);
|
||||
else
|
||||
gsm_dlci_set_opening(dlci);
|
||||
} else {
|
||||
gsm_dlci_set_wait_config(dlci);
|
||||
}
|
||||
/* And wait for virtual carrier */
|
||||
return tty_port_block_til_ready(port, tty, filp);
|
||||
}
|
||||
@ -4142,6 +4337,7 @@ static int gsmtty_ioctl(struct tty_struct *tty,
|
||||
{
|
||||
struct gsm_dlci *dlci = tty->driver_data;
|
||||
struct gsm_netconfig nc;
|
||||
struct gsm_dlci_config dc;
|
||||
int index;
|
||||
|
||||
if (dlci->state == DLCI_CLOSED)
|
||||
@ -4165,6 +4361,23 @@ static int gsmtty_ioctl(struct tty_struct *tty,
|
||||
gsm_destroy_network(dlci);
|
||||
mutex_unlock(&dlci->mutex);
|
||||
return 0;
|
||||
case GSMIOC_GETCONF_DLCI:
|
||||
if (copy_from_user(&dc, (void __user *)arg, sizeof(dc)))
|
||||
return -EFAULT;
|
||||
if (dc.channel != dlci->addr)
|
||||
return -EPERM;
|
||||
gsm_dlci_copy_config_values(dlci, &dc);
|
||||
if (copy_to_user((void __user *)arg, &dc, sizeof(dc)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
case GSMIOC_SETCONF_DLCI:
|
||||
if (copy_from_user(&dc, (void __user *)arg, sizeof(dc)))
|
||||
return -EFAULT;
|
||||
if (dc.channel >= NUM_DLCI)
|
||||
return -EINVAL;
|
||||
if (dc.channel != 0 && dc.channel != dlci->addr)
|
||||
return -EPERM;
|
||||
return gsm_dlci_config(dlci, &dc, 1);
|
||||
case TIOCMIWAIT:
|
||||
return gsm_wait_modem_change(dlci, (u32)arg);
|
||||
default:
|
||||
|
@ -28,27 +28,26 @@
|
||||
* EAGAIN
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/audit.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include "tty.h"
|
||||
|
||||
/*
|
||||
@ -625,7 +624,7 @@ static size_t __process_echoes(struct tty_struct *tty)
|
||||
c = echo_buf(ldata, tail);
|
||||
if (c == ECHO_OP_START) {
|
||||
unsigned char op;
|
||||
int no_space_left = 0;
|
||||
bool space_left = true;
|
||||
|
||||
/*
|
||||
* Since add_echo_byte() is called without holding
|
||||
@ -664,7 +663,7 @@ static size_t __process_echoes(struct tty_struct *tty)
|
||||
num_bs = 8 - (num_chars & 7);
|
||||
|
||||
if (num_bs > space) {
|
||||
no_space_left = 1;
|
||||
space_left = false;
|
||||
break;
|
||||
}
|
||||
space -= num_bs;
|
||||
@ -690,7 +689,7 @@ static size_t __process_echoes(struct tty_struct *tty)
|
||||
case ECHO_OP_START:
|
||||
/* This is an escaped echo op start code */
|
||||
if (!space) {
|
||||
no_space_left = 1;
|
||||
space_left = false;
|
||||
break;
|
||||
}
|
||||
tty_put_char(tty, ECHO_OP_START);
|
||||
@ -710,7 +709,7 @@ static size_t __process_echoes(struct tty_struct *tty)
|
||||
*
|
||||
*/
|
||||
if (space < 2) {
|
||||
no_space_left = 1;
|
||||
space_left = false;
|
||||
break;
|
||||
}
|
||||
tty_put_char(tty, '^');
|
||||
@ -720,7 +719,7 @@ static size_t __process_echoes(struct tty_struct *tty)
|
||||
tail += 2;
|
||||
}
|
||||
|
||||
if (no_space_left)
|
||||
if (!space_left)
|
||||
break;
|
||||
} else {
|
||||
if (O_OPOST(tty)) {
|
||||
@ -1177,7 +1176,7 @@ static void n_tty_receive_overrun(struct tty_struct *tty)
|
||||
|
||||
ldata->num_overrun++;
|
||||
if (time_after(jiffies, ldata->overrun_time + HZ) ||
|
||||
time_after(ldata->overrun_time, jiffies)) {
|
||||
time_after(ldata->overrun_time, jiffies)) {
|
||||
tty_warn(tty, "%d input overrun(s)\n", ldata->num_overrun);
|
||||
ldata->overrun_time = jiffies;
|
||||
ldata->num_overrun = 0;
|
||||
@ -1691,7 +1690,7 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp,
|
||||
|
||||
room = N_TTY_BUF_SIZE - (ldata->read_head - tail);
|
||||
if (I_PARMRK(tty))
|
||||
room = (room + 2) / 3;
|
||||
room = DIV_ROUND_UP(room, 3);
|
||||
room--;
|
||||
if (room <= 0) {
|
||||
overflow = ldata->icanon && ldata->canon_head == tail;
|
||||
|
@ -365,6 +365,13 @@ static inline void serial8250_do_prepare_rx_dma(struct uart_8250_port *p)
|
||||
if (dma->prepare_rx_dma)
|
||||
dma->prepare_rx_dma(p);
|
||||
}
|
||||
|
||||
static inline bool serial8250_tx_dma_running(struct uart_8250_port *p)
|
||||
{
|
||||
struct uart_8250_dma *dma = p->dma;
|
||||
|
||||
return dma && dma->tx_running;
|
||||
}
|
||||
#else
|
||||
static inline int serial8250_tx_dma(struct uart_8250_port *p)
|
||||
{
|
||||
@ -380,6 +387,11 @@ static inline int serial8250_request_dma(struct uart_8250_port *p)
|
||||
return -1;
|
||||
}
|
||||
static inline void serial8250_release_dma(struct uart_8250_port *p) { }
|
||||
|
||||
static inline bool serial8250_tx_dma_running(struct uart_8250_port *p)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
|
||||
|
@ -1014,14 +1014,16 @@ static int brcmuart_probe(struct platform_device *pdev)
|
||||
/* See if a Baud clock has been specified */
|
||||
baud_mux_clk = of_clk_get_by_name(np, "sw_baud");
|
||||
if (IS_ERR(baud_mux_clk)) {
|
||||
if (PTR_ERR(baud_mux_clk) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
if (PTR_ERR(baud_mux_clk) == -EPROBE_DEFER) {
|
||||
ret = -EPROBE_DEFER;
|
||||
goto release_dma;
|
||||
}
|
||||
dev_dbg(dev, "BAUD MUX clock not specified\n");
|
||||
} else {
|
||||
dev_dbg(dev, "BAUD MUX clock found\n");
|
||||
ret = clk_prepare_enable(baud_mux_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto release_dma;
|
||||
priv->baud_mux_clk = baud_mux_clk;
|
||||
init_real_clk_rates(dev, priv);
|
||||
clk_rate = priv->default_mux_rate;
|
||||
@ -1029,7 +1031,8 @@ static int brcmuart_probe(struct platform_device *pdev)
|
||||
|
||||
if (clk_rate == 0) {
|
||||
dev_err(dev, "clock-frequency or clk not defined\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto release_dma;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "DMA is %senabled\n", priv->dma_enabled ? "" : "not ");
|
||||
@ -1116,7 +1119,9 @@ err1:
|
||||
serial8250_unregister_port(priv->line);
|
||||
err:
|
||||
brcmuart_free_bufs(dev, priv);
|
||||
brcmuart_arbitration(priv, 0);
|
||||
release_dma:
|
||||
if (priv->dma_enabled)
|
||||
brcmuart_arbitration(priv, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1128,7 +1133,8 @@ static int brcmuart_remove(struct platform_device *pdev)
|
||||
hrtimer_cancel(&priv->hrt);
|
||||
serial8250_unregister_port(priv->line);
|
||||
brcmuart_free_bufs(&pdev->dev, priv);
|
||||
brcmuart_arbitration(priv, 0);
|
||||
if (priv->dma_enabled)
|
||||
brcmuart_arbitration(priv, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1158,6 +1158,7 @@ void serial8250_unregister_port(int line)
|
||||
uart->port.type = PORT_UNKNOWN;
|
||||
uart->port.dev = &serial8250_isa_devs->dev;
|
||||
uart->capabilities = 0;
|
||||
serial8250_init_port(uart);
|
||||
serial8250_apply_quirks(uart);
|
||||
uart_add_one_port(&serial8250_reg, &uart->port);
|
||||
} else {
|
||||
|
@ -13,36 +13,49 @@
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "8250.h"
|
||||
|
||||
#define UART_DLL_EM 9
|
||||
#define UART_DLM_EM 10
|
||||
#define UART_HCR0_EM 11
|
||||
|
||||
/*
|
||||
* A high value for UART_FCR_EM avoids overlapping with existing UART_*
|
||||
* register defines. UART_FCR_EM_HW is the real HW register offset.
|
||||
*/
|
||||
#define UART_FCR_EM 0x10003
|
||||
#define UART_FCR_EM_HW 3
|
||||
|
||||
#define UART_HCR0_EM_SW_RESET BIT(7) /* SW Reset */
|
||||
|
||||
struct serial8250_em_priv {
|
||||
struct clk *sclk;
|
||||
int line;
|
||||
};
|
||||
|
||||
static void serial8250_em_serial_out(struct uart_port *p, int offset, int value)
|
||||
static void serial8250_em_serial_out_helper(struct uart_port *p, int offset,
|
||||
int value)
|
||||
{
|
||||
switch (offset) {
|
||||
case UART_TX: /* TX @ 0x00 */
|
||||
writeb(value, p->membase);
|
||||
break;
|
||||
case UART_FCR: /* FCR @ 0x0c (+1) */
|
||||
case UART_LCR: /* LCR @ 0x10 (+1) */
|
||||
case UART_MCR: /* MCR @ 0x14 (+1) */
|
||||
case UART_SCR: /* SCR @ 0x20 (+1) */
|
||||
writel(value, p->membase + ((offset + 1) << 2));
|
||||
break;
|
||||
case UART_FCR_EM:
|
||||
writel(value, p->membase + (UART_FCR_EM_HW << 2));
|
||||
break;
|
||||
case UART_IER: /* IER @ 0x04 */
|
||||
value &= 0x0f; /* only 4 valid bits - not Xscale */
|
||||
fallthrough;
|
||||
case UART_DLL_EM: /* DLL @ 0x24 (+9) */
|
||||
case UART_DLM_EM: /* DLM @ 0x28 (+9) */
|
||||
case UART_HCR0_EM: /* HCR0 @ 0x2c */
|
||||
writel(value, p->membase + (offset << 2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,20 +64,81 @@ static unsigned int serial8250_em_serial_in(struct uart_port *p, int offset)
|
||||
switch (offset) {
|
||||
case UART_RX: /* RX @ 0x00 */
|
||||
return readb(p->membase);
|
||||
case UART_LCR: /* LCR @ 0x10 (+1) */
|
||||
case UART_MCR: /* MCR @ 0x14 (+1) */
|
||||
case UART_LSR: /* LSR @ 0x18 (+1) */
|
||||
case UART_MSR: /* MSR @ 0x1c (+1) */
|
||||
case UART_SCR: /* SCR @ 0x20 (+1) */
|
||||
return readl(p->membase + ((offset + 1) << 2));
|
||||
case UART_FCR_EM:
|
||||
return readl(p->membase + (UART_FCR_EM_HW << 2));
|
||||
case UART_IER: /* IER @ 0x04 */
|
||||
case UART_IIR: /* IIR @ 0x08 */
|
||||
case UART_DLL_EM: /* DLL @ 0x24 (+9) */
|
||||
case UART_DLM_EM: /* DLM @ 0x28 (+9) */
|
||||
case UART_HCR0_EM: /* HCR0 @ 0x2c */
|
||||
return readl(p->membase + (offset << 2));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void serial8250_em_reg_update(struct uart_port *p, int off, int value)
|
||||
{
|
||||
unsigned int ier, fcr, lcr, mcr, hcr0;
|
||||
|
||||
ier = serial8250_em_serial_in(p, UART_IER);
|
||||
fcr = serial8250_em_serial_in(p, UART_FCR_EM);
|
||||
lcr = serial8250_em_serial_in(p, UART_LCR);
|
||||
mcr = serial8250_em_serial_in(p, UART_MCR);
|
||||
hcr0 = serial8250_em_serial_in(p, UART_HCR0_EM);
|
||||
|
||||
serial8250_em_serial_out_helper(p, UART_FCR_EM, fcr |
|
||||
UART_FCR_CLEAR_RCVR |
|
||||
UART_FCR_CLEAR_XMIT);
|
||||
serial8250_em_serial_out_helper(p, UART_HCR0_EM, hcr0 |
|
||||
UART_HCR0_EM_SW_RESET);
|
||||
serial8250_em_serial_out_helper(p, UART_HCR0_EM, hcr0 &
|
||||
~UART_HCR0_EM_SW_RESET);
|
||||
|
||||
switch (off) {
|
||||
case UART_FCR_EM:
|
||||
fcr = value;
|
||||
break;
|
||||
case UART_LCR:
|
||||
lcr = value;
|
||||
break;
|
||||
case UART_MCR:
|
||||
mcr = value;
|
||||
break;
|
||||
}
|
||||
|
||||
serial8250_em_serial_out_helper(p, UART_IER, ier);
|
||||
serial8250_em_serial_out_helper(p, UART_FCR_EM, fcr);
|
||||
serial8250_em_serial_out_helper(p, UART_MCR, mcr);
|
||||
serial8250_em_serial_out_helper(p, UART_LCR, lcr);
|
||||
serial8250_em_serial_out_helper(p, UART_HCR0_EM, hcr0);
|
||||
}
|
||||
|
||||
static void serial8250_em_serial_out(struct uart_port *p, int offset, int value)
|
||||
{
|
||||
switch (offset) {
|
||||
case UART_TX:
|
||||
case UART_SCR:
|
||||
case UART_IER:
|
||||
case UART_DLL_EM:
|
||||
case UART_DLM_EM:
|
||||
serial8250_em_serial_out_helper(p, offset, value);
|
||||
break;
|
||||
case UART_FCR:
|
||||
serial8250_em_reg_update(p, UART_FCR_EM, value);
|
||||
break;
|
||||
case UART_LCR:
|
||||
case UART_MCR:
|
||||
serial8250_em_reg_update(p, offset, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int serial8250_em_serial_dl_read(struct uart_8250_port *up)
|
||||
{
|
||||
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)
|
||||
static int serial8250_em_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct serial8250_em_priv *priv;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct uart_8250_port up;
|
||||
struct resource *regs;
|
||||
struct clk *sclk;
|
||||
int irq, ret;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
@ -88,31 +164,26 @@ static int serial8250_em_probe(struct platform_device *pdev)
|
||||
return irq;
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!regs) {
|
||||
dev_err(&pdev->dev, "missing registers\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!regs)
|
||||
return dev_err_probe(dev, -EINVAL, "missing registers\n");
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->sclk = devm_clk_get(&pdev->dev, "sclk");
|
||||
if (IS_ERR(priv->sclk)) {
|
||||
dev_err(&pdev->dev, "unable to get clock\n");
|
||||
return PTR_ERR(priv->sclk);
|
||||
}
|
||||
sclk = devm_clk_get_enabled(dev, "sclk");
|
||||
if (IS_ERR(sclk))
|
||||
return dev_err_probe(dev, PTR_ERR(sclk), "unable to get clock\n");
|
||||
|
||||
memset(&up, 0, sizeof(up));
|
||||
up.port.mapbase = regs->start;
|
||||
up.port.irq = irq;
|
||||
up.port.type = PORT_16750;
|
||||
up.port.flags = UPF_FIXED_PORT | UPF_IOREMAP | UPF_FIXED_TYPE;
|
||||
up.port.dev = &pdev->dev;
|
||||
up.port.dev = dev;
|
||||
up.port.private_data = priv;
|
||||
|
||||
clk_prepare_enable(priv->sclk);
|
||||
up.port.uartclk = clk_get_rate(priv->sclk);
|
||||
up.port.uartclk = clk_get_rate(sclk);
|
||||
|
||||
up.port.iotype = UPIO_MEM32;
|
||||
up.port.serial_in = serial8250_em_serial_in;
|
||||
@ -121,11 +192,8 @@ static int serial8250_em_probe(struct platform_device *pdev)
|
||||
up.dl_write = serial8250_em_serial_dl_write;
|
||||
|
||||
ret = serial8250_register_8250_port(&up);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "unable to register 8250 port\n");
|
||||
clk_disable_unprepare(priv->sclk);
|
||||
return ret;
|
||||
}
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "unable to register 8250 port\n");
|
||||
|
||||
priv->line = ret;
|
||||
platform_set_drvdata(pdev, priv);
|
||||
@ -137,7 +205,6 @@ static int serial8250_em_remove(struct platform_device *pdev)
|
||||
struct serial8250_em_priv *priv = platform_get_drvdata(pdev);
|
||||
|
||||
serial8250_unregister_port(priv->line);
|
||||
clk_disable_unprepare(priv->sclk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/sysrq.h>
|
||||
@ -1932,6 +1933,7 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir)
|
||||
int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
struct tty_port *tport = &port->state->port;
|
||||
bool skip_rx = false;
|
||||
unsigned long flags;
|
||||
u16 status;
|
||||
@ -1957,6 +1959,8 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
|
||||
skip_rx = true;
|
||||
|
||||
if (status & (UART_LSR_DR | UART_LSR_BI) && !skip_rx) {
|
||||
if (irqd_is_wakeup_set(irq_get_irq_data(port->irq)))
|
||||
pm_wakeup_event(tport->tty->dev, 0);
|
||||
if (!up->dma || handle_rx_dma(up, iir))
|
||||
status = serial8250_rx_chars(up, status);
|
||||
}
|
||||
@ -2016,18 +2020,19 @@ static int serial8250_tx_threshold_handle_irq(struct uart_port *port)
|
||||
static unsigned int serial8250_tx_empty(struct uart_port *port)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
unsigned int result = 0;
|
||||
unsigned long flags;
|
||||
u16 lsr;
|
||||
|
||||
serial8250_rpm_get(up);
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
lsr = serial_lsr_in(up);
|
||||
if (!serial8250_tx_dma_running(up) && uart_lsr_tx_empty(serial_lsr_in(up)))
|
||||
result = TIOCSER_TEMT;
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
serial8250_rpm_put(up);
|
||||
|
||||
return uart_lsr_tx_empty(lsr) ? TIOCSER_TEMT : 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned int serial8250_do_get_mctrl(struct uart_port *port)
|
||||
|
@ -248,13 +248,6 @@ config SERIAL_SAMSUNG
|
||||
|
||||
Choose Y/M here only if you build for such SoC.
|
||||
|
||||
config SERIAL_SAMSUNG_UARTS_4
|
||||
bool
|
||||
depends on SERIAL_SAMSUNG
|
||||
default y
|
||||
help
|
||||
Internal node for the common case of 4 Samsung compatible UARTs
|
||||
|
||||
config SERIAL_SAMSUNG_UARTS
|
||||
int
|
||||
depends on SERIAL_SAMSUNG
|
||||
@ -958,7 +951,7 @@ config SERIAL_OMAP_CONSOLE
|
||||
config SERIAL_SIFIVE
|
||||
tristate "SiFive UART support"
|
||||
depends on OF
|
||||
default SOC_SIFIVE || SOC_CANAAN
|
||||
default ARCH_SIFIVE || ARCH_CANAAN
|
||||
select SERIAL_CORE
|
||||
help
|
||||
Select this option if you are building a kernel for a device that
|
||||
@ -968,7 +961,7 @@ config SERIAL_SIFIVE
|
||||
config SERIAL_SIFIVE_CONSOLE
|
||||
bool "Console on SiFive UART"
|
||||
depends on SERIAL_SIFIVE=y
|
||||
default SOC_SIFIVE || SOC_CANAAN
|
||||
default ARCH_SIFIVE || ARCH_CANAAN
|
||||
select SERIAL_CORE_CONSOLE
|
||||
select SERIAL_EARLYCON
|
||||
help
|
||||
|
@ -596,6 +596,40 @@ static int bcm_uart_verify_port(struct uart_port *port,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CONSOLE_POLL
|
||||
/*
|
||||
* return true when outstanding tx equals fifo size
|
||||
*/
|
||||
static bool bcm_uart_tx_full(struct uart_port *port)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
val = bcm_uart_readl(port, UART_MCTL_REG);
|
||||
val = (val & UART_MCTL_TXFIFOFILL_MASK) >> UART_MCTL_TXFIFOFILL_SHIFT;
|
||||
return !(port->fifosize - val);
|
||||
}
|
||||
|
||||
static int bcm_uart_poll_get_char(struct uart_port *port)
|
||||
{
|
||||
unsigned int iestat;
|
||||
|
||||
iestat = bcm_uart_readl(port, UART_IR_REG);
|
||||
if (!(iestat & UART_IR_STAT(UART_IR_RXNOTEMPTY)))
|
||||
return NO_POLL_CHAR;
|
||||
|
||||
return bcm_uart_readl(port, UART_FIFO_REG);
|
||||
}
|
||||
|
||||
static void bcm_uart_poll_put_char(struct uart_port *port, unsigned char c)
|
||||
{
|
||||
while (bcm_uart_tx_full(port)) {
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
bcm_uart_writel(port, c, UART_FIFO_REG);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* serial core callbacks */
|
||||
static const struct uart_ops bcm_uart_ops = {
|
||||
.tx_empty = bcm_uart_tx_empty,
|
||||
@ -614,6 +648,10 @@ static const struct uart_ops bcm_uart_ops = {
|
||||
.request_port = bcm_uart_request_port,
|
||||
.config_port = bcm_uart_config_port,
|
||||
.verify_port = bcm_uart_verify_port,
|
||||
#ifdef CONFIG_CONSOLE_POLL
|
||||
.poll_get_char = bcm_uart_poll_get_char,
|
||||
.poll_put_char = bcm_uart_poll_put_char,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -678,15 +678,14 @@ static int cpm_uart_tx_pump(struct uart_port *port)
|
||||
/* Pick next descriptor and fill from buffer */
|
||||
bdp = pinfo->tx_cur;
|
||||
|
||||
while (!(in_be16(&bdp->cbd_sc) & BD_SC_READY) &&
|
||||
xmit->tail != xmit->head) {
|
||||
while (!(in_be16(&bdp->cbd_sc) & BD_SC_READY) && !uart_circ_empty(xmit)) {
|
||||
count = 0;
|
||||
p = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
|
||||
while (count < pinfo->tx_fifosize) {
|
||||
*p++ = xmit->buf[xmit->tail];
|
||||
uart_xmit_advance(port, 1);
|
||||
count++;
|
||||
if (xmit->head == xmit->tail)
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
}
|
||||
out_be16(&bdp->cbd_datlen, count);
|
||||
|
@ -1296,7 +1296,7 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
|
||||
* 10ms at any baud rate.
|
||||
*/
|
||||
sport->rx_dma_rng_buf_len = (DMA_RX_TIMEOUT * baud / bits / 1000) * 2;
|
||||
sport->rx_dma_rng_buf_len = (1 << (fls(sport->rx_dma_rng_buf_len) - 1));
|
||||
sport->rx_dma_rng_buf_len = (1 << fls(sport->rx_dma_rng_buf_len));
|
||||
if (sport->rx_dma_rng_buf_len < 16)
|
||||
sport->rx_dma_rng_buf_len = 16;
|
||||
|
||||
@ -1406,12 +1406,12 @@ static int lpuart32_config_rs485(struct uart_port *port, struct ktermios *termio
|
||||
struct lpuart_port, port);
|
||||
|
||||
unsigned long modem = lpuart32_read(&sport->port, UARTMODIR)
|
||||
& ~(UARTMODEM_TXRTSPOL | UARTMODEM_TXRTSE);
|
||||
& ~(UARTMODIR_TXRTSPOL | UARTMODIR_TXRTSE);
|
||||
lpuart32_write(&sport->port, modem, UARTMODIR);
|
||||
|
||||
if (rs485->flags & SER_RS485_ENABLED) {
|
||||
/* Enable auto RS-485 RTS mode */
|
||||
modem |= UARTMODEM_TXRTSE;
|
||||
modem |= UARTMODIR_TXRTSE;
|
||||
|
||||
/*
|
||||
* 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
|
||||
* Note: UART is assumed to be active high.
|
||||
*/
|
||||
if (rs485->flags & SER_RS485_RTS_ON_SEND)
|
||||
modem |= UARTMODEM_TXRTSPOL;
|
||||
modem |= UARTMODIR_TXRTSPOL;
|
||||
else if (rs485->flags & SER_RS485_RTS_AFTER_SEND)
|
||||
modem &= ~UARTMODEM_TXRTSPOL;
|
||||
modem &= ~UARTMODIR_TXRTSPOL;
|
||||
}
|
||||
|
||||
lpuart32_write(&sport->port, modem, UARTMODIR);
|
||||
|
@ -289,20 +289,6 @@ static inline int imx_uart_is_imx1(struct imx_port *sport)
|
||||
return sport->devdata->devtype == IMX1_UART;
|
||||
}
|
||||
|
||||
static inline int imx_uart_is_imx21(struct imx_port *sport)
|
||||
{
|
||||
return sport->devdata->devtype == IMX21_UART;
|
||||
}
|
||||
|
||||
static inline int imx_uart_is_imx53(struct imx_port *sport)
|
||||
{
|
||||
return sport->devdata->devtype == IMX53_UART;
|
||||
}
|
||||
|
||||
static inline int imx_uart_is_imx6q(struct imx_port *sport)
|
||||
{
|
||||
return sport->devdata->devtype == IMX6Q_UART;
|
||||
}
|
||||
/*
|
||||
* Save and restore functions for UCR1, UCR2 and UCR3 registers
|
||||
*/
|
||||
@ -1808,9 +1794,7 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
|
||||
static const char *imx_uart_type(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
|
||||
return sport->port.type == PORT_IMX ? "IMX" : NULL;
|
||||
return port->type == PORT_IMX ? "IMX" : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1818,10 +1802,8 @@ static const char *imx_uart_type(struct uart_port *port)
|
||||
*/
|
||||
static void imx_uart_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
|
||||
if (flags & UART_CONFIG_TYPE)
|
||||
sport->port.type = PORT_IMX;
|
||||
port->type = PORT_IMX;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1832,20 +1814,19 @@ static void imx_uart_config_port(struct uart_port *port, int flags)
|
||||
static int
|
||||
imx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
int ret = 0;
|
||||
|
||||
if (ser->type != PORT_UNKNOWN && ser->type != PORT_IMX)
|
||||
ret = -EINVAL;
|
||||
if (sport->port.irq != ser->irq)
|
||||
if (port->irq != ser->irq)
|
||||
ret = -EINVAL;
|
||||
if (ser->io_type != UPIO_MEM)
|
||||
ret = -EINVAL;
|
||||
if (sport->port.uartclk / 16 != ser->baud_base)
|
||||
if (port->uartclk / 16 != ser->baud_base)
|
||||
ret = -EINVAL;
|
||||
if (sport->port.mapbase != (unsigned long)ser->iomem_base)
|
||||
if (port->mapbase != (unsigned long)ser->iomem_base)
|
||||
ret = -EINVAL;
|
||||
if (sport->port.iobase != ser->port)
|
||||
if (port->iobase != ser->port)
|
||||
ret = -EINVAL;
|
||||
if (ser->hub6 != 0)
|
||||
ret = -EINVAL;
|
||||
@ -2262,21 +2243,16 @@ static int imx_uart_probe(struct platform_device *pdev)
|
||||
}
|
||||
sport->port.line = ret;
|
||||
|
||||
if (of_get_property(np, "uart-has-rtscts", NULL) ||
|
||||
of_get_property(np, "fsl,uart-has-rtscts", NULL) /* deprecated */)
|
||||
sport->have_rtscts = 1;
|
||||
sport->have_rtscts = of_property_read_bool(np, "uart-has-rtscts") ||
|
||||
of_property_read_bool(np, "fsl,uart-has-rtscts"); /* deprecated */
|
||||
|
||||
if (of_get_property(np, "fsl,dte-mode", NULL))
|
||||
sport->dte_mode = 1;
|
||||
sport->dte_mode = of_property_read_bool(np, "fsl,dte-mode");
|
||||
|
||||
if (of_get_property(np, "rts-gpios", NULL))
|
||||
sport->have_rtsgpio = 1;
|
||||
sport->have_rtsgpio = of_property_present(np, "rts-gpios");
|
||||
|
||||
if (of_get_property(np, "fsl,inverted-tx", NULL))
|
||||
sport->inverted_tx = 1;
|
||||
sport->inverted_tx = of_property_read_bool(np, "fsl,inverted-tx");
|
||||
|
||||
if (of_get_property(np, "fsl,inverted-rx", NULL))
|
||||
sport->inverted_rx = 1;
|
||||
sport->inverted_rx = of_property_read_bool(np, "fsl,inverted-rx");
|
||||
|
||||
if (!of_property_read_u32_array(np, "fsl,dma-info", dma_buf_conf, 2)) {
|
||||
sport->rx_period_length = dma_buf_conf[0];
|
||||
|
@ -525,6 +525,11 @@ static bool max310x_reg_precious(struct device *dev, unsigned int reg)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool max310x_reg_noinc(struct device *dev, unsigned int reg)
|
||||
{
|
||||
return reg == MAX310X_RHR_REG;
|
||||
}
|
||||
|
||||
static int max310x_set_baud(struct uart_port *port, int baud)
|
||||
{
|
||||
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
|
||||
{
|
||||
struct max310x_one *one = to_max310x_port(port);
|
||||
|
||||
regmap_raw_write(one->regmap, MAX310X_THR_REG, txbuf, len);
|
||||
regmap_noinc_write(one->regmap, MAX310X_THR_REG, txbuf, len);
|
||||
}
|
||||
|
||||
static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned int len)
|
||||
{
|
||||
struct max310x_one *one = to_max310x_port(port);
|
||||
|
||||
regmap_raw_read(one->regmap, MAX310X_RHR_REG, rxbuf, len);
|
||||
regmap_noinc_read(one->regmap, MAX310X_RHR_REG, rxbuf, len);
|
||||
}
|
||||
|
||||
static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
|
||||
@ -1468,6 +1473,10 @@ static struct regmap_config regcfg = {
|
||||
.writeable_reg = max310x_reg_writeable,
|
||||
.volatile_reg = max310x_reg_volatile,
|
||||
.precious_reg = max310x_reg_precious,
|
||||
.writeable_noinc_reg = max310x_reg_noinc,
|
||||
.readable_noinc_reg = max310x_reg_noinc,
|
||||
.max_raw_read = MAX310X_FIFO_SIZE,
|
||||
.max_raw_write = MAX310X_FIFO_SIZE,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SPI_MASTER
|
||||
@ -1553,6 +1562,10 @@ static struct regmap_config regcfg_i2c = {
|
||||
.volatile_reg = max310x_reg_volatile,
|
||||
.precious_reg = max310x_reg_precious,
|
||||
.max_register = MAX310X_I2C_REVID_EXTREG,
|
||||
.writeable_noinc_reg = max310x_reg_noinc,
|
||||
.readable_noinc_reg = max310x_reg_noinc,
|
||||
.max_raw_read = MAX310X_FIFO_SIZE,
|
||||
.max_raw_write = MAX310X_FIFO_SIZE,
|
||||
};
|
||||
|
||||
static const struct max310x_if_cfg max310x_i2c_if_cfg = {
|
||||
|
@ -779,7 +779,7 @@ static int meson_uart_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct meson_uart_data s4_uart_data = {
|
||||
static struct meson_uart_data meson_g12a_uart_data = {
|
||||
.has_xtal_div2 = true,
|
||||
};
|
||||
|
||||
@ -788,9 +788,13 @@ static const struct of_device_id meson_uart_dt_match[] = {
|
||||
{ .compatible = "amlogic,meson8-uart" },
|
||||
{ .compatible = "amlogic,meson8b-uart" },
|
||||
{ .compatible = "amlogic,meson-gx-uart" },
|
||||
{
|
||||
.compatible = "amlogic,meson-g12a-uart",
|
||||
.data = (void *)&meson_g12a_uart_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,meson-s4-uart",
|
||||
.data = (void *)&s4_uart_data,
|
||||
.data = (void *)&meson_g12a_uart_data,
|
||||
},
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
@ -1587,8 +1587,8 @@ static int mxs_auart_probe(struct platform_device *pdev)
|
||||
}
|
||||
s->port.line = ret;
|
||||
|
||||
if (of_get_property(np, "uart-has-rtscts", NULL) ||
|
||||
of_get_property(np, "fsl,uart-has-rtscts", NULL) /* deprecated */)
|
||||
if (of_property_read_bool(np, "uart-has-rtscts") ||
|
||||
of_property_read_bool(np, "fsl,uart-has-rtscts") /* deprecated */)
|
||||
set_bit(MXS_AUART_RTSCTS, &s->flags);
|
||||
|
||||
if (s->port.line >= ARRAY_SIZE(auart_port)) {
|
||||
|
@ -854,21 +854,19 @@ static void qcom_geni_serial_stop_tx(struct uart_port *uport)
|
||||
}
|
||||
|
||||
static void qcom_geni_serial_send_chunk_fifo(struct uart_port *uport,
|
||||
unsigned int chunk)
|
||||
unsigned int remaining)
|
||||
{
|
||||
struct qcom_geni_serial_port *port = to_dev_port(uport);
|
||||
struct circ_buf *xmit = &uport->state->xmit;
|
||||
unsigned int tx_bytes, c, remaining = chunk;
|
||||
unsigned int tx_bytes;
|
||||
u8 buf[BYTES_PER_FIFO_WORD];
|
||||
|
||||
while (remaining) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
tx_bytes = min(remaining, BYTES_PER_FIFO_WORD);
|
||||
|
||||
for (c = 0; c < tx_bytes ; c++) {
|
||||
buf[c] = xmit->buf[xmit->tail];
|
||||
uart_xmit_advance(uport, 1);
|
||||
}
|
||||
memcpy(buf, &xmit->buf[xmit->tail], tx_bytes);
|
||||
uart_xmit_advance(uport, tx_bytes);
|
||||
|
||||
iowrite32_rep(uport->membase + SE_GENI_TX_FIFOn, buf, 1);
|
||||
|
||||
@ -1535,6 +1533,7 @@ static const struct uart_ops qcom_geni_console_pops = {
|
||||
#ifdef CONFIG_CONSOLE_POLL
|
||||
.poll_get_char = qcom_geni_serial_get_char,
|
||||
.poll_put_char = qcom_geni_serial_poll_put_char,
|
||||
.poll_init = qcom_geni_serial_port_setup,
|
||||
#endif
|
||||
.pm = qcom_geni_serial_pm,
|
||||
};
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include <asm/sibyte/swarm.h>
|
||||
|
||||
|
||||
#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
|
||||
#if defined(CONFIG_SIBYTE_BCM1x80)
|
||||
#include <asm/sibyte/bcm1480_regs.h>
|
||||
#include <asm/sibyte/bcm1480_int.h>
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
@ -48,9 +49,6 @@ static struct lock_class_key port_lock_key;
|
||||
*/
|
||||
#define RS485_MAX_RTS_DELAY 100 /* msecs */
|
||||
|
||||
static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
|
||||
const struct ktermios *old_termios);
|
||||
static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
|
||||
static void uart_change_pm(struct uart_state *state,
|
||||
enum uart_pm_state pm_state);
|
||||
|
||||
@ -137,7 +135,7 @@ static void __uart_start(struct tty_struct *tty)
|
||||
struct uart_state *state = tty->driver_data;
|
||||
struct uart_port *port = state->uart_port;
|
||||
|
||||
if (port && !uart_tx_stopped(port))
|
||||
if (port && !(port->flags & UPF_DEAD) && !uart_tx_stopped(port))
|
||||
port->ops->start_tx(port);
|
||||
}
|
||||
|
||||
@ -177,6 +175,51 @@ static void uart_port_dtr_rts(struct uart_port *uport, bool active)
|
||||
uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
|
||||
}
|
||||
|
||||
/* Caller holds port mutex */
|
||||
static void uart_change_line_settings(struct tty_struct *tty, struct uart_state *state,
|
||||
const struct ktermios *old_termios)
|
||||
{
|
||||
struct uart_port *uport = uart_port_check(state);
|
||||
struct ktermios *termios;
|
||||
bool old_hw_stopped;
|
||||
|
||||
/*
|
||||
* If we have no tty, termios, or the port does not exist,
|
||||
* then we can't set the parameters for this port.
|
||||
*/
|
||||
if (!tty || uport->type == PORT_UNKNOWN)
|
||||
return;
|
||||
|
||||
termios = &tty->termios;
|
||||
uport->ops->set_termios(uport, termios, old_termios);
|
||||
|
||||
/*
|
||||
* Set modem status enables based on termios cflag
|
||||
*/
|
||||
spin_lock_irq(&uport->lock);
|
||||
if (termios->c_cflag & CRTSCTS)
|
||||
uport->status |= UPSTAT_CTS_ENABLE;
|
||||
else
|
||||
uport->status &= ~UPSTAT_CTS_ENABLE;
|
||||
|
||||
if (termios->c_cflag & CLOCAL)
|
||||
uport->status &= ~UPSTAT_DCD_ENABLE;
|
||||
else
|
||||
uport->status |= UPSTAT_DCD_ENABLE;
|
||||
|
||||
/* reset sw-assisted CTS flow control based on (possibly) new mode */
|
||||
old_hw_stopped = uport->hw_stopped;
|
||||
uport->hw_stopped = uart_softcts_mode(uport) &&
|
||||
!(uport->ops->get_mctrl(uport) & TIOCM_CTS);
|
||||
if (uport->hw_stopped != old_hw_stopped) {
|
||||
if (!old_hw_stopped)
|
||||
uport->ops->stop_tx(uport);
|
||||
else
|
||||
__uart_start(tty);
|
||||
}
|
||||
spin_unlock_irq(&uport->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Startup the port. This will be called once per open. All calls
|
||||
* 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,
|
||||
/*
|
||||
* Initialise the hardware port settings.
|
||||
*/
|
||||
uart_change_speed(tty, state, NULL);
|
||||
uart_change_line_settings(tty, state, NULL);
|
||||
|
||||
/*
|
||||
* Setup the RTS and DTR signals once the
|
||||
@ -485,52 +528,6 @@ uart_get_divisor(struct uart_port *port, unsigned int baud)
|
||||
}
|
||||
EXPORT_SYMBOL(uart_get_divisor);
|
||||
|
||||
/* Caller holds port mutex */
|
||||
static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
|
||||
const struct ktermios *old_termios)
|
||||
{
|
||||
struct uart_port *uport = uart_port_check(state);
|
||||
struct ktermios *termios;
|
||||
int hw_stopped;
|
||||
|
||||
/*
|
||||
* If we have no tty, termios, or the port does not exist,
|
||||
* then we can't set the parameters for this port.
|
||||
*/
|
||||
if (!tty || uport->type == PORT_UNKNOWN)
|
||||
return;
|
||||
|
||||
termios = &tty->termios;
|
||||
uport->ops->set_termios(uport, termios, old_termios);
|
||||
|
||||
/*
|
||||
* Set modem status enables based on termios cflag
|
||||
*/
|
||||
spin_lock_irq(&uport->lock);
|
||||
if (termios->c_cflag & CRTSCTS)
|
||||
uport->status |= UPSTAT_CTS_ENABLE;
|
||||
else
|
||||
uport->status &= ~UPSTAT_CTS_ENABLE;
|
||||
|
||||
if (termios->c_cflag & CLOCAL)
|
||||
uport->status &= ~UPSTAT_DCD_ENABLE;
|
||||
else
|
||||
uport->status |= UPSTAT_DCD_ENABLE;
|
||||
|
||||
/* reset sw-assisted CTS flow control based on (possibly) new mode */
|
||||
hw_stopped = uport->hw_stopped;
|
||||
uport->hw_stopped = uart_softcts_mode(uport) &&
|
||||
!(uport->ops->get_mctrl(uport) & TIOCM_CTS);
|
||||
if (uport->hw_stopped) {
|
||||
if (!hw_stopped)
|
||||
uport->ops->stop_tx(uport);
|
||||
} else {
|
||||
if (hw_stopped)
|
||||
__uart_start(tty);
|
||||
}
|
||||
spin_unlock_irq(&uport->lock);
|
||||
}
|
||||
|
||||
static int uart_put_char(struct tty_struct *tty, unsigned char c)
|
||||
{
|
||||
struct uart_state *state = tty->driver_data;
|
||||
@ -994,7 +991,7 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
|
||||
current->comm,
|
||||
tty_name(port->tty));
|
||||
}
|
||||
uart_change_speed(tty, state, NULL);
|
||||
uart_change_line_settings(tty, state, NULL);
|
||||
}
|
||||
} else {
|
||||
retval = uart_startup(tty, state, true);
|
||||
@ -1491,7 +1488,7 @@ static int uart_set_iso7816_config(struct uart_port *port,
|
||||
* There are 5 words reserved for future use. Check that userspace
|
||||
* doesn't put stuff in there to prevent breakages in the future.
|
||||
*/
|
||||
for (i = 0; i < 5; i++)
|
||||
for (i = 0; i < ARRAY_SIZE(iso7816.reserved); i++)
|
||||
if (iso7816.reserved[i])
|
||||
return -EINVAL;
|
||||
|
||||
@ -1552,7 +1549,7 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
|
||||
goto out;
|
||||
|
||||
/* rs485_config requires more locking than others */
|
||||
if (cmd == TIOCGRS485)
|
||||
if (cmd == TIOCSRS485)
|
||||
down_write(&tty->termios_rwsem);
|
||||
|
||||
mutex_lock(&port->mutex);
|
||||
@ -1595,7 +1592,7 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
|
||||
}
|
||||
out_up:
|
||||
mutex_unlock(&port->mutex);
|
||||
if (cmd == TIOCGRS485)
|
||||
if (cmd == TIOCSRS485)
|
||||
up_write(&tty->termios_rwsem);
|
||||
out:
|
||||
return ret;
|
||||
@ -1656,15 +1653,15 @@ static void uart_set_termios(struct tty_struct *tty,
|
||||
goto out;
|
||||
}
|
||||
|
||||
uart_change_speed(tty, state, old_termios);
|
||||
uart_change_line_settings(tty, state, old_termios);
|
||||
/* reload cflag from termios; port driver may have overridden flags */
|
||||
cflag = tty->termios.c_cflag;
|
||||
|
||||
/* Handle transition to B0 status */
|
||||
if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
|
||||
if (((old_termios->c_cflag & CBAUD) != B0) && ((cflag & CBAUD) == B0))
|
||||
uart_clear_mctrl(uport, TIOCM_RTS | TIOCM_DTR);
|
||||
/* Handle transition away from B0 status */
|
||||
else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
|
||||
else if (((old_termios->c_cflag & CBAUD) == B0) && ((cflag & CBAUD) != B0)) {
|
||||
unsigned int mask = TIOCM_DTR;
|
||||
|
||||
if (!(cflag & CRTSCTS) || !tty_throttled(tty))
|
||||
@ -2452,7 +2449,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
|
||||
ret = ops->startup(uport);
|
||||
if (ret == 0) {
|
||||
if (tty)
|
||||
uart_change_speed(tty, state, NULL);
|
||||
uart_change_line_settings(tty, state, NULL);
|
||||
spin_lock_irq(&uport->lock);
|
||||
if (!(uport->rs485.flags & SER_RS485_ENABLED))
|
||||
ops->set_mctrl(uport, uport->mctrl);
|
||||
@ -2593,6 +2590,7 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options)
|
||||
{
|
||||
struct uart_driver *drv = driver->driver_state;
|
||||
struct uart_state *state = drv->state + line;
|
||||
enum uart_pm_state pm_state;
|
||||
struct tty_port *tport;
|
||||
struct uart_port *port;
|
||||
int baud = 9600;
|
||||
@ -2610,6 +2608,9 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options)
|
||||
goto out;
|
||||
}
|
||||
|
||||
pm_state = state->pm_state;
|
||||
uart_change_pm(state, UART_PM_STATE_ON);
|
||||
|
||||
if (port->ops->poll_init) {
|
||||
/*
|
||||
* 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)
|
||||
console_list_unlock();
|
||||
}
|
||||
out:
|
||||
if (ret)
|
||||
uart_change_pm(state, pm_state);
|
||||
mutex_unlock(&tport->mutex);
|
||||
return ret;
|
||||
}
|
||||
@ -3305,13 +3308,13 @@ void uart_handle_cts_change(struct uart_port *uport, bool active)
|
||||
if (uart_softcts_mode(uport)) {
|
||||
if (uport->hw_stopped) {
|
||||
if (active) {
|
||||
uport->hw_stopped = 0;
|
||||
uport->hw_stopped = false;
|
||||
uport->ops->start_tx(uport);
|
||||
uart_write_wakeup(uport);
|
||||
}
|
||||
} else {
|
||||
if (!active) {
|
||||
uport->hw_stopped = 1;
|
||||
uport->hw_stopped = true;
|
||||
uport->ops->stop_tx(uport);
|
||||
}
|
||||
}
|
||||
|
@ -588,14 +588,28 @@ static void sci_start_tx(struct uart_port *port)
|
||||
|
||||
if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) &&
|
||||
dma_submit_error(s->cookie_tx)) {
|
||||
if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE)
|
||||
/* Switch irq from SCIF to DMA */
|
||||
disable_irq(s->irqs[SCIx_TXI_IRQ]);
|
||||
|
||||
s->cookie_tx = 0;
|
||||
schedule_work(&s->work_tx);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||
if (!s->chan_tx || s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE ||
|
||||
port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||
/* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
|
||||
ctrl = serial_port_in(port, SCSCR);
|
||||
|
||||
/*
|
||||
* For SCI, TE (transmit enable) must be set after setting TIE
|
||||
* (transmit interrupt enable) or in the same instruction to start
|
||||
* the transmit process.
|
||||
*/
|
||||
if (port->type == PORT_SCI)
|
||||
ctrl |= SCSCR_TE;
|
||||
|
||||
serial_port_out(port, SCSCR, ctrl | SCSCR_TIE);
|
||||
}
|
||||
}
|
||||
@ -833,6 +847,11 @@ static void sci_transmit_chars(struct uart_port *port)
|
||||
} else if (!uart_circ_empty(xmit) && !stopped) {
|
||||
c = xmit->buf[xmit->tail];
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
} else if (port->type == PORT_SCI && uart_circ_empty(xmit)) {
|
||||
ctrl = serial_port_in(port, SCSCR);
|
||||
ctrl &= ~SCSCR_TE;
|
||||
serial_port_out(port, SCSCR, ctrl);
|
||||
return;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@ -846,9 +865,16 @@ static void sci_transmit_chars(struct uart_port *port)
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
if (uart_circ_empty(xmit))
|
||||
sci_stop_tx(port);
|
||||
if (uart_circ_empty(xmit)) {
|
||||
if (port->type == PORT_SCI) {
|
||||
ctrl = serial_port_in(port, SCSCR);
|
||||
ctrl &= ~SCSCR_TIE;
|
||||
ctrl |= SCSCR_TEIE;
|
||||
serial_port_out(port, SCSCR, ctrl);
|
||||
}
|
||||
|
||||
sci_stop_tx(port);
|
||||
}
|
||||
}
|
||||
|
||||
static void sci_receive_chars(struct uart_port *port)
|
||||
@ -1192,9 +1218,15 @@ static void sci_dma_tx_complete(void *arg)
|
||||
schedule_work(&s->work_tx);
|
||||
} else {
|
||||
s->cookie_tx = -EINVAL;
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB ||
|
||||
s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) {
|
||||
u16 ctrl = serial_port_in(port, SCSCR);
|
||||
serial_port_out(port, SCSCR, ctrl & ~SCSCR_TIE);
|
||||
if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) {
|
||||
/* Switch irq from DMA to SCIF */
|
||||
dmaengine_pause(s->chan_tx_saved);
|
||||
enable_irq(s->irqs[SCIx_TXI_IRQ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1266,9 +1298,13 @@ static void sci_dma_rx_reenable_irq(struct sci_port *s)
|
||||
|
||||
/* Direct new serial port interrupts back to CPU */
|
||||
scr = serial_port_in(port, SCSCR);
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||
scr &= ~SCSCR_RDRQE;
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB ||
|
||||
s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) {
|
||||
enable_irq(s->irqs[SCIx_RXI_IRQ]);
|
||||
if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE)
|
||||
scif_set_rtrg(port, s->rx_trigger);
|
||||
else
|
||||
scr &= ~SCSCR_RDRQE;
|
||||
}
|
||||
serial_port_out(port, SCSCR, scr | SCSCR_RIE);
|
||||
}
|
||||
@ -1505,7 +1541,8 @@ static enum hrtimer_restart sci_dma_rx_timer_fn(struct hrtimer *t)
|
||||
tty_flip_buffer_push(&port->state->port);
|
||||
}
|
||||
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB ||
|
||||
s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE)
|
||||
sci_dma_rx_submit(s, true);
|
||||
|
||||
sci_dma_rx_reenable_irq(s);
|
||||
@ -1531,15 +1568,12 @@ static struct dma_chan *sci_request_dma_chan(struct uart_port *port,
|
||||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.direction = dir;
|
||||
if (dir == DMA_MEM_TO_DEV) {
|
||||
cfg.dst_addr = port->mapbase +
|
||||
(sci_getreg(port, SCxTDR)->offset << port->regshift);
|
||||
cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||
} else {
|
||||
cfg.src_addr = port->mapbase +
|
||||
(sci_getreg(port, SCxRDR)->offset << port->regshift);
|
||||
cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||
}
|
||||
cfg.dst_addr = port->mapbase +
|
||||
(sci_getreg(port, SCxTDR)->offset << port->regshift);
|
||||
cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||
cfg.src_addr = port->mapbase +
|
||||
(sci_getreg(port, SCxRDR)->offset << port->regshift);
|
||||
cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||
|
||||
ret = dmaengine_slave_config(chan, &cfg);
|
||||
if (ret) {
|
||||
@ -1574,7 +1608,7 @@ static void sci_request_dma(struct uart_port *port)
|
||||
* Don't request a dma channel if no channel was specified
|
||||
* in the device tree.
|
||||
*/
|
||||
if (!of_find_property(port->dev->of_node, "dmas", NULL))
|
||||
if (!of_property_present(port->dev->of_node, "dmas"))
|
||||
return;
|
||||
|
||||
chan = sci_request_dma_chan(port, DMA_MEM_TO_DEV);
|
||||
@ -1632,7 +1666,8 @@ static void sci_request_dma(struct uart_port *port)
|
||||
|
||||
s->chan_rx_saved = s->chan_rx = chan;
|
||||
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB ||
|
||||
s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE)
|
||||
sci_dma_rx_submit(s, false);
|
||||
}
|
||||
}
|
||||
@ -1685,9 +1720,15 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
|
||||
u16 ssr = serial_port_in(port, SCxSR);
|
||||
|
||||
/* Disable future Rx interrupts */
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||
disable_irq_nosync(irq);
|
||||
scr |= SCSCR_RDRQE;
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB ||
|
||||
s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) {
|
||||
disable_irq_nosync(s->irqs[SCIx_RXI_IRQ]);
|
||||
if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) {
|
||||
scif_set_rtrg(port, 1);
|
||||
scr |= SCSCR_RIE;
|
||||
} else {
|
||||
scr |= SCSCR_RDRQE;
|
||||
}
|
||||
} else {
|
||||
if (sci_dma_rx_submit(s, false) < 0)
|
||||
goto handle_pio;
|
||||
@ -1737,6 +1778,24 @@ static irqreturn_t sci_tx_interrupt(int irq, void *ptr)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t sci_tx_end_interrupt(int irq, void *ptr)
|
||||
{
|
||||
struct uart_port *port = ptr;
|
||||
unsigned long flags;
|
||||
unsigned short ctrl;
|
||||
|
||||
if (port->type != PORT_SCI)
|
||||
return sci_tx_interrupt(irq, ptr);
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
ctrl = serial_port_in(port, SCSCR);
|
||||
ctrl &= ~(SCSCR_TE | SCSCR_TEIE);
|
||||
serial_port_out(port, SCSCR, ctrl);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t sci_br_interrupt(int irq, void *ptr)
|
||||
{
|
||||
struct uart_port *port = ptr;
|
||||
@ -1873,7 +1932,7 @@ static const struct sci_irq_desc {
|
||||
|
||||
[SCIx_TEI_IRQ] = {
|
||||
.desc = "tx end",
|
||||
.handler = sci_tx_interrupt,
|
||||
.handler = sci_tx_end_interrupt,
|
||||
},
|
||||
|
||||
/*
|
||||
@ -2580,8 +2639,14 @@ done:
|
||||
sci_set_mctrl(port, port->mctrl);
|
||||
}
|
||||
|
||||
scr_val |= SCSCR_RE | SCSCR_TE |
|
||||
(s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0));
|
||||
/*
|
||||
* For SCI, TE (transmit enable) must be set after setting TIE
|
||||
* (transmit interrupt enable) or in the same instruction to
|
||||
* start the transmitting process. So skip setting TE here for SCI.
|
||||
*/
|
||||
if (port->type != PORT_SCI)
|
||||
scr_val |= SCSCR_TE;
|
||||
scr_val |= SCSCR_RE | (s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0));
|
||||
serial_port_out(port, SCSCR, scr_val | s->hscif_tot);
|
||||
if ((srr + 1 == 5) &&
|
||||
(port->type == PORT_SCIFA || port->type == PORT_SCIFB)) {
|
||||
@ -3149,7 +3214,7 @@ static int sci_remove(struct platform_device *dev)
|
||||
#define SCI_OF_TYPE(data) ((unsigned long)(data) >> 16)
|
||||
#define SCI_OF_REGTYPE(data) ((unsigned long)(data) & 0xffff)
|
||||
|
||||
static const struct of_device_id of_sci_match[] = {
|
||||
static const struct of_device_id of_sci_match[] __maybe_unused = {
|
||||
/* SoC-specific types */
|
||||
{
|
||||
.compatible = "renesas,scif-r7s72100",
|
||||
|
@ -59,6 +59,9 @@ enum {
|
||||
#define SCSMR_SRC_19 0x0600 /* Sampling rate 1/19 */
|
||||
#define SCSMR_SRC_27 0x0700 /* Sampling rate 1/27 */
|
||||
|
||||
/* Serial Control Register, SCI only bits */
|
||||
#define SCSCR_TEIE BIT(2) /* Transmit End Interrupt Enable */
|
||||
|
||||
/* Serial Control Register, SCIFA/SCIFB only bits */
|
||||
#define SCSCR_TDRQE BIT(15) /* Tx Data Transfer Request Enable */
|
||||
#define SCSCR_RDRQE BIT(14) /* Rx Data Transfer Request Enable */
|
||||
|
@ -1250,7 +1250,7 @@ static struct platform_driver sprd_platform_driver = {
|
||||
.remove = sprd_remove,
|
||||
.driver = {
|
||||
.name = "sprd_serial",
|
||||
.of_match_table = of_match_ptr(serial_ids),
|
||||
.of_match_table = serial_ids,
|
||||
.pm = &sprd_pm_ops,
|
||||
},
|
||||
};
|
||||
|
@ -693,8 +693,9 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
|
||||
int ret;
|
||||
|
||||
if (!stm32_port->hw_flow_control &&
|
||||
port->rs485.flags & SER_RS485_ENABLED) {
|
||||
stm32_port->txdone = false;
|
||||
port->rs485.flags & SER_RS485_ENABLED &&
|
||||
(port->x_char ||
|
||||
!(uart_circ_empty(xmit) || uart_tx_stopped(port)))) {
|
||||
stm32_usart_tc_interrupt_disable(port);
|
||||
stm32_usart_rs485_rts_enable(port);
|
||||
}
|
||||
@ -743,7 +744,6 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
|
||||
stm32_usart_tx_interrupt_disable(port);
|
||||
if (!stm32_port->hw_flow_control &&
|
||||
port->rs485.flags & SER_RS485_ENABLED) {
|
||||
stm32_port->txdone = true;
|
||||
stm32_usart_tc_interrupt_enable(port);
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +203,6 @@ struct stm32_port {
|
||||
bool hw_flow_control;
|
||||
bool swap; /* swap RX & TX pins */
|
||||
bool fifoen;
|
||||
bool txdone;
|
||||
int rxftcfg; /* RX FIFO threshold CFG */
|
||||
int txftcfg; /* TX FIFO threshold CFG */
|
||||
bool wakeup_src;
|
||||
|
@ -1403,7 +1403,7 @@ static int zs_probe(struct platform_device *op)
|
||||
int keyboard_mouse = 0;
|
||||
int err;
|
||||
|
||||
if (of_find_property(op->dev.of_node, "keyboard", NULL))
|
||||
if (of_property_present(op->dev.of_node, "keyboard"))
|
||||
keyboard_mouse = 1;
|
||||
|
||||
/* uarts must come before keyboards/mice */
|
||||
@ -1553,7 +1553,7 @@ static int __init sunzilog_init(void)
|
||||
|
||||
for_each_node_by_name(dp, "zs") {
|
||||
num_sunzilog++;
|
||||
if (of_find_property(dp, "keyboard", NULL))
|
||||
if (of_property_present(dp, "keyboard"))
|
||||
num_keybms++;
|
||||
}
|
||||
|
||||
|
@ -366,15 +366,14 @@ static int qe_uart_tx_pump(struct uart_qe_port *qe_port)
|
||||
/* Pick next descriptor and fill from buffer */
|
||||
bdp = qe_port->tx_cur;
|
||||
|
||||
while (!(ioread16be(&bdp->status) & BD_SC_READY) &&
|
||||
(xmit->tail != xmit->head)) {
|
||||
while (!(ioread16be(&bdp->status) & BD_SC_READY) && !uart_circ_empty(xmit)) {
|
||||
count = 0;
|
||||
p = qe2cpu_addr(be32_to_cpu(bdp->buf), qe_port);
|
||||
while (count < qe_port->tx_fifosize) {
|
||||
*p++ = xmit->buf[xmit->tail];
|
||||
uart_xmit_advance(port, 1);
|
||||
count++;
|
||||
if (xmit->head == xmit->tail)
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1179,7 +1178,7 @@ static int soft_uart_init(struct platform_device *ofdev)
|
||||
struct qe_firmware_info *qe_fw_info;
|
||||
int ret;
|
||||
|
||||
if (of_find_property(np, "soft-uart", NULL)) {
|
||||
if (of_property_read_bool(np, "soft-uart")) {
|
||||
dev_dbg(&ofdev->dev, "using Soft-UART mode\n");
|
||||
soft_uart = 1;
|
||||
} else {
|
||||
|
@ -287,7 +287,6 @@ struct slgt_info {
|
||||
unsigned char *tx_buf;
|
||||
int tx_count;
|
||||
|
||||
char *flag_buf;
|
||||
bool drop_rts_on_tx_done;
|
||||
struct _input_signal_events input_signal_events;
|
||||
|
||||
@ -730,7 +729,7 @@ static void set_termios(struct tty_struct *tty,
|
||||
|
||||
/* Handle turning off CRTSCTS */
|
||||
if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) {
|
||||
tty->hw_stopped = 0;
|
||||
tty->hw_stopped = false;
|
||||
tx_release(tty);
|
||||
}
|
||||
}
|
||||
@ -1953,13 +1952,13 @@ static void cts_change(struct slgt_info *info, unsigned short status)
|
||||
if (info->port.tty) {
|
||||
if (info->port.tty->hw_stopped) {
|
||||
if (info->signals & SerialSignal_CTS) {
|
||||
info->port.tty->hw_stopped = 0;
|
||||
info->port.tty->hw_stopped = false;
|
||||
info->pending_bh |= BH_TRANSMIT;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!(info->signals & SerialSignal_CTS))
|
||||
info->port.tty->hw_stopped = 1;
|
||||
info->port.tty->hw_stopped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3244,13 +3243,7 @@ static int alloc_tmp_rbuf(struct slgt_info *info)
|
||||
info->tmp_rbuf = kmalloc(info->max_frame_size + 5, GFP_KERNEL);
|
||||
if (info->tmp_rbuf == NULL)
|
||||
return -ENOMEM;
|
||||
/* unused flag buffer to satisfy receive_buf calling interface */
|
||||
info->flag_buf = kzalloc(info->max_frame_size + 5, GFP_KERNEL);
|
||||
if (!info->flag_buf) {
|
||||
kfree(info->tmp_rbuf);
|
||||
info->tmp_rbuf = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3258,8 +3251,6 @@ static void free_tmp_rbuf(struct slgt_info *info)
|
||||
{
|
||||
kfree(info->tmp_rbuf);
|
||||
info->tmp_rbuf = NULL;
|
||||
kfree(info->flag_buf);
|
||||
info->flag_buf = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4657,7 +4648,8 @@ check_again:
|
||||
hdlcdev_rx(info,info->tmp_rbuf, framesize);
|
||||
else
|
||||
#endif
|
||||
ldisc_receive_buf(tty, info->tmp_rbuf, info->flag_buf, framesize);
|
||||
ldisc_receive_buf(tty, info->tmp_rbuf, NULL,
|
||||
framesize);
|
||||
}
|
||||
}
|
||||
free_rbufs(info, start, end);
|
||||
@ -4691,8 +4683,8 @@ static bool rx_get_buf(struct slgt_info *info)
|
||||
DBGDATA(info, info->rbufs[i].buf, count, "rx");
|
||||
DBGINFO(("rx_get_buf size=%d\n", count));
|
||||
if (count)
|
||||
ldisc_receive_buf(info->port.tty, info->rbufs[i].buf,
|
||||
info->flag_buf, count);
|
||||
ldisc_receive_buf(info->port.tty, info->rbufs[i].buf, NULL,
|
||||
count);
|
||||
free_rbufs(info, i, i);
|
||||
return true;
|
||||
}
|
||||
|
@ -62,6 +62,8 @@ int __tty_check_change(struct tty_struct *tty, int sig);
|
||||
int tty_check_change(struct tty_struct *tty);
|
||||
void __stop_tty(struct tty_struct *tty);
|
||||
void __start_tty(struct tty_struct *tty);
|
||||
void tty_write_unlock(struct tty_struct *tty);
|
||||
int tty_write_lock(struct tty_struct *tty, int ndelay);
|
||||
void tty_vhangup_session(struct tty_struct *tty);
|
||||
void tty_open_proc_set_tty(struct file *filp, struct tty_struct *tty);
|
||||
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)
|
||||
return i;
|
||||
}
|
||||
|
||||
static void tty_write_unlock(struct tty_struct *tty)
|
||||
void tty_write_unlock(struct tty_struct *tty)
|
||||
{
|
||||
mutex_unlock(&tty->atomic_write_lock);
|
||||
wake_up_interruptible_poll(&tty->write_wait, EPOLLOUT);
|
||||
}
|
||||
|
||||
static int tty_write_lock(struct tty_struct *tty, int ndelay)
|
||||
int tty_write_lock(struct tty_struct *tty, int ndelay)
|
||||
{
|
||||
if (!mutex_trylock(&tty->atomic_write_lock)) {
|
||||
if (ndelay)
|
||||
@ -3614,31 +3614,13 @@ static struct ctl_table tty_table[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct ctl_table tty_dir_table[] = {
|
||||
{
|
||||
.procname = "tty",
|
||||
.mode = 0555,
|
||||
.child = tty_table,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct ctl_table tty_root_table[] = {
|
||||
{
|
||||
.procname = "dev",
|
||||
.mode = 0555,
|
||||
.child = tty_dir_table,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
/*
|
||||
* Ok, now we can initialize the rest of the tty devices and can count
|
||||
* on memory allocations, interrupts etc..
|
||||
*/
|
||||
int __init tty_init(void)
|
||||
{
|
||||
register_sysctl_table(tty_root_table);
|
||||
register_sysctl_init("dev/tty", tty_table);
|
||||
cdev_init(&tty_cdev, &tty_fops);
|
||||
if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
|
||||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
|
||||
|
@ -7,6 +7,7 @@
|
||||
* discipline handling modules (like SLIP).
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/termios.h>
|
||||
#include <linux/errno.h>
|
||||
@ -40,10 +41,10 @@
|
||||
/*
|
||||
* Internal flag options for termios setting behavior
|
||||
*/
|
||||
#define TERMIOS_FLUSH 1
|
||||
#define TERMIOS_WAIT 2
|
||||
#define TERMIOS_TERMIO 4
|
||||
#define TERMIOS_OLD 8
|
||||
#define TERMIOS_FLUSH BIT(0)
|
||||
#define TERMIOS_WAIT BIT(1)
|
||||
#define TERMIOS_TERMIO BIT(2)
|
||||
#define TERMIOS_OLD BIT(3)
|
||||
|
||||
|
||||
/**
|
||||
@ -500,22 +501,43 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
|
||||
tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
|
||||
tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
|
||||
|
||||
ld = tty_ldisc_ref(tty);
|
||||
if (opt & (TERMIOS_FLUSH|TERMIOS_WAIT)) {
|
||||
retry_write_wait:
|
||||
retval = wait_event_interruptible(tty->write_wait, !tty_chars_in_buffer(tty));
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
if (ld != NULL) {
|
||||
if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
|
||||
ld->ops->flush_buffer(tty);
|
||||
tty_ldisc_deref(ld);
|
||||
if (tty_write_lock(tty, 0) < 0)
|
||||
goto retry_write_wait;
|
||||
|
||||
/* Racing writer? */
|
||||
if (tty_chars_in_buffer(tty)) {
|
||||
tty_write_unlock(tty);
|
||||
goto retry_write_wait;
|
||||
}
|
||||
|
||||
ld = tty_ldisc_ref(tty);
|
||||
if (ld != NULL) {
|
||||
if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
|
||||
ld->ops->flush_buffer(tty);
|
||||
tty_ldisc_deref(ld);
|
||||
}
|
||||
|
||||
if ((opt & TERMIOS_WAIT) && tty->ops->wait_until_sent) {
|
||||
tty->ops->wait_until_sent(tty, 0);
|
||||
if (signal_pending(current)) {
|
||||
tty_write_unlock(tty);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
}
|
||||
|
||||
tty_set_termios(tty, &tmp_termios);
|
||||
|
||||
tty_write_unlock(tty);
|
||||
} else {
|
||||
tty_set_termios(tty, &tmp_termios);
|
||||
}
|
||||
|
||||
if (opt & TERMIOS_WAIT) {
|
||||
tty_wait_until_sent(tty, 0);
|
||||
if (signal_pending(current))
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
|
||||
tty_set_termios(tty, &tmp_termios);
|
||||
|
||||
/* FIXME: Arguably if tmp_termios == tty->termios AND the
|
||||
actual requested termios was not tmp_termios then we may
|
||||
want to return an error as no user requested change has
|
||||
|
@ -58,7 +58,6 @@ static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
|
||||
int tty_register_ldisc(struct tty_ldisc_ops *new_ldisc)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
if (new_ldisc->num < N_TTY || new_ldisc->num >= NR_LDISCS)
|
||||
return -EINVAL;
|
||||
@ -67,7 +66,7 @@ int tty_register_ldisc(struct tty_ldisc_ops *new_ldisc)
|
||||
tty_ldiscs[new_ldisc->num] = new_ldisc;
|
||||
raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(tty_register_ldisc);
|
||||
|
||||
|
@ -135,10 +135,9 @@ const struct consw *conswitchp;
|
||||
#define DEFAULT_CURSOR_BLINK_MS 200
|
||||
|
||||
struct vc vc_cons [MAX_NR_CONSOLES];
|
||||
EXPORT_SYMBOL(vc_cons);
|
||||
|
||||
#ifndef VT_SINGLE_DRIVER
|
||||
static const struct consw *con_driver_map[MAX_NR_CONSOLES];
|
||||
#endif
|
||||
|
||||
static int con_open(struct tty_struct *, struct file *);
|
||||
static void vc_init(struct vc_data *vc, unsigned int rows,
|
||||
@ -162,6 +161,7 @@ int default_utf8 = true;
|
||||
module_param(default_utf8, int, S_IRUGO | S_IWUSR);
|
||||
int global_cursor_default = -1;
|
||||
module_param(global_cursor_default, int, S_IRUGO | S_IWUSR);
|
||||
EXPORT_SYMBOL(global_cursor_default);
|
||||
|
||||
static int cur_default = CUR_UNDERLINE;
|
||||
module_param(cur_default, int, S_IRUGO | S_IWUSR);
|
||||
@ -174,6 +174,7 @@ static int ignore_poke;
|
||||
|
||||
int do_poke_blanked_console;
|
||||
int console_blanked;
|
||||
EXPORT_SYMBOL(console_blanked);
|
||||
|
||||
static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
|
||||
static int vesa_off_interval;
|
||||
@ -190,8 +191,10 @@ static DECLARE_WORK(con_driver_unregister_work, con_driver_unregister_callback);
|
||||
* saved_* variants are for save/restore around kernel debugger enter/leave
|
||||
*/
|
||||
int fg_console;
|
||||
EXPORT_SYMBOL(fg_console);
|
||||
int last_console;
|
||||
int want_console = -1;
|
||||
|
||||
static int saved_fg_console;
|
||||
static int saved_last_console;
|
||||
static int saved_want_console;
|
||||
@ -223,6 +226,7 @@ static int scrollback_delta;
|
||||
* the console on our behalf.
|
||||
*/
|
||||
int (*console_blank_hook)(int);
|
||||
EXPORT_SYMBOL(console_blank_hook);
|
||||
|
||||
static DEFINE_TIMER(console_timer, blank_screen_t);
|
||||
static int blank_state;
|
||||
@ -639,6 +643,7 @@ void update_region(struct vc_data *vc, unsigned long start, int count)
|
||||
set_cursor(vc);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(update_region);
|
||||
|
||||
/* Structure of attributes is hardware-dependent */
|
||||
|
||||
@ -984,6 +989,7 @@ void redraw_screen(struct vc_data *vc, int is_switch)
|
||||
notify_update(vc);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(redraw_screen);
|
||||
|
||||
/*
|
||||
* Allocation, freeing and resizing of VTs.
|
||||
@ -1000,10 +1006,10 @@ static void visual_init(struct vc_data *vc, int num, int init)
|
||||
if (vc->vc_sw)
|
||||
module_put(vc->vc_sw->owner);
|
||||
vc->vc_sw = conswitchp;
|
||||
#ifndef VT_SINGLE_DRIVER
|
||||
|
||||
if (con_driver_map[num])
|
||||
vc->vc_sw = con_driver_map[num];
|
||||
#endif
|
||||
|
||||
__module_get(vc->vc_sw->owner);
|
||||
vc->vc_num = num;
|
||||
vc->vc_display_fg = &master_display_fg;
|
||||
@ -1305,6 +1311,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows)
|
||||
{
|
||||
return vc_do_resize(vc->port.tty, vc, cols, rows);
|
||||
}
|
||||
EXPORT_SYMBOL(vc_resize);
|
||||
|
||||
/**
|
||||
* vt_resize - resize a VT
|
||||
@ -1368,6 +1375,7 @@ enum { EPecma = 0, EPdec, EPeq, EPgt, EPlt};
|
||||
|
||||
const unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
|
||||
8,12,10,14, 9,13,11,15 };
|
||||
EXPORT_SYMBOL(color_table);
|
||||
|
||||
/* the default colour table, for VGA+ colour systems */
|
||||
unsigned char default_red[] = {
|
||||
@ -1375,18 +1383,21 @@ unsigned char default_red[] = {
|
||||
0x55, 0xff, 0x55, 0xff, 0x55, 0xff, 0x55, 0xff
|
||||
};
|
||||
module_param_array(default_red, byte, NULL, S_IRUGO | S_IWUSR);
|
||||
EXPORT_SYMBOL(default_red);
|
||||
|
||||
unsigned char default_grn[] = {
|
||||
0x00, 0x00, 0xaa, 0x55, 0x00, 0x00, 0xaa, 0xaa,
|
||||
0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xff, 0xff
|
||||
};
|
||||
module_param_array(default_grn, byte, NULL, S_IRUGO | S_IWUSR);
|
||||
EXPORT_SYMBOL(default_grn);
|
||||
|
||||
unsigned char default_blu[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0x55, 0x55, 0x55, 0x55, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
module_param_array(default_blu, byte, NULL, S_IRUGO | S_IWUSR);
|
||||
EXPORT_SYMBOL(default_blu);
|
||||
|
||||
/*
|
||||
* gotoxy() must verify all boundaries, because the arguments
|
||||
@ -3143,93 +3154,84 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
|
||||
return -EFAULT;
|
||||
ret = 0;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case TIOCL_SETSEL:
|
||||
ret = set_selection_user((struct tiocl_selection
|
||||
__user *)(p+1), tty);
|
||||
break;
|
||||
case TIOCL_PASTESEL:
|
||||
ret = paste_selection(tty);
|
||||
break;
|
||||
case TIOCL_UNBLANKSCREEN:
|
||||
console_lock();
|
||||
unblank_screen();
|
||||
console_unlock();
|
||||
break;
|
||||
case TIOCL_SELLOADLUT:
|
||||
console_lock();
|
||||
ret = sel_loadlut(p);
|
||||
console_unlock();
|
||||
break;
|
||||
case TIOCL_GETSHIFTSTATE:
|
||||
switch (type) {
|
||||
case TIOCL_SETSEL:
|
||||
return set_selection_user((struct tiocl_selection
|
||||
__user *)(p+1), tty);
|
||||
case TIOCL_PASTESEL:
|
||||
return paste_selection(tty);
|
||||
case TIOCL_UNBLANKSCREEN:
|
||||
console_lock();
|
||||
unblank_screen();
|
||||
console_unlock();
|
||||
break;
|
||||
case TIOCL_SELLOADLUT:
|
||||
console_lock();
|
||||
ret = sel_loadlut(p);
|
||||
console_unlock();
|
||||
break;
|
||||
case TIOCL_GETSHIFTSTATE:
|
||||
/*
|
||||
* Make it possible to react to Shift+Mousebutton. Note that
|
||||
* 'shift_state' is an undocumented kernel-internal variable;
|
||||
* programs not closely related to the kernel should not use
|
||||
* this.
|
||||
*/
|
||||
data = vt_get_shift_state();
|
||||
return put_user(data, p);
|
||||
case TIOCL_GETMOUSEREPORTING:
|
||||
console_lock(); /* May be overkill */
|
||||
data = mouse_reporting();
|
||||
console_unlock();
|
||||
return put_user(data, p);
|
||||
case TIOCL_SETVESABLANK:
|
||||
console_lock();
|
||||
ret = set_vesa_blanking(p);
|
||||
console_unlock();
|
||||
break;
|
||||
case TIOCL_GETKMSGREDIRECT:
|
||||
data = vt_get_kmsg_redirect();
|
||||
return put_user(data, p);
|
||||
case TIOCL_SETKMSGREDIRECT:
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
/*
|
||||
* Make it possible to react to Shift+Mousebutton.
|
||||
* Note that 'shift_state' is an undocumented
|
||||
* kernel-internal variable; programs not closely
|
||||
* related to the kernel should not use this.
|
||||
*/
|
||||
data = vt_get_shift_state();
|
||||
ret = put_user(data, p);
|
||||
break;
|
||||
case TIOCL_GETMOUSEREPORTING:
|
||||
console_lock(); /* May be overkill */
|
||||
data = mouse_reporting();
|
||||
console_unlock();
|
||||
ret = put_user(data, p);
|
||||
break;
|
||||
case TIOCL_SETVESABLANK:
|
||||
console_lock();
|
||||
ret = set_vesa_blanking(p);
|
||||
console_unlock();
|
||||
break;
|
||||
case TIOCL_GETKMSGREDIRECT:
|
||||
data = vt_get_kmsg_redirect();
|
||||
ret = put_user(data, p);
|
||||
break;
|
||||
case TIOCL_SETKMSGREDIRECT:
|
||||
if (!capable(CAP_SYS_ADMIN)) {
|
||||
ret = -EPERM;
|
||||
} else {
|
||||
if (get_user(data, p+1))
|
||||
ret = -EFAULT;
|
||||
else
|
||||
vt_kmsg_redirect(data);
|
||||
}
|
||||
break;
|
||||
case TIOCL_GETFGCONSOLE:
|
||||
/* No locking needed as this is a transiently
|
||||
correct return anyway if the caller hasn't
|
||||
disabled switching */
|
||||
ret = fg_console;
|
||||
break;
|
||||
case TIOCL_SCROLLCONSOLE:
|
||||
if (get_user(lines, (s32 __user *)(p+4))) {
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
/* Need the console lock here. Note that lots
|
||||
of other calls need fixing before the lock
|
||||
is actually useful ! */
|
||||
console_lock();
|
||||
scrollfront(vc_cons[fg_console].d, lines);
|
||||
console_unlock();
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
case TIOCL_BLANKSCREEN: /* until explicitly unblanked, not only poked */
|
||||
console_lock();
|
||||
ignore_poke = 1;
|
||||
do_blank_screen(0);
|
||||
console_unlock();
|
||||
break;
|
||||
case TIOCL_BLANKEDSCREEN:
|
||||
ret = console_blanked;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
if (get_user(data, p+1))
|
||||
return -EFAULT;
|
||||
|
||||
vt_kmsg_redirect(data);
|
||||
|
||||
break;
|
||||
case TIOCL_GETFGCONSOLE:
|
||||
/*
|
||||
* No locking needed as this is a transiently correct return
|
||||
* anyway if the caller hasn't disabled switching.
|
||||
*/
|
||||
return fg_console;
|
||||
case TIOCL_SCROLLCONSOLE:
|
||||
if (get_user(lines, (s32 __user *)(p+4)))
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* Needs the console lock here. Note that lots of other calls
|
||||
* need fixing before the lock is actually useful!
|
||||
*/
|
||||
console_lock();
|
||||
scrollfront(vc_cons[fg_console].d, lines);
|
||||
console_unlock();
|
||||
break;
|
||||
case TIOCL_BLANKSCREEN: /* until explicitly unblanked, not only poked */
|
||||
console_lock();
|
||||
ignore_poke = 1;
|
||||
do_blank_screen(0);
|
||||
console_unlock();
|
||||
break;
|
||||
case TIOCL_BLANKEDSCREEN:
|
||||
return console_blanked;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -3571,8 +3573,6 @@ int __init vty_init(const struct file_operations *console_fops)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef VT_SINGLE_DRIVER
|
||||
|
||||
static struct class *vtconsole_class;
|
||||
|
||||
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)
|
||||
do_unregister_con_driver(csw);
|
||||
console_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL(give_up_console);
|
||||
|
||||
static int __init vtconsole_class_init(void)
|
||||
{
|
||||
@ -4273,8 +4274,6 @@ static int __init vtconsole_class_init(void)
|
||||
}
|
||||
postcore_initcall(vtconsole_class_init);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Screen blanking
|
||||
*/
|
||||
@ -4792,23 +4791,3 @@ void vc_scrolldelta_helper(struct vc_data *c, int lines,
|
||||
c->vc_visible_origin = ubase + (from + from_off) % wrap;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vc_scrolldelta_helper);
|
||||
|
||||
/*
|
||||
* Visible symbols for modules
|
||||
*/
|
||||
|
||||
EXPORT_SYMBOL(color_table);
|
||||
EXPORT_SYMBOL(default_red);
|
||||
EXPORT_SYMBOL(default_grn);
|
||||
EXPORT_SYMBOL(default_blu);
|
||||
EXPORT_SYMBOL(update_region);
|
||||
EXPORT_SYMBOL(redraw_screen);
|
||||
EXPORT_SYMBOL(vc_resize);
|
||||
EXPORT_SYMBOL(fg_console);
|
||||
EXPORT_SYMBOL(console_blank_hook);
|
||||
EXPORT_SYMBOL(console_blanked);
|
||||
EXPORT_SYMBOL(vc_cons);
|
||||
EXPORT_SYMBOL(global_cursor_default);
|
||||
#ifndef VT_SINGLE_DRIVER
|
||||
EXPORT_SYMBOL(give_up_console);
|
||||
#endif
|
||||
|
@ -18,16 +18,16 @@ struct plat_serial8250_port {
|
||||
unsigned long iobase; /* io base address */
|
||||
void __iomem *membase; /* ioremap cookie or NULL */
|
||||
resource_size_t mapbase; /* resource base */
|
||||
unsigned int uartclk; /* UART clock rate */
|
||||
unsigned int irq; /* interrupt number */
|
||||
unsigned long irqflags; /* request_irq flags */
|
||||
unsigned int uartclk; /* UART clock rate */
|
||||
void *private_data;
|
||||
unsigned char regshift; /* register shift */
|
||||
unsigned char iotype; /* UPIO_* */
|
||||
unsigned char hub6;
|
||||
unsigned char has_sysrq; /* supports magic SysRq */
|
||||
upf_t flags; /* UPF_* flags */
|
||||
unsigned int type; /* If UPF_FIXED_TYPE */
|
||||
upf_t flags; /* UPF_* flags */
|
||||
unsigned int (*serial_in)(struct uart_port *, int);
|
||||
void (*serial_out)(struct uart_port *, int, int);
|
||||
void (*set_termios)(struct uart_port *,
|
||||
@ -151,26 +151,22 @@ void serial8250_unregister_port(int line);
|
||||
void serial8250_suspend_port(int line);
|
||||
void serial8250_resume_port(int line);
|
||||
|
||||
extern int early_serial_setup(struct uart_port *port);
|
||||
int early_serial_setup(struct uart_port *port);
|
||||
int early_serial8250_setup(struct earlycon_device *device, const char *options);
|
||||
|
||||
extern int early_serial8250_setup(struct earlycon_device *device,
|
||||
const char *options);
|
||||
extern void serial8250_update_uartclk(struct uart_port *port,
|
||||
unsigned int uartclk);
|
||||
extern void serial8250_do_set_termios(struct uart_port *port,
|
||||
struct ktermios *termios, const struct ktermios *old);
|
||||
extern void serial8250_do_set_ldisc(struct uart_port *port,
|
||||
struct ktermios *termios);
|
||||
extern unsigned int serial8250_do_get_mctrl(struct uart_port *port);
|
||||
extern int serial8250_do_startup(struct uart_port *port);
|
||||
extern void serial8250_do_shutdown(struct uart_port *port);
|
||||
extern void serial8250_do_pm(struct uart_port *port, unsigned int state,
|
||||
unsigned int oldstate);
|
||||
extern void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl);
|
||||
extern void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud,
|
||||
unsigned int quot,
|
||||
unsigned int quot_frac);
|
||||
extern int fsl8250_handle_irq(struct uart_port *port);
|
||||
void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk);
|
||||
void serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
const struct ktermios *old);
|
||||
void serial8250_do_set_ldisc(struct uart_port *port, struct ktermios *termios);
|
||||
unsigned int serial8250_do_get_mctrl(struct uart_port *port);
|
||||
int serial8250_do_startup(struct uart_port *port);
|
||||
void serial8250_do_shutdown(struct uart_port *port);
|
||||
void serial8250_do_pm(struct uart_port *port, unsigned int state,
|
||||
unsigned int oldstate);
|
||||
void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl);
|
||||
void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud,
|
||||
unsigned int quot, unsigned int quot_frac);
|
||||
int fsl8250_handle_irq(struct uart_port *port);
|
||||
int serial8250_handle_irq(struct uart_port *port, unsigned int iir);
|
||||
u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr);
|
||||
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,
|
||||
int serial8250_console_setup(struct uart_port *port, char *options, bool probe);
|
||||
int serial8250_console_exit(struct uart_port *port);
|
||||
|
||||
extern void serial8250_set_isa_configurator(void (*v)
|
||||
(int port, struct uart_port *up,
|
||||
u32 *capabilities));
|
||||
void serial8250_set_isa_configurator(void (*v)(int port, struct uart_port *up,
|
||||
u32 *capabilities));
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_RT288X
|
||||
unsigned int au_serial_in(struct uart_port *p, int offset);
|
||||
|
@ -553,7 +553,7 @@ struct uart_port {
|
||||
#define UPSTAT_AUTOXOFF ((__force upstat_t) (1 << 4))
|
||||
#define UPSTAT_SYNC_FIFO ((__force upstat_t) (1 << 5))
|
||||
|
||||
int hw_stopped; /* sw-assisted CTS flow state */
|
||||
bool hw_stopped; /* sw-assisted CTS flow state */
|
||||
unsigned int mctrl; /* current modem ctrl settings */
|
||||
unsigned int frame_time; /* frame timing in ns */
|
||||
unsigned int type; /* port type */
|
||||
@ -812,9 +812,8 @@ extern const struct earlycon_id __earlycon_table_end[];
|
||||
|
||||
#define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn)
|
||||
|
||||
extern int of_setup_earlycon(const struct earlycon_id *match,
|
||||
unsigned long node,
|
||||
const char *options);
|
||||
int of_setup_earlycon(const struct earlycon_id *match, unsigned long node,
|
||||
const char *options);
|
||||
|
||||
#ifdef CONFIG_SERIAL_EARLYCON
|
||||
extern bool earlycon_acpi_spcr_enable __initdata;
|
||||
@ -897,11 +896,11 @@ static inline bool uart_softcts_mode(struct uart_port *uport)
|
||||
* The following are helper functions for the low level drivers.
|
||||
*/
|
||||
|
||||
extern void uart_handle_dcd_change(struct uart_port *uport, bool active);
|
||||
extern void uart_handle_cts_change(struct uart_port *uport, bool active);
|
||||
void uart_handle_dcd_change(struct uart_port *uport, bool active);
|
||||
void uart_handle_cts_change(struct uart_port *uport, bool active);
|
||||
|
||||
extern void uart_insert_char(struct uart_port *port, unsigned int status,
|
||||
unsigned int overrun, unsigned int ch, unsigned int flag);
|
||||
void uart_insert_char(struct uart_port *port, unsigned int status,
|
||||
unsigned int overrun, unsigned int ch, unsigned int flag);
|
||||
|
||||
void uart_xchar_out(struct uart_port *uport, int offset);
|
||||
|
||||
|
@ -227,7 +227,7 @@ struct tty_struct {
|
||||
unsigned long unused[0];
|
||||
} __aligned(sizeof(unsigned long)) ctrl;
|
||||
|
||||
int hw_stopped;
|
||||
bool hw_stopped;
|
||||
unsigned int receive_room;
|
||||
int flow_change;
|
||||
|
||||
|
@ -43,10 +43,25 @@ struct gsm_config_ext {
|
||||
__u32 keep_alive; /* Control channel keep-alive in 1/100th of a
|
||||
* second (0 to disable)
|
||||
*/
|
||||
__u32 reserved[7]; /* For future use, must be initialized to zero */
|
||||
__u32 wait_config; /* Wait for DLCI config before opening virtual link? */
|
||||
__u32 reserved[6]; /* For future use, must be initialized to zero */
|
||||
};
|
||||
|
||||
#define GSMIOC_GETCONF_EXT _IOR('G', 5, struct gsm_config_ext)
|
||||
#define GSMIOC_SETCONF_EXT _IOW('G', 6, struct gsm_config_ext)
|
||||
|
||||
/* Set channel accordingly before calling GSMIOC_GETCONF_DLCI. */
|
||||
struct gsm_dlci_config {
|
||||
__u32 channel; /* DLCI (0 for the associated DLCI) */
|
||||
__u32 adaption; /* Convergence layer type */
|
||||
__u32 mtu; /* Maximum transfer unit */
|
||||
__u32 priority; /* Priority (0 for default value) */
|
||||
__u32 i; /* Frame type (1 = UIH, 2 = UI) */
|
||||
__u32 k; /* Window size (0 for default value) */
|
||||
__u32 reserved[8]; /* For future use, must be initialized to zero */
|
||||
};
|
||||
|
||||
#define GSMIOC_GETCONF_DLCI _IOWR('G', 7, struct gsm_dlci_config)
|
||||
#define GSMIOC_SETCONF_DLCI _IOW('G', 8, struct gsm_dlci_config)
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user