[lapdm] Added flow control between L1 and L2, so DM mode does not crash.
authorAndreas.Eversberg <jolly@eversberg.eu>
Sat, 26 Jun 2010 11:12:25 +0000 (11:12 +0000)
committerAndreas.Eversberg <jolly@eversberg.eu>
Sat, 26 Jun 2010 11:12:25 +0000 (11:12 +0000)
In dedicated mode a frame is sent to layer 1. Subsequent frames are queued
inside lapdm.c until a confirm from layer 1 is received. Since not all
pending frames are sent rapidly at once, the layer 1 does not crash anymore.

Also included in this commit: handling of reset confirm (maybe required
in the future after dedicated mode)

src/host/layer23/include/osmocom/l1ctl.h
src/host/layer23/include/osmocom/lapdm.h
src/host/layer23/src/app_mobile.c
src/host/layer23/src/gsm322.c
src/host/layer23/src/gsm48_rr.c
src/host/layer23/src/l1ctl.c
src/host/layer23/src/lapdm.c

index ad59b2d..cac37cf 100644 (file)
@@ -32,6 +32,9 @@ int l1ctl_tx_ccch_mode_req(struct osmocom_ms *ms, uint8_t ccch_mode);
 
 int l1ctl_tx_echo_req(struct osmocom_ms *ms, unsigned int len);
 
+/* Transmit L1CTL_RESET_REQ */
+int l1ctl_tx_reset_req(struct osmocom_ms *ms, uint8_t type);
+
 /* Transmit L1CTL_PM_REQ */
 int l1ctl_tx_pm_req_range(struct osmocom_ms *ms, uint16_t arfcn_from,
                          uint16_t arfcm_to);
index f1f4ed5..06ac5f8 100644 (file)
@@ -78,6 +78,7 @@ void lapdm_exit(struct lapdm_entity *le);
 
 /* input into layer2 (from layer 1) */
 int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le, struct l1ctl_info_dl *l1i);
+int l2_ph_data_conf(struct msgb *msg, struct lapdm_entity *le);
 
 /* input into layer2 (from layer 3) */
 int rslms_recvmsg(struct msgb *msg, struct osmocom_ms *ms);
