pcuif: Submit data_req with len=0 as idle frames
This way PCU always answers DATA.ind and the BTS can still clearly identify idle frames. It also simplifies testing and verification of correct behavior. Related: SYS#4919 Change-Id: Ife718eeed2af011479c03099ea109518f04567bc
This commit is contained in:
parent
9f43c65c99
commit
fef3da24ae
|
@ -412,7 +412,7 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts,
|
||||||
uint8_t usf;
|
uint8_t usf;
|
||||||
struct msgb *msg = NULL;
|
struct msgb *msg = NULL;
|
||||||
uint32_t poll_fn;
|
uint32_t poll_fn;
|
||||||
enum pcu_gsmtap_category gsmtap_cat;
|
enum pcu_gsmtap_category gsmtap_cat = PCU_GSMTAP_C_DL_DUMMY; /* init: make gcc happy */
|
||||||
bool tx_is_egprs = false;
|
bool tx_is_egprs = false;
|
||||||
bool require_gprs_only;
|
bool require_gprs_only;
|
||||||
enum mcs_kind req_mcs_kind; /* Restrict CS/MCS if DL Data block is to be sent */
|
enum mcs_kind req_mcs_kind; /* Restrict CS/MCS if DL Data block is to be sent */
|
||||||
|
@ -487,9 +487,9 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts,
|
||||||
}
|
}
|
||||||
/* Prio 3: send dummy control message if need to poll or USF */
|
/* Prio 3: send dummy control message if need to poll or USF */
|
||||||
else {
|
else {
|
||||||
/* If there's no TBF attached to this PDCH, we can early skip
|
/* If there's no TBF attached to this PDCH, we can submit an empty
|
||||||
* since there's nothing to transmit nor to poll/USF. This way
|
* data_req since there's nothing to transmit nor to poll/USF. This
|
||||||
* we help BTS energy saving (on TRX!=C0) by sending nothing
|
* way we help BTS energy saving (on TRX!=C0) by sending nothing
|
||||||
* instead of a dummy block. The early return is done here and
|
* instead of a dummy block. The early return is done here and
|
||||||
* not at the start of the function because the condition below
|
* not at the start of the function because the condition below
|
||||||
* (num_tbfs==0) may not be enough, because temporary dummy TBFs
|
* (num_tbfs==0) may not be enough, because temporary dummy TBFs
|
||||||
|
@ -505,13 +505,11 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts,
|
||||||
* TRX0, since BTS is not preparing dummy bursts on idle TS for us */
|
* TRX0, since BTS is not preparing dummy bursts on idle TS for us */
|
||||||
skip_idle = skip_idle && trx != 0;
|
skip_idle = skip_idle && trx != 0;
|
||||||
#endif
|
#endif
|
||||||
if (skip_idle)
|
if (!skip_idle && (msg = sched_dummy())) {
|
||||||
return 0;
|
|
||||||
if ((msg = sched_dummy())) {
|
|
||||||
/* increase counter */
|
/* increase counter */
|
||||||
gsmtap_cat = PCU_GSMTAP_C_DL_DUMMY;
|
gsmtap_cat = PCU_GSMTAP_C_DL_DUMMY;
|
||||||
} else {
|
} else {
|
||||||
return -ENOMEM;
|
msg = NULL; /* submit empty frame */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,6 +519,10 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts,
|
||||||
pdch->fn_without_cs14 = 0;
|
pdch->fn_without_cs14 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Used to measure the leak rate, count all blocks */
|
||||||
|
gprs_bssgp_update_frames_sent();
|
||||||
|
|
||||||
|
if (msg) {
|
||||||
/* msg is now available */
|
/* msg is now available */
|
||||||
bts_do_rate_ctr_add(bts, CTR_RLC_DL_BYTES, msgb_length(msg));
|
bts_do_rate_ctr_add(bts, CTR_RLC_DL_BYTES, msgb_length(msg));
|
||||||
|
|
||||||
|
@ -529,13 +531,11 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts,
|
||||||
usf = usf_tbf ? usf_tbf->m_usf[ts] : USF_UNUSED;
|
usf = usf_tbf ? usf_tbf->m_usf[ts] : USF_UNUSED;
|
||||||
msg->data[0] = (msg->data[0] & 0xf8) | usf;
|
msg->data[0] = (msg->data[0] & 0xf8) | usf;
|
||||||
|
|
||||||
/* Used to measure the leak rate, count all blocks */
|
|
||||||
gprs_bssgp_update_frames_sent();
|
|
||||||
|
|
||||||
/* Send to GSMTAP */
|
/* Send to GSMTAP */
|
||||||
tap_n_acc(msg, bts, trx, ts, fn, gsmtap_cat);
|
tap_n_acc(msg, bts, trx, ts, fn, gsmtap_cat);
|
||||||
|
}
|
||||||
|
|
||||||
/* send PDTCH/PACCH to L1 */
|
/* send PDTCH/PACCH to L1. msg=NULL accepted too (idle block) */
|
||||||
pcu_l1if_tx_pdtch(msg, bts, trx, ts, bts->trx[trx].arfcn, fn, block_nr);
|
pcu_l1if_tx_pdtch(msg, bts, trx, ts, bts->trx[trx].arfcn, fn, block_nr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -212,6 +212,7 @@ static int pcu_tx_data_req(struct gprs_rlcmac_bts *bts, uint8_t trx, uint8_t ts,
|
||||||
data_req->trx_nr = trx;
|
data_req->trx_nr = trx;
|
||||||
data_req->ts_nr = ts;
|
data_req->ts_nr = ts;
|
||||||
data_req->block_nr = block_nr;
|
data_req->block_nr = block_nr;
|
||||||
|
if (len)
|
||||||
memcpy(data_req->data, data, len);
|
memcpy(data_req->data, data, len);
|
||||||
data_req->len = len;
|
data_req->len = len;
|
||||||
|
|
||||||
|
@ -223,12 +224,20 @@ void pcu_l1if_tx_pdtch(msgb *msg, struct gprs_rlcmac_bts *bts, uint8_t trx, uint
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_DIRECT_PHY
|
#ifdef ENABLE_DIRECT_PHY
|
||||||
if (bts->trx[trx].fl1h) {
|
if (bts->trx[trx].fl1h) {
|
||||||
|
if (!msg) /* Simply skip sending idle frames to L1 */
|
||||||
|
return;
|
||||||
l1if_pdch_req(bts->trx[trx].fl1h, ts, 0, fn, arfcn, block_nr,
|
l1if_pdch_req(bts->trx[trx].fl1h, ts, 0, fn, arfcn, block_nr,
|
||||||
msg->data, msg->len);
|
msg->data, msg->len);
|
||||||
msgb_free(msg);
|
msgb_free(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (!msg) {
|
||||||
|
pcu_tx_data_req(bts, trx, ts, PCU_IF_SAPI_PDTCH, arfcn, fn, block_nr,
|
||||||
|
NULL, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pcu_tx_data_req(bts, trx, ts, PCU_IF_SAPI_PDTCH, arfcn, fn, block_nr,
|
pcu_tx_data_req(bts, trx, ts, PCU_IF_SAPI_PDTCH, arfcn, fn, block_nr,
|
||||||
msg->data, msg->len);
|
msg->data, msg->len);
|
||||||
msgb_free(msg);
|
msgb_free(msg);
|
||||||
|
@ -243,10 +252,17 @@ void pcu_l1if_tx_ptcch(struct gprs_rlcmac_bts *bts,
|
||||||
gsmtap_send(the_pcu->gsmtap, arfcn, ts, GSMTAP_CHANNEL_PTCCH, 0, fn, 0, 0, data, data_len);
|
gsmtap_send(the_pcu->gsmtap, arfcn, ts, GSMTAP_CHANNEL_PTCCH, 0, fn, 0, 0, data, data_len);
|
||||||
#ifdef ENABLE_DIRECT_PHY
|
#ifdef ENABLE_DIRECT_PHY
|
||||||
if (bts->trx[trx].fl1h) {
|
if (bts->trx[trx].fl1h) {
|
||||||
|
if (!data_len) /* Simply skip sending idle frames to L1 */
|
||||||
|
return;
|
||||||
l1if_pdch_req(bts->trx[trx].fl1h, ts, 1, fn, arfcn, block_nr, data, data_len);
|
l1if_pdch_req(bts->trx[trx].fl1h, ts, 1, fn, arfcn, block_nr, data, data_len);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (!data_len) {
|
||||||
|
pcu_tx_data_req(bts, trx, ts, PCU_IF_SAPI_PTCCH, arfcn, fn, block_nr, NULL, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pcu_tx_data_req(bts, trx, ts, PCU_IF_SAPI_PTCCH, arfcn, fn, block_nr, data, data_len);
|
pcu_tx_data_req(bts, trx, ts, PCU_IF_SAPI_PTCCH, arfcn, fn, block_nr, data, data_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,8 +560,11 @@ int pcu_rx_rts_req_ptcch(struct gprs_rlcmac_bts *bts, uint8_t trx, uint8_t ts,
|
||||||
* TRX0, since BTS is not preparing dummy bursts on idle TS for us: */
|
* TRX0, since BTS is not preparing dummy bursts on idle TS for us: */
|
||||||
skip_idle = skip_idle && trx != 0;
|
skip_idle = skip_idle && trx != 0;
|
||||||
#endif
|
#endif
|
||||||
if (skip_idle)
|
if (skip_idle) {
|
||||||
|
pcu_l1if_tx_ptcch(bts, trx, ts, bts->trx[trx].arfcn, fn, block_nr,
|
||||||
|
NULL, 0);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
pcu_l1if_tx_ptcch(bts, trx, ts, bts->trx[trx].arfcn, fn, block_nr,
|
pcu_l1if_tx_ptcch(bts, trx, ts, bts->trx[trx].arfcn, fn, block_nr,
|
||||||
pdch->ptcch_msg, GSM_MACBLOCK_LEN);
|
pdch->ptcch_msg, GSM_MACBLOCK_LEN);
|
||||||
|
|
Loading…
Reference in New Issue