| .. | .. |
|---|
| 22 | 22 | * |
|---|
| 23 | 23 | */ |
|---|
| 24 | 24 | |
|---|
| 25 | | -/* |
|---|
| 26 | | - * Serial driver configuration section. Here are the various options: |
|---|
| 27 | | - * |
|---|
| 28 | | - * SERIAL_PARANOIA_CHECK |
|---|
| 29 | | - * Check the magic number for the async_structure where |
|---|
| 30 | | - * ever possible. |
|---|
| 31 | | - */ |
|---|
| 32 | | - |
|---|
| 33 | 25 | #include <linux/delay.h> |
|---|
| 34 | | - |
|---|
| 35 | | -#undef SERIAL_PARANOIA_CHECK |
|---|
| 36 | 26 | |
|---|
| 37 | 27 | /* Set of debugging defines */ |
|---|
| 38 | 28 | |
|---|
| .. | .. |
|---|
| 132 | 122 | |
|---|
| 133 | 123 | #define serial_isroot() (capable(CAP_SYS_ADMIN)) |
|---|
| 134 | 124 | |
|---|
| 135 | | - |
|---|
| 136 | | -static inline int serial_paranoia_check(struct serial_state *info, |
|---|
| 137 | | - char *name, const char *routine) |
|---|
| 138 | | -{ |
|---|
| 139 | | -#ifdef SERIAL_PARANOIA_CHECK |
|---|
| 140 | | - static const char *badmagic = |
|---|
| 141 | | - "Warning: bad magic number for serial struct (%s) in %s\n"; |
|---|
| 142 | | - static const char *badinfo = |
|---|
| 143 | | - "Warning: null async_struct for (%s) in %s\n"; |
|---|
| 144 | | - |
|---|
| 145 | | - if (!info) { |
|---|
| 146 | | - printk(badinfo, name, routine); |
|---|
| 147 | | - return 1; |
|---|
| 148 | | - } |
|---|
| 149 | | - if (info->magic != SERIAL_MAGIC) { |
|---|
| 150 | | - printk(badmagic, name, routine); |
|---|
| 151 | | - return 1; |
|---|
| 152 | | - } |
|---|
| 153 | | -#endif |
|---|
| 154 | | - return 0; |
|---|
| 155 | | -} |
|---|
| 156 | | - |
|---|
| 157 | 125 | /* some serial hardware definitions */ |
|---|
| 158 | 126 | #define SDR_OVRUN (1<<15) |
|---|
| 159 | 127 | #define SDR_RBF (1<<14) |
|---|
| .. | .. |
|---|
| 189 | 157 | struct serial_state *info = tty->driver_data; |
|---|
| 190 | 158 | unsigned long flags; |
|---|
| 191 | 159 | |
|---|
| 192 | | - if (serial_paranoia_check(info, tty->name, "rs_stop")) |
|---|
| 193 | | - return; |
|---|
| 194 | | - |
|---|
| 195 | 160 | local_irq_save(flags); |
|---|
| 196 | 161 | if (info->IER & UART_IER_THRI) { |
|---|
| 197 | 162 | info->IER &= ~UART_IER_THRI; |
|---|
| .. | .. |
|---|
| 208 | 173 | { |
|---|
| 209 | 174 | struct serial_state *info = tty->driver_data; |
|---|
| 210 | 175 | unsigned long flags; |
|---|
| 211 | | - |
|---|
| 212 | | - if (serial_paranoia_check(info, tty->name, "rs_start")) |
|---|
| 213 | | - return; |
|---|
| 214 | 176 | |
|---|
| 215 | 177 | local_irq_save(flags); |
|---|
| 216 | 178 | if (info->xmit.head != info->xmit.tail |
|---|
| .. | .. |
|---|
| 783 | 745 | |
|---|
| 784 | 746 | info = tty->driver_data; |
|---|
| 785 | 747 | |
|---|
| 786 | | - if (serial_paranoia_check(info, tty->name, "rs_put_char")) |
|---|
| 787 | | - return 0; |
|---|
| 788 | | - |
|---|
| 789 | 748 | if (!info->xmit.buf) |
|---|
| 790 | 749 | return 0; |
|---|
| 791 | 750 | |
|---|
| .. | .. |
|---|
| 808 | 767 | struct serial_state *info = tty->driver_data; |
|---|
| 809 | 768 | unsigned long flags; |
|---|
| 810 | 769 | |
|---|
| 811 | | - if (serial_paranoia_check(info, tty->name, "rs_flush_chars")) |
|---|
| 812 | | - return; |
|---|
| 813 | | - |
|---|
| 814 | 770 | if (info->xmit.head == info->xmit.tail |
|---|
| 815 | 771 | || tty->stopped |
|---|
| 816 | 772 | || tty->hw_stopped |
|---|
| .. | .. |
|---|
| 832 | 788 | int c, ret = 0; |
|---|
| 833 | 789 | struct serial_state *info = tty->driver_data; |
|---|
| 834 | 790 | unsigned long flags; |
|---|
| 835 | | - |
|---|
| 836 | | - if (serial_paranoia_check(info, tty->name, "rs_write")) |
|---|
| 837 | | - return 0; |
|---|
| 838 | 791 | |
|---|
| 839 | 792 | if (!info->xmit.buf) |
|---|
| 840 | 793 | return 0; |
|---|
| .. | .. |
|---|
| 878 | 831 | { |
|---|
| 879 | 832 | struct serial_state *info = tty->driver_data; |
|---|
| 880 | 833 | |
|---|
| 881 | | - if (serial_paranoia_check(info, tty->name, "rs_write_room")) |
|---|
| 882 | | - return 0; |
|---|
| 883 | 834 | return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); |
|---|
| 884 | 835 | } |
|---|
| 885 | 836 | |
|---|
| .. | .. |
|---|
| 887 | 838 | { |
|---|
| 888 | 839 | struct serial_state *info = tty->driver_data; |
|---|
| 889 | 840 | |
|---|
| 890 | | - if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) |
|---|
| 891 | | - return 0; |
|---|
| 892 | 841 | return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); |
|---|
| 893 | 842 | } |
|---|
| 894 | 843 | |
|---|
| .. | .. |
|---|
| 897 | 846 | struct serial_state *info = tty->driver_data; |
|---|
| 898 | 847 | unsigned long flags; |
|---|
| 899 | 848 | |
|---|
| 900 | | - if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) |
|---|
| 901 | | - return; |
|---|
| 902 | 849 | local_irq_save(flags); |
|---|
| 903 | 850 | info->xmit.head = info->xmit.tail = 0; |
|---|
| 904 | 851 | local_irq_restore(flags); |
|---|
| .. | .. |
|---|
| 913 | 860 | { |
|---|
| 914 | 861 | struct serial_state *info = tty->driver_data; |
|---|
| 915 | 862 | unsigned long flags; |
|---|
| 916 | | - |
|---|
| 917 | | - if (serial_paranoia_check(info, tty->name, "rs_send_xchar")) |
|---|
| 918 | | - return; |
|---|
| 919 | 863 | |
|---|
| 920 | 864 | info->x_char = ch; |
|---|
| 921 | 865 | if (ch) { |
|---|
| .. | .. |
|---|
| 952 | 896 | printk("throttle %s ....\n", tty_name(tty)); |
|---|
| 953 | 897 | #endif |
|---|
| 954 | 898 | |
|---|
| 955 | | - if (serial_paranoia_check(info, tty->name, "rs_throttle")) |
|---|
| 956 | | - return; |
|---|
| 957 | | - |
|---|
| 958 | 899 | if (I_IXOFF(tty)) |
|---|
| 959 | 900 | rs_send_xchar(tty, STOP_CHAR(tty)); |
|---|
| 960 | 901 | |
|---|
| .. | .. |
|---|
| 973 | 914 | #ifdef SERIAL_DEBUG_THROTTLE |
|---|
| 974 | 915 | printk("unthrottle %s ....\n", tty_name(tty)); |
|---|
| 975 | 916 | #endif |
|---|
| 976 | | - |
|---|
| 977 | | - if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) |
|---|
| 978 | | - return; |
|---|
| 979 | 917 | |
|---|
| 980 | 918 | if (I_IXOFF(tty)) { |
|---|
| 981 | 919 | if (info->x_char) |
|---|
| .. | .. |
|---|
| 996 | 934 | * ------------------------------------------------------------ |
|---|
| 997 | 935 | */ |
|---|
| 998 | 936 | |
|---|
| 999 | | -static int get_serial_info(struct tty_struct *tty, struct serial_state *state, |
|---|
| 1000 | | - struct serial_struct __user * retinfo) |
|---|
| 937 | +static int get_serial_info(struct tty_struct *tty, struct serial_struct *ss) |
|---|
| 1001 | 938 | { |
|---|
| 1002 | | - struct serial_struct tmp; |
|---|
| 1003 | | - |
|---|
| 1004 | | - memset(&tmp, 0, sizeof(tmp)); |
|---|
| 939 | + struct serial_state *state = tty->driver_data; |
|---|
| 940 | + |
|---|
| 1005 | 941 | tty_lock(tty); |
|---|
| 1006 | | - tmp.line = tty->index; |
|---|
| 1007 | | - tmp.port = state->port; |
|---|
| 1008 | | - tmp.flags = state->tport.flags; |
|---|
| 1009 | | - tmp.xmit_fifo_size = state->xmit_fifo_size; |
|---|
| 1010 | | - tmp.baud_base = state->baud_base; |
|---|
| 1011 | | - tmp.close_delay = state->tport.close_delay; |
|---|
| 1012 | | - tmp.closing_wait = state->tport.closing_wait; |
|---|
| 1013 | | - tmp.custom_divisor = state->custom_divisor; |
|---|
| 942 | + ss->line = tty->index; |
|---|
| 943 | + ss->port = state->port; |
|---|
| 944 | + ss->flags = state->tport.flags; |
|---|
| 945 | + ss->xmit_fifo_size = state->xmit_fifo_size; |
|---|
| 946 | + ss->baud_base = state->baud_base; |
|---|
| 947 | + ss->close_delay = state->tport.close_delay; |
|---|
| 948 | + ss->closing_wait = state->tport.closing_wait; |
|---|
| 949 | + ss->custom_divisor = state->custom_divisor; |
|---|
| 1014 | 950 | tty_unlock(tty); |
|---|
| 1015 | | - if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) |
|---|
| 1016 | | - return -EFAULT; |
|---|
| 1017 | 951 | return 0; |
|---|
| 1018 | 952 | } |
|---|
| 1019 | 953 | |
|---|
| 1020 | | -static int set_serial_info(struct tty_struct *tty, struct serial_state *state, |
|---|
| 1021 | | - struct serial_struct __user * new_info) |
|---|
| 954 | +static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss) |
|---|
| 1022 | 955 | { |
|---|
| 956 | + struct serial_state *state = tty->driver_data; |
|---|
| 1023 | 957 | struct tty_port *port = &state->tport; |
|---|
| 1024 | | - struct serial_struct new_serial; |
|---|
| 1025 | 958 | bool change_spd; |
|---|
| 1026 | 959 | int retval = 0; |
|---|
| 1027 | 960 | |
|---|
| 1028 | | - if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) |
|---|
| 1029 | | - return -EFAULT; |
|---|
| 1030 | | - |
|---|
| 1031 | 961 | tty_lock(tty); |
|---|
| 1032 | | - change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) || |
|---|
| 1033 | | - new_serial.custom_divisor != state->custom_divisor; |
|---|
| 1034 | | - if (new_serial.irq || new_serial.port != state->port || |
|---|
| 1035 | | - new_serial.xmit_fifo_size != state->xmit_fifo_size) { |
|---|
| 962 | + change_spd = ((ss->flags ^ port->flags) & ASYNC_SPD_MASK) || |
|---|
| 963 | + ss->custom_divisor != state->custom_divisor; |
|---|
| 964 | + if (ss->irq || ss->port != state->port || |
|---|
| 965 | + ss->xmit_fifo_size != state->xmit_fifo_size) { |
|---|
| 1036 | 966 | tty_unlock(tty); |
|---|
| 1037 | 967 | return -EINVAL; |
|---|
| 1038 | 968 | } |
|---|
| 1039 | 969 | |
|---|
| 1040 | 970 | if (!serial_isroot()) { |
|---|
| 1041 | | - if ((new_serial.baud_base != state->baud_base) || |
|---|
| 1042 | | - (new_serial.close_delay != port->close_delay) || |
|---|
| 1043 | | - (new_serial.xmit_fifo_size != state->xmit_fifo_size) || |
|---|
| 1044 | | - ((new_serial.flags & ~ASYNC_USR_MASK) != |
|---|
| 971 | + if ((ss->baud_base != state->baud_base) || |
|---|
| 972 | + (ss->close_delay != port->close_delay) || |
|---|
| 973 | + (ss->closing_wait != port->closing_wait) || |
|---|
| 974 | + (ss->xmit_fifo_size != state->xmit_fifo_size) || |
|---|
| 975 | + ((ss->flags & ~ASYNC_USR_MASK) != |
|---|
| 1045 | 976 | (port->flags & ~ASYNC_USR_MASK))) { |
|---|
| 1046 | 977 | tty_unlock(tty); |
|---|
| 1047 | 978 | return -EPERM; |
|---|
| 1048 | 979 | } |
|---|
| 1049 | 980 | port->flags = ((port->flags & ~ASYNC_USR_MASK) | |
|---|
| 1050 | | - (new_serial.flags & ASYNC_USR_MASK)); |
|---|
| 1051 | | - state->custom_divisor = new_serial.custom_divisor; |
|---|
| 981 | + (ss->flags & ASYNC_USR_MASK)); |
|---|
| 982 | + state->custom_divisor = ss->custom_divisor; |
|---|
| 1052 | 983 | goto check_and_exit; |
|---|
| 1053 | 984 | } |
|---|
| 1054 | 985 | |
|---|
| 1055 | | - if (new_serial.baud_base < 9600) { |
|---|
| 986 | + if (ss->baud_base < 9600) { |
|---|
| 1056 | 987 | tty_unlock(tty); |
|---|
| 1057 | 988 | return -EINVAL; |
|---|
| 1058 | 989 | } |
|---|
| .. | .. |
|---|
| 1062 | 993 | * At this point, we start making changes..... |
|---|
| 1063 | 994 | */ |
|---|
| 1064 | 995 | |
|---|
| 1065 | | - state->baud_base = new_serial.baud_base; |
|---|
| 996 | + state->baud_base = ss->baud_base; |
|---|
| 1066 | 997 | port->flags = ((port->flags & ~ASYNC_FLAGS) | |
|---|
| 1067 | | - (new_serial.flags & ASYNC_FLAGS)); |
|---|
| 1068 | | - state->custom_divisor = new_serial.custom_divisor; |
|---|
| 1069 | | - port->close_delay = new_serial.close_delay * HZ/100; |
|---|
| 1070 | | - port->closing_wait = new_serial.closing_wait * HZ/100; |
|---|
| 998 | + (ss->flags & ASYNC_FLAGS)); |
|---|
| 999 | + state->custom_divisor = ss->custom_divisor; |
|---|
| 1000 | + port->close_delay = ss->close_delay * HZ/100; |
|---|
| 1001 | + port->closing_wait = ss->closing_wait * HZ/100; |
|---|
| 1071 | 1002 | port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
|---|
| 1072 | 1003 | |
|---|
| 1073 | 1004 | check_and_exit: |
|---|
| 1074 | 1005 | if (tty_port_initialized(port)) { |
|---|
| 1075 | 1006 | if (change_spd) { |
|---|
| 1076 | 1007 | /* warn about deprecation unless clearing */ |
|---|
| 1077 | | - if (new_serial.flags & ASYNC_SPD_MASK) |
|---|
| 1008 | + if (ss->flags & ASYNC_SPD_MASK) |
|---|
| 1078 | 1009 | dev_warn_ratelimited(tty->dev, "use of SPD flags is deprecated\n"); |
|---|
| 1079 | 1010 | change_speed(tty, state, NULL); |
|---|
| 1080 | 1011 | } |
|---|
| .. | .. |
|---|
| 1083 | 1014 | tty_unlock(tty); |
|---|
| 1084 | 1015 | return retval; |
|---|
| 1085 | 1016 | } |
|---|
| 1086 | | - |
|---|
| 1087 | 1017 | |
|---|
| 1088 | 1018 | /* |
|---|
| 1089 | 1019 | * get_lsr_info - get line status register info |
|---|
| .. | .. |
|---|
| 1118 | 1048 | unsigned char control, status; |
|---|
| 1119 | 1049 | unsigned long flags; |
|---|
| 1120 | 1050 | |
|---|
| 1121 | | - if (serial_paranoia_check(info, tty->name, "rs_ioctl")) |
|---|
| 1122 | | - return -ENODEV; |
|---|
| 1123 | 1051 | if (tty_io_error(tty)) |
|---|
| 1124 | 1052 | return -EIO; |
|---|
| 1125 | 1053 | |
|---|
| .. | .. |
|---|
| 1140 | 1068 | struct serial_state *info = tty->driver_data; |
|---|
| 1141 | 1069 | unsigned long flags; |
|---|
| 1142 | 1070 | |
|---|
| 1143 | | - if (serial_paranoia_check(info, tty->name, "rs_ioctl")) |
|---|
| 1144 | | - return -ENODEV; |
|---|
| 1145 | 1071 | if (tty_io_error(tty)) |
|---|
| 1146 | 1072 | return -EIO; |
|---|
| 1147 | 1073 | |
|---|
| .. | .. |
|---|
| 1164 | 1090 | */ |
|---|
| 1165 | 1091 | static int rs_break(struct tty_struct *tty, int break_state) |
|---|
| 1166 | 1092 | { |
|---|
| 1167 | | - struct serial_state *info = tty->driver_data; |
|---|
| 1168 | 1093 | unsigned long flags; |
|---|
| 1169 | | - |
|---|
| 1170 | | - if (serial_paranoia_check(info, tty->name, "rs_break")) |
|---|
| 1171 | | - return -EINVAL; |
|---|
| 1172 | 1094 | |
|---|
| 1173 | 1095 | local_irq_save(flags); |
|---|
| 1174 | 1096 | if (break_state == -1) |
|---|
| .. | .. |
|---|
| 1221 | 1143 | DEFINE_WAIT(wait); |
|---|
| 1222 | 1144 | int ret; |
|---|
| 1223 | 1145 | |
|---|
| 1224 | | - if (serial_paranoia_check(info, tty->name, "rs_ioctl")) |
|---|
| 1225 | | - return -ENODEV; |
|---|
| 1226 | | - |
|---|
| 1227 | | - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && |
|---|
| 1228 | | - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && |
|---|
| 1146 | + if ((cmd != TIOCSERCONFIG) && |
|---|
| 1229 | 1147 | (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { |
|---|
| 1230 | 1148 | if (tty_io_error(tty)) |
|---|
| 1231 | 1149 | return -EIO; |
|---|
| 1232 | 1150 | } |
|---|
| 1233 | 1151 | |
|---|
| 1234 | 1152 | switch (cmd) { |
|---|
| 1235 | | - case TIOCGSERIAL: |
|---|
| 1236 | | - return get_serial_info(tty, info, argp); |
|---|
| 1237 | | - case TIOCSSERIAL: |
|---|
| 1238 | | - return set_serial_info(tty, info, argp); |
|---|
| 1239 | 1153 | case TIOCSERCONFIG: |
|---|
| 1240 | 1154 | return 0; |
|---|
| 1241 | 1155 | |
|---|
| 1242 | 1156 | case TIOCSERGETLSR: /* Get line status register */ |
|---|
| 1243 | 1157 | return get_lsr_info(info, argp); |
|---|
| 1244 | | - |
|---|
| 1245 | | - case TIOCSERGSTRUCT: |
|---|
| 1246 | | - if (copy_to_user(argp, |
|---|
| 1247 | | - info, sizeof(struct serial_state))) |
|---|
| 1248 | | - return -EFAULT; |
|---|
| 1249 | | - return 0; |
|---|
| 1250 | 1158 | |
|---|
| 1251 | 1159 | /* |
|---|
| 1252 | 1160 | * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change |
|---|
| .. | .. |
|---|
| 1287 | 1195 | } |
|---|
| 1288 | 1196 | finish_wait(&info->tport.delta_msr_wait, &wait); |
|---|
| 1289 | 1197 | return ret; |
|---|
| 1290 | | - |
|---|
| 1291 | | - case TIOCSERGWILD: |
|---|
| 1292 | | - case TIOCSERSWILD: |
|---|
| 1293 | | - /* "setserial -W" is called in Debian boot */ |
|---|
| 1294 | | - printk ("TIOCSER?WILD ioctl obsolete, ignored.\n"); |
|---|
| 1295 | | - return 0; |
|---|
| 1296 | 1198 | |
|---|
| 1297 | 1199 | default: |
|---|
| 1298 | 1200 | return -ENOIOCTLCMD; |
|---|
| .. | .. |
|---|
| 1359 | 1261 | struct serial_state *state = tty->driver_data; |
|---|
| 1360 | 1262 | struct tty_port *port = &state->tport; |
|---|
| 1361 | 1263 | |
|---|
| 1362 | | - if (serial_paranoia_check(state, tty->name, "rs_close")) |
|---|
| 1363 | | - return; |
|---|
| 1364 | | - |
|---|
| 1365 | 1264 | if (tty_port_close_start(port, tty, filp) == 0) |
|---|
| 1366 | 1265 | return; |
|---|
| 1367 | 1266 | |
|---|
| .. | .. |
|---|
| 1404 | 1303 | struct serial_state *info = tty->driver_data; |
|---|
| 1405 | 1304 | unsigned long orig_jiffies, char_time; |
|---|
| 1406 | 1305 | int lsr; |
|---|
| 1407 | | - |
|---|
| 1408 | | - if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) |
|---|
| 1409 | | - return; |
|---|
| 1410 | 1306 | |
|---|
| 1411 | 1307 | if (info->xmit_fifo_size == 0) |
|---|
| 1412 | 1308 | return; /* Just in case.... */ |
|---|
| .. | .. |
|---|
| 1466 | 1362 | { |
|---|
| 1467 | 1363 | struct serial_state *info = tty->driver_data; |
|---|
| 1468 | 1364 | |
|---|
| 1469 | | - if (serial_paranoia_check(info, tty->name, "rs_hangup")) |
|---|
| 1470 | | - return; |
|---|
| 1471 | | - |
|---|
| 1472 | 1365 | rs_flush_buffer(tty); |
|---|
| 1473 | 1366 | shutdown(tty, info); |
|---|
| 1474 | 1367 | info->tport.count = 0; |
|---|
| .. | .. |
|---|
| 1493 | 1386 | port->tty = tty; |
|---|
| 1494 | 1387 | tty->driver_data = info; |
|---|
| 1495 | 1388 | tty->port = port; |
|---|
| 1496 | | - if (serial_paranoia_check(info, tty->name, "rs_open")) |
|---|
| 1497 | | - return -ENODEV; |
|---|
| 1498 | 1389 | |
|---|
| 1499 | 1390 | port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
|---|
| 1500 | 1391 | |
|---|
| .. | .. |
|---|
| 1607 | 1498 | .tiocmget = rs_tiocmget, |
|---|
| 1608 | 1499 | .tiocmset = rs_tiocmset, |
|---|
| 1609 | 1500 | .get_icount = rs_get_icount, |
|---|
| 1501 | + .set_serial = set_serial_info, |
|---|
| 1502 | + .get_serial = get_serial_info, |
|---|
| 1610 | 1503 | .proc_show = rs_proc_show, |
|---|
| 1611 | 1504 | }; |
|---|
| 1612 | 1505 | |
|---|