linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
To: linux-wireless@vger.kernel.org
Cc: Luca Coelho <luciano.coelho@intel.com>,
	Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Subject: [PATCH 04/31] iwlwifi: pcie: add initial RTPM support for PCI
Date: Sun, 31 Jan 2016 13:05:59 +0200	[thread overview]
Message-ID: <1454238386-27032-4-git-send-email-emmanuel.grumbach@intel.com> (raw)
In-Reply-To: <0BA3FCBA62E2DC44AF3030971E174FB32E9F363A@hasmsx107.ger.corp.intel.com>

From: Luca Coelho <luciano.coelho@intel.com>

Add an initial implementation of runtime power management (RTPM) for
PCI devices.  With this patch, RTPM is only used when wifi is off
(i.e. the wifi interface is down).  This implementation is behind a
new Kconfig flag, IWLWIFI_PCIE_RTPM.

Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/intel/iwlwifi/Kconfig      | 12 +++++
 drivers/net/wireless/intel/iwlwifi/pcie/drv.c   | 60 +++++++++++++++++++++++--
 drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 27 +++++++++++
 3 files changed, 96 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/Kconfig b/drivers/net/wireless/intel/iwlwifi/Kconfig
index 8660677..acaaf69 100644
--- a/drivers/net/wireless/intel/iwlwifi/Kconfig
+++ b/drivers/net/wireless/intel/iwlwifi/Kconfig
@@ -99,6 +99,18 @@ config IWLWIFI_UAPSD
 
 	  If unsure, say N.
 
+config IWLWIFI_PCIE_RTPM
+       bool "Enable runtime power management mode for PCIe devices"
+       depends on IWLMVM && IWLWIFI_PCIE && PM
+       default false
+       help
+         Say Y here to enable runtime power management for PCIe
+         devices.  If enabled, the device will go into low power mode
+         when idle for a short period of time, allowing for improved
+         power saving during runtime.
+
+	 If unsure, say N.
+
 menu "Debugging Options"
 
 config IWLWIFI_DEBUG
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 6261a68..676d239 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -7,6 +7,7 @@
  *
  * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -66,6 +67,9 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/module.h>
+#ifdef CONFIG_IWLWIFI_PCIE_RTPM
+#include <linux/pm_runtime.h>
+#endif /* CONFIG_IWLWIFI_PCIE_RTPM */
 #include <linux/pci.h>
 #include <linux/pci-aspm.h>
 #include <linux/acpi.h>
@@ -623,6 +627,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (ret)
 		goto out_free_drv;
 
+#ifdef CONFIG_IWLWIFI_PCIE_RTPM
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_set_autosuspend_delay(&pdev->dev,
+					 iwlwifi_mod_params.d0i3_entry_delay);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_allow(&pdev->dev);
+#endif
 	return 0;
 
 out_free_drv:
@@ -689,15 +700,58 @@ static int iwl_pci_resume(struct device *device)
 	return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume);
+#ifdef CONFIG_IWLWIFI_PCIE_RTPM
+static int iwl_pci_runtime_suspend(struct device *device)
+{
+	struct pci_dev *pdev = to_pci_dev(device);
+	struct iwl_trans *trans = pci_get_drvdata(pdev);
+
+	IWL_DEBUG_RPM(trans, "entering runtime suspend\n");
+
+	/* For now we only allow D0I3 if the device is off */
+	if (test_bit(STATUS_DEVICE_ENABLED, &trans->status))
+		return -EBUSY;
+
+	trans->system_pm_mode = IWL_PLAT_PM_MODE_D0I3;
+
+	iwl_trans_d3_suspend(trans, false);
+
+	return 0;
+}
+
+static int iwl_pci_runtime_resume(struct device *device)
+{
+	struct pci_dev *pdev = to_pci_dev(device);
+	struct iwl_trans *trans = pci_get_drvdata(pdev);
+	enum iwl_d3_status d3_status;
+
+	IWL_DEBUG_RPM(trans, "exiting runtime suspend (resume)\n");
+
+	iwl_trans_d3_resume(trans, &d3_status, false);
+
+	trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;
+
+	return 0;
+}
+#endif /* CONFIG_IWLWIFI_PCIE_RTPM */
+
+static const struct dev_pm_ops iwl_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(iwl_pci_suspend,
+				iwl_pci_resume)
+#ifdef CONFIG_IWLWIFI_PCIE_RTPM
+	SET_RUNTIME_PM_OPS(iwl_pci_runtime_suspend,
+			   iwl_pci_runtime_resume,
+			   NULL)
+#endif /* CONFIG_IWLWIFI_PCIE_RTPM */
+};
 
 #define IWL_PM_OPS	(&iwl_dev_pm_ops)
 
