[PATCH v5] iio: chemical: scd30: Replace manual locking with RAII locking

Maxwell Doose posted 1 patch 1 week, 3 days ago
There is a newer version of this series
drivers/iio/chemical/scd30_core.c | 66 ++++++++++++++++++++-----------
1 file changed, 42 insertions(+), 24 deletions(-)
[PATCH v5] iio: chemical: scd30: Replace manual locking with RAII locking
Posted by Maxwell Doose 1 week, 3 days ago
scd30_core.c currently uses manual mutex_lock() and mutex_unlock()
calls. Replace them with the newer guard(mutex)() for cleaner RAII
patterns and to improve maintainability.

Add new helper function scd30_trigger_handler_helper() containing
the critical section for scd30_trigger_handler().

In addition, small refactor to replace "?:" operator with regular
if/else returns.

Signed-off-by: Maxwell Doose <m32285159@gmail.com>
---
 v2:
  - Fix callback issue as noted by Jonathan v1.
  - Refactor critical section of scd30_trigger_handler() into helper
    called scd30_trigger_handler_helper_locked().
  - Revert removal of goto in scd30_trigger_handler().

 v3:
  - Tune up helper to return early on failure condition per Jonathan's
    suggestion.

 v4:
  - Forgot to commit changes listed in v3, now fixed.

 v5:
  - Remove unneeded comment for scd30_trigger_handler_helper() per
    Jonathan's suggestion.
  - Change name of arr_size to scan_data_size per Jonathan's suggestion.
  - Change type of scan_data_size to size_t per Jonathan's suggestion.
  - Added blank line between return and the rest of the function body in
    scd30_trigger_handler_helper().

 drivers/iio/chemical/scd30_core.c | 66 ++++++++++++++++++++-----------
 1 file changed, 42 insertions(+), 24 deletions(-)

