mobile: fix GAPK I/O producing too many UL frames

GAPK I/O is currently generating too many UL voice frames, causing
Tx queue overflow in the L1 PHY.  Change the logic to make DL voice
frames drive the Uplink processing chain, like we do for CSD.

Change-Id: I3a7fa223cb592acd5b850819e0682c9c8f81e9d1
This commit is contained in:
Vadim Yanitskiy 2024-02-06 04:03:36 +07:00
parent 20107916e5
commit f12b17dffb
6 changed files with 18 additions and 71 deletions

View File

@ -42,6 +42,6 @@ gapk_io_state_alloc_mode_rate(struct osmocom_ms *ms,
void gapk_io_state_free(struct gapk_io_state *state);
void gapk_io_enqueue_dl(struct gapk_io_state *state, struct msgb *msg);
int gapk_io_serve_ms(struct osmocom_ms *ms, struct gapk_io_state *state);
void gapk_io_dequeue_ul(struct osmocom_ms *ms, struct gapk_io_state *state);
#endif /* WITH_GAPK_IO */

View File

@ -24,6 +24,5 @@ struct tch_state {
};
int tch_init(struct osmocom_ms *ms);
int tch_serve_ms(struct osmocom_ms *ms);
int tch_send_msg(struct osmocom_ms *ms, struct msgb *msg);
int tch_send_mncc_frame(struct osmocom_ms *ms, const struct gsm_data_frame *frame);

View File

@ -81,7 +81,6 @@ int mobile_work(struct osmocom_ms *ms)
w |= gsm322_cs_dequeue(ms);
w |= gsm_sim_job_dequeue(ms);
w |= mncc_dequeue(ms);
w |= tch_serve_ms(ms);
if (w)
work = 1;
} while (w);

View File

@ -503,6 +503,7 @@ gapk_io_state_alloc_mode_rate(struct osmocom_ms *ms,
return gapk_io_state_alloc(ms, codec);
}
/* Enqueue a Downlink TCH frame */
void gapk_io_enqueue_dl(struct gapk_io_state *state, struct msgb *msg)
{
if (state->tch_dl_fb_len >= GAPK_ULDL_QUEUE_LIMIT) {
@ -513,49 +514,23 @@ void gapk_io_enqueue_dl(struct gapk_io_state *state, struct msgb *msg)
msgb_enqueue_count(&state->tch_dl_fb, msg,
&state->tch_dl_fb_len);
/* Decode and play a received DL TCH frame */
osmo_gapk_pq_execute(state->pq_sink);
}
/* Serves both UL/DL TCH frame I/O buffers */
int gapk_io_serve_ms(struct osmocom_ms *ms, struct gapk_io_state *state)
/* Dequeue an Uplink TCH frame */
void gapk_io_dequeue_ul(struct osmocom_ms *ms, struct gapk_io_state *state)
{
int work = 0;
struct msgb *msg;
/**
* Make sure we have at least two DL frames
* to prevent discontinuous playback.
*/
if (state->tch_dl_fb_len < 2)
return 0;
/* Record and encode an UL TCH frame */
osmo_gapk_pq_execute(state->pq_source);
/**
* TODO: if there is an active call, but no TCH frames
* in DL buffer, put silence frames using the upcoming
* ECU (Error Concealment Unit) of libosmocodec.
*/
while (!llist_empty(&state->tch_dl_fb)) {
/* Decode and play a received DL TCH frame */
osmo_gapk_pq_execute(state->pq_sink);
/* Record and encode an UL TCH frame back */
osmo_gapk_pq_execute(state->pq_source);
work |= 1;
}
while (!llist_empty(&state->tch_ul_fb)) {
struct msgb *tch_msg;
/* Obtain one TCH frame from the UL buffer */
tch_msg = msgb_dequeue_count(&state->tch_ul_fb,
&state->tch_ul_fb_len);
/* Push a voice frame to the lower layers */
tch_send_msg(ms, tch_msg);
work |= 1;
}
return work;
/* Obtain one TCH frame from the UL buffer */
msg = msgb_dequeue_count(&state->tch_ul_fb, &state->tch_ul_fb_len);
if (msg != NULL)
tch_send_msg(ms, msg);
}
/**

View File

@ -45,7 +45,6 @@ void tch_data_state_free(struct tch_data_state *state);
int tch_voice_recv(struct osmocom_ms *ms, struct msgb *msg);
int tch_data_recv(struct osmocom_ms *ms, struct msgb *msg);
int tch_voice_serve_ms(struct osmocom_ms *ms);
/* Receive a Downlink traffic (voice/data) frame from the lower layers */
static int tch_recv_cb(struct osmocom_ms *ms, struct msgb *msg)
@ -116,20 +115,6 @@ int tch_send_mncc_frame(struct osmocom_ms *ms, const struct gsm_data_frame *fram
return tch_send_msg(ms, nmsg);
}
int tch_serve_ms(struct osmocom_ms *ms)
{
struct tch_state *state = ms->tch_state;
int rc = 0;
if (state == NULL)
return 0;
if (state->is_voice)
rc = tch_voice_serve_ms(ms);
/* TODO: else tch_data_serve_ms() */
return rc;
}
static void tch_trans_cstate_active_cb(struct gsm_trans *trans, bool rx_only)
{
struct osmocom_ms *ms = trans->ms;

View File

@ -90,11 +90,12 @@ int tch_voice_recv(struct osmocom_ms *ms, struct msgb *msg)
return tch_forward_mncc(ms, msg);
case TCH_VOICE_IOH_GAPK:
#ifdef WITH_GAPK_IO
/* Enqueue a frame to the DL TCH buffer */
if (state->gapk_io != NULL)
if (state->gapk_io != NULL) {
gapk_io_enqueue_dl(state->gapk_io, msg);
else
gapk_io_dequeue_ul(ms, state->gapk_io);
} else {
msgb_free(msg);
}
break;
#endif
case TCH_VOICE_IOH_L1PHY:
@ -107,18 +108,6 @@ int tch_voice_recv(struct osmocom_ms *ms, struct msgb *msg)
return 0;
}
int tch_voice_serve_ms(struct osmocom_ms *ms)
{
#ifdef WITH_GAPK_IO
struct tch_voice_state *state = &ms->tch_state->voice;
if (state->handler == TCH_VOICE_IOH_GAPK)
return gapk_io_serve_ms(ms, state->gapk_io);
#endif
return 0;
}
int tch_voice_state_init(struct gsm_trans *trans, struct tch_voice_state *state)
{
struct osmocom_ms *ms = trans->ms;