aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bts-sysmo/l1_transp_hw.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/osmo-bts-sysmo/l1_transp_hw.c')
-rw-r--r--src/osmo-bts-sysmo/l1_transp_hw.c81
1 files changed, 56 insertions, 25 deletions
diff --git a/src/osmo-bts-sysmo/l1_transp_hw.c b/src/osmo-bts-sysmo/l1_transp_hw.c
index f0f028bb..da8ac3f3 100644
--- a/src/osmo-bts-sysmo/l1_transp_hw.c
+++ b/src/osmo-bts-sysmo/l1_transp_hw.c
@@ -156,49 +156,80 @@ static int wqueue_vector_cb(struct osmo_fd *fd, unsigned int what)
return 0;
}
-/* callback when there's something to read from the l1 msg_queue */
-static int l1if_fd_cb(struct osmo_fd *ofd, unsigned int what)
+static int prim_size_for_queue(int queue)
{
- //struct msgb *msg = l1p_msgb_alloc();
- struct msgb *msg = msgb_alloc_headroom(SYSMOBTS_PRIM_SIZE, 128, "1l_fd");
- struct femtol1_hdl *fl1h = ofd->data;
- int rc;
-
- msg->l1h = msg->data;
- rc = read(ofd->fd, msg->l1h, msgb_tailroom(msg));
- if (rc < 0) {
- if (rc != -1)
- LOGP(DL1C, LOGL_ERROR, "error reading from L1 msg_queue: %s\n",
- strerror(errno));
- msgb_free(msg);
- return rc;
+ switch (queue) {
+ case MQ_SYS_WRITE:
+ return sizeof(SuperFemto_Prim_t);
+ case MQ_L1_WRITE:
+#ifndef HW_SYSMOBTS_V1
+ case MQ_TCH_WRITE:
+ case MQ_PDTCH_WRITE:
+#endif
+ return sizeof(GsmL1_Prim_t);
+ default:
+ /* The compiler can't know that priv_nr is an enum. Assist. */
+ LOGP(DL1C, LOGL_FATAL, "writing on a wrong queue: %d\n",
+ queue);
+ assert(false);
+ break;
}
- msgb_put(msg, rc);
+}
- switch (ofd->priv_nr) {
+/* callback when there's something to read from the l1 msg_queue */
+static int read_dispatch_one(struct femtol1_hdl *fl1h, struct msgb *msg, int queue)
+{
+ switch (queue) {
case MQ_SYS_WRITE:
- if (rc != sizeof(SuperFemto_Prim_t))
- LOGP(DL1C, LOGL_NOTICE, "%u != "
- "sizeof(SuperFemto_Prim_t)\n", rc);
return l1if_handle_sysprim(fl1h, msg);
case MQ_L1_WRITE:
#ifndef HW_SYSMOBTS_V1
case MQ_TCH_WRITE:
case MQ_PDTCH_WRITE:
#endif
- if (rc != sizeof(GsmL1_Prim_t))
- LOGP(DL1C, LOGL_NOTICE, "%u != "
- "sizeof(GsmL1_Prim_t)\n", rc);
- return l1if_handle_l1prim(ofd->priv_nr, fl1h, msg);
+ return l1if_handle_l1prim(queue, fl1h, msg);
default:
/* The compiler can't know that priv_nr is an enum. Assist. */
LOGP(DL1C, LOGL_FATAL, "writing on a wrong queue: %d\n",
- ofd->priv_nr);
+ queue);
assert(false);
break;
}
};
+static int l1if_fd_cb(struct osmo_fd *ofd, unsigned int what)
+{
+ int i, rc;
+
+ const uint32_t prim_size = prim_size_for_queue(ofd->priv_nr);
+ uint32_t count;
+
+ struct iovec iov[3];
+ struct msgb *msg[ARRAY_SIZE(iov)];
+
+ for (i = 0; i < ARRAY_SIZE(iov); ++i) {
+ msg[i] = msgb_alloc_headroom(prim_size + 128, 128, "1l_fd");
+ msg[i]->l1h = msg[i]->data;
+
+ iov[i].iov_base = msg[i]->l1h;
+ iov[i].iov_len = msgb_tailroom(msg[i]);
+ }
+
+
+ rc = readv(ofd->fd, iov, ARRAY_SIZE(iov));
+ count = rc / prim_size;
+
+ for (i = 0; i < count; ++i) {
+ msgb_put(msg[i], prim_size);
+ read_dispatch_one(ofd->data, msg[i], ofd->priv_nr);
+ }
+
+ for (i = count; i < ARRAY_SIZE(iov); ++i)
+ msgb_free(msg[i]);
+
+ return 1;
+}
+
/* callback when we can write to one of the l1 msg_queue devices */
static int l1fd_write_cb(struct osmo_fd *ofd, struct msgb *msg)
{