bts/pdch: Move the adding of paging to the BTS/PDCH objects

Only the gprs_rlcmac_pdch will manipulate the paging list now. There
can be various more refactorings of the code but they can be done
later. E.g. on memory allocation failure we can continue instead
of leaving the code, we should also set any_tbf only after things
have been paged.
This commit is contained in:
Holger Hans Peter Freyther 2013-10-19 18:28:59 +02:00
parent 24e98d039d
commit f0984897a5
5 changed files with 93 additions and 88 deletions

View File

@ -32,10 +32,17 @@ extern "C" {
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
extern void *tall_pcu_ctx;
static llist_head *gprs_rlcmac_tbfs_lists[] = {
&gprs_rlcmac_ul_tbfs,
&gprs_rlcmac_dl_tbfs,
NULL
};
static BTS s_bts;
BTS* BTS::main_bts()
@ -67,6 +74,83 @@ void BTS::set_current_frame_number(int fn)
m_pollController.expireTimedout(m_cur_fn);
}
int BTS::add_paging(uint8_t chan_needed, uint8_t *identity_lv)
{
uint8_t l, trx, ts, any_tbf = 0;
struct gprs_rlcmac_tbf *tbf;
struct gprs_rlcmac_paging *pag;
uint8_t slot_mask[8];
int8_t first_ts; /* must be signed */
LOGP(DRLCMAC, LOGL_INFO, "Add RR paging: chan-needed=%d MI=%s\n",
chan_needed, osmo_hexdump(identity_lv + 1, identity_lv[0]));
/* collect slots to page
* Mark slots for every TBF, but only mark one of it.
* Mark only the first slot found.
* Don't mark, if TBF uses a different slot that is already marked. */
memset(slot_mask, 0, sizeof(slot_mask));
for (l = 0; gprs_rlcmac_tbfs_lists[l]; l++) {
llist_for_each_entry(tbf, gprs_rlcmac_tbfs_lists[l], list) {
first_ts = -1;
for (ts = 0; ts < 8; ts++) {
if (tbf->pdch[ts]) {
/* remember the first slot found */
if (first_ts < 0)
first_ts = ts;
/* break, if we already marked a slot */
if ((slot_mask[tbf->trx_no] & (1 << ts)))
break;
}
}
/* mark first slot found, if none is marked already */
if (ts == 8 && first_ts >= 0) {
LOGP(DRLCMAC, LOGL_DEBUG, "- %s TBF=%d uses "
"TRX=%d TS=%d, so we mark\n",
(tbf->direction == GPRS_RLCMAC_UL_TBF)
? "UL" : "DL",
tbf->tfi, tbf->trx_no, first_ts);
slot_mask[tbf->trx_no] |= (1 << first_ts);
} else
LOGP(DRLCMAC, LOGL_DEBUG, "- %s TBF=%d uses "
"already marked TRX=%d TS=%d\n",
(tbf->direction == GPRS_RLCMAC_UL_TBF)
? "UL" : "DL",
tbf->tfi, tbf->trx_no, ts);
}
}
/* Now we have a list of marked slots. Every TBF uses at least one
* of these slots. */
/* schedule paging to all marked slots */
for (trx = 0; trx < 8; trx++) {
if (slot_mask[trx] == 0)
continue;
any_tbf = 1;
for (ts = 0; ts < 8; ts++) {
if ((slot_mask[trx] & (1 << ts))) {
/* schedule */
pag = talloc_zero(tall_pcu_ctx,
struct gprs_rlcmac_paging);
if (!pag)
return -ENOMEM;
pag->chan_needed = chan_needed;
memcpy(pag->identity_lv, identity_lv,
identity_lv[0] + 1);
m_bts.trx[trx].pdch[ts].add_paging(pag);
LOGP(DRLCMAC, LOGL_INFO, "Paging on PACCH of "
"TRX=%d TS=%d\n", trx, ts);
}
}
}
if (!any_tbf)
LOGP(DRLCMAC, LOGL_INFO, "No paging, because no TBF\n");
return 0;
}
void gprs_rlcmac_pdch::enable()
{
/* TODO: Check if there are still allocated resources.. */
@ -195,3 +279,7 @@ continue_next:
return msg;
}
void gprs_rlcmac_pdch::add_paging(struct gprs_rlcmac_paging *pag)
{
llist_add(&pag->list, &paging_list);
}

View File

