Skip to content

Commit 71e0779

Browse files
saschahauergregkh
authored andcommitted
tty: n_gsm: do not send/receive in ldisc close path
gsm_cleanup_mux() is called in the line discipline close path which is called at tty_release() time. At this stage the tty is no longer operational enough to send any frames. Sending close frames is therefore not possible and waiting for their answers always times out. This patch removes sending close messages and waiting for their answers from the tty_release path. This patch makes explicit what previously implicitly had been the case already: We are not able to tell the modem that we are about to close the multiplexer on our side. This means the modem will stay in multiplexer mode and re-establishing the multiplexer later fails. The only way for userspace to work around this is to manually send a close frame in N_TTY mode after closing the mux. Signed-off-by: Sascha Hauer <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent e279e6d commit 71e0779

File tree

2 files changed

+42
-19
lines changed

2 files changed

+42
-19
lines changed

Documentation/serial/n_gsm.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ for example, it's possible :
7777

7878
6- first close all virtual ports before closing the physical port.
7979

80+
Note that after closing the physical port the modem is still in multiplexing
81+
mode. This may prevent a successful re-opening of the port later. To avoid
82+
this situation either reset the modem if your hardware allows that or send
83+
a disconnect command frame manually before initializing the multiplexing mode
84+
for the second time. The byte sequence for the disconnect command frame is:
85+
0xf9, 0x03, 0xef, 0x03, 0xc3, 0x16, 0xf9.
86+
8087
Additional Documentation
8188
------------------------
8289
More practical details on the protocol and how it's supported by industrial

drivers/tty/n_gsm.c

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,6 +2015,33 @@ static void gsm_error(struct gsm_mux *gsm,
20152015
gsm->io_error++;
20162016
}
20172017

2018+
static int gsm_disconnect(struct gsm_mux *gsm)
2019+
{
2020+
struct gsm_dlci *dlci = gsm->dlci[0];
2021+
struct gsm_control *gc;
2022+
2023+
if (!dlci)
2024+
return 0;
2025+
2026+
/* In theory disconnecting DLCI 0 is sufficient but for some
2027+
modems this is apparently not the case. */
2028+
gc = gsm_control_send(gsm, CMD_CLD, NULL, 0);
2029+
if (gc)
2030+
gsm_control_wait(gsm, gc);
2031+
2032+
del_timer_sync(&gsm->t2_timer);
2033+
/* Now we are sure T2 has stopped */
2034+
2035+
gsm_dlci_begin_close(dlci);
2036+
wait_event_interruptible(gsm->event,
2037+
dlci->state == DLCI_CLOSED);
2038+
2039+
if (signal_pending(current))
2040+
return -EINTR;
2041+
2042+
return 0;
2043+
}
2044+
20182045
/**
20192046
* gsm_cleanup_mux - generic GSM protocol cleanup
20202047
* @gsm: our mux
@@ -2029,7 +2056,6 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm)
20292056
int i;
20302057
struct gsm_dlci *dlci = gsm->dlci[0];
20312058
struct gsm_msg *txq, *ntxq;
2032-
struct gsm_control *gc;
20332059

20342060
gsm->dead = 1;
20352061

@@ -2045,21 +2071,11 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm)
20452071
if (i == MAX_MUX)
20462072
return;
20472073

2048-
/* In theory disconnecting DLCI 0 is sufficient but for some
2049-
modems this is apparently not the case. */
2050-
if (dlci) {
2051-
gc = gsm_control_send(gsm, CMD_CLD, NULL, 0);
2052-
if (gc)
2053-
gsm_control_wait(gsm, gc);
2054-
}
20552074
del_timer_sync(&gsm->t2_timer);
20562075
/* Now we are sure T2 has stopped */
2057-
if (dlci) {
2076+
if (dlci)
20582077
dlci->dead = 1;
2059-
gsm_dlci_begin_close(dlci);
2060-
wait_event_interruptible(gsm->event,
2061-
dlci->state == DLCI_CLOSED);
2062-
}
2078+
20632079
/* Free up any link layer users */
20642080
mutex_lock(&gsm->mutex);
20652081
for (i = 0; i < NUM_DLCI; i++)
@@ -2519,12 +2535,12 @@ static int gsmld_config(struct tty_struct *tty, struct gsm_mux *gsm,
25192535
*/
25202536

25212537
if (need_close || need_restart) {
2522-
gsm_dlci_begin_close(gsm->dlci[0]);
2523-
/* This will timeout if the link is down due to N2 expiring */
2524-
wait_event_interruptible(gsm->event,
2525-
gsm->dlci[0]->state == DLCI_CLOSED);
2526-
if (signal_pending(current))
2527-
return -EINTR;
2538+
int ret;
2539+
2540+
ret = gsm_disconnect(gsm);
2541+
2542+
if (ret)
2543+
return ret;
25282544
}
25292545
if (need_restart)
25302546
gsm_cleanup_mux(gsm);

0 commit comments

Comments
 (0)