Skip to content

Commit e2e4025

Browse files
freemangordongregkh
authored andcommitted
tty: n_gsm: wait until channel 0 is ready
Currently code does not wait for channel 0 open sequence to complete before pushing data to the other channels. Also, if userland opens tty, it will receive EL2NSYNC. Both issues result in hard to predict initialization sequence and possible userland failures. Fix that by waiting channel 0 open sequence to complete before attempting opening of the other channels. Also, if tty open() is attempted while channel 0 is opening, wait until sequence is complete before returning to userland. Signed-off-by: Ivaylo Dimitrov <[email protected]> Signed-off-by: Tony Lindgren <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent d78a899 commit e2e4025

File tree

1 file changed

+23
-8
lines changed

1 file changed

+23
-8
lines changed

drivers/tty/n_gsm.c

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2244,13 +2244,16 @@ static void gsm_dlci_t1(struct timer_list *t)
22442244
break;
22452245
case DLCI_OPENING:
22462246
if (dlci->retries) {
2247-
dlci->retries--;
2248-
gsm_command(dlci->gsm, dlci->addr, SABM|PF);
2247+
if (!dlci->addr || !gsm->dlci[0] ||
2248+
gsm->dlci[0]->state != DLCI_OPENING) {
2249+
dlci->retries--;
2250+
gsm_command(dlci->gsm, dlci->addr, SABM|PF);
2251+
}
2252+
22492253
mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100);
22502254
} else if (!dlci->addr && gsm->control == (DM | PF)) {
22512255
if (debug & DBG_ERRORS)
2252-
pr_info("DLCI %d opening in ADM mode.\n",
2253-
dlci->addr);
2256+
pr_info("DLCI 0 opening in ADM mode.\n");
22542257
dlci->mode = DLCI_MODE_ADM;
22552258
gsm_dlci_open(dlci);
22562259
} else {
@@ -2308,7 +2311,9 @@ static void gsm_dlci_begin_open(struct gsm_dlci *dlci)
23082311
dlci->retries = gsm->n2;
23092312
if (!need_pn) {
23102313
dlci->state = DLCI_OPENING;
2311-
gsm_command(gsm, dlci->addr, SABM|PF);
2314+
if (!dlci->addr || !gsm->dlci[0] ||
2315+
gsm->dlci[0]->state != DLCI_OPENING)
2316+
gsm_command(gsm, dlci->addr, SABM|PF);
23122317
} else {
23132318
/* Configure DLCI before setup */
23142319
dlci->state = DLCI_CONFIGURE;
@@ -4251,7 +4256,7 @@ static const struct tty_port_operations gsm_port_ops = {
42514256
static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)
42524257
{
42534258
struct gsm_mux *gsm;
4254-
struct gsm_dlci *dlci;
4259+
struct gsm_dlci *dlci, *dlci0;
42554260
unsigned int line = tty->index;
42564261
unsigned int mux = mux_line_to_num(line);
42574262
bool alloc = false;
@@ -4274,10 +4279,20 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)
42744279
perspective as we don't have to worry about this
42754280
if DLCI0 is lost */
42764281
mutex_lock(&gsm->mutex);
4277-
if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) {
4282+
4283+
dlci0 = gsm->dlci[0];
4284+
if (dlci0 && dlci0->state != DLCI_OPEN) {
42784285
mutex_unlock(&gsm->mutex);
4279-
return -EL2NSYNC;
4286+
4287+
if (dlci0->state == DLCI_OPENING)
4288+
wait_event(gsm->event, dlci0->state != DLCI_OPENING);
4289+
4290+
if (dlci0->state != DLCI_OPEN)
4291+
return -EL2NSYNC;
4292+
4293+
mutex_lock(&gsm->mutex);
42804294
}
4295+
42814296
dlci = gsm->dlci[line];
42824297
if (dlci == NULL) {
42834298
alloc = true;

0 commit comments

Comments
 (0)