aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/n_gsm.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-11-25 21:30:21 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-11-25 21:30:21 -0500
commitc42b4e6501cdaabee8cc292ae1ef0f66bf4825c1 (patch)
tree8ae9c4f0881891459107a226968a65a265b34134 /drivers/tty/n_gsm.c
parentaebf045382edb32bd763d8edea02a559e7dc41e9 (diff)
Revert "n_gsm: race between ld close and gsmtty open"
This reverts commit c284ee2cf12b55fa8496b2d098bf0938688f1c1c. Turns out the locking was incorrect. Reported-by: Fengguang Wu <fengguang.wu@intel.com> Cc: Chao Bi <chao.bi@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/n_gsm.c')
-rw-r--r--drivers/tty/n_gsm.c37
1 files changed, 10 insertions, 27 deletions
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 069bfd654485..c0f76da55304 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -2054,11 +2054,9 @@ void gsm_cleanup_mux(struct gsm_mux *gsm)
2054 dlci->state == DLCI_CLOSED); 2054 dlci->state == DLCI_CLOSED);
2055 } 2055 }
2056 /* Free up any link layer users */ 2056 /* Free up any link layer users */
2057 spin_lock(&gsm->lock);
2058 for (i = 0; i < NUM_DLCI; i++) 2057 for (i = 0; i < NUM_DLCI; i++)
2059 if (gsm->dlci[i]) 2058 if (gsm->dlci[i])
2060 gsm_dlci_release(gsm->dlci[i]); 2059 gsm_dlci_release(gsm->dlci[i]);
2061 spin_unlock(&gsm->lock);
2062 /* Now wipe the queues */ 2060 /* Now wipe the queues */
2063 list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list) 2061 list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list)
2064 kfree(txq); 2062 kfree(txq);
@@ -2911,33 +2909,23 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)
2911 This is ok from a locking 2909 This is ok from a locking
2912 perspective as we don't have to worry about this 2910 perspective as we don't have to worry about this
2913 if DLCI0 is lost */ 2911 if DLCI0 is lost */
2914 spin_lock(&gsm->lock); 2912 if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN)
2915 if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) {
2916 spin_unlock(&gsm->lock);
2917 return -EL2NSYNC; 2913 return -EL2NSYNC;
2918 }
2919 dlci = gsm->dlci[line]; 2914 dlci = gsm->dlci[line];
2920 if (dlci == NULL) { 2915 if (dlci == NULL) {
2921 alloc = true; 2916 alloc = true;
2922 dlci = gsm_dlci_alloc(gsm, line); 2917 dlci = gsm_dlci_alloc(gsm, line);
2923 } 2918 }
2924 if (dlci == NULL) { 2919 if (dlci == NULL)
2925 spin_unlock(&gsm->lock);
2926 return -ENOMEM; 2920 return -ENOMEM;
2927 }
2928 ret = tty_port_install(&dlci->port, driver, tty); 2921 ret = tty_port_install(&dlci->port, driver, tty);
2929 if (ret) { 2922 if (ret) {
2930 if (alloc) 2923 if (alloc)
2931 dlci_put(dlci); 2924 dlci_put(dlci);
2932 spin_unlock(&gsm->lock);
2933 return ret; 2925 return ret;
2934 } 2926 }
2935 2927
2936 dlci_get(dlci);
2937 dlci_get(gsm->dlci[0]);
2938 mux_get(gsm);
2939 tty->driver_data = dlci; 2928 tty->driver_data = dlci;
2940 spin_unlock(&gsm->lock);
2941 2929
2942 return 0; 2930 return 0;
2943} 2931}
@@ -2948,6 +2936,9 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)
2948 struct tty_port *port = &dlci->port; 2936 struct tty_port *port = &dlci->port;
2949 2937
2950 port->count++; 2938 port->count++;
2939 dlci_get(dlci);
2940 dlci_get(dlci->gsm->dlci[0]);
2941 mux_get(dlci->gsm);
2951 tty_port_tty_set(port, tty); 2942 tty_port_tty_set(port, tty);
2952 2943
2953 dlci->modem_rx = 0; 2944 dlci->modem_rx = 0;
@@ -2974,7 +2965,7 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp)
2974 mutex_unlock(&dlci->mutex); 2965 mutex_unlock(&dlci->mutex);
2975 gsm = dlci->gsm; 2966 gsm = dlci->gsm;
2976 if (tty_port_close_start(&dlci->port, tty, filp) == 0) 2967 if (tty_port_close_start(&dlci->port, tty, filp) == 0)
2977 return; 2968 goto out;
2978 gsm_dlci_begin_close(dlci); 2969 gsm_dlci_begin_close(dlci);
2979 if (test_bit(ASYNCB_INITIALIZED, &dlci->port.flags)) { 2970 if (test_bit(ASYNCB_INITIALIZED, &dlci->port.flags)) {
2980 if (C_HUPCL(tty)) 2971 if (C_HUPCL(tty))
@@ -2982,7 +2973,10 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp)
2982 } 2973 }
2983 tty_port_close_end(&dlci->port, tty); 2974 tty_port_close_end(&dlci->port, tty);
2984 tty_port_tty_set(&dlci->port, NULL); 2975 tty_port_tty_set(&dlci->port, NULL);
2985 return; 2976out:
2977 dlci_put(dlci);
2978 dlci_put(gsm->dlci[0]);
2979 mux_put(gsm);
2986} 2980}
2987 2981
2988static void gsmtty_hangup(struct tty_struct *tty) 2982static void gsmtty_hangup(struct tty_struct *tty)
@@ -3159,16 +3153,6 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state)
3159 return gsmtty_modem_update(dlci, encode); 3153 return gsmtty_modem_update(dlci, encode);
3160} 3154}
3161 3155
3162static void gsmtty_remove(struct tty_driver *driver, struct tty_struct *tty)
3163{
3164 struct gsm_dlci *dlci = tty->driver_data;
3165 struct gsm_mux *gsm = dlci->gsm;
3166
3167 dlci_put(dlci);
3168 dlci_put(gsm->dlci[0]);
3169 mux_put(gsm);
3170 driver->ttys[tty->index] = NULL;
3171}
3172 3156
3173/* Virtual ttys for the demux */ 3157/* Virtual ttys for the demux */
3174static const struct tty_operations gsmtty_ops = { 3158static const struct tty_operations gsmtty_ops = {
@@ -3188,7 +3172,6 @@ static const struct tty_operations gsmtty_ops = {
3188 .tiocmget = gsmtty_tiocmget, 3172 .tiocmget = gsmtty_tiocmget,
3189 .tiocmset = gsmtty_tiocmset, 3173 .tiocmset = gsmtty_tiocmset,
3190 .break_ctl = gsmtty_break_ctl, 3174 .break_ctl = gsmtty_break_ctl,
3191 .remove = gsmtty_remove,
3192}; 3175};
3193 3176
3194 3177