diff options
Diffstat (limited to 'drivers/net/wireless/ath/wil6210/pcie_bus.c')
-rw-r--r-- | drivers/net/wireless/ath/wil6210/pcie_bus.c | 97 |
1 files changed, 64 insertions, 33 deletions
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index 6a3ab4bf916d..42a5480c764d 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c @@ -21,6 +21,7 @@ #include <linux/suspend.h> #include "wil6210.h" #include <linux/rtnetlink.h> +#include <linux/pm_runtime.h> static bool use_msi = true; module_param(use_msi, bool, 0444); @@ -31,10 +32,8 @@ module_param(ftm_mode, bool, 0444); MODULE_PARM_DESC(ftm_mode, " Set factory test mode, default - false"); #ifdef CONFIG_PM -#ifdef CONFIG_PM_SLEEP static int wil6210_pm_notify(struct notifier_block *notify_block, unsigned long mode, void *unused); -#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM */ static @@ -84,9 +83,7 @@ void wil_set_capabilities(struct wil6210_priv *wil) /* extract FW capabilities from file without loading the FW */ wil_request_firmware(wil, wil->wil_fw_name, false); - - if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING, wil->fw_capabilities)) - wil_to_wiphy(wil)->signal_type = CFG80211_SIGNAL_TYPE_MBM; + wil_refresh_fw_capabilities(wil); } void wil_disable_irq(struct wil6210_priv *wil) @@ -296,15 +293,6 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) wil_set_capabilities(wil); wil6210_clear_irq(wil); - wil->keep_radio_on_during_sleep = - wil->platform_ops.keep_radio_on_during_sleep && - wil->platform_ops.keep_radio_on_during_sleep( - wil->platform_handle) && - test_bit(WMI_FW_CAPABILITY_D3_SUSPEND, wil->fw_capabilities); - - wil_info(wil, "keep_radio_on_during_sleep (%d)\n", - wil->keep_radio_on_during_sleep); - /* FW should raise IRQ when ready */ rc = wil_if_pcie_enable(wil); if (rc) { @@ -320,7 +308,6 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) } #ifdef CONFIG_PM -#ifdef CONFIG_PM_SLEEP wil->pm_notify.notifier_call = wil6210_pm_notify; rc = register_pm_notifier(&wil->pm_notify); if (rc) @@ -328,11 +315,11 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) * be prevented in a later phase if needed */ wil_err(wil, "register_pm_notifier failed: %d\n", rc); -#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM */ wil6210_debugfs_init(wil); + wil_pm_runtime_allow(wil); return 0; @@ -360,11 +347,11 @@ static void wil_pcie_remove(struct pci_dev *pdev) wil_dbg_misc(wil, "pcie_remove\n"); #ifdef CONFIG_PM -#ifdef CONFIG_PM_SLEEP unregister_pm_notifier(&wil->pm_notify); -#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM */ + wil_pm_runtime_forbid(wil); + wil6210_debugfs_remove(wil); rtnl_lock(); wil_p2p_wdev_free(wil); @@ -386,13 +373,15 @@ static const struct pci_device_id wil6210_pcie_ids[] = { MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); #ifdef CONFIG_PM -#ifdef CONFIG_PM_SLEEP static int wil6210_suspend(struct device *dev, bool is_runtime) { int rc = 0; struct pci_dev *pdev = to_pci_dev(dev); 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"); @@ -400,16 +389,18 @@ static int wil6210_suspend(struct device *dev, bool is_runtime) if (rc) goto out; - rc = wil_suspend(wil, is_runtime); + rc = wil_suspend(wil, is_runtime, keep_radio_on); if (!rc) { - wil->suspend_stats.successful_suspends++; - - /* If platform device supports keep_radio_on_during_sleep - * it will control PCIe master + /* In case radio stays on, platform device will control + * PCIe master */ - if (!wil->keep_radio_on_during_sleep) + if (!keep_radio_on) { /* disable bus mastering */ pci_clear_master(pdev); + wil->suspend_stats.r_off.successful_suspends++; + } else { + wil->suspend_stats.r_on.successful_suspends++; + } } out: return rc; @@ -420,23 +411,32 @@ static int wil6210_resume(struct device *dev, bool is_runtime) int rc = 0; struct pci_dev *pdev = to_pci_dev(dev); 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"); - /* If platform device supports keep_radio_on_during_sleep it will - * control PCIe master + /* In case radio stays on, platform device will control + * PCIe master */ - if (!wil->keep_radio_on_during_sleep) + if (!keep_radio_on) /* allow master */ pci_set_master(pdev); - rc = wil_resume(wil, is_runtime); + rc = wil_resume(wil, is_runtime, keep_radio_on); if (rc) { wil_err(wil, "device failed to resume (%d)\n", rc); - wil->suspend_stats.failed_resumes++; - if (!wil->keep_radio_on_during_sleep) + if (!keep_radio_on) { pci_clear_master(pdev); + wil->suspend_stats.r_off.failed_resumes++; + } else { + wil->suspend_stats.r_on.failed_resumes++; + } } else { - wil->suspend_stats.successful_resumes++; + if (keep_radio_on) + wil->suspend_stats.r_on.successful_resumes++; + else + wil->suspend_stats.r_off.successful_resumes++; } return rc; @@ -490,12 +490,43 @@ static int wil6210_pm_resume(struct device *dev) { return wil6210_resume(dev, false); } -#endif /* CONFIG_PM_SLEEP */ +static int wil6210_pm_runtime_idle(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct wil6210_priv *wil = pci_get_drvdata(pdev); + + wil_dbg_pm(wil, "Runtime idle\n"); + + return wil_can_suspend(wil, true); +} + +static int wil6210_pm_runtime_resume(struct device *dev) +{ + return wil6210_resume(dev, true); +} + +static int wil6210_pm_runtime_suspend(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct wil6210_priv *wil = pci_get_drvdata(pdev); + + if (test_bit(wil_status_suspended, wil->status)) { + wil_dbg_pm(wil, "trying to suspend while suspended\n"); + return 1; + } + + return wil6210_suspend(dev, true); +} #endif /* CONFIG_PM */ static const struct dev_pm_ops wil6210_pm_ops = { +#ifdef CONFIG_PM SET_SYSTEM_SLEEP_PM_OPS(wil6210_pm_suspend, wil6210_pm_resume) + SET_RUNTIME_PM_OPS(wil6210_pm_runtime_suspend, + wil6210_pm_runtime_resume, + wil6210_pm_runtime_idle) +#endif /* CONFIG_PM */ }; static struct pci_driver wil6210_driver = { |