TTY / Serial patches for 5.15-rc1

Here is the "big" set of tty/serial driver patches for 5.15-rc1
 
 Nothing major in here at all, just some driver updates and more cleanups
 on old tty apis and code that needed it that includes:
 	- tty.h cleanup of things that didn't belong in it
 	- other tty cleanups by Jiri
 	- driver cleanups
 	- rs485 support added to amba-pl011 driver
 	- dts updates
 	- stm32 serial driver updates
 	- other minor fixes and driver updates
 
 All have been in linux-next for a while with no reported problems.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCYS9/lg8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ylZNwCggKViEViSGqJFIafAZZjmI3Nt6tUAoMkRlhcd
 n1MS3snS0Sq+7BdJs37M
 =GyxP
 -----END PGP SIGNATURE-----

Merge tag 'tty-5.15-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 patches for 5.15-rc1

  Nothing major in here at all, just some driver updates and more
  cleanups on old tty apis and code that needed it that includes:

   - tty.h cleanup of things that didn't belong in it

   - other tty cleanups by Jiri

   - driver cleanups

   - rs485 support added to amba-pl011 driver

   - dts updates

   - stm32 serial driver updates

   - other minor fixes and driver updates

  All have been in linux-next for a while with no reported problems"

* tag 'tty-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (83 commits)
  tty: serial: uartlite: Use read_poll_timeout for a polling loop
  tty: serial: uartlite: Use constants in early_uartlite_putc
  tty: Fix data race between tiocsti() and flush_to_ldisc()
  serial: vt8500: Use of_device_get_match_data
  serial: tegra: Use of_device_get_match_data
  serial: 8250_ingenic: Use of_device_get_match_data
  tty: serial: linflexuart: Remove redundant check to simplify the code
  tty: serial: fsl_lpuart: do software reset for imx7ulp and imx8qxp
  tty: serial: fsl_lpuart: enable two stop bits for lpuart32
  tty: serial: fsl_lpuart: fix the wrong mapbase value
  mxser: use semi-colons instead of commas
  tty: moxa: use semi-colons instead of commas
  tty: serial: fsl_lpuart: check dma_tx_in_progress in tx dma callback
  tty: replace in_irq() with in_hardirq()
  serial: sh-sci: fix break handling for sysrq
  serial: stm32: use devm_platform_get_and_ioremap_resource()
  serial: stm32: use the defined variable to simplify code
  Revert "arm pl011 serial: support multi-irq request"
  tty: serial: samsung: Add Exynos850 SoC data
  tty: serial: samsung: Fix driver data macros style
  ...
This commit is contained in:
Linus Torvalds 2021-09-01 09:51:16 -07:00
commit 7c314bdfb6
86 changed files with 1409 additions and 1035 deletions

View File

@ -64,6 +64,12 @@ properties:
- const: nuvoton,npcm750-uart
- const: nvidia,tegra20-uart
- const: nxp,lpc3220-uart
- items:
- enum:
- exar,xr16l2552
- exar,xr16l2551
- exar,xr16l2550
- const: ns8250
- items:
- enum:
- altr,16550-FIFO32

View File

@ -79,6 +79,7 @@ properties:
power-domains: true
clock-frequency: true
current-speed: true
overrun-throttle-ms: true
required:
- compatible

View File

@ -1,27 +0,0 @@
Binding for Cadence UART Controller
Required properties:
- compatible :
Use "xlnx,xuartps","cdns,uart-r1p8" for Zynq-7xxx SoC.
Use "xlnx,zynqmp-uart","cdns,uart-r1p12" for Zynq Ultrascale+ MPSoC.
- reg: Should contain UART controller registers location and length.
- interrupts: Should contain UART controller interrupts.
- clocks: Must contain phandles to the UART clocks
See ../clocks/clock-bindings.txt for details.
- clock-names: Tuple to identify input clocks, must contain "uart_clk" and "pclk"
See ../clocks/clock-bindings.txt for details.
Optional properties:
- cts-override : Override the CTS modem status signal. This signal will
always be reported as active instead of being obtained from the modem status
register. Define this if your serial port does not use this pin
Example:
uart@e0000000 {
compatible = "cdns,uart-r1p8";
clocks = <&clkc 23>, <&clkc 40>;
clock-names = "uart_clk", "pclk";
reg = <0xE0000000 0x1000>;
interrupts = <0 27 4>;
};

View File

@ -0,0 +1,66 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/serial/cdns,uart.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Cadence UART Controller Device Tree Bindings
maintainers:
- Michal Simek <michal.simek@xilinx.com>
allOf:
- $ref: /schemas/serial.yaml#
properties:
compatible:
oneOf:
- description: UART controller for Zynq-7xxx SoC
items:
- const: xlnx,xuartps
- const: cdns,uart-r1p8
- description: UART controller for Zynq Ultrascale+ MPSoC
items:
- const: xlnx,zynqmp-uart
- const: cdns,uart-r1p12
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 2
clock-names:
items:
- const: uart_clk
- const: pclk
cts-override:
description: |
Override the CTS modem status signal. This signal will
always be reported as active instead of being obtained
from the modem status register. Define this if your serial
port does not use this pin.
type: boolean
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
unevaluatedProperties: false
examples:
- |
uart0: serial@e0000000 {
compatible = "xlnx,xuartps", "cdns,uart-r1p8";
clocks = <&clkc 23>, <&clkc 40>;
clock-names = "uart_clk", "pclk";
reg = <0xE0000000 0x1000>;
interrupts = <0 27 4>;
};

View File

@ -15,6 +15,7 @@ Required properties:
* "mediatek,mt7622-uart" for MT7622 compatible UARTS
* "mediatek,mt7623-uart" for MT7623 compatible UARTS
* "mediatek,mt7629-uart" for MT7629 compatible UARTS
* "mediatek,mt7986-uart", "mediatek,mt6577-uart" for MT7986 compatible UARTS
* "mediatek,mt8127-uart" for MT8127 compatible UARTS
* "mediatek,mt8135-uart" for MT8135 compatible UARTS
* "mediatek,mt8173-uart" for MT8173 compatible UARTS

View File

@ -204,9 +204,9 @@ srmcons_init(void)
struct tty_driver *driver;
int err;
driver = alloc_tty_driver(MAX_SRM_CONSOLE_DEVICES);
if (!driver)
return -ENOMEM;
driver = tty_alloc_driver(MAX_SRM_CONSOLE_DEVICES, 0);
if (IS_ERR(driver))
return PTR_ERR(driver);
tty_port_init(&srmcons_singleton.port);
@ -221,7 +221,7 @@ srmcons_init(void)
tty_port_link_device(&srmcons_singleton.port, driver, 0);
err = tty_register_driver(driver);
if (err) {
put_tty_driver(driver);
tty_driver_kref_put(driver);
tty_port_destroy(&srmcons_singleton.port);
return err;
}

View File

@ -120,35 +120,37 @@ early_param("debug", nf_debug_setup);
static int __init nfcon_init(void)
{
struct tty_driver *driver;
int res;
stderr_id = nf_get_id("NF_STDERR");
if (!stderr_id)
return -ENODEV;
nfcon_tty_driver = alloc_tty_driver(1);
if (!nfcon_tty_driver)
return -ENOMEM;
driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
if (IS_ERR(driver))
return PTR_ERR(driver);
tty_port_init(&nfcon_tty_port);
nfcon_tty_driver->driver_name = "nfcon";
nfcon_tty_driver->name = "nfcon";
nfcon_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
nfcon_tty_driver->subtype = SYSTEM_TYPE_TTY;
nfcon_tty_driver->init_termios = tty_std_termios;
nfcon_tty_driver->flags = TTY_DRIVER_REAL_RAW;
driver->driver_name = "nfcon";
driver->name = "nfcon";
driver->type = TTY_DRIVER_TYPE_SYSTEM;
driver->subtype = SYSTEM_TYPE_TTY;
driver->init_termios = tty_std_termios;
tty_set_operations(nfcon_tty_driver, &nfcon_tty_ops);
tty_port_link_device(&nfcon_tty_port, nfcon_tty_driver, 0);
res = tty_register_driver(nfcon_tty_driver);
tty_set_operations(driver, &nfcon_tty_ops);
tty_port_link_device(&nfcon_tty_port, driver, 0);
res = tty_register_driver(driver);
if (res) {
pr_err("failed to register nfcon tty driver\n");
put_tty_driver(nfcon_tty_driver);
tty_driver_kref_put(driver);
tty_port_destroy(&nfcon_tty_port);
return res;
}
nfcon_tty_driver = driver;
if (!(nf_console.flags & CON_ENABLED))
register_console(&nf_console);
@ -159,7 +161,7 @@ static void __exit nfcon_exit(void)
{
unregister_console(&nf_console);
tty_unregister_driver(nfcon_tty_driver);
put_tty_driver(nfcon_tty_driver);
tty_driver_kref_put(nfcon_tty_driver);
tty_port_destroy(&nfcon_tty_port);
}

View File

@ -138,6 +138,7 @@ static struct tty_driver *pdc_console_tty_driver;
static int __init pdc_console_tty_driver_init(void)
{
struct tty_driver *driver;
int err;
/* Check if the console driver is still registered.
@ -160,31 +161,32 @@ static int __init pdc_console_tty_driver_init(void)
printk(KERN_INFO "The PDC console driver is still registered, removing CON_BOOT flag\n");
pdc_cons.flags &= ~CON_BOOT;
pdc_console_tty_driver = alloc_tty_driver(1);
if (!pdc_console_tty_driver)
return -ENOMEM;
driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_RESET_TERMIOS);
if (IS_ERR(driver))
return PTR_ERR(driver);
tty_port_init(&tty_port);
pdc_console_tty_driver->driver_name = "pdc_cons";
pdc_console_tty_driver->name = "ttyB";
pdc_console_tty_driver->major = MUX_MAJOR;
pdc_console_tty_driver->minor_start = 0;
pdc_console_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
pdc_console_tty_driver->init_termios = tty_std_termios;
pdc_console_tty_driver->flags = TTY_DRIVER_REAL_RAW |
TTY_DRIVER_RESET_TERMIOS;
tty_set_operations(pdc_console_tty_driver, &pdc_console_tty_ops);
tty_port_link_device(&tty_port, pdc_console_tty_driver, 0);
driver->driver_name = "pdc_cons";
driver->name = "ttyB";
driver->major = MUX_MAJOR;
driver->minor_start = 0;
driver->type = TTY_DRIVER_TYPE_SYSTEM;
driver->init_termios = tty_std_termios;
tty_set_operations(driver, &pdc_console_tty_ops);
tty_port_link_device(&tty_port, driver, 0);
err = tty_register_driver(pdc_console_tty_driver);
err = tty_register_driver(driver);
if (err) {
printk(KERN_ERR "Unable to register the PDC console TTY driver\n");
tty_port_destroy(&tty_port);
tty_driver_kref_put(driver);
return err;
}
pdc_console_tty_driver = driver;
return 0;
}
device_initcall(pdc_console_tty_driver_init);

View File

@ -538,12 +538,14 @@ int register_lines(struct line_driver *line_driver,
const struct tty_operations *ops,
struct line *lines, int nlines)
{
struct tty_driver *driver = alloc_tty_driver(nlines);
struct tty_driver *driver;
int err;
int i;
if (!driver)
return -ENOMEM;
driver = tty_alloc_driver(nlines, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(driver))
return PTR_ERR(driver);
driver->driver_name = line_driver->name;
driver->name = line_driver->device_name;
@ -551,9 +553,8 @@ int register_lines(struct line_driver *line_driver,
driver->minor_start = line_driver->minor_start;
driver->type = line_driver->type;
driver->subtype = line_driver->subtype;
driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
driver->init_termios = tty_std_termios;
for (i = 0; i < nlines; i++) {
tty_port_init(&lines[i].port);
lines[i].port.ops = &line_port_ops;
@ -567,7 +568,7 @@ int register_lines(struct line_driver *line_driver,
if (err) {
printk(KERN_ERR "register_lines : can't register %s driver\n",
line_driver->name);
put_tty_driver(driver);
tty_driver_kref_put(driver);
for (i = 0; i < nlines; i++)
tty_port_destroy(&lines[i].port);
return err;

View File

@ -136,28 +136,41 @@ static const struct tty_operations serial_ops = {
static int __init rs_init(void)
{
tty_port_init(&serial_port);
struct tty_driver *driver;
int ret;
serial_driver = alloc_tty_driver(SERIAL_MAX_NUM_LINES);
driver = tty_alloc_driver(SERIAL_MAX_NUM_LINES, TTY_DRIVER_REAL_RAW);
if (IS_ERR(driver))
return PTR_ERR(driver);
tty_port_init(&serial_port);
/* Initialize the tty_driver structure */
serial_driver->driver_name = "iss_serial";
serial_driver->name = "ttyS";
serial_driver->major = TTY_MAJOR;
serial_driver->minor_start = 64;
serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
serial_driver->subtype = SERIAL_TYPE_NORMAL;
serial_driver->init_termios = tty_std_termios;
serial_driver->init_termios.c_cflag =
driver->driver_name = "iss_serial";
driver->name = "ttyS";
driver->major = TTY_MAJOR;
driver->minor_start = 64;
driver->type = TTY_DRIVER_TYPE_SERIAL;
driver->subtype = SERIAL_TYPE_NORMAL;
driver->init_termios = tty_std_termios;
driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
serial_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(serial_driver, &serial_ops);
tty_port_link_device(&serial_port, serial_driver, 0);
tty_set_operations(driver, &serial_ops);
tty_port_link_device(&serial_port, driver, 0);
ret = tty_register_driver(driver);
if (ret) {
pr_err("Couldn't register serial driver\n");
tty_driver_kref_put(driver);
tty_port_destroy(&serial_port);
return ret;
}
serial_driver = driver;
if (tty_register_driver(serial_driver))
panic("Couldn't register serial driver\n");
return 0;
}
@ -165,7 +178,7 @@ static int __init rs_init(void)
static __exit void rs_exit(void)
{
tty_unregister_driver(serial_driver);
put_tty_driver(serial_driver);
tty_driver_kref_put(serial_driver);
tty_port_destroy(&serial_port);
}

View File

@ -2841,7 +2841,7 @@ static int __init synclink_cs_init(void)
err_unreg_tty:
tty_unregister_driver(serial_driver);
err_put_tty:
put_tty_driver(serial_driver);
tty_driver_kref_put(serial_driver);
err:
return rc;
}
@ -2850,7 +2850,7 @@ static void __exit synclink_cs_exit(void)
{
pcmcia_unregister_driver(&mgslpc_driver);
tty_unregister_driver(serial_driver);
put_tty_driver(serial_driver);
tty_driver_kref_put(serial_driver);
}
module_init(synclink_cs_init);

View File

@ -198,7 +198,7 @@ static int __init ttyprintk_init(void)
return 0;
error:
put_tty_driver(ttyprintk_driver);
tty_driver_kref_put(ttyprintk_driver);
tty_port_destroy(&tpk_port.port);
return ret;
}
@ -206,7 +206,7 @@ error:
static void __exit ttyprintk_exit(void)
{
tty_unregister_driver(ttyprintk_driver);
put_tty_driver(ttyprintk_driver);
tty_driver_kref_put(ttyprintk_driver);
tty_port_destroy(&tpk_port.port);
}

View File

@ -347,10 +347,10 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
/* Register the TTY device */
/* Each IP-OCTAL channel is a TTY port */
tty = alloc_tty_driver(NR_CHANNELS);
if (!tty)
return -ENOMEM;
tty = tty_alloc_driver(NR_CHANNELS, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(tty))
return PTR_ERR(tty);
/* Fill struct tty_driver with ipoctal data */
tty->owner = THIS_MODULE;
@ -362,7 +362,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
tty->minor_start = 0;
tty->type = TTY_DRIVER_TYPE_SERIAL;
tty->subtype = SERIAL_TYPE_NORMAL;
tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
tty->init_termios = tty_std_termios;
tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
tty->init_termios.c_ispeed = 9600;
@ -372,7 +371,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
res = tty_register_driver(tty);
if (res) {
dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n");
put_tty_driver(tty);
tty_driver_kref_put(tty);
return res;
}
@ -697,7 +696,7 @@ static void __ipoctal_remove(struct ipoctal *ipoctal)
}
tty_unregister_driver(ipoctal->tty_drv);
put_tty_driver(ipoctal->tty_drv);
tty_driver_kref_put(ipoctal->tty_drv);
kfree(ipoctal);
}

View File

@ -1269,10 +1269,11 @@ static int __init capinc_tty_init(void)
if (!capiminors)
return -ENOMEM;
drv = alloc_tty_driver(capi_ttyminors);
if (!drv) {
drv = tty_alloc_driver(capi_ttyminors, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(drv)) {
kfree(capiminors);
return -ENOMEM;
return PTR_ERR(drv);
}
drv->driver_name = "capi_nc";
drv->name = "capi!";
@ -1285,14 +1286,11 @@ static int __init capinc_tty_init(void)
drv->init_termios.c_oflag = OPOST | ONLCR;
drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
drv->init_termios.c_lflag = 0;
drv->flags =
TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS |
TTY_DRIVER_DYNAMIC_DEV;
tty_set_operations(drv, &capinc_ops);
err = tty_register_driver(drv);
if (err) {
put_tty_driver(drv);
tty_driver_kref_put(drv);
kfree(capiminors);
printk(KERN_ERR "Couldn't register capi_nc driver\n");
return err;
@ -1304,7 +1302,7 @@ static int __init capinc_tty_init(void)
static void __exit capinc_tty_exit(void)
{
tty_unregister_driver(capinc_tty_driver);
put_tty_driver(capinc_tty_driver);
tty_driver_kref_put(capinc_tty_driver);
kfree(capiminors);
}

View File

@ -249,7 +249,7 @@ int bcm_vk_tty_init(struct bcm_vk *vk, char *name)
tty_drv->name = kstrdup(name, GFP_KERNEL);
if (!tty_drv->name) {
err = -ENOMEM;
goto err_put_tty_driver;
goto err_tty_driver_kref_put;
}
tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
tty_drv->subtype = SERIAL_TYPE_NORMAL;
@ -295,8 +295,8 @@ err_kfree_tty_name:
kfree(tty_drv->name);
tty_drv->name = NULL;
err_put_tty_driver:
put_tty_driver(tty_drv);
err_tty_driver_kref_put:
tty_driver_kref_put(tty_drv);
return err;
}
@ -317,7 +317,7 @@ void bcm_vk_tty_exit(struct bcm_vk *vk)
kfree(vk->tty_drv->name);
vk->tty_drv->name = NULL;
put_tty_driver(vk->tty_drv);
tty_driver_kref_put(vk->tty_drv);
}
void bcm_vk_tty_terminate_tty_user(struct bcm_vk *vk)

View File

@ -1135,9 +1135,10 @@ static int __init sdio_uart_init(void)
int ret;
struct tty_driver *tty_drv;
sdio_uart_tty_driver = tty_drv = alloc_tty_driver(UART_NR);
if (!tty_drv)
return -ENOMEM;
sdio_uart_tty_driver = tty_drv = tty_alloc_driver(UART_NR,
TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(tty_drv))
return PTR_ERR(tty_drv);
tty_drv->driver_name = "sdio_uart";
tty_drv->name = "ttySDIO";
@ -1145,7 +1146,6 @@ static int __init sdio_uart_init(void)
tty_drv->minor_start = 0;
tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
tty_drv->subtype = SERIAL_TYPE_NORMAL;
tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
tty_drv->init_termios = tty_std_termios;
tty_drv->init_termios.c_cflag = B4800 | CS8 | CREAD | HUPCL | CLOCAL;
tty_drv->init_termios.c_ispeed = 4800;
@ -1165,7 +1165,7 @@ static int __init sdio_uart_init(void)
err2:
tty_unregister_driver(tty_drv);
err1:
put_tty_driver(tty_drv);
tty_driver_kref_put(tty_drv);
return ret;
}
@ -1173,7 +1173,7 @@ static void __exit sdio_uart_exit(void)
{
sdio_unregister_driver(&sdio_uart_driver);
tty_unregister_driver(sdio_uart_tty_driver);
put_tty_driver(sdio_uart_tty_driver);
tty_driver_kref_put(sdio_uart_tty_driver);
}
module_init(sdio_uart_init);

View File

@ -3241,9 +3241,10 @@ static int __init hso_init(void)
serial_table[i] = NULL;
/* allocate our driver using the proper amount of supported minors */
tty_drv = alloc_tty_driver(HSO_SERIAL_TTY_MINORS);
if (!tty_drv)
return -ENOMEM;
tty_drv = tty_alloc_driver(HSO_SERIAL_TTY_MINORS, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(tty_drv))
return PTR_ERR(tty_drv);
/* fill in all needed values */
tty_drv->driver_name = driver_name;
@ -3256,7 +3257,6 @@ static int __init hso_init(void)
tty_drv->minor_start = 0;
tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
tty_drv->subtype = SERIAL_TYPE_NORMAL;
tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
tty_drv->init_termios = tty_std_termios;
hso_init_termios(&tty_drv->init_termios);
tty_set_operations(tty_drv, &hso_serial_ops);
@ -3281,7 +3281,7 @@ static int __init hso_init(void)
err_unreg_tty:
tty_unregister_driver(tty_drv);
err_free_tty:
put_tty_driver(tty_drv);
tty_driver_kref_put(tty_drv);
return result;
}
@ -3292,7 +3292,7 @@ static void __exit hso_exit(void)
tty_unregister_driver(tty_drv);
/* deregister the usb driver */
usb_deregister(&hso_driver);
put_tty_driver(tty_drv);
tty_driver_kref_put(tty_drv);
}
/* Module definitions */

View File

