fixeria has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-bts/+/27802 )


Change subject: osmo-bts-trx: move tx_tch_common() into a separate file
......................................................................

osmo-bts-trx: move tx_tch_common() into a separate file

Having this function defined as 'static inline' in a header file
would allow the compiler to optimize it better for particular caller.

Change-Id: Id0b9d604e6969a8db73ef451fbcad00f57325fc4
Related: SYS#5919, OS#4823
---
M src/osmo-bts-trx/Makefile.am
M src/osmo-bts-trx/sched_lchan_tchf.c
M src/osmo-bts-trx/sched_lchan_tchh.c
A src/osmo-bts-trx/sched_tch.h
4 files changed, 218 insertions(+), 196 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/02/27802/1

diff --git a/src/osmo-bts-trx/Makefile.am b/src/osmo-bts-trx/Makefile.am
index f6094dd..b7a4e8b 100644
--- a/src/osmo-bts-trx/Makefile.am
+++ b/src/osmo-bts-trx/Makefile.am
@@ -30,6 +30,7 @@

 noinst_HEADERS = \
        sched_utils.h \
+       sched_tch.h \
        trx_if.h \
        l1_if.h \
        amr_loop.h \
diff --git a/src/osmo-bts-trx/sched_lchan_tchf.c 
b/src/osmo-bts-trx/sched_lchan_tchf.c
index 8ca0961..e6e1eff 100644
--- a/src/osmo-bts-trx/sched_lchan_tchf.c
+++ b/src/osmo-bts-trx/sched_lchan_tchf.c
@@ -43,6 +43,7 @@
 #include <osmo-bts/msg_utils.h>

 #include <sched_utils.h>
