Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
24de851b
Commit
24de851b
authored
Aug 16, 2013
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-john' of
git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
parents
d0746663
89716344
Changes
20
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
809 additions
and
713 deletions
+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
No files found.
drivers/net/wireless/iwlwifi/Kconfig
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
24de851b
This diff is collapsed.
Click to expand it.
drivers/net/wireless/iwlwifi/mvm/mac80211.c
View file @
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
View file @
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
View file @
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
View file @
24de851b
This diff is collapsed.
Click to expand it.
drivers/net/wireless/iwlwifi/mvm/rs.h
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment