Re: [PATCH 2/2] iio: accel: Add driver for Murata SCA3300 accelerometer

2021-04-20 Thread Alexandru Ardelean
(

On Mon, Apr 19, 2021 at 11:15 PM Jonathan Cameron  wrote:
>
> On Mon, 19 Apr 2021 20:45:08 +0100
> Jonathan Cameron  wrote:
>
> > On Mon, 19 Apr 2021 16:34:35 +0300
> > Tomas Melin  wrote:
> >
> > > Hi,
> > >
> > > On 4/18/21 1:03 PM, Jonathan Cameron wrote:
> > > > On Fri, 16 Apr 2021 15:21:14 +0300
> > > > Tomas Melin  wrote:
> > > >
> > > >> Updated email-address for Alexandru.
> > > >>
> > > >>
> > > >> On 4/16/21 3:17 PM, Tomas Melin wrote:
> > > >>> On 4/15/21 11:41 AM, Tomas Melin wrote:
> > > >>>
> > > >>>> While working on updates I did notice something new which I cannot
> > > >>>>
> > > >>>> reproduce on older (5.10.17 kernel) version. If compiling this as a
> > > >>>> module, getting error while
> > > >>>>
> > > >>>> unloading module:
> > > >>>>
> > > >>>> [   40.200084] Unable to handle kernel NULL pointer dereference at
> > > >>>> virtual address 0104
> > > >>>> ...
> > > >>>>
> > > >>>> [   40.510054] Backtrace:
> > > >>>> [   40.512502] [] (iio_device_ioctl_handler_unregister)
> > > >>>> from [] (iio_buffers_free_sysfs_and_mask+0x2c/0x6c)
> > > >>>> [   40.523735] [] (iio_buffers_free_sysfs_and_mask) from
> > > >>>> [] (iio_device_unregister+0xa8/0xac)
> > > >>>> [   40.533746]  r5:c1811228 r4:c1811000
> > > >>>> [   40.537318] [] (iio_device_unregister) from []
> > > >>>> (devm_iio_device_unreg+0x1c/0x20)
> > > >>>> [   40.546461]  r5:c2415000 r4:c25bab80
> > > >>>> [   40.550025] [] (devm_iio_device_unreg) from []
> > > >>>> (release_nodes+0x1c0/0x1f0)
> > > >>>> [   40.558654] [] (release_nodes) from []
> > > >>>> (devres_release_all+0x40/0x60)
> > > >>>> [   40.566847]  r10:0081 r9:c235 r8:c0100264 r7:0081
> > > >>>> r6:bf00c010 r5:c19be000
> > > >>>> [   40.574669]  r4:c1a91c00
> > > >>>> [   40.577194] [] (devres_release_all) from []
> > > >>>> (device_release_driver_internal+0x120/0x1cc)
> > > >>>> [   40.587031]  r5:c19be000 r4:c1a91c00
> > > >>>> [   40.590596] [] (device_release_driver_internal) from
> > > >>>> [] (driver_detach+0x54/0x90)
> > > >>>> [   40.599828]  r7:0081 r6: r5:bf00c010 r4:c1a91c00
> > > >>>> [   40.605482] [] (driver_detach) from []
> > > >>>> (bus_remove_driver+0x5c/0xb0)
> > > >>>> [   40.613583]  r5:0800 r4:bf00c010
> > > >>>> [   40.617148] [] (bus_remove_driver) from []
> > > >>>> (driver_unregister+0x38/0x5c)
> > > >>>> [   40.625596]  r5:0800 r4:bf00c010
> > > >>>> [   40.629161] [] (driver_unregister) from []
> > > >>>> (sca3300_driver_exit+0x14/0x8b4 [sca3300])
> > > >>>> [   40.638747]  r5:0800 r4:bf00c080
> > > >>>> [   40.642311] [] (sca3300_driver_exit [sca3300]) from
> > > >>>> [] (sys_delete_module+0x16c/0x238)
> > > >>>> [   40.651990] [] (sys_delete_module) from []
> > > >>>> (__sys_trace_return+0x0/0x1c)
> > > >>>> [   40.660435] Exception stack(0xc2351fa8 to 0xc2351ff0)
> > > >>>> [   40.665484] 1fa0:   0050e5a8  0050e5e4
> > > >>>> 0800 081d4b00 bec18af4
> > > >>>> [   40.673661] 1fc0: 0050e5a8  bec18b50 0081 bec18e51
> > > >>>> 0050e190 0001 bec18d3c
> > > >>>> [   40.681834] 1fe0: 0050cf70 bec18afc 004f1ec8 b6ecb27c
> > > >>>> [   40.686887]  r6:bec18b50 r5: r4:0050e5a8
> > > >>>> [   40.691507] Code: e8bd4000 e1c020d0 e3a0cc01 e3001122 (e5823004)
> > > >>>> [   40.707675] ---[ end trace 189882b050077333 ]---
> > > >>>>
> > > >>>> This happens when building against linux-next
> > > >>>> 5.12.0-rc6-next-20210409. I'm failing to see what is wrong. Any 
> > > >>>> ideas?
> > > >>>>
> > > >>>> Thank

[PATCH] iio: hid-sensors: select IIO_TRIGGERED_BUFFER under HID_SENSOR_IIO_TRIGGER

2021-04-14 Thread Alexandru Ardelean
During commit 067fda1c065ff ("iio: hid-sensors: move triggered buffer
setup into hid_sensor_setup_trigger"), the
iio_triggered_buffer_{setup,cleanup}() functions got moved under the
hid-sensor-trigger module.

The above change works fine, if any of the sensors get built. However, when
only the common hid-sensor-trigger module gets built (and none of the
drivers), then the IIO_TRIGGERED_BUFFER symbol isn't selected/enforced.

Previously, each driver would enforce/select the IIO_TRIGGERED_BUFFER
symbol. With this change the HID_SENSOR_IIO_TRIGGER (for the
hid-sensor-trigger module) will enforce that IIO_TRIGGERED_BUFFER gets
selected.

All HID sensor drivers select the HID_SENSOR_IIO_TRIGGER symbol. So, this
change removes the IIO_TRIGGERED_BUFFER enforcement from each driver.

Fixes: 067fda1c065ff ("iio: hid-sensors: move triggered buffer setup into 
hid_sensor_setup_trigger")
Reported-by: Thomas Deutschmann 
Cc: Srinivas Pandruvada 
Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/accel/Kconfig  | 1 -
 drivers/iio/common/hid-sensors/Kconfig | 1 +
 drivers/iio/gyro/Kconfig   | 1 -
 drivers/iio/humidity/Kconfig   | 1 -
 drivers/iio/light/Kconfig  | 2 --
 drivers/iio/magnetometer/Kconfig   | 1 -
 drivers/iio/orientation/Kconfig| 2 --
 drivers/iio/pressure/Kconfig   | 1 -
 drivers/iio/temperature/Kconfig| 1 -
 9 files changed, 1 insertion(+), 10 deletions(-)

diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index cceda3cecbcf..8b1723635cce 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -229,7 +229,6 @@ config DMARD10
 config HID_SENSOR_ACCEL_3D
depends on HID_SENSOR_HUB
select IIO_BUFFER
-   select IIO_TRIGGERED_BUFFER
select HID_SENSOR_IIO_COMMON
select HID_SENSOR_IIO_TRIGGER
tristate "HID Accelerometers 3D"
diff --git a/drivers/iio/common/hid-sensors/Kconfig 
b/drivers/iio/common/hid-sensors/Kconfig
index 24d492567336..2a3dd3b907be 100644
--- a/drivers/iio/common/hid-sensors/Kconfig
+++ b/drivers/iio/common/hid-sensors/Kconfig
@@ -19,6 +19,7 @@ config HID_SENSOR_IIO_TRIGGER
tristate "Common module (trigger) for all HID Sensor IIO drivers"
depends on HID_SENSOR_HUB && HID_SENSOR_IIO_COMMON && IIO_BUFFER
select IIO_TRIGGER
+   select IIO_TRIGGERED_BUFFER
help
  Say yes here to build trigger support for HID sensors.
  Triggers will be send if all requested attributes were read.
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
index 5824f2edf975..20b5ac7ab66a 100644
--- a/drivers/iio/gyro/Kconfig
+++ b/drivers/iio/gyro/Kconfig
@@ -111,7 +111,6 @@ config FXAS21002C_SPI
 config HID_SENSOR_GYRO_3D
depends on HID_SENSOR_HUB
select IIO_BUFFER
-   select IIO_TRIGGERED_BUFFER
select HID_SENSOR_IIO_COMMON
select HID_SENSOR_IIO_TRIGGER
tristate "HID Gyroscope 3D"
diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig
index 6549fcf6db69..2de5494e7c22 100644
--- a/drivers/iio/humidity/Kconfig
+++ b/drivers/iio/humidity/Kconfig
@@ -52,7 +52,6 @@ config HID_SENSOR_HUMIDITY
tristate "HID Environmental humidity sensor"
depends on HID_SENSOR_HUB
select IIO_BUFFER
-   select IIO_TRIGGERED_BUFFER
select HID_SENSOR_IIO_COMMON
select HID_SENSOR_IIO_TRIGGER
help
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index 33ad4dd0b5c7..917f9becf9c7 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -256,7 +256,6 @@ config ISL29125
 config HID_SENSOR_ALS
depends on HID_SENSOR_HUB
select IIO_BUFFER
-   select IIO_TRIGGERED_BUFFER
select HID_SENSOR_IIO_COMMON
select HID_SENSOR_IIO_TRIGGER
tristate "HID ALS"
@@ -270,7 +269,6 @@ config HID_SENSOR_ALS
 config HID_SENSOR_PROX
depends on HID_SENSOR_HUB
select IIO_BUFFER
-   select IIO_TRIGGERED_BUFFER
select HID_SENSOR_IIO_COMMON
select HID_SENSOR_IIO_TRIGGER
tristate "HID PROX"
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
index 5d4ffd66032e..74ad5701c6c2 100644
--- a/drivers/iio/magnetometer/Kconfig
+++ b/drivers/iio/magnetometer/Kconfig
@@ -95,7 +95,6 @@ config MAG3110
 config HID_SENSOR_MAGNETOMETER_3D
depends on HID_SENSOR_HUB
select IIO_BUFFER
-   select IIO_TRIGGERED_BUFFER
select HID_SENSOR_IIO_COMMON
select HID_SENSOR_IIO_TRIGGER
tristate "HID Magenetometer 3D"
diff --git a/drivers/iio/orientation/Kconfig b/drivers/iio/orientation/Kconfig
index a505583cc2fd..396cbbb867f4 100644
--- a/drivers/iio/orientation/Kconfig
+++ b/drivers/iio/orientation/Kconfig
@@ -9,7 +9,6 @@ menu "Inclinometer sensors"
 config HID_SENSOR_INCLINOMET

Re: [PATCH 0/3] staging: iio: cdc: ad7746: remove platform_data in favor of device tree bindings

2021-04-10 Thread Alexandru Ardelean
On Fri, Apr 9, 2021 at 9:50 PM Lucas Stankus  wrote:
>
> This patch series aims to replace the platform_struct for the ad7746 driver
> in favor of device tree bindings, creating the dt-bindings documentation in
> the process.
>
> Since the header file was only used to define the struct and the excitation
> level values, it was possible to remove the file entirely.

>From my side: I need to get better at understanding IIO and how to
place some logic of devices into IIO,
I don't know if there is a better approach at converting the current
platform_data into DT/OF.
Maybe Jonathan [or someone else] has some better ideas.
Otherwise the overall approach looks fine from my side.

>
> Lucas Stankus (3):
>   dt-bindings: staging: iio: cdc: ad7746: add binding documentation for
> AD7746
>   staging: iio: cdc: ad7746: use dt bindings to set the EXCx pins output
>   staging: iio: cdc: ad7746: use dt binding to set the excitation level
>
>  .../bindings/iio/cdc/adi,ad7746.yaml  | 79 +++
>  drivers/staging/iio/cdc/ad7746.c  | 43 +-
>  drivers/staging/iio/cdc/ad7746.h  | 28 ---
>  3 files changed, 100 insertions(+), 50 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/iio/cdc/adi,ad7746.yaml
>  delete mode 100644 drivers/staging/iio/cdc/ad7746.h
>
> --
> 2.31.1
>


Re: [PATCH 2/3] staging: iio: cdc: ad7746: use dt bindings to set the EXCx pins output

2021-04-10 Thread Alexandru Ardelean
On Sat, Apr 10, 2021 at 7:12 PM Alexandru Ardelean
 wrote:
>
> On Fri, Apr 9, 2021 at 9:51 PM Lucas Stankus  
> wrote:
> >
> > Ditch platform_data fields in favor of device tree properties for
> > configuring EXCA and EXCB output.
> > This also removes the fields from the platform_data struct, since they're
> > not used anymore.
> >
> > Signed-off-by: Lucas Stankus 
> > ---
> >  drivers/staging/iio/cdc/ad7746.c | 33 +---
> >  drivers/staging/iio/cdc/ad7746.h |  4 
> >  2 files changed, 18 insertions(+), 19 deletions(-)
> >
> > diff --git a/drivers/staging/iio/cdc/ad7746.c 
> > b/drivers/staging/iio/cdc/ad7746.c
> > index dfd71e99e872..63041b164dbe 100644
> > --- a/drivers/staging/iio/cdc/ad7746.c
> > +++ b/drivers/staging/iio/cdc/ad7746.c
> > @@ -677,8 +677,10 @@ static int ad7746_probe(struct i2c_client *client,
> > const struct i2c_device_id *id)
> >  {
> > struct ad7746_platform_data *pdata = client->dev.platform_data;
> > +   struct device_node *np = client->dev.of_node;
> > struct ad7746_chip_info *chip;
> > struct iio_dev *indio_dev;
> > +   unsigned int exca_en, excb_en;
> > unsigned char regval = 0;
> > int ret = 0;
> >
> > @@ -703,26 +705,27 @@ static int ad7746_probe(struct i2c_client *client,
> > indio_dev->num_channels = ARRAY_SIZE(ad7746_channels);
> > indio_dev->modes = INDIO_DIRECT_MODE;
> >
>
> [1]
>
> > -   if (pdata) {
> > -   if (pdata->exca_en) {
> > -   if (pdata->exca_inv_en)
> > -   regval |= AD7746_EXCSETUP_NEXCA;
> > -   else
> > -   regval |= AD7746_EXCSETUP_EXCA;
> > -   }
> > +   ret = of_property_read_u32(np, "adi,exca-output", _en);
>
> maybe a better idea would be to use:
>
> device_property_read_u32(dev,  )
> where:
> dev = client->dev.;
>
> this would make the driver a bit more friendly with both OF and ACPI
>
> > +   if (!ret && exca_en) {
> > +   if (exca_en == 1)
> > +   regval |= AD7746_EXCSETUP_EXCA;
> > +   else
> > +   regval |= AD7746_EXCSETUP_NEXCA;
> > +   }
> >
> > -   if (pdata->excb_en) {
> > -   if (pdata->excb_inv_en)
> > -   regval |= AD7746_EXCSETUP_NEXCB;
> > -   else
> > -   regval |= AD7746_EXCSETUP_EXCB;
> > -   }
> > +   ret = of_property_read_u32(np, "adi,excb-output", _en);
> > +   if (!ret && excb_en) {
> > +   if (excb_en == 1)
> > +   regval |= AD7746_EXCSETUP_EXCB;
> > +   else
> > +   regval |= AD7746_EXCSETUP_NEXCB;
> > +   }
> >
> > +   if (pdata) {
> > regval |= AD7746_EXCSETUP_EXCLVL(pdata->exclvl);
> > } else {
> > dev_warn(>dev, "No platform data? using default\n");
> > -   regval = AD7746_EXCSETUP_EXCA | AD7746_EXCSETUP_EXCB |
> > -   AD7746_EXCSETUP_EXCLVL(3);
>
> This logic is problematic now.
> Because no matter what you're setting in the DT, it always gets
> overridden here because there is no platform data.
>
> Maybe a better idea is to do something like:
> if (!pdata)
>  regval = AD7746_EXCSETUP_EXCLVL(3);
>
> but this should be placed somewhere around [1]

[ i can see that this logic will get corrected in the next patch]
to add here a bit: the idea of a patch is that it should try to not
introduce any [even temporary] breakage, even when it's in a series;
if a driver was already broken, then it should get fixed via it's own patch;
but no patch should introduce any breakages [if possible]

>
>
> > +   regval = AD7746_EXCSETUP_EXCLVL(3);
> > }
> >
> > ret = i2c_smbus_write_byte_data(chip->client,
> > diff --git a/drivers/staging/iio/cdc/ad7746.h 
> > b/drivers/staging/iio/cdc/ad7746.h
> > index 8bdbd732dbbd..6cae4ecf779e 100644
> > --- a/drivers/staging/iio/cdc/ad7746.h
> > +++ b/drivers/staging/iio/cdc/ad7746.h
> > @@ -19,10 +19,6 @@
> >
> >  struct ad7746_platform_data {
> > unsigned char exclvl;   /*Excitation Voltage Level */
> > -   bool exca_en;   /* enables EXCA pin as the excitation 
> > output */
> > -   bool exca_inv_en;   /* enables /EXCA pin as the excitation 
> > output */
> > -   bool excb_en;   /* enables EXCB pin as the excitation 
> > output */
> > -   bool excb_inv_en;   /* enables /EXCB pin as the excitation 
> > output */
> >  };
> >
> >  #endif /* IIO_CDC_AD7746_H_ */
> > --
> > 2.31.1
> >


Re: [PATCH 2/3] staging: iio: cdc: ad7746: use dt bindings to set the EXCx pins output

2021-04-10 Thread Alexandru Ardelean
On Fri, Apr 9, 2021 at 9:51 PM Lucas Stankus  wrote:
>
> Ditch platform_data fields in favor of device tree properties for
> configuring EXCA and EXCB output.
> This also removes the fields from the platform_data struct, since they're
> not used anymore.
>
> Signed-off-by: Lucas Stankus 
> ---
>  drivers/staging/iio/cdc/ad7746.c | 33 +---
>  drivers/staging/iio/cdc/ad7746.h |  4 
>  2 files changed, 18 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/staging/iio/cdc/ad7746.c 
> b/drivers/staging/iio/cdc/ad7746.c
> index dfd71e99e872..63041b164dbe 100644
> --- a/drivers/staging/iio/cdc/ad7746.c
> +++ b/drivers/staging/iio/cdc/ad7746.c
> @@ -677,8 +677,10 @@ static int ad7746_probe(struct i2c_client *client,
> const struct i2c_device_id *id)
>  {
> struct ad7746_platform_data *pdata = client->dev.platform_data;
> +   struct device_node *np = client->dev.of_node;
> struct ad7746_chip_info *chip;
> struct iio_dev *indio_dev;
> +   unsigned int exca_en, excb_en;
> unsigned char regval = 0;
> int ret = 0;
>
> @@ -703,26 +705,27 @@ static int ad7746_probe(struct i2c_client *client,
> indio_dev->num_channels = ARRAY_SIZE(ad7746_channels);
> indio_dev->modes = INDIO_DIRECT_MODE;
>

[1]

> -   if (pdata) {
> -   if (pdata->exca_en) {
> -   if (pdata->exca_inv_en)
> -   regval |= AD7746_EXCSETUP_NEXCA;
> -   else
> -   regval |= AD7746_EXCSETUP_EXCA;
> -   }
> +   ret = of_property_read_u32(np, "adi,exca-output", _en);

maybe a better idea would be to use:

device_property_read_u32(dev,  )
where:
dev = client->dev.;

this would make the driver a bit more friendly with both OF and ACPI

> +   if (!ret && exca_en) {
> +   if (exca_en == 1)
> +   regval |= AD7746_EXCSETUP_EXCA;
> +   else
> +   regval |= AD7746_EXCSETUP_NEXCA;
> +   }
>
> -   if (pdata->excb_en) {
> -   if (pdata->excb_inv_en)
> -   regval |= AD7746_EXCSETUP_NEXCB;
> -   else
> -   regval |= AD7746_EXCSETUP_EXCB;
> -   }
> +   ret = of_property_read_u32(np, "adi,excb-output", _en);
> +   if (!ret && excb_en) {
> +   if (excb_en == 1)
> +   regval |= AD7746_EXCSETUP_EXCB;
> +   else
> +   regval |= AD7746_EXCSETUP_NEXCB;
> +   }
>
> +   if (pdata) {
> regval |= AD7746_EXCSETUP_EXCLVL(pdata->exclvl);
> } else {
> dev_warn(>dev, "No platform data? using default\n");
> -   regval = AD7746_EXCSETUP_EXCA | AD7746_EXCSETUP_EXCB |
> -   AD7746_EXCSETUP_EXCLVL(3);

This logic is problematic now.
Because no matter what you're setting in the DT, it always gets
overridden here because there is no platform data.

Maybe a better idea is to do something like:
if (!pdata)
 regval = AD7746_EXCSETUP_EXCLVL(3);

but this should be placed somewhere around [1]


> +   regval = AD7746_EXCSETUP_EXCLVL(3);
> }
>
> ret = i2c_smbus_write_byte_data(chip->client,
> diff --git a/drivers/staging/iio/cdc/ad7746.h 
> b/drivers/staging/iio/cdc/ad7746.h
> index 8bdbd732dbbd..6cae4ecf779e 100644
> --- a/drivers/staging/iio/cdc/ad7746.h
> +++ b/drivers/staging/iio/cdc/ad7746.h
> @@ -19,10 +19,6 @@
>
>  struct ad7746_platform_data {
> unsigned char exclvl;   /*Excitation Voltage Level */
> -   bool exca_en;   /* enables EXCA pin as the excitation output 
> */
> -   bool exca_inv_en;   /* enables /EXCA pin as the excitation output 
> */
> -   bool excb_en;   /* enables EXCB pin as the excitation output 
> */
> -   bool excb_inv_en;   /* enables /EXCB pin as the excitation output 
> */
>  };
>
>  #endif /* IIO_CDC_AD7746_H_ */
> --
> 2.31.1
>


[PATCH] iio: buffer: use sysfs_attr_init() on allocated attrs

2021-04-02 Thread Alexandru Ardelean
When dynamically allocating sysfs attributes, it's a good idea to call
sysfs_attr_init() on them to initialize lock_class_keys.
This change does that.

The lock_class_keys are set when the CONFIG_DEBUG_LOCK_ALLOC symbol is
enabled. Which is [likely] one reason why I did not see this during
development.

I also am not able to see this even with CONFIG_DEBUG_LOCK_ALLOC enabled,
so this may [likely] be reproduce-able on some system configurations.

This was reported via:
  
https://lore.kernel.org/linux-iio/CA+U=DsrsvGgXEF30-vXuXS_k=-mjsjibweezwkb1hjvn1p9...@mail.gmail.com/T/#u

Fixes: 15097c7a1adc ("iio: buffer: wrap all buffer attributes into 
iio_dev_attr")
Reported-by: Marek Szyprowski  
Signed-off-by: Alexandru Ardelean 
---

@Marek: could you maybe test this on your setup?

I haven't been able to reproduce this on mine.

Thanks
Alex

 drivers/iio/industrialio-buffer.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iio/industrialio-buffer.c 
b/drivers/iio/industrialio-buffer.c
index ee5aab9d4a23..06b2ea087408 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -1309,6 +1309,7 @@ static struct attribute *iio_buffer_wrap_attr(struct 
iio_buffer *buffer,
iio_attr->buffer = buffer;
memcpy(_attr->dev_attr, dattr, sizeof(iio_attr->dev_attr));
iio_attr->dev_attr.attr.name = kstrdup_const(attr->name, GFP_KERNEL);
+   sysfs_attr_init(_attr->dev_attr.attr);
 
list_add(_attr->l, >buffer_attr_list);
 
-- 
2.30.2



Re: [PATCH v6 14/24] iio: buffer: wrap all buffer attributes into iio_dev_attr

2021-04-01 Thread Alexandru Ardelean
On Thu, Apr 1, 2021 at 11:29 AM Jonathan Cameron
 wrote:
>
> On Thu, 1 Apr 2021 09:39:47 +0200
> Marek Szyprowski  wrote:
>
> > Hi
> >
> > On 15.02.2021 11:40, Alexandru Ardelean wrote:
> > > This change wraps all buffer attributes into iio_dev_attr objects, and
> > > assigns a reference to the IIO buffer they belong to.
> > >
> > > With the addition of multiple IIO buffers per one IIO device, we need a 
> > > way
> > > to know which IIO buffer is being enabled/disabled/controlled.
> > >
> > > We know that all buffer attributes are device_attributes. So we can wrap
> > > them with a iio_dev_attr types. In the iio_dev_attr type, we can also hold
> > > a reference to an IIO buffer.
> > > So, we end up being able to allocate wrapped attributes for all buffer
> > > attributes (even the one from other drivers).
> > >
> > > The neat part with this mechanism, is that we don't need to add any extra
> > > cleanup, because these attributes are being added to a dynamic list that
> > > will get cleaned up via iio_free_chan_devattr_list().
> > >
> > > With this change, the 'buffer->scan_el_dev_attr_list' list is being 
> > > renamed
> > > to 'buffer->buffer_attr_list', effectively merging (or finalizing the
> > > merge) of the buffer/ & scan_elements/ attributes internally.
> > >
> > > Accessing these new buffer attributes can now be done via
> > > 'to_iio_dev_attr(attr)->buffer' inside the show/store handlers.
> > >
> > > Signed-off-by: Alexandru Ardelean 
> >
> > This patch landed recently in linux-next as commit 15097c7a1adc ("iio:
> > buffer: wrap all buffer attributes into iio_dev_attr"). Sadly it causes
> > a regression and triggers the lock debuging warning:
> >
> > ak8975 9-000c: mounting matrix not found: using identity...
> > ak8975 9-000c: supply vdd not found, using dummy regulator
> > ak8975 9-000c: supply vid not found, using dummy regulator
> > BUG: key cf40d08c has not been registered!
> > [ cut here ]
> > WARNING: CPU: 2 PID: 1 at kernel/locking/lockdep.c:4686
> > __kernfs_create_file+0x7c/0xfc
> > DEBUG_LOCKS_WARN_ON(1)
> > Modules linked in:
> > CPU: 2 PID: 1 Comm: swapper/0 Not tainted 5.12.0-rc2-00153-g15097c7a1adc
> > #2828
> > Hardware name: Samsung Exynos (Flattened Device Tree)
> > [] (unwind_backtrace) from [] (show_stack+0x10/0x14)
> > [] (show_stack) from [] (dump_stack+0xa4/0xc4)
> > [] (dump_stack) from [] (__warn+0x118/0x11c)
> > [] (__warn) from [] (warn_slowpath_fmt+0x78/0xbc)
> > [] (warn_slowpath_fmt) from []
> > (__kernfs_create_file+0x7c/0xfc)
> > [] (__kernfs_create_file) from []
> > (sysfs_add_file_mode_ns+0xa0/0x1cc)
> > [] (sysfs_add_file_mode_ns) from []
> > (internal_create_group+0x138/0x3f4)
> > [] (internal_create_group) from []
> > (internal_create_groups+0x48/0x88)
> > [] (internal_create_groups) from []
> > (device_add+0x2e4/0x7ec)
> > [] (device_add) from [] (cdev_device_add+0x48/0x80)
> > [] (cdev_device_add) from []
> > (__iio_device_register+0x670/0x7c0)
> > [] (__iio_device_register) from []
> > (ak8975_probe+0x3a4/0x584)
> > [] (ak8975_probe) from [] (i2c_device_probe+0x234/0x2a4)
> > [] (i2c_device_probe) from [] (really_probe+0x1d4/0x4ec)
> > [] (really_probe) from []
> > (driver_probe_device+0x78/0x1d8)
> > [] (driver_probe_device) from []
> > (device_driver_attach+0x58/0x60)
> > [] (device_driver_attach) from []
> > (__driver_attach+0xfc/0x160)
> > [] (__driver_attach) from []
> > (bus_for_each_dev+0x6c/0xb8)
> > [] (bus_for_each_dev) from []
> > (bus_add_driver+0x170/0x20c)
> > [] (bus_add_driver) from [] (driver_register+0x78/0x10c)
> > [] (driver_register) from []
> > (i2c_register_driver+0x3c/0xac)
> > [] (i2c_register_driver) from []
> > (do_one_initcall+0x88/0x430)
> > [] (do_one_initcall) from []
> > (kernel_init_freeable+0x190/0x1e0)
> > [] (kernel_init_freeable) from []
> > (kernel_init+0x8/0x118)
> > [] (kernel_init) from [] (ret_from_fork+0x14/0x38)
> > Exception stack(0xc1d09fb0 to 0xc1d09ff8)
> > 9fa0:   
> > 
> > 9fc0:       
> > 
> > 9fe0:     0013 
> > irq event stamp: 485619
> > hardirqs last  enabled at (485619): [] console_unlock+0x500/0x648
> > hardirqs last disabled

Re: [PATCH 00/10] platform/x86: toshiba_acpi: move acpi add/remove to device-managed routines

2021-03-30 Thread Alexandru Ardelean
On Tue, Mar 30, 2021 at 11:21 AM Hans de Goede  wrote:
>
> Hi Alexadru, Jonathan,
>
> On 3/24/21 1:55 PM, Alexandru Ardelean wrote:
> > This changeset tries to do a conversion of the toshiba_acpi driver to use
> > only device-managed routines. The driver registers as a singleton, so no
> > more than one device can be registered at a time.
> >
> > My main intent here is to try to convert the iio_device_alloc() and
> > iio_device_register() to their devm_ variants.
> >
> > Usually, when converting a registration call to device-managed variant, the
> > init order must be preserved. And the deregistration order must be a mirror
> > of the registration (in reverse order).
> >
> > This change tries to do that, by using devm_ variants where available and
> > devm_add_action_or_reset() where this isn't possible.
> > Some deregistration ordering is changed, because it wasn't exactly
> > mirroring (in reverse) the init order.
> >
> > For the IIO subsystem, the toshiba_acpi driver is the only user of
> > iio_device_alloc(). If this changeset is accepted (after discussion), I
> > will propose to remove the iio_device_alloc() function.
> >
> > While I admit this may look like an overzealous effort to use devm_
> > everywhere (in IIO at least), for me it's a fun/interesting excercise.
>
> Alexadru, thank you for the patches.
>
> Jonathan, thank you for the reviews.
>
> To be honest I'm currently inclined to not accept / merge these patches,
> this is based on 2 assumptions from me, which might be wrong. let me explain.
>
> If I understand things correctly, the main reason for this rework of
> the toshiba_acpi code is to move iio_device_alloc() and iio_device_register()
> to their devm_ variants, converting the last users in the tree ?

yes
well, we still have plenty of users iio_device_alloc() /
iio_device_register() inside drivers/iio

but the toshipa_acpi driver is the more quirky user of these functions
[treewide]

i wanted to jump on those simpler IIO cases, but i thought i would
leave those to new contributors [for a while];
the complexity of those conversions is good enough to get some people
started to contribute changes that are a bit more useful than
checkpatch fixes, comment fixes [etc];

[personally] i feel that these devm_ conversions are complex enough to
maybe get people wanting to dig more into some kernel design stuff

>
> This would allow these 2 iio functions to then be e.g. marked as static /
> private helpers inside the iio core, so that all new users can only use
> the devm_ versions. But if I'm reading Jonathan's reaction correctly then
> Jonathan is not planning to do that because they might still be useful
> in some cases.
>
> Jonathan have I correctly understood that you don't plan to make any
> changes to the iio_device_alloc() and iio_device_register() functions
> even if this gets merged ?
>
> Which brings me to my next assumption, Alexandru, I don't read anything
> about testing anywhere. So I'm currently under the assumption that
> you don't have any hardware using the toshiba_acpi driver and that this
> is thus untested ?

yes, i don't have any hw to test this

>
> The not being tested state is my main reason for not wanting to merge
> this. The toshiba_acpi driver likely does not have a whole lot of users,
> so the chances of someone running release candidates or even just the
> latest kernels on hardware which uses it are small.  This means that if
> we accidentally introduce a bug with this series it might not get caught
> until say lots of people start upgrading to Ubuntu 22.04 which is
> the first Ubuntu kernel with your changes; and then at least one of the
> hit users needs to have the skills to find us and get in contact about that.
>
> TL;DR: we might break stuff and if we do it might be a long time until we
> find out we did and then we have been shipping broken code for ages...

ack
well, i don't insist in pushing this series;

another thought was to just send bits of this set, which are simple
enough to consider even on their own;

maybe i'll look for a toshiba laptop with support for this stuff;
i'll see

thanks :)
Alex

>
> Regards,
>
> Hans
>
>
>
>
>
> >
> > Alexandru Ardelean (10):
> >   platform/x86: toshiba_acpi: bind life-time of toshiba_acpi_dev to
> > parent
> >   platform/x86: toshiba_acpi: use devm_add_action_or_reset() for
> > singleton clear
> >   platform/x86: toshiba_acpi: bind registration of miscdev object to
> > parent
> >   platform/x86: toshiba_acpi: use device-managed functions for input
> > device
> >   platform/x86: toshiba_acpi: register backlight with device-managed
> > variant

Re: [PATCH 01/10] platform/x86: toshiba_acpi: bind life-time of toshiba_acpi_dev to parent

2021-03-30 Thread Alexandru Ardelean
On Mon, 29 Mar 2021 at 17:30, Jonathan Cameron  wrote:
>
> On Wed, 24 Mar 2021 14:55:39 +0200
> Alexandru Ardelean  wrote:
>
> > The 'toshiba_acpi_dev' object is allocated first and free'd last. We can
> > bind it's life-time to the parent ACPI device object. This is a first step
> > in using more device-managed allocated functions for this.
> >
> > The main intent is to try to convert the IIO framework to export only
> > device-managed functions (i.e. devm_iio_device_alloc() and
> > devm_iio_device_register()). It's still not 100% sure that this is
> > possible, but for now, this is the process of taking it slowly in that
> > direction.
> >
> > Signed-off-by: Alexandru Ardelean 
>
> Might just be me, but naming anything dev that isn't a struct device *
> is downright confusing?
>

I found it a bit odd as well, but I decided to not take it in
consideration for now.

>
>
>
> > ---
> >  drivers/platform/x86/toshiba_acpi.c | 6 ++
> >  1 file changed, 2 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/platform/x86/toshiba_acpi.c 
> > b/drivers/platform/x86/toshiba_acpi.c
> > index fa7232ad8c39..6d298810b7bf 100644
> > --- a/drivers/platform/x86/toshiba_acpi.c
> > +++ b/drivers/platform/x86/toshiba_acpi.c
> > @@ -2998,8 +2998,6 @@ static int toshiba_acpi_remove(struct acpi_device 
> > *acpi_dev)
> >   if (toshiba_acpi)
> >   toshiba_acpi = NULL;
> >
> > - kfree(dev);
> > -
> >   return 0;
> >  }
> >
> > @@ -3016,6 +3014,7 @@ static const char *find_hci_method(acpi_handle handle)
> >
> >  static int toshiba_acpi_add(struct acpi_device *acpi_dev)
> >  {
> > + struct device *parent = _dev->dev;
> >   struct toshiba_acpi_dev *dev;
> >   const char *hci_method;
> >   u32 dummy;
> > @@ -3033,7 +3032,7 @@ static int toshiba_acpi_add(struct acpi_device 
> > *acpi_dev)
> >   return -ENODEV;
> >   }
> >
> > - dev = kzalloc(sizeof(*dev), GFP_KERNEL);
> > + dev = devm_kzalloc(parent, sizeof(*dev), GFP_KERNEL);
> >   if (!dev)
> >   return -ENOMEM;
> >   dev->acpi_dev = acpi_dev;
> > @@ -3045,7 +3044,6 @@ static int toshiba_acpi_add(struct acpi_device 
> > *acpi_dev)
> >   ret = misc_register(>miscdev);
> >   if (ret) {
> >   pr_err("Failed to register miscdevice\n");
> > - kfree(dev);
> >   return ret;
> >   }
> >
>


Re: [PATCH 00/10] platform/x86: toshiba_acpi: move acpi add/remove to device-managed routines

2021-03-29 Thread Alexandru Ardelean
On Mon, 29 Mar 2021 at 15:38, Jonathan Cameron  wrote:
>
> On Wed, 24 Mar 2021 14:55:38 +0200
> Alexandru Ardelean  wrote:
>
> > This changeset tries to do a conversion of the toshiba_acpi driver to use
> > only device-managed routines. The driver registers as a singleton, so no
> > more than one device can be registered at a time.
> >
> > My main intent here is to try to convert the iio_device_alloc() and
> > iio_device_register() to their devm_ variants.
> >
> > Usually, when converting a registration call to device-managed variant, the
> > init order must be preserved. And the deregistration order must be a mirror
> > of the registration (in reverse order).
> >
> > This change tries to do that, by using devm_ variants where available and
> > devm_add_action_or_reset() where this isn't possible.
> > Some deregistration ordering is changed, because it wasn't exactly
> > mirroring (in reverse) the init order.
> >
> > For the IIO subsystem, the toshiba_acpi driver is the only user of
> > iio_device_alloc(). If this changeset is accepted (after discussion), I
> > will propose to remove the iio_device_alloc() function.
> >
> > While I admit this may look like an overzealous effort to use devm_
> > everywhere (in IIO at least), for me it's a fun/interesting excercise.
> hmm. I am dubious about 'removing' the support for non devm_ in the long
> run because it can lead to requiring fiddly changes in existing drivers
> (like this one :) and I don't want to put that barrier in front of anyone
> using IIO.

Yeah.
I also feel that the current driver is a bit fiddly.
I was undecided [when doing the series], whether to send it as a
whole, or start with sending just a few patches that make sense on
their own.

I might go via the second route and send these individually.

>
> However, I'm more than happy to see them used in very few drivers and
> nice warning text added to suggest people might want to look at whether
> then can move to a device managed probe flow
>
> Jonathan
>
> >
> > Alexandru Ardelean (10):
> >   platform/x86: toshiba_acpi: bind life-time of toshiba_acpi_dev to
> > parent
> >   platform/x86: toshiba_acpi: use devm_add_action_or_reset() for
> > singleton clear
> >   platform/x86: toshiba_acpi: bind registration of miscdev object to
> > parent
> >   platform/x86: toshiba_acpi: use device-managed functions for input
> > device
> >   platform/x86: toshiba_acpi: register backlight with device-managed
> > variant
> >   platform/x86: toshiba_acpi: use devm_led_classdev_register() for LEDs
> >   platform/x86: toshiba_acpi: use device-managed functions for
> > accelerometer
> >   platform/x86: toshiba_acpi: use device-managed for wwan_rfkill
> > management
> >   platform/x86: toshiba_acpi: use device-managed for sysfs removal
> >   platform/x86: toshiba_acpi: bind proc entries creation to parent
> >
> >  drivers/platform/x86/toshiba_acpi.c | 249 +---
> >  1 file changed, 150 insertions(+), 99 deletions(-)
> >
>


Re: linux-next: build failure after merge of the staging tree

2021-03-29 Thread Alexandru Ardelean
On Mon, 29 Mar 2021 at 09:15, Greg KH  wrote:
>
> On Mon, Mar 29, 2021 at 04:55:25PM +1100, Stephen Rothwell wrote:
> > Hi all,
> >
> > After merging the staging tree, today's linux-next build (x86_64
> > allmodconfig) failed like this:
> >
> > drivers/iio/adc/ti-ads131e08.c: In function 'ads131e08_read_reg':
> > drivers/iio/adc/ti-ads131e08.c:180:5: error: 'struct spi_transfer' has no 
> > member named 'delay_usecs'
> >   180 |.delay_usecs = st->sdecode_delay_us,
> >   | ^~~
> > drivers/iio/adc/ti-ads131e08.c: In function 'ads131e08_write_reg':
> > drivers/iio/adc/ti-ads131e08.c:206:5: error: 'struct spi_transfer' has no 
> > member named 'delay_usecs'
> >   206 |.delay_usecs = st->sdecode_delay_us,
> >   | ^~~
> >
> > Caused by commit
> >
> >   d935eddd2799 ("iio: adc: Add driver for Texas Instruments ADS131E0x ADC 
> > family")
> >
> > interacting with commit
> >
> >   3ab1cce55337 ("spi: core: remove 'delay_usecs' field from spi_transfer")
> >
> > from the spi tree.
> >
> > I have applied the following merge fix patch.
> >
> > From: Stephen Rothwell 
> > Date: Mon, 29 Mar 2021 16:51:22 +1100
> > Subject: [PATCH] iio: adc: merge fix for "spi: core: remove 'delay_usecs'
> >  field from spi_transfer"
> >

Reviewed-by: Alexandru Ardelean 

> > Signed-off-by: Stephen Rothwell 
> > ---
> >  drivers/iio/adc/ti-ads131e08.c | 10 --
> >  1 file changed, 8 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/iio/adc/ti-ads131e08.c b/drivers/iio/adc/ti-ads131e08.c
> > index 0060d5f0abb0..764dab087b41 100644
> > --- a/drivers/iio/adc/ti-ads131e08.c
> > +++ b/drivers/iio/adc/ti-ads131e08.c
> > @@ -177,7 +177,10 @@ static int ads131e08_read_reg(struct ads131e08_state 
> > *st, u8 reg)
> >   {
> >   .tx_buf = >tx_buf,
> >   .len = 2,
> > - .delay_usecs = st->sdecode_delay_us,
> > + .delay = {
> > + .value = st->sdecode_delay_us,
> > + .unit = SPI_DELAY_UNIT_USECS,
> > + },
> >   }, {
> >   .rx_buf = >rx_buf,
> >   .len = 1,
> > @@ -203,7 +206,10 @@ static int ads131e08_write_reg(struct ads131e08_state 
> > *st, u8 reg, u8 value)
> >   {
> >   .tx_buf = >tx_buf,
> >   .len = 3,
> > - .delay_usecs = st->sdecode_delay_us,
> > + .delay = {
> > + .value = st->sdecode_delay_us,
> > + .unit = SPI_DELAY_UNIT_USECS,
> > + },
> >   }
> >   };
> >
> > --
> > 2.30.0
> >
>
> Thanks for the fix, looks correct to me.
>
> greg k-h


Re: [PATCH 0/3] iio: adc: ad7923: convert driver resources routines to device-managed counterparts

2021-03-29 Thread Alexandru Ardelean
On Mon, Mar 29, 2021 at 12:48 AM Lucas Stankus
 wrote:
>
> Following the initiative proposed by Alexandru, this patch series aims
> to convert the ad7923 to use only device-managed routines.
>

This idea is becoming popular it seems :)

Thanks to Lars for pointing out that spi_set_drvdata() omission.
With that fixed:

Reviewed-by: Alexandru Ardelean 

If you want, you can also search for more of these xxx_set_drvdata() omissions.
There were more conversions to devm_ that forgot to remove those.
Maybe a cocci script would be nice to find them.
But all this is optional. Only if you want.

> Part of the driver was already using devm_ functions, so it was possible
> to convert the remainder of it without much hassle.
>
> With that, the deregistration function was no longer necessary and could
> be entirely removed from the driver.
>
> Lucas Stankus (3):
>   iio: adc: ad7923: use devm_add_action_or_reset for regulator disable
>   iio: adc: ad7923: use device-managed function for triggered buffer
>   iio: adc: ad7923: register device with devm_iio_device_register
>
>  drivers/iio/adc/ad7923.c | 39 +--
>  1 file changed, 13 insertions(+), 26 deletions(-)
>
> --
> 2.31.0
>


Re: [PATCH] drivers: iio: adc: fix unmet dependency on OF

2021-03-29 Thread Alexandru Ardelean
On Sun, Mar 28, 2021 at 7:08 AM Julian Braha  wrote:
>
> When AD9467 is enabled, and OF is disabled,
> Kbuild gives the following warning:
>
> WARNING: unmet direct dependencies detected for ADI_AXI_ADC
>  Depends on [n]: IIO [=y] && HAS_IOMEM [=y] && OF [=n]
>  Selected by [y]:
>  - AD9467 [=y] && IIO [=y] && SPI [=y]
>
> This is because AD9467 selects ADI_AXI_ADC
> without selecting or depending on OF,
> despite ADI_AXI_ADC depending on OF.
>

Hey,

Thanks for the patch.
This should have been fixed a bit differently with patch:
https://patchwork.kernel.org/project/linux-iio/patch/20210324182746.9337-1-aardel...@deviqon.com/

Can you check if this fixes your setup?

Thanks
Alex

> Signed-off-by: Julian Braha 
> ---
>  drivers/iio/adc/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index e0667c4b3c08..7606c9b1630e 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -248,7 +248,7 @@ config AD799X
>
>  config AD9467
> tristate "Analog Devices AD9467 High Speed ADC driver"
> -   depends on SPI
> +   depends on SPI && OF
> select ADI_AXI_ADC
> help
>   Say yes here to build support for Analog Devices:
> --
> 2.25.1
>


[PATCH] iio: adc: Kconfig: make AD9467 depend on ADI_AXI_ADC symbol

2021-03-24 Thread Alexandru Ardelean
Because a dependency on HAS_IOMEM and OF was added for the ADI AXI ADC
driver, this makes the AD9467 driver have some build/dependency issues
when OF is disabled (typically on ACPI archs like x86).

This is because the selection of the AD9467 enforces the ADI_AXI_ADC symbol
which is blocked by the OF (and potentially HAS_IOMEM) being disabled.

To fix this, we make the AD9467 driver depend on the ADI_AXI_ADC symbol.
The AD9467 driver cannot operate on it's own. It requires the ADI AXI ADC
driver to stream data (or some similar IIO interface).

So, the fix here is to make the AD9467 symbol depend on the ADI_AXI_ADC
symbol. At some point this could become it's own subgroup of high-speed
ADCs.

Fixes: be24c65e9fa24 ("iio: adc: adi-axi-adc: add proper Kconfig dependencies")
Reported-by: Randy Dunlap 
Signed-off-by: Alexandru Ardelean 
---

Apologies for this being too late.
I made the patch but forgot it in a local tree.

Related to discussion:
   https://lkml.org/lkml/2021/3/18/1007

 drivers/iio/adc/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index e0667c4b3c08..dda0f1e37ec1 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -249,7 +249,7 @@ config AD799X
 config AD9467
tristate "Analog Devices AD9467 High Speed ADC driver"
depends on SPI
-   select ADI_AXI_ADC
+   depends on ADI_AXI_ADC
help
  Say yes here to build support for Analog Devices:
  * AD9467 16-Bit, 200 MSPS/250 MSPS Analog-to-Digital Converter
-- 
2.30.2



[PATCH 09/10] platform/x86: toshiba_acpi: use device-managed for sysfs removal

2021-03-24 Thread Alexandru Ardelean
This change moves the creation of the Toshiba ACPI group to be
automatically removed when the parent refcount goes to zero.

The main reason to do this, is to also enforce that the order of removal is
mirroring the order of initialization.

Signed-off-by: Alexandru Ardelean 
---
 drivers/platform/x86/toshiba_acpi.c | 29 +++--
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/platform/x86/toshiba_acpi.c 
b/drivers/platform/x86/toshiba_acpi.c
index a1249f6dde9a..8e8917979047 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -200,7 +200,6 @@ struct toshiba_acpi_dev {
unsigned int usb_three_supported:1;
unsigned int wwan_supported:1;
unsigned int cooling_method_supported:1;
-   unsigned int sysfs_created:1;
unsigned int special_functions;
 
bool kbd_event_generated;
@@ -3019,10 +3018,6 @@ static int toshiba_acpi_remove(struct acpi_device 
*acpi_dev)
 
remove_toshiba_proc_entries(dev);
 
-   if (dev->sysfs_created)
-   sysfs_remove_group(>acpi_dev->dev.kobj,
-  _attr_group);
-
return 0;
 }
 
@@ -3049,6 +3044,13 @@ static void toshiba_acpi_misc_deregister(void *data)
misc_deregister(miscdev);
 }
 
+static void toshiba_acpi_sysfs_remove(void *data)
+{
+   struct kobject *kobj = data;
+
+   sysfs_remove_group(kobj, _attr_group);
+}
+
 static int toshiba_acpi_add(struct acpi_device *acpi_dev)
 {
struct device *parent = _dev->dev;
@@ -3219,21 +3221,20 @@ static int toshiba_acpi_add(struct acpi_device 
*acpi_dev)
 
ret = sysfs_create_group(>acpi_dev->dev.kobj,
 _attr_group);
-   if (ret) {
-   dev->sysfs_created = 0;
-   goto error;
-   }
-   dev->sysfs_created = !ret;
+   if (ret)
+   return ret;
+
+   ret = devm_add_action_or_reset(parent,
+  toshiba_acpi_sysfs_remove,
+  >acpi_dev->dev.kobj);
+   if (ret)
+   return ret;
 
create_toshiba_proc_entries(dev);
 
toshiba_acpi = dev;
 
return 0;
-
-error:
-   toshiba_acpi_remove(acpi_dev);
-   return ret;
 }
 
 static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
-- 
2.30.2



[PATCH 07/10] platform/x86: toshiba_acpi: use device-managed functions for accelerometer

2021-03-24 Thread Alexandru Ardelean
This change converts the IIO registration to use devm_iio_device_alloc()
and devm_iio_device_register().
With this change we can remove the manual deregistrations an freeing of the
IIO data.

This also makes the deregistration symmetrical with the registration.

One side-effect (that is undesired), is that if devm_iio_device_register()
fails, then the IIO object will not be free'd and will stick around until
the parent object is free'd. This is because there is no
devm_iio_device_free() function anymore in IIO.
However, this is a pretty bad corner-case that should not happen under
normal operation.

Signed-off-by: Alexandru Ardelean 
---
 drivers/platform/x86/toshiba_acpi.c | 11 +++
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/platform/x86/toshiba_acpi.c 
b/drivers/platform/x86/toshiba_acpi.c
index e787c140eec2..12860ef60e4d 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -2992,11 +2992,6 @@ static int toshiba_acpi_remove(struct acpi_device 
*acpi_dev)
 
remove_toshiba_proc_entries(dev);
 
-   if (dev->accelerometer_supported && dev->indio_dev) {
-   iio_device_unregister(dev->indio_dev);
-   iio_device_free(dev->indio_dev);
-   }
-
if (dev->sysfs_created)
sysfs_remove_group(>acpi_dev->dev.kobj,
   _attr_group);
@@ -3149,7 +3144,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
 
toshiba_accelerometer_available(dev);
if (dev->accelerometer_supported) {
-   dev->indio_dev = iio_device_alloc(_dev->dev, sizeof(*dev));
+   dev->indio_dev = devm_iio_device_alloc(parent, sizeof(*dev));
if (!dev->indio_dev) {
pr_err("Unable to allocate iio device\n");
goto iio_error;
@@ -3164,10 +3159,10 @@ static int toshiba_acpi_add(struct acpi_device 
*acpi_dev)
dev->indio_dev->num_channels =
ARRAY_SIZE(toshiba_iio_accel_channels);
 
-   ret = iio_device_register(dev->indio_dev);
+   ret = devm_iio_device_register(parent, dev->indio_dev);
if (ret < 0) {
pr_err("Unable to register iio device\n");
-   iio_device_free(dev->indio_dev);
+   dev->indio_dev = NULL;
}
}
 iio_error:
-- 
2.30.2



[PATCH 10/10] platform/x86: toshiba_acpi: bind proc entries creation to parent

2021-03-24 Thread Alexandru Ardelean
This change binds the creation of the proc entries to the parent object,
via the devm_add_action_or_reset() call.
This way when the parent object's refcount goes to zero, the proc entries
are removed in the reverse other in which they were created.

This is the last bit of the toshiba_acpi_remove() function, so in this
change this function is removed.

Signed-off-by: Alexandru Ardelean 
---
 drivers/platform/x86/toshiba_acpi.c | 45 ++---
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/drivers/platform/x86/toshiba_acpi.c 
b/drivers/platform/x86/toshiba_acpi.c
index 8e8917979047..56ee5cd1e90c 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -1671,7 +1671,23 @@ static int __maybe_unused version_proc_show(struct 
seq_file *m, void *v)
 
 #define PROC_TOSHIBA   "toshiba"
 
-static void create_toshiba_proc_entries(struct toshiba_acpi_dev *dev)
+static void remove_toshiba_proc_entries(void *data)
+{
+   struct toshiba_acpi_dev *dev = data;
+
+   if (dev->backlight_dev)
+   remove_proc_entry("lcd", toshiba_proc_dir);
+   if (dev->video_supported)
+   remove_proc_entry("video", toshiba_proc_dir);
+   if (dev->fan_supported)
+   remove_proc_entry("fan", toshiba_proc_dir);
+   if (dev->hotkey_dev)
+   remove_proc_entry("keys", toshiba_proc_dir);
+   remove_proc_entry("version", toshiba_proc_dir);
+}
+
+static int create_toshiba_proc_entries(struct device *parent,
+  struct toshiba_acpi_dev *dev)
 {
if (dev->backlight_dev)
proc_create_data("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir,
@@ -1687,19 +1703,8 @@ static void create_toshiba_proc_entries(struct 
toshiba_acpi_dev *dev)
 _proc_ops, dev);
proc_create_single_data("version", S_IRUGO, toshiba_proc_dir,
version_proc_show, dev);
-}
 
-static void remove_toshiba_proc_entries(struct toshiba_acpi_dev *dev)
-{
-   if (dev->backlight_dev)
-   remove_proc_entry("lcd", toshiba_proc_dir);
-   if (dev->video_supported)
-   remove_proc_entry("video", toshiba_proc_dir);
-   if (dev->fan_supported)
-   remove_proc_entry("fan", toshiba_proc_dir);
-   if (dev->hotkey_dev)
-   remove_proc_entry("keys", toshiba_proc_dir);
-   remove_proc_entry("version", toshiba_proc_dir);
+   return devm_add_action_or_reset(parent, remove_toshiba_proc_entries, 
dev);
 }
 
 static const struct backlight_ops toshiba_backlight_data = {
@@ -3012,15 +3017,6 @@ static void print_supported_features(struct 
toshiba_acpi_dev *dev)
pr_cont("\n");
 }
 
-static int toshiba_acpi_remove(struct acpi_device *acpi_dev)
-{
-   struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
-
-   remove_toshiba_proc_entries(dev);
-
-   return 0;
-}
-
 static const char *find_hci_method(acpi_handle handle)
 {
if (acpi_has_method(handle, "GHCI"))
@@ -3230,7 +3226,9 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
if (ret)
return ret;
 
-   create_toshiba_proc_entries(dev);
+   ret = create_toshiba_proc_entries(parent, dev);
+   if (ret)
+   return ret;
 
toshiba_acpi = dev;
 
@@ -3340,7 +3338,6 @@ static struct acpi_driver toshiba_acpi_driver = {
.flags  = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
.ops= {
.add= toshiba_acpi_add,
-   .remove = toshiba_acpi_remove,
.notify = toshiba_acpi_notify,
},
.drv.pm = _acpi_pm,
-- 
2.30.2



[PATCH 06/10] platform/x86: toshiba_acpi: use devm_led_classdev_register() for LEDs

2021-03-24 Thread Alexandru Ardelean
With this change the deregistration of the LED objects is made symmetrical
(and in reverse) with the registration. We also can get rid of the calls
to led_classdev_unregister(), because the LED objects will be cleaned up
when the reference to the parent device object goes to zero.

This change also unifies the reference to the parent object from
'_dev->dev' and '>acpi_dev->dev' to 'parent', since it's the same
reference, and makes the code-lines a bit shorter.

Signed-off-by: Alexandru Ardelean 
---
 drivers/platform/x86/toshiba_acpi.c | 16 +---
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/platform/x86/toshiba_acpi.c 
b/drivers/platform/x86/toshiba_acpi.c
index ada2a2d8c913..e787c140eec2 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -3001,10 +3001,6 @@ static int toshiba_acpi_remove(struct acpi_device 
*acpi_dev)
sysfs_remove_group(>acpi_dev->dev.kobj,
   _attr_group);
 
-   led_classdev_unregister(>led_dev);
-   led_classdev_unregister(>kbd_led);
-   led_classdev_unregister(>eco_led);
-
if (dev->wwan_rfk) {
rfkill_unregister(dev->wwan_rfk);
rfkill_destroy(dev->wwan_rfk);
@@ -3114,7 +3110,9 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
dev->led_dev.max_brightness = 1;
dev->led_dev.brightness_set = toshiba_illumination_set;
dev->led_dev.brightness_get = toshiba_illumination_get;
-   led_classdev_register(_dev->dev, >led_dev);
+   ret = devm_led_classdev_register(parent, >led_dev);
+   if (ret)
+   return ret;
}
 
toshiba_eco_mode_available(dev);
@@ -3123,7 +3121,9 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
dev->eco_led.max_brightness = 1;
dev->eco_led.brightness_set = toshiba_eco_mode_set_status;
dev->eco_led.brightness_get = toshiba_eco_mode_get_status;
-   led_classdev_register(>acpi_dev->dev, >eco_led);
+   ret = devm_led_classdev_register(parent, >eco_led);
+   if (ret)
+   return ret;
}
 
toshiba_kbd_illum_available(dev);
@@ -3139,7 +3139,9 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
dev->kbd_led.max_brightness = 1;
dev->kbd_led.brightness_set = toshiba_kbd_backlight_set;
dev->kbd_led.brightness_get = toshiba_kbd_backlight_get;
-   led_classdev_register(>acpi_dev->dev, >kbd_led);
+   ret = devm_led_classdev_register(parent, >kbd_led);
+   if (ret)
+   return ret;
}
 
ret = toshiba_touchpad_get(dev, );
-- 
2.30.2



[PATCH 08/10] platform/x86: toshiba_acpi: use device-managed for wwan_rfkill management

2021-03-24 Thread Alexandru Ardelean
This change converts the wwan_rfkill object to be free'd automatically when
the parent refcount goes to zero.
There are 2 cleanup operations required: rfkill_unregister() and
rfkill_destroy(). Since they don't have any devm_ variants, they are hooked
via devm_add_action_or_reset().

The main reason to do this is to enforce ordering on cleanup, when the
Toshiba ACPI device is cleaned up.

Signed-off-by: Alexandru Ardelean 
---
 drivers/platform/x86/toshiba_acpi.c | 40 ++---
 1 file changed, 31 insertions(+), 9 deletions(-)

diff --git a/drivers/platform/x86/toshiba_acpi.c 
b/drivers/platform/x86/toshiba_acpi.c
index 12860ef60e4d..a1249f6dde9a 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -2591,7 +2591,22 @@ static const struct rfkill_ops wwan_rfk_ops = {
.poll = toshiba_acpi_wwan_poll,
 };
 
-static int toshiba_acpi_setup_wwan_rfkill(struct toshiba_acpi_dev *dev)
+static void toshiba_acpi_rfkill_destroy(void *data)
+{
+   struct rfkill *wwan_rfk = data;
+
+   rfkill_destroy(wwan_rfk);
+}
+
+static void toshiba_acpi_rfkill_unreg(void *data)
+{
+   struct rfkill *wwan_rfk = data;
+
+   rfkill_unregister(wwan_rfk);
+}
+
+static int toshiba_acpi_setup_wwan_rfkill(struct device *parent,
+ struct toshiba_acpi_dev *dev)
 {
int ret = toshiba_wireless_status(dev);
 
@@ -2608,15 +2623,27 @@ static int toshiba_acpi_setup_wwan_rfkill(struct 
toshiba_acpi_dev *dev)
return -ENOMEM;
}
 
+   ret = devm_add_action_or_reset(parent, toshiba_acpi_rfkill_destroy,
+  dev->wwan_rfk);
+   if (ret)
+   return ret;
+
rfkill_set_hw_state(dev->wwan_rfk, !dev->killswitch);
 
ret = rfkill_register(dev->wwan_rfk);
if (ret) {
pr_err("Unable to register WWAN rfkill device\n");
-   rfkill_destroy(dev->wwan_rfk);
+   return ret;
}
 
-   return ret;
+   ret = devm_add_action_or_reset(parent, toshiba_acpi_rfkill_unreg,
+  dev->wwan_rfk);
+   if (ret) {
+   dev->wwan_rfk = NULL;
+   return ret;
+   }
+
+   return 0;
 }
 
 /*
@@ -2996,11 +3023,6 @@ static int toshiba_acpi_remove(struct acpi_device 
*acpi_dev)
sysfs_remove_group(>acpi_dev->dev.kobj,
   _attr_group);
 
-   if (dev->wwan_rfk) {
-   rfkill_unregister(dev->wwan_rfk);
-   rfkill_destroy(dev->wwan_rfk);
-   }
-
return 0;
 }
 
@@ -3189,7 +3211,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
 
toshiba_wwan_available(dev);
if (dev->wwan_supported)
-   toshiba_acpi_setup_wwan_rfkill(dev);
+   toshiba_acpi_setup_wwan_rfkill(parent, dev);
 
toshiba_cooling_method_available(dev);
 
-- 
2.30.2



[PATCH 04/10] platform/x86: toshiba_acpi: use device-managed functions for input device

2021-03-24 Thread Alexandru Ardelean
This change uses device managed functions to handle the deregistration of
the keyboard resources when the refcount of the parent device goes to zero.

For the input device devm_input_allocate_device() must be used, and after
that it will be bound also for auto-deregistration when
input_device_register() is called.

The work object is registered for uninit with devm_add_action(), which will
be called on device unregister only.

The i8042 filter is registered with devm_add_action() as well, but it is
done last in the toshiba_acpi_setup_keyboard() function. This is a little
quirky, because this relies on the fact that there can a single
toshiba_acpi_dev object.

Signed-off-by: Alexandru Ardelean 
---
 drivers/platform/x86/toshiba_acpi.c | 55 +++--
 1 file changed, 36 insertions(+), 19 deletions(-)

diff --git a/drivers/platform/x86/toshiba_acpi.c 
b/drivers/platform/x86/toshiba_acpi.c
index 53ef565378ef..556f2cc99bad 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -186,7 +186,6 @@ struct toshiba_acpi_dev {
unsigned int video_supported:1;
unsigned int fan_supported:1;
unsigned int system_event_supported:1;
-   unsigned int ntfy_supported:1;
unsigned int info_supported:1;
unsigned int tr_backlight_supported:1;
unsigned int kbd_illum_supported:1;
@@ -2756,9 +2755,23 @@ static void toshiba_acpi_process_hotkeys(struct 
toshiba_acpi_dev *dev)
}
 }
 
-static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
+static void toshiba_acpi_cancel_hotkey_work(void *data)
+{
+   struct work_struct *hotkey_work = data;
+
+   cancel_work_sync(hotkey_work);
+}
+
+static void toshiba_acpi_i8042_remove_filter(void *data)
+{
+   i8042_remove_filter(toshiba_acpi_i8042_filter);
+}
+
+static int toshiba_acpi_setup_keyboard(struct device *parent,
+  struct toshiba_acpi_dev *dev)
 {
const struct key_entry *keymap = toshiba_acpi_keymap;
+   bool ntfy_supported = false;
acpi_handle ec_handle;
int error;
 
@@ -2779,7 +2792,7 @@ static int toshiba_acpi_setup_keyboard(struct 
toshiba_acpi_dev *dev)
if (toshiba_hotkey_event_type_get(dev, >hotkey_event_type))
pr_notice("Unable to query Hotkey Event Type\n");
 
-   dev->hotkey_dev = input_allocate_device();
+   dev->hotkey_dev = devm_input_allocate_device(parent);
if (!dev->hotkey_dev)
return -ENOMEM;
 
@@ -2798,7 +2811,7 @@ static int toshiba_acpi_setup_keyboard(struct 
toshiba_acpi_dev *dev)
dev->hotkey_event_type);
error = sparse_keymap_setup(dev->hotkey_dev, keymap, NULL);
if (error)
-   goto err_free_dev;
+   goto err_null_dev;
 
/*
 * For some machines the SCI responsible for providing hotkey
@@ -2811,13 +2824,19 @@ static int toshiba_acpi_setup_keyboard(struct 
toshiba_acpi_dev *dev)
if (ec_handle && acpi_has_method(ec_handle, "NTFY")) {
INIT_WORK(>hotkey_work, toshiba_acpi_hotkey_work);
 
+   error = devm_add_action(parent,
+   toshiba_acpi_cancel_hotkey_work,
+   >hotkey_work);
+   if (error)
+   return error;
+
error = i8042_install_filter(toshiba_acpi_i8042_filter);
if (error) {
pr_err("Error installing key filter\n");
-   goto err_free_dev;
+   return error;
}
 
-   dev->ntfy_supported = 1;
+   ntfy_supported = true;
}
 
/*
@@ -2840,13 +2859,19 @@ static int toshiba_acpi_setup_keyboard(struct 
toshiba_acpi_dev *dev)
goto err_remove_filter;
}
 
+   if (ntfy_supported) {
+   error = devm_add_action(parent,
+   toshiba_acpi_i8042_remove_filter,
+   NULL);
+   goto err_remove_filter;
+   }
+
return 0;
 
- err_remove_filter:
-   if (dev->ntfy_supported)
+err_remove_filter:
+   if (ntfy_supported)
i8042_remove_filter(toshiba_acpi_i8042_filter);
- err_free_dev:
-   input_free_device(dev->hotkey_dev);
+err_null_dev:
dev->hotkey_dev = NULL;
return error;
 }
@@ -2974,14 +2999,6 @@ static int toshiba_acpi_remove(struct acpi_device 
*acpi_dev)
sysfs_remove_group(>acpi_dev->dev.kobj,
   _attr_group);
 
-   if (dev->ntfy_supported) {
-   i8042_remove_filter(toshiba_acpi_i8042_filter);
-   cancel_work_sync(>hotkey_work);
-   }
-
-   if (dev->hotkey_dev)
-   input_unregister_device(dev->hotkey_dev);

[PATCH 01/10] platform/x86: toshiba_acpi: bind life-time of toshiba_acpi_dev to parent

2021-03-24 Thread Alexandru Ardelean
The 'toshiba_acpi_dev' object is allocated first and free'd last. We can
bind it's life-time to the parent ACPI device object. This is a first step
in using more device-managed allocated functions for this.

The main intent is to try to convert the IIO framework to export only
device-managed functions (i.e. devm_iio_device_alloc() and
devm_iio_device_register()). It's still not 100% sure that this is
possible, but for now, this is the process of taking it slowly in that
direction.

Signed-off-by: Alexandru Ardelean 
---
 drivers/platform/x86/toshiba_acpi.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/platform/x86/toshiba_acpi.c 
b/drivers/platform/x86/toshiba_acpi.c
index fa7232ad8c39..6d298810b7bf 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -2998,8 +2998,6 @@ static int toshiba_acpi_remove(struct acpi_device 
*acpi_dev)
if (toshiba_acpi)
toshiba_acpi = NULL;
 
-   kfree(dev);
-
return 0;
 }
 
@@ -3016,6 +3014,7 @@ static const char *find_hci_method(acpi_handle handle)
 
 static int toshiba_acpi_add(struct acpi_device *acpi_dev)
 {
+   struct device *parent = _dev->dev;
struct toshiba_acpi_dev *dev;
const char *hci_method;
u32 dummy;
@@ -3033,7 +3032,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
return -ENODEV;
}
 
-   dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+   dev = devm_kzalloc(parent, sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
dev->acpi_dev = acpi_dev;
@@ -3045,7 +3044,6 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
ret = misc_register(>miscdev);
if (ret) {
pr_err("Failed to register miscdevice\n");
-   kfree(dev);
return ret;
}
 
-- 
2.30.2



[PATCH 05/10] platform/x86: toshiba_acpi: register backlight with device-managed variant

2021-03-24 Thread Alexandru Ardelean
This change converts the registration of the backlight data with the
devm_backlight_device_register() function.
This way, the backlight_device_unregister() call is no longer required, and
the order of deregistration is made to be more symmetrical with the
registration order.

Signed-off-by: Alexandru Ardelean 
---
 drivers/platform/x86/toshiba_acpi.c | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/platform/x86/toshiba_acpi.c 
b/drivers/platform/x86/toshiba_acpi.c
index 556f2cc99bad..ada2a2d8c913 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -2876,7 +2876,8 @@ static int toshiba_acpi_setup_keyboard(struct device 
*parent,
return error;
 }
 
-static int toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev)
+static int toshiba_acpi_setup_backlight(struct device *parent,
+   struct toshiba_acpi_dev *dev)
 {
struct backlight_properties props;
int brightness;
@@ -2924,11 +2925,12 @@ static int toshiba_acpi_setup_backlight(struct 
toshiba_acpi_dev *dev)
if (dev->tr_backlight_supported)
props.max_brightness++;
 
-   dev->backlight_dev = backlight_device_register("toshiba",
-  >acpi_dev->dev,
-  dev,
-  _backlight_data,
-  );
+   dev->backlight_dev = devm_backlight_device_register(parent,
+   "toshiba",
+   >acpi_dev->dev,
+   dev,
+   
_backlight_data,
+   );
if (IS_ERR(dev->backlight_dev)) {
ret = PTR_ERR(dev->backlight_dev);
pr_err("Could not register toshiba backlight device\n");
@@ -2999,8 +3001,6 @@ static int toshiba_acpi_remove(struct acpi_device 
*acpi_dev)
sysfs_remove_group(>acpi_dev->dev.kobj,
   _attr_group);
 
-   backlight_device_unregister(dev->backlight_dev);
-
led_classdev_unregister(>led_dev);
led_classdev_unregister(>kbd_led);
led_classdev_unregister(>eco_led);
@@ -3104,9 +3104,9 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
ret = get_tr_backlight_status(dev, );
dev->tr_backlight_supported = !ret;
 
-   ret = toshiba_acpi_setup_backlight(dev);
+   ret = toshiba_acpi_setup_backlight(parent, dev);
if (ret)
-   goto error;
+   return ret;
 
toshiba_illumination_available(dev);
if (dev->illumination_supported) {
-- 
2.30.2



[PATCH 02/10] platform/x86: toshiba_acpi: use devm_add_action_or_reset() for singleton clear

2021-03-24 Thread Alexandru Ardelean
The only reason to do this is to enforce the ordering of deinitialization,
when the conversion of the device-managed functions is done.

The singleton object should be cleared right before it is free'd.

Signed-off-by: Alexandru Ardelean 
---
 drivers/platform/x86/toshiba_acpi.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/platform/x86/toshiba_acpi.c 
b/drivers/platform/x86/toshiba_acpi.c
index 6d298810b7bf..c5284601bc2a 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -2995,9 +2995,6 @@ static int toshiba_acpi_remove(struct acpi_device 
*acpi_dev)
rfkill_destroy(dev->wwan_rfk);
}
 
-   if (toshiba_acpi)
-   toshiba_acpi = NULL;
-
return 0;
 }
 
@@ -3012,6 +3009,11 @@ static const char *find_hci_method(acpi_handle handle)
return NULL;
 }
 
+static void toshiba_acpi_singleton_clear(void *data)
+{
+   toshiba_acpi = NULL;
+}
+
 static int toshiba_acpi_add(struct acpi_device *acpi_dev)
 {
struct device *parent = _dev->dev;
@@ -3035,6 +3037,13 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
dev = devm_kzalloc(parent, sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
+
+   ret = devm_add_action_or_reset(parent,
+  toshiba_acpi_singleton_clear,
+  NULL);
+   if (ret)
+   return ret;
+
dev->acpi_dev = acpi_dev;
dev->method_hci = hci_method;
dev->miscdev.minor = MISC_DYNAMIC_MINOR;
-- 
2.30.2



[PATCH 03/10] platform/x86: toshiba_acpi: bind registration of miscdev object to parent

2021-03-24 Thread Alexandru Ardelean
This change moves the registration of the Toshiba ACPI miscdev to be
handled by the devm_add_action_or_reset() hook. This way, the miscdev will
be unregistered when the reference count of the parent device object goes
to zero.

This also changes the order of cleanup in toshiba_acpi_remove(), where the
miscdev was deregistered first. Now it will be deregistered right before
the toshiba_acpi_dev object is free'd.

Signed-off-by: Alexandru Ardelean 
---
 drivers/platform/x86/toshiba_acpi.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/x86/toshiba_acpi.c 
b/drivers/platform/x86/toshiba_acpi.c
index c5284601bc2a..53ef565378ef 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -2963,8 +2963,6 @@ static int toshiba_acpi_remove(struct acpi_device 
*acpi_dev)
 {
struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
 
-   misc_deregister(>miscdev);
-
remove_toshiba_proc_entries(dev);
 
if (dev->accelerometer_supported && dev->indio_dev) {
@@ -3014,6 +3012,13 @@ static void toshiba_acpi_singleton_clear(void *data)
toshiba_acpi = NULL;
 }
 
+static void toshiba_acpi_misc_deregister(void *data)
+{
+   struct miscdevice *miscdev = data;
+
+   misc_deregister(miscdev);
+}
+
 static int toshiba_acpi_add(struct acpi_device *acpi_dev)
 {
struct device *parent = _dev->dev;
@@ -3056,6 +3061,11 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
return ret;
}
 
+   ret = devm_add_action_or_reset(parent, toshiba_acpi_misc_deregister,
+  >miscdev);
+   if (ret)
+   return ret;
+
acpi_dev->driver_data = dev;
dev_set_drvdata(_dev->dev, dev);
 
-- 
2.30.2



[PATCH 00/10] platform/x86: toshiba_acpi: move acpi add/remove to device-managed routines

2021-03-24 Thread Alexandru Ardelean
This changeset tries to do a conversion of the toshiba_acpi driver to use
only device-managed routines. The driver registers as a singleton, so no
more than one device can be registered at a time.

My main intent here is to try to convert the iio_device_alloc() and
iio_device_register() to their devm_ variants.

Usually, when converting a registration call to device-managed variant, the
init order must be preserved. And the deregistration order must be a mirror
of the registration (in reverse order).

This change tries to do that, by using devm_ variants where available and
devm_add_action_or_reset() where this isn't possible.
Some deregistration ordering is changed, because it wasn't exactly
mirroring (in reverse) the init order.

For the IIO subsystem, the toshiba_acpi driver is the only user of
iio_device_alloc(). If this changeset is accepted (after discussion), I
will propose to remove the iio_device_alloc() function.

While I admit this may look like an overzealous effort to use devm_
everywhere (in IIO at least), for me it's a fun/interesting excercise.

Alexandru Ardelean (10):
  platform/x86: toshiba_acpi: bind life-time of toshiba_acpi_dev to
parent
  platform/x86: toshiba_acpi: use devm_add_action_or_reset() for
singleton clear
  platform/x86: toshiba_acpi: bind registration of miscdev object to
parent
  platform/x86: toshiba_acpi: use device-managed functions for input
device
  platform/x86: toshiba_acpi: register backlight with device-managed
variant
  platform/x86: toshiba_acpi: use devm_led_classdev_register() for LEDs
  platform/x86: toshiba_acpi: use device-managed functions for
accelerometer
  platform/x86: toshiba_acpi: use device-managed for wwan_rfkill
management
  platform/x86: toshiba_acpi: use device-managed for sysfs removal
  platform/x86: toshiba_acpi: bind proc entries creation to parent

 drivers/platform/x86/toshiba_acpi.c | 249 +---
 1 file changed, 150 insertions(+), 99 deletions(-)

-- 
2.30.2



Re: [PATCH v6 20/24] iio: buffer: add ioctl() to support opening extra buffers for IIO device

2021-03-24 Thread Alexandru Ardelean
On Tue, Mar 23, 2021 at 1:35 PM Jonathan Cameron
 wrote:
>
> On Tue, 23 Mar 2021 11:51:04 +0200
> Alexandru Ardelean  wrote:
>
> > On Sun, Mar 21, 2021 at 7:37 PM Jonathan Cameron
> >  wrote:
> > >
> > > On Sat, 20 Mar 2021 17:41:00 +
> > > Jonathan Cameron  wrote:
> > >
> > > > On Mon, 15 Mar 2021 09:58:08 +
> > > > "Sa, Nuno"  wrote:
> > > >
> > > > > > -Original Message-
> > > > > > From: Alexandru Ardelean 
> > > > > > Sent: Saturday, March 6, 2021 6:01 PM
> > > > > > To: Jonathan Cameron 
> > > > > > Cc: Lars-Peter Clausen ; Ardelean,
> > > > > > Alexandru ; LKML  > > > > > ker...@vger.kernel.org>; linux-iio ;
> > > > > > Hennerich, Michael ; Jonathan
> > > > > > Cameron ; Sa, Nuno ;
> > > > > > Bogdan, Dragos 
> > > > > > Subject: Re: [PATCH v6 20/24] iio: buffer: add ioctl() to support 
> > > > > > opening
> > > > > > extra buffers for IIO device
> > > > > >
> > > > > > [External]
> > > > > >
> > > > > > On Sun, Feb 28, 2021 at 9:00 PM Jonathan Cameron
> > > > > >  wrote:
> > > > > > >
> > > > > > > On Sun, 28 Feb 2021 16:51:51 +0100
> > > > > > > Lars-Peter Clausen  wrote:
> > > > > > >
> > > > > > > > On 2/28/21 3:34 PM, Jonathan Cameron wrote:
> > > > > > > > > On Sun, 28 Feb 2021 09:51:38 +0100
> > > > > > > > > Lars-Peter Clausen  wrote:
> > > > > > > > >
> > > > > > > > >> On 2/15/21 11:40 AM, Alexandru Ardelean wrote:
> > > > > > > > >>> With this change, an ioctl() call is added to open a 
> > > > > > > > >>> character
> > > > > > device for a
> > > > > > > > >>> buffer. The ioctl() number is 'i' 0x91, which follows the
> > > > > > > > >>> IIO_GET_EVENT_FD_IOCTL ioctl.
> > > > > > > > >>>
> > > > > > > > >>> The ioctl() will return an FD for the requested buffer 
> > > > > > > > >>> index.
> > > > > > The indexes
> > > > > > > > >>> are the same from the /sys/iio/devices/iio:deviceX/bufferY
> > > > > > (i.e. the Y
> > > > > > > > >>> variable).
> > > > > > > > >>>
> > > > > > > > >>> Since there doesn't seem to be a sane way to return the FD 
> > > > > > > > >>> for
> > > > > > buffer0 to
> > > > > > > > >>> be the same FD for the /dev/iio:deviceX, this ioctl() will 
> > > > > > > > >>> return
> > > > > > another
> > > > > > > > >>> FD for buffer0 (or the first buffer). This duplicate FD 
> > > > > > > > >>> will be
> > > > > > able to
> > > > > > > > >>> access the same buffer object (for buffer0) as accessing
> > > > > > directly the
> > > > > > > > >>> /dev/iio:deviceX chardev.
> > > > > > > > >>>
> > > > > > > > >>> Also, there is no IIO_BUFFER_GET_BUFFER_COUNT ioctl()
> > > > > > implemented, as the
> > > > > > > > >>> index for each buffer (and the count) can be deduced from
> > > > > > the
> > > > > > > > >>> '/sys/bus/iio/devices/iio:deviceX/bufferY' folders (i.e the
> > > > > > number of
> > > > > > > > >>> bufferY folders).
> > > > > > > > >>>
> > > > > > > > >>> Used following C code to test this:
> > > > > > > > >>> ---
> > > > > > > > >>>
> > > > > > > > >>>#include 
> > > > > > > > >>>#include 
> > > > > > > > >>>#include 
> > > > > > > > >>>#include 

Re: [PATCH v6 20/24] iio: buffer: add ioctl() to support opening extra buffers for IIO device

2021-03-23 Thread Alexandru Ardelean
On Sun, Mar 21, 2021 at 7:37 PM Jonathan Cameron
 wrote:
>
> On Sat, 20 Mar 2021 17:41:00 +
> Jonathan Cameron  wrote:
>
> > On Mon, 15 Mar 2021 09:58:08 +
> > "Sa, Nuno"  wrote:
> >
> > > > -Original Message-
> > > > From: Alexandru Ardelean 
> > > > Sent: Saturday, March 6, 2021 6:01 PM
> > > > To: Jonathan Cameron 
> > > > Cc: Lars-Peter Clausen ; Ardelean,
> > > > Alexandru ; LKML  > > > ker...@vger.kernel.org>; linux-iio ;
> > > > Hennerich, Michael ; Jonathan
> > > > Cameron ; Sa, Nuno ;
> > > > Bogdan, Dragos 
> > > > Subject: Re: [PATCH v6 20/24] iio: buffer: add ioctl() to support 
> > > > opening
> > > > extra buffers for IIO device
> > > >
> > > > [External]
> > > >
> > > > On Sun, Feb 28, 2021 at 9:00 PM Jonathan Cameron
> > > >  wrote:
> > > > >
> > > > > On Sun, 28 Feb 2021 16:51:51 +0100
> > > > > Lars-Peter Clausen  wrote:
> > > > >
> > > > > > On 2/28/21 3:34 PM, Jonathan Cameron wrote:
> > > > > > > On Sun, 28 Feb 2021 09:51:38 +0100
> > > > > > > Lars-Peter Clausen  wrote:
> > > > > > >
> > > > > > >> On 2/15/21 11:40 AM, Alexandru Ardelean wrote:
> > > > > > >>> With this change, an ioctl() call is added to open a character
> > > > device for a
> > > > > > >>> buffer. The ioctl() number is 'i' 0x91, which follows the
> > > > > > >>> IIO_GET_EVENT_FD_IOCTL ioctl.
> > > > > > >>>
> > > > > > >>> The ioctl() will return an FD for the requested buffer index.
> > > > The indexes
> > > > > > >>> are the same from the /sys/iio/devices/iio:deviceX/bufferY
> > > > (i.e. the Y
> > > > > > >>> variable).
> > > > > > >>>
> > > > > > >>> Since there doesn't seem to be a sane way to return the FD for
> > > > buffer0 to
> > > > > > >>> be the same FD for the /dev/iio:deviceX, this ioctl() will 
> > > > > > >>> return
> > > > another
> > > > > > >>> FD for buffer0 (or the first buffer). This duplicate FD will be
> > > > able to
> > > > > > >>> access the same buffer object (for buffer0) as accessing
> > > > directly the
> > > > > > >>> /dev/iio:deviceX chardev.
> > > > > > >>>
> > > > > > >>> Also, there is no IIO_BUFFER_GET_BUFFER_COUNT ioctl()
> > > > implemented, as the
> > > > > > >>> index for each buffer (and the count) can be deduced from
> > > > the
> > > > > > >>> '/sys/bus/iio/devices/iio:deviceX/bufferY' folders (i.e the
> > > > number of
> > > > > > >>> bufferY folders).
> > > > > > >>>
> > > > > > >>> Used following C code to test this:
> > > > > > >>> ---
> > > > > > >>>
> > > > > > >>>#include 
> > > > > > >>>#include 
> > > > > > >>>#include 
> > > > > > >>>#include 
> > > > > > >>>#include  > > > > > >>>#include 
> > > > > > >>>
> > > > > > >>>#define IIO_BUFFER_GET_FD_IOCTL  _IOWR('i', 0x91, int)
> > > > > > >>>
> > > > > > >>> int main(int argc, char *argv[])
> > > > > > >>> {
> > > > > > >>>   int fd;
> > > > > > >>>   int fd1;
> > > > > > >>>   int ret;
> > > > > > >>>
> > > > > > >>>   if ((fd = open("/dev/iio:device0", O_RDWR))<0) {
> > > > > > >>>   fprintf(stderr, "Error open() %d errno 
> > > > > > >>> %d\n",fd,
> > > > errno);
> > > > > > >>>   return -1;
> > > > > &g

[PATCH] iio: buffer: return 0 for buffer getfd ioctl handler

2021-03-22 Thread Alexandru Ardelean
As Lars pointed out, we could either return the FD vs memcpy-ing it to the
userspace data object.

However, this comment exposed a bug. We should return 0 or negative from
these ioctl() handlers. Because an ioctl() handler can also return
IIO_IOCTL_UNHANDLED (which is positive 1), which means that the ioctl()
handler doesn't support this ioctl number. Positive 1 could also be a valid
FD number in some corner cases.

The reason we did this is to be able to differentiate between an error
code and an unsupported ioctl number; for unsupported ioctl numbers, the
main loop should keep going.

Maybe we should change this to a higher negative number, to avoid such
cases when/if we add more ioctl() handlers.

Cc: Lars-Peter Clausen 
Fixes: f73f7f4da5818 ("iio: buffer: add ioctl() to support opening extra 
buffers for IIO device")
Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/industrialio-buffer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iio/industrialio-buffer.c 
b/drivers/iio/industrialio-buffer.c
index ee5aab9d4a23..d7a15c9bb0cd 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -1442,7 +1442,7 @@ static long iio_device_buffer_getfd(struct iio_dev 
*indio_dev, unsigned long arg
goto error_free_ib;
}
 
-   return fd;
+   return 0;
 
 error_free_ib:
kfree(ib);
-- 
2.30.2



Re: linux-next: Tree for Mar 16 (AD9467 & ADI_AXI_ADC)

2021-03-17 Thread Alexandru Ardelean
On Tue, Mar 16, 2021 at 11:20 PM Randy Dunlap  wrote:
>
> On 3/15/21 9:50 PM, Stephen Rothwell wrote:
> > Hi all,
> >
> > News: there will be no linux-next release on Friday this week.
> >
> > Warning: Some of the branches in linux-next are still based on v5.12-rc1,
> > so please be careful if you are trying to bisect a bug.
> >
> > News: if your -next included tree is based on Linus' tree tag
> > v5.12-rc1{,-dontuse} (or somewhere between v5.11 and that tag), please
> > consider rebasing it onto v5.12-rc2. Also, please check any branches
> > merged into your branch.
> >
> > Changes since 20210315:
>
>
> on i386 or x86_64:
>
> WARNING: unmet direct dependencies detected for ADI_AXI_ADC
>   Depends on [n]: IIO [=y] && HAS_IOMEM [=y] && OF [=n]
>   Selected by [y]:
>   - AD9467 [=y] && IIO [=y] && SPI [=y]
>
>
> AD9467 should not select ADI_AXI_ADC when OF is not enabled,
> so possibly AD9467 should depend on OF.

Hmm, this becomes a bit complicated.
We got here because we needed to add a depends on HAS_IOMEM for the
ADI_AXI_ADC (due to the s390 arch).
Maybe a better fix would be for AD9467 to depend on ADI_AXI_ADC.
The AD9467 driver can't function without the ADI_AXI_ADC driver.

It is a little early to move this to a "high-speed ADC" subgroup.

>
>
> Full randconfig file is attached.
>
>
> --
> ~Randy
> Reported-by: Randy Dunlap 


Re: [PATCH] iio:dac:max517: Use devm_iio_device_register()

2021-03-14 Thread Alexandru Ardelean
On Sun, Mar 14, 2021 at 11:34 AM Mugilraj Dhavachelvan
 wrote:
>
> Use devm_iio_device_register() to avoid remove function and
> drop explicit call to iio_device_unregister().
>
> Signed-off-by: Mugilraj Dhavachelvan 
> ---
>  drivers/iio/dac/max517.c | 9 +
>  1 file changed, 1 insertion(+), 8 deletions(-)
>
> diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c
> index 7e01838ef4d0..5f72f126162d 100644
> --- a/drivers/iio/dac/max517.c
> +++ b/drivers/iio/dac/max517.c
> @@ -189,13 +189,7 @@ static int max517_probe(struct i2c_client *client,
> data->vref_mv[chan] = platform_data->vref_mv[chan];
> }
>
> -   return iio_device_register(indio_dev);
> -}
> -

In this case you can also remove the line with
 i2c_set_clientdata(client, indio_dev);

A lot of times, when functions like i2c_get_clientdata() get removed,
the i2c_set_clientdata() function becomes useless.
i.e. it stores some data that will never be used in the lifetime of the driver.

It isn't always the case that you can do that; so, some care must be
taken to avoid special cases.
But in this case, you can remove the i2c_set_clientdata() call.


> -static int max517_remove(struct i2c_client *client)
> -{
> -   iio_device_unregister(i2c_get_clientdata(client));
> -   return 0;
> +   return devm_iio_device_register(>dev, indio_dev);
>  }
>
>  static const struct i2c_device_id max517_id[] = {
> @@ -214,7 +208,6 @@ static struct i2c_driver max517_driver = {
> .pm = _pm_ops,
> },
> .probe  = max517_probe,
> -   .remove = max517_remove,
> .id_table   = max517_id,
>  };
>  module_i2c_driver(max517_driver);
> --
> 2.25.1
>


Re: [PATCH] iio: kfifo: add devm_iio_triggered_buffer_setup_ext variant

2021-03-11 Thread Alexandru Ardelean
On Thu, Mar 11, 2021 at 11:14 AM Alexandru Ardelean
 wrote:
>
> This is similar to the {devm_}iio_triggered_buffer_setup_ext variants added
> via commit 5164c7889857 ("iio: triggered-buffer: add
> {devm_}iio_triggered_buffer_setup_ext variants").
>
> These can be used to pass extra buffer attributes to the buffer object.
> This is a bit of temporary mechanism (hopefully) so that drivers that want
> to allocate a kfifo buffer with extra buffer attributes, don't need to
> include 'buffer_impl.h' directly. This can also become an API function (in
> it's own right, unfortunately), but it may be a little less bad vs drivers
> having to include 'buffer_impl.h'.
>
> So, far the drivers that want to pass buffer attributes, all have to do
> with some HW FIFO attributes, so there may be a chance of unifying them
> into IIO core somehow (as some standard API). But, until that happens, we
> just need to let them register their HW FIFO attributes directly (without
> having to let them include 'buffer_impl.h' directly).
>

This isn't required anymore.
Please disregard.
Apologies for the noise

> Signed-off-by: Alexandru Ardelean 
> ---
>
> Related to the discussion here:
>   
> https://lore.kernel.org/linux-iio/CA+U=Dspk3cWjiiRmDrgfHAY6houjr-KtSD3u4BssUcb=c2u...@mail.gmail.com/T/#mcfda9d6cb6426caefa4a5db6d634640bfdbe328e
>
>  drivers/iio/buffer/kfifo_buf.c | 16 ++--
>  include/linux/iio/kfifo_buf.h  | 12 
>  2 files changed, 18 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/iio/buffer/kfifo_buf.c b/drivers/iio/buffer/kfifo_buf.c
> index 4ecfa0ec3016..13eea2e11cbc 100644
> --- a/drivers/iio/buffer/kfifo_buf.c
> +++ b/drivers/iio/buffer/kfifo_buf.c
> @@ -206,22 +206,24 @@ static struct iio_buffer 
> *devm_iio_kfifo_allocate(struct device *dev)
>  }
>
>  /**
> - * devm_iio_kfifo_buffer_setup - Allocate a kfifo buffer & attach it to an 
> IIO device
> + * devm_iio_kfifo_buffer_setup_ext - Allocate a kfifo buffer & attach it to 
> an IIO device
>   * @dev: Device object to which to attach the life-time of this kfifo buffer
>   * @indio_dev: The device the buffer should be attached to
>   * @mode_flags: The mode flags for this buffer (INDIO_BUFFER_SOFTWARE and/or
>   * INDIO_BUFFER_TRIGGERED).
>   * @setup_ops: The setup_ops required to configure the HW part of the buffer 
> (optional)
> + * @buffer_attrs: Extra sysfs buffer attributes for this IIO buffer
>   *
>   * This function allocates a kfifo buffer via devm_iio_kfifo_allocate() and
>   * attaches it to the IIO device via iio_device_attach_buffer().
>   * This is meant to be a bit of a short-hand/helper function as there are a 
> few
>   * drivers that seem to do this.
>   */
> -int devm_iio_kfifo_buffer_setup(struct device *dev,
> -   struct iio_dev *indio_dev,
> -   int mode_flags,
> -   const struct iio_buffer_setup_ops *setup_ops)
> +int devm_iio_kfifo_buffer_setup_ext(struct device *dev,
> +   struct iio_dev *indio_dev,
> +   int mode_flags,
> +   const struct iio_buffer_setup_ops 
> *setup_ops,
> +   const struct attribute **buffer_attrs)
>  {
> struct iio_buffer *buffer;
>
> @@ -237,8 +239,10 @@ int devm_iio_kfifo_buffer_setup(struct device *dev,
> indio_dev->modes |= mode_flags;
> indio_dev->setup_ops = setup_ops;
>
> +   buffer->attrs = buffer_attrs;
> +
> return iio_device_attach_buffer(indio_dev, buffer);
>  }
> -EXPORT_SYMBOL_GPL(devm_iio_kfifo_buffer_setup);
> +EXPORT_SYMBOL_GPL(devm_iio_kfifo_buffer_setup_ext);
>
>  MODULE_LICENSE("GPL");
> diff --git a/include/linux/iio/kfifo_buf.h b/include/linux/iio/kfifo_buf.h
> index 1522896e1daf..ccd2ceae7b25 100644
> --- a/include/linux/iio/kfifo_buf.h
> +++ b/include/linux/iio/kfifo_buf.h
> @@ -10,9 +10,13 @@ struct device;
>  struct iio_buffer *iio_kfifo_allocate(void);
>  void iio_kfifo_free(struct iio_buffer *r);
>
> -int devm_iio_kfifo_buffer_setup(struct device *dev,
> -   struct iio_dev *indio_dev,
> -   int mode_flags,
> -   const struct iio_buffer_setup_ops *setup_ops);
> +int devm_iio_kfifo_buffer_setup_ext(struct device *dev,
> +   struct iio_dev *indio_dev,
> +   int mode_flags,
> +   const struct iio_buffer_setup_ops 
> *setup_ops,
> +   const struct attribute **buffer_attrs);
> +
> +#define devm_iio_kfifo_buffer_setup(dev, indio_dev, mode_flags, setup_ops)   
>   \
> +   devm_iio_kfifo_buffer_setup_ext((dev), (indio_dev), (mode_flags), 
> (setup_ops), NULL)
>
>  #endif
> --
> 2.29.2
>


[PATCH] iio: kfifo: add devm_iio_triggered_buffer_setup_ext variant

2021-03-11 Thread Alexandru Ardelean
This is similar to the {devm_}iio_triggered_buffer_setup_ext variants added
via commit 5164c7889857 ("iio: triggered-buffer: add
{devm_}iio_triggered_buffer_setup_ext variants").

These can be used to pass extra buffer attributes to the buffer object.
This is a bit of temporary mechanism (hopefully) so that drivers that want
to allocate a kfifo buffer with extra buffer attributes, don't need to
include 'buffer_impl.h' directly. This can also become an API function (in
it's own right, unfortunately), but it may be a little less bad vs drivers
having to include 'buffer_impl.h'.

So, far the drivers that want to pass buffer attributes, all have to do
with some HW FIFO attributes, so there may be a chance of unifying them
into IIO core somehow (as some standard API). But, until that happens, we
just need to let them register their HW FIFO attributes directly (without
having to let them include 'buffer_impl.h' directly).

Signed-off-by: Alexandru Ardelean 
---

Related to the discussion here:
  
https://lore.kernel.org/linux-iio/CA+U=Dspk3cWjiiRmDrgfHAY6houjr-KtSD3u4BssUcb=c2u...@mail.gmail.com/T/#mcfda9d6cb6426caefa4a5db6d634640bfdbe328e

 drivers/iio/buffer/kfifo_buf.c | 16 ++--
 include/linux/iio/kfifo_buf.h  | 12 
 2 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/drivers/iio/buffer/kfifo_buf.c b/drivers/iio/buffer/kfifo_buf.c
index 4ecfa0ec3016..13eea2e11cbc 100644
--- a/drivers/iio/buffer/kfifo_buf.c
+++ b/drivers/iio/buffer/kfifo_buf.c
@@ -206,22 +206,24 @@ static struct iio_buffer *devm_iio_kfifo_allocate(struct 
device *dev)
 }
 
 /**
- * devm_iio_kfifo_buffer_setup - Allocate a kfifo buffer & attach it to an IIO 
device
+ * devm_iio_kfifo_buffer_setup_ext - Allocate a kfifo buffer & attach it to an 
IIO device
  * @dev: Device object to which to attach the life-time of this kfifo buffer
  * @indio_dev: The device the buffer should be attached to
  * @mode_flags: The mode flags for this buffer (INDIO_BUFFER_SOFTWARE and/or
  * INDIO_BUFFER_TRIGGERED).
  * @setup_ops: The setup_ops required to configure the HW part of the buffer 
(optional)
+ * @buffer_attrs: Extra sysfs buffer attributes for this IIO buffer
  *
  * This function allocates a kfifo buffer via devm_iio_kfifo_allocate() and
  * attaches it to the IIO device via iio_device_attach_buffer().
  * This is meant to be a bit of a short-hand/helper function as there are a few
  * drivers that seem to do this.
  */
-int devm_iio_kfifo_buffer_setup(struct device *dev,
-   struct iio_dev *indio_dev,
-   int mode_flags,
-   const struct iio_buffer_setup_ops *setup_ops)
+int devm_iio_kfifo_buffer_setup_ext(struct device *dev,
+   struct iio_dev *indio_dev,
+   int mode_flags,
+   const struct iio_buffer_setup_ops 
*setup_ops,
+   const struct attribute **buffer_attrs)
 {
struct iio_buffer *buffer;
 
@@ -237,8 +239,10 @@ int devm_iio_kfifo_buffer_setup(struct device *dev,
indio_dev->modes |= mode_flags;
indio_dev->setup_ops = setup_ops;
 
+   buffer->attrs = buffer_attrs;
+
return iio_device_attach_buffer(indio_dev, buffer);
 }
-EXPORT_SYMBOL_GPL(devm_iio_kfifo_buffer_setup);
+EXPORT_SYMBOL_GPL(devm_iio_kfifo_buffer_setup_ext);
 
 MODULE_LICENSE("GPL");
diff --git a/include/linux/iio/kfifo_buf.h b/include/linux/iio/kfifo_buf.h
index 1522896e1daf..ccd2ceae7b25 100644
--- a/include/linux/iio/kfifo_buf.h
+++ b/include/linux/iio/kfifo_buf.h
@@ -10,9 +10,13 @@ struct device;
 struct iio_buffer *iio_kfifo_allocate(void);
 void iio_kfifo_free(struct iio_buffer *r);
 
-int devm_iio_kfifo_buffer_setup(struct device *dev,
-   struct iio_dev *indio_dev,
-   int mode_flags,
-   const struct iio_buffer_setup_ops *setup_ops);
+int devm_iio_kfifo_buffer_setup_ext(struct device *dev,
+   struct iio_dev *indio_dev,
+   int mode_flags,
+   const struct iio_buffer_setup_ops 
*setup_ops,
+   const struct attribute **buffer_attrs);
+
+#define devm_iio_kfifo_buffer_setup(dev, indio_dev, mode_flags, setup_ops) 
\
+   devm_iio_kfifo_buffer_setup_ext((dev), (indio_dev), (mode_flags), 
(setup_ops), NULL)
 
 #endif
-- 
2.29.2



[PATCH] staging: iio: ad9834: convert to device-managed functions in probe

2021-03-10 Thread Alexandru Ardelean
This change converts the driver to use device-managed functions in the
probe function. For the clock and regulator disable, some
devm_add_action_or_reset() calls are required, and then
devm_iio_device_register() function can be used register the IIO device.

The final aim here would be for IIO to export only the device-managed
functions of it's API. That's a long way to go and this a small step in
that direction.

Signed-off-by: Alexandru Ardelean 
---
 drivers/staging/iio/frequency/ad9834.c | 64 +-
 1 file changed, 31 insertions(+), 33 deletions(-)

diff --git a/drivers/staging/iio/frequency/ad9834.c 
b/drivers/staging/iio/frequency/ad9834.c
index 262c3590e64e..b063cfd0e0e1 100644
--- a/drivers/staging/iio/frequency/ad9834.c
+++ b/drivers/staging/iio/frequency/ad9834.c
@@ -390,6 +390,20 @@ static const struct iio_info ad9833_info = {
.attrs = _attribute_group,
 };
 
+static void ad9834_disable_reg(void *data)
+{
+   struct regulator *reg = data;
+
+   regulator_disable(reg);
+}
+
+static void ad9834_disable_clk(void *data)
+{
+   struct clk *clk = data;
+
+   clk_disable_unprepare(clk);
+}
+
 static int ad9834_probe(struct spi_device *spi)
 {
struct ad9834_state *st;
@@ -407,26 +421,33 @@ static int ad9834_probe(struct spi_device *spi)
return ret;
}
 
+   ret = devm_add_action_or_reset(>dev, ad9834_disable_reg, reg);
+   if (ret)
+   return ret;
+
indio_dev = devm_iio_device_alloc(>dev, sizeof(*st));
if (!indio_dev) {
ret = -ENOMEM;
-   goto error_disable_reg;
+   return ret;
}
-   spi_set_drvdata(spi, indio_dev);
st = iio_priv(indio_dev);
mutex_init(>lock);
st->mclk = devm_clk_get(>dev, NULL);
if (IS_ERR(st->mclk)) {
ret = PTR_ERR(st->mclk);
-   goto error_disable_reg;
+   return ret;
}
 
ret = clk_prepare_enable(st->mclk);
if (ret) {
dev_err(>dev, "Failed to enable master clock\n");
-   goto error_disable_reg;
+   return ret;
}
 
+   ret = devm_add_action_or_reset(>dev, ad9834_disable_clk, st->mclk);
+   if (ret)
+   return ret;
+
st->spi = spi;
st->devid = spi_get_device_id(spi)->driver_data;
st->reg = reg;
@@ -470,48 +491,26 @@ static int ad9834_probe(struct spi_device *spi)
ret = spi_sync(st->spi, >msg);
if (ret) {
dev_err(>dev, "device init failed\n");
-   goto error_clock_unprepare;
+   return ret;
}
 
ret = ad9834_write_frequency(st, AD9834_REG_FREQ0, 100);
if (ret)
-   goto error_clock_unprepare;
+   return ret;
 
ret = ad9834_write_frequency(st, AD9834_REG_FREQ1, 500);
if (ret)
-   goto error_clock_unprepare;
+   return ret;
 
ret = ad9834_write_phase(st, AD9834_REG_PHASE0, 512);
if (ret)
-   goto error_clock_unprepare;
+   return ret;
 
ret = ad9834_write_phase(st, AD9834_REG_PHASE1, 1024);
if (ret)
-   goto error_clock_unprepare;
-
-   ret = iio_device_register(indio_dev);
-   if (ret)
-   goto error_clock_unprepare;
-
-   return 0;
-error_clock_unprepare:
-   clk_disable_unprepare(st->mclk);
-error_disable_reg:
-   regulator_disable(reg);
-
-   return ret;
-}
-
-static int ad9834_remove(struct spi_device *spi)
-{
-   struct iio_dev *indio_dev = spi_get_drvdata(spi);
-   struct ad9834_state *st = iio_priv(indio_dev);
-
-   iio_device_unregister(indio_dev);
-   clk_disable_unprepare(st->mclk);
-   regulator_disable(st->reg);
+   return ret;
 
-   return 0;
+   return devm_iio_device_register(>dev, indio_dev);
 }
 
 static const struct spi_device_id ad9834_id[] = {
@@ -539,7 +538,6 @@ static struct spi_driver ad9834_driver = {
.of_match_table = ad9834_of_match
},
.probe  = ad9834_probe,
-   .remove = ad9834_remove,
.id_table   = ad9834_id,
 };
 module_spi_driver(ad9834_driver);
-- 
2.29.2



[PATCH] iio: temperature: tmp007: use device-managed functions in probe

2021-03-10 Thread Alexandru Ardelean
This change converts the driver to use device-managed functions in the
probe function. The power-down call is handled now via a
devm_add_action_or_reset() hook, and then devm_iio_device_register() can be
used to register the IIO device.

The final aim here would be for IIO to export only the device-managed
functions of it's API. That's a long way to go and this a small step in
that direction.

Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/temperature/tmp007.c | 36 +---
 1 file changed, 15 insertions(+), 21 deletions(-)

diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c
index ad2b35c65548..b422371a4674 100644
--- a/drivers/iio/temperature/tmp007.c
+++ b/drivers/iio/temperature/tmp007.c
@@ -439,6 +439,13 @@ static bool tmp007_identify(struct i2c_client *client)
return (manf_id == TMP007_MANUFACTURER_MAGIC && dev_id == 
TMP007_DEVICE_MAGIC);
 }
 
+static void tmp007_powerdown_action_cb(void *priv)
+{
+   struct tmp007_data *data = priv;
+
+   tmp007_powerdown(data);
+}
+
 static int tmp007_probe(struct i2c_client *client,
const struct i2c_device_id *tmp007_id)
 {
@@ -489,6 +496,10 @@ static int tmp007_probe(struct i2c_client *client,
if (ret < 0)
return ret;
 
+   ret = devm_add_action_or_reset(>dev, 
tmp007_powerdown_action_cb, data);
+   if (ret)
+   return ret;
+
/*
 * Only the following flags can activate ALERT pin. Data 
conversion/validity flags
 * flags can still be polled for getting temperature data
@@ -502,7 +513,7 @@ static int tmp007_probe(struct i2c_client *client,
 
ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS_MASK);
if (ret < 0)
-   goto error_powerdown;
+   return ret;
 
data->status_mask = ret;
data->status_mask |= (TMP007_STATUS_OHF | TMP007_STATUS_OLF
@@ -510,7 +521,7 @@ static int tmp007_probe(struct i2c_client *client,
 
ret = i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK, 
data->status_mask);
if (ret < 0)
-   goto error_powerdown;
+   return ret;
 
if (client->irq) {
ret = devm_request_threaded_irq(>dev, client->irq,
@@ -519,27 +530,11 @@ static int tmp007_probe(struct i2c_client *client,
tmp007_id->name, indio_dev);
if (ret) {
dev_err(>dev, "irq request error %d\n", -ret);
-   goto error_powerdown;
+   return ret;
}
}
 
-   return iio_device_register(indio_dev);
-
-error_powerdown:
-   tmp007_powerdown(data);
-
-   return ret;
-}
-
-static int tmp007_remove(struct i2c_client *client)
-{
-   struct iio_dev *indio_dev = i2c_get_clientdata(client);
-   struct tmp007_data *data = iio_priv(indio_dev);
-
-   iio_device_unregister(indio_dev);
-   tmp007_powerdown(data);
-
-   return 0;
+   return devm_iio_device_register(>dev, indio_dev);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -582,7 +577,6 @@ static struct i2c_driver tmp007_driver = {
.pm = _pm_ops,
},
.probe  = tmp007_probe,
-   .remove = tmp007_remove,
.id_table   = tmp007_id,
 };
 module_i2c_driver(tmp007_driver);
-- 
2.29.2



Re: [PATCH 01/10] spi: spi-axi-spi-engine: remove usage of delay_usecs

2021-03-09 Thread Alexandru Ardelean
On Mon, 8 Mar 2021 at 18:42, Lars-Peter Clausen  wrote:
>
> On 3/8/21 3:54 PM, Alexandru Ardelean wrote:
> > The 'delay_usecs' field was handled for backwards compatibility in case
> > there were some users that still configured SPI delay transfers with
> > this field.
> >
> > They should all be removed by now.
> >
> > Signed-off-by: Alexandru Ardelean 
> > ---
> >   drivers/spi/spi-axi-spi-engine.c | 12 
> >   1 file changed, 4 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/spi/spi-axi-spi-engine.c 
> > b/drivers/spi/spi-axi-spi-engine.c
> > index af86e6d6e16b..80c3e38f5c1b 100644
> > --- a/drivers/spi/spi-axi-spi-engine.c
> > +++ b/drivers/spi/spi-axi-spi-engine.c
> > @@ -170,14 +170,10 @@ static void spi_engine_gen_sleep(struct 
> > spi_engine_program *p, bool dry,
> >   unsigned int t;
> >   int delay;
> >
> > - if (xfer->delay_usecs) {
> > - delay = xfer->delay_usecs;
> > - } else {
> > - delay = spi_delay_to_ns(>delay, xfer);
> > - if (delay < 0)
> > - return;
> > - delay /= 1000;
> > - }
> > + delay = spi_delay_to_ns(>delay, xfer);
> > + if (delay < 0)
> > + return;
>
> Bit of a nit, but this could be `delay <= 0` and then drop the check for
> `delay == 0` below.

hmm, that's a bit debatable, because the `delay == 0` check comes
after `delay /= 1000` ;
to do what you're suggesting, it would probably need a
DIV_ROUND_UP(delay, 1000) to make sure that even sub-microsecond
delays don't become zero;

if you're acking this suggestion i'll implement it;
i'll wait a few more days to see if there are any other acks or
complaints on the set before sending a V2;

btw: this new spi_delay struct supports delays in microseconds,
nanoseconds and clock cycles;
at some point it may be interesting to use a
`spi_delay_to_clk_cycles()` for this driver and other similar;

>
> > + delay /= 1000;
> >
> >   if (delay == 0)
> >   return;
>
>


[PATCH 09/10] spi: core: remove 'delay_usecs' field from spi_transfer

2021-03-08 Thread Alexandru Ardelean
The 'delay' field in the spi_transfer struct is meant to replace the
'delay_usecs' field. However some cleanup was required to remove the
uses of 'delay_usecs'. Now that it's been cleaned up, we can remove it
from the kernel tree.

Signed-off-by: Alexandru Ardelean 
---
 drivers/spi/spi.c   |  1 -
 include/linux/spi/spi.h | 12 
 2 files changed, 13 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index b08efe88ccd6..481427780162 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -3178,7 +3178,6 @@ struct spi_replaced_transfers *spi_replace_transfers(
/* clear cs_change and delay for all but the last */
if (i) {
xfer->cs_change = false;
-   xfer->delay_usecs = 0;
xfer->delay.value = 0;
}
}
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 592897fa4f03..ea1784a43267 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -832,9 +832,6 @@ extern void spi_res_release(struct spi_controller *ctlr,
  * @delay: delay to be introduced after this transfer before
  * (optionally) changing the chipselect status, then starting
  * the next transfer or completing this @spi_message.
- * @delay_usecs: microseconds to delay after this transfer before
- * (optionally) changing the chipselect status, then starting
- * the next transfer or completing this @spi_message.
  * @word_delay: inter word delay to be introduced after each word size
  * (set by bits_per_word) transmission.
  * @effective_speed_hz: the effective SCK-speed that was used to
@@ -946,7 +943,6 @@ struct spi_transfer {
 #defineSPI_NBITS_DUAL  0x02 /* 2bits transfer */
 #defineSPI_NBITS_QUAD  0x04 /* 4bits transfer */
u8  bits_per_word;
-   u16 delay_usecs;
struct spi_delaydelay;
struct spi_delaycs_change_delay;
struct spi_delayword_delay;
@@ -1060,14 +1056,6 @@ spi_transfer_del(struct spi_transfer *t)
 static inline int
 spi_transfer_delay_exec(struct spi_transfer *t)
 {
-   struct spi_delay d;
-
-   if (t->delay_usecs) {
-   d.value = t->delay_usecs;
-   d.unit = SPI_DELAY_UNIT_USECS;
-   return spi_delay_exec(, NULL);
-   }
-
return spi_delay_exec(>delay, t);
 }
 
-- 
2.29.2



[PATCH 08/10] spi: fsl-espi: remove usage of 'delay_usecs' field

2021-03-08 Thread Alexandru Ardelean
The 'delay_usecs' field is being removed from the spi_transfer struct.
This change removes it from the SPI FSL ESPI driver.

Signed-off-by: Alexandru Ardelean 
---
 drivers/spi/spi-fsl-espi.c | 17 +
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
index cf2b947c600e..f7066bef7b06 100644
--- a/drivers/spi/spi-fsl-espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -435,8 +435,7 @@ static int fsl_espi_trans(struct spi_message *m, struct 
spi_transfer *trans)
 static int fsl_espi_do_one_msg(struct spi_master *master,
   struct spi_message *m)
 {
-   unsigned int delay_usecs = 0, rx_nbits = 0;
-   unsigned int delay_nsecs = 0, delay_nsecs1 = 0;
+   unsigned int rx_nbits = 0, delay_nsecs = 0;
struct spi_transfer *t, trans = {};
int ret;
 
@@ -445,16 +444,10 @@ static int fsl_espi_do_one_msg(struct spi_master *master,
goto out;
 
list_for_each_entry(t, >transfers, transfer_list) {
-   if (t->delay_usecs) {
-   if (t->delay_usecs > delay_usecs) {
-   delay_usecs = t->delay_usecs;
-   delay_nsecs = delay_usecs * 1000;
-   }
-   } else {
-   delay_nsecs1 = spi_delay_to_ns(>delay, t);
-   if (delay_nsecs1 > delay_nsecs)
-   delay_nsecs = delay_nsecs1;
-   }
+   unsigned int delay = spi_delay_to_ns(>delay, t);
+
+   if (delay > delay_nsecs)
+   delay_nsecs = delay;
if (t->rx_nbits > rx_nbits)
rx_nbits = t->rx_nbits;
}
-- 
2.29.2



[PATCH 10/10] spi: docs: update info about 'delay_usecs'

2021-03-08 Thread Alexandru Ardelean
The 'delay_usecs' field is no longer present on the spi_transfer struct.
This change updates the doc to mention the usage of the (relatively) new
'delay' field.

Signed-off-by: Alexandru Ardelean 
---
 Documentation/spi/spi-summary.rst | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/Documentation/spi/spi-summary.rst 
b/Documentation/spi/spi-summary.rst
index f1daffe10d78..d4239025461d 100644
--- a/Documentation/spi/spi-summary.rst
+++ b/Documentation/spi/spi-summary.rst
@@ -411,8 +411,11 @@ any more such messages.
 duplex (one pointer is NULL) transfers;
 
   + optionally defining short delays after transfers ... using
-the spi_transfer.delay_usecs setting (this delay can be the
-only protocol effect, if the buffer length is zero);
+the spi_transfer.delay.value setting (this delay can be the
+only protocol effect, if the buffer length is zero) ...
+when specifying this delay the default spi_transfer.delay.unit
+is microseconds, however this can be adjusted to clock cycles
+or nanoseconds if needed;
 
   + whether the chipselect becomes inactive after a transfer and
 any delay ... by using the spi_transfer.cs_change flag;
-- 
2.29.2



[PATCH 00/10] spi: finalize 'delay_usecs' removal/transition

2021-03-08 Thread Alexandru Ardelean
A while back I started the introduction of the 'spi_delay' data type:
  
https://lore.kernel.org/linux-spi/20190926105147.7839-1-alexandru.ardel...@analog.com/

Users of the 'delay_usecs' were removed from drivers.

Now it's time to remove the 'delay_usecs' from the SPI subsystem and use
only the 'delay' field.

This changeset adapts all SPI drivers to do without 'delay_usecs'.
Additionally, for greybus we need to adapt it to use the 'delay' in
nano-seconds and convert it to micro-seconds.

Alexandru Ardelean (10):
  spi: spi-axi-spi-engine: remove usage of delay_usecs
  spi: bcm63xx-spi: don't check 'delay_usecs' field
  spi: spi-bcm-qspi: replace 'delay_usecs' with 'delay.value' check
  spi: spi-sh: replace 'delay_usecs' with 'delay.value' in pr_debug
  spi: spi-tegra20-flash: don't check 'delay_usecs' field for spi
transfer
  staging: greybus: spilib: use 'spi_delay_to_ns' for getting xfer delay
  spi: spi-falcon: remove check for 'delay_usecs'
  spi: fsl-espi: remove usage of 'delay_usecs' field
  spi: core: remove 'delay_usecs' field from spi_transfer
  spi: docs: update info about 'delay_usecs'

 Documentation/spi/spi-summary.rst |  7 +--
 drivers/spi/spi-axi-spi-engine.c  | 12 
 drivers/spi/spi-bcm-qspi.c|  2 +-
 drivers/spi/spi-bcm63xx.c |  2 +-
 drivers/spi/spi-falcon.c  |  2 +-
 drivers/spi/spi-fsl-espi.c| 17 +
 drivers/spi/spi-sh.c  |  4 ++--
 drivers/spi/spi-tegra20-sflash.c  |  3 +--
 drivers/spi/spi.c |  1 -
 drivers/staging/greybus/spilib.c  |  5 -
 include/linux/spi/spi.h   | 12 
 11 files changed, 24 insertions(+), 43 deletions(-)

-- 
2.29.2



[PATCH 04/10] spi: spi-sh: replace 'delay_usecs' with 'delay.value' in pr_debug

2021-03-08 Thread Alexandru Ardelean
The 'delay_usecs' field is going away. The replacement for it is the
'delay' field. So, we should print the 'delay.value' value instead.

Signed-off-by: Alexandru Ardelean 
---
 drivers/spi/spi-sh.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-sh.c b/drivers/spi/spi-sh.c
index 15123a8f41e1..45f304935332 100644
--- a/drivers/spi/spi-sh.c
+++ b/drivers/spi/spi-sh.c
@@ -290,8 +290,8 @@ static void spi_sh_work(struct work_struct *work)
list_for_each_entry(t, >transfers, transfer_list) {
pr_debug("tx_buf = %p, rx_buf = %p\n",
t->tx_buf, t->rx_buf);
-   pr_debug("len = %d, delay_usecs = %d\n",
-   t->len, t->delay_usecs);
+   pr_debug("len = %d, delay.value = %d\n",
+   t->len, t->delay.value);
 
if (t->tx_buf) {
ret = spi_sh_send(ss, mesg, t);
-- 
2.29.2



[PATCH 06/10] staging: greybus: spilib: use 'spi_delay_to_ns' for getting xfer delay

2021-03-08 Thread Alexandru Ardelean
The intent is the removal of the 'delay_usecs' field from the
spi_transfer struct, as there is a 'delay' field that does the same
thing.

The spi_delay_to_ns() can be used to get the transfer delay. It works by
using the 'delay_usecs' field first (if it is non-zero), and finally
uses the 'delay' field.

Since the 'delay_usecs' field is going away, this change makes use of the
spi_delay_to_ns() function. This also means dividing the return value of
the function by 1000, to convert it to microseconds.
To prevent any potential faults when converting to microseconds and since
the result of spi_delay_to_ns() is int, the delay is being computed in 32
bits and then clamped between 0 & U16_MAX.

Signed-off-by: Alexandru Ardelean 
---
 drivers/staging/greybus/spilib.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c
index 672d540d3365..30655153df6a 100644
--- a/drivers/staging/greybus/spilib.c
+++ b/drivers/staging/greybus/spilib.c
@@ -245,6 +245,7 @@ static struct gb_operation *gb_spi_operation_create(struct 
gb_spilib *spi,
/* Fill in the transfers array */
xfer = spi->first_xfer;
while (msg->state != GB_SPI_STATE_OP_DONE) {
+   int xfer_delay;
if (xfer == spi->last_xfer)
xfer_len = spi->last_xfer_size;
else
@@ -259,7 +260,9 @@ static struct gb_operation *gb_spi_operation_create(struct 
gb_spilib *spi,
 
gb_xfer->speed_hz = cpu_to_le32(xfer->speed_hz);
gb_xfer->len = cpu_to_le32(xfer_len);
-   gb_xfer->delay_usecs = cpu_to_le16(xfer->delay_usecs);
+   xfer_delay = spi_delay_to_ns(>delay, xfer) / 1000;
+   xfer_delay = clamp_t(u16, xfer_delay, 0, U16_MAX);
+   gb_xfer->delay_usecs = cpu_to_le16(xfer_delay);
gb_xfer->cs_change = xfer->cs_change;
gb_xfer->bits_per_word = xfer->bits_per_word;
 
-- 
2.29.2



[PATCH 05/10] spi: spi-tegra20-flash: don't check 'delay_usecs' field for spi transfer

2021-03-08 Thread Alexandru Ardelean
The 'delay_usecs' field was handled for backwards compatibility in case
there were some users that still configured SPI delay transfers with
this field.

They should all be removed by now. So we can remove the 'delay_usecs'
handling in this driver.

Signed-off-by: Alexandru Ardelean 
---
 drivers/spi/spi-tegra20-sflash.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c
index cfb7de737937..2888d8a8dc6d 100644
--- a/drivers/spi/spi-tegra20-sflash.c
+++ b/drivers/spi/spi-tegra20-sflash.c
@@ -341,8 +341,7 @@ static int tegra_sflash_transfer_one_message(struct 
spi_master *master,
goto exit;
}
msg->actual_length += xfer->len;
-   if (xfer->cs_change &&
-   (xfer->delay_usecs || xfer->delay.value)) {
+   if (xfer->cs_change && xfer->delay.value) {
tegra_sflash_writel(tsd, tsd->def_command_reg,
SPI_COMMAND);
spi_transfer_delay_exec(xfer);
-- 
2.29.2



[PATCH 07/10] spi: spi-falcon: remove check for 'delay_usecs'

2021-03-08 Thread Alexandru Ardelean
The 'delay_usecs' field is being removed from the spi_transfer struct.
This change removes it from the SPI Falcon driver.

Signed-off-by: Alexandru Ardelean 
---
 drivers/spi/spi-falcon.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-falcon.c b/drivers/spi/spi-falcon.c
index d3336a63f462..a7d4dffac66b 100644
--- a/drivers/spi/spi-falcon.c
+++ b/drivers/spi/spi-falcon.c
@@ -377,7 +377,7 @@ static int falcon_sflash_xfer_one(struct spi_master *master,
 
m->actual_length += t->len;
 
-   WARN_ON(t->delay_usecs || t->delay.value || t->cs_change);
+   WARN_ON(t->delay.value || t->cs_change);
spi_flags = 0;
}
 
-- 
2.29.2



[PATCH 02/10] spi: bcm63xx-spi: don't check 'delay_usecs' field

2021-03-08 Thread Alexandru Ardelean
The 'delay_usecs' field was handled for backwards compatibility in case
there were some users that still configured SPI delay transfers with
this field.

They should all be removed by now.

Signed-off-by: Alexandru Ardelean 
---
 drivers/spi/spi-bcm63xx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c
index d08bb7600150..80fa0ef8909c 100644
--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -369,7 +369,7 @@ static int bcm63xx_spi_transfer_one(struct spi_master 
*master,
}
 
/* CS will be deasserted directly after transfer */
-   if (t->delay_usecs || t->delay.value) {
+   if (t->delay.value) {
dev_err(>dev, "unable to keep CS asserted after 
transfer\n");
status = -EINVAL;
goto exit;
-- 
2.29.2



[PATCH 03/10] spi: spi-bcm-qspi: replace 'delay_usecs' with 'delay.value' check

2021-03-08 Thread Alexandru Ardelean
The 'delay_usecs' field is going away. The replacement for it is the
'delay' field. So, we should check for 'delay.value' being non-zero.

Signed-off-by: Alexandru Ardelean 
---
 drivers/spi/spi-bcm-qspi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c
index 707fe3a5d8ef..a78e56f566dd 100644
--- a/drivers/spi/spi-bcm-qspi.c
+++ b/drivers/spi/spi-bcm-qspi.c
@@ -671,7 +671,7 @@ static int update_qspi_trans_byte_count(struct bcm_qspi 
*qspi,
if (qt->byte >= qt->trans->len) {
/* we're at the end of the spi_transfer */
/* in TX mode, need to pause for a delay or CS change */
-   if (qt->trans->delay_usecs &&
+   if (qt->trans->delay.value &&
(flags & TRANS_STATUS_BREAK_DELAY))
ret |= TRANS_STATUS_BREAK_DELAY;
if (qt->trans->cs_change &&
-- 
2.29.2



[PATCH 01/10] spi: spi-axi-spi-engine: remove usage of delay_usecs

2021-03-08 Thread Alexandru Ardelean
The 'delay_usecs' field was handled for backwards compatibility in case
there were some users that still configured SPI delay transfers with
this field.

They should all be removed by now.

Signed-off-by: Alexandru Ardelean 
---
 drivers/spi/spi-axi-spi-engine.c | 12 
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c
index af86e6d6e16b..80c3e38f5c1b 100644
--- a/drivers/spi/spi-axi-spi-engine.c
+++ b/drivers/spi/spi-axi-spi-engine.c
@@ -170,14 +170,10 @@ static void spi_engine_gen_sleep(struct 
spi_engine_program *p, bool dry,
unsigned int t;
int delay;
 
-   if (xfer->delay_usecs) {
-   delay = xfer->delay_usecs;
-   } else {
-   delay = spi_delay_to_ns(>delay, xfer);
-   if (delay < 0)
-   return;
-   delay /= 1000;
-   }
+   delay = spi_delay_to_ns(>delay, xfer);
+   if (delay < 0)
+   return;
+   delay /= 1000;
 
if (delay == 0)
return;
-- 
2.29.2



Re: [PATCH v2] iio: buffer: fix use-after-free for attached_buffers array

2021-03-07 Thread Alexandru Ardelean
On Sun, Mar 7, 2021 at 8:55 PM Alexandru Ardelean
 wrote:
>
> Thanks to Lars for finding this.
> The free of the 'attached_buffers' array should be done as late as
> possible. This change moves it to iio_buffers_put(), which looks like
> the best place for it, since it takes place right before the IIO device
> data is free'd.
> The free of this array will be handled by calling iio_device_free().
> The iio_buffers_put() function is renamed to iio_device_detach_buffers()
> since the role of this function changes a bit.
>
> It looks like this issue was ocurring on the error path of
> iio_buffers_alloc_sysfs_and_mask() and in
> iio_buffers_free_sysfs_and_mask()
>
> Added a comment in the doc-header of iio_device_attach_buffer() to
> mention how this will be free'd in case anyone is reading the code
> and becoming confused about it.
>
> Fixes: 36f3118c414d ("iio: buffer: introduce support for attaching more IIO 
> buffers")
> Reported-by: Lars-Peter Clausen 
> Signed-off-by: Alexandru Ardelean 
> ---

Forgot the changelog.

Changelog v1 -> v2:
* rename iio_buffers_put() -> iio_device_detach_buffers()

>  drivers/iio/iio_core.h| 4 ++--
>  drivers/iio/industrialio-buffer.c | 9 +
>  drivers/iio/industrialio-core.c   | 2 +-
>  3 files changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
> index 062fe16c6c49..8f4a9b264962 100644
> --- a/drivers/iio/iio_core.h
> +++ b/drivers/iio/iio_core.h
> @@ -77,7 +77,7 @@ void iio_buffers_free_sysfs_and_mask(struct iio_dev 
> *indio_dev);
>
>  void iio_disable_all_buffers(struct iio_dev *indio_dev);
>  void iio_buffer_wakeup_poll(struct iio_dev *indio_dev);
> -void iio_buffers_put(struct iio_dev *indio_dev);
> +void iio_device_detach_buffers(struct iio_dev *indio_dev);
>
>  #else
>
> @@ -93,7 +93,7 @@ static inline void iio_buffers_free_sysfs_and_mask(struct 
> iio_dev *indio_dev) {}
>
>  static inline void iio_disable_all_buffers(struct iio_dev *indio_dev) {}
>  static inline void iio_buffer_wakeup_poll(struct iio_dev *indio_dev) {}
> -static inline void iio_buffers_put(struct iio_dev *indio_dev) {}
> +static inline void iio_device_detach_buffers(struct iio_dev *indio_dev) {}
>
>  #endif
>
> diff --git a/drivers/iio/industrialio-buffer.c 
> b/drivers/iio/industrialio-buffer.c
> index 1a415e97174e..1ff7f731b044 100644
> --- a/drivers/iio/industrialio-buffer.c
> +++ b/drivers/iio/industrialio-buffer.c
> @@ -326,7 +326,7 @@ void iio_buffer_init(struct iio_buffer *buffer)
>  }
>  EXPORT_SYMBOL(iio_buffer_init);
>
> -void iio_buffers_put(struct iio_dev *indio_dev)
> +void iio_device_detach_buffers(struct iio_dev *indio_dev)
>  {
> struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
> struct iio_buffer *buffer;
> @@ -336,6 +336,8 @@ void iio_buffers_put(struct iio_dev *indio_dev)
> buffer = iio_dev_opaque->attached_buffers[i];
> iio_buffer_put(buffer);
> }
> +
> +   kfree(iio_dev_opaque->attached_buffers);
>  }
>
>  static ssize_t iio_show_scan_index(struct device *dev,
> @@ -1764,7 +1766,6 @@ int iio_buffers_alloc_sysfs_and_mask(struct iio_dev 
> *indio_dev)
> buffer = iio_dev_opaque->attached_buffers[unwind_idx];
> __iio_buffer_free_sysfs_and_mask(buffer);
> }
> -   kfree(iio_dev_opaque->attached_buffers);
> return ret;
>  }
>
> @@ -1786,8 +1787,6 @@ void iio_buffers_free_sysfs_and_mask(struct iio_dev 
> *indio_dev)
> buffer = iio_dev_opaque->attached_buffers[i];
> __iio_buffer_free_sysfs_and_mask(buffer);
> }
> -
> -   kfree(iio_dev_opaque->attached_buffers);
>  }
>
>  /**
> @@ -2062,6 +2061,8 @@ static int iio_buffer_mmap(struct file *filep, struct 
> vm_area_struct *vma)
>   * This function attaches a buffer to a IIO device. The buffer stays 
> attached to
>   * the device until the device is freed. For legacy reasons, the first 
> attached
>   * buffer will also be assigned to 'indio_dev->buffer'.
> + * The array allocated here, will be free'd via the 
> iio_device_detach_buffers()
> + * call which is handled by the iio_device_free().
>   */
>  int iio_device_attach_buffer(struct iio_dev *indio_dev,
>  struct iio_buffer *buffer)
> diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
> index d74fbac908df..3be5f75c2846 100644
> --- a/drivers/iio/industrialio-core.c
> +++ b/drivers/iio/industrialio-core.c
> @@ -1587,7 +1587,7 @@ static void iio_dev_release(struct device *device)
> iio_device_unregister_eventset(indio_dev);
> iio_device_unregister_sysfs(indio_dev);
>
> -   iio_buffers_put(indio_dev);
> +   iio_device_detach_buffers(indio_dev);
>
> ida_simple_remove(_ida, indio_dev->id);
> kfree(iio_dev_opaque);
> --
> 2.25.1
>


[PATCH v2] iio: buffer: fix use-after-free for attached_buffers array

2021-03-07 Thread Alexandru Ardelean
Thanks to Lars for finding this.
The free of the 'attached_buffers' array should be done as late as
possible. This change moves it to iio_buffers_put(), which looks like
the best place for it, since it takes place right before the IIO device
data is free'd.
The free of this array will be handled by calling iio_device_free().
The iio_buffers_put() function is renamed to iio_device_detach_buffers()
since the role of this function changes a bit.

It looks like this issue was ocurring on the error path of
iio_buffers_alloc_sysfs_and_mask() and in
iio_buffers_free_sysfs_and_mask()

Added a comment in the doc-header of iio_device_attach_buffer() to
mention how this will be free'd in case anyone is reading the code
and becoming confused about it.

Fixes: 36f3118c414d ("iio: buffer: introduce support for attaching more IIO 
buffers")
Reported-by: Lars-Peter Clausen 
Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/iio_core.h| 4 ++--
 drivers/iio/industrialio-buffer.c | 9 +
 drivers/iio/industrialio-core.c   | 2 +-
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
index 062fe16c6c49..8f4a9b264962 100644
--- a/drivers/iio/iio_core.h
+++ b/drivers/iio/iio_core.h
@@ -77,7 +77,7 @@ void iio_buffers_free_sysfs_and_mask(struct iio_dev 
*indio_dev);
 
 void iio_disable_all_buffers(struct iio_dev *indio_dev);
 void iio_buffer_wakeup_poll(struct iio_dev *indio_dev);
-void iio_buffers_put(struct iio_dev *indio_dev);
+void iio_device_detach_buffers(struct iio_dev *indio_dev);
 
 #else
 
@@ -93,7 +93,7 @@ static inline void iio_buffers_free_sysfs_and_mask(struct 
iio_dev *indio_dev) {}
 
 static inline void iio_disable_all_buffers(struct iio_dev *indio_dev) {}
 static inline void iio_buffer_wakeup_poll(struct iio_dev *indio_dev) {}
-static inline void iio_buffers_put(struct iio_dev *indio_dev) {}
+static inline void iio_device_detach_buffers(struct iio_dev *indio_dev) {}
 
 #endif
 
diff --git a/drivers/iio/industrialio-buffer.c 
b/drivers/iio/industrialio-buffer.c
index 1a415e97174e..1ff7f731b044 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -326,7 +326,7 @@ void iio_buffer_init(struct iio_buffer *buffer)
 }
 EXPORT_SYMBOL(iio_buffer_init);
 
-void iio_buffers_put(struct iio_dev *indio_dev)
+void iio_device_detach_buffers(struct iio_dev *indio_dev)
 {
struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
struct iio_buffer *buffer;
@@ -336,6 +336,8 @@ void iio_buffers_put(struct iio_dev *indio_dev)
buffer = iio_dev_opaque->attached_buffers[i];
iio_buffer_put(buffer);
}
+
+   kfree(iio_dev_opaque->attached_buffers);
 }
 
 static ssize_t iio_show_scan_index(struct device *dev,
@@ -1764,7 +1766,6 @@ int iio_buffers_alloc_sysfs_and_mask(struct iio_dev 
*indio_dev)
buffer = iio_dev_opaque->attached_buffers[unwind_idx];
__iio_buffer_free_sysfs_and_mask(buffer);
}
-   kfree(iio_dev_opaque->attached_buffers);
return ret;
 }
 
@@ -1786,8 +1787,6 @@ void iio_buffers_free_sysfs_and_mask(struct iio_dev 
*indio_dev)
buffer = iio_dev_opaque->attached_buffers[i];
__iio_buffer_free_sysfs_and_mask(buffer);
}
-
-   kfree(iio_dev_opaque->attached_buffers);
 }
 
 /**
@@ -2062,6 +2061,8 @@ static int iio_buffer_mmap(struct file *filep, struct 
vm_area_struct *vma)
  * This function attaches a buffer to a IIO device. The buffer stays attached 
to
  * the device until the device is freed. For legacy reasons, the first attached
  * buffer will also be assigned to 'indio_dev->buffer'.
+ * The array allocated here, will be free'd via the iio_device_detach_buffers()
+ * call which is handled by the iio_device_free().
  */
 int iio_device_attach_buffer(struct iio_dev *indio_dev,
 struct iio_buffer *buffer)
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index d74fbac908df..3be5f75c2846 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -1587,7 +1587,7 @@ static void iio_dev_release(struct device *device)
iio_device_unregister_eventset(indio_dev);
iio_device_unregister_sysfs(indio_dev);
 
-   iio_buffers_put(indio_dev);
+   iio_device_detach_buffers(indio_dev);
 
ida_simple_remove(_ida, indio_dev->id);
kfree(iio_dev_opaque);
-- 
2.25.1



Re: [PATCH 1/2] iio: cros_ec: do an early exit if not physical_device case

2021-03-07 Thread Alexandru Ardelean
On Sun, Mar 7, 2021 at 1:59 PM Jonathan Cameron  wrote:
>
> On Tue, 2 Mar 2021 11:46:06 +0100
> Enric Balletbo i Serra  wrote:
>
> > Hi all,
> >
> > On 21/2/21 17:29, Jonathan Cameron wrote:
> > > On Mon, 23 Nov 2020 16:40:16 +0200
> > > Alexandru Ardelean  wrote:
> > >
> > >> This whole code-block was put under one big if() condition/block.
> > >> This change does an early return if the 'physical_device' boolean is 
> > >> false,
> > >> thus unindenting the block by one level.
> > >>
> > >> No other functional change has been done.
> > >>
> > >> Signed-off-by: Alexandru Ardelean 
> > > @Gwendal, others  This series from Alex has been outstanding for a while
> > > but may well still apply.
> > > Ideally looking for an ack.
> > >
> >
> > This looks good to me.
> >
> > Acked-by: Enric Balletbo i Serra 
>
> Hi Enric, Ack or both patches or just this one?
>
> @Alex, series needs a rebase.  I'm not totally sure what's changed.
> If you don't get to it I'll do it at somepoint but unlikely to
> be terribly soon!

It's likely that it's that iio_device_attach_buffer() went away and
the block got replaced by devm_iio_kfifo_buffer_setup().
I'll re-spin it.
I dropped this set from my main work branch because I didn't know if
it was forgotten, and rebasing it with every change on
devm_iio_kfifo_buffer_setup() and
devm_iio_triggered_buffer_setup_ext() became annoying.
But it shouldn't be hard to re-spin.

>
> Jonathan
>
> >
> > Thanks,
> >  Enric
> >
> > > Thanks,
> > >
> > > Jonathan
> > >
> > >> ---
> > >>  .../cros_ec_sensors/cros_ec_sensors_core.c| 161 +-
> > >>  1 file changed, 81 insertions(+), 80 deletions(-)
> > >>
> > >> diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c 
> > >> b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
> > >> index 5c6c4e6fec9b..9470014936f2 100644
> > >> --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
> > >> +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
> > >> @@ -287,89 +287,90 @@ int cros_ec_sensors_core_init(struct 
> > >> platform_device *pdev,
> > >>
> > >>indio_dev->name = pdev->name;
> > >>
> > >> -  if (physical_device) {
> > >> -  state->param.cmd = MOTIONSENSE_CMD_INFO;
> > >> -  state->param.info.sensor_num = sensor_platform->sensor_num;
> > >> -  ret = cros_ec_motion_send_host_cmd(state, 0);
> > >> -  if (ret) {
> > >> -  dev_warn(dev, "Can not access sensor info\n");
> > >> +  if (!physical_device)
> > >> +  return 0;
> > >> +
> > >> +  state->param.cmd = MOTIONSENSE_CMD_INFO;
> > >> +  state->param.info.sensor_num = sensor_platform->sensor_num;
> > >> +  ret = cros_ec_motion_send_host_cmd(state, 0);
> > >> +  if (ret) {
> > >> +  dev_warn(dev, "Can not access sensor info\n");
> > >> +  return ret;
> > >> +  }
> > >> +  state->type = state->resp->info.type;
> > >> +  state->loc = state->resp->info.location;
> > >> +
> > >> +  /* Set sign vector, only used for backward compatibility. */
> > >> +  memset(state->sign, 1, CROS_EC_SENSOR_MAX_AXIS);
> > >> +
> > >> +  for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
> > >> +  state->calib[i].scale = MOTION_SENSE_DEFAULT_SCALE;
> > >> +
> > >> +  /* 0 is a correct value used to stop the device */
> > >> +  if (state->msg->version < 3) {
> > >> +  get_default_min_max_freq(state->resp->info.type,
> > >> +   [1],
> > >> +   [2],
> > >> +   >fifo_max_event_count);
> > >> +  } else {
> > >> +  frequencies[1] = state->resp->info_3.min_frequency;
> > >> +  frequencies[2] = state->resp->info_3.max_frequency;
> > >> +  state->fifo_max_event_count =
> > >> +  state->resp->info_3.fifo_max_event_count;
> > >> +  }
> > >> +  for (i = 0; i < ARRAY_SIZE(frequencies); i++) {
> > >> + 

Re: [PATCH] iio: buffer: fix use-after-free for attached_buffers array

2021-03-07 Thread Alexandru Ardelean
On Sun, Mar 7, 2021 at 2:54 PM Lars-Peter Clausen  wrote:
>
> On 3/7/21 1:36 PM, Jonathan Cameron wrote:
> > On Sat,  6 Mar 2021 18:47:10 +0200
> > Alexandru Ardelean  wrote:
> >
> >> Thanks to Lars for finding this.
> >> The free of the 'attached_buffers' array should be done as late as
> >> possible. This change moves it to iio_buffers_put(), which looks like
> >> the best place for it, since it takes place right before the IIO device
> >> data is free'd.
> > It feels a bit wrong to do direct freeing of stuff in a _put() call
> > given that kind of implies nothing will happen without some reference
> > count dropping to 0.  We could think about renaming the function to
> > something like
> >
> > iio_buffers_put_and_free_array() but is a bit long winded.
> >
> > Otherwise, I'm fine with this but want to let it sit on list a tiny bit
> > longer before I take it as it's not totally trivial unlike the previous
> > one.
>
> Maybe to go with naming schema of iio_device_attach_buffer() call this
> function iio_device_detach_buffers(). We grab the reference in attach,
> and drop it in detach.

That actually sounds like it fits beautifully ( the
iio_device_detach_buffers() name ).
Thanks for the hint.

I'll send a V2.
I didn't consider more on the renaming of iio_buffers_put() because I
was a bit stressed by the silliness of the use-after-free bug.

Thanks
Alex

>
> - Lars
>


Re: [PATCH v6 20/24] iio: buffer: add ioctl() to support opening extra buffers for IIO device

2021-03-06 Thread Alexandru Ardelean
On Sun, Feb 28, 2021 at 9:00 PM Jonathan Cameron
 wrote:
>
> On Sun, 28 Feb 2021 16:51:51 +0100
> Lars-Peter Clausen  wrote:
>
> > On 2/28/21 3:34 PM, Jonathan Cameron wrote:
> > > On Sun, 28 Feb 2021 09:51:38 +0100
> > > Lars-Peter Clausen  wrote:
> > >
> > >> On 2/15/21 11:40 AM, Alexandru Ardelean wrote:
> > >>> With this change, an ioctl() call is added to open a character device 
> > >>> for a
> > >>> buffer. The ioctl() number is 'i' 0x91, which follows the
> > >>> IIO_GET_EVENT_FD_IOCTL ioctl.
> > >>>
> > >>> The ioctl() will return an FD for the requested buffer index. The 
> > >>> indexes
> > >>> are the same from the /sys/iio/devices/iio:deviceX/bufferY (i.e. the Y
> > >>> variable).
> > >>>
> > >>> Since there doesn't seem to be a sane way to return the FD for buffer0 
> > >>> to
> > >>> be the same FD for the /dev/iio:deviceX, this ioctl() will return 
> > >>> another
> > >>> FD for buffer0 (or the first buffer). This duplicate FD will be able to
> > >>> access the same buffer object (for buffer0) as accessing directly the
> > >>> /dev/iio:deviceX chardev.
> > >>>
> > >>> Also, there is no IIO_BUFFER_GET_BUFFER_COUNT ioctl() implemented, as 
> > >>> the
> > >>> index for each buffer (and the count) can be deduced from the
> > >>> '/sys/bus/iio/devices/iio:deviceX/bufferY' folders (i.e the number of
> > >>> bufferY folders).
> > >>>
> > >>> Used following C code to test this:
> > >>> ---
> > >>>
> > >>>#include 
> > >>>#include 
> > >>>#include 
> > >>>#include 
> > >>>#include  > >>>#include 
> > >>>
> > >>>#define IIO_BUFFER_GET_FD_IOCTL  _IOWR('i', 0x91, int)
> > >>>
> > >>> int main(int argc, char *argv[])
> > >>> {
> > >>>   int fd;
> > >>>   int fd1;
> > >>>   int ret;
> > >>>
> > >>>   if ((fd = open("/dev/iio:device0", O_RDWR))<0) {
> > >>>   fprintf(stderr, "Error open() %d errno %d\n",fd, 
> > >>> errno);
> > >>>   return -1;
> > >>>   }
> > >>>
> > >>>   fprintf(stderr, "Using FD %d\n", fd);
> > >>>
> > >>>   fd1 = atoi(argv[1]);
> > >>>
> > >>>   ret = ioctl(fd, IIO_BUFFER_GET_FD_IOCTL, );
> > >>>   if (ret < 0) {
> > >>>   fprintf(stderr, "Error for buffer %d ioctl() %d errno 
> > >>> %d\n", fd1, ret, errno);
> > >>>   close(fd);
> > >>>   return -1;
> > >>>   }
> > >>>
> > >>>   fprintf(stderr, "Got FD %d\n", fd1);
> > >>>
> > >>>   close(fd1);
> > >>>   close(fd);
> > >>>
> > >>>   return 0;
> > >>> }
> > >>> ---
> > >>>
> > >>> Results are:
> > >>> ---
> > >>># ./test 0
> > >>>Using FD 3
> > >>>Got FD 4
> > >>>
> > >>># ./test 1
> > >>>Using FD 3
> > >>>Got FD 4
> > >>>
> > >>># ./test 2
> > >>>Using FD 3
> > >>>Got FD 4
> > >>>
> > >>># ./test 3
> > >>>Using FD 3
> > >>>Got FD 4
> > >>>
> > >>># ls /sys/bus/iio/devices/iio\:device0
> > >>>buffer  buffer0  buffer1  buffer2  buffer3  dev
> > >>>in_voltage_sampling_frequency  in_voltage_scale
> > >>>in_voltage_scale_available
> > >>>name  of_node  power  scan_elements  subsystem  uevent
> > >>> ---
> > >>&

[PATCH] iio: buffer: fix use-after-free for attached_buffers array

2021-03-06 Thread Alexandru Ardelean
Thanks to Lars for finding this.
The free of the 'attached_buffers' array should be done as late as
possible. This change moves it to iio_buffers_put(), which looks like
the best place for it, since it takes place right before the IIO device
data is free'd.
The free of this array will be handled by calling iio_device_free().

It looks like this issue was ocurring on the error path of
iio_buffers_alloc_sysfs_and_mask() and in
iio_buffers_free_sysfs_and_mask()

Added a comment in the doc-header of iio_device_attach_buffer() to
mention how this will be free'd in case anyone is reading the code
and becoming confused about it.

Fixes: 36f3118c414d ("iio: buffer: introduce support for attaching more IIO 
buffers")
Reported-by: Lars-Peter Clausen 
Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/industrialio-buffer.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/industrialio-buffer.c 
b/drivers/iio/industrialio-buffer.c
index 1a415e97174e..3d0712651d43 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -336,6 +336,8 @@ void iio_buffers_put(struct iio_dev *indio_dev)
buffer = iio_dev_opaque->attached_buffers[i];
iio_buffer_put(buffer);
}
+
+   kfree(iio_dev_opaque->attached_buffers);
 }
 
 static ssize_t iio_show_scan_index(struct device *dev,
@@ -1764,7 +1766,6 @@ int iio_buffers_alloc_sysfs_and_mask(struct iio_dev 
*indio_dev)
buffer = iio_dev_opaque->attached_buffers[unwind_idx];
__iio_buffer_free_sysfs_and_mask(buffer);
}
-   kfree(iio_dev_opaque->attached_buffers);
return ret;
 }
 
@@ -1786,8 +1787,6 @@ void iio_buffers_free_sysfs_and_mask(struct iio_dev 
*indio_dev)
buffer = iio_dev_opaque->attached_buffers[i];
__iio_buffer_free_sysfs_and_mask(buffer);
}
-
-   kfree(iio_dev_opaque->attached_buffers);
 }
 
 /**
@@ -2062,6 +2061,8 @@ static int iio_buffer_mmap(struct file *filep, struct 
vm_area_struct *vma)
  * This function attaches a buffer to a IIO device. The buffer stays attached 
to
  * the device until the device is freed. For legacy reasons, the first attached
  * buffer will also be assigned to 'indio_dev->buffer'.
+ * The array allocated here, will be free'd via the iio_buffers_put() call,
+ * which is handled by the iio_device_free().
  */
 int iio_device_attach_buffer(struct iio_dev *indio_dev,
 struct iio_buffer *buffer)
-- 
2.25.1



[PATCH] iio: kfifo: mask flags without zero-check in devm_iio_kfifo_buffer_setup()

2021-03-06 Thread Alexandru Ardelean
As pointed by Lars, this doesn't require a zero-check. Also, while looking
at this a little closer at it (again), the masking can be done later, as
there is a zero-check for 'mode_flags' anyway, which returns -EINVAL. And
we only need the 'mode_flags' later in the logic.

This change is more of a tweak.

Fixes: ae9886d6aa29 ("iio: kfifo: add devm_iio_kfifo_buffer_setup() helper")
Cc: Lars-Peter Clausen 
Signed-off-by: Alexandru Ardelean 
---

Apologies for the late-ness of this.
I don't know if this makes sense to squash in the original, or to have
as a fix commit.
It is a bit messy now that the original is committed into the tree,
and now we're fixing/tweaking it.

 drivers/iio/buffer/kfifo_buf.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/buffer/kfifo_buf.c b/drivers/iio/buffer/kfifo_buf.c
index e8a434f84778..8e3a1a9e495c 100644
--- a/drivers/iio/buffer/kfifo_buf.c
+++ b/drivers/iio/buffer/kfifo_buf.c
@@ -275,9 +275,6 @@ int devm_iio_kfifo_buffer_setup(struct device *dev,
 {
struct iio_buffer *buffer;
 
-   if (mode_flags)
-   mode_flags &= kfifo_access_funcs.modes;
-
if (!mode_flags)
return -EINVAL;
 
@@ -285,6 +282,8 @@ int devm_iio_kfifo_buffer_setup(struct device *dev,
if (!buffer)
return -ENOMEM;
 
+   mode_flags &= kfifo_access_funcs.modes;
+
indio_dev->modes |= mode_flags;
indio_dev->setup_ops = setup_ops;
 
-- 
2.25.1



Re: [PATCH v6 20/24] iio: buffer: add ioctl() to support opening extra buffers for IIO device

2021-02-28 Thread Alexandru Ardelean
On Sun, Feb 28, 2021 at 5:54 PM Lars-Peter Clausen  wrote:
>
> On 2/28/21 3:34 PM, Jonathan Cameron wrote:
> > On Sun, 28 Feb 2021 09:51:38 +0100
> > Lars-Peter Clausen  wrote:
> >
> >> On 2/15/21 11:40 AM, Alexandru Ardelean wrote:
> >>> With this change, an ioctl() call is added to open a character device for 
> >>> a
> >>> buffer. The ioctl() number is 'i' 0x91, which follows the
> >>> IIO_GET_EVENT_FD_IOCTL ioctl.
> >>>
> >>> The ioctl() will return an FD for the requested buffer index. The indexes
> >>> are the same from the /sys/iio/devices/iio:deviceX/bufferY (i.e. the Y
> >>> variable).
> >>>
> >>> Since there doesn't seem to be a sane way to return the FD for buffer0 to
> >>> be the same FD for the /dev/iio:deviceX, this ioctl() will return another
> >>> FD for buffer0 (or the first buffer). This duplicate FD will be able to
> >>> access the same buffer object (for buffer0) as accessing directly the
> >>> /dev/iio:deviceX chardev.
> >>>
> >>> Also, there is no IIO_BUFFER_GET_BUFFER_COUNT ioctl() implemented, as the
> >>> index for each buffer (and the count) can be deduced from the
> >>> '/sys/bus/iio/devices/iio:deviceX/bufferY' folders (i.e the number of
> >>> bufferY folders).
> >>>
> >>> Used following C code to test this:
> >>> ---
> >>>
> >>>#include 
> >>>#include 
> >>>#include 
> >>>#include 
> >>>#include  >>>#include 
> >>>
> >>>#define IIO_BUFFER_GET_FD_IOCTL  _IOWR('i', 0x91, int)
> >>>
> >>> int main(int argc, char *argv[])
> >>> {
> >>>   int fd;
> >>>   int fd1;
> >>>   int ret;
> >>>
> >>>   if ((fd = open("/dev/iio:device0", O_RDWR))<0) {
> >>>   fprintf(stderr, "Error open() %d errno %d\n",fd, errno);
> >>>   return -1;
> >>>   }
> >>>
> >>>   fprintf(stderr, "Using FD %d\n", fd);
> >>>
> >>>   fd1 = atoi(argv[1]);
> >>>
> >>>   ret = ioctl(fd, IIO_BUFFER_GET_FD_IOCTL, );
> >>>   if (ret < 0) {
> >>>   fprintf(stderr, "Error for buffer %d ioctl() %d errno 
> >>> %d\n", fd1, ret, errno);
> >>>   close(fd);
> >>>   return -1;
> >>>   }
> >>>
> >>>   fprintf(stderr, "Got FD %d\n", fd1);
> >>>
> >>>   close(fd1);
> >>>   close(fd);
> >>>
> >>>   return 0;
> >>> }
> >>> ---
> >>>
> >>> Results are:
> >>> ---
> >>># ./test 0
> >>>Using FD 3
> >>>Got FD 4
> >>>
> >>># ./test 1
> >>>Using FD 3
> >>>Got FD 4
> >>>
> >>># ./test 2
> >>>Using FD 3
> >>>Got FD 4
> >>>
> >>># ./test 3
> >>>Using FD 3
> >>>Got FD 4
> >>>
> >>># ls /sys/bus/iio/devices/iio\:device0
> >>>buffer  buffer0  buffer1  buffer2  buffer3  dev
> >>>in_voltage_sampling_frequency  in_voltage_scale
> >>>in_voltage_scale_available
> >>>name  of_node  power  scan_elements  subsystem  uevent
> >>> ---
> >>>
> >>> iio:device0 has some fake kfifo buffers attached to an IIO device.
> >> For me there is one major problem with this approach. We only allow one
> >> application to open /dev/iio:deviceX at a time. This means we can't have
> >> different applications access different buffers of the same device. I
> >> believe this is a circuital feature.
> > Thats not quite true (I think - though I've not tested it).  What we don't
> > allow is for multiple processes to access them in an unaware fashion.
> > My assumption is we can rely on fork + fd passing via appropriate sockets.
> >
&

Re: [PATCH v6 20/24] iio: buffer: add ioctl() to support opening extra buffers for IIO device

2021-02-28 Thread Alexandru Ardelean
On Sun, Feb 28, 2021 at 9:58 AM Lars-Peter Clausen  wrote:
>
> On 2/15/21 11:40 AM, Alexandru Ardelean wrote:
> > [...]
> >   /**
> >* iio_buffer_wakeup_poll - Wakes up the buffer waitqueue
> >* @indio_dev: The IIO device
> > @@ -1343,6 +1371,96 @@ static void 
> > iio_buffer_unregister_legacy_sysfs_groups(struct iio_dev *indio_dev)
> >   kfree(iio_dev_opaque->legacy_scan_el_group.attrs);
> >   }
> >
> > [...]
> > +static long iio_device_buffer_getfd(struct iio_dev *indio_dev, unsigned 
> > long arg)
> > +{
> > + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
> > + int __user *ival = (int __user *)arg;
> > + struct iio_dev_buffer_pair *ib;
> > + struct iio_buffer *buffer;
> > + int fd, idx, ret;
> > +
> > + if (copy_from_user(, ival, sizeof(idx)))
> > + return -EFAULT;
>
> If we only want to pass an int, we can pass that directly, no need to
> pass it as a pointer.
>
> int fd = arg;

I guess I can simplify this a bit.

>
> > +
> > + if (idx >= iio_dev_opaque->attached_buffers_cnt)
> > + return -ENODEV;
> > +
> > + iio_device_get(indio_dev);
> > +
> > + buffer = iio_dev_opaque->attached_buffers[idx];
> > +
> > + if (test_and_set_bit(IIO_BUSY_BIT_POS, >flags)) {
> > + ret = -EBUSY;
> > + goto error_iio_dev_put;
> > + }
> > +
> > + ib = kzalloc(sizeof(*ib), GFP_KERNEL);
> > + if (!ib) {
> > + ret = -ENOMEM;
> > + goto error_clear_busy_bit;
> > + }
> > +
> > + ib->indio_dev = indio_dev;
> > + ib->buffer = buffer;
> > +
> > + fd = anon_inode_getfd("iio:buffer", _buffer_chrdev_fileops,
> > +   ib, O_RDWR | O_CLOEXEC);
>
> I wonder if we need to allow to pass flags, like e.g. O_NONBLOCK.
>
> Something like
> https://elixir.bootlin.com/linux/latest/source/fs/signalfd.c#L288

Umm, no idea.
I guess we could.
Would a syscall make more sense than an ioctl() here?
I guess for the ioctl() case we would need to change the type (of the
data) to some sort of

struct iio_buffer_get_fd {
  unsigned int buffer_idx;
  unsigned int fd_flags;
};

Or do we just let userspace use fcntl() to change flags to O_NONBLOCK ?

>
> > + if (fd < 0) {
> > + ret = fd;
> > + goto error_free_ib;
> > + }
> > +
> > + if (copy_to_user(ival, , sizeof(fd))) {
> > + put_unused_fd(fd);
> > + ret = -EFAULT;
> > + goto error_free_ib;
> > + }
>
> Here we copy back the fd, but also return it. Just return is probably
> enough.

Hmm.
Yes, it is a bit duplicate.
But it is a good point. Maybe we should return 0 to userspace.

>
> > +
> > + return fd;
> > +
> > +error_free_ib:
> > + kfree(ib);
> > +error_clear_busy_bit:
> > + clear_bit(IIO_BUSY_BIT_POS, >flags);
> > +error_iio_dev_put:
> > + iio_device_put(indio_dev);
> > + return ret;
> > +}
> > [...]
> > diff --git a/include/linux/iio/iio-opaque.h b/include/linux/iio/iio-opaque.h
> > index b6ebc04af3e7..32addd5e790e 100644
> > --- a/include/linux/iio/iio-opaque.h
> > +++ b/include/linux/iio/iio-opaque.h
> > @@ -9,6 +9,7 @@
> >* @event_interface:event chrdevs associated with 
> > interrupt lines
> >* @attached_buffers:   array of buffers statically attached 
> > by the driver
> >* @attached_buffers_cnt:   number of buffers in the array of statically 
> > attached buffers
> > + * @buffer_ioctl_handler:ioctl() handler for this IIO device's buffer 
> > interface
> >* @buffer_list:list of all buffers currently attached
> >* @channel_attr_list:  keep track of automatically created 
> > channel
> >*  attributes
> > @@ -28,6 +29,7 @@ struct iio_dev_opaque {
> >   struct iio_event_interface  *event_interface;
> >   struct iio_buffer   **attached_buffers;
> >   unsigned intattached_buffers_cnt;
> > + struct iio_ioctl_handler*buffer_ioctl_handler;
>
> Can we just embedded this struct so we do not have to
> allocate/deallocate it?

Unfortunately we can't.
The type of ' struct iio_ioctl_handler ' is stored in iio_core.h.
So, we don't know the size here. So we need to keep it as a pointer
and allocate it.
It is a bit of an unfortunate consequence of the design of this
generic ioctl() registering.

>
> >   struct list_headbuffer_list;
> >   struct list_headchannel_attr_list;
> >   struct attribute_group  chan_attr_group;
>
>


Re: [PATCH v6 02/24] iio: kfifo: add devm_iio_kfifo_buffer_setup() helper

2021-02-28 Thread Alexandru Ardelean
On Sun, Feb 28, 2021 at 10:08 AM Lars-Peter Clausen  wrote:
>
> On 2/15/21 11:40 AM, Alexandru Ardelean wrote:
> > +int devm_iio_kfifo_buffer_setup(struct device *dev,
> > + struct iio_dev *indio_dev,
> > + int mode_flags,
> > + const struct iio_buffer_setup_ops *setup_ops)
> > +{
> > + struct iio_buffer *buffer;
> > +
> > + if (mode_flags)
> > + mode_flags &= kfifo_access_funcs.modes;
>
> The if seems unnecessary. If it is 0 and we AND it with something it is
> still 0.

Makes sense.
Will send an update for this.

>


Re: [PATCH v6 19/24] iio: buffer: introduce support for attaching more IIO buffers

2021-02-28 Thread Alexandru Ardelean
On Sun, Feb 28, 2021 at 10:31 AM Lars-Peter Clausen  wrote:
>
> On 2/15/21 11:40 AM, Alexandru Ardelean wrote:
> >   static ssize_t iio_show_scan_index(struct device *dev,
> >  struct device_attribute *attr,
> >  char *buf)
> > @@ -1451,11 +1465,13 @@ static void __iio_buffer_free_sysfs_and_mask(struct 
> > iio_buffer *buffer)
> >   iio_free_chan_devattr_list(>buffer_attr_list);
> >   }
> >
> > -int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
> > +int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
> >   {
> > [...]
> > +error_unwind_sysfs_and_mask:
> > + for (; unwind_idx >= 0; unwind_idx--) {
> > + buffer = iio_dev_opaque->attached_buffers[unwind_idx];
> > + __iio_buffer_free_sysfs_and_mask(buffer);
> > + }
> > + kfree(iio_dev_opaque->attached_buffers);
> > + return ret;
> >   }
> >
> > -void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev)
> > +void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev)
> >   {
> > [...]
> > + for (i = iio_dev_opaque->attached_buffers_cnt - 1; i >= 0; i--) {
> > + buffer = iio_dev_opaque->attached_buffers[i];
> > + __iio_buffer_free_sysfs_and_mask(buffer);
> > + }
> > +
> > + kfree(iio_dev_opaque->attached_buffers);
> >   }
> > [...]
> > diff --git a/drivers/iio/industrialio-core.c 
> > b/drivers/iio/industrialio-core.c
> > index 1d500ea246af..f7f785431106 100644
> > --- a/drivers/iio/industrialio-core.c
> > +++ b/drivers/iio/industrialio-core.c
> > @@ -1583,7 +1583,7 @@ static void iio_dev_release(struct device *device)
> >   iio_device_unregister_eventset(indio_dev);
> >   iio_device_unregister_sysfs(indio_dev);
> >
> > - iio_buffer_put(indio_dev->buffer);
> > + iio_buffers_put(indio_dev);
> We do call kfree(iio_dev_opaque->attached_buffers) before we get here. I
> think we need to keep the array around, otherwise we end of up with a
> use after free.
>

Good catch.
Will send an update here.


[PATCH v2] iio: core: use kstrdup_const/kfree_const for buffer attributes

2021-02-22 Thread Alexandru Ardelean
When the buffer attributes were wrapped in iio_dev_attr types, I forgot to
duplicate the names, so that when iio_free_chan_devattr_list() gets called
on cleanup, these get free'd.
I stumbled over this while accidentally breaking a driver doing
iio_device_register(), and then the issue appeared.

Some ways to fix this are:
1. Just use kstrdup() during iio_buffer_wrap_attr()
2. Just use kfree_const() during iio_free_chan_devattr_list
3. Use both kstrdup_const() & kfree_const() (in the places mentioned above)

This implements the third option, as it allows some users/drivers to
specify some attributes allocated on the heap.

Fixes: a1a11142f66c ("iio: buffer: wrap all buffer attributes into 
iio_dev_attr")
Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/industrialio-buffer.c | 1 +
 drivers/iio/industrialio-core.c   | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/industrialio-buffer.c 
b/drivers/iio/industrialio-buffer.c
index 5d641f8adfbd..ac882e60c419 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -1306,6 +1306,7 @@ static struct attribute *iio_buffer_wrap_attr(struct 
iio_buffer *buffer,
return NULL;
 
iio_attr->buffer = buffer;
+   iio_attr->dev_attr.attr.name = kstrdup_const(attr->name, GFP_KERNEL);
memcpy(_attr->dev_attr, dattr, sizeof(iio_attr->dev_attr));
 
list_add(_attr->l, >buffer_attr_list);
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 0d8c6e88d993..cb2735d2ae4b 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -1358,7 +1358,7 @@ void iio_free_chan_devattr_list(struct list_head 
*attr_list)
struct iio_dev_attr *p, *n;
 
list_for_each_entry_safe(p, n, attr_list, l) {
-   kfree(p->dev_attr.attr.name);
+   kfree_const(p->dev_attr.attr.name);
list_del(>l);
kfree(p);
}
-- 
2.25.1



Re: [PATCH 1/2] iio: core: use kfree_const in iio_free_chan_devattr_list() to free names

2021-02-22 Thread Alexandru Ardelean
On Mon, Feb 22, 2021 at 6:06 PM Jonathan Cameron
 wrote:
>
> On Fri, 19 Feb 2021 10:58:25 +0200
> Alexandru Ardelean  wrote:
>
> > When the buffer attributes were wrapped in iio_dev_attr types, I forgot to
> > duplicate the names, so that when iio_free_chan_devattr_list() gets called
> > on cleanup, these get free'd.
> > I stumbled over this while accidentally breaking a driver doing
> > iio_device_register(), and then the issue appeared.
> >
> > The fix can be just
> > 1. Just use kstrdup() during iio_buffer_wrap_attr()
> > 2. Just use kfree_const() during iio_free_chan_devattr_list
> > 3. Use both kstrdup_const() & kfree_const() (in the places mentioned above)
> >
> > Using kfree_const() should be sufficient, as the attribute names will
> > either be allocated or be stored in rodata.
> >
> > Fixes: a1a11142f66c ("iio: buffer: wrap all buffer attributes into 
> > iio_dev_attr")
> > Signed-off-by: Alexandru Ardelean 
>
> Thinking more on this...  It's fine for the users today, but there is
> nothing stopping a driver passing in names it allocated on the heap.  So
> I think we should revisit this.  Perhaps we need 1 or 3.

Ok.
Will re-send this as 3; that sounds like it gives the best of both worlds.

> > ---
> >  drivers/iio/industrialio-core.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/iio/industrialio-core.c 
> > b/drivers/iio/industrialio-core.c
> > index 0d8c6e88d993..cb2735d2ae4b 100644
> > --- a/drivers/iio/industrialio-core.c
> > +++ b/drivers/iio/industrialio-core.c
> > @@ -1358,7 +1358,7 @@ void iio_free_chan_devattr_list(struct list_head 
> > *attr_list)
> >   struct iio_dev_attr *p, *n;
> >
> >   list_for_each_entry_safe(p, n, attr_list, l) {
> > - kfree(p->dev_attr.attr.name);
> > + kfree_const(p->dev_attr.attr.name);
> >   list_del(>l);
> >   kfree(p);
> >   }
>


Re: [PATCH v3 6/6] iio: buffer-dma: add support for cyclic DMA transfers

2021-02-22 Thread Alexandru Ardelean
On Sun, Feb 21, 2021 at 2:11 PM Jonathan Cameron  wrote:
>
> On Fri, 19 Feb 2021 14:40:12 +0200
> Alexandru Ardelean  wrote:
>
> > From: Lars-Peter Clausen 
> >
> > This change adds support for cyclic DMA transfers using the IIO buffer DMA
> > infrastructure.
> > To do this, userspace must set the IIO_BUFFER_BLOCK_FLAG_CYCLIC flag on the
> > block when enqueueing them via the ENQUEUE_BLOCK ioctl().
> >
> > Signed-off-by: Lars-Peter Clausen 
> > Signed-off-by: Alexandru Ardelean 
> Series in general looks good to me, but this change needs a little more
> detail + probably some level of example userspace flow.
>
> I don't really understand how this is used!
>
> Also, it's easy to test output buffers with the kfifo support so we
> should be able to move forward quickly with that part (1-3, 4 is probably
> fine as well as clearly harmless).
>
> The dma stuff worries me more, at least partly based on the experience
> of the original dma buffers which basically sat their unused (in upstream)
> for a very long time.   So to move these forward, they need to come
> with users...

So, this series will need to be re-sent/re-tested by someone else.
I'm on my last week at ADI and I'm on vacation.

Maybe I can manage to setup something to test as well, but it will take a while.



>
> Thanks,
>
> Jonathan
>
> > ---
> >  .../buffer/industrialio-buffer-dmaengine.c| 24 ---
> >  include/uapi/linux/iio/buffer.h   |  1 +
> >  2 files changed, 17 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c 
> > b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
> > index 65458a6cc81a..39cc230c7991 100644
> > --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c
> > +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
> > @@ -82,14 +82,22 @@ static int iio_dmaengine_buffer_submit_block(struct 
> > iio_dma_buffer_queue *queue,
> >
> >   direction = dmaengine_buffer->is_tx ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
> >
> > - desc = dmaengine_prep_slave_single(dmaengine_buffer->chan,
> > - block->phys_addr, block->block.bytes_used, direction,
> > - DMA_PREP_INTERRUPT);
> > - if (!desc)
> > - return -ENOMEM;
> > -
> > - desc->callback_result = iio_dmaengine_buffer_block_done;
> > - desc->callback_param = block;
> > + if (block->block.flags & IIO_BUFFER_BLOCK_FLAG_CYCLIC) {
> > + desc = dmaengine_prep_dma_cyclic(dmaengine_buffer->chan,
> > + block->phys_addr, block->block.bytes_used,
> > + block->block.bytes_used, direction, 0);
> > + if (!desc)
> > + return -ENOMEM;
> > + } else {
> > + desc = dmaengine_prep_slave_single(dmaengine_buffer->chan,
> > + block->phys_addr, block->block.bytes_used, direction,
> > + DMA_PREP_INTERRUPT);
> > + if (!desc)
> > + return -ENOMEM;
> > +
> > + desc->callback_result = iio_dmaengine_buffer_block_done;
> > + desc->callback_param = block;
> > + }
> >
> >   cookie = dmaengine_submit(desc);
> >   if (dma_submit_error(cookie))
> > diff --git a/include/uapi/linux/iio/buffer.h 
> > b/include/uapi/linux/iio/buffer.h
> > index 4e4ee9befea1..1bde508fe1b9 100644
> > --- a/include/uapi/linux/iio/buffer.h
> > +++ b/include/uapi/linux/iio/buffer.h
> > @@ -33,6 +33,7 @@ struct iio_buffer_block_alloc_req {
> >
> >  /* A function will be assigned later for BIT(0) */
> >  #define IIO_BUFFER_BLOCK_FLAG_RESERVED   (1 << 0)
> > +#define IIO_BUFFER_BLOCK_FLAG_CYCLIC (1 << 1)
> >
> >  /**
> >   * struct iio_buffer_block - Descriptor for a single IIO block
>


[PATCH v3 6/6] iio: buffer-dma: add support for cyclic DMA transfers

2021-02-19 Thread Alexandru Ardelean
From: Lars-Peter Clausen 

This change adds support for cyclic DMA transfers using the IIO buffer DMA
infrastructure.
To do this, userspace must set the IIO_BUFFER_BLOCK_FLAG_CYCLIC flag on the
block when enqueueing them via the ENQUEUE_BLOCK ioctl().

Signed-off-by: Lars-Peter Clausen 
Signed-off-by: Alexandru Ardelean 
---
 .../buffer/industrialio-buffer-dmaengine.c| 24 ---
 include/uapi/linux/iio/buffer.h   |  1 +
 2 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c 
b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
index 65458a6cc81a..39cc230c7991 100644
--- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c
+++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
@@ -82,14 +82,22 @@ static int iio_dmaengine_buffer_submit_block(struct 
iio_dma_buffer_queue *queue,
 
direction = dmaengine_buffer->is_tx ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
 
-   desc = dmaengine_prep_slave_single(dmaengine_buffer->chan,
-   block->phys_addr, block->block.bytes_used, direction,
-   DMA_PREP_INTERRUPT);
-   if (!desc)
-   return -ENOMEM;
-
-   desc->callback_result = iio_dmaengine_buffer_block_done;
-   desc->callback_param = block;
+   if (block->block.flags & IIO_BUFFER_BLOCK_FLAG_CYCLIC) {
+   desc = dmaengine_prep_dma_cyclic(dmaengine_buffer->chan,
+   block->phys_addr, block->block.bytes_used,
+   block->block.bytes_used, direction, 0);
+   if (!desc)
+   return -ENOMEM;
+   } else {
+   desc = dmaengine_prep_slave_single(dmaengine_buffer->chan,
+   block->phys_addr, block->block.bytes_used, direction,
+   DMA_PREP_INTERRUPT);
+   if (!desc)
+   return -ENOMEM;
+
+   desc->callback_result = iio_dmaengine_buffer_block_done;
+   desc->callback_param = block;
+   }
 
cookie = dmaengine_submit(desc);
if (dma_submit_error(cookie))
diff --git a/include/uapi/linux/iio/buffer.h b/include/uapi/linux/iio/buffer.h
index 4e4ee9befea1..1bde508fe1b9 100644
--- a/include/uapi/linux/iio/buffer.h
+++ b/include/uapi/linux/iio/buffer.h
@@ -33,6 +33,7 @@ struct iio_buffer_block_alloc_req {
 
 /* A function will be assigned later for BIT(0) */
 #define IIO_BUFFER_BLOCK_FLAG_RESERVED (1 << 0)
+#define IIO_BUFFER_BLOCK_FLAG_CYCLIC   (1 << 1)
 
 /**
  * struct iio_buffer_block - Descriptor for a single IIO block
-- 
2.27.0



[PATCH v3 2/6] iio: kfifo-buffer: Add output buffer support

2021-02-19 Thread Alexandru Ardelean
From: Lars-Peter Clausen 

Add output buffer support to the kfifo buffer implementation.

The implementation is straight forward and mostly just wraps the kfifo
API to provide the required operations.

Signed-off-by: Lars-Peter Clausen 
Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/buffer/kfifo_buf.c | 50 ++
 1 file changed, 50 insertions(+)

diff --git a/drivers/iio/buffer/kfifo_buf.c b/drivers/iio/buffer/kfifo_buf.c
index 34289ce12f20..e8a434f84778 100644
--- a/drivers/iio/buffer/kfifo_buf.c
+++ b/drivers/iio/buffer/kfifo_buf.c
@@ -138,10 +138,60 @@ static void iio_kfifo_buffer_release(struct iio_buffer 
*buffer)
kfree(kf);
 }
 
+static size_t iio_kfifo_buf_space_available(struct iio_buffer *r)
+{
+   struct iio_kfifo *kf = iio_to_kfifo(r);
+   size_t avail;
+
+   mutex_lock(>user_lock);
+   avail = kfifo_avail(>kf);
+   mutex_unlock(>user_lock);
+
+   return avail;
+}
+
+static int iio_kfifo_remove_from(struct iio_buffer *r, void *data)
+{
+   int ret;
+   struct iio_kfifo *kf = iio_to_kfifo(r);
+
+   if (kfifo_size(>kf) < r->bytes_per_datum)
+   return -EBUSY;
+
+   ret = kfifo_out(>kf, data, r->bytes_per_datum);
+   if (ret != r->bytes_per_datum)
+   return -EBUSY;
+
+   wake_up_interruptible_poll(>pollq, POLLOUT | POLLWRNORM);
+
+   return 0;
+}
+
+static int iio_kfifo_write(struct iio_buffer *r, size_t n,
+   const char __user *buf)
+{
+   struct iio_kfifo *kf = iio_to_kfifo(r);
+   int ret, copied;
+
+   mutex_lock(>user_lock);
+   if (!kfifo_initialized(>kf) || n < kfifo_esize(>kf))
+   ret = -EINVAL;
+   else
+   ret = kfifo_from_user(>kf, buf, n, );
+   mutex_unlock(>user_lock);
+   if (ret)
+   return ret;
+
+   return copied;
+}
+
 static const struct iio_buffer_access_funcs kfifo_access_funcs = {
.store_to = _store_to_kfifo,
.read = _read_kfifo,
.data_available = iio_kfifo_buf_data_available,
+   .remove_from = _kfifo_remove_from,
+   .write = _kfifo_write,
+   .space_available = _kfifo_buf_space_available,
.request_update = _request_update_kfifo,
.set_bytes_per_datum = _set_bytes_per_datum_kfifo,
.set_length = _set_length_kfifo,
-- 
2.27.0



[PATCH v3 5/6] iio: buffer-dma: Add output buffer support

2021-02-19 Thread Alexandru Ardelean
From: Lars-Peter Clausen 

Add support for output buffers to the dma buffer implementation.

Signed-off-by: Lars-Peter Clausen 
Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/adc/adi-axi-adc.c |   3 +-
 drivers/iio/buffer/industrialio-buffer-dma.c  | 116 --
 .../buffer/industrialio-buffer-dmaengine.c|  43 +--
 include/linux/iio/buffer-dma.h|   6 +
 include/linux/iio/buffer-dmaengine.h  |   6 +-
 5 files changed, 151 insertions(+), 23 deletions(-)

diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
index bfa00100a631..98cc1e7caa69 100644
--- a/drivers/iio/adc/adi-axi-adc.c
+++ b/drivers/iio/adc/adi-axi-adc.c
@@ -104,6 +104,7 @@ static unsigned int adi_axi_adc_read(struct 
adi_axi_adc_state *st,
 static int adi_axi_adc_config_dma_buffer(struct device *dev,
 struct iio_dev *indio_dev)
 {
+   enum iio_buffer_direction dir = IIO_BUFFER_DIRECTION_IN;
const char *dma_name;
 
if (!device_property_present(dev, "dmas"))
@@ -113,7 +114,7 @@ static int adi_axi_adc_config_dma_buffer(struct device *dev,
dma_name = "rx";
 
return devm_iio_dmaengine_buffer_setup(indio_dev->dev.parent,
-  indio_dev, dma_name,
+  indio_dev, dir, dma_name,
   NULL, NULL);
 }
 
diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c 
b/drivers/iio/buffer/industrialio-buffer-dma.c
index aa56c10418d0..83074d060535 100644
--- a/drivers/iio/buffer/industrialio-buffer-dma.c
+++ b/drivers/iio/buffer/industrialio-buffer-dma.c
@@ -223,7 +223,8 @@ void iio_dma_buffer_block_done(struct iio_dma_buffer_block 
*block)
spin_unlock_irqrestore(>list_lock, flags);
 
iio_buffer_block_put_atomic(block);
-   wake_up_interruptible_poll(>buffer.pollq, EPOLLIN | EPOLLRDNORM);
+   wake_up_interruptible_poll(>buffer.pollq,
+   (uintptr_t)queue->poll_wakup_flags);
 }
 EXPORT_SYMBOL_GPL(iio_dma_buffer_block_done);
 
@@ -252,7 +253,8 @@ void iio_dma_buffer_block_list_abort(struct 
iio_dma_buffer_queue *queue,
}
spin_unlock_irqrestore(>list_lock, flags);
 
-   wake_up_interruptible_poll(>buffer.pollq, EPOLLIN | EPOLLRDNORM);
+   wake_up_interruptible_poll(>buffer.pollq,
+   (uintptr_t)queue->poll_wakup_flags);
 }
 EXPORT_SYMBOL_GPL(iio_dma_buffer_block_list_abort);
 
@@ -353,9 +355,6 @@ int iio_dma_buffer_request_update(struct iio_buffer *buffer)
}
 
block->block.id = i;
-
-   block->state = IIO_BLOCK_STATE_QUEUED;
-   list_add_tail(>head, >incoming);
}
 
 out_unlock:
@@ -437,7 +436,29 @@ int iio_dma_buffer_enable(struct iio_buffer *buffer,
struct iio_dma_buffer_block *block, *_block;
 
mutex_lock(>lock);
+
+   if (buffer->direction == IIO_BUFFER_DIRECTION_IN)
+   queue->poll_wakup_flags = POLLIN | POLLRDNORM;
+   else
+   queue->poll_wakup_flags = POLLOUT | POLLWRNORM;
+
queue->fileio.enabled = !queue->num_blocks;
+   if (queue->fileio.enabled) {
+   unsigned int i;
+
+   for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) {
+   struct iio_dma_buffer_block *block =
+   queue->fileio.blocks[i];
+   if (buffer->direction == IIO_BUFFER_DIRECTION_IN) {
+   block->state = IIO_BLOCK_STATE_QUEUED;
+   list_add_tail(>head, >incoming);
+   } else {
+   block->state = IIO_BLOCK_STATE_DEQUEUED;
+   list_add_tail(>head, >outgoing);
+   }
+   }
+   }
+
queue->active = true;
list_for_each_entry_safe(block, _block, >incoming, head) {
list_del(>head);
@@ -567,6 +588,61 @@ int iio_dma_buffer_read(struct iio_buffer *buffer, size_t 
n,
 }
 EXPORT_SYMBOL_GPL(iio_dma_buffer_read);
 
+int iio_dma_buffer_write(struct iio_buffer *buf, size_t n,
+   const char __user *user_buffer)
+{
+   struct iio_dma_buffer_queue *queue = iio_buffer_to_queue(buf);
+   struct iio_dma_buffer_block *block;
+   int ret;
+
+   if (n < buf->bytes_per_datum)
+   return -EINVAL;
+
+   mutex_lock(>lock);
+
+   if (!queue->fileio.enabled) {
+   ret = -EBUSY;
+   goto out_unlock;
+   }
+
+   if (!queue->fileio.active_block) {
+   block = iio_dma_buffer_dequeue(queue);
+   if (block == NULL) {
+   ret = 0;
+   goto out_unlock;
+   }
+   queue-&g

[PATCH v3 3/6] iio: triggered-buffer: extend support to configure output buffers

2021-02-19 Thread Alexandru Ardelean
Now that output (kfifo) buffers are supported, we need to extend the
{devm_}iio_triggered_buffer_setup_ext() parameter list to take a direction
parameter.

This allows us to attach an output triggered buffer to a DAC device.
Unfortunately it's a bit difficult to add another macro to avoid changing 5
drivers where {devm_}iio_triggered_buffer_setup_ext() is used.
Well, it's doable, but may not be worth the trouble vs just updating all
these 5 drivers.

Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/accel/adxl372.c   |  1 +
 drivers/iio/accel/bmc150-accel-core.c |  1 +
 drivers/iio/adc/at91-sama5d2_adc.c|  4 ++--
 drivers/iio/buffer/industrialio-triggered-buffer.c|  8 ++--
 .../iio/common/cros_ec_sensors/cros_ec_sensors_core.c |  1 +
 drivers/iio/common/hid-sensors/hid-sensor-trigger.c   |  5 +++--
 include/linux/iio/triggered_buffer.h  | 11 +--
 7 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 8ba1453b8dbf..f2e077f72531 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -1214,6 +1214,7 @@ int adxl372_probe(struct device *dev, struct regmap 
*regmap,
ret = devm_iio_triggered_buffer_setup_ext(dev,
  indio_dev, NULL,
  adxl372_trigger_handler,
+ IIO_BUFFER_DIRECTION_IN,
  _buffer_ops,
  adxl372_fifo_attributes);
if (ret < 0)
diff --git a/drivers/iio/accel/bmc150-accel-core.c 
b/drivers/iio/accel/bmc150-accel-core.c
index b0dbd12cbf42..3e0305b0065b 100644
--- a/drivers/iio/accel/bmc150-accel-core.c
+++ b/drivers/iio/accel/bmc150-accel-core.c
@@ -1743,6 +1743,7 @@ int bmc150_accel_core_probe(struct device *dev, struct 
regmap *regmap, int irq,
ret = iio_triggered_buffer_setup_ext(indio_dev,
 _pollfunc_store_time,
 bmc150_accel_trigger_handler,
+IIO_BUFFER_DIRECTION_IN,
 _accel_buffer_ops,
 fifo_attrs);
if (ret < 0) {
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c 
b/drivers/iio/adc/at91-sama5d2_adc.c
index a7826f097b95..fc134f9c0200 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -1680,8 +1680,8 @@ static int at91_adc_buffer_and_trigger_init(struct device 
*dev,
fifo_attrs = NULL;
 
ret = devm_iio_triggered_buffer_setup_ext(>dev, indio,
-   _pollfunc_store_time,
-   _adc_trigger_handler, _buffer_setup_ops, fifo_attrs);
+   _pollfunc_store_time, _adc_trigger_handler,
+   IIO_BUFFER_DIRECTION_IN, _buffer_setup_ops, fifo_attrs);
if (ret < 0) {
dev_err(dev, "couldn't initialize the buffer.\n");
return ret;
diff --git a/drivers/iio/buffer/industrialio-triggered-buffer.c 
b/drivers/iio/buffer/industrialio-triggered-buffer.c
index b2b1b7d27af4..f400e978cd1e 100644
--- a/drivers/iio/buffer/industrialio-triggered-buffer.c
+++ b/drivers/iio/buffer/industrialio-triggered-buffer.c
@@ -19,6 +19,7 @@
  * @indio_dev: IIO device structure
  * @h: Function which will be used as pollfunc top half
  * @thread:Function which will be used as pollfunc bottom half
+ * @direction: Direction of the data stream (in/out).
  * @setup_ops: Buffer setup functions to use for this device.
  * If NULL the default setup functions for triggered
  * buffers will be used.
@@ -38,6 +39,7 @@
 int iio_triggered_buffer_setup_ext(struct iio_dev *indio_dev,
irqreturn_t (*h)(int irq, void *p),
irqreturn_t (*thread)(int irq, void *p),
+   enum iio_buffer_direction direction,
const struct iio_buffer_setup_ops *setup_ops,
const struct attribute **buffer_attrs)
 {
@@ -68,6 +70,7 @@ int iio_triggered_buffer_setup_ext(struct iio_dev *indio_dev,
/* Flag that polled ring buffering is possible */
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
 
+   buffer->direction = direction;
buffer->attrs = buffer_attrs;
 
ret = iio_device_attach_buffer(indio_dev, buffer);
@@ -105,6 +108,7 @@ int devm_iio_triggered_buffer_setup_ext(struct device *dev,
struct iio_dev *indio_dev,
irqreturn_t (*h)(int irq, void *p),
irqreturn_t (*thread)(int irq, void *p),
+   enum

[PATCH v3 4/6] iio: buffer-dma: Allow to provide custom buffer ops

2021-02-19 Thread Alexandru Ardelean
From: Lars-Peter Clausen 

Some devices that want to make use of the DMA buffer might need to do
something special, like write a register when the buffer is enabled.

Extend the API to allow those drivers to provide their own buffer ops.

Signed-off-by: Lars-Peter Clausen 
Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/adc/adi-axi-adc.c |  3 ++-
 drivers/iio/buffer/industrialio-buffer-dma.c  |  4 +++-
 .../buffer/industrialio-buffer-dmaengine.c| 23 +--
 include/linux/iio/buffer-dma.h|  5 +++-
 include/linux/iio/buffer-dmaengine.h  |  6 +++--
 5 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
index 2e84623f732e..bfa00100a631 100644
--- a/drivers/iio/adc/adi-axi-adc.c
+++ b/drivers/iio/adc/adi-axi-adc.c
@@ -113,7 +113,8 @@ static int adi_axi_adc_config_dma_buffer(struct device *dev,
dma_name = "rx";
 
return devm_iio_dmaengine_buffer_setup(indio_dev->dev.parent,
-  indio_dev, dma_name);
+  indio_dev, dma_name,
+  NULL, NULL);
 }
 
 static int adi_axi_adc_read_raw(struct iio_dev *indio_dev,
diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c 
b/drivers/iio/buffer/industrialio-buffer-dma.c
index 1ae47ed8ef22..aa56c10418d0 100644
--- a/drivers/iio/buffer/industrialio-buffer-dma.c
+++ b/drivers/iio/buffer/industrialio-buffer-dma.c
@@ -892,13 +892,15 @@ EXPORT_SYMBOL_GPL(iio_dma_buffer_set_length);
  * allocations are done from a memory region that can be accessed by the 
device.
  */
 int iio_dma_buffer_init(struct iio_dma_buffer_queue *queue,
-   struct device *dev, const struct iio_dma_buffer_ops *ops)
+   struct device *dev, const struct iio_dma_buffer_ops *ops,
+   void *driver_data)
 {
iio_buffer_init(>buffer);
queue->buffer.length = PAGE_SIZE;
queue->buffer.watermark = queue->buffer.length / 2;
queue->dev = dev;
queue->ops = ops;
+   queue->driver_data = driver_data;
 
INIT_LIST_HEAD(>incoming);
INIT_LIST_HEAD(>outgoing);
diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c 
b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
index 6db24be7e11d..a4e7b97ce239 100644
--- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c
+++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
@@ -163,6 +163,8 @@ static const struct attribute *iio_dmaengine_buffer_attrs[] 
= {
  * iio_dmaengine_buffer_alloc() - Allocate new buffer which uses DMAengine
  * @dev: Parent device for the buffer
  * @channel: DMA channel name, typically "rx".
+ * @ops: Custom iio_dma_buffer_ops, if NULL default ops will be used
+ * @driver_data: Driver data to be passed to custom iio_dma_buffer_ops
  *
  * This allocates a new IIO buffer which internally uses the DMAengine 
framework
  * to perform its transfers. The parent device will be used to request the DMA
@@ -172,7 +174,8 @@ static const struct attribute *iio_dmaengine_buffer_attrs[] 
= {
  * release it.
  */
 static struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev,
-   const char *channel)
+   const char *channel, const struct iio_dma_buffer_ops *ops,
+   void *driver_data)
 {
struct dmaengine_buffer *dmaengine_buffer;
unsigned int width, src_width, dest_width;
@@ -211,7 +214,7 @@ static struct iio_buffer *iio_dmaengine_buffer_alloc(struct 
device *dev,
dmaengine_buffer->max_size = dma_get_max_seg_size(chan->device->dev);
 
iio_dma_buffer_init(_buffer->queue, chan->device->dev,
-   _dmaengine_default_ops);
+   ops ? ops : _dmaengine_default_ops, driver_data);
 
dmaengine_buffer->queue.buffer.attrs = iio_dmaengine_buffer_attrs;
dmaengine_buffer->queue.buffer.access = _dmaengine_buffer_ops;
@@ -249,6 +252,8 @@ static void __devm_iio_dmaengine_buffer_free(struct device 
*dev, void *res)
  * devm_iio_dmaengine_buffer_alloc() - Resource-managed 
iio_dmaengine_buffer_alloc()
  * @dev: Parent device for the buffer
  * @channel: DMA channel name, typically "rx".
+ * @ops: Custom iio_dma_buffer_ops, if NULL default ops will be used
+ * @driver_data: Driver data to be passed to custom iio_dma_buffer_ops
  *
  * This allocates a new IIO buffer which internally uses the DMAengine 
framework
  * to perform its transfers. The parent device will be used to request the DMA
@@ -257,7 +262,8 @@ static void __devm_iio_dmaengine_buffer_free(struct device 
*dev, void *res)
  * The buffer will be automatically de-allocated once the device gets 
destroyed.
  */
 static struct iio_buffer *devm_iio_dmaengine_buffer_alloc(struct device *dev,
-   const char *channel)
+   const char *channel, const struct iio_dma_buffer_ops *ops,
+   vo

[PATCH v3 1/6] iio: Add output buffer support

2021-02-19 Thread Alexandru Ardelean
From: Lars-Peter Clausen 

Currently IIO only supports buffer mode for capture devices like ADCs. Add
support for buffered mode for output devices like DACs.

The output buffer implementation is analogous to the input buffer
implementation. Instead of using read() to get data from the buffer write()
is used to copy data into the buffer.

poll() with POLLOUT will wakeup if there is space available for more or
equal to the configured watermark of samples.

Drivers can remove data from a buffer using iio_buffer_remove_sample(), the
function can e.g. called from a trigger handler to write the data to
hardware.

A buffer can only be either a output buffer or an input, but not both. So,
for a device that has an ADC and DAC path, this will mean 2 IIO buffers
(one for each direction).

The direction of the buffer is decided by the new direction field of the
iio_buffer struct and should be set after allocating and before registering
it.

Signed-off-by: Lars-Peter Clausen 
Signed-off-by: Alexandru Ardelean 
---
 Documentation/ABI/testing/sysfs-bus-iio |   7 ++
 drivers/iio/industrialio-buffer.c   | 133 +++-
 include/linux/iio/buffer.h  |   7 ++
 include/linux/iio/buffer_impl.h |  11 ++
 4 files changed, 154 insertions(+), 4 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-iio 
b/Documentation/ABI/testing/sysfs-bus-iio
index 51feac826cb5..7a87bfb16b22 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -1170,6 +1170,13 @@ Contact: linux-...@vger.kernel.org
 Description:
Number of scans contained by the buffer.
 
+What:  /sys/bus/iio/devices/iio:deviceX/bufferY/direction
+KernelVersion: 5.11
+Contact:   linux-...@vger.kernel.org
+Description:
+   Returns the direction of the data stream of the buffer.
+   The output is "in" or "out".
+
 What:  /sys/bus/iio/devices/iio:deviceX/buffer/enable
 KernelVersion: 2.6.35
 What:  /sys/bus/iio/devices/iio:deviceX/bufferY/enable
diff --git a/drivers/iio/industrialio-buffer.c 
b/drivers/iio/industrialio-buffer.c
index 5d641f8adfbd..db1b91350987 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -162,6 +162,69 @@ static ssize_t iio_buffer_read(struct file *filp, char 
__user *buf,
return ret;
 }
 
+static size_t iio_buffer_space_available(struct iio_buffer *buf)
+{
+   if (buf->access->space_available)
+   return buf->access->space_available(buf);
+
+   return SIZE_MAX;
+}
+
+static ssize_t iio_buffer_write(struct file *filp, const char __user *buf,
+   size_t n, loff_t *f_ps)
+{
+   struct iio_dev_buffer_pair *ib = filp->private_data;
+   struct iio_buffer *rb = ib->buffer;
+   struct iio_dev *indio_dev = ib->indio_dev;
+   DEFINE_WAIT_FUNC(wait, woken_wake_function);
+   size_t datum_size;
+   size_t to_wait;
+   int ret;
+
+   if (!rb || !rb->access->write)
+   return -EINVAL;
+
+   datum_size = rb->bytes_per_datum;
+
+   /*
+* If datum_size is 0 there will never be anything to read from the
+* buffer, so signal end of file now.
+*/
+   if (!datum_size)
+   return 0;
+
+   if (filp->f_flags & O_NONBLOCK)
+   to_wait = 0;
+   else
+   to_wait = min_t(size_t, n / datum_size, rb->watermark);
+
+   add_wait_queue(>pollq, );
+   do {
+   if (!indio_dev->info) {
+   ret = -ENODEV;
+   break;
+   }
+
+   if (iio_buffer_space_available(rb) < to_wait) {
+   if (signal_pending(current)) {
+   ret = -ERESTARTSYS;
+   break;
+   }
+
+   wait_woken(, TASK_INTERRUPTIBLE,
+  MAX_SCHEDULE_TIMEOUT);
+   continue;
+   }
+
+   ret = rb->access->write(rb, n, buf);
+   if (ret == 0 && (filp->f_flags & O_NONBLOCK))
+   ret = -EAGAIN;
+   } while (ret == 0);
+   remove_wait_queue(>pollq, );
+
+   return ret;
+}
+
 /**
  * iio_buffer_poll() - poll the buffer to find out if it has data
  * @filp:  File structure pointer for device access
@@ -182,8 +245,18 @@ static __poll_t iio_buffer_poll(struct file *filp,
return 0;
 
poll_wait(filp, >pollq, wait);
-   if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0))
-   return EPOLLIN | EPOLLRDNORM;
+
+   switch (rb->direction) {
+   case IIO_BUFFER_DIRECTION_IN:
+   if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0))
+   return EPOLLIN | EPOLLRDNORM;
+

[PATCH v3 0/6] iio: Add output buffer support

2021-02-19 Thread Alexandru Ardelean
Changelog v2 -> v3:
* 
https://lore.kernel.org/linux-iio/20210217083438.37865-4-alexandru.ardel...@analog.com/T/#m396545e0c6cc9d58e17f4d79b6fc707fd0373d89
* adding only infrastructure pieces for output DAC buffers, unfortunately I
  couldn't finish a complete DAC change to showcase these changes
* patch 'iio: Add output buffer support'
   - moved new 'bufferY/direction' attribute at the end and added
 comment about what it should be added at the end
* removed Lars' comment '/* need a way of knowing if there may be enough 
data... */'
* updated some various formatting;

Alexandru Ardelean (1):
  iio: triggered-buffer: extend support to configure output buffers

Lars-Peter Clausen (5):
  iio: Add output buffer support
  iio: kfifo-buffer: Add output buffer support
  iio: buffer-dma: Allow to provide custom buffer ops
  iio: buffer-dma: Add output buffer support
  iio: buffer-dma: add support for cyclic DMA transfers

 Documentation/ABI/testing/sysfs-bus-iio   |   7 +
 drivers/iio/accel/adxl372.c   |   1 +
 drivers/iio/accel/bmc150-accel-core.c |   1 +
 drivers/iio/adc/adi-axi-adc.c |   4 +-
 drivers/iio/adc/at91-sama5d2_adc.c|   4 +-
 drivers/iio/buffer/industrialio-buffer-dma.c  | 120 ++--
 .../buffer/industrialio-buffer-dmaengine.c|  72 +++---
 .../buffer/industrialio-triggered-buffer.c|   8 +-
 drivers/iio/buffer/kfifo_buf.c|  50 +++
 .../cros_ec_sensors/cros_ec_sensors_core.c|   1 +
 .../common/hid-sensors/hid-sensor-trigger.c   |   5 +-
 drivers/iio/industrialio-buffer.c | 133 +-
 include/linux/iio/buffer-dma.h|  11 +-
 include/linux/iio/buffer-dmaengine.h  |   8 +-
 include/linux/iio/buffer.h|   7 +
 include/linux/iio/buffer_impl.h   |  11 ++
 include/linux/iio/triggered_buffer.h  |  11 +-
 include/uapi/linux/iio/buffer.h   |   1 +
 18 files changed, 412 insertions(+), 43 deletions(-)

-- 
2.27.0



[PATCH] iio: adc: adi-axi-adc: fix typo in doc-string

2021-02-19 Thread Alexandru Ardelean
The channels are of type iio_chan_spec, not axi_adc_chan_spec. They were in
some earlier version, but forgot to rename in the doc-string.

Fixes: ef04070692a21 ("iio: adc: adi-axi-adc: add support for AXI ADC IP core")
Signed-off-by: Alexandru Ardelean 
---
 include/linux/iio/adc/adi-axi-adc.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/iio/adc/adi-axi-adc.h 
b/include/linux/iio/adc/adi-axi-adc.h
index c5d48e1c2d36..52620e5b8052 100644
--- a/include/linux/iio/adc/adi-axi-adc.h
+++ b/include/linux/iio/adc/adi-axi-adc.h
@@ -15,7 +15,7 @@ struct iio_chan_spec;
  * struct adi_axi_adc_chip_info - Chip specific information
  * @name   Chip name
  * @id Chip ID (usually product ID)
- * @channels   Channel specifications of type @struct axi_adc_chan_spec
+ * @channels   Channel specifications of type @struct iio_chan_spec
  * @num_channels   Number of @channels
  * @scale_tableSupported scales by the chip; tuples of 2 ints
  * @num_scales Number of scales in the table
-- 
2.27.0



[PATCH 1/2] iio: core: use kfree_const in iio_free_chan_devattr_list() to free names

2021-02-19 Thread Alexandru Ardelean
When the buffer attributes were wrapped in iio_dev_attr types, I forgot to
duplicate the names, so that when iio_free_chan_devattr_list() gets called
on cleanup, these get free'd.
I stumbled over this while accidentally breaking a driver doing
iio_device_register(), and then the issue appeared.

The fix can be just
1. Just use kstrdup() during iio_buffer_wrap_attr()
2. Just use kfree_const() during iio_free_chan_devattr_list
3. Use both kstrdup_const() & kfree_const() (in the places mentioned above)

Using kfree_const() should be sufficient, as the attribute names will
either be allocated or be stored in rodata.

Fixes: a1a11142f66c ("iio: buffer: wrap all buffer attributes into 
iio_dev_attr")
Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/industrialio-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 0d8c6e88d993..cb2735d2ae4b 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -1358,7 +1358,7 @@ void iio_free_chan_devattr_list(struct list_head 
*attr_list)
struct iio_dev_attr *p, *n;
 
list_for_each_entry_safe(p, n, attr_list, l) {
-   kfree(p->dev_attr.attr.name);
+   kfree_const(p->dev_attr.attr.name);
list_del(>l);
kfree(p);
}
-- 
2.27.0



[PATCH 2/2] iio: buffer-dma: fix type of 'i' in iio_dma_buffer_alloc_blocks()

2021-02-19 Thread Alexandru Ardelean
When unwinding the cleanup of the blocks, the type of 'i' is important to
be signed, so that the 'i >= 0' condition doesn't underflow and infinitely
loop (or just cause an access violation).

Fixes: ab925b044cfb ("iio: buffer-dma: Add mmap support")
Reported-by: kernel test robot 
Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/buffer/industrialio-buffer-dma.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c 
b/drivers/iio/buffer/industrialio-buffer-dma.c
index d04479194cb4..83074d060535 100644
--- a/drivers/iio/buffer/industrialio-buffer-dma.c
+++ b/drivers/iio/buffer/industrialio-buffer-dma.c
@@ -707,8 +707,7 @@ int iio_dma_buffer_alloc_blocks(struct iio_buffer *buffer,
struct iio_dma_buffer_queue *queue = iio_buffer_to_queue(buffer);
struct iio_dma_buffer_block **blocks;
unsigned int num_blocks;
-   unsigned int i;
-   int ret = 0;
+   int i, ret = 0;
 
mutex_lock(>lock);
 
-- 
2.27.0



[PATCH 0/2] iio: core,buffer-dma: 2 fixes for the recent IIO buffer series

2021-02-19 Thread Alexandru Ardelean
Patchset contains 2 fixes for some patches that are present in the
iio/testing branch.

No idea what's best now, either to re-send the series or to just send these
fixes on their own.
For now I chose to send the fixes on their (due to lack of time).

These could be squashed into the original.

I can also re-send the series, but not from an Analog email; since I will
not have access to it.

Alexandru Ardelean (2):
  iio: core: use kfree_const in iio_free_chan_devattr_list() to free
names
  iio: buffer-dma: fix type of 'i' in iio_dma_buffer_alloc_blocks()

 drivers/iio/buffer/industrialio-buffer-dma.c | 3 +--
 drivers/iio/industrialio-core.c  | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

-- 
2.27.0



Re: [PATCH v2 5/5] iio: dac: ad5686: Add PWM as a trigger source

2021-02-19 Thread Alexandru Ardelean
On Thu, Feb 18, 2021 at 5:31 PM Rob Herring  wrote:
>
> On Thu, Feb 18, 2021 at 8:05 AM Jonathan Cameron  wrote:
> >
> > On Wed, 17 Feb 2021 10:34:38 +0200
> > Alexandru Ardelean  wrote:
> >
> > > From: Mircea Caprioru 
> > >
> > > A PWM signal will be used as a trigger source to have a deterministic
> > > sampling frequency since this family of DAC has no hardware interrupt
> > > source.
> > >
> > > This feature is made optional however, as there are some board setups 
> > > where
> > > this isn't used.
> > >
> >
> > So this is taking a very generic setup, but then implementing it
> > as a bit of a hack within the driver.
> >
> > It's effectively a PWM connected up to an instance
> > of iio/triggers/iio-trig-interrupt.c
> >
> > Now, I've not looked at that trigger driver for a while, so you may well
> > need to figure out how to add a binding to instantiate it.
> > (looks like no one has used it since board file days, or via instantiation
> > from another driver).
> >
> > It's a slightly odd corner case as what it reflects is that we have
> > an interrupt available that is intended to drive some sort of data
> > capture or output (it's a trigger signal) - but exactly what is done
> > is a runtime configurable.  In this particular case that interrupt
> > is hooked up to a PWM and we also want to represent that.
> >
> > The fact it's being driven via a PWM is interesting but we should be
> > able to extend that trigger driver to optionally accept a pwm provider
> > and if it has one provide frequency control.
> >

So, the main intent here was to provide a user for this new output kfifo.
I don't think I have time to re-spin this into a proper solution.
Someone else may come about and do it.

I'll drop this from the series [for now].

> > Binding might look something like the following..
> >
> > interrupt-trigger {
> >interrupts = <>;
> >pwms = < 0 4000 PWM_POLARITY_INVERTED>;
> > };
> >
> > @Rob, what do you think of this odd beast?
>
> So a PWM routed back to a GPIO interrupt? It needs a compatible, but
> otherwise I wouldn't object to the binding if that's what the h/w
> looks like. But from an OS perspective, I don't think you need it.
>
> > So all in all, this generic facility needs a generic implementation, not
> > one buried in a driver.
> >
> > Another open question here is whether you really can't just use an hrtimer
> > to get similar precision?  Way back at the dawn of time in IIO we had
> > code to use the RTC periodic ticks as a trigger with the theory that they
> > would give very precise and even timing.  In the end it turned out that
> > hrtimers worked just as well (and RTCs drivers emulated the periodic
> > ticks via hrtimers, dropping their use of the hardware periodic timers).
>
> +100
>
> A hrtimer is likely going to be more precise. IIRC, timers are
> serviced first. Either way, you're going to have some amount of
> interrupt service latency, so any precision you think you are gaining
> by 'doing it in h/w' isn't really there.
>
> Rob


Re: [PATCH v2 2/5] iio: Add output buffer support

2021-02-19 Thread Alexandru Ardelean
On Thu, Feb 18, 2021 at 5:30 PM Jonathan Cameron  wrote:
>
> On Wed, 17 Feb 2021 10:34:35 +0200
> Alexandru Ardelean  wrote:
>
> > From: Lars-Peter Clausen 
> >
> > Currently IIO only supports buffer mode for capture devices like ADCs. Add
> > support for buffered mode for output devices like DACs.
> >
> > The output buffer implementation is analogous to the input buffer
> > implementation. Instead of using read() to get data from the buffer write()
> > is used to copy data into the buffer.
> >
> > poll() with POLLOUT will wakeup if there is space available for more or
> > equal to the configured watermark of samples.
> >
> > Drivers can remove data from a buffer using iio_buffer_remove_sample(), the
> > function can e.g. called from a trigger handler to write the data to
> > hardware.
> >
> > A buffer can only be either a output buffer or an input, but not both. So,
> > for a device that has an ADC and DAC path, this will mean 2 IIO buffers
> > (one for each direction).
> >
> > The direction of the buffer is decided by the new direction field of the
> > iio_buffer struct and should be set after allocating and before registering
> > it.
> >
> > Signed-off-by: Lars-Peter Clausen 
> > Signed-off-by: Alexandru Ardelean 
>
> Just one question on this, otherwise looks good to me.
>
> Jonathan
>
> > diff --git a/drivers/iio/industrialio-buffer.c 
> > b/drivers/iio/industrialio-buffer.c
> > index 5d641f8adfbd..b9970c68005d 100644
> > --- a/drivers/iio/industrialio-buffer.c
> > +++ b/drivers/iio/industrialio-buffer.c
> > @@ -162,6 +162,69 @@ static ssize_t iio_buffer_read(struct file *filp, char 
> > __user *buf,
> >   return ret;
> >  }
> >
> ...
>
> >  /**
> >   * iio_buffer_poll() - poll the buffer to find out if it has data
> >   * @filp:File structure pointer for device access
> > @@ -182,8 +245,19 @@ static __poll_t iio_buffer_poll(struct file *filp,
> >   return 0;
> >
> >   poll_wait(filp, >pollq, wait);
> > - if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0))
> > - return EPOLLIN | EPOLLRDNORM;
> > +
> > + switch (rb->direction) {
> > + case IIO_BUFFER_DIRECTION_IN:
> > + if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0))
> > + return EPOLLIN | EPOLLRDNORM;
> > + break;
> > + case IIO_BUFFER_DIRECTION_OUT:
> > + if (iio_buffer_space_available(rb) >= rb->watermark)
> > + return EPOLLOUT | EPOLLWRNORM;
> > + break;
> > + }
> > +
> > + /* need a way of knowing if there may be enough data... */
>
> Curious on what this comment is referring to?

I'm also a bit curious about what this comment is referring to.
I can remove it.

Maybe Lars can give some insight.

>
> >   return 0;
> >  }
> >
> > @@ -232,6 +306,16 @@ void iio_buffer_wakeup_poll(struct iio_dev *indio_dev)
> >   }
> >  }
> ...


[PATCH v2 4/5] iio: triggered-buffer: extend support to configure output buffers

2021-02-17 Thread Alexandru Ardelean
Now that output (kfifo) buffers are supported, we need to extend the
{devm_}iio_triggered_buffer_setup_ext() parameter list to take a direction
parameter.

This allows us to attach an output triggered buffer to a DAC device.
Unfortunately it's a bit difficult to add another macro to avoid changing 5
drivers where {devm_}iio_triggered_buffer_setup_ext() is used.
Well, it's doable, but may not be worth the trouble vs just updating all
these 5 drivers.

Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/accel/adxl372.c   |  1 +
 drivers/iio/accel/bmc150-accel-core.c |  1 +
 drivers/iio/adc/at91-sama5d2_adc.c|  4 ++--
 drivers/iio/buffer/industrialio-triggered-buffer.c|  8 ++--
 .../iio/common/cros_ec_sensors/cros_ec_sensors_core.c |  1 +
 drivers/iio/common/hid-sensors/hid-sensor-trigger.c   |  5 +++--
 include/linux/iio/triggered_buffer.h  | 11 +--
 7 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 8ba1453b8dbf..f2e077f72531 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -1214,6 +1214,7 @@ int adxl372_probe(struct device *dev, struct regmap 
*regmap,
ret = devm_iio_triggered_buffer_setup_ext(dev,
  indio_dev, NULL,
  adxl372_trigger_handler,
+ IIO_BUFFER_DIRECTION_IN,
  _buffer_ops,
  adxl372_fifo_attributes);
if (ret < 0)
diff --git a/drivers/iio/accel/bmc150-accel-core.c 
b/drivers/iio/accel/bmc150-accel-core.c
index b0dbd12cbf42..3e0305b0065b 100644
--- a/drivers/iio/accel/bmc150-accel-core.c
+++ b/drivers/iio/accel/bmc150-accel-core.c
@@ -1743,6 +1743,7 @@ int bmc150_accel_core_probe(struct device *dev, struct 
regmap *regmap, int irq,
ret = iio_triggered_buffer_setup_ext(indio_dev,
 _pollfunc_store_time,
 bmc150_accel_trigger_handler,
+IIO_BUFFER_DIRECTION_IN,
 _accel_buffer_ops,
 fifo_attrs);
if (ret < 0) {
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c 
b/drivers/iio/adc/at91-sama5d2_adc.c
index a7826f097b95..fc134f9c0200 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -1680,8 +1680,8 @@ static int at91_adc_buffer_and_trigger_init(struct device 
*dev,
fifo_attrs = NULL;
 
ret = devm_iio_triggered_buffer_setup_ext(>dev, indio,
-   _pollfunc_store_time,
-   _adc_trigger_handler, _buffer_setup_ops, fifo_attrs);
+   _pollfunc_store_time, _adc_trigger_handler,
+   IIO_BUFFER_DIRECTION_IN, _buffer_setup_ops, fifo_attrs);
if (ret < 0) {
dev_err(dev, "couldn't initialize the buffer.\n");
return ret;
diff --git a/drivers/iio/buffer/industrialio-triggered-buffer.c 
b/drivers/iio/buffer/industrialio-triggered-buffer.c
index b2b1b7d27af4..f400e978cd1e 100644
--- a/drivers/iio/buffer/industrialio-triggered-buffer.c
+++ b/drivers/iio/buffer/industrialio-triggered-buffer.c
@@ -19,6 +19,7 @@
  * @indio_dev: IIO device structure
  * @h: Function which will be used as pollfunc top half
  * @thread:Function which will be used as pollfunc bottom half
+ * @direction: Direction of the data stream (in/out).
  * @setup_ops: Buffer setup functions to use for this device.
  * If NULL the default setup functions for triggered
  * buffers will be used.
@@ -38,6 +39,7 @@
 int iio_triggered_buffer_setup_ext(struct iio_dev *indio_dev,
irqreturn_t (*h)(int irq, void *p),
irqreturn_t (*thread)(int irq, void *p),
+   enum iio_buffer_direction direction,
const struct iio_buffer_setup_ops *setup_ops,
const struct attribute **buffer_attrs)
 {
@@ -68,6 +70,7 @@ int iio_triggered_buffer_setup_ext(struct iio_dev *indio_dev,
/* Flag that polled ring buffering is possible */
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
 
+   buffer->direction = direction;
buffer->attrs = buffer_attrs;
 
ret = iio_device_attach_buffer(indio_dev, buffer);
@@ -105,6 +108,7 @@ int devm_iio_triggered_buffer_setup_ext(struct device *dev,
struct iio_dev *indio_dev,
irqreturn_t (*h)(int irq, void *p),
irqreturn_t (*thread)(int irq, void *p),
+   enum

[PATCH v2 5/5] iio: dac: ad5686: Add PWM as a trigger source

2021-02-17 Thread Alexandru Ardelean
From: Mircea Caprioru 

A PWM signal will be used as a trigger source to have a deterministic
sampling frequency since this family of DAC has no hardware interrupt
source.

This feature is made optional however, as there are some board setups where
this isn't used.

Signed-off-by: Mircea Caprioru 
Signed-off-by: Mihail Chindris 
Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/dac/ad5686-spi.c |   2 +-
 drivers/iio/dac/ad5686.c | 146 ++-
 drivers/iio/dac/ad5686.h |   7 +-
 drivers/iio/dac/ad5696-i2c.c |   2 +-
 4 files changed, 152 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/dac/ad5686-spi.c b/drivers/iio/dac/ad5686-spi.c
index 0188ded5137c..07fadcf8e1e3 100644
--- a/drivers/iio/dac/ad5686-spi.c
+++ b/drivers/iio/dac/ad5686-spi.c
@@ -92,7 +92,7 @@ static int ad5686_spi_probe(struct spi_device *spi)
const struct spi_device_id *id = spi_get_device_id(spi);
 
return ad5686_probe(>dev, id->driver_data, id->name,
-   ad5686_spi_write, ad5686_spi_read);
+   ad5686_spi_write, ad5686_spi_read, spi->irq);
 }
 
 static int ad5686_spi_remove(struct spi_device *spi)
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 7d6792ac1020..9e48559ec566 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -16,6 +16,10 @@
 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 
 #include "ad5686.h"
 
@@ -123,6 +127,7 @@ static int ad5686_read_raw(struct iio_dev *indio_dev,
   long m)
 {
struct ad5686_state *st = iio_priv(indio_dev);
+   struct pwm_state state;
int ret;
 
switch (m) {
@@ -139,6 +144,10 @@ static int ad5686_read_raw(struct iio_dev *indio_dev,
*val = st->vref_mv;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
+   case IIO_CHAN_INFO_SAMP_FREQ:
+   pwm_get_state(st->pwm, );
+   *val = DIV_ROUND_CLOSEST_ULL(10ULL, state.period);
+   return IIO_VAL_INT;
}
return -EINVAL;
 }
@@ -150,6 +159,7 @@ static int ad5686_write_raw(struct iio_dev *indio_dev,
long mask)
 {
struct ad5686_state *st = iio_priv(indio_dev);
+   struct pwm_state state;
int ret;
 
switch (mask) {
@@ -164,6 +174,14 @@ static int ad5686_write_raw(struct iio_dev *indio_dev,
val << chan->scan_type.shift);
mutex_unlock(>lock);
break;
+   case IIO_CHAN_INFO_SAMP_FREQ:
+   pwm_get_state(st->pwm, );
+
+   state.period = DIV_ROUND_CLOSEST_ULL(10ULL, val);
+   pwm_set_relative_duty_cycle(, 50, 100);
+
+   ret = pwm_apply_state(st->pwm, );
+   break;
default:
ret = -EINVAL;
}
@@ -171,7 +189,37 @@ static int ad5686_write_raw(struct iio_dev *indio_dev,
return ret;
 }
 
+static int ad5686_trig_set_state(struct iio_trigger *trig,
+bool state)
+{
+   struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+   struct ad5686_state *st = iio_priv(indio_dev);
+   struct pwm_state pwm_st;
+
+   pwm_get_state(st->pwm, _st);
+   pwm_st.enabled = state;
+
+   return pwm_apply_state(st->pwm, _st);
+}
+
+static int ad5686_validate_trigger(struct iio_dev *indio_dev,
+   struct iio_trigger *trig)
+{
+   struct ad5686_state *st = iio_priv(indio_dev);
+
+   if (st->trig != trig)
+   return -EINVAL;
+
+   return 0;
+}
+
+static const struct iio_trigger_ops ad5686_trigger_ops = {
+   .validate_device = _trigger_validate_own_device,
+   .set_trigger_state = _trig_set_state,
+};
+
 static const struct iio_info ad5686_info = {
+   .validate_trigger = _validate_trigger,
.read_raw = ad5686_read_raw,
.write_raw = ad5686_write_raw,
 };
@@ -194,8 +242,10 @@ static const struct iio_chan_spec_ext_info 
ad5686_ext_info[] = {
.output = 1,\
.channel = chan,\
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
-   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\
+   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),\
.address = addr,\
+   .scan_index = chan, \
.scan_type = {  \
.sign = 'u',\
.realbits = (bits), \
@@ -428,13 +478,57 @@ static const struct ad5686_chip_info 
ad568

[PATCH v2 2/5] iio: Add output buffer support

2021-02-17 Thread Alexandru Ardelean
From: Lars-Peter Clausen 

Currently IIO only supports buffer mode for capture devices like ADCs. Add
support for buffered mode for output devices like DACs.

The output buffer implementation is analogous to the input buffer
implementation. Instead of using read() to get data from the buffer write()
is used to copy data into the buffer.

poll() with POLLOUT will wakeup if there is space available for more or
equal to the configured watermark of samples.

Drivers can remove data from a buffer using iio_buffer_remove_sample(), the
function can e.g. called from a trigger handler to write the data to
hardware.

A buffer can only be either a output buffer or an input, but not both. So,
for a device that has an ADC and DAC path, this will mean 2 IIO buffers
(one for each direction).

The direction of the buffer is decided by the new direction field of the
iio_buffer struct and should be set after allocating and before registering
it.

Signed-off-by: Lars-Peter Clausen 
Signed-off-by: Alexandru Ardelean 
---
 Documentation/ABI/testing/sysfs-bus-iio |   7 ++
 drivers/iio/industrialio-buffer.c   | 128 +++-
 include/linux/iio/buffer.h  |   7 ++
 include/linux/iio/buffer_impl.h |  11 ++
 4 files changed, 149 insertions(+), 4 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-iio 
b/Documentation/ABI/testing/sysfs-bus-iio
index f2a72d7fbacb..a42b915bf585 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -1124,6 +1124,13 @@ Contact: linux-...@vger.kernel.org
 Description:
Number of scans contained by the buffer.
 
+What:  /sys/bus/iio/devices/iio:deviceX/bufferY/direction
+KernelVersion: 5.11
+Contact:   linux-...@vger.kernel.org
+Description:
+   Returns the direction of the data stream of the buffer.
+   The output is "in" or "out".
+
 What:  /sys/bus/iio/devices/iio:deviceX/buffer/enable
 KernelVersion: 2.6.35
 What:  /sys/bus/iio/devices/iio:deviceX/bufferY/enable
diff --git a/drivers/iio/industrialio-buffer.c 
b/drivers/iio/industrialio-buffer.c
index 5d641f8adfbd..b9970c68005d 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -162,6 +162,69 @@ static ssize_t iio_buffer_read(struct file *filp, char 
__user *buf,
return ret;
 }
 
+static size_t iio_buffer_space_available(struct iio_buffer *buf)
+{
+   if (buf->access->space_available)
+   return buf->access->space_available(buf);
+
+   return SIZE_MAX;
+}
+
+static ssize_t iio_buffer_write(struct file *filp, const char __user *buf,
+   size_t n, loff_t *f_ps)
+{
+   struct iio_dev_buffer_pair *ib = filp->private_data;
+   struct iio_buffer *rb = ib->buffer;
+   struct iio_dev *indio_dev = ib->indio_dev;
+   DEFINE_WAIT_FUNC(wait, woken_wake_function);
+   size_t datum_size;
+   size_t to_wait;
+   int ret;
+
+   if (!rb || !rb->access->write)
+   return -EINVAL;
+
+   datum_size = rb->bytes_per_datum;
+
+   /*
+* If datum_size is 0 there will never be anything to read from the
+* buffer, so signal end of file now.
+*/
+   if (!datum_size)
+   return 0;
+
+   if (filp->f_flags & O_NONBLOCK)
+   to_wait = 0;
+   else
+   to_wait = min_t(size_t, n / datum_size, rb->watermark);
+
+   add_wait_queue(>pollq, );
+   do {
+   if (!indio_dev->info) {
+   ret = -ENODEV;
+   break;
+   }
+
+   if (iio_buffer_space_available(rb) < to_wait) {
+   if (signal_pending(current)) {
+   ret = -ERESTARTSYS;
+   break;
+   }
+
+   wait_woken(, TASK_INTERRUPTIBLE,
+  MAX_SCHEDULE_TIMEOUT);
+   continue;
+   }
+
+   ret = rb->access->write(rb, n, buf);
+   if (ret == 0 && (filp->f_flags & O_NONBLOCK))
+   ret = -EAGAIN;
+   } while (ret == 0);
+   remove_wait_queue(>pollq, );
+
+   return ret;
+}
+
 /**
  * iio_buffer_poll() - poll the buffer to find out if it has data
  * @filp:  File structure pointer for device access
@@ -182,8 +245,19 @@ static __poll_t iio_buffer_poll(struct file *filp,
return 0;
 
poll_wait(filp, >pollq, wait);
-   if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0))
-   return EPOLLIN | EPOLLRDNORM;
+
+   switch (rb->direction) {
+   case IIO_BUFFER_DIRECTION_IN:
+   if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0))
+   return EPOLLIN | EPOLLRDNORM;
+

[PATCH v2 3/5] iio: kfifo-buffer: Add output buffer support

2021-02-17 Thread Alexandru Ardelean
From: Lars-Peter Clausen 

Add output buffer support to the kfifo buffer implementation.

The implementation is straight forward and mostly just wraps the kfifo
API to provide the required operations.

Signed-off-by: Lars-Peter Clausen 
Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/buffer/kfifo_buf.c | 50 ++
 1 file changed, 50 insertions(+)

diff --git a/drivers/iio/buffer/kfifo_buf.c b/drivers/iio/buffer/kfifo_buf.c
index 34289ce12f20..e8a434f84778 100644
--- a/drivers/iio/buffer/kfifo_buf.c
+++ b/drivers/iio/buffer/kfifo_buf.c
@@ -138,10 +138,60 @@ static void iio_kfifo_buffer_release(struct iio_buffer 
*buffer)
kfree(kf);
 }
 
+static size_t iio_kfifo_buf_space_available(struct iio_buffer *r)
+{
+   struct iio_kfifo *kf = iio_to_kfifo(r);
+   size_t avail;
+
+   mutex_lock(>user_lock);
+   avail = kfifo_avail(>kf);
+   mutex_unlock(>user_lock);
+
+   return avail;
+}
+
+static int iio_kfifo_remove_from(struct iio_buffer *r, void *data)
+{
+   int ret;
+   struct iio_kfifo *kf = iio_to_kfifo(r);
+
+   if (kfifo_size(>kf) < r->bytes_per_datum)
+   return -EBUSY;
+
+   ret = kfifo_out(>kf, data, r->bytes_per_datum);
+   if (ret != r->bytes_per_datum)
+   return -EBUSY;
+
+   wake_up_interruptible_poll(>pollq, POLLOUT | POLLWRNORM);
+
+   return 0;
+}
+
+static int iio_kfifo_write(struct iio_buffer *r, size_t n,
+   const char __user *buf)
+{
+   struct iio_kfifo *kf = iio_to_kfifo(r);
+   int ret, copied;
+
+   mutex_lock(>user_lock);
+   if (!kfifo_initialized(>kf) || n < kfifo_esize(>kf))
+   ret = -EINVAL;
+   else
+   ret = kfifo_from_user(>kf, buf, n, );
+   mutex_unlock(>user_lock);
+   if (ret)
+   return ret;
+
+   return copied;
+}
+
 static const struct iio_buffer_access_funcs kfifo_access_funcs = {
.store_to = _store_to_kfifo,
.read = _read_kfifo,
.data_available = iio_kfifo_buf_data_available,
+   .remove_from = _kfifo_remove_from,
+   .write = _kfifo_write,
+   .space_available = _kfifo_buf_space_available,
.request_update = _request_update_kfifo,
.set_bytes_per_datum = _set_bytes_per_datum_kfifo,
.set_length = _set_length_kfifo,
-- 
2.17.1



[PATCH v2 1/5] iio: Documentation: update definitions for bufferY and scan_elements

2021-02-17 Thread Alexandru Ardelean
Since the new change to the IIO buffer infrastructure, the buffer/ and
scan_elements/ directories have been merged into bufferY/ to have some
attributes available per-buffer.

This change updates the ABI docs to reflect this change.

The hwfifo attributes are not updated, as for now these should be used
via the legacy buffer/ directory until they are moved into core.

Signed-off-by: Alexandru Ardelean 
---
 Documentation/ABI/testing/sysfs-bus-iio | 85 +
 1 file changed, 85 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-bus-iio 
b/Documentation/ABI/testing/sysfs-bus-iio
index d957f5da5c04..f2a72d7fbacb 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -1118,12 +1118,16 @@ Description:
 
 What:  /sys/bus/iio/devices/iio:deviceX/buffer/length
 KernelVersion: 2.6.35
+What:  /sys/bus/iio/devices/iio:deviceX/bufferY/length
+KernelVersion: 5.11
 Contact:   linux-...@vger.kernel.org
 Description:
Number of scans contained by the buffer.
 
 What:  /sys/bus/iio/devices/iio:deviceX/buffer/enable
 KernelVersion: 2.6.35
+What:  /sys/bus/iio/devices/iio:deviceX/bufferY/enable
+KernelVersion: 5.11
 Contact:   linux-...@vger.kernel.org
 Description:
Actually start the buffer capture up.  Will start trigger
@@ -1131,11 +1135,16 @@ Description:
 
 What:  /sys/bus/iio/devices/iio:deviceX/scan_elements
 KernelVersion: 2.6.37
+What:  /sys/bus/iio/devices/iio:deviceX/buffeY
+KernelVersion: 5.11
 Contact:   linux-...@vger.kernel.org
 Description:
Directory containing interfaces for elements that will be
captured for a single triggered sample set in the buffer.
 
+   Since kernel 5.11 the scan_elements attributes are merged into
+   the bufferY directory, to be configurable per buffer.
+
 What:  /sys/.../iio:deviceX/scan_elements/in_accel_x_en
 What:  /sys/.../iio:deviceX/scan_elements/in_accel_y_en
 What:  /sys/.../iio:deviceX/scan_elements/in_accel_z_en
@@ -1164,6 +1173,34 @@ What:
/sys/.../iio:deviceX/scan_elements/in_pressure_en
 What:  /sys/.../iio:deviceX/scan_elements/in_rot_quaternion_en
 What:  /sys/.../iio:deviceX/scan_elements/in_proximity_en
 KernelVersion: 2.6.37
+What:  /sys/.../iio:deviceX/bufferY/in_accel_x_en
+What:  /sys/.../iio:deviceX/bufferY/in_accel_y_en
+What:  /sys/.../iio:deviceX/bufferY/in_accel_z_en
+What:  /sys/.../iio:deviceX/bufferY/in_anglvel_x_en
+What:  /sys/.../iio:deviceX/bufferY/in_anglvel_y_en
+What:  /sys/.../iio:deviceX/bufferY/in_anglvel_z_en
+What:  /sys/.../iio:deviceX/bufferY/in_magn_x_en
+What:  /sys/.../iio:deviceX/bufferY/in_magn_y_en
+What:  /sys/.../iio:deviceX/bufferY/in_magn_z_en
+What:  /sys/.../iio:deviceX/bufferY/in_rot_from_north_magnetic_en
+What:  /sys/.../iio:deviceX/bufferY/in_rot_from_north_true_en
+What:  
/sys/.../iio:deviceX/bufferY/in_rot_from_north_magnetic_tilt_comp_en
+What:  /sys/.../iio:deviceX/bufferY/in_rot_from_north_true_tilt_comp_en
+What:  /sys/.../iio:deviceX/bufferY/in_timestamp_en
+What:  /sys/.../iio:deviceX/bufferY/in_voltageY_supply_en
+What:  /sys/.../iio:deviceX/bufferY/in_voltageY_en
+What:  /sys/.../iio:deviceX/bufferY/in_voltageY-voltageZ_en
+What:  /sys/.../iio:deviceX/bufferY/in_voltageY_i_en
+What:  /sys/.../iio:deviceX/bufferY/in_voltageY_q_en
+What:  /sys/.../iio:deviceX/bufferY/in_voltage_i_en
+What:  /sys/.../iio:deviceX/bufferY/in_voltage_q_en
+What:  /sys/.../iio:deviceX/bufferY/in_incli_x_en
+What:  /sys/.../iio:deviceX/bufferY/in_incli_y_en
+What:  /sys/.../iio:deviceX/bufferY/in_pressureY_en
+What:  /sys/.../iio:deviceX/bufferY/in_pressure_en
+What:  /sys/.../iio:deviceX/bufferY/in_rot_quaternion_en
+What:  /sys/.../iio:deviceX/bufferY/in_proximity_en
+KernelVersion: 5.11
 Contact:   linux-...@vger.kernel.org
 Description:
Scan element control for triggered data capture.
@@ -1185,6 +1222,23 @@ What:
/sys/.../iio:deviceX/scan_elements/in_pressure_type
 What:  /sys/.../iio:deviceX/scan_elements/in_rot_quaternion_type
 What:  /sys/.../iio:deviceX/scan_elements/in_proximity_type
 KernelVersion: 2.6.37
+What:  /sys/.../iio:deviceX/bufferY/in_accel_type
+What:  /sys/.../iio:deviceX/bufferY/in_anglvel_type
+What:  /sys/.../iio:deviceX/bufferY/in_magn_type
+What:  /sys/.../iio:deviceX/bufferY/in_incli_type
+What:  /sys/.../iio:deviceX/bufferY/in_voltageY_type
+What:  /sys/.../iio:deviceX/bufferY/in_voltage_type
+What:  /sys/.../iio:deviceX/bufferY/in_voltageY_supply_type
+What:  /sys/.../iio:deviceX/bufferY/in_voltageY_i_type
+What

[PATCH v2 0/5] iio: Add output buffer support

2021-02-17 Thread Alexandru Ardelean
This patchset is based on the new multibuffer set.
It doesn't require the high-speed/mmap interface.
That will come later on a v2.

Changelog v1 -> v2:
* 
https://lore.kernel.org/linux-iio/20210212102021.47276-4-alexandru.ardel...@analog.com/T/#u
* removed DMA patches for now
* in patch 'iio: Add output buffer support'
  - added /sys/bus/iio/devices/iio:deviceX/bufferY/direction attribute
  - thinking about this, an update to the new buffer infrastructure is
required when adding ADDAC/MxFE/transceivers; right now there is no
problem, because we have only ADCs and DACs; but when we get
transceivers, a bufferY/ directory needs to filter in/out
scan_elements/ ; this only occured to me recently (it's one of those
things that pops up later in mind)
* added 'iio: Documentation: update definitions for bufferY and scan_elements'
  - seems I forgot this on the original multibuffer patchset
* added 'iio: triggered-buffer: extend support to configure output buffers'
  - basically output triggered buffer support
* added 'iio: dac: ad5686: Add PWM as a trigger source'
  - this is a first user of this infrastructure

Alexandru Ardelean (2):
  iio: Documentation: update definitions for bufferY and scan_elements
  iio: triggered-buffer: extend support to configure output buffers

Lars-Peter Clausen (2):
  iio: Add output buffer support
  iio: kfifo-buffer: Add output buffer support

Mircea Caprioru (1):
  iio: dac: ad5686: Add PWM as a trigger source

 Documentation/ABI/testing/sysfs-bus-iio   |  92 +++
 drivers/iio/accel/adxl372.c   |   1 +
 drivers/iio/accel/bmc150-accel-core.c |   1 +
 drivers/iio/adc/at91-sama5d2_adc.c|   4 +-
 .../buffer/industrialio-triggered-buffer.c|   8 +-
 drivers/iio/buffer/kfifo_buf.c|  50 ++
 .../cros_ec_sensors/cros_ec_sensors_core.c|   1 +
 .../common/hid-sensors/hid-sensor-trigger.c   |   5 +-
 drivers/iio/dac/ad5686-spi.c  |   2 +-
 drivers/iio/dac/ad5686.c  | 146 +-
 drivers/iio/dac/ad5686.h  |   7 +-
 drivers/iio/dac/ad5696-i2c.c  |   2 +-
 drivers/iio/industrialio-buffer.c | 128 ++-
 include/linux/iio/buffer.h|   7 +
 include/linux/iio/buffer_impl.h   |  11 ++
 include/linux/iio/triggered_buffer.h  |  11 +-
 16 files changed, 459 insertions(+), 17 deletions(-)

-- 
2.17.1



[PATCH][RESEND] iio: dac: ad5686: Add support for AD5673R/AD5677R

2021-02-16 Thread Alexandru Ardelean
From: Mircea Caprioru 

The AD5673R/AD5677R are low power, 16-channel, 12-/16-bit buffered voltage
output digital-to-analog converters (DACs). They include a 2.5 V internal
reference (enabled by default).

These devices are very similar to AD5674R/AD5679R, except that they
have an i2c interface.

Signed-off-by: Mircea Caprioru 
Signed-off-by: Alexandru Ardelean 
---

Forgot to include the linux-iio list in the first send.

 drivers/iio/dac/Kconfig  |  5 +++--
 drivers/iio/dac/ad5686.c | 12 
 drivers/iio/dac/ad5686.h |  2 ++
 drivers/iio/dac/ad5696-i2c.c |  6 --
 4 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index cea07b4cced1..75e1f2b48638 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -142,8 +142,9 @@ config AD5696_I2C
select AD5686
help
  Say yes here to build support for Analog Devices AD5311R, AD5338R,
- AD5671R, AD5675R, AD5691R, AD5692R, AD5693, AD5693R, AD5694, AD5694R,
- AD5695R, AD5696, and AD5696R Digital to Analog converters.
+ AD5671R, AD5673R, AD5675R, AD5677R, AD5691R, AD5692R, AD5693, AD5693R,
+ AD5694, AD5694R, AD5695R, AD5696, and AD5696R Digital to Analog
+ converters.
 
  To compile this driver as a module, choose M here: the module will be
  called ad5696.
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 7d6792ac1020..99a95282ac57 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -301,6 +301,12 @@ static const struct ad5686_chip_info 
ad5686_chip_info_tbl[] = {
.num_channels = 8,
.regmap_type = AD5686_REGMAP,
},
+   [ID_AD5673R] = {
+   .channels = ad5674r_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 16,
+   .regmap_type = AD5686_REGMAP,
+   },
[ID_AD5674R] = {
.channels = ad5674r_channels,
.int_vref_mv = 2500,
@@ -324,6 +330,12 @@ static const struct ad5686_chip_info 
ad5686_chip_info_tbl[] = {
.num_channels = 8,
.regmap_type = AD5686_REGMAP,
},
+   [ID_AD5677R] = {
+   .channels = ad5679r_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 16,
+   .regmap_type = AD5686_REGMAP,
+   },
[ID_AD5679R] = {
.channels = ad5679r_channels,
.int_vref_mv = 2500,
diff --git a/drivers/iio/dac/ad5686.h b/drivers/iio/dac/ad5686.h
index d9c8ba413fe9..f89a6f92b427 100644
--- a/drivers/iio/dac/ad5686.h
+++ b/drivers/iio/dac/ad5686.h
@@ -55,10 +55,12 @@ enum ad5686_supported_device_ids {
ID_AD5338R,
ID_AD5671R,
ID_AD5672R,
+   ID_AD5673R,
ID_AD5674R,
ID_AD5675R,
ID_AD5676,
ID_AD5676R,
+   ID_AD5677R,
ID_AD5679R,
ID_AD5681R,
ID_AD5682R,
diff --git a/drivers/iio/dac/ad5696-i2c.c b/drivers/iio/dac/ad5696-i2c.c
index a39eda7c02d2..24a6a4a5a2e0 100644
--- a/drivers/iio/dac/ad5696-i2c.c
+++ b/drivers/iio/dac/ad5696-i2c.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * AD5671R, AD5675R, AD5691R, AD5692R, AD5693, AD5693R,
- * AD5694, AD5694R, AD5695R, AD5696, AD5696R
+ * AD5338R, AD5671R, AD5673R, AD5675R, AD5677R, AD5691R, AD5692R, AD5693,
+ * AD5693R, AD5694, AD5694R, AD5695R, AD5696, AD5696R
  * Digital to analog converters driver
  *
  * Copyright 2018 Analog Devices Inc.
@@ -74,7 +74,9 @@ static const struct i2c_device_id ad5686_i2c_id[] = {
{"ad5311r", ID_AD5311R},
{"ad5338r", ID_AD5338R},
{"ad5671r", ID_AD5671R},
+   {"ad5673r", ID_AD5673R},
{"ad5675r", ID_AD5675R},
+   {"ad5677r", ID_AD5677R},
{"ad5691r", ID_AD5691R},
{"ad5692r", ID_AD5692R},
{"ad5693", ID_AD5693},
-- 
2.17.1



[PATCH v4 6/6] tools: iio: add example for high-speed buffer support

2021-02-16 Thread Alexandru Ardelean
Following a recent update to the IIO buffer infrastructure, this change
adds a basic example on how to access an IIO buffer via the new mmap()
interface.

The ioctl() for the high-speed mode needs to be enabled right from the
start, before setting any parameters via sysfs (length, enable, etc), to
make sure that the mmap mode is used and not the fileio mode.

Signed-off-by: Alexandru Ardelean 
---
 tools/iio/iio_generic_buffer.c | 185 +++--
 1 file changed, 179 insertions(+), 6 deletions(-)

diff --git a/tools/iio/iio_generic_buffer.c b/tools/iio/iio_generic_buffer.c
index 2491c54a5e4f..e7c327fa6091 100644
--- a/tools/iio/iio_generic_buffer.c
+++ b/tools/iio/iio_generic_buffer.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include "iio_utils.h"
 
@@ -239,6 +240,133 @@ static int enable_disable_all_channels(char 
*dev_dir_name, int buffer_idx, int e
return 0;
 }
 
+struct mmap_block {
+   struct iio_buffer_block block;
+   void *addr;
+};
+
+static struct mmap_block *enable_high_speed(int buf_fd, unsigned int 
block_size,
+   int nblocks)
+{
+   struct iio_buffer_block_alloc_req req = { 0 };
+   struct mmap_block *mmaps = NULL;
+   int mmaps_cnt = 0;
+   int i, ret;
+
+   /**
+* Validate we can do high-speed by issuing BLOCK_FREE ioctl.
+* If using just BLOCK_ALLOC it's distinguish between ENOSYS
+* and other error types.
+*/
+   ret = ioctl(buf_fd, IIO_BUFFER_BLOCK_FREE_IOCTL, 0);
+   if (ret < 0) {
+   errno = ENOSYS;
+   return NULL;
+   }
+
+   /* for now, this */
+   req.id = 0;
+   req.type = 0;
+   req.size = block_size;
+   req.count = nblocks;
+
+   ret = ioctl(buf_fd, IIO_BUFFER_BLOCK_ALLOC_IOCTL, );
+   if (ret < 0)
+   return NULL;
+
+   if (req.count == 0) {
+   errno = ENOMEM;
+   return NULL;
+   }
+
+   if (req.count < nblocks) {
+   fprintf(stderr, "Requested %d blocks, got %d\n",
+   nblocks, req.count);
+   errno = ENOMEM;
+   return NULL;
+   }
+
+   mmaps = calloc(req.count, sizeof(*mmaps));
+   if (!mmaps) {
+   errno = ENOMEM;
+   return NULL;
+   }
+
+   for (i = 0; i < req.count; i++) {
+   mmaps[i].block.id = i;
+   ret = ioctl(buf_fd, IIO_BUFFER_BLOCK_QUERY_IOCTL, 
[i].block);
+   if (ret < 0)
+   goto error;
+
+   ret = ioctl(buf_fd, IIO_BUFFER_BLOCK_ENQUEUE_IOCTL, 
[i].block);
+   if (ret < 0)
+   goto error;
+
+   mmaps[i].addr = mmap(0, mmaps[i].block.size,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ buf_fd, mmaps[i].block.data.offset);
+
+   if (mmaps[i].addr == MAP_FAILED)
+   goto error;
+
+   mmaps_cnt++;
+   }
+
+   return mmaps;
+
+error:
+   for (i = 0; i < mmaps_cnt; i++)
+   munmap(mmaps[i].addr, mmaps[i].block.size);
+   free(mmaps);
+   ioctl(buf_fd, IIO_BUFFER_BLOCK_FREE_IOCTL, 0);
+   return NULL;
+}
+
+static int read_high_speed(int buf_fd, char *data, unsigned int block_size,
+  struct mmap_block *mmaps, unsigned int mmaps_cnt)
+{
+   struct iio_buffer_block block;
+   int ret;
+
+   /**
+* This is where some buffer-pool management can do wonders,
+* but for the sake of this sample-code, we're just going to
+* copy the data and re-enqueue it back
+*/
+   memset(, 0, sizeof(block));
+   ret = ioctl(buf_fd, IIO_BUFFER_BLOCK_DEQUEUE_IOCTL, );
+   if (ret < 0)
+   return ret;
+
+   /* check for weird conditions */
+   if (block.bytes_used > block_size) {
+   fprintf(stderr,
+   "Got a bigger block (%u) than expected (%u)\n",
+   block.bytes_used, block_size);
+   return -EFBIG;
+   }
+
+   if (block.bytes_used < block_size) {
+   /**
+* This can be normal, with some real-world data
+* terminating abruptly. But log it.
+*/
+   fprintf(stderr,
+   "Got a smaller block (%u) than expected (%u)\n",
+   block.bytes_used, block_size);
+   }
+
+   /* memcpy() the data, we lose some more performance here :p */
+   memcpy(data, mmaps[block.id].addr, block.bytes_used);
+
+   /* and re-queue this back */
+   ret = ioctl(buf_fd, IIO_BUFFER_BLOCK_ENQUEUE_IOCTL, 
[block.id].block);
+   if (ret < 0)
+   return ret;
+
+   return block.bytes_used;
+}
+
 static

[PATCH v4 5/6] iio: buffer-dma: Add mmap support

2021-02-16 Thread Alexandru Ardelean
From: Lars-Peter Clausen 

Add support for the new mmap interface to IIO DMA buffer. This interface
allows to directly map the backing memory of a block to userspace. This is
especially advantageous for high-speed devices where the extra copy from
kernel space to userspace of the data incurs a significant overhead.

In addition this interface allows more fine grained control over how many
blocks are allocated and their size.

Signed-off-by: Lars-Peter Clausen 
Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/buffer/industrialio-buffer-dma.c  | 279 +-
 .../buffer/industrialio-buffer-dmaengine.c|  22 +-
 include/linux/iio/buffer-dma.h|  22 +-
 3 files changed, 306 insertions(+), 17 deletions(-)

diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c 
b/drivers/iio/buffer/industrialio-buffer-dma.c
index 858af7eea53e..e187c1640b17 100644
--- a/drivers/iio/buffer/industrialio-buffer-dma.c
+++ b/drivers/iio/buffer/industrialio-buffer-dma.c
@@ -90,6 +90,9 @@
  * callback is called from within the custom callback.
  */
 
+static unsigned int iio_dma_buffer_max_block_size = SZ_16M;
+module_param_named(max_block_size, iio_dma_buffer_max_block_size, uint, 0644);
+
 static void iio_buffer_block_release(struct kref *kref)
 {
struct iio_dma_buffer_block *block = container_of(kref,
@@ -97,7 +100,7 @@ static void iio_buffer_block_release(struct kref *kref)
 
WARN_ON(block->state != IIO_BLOCK_STATE_DEAD);
 
-   dma_free_coherent(block->queue->dev, PAGE_ALIGN(block->size),
+   dma_free_coherent(block->queue->dev, PAGE_ALIGN(block->block.size),
block->vaddr, block->phys_addr);
 
iio_buffer_put(>queue->buffer);
@@ -178,7 +181,7 @@ static struct iio_dma_buffer_block 
*iio_dma_buffer_alloc_block(
return NULL;
}
 
-   block->size = size;
+   block->block.size = size;
block->state = IIO_BLOCK_STATE_DEQUEUED;
block->queue = queue;
INIT_LIST_HEAD(>head);
@@ -243,7 +246,7 @@ void iio_dma_buffer_block_list_abort(struct 
iio_dma_buffer_queue *queue,
spin_lock_irqsave(>list_lock, flags);
list_for_each_entry_safe(block, _block, list, head) {
list_del(>head);
-   block->bytes_used = 0;
+   block->block.bytes_used = 0;
_iio_dma_buffer_block_done(block);
iio_buffer_block_put_atomic(block);
}
@@ -296,6 +299,10 @@ int iio_dma_buffer_request_update(struct iio_buffer 
*buffer)
 
mutex_lock(>lock);
 
+   /* If in mmap mode dont do anything */
+   if (queue->num_blocks)
+   goto out_unlock;
+
/* Allocations are page aligned */
if (PAGE_ALIGN(queue->fileio.block_size) == PAGE_ALIGN(size))
try_reuse = true;
@@ -330,7 +337,7 @@ int iio_dma_buffer_request_update(struct iio_buffer *buffer)
iio_buffer_block_put(block);
block = NULL;
} else {
-   block->size = size;
+   block->block.size = size;
}
} else {
block = NULL;
@@ -345,6 +352,8 @@ int iio_dma_buffer_request_update(struct iio_buffer *buffer)
queue->fileio.blocks[i] = block;
}
 
+   block->block.id = i;
+
block->state = IIO_BLOCK_STATE_QUEUED;
list_add_tail(>head, >incoming);
}
@@ -428,6 +437,7 @@ int iio_dma_buffer_enable(struct iio_buffer *buffer,
struct iio_dma_buffer_block *block, *_block;
 
mutex_lock(>lock);
+   queue->fileio.enabled = !queue->num_blocks;
queue->active = true;
list_for_each_entry_safe(block, _block, >incoming, head) {
list_del(>head);
@@ -453,6 +463,7 @@ int iio_dma_buffer_disable(struct iio_buffer *buffer,
struct iio_dma_buffer_queue *queue = iio_buffer_to_queue(buffer);
 
mutex_lock(>lock);
+   queue->fileio.enabled = false;
queue->active = false;
 
if (queue->ops && queue->ops->abort)
@@ -514,6 +525,11 @@ int iio_dma_buffer_read(struct iio_buffer *buffer, size_t 
n,
 
mutex_lock(>lock);
 
+   if (!queue->fileio.enabled) {
+   ret = -EBUSY;
+   goto out_unlock;
+   }
+
if (!queue->fileio.active_block) {
block = iio_dma_buffer_dequeue(queue);
if (block == NULL) {
@@ -527,8 +543,8 @@ int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n,
}
 
n = rounddown(n, buffer->bytes_per_datum);
-   if (n > block->bytes_used - queue->fileio.pos)
-   n = block->bytes_used - queue->fileio.pos;
+   if (n >

[PATCH v4 4/6] iio: buffer-dma: reduce the type of block.size to u32

2021-02-16 Thread Alexandru Ardelean
The type of the 'size' parameter in the block struct is size_t which is
64 bit wide on 64 bit archs.
When the mmap interface gets introduced, we will use a 32 bit field in the
block descriptor for the block size, which will cause some compiler-checks
to fail.

32 bits (4 GB) block sizes should be enough. The idea is to allocate more
blocks if the size of a block grows to 4 GB.

Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/buffer/industrialio-buffer-dmaengine.c | 6 +++---
 include/linux/iio/buffer-dma.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c 
b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
index d76179878ff9..19fbe5d9ef5b 100644
--- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c
+++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
@@ -35,8 +35,8 @@ struct dmaengine_buffer {
struct dma_chan *chan;
struct list_head active;
 
-   size_t align;
-   size_t max_size;
+   u32 align;
+   u32 max_size;
 };
 
 static struct dmaengine_buffer *iio_buffer_to_dmaengine_buffer(
@@ -136,7 +136,7 @@ static ssize_t iio_dmaengine_buffer_get_length_align(struct 
device *dev,
struct dmaengine_buffer *dmaengine_buffer =
iio_buffer_to_dmaengine_buffer(buffer);
 
-   return sprintf(buf, "%zu\n", dmaengine_buffer->align);
+   return sprintf(buf, "%u\n", dmaengine_buffer->align);
 }
 
 static IIO_DEVICE_ATTR(length_align_bytes, 0444,
diff --git a/include/linux/iio/buffer-dma.h b/include/linux/iio/buffer-dma.h
index 6564bdcdac66..9de27d23e791 100644
--- a/include/linux/iio/buffer-dma.h
+++ b/include/linux/iio/buffer-dma.h
@@ -55,7 +55,7 @@ struct iio_dma_buffer_block {
 */
void *vaddr;
dma_addr_t phys_addr;
-   size_t size;
+   u32 size;
struct iio_dma_buffer_queue *queue;
 
/* Must not be accessed outside the core. */
-- 
2.17.1



[PATCH v4 3/6] iio: buffer-dma: split iio_dma_buffer_fileio_free() function

2021-02-16 Thread Alexandru Ardelean
A part of the logic in the iio_dma_buffer_exit() is required for the change
to add mmap support to IIO buffers.
This change splits the logic into a separate function, which will be
re-used later.

Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/buffer/industrialio-buffer-dma.c | 45 +++-
 1 file changed, 25 insertions(+), 20 deletions(-)

diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c 
b/drivers/iio/buffer/industrialio-buffer-dma.c
index d348af8b9705..858af7eea53e 100644
--- a/drivers/iio/buffer/industrialio-buffer-dma.c
+++ b/drivers/iio/buffer/industrialio-buffer-dma.c
@@ -356,6 +356,30 @@ int iio_dma_buffer_request_update(struct iio_buffer 
*buffer)
 }
 EXPORT_SYMBOL_GPL(iio_dma_buffer_request_update);
 
+static void iio_dma_buffer_fileio_free(struct iio_dma_buffer_queue *queue)
+{
+   unsigned int i;
+
+   spin_lock_irq(>list_lock);
+   for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) {
+   if (!queue->fileio.blocks[i])
+   continue;
+   queue->fileio.blocks[i]->state = IIO_BLOCK_STATE_DEAD;
+   }
+   INIT_LIST_HEAD(>outgoing);
+   spin_unlock_irq(>list_lock);
+
+   INIT_LIST_HEAD(>incoming);
+
+   for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) {
+   if (!queue->fileio.blocks[i])
+   continue;
+   iio_buffer_block_put(queue->fileio.blocks[i]);
+   queue->fileio.blocks[i] = NULL;
+   }
+   queue->fileio.active_block = NULL;
+}
+
 static void iio_dma_buffer_submit_block(struct iio_dma_buffer_queue *queue,
struct iio_dma_buffer_block *block)
 {
@@ -635,28 +659,9 @@ EXPORT_SYMBOL_GPL(iio_dma_buffer_init);
  */
 void iio_dma_buffer_exit(struct iio_dma_buffer_queue *queue)
 {
-   unsigned int i;
-
mutex_lock(>lock);
 
-   spin_lock_irq(>list_lock);
-   for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) {
-   if (!queue->fileio.blocks[i])
-   continue;
-   queue->fileio.blocks[i]->state = IIO_BLOCK_STATE_DEAD;
-   }
-   INIT_LIST_HEAD(>outgoing);
-   spin_unlock_irq(>list_lock);
-
-   INIT_LIST_HEAD(>incoming);
-
-   for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) {
-   if (!queue->fileio.blocks[i])
-   continue;
-   iio_buffer_block_put(queue->fileio.blocks[i]);
-   queue->fileio.blocks[i] = NULL;
-   }
-   queue->fileio.active_block = NULL;
+   iio_dma_buffer_fileio_free(queue);
queue->ops = NULL;
 
mutex_unlock(>lock);
-- 
2.17.1



[PATCH v4 2/6] Documentation: iio: add doc for high-speed buffer API

2021-02-16 Thread Alexandru Ardelean
This change takes the comment from the commit that introduces the IIO
high-speed buffer API, and formats it into rst format.

Signed-off-by: Alexandru Ardelean 
---
 Documentation/iio/iio_high_speed_buffers.rst | 100 +++
 Documentation/iio/index.rst  |   2 +
 include/uapi/linux/iio/buffer.h  |   5 +
 3 files changed, 107 insertions(+)
 create mode 100644 Documentation/iio/iio_high_speed_buffers.rst

diff --git a/Documentation/iio/iio_high_speed_buffers.rst 
b/Documentation/iio/iio_high_speed_buffers.rst
new file mode 100644
index ..f326e68efe49
--- /dev/null
+++ b/Documentation/iio/iio_high_speed_buffers.rst
@@ -0,0 +1,100 @@
+===
+Industrial IO High-Speed Buffer API
+===
+
+1. Overview
+===
+
+Industrial IO supports access to buffers via an mmap interface. The
+advantage of the mmap based interface compared to the read() based
+interface is that it avoids an extra copy of the data between kernel and
+userspace. This is particular useful for high-speed devices which produce
+several megabytes or even gigabytes of data per second.
+
+The data for the mmap interface is managed at the granularity of so called
+blocks. A block is a contiguous region of memory (at the moment both
+physically and virtually contiguous). Reducing the granularity from byte
+level to block level is done to reduce the userspace-kernelspace
+synchronization overhead since performing syscalls for each byte at a
+data-rate of a few megabytes is not feasible.
+
+This of course leads to a slightly increased latency. For this reason an
+application can choose the size of the blocks as well as how many blocks it
+allocates. E.g. two blocks would be a traditional double buffering scheme.
+But using a higher number might be necessary to avoid underflow/overflow
+situations in the presence of scheduling latencies.
+
+A block can either be owned by kernel space or userspace. When owned by
+userspace it is safe to access the data in the block and process it. When
+owned by kernel space the block can be in one of 3 states:
+
+* It can be in the incoming queue where all blocks submitted from userspace
+  are placed and are waiting to be processed by the kernel driver.
+* It can be currently being processed by the kernel driver, this means it is
+  actively placing capturing data in it (usually using DMA).
+* Or it can be in the outgoing queue where all blocks that have been
+  processed by the kernel are placed. Userspace can dequeue the blocks as
+  necessary.
+
+2. Interface
+
+
+As part of the interface 5 IOCTLs are used to manage the blocks and exchange
+them between userspace and kernelspace. The IOCTLs can be accessed through
+a open file descriptor to a IIO device.
+
+* **IIO_BUFFER_BLOCK_ALLOC_IOCTL(struct iio_buffer_block_alloc_req *)**:
+Allocates new blocks. Can be called multiple times if necessary. A newly
+allocated block is initially owned by userspace.
+
+* **IIO_BUFFER_BLOCK_FREE_IOCTL(void)**:
+   Frees all previously allocated blocks. If the backing memory of a block is
+   still in use by a kernel driver (i.e. active DMA transfer) it will be
+   freed once the kernel driver has released it.
+
+* **IIO_BUFFER_BLOCK_QUERY_IOCTL(struct iio_buffer_block *)**:
+   Queries information about a block. The id of the block about which
+   information is to be queried needs to be set by userspace.
+
+* **IIO_BUFFER_BLOCK_ENQUEUE_IOCTL(struct iio_buffer_block *)**:
+   Places a block on the incoming queue. This transfers ownership of the
+   block from userspace to kernelspace. Userspace must populate the id field
+   of the block to indicate which block to enqueue.
+
+* **IIO_BUFFER_BLOCK_DEQUEUE_IOCTL(struct iio_buffer_block *)**:
+   Removes the first block from the outgoing queue. This transfers ownership
+   of the block from kernelspace to userspace. Kernelspace will populate all
+   fields of the block. If the queue is empty and the file descriptor is set
+   to blocking the IOCTL will block until a new block is available on the
+   outgoing queue.
+
+3. Usage
+
+
+To access the data stored in a block by userspace the block must be mapped
+to the process's memory. This is done by calling mmap() on the IIO device
+file descriptor. Each block has a unique offset assigned to it which should
+be passed to the mmap interface. E.g.
+
+  mmap(0, block.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+   block.offset);
+
+A typical workflow for the new interface is:
+
+  BLOCK_ALLOC
+
+  foreach block
+ BLOCK_QUERY block
+mmap block.data.offset
+BLOCK_ENQUEUE block
+
+  enable buffer
+
+  while !done
+   BLOCK_DEQUEUE block
+   process data
+   BLOCK_ENQUEUE block
+
+  disable buffer
+
+  BLOCK_FREE
diff --git a/Documentation/iio/index.rst b/Documentation/iio/index.rst
index 58b7a4ebac51..aaba78770b47 100644
--- a/Documentation/iio/index.rst
+++ b

[PATCH v4 1/6] iio: core: Add mmap interface infrastructure

2021-02-16 Thread Alexandru Ardelean
From: Lars-Peter Clausen 

Add the necessary infrastructure to the IIO core to support an mmap based
interface to access the capture data.

The advantage of the mmap based interface compared to the read() based
interface is that it avoids an extra copy of the data between kernel and
userspace. This is particular useful for high-speed devices which produce
several megabytes or even gigabytes of data per second.

The data for the mmap interface is managed at the granularity of so called
blocks. A block is a contiguous region of memory (at the moment both
physically and virtually contiguous). Reducing the granularity from byte
level to block level is done to reduce the userspace-kernelspace
synchronization overhead since performing syscalls for each byte at a
data-rate of a few megabytes is not feasible.

This of course leads to a slightly increased latency. For this reason an
application can choose the size of the blocks as well as how many blocks it
allocates. E.g. two blocks would be a traditional double buffering scheme.
But using a higher number might be necessary to avoid underflow/overflow
situations in the presence of scheduling latencies.

A block can either be owned by kernel space or userspace. When owned by
userspace it save to access the data in the block and process it. When
owned by kernel space the block can be in one of 3 states.

It can be in the incoming queue where all blocks submitted from userspace
are placed and are waiting to be processed by the kernel driver.

It can be currently being processed by the kernel driver, this means it is
actively placing capturing data in it (usually using DMA).

Or it can be in the outgoing queue where all blocks that have been
processed by the kernel are placed. Userspace can dequeue the blocks as
necessary.

As part of the interface 5 new IOCTLs to manage the blocks and exchange
them between userspace and kernelspace. The IOCTLs can be accessed through
a open file descriptor to a IIO device.

IIO_BUFFER_BLOCK_ALLOC_IOCTL(struct iio_buffer_block_alloc_req *):
 Allocates new blocks. Can be called multiple times if necessary. A newly
 allocated block is initially owned by userspace.

IIO_BUFFER_BLOCK_FREE_IOCTL(void):
 Frees all previously allocated blocks. If the backing memory of a block is
 still in use by a kernel driver (i.e. active DMA transfer) it will be
 freed once the kernel driver has released it.

IIO_BUFFER_BLOCK_QUERY_IOCTL(struct iio_buffer_block *):
 Queries information about a block. The id of the block about which
 information is to be queried needs to be set by userspace.

IIO_BUFFER_BLOCK_ENQUEUE_IOCTL(struct iio_buffer_block *):
 Places a block on the incoming queue. This transfers ownership of the
 block from userspace to kernelspace. Userspace must populate the id field
 of the block to indicate which block to enqueue.

IIO_BUFFER_BLOCK_DEQUEUE_IOCTL(struct iio_buffer_block *):
 Removes the first block from the outgoing queue. This transfers ownership
 of the block from kernelspace to userspace. Kernelspace will populate all
 fields of the block. If the queue is empty and the file descriptor is set
 to blocking the IOCTL will block until a new block is available on the
 outgoing queue.

To access the data stored in a block by userspace the block must be mapped
to the process's memory. This is done by calling mmap() on the IIO device
file descriptor. Each block has a unique offset assigned to it which should
be passed to the mmap interface. E.g.

  mmap(0, block.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
   block.offset);

A typical workflow for the new interface is:

  BLOCK_ALLOC

  foreach block
 BLOCK_QUERY block
 mmap block.data.offset
 BLOCK_ENQUEUE block

  enable buffer

  while !done
BLOCK_DEQUEUE block
process data
BLOCK_ENQUEUE block

  disable buffer

  BLOCK_FREE

Signed-off-by: Lars-Peter Clausen 
Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/industrialio-buffer.c | 158 ++
 include/linux/iio/buffer-dma.h|   5 -
 include/linux/iio/buffer_impl.h   |  23 +
 include/uapi/linux/iio/buffer.h   |  46 +
 4 files changed, 227 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/industrialio-buffer.c 
b/drivers/iio/industrialio-buffer.c
index 4848932d4394..5d641f8adfbd 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -1371,6 +1372,12 @@ static void 
iio_buffer_unregister_legacy_sysfs_groups(struct iio_dev *indio_dev)
kfree(iio_dev_opaque->legacy_scan_el_group.attrs);
 }
 
+static void iio_buffer_free_blocks(struct iio_buffer *buffer)
+{
+   if (buffer->access->free_blocks)
+   buffer->access->free_blocks(buffer);
+}
+
 static int iio_buffer_chrdev_release(struct inode *inode, struct file *filep)
 {
struct iio_dev_buffer_pair *ib = filep->private

[PATCH v4 0/6] iio: core: Add mmap interface infrastructure

2021-02-16 Thread Alexandru Ardelean
Changelog v3 -> v4:
* 
https://lore.kernel.org/linux-iio/20210215143234.3248-5-alexandru.ardel...@analog.com/T/
* added patch 'iio: buffer-dma: reduce the type of block.size to u32'
  - resolves error on 64 bit archs; 32 bit block size should be enough
* in patch 'iio: buffer-dma: Add mmap support'
  - added 'linux/types.h' include in uapi buffer.h header; an error
shows up when building with 'make allmodconfig'
* in patch 'tools: iio: add example for high-speed buffer support'
  - calling ioctl(BOCK_FREE) only if use_high_speed is true

Changelog v2 -> v3:
* 
https://lore.kernel.org/linux-iio/20210212101143.18993-1-alexandru.ardel...@analog.com/T/#u
* added 'Documentation: iio: add doc for high-speed buffer API'
* add 'iio: buffer-dma: split iio_dma_buffer_fileio_free() function'
* patch 'iio: buffer-dma: Add mmap support'
   - unwind free on error path in iio_dma_buffer_alloc_blocks()
   - removed double mm.h include
* patch 'tools: iio: add example for high-speed buffer support'
   - call IIO_BUFFER_BLOCK_FREE_IOCTL on the error path of the
 enable_high_speed() function

Changelog v1 -> v2:
* 
https://lore.kernel.org/linux-iio/20210211123353.78963-1-alexandru.ardel...@analog.com/T/#t
* removed IIO_BUFFER_BLOCK_FLAG_CYCLIC flag; will be added in a later
  patch
* removed extra line in tools/iio/iio_generic_buffer.c
* patch 'iio: core: Add mmap interface infrastructure'
  added docstrings for new hooks (alloc_blocks, mmap, etc)

This is basically Lars' work adapted from branch:
  https://github.com/larsclausen/linux/commits/iio-high-speed-5.10
[hopefully i got the stuff correctly from that branch]

What is different, is that this one is adapted on top of the multibuffer
support (currently at v5) discussed here:
  
https://lore.kernel.org/linux-iio/20210211122452.78106-1-alexandru.ardel...@analog.com/T/#t

Also, adapted an example for high-speed/mmap support in
'tools/iio/iio_generic_buffer.c'

The example is adapted from libiio:
  https://github.com/analogdevicesinc/libiio/blob/master/local.c#L51
but will all the ioctl()s organized after the one that are reserved
(hopefully) for IIO

Tested that mmap() works.
Moved (artifically) valid buffer0 as buffer2 and the operation still
works.

Alexandru Ardelean (4):
  Documentation: iio: add doc for high-speed buffer API
  iio: buffer-dma: split iio_dma_buffer_fileio_free() function
  iio: buffer-dma: reduce the type of block.size to u32
  tools: iio: add example for high-speed buffer support

Lars-Peter Clausen (2):
  iio: core: Add mmap interface infrastructure
  iio: buffer-dma: Add mmap support

 Documentation/iio/iio_high_speed_buffers.rst  | 100 ++
 Documentation/iio/index.rst   |   2 +
 drivers/iio/buffer/industrialio-buffer-dma.c  | 324 --
 .../buffer/industrialio-buffer-dmaengine.c|  28 +-
 drivers/iio/industrialio-buffer.c | 158 +
 include/linux/iio/buffer-dma.h|  27 +-
 include/linux/iio/buffer_impl.h   |  23 ++
 include/uapi/linux/iio/buffer.h   |  51 +++
 tools/iio/iio_generic_buffer.c| 185 +-
 9 files changed, 847 insertions(+), 51 deletions(-)
 create mode 100644 Documentation/iio/iio_high_speed_buffers.rst

-- 
2.17.1



Re: [PATCH v3 0/5] iio: core: Add mmap interface infrastructure

2021-02-16 Thread Alexandru Ardelean
On Tue, Feb 16, 2021 at 10:02 PM Jonathan Cameron  wrote:
>
> On Mon, 15 Feb 2021 16:32:29 +0200
> Alexandru Ardelean  wrote:
>
>
> Hi Alex,
>
> I'm a little nervous about adding the userspace interface used in this
> series, but it seems reasonable and as you say below, is close to what
> Analog have been using for years.
>
> So I've applied it to the togreg branch of iio.git and pushed out as
> testing as normal.   I'm not going to push that out as anything I can't
> rebase for at least a few weeks, so if anyone else wants to take a look
> that would be great.
>

Oops.
I actually was preparing a new version yesterday with a fix for this
and a few tweaks.
This issue seems to appear on 64 bit only.

Will send it.


> One slight tweak was needed. I forced it with min_t(size_t,...
> as it should always be at least as bit as __u32 so should be fine.
>
>   CHECK   drivers/iio/industrialio-core.c
> In file included from ./include/linux/kernel.h:14,
>  from ./include/asm-generic/bug.h:20,
>  from ./arch/x86/include/asm/bug.h:93,
>  from ./include/linux/bug.h:5,
>  from ./include/linux/mmdebug.h:5,
>  from ./include/linux/gfp.h:5,
>  from ./include/linux/slab.h:15,
>  from drivers/iio/buffer/industrialio-buffer-dmaengine.c:7:
> drivers/iio/buffer/industrialio-buffer-dmaengine.c: In function 
> ‘iio_dmaengine_buffer_submit_block’:
> ./include/linux/minmax.h:18:28: warning: comparison of distinct pointer types 
> lacks a cast
>18 |  (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
>   |^~
> ./include/linux/minmax.h:32:4: note: in expansion of macro ‘__typecheck’
>32 |   (__typecheck(x, y) && __no_side_effects(x, y))
>   |^~~
> ./include/linux/minmax.h:42:24: note: in expansion of macro ‘__safe_cmp’
>42 |  __builtin_choose_expr(__safe_cmp(x, y), \
>   |^~
> ./include/linux/minmax.h:51:19: note: in expansion of macro ‘__careful_cmp’
>51 | #define min(x, y) __careful_cmp(x, y, <)
>   |   ^
> drivers/iio/buffer/industrialio-buffer-dmaengine.c:69:28: note: in expansion 
> of macro ‘min’
>69 |  block->block.bytes_used = min(block->block.size,
>   |^~~
>   CHECK   drivers/iio/buffer/industrialio-buffer-dmaengine.c
>   CHECK   drivers/iio/industrialio-buffer.c
> drivers/iio/buffer/industrialio-buffer-dmaengine.c:69:35: error: incompatible 
> types in comparison expression (different type sizes):
> drivers/iio/buffer/industrialio-buffer-dmaengine.c:69:35:unsigned int *
> drivers/iio/buffer/industrialio-buffer-dmaengine.c:69:35:unsigned long *
>
> Thanks,
>
> Jonathan
>
>
> > Changelog v2 -> v3:
> > * 
> > https://lore.kernel.org/linux-iio/20210212101143.18993-1-alexandru.ardel...@analog.com/T/#u
> > * added 'Documentation: iio: add doc for high-speed buffer API'
> > * add 'iio: buffer-dma: split iio_dma_buffer_fileio_free() function'
> > * patch 'iio: buffer-dma: Add mmap support'
> >- unwind free on error path in iio_dma_buffer_alloc_blocks()
> >- removed double mm.h include
> > * patch 'tools: iio: add example for high-speed buffer support'
> >- call IIO_BUFFER_BLOCK_FREE_IOCTL on the error path of the
> >  enable_high_speed() function
> >
> > Changelog v1 -> v2:
> > * 
> > https://lore.kernel.org/linux-iio/20210211123353.78963-1-alexandru.ardel...@analog.com/T/#t
> > * removed IIO_BUFFER_BLOCK_FLAG_CYCLIC flag; will be added in a later
> >   patch
> > * removed extra line in tools/iio/iio_generic_buffer.c
> > * patch 'iio: core: Add mmap interface infrastructure'
> >   added docstrings for new hooks (alloc_blocks, mmap, etc)
> >
> > This is basically Lars' work adapted from branch:
> >   https://github.com/larsclausen/linux/commits/iio-high-speed-5.10
> > [hopefully i got the stuff correctly from that branch]
> >
> > What is different, is that this one is adapted on top of the multibuffer
> > support (currently at v5) discussed here:
> >   
> > https://lore.kernel.org/linux-iio/20210211122452.78106-1-alexandru.ardel...@analog.com/T/#t
> >
> > Also, adapted an example for high-speed/mmap support in
> > 'tools/iio/iio_generic_buffer.c'
> >
> > The example is adapted from libiio:
> >   https://github.com/analogdevicesinc/libiio/blob/master/local.c#L51
> > but will all the ioctl()s organized after the one that are reserved
> > (hopefully) for IIO
> >
> > Tested that mmap() works.
> > Moved (a

[PATCH] iio: dac: ad5686: Add support for AD5673R/AD5677R

2021-02-16 Thread Alexandru Ardelean
From: Mircea Caprioru 

The AD5673R/AD5677R are low power, 16-channel, 12-/16-bit buffered voltage
output digital-to-analog converters (DACs). They include a 2.5 V internal
reference (enabled by default).

These devices are very similar to AD5674R/AD5679R, except that they
have an i2c interface.

Signed-off-by: Mircea Caprioru 
Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/dac/Kconfig  |  5 +++--
 drivers/iio/dac/ad5686.c | 12 
 drivers/iio/dac/ad5686.h |  2 ++
 drivers/iio/dac/ad5696-i2c.c |  6 --
 4 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index cea07b4cced1..75e1f2b48638 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -142,8 +142,9 @@ config AD5696_I2C
select AD5686
help
  Say yes here to build support for Analog Devices AD5311R, AD5338R,
- AD5671R, AD5675R, AD5691R, AD5692R, AD5693, AD5693R, AD5694, AD5694R,
- AD5695R, AD5696, and AD5696R Digital to Analog converters.
+ AD5671R, AD5673R, AD5675R, AD5677R, AD5691R, AD5692R, AD5693, AD5693R,
+ AD5694, AD5694R, AD5695R, AD5696, and AD5696R Digital to Analog
+ converters.
 
  To compile this driver as a module, choose M here: the module will be
  called ad5696.
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 7d6792ac1020..99a95282ac57 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -301,6 +301,12 @@ static const struct ad5686_chip_info 
ad5686_chip_info_tbl[] = {
.num_channels = 8,
.regmap_type = AD5686_REGMAP,
},
+   [ID_AD5673R] = {
+   .channels = ad5674r_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 16,
+   .regmap_type = AD5686_REGMAP,
+   },
[ID_AD5674R] = {
.channels = ad5674r_channels,
.int_vref_mv = 2500,
@@ -324,6 +330,12 @@ static const struct ad5686_chip_info 
ad5686_chip_info_tbl[] = {
.num_channels = 8,
.regmap_type = AD5686_REGMAP,
},
+   [ID_AD5677R] = {
+   .channels = ad5679r_channels,
+   .int_vref_mv = 2500,
+   .num_channels = 16,
+   .regmap_type = AD5686_REGMAP,
+   },
[ID_AD5679R] = {
.channels = ad5679r_channels,
.int_vref_mv = 2500,
diff --git a/drivers/iio/dac/ad5686.h b/drivers/iio/dac/ad5686.h
index d9c8ba413fe9..f89a6f92b427 100644
--- a/drivers/iio/dac/ad5686.h
+++ b/drivers/iio/dac/ad5686.h
@@ -55,10 +55,12 @@ enum ad5686_supported_device_ids {
ID_AD5338R,
ID_AD5671R,
ID_AD5672R,
+   ID_AD5673R,
ID_AD5674R,
ID_AD5675R,
ID_AD5676,
ID_AD5676R,
+   ID_AD5677R,
ID_AD5679R,
ID_AD5681R,
ID_AD5682R,
diff --git a/drivers/iio/dac/ad5696-i2c.c b/drivers/iio/dac/ad5696-i2c.c
index a39eda7c02d2..24a6a4a5a2e0 100644
--- a/drivers/iio/dac/ad5696-i2c.c
+++ b/drivers/iio/dac/ad5696-i2c.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * AD5671R, AD5675R, AD5691R, AD5692R, AD5693, AD5693R,
- * AD5694, AD5694R, AD5695R, AD5696, AD5696R
+ * AD5338R, AD5671R, AD5673R, AD5675R, AD5677R, AD5691R, AD5692R, AD5693,
+ * AD5693R, AD5694, AD5694R, AD5695R, AD5696, AD5696R
  * Digital to analog converters driver
  *
  * Copyright 2018 Analog Devices Inc.
@@ -74,7 +74,9 @@ static const struct i2c_device_id ad5686_i2c_id[] = {
{"ad5311r", ID_AD5311R},
{"ad5338r", ID_AD5338R},
{"ad5671r", ID_AD5671R},
+   {"ad5673r", ID_AD5673R},
{"ad5675r", ID_AD5675R},
+   {"ad5677r", ID_AD5677R},
{"ad5691r", ID_AD5691R},
{"ad5692r", ID_AD5692R},
{"ad5693", ID_AD5693},
-- 
2.17.1



[PATCH v3 4/5] iio: buffer-dma: Add mmap support

2021-02-15 Thread Alexandru Ardelean
From: Lars-Peter Clausen 

Add support for the new mmap interface to IIO DMA buffer. This interface
allows to directly map the backing memory of a block to userspace. This is
especially advantageous for high-speed devices where the extra copy from
kernel space to userspace of the data incurs a significant overhead.

In addition this interface allows more fine grained control over how many
blocks are allocated and their size.

Signed-off-by: Lars-Peter Clausen 
Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/buffer/industrialio-buffer-dma.c  | 279 +-
 .../buffer/industrialio-buffer-dmaengine.c|  22 +-
 include/linux/iio/buffer-dma.h|  22 +-
 3 files changed, 306 insertions(+), 17 deletions(-)

diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c 
b/drivers/iio/buffer/industrialio-buffer-dma.c
index 858af7eea53e..e187c1640b17 100644
--- a/drivers/iio/buffer/industrialio-buffer-dma.c
+++ b/drivers/iio/buffer/industrialio-buffer-dma.c
@@ -90,6 +90,9 @@
  * callback is called from within the custom callback.
  */
 
+static unsigned int iio_dma_buffer_max_block_size = SZ_16M;
+module_param_named(max_block_size, iio_dma_buffer_max_block_size, uint, 0644);
+
 static void iio_buffer_block_release(struct kref *kref)
 {
struct iio_dma_buffer_block *block = container_of(kref,
@@ -97,7 +100,7 @@ static void iio_buffer_block_release(struct kref *kref)
 
WARN_ON(block->state != IIO_BLOCK_STATE_DEAD);
 
-   dma_free_coherent(block->queue->dev, PAGE_ALIGN(block->size),
+   dma_free_coherent(block->queue->dev, PAGE_ALIGN(block->block.size),
block->vaddr, block->phys_addr);
 
iio_buffer_put(>queue->buffer);
@@ -178,7 +181,7 @@ static struct iio_dma_buffer_block 
*iio_dma_buffer_alloc_block(
return NULL;
}
 
-   block->size = size;
+   block->block.size = size;
block->state = IIO_BLOCK_STATE_DEQUEUED;
block->queue = queue;
INIT_LIST_HEAD(>head);
@@ -243,7 +246,7 @@ void iio_dma_buffer_block_list_abort(struct 
iio_dma_buffer_queue *queue,
spin_lock_irqsave(>list_lock, flags);
list_for_each_entry_safe(block, _block, list, head) {
list_del(>head);
-   block->bytes_used = 0;
+   block->block.bytes_used = 0;
_iio_dma_buffer_block_done(block);
iio_buffer_block_put_atomic(block);
}
@@ -296,6 +299,10 @@ int iio_dma_buffer_request_update(struct iio_buffer 
*buffer)
 
mutex_lock(>lock);
 
+   /* If in mmap mode dont do anything */
+   if (queue->num_blocks)
+   goto out_unlock;
+
/* Allocations are page aligned */
if (PAGE_ALIGN(queue->fileio.block_size) == PAGE_ALIGN(size))
try_reuse = true;
@@ -330,7 +337,7 @@ int iio_dma_buffer_request_update(struct iio_buffer *buffer)
iio_buffer_block_put(block);
block = NULL;
} else {
-   block->size = size;
+   block->block.size = size;
}
} else {
block = NULL;
@@ -345,6 +352,8 @@ int iio_dma_buffer_request_update(struct iio_buffer *buffer)
queue->fileio.blocks[i] = block;
}
 
+   block->block.id = i;
+
block->state = IIO_BLOCK_STATE_QUEUED;
list_add_tail(>head, >incoming);
}
@@ -428,6 +437,7 @@ int iio_dma_buffer_enable(struct iio_buffer *buffer,
struct iio_dma_buffer_block *block, *_block;
 
mutex_lock(>lock);
+   queue->fileio.enabled = !queue->num_blocks;
queue->active = true;
list_for_each_entry_safe(block, _block, >incoming, head) {
list_del(>head);
@@ -453,6 +463,7 @@ int iio_dma_buffer_disable(struct iio_buffer *buffer,
struct iio_dma_buffer_queue *queue = iio_buffer_to_queue(buffer);
 
mutex_lock(>lock);
+   queue->fileio.enabled = false;
queue->active = false;
 
if (queue->ops && queue->ops->abort)
@@ -514,6 +525,11 @@ int iio_dma_buffer_read(struct iio_buffer *buffer, size_t 
n,
 
mutex_lock(>lock);
 
+   if (!queue->fileio.enabled) {
+   ret = -EBUSY;
+   goto out_unlock;
+   }
+
if (!queue->fileio.active_block) {
block = iio_dma_buffer_dequeue(queue);
if (block == NULL) {
@@ -527,8 +543,8 @@ int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n,
}
 
n = rounddown(n, buffer->bytes_per_datum);
-   if (n > block->bytes_used - queue->fileio.pos)
-   n = block->bytes_used - queue->fileio.pos;
+   if (n >

[PATCH v3 5/5] tools: iio: add example for high-speed buffer support

2021-02-15 Thread Alexandru Ardelean
Following a recent update to the IIO buffer infrastructure, this change
adds a basic example on how to access an IIO buffer via the new mmap()
interface.

The ioctl() for the high-speed mode needs to be enabled right from the
start, before setting any parameters via sysfs (length, enable, etc), to
make sure that the mmap mode is used and not the fileio mode.

Signed-off-by: Alexandru Ardelean 
---
 tools/iio/iio_generic_buffer.c | 184 +++--
 1 file changed, 178 insertions(+), 6 deletions(-)

diff --git a/tools/iio/iio_generic_buffer.c b/tools/iio/iio_generic_buffer.c
index 2491c54a5e4f..99dcc3b339b1 100644
--- a/tools/iio/iio_generic_buffer.c
+++ b/tools/iio/iio_generic_buffer.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include "iio_utils.h"
 
@@ -239,6 +240,133 @@ static int enable_disable_all_channels(char 
*dev_dir_name, int buffer_idx, int e
return 0;
 }
 
+struct mmap_block {
+   struct iio_buffer_block block;
+   void *addr;
+};
+
+static struct mmap_block *enable_high_speed(int buf_fd, unsigned int 
block_size,
+   int nblocks)
+{
+   struct iio_buffer_block_alloc_req req = { 0 };
+   struct mmap_block *mmaps = NULL;
+   int mmaps_cnt = 0;
+   int i, ret;
+
+   /**
+* Validate we can do high-speed by issuing BLOCK_FREE ioctl.
+* If using just BLOCK_ALLOC it's distinguish between ENOSYS
+* and other error types.
+*/
+   ret = ioctl(buf_fd, IIO_BUFFER_BLOCK_FREE_IOCTL, 0);
+   if (ret < 0) {
+   errno = ENOSYS;
+   return NULL;
+   }
+
+   /* for now, this */
+   req.id = 0;
+   req.type = 0;
+   req.size = block_size;
+   req.count = nblocks;
+
+   ret = ioctl(buf_fd, IIO_BUFFER_BLOCK_ALLOC_IOCTL, );
+   if (ret < 0)
+   return NULL;
+
+   if (req.count == 0) {
+   errno = ENOMEM;
+   return NULL;
+   }
+
+   if (req.count < nblocks) {
+   fprintf(stderr, "Requested %d blocks, got %d\n",
+   nblocks, req.count);
+   errno = ENOMEM;
+   return NULL;
+   }
+
+   mmaps = calloc(req.count, sizeof(*mmaps));
+   if (!mmaps) {
+   errno = ENOMEM;
+   return NULL;
+   }
+
+   for (i = 0; i < req.count; i++) {
+   mmaps[i].block.id = i;
+   ret = ioctl(buf_fd, IIO_BUFFER_BLOCK_QUERY_IOCTL, 
[i].block);
+   if (ret < 0)
+   goto error;
+
+   ret = ioctl(buf_fd, IIO_BUFFER_BLOCK_ENQUEUE_IOCTL, 
[i].block);
+   if (ret < 0)
+   goto error;
+
+   mmaps[i].addr = mmap(0, mmaps[i].block.size,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ buf_fd, mmaps[i].block.data.offset);
+
+   if (mmaps[i].addr == MAP_FAILED)
+   goto error;
+
+   mmaps_cnt++;
+   }
+
+   return mmaps;
+
+error:
+   for (i = 0; i < mmaps_cnt; i++)
+   munmap(mmaps[i].addr, mmaps[i].block.size);
+   free(mmaps);
+   ioctl(buf_fd, IIO_BUFFER_BLOCK_FREE_IOCTL, 0);
+   return NULL;
+}
+
+static int read_high_speed(int buf_fd, char *data, unsigned int block_size,
+  struct mmap_block *mmaps, unsigned int mmaps_cnt)
+{
+   struct iio_buffer_block block;
+   int ret;
+
+   /**
+* This is where some buffer-pool management can do wonders,
+* but for the sake of this sample-code, we're just going to
+* copy the data and re-enqueue it back
+*/
+   memset(, 0, sizeof(block));
+   ret = ioctl(buf_fd, IIO_BUFFER_BLOCK_DEQUEUE_IOCTL, );
+   if (ret < 0)
+   return ret;
+
+   /* check for weird conditions */
+   if (block.bytes_used > block_size) {
+   fprintf(stderr,
+   "Got a bigger block (%u) than expected (%u)\n",
+   block.bytes_used, block_size);
+   return -EFBIG;
+   }
+
+   if (block.bytes_used < block_size) {
+   /**
+* This can be normal, with some real-world data
+* terminating abruptly. But log it.
+*/
+   fprintf(stderr,
+   "Got a smaller block (%u) than expected (%u)\n",
+   block.bytes_used, block_size);
+   }
+
+   /* memcpy() the data, we lose some more performance here :p */
+   memcpy(data, mmaps[block.id].addr, block.bytes_used);
+
+   /* and re-queue this back */
+   ret = ioctl(buf_fd, IIO_BUFFER_BLOCK_ENQUEUE_IOCTL, 
[block.id].block);
+   if (ret < 0)
+   return ret;
+
+   return block.bytes_used;
+}
+
 static

[PATCH v3 3/5] iio: buffer-dma: split iio_dma_buffer_fileio_free() function

2021-02-15 Thread Alexandru Ardelean
A part of the logic in the iio_dma_buffer_exit() is required for the change
to add mmap support to IIO buffers.
This change splits the logic into a separate function, which will be
re-used later.

Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/buffer/industrialio-buffer-dma.c | 45 +++-
 1 file changed, 25 insertions(+), 20 deletions(-)

diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c 
b/drivers/iio/buffer/industrialio-buffer-dma.c
index d348af8b9705..858af7eea53e 100644
--- a/drivers/iio/buffer/industrialio-buffer-dma.c
+++ b/drivers/iio/buffer/industrialio-buffer-dma.c
@@ -356,6 +356,30 @@ int iio_dma_buffer_request_update(struct iio_buffer 
*buffer)
 }
 EXPORT_SYMBOL_GPL(iio_dma_buffer_request_update);
 
+static void iio_dma_buffer_fileio_free(struct iio_dma_buffer_queue *queue)
+{
+   unsigned int i;
+
+   spin_lock_irq(>list_lock);
+   for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) {
+   if (!queue->fileio.blocks[i])
+   continue;
+   queue->fileio.blocks[i]->state = IIO_BLOCK_STATE_DEAD;
+   }
+   INIT_LIST_HEAD(>outgoing);
+   spin_unlock_irq(>list_lock);
+
+   INIT_LIST_HEAD(>incoming);
+
+   for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) {
+   if (!queue->fileio.blocks[i])
+   continue;
+   iio_buffer_block_put(queue->fileio.blocks[i]);
+   queue->fileio.blocks[i] = NULL;
+   }
+   queue->fileio.active_block = NULL;
+}
+
 static void iio_dma_buffer_submit_block(struct iio_dma_buffer_queue *queue,
struct iio_dma_buffer_block *block)
 {
@@ -635,28 +659,9 @@ EXPORT_SYMBOL_GPL(iio_dma_buffer_init);
  */
 void iio_dma_buffer_exit(struct iio_dma_buffer_queue *queue)
 {
-   unsigned int i;
-
mutex_lock(>lock);
 
-   spin_lock_irq(>list_lock);
-   for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) {
-   if (!queue->fileio.blocks[i])
-   continue;
-   queue->fileio.blocks[i]->state = IIO_BLOCK_STATE_DEAD;
-   }
-   INIT_LIST_HEAD(>outgoing);
-   spin_unlock_irq(>list_lock);
-
-   INIT_LIST_HEAD(>incoming);
-
-   for (i = 0; i < ARRAY_SIZE(queue->fileio.blocks); i++) {
-   if (!queue->fileio.blocks[i])
-   continue;
-   iio_buffer_block_put(queue->fileio.blocks[i]);
-   queue->fileio.blocks[i] = NULL;
-   }
-   queue->fileio.active_block = NULL;
+   iio_dma_buffer_fileio_free(queue);
queue->ops = NULL;
 
mutex_unlock(>lock);
-- 
2.17.1



[PATCH v3 2/5] Documentation: iio: add doc for high-speed buffer API

2021-02-15 Thread Alexandru Ardelean
This change takes the comment from the commit that introduces the IIO
high-speed buffer API, and formats it into rst format.

Signed-off-by: Alexandru Ardelean 
---
 Documentation/iio/iio_high_speed_buffers.rst | 100 +++
 Documentation/iio/index.rst  |   2 +
 include/uapi/linux/iio/buffer.h  |   5 +
 3 files changed, 107 insertions(+)
 create mode 100644 Documentation/iio/iio_high_speed_buffers.rst

diff --git a/Documentation/iio/iio_high_speed_buffers.rst 
b/Documentation/iio/iio_high_speed_buffers.rst
new file mode 100644
index ..f326e68efe49
--- /dev/null
+++ b/Documentation/iio/iio_high_speed_buffers.rst
@@ -0,0 +1,100 @@
+===
+Industrial IO High-Speed Buffer API
+===
+
+1. Overview
+===
+
+Industrial IO supports access to buffers via an mmap interface. The
+advantage of the mmap based interface compared to the read() based
+interface is that it avoids an extra copy of the data between kernel and
+userspace. This is particular useful for high-speed devices which produce
+several megabytes or even gigabytes of data per second.
+
+The data for the mmap interface is managed at the granularity of so called
+blocks. A block is a contiguous region of memory (at the moment both
+physically and virtually contiguous). Reducing the granularity from byte
+level to block level is done to reduce the userspace-kernelspace
+synchronization overhead since performing syscalls for each byte at a
+data-rate of a few megabytes is not feasible.
+
+This of course leads to a slightly increased latency. For this reason an
+application can choose the size of the blocks as well as how many blocks it
+allocates. E.g. two blocks would be a traditional double buffering scheme.
+But using a higher number might be necessary to avoid underflow/overflow
+situations in the presence of scheduling latencies.
+
+A block can either be owned by kernel space or userspace. When owned by
+userspace it is safe to access the data in the block and process it. When
+owned by kernel space the block can be in one of 3 states:
+
+* It can be in the incoming queue where all blocks submitted from userspace
+  are placed and are waiting to be processed by the kernel driver.
+* It can be currently being processed by the kernel driver, this means it is
+  actively placing capturing data in it (usually using DMA).
+* Or it can be in the outgoing queue where all blocks that have been
+  processed by the kernel are placed. Userspace can dequeue the blocks as
+  necessary.
+
+2. Interface
+
+
+As part of the interface 5 IOCTLs are used to manage the blocks and exchange
+them between userspace and kernelspace. The IOCTLs can be accessed through
+a open file descriptor to a IIO device.
+
+* **IIO_BUFFER_BLOCK_ALLOC_IOCTL(struct iio_buffer_block_alloc_req *)**:
+Allocates new blocks. Can be called multiple times if necessary. A newly
+allocated block is initially owned by userspace.
+
+* **IIO_BUFFER_BLOCK_FREE_IOCTL(void)**:
+   Frees all previously allocated blocks. If the backing memory of a block is
+   still in use by a kernel driver (i.e. active DMA transfer) it will be
+   freed once the kernel driver has released it.
+
+* **IIO_BUFFER_BLOCK_QUERY_IOCTL(struct iio_buffer_block *)**:
+   Queries information about a block. The id of the block about which
+   information is to be queried needs to be set by userspace.
+
+* **IIO_BUFFER_BLOCK_ENQUEUE_IOCTL(struct iio_buffer_block *)**:
+   Places a block on the incoming queue. This transfers ownership of the
+   block from userspace to kernelspace. Userspace must populate the id field
+   of the block to indicate which block to enqueue.
+
+* **IIO_BUFFER_BLOCK_DEQUEUE_IOCTL(struct iio_buffer_block *)**:
+   Removes the first block from the outgoing queue. This transfers ownership
+   of the block from kernelspace to userspace. Kernelspace will populate all
+   fields of the block. If the queue is empty and the file descriptor is set
+   to blocking the IOCTL will block until a new block is available on the
+   outgoing queue.
+
+3. Usage
+
+
+To access the data stored in a block by userspace the block must be mapped
+to the process's memory. This is done by calling mmap() on the IIO device
+file descriptor. Each block has a unique offset assigned to it which should
+be passed to the mmap interface. E.g.
+
+  mmap(0, block.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+   block.offset);
+
+A typical workflow for the new interface is:
+
+  BLOCK_ALLOC
+
+  foreach block
+ BLOCK_QUERY block
+mmap block.data.offset
+BLOCK_ENQUEUE block
+
+  enable buffer
+
+  while !done
+   BLOCK_DEQUEUE block
+   process data
+   BLOCK_ENQUEUE block
+
+  disable buffer
+
+  BLOCK_FREE
diff --git a/Documentation/iio/index.rst b/Documentation/iio/index.rst
index 58b7a4ebac51..aaba78770b47 100644
--- a/Documentation/iio/index.rst
+++ b

[PATCH v3 1/5] iio: core: Add mmap interface infrastructure

2021-02-15 Thread Alexandru Ardelean
From: Lars-Peter Clausen 

Add the necessary infrastructure to the IIO core to support an mmap based
interface to access the capture data.

The advantage of the mmap based interface compared to the read() based
interface is that it avoids an extra copy of the data between kernel and
userspace. This is particular useful for high-speed devices which produce
several megabytes or even gigabytes of data per second.

The data for the mmap interface is managed at the granularity of so called
blocks. A block is a contiguous region of memory (at the moment both
physically and virtually contiguous). Reducing the granularity from byte
level to block level is done to reduce the userspace-kernelspace
synchronization overhead since performing syscalls for each byte at a
data-rate of a few megabytes is not feasible.

This of course leads to a slightly increased latency. For this reason an
application can choose the size of the blocks as well as how many blocks it
allocates. E.g. two blocks would be a traditional double buffering scheme.
But using a higher number might be necessary to avoid underflow/overflow
situations in the presence of scheduling latencies.

A block can either be owned by kernel space or userspace. When owned by
userspace it save to access the data in the block and process it. When
owned by kernel space the block can be in one of 3 states.

It can be in the incoming queue where all blocks submitted from userspace
are placed and are waiting to be processed by the kernel driver.

It can be currently being processed by the kernel driver, this means it is
actively placing capturing data in it (usually using DMA).

Or it can be in the outgoing queue where all blocks that have been
processed by the kernel are placed. Userspace can dequeue the blocks as
necessary.

As part of the interface 5 new IOCTLs to manage the blocks and exchange
them between userspace and kernelspace. The IOCTLs can be accessed through
a open file descriptor to a IIO device.

IIO_BUFFER_BLOCK_ALLOC_IOCTL(struct iio_buffer_block_alloc_req *):
 Allocates new blocks. Can be called multiple times if necessary. A newly
 allocated block is initially owned by userspace.

IIO_BUFFER_BLOCK_FREE_IOCTL(void):
 Frees all previously allocated blocks. If the backing memory of a block is
 still in use by a kernel driver (i.e. active DMA transfer) it will be
 freed once the kernel driver has released it.

IIO_BUFFER_BLOCK_QUERY_IOCTL(struct iio_buffer_block *):
 Queries information about a block. The id of the block about which
 information is to be queried needs to be set by userspace.

IIO_BUFFER_BLOCK_ENQUEUE_IOCTL(struct iio_buffer_block *):
 Places a block on the incoming queue. This transfers ownership of the
 block from userspace to kernelspace. Userspace must populate the id field
 of the block to indicate which block to enqueue.

IIO_BUFFER_BLOCK_DEQUEUE_IOCTL(struct iio_buffer_block *):
 Removes the first block from the outgoing queue. This transfers ownership
 of the block from kernelspace to userspace. Kernelspace will populate all
 fields of the block. If the queue is empty and the file descriptor is set
 to blocking the IOCTL will block until a new block is available on the
 outgoing queue.

To access the data stored in a block by userspace the block must be mapped
to the process's memory. This is done by calling mmap() on the IIO device
file descriptor. Each block has a unique offset assigned to it which should
be passed to the mmap interface. E.g.

  mmap(0, block.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
   block.offset);

A typical workflow for the new interface is:

  BLOCK_ALLOC

  foreach block
 BLOCK_QUERY block
 mmap block.data.offset
 BLOCK_ENQUEUE block

  enable buffer

  while !done
BLOCK_DEQUEUE block
process data
BLOCK_ENQUEUE block

  disable buffer

  BLOCK_FREE

Signed-off-by: Lars-Peter Clausen 
Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/industrialio-buffer.c | 158 ++
 include/linux/iio/buffer-dma.h|   5 -
 include/linux/iio/buffer_impl.h   |  23 +
 include/uapi/linux/iio/buffer.h   |  44 +
 4 files changed, 225 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/industrialio-buffer.c 
b/drivers/iio/industrialio-buffer.c
index 4848932d4394..5d641f8adfbd 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -1371,6 +1372,12 @@ static void 
iio_buffer_unregister_legacy_sysfs_groups(struct iio_dev *indio_dev)
kfree(iio_dev_opaque->legacy_scan_el_group.attrs);
 }
 
+static void iio_buffer_free_blocks(struct iio_buffer *buffer)
+{
+   if (buffer->access->free_blocks)
+   buffer->access->free_blocks(buffer);
+}
+
 static int iio_buffer_chrdev_release(struct inode *inode, struct file *filep)
 {
struct iio_dev_buffer_pair *ib = filep->private

[PATCH v3 0/5] iio: core: Add mmap interface infrastructure

2021-02-15 Thread Alexandru Ardelean
Changelog v2 -> v3:
* 
https://lore.kernel.org/linux-iio/20210212101143.18993-1-alexandru.ardel...@analog.com/T/#u
* added 'Documentation: iio: add doc for high-speed buffer API'
* add 'iio: buffer-dma: split iio_dma_buffer_fileio_free() function'
* patch 'iio: buffer-dma: Add mmap support'
   - unwind free on error path in iio_dma_buffer_alloc_blocks()
   - removed double mm.h include
* patch 'tools: iio: add example for high-speed buffer support'
   - call IIO_BUFFER_BLOCK_FREE_IOCTL on the error path of the
 enable_high_speed() function

Changelog v1 -> v2:
* 
https://lore.kernel.org/linux-iio/20210211123353.78963-1-alexandru.ardel...@analog.com/T/#t
* removed IIO_BUFFER_BLOCK_FLAG_CYCLIC flag; will be added in a later
  patch
* removed extra line in tools/iio/iio_generic_buffer.c
* patch 'iio: core: Add mmap interface infrastructure'
  added docstrings for new hooks (alloc_blocks, mmap, etc)

This is basically Lars' work adapted from branch:
  https://github.com/larsclausen/linux/commits/iio-high-speed-5.10
[hopefully i got the stuff correctly from that branch]

What is different, is that this one is adapted on top of the multibuffer
support (currently at v5) discussed here:
  
https://lore.kernel.org/linux-iio/20210211122452.78106-1-alexandru.ardel...@analog.com/T/#t

Also, adapted an example for high-speed/mmap support in
'tools/iio/iio_generic_buffer.c'

The example is adapted from libiio:
  https://github.com/analogdevicesinc/libiio/blob/master/local.c#L51
but will all the ioctl()s organized after the one that are reserved
(hopefully) for IIO

Tested that mmap() works.
Moved (artifically) valid buffer0 as buffer2 and the operation still
works.

Alexandru Ardelean (3):
  Documentation: iio: add doc for high-speed buffer API
  iio: buffer-dma: split iio_dma_buffer_fileio_free() function
  tools: iio: add example for high-speed buffer support

Lars-Peter Clausen (2):
  iio: core: Add mmap interface infrastructure
  iio: buffer-dma: Add mmap support

 Documentation/iio/iio_high_speed_buffers.rst  | 100 ++
 Documentation/iio/index.rst   |   2 +
 drivers/iio/buffer/industrialio-buffer-dma.c  | 324 --
 .../buffer/industrialio-buffer-dmaengine.c|  22 +-
 drivers/iio/industrialio-buffer.c | 158 +
 include/linux/iio/buffer-dma.h|  27 +-
 include/linux/iio/buffer_impl.h   |  23 ++
 include/uapi/linux/iio/buffer.h   |  49 +++
 tools/iio/iio_generic_buffer.c| 184 +-
 9 files changed, 841 insertions(+), 48 deletions(-)
 create mode 100644 Documentation/iio/iio_high_speed_buffers.rst

-- 
2.17.1



Re: [PATCH v6 00/24] iio: core,buffer: add support for multiple IIO buffers per IIO device

2021-02-15 Thread Alexandru Ardelean
On Mon, Feb 15, 2021 at 3:59 PM Jonathan Cameron  wrote:
>
> On Mon, 15 Feb 2021 12:40:19 +0200
> Alexandru Ardelean  wrote:
>
> Hi Alex,
>
> One thought on this that came up whilst reading through it again.
> There are several uses for multiple buffers.
> 1) input vs output buffers
> 2) A device with separately clocked sampling of different channels.

So, ADI typically has use-cases for 1).
Mostly RF transceivers.
Traditionally, these were written (inside the ADI tree) as 2-3 IIO
devices (1 IIO device for each path,1 for TX and 1-2 for RX).
With multi-buffer, they can be a single IIO device with 2-3 IIO buffers.

There are some ADI devices that have channels that can run at different speeds.
But this hasn't been an important use-cases to deal with.
Typically, a common-rate would be picked [for all channels] and that's that.
I think some people find this per-channel rates interesting; but let's see.

>
> For case 2, there is at least sometimes a trigger involved
> (often data ready) so we probably also need to think long term about how
> to support multiple current_triggers in one driver.
>
> I guess that's something for us to figure out when we need it however.
>
> Thanks for you hard work on finally getting this upstream.
> + Lars (and maybe others) for earlier work on this.

Thank you as well.

>
> Whilst I've applied all these, they are only exposed in the testing branch
> of iio.git on kernel.org so far and as such any additional review anyone
> else wants to give would be welcome!

I feel there may be other users stumbling over this multibuffer
support, and try it out.
Often people don't seem to care about multibuffer, until they really need it.
A bit of chicken-n-egg problem.
But after being added, people may see it and start to use it.

>
> Jonathan
>
> > Changelog v5 -> v6:
> > * 
> > https://lore.kernel.org/linux-iio/20210211122452.78106-1-alexandru.ardel...@analog.com/T/#t
> > * merged series 'iio: kfifo: define a devm_iio_kfifo_buffer_setup helper' 
> > into this
> >
> > https://lore.kernel.org/linux-iio/20210214143313.67202-4-alexandru.ardel...@analog.com/T/#u
> > * merged patch 'iio: buffer-dma,adi-axi-adc: introduce 
> > devm_iio_dmaengine_buffer_setup()' into this
> >
> > https://lore.kernel.org/linux-iio/20210214155817.68678-1-alexandru.ardel...@analog.com/T/#u
> > * patch 'iio: core: wrap iio device & buffer into struct for character 
> > devices'
> >- moved kfree(ib) to be first in iio_chrdev_release() to make the cleanup
> >  order be reversed as the open() order
> > * patch 'iio: buffer: group attr count and attr alloc'
> >- sizeof(struct attribute *)  ->   sizeof(*attr)  in kcalloc()
> > * patch 'iio: core: merge buffer/ & scan_elements/ attributes'
> >- minor rework in iio_buffer_register_legacy_sysfs_groups() to
> >  use more 'sizeof(*attrs)' in allocations
> >- fixed typo 'legacy_buffer_el_group' -> 'legacy_buffer_group'
> >- updated comment about
> >  '/* we only need to link the legacy buffer groups for the first buffer 
> > */'
> >  to
> >  '/* we only need to register the legacy groups for the first buffer */'
> > * patch 'iio: buffer: add ioctl() to support opening extra buffers for IIO 
> > device'
> >- removed 'buf_name' from iio_device_buffer_getfd();
> >   passing "iio:buffer" name; since it should be a class-name
> >- removed extra-line in drivers/iio/industrial-core.c
> >-  changed init order in iio_device_buffer_getfd() and matched it with 
> > reverse in
> >   iio_buffer_chrdev_release()
> >- calling put_unused_fd() in iio_device_buffer_getfd() if copy_to_user() 
> > fails
> > * added 'iio: dummy: iio_simple_dummy_buffer: use triggered buffer core 
> > calls'
> > * patch ' iio: buffer: introduce support for attaching more IIO buffers'
> >- now handling iio_device_attach_buffer() error returns
> >- rename iio_buffer_free_sysfs_and_mask() -> 
> > iio_buffers_free_sysfs_and_mask()
> >- rename iio_buffer_alloc_sysfs_and_mask() -> 
> > iio_buffer_alloc_sysfs_and_mask()
> > * patch 'tools: iio: convert iio_generic_buffer to use new IIO buffer API'
> >   - removed extra close() if getfd() ioctl() errors out
> >   - added comment that the sanity check for buffer0 should not be done
> > under normal operation
> >   - update message from
> >"This device does not support buffers"
> >to
> >"Device does not have this many buffers"
> >
> > Changelog v4 -> v5:
> > * 
> > https://lore.kernel.org/linux-iio/20210210100823.4678

Re: [PATCH v2 3/3] tools: iio: add example for high-speed buffer support

2021-02-15 Thread Alexandru Ardelean
On Sun, Feb 14, 2021 at 5:58 PM Jonathan Cameron  wrote:
>
> On Fri, 12 Feb 2021 12:11:43 +0200
> Alexandru Ardelean  wrote:
>
> > Following a recent update to the IIO buffer infrastructure, this change
> > adds a basic example on how to access an IIO buffer via the new mmap()
> > interface.
> >
> > The ioctl() for the high-speed mode needs to be enabled right from the
> > start, before setting any parameters via sysfs (length, enable, etc), to
> > make sure that the mmap mode is used and not the fileio mode.
> >
> > Signed-off-by: Alexandru Ardelean 
>
> Just one small question on error handling. Otherwise this looks fine to me.
>
> thanks,
>
> Jonathan
>
> > ---
> >  tools/iio/iio_generic_buffer.c | 183 +++--
> >  1 file changed, 177 insertions(+), 6 deletions(-)
> >
> > diff --git a/tools/iio/iio_generic_buffer.c b/tools/iio/iio_generic_buffer.c
> > index fdd08514d556..675a7e6047e0 100644
> > --- a/tools/iio/iio_generic_buffer.c
> > +++ b/tools/iio/iio_generic_buffer.c
> > @@ -31,6 +31,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include "iio_utils.h"
> >
> > @@ -239,6 +240,132 @@ static int enable_disable_all_channels(char 
> > *dev_dir_name, int buffer_idx, int e
> >   return 0;
> >  }
> >
> > +struct mmap_block {
> > + struct iio_buffer_block block;
> > + void *addr;
> > +};
> > +
> > +static struct mmap_block *enable_high_speed(int buf_fd, unsigned int 
> > block_size,
> > + int nblocks)
> > +{
> > + struct iio_buffer_block_alloc_req req = { 0 };
> > + struct mmap_block *mmaps = NULL;
> > + int mmaps_cnt = 0;
> > + int i, ret;
> > +
> > + /**
> > +  * Validate we can do high-speed by issuing BLOCK_FREE ioctl.
> > +  * If using just BLOCK_ALLOC it's distinguish between ENOSYS
> > +  * and other error types.
> > +  */
> > + ret = ioctl(buf_fd, IIO_BUFFER_BLOCK_FREE_IOCTL, 0);
> > + if (ret < 0) {
> > + errno = ENOSYS;
> > + return NULL;
> > + }
> > +
> > + /* for now, this */
> > + req.id = 0;
> > + req.type = 0;
> > + req.size = block_size;
> > + req.count = nblocks;
> > +
> > + ret = ioctl(buf_fd, IIO_BUFFER_BLOCK_ALLOC_IOCTL, );
> > + if (ret < 0)
> > + return NULL;
> > +
> > + if (req.count == 0) {
> > + errno = ENOMEM;
> > + return NULL;
> > + }
> > +
> > + if (req.count < nblocks) {
> > + fprintf(stderr, "Requested %d blocks, got %d\n",
> > + nblocks, req.count);
> > + errno = ENOMEM;
> > + return NULL;
> > + }
> > +
> > + mmaps = calloc(req.count, sizeof(*mmaps));
> > + if (!mmaps) {
> > + errno = ENOMEM;
> > + return NULL;
> > + }
> > +
> > + for (i = 0; i < req.count; i++) {
> > + mmaps[i].block.id = i;
> > + ret = ioctl(buf_fd, IIO_BUFFER_BLOCK_QUERY_IOCTL, 
> > [i].block);
> > + if (ret < 0)
> > + goto error;
> > +
> > + ret = ioctl(buf_fd, IIO_BUFFER_BLOCK_ENQUEUE_IOCTL, 
> > [i].block);
> > + if (ret < 0)
> > + goto error;
>
> > +
> > + mmaps[i].addr = mmap(0, mmaps[i].block.size,
> > +   PROT_READ | PROT_WRITE, MAP_SHARED,
> > +   buf_fd, mmaps[i].block.data.offset);
> > +
> > + if (mmaps[i].addr == MAP_FAILED)
> > + goto error;
> > +
> > + mmaps_cnt++;
> > + }
> > +
> > + return mmaps;
> > +
> > +error:
> > + for (i = 0; i < mmaps_cnt; i++)
> > + munmap(mmaps[i].addr, mmaps[i].block.size);
> > + free(mmaps);
>
> No free of the blocks?  We have unmapped them but I'd imagine we'd also
> need to free them from the driver side.

Good catch.

>
> > + return NULL;
> > +}
> > +
> > +static int read_high_speed(int buf_fd, char *data, unsigned int block_size,
> > +struct mmap_block *mmaps, unsigned int mmaps_cnt)
> > +{
> > + struct iio_buffer_block block;
> > +   

[PATCH v6 24/24] tools: iio: convert iio_generic_buffer to use new IIO buffer API

2021-02-15 Thread Alexandru Ardelean
This change makes use of the new IIO buffer API to read data from an IIO
buffer.
It doesn't read the /sys/bus/iio/devices/iio:deviceX/scan_elements dir
anymore, it reads /sys/bus/iio/devices/iio:deviceX/bufferY, where all the
scan_elements have been merged together with the old/classical buffer
attributes.

And it makes use of the new IIO_BUFFER_GET_FD_IOCTL ioctl to get an FD for
the IIO buffer for which to read data from.
It also does a quick sanity check to see that -EBUSY is returned if reading
the chardev after the ioctl() has succeeded.

This was tested with the following cases:
 1. Tested buffer0 works with ioctl()
 2. Tested that buffer0 can't be opened via /dev/iio:deviceX after ioctl()
This check should be omitted under normal operation; it's being done
here to check that the driver change is sane
 3. Moved valid buffer0 to be buffer1, and tested that data comes from it

Signed-off-by: Alexandru Ardelean 
---
 tools/iio/Makefile |   1 +
 tools/iio/iio_generic_buffer.c | 122 ++---
 tools/iio/iio_utils.c  |  13 ++--
 tools/iio/iio_utils.h  |   4 +-
 4 files changed, 107 insertions(+), 33 deletions(-)

diff --git a/tools/iio/Makefile b/tools/iio/Makefile
index 3de763d9ab70..5d12ac4e7f8f 100644
--- a/tools/iio/Makefile
+++ b/tools/iio/Makefile
@@ -27,6 +27,7 @@ include $(srctree)/tools/build/Makefile.include
 #
 $(OUTPUT)include/linux/iio: ../../include/uapi/linux/iio
mkdir -p $(OUTPUT)include/linux/iio 2>&1 || true
+   ln -sf $(CURDIR)/../../include/uapi/linux/iio/buffer.h $@
ln -sf $(CURDIR)/../../include/uapi/linux/iio/events.h $@
ln -sf $(CURDIR)/../../include/uapi/linux/iio/types.h $@
 
diff --git a/tools/iio/iio_generic_buffer.c b/tools/iio/iio_generic_buffer.c
index 7c7240553777..2491c54a5e4f 100644
--- a/tools/iio/iio_generic_buffer.c
+++ b/tools/iio/iio_generic_buffer.c
@@ -30,6 +30,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include "iio_utils.h"
 
 /**
@@ -197,7 +199,7 @@ static void process_scan(char *data, struct 
iio_channel_info *channels,
printf("\n");
 }
 
-static int enable_disable_all_channels(char *dev_dir_name, int enable)
+static int enable_disable_all_channels(char *dev_dir_name, int buffer_idx, int 
enable)
 {
const struct dirent *ent;
char scanelemdir[256];
@@ -205,7 +207,7 @@ static int enable_disable_all_channels(char *dev_dir_name, 
int enable)
int ret;
 
snprintf(scanelemdir, sizeof(scanelemdir),
-FORMAT_SCAN_ELEMENTS_DIR, dev_dir_name);
+FORMAT_SCAN_ELEMENTS_DIR, dev_dir_name, buffer_idx);
scanelemdir[sizeof(scanelemdir)-1] = '\0';
 
dp = opendir(scanelemdir);
@@ -243,6 +245,7 @@ static void print_usage(void)
"Capture, convert and output data from IIO device buffer\n"
"  -a Auto-activate all available channels\n"
"  -A Force-activate ALL channels\n"
+   "  -b  The buffer which to open (by index), default 0\n"
"  -c  Do n conversions, or loop forever if n < 0\n"
"  -e Disable wait for event (new data)\n"
"  -g Use trigger-less mode\n"
@@ -259,6 +262,7 @@ static void print_usage(void)
 static enum autochan autochannels = AUTOCHANNELS_DISABLED;
 static char *dev_dir_name = NULL;
 static char *buf_dir_name = NULL;
+static int buffer_idx = 0;
 static bool current_trigger_set = false;
 
 static void cleanup(void)
@@ -286,7 +290,7 @@ static void cleanup(void)
 
/* Disable channels if auto-enabled */
if (dev_dir_name && autochannels == AUTOCHANNELS_ACTIVE) {
-   ret = enable_disable_all_channels(dev_dir_name, 0);
+   ret = enable_disable_all_channels(dev_dir_name, buffer_idx, 0);
if (ret)
fprintf(stderr, "Failed to disable all channels\n");
autochannels = AUTOCHANNELS_DISABLED;
@@ -333,7 +337,9 @@ int main(int argc, char **argv)
unsigned long long j;
unsigned long toread;
int ret, c;
-   int fp = -1;
+   struct stat st;
+   int fd = -1;
+   int buf_fd = -1;
 
int num_channels = 0;
char *trigger_name = NULL, *device_name = NULL;
@@ -352,7 +358,7 @@ int main(int argc, char **argv)
 
register_cleanup();
 
-   while ((c = getopt_long(argc, argv, "aAc:egl:n:N:t:T:w:?", longopts,
+   while ((c = getopt_long(argc, argv, "aAb:c:egl:n:N:t:T:w:?", longopts,
NULL)) != -1) {
switch (c) {
case 'a':
@@ -361,7 +367,20 @@ int main(int argc, char **argv)
case 'A':
autochannels = AUTOCHANNELS_ENABLED;
force_autoch

[PATCH v6 23/24] tools: iio: privatize globals and functions in iio_generic_buffer.c file

2021-02-15 Thread Alexandru Ardelean
Mostly a tidy-up.
But also helps to understand the limits of scope of these functions and
globals.

Signed-off-by: Alexandru Ardelean 
---
 tools/iio/iio_generic_buffer.c | 31 +++
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/tools/iio/iio_generic_buffer.c b/tools/iio/iio_generic_buffer.c
index 34d63bcebcd2..7c7240553777 100644
--- a/tools/iio/iio_generic_buffer.c
+++ b/tools/iio/iio_generic_buffer.c
@@ -49,7 +49,7 @@ enum autochan {
  * Has the side effect of filling the channels[i].location values used
  * in processing the buffer output.
  **/
-int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
+static int size_from_channelarray(struct iio_channel_info *channels, int 
num_channels)
 {
int bytes = 0;
int i = 0;
@@ -68,7 +68,7 @@ int size_from_channelarray(struct iio_channel_info *channels, 
int num_channels)
return bytes;
 }
 
-void print1byte(uint8_t input, struct iio_channel_info *info)
+static void print1byte(uint8_t input, struct iio_channel_info *info)
 {
/*
 * Shift before conversion to avoid sign extension
@@ -85,7 +85,7 @@ void print1byte(uint8_t input, struct iio_channel_info *info)
}
 }
 
-void print2byte(uint16_t input, struct iio_channel_info *info)
+static void print2byte(uint16_t input, struct iio_channel_info *info)
 {
/* First swap if incorrect endian */
if (info->be)
@@ -108,7 +108,7 @@ void print2byte(uint16_t input, struct iio_channel_info 
*info)
}
 }
 
-void print4byte(uint32_t input, struct iio_channel_info *info)
+static void print4byte(uint32_t input, struct iio_channel_info *info)
 {
/* First swap if incorrect endian */
if (info->be)
@@ -131,7 +131,7 @@ void print4byte(uint32_t input, struct iio_channel_info 
*info)
}
 }
 
-void print8byte(uint64_t input, struct iio_channel_info *info)
+static void print8byte(uint64_t input, struct iio_channel_info *info)
 {
/* First swap if incorrect endian */
if (info->be)
@@ -167,9 +167,8 @@ void print8byte(uint64_t input, struct iio_channel_info 
*info)
  *   to fill the location offsets.
  * @num_channels:  number of channels
  **/
-void process_scan(char *data,
- struct iio_channel_info *channels,
- int num_channels)
+static void process_scan(char *data, struct iio_channel_info *channels,
+int num_channels)
 {
int k;
 
@@ -238,7 +237,7 @@ static int enable_disable_all_channels(char *dev_dir_name, 
int enable)
return 0;
 }
 
-void print_usage(void)
+static void print_usage(void)
 {
fprintf(stderr, "Usage: generic_buffer [options]...\n"
"Capture, convert and output data from IIO device buffer\n"
@@ -257,12 +256,12 @@ void print_usage(void)
"  -w  Set delay between reads in us (event-less 
mode)\n");
 }
 
-enum autochan autochannels = AUTOCHANNELS_DISABLED;
-char *dev_dir_name = NULL;
-char *buf_dir_name = NULL;
-bool current_trigger_set = false;
+static enum autochan autochannels = AUTOCHANNELS_DISABLED;
+static char *dev_dir_name = NULL;
+static char *buf_dir_name = NULL;
+static bool current_trigger_set = false;
 
-void cleanup(void)
+static void cleanup(void)
 {
int ret;
 
@@ -294,14 +293,14 @@ void cleanup(void)
}
 }
 
-void sig_handler(int signum)
+static void sig_handler(int signum)
 {
fprintf(stderr, "Caught signal %d\n", signum);
cleanup();
exit(-signum);
 }
 
-void register_cleanup(void)
+static void register_cleanup(void)
 {
struct sigaction sa = { .sa_handler = sig_handler };
const int signums[] = { SIGINT, SIGTERM, SIGABRT };
-- 
2.17.1



[PATCH v6 21/24] iio: core: rename 'dev' -> 'indio_dev' in iio_device_alloc()

2021-02-15 Thread Alexandru Ardelean
The 'dev' variable name usually refers to 'struct device' types. However in
iio_device_alloc() this was used for the 'struct iio_dev' type, which was
sometimes causing minor confusions.

This change renames the variable to 'indio_dev', which is the usual name
used around IIO for 'struct iio_dev' type objects.
It makes grepping a bit easier as well.

Signed-off-by: Alexandru Ardelean 
---
 drivers/iio/industrialio-core.c | 28 ++--
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index f7f785431106..bdb55901e97c 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -1602,7 +1602,7 @@ struct device_type iio_device_type = {
 struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv)
 {
struct iio_dev_opaque *iio_dev_opaque;
-   struct iio_dev *dev;
+   struct iio_dev *indio_dev;
size_t alloc_size;
 
alloc_size = sizeof(struct iio_dev_opaque);
@@ -1615,31 +1615,31 @@ struct iio_dev *iio_device_alloc(struct device *parent, 
int sizeof_priv)
if (!iio_dev_opaque)
return NULL;
 
-   dev = _dev_opaque->indio_dev;
-   dev->priv = (char *)iio_dev_opaque +
+   indio_dev = _dev_opaque->indio_dev;
+   indio_dev->priv = (char *)iio_dev_opaque +
ALIGN(sizeof(struct iio_dev_opaque), IIO_ALIGN);
 
-   dev->dev.parent = parent;
-   dev->dev.type = _device_type;
-   dev->dev.bus = _bus_type;
-   device_initialize(>dev);
-   dev_set_drvdata(>dev, (void *)dev);
-   mutex_init(>mlock);
-   mutex_init(>info_exist_lock);
+   indio_dev->dev.parent = parent;
+   indio_dev->dev.type = _device_type;
+   indio_dev->dev.bus = _bus_type;
+   device_initialize(_dev->dev);
+   dev_set_drvdata(_dev->dev, (void *)indio_dev);
+   mutex_init(_dev->mlock);
+   mutex_init(_dev->info_exist_lock);
INIT_LIST_HEAD(_dev_opaque->channel_attr_list);
 
-   dev->id = ida_simple_get(_ida, 0, 0, GFP_KERNEL);
-   if (dev->id < 0) {
+   indio_dev->id = ida_simple_get(_ida, 0, 0, GFP_KERNEL);
+   if (indio_dev->id < 0) {
/* cannot use a dev_err as the name isn't available */
pr_err("failed to get device id\n");
kfree(iio_dev_opaque);
return NULL;
}
-   dev_set_name(>dev, "iio:device%d", dev->id);
+   dev_set_name(_dev->dev, "iio:device%d", indio_dev->id);
INIT_LIST_HEAD(_dev_opaque->buffer_list);
INIT_LIST_HEAD(_dev_opaque->ioctl_handlers);
 
-   return dev;
+   return indio_dev;
 }
 EXPORT_SYMBOL(iio_device_alloc);
 
-- 
2.17.1



  1   2   3   4   5   6   7   8   9   10   >