diff --git a/drivers/iio/chemical/scd30_core.c b/drivers/iio/chemical/scd30_core.c
index a665fcb78806..20258059f915 100644
--- a/drivers/iio/chemical/scd30_core.c
+++ b/drivers/iio/chemical/scd30_core.c
@@ -368,11 +368,13 @@ static ssize_t calibration_auto_enable_show(struct device *dev, struct device_at
 	int ret;
 	u16 val;
 
-	mutex_lock(&state->lock);
-	ret = scd30_command_read(state, CMD_ASC, &val);
-	mutex_unlock(&state->lock);
+	guard(mutex)(&state->lock);
 
-	return ret ?: sysfs_emit(buf, "%d\n", val);
+	ret = scd30_command_read(state, CMD_ASC, &val);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%d\n", val);
 }
 
 static ssize_t calibration_auto_enable_store(struct device *dev, struct device_attribute *attr,
@@ -387,11 +389,13 @@ static ssize_t calibration_auto_enable_store(struct device *dev, struct device_a
 	if (ret)
 		return ret;
 
-	mutex_lock(&state->lock);
-	ret = scd30_command_write(state, CMD_ASC, val);
-	mutex_unlock(&state->lock);
+	guard(mutex)(&state->lock);
 
-	return ret ?: len;
+	ret = scd30_command_write(state, CMD_ASC, val);
+	if (ret)
+		return ret;
+
+	return len;
 }
 
 static ssize_t calibration_forced_value_show(struct device *dev, struct device_attribute *attr,
@@ -402,11 +406,13 @@ static ssize_t calibration_forced_value_show(struct device *dev, struct device_a
 	int ret;
 	u16 val;
 
-	mutex_lock(&state->lock);
-	ret = scd30_command_read(state, CMD_FRC, &val);
-	mutex_unlock(&state->lock);
+	guard(mutex)(&state->lock);
 
-	return ret ?: sysfs_emit(buf, "%d\n", val);
+	ret = scd30_command_read(state, CMD_FRC, &val);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%d\n", val);
 }
 
 static ssize_t calibration_forced_value_store(struct device *dev, struct device_attribute *attr,
@@ -424,11 +430,13 @@ static ssize_t calibration_forced_value_store(struct device *dev, struct device_
 	if (val < SCD30_FRC_MIN_PPM || val > SCD30_FRC_MAX_PPM)
 		return -EINVAL;
 
-	mutex_lock(&state->lock);
-	ret = scd30_command_write(state, CMD_FRC, val);
-	mutex_unlock(&state->lock);
+	guard(mutex)(&state->lock);
 
-	return ret ?: len;
+	ret = scd30_command_write(state, CMD_FRC, val);
+	if (ret)
+		return ret;
+
+	return len;
 }
 
 static IIO_DEVICE_ATTR_RO(sampling_frequency_available, 0);
@@ -579,24 +587,34 @@ static irqreturn_t scd30_irq_thread_handler(int irq, void *priv)
 	return IRQ_HANDLED;
 }
 
+static int scd30_trigger_handler_helper(struct iio_dev *indio_dev, int *scan_data,
+					size_t scan_data_size)
+{
+	struct scd30_state *state = iio_priv(indio_dev);
+	int ret;
+
+	guard(mutex)(&state->lock);
+
+	if (!iio_trigger_using_own(indio_dev))
+		ret = scd30_read_poll(state);
+	else
+		ret = scd30_read_meas(state);
+	memcpy(scan_data, state->meas, scan_data_size);
+
+	return ret;
+}
+
 static irqreturn_t scd30_trigger_handler(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
-	struct scd30_state *state = iio_priv(indio_dev);
 	struct {
 		int data[SCD30_MEAS_COUNT];
 		aligned_s64 ts;
 	} scan = { };
 	int ret;
 
-	mutex_lock(&state->lock);
-	if (!iio_trigger_using_own(indio_dev))
-		ret = scd30_read_poll(state);
-	else
-		ret = scd30_read_meas(state);
-	memcpy(scan.data, state->meas, sizeof(state->meas));
-	mutex_unlock(&state->lock);
+	ret = scd30_trigger_handler_helper_locked(indio_dev, scan.data, sizeof(scan.data));
 	if (ret)
 		goto out;
 
-- 
2.54.0
Re: [PATCH v5] iio: chemical: scd30: Replace manual locking with RAII locking
Posted by kernel test robot 1 week, 3 days ago
Hi Maxwell,

kernel test robot noticed the following build errors:

[auto build test ERROR on jic23-iio/togreg]
[also build test ERROR on linus/master v7.1-rc5 next-20260528]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Maxwell-Doose/iio-chemical-scd30-Replace-manual-locking-with-RAII-locking/20260529-063551
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
patch link:    https://lore.kernel.org/r/20260528222906.61561-1-m32285159%40gmail.com
patch subject: [PATCH v5] iio: chemical: scd30: Replace manual locking with RAII locking
config: loongarch-randconfig-r071-20260529 (https://download.01.org/0day-ci/archive/20260529/202605292101.GTdtBJA1-lkp@intel.com/config)
compiler: loongarch64-linux-gcc (GCC) 15.2.0
smatch: v0.5.0-9185-gbcc58b9c
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260529/202605292101.GTdtBJA1-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202605292101.GTdtBJA1-lkp@intel.com/

All error/warnings (new ones prefixed by >>):

   drivers/iio/chemical/scd30_core.c: In function 'scd30_trigger_handler':
>> drivers/iio/chemical/scd30_core.c:617:15: error: implicit declaration of function 'scd30_trigger_handler_helper_locked'; did you mean 'scd30_trigger_handler_helper'? [-Wimplicit-function-declaration]
     617 |         ret = scd30_trigger_handler_helper_locked(indio_dev, scan.data, sizeof(scan.data));
         |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         |               scd30_trigger_handler_helper
   drivers/iio/chemical/scd30_core.c: At top level:
>> drivers/iio/chemical/scd30_core.c:590:12: warning: 'scd30_trigger_handler_helper' defined but not used [-Wunused-function]
     590 | static int scd30_trigger_handler_helper(struct iio_dev *indio_dev, int *scan_data,
         |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~


vim +617 drivers/iio/chemical/scd30_core.c

   589	
 > 590	static int scd30_trigger_handler_helper(struct iio_dev *indio_dev, int *scan_data,
   591						size_t scan_data_size)
   592	{
   593		struct scd30_state *state = iio_priv(indio_dev);
   594		int ret;
   595	
   596		guard(mutex)(&state->lock);
   597	
   598		if (!iio_trigger_using_own(indio_dev))
   599			ret = scd30_read_poll(state);
   600		else
   601			ret = scd30_read_meas(state);
   602		memcpy(scan_data, state->meas, scan_data_size);
   603	
   604		return ret;
   605	}
   606	
   607	static irqreturn_t scd30_trigger_handler(int irq, void *p)
   608	{
   609		struct iio_poll_func *pf = p;
   610		struct iio_dev *indio_dev = pf->indio_dev;
   611		struct {
   612			int data[SCD30_MEAS_COUNT];
   613			aligned_s64 ts;
   614		} scan = { };
   615		int ret;
   616	
 > 617		ret = scd30_trigger_handler_helper_locked(indio_dev, scan.data, sizeof(scan.data));
   618		if (ret)
   619			goto out;
   620	
   621		iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan),
   622					    iio_get_time_ns(indio_dev));
   623	out:
   624		iio_trigger_notify_done(indio_dev->trig);
   625		return IRQ_HANDLED;
   626	}
   627	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v5] iio: chemical: scd30: Replace manual locking with RAII locking
Posted by kernel test robot 1 week, 3 days ago
Hi Maxwell,

kernel test robot noticed the following build errors:

[auto build test ERROR on jic23-iio/togreg]
[also build test ERROR on linus/master v7.1-rc5 next-20260528]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Maxwell-Doose/iio-chemical-scd30-Replace-manual-locking-with-RAII-locking/20260529-063551
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
patch link:    https://lore.kernel.org/r/20260528222906.61561-1-m32285159%40gmail.com
patch subject: [PATCH v5] iio: chemical: scd30: Replace manual locking with RAII locking
config: hexagon-randconfig-r073-20260529 (https://download.01.org/0day-ci/archive/20260529/202605292103.zH0JgWhp-lkp@intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
smatch: v0.5.0-9185-gbcc58b9c
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260529/202605292103.zH0JgWhp-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202605292103.zH0JgWhp-lkp@intel.com/

All errors (new ones prefixed by >>):

>> drivers/iio/chemical/scd30_core.c:617:8: error: call to undeclared function 'scd30_trigger_handler_helper_locked'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
     617 |         ret = scd30_trigger_handler_helper_locked(indio_dev, scan.data, sizeof(scan.data));
         |               ^
   drivers/iio/chemical/scd30_core.c:617:8: note: did you mean 'scd30_trigger_handler_helper'?
   drivers/iio/chemical/scd30_core.c:590:12: note: 'scd30_trigger_handler_helper' declared here
     590 | static int scd30_trigger_handler_helper(struct iio_dev *indio_dev, int *scan_data,
         |            ^
   1 error generated.


vim +/scd30_trigger_handler_helper_locked +617 drivers/iio/chemical/scd30_core.c

   606	
   607	static irqreturn_t scd30_trigger_handler(int irq, void *p)
   608	{
   609		struct iio_poll_func *pf = p;
   610		struct iio_dev *indio_dev = pf->indio_dev;
   611		struct {
   612			int data[SCD30_MEAS_COUNT];
   613			aligned_s64 ts;
   614		} scan = { };
   615		int ret;
   616	
 > 617		ret = scd30_trigger_handler_helper_locked(indio_dev, scan.data, sizeof(scan.data));
   618		if (ret)
   619			goto out;
   620	
   621		iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan),
   622					    iio_get_time_ns(indio_dev));
   623	out:
   624		iio_trigger_notify_done(indio_dev->trig);
   625		return IRQ_HANDLED;
   626	}
   627	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v5] iio: chemical: scd30: Replace manual locking with RAII locking
Posted by Jonathan Cameron 1 week, 3 days ago
On Thu, 28 May 2026 17:29:06 -0500
Maxwell Doose <m32285159@gmail.com> wrote:

> scd30_core.c currently uses manual mutex_lock() and mutex_unlock()
> calls. Replace them with the newer guard(mutex)() for cleaner RAII
> patterns and to improve maintainability.
> 
> Add new helper function scd30_trigger_handler_helper() containing
> the critical section for scd30_trigger_handler().
> 
> In addition, small refactor to replace "?:" operator with regular
> if/else returns.
> 
> Signed-off-by: Maxwell Doose <m32285159@gmail.com>

Looks like you sent a version that won't build.
> +static int scd30_trigger_handler_helper(struct iio_dev *indio_dev, int *scan_data,
> +					size_t scan_data_size)
> +{
> +	struct scd30_state *state = iio_priv(indio_dev);
> +	int ret;
> +
> +	guard(mutex)(&state->lock);
> +
> +	if (!iio_trigger_using_own(indio_dev))
> +		ret = scd30_read_poll(state);
> +	else
> +		ret = scd30_read_meas(state);
> +	memcpy(scan_data, state->meas, scan_data_size);
> +
> +	return ret;
> +}
> +
>  static irqreturn_t scd30_trigger_handler(int irq, void *p)
>  {
>  	struct iio_poll_func *pf = p;
>  	struct iio_dev *indio_dev = pf->indio_dev;
> -	struct scd30_state *state = iio_priv(indio_dev);
>  	struct {
>  		int data[SCD30_MEAS_COUNT];
>  		aligned_s64 ts;
>  	} scan = { };
>  	int ret;
>  
> -	mutex_lock(&state->lock);
> -	if (!iio_trigger_using_own(indio_dev))
> -		ret = scd30_read_poll(state);
> -	else
> -		ret = scd30_read_meas(state);
> -	memcpy(scan.data, state->meas, sizeof(state->meas));
> -	mutex_unlock(&state->lock);
> +	ret = scd30_trigger_handler_helper_locked(indio_dev, scan.data, sizeof(scan.data));
The call needs an update t the new naming.

>  	if (ret)
>  		goto out;
>
Re: [PATCH v5] iio: chemical: scd30: Replace manual locking with RAII locking
Posted by Maxwell Doose 1 week, 3 days ago
On Fri, May 29, 2026 at 5:42 AM Jonathan Cameron <jic23@kernel.org> wrote:
>
> On Thu, 28 May 2026 17:29:06 -0500
> Maxwell Doose <m32285159@gmail.com> wrote:
>
> > scd30_core.c currently uses manual mutex_lock() and mutex_unlock()
> > calls. Replace them with the newer guard(mutex)() for cleaner RAII
> > patterns and to improve maintainability.
> >
> > Add new helper function scd30_trigger_handler_helper() containing
> > the critical section for scd30_trigger_handler().
> >
> > In addition, small refactor to replace "?:" operator with regular
> > if/else returns.
> >
> > Signed-off-by: Maxwell Doose <m32285159@gmail.com>
>
> Looks like you sent a version that won't build.
> > +static int scd30_trigger_handler_helper(struct iio_dev *indio_dev, int *scan_data,
> > +                                     size_t scan_data_size)
> > +{
> > +     struct scd30_state *state = iio_priv(indio_dev);
> > +     int ret;
> > +
> > +     guard(mutex)(&state->lock);
> > +
> > +     if (!iio_trigger_using_own(indio_dev))
> > +             ret = scd30_read_poll(state);
> > +     else
> > +             ret = scd30_read_meas(state);
> > +     memcpy(scan_data, state->meas, scan_data_size);
> > +
> > +     return ret;
> > +}
> > +
> >  static irqreturn_t scd30_trigger_handler(int irq, void *p)
> >  {
> >       struct iio_poll_func *pf = p;
> >       struct iio_dev *indio_dev = pf->indio_dev;
> > -     struct scd30_state *state = iio_priv(indio_dev);
> >       struct {
> >               int data[SCD30_MEAS_COUNT];
> >               aligned_s64 ts;
> >       } scan = { };
> >       int ret;
> >
> > -     mutex_lock(&state->lock);
> > -     if (!iio_trigger_using_own(indio_dev))
> > -             ret = scd30_read_poll(state);
> > -     else
> > -             ret = scd30_read_meas(state);
> > -     memcpy(scan.data, state->meas, sizeof(state->meas));
> > -     mutex_unlock(&state->lock);
> > +     ret = scd30_trigger_handler_helper_locked(indio_dev, scan.data, sizeof(scan.data));
> The call needs an update t the new naming.
>

Gah, I don't know how I missed that :/ Will update for v6.

>
> >       if (ret)
> >               goto out;
> >
>