* [PATCH v8 00/12] iio: ssp_sensors: driver fixes, refactor and cleanup
@ 2026-05-15 17:40 Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 01/12] iio: ssp_sensors: cancel delayed work_refresh on remove Sanjay Chitroda
` (11 more replies)
0 siblings, 12 replies; 13+ messages in thread
From: Sanjay Chitroda @ 2026-05-15 17:40 UTC (permalink / raw)
To: jic23
Cc: dlechner, nuno.sa, andy, sanjayembeddedse, tglx,
christophe.jaillet, mingo, kees, nabijaczleweli, kyungmin.park,
linux-iio, linux-kernel
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Hi all,
This patch series improves resource cleanup and error handling in the
SSP IIO SPI driver by adopting the recently introduced cleanup
helpers.
The changes focus on making probe/remove paths more robust and easier
to reason about by reducing manual unwind logic and ensuring that locks
and dynamically allocated resources are released consistently across
all exit paths.
Key highlights of this series:
- Reuse embedded rx buffer for SPI transfer instead of allocating new
DMA memory in interrupt context for write transaction between AP <-> HUB.
- Replace dynamic resource lifetime management with device‑managed
(devm_) APIs to simplify cleanup and error paths.
- Refactor common helper API, improving readability and reducing
duplicatation.
- Address minor codestyle warnings and use dev_err_probe in probe path.
Changes in v8:
- 0001 has been added fixes-togreg howerver keep this to have baseline
changes for next patches in series
- new 0003 -> refactor transfer logic
- new 0006 -> fix variable type and declration as per review comment
- new 0009 -> use guard() resource management API
- new 0011 -> use return in all legs of function to symmetry
- v7 series -> https://lore.kernel.org/all/20260426091710.3722035-1-sanjayembedded@gmail.com/
Changes in v7:
- first 2 checkpatch patches are applied to iio/testing
- address coding type review comment from Andy at multiple places
- add warning fix in ssp_dev driver
- add new change to cancel refresh work
- add helper API for enable/disable MCU
- Following input from Andy add local variable dev to use with APIs
- v6 series: https://lore.kernel.org/all/20260415050749.3858046-1-sanjayembedded@gmail.com/
Changes in v6:
- 0005: Drop remove() path using devm action with input from David
- 0007: Replace dynamic memory allocation with embedded fixed size struct buffer
- 0004: new: drop duplication in remove()
- 0006: new: Use dev_err_probe in driver probe()
- v5 series: https://lore.kernel.org/all/20260406080852.2727453-1-sanjayembedded@gmail.com/
Changes in v5:
- Drop usage of guard() helpers to avoid mixing mutex_lock() with
guard()(), based on reviewer feedback.
- 0003: Refactor shared helper API, reducing duplication.
- 0004: Convert resource allocation and teardown to devm_ managed APIs to
simplify error handling and probe/remove paths.
- v4 series: https://lore.kernel.org/all/20260326081815.925373-1-sanjayembedded@gmail.com/
Changes in v4:
- Update sequence and make checkpatch style fix in base change
- Split WARNING and CHECK change with input of Andy as 0001 and 0002
- 0003: Use guard() instead of scoped_guard()
- 0004: Use preallocated buffer to stash memory allocation
- v3 series: https://lore.kernel.org/all/20260315125509.857195-1-sanjayembedded@gmail.com/
No functional behavior changes are intended.
Testing:
- Compiled with W=1
- Build-tested on QEMU x86_64
Feedback and reviews are very welcome.
Thanks,
Sanjay Chitroda
Sanjay Chitroda (12):
iio: ssp_sensors: cancel delayed work_refresh on remove
iio: ssp_sensors: factor out pending list add/remove helpers
iio: ssp_sensors: refactor transfer logic into helper
iio: ssp_sensors: factor out MCU enable/disable helpers
iio: ssp_sensors: use local struct device
iio: ssp_sensors: fix variable type and declaration order in probe()
iio: ssp_sensors: Drop duplicated wdt timer and work cleanup
iio: ssp_sensors: convert probe and teardown to devm-managed resources
iio: ssp_sensors: use guard() to release mutexes
iio: ssp_sensors: Use dev_err_probe()
iio: ssp_sensors: return errors directly from ssp_irq_msg()
iio: ssp_sensors: reuse embedded RX buffer for SPI transfers
drivers/iio/common/ssp_sensors/ssp.h | 3 +
drivers/iio/common/ssp_sensors/ssp_dev.c | 191 ++++++++++++-----------
drivers/iio/common/ssp_sensors/ssp_spi.c | 146 ++++++++---------
3 files changed, 178 insertions(+), 162 deletions(-)
base-commit: 1548c54e9adc32a719499216f63fba14b2fc07c3
--
2.34.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v8 01/12] iio: ssp_sensors: cancel delayed work_refresh on remove
2026-05-15 17:40 [PATCH v8 00/12] iio: ssp_sensors: driver fixes, refactor and cleanup Sanjay Chitroda
@ 2026-05-15 17:40 ` Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 02/12] iio: ssp_sensors: factor out pending list add/remove helpers Sanjay Chitroda
` (10 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sanjay Chitroda @ 2026-05-15 17:40 UTC (permalink / raw)
To: jic23
Cc: dlechner, nuno.sa, andy, sanjayembeddedse, tglx,
christophe.jaillet, mingo, kees, nabijaczleweli, kyungmin.park,
linux-iio, linux-kernel
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
The work_refresh may still be pending or running when the device is
removed, cancel the delayed work_refresh in remove path.
Fixes: 50dd64d57eee ("iio: common: ssp_sensors: Add sensorhub driver")
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
drivers/iio/common/ssp_sensors/ssp_dev.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c
index 7d07fae295fd..51730dae5871 100644
--- a/drivers/iio/common/ssp_sensors/ssp_dev.c
+++ b/drivers/iio/common/ssp_sensors/ssp_dev.c
@@ -590,6 +590,7 @@ static void ssp_remove(struct spi_device *spi)
ssp_clean_pending_list(data);
free_irq(data->spi->irq, data);
+ cancel_delayed_work_sync(&data->work_refresh);
timer_delete_sync(&data->wdt_timer);
cancel_work_sync(&data->work_wdt);
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v8 02/12] iio: ssp_sensors: factor out pending list add/remove helpers
2026-05-15 17:40 [PATCH v8 00/12] iio: ssp_sensors: driver fixes, refactor and cleanup Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 01/12] iio: ssp_sensors: cancel delayed work_refresh on remove Sanjay Chitroda
@ 2026-05-15 17:40 ` Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 03/12] iio: ssp_sensors: refactor transfer logic into helper Sanjay Chitroda
` (9 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sanjay Chitroda @ 2026-05-15 17:40 UTC (permalink / raw)
To: jic23
Cc: dlechner, nuno.sa, andy, sanjayembeddedse, tglx,
christophe.jaillet, mingo, kees, nabijaczleweli, kyungmin.park,
linux-iio, linux-kernel
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
The SSP SPI transfer path manipulates the pending message list in
multiple places, open-coding the same locking and list operations.
Refactor the pending list add and remove logic into helper functions.
This reduces duplication and simplifies the transfer flow by
centralizing the pending list handling.
No functional change intended.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Suggested-by: Andy Shevchenko <andriy.shevchenko@intel.com>
---
Changes in v8:
- Following discussion with Andy and Jonathan, handle the flag
and have preparatory changes for subfunction help of critical section
- v7 change: https://lore.kernel.org/all/20260426091710.3722035-3-sanjayembedded@gmail.com/
Changes in v7:
- Following suggestion from Andy, keep helper API definition in single
line and re-place the comment section
- v6 change: https://lore.kernel.org/all/20260415050749.3858046-4-sanjayembedded@gmail.com/
Changes in v6:
- Include tag for the suggestion of helper functions
- Drop completely use_no_irq variable with review comment from Andy
- v5 change: https://lore.kernel.org/all/20260406080852.2727453-4-sanjayembedded@gmail.com/
---
drivers/iio/common/ssp_sensors/ssp_spi.c | 50 ++++++++++++++----------
1 file changed, 30 insertions(+), 20 deletions(-)
diff --git a/drivers/iio/common/ssp_sensors/ssp_spi.c b/drivers/iio/common/ssp_sensors/ssp_spi.c
index 08ed92859be0..3d377a482161 100644
--- a/drivers/iio/common/ssp_sensors/ssp_spi.c
+++ b/drivers/iio/common/ssp_sensors/ssp_spi.c
@@ -174,6 +174,28 @@ static int ssp_check_lines(struct ssp_data *data, bool state)
return 0;
}
+static inline void ssp_pending_add(struct ssp_data *data, struct ssp_msg *msg,
+ bool no_irq)
+{
+ if (no_irq)
+ return;
+
+ mutex_lock(&data->pending_lock);
+ list_add_tail(&msg->list, &data->pending_list);
+ mutex_unlock(&data->pending_lock);
+}
+
+static inline void ssp_pending_del(struct ssp_data *data, struct ssp_msg *msg,
+ bool no_irq)
+{
+ if (no_irq)
+ return;
+
+ mutex_lock(&data->pending_lock);
+ list_del(&msg->list);
+ mutex_unlock(&data->pending_lock);
+}
+
static int ssp_do_transfer(struct ssp_data *data, struct ssp_msg *msg,
struct completion *done, int timeout)
{
@@ -202,35 +224,23 @@ static int ssp_do_transfer(struct ssp_data *data, struct ssp_msg *msg,
goto _error_locked;
}
- if (!use_no_irq) {
- mutex_lock(&data->pending_lock);
- list_add_tail(&msg->list, &data->pending_list);
- mutex_unlock(&data->pending_lock);
- }
+ ssp_pending_add(data, msg, use_no_irq);
status = ssp_check_lines(data, true);
if (status < 0) {
- if (!use_no_irq) {
- mutex_lock(&data->pending_lock);
- list_del(&msg->list);
- mutex_unlock(&data->pending_lock);
- }
+ ssp_pending_del(data, msg, use_no_irq);
goto _error_locked;
}
mutex_unlock(&data->comm_lock);
- if (!use_no_irq && done)
- if (wait_for_completion_timeout(done,
- msecs_to_jiffies(timeout)) ==
- 0) {
- mutex_lock(&data->pending_lock);
- list_del(&msg->list);
- mutex_unlock(&data->pending_lock);
+ if (!use_no_irq && done &&
+ !wait_for_completion_timeout(done, msecs_to_jiffies(timeout))) {
+ ssp_pending_del(data, msg, use_no_irq);
- data->timeout_cnt++;
- return -ETIMEDOUT;
- }
+ data->timeout_cnt++;
+ return -ETIMEDOUT;
+ }
return 0;
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v8 03/12] iio: ssp_sensors: refactor transfer logic into helper
2026-05-15 17:40 [PATCH v8 00/12] iio: ssp_sensors: driver fixes, refactor and cleanup Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 01/12] iio: ssp_sensors: cancel delayed work_refresh on remove Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 02/12] iio: ssp_sensors: factor out pending list add/remove helpers Sanjay Chitroda
@ 2026-05-15 17:40 ` Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 04/12] iio: ssp_sensors: factor out MCU enable/disable helpers Sanjay Chitroda
` (8 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sanjay Chitroda @ 2026-05-15 17:40 UTC (permalink / raw)
To: jic23
Cc: dlechner, nuno.sa, andy, sanjayembeddedse, tglx,
christophe.jaillet, mingo, kees, nabijaczleweli, kyungmin.park,
linux-iio, linux-kernel
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Extract the core transfer logic under comm_lock into a new
__ssp_do_transfer() helper. The change is preparatory for converting
mutex usage to guard() helpers in subsequent patches.
This restructuring simplifies ssp_do_transfer() and makes the
transfer flow easier to follow.
No functional change intended.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
drivers/iio/common/ssp_sensors/ssp_spi.c | 50 +++++++++++++++---------
1 file changed, 32 insertions(+), 18 deletions(-)
diff --git a/drivers/iio/common/ssp_sensors/ssp_spi.c b/drivers/iio/common/ssp_sensors/ssp_spi.c
index 3d377a482161..ebcda6de56c4 100644
--- a/drivers/iio/common/ssp_sensors/ssp_spi.c
+++ b/drivers/iio/common/ssp_sensors/ssp_spi.c
@@ -196,20 +196,13 @@ static inline void ssp_pending_del(struct ssp_data *data, struct ssp_msg *msg,
mutex_unlock(&data->pending_lock);
}
-static int ssp_do_transfer(struct ssp_data *data, struct ssp_msg *msg,
- struct completion *done, int timeout)
+static int __ssp_do_transfer(struct ssp_data *data, struct ssp_msg *msg,
+ bool no_irq)
{
int status;
- /*
- * check if this is a short one way message or the whole transfer has
- * second part after an interrupt
- */
- const bool use_no_irq = msg->length == 0;
- if (data->shut_down)
- return -EPERM;
-
- msg->done = done;
+ /* msg->done must be initialized by caller */
+ WARN_ON(!msg->done);
mutex_lock(&data->comm_lock);
@@ -224,15 +217,41 @@ static int ssp_do_transfer(struct ssp_data *data, struct ssp_msg *msg,
goto _error_locked;
}
- ssp_pending_add(data, msg, use_no_irq);
+ ssp_pending_add(data, msg, no_irq);
status = ssp_check_lines(data, true);
if (status < 0) {
- ssp_pending_del(data, msg, use_no_irq);
+ ssp_pending_del(data, msg, no_irq);
goto _error_locked;
}
mutex_unlock(&data->comm_lock);
+ return 0;
+
+_error_locked:
+ mutex_unlock(&data->comm_lock);
+ data->timeout_cnt++;
+ return status;
+}
+
+static int ssp_do_transfer(struct ssp_data *data, struct ssp_msg *msg,
+ struct completion *done, int timeout)
+{
+ int status;
+ /*
+ * check if this is a short one way message or the whole transfer has
+ * second part after an interrupt
+ */
+ const bool use_no_irq = msg->length == 0;
+
+ if (data->shut_down)
+ return -EPERM;
+
+ msg->done = done;
+
+ status = __ssp_do_transfer(data, msg, use_no_irq);
+ if (status < 0)
+ return status;
if (!use_no_irq && done &&
!wait_for_completion_timeout(done, msecs_to_jiffies(timeout))) {
@@ -243,11 +262,6 @@ static int ssp_do_transfer(struct ssp_data *data, struct ssp_msg *msg,
}
return 0;
-
-_error_locked:
- mutex_unlock(&data->comm_lock);
- data->timeout_cnt++;
- return status;
}
static inline int ssp_spi_sync_command(struct ssp_data *data,
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v8 04/12] iio: ssp_sensors: factor out MCU enable/disable helpers
2026-05-15 17:40 [PATCH v8 00/12] iio: ssp_sensors: driver fixes, refactor and cleanup Sanjay Chitroda
` (2 preceding siblings ...)
2026-05-15 17:40 ` [PATCH v8 03/12] iio: ssp_sensors: refactor transfer logic into helper Sanjay Chitroda
@ 2026-05-15 17:40 ` Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 05/12] iio: ssp_sensors: use local struct device Sanjay Chitroda
` (7 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sanjay Chitroda @ 2026-05-15 17:40 UTC (permalink / raw)
To: jic23
Cc: dlechner, nuno.sa, andy, sanjayembeddedse, tglx,
christophe.jaillet, mingo, kees, nabijaczleweli, kyungmin.park,
linux-iio, linux-kernel
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Refactor the MCU enable and disable logic into small helper functions.
This simplifies the control flow and improves readability.
No functional change intended.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
Changes in v8:
- Following comment from Jonathan, split function to have separate
changes for each small helper function and demote the log level
- v7 change: https://lore.kernel.org/all/20260426091710.3722035-5-sanjayembedded@gmail.com/
---
drivers/iio/common/ssp_sensors/ssp_dev.c | 43 +++++++++++++-----------
1 file changed, 24 insertions(+), 19 deletions(-)
diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c
index 51730dae5871..4280eb590c03 100644
--- a/drivers/iio/common/ssp_sensors/ssp_dev.c
+++ b/drivers/iio/common/ssp_sensors/ssp_dev.c
@@ -89,23 +89,28 @@ static void ssp_sync_available_sensors(struct ssp_data *data)
"SSP_MSG2SSP_AP_MCU_SET_DUMPMODE failed\n");
}
-static void ssp_enable_mcu(struct ssp_data *data, bool enable)
+static void ssp_enable_mcu(struct ssp_data *data)
{
- dev_info(&data->spi->dev, "current shutdown = %d, old = %d\n", enable,
- data->shut_down);
-
- if (enable && data->shut_down) {
- data->shut_down = false;
- enable_irq(data->spi->irq);
- enable_irq_wake(data->spi->irq);
- } else if (!enable && !data->shut_down) {
- data->shut_down = true;
- disable_irq(data->spi->irq);
- disable_irq_wake(data->spi->irq);
- } else {
- dev_warn(&data->spi->dev, "current shutdown = %d, old = %d\n",
- enable, data->shut_down);
- }
+ dev_dbg(&data->spi->dev, "enabling MCU (was shutdown: %d)\n", data->shut_down);
+
+ if (!data->shut_down)
+ return;
+
+ data->shut_down = false;
+ enable_irq(data->spi->irq);
+ enable_irq_wake(data->spi->irq);
+}
+
+static void ssp_disable_mcu(struct ssp_data *data)
+{
+ dev_dbg(&data->spi->dev, "disabling MCU (was shutdown: %d)\n", data->shut_down);
+
+ if (data->shut_down)
+ return;
+
+ data->shut_down = true;
+ disable_irq(data->spi->irq);
+ disable_irq_wake(data->spi->irq);
}
/*
@@ -146,10 +151,10 @@ static int ssp_check_fwbl(struct ssp_data *data)
static void ssp_reset_mcu(struct ssp_data *data)
{
- ssp_enable_mcu(data, false);
+ ssp_disable_mcu(data);
ssp_clean_pending_list(data);
ssp_toggle_mcu_reset_gpio(data);
- ssp_enable_mcu(data, true);
+ ssp_enable_mcu(data);
}
static void ssp_wdt_work_func(struct work_struct *work)
@@ -584,7 +589,7 @@ static void ssp_remove(struct spi_device *spi)
dev_err(&data->spi->dev,
"SSP_MSG2SSP_AP_STATUS_SHUTDOWN failed\n");
- ssp_enable_mcu(data, false);
+ ssp_disable_mcu(data);
ssp_disable_wdt_timer(data);
ssp_clean_pending_list(data);
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v8 05/12] iio: ssp_sensors: use local struct device
2026-05-15 17:40 [PATCH v8 00/12] iio: ssp_sensors: driver fixes, refactor and cleanup Sanjay Chitroda
` (3 preceding siblings ...)
2026-05-15 17:40 ` [PATCH v8 04/12] iio: ssp_sensors: factor out MCU enable/disable helpers Sanjay Chitroda
@ 2026-05-15 17:40 ` Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 06/12] iio: ssp_sensors: fix variable type and declaration order in probe() Sanjay Chitroda
` (6 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sanjay Chitroda @ 2026-05-15 17:40 UTC (permalink / raw)
To: jic23
Cc: dlechner, nuno.sa, andy, sanjayembeddedse, tglx,
christophe.jaillet, mingo, kees, nabijaczleweli, kyungmin.park,
linux-iio, linux-kernel
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Introduce a struct device *dev derived from &spi->dev to improve
readability and drop redundant "Probe failed!" log in probe path.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
Changes in v8:
- Following input from Andy and Jonathan don't mix variable reorder
with new variable addition and drop redundant log
- v7 change: https://lore.kernel.org/all/20260426091710.3722035-6-sanjayembedded@gmail.com/
---
drivers/iio/common/ssp_sensors/ssp_dev.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c
index 4280eb590c03..a652bb56c61f 100644
--- a/drivers/iio/common/ssp_sensors/ssp_dev.c
+++ b/drivers/iio/common/ssp_sensors/ssp_dev.c
@@ -487,27 +487,28 @@ EXPORT_SYMBOL_NS(ssp_register_consumer, "IIO_SSP_SENSORS");
static int ssp_probe(struct spi_device *spi)
{
+ struct device *dev = &spi->dev;
int ret, i;
struct ssp_data *data;
- data = ssp_parse_dt(&spi->dev);
+ data = ssp_parse_dt(dev);
if (!data) {
- dev_err(&spi->dev, "Failed to find platform data\n");
+ dev_err(dev, "Failed to find platform data\n");
return -ENODEV;
}
- ret = mfd_add_devices(&spi->dev, PLATFORM_DEVID_NONE,
+ ret = mfd_add_devices(dev, PLATFORM_DEVID_NONE,
sensorhub_sensor_devs,
ARRAY_SIZE(sensorhub_sensor_devs), NULL, 0, NULL);
if (ret < 0) {
- dev_err(&spi->dev, "mfd add devices fail\n");
+ dev_err(dev, "mfd add devices fail\n");
return ret;
}
spi->mode = SPI_MODE_1;
ret = spi_setup(spi);
if (ret < 0) {
- dev_err(&spi->dev, "Failed to setup spi\n");
+ dev_err(dev, "Failed to setup spi\n");
goto err_setup_spi;
}
@@ -543,7 +544,7 @@ static int ssp_probe(struct spi_device *spi)
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"SSP_Int", data);
if (ret < 0) {
- dev_err(&spi->dev, "Irq request fail\n");
+ dev_err(dev, "Irq request fail\n");
goto err_setup_irq;
}
@@ -557,11 +558,11 @@ static int ssp_probe(struct spi_device *spi)
if (data->fw_dl_state == SSP_FW_DL_STATE_NONE) {
ret = ssp_initialize_mcu(data);
if (ret < 0) {
- dev_err(&spi->dev, "Initialize_mcu failed\n");
+ dev_err(dev, "Initialize_mcu failed\n");
goto err_read_reg;
}
} else {
- dev_err(&spi->dev, "Firmware version not supported\n");
+ dev_err(dev, "Firmware version not supported\n");
ret = -EPERM;
goto err_read_reg;
}
@@ -574,9 +575,7 @@ static int ssp_probe(struct spi_device *spi)
mutex_destroy(&data->pending_lock);
mutex_destroy(&data->comm_lock);
err_setup_spi:
- mfd_remove_devices(&spi->dev);
-
- dev_err(&spi->dev, "Probe failed!\n");
+ mfd_remove_devices(dev);
return ret;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v8 06/12] iio: ssp_sensors: fix variable type and declaration order in probe()
2026-05-15 17:40 [PATCH v8 00/12] iio: ssp_sensors: driver fixes, refactor and cleanup Sanjay Chitroda
` (4 preceding siblings ...)
2026-05-15 17:40 ` [PATCH v8 05/12] iio: ssp_sensors: use local struct device Sanjay Chitroda
@ 2026-05-15 17:40 ` Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 07/12] iio: ssp_sensors: Drop duplicated wdt timer and work cleanup Sanjay Chitroda
` (5 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sanjay Chitroda @ 2026-05-15 17:40 UTC (permalink / raw)
To: jic23
Cc: dlechner, nuno.sa, andy, sanjayembeddedse, tglx,
christophe.jaillet, mingo, kees, nabijaczleweli, kyungmin.park,
linux-iio, linux-kernel
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
The ssp_probe() function declares both loop index and return code
in a single statement. The loop index is unsigned and split declarations
to follow common kernel coding style.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
drivers/iio/common/ssp_sensors/ssp_dev.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c
index a652bb56c61f..f3ad2b38cc12 100644
--- a/drivers/iio/common/ssp_sensors/ssp_dev.c
+++ b/drivers/iio/common/ssp_sensors/ssp_dev.c
@@ -488,8 +488,9 @@ EXPORT_SYMBOL_NS(ssp_register_consumer, "IIO_SSP_SENSORS");
static int ssp_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
- int ret, i;
struct ssp_data *data;
+ unsigned int i;
+ int ret;
data = ssp_parse_dt(dev);
if (!data) {
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v8 07/12] iio: ssp_sensors: Drop duplicated wdt timer and work cleanup
2026-05-15 17:40 [PATCH v8 00/12] iio: ssp_sensors: driver fixes, refactor and cleanup Sanjay Chitroda
` (5 preceding siblings ...)
2026-05-15 17:40 ` [PATCH v8 06/12] iio: ssp_sensors: fix variable type and declaration order in probe() Sanjay Chitroda
@ 2026-05-15 17:40 ` Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 08/12] iio: ssp_sensors: convert probe and teardown to devm-managed resources Sanjay Chitroda
` (4 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sanjay Chitroda @ 2026-05-15 17:40 UTC (permalink / raw)
To: jic23
Cc: dlechner, nuno.sa, andy, sanjayembeddedse, tglx,
christophe.jaillet, mingo, kees, nabijaczleweli, kyungmin.park,
linux-iio, linux-kernel
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
The SSP remove path cleans up the watchdog timer and associated work
both via ssp_disable_wdt_timer() and through explicit timer and work
teardown.
ssp_disable_wdt_timer() already performs a synchronous teardown of the
watchdog timer and watchdog work, guaranteeing that no timer callbacks
or watchdog work can be running or requeued once it returns.
In addition, the remove path disables interrupts and frees IRQ handler
using ssp_disable_mcu() and free_irq(). The refresh work is also
cancelled, preventing wdt_timer being re-armed before teardown. This
ensures that no new refresh or watchdog activity can be triggered from
the IRQ thread and refresh workqueue.
Calling ssp_disable_wdt_timer() after IRQ teardown is safe, as the
watchdog disable helper does not depend on interrupt delivery and
ensures all watchdog activity is fully synchronized before returning.
As a result, the additional timer and work cancellation is redundant
and does not provide additional ordering or race protection. Remove the
duplicated cleanup and rely on the centralized watchdog disable helper.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
Changes in v8:
- Add more information about wdt shifted to specific location and
address comment from Andy
- v7 change: https://lore.kernel.org/all/20260426091710.3722035-7-sanjayembedded@gmail.com/
Changes in v7:
- Following comment from Andy, Study the timer, work and IRQ
relationship and how it would work internally for ssp_sensors and
changes looks correct; updated the commit message to explain the
race condition and information on resource release during teardown.
- v6 change: https://lore.kernel.org/all/20260415050749.3858046-5-sanjayembedded@gmail.com/
---
drivers/iio/common/ssp_sensors/ssp_dev.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c
index f3ad2b38cc12..88bb8ab0cd9b 100644
--- a/drivers/iio/common/ssp_sensors/ssp_dev.c
+++ b/drivers/iio/common/ssp_sensors/ssp_dev.c
@@ -590,15 +590,12 @@ static void ssp_remove(struct spi_device *spi)
"SSP_MSG2SSP_AP_STATUS_SHUTDOWN failed\n");
ssp_disable_mcu(data);
- ssp_disable_wdt_timer(data);
-
ssp_clean_pending_list(data);
free_irq(data->spi->irq, data);
cancel_delayed_work_sync(&data->work_refresh);
- timer_delete_sync(&data->wdt_timer);
- cancel_work_sync(&data->work_wdt);
+ ssp_disable_wdt_timer(data);
mutex_destroy(&data->comm_lock);
mutex_destroy(&data->pending_lock);
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v8 08/12] iio: ssp_sensors: convert probe and teardown to devm-managed resources
2026-05-15 17:40 [PATCH v8 00/12] iio: ssp_sensors: driver fixes, refactor and cleanup Sanjay Chitroda
` (6 preceding siblings ...)
2026-05-15 17:40 ` [PATCH v8 07/12] iio: ssp_sensors: Drop duplicated wdt timer and work cleanup Sanjay Chitroda
@ 2026-05-15 17:40 ` Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 09/12] iio: ssp_sensors: use guard() to release mutexes Sanjay Chitroda
` (3 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sanjay Chitroda @ 2026-05-15 17:40 UTC (permalink / raw)
To: jic23
Cc: dlechner, nuno.sa, andy, sanjayembeddedse, tglx,
christophe.jaillet, mingo, kees, nabijaczleweli, kyungmin.park,
linux-iio, linux-kernel
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Convert SSP driver resource management to use devm-managed helpers
and devm actions, tying the lifetime of all resources to the device.
Mutex initialization, IRQ registration, work items, timers, and MFD
resource are now managed using devm APIs. Cleanup logic previously
handled explicitly in probe error paths and the remove callback is
replaced with devm_add_action_or_reset(), ensuring correct teardown
ordering and consistent behaviour on probe failure and device unbind.
This simplifies the probe path by removing goto-based error handling,
eliminates the remove callback entirely.
No functional change intended.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
drivers/iio/common/ssp_sensors/ssp_dev.c | 114 +++++++++++++----------
1 file changed, 64 insertions(+), 50 deletions(-)
diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c
index 88bb8ab0cd9b..441416c612a4 100644
--- a/drivers/iio/common/ssp_sensors/ssp_dev.c
+++ b/drivers/iio/common/ssp_sensors/ssp_dev.c
@@ -199,6 +199,26 @@ static void ssp_disable_wdt_timer(struct ssp_data *data)
cancel_work_sync(&data->work_wdt);
}
+static void ssp_disable_work_timer(void *ptr)
+{
+ struct ssp_data *data = ptr;
+
+ cancel_delayed_work_sync(&data->work_refresh);
+ ssp_disable_wdt_timer(data);
+}
+
+static void ssp_shutdown_action(void *ptr)
+{
+ struct ssp_data *data = ptr;
+
+ if (ssp_command(data, SSP_MSG2SSP_AP_STATUS_SHUTDOWN, 0) < 0)
+ dev_err(&data->spi->dev,
+ "SSP_MSG2SSP_AP_STATUS_SHUTDOWN failed\n");
+
+ ssp_disable_mcu(data);
+ ssp_clean_pending_list(data);
+}
+
/**
* ssp_get_sensor_delay() - gets sensor data acquisition period
* @data: sensorhub structure
@@ -498,9 +518,8 @@ static int ssp_probe(struct spi_device *spi)
return -ENODEV;
}
- ret = mfd_add_devices(dev, PLATFORM_DEVID_NONE,
- sensorhub_sensor_devs,
- ARRAY_SIZE(sensorhub_sensor_devs), NULL, 0, NULL);
+ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, sensorhub_sensor_devs,
+ ARRAY_SIZE(sensorhub_sensor_devs), NULL, 0, NULL);
if (ret < 0) {
dev_err(dev, "mfd add devices fail\n");
return ret;
@@ -510,14 +529,16 @@ static int ssp_probe(struct spi_device *spi)
ret = spi_setup(spi);
if (ret < 0) {
dev_err(dev, "Failed to setup spi\n");
- goto err_setup_spi;
+ return ret;
}
data->fw_dl_state = SSP_FW_DL_STATE_NONE;
data->spi = spi;
spi_set_drvdata(spi, data);
- mutex_init(&data->comm_lock);
+ ret = devm_mutex_init(dev, &data->comm_lock);
+ if (ret < 0)
+ return ret;
for (i = 0; i < SSP_SENSOR_MAX; ++i) {
data->delay_buf[i] = SSP_DEFAULT_POLLING_DELAY;
@@ -530,7 +551,9 @@ static int ssp_probe(struct spi_device *spi)
data->time_syncing = true;
- mutex_init(&data->pending_lock);
+ ret = devm_mutex_init(dev, &data->pending_lock);
+ if (ret < 0)
+ return ret;
INIT_LIST_HEAD(&data->pending_list);
atomic_set(&data->enable_refcount, 0);
@@ -540,14 +563,23 @@ static int ssp_probe(struct spi_device *spi)
timer_setup(&data->wdt_timer, ssp_wdt_timer_func, 0);
- ret = request_threaded_irq(data->spi->irq, NULL,
- ssp_irq_thread_fn,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- "SSP_Int", data);
- if (ret < 0) {
- dev_err(dev, "Irq request fail\n");
- goto err_setup_irq;
- }
+ /*
+ * Register deferred callback which disable timer and work after
+ * module unloaded.
+ *
+ * driver should cancel delayed refresh work, watchdog work and delete
+ * watchdog timer once interrupt is disabled and IRQ is freed.
+ */
+ ret = devm_add_action_or_reset(dev, ssp_disable_work_timer, data);
+ if (ret < 0)
+ return ret;
+
+ ret = devm_request_threaded_irq(dev, data->spi->irq, NULL,
+ ssp_irq_thread_fn,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "SSP_Int", data);
+ if (ret < 0)
+ return ret;
/* Let's start with enabled one so irq balance could be ok */
data->shut_down = false;
@@ -560,47 +592,30 @@ static int ssp_probe(struct spi_device *spi)
ret = ssp_initialize_mcu(data);
if (ret < 0) {
dev_err(dev, "Initialize_mcu failed\n");
- goto err_read_reg;
+ return ret;
}
} else {
dev_err(dev, "Firmware version not supported\n");
- ret = -EPERM;
- goto err_read_reg;
+ return -EPERM;
}
- return 0;
-
-err_read_reg:
- free_irq(data->spi->irq, data);
-err_setup_irq:
- mutex_destroy(&data->pending_lock);
- mutex_destroy(&data->comm_lock);
-err_setup_spi:
- mfd_remove_devices(dev);
-
- return ret;
-}
-
-static void ssp_remove(struct spi_device *spi)
-{
- struct ssp_data *data = spi_get_drvdata(spi);
-
- if (ssp_command(data, SSP_MSG2SSP_AP_STATUS_SHUTDOWN, 0) < 0)
- dev_err(&data->spi->dev,
- "SSP_MSG2SSP_AP_STATUS_SHUTDOWN failed\n");
-
- ssp_disable_mcu(data);
- ssp_clean_pending_list(data);
-
- free_irq(data->spi->irq, data);
- cancel_delayed_work_sync(&data->work_refresh);
-
- ssp_disable_wdt_timer(data);
-
- mutex_destroy(&data->comm_lock);
- mutex_destroy(&data->pending_lock);
+ /*
+ * Managed shutdown action for the SSP device lifecycle.
+ *
+ * This action unwinds state by:
+ * - notifying the SSP firmware of AP shutdown,
+ * - disabling the MCU to prevent further IRQ activity,
+ * - cleaning up any pending command state.
+ *
+ * The action is registered once the MCU has been initialized so that
+ * both driver removal and probe failure after this point leave the
+ * device in a quiescent state.
+ */
+ ret = devm_add_action_or_reset(dev, ssp_shutdown_action, data);
+ if (ret < 0)
+ return ret;
- mfd_remove_devices(&spi->dev);
+ return 0;
}
static int ssp_suspend(struct device *dev)
@@ -656,7 +671,6 @@ static DEFINE_SIMPLE_DEV_PM_OPS(ssp_pm_ops, ssp_suspend, ssp_resume);
static struct spi_driver ssp_driver = {
.probe = ssp_probe,
- .remove = ssp_remove,
.driver = {
.pm = pm_sleep_ptr(&ssp_pm_ops),
.of_match_table = ssp_of_match,
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v8 09/12] iio: ssp_sensors: use guard() to release mutexes
2026-05-15 17:40 [PATCH v8 00/12] iio: ssp_sensors: driver fixes, refactor and cleanup Sanjay Chitroda
` (7 preceding siblings ...)
2026-05-15 17:40 ` [PATCH v8 08/12] iio: ssp_sensors: convert probe and teardown to devm-managed resources Sanjay Chitroda
@ 2026-05-15 17:40 ` Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 10/12] iio: ssp_sensors: Use dev_err_probe() Sanjay Chitroda
` (2 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Sanjay Chitroda @ 2026-05-15 17:40 UTC (permalink / raw)
To: jic23
Cc: dlechner, nuno.sa, andy, sanjayembeddedse, tglx,
christophe.jaillet, mingo, kees, nabijaczleweli, kyungmin.park,
linux-iio, linux-kernel
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Replace explicit mutex_lock() and mutex_unlock() with the guard() macro
for cleaner and safer mutex handling.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
drivers/iio/common/ssp_sensors/ssp_spi.c | 47 ++++++++++--------------
1 file changed, 20 insertions(+), 27 deletions(-)
diff --git a/drivers/iio/common/ssp_sensors/ssp_spi.c b/drivers/iio/common/ssp_sensors/ssp_spi.c
index ebcda6de56c4..29bc3d48c42f 100644
--- a/drivers/iio/common/ssp_sensors/ssp_spi.c
+++ b/drivers/iio/common/ssp_sensors/ssp_spi.c
@@ -4,6 +4,7 @@
*/
#include "ssp.h"
+#include <linux/cleanup.h>
#define SSP_DEV (&data->spi->dev)
#define SSP_GET_MESSAGE_TYPE(data) ((data) & (3 << SSP_RW))
@@ -180,9 +181,8 @@ static inline void ssp_pending_add(struct ssp_data *data, struct ssp_msg *msg,
if (no_irq)
return;
- mutex_lock(&data->pending_lock);
+ guard(mutex)(&data->pending_lock);
list_add_tail(&msg->list, &data->pending_list);
- mutex_unlock(&data->pending_lock);
}
static inline void ssp_pending_del(struct ssp_data *data, struct ssp_msg *msg,
@@ -191,9 +191,8 @@ static inline void ssp_pending_del(struct ssp_data *data, struct ssp_msg *msg,
if (no_irq)
return;
- mutex_lock(&data->pending_lock);
+ guard(mutex)(&data->pending_lock);
list_del(&msg->list);
- mutex_unlock(&data->pending_lock);
}
static int __ssp_do_transfer(struct ssp_data *data, struct ssp_msg *msg,
@@ -204,17 +203,20 @@ static int __ssp_do_transfer(struct ssp_data *data, struct ssp_msg *msg,
/* msg->done must be initialized by caller */
WARN_ON(!msg->done);
- mutex_lock(&data->comm_lock);
+ guard(mutex)(&data->comm_lock);
status = ssp_check_lines(data, false);
- if (status < 0)
- goto _error_locked;
+ if (status < 0) {
+ data->timeout_cnt++;
+ return status;
+ }
status = spi_write(data->spi, msg->buffer, SSP_HEADER_SIZE);
if (status < 0) {
gpiod_set_value_cansleep(data->ap_mcu_gpiod, 1);
dev_err(SSP_DEV, "%s spi_write fail\n", __func__);
- goto _error_locked;
+ data->timeout_cnt++;
+ return status;
}
ssp_pending_add(data, msg, no_irq);
@@ -222,16 +224,11 @@ static int __ssp_do_transfer(struct ssp_data *data, struct ssp_msg *msg,
status = ssp_check_lines(data, true);
if (status < 0) {
ssp_pending_del(data, msg, no_irq);
- goto _error_locked;
+ data->timeout_cnt++;
+ return status;
}
- mutex_unlock(&data->comm_lock);
return 0;
-
-_error_locked:
- mutex_unlock(&data->comm_lock);
- data->timeout_cnt++;
- return status;
}
static int ssp_do_transfer(struct ssp_data *data, struct ssp_msg *msg,
@@ -379,12 +376,12 @@ int ssp_irq_msg(struct ssp_data *data)
switch (msg_type) {
case SSP_AP2HUB_READ:
- case SSP_AP2HUB_WRITE:
+ case SSP_AP2HUB_WRITE: {
/*
* this is a small list, a few elements - the packets can be
* received with no order
*/
- mutex_lock(&data->pending_lock);
+ guard(mutex)(&data->pending_lock);
list_for_each_entry_safe(iter, n, &data->pending_list, list) {
if (iter->options == msg_options) {
list_del(&iter->list);
@@ -400,10 +397,8 @@ int ssp_irq_msg(struct ssp_data *data)
* check but let's handle this
*/
buffer = kmalloc(length, GFP_KERNEL | GFP_DMA);
- if (!buffer) {
- ret = -ENOMEM;
- goto _unlock;
- }
+ if (!buffer)
+ return -ENOMEM;
/* got dead packet so it is always an error */
ret = spi_read(data->spi, buffer, length);
@@ -415,7 +410,7 @@ int ssp_irq_msg(struct ssp_data *data)
dev_err(SSP_DEV, "No match error %x\n",
msg_options);
- goto _unlock;
+ break;
}
if (msg_type == SSP_AP2HUB_READ)
@@ -433,16 +428,15 @@ int ssp_irq_msg(struct ssp_data *data)
msg->length = 1;
list_add_tail(&msg->list, &data->pending_list);
- goto _unlock;
+ break;
}
}
if (msg->done)
if (!completion_done(msg->done))
complete(msg->done);
-_unlock:
- mutex_unlock(&data->pending_lock);
break;
+ }
case SSP_HUB2AP_WRITE:
buffer = kzalloc(length, GFP_KERNEL | GFP_DMA);
if (!buffer)
@@ -472,7 +466,7 @@ void ssp_clean_pending_list(struct ssp_data *data)
{
struct ssp_msg *msg, *n;
- mutex_lock(&data->pending_lock);
+ guard(mutex)(&data->pending_lock);
list_for_each_entry_safe(msg, n, &data->pending_list, list) {
list_del(&msg->list);
@@ -480,7 +474,6 @@ void ssp_clean_pending_list(struct ssp_data *data)
if (!completion_done(msg->done))
complete(msg->done);
}
- mutex_unlock(&data->pending_lock);
}
int ssp_command(struct ssp_data *data, char command, int arg)
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v8 10/12] iio: ssp_sensors: Use dev_err_probe()
2026-05-15 17:40 [PATCH v8 00/12] iio: ssp_sensors: driver fixes, refactor and cleanup Sanjay Chitroda
` (8 preceding siblings ...)
2026-05-15 17:40 ` [PATCH v8 09/12] iio: ssp_sensors: use guard() to release mutexes Sanjay Chitroda
@ 2026-05-15 17:40 ` Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 11/12] iio: ssp_sensors: return errors directly from ssp_irq_msg() Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 12/12] iio: ssp_sensors: reuse embedded RX buffer for SPI transfers Sanjay Chitroda
11 siblings, 0 replies; 13+ messages in thread
From: Sanjay Chitroda @ 2026-05-15 17:40 UTC (permalink / raw)
To: jic23
Cc: dlechner, nuno.sa, andy, sanjayembeddedse, tglx,
christophe.jaillet, mingo, kees, nabijaczleweli, kyungmin.park,
linux-iio, linux-kernel
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
dev_err_probe() makes error code handling simpler and handle
deferred probe nicely (avoid spamming logs).
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
changes in v8:
- Address coding style comment based on input from Andy
- v7 change: https://lore.kernel.org/all/20260426091710.3722035-9-sanjayembedded@gmail.com/
changes in v7:
- Drop redundant else with refactor as guided by Andy
- Add new change in series for local dev variable with input from Andy
- v6 change: https://lore.kernel.org/all/20260415050749.3858046-7-sanjayembedded@gmail.com/
---
drivers/iio/common/ssp_sensors/ssp_dev.c | 34 +++++++++---------------
1 file changed, 12 insertions(+), 22 deletions(-)
diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c
index 441416c612a4..2cd06c85ffe1 100644
--- a/drivers/iio/common/ssp_sensors/ssp_dev.c
+++ b/drivers/iio/common/ssp_sensors/ssp_dev.c
@@ -513,24 +513,18 @@ static int ssp_probe(struct spi_device *spi)
int ret;
data = ssp_parse_dt(dev);
- if (!data) {
- dev_err(dev, "Failed to find platform data\n");
- return -ENODEV;
- }
+ if (!data)
+ return dev_err_probe(dev, -ENODEV, "Failed to find platform data\n");
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, sensorhub_sensor_devs,
ARRAY_SIZE(sensorhub_sensor_devs), NULL, 0, NULL);
- if (ret < 0) {
- dev_err(dev, "mfd add devices fail\n");
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "mfd add devices fail\n");
spi->mode = SPI_MODE_1;
ret = spi_setup(spi);
- if (ret < 0) {
- dev_err(dev, "Failed to setup spi\n");
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to setup spi\n");
data->fw_dl_state = SSP_FW_DL_STATE_NONE;
data->spi = spi;
@@ -588,16 +582,12 @@ static int ssp_probe(struct spi_device *spi)
enable_irq_wake(data->spi->irq);
data->fw_dl_state = ssp_check_fwbl(data);
- if (data->fw_dl_state == SSP_FW_DL_STATE_NONE) {
- ret = ssp_initialize_mcu(data);
- if (ret < 0) {
- dev_err(dev, "Initialize_mcu failed\n");
- return ret;
- }
- } else {
- dev_err(dev, "Firmware version not supported\n");
- return -EPERM;
- }
+ if (data->fw_dl_state != SSP_FW_DL_STATE_NONE)
+ return dev_err_probe(dev, -EPERM, "Firmware version not supported\n");
+
+ ret = ssp_initialize_mcu(data);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Initialize_mcu failed\n");
/*
* Managed shutdown action for the SSP device lifecycle.
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v8 11/12] iio: ssp_sensors: return errors directly from ssp_irq_msg()
2026-05-15 17:40 [PATCH v8 00/12] iio: ssp_sensors: driver fixes, refactor and cleanup Sanjay Chitroda
` (9 preceding siblings ...)
2026-05-15 17:40 ` [PATCH v8 10/12] iio: ssp_sensors: Use dev_err_probe() Sanjay Chitroda
@ 2026-05-15 17:40 ` Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 12/12] iio: ssp_sensors: reuse embedded RX buffer for SPI transfers Sanjay Chitroda
11 siblings, 0 replies; 13+ messages in thread
From: Sanjay Chitroda @ 2026-05-15 17:40 UTC (permalink / raw)
To: jic23
Cc: dlechner, nuno.sa, andy, sanjayembeddedse, tglx,
christophe.jaillet, mingo, kees, nabijaczleweli, kyungmin.park,
linux-iio, linux-kernel
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
In the switch legs previously used break statements and relied on the
common return path at the end of the function.
Return directly on failure instead, allowing errors to be propagated
immediately. The final return value now clearly indicates success.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
drivers/iio/common/ssp_sensors/ssp_spi.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/iio/common/ssp_sensors/ssp_spi.c b/drivers/iio/common/ssp_sensors/ssp_spi.c
index 29bc3d48c42f..172b4bbd298c 100644
--- a/drivers/iio/common/ssp_sensors/ssp_spi.c
+++ b/drivers/iio/common/ssp_sensors/ssp_spi.c
@@ -386,7 +386,7 @@ int ssp_irq_msg(struct ssp_data *data)
if (iter->options == msg_options) {
list_del(&iter->list);
msg = iter;
- break;
+ return ret;
}
}
@@ -410,7 +410,7 @@ int ssp_irq_msg(struct ssp_data *data)
dev_err(SSP_DEV, "No match error %x\n",
msg_options);
- break;
+ return ret;
}
if (msg_type == SSP_AP2HUB_READ)
@@ -428,14 +428,14 @@ int ssp_irq_msg(struct ssp_data *data)
msg->length = 1;
list_add_tail(&msg->list, &data->pending_list);
- break;
+ return ret;
}
}
if (msg->done)
if (!completion_done(msg->done))
complete(msg->done);
- break;
+ return ret;
}
case SSP_HUB2AP_WRITE:
buffer = kzalloc(length, GFP_KERNEL | GFP_DMA);
@@ -446,20 +446,20 @@ int ssp_irq_msg(struct ssp_data *data)
if (ret < 0) {
dev_err(SSP_DEV, "spi read fail\n");
kfree(buffer);
- break;
+ return ret;
}
ret = ssp_parse_dataframe(data, buffer, length);
kfree(buffer);
- break;
+ return ret;
default:
dev_err(SSP_DEV, "unknown msg type\n");
return -EPROTO;
}
- return ret;
+ return 0;
}
void ssp_clean_pending_list(struct ssp_data *data)
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v8 12/12] iio: ssp_sensors: reuse embedded RX buffer for SPI transfers
2026-05-15 17:40 [PATCH v8 00/12] iio: ssp_sensors: driver fixes, refactor and cleanup Sanjay Chitroda
` (10 preceding siblings ...)
2026-05-15 17:40 ` [PATCH v8 11/12] iio: ssp_sensors: return errors directly from ssp_irq_msg() Sanjay Chitroda
@ 2026-05-15 17:40 ` Sanjay Chitroda
11 siblings, 0 replies; 13+ messages in thread
From: Sanjay Chitroda @ 2026-05-15 17:40 UTC (permalink / raw)
To: jic23
Cc: dlechner, nuno.sa, andy, sanjayembeddedse, tglx,
christophe.jaillet, mingo, kees, nabijaczleweli, kyungmin.park,
linux-iio, linux-kernel
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Avoid allocating a temporary DMA buffer in the interrupt context when
handling hub-to-AP and AP-to-hub SPI write messages.
Replace the dynamically allocated RX buffer with a fixed-size,
preallocated buffer embedded in the driver structure and reused for all
SPI receive operations. This removes memory allocation from the
IRQ path, simplifies lifetime management.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
Changes in v6:
- Address review comment of Jonathan and use __aligned(IIO_DMA_MINALIGN)
and have buffer assignment specific to block instead of top.
- Regarding DMA and size discussion point are open to check
- v7 change: https://lore.kernel.org/all/20260426091710.3722035-10-sanjayembedded@gmail.com/
Changes in v6:
- Replace dynamically allocated RX buffer with embedded fixed-size buffer
- Fix struct layout to satisfy DMA alignment constraints comment from David
- v5 change: https://lore.kernel.org/all/20260406080852.2727453-6-sanjayembedded@gmail.com/
Changes in v5:
- Rebase change on top of latest v5 patch series.
Changes in v4:
- Use preallocated buffer and stash a buffer that gets reused each time instead of a fresh allocation.
- v3 change: https://lore.kernel.org/all/20260315125509.857195-3-sanjayembedded@gmail.com/
Changes in v3:
- prepare series to have all respective cleanup API support for the ssp_sensors following input from Andy Shevchenko
- v2 change: https://lore.kernel.org/all/20260311174151.3441429-1-sanjayembedded@gmail.com/
Changes in v2:
- split series to individual patch
- address review comment from Andy Shevchenko
- v1 change: https://lore.kernel.org/all/20260310200513.2162018-3-sanjayembedded@gmail.com/
---
drivers/iio/common/ssp_sensors/ssp.h | 3 +++
drivers/iio/common/ssp_sensors/ssp_spi.c | 17 +++--------------
2 files changed, 6 insertions(+), 14 deletions(-)
diff --git a/drivers/iio/common/ssp_sensors/ssp.h b/drivers/iio/common/ssp_sensors/ssp.h
index f649cdecc277..6d7409db014e 100644
--- a/drivers/iio/common/ssp_sensors/ssp.h
+++ b/drivers/iio/common/ssp_sensors/ssp.h
@@ -174,6 +174,7 @@ struct ssp_sensorhub_info {
* @pending_list: pending list for messages queued to be sent/read
* @sensor_devs: registered IIO devices table
* @enable_refcount: enable reference count for wdt (watchdog timer)
+ * @rx_buf: buffer to receive SPI data
* @header_buffer: cache aligned buffer for packet header
*/
struct ssp_data {
@@ -221,6 +222,8 @@ struct ssp_data {
struct iio_dev *sensor_devs[SSP_SENSOR_MAX];
atomic_t enable_refcount;
+ u8 rx_buf[SSP_DATA_PACKET_SIZE] __aligned(IIO_DMA_MINALIGN);
+
__le16 header_buffer[SSP_HEADER_BUFFER_SIZE / sizeof(__le16)] __aligned(IIO_DMA_MINALIGN);
};
diff --git a/drivers/iio/common/ssp_sensors/ssp_spi.c b/drivers/iio/common/ssp_sensors/ssp_spi.c
index 172b4bbd298c..d6919e86aa95 100644
--- a/drivers/iio/common/ssp_sensors/ssp_spi.c
+++ b/drivers/iio/common/ssp_sensors/ssp_spi.c
@@ -396,17 +396,13 @@ int ssp_irq_msg(struct ssp_data *data)
* but the slave should not send such ones - it is to
* check but let's handle this
*/
- buffer = kmalloc(length, GFP_KERNEL | GFP_DMA);
- if (!buffer)
- return -ENOMEM;
+ buffer = data->rx_buf;
/* got dead packet so it is always an error */
ret = spi_read(data->spi, buffer, length);
if (ret >= 0)
ret = -EPROTO;
- kfree(buffer);
-
dev_err(SSP_DEV, "No match error %x\n",
msg_options);
@@ -438,22 +434,15 @@ int ssp_irq_msg(struct ssp_data *data)
return ret;
}
case SSP_HUB2AP_WRITE:
- buffer = kzalloc(length, GFP_KERNEL | GFP_DMA);
- if (!buffer)
- return -ENOMEM;
+ buffer = data->rx_buf;
ret = spi_read(data->spi, buffer, length);
if (ret < 0) {
dev_err(SSP_DEV, "spi read fail\n");
- kfree(buffer);
return ret;
}
- ret = ssp_parse_dataframe(data, buffer, length);
-
- kfree(buffer);
- return ret;
-
+ return ssp_parse_dataframe(data, buffer, length);
default:
dev_err(SSP_DEV, "unknown msg type\n");
return -EPROTO;
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-05-15 17:41 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-15 17:40 [PATCH v8 00/12] iio: ssp_sensors: driver fixes, refactor and cleanup Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 01/12] iio: ssp_sensors: cancel delayed work_refresh on remove Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 02/12] iio: ssp_sensors: factor out pending list add/remove helpers Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 03/12] iio: ssp_sensors: refactor transfer logic into helper Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 04/12] iio: ssp_sensors: factor out MCU enable/disable helpers Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 05/12] iio: ssp_sensors: use local struct device Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 06/12] iio: ssp_sensors: fix variable type and declaration order in probe() Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 07/12] iio: ssp_sensors: Drop duplicated wdt timer and work cleanup Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 08/12] iio: ssp_sensors: convert probe and teardown to devm-managed resources Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 09/12] iio: ssp_sensors: use guard() to release mutexes Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 10/12] iio: ssp_sensors: Use dev_err_probe() Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 11/12] iio: ssp_sensors: return errors directly from ssp_irq_msg() Sanjay Chitroda
2026-05-15 17:40 ` [PATCH v8 12/12] iio: ssp_sensors: reuse embedded RX buffer for SPI transfers Sanjay Chitroda
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox