lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20240428182152.7349129c@jic23-huawei>
Date: Sun, 28 Apr 2024 18:21:52 +0100
From: Jonathan Cameron <jic23@...nel.org>
To: Paul Geurts <paul_geurts@...e.nl>
Cc: "lars@...afoo.de" <lars@...afoo.de>, "Michael.Hennerich@...log.com"
 <Michael.Hennerich@...log.com>, "linux-iio@...r.kernel.org"
 <linux-iio@...r.kernel.org>, "linux-kernel@...r.kernel.org"
 <linux-kernel@...r.kernel.org>
Subject: Re: [PATCH] iio: accel: adxl345: Added buffered read support

On Mon, 22 Apr 2024 15:17:47 +0000
Paul Geurts <paul_geurts@...e.nl> wrote:

> On 20-04-2024 14:54, Jonathan Cameron wrote:
> > On Wed, 17 Apr 2024 10:28:34 +0200
> > Paul Geurts <paul_geurts@...e.nl> wrote:
> >
> > Hi Paul, various comments inline.
> >
> >  
> >> This implements buffered reads for the accelerometer data. A buffered
> >> IIO device is created containing 3 channels. The device FIFO is used for
> >> sample buffering to reduce the IRQ load on the host system.
> >>
> >> Reading of the device is triggered by a FIFO waterlevel interrupt. The
> >> waterlevel settings are dependent on the sampling frequency to leverage
> >> IRQ load against responsiveness.  
> > I'm unconvinced that trade off belongs in the driver. Until now we
> > have exposed all the relevant controls to userspace via bufferX/watermark.
> > Set that to 0 or 1 if you don't want a fifo and appropriate level for whatever
> > responsiveness is needed for a particular application.
> >
> > The need to manually disable / enable interrupts is also normally something
> > that needs a close look. Very very occasionally this is necessary but for most
> > devices IRQF_ONESHOT should provide suitable masking.
> >
> > It's also not clear that a trigger is appropriate here. For FIFO equipped devices
> > like this, the trigger abstraction often doesn't work as we don't have one interrupt
> > per 'scan' of data.  In these cases it is not necessary to use a trigger at all
> > and that can simplify things considerably.
> >
> > Jonathan  
> 
> This was my first interaction with the IIO subsystem, So these changes were somewhat of a
> learning experience. Your review comments indicate major refactoring of my patch is in
> order. I will see when I have time to get to it and resend it at some point.

Great that I didn't put you off too much and I should have said welcome!
As someone who has a v9 patch set to send out tomorrow (for another area of the kernel),
I'm well aware there can be quite a learning curve.


A few follow up comments below, but mostly guessing what might have made
things trickier rather than anything useful.

Jonathan