@ -301,20 +301,13 @@ static acpi_status ssam_serdev_setup_via_acpi_crs(struct acpi_resource *rsc,
void *ctx)
{
struct serdev_device *serdev = ctx;
struct acpi_resource_common_serialbus *serial;
struct acpi_resource_uart_serialbus *uart;
bool flow_control;
int status = 0;
if (rsc->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
if (!serdev_acpi_get_uart_resource(rsc, &uart))
return AE_OK;
serial = &rsc->data.common_serial_bus;
if (serial->type != ACPI_RESOURCE_SERIAL_TYPE_UART)
return AE_OK;
uart = &rsc->data.uart_serial_bus;
/* Set up serdev device. */
serdev_device_set_baudrate(serdev, uart->default_baud_rate);

View File

@ -1076,13 +1076,13 @@ static int __init tty3215_init(void)
if (!CONSOLE_IS_3215)
return 0;
driver = alloc_tty_driver(NR_3215);
if (!driver)
return -ENOMEM;
driver = tty_alloc_driver(NR_3215, TTY_DRIVER_REAL_RAW);
if (IS_ERR(driver))
return PTR_ERR(driver);
ret = ccw_driver_register(&raw3215_ccw_driver);
if (ret) {
put_tty_driver(driver);
tty_driver_kref_put(driver);
return ret;
}
/*
@ -1101,11 +1101,10 @@ static int __init tty3215_init(void)
driver->init_termios.c_iflag = IGNBRK | IGNPAR;
driver->init_termios.c_oflag = ONLCR;
driver->init_termios.c_lflag = ISIG;
driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(driver, &tty3215_ops);
ret = tty_register_driver(driver);
if (ret) {
put_tty_driver(driver);
tty_driver_kref_put(driver);
return ret;
}
tty3215_driver = driver;

View File

@ -503,20 +503,20 @@ sclp_tty_init(void)
return 0;
if (!sclp.has_linemode)
return 0;
driver = alloc_tty_driver(1);
if (!driver)
return -ENOMEM;
driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
if (IS_ERR(driver))
return PTR_ERR(driver);
rc = sclp_rw_init();
if (rc) {
put_tty_driver(driver);
tty_driver_kref_put(driver);
return rc;
}
/* Allocate pages for output buffering */
for (i = 0; i < MAX_KMEM_PAGES; i++) {
page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (page == NULL) {
put_tty_driver(driver);
tty_driver_kref_put(driver);
return -ENOMEM;
}
list_add_tail((struct list_head *) page, &sclp_tty_pages);
@ -532,7 +532,7 @@ sclp_tty_init(void)
rc = sclp_register(&sclp_input_event);
if (rc) {
put_tty_driver(driver);
tty_driver_kref_put(driver);
return rc;
}
@ -548,12 +548,11 @@ sclp_tty_init(void)
driver->init_termios.c_iflag = IGNBRK | IGNPAR;
driver->init_termios.c_oflag = ONLCR;
driver->init_termios.c_lflag = ISIG | ECHO;
driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(driver, &sclp_ops);
tty_port_link_device(&sclp_port, driver, 0);
rc = tty_register_driver(driver);
if (rc) {
put_tty_driver(driver);
tty_driver_kref_put(driver);
tty_port_destroy(&sclp_port);
return rc;
}

View File

@ -732,9 +732,9 @@ static int __init sclp_vt220_tty_init(void)
/* Note: we're not testing for CONSOLE_IS_SCLP here to preserve
* symmetry between VM and LPAR systems regarding ttyS1. */
driver = alloc_tty_driver(1);
if (!driver)
return -ENOMEM;
driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
if (IS_ERR(driver))
return PTR_ERR(driver);
rc = __sclp_vt220_init(MAX_KMEM_PAGES);
if (rc)
goto out_driver;
@ -746,7 +746,6 @@ static int __init sclp_vt220_tty_init(void)
driver->type = TTY_DRIVER_TYPE_SYSTEM;
driver->subtype = SYSTEM_TYPE_TTY;
driver->init_termios = tty_std_termios;
driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(driver, &sclp_vt220_ops);
tty_port_link_device(&sclp_vt220_port, driver, 0);
@ -764,7 +763,7 @@ out_reg:
out_init:
__sclp_vt220_cleanup();
out_driver:
put_tty_driver(driver);
tty_driver_kref_put(driver);
return rc;
}
__initcall(sclp_vt220_tty_init);

View File

@ -1935,7 +1935,7 @@ static int __init tty3270_init(void)
tty_set_operations(driver, &tty3270_ops);
ret = tty_register_driver(driver);
if (ret) {
put_tty_driver(driver);
tty_driver_kref_put(driver);
return ret;
}
tty3270_driver = driver;
@ -1952,7 +1952,7 @@ tty3270_exit(void)
driver = tty3270_driver;
tty3270_driver = NULL;
tty_unregister_driver(driver);
put_tty_driver(driver);
tty_driver_kref_put(driver);
tty3270_del_views();
}

View File

@ -2852,11 +2852,11 @@ unregister_loop:
tty_unregister_driver(fwloop_driver);
put_loop:
if (create_loop_dev)
put_tty_driver(fwloop_driver);
tty_driver_kref_put(fwloop_driver);
unregister_driver:
tty_unregister_driver(fwtty_driver);
put_tty:
put_tty_driver(fwtty_driver);
tty_driver_kref_put(fwtty_driver);
remove_debugfs:
debugfs_remove_recursive(fwserial_debugfs);
@ -2871,10 +2871,10 @@ static void __exit fwserial_exit(void)
kmem_cache_destroy(fwtty_txn_cache);
if (create_loop_dev) {
tty_unregister_driver(fwloop_driver);
put_tty_driver(fwloop_driver);
tty_driver_kref_put(fwloop_driver);
}
tty_unregister_driver(fwtty_driver);
put_tty_driver(fwtty_driver);
tty_driver_kref_put(fwtty_driver);
debugfs_remove_recursive(fwserial_debugfs);
}

View File

@ -281,9 +281,10 @@ int register_lte_tty_driver(void)
int ret;
for (i = 0; i < TTY_MAX_COUNT; i++) {
tty_driver = alloc_tty_driver(GDM_TTY_MINOR);
if (!tty_driver)
return -ENOMEM;
tty_driver = tty_alloc_driver(GDM_TTY_MINOR,
TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(tty_driver))
return PTR_ERR(tty_driver);
tty_driver->owner = THIS_MODULE;
tty_driver->driver_name = DRIVER_STRING[i];
@ -291,8 +292,6 @@ int register_lte_tty_driver(void)
tty_driver->major = GDM_TTY_MAJOR;
tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
tty_driver->subtype = SERIAL_TYPE_NORMAL;
tty_driver->flags = TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV;
tty_driver->init_termios = tty_std_termios;
tty_driver->init_termios.c_cflag = B9600 | CS8 | HUPCL | CLOCAL;
tty_driver->init_termios.c_lflag = ISIG | ICANON | IEXTEN;
@ -300,7 +299,7 @@ int register_lte_tty_driver(void)
ret = tty_register_driver(tty_driver);
if (ret) {
put_tty_driver(tty_driver);
tty_driver_kref_put(tty_driver);
return ret;
}
@ -319,7 +318,7 @@ void unregister_lte_tty_driver(void)
tty_driver = gdm_driver[i];
if (tty_driver) {
tty_unregister_driver(tty_driver);
put_tty_driver(tty_driver);
tty_driver_kref_put(tty_driver);
}
}
}

View File

@ -973,7 +973,7 @@ static int gb_tty_init(void)
return 0;
fail_put_gb_tty:
put_tty_driver(gb_tty_driver);
tty_driver_kref_put(gb_tty_driver);
fail_unregister_dev:
return retval;
}
@ -981,7 +981,7 @@ fail_unregister_dev:
static void gb_tty_exit(void)
{
tty_unregister_driver(gb_tty_driver);
put_tty_driver(gb_tty_driver);
tty_driver_kref_put(gb_tty_driver);
idr_destroy(&tty_minors);
}

View File

