lchan: Send the ACT ACK/NACK after the Layer1 has handled act/deact

Send the RSL ACT ACK/NACK after the Layer1 firmware has acked the
activation/deactivation. In case the channel can not be activated
we will send a NACK. In case the channel can not be deactivated we
will send an ACK and the next time the channel is activated we will
send a NACK. The release ack will be sent once the TxDownlink of the
TCH/SDCCH is closed.

Change the rsl_tx_chan_nack method to create a new msgb to be used
by the hardware layer, change the return value to ask the caller to
delete the msgb.
This commit is contained in:
Holger Hans Peter Freyther 2012-04-16 23:09:18 +02:00 committed by Harald Welte
parent 1e2b3259b9
commit d7718280c9
3 changed files with 25 additions and 17 deletions

View File

@ -8,6 +8,7 @@ int rsl_tx_chan_rqd(struct gsm_bts_trx *trx, struct gsm_time *gtime,
int rsl_tx_est_ind(struct gsm_lchan *lchan, uint8_t link_id, uint8_t *data, int len);
int rsl_tx_chan_act_ack(struct gsm_lchan *lchan, struct gsm_time *gtime);
int rsl_tx_chan_act_nack(struct gsm_lchan *lchan, uint8_t cause);
int rsl_tx_rf_rel_ack(struct gsm_lchan *lchan);
/* call-back for LAPDm code, called when it wants to send msgs UP */

View File

@ -517,20 +517,21 @@ int rsl_tx_chan_act_ack(struct gsm_lchan *lchan, struct gsm_time *gtime)
}
/* 8.4.3 sending CHANnel ACTIVation Negative ACK */
static int rsl_tx_chan_nack(struct gsm_bts_trx *trx, struct msgb *msg, uint8_t cause)
int rsl_tx_chan_act_nack(struct gsm_lchan *lchan, uint8_t cause)
{
struct abis_rsl_dchan_hdr *dch = msgb_l2(msg);
uint8_t chan_nr = dch->chan_nr;
struct msgb *msg;
uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
LOGP(DRSL, LOGL_NOTICE, "Sending Channel Activated NACK: cause = 0x%02x\n", cause);
msg->len = 0;
msg->data = msg->tail = msg->l3h;
msg = rsl_msgb_alloc(sizeof(struct abis_rsl_dchan_hdr));
if (!msg)
return -ENOMEM;
/* 9.3.26 Cause */
msgb_tlv_put(msg, RSL_IE_CAUSE, 1, &cause);
rsl_dch_push_hdr(msg, RSL_MT_CHAN_ACTIV_NACK, chan_nr);
msg->trx = trx;
msg->trx = lchan->ts->trx;
return abis_rsl_sendmsg(msg);
}
@ -621,16 +622,14 @@ static int rsl_rx_chan_activ(struct msgb *msg)
/* 9.3.3 Activation Type */
if (!TLVP_PRESENT(&tp, RSL_IE_ACT_TYPE)) {
LOGP(DRSL, LOGL_NOTICE, "missing Activation Type\n");
rsl_tx_chan_nack(msg->trx, msg, RSL_ERR_MAND_IE_ERROR);
return 1;
return rsl_tx_chan_act_nack(lchan, RSL_ERR_MAND_IE_ERROR);
}
type = *TLVP_VAL(&tp, RSL_IE_ACT_TYPE);
/* 9.3.6 Channel Mode */
if (!TLVP_PRESENT(&tp, RSL_IE_CHAN_MODE)) {
LOGP(DRSL, LOGL_NOTICE, "missing Channel Mode\n");
rsl_tx_chan_nack(msg->trx, msg, RSL_ERR_MAND_IE_ERROR);
return 1;
return rsl_tx_chan_act_nack(lchan, RSL_ERR_MAND_IE_ERROR);
}
cm = (struct rsl_ie_chan_mode *) TLVP_VAL(&tp, RSL_IE_CHAN_MODE);
lchan_tchmode_from_cmode(lchan, cm);

View File

@ -33,6 +33,7 @@
#include <osmo-bts/rsl.h>
#include <osmo-bts/amr.h>
#include <osmo-bts/bts.h>
#include <osmo-bts/bts_model.h>
#include "l1_if.h"
#include "femtobts.h"
@ -424,6 +425,7 @@ static const struct lchan_sapis sapis_for_lchan[_GSM_LCHAN_MAX] = {
static int lchan_act_compl_cb(struct msgb *l1_msg, void *data)
{
struct gsm_time *time;
struct gsm_lchan *lchan = data;
GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg);
GsmL1_MphActivateCnf_t *ic = &l1p->u.mphActivateCnf;
@ -446,7 +448,11 @@ static int lchan_act_compl_cb(struct msgb *l1_msg, void *data)
switch (ic->sapi) {
case GsmL1_Sapi_Sdcch:
case GsmL1_Sapi_TchF:
/* FIXME: Send RSL CHAN ACT */
time = bts_model_get_time(lchan->ts->trx->bts);
if (lchan->state == LCHAN_S_ACTIVE)
rsl_tx_chan_act_ack(lchan, time);
else
rsl_tx_chan_act_nack(lchan, RSL_ERR_EQUIPMENT_FAIL);
break;
default:
break;
@ -877,7 +883,8 @@ static int lchan_deact_compl_cb(struct msgb *l1_msg, void *data)
switch (ic->sapi) {
case GsmL1_Sapi_Sdcch:
case GsmL1_Sapi_TchF:
/* FIXME: Send RSL CHAN REL ACK */
if (ic->dir == GsmL1_Dir_TxDownlink)
rsl_tx_rf_rel_ack(lchan);
break;
default:
break;
@ -888,7 +895,7 @@ static int lchan_deact_compl_cb(struct msgb *l1_msg, void *data)
return 0;
}
int lchan_deactivate(struct gsm_lchan *lchan)
static int lchan_deactivate(struct gsm_lchan *lchan)
{
struct femtol1_hdl *fl1h = trx_femtol1_hdl(lchan->ts->trx);
const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type];
@ -1016,15 +1023,16 @@ int bts_model_rsl_chan_act(struct gsm_lchan *lchan, struct tlv_parsed *tp)
lchan->sach_deact = 0;
lchan_activate(lchan);
/* FIXME: only do this in case of success */
return rsl_tx_chan_act_ack(lchan, bts_model_get_time(lchan->ts->trx->bts));
return 0;
}
int bts_model_rsl_chan_rel(struct gsm_lchan *lchan)
{
/* A duplicate RF Release Request, ignore it */
if (lchan->state == LCHAN_S_REL_REQ)
return 0;
lchan_deactivate(lchan);
return rsl_tx_rf_rel_ack(lchan);
return 0;
}
int bts_model_rsl_deact_sacch(struct gsm_lchan *lchan)