diff options
author | Alexander Shishkin <alexander.shishkin@linux.intel.com> | 2011-08-26 06:25:35 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-08-26 14:01:15 -0400 |
commit | 51808f051ede81865b7af351d6c230a1ac244a22 (patch) | |
tree | 434d609919c476e0679bc0260424639257d91f1c | |
parent | efe3ed9837fd2f9679659673f1d2078f1597bf18 (diff) |
max3110: add sysrq support
This patch moves several occurences of similar code inside receive_chars(),
which now also takes care of checking for break and calling sysrq handling
code.
Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/tty/serial/mrst_max3110.c | 99 | ||||
-rw-r--r-- | drivers/tty/serial/mrst_max3110.h | 1 |
2 files changed, 44 insertions, 56 deletions
diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c index c8f986876229..42aa43934b20 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) |
@@ -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; |
@@ -307,13 +295,7 @@ static void send_circ_buf(struct uart_max3110 *max, | |||
307 | pr_warning(PR_FMT "%s(): get err msg %d\n", | 295 | pr_warning(PR_FMT "%s(): get err msg %d\n", |
308 | __func__, ret); | 296 | __func__, ret); |
309 | 297 | ||
310 | for (i = 0, j = 0; i < len; i++) { | 298 | receive_chars(max, ibuf, len); |
311 | if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE) | ||
312 | valid_str[j++] = ibuf[i] & 0xff; | ||
313 | } | ||
314 | |||
315 | if (j) | ||
316 | receive_chars(max, valid_str, j); | ||
317 | 299 | ||
318 | max->port.icount.tx += len; | 300 | max->port.icount.tx += len; |
319 | left -= len; | 301 | left -= len; |
@@ -353,30 +335,48 @@ static void serial_m3110_start_tx(struct uart_port *port) | |||
353 | wake_up(&max->wq); | 335 | wake_up(&max->wq); |
354 | } | 336 | } |
355 | 337 | ||
356 | 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) | ||
357 | { | 340 | { |
358 | struct uart_port *port = &max->port; | 341 | struct uart_port *port = &max->port; |
359 | struct tty_struct *tty; | 342 | struct tty_struct *tty; |
360 | int usable; | 343 | char buf[M3110_RX_FIFO_DEPTH]; |
344 | int r, w, usable; | ||
361 | 345 | ||
362 | /* If uart is not opened, just return */ | 346 | /* If uart is not opened, just return */ |
363 | if (!port->state) | 347 | if (!port->state) |
364 | return; | 348 | return 0; |
365 | 349 | ||
366 | tty = port->state->port.tty; | 350 | tty = port->state->port.tty; |
367 | if (!tty) | 351 | if (!tty) |
368 | 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 | } | ||
369 | 366 | ||
370 | while (len) { | 367 | if (!w) |
371 | usable = tty_buffer_request_room(tty, len); | 368 | return 0; |
369 | |||
370 | for (r = 0; w; r += usable, w -= usable) { | ||
371 | usable = tty_buffer_request_room(tty, w); | ||
372 | if (usable) { | 372 | if (usable) { |
373 | tty_insert_flip_string(tty, str, usable); | 373 | tty_insert_flip_string(tty, buf + r, usable); |
374 | str += usable; | ||
375 | port->icount.rx += usable; | 374 | port->icount.rx += usable; |
376 | } | 375 | } |
377 | len -= usable; | ||
378 | } | 376 | } |
379 | tty_flip_buffer_push(tty); | 377 | tty_flip_buffer_push(tty); |
378 | |||
379 | return r; | ||
380 | } | 380 | } |
381 | 381 | ||
382 | /* | 382 | /* |
@@ -391,28 +391,15 @@ static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len) | |||
391 | */ | 391 | */ |
392 | static void max3110_con_receive(struct uart_max3110 *max) | 392 | static void max3110_con_receive(struct uart_max3110 *max) |
393 | { | 393 | { |
394 | int loop = 1, num, total = 0; | 394 | int loop = 1, num; |
395 | u8 recv_buf[512], *pbuf; | ||
396 | 395 | ||
397 | pbuf = recv_buf; | ||
398 | do { | 396 | do { |
399 | num = max3110_read_multi(max, pbuf); | 397 | num = max3110_read_multi(max); |
400 | 398 | ||
401 | if (num) { | 399 | if (num) { |
402 | loop = 5; | 400 | loop = 5; |
403 | pbuf += num; | ||
404 | total += num; | ||
405 | |||
406 | if (total >= 504) { | ||
407 | receive_chars(max, recv_buf, total); | ||
408 | pbuf = recv_buf; | ||
409 | total = 0; | ||
410 | } | ||
411 | } | 401 | } |
412 | } while (--loop); | 402 | } while (--loop); |
413 | |||
414 | if (total) | ||
415 | receive_chars(max, recv_buf, total); | ||
416 | } | 403 | } |
417 | 404 | ||
418 | static int max3110_main_thread(void *_max) | 405 | static int max3110_main_thread(void *_max) |
diff --git a/drivers/tty/serial/mrst_max3110.h b/drivers/tty/serial/mrst_max3110.h index c37ea48c825a..35af0739513b 100644 --- a/drivers/tty/serial/mrst_max3110.h +++ b/drivers/tty/serial/mrst_max3110.h | |||
@@ -7,6 +7,7 @@ | |||
7 | /* status bits for all 4 MAX3110 operate modes */ | 7 | /* status bits for all 4 MAX3110 operate modes */ |
8 | #define MAX3110_READ_DATA_AVAILABLE (1 << 15) | 8 | #define MAX3110_READ_DATA_AVAILABLE (1 << 15) |
9 | #define MAX3110_WRITE_BUF_EMPTY (1 << 14) | 9 | #define MAX3110_WRITE_BUF_EMPTY (1 << 14) |
10 | #define MAX3110_BREAK (1 << 10) | ||
10 | 11 | ||
11 | #define WC_TAG (3 << 14) | 12 | #define WC_TAG (3 << 14) |
12 | #define RC_TAG (1 << 14) | 13 | #define RC_TAG (1 << 14) |