diff options
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/n_hdlc.c | 132 | ||||
-rw-r--r-- | drivers/tty/serial/samsung.c | 6 |
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 | ||
116 | struct n_hdlc_buf { | 116 | struct 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 | ||
124 | struct n_hdlc_buf_list { | 124 | struct 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 | */ |
159 | static void n_hdlc_buf_return(struct n_hdlc_buf_list *buf_list, | ||
160 | struct n_hdlc_buf *buf); | ||
162 | static void n_hdlc_buf_put(struct n_hdlc_buf_list *list, | 161 | static void n_hdlc_buf_put(struct n_hdlc_buf_list *list, |
163 | struct n_hdlc_buf *buf); | 162 | struct n_hdlc_buf *buf); |
164 | static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *list); | 163 | static 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 | ||
223 | static struct tty_ldisc_ops n_hdlc_ldisc = { | 215 | static 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 | */ | ||
885 | static 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 | */ |
891 | static void n_hdlc_buf_put(struct n_hdlc_buf_list *list, | 903 | static 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 | */ |
917 | static struct n_hdlc_buf* n_hdlc_buf_get(struct n_hdlc_buf_list *list) | 924 | static 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 | ||
936 | static char hdlc_banner[] __initdata = | 942 | static 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 | ||