-#else
+#else /* CONFIG_PM_SLEEP */
 
 #define IWL_PM_OPS	NULL
 
-#endif
+#endif /* CONFIG_PM_SLEEP */
 
 static struct pci_driver iwl_pci_driver = {
 	.name = DRV_NAME,
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index 3581096..db94fe1 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -72,6 +72,9 @@
 #include <linux/bitops.h>
 #include <linux/gfp.h>
 #include <linux/vmalloc.h>
+#ifdef CONFIG_IWLWIFI_PCIE_RTPM
+#include <linux/pm_runtime.h>
+#endif /* CONFIG_IWLWIFI_PCIE_RTPM */
 
 #include "iwl-drv.h"
 #include "iwl-trans.h"
@@ -1194,6 +1197,9 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
 	if (hw_rfkill != was_hw_rfkill)
 		iwl_trans_pcie_rf_kill(trans, hw_rfkill);
 
+#ifdef CONFIG_IWLWIFI_PCIE_RTPM
+	pm_runtime_put_sync(trans->dev);
+#endif /* CONFIG_IWLWIFI_PCIE_RTPM */
 	/* re-take ownership to prevent other users from stealing the deivce */
 	iwl_pcie_prepare_card_hw(trans);
 }
@@ -1353,6 +1359,9 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
 	/* ... rfkill can call stop_device and set it false if needed */
 	iwl_trans_pcie_rf_kill(trans, hw_rfkill);
 
+#ifdef CONFIG_IWLWIFI_PCIE_RTPM
+	pm_runtime_get_sync(trans->dev);
+#endif /* CONFIG_IWLWIFI_PCIE_RTPM */
 	return 0;
 }
 
@@ -1476,6 +1485,10 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	int i;
 
+#ifdef CONFIG_IWLWIFI_PCIE_RTPM
+	/* TODO: check if this is really needed */
+	pm_runtime_disable(trans->dev);
+#endif /* CONFIG_IWLWIFI_PCIE_RTPM */
 	synchronize_irq(trans_pcie->pci_dev->irq);
 
 	iwl_pcie_tx_free(trans);
@@ -1831,6 +1844,9 @@ void iwl_trans_pcie_ref(struct iwl_trans *trans)
 	spin_lock_irqsave(&trans_pcie->ref_lock, flags);
 	IWL_DEBUG_RPM(trans, "ref_counter: %d\n", trans_pcie->ref_count);
 	trans_pcie->ref_count++;
+#ifdef CONFIG_IWLWIFI_PCIE_RTPM
+	pm_runtime_get(&trans_pcie->pci_dev->dev);
+#endif /* CONFIG_IWLWIFI_PCIE_RTPM */
 	spin_unlock_irqrestore(&trans_pcie->ref_lock, flags);
 }
 
@@ -1849,6 +1865,11 @@ void iwl_trans_pcie_unref(struct iwl_trans *trans)
 		return;
 	}
 	trans_pcie->ref_count--;
+#ifdef CONFIG_IWLWIFI_PCIE_RTPM
+	pm_runtime_mark_last_busy(&trans_pcie->pci_dev->dev);
+	pm_runtime_put_autosuspend(&trans_pcie->pci_dev->dev);
+#endif /* CONFIG_IWLWIFI_PCIE_RTPM */
+
 	spin_unlock_irqrestore(&trans_pcie->ref_lock, flags);
 }
 