> >  
> >> +	if (ret < 0)
> >> +		goto out;  
> > return ret;  
> >> +	while (regval & ADXL345_INT_DATA_READY) {
> >> +		ret = regmap_bulk_read(map, ADXL345_REG_DATA_AXIS(0), &axis_data,
> >> +				       sizeof(axis_data));
> >> +		if (ret < 0)
> >> +			goto out;  
> > The datasheet puts a timing requirement on repeat reads that you need to enforce..
> > 5 usec.
> >
> > return ret;  
> 
> I didn't find this requirement in the datasheet. I did however write this for ADXL343, which seems
> to be compatible with ADXL345. But maybe I missed something here?

It's a slow bus, maybe the delay is above that anyway.

> 
> >> +		ret = regmap_read(map, ADXL345_REG_INT_SOURCE, &regval);
> >> +		if (ret < 0)
> >> +			goto out;  
> > return directly - going to a label that does nothing makes a reviewer
> > following code paths have to go see that nothing happens.
> >
> > 			return ret;
> >  
> >> +	}
> >> +
> >> +out:
> >> +	return ret;
> >> +}
> >> +
> >> +static int adxl345_buffer_preenable(struct iio_dev *indio_dev)
> >> +{
> >> +	struct adxl345_data *data = iio_priv(indio_dev);
> >> +	int ret;
> >> +
> >> +	mutex_lock(&data->lock);
> >> +	/* Disable measurement mode to setup everything */
> >> +	ret = regmap_clear_bits(data->regmap, ADXL345_REG_POWER_CTL, ADXL345_POWER_CTL_MEASURE);
> >> +	if (ret < 0)
> >> +		goto out;
> >> +
> >> +	ret = adxl345_flush_fifo(data->regmap);
> >> +	if (ret < 0)
> >> +		goto out_enable;
> >> +
> >> +	/*
> >> +	 * Set the FIFO up in streaming mode so the chip keeps sampling.
> >> +	 * Waterlevel is set by the sample frequency functions as it is dynamic  
> > This I don't follow.  Why is it dynamic?  It's fixed for a given run at a given
> > frequency. I can sort of see a true dynamic adjustment might make sense, but that
> > would be complex and isn't obviously a problem for the kernel.
> >
> > I'd prefer to see this done like the majority of other fifo handling drivers:
> > Make setting the watermark vs frequency a userspace problem.  
> 
> So having an interrupt coming in for every sample on 3200Hz sampling rate completely overloaded my
> i.MX8M Mini CPU (1600MHz) I was testing this on. This was the main reason to be using the internal
> FIFO in the accelerometer. But when doing that, the device becomes somewhat unresponsive on the
> lower frequencies, as it first needs to fill the FIFO before actually firing an interrupt towards
> the CPU. Therefore I created this, which only uses the water level interrupt on highter frequencies
> to try to have best of both worlds. But I agree that this should be a userspace choice.

It's a neat bit of code and maybe one day worth considering if we should try to auto
tune, but definitely not something to do in a driver alongside the initial
enablement.

> 
> >  
> >> +	 */
> >> +	ret = regmap_update_bits(data->regmap, ADXL345_REG_FIFO_CTL,
> >> +				 (int)~(ADXL345_FIFO_CTL_SAMPLES_MASK),
> >> +				 ADXL345_FIFO_CTL_MODE_STREAM);
> >> +	if (ret < 0)
> >> +		goto out_enable;
> >> +
> >> +	/* Enable the Watermark and Overrun interrupt */
> >> +	ret = regmap_write(data->regmap, ADXL345_REG_INT_ENABLE, (ADXL345_INT_WATERMARK |
> >> +			   ADXL345_INT_OVERRUN));
> >> +	if (ret < 0)
> >> +		goto out_enable;
> >> +
> >> +	/* Re-enable measurement mode */
> >> +	ret = regmap_set_bits(data->regmap, ADXL345_REG_POWER_CTL, ADXL345_POWER_CTL_MEASURE);
> >> +	goto out;  
> > Don't do this as it makes for messy control flow to review
> >
> > 	if (ret)
> > 		goto out_enabled;
> >
> > 	mutex_unlock(&data->lock)
> > 	return 0;
> >
> > out_enable:
> > ...
> > Can use guard(mutex)(&data->lock) to avoid need to unlock manually and allow at least
> > some paths to return directly.  
> 
> I am very pleased to find out scoped locking is finally possible in the Linux kernel :-). I didn't know this.
> 

Pretty new + the more complex corners of what can be done are still
controversial.  Thankfully mutexes are a simple case.

> >> +	int ret, data_available;
> >> +
> >> +	mutex_lock(&data->lock);
> >> +
> >> +	/* Disable the IRQ before reading the FIFO */  
> > This needs a lot more explanation.  Disabling interrupts like
> > this can be very expensive and can be hard to reason about
> > + it's not necessary most of the time because of IRQF_ONESHOT.  
> 
> I did experience some issues with the interrupts, hence the disabling. But I might have just
> implemented it badly. I will take a look into why things go bad and try to make it so that
> disabling IRQs is not needed anymore.
> 

Often it's a type issue for interrupts - particularly level vs edge.
Thankfully it's fairly rare to get interrupt controllers that only
do one or the other these days - that used to be really painful to
try and handle in a driver.

> >> +
> >> +	mutex_init(&data->lock);
> >> +
> >>  	indio_dev->name = data->info->name;
> >>  	indio_dev->info = &adxl345_info;
> >> -	indio_dev->modes = INDIO_DIRECT_MODE;
> >> +	indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_TRIGGERED;  
> > No need as INDIO_BUFFER_TRIGGERED is set when you register the buffer.  
> 
> Didn't know that!
> 

It's relatively recent (few years ago) so if you are on an older tree
it might not have been true.

Jonathan


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