@ -43,6 +43,7 @@ struct gprs_rlcmac_pdch {
struct gprs_rlcmac_paging *dequeue_paging();
struct msgb *packet_paging_request();
void add_paging(struct gprs_rlcmac_paging *pag);
/* TODO: the PDCH should know the trx/ts it belongs to */
void free_resources(uint8_t trx, uint8_t ts);
@ -126,6 +127,9 @@ public:
void set_current_frame_number(int frame_number);
int current_frame_number() const;
/** add paging to paging queue(s) */
int add_paging(uint8_t chan_needed, uint8_t *identity_lv);
private:
int m_cur_fn;
struct gprs_rlcmac_bts m_bts;

View File

@ -37,11 +37,6 @@ struct gprs_rlcmac_cs gprs_rlcmac_cs[] = {
LLIST_HEAD(gprs_rlcmac_ul_tbfs);
LLIST_HEAD(gprs_rlcmac_dl_tbfs);
llist_head *gprs_rlcmac_tbfs_lists[] = {
&gprs_rlcmac_ul_tbfs,
&gprs_rlcmac_dl_tbfs,
NULL
};
extern void *tall_pcu_ctx;
#ifdef DEBUG_DIAGRAM
@ -278,86 +273,6 @@ int gprs_rlcmac_rcv_block(struct gprs_rlcmac_bts *bts,
return rc;
}
/* add paging to paging queue(s) */
int gprs_rlcmac_add_paging(struct gprs_rlcmac_bts *bts,
uint8_t chan_needed, uint8_t *identity_lv)
{
uint8_t l, trx, ts, any_tbf = 0;
struct gprs_rlcmac_tbf *tbf;
struct gprs_rlcmac_paging *pag;
uint8_t slot_mask[8];
int8_t first_ts; /* must be signed */
LOGP(DRLCMAC, LOGL_INFO, "Add RR paging: chan-needed=%d MI=%s\n",
chan_needed, osmo_hexdump(identity_lv + 1, identity_lv[0]));
/* collect slots to page
* Mark slots for every TBF, but only mark one of it.
* Mark only the first slot found.
* Don't mark, if TBF uses a different slot that is already marked. */
memset(slot_mask, 0, sizeof(slot_mask));
for (l = 0; gprs_rlcmac_tbfs_lists[l]; l++) {
llist_for_each_entry(tbf, gprs_rlcmac_tbfs_lists[l], list) {
first_ts = -1;
for (ts = 0; ts < 8; ts++) {
if (tbf->pdch[ts]) {
/* remember the first slot found */
if (first_ts < 0)
first_ts = ts;
/* break, if we already marked a slot */
if ((slot_mask[tbf->trx_no] & (1 << ts)))
break;
}
}
/* mark first slot found, if none is marked already */
if (ts == 8 && first_ts >= 0) {
LOGP(DRLCMAC, LOGL_DEBUG, "- %s TBF=%d uses "
"TRX=%d TS=%d, so we mark\n",
(tbf->direction == GPRS_RLCMAC_UL_TBF)
? "UL" : "DL",
tbf->tfi, tbf->trx_no, first_ts);
slot_mask[tbf->trx_no] |= (1 << first_ts);
} else
LOGP(DRLCMAC, LOGL_DEBUG, "- %s TBF=%d uses "
"already marked TRX=%d TS=%d\n",
(tbf->direction == GPRS_RLCMAC_UL_TBF)
? "UL" : "DL",
tbf->tfi, tbf->trx_no, ts);
}
}
/* Now we have a list of marked slots. Every TBF uses at least one
* of these slots. */
/* schedule paging to all marked slots */
for (trx = 0; trx < 8; trx++) {
if (slot_mask[trx] == 0)
continue;
any_tbf = 1;
for (ts = 0; ts < 8; ts++) {
if ((slot_mask[trx] & (1 << ts))) {
/* schedule */
pag = talloc_zero(tall_pcu_ctx,
struct gprs_rlcmac_paging);
if (!pag)
return -ENOMEM;
pag->chan_needed = chan_needed;
memcpy(pag->identity_lv, identity_lv,
identity_lv[0] + 1);
llist_add(&pag->list,
&bts->trx[trx].pdch[ts].paging_list);
LOGP(DRLCMAC, LOGL_INFO, "Paging on PACCH of "
"TRX=%d TS=%d\n", trx, ts);
}
}
}
if (!any_tbf)
LOGP(DRLCMAC, LOGL_INFO, "No paging, because no TBF\n");
return 0;
}
// GSM 04.08 9.1.18 Immediate assignment
int write_immediate_assignment(
struct gprs_rlcmac_bts *bts,

View File

@ -190,8 +190,6 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts,
int gprs_rlcmac_imm_ass_cnf(uint8_t *data, uint32_t fn);
int gprs_rlcmac_add_paging(struct gprs_rlcmac_bts *bts, uint8_t chan_needed, uint8_t *identity_lv);
int remember_timing_advance(uint32_t tlli, uint8_t ta);
int recall_timing_advance(uint32_t tlli);

View File

@ -486,7 +486,7 @@ static int pcu_rx_pag_req(struct gsm_pcu_if_pag_req *pag_req)
LOGP(DL1IF, LOGL_DEBUG, "Paging request received: chan_needed=%d "
"length=%d\n", pag_req->chan_needed, pag_req->identity_lv[0]);
return gprs_rlcmac_add_paging(bts_main_data(), pag_req->chan_needed,
return BTS::main_bts()->add_paging(pag_req->chan_needed,
pag_req->identity_lv);
}