mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 19:29:37 +00:00
remoteproc: qcom_q6v5_mss: fix q6v5_probe() error paths
If an error occurs in q6v5_probe() after the proxy power domains are attached, but before qcom_add_ipa_notify_subdev() is called, qcom_remove_ipa_notify_subdev() is called in the error path, which is a bug. Fix this by having that call be reached through a different label. Additionally, if qcom_add_sysmon_subdev() returns an error, the subdevs that had already been added will not be properly removed. Fix this by having the added subdevs (including the IPA notify one) be removed in this case. Finally, arrange for the sysmon subdev to be removed before the rest in the event rproc_add() returns an error. Have cleanup activity done in q6v5_remove() be done in the reverse order they are set up in q6v5_probe() (the same order they're done in the q6v5_probe() error path). Use a local variable for the remoteproc pointer, which is used repeatedly. Remove errant semicolons at the end of two function blocks. Signed-off-by: Alex Elder <elder@linaro.org> Link: https://lore.kernel.org/r/20200403175005.17130-4-elder@linaro.org Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
This commit is contained in:
parent
13c060b50a
commit
5839681002
1 changed files with 19 additions and 12 deletions
|
@ -367,7 +367,7 @@ static int q6v5_pds_enable(struct q6v5 *qproc, struct device **pds,
|
|||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
static void q6v5_pds_disable(struct q6v5 *qproc, struct device **pds,
|
||||
size_t pd_count)
|
||||
|
@ -1527,7 +1527,7 @@ static int q6v5_pds_attach(struct device *dev, struct device **devs,
|
|||
dev_pm_domain_detach(devs[i], false);
|
||||
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
static void q6v5_pds_detach(struct q6v5 *qproc, struct device **pds,
|
||||
size_t pd_count)
|
||||
|
@ -1766,17 +1766,23 @@ static int q6v5_probe(struct platform_device *pdev)
|
|||
qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
|
||||
if (IS_ERR(qproc->sysmon)) {
|
||||
ret = PTR_ERR(qproc->sysmon);
|
||||
goto detach_proxy_pds;
|
||||
goto remove_subdevs;
|
||||
}
|
||||
|
||||
ret = rproc_add(rproc);
|
||||
if (ret)
|
||||
goto detach_proxy_pds;
|
||||
goto remove_sysmon_subdev;
|
||||
|
||||
return 0;
|
||||
|
||||
detach_proxy_pds:
|
||||
remove_sysmon_subdev:
|
||||
qcom_remove_sysmon_subdev(qproc->sysmon);
|
||||
remove_subdevs:
|
||||
qcom_remove_ipa_notify_subdev(qproc->rproc, &qproc->ipa_notify_subdev);
|
||||
qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
|
||||
qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
|
||||
qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
|
||||
detach_proxy_pds:
|
||||
q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count);
|
||||
detach_active_pds:
|
||||
q6v5_pds_detach(qproc, qproc->active_pds, qproc->active_pd_count);
|
||||
|
@ -1789,19 +1795,20 @@ static int q6v5_probe(struct platform_device *pdev)
|
|||
static int q6v5_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct q6v5 *qproc = platform_get_drvdata(pdev);
|
||||
struct rproc *rproc = qproc->rproc;
|
||||
|
||||
rproc_del(qproc->rproc);
|
||||
rproc_del(rproc);
|
||||
|
||||
qcom_remove_sysmon_subdev(qproc->sysmon);
|
||||
qcom_remove_ipa_notify_subdev(qproc->rproc, &qproc->ipa_notify_subdev);
|
||||
qcom_remove_glink_subdev(qproc->rproc, &qproc->glink_subdev);
|
||||
qcom_remove_smd_subdev(qproc->rproc, &qproc->smd_subdev);
|
||||
qcom_remove_ssr_subdev(qproc->rproc, &qproc->ssr_subdev);
|
||||
qcom_remove_ipa_notify_subdev(rproc, &qproc->ipa_notify_subdev);
|
||||
qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
|
||||
qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
|
||||
qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
|
||||
|
||||
q6v5_pds_detach(qproc, qproc->active_pds, qproc->active_pd_count);
|
||||
q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count);
|
||||
q6v5_pds_detach(qproc, qproc->active_pds, qproc->active_pd_count);
|
||||
|
||||
rproc_free(qproc->rproc);
|
||||
rproc_free(rproc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue