iwlwifi: mvm: Add PBW snoozing enablement
authorAlexander Bondar <alexander.bondar@intel.com>
Sun, 4 Aug 2013 14:52:23 +0000 (17:52 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 16 Aug 2013 10:13:28 +0000 (12:13 +0200)
The Performance Based Window snooze mechanism is based on uAPSD and is
used in low-medium traffic scenarios, in order to provide better power
performance while insuring low latency and jitter for the incoming traffic.
This patch enables PBW snoozing in case uAPSD is enabled and all ACs are
uAPSD trigger and delivery enabled.

Signed-off-by: Alexander Bondar <alexander.bondar@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/iwlwifi/mvm/constants.h
drivers/net/wireless/iwlwifi/mvm/debugfs.c
drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/power.c

index 33f98fc26e2deceaef4283914f36002e0d4da516..2bf29f7992ee4d953536bf1ec6ab0b2fbf1debae 100644 (file)
@@ -73,5 +73,8 @@
 #define IWL_MVM_PS_HEAVY_RX_THLD_PACKETS       20
 #define IWL_MVM_PS_HEAVY_TX_THLD_PERCENT       50
 #define IWL_MVM_PS_HEAVY_RX_THLD_PERCENT       50
+#define IWL_MVM_PS_SNOOZE_INTERVAL             25
+#define IWL_MVM_PS_SNOOZE_WINDOW               50
+#define IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW                25
 
 #endif /* __MVM_CONSTANTS_H */
index c67b17aa7dfb1bc2ec2795dbb86cd4f02dff43f8..2e60be2a7ee35e635409c84b004e8b71d3610a68 100644 (file)
@@ -352,6 +352,10 @@ static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
                IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val);
                dbgfs_pm->lprx_rssi_threshold = val;
                break;
+       case MVM_DEBUGFS_PM_SNOOZE_ENABLE:
+               IWL_DEBUG_POWER(mvm, "snooze_enable=%d\n", val);
+               dbgfs_pm->snooze_ena = val;
+               break;
        }
 }
 
@@ -405,6 +409,10 @@ static ssize_t iwl_dbgfs_pm_params_write(struct file *file,
                    POWER_LPRX_RSSI_THRESHOLD_MIN)
                        return -EINVAL;
                param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD;
+       } else if (!strncmp("snooze_enable=", buf, 14)) {
+               if (sscanf(buf + 14, "%d", &val) != 1)
+                       return -EINVAL;
+               param = MVM_DEBUGFS_PM_SNOOZE_ENABLE;
        } else {
                return -EINVAL;
        }
index bb010b323b0f1e7bb0f151140c88755c432bd92f..8e7ab41079ca6ca51eba975a2e39c92cee5f002b 100644 (file)
@@ -155,8 +155,12 @@ struct iwl_powertable_cmd {
  * @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled.
  *                     Default: 80dbm
  * @num_skip_dtim:     Number of DTIMs to skip if Skip over DTIM flag is set
- * @snooze_interval:   TBD
- * @snooze_window:     TBD
+ * @snooze_interval:   Maximum time between attempts to retrieve buffered data
+ *                     from the AP [msec]
+ * @snooze_window:     A window of time in which PBW snoozing insures that all
+ *                     packets received. It is also the minimum time from last
+ *                     received unicast RX packet, before client stops snoozing
+ *                     for data. [msec]
  * @snooze_step:       TBD
  * @qndp_tid:          TID client shall use for uAPSD QNDP triggers
  * @uapsd_ac_flags:    Set trigger-enabled and delivery-enabled indication for
index ee46dea6950927e64ae8dc20aa342d4324869877..0f33d7f20890b4ea197fff4c53097241ec992d9b 100644 (file)
@@ -180,6 +180,7 @@ enum iwl_dbgfs_pm_mask {
        MVM_DEBUGFS_PM_DISABLE_POWER_OFF = BIT(5),
        MVM_DEBUGFS_PM_LPRX_ENA = BIT(6),
        MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD = BIT(7),
+       MVM_DEBUGFS_PM_SNOOZE_ENABLE = BIT(8),
 };
 
 struct iwl_dbgfs_pm {
@@ -191,6 +192,7 @@ struct iwl_dbgfs_pm {
        bool disable_power_off;
        bool lprx_ena;
        u32 lprx_rssi_threshold;
+       bool snooze_ena;
        int mask;
 };
 
index a5529b85de8b9ddca3675a1b0f5ff49fb685b079..21407a353a3b0e623c87ae3627957ae45ae3b162 100644 (file)
@@ -301,6 +301,20 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
                        cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT);
                cmd->tx_data_timeout_uapsd =
                        cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT);
+
+               if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) |
+                                           BIT(IEEE80211_AC_VI) |
+                                           BIT(IEEE80211_AC_BE) |
+                                           BIT(IEEE80211_AC_BK))) {
+                       cmd->flags |= cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
+                       cmd->snooze_interval =
+                               cpu_to_le16(IWL_MVM_PS_SNOOZE_INTERVAL);
+                       cmd->snooze_window =
+                               (mvm->cur_ucode == IWL_UCODE_WOWLAN) ?
+                               cpu_to_le16(IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW) :
+                               cpu_to_le16(IWL_MVM_PS_SNOOZE_WINDOW);
+               }
+
                cmd->uapsd_max_sp = IWL_UAPSD_MAX_SP;
                cmd->heavy_tx_thld_packets =
                        IWL_MVM_PS_HEAVY_TX_THLD_PACKETS;
@@ -340,6 +354,14 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
        }
        if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
                cmd->lprx_rssi_threshold = mvmvif->dbgfs_pm.lprx_rssi_threshold;
+       if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SNOOZE_ENABLE) {
+               if (mvmvif->dbgfs_pm.snooze_ena)
+                       cmd->flags |=
+                               cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
+               else
+                       cmd->flags &=
+                               cpu_to_le16(~POWER_FLAGS_SNOOZE_ENA_MSK);
+       }
 #endif /* CONFIG_IWLWIFI_DEBUGFS */
 }
 
@@ -475,6 +497,19 @@ static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
                        pos += scnprintf(buf+pos, bufsz-pos,
                                         "heavy_rx_thld_percentage = %d\n",
                                         cmd.heavy_rx_thld_percentage);
+                       pos +=
+                       scnprintf(buf+pos, bufsz-pos, "snooze_enable = %d\n",
+                                 (cmd.flags &
+                                  cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) ?
+                                 1 : 0);
+               }
+               if (cmd.flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
+                       pos += scnprintf(buf+pos, bufsz-pos,
+                                        "snooze_interval = %d\n",
+                                        cmd.snooze_interval);
+                       pos += scnprintf(buf+pos, bufsz-pos,
+                                        "snooze_window = %d\n",
+                                        cmd.snooze_window);
                }
        }
        return pos;