remoteproc: qcom_wcnss: Fix handling the lack of PD regulators in v3

The changes introduced to handle single power domain platforms have
swapped the info pointer increment from num_pd_vregs to num_pds, which
would shift the info pointer past the end of the array for pronto-v3,
which does not list power domain regulators in vregs.

This showed up as a difference between GCC- and LLVM-compiled kernels
on SDM632 devices, where only with LLVM one would get the
"regulator request with no identifier" error, because the out-of-bounds
memory ended up being zeroed. Fix by skipping the increment when there
are more power domains than regulators.

Signed-off-by: Val Packett <val@packett.cool>
Fixes: 65991ea8a6 ("remoteproc: qcom_wcnss: Handle platforms with only single power domain")
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Fixes: 65991ea8a6 ("remoteproc: qcom_wcnss: Handle platforms with only  single power domain")
Link: https://lore.kernel.org/r/20260201210230.911220-1-val@packett.cool
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
This commit is contained in:
Val Packett 2026-02-01 17:55:03 -03:00 committed by Bjorn Andersson
parent 8c952807c2
commit 3dbc90b9c2

View File

@ -441,25 +441,31 @@ static void wcnss_release_pds(struct qcom_wcnss *wcnss)
}
static int wcnss_init_regulators(struct qcom_wcnss *wcnss,
const struct wcnss_vreg_info *info,
int num_vregs, int num_pd_vregs)
const struct wcnss_data *data)
{
const struct wcnss_vreg_info *info = data->vregs;
struct regulator_bulk_data *bulk;
size_t i, possible_pds = 0, num_vregs = data->num_vregs;
int ret;
int i;
for (i = 0; i < WCNSS_MAX_PDS; i++)
if (data->pd_names[i])
possible_pds++;
/*
* If attaching the power domains suceeded we can skip requesting
* the regulators for the power domains. For old device trees we need to
* reserve extra space to manage them through the regulator interface.
*/
if (wcnss->num_pds) {
if (possible_pds >= num_vregs) {
/* Do nothing if vregs do not include PD regulators (pronto-v3) */
} else if (wcnss->num_pds) {
info += wcnss->num_pds;
/* Handle single power domain case */
if (wcnss->num_pds < num_pd_vregs)
num_vregs += num_pd_vregs - wcnss->num_pds;
if (wcnss->num_pds < data->num_pd_vregs)
num_vregs += data->num_pd_vregs - wcnss->num_pds;
} else {
num_vregs += num_pd_vregs;
num_vregs += data->num_pd_vregs;
}
bulk = devm_kcalloc(wcnss->dev,
@ -607,8 +613,7 @@ static int wcnss_probe(struct platform_device *pdev)
if (ret && (ret != -ENODATA || !data->num_pd_vregs))
return ret;
ret = wcnss_init_regulators(wcnss, data->vregs, data->num_vregs,
data->num_pd_vregs);
ret = wcnss_init_regulators(wcnss, data);
if (ret)
goto detach_pds;