From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DC8DD5012B5; Tue, 13 Oct 2026 12:45:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791895527; cv=none; b=uhUPiBc7GcR0Bc0fWv9Py6eZWoxb3sXtWl+Shul8rn8jZofrS/T6VIJrrBfT8qi1eQ93DC4KZcRcF6KlEyK6D4CC1WTgf1dxwjZAA18swnxNwJdSze4WtRwSKpKpQxcFCUuA9nDmeUAEs6vRJaS9ZOa+1rq4CRNuywM8iG4Rwj0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791895527; c=relaxed/simple; bh=0ULH/a3FfptyJqoAXX+Am2U4RAIojA2xWF8f7S3/+8g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=b2wGZX5ru+tOnpPzR2Nwiu0G6XasCiu9M1Qdg4pqipRQ0Gzr+kCFJnlxpdTuXCltdOmifRfXqU/AsziCrMBVB9CpiMvhpYTm3gAUXpw4lgLdMa+6Mbghp4XJDqnZmpcbZ178lgew7AXWlBN1naQ23zNV7gZqo2QIBpU3RXHPhKA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=1VWXFIIF; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="1VWXFIIF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EE5D41F000FF; Tue, 13 Oct 2026 12:45:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1791895525; bh=xQ/gl90H40nq0Gj+zHp6Ngzxns+b+UVxkWIfuYOTs70=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=1VWXFIIF6HlnAn/5F4lRsPhm2T099OcU5kXpI2vWbiIJljdgxSAh8SZa0zRXFf1I/ +RahChxOjGu6IXXJCzBX33oTAMIIoqGAd2KfJYKPd8mcZadW2W+JB/ptClSi5s4QoR RTxLdEzUjWiIyYvvn/KybGc4tsuCGfAxKKeG4A6U= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, stable , Daniel Starke , Sasha Levin Subject: [PATCH 6.12 303/497] tty: n_gsm: fix missing modem controls after DLCI open in convergence layer type 2 Date: Tue, 13 Oct 2026 13:37:50 +0200 Message-ID: <20261013112915.089611042@linuxfoundation.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261013112907.864180619@linuxfoundation.org> References: <20261013112907.864180619@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.12-stable review patch. If anyone has any objections, please let me know. ------------------ From: Daniel Starke [ Upstream commit 11ea5a63d30ad6d305b1c22301cd99ff45a98c8d ] The current implementation only updates the virtual V.24 control signals after DLCI open in basic option mode. In advanced option mode with convergence layer type 2 an empty data frame needs to be transmitted to inform the peer about the initial virtual V.24 control signals. Not doing so has two unwanted side effects: 1. hardware flow control status is unclear (initial CTS line is unknown) 2. DLCI user presence is not transmitted (initial DTR line is unknown) Applications waiting on these lines can not start after a DLCI has been opened until the first data frame has been transmitted. Fix this by using gsm_modem_update() thoroughly which handles basic and advanced option mode correctly. Add a flag in gsm_modem_update() and the delegated gsm_modem_upd_via_msc() to control whether waiting for the MSC command response is possible. Remove obsolete gsm_modem_send_initial_msc(). Fixes: 3cf0b3c243e5 ("tty: n_gsm: Don't block input queue by waiting MSC") Cc: stable Signed-off-by: Daniel Starke Link: https://patch.msgid.link/20260826063026.2472-1-daniel.starke@siemens.com Signed-off-by: Greg Kroah-Hartman [ sashal: Adjusted context to match the @dlci parameter comment without a colon. ] Signed-off-by: Sasha Levin --- drivers/tty/n_gsm.c | 47 ++++++++++++++------------------------------- 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index c917fc20b469a..028b37d6f06a6 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -454,14 +454,13 @@ static const u8 gsm_fcs8[256] = { static void gsm_dlci_close(struct gsm_dlci *dlci); static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len); -static int gsm_modem_update(struct gsm_dlci *dlci, u8 brk); +static int gsm_modem_update(struct gsm_dlci *dlci, u8 brk, bool wait); static struct gsm_msg *gsm_data_alloc(struct gsm_mux *gsm, u8 addr, int len, u8 ctrl); static int gsm_send_packet(struct gsm_mux *gsm, struct gsm_msg *msg); static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr); static void gsmld_write_trigger(struct gsm_mux *gsm); static void gsmld_write_task(struct work_struct *work); -static int gsm_modem_send_initial_msc(struct gsm_dlci *dlci); /** * gsm_fcs_add - update FCS @@ -2175,7 +2174,7 @@ static void gsm_dlci_open(struct gsm_dlci *dlci) pr_debug("DLCI %d goes open.\n", dlci->addr); /* Send current modem state */ if (dlci->addr) { - gsm_modem_send_initial_msc(dlci); + gsm_modem_update(dlci, 0, false); } else { /* Start keep-alive control */ gsm->ka_num = 0; @@ -4132,9 +4131,10 @@ static void gsm_modem_upd_via_data(struct gsm_dlci *dlci, u8 brk) * gsm_modem_upd_via_msc - send modem bits via control frame * @dlci: channel * @brk: break signal + * @wait: wait for the MSC command */ -static int gsm_modem_upd_via_msc(struct gsm_dlci *dlci, u8 brk) +static int gsm_modem_upd_via_msc(struct gsm_dlci *dlci, u8 brk, bool wait) { u8 modembits[3]; struct gsm_control *ctrl; @@ -4151,41 +4151,22 @@ static int gsm_modem_upd_via_msc(struct gsm_dlci *dlci, u8 brk) modembits[2] = (brk << 4) | 2 | EA; /* Length, Break, EA */ len++; } + if (!wait) + return gsm_control_command(dlci->gsm, CMD_MSC, modembits, len); ctrl = gsm_control_send(dlci->gsm, CMD_MSC, modembits, len); if (ctrl == NULL) return -ENOMEM; return gsm_control_wait(dlci->gsm, ctrl); } -/** - * gsm_modem_send_initial_msc - Send initial modem status message - * - * @dlci channel - * - * Send an initial MSC message after DLCI open to set the initial - * modem status lines. This is only done for basic mode. - * Does not wait for a response as we cannot block the input queue - * processing. - */ -static int gsm_modem_send_initial_msc(struct gsm_dlci *dlci) -{ - u8 modembits[2]; - - if (dlci->adaption != 1 || dlci->gsm->encoding != GSM_BASIC_OPT) - return 0; - - modembits[0] = (dlci->addr << 2) | 2 | EA; /* DLCI, Valid, EA */ - modembits[1] = (gsm_encode_modem(dlci) << 1) | EA; - return gsm_control_command(dlci->gsm, CMD_MSC, (const u8 *)&modembits, 2); -} - /** * gsm_modem_update - send modem status line state * @dlci: channel * @brk: break signal + * @wait: wait for the MSC command */ -static int gsm_modem_update(struct gsm_dlci *dlci, u8 brk) +static int gsm_modem_update(struct gsm_dlci *dlci, u8 brk, bool wait) { if (dlci->gsm->dead) return -EL2HLT; @@ -4195,7 +4176,7 @@ static int gsm_modem_update(struct gsm_dlci *dlci, u8 brk) return 0; } else if (dlci->gsm->encoding == GSM_BASIC_OPT) { /* Send as MSC control message. */ - return gsm_modem_upd_via_msc(dlci, brk); + return gsm_modem_upd_via_msc(dlci, brk, wait); } /* Modem status lines are not supported. */ @@ -4261,7 +4242,7 @@ static void gsm_dtr_rts(struct tty_port *port, bool active) modem_tx &= ~(TIOCM_DTR | TIOCM_RTS); if (modem_tx != dlci->modem_tx) { dlci->modem_tx = modem_tx; - gsm_modem_update(dlci, 0); + gsm_modem_update(dlci, 0, true); } } @@ -4457,7 +4438,7 @@ static int gsmtty_tiocmset(struct tty_struct *tty, if (modem_tx != dlci->modem_tx) { dlci->modem_tx = modem_tx; - return gsm_modem_update(dlci, 0); + return gsm_modem_update(dlci, 0, true); } return 0; } @@ -4539,7 +4520,7 @@ static void gsmtty_throttle(struct tty_struct *tty) dlci->modem_tx &= ~TIOCM_RTS; dlci->throttled = true; /* Send an MSC with RTS cleared */ - gsm_modem_update(dlci, 0); + gsm_modem_update(dlci, 0, true); } static void gsmtty_unthrottle(struct tty_struct *tty) @@ -4551,7 +4532,7 @@ static void gsmtty_unthrottle(struct tty_struct *tty) dlci->modem_tx |= TIOCM_RTS; dlci->throttled = false; /* Send an MSC with RTS set */ - gsm_modem_update(dlci, 0); + gsm_modem_update(dlci, 0, true); } static int gsmtty_break_ctl(struct tty_struct *tty, int state) @@ -4569,7 +4550,7 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state) if (encode > 0x0F) encode = 0x0F; /* Best effort */ } - return gsm_modem_update(dlci, encode); + return gsm_modem_update(dlci, encode, true); } static void gsmtty_cleanup(struct tty_struct *tty) -- 2.53.0