Revert "n_gsm: race between ld close and gsmtty open"
This reverts commit c284ee2cf1
. 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>
This commit is contained in:
parent
aebf045382
commit
c42b4e6501
@ -2054,11 +2054,9 @@ void gsm_cleanup_mux(struct gsm_mux *gsm)
|
|||||||
dlci->state == DLCI_CLOSED);
|
dlci->state == DLCI_CLOSED);
|
||||||
}
|
}
|
||||||
/* Free up any link layer users */
|
/* Free up any link layer users */
|
||||||
spin_lock(&gsm->lock);
|
|
||||||
for (i = 0; i < NUM_DLCI; i++)
|
for (i = 0; i < NUM_DLCI; i++)
|
||||||
if (gsm->dlci[i])
|
if (gsm->dlci[i])
|
||||||
gsm_dlci_release(gsm->dlci[i]);
|
gsm_dlci_release(gsm->dlci[i]);
|
||||||
spin_unlock(&gsm->lock);
|
|
||||||
/* Now wipe the queues */
|
/* Now wipe the queues */
|
||||||
list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list)
|
list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list)
|
||||||
kfree(txq);
|
kfree(txq);
|
||||||
@ -2911,33 +2909,23 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)
|
|||||||
This is ok from a locking
|
This is ok from a locking
|
||||||
perspective as we don't have to worry about this
|
perspective as we don't have to worry about this
|
||||||
if DLCI0 is lost */
|
if DLCI0 is lost */
|
||||||
spin_lock(&gsm->lock);
|
if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN)
|
||||||
if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) {
|
|
||||||
spin_unlock(&gsm->lock);
|
|
||||||
return -EL2NSYNC;
|
return -EL2NSYNC;
|
||||||
}
|
|
||||||
dlci = gsm->dlci[line];
|
dlci = gsm->dlci[line];
|
||||||
if (dlci == NULL) {
|
if (dlci == NULL) {
|
||||||
alloc = true;
|
alloc = true;
|
||||||
dlci = gsm_dlci_alloc(gsm, line);
|
dlci = gsm_dlci_alloc(gsm, line);
|
||||||
}
|
}
|
||||||
if (dlci == NULL) {
|
if (dlci == NULL)
|
||||||
spin_unlock(&gsm->lock);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
ret = tty_port_install(&dlci->port, driver, tty);
|
ret = tty_port_install(&dlci->port, driver, tty);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (alloc)
|
if (alloc)
|
||||||
dlci_put(dlci);
|
dlci_put(dlci);
|
||||||
spin_unlock(&gsm->lock);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
dlci_get(dlci);
|
|
||||||
dlci_get(gsm->dlci[0]);
|
|
||||||
mux_get(gsm);
|
|
||||||
tty->driver_data = dlci;
|
tty->driver_data = dlci;
|
||||||
spin_unlock(&gsm->lock);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2948,6 +2936,9 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)
|
|||||||
struct tty_port *port = &dlci->port;
|
struct tty_port *port = &dlci->port;
|
||||||
|
|
||||||
port->count++;
|
port->count++;
|
||||||
|
dlci_get(dlci);
|
||||||
|
dlci_get(dlci->gsm->dlci[0]);
|
||||||
|
mux_get(dlci->gsm);
|
||||||
tty_port_tty_set(port, tty);
|
tty_port_tty_set(port, tty);
|
||||||
|
|
||||||
dlci->modem_rx = 0;
|
dlci->modem_rx = 0;
|
||||||
@ -2974,7 +2965,7 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp)
|
|||||||
mutex_unlock(&dlci->mutex);
|
mutex_unlock(&dlci->mutex);
|
||||||
gsm = dlci->gsm;
|
gsm = dlci->gsm;
|
||||||
if (tty_port_close_start(&dlci->port, tty, filp) == 0)
|
if (tty_port_close_start(&dlci->port, tty, filp) == 0)
|
||||||
return;
|
goto out;
|
||||||
gsm_dlci_begin_close(dlci);
|
gsm_dlci_begin_close(dlci);
|
||||||
if (test_bit(ASYNCB_INITIALIZED, &dlci->port.flags)) {
|
if (test_bit(ASYNCB_INITIALIZED, &dlci->port.flags)) {
|
||||||
if (C_HUPCL(tty))
|
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_close_end(&dlci->port, tty);
|
||||||
tty_port_tty_set(&dlci->port, NULL);
|
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)
|
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);
|
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 */
|
/* Virtual ttys for the demux */
|
||||||
static const struct tty_operations gsmtty_ops = {
|
static const struct tty_operations gsmtty_ops = {
|
||||||
@ -3188,7 +3172,6 @@ static const struct tty_operations gsmtty_ops = {
|
|||||||
.tiocmget = gsmtty_tiocmget,
|
.tiocmget = gsmtty_tiocmget,
|
||||||
.tiocmset = gsmtty_tiocmset,
|
.tiocmset = gsmtty_tiocmset,
|
||||||
.break_ctl = gsmtty_break_ctl,
|
.break_ctl = gsmtty_break_ctl,
|
||||||
.remove = gsmtty_remove,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user