mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 03:53:37 +02:00
TTY/Serial driver fixes for 7.1-rc6
Here are some small serial driver fixes for 7.1-rc6. Included in here
are:
- mips serial driver fixes to resolve some long-standing issues with
how they interacted with the console. That's the "majority" of the
changes in this merge request
- sh-sci driver regression fix
- 8250 driver regression fixes
- other small serial driver fixes for reported problems.
All of these have been in linux-next for over a week with no reported
issues.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-----BEGIN PGP SIGNATURE-----
iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCahrImA8cZ3JlZ0Brcm9h
aC5jb20ACgkQMUfUDdst+ykedQCfb1CR0Z6lElo/02m3wmR+EfvGyoUAoLj8QU71
dFaLWzZQk8Hb6ajmVYK5
=tgAC
-----END PGP SIGNATURE-----
Merge tag 'tty-7.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver fixes from Greg KH:
"Here are some small serial driver fixes for 7.1-rc6. Included in here
are:
- mips serial driver fixes to resolve some long-standing issues with
how they interacted with the console. That's the "majority" of the
changes in this merge request
- sh-sci driver regression fix
- 8250 driver regression fixes
- other small serial driver fixes for reported problems.
All of these have been in linux-next for over a week with no reported
issues"
* tag 'tty-7.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
serial: dz: Enable modular build
serial: zs: Convert to use a platform device
serial: dz: Convert to use a platform device
serial: zs: Switch to using channel reset
serial: zs: Fix bootconsole handover lockup
serial: dz: Fix bootconsole handover lockup
serial: dz: Fix bootconsole message clobbering at chip reset
serial: 8250_dw: dispatch SysRq character in dw8250_handle_irq()
serial: 8250: dispatch SysRq character in serial8250_handle_irq()
serial: core: introduce guard(uart_port_lock_check_sysrq_irqsave)
tty: serial: samsung: Remove redundant port lock acquisition in rx helpers
serial: altera_jtaguart: handle uart_add_one_port() failures
serial: qcom_geni: fix kfifo underflow when flush precedes DMA completion IRQ
serial: fsl_lpuart: fix rx buffer and DMA map leaks in start_rx_dma
tty: add missing tty_driver include to tty_port.h
serial: qcom-geni: fix UART_RX_PAR_EN bit position
serial: sh-sci: fix memory region release in error path
tty: serial: pch_uart: add check for dma_alloc_coherent()
serial: zs: Fix swapped RI/DSR modem line transition counting
This commit is contained in:
commit
495fb8dd7f
|
|
@ -10,6 +10,14 @@
|
|||
#include <linux/mc146818rtc.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
|
||||
#include <asm/dec/interrupts.h>
|
||||
#include <asm/dec/ioasic_addrs.h>
|
||||
#include <asm/dec/kn01.h>
|
||||
#include <asm/dec/kn02.h>
|
||||
#include <asm/dec/system.h>
|
||||
|
||||
static struct resource dec_rtc_resources[] = {
|
||||
{
|
||||
.name = "rtc",
|
||||
|
|
@ -30,11 +38,110 @@ static struct platform_device dec_rtc_device = {
|
|||
.num_resources = ARRAY_SIZE(dec_rtc_resources),
|
||||
};
|
||||
|
||||
static struct resource dec_dz_resources[] = {
|
||||
{ .name = "dz", .flags = IORESOURCE_MEM, },
|
||||
{ .name = "dz", .flags = IORESOURCE_IRQ, },
|
||||
};
|
||||
|
||||
static struct platform_device dec_dz_device = {
|
||||
.name = "dz",
|
||||
.id = PLATFORM_DEVID_NONE,
|
||||
.resource = dec_dz_resources,
|
||||
.num_resources = ARRAY_SIZE(dec_dz_resources),
|
||||
};
|
||||
|
||||
static struct platform_device *dec_dz_devices[] __initdata = {
|
||||
&dec_dz_device,
|
||||
};
|
||||
|
||||
static struct resource dec_zs_resources[][2] = {
|
||||
{
|
||||
{ .name = "scc0", .flags = IORESOURCE_MEM, },
|
||||
{ .name = "scc0", .flags = IORESOURCE_IRQ, },
|
||||
},
|
||||
{
|
||||
{ .name = "scc1", .flags = IORESOURCE_MEM, },
|
||||
{ .name = "scc1", .flags = IORESOURCE_IRQ, },
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device dec_zs_device[] = {
|
||||
{
|
||||
.name = "zs",
|
||||
.id = 0,
|
||||
.resource = dec_zs_resources[0],
|
||||
.num_resources = ARRAY_SIZE(dec_zs_resources[0]),
|
||||
},
|
||||
{
|
||||
.name = "zs",
|
||||
.id = 1,
|
||||
.resource = dec_zs_resources[1],
|
||||
.num_resources = ARRAY_SIZE(dec_zs_resources[1]),
|
||||
},
|
||||
};
|
||||
|
||||
static int __init dec_add_devices(void)
|
||||
{
|
||||
struct platform_device *dec_zs_devices[ARRAY_SIZE(dec_zs_device)];
|
||||
int ret1, ret2, ret3;
|
||||
int num_dz, num_zs;
|
||||
int irq, i;
|
||||
|
||||
dec_rtc_resources[0].start = RTC_PORT(0);
|
||||
dec_rtc_resources[0].end = RTC_PORT(0) + dec_kn_slot_size - 1;
|
||||
return platform_device_register(&dec_rtc_device);
|
||||
|
||||
i = 0;
|
||||
irq = dec_interrupt[DEC_IRQ_DZ11];
|
||||
if (IS_ENABLED(CONFIG_32BIT) && irq >= 0) {
|
||||
resource_size_t base;
|
||||
|
||||
switch (mips_machtype) {
|
||||
case MACH_DS23100:
|
||||
case MACH_DS5100:
|
||||
base = dec_kn_slot_base + KN01_DZ11;
|
||||
break;
|
||||
default:
|
||||
base = dec_kn_slot_base + KN02_DZ11;
|
||||
break;
|
||||
}
|
||||
dec_dz_device.resource[0].start = base;
|
||||
dec_dz_device.resource[0].end = base + dec_kn_slot_size - 1;
|
||||
dec_dz_device.resource[1].start = irq;
|
||||
dec_dz_device.resource[1].end = irq;
|
||||
i++;
|
||||
}
|
||||
num_dz = i;
|
||||
|
||||
i = 0;
|
||||
irq = dec_interrupt[DEC_IRQ_SCC0];
|
||||
if (irq >= 0) {
|
||||
resource_size_t base = dec_kn_slot_base + IOASIC_SCC0;
|
||||
|
||||
dec_zs_device[i].resource[0].start = base;
|
||||
dec_zs_device[i].resource[0].end = base + dec_kn_slot_size - 1;
|
||||
dec_zs_device[i].resource[1].start = irq;
|
||||
dec_zs_device[i].resource[1].end = irq;
|
||||
dec_zs_devices[i] = &dec_zs_device[i];
|
||||
i++;
|
||||
}
|
||||
irq = dec_interrupt[DEC_IRQ_SCC1];
|
||||
if (irq >= 0) {
|
||||
resource_size_t base = dec_kn_slot_base + IOASIC_SCC1;
|
||||
|
||||
dec_zs_device[i].resource[0].start = base;
|
||||
dec_zs_device[i].resource[0].end = base + dec_kn_slot_size - 1;
|
||||
dec_zs_device[i].resource[1].start = irq;
|
||||
dec_zs_device[i].resource[1].end = irq;
|
||||
dec_zs_devices[i] = &dec_zs_device[i];
|
||||
i++;
|
||||
}
|
||||
num_zs = i;
|
||||
|
||||
ret1 = platform_device_register(&dec_rtc_device);
|
||||
ret2 = IS_ENABLED(CONFIG_32BIT) ?
|
||||
platform_add_devices(dec_dz_devices, num_dz) : 0;
|
||||
ret3 = platform_add_devices(dec_zs_devices, num_zs);
|
||||
return ret1 ? ret1 : ret2 ? ret2 : ret3;
|
||||
}
|
||||
|
||||
device_initcall(dec_add_devices);
|
||||
|
|
|
|||
|
|
@ -427,7 +427,7 @@ static int dw8250_handle_irq(struct uart_port *p)
|
|||
unsigned int quirks = d->pdata->quirks;
|
||||
unsigned int status;
|
||||
|
||||
guard(uart_port_lock_irqsave)(p);
|
||||
guard(uart_port_lock_check_sysrq_irqsave)(p);
|
||||
|
||||
switch (FIELD_GET(DW_UART_IIR_IID, iir)) {
|
||||
case UART_IIR_NO_INT:
|
||||
|
|
|
|||
|
|
@ -1784,7 +1784,10 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir)
|
|||
}
|
||||
|
||||
/*
|
||||
* Context: port's lock must be held by the caller.
|
||||
* Context: port's lock must be held by the caller. The caller must
|
||||
* release it via guard(uart_port_lock_check_sysrq_irqsave) or
|
||||
* uart_unlock_and_check_sysrq_irqrestore(), which captures SysRq
|
||||
* character on unlock.
|
||||
*/
|
||||
void serial8250_handle_irq_locked(struct uart_port *port, unsigned int iir)
|
||||
{
|
||||
|
|
@ -1837,7 +1840,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
|
|||
if (iir & UART_IIR_NO_INT)
|
||||
return 0;
|
||||
|
||||
guard(uart_port_lock_irqsave)(port);
|
||||
guard(uart_port_lock_check_sysrq_irqsave)(port);
|
||||
serial8250_handle_irq_locked(port, iir);
|
||||
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -334,7 +334,7 @@ config SERIAL_MAX310X
|
|||
Say Y here if you want to support this ICs.
|
||||
|
||||
config SERIAL_DZ
|
||||
bool "DECstation DZ serial driver"
|
||||
tristate "DECstation DZ serial driver"
|
||||
depends on MACH_DECSTATION && 32BIT
|
||||
select SERIAL_CORE
|
||||
default y
|
||||
|
|
|
|||
|
|
@ -379,6 +379,7 @@ static int altera_jtaguart_probe(struct platform_device *pdev)
|
|||
struct resource *res_mem;
|
||||
int i = pdev->id;
|
||||
int irq;
|
||||
int ret;
|
||||
|
||||
/* -1 emphasizes that the platform must have one port, no .N suffix */
|
||||
if (i == -1)
|
||||
|
|
@ -418,7 +419,11 @@ static int altera_jtaguart_probe(struct platform_device *pdev)
|
|||
port->flags = UPF_BOOT_AUTOCONF;
|
||||
port->dev = &pdev->dev;
|
||||
|
||||
uart_add_one_port(&altera_jtaguart_driver, port);
|
||||
ret = uart_add_one_port(&altera_jtaguart_driver, port);
|
||||
if (ret) {
|
||||
iounmap(port->membase);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/sysrq.h>
|
||||
|
|
@ -48,14 +49,6 @@
|
|||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/bootinfo.h>
|
||||
|
||||
#include <asm/dec/interrupts.h>
|
||||
#include <asm/dec/kn01.h>
|
||||
#include <asm/dec/kn02.h>
|
||||
#include <asm/dec/machtype.h>
|
||||
#include <asm/dec/prom.h>
|
||||
#include <asm/dec/system.h>
|
||||
|
||||
#include "dz.h"
|
||||
|
||||
|
|
@ -65,7 +58,9 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
|
||||
static char dz_name[] __initdata = "DECstation DZ serial driver version ";
|
||||
static char dz_version[] __initdata = "1.04";
|
||||
static char dz_version[] __initdata = "1.05";
|
||||
|
||||
#define DZ_IO_SIZE 0x20 /* IOMEM space size. */
|
||||
|
||||
struct dz_port {
|
||||
struct dz_mux *mux;
|
||||
|
|
@ -81,6 +76,7 @@ struct dz_mux {
|
|||
};
|
||||
|
||||
static struct dz_mux dz_mux;
|
||||
static struct uart_driver dz_reg;
|
||||
|
||||
static inline struct dz_port *to_dport(struct uart_port *uport)
|
||||
{
|
||||
|
|
@ -542,14 +538,47 @@ static int dz_encode_baud_rate(unsigned int baud)
|
|||
static void dz_reset(struct dz_port *dport)
|
||||
{
|
||||
struct dz_mux *mux = dport->mux;
|
||||
unsigned short tcr;
|
||||
int loops = 10000;
|
||||
|
||||
if (mux->initialised)
|
||||
return;
|
||||
|
||||
tcr = dz_in(dport, DZ_TCR);
|
||||
|
||||
/* Do not disturb any ongoing transmissions. */
|
||||
if (dz_in(dport, DZ_CSR) & DZ_MSE) {
|
||||
unsigned short csr, mask;
|
||||
|
||||
mask = tcr;
|
||||
while ((mask & DZ_LNENB) && loops--) {
|
||||
csr = dz_in(dport, DZ_CSR);
|
||||
if (!(csr & DZ_TRDY))
|
||||
continue;
|
||||
mask &= ~(1 << ((csr & DZ_TLINE) >> 8));
|
||||
dz_out(dport, DZ_TCR, mask);
|
||||
iob();
|
||||
udelay(2); /* 1.4us TRDY recovery. */
|
||||
}
|
||||
fsleep(1200); /* Transmitter drain. */
|
||||
}
|
||||
|
||||
dz_out(dport, DZ_CSR, DZ_CLR);
|
||||
while (dz_in(dport, DZ_CSR) & DZ_CLR);
|
||||
iob();
|
||||
|
||||
/*
|
||||
* Set parameters across all lines such as not to interfere
|
||||
* with the initial PROM-based console. Otherwise any output
|
||||
* produced before the console handover would cause the system
|
||||
* firmware to produce rubbish.
|
||||
*/
|
||||
for (int line = 0; line < DZ_NB_PORT; line++)
|
||||
dz_out(dport, DZ_LPR, DZ_B9600 | DZ_CS8 | line);
|
||||
|
||||
/* Re-enable transmission for the initial PROM-based console. */
|
||||
dz_out(dport, DZ_TCR, tcr);
|
||||
|
||||
/* Enable scanning. */
|
||||
dz_out(dport, DZ_CSR, DZ_MSE);
|
||||
|
||||
|
|
@ -633,26 +662,6 @@ static void dz_set_termios(struct uart_port *uport, struct ktermios *termios,
|
|||
uart_port_unlock_irqrestore(&dport->port, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hack alert!
|
||||
* Required solely so that the initial PROM-based console
|
||||
* works undisturbed in parallel with this one.
|
||||
*/
|
||||
static void dz_pm(struct uart_port *uport, unsigned int state,
|
||||
unsigned int oldstate)
|
||||
{
|
||||
struct dz_port *dport = to_dport(uport);
|
||||
unsigned long flags;
|
||||
|
||||
uart_port_lock_irqsave(&dport->port, &flags);
|
||||
if (state < 3)
|
||||
dz_start_tx(&dport->port);
|
||||
else
|
||||
dz_stop_tx(&dport->port);
|
||||
uart_port_unlock_irqrestore(&dport->port, flags);
|
||||
}
|
||||
|
||||
|
||||
static const char *dz_type(struct uart_port *uport)
|
||||
{
|
||||
return "DZ";
|
||||
|
|
@ -668,14 +677,13 @@ static void dz_release_port(struct uart_port *uport)
|
|||
|
||||
map_guard = atomic_add_return(-1, &mux->map_guard);
|
||||
if (!map_guard)
|
||||
release_mem_region(uport->mapbase, dec_kn_slot_size);
|
||||
release_mem_region(uport->mapbase, DZ_IO_SIZE);
|
||||
}
|
||||
|
||||
static int dz_map_port(struct uart_port *uport)
|
||||
{
|
||||
if (!uport->membase)
|
||||
uport->membase = ioremap(uport->mapbase,
|
||||
dec_kn_slot_size);
|
||||
uport->membase = ioremap(uport->mapbase, DZ_IO_SIZE);
|
||||
if (!uport->membase) {
|
||||
printk(KERN_ERR "dz: Cannot map MMIO\n");
|
||||
return -ENOMEM;
|
||||
|
|
@ -691,8 +699,7 @@ static int dz_request_port(struct uart_port *uport)
|
|||
|
||||
map_guard = atomic_add_return(1, &mux->map_guard);
|
||||
if (map_guard == 1) {
|
||||
if (!request_mem_region(uport->mapbase, dec_kn_slot_size,
|
||||
"dz")) {
|
||||
if (!request_mem_region(uport->mapbase, DZ_IO_SIZE, "dz")) {
|
||||
atomic_add(-1, &mux->map_guard);
|
||||
printk(KERN_ERR
|
||||
"dz: Unable to reserve MMIO resource\n");
|
||||
|
|
@ -703,7 +710,7 @@ static int dz_request_port(struct uart_port *uport)
|
|||
if (ret) {
|
||||
map_guard = atomic_add_return(-1, &mux->map_guard);
|
||||
if (!map_guard)
|
||||
release_mem_region(uport->mapbase, dec_kn_slot_size);
|
||||
release_mem_region(uport->mapbase, DZ_IO_SIZE);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -748,7 +755,6 @@ static const struct uart_ops dz_ops = {
|
|||
.startup = dz_startup,
|
||||
.shutdown = dz_shutdown,
|
||||
.set_termios = dz_set_termios,
|
||||
.pm = dz_pm,
|
||||
.type = dz_type,
|
||||
.release_port = dz_release_port,
|
||||
.request_port = dz_request_port,
|
||||
|
|
@ -756,20 +762,15 @@ static const struct uart_ops dz_ops = {
|
|||
.verify_port = dz_verify_port,
|
||||
};
|
||||
|
||||
static void __init dz_init_ports(void)
|
||||
static int __init dz_probe(struct platform_device *pdev)
|
||||
{
|
||||
static int first = 1;
|
||||
unsigned long base;
|
||||
struct resource *mem_resource, *irq_resource;
|
||||
int line;
|
||||
|
||||
if (!first)
|
||||
return;
|
||||
first = 0;
|
||||
|
||||
if (mips_machtype == MACH_DS23100 || mips_machtype == MACH_DS5100)
|
||||
base = dec_kn_slot_base + KN01_DZ11;
|
||||
else
|
||||
base = dec_kn_slot_base + KN02_DZ11;
|
||||
mem_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
irq_resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (!mem_resource || !irq_resource)
|
||||
return -ENODEV;
|
||||
|
||||
for (line = 0; line < DZ_NB_PORT; line++) {
|
||||
struct dz_port *dport = &dz_mux.dport[line];
|
||||
|
|
@ -777,14 +778,33 @@ static void __init dz_init_ports(void)
|
|||
|
||||
dport->mux = &dz_mux;
|
||||
|
||||
uport->irq = dec_interrupt[DEC_IRQ_DZ11];
|
||||
uport->dev = &pdev->dev;
|
||||
uport->irq = irq_resource->start;
|
||||
uport->fifosize = 1;
|
||||
uport->iotype = UPIO_MEM;
|
||||
uport->flags = UPF_BOOT_AUTOCONF;
|
||||
uport->ops = &dz_ops;
|
||||
uport->line = line;
|
||||
uport->mapbase = base;
|
||||
uport->mapbase = mem_resource->start;
|
||||
uport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_DZ_CONSOLE);
|
||||
|
||||
if (uart_add_one_port(&dz_reg, uport))
|
||||
uport->dev = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit dz_remove(struct platform_device *pdev)
|
||||
{
|
||||
int line;
|
||||
|
||||
for (line = DZ_NB_PORT - 1; line >= 0; line--) {
|
||||
struct dz_port *dport = &dz_mux.dport[line];
|
||||
struct uart_port *uport = &dport->port;
|
||||
|
||||
if (uport->dev)
|
||||
uart_remove_one_port(&dz_reg, uport);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -867,24 +887,14 @@ static int __init dz_console_setup(struct console *co, char *options)
|
|||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
int ret;
|
||||
|
||||
ret = dz_map_port(uport);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spin_lock_init(&dport->port.lock); /* For dz_pm(). */
|
||||
|
||||
dz_reset(dport);
|
||||
dz_pm(uport, 0, -1);
|
||||
|
||||
if (!dport->mux)
|
||||
return -ENODEV;
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
|
||||
return uart_set_options(&dport->port, co, baud, parity, bits, flow);
|
||||
return uart_set_options(uport, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
static struct uart_driver dz_reg;
|
||||
static struct console dz_console = {
|
||||
.name = "ttyS",
|
||||
.write = dz_console_print,
|
||||
|
|
@ -895,18 +905,6 @@ static struct console dz_console = {
|
|||
.data = &dz_reg,
|
||||
};
|
||||
|
||||
static int __init dz_serial_console_init(void)
|
||||
{
|
||||
if (!IOASIC) {
|
||||
dz_init_ports();
|
||||
register_console(&dz_console);
|
||||
return 0;
|
||||
} else
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
console_initcall(dz_serial_console_init);
|
||||
|
||||
#define SERIAL_DZ_CONSOLE &dz_console
|
||||
#else
|
||||
#define SERIAL_DZ_CONSOLE NULL
|
||||
|
|
@ -922,25 +920,32 @@ static struct uart_driver dz_reg = {
|
|||
.cons = SERIAL_DZ_CONSOLE,
|
||||
};
|
||||
|
||||
static struct platform_driver dz_driver = {
|
||||
.remove = __exit_p(dz_remove),
|
||||
.driver = { .name = "dz" },
|
||||
};
|
||||
|
||||
static int __init dz_init(void)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
if (IOASIC)
|
||||
return -ENXIO;
|
||||
int ret;
|
||||
|
||||
printk("%s%s\n", dz_name, dz_version);
|
||||
|
||||
dz_init_ports();
|
||||
|
||||
ret = uart_register_driver(&dz_reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = platform_driver_probe(&dz_driver, dz_probe);
|
||||
if (ret)
|
||||
uart_unregister_driver(&dz_reg);
|
||||
|
||||
for (i = 0; i < DZ_NB_PORT; i++)
|
||||
uart_add_one_port(&dz_reg, &dz_mux.dport[i].port);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
static void __exit dz_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&dz_driver);
|
||||
uart_unregister_driver(&dz_reg);
|
||||
}
|
||||
|
||||
module_init(dz_init);
|
||||
module_exit(dz_exit);
|
||||
|
|
|
|||
|
|
@ -1379,7 +1379,8 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
|
|||
|
||||
if (!nent) {
|
||||
dev_err(sport->port.dev, "DMA Rx mapping error\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err_free_buf;
|
||||
}
|
||||
|
||||
dma_rx_sconfig.src_addr = lpuart_dma_datareg_addr(sport);
|
||||
|
|
@ -1391,7 +1392,7 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
|
|||
if (ret < 0) {
|
||||
dev_err(sport->port.dev,
|
||||
"DMA Rx slave config failed, err = %d\n", ret);
|
||||
return ret;
|
||||
goto err_unmap_sg;
|
||||
}
|
||||
|
||||
sport->dma_rx_desc = dmaengine_prep_dma_cyclic(chan,
|
||||
|
|
@ -1402,7 +1403,8 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
|
|||
DMA_PREP_INTERRUPT);
|
||||
if (!sport->dma_rx_desc) {
|
||||
dev_err(sport->port.dev, "Cannot prepare cyclic DMA\n");
|
||||
return -EFAULT;
|
||||
ret = -ENOMEM;
|
||||
goto err_unmap_sg;
|
||||
}
|
||||
|
||||
sport->dma_rx_desc->callback = lpuart_dma_rx_complete;
|
||||
|
|
@ -1426,6 +1428,13 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
|
|||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_unmap_sg:
|
||||
dma_unmap_sg(chan->device->dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE);
|
||||
err_free_buf:
|
||||
kfree(ring->buf);
|
||||
ring->buf = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lpuart_dma_rx_free(struct uart_port *port)
|
||||
|
|
|
|||
|
|
@ -689,8 +689,7 @@ static void pch_request_dma(struct uart_port *port)
|
|||
if (!chan) {
|
||||
dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Tx)\n",
|
||||
__func__);
|
||||
pci_dev_put(dma_dev);
|
||||
return;
|
||||
goto err_pci_get;
|
||||
}
|
||||
priv->chan_tx = chan;
|
||||
|
||||
|
|
@ -704,18 +703,26 @@ static void pch_request_dma(struct uart_port *port)
|
|||
if (!chan) {
|
||||
dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Rx)\n",
|
||||
__func__);
|
||||
dma_release_channel(priv->chan_tx);
|
||||
priv->chan_tx = NULL;
|
||||
pci_dev_put(dma_dev);
|
||||
return;
|
||||
goto err_req_tx;
|
||||
}
|
||||
|
||||
/* Get Consistent memory for DMA */
|
||||
priv->rx_buf_virt = dma_alloc_coherent(port->dev, port->fifosize,
|
||||
&priv->rx_buf_dma, GFP_KERNEL);
|
||||
if (!priv->rx_buf_virt)
|
||||
goto err_req_rx;
|
||||
priv->chan_rx = chan;
|
||||
|
||||
pci_dev_put(dma_dev);
|
||||
return;
|
||||
|
||||
err_req_rx:
|
||||
dma_release_channel(chan);
|
||||
err_req_tx:
|
||||
dma_release_channel(priv->chan_tx);
|
||||
priv->chan_tx = NULL;
|
||||
err_pci_get:
|
||||
pci_dev_put(dma_dev);
|
||||
}
|
||||
|
||||
static void pch_dma_rx_complete(void *arg)
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@
|
|||
#define TX_STOP_BIT_LEN_2 2
|
||||
|
||||
/* SE_UART_RX_TRANS_CFG */
|
||||
#define UART_RX_PAR_EN BIT(3)
|
||||
#define UART_RX_PAR_EN BIT(4)
|
||||
|
||||
/* SE_UART_RX_WORD_LEN */
|
||||
#define RX_WORD_LEN_MASK GENMASK(9, 0)
|
||||
|
|
@ -1031,8 +1031,20 @@ static void qcom_geni_serial_handle_tx_dma(struct uart_port *uport)
|
|||
{
|
||||
struct qcom_geni_serial_port *port = to_dev_port(uport);
|
||||
struct tty_port *tport = &uport->state->port;
|
||||
unsigned int fifo_len = kfifo_len(&tport->xmit_fifo);
|
||||
|
||||
/*
|
||||
* Only advance the kfifo if it still contains the bytes that were
|
||||
* transferred. uart_flush_buffer() may have run before this IRQ
|
||||
* fired: it calls kfifo_reset() under the port lock, making
|
||||
* fifo_len = 0 while tx_remaining remains non-zero. Calling
|
||||
* uart_xmit_advance() in that case would underflow kfifo->out past
|
||||
* kfifo->in, making kfifo_len() wrap to UART_XMIT_SIZE - tx_remaining
|
||||
* and triggering a spurious large DMA transfer of stale data.
|
||||
*/
|
||||
if (fifo_len >= port->tx_remaining)
|
||||
uart_xmit_advance(uport, port->tx_remaining);
|
||||
|
||||
uart_xmit_advance(uport, port->tx_remaining);
|
||||
geni_se_tx_dma_unprep(&port->se, port->tx_dma_addr, port->tx_remaining);
|
||||
port->tx_dma_addr = 0;
|
||||
port->tx_remaining = 0;
|
||||
|
|
|
|||
|
|
@ -245,12 +245,9 @@ static bool s3c24xx_serial_txempty_nofifo(const struct uart_port *port)
|
|||
static void s3c24xx_serial_rx_enable(struct uart_port *port)
|
||||
{
|
||||
struct s3c24xx_uart_port *ourport = to_ourport(port);
|
||||
unsigned long flags;
|
||||
int count = 10000;
|
||||
u32 ucon, ufcon;
|
||||
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
|
||||
while (--count && !s3c24xx_serial_txempty_nofifo(port))
|
||||
udelay(100);
|
||||
|
||||
|
|
@ -263,23 +260,18 @@ static void s3c24xx_serial_rx_enable(struct uart_port *port)
|
|||
wr_regl(port, S3C2410_UCON, ucon);
|
||||
|
||||
ourport->rx_enabled = 1;
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
}
|
||||
|
||||
static void s3c24xx_serial_rx_disable(struct uart_port *port)
|
||||
{
|
||||
struct s3c24xx_uart_port *ourport = to_ourport(port);
|
||||
unsigned long flags;
|
||||
u32 ucon;
|
||||
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
|
||||
ucon = rd_regl(port, S3C2410_UCON);
|
||||
ucon &= ~S3C2410_UCON_RXIRQMODE;
|
||||
wr_regl(port, S3C2410_UCON, ucon);
|
||||
|
||||
ourport->rx_enabled = 0;
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
}
|
||||
|
||||
static void s3c24xx_serial_stop_tx(struct uart_port *port)
|
||||
|
|
|
|||
|
|
@ -3025,7 +3025,7 @@ int sci_request_port(struct uart_port *port)
|
|||
|
||||
ret = sci_remap_port(port);
|
||||
if (unlikely(ret != 0)) {
|
||||
release_resource(res);
|
||||
release_mem_region(port->mapbase, sport->reg_size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
|
@ -66,10 +67,6 @@
|
|||
|
||||
#include <linux/atomic.h>
|
||||
|
||||
#include <asm/dec/interrupts.h>
|
||||
#include <asm/dec/ioasic_addrs.h>
|
||||
#include <asm/dec/system.h>
|
||||
|
||||
#include "zs.h"
|
||||
|
||||
|
||||
|
|
@ -79,7 +76,7 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
|
||||
static char zs_name[] __initdata = "DECstation Z85C30 serial driver version ";
|
||||
static char zs_version[] __initdata = "0.10";
|
||||
static char zs_version[] __initdata = "0.11";
|
||||
|
||||
/*
|
||||
* It would be nice to dynamically allocate everything that
|
||||
|
|
@ -98,25 +95,27 @@ static char zs_version[] __initdata = "0.10";
|
|||
|
||||
#define to_zport(uport) container_of(uport, struct zs_port, port)
|
||||
|
||||
struct zs_parms {
|
||||
resource_size_t scc[ZS_NUM_SCCS];
|
||||
int irq[ZS_NUM_SCCS];
|
||||
};
|
||||
|
||||
static struct zs_scc zs_sccs[ZS_NUM_SCCS];
|
||||
static struct uart_driver zs_reg;
|
||||
|
||||
/*
|
||||
* Set parameters in WR5, WR12, WR13 such as not to interfere
|
||||
* with the initial PROM-based console. Otherwise any output
|
||||
* produced before the console handover would cause the system
|
||||
* firmware to hang (TxENAB) or produce rubbish (Tx8, B9600).
|
||||
*/
|
||||
static u8 zs_init_regs[ZS_NUM_REGS] __initdata = {
|
||||
0, /* write 0 */
|
||||
PAR_SPEC, /* write 1 */
|
||||
0, /* write 2 */
|
||||
0, /* write 3 */
|
||||
X16CLK | SB1, /* write 4 */
|
||||
0, /* write 5 */
|
||||
Tx8 | TxENAB, /* write 5 */
|
||||
0, 0, 0, /* write 6, 7, 8 */
|
||||
MIE | DLC | NV, /* write 9 */
|
||||
NRZ, /* write 10 */
|
||||
TCBR | RCBR, /* write 11 */
|
||||
0, 0, /* BRG time constant, write 12 + 13 */
|
||||
0x16, 0x00, /* BRG time constant, write 12 + 13 */
|
||||
BRSRC | BRENABL, /* write 14 */
|
||||
0, /* write 15 */
|
||||
};
|
||||
|
|
@ -680,9 +679,9 @@ static void zs_status_handle(struct zs_port *zport, struct zs_port *zport_a)
|
|||
uart_handle_dcd_change(uport,
|
||||
zport->mctrl & TIOCM_CAR);
|
||||
if (delta & TIOCM_RNG)
|
||||
uport->icount.dsr++;
|
||||
if (delta & TIOCM_DSR)
|
||||
uport->icount.rng++;
|
||||
if (delta & TIOCM_DSR)
|
||||
uport->icount.dsr++;
|
||||
|
||||
if (delta)
|
||||
wake_up_interruptible(&uport->state->port.delta_msr_wait);
|
||||
|
|
@ -826,22 +825,22 @@ static void zs_shutdown(struct uart_port *uport)
|
|||
|
||||
static void zs_reset(struct zs_port *zport)
|
||||
{
|
||||
struct zs_port *zport_a = &zport->scc->zport[ZS_CHAN_A];
|
||||
struct zs_scc *scc = zport->scc;
|
||||
int irq;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&scc->zlock, flags);
|
||||
irq = !irqs_disabled_flags(flags);
|
||||
if (!scc->initialised) {
|
||||
/* Reset the pointer first, just in case... */
|
||||
read_zsreg(zport, R0);
|
||||
/* And let the current transmission finish. */
|
||||
zs_line_drain(zport, irq);
|
||||
write_zsreg(zport, R9, FHWRES);
|
||||
udelay(10);
|
||||
write_zsreg(zport, R9, 0);
|
||||
scc->initialised = 1;
|
||||
}
|
||||
|
||||
/* Reset the pointer first, just in case... */
|
||||
read_zsreg(zport, R0);
|
||||
/* And let the current transmission finish. */
|
||||
zs_line_drain(zport, irq);
|
||||
write_zsreg(zport, R9, zport == zport_a ? CHRA : CHRB);
|
||||
udelay(10);
|
||||
write_zsreg(zport, R9, 0);
|
||||
|
||||
load_zsregs(zport, zport->regs, irq);
|
||||
spin_unlock_irqrestore(&scc->zlock, flags);
|
||||
}
|
||||
|
|
@ -956,23 +955,6 @@ static void zs_set_termios(struct uart_port *uport, struct ktermios *termios,
|
|||
spin_unlock_irqrestore(&scc->zlock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hack alert!
|
||||
* Required solely so that the initial PROM-based console
|
||||
* works undisturbed in parallel with this one.
|
||||
*/
|
||||
static void zs_pm(struct uart_port *uport, unsigned int state,
|
||||
unsigned int oldstate)
|
||||
{
|
||||
struct zs_port *zport = to_zport(uport);
|
||||
|
||||
if (state < 3)
|
||||
zport->regs[5] |= TxENAB;
|
||||
else
|
||||
zport->regs[5] &= ~TxENAB;
|
||||
write_zsreg(zport, R5, zport->regs[5]);
|
||||
}
|
||||
|
||||
|
||||
static const char *zs_type(struct uart_port *uport)
|
||||
{
|
||||
|
|
@ -1055,7 +1037,6 @@ static const struct uart_ops zs_ops = {
|
|||
.startup = zs_startup,
|
||||
.shutdown = zs_shutdown,
|
||||
.set_termios = zs_set_termios,
|
||||
.pm = zs_pm,
|
||||
.type = zs_type,
|
||||
.release_port = zs_release_port,
|
||||
.request_port = zs_request_port,
|
||||
|
|
@ -1066,63 +1047,62 @@ static const struct uart_ops zs_ops = {
|
|||
/*
|
||||
* Initialize Z85C30 port structures.
|
||||
*/
|
||||
static int __init zs_probe_sccs(void)
|
||||
static int __init zs_probe(struct platform_device *pdev)
|
||||
{
|
||||
static int probed;
|
||||
struct zs_parms zs_parms;
|
||||
int chip, side, irq;
|
||||
int n_chips = 0;
|
||||
struct resource *mem_resource, *irq_resource;
|
||||
int chip, side;
|
||||
int i;
|
||||
|
||||
if (probed)
|
||||
return 0;
|
||||
mem_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
irq_resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (!mem_resource || !irq_resource)
|
||||
return -ENODEV;
|
||||
|
||||
irq = dec_interrupt[DEC_IRQ_SCC0];
|
||||
if (irq >= 0) {
|
||||
zs_parms.scc[n_chips] = IOASIC_SCC0;
|
||||
zs_parms.irq[n_chips] = dec_interrupt[DEC_IRQ_SCC0];
|
||||
n_chips++;
|
||||
}
|
||||
irq = dec_interrupt[DEC_IRQ_SCC1];
|
||||
if (irq >= 0) {
|
||||
zs_parms.scc[n_chips] = IOASIC_SCC1;
|
||||
zs_parms.irq[n_chips] = dec_interrupt[DEC_IRQ_SCC1];
|
||||
n_chips++;
|
||||
}
|
||||
if (!n_chips)
|
||||
return -ENXIO;
|
||||
chip = pdev->id;
|
||||
spin_lock_init(&zs_sccs[chip].zlock);
|
||||
for (side = 0; side < ZS_NUM_CHAN; side++) {
|
||||
struct zs_port *zport = &zs_sccs[chip].zport[side];
|
||||
struct uart_port *uport = &zport->port;
|
||||
|
||||
probed = 1;
|
||||
zport->scc = &zs_sccs[chip];
|
||||
zport->clk_mode = 16;
|
||||
|
||||
for (chip = 0; chip < n_chips; chip++) {
|
||||
spin_lock_init(&zs_sccs[chip].zlock);
|
||||
for (side = 0; side < ZS_NUM_CHAN; side++) {
|
||||
struct zs_port *zport = &zs_sccs[chip].zport[side];
|
||||
struct uart_port *uport = &zport->port;
|
||||
uport->dev = &pdev->dev;
|
||||
uport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_ZS_CONSOLE);
|
||||
uport->irq = irq_resource->start;
|
||||
uport->uartclk = ZS_CLOCK;
|
||||
uport->fifosize = 1;
|
||||
uport->iotype = UPIO_MEM;
|
||||
uport->flags = UPF_BOOT_AUTOCONF;
|
||||
uport->ops = &zs_ops;
|
||||
uport->line = chip * ZS_NUM_CHAN + side;
|
||||
uport->mapbase = mem_resource->start +
|
||||
(side ^ ZS_CHAN_B) * ZS_CHAN_IO_SIZE;
|
||||
|
||||
zport->scc = &zs_sccs[chip];
|
||||
zport->clk_mode = 16;
|
||||
for (i = 0; i < ZS_NUM_REGS; i++)
|
||||
zport->regs[i] = zs_init_regs[i];
|
||||
|
||||
uport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_ZS_CONSOLE);
|
||||
uport->irq = zs_parms.irq[chip];
|
||||
uport->uartclk = ZS_CLOCK;
|
||||
uport->fifosize = 1;
|
||||
uport->iotype = UPIO_MEM;
|
||||
uport->flags = UPF_BOOT_AUTOCONF;
|
||||
uport->ops = &zs_ops;
|
||||
uport->line = chip * ZS_NUM_CHAN + side;
|
||||
uport->mapbase = dec_kn_slot_base +
|
||||
zs_parms.scc[chip] +
|
||||
(side ^ ZS_CHAN_B) * ZS_CHAN_IO_SIZE;
|
||||
|
||||
for (i = 0; i < ZS_NUM_REGS; i++)
|
||||
zport->regs[i] = zs_init_regs[i];
|
||||
}
|
||||
if (uart_add_one_port(&zs_reg, uport))
|
||||
uport->dev = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit zs_remove(struct platform_device *pdev)
|
||||
{
|
||||
int chip, side;
|
||||
|
||||
chip = pdev->id;
|
||||
for (side = ZS_NUM_CHAN - 1; side >= 0; side--) {
|
||||
struct zs_port *zport = &zs_sccs[chip].zport[side];
|
||||
struct uart_port *uport = &zport->port;
|
||||
|
||||
if (uport->dev)
|
||||
uart_remove_one_port(&zs_reg, uport);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_SERIAL_ZS_CONSOLE
|
||||
static void zs_console_putchar(struct uart_port *uport, unsigned char ch)
|
||||
|
|
@ -1203,21 +1183,14 @@ static int __init zs_console_setup(struct console *co, char *options)
|
|||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
int ret;
|
||||
|
||||
ret = zs_map_port(uport);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
zs_reset(zport);
|
||||
zs_pm(uport, 0, -1);
|
||||
|
||||
if (!zport->scc)
|
||||
return -ENODEV;
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
return uart_set_options(uport, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
static struct uart_driver zs_reg;
|
||||
static struct console zs_console = {
|
||||
.name = "ttyS",
|
||||
.write = zs_console_write,
|
||||
|
|
@ -1228,23 +1201,6 @@ static struct console zs_console = {
|
|||
.data = &zs_reg,
|
||||
};
|
||||
|
||||
/*
|
||||
* Register console.
|
||||
*/
|
||||
static int __init zs_serial_console_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = zs_probe_sccs();
|
||||
if (ret)
|
||||
return ret;
|
||||
register_console(&zs_console);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
console_initcall(zs_serial_console_init);
|
||||
|
||||
#define SERIAL_ZS_CONSOLE &zs_console
|
||||
#else
|
||||
#define SERIAL_ZS_CONSOLE NULL
|
||||
|
|
@ -1260,47 +1216,31 @@ static struct uart_driver zs_reg = {
|
|||
.cons = SERIAL_ZS_CONSOLE,
|
||||
};
|
||||
|
||||
static struct platform_driver zs_driver = {
|
||||
.remove = __exit_p(zs_remove),
|
||||
.driver = { .name = "zs" },
|
||||
};
|
||||
|
||||
/* zs_init inits the driver. */
|
||||
static int __init zs_init(void)
|
||||
{
|
||||
int i, ret;
|
||||
int ret;
|
||||
|
||||
pr_info("%s%s\n", zs_name, zs_version);
|
||||
|
||||
/* Find out how many Z85C30 SCCs we have. */
|
||||
ret = zs_probe_sccs();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = uart_register_driver(&zs_reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = platform_driver_probe(&zs_driver, zs_probe);
|
||||
if (ret)
|
||||
uart_unregister_driver(&zs_reg);
|
||||
|
||||
for (i = 0; i < ZS_NUM_SCCS * ZS_NUM_CHAN; i++) {
|
||||
struct zs_scc *scc = &zs_sccs[i / ZS_NUM_CHAN];
|
||||
struct zs_port *zport = &scc->zport[i % ZS_NUM_CHAN];
|
||||
struct uart_port *uport = &zport->port;
|
||||
|
||||
if (zport->scc)
|
||||
uart_add_one_port(&zs_reg, uport);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit zs_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = ZS_NUM_SCCS * ZS_NUM_CHAN - 1; i >= 0; i--) {
|
||||
struct zs_scc *scc = &zs_sccs[i / ZS_NUM_CHAN];
|
||||
struct zs_port *zport = &scc->zport[i % ZS_NUM_CHAN];
|
||||
struct uart_port *uport = &zport->port;
|
||||
|
||||
if (zport->scc)
|
||||
uart_remove_one_port(&zs_reg, uport);
|
||||
}
|
||||
|
||||
platform_driver_unregister(&zs_driver);
|
||||
uart_unregister_driver(&zs_reg);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ struct zs_scc {
|
|||
struct zs_port zport[2];
|
||||
spinlock_t zlock;
|
||||
atomic_t irq_guard;
|
||||
int initialised;
|
||||
};
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
|
|
|||
|
|
@ -1274,6 +1274,18 @@ static inline void uart_unlock_and_check_sysrq_irqrestore(struct uart_port *port
|
|||
}
|
||||
#endif /* CONFIG_MAGIC_SYSRQ_SERIAL */
|
||||
|
||||
/*
|
||||
* Variant of guard(uart_port_lock_irqsave) for IRQ handlers that may capture
|
||||
* a SysRq character via uart_prepare_sysrq_char(). The destructor uses the
|
||||
* sysrq-aware unlock helper so that a captured port->sysrq_ch is dispatched
|
||||
* to handle_sysrq() on scope exit. The plain guard variant silently drops
|
||||
* sysrq_ch and must not be used by callers that process RX.
|
||||
*/
|
||||
DEFINE_LOCK_GUARD_1(uart_port_lock_check_sysrq_irqsave, struct uart_port,
|
||||
uart_port_lock_irqsave(_T->lock, &_T->flags),
|
||||
uart_unlock_and_check_sysrq_irqrestore(_T->lock, _T->flags),
|
||||
unsigned long flags);
|
||||
|
||||
/*
|
||||
* We do the SysRQ and SAK checking like this...
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@
|
|||
#include <linux/kref.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/tty_buffer.h>
|
||||
#include <linux/tty_driver.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
struct attribute_group;
|
||||
struct tty_driver;
|
||||
struct tty_port;
|
||||
struct tty_struct;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user