introduce cache of 6 last recently received measurement reports for each lchan
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 012481a..b21f8aa 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -194,6 +194,10 @@
 	/* use count. how many users use this channel */
 	unsigned int use_count;
 
+	/* cache of last measurement reports on this lchan */
+	struct gsm_meas_rep meas_rep[6];
+	int meas_rep_idx;
+
 	struct {
 		u_int32_t bound_ip;
 		u_int16_t bound_port;
@@ -564,4 +568,6 @@
 
 void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked);
 
+struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan);
+
 #endif
diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c
index c6675c8..51d5244 100644
--- a/openbsc/src/abis_rsl.c
+++ b/openbsc/src/abis_rsl.c
@@ -998,14 +998,12 @@
 {
 	struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
 	struct tlv_parsed tp;
-	struct gsm_meas_rep mr;
+	struct gsm_meas_rep *mr = lchan_next_meas_rep(msg->lchan);
 	u_int8_t len;
 	const u_int8_t *val;
 	int rc;
 
-	memset(&mr, 0, sizeof(mr));
-
-	mr.lchan = msg->lchan;
+	memset(mr, 0, sizeof(*mr));
 
 	rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
 
@@ -1015,44 +1013,44 @@
 		return -EIO;
 
 	/* Mandatory Parts */
-	mr.nr = *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR);
+	mr->nr = *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR);
 
 	len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
 	val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
 	if (len >= 3) {
 		if (val[0] & 0x40)
-			mr.flags |= MEAS_REP_F_DL_DTX;
-		mr.ul.full.rx_lev = val[0] & 0x3f;
-		mr.ul.sub.rx_lev = val[1] & 0x3f;
-		mr.ul.full.rx_qual = val[2]>>3 & 0x7;
-		mr.ul.sub.rx_qual = val[2] & 0x7;
+			mr->flags |= MEAS_REP_F_DL_DTX;
+		mr->ul.full.rx_lev = val[0] & 0x3f;
+		mr->ul.sub.rx_lev = val[1] & 0x3f;
+		mr->ul.full.rx_qual = val[2]>>3 & 0x7;
+		mr->ul.sub.rx_qual = val[2] & 0x7;
 	}
 
-	mr.bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
+	mr->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
 
 	/* Optional Parts */
 	if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
-		mr.ms_timing_offset =
+		mr->ms_timing_offset =
 			*TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET);
 
 	if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
 		val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
-		mr.flags |= MEAS_REP_F_MS_L1;
-		mr.ms_l1.pwr = ms_pwr_dbm(msg->trx->bts->band, val[0] >> 3);
+		mr->flags |= MEAS_REP_F_MS_L1;
+		mr->ms_l1.pwr = ms_pwr_dbm(msg->trx->bts->band, val[0] >> 3);
 		if (val[0] & 0x04)
-			mr.flags |= MEAS_REP_F_FPC;
-		mr.ms_l1.ta = val[1];
+			mr->flags |= MEAS_REP_F_FPC;
+		mr->ms_l1.ta = val[1];
 	}
 	if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
 		msg->l3h = (u_int8_t *) TLVP_VAL(&tp, RSL_IE_L3_INFO);
-		rc = gsm48_parse_meas_rep(&mr, msg);
+		rc = gsm48_parse_meas_rep(mr, msg);
 		if (rc < 0)
 			return rc;
 	}
 
-	print_meas_rep(&mr);
+	print_meas_rep(mr);
 
-	dispatch_signal(SS_LCHAN, S_LCHAN_MEAS_REP, &mr);
+	dispatch_signal(SS_LCHAN, S_LCHAN_MEAS_REP, mr);
 
 	return 0;
 }
diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c
index 2f0d7b9..0a29847 100644
--- a/openbsc/src/chan_alloc.c
+++ b/openbsc/src/chan_alloc.c
@@ -235,6 +235,8 @@
 /* Free a logical channel */
 void lchan_free(struct gsm_lchan *lchan)
 {
+	int i;
+
 	lchan->type = GSM_LCHAN_NONE;
 	if (lchan->subscr) {
 		subscr_put(lchan->subscr);
@@ -250,6 +252,13 @@
 	/* stop the timer */
 	bsc_del_timer(&lchan->release_timer);
 
+	/* clear cached measuement reports */
+	lchan->meas_rep_idx = 0;
+	for (i = 0; i < ARRAY_SIZE(lchan->meas_rep); i++) {
+		lchan->meas_rep[i].flags = 0;
+		lchan->meas_rep[i].nr = 0;
+	}
+
 	/* FIXME: ts_free() the timeslot, if we're the last logical
 	 * channel using it */
 }
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c
index 6d05a20..ef29b29 100644
--- a/openbsc/src/gsm_04_08.c
+++ b/openbsc/src/gsm_04_08.c
@@ -1558,13 +1558,13 @@
 
 static int gsm48_rx_rr_meas_rep(struct msgb *msg)
 {
-	static struct gsm_meas_rep meas_rep;
+	struct gsm_meas_rep *meas_rep = lchan_next_meas_rep(msg->lchan);
 
 	/* This shouldn't actually end up here, as RSL treats
 	 * L3 Info of 08.58 MEASUREMENT REPORT different by calling
 	 * directly into gsm48_parse_meas_rep */
 	DEBUGP(DMEAS, "DIRECT GSM48 MEASUREMENT REPORT ?!? ");
-	gsm48_parse_meas_rep(&meas_rep, msg);
+	gsm48_parse_meas_rep(meas_rep, msg);
 
 	return 0;
 }
diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c
index 91a854f..94ed91b 100644
--- a/openbsc/src/gsm_data.c
+++ b/openbsc/src/gsm_data.c
@@ -415,3 +415,16 @@
 		return "none";
 	return rrlp_mode_names[mode];
 }
+
+struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan)
+{
+	struct gsm_meas_rep *meas_rep;
+
+	meas_rep = &lchan->meas_rep[lchan->meas_rep_idx];
+	memset(meas_rep, 0, sizeof(*meas_rep));
+	meas_rep->lchan = lchan;
+	lchan->meas_rep_idx = (lchan->meas_rep_idx + 1)
+					% ARRAY_SIZE(lchan->meas_rep);
+
+	return meas_rep;
+}