aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/pmac_zilog.c
diff options
context:
space:
mode:
authorJiri Slaby <jslaby@suse.cz>2013-01-03 09:53:06 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-01-16 01:30:15 -0500
commit2e124b4a390ca85325fae75764bef92f0547fa25 (patch)
tree5519fbcdbe954e79b271ea6d31ac5a4dc754c4f5 /drivers/tty/serial/pmac_zilog.c
parentd6c53c0e9bd0a83f9f9ddbc9fd80141a54d83896 (diff)
TTY: switch tty_flip_buffer_push
Now, we start converting tty buffer functions to actually use tty_port. This will allow us to get rid of the need of tty in many call sites. Only tty_port will needed and hence no more tty_port_tty_get in those paths. Now, the one where most of tty_port_tty_get gets removed: tty_flip_buffer_push. IOW we also closed all the races in drivers not using tty_port_tty_get at all yet. Also we move tty_flip_buffer_push declaration from include/linux/tty.h to include/linux/tty_flip.h to all others while we are changing it anyway. Signed-off-by: Jiri Slaby <jslaby@suse.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/pmac_zilog.c')
-rw-r--r--drivers/tty/serial/pmac_zilog.c30
1 files changed, 14 insertions, 16 deletions
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c
index 73a3f295e7c4..b1785f58b6e3 100644
--- a/drivers/tty/serial/pmac_zilog.c
+++ b/drivers/tty/serial/pmac_zilog.c
@@ -227,21 +227,19 @@ static void pmz_interrupt_control(struct uart_pmac_port *uap, int enable)
227 write_zsreg(uap, R1, uap->curregs[1]); 227 write_zsreg(uap, R1, uap->curregs[1]);
228} 228}
229 229
230static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap) 230static bool pmz_receive_chars(struct uart_pmac_port *uap)
231{ 231{
232 struct tty_port *port; 232 struct tty_port *port;
233 struct tty_struct *tty = NULL;
234 unsigned char ch, r1, drop, error, flag; 233 unsigned char ch, r1, drop, error, flag;
235 int loops = 0; 234 int loops = 0;
236 235
237 /* Sanity check, make sure the old bug is no longer happening */ 236 /* Sanity check, make sure the old bug is no longer happening */
238 if (uap->port.state == NULL || uap->port.state->port.tty == NULL) { 237 if (uap->port.state == NULL) {
239 WARN_ON(1); 238 WARN_ON(1);
240 (void)read_zsdata(uap); 239 (void)read_zsdata(uap);
241 return NULL; 240 return false;
242 } 241 }
243 port = &uap->port.state->port; 242 port = &uap->port.state->port;
244 tty = port->tty; /* TOCTOU above */
245 243
246 while (1) { 244 while (1) {
247 error = 0; 245 error = 0;
@@ -330,11 +328,11 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap)
330 break; 328 break;
331 } 329 }
332 330
333 return tty; 331 return true;
334 flood: 332 flood:
335 pmz_interrupt_control(uap, 0); 333 pmz_interrupt_control(uap, 0);
336 pmz_error("pmz: rx irq flood !\n"); 334 pmz_error("pmz: rx irq flood !\n");
337 return tty; 335 return true;
338} 336}
339 337
340static void pmz_status_handle(struct uart_pmac_port *uap) 338static void pmz_status_handle(struct uart_pmac_port *uap)
@@ -455,7 +453,7 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id)
455 struct uart_pmac_port *uap_a; 453 struct uart_pmac_port *uap_a;
456 struct uart_pmac_port *uap_b; 454 struct uart_pmac_port *uap_b;
457 int rc = IRQ_NONE; 455 int rc = IRQ_NONE;
458 struct tty_struct *tty; 456 bool push;
459 u8 r3; 457 u8 r3;
460 458
461 uap_a = pmz_get_port_A(uap); 459 uap_a = pmz_get_port_A(uap);
@@ -468,7 +466,7 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id)
468 pmz_debug("irq, r3: %x\n", r3); 466 pmz_debug("irq, r3: %x\n", r3);
469#endif 467#endif
470 /* Channel A */ 468 /* Channel A */
471 tty = NULL; 469 push = false;
472 if (r3 & (CHAEXT | CHATxIP | CHARxIP)) { 470 if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
473 if (!ZS_IS_OPEN(uap_a)) { 471 if (!ZS_IS_OPEN(uap_a)) {
474 pmz_debug("ChanA interrupt while not open !\n"); 472 pmz_debug("ChanA interrupt while not open !\n");
@@ -479,21 +477,21 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id)
479 if (r3 & CHAEXT) 477 if (r3 & CHAEXT)
480 pmz_status_handle(uap_a); 478 pmz_status_handle(uap_a);
481 if (r3 & CHARxIP) 479 if (r3 & CHARxIP)
482 tty = pmz_receive_chars(uap_a); 480 push = pmz_receive_chars(uap_a);
483 if (r3 & CHATxIP) 481 if (r3 & CHATxIP)
484 pmz_transmit_chars(uap_a); 482 pmz_transmit_chars(uap_a);
485 rc = IRQ_HANDLED; 483 rc = IRQ_HANDLED;
486 } 484 }
487 skip_a: 485 skip_a:
488 spin_unlock(&uap_a->port.lock); 486 spin_unlock(&uap_a->port.lock);
489 if (tty != NULL) 487 if (push)
490 tty_flip_buffer_push(tty); 488 tty_flip_buffer_push(&uap->port.state->port);
491 489
492 if (!uap_b) 490 if (!uap_b)
493 goto out; 491 goto out;
494 492
495 spin_lock(&uap_b->port.lock); 493 spin_lock(&uap_b->port.lock);
496 tty = NULL; 494 push = false;
497 if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) { 495 if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
498 if (!ZS_IS_OPEN(uap_b)) { 496 if (!ZS_IS_OPEN(uap_b)) {
499 pmz_debug("ChanB interrupt while not open !\n"); 497 pmz_debug("ChanB interrupt while not open !\n");
@@ -504,15 +502,15 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id)
504 if (r3 & CHBEXT) 502 if (r3 & CHBEXT)
505 pmz_status_handle(uap_b); 503 pmz_status_handle(uap_b);
506 if (r3 & CHBRxIP) 504 if (r3 & CHBRxIP)
507 tty = pmz_receive_chars(uap_b); 505 push = pmz_receive_chars(uap_b);
508 if (r3 & CHBTxIP) 506 if (r3 & CHBTxIP)
509 pmz_transmit_chars(uap_b); 507 pmz_transmit_chars(uap_b);
510 rc = IRQ_HANDLED; 508 rc = IRQ_HANDLED;
511 } 509 }
512 skip_b: 510 skip_b:
513 spin_unlock(&uap_b->port.lock); 511 spin_unlock(&uap_b->port.lock);
514 if (tty != NULL) 512 if (push)
515 tty_flip_buffer_push(tty); 513 tty_flip_buffer_push(&uap->port.state->port);
516 514
517 out: 515 out:
518 return rc; 516 return rc;