Skip to content

libiio-v1: Setting buffer length in mmap/dmabuf cases #1312

@schwesinger

Description

@schwesinger

Hi,

when creating IIO blocks (during creation of an IIO stream [1]), block_size of the IIO buffer is set to the size of the IIO block in case the mmap/dmabuf APIs are not used [2]. Later when the IIO buffer is enabled, the length attribute of the buffer is set to the number of samples derived from the block_size and sample_size [3] [4] [5].
When the dmabuf API is used with an IIO buffer block_size is not set and the length attribute of the buffer is left at its default value, which was 2048 samples (per channel) in my experiments.

In the FPGA design I'm using, the length attribute of the buffer is used to determine the number of samples that are to be transmitted per DMA transaction. For IIO blocks that can hold more than 2048 samples, the remaining block space is filled with "bogus" data*, the 2049th sample will be present in the next IIO block. This was observed when correlating the raw received data with data obtained from an ILA triggering on TLAST of the DMA FIFO core.

Manually setting buffer/length to the IIO block size via the sysfs interface fixes the issue and continuous transfers work as expected. Unfortunately, I was not able to programmatically set buffer/length using libiio: Iterating over the attributes of the IIO buffer in question only returns data_available, direction and length_align_bytes. Thus, I resorted to patching libiio to set the block_size of the IIO buffer during block creation as in the non-dmabuf case:

diff --git a/block.c b/block.c
index d26314fb..cab112ae 100644
--- a/block.c
+++ b/block.c
@@ -67,8 +67,6 @@ iio_buffer_create_block(struct iio_buffer *buf, size_t size)

                if (size > buf->length)
                      buf->length = size;
-
-               buf->block_size = size;
        }

        block->buffer = buf;
@@ -76,6 +74,7 @@ iio_buffer_create_block(struct iio_buffer *buf, size_t size)

        iio_mutex_lock(buf->lock);
        buf->nb_blocks++;
+       buf->block_size = size;
        iio_mutex_unlock(buf->lock);

        return block;
diff --git a/local.c b/local.c
index ca5edfc5..e8065133 100644
--- a/local.c
+++ b/local.c
@@ -328,9 +328,6 @@ static int local_enable_buffer(struct iio_buffer_pdata *pdata,
 {
        int ret;

-       if ((pdata->dmabuf_supported | pdata->mmap_supported) != !nb_samples)
-               return -EINVAL;
-
        if (enable && nb_samples) {
                ret = local_set_buffer_size(pdata, nb_samples);
                if (ret)

However, I'm absolutely unsure, if this is the right approach because the checks in local_enable_buffer, can be interpreted as deliberate checks for an IIO buffer block_size set to zero (converted to number of samples nb_samples). As I don't know all the other use cases/contexts for using IIO blocks, this patch could well introduce some unintended side effects. So could anybody more familiar with libiio internals have a look?

*) For testing purposes I initialized the mmap()ed dmabuf memory in local_create_dmabuf() with a recurring 4-byte pattern. And repeated my test without setting the IIO buffer length. The pattern was found in the transmitted data with series of zeroes interspersed. So maybe it's advisable to zero dmabuf memory right after allocation?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions