* [PATCH v2 1/7] iio: core: Add and export __iio_dev_mode_lock()
2025-12-12 2:45 [PATCH v2 0/7] iio: core: Introduce cleanup.h support for mode locks Kurt Borja
@ 2025-12-12 2:45 ` Kurt Borja
2025-12-12 18:21 ` Andy Shevchenko
2025-12-12 2:45 ` [PATCH v2 2/7] iio: core: Refactor iio_device_claim_direct() implementation Kurt Borja
` (5 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: Kurt Borja @ 2025-12-12 2:45 UTC (permalink / raw)
To: Andy Shevchenko, Lars-Peter Clausen, Michael Hennerich,
Jonathan Cameron, Benson Leung, Antoniu Miclaus, Gwendal Grignou,
Shrikant Raskar, Per-Daniel Olsson
Cc: David Lechner, Nuno Sá, Andy Shevchenko, Guenter Roeck,
Jonathan Cameron, linux-iio, linux-kernel, chrome-platform,
Kurt Borja
Add infallible wrappers around the internal IIO mode lock.
As mentioned in the documentation, this is not meant to be used by
drivers, instead this will aid in the eventual addition of cleanup
classes around conditional locks.
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/iio/industrialio-core.c | 30 ++++++++++++++++++++++++++++++
include/linux/iio/iio.h | 3 +++
2 files changed, 33 insertions(+)
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index f69deefcfb6f..1cce2d1ecef1 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -2171,6 +2171,36 @@ int __devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev,
}
EXPORT_SYMBOL_GPL(__devm_iio_device_register);
+/**
+ * __iio_dev_mode_lock - Locks the current IIO device mode
+ * @indio_dev: the iio_dev associated with the device
+ *
+ * If the device is either in direct or buffer mode, it's guaranteed to stay
+ * that way until __iio_dev_mode_unlock() is called.
+ *
+ * This function is not meant to be used directly by drivers to protect internal
+ * state, a driver should have it's own mechanisms for that matter.
+ *
+ * There are very few cases where a driver actually needs to lock any mode. It's
+ * *strongly* recommended to use iio_device_claim_direct() or
+ * iio_device_claim_buffer_mode() pairs or related helpers.
+ */
+void __iio_dev_mode_lock(struct iio_dev *indio_dev)
+{
+ mutex_lock(&to_iio_dev_opaque(indio_dev)->mlock);
+}
+EXPORT_SYMBOL_GPL(__iio_dev_mode_lock);
+
+/**
+ * __iio_dev_mode_unlock - Unlocks the current IIO device mode
+ * @indio_dev: the iio_dev associated with the device
+ */
+void __iio_dev_mode_unlock(struct iio_dev *indio_dev)
+{
+ mutex_unlock(&to_iio_dev_opaque(indio_dev)->mlock);
+}
+EXPORT_SYMBOL_GPL(__iio_dev_mode_unlock);
+
/**
* __iio_device_claim_direct - Keep device in direct mode
* @indio_dev: the iio_dev associated with the device
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index 872ebdf0dd77..aecda887d833 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -661,6 +661,9 @@ void iio_device_unregister(struct iio_dev *indio_dev);
int __devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev,
struct module *this_mod);
int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp);
+
+void __iio_dev_mode_lock(struct iio_dev *indio_dev) __acquires(indio_dev);
+void __iio_dev_mode_unlock(struct iio_dev *indio_dev) __releases(indio_dev);
bool __iio_device_claim_direct(struct iio_dev *indio_dev);
void __iio_device_release_direct(struct iio_dev *indio_dev);
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH v2 1/7] iio: core: Add and export __iio_dev_mode_lock()
2025-12-12 2:45 ` [PATCH v2 1/7] iio: core: Add and export __iio_dev_mode_lock() Kurt Borja
@ 2025-12-12 18:21 ` Andy Shevchenko
0 siblings, 0 replies; 11+ messages in thread
From: Andy Shevchenko @ 2025-12-12 18:21 UTC (permalink / raw)
To: Kurt Borja
Cc: Lars-Peter Clausen, Michael Hennerich, Jonathan Cameron,
Benson Leung, Antoniu Miclaus, Gwendal Grignou, Shrikant Raskar,
Per-Daniel Olsson, David Lechner, Nuno Sá, Andy Shevchenko,
Guenter Roeck, Jonathan Cameron, linux-iio, linux-kernel,
chrome-platform
On Thu, Dec 11, 2025 at 09:45:19PM -0500, Kurt Borja wrote:
> Add infallible wrappers around the internal IIO mode lock.
>
> As mentioned in the documentation, this is not meant to be used by
> drivers, instead this will aid in the eventual addition of cleanup
> classes around conditional locks.
...
> +EXPORT_SYMBOL_GPL(__iio_dev_mode_lock);
> +EXPORT_SYMBOL_GPL(__iio_dev_mode_unlock);
Put them to "IIO_CORE" namespace.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2 2/7] iio: core: Refactor iio_device_claim_direct() implementation
2025-12-12 2:45 [PATCH v2 0/7] iio: core: Introduce cleanup.h support for mode locks Kurt Borja
2025-12-12 2:45 ` [PATCH v2 1/7] iio: core: Add and export __iio_dev_mode_lock() Kurt Borja
@ 2025-12-12 2:45 ` Kurt Borja
2025-12-12 18:23 ` Andy Shevchenko
2025-12-12 2:45 ` [PATCH v2 3/7] iio: core: Match iio_device_claim_*() semantics and implementation Kurt Borja
` (4 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: Kurt Borja @ 2025-12-12 2:45 UTC (permalink / raw)
To: Andy Shevchenko, Lars-Peter Clausen, Michael Hennerich,
Jonathan Cameron, Benson Leung, Antoniu Miclaus, Gwendal Grignou,
Shrikant Raskar, Per-Daniel Olsson
Cc: David Lechner, Nuno Sá, Andy Shevchenko, Guenter Roeck,
Jonathan Cameron, linux-iio, linux-kernel, chrome-platform,
Kurt Borja
In order to eventually unify the locking API, implement
iio_device_claim_direct() fully inline, with the use of
__iio_dev_mode_lock(), which takes care of sparse annotations.
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/iio/industrialio-core.c | 44 -----------------------------------------
include/linux/iio/iio.h | 38 +++++++++++++++++++++++------------
2 files changed, 25 insertions(+), 57 deletions(-)
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 1cce2d1ecef1..cffc6efb6617 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -2201,50 +2201,6 @@ void __iio_dev_mode_unlock(struct iio_dev *indio_dev)
}
EXPORT_SYMBOL_GPL(__iio_dev_mode_unlock);
-/**
- * __iio_device_claim_direct - Keep device in direct mode
- * @indio_dev: the iio_dev associated with the device
- *
- * If the device is in direct mode it is guaranteed to stay
- * that way until __iio_device_release_direct() is called.
- *
- * Use with __iio_device_release_direct().
- *
- * Drivers should only call iio_device_claim_direct().
- *
- * Returns: true on success, false on failure.
- */
-bool __iio_device_claim_direct(struct iio_dev *indio_dev)
-{
- struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
-
- mutex_lock(&iio_dev_opaque->mlock);
-
- if (iio_buffer_enabled(indio_dev)) {
- mutex_unlock(&iio_dev_opaque->mlock);
- return false;
- }
- return true;
-}
-EXPORT_SYMBOL_GPL(__iio_device_claim_direct);
-
-/**
- * __iio_device_release_direct - releases claim on direct mode
- * @indio_dev: the iio_dev associated with the device
- *
- * Release the claim. Device is no longer guaranteed to stay
- * in direct mode.
- *
- * Drivers should only call iio_device_release_direct().
- *
- * Use with __iio_device_claim_direct()
- */
-void __iio_device_release_direct(struct iio_dev *indio_dev)
-{
- mutex_unlock(&to_iio_dev_opaque(indio_dev)->mlock);
-}
-EXPORT_SYMBOL_GPL(__iio_device_release_direct);
-
/**
* iio_device_claim_buffer_mode - Keep device in buffer mode
* @indio_dev: the iio_dev associated with the device
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index aecda887d833..76398dbfa5ca 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -664,30 +664,42 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp);
void __iio_dev_mode_lock(struct iio_dev *indio_dev) __acquires(indio_dev);
void __iio_dev_mode_unlock(struct iio_dev *indio_dev) __releases(indio_dev);
-bool __iio_device_claim_direct(struct iio_dev *indio_dev);
-void __iio_device_release_direct(struct iio_dev *indio_dev);
-/*
- * Helper functions that allow claim and release of direct mode
- * in a fashion that doesn't generate many false positives from sparse.
- * Note this must remain static inline in the header so that sparse
- * can see the __acquire() marking. Revisit when sparse supports
- * __cond_acquires()
+/**
+ * iio_device_claim_direct - Keep device in direct mode
+ * @indio_dev: the iio_dev associated with the device
+ *
+ * If the device is in direct mode it is guaranteed to stay
+ * that way until iio_device_release_direct() is called.
+ *
+ * Use with iio_device_release_direct().
+ *
+ * Returns: true on success, false on failure.
*/
static inline bool iio_device_claim_direct(struct iio_dev *indio_dev)
{
- if (!__iio_device_claim_direct(indio_dev))
- return false;
+ __iio_dev_mode_lock(indio_dev);
- __acquire(iio_dev);
+ if (iio_buffer_enabled(indio_dev)) {
+ __iio_dev_mode_unlock(indio_dev);
+ return false;
+ }
return true;
}
+/**
+ * iio_device_release_direct - Releases claim on direct mode
+ * @indio_dev: the iio_dev associated with the device
+ *
+ * Release the claim. Device is no longer guaranteed to stay
+ * in direct mode.
+ *
+ * Use with iio_device_claim_direct()
+ */
static inline void iio_device_release_direct(struct iio_dev *indio_dev)
{
- __iio_device_release_direct(indio_dev);
- __release(indio_dev);
+ __iio_dev_mode_unlock(indio_dev);
}
int iio_device_claim_buffer_mode(struct iio_dev *indio_dev);
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH v2 2/7] iio: core: Refactor iio_device_claim_direct() implementation
2025-12-12 2:45 ` [PATCH v2 2/7] iio: core: Refactor iio_device_claim_direct() implementation Kurt Borja
@ 2025-12-12 18:23 ` Andy Shevchenko
0 siblings, 0 replies; 11+ messages in thread
From: Andy Shevchenko @ 2025-12-12 18:23 UTC (permalink / raw)
To: Kurt Borja
Cc: Lars-Peter Clausen, Michael Hennerich, Jonathan Cameron,
Benson Leung, Antoniu Miclaus, Gwendal Grignou, Shrikant Raskar,
Per-Daniel Olsson, David Lechner, Nuno Sá, Andy Shevchenko,
Guenter Roeck, Jonathan Cameron, linux-iio, linux-kernel,
chrome-platform
On Thu, Dec 11, 2025 at 09:45:20PM -0500, Kurt Borja wrote:
> In order to eventually unify the locking API, implement
> iio_device_claim_direct() fully inline, with the use of
> __iio_dev_mode_lock(), which takes care of sparse annotations.
...
> +/**
> + * iio_device_claim_direct - Keep device in direct mode
> + * @indio_dev: the iio_dev associated with the device
> + *
> + * If the device is in direct mode it is guaranteed to stay
> + * that way until iio_device_release_direct() is called.
> + *
> + * Use with iio_device_release_direct().
Nice.
> + * Returns: true on success, false on failure.
> */
...
> +/**
> + * iio_device_release_direct - Releases claim on direct mode
> + * @indio_dev: the iio_dev associated with the device
> + *
> + * Release the claim. Device is no longer guaranteed to stay
> + * in direct mode.
> + *
> + * Use with iio_device_claim_direct()
Not nice — missed period.
> + */
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2 3/7] iio: core: Match iio_device_claim_*() semantics and implementation
2025-12-12 2:45 [PATCH v2 0/7] iio: core: Introduce cleanup.h support for mode locks Kurt Borja
2025-12-12 2:45 ` [PATCH v2 1/7] iio: core: Add and export __iio_dev_mode_lock() Kurt Borja
2025-12-12 2:45 ` [PATCH v2 2/7] iio: core: Refactor iio_device_claim_direct() implementation Kurt Borja
@ 2025-12-12 2:45 ` Kurt Borja
2025-12-12 18:27 ` Andy Shevchenko
2025-12-12 2:45 ` [PATCH v2 4/7] iio: core: Add cleanup.h support for iio_device_claim_*() Kurt Borja
` (3 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: Kurt Borja @ 2025-12-12 2:45 UTC (permalink / raw)
To: Andy Shevchenko, Lars-Peter Clausen, Michael Hennerich,
Jonathan Cameron, Benson Leung, Antoniu Miclaus, Gwendal Grignou,
Shrikant Raskar, Per-Daniel Olsson
Cc: David Lechner, Nuno Sá, Andy Shevchenko, Guenter Roeck,
Jonathan Cameron, linux-iio, linux-kernel, chrome-platform,
Kurt Borja
Implement iio_device_claim_buffer_mode() fully inline with the use of
__iio_dev_mode_lock(), which takes care of sparse annotations.
To completely match iio_device_claim_direct() semantics, we need to
also change iio_device_claim_buffer_mode() return semantics to usual
true/false conditional lock semantics.
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/iio/adc/ade9000.c | 2 +-
.../common/cros_ec_sensors/cros_ec_sensors_core.c | 5 +--
drivers/iio/health/max30100.c | 2 +-
drivers/iio/health/max30102.c | 2 +-
drivers/iio/industrialio-core.c | 40 ----------------------
drivers/iio/light/opt4060.c | 2 +-
include/linux/iio/iio.h | 38 ++++++++++++++++++--
7 files changed, 41 insertions(+), 50 deletions(-)
diff --git a/drivers/iio/adc/ade9000.c b/drivers/iio/adc/ade9000.c
index 2de8a718d62a..b345c4d1ef24 100644
--- a/drivers/iio/adc/ade9000.c
+++ b/drivers/iio/adc/ade9000.c
@@ -964,7 +964,7 @@ static irqreturn_t ade9000_dready_thread(int irq, void *data)
struct iio_dev *indio_dev = data;
/* Handle data ready interrupt from C4/EVENT/DREADY pin */
- if (!iio_device_claim_buffer_mode(indio_dev)) {
+ if (iio_device_claim_buffer_mode(indio_dev)) {
ade9000_iio_push_buffer(indio_dev);
iio_device_release_buffer_mode(indio_dev);
}
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 9ac80e4b7d75..8ed4b2e410c8 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
@@ -188,11 +188,8 @@ int cros_ec_sensors_push_data(struct iio_dev *indio_dev,
/*
* Ignore samples if the buffer is not set: it is needed if the ODR is
* set but the buffer is not enabled yet.
- *
- * Note: iio_device_claim_buffer_mode() returns -EBUSY if the buffer
- * is not enabled.
*/
- if (iio_device_claim_buffer_mode(indio_dev) < 0)
+ if (!iio_device_claim_buffer_mode(indio_dev))
return 0;
out = (s16 *)st->samples;
diff --git a/drivers/iio/health/max30100.c b/drivers/iio/health/max30100.c
index 3d441013893c..3f3680c4b42f 100644
--- a/drivers/iio/health/max30100.c
+++ b/drivers/iio/health/max30100.c
@@ -417,7 +417,7 @@ static int max30100_read_raw(struct iio_dev *indio_dev,
* Temperature reading can only be acquired while engine
* is running
*/
- if (iio_device_claim_buffer_mode(indio_dev)) {
+ if (!iio_device_claim_buffer_mode(indio_dev)) {
/*
* Replacing -EBUSY or other error code
* returned by iio_device_claim_buffer_mode()
diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index a48c0881a4c7..288c2f37a4a2 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -476,7 +476,7 @@ static int max30102_read_raw(struct iio_dev *indio_dev,
* shutdown; leave shutdown briefly when buffer not running
*/
any_mode_retry:
- if (iio_device_claim_buffer_mode(indio_dev)) {
+ if (!iio_device_claim_buffer_mode(indio_dev)) {
/*
* This one is a *bit* hacky. If we cannot claim buffer
* mode, then try direct mode so that we make sure
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index cffc6efb6617..46e336bff64c 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -2201,46 +2201,6 @@ void __iio_dev_mode_unlock(struct iio_dev *indio_dev)
}
EXPORT_SYMBOL_GPL(__iio_dev_mode_unlock);
-/**
- * iio_device_claim_buffer_mode - Keep device in buffer mode
- * @indio_dev: the iio_dev associated with the device
- *
- * If the device is in buffer mode it is guaranteed to stay
- * that way until iio_device_release_buffer_mode() is called.
- *
- * Use with iio_device_release_buffer_mode().
- *
- * Returns: 0 on success, -EBUSY on failure.
- */
-int iio_device_claim_buffer_mode(struct iio_dev *indio_dev)
-{
- struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
-
- mutex_lock(&iio_dev_opaque->mlock);
-
- if (iio_buffer_enabled(indio_dev))
- return 0;
-
- mutex_unlock(&iio_dev_opaque->mlock);
- return -EBUSY;
-}
-EXPORT_SYMBOL_GPL(iio_device_claim_buffer_mode);
-
-/**
- * iio_device_release_buffer_mode - releases claim on buffer mode
- * @indio_dev: the iio_dev associated with the device
- *
- * Release the claim. Device is no longer guaranteed to stay
- * in buffer mode.
- *
- * Use with iio_device_claim_buffer_mode().
- */
-void iio_device_release_buffer_mode(struct iio_dev *indio_dev)
-{
- mutex_unlock(&to_iio_dev_opaque(indio_dev)->mlock);
-}
-EXPORT_SYMBOL_GPL(iio_device_release_buffer_mode);
-
/**
* iio_device_get_current_mode() - helper function providing read-only access to
* the opaque @currentmode variable
diff --git a/drivers/iio/light/opt4060.c b/drivers/iio/light/opt4060.c
index 981c704e7df5..8cb3fa38077e 100644
--- a/drivers/iio/light/opt4060.c
+++ b/drivers/iio/light/opt4060.c
@@ -304,7 +304,7 @@ static int opt4060_set_driver_state(struct iio_dev *indio_dev,
struct opt4060_chip *chip = iio_priv(indio_dev);
int ret = 0;
any_mode_retry:
- if (iio_device_claim_buffer_mode(indio_dev)) {
+ if (!iio_device_claim_buffer_mode(indio_dev)) {
/*
* This one is a *bit* hacky. If we cannot claim buffer mode,
* then try direct mode so that we make sure things cannot
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index 76398dbfa5ca..f8a7ef709210 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -702,8 +702,42 @@ static inline void iio_device_release_direct(struct iio_dev *indio_dev)
__iio_dev_mode_unlock(indio_dev);
}
-int iio_device_claim_buffer_mode(struct iio_dev *indio_dev);
-void iio_device_release_buffer_mode(struct iio_dev *indio_dev);
+/**
+ * iio_device_claim_buffer_mode - Keep device in buffer mode
+ * @indio_dev: the iio_dev associated with the device
+ *
+ * If the device is in buffer mode it is guaranteed to stay
+ * that way until iio_device_release_buffer_mode() is called.
+ *
+ * Use with iio_device_release_buffer_mode().
+ *
+ * Returns: true on success, false on failure.
+ */
+static inline bool iio_device_claim_buffer_mode(struct iio_dev *indio_dev)
+{
+ __iio_dev_mode_lock(indio_dev);
+
+ if (!iio_buffer_enabled(indio_dev)) {
+ __iio_dev_mode_unlock(indio_dev);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * iio_device_release_buffer_mode - releases claim on buffer mode
+ * @indio_dev: the iio_dev associated with the device
+ *
+ * Release the claim. Device is no longer guaranteed to stay
+ * in buffer mode.
+ *
+ * Use with iio_device_claim_buffer_mode().
+ */
+static inline void iio_device_release_buffer_mode(struct iio_dev *indio_dev)
+{
+ __iio_dev_mode_unlock(indio_dev);
+}
extern const struct bus_type iio_bus_type;
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH v2 3/7] iio: core: Match iio_device_claim_*() semantics and implementation
2025-12-12 2:45 ` [PATCH v2 3/7] iio: core: Match iio_device_claim_*() semantics and implementation Kurt Borja
@ 2025-12-12 18:27 ` Andy Shevchenko
0 siblings, 0 replies; 11+ messages in thread
From: Andy Shevchenko @ 2025-12-12 18:27 UTC (permalink / raw)
To: Kurt Borja
Cc: Lars-Peter Clausen, Michael Hennerich, Jonathan Cameron,
Benson Leung, Antoniu Miclaus, Gwendal Grignou, Shrikant Raskar,
Per-Daniel Olsson, David Lechner, Nuno Sá, Andy Shevchenko,
Guenter Roeck, Jonathan Cameron, linux-iio, linux-kernel,
chrome-platform
On Thu, Dec 11, 2025 at 09:45:21PM -0500, Kurt Borja wrote:
> Implement iio_device_claim_buffer_mode() fully inline with the use of
> __iio_dev_mode_lock(), which takes care of sparse annotations.
>
> To completely match iio_device_claim_direct() semantics, we need to
> also change iio_device_claim_buffer_mode() return semantics to usual
> true/false conditional lock semantics.
...
> - if (iio_device_claim_buffer_mode(indio_dev)) {
> + if (!iio_device_claim_buffer_mode(indio_dev)) {
> /*
> * Replacing -EBUSY or other error code
> * returned by iio_device_claim_buffer_mode()
In one of the previous files you removed a comment, and here it's still present.
...
> - if (iio_device_claim_buffer_mode(indio_dev)) {
> + if (!iio_device_claim_buffer_mode(indio_dev)) {
> /*
> * This one is a *bit* hacky. If we cannot claim buffer
> * mode, then try direct mode so that we make sure
Also check if this comment needs to be amended.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2 4/7] iio: core: Add cleanup.h support for iio_device_claim_*()
2025-12-12 2:45 [PATCH v2 0/7] iio: core: Introduce cleanup.h support for mode locks Kurt Borja
` (2 preceding siblings ...)
2025-12-12 2:45 ` [PATCH v2 3/7] iio: core: Match iio_device_claim_*() semantics and implementation Kurt Borja
@ 2025-12-12 2:45 ` Kurt Borja
2025-12-12 2:45 ` [PATCH v2 5/7] iio: light: vcnl4000: Use IIO cleanup helpers Kurt Borja
` (2 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Kurt Borja @ 2025-12-12 2:45 UTC (permalink / raw)
To: Andy Shevchenko, Lars-Peter Clausen, Michael Hennerich,
Jonathan Cameron, Benson Leung, Antoniu Miclaus, Gwendal Grignou,
Shrikant Raskar, Per-Daniel Olsson
Cc: David Lechner, Nuno Sá, Andy Shevchenko, Guenter Roeck,
Jonathan Cameron, linux-iio, linux-kernel, chrome-platform,
Kurt Borja
Add guard classes for iio_device_claim_*() conditional locks. This will
aid drivers write safer and cleaner code when dealing with some common
patterns.
These classes are not meant to be used directly by drivers (hence the
__priv__ prefix). Instead, documented wrapper macros are provided to
enforce the use of ACQUIRE() or guard() semantics and avoid the
problematic scoped guard.
Suggested-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
include/linux/iio/iio.h | 83 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 83 insertions(+)
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index f8a7ef709210..c84853c7a37f 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -10,6 +10,7 @@
#include <linux/align.h>
#include <linux/device.h>
#include <linux/cdev.h>
+#include <linux/cleanup.h>
#include <linux/compiler_types.h>
#include <linux/minmax.h>
#include <linux/slab.h>
@@ -739,6 +740,88 @@ static inline void iio_device_release_buffer_mode(struct iio_dev *indio_dev)
__iio_dev_mode_unlock(indio_dev);
}
+DEFINE_GUARD(__priv__iio_dev_mode_lock, struct iio_dev *,
+ __iio_dev_mode_lock(_T), __iio_dev_mode_unlock(_T));
+DEFINE_GUARD_COND(__priv__iio_dev_mode_lock, _try_buffer,
+ iio_device_claim_buffer_mode(_T));
+DEFINE_GUARD_COND(__priv__iio_dev_mode_lock, _try_direct,
+ iio_device_claim_direct(_T));
+
+/**
+ * IIO_DEV_ACQUIRE_DIRECT_MODE(_dev, _var) - Tries to acquire the direct mode
+ * lock with automatic release
+ * @_dev: IIO device instance
+ * @_var: Dummy variable identifier to store acquire result
+ *
+ * Tries to acquire the direct mode lock with cleanup ACQUIRE() semantics and
+ * automatically releases it at the end of the scope. It most be always paired
+ * with IIO_DEV_ACQUIRE_ERR(), for example::
+ *
+ * IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
+ * if (IIO_DEV_ACQUIRE_ERR(&claim))
+ * return -EBUSY;
+ *
+ * ...or a more common scenario (notice scope the braces)::
+ *
+ * switch() {
+ * case IIO_CHAN_INFO_RAW: {
+ * IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
+ * if (IIO_DEV_ACQUIRE_ERR(&claim))
+ * return -EBUSY;
+ *
+ * ...
+ * }
+ * case IIO_CHAN_INFO_SCALE:
+ * ...
+ * ...
+ * }
+ *
+ * Context: Can sleep
+ */
+#define IIO_DEV_ACQUIRE_DIRECT_MODE(_dev, _var) \
+ ACQUIRE(__priv__iio_dev_mode_lock_try_direct, _var)(_dev)
+
+/**
+ * IIO_DEV_ACQUIRE_BUFFER_MODE(_dev, _var) - Tries to acquire the buffer mode
+ * lock with automatic release
+ * @_dev: IIO device instance
+ * @_var: Dummy variable identifier to store acquire result
+ *
+ * Tries to acquire the direct mode lock and automatically releases it at the
+ * end of the scope. It most be paired with IIO_DEV_ACQUIRE_ERR(), for example::
+ *
+ * IIO_DEV_ACQUIRE_BUFFER_MODE(indio_dev, claim);
+ * if (IIO_DEV_ACQUIRE_ERR(&claim))
+ * return IRQ_HANDLED;
+ *
+ * Context: Can sleep
+ */
+#define IIO_DEV_ACQUIRE_BUFFER_MODE(_dev, _var) \
+ ACQUIRE(__priv__iio_dev_mode_lock_try_buffer, _var)(_dev)
+
+/**
+ * IIO_DEV_ACQUIRE_ERR() - ACQUIRE_ERR() wrapper
+ * @_var: Dummy variable passed to IIO_DEV_ACQUIRE_*_MODE()
+ *
+ * Return: true on success, false on error
+ */
+#define IIO_DEV_ACQUIRE_ERR(_var_ptr) \
+ ACQUIRE_ERR(__priv__iio_dev_mode_lock_try_buffer, _var_ptr)
+
+/**
+ * IIO_DEV_GUARD_ANY_MODE - Acquires the mode lock with automatic release
+ * @_dev: IIO device instance
+ *
+ * Acquires the mode lock with cleanup guard() semantics. It is usually paired
+ * with iio_buffer_enabled().
+ *
+ * This should *not* be used to protect internal driver state and it's use in
+ * general is *strongly* discouraged. Use any of the IIO_DEV_ACQUIRE_*_MODE()
+ * variants.
+ */
+#define IIO_DEV_GUARD_ANY_MODE(_dev) \
+ guard(__priv__iio_dev_mode_lock)(_dev)
+
extern const struct bus_type iio_bus_type;
/**
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 5/7] iio: light: vcnl4000: Use IIO cleanup helpers
2025-12-12 2:45 [PATCH v2 0/7] iio: core: Introduce cleanup.h support for mode locks Kurt Borja
` (3 preceding siblings ...)
2025-12-12 2:45 ` [PATCH v2 4/7] iio: core: Add cleanup.h support for iio_device_claim_*() Kurt Borja
@ 2025-12-12 2:45 ` Kurt Borja
2025-12-12 2:45 ` [PATCH v2 6/7] iio: health: max30102: " Kurt Borja
2025-12-12 2:45 ` [PATCH v2 7/7] iio: light: opt4060: " Kurt Borja
6 siblings, 0 replies; 11+ messages in thread
From: Kurt Borja @ 2025-12-12 2:45 UTC (permalink / raw)
To: Andy Shevchenko, Lars-Peter Clausen, Michael Hennerich,
Jonathan Cameron, Benson Leung, Antoniu Miclaus, Gwendal Grignou,
Shrikant Raskar, Per-Daniel Olsson
Cc: David Lechner, Nuno Sá, Andy Shevchenko, Guenter Roeck,
Jonathan Cameron, linux-iio, linux-kernel, chrome-platform,
Kurt Borja
Use IIO_DEV_ACQUIRE_DIRECT_MODE() helper to automatically release direct
mode.
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/iio/light/vcnl4000.c | 49 ++++++++++++++++----------------------------
1 file changed, 18 insertions(+), 31 deletions(-)
diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index 4dbb2294a843..4184104ac8f2 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -1078,20 +1078,17 @@ static int vcnl4010_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
- case IIO_CHAN_INFO_SCALE:
- if (!iio_device_claim_direct(indio_dev))
+ case IIO_CHAN_INFO_SCALE: {
+ IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
+ if (IIO_DEV_ACQUIRE_ERR(&claim))
return -EBUSY;
/* Protect against event capture. */
- if (vcnl4010_is_in_periodic_mode(data)) {
- ret = -EBUSY;
- } else {
- ret = vcnl4000_read_raw(indio_dev, chan, val, val2,
- mask);
- }
+ if (vcnl4010_is_in_periodic_mode(data))
+ return -EBUSY;
- iio_device_release_direct(indio_dev);
- return ret;
+ return vcnl4000_read_raw(indio_dev, chan, val, val2, mask);
+ }
case IIO_CHAN_INFO_SAMP_FREQ:
switch (chan->type) {
case IIO_PROXIMITY:
@@ -1148,36 +1145,27 @@ static int vcnl4010_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
- int ret;
struct vcnl4000_data *data = iio_priv(indio_dev);
- if (!iio_device_claim_direct(indio_dev))
+ IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
+ if (IIO_DEV_ACQUIRE_ERR(&claim))
return -EBUSY;
/* Protect against event capture. */
- if (vcnl4010_is_in_periodic_mode(data)) {
- ret = -EBUSY;
- goto end;
- }
+ if (vcnl4010_is_in_periodic_mode(data))
+ return -EBUSY;
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
switch (chan->type) {
case IIO_PROXIMITY:
- ret = vcnl4010_write_proxy_samp_freq(data, val, val2);
- goto end;
+ return vcnl4010_write_proxy_samp_freq(data, val, val2);
default:
- ret = -EINVAL;
- goto end;
+ return -EINVAL;
}
default:
- ret = -EINVAL;
- goto end;
+ return -EINVAL;
}
-
-end:
- iio_device_release_direct(indio_dev);
- return ret;
}
static int vcnl4010_read_event(struct iio_dev *indio_dev,
@@ -1438,14 +1426,13 @@ static int vcnl4010_config_threshold_disable(struct vcnl4000_data *data)
static int vcnl4010_config_threshold(struct iio_dev *indio_dev, bool state)
{
struct vcnl4000_data *data = iio_priv(indio_dev);
- int ret;
if (state) {
- if (!iio_device_claim_direct(indio_dev))
+ IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
+ if (IIO_DEV_ACQUIRE_ERR(&claim))
return -EBUSY;
- ret = vcnl4010_config_threshold_enable(data);
- iio_device_release_direct(indio_dev);
- return ret;
+
+ return vcnl4010_config_threshold_enable(data);
} else {
return vcnl4010_config_threshold_disable(data);
}
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 6/7] iio: health: max30102: Use IIO cleanup helpers
2025-12-12 2:45 [PATCH v2 0/7] iio: core: Introduce cleanup.h support for mode locks Kurt Borja
` (4 preceding siblings ...)
2025-12-12 2:45 ` [PATCH v2 5/7] iio: light: vcnl4000: Use IIO cleanup helpers Kurt Borja
@ 2025-12-12 2:45 ` Kurt Borja
2025-12-12 2:45 ` [PATCH v2 7/7] iio: light: opt4060: " Kurt Borja
6 siblings, 0 replies; 11+ messages in thread
From: Kurt Borja @ 2025-12-12 2:45 UTC (permalink / raw)
To: Andy Shevchenko, Lars-Peter Clausen, Michael Hennerich,
Jonathan Cameron, Benson Leung, Antoniu Miclaus, Gwendal Grignou,
Shrikant Raskar, Per-Daniel Olsson
Cc: David Lechner, Nuno Sá, Andy Shevchenko, Guenter Roeck,
Jonathan Cameron, linux-iio, linux-kernel, chrome-platform,
Kurt Borja
Use IIO_DEV_GUARD_ANY_MODE() cleanup helper to simplify and drop
busy-waiting code in max30102_read_raw().
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/iio/health/max30102.c | 33 +++++++++------------------------
1 file changed, 9 insertions(+), 24 deletions(-)
diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index 288c2f37a4a2..94e15598ffe7 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -467,44 +467,29 @@ static int max30102_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask)
{
struct max30102_data *data = iio_priv(indio_dev);
- int ret = -EINVAL;
+ int ret;
switch (mask) {
- case IIO_CHAN_INFO_RAW:
+ case IIO_CHAN_INFO_RAW: {
/*
* Temperature reading can only be acquired when not in
* shutdown; leave shutdown briefly when buffer not running
*/
-any_mode_retry:
- if (!iio_device_claim_buffer_mode(indio_dev)) {
- /*
- * This one is a *bit* hacky. If we cannot claim buffer
- * mode, then try direct mode so that we make sure
- * things cannot concurrently change. And we just keep
- * trying until we get one of the modes...
- */
- if (!iio_device_claim_direct(indio_dev))
- goto any_mode_retry;
+ IIO_DEV_GUARD_ANY_MODE(indio_dev);
- ret = max30102_get_temp(data, val, true);
- iio_device_release_direct(indio_dev);
- } else {
- ret = max30102_get_temp(data, val, false);
- iio_device_release_buffer_mode(indio_dev);
- }
+ ret = max30102_get_temp(data, val, !iio_buffer_enabled(indio_dev));
if (ret)
return ret;
- ret = IIO_VAL_INT;
- break;
+ return IIO_VAL_INT;
+ }
case IIO_CHAN_INFO_SCALE:
*val = 1000; /* 62.5 */
*val2 = 16;
- ret = IIO_VAL_FRACTIONAL;
- break;
+ return IIO_VAL_FRACTIONAL;
+ default:
+ return -EINVAL;
}
-
- return ret;
}
static const struct iio_info max30102_info = {
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 7/7] iio: light: opt4060: Use IIO cleanup helpers
2025-12-12 2:45 [PATCH v2 0/7] iio: core: Introduce cleanup.h support for mode locks Kurt Borja
` (5 preceding siblings ...)
2025-12-12 2:45 ` [PATCH v2 6/7] iio: health: max30102: " Kurt Borja
@ 2025-12-12 2:45 ` Kurt Borja
6 siblings, 0 replies; 11+ messages in thread
From: Kurt Borja @ 2025-12-12 2:45 UTC (permalink / raw)
To: Andy Shevchenko, Lars-Peter Clausen, Michael Hennerich,
Jonathan Cameron, Benson Leung, Antoniu Miclaus, Gwendal Grignou,
Shrikant Raskar, Per-Daniel Olsson
Cc: David Lechner, Nuno Sá, Andy Shevchenko, Guenter Roeck,
Jonathan Cameron, linux-iio, linux-kernel, chrome-platform,
Kurt Borja
Use IIO_DEV_GUARD_ANY_MODE() cleanup helper to simplify and drop
busy-waiting code in opt4060_set_driver_state().
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/iio/light/opt4060.c | 52 +++++++++++++++------------------------------
1 file changed, 17 insertions(+), 35 deletions(-)
diff --git a/drivers/iio/light/opt4060.c b/drivers/iio/light/opt4060.c
index 8cb3fa38077e..943e5963d568 100644
--- a/drivers/iio/light/opt4060.c
+++ b/drivers/iio/light/opt4060.c
@@ -302,41 +302,23 @@ static int opt4060_set_driver_state(struct iio_dev *indio_dev,
bool continuous_irq)
{
struct opt4060_chip *chip = iio_priv(indio_dev);
- int ret = 0;
-any_mode_retry:
- if (!iio_device_claim_buffer_mode(indio_dev)) {
- /*
- * This one is a *bit* hacky. If we cannot claim buffer mode,
- * then try direct mode so that we make sure things cannot
- * concurrently change. And we just keep trying until we get one
- * of the modes...
- */
- if (!iio_device_claim_direct(indio_dev))
- goto any_mode_retry;
- /*
- * This path means that we managed to claim direct mode. In
- * this case the buffer isn't enabled and it's okay to leave
- * continuous mode for sampling and/or irq.
- */
- ret = opt4060_set_state_common(chip, continuous_sampling,
- continuous_irq);
- iio_device_release_direct(indio_dev);
- return ret;
- } else {
- /*
- * This path means that we managed to claim buffer mode. In
- * this case the buffer is enabled and irq and sampling must go
- * to or remain continuous, but only if the trigger is from this
- * device.
- */
- if (!iio_trigger_validate_own_device(indio_dev->trig, indio_dev))
- ret = opt4060_set_state_common(chip, true, true);
- else
- ret = opt4060_set_state_common(chip, continuous_sampling,
- continuous_irq);
- iio_device_release_buffer_mode(indio_dev);
- }
- return ret;
+
+ IIO_DEV_GUARD_ANY_MODE(indio_dev);
+
+ /*
+ * If we manage to claim buffer mode and we are using our own trigger,
+ * IRQ and sampling must go to or remain continuous.
+ */
+ if (iio_buffer_enabled(indio_dev) &&
+ iio_trigger_validate_own_device(indio_dev->trig, indio_dev))
+ return opt4060_set_state_common(chip, true, true);
+
+ /*
+ * This path means that we managed to claim direct mode. In this case
+ * the buffer isn't enabled and it's okay to leave continuous mode for
+ * sampling and/or irq.
+ */
+ return opt4060_set_state_common(chip, continuous_sampling, continuous_irq);
}
/*
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread