* [PATCH v6 1/8] iio: light: opt3001: move device registration to end of probe()
2026-06-14 13:19 [PATCH v6 0/8] iio: light: opt3001: driver cleanup Joshua Crofts
@ 2026-06-14 13:19 ` Joshua Crofts
2026-06-17 10:20 ` Andy Shevchenko
2026-06-14 13:19 ` [PATCH v6 2/8] iio: light: opt3001: use local struct device and i2c_client variables Joshua Crofts
` (7 subsequent siblings)
8 siblings, 1 reply; 12+ messages in thread
From: Joshua Crofts @ 2026-06-14 13:19 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko
Cc: linux-iio, linux-kernel, Joshua Crofts
Move IIO device registration to the end of the probe() function to
follow standard driver teardown/setup ordering and improve driver
logic. Additionally, switch devm_iio_device_register() to its
unmanaged counterpart as current driver implementation mixes managed
and unmanaged resources, causing potential resource leaks.
Also, add iio_device_unregister() to remove() function to correctly
handle teardown.
Suggested-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Joshua Crofts <joshua.crofts1@gmail.com>
---
drivers/iio/light/opt3001.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
index 03c7a87b4a8e..6a39f116f931 100644
--- a/drivers/iio/light/opt3001.c
+++ b/drivers/iio/light/opt3001.c
@@ -874,12 +874,6 @@ static int opt3001_probe(struct i2c_client *client)
iio->modes = INDIO_DIRECT_MODE;
iio->info = &opt3001_info;
- ret = devm_iio_device_register(dev, iio);
- if (ret) {
- dev_err(dev, "failed to register IIO device\n");
- return ret;
- }
-
/* Make use of INT pin only if valid IRQ no. is given */
if (irq > 0) {
ret = request_threaded_irq(irq, NULL, opt3001_irq,
@@ -894,7 +888,17 @@ static int opt3001_probe(struct i2c_client *client)
dev_dbg(opt->dev, "enabling interrupt-less operation\n");
}
+ ret = iio_device_register(iio);
+ if (ret)
+ goto free_irq;
+
return 0;
+
+free_irq:
+ if (irq > 0)
+ free_irq(irq, iio);
+
+ return ret;
}
static void opt3001_remove(struct i2c_client *client)
@@ -904,6 +908,8 @@ static void opt3001_remove(struct i2c_client *client)
int ret;
u16 reg;
+ iio_device_unregister(iio);
+
if (opt->use_irq)
free_irq(client->irq, iio);
--
2.54.0
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH v6 1/8] iio: light: opt3001: move device registration to end of probe()
2026-06-14 13:19 ` [PATCH v6 1/8] iio: light: opt3001: move device registration to end of probe() Joshua Crofts
@ 2026-06-17 10:20 ` Andy Shevchenko
0 siblings, 0 replies; 12+ messages in thread
From: Andy Shevchenko @ 2026-06-17 10:20 UTC (permalink / raw)
To: Joshua Crofts
Cc: Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, linux-iio, linux-kernel
On Sun, Jun 14, 2026 at 03:19:03PM +0200, Joshua Crofts wrote:
> Move IIO device registration to the end of the probe() function to
> follow standard driver teardown/setup ordering and improve driver
> logic. Additionally, switch devm_iio_device_register() to its
> unmanaged counterpart as current driver implementation mixes managed
> and unmanaged resources, causing potential resource leaks.
>
> Also, add iio_device_unregister() to remove() function to correctly
> handle teardown.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v6 2/8] iio: light: opt3001: use local struct device and i2c_client variables
2026-06-14 13:19 [PATCH v6 0/8] iio: light: opt3001: driver cleanup Joshua Crofts
2026-06-14 13:19 ` [PATCH v6 1/8] iio: light: opt3001: move device registration to end of probe() Joshua Crofts
@ 2026-06-14 13:19 ` Joshua Crofts
2026-06-14 13:19 ` [PATCH v6 3/8] iio: light: opt3001: prefer dev_err_probe() Joshua Crofts
` (6 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Joshua Crofts @ 2026-06-14 13:19 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko
Cc: linux-iio, linux-kernel, Joshua Crofts, Andy Shevchenko
Switch the driver to use local variables for struct device and struct
i2c_client and remove struct device member from struct opt3001, as the
former can be derived from struct client.
No functional change.
Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Joshua Crofts <joshua.crofts1@gmail.com>
---
drivers/iio/light/opt3001.c | 139 +++++++++++++++++++++++---------------------
1 file changed, 73 insertions(+), 66 deletions(-)
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
index 6a39f116f931..28455d887e1d 100644
--- a/drivers/iio/light/opt3001.c
+++ b/drivers/iio/light/opt3001.c
@@ -101,7 +101,6 @@ struct opt3001_chip_info {
struct opt3001 {
struct i2c_client *client;
- struct device *dev;
struct mutex lock;
bool ok_to_ignore_lock;
@@ -313,6 +312,8 @@ static const struct iio_chan_spec opt3002_channels[] = {
static int opt3001_get_processed(struct opt3001 *opt, int *val, int *val2)
{
+ struct i2c_client *client = opt->client;
+ struct device *dev = &client->dev;
int ret;
u16 mantissa;
u16 reg;
@@ -326,12 +327,12 @@ static int opt3001_get_processed(struct opt3001 *opt, int *val, int *val2)
* doing so will overwrite the low-level limit value however we
* will restore this value later on.
*/
- ret = i2c_smbus_write_word_swapped(opt->client,
- OPT3001_LOW_LIMIT,
- OPT3001_LOW_LIMIT_EOC_ENABLE);
+ ret = i2c_smbus_write_word_swapped(client,
+ OPT3001_LOW_LIMIT,
+ OPT3001_LOW_LIMIT_EOC_ENABLE);
if (ret < 0) {
- dev_err(opt->dev, "failed to write register %02x\n",
- OPT3001_LOW_LIMIT);
+ dev_err(dev, "failed to write register %02x\n",
+ OPT3001_LOW_LIMIT);
return ret;
}
@@ -343,21 +344,20 @@ static int opt3001_get_processed(struct opt3001 *opt, int *val, int *val2)
opt->result_ready = false;
/* Configure for single-conversion mode and start a new conversion */
- ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+ ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION);
if (ret < 0) {
- dev_err(opt->dev, "failed to read register %02x\n",
- OPT3001_CONFIGURATION);
+ dev_err(dev, "failed to read register %02x\n",
+ OPT3001_CONFIGURATION);
goto err;
}
reg = ret;
opt3001_set_mode(opt, ®, OPT3001_CONFIGURATION_M_SINGLE);
- ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
- reg);
+ ret = i2c_smbus_write_word_swapped(client, OPT3001_CONFIGURATION, reg);
if (ret < 0) {
- dev_err(opt->dev, "failed to write register %02x\n",
- OPT3001_CONFIGURATION);
+ dev_err(dev, "failed to write register %02x\n",
+ OPT3001_CONFIGURATION);
goto err;
}
@@ -375,10 +375,9 @@ static int opt3001_get_processed(struct opt3001 *opt, int *val, int *val2)
msleep(timeout);
/* Check result ready flag */
- ret = i2c_smbus_read_word_swapped(opt->client,
- OPT3001_CONFIGURATION);
+ ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION);
if (ret < 0) {
- dev_err(opt->dev, "failed to read register %02x\n",
+ dev_err(dev, "failed to read register %02x\n",
OPT3001_CONFIGURATION);
goto err;
}
@@ -389,9 +388,9 @@ static int opt3001_get_processed(struct opt3001 *opt, int *val, int *val2)
}
/* Obtain value */
- ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_RESULT);
+ ret = i2c_smbus_read_word_swapped(client, OPT3001_RESULT);
if (ret < 0) {
- dev_err(opt->dev, "failed to read register %02x\n",
+ dev_err(dev, "failed to read register %02x\n",
OPT3001_RESULT);
goto err;
}
@@ -416,12 +415,12 @@ static int opt3001_get_processed(struct opt3001 *opt, int *val, int *val2)
* bit-overlap and therefore can't be done.
*/
value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa;
- ret = i2c_smbus_write_word_swapped(opt->client,
+ ret = i2c_smbus_write_word_swapped(client,
OPT3001_LOW_LIMIT,
value);
if (ret < 0) {
- dev_err(opt->dev, "failed to write register %02x\n",
- OPT3001_LOW_LIMIT);
+ dev_err(dev, "failed to write register %02x\n",
+ OPT3001_LOW_LIMIT);
return ret;
}
}
@@ -444,13 +443,15 @@ static int opt3001_get_int_time(struct opt3001 *opt, int *val, int *val2)
static int opt3001_set_int_time(struct opt3001 *opt, int time)
{
+ struct i2c_client *client = opt->client;
+ struct device *dev = &client->dev;
int ret;
u16 reg;
- ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+ ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION);
if (ret < 0) {
- dev_err(opt->dev, "failed to read register %02x\n",
- OPT3001_CONFIGURATION);
+ dev_err(dev, "failed to read register %02x\n",
+ OPT3001_CONFIGURATION);
return ret;
}
@@ -469,8 +470,7 @@ static int opt3001_set_int_time(struct opt3001 *opt, int time)
return -EINVAL;
}
- return i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
- reg);
+ return i2c_smbus_write_word_swapped(client, OPT3001_CONFIGURATION, reg);
}
static int opt3001_read_raw(struct iio_dev *iio,
@@ -565,6 +565,8 @@ static int opt3001_write_event_value(struct iio_dev *iio,
int val, int val2)
{
struct opt3001 *opt = iio_priv(iio);
+ struct i2c_client *client = opt->client;
+ struct device *dev = &client->dev;
int ret;
int whole;
int integer;
@@ -583,7 +585,7 @@ static int opt3001_write_event_value(struct iio_dev *iio,
ret = opt3001_find_scale(opt, val, val2, &exponent);
if (ret < 0) {
- dev_err(opt->dev, "can't find scale for %d.%06u\n", val, val2);
+ dev_err(dev, "can't find scale for %d.%06u\n", val, val2);
goto err;
}
@@ -611,9 +613,9 @@ static int opt3001_write_event_value(struct iio_dev *iio,
goto err;
}
- ret = i2c_smbus_write_word_swapped(opt->client, reg, value);
+ ret = i2c_smbus_write_word_swapped(client, reg, value);
if (ret < 0) {
- dev_err(opt->dev, "failed to write register %02x\n", reg);
+ dev_err(dev, "failed to write register %02x\n", reg);
goto err;
}
@@ -637,6 +639,8 @@ static int opt3001_write_event_config(struct iio_dev *iio,
enum iio_event_direction dir, bool state)
{
struct opt3001 *opt = iio_priv(iio);
+ struct i2c_client *client = opt->client;
+ struct device *dev = &client->dev;
int ret;
u16 mode;
u16 reg;
@@ -652,21 +656,20 @@ static int opt3001_write_event_config(struct iio_dev *iio,
mode = state ? OPT3001_CONFIGURATION_M_CONTINUOUS
: OPT3001_CONFIGURATION_M_SHUTDOWN;
- ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+ ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION);
if (ret < 0) {
- dev_err(opt->dev, "failed to read register %02x\n",
- OPT3001_CONFIGURATION);
+ dev_err(dev, "failed to read register %02x\n",
+ OPT3001_CONFIGURATION);
goto err;
}
reg = ret;
opt3001_set_mode(opt, ®, mode);
- ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
- reg);
+ ret = i2c_smbus_write_word_swapped(client, OPT3001_CONFIGURATION, reg);
if (ret < 0) {
- dev_err(opt->dev, "failed to write register %02x\n",
- OPT3001_CONFIGURATION);
+ dev_err(dev, "failed to write register %02x\n",
+ OPT3001_CONFIGURATION);
goto err;
}
@@ -688,13 +691,15 @@ static const struct iio_info opt3001_info = {
static int opt3001_read_id(struct opt3001 *opt)
{
+ struct i2c_client *client = opt->client;
+ struct device *dev = &client->dev;
char manufacturer[2];
u16 device_id;
int ret;
- ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_MANUFACTURER_ID);
+ ret = i2c_smbus_read_word_swapped(client, OPT3001_MANUFACTURER_ID);
if (ret < 0) {
- dev_err(opt->dev, "failed to read register %02x\n",
+ dev_err(dev, "failed to read register %02x\n",
OPT3001_MANUFACTURER_ID);
return ret;
}
@@ -702,29 +707,31 @@ static int opt3001_read_id(struct opt3001 *opt)
manufacturer[0] = ret >> 8;
manufacturer[1] = ret & 0xff;
- ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_DEVICE_ID);
+ ret = i2c_smbus_read_word_swapped(client, OPT3001_DEVICE_ID);
if (ret < 0) {
- dev_err(opt->dev, "failed to read register %02x\n",
+ dev_err(dev, "failed to read register %02x\n",
OPT3001_DEVICE_ID);
return ret;
}
device_id = ret;
- dev_info(opt->dev, "Found %c%c OPT%04x\n", manufacturer[0],
- manufacturer[1], device_id);
+ dev_info(dev, "Found %c%c OPT%04x\n", manufacturer[0], manufacturer[1],
+ device_id);
return 0;
}
static int opt3001_configure(struct opt3001 *opt)
{
+ struct i2c_client *client = opt->client;
+ struct device *dev = &client->dev;
int ret;
u16 reg;
- ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+ ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION);
if (ret < 0) {
- dev_err(opt->dev, "failed to read register %02x\n",
+ dev_err(dev, "failed to read register %02x\n",
OPT3001_CONFIGURATION);
return ret;
}
@@ -750,17 +757,16 @@ static int opt3001_configure(struct opt3001 *opt)
reg &= ~OPT3001_CONFIGURATION_ME;
reg &= ~OPT3001_CONFIGURATION_FC_MASK;
- ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
- reg);
+ ret = i2c_smbus_write_word_swapped(client, OPT3001_CONFIGURATION, reg);
if (ret < 0) {
- dev_err(opt->dev, "failed to write register %02x\n",
+ dev_err(dev, "failed to write register %02x\n",
OPT3001_CONFIGURATION);
return ret;
}
- ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_LOW_LIMIT);
+ ret = i2c_smbus_read_word_swapped(client, OPT3001_LOW_LIMIT);
if (ret < 0) {
- dev_err(opt->dev, "failed to read register %02x\n",
+ dev_err(dev, "failed to read register %02x\n",
OPT3001_LOW_LIMIT);
return ret;
}
@@ -768,9 +774,9 @@ static int opt3001_configure(struct opt3001 *opt)
opt->low_thresh_mantissa = OPT3001_REG_MANTISSA(ret);
opt->low_thresh_exp = OPT3001_REG_EXPONENT(ret);
- ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_HIGH_LIMIT);
+ ret = i2c_smbus_read_word_swapped(client, OPT3001_HIGH_LIMIT);
if (ret < 0) {
- dev_err(opt->dev, "failed to read register %02x\n",
+ dev_err(dev, "failed to read register %02x\n",
OPT3001_HIGH_LIMIT);
return ret;
}
@@ -785,6 +791,8 @@ static irqreturn_t opt3001_irq(int irq, void *_iio)
{
struct iio_dev *iio = _iio;
struct opt3001 *opt = iio_priv(iio);
+ struct i2c_client *client = opt->client;
+ struct device *dev = &client->dev;
int ret;
bool wake_result_ready_queue = false;
enum iio_chan_type chan_type = opt->chip_info->chan_type;
@@ -793,10 +801,10 @@ static irqreturn_t opt3001_irq(int irq, void *_iio)
if (!ok_to_ignore_lock)
mutex_lock(&opt->lock);
- ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+ ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION);
if (ret < 0) {
- dev_err(opt->dev, "failed to read register %02x\n",
- OPT3001_CONFIGURATION);
+ dev_err(dev, "failed to read register %02x\n",
+ OPT3001_CONFIGURATION);
goto out;
}
@@ -815,10 +823,10 @@ static irqreturn_t opt3001_irq(int irq, void *_iio)
IIO_EV_DIR_FALLING),
iio_get_time_ns(iio));
} else if (ret & OPT3001_CONFIGURATION_CRF) {
- ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_RESULT);
+ ret = i2c_smbus_read_word_swapped(client, OPT3001_RESULT);
if (ret < 0) {
- dev_err(opt->dev, "failed to read register %02x\n",
- OPT3001_RESULT);
+ dev_err(dev, "failed to read register %02x\n",
+ OPT3001_RESULT);
goto out;
}
opt->result = ret;
@@ -851,7 +859,6 @@ static int opt3001_probe(struct i2c_client *client)
opt = iio_priv(iio);
opt->client = client;
- opt->dev = dev;
opt->chip_info = i2c_get_match_data(client);
mutex_init(&opt->lock);
@@ -885,7 +892,7 @@ static int opt3001_probe(struct i2c_client *client)
}
opt->use_irq = true;
} else {
- dev_dbg(opt->dev, "enabling interrupt-less operation\n");
+ dev_dbg(dev, "enabling interrupt-less operation\n");
}
ret = iio_device_register(iio);
@@ -905,6 +912,7 @@ static void opt3001_remove(struct i2c_client *client)
{
struct iio_dev *iio = i2c_get_clientdata(client);
struct opt3001 *opt = iio_priv(iio);
+ struct device *dev = &client->dev;
int ret;
u16 reg;
@@ -913,21 +921,20 @@ static void opt3001_remove(struct i2c_client *client)
if (opt->use_irq)
free_irq(client->irq, iio);
- ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+ ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION);
if (ret < 0) {
- dev_err(opt->dev, "failed to read register %02x\n",
- OPT3001_CONFIGURATION);
+ dev_err(dev, "failed to read register %02x\n",
+ OPT3001_CONFIGURATION);
return;
}
reg = ret;
opt3001_set_mode(opt, ®, OPT3001_CONFIGURATION_M_SHUTDOWN);
- ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
- reg);
+ ret = i2c_smbus_write_word_swapped(client, OPT3001_CONFIGURATION, reg);
if (ret < 0) {
- dev_err(opt->dev, "failed to write register %02x\n",
- OPT3001_CONFIGURATION);
+ dev_err(dev, "failed to write register %02x\n",
+ OPT3001_CONFIGURATION);
}
}
--
2.54.0
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH v6 3/8] iio: light: opt3001: prefer dev_err_probe()
2026-06-14 13:19 [PATCH v6 0/8] iio: light: opt3001: driver cleanup Joshua Crofts
2026-06-14 13:19 ` [PATCH v6 1/8] iio: light: opt3001: move device registration to end of probe() Joshua Crofts
2026-06-14 13:19 ` [PATCH v6 2/8] iio: light: opt3001: use local struct device and i2c_client variables Joshua Crofts
@ 2026-06-14 13:19 ` Joshua Crofts
2026-06-14 13:19 ` [PATCH v6 4/8] iio: light: opt3001: ensure correct parenthesis alignment Joshua Crofts
` (5 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Joshua Crofts @ 2026-06-14 13:19 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko
Cc: linux-iio, linux-kernel, Joshua Crofts, Maxwell Doose, Andy Shevchenko
Switch driver to use dev_err_probe() to unify error messages generated
in *_probe() and probe path functions.
Reviewed-by: Maxwell Doose <m32285159@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Joshua Crofts <joshua.crofts1@gmail.com>
---
drivers/iio/light/opt3001.c | 57 ++++++++++++++++++---------------------------
1 file changed, 23 insertions(+), 34 deletions(-)
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
index 28455d887e1d..c1062ace184c 100644
--- a/drivers/iio/light/opt3001.c
+++ b/drivers/iio/light/opt3001.c
@@ -698,21 +698,17 @@ static int opt3001_read_id(struct opt3001 *opt)
int ret;
ret = i2c_smbus_read_word_swapped(client, OPT3001_MANUFACTURER_ID);
- if (ret < 0) {
- dev_err(dev, "failed to read register %02x\n",
- OPT3001_MANUFACTURER_ID);
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to read register %02x\n",
+ OPT3001_MANUFACTURER_ID);
manufacturer[0] = ret >> 8;
manufacturer[1] = ret & 0xff;
ret = i2c_smbus_read_word_swapped(client, OPT3001_DEVICE_ID);
- if (ret < 0) {
- dev_err(dev, "failed to read register %02x\n",
- OPT3001_DEVICE_ID);
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to read register %02x\n",
+ OPT3001_DEVICE_ID);
device_id = ret;
@@ -730,11 +726,9 @@ static int opt3001_configure(struct opt3001 *opt)
u16 reg;
ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION);
- if (ret < 0) {
- dev_err(dev, "failed to read register %02x\n",
- OPT3001_CONFIGURATION);
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to read register %02x\n",
+ OPT3001_CONFIGURATION);
reg = ret;
@@ -758,28 +752,22 @@ static int opt3001_configure(struct opt3001 *opt)
reg &= ~OPT3001_CONFIGURATION_FC_MASK;
ret = i2c_smbus_write_word_swapped(client, OPT3001_CONFIGURATION, reg);
- if (ret < 0) {
- dev_err(dev, "failed to write register %02x\n",
- OPT3001_CONFIGURATION);
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to write register %02x\n",
+ OPT3001_CONFIGURATION);
ret = i2c_smbus_read_word_swapped(client, OPT3001_LOW_LIMIT);
- if (ret < 0) {
- dev_err(dev, "failed to read register %02x\n",
- OPT3001_LOW_LIMIT);
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to read register %02x\n",
+ OPT3001_LOW_LIMIT);
opt->low_thresh_mantissa = OPT3001_REG_MANTISSA(ret);
opt->low_thresh_exp = OPT3001_REG_EXPONENT(ret);
ret = i2c_smbus_read_word_swapped(client, OPT3001_HIGH_LIMIT);
- if (ret < 0) {
- dev_err(dev, "failed to read register %02x\n",
- OPT3001_HIGH_LIMIT);
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to read register %02x\n",
+ OPT3001_HIGH_LIMIT);
opt->high_thresh_mantissa = OPT3001_REG_MANTISSA(ret);
opt->high_thresh_exp = OPT3001_REG_EXPONENT(ret);
@@ -886,10 +874,11 @@ static int opt3001_probe(struct i2c_client *client)
ret = request_threaded_irq(irq, NULL, opt3001_irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"opt3001", iio);
- if (ret) {
- dev_err(dev, "failed to request IRQ #%d\n", irq);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to request IRQ #%d\n",
+ irq);
+
opt->use_irq = true;
} else {
dev_dbg(dev, "enabling interrupt-less operation\n");
--
2.54.0
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH v6 4/8] iio: light: opt3001: ensure correct parenthesis alignment
2026-06-14 13:19 [PATCH v6 0/8] iio: light: opt3001: driver cleanup Joshua Crofts
` (2 preceding siblings ...)
2026-06-14 13:19 ` [PATCH v6 3/8] iio: light: opt3001: prefer dev_err_probe() Joshua Crofts
@ 2026-06-14 13:19 ` Joshua Crofts
2026-06-14 13:19 ` [PATCH v6 5/8] iio: light: opt3001: localize for loop iterator Joshua Crofts
` (4 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Joshua Crofts @ 2026-06-14 13:19 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko
Cc: linux-iio, linux-kernel, Joshua Crofts, Andy Shevchenko, Maxwell Doose
Ensure correct parenthesis alignment per checkpatch.pl report.
No functional change.
Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Maxwell Doose <m32285159@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Joshua Crofts <joshua.crofts1@gmail.com>
---
drivers/iio/light/opt3001.c | 71 +++++++++++++++++++++++++--------------------
1 file changed, 39 insertions(+), 32 deletions(-)
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
index c1062ace184c..7aee251386e9 100644
--- a/drivers/iio/light/opt3001.c
+++ b/drivers/iio/light/opt3001.c
@@ -223,8 +223,8 @@ static const struct opt3001_scale opt3002_scales[] = {
},
};
-static int opt3001_find_scale(const struct opt3001 *opt, int val,
- int val2, u8 *exponent)
+static int opt3001_find_scale(const struct opt3001 *opt, int val, int val2,
+ u8 *exponent)
{
int i;
for (i = 0; i < ARRAY_SIZE(*opt->chip_info->scales); i++) {
@@ -242,8 +242,8 @@ static int opt3001_find_scale(const struct opt3001 *opt, int val,
return -EINVAL;
}
-static void opt3001_to_iio_ret(struct opt3001 *opt, u8 exponent,
- u16 mantissa, int *val, int *val2)
+static void opt3001_to_iio_ret(struct opt3001 *opt, u8 exponent, u16 mantissa,
+ int *val, int *val2)
{
int ret;
int whole = opt->chip_info->factor_whole;
@@ -364,8 +364,8 @@ static int opt3001_get_processed(struct opt3001 *opt, int *val, int *val2)
if (opt->use_irq) {
/* Wait for the IRQ to indicate the conversion is complete */
ret = wait_event_timeout(opt->result_ready_queue,
- opt->result_ready,
- msecs_to_jiffies(OPT3001_RESULT_READY_LONG));
+ opt->result_ready,
+ msecs_to_jiffies(OPT3001_RESULT_READY_LONG));
if (ret == 0)
return -ETIMEDOUT;
} else {
@@ -474,8 +474,8 @@ static int opt3001_set_int_time(struct opt3001 *opt, int time)
}
static int opt3001_read_raw(struct iio_dev *iio,
- struct iio_chan_spec const *chan, int *val, int *val2,
- long mask)
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
{
struct opt3001 *opt = iio_priv(iio);
int ret;
@@ -506,8 +506,8 @@ static int opt3001_read_raw(struct iio_dev *iio,
}
static int opt3001_write_raw(struct iio_dev *iio,
- struct iio_chan_spec const *chan, int val, int val2,
- long mask)
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
{
struct opt3001 *opt = iio_priv(iio);
int ret;
@@ -532,9 +532,11 @@ static int opt3001_write_raw(struct iio_dev *iio,
}
static int opt3001_read_event_value(struct iio_dev *iio,
- const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, enum iio_event_info info,
- int *val, int *val2)
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int *val, int *val2)
{
struct opt3001 *opt = iio_priv(iio);
int ret = IIO_VAL_INT_PLUS_MICRO;
@@ -544,11 +546,11 @@ static int opt3001_read_event_value(struct iio_dev *iio,
switch (dir) {
case IIO_EV_DIR_RISING:
opt3001_to_iio_ret(opt, opt->high_thresh_exp,
- opt->high_thresh_mantissa, val, val2);
+ opt->high_thresh_mantissa, val, val2);
break;
case IIO_EV_DIR_FALLING:
opt3001_to_iio_ret(opt, opt->low_thresh_exp,
- opt->low_thresh_mantissa, val, val2);
+ opt->low_thresh_mantissa, val, val2);
break;
default:
ret = -EINVAL;
@@ -560,9 +562,11 @@ static int opt3001_read_event_value(struct iio_dev *iio,
}
static int opt3001_write_event_value(struct iio_dev *iio,
- const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, enum iio_event_info info,
- int val, int val2)
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int val, int val2)
{
struct opt3001 *opt = iio_priv(iio);
struct i2c_client *client = opt->client;
@@ -626,8 +630,9 @@ static int opt3001_write_event_value(struct iio_dev *iio,
}
static int opt3001_read_event_config(struct iio_dev *iio,
- const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir)
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
{
struct opt3001 *opt = iio_priv(iio);
@@ -635,8 +640,10 @@ static int opt3001_read_event_config(struct iio_dev *iio,
}
static int opt3001_write_event_config(struct iio_dev *iio,
- const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, bool state)
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ bool state)
{
struct opt3001 *opt = iio_priv(iio);
struct i2c_client *client = opt->client;
@@ -800,16 +807,16 @@ static irqreturn_t opt3001_irq(int irq, void *_iio)
OPT3001_CONFIGURATION_M_CONTINUOUS) {
if (ret & OPT3001_CONFIGURATION_FH)
iio_push_event(iio,
- IIO_UNMOD_EVENT_CODE(chan_type, 0,
- IIO_EV_TYPE_THRESH,
- IIO_EV_DIR_RISING),
- iio_get_time_ns(iio));
+ IIO_UNMOD_EVENT_CODE(chan_type, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ iio_get_time_ns(iio));
if (ret & OPT3001_CONFIGURATION_FL)
iio_push_event(iio,
- IIO_UNMOD_EVENT_CODE(chan_type, 0,
- IIO_EV_TYPE_THRESH,
- IIO_EV_DIR_FALLING),
- iio_get_time_ns(iio));
+ IIO_UNMOD_EVENT_CODE(chan_type, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ iio_get_time_ns(iio));
} else if (ret & OPT3001_CONFIGURATION_CRF) {
ret = i2c_smbus_read_word_swapped(client, OPT3001_RESULT);
if (ret < 0) {
@@ -872,8 +879,8 @@ static int opt3001_probe(struct i2c_client *client)
/* Make use of INT pin only if valid IRQ no. is given */
if (irq > 0) {
ret = request_threaded_irq(irq, NULL, opt3001_irq,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- "opt3001", iio);
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "opt3001", iio);
if (ret)
return dev_err_probe(dev, ret,
"failed to request IRQ #%d\n",
--
2.54.0
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH v6 5/8] iio: light: opt3001: localize for loop iterator
2026-06-14 13:19 [PATCH v6 0/8] iio: light: opt3001: driver cleanup Joshua Crofts
` (3 preceding siblings ...)
2026-06-14 13:19 ` [PATCH v6 4/8] iio: light: opt3001: ensure correct parenthesis alignment Joshua Crofts
@ 2026-06-14 13:19 ` Joshua Crofts
2026-06-14 13:19 ` [PATCH v6 6/8] iio: light: opt3001: move driver to guard(mutex)() use Joshua Crofts
` (3 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Joshua Crofts @ 2026-06-14 13:19 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko
Cc: linux-iio, linux-kernel, Joshua Crofts, Maxwell Doose, Andy Shevchenko
Localize loop iterator to tighten scope and improve code style
per checkpatch.pl report.
No functional change.
Reviewed-by: Maxwell Doose <m32285159@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Joshua Crofts <joshua.crofts1@gmail.com>
---
drivers/iio/light/opt3001.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
index 7aee251386e9..80a2ede91272 100644
--- a/drivers/iio/light/opt3001.c
+++ b/drivers/iio/light/opt3001.c
@@ -226,8 +226,7 @@ static const struct opt3001_scale opt3002_scales[] = {
static int opt3001_find_scale(const struct opt3001 *opt, int val, int val2,
u8 *exponent)
{
- int i;
- for (i = 0; i < ARRAY_SIZE(*opt->chip_info->scales); i++) {
+ for (unsigned int i = 0; i < ARRAY_SIZE(*opt->chip_info->scales); i++) {
const struct opt3001_scale *scale = &(*opt->chip_info->scales)[i];
/*
* Compare the integer and micro parts to determine value scale.
--
2.54.0
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH v6 6/8] iio: light: opt3001: move driver to guard(mutex)() use
2026-06-14 13:19 [PATCH v6 0/8] iio: light: opt3001: driver cleanup Joshua Crofts
` (4 preceding siblings ...)
2026-06-14 13:19 ` [PATCH v6 5/8] iio: light: opt3001: localize for loop iterator Joshua Crofts
@ 2026-06-14 13:19 ` Joshua Crofts
2026-06-14 13:19 ` [PATCH v6 7/8] iio: light: opt3001: switch driver to managed resources Joshua Crofts
` (2 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Joshua Crofts @ 2026-06-14 13:19 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko
Cc: linux-iio, linux-kernel, Joshua Crofts, Andy Shevchenko
Move driver to use guard(mutex)() macro, to facilitate automatic
locking/unlocking of resources. This modernizes the driver and
improves code style.
While at it, remove unnecessary gotos and return variables.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Joshua Crofts <joshua.crofts1@gmail.com>
---
drivers/iio/light/opt3001.c | 61 +++++++++++++++------------------------------
1 file changed, 20 insertions(+), 41 deletions(-)
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
index 80a2ede91272..a4d626006eb3 100644
--- a/drivers/iio/light/opt3001.c
+++ b/drivers/iio/light/opt3001.c
@@ -10,6 +10,7 @@
#include <linux/array_size.h>
#include <linux/bits.h>
+#include <linux/cleanup.h>
#include <linux/delay.h>
#include <linux/dev_printk.h>
#include <linux/errno.h>
@@ -477,7 +478,6 @@ static int opt3001_read_raw(struct iio_dev *iio,
int *val, int *val2, long mask)
{
struct opt3001 *opt = iio_priv(iio);
- int ret;
if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
return -EBUSY;
@@ -485,23 +485,17 @@ static int opt3001_read_raw(struct iio_dev *iio,
if (chan->type != opt->chip_info->chan_type)
return -EINVAL;
- mutex_lock(&opt->lock);
+ guard(mutex)(&opt->lock);
switch (mask) {
case IIO_CHAN_INFO_RAW:
case IIO_CHAN_INFO_PROCESSED:
- ret = opt3001_get_processed(opt, val, val2);
- break;
+ return opt3001_get_processed(opt, val, val2);
case IIO_CHAN_INFO_INT_TIME:
- ret = opt3001_get_int_time(opt, val, val2);
- break;
+ return opt3001_get_int_time(opt, val, val2);
default:
- ret = -EINVAL;
+ return -EINVAL;
}
-
- mutex_unlock(&opt->lock);
-
- return ret;
}
static int opt3001_write_raw(struct iio_dev *iio,
@@ -509,7 +503,6 @@ static int opt3001_write_raw(struct iio_dev *iio,
int val, int val2, long mask)
{
struct opt3001 *opt = iio_priv(iio);
- int ret;
if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
return -EBUSY;
@@ -523,11 +516,9 @@ static int opt3001_write_raw(struct iio_dev *iio,
if (val != 0)
return -EINVAL;
- mutex_lock(&opt->lock);
- ret = opt3001_set_int_time(opt, val2);
- mutex_unlock(&opt->lock);
+ guard(mutex)(&opt->lock);
- return ret;
+ return opt3001_set_int_time(opt, val2);
}
static int opt3001_read_event_value(struct iio_dev *iio,
@@ -538,26 +529,21 @@ static int opt3001_read_event_value(struct iio_dev *iio,
int *val, int *val2)
{
struct opt3001 *opt = iio_priv(iio);
- int ret = IIO_VAL_INT_PLUS_MICRO;
- mutex_lock(&opt->lock);
+ guard(mutex)(&opt->lock);
switch (dir) {
case IIO_EV_DIR_RISING:
opt3001_to_iio_ret(opt, opt->high_thresh_exp,
opt->high_thresh_mantissa, val, val2);
- break;
+ return IIO_VAL_INT_PLUS_MICRO;
case IIO_EV_DIR_FALLING:
opt3001_to_iio_ret(opt, opt->low_thresh_exp,
opt->low_thresh_mantissa, val, val2);
- break;
+ return IIO_VAL_INT_PLUS_MICRO;
default:
- ret = -EINVAL;
+ return -EINVAL;
}
-
- mutex_unlock(&opt->lock);
-
- return ret;
}
static int opt3001_write_event_value(struct iio_dev *iio,
@@ -584,12 +570,12 @@ static int opt3001_write_event_value(struct iio_dev *iio,
if (val < 0)
return -EINVAL;
- mutex_lock(&opt->lock);
+ guard(mutex)(&opt->lock);
ret = opt3001_find_scale(opt, val, val2, &exponent);
if (ret < 0) {
dev_err(dev, "can't find scale for %d.%06u\n", val, val2);
- goto err;
+ return ret;
}
whole = opt->chip_info->factor_whole;
@@ -612,20 +598,16 @@ static int opt3001_write_event_value(struct iio_dev *iio,
opt->low_thresh_exp = exponent;
break;
default:
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
ret = i2c_smbus_write_word_swapped(client, reg, value);
if (ret < 0) {
dev_err(dev, "failed to write register %02x\n", reg);
- goto err;
+ return ret;
}
-err:
- mutex_unlock(&opt->lock);
-
- return ret;
+ return 0;
}
static int opt3001_read_event_config(struct iio_dev *iio,
@@ -657,7 +639,7 @@ static int opt3001_write_event_config(struct iio_dev *iio,
if (!state && opt->mode == OPT3001_CONFIGURATION_M_SHUTDOWN)
return 0;
- mutex_lock(&opt->lock);
+ guard(mutex)(&opt->lock);
mode = state ? OPT3001_CONFIGURATION_M_CONTINUOUS
: OPT3001_CONFIGURATION_M_SHUTDOWN;
@@ -666,7 +648,7 @@ static int opt3001_write_event_config(struct iio_dev *iio,
if (ret < 0) {
dev_err(dev, "failed to read register %02x\n",
OPT3001_CONFIGURATION);
- goto err;
+ return ret;
}
reg = ret;
@@ -676,13 +658,10 @@ static int opt3001_write_event_config(struct iio_dev *iio,
if (ret < 0) {
dev_err(dev, "failed to write register %02x\n",
OPT3001_CONFIGURATION);
- goto err;
+ return ret;
}
-err:
- mutex_unlock(&opt->lock);
-
- return ret;
+ return 0;
}
static const struct iio_info opt3001_info = {
--
2.54.0
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH v6 7/8] iio: light: opt3001: switch driver to managed resources
2026-06-14 13:19 [PATCH v6 0/8] iio: light: opt3001: driver cleanup Joshua Crofts
` (5 preceding siblings ...)
2026-06-14 13:19 ` [PATCH v6 6/8] iio: light: opt3001: move driver to guard(mutex)() use Joshua Crofts
@ 2026-06-14 13:19 ` Joshua Crofts
2026-06-14 13:19 ` [PATCH v6 8/8] iio: light: opt3001: add comment to mutex Joshua Crofts
2026-06-21 14:50 ` [PATCH v6 0/8] iio: light: opt3001: driver cleanup Jonathan Cameron
8 siblings, 0 replies; 12+ messages in thread
From: Joshua Crofts @ 2026-06-14 13:19 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko
Cc: linux-iio, linux-kernel, Joshua Crofts
Move the driver to use devm_* functions to automate resource
management and simplify error handling. This also allows removal
of the opt3001_remove() function.
Signed-off-by: Joshua Crofts <joshua.crofts1@gmail.com>
---
drivers/iio/light/opt3001.c | 88 ++++++++++++++++++++-------------------------
1 file changed, 38 insertions(+), 50 deletions(-)
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
index a4d626006eb3..b657aa88c1b4 100644
--- a/drivers/iio/light/opt3001.c
+++ b/drivers/iio/light/opt3001.c
@@ -703,6 +703,30 @@ static int opt3001_read_id(struct opt3001 *opt)
return 0;
}
+static void opt3001_power_off(void *data)
+{
+ struct opt3001 *opt = data;
+ struct i2c_client *client = opt->client;
+ struct device *dev = &client->dev;
+ u16 reg_val;
+ int ret;
+
+ ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION);
+ if (ret < 0) {
+ dev_err(dev, "failed to read register %02x\n",
+ OPT3001_CONFIGURATION);
+ return;
+ }
+
+ reg_val = ret;
+ opt3001_set_mode(opt, ®_val, OPT3001_CONFIGURATION_M_SHUTDOWN);
+
+ ret = i2c_smbus_write_word_swapped(client, OPT3001_CONFIGURATION, reg_val);
+ if (ret < 0)
+ dev_err(dev, "failed to write to register %02x\n",
+ OPT3001_CONFIGURATION);
+}
+
static int opt3001_configure(struct opt3001 *opt)
{
struct i2c_client *client = opt->client;
@@ -741,6 +765,11 @@ static int opt3001_configure(struct opt3001 *opt)
return dev_err_probe(dev, ret, "failed to write register %02x\n",
OPT3001_CONFIGURATION);
+ ret = devm_add_action_or_reset(dev, opt3001_power_off, opt);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to register power off function\n");
+
ret = i2c_smbus_read_word_swapped(client, OPT3001_LOW_LIMIT);
if (ret < 0)
return dev_err_probe(dev, ret, "failed to read register %02x\n",
@@ -834,9 +863,11 @@ static int opt3001_probe(struct i2c_client *client)
opt->client = client;
opt->chip_info = i2c_get_match_data(client);
- mutex_init(&opt->lock);
+ ret = devm_mutex_init(dev, &opt->lock);
+ if (ret)
+ return ret;
+
init_waitqueue_head(&opt->result_ready_queue);
- i2c_set_clientdata(client, iio);
if (opt->chip_info->has_id) {
ret = opt3001_read_id(opt);
@@ -856,60 +887,18 @@ static int opt3001_probe(struct i2c_client *client)
/* Make use of INT pin only if valid IRQ no. is given */
if (irq > 0) {
- ret = request_threaded_irq(irq, NULL, opt3001_irq,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- "opt3001", iio);
+ ret = devm_request_threaded_irq(dev, irq, NULL, opt3001_irq,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "opt3001", iio);
if (ret)
- return dev_err_probe(dev, ret,
- "failed to request IRQ #%d\n",
- irq);
+ return ret;
opt->use_irq = true;
} else {
dev_dbg(dev, "enabling interrupt-less operation\n");
}
- ret = iio_device_register(iio);
- if (ret)
- goto free_irq;
-
- return 0;
-
-free_irq:
- if (irq > 0)
- free_irq(irq, iio);
-
- return ret;
-}
-
-static void opt3001_remove(struct i2c_client *client)
-{
- struct iio_dev *iio = i2c_get_clientdata(client);
- struct opt3001 *opt = iio_priv(iio);
- struct device *dev = &client->dev;
- int ret;
- u16 reg;
-
- iio_device_unregister(iio);
-
- if (opt->use_irq)
- free_irq(client->irq, iio);
-
- ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION);
- if (ret < 0) {
- dev_err(dev, "failed to read register %02x\n",
- OPT3001_CONFIGURATION);
- return;
- }
-
- reg = ret;
- opt3001_set_mode(opt, ®, OPT3001_CONFIGURATION_M_SHUTDOWN);
-
- ret = i2c_smbus_write_word_swapped(client, OPT3001_CONFIGURATION, reg);
- if (ret < 0) {
- dev_err(dev, "failed to write register %02x\n",
- OPT3001_CONFIGURATION);
- }
+ return devm_iio_device_register(dev, iio);
}
static const struct opt3001_chip_info opt3001_chip_information = {
@@ -950,7 +939,6 @@ MODULE_DEVICE_TABLE(of, opt3001_of_match);
static struct i2c_driver opt3001_driver = {
.probe = opt3001_probe,
- .remove = opt3001_remove,
.id_table = opt3001_id,
.driver = {
--
2.54.0
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH v6 8/8] iio: light: opt3001: add comment to mutex
2026-06-14 13:19 [PATCH v6 0/8] iio: light: opt3001: driver cleanup Joshua Crofts
` (6 preceding siblings ...)
2026-06-14 13:19 ` [PATCH v6 7/8] iio: light: opt3001: switch driver to managed resources Joshua Crofts
@ 2026-06-14 13:19 ` Joshua Crofts
2026-06-17 10:21 ` Andy Shevchenko
2026-06-21 14:50 ` [PATCH v6 0/8] iio: light: opt3001: driver cleanup Jonathan Cameron
8 siblings, 1 reply; 12+ messages in thread
From: Joshua Crofts @ 2026-06-14 13:19 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko
Cc: linux-iio, linux-kernel, Joshua Crofts, Maxwell Doose
Add comment to mutex per checkpatch.pl report. While we're at it, add
a comment to bool ok_to_ignore_lock.
No functional change.
Reviewed-by: Maxwell Doose <m32285159@gmail.com>
Signed-off-by: Joshua Crofts <joshua.crofts1@gmail.com>
---
drivers/iio/light/opt3001.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
index b657aa88c1b4..7afa0a6c1948 100644
--- a/drivers/iio/light/opt3001.c
+++ b/drivers/iio/light/opt3001.c
@@ -103,7 +103,13 @@ struct opt3001_chip_info {
struct opt3001 {
struct i2c_client *client;
+ /*
+ * Ensure data capture and read-modify-write sequences are
+ * not interrupted.
+ */
struct mutex lock;
+
+ /* Allows for IRQs to bypass locking mechanism */
bool ok_to_ignore_lock;
bool result_ready;
wait_queue_head_t result_ready_queue;
--
2.54.0
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH v6 8/8] iio: light: opt3001: add comment to mutex
2026-06-14 13:19 ` [PATCH v6 8/8] iio: light: opt3001: add comment to mutex Joshua Crofts
@ 2026-06-17 10:21 ` Andy Shevchenko
0 siblings, 0 replies; 12+ messages in thread
From: Andy Shevchenko @ 2026-06-17 10:21 UTC (permalink / raw)
To: Joshua Crofts
Cc: Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, linux-iio, linux-kernel, Maxwell Doose
On Sun, Jun 14, 2026 at 03:19:10PM +0200, Joshua Crofts wrote:
> Add comment to mutex per checkpatch.pl report. While we're at it, add
> a comment to bool ok_to_ignore_lock.
>
> No functional change.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 0/8] iio: light: opt3001: driver cleanup
2026-06-14 13:19 [PATCH v6 0/8] iio: light: opt3001: driver cleanup Joshua Crofts
` (7 preceding siblings ...)
2026-06-14 13:19 ` [PATCH v6 8/8] iio: light: opt3001: add comment to mutex Joshua Crofts
@ 2026-06-21 14:50 ` Jonathan Cameron
8 siblings, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2026-06-21 14:50 UTC (permalink / raw)
To: Joshua Crofts
Cc: David Lechner, Nuno Sá,
Andy Shevchenko, linux-iio, linux-kernel, Andy Shevchenko,
Maxwell Doose, Andy Shevchenko
On Sun, 14 Jun 2026 15:19:02 +0200
Joshua Crofts <joshua.crofts1@gmail.com> wrote:
> This series deals with cleaning up the TI OPT3001 sensor driver,
> moving it to more modern kernel practices and improving the code style.
>
> While reviewing, Jonathan Cameron (and eventually Sashiko) found a race
> condition where userspace could start interacting with the device
> before the hardware IRQ was set up.
>
> Changes include:
> - moving the driver to use devm_* functions
> - IWYU cleanups
> - removal of unnecessary macros and comments
> - using dev_err_probe() in probe and probe path functions
> - checkpatch.pl warning cleanups
> - fixing a race condition found in opt3001_probe() function
>
Series applied to the testing branch of iio.git. I'll be rebasing
that on rc1 once it is available
Thanks,
Jonathan
> ---
> Changes in v6:
> - Pull review tags
> - PATCH 2: reduce code churn
> - Reorder patches to reduce churn
> - Rebase on updated testing branch
> - Link to v5: https://lore.kernel.org/r/20260603-opt3001-cleanup-v5-0-3ef7b926d555@gmail.com
>
> Changes in v5:
> - PATCH 7: remove dead code oneliner
> - Pull new review trailers
> - Link to v4: https://lore.kernel.org/r/20260525-opt3001-cleanup-v4-0-65b36a174f78@gmail.com/
>
> Changes in v4:
> - Fix bad merge
> - Edit commit messages
> - PATCH 1: add free_irq on iio_device_register error
> - PATCH 8: change comments
> - Link to v3: https://lore.kernel.org/r/20260521-opt3001-cleanup-v3-0-820169dec8c3@gmail.com
>
> Changes in v3:
> - PATCH 1: fix build error
> - PATCH 2: remove struct device member from struct opt3001
> - PATCH 6: edit return statements
> - Pull additional trailers from previous version's reviews
> - Edit commit messages
> - Link to v2: https://lore.kernel.org/r/20260512-opt3001-cleanup-v2-0-8018cf3a8a0a@gmail.com
>
> Changes in v2:
> - PATCH 1: added patch that fixes race condition
> - PATCH 3: remove wrong usage of GENMASK()
> - PATCH 4: add patch that moves driver to use local structs
> - PATCH 5: add patch that ensures correct parenthesis alignment
> - PATCH 6: change int to unsigned int
> - PATCH 7: moved opt3001_read_id() function to use dev_err_probe()
> - PATCH 9: removed unnecessary dev_err_probe() calls, reordering
> - PATCH 10: added patch that adds a comment to mutex declaration
> - Link to v1: https://lore.kernel.org/r/20260511-opt3001-cleanup-v1-0-f7879dc3455c@gmail.com
>
> ---
> To: Jonathan Cameron <jic23@kernel.org>
> To: David Lechner <dlechner@baylibre.com>
> To: Nuno Sá <nuno.sa@analog.com>
> To: Andy Shevchenko <andy@kernel.org>
> Cc: linux-iio@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Joshua Crofts <joshua.crofts1@gmail.com>
>
> ---
> Joshua Crofts (8):
> iio: light: opt3001: move device registration to end of probe()
> iio: light: opt3001: use local struct device and i2c_client variables
> iio: light: opt3001: prefer dev_err_probe()
> iio: light: opt3001: ensure correct parenthesis alignment
> iio: light: opt3001: localize for loop iterator
> iio: light: opt3001: move driver to guard(mutex)() use
> iio: light: opt3001: switch driver to managed resources
> iio: light: opt3001: add comment to mutex
>
> drivers/iio/light/opt3001.c | 381 +++++++++++++++++++++-----------------------
> 1 file changed, 181 insertions(+), 200 deletions(-)
> ---
> base-commit: 5eff1cd0d0156240c0839921b537599ae77a2ce2
> change-id: 20260603-opt3001-cleanup-149be05f699b
>
> Best regards,
^ permalink raw reply [flat|nested] 12+ messages in thread