mirror of
https://github.com/torvalds/linux.git
synced 2026-07-29 10:41:49 +02:00
PCI: qcom: Set max OPP before DBI access during resume
During resume, qcom_pcie_icc_opp_update() may access DBI registers before
the OPP votes are restored, triggering NoC errors.
Set the PCIe controller to the maximum OPP first in resume_noirq(), then
proceed with link/DBI accesses. The OPP is later updated again based on
the actual link bandwidth requirements.
Introduce a helper to reuse the max-OPP setup code and share it with
probe().
Fixes: 5b6272e0ef ("PCI: qcom: Add OPP support to scale performance")
Signed-off-by: Qiang Yu <qiang.yu@oss.qualcomm.com>
[mani: commit log and error log rewording]
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Link: https://patch.msgid.link/20260416-setmaxopp-v1-1-6a74e2d945a0@oss.qualcomm.com
This commit is contained in:
parent
254f49634e
commit
5dc31cd4a9
|
|
@ -1613,6 +1613,22 @@ static void qcom_pcie_icc_opp_update(struct qcom_pcie *pcie)
|
|||
}
|
||||
}
|
||||
|
||||
static int qcom_pcie_set_max_opp(struct device *dev)
|
||||
{
|
||||
unsigned long max_freq = ULONG_MAX;
|
||||
struct dev_pm_opp *opp;
|
||||
int ret;
|
||||
|
||||
opp = dev_pm_opp_find_freq_floor(dev, &max_freq);
|
||||
if (IS_ERR(opp))
|
||||
return PTR_ERR(opp);
|
||||
|
||||
ret = dev_pm_opp_set_opp(dev, opp);
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_pcie_link_transition_count(struct seq_file *s, void *data)
|
||||
{
|
||||
struct qcom_pcie *pcie = (struct qcom_pcie *)dev_get_drvdata(s->private);
|
||||
|
|
@ -1845,9 +1861,7 @@ static int qcom_pcie_probe(struct platform_device *pdev)
|
|||
struct qcom_pcie_perst *perst, *tmp_perst;
|
||||
struct qcom_pcie_port *port, *tmp_port;
|
||||
const struct qcom_pcie_cfg *pcie_cfg;
|
||||
unsigned long max_freq = ULONG_MAX;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct dev_pm_opp *opp;
|
||||
struct qcom_pcie *pcie;
|
||||
struct dw_pcie_rp *pp;
|
||||
struct resource *res;
|
||||
|
|
@ -1951,21 +1965,9 @@ static int qcom_pcie_probe(struct platform_device *pdev)
|
|||
* probe(), OPP will be updated using qcom_pcie_icc_opp_update().
|
||||
*/
|
||||
if (!ret) {
|
||||
opp = dev_pm_opp_find_freq_floor(dev, &max_freq);
|
||||
if (IS_ERR(opp)) {
|
||||
ret = PTR_ERR(opp);
|
||||
dev_err_probe(pci->dev, ret,
|
||||
"Unable to find max freq OPP\n");
|
||||
goto err_pm_runtime_put;
|
||||
} else {
|
||||
ret = dev_pm_opp_set_opp(dev, opp);
|
||||
}
|
||||
|
||||
dev_pm_opp_put(opp);
|
||||
ret = qcom_pcie_set_max_opp(dev);
|
||||
if (ret) {
|
||||
dev_err_probe(pci->dev, ret,
|
||||
"Failed to set OPP for freq %lu\n",
|
||||
max_freq);
|
||||
dev_err_probe(dev, ret, "Failed to set max OPP\n");
|
||||
goto err_pm_runtime_put;
|
||||
}
|
||||
|
||||
|
|
@ -2100,6 +2102,14 @@ static int qcom_pcie_resume_noirq(struct device *dev)
|
|||
return 0;
|
||||
|
||||
if (pm_suspend_target_state != PM_SUSPEND_MEM) {
|
||||
if (pcie->use_pm_opp) {
|
||||
ret = qcom_pcie_set_max_opp(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to set max OPP: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = icc_enable(pcie->icc_cpu);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable CPU-PCIe interconnect path: %d\n", ret);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user