Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
24de851b
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
160
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看板
提交
24de851b
编写于
8月 16, 2013
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-john' of
git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
上级
d0746663
89716344
变更
20
展开全部
隐藏空白更改
内联
并排
Showing
20 changed file
with
809 addition
and
713 deletion
+809
-713
drivers/net/wireless/iwlwifi/Kconfig
drivers/net/wireless/iwlwifi/Kconfig
+7
-6
drivers/net/wireless/iwlwifi/iwl-debug.h
drivers/net/wireless/iwlwifi/iwl-debug.h
+2
-0
drivers/net/wireless/iwlwifi/iwl-drv.c
drivers/net/wireless/iwlwifi/iwl-drv.c
+6
-4
drivers/net/wireless/iwlwifi/iwl-fw.h
drivers/net/wireless/iwlwifi/iwl-fw.h
+5
-0
drivers/net/wireless/iwlwifi/mvm/constants.h
drivers/net/wireless/iwlwifi/mvm/constants.h
+9
-0
drivers/net/wireless/iwlwifi/mvm/d3.c
drivers/net/wireless/iwlwifi/mvm/d3.c
+88
-63
drivers/net/wireless/iwlwifi/mvm/debugfs.c
drivers/net/wireless/iwlwifi/mvm/debugfs.c
+11
-6
drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+14
-10
drivers/net/wireless/iwlwifi/mvm/fw-api.h
drivers/net/wireless/iwlwifi/mvm/fw-api.h
+177
-51
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
+24
-5
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/mvm.h
+25
-2
drivers/net/wireless/iwlwifi/mvm/power.c
drivers/net/wireless/iwlwifi/mvm/power.c
+179
-20
drivers/net/wireless/iwlwifi/mvm/rs.c
drivers/net/wireless/iwlwifi/mvm/rs.c
+62
-412
drivers/net/wireless/iwlwifi/mvm/rs.h
drivers/net/wireless/iwlwifi/mvm/rs.h
+6
-58
drivers/net/wireless/iwlwifi/mvm/rx.c
drivers/net/wireless/iwlwifi/mvm/rx.c
+60
-1
drivers/net/wireless/iwlwifi/mvm/time-event.c
drivers/net/wireless/iwlwifi/mvm/time-event.c
+73
-23
drivers/net/wireless/iwlwifi/pcie/drv.c
drivers/net/wireless/iwlwifi/pcie/drv.c
+3
-3
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/rx.c
+18
-25
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/iwlwifi/pcie/trans.c
+15
-11
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/iwlwifi/pcie/tx.c
+25
-13
未找到文件。
drivers/net/wireless/iwlwifi/Kconfig
浏览文件 @
24de851b
...
...
@@ -22,6 +22,8 @@ config IWLWIFI
Intel Wireless WiFi Link 6150BGN 2 Adapter
Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN)
Intel 2000 Series Wi-Fi Adapters
Intel 7260 Wi-Fi Adapter
Intel 3160 Wi-Fi Adapter
This driver uses the kernel's mac80211 subsystem.
...
...
@@ -46,17 +48,16 @@ config IWLDVM
depends on IWLWIFI
default IWLWIFI
help
This is the driver supporting the DVM firmware which is
currently the only firmware available for existing devices.
This is the driver that supports the DVM firmware which is
used by most existing devices (with the exception of 7260
and 3160).
config IWLMVM
tristate "Intel Wireless WiFi MVM Firmware support"
depends on IWLWIFI
help
This is the driver supporting the MVM firmware which is
currently only available for 7000 series devices.
Say yes if you have such a device.
This is the driver that supports the MVM firmware which is
currently only available for 7260 and 3160 devices.
# don't call it _MODULE -- will confuse Kconfig/fixdep/...
config IWLWIFI_OPMODE_MODULAR
...
...
drivers/net/wireless/iwlwifi/iwl-debug.h
浏览文件 @
24de851b
...
...
@@ -145,6 +145,7 @@ do { \
#define IWL_DL_RX 0x01000000
#define IWL_DL_ISR 0x02000000
#define IWL_DL_HT 0x04000000
#define IWL_DL_EXTERNAL 0x08000000
/* 0xF0000000 - 0x10000000 */
#define IWL_DL_11H 0x10000000
#define IWL_DL_STATS 0x20000000
...
...
@@ -153,6 +154,7 @@ do { \
#define IWL_DEBUG_INFO(p, f, a...) IWL_DEBUG(p, IWL_DL_INFO, f, ## a)
#define IWL_DEBUG_MAC80211(p, f, a...) IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a)
#define IWL_DEBUG_EXTERNAL(p, f, a...) IWL_DEBUG(p, IWL_DL_EXTERNAL, f, ## a)
#define IWL_DEBUG_TEMP(p, f, a...) IWL_DEBUG(p, IWL_DL_TEMP, f, ## a)
#define IWL_DEBUG_SCAN(p, f, a...) IWL_DEBUG(p, IWL_DL_SCAN, f, ## a)
#define IWL_DEBUG_RX(p, f, a...) IWL_DEBUG(p, IWL_DL_RX, f, ## a)
...
...
drivers/net/wireless/iwlwifi/iwl-drv.c
浏览文件 @
24de851b
...
...
@@ -843,7 +843,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
int
i
;
bool
load_module
=
false
;
fw
->
ucode_capa
.
max_probe_length
=
200
;
fw
->
ucode_capa
.
max_probe_length
=
IWL_DEFAULT_MAX_PROBE_LENGTH
;
fw
->
ucode_capa
.
standard_phy_calibration_size
=
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE
;
...
...
@@ -1032,8 +1032,10 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
int
ret
;
drv
=
kzalloc
(
sizeof
(
*
drv
),
GFP_KERNEL
);
if
(
!
drv
)
return
NULL
;
if
(
!
drv
)
{
ret
=
-
ENOMEM
;
goto
err
;
}
drv
->
trans
=
trans
;
drv
->
dev
=
trans
->
dev
;
...
...
@@ -1078,7 +1080,7 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
err_free_drv:
#endif
kfree
(
drv
);
err:
return
ERR_PTR
(
ret
);
}
...
...
drivers/net/wireless/iwlwifi/iwl-fw.h
浏览文件 @
24de851b
...
...
@@ -76,6 +76,7 @@
* @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS
* @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD
* @IWL_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api
* @IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2: using the new time event API.
* @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six
* (rather than two) IPv6 addresses
* @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API
...
...
@@ -88,6 +89,7 @@ enum iwl_ucode_tlv_flag {
IWL_UCODE_TLV_FLAGS_DW_BC_TABLE
=
BIT
(
4
),
IWL_UCODE_TLV_FLAGS_UAPSD
=
BIT
(
6
),
IWL_UCODE_TLV_FLAGS_RX_ENERGY_API
=
BIT
(
8
),
IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2
=
BIT
(
9
),
IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS
=
BIT
(
10
),
IWL_UCODE_TLV_FLAGS_BF_UPDATED
=
BIT
(
11
),
};
...
...
@@ -97,6 +99,9 @@ enum iwl_ucode_tlv_flag {
#define IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE 19
#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE 253
/* The default max probe length if not specified by the firmware file */
#define IWL_DEFAULT_MAX_PROBE_LENGTH 200
/**
* enum iwl_ucode_type
*
...
...
drivers/net/wireless/iwlwifi/mvm/constants.h
浏览文件 @
24de851b
...
...
@@ -67,5 +67,14 @@
#define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
#define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC)
#define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC)
#define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
#define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
#define IWL_MVM_PS_HEAVY_TX_THLD_PACKETS 20
#define IWL_MVM_PS_HEAVY_RX_THLD_PACKETS 20
#define IWL_MVM_PS_HEAVY_TX_THLD_PERCENT 50
#define IWL_MVM_PS_HEAVY_RX_THLD_PERCENT 50
#define IWL_MVM_PS_SNOOZE_INTERVAL 25
#define IWL_MVM_PS_SNOOZE_WINDOW 50
#define IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW 25
#endif
/* __MVM_CONSTANTS_H */
drivers/net/wireless/iwlwifi/mvm/d3.c
浏览文件 @
24de851b
...
...
@@ -1109,73 +1109,16 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
return
__iwl_mvm_suspend
(
hw
,
wowlan
,
false
);
}
static
void
iwl_mvm_query_wakeup_reasons
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
)
static
void
iwl_mvm_report_wakeup_reasons
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
struct
iwl_wowlan_status
*
status
)
{
u32
base
=
mvm
->
error_event_table
;
struct
error_table_start
{
/* cf. struct iwl_error_event_table */
u32
valid
;
u32
error_id
;
}
err_info
;
struct
sk_buff
*
pkt
=
NULL
;
struct
cfg80211_wowlan_wakeup
wakeup
=
{
.
pattern_idx
=
-
1
,
};
struct
cfg80211_wowlan_wakeup
*
wakeup_report
=
&
wakeup
;
struct
iwl_host_cmd
cmd
=
{
.
id
=
WOWLAN_GET_STATUSES
,
.
flags
=
CMD_SYNC
|
CMD_WANT_SKB
,
};
struct
iwl_wowlan_status
*
status
;
u32
reasons
;
int
ret
,
len
;
struct
sk_buff
*
pkt
=
NULL
;
iwl_trans_read_mem_bytes
(
mvm
->
trans
,
base
,
&
err_info
,
sizeof
(
err_info
));
if
(
err_info
.
valid
)
{
IWL_INFO
(
mvm
,
"error table is valid (%d)
\n
"
,
err_info
.
valid
);
if
(
err_info
.
error_id
==
RF_KILL_INDICATOR_FOR_WOWLAN
)
{
wakeup
.
rfkill_release
=
true
;
ieee80211_report_wowlan_wakeup
(
vif
,
&
wakeup
,
GFP_KERNEL
);
}
return
;
}
/* only for tracing for now */
ret
=
iwl_mvm_send_cmd_pdu
(
mvm
,
OFFLOADS_QUERY_CMD
,
CMD_SYNC
,
0
,
NULL
);
if
(
ret
)
IWL_ERR
(
mvm
,
"failed to query offload statistics (%d)
\n
"
,
ret
);
ret
=
iwl_mvm_send_cmd
(
mvm
,
&
cmd
);
if
(
ret
)
{
IWL_ERR
(
mvm
,
"failed to query status (%d)
\n
"
,
ret
);
return
;
}
/* RF-kill already asserted again... */
if
(
!
cmd
.
resp_pkt
)
return
;
len
=
le32_to_cpu
(
cmd
.
resp_pkt
->
len_n_flags
)
&
FH_RSCSR_FRAME_SIZE_MSK
;
if
(
len
-
sizeof
(
struct
iwl_cmd_header
)
<
sizeof
(
*
status
))
{
IWL_ERR
(
mvm
,
"Invalid WoWLAN status response!
\n
"
);
goto
out
;
}
status
=
(
void
*
)
cmd
.
resp_pkt
->
data
;
if
(
len
-
sizeof
(
struct
iwl_cmd_header
)
!=
sizeof
(
*
status
)
+
ALIGN
(
le32_to_cpu
(
status
->
wake_packet_bufsize
),
4
))
{
IWL_ERR
(
mvm
,
"Invalid WoWLAN status response!
\n
"
);
goto
out
;
}
reasons
=
le32_to_cpu
(
status
->
wakeup_reasons
);
u32
reasons
=
le32_to_cpu
(
status
->
wakeup_reasons
);
if
(
reasons
==
IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS
)
{
wakeup_report
=
NULL
;
...
...
@@ -1238,6 +1181,12 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
pktsize
-=
hdrlen
;
if
(
ieee80211_has_protected
(
hdr
->
frame_control
))
{
/*
* This is unlocked and using gtk_i(c)vlen,
* but since everything is under RTNL still
* that's not really a problem - changing
* it would be difficult.
*/
if
(
is_multicast_ether_addr
(
hdr
->
addr1
))
{
ivlen
=
mvm
->
gtk_ivlen
;
icvlen
+=
mvm
->
gtk_icvlen
;
...
...
@@ -1288,9 +1237,82 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
report:
ieee80211_report_wowlan_wakeup
(
vif
,
wakeup_report
,
GFP_KERNEL
);
kfree_skb
(
pkt
);
}
out:
/* releases the MVM mutex */
static
void
iwl_mvm_query_wakeup_reasons
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
)
{
u32
base
=
mvm
->
error_event_table
;
struct
error_table_start
{
/* cf. struct iwl_error_event_table */
u32
valid
;
u32
error_id
;
}
err_info
;
struct
iwl_host_cmd
cmd
=
{
.
id
=
WOWLAN_GET_STATUSES
,
.
flags
=
CMD_SYNC
|
CMD_WANT_SKB
,
};
struct
iwl_wowlan_status
*
status
;
int
ret
,
len
;
iwl_trans_read_mem_bytes
(
mvm
->
trans
,
base
,
&
err_info
,
sizeof
(
err_info
));
if
(
err_info
.
valid
)
{
IWL_INFO
(
mvm
,
"error table is valid (%d)
\n
"
,
err_info
.
valid
);
if
(
err_info
.
error_id
==
RF_KILL_INDICATOR_FOR_WOWLAN
)
{
struct
cfg80211_wowlan_wakeup
wakeup
=
{
.
rfkill_release
=
true
,
};
ieee80211_report_wowlan_wakeup
(
vif
,
&
wakeup
,
GFP_KERNEL
);
}
goto
out_unlock
;
}
/* only for tracing for now */
ret
=
iwl_mvm_send_cmd_pdu
(
mvm
,
OFFLOADS_QUERY_CMD
,
CMD_SYNC
,
0
,
NULL
);
if
(
ret
)
IWL_ERR
(
mvm
,
"failed to query offload statistics (%d)
\n
"
,
ret
);
ret
=
iwl_mvm_send_cmd
(
mvm
,
&
cmd
);
if
(
ret
)
{
IWL_ERR
(
mvm
,
"failed to query status (%d)
\n
"
,
ret
);
goto
out_unlock
;
}
/* RF-kill already asserted again... */
if
(
!
cmd
.
resp_pkt
)
goto
out_unlock
;
len
=
le32_to_cpu
(
cmd
.
resp_pkt
->
len_n_flags
)
&
FH_RSCSR_FRAME_SIZE_MSK
;
if
(
len
-
sizeof
(
struct
iwl_cmd_header
)
<
sizeof
(
*
status
))
{
IWL_ERR
(
mvm
,
"Invalid WoWLAN status response!
\n
"
);
goto
out_free_resp
;
}
status
=
(
void
*
)
cmd
.
resp_pkt
->
data
;
if
(
len
-
sizeof
(
struct
iwl_cmd_header
)
!=
sizeof
(
*
status
)
+
ALIGN
(
le32_to_cpu
(
status
->
wake_packet_bufsize
),
4
))
{
IWL_ERR
(
mvm
,
"Invalid WoWLAN status response!
\n
"
);
goto
out_free_resp
;
}
/* now we have all the data we need, unlock to avoid mac80211 issues */
mutex_unlock
(
&
mvm
->
mutex
);
iwl_mvm_report_wakeup_reasons
(
mvm
,
vif
,
status
);
iwl_free_resp
(
&
cmd
);
return
;
out_free_resp:
iwl_free_resp
(
&
cmd
);
out_unlock:
mutex_unlock
(
&
mvm
->
mutex
);
}
static
void
iwl_mvm_read_d3_sram
(
struct
iwl_mvm
*
mvm
)
...
...
@@ -1347,10 +1369,13 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
iwl_mvm_read_d3_sram
(
mvm
);
iwl_mvm_query_wakeup_reasons
(
mvm
,
vif
);
/* has unlocked the mutex, so skip that */
goto
out
;
out_unlock:
mutex_unlock
(
&
mvm
->
mutex
);
out:
if
(
!
test
&&
vif
)
ieee80211_resume_disconnect
(
vif
);
...
...
drivers/net/wireless/iwlwifi/mvm/debugfs.c
浏览文件 @
24de851b
...
...
@@ -352,6 +352,10 @@ static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
IWL_DEBUG_POWER
(
mvm
,
"lprx_rssi_threshold=%d
\n
"
,
val
);
dbgfs_pm
->
lprx_rssi_threshold
=
val
;
break
;
case
MVM_DEBUGFS_PM_SNOOZE_ENABLE
:
IWL_DEBUG_POWER
(
mvm
,
"snooze_enable=%d
\n
"
,
val
);
dbgfs_pm
->
snooze_ena
=
val
;
break
;
}
}
...
...
@@ -405,6 +409,10 @@ static ssize_t iwl_dbgfs_pm_params_write(struct file *file,
POWER_LPRX_RSSI_THRESHOLD_MIN
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD
;
}
else
if
(
!
strncmp
(
"snooze_enable="
,
buf
,
14
))
{
if
(
sscanf
(
buf
+
14
,
"%d"
,
&
val
)
!=
1
)
return
-
EINVAL
;
param
=
MVM_DEBUGFS_PM_SNOOZE_ENABLE
;
}
else
{
return
-
EINVAL
;
}
...
...
@@ -424,7 +432,7 @@ static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
struct
ieee80211_vif
*
vif
=
file
->
private_data
;
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
struct
iwl_mvm
*
mvm
=
mvmvif
->
dbgfs_data
;
char
buf
[
256
];
char
buf
[
512
];
int
bufsz
=
sizeof
(
buf
);
int
pos
;
...
...
@@ -895,10 +903,7 @@ static ssize_t iwl_dbgfs_bf_params_write(struct file *file,
if
(
param
==
MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
&&
!
value
)
{
ret
=
iwl_mvm_disable_beacon_filter
(
mvm
,
vif
);
}
else
{
if
(
mvmvif
->
bf_enabled
)
ret
=
iwl_mvm_enable_beacon_filter
(
mvm
,
vif
);
else
ret
=
iwl_mvm_disable_beacon_filter
(
mvm
,
vif
);
ret
=
iwl_mvm_enable_beacon_filter
(
mvm
,
vif
);
}
mutex_unlock
(
&
mvm
->
mutex
);
...
...
@@ -923,7 +928,7 @@ static ssize_t iwl_dbgfs_bf_params_read(struct file *file,
};
iwl_mvm_beacon_filter_debugfs_parameters
(
vif
,
&
cmd
);
if
(
mvmvif
->
bf_enabled
)
if
(
mvmvif
->
bf_
data
.
bf_
enabled
)
cmd
.
bf_enable_beacon_filter
=
cpu_to_le32
(
1
);
else
cmd
.
bf_enable_beacon_filter
=
0
;
...
...
drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
浏览文件 @
24de851b
...
...
@@ -155,8 +155,12 @@ struct iwl_powertable_cmd {
* @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled.
* Default: 80dbm
* @num_skip_dtim: Number of DTIMs to skip if Skip over DTIM flag is set
* @snooze_interval: TBD
* @snooze_window: TBD
* @snooze_interval: Maximum time between attempts to retrieve buffered data
* from the AP [msec]
* @snooze_window: A window of time in which PBW snoozing insures that all
* packets received. It is also the minimum time from last
* received unicast RX packet, before client stops snoozing
* for data. [msec]
* @snooze_step: TBD
* @qndp_tid: TID client shall use for uAPSD QNDP triggers
* @uapsd_ac_flags: Set trigger-enabled and delivery-enabled indication for
...
...
@@ -164,10 +168,10 @@ struct iwl_powertable_cmd {
* Use IEEE80211_WMM_IE_STA_QOSINFO_AC* for correct values.
* @uapsd_max_sp: Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct
* values.
* @heavy_t
raffic_thr_tx_pk
ts: TX threshold measured in number of packets
* @heavy_
traffic_thr_rx_pk
ts: RX threshold measured in number of packets
* @heavy_t
raffic_thr_tx_load
: TX threshold measured in load's percentage
* @heavy_
traffic_thr_rx_load
: RX threshold measured in load's percentage
* @heavy_t
x_thld_packe
ts: TX threshold measured in number of packets
* @heavy_
rx_thld_packe
ts: RX threshold measured in number of packets
* @heavy_t
x_thld_percentage
: TX threshold measured in load's percentage
* @heavy_
rx_thld_percentage
: RX threshold measured in load's percentage
* @limited_ps_threshold:
*/
struct
iwl_mac_power_cmd
{
...
...
@@ -189,10 +193,10 @@ struct iwl_mac_power_cmd {
u8
qndp_tid
;
u8
uapsd_ac_flags
;
u8
uapsd_max_sp
;
u8
heavy_t
raffic_threshold_tx
_packets
;
u8
heavy_
traffic_threshold_rx
_packets
;
u8
heavy_t
raffic_threshold_tx
_percentage
;
u8
heavy_
traffic_threshold_rx
_percentage
;
u8
heavy_t
x_thld
_packets
;
u8
heavy_
rx_thld
_packets
;
u8
heavy_t
x_thld
_percentage
;
u8
heavy_
rx_thld
_percentage
;
u8
limited_ps_threshold
;
u8
reserved
;
}
__packed
;
...
...
drivers/net/wireless/iwlwifi/mvm/fw-api.h
浏览文件 @
24de851b
...
...
@@ -499,71 +499,199 @@ enum iwl_time_event_type {
TE_MAX
};
/* MAC_EVENT_TYPE_API_E_VER_1 */
/* Time event - defines for command API v1 */
/*
* @TE_V1_FRAG_NONE: fragmentation of the time event is NOT allowed.
* @TE_V1_FRAG_SINGLE: fragmentation of the time event is allowed, but only
* the first fragment is scheduled.
* @TE_V1_FRAG_DUAL: fragmentation of the time event is allowed, but only
* the first 2 fragments are scheduled.
* @TE_V1_FRAG_ENDLESS: fragmentation of the time event is allowed, and any
* number of fragments are valid.
*
* Other than the constant defined above, specifying a fragmentation value 'x'
* means that the event can be fragmented but only the first 'x' will be
* scheduled.
*/
enum
{
TE_V1_FRAG_NONE
=
0
,
TE_V1_FRAG_SINGLE
=
1
,
TE_V1_FRAG_DUAL
=
2
,
TE_V1_FRAG_ENDLESS
=
0xffffffff
};
/* If a Time Event can be fragmented, this is the max number of fragments */
#define TE_V1_FRAG_MAX_MSK 0x0fffffff
/* Repeat the time event endlessly (until removed) */
#define TE_V1_REPEAT_ENDLESS 0xffffffff
/* If a Time Event has bounded repetitions, this is the maximal value */
#define TE_V1_REPEAT_MAX_MSK_V1 0x0fffffff
/* Time Event dependencies: none, on another TE, or in a specific time */
enum
{
TE_INDEPENDENT
=
0
,
TE_
DEP_OTHER
=
1
,
TE_
DEP_TSF
=
2
,
TE_
EVENT_SOCIOPATHIC
=
4
,
TE_
V1_
INDEPENDENT
=
0
,
TE_
V1_DEP_OTHER
=
BIT
(
0
)
,
TE_
V1_DEP_TSF
=
BIT
(
1
)
,
TE_
V1_EVENT_SOCIOPATHIC
=
BIT
(
2
)
,
};
/* MAC_EVENT_DEPENDENCY_POLICY_API_E_VER_2 */
/*
* @TE_V1_NOTIF_NONE: no notifications
* @TE_V1_NOTIF_HOST_EVENT_START: request/receive notification on event start
* @TE_V1_NOTIF_HOST_EVENT_END:request/receive notification on event end
* @TE_V1_NOTIF_INTERNAL_EVENT_START: internal FW use
* @TE_V1_NOTIF_INTERNAL_EVENT_END: internal FW use.
* @TE_V1_NOTIF_HOST_FRAG_START: request/receive notification on frag start
* @TE_V1_NOTIF_HOST_FRAG_END:request/receive notification on frag end
* @TE_V1_NOTIF_INTERNAL_FRAG_START: internal FW use.
* @TE_V1_NOTIF_INTERNAL_FRAG_END: internal FW use.
*
* Supported Time event notifications configuration.
* A notification (both event and fragment) includes a status indicating weather
* the FW was able to schedule the event or not. For fragment start/end
* notification the status is always success. There is no start/end fragment
* notification for monolithic events.
*
* @TE_NOTIF_NONE: no notifications
* @TE_NOTIF_HOST_EVENT_START: request/receive notification on event start
* @TE_NOTIF_HOST_EVENT_END:request/receive notification on event end
* @TE_NOTIF_INTERNAL_EVENT_START: internal FW use
* @TE_NOTIF_INTERNAL_EVENT_END: internal FW use.
* @TE_NOTIF_HOST_FRAG_START: request/receive notification on frag start
* @TE_NOTIF_HOST_FRAG_END:request/receive notification on frag end
* @TE_NOTIF_INTERNAL_FRAG_START: internal FW use.
* @TE_NOTIF_INTERNAL_FRAG_END: internal FW use.
*/
enum
{
TE_NOTIF_NONE
=
0
,
TE_
NOTIF_HOST_EVENT_START
=
0x1
,
TE_
NOTIF_HOST_EVENT_END
=
0x2
,
TE_
NOTIF_INTERNAL_EVENT_START
=
0x4
,
TE_
NOTIF_INTERNAL_EVENT_END
=
0x8
,
TE_
NOTIF_HOST_FRAG_START
=
0x10
,
TE_
NOTIF_HOST_FRAG_END
=
0x20
,
TE_
NOTIF_INTERNAL_FRAG_START
=
0x40
,
TE_
NOTIF_INTERNAL_FRAG_END
=
0x80
TE_
V1_
NOTIF_NONE
=
0
,
TE_
V1_NOTIF_HOST_EVENT_START
=
BIT
(
0
)
,
TE_
V1_NOTIF_HOST_EVENT_END
=
BIT
(
1
)
,
TE_
V1_NOTIF_INTERNAL_EVENT_START
=
BIT
(
2
)
,
TE_
V1_NOTIF_INTERNAL_EVENT_END
=
BIT
(
3
)
,
TE_
V1_NOTIF_HOST_FRAG_START
=
BIT
(
4
)
,
TE_
V1_NOTIF_HOST_FRAG_END
=
BIT
(
5
)
,
TE_
V1_NOTIF_INTERNAL_FRAG_START
=
BIT
(
6
)
,
TE_
V1_NOTIF_INTERNAL_FRAG_END
=
BIT
(
7
),
};
/* MAC_EVENT_ACTION_API_E_VER_2 */
/**
* struct iwl_time_event_cmd_api_v1 - configuring Time Events
* with struct MAC_TIME_EVENT_DATA_API_S_VER_1 (see also
* with version 2. determined by IWL_UCODE_TLV_FLAGS)
* ( TIME_EVENT_CMD = 0x29 )
* @id_and_color: ID and color of the relevant MAC
* @action: action to perform, one of FW_CTXT_ACTION_*
* @id: this field has two meanings, depending on the action:
* If the action is ADD, then it means the type of event to add.
* For all other actions it is the unique event ID assigned when the
* event was added by the FW.
* @apply_time: When to start the Time Event (in GP2)
* @max_delay: maximum delay to event's start (apply time), in TU
* @depends_on: the unique ID of the event we depend on (if any)
* @interval: interval between repetitions, in TU
* @interval_reciprocal: 2^32 / interval
* @duration: duration of event in TU
* @repeat: how many repetitions to do, can be TE_REPEAT_ENDLESS
* @dep_policy: one of TE_V1_INDEPENDENT, TE_V1_DEP_OTHER, TE_V1_DEP_TSF
* and TE_V1_EVENT_SOCIOPATHIC
* @is_present: 0 or 1, are we present or absent during the Time Event
* @max_frags: maximal number of fragments the Time Event can be divided to
* @notify: notifications using TE_V1_NOTIF_* (whom to notify when)
*/
struct
iwl_time_event_cmd_v1
{
/* COMMON_INDEX_HDR_API_S_VER_1 */
__le32
id_and_color
;
__le32
action
;
__le32
id
;
/* MAC_TIME_EVENT_DATA_API_S_VER_1 */
__le32
apply_time
;
__le32
max_delay
;
__le32
dep_policy
;
__le32
depends_on
;
__le32
is_present
;
__le32
max_frags
;
__le32
interval
;
__le32
interval_reciprocal
;
__le32
duration
;
__le32
repeat
;
__le32
notify
;
}
__packed
;
/* MAC_TIME_EVENT_CMD_API_S_VER_1 */
/* Time event - defines for command API v2 */
/*
* @TE_FRAG_NONE: fragmentation of the time event is NOT allowed.
* @TE_FRAG_SINGLE: fragmentation of the time event is allowed, but only
* @TE_
V2_
FRAG_NONE: fragmentation of the time event is NOT allowed.
* @TE_
V2_
FRAG_SINGLE: fragmentation of the time event is allowed, but only
* the first fragment is scheduled.
* @TE_FRAG_DUAL: fragmentation of the time event is allowed, but only
* @TE_
V2_
FRAG_DUAL: fragmentation of the time event is allowed, but only
* the first 2 fragments are scheduled.
* @TE_
FRAG_ENDLESS: fragmentation of the time event is allowed, and any number
* of fragments are valid.
* @TE_
V2_FRAG_ENDLESS: fragmentation of the time event is allowed, and any
*
number
of fragments are valid.
*
* Other than the constant defined above, specifying a fragmentation value 'x'
* means that the event can be fragmented but only the first 'x' will be
* scheduled.
*/
enum
{
TE_FRAG_NONE
=
0
,
TE_FRAG_SINGLE
=
1
,
TE_FRAG_DUAL
=
2
,
TE_FRAG_ENDLESS
=
0xffffffff
TE_V2_FRAG_NONE
=
0
,
TE_V2_FRAG_SINGLE
=
1
,
TE_V2_FRAG_DUAL
=
2
,
TE_V2_FRAG_MAX
=
0xfe
,
TE_V2_FRAG_ENDLESS
=
0xff
};
/* Repeat the time event endlessly (until removed) */
#define TE_
REPEAT_ENDLESS (0xffffffff)
#define TE_
V2_REPEAT_ENDLESS 0xff
/* If a Time Event has bounded repetitions, this is the maximal value */
#define TE_REPEAT_MAX_MSK (0x0fffffff)
/* If a Time Event can be fragmented, this is the max number of fragments */
#define TE_FRAG_MAX_MSK (0x0fffffff)
#define TE_V2_REPEAT_MAX 0xfe
#define TE_V2_PLACEMENT_POS 12
#define TE_V2_ABSENCE_POS 15
/* Time event policy values (for time event cmd api v2)
* A notification (both event and fragment) includes a status indicating weather
* the FW was able to schedule the event or not. For fragment start/end
* notification the status is always success. There is no start/end fragment
* notification for monolithic events.
*
* @TE_V2_DEFAULT_POLICY: independent, social, present, unoticable
* @TE_V2_NOTIF_HOST_EVENT_START: request/receive notification on event start
* @TE_V2_NOTIF_HOST_EVENT_END:request/receive notification on event end
* @TE_V2_NOTIF_INTERNAL_EVENT_START: internal FW use
* @TE_V2_NOTIF_INTERNAL_EVENT_END: internal FW use.
* @TE_V2_NOTIF_HOST_FRAG_START: request/receive notification on frag start
* @TE_V2_NOTIF_HOST_FRAG_END:request/receive notification on frag end
* @TE_V2_NOTIF_INTERNAL_FRAG_START: internal FW use.
* @TE_V2_NOTIF_INTERNAL_FRAG_END: internal FW use.
* @TE_V2_DEP_OTHER: depends on another time event
* @TE_V2_DEP_TSF: depends on a specific time
* @TE_V2_EVENT_SOCIOPATHIC: can't co-exist with other events of tha same MAC
* @TE_V2_ABSENCE: are we present or absent during the Time Event.
*/
enum
{
TE_V2_DEFAULT_POLICY
=
0x0
,
/* notifications (event start/stop, fragment start/stop) */
TE_V2_NOTIF_HOST_EVENT_START
=
BIT
(
0
),
TE_V2_NOTIF_HOST_EVENT_END
=
BIT
(
1
),
TE_V2_NOTIF_INTERNAL_EVENT_START
=
BIT
(
2
),
TE_V2_NOTIF_INTERNAL_EVENT_END
=
BIT
(
3
),
TE_V2_NOTIF_HOST_FRAG_START
=
BIT
(
4
),
TE_V2_NOTIF_HOST_FRAG_END
=
BIT
(
5
),
TE_V2_NOTIF_INTERNAL_FRAG_START
=
BIT
(
6
),
TE_V2_NOTIF_INTERNAL_FRAG_END
=
BIT
(
7
),
TE_V2_NOTIF_MSK
=
0xff
,
/* placement characteristics */
TE_V2_DEP_OTHER
=
BIT
(
TE_V2_PLACEMENT_POS
),
TE_V2_DEP_TSF
=
BIT
(
TE_V2_PLACEMENT_POS
+
1
),
TE_V2_EVENT_SOCIOPATHIC
=
BIT
(
TE_V2_PLACEMENT_POS
+
2
),
/* are we present or absent during the Time Event. */
TE_V2_ABSENCE
=
BIT
(
TE_V2_ABSENCE_POS
),
};
/**
* struct iwl_time_event_cmd - configuring Time Events
* struct iwl_time_event_cmd_api_v2 - configuring Time Events
* with struct MAC_TIME_EVENT_DATA_API_S_VER_2 (see also
* with version 1. determined by IWL_UCODE_TLV_FLAGS)
* ( TIME_EVENT_CMD = 0x29 )
* @id_and_color: ID and color of the relevant MAC
* @action: action to perform, one of FW_CTXT_ACTION_*
...
...
@@ -575,32 +703,30 @@ enum {
* @max_delay: maximum delay to event's start (apply time), in TU
* @depends_on: the unique ID of the event we depend on (if any)
* @interval: interval between repetitions, in TU
* @interval_reciprocal: 2^32 / interval
* @duration: duration of event in TU
* @repeat: how many repetitions to do, can be TE_REPEAT_ENDLESS
* @dep_policy: one of TE_INDEPENDENT, TE_DEP_OTHER, TE_DEP_TSF
* @is_present: 0 or 1, are we present or absent during the Time Event
* @max_frags: maximal number of fragments the Time Event can be divided to
* @notify: notifications using TE_NOTIF_* (whom to notify when)
* @policy: defines whether uCode shall notify the host or other uCode modules
* on event and/or fragment start and/or end
* using one of TE_INDEPENDENT, TE_DEP_OTHER, TE_DEP_TSF
* TE_EVENT_SOCIOPATHIC
* using TE_ABSENCE and using TE_NOTIF_*
*/
struct
iwl_time_event_cmd
{
struct
iwl_time_event_cmd
_v2
{
/* COMMON_INDEX_HDR_API_S_VER_1 */
__le32
id_and_color
;
__le32
action
;
__le32
id
;
/* MAC_TIME_EVENT_DATA_API_S_VER_
1
*/
/* MAC_TIME_EVENT_DATA_API_S_VER_
2
*/
__le32
apply_time
;
__le32
max_delay
;
__le32
dep_policy
;
__le32
depends_on
;
__le32
is_present
;
__le32
max_frags
;
__le32
interval
;
__le32
interval_reciprocal
;
__le32
duration
;
__le32
repeat
;
__le32
notify
;
}
__packed
;
/* MAC_TIME_EVENT_CMD_API_S_VER_1 */
u8
repeat
;
u8
max_frags
;
__le16
policy
;
}
__packed
;
/* MAC_TIME_EVENT_CMD_API_S_VER_2 */
/**
* struct iwl_time_event_resp - response structure to iwl_time_event_cmd
...
...
@@ -1195,7 +1321,7 @@ struct mvm_statistics_general {
struct
mvm_statistics_general_common
common
;
__le32
beacon_filtered
;
__le32
missed_beacons
;
__s8
beacon_filter_
e
verage_energy
;
__s8
beacon_filter_
a
verage_energy
;
__s8
beacon_filter_reason
;
__s8
beacon_filter_current_energy
;
__s8
beacon_filter_reserved
;
...
...
drivers/net/wireless/iwlwifi/mvm/mac80211.c
浏览文件 @
24de851b
...
...
@@ -155,7 +155,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
IEEE80211_HW_TIMING_BEACON_ONLY
|
IEEE80211_HW_CONNECTION_MONITOR
|
IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS
|
IEEE80211_HW_SUPPORTS_STATIC_SMPS
;
IEEE80211_HW_SUPPORTS_STATIC_SMPS
|
IEEE80211_HW_SUPPORTS_UAPSD
;
hw
->
queues
=
IWL_MVM_FIRST_AGG_QUEUE
;
hw
->
offchannel_tx_hw_queue
=
IWL_MVM_OFFCHANNEL_QUEUE
;
...
...
@@ -190,6 +191,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw
->
wiphy
->
max_remain_on_channel_duration
=
10000
;
hw
->
max_listen_interval
=
IWL_CONN_MAX_LISTEN_INTERVAL
;
hw
->
uapsd_queues
=
IWL_UAPSD_AC_INFO
;
hw
->
uapsd_max_sp_len
=
IWL_UAPSD_MAX_SP
;
/* Extract MAC address */
memcpy
(
mvm
->
addresses
[
0
].
addr
,
mvm
->
nvm_data
->
hw_addr
,
ETH_ALEN
);
...
...
@@ -577,7 +580,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
vif
->
type
==
NL80211_IFTYPE_STATION
&&
!
vif
->
p2p
&&
mvm
->
fw
->
ucode_capa
.
flags
&
IWL_UCODE_TLV_FLAGS_BF_UPDATED
){
mvm
->
bf_allowed_vif
=
mvmvif
;
vif
->
driver_flags
|=
IEEE80211_VIF_BEACON_FILTER
;
vif
->
driver_flags
|=
IEEE80211_VIF_BEACON_FILTER
|
IEEE80211_VIF_SUPPORTS_CQM_RSSI
;
}
/*
...
...
@@ -617,7 +621,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
out_free_bf:
if
(
mvm
->
bf_allowed_vif
==
mvmvif
)
{
mvm
->
bf_allowed_vif
=
NULL
;
vif
->
driver_flags
&=
~
IEEE80211_VIF_BEACON_FILTER
;
vif
->
driver_flags
&=
~
(
IEEE80211_VIF_BEACON_FILTER
|
IEEE80211_VIF_SUPPORTS_CQM_RSSI
);
}
out_remove_mac:
mvmvif
->
phy_ctxt
=
NULL
;
...
...
@@ -683,7 +688,8 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
if
(
mvm
->
bf_allowed_vif
==
mvmvif
)
{
mvm
->
bf_allowed_vif
=
NULL
;
vif
->
driver_flags
&=
~
IEEE80211_VIF_BEACON_FILTER
;
vif
->
driver_flags
&=
~
(
IEEE80211_VIF_BEACON_FILTER
|
IEEE80211_VIF_SUPPORTS_CQM_RSSI
);
}
iwl_mvm_vif_dbgfs_clean
(
mvm
,
vif
);
...
...
@@ -801,6 +807,10 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
if
(
ret
)
IWL_ERR
(
mvm
,
"failed to update quotas
\n
"
);
}
/* reset rssi values */
mvmvif
->
bf_data
.
ave_beacon_signal
=
0
;
if
(
!
(
mvm
->
fw
->
ucode_capa
.
flags
&
IWL_UCODE_TLV_FLAGS_UAPSD
))
{
/* Workaround for FW bug, otherwise FW disables device
* power save upon disassociation
...
...
@@ -817,7 +827,7 @@ 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
)
{
}
else
if
(
changes
&
(
BSS_CHANGED_PS
|
BSS_CHANGED_QOS
)
)
{
ret
=
iwl_mvm_power_update_mode
(
mvm
,
vif
);
if
(
ret
)
IWL_ERR
(
mvm
,
"failed to update power mode
\n
"
);
...
...
@@ -827,6 +837,15 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
bss_conf
->
txpower
);
iwl_mvm_set_tx_power
(
mvm
,
vif
,
bss_conf
->
txpower
);
}
if
(
changes
&
BSS_CHANGED_CQM
)
{
IWL_DEBUG_MAC80211
(
mvm
,
"cqm info_changed"
);
/* reset cqm events tracking */
mvmvif
->
bf_data
.
last_cqm_event
=
0
;
ret
=
iwl_mvm_update_beacon_filter
(
mvm
,
vif
);
if
(
ret
)
IWL_ERR
(
mvm
,
"failed to update CQM thresholds
\n
"
);
}
}
static
int
iwl_mvm_start_ap
(
struct
ieee80211_hw
*
hw
,
struct
ieee80211_vif
*
vif
)
...
...
drivers/net/wireless/iwlwifi/mvm/mvm.h
浏览文件 @
24de851b
...
...
@@ -153,6 +153,11 @@ enum iwl_power_scheme {
};
#define IWL_CONN_MAX_LISTEN_INTERVAL 70
#define IWL_UAPSD_AC_INFO (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\
IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |\
IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |\
IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
#define IWL_UAPSD_MAX_SP IEEE80211_WMM_IE_STA_QOSINFO_SP_2
struct
iwl_mvm_power_ops
{
int
(
*
power_update_mode
)(
struct
iwl_mvm
*
mvm
,
...
...
@@ -175,6 +180,7 @@ enum iwl_dbgfs_pm_mask {
MVM_DEBUGFS_PM_DISABLE_POWER_OFF
=
BIT
(
5
),
MVM_DEBUGFS_PM_LPRX_ENA
=
BIT
(
6
),
MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD
=
BIT
(
7
),
MVM_DEBUGFS_PM_SNOOZE_ENABLE
=
BIT
(
8
),
};
struct
iwl_dbgfs_pm
{
...
...
@@ -186,6 +192,7 @@ struct iwl_dbgfs_pm {
bool
disable_power_off
;
bool
lprx_ena
;
u32
lprx_rssi_threshold
;
bool
snooze_ena
;
int
mask
;
};
...
...
@@ -227,6 +234,21 @@ enum iwl_mvm_smps_type_request {
NUM_IWL_MVM_SMPS_REQ
,
};
/**
* struct iwl_mvm_vif_bf_data - beacon filtering related data
* @bf_enabled: indicates if beacon filtering is enabled
* @ba_enabled: indicated if beacon abort is enabled
* @last_beacon_signal: last beacon rssi signal in dbm
* @ave_beacon_signal: average beacon signal
* @last_cqm_event: rssi of the last cqm event
*/
struct
iwl_mvm_vif_bf_data
{
bool
bf_enabled
;
bool
ba_enabled
;
s8
ave_beacon_signal
;
s8
last_cqm_event
;
};
/**
* struct iwl_mvm_vif - data per Virtual Interface, it is a MAC context
* @id: between 0 and 3
...
...
@@ -252,8 +274,7 @@ struct iwl_mvm_vif {
bool
uploaded
;
bool
ap_active
;
bool
monitor_active
;
/* indicate whether beacon filtering is enabled */
bool
bf_enabled
;
struct
iwl_mvm_vif_bf_data
bf_data
;
u32
ap_beacon_time
;
...
...
@@ -754,6 +775,8 @@ int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
struct
iwl_beacon_filter_cmd
*
cmd
);
int
iwl_mvm_update_beacon_abort
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
bool
enable
);
int
iwl_mvm_update_beacon_filter
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
);
/* SMPS */
void
iwl_mvm_update_smps
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
...
...
drivers/net/wireless/iwlwifi/mvm/power.c
浏览文件 @
24de851b
...
...
@@ -110,6 +110,23 @@ int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
return
ret
;
}
static
void
iwl_mvm_beacon_filter_set_cqm_params
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
struct
iwl_beacon_filter_cmd
*
cmd
)
{
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
if
(
vif
->
bss_conf
.
cqm_rssi_thold
)
{
cmd
->
bf_energy_delta
=
cpu_to_le32
(
vif
->
bss_conf
.
cqm_rssi_hyst
);
/* fw uses an absolute value for this */
cmd
->
bf_roaming_state
=
cpu_to_le32
(
-
vif
->
bss_conf
.
cqm_rssi_thold
);
}
cmd
->
ba_enable_beacon_abort
=
cpu_to_le32
(
mvmvif
->
bf_data
.
ba_enabled
);
}
int
iwl_mvm_update_beacon_abort
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
bool
enable
)
{
...
...
@@ -120,12 +137,14 @@ int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
.
ba_enable_beacon_abort
=
cpu_to_le32
(
enable
),
};
if
(
!
mvmvif
->
bf_enabled
)
if
(
!
mvmvif
->
bf_
data
.
bf_
enabled
)
return
0
;
if
(
mvm
->
cur_ucode
==
IWL_UCODE_WOWLAN
)
cmd
.
ba_escape_timer
=
cpu_to_le32
(
IWL_BA_ESCAPE_TIMER_D3
);
mvmvif
->
bf_data
.
ba_enabled
=
enable
;
iwl_mvm_beacon_filter_set_cqm_params
(
mvm
,
vif
,
&
cmd
);
iwl_mvm_beacon_filter_debugfs_parameters
(
vif
,
&
cmd
);
return
iwl_mvm_beacon_filter_send_cmd
(
mvm
,
&
cmd
);
}
...
...
@@ -140,17 +159,30 @@ static void iwl_mvm_power_log(struct iwl_mvm *mvm,
IWL_DEBUG_POWER
(
mvm
,
"Keep alive = %u sec
\n
"
,
le16_to_cpu
(
cmd
->
keep_alive_seconds
));
if
(
cmd
->
flags
&
cpu_to_le16
(
POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK
))
{
IWL_DEBUG_POWER
(
mvm
,
"Rx timeout = %u usec
\n
"
,
le32_to_cpu
(
cmd
->
rx_data_timeout
));
IWL_DEBUG_POWER
(
mvm
,
"Tx timeout = %u usec
\n
"
,
le32_to_cpu
(
cmd
->
tx_data_timeout
));
if
(
cmd
->
flags
&
cpu_to_le16
(
POWER_FLAGS_SKIP_OVER_DTIM_MSK
))
IWL_DEBUG_POWER
(
mvm
,
"DTIM periods to skip = %u
\n
"
,
cmd
->
skip_dtim_periods
);
if
(
cmd
->
flags
&
cpu_to_le16
(
POWER_FLAGS_LPRX_ENA_MSK
))
IWL_DEBUG_POWER
(
mvm
,
"LP RX RSSI threshold = %u
\n
"
,
cmd
->
lprx_rssi_threshold
);
if
(
!
(
cmd
->
flags
&
cpu_to_le16
(
POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK
)))
{
IWL_DEBUG_POWER
(
mvm
,
"Disable power management
\n
"
);
return
;
}
IWL_DEBUG_POWER
(
mvm
,
"Rx timeout = %u usec
\n
"
,
le32_to_cpu
(
cmd
->
rx_data_timeout
));
IWL_DEBUG_POWER
(
mvm
,
"Tx timeout = %u usec
\n
"
,
le32_to_cpu
(
cmd
->
tx_data_timeout
));
if
(
cmd
->
flags
&
cpu_to_le16
(
POWER_FLAGS_SKIP_OVER_DTIM_MSK
))
IWL_DEBUG_POWER
(
mvm
,
"DTIM periods to skip = %u
\n
"
,
cmd
->
skip_dtim_periods
);
if
(
cmd
->
flags
&
cpu_to_le16
(
POWER_FLAGS_LPRX_ENA_MSK
))
IWL_DEBUG_POWER
(
mvm
,
"LP RX RSSI threshold = %u
\n
"
,
cmd
->
lprx_rssi_threshold
);
if
(
cmd
->
flags
&
cpu_to_le16
(
POWER_FLAGS_ADVANCE_PM_ENA_MSK
))
{
IWL_DEBUG_POWER
(
mvm
,
"uAPSD enabled
\n
"
);
IWL_DEBUG_POWER
(
mvm
,
"Rx timeout (uAPSD) = %u usec
\n
"
,
le32_to_cpu
(
cmd
->
rx_data_timeout_uapsd
));
IWL_DEBUG_POWER
(
mvm
,
"Tx timeout (uAPSD) = %u usec
\n
"
,
le32_to_cpu
(
cmd
->
tx_data_timeout_uapsd
));
IWL_DEBUG_POWER
(
mvm
,
"QNDP TID = %d
\n
"
,
cmd
->
qndp_tid
);
IWL_DEBUG_POWER
(
mvm
,
"ACs flags = 0x%x
\n
"
,
cmd
->
uapsd_ac_flags
);
IWL_DEBUG_POWER
(
mvm
,
"Max SP = %d
\n
"
,
cmd
->
uapsd_max_sp
);
}
}
...
...
@@ -166,6 +198,8 @@ 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
;
cmd
->
id_and_color
=
cpu_to_le32
(
FW_CMD_ID_AND_COLOR
(
mvmvif
->
id
,
mvmvif
->
color
));
...
...
@@ -235,6 +269,63 @@ 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
;
cmd
->
flags
|=
cpu_to_le16
(
POWER_FLAGS_ADVANCE_PM_ENA_MSK
);
cmd
->
uapsd_ac_flags
|=
BIT
(
ac
);
/* QNDP TID - the highest TID with no admission control */
if
(
!
tid_found
&&
!
mvmvif
->
queue_params
[
ac
].
acm
)
{
tid_found
=
true
;
switch
(
ac
)
{
case
IEEE80211_AC_VO
:
cmd
->
qndp_tid
=
6
;
break
;
case
IEEE80211_AC_VI
:
cmd
->
qndp_tid
=
5
;
break
;
case
IEEE80211_AC_BE
:
cmd
->
qndp_tid
=
0
;
break
;
case
IEEE80211_AC_BK
:
cmd
->
qndp_tid
=
1
;
break
;
}
}
}
if
(
cmd
->
flags
&
cpu_to_le16
(
POWER_FLAGS_ADVANCE_PM_ENA_MSK
))
{
cmd
->
rx_data_timeout_uapsd
=
cpu_to_le32
(
IWL_MVM_UAPSD_RX_DATA_TIMEOUT
);
cmd
->
tx_data_timeout_uapsd
=
cpu_to_le32
(
IWL_MVM_UAPSD_TX_DATA_TIMEOUT
);
if
(
cmd
->
uapsd_ac_flags
==
(
BIT
(
IEEE80211_AC_VO
)
|
BIT
(
IEEE80211_AC_VI
)
|
BIT
(
IEEE80211_AC_BE
)
|
BIT
(
IEEE80211_AC_BK
)))
{
cmd
->
flags
|=
cpu_to_le16
(
POWER_FLAGS_SNOOZE_ENA_MSK
);
cmd
->
snooze_interval
=
cpu_to_le16
(
IWL_MVM_PS_SNOOZE_INTERVAL
);
cmd
->
snooze_window
=
(
mvm
->
cur_ucode
==
IWL_UCODE_WOWLAN
)
?
cpu_to_le16
(
IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW
)
:
cpu_to_le16
(
IWL_MVM_PS_SNOOZE_WINDOW
);
}
cmd
->
uapsd_max_sp
=
IWL_UAPSD_MAX_SP
;
cmd
->
heavy_tx_thld_packets
=
IWL_MVM_PS_HEAVY_TX_THLD_PACKETS
;
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
;
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
if
(
mvmvif
->
dbgfs_pm
.
mask
&
MVM_DEBUGFS_PM_KEEP_ALIVE
)
cmd
->
keep_alive_seconds
=
...
...
@@ -263,6 +354,14 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
}
if
(
mvmvif
->
dbgfs_pm
.
mask
&
MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD
)
cmd
->
lprx_rssi_threshold
=
mvmvif
->
dbgfs_pm
.
lprx_rssi_threshold
;
if
(
mvmvif
->
dbgfs_pm
.
mask
&
MVM_DEBUGFS_PM_SNOOZE_ENABLE
)
{
if
(
mvmvif
->
dbgfs_pm
.
snooze_ena
)
cmd
->
flags
|=
cpu_to_le16
(
POWER_FLAGS_SNOOZE_ENA_MSK
);
else
cmd
->
flags
&=
cpu_to_le16
(
~
POWER_FLAGS_SNOOZE_ENA_MSK
);
}
#endif
/* CONFIG_IWLWIFI_DEBUGFS */
}
...
...
@@ -342,8 +441,6 @@ static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
(
cmd
.
flags
&
cpu_to_le16
(
POWER_FLAGS_POWER_SAVE_ENA_MSK
))
?
0
:
1
);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"skip_dtim_periods = %d
\n
"
,
cmd
.
skip_dtim_periods
);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"power_scheme = %d
\n
"
,
iwlmvm_mod_params
.
power_scheme
);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"flags = 0x%x
\n
"
,
...
...
@@ -356,14 +453,64 @@ static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
(
cmd
.
flags
&
cpu_to_le16
(
POWER_FLAGS_SKIP_OVER_DTIM_MSK
))
?
1
:
0
);
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
));
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
);
}
}
return
pos
;
}
...
...
@@ -417,11 +564,12 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
vif
->
type
!=
NL80211_IFTYPE_STATION
||
vif
->
p2p
)
return
0
;
iwl_mvm_beacon_filter_set_cqm_params
(
mvm
,
vif
,
&
cmd
);
iwl_mvm_beacon_filter_debugfs_parameters
(
vif
,
&
cmd
);
ret
=
iwl_mvm_beacon_filter_send_cmd
(
mvm
,
&
cmd
);
if
(
!
ret
)
mvmvif
->
bf_enabled
=
true
;
mvmvif
->
bf_
data
.
bf_
enabled
=
true
;
return
ret
;
}
...
...
@@ -440,11 +588,22 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
ret
=
iwl_mvm_beacon_filter_send_cmd
(
mvm
,
&
cmd
);
if
(
!
ret
)
mvmvif
->
bf_enabled
=
false
;
mvmvif
->
bf_
data
.
bf_
enabled
=
false
;
return
ret
;
}
int
iwl_mvm_update_beacon_filter
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
)
{
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
if
(
!
mvmvif
->
bf_data
.
bf_enabled
)
return
0
;
return
iwl_mvm_enable_beacon_filter
(
mvm
,
vif
);
}
const
struct
iwl_mvm_power_ops
pm_mac_ops
=
{
.
power_update_mode
=
iwl_mvm_power_mac_update_mode
,
.
power_disable
=
iwl_mvm_power_mac_disable
,
...
...
drivers/net/wireless/iwlwifi/mvm/rs.c
浏览文件 @
24de851b
此差异已折叠。
点击以展开。
drivers/net/wireless/iwlwifi/mvm/rs.h
浏览文件 @
24de851b
...
...
@@ -38,14 +38,8 @@ struct iwl_rs_rate_info {
u8
plcp
;
/* uCode API: IWL_RATE_6M_PLCP, etc. */
u8
plcp_siso
;
/* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */
u8
plcp_mimo2
;
/* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */
u8
plcp_mimo3
;
/* uCode API: IWL_RATE_MIMO3_6M_PLCP, etc. */
u8
ieee
;
/* MAC header: IWL_RATE_6M_IEEE, etc. */
u8
prev_ieee
;
/* previous rate in IEEE speeds */
u8
next_ieee
;
/* next rate in IEEE speeds */
u8
prev_rs
;
/* previous rate used in rs algo */
u8
next_rs
;
/* next rate used in rs algo */
u8
prev_rs_tgg
;
/* previous rate used in TGG rs algo */
u8
next_rs_tgg
;
/* next rate used in TGG rs algo */
};
#define IWL_RATE_60M_PLCP 3
...
...
@@ -120,23 +114,6 @@ enum {
IWL_RATE_MIMO3_INVM_PLCP
=
IWL_RATE_SISO_INVM_PLCP
,
};
/* MAC header values for bit rates */
enum
{
IWL_RATE_6M_IEEE
=
12
,
IWL_RATE_9M_IEEE
=
18
,
IWL_RATE_12M_IEEE
=
24
,
IWL_RATE_18M_IEEE
=
36
,
IWL_RATE_24M_IEEE
=
48
,
IWL_RATE_36M_IEEE
=
72
,
IWL_RATE_48M_IEEE
=
96
,
IWL_RATE_54M_IEEE
=
108
,
IWL_RATE_60M_IEEE
=
120
,
IWL_RATE_1M_IEEE
=
2
,
IWL_RATE_2M_IEEE
=
4
,
IWL_RATE_5M_IEEE
=
11
,
IWL_RATE_11M_IEEE
=
22
,
};
#define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1)
#define IWL_INVALID_VALUE -1
...
...
@@ -165,47 +142,22 @@ enum {
#define IWL_LEGACY_SWITCH_ANTENNA1 0
#define IWL_LEGACY_SWITCH_ANTENNA2 1
#define IWL_LEGACY_SWITCH_SISO 2
#define IWL_LEGACY_SWITCH_MIMO2_AB 3
#define IWL_LEGACY_SWITCH_MIMO2_AC 4
#define IWL_LEGACY_SWITCH_MIMO2_BC 5
#define IWL_LEGACY_SWITCH_MIMO3_ABC 6
#define IWL_LEGACY_SWITCH_MIMO2 3
/* possible actions when in siso mode */
#define IWL_SISO_SWITCH_ANTENNA1 0
#define IWL_SISO_SWITCH_ANTENNA2 1
#define IWL_SISO_SWITCH_MIMO2_AB 2
#define IWL_SISO_SWITCH_MIMO2_AC 3
#define IWL_SISO_SWITCH_MIMO2_BC 4
#define IWL_SISO_SWITCH_GI 5
#define IWL_SISO_SWITCH_MIMO3_ABC 6
#define IWL_SISO_SWITCH_MIMO2 2
#define IWL_SISO_SWITCH_GI 3
/* possible actions when in mimo mode */
#define IWL_MIMO2_SWITCH_ANTENNA1 0
#define IWL_MIMO2_SWITCH_ANTENNA2 1
#define IWL_MIMO2_SWITCH_SISO_A 2
#define IWL_MIMO2_SWITCH_SISO_B 3
#define IWL_MIMO2_SWITCH_SISO_C 4
#define IWL_MIMO2_SWITCH_GI 5
#define IWL_MIMO2_SWITCH_MIMO3_ABC 6
/* possible actions when in mimo3 mode */
#define IWL_MIMO3_SWITCH_ANTENNA1 0
#define IWL_MIMO3_SWITCH_ANTENNA2 1
#define IWL_MIMO3_SWITCH_SISO_A 2
#define IWL_MIMO3_SWITCH_SISO_B 3
#define IWL_MIMO3_SWITCH_SISO_C 4
#define IWL_MIMO3_SWITCH_MIMO2_AB 5
#define IWL_MIMO3_SWITCH_MIMO2_AC 6
#define IWL_MIMO3_SWITCH_MIMO2_BC 7
#define IWL_MIMO3_SWITCH_GI 8
#define IWL_MAX_11N_MIMO3_SEARCH IWL_MIMO3_SWITCH_GI
#define IWL_MAX_SEARCH IWL_MIMO2_SWITCH_MIMO3_ABC
#define IWL_MIMO2_SWITCH_GI 4
/*FIXME:RS:add possible actions for MIMO3*/
#define IWL_MAX_SEARCH IWL_MIMO2_SWITCH_GI
#define IWL_ACTION_LIMIT 3
/* # possible actions */
...
...
@@ -240,15 +192,13 @@ enum iwl_table_type {
LQ_A
,
LQ_SISO
,
/* high-throughput types */
LQ_MIMO2
,
LQ_MIMO3
,
LQ_MAX
,
};
#define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A))
#define is_siso(tbl) ((tbl) == LQ_SISO)
#define is_mimo2(tbl) ((tbl) == LQ_MIMO2)
#define is_mimo3(tbl) ((tbl) == LQ_MIMO3)
#define is_mimo(tbl) (is_mimo2(tbl) || is_mimo3(tbl))
#define is_mimo(tbl) is_mimo2(tbl)
#define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl))
#define is_a_band(tbl) ((tbl) == LQ_A)
#define is_g_and(tbl) ((tbl) == LQ_G)
...
...
@@ -320,7 +270,6 @@ struct iwl_lq_sta {
u16
active_legacy_rate
;
u16
active_siso_rate
;
u16
active_mimo2_rate
;
u16
active_mimo3_rate
;
s8
max_rate_idx
;
/* Max rate set by user */
u8
missed_rate_counter
;
...
...
@@ -330,7 +279,6 @@ struct iwl_lq_sta {
#ifdef CONFIG_MAC80211_DEBUGFS
struct
dentry
*
rs_sta_dbgfs_scale_table_file
;
struct
dentry
*
rs_sta_dbgfs_stats_table_file
;
struct
dentry
*
rs_sta_dbgfs_rate_scale_data_file
;
struct
dentry
*
rs_sta_dbgfs_tx_agg_tid_en_file
;
u32
dbg_fixed_rate
;
#endif
...
...
drivers/net/wireless/iwlwifi/mvm/rx.c
浏览文件 @
24de851b
...
...
@@ -396,11 +396,62 @@ static void iwl_mvm_update_rx_statistics(struct iwl_mvm *mvm,
memcpy
(
&
mvm
->
rx_stats
,
&
stats
->
rx
,
sizeof
(
struct
mvm_statistics_rx
));
}
struct
iwl_mvm_stat_data
{
struct
iwl_notif_statistics
*
stats
;
struct
iwl_mvm
*
mvm
;
};
static
void
iwl_mvm_stat_iterator
(
void
*
_data
,
u8
*
mac
,
struct
ieee80211_vif
*
vif
)
{
struct
iwl_mvm_stat_data
*
data
=
_data
;
struct
iwl_notif_statistics
*
stats
=
data
->
stats
;
struct
iwl_mvm
*
mvm
=
data
->
mvm
;
int
sig
=
-
stats
->
general
.
beacon_filter_average_energy
;
int
last_event
;
int
thold
=
vif
->
bss_conf
.
cqm_rssi_thold
;
int
hyst
=
vif
->
bss_conf
.
cqm_rssi_hyst
;
u16
id
=
le32_to_cpu
(
stats
->
rx
.
general
.
mac_id
);
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
if
(
mvmvif
->
id
!=
id
)
return
;
if
(
vif
->
type
!=
NL80211_IFTYPE_STATION
)
return
;
mvmvif
->
bf_data
.
ave_beacon_signal
=
sig
;
if
(
!
(
vif
->
driver_flags
&
IEEE80211_VIF_SUPPORTS_CQM_RSSI
))
return
;
/* CQM Notification */
last_event
=
mvmvif
->
bf_data
.
last_cqm_event
;
if
(
thold
&&
sig
<
thold
&&
(
last_event
==
0
||
sig
<
last_event
-
hyst
))
{
mvmvif
->
bf_data
.
last_cqm_event
=
sig
;
IWL_DEBUG_RX
(
mvm
,
"cqm_iterator cqm low %d
\n
"
,
sig
);
ieee80211_cqm_rssi_notify
(
vif
,
NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW
,
GFP_KERNEL
);
}
else
if
(
sig
>
thold
&&
(
last_event
==
0
||
sig
>
last_event
+
hyst
))
{
mvmvif
->
bf_data
.
last_cqm_event
=
sig
;
IWL_DEBUG_RX
(
mvm
,
"cqm_iterator cqm high %d
\n
"
,
sig
);
ieee80211_cqm_rssi_notify
(
vif
,
NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH
,
GFP_KERNEL
);
}
}
/*
* iwl_mvm_rx_statistics - STATISTICS_NOTIFICATION handler
*
* TODO: This handler is implemented partially.
* It only gets the NIC's temperature.
*/
int
iwl_mvm_rx_statistics
(
struct
iwl_mvm
*
mvm
,
struct
iwl_rx_cmd_buffer
*
rxb
,
...
...
@@ -409,6 +460,10 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm,
struct
iwl_rx_packet
*
pkt
=
rxb_addr
(
rxb
);
struct
iwl_notif_statistics
*
stats
=
(
void
*
)
&
pkt
->
data
;
struct
mvm_statistics_general_common
*
common
=
&
stats
->
general
.
common
;
struct
iwl_mvm_stat_data
data
=
{
.
stats
=
stats
,
.
mvm
=
mvm
,
};
if
(
mvm
->
temperature
!=
le32_to_cpu
(
common
->
temperature
))
{
mvm
->
temperature
=
le32_to_cpu
(
common
->
temperature
);
...
...
@@ -416,5 +471,9 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm,
}
iwl_mvm_update_rx_statistics
(
mvm
,
stats
);
ieee80211_iterate_active_interfaces
(
mvm
->
hw
,
IEEE80211_IFACE_ITER_NORMAL
,
iwl_mvm_stat_iterator
,
&
data
);
return
0
;
}
drivers/net/wireless/iwlwifi/mvm/time-event.c
浏览文件 @
24de851b
...
...
@@ -165,7 +165,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
WARN_ONCE
(
!
le32_to_cpu
(
notif
->
status
),
"Failed to schedule time event
\n
"
);
if
(
le32_to_cpu
(
notif
->
action
)
&
TE_NOTIF_HOST_EVENT_END
)
{
if
(
le32_to_cpu
(
notif
->
action
)
&
TE_
V2_
NOTIF_HOST_EVENT_END
)
{
IWL_DEBUG_TE
(
mvm
,
"TE ended - current time %lu, estimated end %lu
\n
"
,
jiffies
,
te_data
->
end_jiffies
);
...
...
@@ -188,7 +188,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
}
iwl_mvm_te_clear_data
(
mvm
,
te_data
);
}
else
if
(
le32_to_cpu
(
notif
->
action
)
&
TE_NOTIF_HOST_EVENT_START
)
{
}
else
if
(
le32_to_cpu
(
notif
->
action
)
&
TE_
V2_
NOTIF_HOST_EVENT_START
)
{
te_data
->
running
=
true
;
te_data
->
end_jiffies
=
TU_TO_EXP_TIME
(
te_data
->
duration
);
...
...
@@ -255,10 +255,67 @@ static bool iwl_mvm_time_event_response(struct iwl_notif_wait_data *notif_wait,
return
true
;
}
/* used to convert from time event API v2 to v1 */
#define TE_V2_DEP_POLICY_MSK (TE_V2_DEP_OTHER | TE_V2_DEP_TSF |\
TE_V2_EVENT_SOCIOPATHIC)
static
inline
u16
te_v2_get_notify
(
__le16
policy
)
{
return
le16_to_cpu
(
policy
)
&
TE_V2_NOTIF_MSK
;
}
static
inline
u16
te_v2_get_dep_policy
(
__le16
policy
)
{
return
(
le16_to_cpu
(
policy
)
&
TE_V2_DEP_POLICY_MSK
)
>>
TE_V2_PLACEMENT_POS
;
}
static
inline
u16
te_v2_get_absence
(
__le16
policy
)
{
return
(
le16_to_cpu
(
policy
)
&
TE_V2_ABSENCE
)
>>
TE_V2_ABSENCE_POS
;
}
static
void
iwl_mvm_te_v2_to_v1
(
const
struct
iwl_time_event_cmd_v2
*
cmd_v2
,
struct
iwl_time_event_cmd_v1
*
cmd_v1
)
{
cmd_v1
->
id_and_color
=
cmd_v2
->
id_and_color
;
cmd_v1
->
action
=
cmd_v2
->
action
;
cmd_v1
->
id
=
cmd_v2
->
id
;
cmd_v1
->
apply_time
=
cmd_v2
->
apply_time
;
cmd_v1
->
max_delay
=
cmd_v2
->
max_delay
;
cmd_v1
->
depends_on
=
cmd_v2
->
depends_on
;
cmd_v1
->
interval
=
cmd_v2
->
interval
;
cmd_v1
->
duration
=
cmd_v2
->
duration
;
if
(
cmd_v2
->
repeat
==
TE_V2_REPEAT_ENDLESS
)
cmd_v1
->
repeat
=
cpu_to_le32
(
TE_V1_REPEAT_ENDLESS
);
else
cmd_v1
->
repeat
=
cpu_to_le32
(
cmd_v2
->
repeat
);
cmd_v1
->
max_frags
=
cpu_to_le32
(
cmd_v2
->
max_frags
);
cmd_v1
->
interval_reciprocal
=
0
;
/* unused */
cmd_v1
->
dep_policy
=
cpu_to_le32
(
te_v2_get_dep_policy
(
cmd_v2
->
policy
));
cmd_v1
->
is_present
=
cpu_to_le32
(
!
te_v2_get_absence
(
cmd_v2
->
policy
));
cmd_v1
->
notify
=
cpu_to_le32
(
te_v2_get_notify
(
cmd_v2
->
policy
));
}
static
int
iwl_mvm_send_time_event_cmd
(
struct
iwl_mvm
*
mvm
,
const
struct
iwl_time_event_cmd_v2
*
cmd
)
{
struct
iwl_time_event_cmd_v1
cmd_v1
;
if
(
mvm
->
fw
->
ucode_capa
.
flags
&
IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2
)
return
iwl_mvm_send_cmd_pdu
(
mvm
,
TIME_EVENT_CMD
,
CMD_SYNC
,
sizeof
(
*
cmd
),
cmd
);
iwl_mvm_te_v2_to_v1
(
cmd
,
&
cmd_v1
);
return
iwl_mvm_send_cmd_pdu
(
mvm
,
TIME_EVENT_CMD
,
CMD_SYNC
,
sizeof
(
cmd_v1
),
&
cmd_v1
);
}
static
int
iwl_mvm_time_event_send_add
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
struct
iwl_mvm_time_event_data
*
te_data
,
struct
iwl_time_event_cmd
*
te_cmd
)
struct
iwl_time_event_cmd
_v2
*
te_cmd
)
{
static
const
u8
time_event_response
[]
=
{
TIME_EVENT_CMD
};
struct
iwl_notification_wait
wait_time_event
;
...
...
@@ -294,8 +351,7 @@ static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm,
ARRAY_SIZE
(
time_event_response
),
iwl_mvm_time_event_response
,
te_data
);
ret
=
iwl_mvm_send_cmd_pdu
(
mvm
,
TIME_EVENT_CMD
,
CMD_SYNC
,
sizeof
(
*
te_cmd
),
te_cmd
);
ret
=
iwl_mvm_send_time_event_cmd
(
mvm
,
te_cmd
);
if
(
ret
)
{
IWL_ERR
(
mvm
,
"Couldn't send TIME_EVENT_CMD: %d
\n
"
,
ret
);
iwl_remove_notification
(
&
mvm
->
notif_wait
,
&
wait_time_event
);
...
...
@@ -322,7 +378,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
{
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
struct
iwl_mvm_time_event_data
*
te_data
=
&
mvmvif
->
time_event_data
;
struct
iwl_time_event_cmd
time_cmd
=
{};
struct
iwl_time_event_cmd
_v2
time_cmd
=
{};
lockdep_assert_held
(
&
mvm
->
mutex
);
...
...
@@ -356,17 +412,14 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
time_cmd
.
apply_time
=
cpu_to_le32
(
iwl_read_prph
(
mvm
->
trans
,
DEVICE_SYSTEM_TIME_REG
));
time_cmd
.
dep_policy
=
TE_INDEPENDENT
;
time_cmd
.
is_present
=
cpu_to_le32
(
1
);
time_cmd
.
max_frags
=
cpu_to_le32
(
TE_FRAG_NONE
);
time_cmd
.
max_frags
=
TE_V2_FRAG_NONE
;
time_cmd
.
max_delay
=
cpu_to_le32
(
500
);
/* TODO: why do we need to interval = bi if it is not periodic? */
time_cmd
.
interval
=
cpu_to_le32
(
1
);
time_cmd
.
interval_reciprocal
=
cpu_to_le32
(
iwl_mvm_reciprocal
(
1
));
time_cmd
.
duration
=
cpu_to_le32
(
duration
);
time_cmd
.
repeat
=
cpu_to_le32
(
1
)
;
time_cmd
.
notify
=
cpu_to_le32
(
TE
_NOTIF_HOST_EVENT_START
|
TE_NOTIF_HOST_EVENT_END
);
time_cmd
.
repeat
=
1
;
time_cmd
.
policy
=
cpu_to_le16
(
TE_V2
_NOTIF_HOST_EVENT_START
|
TE_
V2_
NOTIF_HOST_EVENT_END
);
iwl_mvm_time_event_send_add
(
mvm
,
vif
,
te_data
,
&
time_cmd
);
}
...
...
@@ -380,7 +433,7 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
struct
iwl_mvm_vif
*
mvmvif
,
struct
iwl_mvm_time_event_data
*
te_data
)
{
struct
iwl_time_event_cmd
time_cmd
=
{};
struct
iwl_time_event_cmd
_v2
time_cmd
=
{};
u32
id
,
uid
;
int
ret
;
...
...
@@ -417,8 +470,7 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
cpu_to_le32
(
FW_CMD_ID_AND_COLOR
(
mvmvif
->
id
,
mvmvif
->
color
));
IWL_DEBUG_TE
(
mvm
,
"Removing TE 0x%x
\n
"
,
le32_to_cpu
(
time_cmd
.
id
));
ret
=
iwl_mvm_send_cmd_pdu
(
mvm
,
TIME_EVENT_CMD
,
CMD_SYNC
,
sizeof
(
time_cmd
),
&
time_cmd
);
ret
=
iwl_mvm_send_time_event_cmd
(
mvm
,
&
time_cmd
);
if
(
WARN_ON
(
ret
))
return
;
}
...
...
@@ -438,7 +490,7 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
{
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
struct
iwl_mvm_time_event_data
*
te_data
=
&
mvmvif
->
time_event_data
;
struct
iwl_time_event_cmd
time_cmd
=
{};
struct
iwl_time_event_cmd
_v2
time_cmd
=
{};
lockdep_assert_held
(
&
mvm
->
mutex
);
if
(
te_data
->
running
)
{
...
...
@@ -469,8 +521,6 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
}
time_cmd
.
apply_time
=
cpu_to_le32
(
0
);
time_cmd
.
dep_policy
=
cpu_to_le32
(
TE_INDEPENDENT
);
time_cmd
.
is_present
=
cpu_to_le32
(
1
);
time_cmd
.
interval
=
cpu_to_le32
(
1
);
/*
...
...
@@ -479,12 +529,12 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* scheduled. To improve the chances of it being scheduled, allow them
* to be fragmented, and in addition allow them to be delayed.
*/
time_cmd
.
max_frags
=
cpu_to_le32
(
MSEC_TO_TU
(
duration
)
/
20
);
time_cmd
.
max_frags
=
min
(
MSEC_TO_TU
(
duration
)
/
50
,
TE_V2_FRAG_ENDLESS
);
time_cmd
.
max_delay
=
cpu_to_le32
(
MSEC_TO_TU
(
duration
/
2
));
time_cmd
.
duration
=
cpu_to_le32
(
MSEC_TO_TU
(
duration
));
time_cmd
.
repeat
=
cpu_to_le32
(
1
)
;
time_cmd
.
notify
=
cpu_to_le32
(
TE
_NOTIF_HOST_EVENT_START
|
TE_NOTIF_HOST_EVENT_END
);
time_cmd
.
repeat
=
1
;
time_cmd
.
policy
=
cpu_to_le16
(
TE_V2
_NOTIF_HOST_EVENT_START
|
TE_
V2_
NOTIF_HOST_EVENT_END
);
return
iwl_mvm_time_event_send_add
(
mvm
,
vif
,
te_data
,
&
time_cmd
);
}
...
...
drivers/net/wireless/iwlwifi/pcie/drv.c
浏览文件 @
24de851b
...
...
@@ -325,15 +325,15 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
int
ret
;
iwl_trans
=
iwl_trans_pcie_alloc
(
pdev
,
ent
,
cfg
);
if
(
iwl_trans
==
NULL
)
return
-
ENOMEM
;
if
(
IS_ERR
(
iwl_trans
)
)
return
PTR_ERR
(
iwl_trans
)
;
pci_set_drvdata
(
pdev
,
iwl_trans
);
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
iwl_trans
);
trans_pcie
->
drv
=
iwl_drv_start
(
iwl_trans
,
cfg
);
if
(
IS_ERR
_OR_NULL
(
trans_pcie
->
drv
))
{
if
(
IS_ERR
(
trans_pcie
->
drv
))
{
ret
=
PTR_ERR
(
trans_pcie
->
drv
);
goto
out_free_trans
;
}
...
...
drivers/net/wireless/iwlwifi/pcie/rx.c
浏览文件 @
24de851b
...
...
@@ -112,15 +112,16 @@
*/
static
int
iwl_rxq_space
(
const
struct
iwl_rxq
*
rxq
)
{
int
s
=
rxq
->
read
-
rxq
->
write
;
if
(
s
<=
0
)
s
+=
RX_QUEUE_SIZE
;
/* keep some buffer to not confuse full and empty queue */
s
-=
2
;
if
(
s
<
0
)
s
=
0
;
return
s
;
/* Make sure RX_QUEUE_SIZE is a power of 2 */
BUILD_BUG_ON
(
RX_QUEUE_SIZE
&
(
RX_QUEUE_SIZE
-
1
));
/*
* There can be up to (RX_QUEUE_SIZE - 1) free slots, to avoid ambiguity
* between empty and completely full queues.
* The following is equivalent to modulo by RX_QUEUE_SIZE and is well
* defined for negative dividends.
*/
return
(
rxq
->
read
-
rxq
->
write
-
1
)
&
(
RX_QUEUE_SIZE
-
1
);
}
/*
...
...
@@ -1128,6 +1129,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
struct
iwl_trans
*
trans
=
data
;
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
u32
inta
,
inta_mask
;
irqreturn_t
ret
=
IRQ_NONE
;
lockdep_assert_held
(
&
trans_pcie
->
irq_lock
);
...
...
@@ -1176,10 +1178,8 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
/* the thread will service interrupts and re-enable them */
if
(
likely
(
inta
))
return
IRQ_WAKE_THREAD
;
else
if
(
test_bit
(
STATUS_INT_ENABLED
,
&
trans_pcie
->
status
)
&&
!
trans_pcie
->
inta
)
iwl_enable_interrupts
(
trans
);
return
IRQ_HANDLED
;
ret
=
IRQ_HANDLED
;
none:
/* re-enable interrupts here since we don't have anything to service. */
...
...
@@ -1188,7 +1188,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
!
trans_pcie
->
inta
)
iwl_enable_interrupts
(
trans
);
return
IRQ_NONE
;
return
ret
;
}
/* interrupt handler using ict table, with this interrupt driver will
...
...
@@ -1207,6 +1207,7 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
u32
val
=
0
;
u32
read
;
unsigned
long
flags
;
irqreturn_t
ret
=
IRQ_NONE
;
if
(
!
trans
)
return
IRQ_NONE
;
...
...
@@ -1219,7 +1220,7 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
* use legacy interrupt.
*/
if
(
unlikely
(
!
trans_pcie
->
use_ict
))
{
irqreturn_t
ret
=
iwl_pcie_isr
(
irq
,
data
);
ret
=
iwl_pcie_isr
(
irq
,
data
);
spin_unlock_irqrestore
(
&
trans_pcie
->
irq_lock
,
flags
);
return
ret
;
}
...
...
@@ -1288,17 +1289,9 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
if
(
likely
(
inta
))
{
spin_unlock_irqrestore
(
&
trans_pcie
->
irq_lock
,
flags
);
return
IRQ_WAKE_THREAD
;
}
else
if
(
test_bit
(
STATUS_INT_ENABLED
,
&
trans_pcie
->
status
)
&&
!
trans_pcie
->
inta
)
{
/* Allow interrupt if was disabled by this handler and
* no tasklet was schedules, We should not enable interrupt,
* tasklet will enable it.
*/
iwl_enable_interrupts
(
trans
);
}
spin_unlock_irqrestore
(
&
trans_pcie
->
irq_lock
,
flags
);
return
IRQ_HANDLED
;
ret
=
IRQ_HANDLED
;
none:
/* re-enable interrupts here since we don't have anything to service.
...
...
@@ -1309,5 +1302,5 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
iwl_enable_interrupts
(
trans
);
spin_unlock_irqrestore
(
&
trans_pcie
->
irq_lock
,
flags
);
return
IRQ_NONE
;
return
ret
;
}
drivers/net/wireless/iwlwifi/pcie/trans.c
浏览文件 @
24de851b
...
...
@@ -1386,9 +1386,10 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
trans
=
kzalloc
(
sizeof
(
struct
iwl_trans
)
+
sizeof
(
struct
iwl_trans_pcie
),
GFP_KERNEL
);
if
(
!
trans
)
return
NULL
;
if
(
!
trans
)
{
err
=
-
ENOMEM
;
goto
out
;
}
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
...
...
@@ -1411,10 +1412,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
PCIE_LINK_STATE_CLKPM
);
}
if
(
pci_enable_device
(
pdev
))
{
err
=
-
ENODEV
;
err
=
pci_enable_device
(
pdev
);
if
(
err
)
goto
out_no_pci
;
}
pci_set_master
(
pdev
);
...
...
@@ -1483,17 +1483,20 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
SLAB_HWCACHE_ALIGN
,
NULL
);
if
(
!
trans
->
dev_cmd_pool
)
if
(
!
trans
->
dev_cmd_pool
)
{
err
=
-
ENOMEM
;
goto
out_pci_disable_msi
;
}
trans_pcie
->
inta_mask
=
CSR_INI_SET_MASK
;
if
(
iwl_pcie_alloc_ict
(
trans
))
goto
out_free_cmd_pool
;
if
(
request_threaded_irq
(
pdev
->
irq
,
iwl_pcie_isr_ict
,
iwl_pcie_irq_handler
,
IRQF_SHARED
,
DRV_NAME
,
trans
))
{
err
=
request_threaded_irq
(
pdev
->
irq
,
iwl_pcie_isr_ict
,
iwl_pcie_irq_handler
,
IRQF_SHARED
,
DRV_NAME
,
trans
);
if
(
err
)
{
IWL_ERR
(
trans
,
"Error allocating IRQ %d
\n
"
,
pdev
->
irq
);
goto
out_free_ict
;
}
...
...
@@ -1512,5 +1515,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
pci_disable_device
(
pdev
);
out_no_pci:
kfree
(
trans
);
return
NULL
;
out:
return
ERR_PTR
(
err
);
}
drivers/net/wireless/iwlwifi/pcie/tx.c
浏览文件 @
24de851b
...
...
@@ -65,18 +65,30 @@
***************************************************/
static
int
iwl_queue_space
(
const
struct
iwl_queue
*
q
)
{
int
s
=
q
->
read_ptr
-
q
->
write_ptr
;
if
(
q
->
read_ptr
>
q
->
write_ptr
)
s
-=
q
->
n_bd
;
if
(
s
<=
0
)
s
+=
q
->
n_window
;
/* keep some reserve to not confuse empty and full situations */
s
-=
2
;
if
(
s
<
0
)
s
=
0
;
return
s
;
unsigned
int
max
;
unsigned
int
used
;
/*
* To avoid ambiguity between empty and completely full queues, there
* should always be less than q->n_bd elements in the queue.
* If q->n_window is smaller than q->n_bd, there is no need to reserve
* any queue entries for this purpose.
*/
if
(
q
->
n_window
<
q
->
n_bd
)
max
=
q
->
n_window
;
else
max
=
q
->
n_bd
-
1
;
/*
* q->n_bd is a power of 2, so the following is equivalent to modulo by
* q->n_bd and is well defined for negative dividends.
*/
used
=
(
q
->
write_ptr
-
q
->
read_ptr
)
&
(
q
->
n_bd
-
1
);
if
(
WARN_ON
(
used
>
max
))
return
0
;
return
max
-
used
;
}
/*
...
...
@@ -826,7 +838,7 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
sizeof
(
struct
iwl_txq
),
GFP_KERNEL
);
if
(
!
trans_pcie
->
txq
)
{
IWL_ERR
(
trans
,
"Not enough memory for txq
\n
"
);
ret
=
ENOMEM
;
ret
=
-
ENOMEM
;
goto
error
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录