From patchwork Mon Oct 24 13:01:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "D. Starke" X-Patchwork-Id: 10313 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp657078wru; Mon, 24 Oct 2022 14:20:01 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5KzZsZ9lx7BExo9f58RzkhHLZ2w2P/MTTIwJ/q0M4L2yByyYybIY9Xex3uQGRRJKOukMRO X-Received: by 2002:a17:90a:3e81:b0:212:cc3c:b02f with SMTP id k1-20020a17090a3e8100b00212cc3cb02fmr23427005pjc.67.1666646401419; Mon, 24 Oct 2022 14:20:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666646401; cv=none; d=google.com; s=arc-20160816; b=XCcmTsuWpDLIXbgMLkXUadMmKKBWICFKrklCRFYGsCYzXm4DD7sylDR0gX+We8vIXi idB2Aw3dCM7LOs47o9vyhQSmBw8krRR1SIpFK0zAVdhk201TjIry5rzYRIst6LGxIgY8 yfWMFmWMhHVBLRG6TgAS1VyL5BZZ1xkwudjEoIt2Mit8bUy22QWRdyP9VghZZFTAYiS+ 8zXkbhQk2VTy0vctRIKlGDMOHCHX+dUrDmzhHny1UDzr5z+fVbNOfcOudjjck/ey0Irn jVga+OhpQve/2gJNQtuio69L1ad9D4HdG7JVzeLhGbm84QOjJHDv0wa1XcdpTwYQ6xhf ljWA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:feedback-id:content-transfer-encoding :mime-version:message-id:date:subject:cc:to:from:dkim-signature; bh=K2kGQ1uzzqA0xWymbFltF9V6/W7ChuSY3sWXqrXX9m8=; b=PFqhNLQgcxaYFvsoJ/ApuzCWnxROrCx1A0covYYU/b2L6fzSdn+8Gqu6tfDrFdFFkh iZO9G/dsZc0ImyP3yTeeZ5pwPC7PBFm3260TAb0wqwOk9Ci6P1fB57I2ndby4Y9pPlb0 1GyaKYRFg2aVar72LPd+gqRADp8aRccQj625/HS90Ymc7QWtz/W2fKSesB6Lg9WUFfxa f9X8yO/5JgkwxTnuQ8tlfBPQisBYRSdxEMfAFRTcDcBLwIulOxTv7TF32ZRaGSexKtnB rqcWfU4l9N3fSmRuzsEZqf7Z0auDLNQJII4aGZisXsAd1Edwm7p0Yed5W5qdJcPlMzFB gzJQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@siemens.com header.s=fm1 header.b=iCo9+oyt; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=siemens.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id x21-20020a631715000000b0046f18bdf887si579704pgl.476.2022.10.24.14.19.47; Mon, 24 Oct 2022 14:20:01 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@siemens.com header.s=fm1 header.b=iCo9+oyt; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=siemens.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234124AbiJXVR4 (ORCPT + 99 others); Mon, 24 Oct 2022 17:17:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46508 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230453AbiJXVRR (ORCPT ); Mon, 24 Oct 2022 17:17:17 -0400 X-Greylist: delayed 1889 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Mon, 24 Oct 2022 12:23:18 PDT Received: from mta-65-225.siemens.flowmailer.net (mta-65-225.siemens.flowmailer.net [185.136.65.225]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 567852D2D5E for ; Mon, 24 Oct 2022 12:23:18 -0700 (PDT) Received: by mta-65-225.siemens.flowmailer.net with ESMTPSA id 20221024130239ff05e52880d9cf551f for ; Mon, 24 Oct 2022 15:02:39 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=daniel.starke@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc; bh=K2kGQ1uzzqA0xWymbFltF9V6/W7ChuSY3sWXqrXX9m8=; b=iCo9+oytoKkqsi8D6FE1CqIrKRjRBDp0s+x9g85W4BMGVfZAjDlMJCk0M8NCG3YgAXHg1Y UknYlfcxZN7zk9hKtLB/4hNCrwX4cPP/EiBlR3VHPSwIfGqZhCVy1Gh1lXj2/FAVOAvfCHVy ej/gR5+Z+wXC/8GDp9yPdAd/ojYU0=; From: "D. Starke" To: linux-serial@vger.kernel.org, gregkh@linuxfoundation.org, jirislaby@kernel.org, ilpo.jarvinen@linux.intel.com Cc: linux-kernel@vger.kernel.org, Daniel Starke Subject: [PATCH v2 1/3] tty: n_gsm: introduce macro for minimal unit size Date: Mon, 24 Oct 2022 15:01:12 +0200 Message-Id: <20221024130114.2070-1-daniel.starke@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-314044:519-21489:flowmailer X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_MSPIKE_H2, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1747605416775383764?= X-GMAIL-MSGID: =?utf-8?q?1747605416775383764?= From: Daniel Starke n_gsm has a minimal protocol overhead of 7 bytes. The current code already checks whether the configured MRU/MTU size is at least one byte more than this. Introduce the macro MIN_MTU to make this value more obvious. Signed-off-by: Daniel Starke Reviewed-by: Ilpo Järvinen --- drivers/tty/n_gsm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) v1 -> v2: Incorporated review comments. Link: https://lore.kernel.org/all/fe537e8-7b2-61e2-767d-787b923c7456@linux.intel.com/ diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 5e516f5cac5a..570c40a3d78f 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -89,6 +89,7 @@ module_param(debug, int, 0600); */ #define MAX_MRU 1500 #define MAX_MTU 1500 +#define MIN_MTU (PROT_OVERHEAD + 1) /* SOF, ADDR, CTRL, LEN1, LEN2, ..., FCS, EOF */ #define PROT_OVERHEAD 7 #define GSM_NET_TX_TIMEOUT (HZ*10) @@ -2712,7 +2713,9 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c) if ((c->adaption != 1 && c->adaption != 2) || c->k) return -EOPNOTSUPP; /* Check the MRU/MTU range looks sane */ - if (c->mru > MAX_MRU || c->mtu > MAX_MTU || c->mru < 8 || c->mtu < 8) + if (c->mru < MIN_MTU || c->mtu < MIN_MTU) + return -EINVAL; + if (c->mru > MAX_MRU || c->mtu > MAX_MTU) return -EINVAL; if (c->n2 > 255) return -EINVAL; @@ -3296,7 +3299,7 @@ static int gsm_create_network(struct gsm_dlci *dlci, struct gsm_netconfig *nc) return -ENOMEM; } net->mtu = dlci->gsm->mtu; - net->min_mtu = 8; + net->min_mtu = MIN_MTU; net->max_mtu = dlci->gsm->mtu; mux_net = netdev_priv(net); mux_net->dlci = dlci; From patchwork Mon Oct 24 13:01:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "D. Starke" X-Patchwork-Id: 10314 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp657079wru; Mon, 24 Oct 2022 14:20:01 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5gfwWtHw/tiUDZCtkUndhptAdMl7ozHA0dZaVTKNizRbPcs+0jvoI4lQHQtFl6IflSg5MQ X-Received: by 2002:a05:6a00:1581:b0:563:36e1:38a8 with SMTP id u1-20020a056a00158100b0056336e138a8mr36447909pfk.80.1666646401482; Mon, 24 Oct 2022 14:20:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666646401; cv=none; d=google.com; s=arc-20160816; b=A/6pU+5AyWGpvreKZ2QWNUhUh98obSzTRH7MXSJwD4KYS7gs0sM9lu9I5hsg33yPUH E4uafr3e4r/cjQIs9o07u70Giuzbs8Xfgr3kz2+vOENwgfWfver1zxS40sYvpFx2EjuJ J9l6iie6h2K2LeScAO9UDq618ria2WmTO+zbZAXuvHKVTRvRxmxvrWlUuec1wzY8D7Af s9NCLlaSWibpENuVaeIq57grC+afdIes5l40aXO+dyTAjwK9VgpkqdkJpzsXJxS0fnjS pbqMDPjOEAtkGWV+F3my7wmjMHhyd6SuE93YCGBK72rKyYqcq3qHXqlEmW9RE9zzcyuy NUHg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:feedback-id:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=7VRrKS7PPbZQ9y6ThMivwxpoz+H3EcUazjPIe8pSDps=; b=HhXGwLnBlMNuOUUdAdXYb3GMd3TWyAH0Oq2t5kGDZGJIx0wSFHuHaR4ogdV3pBYopk Z0H63FhzC7XCmBdOfcyjC/FGL1qS6ku6/iZwTglLcwIXulT3yNUPjoSNBS19sDNnEGm+ 3/IDL0rQc+lMFRGQAZmN+3cvLd9rNEfed8lYtmO56yXKl/MhqQOqk6iGZY08Iqgh2Bvb GfsAbsKKvRWRCSvvZ3iNreitpMCcSRtru+fqH2YDVWJusjyUIDTEWez/y4v7mz1Ju6G9 tFK6Ozw5qmZmXdN1G5J1GKQLHf0PHgejeUOht9tjynwWzJKRpOdmjHASUhlRSZZ3NPzZ Wv6w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@siemens.com header.s=fm1 header.b=V0rYZsTI; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=siemens.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id 21-20020a631955000000b0042f6352ba2csi612973pgz.745.2022.10.24.14.19.48; Mon, 24 Oct 2022 14:20:01 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@siemens.com header.s=fm1 header.b=V0rYZsTI; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=siemens.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234343AbiJXVSF (ORCPT + 99 others); Mon, 24 Oct 2022 17:18:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47486 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234315AbiJXVRb (ORCPT ); Mon, 24 Oct 2022 17:17:31 -0400 X-Greylist: delayed 1920 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Mon, 24 Oct 2022 12:23:32 PDT Received: from mta-65-225.siemens.flowmailer.net (mta-65-225.siemens.flowmailer.net [185.136.65.225]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 790802D2C10 for ; Mon, 24 Oct 2022 12:23:32 -0700 (PDT) Received: by mta-65-225.siemens.flowmailer.net with ESMTPSA id 2022102413024033e5b3554e259b0208 for ; Mon, 24 Oct 2022 15:02:40 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=daniel.starke@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=7VRrKS7PPbZQ9y6ThMivwxpoz+H3EcUazjPIe8pSDps=; b=V0rYZsTI3y1VRvUZkMIeRp+fkmAJhS6kjgD0vPaLebpfAj63JfJoB1Oyoiw+RoVBiB8pVl Ju8hXraHYP37gUjGDK0ZXR+JDMz8v4Dc54+JWYdI59iri5RKQTKR0QhH3aI0/d608RSBYEr1 +IM3iSc+BKC/5Szivs/KBt1YaRzOg=; From: "D. Starke" To: linux-serial@vger.kernel.org, gregkh@linuxfoundation.org, jirislaby@kernel.org, ilpo.jarvinen@linux.intel.com Cc: linux-kernel@vger.kernel.org, Daniel Starke Subject: [PATCH v2 2/3] tty: n_gsm: add parameters used with parameter negotiation Date: Mon, 24 Oct 2022 15:01:13 +0200 Message-Id: <20221024130114.2070-2-daniel.starke@siemens.com> In-Reply-To: <20221024130114.2070-1-daniel.starke@siemens.com> References: <20221024130114.2070-1-daniel.starke@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-314044:519-21489:flowmailer X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_MSPIKE_H2, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1747605416754835988?= X-GMAIL-MSGID: =?utf-8?q?1747605416754835988?= From: Daniel Starke n_gsm is based on the 3GPP 07.010 and its newer version is the 3GPP 27.010. See https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=1516 The changes from 07.010 to 27.010 are non-functional. Therefore, I refer to the newer 27.010 here. Chapter 5.4.6.3.1 describes the encoding of the parameter negotiation messages. Add the parameters used there to 'gsm_mux' and 'gsm_dlci' and initialize both according to the value ranges and recommended defaults defined in chapter 5.7. Replace the use of the DLC default values from the 'gsm_mux' fields with the DLC specific values from the 'gsm_dlci' fields where applicable. Signed-off-by: Daniel Starke Reviewed-by: Ilpo Järvinen --- drivers/tty/n_gsm.c | 58 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 13 deletions(-) v1 -> v2: Incorporated review comments. Changed type of t3 in gsm_mux to unsigned int. Link: https://lore.kernel.org/all/4519259-1e70-351c-756c-57c1e665e94@linux.intel.com/ diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 570c40a3d78f..c217013b3e16 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -75,7 +76,12 @@ module_param(debug, int, 0600); #define T1 10 /* 100mS */ #define T2 34 /* 333mS */ +#define T3 10 /* 10s */ #define N2 3 /* Retry 3 times */ +#define K 2 /* outstanding I frames */ + +#define MAX_T3 255 /* In seconds. */ +#define MAX_WINDOW_SIZE 7 /* Limit of K in error recovery mode. */ /* Use long timers for testing at low speed with debug on */ #ifdef DEBUG_TIMING @@ -160,7 +166,12 @@ struct gsm_dlci { int prev_adaption; u32 modem_rx; /* Our incoming virtual modem lines */ u32 modem_tx; /* Our outgoing modem lines */ + unsigned int mtu; bool dead; /* Refuse re-open */ + /* Configuration */ + u8 prio; /* Priority */ + u8 ftype; /* Frame type */ + u8 k; /* Window size */ /* Flow control */ bool throttled; /* Private copy of throttle state */ bool constipated; /* Throttle status for outgoing */ @@ -283,7 +294,9 @@ struct gsm_mux { int adaption; /* 1 or 2 supported */ u8 ftype; /* UI or UIH */ int t1, t2; /* Timers in 1/100th of a sec */ + unsigned int t3; /* Power wake-up timer in seconds. */ int n2; /* Retry count */ + u8 k; /* Window size */ /* Statistics (not currently exposed) */ unsigned long bad_fcs; @@ -1075,12 +1088,12 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci) return 0; /* MTU/MRU count only the data bits but watch adaption mode */ - if ((len + h) > gsm->mtu) - len = gsm->mtu - h; + if ((len + h) > dlci->mtu) + len = dlci->mtu - h; size = len + h; - msg = gsm_data_alloc(gsm, dlci->addr, size, gsm->ftype); + msg = gsm_data_alloc(gsm, dlci->addr, size, dlci->ftype); if (!msg) return -ENOMEM; dp = msg->data; @@ -1144,19 +1157,19 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, len = dlci->skb->len + overhead; /* MTU/MRU count only the data bits */ - if (len > gsm->mtu) { + if (len > dlci->mtu) { if (dlci->adaption == 3) { /* Over long frame, bin it */ dev_kfree_skb_any(dlci->skb); dlci->skb = NULL; return 0; } - len = gsm->mtu; + len = dlci->mtu; } else last = 1; size = len + overhead; - msg = gsm_data_alloc(gsm, dlci->addr, size, gsm->ftype); + msg = gsm_data_alloc(gsm, dlci->addr, size, dlci->ftype); if (msg == NULL) { skb_queue_tail(&dlci->skb_list, dlci->skb); dlci->skb = NULL; @@ -1213,7 +1226,7 @@ static int gsm_dlci_modem_output(struct gsm_mux *gsm, struct gsm_dlci *dlci, return -EINVAL; } - msg = gsm_data_alloc(gsm, dlci->addr, size, gsm->ftype); + msg = gsm_data_alloc(gsm, dlci->addr, size, dlci->ftype); if (!msg) { pr_err("%s: gsm_data_alloc error", __func__); return -ENOMEM; @@ -1338,8 +1351,9 @@ static void gsm_dlci_data_kick(struct gsm_dlci *dlci) static int gsm_control_command(struct gsm_mux *gsm, int cmd, const u8 *data, int dlen) { - struct gsm_msg *msg = gsm_data_alloc(gsm, 0, dlen + 2, gsm->ftype); + struct gsm_msg *msg; + msg = gsm_data_alloc(gsm, 0, dlen + 2, gsm->dlci[0]->ftype); if (msg == NULL) return -ENOMEM; @@ -1365,7 +1379,8 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, const u8 *data, int dlen) { struct gsm_msg *msg; - msg = gsm_data_alloc(gsm, 0, dlen + 2, gsm->ftype); + + msg = gsm_data_alloc(gsm, 0, dlen + 2, gsm->dlci[0]->ftype); if (msg == NULL) return; msg->data[0] = (cmd & 0xFE) << 1 | EA; /* Clear C/R */ @@ -2075,6 +2090,13 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr) dlci->gsm = gsm; dlci->addr = addr; dlci->adaption = gsm->adaption; + dlci->mtu = gsm->mtu; + if (addr == 0) + dlci->prio = 0; + else + dlci->prio = roundup(addr + 1, 8) - 1; + dlci->ftype = gsm->ftype; + dlci->k = gsm->k; dlci->state = DLCI_CLOSED; if (addr) { dlci->data = gsm_dlci_data; @@ -2650,7 +2672,9 @@ static struct gsm_mux *gsm_alloc_mux(void) gsm->t1 = T1; gsm->t2 = T2; + gsm->t3 = T3; gsm->n2 = N2; + gsm->k = K; gsm->ftype = UIH; gsm->adaption = 1; gsm->encoding = GSM_ADV_OPT; @@ -2691,7 +2715,7 @@ static void gsm_copy_config_values(struct gsm_mux *gsm, c->initiator = gsm->initiator; c->t1 = gsm->t1; c->t2 = gsm->t2; - c->t3 = 0; /* Not supported */ + c->t3 = gsm->t3; c->n2 = gsm->n2; if (gsm->ftype == UIH) c->i = 1; @@ -2700,7 +2724,7 @@ static void gsm_copy_config_values(struct gsm_mux *gsm, pr_debug("Ftype %d i %d\n", gsm->ftype, c->i); c->mru = gsm->mru; c->mtu = gsm->mtu; - c->k = 0; + c->k = gsm->k; } static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c) @@ -2717,12 +2741,16 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c) return -EINVAL; if (c->mru > MAX_MRU || c->mtu > MAX_MTU) return -EINVAL; + if (c->t3 > MAX_T3) + return -EINVAL; if (c->n2 > 255) return -EINVAL; if (c->encapsulation > 1) /* Basic, advanced, no I */ return -EINVAL; if (c->initiator > 1) return -EINVAL; + if (c->k > MAX_WINDOW_SIZE) + return -EINVAL; if (c->i == 0 || c->i > 2) /* UIH and UI only */ return -EINVAL; /* @@ -2770,6 +2798,10 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c) gsm->t1 = c->t1; if (c->t2) gsm->t2 = c->t2; + if (c->t3) + gsm->t3 = c->t3; + if (c->k) + gsm->k = c->k; /* * FIXME: We need to separate activation/deactivation from adding @@ -3298,9 +3330,9 @@ static int gsm_create_network(struct gsm_dlci *dlci, struct gsm_netconfig *nc) pr_err("alloc_netdev failed\n"); return -ENOMEM; } - net->mtu = dlci->gsm->mtu; + net->mtu = dlci->mtu; net->min_mtu = MIN_MTU; - net->max_mtu = dlci->gsm->mtu; + net->max_mtu = dlci->mtu; mux_net = netdev_priv(net); mux_net->dlci = dlci; kref_init(&mux_net->ref); From patchwork Mon Oct 24 13:01:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "D. Starke" X-Patchwork-Id: 10427 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp729654wru; Mon, 24 Oct 2022 17:45:14 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5eUI9cPov+5e8G6qHuwsx+eJp+OrPS7ArP032MmJWVODZXKAIhi0IUO/zbJZRXu0PFQbhp X-Received: by 2002:a05:6402:26cf:b0:45d:48d7:928e with SMTP id x15-20020a05640226cf00b0045d48d7928emr32045383edd.275.1666658714238; Mon, 24 Oct 2022 17:45:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666658714; cv=none; d=google.com; s=arc-20160816; b=LrJXiUGq21qONAhwAgWGu3dzLg33uMP3ZbryVoET5wZfXCNSnw3MK92t1qMe+BtO/l EGd6cpSW0DPlMpOgi4ST72j5KaqZh0JMRXQ8ak23WQVOkU82R24Zn+edE2kR4tkrAK9h Uqwg75BfTwilQ4FfaG9CYUstdqHyPK77vKETUL1OyiUuseOV1v21YoeXkc6Pk40GaVdz YUIIMRf5OOpBmC8MNXWnzc3wihXm7eUk99hvBhnWiTPQvvTRShVidcqMb+jRQjQ/pDli xUd7V3HGdh4Auw5wtVKOUHf9/ILzw+uysJi8vIqzcSeyg4Ro7jQMsnpDqk46JQ6WjqH0 5JCg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:feedback-id:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=jV4KNLQLNdeRQVVVRbZSItB2K9nwNymWyBqfbbOJeU4=; b=BCt5JT88PR42wxH4kaAs82iPkF39gSYkZKtcc2da3xyKKlpAjIDb+6CtwB+L4+kbnN Z/L4TKlo4YM7QM+h9ygLe0LhSz325hJOuhzW4ijJ7vbxta0ODyHnaW7DkYVzdT2zrPIB /dNk8egbi9L2bO+ktdxroEXmbO7cBcM4C5sZSbsyKDCd/awo9pvXLtPYZHuN3UQU9nK6 BEaVJlvFZ7WR9x2Qu3u8lY9OLv+pIsGdf92xrFBlePCky36rOC1HZ3EiRJAraB75lSu0 kbVsXtZEvVMzFDYxS+V19lWKyGACkCU/EXHGrvhyp3GIoFpll9vOcJ/6eTPszY6NaP2M 5eqg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@siemens.com header.s=fm1 header.b=RsuCE0Aj; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=siemens.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id g6-20020a170906520600b0078d40f7ef1fsi1032819ejm.330.2022.10.24.17.44.48; Mon, 24 Oct 2022 17:45:14 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@siemens.com header.s=fm1 header.b=RsuCE0Aj; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=siemens.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229967AbiJYAiS (ORCPT + 99 others); Mon, 24 Oct 2022 20:38:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33542 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230502AbiJYAiA (ORCPT ); Mon, 24 Oct 2022 20:38:00 -0400 X-Greylist: delayed 29654 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Mon, 24 Oct 2022 16:04:48 PDT Received: from mta-64-228.siemens.flowmailer.net (mta-64-228.siemens.flowmailer.net [185.136.64.228]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 06E7B9D52E for ; Mon, 24 Oct 2022 16:04:48 -0700 (PDT) Received: by mta-64-228.siemens.flowmailer.net with ESMTPSA id 20221024130241cafa81e02a78a0ed53 for ; Mon, 24 Oct 2022 15:02:41 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=daniel.starke@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=jV4KNLQLNdeRQVVVRbZSItB2K9nwNymWyBqfbbOJeU4=; b=RsuCE0Ajp+y46RAlixCduV2X5Vv0SNq/rzBFhn21ONd5J9t6A7EvTaCkpUi/436PWjXovf AzQw7qZqO71SBl1okUvrxEgccz5hLUVtqgLKsLOLRGDIifOEavWUVsUJbASKsyb0NhrUC35I U0inZPJhC/dYPUsGgPw1TstKJcnRI=; From: "D. Starke" To: linux-serial@vger.kernel.org, gregkh@linuxfoundation.org, jirislaby@kernel.org, ilpo.jarvinen@linux.intel.com Cc: linux-kernel@vger.kernel.org, Daniel Starke Subject: [PATCH v2 3/3] tty: n_gsm: add parameter negotiation support Date: Mon, 24 Oct 2022 15:01:14 +0200 Message-Id: <20221024130114.2070-3-daniel.starke@siemens.com> In-Reply-To: <20221024130114.2070-1-daniel.starke@siemens.com> References: <20221024130114.2070-1-daniel.starke@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-314044:519-21489:flowmailer X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_MSPIKE_H2, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1747618327934836317?= X-GMAIL-MSGID: =?utf-8?q?1747618327934836317?= From: Daniel Starke n_gsm is based on the 3GPP 07.010 and its newer version is the 3GPP 27.010. See https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=1516 The changes from 07.010 to 27.010 are non-functional. Therefore, I refer to the newer 27.010 here. Chapter 5.1.8.1.1 describes the parameter negotiation messages and parameters. Chapter 5.4.1 states that the default parameters are to be used if no negotiation is performed. Chapter 5.4.6.3.1 describes the encoding of the parameter negotiation message. The meaning of the parameters and allowed value ranges can be found in chapter 5.7. Add parameter negotiation support accordingly. DLCI specific parameter configuration by the user requires additional ioctls. This is subject to another patch. Signed-off-by: Daniel Starke --- drivers/tty/n_gsm.c | 335 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 327 insertions(+), 8 deletions(-) v1 -> v2: Incorporated review comments. Simplification of command retry handling remains subject to future patches. Link: https://lore.kernel.org/all/8c2b9492-caf4-7a48-3a7b-da939a4ac8b6@linux.intel.com/ diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index c217013b3e16..11d3730bf436 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -127,6 +128,7 @@ struct gsm_msg { enum gsm_dlci_state { DLCI_CLOSED, + DLCI_CONFIGURE, /* Sending PN (for adaption > 1) */ DLCI_OPENING, /* Sending SABM not seen UA */ DLCI_OPEN, /* SABM/UA complete */ DLCI_CLOSING, /* Sending DISC not seen UA/DM */ @@ -184,6 +186,30 @@ struct gsm_dlci { struct net_device *net; /* network interface, if created */ }; +/* + * Parameter bits used for parameter negotiation according to 3GPP 27.010 + * chapter 5.4.6.3.1. + */ + +struct gsm_dlci_param_bits { + u8 d_bits; + u8 i_cl_bits; + u8 p_bits; + u8 t_bits; + __le16 n_bits; + u8 na_bits; + u8 k_bits; +} __packed; + +#define PN_D_FIELD_DLCI GENMASK(5, 0) +#define PN_I_CL_FIELD_FTYPE GENMASK(3, 0) +#define PN_I_CL_FIELD_ADAPTION GENMASK(7, 4) +#define PN_P_FIELD_PRIO GENMASK(5, 0) +#define PN_T_FIELD_T1 GENMASK(7, 0) +#define PN_N_FIELD_N1 GENMASK(15, 0) +#define PN_NA_FIELD_N2 GENMASK(7, 0) +#define PN_K_FIELD_K GENMASK(2, 0) + /* Total number of supported devices */ #define GSM_TTY_MINORS 256 @@ -411,6 +437,7 @@ static const u8 gsm_fcs8[256] = { #define INIT_FCS 0xFF #define GOOD_FCS 0xCF +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 struct gsm_msg *gsm_data_alloc(struct gsm_mux *gsm, u8 addr, int len, @@ -533,6 +560,59 @@ static void gsm_hex_dump_bytes(const char *fname, const u8 *data, kfree(prefix); } +/** + * gsm_encode_params - encode DLCI parameters + * @dlci: DLCI to encode from + * @params: buffer to fill with the encoded parameters + * + * Encodes the parameters according to GSM 07.10 section 5.4.6.3.1 + * table 3. + */ +static int gsm_encode_params(const struct gsm_dlci *dlci, + struct gsm_dlci_param_bits *params) +{ + const struct gsm_mux *gsm = dlci->gsm; + unsigned int i, cl; + + switch (dlci->ftype) { + case UIH: + i = 0; /* UIH */ + break; + case UI: + i = 1; /* UI */ + break; + default: + pr_err("%s: unsupported frame type %d\n", __func__, + dlci->ftype); + return -EINVAL; + } + + switch (dlci->adaption) { + case 1: /* Unstructured */ + cl = 0; /* convergence layer type 1 */ + break; + case 2: /* Unstructured with modem bits. */ + cl = 1; /* convergence layer type 2 */ + break; + default: + pr_err("%s: unsupported adaption %d\n", __func__, + dlci->adaption); + return -EINVAL; + } + + params->d_bits = FIELD_PREP(PN_D_FIELD_DLCI, dlci->addr); + /* UIH, convergence layer type 1 */ + params->i_cl_bits = FIELD_PREP(PN_I_CL_FIELD_FTYPE, i) | + FIELD_PREP(PN_I_CL_FIELD_ADAPTION, cl); + params->p_bits = FIELD_PREP(PN_P_FIELD_PRIO, dlci->prio); + params->t_bits = FIELD_PREP(PN_T_FIELD_T1, gsm->t1); + params->n_bits = cpu_to_le16(FIELD_PREP(PN_N_FIELD_N1, dlci->mtu)); + params->na_bits = FIELD_PREP(PN_NA_FIELD_N2, gsm->n2); + params->k_bits = FIELD_PREP(PN_K_FIELD_K, dlci->k); + + return 0; +} + /** * gsm_register_devices - register all tty devices for a given mux index * @@ -1450,6 +1530,116 @@ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci, dlci->modem_rx = mlines; } +/** + * gsm_process_negotiation - process received parameters + * @gsm: GSM channel + * @addr: DLCI address + * @cr: command/response + * @params: encoded parameters from the parameter negotiation message + * + * Used when the response for our parameter negotiation command was + * received. + */ +static int gsm_process_negotiation(struct gsm_mux *gsm, unsigned int addr, + unsigned int cr, + const struct gsm_dlci_param_bits *params) +{ + struct gsm_dlci *dlci = gsm->dlci[addr]; + unsigned int ftype, i, adaption, prio, n1, k; + + i = FIELD_GET(PN_I_CL_FIELD_FTYPE, params->i_cl_bits); + adaption = FIELD_GET(PN_I_CL_FIELD_ADAPTION, params->i_cl_bits) + 1; + prio = FIELD_GET(PN_P_FIELD_PRIO, params->p_bits); + n1 = FIELD_GET(PN_N_FIELD_N1, le16_to_cpu(params->n_bits)); + k = FIELD_GET(PN_K_FIELD_K, params->k_bits); + + if (n1 < MIN_MTU) { + if (debug & DBG_ERRORS) + pr_info("%s N1 out of range in PN\n", __func__); + return -EINVAL; + } + + switch (i) { + case 0x00: + ftype = UIH; + break; + case 0x01: + ftype = UI; + break; + case 0x02: /* I frames are not supported */ + if (debug & DBG_ERRORS) + pr_info("%s unsupported I frame request in PN\n", + __func__); + return -EINVAL; + default: + if (debug & DBG_ERRORS) + pr_info("%s i out of range in PN\n", __func__); + return -EINVAL; + } + + if (!cr && gsm->initiator) { + if (adaption != dlci->adaption) { + if (debug & DBG_ERRORS) + pr_info("%s invalid adaption %d in PN\n", + __func__, adaption); + return -EINVAL; + } + if (prio != dlci->prio) { + if (debug & DBG_ERRORS) + pr_info("%s invalid priority %d in PN", + __func__, prio); + return -EINVAL; + } + if (n1 > gsm->mru || n1 > dlci->mtu) { + /* We requested a frame size but the other party wants + * to send larger frames. The standard allows only a + * smaller response value than requested (5.4.6.3.1). + */ + if (debug & DBG_ERRORS) + pr_info("%s invalid N1 %d in PN\n", __func__, + n1); + return -EINVAL; + } + dlci->mtu = n1; + if (ftype != dlci->ftype) { + if (debug & DBG_ERRORS) + pr_info("%s invalid i %d in PN\n", __func__, i); + return -EINVAL; + } + if (ftype != UI && ftype != UIH && k > dlci->k) { + if (debug & DBG_ERRORS) + pr_info("%s invalid k %d in PN\n", __func__, k); + return -EINVAL; + } + dlci->k = k; + } else if (cr && !gsm->initiator) { + /* Only convergence layer type 1 and 2 are supported. */ + if (adaption != 1 && adaption != 2) { + if (debug & DBG_ERRORS) + pr_info("%s invalid adaption %d in PN\n", + __func__, adaption); + return -EINVAL; + } + dlci->adaption = adaption; + if (n1 > gsm->mru) { + /* Propose a smaller value */ + dlci->mtu = gsm->mru; + } else if (n1 > MAX_MTU) { + /* Propose a smaller value */ + dlci->mtu = MAX_MTU; + } else { + dlci->mtu = n1; + } + dlci->prio = prio; + dlci->ftype = ftype; + dlci->k = k; + } else { + return -EINVAL; + } + + return 0; +} + /** * gsm_control_modem - modem status received * @gsm: GSM channel @@ -1503,6 +1693,65 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen) gsm_control_reply(gsm, CMD_MSC, data, clen); } +/** + * gsm_control_negotiation - parameter negotiation received + * @gsm: GSM channel + * @cr: command/response flag + * @data: data following command + * @dlen: data length + * + * We have received a parameter negotiation message. This is used by + * the GSM mux protocol to configure protocol parameters for a new DLCI. + */ +static void gsm_control_negotiation(struct gsm_mux *gsm, unsigned int cr, + const u8 *data, unsigned int dlen) +{ + unsigned int addr; + struct gsm_dlci_param_bits pn_reply; + struct gsm_dlci *dlci; + struct gsm_dlci_param_bits *params; + + if (dlen < sizeof(struct gsm_dlci_param_bits)) + return; + + /* Invalid DLCI? */ + params = (struct gsm_dlci_param_bits *)data; + addr = FIELD_GET(PN_D_FIELD_DLCI, params->d_bits); + if (addr == 0 || addr >= NUM_DLCI || !gsm->dlci[addr]) + return; + dlci = gsm->dlci[addr]; + + /* Too late for parameter negotiation? */ + if ((!cr && dlci->state == DLCI_OPENING) || dlci->state == DLCI_OPEN) + return; + + /* Process the received parameters */ + if (gsm_process_negotiation(gsm, addr, cr, params) != 0) { + /* Negotiation failed. Close the link. */ + if (debug & DBG_ERRORS) + pr_info("%s PN failed\n", __func__); + gsm_dlci_close(dlci); + return; + } + + if (cr) { + /* Reply command with accepted parameters. */ + if (gsm_encode_params(dlci, &pn_reply) == 0) + gsm_control_reply(gsm, CMD_PN, (const u8 *)&pn_reply, + sizeof(pn_reply)); + else if (debug & DBG_ERRORS) + pr_info("%s PN invalid\n", __func__); + } else if (dlci->state == DLCI_CONFIGURE) { + /* Proceed with link setup by sending SABM before UA */ + dlci->state = DLCI_OPENING; + gsm_command(gsm, dlci->addr, SABM|PF); + mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100); + } else { + if (debug & DBG_ERRORS) + pr_info("%s PN in invalid state\n", __func__); + } +} + /** * gsm_control_rls - remote line status * @gsm: GSM channel @@ -1612,8 +1861,12 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command, /* Modem wishes to enter power saving state */ gsm_control_reply(gsm, CMD_PSC, NULL, 0); break; + /* Optional commands */ + case CMD_PN: + /* Modem sends a parameter negotiation command */ + gsm_control_negotiation(gsm, 1, data, clen); + break; /* Optional unsupported commands */ - case CMD_PN: /* Parameter negotiation */ case CMD_RPN: /* Remote port negotiation */ case CMD_SNC: /* Service negotiation command */ default: @@ -1646,8 +1899,8 @@ static void gsm_control_response(struct gsm_mux *gsm, unsigned int command, spin_lock_irqsave(&gsm->control_lock, flags); ctrl = gsm->pending_cmd; - /* Does the reply match our command */ command |= 1; + /* Does the reply match our command */ if (ctrl != NULL && (command == ctrl->cmd || command == CMD_NSC)) { /* Our command was replied to, kill the retry timer */ del_timer(&gsm->t2_timer); @@ -1657,6 +1910,9 @@ static void gsm_control_response(struct gsm_mux *gsm, unsigned int command, ctrl->error = -EOPNOTSUPP; ctrl->done = 1; wake_up(&gsm->event); + /* Or did we receive the PN response to our PN command */ + } else if (command == CMD_PN) { + gsm_control_negotiation(gsm, 0, data, clen); } spin_unlock_irqrestore(&gsm->control_lock, flags); } @@ -1834,6 +2090,32 @@ static void gsm_dlci_open(struct gsm_dlci *dlci) wake_up(&dlci->gsm->event); } +/** + * gsm_dlci_negotiate - start parameter negotiation + * @dlci: DLCI to open + * + * Starts the parameter negotiation for the new DLCI. This needs to be done + * before the DLCI initialized the channel via SABM. + */ +static int gsm_dlci_negotiate(struct gsm_dlci *dlci) +{ + struct gsm_mux *gsm = dlci->gsm; + struct gsm_dlci_param_bits params; + int ret; + + ret = gsm_encode_params(dlci, ¶ms); + if (ret != 0) + return ret; + + /* We cannot asynchronous wait for the command response with + * gsm_command() and gsm_control_wait() at this point. + */ + ret = gsm_control_command(gsm, CMD_PN, (const u8 *)¶ms, + sizeof(params)); + + return ret; +} + /** * gsm_dlci_t1 - T1 timer expiry * @t: timer contained in the DLCI that opened @@ -1855,6 +2137,14 @@ static void gsm_dlci_t1(struct timer_list *t) struct gsm_mux *gsm = dlci->gsm; switch (dlci->state) { + case DLCI_CONFIGURE: + if (dlci->retries && gsm_dlci_negotiate(dlci) == 0) { + dlci->retries--; + mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100); + } else { + gsm_dlci_begin_close(dlci); /* prevent half open link */ + } + break; case DLCI_OPENING: if (dlci->retries) { dlci->retries--; @@ -1893,17 +2183,46 @@ static void gsm_dlci_t1(struct timer_list *t) * to the modem which should then reply with a UA or ADM, at which point * we will move into open state. Opening is done asynchronously with retry * running off timers and the responses. + * Parameter negotiation is performed before SABM if required. */ static void gsm_dlci_begin_open(struct gsm_dlci *dlci) { - struct gsm_mux *gsm = dlci->gsm; - if (dlci->state == DLCI_OPEN || dlci->state == DLCI_OPENING) + struct gsm_mux *gsm = dlci ? dlci->gsm : NULL; + bool need_pn = false; + + if (!gsm) return; - dlci->retries = gsm->n2; - dlci->state = DLCI_OPENING; - gsm_command(dlci->gsm, dlci->addr, SABM|PF); - mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100); + + if (dlci->addr != 0) { + if (gsm->adaption != 1 || gsm->adaption != dlci->adaption) + need_pn = true; + if (dlci->prio != (roundup(dlci->addr + 1, 8) - 1)) + need_pn = true; + if (gsm->ftype != dlci->ftype) + need_pn = true; + } + + switch (dlci->state) { + case DLCI_CLOSED: + case DLCI_CLOSING: + dlci->retries = gsm->n2; + if (!need_pn) { + dlci->state = DLCI_OPENING; + gsm_command(gsm, dlci->addr, SABM|PF); + } else { + /* Configure DLCI before setup */ + dlci->state = DLCI_CONFIGURE; + if (gsm_dlci_negotiate(dlci) != 0) { + gsm_dlci_close(dlci); + return; + } + } + mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100); + break; + default: + break; + } } /**