<p>neels has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-bsc/+/24377">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add VAMOS secondary lchans to timeslot struct<br><br>So far there is a bunch of code setting a primary lchan in VAMOS mode.<br>This patch now adds the actual secondary "shadow" lchans that may be<br>combined with a primary lchan in VAMOS mode to form a multiplex.<br><br>VAMOS lchans are put in the same ts->lchan[] array that keeps the<br>primary lchans. They are at most two additional usable lchans (for a<br>TCH/H shadow) added to either TCH/F or TCH/H.<br><br>Keeping these in the same array allows looping over all lchans easily.<br>The ts->max_primary_lchans indicates the index of the first VAMOS shadow<br>lchan.<br><br>Related: SYS#5315 OS#4940<br>Change-Id: I928af99498bba488d317693f3144d4fccbbe9af3<br>---<br>M include/osmocom/bsc/gsm_data.h<br>M src/osmo-bsc/abis_rsl.c<br>M src/osmo-bsc/assignment_fsm.c<br>M src/osmo-bsc/gsm_data.c<br>M src/osmo-bsc/lchan_fsm.c<br>M src/osmo-bsc/timeslot_fsm.c<br>6 files changed, 152 insertions(+), 13 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/77/24377/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h</span><br><span>index 8ce5a91..4690a2c 100644</span><br><span>--- a/include/osmocom/bsc/gsm_data.h</span><br><span>+++ b/include/osmocom/bsc/gsm_data.h</span><br><span>@@ -1041,8 +1041,11 @@</span><br><span> </span><br><span> enum gsm_phys_chan_config ts_pchan(struct gsm_bts_trx_ts *ts);</span><br><span> uint8_t pchan_subslots(enum gsm_phys_chan_config pchan);</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t pchan_subslots_vamos(enum gsm_phys_chan_config pchan);</span><br><span> bool ts_is_tch(struct gsm_bts_trx_ts *ts);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct gsm_lchan *gsm_lchan_vamos_to_primary(const struct gsm_lchan *lchan_vamos, int idx);</span><br><span style="color: hsl(120, 100%, 40%);">+struct gsm_lchan *gsm_lchan_primary_to_vamos(const struct gsm_lchan *lchan_primary, int idx);</span><br><span> </span><br><span> struct gsm_bts *conn_get_bts(struct gsm_subscriber_connection *conn);</span><br><span> </span><br><span>diff --git a/src/osmo-bsc/abis_rsl.c b/src/osmo-bsc/abis_rsl.c</span><br><span>index 476cc3a..e1d8a41 100644</span><br><span>--- a/src/osmo-bsc/abis_rsl.c</span><br><span>+++ b/src/osmo-bsc/abis_rsl.c</span><br><span>@@ -1670,6 +1670,8 @@</span><br><span>  * or unsuccessfully). */</span><br><span> static bool force_free_lchan_for_emergency(struct chan_rqd *rqd)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>     /* If the request is not about an emergency call, we may exit early, without doing anything. */</span><br><span>      if (rqd->reason != GSM_CHREQ_REASON_EMERG)</span><br><span>               return false;</span><br><span>@@ -1691,10 +1693,11 @@</span><br><span>        * This will take a short amount of time. We need to come back and check regulary to see if we managed to</span><br><span>     * free up another lchan. */</span><br><span>         if (!rqd->release_lchan) {</span><br><span style="color: hsl(120, 100%, 40%);">+         struct gsm_lchan *release_lchan;</span><br><span>             /* Pick any busy TCH/F or TCH/H lchan and inititate a channel</span><br><span>                 * release to make room for the incoming emergency call */</span><br><span style="color: hsl(0, 100%, 40%);">-              rqd->release_lchan = get_any_lchan(rqd->bts);</span><br><span style="color: hsl(0, 100%, 40%);">-             if (!rqd->release_lchan) {</span><br><span style="color: hsl(120, 100%, 40%);">+         rqd->release_lchan = release_lchan = get_any_lchan(rqd->bts);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!release_lchan) {</span><br><span>                        /* It can not happen that we first find out that there</span><br><span>                        * is no TCH/H or TCH/F available and at the same time</span><br><span>                        * we ware unable to find any busy TCH/H or TCH/F. In</span><br><span>@@ -1707,10 +1710,18 @@</span><br><span> </span><br><span>          LOG_BTS(rqd->bts, DRSL, LOGL_NOTICE,</span><br><span>                      "CHAN RQD/EMERGENCY-PRIORITY: inducing termination of lchan %s (state:%s) in favor of incoming EMERGENCY CALL!\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                    gsm_lchan_name(rqd->release_lchan), osmo_fsm_inst_state_name(rqd->release_lchan->fi));</span><br><span style="color: hsl(120, 100%, 40%);">+                       gsm_lchan_name(release_lchan), osmo_fsm_inst_state_name(release_lchan->fi));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-             lchan_release(rqd->release_lchan, !!(rqd->release_lchan->conn), true, 0,</span><br><span style="color: hsl(0, 100%, 40%);">-                             gscon_last_eutran_plmn(rqd->release_lchan->conn));</span><br><span style="color: hsl(120, 100%, 40%);">+                lchan_release(release_lchan, !!(release_lchan->conn), true, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                           gscon_last_eutran_plmn(release_lchan->conn));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Also release any overlapping VAMOS multiplexes on this lchan */</span><br><span style="color: hsl(120, 100%, 40%);">+            for (i = 0; i < 2; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  struct gsm_lchan *lchan_vamos = gsm_lchan_primary_to_vamos(release_lchan, i);</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (lchan_vamos)</span><br><span style="color: hsl(120, 100%, 40%);">+                              lchan_release(lchan_vamos, !!(lchan_vamos->conn), true, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                                       gscon_last_eutran_plmn(lchan_vamos->conn));</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span>    } else {</span><br><span>             /* BTS is shutting down, give up... */</span><br><span>               if (rqd->release_lchan->ts->fi->state == TS_ST_NOT_INITIALIZED)</span><br><span>diff --git a/src/osmo-bsc/assignment_fsm.c b/src/osmo-bsc/assignment_fsm.c</span><br><span>index d3bdaf1..854a906 100644</span><br><span>--- a/src/osmo-bsc/assignment_fsm.c</span><br><span>+++ b/src/osmo-bsc/assignment_fsm.c</span><br><span>@@ -637,6 +637,7 @@</span><br><span>           .ta_known = true,</span><br><span>            .tsc_set = req->tsc_set,</span><br><span>          .tsc = req->tsc,</span><br><span style="color: hsl(120, 100%, 40%);">+           .vamos = conn->assignment.new_lchan->vamos.is_secondary,</span><br><span>       };</span><br><span>   lchan_activate(conn->assignment.new_lchan, &activ_info);</span><br><span> }</span><br><span>diff --git a/src/osmo-bsc/gsm_data.c b/src/osmo-bsc/gsm_data.c</span><br><span>index 159c016..85ce8bf 100644</span><br><span>--- a/src/osmo-bsc/gsm_data.c</span><br><span>+++ b/src/osmo-bsc/gsm_data.c</span><br><span>@@ -337,8 +337,9 @@</span><br><span> char *gsm_lchan_name_compute(void *ctx, const struct gsm_lchan *lchan)</span><br><span> {</span><br><span>   struct gsm_bts_trx_ts *ts = lchan->ts;</span><br><span style="color: hsl(0, 100%, 40%);">-       return talloc_asprintf(ctx, "(bts=%d,trx=%d,ts=%d,ss=%d)",</span><br><span style="color: hsl(0, 100%, 40%);">-                           ts->trx->bts->nr, ts->trx->nr, ts->nr, lchan->nr);</span><br><span style="color: hsl(120, 100%, 40%);">+        return talloc_asprintf(ctx, "(bts=%d,trx=%d,ts=%d,ss=%d%s)",</span><br><span style="color: hsl(120, 100%, 40%);">+                               ts->trx->bts->nr, ts->trx->nr, ts->nr, lchan->nr,</span><br><span style="color: hsl(120, 100%, 40%);">+                        lchan->vamos.is_secondary ? "-VAMOS" : "");</span><br><span> }</span><br><span> </span><br><span> /* obtain the MO structure for a given object instance */</span><br><span>@@ -545,9 +546,13 @@</span><br><span> </span><br><span> uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-     /* Note: non-standard Osmocom style dyn TS PDCH mode chan_nr is only used within</span><br><span style="color: hsl(0, 100%, 40%);">-         * rsl_tx_dyn_ts_pdch_act_deact(). */</span><br><span style="color: hsl(0, 100%, 40%);">-   return gsm_pchan2chan_nr(lchan->ts->pchan_is, lchan->ts->nr, lchan->nr);</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t lchan_nr = lchan->nr;</span><br><span style="color: hsl(120, 100%, 40%);">+      /* The VAMOS lchans are behind the primary ones in the ts->lchan[] array. They keep their lchan->nr as in the</span><br><span style="color: hsl(120, 100%, 40%);">+    * array, but on the wire they are the "shadow" lchans for the primary lchans. For example, for TCH/F, there is</span><br><span style="color: hsl(120, 100%, 40%);">+      * a primary ts->lchan[0] and a VAMOS ts->lchan[1]. Still, the VAMOS lchan should send chan_nr = 0. */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (lchan->vamos.is_secondary)</span><br><span style="color: hsl(120, 100%, 40%);">+             lchan_nr -= lchan->ts->max_primary_lchans;</span><br><span style="color: hsl(120, 100%, 40%);">+      return gsm_pchan2chan_nr(lchan->ts->pchan_is, lchan->ts->nr, lchan_nr);</span><br><span> }</span><br><span> </span><br><span> static const uint8_t subslots_per_pchan[] = {</span><br><span>@@ -574,6 +579,30 @@</span><br><span>         return subslots_per_pchan[pchan];</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static const uint8_t subslots_per_pchan_vamos[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+       [GSM_PCHAN_NONE] = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+ [GSM_PCHAN_CCCH] = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+ [GSM_PCHAN_PDCH] = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+ [GSM_PCHAN_CCCH_SDCCH4] = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+  /* VAMOS: on a TCH/F, there may be a TCH/H shadow */</span><br><span style="color: hsl(120, 100%, 40%);">+  [GSM_PCHAN_TCH_F] = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+        [GSM_PCHAN_TCH_H] = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+        [GSM_PCHAN_SDCCH8_SACCH8C] = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+       [GSM_PCHAN_CCCH_SDCCH4_CBCH] = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+     [GSM_PCHAN_SDCCH8_SACCH8C_CBCH] = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+  [GSM_PCHAN_TCH_F_TCH_H_PDCH] = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+     [GSM_PCHAN_TCH_F_PDCH] = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Return the maximum number of VAMOS secondary lchans that may be used in a timeslot of the given physical channel</span><br><span style="color: hsl(120, 100%, 40%);">+ * configuration. */</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t pchan_subslots_vamos(enum gsm_phys_chan_config pchan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        if (pchan < 0 || pchan >= ARRAY_SIZE(subslots_per_pchan_vamos))</span><br><span style="color: hsl(120, 100%, 40%);">+         return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     return subslots_per_pchan_vamos[pchan];</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static bool pchan_is_tch(enum gsm_phys_chan_config pchan)</span><br><span> {</span><br><span>       switch (pchan) {</span><br><span>@@ -590,6 +619,80 @@</span><br><span>      return pchan_is_tch(ts->pchan_is);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct gsm_lchan *gsm_lchan_vamos_to_primary(const struct gsm_lchan *lchan_vamos, int idx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm_lchan *lchan_primary;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!lchan_vamos || !lchan_vamos->vamos.is_secondary)</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        lchan_primary = &lchan_vamos->ts->lchan[0];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       switch (idx) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+               goto return_lchan_primary;</span><br><span style="color: hsl(120, 100%, 40%);">+    case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (lchan_primary->type) {</span><br><span style="color: hsl(120, 100%, 40%);">+     case GSM_LCHAN_TCH_F:</span><br><span style="color: hsl(120, 100%, 40%);">+         return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+      case GSM_LCHAN_TCH_H:</span><br><span style="color: hsl(120, 100%, 40%);">+         lchan_primary = &lchan_vamos->ts->lchan[1];</span><br><span style="color: hsl(120, 100%, 40%);">+         break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+return_lchan_primary:</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!lchan_primary->fi)</span><br><span style="color: hsl(120, 100%, 40%);">+            return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return lchan_primary;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct gsm_lchan *gsm_lchan_primary_to_vamos(const struct gsm_lchan *lchan_primary, int idx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct gsm_lchan *first_vamos_lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct gsm_lchan *lchan_vamos;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct gsm_bts_trx_ts *ts;</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!lchan_primary || lchan_primary->vamos.is_secondary)</span><br><span style="color: hsl(120, 100%, 40%);">+           return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        ts = lchan_primary->ts;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  first_vamos_lchan = &ts->lchan[ts->max_primary_lchans];</span><br><span style="color: hsl(120, 100%, 40%);">+     if (first_vamos_lchan == ts->lchan)</span><br><span style="color: hsl(120, 100%, 40%);">+                return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        lchan_vamos = first_vamos_lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (idx) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+               goto return_lchan_vamos;</span><br><span style="color: hsl(120, 100%, 40%);">+      case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (lchan_vamos->type) {</span><br><span style="color: hsl(120, 100%, 40%);">+       case GSM_LCHAN_TCH_F:</span><br><span style="color: hsl(120, 100%, 40%);">+         return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+      case GSM_LCHAN_TCH_H:</span><br><span style="color: hsl(120, 100%, 40%);">+         lchan_vamos = first_vamos_lchan + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+          break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+return_lchan_vamos:</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!lchan_vamos->fi)</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return lchan_vamos;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct gsm_bts *conn_get_bts(struct gsm_subscriber_connection *conn) {</span><br><span>   if (!conn || !conn->lchan)</span><br><span>                return NULL;</span><br><span>diff --git a/src/osmo-bsc/lchan_fsm.c b/src/osmo-bsc/lchan_fsm.c</span><br><span>index f20c147..f233a5a 100644</span><br><span>--- a/src/osmo-bsc/lchan_fsm.c</span><br><span>+++ b/src/osmo-bsc/lchan_fsm.c</span><br><span>@@ -649,7 +649,7 @@</span><br><span>                      lchan->bs_power = bts->bs_power_ctrl.bs_power_val_db / 2;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (info->ch_mode_rate.chan_mode == GSM48_CMODE_SPEECH_AMR) {</span><br><span style="color: hsl(120, 100%, 40%);">+      if (gsm48_chan_mode_to_non_vamos(info->ch_mode_rate.chan_mode) == GSM48_CMODE_SPEECH_AMR) {</span><br><span>               if (lchan_mr_config(&lchan->activate.mr_conf_filtered, lchan, info->ch_mode_rate.s15_s0) < 0) {</span><br><span>                         lchan_fail("Can not generate multirate configuration IE\n");</span><br><span>                       return;</span><br><span>diff --git a/src/osmo-bsc/timeslot_fsm.c b/src/osmo-bsc/timeslot_fsm.c</span><br><span>index 8d340fb..d1f49a3 100644</span><br><span>--- a/src/osmo-bsc/timeslot_fsm.c</span><br><span>+++ b/src/osmo-bsc/timeslot_fsm.c</span><br><span>@@ -195,18 +195,39 @@</span><br><span>     ts->max_primary_lchans = pchan_subslots(ts->pchan_is);</span><br><span>         LOG_TS(ts, LOGL_DEBUG, "pchan_is=%s max_primary_lchans=%d max_lchans_possible=%d\n",</span><br><span>              gsm_pchan_name(ts->pchan_is), ts->max_primary_lchans, ts->max_lchans_possible);</span><br><span style="color: hsl(120, 100%, 40%);">+       switch (ts->pchan_is) {</span><br><span style="color: hsl(120, 100%, 40%);">+    case GSM_PCHAN_TCH_F:</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM_PCHAN_TCH_H:</span><br><span style="color: hsl(120, 100%, 40%);">+         for (i = 0; i < ts->max_lchans_possible; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 lchan = &ts->lchan[i];</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (i < ts->max_primary_lchans)</span><br><span style="color: hsl(120, 100%, 40%);">+                         lchan->vamos.is_secondary = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                 else</span><br><span style="color: hsl(120, 100%, 40%);">+                          lchan->vamos.is_secondary = true;</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              ts_for_n_lchans(lchan, ts, ts->max_lchans_possible)</span><br><span style="color: hsl(120, 100%, 40%);">+                        lchan->vamos.is_secondary = false;</span><br><span style="color: hsl(120, 100%, 40%);">+         break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span> }</span><br><span> </span><br><span> static void ts_setup_lchans(struct gsm_bts_trx_ts *ts)</span><br><span> {</span><br><span>    int i, max_lchans;</span><br><span style="color: hsl(120, 100%, 40%);">+    int max_lchans_vamos;</span><br><span> </span><br><span>    ts->pchan_on_init = ts->pchan_from_config;</span><br><span>     ts_fsm_update_id(ts);</span><br><span> </span><br><span>    max_lchans = pchan_subslots(ts->pchan_on_init);</span><br><span style="color: hsl(0, 100%, 40%);">-      LOG_TS(ts, LOGL_DEBUG, "max lchans: %d\n", max_lchans);</span><br><span style="color: hsl(0, 100%, 40%);">-       ts->max_lchans_possible = max_lchans;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (osmo_bts_has_feature(&ts->trx->bts->features, BTS_FEAT_VAMOS))</span><br><span style="color: hsl(120, 100%, 40%);">+               max_lchans_vamos = pchan_subslots_vamos(ts->pchan_on_init);</span><br><span style="color: hsl(120, 100%, 40%);">+        else</span><br><span style="color: hsl(120, 100%, 40%);">+          max_lchans_vamos = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ LOG_TS(ts, LOGL_DEBUG, "max lchans: %d + %d VAMOS secondaries\n", max_lchans, max_lchans_vamos);</span><br><span style="color: hsl(120, 100%, 40%);">+    ts->max_lchans_possible = max_lchans + max_lchans_vamos;</span><br><span>  ts->max_primary_lchans = 0;</span><br><span> </span><br><span>   for (i = 0; i < ts->max_lchans_possible; i++) {</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-bsc/+/24377">change 24377</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-bsc/+/24377"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-bsc </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I928af99498bba488d317693f3144d4fccbbe9af3 </div>
<div style="display:none"> Gerrit-Change-Number: 24377 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>