diff options
Diffstat (limited to 'drivers/tty/n_gsm.c')
-rw-r--r-- | drivers/tty/n_gsm.c | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index e0f80ce0cf8f..4a43ef5d7962 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c | |||
@@ -1689,6 +1689,8 @@ static inline void dlci_put(struct gsm_dlci *dlci) | |||
1689 | tty_port_put(&dlci->port); | 1689 | tty_port_put(&dlci->port); |
1690 | } | 1690 | } |
1691 | 1691 | ||
1692 | static void gsm_destroy_network(struct gsm_dlci *dlci); | ||
1693 | |||
1692 | /** | 1694 | /** |
1693 | * gsm_dlci_release - release DLCI | 1695 | * gsm_dlci_release - release DLCI |
1694 | * @dlci: DLCI to destroy | 1696 | * @dlci: DLCI to destroy |
@@ -1702,9 +1704,19 @@ static void gsm_dlci_release(struct gsm_dlci *dlci) | |||
1702 | { | 1704 | { |
1703 | struct tty_struct *tty = tty_port_tty_get(&dlci->port); | 1705 | struct tty_struct *tty = tty_port_tty_get(&dlci->port); |
1704 | if (tty) { | 1706 | if (tty) { |
1707 | mutex_lock(&dlci->mutex); | ||
1708 | gsm_destroy_network(dlci); | ||
1709 | mutex_unlock(&dlci->mutex); | ||
1710 | |||
1711 | /* tty_vhangup needs the tty_lock, so unlock and | ||
1712 | relock after doing the hangup. */ | ||
1713 | tty_unlock(tty); | ||
1705 | tty_vhangup(tty); | 1714 | tty_vhangup(tty); |
1715 | tty_lock(tty); | ||
1716 | tty_port_tty_set(&dlci->port, NULL); | ||
1706 | tty_kref_put(tty); | 1717 | tty_kref_put(tty); |
1707 | } | 1718 | } |
1719 | dlci->state = DLCI_CLOSED; | ||
1708 | dlci_put(dlci); | 1720 | dlci_put(dlci); |
1709 | } | 1721 | } |
1710 | 1722 | ||
@@ -2947,6 +2959,8 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp) | |||
2947 | 2959 | ||
2948 | if (dlci == NULL) | 2960 | if (dlci == NULL) |
2949 | return; | 2961 | return; |
2962 | if (dlci->state == DLCI_CLOSED) | ||
2963 | return; | ||
2950 | mutex_lock(&dlci->mutex); | 2964 | mutex_lock(&dlci->mutex); |
2951 | gsm_destroy_network(dlci); | 2965 | gsm_destroy_network(dlci); |
2952 | mutex_unlock(&dlci->mutex); | 2966 | mutex_unlock(&dlci->mutex); |
@@ -2965,6 +2979,8 @@ out: | |||
2965 | static void gsmtty_hangup(struct tty_struct *tty) | 2979 | static void gsmtty_hangup(struct tty_struct *tty) |
2966 | { | 2980 | { |
2967 | struct gsm_dlci *dlci = tty->driver_data; | 2981 | struct gsm_dlci *dlci = tty->driver_data; |
2982 | if (dlci->state == DLCI_CLOSED) | ||
2983 | return; | ||
2968 | tty_port_hangup(&dlci->port); | 2984 | tty_port_hangup(&dlci->port); |
2969 | gsm_dlci_begin_close(dlci); | 2985 | gsm_dlci_begin_close(dlci); |
2970 | } | 2986 | } |
@@ -2972,9 +2988,12 @@ static void gsmtty_hangup(struct tty_struct *tty) | |||
2972 | static int gsmtty_write(struct tty_struct *tty, const unsigned char *buf, | 2988 | static int gsmtty_write(struct tty_struct *tty, const unsigned char *buf, |
2973 | int len) | 2989 | int len) |
2974 | { | 2990 | { |
2991 | int sent; | ||
2975 | struct gsm_dlci *dlci = tty->driver_data; | 2992 | struct gsm_dlci *dlci = tty->driver_data; |
2993 | if (dlci->state == DLCI_CLOSED) | ||
2994 | return -EINVAL; | ||
2976 | /* Stuff the bytes into the fifo queue */ | 2995 | /* Stuff the bytes into the fifo queue */ |
2977 | int sent = kfifo_in_locked(dlci->fifo, buf, len, &dlci->lock); | 2996 | sent = kfifo_in_locked(dlci->fifo, buf, len, &dlci->lock); |
2978 | /* Need to kick the channel */ | 2997 | /* Need to kick the channel */ |
2979 | gsm_dlci_data_kick(dlci); | 2998 | gsm_dlci_data_kick(dlci); |
2980 | return sent; | 2999 | return sent; |
@@ -2983,18 +3002,24 @@ static int gsmtty_write(struct tty_struct *tty, const unsigned char *buf, | |||
2983 | static int gsmtty_write_room(struct tty_struct *tty) | 3002 | static int gsmtty_write_room(struct tty_struct *tty) |
2984 | { | 3003 | { |
2985 | struct gsm_dlci *dlci = tty->driver_data; | 3004 | struct gsm_dlci *dlci = tty->driver_data; |
3005 | if (dlci->state == DLCI_CLOSED) | ||
3006 | return -EINVAL; | ||
2986 | return TX_SIZE - kfifo_len(dlci->fifo); | 3007 | return TX_SIZE - kfifo_len(dlci->fifo); |
2987 | } | 3008 | } |
2988 | 3009 | ||
2989 | static int gsmtty_chars_in_buffer(struct tty_struct *tty) | 3010 | static int gsmtty_chars_in_buffer(struct tty_struct *tty) |
2990 | { | 3011 | { |
2991 | struct gsm_dlci *dlci = tty->driver_data; | 3012 | struct gsm_dlci *dlci = tty->driver_data; |
3013 | if (dlci->state == DLCI_CLOSED) | ||
3014 | return -EINVAL; | ||
2992 | return kfifo_len(dlci->fifo); | 3015 | return kfifo_len(dlci->fifo); |
2993 | } | 3016 | } |
2994 | 3017 | ||
2995 | static void gsmtty_flush_buffer(struct tty_struct *tty) | 3018 | static void gsmtty_flush_buffer(struct tty_struct *tty) |
2996 | { | 3019 | { |
2997 | struct gsm_dlci *dlci = tty->driver_data; | 3020 | struct gsm_dlci *dlci = tty->driver_data; |
3021 | if (dlci->state == DLCI_CLOSED) | ||
3022 | return; | ||
2998 | /* Caution needed: If we implement reliable transport classes | 3023 | /* Caution needed: If we implement reliable transport classes |
2999 | then the data being transmitted can't simply be junked once | 3024 | then the data being transmitted can't simply be junked once |
3000 | it has first hit the stack. Until then we can just blow it | 3025 | it has first hit the stack. Until then we can just blow it |
@@ -3013,6 +3038,8 @@ static void gsmtty_wait_until_sent(struct tty_struct *tty, int timeout) | |||
3013 | static int gsmtty_tiocmget(struct tty_struct *tty) | 3038 | static int gsmtty_tiocmget(struct tty_struct *tty) |
3014 | { | 3039 | { |
3015 | struct gsm_dlci *dlci = tty->driver_data; | 3040 | struct gsm_dlci *dlci = tty->driver_data; |
3041 | if (dlci->state == DLCI_CLOSED) | ||
3042 | return -EINVAL; | ||
3016 | return dlci->modem_rx; | 3043 | return dlci->modem_rx; |
3017 | } | 3044 | } |
3018 | 3045 | ||
@@ -3022,6 +3049,8 @@ static int gsmtty_tiocmset(struct tty_struct *tty, | |||
3022 | struct gsm_dlci *dlci = tty->driver_data; | 3049 | struct gsm_dlci *dlci = tty->driver_data; |
3023 | unsigned int modem_tx = dlci->modem_tx; | 3050 | unsigned int modem_tx = dlci->modem_tx; |
3024 | 3051 | ||
3052 | if (dlci->state == DLCI_CLOSED) | ||
3053 | return -EINVAL; | ||
3025 | modem_tx &= ~clear; | 3054 | modem_tx &= ~clear; |
3026 | modem_tx |= set; | 3055 | modem_tx |= set; |
3027 | 3056 | ||
@@ -3040,6 +3069,8 @@ static int gsmtty_ioctl(struct tty_struct *tty, | |||
3040 | struct gsm_netconfig nc; | 3069 | struct gsm_netconfig nc; |
3041 | int index; | 3070 | int index; |
3042 | 3071 | ||
3072 | if (dlci->state == DLCI_CLOSED) | ||
3073 | return -EINVAL; | ||
3043 | switch (cmd) { | 3074 | switch (cmd) { |
3044 | case GSMIOC_ENABLE_NET: | 3075 | case GSMIOC_ENABLE_NET: |
3045 | if (copy_from_user(&nc, (void __user *)arg, sizeof(nc))) | 3076 | if (copy_from_user(&nc, (void __user *)arg, sizeof(nc))) |
@@ -3066,6 +3097,9 @@ static int gsmtty_ioctl(struct tty_struct *tty, | |||
3066 | 3097 | ||
3067 | static void gsmtty_set_termios(struct tty_struct *tty, struct ktermios *old) | 3098 | static void gsmtty_set_termios(struct tty_struct *tty, struct ktermios *old) |
3068 | { | 3099 | { |
3100 | struct gsm_dlci *dlci = tty->driver_data; | ||
3101 | if (dlci->state == DLCI_CLOSED) | ||
3102 | return; | ||
3069 | /* For the moment its fixed. In actual fact the speed information | 3103 | /* For the moment its fixed. In actual fact the speed information |
3070 | for the virtual channel can be propogated in both directions by | 3104 | for the virtual channel can be propogated in both directions by |
3071 | the RPN control message. This however rapidly gets nasty as we | 3105 | the RPN control message. This however rapidly gets nasty as we |
@@ -3077,6 +3111,8 @@ static void gsmtty_set_termios(struct tty_struct *tty, struct ktermios *old) | |||
3077 | static void gsmtty_throttle(struct tty_struct *tty) | 3111 | static void gsmtty_throttle(struct tty_struct *tty) |
3078 | { | 3112 | { |
3079 | struct gsm_dlci *dlci = tty->driver_data; | 3113 | struct gsm_dlci *dlci = tty->driver_data; |
3114 | if (dlci->state == DLCI_CLOSED) | ||
3115 | return; | ||
3080 | if (tty->termios.c_cflag & CRTSCTS) | 3116 | if (tty->termios.c_cflag & CRTSCTS) |
3081 | dlci->modem_tx &= ~TIOCM_DTR; | 3117 | dlci->modem_tx &= ~TIOCM_DTR; |
3082 | dlci->throttled = 1; | 3118 | dlci->throttled = 1; |
@@ -3087,6 +3123,8 @@ static void gsmtty_throttle(struct tty_struct *tty) | |||
3087 | static void gsmtty_unthrottle(struct tty_struct *tty) | 3123 | static void gsmtty_unthrottle(struct tty_struct *tty) |
3088 | { | 3124 | { |
3089 | struct gsm_dlci *dlci = tty->driver_data; | 3125 | struct gsm_dlci *dlci = tty->driver_data; |
3126 | if (dlci->state == DLCI_CLOSED) | ||
3127 | return; | ||
3090 | if (tty->termios.c_cflag & CRTSCTS) | 3128 | if (tty->termios.c_cflag & CRTSCTS) |
3091 | dlci->modem_tx |= TIOCM_DTR; | 3129 | dlci->modem_tx |= TIOCM_DTR; |
3092 | dlci->throttled = 0; | 3130 | dlci->throttled = 0; |
@@ -3098,6 +3136,8 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state) | |||
3098 | { | 3136 | { |
3099 | struct gsm_dlci *dlci = tty->driver_data; | 3137 | struct gsm_dlci *dlci = tty->driver_data; |
3100 | int encode = 0; /* Off */ | 3138 | int encode = 0; /* Off */ |
3139 | if (dlci->state == DLCI_CLOSED) | ||
3140 | return -EINVAL; | ||
3101 | 3141 | ||
3102 | if (state == -1) /* "On indefinitely" - we can't encode this | 3142 | if (state == -1) /* "On indefinitely" - we can't encode this |
3103 | properly */ | 3143 | properly */ |