提交 680c242d 编写于 作者: L Lazar Alexei 提交者: Kalle Valo

wil6210: fix PCIe bus mastering in case of interface down

In case of interface down, radio is turned off but PCIe mastering is
not cleared.
This can cause unexpected PCIe access to the shutdown device.
Fix this by clearing PCIe mastering also in case interface is down
Signed-off-by: NLazar Alexei <qca_ailizaro@qca.qualcomm.com>
Signed-off-by: NMaya Erez <qca_merez@qca.qualcomm.com>
Signed-off-by: NKalle Valo <kvalo@qca.qualcomm.com>
上级 6804cd10
...@@ -379,6 +379,9 @@ static int wil6210_suspend(struct device *dev, bool is_runtime) ...@@ -379,6 +379,9 @@ static int wil6210_suspend(struct device *dev, bool is_runtime)
int rc = 0; int rc = 0;
struct pci_dev *pdev = to_pci_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
struct wil6210_priv *wil = pci_get_drvdata(pdev); struct wil6210_priv *wil = pci_get_drvdata(pdev);
struct net_device *ndev = wil_to_ndev(wil);
bool keep_radio_on = ndev->flags & IFF_UP &&
wil->keep_radio_on_during_sleep;
wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system"); wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system");
...@@ -386,14 +389,14 @@ static int wil6210_suspend(struct device *dev, bool is_runtime) ...@@ -386,14 +389,14 @@ static int wil6210_suspend(struct device *dev, bool is_runtime)
if (rc) if (rc)
goto out; goto out;
rc = wil_suspend(wil, is_runtime); rc = wil_suspend(wil, is_runtime, keep_radio_on);
if (!rc) { if (!rc) {
wil->suspend_stats.successful_suspends++; wil->suspend_stats.successful_suspends++;
/* If platform device supports keep_radio_on_during_sleep /* In case radio stays on, platform device will control
* it will control PCIe master * PCIe master
*/ */
if (!wil->keep_radio_on_during_sleep) if (!keep_radio_on)
/* disable bus mastering */ /* disable bus mastering */
pci_clear_master(pdev); pci_clear_master(pdev);
} }
...@@ -406,20 +409,23 @@ static int wil6210_resume(struct device *dev, bool is_runtime) ...@@ -406,20 +409,23 @@ static int wil6210_resume(struct device *dev, bool is_runtime)
int rc = 0; int rc = 0;
struct pci_dev *pdev = to_pci_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
struct wil6210_priv *wil = pci_get_drvdata(pdev); struct wil6210_priv *wil = pci_get_drvdata(pdev);
struct net_device *ndev = wil_to_ndev(wil);
bool keep_radio_on = ndev->flags & IFF_UP &&
wil->keep_radio_on_during_sleep;
wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system"); wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system");
/* If platform device supports keep_radio_on_during_sleep it will /* In case radio stays on, platform device will control
* control PCIe master * PCIe master
*/ */
if (!wil->keep_radio_on_during_sleep) if (!keep_radio_on)
/* allow master */ /* allow master */
pci_set_master(pdev); pci_set_master(pdev);
rc = wil_resume(wil, is_runtime); rc = wil_resume(wil, is_runtime, keep_radio_on);
if (rc) { if (rc) {
wil_err(wil, "device failed to resume (%d)\n", rc); wil_err(wil, "device failed to resume (%d)\n", rc);
wil->suspend_stats.failed_resumes++; wil->suspend_stats.failed_resumes++;
if (!wil->keep_radio_on_during_sleep) if (!keep_radio_on)
pci_clear_master(pdev); pci_clear_master(pdev);
} else { } else {
wil->suspend_stats.successful_resumes++; wil->suspend_stats.successful_resumes++;
......
...@@ -304,12 +304,9 @@ static int wil_resume_radio_off(struct wil6210_priv *wil) ...@@ -304,12 +304,9 @@ static int wil_resume_radio_off(struct wil6210_priv *wil)
return rc; return rc;
} }
int wil_suspend(struct wil6210_priv *wil, bool is_runtime) int wil_suspend(struct wil6210_priv *wil, bool is_runtime, bool keep_radio_on)
{ {
int rc = 0; int rc = 0;
struct net_device *ndev = wil_to_ndev(wil);
bool keep_radio_on = ndev->flags & IFF_UP &&
wil->keep_radio_on_during_sleep;
wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system"); wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system");
...@@ -332,12 +329,9 @@ int wil_suspend(struct wil6210_priv *wil, bool is_runtime) ...@@ -332,12 +329,9 @@ int wil_suspend(struct wil6210_priv *wil, bool is_runtime)
return rc; return rc;
} }
int wil_resume(struct wil6210_priv *wil, bool is_runtime) int wil_resume(struct wil6210_priv *wil, bool is_runtime, bool keep_radio_on)
{ {
int rc = 0; int rc = 0;
struct net_device *ndev = wil_to_ndev(wil);
bool keep_radio_on = ndev->flags & IFF_UP &&
wil->keep_radio_on_during_sleep;
unsigned long long suspend_time_usec = 0; unsigned long long suspend_time_usec = 0;
wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system"); wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system");
......
...@@ -1016,8 +1016,8 @@ int wil_pm_runtime_get(struct wil6210_priv *wil); ...@@ -1016,8 +1016,8 @@ int wil_pm_runtime_get(struct wil6210_priv *wil);
void wil_pm_runtime_put(struct wil6210_priv *wil); void wil_pm_runtime_put(struct wil6210_priv *wil);
int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime); int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime);
int wil_suspend(struct wil6210_priv *wil, bool is_runtime); int wil_suspend(struct wil6210_priv *wil, bool is_runtime, bool keep_radio_on);
int wil_resume(struct wil6210_priv *wil, bool is_runtime); int wil_resume(struct wil6210_priv *wil, bool is_runtime, bool keep_radio_on);
bool wil_is_wmi_idle(struct wil6210_priv *wil); bool wil_is_wmi_idle(struct wil6210_priv *wil);
int wmi_resume(struct wil6210_priv *wil); int wmi_resume(struct wil6210_priv *wil);
int wmi_suspend(struct wil6210_priv *wil); int wmi_suspend(struct wil6210_priv *wil);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册