aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2013-05-01 16:13:37 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2013-06-24 08:02:34 +0200
commit718cc9dcac1634d4d7313e4130fdf0343d5046dd (patch)
treeb3007816e050dcef26c24711fb82b260ff4e9301
parent44eec601bc88a454a866ea6e5d9c2107752df040 (diff)
sysmobts: Read multiple primitives at once but only up to 3
In most cases there are multiple messages ready to be read from the queue and it is more efficient to read them in one go instead of going through the select again.
-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)
{