TTY/Serial fixes for 4.12-rc3
Here are some serial and tty fixes for 4.12-rc3. They are a bit "bigger" than normal, which is why I had them "bake" in linux-next for a few weeks and didn't send them to you for -rc2. They revert a few of the serdev patches from 4.12-rc1, and bring things back to how they were in 4.11, to try to make things a bit more stable there. Rob and Johan both agree that this is the way forward, so this isn't people squabbling over semantics. Other than that, just a few minor serial driver fixes that people have had problems with. All of these have been in linux-next for a few weeks with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCWSlOHA8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ylDCACgn7RHT16JUASggJmRUBeadxQcFQAAnjtxX2kc 0AQLqXxqGyFxVZClAYMy =Y6+X -----END PGP SIGNATURE----- Merge tag 'tty-4.12-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty Pull tty/serial fixes from Greg KH: "Here are some serial and tty fixes for 4.12-rc3. They are a bit bigger than normal, which is why I had them bake in linux-next for a few weeks and didn't send them to you for -rc2. They revert a few of the serdev patches from 4.12-rc1, and bring things back to how they were in 4.11, to try to make things a bit more stable there. Rob and Johan both agree that this is the way forward, so this isn't people squabbling over semantics. Other than that, just a few minor serial driver fixes that people have had problems with. All of these have been in linux-next for a few weeks with no reported issues" * tag 'tty-4.12-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: serial: altera_uart: call iounmap() at driver remove serial: imx: ensure UCR3 and UFCR are setup correctly MAINTAINERS/serial: Change maintainer of jsm driver serial: enable serdev support tty/serdev: add serdev registration interface serdev: Restore serdev_device_write_buf for atomic context serial: core: fix crash in uart_suspend_port tty: fix port buffer locking tty: ehv_bytechan: clean up init error handling serial: ifx6x60: fix use-after-free on module unload serial: altera_jtaguart: adding iounmap() serial: exar: Fix stuck MSIs serial: efm32: Fix parity management in 'efm32_uart_console_get_options()' serdev: fix tty-port client deregistration Revert "tty_port: register tty ports with serdev bus" drivers/tty: 8250: only call fintek_8250_probe when doing port I/O
This commit is contained in:
commit
249f1efd8e
@ -7143,7 +7143,7 @@ S: Maintained
|
||||
F: drivers/media/platform/rcar_jpu.c
|
||||
|
||||
JSM Neo PCI based serial card
|
||||
M: Gabriel Krisman Bertazi <krisman@linux.vnet.ibm.com>
|
||||
M: Guilherme G. Piccoli <gpiccoli@linux.vnet.ibm.com>
|
||||
L: linux-serial@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/tty/serial/jsm/
|
||||
|
@ -764,7 +764,7 @@ static int __init ehv_bc_init(void)
|
||||
ehv_bc_driver = alloc_tty_driver(count);
|
||||
if (!ehv_bc_driver) {
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
goto err_free_bcs;
|
||||
}
|
||||
|
||||
ehv_bc_driver->driver_name = "ehv-bc";
|
||||
@ -778,24 +778,23 @@ static int __init ehv_bc_init(void)
|
||||
ret = tty_register_driver(ehv_bc_driver);
|
||||
if (ret) {
|
||||
pr_err("ehv-bc: could not register tty driver (ret=%i)\n", ret);
|
||||
goto error;
|
||||
goto err_put_tty_driver;
|
||||
}
|
||||
|
||||
ret = platform_driver_register(&ehv_bc_tty_driver);
|
||||
if (ret) {
|
||||
pr_err("ehv-bc: could not register platform driver (ret=%i)\n",
|
||||
ret);
|
||||
goto error;
|
||||
goto err_deregister_tty_driver;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (ehv_bc_driver) {
|
||||
tty_unregister_driver(ehv_bc_driver);
|
||||
put_tty_driver(ehv_bc_driver);
|
||||
}
|
||||
|
||||
err_deregister_tty_driver:
|
||||
tty_unregister_driver(ehv_bc_driver);
|
||||
err_put_tty_driver:
|
||||
put_tty_driver(ehv_bc_driver);
|
||||
err_free_bcs:
|
||||
kfree(bcs);
|
||||
|
||||
return ret;
|
||||
|
@ -122,6 +122,18 @@ void serdev_device_write_wakeup(struct serdev_device *serdev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(serdev_device_write_wakeup);
|
||||
|
||||
int serdev_device_write_buf(struct serdev_device *serdev,
|
||||
const unsigned char *buf, size_t count)
|
||||
{
|
||||
struct serdev_controller *ctrl = serdev->ctrl;
|
||||
|
||||
if (!ctrl || !ctrl->ops->write_buf)
|
||||
return -EINVAL;
|
||||
|
||||
return ctrl->ops->write_buf(ctrl, buf, count);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(serdev_device_write_buf);
|
||||
|
||||
int serdev_device_write(struct serdev_device *serdev,
|
||||
const unsigned char *buf, size_t count,
|
||||
unsigned long timeout)
|
||||
|
@ -102,9 +102,6 @@ static int ttyport_open(struct serdev_controller *ctrl)
|
||||
return PTR_ERR(tty);
|
||||
serport->tty = tty;
|
||||
|
||||
serport->port->client_ops = &client_ops;
|
||||
serport->port->client_data = ctrl;
|
||||
|
||||
if (tty->ops->open)
|
||||
tty->ops->open(serport->tty, NULL);
|
||||
else
|
||||
@ -215,6 +212,7 @@ struct device *serdev_tty_port_register(struct tty_port *port,
|
||||
struct device *parent,
|
||||
struct tty_driver *drv, int idx)
|
||||
{
|
||||
const struct tty_port_client_operations *old_ops;
|
||||
struct serdev_controller *ctrl;
|
||||
struct serport *serport;
|
||||
int ret;
|
||||
@ -233,28 +231,37 @@ struct device *serdev_tty_port_register(struct tty_port *port,
|
||||
|
||||
ctrl->ops = &ctrl_ops;
|
||||
|
||||
old_ops = port->client_ops;
|
||||
port->client_ops = &client_ops;
|
||||
port->client_data = ctrl;
|
||||
|
||||
ret = serdev_controller_add(ctrl);
|
||||
if (ret)
|
||||
goto err_controller_put;
|
||||
goto err_reset_data;
|
||||
|
||||
dev_info(&ctrl->dev, "tty port %s%d registered\n", drv->name, idx);
|
||||
return &ctrl->dev;
|
||||
|
||||
err_controller_put:
|
||||
err_reset_data:
|
||||
port->client_data = NULL;
|
||||
port->client_ops = old_ops;
|
||||
serdev_controller_put(ctrl);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
void serdev_tty_port_unregister(struct tty_port *port)
|
||||
int serdev_tty_port_unregister(struct tty_port *port)
|
||||
{
|
||||
struct serdev_controller *ctrl = port->client_data;
|
||||
struct serport *serport = serdev_controller_get_drvdata(ctrl);
|
||||
|
||||
if (!serport)
|
||||
return;
|
||||
return -ENODEV;
|
||||
|
||||
serdev_controller_remove(ctrl);
|
||||
port->client_ops = NULL;
|
||||
port->client_data = NULL;
|
||||
serdev_controller_put(ctrl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -47,6 +47,7 @@
|
||||
/*
|
||||
* These are definitions for the Exar XR17V35X and XR17(C|D)15X
|
||||
*/
|
||||
#define UART_EXAR_INT0 0x80
|
||||
#define UART_EXAR_SLEEP 0x8b /* Sleep mode */
|
||||
#define UART_EXAR_DVID 0x8d /* Device identification */
|
||||
|
||||
@ -1337,7 +1338,7 @@ out_lock:
|
||||
/*
|
||||
* Check if the device is a Fintek F81216A
|
||||
*/
|
||||
if (port->type == PORT_16550A)
|
||||
if (port->type == PORT_16550A && port->iotype == UPIO_PORT)
|
||||
fintek_8250_probe(up);
|
||||
|
||||
if (up->capabilities != old_capabilities) {
|
||||
@ -1869,17 +1870,13 @@ static int serial8250_default_handle_irq(struct uart_port *port)
|
||||
static int exar_handle_irq(struct uart_port *port)
|
||||
{
|
||||
unsigned int iir = serial_port_in(port, UART_IIR);
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
ret = serial8250_handle_irq(port, iir);
|
||||
if (((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) &&
|
||||
serial_port_in(port, UART_EXAR_INT0) != 0)
|
||||
ret = 1;
|
||||
|
||||
if ((port->type == PORT_XR17V35X) ||
|
||||
(port->type == PORT_XR17D15X)) {
|
||||
serial_port_in(port, 0x80);
|
||||
serial_port_in(port, 0x81);
|
||||
serial_port_in(port, 0x82);
|
||||
serial_port_in(port, 0x83);
|
||||
}
|
||||
ret |= serial8250_handle_irq(port, iir);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -2177,6 +2174,8 @@ int serial8250_do_startup(struct uart_port *port)
|
||||
serial_port_in(port, UART_RX);
|
||||
serial_port_in(port, UART_IIR);
|
||||
serial_port_in(port, UART_MSR);
|
||||
if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X))
|
||||
serial_port_in(port, UART_EXAR_INT0);
|
||||
|
||||
/*
|
||||
* At this point, there's no way the LSR could still be 0xff;
|
||||
@ -2335,6 +2334,8 @@ dont_test_tx_en:
|
||||
serial_port_in(port, UART_RX);
|
||||
serial_port_in(port, UART_IIR);
|
||||
serial_port_in(port, UART_MSR);
|
||||
if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X))
|
||||
serial_port_in(port, UART_EXAR_INT0);
|
||||
up->lsr_saved_flags = 0;
|
||||
up->msr_saved_flags = 0;
|
||||
|
||||
|
@ -478,6 +478,7 @@ static int altera_jtaguart_remove(struct platform_device *pdev)
|
||||
|
||||
port = &altera_jtaguart_ports[i].port;
|
||||
uart_remove_one_port(&altera_jtaguart_driver, port);
|
||||
iounmap(port->membase);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -615,6 +615,7 @@ static int altera_uart_remove(struct platform_device *pdev)
|
||||
if (port) {
|
||||
uart_remove_one_port(&altera_uart_driver, port);
|
||||
port->mapbase = 0;
|
||||
iounmap(port->membase);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -27,6 +27,7 @@
|
||||
#define UARTn_FRAME 0x04
|
||||
#define UARTn_FRAME_DATABITS__MASK 0x000f
|
||||
#define UARTn_FRAME_DATABITS(n) ((n) - 3)
|
||||
#define UARTn_FRAME_PARITY__MASK 0x0300
|
||||
#define UARTn_FRAME_PARITY_NONE 0x0000
|
||||
#define UARTn_FRAME_PARITY_EVEN 0x0200
|
||||
#define UARTn_FRAME_PARITY_ODD 0x0300
|
||||
@ -572,12 +573,16 @@ static void efm32_uart_console_get_options(struct efm32_uart_port *efm_port,
|
||||
16 * (4 + (clkdiv >> 6)));
|
||||
|
||||
frame = efm32_uart_read32(efm_port, UARTn_FRAME);
|
||||
if (frame & UARTn_FRAME_PARITY_ODD)
|
||||
switch (frame & UARTn_FRAME_PARITY__MASK) {
|
||||
case UARTn_FRAME_PARITY_ODD:
|
||||
*parity = 'o';
|
||||
else if (frame & UARTn_FRAME_PARITY_EVEN)
|
||||
break;
|
||||
case UARTn_FRAME_PARITY_EVEN:
|
||||
*parity = 'e';
|
||||
else
|
||||
break;
|
||||
default:
|
||||
*parity = 'n';
|
||||
}
|
||||
|
||||
*bits = (frame & UARTn_FRAME_DATABITS__MASK) -
|
||||
UARTn_FRAME_DATABITS(4) + 4;
|
||||
|
@ -1382,9 +1382,9 @@ static struct spi_driver ifx_spi_driver = {
|
||||
static void __exit ifx_spi_exit(void)
|
||||
{
|
||||
/* unregister */
|
||||
spi_unregister_driver(&ifx_spi_driver);
|
||||
tty_unregister_driver(tty_drv);
|
||||
put_tty_driver(tty_drv);
|
||||
spi_unregister_driver(&ifx_spi_driver);
|
||||
unregister_reboot_notifier(&ifx_modem_reboot_notifier_block);
|
||||
}
|
||||
|
||||
|
@ -2184,7 +2184,9 @@ static int serial_imx_probe(struct platform_device *pdev)
|
||||
* and DCD (when they are outputs) or enables the respective
|
||||
* irqs. So set this bit early, i.e. before requesting irqs.
|
||||
*/
|
||||
writel(UFCR_DCEDTE, sport->port.membase + UFCR);
|
||||
reg = readl(sport->port.membase + UFCR);
|
||||
if (!(reg & UFCR_DCEDTE))
|
||||
writel(reg | UFCR_DCEDTE, sport->port.membase + UFCR);
|
||||
|
||||
/*
|
||||
* Disable UCR3_RI and UCR3_DCD irqs. They are also not
|
||||
@ -2195,7 +2197,15 @@ static int serial_imx_probe(struct platform_device *pdev)
|
||||
sport->port.membase + UCR3);
|
||||
|
||||
} else {
|
||||
writel(0, sport->port.membase + UFCR);
|
||||
unsigned long ucr3 = UCR3_DSR;
|
||||
|
||||
reg = readl(sport->port.membase + UFCR);
|
||||
if (reg & UFCR_DCEDTE)
|
||||
writel(reg & ~UFCR_DCEDTE, sport->port.membase + UFCR);
|
||||
|
||||
if (!is_imx1_uart(sport))
|
||||
ucr3 |= IMX21_UCR3_RXDMUXSEL | UCR3_ADNIMP;
|
||||
writel(ucr3, sport->port.membase + UCR3);
|
||||
}
|
||||
|
||||
clk_disable_unprepare(sport->clk_ipg);
|
||||
|
@ -2083,7 +2083,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
|
||||
mutex_lock(&port->mutex);
|
||||
|
||||
tty_dev = device_find_child(uport->dev, &match, serial_match_port);
|
||||
if (device_may_wakeup(tty_dev)) {
|
||||
if (tty_dev && device_may_wakeup(tty_dev)) {
|
||||
if (!enable_irq_wake(uport->irq))
|
||||
uport->irq_wake = 1;
|
||||
put_device(tty_dev);
|
||||
@ -2782,7 +2782,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
|
||||
* Register the port whether it's detected or not. This allows
|
||||
* setserial to be used to alter this port's parameters.
|
||||
*/
|
||||
tty_dev = tty_port_register_device_attr(port, drv->tty_driver,
|
||||
tty_dev = tty_port_register_device_attr_serdev(port, drv->tty_driver,
|
||||
uport->line, uport->dev, port, uport->tty_groups);
|
||||
if (likely(!IS_ERR(tty_dev))) {
|
||||
device_set_wakeup_capable(tty_dev, 1);
|
||||
@ -2845,7 +2845,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
|
||||
/*
|
||||
* Remove the devices from the tty layer
|
||||
*/
|
||||
tty_unregister_device(drv->tty_driver, uport->line);
|
||||
tty_port_unregister_device(port, drv->tty_driver, uport->line);
|
||||
|
||||
tty = tty_port_tty_get(port);
|
||||
if (tty) {
|
||||
|
@ -34,7 +34,9 @@ static int tty_port_default_receive_buf(struct tty_port *port,
|
||||
if (!disc)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&tty->atomic_write_lock);
|
||||
ret = tty_ldisc_receive_buf(disc, p, (char *)f, count);
|
||||
mutex_unlock(&tty->atomic_write_lock);
|
||||
|
||||
tty_ldisc_deref(disc);
|
||||
|
||||
@ -128,20 +130,86 @@ 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)
|
||||
{
|
||||
tty_port_link_device(port, driver, index);
|
||||
return tty_register_device_attr(driver, index, device, drvdata,
|
||||
attr_grp);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
|
||||
|
||||
/**
|
||||
* tty_port_register_device_attr_serdev - register tty or serdev device
|
||||
* @port: tty_port of the device
|
||||
* @driver: tty_driver for this device
|
||||
* @index: index of the tty
|
||||
* @device: parent if exists, otherwise NULL
|
||||
* @drvdata: driver data for the device
|
||||
* @attr_grp: attribute group for the device
|
||||
*
|
||||
* Register a serdev or tty device depending on if the parent device has any
|
||||
* defined serdev clients or not.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
tty_port_link_device(port, driver, index);
|
||||
|
||||
dev = serdev_tty_port_register(port, device, driver, index);
|
||||
if (PTR_ERR(dev) != -ENODEV)
|
||||
if (PTR_ERR(dev) != -ENODEV) {
|
||||
/* Skip creating cdev if we registered a serdev device */
|
||||
return dev;
|
||||
}
|
||||
|
||||
return tty_register_device_attr(driver, index, device, drvdata,
|
||||
attr_grp);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
|
||||
EXPORT_SYMBOL_GPL(tty_port_register_device_attr_serdev);
|
||||
|
||||
/**
|
||||
* tty_port_register_device_serdev - register tty or serdev device
|
||||
* @port: tty_port of the device
|
||||
* @driver: tty_driver for this device
|
||||
* @index: index of the tty
|
||||
* @device: parent if exists, otherwise NULL
|
||||
*
|
||||
* Register a serdev or tty device depending on if the parent device has any
|
||||
* defined serdev clients or not.
|
||||
*/
|
||||
struct device *tty_port_register_device_serdev(struct tty_port *port,
|
||||
struct tty_driver *driver, unsigned index,
|
||||
struct device *device)
|
||||
{
|
||||
return tty_port_register_device_attr_serdev(port, driver, index,
|
||||
device, NULL, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tty_port_register_device_serdev);
|
||||
|
||||
/**
|
||||
* tty_port_unregister_device - deregister a tty or serdev device
|
||||
* @port: tty_port of the device
|
||||
* @driver: tty_driver for this device
|
||||
* @index: index of the tty
|
||||
*
|
||||
* If a tty or serdev device is registered with a call to
|
||||
* tty_port_register_device_serdev() then this function must be called when
|
||||
* the device is gone.
|
||||
*/
|
||||
void tty_port_unregister_device(struct tty_port *port,
|
||||
struct tty_driver *driver, unsigned index)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = serdev_tty_port_unregister(port);
|
||||
if (ret == 0)
|
||||
return;
|
||||
|
||||
tty_unregister_device(driver, index);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tty_port_unregister_device);
|
||||
|
||||
int tty_port_alloc_xmit_buf(struct tty_port *port)
|
||||
{
|
||||
@ -189,9 +257,6 @@ static void tty_port_destructor(struct kref *kref)
|
||||
/* check if last port ref was dropped before tty release */
|
||||
if (WARN_ON(port->itty))
|
||||
return;
|
||||
|
||||
serdev_tty_port_unregister(port);
|
||||
|
||||
if (port->xmit_buf)
|
||||
free_page((unsigned long)port->xmit_buf);
|
||||
tty_port_destroy(port);
|
||||
|
@ -195,6 +195,7 @@ int serdev_device_open(struct serdev_device *);
|
||||
void serdev_device_close(struct serdev_device *);
|
||||
unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int);
|
||||
void serdev_device_set_flow_control(struct serdev_device *, bool);
|
||||
int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_t);
|
||||
void serdev_device_wait_until_sent(struct serdev_device *, long);
|
||||
int serdev_device_get_tiocm(struct serdev_device *);
|
||||
int serdev_device_set_tiocm(struct serdev_device *, int, int);
|
||||
@ -236,6 +237,12 @@ static inline unsigned int serdev_device_set_baudrate(struct serdev_device *sdev
|
||||
return 0;
|
||||
}
|
||||
static inline void serdev_device_set_flow_control(struct serdev_device *sdev, bool enable) {}
|
||||
static inline int serdev_device_write_buf(struct serdev_device *serdev,
|
||||
const unsigned char *buf,
|
||||
size_t count)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline void serdev_device_wait_until_sent(struct serdev_device *sdev, long timeout) {}
|
||||
static inline int serdev_device_get_tiocm(struct serdev_device *serdev)
|
||||
{
|
||||
@ -301,7 +308,7 @@ struct tty_driver;
|
||||
struct device *serdev_tty_port_register(struct tty_port *port,
|
||||
struct device *parent,
|
||||
struct tty_driver *drv, int idx);
|
||||
void serdev_tty_port_unregister(struct tty_port *port);
|
||||
int serdev_tty_port_unregister(struct tty_port *port);
|
||||
#else
|
||||
static inline struct device *serdev_tty_port_register(struct tty_port *port,
|
||||
struct device *parent,
|
||||
@ -309,14 +316,10 @@ static inline struct device *serdev_tty_port_register(struct tty_port *port,
|
||||
{
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
static inline void serdev_tty_port_unregister(struct tty_port *port) {}
|
||||
static inline int serdev_tty_port_unregister(struct tty_port *port)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */
|
||||
|
||||
static inline int serdev_device_write_buf(struct serdev_device *serdev,
|
||||
const unsigned char *data,
|
||||
size_t count)
|
||||
{
|
||||
return serdev_device_write(serdev, data, count, 0);
|
||||
}
|
||||
|
||||
#endif /*_LINUX_SERDEV_H */
|
||||
|
@ -558,6 +558,15 @@ 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);
|
||||
|
Loading…
Reference in New Issue
Block a user