@ -22,8 +22,6 @@
*
*/
#include <linux/delay.h>
/* Set of debugging defines */
#undef SERIAL_DEBUG_INTR
@ -31,55 +29,42 @@
#undef SERIAL_DEBUG_FLOW
#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
/* Sanity checks */
#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
tty->name, (info->tport.flags), serial_driver->refcount,info->count,tty->count,s)
#else
#define DBG_CNT(s)
#endif
/*
* End of serial driver configuration section.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/serial.h>
#include <linux/serial_reg.h>
static char *serial_version = "4.30";
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/bitops.h>
#include <linux/circ_buf.h>
#include <linux/console.h>
#include <linux/major.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <asm/setup.h>
#include <asm/irq.h>
#include <linux/ptrace.h>
#include <linux/seq_file.h>
#include <linux/serial.h>
#include <linux/serial_reg.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/tty_flip.h>
#include <linux/tty.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include <asm/irq.h>
#include <asm/setup.h>
struct serial_state {
struct tty_port tport;
@ -88,7 +73,6 @@ struct serial_state {
unsigned long port;
int baud_base;
int xmit_fifo_size;
int custom_divisor;
int read_status_mask;
int ignore_status_mask;
@ -99,14 +83,13 @@ struct serial_state {
int x_char; /* xon/xoff character */
};
#define custom amiga_custom
static char *serial_name = "Amiga-builtin serial driver";
static struct tty_driver *serial_driver;
/* number of characters left in xmit buffer before we ask for more */
#define WAKEUP_CHARS 256
#define XMIT_FIFO_SIZE 1
static unsigned char current_ctl_bits;
static void change_speed(struct tty_struct *tty, struct serial_state *info,
@ -114,13 +97,7 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info,
static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
static struct serial_state rs_table[1];
#define NR_PORTS ARRAY_SIZE(rs_table)
#include <linux/uaccess.h>
#define serial_isroot() (capable(CAP_SYS_ADMIN))
static struct serial_state serial_state;
/* some serial hardware definitions */
#define SDR_OVRUN (1<<15)
@ -161,9 +138,9 @@ static void rs_stop(struct tty_struct *tty)
if (info->IER & UART_IER_THRI) {
info->IER &= ~UART_IER_THRI;
/* disable Tx interrupt and remove any pending interrupts */
custom.intena = IF_TBE;
amiga_custom.intena = IF_TBE;
mb();
custom.intreq = IF_TBE;
amiga_custom.intreq = IF_TBE;
mb();
}
local_irq_restore(flags);
@ -179,10 +156,10 @@ static void rs_start(struct tty_struct *tty)
&& info->xmit.buf
&& !(info->IER & UART_IER_THRI)) {
info->IER |= UART_IER_THRI;
custom.intena = IF_SETCLR | IF_TBE;
amiga_custom.intena = IF_SETCLR | IF_TBE;
mb();
/* set a pending Tx Interrupt, transmitter should restart now */
custom.intreq = IF_SETCLR | IF_TBE;
amiga_custom.intreq = IF_SETCLR | IF_TBE;
mb();
}
local_irq_restore(flags);
@ -191,21 +168,8 @@ static void rs_start(struct tty_struct *tty)
/*
* ----------------------------------------------------------------------
*
* Here starts the interrupt handling routines. All of the following
* subroutines are declared as inline and are folded into
* rs_interrupt(). They were separated out for readability's sake.
* Here start the interrupt handling routines.
*
* Note: rs_interrupt() is a "fast" interrupt, which means that it
* runs with interrupts turned off. People who may want to modify
* rs_interrupt() should try to keep the interrupt handler as fast as
* possible. After you are done making modifications, it is not a bad
* idea to do:
*
* gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
*
* and look at the resulting assemble code in serial.s.
*
* - Ted Ts'o (tytso@mit.edu), 7-Mar-93
* -----------------------------------------------------------------------
*/
@ -220,9 +184,9 @@ static void receive_chars(struct serial_state *info)
icount = &info->icount;
status = UART_LSR_DR; /* We obviously have a character! */
serdatr = custom.serdatr;
serdatr = amiga_custom.serdatr;
mb();
custom.intreq = IF_RBF;
amiga_custom.intreq = IF_RBF;
mb();
if((serdatr & 0x1ff) == 0)
@ -299,10 +263,10 @@ out:
static void transmit_chars(struct serial_state *info)
{
custom.intreq = IF_TBE;
amiga_custom.intreq = IF_TBE;
mb();
if (info->x_char) {
custom.serdat = info->x_char | 0x100;
amiga_custom.serdat = info->x_char | 0x100;
mb();
info->icount.tx++;
info->x_char = 0;
@ -312,12 +276,12 @@ static void transmit_chars(struct serial_state *info)
|| info->tport.tty->flow.stopped
|| info->tport.tty->hw_stopped) {
info->IER &= ~UART_IER_THRI;
custom.intena = IF_TBE;
amiga_custom.intena = IF_TBE;
mb();
return;
}
custom.serdat = info->xmit.buf[info->xmit.tail++] | 0x100;
amiga_custom.serdat = info->xmit.buf[info->xmit.tail++] | 0x100;
mb();
info->xmit.tail = info->xmit.tail & (SERIAL_XMIT_SIZE-1);
info->icount.tx++;
@ -331,7 +295,7 @@ static void transmit_chars(struct serial_state *info)
printk("THRE...");
#endif
if (info->xmit.head == info->xmit.tail) {
custom.intena = IF_TBE;
amiga_custom.intena = IF_TBE;
mb();
info->IER &= ~UART_IER_THRI;
}
@ -384,10 +348,10 @@ static void check_modem_status(struct serial_state *info)
#endif
port->tty->hw_stopped = 0;
info->IER |= UART_IER_THRI;
custom.intena = IF_SETCLR | IF_TBE;
amiga_custom.intena = IF_SETCLR | IF_TBE;
mb();
/* set a pending Tx Interrupt, transmitter should restart now */
custom.intreq = IF_SETCLR | IF_TBE;
amiga_custom.intreq = IF_SETCLR | IF_TBE;
mb();
tty_wakeup(port->tty);
return;
@ -400,9 +364,9 @@ static void check_modem_status(struct serial_state *info)
port->tty->hw_stopped = 1;
info->IER &= ~UART_IER_THRI;
/* disable Tx interrupt and remove any pending interrupts */
custom.intena = IF_TBE;
amiga_custom.intena = IF_TBE;
mb();
custom.intreq = IF_TBE;
amiga_custom.intreq = IF_TBE;
mb();
}
}
@ -444,7 +408,7 @@ static irqreturn_t ser_tx_int(int irq, void *dev_id)
{
struct serial_state *info = dev_id;
if (custom.serdatr & SDR_TBE) {
if (amiga_custom.serdatr & SDR_TBE) {
#ifdef SERIAL_DEBUG_INTR
printk("ser_tx_int...");
#endif
@ -504,20 +468,20 @@ static int startup(struct tty_struct *tty, struct serial_state *info)
/* Clear anything in the input buffer */
custom.intreq = IF_RBF;
amiga_custom.intreq = IF_RBF;
mb();
retval = request_irq(IRQ_AMIGA_VERTB, ser_vbl_int, 0, "serial status", info);
if (retval) {
if (serial_isroot()) {
set_bit(TTY_IO_ERROR, &tty->flags);
retval = 0;
}
goto errout;
if (capable(CAP_SYS_ADMIN)) {
set_bit(TTY_IO_ERROR, &tty->flags);
retval = 0;
}
goto errout;
}
/* enable both Rx and Tx interrupts */
custom.intena = IF_SETCLR | IF_RBF | IF_TBE;
amiga_custom.intena = IF_SETCLR | IF_RBF | IF_TBE;
mb();
info->IER = UART_IER_MSI;
@ -553,13 +517,10 @@ errout:
static void shutdown(struct tty_struct *tty, struct serial_state *info)
{
unsigned long flags;
struct serial_state *state;
if (!tty_port_initialized(&info->tport))
return;
state = info;
#ifdef SERIAL_DEBUG_OPEN
printk("Shutting down serial port %d ....\n", info->line);
#endif
@ -583,11 +544,11 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info)
}
info->IER = 0;
custom.intena = IF_RBF | IF_TBE;
amiga_custom.intena = IF_RBF | IF_TBE;
mb();
/* disable break condition */
custom.adkcon = AC_UARTBRK;
amiga_custom.adkcon = AC_UARTBRK;
mb();
if (C_HUPCL(tty))
@ -671,7 +632,7 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info,
if (!quot)
quot = baud_base / 9600;
info->quot = quot;
info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base);
info->timeout = (XMIT_FIFO_SIZE*HZ*bits*quot) / baud_base;
info->timeout += HZ/50; /* Add .02 seconds of slop */
/* CTS flow control flag and modem status interrupts */
@ -731,7 +692,7 @@ static void change_speed(struct tty_struct *tty, struct serial_state *info,
if(cval & UART_LCR_PARITY)
serper |= (SERPER_PARENB);
custom.serper = serper;
amiga_custom.serper = serper;
mb();
}
@ -775,10 +736,10 @@ static void rs_flush_chars(struct tty_struct *tty)
local_irq_save(flags);
info->IER |= UART_IER_THRI;
custom.intena = IF_SETCLR | IF_TBE;
amiga_custom.intena = IF_SETCLR | IF_TBE;
mb();
/* set a pending Tx Interrupt, transmitter should restart now */
custom.intreq = IF_SETCLR | IF_TBE;
amiga_custom.intreq = IF_SETCLR | IF_TBE;
mb();
local_irq_restore(flags);
}
@ -817,10 +778,10 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count
&& !(info->IER & UART_IER_THRI)) {
info->IER |= UART_IER_THRI;
local_irq_disable();
custom.intena = IF_SETCLR | IF_TBE;
amiga_custom.intena = IF_SETCLR | IF_TBE;
mb();
/* set a pending Tx Interrupt, transmitter should restart now */
custom.intreq = IF_SETCLR | IF_TBE;
amiga_custom.intreq = IF_SETCLR | IF_TBE;
mb();
local_irq_restore(flags);
}
@ -867,11 +828,11 @@ static void rs_send_xchar(struct tty_struct *tty, char ch)
/* Check this ! */
local_irq_save(flags);
if(!(custom.intenar & IF_TBE)) {
custom.intena = IF_SETCLR | IF_TBE;
if(!(amiga_custom.intenar & IF_TBE)) {
amiga_custom.intena = IF_SETCLR | IF_TBE;
mb();
/* set a pending Tx Interrupt, transmitter should restart now */
custom.intreq = IF_SETCLR | IF_TBE;
amiga_custom.intreq = IF_SETCLR | IF_TBE;
mb();
}
local_irq_restore(flags);
@ -948,7 +909,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_struct *ss)
ss->line = tty->index;
ss->port = state->port;
ss->flags = state->tport.flags;
ss->xmit_fifo_size = state->xmit_fifo_size;
ss->xmit_fifo_size = XMIT_FIFO_SIZE;
ss->baud_base = state->baud_base;
ss->close_delay = close_delay;
ss->closing_wait = closing_wait;
@ -969,7 +930,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
change_spd = ((ss->flags ^ port->flags) & ASYNC_SPD_MASK) ||
ss->custom_divisor != state->custom_divisor;
if (ss->irq || ss->port != state->port ||
ss->xmit_fifo_size != state->xmit_fifo_size) {
ss->xmit_fifo_size != XMIT_FIFO_SIZE) {
tty_unlock(tty);
return -EINVAL;
}
@ -979,11 +940,10 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
if (closing_wait != ASYNC_CLOSING_WAIT_NONE)
closing_wait = msecs_to_jiffies(closing_wait * 10);
if (!serial_isroot()) {
if (!capable(CAP_SYS_ADMIN)) {
if ((ss->baud_base != state->baud_base) ||
(close_delay != port->close_delay) ||
(closing_wait != port->closing_wait) ||
(ss->xmit_fifo_size != state->xmit_fifo_size) ||
((ss->flags & ~ASYNC_USR_MASK) !=
(port->flags & ~ASYNC_USR_MASK))) {
tty_unlock(tty);
@ -1043,7 +1003,7 @@ static int get_lsr_info(struct serial_state *info, unsigned int __user *value)
unsigned long flags;
local_irq_save(flags);
status = custom.serdatr;
status = amiga_custom.serdatr;
mb();
local_irq_restore(flags);
result = ((status & SDR_TSRE) ? TIOCSER_TEMT : 0);
@ -1105,9 +1065,9 @@ static int rs_break(struct tty_struct *tty, int break_state)
local_irq_save(flags);
if (break_state == -1)
custom.adkcon = AC_SETCLR | AC_UARTBRK;
amiga_custom.adkcon = AC_SETCLR | AC_UARTBRK;
else
custom.adkcon = AC_UARTBRK;
amiga_custom.adkcon = AC_UARTBRK;
mb();
local_irq_restore(flags);
return 0;
@ -1284,10 +1244,10 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
state->read_status_mask &= ~UART_LSR_DR;
if (tty_port_initialized(port)) {
/* disable receive interrupts */
custom.intena = IF_RBF;
amiga_custom.intena = IF_RBF;
mb();
/* clear any pending receive interrupt */
custom.intreq = IF_RBF;
amiga_custom.intreq = IF_RBF;
mb();
/*
@ -1315,9 +1275,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
unsigned long orig_jiffies, char_time;
int lsr;
if (info->xmit_fifo_size == 0)
return; /* Just in case.... */
orig_jiffies = jiffies;
/*
@ -1328,7 +1285,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
* Note: we have to use pretty tight timings here to satisfy
* the NIST-PCTS.
*/
char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
char_time = (info->timeout - HZ/50) / XMIT_FIFO_SIZE;
char_time = char_time / 5;
if (char_time == 0)
char_time = 1;
@ -1349,7 +1306,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
printk("jiff=%lu...", jiffies);
#endif
while(!((lsr = custom.serdatr) & SDR_TSRE)) {
while(!((lsr = amiga_custom.serdatr) & SDR_TSRE)) {
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
printk("serdatr = %d (jiff=%lu)...", lsr, jiffies);
#endif
@ -1389,14 +1346,14 @@ static void rs_hangup(struct tty_struct *tty)
*/
static int rs_open(struct tty_struct *tty, struct file * filp)
{
struct serial_state *info = rs_table + tty->index;
struct tty_port *port = &info->tport;
struct tty_port *port = tty->port;
struct serial_state *info = container_of(port, struct serial_state,
tport);
int retval;
port->count++;
port->tty = tty;
tty->driver_data = info;
tty->port = port;
retval = startup(tty, info);
if (retval) {
@ -1461,8 +1418,8 @@ static inline void line_info(struct seq_file *m, int line,
static int rs_proc_show(struct seq_file *m, void *v)
{
seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version);
line_info(m, 0, &rs_table[0]);
seq_printf(m, "serinfo:1.0 driver:4.30\n");
line_info(m, 0, &serial_state);
return 0;
}
@ -1474,17 +1431,6 @@ static int rs_proc_show(struct seq_file *m, void *v)
* ---------------------------------------------------------------------
*/
/*
* This routine prints out the appropriate serial driver version
* number, and identifies which options were configured into this
* driver.
*/
static void show_serial_version(void)
{
printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
}
static const struct tty_operations serial_ops = {
.open = rs_open,
.close = rs_close,
@ -1543,52 +1489,43 @@ static const struct tty_port_operations amiga_port_ops = {
*/
static int __init amiga_serial_probe(struct platform_device *pdev)
{
struct serial_state *state = &serial_state;
struct tty_driver *driver;
unsigned long flags;
struct serial_state * state;
int error;
serial_driver = alloc_tty_driver(NR_PORTS);
if (!serial_driver)
return -ENOMEM;
show_serial_version();
driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
if (IS_ERR(driver))
return PTR_ERR(driver);
/* Initialize the tty_driver structure */
serial_driver->driver_name = "amiserial";
serial_driver->name = "ttyS";
serial_driver->major = TTY_MAJOR;
serial_driver->minor_start = 64;
serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
serial_driver->subtype = SERIAL_TYPE_NORMAL;
serial_driver->init_termios = tty_std_termios;
serial_driver->init_termios.c_cflag =
driver->driver_name = "amiserial";
driver->name = "ttyS";
driver->major = TTY_MAJOR;
driver->minor_start = 64;
driver->type = TTY_DRIVER_TYPE_SERIAL;
driver->subtype = SERIAL_TYPE_NORMAL;
driver->init_termios = tty_std_termios;
driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
serial_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(serial_driver, &serial_ops);
tty_set_operations(driver, &serial_ops);
state = rs_table;
state->port = (int)&custom.serdatr; /* Just to give it a value */
state->custom_divisor = 0;
state->icount.cts = state->icount.dsr =
state->icount.rng = state->icount.dcd = 0;
state->icount.rx = state->icount.tx = 0;
state->icount.frame = state->icount.parity = 0;
state->icount.overrun = state->icount.brk = 0;
memset(state, 0, sizeof(*state));
state->port = (int)&amiga_custom.serdatr; /* Just to give it a value */
tty_port_init(&state->tport);
state->tport.ops = &amiga_port_ops;
tty_port_link_device(&state->tport, serial_driver, 0);
tty_port_link_device(&state->tport, driver, 0);
error = tty_register_driver(serial_driver);
error = tty_register_driver(driver);
if (error)
goto fail_put_tty_driver;
goto fail_tty_driver_kref_put;
printk(KERN_INFO "ttyS0 is the amiga builtin serial port\n");
/* Hardware set up */
state->baud_base = amiga_colorclock;
state->xmit_fifo_size = 1;
/* set ISRs, and then disable the rx interrupts */
error = request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state);
@ -1603,11 +1540,11 @@ static int __init amiga_serial_probe(struct platform_device *pdev)
local_irq_save(flags);
/* turn off Rx and Tx interrupts */
custom.intena = IF_RBF | IF_TBE;
amiga_custom.intena = IF_RBF | IF_TBE;
mb();
/* clear any pending interrupt */
custom.intreq = IF_RBF | IF_TBE;
amiga_custom.intreq = IF_RBF | IF_TBE;
mb();
local_irq_restore(flags);
@ -1621,15 +1558,17 @@ static int __init amiga_serial_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, state);
serial_driver = driver;
return 0;
fail_free_irq:
free_irq(IRQ_AMIGA_TBE, state);
fail_unregister:
tty_unregister_driver(serial_driver);
fail_put_tty_driver:
tty_unregister_driver(driver);
fail_tty_driver_kref_put:
tty_port_destroy(&state->tport);
put_tty_driver(serial_driver);
tty_driver_kref_put(driver);
return error;
}
@ -1637,9 +1576,8 @@ static int __exit amiga_serial_remove(struct platform_device *pdev)
{
struct serial_state *state = platform_get_drvdata(pdev);
/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
tty_unregister_driver(serial_driver);
put_tty_driver(serial_driver);
tty_driver_kref_put(serial_driver);
tty_port_destroy(&state->tport);
free_irq(IRQ_AMIGA_TBE, state);
@ -1668,8 +1606,8 @@ module_platform_driver_probe(amiga_serial_driver, amiga_serial_probe);
static void amiga_serial_putc(char c)
{
custom.serdat = (unsigned char)c | 0x100;
while (!(custom.serdatr & 0x2000))
amiga_custom.serdat = (unsigned char)c | 0x100;
while (!(amiga_custom.serdatr & 0x2000))
barrier();
}
@ -1682,9 +1620,9 @@ static void amiga_serial_putc(char c)
static void serial_console_write(struct console *co, const char *s,
unsigned count)
{
unsigned short intena = custom.intenar;
unsigned short intena = amiga_custom.intenar;
custom.intena = IF_TBE;
amiga_custom.intena = IF_TBE;
while (count--) {
if (*s == '\n')
@ -1692,7 +1630,7 @@ static void serial_console_write(struct console *co, const char *s,
amiga_serial_putc(*s++);
}
custom.intena = IF_SETCLR | (intena & IF_TBE);
amiga_custom.intena = IF_SETCLR | (intena & IF_TBE);
}
static struct tty_driver *serial_console_device(struct console *c, int *index)

View File

@ -751,6 +751,7 @@ static struct platform_driver ehv_bc_tty_driver = {
*/
static int __init ehv_bc_init(void)
{
struct tty_driver *driver;
struct device_node *np;
unsigned int count = 0; /* Number of elements in bcs[] */
int ret;
@ -773,26 +774,28 @@ static int __init ehv_bc_init(void)
if (!bcs)
return -ENOMEM;
ehv_bc_driver = alloc_tty_driver(count);
if (!ehv_bc_driver) {
ret = -ENOMEM;
driver = tty_alloc_driver(count, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(driver)) {
ret = PTR_ERR(driver);
goto err_free_bcs;
}
ehv_bc_driver->driver_name = "ehv-bc";
ehv_bc_driver->name = ehv_bc_console.name;
ehv_bc_driver->type = TTY_DRIVER_TYPE_CONSOLE;
ehv_bc_driver->subtype = SYSTEM_TYPE_CONSOLE;
ehv_bc_driver->init_termios = tty_std_termios;
ehv_bc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
tty_set_operations(ehv_bc_driver, &ehv_bc_ops);
driver->driver_name = "ehv-bc";
driver->name = ehv_bc_console.name;
driver->type = TTY_DRIVER_TYPE_CONSOLE;
driver->subtype = SYSTEM_TYPE_CONSOLE;
driver->init_termios = tty_std_termios;
tty_set_operations(driver, &ehv_bc_ops);
ret = tty_register_driver(ehv_bc_driver);
ret = tty_register_driver(driver);
if (ret) {
pr_err("ehv-bc: could not register tty driver (ret=%i)\n", ret);
goto err_put_tty_driver;
goto err_tty_driver_kref_put;
}
ehv_bc_driver = driver;
ret = platform_driver_register(&ehv_bc_tty_driver);
if (ret) {
pr_err("ehv-bc: could not register platform driver (ret=%i)\n",
@ -803,9 +806,10 @@ static int __init ehv_bc_init(void)
return 0;
err_deregister_tty_driver:
tty_unregister_driver(ehv_bc_driver);
err_put_tty_driver:
put_tty_driver(ehv_bc_driver);
ehv_bc_driver = NULL;
tty_unregister_driver(driver);
err_tty_driver_kref_put:
tty_driver_kref_put(driver);
err_free_bcs:
kfree(bcs);

View File

@ -253,18 +253,18 @@ static int goldfish_tty_create_driver(void)
ret = -ENOMEM;
goto err_alloc_goldfish_ttys_failed;
}
tty = alloc_tty_driver(goldfish_tty_line_count);
if (tty == NULL) {
ret = -ENOMEM;
goto err_alloc_tty_driver_failed;
tty = tty_alloc_driver(goldfish_tty_line_count,
TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(tty)) {
ret = PTR_ERR(tty);
goto err_tty_alloc_driver_failed;
}
tty->driver_name = "goldfish";
tty->name = "ttyGF";
tty->type = TTY_DRIVER_TYPE_SERIAL;
tty->subtype = SERIAL_TYPE_NORMAL;
tty->init_termios = tty_std_termios;
tty->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV;
tty_set_operations(tty, &goldfish_tty_ops);
ret = tty_register_driver(tty);
if (ret)
@ -274,8 +274,8 @@ static int goldfish_tty_create_driver(void)
return 0;
err_tty_register_driver_failed:
put_tty_driver(tty);
err_alloc_tty_driver_failed:
tty_driver_kref_put(tty);
err_tty_alloc_driver_failed:
kfree(goldfish_ttys);
goldfish_ttys = NULL;
err_alloc_goldfish_ttys_failed:
@ -285,7 +285,7 @@ err_alloc_goldfish_ttys_failed:
static void goldfish_tty_delete_driver(void)
{
tty_unregister_driver(goldfish_tty_driver);
put_tty_driver(goldfish_tty_driver);
tty_driver_kref_put(goldfish_tty_driver);
goldfish_tty_driver = NULL;
kfree(goldfish_ttys);
goldfish_ttys = NULL;

View File

@ -1021,9 +1021,10 @@ static int hvc_init(void)
int err;
/* We need more than hvc_count adapters due to hotplug additions. */
drv = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
if (!drv) {
err = -ENOMEM;
drv = tty_alloc_driver(HVC_ALLOC_TTY_ADAPTERS, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_RESET_TERMIOS);
if (IS_ERR(drv)) {
err = PTR_ERR(drv);
goto out;
}
@ -1033,7 +1034,6 @@ static int hvc_init(void)
drv->minor_start = HVC_MINOR;
drv->type = TTY_DRIVER_TYPE_SYSTEM;
drv->init_termios = tty_std_termios;
drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
tty_set_operations(drv, &hvc_ops);
/* Always start the kthread because there can be hotplug vty adapters
@ -1063,7 +1063,7 @@ stop_thread:
kthread_stop(hvc_task);
hvc_task = NULL;
put_tty:
put_tty_driver(drv);
tty_driver_kref_put(drv);
out:
return err;
}

View File

@ -86,7 +86,11 @@ static int __write_console(struct xencons_info *xencons,
cons = intf->out_cons;
prod = intf->out_prod;
mb(); /* update queue values before going on */
BUG_ON((prod - cons) > sizeof(intf->out));
if ((prod - cons) > sizeof(intf->out)) {
pr_err_once("xencons: Illegal ring page indices");
return -EINVAL;
}
while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
@ -114,7 +118,10 @@ static int domU_write_console(uint32_t vtermno, const char *data, int len)
*/
while (len) {
int sent = __write_console(cons, data, len);
if (sent < 0)
return sent;
data += sent;
len -= sent;
@ -138,7 +145,11 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len)
cons = intf->in_cons;
prod = intf->in_prod;
mb(); /* get pointers before reading ring */
BUG_ON((prod - cons) > sizeof(intf->in));
if ((prod - cons) > sizeof(intf->in)) {
pr_err_once("xencons: Illegal ring page indices");
return -EINVAL;
}
while (cons != prod && recv < len)
buf[recv++] = intf->in[MASK_XENCONS_IDX(cons++, intf->in)];

View File

@ -1445,10 +1445,11 @@ static int hvcs_initialize(void)
} else
num_ttys_to_alloc = hvcs_parm_num_devs;
hvcs_tty_driver = alloc_tty_driver(num_ttys_to_alloc);
if (!hvcs_tty_driver) {
hvcs_tty_driver = tty_alloc_driver(num_ttys_to_alloc,
TTY_DRIVER_REAL_RAW);
if (IS_ERR(hvcs_tty_driver)) {
mutex_unlock(&hvcs_init_mutex);
return -ENOMEM;
return PTR_ERR(hvcs_tty_driver);
}
if (hvcs_alloc_index_list(num_ttys_to_alloc)) {
@ -1473,7 +1474,6 @@ static int hvcs_initialize(void)
* throw us into a horrible recursive echo-echo-echo loop.
*/
hvcs_tty_driver->init_termios = hvcs_tty_termios;
hvcs_tty_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(hvcs_tty_driver, &hvcs_ops);
@ -1509,7 +1509,7 @@ buff_alloc_fail:
register_fail:
hvcs_free_index_list();
index_fail:
put_tty_driver(hvcs_tty_driver);
tty_driver_kref_put(hvcs_tty_driver);
hvcs_tty_driver = NULL;
mutex_unlock(&hvcs_init_mutex);
return rc;
@ -1562,7 +1562,7 @@ static void __exit hvcs_module_exit(void)
hvcs_free_index_list();
put_tty_driver(hvcs_tty_driver);
tty_driver_kref_put(hvcs_tty_driver);
printk(KERN_INFO "HVCS: driver module removed.\n");
}

View File

@ -1038,29 +1038,29 @@ static const struct tty_operations hvsi_ops = {
static int __init hvsi_init(void)
{
int i;
struct tty_driver *driver;
int i, ret;
hvsi_driver = alloc_tty_driver(hvsi_count);
if (!hvsi_driver)
return -ENOMEM;
driver = tty_alloc_driver(hvsi_count, TTY_DRIVER_REAL_RAW);
if (IS_ERR(driver))
return PTR_ERR(driver);
hvsi_driver->driver_name = "hvsi";
hvsi_driver->name = "hvsi";
hvsi_driver->major = HVSI_MAJOR;
hvsi_driver->minor_start = HVSI_MINOR;
hvsi_driver->type = TTY_DRIVER_TYPE_SYSTEM;
hvsi_driver->init_termios = tty_std_termios;
hvsi_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
hvsi_driver->init_termios.c_ispeed = 9600;
hvsi_driver->init_termios.c_ospeed = 9600;
hvsi_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(hvsi_driver, &hvsi_ops);
driver->driver_name = "hvsi";
driver->name = "hvsi";
driver->major = HVSI_MAJOR;
driver->minor_start = HVSI_MINOR;
driver->type = TTY_DRIVER_TYPE_SYSTEM;
driver->init_termios = tty_std_termios;
driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
driver->init_termios.c_ispeed = 9600;
driver->init_termios.c_ospeed = 9600;
tty_set_operations(driver, &hvsi_ops);
for (i=0; i < hvsi_count; i++) {
struct hvsi_struct *hp = &hvsi_ports[i];
int ret = 1;
tty_port_link_device(&hp->port, hvsi_driver, i);
tty_port_link_device(&hp->port, driver, i);
ret = request_irq(hp->virq, hvsi_interrupt, 0, "hvsi", hp);
if (ret)
@ -1069,12 +1069,27 @@ static int __init hvsi_init(void)
}
hvsi_wait = wait_for_state; /* irqs active now */
if (tty_register_driver(hvsi_driver))
panic("Couldn't register hvsi console driver\n");
ret = tty_register_driver(driver);
if (ret) {
pr_err("Couldn't register hvsi console driver\n");
goto err_free_irq;
}
hvsi_driver = driver;
printk(KERN_DEBUG "HVSI: registered %i devices\n", hvsi_count);
return 0;
err_free_irq:
hvsi_wait = poll_for_state;
for (i = 0; i < hvsi_count; i++) {
struct hvsi_struct *hp = &hvsi_ports[i];
free_irq(hp->virq, hp);
}
tty_driver_kref_put(driver);
return ret;
}
device_initcall(hvsi_init);

View File

@ -564,9 +564,10 @@ int ipwireless_tty_init(void)
{
int result;
ipw_tty_driver = alloc_tty_driver(IPWIRELESS_PCMCIA_MINORS);
if (!ipw_tty_driver)
return -ENOMEM;
ipw_tty_driver = tty_alloc_driver(IPWIRELESS_PCMCIA_MINORS,
TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(ipw_tty_driver))
return PTR_ERR(ipw_tty_driver);
ipw_tty_driver->driver_name = IPWIRELESS_PCCARD_NAME;
ipw_tty_driver->name = "ttyIPWp";
@ -574,7 +575,6 @@ int ipwireless_tty_init(void)
ipw_tty_driver->minor_start = IPWIRELESS_PCMCIA_START;
ipw_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
ipw_tty_driver->subtype = SERIAL_TYPE_NORMAL;
ipw_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
ipw_tty_driver->init_termios = tty_std_termios;
ipw_tty_driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
@ -585,7 +585,7 @@ int ipwireless_tty_init(void)
if (result) {
printk(KERN_ERR IPWIRELESS_PCCARD_NAME
": failed to register tty driver\n");
put_tty_driver(ipw_tty_driver);
tty_driver_kref_put(ipw_tty_driver);
return result;
}
@ -595,7 +595,7 @@ int ipwireless_tty_init(void)
void ipwireless_tty_release(void)
{
tty_unregister_driver(ipw_tty_driver);
put_tty_driver(ipw_tty_driver);
tty_driver_kref_put(ipw_tty_driver);
}
int ipwireless_tty_is_modem(struct ipw_tty *tty)

View File

@ -1042,7 +1042,7 @@ err_destroy_ports:
dport = &priv->ports[nport];
tty_port_destroy(&dport->port);
}
put_tty_driver(priv->driver);
tty_driver_kref_put(priv->driver);
return ret;
}

View File

@ -1053,7 +1053,7 @@ static int __init moxa_init(void)
if (tty_register_driver(moxaDriver)) {
printk(KERN_ERR "can't register MOXA Smartio tty driver!\n");
put_tty_driver(moxaDriver);
tty_driver_kref_put(moxaDriver);
return -1;
}
@ -1119,7 +1119,7 @@ static void __exit moxa_exit(void)
del_timer_sync(&moxaTimer);
tty_unregister_driver(moxaDriver);
put_tty_driver(moxaDriver);
tty_driver_kref_put(moxaDriver);
}
module_init(moxa_init);
@ -2034,10 +2034,10 @@ static int moxa_get_serial_info(struct tty_struct *tty,
if (!info)
return -ENODEV;
mutex_lock(&info->port.mutex);
ss->type = info->type,
ss->line = info->port.tty->index,
ss->flags = info->port.flags,
ss->baud_base = 921600,
ss->type = info->type;
ss->line = info->port.tty->index;
ss->flags = info->port.flags;
ss->baud_base = 921600;
ss->close_delay = jiffies_to_msecs(info->port.close_delay) / 10;
mutex_unlock(&info->port.mutex);
return 0;

View File

@ -1039,12 +1039,12 @@ static int mxser_get_serial_info(struct tty_struct *tty,
if (closing_wait != ASYNC_CLOSING_WAIT_NONE)
closing_wait = jiffies_to_msecs(closing_wait) / 10;
ss->type = info->type,
ss->line = tty->index,
ss->port = info->ioaddr,
ss->irq = info->board->irq,
ss->flags = info->port.flags,
ss->baud_base = MXSER_BAUD_BASE,
ss->type = info->type;
ss->line = tty->index;
ss->port = info->ioaddr;
ss->irq = info->board->irq;
ss->flags = info->port.flags;
ss->baud_base = MXSER_BAUD_BASE;
ss->close_delay = close_delay;
ss->closing_wait = closing_wait;
ss->custom_divisor = MXSER_CUSTOM_DIVISOR,
@ -1976,9 +1976,10 @@ static int __init mxser_module_init(void)
{
int retval;
mxvar_sdriver = alloc_tty_driver(MXSER_PORTS);
if (!mxvar_sdriver)
return -ENOMEM;
mxvar_sdriver = tty_alloc_driver(MXSER_PORTS, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(mxvar_sdriver))
return PTR_ERR(mxvar_sdriver);
/* Initialize the tty_driver structure */
mxvar_sdriver->name = "ttyMI";
@ -1988,7 +1989,6 @@ static int __init mxser_module_init(void)
mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL;
mxvar_sdriver->init_termios = tty_std_termios;
mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_DYNAMIC_DEV;
tty_set_operations(mxvar_sdriver, &mxser_ops);
retval = tty_register_driver(mxvar_sdriver);
@ -2008,7 +2008,7 @@ static int __init mxser_module_init(void)
err_unr:
tty_unregister_driver(mxvar_sdriver);
err_put:
put_tty_driver(mxvar_sdriver);
tty_driver_kref_put(mxvar_sdriver);
return retval;
}
@ -2016,7 +2016,7 @@ static void __exit mxser_module_exit(void)
{
pci_unregister_driver(&mxser_driver);
tty_unregister_driver(mxvar_sdriver);
put_tty_driver(mxvar_sdriver);
tty_driver_kref_put(mxvar_sdriver);
}
module_init(mxser_module_init);

View File

@ -3252,10 +3252,11 @@ static int __init gsm_init(void)
return status;
}
gsm_tty_driver = alloc_tty_driver(256);
if (!gsm_tty_driver) {
gsm_tty_driver = tty_alloc_driver(256, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
if (IS_ERR(gsm_tty_driver)) {
pr_err("gsm_init: tty allocation failed.\n");
status = -ENOMEM;
status = PTR_ERR(gsm_tty_driver);
goto err_unreg_ldisc;
}
gsm_tty_driver->driver_name = "gsmtty";
@ -3264,8 +3265,6 @@ static int __init gsm_init(void)
gsm_tty_driver->minor_start = 0;
gsm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
gsm_tty_driver->subtype = SERIAL_TYPE_NORMAL;
gsm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV
| TTY_DRIVER_HARDWARE_BREAK;
gsm_tty_driver->init_termios = tty_std_termios;
/* Fixme */
gsm_tty_driver->init_termios.c_lflag &= ~ECHO;
@ -3280,7 +3279,7 @@ static int __init gsm_init(void)
gsm_tty_driver->major, gsm_tty_driver->minor_start);
return 0;
err_put_driver:
put_tty_driver(gsm_tty_driver);
tty_driver_kref_put(gsm_tty_driver);
err_unreg_ldisc:
tty_unregister_ldisc(&tty_ldisc_packet);
return status;
@ -3290,7 +3289,7 @@ static void __exit gsm_exit(void)
{
tty_unregister_ldisc(&tty_ldisc_packet);
tty_unregister_driver(gsm_tty_driver);
put_tty_driver(gsm_tty_driver);
tty_driver_kref_put(gsm_tty_driver);
}
module_init(gsm_init);

View File

@ -1824,16 +1824,16 @@ static __init int nozomi_init(void)
{
int ret;
ntty_driver = alloc_tty_driver(NTTY_TTY_MAXMINORS);
if (!ntty_driver)
return -ENOMEM;
ntty_driver = tty_alloc_driver(NTTY_TTY_MAXMINORS, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(ntty_driver))
return PTR_ERR(ntty_driver);
ntty_driver->driver_name = NOZOMI_NAME_TTY;
ntty_driver->name = "noz";
ntty_driver->major = 0;
ntty_driver->type = TTY_DRIVER_TYPE_SERIAL;
ntty_driver->subtype = SERIAL_TYPE_NORMAL;
ntty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
ntty_driver->init_termios = tty_std_termios;
ntty_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | \
HUPCL | CLOCAL;
@ -1857,7 +1857,7 @@ static __init int nozomi_init(void)
unr_tty:
tty_unregister_driver(ntty_driver);
free_tty:
put_tty_driver(ntty_driver);
tty_driver_kref_put(ntty_driver);
return ret;
}
@ -1865,7 +1865,7 @@ static __exit void nozomi_exit(void)
{
pci_unregister_driver(&nozomi_driver);
tty_unregister_driver(ntty_driver);
put_tty_driver(ntty_driver);
tty_driver_kref_put(ntty_driver);
}
module_init(nozomi_init);

View File

@ -562,23 +562,45 @@ struct acpi_serdev_lookup {
int index;
};
/**
* serdev_acpi_get_uart_resource - Gets UARTSerialBus resource if type matches
* @ares: ACPI resource
* @uart: Pointer to UARTSerialBus resource will be returned here
*
* Checks if the given ACPI resource is of type UARTSerialBus.
* In this case, returns a pointer to it to the caller.
*
* Return: True if resource type is of UARTSerialBus, otherwise false.
*/
bool serdev_acpi_get_uart_resource(struct acpi_resource *ares,
struct acpi_resource_uart_serialbus **uart)
{
struct acpi_resource_uart_serialbus *sb;
if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
return false;
sb = &ares->data.uart_serial_bus;
if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_UART)
return false;
*uart = sb;
return true;
}
EXPORT_SYMBOL_GPL(serdev_acpi_get_uart_resource);
static int acpi_serdev_parse_resource(struct acpi_resource *ares, void *data)
{
struct acpi_serdev_lookup *lookup = data;
struct acpi_resource_uart_serialbus *sb;
acpi_status status;
if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
return 1;
if (ares->data.common_serial_bus.type != ACPI_RESOURCE_SERIAL_TYPE_UART)
if (!serdev_acpi_get_uart_resource(ares, &sb))
return 1;
if (lookup->index != -1 && lookup->n++ != lookup->index)
return 1;
sb = &ares->data.uart_serial_bus;
status = acpi_get_handle(lookup->device_handle,
sb->resource_source.string_ptr,
&lookup->controller_handle);
@ -586,7 +608,7 @@ static int acpi_serdev_parse_resource(struct acpi_resource *ares, void *data)
return 1;
/*
* NOTE: Ideally, we would also want to retreive other properties here,
* NOTE: Ideally, we would also want to retrieve other properties here,
* once setting them before opening the device is supported by serdev.
*/

View File

@ -941,7 +941,7 @@ static int brcmuart_probe(struct platform_device *pdev)
struct clk *baud_mux_clk;
struct uart_8250_port up;
struct resource *irq;
void __iomem *membase = 0;
void __iomem *membase = NULL;
resource_size_t mapbase = 0;
u32 clk_rate = 0;
int ret;

View File

@ -114,6 +114,7 @@ struct exar8250;
struct exar8250_platform {
int (*rs485_config)(struct uart_port *, struct serial_rs485 *);
int (*register_gpio)(struct pci_dev *, struct uart_8250_port *);
void (*unregister_gpio)(struct uart_8250_port *);
};
/**
@ -352,9 +353,8 @@ static void setup_gpio(struct pci_dev *pcidev, u8 __iomem *p)
writeb(0x00, p + UART_EXAR_MPIOOD_15_8);
}
static void *
__xr17v35x_register_gpio(struct pci_dev *pcidev,
const struct software_node *node)
static struct platform_device *__xr17v35x_register_gpio(struct pci_dev *pcidev,
const struct software_node *node)
{
struct platform_device *pdev;
@ -374,6 +374,12 @@ __xr17v35x_register_gpio(struct pci_dev *pcidev,
return pdev;
}
static void __xr17v35x_unregister_gpio(struct platform_device *pdev)
{
device_remove_software_node(&pdev->dev);
platform_device_unregister(pdev);
}
static const struct property_entry exar_gpio_properties[] = {
PROPERTY_ENTRY_U32("exar,first-pin", 0),
PROPERTY_ENTRY_U32("ngpios", 16),
@ -384,8 +390,7 @@ static const struct software_node exar_gpio_node = {
.properties = exar_gpio_properties,
};
static int xr17v35x_register_gpio(struct pci_dev *pcidev,
struct uart_8250_port *port)
static int xr17v35x_register_gpio(struct pci_dev *pcidev, struct uart_8250_port *port)
{
if (pcidev->vendor == PCI_VENDOR_ID_EXAR)
port->port.private_data =
@ -394,6 +399,15 @@ static int xr17v35x_register_gpio(struct pci_dev *pcidev,
return 0;
}
static void xr17v35x_unregister_gpio(struct uart_8250_port *port)
{
if (!port->port.private_data)
return;
__xr17v35x_unregister_gpio(port->port.private_data);
port->port.private_data = NULL;
}
static int generic_rs485_config(struct uart_port *port,
struct serial_rs485 *rs485)
{
@ -419,6 +433,7 @@ static int generic_rs485_config(struct uart_port *port,
static const struct exar8250_platform exar8250_default_platform = {
.register_gpio = xr17v35x_register_gpio,
.unregister_gpio = xr17v35x_unregister_gpio,
.rs485_config = generic_rs485_config,
};
@ -484,6 +499,7 @@ static int iot2040_register_gpio(struct pci_dev *pcidev,
static const struct exar8250_platform iot2040_platform = {
.rs485_config = iot2040_rs485_config,
.register_gpio = iot2040_register_gpio,
.unregister_gpio = xr17v35x_unregister_gpio,
};
/*
@ -555,17 +571,11 @@ pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,
static void pci_xr17v35x_exit(struct pci_dev *pcidev)
{
const struct exar8250_platform *platform = exar_get_platform();
struct exar8250 *priv = pci_get_drvdata(pcidev);
struct uart_8250_port *port = serial8250_get_port(priv->line[0]);
struct platform_device *pdev;
pdev = port->port.private_data;
if (!pdev)
return;
device_remove_software_node(&pdev->dev);
platform_device_unregister(pdev);
port->port.private_data = NULL;
platform->unregister_gpio(port);
}
static inline void exar_misc_clear(struct exar8250 *priv)

View File

@ -209,16 +209,14 @@ static int ingenic_uart_probe(struct platform_device *pdev)
struct uart_8250_port uart = {};
struct ingenic_uart_data *data;
const struct ingenic_uart_config *cdata;
const struct of_device_id *match;
struct resource *regs;
int irq, err, line;
match = of_match_device(of_match, &pdev->dev);
if (!match) {
cdata = of_device_get_match_data(&pdev->dev);
if (!cdata) {
dev_err(&pdev->dev, "Error: No device match found\n");
return -ENODEV;
}
cdata = match->data;
irq = platform_get_irq(pdev, 0);
if (irq < 0)

View File

@ -158,6 +158,16 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
{
struct uart_8250_dma *dma = &lpss->data.dma;
struct uart_8250_port *up = up_to_u8250p(port);
/*
* This simply makes the checks in the 8250_port to try the DMA
* channel request which in turn uses the magic of ACPI tables
* parsing (see drivers/dma/acpi-dma.c for the details) and
* matching with the registered General Purpose DMA controllers.
*/
up->dma = dma;
return 0;
}

View File

@ -538,7 +538,7 @@ static void omap_8250_pm(struct uart_port *port, unsigned int state,
static void omap_serial_fill_features_erratas(struct uart_8250_port *up,
struct omap8250_priv *priv)
{
const struct soc_device_attribute k3_soc_devices[] = {
static const struct soc_device_attribute k3_soc_devices[] = {
{ .family = "AM65X", },
{ .family = "J721E", .revision = "SR1.0" },
{ /* sentinel */ }
@ -617,7 +617,7 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)
struct uart_port *port = dev_id;
struct omap8250_priv *priv = port->private_data;
struct uart_8250_port *up = up_to_u8250p(port);
unsigned int iir;
unsigned int iir, lsr;
int ret;
#ifdef CONFIG_SERIAL_8250_DMA
@ -628,6 +628,7 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)
#endif
serial8250_rpm_get(up);
lsr = serial_port_in(port, UART_LSR);
iir = serial_port_in(port, UART_IIR);
ret = serial8250_handle_irq(port, iir);
@ -642,6 +643,24 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)
serial_port_in(port, UART_RX);
}
/* Stop processing interrupts on input overrun */
if ((lsr & UART_LSR_OE) && up->overrun_backoff_time_ms > 0) {
unsigned long delay;
up->ier = port->serial_in(port, UART_IER);
if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) {
port->ops->stop_rx(port);
} else {
/* Keep restarting the timer until
* the input overrun subsides.
*/
cancel_delayed_work(&up->overrun_backoff);
}
delay = msecs_to_jiffies(up->overrun_backoff_time_ms);
schedule_delayed_work(&up->overrun_backoff, delay);
}
serial8250_rpm_put(up);
return IRQ_RETVAL(ret);
@ -1353,6 +1372,10 @@ static int omap8250_probe(struct platform_device *pdev)
}
}
if (of_property_read_u32(np, "overrun-throttle-ms",
&up.overrun_backoff_time_ms) != 0)
up.overrun_backoff_time_ms = 0;
priv->wakeirq = irq_of_parse_and_map(np, 1);
pdata = of_device_get_match_data(&pdev->dev);

View File

@ -87,7 +87,7 @@ static void moan_device(const char *str, struct pci_dev *dev)
static int
setup_port(struct serial_private *priv, struct uart_8250_port *port,
int bar, int offset, int regshift)
u8 bar, unsigned int offset, int regshift)
{
struct pci_dev *dev = priv->dev;

View File

@ -13,6 +13,7 @@
#include <linux/pnp.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/property.h>
#include <linux/serial_core.h>
#include <linux/bitops.h>
@ -475,6 +476,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
uart.port.flags |= UPF_SHARE_IRQ;
uart.port.uartclk = 1843200;
device_property_read_u32(&dev->dev, "clock-frequency", &uart.port.uartclk);
uart.port.dev = &dev->dev;
line = serial8250_register_8250_port(&uart);

View File

@ -122,7 +122,8 @@ static const struct serial8250_config uart_config[] = {
.name = "16C950/954",
.fifo_size = 128,
.tx_loadsz = 128,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01,
.rxtrig_bytes = {16, 32, 112, 120},
/* UART_CAP_EFR breaks billionon CF bluetooth card. */
.flags = UART_CAP_FIFO | UART_CAP_SLEEP,
},

View File

@ -363,7 +363,7 @@ config SERIAL_8250_BCM2835AUX
config SERIAL_8250_FSL
bool
depends on SERIAL_8250_CONSOLE
default PPC || ARM || ARM64
default PPC || ARM || ARM64 || COMPILE_TEST
config SERIAL_8250_DW
tristate "Support for Synopsys DesignWare 8250 quirks"
@ -375,7 +375,8 @@ config SERIAL_8250_DW
config SERIAL_8250_EM
tristate "Support for Emma Mobile integrated serial port"
depends on SERIAL_8250 && ARM && HAVE_CLK
depends on SERIAL_8250 && HAVE_CLK
depends on ARM || COMPILE_TEST
help
Selecting this option will add support for the integrated serial
port hardware found on the Emma Mobile line of processors.
@ -383,7 +384,8 @@ config SERIAL_8250_EM
config SERIAL_8250_IOC3
tristate "SGI IOC3 8250 UART support"
depends on SGI_MFD_IOC3 && SERIAL_8250
depends on SERIAL_8250
depends on SGI_MFD_IOC3 || COMPILE_TEST
select SERIAL_8250_EXTENDED
select SERIAL_8250_SHARE_IRQ
help
@ -495,7 +497,7 @@ config SERIAL_8250_MID
config SERIAL_8250_PXA
tristate "PXA serial port support"
depends on SERIAL_8250
depends on ARCH_PXA || ARCH_MMP
depends on ARCH_PXA || ARCH_MMP || COMPILE_TEST
help
If you have a machine based on an Intel XScale PXA2xx CPU you can
enable its onboard serial ports by enabling this option. The option is

View File

@ -959,7 +959,7 @@ config SERIAL_VT8500_CONSOLE
config SERIAL_OMAP
tristate "OMAP serial port support"
depends on ARCH_OMAP2PLUS || COMPILE_TEST
depends on (ARCH_OMAP2PLUS && !SERIAL_8250_OMAP) || COMPILE_TEST
select SERIAL_CORE
help
If you have a machine based on an Texas Instruments OMAP CPU you
@ -1382,7 +1382,7 @@ config SERIAL_ST_ASC
select SERIAL_CORE
depends on ARM || COMPILE_TEST
help
This driver is for the on-chip Asychronous Serial Controller on
This driver is for the on-chip Asynchronous Serial Controller on
STMicroelectronics STi SoCs.
ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
It support all industry standard baud rates.

View File

@ -265,6 +265,8 @@ struct uart_amba_port {
unsigned int old_cr; /* state during shutdown */
unsigned int fixed_baud; /* vendor-set fixed baud rate */
char type[12];
bool rs485_tx_started;
unsigned int rs485_tx_drain_interval; /* usecs */
#ifdef CONFIG_DMA_ENGINE
/* DMA stuff */
bool using_tx_dma;
@ -275,6 +277,8 @@ struct uart_amba_port {
#endif
};
static unsigned int pl011_tx_empty(struct uart_port *port);
static unsigned int pl011_reg_to_offset(const struct uart_amba_port *uap,
unsigned int reg)
{
@ -1282,6 +1286,42 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
#define pl011_dma_flush_buffer NULL
#endif
static void pl011_rs485_tx_stop(struct uart_amba_port *uap)
{
struct uart_port *port = &uap->port;
int i = 0;
u32 cr;
/* Wait until hardware tx queue is empty */
while (!pl011_tx_empty(port)) {
if (i == port->fifosize) {
dev_warn(port->dev,
"timeout while draining hardware tx queue\n");
break;
}
udelay(uap->rs485_tx_drain_interval);
i++;
}
if (port->rs485.delay_rts_after_send)
mdelay(port->rs485.delay_rts_after_send);
cr = pl011_read(uap, REG_CR);
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
cr &= ~UART011_CR_RTS;
else
cr |= UART011_CR_RTS;
/* Disable the transmitter and reenable the transceiver */
cr &= ~UART011_CR_TXE;
cr |= UART011_CR_RXE;
pl011_write(cr, uap, REG_CR);
uap->rs485_tx_started = false;
}
static void pl011_stop_tx(struct uart_port *port)
{
struct uart_amba_port *uap =
@ -1290,6 +1330,9 @@ static void pl011_stop_tx(struct uart_port *port)
uap->im &= ~UART011_TXIM;
pl011_write(uap->im, uap, REG_IMSC);
pl011_dma_tx_stop(uap);
if ((port->rs485.flags & SER_RS485_ENABLED) && uap->rs485_tx_started)
pl011_rs485_tx_stop(uap);
}
static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
@ -1380,6 +1423,32 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
return true;
}
static void pl011_rs485_tx_start(struct uart_amba_port *uap)
{
struct uart_port *port = &uap->port;
u32 cr;
/* Enable transmitter */
cr = pl011_read(uap, REG_CR);
cr |= UART011_CR_TXE;
/* Disable receiver if half-duplex */
if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
cr &= ~UART011_CR_RXE;
if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
cr &= ~UART011_CR_RTS;
else
cr |= UART011_CR_RTS;
pl011_write(cr, uap, REG_CR);
if (port->rs485.delay_rts_before_send)
mdelay(port->rs485.delay_rts_before_send);
uap->rs485_tx_started = true;
}
/* Returns true if tx interrupts have to be (kept) enabled */
static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
{
@ -1397,6 +1466,10 @@ static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
return false;
}
if ((uap->port.rs485.flags & SER_RS485_ENABLED) &&
!uap->rs485_tx_started)
pl011_rs485_tx_start(uap);
/* If we are using DMA mode, try to send some characters. */
if (pl011_dma_tx_irq(uap))
return true;
@ -1542,6 +1615,9 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
container_of(port, struct uart_amba_port, port);
unsigned int cr;
if (port->rs485.flags & SER_RS485_ENABLED)
mctrl &= ~TIOCM_RTS;
cr = pl011_read(uap, REG_CR);
#define TIOCMBIT(tiocmbit, uartbit) \
@ -1763,7 +1839,17 @@ static int pl011_startup(struct uart_port *port)
/* restore RTS and DTR */
cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
cr |= UART01x_CR_UARTEN | UART011_CR_RXE;
if (port->rs485.flags & SER_RS485_ENABLED) {
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
cr &= ~UART011_CR_RTS;
else
cr |= UART011_CR_RTS;
} else {
cr |= UART011_CR_TXE;
}
pl011_write(cr, uap, REG_CR);
spin_unlock_irq(&uap->port.lock);
@ -1864,6 +1950,9 @@ static void pl011_shutdown(struct uart_port *port)
pl011_dma_shutdown(uap);
if ((port->rs485.flags & SER_RS485_ENABLED) && uap->rs485_tx_started)
pl011_rs485_tx_stop(uap);
free_irq(uap->port.irq, uap);
pl011_disable_uart(uap);
@ -1941,6 +2030,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
unsigned int lcr_h, old_cr;
unsigned long flags;
unsigned int baud, quot, clkdiv;
unsigned int bits;
if (uap->vendor->oversampling)
clkdiv = 8;
@ -1991,6 +2081,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
if (uap->fifosize > 1)
lcr_h |= UART01x_LCRH_FEN;
bits = tty_get_frame_size(termios->c_cflag);
spin_lock_irqsave(&port->lock, flags);
/*
@ -1998,11 +2090,21 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
*/
uart_update_timeout(port, termios->c_cflag, baud);
/*
* Calculate the approximated time it takes to transmit one character
* with the given baud rate. We use this as the poll interval when we
* wait for the tx queue to empty.
*/
uap->rs485_tx_drain_interval = (bits * 1000 * 1000) / baud;
pl011_setup_status_masks(port, termios);
if (UART_ENABLE_MS(port, termios->c_cflag))
pl011_enable_ms(port);
if (port->rs485.flags & SER_RS485_ENABLED)
termios->c_cflag &= ~CRTSCTS;
/* first, disable everything */
old_cr = pl011_read(uap, REG_CR);
pl011_write(0, uap, REG_CR);
@ -2124,6 +2226,41 @@ static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser)
return ret;
}
static int pl011_rs485_config(struct uart_port *port,
struct serial_rs485 *rs485)
{
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
/* pick sane settings if the user hasn't */
if (!(rs485->flags & SER_RS485_RTS_ON_SEND) ==
!(rs485->flags & SER_RS485_RTS_AFTER_SEND)) {
rs485->flags |= SER_RS485_RTS_ON_SEND;
rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
}
/* clamp the delays to [0, 100ms] */
rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U);
memset(rs485->padding, 0, sizeof(rs485->padding));
if (port->rs485.flags & SER_RS485_ENABLED)
pl011_rs485_tx_stop(uap);
/* Set new configuration */
port->rs485 = *rs485;
/* Make sure auto RTS is disabled */
if (port->rs485.flags & SER_RS485_ENABLED) {
u32 cr = pl011_read(uap, REG_CR);
cr &= ~UART011_CR_RTSEN;
pl011_write(cr, uap, REG_CR);
port->status &= ~UPSTAT_AUTORTS;
}
return 0;
}
static const struct uart_ops amba_pl011_pops = {
.tx_empty = pl011_tx_empty,
.set_mctrl = pl011_set_mctrl,
@ -2588,10 +2725,28 @@ static int pl011_find_free_port(void)
return -EBUSY;
}
static int pl011_get_rs485_mode(struct uart_amba_port *uap)
{
struct uart_port *port = &uap->port;
struct serial_rs485 *rs485 = &port->rs485;
int ret;
ret = uart_get_rs485_mode(port);
if (ret)
return ret;
/* clamp the delays to [0, 100ms] */
rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U);
return 0;
}
static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap,
struct resource *mmiobase, int index)
{
void __iomem *base;
int ret;
base = devm_ioremap_resource(dev, mmiobase);
if (IS_ERR(base))
@ -2608,6 +2763,10 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap,
uap->port.flags = UPF_BOOT_AUTOCONF;
uap->port.line = index;
ret = pl011_get_rs485_mode(uap);
if (ret)
return ret;
amba_ports[index] = uap;
return 0;
@ -2665,7 +2824,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
uap->port.iotype = vendor->access_32b ? UPIO_MEM32 : UPIO_MEM;
uap->port.irq = dev->irq[0];
uap->port.ops = &amba_pl011_pops;
uap->port.rs485_config = pl011_rs485_config;
snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev));
ret = pl011_setup_port(&dev->dev, uap, &dev->res, portnr);

View File

@ -861,11 +861,7 @@ static int linflex_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, sport);
ret = uart_add_one_port(&linflex_reg, sport);
if (ret)
return ret;
return 0;
return uart_add_one_port(&linflex_reg, sport);
}
static int linflex_remove(struct platform_device *pdev)

View File

@ -7,6 +7,7 @@
#include <linux/clk.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/dmapool.h>
@ -109,6 +110,11 @@
#define UARTSFIFO_TXOF 0x02
#define UARTSFIFO_RXUF 0x01
/* 32-bit global registers only for i.MX7ULP/i.MX8x
* Used to reset all internal logic and registers, except the Global Register.
*/
#define UART_GLOBAL 0x8
/* 32-bit register definition */
#define UARTBAUD 0x00
#define UARTSTAT 0x04
@ -219,6 +225,10 @@
#define UARTWATER_TXWATER_OFF 0
#define UARTWATER_RXWATER_OFF 16
#define UART_GLOBAL_RST 0x2
#define GLOBAL_RST_MIN_US 20
#define GLOBAL_RST_MAX_US 40
/* Rx DMA timeout in ms, which is used to calculate Rx ring buffer size */
#define DMA_RX_TIMEOUT (10)
@ -320,6 +330,11 @@ static inline bool is_layerscape_lpuart(struct lpuart_port *sport)
sport->devtype == LS1028A_LPUART);
}
static inline bool is_imx7ulp_lpuart(struct lpuart_port *sport)
{
return sport->devtype == IMX7ULP_LPUART;
}
static inline bool is_imx8qxp_lpuart(struct lpuart_port *sport)
{
return sport->devtype == IMX8QXP_LPUART;
@ -383,6 +398,33 @@ static unsigned int lpuart_get_baud_clk_rate(struct lpuart_port *sport)
#define lpuart_enable_clks(x) __lpuart_enable_clks(x, true)
#define lpuart_disable_clks(x) __lpuart_enable_clks(x, false)
static int lpuart_global_reset(struct lpuart_port *sport)
{
struct uart_port *port = &sport->port;
void __iomem *global_addr;
int ret;
if (uart_console(port))
return 0;
ret = clk_prepare_enable(sport->ipg_clk);
if (ret) {
dev_err(sport->port.dev, "failed to enable uart ipg clk: %d\n", ret);
return ret;
}
if (is_imx7ulp_lpuart(sport) || is_imx8qxp_lpuart(sport)) {
global_addr = port->membase + UART_GLOBAL - IMX_REG_OFF;
writel(UART_GLOBAL_RST, global_addr);
usleep_range(GLOBAL_RST_MIN_US, GLOBAL_RST_MAX_US);
writel(0, global_addr);
usleep_range(GLOBAL_RST_MIN_US, GLOBAL_RST_MAX_US);
}
clk_disable_unprepare(sport->ipg_clk);
return 0;
}
static void lpuart_stop_tx(struct uart_port *port)
{
unsigned char temp;
@ -479,6 +521,10 @@ static void lpuart_dma_tx_complete(void *arg)
unsigned long flags;
spin_lock_irqsave(&sport->port.lock, flags);
if (!sport->dma_tx_in_progress) {
spin_unlock_irqrestore(&sport->port.lock, flags);
return;
}
dma_unmap_sg(chan->device->dev, sgl, sport->dma_tx_nents,
DMA_TO_DEVICE);
@ -2045,11 +2091,12 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
{
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
unsigned long flags;
unsigned long ctrl, old_ctrl, modem;
unsigned long ctrl, old_ctrl, bd, modem;
unsigned int baud;
unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
ctrl = old_ctrl = lpuart32_read(&sport->port, UARTCTRL);
bd = lpuart32_read(&sport->port, UARTBAUD);
modem = lpuart32_read(&sport->port, UARTMODIR);
/*
* only support CS8 and CS7, and for CS7 must enable PE.
@ -2093,7 +2140,9 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
}
if (termios->c_cflag & CSTOPB)
termios->c_cflag &= ~CSTOPB;
bd |= UARTBAUD_SBNS;
else
bd &= ~UARTBAUD_SBNS;
/* parity must be enabled when CS7 to match 8-bits format */
if ((termios->c_cflag & CSIZE) == CS7)
@ -2163,6 +2212,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
lpuart32_write(&sport->port, old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE),
UARTCTRL);
lpuart32_write(&sport->port, bd, UARTBAUD);
lpuart32_serial_setbrg(sport, baud);
lpuart32_write(&sport->port, modem, UARTMODIR);
lpuart32_write(&sport->port, ctrl, UARTCTRL);
@ -2611,7 +2661,7 @@ static int lpuart_probe(struct platform_device *pdev)
return PTR_ERR(sport->port.membase);
sport->port.membase += sdata->reg_off;
sport->port.mapbase = res->start;
sport->port.mapbase = res->start + sdata->reg_off;
sport->port.dev = &pdev->dev;
sport->port.type = PORT_LPUART;
sport->devtype = sdata->devtype;
@ -2691,6 +2741,10 @@ static int lpuart_probe(struct platform_device *pdev)
if (ret)
goto failed_attach_port;
ret = lpuart_global_reset(sport);
if (ret)
goto failed_reset;
ret = uart_get_rs485_mode(&sport->port);
if (ret)
goto failed_get_rs485;
@ -2707,6 +2761,8 @@ static int lpuart_probe(struct platform_device *pdev)
return 0;
failed_get_rs485:
failed_reset:
uart_remove_one_port(&lpuart_reg, &sport->port);
failed_attach_port:
failed_irq_request:
lpuart_disable_clks(sport);

View File

@ -815,7 +815,9 @@ static void neo_parse_isr(struct jsm_board *brd, u32 port)
/* Parse any modem signal changes */
jsm_dbg(INTR, &ch->ch_bd->pci_dev,
"MOD_STAT: sending to parse_modem_sigs\n");
spin_lock_irqsave(&ch->uart_port.lock, lock_flags);
neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
spin_unlock_irqrestore(&ch->uart_port.lock, lock_flags);
}
}

View File

@ -187,6 +187,7 @@ static void jsm_tty_break(struct uart_port *port, int break_state)
static int jsm_tty_open(struct uart_port *port)
{
unsigned long lock_flags;
struct jsm_board *brd;
struct jsm_channel *channel =
container_of(port, struct jsm_channel, uart_port);
@ -240,6 +241,7 @@ static int jsm_tty_open(struct uart_port *port)
channel->ch_cached_lsr = 0;
channel->ch_stops_sent = 0;
spin_lock_irqsave(&port->lock, lock_flags);
termios = &port->state->port.tty->termios;
channel->ch_c_cflag = termios->c_cflag;
channel->ch_c_iflag = termios->c_iflag;
@ -259,6 +261,7 @@ static int jsm_tty_open(struct uart_port *port)
jsm_carrier(channel);
channel->ch_open_count++;
spin_unlock_irqrestore(&port->lock, lock_flags);
jsm_dbg(OPEN, &channel->ch_bd->pci_dev, "finish\n");
return 0;

View File

@ -330,17 +330,16 @@ int kgdb_register_nmi_console(void)
if (!arch_kgdb_ops.enable_nmi)
return 0;
kgdb_nmi_tty_driver = alloc_tty_driver(1);
if (!kgdb_nmi_tty_driver) {
kgdb_nmi_tty_driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
if (IS_ERR(kgdb_nmi_tty_driver)) {
pr_err("%s: cannot allocate tty\n", __func__);
return -ENOMEM;
return PTR_ERR(kgdb_nmi_tty_driver);
}
kgdb_nmi_tty_driver->driver_name = "ttyNMI";
kgdb_nmi_tty_driver->name = "ttyNMI";
kgdb_nmi_tty_driver->num = 1;
kgdb_nmi_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
kgdb_nmi_tty_driver->subtype = SERIAL_TYPE_NORMAL;
kgdb_nmi_tty_driver->flags = TTY_DRIVER_REAL_RAW;
kgdb_nmi_tty_driver->init_termios = tty_std_termios;
tty_termios_encode_baud_rate(&kgdb_nmi_tty_driver->init_termios,
KGDB_NMI_BAUD, KGDB_NMI_BAUD);
@ -356,7 +355,7 @@ int kgdb_register_nmi_console(void)
return 0;
err_drv_reg:
put_tty_driver(kgdb_nmi_tty_driver);
tty_driver_kref_put(kgdb_nmi_tty_driver);
return ret;
}
EXPORT_SYMBOL_GPL(kgdb_register_nmi_console);
@ -374,7 +373,7 @@ int kgdb_unregister_nmi_console(void)
return ret;
tty_unregister_driver(kgdb_nmi_tty_driver);
put_tty_driver(kgdb_nmi_tty_driver);
tty_driver_kref_put(kgdb_nmi_tty_driver);
return 0;
}

View File

@ -1271,18 +1271,13 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
/* Always ask for fixed clock rate from a property. */
device_property_read_u32(dev, "clock-frequency", &uartclk);
s->clk = devm_clk_get_optional(dev, "osc");
xtal = device_property_match_string(dev, "clock-names", "osc") < 0;
if (xtal)
s->clk = devm_clk_get_optional(dev, "xtal");
else
s->clk = devm_clk_get_optional(dev, "osc");
if (IS_ERR(s->clk))
return PTR_ERR(s->clk);
if (s->clk) {
xtal = false;
} else {
s->clk = devm_clk_get_optional(dev, "xtal");
if (IS_ERR(s->clk))
return PTR_ERR(s->clk);
xtal = true;
}
ret = clk_prepare_enable(s->clk);
if (ret)

View File

@ -276,11 +276,8 @@ static void serial_omap_enable_ms(struct uart_port *port)
dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->port.line);
pm_runtime_get_sync(up->dev);
up->ier |= UART_IER_MSI;
serial_out(up, UART_IER, up->ier);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_stop_tx(struct uart_port *port)
@ -288,8 +285,6 @@ static void serial_omap_stop_tx(struct uart_port *port)
struct uart_omap_port *up = to_uart_omap_port(port);
int res;
pm_runtime_get_sync(up->dev);
/* Handle RS-485 */
if (port->rs485.flags & SER_RS485_ENABLED) {
if (up->scr & OMAP_UART_SCR_TX_EMPTY) {
@ -330,21 +325,15 @@ static void serial_omap_stop_tx(struct uart_port *port)
up->ier &= ~UART_IER_THRI;
serial_out(up, UART_IER, up->ier);
}
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_stop_rx(struct uart_port *port)
{
struct uart_omap_port *up = to_uart_omap_port(port);
pm_runtime_get_sync(up->dev);
up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
up->port.read_status_mask &= ~UART_LSR_DR;
serial_out(up, UART_IER, up->ier);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
@ -399,8 +388,6 @@ static void serial_omap_start_tx(struct uart_port *port)
struct uart_omap_port *up = to_uart_omap_port(port);
int res;
pm_runtime_get_sync(up->dev);
/* Handle RS-485 */
if (port->rs485.flags & SER_RS485_ENABLED) {
/* Fire THR interrupts when FIFO is below trigger level */
@ -421,8 +408,6 @@ static void serial_omap_start_tx(struct uart_port *port)
up->rs485_tx_filter_count = 0;
serial_omap_enable_ier_thri(up);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_throttle(struct uart_port *port)
@ -430,13 +415,10 @@ static void serial_omap_throttle(struct uart_port *port)
struct uart_omap_port *up = to_uart_omap_port(port);
unsigned long flags;
pm_runtime_get_sync(up->dev);
spin_lock_irqsave(&up->port.lock, flags);
up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
serial_out(up, UART_IER, up->ier);
spin_unlock_irqrestore(&up->port.lock, flags);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_unthrottle(struct uart_port *port)
@ -444,13 +426,10 @@ static void serial_omap_unthrottle(struct uart_port *port)
struct uart_omap_port *up = to_uart_omap_port(port);
unsigned long flags;
pm_runtime_get_sync(up->dev);
spin_lock_irqsave(&up->port.lock, flags);
up->ier |= UART_IER_RLSI | UART_IER_RDI;
serial_out(up, UART_IER, up->ier);
spin_unlock_irqrestore(&up->port.lock, flags);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
static unsigned int check_modem_status(struct uart_omap_port *up)
@ -576,7 +555,6 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id)
int max_count = 256;
spin_lock(&up->port.lock);
pm_runtime_get_sync(up->dev);
do {
iir = serial_in(up, UART_IIR);
@ -616,8 +594,6 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id)
tty_flip_buffer_push(&up->port.state->port);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
up->port_activity = jiffies;
return ret;
@ -629,13 +605,11 @@ static unsigned int serial_omap_tx_empty(struct uart_port *port)
unsigned long flags;
unsigned int ret = 0;
pm_runtime_get_sync(up->dev);
dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->port.line);
spin_lock_irqsave(&up->port.lock, flags);
ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
spin_unlock_irqrestore(&up->port.lock, flags);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
return ret;
}
@ -645,10 +619,7 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port)
unsigned int status;
unsigned int ret = 0;
pm_runtime_get_sync(up->dev);
status = check_modem_status(up);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->port.line);
@ -680,7 +651,6 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
if (mctrl & TIOCM_LOOP)
mcr |= UART_MCR_LOOP;
pm_runtime_get_sync(up->dev);
old_mcr = serial_in(up, UART_MCR);
old_mcr &= ~(UART_MCR_LOOP | UART_MCR_OUT2 | UART_MCR_OUT1 |
UART_MCR_DTR | UART_MCR_RTS);
@ -696,9 +666,6 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
up->efr &= ~UART_EFR_RTS;
serial_out(up, UART_EFR, up->efr);
serial_out(up, UART_LCR, lcr);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_break_ctl(struct uart_port *port, int break_state)
@ -707,7 +674,6 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state)
unsigned long flags;
dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->port.line);
pm_runtime_get_sync(up->dev);
spin_lock_irqsave(&up->port.lock, flags);
if (break_state == -1)
up->lcr |= UART_LCR_SBC;
@ -715,8 +681,6 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state)
up->lcr &= ~UART_LCR_SBC;
serial_out(up, UART_LCR, up->lcr);
spin_unlock_irqrestore(&up->port.lock, flags);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
static int serial_omap_startup(struct uart_port *port)
@ -788,8 +752,6 @@ static int serial_omap_startup(struct uart_port *port)
serial_out(up, UART_OMAP_WER, up->wer);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
up->port_activity = jiffies;
return 0;
}
@ -801,7 +763,6 @@ static void serial_omap_shutdown(struct uart_port *port)
dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->port.line);
pm_runtime_get_sync(up->dev);
/*
* Disable interrupts from this port
*/
@ -825,8 +786,7 @@ static void serial_omap_shutdown(struct uart_port *port)
if (serial_in(up, UART_LSR) & UART_LSR_DR)
(void) serial_in(up, UART_RX);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
pm_runtime_put_sync(up->dev);
free_irq(up->port.irq, up);
dev_pm_clear_wake_irq(up->dev);
}
@ -896,7 +856,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
* Ok, we're now changing the port state. Do it with
* interrupts disabled.
*/
pm_runtime_get_sync(up->dev);
spin_lock_irqsave(&up->port.lock, flags);
/*
@ -1096,8 +1055,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
serial_omap_set_mctrl(&up->port, up->port.mctrl);
spin_unlock_irqrestore(&up->port.lock, flags);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line);
}
@ -1110,7 +1067,6 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->port.line);
pm_runtime_get_sync(up->dev);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
efr = serial_in(up, UART_EFR);
serial_out(up, UART_EFR, efr | UART_EFR_ECB);
@ -1120,9 +1076,6 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(up, UART_EFR, efr);
serial_out(up, UART_LCR, 0);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_release_port(struct uart_port *port)
@ -1202,11 +1155,8 @@ static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
{
struct uart_omap_port *up = to_uart_omap_port(port);
pm_runtime_get_sync(up->dev);
wait_for_xmitr(up);
serial_out(up, UART_TX, ch);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
static int serial_omap_poll_get_char(struct uart_port *port)
@ -1214,7 +1164,6 @@ static int serial_omap_poll_get_char(struct uart_port *port)
struct uart_omap_port *up = to_uart_omap_port(port);
unsigned int status;
pm_runtime_get_sync(up->dev);
status = serial_in(up, UART_LSR);
if (!(status & UART_LSR_DR)) {
status = NO_POLL_CHAR;
@ -1224,9 +1173,6 @@ static int serial_omap_poll_get_char(struct uart_port *port)
status = serial_in(up, UART_RX);
out:
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
return status;
}
@ -1309,8 +1255,6 @@ serial_omap_console_write(struct console *co, const char *s,
unsigned int ier;
int locked = 1;
pm_runtime_get_sync(up->dev);
local_irq_save(flags);
if (up->port.sysrq)
locked = 0;
@ -1343,8 +1287,6 @@ serial_omap_console_write(struct console *co, const char *s,
if (up->msr_saved_flags)
check_modem_status(up);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
if (locked)
spin_unlock(&up->port.lock);
local_irq_restore(flags);
@ -1403,8 +1345,6 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
unsigned int mode;
int val;
pm_runtime_get_sync(up->dev);
/* Disable interrupts from this port */
mode = up->ier;
up->ier = 0;
@ -1438,9 +1378,6 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
serial_out(up, UART_OMAP_SCR, up->scr);
}
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
return 0;
}
@ -1737,11 +1674,7 @@ static int serial_omap_probe(struct platform_device *pdev)
omap_up_info->autosuspend_timeout = -1;
device_init_wakeup(up->dev, true);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev,
omap_up_info->autosuspend_timeout);
pm_runtime_irq_safe(&pdev->dev);
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
@ -1755,12 +1688,9 @@ static int serial_omap_probe(struct platform_device *pdev)
if (ret != 0)
goto err_add_port;
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
return 0;
err_add_port:
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
cpu_latency_qos_remove_request(&up->pm_qos_request);
@ -1778,7 +1708,6 @@ static int serial_omap_remove(struct platform_device *dev)
uart_remove_one_port(&serial_omap_reg, &up->port);
pm_runtime_dont_use_autosuspend(up->dev);
pm_runtime_put_sync(up->dev);
pm_runtime_disable(up->dev);
cpu_latency_qos_remove_request(&up->pm_qos_request);

