diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/serial/68328serial.c | 102 |
1 files changed, 44 insertions, 58 deletions
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index b88a7c1158af..bff94541991c 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c | |||
@@ -131,17 +131,6 @@ static int m68328_console_baud = CONSOLE_BAUD_RATE; | |||
131 | static int m68328_console_cbaud = DEFAULT_CBAUD; | 131 | static int m68328_console_cbaud = DEFAULT_CBAUD; |
132 | 132 | ||
133 | 133 | ||
134 | /* | ||
135 | * tmp_buf is used as a temporary buffer by serial_write. We need to | ||
136 | * lock it in case the memcpy_fromfs blocks while swapping in a page, | ||
137 | * and some other program tries to do a serial write at the same time. | ||
138 | * Since the lock will only come under contention when the system is | ||
139 | * swapping and available memory is low, it makes sense to share one | ||
140 | * buffer across all the serial ports, since it significantly saves | ||
141 | * memory if large numbers of serial ports are open. | ||
142 | */ | ||
143 | static unsigned char tmp_buf[SERIAL_XMIT_SIZE]; /* This is cheating */ | ||
144 | |||
145 | static inline int serial_paranoia_check(struct m68k_serial *info, | 134 | static inline int serial_paranoia_check(struct m68k_serial *info, |
146 | char *name, const char *routine) | 135 | char *name, const char *routine) |
147 | { | 136 | { |
@@ -211,16 +200,16 @@ static void rs_stop(struct tty_struct *tty) | |||
211 | if (serial_paranoia_check(info, tty->name, "rs_stop")) | 200 | if (serial_paranoia_check(info, tty->name, "rs_stop")) |
212 | return; | 201 | return; |
213 | 202 | ||
214 | save_flags(flags); cli(); | 203 | local_irq_save(flags); |
215 | uart->ustcnt &= ~USTCNT_TXEN; | 204 | uart->ustcnt &= ~USTCNT_TXEN; |
216 | restore_flags(flags); | 205 | local_irq_restore(flags); |
217 | } | 206 | } |
218 | 207 | ||
219 | static void rs_put_char(char ch) | 208 | static void rs_put_char(char ch) |
220 | { | 209 | { |
221 | int flags, loops = 0; | 210 | int flags, loops = 0; |
222 | 211 | ||
223 | save_flags(flags); cli(); | 212 | local_irq_save(flags); |
224 | 213 | ||
225 | while (!(UTX & UTX_TX_AVAIL) && (loops < 1000)) { | 214 | while (!(UTX & UTX_TX_AVAIL) && (loops < 1000)) { |
226 | loops++; | 215 | loops++; |
@@ -229,7 +218,7 @@ static void rs_put_char(char ch) | |||
229 | 218 | ||
230 | UTX_TXDATA = ch; | 219 | UTX_TXDATA = ch; |
231 | udelay(5); | 220 | udelay(5); |
232 | restore_flags(flags); | 221 | local_irq_restore(flags); |
233 | } | 222 | } |
234 | 223 | ||
235 | static void rs_start(struct tty_struct *tty) | 224 | static void rs_start(struct tty_struct *tty) |
@@ -241,7 +230,7 @@ static void rs_start(struct tty_struct *tty) | |||
241 | if (serial_paranoia_check(info, tty->name, "rs_start")) | 230 | if (serial_paranoia_check(info, tty->name, "rs_start")) |
242 | return; | 231 | return; |
243 | 232 | ||
244 | save_flags(flags); cli(); | 233 | local_irq_save(flags); |
245 | if (info->xmit_cnt && info->xmit_buf && !(uart->ustcnt & USTCNT_TXEN)) { | 234 | if (info->xmit_cnt && info->xmit_buf && !(uart->ustcnt & USTCNT_TXEN)) { |
246 | #ifdef USE_INTS | 235 | #ifdef USE_INTS |
247 | uart->ustcnt |= USTCNT_TXEN | USTCNT_TX_INTR_MASK; | 236 | uart->ustcnt |= USTCNT_TXEN | USTCNT_TX_INTR_MASK; |
@@ -249,7 +238,7 @@ static void rs_start(struct tty_struct *tty) | |||
249 | uart->ustcnt |= USTCNT_TXEN; | 238 | uart->ustcnt |= USTCNT_TXEN; |
250 | #endif | 239 | #endif |
251 | } | 240 | } |
252 | restore_flags(flags); | 241 | local_irq_restore(flags); |
253 | } | 242 | } |
254 | 243 | ||
255 | /* Drop into either the boot monitor or kadb upon receiving a break | 244 | /* Drop into either the boot monitor or kadb upon receiving a break |
@@ -327,14 +316,6 @@ static void receive_chars(struct m68k_serial *info, struct pt_regs *regs, | |||
327 | if(!tty) | 316 | if(!tty) |
328 | goto clear_and_exit; | 317 | goto clear_and_exit; |
329 | 318 | ||
330 | /* | ||
331 | * Make sure that we do not overflow the buffer | ||
332 | */ | ||
333 | if (tty_request_buffer_room(tty, 1) == 0) { | ||
334 | tty_schedule_flip(tty); | ||
335 | return; | ||
336 | } | ||
337 | |||
338 | flag = TTY_NORMAL; | 319 | flag = TTY_NORMAL; |
339 | 320 | ||
340 | if(rx & URX_PARITY_ERROR) { | 321 | if(rx & URX_PARITY_ERROR) { |
@@ -473,7 +454,7 @@ static int startup(struct m68k_serial * info) | |||
473 | return -ENOMEM; | 454 | return -ENOMEM; |
474 | } | 455 | } |
475 | 456 | ||
476 | save_flags(flags); cli(); | 457 | local_irq_save(flags); |
477 | 458 | ||
478 | /* | 459 | /* |
479 | * Clear the FIFO buffers and disable them | 460 | * Clear the FIFO buffers and disable them |
@@ -506,7 +487,7 @@ static int startup(struct m68k_serial * info) | |||
506 | change_speed(info); | 487 | change_speed(info); |
507 | 488 | ||
508 | info->flags |= S_INITIALIZED; | 489 | info->flags |= S_INITIALIZED; |
509 | restore_flags(flags); | 490 | local_irq_restore(flags); |
510 | return 0; | 491 | return 0; |
511 | } | 492 | } |
512 | 493 | ||
@@ -523,7 +504,7 @@ static void shutdown(struct m68k_serial * info) | |||
523 | if (!(info->flags & S_INITIALIZED)) | 504 | if (!(info->flags & S_INITIALIZED)) |
524 | return; | 505 | return; |
525 | 506 | ||
526 | save_flags(flags); cli(); /* Disable interrupts */ | 507 | local_irq_save(flags); |
527 | 508 | ||
528 | if (info->xmit_buf) { | 509 | if (info->xmit_buf) { |
529 | free_page((unsigned long) info->xmit_buf); | 510 | free_page((unsigned long) info->xmit_buf); |
@@ -534,7 +515,7 @@ static void shutdown(struct m68k_serial * info) | |||
534 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 515 | set_bit(TTY_IO_ERROR, &info->tty->flags); |
535 | 516 | ||
536 | info->flags &= ~S_INITIALIZED; | 517 | info->flags &= ~S_INITIALIZED; |
537 | restore_flags(flags); | 518 | local_irq_restore(flags); |
538 | } | 519 | } |
539 | 520 | ||
540 | struct { | 521 | struct { |
@@ -655,24 +636,24 @@ static void rs_fair_output(void) | |||
655 | if (info == 0) return; | 636 | if (info == 0) return; |
656 | if (info->xmit_buf == 0) return; | 637 | if (info->xmit_buf == 0) return; |
657 | 638 | ||
658 | save_flags(flags); cli(); | 639 | local_irq_save(flags); |
659 | left = info->xmit_cnt; | 640 | left = info->xmit_cnt; |
660 | while (left != 0) { | 641 | while (left != 0) { |
661 | c = info->xmit_buf[info->xmit_tail]; | 642 | c = info->xmit_buf[info->xmit_tail]; |
662 | info->xmit_tail = (info->xmit_tail+1) & (SERIAL_XMIT_SIZE-1); | 643 | info->xmit_tail = (info->xmit_tail+1) & (SERIAL_XMIT_SIZE-1); |
663 | info->xmit_cnt--; | 644 | info->xmit_cnt--; |
664 | restore_flags(flags); | 645 | local_irq_restore(flags); |
665 | 646 | ||
666 | rs_put_char(c); | 647 | rs_put_char(c); |
667 | 648 | ||
668 | save_flags(flags); cli(); | 649 | local_irq_save(flags); |
669 | left = min(info->xmit_cnt, left-1); | 650 | left = min(info->xmit_cnt, left-1); |
670 | } | 651 | } |
671 | 652 | ||
672 | /* Last character is being transmitted now (hopefully). */ | 653 | /* Last character is being transmitted now (hopefully). */ |
673 | udelay(5); | 654 | udelay(5); |
674 | 655 | ||
675 | restore_flags(flags); | 656 | local_irq_restore(flags); |
676 | return; | 657 | return; |
677 | } | 658 | } |
678 | 659 | ||
@@ -720,11 +701,11 @@ static void rs_flush_chars(struct tty_struct *tty) | |||
720 | #endif | 701 | #endif |
721 | 702 | ||
722 | /* Enable transmitter */ | 703 | /* Enable transmitter */ |
723 | save_flags(flags); cli(); | 704 | local_irq_save(flags); |
724 | 705 | ||
725 | if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || | 706 | if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || |
726 | !info->xmit_buf) { | 707 | !info->xmit_buf) { |
727 | restore_flags(flags); | 708 | local_irq_restore(flags); |
728 | return; | 709 | return; |
729 | } | 710 | } |
730 | 711 | ||
@@ -749,7 +730,7 @@ static void rs_flush_chars(struct tty_struct *tty) | |||
749 | while (!(uart->utx.w & UTX_TX_AVAIL)) udelay(5); | 730 | while (!(uart->utx.w & UTX_TX_AVAIL)) udelay(5); |
750 | } | 731 | } |
751 | #endif | 732 | #endif |
752 | restore_flags(flags); | 733 | local_irq_restore(flags); |
753 | } | 734 | } |
754 | 735 | ||
755 | extern void console_printn(const char * b, int count); | 736 | extern void console_printn(const char * b, int count); |
@@ -768,18 +749,22 @@ static int rs_write(struct tty_struct * tty, | |||
768 | if (!tty || !info->xmit_buf) | 749 | if (!tty || !info->xmit_buf) |
769 | return 0; | 750 | return 0; |
770 | 751 | ||
771 | save_flags(flags); | 752 | local_save_flags(flags); |
772 | while (1) { | 753 | while (1) { |
773 | cli(); | 754 | local_irq_disable(); |
774 | c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, | 755 | c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, |
775 | SERIAL_XMIT_SIZE - info->xmit_head)); | 756 | SERIAL_XMIT_SIZE - info->xmit_head)); |
757 | local_irq_restore(flags); | ||
758 | |||
776 | if (c <= 0) | 759 | if (c <= 0) |
777 | break; | 760 | break; |
778 | 761 | ||
779 | memcpy(info->xmit_buf + info->xmit_head, buf, c); | 762 | memcpy(info->xmit_buf + info->xmit_head, buf, c); |
763 | |||
764 | local_irq_disable(); | ||
780 | info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); | 765 | info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); |
781 | info->xmit_cnt += c; | 766 | info->xmit_cnt += c; |
782 | restore_flags(flags); | 767 | local_irq_restore(flags); |
783 | buf += c; | 768 | buf += c; |
784 | count -= c; | 769 | count -= c; |
785 | total += c; | 770 | total += c; |
@@ -787,7 +772,7 @@ static int rs_write(struct tty_struct * tty, | |||
787 | 772 | ||
788 | if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) { | 773 | if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) { |
789 | /* Enable transmitter */ | 774 | /* Enable transmitter */ |
790 | cli(); | 775 | local_irq_disable(); |
791 | #ifndef USE_INTS | 776 | #ifndef USE_INTS |
792 | while(info->xmit_cnt) { | 777 | while(info->xmit_cnt) { |
793 | #endif | 778 | #endif |
@@ -807,9 +792,9 @@ static int rs_write(struct tty_struct * tty, | |||
807 | #ifndef USE_INTS | 792 | #ifndef USE_INTS |
808 | } | 793 | } |
809 | #endif | 794 | #endif |
810 | restore_flags(flags); | 795 | local_irq_restore(flags); |
811 | } | 796 | } |
812 | restore_flags(flags); | 797 | |
813 | return total; | 798 | return total; |
814 | } | 799 | } |
815 | 800 | ||
@@ -838,12 +823,13 @@ static int rs_chars_in_buffer(struct tty_struct *tty) | |||
838 | static void rs_flush_buffer(struct tty_struct *tty) | 823 | static void rs_flush_buffer(struct tty_struct *tty) |
839 | { | 824 | { |
840 | struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; | 825 | struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; |
826 | unsigned long flags; | ||
841 | 827 | ||
842 | if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) | 828 | if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) |
843 | return; | 829 | return; |
844 | cli(); | 830 | local_irq_save(flags); |
845 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | 831 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; |
846 | sti(); | 832 | local_irq_restore(flags); |
847 | tty_wakeup(tty); | 833 | tty_wakeup(tty); |
848 | } | 834 | } |
849 | 835 | ||
@@ -973,14 +959,15 @@ static int get_lsr_info(struct m68k_serial * info, unsigned int *value) | |||
973 | m68328_uart *uart = &uart_addr[info->line]; | 959 | m68328_uart *uart = &uart_addr[info->line]; |
974 | #endif | 960 | #endif |
975 | unsigned char status; | 961 | unsigned char status; |
962 | unsigned long flags; | ||
976 | 963 | ||
977 | cli(); | 964 | local_irq_save(flags); |
978 | #ifdef CONFIG_SERIAL_68328_RTS_CTS | 965 | #ifdef CONFIG_SERIAL_68328_RTS_CTS |
979 | status = (uart->utx.w & UTX_CTS_STAT) ? 1 : 0; | 966 | status = (uart->utx.w & UTX_CTS_STAT) ? 1 : 0; |
980 | #else | 967 | #else |
981 | status = 0; | 968 | status = 0; |
982 | #endif | 969 | #endif |
983 | sti(); | 970 | local_irq_restore(flags); |
984 | put_user(status,value); | 971 | put_user(status,value); |
985 | return 0; | 972 | return 0; |
986 | } | 973 | } |
@@ -994,14 +981,13 @@ static void send_break(struct m68k_serial * info, unsigned int duration) | |||
994 | unsigned long flags; | 981 | unsigned long flags; |
995 | if (!info->port) | 982 | if (!info->port) |
996 | return; | 983 | return; |
997 | save_flags(flags); | 984 | local_irq_save(flags); |
998 | cli(); | ||
999 | #ifdef USE_INTS | 985 | #ifdef USE_INTS |
1000 | uart->utx.w |= UTX_SEND_BREAK; | 986 | uart->utx.w |= UTX_SEND_BREAK; |
1001 | msleep_interruptible(duration); | 987 | msleep_interruptible(duration); |
1002 | uart->utx.w &= ~UTX_SEND_BREAK; | 988 | uart->utx.w &= ~UTX_SEND_BREAK; |
1003 | #endif | 989 | #endif |
1004 | restore_flags(flags); | 990 | local_irq_restore(flags); |
1005 | } | 991 | } |
1006 | 992 | ||
1007 | static int rs_ioctl(struct tty_struct *tty, struct file * file, | 993 | static int rs_ioctl(struct tty_struct *tty, struct file * file, |
@@ -1060,7 +1046,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, | |||
1060 | (struct serial_struct *) arg); | 1046 | (struct serial_struct *) arg); |
1061 | case TIOCSERGETLSR: /* Get line status register */ | 1047 | case TIOCSERGETLSR: /* Get line status register */ |
1062 | if (access_ok(VERIFY_WRITE, (void *) arg, | 1048 | if (access_ok(VERIFY_WRITE, (void *) arg, |
1063 | sizeof(unsigned int)); | 1049 | sizeof(unsigned int))) |
1064 | return get_lsr_info(info, (unsigned int *) arg); | 1050 | return get_lsr_info(info, (unsigned int *) arg); |
1065 | return -EFAULT; | 1051 | return -EFAULT; |
1066 | case TIOCSERGSTRUCT: | 1052 | case TIOCSERGSTRUCT: |
@@ -1113,10 +1099,10 @@ static void rs_close(struct tty_struct *tty, struct file * filp) | |||
1113 | if (!info || serial_paranoia_check(info, tty->name, "rs_close")) | 1099 | if (!info || serial_paranoia_check(info, tty->name, "rs_close")) |
1114 | return; | 1100 | return; |
1115 | 1101 | ||
1116 | save_flags(flags); cli(); | 1102 | local_irq_save(flags); |
1117 | 1103 | ||
1118 | if (tty_hung_up_p(filp)) { | 1104 | if (tty_hung_up_p(filp)) { |
1119 | restore_flags(flags); | 1105 | local_irq_restore(flags); |
1120 | return; | 1106 | return; |
1121 | } | 1107 | } |
1122 | 1108 | ||
@@ -1138,7 +1124,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) | |||
1138 | info->count = 0; | 1124 | info->count = 0; |
1139 | } | 1125 | } |
1140 | if (info->count) { | 1126 | if (info->count) { |
1141 | restore_flags(flags); | 1127 | local_irq_restore(flags); |
1142 | return; | 1128 | return; |
1143 | } | 1129 | } |
1144 | info->flags |= S_CLOSING; | 1130 | info->flags |= S_CLOSING; |
@@ -1186,7 +1172,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) | |||
1186 | } | 1172 | } |
1187 | info->flags &= ~(S_NORMAL_ACTIVE|S_CLOSING); | 1173 | info->flags &= ~(S_NORMAL_ACTIVE|S_CLOSING); |
1188 | wake_up_interruptible(&info->close_wait); | 1174 | wake_up_interruptible(&info->close_wait); |
1189 | restore_flags(flags); | 1175 | local_irq_restore(flags); |
1190 | } | 1176 | } |
1191 | 1177 | ||
1192 | /* | 1178 | /* |
@@ -1262,9 +1248,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
1262 | info->count--; | 1248 | info->count--; |
1263 | info->blocked_open++; | 1249 | info->blocked_open++; |
1264 | while (1) { | 1250 | while (1) { |
1265 | cli(); | 1251 | local_irq_disable(); |
1266 | m68k_rtsdtr(info, 1); | 1252 | m68k_rtsdtr(info, 1); |
1267 | sti(); | 1253 | local_irq_enable(); |
1268 | current->state = TASK_INTERRUPTIBLE; | 1254 | current->state = TASK_INTERRUPTIBLE; |
1269 | if (tty_hung_up_p(filp) || | 1255 | if (tty_hung_up_p(filp) || |
1270 | !(info->flags & S_INITIALIZED)) { | 1256 | !(info->flags & S_INITIALIZED)) { |
@@ -1444,7 +1430,7 @@ rs68328_init(void) | |||
1444 | return -ENOMEM; | 1430 | return -ENOMEM; |
1445 | } | 1431 | } |
1446 | 1432 | ||
1447 | save_flags(flags); cli(); | 1433 | local_irq_save(flags); |
1448 | 1434 | ||
1449 | for(i=0;i<NR_PORTS;i++) { | 1435 | for(i=0;i<NR_PORTS;i++) { |
1450 | 1436 | ||
@@ -1489,7 +1475,7 @@ rs68328_init(void) | |||
1489 | serial_pm[i]->data = info; | 1475 | serial_pm[i]->data = info; |
1490 | #endif | 1476 | #endif |
1491 | } | 1477 | } |
1492 | restore_flags(flags); | 1478 | local_irq_restore(flags); |
1493 | return 0; | 1479 | return 0; |
1494 | } | 1480 | } |
1495 | 1481 | ||