iio: Add support for describing scan offsets in buffer ops
Hello,
This is a tentative proposal with no code attached. This issue came up while hacking on the mpu6050 driver but it applies to other complex devices and a solution belongs in the IIO core.
One IIO limitation is that while samples can be described through a relatively generic scan_type they must be placed in the output buffer according to an specific iio alignment algorithm. For example if the device has one 16bit channel and one 32bit channel the output needs to have 16bits of padding between them. When this does not match the hardware format the solution is for the driver to unpack the hardware samples and repack them in the iio format.
I propose that we add a new function in iio_buffer_setup_ops which looks like this:
int (*get_scan_offsets)(struct iio_dev *indio_dev,
off_t *scan_offsets, size_t *sample_bytes);
This would be called when enabling a buffer to fetch the offset in the sample for each channel (by scan_index) based on the currently configured scan mask. Then the iio core would then handle rearranging sample bytes as expected by the buffer consumer. Driver implementations could look something like this:
off_t pos = 0;
if (scan_mask & (1 << SCAN_INDEX_TEMP))) {
scan_offsets[SCAN_INDEX_TEMP] = pos++;
}
/* No 2-bytes alignment here! */
if (scan_mask & SCAN_MASK_ACCEL_ANY) {
scan_offsets[SCAN_INDEX_ACCEL_X] = pos + 0;
scan_offsets[SCAN_INDEX_ACCEL_Y] = pos + 2;
scan_offsets[SCAN_INDEX_ACCEL_Z] = pos + 4;
pos += 6;
}*sample_bytes = pos;
This could be implemented as an extension to the current buffer demuxing support which currently only deals with differences in scan_masks. This mechanism would very nicely deal with devices where it is not possible to select X/Y/Z individually because the iio core would just ignore the gap in offsets.
This can even be exposed to userspace in a compatible manner. User would do something like:
ioctl(iio_fd, IIO_USER_HANDLES_SCAN_OFFSETS, 1);
ioctl(iio_fd, IIO_GET_SCAN_OFFSETS, &scan_offsets, &sample_bytes);When the consumer is marked as aware of scan offsets this way the iio core can skip demuxing for increased performance. The IIO core can implement IIO_GET_SCAN_OFFSETS itself when the driver has no custom implementation. An application could rely on IIO_GET_SCAN_OFFSETS for all devices as long as it's acceptable to ignore old kernels.
This would be particularly useful if IIO sample buffers are memory-mapped eventually. I think that this extension would be incrementally useful to that effort.
Signature · 2 lines
Regards, Leonard
Jonathan Cameron
maintainerQuoted 5 lines · Crestez Dan Leonard
Hello,
This is a tentative proposal with no code attached. This issue came up while hacking on the mpu6050 driver but it applies to other complex devices and a solution belongs in the IIO core.
I'm not so convinced (yet). This is actually a fairly unusual case and the 'byte mangling' can often be handled in a relatively fixed way in a driver whereas it can be more complex in the core.
Interesting idea though.. Effectively you are hand specifying the demux tables that we generate and making them more flexible.
Quoted 8 lines
One IIO limitation is that while samples can be described through a relatively generic
scan_typethey must be placed in the output buffer according to an specific iio alignment algorithm. For example if the device has one 16bit channel and one 32bit channel the output needs to have 16bits of padding between them. When this does not match the hardware format the solution is for the driver to unpack the hardware samples and repack them in the iio format.
It's pretty much got to happen somewhere to get the data into a form that can be used at speed. Remember we are doing this on the back of expensive bus transactions (a lot of the time).
Quoted 25 lines
I propose that we add a new function in
iio_buffer_setup_opswhich looks like this:int (*get_scan_offsets)(struct
iio_dev*indio_dev,off_t *scan_offsets, size_t *sample_bytes);This would be called when enabling a buffer to fetch the offset in the sample for each channel (by
scan_index) based on the currently configured scan mask. Then the iio core would then handle rearranging sample bytes as expected by the buffer consumer. Driver implementations could look something like this:
off_tpos = 0;if (scan_mask & (1 << SCAN_INDEX_TEMP))) { scan_offsets[SCAN_INDEX_TEMP] = pos++; } /* No 2-bytes alignment here! */ if (scan_mask & SCAN_MASK_ACCEL_ANY) { scan_offsets[SCAN_INDEX_ACCEL_X] = pos + 0; scan_offsets[SCAN_INDEX_ACCEL_Y] = pos + 2; scan_offsets[SCAN_INDEX_ACCEL_Z] = pos + 4; pos += 6; }
Quoted 1 line
*sample_bytes= pos;
Sure - this side is straight forward enough. It's the core complexity that makes me wonder if this is worthwhile. Btw if this is worth doing then we should really be looking at non byte aligned packed records as well (just to make it really hideous!)
The killer in here is endian requirements. If the core is repacking data it will need to understand these completely. Two options exist, either the core needs to 'edit' the shift provided by the driver, or it needs to do endian dependent data realignment.
Take a typical 3 byte unaligned packed record being expanded to a 4 byte aligned record. I think the easy cases are:
ABC -> 0ABC
CBA -> CBA0
so endian dependent shifts.
Whereas a repack in the driver should inherently know what the right combination should be.
I'm not saying it couldn't be done in the core of course, merely that it is more complex that it initially looks.
I've already suggested we might look at doing a few 'special cases' to relax the power of two requirement - but I'd do that off the back of the current description rather than introducing another. It does have the same complexity issues though so until we have code I'm unconvinced it is worth it.
Quoted 10 lines
This could be implemented as an extension to the current buffer demuxing support which currently only deals with differences in
scan_masks. This mechanism would very nicely deal with devices where it is not possible to select X/Y/Z individually because the iio core would just ignore the gap in offsets.This can even be exposed to userspace in a compatible manner. User would do something like:
Quoted 8 lines
ioctl(iio_fd, IIO_USER_HANDLES_SCAN_OFFSETS, 1); ioctl(iio_fd, IIO_GET_SCAN_OFFSETS, &scan_offsets, &sample_bytes);When the consumer is marked as aware of scan offsets this way the iio core can skip demuxing for increased performance. The IIO core can implement
IIO_GET_SCAN_OFFSETSitself when the driver has no custom implementation. An application could rely onIIO_GET_SCAN_OFFSETSfor all devices as long as it's acceptable to ignore old kernels.
Be careful here. The demux wasn't actually written in the first place for this usage at all (it was an added bonus)
It's about sending different streams
of data to different consumers. That is definitely not compatible with passing this stuff up to user space as it's downright complex to do. Making in kernel consumers aware of this more complex handling is going to be fiddly. Again could be done, but is it worth it? I suppose we could make the demux aware of what it is sending to, but that adds more complexity.
Quoted 4 lines
This would be particularly useful if IIO sample buffers are memory-mapped eventually. I think that this extension would be incrementally useful to that effort.
Perhaps. I'm interested to hear other views on this suggestion, but right now I'm not convinced. I'd argue that we want clean data presentations to userspace and that the restrictions as they currently stand are not really that burdensome on the data.
The exception is dma buffers - in those cases it really might be the case that we want to allow more complex alignment.
Right now there is no option to have multiple consumers for a dma buffer and I'm not sure there ever will be. However, they don't fall into categories where we use the multiconsumer stuff now (which is mostly about SoC ADCs with lots of different types of channel for things like thermal / battery monitoring - there are other issues there between polled and pushed data flows, but that is a whole different issue!)
Hence for DMA buffers there is no need to enforce the power of two byte alignment requirements though, the first time this happens we should think carefully about whether we 'want' to allow the additional flexibility.
Jonathan
Quoted 26 lines · Jonathan Cameron
Quoted 24 lines · Crestez Dan Leonard
I propose that we add a new function in
iio_buffer_setup_opswhich looks like this:int (*get_scan_offsets)(struct
iio_dev*indio_dev,off_t *scan_offsets, size_t *sample_bytes);This would be called when enabling a buffer to fetch the offset in the sample for each channel (by
scan_index) based on the currently configured scan mask. Then the iio core would then handle rearranging sample bytes as expected by the buffer consumer. Driver implementations could look something like this:
off_tpos = 0;if (scan_mask & (1 << SCAN_INDEX_TEMP))) { scan_offsets[SCAN_INDEX_TEMP] = pos++; } /* No 2-bytes alignment here! */ if (scan_mask & SCAN_MASK_ACCEL_ANY) { scan_offsets[SCAN_INDEX_ACCEL_X] = pos + 0; scan_offsets[SCAN_INDEX_ACCEL_Y] = pos + 2; scan_offsets[SCAN_INDEX_ACCEL_Z] = pos + 4; pos += 6; }Quoted 1 line
*sample_bytes= pos;
Quoted 4 lines
Sure - this side is straight forward enough. It's the core complexity that makes me wonder if this is worthwhile. Btw if this is worth doing then we should really be looking at non byte aligned packed records as well (just to make it really hideous!)
You could have a bunch of channels with different realbits/shift and the same offset.
Quoted 5 lines
The killer in here is endian requirements. If the core is repacking data it will need to understand these completely. Two options exist, either the core needs to 'edit' the shift provided by the driver, or it needs to do endian dependent data realignment.
Quoted 7 lines
Take a typical 3 byte unaligned packed record being expanded to a 4 byte aligned record. I think the easy cases are:
ABC -> 0ABC
CBA -> CBA0
so endian dependent shifts.
I'm not sure how unaligned 24bit channels would be handled. Maybe it could be done storagebits=32, realbits=24, shift=8 or 0 and offsets that are multiples of 3?
I guess it would have to know about endianness.
Quoted 4 lines
Quoted 3 lines
This would be particularly useful if IIO sample buffers are memory-mapped eventually. I think that this extension would be incrementally useful to that effort.
Quoted 8 lines
Perhaps. I'm interested to hear other views on this suggestion, but right now I'm not convinced. I'd argue that we want clean data presentations to userspace and that the restrictions as they currently stand are not really that burdensome on the data.
The exception is dma buffers - in those cases it really might be the case that we want to allow more complex alignment.
The point of exposing this through the iio core to userspace is that it could be used to support this kind of devices. It's not worth exposing as ABI unless it can support a lot of stuff at once.
It might make more sense to just provide some helpers for drivers to do their own easy reformatting.
Quoted 34 lines · Crestez Dan Leonard
Quoted 2 lines · Jonathan Cameron
Quoted 1 line · Crestez Dan Leonard
I propose that we add a new function in
iio_buffer_setup_opswhichlooks
Quoted 7 lines
Quoted 7 lines
like this:
int (*get_scan_offsets)(struct
iio_dev*indio_dev,off_t *scan_offsets, size_t *sample_bytes);This would be called when enabling a buffer to fetch the offset in
the
Quoted 2 lines
Quoted 2 lines
sample for each channel (by
scan_index) based on the currently configured scan mask. Then the iio core would then handlerearranging
Quoted 1 line
Quoted 1 line
sample bytes as expected by the buffer consumer. Driver
implementations
Quoted 14 lines
Quoted 13 lines
could look something like this:
off_tpos = 0;if (scan_mask & (1 << SCAN_INDEX_TEMP))) { scan_offsets[SCAN_INDEX_TEMP] = pos++; } /* No 2-bytes alignment here! */ if (scan_mask & SCAN_MASK_ACCEL_ANY) { scan_offsets[SCAN_INDEX_ACCEL_X] = pos + 0; scan_offsets[SCAN_INDEX_ACCEL_Y] = pos + 2; scan_offsets[SCAN_INDEX_ACCEL_Z] = pos + 4; pos += 6; }Quoted 1 line
*sample_bytes= pos;Quoted 1 line
Sure - this side is straight forward enough. It's the core
complexity
Quoted 1 line
that makes me wonder if this is worthwhile. Btw if this is worth
Quoted 8 lines
doing
Quoted 1 line
then we should really be looking at non byte aligned packed records
as
Quoted 1 line
well (just to make it really hideous!)
You could have a bunch of channels with different realbits/shift and the
same offset.
Good point.
Quoted 36 lines
Quoted 2 lines
The killer in here is endian requirements. If the core is repacking
data
Quoted 1 line
it will need to understand these completely. Two options exist,
either
Quoted 1 line
the core needs to 'edit' the shift provided by the driver, or it
needs
Quoted 9 lines
to do endian dependent data realignment.
Take a typical 3 byte unaligned packed record being expanded to a 4 byte aligned record. I think the easy cases are:
ABC -> 0ABC
CBA -> CBA0
so endian dependent shifts.I'm not sure how unaligned 24bit channels would be handled. Maybe it could be done storagebits=32, realbits=24, shift=8 or 0 and offsets that
are multiples of 3?I guess it would have to know about endianness.
Quoted 7 lines
Quoted 3 lines
This would be particularly useful if IIO sample buffers are memory-mapped eventually. I think that this extension would be incrementally useful to that effort.
Perhaps. I'm interested to hear other views on this suggestion, but right now I'm not convinced. I'd argue that we want clean data presentations to userspace and that the restrictions as they
currently
Quoted 5 lines
stand are not really that burdensome on the data.
The exception is dma buffers - in those cases it really might be the case that we want to allow more complex alignment.
Quoted 6 lines
The point of exposing this through the iio core to userspace is that it could be used to support this kind of devices. It's not worth exposing as ABI unless it can support a lot of stuff at once.
It might make more sense to just provide some helpers for drivers to do their own easy reformatting.
Certainly seems like that to me. Nothing stops us looking again at this in the future.
J
Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse my brevity.