View File

@ -65,6 +65,7 @@ enum s3c24xx_port_type {
struct s3c24xx_uart_info {
char *name;
enum s3c24xx_port_type type;
unsigned int has_usi;
unsigned int port_type;
unsigned int fifosize;
unsigned long rx_fifomask;
@ -305,8 +306,9 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port)
dmaengine_pause(dma->tx_chan);
dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state);
dmaengine_terminate_all(dma->tx_chan);
dma_sync_single_for_cpu(ourport->port.dev,
dma->tx_transfer_addr, dma->tx_size, DMA_TO_DEVICE);
dma_sync_single_for_cpu(dma->tx_chan->device->dev,
dma->tx_transfer_addr, dma->tx_size,
DMA_TO_DEVICE);
async_tx_ack(dma->tx_desc);
count = dma->tx_bytes_requested - state.residue;
xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
@ -338,8 +340,9 @@ static void s3c24xx_serial_tx_dma_complete(void *args)
count = dma->tx_bytes_requested - state.residue;
async_tx_ack(dma->tx_desc);
dma_sync_single_for_cpu(ourport->port.dev, dma->tx_transfer_addr,
dma->tx_size, DMA_TO_DEVICE);
dma_sync_single_for_cpu(dma->tx_chan->device->dev,
dma->tx_transfer_addr, dma->tx_size,
DMA_TO_DEVICE);
spin_lock_irqsave(&port->lock, flags);
@ -443,8 +446,9 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport,
dma->tx_size = count & ~(dma_get_cache_alignment() - 1);
dma->tx_transfer_addr = dma->tx_addr + xmit->tail;
dma_sync_single_for_device(ourport->port.dev, dma->tx_transfer_addr,
dma->tx_size, DMA_TO_DEVICE);
dma_sync_single_for_device(dma->tx_chan->device->dev,
dma->tx_transfer_addr, dma->tx_size,
DMA_TO_DEVICE);
dma->tx_desc = dmaengine_prep_slave_single(dma->tx_chan,
dma->tx_transfer_addr, dma->tx_size,
@ -515,7 +519,7 @@ static void s3c24xx_uart_copy_rx_to_tty(struct s3c24xx_uart_port *ourport,
if (!count)
return;
dma_sync_single_for_cpu(ourport->port.dev, dma->rx_addr,
dma_sync_single_for_cpu(dma->rx_chan->device->dev, dma->rx_addr,
dma->rx_size, DMA_FROM_DEVICE);
ourport->port.icount.rx += count;
@ -636,8 +640,8 @@ static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport)
{
struct s3c24xx_uart_dma *dma = ourport->dma;
dma_sync_single_for_device(ourport->port.dev, dma->rx_addr,
dma->rx_size, DMA_FROM_DEVICE);
dma_sync_single_for_device(dma->rx_chan->device->dev, dma->rx_addr,
dma->rx_size, DMA_FROM_DEVICE);
dma->rx_desc = dmaengine_prep_slave_single(dma->rx_chan,
dma->rx_addr, dma->rx_size, DMA_DEV_TO_MEM,
@ -1102,18 +1106,19 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
goto err_release_tx;
}
dma->rx_addr = dma_map_single(p->port.dev, dma->rx_buf,
dma->rx_size, DMA_FROM_DEVICE);
if (dma_mapping_error(p->port.dev, dma->rx_addr)) {
dma->rx_addr = dma_map_single(dma->rx_chan->device->dev, dma->rx_buf,
dma->rx_size, DMA_FROM_DEVICE);
if (dma_mapping_error(dma->rx_chan->device->dev, dma->rx_addr)) {
reason = "DMA mapping error for RX buffer";
ret = -EIO;
goto err_free_rx;
}
/* TX buffer */
dma->tx_addr = dma_map_single(p->port.dev, p->port.state->xmit.buf,
UART_XMIT_SIZE, DMA_TO_DEVICE);
if (dma_mapping_error(p->port.dev, dma->tx_addr)) {
dma->tx_addr = dma_map_single(dma->tx_chan->device->dev,
p->port.state->xmit.buf, UART_XMIT_SIZE,
DMA_TO_DEVICE);
if (dma_mapping_error(dma->tx_chan->device->dev, dma->tx_addr)) {
reason = "DMA mapping error for TX buffer";
ret = -EIO;
goto err_unmap_rx;
@ -1122,8 +1127,8 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
return 0;
err_unmap_rx:
dma_unmap_single(p->port.dev, dma->rx_addr, dma->rx_size,
DMA_FROM_DEVICE);
dma_unmap_single(dma->rx_chan->device->dev, dma->rx_addr,
dma->rx_size, DMA_FROM_DEVICE);
err_free_rx:
kfree(dma->rx_buf);
err_release_tx:
@ -1142,8 +1147,8 @@ static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p)
if (dma->rx_chan) {
dmaengine_terminate_all(dma->rx_chan);
dma_unmap_single(p->port.dev, dma->rx_addr,
dma->rx_size, DMA_FROM_DEVICE);
dma_unmap_single(dma->rx_chan->device->dev, dma->rx_addr,
dma->rx_size, DMA_FROM_DEVICE);
kfree(dma->rx_buf);
dma_release_channel(dma->rx_chan);
dma->rx_chan = NULL;
@ -1151,8 +1156,8 @@ static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p)
if (dma->tx_chan) {
dmaengine_terminate_all(dma->tx_chan);
dma_unmap_single(p->port.dev, dma->tx_addr,
UART_XMIT_SIZE, DMA_TO_DEVICE);
dma_unmap_single(dma->tx_chan->device->dev, dma->tx_addr,
UART_XMIT_SIZE, DMA_TO_DEVICE);
dma_release_channel(dma->tx_chan);
dma->tx_chan = NULL;
}
@ -1352,6 +1357,28 @@ static int apple_s5l_serial_startup(struct uart_port *port)
return ret;
}
static void exynos_usi_init(struct uart_port *port)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
struct s3c24xx_uart_info *info = ourport->info;
unsigned int val;
if (!info->has_usi)
return;
/* Clear the software reset of USI block (it's set at startup) */
val = rd_regl(port, USI_CON);
val &= ~USI_CON_RESET_MASK;
wr_regl(port, USI_CON, val);
udelay(1);
/* Continuously provide the clock to USI IP w/o gating (for Rx mode) */
val = rd_regl(port, USI_OPTION);
val &= ~USI_OPTION_HWACG_MASK;
val |= USI_OPTION_HWACG_CLKREQ_ON;
wr_regl(port, USI_OPTION, val);
}
/* power power management control */
static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
@ -1379,6 +1406,7 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
if (!IS_ERR(ourport->baudclk))
clk_prepare_enable(ourport->baudclk);
exynos_usi_init(port);
break;
default:
dev_err(port->dev, "s3c24xx_serial: unknown pm %d\n", level);
@ -2102,6 +2130,8 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
if (ret)
pr_warn("uart: failed to enable baudclk\n");
exynos_usi_init(port);
/* Keep all interrupts masked and cleared */
switch (ourport->info->type) {
case TYPE_S3C6400:
@ -2750,10 +2780,11 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
#endif
#if defined(CONFIG_ARCH_EXYNOS)
#define EXYNOS_COMMON_SERIAL_DRV_DATA \
#define EXYNOS_COMMON_SERIAL_DRV_DATA_USI(_has_usi) \
.info = &(struct s3c24xx_uart_info) { \
.name = "Samsung Exynos UART", \
.type = TYPE_S3C6400, \
.has_usi = _has_usi, \
.port_type = PORT_S3C6400, \
.has_divslot = 1, \
.rx_fifomask = S5PV210_UFSTAT_RXMASK, \
@ -2773,6 +2804,9 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
.has_fracval = 1, \
} \
#define EXYNOS_COMMON_SERIAL_DRV_DATA \
EXYNOS_COMMON_SERIAL_DRV_DATA_USI(0)
static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
EXYNOS_COMMON_SERIAL_DRV_DATA,
.fifosize = { 256, 64, 16, 16 },
@ -2783,11 +2817,19 @@ static struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = {
.fifosize = { 64, 256, 16, 256 },
};
static struct s3c24xx_serial_drv_data exynos850_serial_drv_data = {
EXYNOS_COMMON_SERIAL_DRV_DATA_USI(1),
.fifosize = { 256, 64, 64, 64 },
};
#define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos4210_serial_drv_data)
#define EXYNOS5433_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos5433_serial_drv_data)
#define EXYNOS850_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos850_serial_drv_data)
#else
#define EXYNOS4210_SERIAL_DRV_DATA (kernel_ulong_t)NULL
#define EXYNOS5433_SERIAL_DRV_DATA (kernel_ulong_t)NULL
#define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
#define EXYNOS5433_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
#define EXYNOS850_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
#endif
#ifdef CONFIG_ARCH_APPLE
@ -2843,6 +2885,9 @@ static const struct platform_device_id s3c24xx_serial_driver_ids[] = {
}, {
.name = "s5l-uart",
.driver_data = S5L_SERIAL_DRV_DATA,
}, {
.name = "exynos850-uart",
.driver_data = EXYNOS850_SERIAL_DRV_DATA,
},
{ },
};
@ -2866,6 +2911,8 @@ static const struct of_device_id s3c24xx_uart_dt_match[] = {
.data = (void *)EXYNOS5433_SERIAL_DRV_DATA },
{ .compatible = "apple,s5l-uart",
.data = (void *)S5L_SERIAL_DRV_DATA },
{ .compatible = "samsung,exynos850-uart",
.data = (void *)EXYNOS850_SERIAL_DRV_DATA },
{},
};
MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);

View File

@ -1568,14 +1568,12 @@ static int tegra_uart_probe(struct platform_device *pdev)
struct resource *resource;
int ret;
const struct tegra_uart_chip_data *cdata;
const struct of_device_id *match;
match = of_match_device(tegra_uart_of_match, &pdev->dev);
if (!match) {
cdata = of_device_get_match_data(&pdev->dev);
if (!cdata) {
dev_err(&pdev->dev, "Error: No device match found\n");
return -ENODEV;
}
cdata = match->data;
tup = devm_kzalloc(&pdev->dev, sizeof(*tup), GFP_KERNEL);
if (!tup) {

View File

@ -2314,6 +2314,14 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
port->dev ? ": " : "",
port->name,
address, port->irq, port->uartclk / 16, uart_type(port));
/* The magic multiplier feature is a bit obscure, so report it too. */
if (port->flags & UPF_MAGIC_MULTIPLIER)
pr_info("%s%s%s extra baud rates supported: %d, %d",
port->dev ? dev_name(port->dev) : "",
port->dev ? ": " : "",
port->name,
port->uartclk / 8, port->uartclk / 4);
}
static void
@ -2522,9 +2530,12 @@ int uart_register_driver(struct uart_driver *drv)
if (!drv->state)
goto out;
normal = alloc_tty_driver(drv->nr);
if (!normal)
normal = tty_alloc_driver(drv->nr, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(normal)) {
retval = PTR_ERR(normal);
goto out_kfree;
}
drv->tty_driver = normal;
@ -2537,7 +2548,6 @@ int uart_register_driver(struct uart_driver *drv)
normal->init_termios = tty_std_termios;
normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600;
normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
normal->driver_state = drv;
tty_set_operations(normal, &uart_ops);
@ -2558,7 +2568,7 @@ int uart_register_driver(struct uart_driver *drv)
for (i = 0; i < drv->nr; i++)
tty_port_destroy(&drv->state[i].port);
put_tty_driver(normal);
tty_driver_kref_put(normal);
out_kfree:
kfree(drv->state);
out:
@ -2580,7 +2590,7 @@ void uart_unregister_driver(struct uart_driver *drv)
unsigned int i;
tty_unregister_driver(p);
put_tty_driver(p);
tty_driver_kref_put(p);
for (i = 0; i < drv->nr; i++)
tty_port_destroy(&drv->state[i].port);
kfree(drv->state);

View File

@ -1758,6 +1758,10 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr)
/* Handle BREAKs */
sci_handle_breaks(port);
/* drop invalid character received before break was detected */
serial_port_in(port, SCxRDR);
sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port));
return IRQ_HANDLED;
@ -1837,7 +1841,8 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
ret = sci_er_interrupt(irq, ptr);
/* Break Interrupt */
if ((ssr_status & SCxSR_BRK(port)) && err_enabled)
if (s->irqs[SCIx_ERI_IRQ] != s->irqs[SCIx_BRI_IRQ] &&
(ssr_status & SCxSR_BRK(port)) && err_enabled)
ret = sci_br_interrupt(irq, ptr);
/* Overrun Interrupt */

