iwlagn: move PCI power related functions to the PCI layer
authorWey-Yi Guy <wey-yi.w.guy@intel.com>
Fri, 10 Jun 2011 18:23:36 +0000 (11:23 -0700)
committerWey-Yi Guy <wey-yi.w.guy@intel.com>
Sat, 18 Jun 2011 15:17:29 +0000 (08:17 -0700)
Continue to popule the PCI layer and the iwl_bus_ops with the power related
stuff.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
drivers/net/wireless/iwlwifi/iwl-agn-hw.h
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-pci.c
drivers/net/wireless/iwlwifi/iwl-power.c
drivers/net/wireless/iwlwifi/iwl-power.h

index 7bd19f4e66de6339a8d994a41437a3487e1596af..0e5b842529c40ac7532f54a7f1174bff936d877b 100644 (file)
 /* RSSI to dBm */
 #define IWLAGN_RSSI_OFFSET     44
 
-/* PCI registers */
-#define PCI_CFG_RETRY_TIMEOUT  0x041
-
-/* PCI register values */
-#define PCI_CFG_LINK_CTRL_VAL_L0S_EN   0x01
-#define PCI_CFG_LINK_CTRL_VAL_L1_EN    0x02
-
 #define IWLAGN_DEFAULT_TX_RETRY  15
 
 /* Limit range of txpower output target to be between these values */
index 4268a3f4141370eaa402f30dc019205899456173..360df33585ee507251c9589fb7ae5cc3298e52b0 100644 (file)
@@ -997,8 +997,6 @@ void iwl_apm_stop(struct iwl_priv *priv)
 int iwl_apm_init(struct iwl_priv *priv)
 {
        int ret = 0;
-       u16 lctl;
-
        IWL_DEBUG_INFO(priv, "Init card's basic functions\n");
 
        /*
@@ -1027,27 +1025,7 @@ int iwl_apm_init(struct iwl_priv *priv)
        iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
                                    CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
 
-       /*
-        * HW bug W/A for instability in PCIe bus L0->L0S->L1 transition.
-        * Check if BIOS (or OS) enabled L1-ASPM on this device.
-        * If so (likely), disable L0S, so device moves directly L0->L1;
-        *    costs negligible amount of power savings.
-        * If not (unlikely), enable L0S, so there is at least some
-        *    power savings, even without L1.
-        */
-       lctl = iwl_pcie_link_ctl(priv);
-       if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
-                               PCI_CFG_LINK_CTRL_VAL_L1_EN) {
-               /* L1-ASPM enabled; disable(!) L0S  */
-               iwl_set_bit(priv, CSR_GIO_REG,
-                               CSR_GIO_REG_VAL_L0S_ENABLED);
-               IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n");
-       } else {
-               /* L1-ASPM disabled; enable(!) L0S */
-               iwl_clear_bit(priv, CSR_GIO_REG,
-                               CSR_GIO_REG_VAL_L0S_ENABLED);
-               IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n");
-       }
+       priv->bus.ops->apm_config(&priv->bus);
 
        /* Configure analog phase-lock-loop before activating to D0A */
        if (priv->cfg->base_params->pll_cfg_val)
index 84032bbfefd6c53ac3d3c6371006c31e682d764d..a09361dd62dd4b4070e0937839c77434c2f1b94a 100644 (file)
@@ -470,20 +470,6 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
 
 int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
 
-
-/*****************************************************
- * PCI                                              *
- *****************************************************/
-
-static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
-{
-       int pos;
-       u16 pci_lnk_ctl;
-       pos = pci_find_capability(priv->pci_dev, PCI_CAP_ID_EXP);
-       pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
-       return pci_lnk_ctl;
-}
-
 void iwl_bg_watchdog(unsigned long data);
 u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval);
 __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
index 700e9f92129c5d88f2299e0c12ffaff28dd3df80..797d4f3f879e48470c0baa864c1de0592335ac95 100644 (file)
@@ -1193,6 +1193,9 @@ struct iwl_bus;
 
 /**
  * struct iwl_bus_ops - bus specific operations
+
+ * @get_pm_support: must returns true if the bus can go to sleep
+ * @apm_config: will be called during the config of the APM configuration
  * @set_drv_data: set the priv pointer to the bus layer
  * @get_dev: returns the device struct
  * @write8: write a byte to register at offset ofs
@@ -1200,6 +1203,8 @@ struct iwl_bus;
  * @wread32: read a dword at register at offset ofs
  */
 struct iwl_bus_ops {
+       bool (*get_pm_support)(struct iwl_bus *bus);
+       void (*apm_config)(struct iwl_bus *bus);
        void (*set_drv_data)(struct iwl_bus *bus, void *priv);
        struct device *(*get_dev)(const struct iwl_bus *bus);
        void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val);
index 43de98efa3e4113bb87f8900b6506fc5b31c726e..d8c6ec8947c22fd09db1c9b40651099bee73ef8f 100644 (file)
 #include "iwl-pci.h"
 #include "iwl-agn.h"
 #include "iwl-core.h"
