Commit 2ec7a802 authored by Daniel Starke's avatar Daniel Starke Committed by Greg Kroah-Hartman

tty: n_gsm: add parameters used with parameter negotiation

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: default avatarDaniel Starke <daniel.starke@siemens.com>
Link: https://lore.kernel.org/r/20221103091743.2119-2-daniel.starke@siemens.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7a121247
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/math.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/poll.h> #include <linux/poll.h>
...@@ -75,7 +76,12 @@ module_param(debug, int, 0600); ...@@ -75,7 +76,12 @@ module_param(debug, int, 0600);
#define T1 10 /* 100mS */ #define T1 10 /* 100mS */
#define T2 34 /* 333mS */ #define T2 34 /* 333mS */
#define T3 10 /* 10s */
#define N2 3 /* Retry 3 times */ #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 */ /* Use long timers for testing at low speed with debug on */
#ifdef DEBUG_TIMING #ifdef DEBUG_TIMING
...@@ -160,7 +166,12 @@ struct gsm_dlci { ...@@ -160,7 +166,12 @@ struct gsm_dlci {
int prev_adaption; int prev_adaption;
u32 modem_rx; /* Our incoming virtual modem lines */ u32 modem_rx; /* Our incoming virtual modem lines */
u32 modem_tx; /* Our outgoing modem lines */ u32 modem_tx; /* Our outgoing modem lines */
unsigned int mtu;
bool dead; /* Refuse re-open */ bool dead; /* Refuse re-open */
/* Configuration */
u8 prio; /* Priority */
u8 ftype; /* Frame type */
u8 k; /* Window size */
/* Flow control */ /* Flow control */
bool throttled; /* Private copy of throttle state */ bool throttled; /* Private copy of throttle state */
bool constipated; /* Throttle status for outgoing */ bool constipated; /* Throttle status for outgoing */
...@@ -283,7 +294,9 @@ struct gsm_mux { ...@@ -283,7 +294,9 @@ struct gsm_mux {
int adaption; /* 1 or 2 supported */ int adaption; /* 1 or 2 supported */
u8 ftype; /* UI or UIH */ u8 ftype; /* UI or UIH */
int t1, t2; /* Timers in 1/100th of a sec */ int t1, t2; /* Timers in 1/100th of a sec */
unsigned int t3; /* Power wake-up timer in seconds. */
int n2; /* Retry count */ int n2; /* Retry count */
u8 k; /* Window size */
/* Statistics (not currently exposed) */ /* Statistics (not currently exposed) */
unsigned long bad_fcs; unsigned long bad_fcs;
...@@ -1075,12 +1088,12 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci) ...@@ -1075,12 +1088,12 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci)
return 0; return 0;
/* MTU/MRU count only the data bits but watch adaption mode */ /* MTU/MRU count only the data bits but watch adaption mode */
if ((len + h) > gsm->mtu) if ((len + h) > dlci->mtu)
len = gsm->mtu - h; len = dlci->mtu - h;
size = len + 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) if (!msg)
return -ENOMEM; return -ENOMEM;
dp = msg->data; dp = msg->data;
...@@ -1144,19 +1157,19 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, ...@@ -1144,19 +1157,19 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm,
len = dlci->skb->len + overhead; len = dlci->skb->len + overhead;
/* MTU/MRU count only the data bits */ /* MTU/MRU count only the data bits */
if (len > gsm->mtu) { if (len > dlci->mtu) {
if (dlci->adaption == 3) { if (dlci->adaption == 3) {
/* Over long frame, bin it */ /* Over long frame, bin it */
dev_kfree_skb_any(dlci->skb); dev_kfree_skb_any(dlci->skb);
dlci->skb = NULL; dlci->skb = NULL;
return 0; return 0;
} }
len = gsm->mtu; len = dlci->mtu;
} else } else
last = 1; last = 1;
size = len + overhead; 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) { if (msg == NULL) {
skb_queue_tail(&dlci->skb_list, dlci->skb); skb_queue_tail(&dlci->skb_list, dlci->skb);
dlci->skb = NULL; dlci->skb = NULL;
...@@ -1213,7 +1226,7 @@ static int gsm_dlci_modem_output(struct gsm_mux *gsm, struct gsm_dlci *dlci, ...@@ -1213,7 +1226,7 @@ static int gsm_dlci_modem_output(struct gsm_mux *gsm, struct gsm_dlci *dlci,
return -EINVAL; return -EINVAL;
} }
msg = gsm_data_alloc(gsm, dlci->addr, size, gsm->ftype); msg = gsm_data_alloc(gsm, dlci->addr, size, dlci->ftype);
if (!msg) { if (!msg) {
pr_err("%s: gsm_data_alloc error", __func__); pr_err("%s: gsm_data_alloc error", __func__);
return -ENOMEM; return -ENOMEM;
...@@ -1338,8 +1351,9 @@ static void gsm_dlci_data_kick(struct gsm_dlci *dlci) ...@@ -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, static int gsm_control_command(struct gsm_mux *gsm, int cmd, const u8 *data,
int dlen) 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) if (msg == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -1365,7 +1379,8 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, const u8 *data, ...@@ -1365,7 +1379,8 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, const u8 *data,
int dlen) int dlen)
{ {
struct gsm_msg *msg; 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) if (msg == NULL)
return; return;
msg->data[0] = (cmd & 0xFE) << 1 | EA; /* Clear C/R */ 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) ...@@ -2075,6 +2090,13 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr)
dlci->gsm = gsm; dlci->gsm = gsm;
dlci->addr = addr; dlci->addr = addr;
dlci->adaption = gsm->adaption; 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; dlci->state = DLCI_CLOSED;
if (addr) { if (addr) {
dlci->data = gsm_dlci_data; dlci->data = gsm_dlci_data;
...@@ -2650,7 +2672,9 @@ static struct gsm_mux *gsm_alloc_mux(void) ...@@ -2650,7 +2672,9 @@ static struct gsm_mux *gsm_alloc_mux(void)
gsm->t1 = T1; gsm->t1 = T1;
gsm->t2 = T2; gsm->t2 = T2;
gsm->t3 = T3;
gsm->n2 = N2; gsm->n2 = N2;
gsm->k = K;
gsm->ftype = UIH; gsm->ftype = UIH;
gsm->adaption = 1; gsm->adaption = 1;
gsm->encoding = GSM_ADV_OPT; gsm->encoding = GSM_ADV_OPT;
...@@ -2691,7 +2715,7 @@ static void gsm_copy_config_values(struct gsm_mux *gsm, ...@@ -2691,7 +2715,7 @@ static void gsm_copy_config_values(struct gsm_mux *gsm,
c->initiator = gsm->initiator; c->initiator = gsm->initiator;
c->t1 = gsm->t1; c->t1 = gsm->t1;
c->t2 = gsm->t2; c->t2 = gsm->t2;
c->t3 = 0; /* Not supported */ c->t3 = gsm->t3;
c->n2 = gsm->n2; c->n2 = gsm->n2;
if (gsm->ftype == UIH) if (gsm->ftype == UIH)
c->i = 1; c->i = 1;
...@@ -2700,7 +2724,7 @@ static void gsm_copy_config_values(struct gsm_mux *gsm, ...@@ -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); pr_debug("Ftype %d i %d\n", gsm->ftype, c->i);
c->mru = gsm->mru; c->mru = gsm->mru;
c->mtu = gsm->mtu; c->mtu = gsm->mtu;
c->k = 0; c->k = gsm->k;
} }
static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c) 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) ...@@ -2717,12 +2741,16 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c)
return -EINVAL; return -EINVAL;
if (c->mru > MAX_MRU || c->mtu > MAX_MTU) if (c->mru > MAX_MRU || c->mtu > MAX_MTU)
return -EINVAL; return -EINVAL;
if (c->t3 > MAX_T3)
return -EINVAL;
if (c->n2 > 255) if (c->n2 > 255)
return -EINVAL; return -EINVAL;
if (c->encapsulation > 1) /* Basic, advanced, no I */ if (c->encapsulation > 1) /* Basic, advanced, no I */
return -EINVAL; return -EINVAL;
if (c->initiator > 1) if (c->initiator > 1)
return -EINVAL; return -EINVAL;
if (c->k > MAX_WINDOW_SIZE)
return -EINVAL;
if (c->i == 0 || c->i > 2) /* UIH and UI only */ if (c->i == 0 || c->i > 2) /* UIH and UI only */
return -EINVAL; return -EINVAL;
/* /*
...@@ -2770,6 +2798,10 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c) ...@@ -2770,6 +2798,10 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c)
gsm->t1 = c->t1; gsm->t1 = c->t1;
if (c->t2) if (c->t2)
gsm->t2 = 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 * 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) ...@@ -3298,9 +3330,9 @@ static int gsm_create_network(struct gsm_dlci *dlci, struct gsm_netconfig *nc)
pr_err("alloc_netdev failed\n"); pr_err("alloc_netdev failed\n");
return -ENOMEM; return -ENOMEM;
} }
net->mtu = dlci->gsm->mtu; net->mtu = dlci->mtu;
net->min_mtu = MIN_MTU; net->min_mtu = MIN_MTU;
net->max_mtu = dlci->gsm->mtu; net->max_mtu = dlci->mtu;
mux_net = netdev_priv(net); mux_net = netdev_priv(net);
mux_net->dlci = dlci; mux_net->dlci = dlci;
kref_init(&mux_net->ref); kref_init(&mux_net->ref);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment