Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
623c4387
cloud-kernel
项目概览
openanolis
/
cloud-kernel
接近 2 年 前同步成功
通知
170
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
623c4387
编写于
12月 18, 2013
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-john' of
git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
上级
204e35a9
cf4ef654
变更
35
展开全部
隐藏空白更改
内联
并排
Showing
35 changed file
with
1837 addition
and
766 deletion
+1837
-766
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
+0
-6
drivers/net/wireless/iwlwifi/dvm/main.c
drivers/net/wireless/iwlwifi/dvm/main.c
+2
-2
drivers/net/wireless/iwlwifi/iwl-7000.c
drivers/net/wireless/iwlwifi/iwl-7000.c
+1
-1
drivers/net/wireless/iwlwifi/iwl-config.h
drivers/net/wireless/iwlwifi/iwl-config.h
+2
-0
drivers/net/wireless/iwlwifi/iwl-drv.c
drivers/net/wireless/iwlwifi/iwl-drv.c
+39
-0
drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
+7
-0
drivers/net/wireless/iwlwifi/iwl-fw-file.h
drivers/net/wireless/iwlwifi/iwl-fw-file.h
+1
-0
drivers/net/wireless/iwlwifi/iwl-fw.h
drivers/net/wireless/iwlwifi/iwl-fw.h
+46
-0
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
+14
-1
drivers/net/wireless/iwlwifi/iwl-op-mode.h
drivers/net/wireless/iwlwifi/iwl-op-mode.h
+1
-3
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/iwlwifi/iwl-trans.h
+52
-14
drivers/net/wireless/iwlwifi/mvm/Makefile
drivers/net/wireless/iwlwifi/mvm/Makefile
+1
-2
drivers/net/wireless/iwlwifi/mvm/binding.c
drivers/net/wireless/iwlwifi/mvm/binding.c
+15
-1
drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
+353
-0
drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+16
-0
drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
+9
-1
drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
+1
-0
drivers/net/wireless/iwlwifi/mvm/fw-api.h
drivers/net/wireless/iwlwifi/mvm/fw-api.h
+65
-0
drivers/net/wireless/iwlwifi/mvm/fw.c
drivers/net/wireless/iwlwifi/mvm/fw.c
+18
-10
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
+174
-78
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/mvm.h
+37
-8
drivers/net/wireless/iwlwifi/mvm/ops.c
drivers/net/wireless/iwlwifi/mvm/ops.c
+12
-8
drivers/net/wireless/iwlwifi/mvm/power.c
drivers/net/wireless/iwlwifi/mvm/power.c
+243
-152
drivers/net/wireless/iwlwifi/mvm/rs.c
drivers/net/wireless/iwlwifi/mvm/rs.c
+350
-336
drivers/net/wireless/iwlwifi/mvm/rs.h
drivers/net/wireless/iwlwifi/mvm/rs.h
+0
-2
drivers/net/wireless/iwlwifi/mvm/rx.c
drivers/net/wireless/iwlwifi/mvm/rx.c
+6
-0
drivers/net/wireless/iwlwifi/mvm/sf.c
drivers/net/wireless/iwlwifi/mvm/sf.c
+291
-0
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/wireless/iwlwifi/mvm/sta.c
+4
-17
drivers/net/wireless/iwlwifi/mvm/tt.c
drivers/net/wireless/iwlwifi/mvm/tt.c
+1
-1
drivers/net/wireless/iwlwifi/mvm/tx.c
drivers/net/wireless/iwlwifi/mvm/tx.c
+1
-2
drivers/net/wireless/iwlwifi/mvm/utils.c
drivers/net/wireless/iwlwifi/mvm/utils.c
+5
-0
drivers/net/wireless/iwlwifi/pcie/internal.h
drivers/net/wireless/iwlwifi/pcie/internal.h
+2
-31
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/rx.c
+16
-19
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/iwlwifi/pcie/trans.c
+37
-49
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/iwlwifi/pcie/tx.c
+15
-22
未找到文件。
drivers/net/wireless/iwlwifi/dvm/mac80211.c
浏览文件 @
623c4387
...
...
@@ -322,12 +322,6 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
flush_workqueue
(
priv
->
workqueue
);
/* User space software may expect getting rfkill changes
* even if interface is down, trans->down will leave the RF
* kill interrupt enabled
*/
iwl_trans_stop_hw
(
priv
->
trans
,
false
);
IWL_DEBUG_MAC80211
(
priv
,
"leave
\n
"
);
}
...
...
drivers/net/wireless/iwlwifi/dvm/main.c
浏览文件 @
623c4387
...
...
@@ -1313,7 +1313,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
}
/* Reset chip to save power until we load uCode during "up". */
iwl_trans_stop_
hw
(
priv
->
trans
,
false
);
iwl_trans_stop_
device
(
priv
->
trans
);
priv
->
nvm_data
=
iwl_parse_eeprom_data
(
priv
->
trans
->
dev
,
priv
->
cfg
,
priv
->
eeprom_blob
,
...
...
@@ -1458,7 +1458,7 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
dev_kfree_skb
(
priv
->
beacon_skb
);
iwl_trans_
stop_hw
(
priv
->
trans
,
true
);
iwl_trans_
op_mode_leave
(
priv
->
trans
);
ieee80211_free_hw
(
priv
->
hw
);
}
...
...
drivers/net/wireless/iwlwifi/iwl-7000.c
浏览文件 @
623c4387
...
...
@@ -108,7 +108,7 @@ static const struct iwl_base_params iwl7000_base_params = {
};
static
const
struct
iwl_ht_params
iwl7000_ht_params
=
{
.
use_rts_for_aggregation
=
true
,
/* use rts/cts protection */
.
stbc
=
true
,
.
ht40_bands
=
BIT
(
IEEE80211_BAND_2GHZ
)
|
BIT
(
IEEE80211_BAND_5GHZ
),
};
...
...
drivers/net/wireless/iwlwifi/iwl-config.h
浏览文件 @
623c4387
...
...
@@ -162,12 +162,14 @@ struct iwl_base_params {
};
/*
* @stbc: support Tx STBC and 1*SS Rx STBC
* @use_rts_for_aggregation: use rts/cts protection for HT traffic
* @ht40_bands: bitmap of bands (using %IEEE80211_BAND_*) that support HT40
*/
struct
iwl_ht_params
{
enum
ieee80211_smps_mode
smps_mode
;
const
bool
ht_greenfield_support
;
/* if used set to true */
const
bool
stbc
;
bool
use_rts_for_aggregation
;
u8
ht40_bands
;
};
...
...
drivers/net/wireless/iwlwifi/iwl-drv.c
浏览文件 @
623c4387
...
...
@@ -322,6 +322,41 @@ static void set_sec_offset(struct iwl_firmware_pieces *pieces,
pieces
->
img
[
type
].
sec
[
sec
].
offset
=
offset
;
}
static
int
iwl_store_cscheme
(
struct
iwl_fw
*
fw
,
const
u8
*
data
,
const
u32
len
)
{
int
i
,
j
;
struct
iwl_fw_cscheme_list
*
l
=
(
struct
iwl_fw_cscheme_list
*
)
data
;
struct
iwl_fw_cipher_scheme
*
fwcs
;
struct
ieee80211_cipher_scheme
*
cs
;
u32
cipher
;
if
(
len
<
sizeof
(
*
l
)
||
len
<
sizeof
(
l
->
size
)
+
l
->
size
*
sizeof
(
l
->
cs
[
0
]))
return
-
EINVAL
;
for
(
i
=
0
,
j
=
0
;
i
<
IWL_UCODE_MAX_CS
&&
i
<
l
->
size
;
i
++
)
{
fwcs
=
&
l
->
cs
[
j
];
cipher
=
le32_to_cpu
(
fwcs
->
cipher
);
/* we skip schemes with zero cipher suite selector */
if
(
!
cipher
)
continue
;
cs
=
&
fw
->
cs
[
j
++
];
cs
->
cipher
=
cipher
;
cs
->
iftype
=
BIT
(
NL80211_IFTYPE_STATION
);
cs
->
hdr_len
=
fwcs
->
hdr_len
;
cs
->
pn_len
=
fwcs
->
pn_len
;
cs
->
pn_off
=
fwcs
->
pn_off
;
cs
->
key_idx_off
=
fwcs
->
key_idx_off
;
cs
->
key_idx_mask
=
fwcs
->
key_idx_mask
;
cs
->
key_idx_shift
=
fwcs
->
key_idx_shift
;
cs
->
mic_len
=
fwcs
->
mic_len
;
}
return
0
;
}
/*
* Gets uCode section from tlv.
*/
...
...
@@ -729,6 +764,10 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
return
-
EINVAL
;
}
break
;
case
IWL_UCODE_TLV_CSCHEME
:
if
(
iwl_store_cscheme
(
&
drv
->
fw
,
tlv_data
,
tlv_len
))
goto
invalid_tlv_len
;
break
;
default:
IWL_DEBUG_INFO
(
drv
,
"unknown TLV: %d
\n
"
,
tlv_type
);
break
;
...
...
drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
浏览文件 @
623c4387
...
...
@@ -751,6 +751,13 @@ void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
ht_info
->
ht_supported
=
true
;
ht_info
->
cap
=
IEEE80211_HT_CAP_DSSSCCK40
;
if
(
cfg
->
ht_params
->
stbc
)
{
ht_info
->
cap
|=
(
1
<<
IEEE80211_HT_CAP_RX_STBC_SHIFT
);
if
(
tx_chains
>
1
)
ht_info
->
cap
|=
IEEE80211_HT_CAP_TX_STBC
;
}
if
(
iwlwifi_mod_params
.
amsdu_size_8K
)
ht_info
->
cap
|=
IEEE80211_HT_CAP_MAX_AMSDU
;
...
...
drivers/net/wireless/iwlwifi/iwl-fw-file.h
浏览文件 @
623c4387
...
...
@@ -125,6 +125,7 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_SECURE_SEC_INIT
=
25
,
IWL_UCODE_TLV_SECURE_SEC_WOWLAN
=
26
,
IWL_UCODE_TLV_NUM_OF_CPU
=
27
,
IWL_UCODE_TLV_CSCHEME
=
28
,
};
struct
iwl_ucode_tlv
{
...
...
drivers/net/wireless/iwlwifi/iwl-fw.h
浏览文件 @
623c4387
...
...
@@ -92,6 +92,9 @@
* @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API
* @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command
* containing CAM (Continuous Active Mode) indication.
* @IWL_UCODE_TLV_FLAGS_P2P_PS: P2P client power save is supported (only on a
* single bound interface).
* @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save
*/
enum
iwl_ucode_tlv_flag
{
IWL_UCODE_TLV_FLAGS_PAN
=
BIT
(
0
),
...
...
@@ -113,7 +116,9 @@ enum iwl_ucode_tlv_flag {
IWL_UCODE_TLV_FLAGS_SCHED_SCAN
=
BIT
(
17
),
IWL_UCODE_TLV_FLAGS_STA_KEY_CMD
=
BIT
(
19
),
IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD
=
BIT
(
20
),
IWL_UCODE_TLV_FLAGS_P2P_PS
=
BIT
(
21
),
IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT
=
BIT
(
24
),
IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD
=
BIT
(
26
),
};
/* The default calibrate table size if not specified by firmware file */
...
...
@@ -209,6 +214,44 @@ enum iwl_fw_phy_cfg {
FW_PHY_CFG_RX_CHAIN
=
0xf
<<
FW_PHY_CFG_RX_CHAIN_POS
,
};
#define IWL_UCODE_MAX_CS 1
/**
* struct iwl_fw_cipher_scheme - a cipher scheme supported by FW.
* @cipher: a cipher suite selector
* @flags: cipher scheme flags (currently reserved for a future use)
* @hdr_len: a size of MPDU security header
* @pn_len: a size of PN
* @pn_off: an offset of pn from the beginning of the security header
* @key_idx_off: an offset of key index byte in the security header
* @key_idx_mask: a bit mask of key_idx bits
* @key_idx_shift: bit shift needed to get key_idx
* @mic_len: mic length in bytes
* @hw_cipher: a HW cipher index used in host commands
*/
struct
iwl_fw_cipher_scheme
{
__le32
cipher
;
u8
flags
;
u8
hdr_len
;
u8
pn_len
;
u8
pn_off
;
u8
key_idx_off
;
u8
key_idx_mask
;
u8
key_idx_shift
;
u8
mic_len
;
u8
hw_cipher
;
}
__packed
;
/**
* struct iwl_fw_cscheme_list - a cipher scheme list
* @size: a number of entries
* @cs: cipher scheme entries
*/
struct
iwl_fw_cscheme_list
{
u8
size
;
struct
iwl_fw_cipher_scheme
cs
[];
}
__packed
;
/**
* struct iwl_fw - variables associated with the firmware
*
...
...
@@ -224,6 +267,7 @@ enum iwl_fw_phy_cfg {
* @inst_evtlog_size: event log size for runtime ucode.
* @inst_errlog_ptr: error log offfset for runtime ucode.
* @mvm_fw: indicates this is MVM firmware
* @cipher_scheme: optional external cipher scheme.
*/
struct
iwl_fw
{
u32
ucode_ver
;
...
...
@@ -243,6 +287,8 @@ struct iwl_fw {
u32
phy_config
;
bool
mvm_fw
;
struct
ieee80211_cipher_scheme
cs
[
IWL_UCODE_MAX_CS
];
};
static
inline
u8
iwl_fw_valid_tx_ant
(
const
struct
iwl_fw
*
fw
)
...
...
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
浏览文件 @
623c4387
...
...
@@ -263,13 +263,20 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
struct
iwl_nvm_data
*
data
,
struct
ieee80211_sta_vht_cap
*
vht_cap
)
{
int
num_ants
=
num_of_ant
(
data
->
valid_rx_ant
);
int
bf_sts_cap
=
num_ants
-
1
;
vht_cap
->
vht_supported
=
true
;
vht_cap
->
cap
=
IEEE80211_VHT_CAP_SHORT_GI_80
|
IEEE80211_VHT_CAP_RXSTBC_1
|
IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE
|
bf_sts_cap
<<
IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT
|
7
<<
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT
;
if
(
num_ants
>
1
)
vht_cap
->
cap
|=
IEEE80211_VHT_CAP_TXSTBC
;
if
(
iwlwifi_mod_params
.
amsdu_size_8K
)
vht_cap
->
cap
|=
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991
;
...
...
@@ -283,16 +290,22 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
IEEE80211_VHT_MCS_NOT_SUPPORTED
<<
12
|
IEEE80211_VHT_MCS_NOT_SUPPORTED
<<
14
);
if
(
num_of_ant
(
data
->
valid_rx_ant
)
==
1
||
/* Max rate for Long GI NSS=2 80Mhz is 780Mbps */
vht_cap
->
vht_mcs
.
rx_highest
=
cpu_to_le16
(
780
);
if
(
num_ants
==
1
||
cfg
->
rx_with_siso_diversity
)
{
vht_cap
->
cap
|=
IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN
|
IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN
;
/* this works because NOT_SUPPORTED == 3 */
vht_cap
->
vht_mcs
.
rx_mcs_map
|=
cpu_to_le16
(
IEEE80211_VHT_MCS_NOT_SUPPORTED
<<
2
);
/* Max rate for Long GI NSS=1 80Mhz is 390Mbps */
vht_cap
->
vht_mcs
.
rx_highest
=
cpu_to_le16
(
390
);
}
vht_cap
->
vht_mcs
.
tx_mcs_map
=
vht_cap
->
vht_mcs
.
rx_mcs_map
;
vht_cap
->
vht_mcs
.
tx_highest
=
vht_cap
->
vht_mcs
.
rx_highest
;
}
static
void
iwl_init_sbands
(
struct
device
*
dev
,
const
struct
iwl_cfg
*
cfg
,
...
...
drivers/net/wireless/iwlwifi/iwl-op-mode.h
浏览文件 @
623c4387
...
...
@@ -155,14 +155,12 @@ void iwl_opmode_deregister(const char *name);
/**
* struct iwl_op_mode - operational mode
* @ops - pointer to its own ops
*
* This holds an implementation of the mac80211 / fw API.
*
* @ops - pointer to its own ops
*/
struct
iwl_op_mode
{
const
struct
iwl_op_mode_ops
*
ops
;
const
struct
iwl_trans
*
trans
;
char
op_mode_specific
[
0
]
__aligned
(
sizeof
(
void
*
));
};
...
...
drivers/net/wireless/iwlwifi/iwl-trans.h
浏览文件 @
623c4387
...
...
@@ -70,6 +70,7 @@
#include "iwl-debug.h"
#include "iwl-config.h"
#include "iwl-fw.h"
#include "iwl-op-mode.h"
/**
* DOC: Transport layer - what is it ?
...
...
@@ -100,8 +101,7 @@
* start_fw
*
* 5) Then when finished (or reset):
* stop_fw (a.k.a. stop device for the moment)
* stop_hw
* stop_device
*
* 6) Eventually, the free function will be called.
*/
...
...
@@ -317,6 +317,24 @@ enum iwl_d3_status {
IWL_D3_STATUS_RESET
,
};
/**
* enum iwl_trans_status: transport status flags
* @STATUS_SYNC_HCMD_ACTIVE: a SYNC command is being processed
* @STATUS_DEVICE_ENABLED: APM is enabled
* @STATUS_TPOWER_PMI: the device might be asleep (need to wake it up)
* @STATUS_INT_ENABLED: interrupts are enabled
* @STATUS_RFKILL: the HW RFkill switch is in KILL position
* @STATUS_FW_ERROR: the fw is in error state
*/
enum
iwl_trans_status
{
STATUS_SYNC_HCMD_ACTIVE
,
STATUS_DEVICE_ENABLED
,
STATUS_TPOWER_PMI
,
STATUS_INT_ENABLED
,
STATUS_RFKILL
,
STATUS_FW_ERROR
,
};
/**
* struct iwl_trans_config - transport configuration
*
...
...
@@ -361,9 +379,7 @@ struct iwl_trans;
*
* @start_hw: starts the HW- from that point on, the HW can send interrupts
* May sleep
* @stop_hw: stops the HW- from that point on, the HW will be in low power but
* will still issue interrupt if the HW RF kill is triggered unless
* op_mode_leaving is true.
* @op_mode_leave: Turn off the HW RF kill indication if on
* May sleep
* @start_fw: allocates and inits all the resources for the transport
* layer. Also kick a fw image.
...
...
@@ -371,8 +387,11 @@ struct iwl_trans;
* @fw_alive: called when the fw sends alive notification. If the fw provides
* the SCD base address in SRAM, then provide it here, or 0 otherwise.
* May sleep
* @stop_device:stops the whole device (embedded CPU put to reset)
* May sleep
* @stop_device: stops the whole device (embedded CPU put to reset) and stops
* the HW. From that point on, the HW will be in low power but will still
* issue interrupt if the HW RF kill is triggered. This callback must do
* the right thing and not crash even if start_hw() was called but not
* start_fw(). May sleep
* @d3_suspend: put the device into the correct mode for WoWLAN during
* suspend. This is optional, if not implemented WoWLAN will not be
* supported. This callback may sleep.
...
...
@@ -418,7 +437,7 @@ struct iwl_trans;
struct
iwl_trans_ops
{
int
(
*
start_hw
)(
struct
iwl_trans
*
iwl_trans
);
void
(
*
stop_hw
)(
struct
iwl_trans
*
iwl_trans
,
bool
op_mode_leaving
);
void
(
*
op_mode_leave
)(
struct
iwl_trans
*
iwl_trans
);
int
(
*
start_fw
)(
struct
iwl_trans
*
trans
,
const
struct
fw_img
*
fw
,
bool
run_in_rfkill
);
void
(
*
fw_alive
)(
struct
iwl_trans
*
trans
,
u32
scd_addr
);
...
...
@@ -479,6 +498,7 @@ enum iwl_trans_state {
* @ops - pointer to iwl_trans_ops
* @op_mode - pointer to the op_mode
* @cfg - pointer to the configuration
* @status: a bit-mask of transport status flags
* @dev - pointer to struct device * that represents the device
* @hw_id: a u32 with the ID of the device / subdevice.
* Set during transport allocation.
...
...
@@ -499,6 +519,7 @@ struct iwl_trans {
struct
iwl_op_mode
*
op_mode
;
const
struct
iwl_cfg
*
cfg
;
enum
iwl_trans_state
state
;
unsigned
long
status
;
struct
device
*
dev
;
u32
hw_rev
;
...
...
@@ -540,15 +561,14 @@ static inline int iwl_trans_start_hw(struct iwl_trans *trans)
return
trans
->
ops
->
start_hw
(
trans
);
}
static
inline
void
iwl_trans_stop_hw
(
struct
iwl_trans
*
trans
,
bool
op_mode_leaving
)
static
inline
void
iwl_trans_op_mode_leave
(
struct
iwl_trans
*
trans
)
{
might_sleep
();
trans
->
ops
->
stop_hw
(
trans
,
op_mode_leaving
);
if
(
trans
->
ops
->
op_mode_leave
)
trans
->
ops
->
op_mode_leave
(
trans
);
if
(
op_mode_leaving
)
trans
->
op_mode
=
NULL
;
trans
->
op_mode
=
NULL
;
trans
->
state
=
IWL_TRANS_NO_FW
;
}
...
...
@@ -570,6 +590,7 @@ static inline int iwl_trans_start_fw(struct iwl_trans *trans,
WARN_ON_ONCE
(
!
trans
->
rx_mpdu_cmd
);
clear_bit
(
STATUS_FW_ERROR
,
&
trans
->
status
);
return
trans
->
ops
->
start_fw
(
trans
,
fw
,
run_in_rfkill
);
}
...
...
@@ -601,6 +622,9 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
{
int
ret
;
if
(
unlikely
(
test_bit
(
STATUS_FW_ERROR
,
&
trans
->
status
)))
return
-
EIO
;
if
(
unlikely
(
trans
->
state
!=
IWL_TRANS_FW_ALIVE
))
{
IWL_ERR
(
trans
,
"%s bad state = %d"
,
__func__
,
trans
->
state
);
return
-
EIO
;
...
...
@@ -640,6 +664,9 @@ static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans,
static
inline
int
iwl_trans_tx
(
struct
iwl_trans
*
trans
,
struct
sk_buff
*
skb
,
struct
iwl_device_cmd
*
dev_cmd
,
int
queue
)
{
if
(
unlikely
(
test_bit
(
STATUS_FW_ERROR
,
&
trans
->
status
)))
return
-
EIO
;
if
(
unlikely
(
trans
->
state
!=
IWL_TRANS_FW_ALIVE
))
IWL_ERR
(
trans
,
"%s bad state = %d"
,
__func__
,
trans
->
state
);
...
...
@@ -760,7 +787,8 @@ static inline u32 iwl_trans_write_mem32(struct iwl_trans *trans, u32 addr,
static
inline
void
iwl_trans_set_pmi
(
struct
iwl_trans
*
trans
,
bool
state
)
{
trans
->
ops
->
set_pmi
(
trans
,
state
);
if
(
trans
->
ops
->
set_pmi
)
trans
->
ops
->
set_pmi
(
trans
,
state
);
}
static
inline
void
...
...
@@ -780,6 +808,16 @@ iwl_trans_release_nic_access(struct iwl_trans *trans, unsigned long *flags)
__release
(
nic_access
);
}
static
inline
void
iwl_trans_fw_error
(
struct
iwl_trans
*
trans
)
{
if
(
WARN_ON_ONCE
(
!
trans
->
op_mode
))
return
;
/* prevent double restarts due to the same erroneous FW */
if
(
!
test_and_set_bit
(
STATUS_FW_ERROR
,
&
trans
->
status
))
iwl_op_mode_nic_error
(
trans
->
op_mode
);
}
/*****************************************************
* driver (transport) register/unregister functions
******************************************************/
...
...
drivers/net/wireless/iwlwifi/mvm/Makefile
浏览文件 @
623c4387
obj-$(CONFIG_IWLMVM)
+=
iwlmvm.o
iwlmvm-y
+=
fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
iwlmvm-y
+=
utils.o rx.o tx.o binding.o quota.o sta.o
iwlmvm-y
+=
utils.o rx.o tx.o binding.o quota.o sta.o
sf.o
iwlmvm-y
+=
scan.o time-event.o rs.o
iwlmvm-y
+=
power.o power_legacy.o bt-coex.o
iwlmvm-y
+=
led.o tt.o
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS)
+=
debugfs.o
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS)
+=
debugfs.o debugfs-vif.o
iwlmvm-$(CONFIG_PM_SLEEP)
+=
d3.o
...
...
drivers/net/wireless/iwlwifi/mvm/binding.c
浏览文件 @
623c4387
...
...
@@ -183,15 +183,29 @@ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if
(
WARN_ON_ONCE
(
!
mvmvif
->
phy_ctxt
))
return
-
EINVAL
;
/*
* Update SF - Disable if needed. if this fails, SF might still be on
* while many macs are bound, which is forbidden - so fail the binding.
*/
if
(
iwl_mvm_sf_update
(
mvm
,
vif
,
false
))
return
-
EINVAL
;
return
iwl_mvm_binding_update
(
mvm
,
vif
,
mvmvif
->
phy_ctxt
,
true
);
}
int
iwl_mvm_binding_remove_vif
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
)
{
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
int
ret
;
if
(
WARN_ON_ONCE
(
!
mvmvif
->
phy_ctxt
))
return
-
EINVAL
;
return
iwl_mvm_binding_update
(
mvm
,
vif
,
mvmvif
->
phy_ctxt
,
false
);
ret
=
iwl_mvm_binding_update
(
mvm
,
vif
,
mvmvif
->
phy_ctxt
,
false
);
if
(
!
ret
)
if
(
iwl_mvm_sf_update
(
mvm
,
vif
,
true
))
IWL_ERR
(
mvm
,
"Failed to update SF state
\n
"
);
return
ret
;
}
drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
浏览文件 @
623c4387
...
...
@@ -63,6 +63,150 @@
#include "mvm.h"
#include "debugfs.h"
static
void
iwl_dbgfs_update_pm
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
enum
iwl_dbgfs_pm_mask
param
,
int
val
)
{
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
struct
iwl_dbgfs_pm
*
dbgfs_pm
=
&
mvmvif
->
dbgfs_pm
;
dbgfs_pm
->
mask
|=
param
;
switch
(
param
)
{
case
MVM_DEBUGFS_PM_KEEP_ALIVE
:
{
struct
ieee80211_hw
*
hw
=
mvm
->
hw
;
int
dtimper
=
hw
->
conf
.
ps_dtim_period
?:
1
;
int
dtimper_msec
=
dtimper
*
vif
->
bss_conf
.
beacon_int
;
IWL_DEBUG_POWER
(
mvm
,
"debugfs: set keep_alive= %d sec
\n
"
,
val
);
if
(
val
*
MSEC_PER_SEC
<
3
*
dtimper_msec
)
IWL_WARN
(
mvm
,
"debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)
\n
"
,
val
*
MSEC_PER_SEC
,
3
*
dtimper_msec
);
dbgfs_pm
->
keep_alive_seconds
=
val
;
break
;
}
case
MVM_DEBUGFS_PM_SKIP_OVER_DTIM
:
IWL_DEBUG_POWER
(
mvm
,
"skip_over_dtim %s
\n
"
,
val
?
"enabled"
:
"disabled"
);
dbgfs_pm
->
skip_over_dtim
=
val
;
break
;
case
MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS
:
IWL_DEBUG_POWER
(
mvm
,
"skip_dtim_periods=%d
\n
"
,
val
);
dbgfs_pm
->
skip_dtim_periods
=
val
;
break
;
case
MVM_DEBUGFS_PM_RX_DATA_TIMEOUT
:
IWL_DEBUG_POWER
(
mvm
,
"rx_data_timeout=%d
\n
"
,
val
);
dbgfs_pm
->
rx_data_timeout
=
val
;
break
;
case
MVM_DEBUGFS_PM_TX_DATA_TIMEOUT
:
IWL_DEBUG_POWER
(
mvm
,
"tx_data_timeout=%d
\n
"
,
val
);
dbgfs_pm
->
tx_data_timeout
=
val
;
break
;
case
MVM_DEBUGFS_PM_DISABLE_POWER_OFF
:
IWL_DEBUG_POWER
(
mvm
,
"disable_power_off=%d
\n
"
,
val
);
dbgfs_pm
->
disable_power_off
=
val
;
break
;
case
MVM_DEBUGFS_PM_LPRX_ENA
:
IWL_DEBUG_POWER
(
mvm
,
"lprx %s
\n
"
,
val
?
"enabled"
:
"disabled"
);
dbgfs_pm
->
lprx_ena
=
val
;
break
;
case
MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD
:
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
;
case
MVM_DEBUGFS_PM_UAPSD_MISBEHAVING
:
IWL_DEBUG_POWER
(
mvm
,
"uapsd_misbehaving_enable=%d
\n
"
,
val
);
dbgfs_pm
->
uapsd_misbehaving
=
val
;
break
;
}
}
static
ssize_t
iwl_dbgfs_pm_params_write
(
struct
ieee80211_vif
*
vif
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
struct
iwl_mvm
*
mvm
=
mvmvif
->
mvm
;
enum
iwl_dbgfs_pm_mask
param
;
int
val
,
ret
;
if
(
!
strncmp
(
"keep_alive="
,
buf
,
11
))
{
if
(
sscanf
(
buf
+
11
,
"%d"
,
&
val
)
!=
1
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_PM_KEEP_ALIVE
;
}
else
if
(
!
strncmp
(
"skip_over_dtim="
,
buf
,
15
))
{
if
(
sscanf
(
buf
+
15
,
"%d"
,
&
val
)
!=
1
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_PM_SKIP_OVER_DTIM
;
}
else
if
(
!
strncmp
(
"skip_dtim_periods="
,
buf
,
18
))
{
if
(
sscanf
(
buf
+
18
,
"%d"
,
&
val
)
!=
1
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS
;
}
else
if
(
!
strncmp
(
"rx_data_timeout="
,
buf
,
16
))
{
if
(
sscanf
(
buf
+
16
,
"%d"
,
&
val
)
!=
1
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_PM_RX_DATA_TIMEOUT
;
}
else
if
(
!
strncmp
(
"tx_data_timeout="
,
buf
,
16
))
{
if
(
sscanf
(
buf
+
16
,
"%d"
,
&
val
)
!=
1
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_PM_TX_DATA_TIMEOUT
;
}
else
if
(
!
strncmp
(
"disable_power_off="
,
buf
,
18
)
&&
!
(
mvm
->
fw
->
ucode_capa
.
flags
&
IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD
))
{
if
(
sscanf
(
buf
+
18
,
"%d"
,
&
val
)
!=
1
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_PM_DISABLE_POWER_OFF
;
}
else
if
(
!
strncmp
(
"lprx="
,
buf
,
5
))
{
if
(
sscanf
(
buf
+
5
,
"%d"
,
&
val
)
!=
1
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_PM_LPRX_ENA
;
}
else
if
(
!
strncmp
(
"lprx_rssi_threshold="
,
buf
,
20
))
{
if
(
sscanf
(
buf
+
20
,
"%d"
,
&
val
)
!=
1
)
return
-
EINVAL
;
if
(
val
>
POWER_LPRX_RSSI_THRESHOLD_MAX
||
val
<
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
if
(
!
strncmp
(
"uapsd_misbehaving="
,
buf
,
18
))
{
if
(
sscanf
(
buf
+
18
,
"%d"
,
&
val
)
!=
1
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_PM_UAPSD_MISBEHAVING
;
}
else
{
return
-
EINVAL
;
}
mutex_lock
(
&
mvm
->
mutex
);
iwl_dbgfs_update_pm
(
mvm
,
vif
,
param
,
val
);
ret
=
iwl_mvm_power_update_mode
(
mvm
,
vif
);
mutex_unlock
(
&
mvm
->
mutex
);
return
ret
?:
count
;
}
static
ssize_t
iwl_dbgfs_pm_params_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
ieee80211_vif
*
vif
=
file
->
private_data
;
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
struct
iwl_mvm
*
mvm
=
mvmvif
->
mvm
;
char
buf
[
512
];
int
bufsz
=
sizeof
(
buf
);
int
pos
;
pos
=
iwl_mvm_power_dbgfs_read
(
mvm
,
vif
,
buf
,
bufsz
);
return
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
pos
);
}
static
ssize_t
iwl_dbgfs_mac_params_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
...
...
@@ -125,6 +269,201 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
return
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
pos
);
}
static
void
iwl_dbgfs_update_bf
(
struct
ieee80211_vif
*
vif
,
enum
iwl_dbgfs_bf_mask
param
,
int
value
)
{
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
struct
iwl_dbgfs_bf
*
dbgfs_bf
=
&
mvmvif
->
dbgfs_bf
;
dbgfs_bf
->
mask
|=
param
;
switch
(
param
)
{
case
MVM_DEBUGFS_BF_ENERGY_DELTA
:
dbgfs_bf
->
bf_energy_delta
=
value
;
break
;
case
MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA
:
dbgfs_bf
->
bf_roaming_energy_delta
=
value
;
break
;
case
MVM_DEBUGFS_BF_ROAMING_STATE
:
dbgfs_bf
->
bf_roaming_state
=
value
;
break
;
case
MVM_DEBUGFS_BF_TEMP_THRESHOLD
:
dbgfs_bf
->
bf_temp_threshold
=
value
;
break
;
case
MVM_DEBUGFS_BF_TEMP_FAST_FILTER
:
dbgfs_bf
->
bf_temp_fast_filter
=
value
;
break
;
case
MVM_DEBUGFS_BF_TEMP_SLOW_FILTER
:
dbgfs_bf
->
bf_temp_slow_filter
=
value
;
break
;
case
MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
:
dbgfs_bf
->
bf_enable_beacon_filter
=
value
;
break
;
case
MVM_DEBUGFS_BF_DEBUG_FLAG
:
dbgfs_bf
->
bf_debug_flag
=
value
;
break
;
case
MVM_DEBUGFS_BF_ESCAPE_TIMER
:
dbgfs_bf
->
bf_escape_timer
=
value
;
break
;
case
MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT
:
dbgfs_bf
->
ba_enable_beacon_abort
=
value
;
break
;
case
MVM_DEBUGFS_BA_ESCAPE_TIMER
:
dbgfs_bf
->
ba_escape_timer
=
value
;
break
;
}
}
static
ssize_t
iwl_dbgfs_bf_params_write
(
struct
ieee80211_vif
*
vif
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
struct
iwl_mvm
*
mvm
=
mvmvif
->
mvm
;
enum
iwl_dbgfs_bf_mask
param
;
int
value
,
ret
=
0
;
if
(
!
strncmp
(
"bf_energy_delta="
,
buf
,
16
))
{
if
(
sscanf
(
buf
+
16
,
"%d"
,
&
value
)
!=
1
)
return
-
EINVAL
;
if
(
value
<
IWL_BF_ENERGY_DELTA_MIN
||
value
>
IWL_BF_ENERGY_DELTA_MAX
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_BF_ENERGY_DELTA
;
}
else
if
(
!
strncmp
(
"bf_roaming_energy_delta="
,
buf
,
24
))
{
if
(
sscanf
(
buf
+
24
,
"%d"
,
&
value
)
!=
1
)
return
-
EINVAL
;
if
(
value
<
IWL_BF_ROAMING_ENERGY_DELTA_MIN
||
value
>
IWL_BF_ROAMING_ENERGY_DELTA_MAX
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA
;
}
else
if
(
!
strncmp
(
"bf_roaming_state="
,
buf
,
17
))
{
if
(
sscanf
(
buf
+
17
,
"%d"
,
&
value
)
!=
1
)
return
-
EINVAL
;
if
(
value
<
IWL_BF_ROAMING_STATE_MIN
||
value
>
IWL_BF_ROAMING_STATE_MAX
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_BF_ROAMING_STATE
;
}
else
if
(
!
strncmp
(
"bf_temp_threshold="
,
buf
,
18
))
{
if
(
sscanf
(
buf
+
18
,
"%d"
,
&
value
)
!=
1
)
return
-
EINVAL
;
if
(
value
<
IWL_BF_TEMP_THRESHOLD_MIN
||
value
>
IWL_BF_TEMP_THRESHOLD_MAX
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_BF_TEMP_THRESHOLD
;
}
else
if
(
!
strncmp
(
"bf_temp_fast_filter="
,
buf
,
20
))
{
if
(
sscanf
(
buf
+
20
,
"%d"
,
&
value
)
!=
1
)
return
-
EINVAL
;
if
(
value
<
IWL_BF_TEMP_FAST_FILTER_MIN
||
value
>
IWL_BF_TEMP_FAST_FILTER_MAX
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_BF_TEMP_FAST_FILTER
;
}
else
if
(
!
strncmp
(
"bf_temp_slow_filter="
,
buf
,
20
))
{
if
(
sscanf
(
buf
+
20
,
"%d"
,
&
value
)
!=
1
)
return
-
EINVAL
;
if
(
value
<
IWL_BF_TEMP_SLOW_FILTER_MIN
||
value
>
IWL_BF_TEMP_SLOW_FILTER_MAX
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_BF_TEMP_SLOW_FILTER
;
}
else
if
(
!
strncmp
(
"bf_enable_beacon_filter="
,
buf
,
24
))
{
if
(
sscanf
(
buf
+
24
,
"%d"
,
&
value
)
!=
1
)
return
-
EINVAL
;
if
(
value
<
0
||
value
>
1
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
;
}
else
if
(
!
strncmp
(
"bf_debug_flag="
,
buf
,
14
))
{
if
(
sscanf
(
buf
+
14
,
"%d"
,
&
value
)
!=
1
)
return
-
EINVAL
;
if
(
value
<
0
||
value
>
1
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_BF_DEBUG_FLAG
;
}
else
if
(
!
strncmp
(
"bf_escape_timer="
,
buf
,
16
))
{
if
(
sscanf
(
buf
+
16
,
"%d"
,
&
value
)
!=
1
)
return
-
EINVAL
;
if
(
value
<
IWL_BF_ESCAPE_TIMER_MIN
||
value
>
IWL_BF_ESCAPE_TIMER_MAX
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_BF_ESCAPE_TIMER
;
}
else
if
(
!
strncmp
(
"ba_escape_timer="
,
buf
,
16
))
{
if
(
sscanf
(
buf
+
16
,
"%d"
,
&
value
)
!=
1
)
return
-
EINVAL
;
if
(
value
<
IWL_BA_ESCAPE_TIMER_MIN
||
value
>
IWL_BA_ESCAPE_TIMER_MAX
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_BA_ESCAPE_TIMER
;
}
else
if
(
!
strncmp
(
"ba_enable_beacon_abort="
,
buf
,
23
))
{
if
(
sscanf
(
buf
+
23
,
"%d"
,
&
value
)
!=
1
)
return
-
EINVAL
;
if
(
value
<
0
||
value
>
1
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT
;
}
else
{
return
-
EINVAL
;
}
mutex_lock
(
&
mvm
->
mutex
);
iwl_dbgfs_update_bf
(
vif
,
param
,
value
);
if
(
param
==
MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
&&
!
value
)
ret
=
iwl_mvm_disable_beacon_filter
(
mvm
,
vif
);
else
ret
=
iwl_mvm_enable_beacon_filter
(
mvm
,
vif
);
mutex_unlock
(
&
mvm
->
mutex
);
return
ret
?:
count
;
}
static
ssize_t
iwl_dbgfs_bf_params_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
ieee80211_vif
*
vif
=
file
->
private_data
;
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
char
buf
[
256
];
int
pos
=
0
;
const
size_t
bufsz
=
sizeof
(
buf
);
struct
iwl_beacon_filter_cmd
cmd
=
{
IWL_BF_CMD_CONFIG_DEFAULTS
,
.
bf_enable_beacon_filter
=
cpu_to_le32
(
IWL_BF_ENABLE_BEACON_FILTER_DEFAULT
),
.
ba_enable_beacon_abort
=
cpu_to_le32
(
IWL_BA_ENABLE_BEACON_ABORT_DEFAULT
),
};
iwl_mvm_beacon_filter_debugfs_parameters
(
vif
,
&
cmd
);
if
(
mvmvif
->
bf_data
.
bf_enabled
)
cmd
.
bf_enable_beacon_filter
=
cpu_to_le32
(
1
);
else
cmd
.
bf_enable_beacon_filter
=
0
;
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"bf_energy_delta = %d
\n
"
,
le32_to_cpu
(
cmd
.
bf_energy_delta
));
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"bf_roaming_energy_delta = %d
\n
"
,
le32_to_cpu
(
cmd
.
bf_roaming_energy_delta
));
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"bf_roaming_state = %d
\n
"
,
le32_to_cpu
(
cmd
.
bf_roaming_state
));
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"bf_temp_threshold = %d
\n
"
,
le32_to_cpu
(
cmd
.
bf_temp_threshold
));
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"bf_temp_fast_filter = %d
\n
"
,
le32_to_cpu
(
cmd
.
bf_temp_fast_filter
));
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"bf_temp_slow_filter = %d
\n
"
,
le32_to_cpu
(
cmd
.
bf_temp_slow_filter
));
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"bf_enable_beacon_filter = %d
\n
"
,
le32_to_cpu
(
cmd
.
bf_enable_beacon_filter
));
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"bf_debug_flag = %d
\n
"
,
le32_to_cpu
(
cmd
.
bf_debug_flag
));
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"bf_escape_timer = %d
\n
"
,
le32_to_cpu
(
cmd
.
bf_escape_timer
));
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"ba_escape_timer = %d
\n
"
,
le32_to_cpu
(
cmd
.
ba_escape_timer
));
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"ba_enable_beacon_abort = %d
\n
"
,
le32_to_cpu
(
cmd
.
ba_enable_beacon_abort
));
return
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
pos
);
}
#define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
_MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
_MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
#define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \
if (!debugfs_create_file(#name, mode, parent, vif, \
&iwl_dbgfs_##name##_ops)) \
...
...
@@ -132,6 +471,8 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
} while (0)
MVM_DEBUGFS_READ_FILE_OPS
(
mac_params
);
MVM_DEBUGFS_READ_WRITE_FILE_OPS
(
pm_params
,
32
);
MVM_DEBUGFS_READ_WRITE_FILE_OPS
(
bf_params
,
256
);
void
iwl_mvm_vif_dbgfs_register
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
)
{
...
...
@@ -155,9 +496,21 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
return
;
}
if
(
iwlmvm_mod_params
.
power_scheme
!=
IWL_POWER_SCHEME_CAM
&&
((
vif
->
type
==
NL80211_IFTYPE_STATION
&&
!
vif
->
p2p
)
||
(
vif
->
type
==
NL80211_IFTYPE_STATION
&&
vif
->
p2p
&&
mvm
->
fw
->
ucode_capa
.
flags
&
IWL_UCODE_TLV_FLAGS_P2P_PS
)))
MVM_DEBUGFS_ADD_FILE_VIF
(
pm_params
,
mvmvif
->
dbgfs_dir
,
S_IWUSR
|
S_IRUSR
);
MVM_DEBUGFS_ADD_FILE_VIF
(
mac_params
,
mvmvif
->
dbgfs_dir
,
S_IRUSR
);
if
(
vif
->
type
==
NL80211_IFTYPE_STATION
&&
!
vif
->
p2p
&&
mvmvif
==
mvm
->
bf_allowed_vif
)
MVM_DEBUGFS_ADD_FILE_VIF
(
bf_params
,
mvmvif
->
dbgfs_dir
,
S_IRUSR
|
S_IWUSR
);
/*
* Create symlink for convenience pointing to interface specific
* debugfs entries for the driver. For example, under
...
...
drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
浏览文件 @
623c4387
...
...
@@ -85,6 +85,8 @@
* PBW Snoozing enabled
* @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask
* @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
* @POWER_FLAGS_AP_UAPSD_MISBEHAVING_ENA_MSK: AP/GO's uAPSD misbehaving
* detection enablement
*/
enum
iwl_power_flags
{
POWER_FLAGS_POWER_SAVE_ENA_MSK
=
BIT
(
0
),
...
...
@@ -94,6 +96,7 @@ enum iwl_power_flags {
POWER_FLAGS_BT_SCO_ENA
=
BIT
(
8
),
POWER_FLAGS_ADVANCE_PM_ENA_MSK
=
BIT
(
9
),
POWER_FLAGS_LPRX_ENA_MSK
=
BIT
(
11
),
POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK
=
BIT
(
12
),
};
#define IWL_POWER_VEC_SIZE 5
...
...
@@ -228,6 +231,19 @@ struct iwl_mac_power_cmd {
u8
reserved
;
}
__packed
;
/*
* struct iwl_uapsd_misbehaving_ap_notif - FW sends this notification when
* associated AP is identified as improperly implementing uAPSD protocol.
* PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78
* @sta_id: index of station in uCode's station table - associated AP ID in
* this context.
*/
struct
iwl_uapsd_misbehaving_ap_notif
{
__le32
sta_id
;
u8
mac_id
;
u8
reserved
[
3
];
}
__packed
;
/**
* struct iwl_beacon_filter_cmd
* REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
...
...
drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
浏览文件 @
623c4387
...
...
@@ -138,7 +138,14 @@ enum iwl_sta_flags {
/**
* enum iwl_sta_key_flag - key flags for the ADD_STA host command
* @STA_KEY_FLG_EN_MSK: mask for encryption algorithm
* @STA_KEY_FLG_NO_ENC: no encryption
* @STA_KEY_FLG_WEP: WEP encryption algorithm
* @STA_KEY_FLG_CCM: CCMP encryption algorithm
* @STA_KEY_FLG_TKIP: TKIP encryption algorithm
* @STA_KEY_FLG_EXT: extended cipher algorithm (depends on the FW support)
* @STA_KEY_FLG_CMAC: CMAC encryption algorithm
* @STA_KEY_FLG_ENC_UNKNOWN: unknown encryption algorithm
* @STA_KEY_FLG_EN_MSK: mask for encryption algorithmi value
* @STA_KEY_FLG_WEP_KEY_MAP: wep is either a group key (0 - legacy WEP) or from
* station info array (1 - n 1X mode)
* @STA_KEY_FLG_KEYID_MSK: the index of the key
...
...
@@ -152,6 +159,7 @@ enum iwl_sta_key_flag {
STA_KEY_FLG_WEP
=
(
1
<<
0
),
STA_KEY_FLG_CCM
=
(
2
<<
0
),
STA_KEY_FLG_TKIP
=
(
3
<<
0
),
STA_KEY_FLG_EXT
=
(
4
<<
0
),
STA_KEY_FLG_CMAC
=
(
6
<<
0
),
STA_KEY_FLG_ENC_UNKNOWN
=
(
7
<<
0
),
STA_KEY_FLG_EN_MSK
=
(
7
<<
0
),
...
...
drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
浏览文件 @
623c4387
...
...
@@ -132,6 +132,7 @@ enum iwl_tx_flags {
#define TX_CMD_SEC_WEP 0x01
#define TX_CMD_SEC_CCM 0x02
#define TX_CMD_SEC_TKIP 0x03
#define TX_CMD_SEC_EXT 0x04
#define TX_CMD_SEC_MSK 0x07
#define TX_CMD_SEC_WEP_KEY_IDX_POS 6
#define TX_CMD_SEC_WEP_KEY_IDX_MSK 0xc0
...
...
drivers/net/wireless/iwlwifi/mvm/fw-api.h
浏览文件 @
623c4387
...
...
@@ -141,6 +141,7 @@ enum {
/* Power - legacy power table command */
POWER_TABLE_CMD
=
0x77
,
PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION
=
0x78
,
/* Thermal Throttling*/
REPLY_THERMAL_MNG_BACKOFF
=
0x7e
,
...
...
@@ -183,6 +184,7 @@ enum {
BT_PROFILE_NOTIFICATION
=
0xce
,
BT_COEX_CI
=
0x5d
,
REPLY_SF_CFG_CMD
=
0xd1
,
REPLY_BEACON_FILTERING_CMD
=
0xd2
,
REPLY_DEBUG_CMD
=
0xf0
,
...
...
@@ -1052,6 +1054,7 @@ enum iwl_mvm_rx_status {
RX_MPDU_RES_STATUS_SEC_WEP_ENC
=
(
1
<<
8
),
RX_MPDU_RES_STATUS_SEC_CCM_ENC
=
(
2
<<
8
),
RX_MPDU_RES_STATUS_SEC_TKIP_ENC
=
(
3
<<
8
),
RX_MPDU_RES_STATUS_SEC_EXT_ENC
=
(
4
<<
8
),
RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC
=
(
6
<<
8
),
RX_MPDU_RES_STATUS_SEC_ENC_ERR
=
(
7
<<
8
),
RX_MPDU_RES_STATUS_SEC_ENC_MSK
=
(
7
<<
8
),
...
...
@@ -1131,6 +1134,7 @@ struct iwl_set_calib_default_cmd {
}
__packed
;
/* PHY_CALIB_OVERRIDE_VALUES_S */
#define MAX_PORT_ID_NUM 2
#define MAX_MCAST_FILTERING_ADDRESSES 256
/**
* struct iwl_mcast_filter_cmd - configure multicast filter.
...
...
@@ -1363,4 +1367,65 @@ struct iwl_notif_statistics { /* STATISTICS_NTFY_API_S_VER_8 */
struct
mvm_statistics_general
general
;
}
__packed
;
/***********************************
* Smart Fifo API
***********************************/
/* Smart Fifo state */
enum
iwl_sf_state
{
SF_LONG_DELAY_ON
=
0
,
/* should never be called by driver */
SF_FULL_ON
,
SF_UNINIT
,
SF_INIT_OFF
,
SF_HW_NUM_STATES
};
/* Smart Fifo possible scenario */
enum
iwl_sf_scenario
{
SF_SCENARIO_SINGLE_UNICAST
,
SF_SCENARIO_AGG_UNICAST
,
SF_SCENARIO_MULTICAST
,
SF_SCENARIO_BA_RESP
,
SF_SCENARIO_TX_RESP
,
SF_NUM_SCENARIO
};
#define SF_TRANSIENT_STATES_NUMBER 2
/* SF_LONG_DELAY_ON and SF_FULL_ON */
#define SF_NUM_TIMEOUT_TYPES 2
/* Aging timer and Idle timer */
/* smart FIFO default values */
#define SF_W_MARK_SISO 4096
#define SF_W_MARK_MIMO2 8192
#define SF_W_MARK_MIMO3 6144
#define SF_W_MARK_LEGACY 4096
#define SF_W_MARK_SCAN 4096
/* SF Scenarios timers for FULL_ON state (aligned to 32 uSec) */
#define SF_SINGLE_UNICAST_IDLE_TIMER 320
/* 300 uSec */
#define SF_SINGLE_UNICAST_AGING_TIMER 2016
/* 2 mSec */
#define SF_AGG_UNICAST_IDLE_TIMER 320
/* 300 uSec */
#define SF_AGG_UNICAST_AGING_TIMER 2016
/* 2 mSec */
#define SF_MCAST_IDLE_TIMER 2016
/* 2 mSec */
#define SF_MCAST_AGING_TIMER 10016
/* 10 mSec */
#define SF_BA_IDLE_TIMER 320
/* 300 uSec */
#define SF_BA_AGING_TIMER 2016
/* 2 mSec */
#define SF_TX_RE_IDLE_TIMER 320
/* 300 uSec */
#define SF_TX_RE_AGING_TIMER 2016
/* 2 mSec */
#define SF_LONG_DELAY_AGING_TIMER 1000000
/* 1 Sec */
/**
* Smart Fifo configuration command.
* @state: smart fifo state, types listed in iwl_sf_sate.
* @watermark: Minimum allowed availabe free space in RXF for transient state.
* @long_delay_timeouts: aging and idle timer values for each scenario
* in long delay state.
* @full_on_timeouts: timer values for each scenario in full on state.
*/
struct
iwl_sf_cfg_cmd
{
enum
iwl_sf_state
state
;
__le32
watermark
[
SF_TRANSIENT_STATES_NUMBER
];
__le32
long_delay_timeouts
[
SF_NUM_SCENARIO
][
SF_NUM_TIMEOUT_TYPES
];
__le32
full_on_timeouts
[
SF_NUM_SCENARIO
][
SF_NUM_TIMEOUT_TYPES
];
}
__packed
;
/* SF_CFG_API_S_VER_2 */
#endif
/* __fw_api_h__ */
drivers/net/wireless/iwlwifi/mvm/fw.c
浏览文件 @
623c4387
...
...
@@ -241,7 +241,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
lockdep_assert_held
(
&
mvm
->
mutex
);
if
(
mvm
->
init_ucode_complete
)
if
(
WARN_ON_ONCE
(
mvm
->
init_ucode_complete
)
)
return
0
;
iwl_init_notification_wait
(
&
mvm
->
notif_wait
,
...
...
@@ -287,7 +287,8 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
IWL_DEBUG_RF_KILL
(
mvm
,
"jump over all phy activities due to RF kill
\n
"
);
iwl_remove_notification
(
&
mvm
->
notif_wait
,
&
calib_wait
);
return
1
;
ret
=
1
;
goto
out
;
}
/* Send TX valid antennas before triggering calibrations */
...
...
@@ -319,9 +320,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
error:
iwl_remove_notification
(
&
mvm
->
notif_wait
,
&
calib_wait
);
out:
if
(
!
iwlmvm_mod_params
.
init_dbg
)
{
iwl_trans_stop_device
(
mvm
->
trans
);
}
else
if
(
!
mvm
->
nvm_data
)
{
if
(
iwlmvm_mod_params
.
init_dbg
&&
!
mvm
->
nvm_data
)
{
/* we want to debug INIT and we have no NVM - fake */
mvm
->
nvm_data
=
kzalloc
(
sizeof
(
struct
iwl_nvm_data
)
+
sizeof
(
struct
ieee80211_channel
)
+
...
...
@@ -370,11 +369,16 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
ret
=
-
ERFKILL
;
goto
error
;
}
/* should stop & start HW since that INIT image just loaded */
iwl_trans_stop_hw
(
mvm
->
trans
,
false
);
ret
=
iwl_trans_start_hw
(
mvm
->
trans
);
if
(
ret
)
return
ret
;
if
(
!
iwlmvm_mod_params
.
init_dbg
)
{
/*
* should stop and start HW since that INIT
* image just loaded
*/
iwl_trans_stop_device
(
mvm
->
trans
);
ret
=
iwl_trans_start_hw
(
mvm
->
trans
);
if
(
ret
)
return
ret
;
}
}
if
(
iwlmvm_mod_params
.
init_dbg
)
...
...
@@ -386,6 +390,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto
error
;
}
ret
=
iwl_mvm_sf_update
(
mvm
,
NULL
,
false
);
if
(
ret
)
IWL_ERR
(
mvm
,
"Failed to initialize Smart Fifo
\n
"
);
ret
=
iwl_send_tx_ant_cfg
(
mvm
,
iwl_fw_valid_tx_ant
(
mvm
->
fw
));
if
(
ret
)
goto
error
;
...
...
drivers/net/wireless/iwlwifi/mvm/mac80211.c
浏览文件 @
623c4387
...
...
@@ -261,6 +261,12 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
mvm
->
rts_threshold
=
IEEE80211_MAX_RTS_THRESHOLD
;
/* currently FW API supports only one optional cipher scheme */
if
(
mvm
->
fw
->
cs
&&
mvm
->
fw
->
cs
->
cipher
)
{
mvm
->
hw
->
n_cipher_schemes
=
1
;
mvm
->
hw
->
cipher_schemes
=
mvm
->
fw
->
cs
;
}
#ifdef CONFIG_PM_SLEEP
if
(
mvm
->
fw
->
img
[
IWL_UCODE_WOWLAN
].
sec
[
0
].
len
&&
mvm
->
trans
->
ops
->
d3_suspend
&&
...
...
@@ -399,7 +405,6 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
static
void
iwl_mvm_restart_cleanup
(
struct
iwl_mvm
*
mvm
)
{
iwl_trans_stop_device
(
mvm
->
trans
);
iwl_trans_stop_hw
(
mvm
->
trans
,
false
);
mvm
->
scan_status
=
IWL_MVM_SCAN_NONE
;
...
...
@@ -471,7 +476,6 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
cancel_work_sync
(
&
mvm
->
roc_done_wk
);
iwl_trans_stop_device
(
mvm
->
trans
);
iwl_trans_stop_hw
(
mvm
->
trans
,
false
);
iwl_mvm_async_handlers_purge
(
mvm
);
/* async_handlers_list is empty and will stay empty: HW is stopped */
...
...
@@ -488,17 +492,6 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
cancel_work_sync
(
&
mvm
->
async_handlers_wk
);
}
static
void
iwl_mvm_pm_disable_iterator
(
void
*
data
,
u8
*
mac
,
struct
ieee80211_vif
*
vif
)
{
struct
iwl_mvm
*
mvm
=
data
;
int
ret
;
ret
=
iwl_mvm_power_disable
(
mvm
,
vif
);
if
(
ret
)
IWL_ERR
(
mvm
,
"failed to disable power management
\n
"
);
}
static
void
iwl_mvm_power_update_iterator
(
void
*
data
,
u8
*
mac
,
struct
ieee80211_vif
*
vif
)
{
...
...
@@ -521,6 +514,20 @@ static struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm)
return
NULL
;
}
static
int
iwl_mvm_set_tx_power
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
s8
tx_power
)
{
/* FW is in charge of regulatory enforcement */
struct
iwl_reduce_tx_power_cmd
reduce_txpwr_cmd
=
{
.
mac_context_id
=
iwl_mvm_vif_from_mac80211
(
vif
)
->
id
,
.
pwr_restriction
=
cpu_to_le16
(
tx_power
),
};
return
iwl_mvm_send_cmd_pdu
(
mvm
,
REDUCE_TX_POWER_CMD
,
CMD_SYNC
,
sizeof
(
reduce_txpwr_cmd
),
&
reduce_txpwr_cmd
);
}
static
int
iwl_mvm_mac_add_interface
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
)
{
...
...
@@ -541,26 +548,9 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
if
(
ret
)
goto
out_unlock
;
/*
* TODO: remove this temporary code.
* Currently MVM FW supports power management only on single MAC.
* If new interface added, disable PM on existing interface.
* P2P device is a special case, since it is handled by FW similary to
* scan. If P2P deviced is added, PM remains enabled on existing
* interface.
* Note: the method below does not count the new interface being added
* at this moment.
*/
/* Counting number of interfaces is needed for legacy PM */
if
(
vif
->
type
!=
NL80211_IFTYPE_P2P_DEVICE
)
mvm
->
vif_count
++
;
if
(
mvm
->
vif_count
>
1
)
{
IWL_DEBUG_MAC80211
(
mvm
,
"Disable power on existing interfaces
\n
"
);
ieee80211_iterate_active_interfaces_atomic
(
mvm
->
hw
,
IEEE80211_IFACE_ITER_NORMAL
,
iwl_mvm_pm_disable_iterator
,
mvm
);
}
/*
* The AP binding flow can be done only after the beacon
...
...
@@ -591,11 +581,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
if
(
ret
)
goto
out_release
;
/*
* Update power state on the new interface. Admittedly, based on
* mac80211 logics this power update will disable power management
*/
iwl_mvm_power_update_mode
(
mvm
,
vif
);
iwl_mvm_power_disable
(
mvm
,
vif
);
/* beacon filtering */
ret
=
iwl_mvm_disable_beacon_filter
(
mvm
,
vif
);
...
...
@@ -656,9 +642,12 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
out_release:
if
(
vif
->
type
!=
NL80211_IFTYPE_P2P_DEVICE
)
mvm
->
vif_count
--
;
/* TODO: remove this when legacy PM will be discarded */
ieee80211_iterate_active_interfaces
(
mvm
->
hw
,
IEEE80211_IFACE_ITER_NORMAL
,
iwl_mvm_power_update_iterator
,
mvm
);
iwl_mvm_mac_ctxt_release
(
mvm
,
vif
);
out_unlock:
mutex_unlock
(
&
mvm
->
mutex
);
...
...
@@ -744,21 +733,13 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
mvmvif
->
phy_ctxt
=
NULL
;
}
/*
* TODO: remove this temporary code.
* Currently MVM FW supports power management only on single MAC.
* Check if only one additional interface remains after removing
* current one. Update power mode on the remaining interface.
*/
if
(
mvm
->
vif_count
&&
vif
->
type
!=
NL80211_IFTYPE_P2P_DEVICE
)
mvm
->
vif_count
--
;
IWL_DEBUG_MAC80211
(
mvm
,
"Currently %d interfaces active
\n
"
,
mvm
->
vif_count
);
if
(
mvm
->
vif_count
==
1
)
{
ieee80211_iterate_active_interfaces
(
mvm
->
hw
,
IEEE80211_IFACE_ITER_NORMAL
,
iwl_mvm_power_update_iterator
,
mvm
);
}
/* TODO: remove this when legacy PM will be discarded */
ieee80211_iterate_active_interfaces
(
mvm
->
hw
,
IEEE80211_IFACE_ITER_NORMAL
,
iwl_mvm_power_update_iterator
,
mvm
);
iwl_mvm_mac_ctxt_remove
(
mvm
,
vif
);
...
...
@@ -767,23 +748,91 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
mutex_unlock
(
&
mvm
->
mutex
);
}
static
int
iwl_mvm_set_tx_power
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
s8
tx_power
)
static
int
iwl_mvm_mac_config
(
struct
ieee80211_hw
*
hw
,
u32
changed
)
{
/* FW is in charge of regulatory enforcement */
struct
iwl_reduce_tx_power_cmd
reduce_txpwr_cmd
=
{
.
mac_context_id
=
iwl_mvm_vif_from_mac80211
(
vif
)
->
id
,
.
pwr_restriction
=
cpu_to_le16
(
tx_power
),
return
0
;
}
struct
iwl_mvm_mc_iter_data
{
struct
iwl_mvm
*
mvm
;
int
port_id
;
};
static
void
iwl_mvm_mc_iface_iterator
(
void
*
_data
,
u8
*
mac
,
struct
ieee80211_vif
*
vif
)
{
struct
iwl_mvm_mc_iter_data
*
data
=
_data
;
struct
iwl_mvm
*
mvm
=
data
->
mvm
;
struct
iwl_mcast_filter_cmd
*
cmd
=
mvm
->
mcast_filter_cmd
;
int
ret
,
len
;
/* if we don't have free ports, mcast frames will be dropped */
if
(
WARN_ON_ONCE
(
data
->
port_id
>=
MAX_PORT_ID_NUM
))
return
;
if
(
vif
->
type
!=
NL80211_IFTYPE_STATION
||
!
vif
->
bss_conf
.
assoc
)
return
;
cmd
->
port_id
=
data
->
port_id
++
;
memcpy
(
cmd
->
bssid
,
vif
->
bss_conf
.
bssid
,
ETH_ALEN
);
len
=
roundup
(
sizeof
(
*
cmd
)
+
cmd
->
count
*
ETH_ALEN
,
4
);
ret
=
iwl_mvm_send_cmd_pdu
(
mvm
,
MCAST_FILTER_CMD
,
CMD_SYNC
,
len
,
cmd
);
if
(
ret
)
IWL_ERR
(
mvm
,
"mcast filter cmd error. ret=%d
\n
"
,
ret
);
}
static
void
iwl_mvm_recalc_multicast
(
struct
iwl_mvm
*
mvm
)
{
struct
iwl_mvm_mc_iter_data
iter_data
=
{
.
mvm
=
mvm
,
};
return
iwl_mvm_send_cmd_pdu
(
mvm
,
REDUCE_TX_POWER_CMD
,
CMD_SYNC
,
sizeof
(
reduce_txpwr_cmd
),
&
reduce_txpwr_cmd
);
lockdep_assert_held
(
&
mvm
->
mutex
);
if
(
WARN_ON_ONCE
(
!
mvm
->
mcast_filter_cmd
))
return
;
ieee80211_iterate_active_interfaces
(
mvm
->
hw
,
IEEE80211_IFACE_ITER_NORMAL
,
iwl_mvm_mc_iface_iterator
,
&
iter_data
);
}
static
int
iwl_mvm_mac_config
(
struct
ieee80211_hw
*
hw
,
u32
changed
)
static
u64
iwl_mvm_prepare_multicast
(
struct
ieee80211_hw
*
hw
,
struct
netdev_hw_addr_list
*
mc_list
)
{
return
0
;
struct
iwl_mvm
*
mvm
=
IWL_MAC80211_GET_MVM
(
hw
);
struct
iwl_mcast_filter_cmd
*
cmd
;
struct
netdev_hw_addr
*
addr
;
int
addr_count
=
netdev_hw_addr_list_count
(
mc_list
);
bool
pass_all
=
false
;
int
len
;
if
(
addr_count
>
MAX_MCAST_FILTERING_ADDRESSES
)
{
pass_all
=
true
;
addr_count
=
0
;
}
len
=
roundup
(
sizeof
(
*
cmd
)
+
addr_count
*
ETH_ALEN
,
4
);
cmd
=
kzalloc
(
len
,
GFP_ATOMIC
);
if
(
!
cmd
)
return
0
;
if
(
pass_all
)
{
cmd
->
pass_all
=
1
;
return
(
u64
)(
unsigned
long
)
cmd
;
}
netdev_hw_addr_list_for_each
(
addr
,
mc_list
)
{
IWL_DEBUG_MAC80211
(
mvm
,
"mcast addr (%d): %pM
\n
"
,
cmd
->
count
,
addr
->
addr
);
memcpy
(
&
cmd
->
addr_list
[
cmd
->
count
*
ETH_ALEN
],
addr
->
addr
,
ETH_ALEN
);
cmd
->
count
++
;
}
return
(
u64
)(
unsigned
long
)
cmd
;
}
static
void
iwl_mvm_configure_filter
(
struct
ieee80211_hw
*
hw
,
...
...
@@ -791,21 +840,22 @@ static void iwl_mvm_configure_filter(struct ieee80211_hw *hw,
unsigned
int
*
total_flags
,
u64
multicast
)
{
*
total_flags
=
0
;
}
struct
iwl_mvm
*
mvm
=
IWL_MAC80211_GET_MVM
(
hw
)
;
struct
iwl_mcast_filter_cmd
*
cmd
=
(
void
*
)(
unsigned
long
)
multicast
;
static
int
iwl_mvm_configure_mcast_filter
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
)
{
struct
iwl_mcast_filter_cmd
mcast_filter_cmd
=
{
.
pass_all
=
1
,
};
mutex_lock
(
&
mvm
->
mutex
);
/* replace previous configuration */
kfree
(
mvm
->
mcast_filter_cmd
);
mvm
->
mcast_filter_cmd
=
cmd
;
memcpy
(
mcast_filter_cmd
.
bssid
,
vif
->
bss_conf
.
bssid
,
ETH_ALEN
);
if
(
!
cmd
)
goto
out
;
return
iwl_mvm_send_cmd_pdu
(
mvm
,
MCAST_FILTER_CMD
,
CMD_SYNC
,
sizeof
(
mcast_filter_cmd
),
&
mcast_filter_cmd
);
iwl_mvm_recalc_multicast
(
mvm
);
out:
mutex_unlock
(
&
mvm
->
mutex
);
*
total_flags
=
0
;
}
static
void
iwl_mvm_bss_info_changed_station
(
struct
iwl_mvm
*
mvm
,
...
...
@@ -828,7 +878,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
IWL_ERR
(
mvm
,
"failed to update quotas
\n
"
);
return
;
}
iwl_mvm_configure_mcast_filter
(
mvm
,
vif
);
if
(
test_bit
(
IWL_MVM_STATUS_IN_HW_RESTART
,
&
mvm
->
status
))
{
...
...
@@ -850,7 +899,17 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
iwl_mvm_protect_session
(
mvm
,
vif
,
dur
,
dur
,
5
*
dur
);
}
iwl_mvm_sf_update
(
mvm
,
vif
,
false
);
iwl_mvm_power_vif_assoc
(
mvm
,
vif
);
}
else
if
(
mvmvif
->
ap_sta_id
!=
IWL_MVM_STATION_COUNT
)
{
/*
* If update fails - SF might be running in associated
* mode while disassociated - which is forbidden.
*/
WARN_ONCE
(
iwl_mvm_sf_update
(
mvm
,
vif
,
false
),
"Failed to update SF upon disassociation
\n
"
);
/* remove AP station now that the MAC is unassoc */
ret
=
iwl_mvm_rm_sta_id
(
mvm
,
vif
,
mvmvif
->
ap_sta_id
);
if
(
ret
)
...
...
@@ -862,6 +921,8 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
IWL_ERR
(
mvm
,
"failed to update quotas
\n
"
);
}
iwl_mvm_recalc_multicast
(
mvm
);
/* reset rssi values */
mvmvif
->
bf_data
.
ave_beacon_signal
=
0
;
...
...
@@ -882,7 +943,8 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
*/
iwl_mvm_remove_time_event
(
mvm
,
mvmvif
,
&
mvmvif
->
time_event_data
);
}
else
if
(
changes
&
(
BSS_CHANGED_PS
|
BSS_CHANGED_QOS
))
{
}
else
if
(
changes
&
(
BSS_CHANGED_PS
|
BSS_CHANGED_P2P_PS
|
BSS_CHANGED_QOS
))
{
ret
=
iwl_mvm_power_update_mode
(
mvm
,
vif
);
if
(
ret
)
IWL_ERR
(
mvm
,
"failed to update power mode
\n
"
);
...
...
@@ -991,11 +1053,16 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
struct
ieee80211_bss_conf
*
bss_conf
,
u32
changes
)
{
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
enum
ieee80211_bss_change
ht_change
=
BSS_CHANGED_ERP_CTS_PROT
|
BSS_CHANGED_HT
|
BSS_CHANGED_BANDWIDTH
;
int
ret
;
/* Changes will be applied when the AP/IBSS is started */
if
(
!
mvmvif
->
ap_ibss_active
)
return
;
if
(
changes
&
ht_change
)
{
ret
=
iwl_mvm_mac_ctxt_changed
(
mvm
,
vif
);
if
(
ret
)
...
...
@@ -1222,6 +1289,17 @@ static int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
return
0
;
}
static
void
iwl_mvm_sta_rc_update
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
u32
changed
)
{
struct
iwl_mvm
*
mvm
=
IWL_MAC80211_GET_MVM
(
hw
);
if
(
vif
->
type
==
NL80211_IFTYPE_STATION
&&
changed
&
IEEE80211_RC_NSS_CHANGED
)
iwl_mvm_sf_update
(
mvm
,
vif
,
false
);
}
static
int
iwl_mvm_mac_conf_tx
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
,
u16
ac
,
const
struct
ieee80211_tx_queue_params
*
params
)
...
...
@@ -1344,7 +1422,12 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
*/
return
0
;
default:
return
-
EOPNOTSUPP
;
/* currently FW supports only one optional cipher scheme */
if
(
hw
->
n_cipher_schemes
&&
hw
->
cipher_schemes
->
cipher
==
key
->
cipher
)
key
->
flags
|=
IEEE80211_KEY_FLAG_PUT_IV_SPACE
;
else
return
-
EOPNOTSUPP
;
}
mutex_lock
(
&
mvm
->
mutex
);
...
...
@@ -1550,7 +1633,7 @@ static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
goto
out
;
}
ret
=
iwl_mvm_phy_ctxt_changed
(
mvm
,
phy_ctxt
,
&
ctx
->
def
,
ret
=
iwl_mvm_phy_ctxt_changed
(
mvm
,
phy_ctxt
,
&
ctx
->
min_
def
,
ctx
->
rx_chains_static
,
ctx
->
rx_chains_dynamic
);
if
(
ret
)
{
...
...
@@ -1594,7 +1677,7 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
return
;
mutex_lock
(
&
mvm
->
mutex
);
iwl_mvm_phy_ctxt_changed
(
mvm
,
phy_ctxt
,
&
ctx
->
def
,
iwl_mvm_phy_ctxt_changed
(
mvm
,
phy_ctxt
,
&
ctx
->
min_
def
,
ctx
->
rx_chains_static
,
ctx
->
rx_chains_dynamic
);
iwl_mvm_bt_coex_vif_change
(
mvm
);
...
...
@@ -1637,7 +1720,13 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
goto
out_unlock
;
/*
* Setting the quota at this stage is only required for monitor
* Power state must be updated before quotas,
* otherwise fw will complain.
*/
mvm
->
bound_vif_cnt
++
;
iwl_mvm_power_update_binding
(
mvm
,
vif
,
true
);
/* Setting the quota at this stage is only required for monitor
* interfaces. For the other types, the bss_info changed flow
* will handle quota settings.
*/
...
...
@@ -1652,6 +1741,8 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
out_remove_binding:
iwl_mvm_binding_remove_vif
(
mvm
,
vif
);
mvm
->
bound_vif_cnt
--
;
iwl_mvm_power_update_binding
(
mvm
,
vif
,
false
);
out_unlock:
mutex_unlock
(
&
mvm
->
mutex
);
if
(
ret
)
...
...
@@ -1685,6 +1776,9 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
iwl_mvm_binding_remove_vif
(
mvm
,
vif
);
out_unlock:
mvmvif
->
phy_ctxt
=
NULL
;
mvm
->
bound_vif_cnt
--
;
iwl_mvm_power_update_binding
(
mvm
,
vif
,
false
);
mutex_unlock
(
&
mvm
->
mutex
);
}
...
...
@@ -1779,6 +1873,7 @@ struct ieee80211_ops iwl_mvm_hw_ops = {
.
add_interface
=
iwl_mvm_mac_add_interface
,
.
remove_interface
=
iwl_mvm_mac_remove_interface
,
.
config
=
iwl_mvm_mac_config
,
.
prepare_multicast
=
iwl_mvm_prepare_multicast
,
.
configure_filter
=
iwl_mvm_configure_filter
,
.
bss_info_changed
=
iwl_mvm_bss_info_changed
,
.
hw_scan
=
iwl_mvm_mac_hw_scan
,
...
...
@@ -1788,6 +1883,7 @@ struct ieee80211_ops iwl_mvm_hw_ops = {
.
sta_notify
=
iwl_mvm_mac_sta_notify
,
.
allow_buffered_frames
=
iwl_mvm_mac_allow_buffered_frames
,
.
set_rts_threshold
=
iwl_mvm_mac_set_rts_threshold
,
.
sta_rc_update
=
iwl_mvm_sta_rc_update
,
.
conf_tx
=
iwl_mvm_mac_conf_tx
,
.
mgd_prepare_tx
=
iwl_mvm_mac_mgd_prepare_tx
,
.
sched_scan_start
=
iwl_mvm_mac_sched_scan_start
,
...
...
drivers/net/wireless/iwlwifi/mvm/mvm.h
浏览文件 @
623c4387
...
...
@@ -163,6 +163,8 @@ struct iwl_mvm_power_ops {
struct
ieee80211_vif
*
vif
);
int
(
*
power_update_device_mode
)(
struct
iwl_mvm
*
mvm
);
int
(
*
power_disable
)(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
);
void
(
*
power_update_binding
)(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
bool
assign
);
#ifdef CONFIG_IWLWIFI_DEBUGFS
int
(
*
power_dbgfs_read
)(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
char
*
buf
,
int
bufsz
);
...
...
@@ -181,6 +183,7 @@ enum iwl_dbgfs_pm_mask {
MVM_DEBUGFS_PM_LPRX_ENA
=
BIT
(
6
),
MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD
=
BIT
(
7
),
MVM_DEBUGFS_PM_SNOOZE_ENABLE
=
BIT
(
8
),
MVM_DEBUGFS_PM_UAPSD_MISBEHAVING
=
BIT
(
9
),
};
struct
iwl_dbgfs_pm
{
...
...
@@ -193,6 +196,7 @@ struct iwl_dbgfs_pm {
bool
lprx_ena
;
u32
lprx_rssi_threshold
;
bool
snooze_ena
;
bool
uapsd_misbehaving
;
int
mask
;
};
...
...
@@ -269,8 +273,8 @@ struct iwl_mvm_vif_bf_data {
* @bcast_sta: station used for broadcast packets. Used by the following
* vifs: P2P_DEVICE, GO and AP.
* @beacon_skb: the skb used to hold the AP/GO beacon template
* @smps_requests: the
requests of of differents parts of the driver, regard
the desired smps mode
.
* @smps_requests: the
SMPS requests of differents parts of the driver,
* combined on update to yield the overall request to mac80211
.
*/
struct
iwl_mvm_vif
{
u16
id
;
...
...
@@ -331,6 +335,11 @@ struct iwl_mvm_vif {
#endif
enum
ieee80211_smps_mode
smps_requests
[
NUM_IWL_MVM_SMPS_REQ
];
/* FW identified misbehaving AP */
u8
uapsd_misbehaving_bssid
[
ETH_ALEN
];
bool
pm_prevented
;
};
static
inline
struct
iwl_mvm_vif
*
...
...
@@ -479,6 +488,7 @@ struct iwl_mvm {
/* Scan status, cmd (pre-allocated) and auxiliary station */
enum
iwl_scan_status
scan_status
;
struct
iwl_scan_cmd
*
scan_cmd
;
struct
iwl_mcast_filter_cmd
*
mcast_filter_cmd
;
/* rx chain antennas set through debugfs for the scan command */
u8
scan_rx_ant
;
...
...
@@ -489,6 +499,9 @@ struct iwl_mvm {
u8
scan_last_antenna_idx
;
/* to toggle TX between antennas */
u8
mgmt_last_antenna_idx
;
/* last smart fifo state that was successfully sent to firmware */
enum
iwl_sf_state
sf_state
;
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct
dentry
*
debugfs_dir
;
u32
dbgfs_sram_offset
,
dbgfs_sram_len
;
...
...
@@ -512,12 +525,6 @@ struct iwl_mvm {
*/
unsigned
long
fw_key_table
[
BITS_TO_LONGS
(
STA_KEY_MAX_NUM
)];
/*
* This counter of created interfaces is referenced only in conjunction
* with FW limitation related to power management. Currently PM is
* supported only on a single interface.
* IMPORTANT: this variable counts all interfaces except P2P device.
*/
u8
vif_count
;
/* -1 for always, 0 for never, >0 for that many times */
...
...
@@ -560,6 +567,11 @@ struct iwl_mvm {
u8
aux_queue
;
u8
first_agg_queue
;
u8
last_agg_queue
;
u8
bound_vif_cnt
;
/* Indicate if device power save is allowed */
bool
ps_prevented
;
};
/* Extract MVM priv from op_mode and _hw */
...
...
@@ -778,6 +790,19 @@ static inline int iwl_mvm_power_update_device_mode(struct iwl_mvm *mvm)
return
0
;
}
static
inline
void
iwl_mvm_power_update_binding
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
bool
assign
)
{
if
(
mvm
->
pm_ops
->
power_update_binding
)
mvm
->
pm_ops
->
power_update_binding
(
mvm
,
vif
,
assign
);
}
void
iwl_mvm_power_vif_assoc
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
);
int
iwl_mvm_power_uapsd_misbehaving_ap_notif
(
struct
iwl_mvm
*
mvm
,
struct
iwl_rx_cmd_buffer
*
rxb
,
struct
iwl_device_cmd
*
cmd
);
#ifdef CONFIG_IWLWIFI_DEBUGFS
static
inline
int
iwl_mvm_power_dbgfs_read
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
...
...
@@ -869,4 +894,8 @@ void iwl_mvm_tt_initialize(struct iwl_mvm *mvm);
void
iwl_mvm_tt_exit
(
struct
iwl_mvm
*
mvm
);
void
iwl_mvm_set_hw_ctkill_state
(
struct
iwl_mvm
*
mvm
,
bool
state
);
/* smart fifo */
int
iwl_mvm_sf_update
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
bool
added_vif
);
#endif
/* __IWL_MVM_H__ */
drivers/net/wireless/iwlwifi/mvm/ops.c
浏览文件 @
623c4387
...
...
@@ -236,6 +236,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
false
),
RX_HANDLER
(
REPLY_ERROR
,
iwl_mvm_rx_fw_error
,
false
),
RX_HANDLER
(
PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION
,
iwl_mvm_power_uapsd_misbehaving_ap_notif
,
false
),
};
#undef RX_HANDLER
#define CMD(x) [x] = #x
...
...
@@ -311,6 +313,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD
(
REPLY_THERMAL_MNG_BACKOFF
),
CMD
(
MAC_PM_POWER_TABLE
),
CMD
(
BT_COEX_CI
),
CMD
(
PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION
),
};
#undef CMD
...
...
@@ -341,7 +344,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
op_mode
=
hw
->
priv
;
op_mode
->
ops
=
&
iwl_mvm_ops
;
op_mode
->
trans
=
trans
;
mvm
=
IWL_OP_MODE_GET_MVM
(
op_mode
);
mvm
->
dev
=
trans
->
dev
;
...
...
@@ -359,6 +361,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mvm
->
aux_queue
=
11
;
mvm
->
first_agg_queue
=
12
;
}
mvm
->
sf_state
=
SF_UNINIT
;
mutex_init
(
&
mvm
->
mutex
);
spin_lock_init
(
&
mvm
->
async_handlers_lock
);
...
...
@@ -424,7 +427,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
* there is no need to unnecessarily power up the NIC at driver load
*/
if
(
iwlwifi_mod_params
.
nvm_file
)
{
iwl_nvm_init
(
mvm
);
err
=
iwl_nvm_init
(
mvm
);
if
(
err
)
goto
out_free
;
}
else
{
err
=
iwl_trans_start_hw
(
mvm
->
trans
);
if
(
err
)
...
...
@@ -432,16 +437,13 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mutex_lock
(
&
mvm
->
mutex
);
err
=
iwl_run_init_mvm_ucode
(
mvm
,
true
);
iwl_trans_stop_device
(
trans
);
mutex_unlock
(
&
mvm
->
mutex
);
/* returns 0 if successful, 1 if success but in rfkill */
if
(
err
<
0
&&
!
iwlmvm_mod_params
.
init_dbg
)
{
IWL_ERR
(
mvm
,
"Failed to run INIT ucode: %d
\n
"
,
err
);
goto
out_free
;
}
/* Stop the hw after the ALIVE and NVM has been read */
if
(
!
iwlmvm_mod_params
.
init_dbg
)
iwl_trans_stop_hw
(
mvm
->
trans
,
false
);
}
scan_size
=
sizeof
(
struct
iwl_scan_cmd
)
+
...
...
@@ -474,7 +476,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
iwl_phy_db_free
(
mvm
->
phy_db
);
kfree
(
mvm
->
scan_cmd
);
if
(
!
iwlwifi_mod_params
.
nvm_file
)
iwl_trans_
stop_hw
(
trans
,
true
);
iwl_trans_
op_mode_leave
(
trans
);
ieee80211_free_hw
(
mvm
->
hw
);
return
NULL
;
}
...
...
@@ -491,12 +493,14 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
ieee80211_unregister_hw
(
mvm
->
hw
);
kfree
(
mvm
->
scan_cmd
);
kfree
(
mvm
->
mcast_filter_cmd
);
mvm
->
mcast_filter_cmd
=
NULL
;
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS)
kfree
(
mvm
->
d3_resume_sram
);
#endif
iwl_trans_
stop_hw
(
mvm
->
trans
,
true
);
iwl_trans_
op_mode_leave
(
mvm
->
trans
);
iwl_phy_db_free
(
mvm
->
phy_db
);
mvm
->
phy_db
=
NULL
;
...
...
drivers/net/wireless/iwlwifi/mvm/power.c
浏览文件 @
623c4387
...
...
@@ -186,6 +186,92 @@ static void iwl_mvm_power_log(struct iwl_mvm *mvm,
}
}
static
void
iwl_mvm_power_configure_uapsd
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
struct
iwl_mac_power_cmd
*
cmd
)
{
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
enum
ieee80211_ac_numbers
ac
;
bool
tid_found
=
false
;
for
(
ac
=
IEEE80211_AC_VO
;
ac
<=
IEEE80211_AC_BK
;
ac
++
)
{
if
(
!
mvmvif
->
queue_params
[
ac
].
uapsd
)
continue
;
if
(
mvm
->
cur_ucode
!=
IWL_UCODE_WOWLAN
)
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
)))
return
;
cmd
->
flags
|=
cpu_to_le16
(
POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK
);
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
;
if
(
mvm
->
cur_ucode
==
IWL_UCODE_WOWLAN
||
cmd
->
flags
&
cpu_to_le16
(
POWER_FLAGS_SNOOZE_ENA_MSK
))
{
cmd
->
rx_data_timeout_uapsd
=
cpu_to_le32
(
IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT
);
cmd
->
tx_data_timeout_uapsd
=
cpu_to_le32
(
IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT
);
}
else
{
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
);
}
if
(
cmd
->
flags
&
cpu_to_le16
(
POWER_FLAGS_SNOOZE_ENA_MSK
))
{
cmd
->
heavy_tx_thld_packets
=
IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS
;
cmd
->
heavy_rx_thld_packets
=
IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS
;
}
else
{
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
;
}
static
void
iwl_mvm_power_build_cmd
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
struct
iwl_mac_power_cmd
*
cmd
)
...
...
@@ -198,8 +284,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
bool
radar_detect
=
false
;
struct
iwl_mvm_vif
*
mvmvif
__maybe_unused
=
iwl_mvm_vif_from_mac80211
(
vif
);
enum
ieee80211_ac_numbers
ac
;
bool
tid_found
=
false
;
bool
allow_uapsd
=
true
;
cmd
->
id_and_color
=
cpu_to_le32
(
FW_CMD_ID_AND_COLOR
(
mvmvif
->
id
,
mvmvif
->
color
));
...
...
@@ -217,7 +302,8 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
keep_alive
=
DIV_ROUND_UP
(
keep_alive
,
MSEC_PER_SEC
);
cmd
->
keep_alive_seconds
=
cpu_to_le16
(
keep_alive
);
if
(
iwlmvm_mod_params
.
power_scheme
==
IWL_POWER_SCHEME_CAM
)
if
(
iwlmvm_mod_params
.
power_scheme
==
IWL_POWER_SCHEME_CAM
||
mvm
->
ps_prevented
)
return
;
cmd
->
flags
|=
cpu_to_le16
(
POWER_FLAGS_POWER_SAVE_ENA_MSK
);
...
...
@@ -227,7 +313,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
mvmvif
->
dbgfs_pm
.
disable_power_off
)
cmd
->
flags
&=
cpu_to_le16
(
~
POWER_FLAGS_POWER_SAVE_ENA_MSK
);
#endif
if
(
!
vif
->
bss_conf
.
ps
)
if
(
!
vif
->
bss_conf
.
ps
||
mvmvif
->
pm_prevented
)
return
;
cmd
->
flags
|=
cpu_to_le16
(
POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK
);
...
...
@@ -269,81 +355,24 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
cpu_to_le32
(
IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT
);
}
for
(
ac
=
IEEE80211_AC_VO
;
ac
<=
IEEE80211_AC_BK
;
ac
++
)
{
if
(
!
mvmvif
->
queue_params
[
ac
].
uapsd
)
continue
;
if
(
mvm
->
cur_ucode
!=
IWL_UCODE_WOWLAN
)
cmd
->
flags
|=
cpu_to_le16
(
POWER_FLAGS_ADVANCE_PM_ENA_MSK
);
cmd
->
uapsd_ac_flags
|=
BIT
(
ac
);
if
(
!
memcmp
(
mvmvif
->
uapsd_misbehaving_bssid
,
vif
->
bss_conf
.
bssid
,
ETH_ALEN
))
allow_uapsd
=
false
;
/* 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
))
{
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
;
if
(
mvm
->
cur_ucode
==
IWL_UCODE_WOWLAN
||
cmd
->
flags
&
cpu_to_le16
(
POWER_FLAGS_SNOOZE_ENA_MSK
))
{
cmd
->
rx_data_timeout_uapsd
=
cpu_to_le32
(
IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT
);
cmd
->
tx_data_timeout_uapsd
=
cpu_to_le32
(
IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT
);
}
else
{
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
);
}
if
(
vif
->
p2p
&&
!
(
mvm
->
fw
->
ucode_capa
.
flags
&
IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD
))
allow_uapsd
=
false
;
/*
* Avoid using uAPSD if P2P client is associated to GO that uses
* opportunistic power save. This is due to current FW limitation.
*/
if
(
vif
->
p2p
&&
vif
->
bss_conf
.
p2p_noa_attr
.
oppps_ctwindow
&
IEEE80211_P2P_OPPPS_ENABLE_BIT
)
allow_uapsd
=
false
;
if
(
cmd
->
flags
&
cpu_to_le16
(
POWER_FLAGS_SNOOZE_ENA_MSK
))
{
cmd
->
heavy_tx_thld_packets
=
IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS
;
cmd
->
heavy_rx_thld_packets
=
IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS
;
}
else
{
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
;
}
if
(
allow_uapsd
)
iwl_mvm_power_configure_uapsd
(
mvm
,
vif
,
cmd
);
#ifdef CONFIG_IWLWIFI_DEBUGFS
if
(
mvmvif
->
dbgfs_pm
.
mask
&
MVM_DEBUGFS_PM_KEEP_ALIVE
)
...
...
@@ -381,6 +410,13 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
cmd
->
flags
&=
cpu_to_le16
(
~
POWER_FLAGS_SNOOZE_ENA_MSK
);
}
if
(
mvmvif
->
dbgfs_pm
.
mask
&
MVM_DEBUGFS_PM_UAPSD_MISBEHAVING
)
{
u16
flag
=
POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK
;
if
(
mvmvif
->
dbgfs_pm
.
uapsd_misbehaving
)
cmd
->
flags
|=
cpu_to_le16
(
flag
);
else
cmd
->
flags
&=
cpu_to_le16
(
flag
);
}
#endif
/* CONFIG_IWLWIFI_DEBUGFS */
}
...
...
@@ -391,18 +427,11 @@ static int iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm,
bool
ba_enable
;
struct
iwl_mac_power_cmd
cmd
=
{};
if
(
vif
->
type
!=
NL80211_IFTYPE_STATION
||
vif
->
p2p
)
if
(
vif
->
type
!=
NL80211_IFTYPE_STATION
)
return
0
;
/*
* 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
)
if
(
vif
->
p2p
&&
!
(
mvm
->
fw
->
ucode_capa
.
flags
&
IWL_UCODE_TLV_FLAGS_P2P_PS
))
return
0
;
iwl_mvm_power_build_cmd
(
mvm
,
vif
,
&
cmd
);
...
...
@@ -446,7 +475,7 @@ static int iwl_mvm_power_mac_disable(struct iwl_mvm *mvm,
sizeof
(
cmd
),
&
cmd
);
}
static
int
iwl_mvm_power_update_device
(
struct
iwl_mvm
*
mvm
)
static
int
_iwl_mvm_power_update_device
(
struct
iwl_mvm
*
mvm
,
bool
force_disable
)
{
struct
iwl_device_power_cmd
cmd
=
{
.
flags
=
cpu_to_le16
(
DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK
),
...
...
@@ -455,7 +484,8 @@ static int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
if
(
!
(
mvm
->
fw
->
ucode_capa
.
flags
&
IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD
))
return
0
;
if
(
iwlmvm_mod_params
.
power_scheme
==
IWL_POWER_SCHEME_CAM
)
if
(
iwlmvm_mod_params
.
power_scheme
==
IWL_POWER_SCHEME_CAM
||
force_disable
)
cmd
.
flags
|=
cpu_to_le16
(
DEVICE_POWER_FLAGS_CAM_MSK
);
#ifdef CONFIG_IWLWIFI_DEBUGFS
...
...
@@ -472,6 +502,78 @@ static int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
&
cmd
);
}
static
int
iwl_mvm_power_update_device
(
struct
iwl_mvm
*
mvm
)
{
return
_iwl_mvm_power_update_device
(
mvm
,
false
);
}
void
iwl_mvm_power_vif_assoc
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
)
{
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
if
(
memcmp
(
vif
->
bss_conf
.
bssid
,
mvmvif
->
uapsd_misbehaving_bssid
,
ETH_ALEN
))
memset
(
mvmvif
->
uapsd_misbehaving_bssid
,
0
,
ETH_ALEN
);
}
static
void
iwl_mvm_power_uapsd_misbehav_ap_iterator
(
void
*
_data
,
u8
*
mac
,
struct
ieee80211_vif
*
vif
)
{
u8
*
ap_sta_id
=
_data
;
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
/* The ap_sta_id is not expected to change during current association
* so no explicit protection is needed
*/
if
(
mvmvif
->
ap_sta_id
==
*
ap_sta_id
)
memcpy
(
mvmvif
->
uapsd_misbehaving_bssid
,
vif
->
bss_conf
.
bssid
,
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
)
{
struct
iwl_rx_packet
*
pkt
=
rxb_addr
(
rxb
);
struct
iwl_uapsd_misbehaving_ap_notif
*
notif
=
(
void
*
)
pkt
->
data
;
u8
ap_sta_id
=
le32_to_cpu
(
notif
->
sta_id
);
ieee80211_iterate_active_interfaces_atomic
(
mvm
->
hw
,
IEEE80211_IFACE_ITER_NORMAL
,
iwl_mvm_power_uapsd_misbehav_ap_iterator
,
&
ap_sta_id
);
return
0
;
}
static
void
iwl_mvm_power_binding_iterator
(
void
*
_data
,
u8
*
mac
,
struct
ieee80211_vif
*
vif
)
{
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
struct
iwl_mvm
*
mvm
=
_data
;
int
ret
;
mvmvif
->
pm_prevented
=
(
mvm
->
bound_vif_cnt
<=
1
)
?
false
:
true
;
ret
=
iwl_mvm_power_mac_update_mode
(
mvm
,
vif
);
WARN_ONCE
(
ret
,
"Failed to update power parameters on a specific vif
\n
"
);
}
static
void
_iwl_mvm_power_update_binding
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
bool
assign
)
{
if
(
vif
->
type
==
NL80211_IFTYPE_MONITOR
)
{
int
ret
=
_iwl_mvm_power_update_device
(
mvm
,
assign
);
mvm
->
ps_prevented
=
assign
;
WARN_ONCE
(
ret
,
"Failed to update power device state
\n
"
);
}
ieee80211_iterate_active_interfaces
(
mvm
->
hw
,
IEEE80211_IFACE_ITER_NORMAL
,
iwl_mvm_power_binding_iterator
,
mvm
);
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
static
int
iwl_mvm_power_mac_dbgfs_read
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
char
*
buf
,
...
...
@@ -494,70 +596,58 @@ static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
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
);
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
));
}
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
);
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
);
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
);
}
if
(
!
(
cmd
.
flags
&
cpu_to_le16
(
POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK
)))
return
pos
;
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"skip_over_dtim = %d
\n
"
,
(
cmd
.
flags
&
cpu_to_le16
(
POWER_FLAGS_SKIP_OVER_DTIM_MSK
))
?
1
:
0
);
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
));
}
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
);
if
(
!
(
cmd
.
flags
&
cpu_to_le16
(
POWER_FLAGS_ADVANCE_PM_ENA_MSK
)))
return
pos
;
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
);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"uapsd_misbehaving_enable = %d
\n
"
,
(
cmd
.
flags
&
cpu_to_le16
(
POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK
))
?
1
:
0
);
if
(
!
(
cmd
.
flags
&
cpu_to_le16
(
POWER_FLAGS_SNOOZE_ENA_MSK
)))
return
pos
;
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
;
}
...
...
@@ -654,6 +744,7 @@ const struct iwl_mvm_power_ops pm_mac_ops = {
.
power_update_mode
=
iwl_mvm_power_mac_update_mode
,
.
power_update_device_mode
=
iwl_mvm_power_update_device
,
.
power_disable
=
iwl_mvm_power_mac_disable
,
.
power_update_binding
=
_iwl_mvm_power_update_binding
,
#ifdef CONFIG_IWLWIFI_DEBUGFS
.
power_dbgfs_read
=
iwl_mvm_power_mac_dbgfs_read
,
#endif
...
...
drivers/net/wireless/iwlwifi/mvm/rs.c
浏览文件 @
623c4387
此差异已折叠。
点击以展开。
drivers/net/wireless/iwlwifi/mvm/rs.h
浏览文件 @
623c4387
...
...
@@ -278,7 +278,6 @@ struct iwl_scale_tbl_info {
struct
rs_rate
rate
;
enum
rs_column
column
;
s32
*
expected_tpt
;
/* throughput metrics; expected_tpt_G, etc. */
u32
current_rate
;
/* rate_n_flags, uCode API format */
struct
iwl_rate_scale_data
win
[
IWL_RATE_COUNT
];
/* rate histories */
};
...
...
@@ -315,7 +314,6 @@ struct iwl_lq_sta {
enum
ieee80211_band
band
;
/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
u32
supp_rates
;
u16
active_legacy_rate
;
u16
active_siso_rate
;
u16
active_mimo2_rate
;
...
...
drivers/net/wireless/iwlwifi/mvm/rx.c
浏览文件 @
623c4387
...
...
@@ -251,6 +251,12 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm,
stats
->
flag
|=
RX_FLAG_DECRYPTED
;
return
0
;
case
RX_MPDU_RES_STATUS_SEC_EXT_ENC
:
if
(
!
(
rx_pkt_status
&
RX_MPDU_RES_STATUS_MIC_OK
))
return
-
1
;
stats
->
flag
|=
RX_FLAG_DECRYPTED
;
return
0
;
default:
IWL_ERR
(
mvm
,
"Unhandled alg: 0x%x
\n
"
,
rx_pkt_status
);
}
...
...
drivers/net/wireless/iwlwifi/mvm/sf.c
0 → 100644
浏览文件 @
623c4387
/******************************************************************************
*
* 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) 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
* in the file called COPYING.
*
* 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) 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 "mvm.h"
/* For counting bound interfaces */
struct
iwl_mvm_active_iface_iterator_data
{
struct
ieee80211_vif
*
ignore_vif
;
u8
sta_vif_ap_sta_id
;
enum
iwl_sf_state
sta_vif_state
;
int
num_active_macs
;
};
/*
* Count bound interfaces which are not p2p, besides data->ignore_vif.
* data->station_vif will point to one bound vif of type station, if exists.
*/
static
void
iwl_mvm_bound_iface_iterator
(
void
*
_data
,
u8
*
mac
,
struct
ieee80211_vif
*
vif
)
{
struct
iwl_mvm_active_iface_iterator_data
*
data
=
_data
;
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
if
(
vif
==
data
->
ignore_vif
||
!
mvmvif
->
phy_ctxt
||
vif
->
type
==
NL80211_IFTYPE_P2P_DEVICE
)
return
;
data
->
num_active_macs
++
;
if
(
vif
->
type
==
NL80211_IFTYPE_STATION
)
{
data
->
sta_vif_ap_sta_id
=
mvmvif
->
ap_sta_id
;
if
(
vif
->
bss_conf
.
assoc
)
data
->
sta_vif_state
=
SF_FULL_ON
;
else
data
->
sta_vif_state
=
SF_INIT_OFF
;
}
}
/*
* Aging and idle timeouts for the different possible scenarios
* in SF_FULL_ON state.
*/
static
const
__le32
sf_full_timeout
[
SF_NUM_SCENARIO
][
SF_NUM_TIMEOUT_TYPES
]
=
{
{
cpu_to_le32
(
SF_SINGLE_UNICAST_AGING_TIMER
),
cpu_to_le32
(
SF_SINGLE_UNICAST_IDLE_TIMER
)
},
{
cpu_to_le32
(
SF_AGG_UNICAST_AGING_TIMER
),
cpu_to_le32
(
SF_AGG_UNICAST_IDLE_TIMER
)
},
{
cpu_to_le32
(
SF_MCAST_AGING_TIMER
),
cpu_to_le32
(
SF_MCAST_IDLE_TIMER
)
},
{
cpu_to_le32
(
SF_BA_AGING_TIMER
),
cpu_to_le32
(
SF_BA_IDLE_TIMER
)
},
{
cpu_to_le32
(
SF_TX_RE_AGING_TIMER
),
cpu_to_le32
(
SF_TX_RE_IDLE_TIMER
)
},
};
static
void
iwl_mvm_fill_sf_command
(
struct
iwl_sf_cfg_cmd
*
sf_cmd
,
struct
ieee80211_sta
*
sta
)
{
int
i
,
j
,
watermark
;
sf_cmd
->
watermark
[
SF_LONG_DELAY_ON
]
=
cpu_to_le32
(
SF_W_MARK_SCAN
);
/*
* If we are in association flow - check antenna configuration
* capabilities of the AP station, and choose the watermark accordingly.
*/
if
(
sta
)
{
if
(
sta
->
ht_cap
.
ht_supported
||
sta
->
vht_cap
.
vht_supported
)
{
switch
(
sta
->
rx_nss
)
{
case
1
:
watermark
=
SF_W_MARK_SISO
;
break
;
case
2
:
watermark
=
SF_W_MARK_MIMO2
;
break
;
default:
watermark
=
SF_W_MARK_MIMO3
;
break
;
}
}
else
{
watermark
=
SF_W_MARK_LEGACY
;
}
/* default watermark value for unassociated mode. */
}
else
{
watermark
=
SF_W_MARK_MIMO2
;
}
sf_cmd
->
watermark
[
SF_FULL_ON
]
=
cpu_to_le32
(
watermark
);
for
(
i
=
0
;
i
<
SF_NUM_SCENARIO
;
i
++
)
{
for
(
j
=
0
;
j
<
SF_NUM_TIMEOUT_TYPES
;
j
++
)
{
sf_cmd
->
long_delay_timeouts
[
i
][
j
]
=
cpu_to_le32
(
SF_LONG_DELAY_AGING_TIMER
);
}
}
BUILD_BUG_ON
(
sizeof
(
sf_full_timeout
)
!=
sizeof
(
__le32
)
*
SF_NUM_SCENARIO
*
SF_NUM_TIMEOUT_TYPES
);
memcpy
(
sf_cmd
->
full_on_timeouts
,
sf_full_timeout
,
sizeof
(
sf_full_timeout
));
}
static
int
iwl_mvm_sf_config
(
struct
iwl_mvm
*
mvm
,
u8
sta_id
,
enum
iwl_sf_state
new_state
)
{
struct
iwl_sf_cfg_cmd
sf_cmd
=
{
.
state
=
new_state
,
};
struct
ieee80211_sta
*
sta
;
int
ret
=
0
;
/*
* If an associated AP sta changed its antenna configuration, the state
* will remain FULL_ON but SF parameters need to be reconsidered.
*/
if
(
new_state
!=
SF_FULL_ON
&&
mvm
->
sf_state
==
new_state
)
return
0
;
switch
(
new_state
)
{
case
SF_UNINIT
:
break
;
case
SF_FULL_ON
:
if
(
sta_id
==
IWL_MVM_STATION_COUNT
)
{
IWL_ERR
(
mvm
,
"No station: Cannot switch SF to FULL_ON
\n
"
);
return
-
EINVAL
;
}
rcu_read_lock
();
sta
=
rcu_dereference
(
mvm
->
fw_id_to_mac_id
[
sta_id
]);
if
(
IS_ERR_OR_NULL
(
sta
))
{
IWL_ERR
(
mvm
,
"Invalid station id
\n
"
);
rcu_read_unlock
();
return
-
EINVAL
;
}
iwl_mvm_fill_sf_command
(
&
sf_cmd
,
sta
);
rcu_read_unlock
();
break
;
case
SF_INIT_OFF
:
iwl_mvm_fill_sf_command
(
&
sf_cmd
,
NULL
);
break
;
default:
WARN_ONCE
(
1
,
"Invalid state: %d. not sending Smart Fifo cmd
\n
"
,
new_state
);
return
-
EINVAL
;
}
ret
=
iwl_mvm_send_cmd_pdu
(
mvm
,
REPLY_SF_CFG_CMD
,
CMD_ASYNC
,
sizeof
(
sf_cmd
),
&
sf_cmd
);
if
(
!
ret
)
mvm
->
sf_state
=
new_state
;
return
ret
;
}
/*
* Update Smart fifo:
* Count bound interfaces that are not to be removed, ignoring p2p devices,
* and set new state accordingly.
*/
int
iwl_mvm_sf_update
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
changed_vif
,
bool
remove_vif
)
{
enum
iwl_sf_state
new_state
;
u8
sta_id
=
IWL_MVM_STATION_COUNT
;
struct
iwl_mvm_vif
*
mvmvif
=
NULL
;
struct
iwl_mvm_active_iface_iterator_data
data
=
{
.
ignore_vif
=
changed_vif
,
.
sta_vif_state
=
SF_UNINIT
,
.
sta_vif_ap_sta_id
=
IWL_MVM_STATION_COUNT
,
};
if
(
IWL_UCODE_API
(
mvm
->
fw
->
ucode_ver
)
<
8
)
return
0
;
/*
* Ignore the call if we are in HW Restart flow, or if the handled
* vif is a p2p device.
*/
if
(
test_bit
(
IWL_MVM_STATUS_IN_HW_RESTART
,
&
mvm
->
status
)
||
(
changed_vif
&&
changed_vif
->
type
==
NL80211_IFTYPE_P2P_DEVICE
))
return
0
;
ieee80211_iterate_active_interfaces_atomic
(
mvm
->
hw
,
IEEE80211_IFACE_ITER_NORMAL
,
iwl_mvm_bound_iface_iterator
,
&
data
);
/* If changed_vif exists and is not to be removed, add to the count */
if
(
changed_vif
&&
!
remove_vif
)
data
.
num_active_macs
++
;
switch
(
data
.
num_active_macs
)
{
case
0
:
/* If there are no active macs - change state to SF_INIT_OFF */
new_state
=
SF_INIT_OFF
;
break
;
case
1
:
if
(
remove_vif
)
{
/* The one active mac left is of type station
* and we filled the relevant data during iteration
*/
new_state
=
data
.
sta_vif_state
;
sta_id
=
data
.
sta_vif_ap_sta_id
;
}
else
{
if
(
WARN_ON
(
!
changed_vif
))
return
-
EINVAL
;
if
(
changed_vif
->
type
!=
NL80211_IFTYPE_STATION
)
{
new_state
=
SF_UNINIT
;
}
else
if
(
changed_vif
->
bss_conf
.
assoc
)
{
mvmvif
=
iwl_mvm_vif_from_mac80211
(
changed_vif
);
sta_id
=
mvmvif
->
ap_sta_id
;
new_state
=
SF_FULL_ON
;
}
else
{
new_state
=
SF_INIT_OFF
;
}
}
break
;
default:
/* If there are multiple active macs - change to SF_UNINIT */
new_state
=
SF_UNINIT
;
}
return
iwl_mvm_sf_config
(
mvm
,
sta_id
,
new_state
);
}
drivers/net/wireless/iwlwifi/mvm/sta.c
浏览文件 @
623c4387
...
...
@@ -939,19 +939,6 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
IWL_DEBUG_HT
(
mvm
,
"Tx aggregation enabled on ra = %pM tid = %d
\n
"
,
sta
->
addr
,
tid
);
if
(
mvm
->
cfg
->
ht_params
->
use_rts_for_aggregation
)
{
/*
* switch to RTS/CTS if it is the prefer protection
* method for HT traffic
* this function also sends the LQ command
*/
return
iwl_mvm_tx_protection
(
mvm
,
mvmsta
,
true
);
/*
* TODO: remove the TLC_RTS flag when we tear down the last
* AGG session (agg_tids_count in DVM)
*/
}
return
iwl_mvm_send_lq_cmd
(
mvm
,
&
mvmsta
->
lq_sta
.
lq
,
false
);
}
...
...
@@ -1130,8 +1117,8 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
memcpy
(
cmd
.
key
,
keyconf
->
key
,
keyconf
->
keylen
);
break
;
default:
WARN_ON
(
1
);
return
-
EINVAL
;
key_flags
|=
cpu_to_le16
(
STA_KEY_FLG_EXT
);
memcpy
(
cmd
.
key
,
keyconf
->
key
,
keyconf
->
keylen
)
;
}
if
(
!
(
keyconf
->
flags
&
IEEE80211_KEY_FLAG_PAIRWISE
))
...
...
@@ -1295,8 +1282,8 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
0
,
NULL
,
CMD_SYNC
);
break
;
default:
IWL_ERR
(
mvm
,
"Unknown cipher %x
\n
"
,
keyconf
->
cipher
);
ret
=
-
EINVAL
;
ret
=
iwl_mvm_send_sta_key
(
mvm
,
mvm_sta
,
keyconf
,
sta_id
,
0
,
NULL
,
CMD_SYNC
)
;
}
if
(
ret
)
...
...
drivers/net/wireless/iwlwifi/mvm/tt.c
浏览文件 @
623c4387
...
...
@@ -340,7 +340,7 @@ static void check_exit_ctkill(struct work_struct *work)
iwl_trans_start_hw
(
mvm
->
trans
);
temp
=
check_nic_temperature
(
mvm
);
iwl_trans_stop_
hw
(
mvm
->
trans
,
false
);
iwl_trans_stop_
device
(
mvm
->
trans
);
if
(
temp
<
MIN_TEMPERATURE
||
temp
>
MAX_TEMPERATURE
)
{
IWL_DEBUG_TEMP
(
mvm
,
"Failed to measure NIC temperature
\n
"
);
...
...
drivers/net/wireless/iwlwifi/mvm/tx.c
浏览文件 @
623c4387
...
...
@@ -253,8 +253,7 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
memcpy
(
&
tx_cmd
->
key
[
3
],
keyconf
->
key
,
keyconf
->
keylen
);
break
;
default:
IWL_ERR
(
mvm
,
"Unknown encode cipher %x
\n
"
,
keyconf
->
cipher
);
break
;
tx_cmd
->
sec_ctl
|=
TX_CMD_SEC_EXT
;
}
}
...
...
drivers/net/wireless/iwlwifi/mvm/utils.c
浏览文件 @
623c4387
...
...
@@ -518,6 +518,11 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
int
i
;
lockdep_assert_held
(
&
mvm
->
mutex
);
/* SMPS is irrelevant for NICs that don't have at least 2 RX antenna */
if
(
num_of_ant
(
iwl_fw_valid_rx_ant
(
mvm
->
fw
))
==
1
)
return
;
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
mvmvif
->
smps_requests
[
req_type
]
=
smps_request
;
for
(
i
=
0
;
i
<
NUM_IWL_MVM_SMPS_REQ
;
i
++
)
{
...
...
drivers/net/wireless/iwlwifi/pcie/internal.h
浏览文件 @
623c4387
...
...
@@ -256,7 +256,6 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx)
* @hw_base: pci hardware address support
* @ucode_write_complete: indicates that the ucode has been copied.
* @ucode_write_waitq: wait queue for uCode load
* @status - transport specific status flags
* @cmd_queue - command queue number
* @rx_buf_size_8k: 8 kB RX buffer size
* @bc_table_dword: true if the BC table expects DWORD (as opposed to bytes)
...
...
@@ -296,7 +295,6 @@ struct iwl_trans_pcie {
wait_queue_head_t
ucode_write_waitq
;
wait_queue_head_t
wait_command_queue
;
unsigned
long
status
;
u8
cmd_queue
;
u8
cmd_fifo
;
u8
n_no_reclaim_cmds
;
...
...
@@ -315,24 +313,6 @@ struct iwl_trans_pcie {
spinlock_t
reg_lock
;
};
/**
* enum iwl_pcie_status: status of the PCIe transport
* @STATUS_HCMD_ACTIVE: a SYNC command is being processed
* @STATUS_DEVICE_ENABLED: APM is enabled
* @STATUS_TPOWER_PMI: the device might be asleep (need to wake it up)
* @STATUS_INT_ENABLED: interrupts are enabled
* @STATUS_RFKILL: the HW RFkill switch is in KILL position
* @STATUS_FW_ERROR: the fw is in error state
*/
enum
iwl_pcie_status
{
STATUS_HCMD_ACTIVE
,
STATUS_DEVICE_ENABLED
,
STATUS_TPOWER_PMI
,
STATUS_INT_ENABLED
,
STATUS_RFKILL
,
STATUS_FW_ERROR
,
};
#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \
((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific))
...
...
@@ -399,8 +379,7 @@ void iwl_pcie_dump_csr(struct iwl_trans *trans);
******************************************************/
static
inline
void
iwl_disable_interrupts
(
struct
iwl_trans
*
trans
)
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
clear_bit
(
STATUS_INT_ENABLED
,
&
trans_pcie
->
status
);
clear_bit
(
STATUS_INT_ENABLED
,
&
trans
->
status
);
/* disable interrupts from uCode/NIC to host */
iwl_write32
(
trans
,
CSR_INT_MASK
,
0x00000000
);
...
...
@@ -417,7 +396,7 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans)
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
IWL_DEBUG_ISR
(
trans
,
"Enabling interrupts
\n
"
);
set_bit
(
STATUS_INT_ENABLED
,
&
trans
_pcie
->
status
);
set_bit
(
STATUS_INT_ENABLED
,
&
trans
->
status
);
iwl_write32
(
trans
,
CSR_INT_MASK
,
trans_pcie
->
inta_mask
);
}
...
...
@@ -477,12 +456,4 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW
);
}
static
inline
void
iwl_nic_error
(
struct
iwl_trans
*
trans
)
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
set_bit
(
STATUS_FW_ERROR
,
&
trans_pcie
->
status
);
iwl_op_mode_nic_error
(
trans
->
op_mode
);
}
#endif
/* __iwl_trans_int_pcie_h__ */
drivers/net/wireless/iwlwifi/pcie/rx.c
浏览文件 @
623c4387
...
...
@@ -162,11 +162,8 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
rxq
->
write_actual
=
(
rxq
->
write
&
~
0x7
);
iwl_write32
(
trans
,
FH_RSCSR_CHNL0_WPTR
,
rxq
->
write_actual
);
}
else
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
/* If power-saving is in use, make sure device is awake */
if
(
test_bit
(
STATUS_TPOWER_PMI
,
&
trans
_pcie
->
status
))
{
if
(
test_bit
(
STATUS_TPOWER_PMI
,
&
trans
->
status
))
{
reg
=
iwl_read32
(
trans
,
CSR_UCODE_DRV_GP1
);
if
(
reg
&
CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP
)
{
...
...
@@ -222,7 +219,7 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
* stopped, we cannot access the HW (in particular not prph).
* So don't try to restock if the APM has been already stopped.
*/
if
(
!
test_bit
(
STATUS_DEVICE_ENABLED
,
&
trans
_pcie
->
status
))
if
(
!
test_bit
(
STATUS_DEVICE_ENABLED
,
&
trans
->
status
))
return
;
spin_lock_irqsave
(
&
rxq
->
lock
,
flags
);
...
...
@@ -791,7 +788,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
APMS_CLK_VAL_MRB_FUNC_MODE
)
||
(
iwl_read_prph
(
trans
,
APMG_PS_CTRL_REG
)
&
APMG_PS_CTRL_VAL_RESET_REQ
)))
{
clear_bit
(
STATUS_
HCMD_ACTIVE
,
&
trans_pcie
->
status
);
clear_bit
(
STATUS_
SYNC_HCMD_ACTIVE
,
&
trans
->
status
);
iwl_op_mode_wimax_active
(
trans
->
op_mode
);
wake_up
(
&
trans_pcie
->
wait_command_queue
);
return
;
...
...
@@ -800,14 +797,14 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
iwl_pcie_dump_csr
(
trans
);
iwl_dump_fh
(
trans
,
NULL
);
/* set the ERROR bit before we wake up the caller */
set_bit
(
STATUS_FW_ERROR
,
&
trans_pcie
->
status
);
clear_bit
(
STATUS_HCMD_ACTIVE
,
&
trans_pcie
->
status
);
wake_up
(
&
trans_pcie
->
wait_command_queue
);
local_bh_disable
();
iwl_nic_error
(
trans
);
/* The STATUS_FW_ERROR bit is set in this function. This must happen
* before we wake up the command caller, to ensure a proper cleanup. */
iwl_trans_fw_error
(
trans
);
local_bh_enable
();
clear_bit
(
STATUS_SYNC_HCMD_ACTIVE
,
&
trans
->
status
);
wake_up
(
&
trans_pcie
->
wait_command_queue
);
}
irqreturn_t
iwl_pcie_irq_handler
(
int
irq
,
void
*
dev_id
)
...
...
@@ -894,14 +891,14 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
iwl_op_mode_hw_rf_kill
(
trans
->
op_mode
,
hw_rfkill
);
if
(
hw_rfkill
)
{
set_bit
(
STATUS_RFKILL
,
&
trans
_pcie
->
status
);
if
(
test_and_clear_bit
(
STATUS_HCMD_ACTIVE
,
&
trans
_pcie
->
status
))
set_bit
(
STATUS_RFKILL
,
&
trans
->
status
);
if
(
test_and_clear_bit
(
STATUS_
SYNC_
HCMD_ACTIVE
,
&
trans
->
status
))
IWL_DEBUG_RF_KILL
(
trans
,
"Rfkill while SYNC HCMD in flight
\n
"
);
wake_up
(
&
trans_pcie
->
wait_command_queue
);
}
else
{
clear_bit
(
STATUS_RFKILL
,
&
trans
_pcie
->
status
);
clear_bit
(
STATUS_RFKILL
,
&
trans
->
status
);
}
handled
|=
CSR_INT_BIT_RF_KILL
;
...
...
@@ -1005,7 +1002,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
/* Re-enable all interrupts */
/* only Re-enable if disabled by irq */
if
(
test_bit
(
STATUS_INT_ENABLED
,
&
trans
_pcie
->
status
))
if
(
test_bit
(
STATUS_INT_ENABLED
,
&
trans
->
status
))
iwl_enable_interrupts
(
trans
);
/* Re-enable RF_KILL if it occurred */
else
if
(
handled
&
CSR_INT_BIT_RF_KILL
)
...
...
@@ -1160,7 +1157,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
* the handler can be scheduled because of a previous
* interrupt.
*/
if
(
test_bit
(
STATUS_INT_ENABLED
,
&
trans
_pcie
->
status
)
&&
if
(
test_bit
(
STATUS_INT_ENABLED
,
&
trans
->
status
)
&&
!
trans_pcie
->
inta
)
iwl_enable_interrupts
(
trans
);
return
IRQ_NONE
;
...
...
@@ -1290,7 +1287,7 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
/* re-enable interrupts here since we don't have anything to service.
* only Re-enable if disabled by irq.
*/
if
(
test_bit
(
STATUS_INT_ENABLED
,
&
trans
_pcie
->
status
)
&&
if
(
test_bit
(
STATUS_INT_ENABLED
,
&
trans
->
status
)
&&
!
trans_pcie
->
inta
)
iwl_enable_interrupts
(
trans
);
...
...
drivers/net/wireless/iwlwifi/pcie/trans.c
浏览文件 @
623c4387
...
...
@@ -150,7 +150,6 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans)
*/
static
int
iwl_pcie_apm_init
(
struct
iwl_trans
*
trans
)
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
int
ret
=
0
;
IWL_DEBUG_INFO
(
trans
,
"Init card's basic functions
\n
"
);
...
...
@@ -223,7 +222,7 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
/* Clear the interrupt in APMG if the NIC is in RFKILL */
iwl_write_prph
(
trans
,
APMG_RTC_INT_STT_REG
,
APMG_RTC_INT_STT_RFKILL
);
set_bit
(
STATUS_DEVICE_ENABLED
,
&
trans
_pcie
->
status
);
set_bit
(
STATUS_DEVICE_ENABLED
,
&
trans
->
status
);
out:
return
ret
;
...
...
@@ -249,10 +248,9 @@ static int iwl_pcie_apm_stop_master(struct iwl_trans *trans)
static
void
iwl_pcie_apm_stop
(
struct
iwl_trans
*
trans
)
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
IWL_DEBUG_INFO
(
trans
,
"Stop card, put in low power state
\n
"
);
clear_bit
(
STATUS_DEVICE_ENABLED
,
&
trans
_pcie
->
status
);
clear_bit
(
STATUS_DEVICE_ENABLED
,
&
trans
->
status
);
/* Stop device's DMA activity */
iwl_pcie_apm_stop_master
(
trans
);
...
...
@@ -582,7 +580,6 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
static
int
iwl_trans_pcie_start_fw
(
struct
iwl_trans
*
trans
,
const
struct
fw_img
*
fw
,
bool
run_in_rfkill
)
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
int
ret
;
bool
hw_rfkill
;
...
...
@@ -592,16 +589,14 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
return
-
EIO
;
}
clear_bit
(
STATUS_FW_ERROR
,
&
trans_pcie
->
status
);
iwl_enable_rfkill_int
(
trans
);
/* If platform's RF_KILL switch is NOT set to KILL */
hw_rfkill
=
iwl_is_rfkill_set
(
trans
);
if
(
hw_rfkill
)
set_bit
(
STATUS_RFKILL
,
&
trans
_pcie
->
status
);
set_bit
(
STATUS_RFKILL
,
&
trans
->
status
);
else
clear_bit
(
STATUS_RFKILL
,
&
trans
_pcie
->
status
);
clear_bit
(
STATUS_RFKILL
,
&
trans
->
status
);
iwl_op_mode_hw_rf_kill
(
trans
->
op_mode
,
hw_rfkill
);
if
(
hw_rfkill
&&
!
run_in_rfkill
)
return
-
ERFKILL
;
...
...
@@ -641,6 +636,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
unsigned
long
flags
;
bool
hw_rfkill
;
/* tell the device to stop sending interrupts */
spin_lock_irqsave
(
&
trans_pcie
->
irq_lock
,
flags
);
...
...
@@ -657,7 +653,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
* restart. So don't process again if the device is
* already dead.
*/
if
(
test_bit
(
STATUS_DEVICE_ENABLED
,
&
trans
_pcie
->
status
))
{
if
(
test_bit
(
STATUS_DEVICE_ENABLED
,
&
trans
->
status
))
{
iwl_pcie_tx_stop
(
trans
);
iwl_pcie_rx_stop
(
trans
);
...
...
@@ -681,17 +677,34 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
iwl_disable_interrupts
(
trans
);
spin_unlock_irqrestore
(
&
trans_pcie
->
irq_lock
,
flags
);
iwl_enable_rfkill_int
(
trans
);
/* stop and reset the on-board processor */
iwl_write32
(
trans
,
CSR_RESET
,
CSR_RESET_REG_FLAG_NEVO_RESET
);
/* clear all status bits */
clear_bit
(
STATUS_HCMD_ACTIVE
,
&
trans_pcie
->
status
);
clear_bit
(
STATUS_INT_ENABLED
,
&
trans_pcie
->
status
);
clear_bit
(
STATUS_DEVICE_ENABLED
,
&
trans_pcie
->
status
);
clear_bit
(
STATUS_TPOWER_PMI
,
&
trans_pcie
->
status
);
clear_bit
(
STATUS_RFKILL
,
&
trans_pcie
->
status
);
clear_bit
(
STATUS_SYNC_HCMD_ACTIVE
,
&
trans
->
status
);
clear_bit
(
STATUS_INT_ENABLED
,
&
trans
->
status
);
clear_bit
(
STATUS_DEVICE_ENABLED
,
&
trans
->
status
);
clear_bit
(
STATUS_TPOWER_PMI
,
&
trans
->
status
);
clear_bit
(
STATUS_RFKILL
,
&
trans
->
status
);
/*
* Even if we stop the HW, we still want the RF kill
* interrupt
*/
iwl_enable_rfkill_int
(
trans
);
/*
* Check again since the RF kill state may have changed while
* all the interrupts were disabled, in this case we couldn't
* receive the RF kill interrupt and update the state in the
* op_mode.
*/
hw_rfkill
=
iwl_is_rfkill_set
(
trans
);
if
(
hw_rfkill
)
set_bit
(
STATUS_RFKILL
,
&
trans
->
status
);
else
clear_bit
(
STATUS_RFKILL
,
&
trans
->
status
);
iwl_op_mode_hw_rf_kill
(
trans
->
op_mode
,
hw_rfkill
);
}
static
void
iwl_trans_pcie_d3_suspend
(
struct
iwl_trans
*
trans
,
bool
test
)
...
...
@@ -776,7 +789,6 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
static
int
iwl_trans_pcie_start_hw
(
struct
iwl_trans
*
trans
)
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
bool
hw_rfkill
;
int
err
;
...
...
@@ -798,21 +810,20 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
hw_rfkill
=
iwl_is_rfkill_set
(
trans
);
if
(
hw_rfkill
)
set_bit
(
STATUS_RFKILL
,
&
trans
_pcie
->
status
);
set_bit
(
STATUS_RFKILL
,
&
trans
->
status
);
else
clear_bit
(
STATUS_RFKILL
,
&
trans
_pcie
->
status
);
clear_bit
(
STATUS_RFKILL
,
&
trans
->
status
);
iwl_op_mode_hw_rf_kill
(
trans
->
op_mode
,
hw_rfkill
);
return
0
;
}
static
void
iwl_trans_pcie_stop_hw
(
struct
iwl_trans
*
trans
,
bool
op_mode_leaving
)
static
void
iwl_trans_pcie_op_mode_leave
(
struct
iwl_trans
*
trans
)
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
bool
hw_rfkill
;
unsigned
long
flags
;
/* disable interrupts - don't enable HW RF kill interrupt */
spin_lock_irqsave
(
&
trans_pcie
->
irq_lock
,
flags
);
iwl_disable_interrupts
(
trans
);
spin_unlock_irqrestore
(
&
trans_pcie
->
irq_lock
,
flags
);
...
...
@@ -824,27 +835,6 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans,
spin_unlock_irqrestore
(
&
trans_pcie
->
irq_lock
,
flags
);
iwl_pcie_disable_ict
(
trans
);
if
(
!
op_mode_leaving
)
{
/*
* Even if we stop the HW, we still want the RF kill
* interrupt
*/
iwl_enable_rfkill_int
(
trans
);
/*
* Check again since the RF kill state may have changed while
* all the interrupts were disabled, in this case we couldn't
* receive the RF kill interrupt and update the state in the
* op_mode.
*/
hw_rfkill
=
iwl_is_rfkill_set
(
trans
);
if
(
hw_rfkill
)
set_bit
(
STATUS_RFKILL
,
&
trans_pcie
->
status
);
else
clear_bit
(
STATUS_RFKILL
,
&
trans_pcie
->
status
);
iwl_op_mode_hw_rf_kill
(
trans
->
op_mode
,
hw_rfkill
);
}
}
static
void
iwl_trans_pcie_write8
(
struct
iwl_trans
*
trans
,
u32
ofs
,
u8
val
)
...
...
@@ -928,12 +918,10 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
static
void
iwl_trans_pcie_set_pmi
(
struct
iwl_trans
*
trans
,
bool
state
)
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
if
(
state
)
set_bit
(
STATUS_TPOWER_PMI
,
&
trans
_pcie
->
status
);
set_bit
(
STATUS_TPOWER_PMI
,
&
trans
->
status
);
else
clear_bit
(
STATUS_TPOWER_PMI
,
&
trans
_pcie
->
status
);
clear_bit
(
STATUS_TPOWER_PMI
,
&
trans
->
status
);
}
static
bool
iwl_trans_pcie_grab_nic_access
(
struct
iwl_trans
*
trans
,
bool
silent
,
...
...
@@ -1457,7 +1445,7 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
static
const
struct
iwl_trans_ops
trans_ops_pcie
=
{
.
start_hw
=
iwl_trans_pcie_start_hw
,
.
stop_hw
=
iwl_trans_pcie_stop_hw
,
.
op_mode_leave
=
iwl_trans_pcie_op_mode_leave
,
.
fw_alive
=
iwl_trans_pcie_fw_alive
,
.
start_fw
=
iwl_trans_pcie_start_fw
,
.
stop_device
=
iwl_trans_pcie_stop_device
,
...
...
drivers/net/wireless/iwlwifi/pcie/tx.c
浏览文件 @
623c4387
...
...
@@ -207,7 +207,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
IWL_ERR
(
trans
,
"scratch %d = 0x%08x
\n
"
,
i
,
le32_to_cpu
(
txq
->
scratchbufs
[
i
].
scratch
));
iwl_
nic
_error
(
trans
);
iwl_
trans_fw
_error
(
trans
);
}
/*
...
...
@@ -300,10 +300,8 @@ void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq)
iwl_write32
(
trans
,
HBUS_TARG_WRPTR
,
txq
->
q
.
write_ptr
|
(
txq_id
<<
8
));
}
else
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
/* if we're trying to save power */
if
(
test_bit
(
STATUS_TPOWER_PMI
,
&
trans
_pcie
->
status
))
{
if
(
test_bit
(
STATUS_TPOWER_PMI
,
&
trans
->
status
))
{
/* wake up nic if it's powered down ...
* uCode will wake up, and interrupt us again, so next
* time we'll skip this part. */
...
...
@@ -1023,7 +1021,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
if
(
nfreed
++
>
0
)
{
IWL_ERR
(
trans
,
"HCMD skipped: index (%d) %d %d
\n
"
,
idx
,
q
->
write_ptr
,
q
->
read_ptr
);
iwl_
nic
_error
(
trans
);
iwl_
trans_fw
_error
(
trans
);
}
}
...
...
@@ -1449,12 +1447,12 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
iwl_pcie_cmdq_reclaim
(
trans
,
txq_id
,
index
);
if
(
!
(
meta
->
flags
&
CMD_ASYNC
))
{
if
(
!
test_bit
(
STATUS_
HCMD_ACTIVE
,
&
trans_pcie
->
status
))
{
if
(
!
test_bit
(
STATUS_
SYNC_HCMD_ACTIVE
,
&
trans
->
status
))
{
IWL_WARN
(
trans
,
"HCMD_ACTIVE already clear for command %s
\n
"
,
get_cmd_string
(
trans_pcie
,
cmd
->
hdr
.
cmd
));
}
clear_bit
(
STATUS_
HCMD_ACTIVE
,
&
trans_pcie
->
status
);
clear_bit
(
STATUS_
SYNC_HCMD_ACTIVE
,
&
trans
->
status
);
IWL_DEBUG_INFO
(
trans
,
"Clearing HCMD_ACTIVE for command %s
\n
"
,
get_cmd_string
(
trans_pcie
,
cmd
->
hdr
.
cmd
));
wake_up
(
&
trans_pcie
->
wait_command_queue
);
...
...
@@ -1499,8 +1497,8 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
IWL_DEBUG_INFO
(
trans
,
"Attempting to send sync command %s
\n
"
,
get_cmd_string
(
trans_pcie
,
cmd
->
id
));
if
(
WARN
(
test_and_set_bit
(
STATUS_HCMD_ACTIVE
,
&
trans
_pcie
->
status
),
if
(
WARN
(
test_and_set_bit
(
STATUS_
SYNC_
HCMD_ACTIVE
,
&
trans
->
status
),
"Command %s: a command is already active!
\n
"
,
get_cmd_string
(
trans_pcie
,
cmd
->
id
)))
return
-
EIO
;
...
...
@@ -1511,7 +1509,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
cmd_idx
=
iwl_pcie_enqueue_hcmd
(
trans
,
cmd
);
if
(
cmd_idx
<
0
)
{
ret
=
cmd_idx
;
clear_bit
(
STATUS_
HCMD_ACTIVE
,
&
trans_pcie
->
status
);
clear_bit
(
STATUS_
SYNC_HCMD_ACTIVE
,
&
trans
->
status
);
IWL_ERR
(
trans
,
"Error sending %s: enqueue_hcmd failed: %d
\n
"
,
get_cmd_string
(
trans_pcie
,
cmd
->
id
),
ret
);
...
...
@@ -1523,8 +1521,8 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
timeout
-=
COMMAND_POKE_TIMEOUT
;
ret
=
wait_event_timeout
(
trans_pcie
->
wait_command_queue
,
!
test_bit
(
STATUS_HCMD_ACTIVE
,
&
trans
_pcie
->
status
),
!
test_bit
(
STATUS_
SYNC_
HCMD_ACTIVE
,
&
trans
->
status
),
COMMAND_POKE_TIMEOUT
);
if
(
ret
)
break
;
...
...
@@ -1552,17 +1550,17 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
IWL_ERR
(
trans
,
"Current CMD queue read_ptr %d write_ptr %d
\n
"
,
q
->
read_ptr
,
q
->
write_ptr
);
clear_bit
(
STATUS_
HCMD_ACTIVE
,
&
trans_pcie
->
status
);
clear_bit
(
STATUS_
SYNC_HCMD_ACTIVE
,
&
trans
->
status
);
IWL_DEBUG_INFO
(
trans
,
"Clearing HCMD_ACTIVE for command %s
\n
"
,
get_cmd_string
(
trans_pcie
,
cmd
->
id
));
ret
=
-
ETIMEDOUT
;
iwl_
nic
_error
(
trans
);
iwl_
trans_fw
_error
(
trans
);
goto
cancel
;
}
if
(
test_bit
(
STATUS_FW_ERROR
,
&
trans
_pcie
->
status
))
{
if
(
test_bit
(
STATUS_FW_ERROR
,
&
trans
->
status
))
{
IWL_ERR
(
trans
,
"FW error in SYNC CMD %s
\n
"
,
get_cmd_string
(
trans_pcie
,
cmd
->
id
));
dump_stack
();
...
...
@@ -1571,7 +1569,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
}
if
(
!
(
cmd
->
flags
&
CMD_SEND_IN_RFKILL
)
&&
test_bit
(
STATUS_RFKILL
,
&
trans
_pcie
->
status
))
{
test_bit
(
STATUS_RFKILL
,
&
trans
->
status
))
{
IWL_DEBUG_RF_KILL
(
trans
,
"RFKILL in SYNC CMD... no rsp
\n
"
);
ret
=
-
ERFKILL
;
goto
cancel
;
...
...
@@ -1608,13 +1606,8 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
int
iwl_trans_pcie_send_hcmd
(
struct
iwl_trans
*
trans
,
struct
iwl_host_cmd
*
cmd
)
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
if
(
test_bit
(
STATUS_FW_ERROR
,
&
trans_pcie
->
status
))
return
-
EIO
;
if
(
!
(
cmd
->
flags
&
CMD_SEND_IN_RFKILL
)
&&
test_bit
(
STATUS_RFKILL
,
&
trans
_pcie
->
status
))
{
test_bit
(
STATUS_RFKILL
,
&
trans
->
status
))
{
IWL_DEBUG_RF_KILL
(
trans
,
"Dropping CMD 0x%x: RF KILL
\n
"
,
cmd
->
id
);
return
-
ERFKILL
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录