]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
Add support for polling to the sunhv serial driver.
authorAllen Pais <allen.pais@oracle.com>
Thu, 28 Jan 2016 18:05:58 +0000 (23:35 +0530)
committerAllen Pais <allen.pais@oracle.com>
Thu, 28 Jan 2016 18:05:58 +0000 (23:35 +0530)
Oragbug: 21793591

Signed-off-by: Greg Onufer <greg.onufer@oracle.com>
Signed-off-by: Allen Pais <allen.pais@oracle.com>
drivers/tty/serial/Kconfig
drivers/tty/serial/sunhv.c

index f8120c1bde14760f306e425d4d0de2d23f26d0e2..a4c5eab560474c2f96fa155c61a28dad4df2f884 100644 (file)
@@ -713,6 +713,14 @@ config SERIAL_SUNHV
          This driver supports the console device found on SUN4V Sparc
          systems.  Say Y if you want to be able to use this device.
 
+config SERIAL_SUNHV_POLLING
+       bool "Sun4v Hypervisor Console polling support"
+       depends on SERIAL_SUNHV=y
+       help
+         If you would like the sunhv driver to support polling when
+         interrupts are not available you can do so by answering Y
+         to this option.
+
 config SERIAL_IP22_ZILOG
        tristate "SGI Zilog8530 serial support"
        depends on SGI_HAS_ZILOG
index c694b8e6591d050421b7d5db3e22041f5aeccd09..0fedd8bf5ee30e93221045cb6d544b315810754f 100644 (file)
 static char *con_write_page;
 static char *con_read_page;
 
+#ifdef CONFIG_SERIAL_SUNHV_POLLING
+static struct timer_list con_timer;
+static unsigned long con_interrupt_timeout;
+#endif
+
+
 static int hung_up = 0;
 
 static void transmit_chars_putchar(struct uart_port *port, struct circ_buf *xmit)
@@ -230,6 +236,19 @@ static irqreturn_t sunhv_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_SERIAL_SUNHV_POLLING
+static void sun4v_timer_poll(unsigned long data)
+{
+       struct uart_port *port = (struct uart_port *)data;
+
+       if (!port)
+               return;
+
+       (void) sunhv_interrupt(0, port);
+       mod_timer(&con_timer, jiffies + con_interrupt_timeout);
+}
+#endif
+
 /* port->lock is not held.  */
 static unsigned int sunhv_tx_empty(struct uart_port *port)
 {
@@ -574,6 +593,24 @@ static int hv_probe(struct platform_device *op)
        if (err)
                goto out_remove_port;
 
+#ifdef CONFIG_SERIAL_SUNHV_POLLING
+       /*
+        * If "qcn" is in compatible then this is running on legion
+        * and probably needs polling.
+        */
+       if (of_device_is_compatible(op->dev.of_node, "qcn")) {
+               printk(KERN_INFO "%s%u: polling\n", sunhv_console.name,
+                      port->line);
+               init_timer(&con_timer);
+               con_timer.function = sun4v_timer_poll;
+               con_timer.data = (unsigned long)port;
+               con_interrupt_timeout = 6;
+               mod_timer(&con_timer, jiffies + con_interrupt_timeout);
+       } else {
+               con_interrupt_timeout = 0;
+       }
+#endif
+
        platform_set_drvdata(op, port);
 
        return 0;
@@ -600,6 +637,11 @@ static int hv_remove(struct platform_device *dev)
 {
        struct uart_port *port = platform_get_drvdata(dev);
 
+#ifdef CONFIG_SERIAL_SUNHV_POLLING
+       if (con_interrupt_timeout)
+               del_timer_sync(&con_timer);
+#endif
+
        free_irq(port->irq, port);
 
        uart_remove_one_port(&sunhv_reg, port);