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:
Linus Torvalds 2023-04-27 11:46:26 -07:00
commit b39667abcd
57 changed files with 951 additions and 478 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
};

View File

@ -65,6 +65,9 @@ properties:
- const: rx
- const: tx
power-domains:
maxItems: 1
required:
- compatible
- reg

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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>;

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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.

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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:

View File

@ -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;

View File

@ -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)

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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)

View File

@ -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

View File

@ -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
};

View File

@ -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);

View File

@ -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);

View File

@ -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];

View File

@ -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 = {

View File

@ -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 */ },
};

View File

@ -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)) {

View File

@ -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,
};

View File

@ -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>

View File

@ -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);
}
}

View File

@ -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",

View File

@ -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 */

View File

@ -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,
},
};

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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++;
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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