Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
0d920987
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 大约 4 年
通知
14
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
0d920987
编写于
4月 16, 2012
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'wireless-next' of
git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi
上级
94a2ca31
ef213d6d
变更
15
显示空白变更内容
内联
并排
Showing
15 changed file
with
755 addition
and
763 deletion
+755
-763
drivers/net/wireless/iwlwifi/Kconfig
drivers/net/wireless/iwlwifi/Kconfig
+15
-14
drivers/net/wireless/iwlwifi/iwl-agn-devices.c
drivers/net/wireless/iwlwifi/iwl-agn-devices.c
+74
-0
drivers/net/wireless/iwlwifi/iwl-agn-lib.c
drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+18
-12
drivers/net/wireless/iwlwifi/iwl-agn-rs.c
drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+10
-2
drivers/net/wireless/iwlwifi/iwl-agn-rx.c
drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+39
-0
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+309
-0
drivers/net/wireless/iwlwifi/iwl-agn-sta.c
drivers/net/wireless/iwlwifi/iwl-agn-sta.c
+96
-50
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-agn.c
+123
-3
drivers/net/wireless/iwlwifi/iwl-agn.h
drivers/net/wireless/iwlwifi/iwl-agn.h
+54
-5
drivers/net/wireless/iwlwifi/iwl-commands.h
drivers/net/wireless/iwlwifi/iwl-commands.h
+2
-2
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.c
+0
-604
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-core.h
+0
-68
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-dev.h
+0
-2
drivers/net/wireless/iwlwifi/iwl-mac80211.c
drivers/net/wireless/iwlwifi/iwl-mac80211.c
+15
-0
drivers/net/wireless/iwlwifi/iwl-shared.h
drivers/net/wireless/iwlwifi/iwl-shared.h
+0
-1
未找到文件。
drivers/net/wireless/iwlwifi/Kconfig
浏览文件 @
0d920987
...
...
@@ -113,6 +113,7 @@ config IWLWIFI_DEVICE_TESTMODE
generic netlink message via NL80211_TESTMODE channel.
config IWLWIFI_P2P
def_bool y
bool "iwlwifi experimental P2P support"
depends on IWLWIFI
help
...
...
drivers/net/wireless/iwlwifi/iwl-agn-devices.c
浏览文件 @
0d920987
...
...
@@ -71,6 +71,80 @@ static void iwl1000_nic_config(struct iwl_priv *priv)
~
APMG_SVR_VOLTAGE_CONFIG_BIT_MSK
);
}
/**
* iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time
* @priv -- pointer to iwl_priv data structure
* @tsf_bits -- number of bits need to shift for masking)
*/
static
inline
u32
iwl_beacon_time_mask_low
(
struct
iwl_priv
*
priv
,
u16
tsf_bits
)
{
return
(
1
<<
tsf_bits
)
-
1
;
}
/**
* iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time
* @priv -- pointer to iwl_priv data structure
* @tsf_bits -- number of bits need to shift for masking)
*/
static
inline
u32
iwl_beacon_time_mask_high
(
struct
iwl_priv
*
priv
,
u16
tsf_bits
)
{
return
((
1
<<
(
32
-
tsf_bits
))
-
1
)
<<
tsf_bits
;
}
/*
* extended beacon time format
* time in usec will be changed into a 32-bit value in extended:internal format
* the extended part is the beacon counts
* the internal part is the time in usec within one beacon interval
*/
static
u32
iwl_usecs_to_beacons
(
struct
iwl_priv
*
priv
,
u32
usec
,
u32
beacon_interval
)
{
u32
quot
;
u32
rem
;
u32
interval
=
beacon_interval
*
TIME_UNIT
;
if
(
!
interval
||
!
usec
)
return
0
;
quot
=
(
usec
/
interval
)
&
(
iwl_beacon_time_mask_high
(
priv
,
IWLAGN_EXT_BEACON_TIME_POS
)
>>
IWLAGN_EXT_BEACON_TIME_POS
);
rem
=
(
usec
%
interval
)
&
iwl_beacon_time_mask_low
(
priv
,
IWLAGN_EXT_BEACON_TIME_POS
);
return
(
quot
<<
IWLAGN_EXT_BEACON_TIME_POS
)
+
rem
;
}
/* base is usually what we get from ucode with each received frame,
* the same as HW timer counter counting down
*/
static
__le32
iwl_add_beacon_time
(
struct
iwl_priv
*
priv
,
u32
base
,
u32
addon
,
u32
beacon_interval
)
{
u32
base_low
=
base
&
iwl_beacon_time_mask_low
(
priv
,
IWLAGN_EXT_BEACON_TIME_POS
);
u32
addon_low
=
addon
&
iwl_beacon_time_mask_low
(
priv
,
IWLAGN_EXT_BEACON_TIME_POS
);
u32
interval
=
beacon_interval
*
TIME_UNIT
;
u32
res
=
(
base
&
iwl_beacon_time_mask_high
(
priv
,
IWLAGN_EXT_BEACON_TIME_POS
))
+
(
addon
&
iwl_beacon_time_mask_high
(
priv
,
IWLAGN_EXT_BEACON_TIME_POS
));
if
(
base_low
>
addon_low
)
res
+=
base_low
-
addon_low
;
else
if
(
base_low
<
addon_low
)
{
res
+=
interval
+
base_low
-
addon_low
;
res
+=
(
1
<<
IWLAGN_EXT_BEACON_TIME_POS
);
}
else
res
+=
(
1
<<
IWLAGN_EXT_BEACON_TIME_POS
);
return
cpu_to_le32
(
res
);
}
static
const
struct
iwl_sensitivity_ranges
iwl1000_sensitivity
=
{
.
min_nrg_cck
=
95
,
.
auto_corr_min_ofdm
=
90
,
...
...
drivers/net/wireless/iwlwifi/iwl-agn-lib.c
浏览文件 @
0d920987
...
...
@@ -307,24 +307,30 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
.
bt3_prio_sample_time
=
IWLAGN_BT3_PRIO_SAMPLE_DEFAULT
,
.
bt3_timer_t2_value
=
IWLAGN_BT3_T2_DEFAULT
,
};
struct
iwl
6000_bt_cmd
bt_cmd_6000
;
struct
iwl
2000_bt_cmd
bt_cmd_2000
;
struct
iwl
_bt_cmd_v1
bt_cmd_v1
;
struct
iwl
_bt_cmd_v2
bt_cmd_v2
;
int
ret
;
BUILD_BUG_ON
(
sizeof
(
iwlagn_def_3w_lookup
)
!=
sizeof
(
basic
.
bt3_lookup_table
));
if
(
cfg
(
priv
)
->
bt_params
)
{
/*
* newer generation of devices (2000 series and newer)
* use the version 2 of the bt command
* we need to make sure sending the host command
* with correct data structure to avoid uCode assert
*/
if
(
cfg
(
priv
)
->
bt_params
->
bt_session_2
)
{
bt_cmd_
2000
.
prio_boost
=
cpu_to_le32
(
bt_cmd_
v2
.
prio_boost
=
cpu_to_le32
(
cfg
(
priv
)
->
bt_params
->
bt_prio_boost
);
bt_cmd_
2000
.
tx_prio_boost
=
0
;
bt_cmd_
2000
.
rx_prio_boost
=
0
;
bt_cmd_
v2
.
tx_prio_boost
=
0
;
bt_cmd_
v2
.
rx_prio_boost
=
0
;
}
else
{
bt_cmd_
6000
.
prio_boost
=
bt_cmd_
v1
.
prio_boost
=
cfg
(
priv
)
->
bt_params
->
bt_prio_boost
;
bt_cmd_
6000
.
tx_prio_boost
=
0
;
bt_cmd_
6000
.
rx_prio_boost
=
0
;
bt_cmd_
v1
.
tx_prio_boost
=
0
;
bt_cmd_
v1
.
rx_prio_boost
=
0
;
}
}
else
{
IWL_ERR
(
priv
,
"failed to construct BT Coex Config
\n
"
);
...
...
@@ -371,15 +377,15 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
"full concurrency"
:
"3-wire"
);
if
(
cfg
(
priv
)
->
bt_params
->
bt_session_2
)
{
memcpy
(
&
bt_cmd_
2000
.
basic
,
&
basic
,
memcpy
(
&
bt_cmd_
v2
.
basic
,
&
basic
,
sizeof
(
basic
));
ret
=
iwl_dvm_send_cmd_pdu
(
priv
,
REPLY_BT_CONFIG
,
CMD_SYNC
,
sizeof
(
bt_cmd_
2000
),
&
bt_cmd_2000
);
CMD_SYNC
,
sizeof
(
bt_cmd_
v2
),
&
bt_cmd_v2
);
}
else
{
memcpy
(
&
bt_cmd_
6000
.
basic
,
&
basic
,
memcpy
(
&
bt_cmd_
v1
.
basic
,
&
basic
,
sizeof
(
basic
));
ret
=
iwl_dvm_send_cmd_pdu
(
priv
,
REPLY_BT_CONFIG
,
CMD_SYNC
,
sizeof
(
bt_cmd_
6000
),
&
bt_cmd_6000
);
CMD_SYNC
,
sizeof
(
bt_cmd_
v1
),
&
bt_cmd_v1
);
}
if
(
ret
)
IWL_ERR
(
priv
,
"failed to send BT Coex Config
\n
"
);
...
...
drivers/net/wireless/iwlwifi/iwl-agn-rs.c
浏览文件 @
0d920987
...
...
@@ -2826,6 +2826,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
struct
iwl_station_priv
*
sta_priv
;
struct
iwl_lq_sta
*
lq_sta
;
struct
ieee80211_supported_band
*
sband
;
unsigned
long
supp
;
/* must be unsigned long for for_each_set_bit */
sta_priv
=
(
struct
iwl_station_priv
*
)
sta
->
drv_priv
;
lq_sta
=
&
sta_priv
->
lq_sta
;
...
...
@@ -2855,8 +2856,15 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
lq_sta
->
max_rate_idx
=
-
1
;
lq_sta
->
missed_rate_counter
=
IWL_MISSED_RATE_MAX
;
lq_sta
->
is_green
=
rs_use_green
(
sta
);
lq_sta
->
active_legacy_rate
=
priv
->
active_rate
&
~
(
0x1000
);
lq_sta
->
band
=
priv
->
band
;
lq_sta
->
band
=
sband
->
band
;
/*
* active legacy rates as per supported rates bitmap
*/
supp
=
sta
->
supp_rates
[
sband
->
band
];
lq_sta
->
active_legacy_rate
=
0
;
for_each_set_bit
(
i
,
&
supp
,
BITS_PER_LONG
)
lq_sta
->
active_legacy_rate
|=
BIT
(
sband
->
bitrates
[
i
].
hw_value
);
/*
* active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
* supp_rates[] does not; shift to convert format, force 9 MBits off.
...
...
drivers/net/wireless/iwlwifi/iwl-agn-rx.c
浏览文件 @
0d920987
...
...
@@ -284,6 +284,45 @@ static bool iwlagn_good_plcp_health(struct iwl_priv *priv,
return
true
;
}
int
iwl_force_rf_reset
(
struct
iwl_priv
*
priv
,
bool
external
)
{
struct
iwl_rf_reset
*
rf_reset
;
if
(
test_bit
(
STATUS_EXIT_PENDING
,
&
priv
->
status
))
return
-
EAGAIN
;
if
(
!
iwl_is_any_associated
(
priv
))
{
IWL_DEBUG_SCAN
(
priv
,
"force reset rejected: not associated
\n
"
);
return
-
ENOLINK
;
}
rf_reset
=
&
priv
->
rf_reset
;
rf_reset
->
reset_request_count
++
;
if
(
!
external
&&
rf_reset
->
last_reset_jiffies
&&
time_after
(
rf_reset
->
last_reset_jiffies
+
IWL_DELAY_NEXT_FORCE_RF_RESET
,
jiffies
))
{
IWL_DEBUG_INFO
(
priv
,
"RF reset rejected
\n
"
);
rf_reset
->
reset_reject_count
++
;
return
-
EAGAIN
;
}
rf_reset
->
reset_success_count
++
;
rf_reset
->
last_reset_jiffies
=
jiffies
;
/*
* There is no easy and better way to force reset the radio,
* the only known method is switching channel which will force to
* reset and tune the radio.
* Use internal short scan (single channel) operation to should
* achieve this objective.
* Driver should reset the radio when number of consecutive missed
* beacon, or any other uCode error condition detected.
*/
IWL_DEBUG_INFO
(
priv
,
"perform radio reset.
\n
"
);
iwl_internal_short_hw_scan
(
priv
);
return
0
;
}
static
void
iwlagn_recover_from_statistics
(
struct
iwl_priv
*
priv
,
struct
statistics_rx_phy
*
cur_ofdm
,
struct
statistics_rx_ht_phy
*
cur_ofdm_ht
,
...
...
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
浏览文件 @
0d920987
...
...
@@ -32,6 +32,78 @@
#include "iwl-trans.h"
#include "iwl-shared.h"
/*
* initialize rxon structure with default values from eeprom
*/
void
iwl_connection_init_rx_config
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
)
{
const
struct
iwl_channel_info
*
ch_info
;
memset
(
&
ctx
->
staging
,
0
,
sizeof
(
ctx
->
staging
));
if
(
!
ctx
->
vif
)
{
ctx
->
staging
.
dev_type
=
ctx
->
unused_devtype
;
}
else
switch
(
ctx
->
vif
->
type
)
{
case
NL80211_IFTYPE_AP
:
ctx
->
staging
.
dev_type
=
ctx
->
ap_devtype
;
break
;
case
NL80211_IFTYPE_STATION
:
ctx
->
staging
.
dev_type
=
ctx
->
station_devtype
;
ctx
->
staging
.
filter_flags
=
RXON_FILTER_ACCEPT_GRP_MSK
;
break
;
case
NL80211_IFTYPE_ADHOC
:
ctx
->
staging
.
dev_type
=
ctx
->
ibss_devtype
;
ctx
->
staging
.
flags
=
RXON_FLG_SHORT_PREAMBLE_MSK
;
ctx
->
staging
.
filter_flags
=
RXON_FILTER_BCON_AWARE_MSK
|
RXON_FILTER_ACCEPT_GRP_MSK
;
break
;
default:
IWL_ERR
(
priv
,
"Unsupported interface type %d
\n
"
,
ctx
->
vif
->
type
);
break
;
}
#if 0
/* TODO: Figure out when short_preamble would be set and cache from
* that */
if (!hw_to_local(priv->hw)->short_preamble)
ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
else
ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
#endif
ch_info
=
iwl_get_channel_info
(
priv
,
priv
->
band
,
le16_to_cpu
(
ctx
->
active
.
channel
));
if
(
!
ch_info
)
ch_info
=
&
priv
->
channel_info
[
0
];
ctx
->
staging
.
channel
=
cpu_to_le16
(
ch_info
->
channel
);
priv
->
band
=
ch_info
->
band
;
iwl_set_flags_for_band
(
priv
,
ctx
,
priv
->
band
,
ctx
->
vif
);
ctx
->
staging
.
ofdm_basic_rates
=
(
IWL_OFDM_RATES_MASK
>>
IWL_FIRST_OFDM_RATE
)
&
0xFF
;
ctx
->
staging
.
cck_basic_rates
=
(
IWL_CCK_RATES_MASK
>>
IWL_FIRST_CCK_RATE
)
&
0xF
;
/* clear both MIX and PURE40 mode flag */
ctx
->
staging
.
flags
&=
~
(
RXON_FLG_CHANNEL_MODE_MIXED
|
RXON_FLG_CHANNEL_MODE_PURE_40
);
if
(
ctx
->
vif
)
memcpy
(
ctx
->
staging
.
node_addr
,
ctx
->
vif
->
addr
,
ETH_ALEN
);
ctx
->
staging
.
ofdm_ht_single_stream_basic_rates
=
0xff
;
ctx
->
staging
.
ofdm_ht_dual_stream_basic_rates
=
0xff
;
ctx
->
staging
.
ofdm_ht_triple_stream_basic_rates
=
0xff
;
}
static
int
iwlagn_disable_bss
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
,
struct
iwl_rxon_cmd
*
send
)
...
...
@@ -335,6 +407,61 @@ static int iwlagn_rxon_disconn(struct iwl_priv *priv,
return
0
;
}
static
int
iwl_set_tx_power
(
struct
iwl_priv
*
priv
,
s8
tx_power
,
bool
force
)
{
int
ret
;
s8
prev_tx_power
;
bool
defer
;
struct
iwl_rxon_context
*
ctx
=
&
priv
->
contexts
[
IWL_RXON_CTX_BSS
];
lockdep_assert_held
(
&
priv
->
mutex
);
if
(
priv
->
tx_power_user_lmt
==
tx_power
&&
!
force
)
return
0
;
if
(
tx_power
<
IWLAGN_TX_POWER_TARGET_POWER_MIN
)
{
IWL_WARN
(
priv
,
"Requested user TXPOWER %d below lower limit %d.
\n
"
,
tx_power
,
IWLAGN_TX_POWER_TARGET_POWER_MIN
);
return
-
EINVAL
;
}
if
(
tx_power
>
priv
->
tx_power_device_lmt
)
{
IWL_WARN
(
priv
,
"Requested user TXPOWER %d above upper limit %d.
\n
"
,
tx_power
,
priv
->
tx_power_device_lmt
);
return
-
EINVAL
;
}
if
(
!
iwl_is_ready_rf
(
priv
))
return
-
EIO
;
/* scan complete and commit_rxon use tx_power_next value,
* it always need to be updated for newest request */
priv
->
tx_power_next
=
tx_power
;
/* do not set tx power when scanning or channel changing */
defer
=
test_bit
(
STATUS_SCANNING
,
&
priv
->
status
)
||
memcmp
(
&
ctx
->
active
,
&
ctx
->
staging
,
sizeof
(
ctx
->
staging
));
if
(
defer
&&
!
force
)
{
IWL_DEBUG_INFO
(
priv
,
"Deferring tx power set
\n
"
);
return
0
;
}
prev_tx_power
=
priv
->
tx_power_user_lmt
;
priv
->
tx_power_user_lmt
=
tx_power
;
ret
=
iwlagn_send_tx_power
(
priv
);
/* if fail to set tx_power, restore the orig. tx power */
if
(
ret
)
{
priv
->
tx_power_user_lmt
=
prev_tx_power
;
priv
->
tx_power_next
=
prev_tx_power
;
}
return
ret
;
}
static
int
iwlagn_rxon_connect
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
)
{
...
...
@@ -501,6 +628,161 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
return
ret
;
}
static
void
_iwl_set_rxon_ht
(
struct
iwl_priv
*
priv
,
struct
iwl_ht_config
*
ht_conf
,
struct
iwl_rxon_context
*
ctx
)
{
struct
iwl_rxon_cmd
*
rxon
=
&
ctx
->
staging
;
if
(
!
ctx
->
ht
.
enabled
)
{
rxon
->
flags
&=
~
(
RXON_FLG_CHANNEL_MODE_MSK
|
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK
|
RXON_FLG_HT40_PROT_MSK
|
RXON_FLG_HT_PROT_MSK
);
return
;
}
/* FIXME: if the definition of ht.protection changed, the "translation"
* will be needed for rxon->flags
*/
rxon
->
flags
|=
cpu_to_le32
(
ctx
->
ht
.
protection
<<
RXON_FLG_HT_OPERATING_MODE_POS
);
/* Set up channel bandwidth:
* 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */
/* clear the HT channel mode before set the mode */
rxon
->
flags
&=
~
(
RXON_FLG_CHANNEL_MODE_MSK
|
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK
);
if
(
iwl_is_ht40_tx_allowed
(
priv
,
ctx
,
NULL
))
{
/* pure ht40 */
if
(
ctx
->
ht
.
protection
==
IEEE80211_HT_OP_MODE_PROTECTION_20MHZ
)
{
rxon
->
flags
|=
RXON_FLG_CHANNEL_MODE_PURE_40
;
/*
* Note: control channel is opposite of extension
* channel
*/
switch
(
ctx
->
ht
.
extension_chan_offset
)
{
case
IEEE80211_HT_PARAM_CHA_SEC_ABOVE
:
rxon
->
flags
&=
~
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK
;
break
;
case
IEEE80211_HT_PARAM_CHA_SEC_BELOW
:
rxon
->
flags
|=
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK
;
break
;
}
}
else
{
/*
* Note: control channel is opposite of extension
* channel
*/
switch
(
ctx
->
ht
.
extension_chan_offset
)
{
case
IEEE80211_HT_PARAM_CHA_SEC_ABOVE
:
rxon
->
flags
&=
~
(
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK
);
rxon
->
flags
|=
RXON_FLG_CHANNEL_MODE_MIXED
;
break
;
case
IEEE80211_HT_PARAM_CHA_SEC_BELOW
:
rxon
->
flags
|=
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK
;
rxon
->
flags
|=
RXON_FLG_CHANNEL_MODE_MIXED
;
break
;
case
IEEE80211_HT_PARAM_CHA_SEC_NONE
:
default:
/*
* channel location only valid if in Mixed
* mode
*/
IWL_ERR
(
priv
,
"invalid extension channel offset
\n
"
);
break
;
}
}
}
else
{
rxon
->
flags
|=
RXON_FLG_CHANNEL_MODE_LEGACY
;
}
iwlagn_set_rxon_chain
(
priv
,
ctx
);
IWL_DEBUG_ASSOC
(
priv
,
"rxon flags 0x%X operation mode :0x%X "
"extension channel offset 0x%x
\n
"
,
le32_to_cpu
(
rxon
->
flags
),
ctx
->
ht
.
protection
,
ctx
->
ht
.
extension_chan_offset
);
}
void
iwl_set_rxon_ht
(
struct
iwl_priv
*
priv
,
struct
iwl_ht_config
*
ht_conf
)
{
struct
iwl_rxon_context
*
ctx
;
for_each_context
(
priv
,
ctx
)
_iwl_set_rxon_ht
(
priv
,
ht_conf
,
ctx
);
}
/**
* iwl_set_rxon_channel - Set the band and channel values in staging RXON
* @ch: requested channel as a pointer to struct ieee80211_channel
* NOTE: Does not commit to the hardware; it sets appropriate bit fields
* in the staging RXON flag structure based on the ch->band
*/
void
iwl_set_rxon_channel
(
struct
iwl_priv
*
priv
,
struct
ieee80211_channel
*
ch
,
struct
iwl_rxon_context
*
ctx
)
{
enum
ieee80211_band
band
=
ch
->
band
;
u16
channel
=
ch
->
hw_value
;
if
((
le16_to_cpu
(
ctx
->
staging
.
channel
)
==
channel
)
&&
(
priv
->
band
==
band
))
return
;
ctx
->
staging
.
channel
=
cpu_to_le16
(
channel
);
if
(
band
==
IEEE80211_BAND_5GHZ
)
ctx
->
staging
.
flags
&=
~
RXON_FLG_BAND_24G_MSK
;
else
ctx
->
staging
.
flags
|=
RXON_FLG_BAND_24G_MSK
;
priv
->
band
=
band
;
IWL_DEBUG_INFO
(
priv
,
"Staging channel set to %d [%d]
\n
"
,
channel
,
band
);
}
void
iwl_set_flags_for_band
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
,
enum
ieee80211_band
band
,
struct
ieee80211_vif
*
vif
)
{
if
(
band
==
IEEE80211_BAND_5GHZ
)
{
ctx
->
staging
.
flags
&=
~
(
RXON_FLG_BAND_24G_MSK
|
RXON_FLG_AUTO_DETECT_MSK
|
RXON_FLG_CCK_MSK
);
ctx
->
staging
.
flags
|=
RXON_FLG_SHORT_SLOT_MSK
;
}
else
{
/* Copied from iwl_post_associate() */
if
(
vif
&&
vif
->
bss_conf
.
use_short_slot
)
ctx
->
staging
.
flags
|=
RXON_FLG_SHORT_SLOT_MSK
;
else
ctx
->
staging
.
flags
&=
~
RXON_FLG_SHORT_SLOT_MSK
;
ctx
->
staging
.
flags
|=
RXON_FLG_BAND_24G_MSK
;
ctx
->
staging
.
flags
|=
RXON_FLG_AUTO_DETECT_MSK
;
ctx
->
staging
.
flags
&=
~
RXON_FLG_CCK_MSK
;
}
}
void
iwl_set_rate
(
struct
iwl_priv
*
priv
)
{
struct
iwl_rxon_context
*
ctx
;
for_each_context
(
priv
,
ctx
)
{
ctx
->
staging
.
cck_basic_rates
=
(
IWL_CCK_BASIC_RATES_MASK
>>
IWL_FIRST_CCK_RATE
)
&
0xF
;
ctx
->
staging
.
ofdm_basic_rates
=
(
IWL_OFDM_BASIC_RATES_MASK
>>
IWL_FIRST_OFDM_RATE
)
&
0xFF
;
}
}
static
void
iwl_set_rxon_hwcrypto
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
,
int
hw_decrypt
)
{
...
...
@@ -649,6 +931,33 @@ static int iwl_full_rxon_required(struct iwl_priv *priv,
return
0
;
}
#ifdef CONFIG_IWLWIFI_DEBUG
void
iwl_print_rx_config_cmd
(
struct
iwl_priv
*
priv
,
enum
iwl_rxon_context_id
ctxid
)
{
struct
iwl_rxon_context
*
ctx
=
&
priv
->
contexts
[
ctxid
];
struct
iwl_rxon_cmd
*
rxon
=
&
ctx
->
staging
;
IWL_DEBUG_RADIO
(
priv
,
"RX CONFIG:
\n
"
);
iwl_print_hex_dump
(
priv
,
IWL_DL_RADIO
,
(
u8
*
)
rxon
,
sizeof
(
*
rxon
));
IWL_DEBUG_RADIO
(
priv
,
"u16 channel: 0x%x
\n
"
,
le16_to_cpu
(
rxon
->
channel
));
IWL_DEBUG_RADIO
(
priv
,
"u32 flags: 0x%08X
\n
"
,
le32_to_cpu
(
rxon
->
flags
));
IWL_DEBUG_RADIO
(
priv
,
"u32 filter_flags: 0x%08x
\n
"
,
le32_to_cpu
(
rxon
->
filter_flags
));
IWL_DEBUG_RADIO
(
priv
,
"u8 dev_type: 0x%x
\n
"
,
rxon
->
dev_type
);
IWL_DEBUG_RADIO
(
priv
,
"u8 ofdm_basic_rates: 0x%02x
\n
"
,
rxon
->
ofdm_basic_rates
);
IWL_DEBUG_RADIO
(
priv
,
"u8 cck_basic_rates: 0x%02x
\n
"
,
rxon
->
cck_basic_rates
);
IWL_DEBUG_RADIO
(
priv
,
"u8[6] node_addr: %pM
\n
"
,
rxon
->
node_addr
);
IWL_DEBUG_RADIO
(
priv
,
"u8[6] bssid_addr: %pM
\n
"
,
rxon
->
bssid_addr
);
IWL_DEBUG_RADIO
(
priv
,
"u16 assoc_id: 0x%x
\n
"
,
le16_to_cpu
(
rxon
->
assoc_id
));
}
#endif
/**
* iwlagn_commit_rxon - commit staging_rxon to hardware
*
...
...
drivers/net/wireless/iwlwifi/iwl-agn-sta.c
浏览文件 @
0d920987
...
...
@@ -34,6 +34,8 @@
#include "iwl-agn.h"
#include "iwl-trans.h"
const
u8
iwl_bcast_addr
[
ETH_ALEN
]
=
{
0xFF
,
0xFF
,
0xFF
,
0xFF
,
0xFF
,
0xFF
};
static
int
iwl_sta_ucode_activate
(
struct
iwl_priv
*
priv
,
u8
sta_id
)
{
lockdep_assert_held
(
&
priv
->
sta_lock
);
...
...
@@ -170,6 +172,50 @@ int iwl_send_add_sta(struct iwl_priv *priv,
return
cmd
.
handler_status
;
}
static
bool
iwl_is_channel_extension
(
struct
iwl_priv
*
priv
,
enum
ieee80211_band
band
,
u16
channel
,
u8
extension_chan_offset
)
{
const
struct
iwl_channel_info
*
ch_info
;
ch_info
=
iwl_get_channel_info
(
priv
,
band
,
channel
);
if
(
!
is_channel_valid
(
ch_info
))
return
false
;
if
(
extension_chan_offset
==
IEEE80211_HT_PARAM_CHA_SEC_ABOVE
)
return
!
(
ch_info
->
ht40_extension_channel
&
IEEE80211_CHAN_NO_HT40PLUS
);
else
if
(
extension_chan_offset
==
IEEE80211_HT_PARAM_CHA_SEC_BELOW
)
return
!
(
ch_info
->
ht40_extension_channel
&
IEEE80211_CHAN_NO_HT40MINUS
);
return
false
;
}
bool
iwl_is_ht40_tx_allowed
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
,
struct
ieee80211_sta_ht_cap
*
ht_cap
)
{
if
(
!
ctx
->
ht
.
enabled
||
!
ctx
->
ht
.
is_40mhz
)
return
false
;
/*
* We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
* the bit will not set if it is pure 40MHz case
*/
if
(
ht_cap
&&
!
ht_cap
->
ht_supported
)
return
false
;
#ifdef CONFIG_IWLWIFI_DEBUGFS
if
(
priv
->
disable_ht40
)
return
false
;
#endif
return
iwl_is_channel_extension
(
priv
,
priv
->
band
,
le16_to_cpu
(
ctx
->
staging
.
channel
),
ctx
->
ht
.
extension_chan_offset
);
}
static
void
iwl_sta_calc_ht_flags
(
struct
iwl_priv
*
priv
,
struct
ieee80211_sta
*
sta
,
struct
iwl_rxon_context
*
ctx
,
...
...
@@ -581,6 +627,56 @@ void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id,
spin_unlock_bh
(
&
priv
->
sta_lock
);
}
static
void
iwl_sta_fill_lq
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
,
u8
sta_id
,
struct
iwl_link_quality_cmd
*
link_cmd
)
{
int
i
,
r
;
u32
rate_flags
=
0
;
__le32
rate_n_flags
;
lockdep_assert_held
(
&
priv
->
mutex
);
memset
(
link_cmd
,
0
,
sizeof
(
*
link_cmd
));
/* Set up the rate scaling to start at selected rate, fall back
* all the way down to 1M in IEEE order, and then spin on 1M */
if
(
priv
->
band
==
IEEE80211_BAND_5GHZ
)
r
=
IWL_RATE_6M_INDEX
;
else
if
(
ctx
&&
ctx
->
vif
&&
ctx
->
vif
->
p2p
)
r
=
IWL_RATE_6M_INDEX
;
else
r
=
IWL_RATE_1M_INDEX
;
if
(
r
>=
IWL_FIRST_CCK_RATE
&&
r
<=
IWL_LAST_CCK_RATE
)
rate_flags
|=
RATE_MCS_CCK_MSK
;
rate_flags
|=
first_antenna
(
priv
->
hw_params
.
valid_tx_ant
)
<<
RATE_MCS_ANT_POS
;
rate_n_flags
=
iwl_hw_set_rate_n_flags
(
iwl_rates
[
r
].
plcp
,
rate_flags
);
for
(
i
=
0
;
i
<
LINK_QUAL_MAX_RETRY_NUM
;
i
++
)
link_cmd
->
rs_table
[
i
].
rate_n_flags
=
rate_n_flags
;
link_cmd
->
general_params
.
single_stream_ant_msk
=
first_antenna
(
priv
->
hw_params
.
valid_tx_ant
);
link_cmd
->
general_params
.
dual_stream_ant_msk
=
priv
->
hw_params
.
valid_tx_ant
&
~
first_antenna
(
priv
->
hw_params
.
valid_tx_ant
);
if
(
!
link_cmd
->
general_params
.
dual_stream_ant_msk
)
{
link_cmd
->
general_params
.
dual_stream_ant_msk
=
ANT_AB
;
}
else
if
(
num_of_ant
(
priv
->
hw_params
.
valid_tx_ant
)
==
2
)
{
link_cmd
->
general_params
.
dual_stream_ant_msk
=
priv
->
hw_params
.
valid_tx_ant
;
}
link_cmd
->
agg_params
.
agg_dis_start_th
=
LINK_QUAL_AGG_DISABLE_START_DEF
;
link_cmd
->
agg_params
.
agg_time_limit
=
cpu_to_le16
(
LINK_QUAL_AGG_TIME_LIMIT_DEF
);
link_cmd
->
sta_id
=
sta_id
;
}
/**
* iwl_clear_ucode_stations - clear ucode station table bits
*
...
...
@@ -841,56 +937,6 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
}
void
iwl_sta_fill_lq
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
,
u8
sta_id
,
struct
iwl_link_quality_cmd
*
link_cmd
)
{
int
i
,
r
;
u32
rate_flags
=
0
;
__le32
rate_n_flags
;
lockdep_assert_held
(
&
priv
->
mutex
);
memset
(
link_cmd
,
0
,
sizeof
(
*
link_cmd
));
/* Set up the rate scaling to start at selected rate, fall back
* all the way down to 1M in IEEE order, and then spin on 1M */
if
(
priv
->
band
==
IEEE80211_BAND_5GHZ
)
r
=
IWL_RATE_6M_INDEX
;
else
if
(
ctx
&&
ctx
->
vif
&&
ctx
->
vif
->
p2p
)
r
=
IWL_RATE_6M_INDEX
;
else
r
=
IWL_RATE_1M_INDEX
;
if
(
r
>=
IWL_FIRST_CCK_RATE
&&
r
<=
IWL_LAST_CCK_RATE
)
rate_flags
|=
RATE_MCS_CCK_MSK
;
rate_flags
|=
first_antenna
(
priv
->
hw_params
.
valid_tx_ant
)
<<
RATE_MCS_ANT_POS
;
rate_n_flags
=
iwl_hw_set_rate_n_flags
(
iwl_rates
[
r
].
plcp
,
rate_flags
);
for
(
i
=
0
;
i
<
LINK_QUAL_MAX_RETRY_NUM
;
i
++
)
link_cmd
->
rs_table
[
i
].
rate_n_flags
=
rate_n_flags
;
link_cmd
->
general_params
.
single_stream_ant_msk
=
first_antenna
(
priv
->
hw_params
.
valid_tx_ant
);
link_cmd
->
general_params
.
dual_stream_ant_msk
=
priv
->
hw_params
.
valid_tx_ant
&
~
first_antenna
(
priv
->
hw_params
.
valid_tx_ant
);
if
(
!
link_cmd
->
general_params
.
dual_stream_ant_msk
)
{
link_cmd
->
general_params
.
dual_stream_ant_msk
=
ANT_AB
;
}
else
if
(
num_of_ant
(
priv
->
hw_params
.
valid_tx_ant
)
==
2
)
{
link_cmd
->
general_params
.
dual_stream_ant_msk
=
priv
->
hw_params
.
valid_tx_ant
;
}
link_cmd
->
agg_params
.
agg_dis_start_th
=
LINK_QUAL_AGG_DISABLE_START_DEF
;
link_cmd
->
agg_params
.
agg_time_limit
=
cpu_to_le16
(
LINK_QUAL_AGG_TIME_LIMIT_DEF
);
link_cmd
->
sta_id
=
sta_id
;
}
static
struct
iwl_link_quality_cmd
*
iwl_sta_alloc_lq
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
,
u8
sta_id
)
...
...
drivers/net/wireless/iwlwifi/iwl-agn.c
浏览文件 @
0d920987
...
...
@@ -289,6 +289,25 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
mutex_unlock
(
&
priv
->
mutex
);
}
int
iwl_send_statistics_request
(
struct
iwl_priv
*
priv
,
u8
flags
,
bool
clear
)
{
struct
iwl_statistics_cmd
statistics_cmd
=
{
.
configuration_flags
=
clear
?
IWL_STATS_CONF_CLEAR_STATS
:
0
,
};
if
(
flags
&
CMD_ASYNC
)
return
iwl_dvm_send_cmd_pdu
(
priv
,
REPLY_STATISTICS_CMD
,
CMD_ASYNC
,
sizeof
(
struct
iwl_statistics_cmd
),
&
statistics_cmd
);
else
return
iwl_dvm_send_cmd_pdu
(
priv
,
REPLY_STATISTICS_CMD
,
CMD_SYNC
,
sizeof
(
struct
iwl_statistics_cmd
),
&
statistics_cmd
);
}
/**
* iwl_bg_statistics_periodic - Timer callback to queue statistics
*
...
...
@@ -726,6 +745,29 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
}
}
static
void
iwl_send_bt_config
(
struct
iwl_priv
*
priv
)
{
struct
iwl_bt_cmd
bt_cmd
=
{
.
lead_time
=
BT_LEAD_TIME_DEF
,
.
max_kill
=
BT_MAX_KILL_DEF
,
.
kill_ack_mask
=
0
,
.
kill_cts_mask
=
0
,
};
if
(
!
iwlagn_mod_params
.
bt_coex_active
)
bt_cmd
.
flags
=
BT_COEX_DISABLE
;
else
bt_cmd
.
flags
=
BT_COEX_ENABLE
;
priv
->
bt_enable_flag
=
bt_cmd
.
flags
;
IWL_DEBUG_INFO
(
priv
,
"BT coex %s
\n
"
,
(
bt_cmd
.
flags
==
BT_COEX_DISABLE
)
?
"disable"
:
"active"
);
if
(
iwl_dvm_send_cmd_pdu
(
priv
,
REPLY_BT_CONFIG
,
CMD_SYNC
,
sizeof
(
struct
iwl_bt_cmd
),
&
bt_cmd
))
IWL_ERR
(
priv
,
"failed to send BT Coex Config
\n
"
);
}
/**
* iwl_alive_start - called after REPLY_ALIVE notification received
* from protocol/runtime uCode (initialization uCode's
...
...
@@ -790,8 +832,6 @@ int iwl_alive_start(struct iwl_priv *priv)
ieee80211_wake_queues
(
priv
->
hw
);
priv
->
active_rate
=
IWL_RATES_MASK
;
/* Configure Tx antenna selection based on H/W config */
iwlagn_send_tx_ant_config
(
priv
,
priv
->
hw_params
.
valid_tx_ant
);
...
...
@@ -1524,7 +1564,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
ucode_flags
=
fw
->
ucode_capa
.
flags
;
#ifndef CONFIG_IWLWIFI_P2P
ucode_flags
&=
~
IWL_UCODE_TLV_FLAGS_P
AN
;
ucode_flags
&=
~
IWL_UCODE_TLV_FLAGS_P
2P
;
#endif
if
(
ucode_flags
&
IWL_UCODE_TLV_FLAGS_PAN
)
{
...
...
@@ -2121,6 +2161,65 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
return
pos
;
}
static
void
iwlagn_fw_error
(
struct
iwl_priv
*
priv
,
bool
ondemand
)
{
unsigned
int
reload_msec
;
unsigned
long
reload_jiffies
;
#ifdef CONFIG_IWLWIFI_DEBUG
if
(
iwl_have_debug_level
(
IWL_DL_FW_ERRORS
))
iwl_print_rx_config_cmd
(
priv
,
IWL_RXON_CTX_BSS
);
#endif
/* uCode is no longer loaded. */
priv
->
ucode_loaded
=
false
;
/* Set the FW error flag -- cleared on iwl_down */
set_bit
(
STATUS_FW_ERROR
,
&
priv
->
status
);
/* Cancel currently queued command. */
clear_bit
(
STATUS_HCMD_ACTIVE
,
&
priv
->
shrd
->
status
);
iwl_abort_notification_waits
(
&
priv
->
notif_wait
);
/* Keep the restart process from trying to send host
* commands by clearing the ready bit */
clear_bit
(
STATUS_READY
,
&
priv
->
status
);
wake_up
(
&
trans
(
priv
)
->
wait_command_queue
);
if
(
!
ondemand
)
{
/*
* If firmware keep reloading, then it indicate something
* serious wrong and firmware having problem to recover
* from it. Instead of keep trying which will fill the syslog
* and hang the system, let's just stop it
*/
reload_jiffies
=
jiffies
;
reload_msec
=
jiffies_to_msecs
((
long
)
reload_jiffies
-
(
long
)
priv
->
reload_jiffies
);
priv
->
reload_jiffies
=
reload_jiffies
;
if
(
reload_msec
<=
IWL_MIN_RELOAD_DURATION
)
{
priv
->
reload_count
++
;
if
(
priv
->
reload_count
>=
IWL_MAX_CONTINUE_RELOAD_CNT
)
{
IWL_ERR
(
priv
,
"BUG_ON, Stop restarting
\n
"
);
return
;
}
}
else
priv
->
reload_count
=
0
;
}
if
(
!
test_bit
(
STATUS_EXIT_PENDING
,
&
priv
->
status
))
{
if
(
iwlagn_mod_params
.
restart_fw
)
{
IWL_DEBUG_FW_ERRORS
(
priv
,
"Restarting adapter due to uCode error.
\n
"
);
queue_work
(
priv
->
workqueue
,
&
priv
->
restart
);
}
else
IWL_DEBUG_FW_ERRORS
(
priv
,
"Detected FW error, but not restarting
\n
"
);
}
}
static
void
iwl_nic_error
(
struct
iwl_op_mode
*
op_mode
)
{
struct
iwl_priv
*
priv
=
IWL_OP_MODE_GET_DVM
(
op_mode
);
...
...
@@ -2210,6 +2309,27 @@ void iwlagn_lift_passive_no_rx(struct iwl_priv *priv)
priv
->
passive_no_rx
=
false
;
}
static
void
iwl_free_skb
(
struct
iwl_op_mode
*
op_mode
,
struct
sk_buff
*
skb
)
{
struct
ieee80211_tx_info
*
info
;
info
=
IEEE80211_SKB_CB
(
skb
);
kmem_cache_free
(
iwl_tx_cmd_pool
,
(
info
->
driver_data
[
1
]));
dev_kfree_skb_any
(
skb
);
}
static
void
iwl_set_hw_rfkill_state
(
struct
iwl_op_mode
*
op_mode
,
bool
state
)
{
struct
iwl_priv
*
priv
=
IWL_OP_MODE_GET_DVM
(
op_mode
);
if
(
state
)
set_bit
(
STATUS_RF_KILL_HW
,
&
priv
->
status
);
else
clear_bit
(
STATUS_RF_KILL_HW
,
&
priv
->
status
);
wiphy_rfkill_set_hw_state
(
priv
->
hw
->
wiphy
,
state
);
}
const
struct
iwl_op_mode_ops
iwl_dvm_ops
=
{
.
start
=
iwl_op_mode_dvm_start
,
.
stop
=
iwl_op_mode_dvm_stop
,
...
...
drivers/net/wireless/iwlwifi/iwl-agn.h
浏览文件 @
0d920987
...
...
@@ -97,11 +97,9 @@ static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd)
void
iwl_down
(
struct
iwl_priv
*
priv
);
void
iwl_cancel_deferred_work
(
struct
iwl_priv
*
priv
);
void
iwlagn_prepare_restart
(
struct
iwl_priv
*
priv
);
void
iwl_free_skb
(
struct
iwl_op_mode
*
op_mode
,
struct
sk_buff
*
skb
);
int
__must_check
iwl_rx_dispatch
(
struct
iwl_op_mode
*
op_mode
,
struct
iwl_rx_cmd_buffer
*
rxb
,
struct
iwl_device_cmd
*
cmd
);
void
iwl_set_hw_rfkill_state
(
struct
iwl_op_mode
*
op_mode
,
bool
state
);
bool
iwl_check_for_ct_kill
(
struct
iwl_priv
*
priv
);
...
...
@@ -119,6 +117,8 @@ int iwl_dvm_send_cmd_pdu(struct iwl_priv *priv, u8 id,
u32
flags
,
u16
len
,
const
void
*
data
);
/* RXON */
void
iwl_connection_init_rx_config
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
);
int
iwlagn_set_pan_params
(
struct
iwl_priv
*
priv
);
int
iwlagn_commit_rxon
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
);
void
iwlagn_set_rxon_chain
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
);
...
...
@@ -129,6 +129,14 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
u32
changes
);
void
iwlagn_config_ht40
(
struct
ieee80211_conf
*
conf
,
struct
iwl_rxon_context
*
ctx
);
void
iwl_set_rxon_ht
(
struct
iwl_priv
*
priv
,
struct
iwl_ht_config
*
ht_conf
);
void
iwl_set_rxon_channel
(
struct
iwl_priv
*
priv
,
struct
ieee80211_channel
*
ch
,
struct
iwl_rxon_context
*
ctx
);
void
iwl_set_flags_for_band
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
,
enum
ieee80211_band
band
,
struct
ieee80211_vif
*
vif
);
void
iwl_set_rate
(
struct
iwl_priv
*
priv
);
/* uCode */
int
iwl_send_bt_env
(
struct
iwl_priv
*
priv
,
u8
action
,
u8
type
);
...
...
@@ -141,9 +149,9 @@ int iwl_send_calib_results(struct iwl_priv *priv);
int
iwl_calib_set
(
struct
iwl_priv
*
priv
,
const
struct
iwl_calib_hdr
*
cmd
,
int
len
);
void
iwl_calib_free_results
(
struct
iwl_priv
*
priv
);
void
iwlagn_fw_error
(
struct
iwl_priv
*
priv
,
bool
ondemand
);
int
iwl_dump_nic_event_log
(
struct
iwl_priv
*
priv
,
bool
full_log
,
char
**
buf
,
bool
display
);
int
iwlagn_hw_valid_rtc_data_addr
(
u32
addr
);
/* lib */
int
iwlagn_send_tx_power
(
struct
iwl_priv
*
priv
);
...
...
@@ -151,6 +159,15 @@ void iwlagn_temperature(struct iwl_priv *priv);
int
iwlagn_txfifo_flush
(
struct
iwl_priv
*
priv
,
u16
flush_control
);
void
iwlagn_dev_txfifo_flush
(
struct
iwl_priv
*
priv
,
u16
flush_control
);
int
iwlagn_send_beacon_cmd
(
struct
iwl_priv
*
priv
);
int
iwl_send_statistics_request
(
struct
iwl_priv
*
priv
,
u8
flags
,
bool
clear
);
static
inline
const
struct
ieee80211_supported_band
*
iwl_get_hw_mode
(
struct
iwl_priv
*
priv
,
enum
ieee80211_band
band
)
{
return
priv
->
hw
->
wiphy
->
bands
[
band
];
}
#ifdef CONFIG_PM_SLEEP
int
iwlagn_send_patterns
(
struct
iwl_priv
*
priv
,
struct
cfg80211_wowlan
*
wowlan
);
...
...
@@ -160,6 +177,7 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan);
/* rx */
int
iwlagn_hwrate_to_mac80211_idx
(
u32
rate_n_flags
,
enum
ieee80211_band
band
);
void
iwl_setup_rx_handlers
(
struct
iwl_priv
*
priv
);
void
iwl_chswitch_done
(
struct
iwl_priv
*
priv
,
bool
is_success
);
/* tx */
...
...
@@ -205,6 +223,30 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
void
iwlagn_post_scan
(
struct
iwl_priv
*
priv
);
void
iwlagn_disable_roc
(
struct
iwl_priv
*
priv
);
int
iwl_force_rf_reset
(
struct
iwl_priv
*
priv
,
bool
external
);
void
iwl_init_scan_params
(
struct
iwl_priv
*
priv
);
int
iwl_scan_cancel
(
struct
iwl_priv
*
priv
);
void
iwl_scan_cancel_timeout
(
struct
iwl_priv
*
priv
,
unsigned
long
ms
);
void
iwl_force_scan_end
(
struct
iwl_priv
*
priv
);
void
iwl_internal_short_hw_scan
(
struct
iwl_priv
*
priv
);
void
iwl_setup_rx_scan_handlers
(
struct
iwl_priv
*
priv
);
void
iwl_setup_scan_deferred_work
(
struct
iwl_priv
*
priv
);
void
iwl_cancel_scan_deferred_work
(
struct
iwl_priv
*
priv
);
int
__must_check
iwl_scan_initiate
(
struct
iwl_priv
*
priv
,
struct
ieee80211_vif
*
vif
,
enum
iwl_scan_type
scan_type
,
enum
ieee80211_band
band
);
/* For faster active scanning, scan will move to the next channel if fewer than
* PLCP_QUIET_THRESH packets are heard on this channel within
* ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell
* time if it's a quiet channel (nothing responded to our probe, and there's
* no other traffic).
* Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */
#define IWL_ACTIVE_QUIET_TIME cpu_to_le16(10)
/* msec */
#define IWL_PLCP_QUIET_THRESH cpu_to_le16(1)
/* packets */
#define IWL_SCAN_CHECK_WATCHDOG (HZ * 7)
/* bt coex */
void
iwlagn_send_advance_bt_config
(
struct
iwl_priv
*
priv
);
...
...
@@ -217,6 +259,12 @@ void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv);
void
iwlagn_bt_coex_rssi_monitor
(
struct
iwl_priv
*
priv
);
void
iwlagn_bt_adjust_rssi_monitor
(
struct
iwl_priv
*
priv
,
bool
rssi_ena
);
static
inline
bool
iwl_advanced_bt_coexist
(
struct
iwl_priv
*
priv
)
{
return
cfg
(
priv
)
->
bt_params
&&
cfg
(
priv
)
->
bt_params
->
advanced_bt_coexist
;
}
#ifdef CONFIG_IWLWIFI_DEBUG
const
char
*
iwl_get_tx_fail_reason
(
u32
status
);
const
char
*
iwl_get_agg_tx_fail_reason
(
u16
status
);
...
...
@@ -255,8 +303,6 @@ void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id,
u8
iwl_prep_station
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
,
const
u8
*
addr
,
bool
is_ap
,
struct
ieee80211_sta
*
sta
);
void
iwl_sta_fill_lq
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
,
u8
sta_id
,
struct
iwl_link_quality_cmd
*
link_cmd
);
int
iwl_send_lq_cmd
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
,
struct
iwl_link_quality_cmd
*
lq
,
u8
flags
,
bool
init
);
int
iwl_add_sta_callback
(
struct
iwl_priv
*
priv
,
struct
iwl_rx_cmd_buffer
*
rxb
,
...
...
@@ -264,6 +310,9 @@ int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
int
iwl_sta_update_ht
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
,
struct
ieee80211_sta
*
sta
);
bool
iwl_is_ht40_tx_allowed
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
,
struct
ieee80211_sta_ht_cap
*
ht_cap
);
static
inline
int
iwl_sta_id
(
struct
ieee80211_sta
*
sta
)
{
...
...
drivers/net/wireless/iwlwifi/iwl-commands.h
浏览文件 @
0d920987
...
...
@@ -1918,7 +1918,7 @@ struct iwl_basic_bt_cmd {
__le16
valid
;
};
struct
iwl
6000_bt_cmd
{
struct
iwl
_bt_cmd_v1
{
struct
iwl_basic_bt_cmd
basic
;
u8
prio_boost
;
/*
...
...
@@ -1929,7 +1929,7 @@ struct iwl6000_bt_cmd {
__le16
rx_prio_boost
;
/* SW boost of WiFi rx priority */
};
struct
iwl
2000_bt_cmd
{
struct
iwl
_bt_cmd_v2
{
struct
iwl_basic_bt_cmd
basic
;
__le32
prio_boost
;
/*
...
...
drivers/net/wireless/iwlwifi/iwl-core.c
浏览文件 @
0d920987
...
...
@@ -41,477 +41,6 @@
#include "iwl-agn.h"
#include "iwl-trans.h"
const
u8
iwl_bcast_addr
[
ETH_ALEN
]
=
{
0xFF
,
0xFF
,
0xFF
,
0xFF
,
0xFF
,
0xFF
};
static
bool
iwl_is_channel_extension
(
struct
iwl_priv
*
priv
,
enum
ieee80211_band
band
,
u16
channel
,
u8
extension_chan_offset
)
{
const
struct
iwl_channel_info
*
ch_info
;
ch_info
=
iwl_get_channel_info
(
priv
,
band
,
channel
);
if
(
!
is_channel_valid
(
ch_info
))
return
false
;
if
(
extension_chan_offset
==
IEEE80211_HT_PARAM_CHA_SEC_ABOVE
)
return
!
(
ch_info
->
ht40_extension_channel
&
IEEE80211_CHAN_NO_HT40PLUS
);
else
if
(
extension_chan_offset
==
IEEE80211_HT_PARAM_CHA_SEC_BELOW
)
return
!
(
ch_info
->
ht40_extension_channel
&
IEEE80211_CHAN_NO_HT40MINUS
);
return
false
;
}
bool
iwl_is_ht40_tx_allowed
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
,
struct
ieee80211_sta_ht_cap
*
ht_cap
)
{
if
(
!
ctx
->
ht
.
enabled
||
!
ctx
->
ht
.
is_40mhz
)
return
false
;
/*
* We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
* the bit will not set if it is pure 40MHz case
*/
if
(
ht_cap
&&
!
ht_cap
->
ht_supported
)
return
false
;
#ifdef CONFIG_IWLWIFI_DEBUGFS
if
(
priv
->
disable_ht40
)
return
false
;
#endif
return
iwl_is_channel_extension
(
priv
,
priv
->
band
,
le16_to_cpu
(
ctx
->
staging
.
channel
),
ctx
->
ht
.
extension_chan_offset
);
}
static
void
_iwl_set_rxon_ht
(
struct
iwl_priv
*
priv
,
struct
iwl_ht_config
*
ht_conf
,
struct
iwl_rxon_context
*
ctx
)
{
struct
iwl_rxon_cmd
*
rxon
=
&
ctx
->
staging
;
if
(
!
ctx
->
ht
.
enabled
)
{
rxon
->
flags
&=
~
(
RXON_FLG_CHANNEL_MODE_MSK
|
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK
|
RXON_FLG_HT40_PROT_MSK
|
RXON_FLG_HT_PROT_MSK
);
return
;
}
/* FIXME: if the definition of ht.protection changed, the "translation"
* will be needed for rxon->flags
*/
rxon
->
flags
|=
cpu_to_le32
(
ctx
->
ht
.
protection
<<
RXON_FLG_HT_OPERATING_MODE_POS
);
/* Set up channel bandwidth:
* 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */
/* clear the HT channel mode before set the mode */
rxon
->
flags
&=
~
(
RXON_FLG_CHANNEL_MODE_MSK
|
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK
);
if
(
iwl_is_ht40_tx_allowed
(
priv
,
ctx
,
NULL
))
{
/* pure ht40 */
if
(
ctx
->
ht
.
protection
==
IEEE80211_HT_OP_MODE_PROTECTION_20MHZ
)
{
rxon
->
flags
|=
RXON_FLG_CHANNEL_MODE_PURE_40
;
/* Note: control channel is opposite of extension channel */
switch
(
ctx
->
ht
.
extension_chan_offset
)
{
case
IEEE80211_HT_PARAM_CHA_SEC_ABOVE
:
rxon
->
flags
&=
~
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK
;
break
;
case
IEEE80211_HT_PARAM_CHA_SEC_BELOW
:
rxon
->
flags
|=
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK
;
break
;
}
}
else
{
/* Note: control channel is opposite of extension channel */
switch
(
ctx
->
ht
.
extension_chan_offset
)
{
case
IEEE80211_HT_PARAM_CHA_SEC_ABOVE
:
rxon
->
flags
&=
~
(
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK
);
rxon
->
flags
|=
RXON_FLG_CHANNEL_MODE_MIXED
;
break
;
case
IEEE80211_HT_PARAM_CHA_SEC_BELOW
:
rxon
->
flags
|=
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK
;
rxon
->
flags
|=
RXON_FLG_CHANNEL_MODE_MIXED
;
break
;
case
IEEE80211_HT_PARAM_CHA_SEC_NONE
:
default:
/* channel location only valid if in Mixed mode */
IWL_ERR
(
priv
,
"invalid extension channel offset
\n
"
);
break
;
}
}
}
else
{
rxon
->
flags
|=
RXON_FLG_CHANNEL_MODE_LEGACY
;
}
iwlagn_set_rxon_chain
(
priv
,
ctx
);
IWL_DEBUG_ASSOC
(
priv
,
"rxon flags 0x%X operation mode :0x%X "
"extension channel offset 0x%x
\n
"
,
le32_to_cpu
(
rxon
->
flags
),
ctx
->
ht
.
protection
,
ctx
->
ht
.
extension_chan_offset
);
}
void
iwl_set_rxon_ht
(
struct
iwl_priv
*
priv
,
struct
iwl_ht_config
*
ht_conf
)
{
struct
iwl_rxon_context
*
ctx
;
for_each_context
(
priv
,
ctx
)
_iwl_set_rxon_ht
(
priv
,
ht_conf
,
ctx
);
}
/**
* iwl_set_rxon_channel - Set the band and channel values in staging RXON
* @ch: requested channel as a pointer to struct ieee80211_channel
* NOTE: Does not commit to the hardware; it sets appropriate bit fields
* in the staging RXON flag structure based on the ch->band
*/
void
iwl_set_rxon_channel
(
struct
iwl_priv
*
priv
,
struct
ieee80211_channel
*
ch
,
struct
iwl_rxon_context
*
ctx
)
{
enum
ieee80211_band
band
=
ch
->
band
;
u16
channel
=
ch
->
hw_value
;
if
((
le16_to_cpu
(
ctx
->
staging
.
channel
)
==
channel
)
&&
(
priv
->
band
==
band
))
return
;
ctx
->
staging
.
channel
=
cpu_to_le16
(
channel
);
if
(
band
==
IEEE80211_BAND_5GHZ
)
ctx
->
staging
.
flags
&=
~
RXON_FLG_BAND_24G_MSK
;
else
ctx
->
staging
.
flags
|=
RXON_FLG_BAND_24G_MSK
;
priv
->
band
=
band
;
IWL_DEBUG_INFO
(
priv
,
"Staging channel set to %d [%d]
\n
"
,
channel
,
band
);
}
void
iwl_set_flags_for_band
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
,
enum
ieee80211_band
band
,
struct
ieee80211_vif
*
vif
)
{
if
(
band
==
IEEE80211_BAND_5GHZ
)
{
ctx
->
staging
.
flags
&=
~
(
RXON_FLG_BAND_24G_MSK
|
RXON_FLG_AUTO_DETECT_MSK
|
RXON_FLG_CCK_MSK
);
ctx
->
staging
.
flags
|=
RXON_FLG_SHORT_SLOT_MSK
;
}
else
{
/* Copied from iwl_post_associate() */
if
(
vif
&&
vif
->
bss_conf
.
use_short_slot
)
ctx
->
staging
.
flags
|=
RXON_FLG_SHORT_SLOT_MSK
;
else
ctx
->
staging
.
flags
&=
~
RXON_FLG_SHORT_SLOT_MSK
;
ctx
->
staging
.
flags
|=
RXON_FLG_BAND_24G_MSK
;
ctx
->
staging
.
flags
|=
RXON_FLG_AUTO_DETECT_MSK
;
ctx
->
staging
.
flags
&=
~
RXON_FLG_CCK_MSK
;
}
}
/*
* initialize rxon structure with default values from eeprom
*/
void
iwl_connection_init_rx_config
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
)
{
const
struct
iwl_channel_info
*
ch_info
;
memset
(
&
ctx
->
staging
,
0
,
sizeof
(
ctx
->
staging
));
if
(
!
ctx
->
vif
)
{
ctx
->
staging
.
dev_type
=
ctx
->
unused_devtype
;
}
else
switch
(
ctx
->
vif
->
type
)
{
case
NL80211_IFTYPE_AP
:
ctx
->
staging
.
dev_type
=
ctx
->
ap_devtype
;
break
;
case
NL80211_IFTYPE_STATION
:
ctx
->
staging
.
dev_type
=
ctx
->
station_devtype
;
ctx
->
staging
.
filter_flags
=
RXON_FILTER_ACCEPT_GRP_MSK
;
break
;
case
NL80211_IFTYPE_ADHOC
:
ctx
->
staging
.
dev_type
=
ctx
->
ibss_devtype
;
ctx
->
staging
.
flags
=
RXON_FLG_SHORT_PREAMBLE_MSK
;
ctx
->
staging
.
filter_flags
=
RXON_FILTER_BCON_AWARE_MSK
|
RXON_FILTER_ACCEPT_GRP_MSK
;
break
;
default:
IWL_ERR
(
priv
,
"Unsupported interface type %d
\n
"
,
ctx
->
vif
->
type
);
break
;
}
#if 0
/* TODO: Figure out when short_preamble would be set and cache from
* that */
if (!hw_to_local(priv->hw)->short_preamble)
ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
else
ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
#endif
ch_info
=
iwl_get_channel_info
(
priv
,
priv
->
band
,
le16_to_cpu
(
ctx
->
active
.
channel
));
if
(
!
ch_info
)
ch_info
=
&
priv
->
channel_info
[
0
];
ctx
->
staging
.
channel
=
cpu_to_le16
(
ch_info
->
channel
);
priv
->
band
=
ch_info
->
band
;
iwl_set_flags_for_band
(
priv
,
ctx
,
priv
->
band
,
ctx
->
vif
);
ctx
->
staging
.
ofdm_basic_rates
=
(
IWL_OFDM_RATES_MASK
>>
IWL_FIRST_OFDM_RATE
)
&
0xFF
;
ctx
->
staging
.
cck_basic_rates
=
(
IWL_CCK_RATES_MASK
>>
IWL_FIRST_CCK_RATE
)
&
0xF
;
/* clear both MIX and PURE40 mode flag */
ctx
->
staging
.
flags
&=
~
(
RXON_FLG_CHANNEL_MODE_MIXED
|
RXON_FLG_CHANNEL_MODE_PURE_40
);
if
(
ctx
->
vif
)
memcpy
(
ctx
->
staging
.
node_addr
,
ctx
->
vif
->
addr
,
ETH_ALEN
);
ctx
->
staging
.
ofdm_ht_single_stream_basic_rates
=
0xff
;
ctx
->
staging
.
ofdm_ht_dual_stream_basic_rates
=
0xff
;
ctx
->
staging
.
ofdm_ht_triple_stream_basic_rates
=
0xff
;
}
void
iwl_set_rate
(
struct
iwl_priv
*
priv
)
{
const
struct
ieee80211_supported_band
*
hw
=
NULL
;
struct
ieee80211_rate
*
rate
;
struct
iwl_rxon_context
*
ctx
;
int
i
;
hw
=
iwl_get_hw_mode
(
priv
,
priv
->
band
);
if
(
!
hw
)
{
IWL_ERR
(
priv
,
"Failed to set rate: unable to get hw mode
\n
"
);
return
;
}
priv
->
active_rate
=
0
;
for
(
i
=
0
;
i
<
hw
->
n_bitrates
;
i
++
)
{
rate
=
&
(
hw
->
bitrates
[
i
]);
if
(
rate
->
hw_value
<
IWL_RATE_COUNT_LEGACY
)
priv
->
active_rate
|=
(
1
<<
rate
->
hw_value
);
}
IWL_DEBUG_RATE
(
priv
,
"Set active_rate = %0x
\n
"
,
priv
->
active_rate
);
for_each_context
(
priv
,
ctx
)
{
ctx
->
staging
.
cck_basic_rates
=
(
IWL_CCK_BASIC_RATES_MASK
>>
IWL_FIRST_CCK_RATE
)
&
0xF
;
ctx
->
staging
.
ofdm_basic_rates
=
(
IWL_OFDM_BASIC_RATES_MASK
>>
IWL_FIRST_OFDM_RATE
)
&
0xFF
;
}
}
void
iwl_chswitch_done
(
struct
iwl_priv
*
priv
,
bool
is_success
)
{
/*
* MULTI-FIXME
* See iwlagn_mac_channel_switch.
*/
struct
iwl_rxon_context
*
ctx
=
&
priv
->
contexts
[
IWL_RXON_CTX_BSS
];
if
(
test_bit
(
STATUS_EXIT_PENDING
,
&
priv
->
status
))
return
;
if
(
test_and_clear_bit
(
STATUS_CHANNEL_SWITCH_PENDING
,
&
priv
->
status
))
ieee80211_chswitch_done
(
ctx
->
vif
,
is_success
);
}
#ifdef CONFIG_IWLWIFI_DEBUG
void
iwl_print_rx_config_cmd
(
struct
iwl_priv
*
priv
,
enum
iwl_rxon_context_id
ctxid
)
{
struct
iwl_rxon_context
*
ctx
=
&
priv
->
contexts
[
ctxid
];
struct
iwl_rxon_cmd
*
rxon
=
&
ctx
->
staging
;
IWL_DEBUG_RADIO
(
priv
,
"RX CONFIG:
\n
"
);
iwl_print_hex_dump
(
priv
,
IWL_DL_RADIO
,
(
u8
*
)
rxon
,
sizeof
(
*
rxon
));
IWL_DEBUG_RADIO
(
priv
,
"u16 channel: 0x%x
\n
"
,
le16_to_cpu
(
rxon
->
channel
));
IWL_DEBUG_RADIO
(
priv
,
"u32 flags: 0x%08X
\n
"
,
le32_to_cpu
(
rxon
->
flags
));
IWL_DEBUG_RADIO
(
priv
,
"u32 filter_flags: 0x%08x
\n
"
,
le32_to_cpu
(
rxon
->
filter_flags
));
IWL_DEBUG_RADIO
(
priv
,
"u8 dev_type: 0x%x
\n
"
,
rxon
->
dev_type
);
IWL_DEBUG_RADIO
(
priv
,
"u8 ofdm_basic_rates: 0x%02x
\n
"
,
rxon
->
ofdm_basic_rates
);
IWL_DEBUG_RADIO
(
priv
,
"u8 cck_basic_rates: 0x%02x
\n
"
,
rxon
->
cck_basic_rates
);
IWL_DEBUG_RADIO
(
priv
,
"u8[6] node_addr: %pM
\n
"
,
rxon
->
node_addr
);
IWL_DEBUG_RADIO
(
priv
,
"u8[6] bssid_addr: %pM
\n
"
,
rxon
->
bssid_addr
);
IWL_DEBUG_RADIO
(
priv
,
"u16 assoc_id: 0x%x
\n
"
,
le16_to_cpu
(
rxon
->
assoc_id
));
}
#endif
void
iwlagn_fw_error
(
struct
iwl_priv
*
priv
,
bool
ondemand
)
{
unsigned
int
reload_msec
;
unsigned
long
reload_jiffies
;
#ifdef CONFIG_IWLWIFI_DEBUG
if
(
iwl_have_debug_level
(
IWL_DL_FW_ERRORS
))
iwl_print_rx_config_cmd
(
priv
,
IWL_RXON_CTX_BSS
);
#endif
/* uCode is no longer loaded. */
priv
->
ucode_loaded
=
false
;
/* Set the FW error flag -- cleared on iwl_down */
set_bit
(
STATUS_FW_ERROR
,
&
priv
->
status
);
/* Cancel currently queued command. */
clear_bit
(
STATUS_HCMD_ACTIVE
,
&
priv
->
shrd
->
status
);
iwl_abort_notification_waits
(
&
priv
->
notif_wait
);
/* Keep the restart process from trying to send host
* commands by clearing the ready bit */
clear_bit
(
STATUS_READY
,
&
priv
->
status
);
wake_up
(
&
trans
(
priv
)
->
wait_command_queue
);
if
(
!
ondemand
)
{
/*
* If firmware keep reloading, then it indicate something
* serious wrong and firmware having problem to recover
* from it. Instead of keep trying which will fill the syslog
* and hang the system, let's just stop it
*/
reload_jiffies
=
jiffies
;
reload_msec
=
jiffies_to_msecs
((
long
)
reload_jiffies
-
(
long
)
priv
->
reload_jiffies
);
priv
->
reload_jiffies
=
reload_jiffies
;
if
(
reload_msec
<=
IWL_MIN_RELOAD_DURATION
)
{
priv
->
reload_count
++
;
if
(
priv
->
reload_count
>=
IWL_MAX_CONTINUE_RELOAD_CNT
)
{
IWL_ERR
(
priv
,
"BUG_ON, Stop restarting
\n
"
);
return
;
}
}
else
priv
->
reload_count
=
0
;
}
if
(
!
test_bit
(
STATUS_EXIT_PENDING
,
&
priv
->
status
))
{
if
(
iwlagn_mod_params
.
restart_fw
)
{
IWL_DEBUG_FW_ERRORS
(
priv
,
"Restarting adapter due to uCode error.
\n
"
);
queue_work
(
priv
->
workqueue
,
&
priv
->
restart
);
}
else
IWL_DEBUG_FW_ERRORS
(
priv
,
"Detected FW error, but not restarting
\n
"
);
}
}
int
iwl_set_tx_power
(
struct
iwl_priv
*
priv
,
s8
tx_power
,
bool
force
)
{
int
ret
;
s8
prev_tx_power
;
bool
defer
;
struct
iwl_rxon_context
*
ctx
=
&
priv
->
contexts
[
IWL_RXON_CTX_BSS
];
lockdep_assert_held
(
&
priv
->
mutex
);
if
(
priv
->
tx_power_user_lmt
==
tx_power
&&
!
force
)
return
0
;
if
(
tx_power
<
IWLAGN_TX_POWER_TARGET_POWER_MIN
)
{
IWL_WARN
(
priv
,
"Requested user TXPOWER %d below lower limit %d.
\n
"
,
tx_power
,
IWLAGN_TX_POWER_TARGET_POWER_MIN
);
return
-
EINVAL
;
}
if
(
tx_power
>
priv
->
tx_power_device_lmt
)
{
IWL_WARN
(
priv
,
"Requested user TXPOWER %d above upper limit %d.
\n
"
,
tx_power
,
priv
->
tx_power_device_lmt
);
return
-
EINVAL
;
}
if
(
!
iwl_is_ready_rf
(
priv
))
return
-
EIO
;
/* scan complete and commit_rxon use tx_power_next value,
* it always need to be updated for newest request */
priv
->
tx_power_next
=
tx_power
;
/* do not set tx power when scanning or channel changing */
defer
=
test_bit
(
STATUS_SCANNING
,
&
priv
->
status
)
||
memcmp
(
&
ctx
->
active
,
&
ctx
->
staging
,
sizeof
(
ctx
->
staging
));
if
(
defer
&&
!
force
)
{
IWL_DEBUG_INFO
(
priv
,
"Deferring tx power set
\n
"
);
return
0
;
}
prev_tx_power
=
priv
->
tx_power_user_lmt
;
priv
->
tx_power_user_lmt
=
tx_power
;
ret
=
iwlagn_send_tx_power
(
priv
);
/* if fail to set tx_power, restore the orig. tx power */
if
(
ret
)
{
priv
->
tx_power_user_lmt
=
prev_tx_power
;
priv
->
tx_power_next
=
prev_tx_power
;
}
return
ret
;
}
void
iwl_send_bt_config
(
struct
iwl_priv
*
priv
)
{
struct
iwl_bt_cmd
bt_cmd
=
{
.
lead_time
=
BT_LEAD_TIME_DEF
,
.
max_kill
=
BT_MAX_KILL_DEF
,
.
kill_ack_mask
=
0
,
.
kill_cts_mask
=
0
,
};
if
(
!
iwlagn_mod_params
.
bt_coex_active
)
bt_cmd
.
flags
=
BT_COEX_DISABLE
;
else
bt_cmd
.
flags
=
BT_COEX_ENABLE
;
priv
->
bt_enable_flag
=
bt_cmd
.
flags
;
IWL_DEBUG_INFO
(
priv
,
"BT coex %s
\n
"
,
(
bt_cmd
.
flags
==
BT_COEX_DISABLE
)
?
"disable"
:
"active"
);
if
(
iwl_dvm_send_cmd_pdu
(
priv
,
REPLY_BT_CONFIG
,
CMD_SYNC
,
sizeof
(
struct
iwl_bt_cmd
),
&
bt_cmd
))
IWL_ERR
(
priv
,
"failed to send BT Coex Config
\n
"
);
}
int
iwl_send_statistics_request
(
struct
iwl_priv
*
priv
,
u8
flags
,
bool
clear
)
{
struct
iwl_statistics_cmd
statistics_cmd
=
{
.
configuration_flags
=
clear
?
IWL_STATS_CONF_CLEAR_STATS
:
0
,
};
if
(
flags
&
CMD_ASYNC
)
return
iwl_dvm_send_cmd_pdu
(
priv
,
REPLY_STATISTICS_CMD
,
CMD_ASYNC
,
sizeof
(
struct
iwl_statistics_cmd
),
&
statistics_cmd
);
else
return
iwl_dvm_send_cmd_pdu
(
priv
,
REPLY_STATISTICS_CMD
,
CMD_SYNC
,
sizeof
(
struct
iwl_statistics_cmd
),
&
statistics_cmd
);
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
...
...
@@ -746,45 +275,6 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
}
#endif
int
iwl_force_rf_reset
(
struct
iwl_priv
*
priv
,
bool
external
)
{
struct
iwl_rf_reset
*
rf_reset
;
if
(
test_bit
(
STATUS_EXIT_PENDING
,
&
priv
->
status
))
return
-
EAGAIN
;
if
(
!
iwl_is_any_associated
(
priv
))
{
IWL_DEBUG_SCAN
(
priv
,
"force reset rejected: not associated
\n
"
);
return
-
ENOLINK
;
}
rf_reset
=
&
priv
->
rf_reset
;
rf_reset
->
reset_request_count
++
;
if
(
!
external
&&
rf_reset
->
last_reset_jiffies
&&
time_after
(
rf_reset
->
last_reset_jiffies
+
IWL_DELAY_NEXT_FORCE_RF_RESET
,
jiffies
))
{
IWL_DEBUG_INFO
(
priv
,
"RF reset rejected
\n
"
);
rf_reset
->
reset_reject_count
++
;
return
-
EAGAIN
;
}
rf_reset
->
reset_success_count
++
;
rf_reset
->
last_reset_jiffies
=
jiffies
;
/*
* There is no easy and better way to force reset the radio,
* the only known method is switching channel which will force to
* reset and tune the radio.
* Use internal short scan (single channel) operation to should
* achieve this objective.
* Driver should reset the radio when number of consecutive missed
* beacon, or any other uCode error condition detected.
*/
IWL_DEBUG_INFO
(
priv
,
"perform radio reset.
\n
"
);
iwl_internal_short_hw_scan
(
priv
);
return
0
;
}
int
iwl_cmd_echo_test
(
struct
iwl_priv
*
priv
)
{
int
ret
;
...
...
@@ -801,97 +291,3 @@ int iwl_cmd_echo_test(struct iwl_priv *priv)
IWL_DEBUG_INFO
(
priv
,
"echo testing pass
\n
"
);
return
ret
;
}
/**
* iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time
* @priv -- pointer to iwl_priv data structure
* @tsf_bits -- number of bits need to shift for masking)
*/
static
inline
u32
iwl_beacon_time_mask_low
(
struct
iwl_priv
*
priv
,
u16
tsf_bits
)
{
return
(
1
<<
tsf_bits
)
-
1
;
}
/**
* iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time
* @priv -- pointer to iwl_priv data structure
* @tsf_bits -- number of bits need to shift for masking)
*/
static
inline
u32
iwl_beacon_time_mask_high
(
struct
iwl_priv
*
priv
,
u16
tsf_bits
)
{
return
((
1
<<
(
32
-
tsf_bits
))
-
1
)
<<
tsf_bits
;
}
/*
* extended beacon time format
* time in usec will be changed into a 32-bit value in extended:internal format
* the extended part is the beacon counts
* the internal part is the time in usec within one beacon interval
*/
u32
iwl_usecs_to_beacons
(
struct
iwl_priv
*
priv
,
u32
usec
,
u32
beacon_interval
)
{
u32
quot
;
u32
rem
;
u32
interval
=
beacon_interval
*
TIME_UNIT
;
if
(
!
interval
||
!
usec
)
return
0
;
quot
=
(
usec
/
interval
)
&
(
iwl_beacon_time_mask_high
(
priv
,
IWLAGN_EXT_BEACON_TIME_POS
)
>>
IWLAGN_EXT_BEACON_TIME_POS
);
rem
=
(
usec
%
interval
)
&
iwl_beacon_time_mask_low
(
priv
,
IWLAGN_EXT_BEACON_TIME_POS
);
return
(
quot
<<
IWLAGN_EXT_BEACON_TIME_POS
)
+
rem
;
}
/* base is usually what we get from ucode with each received frame,
* the same as HW timer counter counting down
*/
__le32
iwl_add_beacon_time
(
struct
iwl_priv
*
priv
,
u32
base
,
u32
addon
,
u32
beacon_interval
)
{
u32
base_low
=
base
&
iwl_beacon_time_mask_low
(
priv
,
IWLAGN_EXT_BEACON_TIME_POS
);
u32
addon_low
=
addon
&
iwl_beacon_time_mask_low
(
priv
,
IWLAGN_EXT_BEACON_TIME_POS
);
u32
interval
=
beacon_interval
*
TIME_UNIT
;
u32
res
=
(
base
&
iwl_beacon_time_mask_high
(
priv
,
IWLAGN_EXT_BEACON_TIME_POS
))
+
(
addon
&
iwl_beacon_time_mask_high
(
priv
,
IWLAGN_EXT_BEACON_TIME_POS
));
if
(
base_low
>
addon_low
)
res
+=
base_low
-
addon_low
;
else
if
(
base_low
<
addon_low
)
{
res
+=
interval
+
base_low
-
addon_low
;
res
+=
(
1
<<
IWLAGN_EXT_BEACON_TIME_POS
);
}
else
res
+=
(
1
<<
IWLAGN_EXT_BEACON_TIME_POS
);
return
cpu_to_le32
(
res
);
}
void
iwl_set_hw_rfkill_state
(
struct
iwl_op_mode
*
op_mode
,
bool
state
)
{
struct
iwl_priv
*
priv
=
IWL_OP_MODE_GET_DVM
(
op_mode
);
if
(
state
)
set_bit
(
STATUS_RF_KILL_HW
,
&
priv
->
status
);
else
clear_bit
(
STATUS_RF_KILL_HW
,
&
priv
->
status
);
wiphy_rfkill_set_hw_state
(
priv
->
hw
->
wiphy
,
state
);
}
void
iwl_free_skb
(
struct
iwl_op_mode
*
op_mode
,
struct
sk_buff
*
skb
)
{
struct
ieee80211_tx_info
*
info
;
info
=
IEEE80211_SKB_CB
(
skb
);
kmem_cache_free
(
iwl_tx_cmd_pool
,
(
info
->
driver_data
[
1
]));
dev_kfree_skb_any
(
skb
);
}
drivers/net/wireless/iwlwifi/iwl-core.h
浏览文件 @
0d920987
...
...
@@ -78,19 +78,6 @@ struct iwl_cmd;
* L i b *
***************************/
void
iwl_set_rxon_channel
(
struct
iwl_priv
*
priv
,
struct
ieee80211_channel
*
ch
,
struct
iwl_rxon_context
*
ctx
);
void
iwl_set_flags_for_band
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
,
enum
ieee80211_band
band
,
struct
ieee80211_vif
*
vif
);
void
iwl_set_rxon_ht
(
struct
iwl_priv
*
priv
,
struct
iwl_ht_config
*
ht_conf
);
bool
iwl_is_ht40_tx_allowed
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
,
struct
ieee80211_sta_ht_cap
*
ht_cap
);
void
iwl_connection_init_rx_config
(
struct
iwl_priv
*
priv
,
struct
iwl_rxon_context
*
ctx
);
void
iwl_set_rate
(
struct
iwl_priv
*
priv
);
int
iwl_cmd_echo_test
(
struct
iwl_priv
*
priv
);
#ifdef CONFIG_IWLWIFI_DEBUGFS
int
iwl_alloc_traffic_mem
(
struct
iwl_priv
*
priv
);
...
...
@@ -131,43 +118,9 @@ static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx,
}
#endif
/*****************************************************
* RX
******************************************************/
void
iwl_chswitch_done
(
struct
iwl_priv
*
priv
,
bool
is_success
);
/*****************************************************
* TX power
****************************************************/
int
iwl_set_tx_power
(
struct
iwl_priv
*
priv
,
s8
tx_power
,
bool
force
);
/*******************************************************************************
* Scanning
******************************************************************************/
void
iwl_init_scan_params
(
struct
iwl_priv
*
priv
);
int
iwl_scan_cancel
(
struct
iwl_priv
*
priv
);
void
iwl_scan_cancel_timeout
(
struct
iwl_priv
*
priv
,
unsigned
long
ms
);
void
iwl_force_scan_end
(
struct
iwl_priv
*
priv
);
void
iwl_internal_short_hw_scan
(
struct
iwl_priv
*
priv
);
void
iwl_setup_rx_scan_handlers
(
struct
iwl_priv
*
priv
);
void
iwl_setup_scan_deferred_work
(
struct
iwl_priv
*
priv
);
void
iwl_cancel_scan_deferred_work
(
struct
iwl_priv
*
priv
);
int
__must_check
iwl_scan_initiate
(
struct
iwl_priv
*
priv
,
struct
ieee80211_vif
*
vif
,
enum
iwl_scan_type
scan_type
,
enum
ieee80211_band
band
);
/* For faster active scanning, scan will move to the next channel if fewer than
* PLCP_QUIET_THRESH packets are heard on this channel within
* ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell
* time if it's a quiet channel (nothing responded to our probe, and there's
* no other traffic).
* Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */
#define IWL_ACTIVE_QUIET_TIME cpu_to_le16(10)
/* msec */
#define IWL_PLCP_QUIET_THRESH cpu_to_le16(1)
/* packets */
#define IWL_SCAN_CHECK_WATCHDOG (HZ * 7)
/* traffic log definitions */
#define IWL_TRAFFIC_ENTRIES (256)
#define IWL_TRAFFIC_ENTRY_SIZE (64)
...
...
@@ -175,27 +128,6 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
/*****************************************************
* S e n d i n g H o s t C o m m a n d s *
*****************************************************/
u32
iwl_usecs_to_beacons
(
struct
iwl_priv
*
priv
,
u32
usec
,
u32
beacon_interval
);
__le32
iwl_add_beacon_time
(
struct
iwl_priv
*
priv
,
u32
base
,
u32
addon
,
u32
beacon_interval
);
extern
void
iwl_send_bt_config
(
struct
iwl_priv
*
priv
);
extern
int
iwl_send_statistics_request
(
struct
iwl_priv
*
priv
,
u8
flags
,
bool
clear
);
static
inline
const
struct
ieee80211_supported_band
*
iwl_get_hw_mode
(
struct
iwl_priv
*
priv
,
enum
ieee80211_band
band
)
{
return
priv
->
hw
->
wiphy
->
bands
[
band
];
}
static
inline
bool
iwl_advanced_bt_coexist
(
struct
iwl_priv
*
priv
)
{
return
cfg
(
priv
)
->
bt_params
&&
cfg
(
priv
)
->
bt_params
->
advanced_bt_coexist
;
}
extern
bool
bt_siso_mode
;
#endif
/* __iwl_core_h__ */
drivers/net/wireless/iwlwifi/iwl-dev.h
浏览文件 @
0d920987
...
...
@@ -861,8 +861,6 @@ struct iwl_priv {
__le16
switch_channel
;
u16
active_rate
;
u8
start_calib
;
struct
iwl_sensitivity_data
sensitivity_data
;
struct
iwl_chain_noise_data
chain_noise_data
;
...
...
drivers/net/wireless/iwlwifi/iwl-mac80211.c
浏览文件 @
0d920987
...
...
@@ -914,6 +914,21 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211
(
priv
,
"leave
\n
"
);
}
void
iwl_chswitch_done
(
struct
iwl_priv
*
priv
,
bool
is_success
)
{
/*
* MULTI-FIXME
* See iwlagn_mac_channel_switch.
*/
struct
iwl_rxon_context
*
ctx
=
&
priv
->
contexts
[
IWL_RXON_CTX_BSS
];
if
(
test_bit
(
STATUS_EXIT_PENDING
,
&
priv
->
status
))
return
;
if
(
test_and_clear_bit
(
STATUS_CHANNEL_SWITCH_PENDING
,
&
priv
->
status
))
ieee80211_chswitch_done
(
ctx
->
vif
,
is_success
);
}
static
void
iwlagn_configure_filter
(
struct
ieee80211_hw
*
hw
,
unsigned
int
changed_flags
,
unsigned
int
*
total_flags
,
...
...
drivers/net/wireless/iwlwifi/iwl-shared.h
浏览文件 @
0d920987
...
...
@@ -190,7 +190,6 @@ enum iwl_rxon_context_id {
NUM_IWL_RXON_CTX
};
int
iwlagn_hw_valid_rtc_data_addr
(
u32
addr
);
const
char
*
get_cmd_string
(
u8
cmd
);
#define IWL_CMD(x) case x: return #x
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录