These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / net / wireless / iwlwifi / mvm / power.c
index d2c6ba9..bed9696 100644 (file)
@@ -7,6 +7,7 @@
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2015        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
@@ -33,6 +34,7 @@
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2015        Intel Deutschland GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -112,11 +114,12 @@ int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
 static
 void iwl_mvm_beacon_filter_set_cqm_params(struct iwl_mvm *mvm,
                                          struct ieee80211_vif *vif,
-                                         struct iwl_beacon_filter_cmd *cmd)
+                                         struct iwl_beacon_filter_cmd *cmd,
+                                         bool d0i3)
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 
-       if (vif->bss_conf.cqm_rssi_thold) {
+       if (vif->bss_conf.cqm_rssi_thold && !d0i3) {
                cmd->bf_energy_delta =
                        cpu_to_le32(vif->bss_conf.cqm_rssi_hyst);
                /* fw uses an absolute value for this */
@@ -287,27 +290,6 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
        return true;
 }
 
-static int iwl_mvm_power_get_skip_over_dtim(int dtimper, int bi)
-{
-       int numerator;
-       int dtim_interval = dtimper * bi;
-
-       if (WARN_ON(!dtim_interval))
-               return 0;
-
-       if (dtimper == 1) {
-               if (bi > 100)
-                       numerator = 408;
-               else
-                       numerator = 510;
-       } else if (dtimper < 10) {
-               numerator = 612;
-       } else {
-               return 0;
-       }
-       return max(1, (numerator / dtim_interval));
-}
-
 static bool iwl_mvm_power_is_radar(struct ieee80211_vif *vif)
 {
        struct ieee80211_chanctx_conf *chanctx_conf;
@@ -326,13 +308,51 @@ static bool iwl_mvm_power_is_radar(struct ieee80211_vif *vif)
        return radar_detect;
 }
 
+static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm,
+                                          struct ieee80211_vif *vif,
+                                          struct iwl_mac_power_cmd *cmd,
+                                          bool host_awake)
+{
+       int dtimper = vif->bss_conf.dtim_period ?: 1;
+       int skip;
+
+       /* disable, in case we're supposed to override */
+       cmd->skip_dtim_periods = 0;
+       cmd->flags &= ~cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
+
+       if (iwl_mvm_power_is_radar(vif))
+               return;
+
+       if (dtimper >= 10)
+               return;
+
+       /* TODO: check that multicast wake lock is off */
+
+       if (host_awake) {
+               if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_LP)
+                       return;
+               skip = 2;
+       } else {
+               int dtimper_tu = dtimper * vif->bss_conf.beacon_int;
+
+               if (WARN_ON(!dtimper_tu))
+                       return;
+               /* configure skip over dtim up to 306TU - 314 msec */
+               skip = max_t(u8, 1, 306 / dtimper_tu);
+       }
+
+       /* the firmware really expects "look at every X DTIMs", so add 1 */
+       cmd->skip_dtim_periods = 1 + skip;
+       cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
+}
+
 static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
                                    struct ieee80211_vif *vif,
-                                   struct iwl_mac_power_cmd *cmd)
+                                   struct iwl_mac_power_cmd *cmd,
+                                   bool host_awake)
 {
        int dtimper, bi;
        int keep_alive;
-       bool radar_detect = false;
        struct iwl_mvm_vif *mvmvif __maybe_unused =
                iwl_mvm_vif_from_mac80211(vif);
 
@@ -357,8 +377,13 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
 
        cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
 
-       if (!vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif) ||
-           !mvmvif->pm_enabled)
+       if (!vif->bss_conf.ps || !mvmvif->pm_enabled)
+               return;
+
+       if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
+           (!fw_has_capa(&mvm->fw->ucode_capa,
+                        IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS) ||
+            !IWL_MVM_P2P_LOWLATENCY_PS_ENABLE))
                return;
 
        cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
@@ -370,30 +395,25 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
                cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD;
        }
 
-       /* Check if radar detection is required on current channel */
-       radar_detect = iwl_mvm_power_is_radar(vif);
-
-       /* Check skip over DTIM conditions */
-       if (!radar_detect && (dtimper < 10) &&
-           (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP ||
-            mvm->cur_ucode == IWL_UCODE_WOWLAN)) {
-               cmd->skip_dtim_periods =
-                       iwl_mvm_power_get_skip_over_dtim(dtimper, bi);
-               if (cmd->skip_dtim_periods)
-                       cmd->flags |=
-                               cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
-       }
+       iwl_mvm_power_config_skip_dtim(mvm, vif, cmd, host_awake);
 
