2013-01-24 14:25:36 +01:00
/******************************************************************************
*
* This file is provided under a dual BSD / GPLv2 license . When using or
* redistributing this file , you may do so under either license .
*
* GPL LICENSE SUMMARY
*
* Copyright ( c ) 2012 - 2013 Intel Corporation . All rights reserved .
*
* 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
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 ,
* USA
*
* The full GNU General Public License is included in this distribution
2013-02-18 09:22:28 +02:00
* in the file called COPYING .
2013-01-24 14:25:36 +01:00
*
* Contact Information :
* Intel Linux Wireless < ilw @ linux . intel . com >
* Intel Corporation , 5200 N . E . Elam Young Parkway , Hillsboro , OR 97124 - 6497
*
* BSD LICENSE
*
* Copyright ( c ) 2012 - 2013 Intel Corporation . All rights reserved .
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
*
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in
* the documentation and / or other materials provided with the
* distribution .
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
* SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT
* LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/init.h>
# include <net/mac80211.h>
# include "iwl-debug.h"
# include "mvm.h"
# include "iwl-modparams.h"
# include "fw-api-power.h"
# define POWER_KEEP_ALIVE_PERIOD_SEC 25
2013-03-10 15:29:44 +02:00
int iwl_mvm_beacon_filter_send_cmd ( struct iwl_mvm * mvm ,
struct iwl_beacon_filter_cmd * cmd )
2013-05-06 13:03:59 +03:00
{
int ret ;
ret = iwl_mvm_send_cmd_pdu ( mvm , REPLY_BEACON_FILTERING_CMD , CMD_SYNC ,
sizeof ( struct iwl_beacon_filter_cmd ) , cmd ) ;
if ( ! ret ) {
IWL_DEBUG_POWER ( mvm , " ba_enable_beacon_abort is: %d \n " ,
2013-07-16 11:15:35 +03:00
le32_to_cpu ( cmd - > ba_enable_beacon_abort ) ) ;
2013-05-06 13:03:59 +03:00
IWL_DEBUG_POWER ( mvm , " ba_escape_timer is: %d \n " ,
2013-07-16 11:15:35 +03:00
le32_to_cpu ( cmd - > ba_escape_timer ) ) ;
2013-05-06 13:03:59 +03:00
IWL_DEBUG_POWER ( mvm , " bf_debug_flag is: %d \n " ,
2013-07-16 11:15:35 +03:00
le32_to_cpu ( cmd - > bf_debug_flag ) ) ;
2013-05-06 13:03:59 +03:00
IWL_DEBUG_POWER ( mvm , " bf_enable_beacon_filter is: %d \n " ,
2013-07-16 11:15:35 +03:00
le32_to_cpu ( cmd - > bf_enable_beacon_filter ) ) ;
2013-05-06 13:03:59 +03:00
IWL_DEBUG_POWER ( mvm , " bf_energy_delta is: %d \n " ,
2013-07-16 11:15:35 +03:00
le32_to_cpu ( cmd - > bf_energy_delta ) ) ;
2013-05-06 13:03:59 +03:00
IWL_DEBUG_POWER ( mvm , " bf_escape_timer is: %d \n " ,
2013-07-16 11:15:35 +03:00
le32_to_cpu ( cmd - > bf_escape_timer ) ) ;
2013-05-06 13:03:59 +03:00
IWL_DEBUG_POWER ( mvm , " bf_roaming_energy_delta is: %d \n " ,
2013-07-16 11:15:35 +03:00
le32_to_cpu ( cmd - > bf_roaming_energy_delta ) ) ;
2013-05-06 13:03:59 +03:00
IWL_DEBUG_POWER ( mvm , " bf_roaming_state is: %d \n " ,
2013-07-16 11:15:35 +03:00
le32_to_cpu ( cmd - > bf_roaming_state ) ) ;
IWL_DEBUG_POWER ( mvm , " bf_temp_threshold is: %d \n " ,
le32_to_cpu ( cmd - > bf_temp_threshold ) ) ;
IWL_DEBUG_POWER ( mvm , " bf_temp_fast_filter is: %d \n " ,
le32_to_cpu ( cmd - > bf_temp_fast_filter ) ) ;
IWL_DEBUG_POWER ( mvm , " bf_temp_slow_filter is: %d \n " ,
le32_to_cpu ( cmd - > bf_temp_slow_filter ) ) ;
2013-05-06 13:03:59 +03:00
}
return ret ;
}
2013-03-10 15:29:44 +02:00
int iwl_mvm_update_beacon_abort ( struct iwl_mvm * mvm ,
struct ieee80211_vif * vif , bool enable )
2013-05-06 13:03:59 +03:00
{
struct iwl_mvm_vif * mvmvif = iwl_mvm_vif_from_mac80211 ( vif ) ;
struct iwl_beacon_filter_cmd cmd = {
IWL_BF_CMD_CONFIG_DEFAULTS ,
2013-07-16 11:15:35 +03:00
. bf_enable_beacon_filter = cpu_to_le32 ( 1 ) ,
. ba_enable_beacon_abort = cpu_to_le32 ( enable ) ,
2013-05-06 13:03:59 +03:00
} ;
if ( ! mvmvif - > bf_enabled )
return 0 ;
2013-07-22 15:39:26 +03:00
if ( mvm - > cur_ucode = = IWL_UCODE_WOWLAN )
cmd . ba_escape_timer = cpu_to_le32 ( IWL_BA_ESCAPE_TIMER_D3 ) ;
2013-05-21 14:49:09 +03:00
iwl_mvm_beacon_filter_debugfs_parameters ( vif , & cmd ) ;
2013-05-06 13:03:59 +03:00
return iwl_mvm_beacon_filter_send_cmd ( mvm , & cmd ) ;
}
2013-03-05 14:08:23 +02:00
static void iwl_mvm_power_log ( struct iwl_mvm * mvm ,
2013-03-10 15:29:44 +02:00
struct iwl_mac_power_cmd * cmd )
2013-03-05 14:08:23 +02:00
{
IWL_DEBUG_POWER ( mvm ,
2013-03-10 15:29:44 +02:00
" Sending power table command on mac id 0x%X for power level %d, flags = 0x%X \n " ,
cmd - > id_and_color , iwlmvm_mod_params . power_scheme ,
2013-03-05 14:08:23 +02:00
le16_to_cpu ( cmd - > flags ) ) ;
2013-03-10 15:29:44 +02:00
IWL_DEBUG_POWER ( mvm , " Keep alive = %u sec \n " ,
le16_to_cpu ( cmd - > keep_alive_seconds ) ) ;
2013-03-05 14:08:23 +02:00
2013-04-07 14:08:59 +03:00
if ( ! ( cmd - > flags & cpu_to_le16 ( POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK ) ) ) {
IWL_DEBUG_POWER ( mvm , " Disable power management \n " ) ;
return ;
}
IWL_DEBUG_POWER ( mvm , " Rx timeout = %u usec \n " ,
le32_to_cpu ( cmd - > rx_data_timeout ) ) ;
IWL_DEBUG_POWER ( mvm , " Tx timeout = %u usec \n " ,
le32_to_cpu ( cmd - > tx_data_timeout ) ) ;
if ( cmd - > flags & cpu_to_le16 ( POWER_FLAGS_SKIP_OVER_DTIM_MSK ) )
IWL_DEBUG_POWER ( mvm , " DTIM periods to skip = %u \n " ,
cmd - > skip_dtim_periods ) ;
if ( cmd - > flags & cpu_to_le16 ( POWER_FLAGS_LPRX_ENA_MSK ) )
IWL_DEBUG_POWER ( mvm , " LP RX RSSI threshold = %u \n " ,
cmd - > lprx_rssi_threshold ) ;
if ( cmd - > flags & cpu_to_le16 ( POWER_FLAGS_ADVANCE_PM_ENA_MSK ) ) {
IWL_DEBUG_POWER ( mvm , " uAPSD enabled \n " ) ;
IWL_DEBUG_POWER ( mvm , " Rx timeout (uAPSD) = %u usec \n " ,
le32_to_cpu ( cmd - > rx_data_timeout_uapsd ) ) ;
IWL_DEBUG_POWER ( mvm , " Tx timeout (uAPSD) = %u usec \n " ,
le32_to_cpu ( cmd - > tx_data_timeout_uapsd ) ) ;
IWL_DEBUG_POWER ( mvm , " QNDP TID = %d \n " , cmd - > qndp_tid ) ;
IWL_DEBUG_POWER ( mvm , " ACs flags = 0x%x \n " , cmd - > uapsd_ac_flags ) ;
IWL_DEBUG_POWER ( mvm , " Max SP = %d \n " , cmd - > uapsd_max_sp ) ;
2013-03-05 14:08:23 +02:00
}
}
2013-03-10 15:29:44 +02:00
static void iwl_mvm_power_build_cmd ( struct iwl_mvm * mvm ,
struct ieee80211_vif * vif ,
struct iwl_mac_power_cmd * cmd )
2013-01-24 14:25:36 +01:00
{
struct ieee80211_hw * hw = mvm - > hw ;
struct ieee80211_chanctx_conf * chanctx_conf ;
struct ieee80211_channel * chan ;
int dtimper , dtimper_msec ;
int keep_alive ;
bool radar_detect = false ;
2013-05-21 14:49:09 +03:00
struct iwl_mvm_vif * mvmvif __maybe_unused =
iwl_mvm_vif_from_mac80211 ( vif ) ;
2013-04-07 14:08:59 +03:00
enum ieee80211_ac_numbers ac ;
bool tid_found = false ;
2013-01-24 14:25:36 +01:00
2013-03-10 15:29:44 +02:00
cmd - > id_and_color = cpu_to_le32 ( FW_CMD_ID_AND_COLOR ( mvmvif - > id ,
mvmvif - > color ) ) ;
dtimper = hw - > conf . ps_dtim_period ? : 1 ;
2013-03-05 14:01:27 +02:00
/*
* Regardless of power management state the driver must set
* keep alive period . FW will use it for sending keep alive NDPs
2013-03-10 15:29:44 +02:00
* immediately after association . Check that keep alive period
* is at least 3 * DTIM
2013-03-05 14:01:27 +02:00
*/
2013-03-10 15:29:44 +02:00
dtimper_msec = dtimper * vif - > bss_conf . beacon_int ;
keep_alive = max_t ( int , 3 * dtimper_msec ,
MSEC_PER_SEC * POWER_KEEP_ALIVE_PERIOD_SEC ) ;
keep_alive = DIV_ROUND_UP ( keep_alive , MSEC_PER_SEC ) ;
cmd - > keep_alive_seconds = cpu_to_le16 ( keep_alive ) ;
2013-03-05 14:01:27 +02:00
2013-04-03 16:28:47 +03:00
if ( iwlmvm_mod_params . power_scheme = = IWL_POWER_SCHEME_CAM )
2013-01-24 14:25:36 +01:00
return ;
2013-03-05 12:54:00 +02:00
cmd - > flags | = cpu_to_le16 ( POWER_FLAGS_POWER_SAVE_ENA_MSK ) ;
2013-05-21 14:49:09 +03:00
# ifdef CONFIG_IWLWIFI_DEBUGFS
if ( mvmvif - > dbgfs_pm . mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF & &
mvmvif - > dbgfs_pm . disable_power_off )
cmd - > flags & = cpu_to_le16 ( ~ POWER_FLAGS_POWER_SAVE_ENA_MSK ) ;
# endif
2013-03-05 12:54:00 +02:00
if ( ! vif - > bss_conf . ps )
return ;
cmd - > flags | = cpu_to_le16 ( POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK ) ;
2013-01-24 14:25:36 +01:00
2013-03-21 17:14:14 +02:00
if ( vif - > bss_conf . beacon_rate & &
( vif - > bss_conf . beacon_rate - > bitrate = = 10 | |
vif - > bss_conf . beacon_rate - > bitrate = = 60 ) ) {
cmd - > flags | = cpu_to_le16 ( POWER_FLAGS_LPRX_ENA_MSK ) ;
2013-03-10 15:29:44 +02:00
cmd - > lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD ;
2013-03-21 17:14:14 +02:00
}
2013-01-24 14:25:36 +01:00
/* Check if radar detection is required on current channel */
rcu_read_lock ( ) ;
chanctx_conf = rcu_dereference ( vif - > chanctx_conf ) ;
WARN_ON ( ! chanctx_conf ) ;
if ( chanctx_conf ) {
chan = chanctx_conf - > def . chan ;
radar_detect = chan - > flags & IEEE80211_CHAN_RADAR ;
}
rcu_read_unlock ( ) ;
/* Check skip over DTIM conditions */
if ( ! radar_detect & & ( dtimper < = 10 ) & &
2013-04-23 13:52:10 +03:00
( iwlmvm_mod_params . power_scheme = = IWL_POWER_SCHEME_LP | |
mvm - > cur_ucode = = IWL_UCODE_WOWLAN ) ) {
2013-03-05 13:47:04 +02:00
cmd - > flags | = cpu_to_le16 ( POWER_FLAGS_SKIP_OVER_DTIM_MSK ) ;
2013-03-10 15:29:44 +02:00
cmd - > skip_dtim_periods = 3 ;
2013-04-23 13:32:35 +03:00
}
2013-01-24 14:25:36 +01:00
2013-04-23 13:52:10 +03:00
if ( mvm - > cur_ucode ! = IWL_UCODE_WOWLAN ) {
2013-06-14 13:36:21 +02:00
cmd - > rx_data_timeout =
cpu_to_le32 ( IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT ) ;
cmd - > tx_data_timeout =
cpu_to_le32 ( IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT ) ;
2013-04-23 13:52:10 +03:00
} else {
2013-06-14 13:36:21 +02:00
cmd - > rx_data_timeout =
cpu_to_le32 ( IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT ) ;
cmd - > tx_data_timeout =
cpu_to_le32 ( IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT ) ;
2013-04-23 13:52:10 +03:00
}
2013-05-21 14:49:09 +03:00
2013-04-07 14:08:59 +03:00
for ( ac = IEEE80211_AC_VO ; ac < = IEEE80211_AC_BK ; ac + + ) {
if ( ! mvmvif - > queue_params [ ac ] . uapsd )
continue ;
cmd - > flags | = cpu_to_le16 ( POWER_FLAGS_ADVANCE_PM_ENA_MSK ) ;
cmd - > uapsd_ac_flags | = BIT ( ac ) ;
/* QNDP TID - the highest TID with no admission control */
if ( ! tid_found & & ! mvmvif - > queue_params [ ac ] . acm ) {
tid_found = true ;
switch ( ac ) {
case IEEE80211_AC_VO :
cmd - > qndp_tid = 6 ;
break ;
case IEEE80211_AC_VI :
cmd - > qndp_tid = 5 ;
break ;
case IEEE80211_AC_BE :
cmd - > qndp_tid = 0 ;
break ;
case IEEE80211_AC_BK :
cmd - > qndp_tid = 1 ;
break ;
}
}
}
if ( cmd - > flags & cpu_to_le16 ( POWER_FLAGS_ADVANCE_PM_ENA_MSK ) ) {
cmd - > rx_data_timeout_uapsd =
cpu_to_le32 ( IWL_MVM_UAPSD_RX_DATA_TIMEOUT ) ;
cmd - > tx_data_timeout_uapsd =
cpu_to_le32 ( IWL_MVM_UAPSD_TX_DATA_TIMEOUT ) ;
cmd - > uapsd_max_sp = IWL_UAPSD_MAX_SP ;
cmd - > heavy_tx_thld_packets =
IWL_MVM_PS_HEAVY_TX_THLD_PACKETS ;
cmd - > heavy_rx_thld_packets =
IWL_MVM_PS_HEAVY_RX_THLD_PACKETS ;
cmd - > heavy_tx_thld_percentage =
IWL_MVM_PS_HEAVY_TX_THLD_PERCENT ;
cmd - > heavy_rx_thld_percentage =
IWL_MVM_PS_HEAVY_RX_THLD_PERCENT ;
}
2013-05-21 14:49:09 +03:00
# ifdef CONFIG_IWLWIFI_DEBUGFS
if ( mvmvif - > dbgfs_pm . mask & MVM_DEBUGFS_PM_KEEP_ALIVE )
2013-03-10 15:29:44 +02:00
cmd - > keep_alive_seconds =
cpu_to_le16 ( mvmvif - > dbgfs_pm . keep_alive_seconds ) ;
2013-05-21 14:49:09 +03:00
if ( mvmvif - > dbgfs_pm . mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM ) {
if ( mvmvif - > dbgfs_pm . skip_over_dtim )
cmd - > flags | =
cpu_to_le16 ( POWER_FLAGS_SKIP_OVER_DTIM_MSK ) ;
else
cmd - > flags & =
cpu_to_le16 ( ~ POWER_FLAGS_SKIP_OVER_DTIM_MSK ) ;
}
if ( mvmvif - > dbgfs_pm . mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT )
cmd - > rx_data_timeout =
cpu_to_le32 ( mvmvif - > dbgfs_pm . rx_data_timeout ) ;
if ( mvmvif - > dbgfs_pm . mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT )
cmd - > tx_data_timeout =
cpu_to_le32 ( mvmvif - > dbgfs_pm . tx_data_timeout ) ;
if ( mvmvif - > dbgfs_pm . mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS )
2013-03-10 15:29:44 +02:00
cmd - > skip_dtim_periods = mvmvif - > dbgfs_pm . skip_dtim_periods ;
2013-03-21 17:14:14 +02:00
if ( mvmvif - > dbgfs_pm . mask & MVM_DEBUGFS_PM_LPRX_ENA ) {
if ( mvmvif - > dbgfs_pm . lprx_ena )
cmd - > flags | = cpu_to_le16 ( POWER_FLAGS_LPRX_ENA_MSK ) ;
else
cmd - > flags & = cpu_to_le16 ( ~ POWER_FLAGS_LPRX_ENA_MSK ) ;
}
if ( mvmvif - > dbgfs_pm . mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD )
2013-03-10 15:29:44 +02:00
cmd - > lprx_rssi_threshold = mvmvif - > dbgfs_pm . lprx_rssi_threshold ;
2013-05-21 14:49:09 +03:00
# endif /* CONFIG_IWLWIFI_DEBUGFS */
2013-01-24 14:25:36 +01:00
}
2013-03-10 15:29:44 +02:00
static int iwl_mvm_power_mac_update_mode ( struct iwl_mvm * mvm ,
struct ieee80211_vif * vif )
2013-01-24 14:25:36 +01:00
{
2013-05-06 13:03:59 +03:00
int ret ;
bool ba_enable ;
2013-03-10 15:29:44 +02:00
struct iwl_mac_power_cmd cmd = { } ;
2013-01-24 14:25:36 +01:00
if ( vif - > type ! = NL80211_IFTYPE_STATION | | vif - > p2p )
return 0 ;
2013-05-29 10:19:50 +03:00
/*
* TODO : The following vif_count verification is temporary condition .
* Avoid power mode update if more than one interface is currently
* active . Remove this condition when FW will support power management
* on multiple MACs .
*/
IWL_DEBUG_POWER ( mvm , " Currently %d interfaces active \n " ,
mvm - > vif_count ) ;
if ( mvm - > vif_count > 1 )
return 0 ;
2013-03-05 13:47:04 +02:00
iwl_mvm_power_build_cmd ( mvm , vif , & cmd ) ;
2013-03-05 14:08:23 +02:00
iwl_mvm_power_log ( mvm , & cmd ) ;
2013-01-24 14:25:36 +01:00
2013-03-10 15:29:44 +02:00
ret = iwl_mvm_send_cmd_pdu ( mvm , MAC_PM_POWER_TABLE , CMD_SYNC ,
2013-05-06 13:03:59 +03:00
sizeof ( cmd ) , & cmd ) ;
if ( ret )
return ret ;
ba_enable = ! ! ( cmd . flags &
cpu_to_le16 ( POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK ) ) ;
return iwl_mvm_update_beacon_abort ( mvm , vif , ba_enable ) ;
2013-01-24 14:25:36 +01:00
}
2013-03-10 15:29:44 +02:00
static int iwl_mvm_power_mac_disable ( struct iwl_mvm * mvm ,
struct ieee80211_vif * vif )
2013-01-24 14:25:36 +01:00
{
2013-03-10 15:29:44 +02:00
struct iwl_mac_power_cmd cmd = { } ;
2013-05-21 14:49:09 +03:00
struct iwl_mvm_vif * mvmvif __maybe_unused =
iwl_mvm_vif_from_mac80211 ( vif ) ;
2013-01-24 14:25:36 +01:00
if ( vif - > type ! = NL80211_IFTYPE_STATION | | vif - > p2p )
return 0 ;
2013-03-10 15:29:44 +02:00
cmd . id_and_color = cpu_to_le32 ( FW_CMD_ID_AND_COLOR ( mvmvif - > id ,
mvmvif - > color ) ) ;
2013-04-03 16:28:47 +03:00
if ( iwlmvm_mod_params . power_scheme ! = IWL_POWER_SCHEME_CAM )
2013-03-05 12:54:00 +02:00
cmd . flags | = cpu_to_le16 ( POWER_FLAGS_POWER_SAVE_ENA_MSK ) ;
2013-05-21 14:49:09 +03:00
# ifdef CONFIG_IWLWIFI_DEBUGFS
if ( mvmvif - > dbgfs_pm . mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF & &
mvmvif - > dbgfs_pm . disable_power_off )
cmd . flags & = cpu_to_le16 ( ~ POWER_FLAGS_POWER_SAVE_ENA_MSK ) ;
# endif
2013-03-05 14:08:23 +02:00
iwl_mvm_power_log ( mvm , & cmd ) ;
2013-01-24 14:25:36 +01:00
2013-03-10 15:29:44 +02:00
return iwl_mvm_send_cmd_pdu ( mvm , MAC_PM_POWER_TABLE , CMD_ASYNC ,
2013-01-24 14:25:36 +01:00
sizeof ( cmd ) , & cmd ) ;
}
2012-12-12 11:16:19 +02:00
2013-05-21 14:49:09 +03:00
# ifdef CONFIG_IWLWIFI_DEBUGFS
2013-03-10 15:29:44 +02:00
static int iwl_mvm_power_mac_dbgfs_read ( struct iwl_mvm * mvm ,
struct ieee80211_vif * vif , char * buf ,
int bufsz )
{
struct iwl_mac_power_cmd cmd = { } ;
int pos = 0 ;
iwl_mvm_power_build_cmd ( mvm , vif , & cmd ) ;
pos + = scnprintf ( buf + pos , bufsz - pos , " disable_power_off = %d \n " ,
( cmd . flags &
cpu_to_le16 ( POWER_FLAGS_POWER_SAVE_ENA_MSK ) ) ?
0 : 1 ) ;
pos + = scnprintf ( buf + pos , bufsz - pos , " power_scheme = %d \n " ,
iwlmvm_mod_params . power_scheme ) ;
pos + = scnprintf ( buf + pos , bufsz - pos , " flags = 0x%x \n " ,
le16_to_cpu ( cmd . flags ) ) ;
pos + = scnprintf ( buf + pos , bufsz - pos , " keep_alive = %d \n " ,
le16_to_cpu ( cmd . keep_alive_seconds ) ) ;
if ( cmd . flags & cpu_to_le16 ( POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK ) ) {
pos + = scnprintf ( buf + pos , bufsz - pos , " skip_over_dtim = %d \n " ,
( cmd . flags &
cpu_to_le16 ( POWER_FLAGS_SKIP_OVER_DTIM_MSK ) ) ?
1 : 0 ) ;
2013-04-07 14:08:59 +03:00
pos + = scnprintf ( buf + pos , bufsz - pos , " skip_dtim_periods = %d \n " ,
cmd . skip_dtim_periods ) ;
if ( ! ( cmd . flags &
cpu_to_le16 ( POWER_FLAGS_ADVANCE_PM_ENA_MSK ) ) ) {
pos + = scnprintf ( buf + pos , bufsz - pos ,
" rx_data_timeout = %d \n " ,
le32_to_cpu ( cmd . rx_data_timeout ) ) ;
pos + = scnprintf ( buf + pos , bufsz - pos ,
" tx_data_timeout = %d \n " ,
le32_to_cpu ( cmd . tx_data_timeout ) ) ;
}
2013-03-10 15:29:44 +02:00
if ( cmd . flags & cpu_to_le16 ( POWER_FLAGS_LPRX_ENA_MSK ) )
pos + = scnprintf ( buf + pos , bufsz - pos ,
" lprx_rssi_threshold = %d \n " ,
cmd . lprx_rssi_threshold ) ;
2013-04-07 14:08:59 +03:00
if ( cmd . flags & cpu_to_le16 ( POWER_FLAGS_ADVANCE_PM_ENA_MSK ) ) {
pos + =
scnprintf ( buf + pos , bufsz - pos ,
" rx_data_timeout_uapsd = %d \n " ,
le32_to_cpu ( cmd . rx_data_timeout_uapsd ) ) ;
pos + =
scnprintf ( buf + pos , bufsz - pos ,
" tx_data_timeout_uapsd = %d \n " ,
le32_to_cpu ( cmd . tx_data_timeout_uapsd ) ) ;
pos + = scnprintf ( buf + pos , bufsz - pos , " qndp_tid = %d \n " ,
cmd . qndp_tid ) ;
pos + = scnprintf ( buf + pos , bufsz - pos ,
" uapsd_ac_flags = 0x%x \n " ,
cmd . uapsd_ac_flags ) ;
pos + = scnprintf ( buf + pos , bufsz - pos ,
" uapsd_max_sp = %d \n " ,
cmd . uapsd_max_sp ) ;
pos + = scnprintf ( buf + pos , bufsz - pos ,
" heavy_tx_thld_packets = %d \n " ,
cmd . heavy_tx_thld_packets ) ;
pos + = scnprintf ( buf + pos , bufsz - pos ,
" heavy_rx_thld_packets = %d \n " ,
cmd . heavy_rx_thld_packets ) ;
pos + = scnprintf ( buf + pos , bufsz - pos ,
" heavy_tx_thld_percentage = %d \n " ,
cmd . heavy_tx_thld_percentage ) ;
pos + = scnprintf ( buf + pos , bufsz - pos ,
" heavy_rx_thld_percentage = %d \n " ,
cmd . heavy_rx_thld_percentage ) ;
}
2013-03-10 15:29:44 +02:00
}
return pos ;
}
2013-05-21 14:49:09 +03:00
void
iwl_mvm_beacon_filter_debugfs_parameters ( struct ieee80211_vif * vif ,
struct iwl_beacon_filter_cmd * cmd )
{
struct iwl_mvm_vif * mvmvif = iwl_mvm_vif_from_mac80211 ( vif ) ;
struct iwl_dbgfs_bf * dbgfs_bf = & mvmvif - > dbgfs_bf ;
if ( dbgfs_bf - > mask & MVM_DEBUGFS_BF_ENERGY_DELTA )
2013-07-16 11:15:35 +03:00
cmd - > bf_energy_delta = cpu_to_le32 ( dbgfs_bf - > bf_energy_delta ) ;
2013-05-21 14:49:09 +03:00
if ( dbgfs_bf - > mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA )
cmd - > bf_roaming_energy_delta =
2013-07-16 11:15:35 +03:00
cpu_to_le32 ( dbgfs_bf - > bf_roaming_energy_delta ) ;
2013-05-21 14:49:09 +03:00
if ( dbgfs_bf - > mask & MVM_DEBUGFS_BF_ROAMING_STATE )
2013-07-16 11:15:35 +03:00
cmd - > bf_roaming_state = cpu_to_le32 ( dbgfs_bf - > bf_roaming_state ) ;
if ( dbgfs_bf - > mask & MVM_DEBUGFS_BF_TEMP_THRESHOLD )
cmd - > bf_temp_threshold =
cpu_to_le32 ( dbgfs_bf - > bf_temp_threshold ) ;
if ( dbgfs_bf - > mask & MVM_DEBUGFS_BF_TEMP_FAST_FILTER )
cmd - > bf_temp_fast_filter =
cpu_to_le32 ( dbgfs_bf - > bf_temp_fast_filter ) ;
if ( dbgfs_bf - > mask & MVM_DEBUGFS_BF_TEMP_SLOW_FILTER )
cmd - > bf_temp_slow_filter =
cpu_to_le32 ( dbgfs_bf - > bf_temp_slow_filter ) ;
2013-05-21 14:49:09 +03:00
if ( dbgfs_bf - > mask & MVM_DEBUGFS_BF_DEBUG_FLAG )
2013-07-16 11:15:35 +03:00
cmd - > bf_debug_flag = cpu_to_le32 ( dbgfs_bf - > bf_debug_flag ) ;
2013-05-21 14:49:09 +03:00
if ( dbgfs_bf - > mask & MVM_DEBUGFS_BF_ESCAPE_TIMER )
cmd - > bf_escape_timer = cpu_to_le32 ( dbgfs_bf - > bf_escape_timer ) ;
if ( dbgfs_bf - > mask & MVM_DEBUGFS_BA_ESCAPE_TIMER )
cmd - > ba_escape_timer = cpu_to_le32 ( dbgfs_bf - > ba_escape_timer ) ;
if ( dbgfs_bf - > mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT )
2013-07-16 11:15:35 +03:00
cmd - > ba_enable_beacon_abort =
cpu_to_le32 ( dbgfs_bf - > ba_enable_beacon_abort ) ;
2013-05-21 14:49:09 +03:00
}
# endif
2012-12-12 11:16:19 +02:00
int iwl_mvm_enable_beacon_filter ( struct iwl_mvm * mvm ,
struct ieee80211_vif * vif )
{
struct iwl_mvm_vif * mvmvif = iwl_mvm_vif_from_mac80211 ( vif ) ;
struct iwl_beacon_filter_cmd cmd = {
2013-05-06 13:03:59 +03:00
IWL_BF_CMD_CONFIG_DEFAULTS ,
2013-07-16 11:15:35 +03:00
. bf_enable_beacon_filter = cpu_to_le32 ( 1 ) ,
2012-12-12 11:16:19 +02:00
} ;
2013-05-06 13:03:59 +03:00
int ret ;
2012-12-12 11:16:19 +02:00
if ( mvmvif ! = mvm - > bf_allowed_vif | |
vif - > type ! = NL80211_IFTYPE_STATION | | vif - > p2p )
return 0 ;
2013-05-21 14:49:09 +03:00
iwl_mvm_beacon_filter_debugfs_parameters ( vif , & cmd ) ;
2013-05-06 13:03:59 +03:00
ret = iwl_mvm_beacon_filter_send_cmd ( mvm , & cmd ) ;
if ( ! ret )
mvmvif - > bf_enabled = true ;
return ret ;
2012-12-12 11:16:19 +02:00
}
int iwl_mvm_disable_beacon_filter ( struct iwl_mvm * mvm ,
struct ieee80211_vif * vif )
{
2013-05-06 13:03:59 +03:00
struct iwl_beacon_filter_cmd cmd = { } ;
struct iwl_mvm_vif * mvmvif = iwl_mvm_vif_from_mac80211 ( vif ) ;
int ret ;
2012-12-12 11:16:19 +02:00
2013-07-16 11:15:35 +03:00
if ( ! ( mvm - > fw - > ucode_capa . flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED ) | |
vif - > type ! = NL80211_IFTYPE_STATION | | vif - > p2p )
2012-12-12 11:16:19 +02:00
return 0 ;
2013-05-06 13:03:59 +03:00
ret = iwl_mvm_beacon_filter_send_cmd ( mvm , & cmd ) ;
if ( ! ret )
mvmvif - > bf_enabled = false ;
return ret ;
2012-12-12 11:16:19 +02:00
}
2013-03-10 15:29:44 +02:00
const struct iwl_mvm_power_ops pm_mac_ops = {
. power_update_mode = iwl_mvm_power_mac_update_mode ,
. power_disable = iwl_mvm_power_mac_disable ,
# ifdef CONFIG_IWLWIFI_DEBUGFS
. power_dbgfs_read = iwl_mvm_power_mac_dbgfs_read ,
# endif
} ;