aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2009-11-05 08:28:29 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-11 18:18:05 -0500
commit530646f4695b396aeeec2ca912dcc3a9c95e0f52 (patch)
tree497560a2cd9c8d1e6022e0553bf2fe9c794bf95a /drivers/mmc
parent0395b48c78ed822f251ab15d0fbc3ce06f41ffb1 (diff)
sdio_uart: refcount the tty objects
The tty can go away underneath us, so we must refcount it. Do the naïve implementation initially. We will worry about startup shortly. Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/card/sdio_uart.c59
1 files changed, 42 insertions, 17 deletions
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index 671fe5efabf3..86ad54341128 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -172,8 +172,13 @@ static void sdio_uart_port_remove(struct sdio_uart_port *port)
172 sdio_claim_host(func); 172 sdio_claim_host(func);
173 port->func = NULL; 173 port->func = NULL;
174 mutex_unlock(&port->func_lock); 174 mutex_unlock(&port->func_lock);
175 if (port->opened) 175 if (port->opened) {
176 tty_hangup(port->port.tty); 176 struct tty_struct *tty = tty_port_tty_get(&port->port);
177 /* tty_hangup is async so is this safe as is ?? */
178 if (tty)
179 tty_hangup(tty);
180 tty_kref_put(tty);
181 }
177 mutex_unlock(&port->open_lock); 182 mutex_unlock(&port->open_lock);
178 sdio_release_irq(func); 183 sdio_release_irq(func);
179 sdio_disable_func(func); 184 sdio_disable_func(func);
@@ -392,7 +397,7 @@ static void sdio_uart_stop_rx(struct sdio_uart_port *port)
392static void sdio_uart_receive_chars(struct sdio_uart_port *port, 397static void sdio_uart_receive_chars(struct sdio_uart_port *port,
393 unsigned int *status) 398 unsigned int *status)
394{ 399{
395 struct tty_struct *tty = port->port.tty; 400 struct tty_struct *tty = tty_port_tty_get(&port->port);
396 unsigned int ch, flag; 401 unsigned int ch, flag;
397 int max_count = 256; 402 int max_count = 256;
398 403
@@ -429,25 +434,30 @@ static void sdio_uart_receive_chars(struct sdio_uart_port *port,
429 } 434 }
430 435
431 if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0) 436 if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0)
432 tty_insert_flip_char(tty, ch, flag); 437 if (tty)
438 tty_insert_flip_char(tty, ch, flag);
433 439
434 /* 440 /*
435 * Overrun is special. Since it's reported immediately, 441 * Overrun is special. Since it's reported immediately,
436 * it doesn't affect the current character. 442 * it doesn't affect the current character.
437 */ 443 */
438 if (*status & ~port->ignore_status_mask & UART_LSR_OE) 444 if (*status & ~port->ignore_status_mask & UART_LSR_OE)
439 tty_insert_flip_char(tty, 0, TTY_OVERRUN); 445 if (tty)
446 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
440 447
441 *status = sdio_in(port, UART_LSR); 448 *status = sdio_in(port, UART_LSR);
442 } while ((*status & UART_LSR_DR) && (max_count-- > 0)); 449 } while ((*status & UART_LSR_DR) && (max_count-- > 0));
443 tty_flip_buffer_push(tty); 450 if (tty) {
451 tty_flip_buffer_push(tty);
452 tty_kref_put(tty);
453 }
444} 454}
445 455
446static void sdio_uart_transmit_chars(struct sdio_uart_port *port) 456static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
447{ 457{
448 struct circ_buf *xmit = &port->xmit; 458 struct circ_buf *xmit = &port->xmit;
449 int count; 459 int count;
450 struct tty_struct *tty = port->port.tty; 460 struct tty_struct *tty;
451 461
452 if (port->x_char) { 462 if (port->x_char) {
453 sdio_out(port, UART_TX, port->x_char); 463 sdio_out(port, UART_TX, port->x_char);
@@ -455,8 +465,12 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
455 port->x_char = 0; 465 port->x_char = 0;
456 return; 466 return;
457 } 467 }
458 if (circ_empty(xmit) || tty->stopped || tty->hw_stopped) { 468
469 tty = tty_port_tty_get(&port->port);
470
471 if (tty == NULL || circ_empty(xmit) || tty->stopped || tty->hw_stopped) {
459 sdio_uart_stop_tx(port); 472 sdio_uart_stop_tx(port);
473 tty_kref_put(tty);
460 return; 474 return;
461 } 475 }
462 476
@@ -474,12 +488,13 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
474 488
475 if (circ_empty(xmit)) 489 if (circ_empty(xmit))
476 sdio_uart_stop_tx(port); 490 sdio_uart_stop_tx(port);
491 tty_kref_put(tty);
477} 492}
478 493
479static void sdio_uart_check_modem_status(struct sdio_uart_port *port) 494static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
480{ 495{
481 int status; 496 int status;
482 struct tty_struct *tty = port->port.tty; 497 struct tty_struct *tty;
483 498
484 status = sdio_in(port, UART_MSR); 499 status = sdio_in(port, UART_MSR);
485 500
@@ -494,7 +509,8 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
494 port->icount.dcd++; 509 port->icount.dcd++;
495 if (status & UART_MSR_DCTS) { 510 if (status & UART_MSR_DCTS) {
496 port->icount.cts++; 511 port->icount.cts++;
497 if (tty->termios->c_cflag & CRTSCTS) { 512 tty = tty_port_tty_get(&port->port);
513 if (tty && (tty->termios->c_cflag & CRTSCTS)) {
498 int cts = (status & UART_MSR_CTS); 514 int cts = (status & UART_MSR_CTS);
499 if (tty->hw_stopped) { 515 if (tty->hw_stopped) {
500 if (cts) { 516 if (cts) {
@@ -509,6 +525,7 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
509 } 525 }
510 } 526 }
511 } 527 }
528 tty_kref_put(tty);
512 } 529 }
513} 530}
514 531
@@ -548,8 +565,10 @@ static void sdio_uart_irq(struct sdio_func *func)
548static int sdio_uart_startup(struct sdio_uart_port *port) 565static int sdio_uart_startup(struct sdio_uart_port *port)
549{ 566{
550 unsigned long page; 567 unsigned long page;
551 int ret; 568 int ret = -ENOMEM;
552 struct tty_struct *tty = port->port.tty; 569 struct tty_struct *tty = tty_port_tty_get(&port->port);
570
571 /* FIXME: What if it is NULL ?? */
553 572
554 /* 573 /*
555 * Set the TTY IO error marker - we will only clear this 574 * Set the TTY IO error marker - we will only clear this
@@ -560,7 +579,7 @@ static int sdio_uart_startup(struct sdio_uart_port *port)
560 /* Initialise and allocate the transmit buffer. */ 579 /* Initialise and allocate the transmit buffer. */
561 page = __get_free_page(GFP_KERNEL); 580 page = __get_free_page(GFP_KERNEL);
562 if (!page) 581 if (!page)
563 return -ENOMEM; 582 goto err0;
564 port->xmit.buf = (unsigned char *)page; 583 port->xmit.buf = (unsigned char *)page;
565 circ_clear(&port->xmit); 584 circ_clear(&port->xmit);
566 585
@@ -614,6 +633,7 @@ static int sdio_uart_startup(struct sdio_uart_port *port)
614 sdio_uart_irq(port->func); 633 sdio_uart_irq(port->func);
615 634
616 sdio_uart_release_func(port); 635 sdio_uart_release_func(port);
636 tty_kref_put(tty);
617 return 0; 637 return 0;
618 638
619err3: 639err3:
@@ -622,12 +642,15 @@ err2:
622 sdio_uart_release_func(port); 642 sdio_uart_release_func(port);
623err1: 643err1:
624 free_page((unsigned long)port->xmit.buf); 644 free_page((unsigned long)port->xmit.buf);
645err0:
646 tty_kref_put(tty);
625 return ret; 647 return ret;
626} 648}
627 649
628static void sdio_uart_shutdown(struct sdio_uart_port *port) 650static void sdio_uart_shutdown(struct sdio_uart_port *port)
629{ 651{
630 int ret; 652 int ret;
653 struct tty_struct *tty;
631 654
632 ret = sdio_uart_claim_func(port); 655 ret = sdio_uart_claim_func(port);
633 if (ret) 656 if (ret)
@@ -637,9 +660,11 @@ static void sdio_uart_shutdown(struct sdio_uart_port *port)
637 660
638 /* TODO: wait here for TX FIFO to drain */ 661 /* TODO: wait here for TX FIFO to drain */
639 662
663 tty = tty_port_tty_get(&port->port);
640 /* Turn off DTR and RTS early. */ 664 /* Turn off DTR and RTS early. */
641 if (port->port.tty->termios->c_cflag & HUPCL) 665 if (tty && (tty->termios->c_cflag & HUPCL))
642 sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); 666 sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
667 tty_kref_put(tty);
643 668
644 /* Disable interrupts from this port */ 669 /* Disable interrupts from this port */
645 sdio_release_irq(port->func); 670 sdio_release_irq(port->func);
@@ -688,11 +713,11 @@ static int sdio_uart_open(struct tty_struct *tty, struct file *filp)
688 713
689 if (!port->opened) { 714 if (!port->opened) {
690 tty->driver_data = port; 715 tty->driver_data = port;
691 port->port.tty = tty; 716 tty_port_tty_set(&port->port, tty);
692 ret = sdio_uart_startup(port); 717 ret = sdio_uart_startup(port);
693 if (ret) { 718 if (ret) {
694 tty->driver_data = NULL; 719 tty->driver_data = NULL;
695 port->port.tty = NULL; 720 tty_port_tty_set(&port->port, NULL);
696 mutex_unlock(&port->open_lock); 721 mutex_unlock(&port->open_lock);
697 sdio_uart_port_put(port); 722 sdio_uart_port_put(port);
698 return ret; 723 return ret;
@@ -727,7 +752,7 @@ static void sdio_uart_close(struct tty_struct *tty, struct file * filp)
727 tty->closing = 1; 752 tty->closing = 1;
728 sdio_uart_shutdown(port); 753 sdio_uart_shutdown(port);
729 tty_ldisc_flush(tty); 754 tty_ldisc_flush(tty);
730 port->port.tty = NULL; 755 tty_port_tty_set(&port->port, NULL);
731 tty->driver_data = NULL; 756 tty->driver_data = NULL;
732 tty->closing = 0; 757 tty->closing = 0;
733 } 758 }