View File

@ -1034,8 +1034,8 @@ static int stm32_usart_init_port(struct stm32_port *stm32port,
int ret, irq;
irq = platform_get_irq(pdev, 0);
if (irq <= 0)
return irq ? : -ENODEV;
if (irq < 0)
return irq;
port->iotype = UPIO_MEM;
port->flags = UPF_BOOT_AUTOCONF;
@ -1064,8 +1064,7 @@ static int stm32_usart_init_port(struct stm32_port *stm32port,
&stm32port->txftcfg);
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
port->membase = devm_ioremap_resource(&pdev->dev, res);
port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(port->membase))
return PTR_ERR(port->membase);
port->mapbase = res->start;
@ -1177,7 +1176,7 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
if (uart_console(port))
return -ENODEV;
stm32port->rx_buf = dma_alloc_coherent(&pdev->dev, RX_BUF_L,
stm32port->rx_buf = dma_alloc_coherent(dev, RX_BUF_L,
&stm32port->rx_dma_buf,
GFP_KERNEL);
if (!stm32port->rx_buf)
@ -1243,7 +1242,7 @@ static int stm32_usart_of_dma_tx_probe(struct stm32_port *stm32port,
stm32port->tx_dma_busy = false;
stm32port->tx_buf = dma_alloc_coherent(&pdev->dev, TX_BUF_L,
stm32port->tx_buf = dma_alloc_coherent(dev, TX_BUF_L,
&stm32port->tx_dma_buf,
GFP_KERNEL);
if (!stm32port->tx_buf)

View File

@ -17,11 +17,13 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/clk.h>
#include <linux/pm_runtime.h>
#define ULITE_NAME "ttyUL"
#define ULITE_MAJOR 204
@ -54,6 +56,7 @@
#define ULITE_CONTROL_RST_TX 0x01
#define ULITE_CONTROL_RST_RX 0x02
#define ULITE_CONTROL_IE 0x10
#define UART_AUTOSUSPEND_TIMEOUT 3000 /* ms */
/* Static pointer to console port */
#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
@ -390,12 +393,16 @@ static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser)
static void ulite_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
struct uartlite_data *pdata = port->private_data;
int ret;
if (!state)
clk_enable(pdata->clk);
else
clk_disable(pdata->clk);
if (!state) {
ret = pm_runtime_get_sync(port->dev);
if (ret < 0)
dev_err(port->dev, "Failed to enable clocks\n");
} else {
pm_runtime_mark_last_busy(port->dev);
pm_runtime_put_autosuspend(port->dev);
}
}
#ifdef CONFIG_CONSOLE_POLL
@ -448,24 +455,15 @@ static const struct uart_ops ulite_ops = {
static void ulite_console_wait_tx(struct uart_port *port)
{
u8 val;
unsigned long timeout;
/*
* Spin waiting for TX fifo to have space available.
* When using the Microblaze Debug Module this can take up to 1s
*/
timeout = jiffies + msecs_to_jiffies(1000);
while (1) {
val = uart_in32(ULITE_STATUS, port);
if ((val & ULITE_STATUS_TXFULL) == 0)
break;
if (time_after(jiffies, timeout)) {
dev_warn(port->dev,
"timeout waiting for TX buffer empty\n");
break;
}
cpu_relax();
}
if (read_poll_timeout_atomic(uart_in32, val, !(val & ULITE_STATUS_TXFULL),
0, 1000000, false, ULITE_STATUS, port))
dev_warn(port->dev,
"timeout waiting for TX buffer empty\n");
}
static void ulite_console_putchar(struct uart_port *port, int ch)
@ -555,16 +553,15 @@ static void early_uartlite_putc(struct uart_port *port, int c)
* This limit is pretty arbitrary, unless we are at about 10 baud
* we'll never timeout on a working UART.
*/
unsigned retries = 1000000;
/* read status bit - 0x8 offset */
while (--retries && (readl(port->membase + 8) & (1 << 3)))
while (--retries &&
(readl(port->membase + ULITE_STATUS) & ULITE_STATUS_TXFULL))
;
/* Only attempt the iowrite if we didn't timeout */
/* write to TX_FIFO - 0x4 offset */
if (retries)
writel(c & 0xff, port->membase + 4);
writel(c & 0xff, port->membase + ULITE_TX);
}
static void early_uartlite_write(struct console *console,
@ -719,11 +716,38 @@ static int __maybe_unused ulite_resume(struct device *dev)
return 0;
}
static int __maybe_unused ulite_runtime_suspend(struct device *dev)
{
struct uart_port *port = dev_get_drvdata(dev);
struct uartlite_data *pdata = port->private_data;
clk_disable(pdata->clk);
return 0;
};
static int __maybe_unused ulite_runtime_resume(struct device *dev)
{
struct uart_port *port = dev_get_drvdata(dev);
struct uartlite_data *pdata = port->private_data;
int ret;
ret = clk_enable(pdata->clk);
if (ret) {
dev_err(dev, "Cannot enable clock.\n");
return ret;
}
return 0;
}
/* ---------------------------------------------------------------------
* Platform bus binding
*/
static SIMPLE_DEV_PM_OPS(ulite_pm_ops, ulite_suspend, ulite_resume);
static const struct dev_pm_ops ulite_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(ulite_suspend, ulite_resume)
SET_RUNTIME_PM_OPS(ulite_runtime_suspend,
ulite_runtime_resume, NULL)
};
#if defined(CONFIG_OF)
/* Match table for of_platform binding */
@ -779,18 +803,25 @@ static int ulite_probe(struct platform_device *pdev)
return ret;
}
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
if (!ulite_uart_driver.state) {
dev_dbg(&pdev->dev, "uartlite: calling uart_register_driver()\n");
ret = uart_register_driver(&ulite_uart_driver);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register driver\n");
clk_disable_unprepare(pdata->clk);
return ret;
}
}
ret = ulite_assign(&pdev->dev, id, res->start, irq, pdata);
clk_disable(pdata->clk);
pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
return ret;
}
@ -799,9 +830,14 @@ static int ulite_remove(struct platform_device *pdev)
{
struct uart_port *port = dev_get_drvdata(&pdev->dev);
struct uartlite_data *pdata = port->private_data;
int rc;
clk_disable_unprepare(pdata->clk);
return ulite_release(&pdev->dev);
rc = ulite_release(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
return rc;
}
/* work with hotplug and coldplug */

View File

@ -623,17 +623,14 @@ static int vt8500_serial_probe(struct platform_device *pdev)
struct vt8500_port *vt8500_port;
struct resource *mmres, *irqres;
struct device_node *np = pdev->dev.of_node;
const struct of_device_id *match;
const unsigned int *flags;
int ret;
int port;
match = of_match_device(wmt_dt_ids, &pdev->dev);
if (!match)
flags = of_device_get_match_data(&pdev->dev);
if (!flags)
return -EINVAL;
flags = match->data;
mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!mmres || !irqres)

