diff options
Diffstat (limited to 'drivers/char/synclink_gt.c')
-rw-r--r-- | drivers/char/synclink_gt.c | 92 |
1 files changed, 47 insertions, 45 deletions
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 334cf5c8c8b6..fef80cfcab5c 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -40,8 +40,8 @@ | |||
40 | #define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt | 40 | #define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt |
41 | #define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt | 41 | #define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt |
42 | #define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label)) | 42 | #define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label)) |
43 | //#define DBGTBUF(info) dump_tbufs(info) | 43 | /*#define DBGTBUF(info) dump_tbufs(info)*/ |
44 | //#define DBGRBUF(info) dump_rbufs(info) | 44 | /*#define DBGRBUF(info) dump_rbufs(info)*/ |
45 | 45 | ||
46 | 46 | ||
47 | #include <linux/module.h> | 47 | #include <linux/module.h> |
@@ -62,7 +62,6 @@ | |||
62 | #include <linux/mm.h> | 62 | #include <linux/mm.h> |
63 | #include <linux/seq_file.h> | 63 | #include <linux/seq_file.h> |
64 | #include <linux/slab.h> | 64 | #include <linux/slab.h> |
65 | #include <linux/smp_lock.h> | ||
66 | #include <linux/netdevice.h> | 65 | #include <linux/netdevice.h> |
67 | #include <linux/vmalloc.h> | 66 | #include <linux/vmalloc.h> |
68 | #include <linux/init.h> | 67 | #include <linux/init.h> |
@@ -676,12 +675,14 @@ static int open(struct tty_struct *tty, struct file *filp) | |||
676 | goto cleanup; | 675 | goto cleanup; |
677 | } | 676 | } |
678 | 677 | ||
678 | mutex_lock(&info->port.mutex); | ||
679 | info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 679 | info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
680 | 680 | ||
681 | spin_lock_irqsave(&info->netlock, flags); | 681 | spin_lock_irqsave(&info->netlock, flags); |
682 | if (info->netcount) { | 682 | if (info->netcount) { |
683 | retval = -EBUSY; | 683 | retval = -EBUSY; |
684 | spin_unlock_irqrestore(&info->netlock, flags); | 684 | spin_unlock_irqrestore(&info->netlock, flags); |
685 | mutex_unlock(&info->port.mutex); | ||
685 | goto cleanup; | 686 | goto cleanup; |
686 | } | 687 | } |
687 | info->port.count++; | 688 | info->port.count++; |
@@ -693,7 +694,7 @@ static int open(struct tty_struct *tty, struct file *filp) | |||
693 | if (retval < 0) | 694 | if (retval < 0) |
694 | goto cleanup; | 695 | goto cleanup; |
695 | } | 696 | } |
696 | 697 | mutex_unlock(&info->port.mutex); | |
697 | retval = block_til_ready(tty, filp, info); | 698 | retval = block_til_ready(tty, filp, info); |
698 | if (retval) { | 699 | if (retval) { |
699 | DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval)); | 700 | DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval)); |
@@ -725,12 +726,14 @@ static void close(struct tty_struct *tty, struct file *filp) | |||
725 | if (tty_port_close_start(&info->port, tty, filp) == 0) | 726 | if (tty_port_close_start(&info->port, tty, filp) == 0) |
726 | goto cleanup; | 727 | goto cleanup; |
727 | 728 | ||
729 | mutex_lock(&info->port.mutex); | ||
728 | if (info->port.flags & ASYNC_INITIALIZED) | 730 | if (info->port.flags & ASYNC_INITIALIZED) |
729 | wait_until_sent(tty, info->timeout); | 731 | wait_until_sent(tty, info->timeout); |
730 | flush_buffer(tty); | 732 | flush_buffer(tty); |
731 | tty_ldisc_flush(tty); | 733 | tty_ldisc_flush(tty); |
732 | 734 | ||
733 | shutdown(info); | 735 | shutdown(info); |
736 | mutex_unlock(&info->port.mutex); | ||
734 | 737 | ||
735 | tty_port_close_end(&info->port, tty); | 738 | tty_port_close_end(&info->port, tty); |
736 | info->port.tty = NULL; | 739 | info->port.tty = NULL; |
@@ -741,17 +744,23 @@ cleanup: | |||
741 | static void hangup(struct tty_struct *tty) | 744 | static void hangup(struct tty_struct *tty) |
742 | { | 745 | { |
743 | struct slgt_info *info = tty->driver_data; | 746 | struct slgt_info *info = tty->driver_data; |
747 | unsigned long flags; | ||
744 | 748 | ||
745 | if (sanity_check(info, tty->name, "hangup")) | 749 | if (sanity_check(info, tty->name, "hangup")) |
746 | return; | 750 | return; |
747 | DBGINFO(("%s hangup\n", info->device_name)); | 751 | DBGINFO(("%s hangup\n", info->device_name)); |
748 | 752 | ||
749 | flush_buffer(tty); | 753 | flush_buffer(tty); |
754 | |||
755 | mutex_lock(&info->port.mutex); | ||
750 | shutdown(info); | 756 | shutdown(info); |
751 | 757 | ||
758 | spin_lock_irqsave(&info->port.lock, flags); | ||
752 | info->port.count = 0; | 759 | info->port.count = 0; |
753 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 760 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
754 | info->port.tty = NULL; | 761 | info->port.tty = NULL; |
762 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
763 | mutex_unlock(&info->port.mutex); | ||
755 | 764 | ||
756 | wake_up_interruptible(&info->port.open_wait); | 765 | wake_up_interruptible(&info->port.open_wait); |
757 | } | 766 | } |
@@ -901,8 +910,6 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) | |||
901 | * Note: use tight timings here to satisfy the NIST-PCTS. | 910 | * Note: use tight timings here to satisfy the NIST-PCTS. |
902 | */ | 911 | */ |
903 | 912 | ||
904 | lock_kernel(); | ||
905 | |||
906 | if (info->params.data_rate) { | 913 | if (info->params.data_rate) { |
907 | char_time = info->timeout/(32 * 5); | 914 | char_time = info->timeout/(32 * 5); |
908 | if (!char_time) | 915 | if (!char_time) |
@@ -920,8 +927,6 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) | |||
920 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) | 927 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) |
921 | break; | 928 | break; |
922 | } | 929 | } |
923 | unlock_kernel(); | ||
924 | |||
925 | exit: | 930 | exit: |
926 | DBGINFO(("%s wait_until_sent exit\n", info->device_name)); | 931 | DBGINFO(("%s wait_until_sent exit\n", info->device_name)); |
927 | } | 932 | } |
@@ -1041,8 +1046,37 @@ static int ioctl(struct tty_struct *tty, struct file *file, | |||
1041 | return -EIO; | 1046 | return -EIO; |
1042 | } | 1047 | } |
1043 | 1048 | ||
1044 | lock_kernel(); | 1049 | switch (cmd) { |
1045 | 1050 | case MGSL_IOCWAITEVENT: | |
1051 | return wait_mgsl_event(info, argp); | ||
1052 | case TIOCMIWAIT: | ||
1053 | return modem_input_wait(info,(int)arg); | ||
1054 | case TIOCGICOUNT: | ||
1055 | spin_lock_irqsave(&info->lock,flags); | ||
1056 | cnow = info->icount; | ||
1057 | spin_unlock_irqrestore(&info->lock,flags); | ||
1058 | p_cuser = argp; | ||
1059 | if (put_user(cnow.cts, &p_cuser->cts) || | ||
1060 | put_user(cnow.dsr, &p_cuser->dsr) || | ||
1061 | put_user(cnow.rng, &p_cuser->rng) || | ||
1062 | put_user(cnow.dcd, &p_cuser->dcd) || | ||
1063 | put_user(cnow.rx, &p_cuser->rx) || | ||
1064 | put_user(cnow.tx, &p_cuser->tx) || | ||
1065 | put_user(cnow.frame, &p_cuser->frame) || | ||
1066 | put_user(cnow.overrun, &p_cuser->overrun) || | ||
1067 | put_user(cnow.parity, &p_cuser->parity) || | ||
1068 | put_user(cnow.brk, &p_cuser->brk) || | ||
1069 | put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) | ||
1070 | return -EFAULT; | ||
1071 | return 0; | ||
1072 | case MGSL_IOCSGPIO: | ||
1073 | return set_gpio(info, argp); | ||
1074 | case MGSL_IOCGGPIO: | ||
1075 | return get_gpio(info, argp); | ||
1076 | case MGSL_IOCWAITGPIO: | ||
1077 | return wait_gpio(info, argp); | ||
1078 | } | ||
1079 | mutex_lock(&info->port.mutex); | ||
1046 | switch (cmd) { | 1080 | switch (cmd) { |
1047 | case MGSL_IOCGPARAMS: | 1081 | case MGSL_IOCGPARAMS: |
1048 | ret = get_params(info, argp); | 1082 | ret = get_params(info, argp); |
@@ -1068,50 +1102,16 @@ static int ioctl(struct tty_struct *tty, struct file *file, | |||
1068 | case MGSL_IOCGSTATS: | 1102 | case MGSL_IOCGSTATS: |
1069 | ret = get_stats(info, argp); | 1103 | ret = get_stats(info, argp); |
1070 | break; | 1104 | break; |
1071 | case MGSL_IOCWAITEVENT: | ||
1072 | ret = wait_mgsl_event(info, argp); | ||
1073 | break; | ||
1074 | case TIOCMIWAIT: | ||
1075 | ret = modem_input_wait(info,(int)arg); | ||
1076 | break; | ||
1077 | case MGSL_IOCGIF: | 1105 | case MGSL_IOCGIF: |
1078 | ret = get_interface(info, argp); | 1106 | ret = get_interface(info, argp); |
1079 | break; | 1107 | break; |
1080 | case MGSL_IOCSIF: | 1108 | case MGSL_IOCSIF: |
1081 | ret = set_interface(info,(int)arg); | 1109 | ret = set_interface(info,(int)arg); |
1082 | break; | 1110 | break; |
1083 | case MGSL_IOCSGPIO: | ||
1084 | ret = set_gpio(info, argp); | ||
1085 | break; | ||
1086 | case MGSL_IOCGGPIO: | ||
1087 | ret = get_gpio(info, argp); | ||
1088 | break; | ||
1089 | case MGSL_IOCWAITGPIO: | ||
1090 | ret = wait_gpio(info, argp); | ||
1091 | break; | ||
1092 | case TIOCGICOUNT: | ||
1093 | spin_lock_irqsave(&info->lock,flags); | ||
1094 | cnow = info->icount; | ||
1095 | spin_unlock_irqrestore(&info->lock,flags); | ||
1096 | p_cuser = argp; | ||
1097 | if (put_user(cnow.cts, &p_cuser->cts) || | ||
1098 | put_user(cnow.dsr, &p_cuser->dsr) || | ||
1099 | put_user(cnow.rng, &p_cuser->rng) || | ||
1100 | put_user(cnow.dcd, &p_cuser->dcd) || | ||
1101 | put_user(cnow.rx, &p_cuser->rx) || | ||
1102 | put_user(cnow.tx, &p_cuser->tx) || | ||
1103 | put_user(cnow.frame, &p_cuser->frame) || | ||
1104 | put_user(cnow.overrun, &p_cuser->overrun) || | ||
1105 | put_user(cnow.parity, &p_cuser->parity) || | ||
1106 | put_user(cnow.brk, &p_cuser->brk) || | ||
1107 | put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) | ||
1108 | ret = -EFAULT; | ||
1109 | ret = 0; | ||
1110 | break; | ||
1111 | default: | 1111 | default: |
1112 | ret = -ENOIOCTLCMD; | 1112 | ret = -ENOIOCTLCMD; |
1113 | } | 1113 | } |
1114 | unlock_kernel(); | 1114 | mutex_unlock(&info->port.mutex); |
1115 | return ret; | 1115 | return ret; |
1116 | } | 1116 | } |
1117 | 1117 | ||
@@ -3244,7 +3244,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3244 | } | 3244 | } |
3245 | 3245 | ||
3246 | DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); | 3246 | DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); |
3247 | tty_unlock(); | ||
3247 | schedule(); | 3248 | schedule(); |
3249 | tty_lock(); | ||
3248 | } | 3250 | } |
3249 | 3251 | ||
3250 | set_current_state(TASK_RUNNING); | 3252 | set_current_state(TASK_RUNNING); |