aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/n_hdlc.c132
-rw-r--r--drivers/tty/serial/samsung.c6
2 files changed, 73 insertions, 65 deletions
diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c
index 1bacbc3b19a0..e94aea8c0d05 100644
--- a/drivers/tty/n_hdlc.c
+++ b/drivers/tty/n_hdlc.c
@@ -114,7 +114,7 @@
114#define DEFAULT_TX_BUF_COUNT 3 114#define DEFAULT_TX_BUF_COUNT 3
115 115
116struct n_hdlc_buf { 116struct n_hdlc_buf {
117 struct n_hdlc_buf *link; 117 struct list_head list_item;
118 int count; 118 int count;
119 char buf[1]; 119 char buf[1];
120}; 120};
@@ -122,8 +122,7 @@ struct n_hdlc_buf {
122#define N_HDLC_BUF_SIZE (sizeof(struct n_hdlc_buf) + maxframe) 122#define N_HDLC_BUF_SIZE (sizeof(struct n_hdlc_buf) + maxframe)
123 123
124struct n_hdlc_buf_list { 124struct n_hdlc_buf_list {
125 struct n_hdlc_buf *head; 125 struct list_head list;
126 struct n_hdlc_buf *tail;
127 int count; 126 int count;
128 spinlock_t spinlock; 127 spinlock_t spinlock;
129}; 128};
@@ -136,7 +135,6 @@ struct n_hdlc_buf_list {
136 * @backup_tty - TTY to use if tty gets closed 135 * @backup_tty - TTY to use if tty gets closed
137 * @tbusy - reentrancy flag for tx wakeup code 136 * @tbusy - reentrancy flag for tx wakeup code
138 * @woke_up - FIXME: describe this field 137 * @woke_up - FIXME: describe this field
139 * @tbuf - currently transmitting tx buffer
140 * @tx_buf_list - list of pending transmit frame buffers 138 * @tx_buf_list - list of pending transmit frame buffers
141 * @rx_buf_list - list of received frame buffers 139 * @rx_buf_list - list of received frame buffers
142 * @tx_free_buf_list - list unused transmit frame buffers 140 * @tx_free_buf_list - list unused transmit frame buffers
@@ -149,7 +147,6 @@ struct n_hdlc {
149 struct tty_struct *backup_tty; 147 struct tty_struct *backup_tty;
150 int tbusy; 148 int tbusy;
151 int woke_up; 149 int woke_up;
152 struct n_hdlc_buf *tbuf;
153 struct n_hdlc_buf_list tx_buf_list; 150 struct n_hdlc_buf_list tx_buf_list;
154 struct n_hdlc_buf_list rx_buf_list; 151 struct n_hdlc_buf_list rx_buf_list;
155 struct n_hdlc_buf_list tx_free_buf_list; 152 struct n_hdlc_buf_list tx_free_buf_list;
@@ -159,6 +156,8 @@ struct n_hdlc {
159/* 156/*
160 * HDLC buffer list manipulation functions 157 * HDLC buffer list manipulation functions
161 */ 158 */
159static void n_hdlc_buf_return(struct n_hdlc_buf_list *buf_list,
160 struct n_hdlc_buf *buf);
162static void n_hdlc_buf_put(struct n_hdlc_buf_list *list, 161static void n_hdlc_buf_put(struct n_hdlc_buf_list *list,
163 struct n_hdlc_buf *buf); 162 struct n_hdlc_buf *buf);
164static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *list); 163static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *list);
@@ -208,16 +207,9 @@ static void flush_tx_queue(struct tty_struct *tty)
208{ 207{
209 struct n_hdlc *n_hdlc = tty2n_hdlc(tty); 208 struct n_hdlc *n_hdlc = tty2n_hdlc(tty);
210 struct n_hdlc_buf *buf; 209 struct n_hdlc_buf *buf;
211 unsigned long flags;
212 210
213 while ((buf = n_hdlc_buf_get(&n_hdlc->tx_buf_list))) 211 while ((buf = n_hdlc_buf_get(&n_hdlc->tx_buf_list)))
214 n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, buf); 212 n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, buf);
215 spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags);
216 if (n_hdlc->tbuf) {
217 n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, n_hdlc->tbuf);
218 n_hdlc->tbuf = NULL;
219 }
220 spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);
221} 213}
222 214
223static struct tty_ldisc_ops n_hdlc_ldisc = { 215static struct tty_ldisc_ops n_hdlc_ldisc = {
@@ -283,7 +275,6 @@ static void n_hdlc_release(struct n_hdlc *n_hdlc)
283 } else 275 } else
284 break; 276 break;
285 } 277 }
286 kfree(n_hdlc->tbuf);
287 kfree(n_hdlc); 278 kfree(n_hdlc);
288 279
289} /* end of n_hdlc_release() */ 280} /* end of n_hdlc_release() */
@@ -402,13 +393,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty)
402 n_hdlc->woke_up = 0; 393 n_hdlc->woke_up = 0;
403 spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); 394 spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);
404 395
405 /* get current transmit buffer or get new transmit */ 396 tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);
406 /* buffer from list of pending transmit buffers */
407
408 tbuf = n_hdlc->tbuf;
409 if (!tbuf)
410 tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);
411
412 while (tbuf) { 397 while (tbuf) {
413 if (debuglevel >= DEBUG_LEVEL_INFO) 398 if (debuglevel >= DEBUG_LEVEL_INFO)
414 printk("%s(%d)sending frame %p, count=%d\n", 399 printk("%s(%d)sending frame %p, count=%d\n",
@@ -420,7 +405,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty)
420 405
421 /* rollback was possible and has been done */ 406 /* rollback was possible and has been done */
422 if (actual == -ERESTARTSYS) { 407 if (actual == -ERESTARTSYS) {
423 n_hdlc->tbuf = tbuf; 408 n_hdlc_buf_return(&n_hdlc->tx_buf_list, tbuf);
424 break; 409 break;
425 } 410 }
426 /* if transmit error, throw frame away by */ 411 /* if transmit error, throw frame away by */
@@ -435,10 +420,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty)
435 420
436 /* free current transmit buffer */ 421 /* free current transmit buffer */
437 n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, tbuf); 422 n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, tbuf);
438 423
439 /* this tx buffer is done */
440 n_hdlc->tbuf = NULL;
441
442 /* wait up sleeping writers */ 424 /* wait up sleeping writers */
443 wake_up_interruptible(&tty->write_wait); 425 wake_up_interruptible(&tty->write_wait);
444 426
@@ -448,10 +430,12 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty)
448 if (debuglevel >= DEBUG_LEVEL_INFO) 430 if (debuglevel >= DEBUG_LEVEL_INFO)
449 printk("%s(%d)frame %p pending\n", 431 printk("%s(%d)frame %p pending\n",
450 __FILE__,__LINE__,tbuf); 432 __FILE__,__LINE__,tbuf);
451 433
452 /* buffer not accepted by driver */ 434 /*
453 /* set this buffer as pending buffer */ 435 * the buffer was not accepted by driver,
454 n_hdlc->tbuf = tbuf; 436 * return it back into tx queue
437 */
438 n_hdlc_buf_return(&n_hdlc->tx_buf_list, tbuf);
455 break; 439 break;
456 } 440 }
457 } 441 }
@@ -749,7 +733,8 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,
749 int error = 0; 733 int error = 0;
750 int count; 734 int count;
751 unsigned long flags; 735 unsigned long flags;
752 736 struct n_hdlc_buf *buf = NULL;
737
753 if (debuglevel >= DEBUG_LEVEL_INFO) 738 if (debuglevel >= DEBUG_LEVEL_INFO)
754 printk("%s(%d)n_hdlc_tty_ioctl() called %d\n", 739 printk("%s(%d)n_hdlc_tty_ioctl() called %d\n",
755 __FILE__,__LINE__,cmd); 740 __FILE__,__LINE__,cmd);
@@ -763,8 +748,10 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,
763 /* report count of read data available */ 748 /* report count of read data available */
764 /* in next available frame (if any) */ 749 /* in next available frame (if any) */
765 spin_lock_irqsave(&n_hdlc->rx_buf_list.spinlock,flags); 750 spin_lock_irqsave(&n_hdlc->rx_buf_list.spinlock,flags);
766 if (n_hdlc->rx_buf_list.head) 751 buf = list_first_entry_or_null(&n_hdlc->rx_buf_list.list,
767 count = n_hdlc->rx_buf_list.head->count; 752 struct n_hdlc_buf, list_item);
753 if (buf)
754 count = buf->count;
768 else 755 else
769 count = 0; 756 count = 0;
770 spin_unlock_irqrestore(&n_hdlc->rx_buf_list.spinlock,flags); 757 spin_unlock_irqrestore(&n_hdlc->rx_buf_list.spinlock,flags);
@@ -776,8 +763,10 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,
776 count = tty_chars_in_buffer(tty); 763 count = tty_chars_in_buffer(tty);
777 /* add size of next output frame in queue */ 764 /* add size of next output frame in queue */
778 spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock,flags); 765 spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock,flags);
779 if (n_hdlc->tx_buf_list.head) 766 buf = list_first_entry_or_null(&n_hdlc->tx_buf_list.list,
780 count += n_hdlc->tx_buf_list.head->count; 767 struct n_hdlc_buf, list_item);
768 if (buf)
769 count += buf->count;
781 spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock,flags); 770 spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock,flags);
782 error = put_user(count, (int __user *)arg); 771 error = put_user(count, (int __user *)arg);
783 break; 772 break;
@@ -825,14 +814,14 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,
825 poll_wait(filp, &tty->write_wait, wait); 814 poll_wait(filp, &tty->write_wait, wait);
826 815
827 /* set bits for operations that won't block */ 816 /* set bits for operations that won't block */
828 if (n_hdlc->rx_buf_list.head) 817 if (!list_empty(&n_hdlc->rx_buf_list.list))
829 mask |= POLLIN | POLLRDNORM; /* readable */ 818 mask |= POLLIN | POLLRDNORM; /* readable */
830 if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) 819 if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
831 mask |= POLLHUP; 820 mask |= POLLHUP;
832 if (tty_hung_up_p(filp)) 821 if (tty_hung_up_p(filp))
833 mask |= POLLHUP; 822 mask |= POLLHUP;
834 if (!tty_is_writelocked(tty) && 823 if (!tty_is_writelocked(tty) &&
835 n_hdlc->tx_free_buf_list.head) 824 !list_empty(&n_hdlc->tx_free_buf_list.list))
836 mask |= POLLOUT | POLLWRNORM; /* writable */ 825 mask |= POLLOUT | POLLWRNORM; /* writable */
837 } 826 }
838 return mask; 827 return mask;
@@ -856,7 +845,12 @@ static struct n_hdlc *n_hdlc_alloc(void)
856 spin_lock_init(&n_hdlc->tx_free_buf_list.spinlock); 845 spin_lock_init(&n_hdlc->tx_free_buf_list.spinlock);
857 spin_lock_init(&n_hdlc->rx_buf_list.spinlock); 846 spin_lock_init(&n_hdlc->rx_buf_list.spinlock);
858 spin_lock_init(&n_hdlc->tx_buf_list.spinlock); 847 spin_lock_init(&n_hdlc->tx_buf_list.spinlock);
859 848
849 INIT_LIST_HEAD(&n_hdlc->rx_free_buf_list.list);
850 INIT_LIST_HEAD(&n_hdlc->tx_free_buf_list.list);
851 INIT_LIST_HEAD(&n_hdlc->rx_buf_list.list);
852 INIT_LIST_HEAD(&n_hdlc->tx_buf_list.list);
853
860 /* allocate free rx buffer list */ 854 /* allocate free rx buffer list */
861 for(i=0;i<DEFAULT_RX_BUF_COUNT;i++) { 855 for(i=0;i<DEFAULT_RX_BUF_COUNT;i++) {
862 buf = kmalloc(N_HDLC_BUF_SIZE, GFP_KERNEL); 856 buf = kmalloc(N_HDLC_BUF_SIZE, GFP_KERNEL);
@@ -884,53 +878,65 @@ static struct n_hdlc *n_hdlc_alloc(void)
884} /* end of n_hdlc_alloc() */ 878} /* end of n_hdlc_alloc() */
885 879
886/** 880/**
881 * n_hdlc_buf_return - put the HDLC buffer after the head of the specified list
882 * @buf_list - pointer to the buffer list
883 * @buf - pointer to the buffer
884 */
885static void n_hdlc_buf_return(struct n_hdlc_buf_list *buf_list,
886 struct n_hdlc_buf *buf)
887{
888 unsigned long flags;
889
890 spin_lock_irqsave(&buf_list->spinlock, flags);
891
892 list_add(&buf->list_item, &buf_list->list);
893 buf_list->count++;
894
895 spin_unlock_irqrestore(&buf_list->spinlock, flags);
896}
897
898/**
887 * n_hdlc_buf_put - add specified HDLC buffer to tail of specified list 899 * n_hdlc_buf_put - add specified HDLC buffer to tail of specified list
888 * @list - pointer to buffer list 900 * @buf_list - pointer to buffer list
889 * @buf - pointer to buffer 901 * @buf - pointer to buffer
890 */ 902 */
891static void n_hdlc_buf_put(struct n_hdlc_buf_list *list, 903static void n_hdlc_buf_put(struct n_hdlc_buf_list *buf_list,
892 struct n_hdlc_buf *buf) 904 struct n_hdlc_buf *buf)
893{ 905{
894 unsigned long flags; 906 unsigned long flags;
895 spin_lock_irqsave(&list->spinlock,flags); 907
896 908 spin_lock_irqsave(&buf_list->spinlock, flags);
897 buf->link=NULL; 909
898 if (list->tail) 910 list_add_tail(&buf->list_item, &buf_list->list);
899 list->tail->link = buf; 911 buf_list->count++;
900 else 912
901 list->head = buf; 913 spin_unlock_irqrestore(&buf_list->spinlock, flags);
902 list->tail = buf;
903 (list->count)++;
904
905 spin_unlock_irqrestore(&list->spinlock,flags);
906
907} /* end of n_hdlc_buf_put() */ 914} /* end of n_hdlc_buf_put() */
908 915
909/** 916/**
910 * n_hdlc_buf_get - remove and return an HDLC buffer from list 917 * n_hdlc_buf_get - remove and return an HDLC buffer from list
911 * @list - pointer to HDLC buffer list 918 * @buf_list - pointer to HDLC buffer list
912 * 919 *
913 * Remove and return an HDLC buffer from the head of the specified HDLC buffer 920 * Remove and return an HDLC buffer from the head of the specified HDLC buffer
914 * list. 921 * list.
915 * Returns a pointer to HDLC buffer if available, otherwise %NULL. 922 * Returns a pointer to HDLC buffer if available, otherwise %NULL.
916 */ 923 */
917static struct n_hdlc_buf* n_hdlc_buf_get(struct n_hdlc_buf_list *list) 924static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *buf_list)
918{ 925{
919 unsigned long flags; 926 unsigned long flags;
920 struct n_hdlc_buf *buf; 927 struct n_hdlc_buf *buf;
921 spin_lock_irqsave(&list->spinlock,flags); 928
922 929 spin_lock_irqsave(&buf_list->spinlock, flags);
923 buf = list->head; 930
931 buf = list_first_entry_or_null(&buf_list->list,
932 struct n_hdlc_buf, list_item);
924 if (buf) { 933 if (buf) {
925 list->head = buf->link; 934 list_del(&buf->list_item);
926 (list->count)--; 935 buf_list->count--;
927 } 936 }
928 if (!list->head) 937
929 list->tail = NULL; 938 spin_unlock_irqrestore(&buf_list->spinlock, flags);
930
931 spin_unlock_irqrestore(&list->spinlock,flags);
932 return buf; 939 return buf;
933
934} /* end of n_hdlc_buf_get() */ 940} /* end of n_hdlc_buf_get() */
935 941
936static char hdlc_banner[] __initdata = 942static char hdlc_banner[] __initdata =
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index b4f86c219db1..7a17aedbf902 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -1031,8 +1031,10 @@ static int s3c64xx_serial_startup(struct uart_port *port)
1031 if (ourport->dma) { 1031 if (ourport->dma) {
1032 ret = s3c24xx_serial_request_dma(ourport); 1032 ret = s3c24xx_serial_request_dma(ourport);
1033 if (ret < 0) { 1033 if (ret < 0) {
1034 dev_warn(port->dev, "DMA request failed\n"); 1034 dev_warn(port->dev,
1035 return ret; 1035 "DMA request failed, DMA will not be used\n");
1036 devm_kfree(port->dev, ourport->dma);
1037 ourport->dma = NULL;
1036 } 1038 }
1037 } 1039 }
1038 1040