All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Manaf Meethalavalappu Pallikunhi" <manaf.pallikunhi@oss.qualcomm.com>
Cc: mfd@lists.linux.dev, devicetree@vger.kernel.org, robh@kernel.org,
	linux-hwmon@vger.kernel.org, conor+dt@kernel.org, lee@kernel.org
Subject: Re: [PATCH v2 02/10] hwmon: Add Qualcomm PMIC BCL driver
Date: Tue, 21 Jul 2026 19:20:47 +0000	[thread overview]
Message-ID: <20260721192047.76EA01F00A3D@smtp.kernel.org> (raw)
In-Reply-To: <20260722-qcom-bcl-hwmon-v2-2-febe2805e17b@oss.qualcomm.com>

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] Uninitialized cache timestamps cause the driver to erroneously return cached 0 readings instead of hardware values for the first 5 minutes of system uptime.
- [High] Writing the maximum valid threshold value to certain sysfs attributes causes integer truncation when written to the hardware register, silently applying a dangerously low or zero limit.
- [Medium] Devres teardown ordering race allows the delayed polling work to re-enable `irq_wake` after it was disabled, causing an unbalanced wake count and triggering a kernel warning on driver unbind.
- [Medium] pmh0101_data is missing `.data_field_bits_size`, preventing voltage input readings from being exposed.
- [Low] Using `DIV_ROUND_CLOSEST` with a 64-bit signed dividend causes a link error on 32-bit architectures.
--

--- Patch [2]: [PATCH v2 02/10] hwmon: Add Qualcomm PMIC BCL driver ---
commit d1c02d33d76b0d05ddfd0d17bd163dd47036945c
Author: Manaf Meethalavalappu Pallikunhi <manaf.pallikunhi@oss.qualcomm.com>
Subject: hwmon: Add Qualcomm PMIC BCL driver

This commit adds a new driver for Qualcomm SPMI PMIC Battery Current Limiting
(BCL). It exposes battery voltage and current monitoring through the hwmon
interface, including threshold-based alarms and interrupt notifications.

> diff --git a/drivers/hwmon/qcom-bcl-hwmon.c b/drivers/hwmon/qcom-bcl-hwmon.c
> new file mode 100644
> index 0000000000000..a21433b45482c
> --- /dev/null
> +++ b/drivers/hwmon/qcom-bcl-hwmon.c

[ ... ]

