diff options
Diffstat (limited to 'drivers/tty/serial/mrst_max3110.c')
| -rw-r--r-- | drivers/tty/serial/mrst_max3110.c | 93 |
1 files changed, 49 insertions, 44 deletions
diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c index df2a2240a3a..db0448ae59d 100644 --- a/drivers/tty/serial/mrst_max3110.c +++ b/drivers/tty/serial/mrst_max3110.c @@ -43,6 +43,7 @@ #include <linux/kthread.h> #include <linux/spi/spi.h> +#include <linux/pm.h> #include "mrst_max3110.h" @@ -61,6 +62,7 @@ struct uart_max3110 { struct task_struct *main_thread; struct task_struct *read_thread; struct mutex thread_mutex; + struct mutex io_mutex; u32 baud; u16 cur_conf; @@ -90,6 +92,7 @@ static int max3110_write_then_read(struct uart_max3110 *max, struct spi_transfer x; int ret; + mutex_lock(&max->io_mutex); spi_message_init(&message); memset(&x, 0, sizeof x); x.len = len; @@ -104,6 +107,7 @@ static int max3110_write_then_read(struct uart_max3110 *max, /* Do the i/o */ ret = spi_sync(spi, &message); + mutex_unlock(&max->io_mutex); return ret; } @@ -339,7 +343,7 @@ static int receive_chars(struct uart_max3110 *max, unsigned short *str, int len) { struct uart_port *port = &max->port; - struct tty_struct *tty; + struct tty_port *tport; char buf[M3110_RX_FIFO_DEPTH]; int r, w, usable; @@ -347,9 +351,7 @@ receive_chars(struct uart_max3110 *max, unsigned short *str, int len) if (!port->state) return 0; - tty = tty_port_tty_get(&port->state->port); - if (!tty) - return 0; + tport = &port->state->port; for (r = 0, w = 0; r < len; r++) { if (str[r] & MAX3110_BREAK && @@ -364,20 +366,17 @@ receive_chars(struct uart_max3110 *max, unsigned short *str, int len) } } - if (!w) { - tty_kref_put(tty); + if (!w) return 0; - } for (r = 0; w; r += usable, w -= usable) { - usable = tty_buffer_request_room(tty, w); + usable = tty_buffer_request_room(tport, w); if (usable) { - tty_insert_flip_string(tty, buf + r, usable); + tty_insert_flip_string(tport, buf + r, usable); port->icount.rx += usable; } } - tty_flip_buffer_push(tty); - tty_kref_put(tty); + tty_flip_buffer_push(tport); return r; } @@ -493,22 +492,12 @@ static int serial_m3110_startup(struct uart_port *port) | WC_BAUD_DR2; /* as we use thread to handle tx/rx, need set low latency */ - port->state->port.tty->low_latency = 1; + port->state->port.low_latency = 1; if (max->irq) { - max->read_thread = NULL; - ret = request_irq(max->irq, serial_m3110_irq, - IRQ_TYPE_EDGE_FALLING, "max3110", max); - if (ret) { - max->irq = 0; - pr_err(PR_FMT "unable to allocate IRQ, polling\n"); - } else { - /* Enable RX IRQ only */ - config |= WC_RXA_IRQ_ENABLE; - } - } - - if (max->irq == 0) { + /* Enable RX IRQ only */ + config |= WC_RXA_IRQ_ENABLE; + } else { /* If IRQ is disabled, start a read thread for input data */ max->read_thread = kthread_run(max3110_read_thread, max, "max3110_read"); @@ -522,8 +511,6 @@ static int serial_m3110_startup(struct uart_port *port) ret = max3110_out(max, config); if (ret) { - if (max->irq) - free_irq(max->irq, max); if (max->read_thread) kthread_stop(max->read_thread); max->read_thread = NULL; @@ -545,9 +532,6 @@ static void serial_m3110_shutdown(struct uart_port *port) max->read_thread = NULL; } - if (max->irq) - free_irq(max->irq, max); - /* Disable interrupts from this port */ config = WC_TAG | WC_SW_SHDI; max3110_out(max, config); @@ -718,7 +702,7 @@ static void serial_m3110_enable_ms(struct uart_port *port) { } -struct uart_ops serial_m3110_ops = { +static struct uart_ops serial_m3110_ops = { .tx_empty = serial_m3110_tx_empty, .set_mctrl = serial_m3110_set_mctrl, .get_mctrl = serial_m3110_get_mctrl, @@ -748,32 +732,40 @@ static struct uart_driver serial_m3110_reg = { .cons = &serial_m3110_console, }; -#ifdef CONFIG_PM -static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int serial_m3110_suspend(struct device *dev) { + struct spi_device *spi = to_spi_device(dev); struct uart_max3110 *max = spi_get_drvdata(spi); - disable_irq(max->irq); + if (max->irq > 0) + disable_irq(max->irq); uart_suspend_port(&serial_m3110_reg, &max->port); max3110_out(max, max->cur_conf | WC_SW_SHDI); return 0; } -static int serial_m3110_resume(struct spi_device *spi) +static int serial_m3110_resume(struct device *dev) { + struct spi_device *spi = to_spi_device(dev); struct uart_max3110 *max = spi_get_drvdata(spi); max3110_out(max, max->cur_conf); uart_resume_port(&serial_m3110_reg, &max->port); - enable_irq(max->irq); + if (max->irq > 0) + enable_irq(max->irq); return 0; } + +static SIMPLE_DEV_PM_OPS(serial_m3110_pm_ops, serial_m3110_suspend, + serial_m3110_resume); +#define SERIAL_M3110_PM_OPS (&serial_m3110_pm_ops) + #else -#define serial_m3110_suspend NULL -#define serial_m3110_resume NULL +#define SERIAL_M3110_PM_OPS NULL #endif -static int __devinit serial_m3110_probe(struct spi_device *spi) +static int serial_m3110_probe(struct spi_device *spi) { struct uart_max3110 *max; void *buffer; @@ -802,6 +794,7 @@ static int __devinit serial_m3110_probe(struct spi_device *spi) max->irq = (u16)spi->irq; mutex_init(&max->thread_mutex); + mutex_init(&max->io_mutex); max->word_7bits = 0; max->parity = 0; @@ -839,11 +832,21 @@ static int __devinit serial_m3110_probe(struct spi_device *spi) goto err_kthread; } + if (max->irq) { + ret = request_irq(max->irq, serial_m3110_irq, + IRQ_TYPE_EDGE_FALLING, "max3110", max); + if (ret) { + max->irq = 0; + dev_warn(&spi->dev, + "unable to allocate IRQ, will use polling method\n"); + } + } + spi_set_drvdata(spi, max); pmax = max; /* Give membase a psudo value to pass serial_core's check */ - max->port.membase = (void *)0xff110000; + max->port.membase = (unsigned char __iomem *)0xff110000; uart_add_one_port(&serial_m3110_reg, &max->port); return 0; @@ -855,7 +858,7 @@ err_get_page: return ret; } -static int __devexit serial_m3110_remove(struct spi_device *dev) +static int serial_m3110_remove(struct spi_device *dev) { struct uart_max3110 *max = spi_get_drvdata(dev); @@ -866,6 +869,9 @@ static int __devexit serial_m3110_remove(struct spi_device *dev) free_page((unsigned long)max->con_xmit.buf); + if (max->irq) + free_irq(max->irq, max); + if (max->main_thread) kthread_stop(max->main_thread); @@ -877,11 +883,10 @@ static struct spi_driver uart_max3110_driver = { .driver = { .name = "spi_max3111", .owner = THIS_MODULE, + .pm = SERIAL_M3110_PM_OPS, }, .probe = serial_m3110_probe, - .remove = __devexit_p(serial_m3110_remove), - .suspend = serial_m3110_suspend, - .resume = serial_m3110_resume, + .remove = serial_m3110_remove, }; static int __init serial_m3110_init(void) |