+#include "iwl-io.h"
+
+/* PCI registers */
+#define PCI_CFG_RETRY_TIMEOUT  0x041
+#define PCI_CFG_LINK_CTRL_VAL_L0S_EN   0x01
+#define PCI_CFG_LINK_CTRL_VAL_L1_EN    0x02
 
 struct iwl_pci_bus {
        /* basic pci-network driver stuff */
@@ -81,6 +87,50 @@ struct iwl_pci_bus {
 #define IWL_BUS_GET_PCI_DEV(_iwl_bus) \
                        ((IWL_BUS_GET_PCI_BUS(_iwl_bus))->pci_dev)
 
+static u16 iwl_pciexp_link_ctrl(struct iwl_bus *bus)
+{
+       int pos;
+       u16 pci_lnk_ctl;
+       struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus);
+
+       pos = pci_find_capability(pci_dev, PCI_CAP_ID_EXP);
+       pci_read_config_word(pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
+       return pci_lnk_ctl;
+}
+
+static bool iwl_pci_is_pm_supported(struct iwl_bus *bus)
+{
+       u16 lctl = iwl_pciexp_link_ctrl(bus);
+
+       return !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+}
+
+static void iwl_pci_apm_config(struct iwl_bus *bus)
+{
+       /*
+        * HW bug W/A for instability in PCIe bus L0S->L1 transition.
+        * Check if BIOS (or OS) enabled L1-ASPM on this device.
+        * If so (likely), disable L0S, so device moves directly L0->L1;
+        *    costs negligible amount of power savings.
+        * If not (unlikely), enable L0S, so there is at least some
+        *    power savings, even without L1.
+        */
+       u16 lctl = iwl_pciexp_link_ctrl(bus);
+
+       if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
+                               PCI_CFG_LINK_CTRL_VAL_L1_EN) {
+               /* L1-ASPM enabled; disable(!) L0S */
+               iwl_set_bit(bus->priv, CSR_GIO_REG,
+                               CSR_GIO_REG_VAL_L0S_ENABLED);
+               IWL_DEBUG_POWER(bus->priv, "L1 Enabled; Disabling L0S\n");
+       } else {
+               /* L1-ASPM disabled; enable(!) L0S */
+               iwl_clear_bit(bus->priv, CSR_GIO_REG,
+                               CSR_GIO_REG_VAL_L0S_ENABLED);
+               IWL_DEBUG_POWER(bus->priv, "L1 Disabled; Enabling L0S\n");
+       }
+}
+
 static void iwl_pci_set_drv_data(struct iwl_bus *bus, void *drv_priv)
 {
        pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), drv_priv);
@@ -108,6 +158,8 @@ static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs)
 }
 
 static struct iwl_bus_ops pci_ops = {
+       .get_pm_support = iwl_pci_is_pm_supported,
+       .apm_config = iwl_pci_apm_config,
        .set_drv_data = iwl_pci_set_drv_data,
        .get_dev = iwl_pci_get_dev,
        .write8 = iwl_pci_write8,
index a69b55124176be42c4f453a1569e09d46b1d361f..970c514623b93f802788357b3136941808bc79c4 100644 (file)
@@ -245,7 +245,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
                }
        }
 
-       if (priv->power_data.pci_pm)
+       if (priv->power_data.bus_pm)
                cmd->flags |= IWL_POWER_PCI_PM_MSK;
        else
                cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
@@ -260,7 +260,7 @@ static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv,
 {
        memset(cmd, 0, sizeof(*cmd));
 
-       if (priv->power_data.pci_pm)
+       if (priv->power_data.bus_pm)
                cmd->flags |= IWL_POWER_PCI_PM_MSK;
 
        IWL_DEBUG_POWER(priv, "Sleep command for CAM\n");
@@ -296,7 +296,7 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
        cmd->flags = IWL_POWER_DRIVER_ALLOW_SLEEP_MSK |
                     IWL_POWER_FAST_PD; /* no use seeing frames for others */
 
-       if (priv->power_data.pci_pm)
+       if (priv->power_data.bus_pm)
                cmd->flags |= IWL_POWER_PCI_PM_MSK;
 
        if (priv->cfg->base_params->shadow_reg_enable)
@@ -425,9 +425,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
 /* initialize to default */
 void iwl_power_initialize(struct iwl_priv *priv)
 {
-       u16 lctl = iwl_pcie_link_ctl(priv);
-
-       priv->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+       priv->power_data.bus_pm = priv->bus.ops->get_pm_support(&priv->bus);
 
        priv->power_data.debug_sleep_level_override = -1;
 
index 59635d784e27ae88e481eaabc02c5ba2ab20ae38..5f7b720cf1a4335236c86ed5cc1f8230658c9f01 100644 (file)
@@ -43,7 +43,7 @@ struct iwl_power_mgr {
        struct iwl_powertable_cmd sleep_cmd;
        struct iwl_powertable_cmd sleep_cmd_next;
        int debug_sleep_level_override;
-       bool pci_pm;
+       bool bus_pm;
 };
 
 int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,