> +static const struct bcl_desc pmh0101_data = {
> +	.reg_fields = bcl_pmh0101_reg_fields,
> +	.num_reg_fields = F_CURR_MON_EN + 1,
> +	.thresh_field_bits_size = 8,
> +	.battery_config_field = REG_FIELD(0, 0, 0),
> +	.channel_cfg[BCL_BATT_1S][CHANNEL_IN] = {

[Severity: Medium]
Is the pmh0101_data descriptor missing a .data_field_bits_size initialization?

This descriptor defines F_IN_INPUT and F_IN_INPUT1 for 16-bit reads but
omits .data_field_bits_size. Since it zero-initializes to 0,
bcl_build_hwmon_info() will treat the input reading feature as disabled and
skip initializing the sensor, hiding the hardware functionality.

[ ... ]

> +static int bcl_convert_raw_to_milliunit(const struct bcl_device *bcl,
> +					s32 raw_val,
> +					enum bcl_channel type,
> +					u8 field_width)
> +{
> +	const struct bcl_desc *desc = bcl->desc;
> +	u32 def_scale = desc->channel_cfg[bcl->batt_config][type].default_scale_nu;
> +	u32 scaling_factor = (field_width > 8) ? def_scale : (def_scale << field_width);
> +
> +	return DIV_ROUND_CLOSEST((s64)raw_val * scaling_factor, 1000000);
> +}

[Severity: Low]
Will this cause a build failure on 32-bit architectures?

Using DIV_ROUND_CLOSEST with a 64-bit signed dividend utilizes the standard
division operator, which translates to a 64-bit signed division instruction.
Since the kernel does not implement __divdi3 for 32-bit architectures,
should div_s64() be used instead to prevent link errors?

[ ... ]

> +static int bcl_curr_thresh_write(struct bcl_device *bcl, long value, enum bcl_limit_alarm lvl)
> +{
> +	const struct bcl_desc *desc = bcl->desc;
> +	u32 raw_val;
> +
> +	int thresh = clamp_val(value, 0, desc->channel_cfg[bcl->batt_config][CHANNEL_CURR].max);
> +
> +	if (desc->channel_cfg[bcl->batt_config][CHANNEL_CURR].thresh_type[lvl] == THRESH_TYPE_ADC)
> +		raw_val = bcl_convert_milliunit_to_raw(bcl, thresh, CHANNEL_CURR,
> +						       desc->thresh_field_bits_size);
> +	else
> +		raw_val = bcl_convert_milliunit_to_index(bcl, thresh, CHANNEL_CURR);
> +
> +	return regmap_field_write(bcl->fields[F_CURR_H0_THR + lvl], raw_val);
> +}

[Severity: High]
Can writing the maximum valid threshold value to the sysfs attributes cause
integer truncation when written to the hardware register?

For the pm7250b_data variant, the maximum threshold is set to 10000, which
translates to a raw value of 256. When regmap_field_write() writes this to
an 8-bit field, it gets masked to 0, silently applying a 0 mA threshold
instead of the maximum.

Similarly for smb2360_data, the max voltage is 8400, which translates to
index 78. This masks to 14 in a 6-bit field, setting a 5200mV threshold.
Could the driver verify the value fits in the destination regmap field
before writing?

[ ... ]

> +static int bcl_curr_input_read(struct bcl_device *bcl, long *out)
> +{
> +	int ret;
> +	u32 raw_val = 0, msb = 0;
> +	s32 signed_val;
> +	const struct bcl_desc *desc = bcl->desc;
> +
> +	/* Return cached value if read too soon after last update */
> +	if (time_before(jiffies, bcl->last_curr_updated + HZ)) {
> +		*out = bcl->last_curr_input;
> +		return 0;
> +	}

[Severity: High]
Will this erroneously return cached 0 readings for the first 5 minutes of
system uptime?

The last_curr_updated timestamp is zero-initialized by devm_kzalloc(). The
kernel initializes jiffies to INITIAL_JIFFIES (typically 5 minutes before
wrap-around, e.g., -300 * HZ). Due to unsigned wrap-around comparison
semantics, time_before(jiffies, bcl->last_curr_updated + HZ) will evaluate
to true until jiffies reaches HZ.

This causes the driver to bypass hardware reads entirely and return the
uninitialized 0 value across all channels.

[ ... ]

> +static int bcl_alarm_irq_init(struct platform_device *pdev,
> +			      struct bcl_device *bcl)
> +{

[ ... ]

> +		ret = devm_request_threaded_irq(&pdev->dev, irq_num, NULL,
> +						bcl_handle_alarm, IRQF_ONESHOT,
> +						bcl_int_names[i], alarm);
> +		if (ret)
> +			return ret;
> +
> +		ret = devm_add_action_or_reset(&pdev->dev, bcl_alarm_work_cleanup_action,
> +					       alarm);
> +		if (ret)
> +			return ret;
> +
> +		if (!enable_irq_wake(irq_num))
> +			alarm->irq_wake_enabled = true;
> +
> +		ret = devm_add_action_or_reset(&pdev->dev, bcl_alarm_wake_cleanup_action,
> +					       alarm);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}

[Severity: Medium]
Does this devres teardown ordering allow the delayed polling work to
re-enable irq_wake after it was already disabled?

Since bcl_alarm_work_cleanup_action is registered before
bcl_alarm_wake_cleanup_action, the LIFO teardown executes the wake cleanup
first, disabling irq_wake.

Concurrently, the uncancelled alarm_poll_work can race to execute
bcl_alarm_enable_poll() and re-enable irq_wake before the work cleanup
action runs to cancel the work queue. Could this cause an unbalanced wake
count and trigger a kernel warning on driver unbind?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260722-qcom-bcl-hwmon-v2-0-febe2805e17b@oss.qualcomm.com?part=2

  reply	other threads:[~2026-07-21 19:20 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-21 18:30 [PATCH v2 00/10] hwmon: Add Qualcomm SPMI BCL driver Manaf Meethalavalappu Pallikunhi
2026-07-21 18:30 ` [PATCH v2 01/10] dt-bindings: hwmon: Describe Qualcomm BCL hardware Manaf Meethalavalappu Pallikunhi
2026-07-21 18:36   ` sashiko-bot
2026-07-21 18:30 ` [PATCH v2 02/10] hwmon: Add Qualcomm PMIC BCL driver Manaf Meethalavalappu Pallikunhi
2026-07-21 19:20   ` sashiko-bot [this message]
2026-07-21 20:44   ` Guenter Roeck
2026-07-22 17:38     ` Manaf Meethalavalappu Pallikunhi
2026-07-22 17:46       ` Guenter Roeck
2026-07-22 18:19         ` Manaf Meethalavalappu Pallikunhi
2026-07-22 18:59           ` Guenter Roeck
2026-07-21 18:30 ` [PATCH v2 03/10] arm64: dts: qcom: pm7250b: Enable BCL sensor node Manaf Meethalavalappu Pallikunhi
2026-07-21 19:13   ` sashiko-bot
2026-07-21 18:30 ` [PATCH v2 04/10] arm64: dts: qcom: hamoa-pmic: " Manaf Meethalavalappu Pallikunhi
2026-07-21 18:37   ` sashiko-bot
2026-07-21 18:30 ` [PATCH v2 05/10] arm64: dts: qcom: pm8350c: " Manaf Meethalavalappu Pallikunhi
2026-07-21 19:14   ` sashiko-bot
2026-07-21 18:30 ` [PATCH v2 06/10] arm64: dts: qcom: pmh0101: " Manaf Meethalavalappu Pallikunhi
2026-07-21 19:17   ` sashiko-bot
2026-07-21 18:30 ` [PATCH v2 07/10] arm64: dts: qcom: pm8550: " Manaf Meethalavalappu Pallikunhi
2026-07-21 19:14   ` sashiko-bot
2026-07-21 18:30 ` [PATCH v2 08/10] arm64: dts: qcom: pmih0108-kaanapali: " Manaf Meethalavalappu Pallikunhi
2026-07-21 19:17   ` sashiko-bot
2026-07-21 18:30 ` [PATCH v2 09/10] arm64: dts: qcom: pmih0108: " Manaf Meethalavalappu Pallikunhi
2026-07-21 19:16   ` sashiko-bot
2026-07-21 18:30 ` [PATCH v2 10/10] arm64: dts: qcom: smb2370: " Manaf Meethalavalappu Pallikunhi
2026-07-21 19:17   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260721192047.76EA01F00A3D@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=lee@kernel.org \
    --cc=linux-hwmon@vger.kernel.org \
    --cc=manaf.pallikunhi@oss.qualcomm.com \
    --cc=mfd@lists.linux.dev \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.