aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/pch_uart.c
diff options
context:
space:
mode:
authorTomoya MORINAGA <tomoya-linux@dsn.okisemi.com>2011-02-22 20:03:12 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-02-22 20:22:02 -0500
commitda3564ee027e788a5ff8e520fb2d2b00a78b2464 (patch)
tree31cb96fb375b2c4ed85e48744392903b0828275e /drivers/tty/serial/pch_uart.c
parent4c37705877e74c02c968735c2eee0f84914cf557 (diff)
pch_uart: add multi-scatter processing
Currently, this driver can handle only single scatterlist. Thus, it can't send data beyond FIFO size. This patch enables this driver can handle multiple scatter list. Signed-off-by: Tomoya MORINAGA <tomoya-linux@dsn.okisemi.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/tty/serial/pch_uart.c')
-rw-r--r--drivers/tty/serial/pch_uart.c117
1 files changed, 89 insertions, 28 deletions
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 3b2fb93e1fa..c1386eb255d 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -226,7 +226,8 @@ struct eg20t_port {
226 struct pch_dma_slave param_rx; 226 struct pch_dma_slave param_rx;
227 struct dma_chan *chan_tx; 227 struct dma_chan *chan_tx;
228 struct dma_chan *chan_rx; 228 struct dma_chan *chan_rx;
229 struct scatterlist sg_tx; 229 struct scatterlist *sg_tx_p;
230 int nent;
230 struct scatterlist sg_rx; 231 struct scatterlist sg_rx;
231 int tx_dma_use; 232 int tx_dma_use;
232 void *rx_buf_virt; 233 void *rx_buf_virt;
@@ -595,16 +596,20 @@ static void pch_dma_rx_complete(void *arg)
595 struct eg20t_port *priv = arg; 596 struct eg20t_port *priv = arg;
596 struct uart_port *port = &priv->port; 597 struct uart_port *port = &priv->port;
597 struct tty_struct *tty = tty_port_tty_get(&port->state->port); 598 struct tty_struct *tty = tty_port_tty_get(&port->state->port);
599 int count;
598 600
599 if (!tty) { 601 if (!tty) {
600 pr_debug("%s:tty is busy now", __func__); 602 pr_debug("%s:tty is busy now", __func__);
601 return; 603 return;
602 } 604 }
603 605
604 if (dma_push_rx(priv, priv->trigger_level)) 606 dma_sync_sg_for_cpu(port->dev, &priv->sg_rx, 1, DMA_FROM_DEVICE);
607 count = dma_push_rx(priv, priv->trigger_level);
608 if (count)
605 tty_flip_buffer_push(tty); 609 tty_flip_buffer_push(tty);
606
607 tty_kref_put(tty); 610 tty_kref_put(tty);
611 async_tx_ack(priv->desc_rx);
612 pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT);
608} 613}
609 614
610static void pch_dma_tx_complete(void *arg) 615static void pch_dma_tx_complete(void *arg)
@@ -612,13 +617,21 @@ static void pch_dma_tx_complete(void *arg)
612 struct eg20t_port *priv = arg; 617 struct eg20t_port *priv = arg;
613 struct uart_port *port = &priv->port; 618 struct uart_port *port = &priv->port;
614 struct circ_buf *xmit = &port->state->xmit; 619 struct circ_buf *xmit = &port->state->xmit;
620 struct scatterlist *sg = priv->sg_tx_p;
621 int i;
615 622
616 xmit->tail += sg_dma_len(&priv->sg_tx); 623 for (i = 0; i < priv->nent; i++, sg++) {
624 xmit->tail += sg_dma_len(sg);
625 port->icount.tx += sg_dma_len(sg);
626 }
617 xmit->tail &= UART_XMIT_SIZE - 1; 627 xmit->tail &= UART_XMIT_SIZE - 1;
618 port->icount.tx += sg_dma_len(&priv->sg_tx);
619
620 async_tx_ack(priv->desc_tx); 628 async_tx_ack(priv->desc_tx);
629 dma_unmap_sg(port->dev, sg, priv->nent, DMA_TO_DEVICE);
621 priv->tx_dma_use = 0; 630 priv->tx_dma_use = 0;
631 priv->nent = 0;
632 kfree(priv->sg_tx_p);
633 if (uart_circ_chars_pending(xmit))
634 pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_TX_INT);
622} 635}
623 636
624static int pop_tx(struct eg20t_port *priv, unsigned char *buf, int size) 637static int pop_tx(struct eg20t_port *priv, unsigned char *buf, int size)
@@ -682,7 +695,7 @@ static int dma_handle_rx(struct eg20t_port *priv)
682 695
683 sg_init_table(&priv->sg_rx, 1); /* Initialize SG table */ 696 sg_init_table(&priv->sg_rx, 1); /* Initialize SG table */
684 697
685 sg_dma_len(sg) = priv->fifo_size; 698 sg_dma_len(sg) = priv->trigger_level;
686 699
687 sg_set_page(&priv->sg_rx, virt_to_page(priv->rx_buf_virt), 700 sg_set_page(&priv->sg_rx, virt_to_page(priv->rx_buf_virt),
688 sg_dma_len(sg), (unsigned long)priv->rx_buf_virt & 701 sg_dma_len(sg), (unsigned long)priv->rx_buf_virt &
@@ -692,7 +705,8 @@ static int dma_handle_rx(struct eg20t_port *priv)
692 705
693 desc = priv->chan_rx->device->device_prep_slave_sg(priv->chan_rx, 706 desc = priv->chan_rx->device->device_prep_slave_sg(priv->chan_rx,
694 sg, 1, DMA_FROM_DEVICE, 707 sg, 1, DMA_FROM_DEVICE,
695 DMA_PREP_INTERRUPT); 708 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
709
696 if (!desc) 710 if (!desc)
697 return 0; 711 return 0;
698 712
@@ -731,6 +745,9 @@ static unsigned int handle_tx(struct eg20t_port *priv)
731 fifo_size--; 745 fifo_size--;
732 } 746 }
733 size = min(xmit->head - xmit->tail, fifo_size); 747 size = min(xmit->head - xmit->tail, fifo_size);
748 if (size < 0)
749 size = fifo_size;
750
734 tx_size = pop_tx(priv, xmit->buf, size); 751 tx_size = pop_tx(priv, xmit->buf, size);
735 if (tx_size > 0) { 752 if (tx_size > 0) {
736 ret = pch_uart_hal_write(priv, xmit->buf, tx_size); 753 ret = pch_uart_hal_write(priv, xmit->buf, tx_size);
@@ -740,8 +757,10 @@ static unsigned int handle_tx(struct eg20t_port *priv)
740 757
741 priv->tx_empty = tx_empty; 758 priv->tx_empty = tx_empty;
742 759
743 if (tx_empty) 760 if (tx_empty) {
744 pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT); 761 pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
762 uart_write_wakeup(port);
763 }
745 764
746 return PCH_UART_HANDLED_TX_INT; 765 return PCH_UART_HANDLED_TX_INT;
747} 766}
@@ -750,11 +769,16 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
750{ 769{
751 struct uart_port *port = &priv->port; 770 struct uart_port *port = &priv->port;
752 struct circ_buf *xmit = &port->state->xmit; 771 struct circ_buf *xmit = &port->state->xmit;
753 struct scatterlist *sg = &priv->sg_tx; 772 struct scatterlist *sg;
754 int nent; 773 int nent;
755 int fifo_size; 774 int fifo_size;
756 int tx_empty; 775 int tx_empty;
757 struct dma_async_tx_descriptor *desc; 776 struct dma_async_tx_descriptor *desc;
777 int num;
778 int i;
779 int bytes;
780 int size;
781 int rem;
758 782
759 if (!priv->start_tx) { 783 if (!priv->start_tx) {
760 pr_info("%s:Tx isn't started. (%lu)\n", __func__, jiffies); 784 pr_info("%s:Tx isn't started. (%lu)\n", __func__, jiffies);
@@ -772,37 +796,68 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
772 fifo_size--; 796 fifo_size--;
773 } 797 }
774 798
775 pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT); 799 bytes = min((int)CIRC_CNT(xmit->head, xmit->tail,
800 UART_XMIT_SIZE), CIRC_CNT_TO_END(xmit->head,
801 xmit->tail, UART_XMIT_SIZE));
802 if (!bytes) {
803 pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
804 uart_write_wakeup(port);
805 return 0;
806 }
807
808 if (bytes > fifo_size) {
809 num = bytes / fifo_size + 1;
810 size = fifo_size;
811 rem = bytes % fifo_size;
812 } else {
813 num = 1;
814 size = bytes;
815 rem = bytes;
816 }
776 817
777 priv->tx_dma_use = 1; 818 priv->tx_dma_use = 1;
778 819
779 sg_init_table(&priv->sg_tx, 1); /* Initialize SG table */ 820 priv->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC);
821
822 sg_init_table(priv->sg_tx_p, num); /* Initialize SG table */
823 sg = priv->sg_tx_p;
780 824
781 sg_set_page(&priv->sg_tx, virt_to_page(xmit->buf), 825 for (i = 0; i < num; i++, sg++) {
782 UART_XMIT_SIZE, (int)xmit->buf & ~PAGE_MASK); 826 if (i == (num - 1))
827 sg_set_page(sg, virt_to_page(xmit->buf),
828 rem, fifo_size * i);
829 else
830 sg_set_page(sg, virt_to_page(xmit->buf),
831 size, fifo_size * i);
832 }
783 833
784 nent = dma_map_sg(port->dev, &priv->sg_tx, 1, DMA_TO_DEVICE); 834 sg = priv->sg_tx_p;
835 nent = dma_map_sg(port->dev, sg, num, DMA_TO_DEVICE);
785 if (!nent) { 836 if (!nent) {
786 pr_err("%s:dma_map_sg Failed\n", __func__); 837 pr_err("%s:dma_map_sg Failed\n", __func__);
787 return 0; 838 return 0;
788 } 839 }
789 840 priv->nent = nent;
790 sg->offset = xmit->tail & (UART_XMIT_SIZE - 1); 841
791 sg_dma_address(sg) = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) + 842 for (i = 0; i < nent; i++, sg++) {
792 sg->offset; 843 sg->offset = (xmit->tail & (UART_XMIT_SIZE - 1)) +
793 sg_dma_len(sg) = min((int)CIRC_CNT(xmit->head, xmit->tail, 844 fifo_size * i;
794 UART_XMIT_SIZE), CIRC_CNT_TO_END(xmit->head, 845 sg_dma_address(sg) = (sg_dma_address(sg) &
795 xmit->tail, UART_XMIT_SIZE)); 846 ~(UART_XMIT_SIZE - 1)) + sg->offset;
847 if (i == (nent - 1))
848 sg_dma_len(sg) = rem;
849 else
850 sg_dma_len(sg) = size;
851 }
796 852
797 desc = priv->chan_tx->device->device_prep_slave_sg(priv->chan_tx, 853 desc = priv->chan_tx->device->device_prep_slave_sg(priv->chan_tx,
798 sg, nent, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 854 priv->sg_tx_p, nent, DMA_TO_DEVICE,
855 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
799 if (!desc) { 856 if (!desc) {
800 pr_err("%s:device_prep_slave_sg Failed\n", __func__); 857 pr_err("%s:device_prep_slave_sg Failed\n", __func__);
801 return 0; 858 return 0;
802 } 859 }
803 860 dma_sync_sg_for_device(port->dev, priv->sg_tx_p, nent, DMA_TO_DEVICE);
804 dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE);
805
806 priv->desc_tx = desc; 861 priv->desc_tx = desc;
807 desc->callback = pch_dma_tx_complete; 862 desc->callback = pch_dma_tx_complete;
808 desc->callback_param = priv; 863 desc->callback_param = priv;
@@ -857,10 +912,16 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
857 } 912 }
858 break; 913 break;
859 case PCH_UART_IID_RDR: /* Received Data Ready */ 914 case PCH_UART_IID_RDR: /* Received Data Ready */
860 if (priv->use_dma) 915 if (priv->use_dma) {
916 pch_uart_hal_disable_interrupt(priv,
917 PCH_UART_HAL_RX_INT);
861 ret = dma_handle_rx(priv); 918 ret = dma_handle_rx(priv);
862 else 919 if (!ret)
920 pch_uart_hal_enable_interrupt(priv,
921 PCH_UART_HAL_RX_INT);
922 } else {
863 ret = handle_rx(priv); 923 ret = handle_rx(priv);
924 }
864 break; 925 break;
865 case PCH_UART_IID_RDR_TO: /* Received Data Ready 926 case PCH_UART_IID_RDR_TO: /* Received Data Ready
866 (FIFO Timeout) */ 927 (FIFO Timeout) */