All of lore.kernel.org
 help / color / mirror / Atom feed
* Let's design the next-gen libiio!
@ 2019-12-09 15:26 Paul Cercueil
       [not found] ` <c97d848ec9898eb46b8adf5bda87ccb4fc8e2e2a.camel@analog.com>
  2019-12-30 18:23 ` Jonathan Cameron
  0 siblings, 2 replies; 6+ messages in thread
From: Paul Cercueil @ 2019-12-09 15:26 UTC (permalink / raw)
  To: IIO, Robin Getz, Michael Hennerich, Travis Collins,
	Dragos Bogdan, Dan Nechita, Lars-Peter Clausen, Romain Roffé,
	Rémi Lefèvre, Parrot developers, Doug Geiger,
	Matt Fornero, Ousman Sadiq, Neil MacEwen, Kishor Akkala,
	Bhanu Medasani, Jerome Chevalier, Andrea Galbusera,
	Lucas Magasweran, Matej Kenda, Michael Heimpold,
	Andreas Brauchli, Adrian Freihofer, David Frey,
	Geert Uytterhoeven, Adrian Freihofer, Gwendal Grignou, JaredD,
	Jeremy Trimble, Johnny Vestergaard, Jonas Hansen, Jorik Jonker,
	Julien Malik, Marc Titinger, Markus Gnadl, Morten Fyhn Amundsen,
	Nicholas Pillitteri, Pierre-Jean Texier

Hello beautiful people,

First of all, apologies for sending such a long email. Double apologies 
if
you're caught in the email chain and you don't care about the topic. 
Just
don't click "reply all" when you send me an angry response, as the 
thread will
be publicly logged.

