mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-01 14:44:12 +00:00
TTY/Serial fixes for 4.17-rc3
Here are some tty and serial driver fixes for reported issues for 4.17-rc3. Nothing major, but a number of small things: - device tree fixes/updates for serial ports - earlycon fixes - n_gsm fixes - tty core change reverted to help resolve syszkaller reports - other serial driver small fixes All of these have been in linux-next with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCWuM0Vg8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+yksXgCgqT2E9Ah5O/uZp3yGAjRILKjX294AoI46+t3W Xy8WA1Fw1NCMBvfvCVIv =gBd0 -----END PGP SIGNATURE----- Merge tag 'tty-4.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty Pull tty/serial fixes from Greg KH: "Here are some tty and serial driver fixes for reported issues for 4.17-rc3. Nothing major, but a number of small things: - device tree fixes/updates for serial ports - earlycon fixes - n_gsm fixes - tty core change reverted to help resolve syszkaller reports - other serial driver small fixes All of these have been in linux-next with no reported issues" * tag 'tty-4.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: tty: Use __GFP_NOFAIL for tty_ldisc_get() tty: serial: xuartps: Setup early console when uartclk is also passed tty: Don't call panic() at tty_ldisc_init() tty: Avoid possible error pointer dereference at tty_ldisc_restore(). dt-bindings: mvebu-uart: DT fix s/interrupts-names/interrupt-names/ tty: serial: qcom_geni_serial: Use signed variable to get IRQ earlycon: Use a pointer table to fix __earlycon_table stride serial: sh-sci: Document r8a77470 bindings dt-bindings: meson-uart: DT fix s/clocks-names/clock-names/ serial: imx: fix cached UCR2 read on software reset serial: imx: warn user when using unsupported configuration serial: mvebu-uart: Fix local flags handling on termios update tty: n_gsm: Fix DLCI handling for ADM mode if debug & 2 is not set tty: n_gsm: Fix long delays with control frame timeouts in ADM mode
This commit is contained in:
commit
b52c85a7b7
15 changed files with 93 additions and 40 deletions
|
@ -21,7 +21,7 @@ Required properties:
|
||||||
- interrupts : identifier to the device interrupt
|
- interrupts : identifier to the device interrupt
|
||||||
- clocks : a list of phandle + clock-specifier pairs, one for each
|
- clocks : a list of phandle + clock-specifier pairs, one for each
|
||||||
entry in clock names.
|
entry in clock names.
|
||||||
- clocks-names :
|
- clock-names :
|
||||||
* "xtal" for external xtal clock identifier
|
* "xtal" for external xtal clock identifier
|
||||||
* "pclk" for the bus core clock, either the clk81 clock or the gate clock
|
* "pclk" for the bus core clock, either the clk81 clock or the gate clock
|
||||||
* "baud" for the source of the baudrate generator, can be either the xtal
|
* "baud" for the source of the baudrate generator, can be either the xtal
|
||||||
|
|
|
@ -24,7 +24,7 @@ Required properties:
|
||||||
- Must contain two elements for the extended variant of the IP
|
- Must contain two elements for the extended variant of the IP
|
||||||
(marvell,armada-3700-uart-ext): "uart-tx" and "uart-rx",
|
(marvell,armada-3700-uart-ext): "uart-tx" and "uart-rx",
|
||||||
respectively the UART TX interrupt and the UART RX interrupt. A
|
respectively the UART TX interrupt and the UART RX interrupt. A
|
||||||
corresponding interrupts-names property must be defined.
|
corresponding interrupt-names property must be defined.
|
||||||
- For backward compatibility reasons, a single element interrupts
|
- For backward compatibility reasons, a single element interrupts
|
||||||
property is also supported for the standard variant of the IP,
|
property is also supported for the standard variant of the IP,
|
||||||
containing only the UART sum interrupt. This form is deprecated
|
containing only the UART sum interrupt. This form is deprecated
|
||||||
|
|
|
@ -17,6 +17,8 @@ Required properties:
|
||||||
- "renesas,scifa-r8a7745" for R8A7745 (RZ/G1E) SCIFA compatible UART.
|
- "renesas,scifa-r8a7745" for R8A7745 (RZ/G1E) SCIFA compatible UART.
|
||||||
- "renesas,scifb-r8a7745" for R8A7745 (RZ/G1E) SCIFB compatible UART.
|
- "renesas,scifb-r8a7745" for R8A7745 (RZ/G1E) SCIFB compatible UART.
|
||||||
- "renesas,hscif-r8a7745" for R8A7745 (RZ/G1E) HSCIF compatible UART.
|
- "renesas,hscif-r8a7745" for R8A7745 (RZ/G1E) HSCIF compatible UART.
|
||||||
|
- "renesas,scif-r8a77470" for R8A77470 (RZ/G1C) SCIF compatible UART.
|
||||||
|
- "renesas,hscif-r8a77470" for R8A77470 (RZ/G1C) HSCIF compatible UART.
|
||||||
- "renesas,scif-r8a7778" for R8A7778 (R-Car M1) SCIF compatible UART.
|
- "renesas,scif-r8a7778" for R8A7778 (R-Car M1) SCIF compatible UART.
|
||||||
- "renesas,scif-r8a7779" for R8A7779 (R-Car H1) SCIF compatible UART.
|
- "renesas,scif-r8a7779" for R8A7779 (R-Car H1) SCIF compatible UART.
|
||||||
- "renesas,scif-r8a7790" for R8A7790 (R-Car H2) SCIF compatible UART.
|
- "renesas,scif-r8a7790" for R8A7790 (R-Car H2) SCIF compatible UART.
|
||||||
|
|
|
@ -942,7 +942,7 @@ int __init early_init_dt_scan_chosen_stdout(void)
|
||||||
int offset;
|
int offset;
|
||||||
const char *p, *q, *options = NULL;
|
const char *p, *q, *options = NULL;
|
||||||
int l;
|
int l;
|
||||||
const struct earlycon_id *match;
|
const struct earlycon_id **p_match;
|
||||||
const void *fdt = initial_boot_params;
|
const void *fdt = initial_boot_params;
|
||||||
|
|
||||||
offset = fdt_path_offset(fdt, "/chosen");
|
offset = fdt_path_offset(fdt, "/chosen");
|
||||||
|
@ -969,7 +969,10 @@ int __init early_init_dt_scan_chosen_stdout(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (match = __earlycon_table; match < __earlycon_table_end; match++) {
|
for (p_match = __earlycon_table; p_match < __earlycon_table_end;
|
||||||
|
p_match++) {
|
||||||
|
const struct earlycon_id *match = *p_match;
|
||||||
|
|
||||||
if (!match->compatible[0])
|
if (!match->compatible[0])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -121,6 +121,9 @@ struct gsm_dlci {
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
|
|
||||||
/* Link layer */
|
/* Link layer */
|
||||||
|
int mode;
|
||||||
|
#define DLCI_MODE_ABM 0 /* Normal Asynchronous Balanced Mode */
|
||||||
|
#define DLCI_MODE_ADM 1 /* Asynchronous Disconnected Mode */
|
||||||
spinlock_t lock; /* Protects the internal state */
|
spinlock_t lock; /* Protects the internal state */
|
||||||
struct timer_list t1; /* Retransmit timer for SABM and UA */
|
struct timer_list t1; /* Retransmit timer for SABM and UA */
|
||||||
int retries;
|
int retries;
|
||||||
|
@ -1364,7 +1367,13 @@ static struct gsm_control *gsm_control_send(struct gsm_mux *gsm,
|
||||||
ctrl->data = data;
|
ctrl->data = data;
|
||||||
ctrl->len = clen;
|
ctrl->len = clen;
|
||||||
gsm->pending_cmd = ctrl;
|
gsm->pending_cmd = ctrl;
|
||||||
gsm->cretries = gsm->n2;
|
|
||||||
|
/* If DLCI0 is in ADM mode skip retries, it won't respond */
|
||||||
|
if (gsm->dlci[0]->mode == DLCI_MODE_ADM)
|
||||||
|
gsm->cretries = 1;
|
||||||
|
else
|
||||||
|
gsm->cretries = gsm->n2;
|
||||||
|
|
||||||
mod_timer(&gsm->t2_timer, jiffies + gsm->t2 * HZ / 100);
|
mod_timer(&gsm->t2_timer, jiffies + gsm->t2 * HZ / 100);
|
||||||
gsm_control_transmit(gsm, ctrl);
|
gsm_control_transmit(gsm, ctrl);
|
||||||
spin_unlock_irqrestore(&gsm->control_lock, flags);
|
spin_unlock_irqrestore(&gsm->control_lock, flags);
|
||||||
|
@ -1472,6 +1481,7 @@ static void gsm_dlci_t1(struct timer_list *t)
|
||||||
if (debug & 8)
|
if (debug & 8)
|
||||||
pr_info("DLCI %d opening in ADM mode.\n",
|
pr_info("DLCI %d opening in ADM mode.\n",
|
||||||
dlci->addr);
|
dlci->addr);
|
||||||
|
dlci->mode = DLCI_MODE_ADM;
|
||||||
gsm_dlci_open(dlci);
|
gsm_dlci_open(dlci);
|
||||||
} else {
|
} else {
|
||||||
gsm_dlci_close(dlci);
|
gsm_dlci_close(dlci);
|
||||||
|
@ -2861,11 +2871,22 @@ static int gsmtty_modem_update(struct gsm_dlci *dlci, u8 brk)
|
||||||
static int gsm_carrier_raised(struct tty_port *port)
|
static int gsm_carrier_raised(struct tty_port *port)
|
||||||
{
|
{
|
||||||
struct gsm_dlci *dlci = container_of(port, struct gsm_dlci, port);
|
struct gsm_dlci *dlci = container_of(port, struct gsm_dlci, port);
|
||||||
|
struct gsm_mux *gsm = dlci->gsm;
|
||||||
|
|
||||||
/* Not yet open so no carrier info */
|
/* Not yet open so no carrier info */
|
||||||
if (dlci->state != DLCI_OPEN)
|
if (dlci->state != DLCI_OPEN)
|
||||||
return 0;
|
return 0;
|
||||||
if (debug & 2)
|
if (debug & 2)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Basic mode with control channel in ADM mode may not respond
|
||||||
|
* to CMD_MSC at all and modem_rx is empty.
|
||||||
|
*/
|
||||||
|
if (gsm->encoding == 0 && gsm->dlci[0]->mode == DLCI_MODE_ADM &&
|
||||||
|
!dlci->modem_rx)
|
||||||
|
return 1;
|
||||||
|
|
||||||
return dlci->modem_rx & TIOCM_CD;
|
return dlci->modem_rx & TIOCM_CD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -169,7 +169,7 @@ static int __init register_earlycon(char *buf, const struct earlycon_id *match)
|
||||||
*/
|
*/
|
||||||
int __init setup_earlycon(char *buf)
|
int __init setup_earlycon(char *buf)
|
||||||
{
|
{
|
||||||
const struct earlycon_id *match;
|
const struct earlycon_id **p_match;
|
||||||
|
|
||||||
if (!buf || !buf[0])
|
if (!buf || !buf[0])
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -177,7 +177,9 @@ int __init setup_earlycon(char *buf)
|
||||||
if (early_con.flags & CON_ENABLED)
|
if (early_con.flags & CON_ENABLED)
|
||||||
return -EALREADY;
|
return -EALREADY;
|
||||||
|
|
||||||
for (match = __earlycon_table; match < __earlycon_table_end; match++) {
|
for (p_match = __earlycon_table; p_match < __earlycon_table_end;
|
||||||
|
p_match++) {
|
||||||
|
const struct earlycon_id *match = *p_match;
|
||||||
size_t len = strlen(match->name);
|
size_t len = strlen(match->name);
|
||||||
|
|
||||||
if (strncmp(buf, match->name, len))
|
if (strncmp(buf, match->name, len))
|
||||||
|
|
|
@ -316,7 +316,7 @@ static u32 imx_uart_readl(struct imx_port *sport, u32 offset)
|
||||||
* differ from the value that was last written. As it only
|
* differ from the value that was last written. As it only
|
||||||
* clears after being set, reread conditionally.
|
* clears after being set, reread conditionally.
|
||||||
*/
|
*/
|
||||||
if (sport->ucr2 & UCR2_SRST)
|
if (!(sport->ucr2 & UCR2_SRST))
|
||||||
sport->ucr2 = readl(sport->port.membase + offset);
|
sport->ucr2 = readl(sport->port.membase + offset);
|
||||||
return sport->ucr2;
|
return sport->ucr2;
|
||||||
break;
|
break;
|
||||||
|
@ -1833,6 +1833,11 @@ static int imx_uart_rs485_config(struct uart_port *port,
|
||||||
rs485conf->flags &= ~SER_RS485_ENABLED;
|
rs485conf->flags &= ~SER_RS485_ENABLED;
|
||||||
|
|
||||||
if (rs485conf->flags & SER_RS485_ENABLED) {
|
if (rs485conf->flags & SER_RS485_ENABLED) {
|
||||||
|
/* Enable receiver if low-active RTS signal is requested */
|
||||||
|
if (sport->have_rtscts && !sport->have_rtsgpio &&
|
||||||
|
!(rs485conf->flags & SER_RS485_RTS_ON_SEND))
|
||||||
|
rs485conf->flags |= SER_RS485_RX_DURING_TX;
|
||||||
|
|
||||||
/* disable transmitter */
|
/* disable transmitter */
|
||||||
ucr2 = imx_uart_readl(sport, UCR2);
|
ucr2 = imx_uart_readl(sport, UCR2);
|
||||||
if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
|
if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
|
||||||
|
@ -2265,6 +2270,18 @@ static int imx_uart_probe(struct platform_device *pdev)
|
||||||
(!sport->have_rtscts && !sport->have_rtsgpio))
|
(!sport->have_rtscts && !sport->have_rtsgpio))
|
||||||
dev_err(&pdev->dev, "no RTS control, disabling rs485\n");
|
dev_err(&pdev->dev, "no RTS control, disabling rs485\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If using the i.MX UART RTS/CTS control then the RTS (CTS_B)
|
||||||
|
* signal cannot be set low during transmission in case the
|
||||||
|
* receiver is off (limitation of the i.MX UART IP).
|
||||||
|
*/
|
||||||
|
if (sport->port.rs485.flags & SER_RS485_ENABLED &&
|
||||||
|
sport->have_rtscts && !sport->have_rtsgpio &&
|
||||||
|
(!(sport->port.rs485.flags & SER_RS485_RTS_ON_SEND) &&
|
||||||
|
!(sport->port.rs485.flags & SER_RS485_RX_DURING_TX)))
|
||||||
|
dev_err(&pdev->dev,
|
||||||
|
"low-active RTS not possible when receiver is off, enabling receiver\n");
|
||||||
|
|
||||||
imx_uart_rs485_config(&sport->port, &sport->port.rs485);
|
imx_uart_rs485_config(&sport->port, &sport->port.rs485);
|
||||||
|
|
||||||
/* Disable interrupts before requesting them */
|
/* Disable interrupts before requesting them */
|
||||||
|
|
|
@ -495,7 +495,6 @@ static void mvebu_uart_set_termios(struct uart_port *port,
|
||||||
termios->c_iflag |= old->c_iflag & ~(INPCK | IGNPAR);
|
termios->c_iflag |= old->c_iflag & ~(INPCK | IGNPAR);
|
||||||
termios->c_cflag &= CREAD | CBAUD;
|
termios->c_cflag &= CREAD | CBAUD;
|
||||||
termios->c_cflag |= old->c_cflag & ~(CREAD | CBAUD);
|
termios->c_cflag |= old->c_cflag & ~(CREAD | CBAUD);
|
||||||
termios->c_lflag = old->c_lflag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
|
|
@ -1022,6 +1022,7 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
|
||||||
struct qcom_geni_serial_port *port;
|
struct qcom_geni_serial_port *port;
|
||||||
struct uart_port *uport;
|
struct uart_port *uport;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
|
int irq;
|
||||||
|
|
||||||
if (pdev->dev.of_node)
|
if (pdev->dev.of_node)
|
||||||
line = of_alias_get_id(pdev->dev.of_node, "serial");
|
line = of_alias_get_id(pdev->dev.of_node, "serial");
|
||||||
|
@ -1061,11 +1062,12 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
|
||||||
port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
|
port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
|
||||||
port->tx_fifo_width = DEF_FIFO_WIDTH_BITS;
|
port->tx_fifo_width = DEF_FIFO_WIDTH_BITS;
|
||||||
|
|
||||||
uport->irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (uport->irq < 0) {
|
if (irq < 0) {
|
||||||
dev_err(&pdev->dev, "Failed to get IRQ %d\n", uport->irq);
|
dev_err(&pdev->dev, "Failed to get IRQ %d\n", irq);
|
||||||
return uport->irq;
|
return irq;
|
||||||
}
|
}
|
||||||
|
uport->irq = irq;
|
||||||
|
|
||||||
uport->private_data = &qcom_geni_console_driver;
|
uport->private_data = &qcom_geni_console_driver;
|
||||||
platform_set_drvdata(pdev, port);
|
platform_set_drvdata(pdev, port);
|
||||||
|
|
|
@ -1181,7 +1181,7 @@ static int __init cdns_early_console_setup(struct earlycon_device *device,
|
||||||
/* only set baud if specified on command line - otherwise
|
/* only set baud if specified on command line - otherwise
|
||||||
* assume it has been initialized by a boot loader.
|
* assume it has been initialized by a boot loader.
|
||||||
*/
|
*/
|
||||||
if (device->baud) {
|
if (port->uartclk && device->baud) {
|
||||||
u32 cd = 0, bdiv = 0;
|
u32 cd = 0, bdiv = 0;
|
||||||
u32 mr;
|
u32 mr;
|
||||||
int div8;
|
int div8;
|
||||||
|
|
|
@ -2816,7 +2816,10 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx)
|
||||||
|
|
||||||
kref_init(&tty->kref);
|
kref_init(&tty->kref);
|
||||||
tty->magic = TTY_MAGIC;
|
tty->magic = TTY_MAGIC;
|
||||||
tty_ldisc_init(tty);
|
if (tty_ldisc_init(tty)) {
|
||||||
|
kfree(tty);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
tty->session = NULL;
|
tty->session = NULL;
|
||||||
tty->pgrp = NULL;
|
tty->pgrp = NULL;
|
||||||
mutex_init(&tty->legacy_mutex);
|
mutex_init(&tty->legacy_mutex);
|
||||||
|
|
|
@ -176,12 +176,11 @@ static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
|
||||||
return ERR_CAST(ldops);
|
return ERR_CAST(ldops);
|
||||||
}
|
}
|
||||||
|
|
||||||
ld = kmalloc(sizeof(struct tty_ldisc), GFP_KERNEL);
|
/*
|
||||||
if (ld == NULL) {
|
* There is no way to handle allocation failure of only 16 bytes.
|
||||||
put_ldops(ldops);
|
* Let's simplify error handling and save more memory.
|
||||||
return ERR_PTR(-ENOMEM);
|
*/
|
||||||
}
|
ld = kmalloc(sizeof(struct tty_ldisc), GFP_KERNEL | __GFP_NOFAIL);
|
||||||
|
|
||||||
ld->ops = ldops;
|
ld->ops = ldops;
|
||||||
ld->tty = tty;
|
ld->tty = tty;
|
||||||
|
|
||||||
|
@ -527,19 +526,16 @@ static int tty_ldisc_failto(struct tty_struct *tty, int ld)
|
||||||
static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
|
static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
|
||||||
{
|
{
|
||||||
/* There is an outstanding reference here so this is safe */
|
/* There is an outstanding reference here so this is safe */
|
||||||
old = tty_ldisc_get(tty, old->ops->num);
|
if (tty_ldisc_failto(tty, old->ops->num) < 0) {
|
||||||
WARN_ON(IS_ERR(old));
|
const char *name = tty_name(tty);
|
||||||
tty->ldisc = old;
|
|
||||||
tty_set_termios_ldisc(tty, old->ops->num);
|
pr_warn("Falling back ldisc for %s.\n", name);
|
||||||
if (tty_ldisc_open(tty, old) < 0) {
|
|
||||||
tty_ldisc_put(old);
|
|
||||||
/* The traditional behaviour is to fall back to N_TTY, we
|
/* The traditional behaviour is to fall back to N_TTY, we
|
||||||
want to avoid falling back to N_NULL unless we have no
|
want to avoid falling back to N_NULL unless we have no
|
||||||
choice to avoid the risk of breaking anything */
|
choice to avoid the risk of breaking anything */
|
||||||
if (tty_ldisc_failto(tty, N_TTY) < 0 &&
|
if (tty_ldisc_failto(tty, N_TTY) < 0 &&
|
||||||
tty_ldisc_failto(tty, N_NULL) < 0)
|
tty_ldisc_failto(tty, N_NULL) < 0)
|
||||||
panic("Couldn't open N_NULL ldisc for %s.",
|
panic("Couldn't open N_NULL ldisc for %s.", name);
|
||||||
tty_name(tty));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -824,12 +820,13 @@ EXPORT_SYMBOL_GPL(tty_ldisc_release);
|
||||||
* the tty structure is not completely set up when this call is made.
|
* the tty structure is not completely set up when this call is made.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void tty_ldisc_init(struct tty_struct *tty)
|
int tty_ldisc_init(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY);
|
struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY);
|
||||||
if (IS_ERR(ld))
|
if (IS_ERR(ld))
|
||||||
panic("n_tty: init_tty");
|
return PTR_ERR(ld);
|
||||||
tty->ldisc = ld;
|
tty->ldisc = ld;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -188,7 +188,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_EARLYCON
|
#ifdef CONFIG_SERIAL_EARLYCON
|
||||||
#define EARLYCON_TABLE() STRUCT_ALIGN(); \
|
#define EARLYCON_TABLE() . = ALIGN(8); \
|
||||||
VMLINUX_SYMBOL(__earlycon_table) = .; \
|
VMLINUX_SYMBOL(__earlycon_table) = .; \
|
||||||
KEEP(*(__earlycon_table)) \
|
KEEP(*(__earlycon_table)) \
|
||||||
VMLINUX_SYMBOL(__earlycon_table_end) = .;
|
VMLINUX_SYMBOL(__earlycon_table_end) = .;
|
||||||
|
|
|
@ -351,10 +351,10 @@ struct earlycon_id {
|
||||||
char name[16];
|
char name[16];
|
||||||
char compatible[128];
|
char compatible[128];
|
||||||
int (*setup)(struct earlycon_device *, const char *options);
|
int (*setup)(struct earlycon_device *, const char *options);
|
||||||
} __aligned(32);
|
};
|
||||||
|
|
||||||
extern const struct earlycon_id __earlycon_table[];
|
extern const struct earlycon_id *__earlycon_table[];
|
||||||
extern const struct earlycon_id __earlycon_table_end[];
|
extern const struct earlycon_id *__earlycon_table_end[];
|
||||||
|
|
||||||
#if defined(CONFIG_SERIAL_EARLYCON) && !defined(MODULE)
|
#if defined(CONFIG_SERIAL_EARLYCON) && !defined(MODULE)
|
||||||
#define EARLYCON_USED_OR_UNUSED __used
|
#define EARLYCON_USED_OR_UNUSED __used
|
||||||
|
@ -362,12 +362,19 @@ extern const struct earlycon_id __earlycon_table_end[];
|
||||||
#define EARLYCON_USED_OR_UNUSED __maybe_unused
|
#define EARLYCON_USED_OR_UNUSED __maybe_unused
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define OF_EARLYCON_DECLARE(_name, compat, fn) \
|
#define _OF_EARLYCON_DECLARE(_name, compat, fn, unique_id) \
|
||||||
static const struct earlycon_id __UNIQUE_ID(__earlycon_##_name) \
|
static const struct earlycon_id unique_id \
|
||||||
EARLYCON_USED_OR_UNUSED __section(__earlycon_table) \
|
EARLYCON_USED_OR_UNUSED __initconst \
|
||||||
= { .name = __stringify(_name), \
|
= { .name = __stringify(_name), \
|
||||||
.compatible = compat, \
|
.compatible = compat, \
|
||||||
.setup = fn }
|
.setup = fn }; \
|
||||||
|
static const struct earlycon_id EARLYCON_USED_OR_UNUSED \
|
||||||
|
__section(__earlycon_table) \
|
||||||
|
* const __PASTE(__p, unique_id) = &unique_id
|
||||||
|
|
||||||
|
#define OF_EARLYCON_DECLARE(_name, compat, fn) \
|
||||||
|
_OF_EARLYCON_DECLARE(_name, compat, fn, \
|
||||||
|
__UNIQUE_ID(__earlycon_##_name))
|
||||||
|
|
||||||
#define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn)
|
#define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn)
|
||||||
|
|
||||||
|
|
|
@ -701,7 +701,7 @@ extern int tty_unregister_ldisc(int disc);
|
||||||
extern int tty_set_ldisc(struct tty_struct *tty, int disc);
|
extern int tty_set_ldisc(struct tty_struct *tty, int disc);
|
||||||
extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty);
|
extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty);
|
||||||
extern void tty_ldisc_release(struct tty_struct *tty);
|
extern void tty_ldisc_release(struct tty_struct *tty);
|
||||||
extern void tty_ldisc_init(struct tty_struct *tty);
|
extern int __must_check tty_ldisc_init(struct tty_struct *tty);
|
||||||
extern void tty_ldisc_deinit(struct tty_struct *tty);
|
extern void tty_ldisc_deinit(struct tty_struct *tty);
|
||||||
extern int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p,
|
extern int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p,
|
||||||
char *f, int count);
|
char *f, int count);
|
||||||
|
|
Loading…
Reference in a new issue