From bd6e320c086b0b272665b82ab794a03755706055 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 5 Jan 2018 07:24:04 +0700 Subject: trxcon/scheduler: use linuxlist API for lchan management As there is no any order relation between logical channels, it's better to use the linuxlist API instead of talloc array. Change-Id: I5a78582c77ed1ab33817d240e065dc4cd4708199 --- src/host/trxcon/l1ctl.c | 14 ++++-- src/host/trxcon/sched_trx.c | 107 ++++++++++++++++++++++---------------------- src/host/trxcon/sched_trx.h | 4 +- 3 files changed, 67 insertions(+), 58 deletions(-) (limited to 'src/host') diff --git a/src/host/trxcon/l1ctl.c b/src/host/trxcon/l1ctl.c index 070ee565..dd75af95 100644 --- a/src/host/trxcon/l1ctl.c +++ b/src/host/trxcon/l1ctl.c @@ -700,8 +700,9 @@ static int l1ctl_rx_param_req(struct l1ctl_link *l1l, struct msgb *msg) static int l1ctl_rx_tch_mode_req(struct l1ctl_link *l1l, struct msgb *msg) { struct l1ctl_tch_mode_req *req; + struct trx_lchan_state *lchan; struct trx_ts *ts; - int len, i, j; + int i; req = (struct l1ctl_tch_mode_req *) msg->l1h; @@ -720,9 +721,14 @@ static int l1ctl_rx_tch_mode_req(struct l1ctl_link *l1l, struct msgb *msg) continue; /* Iterate over all allocated lchans */ - len = talloc_array_length(ts->lchans); - for (j = 0; j < len; j++) - ts->lchans[j].tch_mode = req->tch_mode; + llist_for_each_entry(lchan, &ts->lchans, list) { + /* Omit inactive channels */ + if (!lchan->active) + continue; + + /* Set TCH mode */ + lchan->tch_mode = req->tch_mode; + } } /* TODO: do we need to care about audio_mode? */ diff --git a/src/host/trxcon/sched_trx.c b/src/host/trxcon/sched_trx.c index 95678442..0a9b7f73 100644 --- a/src/host/trxcon/sched_trx.c +++ b/src/host/trxcon/sched_trx.c @@ -185,6 +185,7 @@ struct trx_ts *sched_trx_add_ts(struct trx_instance *trx, int tn) void sched_trx_del_ts(struct trx_instance *trx, int tn) { + struct trx_lchan_state *lchan; struct trx_ts *ts; /* Find ts in list */ @@ -198,7 +199,8 @@ void sched_trx_del_ts(struct trx_instance *trx, int tn) sched_trx_deactivate_all_lchans(ts); /* Free channel states */ - talloc_free(ts->lchans); + llist_for_each_entry(lchan, &ts->lchans, list) + talloc_free(lchan); /* Flush queue primitives for TX */ sched_prim_flush_queue(&ts->tx_prims); @@ -211,10 +213,14 @@ void sched_trx_del_ts(struct trx_instance *trx, int tn) trx_if_cmd_setslot(trx, tn, 0); } +#define LAYOUT_HAS_LCHAN(layout, lchan) \ + (layout->lchan_mask & ((uint64_t) 0x01 << lchan)) + int sched_trx_configure_ts(struct trx_instance *trx, int tn, enum gsm_phys_chan_config config) { - int i, type, lchan_cnt = 0; + struct trx_lchan_state *lchan; + enum trx_lchan_type type; struct trx_ts *ts; /* Try to find specified ts */ @@ -229,9 +235,6 @@ int sched_trx_configure_ts(struct trx_instance *trx, int tn, return -ENOMEM; } - /* Init queue primitives for TX */ - INIT_LLIST_HEAD(&ts->tx_prims); - /* Choose proper multiframe layout */ ts->mf_layout = sched_mframe_layout(config, tn); if (ts->mf_layout->chan_config != config) @@ -240,29 +243,30 @@ int sched_trx_configure_ts(struct trx_instance *trx, int tn, LOGP(DSCH, LOGL_NOTICE, "(Re)configure TDMA timeslot #%u as %s\n", tn, ts->mf_layout->name); - /* Count channel states */ - for (type = 0; type < _TRX_CHAN_MAX; type++) - if (ts->mf_layout->lchan_mask & ((uint64_t) 0x01 << type)) - lchan_cnt++; - - if (!lchan_cnt) - return 0; + /* Init queue primitives for TX */ + INIT_LLIST_HEAD(&ts->tx_prims); + /* Init logical channels list */ + INIT_LLIST_HEAD(&ts->lchans); /* Allocate channel states */ - ts->lchans = talloc_zero_array(ts, struct trx_lchan_state, lchan_cnt); - if (ts->lchans == NULL) - return -ENOMEM; - - /* Init channel states */ - for (type = 0, i = 0; type < _TRX_CHAN_MAX; type++) { - if (ts->mf_layout->lchan_mask & ((uint64_t) 0x01 << type)) { - /* Set proper channel type */ - ts->lchans[i++].type = type; - - /* Enable channel automatically if required */ - if (trx_lchan_desc[type].flags & TRX_CH_FLAG_AUTO) - sched_trx_activate_lchan(ts, type); - } + for (type = 0; type < _TRX_CHAN_MAX; type++) { + if (!LAYOUT_HAS_LCHAN(ts->mf_layout, type)) + continue; + + /* Allocate a channel state */ + lchan = talloc_zero(ts, struct trx_lchan_state); + if (!lchan) + return -ENOMEM; + + /* Set channel type */ + lchan->type = type; + + /* Add to the list of channel states */ + llist_add_tail(&lchan->list, &ts->lchans); + + /* Enable channel automatically if required */ + if (trx_lchan_desc[type].flags & TRX_CH_FLAG_AUTO) + sched_trx_activate_lchan(ts, type); } /* Notify transceiver about TS activation */ @@ -274,6 +278,7 @@ int sched_trx_configure_ts(struct trx_instance *trx, int tn, int sched_trx_reset_ts(struct trx_instance *trx, int tn) { + struct trx_lchan_state *lchan, *lchan_next; struct trx_ts *ts; /* Try to find specified ts */ @@ -294,7 +299,10 @@ int sched_trx_reset_ts(struct trx_instance *trx, int tn) sched_trx_deactivate_all_lchans(ts); /* Free channel states */ - talloc_free(ts->lchans); + llist_for_each_entry_safe(lchan, lchan_next, &ts->lchans, list) { + llist_del(&lchan->list); + talloc_free(lchan); + } /* Notify transceiver about that */ trx_if_cmd_setslot(trx, tn, 0); @@ -305,9 +313,7 @@ int sched_trx_reset_ts(struct trx_instance *trx, int tn) int sched_trx_start_ciphering(struct trx_ts *ts, uint8_t algo, uint8_t *key, uint8_t key_len) { - struct trx_lchan_state *state; - size_t len; - int i; + struct trx_lchan_state *lchan; /* Prevent NULL-pointer deference */ if (!ts) @@ -318,16 +324,18 @@ int sched_trx_start_ciphering(struct trx_ts *ts, uint8_t algo, return -ERANGE; /* Iterate over all allocated logical channels */ - len = talloc_array_length(ts->lchans); - for (i = 0; i < len; i++) { + llist_for_each_entry(lchan, &ts->lchans, list) { + /* Omit inactive channels */ + if (!lchan->active) + continue; + /* Set key length and algorithm */ - state = ts->lchans + i; - state->a5.key_len = key_len; - state->a5.algo = algo; + lchan->a5.key_len = key_len; + lchan->a5.algo = algo; /* Copy requested key */ if (key_len) - memcpy(state->a5.key, key, key_len); + memcpy(lchan->a5.key, key, key_len); } return 0; @@ -336,12 +344,11 @@ int sched_trx_start_ciphering(struct trx_ts *ts, uint8_t algo, struct trx_lchan_state *sched_trx_find_lchan(struct trx_ts *ts, enum trx_lchan_type chan) { - int i, len; + struct trx_lchan_state *lchan; - len = talloc_array_length(ts->lchans); - for (i = 0; i < len; i++) - if (ts->lchans[i].type == chan) - return ts->lchans + i; + llist_for_each_entry(lchan, &ts->lchans, list) + if (lchan->type == chan) + return lchan; return NULL; } @@ -350,18 +357,16 @@ int sched_trx_set_lchans(struct trx_ts *ts, uint8_t chan_nr, int active) { const struct trx_lchan_desc *lchan_desc; struct trx_lchan_state *lchan; - int len, i, rc = 0; + int rc = 0; /* Prevent NULL-pointer deference */ - if (ts == NULL || ts->lchans == NULL) { + if (ts == NULL) { LOGP(DSCH, LOGL_ERROR, "Timeslot isn't configured\n"); return -EINVAL; } /* Iterate over all allocated lchans */ - len = talloc_array_length(ts->lchans); - for (i = 0; i < len; i++) { - lchan = ts->lchans + i; + llist_for_each_entry(lchan, &ts->lchans, list) { lchan_desc = &trx_lchan_desc[lchan->type]; if (lchan_desc->chan_nr == (chan_nr & 0xf8)) { @@ -396,14 +401,14 @@ int sched_trx_activate_lchan(struct trx_ts *ts, enum trx_lchan_type chan) /* Conditionally allocate memory for bursts */ if (lchan_desc->rx_fn && lchan_desc->burst_buf_size > 0) { - lchan->rx_bursts = talloc_zero_size(ts->lchans, + lchan->rx_bursts = talloc_zero_size(lchan, lchan_desc->burst_buf_size); if (lchan->rx_bursts == NULL) return -ENOMEM; } if (lchan_desc->tx_fn && lchan_desc->burst_buf_size > 0) { - lchan->tx_bursts = talloc_zero_size(ts->lchans, + lchan->tx_bursts = talloc_zero_size(lchan, lchan_desc->burst_buf_size); if (lchan->tx_bursts == NULL) return -ENOMEM; @@ -481,15 +486,11 @@ int sched_trx_deactivate_lchan(struct trx_ts *ts, enum trx_lchan_type chan) void sched_trx_deactivate_all_lchans(struct trx_ts *ts) { struct trx_lchan_state *lchan; - int i, len; LOGP(DSCH, LOGL_DEBUG, "Deactivating all logical channels " "on ts=%d\n", ts->index); - len = talloc_array_length(ts->lchans); - for (i = 0; i < len; i++) { - lchan = ts->lchans + i; - + llist_for_each_entry(lchan, &ts->lchans, list) { /* Omit inactive channels */ if (!lchan->active) continue; diff --git a/src/host/trxcon/sched_trx.h b/src/host/trxcon/sched_trx.h index b93011cb..7ee1d472 100644 --- a/src/host/trxcon/sched_trx.h +++ b/src/host/trxcon/sched_trx.h @@ -146,6 +146,8 @@ struct trx_lchan_state { enum trx_lchan_type type; /*! \brief Channel status */ uint8_t active; + /*! \brief Link to a list of channels */ + struct llist_head list; /*! \brief Burst type: GMSK or 8PSK */ enum trx_burst_type burst_type; @@ -221,7 +223,7 @@ struct trx_ts { /*! \brief Pointer to multiframe layout */ const struct trx_multiframe *mf_layout; /*! \brief Channel states for logical channels */ - struct trx_lchan_state *lchans; + struct llist_head lchans; /*! \brief Queue primitives for TX */ struct llist_head tx_prims; }; -- cgit v1.2.3