The reason for you receiving this, is that you've been involved with 
libiio
(https://github.com/analogdevicesinc/libiio) either directly or 
indirectly,
or subscribed to the IIO kernel mailing list, or have shown interest in 
the
project, or have an homonym who does.

About five years ago libiio was born, as an easy-to-use library for
interfacing to Linux' Industrial Input/Output (IIO) kernel subsystem, 
either
with devices preset on the host platform, or on a remote target 
platform.
I think we did a good job, as the API was never broken since its first 
release,
and the praise/hate ratio we received was very encouraging. We've seen 
people
using it in all kinds of applications, from car infotainment to space 
research,
from drones to software radio.

It's not perfect, though, and its current design has room for 
improvements,
both inside and outside the library. However, we've hit a point where 
such
improvements would require a redesign of the library and kernel bits, 
and as a
consequence, a breakage of the API. It's time for the next-gen libiio, 
and a
overhaul of the whole IIO stack, really.

Your mission, should you choose to accept it, is to feed me with ideas,
concerns, comments about what you think libiio was lacking or just not 
doing
right. We want to open the possibility for all interested parties to 
help
sketch the future library.

I have compiled below a list of changes that we think should be done, 
comments
are very welcome. Note that emails in HTML form will probably be 
bounced back
by the IIO mailing list, so please write responses in plain text.

Thank you for your time.

Kind regards,
Paul Cercueil

------
Kernel
------

* Support for buffer metadata
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Support tagging the buffers with any relevant information. Either 
from the IIO
  core for general accounting (e.g. timestamp) or from the driver for
  hardware-facing code (e.g. buffer underflow).
  Metadata would be attached to a specific sample in the buffer 
(metadata that
  applies to the whole buffer can be attached to the first sample). 
Several
  entries could be attached to the same sample. The format would be a 
simple
  key="value", I don't think we need anything more complex than that.
  For DACs, it should be possible to set metadata from userspace. The 
drivers
  would then interpret the metadata tags if they need to.

* Facility to detect overflow/underflow
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  There should be a way to detect overflows (for ADCs) and underflows 
(for
  DACs), if the hardware supports it, and report them to userspace 
(through a
  IIO event, I suppose). This is something that could be done by the 
drivers,
  but maybe it would make sense to have this functionality in the IIO 
common
  code?

* Delayed attribute write / Command queues
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  We need a mechanism that allows us to change the value of an 
attribute at a
  very specific time (or sample number) after a capture or upload is 
started;
  some kind of script mechanism, or 'command list' analog to the 
display lists
  used in old GPUs. This would be used for instance in software 
applications
  doing time-divison duplexing (TDD).

* Better high-speed buffer mechanism
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  The current buffer API is fine for low-speed devices, but we're 
dealing with
  ADCs and DACs of the GB/s class. ADI already contributed an improved 
(faster)
  buffer mechanism, but which is incomplete (no support for DACs), 
doesn't
  integrate very well in the ecosystem, and is somewhat redundant with 
the old
  one.

  The idea would be to deprecate this API and propose an alternative 
that
  makes use of current technology, like dmabuf. The concept would stay 
the
  same, each IIO device has a pool of DMA buffers, and userspace can 
queue
  and dequeue buffers.

  The rationale behind this change, is that with the current two APIs 
it is not
  possible to move data between IIO devices and a network or USB card 
without
  having the CPU copy the data. This is an important problem, as 
high-speed
  ADCs and DACs are generally connected to FPGAs running Linux on a 
softcore,
  which stream their data to a workstation for further processing. With 
the
  new API, the userspace software would simply obtain a pointer to a 
dmabuf
  from the IIO interface, and simply pass it to the network card (this 
means
  the network stack and USB stack would also need to support dmabuf).

  An alternative would be to keep the current file-based buffer and
  buffer-queue-based APIs, but enhance the former one with support for
  splicing (with splice()/vmsplice()). This might arguably be easier to 
do,
  since the network stack already supports it. The problem with 
splicing is
  that the kernel swaps each data page with a fresh zeroed page in 
order to
  avoid leaking kernel memory. To be truely zero-copy, this requires 
the page
  cleaning mechanism to be offloaded to e.g. DMA, otherwise the process 
isn't
  entirely CPU-free.

* Parsable attribute names
  ~~~~~~~~~~~~~~~~~~~~~~~~

  IIO attributes follow a certain formatting that does not make it 
possible to
  reconstruct the devices/channels/attributes tree in userspace. The 
channel
  attributes are formatted as:
  <direction>_<type><id>_<modifier>_<extended-name>_<attribute-name>
  The problem is that <extended-name>, <modifier> and <attribute-name> 
can
  contain underscores, which makes it impossible to parse. For instance,
  with an attribute named "in_voltage0_high_impedence_line_enable":
  Is the extended name "high_impedence_line" and the attribute name 
"enable",
  or is the extended name "high_impedence" and the attribute name 
"line_enable"?

  Since the sysfs attributes is ABI, the solution could be to have a 
separate
  sysfs file, for instance <direction>_<type><id>_extended_name, that 
would
  contain the extended name of the channel. This should be enough for 
the IIO
  sysfs interface to be machine-readable.

-------
Libiio2
-------

* stdio redirection
  ~~~~~~~~~~~~~~~~~

  Right now libiio prints its debug information unconditionally to
  stdout/stderr, it should be modified to be able to output its log to 
any
  valid file descriptor. While that looks simple on paper, it must be 
set up
  before a library context is created, since the context creation 
itself may
  print debug information. This require the context allocation to be 
separated
  from its initialization, so a break of API.

* Separate allocation from initialization
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  As stated above, functions to alloc/destroy and init/deinit the 
various IIO
  structures should be separate; this would allow e.g. to set some 
parameters
  to a iio_context before the context creation happens, for instance 
where to
  redirect the debug output.

* Modular backends
  ~~~~~~~~~~~~~~~~

  Right now the backends of libiio are tightly coupled to the core. It 
would
  be great if the users could install only the backends they're 
interested in.
  Of course, backends could still be backed into the core library, and 
that
  would stay the default behaviour for non-Linux platforms.

  This requires two things:
  - The libiio backends must be able to be updated independently of the 
main
 library, therefore they should only depend on the top-level API of 
libiio.
 Apart from a few exceptions here and there, this is already mostly the
 case.
  - There needs to be a facility to load external backends based on the
 backend name. Thanksfully with URIs this becomes easy: creating a 
context
 from the URI "foo:" would result in the backend module "foo" loaded 
from
 the disk, if not already baked in.

* Event support
  ~~~~~~~~~~~~~

  The IIO subsystem has support for events. This allows the userspace 
to get
  notified for instance when a temperature gets over or under a 
threshold.
  Right now, libiio cannot easily support events, as the client/server
  protocol of the network backend doesn't really allow it. Therefore, 
the new
  libiio2 library should be designed from the ground up with support for
  events, and the API should offer a way to register a callback that 
would be
  called when a IIO event occurs.

* Context change detection
  ~~~~~~~~~~~~~~~~~~~~~~~~

  When a device is added, removed or the context becomes unavailable 
(e.g. the
  USB cable was unplugged), there should be a built-in mechanism to 
notify the
  applications using libiio2, maybe using the same mechanism as for IIO 
events.

  The same would apply on the local backend, if for instance a new 
device
  appears, the library should be able to pick it up and report the new 
device
  to the application.

* Asynchronous network communication
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  The network communication between libiio and IIO is sub-par, because 
it uses
  a synchronous request-response protocol. This causes the throughput 
to max
  out way below the theorical maximum throughput of Gigabit Ethernet.
  The communication protocol should be modified in a way that fully 
maximizes
  the throughput.

  The old communication protocol should still be available and used by 
default
  unless the two parties agree to use the new protocol. This ensures 
that
  TinyIIOD (the microcontroller variant of IIOD, the server that 
communicates
  with the network backend of libiio) can still work with the network 
backend of
  libiio2. Alternatively, TinyIIOD could be updated to the new network 
protocol.
  That way, the old network protocol wouldn't have to stick around.

  To implement the asynchronous network communication, we could have a 
look at
  ZeroMQ (https://zeromq.org) which seems to be designed for that 
particular
  task, and is available under a LGPLv3 license. It is however 
uncertain how
  that would work on the IIOD side (because of the zero-copy 
requirement - see
  below).

  Additionally, the network backend should part ways with its current
  ASCII-based protocol. This made sense when libiio was first created, 
but it
  requires quite a complex parser on the server side that could go away 
by
  resorting to a more classic protocol.

* Zero-copy
  ~~~~~~~~~

  Apart from supporting the new network protocol, libiio should provide 
a way
  to stream data between IIO devices and standard file descriptors or 
sockets
  without having the CPU copy the data.

  If a dmabuf-based IIO kernel interface is used, we need a way to send 
a
  dmabuf to a socket, and I'm not sure that this is currently possible.
  But as dmabuf are internally just scatterlists, and the sockets 
support
  splice(), that should be somewhat doable.

  To complicate things, IIOD (the network server) must be able to 
stream the
  same data to more than one client at a time, unless we decide that 
this is
  no more a requirement. This means that one single dmabuf would be 
submitted
  to more than one socket.

  Streaming data to multiple clients using zero-copy techniques in IIOD 
also
  implies that the data cannot be modified, which means that the server 
cannot
  do the demuxing, and this task is devoted to the clients; so the 
(currently
  optional) server-side demuxing option would be removed.

* USB3
  ~~~~

  Just like the network, the USB backend should be updated to be able 
to reach
  out the maximum throughput offered by USB3.

  The principal problem with USB is the short number of endpoints, 
which limits
  the functionality, as it may not be possible to stream data from 
different
  devices at the same time. Right now, a pair of endpoints is reserved 
for
  generic commands (read attributes, open/close IIO device, etc.), and 
one pair
  is reserved per IIO device streaming data.

  There are several possibilities:
  - the USB backend could multiplex accesses into one single pair of
 endpoints, which basically do in software what USB controllers do in
 hardware;
  - Rework the communication protocol so that only one endpoint is 
needed per
 streaming device instead of two;
  - Negate the problem, and consider it okay that the number of USB 
endpoints
 is a limiting factor.

* PCIe backend
  ~~~~~~~~~~~~

  There is a need for a backend to support the PCIe cards populated with
  various chips and a FPGA with a softcore running Linux. The 
communication
  between the remote OS and the host OS would be something similar to 
Xillybus.

* Command queues
  ~~~~~~~~~~~~~~

  The libiio2 API bits to use the "delayed attribute write / command 
queue"
  feature of the kernel. A command queue would contain several commands 
(e.g.
  submit buffer, change a parameter, submit another buffer), that would 
be
  built in the upper layer of the library using a specific API, and then
  performed atomically on the remote device.

* Buffer overhaul
  ~~~~~~~~~~~~~~~

  Instead of having one iio_buffer, that is either pushed or refilled, 
the idea
  would be to provide an API that allows the client application to 
request,
  enqueue or dequeue the buffers itself. This would offer much greater 
control
  on the buffer management to the application.

* Backwards-compatibility
  ~~~~~~~~~~~~~~~~~~~~~~~

  Backwards compatibility is not a hard requirement, but it should 
still be
  possible to be done by implementing the libiio API on top of libiio2. 
Things
  like buffer refill/push of libiio can be implemented on top of the 
new buffer
  queue system. New features, like buffer metadata support wouldn't be
  backported.

  This should be considered low-priority - we're not yet at the point 
where
  libiio1 is deprecated.



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-01-03 10:46 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-09 15:26 Let's design the next-gen libiio! Paul Cercueil
     [not found] ` <c97d848ec9898eb46b8adf5bda87ccb4fc8e2e2a.camel@analog.com>
2019-12-20 15:28   ` Paul Cercueil
2019-12-30 18:31     ` Jonathan Cameron
2019-12-30 18:23 ` Jonathan Cameron
2020-01-03  2:10   ` Paul Cercueil
2020-01-03 10:46     ` Jonathan Cameron

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.