layer1: remove second memory copy on normal burst receive
authorHarald Welte <laforge@gnumonks.org>
Sat, 29 May 2010 10:57:48 +0000 (12:57 +0200)
committerHarald Welte <laforge@gnumonks.org>
Sat, 29 May 2010 10:57:48 +0000 (12:57 +0200)
Rather than copying everythin from DSP to the global/static rxnb data structure
only to copy it later into the L1CTL message, we can allocate the L1CTL message
in advance and directly fill it.

src/target/firmware/layer1/prim_rx_nb.c

index 3f909b7..cf6df48 100644 (file)
 
 struct l1s_rxnb_state {
        struct l1s_meas_hdr meas[4];
-       uint16_t crc;
-       uint16_t fire;
-       uint16_t num_biterr;
-       uint8_t frame[24]
+
+       struct msgb *msg;
+       struct l1ctl_info_dl *dl;
+       struct l1ctl_data_ind *di;
 };
 
 static struct l1s_rxnb_state rxnb;
@@ -62,7 +62,6 @@ static int l1s_nb_resp(__unused uint8_t p1, uint8_t burst_id, uint16_t p3)
 {
        uint8_t mf_task_id = p3 & 0xff;
        uint8_t mf_task_flags = p3 >> 8;
-       struct msgb *msg;
        uint16_t rf_arfcn = l1s.serving_cell.arfcn;
 
        putchart('n');
@@ -93,51 +92,48 @@ static int l1s_nb_resp(__unused uint8_t p1, uint8_t burst_id, uint16_t p3)
 
        /* 4th burst, get frame data */
        if (dsp_api.db_r->d_burst_d == 3) {
-               struct l1ctl_hdr *l1h;
-               struct l1ctl_info_dl *dl;
-               struct l1ctl_data_ind *di;
+               uint8_t i, j;
+               uint16_t num_biterr;
                uint32_t avg_snr = 0;
                int32_t avg_dbm8 = 0;
-               uint8_t i, j;
-
-               rxnb.num_biterr = dsp_api.ndb->a_cd[2] & 0xffff;
-               rxnb.crc = ((dsp_api.ndb->a_cd[0] & 0xffff) & ((1 << B_FIRE1) | (1 << B_FIRE0))) >> B_FIRE0;
-               rxnb.fire = ((dsp_api.ndb->a_cd[0] & 0xffff) & (1 << B_FIRE1)) >> B_FIRE1;
-
-               /* copy actual data, skipping the information block [0,1,2] */
-               for (j = 0,i = 3; i < 15; i++) {
-                       rxnb.frame[j++] = dsp_api.ndb->a_cd[i] & 0xFF;
-                       rxnb.frame[j++] = (dsp_api.ndb->a_cd[i] >> 8) & 0xFF;
-               }
-
-               /* place it in the queue for the layer2 */
-               msg = l1_create_l2_msg(L1CTL_DATA_IND, l1s.current_time.fn-4,
-                                       0, rf_arfcn);
-               l1h = (struct l1ctl_hdr *) msg->l1h;
-               dl = (struct l1ctl_info_dl *) l1h->data;
-               di = (struct l1ctl_data_ind *) msgb_put(msg, sizeof(*di));
 
                /* Set Channel Number depending on MFrame Task ID */
-               dl->chan_nr = mframe_task2chan_nr(mf_task_id, 0); /* FIXME: TS */
+               rxnb.dl->chan_nr = mframe_task2chan_nr(mf_task_id, 0); /* FIXME: TS */
 
                /* Set SACCH indication in Link IDentifier */
                if (mf_task_flags & MF_F_SACCH)
-                       dl->link_id = 0x40;
+                       rxnb.dl->link_id = 0x40;
                else
-                       dl->link_id = 0x00;
+                       rxnb.dl->link_id = 0x00;
+
+               rxnb.dl->band_arfcn = htons(rf_arfcn);
+
+               rxnb.dl->frame_nr = htonl(l1s.current_time.fn-4);
 
                /* compute average snr and rx level */
                for (i = 0; i < 4; ++i) {
                        avg_snr += rxnb.meas[i].snr;
                        avg_dbm8 += rxnb.meas[i].pm_dbm8;
                }
-               dl->snr = avg_snr / 4;
-               dl->rx_level = (avg_dbm8 / (8*4)) + 110;
+               rxnb.dl->snr = avg_snr / 4;
+               rxnb.dl->rx_level = (avg_dbm8 / (8*4)) + 110;
+
+               num_biterr = dsp_api.ndb->a_cd[2] & 0xffff;
+               if (num_biterr > 0xff)
+                       rxnb.dl->num_biterr = 0xff;
+               else
+                       rxnb.dl->num_biterr = num_biterr;
 
-               /* copy the actual payload data */
-               for (i = 0; i < 23; ++i)
-                       di->data[i] = rxnb.frame[i];
-               l1_queue_for_l2(msg);
+               rxnb.dl->fire_crc = ((dsp_api.ndb->a_cd[0] & 0xffff) & ((1 << B_FIRE1) | (1 << B_FIRE0))) >> B_FIRE0;
+
+               /* copy actual data, skipping the information block [0,1,2] */
+               for (j = 0,i = 3; i < 15; i++) {
+                       rxnb.di->data[j++] = dsp_api.ndb->a_cd[i] & 0xFF;
+                       rxnb.di->data[j++] = (dsp_api.ndb->a_cd[i] >> 8) & 0xFF;
+               }
+
+               l1_queue_for_l2(rxnb.msg);
+               rxnb.msg = NULL; rxnb.dl = NULL; rxnb.di = NULL;
 
                /* clear downlink task */
                dsp_api.db_w->d_task_d = 0;
@@ -155,6 +151,21 @@ static int l1s_nb_cmd(__unused uint8_t p1, uint8_t burst_id,
        uint8_t tsc = l1s.serving_cell.bsic & 0x7;
 
        putchart('N');
+
+       if (burst_id == 1) {
+               /* allocate message only at 2nd burst in case of
+                * consecutive/overlapping normal burst RX tasks */
+               /* FIXME: we actually want all allocation out of L1S! */
+               if (rxnb.msg)
+                       printf("nb_cmd(0) and rxnb.msg != NULL\n");
+               /* allocate msgb as needed. FIXME: from L1A ?? */
+               rxnb.msg = l1ctl_msgb_alloc(L1CTL_DATA_IND);
+               if (!rxnb.msg)
+                       printf("nb_cmd(0): unable to allocate msgb\n");
+               rxnb.dl = (struct l1ctl_info_dl *) msgb_put(rxnb.msg, sizeof(*rxnb.dl));
+               rxnb.di = (struct l1ctl_data_ind *) msgb_put(rxnb.msg, sizeof(*rxnb.di));
+       }
+
        dsp_load_rx_task(ALLC_DSP_TASK, burst_id, tsc);
        dsp_end_scenario();