View File

@ -3647,7 +3647,7 @@ static void slgt_cleanup(void)
for (info=slgt_device_list ; info != NULL ; info=info->next_device)
tty_unregister_device(serial_driver, info->line);
tty_unregister_driver(serial_driver);
put_tty_driver(serial_driver);
tty_driver_kref_put(serial_driver);
}
/* reset devices */
@ -3686,10 +3686,11 @@ static int __init slgt_init(void)
printk(KERN_INFO "%s\n", driver_name);
serial_driver = alloc_tty_driver(MAX_DEVICES);
if (!serial_driver) {
serial_driver = tty_alloc_driver(MAX_DEVICES, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(serial_driver)) {
printk("%s can't allocate tty driver\n", driver_name);
return -ENOMEM;
return PTR_ERR(serial_driver);
}
/* Initialize the tty_driver structure */
@ -3705,11 +3706,10 @@ static int __init slgt_init(void)
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
serial_driver->init_termios.c_ispeed = 9600;
serial_driver->init_termios.c_ospeed = 9600;
serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
tty_set_operations(serial_driver, &ops);
if ((rc = tty_register_driver(serial_driver)) < 0) {
DBGERR(("%s can't register serial driver\n", driver_name));
put_tty_driver(serial_driver);
tty_driver_kref_put(serial_driver);
serial_driver = NULL;
goto error;
}

View File

@ -258,7 +258,7 @@ static void sysrq_handle_showallcpus(int key)
if (!trigger_all_cpu_backtrace()) {
struct pt_regs *regs = NULL;
if (in_irq())
if (in_hardirq())
regs = get_irq_regs();
if (regs) {
pr_info("CPU%d:\n", smp_processor_id());
@ -280,7 +280,7 @@ static void sysrq_handle_showregs(int key)
{
struct pt_regs *regs = NULL;
if (in_irq())
if (in_hardirq())
regs = get_irq_regs();
if (regs)
show_regs(regs);

View File

@ -2290,8 +2290,6 @@ static int tty_fasync(int fd, struct file *filp, int on)
* Locking:
* Called functions take tty_ldiscs_lock
* current->signal->tty check is safe without locks
*
* FIXME: may race normal receive processing
*/
static int tiocsti(struct tty_struct *tty, char __user *p)
@ -2307,8 +2305,10 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
ld = tty_ldisc_ref_wait(tty);
if (!ld)
return -EIO;
tty_buffer_lock_exclusive(tty->port);
if (ld->ops->receive_buf)
ld->ops->receive_buf(tty, &ch, &mbz, 1);
tty_buffer_unlock_exclusive(tty->port);
tty_ldisc_deref(ld);
return 0;
}
@ -3438,19 +3438,6 @@ void tty_driver_kref_put(struct tty_driver *driver)
}
EXPORT_SYMBOL(tty_driver_kref_put);
void tty_set_operations(struct tty_driver *driver,
const struct tty_operations *op)
{
driver->ops = op;
};
EXPORT_SYMBOL(tty_set_operations);
void put_tty_driver(struct tty_driver *d)
{
tty_driver_kref_put(d);
}
EXPORT_SYMBOL(put_tty_driver);
/*
* Called by a tty driver to register itself.
*/

View File

@ -84,7 +84,7 @@ static int __init ttynull_init(void)
ret = tty_register_driver(driver);
if (ret < 0) {
put_tty_driver(driver);
tty_driver_kref_put(driver);
tty_port_destroy(&ttynull_port);
return ret;
}
@ -99,7 +99,7 @@ static void __exit ttynull_exit(void)
{
unregister_console(&ttynull_console);
tty_unregister_driver(ttynull_driver);
put_tty_driver(ttynull_driver);
tty_driver_kref_put(ttynull_driver);
tty_port_destroy(&ttynull_port);
}

View File

@ -1028,7 +1028,7 @@ static int vcc_tty_init(void)
rv = tty_register_driver(vcc_tty_driver);
if (rv) {
pr_err("VCC: TTY driver registration failed\n");
put_tty_driver(vcc_tty_driver);
tty_driver_kref_put(vcc_tty_driver);
vcc_tty_driver = NULL;
return rv;
}
@ -1041,7 +1041,7 @@ static int vcc_tty_init(void)
static void vcc_tty_exit(void)
{
tty_unregister_driver(vcc_tty_driver);
put_tty_driver(vcc_tty_driver);
tty_driver_kref_put(vcc_tty_driver);
vccdbg("VCC: TTY driver unregistered\n");
vcc_tty_driver = NULL;

View File

@ -1171,9 +1171,9 @@ static inline unsigned char getleds(void)
*
* Check the status of a keyboard led flag and report it back
*/
int vt_get_leds(int console, int flag)
int vt_get_leds(unsigned int console, int flag)
{
struct kbd_struct *kb = kbd_table + console;
struct kbd_struct *kb = &kbd_table[console];
int ret;
unsigned long flags;
@ -1193,9 +1193,9 @@ EXPORT_SYMBOL_GPL(vt_get_leds);
* Set the LEDs on a console. This is a wrapper for the VT layer
* so that we can keep kbd knowledge internal
*/
void vt_set_led_state(int console, int leds)
void vt_set_led_state(unsigned int console, int leds)
{
struct kbd_struct *kb = kbd_table + console;
struct kbd_struct *kb = &kbd_table[console];
setledstate(kb, leds);
}
@ -1212,9 +1212,9 @@ void vt_set_led_state(int console, int leds)
* don't hold the lock. We probably need to split out an LED lock
* but not during an -rc release!
*/
void vt_kbd_con_start(int console)
void vt_kbd_con_start(unsigned int console)
{
struct kbd_struct *kb = kbd_table + console;
struct kbd_struct *kb = &kbd_table[console];
unsigned long flags;
spin_lock_irqsave(&led_lock, flags);
clr_vc_kbd_led(kb, VC_SCROLLOCK);
@ -1229,9 +1229,9 @@ void vt_kbd_con_start(int console)
* Handle console stop. This is a wrapper for the VT layer
* so that we can keep kbd knowledge internal
*/
void vt_kbd_con_stop(int console)
void vt_kbd_con_stop(unsigned int console)
{
struct kbd_struct *kb = kbd_table + console;
struct kbd_struct *kb = &kbd_table[console];
unsigned long flags;
spin_lock_irqsave(&led_lock, flags);
set_vc_kbd_led(kb, VC_SCROLLOCK);
@ -1377,7 +1377,7 @@ static void kbd_rawcode(unsigned char data)
{
struct vc_data *vc = vc_cons[fg_console].d;
kbd = kbd_table + vc->vc_num;
kbd = &kbd_table[vc->vc_num];
if (kbd->kbdmode == VC_RAW)
put_queue(vc, data);
}
@ -1400,7 +1400,7 @@ static void kbd_keycode(unsigned int keycode, int down, bool hw_raw)
tty->driver_data = vc;
}
kbd = kbd_table + vc->vc_num;
kbd = &kbd_table[vc->vc_num];
#ifdef CONFIG_SPARC
if (keycode == KEY_STOP)
@ -1825,9 +1825,9 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
* Update the keyboard mode bits while holding the correct locks.
* Return 0 for success or an error code.
*/
int vt_do_kdskbmode(int console, unsigned int arg)
int vt_do_kdskbmode(unsigned int console, unsigned int arg)
{
struct kbd_struct *kb = kbd_table + console;
struct kbd_struct *kb = &kbd_table[console];
int ret = 0;
unsigned long flags;
@ -1865,9 +1865,9 @@ int vt_do_kdskbmode(int console, unsigned int arg)
* Update the keyboard meta bits while holding the correct locks.
* Return 0 for success or an error code.
*/
int vt_do_kdskbmeta(int console, unsigned int arg)
int vt_do_kdskbmeta(unsigned int console, unsigned int arg)
{
struct kbd_struct *kb = kbd_table + console;
struct kbd_struct *kb = &kbd_table[console];
int ret = 0;
unsigned long flags;
@ -2008,9 +2008,9 @@ out:
}
int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
int console)
unsigned int console)
{
struct kbd_struct *kb = kbd_table + console;
struct kbd_struct *kb = &kbd_table[console];
struct kbentry kbe;
if (copy_from_user(&kbe, user_kbe, sizeof(struct kbentry)))
@ -2097,9 +2097,9 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
return ret;
}
int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm)
int vt_do_kdskled(unsigned int console, int cmd, unsigned long arg, int perm)
{
struct kbd_struct *kb = kbd_table + console;
struct kbd_struct *kb = &kbd_table[console];
unsigned long flags;
unsigned char ucval;
@ -2139,9 +2139,9 @@ int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm)
return -ENOIOCTLCMD;
}
int vt_do_kdgkbmode(int console)
int vt_do_kdgkbmode(unsigned int console)
{
struct kbd_struct *kb = kbd_table + console;
struct kbd_struct *kb = &kbd_table[console];
/* This is a spot read so needs no locking */
switch (kb->kbdmode) {
case VC_RAW:
@ -2163,9 +2163,9 @@ int vt_do_kdgkbmode(int console)
*
* Report the meta flag status of this console
*/
int vt_do_kdgkbmeta(int console)
int vt_do_kdgkbmeta(unsigned int console)
{
struct kbd_struct *kb = kbd_table + console;
struct kbd_struct *kb = &kbd_table[console];
/* Again a spot read so no locking */
return vc_kbd_mode(kb, VC_META) ? K_ESCPREFIX : K_METABIT;
}
@ -2176,7 +2176,7 @@ int vt_do_kdgkbmeta(int console)
*
* Restore the unicode console state to its default
*/
void vt_reset_unicode(int console)
void vt_reset_unicode(unsigned int console)
{
unsigned long flags;
@ -2204,9 +2204,9 @@ int vt_get_shift_state(void)
* Reset the keyboard bits for a console as part of a general console
* reset event
*/
void vt_reset_keyboard(int console)
void vt_reset_keyboard(unsigned int console)
{
struct kbd_struct *kb = kbd_table + console;
struct kbd_struct *kb = &kbd_table[console];
unsigned long flags;
spin_lock_irqsave(&kbd_event_lock, flags);
@ -2234,9 +2234,9 @@ void vt_reset_keyboard(int console)
* caller must be sure that there are no synchronization needs
*/
int vt_get_kbd_mode_bit(int console, int bit)
int vt_get_kbd_mode_bit(unsigned int console, int bit)
{
struct kbd_struct *kb = kbd_table + console;
struct kbd_struct *kb = &kbd_table[console];
return vc_kbd_mode(kb, bit);
}
@ -2249,9 +2249,9 @@ int vt_get_kbd_mode_bit(int console, int bit)
* caller must be sure that there are no synchronization needs
*/
void vt_set_kbd_mode_bit(int console, int bit)
void vt_set_kbd_mode_bit(unsigned int console, int bit)
{
struct kbd_struct *kb = kbd_table + console;
struct kbd_struct *kb = &kbd_table[console];
unsigned long flags;
spin_lock_irqsave(&kbd_event_lock, flags);
@ -2268,9 +2268,9 @@ void vt_set_kbd_mode_bit(int console, int bit)
* caller must be sure that there are no synchronization needs
*/
void vt_clr_kbd_mode_bit(int console, int bit)
void vt_clr_kbd_mode_bit(unsigned int console, int bit)
{
struct kbd_struct *kb = kbd_table + console;
struct kbd_struct *kb = &kbd_table[console];
unsigned long flags;
spin_lock_irqsave(&kbd_event_lock, flags);

View File

@ -1219,8 +1219,25 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
new_row_size = new_cols << 1;
new_screen_size = new_row_size * new_rows;
if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
return 0;
if (new_cols == vc->vc_cols && new_rows == vc->vc_rows) {
/*
* This function is being called here to cover the case
* where the userspace calls the FBIOPUT_VSCREENINFO twice,
* passing the same fb_var_screeninfo containing the fields
* yres/xres equal to a number non-multiple of vc_font.height
* and yres_virtual/xres_virtual equal to number lesser than the
* vc_font.height and yres/xres.
* In the second call, the struct fb_var_screeninfo isn't
* being modified by the underlying driver because of the
* if above, and this causes the fbcon_display->vrows to become
* negative and it eventually leads to out-of-bound
* access by the imageblit function.
* To give the correct values to the struct and to not have
* to deal with possible errors from the code below, we call
* the resize_screen here as well.
*/
return resize_screen(vc, new_cols, new_rows, user);
}
if (new_screen_size > KMALLOC_MAX_SIZE || !new_screen_size)
return -EINVAL;
@ -3582,8 +3599,9 @@ int __init vty_init(const struct file_operations *console_fops)
vcs_init();
console_driver = alloc_tty_driver(MAX_NR_CONSOLES);
if (!console_driver)
console_driver = tty_alloc_driver(MAX_NR_CONSOLES, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_RESET_TERMIOS);
if (IS_ERR(console_driver))
panic("Couldn't allocate console driver\n");
console_driver->name = "tty";
@ -3594,7 +3612,6 @@ int __init vty_init(const struct file_operations *console_fops)
console_driver->init_termios = tty_std_termios;
if (default_utf8)
console_driver->init_termios.c_iflag |= IUTF8;
console_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
tty_set_operations(console_driver, &con_ops);
if (tty_register_driver(console_driver))
panic("Couldn't register console driver\n");

View File

@ -2027,16 +2027,16 @@ static const struct tty_operations acm_ops = {
static int __init acm_init(void)
{
int retval;
acm_tty_driver = alloc_tty_driver(ACM_TTY_MINORS);
if (!acm_tty_driver)
return -ENOMEM;
acm_tty_driver = tty_alloc_driver(ACM_TTY_MINORS, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(acm_tty_driver))
return PTR_ERR(acm_tty_driver);
acm_tty_driver->driver_name = "acm",
acm_tty_driver->name = "ttyACM",
acm_tty_driver->major = ACM_TTY_MAJOR,
acm_tty_driver->minor_start = 0,
acm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL,
acm_tty_driver->subtype = SERIAL_TYPE_NORMAL,
acm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
acm_tty_driver->init_termios = tty_std_termios;
acm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD |
HUPCL | CLOCAL;
@ -2044,14 +2044,14 @@ static int __init acm_init(void)
retval = tty_register_driver(acm_tty_driver);
if (retval) {
put_tty_driver(acm_tty_driver);
tty_driver_kref_put(acm_tty_driver);
return retval;
}
retval = usb_register(&acm_driver);
if (retval) {
tty_unregister_driver(acm_tty_driver);
put_tty_driver(acm_tty_driver);
tty_driver_kref_put(acm_tty_driver);
return retval;
}
@ -2064,7 +2064,7 @@ static void __exit acm_exit(void)
{
usb_deregister(&acm_driver);
tty_unregister_driver(acm_tty_driver);
put_tty_driver(acm_tty_driver);
tty_driver_kref_put(acm_tty_driver);
idr_destroy(&acm_minors);
}

View File

@ -1445,51 +1445,53 @@ EXPORT_SYMBOL_GPL(gserial_resume);
static int userial_init(void)
{
struct tty_driver *driver;
unsigned i;
int status;
gs_tty_driver = alloc_tty_driver(MAX_U_SERIAL_PORTS);
if (!gs_tty_driver)
return -ENOMEM;
driver = tty_alloc_driver(MAX_U_SERIAL_PORTS, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(driver))
return PTR_ERR(driver);
gs_tty_driver->driver_name = "g_serial";
gs_tty_driver->name = "ttyGS";
driver->driver_name = "g_serial";
driver->name = "ttyGS";
/* uses dynamically assigned dev_t values */
gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
gs_tty_driver->init_termios = tty_std_termios;
driver->type = TTY_DRIVER_TYPE_SERIAL;
driver->subtype = SERIAL_TYPE_NORMAL;
driver->init_termios = tty_std_termios;
/* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on
* MS-Windows. Otherwise, most of these flags shouldn't affect
* anything unless we were to actually hook up to a serial line.
*/
gs_tty_driver->init_termios.c_cflag =
driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
gs_tty_driver->init_termios.c_ispeed = 9600;
gs_tty_driver->init_termios.c_ospeed = 9600;
driver->init_termios.c_ispeed = 9600;
driver->init_termios.c_ospeed = 9600;
tty_set_operations(gs_tty_driver, &gs_tty_ops);
tty_set_operations(driver, &gs_tty_ops);
for (i = 0; i < MAX_U_SERIAL_PORTS; i++)
mutex_init(&ports[i].lock);
/* export the driver ... */
status = tty_register_driver(gs_tty_driver);
status = tty_register_driver(driver);
if (status) {
pr_err("%s: cannot register, err %d\n",
__func__, status);
goto fail;
}
gs_tty_driver = driver;
pr_debug("%s: registered %d ttyGS* device%s\n", __func__,
MAX_U_SERIAL_PORTS,
(MAX_U_SERIAL_PORTS == 1) ? "" : "s");
return status;
fail:
put_tty_driver(gs_tty_driver);
gs_tty_driver = NULL;
tty_driver_kref_put(driver);
return status;
}
module_init(userial_init);
@ -1497,7 +1499,7 @@ module_init(userial_init);
static void userial_cleanup(void)
{
tty_unregister_driver(gs_tty_driver);
put_tty_driver(gs_tty_driver);
tty_driver_kref_put(gs_tty_driver);
gs_tty_driver = NULL;
}
module_exit(userial_cleanup);

View File

@ -541,7 +541,7 @@ static int dbc_tty_init(void)
ret = tty_register_driver(dbc_tty_driver);
if (ret) {
pr_err("Can't register dbc tty driver\n");
put_tty_driver(dbc_tty_driver);
tty_driver_kref_put(dbc_tty_driver);
}
return ret;
}
@ -550,7 +550,7 @@ static void dbc_tty_exit(void)
{
if (dbc_tty_driver) {
tty_unregister_driver(dbc_tty_driver);
put_tty_driver(dbc_tty_driver);
tty_driver_kref_put(dbc_tty_driver);
dbc_tty_driver = NULL;
}
}

View File

@ -1319,9 +1319,10 @@ static int __init usb_serial_init(void)
{
int result;
usb_serial_tty_driver = alloc_tty_driver(USB_SERIAL_TTY_MINORS);
if (!usb_serial_tty_driver)
return -ENOMEM;
usb_serial_tty_driver = tty_alloc_driver(USB_SERIAL_TTY_MINORS,
TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(usb_serial_tty_driver))
return PTR_ERR(usb_serial_tty_driver);
/* Initialize our global data */
result = bus_register(&usb_serial_bus_type);
@ -1336,8 +1337,6 @@ static int __init usb_serial_init(void)
usb_serial_tty_driver->minor_start = 0;
usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV;
usb_serial_tty_driver->init_termios = tty_std_termios;
usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
| HUPCL | CLOCAL;
@ -1367,7 +1366,7 @@ exit_reg_driver:
exit_bus:
pr_err("%s - returning with error %d\n", __func__, result);
put_tty_driver(usb_serial_tty_driver);
tty_driver_kref_put(usb_serial_tty_driver);
return result;
}
@ -1379,7 +1378,7 @@ static void __exit usb_serial_exit(void)
usb_serial_generic_deregister();
tty_unregister_driver(usb_serial_tty_driver);
put_tty_driver(usb_serial_tty_driver);
tty_driver_kref_put(usb_serial_tty_driver);
bus_unregister(&usb_serial_bus_type);
idr_destroy(&serial_minors);
}

View File

@ -327,4 +327,18 @@ static inline int serdev_tty_port_unregister(struct tty_port *port)
}
#endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */
struct acpi_resource;
struct acpi_resource_uart_serialbus;
#ifdef CONFIG_ACPI
bool serdev_acpi_get_uart_resource(struct acpi_resource *ares,
struct acpi_resource_uart_serialbus **uart);
#else
static inline bool serdev_acpi_get_uart_resource(struct acpi_resource *ares,
struct acpi_resource_uart_serialbus **uart)
{
return false;
}
#endif /* CONFIG_ACPI */
#endif /*_LINUX_SERDEV_H */

View File

@ -27,6 +27,15 @@
#define S3C2410_UERSTAT (0x14)
#define S3C2410_UFSTAT (0x18)
#define S3C2410_UMSTAT (0x1C)
#define USI_CON (0xC4)
#define USI_OPTION (0xC8)
#define USI_CON_RESET (1<<0)
#define USI_CON_RESET_MASK (1<<0)
#define USI_OPTION_HWACG_CLKREQ_ON (1<<1)
#define USI_OPTION_HWACG_CLKSTOP_ON (1<<2)
#define USI_OPTION_HWACG_MASK (3<<1)
#define S3C2410_LCON_CFGMASK ((0xF<<3)|(0x3))

View File

@ -6,11 +6,12 @@
#include <linux/major.h>
#include <linux/termios.h>
#include <linux/workqueue.h>
#include <linux/tty_buffer.h>
#include <linux/tty_driver.h>
#include <linux/tty_ldisc.h>
#include <linux/tty_port.h>
#include <linux/mutex.h>
#include <linux/tty_flags.h>
#include <linux/seq_file.h>
#include <uapi/linux/tty.h>
#include <linux/rwsem.h>
#include <linux/llist.h>
@ -31,54 +32,6 @@
*/
#define __DISABLED_CHAR '\0'
struct tty_buffer {
union {
struct tty_buffer *next;
struct llist_node free;
};
int used;
int size;
int commit;
int read;
int flags;
/* Data points here */
unsigned long data[];
};
/* Values for .flags field of tty_buffer */
#define TTYB_NORMAL 1 /* buffer has no flags buffer */
static inline unsigned char *char_buf_ptr(struct tty_buffer *b, int ofs)
{
return ((unsigned char *)b->data) + ofs;
}
static inline char *flag_buf_ptr(struct tty_buffer *b, int ofs)
{
return (char *)char_buf_ptr(b, ofs) + b->size;
}
struct tty_bufhead {
struct tty_buffer *head; /* Queue head */
struct work_struct work;
struct mutex lock;
atomic_t priority;
struct tty_buffer sentinel;
struct llist_head free; /* Free queue head */
atomic_t mem_used; /* In-use buffers excluding free list */
int mem_limit;
struct tty_buffer *tail; /* Active buffer */
};
/*
* When a break, frame error, or parity error happens, these codes are
* stuffed into the flags buffer.
*/
#define TTY_NORMAL 0
#define TTY_BREAK 1
#define TTY_FRAME 2
#define TTY_PARITY 3
#define TTY_OVERRUN 4
#define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR])
#define QUIT_CHAR(tty) ((tty)->termios.c_cc[VQUIT])
#define ERASE_CHAR(tty) ((tty)->termios.c_cc[VERASE])
@ -164,85 +117,6 @@ struct tty_bufhead {
struct device;
struct signal_struct;
/*
* Port level information. Each device keeps its own port level information
* so provide a common structure for those ports wanting to use common support
* routines.
*
* The tty port has a different lifetime to the tty so must be kept apart.
* In addition be careful as tty -> port mappings are valid for the life
* of the tty object but in many cases port -> tty mappings are valid only
* until a hangup so don't use the wrong path.
*/
struct tty_port;
struct tty_port_operations {
/* Return 1 if the carrier is raised */
int (*carrier_raised)(struct tty_port *port);
/* Control the DTR line */
void (*dtr_rts)(struct tty_port *port, int raise);
/* Called when the last close completes or a hangup finishes
IFF the port was initialized. Do not use to free resources. Called
under the port mutex to serialize against activate/shutdowns */
void (*shutdown)(struct tty_port *port);
/* Called under the port mutex from tty_port_open, serialized using
the port mutex */
/* FIXME: long term getting the tty argument *out* of this would be
good for consoles */
int (*activate)(struct tty_port *port, struct tty_struct *tty);
/* Called on the final put of a port */
void (*destruct)(struct tty_port *port);
};
struct tty_port_client_operations {
int (*receive_buf)(struct tty_port *port, const unsigned char *, const unsigned char *, size_t);
void (*write_wakeup)(struct tty_port *port);
};
extern const struct tty_port_client_operations tty_port_default_client_ops;
struct tty_port {
struct tty_bufhead buf; /* Locked internally */
struct tty_struct *tty; /* Back pointer */
struct tty_struct *itty; /* internal back ptr */
const struct tty_port_operations *ops; /* Port operations */
const struct tty_port_client_operations *client_ops; /* Port client operations */
spinlock_t lock; /* Lock protecting tty field */
int blocked_open; /* Waiting to open */
int count; /* Usage count */
wait_queue_head_t open_wait; /* Open waiters */
wait_queue_head_t delta_msr_wait; /* Modem status change */
unsigned long flags; /* User TTY flags ASYNC_ */
unsigned long iflags; /* Internal flags TTY_PORT_ */
unsigned char console:1; /* port is a console */
struct mutex mutex; /* Locking */
struct mutex buf_mutex; /* Buffer alloc lock */
unsigned char *xmit_buf; /* Optional buffer */
unsigned int close_delay; /* Close port delay */
unsigned int closing_wait; /* Delay for output */
int drain_delay; /* Set to zero if no pure time
based drain is needed else
set to size of fifo */
struct kref kref; /* Ref counter */
void *client_data;
};
/* tty_port::iflags bits -- use atomic bit ops */
#define TTY_PORT_INITIALIZED 0 /* device is initialized */
#define TTY_PORT_SUSPENDED 1 /* device is suspended */
#define TTY_PORT_ACTIVE 2 /* device is open */
/*
* uart drivers: use the uart_port::status field and the UPSTAT_* defines
* for s/w-based flow control steering and carrier detection status
*/
#define TTY_PORT_CTS_FLOW 3 /* h/w flow control enabled */
#define TTY_PORT_CHECK_CD 4 /* carrier detect enabled */
#define TTY_PORT_KOPENED 5 /* device exclusively opened by
kernel */
struct tty_operations;
/**
@ -446,15 +320,6 @@ extern const char *tty_driver_name(const struct tty_struct *tty);
extern void tty_wait_until_sent(struct tty_struct *tty, long timeout);
extern void stop_tty(struct tty_struct *tty);
extern void start_tty(struct tty_struct *tty);
extern int tty_register_driver(struct tty_driver *driver);
extern void tty_unregister_driver(struct tty_driver *driver);
extern struct device *tty_register_device(struct tty_driver *driver,
unsigned index, struct device *dev);
extern struct device *tty_register_device_attr(struct tty_driver *driver,
unsigned index, struct device *device,
void *drvdata,
const struct attribute_group **attr_grp);
extern void tty_unregister_device(struct tty_driver *driver, unsigned index);
extern void tty_write_message(struct tty_struct *tty, char *msg);
extern int tty_send_xchar(struct tty_struct *tty, char ch);
extern int tty_put_char(struct tty_struct *tty, unsigned char c);
@ -502,13 +367,7 @@ extern void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old);
extern int tty_termios_hw_change(const struct ktermios *a, const struct ktermios *b);
extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt);
extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
extern void tty_ldisc_deref(struct tty_ldisc *);
extern struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *);
extern const struct seq_operations tty_ldiscs_seq_ops;
extern void tty_wakeup(struct tty_struct *tty);
extern void tty_ldisc_flush(struct tty_struct *tty);
extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
@ -522,128 +381,6 @@ extern int tty_standard_install(struct tty_driver *driver,
extern struct mutex tty_mutex;
extern void tty_port_init(struct tty_port *port);
extern void tty_port_link_device(struct tty_port *port,
struct tty_driver *driver, unsigned index);
extern struct device *tty_port_register_device(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device);
extern struct device *tty_port_register_device_attr(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device, void *drvdata,
const struct attribute_group **attr_grp);
extern struct device *tty_port_register_device_serdev(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device);
extern struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device, void *drvdata,
const struct attribute_group **attr_grp);
extern void tty_port_unregister_device(struct tty_port *port,
struct tty_driver *driver, unsigned index);
extern int tty_port_alloc_xmit_buf(struct tty_port *port);
extern void tty_port_free_xmit_buf(struct tty_port *port);
extern void tty_port_destroy(struct tty_port *port);
extern void tty_port_put(struct tty_port *port);
static inline struct tty_port *tty_port_get(struct tty_port *port)
{
if (port && kref_get_unless_zero(&port->kref))
return port;
return NULL;
}
/* If the cts flow control is enabled, return true. */
static inline bool tty_port_cts_enabled(const struct tty_port *port)
{
return test_bit(TTY_PORT_CTS_FLOW, &port->iflags);
}
static inline void tty_port_set_cts_flow(struct tty_port *port, bool val)
{
assign_bit(TTY_PORT_CTS_FLOW, &port->iflags, val);
}
static inline bool tty_port_active(const struct tty_port *port)
{
return test_bit(TTY_PORT_ACTIVE, &port->iflags);
}
static inline void tty_port_set_active(struct tty_port *port, bool val)
{
assign_bit(TTY_PORT_ACTIVE, &port->iflags, val);
}
static inline bool tty_port_check_carrier(const struct tty_port *port)
{
return test_bit(TTY_PORT_CHECK_CD, &port->iflags);
}
static inline void tty_port_set_check_carrier(struct tty_port *port, bool val)
{
assign_bit(TTY_PORT_CHECK_CD, &port->iflags, val);
}
static inline bool tty_port_suspended(const struct tty_port *port)
{
return test_bit(TTY_PORT_SUSPENDED, &port->iflags);
}
static inline void tty_port_set_suspended(struct tty_port *port, bool val)
{
assign_bit(TTY_PORT_SUSPENDED, &port->iflags, val);
}
static inline bool tty_port_initialized(const struct tty_port *port)
{
return test_bit(TTY_PORT_INITIALIZED, &port->iflags);
}
static inline void tty_port_set_initialized(struct tty_port *port, bool val)
{
assign_bit(TTY_PORT_INITIALIZED, &port->iflags, val);
}
static inline bool tty_port_kopened(const struct tty_port *port)
{
return test_bit(TTY_PORT_KOPENED, &port->iflags);
}
static inline void tty_port_set_kopened(struct tty_port *port, bool val)
{
assign_bit(TTY_PORT_KOPENED, &port->iflags, val);
}
extern struct tty_struct *tty_port_tty_get(struct tty_port *port);
extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty);
extern int tty_port_carrier_raised(struct tty_port *port);
extern void tty_port_raise_dtr_rts(struct tty_port *port);
extern void tty_port_lower_dtr_rts(struct tty_port *port);
extern void tty_port_hangup(struct tty_port *port);
extern void tty_port_tty_hangup(struct tty_port *port, bool check_clocal);
extern void tty_port_tty_wakeup(struct tty_port *port);
extern int tty_port_block_til_ready(struct tty_port *port,
struct tty_struct *tty, struct file *filp);
extern int tty_port_close_start(struct tty_port *port,
struct tty_struct *tty, struct file *filp);
extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);
extern void tty_port_close(struct tty_port *port,
struct tty_struct *tty, struct file *filp);
extern int tty_port_install(struct tty_port *port, struct tty_driver *driver,
struct tty_struct *tty);
extern int tty_port_open(struct tty_port *port,
struct tty_struct *tty, struct file *filp);
static inline int tty_port_users(struct tty_port *port)
{
return port->count + port->blocked_open;
}
extern int tty_register_ldisc(struct tty_ldisc_ops *new_ldisc);
extern void tty_unregister_ldisc(struct tty_ldisc_ops *ldisc);
extern int tty_set_ldisc(struct tty_struct *tty, int disc);
extern int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p,
const char *f, int count);
/* n_tty.c */
extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops);
#ifdef CONFIG_TTY
@ -691,12 +428,4 @@ extern void tty_lock_slave(struct tty_struct *tty);
extern void tty_unlock_slave(struct tty_struct *tty);
extern void tty_set_lock_subclass(struct tty_struct *tty);
#ifdef CONFIG_PROC_FS
extern void proc_tty_register_driver(struct tty_driver *);
extern void proc_tty_unregister_driver(struct tty_driver *);
#else
static inline void proc_tty_register_driver(struct tty_driver *d) {}
static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
#endif
#endif

View File

@ -0,0 +1,59 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_TTY_BUFFER_H
#define _LINUX_TTY_BUFFER_H
#include <linux/atomic.h>
#include <linux/llist.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
struct tty_buffer {
union {
struct tty_buffer *next;
struct llist_node free;
};
int used;
int size;
int commit;
int read;
int flags;
/* Data points here */
unsigned long data[];
};
/* Values for .flags field of tty_buffer */
#define TTYB_NORMAL 1 /* buffer has no flags buffer */
static inline unsigned char *char_buf_ptr(struct tty_buffer *b, int ofs)
{
return ((unsigned char *)b->data) + ofs;
}
static inline char *flag_buf_ptr(struct tty_buffer *b, int ofs)
{
return (char *)char_buf_ptr(b, ofs) + b->size;
}
struct tty_bufhead {
struct tty_buffer *head; /* Queue head */
struct work_struct work;
struct mutex lock;
atomic_t priority;
struct tty_buffer sentinel;
struct llist_head free; /* Free queue head */
atomic_t mem_used; /* In-use buffers excluding free list */
int mem_limit;
struct tty_buffer *tail; /* Active buffer */
};
/*
* When a break, frame error, or parity error happens, these codes are
* stuffed into the flags buffer.
*/
#define TTY_NORMAL 0
#define TTY_BREAK 1
#define TTY_FRAME 2
#define TTY_PARITY 3
#define TTY_OVERRUN 4
#endif

View File

@ -233,6 +233,7 @@
#include <linux/export.h>
#include <linux/fs.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/cdev.h>
#include <linux/termios.h>
@ -328,9 +329,6 @@ extern struct list_head tty_drivers;
extern struct tty_driver *__tty_alloc_driver(unsigned int lines,
struct module *owner, unsigned long flags);
extern void put_tty_driver(struct tty_driver *driver);
extern void tty_set_operations(struct tty_driver *driver,
const struct tty_operations *op);
extern struct tty_driver *tty_find_polling_driver(char *name, int *line);
extern void tty_driver_kref_put(struct tty_driver *driver);
@ -339,24 +337,18 @@ extern void tty_driver_kref_put(struct tty_driver *driver);
#define tty_alloc_driver(lines, flags) \
__tty_alloc_driver(lines, THIS_MODULE, flags)
/*
* DEPRECATED Do not use this in new code, use tty_alloc_driver instead.
* (And change the return value checks.)
*/
static inline struct tty_driver *alloc_tty_driver(unsigned int lines)
{
struct tty_driver *ret = tty_alloc_driver(lines, 0);
if (IS_ERR(ret))
return NULL;
return ret;
}
static inline struct tty_driver *tty_driver_kref_get(struct tty_driver *d)
{
kref_get(&d->kref);
return d;
}
static inline void tty_set_operations(struct tty_driver *driver,
const struct tty_operations *op)
{
driver->ops = op;
}
/* tty driver magic number */
#define TTY_DRIVER_MAGIC 0x5402
@ -434,4 +426,21 @@ static inline struct tty_driver *tty_driver_kref_get(struct tty_driver *d)
/* serial subtype definitions */
#define SERIAL_TYPE_NORMAL 1
int tty_register_driver(struct tty_driver *driver);
void tty_unregister_driver(struct tty_driver *driver);
struct device *tty_register_device(struct tty_driver *driver, unsigned index,
struct device *dev);
struct device *tty_register_device_attr(struct tty_driver *driver,
unsigned index, struct device *device, void *drvdata,
const struct attribute_group **attr_grp);
void tty_unregister_device(struct tty_driver *driver, unsigned index);
#ifdef CONFIG_PROC_FS
void proc_tty_register_driver(struct tty_driver *);
void proc_tty_unregister_driver(struct tty_driver *);
#else
static inline void proc_tty_register_driver(struct tty_driver *d) {}
static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
#endif
#endif /* #ifdef _LINUX_TTY_DRIVER_H */

View File

@ -2,7 +2,10 @@
#ifndef _LINUX_TTY_FLIP_H
#define _LINUX_TTY_FLIP_H
#include <linux/tty.h>
#include <linux/tty_buffer.h>
#include <linux/tty_port.h>
struct tty_ldisc;
extern int tty_buffer_set_limit(struct tty_port *port, int limit);
extern unsigned int tty_buffer_space_avail(struct tty_port *port);
@ -39,6 +42,9 @@ static inline int tty_insert_flip_string(struct tty_port *port,
return tty_insert_flip_string_fixed_flag(port, chars, TTY_NORMAL, size);
}
int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p,
const char *f, int count);
extern void tty_buffer_lock_exclusive(struct tty_port *port);
extern void tty_buffer_unlock_exclusive(struct tty_port *port);

View File

@ -2,6 +2,8 @@
#ifndef _LINUX_TTY_LDISC_H
#define _LINUX_TTY_LDISC_H
struct tty_struct;
/*
* This structure defines the interface between the tty line discipline
* implementation and the tty routines. The following routines can be
@ -126,6 +128,9 @@
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/atomic.h>
#include <linux/list.h>
#include <linux/lockdep.h>
#include <linux/seq_file.h>
/*
* the semaphore definition
@ -220,4 +225,16 @@ struct tty_ldisc {
#define MODULE_ALIAS_LDISC(ldisc) \
MODULE_ALIAS("tty-ldisc-" __stringify(ldisc))
extern const struct seq_operations tty_ldiscs_seq_ops;
struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
void tty_ldisc_deref(struct tty_ldisc *);
struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *);
void tty_ldisc_flush(struct tty_struct *tty);
int tty_register_ldisc(struct tty_ldisc_ops *new_ldisc);
void tty_unregister_ldisc(struct tty_ldisc_ops *ldisc);
int tty_set_ldisc(struct tty_struct *tty, int disc);
#endif /* _LINUX_TTY_LDISC_H */

208
include/linux/tty_port.h Normal file
View File

@ -0,0 +1,208 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_TTY_PORT_H
#define _LINUX_TTY_PORT_H
#include <linux/kref.h>
#include <linux/mutex.h>
#include <linux/tty_buffer.h>
#include <linux/wait.h>
/*
* Port level information. Each device keeps its own port level information
* so provide a common structure for those ports wanting to use common support
* routines.
*
* The tty port has a different lifetime to the tty so must be kept apart.
* In addition be careful as tty -> port mappings are valid for the life
* of the tty object but in many cases port -> tty mappings are valid only
* until a hangup so don't use the wrong path.
*/
struct attribute_group;
struct tty_driver;
struct tty_port;
struct tty_struct;
struct tty_port_operations {
/* Return 1 if the carrier is raised */
int (*carrier_raised)(struct tty_port *port);
/* Control the DTR line */
void (*dtr_rts)(struct tty_port *port, int raise);
/* Called when the last close completes or a hangup finishes
IFF the port was initialized. Do not use to free resources. Called
under the port mutex to serialize against activate/shutdowns */
void (*shutdown)(struct tty_port *port);
/* Called under the port mutex from tty_port_open, serialized using
the port mutex */
/* FIXME: long term getting the tty argument *out* of this would be
good for consoles */
int (*activate)(struct tty_port *port, struct tty_struct *tty);
/* Called on the final put of a port */
void (*destruct)(struct tty_port *port);
};
struct tty_port_client_operations {
int (*receive_buf)(struct tty_port *port, const unsigned char *, const unsigned char *, size_t);
void (*write_wakeup)(struct tty_port *port);
};
extern const struct tty_port_client_operations tty_port_default_client_ops;
struct tty_port {
struct tty_bufhead buf; /* Locked internally */
struct tty_struct *tty; /* Back pointer */
struct tty_struct *itty; /* internal back ptr */
const struct tty_port_operations *ops; /* Port operations */
const struct tty_port_client_operations *client_ops; /* Port client operations */
spinlock_t lock; /* Lock protecting tty field */
int blocked_open; /* Waiting to open */
int count; /* Usage count */
wait_queue_head_t open_wait; /* Open waiters */
wait_queue_head_t delta_msr_wait; /* Modem status change */
unsigned long flags; /* User TTY flags ASYNC_ */
unsigned long iflags; /* Internal flags TTY_PORT_ */
unsigned char console:1; /* port is a console */
struct mutex mutex; /* Locking */
struct mutex buf_mutex; /* Buffer alloc lock */
unsigned char *xmit_buf; /* Optional buffer */
unsigned int close_delay; /* Close port delay */
unsigned int closing_wait; /* Delay for output */
int drain_delay; /* Set to zero if no pure time
based drain is needed else
set to size of fifo */
struct kref kref; /* Ref counter */
void *client_data;
};
/* tty_port::iflags bits -- use atomic bit ops */
#define TTY_PORT_INITIALIZED 0 /* device is initialized */
#define TTY_PORT_SUSPENDED 1 /* device is suspended */
#define TTY_PORT_ACTIVE 2 /* device is open */
/*
* uart drivers: use the uart_port::status field and the UPSTAT_* defines
* for s/w-based flow control steering and carrier detection status
*/
#define TTY_PORT_CTS_FLOW 3 /* h/w flow control enabled */
#define TTY_PORT_CHECK_CD 4 /* carrier detect enabled */
#define TTY_PORT_KOPENED 5 /* device exclusively opened by
kernel */
void tty_port_init(struct tty_port *port);
void tty_port_link_device(struct tty_port *port, struct tty_driver *driver,
unsigned index);
struct device *tty_port_register_device(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device);
struct device *tty_port_register_device_attr(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device, void *drvdata,
const struct attribute_group **attr_grp);
struct device *tty_port_register_device_serdev(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device);
struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device, void *drvdata,
const struct attribute_group **attr_grp);
void tty_port_unregister_device(struct tty_port *port,
struct tty_driver *driver, unsigned index);
int tty_port_alloc_xmit_buf(struct tty_port *port);
void tty_port_free_xmit_buf(struct tty_port *port);
void tty_port_destroy(struct tty_port *port);
void tty_port_put(struct tty_port *port);
static inline struct tty_port *tty_port_get(struct tty_port *port)
{
if (port && kref_get_unless_zero(&port->kref))
return port;
return NULL;
}
/* If the cts flow control is enabled, return true. */
static inline bool tty_port_cts_enabled(const struct tty_port *port)
{
return test_bit(TTY_PORT_CTS_FLOW, &port->iflags);
}
static inline void tty_port_set_cts_flow(struct tty_port *port, bool val)
{
assign_bit(TTY_PORT_CTS_FLOW, &port->iflags, val);
}
static inline bool tty_port_active(const struct tty_port *port)
{
return test_bit(TTY_PORT_ACTIVE, &port->iflags);
}
static inline void tty_port_set_active(struct tty_port *port, bool val)
{
assign_bit(TTY_PORT_ACTIVE, &port->iflags, val);
}
static inline bool tty_port_check_carrier(const struct tty_port *port)
{
return test_bit(TTY_PORT_CHECK_CD, &port->iflags);
}
static inline void tty_port_set_check_carrier(struct tty_port *port, bool val)
{
assign_bit(TTY_PORT_CHECK_CD, &port->iflags, val);
}
static inline bool tty_port_suspended(const struct tty_port *port)
{
return test_bit(TTY_PORT_SUSPENDED, &port->iflags);
}
static inline void tty_port_set_suspended(struct tty_port *port, bool val)
{
assign_bit(TTY_PORT_SUSPENDED, &port->iflags, val);
}
static inline bool tty_port_initialized(const struct tty_port *port)
{
return test_bit(TTY_PORT_INITIALIZED, &port->iflags);
}
static inline void tty_port_set_initialized(struct tty_port *port, bool val)
{
assign_bit(TTY_PORT_INITIALIZED, &port->iflags, val);
}
static inline bool tty_port_kopened(const struct tty_port *port)
{
return test_bit(TTY_PORT_KOPENED, &port->iflags);
}
static inline void tty_port_set_kopened(struct tty_port *port, bool val)
{
assign_bit(TTY_PORT_KOPENED, &port->iflags, val);
}
struct tty_struct *tty_port_tty_get(struct tty_port *port);
void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty);
int tty_port_carrier_raised(struct tty_port *port);
void tty_port_raise_dtr_rts(struct tty_port *port);
void tty_port_lower_dtr_rts(struct tty_port *port);
void tty_port_hangup(struct tty_port *port);
void tty_port_tty_hangup(struct tty_port *port, bool check_clocal);
void tty_port_tty_wakeup(struct tty_port *port);
int tty_port_block_til_ready(struct tty_port *port, struct tty_struct *tty,
struct file *filp);
int tty_port_close_start(struct tty_port *port, struct tty_struct *tty,
struct file *filp);
void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);
void tty_port_close(struct tty_port *port, struct tty_struct *tty,
struct file *filp);
int tty_port_install(struct tty_port *port, struct tty_driver *driver,
struct tty_struct *tty);
int tty_port_open(struct tty_port *port, struct tty_struct *tty,
struct file *filp);
static inline int tty_port_users(struct tty_port *port)
{
return port->count + port->blocked_open;
}
#endif

