aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bts-sysmo/l1_transp_hw.c
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2013-05-04 11:30:18 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2013-06-24 08:02:34 +0200
commit44eec601bc88a454a866ea6e5d9c2107752df040 (patch)
treea58b253b7a77b4a4701c5f8c07b474254e8f15e8 /src/osmo-bts-sysmo/l1_transp_hw.c
parent25346fe0d7a8b83acdee8332bec921dbb254f016 (diff)
sysmobts: Use writev for the outgoing data of the write queue
Attempt to write multiple primitives at the same time instead of the select/write, select/write that is currently done. The queue size is big enough to hold several entries at the same time and it is unlikely we get the -EAGAIN from the kernel driver. The writev code works by assuming that each element in the queue has the same size. This is not verified by the code and if this assumption breaks at some point the code will drop primitives or send some twice.
Diffstat (limited to 'src/osmo-bts-sysmo/l1_transp_hw.c')
-rw-r--r--src/osmo-bts-sysmo/l1_transp_hw.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/osmo-bts-sysmo/l1_transp_hw.c b/src/osmo-bts-sysmo/l1_transp_hw.c
index 4db4b30b..f0f028bb 100644
--- a/src/osmo-bts-sysmo/l1_transp_hw.c
+++ b/src/osmo-bts-sysmo/l1_transp_hw.c
@@ -88,6 +88,74 @@ static const char *wr_devnames[] = {
osmo_static_assert(sizeof(GsmL1_Prim_t) + 128 <= SYSMOBTS_PRIM_SIZE, l1_prim)
osmo_static_assert(sizeof(SuperFemto_Prim_t) + 128 <= SYSMOBTS_PRIM_SIZE, super_prim)
+static int wqueue_vector_cb(struct osmo_fd *fd, unsigned int what)
+{
+ struct osmo_wqueue *queue;
+
+ queue = container_of(fd, struct osmo_wqueue, bfd);
+
+ if (what & BSC_FD_READ)
+ queue->read_cb(fd);
+
+ if (what & BSC_FD_EXCEPT)
+ queue->except_cb(fd);
+
+ if (what & BSC_FD_WRITE) {
+ struct iovec iov[5];
+ struct msgb *msg, *tmp;
+ int written, count = 0;
+
+ fd->when &= ~BSC_FD_WRITE;
+
+ llist_for_each_entry(msg, &queue->msg_queue, list) {
+ /* more writes than we have */
+ if (count >= ARRAY_SIZE(iov))
+ break;
+
+ iov[count].iov_base = msg->l1h;
+ iov[count].iov_len = msgb_l1len(msg);
+ count += 1;
+ }
+
+ /* TODO: check if all lengths are the same. */
+
+
+ /* Nothing scheduled? This should not happen. */
+ if (count == 0) {
+ if (!llist_empty(&queue->msg_queue))
+ fd->when |= BSC_FD_WRITE;
+ return 0;
+ }
+
+ written = writev(fd->fd, iov, count);
+ if (written < 0) {
+ /* nothing written?! */
+ if (!llist_empty(&queue->msg_queue))
+ fd->when |= BSC_FD_WRITE;
+ return 0;
+ }
+
+ /* now delete the written entries */
+ written = written / iov[0].iov_len;
+ count = 0;
+ llist_for_each_entry_safe(msg, tmp, &queue->msg_queue, list) {
+ queue->current_length -= 1;
+
+ llist_del(&msg->list);
+ msgb_free(msg);
+
+ count += 1;
+ if (count >= written)
+ break;
+ }
+
+ if (!llist_empty(&queue->msg_queue))
+ fd->when |= BSC_FD_WRITE;
+ }
+
+ 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)
{
@@ -185,6 +253,7 @@ int l1if_transport_open(int q, struct femtol1_hdl *hdl)
}
osmo_wqueue_init(wq, 10);
wq->write_cb = l1fd_write_cb;
+ write_ofd->cb = wqueue_vector_cb;
write_ofd->fd = rc;
write_ofd->priv_nr = q;
write_ofd->data = hdl;