index 9e8938c..a7a1215 100644 (file)
@@ -80,11 +80,8 @@ static int signal_cb(unsigned int subsys, unsigned int signal,
 
        switch (signal) {
        case S_L1CTL_RESET:
-               if (started) {
-                       printf("L1_RESET, TODO: resend last radio request "
-                               "(CCCH / dedicated / power scan)\n");
+               if (started)
                        break;
-               }
                started = 1;
                ms = signal_data;
                /* insert test card, if enabled */
index 8c51d01..672f77e 100644 (file)
@@ -221,6 +221,7 @@ int gsm322_cs_sendmsg(struct osmocom_ms *ms, struct msgb *msg)
 
 static int gsm322_sync_to_cell(struct osmocom_ms *ms, struct gsm322_cellsel *cs)
 {
+//     l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
        return l1ctl_tx_fbsb_req(ms, cs->arfcn,
                                 L1CTL_FBSB_F_FB01SB, 100, 0,
                                 CCCH_MODE_COMBINED);
@@ -2404,6 +2405,9 @@ static int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
                ms = rc->ms;
                gsm48_rr_rach_conf(ms, rc->fn);
                break;
+       case S_L1CTL_RESET:
+               LOGP(DCS, LOGL_INFO, "Reset\n");
+               break;
        }
 
        return 0;
index 415adc4..20580b2 100644 (file)
@@ -215,7 +215,8 @@ static void new_rr_state(struct gsm48_rrlayer *rr, int state)
                struct msgb *msg, *nmsg;
 
                /* release dedicated mode, if any */
-               tx_ph_dm_rel_req(rr->ms);
+//             tx_ph_dm_rel_req(rr->ms);
+               l1ctl_tx_reset_req(rr->ms, L1CTL_RES_T_FULL);
                /* free establish message, if any */
                rr->rr_est_req = 0;
                if (rr->rr_est_msg) {
index 6e59204..38d4f5d 100644 (file)
@@ -208,6 +208,26 @@ static int rx_ph_data_ind(struct osmocom_ms *ms, struct msgb *msg)
        return 0;
 }
 
+/* Receive L1CTL_DATA_CONF (Data Confirm from L1) */
+static int rx_ph_data_conf(struct osmocom_ms *ms, struct msgb *msg)
+{
+       struct l1ctl_info_dl *dl;
+       struct lapdm_entity *le;
+
+       dl = (struct l1ctl_info_dl *) msg->l1h;
+
+       /* determine LAPDm entity based on SACCH or not */
+       if (dl->link_id & 0x40)
+               le = &ms->l2_entity.lapdm_acch;
+       else
+               le = &ms->l2_entity.lapdm_dcch;
+
+       /* send it up into LAPDm */
+       l2_ph_data_conf(msg, le);
+
+       return 0;
+}
+
 /* Transmit L1CTL_DATA_REQ */
 int tx_ph_data_req(struct osmocom_ms *ms, struct msgb *msg,
                   uint8_t chan_nr, uint8_t link_id)
@@ -397,6 +417,23 @@ int l1ctl_tx_pm_req_range(struct osmocom_ms *ms, uint16_t arfcn_from,
        return osmo_send_l1(ms, msg);
 }
 
+/* Transmit L1CTL_RESET_REQ */
+int l1ctl_tx_reset_req(struct osmocom_ms *ms, uint8_t type)
+{
+       struct msgb *msg;
+       struct l1ctl_reset *res;
+
+       msg = osmo_l1_alloc(L1CTL_RESET_REQ);
+       if (!msg)
+               return -1;
+
+       printf("Tx Reset Req (%u)\n", type);
+       res = (struct l1ctl_reset *) msgb_put(msg, sizeof(*res));
+       res->type = type;
+
+       return osmo_send_l1(ms, msg);
+}
+
 /* Receive L1CTL_RESET_IND */
 static int rx_l1_reset(struct osmocom_ms *ms)
 {
@@ -452,7 +489,11 @@ int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg)
        case L1CTL_DATA_IND:
                rc = rx_ph_data_ind(ms, msg);
                break;
+       case L1CTL_DATA_CONF:
+               rc = rx_ph_data_conf(ms, msg);
+               break;
        case L1CTL_RESET_IND:
+       case L1CTL_RESET_CONF:
                rc = rx_l1_reset(ms);
                msgb_free(msg);
                break;
@@ -462,19 +503,10 @@ int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg)
                if (l1h->flags & L1CTL_F_DONE)
                        dispatch_signal(SS_L1CTL, S_L1CTL_PM_DONE, ms);
                break;
-       case L1CTL_RESET_CONF:
-               LOGP(DL1C, LOGL_NOTICE, "L1CTL_RESET_CONF\n");
-               msgb_free(msg);
-               break;
        case L1CTL_RACH_CONF:
-               LOGP(DL1C, LOGL_NOTICE, "L1CTL_RACH_CONF\n");
                rc = rx_l1_rach_conf(ms, msg);
                msgb_free(msg);
                break;
-       case L1CTL_DATA_CONF:
-               LOGP(DL1C, LOGL_NOTICE, "L1CTL_DATA_CONF\n");
-               msgb_free(msg);
-               break;
        default:
                fprintf(stderr, "Unknown MSG: %u\n", l1h->msg_type);
                msgb_free(msg);
index c3a86b1..fea63c1 100644 (file)
@@ -297,14 +297,13 @@ static int tx_ph_data_enqueue(struct lapdm_datalink *dl, struct msgb *msg,
 
        /* send the frame now */
        le->tx_pending = 1;
-#warning HACK: no confirm yet! (queue is always empty now)
-le->tx_pending = 0;
+#if 0
 printf("-> tx chan_nr 0x%x link_id 0x%x len %d data", chan_nr, link_id, msgb_l2len(msg));
 int i;
 for (i = 0; i < msgb_l2len(msg); i++)
        printf(" %02x", msg->l2h[i]);
 printf("\n");
-//usleep(100000);
+#endif
        lapdm_pad_msgb(msg, n201);
        return tx_ph_data_req(ms, msg, chan_nr, link_id);
 }
@@ -312,15 +311,23 @@ printf("\n");
 /* get next frame from the tx queue. because the ms has multiple datalinks,
  * each datalink's queue is read round-robin.
  */
-static int tx_ph_data_dequeue(struct lapdm_entity *le)
+int l2_ph_data_conf(struct msgb *msg, struct lapdm_entity *le)
 {
        struct osmocom_ms *ms = le->ms;
        struct lapdm_datalink *dl;
        int last = le->last_tx_dequeue;
        int i = last, n = ARRAY_SIZE(le->datalink);
-       struct msgb *msg;
        uint8_t chan_nr, link_id, n201;
 
+       /* we may send again */
+       le->tx_pending = 0;
+
+#if 0
+printf("-> tx confirm\n");
+#endif
+       /* free confirm message */
+       msgb_free(msg);
+
        /* round-robin dequeue */
        do {
                /* next */
@@ -331,7 +338,7 @@ static int tx_ph_data_dequeue(struct lapdm_entity *le)
        } while (i != last);
 
        /* no message in all queues */
-       if (msg)
+       if (!msg)
                return 0;
 
        /* Pull chan_nr and link_id */
@@ -347,6 +354,12 @@ static int tx_ph_data_dequeue(struct lapdm_entity *le)
 
        /* Pad the frame, we can transmit now */
        le->tx_pending = 1;
+#if 0
+printf("-> more tx chan_nr 0x%x link_id 0x%x len %d data", chan_nr, link_id, msgb_l2len(msg));
+for (i = 0; i < msgb_l2len(msg); i++)
+       printf(" %02x", msg->l2h[i]);
+printf("\n");
+#endif
        lapdm_pad_msgb(msg, n201);
        return tx_ph_data_req(ms, msg, chan_nr, link_id);
 }
@@ -1419,6 +1432,13 @@ static int lapdm_ph_data_ind(struct msgb *msg, struct lapdm_msg_ctx *mctx)
 {
        int rc;
 
+#if 0
+printf("-> rx chan_nr 0x%x link_id 0x%x len %d data", mctx->chan_nr, mctx->link_id, msgb_l2len(msg));
+int i;
+for (i = 0; i < msgb_l2len(msg); i++)
+       printf(" %02x", msg->l2h[i]);
+printf("\n");
+#endif
        /* G.2.3 EA bit set to "0" is not allowed in GSM */
        if (!LAPDm_ADDR_EA(mctx->addr)) {
                LOGP(DLAPDM, LOGL_NOTICE, "EA bit 0 is not allowed in GSM\n");
@@ -1959,7 +1979,7 @@ const char *lapdm_state_names[] = {
        "LAPDm_STATE_SABM_SENT",
        "LAPDm_STATE_MF_EST",
        "LAPDm_STATE_TIMER_RECOV",
-       "LAPDm_STATE_OWN_RCVR_BUSY"
+       "LAPDm_STATE_DISC_SENT",
 };
 
 /* statefull handling for RSLms RLL messages from L3 */