View File

@ -148,26 +148,26 @@ void hide_boot_cursor(bool hide);
/* keyboard provided interfaces */
int vt_do_diacrit(unsigned int cmd, void __user *up, int eperm);
int vt_do_kdskbmode(int console, unsigned int arg);
int vt_do_kdskbmeta(int console, unsigned int arg);
int vt_do_kdskbmode(unsigned int console, unsigned int arg);
int vt_do_kdskbmeta(unsigned int console, unsigned int arg);
int vt_do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc,
int perm);
int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
int console);
unsigned int console);
int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm);
int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm);
int vt_do_kdgkbmode(int console);
int vt_do_kdgkbmeta(int console);
void vt_reset_unicode(int console);
int vt_do_kdskled(unsigned int console, int cmd, unsigned long arg, int perm);
int vt_do_kdgkbmode(unsigned int console);
int vt_do_kdgkbmeta(unsigned int console);
void vt_reset_unicode(unsigned int console);
int vt_get_shift_state(void);
void vt_reset_keyboard(int console);
int vt_get_leds(int console, int flag);
int vt_get_kbd_mode_bit(int console, int bit);
void vt_set_kbd_mode_bit(int console, int bit);
void vt_clr_kbd_mode_bit(int console, int bit);
void vt_set_led_state(int console, int leds);
void vt_kbd_con_start(int console);
void vt_kbd_con_stop(int console);
void vt_reset_keyboard(unsigned int console);
int vt_get_leds(unsigned int console, int flag);
int vt_get_kbd_mode_bit(unsigned int console, int bit);
void vt_set_kbd_mode_bit(unsigned int console, int bit);
void vt_clr_kbd_mode_bit(unsigned int console, int bit);
void vt_set_led_state(unsigned int console, int leds);
void vt_kbd_con_start(unsigned int console);
void vt_kbd_con_stop(unsigned int console);
void vc_scrolldelta_helper(struct vc_data *c, int lines,
unsigned int rolled_over, void *_base, unsigned int size);