@@ -2728,6 +2749,12 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
 
 	trans_pcie->inta_mask = CSR_INI_SET_MASK;
 
+#ifdef CONFIG_IWLWIFI_PCIE_RTPM
+	trans->runtime_pm_mode = IWL_PLAT_PM_MODE_D0I3;
+#else
+	trans->runtime_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
+#endif /* CONFIG_IWLWIFI_PCIE_RTPM */
+
 	return trans;
 
 out_free_ict:
-- 
2.5.0


  parent reply	other threads:[~2016-01-31 11:06 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-01-31 11:05 pull request: iwlwifi-next 2016-01-31 Grumbach, Emmanuel
2016-01-31 11:05 ` [PATCH 01/31] iwlwifi: pcie: buffer packets to avoid overflowing Tx queues Emmanuel Grumbach
2016-01-31 11:05 ` [PATCH 02/31] iwlwifi: pcie: add infrastructure for multi-queue rx Emmanuel Grumbach
2016-01-31 11:05 ` [PATCH 03/31] iwlwifi: pcie: add 9000 series multi queue rx DMA support Emmanuel Grumbach
2016-01-31 11:05 ` Emmanuel Grumbach [this message]
2016-02-01 14:32   ` [PATCH 04/31] iwlwifi: pcie: add initial RTPM support for PCI Kalle Valo
2016-02-01 14:38     ` Grumbach, Emmanuel
2016-02-01 14:43       ` Grumbach, Emmanuel
2016-01-31 11:06 ` [PATCH 05/31] iwlwifi: pcie: add RTPM support when wifi is enabled Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 06/31] iwlwifi: mvm: Do not switch to D3 image on suspend Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 07/31] iwlwifi: various comments and code cleanups Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 08/31] iwlwifi: dvm: handle zero brightness for wifi LED Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 09/31] iwlwifi: Document missing module options Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 10/31] iwlwifi: mvm: add trigger for firmware dump upon TX response status Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 11/31] iwlwifi: mvm: Add P2P client snoozing Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 12/31] iwlwifi: mvm: make collecting fw debug data optional Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 13/31] iwlwifi: mvm: remove shadowing variable Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 14/31] iwlwifi: mvm: fix debugfs signedness warning Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 15/31] iwlwifi: mvm: add support for negative temperatures Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 16/31] iwlwifi: mvm: support beacon storing Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 17/31] iwlwifi: mvm: track low-latency sources separately Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 18/31] iwlwifi: mvm: support setting minimum quota from debugfs Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 19/31] iwlwifi: mvm: change access to ieee80211_hdr Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 20/31] iwlwifi: mvm: add debug print if scan config is ignored Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 21/31] iwlwifi: mvm: change the check for ADD_STA status Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 22/31] iwlwifi: mvm: add tlv for multi queue rx support Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 23/31] iwlwifi: treat iwl_parse_nvm_data() MAC addr as little endian Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 24/31] iwlwifi: mvm: Remove bf_vif from iwl_power_vifs Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 25/31] iwlwifi: mvm: Remove iwl_mvm_update_beacon_abort Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 26/31] iwlwifi: mvm: add new ADD_STA command version Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 27/31] iwlwifi: mvm: rs: fix TPC action decision algorithm Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 28/31] iwlwifi: mvm: support rss queues configuration command Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 29/31] iwlwifi: pcie: enable multi-queue rx path Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 30/31] iwlwifi: pcie: update iwl_mpdu_desc fields Emmanuel Grumbach
2016-01-31 11:06 ` [PATCH 31/31] iwlwifi: mvm: allow to disable beacon filtering for AP/GO interface Emmanuel Grumbach
2016-02-06 11:06 ` pull request: iwlwifi-next 2016-01-31 Kalle Valo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1454238386-27032-4-git-send-email-emmanuel.grumbach@intel.com \
    --to=emmanuel.grumbach@intel.com \
    --cc=linux-wireless@vger.kernel.org \
    --cc=luciano.coelho@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).