aboutsummaryrefslogtreecommitdiffstats
path: root/src/pdch_ul_controller.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pdch_ul_controller.c')
-rw-r--r--src/pdch_ul_controller.c56
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;