-       if (mvm->cur_ucode != IWL_UCODE_WOWLAN) {
+       if (!host_awake) {
                cmd->rx_data_timeout =
-                       cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT);
+                       cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
                cmd->tx_data_timeout =
-                       cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT);
+                       cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
+       } else if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
+                  fw_has_capa(&mvm->fw->ucode_capa,
+                              IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS)) {
+               cmd->tx_data_timeout =
+                       cpu_to_le32(IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT);
+               cmd->rx_data_timeout =
+                       cpu_to_le32(IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT);
        } else {
                cmd->rx_data_timeout =
-                       cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
+                       cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT);
                cmd->tx_data_timeout =
-                       cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
+                       cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT);
        }
 
        if (iwl_mvm_power_allow_uapsd(mvm, vif))
@@ -450,7 +470,8 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
 {
        struct iwl_mac_power_cmd cmd = {};
 
-       iwl_mvm_power_build_cmd(mvm, vif, &cmd);
+       iwl_mvm_power_build_cmd(mvm, vif, &cmd,
+                               mvm->cur_ucode != IWL_UCODE_WOWLAN);
        iwl_mvm_power_log(mvm, &cmd);
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd));
@@ -463,14 +484,14 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
 int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
 {
        struct iwl_device_power_cmd cmd = {
-               .flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK),
+               .flags = 0,
        };
 
        if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
                mvm->ps_disabled = true;
 
-       if (mvm->ps_disabled)
-               cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_CAM_MSK);
+       if (!mvm->ps_disabled)
+               cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        if ((mvm->cur_ucode == IWL_UCODE_WOWLAN) ? mvm->disable_power_off_d3 :
@@ -509,9 +530,8 @@ static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac,
                       ETH_ALEN);
 }
 
-int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
-                                            struct iwl_rx_cmd_buffer *rxb,
-                                            struct iwl_device_cmd *cmd)
+void iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
+                                             struct iwl_rx_cmd_buffer *rxb)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_uapsd_misbehaving_ap_notif *notif = (void *)pkt->data;
@@ -520,8 +540,6 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
        ieee80211_iterate_active_interfaces_atomic(
                mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
                iwl_mvm_power_uapsd_misbehav_ap_iterator, &ap_sta_id);
-
-       return 0;
 }
 
 struct iwl_power_vifs {
@@ -810,7 +828,7 @@ static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
            vif->type != NL80211_IFTYPE_STATION || vif->p2p)
                return 0;
 
-       iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd);
+       iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd, d0i3);
        if (!d0i3)
                iwl_mvm_beacon_filter_debugfs_parameters(vif, cmd);
        ret = iwl_mvm_beacon_filter_send_cmd(mvm, cmd, cmd_flags);
@@ -989,25 +1007,8 @@ int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
        if (!vif->bss_conf.assoc)
                return 0;
 
-       iwl_mvm_power_build_cmd(mvm, vif, &cmd);
-       if (enable) {
-               /* configure skip over dtim up to 306TU - 314 msec */
-               int dtimper = vif->bss_conf.dtim_period ?: 1;
-               int dtimper_tu = dtimper * vif->bss_conf.beacon_int;
-               bool radar_detect = iwl_mvm_power_is_radar(vif);
+       iwl_mvm_power_build_cmd(mvm, vif, &cmd, !enable);
 
-               if (WARN_ON(!dtimper_tu))
-                       return 0;
-
-               /* Check skip over DTIM conditions */
-               /* TODO: check that multicast wake lock is off */
-               if (!radar_detect && (dtimper < 10)) {
-                       cmd.skip_dtim_periods = 306 / dtimper_tu;
-                       if (cmd.skip_dtim_periods)
-                               cmd.flags |= cpu_to_le16(
-                                       POWER_FLAGS_SKIP_OVER_DTIM_MSK);
-               }
-       }
        iwl_mvm_power_log(mvm, &cmd);
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        memcpy(&mvmvif->mac_pwr_cmd, &cmd, sizeof(cmd));