aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/8250.c21
-rw-r--r--drivers/serial/bfin_5xx.c125
-rw-r--r--drivers/serial/icom.c55
-rw-r--r--drivers/serial/sunhv.c276
4 files changed, 332 insertions, 145 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 48e259a0167d..c84dab083a85 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -894,7 +894,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
894 quot = serial_dl_read(up); 894 quot = serial_dl_read(up);
895 quot <<= 3; 895 quot <<= 3;
896 896
897 status1 = serial_in(up, 0x04); /* EXCR1 */ 897 status1 = serial_in(up, 0x04); /* EXCR2 */
898 status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ 898 status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
899 status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ 899 status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
900 serial_outp(up, 0x04, status1); 900 serial_outp(up, 0x04, status1);
@@ -2617,7 +2617,22 @@ void serial8250_suspend_port(int line)
2617 */ 2617 */
2618void serial8250_resume_port(int line) 2618void serial8250_resume_port(int line)
2619{ 2619{
2620 uart_resume_port(&serial8250_reg, &serial8250_ports[line].port); 2620 struct uart_8250_port *up = &serial8250_ports[line];
2621
2622 if (up->capabilities & UART_NATSEMI) {
2623 unsigned char tmp;
2624
2625 /* Ensure it's still in high speed mode */
2626 serial_outp(up, UART_LCR, 0xE0);
2627
2628 tmp = serial_in(up, 0x04); /* EXCR2 */
2629 tmp &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
2630 tmp |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
2631 serial_outp(up, 0x04, tmp);
2632
2633 serial_outp(up, UART_LCR, 0);
2634 }
2635 uart_resume_port(&serial8250_reg, &up->port);
2621} 2636}
2622 2637
2623/* 2638/*
@@ -2694,7 +2709,7 @@ static int serial8250_resume(struct platform_device *dev)
2694 struct uart_8250_port *up = &serial8250_ports[i]; 2709 struct uart_8250_port *up = &serial8250_ports[i];
2695 2710
2696 if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) 2711 if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
2697 uart_resume_port(&serial8250_reg, &up->port); 2712 serial8250_resume_port(i);
2698 } 2713 }
2699 2714
2700 return 0; 2715 return 0;
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index 408390f93db9..787dc7168f3e 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -6,8 +6,6 @@
6 * Created: 6 * Created:
7 * Description: Driver for blackfin 5xx serial ports 7 * Description: Driver for blackfin 5xx serial ports
8 * 8 *
9 * Rev: $Id: bfin_5xx.c,v 1.19 2006/09/24 02:33:53 aubrey Exp $
10 *
11 * Modified: 9 * Modified:
12 * Copyright 2006 Analog Devices Inc. 10 * Copyright 2006 Analog Devices Inc.
13 * 11 *
@@ -152,7 +150,7 @@ static void local_put_char(struct bfin_serial_port *uart, char ch)
152 150
153static void bfin_serial_rx_chars(struct bfin_serial_port *uart) 151static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
154{ 152{
155 struct tty_struct *tty = uart->port.info?uart->port.info->tty:0; 153 struct tty_struct *tty = uart->port.info->tty;
156 unsigned int status, ch, flg; 154 unsigned int status, ch, flg;
157#ifdef BF533_FAMILY 155#ifdef BF533_FAMILY
158 static int in_break = 0; 156 static int in_break = 0;
@@ -173,8 +171,10 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
173 if (ch != 0) { 171 if (ch != 0) {
174 in_break = 0; 172 in_break = 0;
175 ch = UART_GET_CHAR(uart); 173 ch = UART_GET_CHAR(uart);
176 } 174 if (bfin_revid() < 5)
177 return; 175 return;
176 } else
177 return;
178 } 178 }
179#endif 179#endif
180 180
@@ -185,27 +185,32 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
185 uart->port.icount.brk++; 185 uart->port.icount.brk++;
186 if (uart_handle_break(&uart->port)) 186 if (uart_handle_break(&uart->port))
187 goto ignore_char; 187 goto ignore_char;
188 flg = TTY_BREAK; 188 }
189 } else if (status & PE) { 189 if (status & PE)
190 flg = TTY_PARITY;
191 uart->port.icount.parity++; 190 uart->port.icount.parity++;
192 } else if (status & OE) { 191 if (status & OE)
193 flg = TTY_OVERRUN;
194 uart->port.icount.overrun++; 192 uart->port.icount.overrun++;
195 } else if (status & FE) { 193 if (status & FE)
196 flg = TTY_FRAME;
197 uart->port.icount.frame++; 194 uart->port.icount.frame++;
198 } else 195
196 status &= uart->port.read_status_mask;
197
198 if (status & BI)
199 flg = TTY_BREAK;
200 else if (status & PE)
201 flg = TTY_PARITY;
202 else if (status & FE)
203 flg = TTY_FRAME;
204 else
199 flg = TTY_NORMAL; 205 flg = TTY_NORMAL;
200 206
201 if (uart_handle_sysrq_char(&uart->port, ch)) 207 if (uart_handle_sysrq_char(&uart->port, ch))
202 goto ignore_char; 208 goto ignore_char;
203 if (tty)
204 uart_insert_char(&uart->port, status, 2, ch, flg);
205 209
206ignore_char: 210 uart_insert_char(&uart->port, status, OE, ch, flg);
207 if (tty) 211
208 tty_flip_buffer_push(tty); 212 ignore_char:
213 tty_flip_buffer_push(tty);
209} 214}
210 215
211static void bfin_serial_tx_chars(struct bfin_serial_port *uart) 216static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
@@ -240,24 +245,29 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
240 bfin_serial_stop_tx(&uart->port); 245 bfin_serial_stop_tx(&uart->port);
241} 246}
242 247
243static irqreturn_t bfin_serial_int(int irq, void *dev_id) 248static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id)
244{ 249{
245 struct bfin_serial_port *uart = dev_id; 250 struct bfin_serial_port *uart = dev_id;
246 unsigned short status;
247 251
248 spin_lock(&uart->port.lock); 252 spin_lock(&uart->port.lock);
249 status = UART_GET_IIR(uart); 253 while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_RX_READY)
250 do { 254 bfin_serial_rx_chars(uart);
251 if ((status & IIR_STATUS) == IIR_TX_READY)
252 bfin_serial_tx_chars(uart);
253 if ((status & IIR_STATUS) == IIR_RX_READY)
254 bfin_serial_rx_chars(uart);
255 status = UART_GET_IIR(uart);
256 } while (status & (IIR_TX_READY | IIR_RX_READY));
257 spin_unlock(&uart->port.lock); 255 spin_unlock(&uart->port.lock);
258 return IRQ_HANDLED; 256 return IRQ_HANDLED;
259} 257}
260 258
259static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id)
260{
261 struct bfin_serial_port *uart = dev_id;
262
263 spin_lock(&uart->port.lock);
264 while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_TX_READY)
265 bfin_serial_tx_chars(uart);
266 spin_unlock(&uart->port.lock);
267 return IRQ_HANDLED;
268}
269
270
261static void bfin_serial_do_work(struct work_struct *work) 271static void bfin_serial_do_work(struct work_struct *work)
262{ 272{
263 struct bfin_serial_port *uart = container_of(work, struct bfin_serial_port, cts_workqueue); 273 struct bfin_serial_port *uart = container_of(work, struct bfin_serial_port, cts_workqueue);
@@ -319,7 +329,7 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
319 spin_unlock_irqrestore(&uart->port.lock, flags); 329 spin_unlock_irqrestore(&uart->port.lock, flags);
320} 330}
321 331
322static void bfin_serial_dma_rx_chars(struct bfin_serial_port * uart) 332static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
323{ 333{
324 struct tty_struct *tty = uart->port.info->tty; 334 struct tty_struct *tty = uart->port.info->tty;
325 int i, flg, status; 335 int i, flg, status;
@@ -331,25 +341,32 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port * uart)
331 uart->port.icount.brk++; 341 uart->port.icount.brk++;
332 if (uart_handle_break(&uart->port)) 342 if (uart_handle_break(&uart->port))
333 goto dma_ignore_char; 343 goto dma_ignore_char;
334 flg = TTY_BREAK; 344 }
335 } else if (status & PE) { 345 if (status & PE)
336 flg = TTY_PARITY;
337 uart->port.icount.parity++; 346 uart->port.icount.parity++;
338 } else if (status & OE) { 347 if (status & OE)
339 flg = TTY_OVERRUN;
340 uart->port.icount.overrun++; 348 uart->port.icount.overrun++;
341 } else if (status & FE) { 349 if (status & FE)
342 flg = TTY_FRAME;
343 uart->port.icount.frame++; 350 uart->port.icount.frame++;
344 } else 351
352 status &= uart->port.read_status_mask;
353
354 if (status & BI)
355 flg = TTY_BREAK;
356 else if (status & PE)
357 flg = TTY_PARITY;
358 else if (status & FE)
359 flg = TTY_FRAME;
360 else
345 flg = TTY_NORMAL; 361 flg = TTY_NORMAL;
346 362
347 for (i = uart->rx_dma_buf.head; i < uart->rx_dma_buf.tail; i++) { 363 for (i = uart->rx_dma_buf.head; i < uart->rx_dma_buf.tail; i++) {
348 if (uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i])) 364 if (uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i]))
349 goto dma_ignore_char; 365 goto dma_ignore_char;
350 uart_insert_char(&uart->port, status, 2, uart->rx_dma_buf.buf[i], flg); 366 uart_insert_char(&uart->port, status, OE, uart->rx_dma_buf.buf[i], flg);
351 } 367 }
352dma_ignore_char: 368
369 dma_ignore_char:
353 tty_flip_buffer_push(tty); 370 tty_flip_buffer_push(tty);
354} 371}
355 372
@@ -545,14 +562,14 @@ static int bfin_serial_startup(struct uart_port *port)
545 add_timer(&(uart->rx_dma_timer)); 562 add_timer(&(uart->rx_dma_timer));
546#else 563#else
547 if (request_irq 564 if (request_irq
548 (uart->port.irq, bfin_serial_int, IRQF_DISABLED, 565 (uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED,
549 "BFIN_UART_RX", uart)) { 566 "BFIN_UART_RX", uart)) {
550 printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n"); 567 printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n");
551 return -EBUSY; 568 return -EBUSY;
552 } 569 }
553 570
554 if (request_irq 571 if (request_irq
555 (uart->port.irq+1, bfin_serial_int, IRQF_DISABLED, 572 (uart->port.irq+1, bfin_serial_tx_int, IRQF_DISABLED,
556 "BFIN_UART_TX", uart)) { 573 "BFIN_UART_TX", uart)) {
557 printk(KERN_NOTICE "Unable to attach BlackFin UART TX interrupt\n"); 574 printk(KERN_NOTICE "Unable to attach BlackFin UART TX interrupt\n");
558 free_irq(uart->port.irq, uart); 575 free_irq(uart->port.irq, uart);
@@ -614,13 +631,27 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
614 lcr |= EPS; 631 lcr |= EPS;
615 } 632 }
616 633
617 /* These controls are not implemented for this port */ 634 port->read_status_mask = OE;
618 termios->c_iflag |= INPCK | BRKINT | PARMRK; 635 if (termios->c_iflag & INPCK)
619 termios->c_iflag &= ~(IGNPAR | IGNBRK); 636 port->read_status_mask |= (FE | PE);
637 if (termios->c_iflag & (BRKINT | PARMRK))
638 port->read_status_mask |= BI;
620 639
621 /* These controls are not implemented for this port */ 640 /*
622 termios->c_iflag |= INPCK | BRKINT | PARMRK; 641 * Characters to ignore
623 termios->c_iflag &= ~(IGNPAR | IGNBRK); 642 */
643 port->ignore_status_mask = 0;
644 if (termios->c_iflag & IGNPAR)
645 port->ignore_status_mask |= FE | PE;
646 if (termios->c_iflag & IGNBRK) {
647 port->ignore_status_mask |= BI;
648 /*
649 * If we're ignoring parity and break indicators,
650 * ignore overruns too (for real raw support).
651 */
652 if (termios->c_iflag & IGNPAR)
653 port->ignore_status_mask |= OE;
654 }
624 655
625 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 656 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
626 quot = uart_get_divisor(port, baud); 657 quot = uart_get_divisor(port, baud);
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
index 6202995e8211..9d3105b64a7a 100644
--- a/drivers/serial/icom.c
+++ b/drivers/serial/icom.c
@@ -69,33 +69,40 @@
69 69
70static const struct pci_device_id icom_pci_table[] = { 70static const struct pci_device_id icom_pci_table[] = {
71 { 71 {
72 .vendor = PCI_VENDOR_ID_IBM, 72 .vendor = PCI_VENDOR_ID_IBM,
73 .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1, 73 .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1,
74 .subvendor = PCI_ANY_ID, 74 .subvendor = PCI_ANY_ID,
75 .subdevice = PCI_ANY_ID, 75 .subdevice = PCI_ANY_ID,
76 .driver_data = ADAPTER_V1, 76 .driver_data = ADAPTER_V1,
77 }, 77 },
78 { 78 {
79 .vendor = PCI_VENDOR_ID_IBM, 79 .vendor = PCI_VENDOR_ID_IBM,
80 .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2, 80 .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
81 .subvendor = PCI_VENDOR_ID_IBM, 81 .subvendor = PCI_VENDOR_ID_IBM,
82 .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX, 82 .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX,
83 .driver_data = ADAPTER_V2, 83 .driver_data = ADAPTER_V2,
84 }, 84 },
85 { 85 {
86 .vendor = PCI_VENDOR_ID_IBM, 86 .vendor = PCI_VENDOR_ID_IBM,
87 .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2, 87 .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
88 .subvendor = PCI_VENDOR_ID_IBM, 88 .subvendor = PCI_VENDOR_ID_IBM,
89 .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM, 89 .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM,
90 .driver_data = ADAPTER_V2, 90 .driver_data = ADAPTER_V2,
91 }, 91 },
92 { 92 {
93 .vendor = PCI_VENDOR_ID_IBM, 93 .vendor = PCI_VENDOR_ID_IBM,
94 .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2, 94 .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
95 .subvendor = PCI_VENDOR_ID_IBM, 95 .subvendor = PCI_VENDOR_ID_IBM,
96 .subdevice = PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL, 96 .subdevice = PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL,
97 .driver_data = ADAPTER_V2, 97 .driver_data = ADAPTER_V2,
98 }, 98 },
99 {
100 .vendor = PCI_VENDOR_ID_IBM,
101 .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
102 .subvendor = PCI_VENDOR_ID_IBM,
103 .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE,
104 .driver_data = ADAPTER_V2,
105 },
99 {} 106 {}
100}; 107};
101 108
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c
index c3a6bd2e7950..96557e6dba60 100644
--- a/drivers/serial/sunhv.c
+++ b/drivers/serial/sunhv.c
@@ -1,6 +1,6 @@
1/* sunhv.c: Serial driver for SUN4V hypervisor console. 1/* sunhv.c: Serial driver for SUN4V hypervisor console.
2 * 2 *
3 * Copyright (C) 2006 David S. Miller (davem@davemloft.net) 3 * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
4 */ 4 */
5 5
6#include <linux/module.h> 6#include <linux/module.h>
@@ -35,57 +35,51 @@
35#define CON_BREAK ((long)-1) 35#define CON_BREAK ((long)-1)
36#define CON_HUP ((long)-2) 36#define CON_HUP ((long)-2)
37 37
38static inline long hypervisor_con_getchar(long *status) 38#define IGNORE_BREAK 0x1
39{ 39#define IGNORE_ALL 0x2
40 register unsigned long func asm("%o5");
41 register unsigned long arg0 asm("%o0");
42 register unsigned long arg1 asm("%o1");
43
44 func = HV_FAST_CONS_GETCHAR;
45 arg0 = 0;
46 arg1 = 0;
47 __asm__ __volatile__("ta %6"
48 : "=&r" (func), "=&r" (arg0), "=&r" (arg1)
49 : "0" (func), "1" (arg0), "2" (arg1),
50 "i" (HV_FAST_TRAP));
51 40
52 *status = arg0; 41static char *con_write_page;
42static char *con_read_page;
53 43
54 return (long) arg1; 44static int hung_up = 0;
55}
56 45
57static inline long hypervisor_con_putchar(long ch) 46static void transmit_chars_putchar(struct uart_port *port, struct circ_buf *xmit)
58{ 47{
59 register unsigned long func asm("%o5"); 48 while (!uart_circ_empty(xmit)) {
60 register unsigned long arg0 asm("%o0"); 49 long status = sun4v_con_putchar(xmit->buf[xmit->tail]);
61 50
62 func = HV_FAST_CONS_PUTCHAR; 51 if (status != HV_EOK)
63 arg0 = ch; 52 break;
64 __asm__ __volatile__("ta %4"
65 : "=&r" (func), "=&r" (arg0)
66 : "0" (func), "1" (arg0), "i" (HV_FAST_TRAP));
67 53
68 return (long) arg0; 54 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
55 port->icount.tx++;
56 }
69} 57}
70 58
71#define IGNORE_BREAK 0x1 59static void transmit_chars_write(struct uart_port *port, struct circ_buf *xmit)
72#define IGNORE_ALL 0x2 60{
61 while (!uart_circ_empty(xmit)) {
62 unsigned long ra = __pa(xmit->buf + xmit->tail);
63 unsigned long len, status, sent;
73 64
74static int hung_up = 0; 65 len = CIRC_CNT_TO_END(xmit->head, xmit->tail,
66 UART_XMIT_SIZE);
67 status = sun4v_con_write(ra, len, &sent);
68 if (status != HV_EOK)
69 break;
70 xmit->tail = (xmit->tail + sent) & (UART_XMIT_SIZE - 1);
71 port->icount.tx += sent;
72 }
73}
75 74
76static struct tty_struct *receive_chars(struct uart_port *port) 75static int receive_chars_getchar(struct uart_port *port, struct tty_struct *tty)
77{ 76{
78 struct tty_struct *tty = NULL;
79 int saw_console_brk = 0; 77 int saw_console_brk = 0;
80 int limit = 10000; 78 int limit = 10000;
81 79
82 if (port->info != NULL) /* Unopened serial console */
83 tty = port->info->tty;
84
85 while (limit-- > 0) { 80 while (limit-- > 0) {
86 long status; 81 long status;
87 long c = hypervisor_con_getchar(&status); 82 long c = sun4v_con_getchar(&status);
88 unsigned char flag;
89 83
90 if (status == HV_EWOULDBLOCK) 84 if (status == HV_EWOULDBLOCK)
91 break; 85 break;
@@ -110,27 +104,90 @@ static struct tty_struct *receive_chars(struct uart_port *port)
110 continue; 104 continue;
111 } 105 }
112 106
113 flag = TTY_NORMAL;
114 port->icount.rx++; 107 port->icount.rx++;
115 if (c == CON_BREAK) {
116 port->icount.brk++;
117 if (uart_handle_break(port))
118 continue;
119 flag = TTY_BREAK;
120 }
121 108
122 if (uart_handle_sysrq_char(port, c)) 109 if (uart_handle_sysrq_char(port, c))
123 continue; 110 continue;
124 111
125 if ((port->ignore_status_mask & IGNORE_ALL) || 112 tty_insert_flip_char(tty, c, TTY_NORMAL);
126 ((port->ignore_status_mask & IGNORE_BREAK) && 113 }
127 (c == CON_BREAK))) 114
115 return saw_console_brk;
116}
117
118static int receive_chars_read(struct uart_port *port, struct tty_struct *tty)
119{
120 int saw_console_brk = 0;
121 int limit = 10000;
122
123 while (limit-- > 0) {
124 unsigned long ra = __pa(con_read_page);
125 unsigned long bytes_read, i;
126 long stat = sun4v_con_read(ra, PAGE_SIZE, &bytes_read);
127
128 if (stat != HV_EOK) {
129 bytes_read = 0;
130
131 if (stat == CON_BREAK) {
132 if (uart_handle_break(port))
133 continue;
134 saw_console_brk = 1;
135 *con_read_page = 0;
136 bytes_read = 1;
137 } else if (stat == CON_HUP) {
138 hung_up = 1;
139 uart_handle_dcd_change(port, 0);
140 continue;
141 } else {
142 /* HV_EWOULDBLOCK, etc. */
143 break;
144 }
145 }
146
147 if (hung_up) {
148 hung_up = 0;
149 uart_handle_dcd_change(port, 1);
150 }
151
152 for (i = 0; i < bytes_read; i++)
153 uart_handle_sysrq_char(port, con_read_page[i]);
154
155 if (tty == NULL)
128 continue; 156 continue;
129 157
130 tty_insert_flip_char(tty, c, flag); 158 port->icount.rx += bytes_read;
159
160 tty_insert_flip_string(tty, con_read_page, bytes_read);
131 } 161 }
132 162
133 if (saw_console_brk) 163 return saw_console_brk;
164}
165
166struct sunhv_ops {
167 void (*transmit_chars)(struct uart_port *port, struct circ_buf *xmit);
168 int (*receive_chars)(struct uart_port *port, struct tty_struct *tty);
169};
170
171static struct sunhv_ops bychar_ops = {
172 .transmit_chars = transmit_chars_putchar,
173 .receive_chars = receive_chars_getchar,
174};
175
176static struct sunhv_ops bywrite_ops = {
177 .transmit_chars = transmit_chars_write,
178 .receive_chars = receive_chars_read,
179};
180
181static struct sunhv_ops *sunhv_ops = &bychar_ops;
182
183static struct tty_struct *receive_chars(struct uart_port *port)
184{
185 struct tty_struct *tty = NULL;
186
187 if (port->info != NULL) /* Unopened serial console */
188 tty = port->info->tty;
189
190 if (sunhv_ops->receive_chars(port, tty))
134 sun_do_break(); 191 sun_do_break();
135 192
136 return tty; 193 return tty;
@@ -147,15 +204,7 @@ static void transmit_chars(struct uart_port *port)
147 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) 204 if (uart_circ_empty(xmit) || uart_tx_stopped(port))
148 return; 205 return;
149 206
150 while (!uart_circ_empty(xmit)) { 207 sunhv_ops->transmit_chars(port, xmit);
151 long status = hypervisor_con_putchar(xmit->buf[xmit->tail]);
152
153 if (status != HV_EOK)
154 break;
155
156 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
157 port->icount.tx++;
158 }
159 208
160 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 209 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
161 uart_write_wakeup(port); 210 uart_write_wakeup(port);
@@ -212,7 +261,7 @@ static void sunhv_start_tx(struct uart_port *port)
212 struct circ_buf *xmit = &port->info->xmit; 261 struct circ_buf *xmit = &port->info->xmit;
213 262
214 while (!uart_circ_empty(xmit)) { 263 while (!uart_circ_empty(xmit)) {
215 long status = hypervisor_con_putchar(xmit->buf[xmit->tail]); 264 long status = sun4v_con_putchar(xmit->buf[xmit->tail]);
216 265
217 if (status != HV_EOK) 266 if (status != HV_EOK)
218 break; 267 break;
@@ -231,9 +280,10 @@ static void sunhv_send_xchar(struct uart_port *port, char ch)
231 spin_lock_irqsave(&port->lock, flags); 280 spin_lock_irqsave(&port->lock, flags);
232 281
233 while (limit-- > 0) { 282 while (limit-- > 0) {
234 long status = hypervisor_con_putchar(ch); 283 long status = sun4v_con_putchar(ch);
235 if (status == HV_EOK) 284 if (status == HV_EOK)
236 break; 285 break;
286 udelay(1);
237 } 287 }
238 288
239 spin_unlock_irqrestore(&port->lock, flags); 289 spin_unlock_irqrestore(&port->lock, flags);
@@ -254,15 +304,15 @@ static void sunhv_break_ctl(struct uart_port *port, int break_state)
254{ 304{
255 if (break_state) { 305 if (break_state) {
256 unsigned long flags; 306 unsigned long flags;
257 int limit = 1000000; 307 int limit = 10000;
258 308
259 spin_lock_irqsave(&port->lock, flags); 309 spin_lock_irqsave(&port->lock, flags);
260 310
261 while (limit-- > 0) { 311 while (limit-- > 0) {
262 long status = hypervisor_con_putchar(CON_BREAK); 312 long status = sun4v_con_putchar(CON_BREAK);
263 if (status == HV_EOK) 313 if (status == HV_EOK)
264 break; 314 break;
265 udelay(2); 315 udelay(1);
266 } 316 }
267 317
268 spin_unlock_irqrestore(&port->lock, flags); 318 spin_unlock_irqrestore(&port->lock, flags);
@@ -359,38 +409,99 @@ static struct uart_driver sunhv_reg = {
359 409
360static struct uart_port *sunhv_port; 410static struct uart_port *sunhv_port;
361 411
362static inline void sunhv_console_putchar(struct uart_port *port, char c) 412/* Copy 's' into the con_write_page, decoding "\n" into
413 * "\r\n" along the way. We have to return two lengths
414 * because the caller needs to know how much to advance
415 * 's' and also how many bytes to output via con_write_page.
416 */
417static int fill_con_write_page(const char *s, unsigned int n,
418 unsigned long *page_bytes)
419{
420 const char *orig_s = s;
421 char *p = con_write_page;
422 int left = PAGE_SIZE;
423
424 while (n--) {
425 if (*s == '\n') {
426 if (left < 2)
427 break;
428 *p++ = '\r';
429 left--;
430 } else if (left < 1)
431 break;
432 *p++ = *s++;
433 left--;
434 }
435 *page_bytes = p - con_write_page;
436 return s - orig_s;
437}
438
439static void sunhv_console_write_paged(struct console *con, const char *s, unsigned n)
363{ 440{
441 struct uart_port *port = sunhv_port;
364 unsigned long flags; 442 unsigned long flags;
365 int limit = 1000000;
366 443
367 spin_lock_irqsave(&port->lock, flags); 444 spin_lock_irqsave(&port->lock, flags);
445 while (n > 0) {
446 unsigned long ra = __pa(con_write_page);
447 unsigned long page_bytes;
448 unsigned int cpy = fill_con_write_page(s, n,
449 &page_bytes);
450
451 n -= cpy;
452 s += cpy;
453 while (page_bytes > 0) {
454 unsigned long written;
455 int limit = 1000000;
456
457 while (limit--) {
458 unsigned long stat;
459
460 stat = sun4v_con_write(ra, page_bytes,
461 &written);
462 if (stat == HV_EOK)
463 break;
464 udelay(1);
465 }
466 if (limit <= 0)
467 break;
468 page_bytes -= written;
469 ra += written;
470 }
471 }
472 spin_unlock_irqrestore(&port->lock, flags);
473}
474
475static inline void sunhv_console_putchar(struct uart_port *port, char c)
476{
477 int limit = 1000000;
368 478
369 while (limit-- > 0) { 479 while (limit-- > 0) {
370 long status = hypervisor_con_putchar(c); 480 long status = sun4v_con_putchar(c);
371 if (status == HV_EOK) 481 if (status == HV_EOK)
372 break; 482 break;
373 udelay(2); 483 udelay(1);
374 } 484 }
375
376 spin_unlock_irqrestore(&port->lock, flags);
377} 485}
378 486
379static void sunhv_console_write(struct console *con, const char *s, unsigned n) 487static void sunhv_console_write_bychar(struct console *con, const char *s, unsigned n)
380{ 488{
381 struct uart_port *port = sunhv_port; 489 struct uart_port *port = sunhv_port;
490 unsigned long flags;
382 int i; 491 int i;
383 492
493 spin_lock_irqsave(&port->lock, flags);
384 for (i = 0; i < n; i++) { 494 for (i = 0; i < n; i++) {
385 if (*s == '\n') 495 if (*s == '\n')
386 sunhv_console_putchar(port, '\r'); 496 sunhv_console_putchar(port, '\r');
387 sunhv_console_putchar(port, *s++); 497 sunhv_console_putchar(port, *s++);
388 } 498 }
499 spin_unlock_irqrestore(&port->lock, flags);
389} 500}
390 501
391static struct console sunhv_console = { 502static struct console sunhv_console = {
392 .name = "ttyHV", 503 .name = "ttyHV",
393 .write = sunhv_console_write, 504 .write = sunhv_console_write_bychar,
394 .device = uart_console_device, 505 .device = uart_console_device,
395 .flags = CON_PRINTBUFFER, 506 .flags = CON_PRINTBUFFER,
396 .index = -1, 507 .index = -1,
@@ -410,6 +521,7 @@ static inline struct console *SUNHV_CONSOLE(void)
410static int __devinit hv_probe(struct of_device *op, const struct of_device_id *match) 521static int __devinit hv_probe(struct of_device *op, const struct of_device_id *match)
411{ 522{
412 struct uart_port *port; 523 struct uart_port *port;
524 unsigned long minor;
413 int err; 525 int err;
414 526
415 if (op->irqs[0] == 0xffffffff) 527 if (op->irqs[0] == 0xffffffff)
@@ -419,6 +531,22 @@ static int __devinit hv_probe(struct of_device *op, const struct of_device_id *m
419 if (unlikely(!port)) 531 if (unlikely(!port))
420 return -ENOMEM; 532 return -ENOMEM;
421 533
534 minor = 1;
535 if (sun4v_hvapi_register(HV_GRP_CORE, 1, &minor) == 0 &&
536 minor >= 1) {
537 err = -ENOMEM;
538 con_write_page = kzalloc(PAGE_SIZE, GFP_KERNEL);
539 if (!con_write_page)
540 goto out_free_port;
541
542 con_read_page = kzalloc(PAGE_SIZE, GFP_KERNEL);
543 if (!con_read_page)
544 goto out_free_con_write_page;
545
546 sunhv_console.write = sunhv_console_write_paged;
547 sunhv_ops = &bywrite_ops;
548 }
549
422 sunhv_port = port; 550 sunhv_port = port;
423 551
424 port->line = 0; 552 port->line = 0;
@@ -437,7 +565,7 @@ static int __devinit hv_probe(struct of_device *op, const struct of_device_id *m
437 565
438 err = uart_register_driver(&sunhv_reg); 566 err = uart_register_driver(&sunhv_reg);
439 if (err) 567 if (err)
440 goto out_free_port; 568 goto out_free_con_read_page;
441 569
442 sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64; 570 sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64;
443 sunserial_current_minor += 1; 571 sunserial_current_minor += 1;
@@ -463,6 +591,12 @@ out_unregister_driver:
463 sunserial_current_minor -= 1; 591 sunserial_current_minor -= 1;
464 uart_unregister_driver(&sunhv_reg); 592 uart_unregister_driver(&sunhv_reg);
465 593
594out_free_con_read_page:
595 kfree(con_read_page);
596
597out_free_con_write_page:
598 kfree(con_write_page);
599
466out_free_port: 600out_free_port:
467 kfree(port); 601 kfree(port);
468 sunhv_port = NULL; 602 sunhv_port = NULL;