diff options
Diffstat (limited to 'src/pdch_ul_controller.c')
-rw-r--r-- | src/pdch_ul_controller.c | 56 |
1 files changed, 27 insertions, 29 deletions
diff --git a/src/pdch_ul_controller.c b/src/pdch_ul_controller.c index 59110800..661957bb 100644 --- a/src/pdch_ul_controller.c +++ b/src/pdch_ul_controller.c @@ -12,15 +12,13 @@ * 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 General Public License - * along with it program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <unistd.h> #include <talloc.h> +#include <osmocom/gsm/gsm0502.h> + #include "pdch_ul_controller.h" #include "bts.h" #include "sba.h" @@ -38,19 +36,14 @@ const struct value_string pdch_ul_node_names[] = { { 0, NULL } }; -#define GSM_MAX_FN_THRESH (GSM_MAX_FN >> 1) -/* 0: equal, -1: fn1 BEFORE fn2, 1: fn1 AFTER fn2 */ -static inline int fn_cmp(uint32_t fn1, uint32_t fn2) -{ - if (fn1 == fn2) - return 0; - /* FN1 goes before FN2: */ - if ((fn1 < fn2 && (fn2 - fn1) < GSM_MAX_FN_THRESH) || - (fn1 > fn2 && (fn1 - fn2) > GSM_MAX_FN_THRESH)) - return -1; - /* FN1 goes after FN2: */ - return 1; -} +const struct value_string pdch_ulc_tbf_poll_reason_names[] = { + { PDCH_ULC_POLL_UL_ASS, "UL_ASS" }, + { PDCH_ULC_POLL_DL_ASS, "DL_ASS" }, + { PDCH_ULC_POLL_UL_ACK, "UL_ACK" }, + { PDCH_ULC_POLL_DL_ACK, "DL_ACK" }, + { PDCH_ULC_POLL_CELL_CHG_CONTINUE, "CELL_CHG_CONTINUE" }, + { 0, NULL } +}; struct pdch_ulc *pdch_ulc_alloc(struct gprs_rlcmac_pdch *pdch, void *ctx) { @@ -66,13 +59,14 @@ struct pdch_ulc *pdch_ulc_alloc(struct gprs_rlcmac_pdch *pdch, void *ctx) struct pdch_ulc_node *pdch_ulc_get_node(struct pdch_ulc *ulc, uint32_t fn) { + OSMO_ASSERT(ulc); struct rb_node *node = ulc->tree_root.rb_node; struct pdch_ulc_node *it; int res; while (node) { it = rb_entry(node, struct pdch_ulc_node, node); - res = fn_cmp(it->fn, fn); + res = gsm0502_fncmp(it->fn, fn); if (res > 0) /* it->fn AFTER fn */ node = node->rb_left; else if (res < 0) /* it->fn BEFORE fn */ @@ -152,7 +146,7 @@ int pdch_ulc_get_next_free_rrbp_fn(struct pdch_ulc *ulc, uint32_t fn, uint32_t * } /* Get next free (unreserved) FN which is not located in time before "start_fn" */ -uint32_t pdch_ulc_get_next_free_fn(struct pdch_ulc *ulc, uint32_t start_fn) +uint32_t pdch_ulc_get_next_free_fn(const struct pdch_ulc *ulc, uint32_t start_fn) { struct rb_node *node; struct pdch_ulc_node *it; @@ -161,12 +155,12 @@ uint32_t pdch_ulc_get_next_free_fn(struct pdch_ulc *ulc, uint32_t start_fn) for (node = rb_first(&ulc->tree_root); node; node = rb_next(node)) { it = container_of(node, struct pdch_ulc_node, node); - res = fn_cmp(it->fn, check_fn); + res = gsm0502_fncmp(it->fn, check_fn); if (res > 0) { /* it->fn AFTER check_fn */ /* Next reserved FN is passed check_fn, hence it means check_fn is free */ return check_fn; } - /* if it->fn < check_fn, simply continue iterating, we want to reach at least check_fn */ + if (res == 0)/* it->fn == fn */ check_fn = fn_next_block(check_fn); /* if it->fn < check_fn, simply continue iterating, we want to reach at least check_fn */ @@ -187,6 +181,9 @@ static int pdch_ulc_add_node(struct pdch_ulc *ulc, struct pdch_ulc_node *item) struct rb_node **n = &(ulc->tree_root.rb_node); struct rb_node *parent = NULL; + LOGPDCH(ulc->pdch, DRLCMAC, LOGL_DEBUG, "Reserving FN %u for type %s\n", + item->fn, get_value_string(pdch_ul_node_names, item->type)); + while (*n) { struct pdch_ulc_node *it; int res; @@ -194,7 +191,7 @@ static int pdch_ulc_add_node(struct pdch_ulc *ulc, struct pdch_ulc_node *item) it = container_of(*n, struct pdch_ulc_node, node); parent = *n; - res = fn_cmp(item->fn, it->fn); + res = gsm0502_fncmp(item->fn, it->fn); if (res < 0) { /* item->fn "BEFORE" it->fn */ n = &((*n)->rb_left); } else if (res > 0) { /* item->fn "AFTER" it->fn */ @@ -270,7 +267,7 @@ void pdch_ulc_release_tbf(struct pdch_ulc *ulc, const struct gprs_rlcmac_tbf *tb item_tbf = item->tbf_poll.poll_tbf; break; case PDCH_ULC_NODE_TBF_USF: - item_tbf = (struct gprs_rlcmac_tbf *)item->tbf_usf.ul_tbf; + item_tbf = ul_tbf_as_tbf_const(item->tbf_usf.ul_tbf); break; default: OSMO_ASSERT(0); @@ -294,9 +291,9 @@ void pdch_ulc_expire_fn(struct pdch_ulc *ulc, uint32_t fn) int res; struct rb_node *first; - while((first = rb_first(&ulc->tree_root))) { + while ((first = rb_first(&ulc->tree_root))) { item = container_of(first, struct pdch_ulc_node, node); - res = fn_cmp(item->fn, fn); + res = gsm0502_fncmp(item->fn, fn); if (res > 0) /* item->fn AFTER fn */ break; if (res < 0) { /* item->fn BEFORE fn */ @@ -311,14 +308,15 @@ void pdch_ulc_expire_fn(struct pdch_ulc *ulc, uint32_t fn) case PDCH_ULC_NODE_TBF_USF: LOGPDCH(ulc->pdch, DRLCMAC, LOGL_INFO, "Timeout for registered USF (FN=%u): %s\n", - item->fn, tbf_name((struct gprs_rlcmac_tbf *)item->tbf_usf.ul_tbf)); + item->fn, tbf_name(ul_tbf_as_tbf_const(item->tbf_usf.ul_tbf))); tbf_usf_timeout(item->tbf_usf.ul_tbf); break; case PDCH_ULC_NODE_TBF_POLL: LOGPDCH(ulc->pdch, DRLCMAC, LOGL_NOTICE, - "Timeout for registered POLL (FN=%u): %s\n", - item->fn, tbf_name(item->tbf_poll.poll_tbf)); - tbf_poll_timeout(item->tbf_poll.poll_tbf, item->fn, item->tbf_poll.reason); + "Timeout for registered POLL (FN=%u, reason=%s): %s\n", + item->fn, get_value_string(pdch_ulc_tbf_poll_reason_names, item->tbf_poll.reason), + tbf_name(item->tbf_poll.poll_tbf)); + tbf_poll_timeout(item->tbf_poll.poll_tbf, ulc->pdch, item->fn, item->tbf_poll.reason); break; case PDCH_ULC_NODE_SBA: sba = item->sba.sba; |