+#include <sched_tch.h>
 #include <amr_loop.h>

 /* 3GPP TS 45.009, table 3.2.1.3-{1,3}: AMR on Uplink TCH/F.
@@ -319,196 +320,6 @@
                                      meas_avg.ci_cb, is_sub);
 }

-/* common section for generation of TCH bursts (TCH/H and TCH/F).
- * FIXME: this function is over-complicated, refactor / get rid of it. */
-void tx_tch_common(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br,
-                  struct msgb **_msg_tch, struct msgb **_msg_facch)
-{
-       struct msgb *msg1, *msg2, *msg_tch = NULL, *msg_facch = NULL;
-       struct l1sched_chan_state *chan_state = &l1ts->chan_state[br->chan];
-       uint8_t rsl_cmode = chan_state->rsl_cmode;
-       uint8_t tch_mode = chan_state->tch_mode;
-       struct osmo_phsap_prim *l1sap;
-
-       /* handle loss detection of received TCH frames */
-       if (rsl_cmode == RSL_CMOD_SPD_SPEECH
-           && ++(chan_state->lost_frames) > 5) {
-               uint8_t tch_data[GSM_FR_BYTES];
-               int len;
-
-               LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Missing TCH bursts 
detected, sending BFI\n");
-
-               /* indicate bad frame */
-               switch (tch_mode) {
-               case GSM48_CMODE_SPEECH_V1: /* FR / HR */
-                       if (br->chan != TRXC_TCHF) { /* HR */
-                               tch_data[0] = 0x70; /* F = 0, FT = 111 */
-                               memset(tch_data + 1, 0, 14);
-                               len = 15;
-                               break;
-                       }
-                       memset(tch_data, 0, GSM_FR_BYTES);
-                       len = GSM_FR_BYTES;
-                       break;
-               case GSM48_CMODE_SPEECH_EFR: /* EFR */
-                       if (br->chan != TRXC_TCHF)
-                               goto inval_mode1;
-                       memset(tch_data, 0, GSM_EFR_BYTES);
-                       len = GSM_EFR_BYTES;
-                       break;
-               case GSM48_CMODE_SPEECH_AMR: /* AMR */
-                       len = osmo_amr_rtp_enc(tch_data,
-                               chan_state->codec[chan_state->dl_cmr],
-                               chan_state->codec[chan_state->dl_ft], AMR_BAD);
-                       if (len < 2) {
-                               LOGL1SB(DL1P, LOGL_ERROR, l1ts, br,
-                                       "Failed to encode AMR_BAD frame 
(rc=%d), "
-                                       "not sending BFI\n", len);
-                               return;
-                       }
-                       memset(tch_data + 2, 0, len - 2);
-                       break;
-               default:
-inval_mode1:
-                       LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "TCH mode invalid, 
please fix!\n");
-                       len = 0;
-               }
-
-               if (len) {
-                       /* Note: RSSI/ToA256 is set to 0 to indicate to the 
higher
-                        * layers that this is a faked tch_ind */
-                       _sched_compose_tch_ind(l1ts, br->fn, br->chan,
-                                              tch_data, len, 0, 10000, 0, 0, 
0);
-               }
-       }
-
-       /* get frame and unlink from queue */
-       msg1 = _sched_dequeue_prim(l1ts, br);
-       msg2 = _sched_dequeue_prim(l1ts, br);
-       if (msg1) {
-               l1sap = msgb_l1sap_prim(msg1);
-               if (l1sap->oph.primitive == PRIM_TCH) {
-                       msg_tch = msg1;
-                       if (msg2) {
-                               l1sap = msgb_l1sap_prim(msg2);
-                               if (l1sap->oph.primitive == PRIM_TCH) {
-                                       LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, 
"TCH twice, please FIX!\n");
-                                       msgb_free(msg2);
-                               } else
-                                       msg_facch = msg2;
-                       }
-               } else {
-                       msg_facch = msg1;
-                       if (msg2) {
-                               l1sap = msgb_l1sap_prim(msg2);
-                               if (l1sap->oph.primitive != PRIM_TCH) {
-                                       LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, 
"FACCH twice, please FIX!\n");
-                                       msgb_free(msg2);
-                               } else
-                                       msg_tch = msg2;
-                       }
-               }
-       }
-
-       /* check validity of message */
-       if (msg_facch && msgb_l2len(msg_facch) != GSM_MACBLOCK_LEN) {
-               LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, "Prim has odd len=%u != 
%u\n",
-                       msgb_l2len(msg_facch), GSM_MACBLOCK_LEN);
-               /* free message */
-               msgb_free(msg_facch);
-               msg_facch = NULL;
-       }
-
-       /* check validity of message, get AMR ft and cmr */
-       if (!msg_facch && msg_tch) {
-               int len;
-               uint8_t cmr_codec;
-               int cmr, ft, i;
-               enum osmo_amr_type ft_codec;
-               enum osmo_amr_quality bfi;
-               int8_t sti, cmi;
-               bool amr_is_cmr = !dl_amr_fn_is_cmi(br->fn);
-
-               if (rsl_cmode != RSL_CMOD_SPD_SPEECH) {
-                       LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Dropping speech 
frame, "
-                               "because we are not in speech mode\n");
-                       goto free_bad_msg;
-               }
-
-               switch (tch_mode) {
-               case GSM48_CMODE_SPEECH_V1: /* FR / HR */
-                       if (br->chan != TRXC_TCHF) /* HR */
-                               len = 15;
-                       else
-                               len = GSM_FR_BYTES;
-                       break;
-               case GSM48_CMODE_SPEECH_EFR: /* EFR */
-                       if (br->chan != TRXC_TCHF)
-                               goto inval_mode2;
-                       len = GSM_EFR_BYTES;
-                       break;
-               case GSM48_CMODE_SPEECH_AMR: /* AMR */
-                       len = osmo_amr_rtp_dec(msg_tch->l2h, 
msgb_l2len(msg_tch),
-                                              &cmr_codec, &cmi, &ft_codec,
-                                              &bfi, &sti);
-                       if (len < 0) {
-                               LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "Cannot 
send invalid AMR payload\n");
-                               goto free_bad_msg;
-                       }
-                       cmr = -1;
-                       ft = -1;
-                       for (i = 0; i < chan_state->codecs; i++) {
-                               if (chan_state->codec[i] == cmr_codec)
-                                       cmr = i;
-                               if (chan_state->codec[i] == ft_codec)
-                                       ft = i;
-                       }
-                       if (cmr >= 0) { /* new request */
-                               chan_state->dl_cmr = cmr;
-                               /* disable AMR loop */
-                               trx_loop_amr_set(chan_state, 0);
-                       } else {
-                               /* enable AMR loop */
-                               trx_loop_amr_set(chan_state, 1);
-                       }
-                       if (ft < 0) {
-                               LOGL1SB(DL1P, LOGL_ERROR, l1ts, br,
-                                       "Codec (FT = %d) of RTP frame not in 
list\n", ft_codec);
-                               goto free_bad_msg;
-                       }
-                       if (amr_is_cmr && chan_state->dl_ft != ft) {
-                               LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Codec (FT 
= %d) "
-                                       " of RTP cannot be changed now, but in 
next frame\n", ft_codec);
-                               goto free_bad_msg;
-                       }
-                       chan_state->dl_ft = ft;
-                       if (bfi == AMR_BAD) {
-                               LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, 
"Transmitting 'bad AMR frame'\n");
-                               goto free_bad_msg;
-                       }
-                       break;
-               default:
-inval_mode2:
-                       LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "TCH mode invalid, 
please fix!\n");
-                       goto free_bad_msg;
-               }
-               if (msgb_l2len(msg_tch) != len) {
-                       LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "Cannot send 
payload with "
-                               "invalid length! (expecting %d, received %d)\n",
-                               len, msgb_l2len(msg_tch));
-free_bad_msg:
-                       /* free message */
-                       msgb_free(msg_tch);
-                       msg_tch = NULL;
-                       goto send_frame;
-               }
-       }
-
-send_frame:
-       *_msg_tch = msg_tch;
-       *_msg_facch = msg_facch;
-}
-
 /* obtain a to-be-transmitted TCH/F (Full Traffic Channel) burst */
 int tx_tchf_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br)
 {
diff --git a/src/osmo-bts-trx/sched_lchan_tchh.c 
b/src/osmo-bts-trx/sched_lchan_tchh.c
index e3ce600..bacd49b 100644
--- a/src/osmo-bts-trx/sched_lchan_tchh.c
+++ b/src/osmo-bts-trx/sched_lchan_tchh.c
@@ -43,6 +43,7 @@
 #include <osmo-bts/msg_utils.h>

 #include <sched_utils.h>
+#include <sched_tch.h>
 #include <amr_loop.h>

 /* 3GPP TS 45.009, table 3.2.1.3-{2,4}: AMR on Uplink TCH/H.
@@ -350,12 +351,6 @@
                                      meas_avg.ci_cb, is_sub);
 }

-/* common section for generation of TCH bursts (TCH/H and TCH/F).
- * FIXME: this function is over-complicated, refactor / get rid of it. */
-extern void tx_tch_common(struct l1sched_ts *l1ts,
-                         const struct trx_dl_burst_req *br,
-                         struct msgb **_msg_tch, struct msgb **_msg_facch);
-
 /* obtain a to-be-transmitted TCH/H (Half Traffic Channel) burst */
 int tx_tchh_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br)
 {
diff --git a/src/osmo-bts-trx/sched_tch.h b/src/osmo-bts-trx/sched_tch.h
new file mode 100644
index 0000000..f3e9c69
--- /dev/null
+++ b/src/osmo-bts-trx/sched_tch.h
@@ -0,0 +1,215 @@
+/* Common API for TCH channels.
+ *
+ * (C) 2013 by Andreas Eversberg <[email protected]>
+ * (C) 2015-2017 by Harald Welte <[email protected]>
+ * Contributions by sysmocom - s.f.m.c. GmbH
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+void trx_loop_amr_set(struct l1sched_chan_state *chan_state, int loop);
+
+/* Common section for generation of Downlink bursts (TCH/H and TCH/F) */
+static inline void tx_tch_common(struct l1sched_ts *l1ts, struct 
trx_dl_burst_req *br,
+                                struct msgb **_msg_tch, struct msgb 
**_msg_facch)
+{
+       struct msgb *msg1, *msg2, *msg_tch = NULL, *msg_facch = NULL;
+       struct l1sched_chan_state *chan_state = &l1ts->chan_state[br->chan];
+       uint8_t rsl_cmode = chan_state->rsl_cmode;
+       uint8_t tch_mode = chan_state->tch_mode;
+       struct osmo_phsap_prim *l1sap;
+
+       /* handle loss detection of received TCH frames */
+       if (rsl_cmode == RSL_CMOD_SPD_SPEECH
+           && ++(chan_state->lost_frames) > 5) {
+               uint8_t tch_data[GSM_FR_BYTES];
+               int len;
+
+               LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Missing TCH bursts 
detected, sending BFI\n");
+
+               /* indicate bad frame */
+               switch (tch_mode) {
+               case GSM48_CMODE_SPEECH_V1: /* FR / HR */
+                       if (br->chan != TRXC_TCHF) { /* HR */
+                               tch_data[0] = 0x70; /* F = 0, FT = 111 */
+                               memset(tch_data + 1, 0, 14);
+                               len = 15;
+                               break;
+                       }
+                       memset(tch_data, 0, GSM_FR_BYTES);
+                       len = GSM_FR_BYTES;
+                       break;
+               case GSM48_CMODE_SPEECH_EFR: /* EFR */
+                       if (br->chan != TRXC_TCHF)
+                               goto inval_mode1;
+                       memset(tch_data, 0, GSM_EFR_BYTES);
+                       len = GSM_EFR_BYTES;
+                       break;
+               case GSM48_CMODE_SPEECH_AMR: /* AMR */
+                       len = osmo_amr_rtp_enc(tch_data,
+                               chan_state->codec[chan_state->dl_cmr],
+                               chan_state->codec[chan_state->dl_ft], AMR_BAD);
+                       if (len < 2) {
+                               LOGL1SB(DL1P, LOGL_ERROR, l1ts, br,
+                                       "Failed to encode AMR_BAD frame 
(rc=%d), "
+                                       "not sending BFI\n", len);
+                               return;
+                       }
+                       memset(tch_data + 2, 0, len - 2);
+                       break;
+               default:
+inval_mode1:
+                       LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "TCH mode invalid, 
please fix!\n");
+                       len = 0;
+               }
+
+               if (len) {
+                       /* Note: RSSI/ToA256 is set to 0 to indicate to the 
higher
+                        * layers that this is a faked tch_ind */
+                       _sched_compose_tch_ind(l1ts, br->fn, br->chan,
+                                              tch_data, len, 0, 10000, 0, 0, 
0);
+               }
+       }
+
+       /* get frame and unlink from queue */
+       msg1 = _sched_dequeue_prim(l1ts, br);
+       msg2 = _sched_dequeue_prim(l1ts, br);
+       if (msg1) {
+               l1sap = msgb_l1sap_prim(msg1);
+               if (l1sap->oph.primitive == PRIM_TCH) {
+                       msg_tch = msg1;
+                       if (msg2) {
+                               l1sap = msgb_l1sap_prim(msg2);
+                               if (l1sap->oph.primitive == PRIM_TCH) {
+                                       LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, 
"TCH twice, please FIX!\n");
+                                       msgb_free(msg2);
+                               } else
+                                       msg_facch = msg2;
+                       }
+               } else {
+                       msg_facch = msg1;
+                       if (msg2) {
+                               l1sap = msgb_l1sap_prim(msg2);
+                               if (l1sap->oph.primitive != PRIM_TCH) {
+                                       LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, 
"FACCH twice, please FIX!\n");
+                                       msgb_free(msg2);
+                               } else
+                                       msg_tch = msg2;
+                       }
+               }
+       }
+
+       /* check validity of message */
+       if (msg_facch && msgb_l2len(msg_facch) != GSM_MACBLOCK_LEN) {
+               LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, "Prim has odd len=%u != 
%u\n",
+                       msgb_l2len(msg_facch), GSM_MACBLOCK_LEN);
+               /* free message */
+               msgb_free(msg_facch);
+               msg_facch = NULL;
+       }
+
+       /* check validity of message, get AMR ft and cmr */
+       if (!msg_facch && msg_tch) {
+               int len;
+               uint8_t cmr_codec;
+               int cmr, ft, i;
+               enum osmo_amr_type ft_codec;
+               enum osmo_amr_quality bfi;
+               int8_t sti, cmi;
+               bool amr_is_cmr = !dl_amr_fn_is_cmi(br->fn);
+
+               if (rsl_cmode != RSL_CMOD_SPD_SPEECH) {
+                       LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Dropping speech 
frame, "
+                               "because we are not in speech mode\n");
+                       goto free_bad_msg;
+               }
+
+               switch (tch_mode) {
+               case GSM48_CMODE_SPEECH_V1: /* FR / HR */
+                       if (br->chan != TRXC_TCHF) /* HR */
+                               len = 15;
+                       else
+                               len = GSM_FR_BYTES;
+                       break;
+               case GSM48_CMODE_SPEECH_EFR: /* EFR */
+                       if (br->chan != TRXC_TCHF)
+                               goto inval_mode2;
+                       len = GSM_EFR_BYTES;
+                       break;
+               case GSM48_CMODE_SPEECH_AMR: /* AMR */
+                       len = osmo_amr_rtp_dec(msg_tch->l2h, 
msgb_l2len(msg_tch),
+                                              &cmr_codec, &cmi, &ft_codec,
+                                              &bfi, &sti);
+                       if (len < 0) {
+                               LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "Cannot 
send invalid AMR payload\n");
+                               goto free_bad_msg;
+                       }
+                       cmr = -1;
+                       ft = -1;
+                       for (i = 0; i < chan_state->codecs; i++) {
+                               if (chan_state->codec[i] == cmr_codec)
+                                       cmr = i;
+                               if (chan_state->codec[i] == ft_codec)
+                                       ft = i;
+                       }
+                       if (cmr >= 0) { /* new request */
+                               chan_state->dl_cmr = cmr;
+                               /* disable AMR loop */
+                               trx_loop_amr_set(chan_state, 0);
+                       } else {
+                               /* enable AMR loop */
+                               trx_loop_amr_set(chan_state, 1);
+                       }
+                       if (ft < 0) {
+                               LOGL1SB(DL1P, LOGL_ERROR, l1ts, br,
+                                       "Codec (FT = %d) of RTP frame not in 
list\n", ft_codec);
+                               goto free_bad_msg;
+                       }
+                       if (amr_is_cmr && chan_state->dl_ft != ft) {
+                               LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Codec (FT 
= %d) "
+                                       " of RTP cannot be changed now, but in 
next frame\n", ft_codec);
+                               goto free_bad_msg;
+                       }
+                       chan_state->dl_ft = ft;
+                       if (bfi == AMR_BAD) {
+                               LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, 
"Transmitting 'bad AMR frame'\n");
+                               goto free_bad_msg;
+                       }
+                       break;
+               default:
+inval_mode2:
+                       LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "TCH mode invalid, 
please fix!\n");
+                       goto free_bad_msg;
+               }
+               if (msgb_l2len(msg_tch) != len) {
+                       LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "Cannot send 
payload with "
+                               "invalid length! (expecting %d, received %d)\n",
+                               len, msgb_l2len(msg_tch));
+free_bad_msg:
+                       /* free message */
+                       msgb_free(msg_tch);
+                       msg_tch = NULL;
+                       goto send_frame;
+               }
+       }
+
+send_frame:
+       *_msg_tch = msg_tch;
+       *_msg_facch = msg_facch;
+}

--
To view, visit https://gerrit.osmocom.org/c/osmo-bts/+/27802
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: Id0b9d604e6969a8db73ef451fbcad00f57325fc4
Gerrit-Change-Number: 27802
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <[email protected]>
Gerrit-MessageType: newchange

Reply via email to