aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-11-25 18:30:21 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-11-25 18:30:21 -0800
commitc42b4e6501cdaabee8cc292ae1ef0f66bf4825c1 (patch)
tree8ae9c4f0881891459107a226968a65a265b34134
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>
-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)
dlci->state == DLCI_CLOSED);
}
/* Free up any link layer users */
- spin_lock(&gsm->lock);
for (i = 0; i < NUM_DLCI; i++)
if (gsm->dlci[i])
gsm_dlci_release(gsm->dlci[i]);
- spin_unlock(&gsm->lock);
/* Now wipe the queues */
list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list)
kfree(txq);
@@ -2911,33 +2909,23 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)
This is ok from a locking
perspective as we don't have to worry about this
if DLCI0 is lost */
- spin_lock(&gsm->lock);
- if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) {
- spin_unlock(&gsm->lock);
+ if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN)
return -EL2NSYNC;
- }
dlci = gsm->dlci[line];
if (dlci == NULL) {
alloc = true;
dlci = gsm_dlci_alloc(gsm, line);
}
- if (dlci == NULL) {
- spin_unlock(&gsm->lock);
+ if (dlci == NULL)
return -ENOMEM;
- }
ret = tty_port_install(&dlci->port, driver, tty);
if (ret) {
if (alloc)
dlci_put(dlci);
- spin_unlock(&gsm->lock);
return ret;
}
- dlci_get(dlci);
- dlci_get(gsm->dlci[0]);
- mux_get(gsm);
tty->driver_data = dlci;
- spin_unlock(&gsm->lock);
return 0;
}
@@ -2948,6 +2936,9 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)
struct tty_port *port = &dlci->port;
port->count++;
+ dlci_get(dlci);
+ dlci_get(dlci->gsm->dlci[0]);
+ mux_get(dlci->gsm);
tty_port_tty_set(port, tty);
dlci->modem_rx = 0;
@@ -2974,7 +2965,7 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp)
mutex_unlock(&dlci->mutex);
gsm = dlci->gsm;
if (tty_port_close_start(&dlci->port, tty, filp) == 0)
- return;
+ goto out;
gsm_dlci_begin_close(dlci);
if (test_bit(ASYNCB_INITIALIZED, &dlci->port.flags)) {
if (C_HUPCL(tty))
@@ -2982,7 +2973,10 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp)
}
tty_port_close_end(&dlci->port, tty);
tty_port_tty_set(&dlci->port, NULL);
- return;
+out:
+ dlci_put(dlci);
+ dlci_put(gsm->dlci[0]);
+ mux_put(gsm);
}
static void gsmtty_hangup(struct tty_struct *tty)
@@ -3159,16 +3153,6 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state)
return gsmtty_modem_update(dlci, encode);
}
-static void gsmtty_remove(struct tty_driver *driver, struct tty_struct *tty)
-{
- struct gsm_dlci *dlci = tty->driver_data;
- struct gsm_mux *gsm = dlci->gsm;
-
- dlci_put(dlci);
- dlci_put(gsm->dlci[0]);
- mux_put(gsm);
- driver->ttys[tty->index] = NULL;
-}
/* Virtual ttys for the demux */
static const struct tty_operations gsmtty_ops = {
@@ -3188,7 +3172,6 @@ static const struct tty_operations gsmtty_ops = {
.tiocmget = gsmtty_tiocmget,
.tiocmset = gsmtty_tiocmset,
.break_ctl = gsmtty_break_ctl,
- .remove = gsmtty_remove,
};