summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSylvain Munaut2011-04-24 11:20:48 +0200
committerSylvain Munaut2011-07-28 21:30:50 +0200
commit643aad2ef4b0677b95aa94f5eb7a2d01db1fe004 (patch)
treea2c74e818f4b8b8a5d1d099cc859e1642f95717e /src
parentl1ctl: Add definition for TRAFFIC_{REQ,CONF,IND} (diff)
downloadosmocom-643aad2ef4b0677b95aa94f5eb7a2d01db1fe004.tar.gz
osmocom-643aad2ef4b0677b95aa94f5eb7a2d01db1fe004.tar.xz
osmocom-643aad2ef4b0677b95aa94f5eb7a2d01db1fe004.zip
fw/l1: Add a queue for traffic frame to send to network (TRAFFIC_REQ)
Also hard limit to maximum 4 pending frames (should not happen !), the upstream is supposed to do its own flow control. Written-by: Andreas Eversberg <jolly@eversberg.eu> Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Diffstat (limited to 'src')
-rw-r--r--src/target/firmware/include/layer1/sync.h1
-rw-r--r--src/target/firmware/layer1/l23_api.c27
2 files changed, 28 insertions, 0 deletions
diff --git a/src/target/firmware/include/layer1/sync.h b/src/target/firmware/include/layer1/sync.h
index 8ed2cb1..4247dab 100644
--- a/src/target/firmware/include/layer1/sync.h
+++ b/src/target/firmware/include/layer1/sync.h
@@ -27,6 +27,7 @@ struct l1_cell_info {
enum l1s_chan {
L1S_CHAN_MAIN,
L1S_CHAN_SACCH,
+ L1S_CHAN_TRAFFIC,
_NUM_L1S_CHAN
};
diff --git a/src/target/firmware/layer1/l23_api.c b/src/target/firmware/layer1/l23_api.c
index 3baba17..2a22db8 100644
--- a/src/target/firmware/layer1/l23_api.c
+++ b/src/target/firmware/layer1/l23_api.c
@@ -303,6 +303,7 @@ static void l1ctl_rx_dm_rel_req(struct msgb *msg)
l1s.dedicated.type = GSM_DCHAN_NONE;
l1a_txq_msgb_flush(&l1s.tx_queue[L1S_CHAN_MAIN]);
l1a_txq_msgb_flush(&l1s.tx_queue[L1S_CHAN_SACCH]);
+ l1a_txq_msgb_flush(&l1s.tx_queue[L1S_CHAN_TRAFFIC]);
l1a_meas_msgb_set(NULL);
dsp_load_ciph_param(0, NULL);
l1a_tch_mode_set(GSM48_CMODE_SIGN);
@@ -517,6 +518,28 @@ static void l1ctl_rx_neigh_pm_req(struct msgb *msg)
mframe_enable(MF_TASK_NEIGH_PM51);
}
+/* receive a L1CTL_TRAFFIC_REQ from L23 */
+static void l1ctl_rx_traffic_req(struct msgb *msg)
+{
+ struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
+ struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data;
+ struct l1ctl_traffic_req *tr = (struct l1ctl_traffic_req *) ul->payload;
+ int num = 0;
+
+ /* printd("L1CTL_TRAFFIC_REQ\n"); */ /* Very verbose, can overwelm serial */
+
+ msg->l2h = tr->data;
+
+ num = l1a_txq_msgb_count(&l1s.tx_queue[L1S_CHAN_TRAFFIC]);
+ if (num >= 4) {
+ printd("dropping traffic frame\n");
+ msgb_free(msg);
+ return;
+ }
+
+ l1a_txq_msgb_enq(&l1s.tx_queue[L1S_CHAN_TRAFFIC], msg);
+}
+
/* callback from SERCOMM when L2 sends a message to L1 */
static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg)
{
@@ -580,6 +603,10 @@ static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg)
case L1CTL_NEIGH_PM_REQ:
l1ctl_rx_neigh_pm_req(msg);
break;
+ case L1CTL_TRAFFIC_REQ:
+ l1ctl_rx_traffic_req(msg);
+ /* we have to keep the msgb, not free it! */
+ goto exit_nofree;
}
exit_msgbfree: