diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-11 23:08:47 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-11 23:08:47 +0100 |
commit | c6bd5bcc4983f1a2d2f87a3769bf309482ee8c04 (patch) | |
tree | 2ff9c4496dc2258d601a1bcd82040470704dae3b /drivers/tty/serial/samsung.c | |
parent | Merge tag 'staging-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/... (diff) | |
parent | staging: sb105x: fix potential NULL pointer dereference in mp_chars_in_buffer() (diff) | |
download | linux-c6bd5bcc4983f1a2d2f87a3769bf309482ee8c04.tar.xz linux-c6bd5bcc4983f1a2d2f87a3769bf309482ee8c04.zip |
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/samsung.c')
-rw-r--r-- | drivers/tty/serial/samsung.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 7f04717176aa..fb0e0f0bed0e 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -223,8 +223,11 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id) struct uart_port *port = &ourport->port; struct tty_struct *tty = port->state->port.tty; unsigned int ufcon, ch, flag, ufstat, uerstat; + unsigned long flags; int max_count = 64; + spin_lock_irqsave(&port->lock, flags); + while (max_count-- > 0) { ufcon = rd_regl(port, S3C2410_UFCON); ufstat = rd_regl(port, S3C2410_UFSTAT); @@ -299,6 +302,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id) tty_flip_buffer_push(tty); out: + spin_unlock_irqrestore(&port->lock, flags); return IRQ_HANDLED; } @@ -307,8 +311,11 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) struct s3c24xx_uart_port *ourport = id; struct uart_port *port = &ourport->port; struct circ_buf *xmit = &port->state->xmit; + unsigned long flags; int count = 256; + spin_lock_irqsave(&port->lock, flags); + if (port->x_char) { wr_regb(port, S3C2410_UTXH, port->x_char); port->icount.tx++; @@ -336,13 +343,17 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) port->icount.tx++; } - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) { + spin_unlock(&port->lock); uart_write_wakeup(port); + spin_lock(&port->lock); + } if (uart_circ_empty(xmit)) s3c24xx_serial_stop_tx(port); out: + spin_unlock_irqrestore(&port->lock, flags); return IRQ_HANDLED; } @@ -352,10 +363,8 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id) struct s3c24xx_uart_port *ourport = id; struct uart_port *port = &ourport->port; unsigned int pend = rd_regl(port, S3C64XX_UINTP); - unsigned long flags; irqreturn_t ret = IRQ_HANDLED; - spin_lock_irqsave(&port->lock, flags); if (pend & S3C64XX_UINTM_RXD_MSK) { ret = s3c24xx_serial_rx_chars(irq, id); wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_RXD_MSK); @@ -364,7 +373,6 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id) ret = s3c24xx_serial_tx_chars(irq, id); wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_TXD_MSK); } - spin_unlock_irqrestore(&port->lock, flags); return ret; } @@ -530,16 +538,16 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, switch (level) { case 3: if (!IS_ERR(ourport->baudclk)) - clk_disable(ourport->baudclk); + clk_disable_unprepare(ourport->baudclk); - clk_disable(ourport->clk); + clk_disable_unprepare(ourport->clk); break; case 0: - clk_enable(ourport->clk); + clk_prepare_enable(ourport->clk); if (!IS_ERR(ourport->baudclk)) - clk_enable(ourport->baudclk); + clk_prepare_enable(ourport->baudclk); break; default: @@ -713,11 +721,11 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, s3c24xx_serial_setsource(port, clk_sel); if (!IS_ERR(ourport->baudclk)) { - clk_disable(ourport->baudclk); + clk_disable_unprepare(ourport->baudclk); ourport->baudclk = ERR_PTR(-EINVAL); } - clk_enable(clk); + clk_prepare_enable(clk); ourport->baudclk = clk; ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0; @@ -1256,7 +1264,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) return ret; } -static int __devexit s3c24xx_serial_remove(struct platform_device *dev) +static int s3c24xx_serial_remove(struct platform_device *dev) { struct uart_port *port = s3c24xx_dev_to_port(&dev->dev); @@ -1287,9 +1295,9 @@ static int s3c24xx_serial_resume(struct device *dev) struct s3c24xx_uart_port *ourport = to_ourport(port); if (port) { - clk_enable(ourport->clk); + clk_prepare_enable(ourport->clk); s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port)); - clk_disable(ourport->clk); + clk_disable_unprepare(ourport->clk); uart_resume_port(&s3c24xx_uart_drv, port); } @@ -1701,6 +1709,16 @@ MODULE_DEVICE_TABLE(platform, s3c24xx_serial_driver_ids); #ifdef CONFIG_OF static const struct of_device_id s3c24xx_uart_dt_match[] = { + { .compatible = "samsung,s3c2410-uart", + .data = (void *)S3C2410_SERIAL_DRV_DATA }, + { .compatible = "samsung,s3c2412-uart", + .data = (void *)S3C2412_SERIAL_DRV_DATA }, + { .compatible = "samsung,s3c2440-uart", + .data = (void *)S3C2440_SERIAL_DRV_DATA }, + { .compatible = "samsung,s3c6400-uart", + .data = (void *)S3C6400_SERIAL_DRV_DATA }, + { .compatible = "samsung,s5pv210-uart", + .data = (void *)S5PV210_SERIAL_DRV_DATA }, { .compatible = "samsung,exynos4210-uart", .data = (void *)EXYNOS4210_SERIAL_DRV_DATA }, {}, @@ -1712,7 +1730,7 @@ MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match); static struct platform_driver samsung_serial_driver = { .probe = s3c24xx_serial_probe, - .remove = __devexit_p(s3c24xx_serial_remove), + .remove = s3c24xx_serial_remove, .id_table = s3c24xx_serial_driver_ids, .driver = { .name = "samsung-uart", |