diff --git a/README_BUILD.md b/README_BUILD.md index 19d787cd7..00c043273 100644 --- a/README_BUILD.md +++ b/README_BUILD.md @@ -164,6 +164,46 @@ It will try to link against the `call_function` symbol even though it's clearly For this reason, when building with MSVC, please build in `RelWithDebInfo` mode. If you try to build in `Debug` mode, it will error. +## Environment Variable Configuration + +### DMA Heap Path Configuration + +libiio supports configuring the DMA heap path globally through the `LIBIIO_DMA_HEAP_PATH` environment variable. This overrides the default `/dev/dma_heap/system` path for all IIO devices. + +#### Supported Format (Global Only) +```bash +export LIBIIO_DMA_HEAP_PATH=heap_name +``` +This will use `/dev/dma_heap/` for every device. + +#### Accepted Values + +The environment variable accepts only the following predefined heap names: +- `system` (default when unset or empty) +- `default_cma_region` +- `reserved` +- `linux,cma` +- `default-pool` + +**Examples:** +```bash +export LIBIIO_DMA_HEAP_PATH=default_cma_region +./an_iio_application + +export LIBIIO_DMA_HEAP_PATH=reserved +./an_iio_application +``` + +#### Behavior and Error Handling + +- **Unset or empty**: Defaults to `system` heap (`/dev/dma_heap/system`) +- **Valid value**: Uses the specified heap (`/dev/dma_heap/`) +- **Invalid value**: **Operation fails with error** - no fallback occurs + +Setting an invalid heap name will cause DMABUF operations to fail immediately with an error message listing the accepted values. This ensures users are aware when their configuration is incorrect rather than silently using a fallback. + +This feature is intended for users who need to select an alternative DMA heap present under `/dev/dma_heap/` (for example a reserved or CMA heap). + ## Instructions applicable to Microcontroller configurations ### Install Prerequisites/Dependencies diff --git a/bindings/cpp/iio.hpp b/bindings/cpp/iio.hpp index 0956acecf..f2b1f1e4b 100644 --- a/bindings/cpp/iio.hpp +++ b/bindings/cpp/iio.hpp @@ -572,7 +572,7 @@ class Device : public impl::IndexedSequence Device trigger() const {return Device{const_cast(impl::check(iio_device_get_trigger(p), "iio_device_get_trigger"))};} void set_trigger(iio_device const * trigger) {impl::check(iio_device_set_trigger(p, trigger), "iio_device_set_trigger");} bool is_trigger() const {return iio_device_is_trigger(p);} - BufferPtr create_buffer(iio_buffer_params * params, iio_channels_mask * mask) {return BufferPtr(impl::check(iio_device_create_buffer(p, params, mask), "iio_device_create_buffer"));} + BufferPtr create_buffer(unsigned int idx, iio_channels_mask * mask) {return BufferPtr(impl::check(iio_device_create_buffer(p, idx, mask), "iio_device_create_buffer"));} bool is_hwmon() const {return iio_device_is_hwmon(p);} EventStreamPtr create_event_stream() { return EventStreamPtr{impl::check(iio_device_create_event_stream(p), "iio_device_create_event_stream")};} ssize_t sample_size(iio_channels_mask * mask) const {return impl::check_n(iio_device_get_sample_size(p, mask), "iio_device_get_sample_size");} diff --git a/bindings/csharp/IOBuffer.cs b/bindings/csharp/IOBuffer.cs index 4f535ac79..298828f7c 100644 --- a/bindings/csharp/IOBuffer.cs +++ b/bindings/csharp/IOBuffer.cs @@ -22,7 +22,7 @@ namespace iio public class IOBuffer : IIOObject { [DllImport(IioLib.dllname, CallingConvention = CallingConvention.Cdecl)] - private static extern IIOPtr iio_device_create_buffer(IntPtr dev, IntPtr buffer_params, IntPtr mask); + private static extern IIOPtr iio_device_create_buffer(IntPtr dev, uint index, IntPtr mask); [DllImport(IioLib.dllname, CallingConvention = CallingConvention.Cdecl)] private static extern void iio_buffer_destroy(IntPtr buf); @@ -75,12 +75,12 @@ public bool enabled { /// The channels mask to use to create the buffer object. /// The index of the hardware buffer. Should be 0 in most cases. /// The buffer could not be created. - public IOBuffer(Device dev, ChannelsMask mask) + public IOBuffer(Device dev, ChannelsMask mask, uint index = 0) { this.mask = mask; this.dev = dev; - IIOPtr ptr = iio_device_create_buffer(dev.dev, IntPtr.Zero, mask.hdl); + IIOPtr ptr = iio_device_create_buffer(dev.dev, index, mask.hdl); if (!ptr) throw new IIOException("Unable to create buffer", ptr); diff --git a/bindings/python/iio/__init__.py b/bindings/python/iio/__init__.py index 0719c9169..47e845dba 100644 --- a/bindings/python/iio/__init__.py +++ b/bindings/python/iio/__init__.py @@ -133,9 +133,6 @@ class _Attr(Structure): class ContextParams(Structure): pass # TODO -class BufferParams(Structure): - pass # TODO - class DataFormat(Structure): """Represents the data format of an IIO channel.""" @@ -317,7 +314,6 @@ class ChannelType(Enum): _BlockPtr = _POINTER(_Block) _DataFormatPtr = _POINTER(DataFormat) _ContextParamsPtr = _POINTER(ContextParams) -_BufferParamsPtr = _POINTER(BufferParams) _StreamPtr = _POINTER(_Stream) _AttrPtr = _POINTER(_Attr) @@ -654,7 +650,7 @@ class ChannelType(Enum): _create_buffer.restype = _BufferPtr _create_buffer.argtypes = ( _DevicePtr, - _BufferParamsPtr, + c_uint, _ChannelsMaskPtr, ) _create_buffer.errcheck = _check_ptr_err @@ -1103,7 +1099,7 @@ def buffer(self): class Buffer(_IIO_Object): """Represents a hardware I/O buffer.""" - def __init__(self, device, mask, params): + def __init__(self, device, mask, idx=0): """ Initialize a new instance of the Buffer class. @@ -1119,7 +1115,7 @@ def __init__(self, device, mask, params): An new instance of this class """ try: - self._buffer = _create_buffer(device._device, params._params, mask._mask) + self._buffer = _create_buffer(device._device, idx, mask._mask) except Exception: self._buffer = None raise diff --git a/buffer.c b/buffer.c index 1a7c73db6..522c99a39 100644 --- a/buffer.c +++ b/buffer.c @@ -98,8 +98,7 @@ static int iio_buffer_enqueue_worker(void *_, void *d) } struct iio_buffer * -iio_device_create_buffer(const struct iio_device *dev, - struct iio_buffer_params *params, +iio_device_create_buffer(const struct iio_device *dev, unsigned int idx, const struct iio_channels_mask *mask) { const struct iio_backend_ops *ops = dev->ctx->ops; @@ -122,21 +121,8 @@ iio_device_create_buffer(const struct iio_device *dev, if (!buf) return iio_ptr(-ENOMEM); - if (params) { - /* We need to make sure that all reserved bytes are zero initialized. - * This is important for the ABI stability. - */ - for (i = 0; i < sizeof(buf->params.__rsrv); i++) { - if (params->__rsrv[i]) { - dev_err(dev, "Reserved bytes in buffer params must be zero.\n"); - err = -E2BIG; - goto err_free_buf; - } - } - - buf->params = *params; - } buf->dev = dev; + buf->idx = idx; /* Duplicate buffer attributes from the iio_device. * This ensures that those can contain a pointer to our iio_buffer */ @@ -175,7 +161,7 @@ iio_device_create_buffer(const struct iio_device *dev, if (err < 0) goto err_free_mutex; - buf->pdata = ops->create_buffer(dev, &buf->params, buf->mask); + buf->pdata = ops->create_buffer(dev, idx, buf->mask); err = iio_err(buf->pdata); if (err < 0) goto err_destroy_worker; diff --git a/compat.c b/compat.c index fbe1362a4..77e2ec68e 100644 --- a/compat.c +++ b/compat.c @@ -39,7 +39,6 @@ struct iio_channel; struct iio_channels_mask; struct iio_context; struct iio_context_params; -struct iio_buffer_params; struct iio_data_format; struct iio_device; struct iio_scan; @@ -168,7 +167,7 @@ struct compat { /* Buffers */ struct iio_buffer * (*iio_device_create_buffer)(const struct iio_device *, - struct iio_buffer_params *, + unsigned int, const struct iio_channels_mask *); void (*iio_buffer_destroy)(struct iio_buffer *); void (*iio_buffer_cancel)(struct iio_buffer *); @@ -2038,7 +2037,7 @@ struct iio_buffer * iio_device_create_buffer(const struct iio_device *dev, len = samples_count * compat->sample_size; compat->size = len; - buf = IIO_CALL(iio_device_create_buffer)(dev, NULL, dev_compat->mask); + buf = IIO_CALL(iio_device_create_buffer)(dev, 0, dev_compat->mask); err = iio_err(buf); if (err) goto err_free_compat; diff --git a/examples/ad9361-iiostream.c b/examples/ad9361-iiostream.c index 2e79bc957..61508821f 100644 --- a/examples/ad9361-iiostream.c +++ b/examples/ad9361-iiostream.c @@ -263,14 +263,14 @@ int main (int argc, char **argv) iio_channel_enable(tx0_q, txmask); printf("* Creating non-cyclic IIO buffers with 1 MiS\n"); - rxbuf = iio_device_create_buffer(rx, NULL, rxmask); + rxbuf = iio_device_create_buffer(rx, 0, rxmask); err = iio_err(rxbuf); if (err) { rxbuf = NULL; dev_perror(rx, err, "Could not create RX buffer"); shutdown(); } - txbuf = iio_device_create_buffer(tx, NULL, txmask); + txbuf = iio_device_create_buffer(tx, 0, txmask); err = iio_err(txbuf); if (err) { txbuf = NULL; diff --git a/examples/ad9371-iiostream.c b/examples/ad9371-iiostream.c index b3925e407..e1c10182f 100644 --- a/examples/ad9371-iiostream.c +++ b/examples/ad9371-iiostream.c @@ -270,14 +270,14 @@ int main (int argc, char **argv) iio_channel_enable(tx0_q, txmask); printf("* Creating non-cyclic IIO buffers with 1 MiS\n"); - rxbuf = iio_device_create_buffer(rx, NULL, rxmask); + rxbuf = iio_device_create_buffer(rx, 0, rxmask); err = iio_err(rxbuf); if (err) { rxbuf = NULL; dev_perror(rx, err, "Could not create RX buffer"); shutdown(); } - txbuf = iio_device_create_buffer(tx, NULL, txmask); + txbuf = iio_device_create_buffer(tx, 0, txmask); err = iio_err(txbuf); if (err) { txbuf = NULL; diff --git a/examples/adrv9002-iiostream.c b/examples/adrv9002-iiostream.c index 22d33a777..593d118d2 100644 --- a/examples/adrv9002-iiostream.c +++ b/examples/adrv9002-iiostream.c @@ -281,14 +281,14 @@ int main(int argc, char **argv) } info("* Creating non-cyclic IIO buffers with 1 MiS\n"); - rxbuf = iio_device_create_buffer(rx, NULL, rxmask); + rxbuf = iio_device_create_buffer(rx, 0, rxmask); if (iio_err(rxbuf)) { rxbuf = NULL; ctx_perror(ctx, iio_err(rxbuf), "Could not create RX buffer"); goto clean; } - txbuf = iio_device_create_buffer(tx, NULL, txmask); + txbuf = iio_device_create_buffer(tx, 0, txmask); if (iio_err(txbuf)) { txbuf = NULL; ctx_perror(ctx, iio_err(txbuf), "Could not create TX buffer"); diff --git a/examples/adrv9009-iiostream.c b/examples/adrv9009-iiostream.c index 100da16d3..7e1a16bba 100644 --- a/examples/adrv9009-iiostream.c +++ b/examples/adrv9009-iiostream.c @@ -262,14 +262,14 @@ int main (int argc, char **argv) iio_channel_enable(tx0_q, txmask); printf("* Creating non-cyclic IIO buffers with 1 MiS\n"); - rxbuf = iio_device_create_buffer(rx, NULL, rxmask); + rxbuf = iio_device_create_buffer(rx, 0, rxmask); err = iio_err(rxbuf); if (err) { rxbuf = NULL; ctx_perror(ctx, err, "Could not create RX buffer"); shutdown(); } - txbuf = iio_device_create_buffer(tx, NULL, txmask); + txbuf = iio_device_create_buffer(tx, 0, txmask); err = iio_err(txbuf); if (err) { txbuf = NULL; diff --git a/examples/dummy-iiostream.c b/examples/dummy-iiostream.c index d7bab1e8a..41b414052 100644 --- a/examples/dummy-iiostream.c +++ b/examples/dummy-iiostream.c @@ -304,7 +304,7 @@ int main (int argc, char **argv) } printf("* Creating non-cyclic RX IIO buffer\n"); - rxbuf = iio_device_create_buffer(dev, NULL, rxmask); + rxbuf = iio_device_create_buffer(dev, 0, rxmask); err = iio_err(rxbuf); if (err) { rxbuf = NULL; diff --git a/examples/iio_adi_xflow_check.c b/examples/iio_adi_xflow_check.c index c518fd995..de1f0877a 100644 --- a/examples/iio_adi_xflow_check.c +++ b/examples/iio_adi_xflow_check.c @@ -232,7 +232,7 @@ int main(int argc, char **argv) printf("Monitoring %s for underflows/overflows\n", iio_device_get_name(dev)); - buffer = iio_device_create_buffer(dev, NULL, mask); + buffer = iio_device_create_buffer(dev, 0, mask); ret = iio_err(buffer); if (ret) { IIO_PERROR(ret, "Unable to create buffer"); diff --git a/iio-private.h b/iio-private.h index d907bd725..dbdf4e011 100644 --- a/iio-private.h +++ b/iio-private.h @@ -140,7 +140,8 @@ struct iio_buffer { size_t length; struct iio_channels_mask *mask; - struct iio_buffer_params params; + unsigned int idx; + struct iio_task *worker; /* These two fields are set by the last block created. They are only diff --git a/iiod-client.c b/iiod-client.c index faab598d8..6dcbb92ad 100644 --- a/iiod-client.c +++ b/iiod-client.c @@ -15,12 +15,6 @@ #include #include -#ifdef _WIN32 -#include -#else -#include -#endif - #include #include #include @@ -59,7 +53,7 @@ struct iiod_client_buffer_pdata { struct iio_channels_mask *mask; const struct iio_device *dev; - struct iio_buffer_params params; + uint16_t idx; /* TODO: atomic? */ uint16_t next_block_idx; @@ -584,7 +578,7 @@ static ssize_t iiod_client_read_attr_new(struct iiod_client *client, return -ENOENT; arg1 = (uint16_t) i; - arg2 = (uint16_t) buf->params.idx; + arg2 = (uint16_t) buf->idx; break; default: return -EINVAL; @@ -750,7 +744,7 @@ static ssize_t iiod_client_write_attr_new(struct iiod_client *client, return -ENOENT; arg1 = (uint16_t) i; - arg2 = (uint16_t) buf->params.idx; + arg2 = (uint16_t) buf->idx; break; default: return -EINVAL; @@ -1427,7 +1421,7 @@ ssize_t iiod_client_writebuf(struct iiod_client_buffer_pdata *pdata, struct iiod_client_buffer_pdata * iiod_client_create_buffer(struct iiod_client *client, struct iiod_client *client_fb, - const struct iio_device *dev, const struct iio_buffer_params *params, + const struct iio_device *dev, unsigned int idx, struct iio_channels_mask *mask) { struct iiod_io *io; @@ -1441,37 +1435,23 @@ iiod_client_create_buffer(struct iiod_client *client, return iio_ptr(-ENOMEM); pdata->dev = dev; - pdata->params = *params; + pdata->idx = (uint16_t) idx; pdata->client = client; pdata->client_fb = client_fb; pdata->mask = mask; if (iiod_client_uses_binary_interface(client)) { - struct iiod_buf_params *buf_params; - size_t len = sizeof(*buf_params) + mask->words * sizeof(uint32_t); - io = iiod_responder_get_default_io(client->responder); cmd.op = IIOD_OP_CREATE_BUFFER; cmd.dev = (uint8_t) iio_device_get_index(dev); - cmd.code = pdata->params.idx; - - buf_params = malloc(len); - if (!buf_params) { - err = -ENOMEM; - goto err_free_pdata; - } - - buf_params->dma_allocator = htonl(params->dma_allocator); - buf_params->nb_mask = (unsigned int) mask->words; - for (unsigned int i = 0; i < mask->words; i++) - buf_params->mask[i] = htonl(mask->mask[i]); + cmd.code = pdata->idx; - buf.ptr = buf_params; - buf.size = len; + /* TODO: endianness */ + buf.ptr = mask->mask; + buf.size = mask->words * 4; err = iiod_io_exec_command(io, &cmd, &buf, &buf); - free(buf_params); if (err < 0) goto err_free_pdata; } @@ -1494,7 +1474,7 @@ void iiod_client_free_buffer(struct iiod_client_buffer_pdata *pdata) cmd.op = IIOD_OP_FREE_BUFFER; cmd.dev = (uint8_t) iio_device_get_index(pdata->dev); - cmd.code = pdata->params.idx; + cmd.code = pdata->idx; iiod_io_exec_simple_command(io, &cmd); } @@ -1537,7 +1517,7 @@ int iiod_client_enable_buffer(struct iiod_client_buffer_pdata *pdata, cmd.op = enable ? IIOD_OP_ENABLE_BUFFER : IIOD_OP_DISABLE_BUFFER; cmd.dev = (uint8_t) iio_device_get_index(pdata->dev); - cmd.code = pdata->params.idx; + cmd.code = pdata->idx; io = iiod_responder_get_default_io(client->responder); @@ -1583,7 +1563,7 @@ iiod_client_create_block(struct iiod_client_buffer_pdata *pdata, cmd.op = IIOD_OP_CREATE_BLOCK; cmd.dev = (uint8_t) iio_device_get_index(pdata->dev); - cmd.code = pdata->params.idx | (block->idx << 16); + cmd.code = pdata->idx | (block->idx << 16); ret = iiod_io_exec_command(block->io, &cmd, &buf, NULL); if (ret < 0) @@ -1619,7 +1599,7 @@ void iiod_client_free_block(struct iio_block_pdata *block) cmd.op = IIOD_OP_FREE_BLOCK; cmd.dev = (uint8_t) iio_device_get_index(pdata->dev); - cmd.code = pdata->params.idx | (block->idx << 16); + cmd.code = pdata->idx | (block->idx << 16); /* Cancel any I/O going on. This means we must send the block free * command through the main I/O as the block's I/O stream is @@ -1647,7 +1627,7 @@ int iiod_client_enqueue_block(struct iio_block_pdata *block, cmd.op = cyclic ? IIOD_OP_ENQUEUE_BLOCK_CYCLIC : IIOD_OP_TRANSFER_BLOCK; cmd.dev = (uint8_t) iio_device_get_index(pdata->dev); - cmd.code = pdata->params.idx | (block->idx << 16); + cmd.code = pdata->idx | (block->idx << 16); block->bytes_used = bytes_used; buf[0].ptr = &block->bytes_used; @@ -1697,7 +1677,7 @@ int iiod_client_dequeue_block(struct iio_block_pdata *block, bool nonblock) /* The previous enqueue succeeded, but the dequeue failed. */ cmd.op = IIOD_OP_RETRY_DEQUEUE_BLOCK; cmd.dev = (uint8_t) iio_device_get_index(pdata->dev); - cmd.code = pdata->params.idx | (block->idx << 16); + cmd.code = pdata->idx | (block->idx << 16); buf.ptr = block->data; buf.size = block->bytes_used; diff --git a/iiod-responder.h b/iiod-responder.h index 24e96add0..3fd48a503 100644 --- a/iiod-responder.h +++ b/iiod-responder.h @@ -65,12 +65,6 @@ struct iiod_command { int32_t code; }; -struct iiod_buf_params { - unsigned int dma_allocator; - unsigned int nb_mask; - unsigned int mask[]; -}; - struct iiod_buf { void *ptr; size_t size; diff --git a/iiod/ops.c b/iiod/ops.c index 6ded5752f..4b346d18d 100644 --- a/iiod/ops.c +++ b/iiod/ops.c @@ -352,7 +352,7 @@ static int create_buf_and_blocks(struct DevEntry *entry, size_t samples_count, if (!entry->blocks) return -ENOMEM; - entry->buf = iio_device_create_buffer(entry->dev, NULL, mask); + entry->buf = iio_device_create_buffer(entry->dev, 0, mask); err = iio_err(entry->buf); if (err) goto err_free_blocks_array; @@ -832,7 +832,7 @@ static int open_dev_helper(struct parser_pdata *pdata, struct iio_device *dev, * a previous. E.g. like * * iio_buffer_destroy(buf); - * buf = iio_device_create_buffer(dev, ¶ms, true); + * buf = iio_device_create_buffer(dev, n, true); * * In this case the two buffers each use their own * communication channel which are unordered to each diff --git a/iiod/responder.c b/iiod/responder.c index 7dcc7fbfa..3104b0086 100644 --- a/iiod/responder.c +++ b/iiod/responder.c @@ -394,9 +394,7 @@ static void handle_create_buffer(struct parser_pdata *pdata, struct iio_channel *chn; struct buffer_entry *entry; struct iio_buffer *buf; - struct iiod_buf_params *params; struct iiod_buf data; - struct iio_buffer_params buffer_params = {0}; unsigned int i, nb_channels; size_t nb_words; int ret = -EINVAL; @@ -422,35 +420,13 @@ static void handle_create_buffer(struct parser_pdata *pdata, goto err_free_entry; } - params = malloc(sizeof(*params) + nb_words * sizeof(uint32_t)); - if (!params) { - ret = -ENOMEM; - goto err_free_words; - } - - data.ptr = params; - data.size = nb_words * 4 + sizeof(*params); + /* TODO: endianness */ + data.ptr = entry->words; + data.size = nb_words * 4; ret = iiod_command_data_read(cmd_data, &data); - if (ret < 0) { - free(params); - goto err_free_words; - } - - /* sanity check that the number of masks sent by the client matches the one we have */ - if (params->nb_mask != nb_words) { - IIO_ERROR("Buffer %u: unexpected number of words (%u != %zu)\n", - cmd->code, params->nb_mask, nb_words); - ret = -EINVAL; - free(params); + if (ret < 0) goto err_free_words; - } - - buffer_params.dma_allocator = ntohl(params->dma_allocator); - for (i = 0; i < nb_words; i++) - entry->words[i] = ntohl(params->mask[i]); - - free(params); /* Create a temporary mask object */ mask = iio_create_channels_mask(nb_channels); @@ -501,8 +477,7 @@ static void handle_create_buffer(struct parser_pdata *pdata, if (ret) goto err_destroy_dequeue_task; - buffer_params.idx = entry->idx; - buf = iio_device_create_buffer(dev, &buffer_params, mask); + buf = iio_device_create_buffer(dev, entry->idx, mask); ret = iio_err(buf); if (ret) goto err_destroy_lock; diff --git a/include/iio/iio-backend.h b/include/iio/iio-backend.h index 8efc18ace..93fdc5c52 100644 --- a/include/iio/iio-backend.h +++ b/include/iio/iio-backend.h @@ -110,7 +110,7 @@ struct iio_backend_ops { int (*set_timeout)(struct iio_context *ctx, unsigned int timeout); struct iio_buffer_pdata *(*create_buffer)(const struct iio_device *dev, - struct iio_buffer_params *params, + unsigned int idx, struct iio_channels_mask *mask); void (*free_buffer)(struct iio_buffer_pdata *pdata); int (*enable_buffer)(struct iio_buffer_pdata *pdata, diff --git a/include/iio/iio.h b/include/iio/iio.h index 8e62ec526..e007da7db 100644 --- a/include/iio/iio.h +++ b/include/iio/iio.h @@ -156,36 +156,6 @@ struct iio_context_params { char __rsrv[32]; }; -/** - * @enum iio_buffer_dma_allocator - * @brief Provides low-level control over DMA buffer allocation. - */ -enum iio_buffer_dma_allocator { - /** @brief May use scattered DMA memory (default). */ - IIO_DMA_ALLOCATOR_SYSTEM = 0, - - /** @brief Enforces contiguous DMA memory (for expert use only). */ - IIO_DMA_ALLOCATOR_CMA_LINUX = 1, -}; - -/** - * @struct iio_buffer_params - * @brief Used to pass parameters to the iio_device_create_buffer function - */ -struct iio_buffer_params { - /** @brief The index of the hardware buffer. Should be 0 in most cases. - * (default: 0) */ - unsigned int idx; - - /** @brief Use the allocator to allocate a DMA buffer. - * In most cases, this should be set to IIO_DMA_ALLOCATOR_SYSTEM. - * ONLY change this to a different option if you fully understand the - * implications. (default: IIO_DMA_ALLOCATOR_SYSTEM) */ - enum iio_buffer_dma_allocator dma_allocator; - /** @brief Reserved for future fields. Should always be 0 initialized. */ - unsigned char __rsrv[64]; -}; - /* * header guard to protect these enums from being defined * twice @@ -1148,15 +1118,12 @@ iio_buffer_find_attr(const struct iio_buffer *buf, const char *name); /** @brief Create an input or output buffer associated to the given device * @param dev A pointer to an iio_device structure - * @param params A pointer to an iio_buffer_params structure. If NULL is passed, - * default values are used, for more information see comments in - * struct iio_buffer_params. + * @param idx The index of the hardware buffer. Should be 0 in most cases. * @param mask A pointer to an iio_channels_mask structure. * @return On success, a pointer to an iio_buffer structure * @return On failure, a pointer-encoded error is returned */ __api __check_ret struct iio_buffer * -iio_device_create_buffer(const struct iio_device *dev, - struct iio_buffer_params *params, +iio_device_create_buffer(const struct iio_device *dev, unsigned int idx, const struct iio_channels_mask *mask); diff --git a/include/iio/iiod-client.h b/include/iio/iiod-client.h index e66c6d0ac..636c9e603 100644 --- a/include/iio/iiod-client.h +++ b/include/iio/iiod-client.h @@ -17,7 +17,6 @@ struct iiod_client; struct iiod_client_io; struct iiod_client_pdata; struct iio_event_stream_pdata; -struct iio_buffer_params; struct iiod_client_ops { ssize_t (*write)(struct iiod_client_pdata *desc, @@ -71,7 +70,7 @@ iiod_client_create_context(struct iiod_client *client, __api struct iiod_client_buffer_pdata * iiod_client_create_buffer(struct iiod_client *client, struct iiod_client *client_fb, - const struct iio_device *dev, const struct iio_buffer_params *params, + const struct iio_device *dev, unsigned int idx, struct iio_channels_mask *mask); __api void iiod_client_free_buffer(struct iiod_client_buffer_pdata *pdata); __api int iiod_client_enable_buffer(struct iiod_client_buffer_pdata *pdata, diff --git a/local-dmabuf.c b/local-dmabuf.c index a28ae9d3a..9f12243d3 100644 --- a/local-dmabuf.c +++ b/local-dmabuf.c @@ -23,6 +23,9 @@ #include #include +#define LIBIIO_DMA_HEAP_ENV_VAR "LIBIIO_DMA_HEAP_PATH" +#define MAX_DMA_HEAP_PATH 64 + struct iio_dmabuf_heap_data { uint64_t len; uint32_t fd; @@ -55,6 +58,41 @@ struct dma_buf_sync { uint64_t flags; }; +/* Return global DMA heap name from environment. + * Format: + * LIBIIO_DMA_HEAP_PATH=heap_name + * Returns validated heap name, or NULL if invalid value is set. + * If environment variable is unset or empty, defaults to "system". + */ +static const char *get_dma_heap_name(void) +{ + const char *env_value = getenv(LIBIIO_DMA_HEAP_ENV_VAR); + static const char *accepted_heaps[] = { + "system", + "default_cma_region", + "reserved", + "linux,cma", + "default-pool" + }; + size_t num_accepted_heaps = ARRAY_SIZE(accepted_heaps); + size_t i; + + if (!env_value || !*env_value) + return "system"; + + for (i = 0; i < num_accepted_heaps; i++) { + if (!strcmp(env_value, accepted_heaps[i])) + return accepted_heaps[i]; + } + + /* Environment variable value is not in the accepted pool */ + prm_err(NULL, "LIBIIO_DMA_HEAP_PATH value '%s' is not recognized. " + "Accepted values are: \"system\", \"default_cma_region\", " + "\"reserved\", \"linux,cma\", \"default-pool\"\n", env_value); + + return NULL; +} + static int enable_cpu_access(struct iio_block_pdata *pdata, bool enable) { struct dma_buf_sync dbuf_sync = { 0 }; @@ -78,20 +116,28 @@ local_create_dmabuf(struct iio_buffer_pdata *pdata, size_t size, void **data) .fd_flags = O_CLOEXEC | O_RDWR, }; struct iio_block_pdata *priv; - int ret, fd, devfd = -1; + const char *heap_name; + char dma_heap_path[MAX_DMA_HEAP_PATH]; + int ret, fd, devfd; priv = zalloc(sizeof(*priv)); if (!priv) return iio_ptr(-ENOMEM); - switch (pdata->params->dma_allocator) { - case IIO_DMA_ALLOCATOR_SYSTEM: - devfd = open("/dev/dma_heap/system", O_RDONLY | O_CLOEXEC | O_NOFOLLOW); /* Flawfinder: ignore */ - break; - case IIO_DMA_ALLOCATOR_CMA_LINUX: - devfd = open("/dev/dma_heap/linux,cma", O_RDONLY | O_CLOEXEC | O_NOFOLLOW); /* Flawfinder: ignore */ - break; + /* Determine DMA heap path from global environment variable */ + heap_name = get_dma_heap_name(); + if (!heap_name) { + ret = -EINVAL; + goto err_free_priv; + } + + ret = snprintf(dma_heap_path, sizeof(dma_heap_path), "/dev/dma_heap/%s", heap_name); + if (ret < 0 || ret >= (int)sizeof(dma_heap_path)) { + ret = -EINVAL; + goto err_free_priv; } + + devfd = open(dma_heap_path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); /* Flawfinder: ignore */ if (devfd < 0) { ret = -errno; diff --git a/local.c b/local.c index b0eed8fc6..4eef17912 100644 --- a/local.c +++ b/local.c @@ -286,7 +286,7 @@ local_set_buffer_size(const struct iio_buffer_pdata *pdata, size_t nb_samples) iio_snprintf(buf, sizeof(buf), "%zu", nb_samples); - ret = local_write_dev_attr(pdata->dev, pdata->params->idx, "length", + ret = local_write_dev_attr(pdata->dev, pdata->idx, "length", buf, strlen(buf) + 1, IIO_ATTR_TYPE_BUFFER); if (ret < 0) return (int) ret; @@ -302,7 +302,7 @@ local_set_watermark(const struct iio_buffer_pdata *pdata, size_t nb_samples) iio_snprintf(buf, sizeof(buf), "%zu", nb_samples); - ret = local_write_dev_attr(pdata->dev, pdata->params->idx, "watermark", + ret = local_write_dev_attr(pdata->dev, pdata->idx, "watermark", buf, strlen(buf) + 1, IIO_ATTR_TYPE_BUFFER); if (ret < 0 && ret != -ENOENT && ret != -EACCES) return (int) ret; @@ -314,7 +314,7 @@ static int local_do_enable_buffer(struct iio_buffer_pdata *pdata, bool enable) { int ret; - ret = (int) local_write_dev_attr(pdata->dev, pdata->params->idx, "enable", + ret = (int) local_write_dev_attr(pdata->dev, pdata->idx, "enable", enable ? "1" : "0", 2, IIO_ATTR_TYPE_BUFFER); if (ret < 0) @@ -1395,7 +1395,7 @@ local_read_attr(const struct iio_attr *attr, char *dst, size_t len) unsigned int buf_id = 0; if (type == IIO_ATTR_TYPE_BUFFER) - buf_id = attr->iio.buf->params.idx; + buf_id = attr->iio.buf->idx; return local_read_dev_attr(dev, buf_id, filename, dst, len, type); } @@ -1409,7 +1409,7 @@ local_write_attr(const struct iio_attr *attr, const char *src, size_t len) unsigned int buf_id = 0; if (type == IIO_ATTR_TYPE_BUFFER) - buf_id = attr->iio.buf->params.idx; + buf_id = attr->iio.buf->idx; return local_write_dev_attr(dev, buf_id, filename, src, len, type); } @@ -1478,8 +1478,7 @@ static void local_close_fd(const struct iio_device *dev, int fd) } static struct iio_buffer_pdata * -local_create_buffer(const struct iio_device *dev, - struct iio_buffer_params *params, +local_create_buffer(const struct iio_device *dev, unsigned int idx, struct iio_channels_mask *mask) { struct iio_buffer_pdata *pdata; @@ -1506,15 +1505,15 @@ local_create_buffer(const struct iio_device *dev, goto err_free_mmap_pdata; } - err = local_open_fd(dev, false, params->idx); + err = local_open_fd(dev, false, idx); if (err < 0) goto err_close_eventfd; fd = err; - pdata->params = params; pdata->cancel_fd = cancel_fd; pdata->fd = fd; + pdata->idx = idx; /* Disable buffer */ err = local_do_enable_buffer(pdata, false); @@ -1525,7 +1524,7 @@ local_create_buffer(const struct iio_device *dev, for (i = 0; i < dev->nb_channels; i++) { chn = dev->channels[i]; if (chn->index >= 0) { - err = channel_write_state(chn, params->idx, false); + err = channel_write_state(chn, idx, false); if (err < 0) goto err_close; } @@ -1535,7 +1534,7 @@ local_create_buffer(const struct iio_device *dev, for (i = 0; i < dev->nb_channels; i++) { chn = dev->channels[i]; if (chn->index >= 0 && iio_channel_is_enabled(chn, mask)) { - err = channel_write_state(chn, params->idx, true); + err = channel_write_state(chn, idx, true); if (err < 0) goto err_close; } @@ -1546,7 +1545,7 @@ local_create_buffer(const struct iio_device *dev, for (i = 0; i < dev->nb_channels; i++) { chn = dev->channels[i]; if (chn->index >= 0) { - err = channel_read_state(chn, params->idx); + err = channel_read_state(chn, idx); if (err < 0) goto err_close; diff --git a/local.h b/local.h index 8caba0926..547eb9e42 100644 --- a/local.h +++ b/local.h @@ -15,14 +15,13 @@ struct iio_buffer_impl_pdata; struct iio_block_impl_pdata; struct iio_device; -struct iio_buffer_params; struct timespec; struct iio_buffer_pdata { const struct iio_device *dev; struct iio_buffer_impl_pdata *pdata; int fd, cancel_fd; - struct iio_buffer_params *params; + unsigned int idx; bool dmabuf_supported; bool mmap_supported; size_t size; diff --git a/man/iio_rwdev.1.in b/man/iio_rwdev.1.in index afcb3a50a..4001a899b 100644 --- a/man/iio_rwdev.1.in +++ b/man/iio_rwdev.1.in @@ -60,9 +60,6 @@ Use cyclic buffer mode. .TP .B \-B \-\-benchmark Benchmark throughput. Statistics will be printed on the standard input. -.TP -.B \-C, \-\-cma -Use CMA-Linux allocator for DMA buffer. ##COMMON_OPTION_START## ##COMMON_OPTION_STOP## .SH RETURN VALUE diff --git a/man/iio_stresstest.1.in b/man/iio_stresstest.1.in index d590f8795..547383199 100644 --- a/man/iio_stresstest.1.in +++ b/man/iio_stresstest.1.in @@ -55,9 +55,6 @@ Time to wait (in seconds) before stopping all threads .B \-t, \-\-threads Number of threads to use .TP -.B \-C, \-\-cma -Use CMA-Linux allocator for DMA buffer -.TP .B \-v, \-\-verbose Increase verbosity (-vv and -vvv for more) diff --git a/network.c b/network.c index 8248bb757..1a2950c62 100644 --- a/network.c +++ b/network.c @@ -441,12 +441,11 @@ static int network_set_timeout(struct iio_context *ctx, unsigned int timeout) } static struct iio_buffer_pdata * -network_create_buffer(const struct iio_device *dev, - struct iio_buffer_params *buffer_params, +network_create_buffer(const struct iio_device *dev, unsigned int idx, struct iio_channels_mask *mask) { const struct iio_context *ctx = iio_device_get_context(dev); - const struct iio_context_params *ctx_params = iio_context_get_params(ctx); + const struct iio_context_params *params = iio_context_get_params(ctx); struct iio_context_pdata *pdata = iio_context_get_pdata(ctx); struct iio_buffer_pdata *buf; int ret; @@ -455,7 +454,7 @@ network_create_buffer(const struct iio_device *dev, if (!buf) return iio_ptr(-ENOMEM); - buf->io_ctx.params = ctx_params; + buf->io_ctx.params = params; buf->io_ctx.ctx_pdata = pdata; buf->dev = dev; @@ -468,7 +467,7 @@ network_create_buffer(const struct iio_device *dev, buf->pdata = iiod_client_create_buffer(buf->iiod_client, pdata->iiod_client, - dev, buffer_params, mask); + dev, idx, mask); ret = iio_err(buf->pdata); if (ret) { dev_perror(dev, ret, "Unable to create buffer"); diff --git a/serial.c b/serial.c index bda81e867..e122997a9 100644 --- a/serial.c +++ b/serial.c @@ -226,8 +226,7 @@ static int serial_set_trigger(const struct iio_device *dev, } static struct iio_buffer_pdata * -serial_create_buffer(const struct iio_device *dev, - struct iio_buffer_params *params, +serial_create_buffer(const struct iio_device *dev, unsigned int idx, struct iio_channels_mask *mask) { const struct iio_context *ctx = iio_device_get_context(dev); @@ -241,7 +240,7 @@ serial_create_buffer(const struct iio_device *dev, buf->pdata = iiod_client_create_buffer(pdata->iiod_client, pdata->iiod_client, - dev, params, mask); + dev, idx, mask); ret = iio_err(buf->pdata); if (ret) { dev_perror(dev, ret, "Unable to create buffer"); diff --git a/usb.c b/usb.c index 506a26c17..1c4438f2d 100644 --- a/usb.c +++ b/usb.c @@ -403,12 +403,11 @@ usb_writebuf(struct iio_buffer_pdata *pdata, const void *src, size_t len) } static struct iio_buffer_pdata * -usb_create_buffer(const struct iio_device *dev, - struct iio_buffer_params *params, +usb_create_buffer(const struct iio_device *dev, unsigned int idx, struct iio_channels_mask *mask) { const struct iio_context *ctx = iio_device_get_context(dev); - const struct iio_context_params *ctx_params = iio_context_get_params(ctx); + const struct iio_context_params *params = iio_context_get_params(ctx); struct iio_context_pdata *ctx_pdata = iio_context_get_pdata(ctx); struct iio_buffer_pdata *buf; int ret; @@ -437,7 +436,7 @@ usb_create_buffer(const struct iio_device *dev, goto err_free_ep; } - buf->io_ctx.iiod_client = iiod_client_new(ctx_params, &buf->io_ctx, + buf->io_ctx.iiod_client = iiod_client_new(params, &buf->io_ctx, &usb_iiod_client_ops); ret = iio_err(buf->io_ctx.iiod_client); if (ret) { @@ -447,7 +446,7 @@ usb_create_buffer(const struct iio_device *dev, buf->pdata = iiod_client_create_buffer(buf->io_ctx.iiod_client, ctx_pdata->io_ctx.iiod_client, - dev, params, mask); + dev, idx, mask); ret = iio_err(buf->pdata); if (ret) { dev_perror(dev, ret, "Unable to create iiod-client buffer"); diff --git a/utils/iio_attr.c b/utils/iio_attr.c index 8ed0a523d..222471e5a 100644 --- a/utils/iio_attr.c +++ b/utils/iio_attr.c @@ -306,7 +306,7 @@ int main(int argc, char **argv) * so if there is one, we skip that argument during getopt processing * look for "-" followed by a number. */ - if (strnlen(argv[argc - 1], 2) >= 2 && argv[argc - 1][0] == '-' && + if (strnlen(argv[argc - 1], 2) >= 2 && argv[argc - 1][0] == '-' && (argv[argc - 1][1] >= '0' && argv[argc - 1][1] <= '9')) { argd--; } @@ -780,7 +780,7 @@ int main(int argc, char **argv) } if (mask) - buffer = iio_device_create_buffer(dev, NULL, mask); + buffer = iio_device_create_buffer(dev, 0, mask); if (mask && !iio_err(buffer)) { nb_attrs = iio_buffer_get_attrs_count(buffer); diff --git a/utils/iio_info.c b/utils/iio_info.c index 20914ee24..d46102d2b 100644 --- a/utils/iio_info.c +++ b/utils/iio_info.c @@ -368,7 +368,7 @@ int main(int argc, char **argv) } if (mask) - buffer = iio_device_create_buffer(dev, NULL, mask); + buffer = iio_device_create_buffer(dev, 0, mask); if (mask && !iio_err(buffer)) { nb_attrs = iio_buffer_get_attrs_count(buffer); if (nb_attrs) diff --git a/utils/iio_rwdev.c b/utils/iio_rwdev.c index aa17a1d11..b21062c84 100644 --- a/utils/iio_rwdev.c +++ b/utils/iio_rwdev.c @@ -41,13 +41,12 @@ static const struct option options[] = { {"write", no_argument, 0, 'w'}, {"cyclic", no_argument, 0, 'c'}, {"benchmark", no_argument, 0, 'B'}, - {"cma", no_argument, 0, 'C'}, {0, 0, 0, 0}, }; static const char *options_descriptions[] = { "[-t ] [-b ]" - "[-s ] [ ...] [-C]", + "[-s ] [ ...]", "Use the specified trigger.", "Set the trigger to the specified rate (Hz). Default is 100 Hz.", "Size of the transfer buffer. Default is 256.", @@ -57,7 +56,6 @@ static const char *options_descriptions[] = { "Use cyclic buffer mode.", "Benchmark throughput." "\n\t\t\tStatistics will be printed on the standard input.", - "Use CMA-Linux allocator for DMA buffer." }; static struct iio_context *ctx; @@ -207,7 +205,7 @@ static ssize_t transfer_sample(const struct iio_channel *chn, return (ssize_t) nb; } -#define MY_OPTS "t:b:s:T:r:wcBC" +#define MY_OPTS "t:b:s:T:r:wcB" int main(int argc, char **argv) { @@ -225,7 +223,6 @@ int main(int argc, char **argv) struct iio_stream *stream; const struct iio_block *block; struct iio_channels_mask *mask; - struct iio_buffer_params buffer_params = {0}; const struct iio_channels_mask *hw_mask; const struct iio_attr *uri, *attr; struct option *opts; @@ -297,9 +294,6 @@ int main(int argc, char **argv) case 'w': is_write = true; break; - case 'C': - buffer_params.dma_allocator = IIO_DMA_ALLOCATOR_CMA_LINUX; - break; case '?': printf("Unknown argument '%c'\n", c); goto err_free_ctx; @@ -443,7 +437,7 @@ int main(int argc, char **argv) goto err_free_mask; } - buffer = iio_device_create_buffer(dev, &buffer_params, mask); + buffer = iio_device_create_buffer(dev, 0, mask); ret = iio_err(buffer); if (ret) { dev_perror(dev, ret, "Unable to allocate buffer"); diff --git a/utils/iio_stresstest.c b/utils/iio_stresstest.c index 2a2c4d8a8..d627c3be7 100644 --- a/utils/iio_stresstest.c +++ b/utils/iio_stresstest.c @@ -102,21 +102,18 @@ static const struct option options[] = { {"buffer-size", required_argument, 0, 'b'}, {"duration", required_argument, 0, 'd'}, {"threads", required_argument, 0, 't'}, - {"cma", no_argument, 0, 'C'}, {"verbose", no_argument, 0, 'v'}, {0, 0, 0, 0}, }; static const char *options_descriptions[] = { - ("[-u ] [-b ] [-d ]" - "[-t ] [-C ]" + ("[-u ] [-b ] [-d ] [-t ]" " [ ...]"), "Show this help and quit.", "Use the context at the provided URI.", "Size of the capture buffer. Default is 256.", "Time to wait (in s) between stopping all threads", "Number of Threads", - "Use CMA-Linux allocator for DMA buffer.", "Increase verbosity (-vv and -vvv for more)", }; @@ -227,7 +224,6 @@ static void *client_thread(void *data) const struct iio_device *dev; const struct iio_channel *ch; struct iio_channels_mask *mask; - struct iio_buffer_params buffer_params = {0}; struct timeval start, end; int id = -1, stamp, r_errno; ssize_t ret; @@ -312,7 +308,7 @@ static void *client_thread(void *data) i = 0; while (threads_running || i == 0) { info->buffers[id]++; - buffer = iio_device_create_buffer(dev, &buffer_params, mask); + buffer = iio_device_create_buffer(dev, info->buffer_size, mask); ret = iio_err(buffer); if (ret) { struct timespec wait; @@ -400,7 +396,6 @@ int main(int argc, char **argv) struct iio_buffer *buffer; struct iio_context *ctx; struct iio_channel *ch; - struct iio_buffer_params buffer_params = {0}; struct iio_channels_mask *mask; const char *name; int c, pret, option_index, err; @@ -429,7 +424,7 @@ int main(int argc, char **argv) if(!min_samples) min_samples = 128; - while ((c = getopt_long(argc, argv, "hvu:b:t:T:C", + while ((c = getopt_long(argc, argv, "hvu:b:t:T", options, &option_index)) != -1) { switch (c) { case 'h': @@ -457,9 +452,6 @@ int main(int argc, char **argv) info.num_threads = sanitize_clamp("threads", info.argv[info.arg_index], 1, 1024); break; - case 'C': - buffer_params.dma_allocator = IIO_DMA_ALLOCATOR_CMA_LINUX; - break; case 'v': if (!info.verbose) info.arg_index++; @@ -498,7 +490,7 @@ int main(int argc, char **argv) iio_channel_enable(ch, mask); } - buffer = iio_device_create_buffer(dev, &buffer_params, mask); + buffer = iio_device_create_buffer(dev, 0, mask); if (!iio_err(buffer)) { iio_buffer_destroy(buffer);