diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-26 09:11:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-26 09:11:09 -0400 |
commit | efb8d21b2c6db3497655cc6a033ae8a9883e4063 (patch) | |
tree | a14a0dbb9fec3a6db5e542ba7ed4a49681706420 /drivers/tty/serial/mrst_max3110.c | |
parent | 3cb603284b3d256ae9ae9e65887cee8416bfef15 (diff) | |
parent | d208a3bf77f902283894f546b6b5383202cf7882 (diff) |
Merge branch 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
* 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (79 commits)
TTY: serial_core: Fix crash if DCD drop during suspend
tty/serial: atmel_serial: bootconsole removed from auto-enumerates
Revert "TTY: call tty_driver_lookup_tty unconditionally"
tty/serial: atmel_serial: add device tree support
tty/serial: atmel_serial: auto-enumerate ports
tty/serial: atmel_serial: whitespace and braces modifications
tty/serial: atmel_serial: change platform_data variable name
tty/serial: RS485 bindings for device tree
TTY: call tty_driver_lookup_tty unconditionally
TTY: pty, release tty in all ptmx_open fail paths
TTY: make tty_add_file non-failing
TTY: drop driver reference in tty_open fail path
8250_pci: Fix kernel panic when pch_uart is disabled
h8300: drivers/serial/Kconfig was moved
parport_pc: release IO region properly if unsupported ITE887x card is found
tty: Support compat_ioctl get/set termios_locked
hvc_console: display printk messages on console.
TTY: snyclinkmp: forever loop in tx_load_dma_buffer()
tty/n_gsm: avoid fifo overflow in gsm_dlci_data_output
tty/n_gsm: fix a bug in gsm_dlci_data_output (adaption = 2 case)
...
Fix up Conflicts in:
- drivers/tty/serial/8250_pci.c
Trivial conflict with removed duplicate device ID
- drivers/tty/serial/atmel_serial.c
Annoying silly conflict between "specify the port num via
platform_data" and other changes to atmel_console_init
Diffstat (limited to 'drivers/tty/serial/mrst_max3110.c')
-rw-r--r-- | drivers/tty/serial/mrst_max3110.c | 115 |
1 files changed, 54 insertions, 61 deletions
diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c index 492c14d63e99..4c309e869903 100644 --- a/drivers/tty/serial/mrst_max3110.c +++ b/drivers/tty/serial/mrst_max3110.c | |||
@@ -27,6 +27,10 @@ | |||
27 | * interrupt for a low speed UART device | 27 | * interrupt for a low speed UART device |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #ifdef CONFIG_MAGIC_SYSRQ | ||
31 | #define SUPPORT_SYSRQ | ||
32 | #endif | ||
33 | |||
30 | #include <linux/module.h> | 34 | #include <linux/module.h> |
31 | #include <linux/ioport.h> | 35 | #include <linux/ioport.h> |
32 | #include <linux/irq.h> | 36 | #include <linux/irq.h> |
@@ -73,9 +77,9 @@ struct uart_max3110 { | |||
73 | /* global data structure, may need be removed */ | 77 | /* global data structure, may need be removed */ |
74 | static struct uart_max3110 *pmax; | 78 | static struct uart_max3110 *pmax; |
75 | 79 | ||
76 | static void receive_chars(struct uart_max3110 *max, | 80 | static int receive_chars(struct uart_max3110 *max, |
77 | unsigned char *str, int len); | 81 | unsigned short *str, int len); |
78 | static int max3110_read_multi(struct uart_max3110 *max, u8 *buf); | 82 | static int max3110_read_multi(struct uart_max3110 *max); |
79 | static void max3110_con_receive(struct uart_max3110 *max); | 83 | static void max3110_con_receive(struct uart_max3110 *max); |
80 | 84 | ||
81 | static int max3110_write_then_read(struct uart_max3110 *max, | 85 | static int max3110_write_then_read(struct uart_max3110 *max, |
@@ -108,7 +112,6 @@ static int max3110_out(struct uart_max3110 *max, const u16 out) | |||
108 | { | 112 | { |
109 | void *buf; | 113 | void *buf; |
110 | u16 *obuf, *ibuf; | 114 | u16 *obuf, *ibuf; |
111 | u8 ch; | ||
112 | int ret; | 115 | int ret; |
113 | 116 | ||
114 | buf = kzalloc(8, GFP_KERNEL | GFP_DMA); | 117 | buf = kzalloc(8, GFP_KERNEL | GFP_DMA); |
@@ -125,11 +128,7 @@ static int max3110_out(struct uart_max3110 *max, const u16 out) | |||
125 | goto exit; | 128 | goto exit; |
126 | } | 129 | } |
127 | 130 | ||
128 | /* If some valid data is read back */ | 131 | receive_chars(max, ibuf, 1); |
129 | if (*ibuf & MAX3110_READ_DATA_AVAILABLE) { | ||
130 | ch = *ibuf & 0xff; | ||
131 | receive_chars(max, &ch, 1); | ||
132 | } | ||
133 | 132 | ||
134 | exit: | 133 | exit: |
135 | kfree(buf); | 134 | kfree(buf); |
@@ -142,12 +141,11 @@ exit: | |||
142 | * | 141 | * |
143 | * Return how many valide bytes are read back | 142 | * Return how many valide bytes are read back |
144 | */ | 143 | */ |
145 | static int max3110_read_multi(struct uart_max3110 *max, u8 *rxbuf) | 144 | static int max3110_read_multi(struct uart_max3110 *max) |
146 | { | 145 | { |
147 | void *buf; | 146 | void *buf; |
148 | u16 *obuf, *ibuf; | 147 | u16 *obuf, *ibuf; |
149 | u8 *pbuf, valid_str[M3110_RX_FIFO_DEPTH]; | 148 | int ret, blen; |
150 | int i, j, blen; | ||
151 | 149 | ||
152 | blen = M3110_RX_FIFO_DEPTH * sizeof(u16); | 150 | blen = M3110_RX_FIFO_DEPTH * sizeof(u16); |
153 | buf = kzalloc(blen * 2, GFP_KERNEL | GFP_DMA); | 151 | buf = kzalloc(blen * 2, GFP_KERNEL | GFP_DMA); |
@@ -165,19 +163,10 @@ static int max3110_read_multi(struct uart_max3110 *max, u8 *rxbuf) | |||
165 | return 0; | 163 | return 0; |
166 | } | 164 | } |
167 | 165 | ||
168 | /* If caller doesn't provide a buffer, then handle received char */ | 166 | ret = receive_chars(max, ibuf, M3110_RX_FIFO_DEPTH); |
169 | pbuf = rxbuf ? rxbuf : valid_str; | ||
170 | |||
171 | for (i = 0, j = 0; i < M3110_RX_FIFO_DEPTH; i++) { | ||
172 | if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE) | ||
173 | pbuf[j++] = ibuf[i] & 0xff; | ||
174 | } | ||
175 | |||
176 | if (j && (pbuf == valid_str)) | ||
177 | receive_chars(max, valid_str, j); | ||
178 | 167 | ||
179 | kfree(buf); | 168 | kfree(buf); |
180 | return j; | 169 | return ret; |
181 | } | 170 | } |
182 | 171 | ||
183 | static void serial_m3110_con_putchar(struct uart_port *port, int ch) | 172 | static void serial_m3110_con_putchar(struct uart_port *port, int ch) |
@@ -207,7 +196,7 @@ static void serial_m3110_con_write(struct console *co, | |||
207 | uart_console_write(&pmax->port, s, count, serial_m3110_con_putchar); | 196 | uart_console_write(&pmax->port, s, count, serial_m3110_con_putchar); |
208 | 197 | ||
209 | if (!test_and_set_bit(CON_TX_NEEDED, &pmax->uart_flags)) | 198 | if (!test_and_set_bit(CON_TX_NEEDED, &pmax->uart_flags)) |
210 | wake_up_process(pmax->main_thread); | 199 | wake_up(&pmax->wq); |
211 | } | 200 | } |
212 | 201 | ||
213 | static int __init | 202 | static int __init |
@@ -276,8 +265,7 @@ static void send_circ_buf(struct uart_max3110 *max, | |||
276 | { | 265 | { |
277 | void *buf; | 266 | void *buf; |
278 | u16 *obuf, *ibuf; | 267 | u16 *obuf, *ibuf; |
279 | u8 valid_str[WORDS_PER_XFER]; | 268 | int i, len, blen, dma_size, left, ret = 0; |
280 | int i, j, len, blen, dma_size, left, ret = 0; | ||
281 | 269 | ||
282 | 270 | ||
283 | dma_size = WORDS_PER_XFER * sizeof(u16) * 2; | 271 | dma_size = WORDS_PER_XFER * sizeof(u16) * 2; |
@@ -301,18 +289,13 @@ static void send_circ_buf(struct uart_max3110 *max, | |||
301 | } | 289 | } |
302 | 290 | ||
303 | /* Fail to send msg to console is not very critical */ | 291 | /* Fail to send msg to console is not very critical */ |
292 | |||
304 | ret = max3110_write_then_read(max, obuf, ibuf, blen, 0); | 293 | ret = max3110_write_then_read(max, obuf, ibuf, blen, 0); |
305 | if (ret) | 294 | if (ret) |
306 | pr_warning(PR_FMT "%s(): get err msg %d\n", | 295 | pr_warning(PR_FMT "%s(): get err msg %d\n", |
307 | __func__, ret); | 296 | __func__, ret); |
308 | 297 | ||
309 | for (i = 0, j = 0; i < len; i++) { | 298 | receive_chars(max, ibuf, len); |
310 | if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE) | ||
311 | valid_str[j++] = ibuf[i] & 0xff; | ||
312 | } | ||
313 | |||
314 | if (j) | ||
315 | receive_chars(max, valid_str, j); | ||
316 | 299 | ||
317 | max->port.icount.tx += len; | 300 | max->port.icount.tx += len; |
318 | left -= len; | 301 | left -= len; |
@@ -349,33 +332,54 @@ static void serial_m3110_start_tx(struct uart_port *port) | |||
349 | container_of(port, struct uart_max3110, port); | 332 | container_of(port, struct uart_max3110, port); |
350 | 333 | ||
351 | if (!test_and_set_bit(UART_TX_NEEDED, &max->uart_flags)) | 334 | if (!test_and_set_bit(UART_TX_NEEDED, &max->uart_flags)) |
352 | wake_up_process(max->main_thread); | 335 | wake_up(&max->wq); |
353 | } | 336 | } |
354 | 337 | ||
355 | static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len) | 338 | static int |
339 | receive_chars(struct uart_max3110 *max, unsigned short *str, int len) | ||
356 | { | 340 | { |
357 | struct uart_port *port = &max->port; | 341 | struct uart_port *port = &max->port; |
358 | struct tty_struct *tty; | 342 | struct tty_struct *tty; |
359 | int usable; | 343 | char buf[M3110_RX_FIFO_DEPTH]; |
344 | int r, w, usable; | ||
360 | 345 | ||
361 | /* If uart is not opened, just return */ | 346 | /* If uart is not opened, just return */ |
362 | if (!port->state) | 347 | if (!port->state) |
363 | return; | 348 | return 0; |
364 | 349 | ||
365 | tty = port->state->port.tty; | 350 | tty = tty_port_tty_get(&port->state->port); |
366 | if (!tty) | 351 | if (!tty) |
367 | return; | 352 | return 0; |
353 | |||
354 | for (r = 0, w = 0; r < len; r++) { | ||
355 | if (str[r] & MAX3110_BREAK && | ||
356 | uart_handle_break(port)) | ||
357 | continue; | ||
358 | |||
359 | if (str[r] & MAX3110_READ_DATA_AVAILABLE) { | ||
360 | if (uart_handle_sysrq_char(port, str[r] & 0xff)) | ||
361 | continue; | ||
362 | |||
363 | buf[w++] = str[r] & 0xff; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | if (!w) { | ||
368 | tty_kref_put(tty); | ||
369 | return 0; | ||
370 | } | ||
368 | 371 | ||
369 | while (len) { | 372 | for (r = 0; w; r += usable, w -= usable) { |
370 | usable = tty_buffer_request_room(tty, len); | 373 | usable = tty_buffer_request_room(tty, w); |
371 | if (usable) { | 374 | if (usable) { |
372 | tty_insert_flip_string(tty, str, usable); | 375 | tty_insert_flip_string(tty, buf + r, usable); |
373 | str += usable; | ||
374 | port->icount.rx += usable; | 376 | port->icount.rx += usable; |
375 | } | 377 | } |
376 | len -= usable; | ||
377 | } | 378 | } |
378 | tty_flip_buffer_push(tty); | 379 | tty_flip_buffer_push(tty); |
380 | tty_kref_put(tty); | ||
381 | |||
382 | return r; | ||
379 | } | 383 | } |
380 | 384 | ||
381 | /* | 385 | /* |
@@ -390,28 +394,15 @@ static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len) | |||
390 | */ | 394 | */ |
391 | static void max3110_con_receive(struct uart_max3110 *max) | 395 | static void max3110_con_receive(struct uart_max3110 *max) |
392 | { | 396 | { |
393 | int loop = 1, num, total = 0; | 397 | int loop = 1, num; |
394 | u8 recv_buf[512], *pbuf; | ||
395 | 398 | ||
396 | pbuf = recv_buf; | ||
397 | do { | 399 | do { |
398 | num = max3110_read_multi(max, pbuf); | 400 | num = max3110_read_multi(max); |
399 | 401 | ||
400 | if (num) { | 402 | if (num) { |
401 | loop = 5; | 403 | loop = 5; |
402 | pbuf += num; | ||
403 | total += num; | ||
404 | |||
405 | if (total >= 504) { | ||
406 | receive_chars(max, recv_buf, total); | ||
407 | pbuf = recv_buf; | ||
408 | total = 0; | ||
409 | } | ||
410 | } | 404 | } |
411 | } while (--loop); | 405 | } while (--loop); |
412 | |||
413 | if (total) | ||
414 | receive_chars(max, recv_buf, total); | ||
415 | } | 406 | } |
416 | 407 | ||
417 | static int max3110_main_thread(void *_max) | 408 | static int max3110_main_thread(void *_max) |
@@ -424,7 +415,8 @@ static int max3110_main_thread(void *_max) | |||
424 | pr_info(PR_FMT "start main thread\n"); | 415 | pr_info(PR_FMT "start main thread\n"); |
425 | 416 | ||
426 | do { | 417 | do { |
427 | wait_event_interruptible(*wq, max->uart_flags || kthread_should_stop()); | 418 | wait_event_interruptible(*wq, |
419 | max->uart_flags || kthread_should_stop()); | ||
428 | 420 | ||
429 | mutex_lock(&max->thread_mutex); | 421 | mutex_lock(&max->thread_mutex); |
430 | 422 | ||
@@ -452,8 +444,9 @@ static irqreturn_t serial_m3110_irq(int irq, void *dev_id) | |||
452 | 444 | ||
453 | /* max3110's irq is a falling edge, not level triggered, | 445 | /* max3110's irq is a falling edge, not level triggered, |
454 | * so no need to disable the irq */ | 446 | * so no need to disable the irq */ |
447 | |||
455 | if (!test_and_set_bit(BIT_IRQ_PENDING, &max->uart_flags)) | 448 | if (!test_and_set_bit(BIT_IRQ_PENDING, &max->uart_flags)) |
456 | wake_up_process(max->main_thread); | 449 | wake_up(&max->wq); |
457 | 450 | ||
458 | return IRQ_HANDLED; | 451 | return IRQ_HANDLED; |
459 | } | 452 | } |