View File

@ -62,6 +62,7 @@
* ST16C654: 8 16 56 60 8 16 32 56 PORT_16654
* TI16C750: 1 16 32 56 xx xx xx xx PORT_16750
* TI16C752: 8 16 56 60 8 16 32 56
* OX16C950: 16 32 112 120 16 32 64 112 PORT_16C950
* Tegra: 1 4 8 14 16 8 4 1 PORT_TEGRA
*/
#define UART_FCR_R_TRIG_00 0x00

View File

@ -1127,9 +1127,10 @@ int __init rfcomm_init_ttys(void)
{
int error;
rfcomm_tty_driver = alloc_tty_driver(RFCOMM_TTY_PORTS);
if (!rfcomm_tty_driver)
return -ENOMEM;
rfcomm_tty_driver = tty_alloc_driver(RFCOMM_TTY_PORTS,
TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(rfcomm_tty_driver))
return PTR_ERR(rfcomm_tty_driver);
rfcomm_tty_driver->driver_name = "rfcomm";
rfcomm_tty_driver->name = "rfcomm";
@ -1137,7 +1138,6 @@ int __init rfcomm_init_ttys(void)
rfcomm_tty_driver->minor_start = RFCOMM_TTY_MINOR;
rfcomm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL;
rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
rfcomm_tty_driver->init_termios = tty_std_termios;
rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON;
@ -1146,7 +1146,7 @@ int __init rfcomm_init_ttys(void)
error = tty_register_driver(rfcomm_tty_driver);
if (error) {
BT_ERR("Can't register RFCOMM TTY driver");
put_tty_driver(rfcomm_tty_driver);
tty_driver_kref_put(rfcomm_tty_driver);
return error;
}
@ -1158,5 +1158,5 @@ int __init rfcomm_init_ttys(void)
void rfcomm_cleanup_ttys(void)
{
tty_unregister_driver(rfcomm_tty_driver);
put_tty_driver(rfcomm_tty_driver);
tty_driver_kref_put(rfcomm_tty_driver);
}