From nobody Thu Apr 16 06:49:09 2026 Received: from mail-pl1-f169.google.com (mail-pl1-f169.google.com [209.85.214.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5EE2B30DD2A for ; Mon, 2 Mar 2026 05:26:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772429178; cv=none; b=K9R8azBWwPK6BzfTdABSI9YH0nyTn1sGoNshN82buFIvOX5fHzg0dwJrq0dILU0SAXRkxFPRxM6k/MwMItI0lqVzfW5VIMH8hf6MP8Qk7J8sQo26doocaWsmeyA9TMLz7gUtypTNg6pxHy73v06D87zcm5OGw8Ijqxe59Gx2dsk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772429178; c=relaxed/simple; bh=BShzcGQ5TSxPcPyjbcHQImaTpsxpGLqHCWEyrwfxpgM=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=P6jPnQF4ZFP6AxM2xE83DBJrcDoFRx31SU+fNa699CIlnmAcrJ09cflZgMoxTeVMKZ3ftYpkUjZUXUNUjE2RtB2+84pPzm7WPb16DluZD0AHkDwNdjPTUZn7k2Jup7kj2SdjipIx1BL83VK4GMHPODzLfBS+c+DrlqSUHUyBnrc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Cd7S0uwJ; arc=none smtp.client-ip=209.85.214.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Cd7S0uwJ" Received: by mail-pl1-f169.google.com with SMTP id d9443c01a7336-2ae50a33ff8so3352015ad.3 for ; Sun, 01 Mar 2026 21:26:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772429177; x=1773033977; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=7DjFw8npH/saWUp4S7FK0mRYY41Jcjm78Vwid4RX8Dg=; b=Cd7S0uwJ51cPqwfMGuJVVFOZ2VJwljY7WcuO2xhQPmc8cjR7eg4cFtYnoid/EdXCK8 jpWDdfp2aFvClifu94XBu1j5NPBFKc2VFFEHdjFSxflwAfT8XafXfp6xnI2gxYfw+87g VjHmV+f95vEhSIgYvT8AtwlKhjL8L7LzsEyLjPTIh2Xlho1aZjtWdZfdCZ3r2SmjDr0c ZgGU3QcZsv3RBk8BTssWIyexVdgdzaytGne5ebiW9ELE1tZiMObZvc9SaD31nvEMd6cP NYj5Gn3nHescv9dL02T/D9NdRGRz2xr17eYRsVNRlTYlCOqHRI3QAwUx7srKE6Qz6h5a m+MQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772429177; x=1773033977; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=7DjFw8npH/saWUp4S7FK0mRYY41Jcjm78Vwid4RX8Dg=; b=NQhP28IG5BwenbrZil1rE2OEa+gN9HG7nm9a5AcEpXL822EnBqccTDXSunmkcmhb8r fj0g2mGdSyxOlEnaFXcaW+RJ+GHkUNadxqtFzPG/LdGuASJjZR9ApKBt5/h5hzdeQ41N RlE4fJnQ28XVtN5YpMKjl1no1vw0lSVqLZkLw0N/dOBGCRb/N4oSzcwZyK3W4PYqYCMG KvFdtg5zqcURkcboaO8WTCuG53n+Qmf9L18oR37j16h0HKrNlCSRIhd9pEqyxUN+U8Fh I6WSUbXYIt8joD1+S0ageMcH4oWU/mHlCKbCBpifstuYywb+b1+n20jIZX1Zzlklg5Wh j3ug== X-Forwarded-Encrypted: i=1; AJvYcCVXCI1InsTNQiH3CP0NHcML2QE0qE8NJzYhBA4Qp37QsGLcBxsdLMMVeius8QLAL04++NiBRVYOj1TTGR4=@vger.kernel.org X-Gm-Message-State: AOJu0YyzTNM7EvgnhENQdOxaqS2GSMfleXCYlLJpgZl6FA88ZGWBoJIO CKN+06K72ZHAV4ksUMMcDAuJkgZmtum6hJmMlN1yWpC90qKRWwDfejFq X-Gm-Gg: ATEYQzwV7szNy/LD9k84k40dpUqrp/qG9hWNuIEo3e0cAegRGGXPKFjHSYdVaTmNUCD cv6b2ysU7yNqjWQF/VRMe6OlK5mrjf6harDLYKywzqI/ULCfycEBE0KiMrsc0TePzvuUxoSPshK mzt33lMpydfjZlbUvc6Xsr5NOIcmLYOkoh3LlcfIfm56VxDdZ5ntKg8N6g3ziHmYKr3ZpHjzEXX fy/xlOKT2hjFzRYUtJcOrNzmUM4VRsQ8mK7OGDqYxflm8+bicGsNWt8F31FmAWRSdzL2DSvQCD1 DfF0Uha26lUjMKQ2ZXMndNZ3JOuJVfZYO3VVK28FXaVqSKZydp4yiEbMqUeoyUpjdqGw73wX8cp wXJTlq4/JynGXWbXCPyiAMKvzNEl+yimtbeM+Z3ipFz2XpozpMWnhDm8PDCB8O1KZklJoJTr4lU 0l3o4ehsk+rp0GZw7HdATQf2urnPrs/Vn+KSef64gVpw== X-Received: by 2002:a17:903:1250:b0:2a7:cb46:706e with SMTP id d9443c01a7336-2ae2e47e0b7mr107067965ad.35.1772429176483; Sun, 01 Mar 2026 21:26:16 -0800 (PST) Received: from debian.ari ([152.58.177.124]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2ae4f945985sm24692575ad.71.2026.03.01.21.26.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 01 Mar 2026 21:26:16 -0800 (PST) From: Archit Anant To: jic23@kernel.org, dlechner@baylibre.com Cc: lars@metafoo.de, Michael.Hennerich@analog.com, nuno.sa@analog.com, andy@kernel.org, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, Archit Anant Subject: [PATCH v2] iio: adc: ad799x: convert to fully managed resources Date: Mon, 2 Mar 2026 10:55:59 +0530 Message-Id: <20260302052559.19494-1-architanant5@gmail.com> X-Mailer: git-send-email 2.39.5 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Refactor the driver to use device-managed allocations and actions, allowing for the complete removal of the ad799x_remove() function and simplifying the error paths in probe(). Key changes: - Replace the dynamic rx_buf allocation with a fixed-size, DMA-safe buffer using IIO_DECLARE_DMA_BUFFER_WITH_TS() in the state struct. This avoids memory leaks during scan mode updates and removes the need for manual kfree(). - Cache the VCC and VREF voltages in the state structure during probe() to avoid querying the regulator API during fast-path read_raw() calls. - Use devm_add_action_or_reset() to register regulator_disable() callbacks for both VCC and VREF regulators. - Convert iio_triggered_buffer_setup() and iio_device_register() to their devm_ variants, ensuring safe, reverse-order unwinding. Signed-off-by: Archit Anant --- Changes in v2: - Refactored entire resource management to eliminate remove() function based on feedback from David Lechner and Jonathan Cameron. - Cached voltages to prevent mixing manual regulator disables with devm-managed device unregistration. drivers/iio/adc/ad799x.c | 83 +++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c index 108bb22162ef..4a3db6f0a8d8 100644 --- a/drivers/iio/adc/ad799x.c +++ b/drivers/iio/adc/ad799x.c @@ -39,6 +39,7 @@ #include =20 #define AD799X_CHANNEL_SHIFT 4 +#define AD799X_MAX_CHANNELS 8 =20 /* * AD7991, AD7995 and AD7999 defines @@ -133,8 +134,12 @@ struct ad799x_state { unsigned int id; u16 config; =20 - u8 *rx_buf; unsigned int transfer_size; + + int vcc_uv; + int vref_uv; + + IIO_DECLARE_DMA_BUFFER_WITH_TS(__be16, rx_buf, AD799X_MAX_CHANNELS); }; =20 static int ad799x_write_config(struct ad799x_state *st, u16 val) @@ -217,11 +222,11 @@ static irqreturn_t ad799x_trigger_handler(int irq, vo= id *p) } =20 b_sent =3D i2c_smbus_read_i2c_block_data(st->client, - cmd, st->transfer_size, st->rx_buf); + cmd, st->transfer_size, (u8 *)st->rx_buf); if (b_sent < 0) goto out; =20 - iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf, + iio_push_to_buffers_with_timestamp(indio_dev, &st->rx_buf, iio_get_time_ns(indio_dev)); out: iio_trigger_notify_done(indio_dev->trig); @@ -234,11 +239,6 @@ static int ad799x_update_scan_mode(struct iio_dev *ind= io_dev, { struct ad799x_state *st =3D iio_priv(indio_dev); =20 - kfree(st->rx_buf); - st->rx_buf =3D kmalloc(indio_dev->scan_bytes, GFP_KERNEL); - if (!st->rx_buf) - return -ENOMEM; - st->transfer_size =3D bitmap_weight(scan_mask, iio_get_masklength(indio_dev)) * 2; =20 @@ -307,9 +307,9 @@ static int ad799x_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: if (st->vref) - ret =3D regulator_get_voltage(st->vref); + ret =3D st->vref_uv; else - ret =3D regulator_get_voltage(st->reg); + ret =3D st->vcc_uv; =20 if (ret < 0) return ret; @@ -781,6 +781,13 @@ static const struct ad799x_chip_info ad799x_chip_info_= tbl[] =3D { }, }; =20 +static void ad799x_reg_disable(void *data) +{ + struct regulator *reg =3D data; + + regulator_disable(reg); +} + static int ad799x_probe(struct i2c_client *client) { const struct i2c_device_id *id =3D i2c_client_get_device_id(client); @@ -813,6 +820,14 @@ static int ad799x_probe(struct i2c_client *client) ret =3D regulator_enable(st->reg); if (ret) return ret; + ret =3D devm_add_action_or_reset(&client->dev, ad799x_reg_disable, st->re= g); + if (ret) + return ret; + + ret =3D regulator_get_voltage(st->reg); + if (ret < 0) + return ret; + st->vcc_uv =3D ret; =20 /* check if an external reference is supplied */ if (chip_info->has_vref) { @@ -820,7 +835,7 @@ static int ad799x_probe(struct i2c_client *client) ret =3D PTR_ERR_OR_ZERO(st->vref); if (ret) { if (ret !=3D -ENODEV) - goto error_disable_reg; + return ret; st->vref =3D NULL; dev_info(&client->dev, "Using VCC reference voltage\n"); } @@ -830,7 +845,14 @@ static int ad799x_probe(struct i2c_client *client) extra_config |=3D AD7991_REF_SEL; ret =3D regulator_enable(st->vref); if (ret) - goto error_disable_reg; + return ret; + ret =3D devm_add_action_or_reset(&client->dev, ad799x_reg_disable, st->= vref); + if (ret) + return ret; + ret =3D regulator_get_voltage(st->vref); + if (ret < 0) + return ret; + st->vref_uv =3D ret; } } =20 @@ -845,12 +867,12 @@ static int ad799x_probe(struct i2c_client *client) =20 ret =3D ad799x_update_config(st, st->chip_config->default_config | extra_= config); if (ret) - goto error_disable_vref; + return ret; =20 - ret =3D iio_triggered_buffer_setup(indio_dev, NULL, + ret =3D devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL, &ad799x_trigger_handler, NULL); if (ret) - goto error_disable_vref; + return ret; =20 if (client->irq > 0) { ret =3D devm_request_threaded_irq(&client->dev, @@ -862,40 +884,16 @@ static int ad799x_probe(struct i2c_client *client) client->name, indio_dev); if (ret) - goto error_cleanup_ring; + return ret; } =20 mutex_init(&st->lock); =20 - ret =3D iio_device_register(indio_dev); + ret =3D devm_iio_device_register(&client->dev, indio_dev); if (ret) - goto error_cleanup_ring; + return ret; =20 return 0; - -error_cleanup_ring: - iio_triggered_buffer_cleanup(indio_dev); -error_disable_vref: - if (st->vref) - regulator_disable(st->vref); -error_disable_reg: - regulator_disable(st->reg); - - return ret; -} - -static void ad799x_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev =3D i2c_get_clientdata(client); - struct ad799x_state *st =3D iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - iio_triggered_buffer_cleanup(indio_dev); - if (st->vref) - regulator_disable(st->vref); - regulator_disable(st->reg); - kfree(st->rx_buf); } =20 static int ad799x_suspend(struct device *dev) @@ -965,7 +963,6 @@ static struct i2c_driver ad799x_driver =3D { .pm =3D pm_sleep_ptr(&ad799x_pm_ops), }, .probe =3D ad799x_probe, - .remove =3D ad799x_remove, .id_table =3D ad799x_id, }; module_i2c_driver(ad799x_driver); --=20 2.39.5