diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-11 14:08:47 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-11 14:08:47 -0800 |
commit | c6bd5bcc4983f1a2d2f87a3769bf309482ee8c04 (patch) | |
tree | 2ff9c4496dc2258d601a1bcd82040470704dae3b /drivers/tty/serial/serial_core.c | |
parent | 8966961b31c251b854169e9886394c2a20f2cea7 (diff) | |
parent | b0ab02361167faa82198b783a8d555eb6f58901c (diff) |
Merge tag 'tty-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull TTY/Serial merge from Greg Kroah-Hartman:
"Here's the big tty/serial tree set of changes for 3.8-rc1.
Contained in here is a bunch more reworks of the tty port layer from
Jiri and bugfixes from Alan, along with a number of other tty and
serial driver updates by the various driver authors.
Also, Jiri has been coerced^Wconvinced to be the co-maintainer of the
TTY layer, which is much appreciated by me.
All of these have been in the linux-next tree for a while.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"
Fixed up some trivial conflicts in the staging tree, due to the fwserial
driver having come in both ways (but fixed up a bit in the serial tree),
and the ioctl handling in the dgrp driver having been done slightly
differently (staging tree got that one right, and removed both
TIOCGSOFTCAR and TIOCSSOFTCAR).
* tag 'tty-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (146 commits)
staging: sb105x: fix potential NULL pointer dereference in mp_chars_in_buffer()
staging/fwserial: Remove superfluous free
staging/fwserial: Use WARN_ONCE when port table is corrupted
staging/fwserial: Destruct embedded tty_port on teardown
staging/fwserial: Fix build breakage when !CONFIG_BUG
staging: fwserial: Add TTY-over-Firewire serial driver
drivers/tty/serial/serial_core.c: clean up HIGH_BITS_OFFSET usage
staging: dgrp: dgrp_tty.c: Audit the return values of get/put_user()
staging: dgrp: dgrp_tty.c: Remove the TIOCSSOFTCAR ioctl handler from dgrp driver
serial: ifx6x60: Add modem power off function in the platform reboot process
serial: mxs-auart: unmap the scatter list before we copy the data
serial: mxs-auart: disable the Receive Timeout Interrupt when DMA is enabled
serial: max310x: Setup missing "can_sleep" field for GPIO
tty/serial: fix ifx6x60.c declaration warning
serial: samsung: add devicetree properties for non-Exynos SoCs
serial: samsung: fix potential soft lockup during uart write
tty: vt: Remove redundant null check before kfree.
tty/8250 Add check for pci_ioremap_bar failure
tty/8250 Add support for Commtech's Fastcom Async-335 and Fastcom Async-PCIe cards
tty/8250 Add XR17D15x devices to the exar_handle_irq override
...
Diffstat (limited to 'drivers/tty/serial/serial_core.c')
-rw-r--r-- | drivers/tty/serial/serial_core.c | 186 |
1 files changed, 171 insertions, 15 deletions
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 0fcfd98a9566..fb5aa42fde7e 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -634,10 +634,10 @@ static void uart_unthrottle(struct tty_struct *tty) uart_set_mctrl(port, TIOCM_RTS); } -static void uart_get_info(struct tty_port *port, - struct uart_state *state, +static void do_uart_get_info(struct tty_port *port, struct serial_struct *retinfo) { + struct uart_state *state = container_of(port, struct uart_state, port); struct uart_port *uport = state->uart_port; memset(retinfo, 0, sizeof(*retinfo)); @@ -662,17 +662,21 @@ static void uart_get_info(struct tty_port *port, retinfo->iomem_base = (void *)(unsigned long)uport->mapbase; } -static int uart_get_info_user(struct uart_state *state, - struct serial_struct __user *retinfo) +static void uart_get_info(struct tty_port *port, + struct serial_struct *retinfo) { - struct tty_port *port = &state->port; - struct serial_struct tmp; - /* Ensure the state we copy is consistent and no hardware changes occur as we go */ mutex_lock(&port->mutex); - uart_get_info(port, state, &tmp); + do_uart_get_info(port, retinfo); mutex_unlock(&port->mutex); +} + +static int uart_get_info_user(struct tty_port *port, + struct serial_struct __user *retinfo) +{ + struct serial_struct tmp; + uart_get_info(port, &tmp); if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) return -EFAULT; @@ -1131,7 +1135,7 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, */ switch (cmd) { case TIOCGSERIAL: - ret = uart_get_info_user(state, uarg); + ret = uart_get_info_user(port, uarg); break; case TIOCSSERIAL: @@ -2293,6 +2297,8 @@ int uart_register_driver(struct uart_driver *drv) if (retval >= 0) return retval; + for (i = 0; i < drv->nr; i++) + tty_port_destroy(&drv->state[i].port); put_tty_driver(normal); out_kfree: kfree(drv->state); @@ -2312,8 +2318,12 @@ out: void uart_unregister_driver(struct uart_driver *drv) { struct tty_driver *p = drv->tty_driver; + unsigned int i; + tty_unregister_driver(p); put_tty_driver(p); + for (i = 0; i < drv->nr; i++) + tty_port_destroy(&drv->state[i].port); kfree(drv->state); drv->state = NULL; drv->tty_driver = NULL; @@ -2329,21 +2339,166 @@ struct tty_driver *uart_console_device(struct console *co, int *index) static ssize_t uart_get_attr_uartclk(struct device *dev, struct device_attribute *attr, char *buf) { - int ret; + struct serial_struct tmp; struct tty_port *port = dev_get_drvdata(dev); - struct uart_state *state = container_of(port, struct uart_state, port); - mutex_lock(&state->port.mutex); - ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk); - mutex_unlock(&state->port.mutex); + uart_get_info(port, &tmp); + return snprintf(buf, PAGE_SIZE, "%d\n", tmp.baud_base * 16); +} - return ret; +static ssize_t uart_get_attr_type(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct serial_struct tmp; + struct tty_port *port = dev_get_drvdata(dev); + + uart_get_info(port, &tmp); + return snprintf(buf, PAGE_SIZE, "%d\n", tmp.type); +} +static ssize_t uart_get_attr_line(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct serial_struct tmp; + struct tty_port *port = dev_get_drvdata(dev); + + uart_get_info(port, &tmp); + return snprintf(buf, PAGE_SIZE, "%d\n", tmp.line); +} + +static ssize_t uart_get_attr_port(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct serial_struct tmp; + struct tty_port *port = dev_get_drvdata(dev); + unsigned long ioaddr; + + uart_get_info(port, &tmp); + ioaddr = tmp.port; + if (HIGH_BITS_OFFSET) + ioaddr |= (unsigned long)tmp.port_high << HIGH_BITS_OFFSET; + return snprintf(buf, PAGE_SIZE, "0x%lX\n", ioaddr); } +static ssize_t uart_get_attr_irq(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct serial_struct tmp; + struct tty_port *port = dev_get_drvdata(dev); + + uart_get_info(port, &tmp); + return snprintf(buf, PAGE_SIZE, "%d\n", tmp.irq); +} + +static ssize_t uart_get_attr_flags(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct serial_struct tmp; + struct tty_port *port = dev_get_drvdata(dev); + + uart_get_info(port, &tmp); + return snprintf(buf, PAGE_SIZE, "0x%X\n", tmp.flags); +} + +static ssize_t uart_get_attr_xmit_fifo_size(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct serial_struct tmp; + struct tty_port *port = dev_get_drvdata(dev); + + uart_get_info(port, &tmp); + return snprintf(buf, PAGE_SIZE, "%d\n", tmp.xmit_fifo_size); +} + + +static ssize_t uart_get_attr_close_delay(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct serial_struct tmp; + struct tty_port *port = dev_get_drvdata(dev); + + uart_get_info(port, &tmp); + return snprintf(buf, PAGE_SIZE, "%d\n", tmp.close_delay); +} + + +static ssize_t uart_get_attr_closing_wait(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct serial_struct tmp; + struct tty_port *port = dev_get_drvdata(dev); + + uart_get_info(port, &tmp); + return snprintf(buf, PAGE_SIZE, "%d\n", tmp.closing_wait); +} + +static ssize_t uart_get_attr_custom_divisor(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct serial_struct tmp; + struct tty_port *port = dev_get_drvdata(dev); + + uart_get_info(port, &tmp); + return snprintf(buf, PAGE_SIZE, "%d\n", tmp.custom_divisor); +} + +static ssize_t uart_get_attr_io_type(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct serial_struct tmp; + struct tty_port *port = dev_get_drvdata(dev); + + uart_get_info(port, &tmp); + return snprintf(buf, PAGE_SIZE, "%d\n", tmp.io_type); +} + +static ssize_t uart_get_attr_iomem_base(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct serial_struct tmp; + struct tty_port *port = dev_get_drvdata(dev); + + uart_get_info(port, &tmp); + return snprintf(buf, PAGE_SIZE, "0x%lX\n", (unsigned long)tmp.iomem_base); +} + +static ssize_t uart_get_attr_iomem_reg_shift(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct serial_struct tmp; + struct tty_port *port = dev_get_drvdata(dev); + + uart_get_info(port, &tmp); + return snprintf(buf, PAGE_SIZE, "%d\n", tmp.iomem_reg_shift); +} + +static DEVICE_ATTR(type, S_IRUSR | S_IRGRP, uart_get_attr_type, NULL); +static DEVICE_ATTR(line, S_IRUSR | S_IRGRP, uart_get_attr_line, NULL); +static DEVICE_ATTR(port, S_IRUSR | S_IRGRP, uart_get_attr_port, NULL); +static DEVICE_ATTR(irq, S_IRUSR | S_IRGRP, uart_get_attr_irq, NULL); +static DEVICE_ATTR(flags, S_IRUSR | S_IRGRP, uart_get_attr_flags, NULL); +static DEVICE_ATTR(xmit_fifo_size, S_IRUSR | S_IRGRP, uart_get_attr_xmit_fifo_size, NULL); static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk, NULL); +static DEVICE_ATTR(close_delay, S_IRUSR | S_IRGRP, uart_get_attr_close_delay, NULL); +static DEVICE_ATTR(closing_wait, S_IRUSR | S_IRGRP, uart_get_attr_closing_wait, NULL); +static DEVICE_ATTR(custom_divisor, S_IRUSR | S_IRGRP, uart_get_attr_custom_divisor, NULL); +static DEVICE_ATTR(io_type, S_IRUSR | S_IRGRP, uart_get_attr_io_type, NULL); +static DEVICE_ATTR(iomem_base, S_IRUSR | S_IRGRP, uart_get_attr_iomem_base, NULL); +static DEVICE_ATTR(iomem_reg_shift, S_IRUSR | S_IRGRP, uart_get_attr_iomem_reg_shift, NULL); static struct attribute *tty_dev_attrs[] = { + &dev_attr_type.attr, + &dev_attr_line.attr, + &dev_attr_port.attr, + &dev_attr_irq.attr, + &dev_attr_flags.attr, + &dev_attr_xmit_fifo_size.attr, &dev_attr_uartclk.attr, + &dev_attr_close_delay.attr, + &dev_attr_closing_wait.attr, + &dev_attr_custom_divisor.attr, + &dev_attr_io_type.attr, + &dev_attr_iomem_base.attr, + &dev_attr_iomem_reg_shift.attr, NULL, }; @@ -2356,6 +2511,7 @@ static const struct attribute_group *tty_dev_attr_groups[] = { NULL }; + /** * uart_add_one_port - attach a driver-defined port structure * @drv: pointer to the uart low level driver structure for this port |