diff options
Diffstat (limited to 'src/osmo-bts-sysmo')
-rw-r--r-- | src/osmo-bts-sysmo/l1_transp_hw.c | 81 |
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) { |