diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/card/sdio_uart.c | 93 |
1 files changed, 30 insertions, 63 deletions
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index f53755533e7e..3fab78ba8952 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/gfp.h> | 37 | #include <linux/gfp.h> |
38 | #include <linux/tty.h> | 38 | #include <linux/tty.h> |
39 | #include <linux/tty_flip.h> | 39 | #include <linux/tty_flip.h> |
40 | #include <linux/kfifo.h> | ||
40 | 41 | ||
41 | #include <linux/mmc/core.h> | 42 | #include <linux/mmc/core.h> |
42 | #include <linux/mmc/card.h> | 43 | #include <linux/mmc/card.h> |
@@ -47,19 +48,9 @@ | |||
47 | #define UART_NR 8 /* Number of UARTs this driver can handle */ | 48 | #define UART_NR 8 /* Number of UARTs this driver can handle */ |
48 | 49 | ||
49 | 50 | ||
50 | #define UART_XMIT_SIZE PAGE_SIZE | 51 | #define FIFO_SIZE PAGE_SIZE |
51 | #define WAKEUP_CHARS 256 | 52 | #define WAKEUP_CHARS 256 |
52 | 53 | ||
53 | #define circ_empty(circ) ((circ)->head == (circ)->tail) | ||
54 | #define circ_clear(circ) ((circ)->head = (circ)->tail = 0) | ||
55 | |||
56 | #define circ_chars_pending(circ) \ | ||
57 | (CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE)) | ||
58 | |||
59 | #define circ_chars_free(circ) \ | ||
60 | (CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE)) | ||
61 | |||
62 | |||
63 | struct uart_icount { | 54 | struct uart_icount { |
64 | __u32 cts; | 55 | __u32 cts; |
65 | __u32 dsr; | 56 | __u32 dsr; |
@@ -82,7 +73,7 @@ struct sdio_uart_port { | |||
82 | struct mutex func_lock; | 73 | struct mutex func_lock; |
83 | struct task_struct *in_sdio_uart_irq; | 74 | struct task_struct *in_sdio_uart_irq; |
84 | unsigned int regs_offset; | 75 | unsigned int regs_offset; |
85 | struct circ_buf xmit; | 76 | struct kfifo xmit_fifo; |
86 | spinlock_t write_lock; | 77 | spinlock_t write_lock; |
87 | struct uart_icount icount; | 78 | struct uart_icount icount; |
88 | unsigned int uartclk; | 79 | unsigned int uartclk; |
@@ -105,6 +96,8 @@ static int sdio_uart_add_port(struct sdio_uart_port *port) | |||
105 | kref_init(&port->kref); | 96 | kref_init(&port->kref); |
106 | mutex_init(&port->func_lock); | 97 | mutex_init(&port->func_lock); |
107 | spin_lock_init(&port->write_lock); | 98 | spin_lock_init(&port->write_lock); |
99 | if (kfifo_alloc(&port->xmit_fifo, FIFO_SIZE, GFP_KERNEL)) | ||
100 | return -ENOMEM; | ||
108 | 101 | ||
109 | spin_lock(&sdio_uart_table_lock); | 102 | spin_lock(&sdio_uart_table_lock); |
110 | for (index = 0; index < UART_NR; index++) { | 103 | for (index = 0; index < UART_NR; index++) { |
@@ -140,6 +133,7 @@ static void sdio_uart_port_destroy(struct kref *kref) | |||
140 | { | 133 | { |
141 | struct sdio_uart_port *port = | 134 | struct sdio_uart_port *port = |
142 | container_of(kref, struct sdio_uart_port, kref); | 135 | container_of(kref, struct sdio_uart_port, kref); |
136 | kfifo_free(&port->xmit_fifo); | ||
143 | kfree(port); | 137 | kfree(port); |
144 | } | 138 | } |
145 | 139 | ||
@@ -456,9 +450,11 @@ static void sdio_uart_receive_chars(struct sdio_uart_port *port, | |||
456 | 450 | ||
457 | static void sdio_uart_transmit_chars(struct sdio_uart_port *port) | 451 | static void sdio_uart_transmit_chars(struct sdio_uart_port *port) |
458 | { | 452 | { |
459 | struct circ_buf *xmit = &port->xmit; | 453 | struct kfifo *xmit = &port->xmit_fifo; |
460 | int count; | 454 | int count; |
461 | struct tty_struct *tty; | 455 | struct tty_struct *tty; |
456 | u8 iobuf[16]; | ||
457 | int len; | ||
462 | 458 | ||
463 | if (port->x_char) { | 459 | if (port->x_char) { |
464 | sdio_out(port, UART_TX, port->x_char); | 460 | sdio_out(port, UART_TX, port->x_char); |
@@ -469,27 +465,25 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port) | |||
469 | 465 | ||
470 | tty = tty_port_tty_get(&port->port); | 466 | tty = tty_port_tty_get(&port->port); |
471 | 467 | ||
472 | if (tty == NULL || circ_empty(xmit) || | 468 | if (tty == NULL || !kfifo_len(xmit) || |
473 | tty->stopped || tty->hw_stopped) { | 469 | tty->stopped || tty->hw_stopped) { |
474 | sdio_uart_stop_tx(port); | 470 | sdio_uart_stop_tx(port); |
475 | tty_kref_put(tty); | 471 | tty_kref_put(tty); |
476 | return; | 472 | return; |
477 | } | 473 | } |
478 | 474 | ||
479 | count = 16; | 475 | len = kfifo_out_locked(xmit, iobuf, 16, &port->write_lock); |
480 | do { | 476 | for (count = 0; count < len; count++) { |
481 | sdio_out(port, UART_TX, xmit->buf[xmit->tail]); | 477 | sdio_out(port, UART_TX, iobuf[count]); |
482 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
483 | port->icount.tx++; | 478 | port->icount.tx++; |
484 | if (circ_empty(xmit)) | 479 | } |
485 | break; | ||
486 | } while (--count > 0); | ||
487 | 480 | ||
488 | if (circ_chars_pending(xmit) < WAKEUP_CHARS) | 481 | len = kfifo_len(xmit); |
482 | if (len < WAKEUP_CHARS) { | ||
489 | tty_wakeup(tty); | 483 | tty_wakeup(tty); |
490 | 484 | if (len == 0) | |
491 | if (circ_empty(xmit)) | 485 | sdio_uart_stop_tx(port); |
492 | sdio_uart_stop_tx(port); | 486 | } |
493 | tty_kref_put(tty); | 487 | tty_kref_put(tty); |
494 | } | 488 | } |
495 | 489 | ||
@@ -632,7 +626,6 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) | |||
632 | { | 626 | { |
633 | struct sdio_uart_port *port = | 627 | struct sdio_uart_port *port = |
634 | container_of(tport, struct sdio_uart_port, port); | 628 | container_of(tport, struct sdio_uart_port, port); |
635 | unsigned long page; | ||
636 | int ret; | 629 | int ret; |
637 | 630 | ||
638 | /* | 631 | /* |
@@ -641,22 +634,17 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) | |||
641 | */ | 634 | */ |
642 | set_bit(TTY_IO_ERROR, &tty->flags); | 635 | set_bit(TTY_IO_ERROR, &tty->flags); |
643 | 636 | ||
644 | /* Initialise and allocate the transmit buffer. */ | 637 | kfifo_reset(&port->xmit_fifo); |
645 | page = __get_free_page(GFP_KERNEL); | ||
646 | if (!page) | ||
647 | return -ENOMEM; | ||
648 | port->xmit.buf = (unsigned char *)page; | ||
649 | circ_clear(&port->xmit); | ||
650 | 638 | ||
651 | ret = sdio_uart_claim_func(port); | 639 | ret = sdio_uart_claim_func(port); |
652 | if (ret) | 640 | if (ret) |
653 | goto err1; | 641 | return ret; |
654 | ret = sdio_enable_func(port->func); | 642 | ret = sdio_enable_func(port->func); |
655 | if (ret) | 643 | if (ret) |
656 | goto err2; | 644 | goto err1; |
657 | ret = sdio_claim_irq(port->func, sdio_uart_irq); | 645 | ret = sdio_claim_irq(port->func, sdio_uart_irq); |
658 | if (ret) | 646 | if (ret) |
659 | goto err3; | 647 | goto err2; |
660 | 648 | ||
661 | /* | 649 | /* |
662 | * Clear the FIFO buffers and disable them. | 650 | * Clear the FIFO buffers and disable them. |
@@ -700,12 +688,10 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) | |||
700 | sdio_uart_release_func(port); | 688 | sdio_uart_release_func(port); |
701 | return 0; | 689 | return 0; |
702 | 690 | ||
703 | err3: | ||
704 | sdio_disable_func(port->func); | ||
705 | err2: | 691 | err2: |
706 | sdio_uart_release_func(port); | 692 | sdio_disable_func(port->func); |
707 | err1: | 693 | err1: |
708 | free_page((unsigned long)port->xmit.buf); | 694 | sdio_uart_release_func(port); |
709 | return ret; | 695 | return ret; |
710 | } | 696 | } |
711 | 697 | ||
@@ -727,7 +713,7 @@ static void sdio_uart_shutdown(struct tty_port *tport) | |||
727 | 713 | ||
728 | ret = sdio_uart_claim_func(port); | 714 | ret = sdio_uart_claim_func(port); |
729 | if (ret) | 715 | if (ret) |
730 | goto skip; | 716 | return; |
731 | 717 | ||
732 | sdio_uart_stop_rx(port); | 718 | sdio_uart_stop_rx(port); |
733 | 719 | ||
@@ -749,10 +735,6 @@ static void sdio_uart_shutdown(struct tty_port *tport) | |||
749 | sdio_disable_func(port->func); | 735 | sdio_disable_func(port->func); |
750 | 736 | ||
751 | sdio_uart_release_func(port); | 737 | sdio_uart_release_func(port); |
752 | |||
753 | skip: | ||
754 | /* Free the transmit buffer page. */ | ||
755 | free_page((unsigned long)port->xmit.buf); | ||
756 | } | 738 | } |
757 | 739 | ||
758 | /** | 740 | /** |
@@ -822,27 +804,12 @@ static int sdio_uart_write(struct tty_struct *tty, const unsigned char *buf, | |||
822 | int count) | 804 | int count) |
823 | { | 805 | { |
824 | struct sdio_uart_port *port = tty->driver_data; | 806 | struct sdio_uart_port *port = tty->driver_data; |
825 | struct circ_buf *circ = &port->xmit; | 807 | int ret; |
826 | int c, ret = 0; | ||
827 | 808 | ||
828 | if (!port->func) | 809 | if (!port->func) |
829 | return -ENODEV; | 810 | return -ENODEV; |
830 | 811 | ||
831 | spin_lock(&port->write_lock); | 812 | ret = kfifo_in_locked(&port->xmit_fifo, buf, count, &port->write_lock); |
832 | while (1) { | ||
833 | c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); | ||
834 | if (count < c) | ||
835 | c = count; | ||
836 | if (c <= 0) | ||
837 | break; | ||
838 | memcpy(circ->buf + circ->head, buf, c); | ||
839 | circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1); | ||
840 | buf += c; | ||
841 | count -= c; | ||
842 | ret += c; | ||
843 | } | ||
844 | spin_unlock(&port->write_lock); | ||
845 | |||
846 | if (!(port->ier & UART_IER_THRI)) { | 813 | if (!(port->ier & UART_IER_THRI)) { |
847 | int err = sdio_uart_claim_func(port); | 814 | int err = sdio_uart_claim_func(port); |
848 | if (!err) { | 815 | if (!err) { |
@@ -859,13 +826,13 @@ static int sdio_uart_write(struct tty_struct *tty, const unsigned char *buf, | |||
859 | static int sdio_uart_write_room(struct tty_struct *tty) | 826 | static int sdio_uart_write_room(struct tty_struct *tty) |
860 | { | 827 | { |
861 | struct sdio_uart_port *port = tty->driver_data; | 828 | struct sdio_uart_port *port = tty->driver_data; |
862 | return port ? circ_chars_free(&port->xmit) : 0; | 829 | return FIFO_SIZE - kfifo_len(&port->xmit_fifo); |
863 | } | 830 | } |
864 | 831 | ||
865 | static int sdio_uart_chars_in_buffer(struct tty_struct *tty) | 832 | static int sdio_uart_chars_in_buffer(struct tty_struct *tty) |
866 | { | 833 | { |
867 | struct sdio_uart_port *port = tty->driver_data; | 834 | struct sdio_uart_port *port = tty->driver_data; |
868 | return port ? circ_chars_pending(&port->xmit) : 0; | 835 | return kfifo_len(&port->xmit_fifo); |
869 | } | 836 | } |
870 | 837 | ||
871 | static void sdio_uart_send_xchar(struct tty_struct *tty, char ch) | 838 | static void sdio_uart_send_xchar(struct tty_struct *tty, char ch) |