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
d878b3af
Commit
d878b3af
authored
Jul 23, 2014
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
16e75453
f697267f
Changes
21
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
966 additions
and
395 deletions
+966
-395
drivers/net/wireless/iwlwifi/Kconfig
drivers/net/wireless/iwlwifi/Kconfig
+13
-12
drivers/net/wireless/iwlwifi/iwl-8000.c
drivers/net/wireless/iwlwifi/iwl-8000.c
+4
-0
drivers/net/wireless/iwlwifi/iwl-config.h
drivers/net/wireless/iwlwifi/iwl-config.h
+2
-0
drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
+15
-2
drivers/net/wireless/iwlwifi/iwl-modparams.h
drivers/net/wireless/iwlwifi/iwl-modparams.h
+1
-1
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/iwlwifi/iwl-trans.h
+12
-9
drivers/net/wireless/iwlwifi/mvm/coex.c
drivers/net/wireless/iwlwifi/mvm/coex.c
+84
-109
drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
+22
-97
drivers/net/wireless/iwlwifi/mvm/debugfs.c
drivers/net/wireless/iwlwifi/mvm/debugfs.c
+84
-20
drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
+2
-0
drivers/net/wireless/iwlwifi/mvm/fw-api.h
drivers/net/wireless/iwlwifi/mvm/fw-api.h
+67
-0
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+13
-2
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
+288
-95
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/mvm.h
+44
-8
drivers/net/wireless/iwlwifi/mvm/nvm.c
drivers/net/wireless/iwlwifi/mvm/nvm.c
+2
-2
drivers/net/wireless/iwlwifi/mvm/ops.c
drivers/net/wireless/iwlwifi/mvm/ops.c
+12
-2
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/wireless/iwlwifi/mvm/sta.c
+13
-11
drivers/net/wireless/iwlwifi/mvm/time-event.c
drivers/net/wireless/iwlwifi/mvm/time-event.c
+75
-14
drivers/net/wireless/iwlwifi/mvm/tt.c
drivers/net/wireless/iwlwifi/mvm/tt.c
+9
-3
drivers/net/wireless/iwlwifi/mvm/tx.c
drivers/net/wireless/iwlwifi/mvm/tx.c
+10
-0
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/iwlwifi/pcie/trans.c
+194
-8
No files found.
drivers/net/wireless/iwlwifi/Kconfig
View file @
d878b3af
...
...
@@ -20,16 +20,17 @@ config IWLWIFI
Intel 2000 Series Wi-Fi Adapters
Intel 7260 Wi-Fi Adapter
Intel 3160 Wi-Fi Adapter
Intel 7265 Wi-Fi Adapter
This driver uses the kernel's mac80211 subsystem.
In order to use this driver, you will need a
microcode (uCode)
In order to use this driver, you will need a
firmware
image for it. You can obtain the microcode from:
<http://
intellinuxwireless.org/
>.
<http://
wireless.kernel.org/en/users/Drivers/iwlwifi
>.
The
microcod
e is typically installed in /lib/firmware. You can
The
firmwar
e is typically installed in /lib/firmware. You can
look in the hotplug script /etc/hotplug/firmware.agent to
determine which directory FIRMWARE_DIR is set to when the script
runs.
...
...
@@ -39,9 +40,10 @@ config IWLWIFI
say M here and read <file:Documentation/kbuild/modules.txt>. The
module will be called iwlwifi.
if IWLWIFI
config IWLWIFI_LEDS
bool
depends on IWLWIFI
depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI
select LEDS_TRIGGERS
select MAC80211_LEDS
...
...
@@ -49,7 +51,7 @@ config IWLWIFI_LEDS
config IWLDVM
tristate "Intel Wireless WiFi DVM Firmware support"
depends on
IWLWIFI
depends on
m
default IWLWIFI
help
This is the driver that supports the DVM firmware which is
...
...
@@ -58,7 +60,7 @@ config IWLDVM
config IWLMVM
tristate "Intel Wireless WiFi MVM Firmware support"
depends on
IWLWIFI
depends on
m
help
This is the driver that supports the MVM firmware which is
currently only available for 7260 and 3160 devices.
...
...
@@ -70,7 +72,7 @@ config IWLWIFI_OPMODE_MODULAR
default y if IWLMVM=m
comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM"
depends on IWL
WIFI && IWL
DVM=n && IWLMVM=n
depends on IWLDVM=n && IWLMVM=n
config IWLWIFI_BCAST_FILTERING
bool "Enable broadcast filtering"
...
...
@@ -86,11 +88,9 @@ config IWLWIFI_BCAST_FILTERING
expect incoming broadcasts for their normal operations.
menu "Debugging Options"
depends on IWLWIFI
config IWLWIFI_DEBUG
bool "Enable full debugging output in the iwlwifi driver"
depends on IWLWIFI
---help---
This option will enable debug tracing output for the iwlwifi drivers
...
...
@@ -115,7 +115,7 @@ config IWLWIFI_DEBUG
config IWLWIFI_DEBUGFS
bool "iwlwifi debugfs support"
depends on
IWLWIFI &&
MAC80211_DEBUGFS
depends on MAC80211_DEBUGFS
---help---
Enable creation of debugfs files for the iwlwifi drivers. This
is a low-impact option that allows getting insight into the
...
...
@@ -123,13 +123,12 @@ config IWLWIFI_DEBUGFS
config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
bool "Experimental uCode support"
depends on IWLWIFI
&& IWLWIFI
_DEBUG
depends on IWLWIFI_DEBUG
---help---
Enable use of experimental ucode for testing and debugging.
config IWLWIFI_DEVICE_TRACING
bool "iwlwifi device access tracing"
depends on IWLWIFI
depends on EVENT_TRACING
help
Say Y here to trace all commands, including TX frames and IO
...
...
@@ -145,3 +144,5 @@ config IWLWIFI_DEVICE_TRACING
If unsure, say Y so we can help you better when problems
occur.
endmenu
endif
drivers/net/wireless/iwlwifi/iwl-8000.c
View file @
d878b3af
...
...
@@ -85,6 +85,9 @@
#define NVM_HW_SECTION_NUM_FAMILY_8000 10
#define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000.bin"
/* Max SDIO RX aggregation size of the ADDBA request/response */
#define MAX_RX_AGG_SIZE_8260_SDIO 28
static
const
struct
iwl_base_params
iwl8000_base_params
=
{
.
eeprom_size
=
OTP_LOW_IMAGE_SIZE_FAMILY_8000
,
.
num_of_queues
=
IWLAGN_NUM_QUEUES
,
...
...
@@ -129,6 +132,7 @@ const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
.
nvm_ver
=
IWL8000_NVM_VERSION
,
.
nvm_calib_ver
=
IWL8000_TX_POWER_VERSION
,
.
default_nvm_file
=
DEFAULT_NVM_FILE_FAMILY_8000
,
.
max_rx_agg_size
=
MAX_RX_AGG_SIZE_8260_SDIO
,
};
MODULE_FIRMWARE
(
IWL8000_MODULE_FIRMWARE
(
IWL8000_UCODE_API_OK
));
drivers/net/wireless/iwlwifi/iwl-config.h
View file @
d878b3af
...
...
@@ -240,6 +240,7 @@ struct iwl_pwr_tx_backoff {
* @d0i3: device uses d0i3 instead of d3
* @nvm_hw_section_num: the ID of the HW NVM section
* @pwr_tx_backoffs: translation table between power limits and backoffs
* @max_rx_agg_size: max RX aggregation size of the ADDBA request/response
*
* We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs
...
...
@@ -276,6 +277,7 @@ struct iwl_cfg {
const
struct
iwl_pwr_tx_backoff
*
pwr_tx_backoffs
;
bool
no_power_up_nic_in_init
;
const
char
*
default_nvm_file
;
unsigned
int
max_rx_agg_size
;
};
/*
...
...
drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
View file @
d878b3af
...
...
@@ -70,21 +70,24 @@
/**
* enum iwl_fw_error_dump_type - types of data in the dump file
* @IWL_FW_ERROR_DUMP_SRAM:
* @IWL_FW_ERROR_DUMP_
REG:
* @IWL_FW_ERROR_DUMP_
CSR: Control Status Registers - from offset 0
* @IWL_FW_ERROR_DUMP_RXF:
* @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as
* &struct iwl_fw_error_dump_txcmd packets
* @IWL_FW_ERROR_DUMP_DEV_FW_INFO: struct %iwl_fw_error_dump_info
* info on the device / firmware.
* @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor
* @IWL_FW_ERROR_DUMP_PRPH: range of periphery registers - there can be several
* sections like this in a single file.
*/
enum
iwl_fw_error_dump_type
{
IWL_FW_ERROR_DUMP_SRAM
=
0
,
IWL_FW_ERROR_DUMP_
REG
=
1
,
IWL_FW_ERROR_DUMP_
CSR
=
1
,
IWL_FW_ERROR_DUMP_RXF
=
2
,
IWL_FW_ERROR_DUMP_TXCMD
=
3
,
IWL_FW_ERROR_DUMP_DEV_FW_INFO
=
4
,
IWL_FW_ERROR_DUMP_FW_MONITOR
=
5
,
IWL_FW_ERROR_DUMP_PRPH
=
6
,
IWL_FW_ERROR_DUMP_MAX
,
};
...
...
@@ -162,6 +165,16 @@ struct iwl_fw_error_dump_fw_mon {
u8
data
[];
}
__packed
;
/**
* struct iwl_fw_error_dump_prph - periphery registers data
* @prph_start: address of the first register in this chunk
* @data: the content of the registers
*/
struct
iwl_fw_error_dump_prph
{
__le32
prph_start
;
__le32
data
[];
};
/**
* iwl_fw_error_next_data - advance fw error dump data pointer
* @data: previous data block
...
...
drivers/net/wireless/iwlwifi/iwl-modparams.h
View file @
d878b3af
...
...
@@ -99,7 +99,7 @@ enum iwl_disable_11n {
* @wd_disable: disable stuck queue check, default = 1
* @bt_coex_active: enable bt coex, default = true
* @led_mode: system default, default = 0
* @power_save:
dis
able power save, default = false
* @power_save:
en
able power save, default = false
* @power_level: power level, default = 1
* @debug_level: levels are IWL_DL_*
* @ant_coupling: antenna coupling in dB, default = 0
...
...
drivers/net/wireless/iwlwifi/iwl-trans.h
View file @
d878b3af
...
...
@@ -394,6 +394,11 @@ struct iwl_trans_config {
const
char
*
const
*
command_names
;
};
struct
iwl_trans_dump_data
{
u32
len
;
u8
data
[];
};
struct
iwl_trans
;
/**
...
...
@@ -461,10 +466,8 @@ struct iwl_trans;
* @unref: release a reference previously taken with @ref. Note that
* initially the reference count is 1, making an initial @unref
* necessary to allow low power states.
* @dump_data: fill a data dump with debug data, maybe containing last
* TX'ed commands and similar. When called with a NULL buffer and
* zero buffer length, provide only the (estimated) required buffer
* length. Return the used buffer length.
* @dump_data: return a vmalloc'ed buffer with debug data, maybe containing last
* TX'ed commands and similar. The buffer will be vfree'd by the caller.
* Note that the transport must fill in the proper file headers.
*/
struct
iwl_trans_ops
{
...
...
@@ -518,7 +521,7 @@ struct iwl_trans_ops {
void
(
*
unref
)(
struct
iwl_trans
*
trans
);
#ifdef CONFIG_IWLWIFI_DEBUGFS
u32
(
*
dump_data
)(
struct
iwl_trans
*
trans
,
void
*
buf
,
u32
buflen
);
struct
iwl_trans_dump_data
*
(
*
dump_data
)(
struct
iwl_trans
*
trans
);
#endif
};
...
...
@@ -685,12 +688,12 @@ static inline void iwl_trans_unref(struct iwl_trans *trans)
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
static
inline
u32
iwl_trans_dump_data
(
struct
iwl_trans
*
trans
,
void
*
buf
,
u32
buflen
)
static
inline
struct
iwl_trans_dump_data
*
iwl_trans_dump_data
(
struct
iwl_trans
*
trans
)
{
if
(
!
trans
->
ops
->
dump_data
)
return
0
;
return
trans
->
ops
->
dump_data
(
trans
,
buf
,
buflen
);
return
NULL
;
return
trans
->
ops
->
dump_data
(
trans
);
}
#endif
...
...
drivers/net/wireless/iwlwifi/mvm/coex.c
View file @
d878b3af
This diff is collapsed.
Click to expand it.
drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
View file @
d878b3af
...
...
@@ -649,10 +649,6 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm)
sizeof
(
iwl_bt_prio_boost
));
memcpy
(
&
bt_cmd
->
bt4_multiprio_lut
,
iwl_bt_mprio_lut
,
sizeof
(
iwl_bt_mprio_lut
));
bt_cmd
->
kill_ack_msk
=
cpu_to_le32
(
iwl_bt_ack_kill_msk
[
BT_KILL_MSK_DEFAULT
]);
bt_cmd
->
kill_cts_msk
=
cpu_to_le32
(
iwl_bt_cts_kill_msk
[
BT_KILL_MSK_DEFAULT
]);
send_cmd:
memset
(
&
mvm
->
last_bt_notif_old
,
0
,
sizeof
(
mvm
->
last_bt_notif_old
));
...
...
@@ -664,12 +660,13 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm)
return
ret
;
}
static
int
iwl_mvm_bt_udpate_ctrl_kill_msk
(
struct
iwl_mvm
*
mvm
,
bool
reduced_tx_power
)
static
int
iwl_mvm_bt_udpate_ctrl_kill_msk
(
struct
iwl_mvm
*
mvm
)
{
enum
iwl_bt_kill_msk
bt_kill_msk
;
struct
iwl_bt_coex_cmd_old
*
bt_cmd
;
struct
iwl_bt_coex_profile_notif_old
*
notif
=
&
mvm
->
last_bt_notif_old
;
u32
primary_lut
=
le32_to_cpu
(
notif
->
primary_ch_lut
);
u32
ag
=
le32_to_cpu
(
notif
->
bt_activity_grading
);
struct
iwl_bt_coex_cmd_old
*
bt_cmd
;
u8
ack_kill_msk
,
cts_kill_msk
;
struct
iwl_host_cmd
cmd
=
{
.
id
=
BT_CONFIG
,
.
data
[
0
]
=
&
bt_cmd
,
...
...
@@ -680,31 +677,15 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
lockdep_assert_held
(
&
mvm
->
mutex
);
if
(
reduced_tx_power
)
{
/* Reduced Tx power has precedence on the type of the profile */
bt_kill_msk
=
BT_KILL_MSK_REDUCED_TXPOW
;
}
else
{
/* Low latency BT profile is active: give higher prio to BT */
if
(
BT_MBOX_MSG
(
notif
,
3
,
SCO_STATE
)
||
BT_MBOX_MSG
(
notif
,
3
,
A2DP_STATE
)
||
BT_MBOX_MSG
(
notif
,
3
,
SNIFF_STATE
))
bt_kill_msk
=
BT_KILL_MSK_SCO_HID_A2DP
;
else
bt_kill_msk
=
BT_KILL_MSK_DEFAULT
;
}
IWL_DEBUG_COEX
(
mvm
,
"Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive
\n
"
,
bt_kill_msk
,
BT_MBOX_MSG
(
notif
,
3
,
SCO_STATE
)
?
""
:
"in"
,
BT_MBOX_MSG
(
notif
,
3
,
A2DP_STATE
)
?
""
:
"in"
,
BT_MBOX_MSG
(
notif
,
3
,
SNIFF_STATE
)
?
""
:
"in"
);
ack_kill_msk
=
iwl_bt_ack_kill_msk
[
ag
][
primary_lut
];
cts_kill_msk
=
iwl_bt_cts_kill_msk
[
ag
][
primary_lut
];
/* Don't send HCMD if there is no update */
if
(
bt_kill_msk
==
mvm
->
bt
_kill_msk
)
if
(
mvm
->
bt_ack_kill_msk
[
0
]
==
ack_kill_msk
&&
mvm
->
bt_cts_kill_msk
[
0
]
==
cts
_kill_msk
)
return
0
;
mvm
->
bt_kill_msk
=
bt_kill_msk
;
mvm
->
bt_ack_kill_msk
[
0
]
=
ack_kill_msk
;
mvm
->
bt_cts_kill_msk
[
0
]
=
cts_kill_msk
;
bt_cmd
=
kzalloc
(
sizeof
(
*
bt_cmd
),
GFP_KERNEL
);
if
(
!
bt_cmd
)
...
...
@@ -712,16 +693,12 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
cmd
.
data
[
0
]
=
bt_cmd
;
bt_cmd
->
flags
=
cpu_to_le32
(
BT_COEX_NW_OLD
);
bt_cmd
->
kill_ack_msk
=
cpu_to_le32
(
iwl_bt_
ack_kill_msk
[
bt
_kill_msk
]);
bt_cmd
->
kill_cts_msk
=
cpu_to_le32
(
iwl_bt_ct
s_kill_msk
[
bt
_kill_msk
]);
bt_cmd
->
kill_ack_msk
=
cpu_to_le32
(
iwl_bt_
ctl_kill_msk
[
ack
_kill_msk
]);
bt_cmd
->
kill_cts_msk
=
cpu_to_le32
(
iwl_bt_ct
l_kill_msk
[
cts
_kill_msk
]);
bt_cmd
->
valid_bit_msk
|=
cpu_to_le32
(
BT_VALID_ENABLE
|
BT_VALID_KILL_ACK
|
BT_VALID_KILL_CTS
);
IWL_DEBUG_COEX
(
mvm
,
"ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x
\n
"
,
iwl_bt_ack_kill_msk
[
bt_kill_msk
],
iwl_bt_cts_kill_msk
[
bt_kill_msk
]);
ret
=
iwl_mvm_send_cmd
(
mvm
,
&
cmd
);
kfree
(
bt_cmd
);
...
...
@@ -777,8 +754,6 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
struct
iwl_bt_iterator_data
{
struct
iwl_bt_coex_profile_notif_old
*
notif
;
struct
iwl_mvm
*
mvm
;
u32
num_bss_ifaces
;
bool
reduced_tx_power
;
struct
ieee80211_chanctx_conf
*
primary
;
struct
ieee80211_chanctx_conf
*
secondary
;
bool
primary_ll
;
...
...
@@ -814,22 +789,12 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
switch
(
vif
->
type
)
{
case
NL80211_IFTYPE_STATION
:
/* Count BSSes vifs */
data
->
num_bss_ifaces
++
;
/* default smps_mode for BSS / P2P client is AUTOMATIC */
smps_mode
=
IEEE80211_SMPS_AUTOMATIC
;
break
;
case
NL80211_IFTYPE_AP
:
/* default smps_mode for AP / GO is OFF */
smps_mode
=
IEEE80211_SMPS_OFF
;
if
(
!
mvmvif
->
ap_ibss_active
)
{
iwl_mvm_update_smps
(
mvm
,
vif
,
IWL_MVM_SMPS_REQ_BT_COEX
,
smps_mode
);
if
(
!
mvmvif
->
ap_ibss_active
)
return
;
}
/* the Ack / Cts kill mask must be default if AP / GO */
data
->
reduced_tx_power
=
false
;
break
;
default:
return
;
...
...
@@ -840,11 +805,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
/* If channel context is invalid or not on 2.4GHz .. */
if
((
!
chanctx_conf
||
chanctx_conf
->
def
.
chan
->
band
!=
IEEE80211_BAND_2GHZ
))
{
/* ... relax constraints and disable rssi events */
iwl_mvm_update_smps
(
mvm
,
vif
,
IWL_MVM_SMPS_REQ_BT_COEX
,
smps_mode
);
data
->
reduced_tx_power
=
false
;
if
(
vif
->
type
==
NL80211_IFTYPE_STATION
)
{
/* ... relax constraints and disable rssi events */
iwl_mvm_update_smps
(
mvm
,
vif
,
IWL_MVM_SMPS_REQ_BT_COEX
,
smps_mode
);
iwl_mvm_bt_coex_reduced_txp
(
mvm
,
mvmvif
->
ap_sta_id
,
false
);
iwl_mvm_bt_coex_enable_rssi_event
(
mvm
,
vif
,
false
,
0
);
...
...
@@ -869,7 +833,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
mvmvif
->
id
,
data
->
notif
->
bt_status
,
bt_activity_grading
,
smps_mode
);
iwl_mvm_update_smps
(
mvm
,
vif
,
IWL_MVM_SMPS_REQ_BT_COEX
,
smps_mode
);
if
(
vif
->
type
==
NL80211_IFTYPE_STATION
)
iwl_mvm_update_smps
(
mvm
,
vif
,
IWL_MVM_SMPS_REQ_BT_COEX
,
smps_mode
);
/* low latency is always primary */
if
(
iwl_mvm_vif_low_latency
(
mvmvif
))
{
...
...
@@ -920,7 +886,6 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if
(
iwl_get_coex_type
(
mvm
,
vif
)
==
BT_COEX_LOOSE_LUT
||
mvm
->
cfg
->
bt_shared_single_ant
||
!
vif
->
bss_conf
.
assoc
||
!
data
->
notif
->
bt_status
)
{
data
->
reduced_tx_power
=
false
;
iwl_mvm_bt_coex_reduced_txp
(
mvm
,
mvmvif
->
ap_sta_id
,
false
);
iwl_mvm_bt_coex_enable_rssi_event
(
mvm
,
vif
,
false
,
0
);
return
;
...
...
@@ -935,23 +900,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if
(
ave_rssi
>
-
IWL_MVM_BT_COEX_EN_RED_TXP_THRESH
)
{
if
(
iwl_mvm_bt_coex_reduced_txp
(
mvm
,
mvmvif
->
ap_sta_id
,
true
))
IWL_ERR
(
mvm
,
"Couldn't send BT_CONFIG cmd
\n
"
);
/*
* bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the
* BSS / P2P clients have rssi above threshold.
* We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before
* the iteration, if one interface's rssi isn't good enough,
* bt_kill_msk will be set to default values.
*/
}
else
if
(
ave_rssi
<
-
IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH
)
{
if
(
iwl_mvm_bt_coex_reduced_txp
(
mvm
,
mvmvif
->
ap_sta_id
,
false
))
IWL_ERR
(
mvm
,
"Couldn't send BT_CONFIG cmd
\n
"
);
/*
* One interface hasn't rssi above threshold, bt_kill_msk must
* be set to default values.
*/
data
->
reduced_tx_power
=
false
;
}
/* Begin to monitor the RSSI: it may influence the reduced Tx power */
...
...
@@ -963,7 +914,6 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
struct
iwl_bt_iterator_data
data
=
{
.
mvm
=
mvm
,
.
notif
=
&
mvm
->
last_bt_notif_old
,
.
reduced_tx_power
=
true
,
};
struct
iwl_bt_coex_ci_cmd_old
cmd
=
{};
u8
ci_bw_idx
;
...
...
@@ -1037,14 +987,7 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
memcpy
(
&
mvm
->
last_bt_ci_cmd_old
,
&
cmd
,
sizeof
(
cmd
));
}
/*
* If there are no BSS / P2P client interfaces, reduced Tx Power is
* irrelevant since it is based on the RSSI coming from the beacon.
* Use BT_KILL_MSK_DEFAULT in that case.
*/
data
.
reduced_tx_power
=
data
.
reduced_tx_power
&&
data
.
num_bss_ifaces
;
if
(
iwl_mvm_bt_udpate_ctrl_kill_msk
(
mvm
,
data
.
reduced_tx_power
))
if
(
iwl_mvm_bt_udpate_ctrl_kill_msk
(
mvm
))
IWL_ERR
(
mvm
,
"Failed to update the ctrl_kill_msk
\n
"
);
}
...
...
@@ -1115,16 +1058,6 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
return
;
mvmsta
=
iwl_mvm_sta_from_mac80211
(
sta
);
data
->
num_bss_ifaces
++
;
/*
* This interface doesn't support reduced Tx power (because of low
* RSSI probably), then set bt_kill_msk to default values.
*/
if
(
!
mvmsta
->
bt_reduced_txpower
)
data
->
reduced_tx_power
=
false
;
/* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */
}
void
iwl_mvm_bt_rssi_event_old
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
...
...
@@ -1133,7 +1066,6 @@ void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct
iwl_mvm_vif
*
mvmvif
=
(
void
*
)
vif
->
drv_priv
;
struct
iwl_bt_iterator_data
data
=
{
.
mvm
=
mvm
,
.
reduced_tx_power
=
true
,
};
int
ret
;
...
...
@@ -1175,14 +1107,7 @@ void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvm
->
hw
,
IEEE80211_IFACE_ITER_NORMAL
,
iwl_mvm_bt_rssi_iterator
,
&
data
);
/*
* If there are no BSS / P2P client interfaces, reduced Tx Power is
* irrelevant since it is based on the RSSI coming from the beacon.
* Use BT_KILL_MSK_DEFAULT in that case.
*/
data
.
reduced_tx_power
=
data
.
reduced_tx_power
&&
data
.
num_bss_ifaces
;
if
(
iwl_mvm_bt_udpate_ctrl_kill_msk
(
mvm
,
data
.
reduced_tx_power
))
if
(
iwl_mvm_bt_udpate_ctrl_kill_msk
(
mvm
))
IWL_ERR
(
mvm
,
"Failed to update the ctrl_kill_msk
\n
"
);
}
...
...
drivers/net/wireless/iwlwifi/mvm/debugfs.c
View file @
d878b3af
...
...
@@ -146,17 +146,47 @@ static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
iwl_fw_error_dump_file
*
dump_file
=
file
->
private_data
;
struct
iwl_mvm_dump_ptrs
*
dump_ptrs
=
(
void
*
)
file
->
private_data
;
ssize_t
bytes_read
=
0
;
ssize_t
bytes_read_trans
=
0
;
if
(
*
ppos
<
dump_ptrs
->
op_mode_len
)
bytes_read
+=
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
dump_ptrs
->
op_mode_ptr
,
dump_ptrs
->
op_mode_len
);
if
(
bytes_read
<
0
||
*
ppos
<
dump_ptrs
->
op_mode_len
)
return
bytes_read
;
if
(
dump_ptrs
->
trans_ptr
)
{
*
ppos
-=
dump_ptrs
->
op_mode_len
;
bytes_read_trans
=
simple_read_from_buffer
(
user_buf
+
bytes_read
,
count
-
bytes_read
,
ppos
,
dump_ptrs
->
trans_ptr
->
data
,
dump_ptrs
->
trans_ptr
->
len
);
*
ppos
+=
dump_ptrs
->
op_mode_len
;
if
(
bytes_read_trans
>=
0
)
bytes_read
+=
bytes_read_trans
;
else
if
(
!
bytes_read
)
/* propagate the failure */
return
bytes_read_trans
;
}
return
bytes_read
;
return
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
dump_file
,
le32_to_cpu
(
dump_file
->
file_len
));
}
static
int
iwl_dbgfs_fw_error_dump_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
vfree
(
file
->
private_data
);
struct
iwl_mvm_dump_ptrs
*
dump_ptrs
=
(
void
*
)
file
->
private_data
;
vfree
(
dump_ptrs
->
op_mode_ptr
);
vfree
(
dump_ptrs
->
trans_ptr
);
kfree
(
dump_ptrs
);
return
0
;
}
...
...
@@ -514,9 +544,9 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"BT Configuration CMD
\n
"
);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"
\t
ACK Kill Mask 0x%08x
\n
"
,
iwl_bt_
ack_kill_msk
[
mvm
->
bt_kill_msk
]);
iwl_bt_
ctl_kill_msk
[
mvm
->
bt_ack_kill_msk
[
0
]
]);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"
\t
CTS Kill Mask 0x%08x
\n
"
,
iwl_bt_ct
s_kill_msk
[
mvm
->
bt_kill_msk
]);
iwl_bt_ct
l_kill_msk
[
mvm
->
bt_cts_kill_msk
[
0
]
]);
}
else
{
struct
iwl_bt_coex_ci_cmd
*
cmd
=
&
mvm
->
last_bt_ci_cmd
;
...
...
@@ -531,10 +561,19 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
le64_to_cpu
(
cmd
->
bt_secondary_ci
));
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"BT Configuration CMD
\n
"
);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"
\t
ACK Kill Mask 0x%08x
\n
"
,
iwl_bt_ack_kill_msk
[
mvm
->
bt_kill_msk
]);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"
\t
CTS Kill Mask 0x%08x
\n
"
,
iwl_bt_cts_kill_msk
[
mvm
->
bt_kill_msk
]);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"
\t
Primary: ACK Kill Mask 0x%08x
\n
"
,
iwl_bt_ctl_kill_msk
[
mvm
->
bt_ack_kill_msk
[
0
]]);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"
\t
Primary: CTS Kill Mask 0x%08x
\n
"
,
iwl_bt_ctl_kill_msk
[
mvm
->
bt_cts_kill_msk
[
0
]]);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"
\t
Secondary: ACK Kill Mask 0x%08x
\n
"
,
iwl_bt_ctl_kill_msk
[
mvm
->
bt_ack_kill_msk
[
1
]]);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"
\t
Secondary: CTS Kill Mask 0x%08x
\n
"
,
iwl_bt_ctl_kill_msk
[
mvm
->
bt_cts_kill_msk
[
1
]]);
}
mutex_unlock
(
&
mvm
->
mutex
);
...
...
@@ -830,8 +869,14 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
static
ssize_t
iwl_dbgfs_fw_nmi_write
(
struct
iwl_mvm
*
mvm
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
int
ret
=
iwl_mvm_ref_sync
(
mvm
,
IWL_MVM_REF_NMI
);
if
(
ret
)
return
ret
;
iwl_force_nmi
(
mvm
->
trans
);
iwl_mvm_unref
(
mvm
,
IWL_MVM_REF_NMI
);
return
count
;
}
...
...
@@ -1115,11 +1160,11 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
}
#endif
#define PRINT_MVM_REF(ref) do { \
if (
test_bit(ref, mvm->ref_bitmap))
\
pos += scnprintf(buf + pos, bufsz - pos, \
"\t(0x%lx)
%s\n",
\
BIT(ref),
#ref);
\
#define PRINT_MVM_REF(ref) do {
\
if (
mvm->refs[ref])
\
pos += scnprintf(buf + pos, bufsz - pos,
\
"\t(0x%lx)
: %d %s\n",
\
BIT(ref),
mvm->refs[ref], #ref);
\
} while (0)
static
ssize_t
iwl_dbgfs_d0i3_refs_read
(
struct
file
*
file
,
...
...
@@ -1127,12 +1172,17 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
size_t
count
,
loff_t
*
ppos
)
{
struct
iwl_mvm
*
mvm
=
file
->
private_data
;
int
pos
=
0
;
int
i
,
pos
=
0
;
char
buf
[
256
];
const
size_t
bufsz
=
sizeof
(
buf
);
u32
refs
=
0
;
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"taken mvm refs: 0x%lx
\n
"
,
mvm
->
ref_bitmap
[
0
]);
for
(
i
=
0
;
i
<
IWL_MVM_REF_COUNT
;
i
++
)
if
(
mvm
->
refs
[
i
])
refs
|=
BIT
(
i
);
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"taken mvm refs: 0x%x
\n
"
,
refs
);
PRINT_MVM_REF
(
IWL_MVM_REF_UCODE_DOWN
);
PRINT_MVM_REF
(
IWL_MVM_REF_SCAN
);
...
...
@@ -1158,7 +1208,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf,
mutex_lock
(
&
mvm
->
mutex
);
taken
=
test_bit
(
IWL_MVM_REF_USER
,
mvm
->
ref_bitmap
)
;
taken
=
mvm
->
refs
[
IWL_MVM_REF_USER
]
;
if
(
value
==
1
&&
!
taken
)
iwl_mvm_ref
(
mvm
,
IWL_MVM_REF_USER
);
else
if
(
value
==
0
&&
taken
)
...
...
@@ -1194,14 +1244,21 @@ iwl_dbgfs_prph_reg_read(struct file *file,
int
pos
=
0
;
char
buf
[
32
];
const
size_t
bufsz
=
sizeof
(
buf
);
int
ret
;
if
(
!
mvm
->
dbgfs_prph_reg_addr
)
return
-
EINVAL
;
ret
=
iwl_mvm_ref_sync
(
mvm
,
IWL_MVM_REF_PRPH_READ
);
if
(
ret
)
return
ret
;
pos
+=
scnprintf
(
buf
+
pos
,
bufsz
-
pos
,
"Reg 0x%x: (0x%x)
\n
"
,
mvm
->
dbgfs_prph_reg_addr
,
iwl_read_prph
(
mvm
->
trans
,
mvm
->
dbgfs_prph_reg_addr
));
iwl_mvm_unref
(
mvm
,
IWL_MVM_REF_PRPH_READ
);
return
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
pos
);
}
...
...
@@ -1211,6 +1268,7 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
{
u8
args
;
u32
value
;
int
ret
;
args
=
sscanf
(
buf
,
"%i %i"
,
&
mvm
->
dbgfs_prph_reg_addr
,
&
value
);
/* if we only want to set the reg address - nothing more to do */
...
...
@@ -1221,7 +1279,13 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
if
(
args
!=
2
)
return
-
EINVAL
;
ret
=
iwl_mvm_ref_sync
(
mvm
,
IWL_MVM_REF_PRPH_WRITE
);
if
(
ret
)
return
ret
;
iwl_write_prph
(
mvm
->
trans
,
mvm
->
dbgfs_prph_reg_addr
,
value
);
iwl_mvm_unref
(
mvm
,
IWL_MVM_REF_PRPH_WRITE
);
out:
return
count
;
}
...
...
drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
View file @
d878b3af
...
...
@@ -385,6 +385,8 @@ enum iwl_bt_activity_grading {
BT_ON_NO_CONNECTION
=
1
,
BT_LOW_TRAFFIC
=
2
,
BT_HIGH_TRAFFIC
=
3
,
BT_MAX_AG
,
};
/* BT_COEX_BT_ACTIVITY_GRADING_API_E_VER_1 */
enum
iwl_bt_ci_compliance
{
...
...
drivers/net/wireless/iwlwifi/mvm/fw-api.h
View file @
d878b3af
...
...
@@ -133,6 +133,7 @@ enum {
/* Scan offload */
SCAN_OFFLOAD_REQUEST_CMD
=
0x51
,
SCAN_OFFLOAD_ABORT_CMD
=
0x52
,
HOT_SPOT_CMD
=
0x53
,
SCAN_OFFLOAD_COMPLETE
=
0x6D
,
SCAN_OFFLOAD_UPDATE_PROFILES_CMD
=
0x6E
,
SCAN_OFFLOAD_CONFIG_CMD
=
0x6f
,
...
...
@@ -910,6 +911,72 @@ struct iwl_phy_context_cmd {
__le32
dsp_cfg_flags
;
}
__packed
;
/* PHY_CONTEXT_CMD_API_VER_1 */
/*
* Aux ROC command
*
* Command requests the firmware to create a time event for a certain duration
* and remain on the given channel. This is done by using the Aux framework in
* the FW.
* The command was first used for Hot Spot issues - but can be used regardless
* to Hot Spot.
*
* ( HOT_SPOT_CMD 0x53 )
*
* @id_and_color: ID and color of the MAC
* @action: action to perform, one of FW_CTXT_ACTION_*
* @event_unique_id: If the action FW_CTXT_ACTION_REMOVE then the
* event_unique_id should be the id of the time event assigned by ucode.
* Otherwise ignore the event_unique_id.
* @sta_id_and_color: station id and color, resumed during "Remain On Channel"
* activity.
* @channel_info: channel info
* @node_addr: Our MAC Address
* @reserved: reserved for alignment
* @apply_time: GP2 value to start (should always be the current GP2 value)
* @apply_time_max_delay: Maximum apply time delay value in TU. Defines max
* time by which start of the event is allowed to be postponed.
* @duration: event duration in TU To calculate event duration:
* timeEventDuration = min(duration, remainingQuota)
*/
struct
iwl_hs20_roc_req
{
/* COMMON_INDEX_HDR_API_S_VER_1 hdr */
__le32
id_and_color
;
__le32
action
;
__le32
event_unique_id
;
__le32
sta_id_and_color
;
struct
iwl_fw_channel_info
channel_info
;
u8
node_addr
[
ETH_ALEN
];
__le16
reserved
;
__le32
apply_time
;
__le32
apply_time_max_delay
;
__le32
duration
;
}
__packed
;
/* HOT_SPOT_CMD_API_S_VER_1 */
/*
* values for AUX ROC result values
*/
enum
iwl_mvm_hot_spot
{
HOT_SPOT_RSP_STATUS_OK
,
HOT_SPOT_RSP_STATUS_TOO_MANY_EVENTS
,
HOT_SPOT_MAX_NUM_OF_SESSIONS
,
};
/*
* Aux ROC command response
*
* In response to iwl_hs20_roc_req the FW sends this command to notify the
* driver the uid of the timevent.
*
* ( HOT_SPOT_CMD 0x53 )
*
* @event_unique_id: Unique ID of time event assigned by ucode
* @status: Return status 0 is success, all the rest used for specific errors
*/
struct
iwl_hs20_roc_res
{
__le32
event_unique_id
;
__le32
status
;
}
__packed
;
/* HOT_SPOT_RSP_API_S_VER_1 */
#define IWL_RX_INFO_PHY_CNT 8
#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1
#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff
...
...
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
View file @
d878b3af
...
...
@@ -1074,8 +1074,12 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
/* Fill the common data for all mac context types */
iwl_mvm_mac_ctxt_cmd_common
(
mvm
,
vif
,
&
cmd
,
action
);
/* Also enable probe requests to pass */
cmd
.
filter_flags
|=
cpu_to_le32
(
MAC_FILTER_IN_PROBE_REQUEST
);
/*
* pass probe requests and beacons from other APs (needed
* for ht protection)
*/
cmd
.
filter_flags
|=
cpu_to_le32
(
MAC_FILTER_IN_PROBE_REQUEST
|
MAC_FILTER_IN_BEACON
);
/* Fill the data specific for ap mode */
iwl_mvm_mac_ctxt_cmd_fill_ap
(
mvm
,
vif
,
&
cmd
.
ap
,
...
...
@@ -1096,6 +1100,13 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
/* Fill the common data for all mac context types */
iwl_mvm_mac_ctxt_cmd_common
(
mvm
,
vif
,
&
cmd
,
action
);
/*
* pass probe requests and beacons from other APs (needed
* for ht protection)
*/
cmd
.
filter_flags
|=
cpu_to_le32
(
MAC_FILTER_IN_PROBE_REQUEST
|
MAC_FILTER_IN_BEACON
);
/* Fill the data specific for GO mode */
iwl_mvm_mac_ctxt_cmd_fill_ap
(
mvm
,
vif
,
&
cmd
.
go
.
ap
,
action
==
FW_CTXT_ACTION_ADD
);
...
...
drivers/net/wireless/iwlwifi/mvm/mac80211.c
View file @
d878b3af
This diff is collapsed.
Click to expand it.
drivers/net/wireless/iwlwifi/mvm/mvm.h
View file @
d878b3af
...
...
@@ -82,6 +82,8 @@
/* RSSI offset for WkP */
#define IWL_RSSI_OFFSET 50
#define IWL_MVM_MISSED_BEACONS_THRESHOLD 8
/* A TimeUnit is 1024 microsecond */
#define MSEC_TO_TU(_msec) (_msec*1000/1024)
/*
* The CSA NoA is scheduled IWL_MVM_CHANNEL_SWITCH_TIME TUs before "beacon 0"
...
...
@@ -126,6 +128,21 @@ struct iwl_mvm_mod_params {
};
extern
struct
iwl_mvm_mod_params
iwlmvm_mod_params
;
/**
* struct iwl_mvm_dump_ptrs - set of pointers needed for the fw-error-dump
*
* @op_mode_ptr: pointer to the buffer coming from the mvm op_mode
* @trans_ptr: pointer to struct %iwl_trans_dump_data which contains the
* transport's data.
* @trans_len: length of the valid data in trans_ptr
* @op_mode_len: length of the valid data in op_mode_ptr
*/
struct
iwl_mvm_dump_ptrs
{
struct
iwl_trans_dump_data
*
trans_ptr
;
void
*
op_mode_ptr
;
u32
op_mode_len
;
};
struct
iwl_mvm_phy_ctxt
{
u16
id
;
u16
color
;
...
...
@@ -249,6 +266,15 @@ enum iwl_mvm_ref_type {
IWL_MVM_REF_TX
,
IWL_MVM_REF_TX_AGG
,
IWL_MVM_REF_ADD_IF
,
IWL_MVM_REF_START_AP
,
IWL_MVM_REF_BSS_CHANGED
,
IWL_MVM_REF_PREPARE_TX
,
IWL_MVM_REF_PROTECT_TDLS
,
IWL_MVM_REF_CHECK_CTKILL
,
IWL_MVM_REF_PRPH_READ
,
IWL_MVM_REF_PRPH_WRITE
,
IWL_MVM_REF_NMI
,
IWL_MVM_REF_TM_CMD
,
IWL_MVM_REF_EXIT_WORK
,
IWL_MVM_REF_COUNT
,
...
...
@@ -327,6 +353,7 @@ struct iwl_mvm_vif {
*/
struct
ieee80211_tx_queue_params
queue_params
[
IEEE80211_NUM_ACS
];
struct
iwl_mvm_time_event_data
time_event_data
;
struct
iwl_mvm_time_event_data
hs_time_event_data
;
struct
iwl_mvm_int_sta
bcast_sta
;
...
...
@@ -606,14 +633,15 @@ struct iwl_mvm {
*/
unsigned
long
fw_key_table
[
BITS_TO_LONGS
(
STA_KEY_MAX_NUM
)];
/* A bitmap of reference types taken by the driver. */
unsigned
long
ref_bitmap
[
BITS_TO_LONGS
(
IWL_MVM_REF_COUNT
)];
/* references taken by the driver and spinlock protecting them */
spinlock_t
refs_lock
;
u8
refs
[
IWL_MVM_REF_COUNT
];
u8
vif_count
;
/* -1 for always, 0 for never, >0 for that many times */
s8
restart_fw
;
void
*
fw_error_dump
;
struct
iwl_mvm_dump_ptrs
*
fw_error_dump
;
#ifdef CONFIG_IWLWIFI_LEDS
struct
led_classdev
led
;
...
...
@@ -647,7 +675,8 @@ struct iwl_mvm {
wait_queue_head_t
d0i3_exit_waitq
;
/* BT-Coex */
u8
bt_kill_msk
;
u8
bt_ack_kill_msk
[
NUM_PHY_CTX
];
u8
bt_cts_kill_msk
[
NUM_PHY_CTX
];
struct
iwl_bt_coex_profile_notif_old
last_bt_notif_old
;
struct
iwl_bt_coex_ci_cmd_old
last_bt_ci_cmd_old
;
...
...
@@ -659,6 +688,9 @@ struct iwl_mvm {
u8
bt_tx_prio
;
enum
iwl_bt_force_ant_mode
bt_force_ant_mode
;
/* Aux ROC */
struct
list_head
aux_roc_te_list
;
/* Thermal Throttling and CTkill */
struct
iwl_mvm_tt_mgmt
thermal_throttle
;
s32
temperature
;
/* Celsius */
...
...
@@ -697,6 +729,7 @@ enum iwl_mvm_status {
IWL_MVM_STATUS_ROC_RUNNING
,
IWL_MVM_STATUS_IN_HW_RESTART
,
IWL_MVM_STATUS_IN_D0I3
,
IWL_MVM_STATUS_ROC_AUX_RUNNING
,
};
static
inline
bool
iwl_mvm_is_radio_killed
(
struct
iwl_mvm
*
mvm
)
...
...
@@ -988,6 +1021,7 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
/* D0i3 */
void
iwl_mvm_ref
(
struct
iwl_mvm
*
mvm
,
enum
iwl_mvm_ref_type
ref_type
);
void
iwl_mvm_unref
(
struct
iwl_mvm
*
mvm
,
enum
iwl_mvm_ref_type
ref_type
);
int
iwl_mvm_ref_sync
(
struct
iwl_mvm
*
mvm
,
enum
iwl_mvm_ref_type
ref_type
);
void
iwl_mvm_d0i3_enable_tx
(
struct
iwl_mvm
*
mvm
,
__le16
*
qos_seq
);
int
_iwl_mvm_exit_d0i3
(
struct
iwl_mvm
*
mvm
);
...
...
@@ -1029,12 +1063,14 @@ int iwl_mvm_rx_ant_coupling_notif_old(struct iwl_mvm *mvm,
enum
iwl_bt_kill_msk
{
BT_KILL_MSK_DEFAULT
,
BT_KILL_MSK_
SCO_HID_A2DP
,
BT_KILL_MSK_
REDUCED_TXPOW
,
BT_KILL_MSK_
NEVER
,
BT_KILL_MSK_
ALWAYS
,
BT_KILL_MSK_MAX
,
};
extern
const
u32
iwl_bt_ack_kill_msk
[
BT_KILL_MSK_MAX
];
extern
const
u32
iwl_bt_cts_kill_msk
[
BT_KILL_MSK_MAX
];
extern
const
u8
iwl_bt_ack_kill_msk
[
BT_MAX_AG
][
BT_COEX_MAX_LUT
];
extern
const
u8
iwl_bt_cts_kill_msk
[
BT_MAX_AG
][
BT_COEX_MAX_LUT
];
extern
const
u32
iwl_bt_ctl_kill_msk
[
BT_KILL_MSK_MAX
];
/* beacon filtering */
#ifdef CONFIG_IWLWIFI_DEBUGFS
...
...
drivers/net/wireless/iwlwifi/mvm/nvm.c
View file @
d878b3af
...
...
@@ -265,7 +265,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
if
(
mvm
->
trans
->
cfg
->
device_family
!=
IWL_DEVICE_FAMILY_8000
)
{
if
(
!
mvm
->
nvm_sections
[
NVM_SECTION_TYPE_SW
].
data
||
!
mvm
->
nvm_sections
[
mvm
->
cfg
->
nvm_hw_section_num
].
data
)
{
IWL_ERR
(
mvm
,
"Can't parse empty NVM sections
\n
"
);
IWL_ERR
(
mvm
,
"Can't parse empty
OTP/
NVM sections
\n
"
);
return
NULL
;
}
}
else
{
...
...
@@ -273,7 +273,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
if
(
!
mvm
->
nvm_sections
[
NVM_SECTION_TYPE_SW
].
data
||
!
mvm
->
nvm_sections
[
NVM_SECTION_TYPE_REGULATORY
].
data
)
{
IWL_ERR
(
mvm
,
"Can't parse empty family 8000 NVM sections
\n
"
);
"Can't parse empty family 8000
OTP/
NVM sections
\n
"
);
return
NULL
;
}
/* MAC_OVERRIDE or at least HW section must exist */
...
...
drivers/net/wireless/iwlwifi/mvm/ops.c
View file @
d878b3af
...
...
@@ -289,6 +289,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD
(
MATCH_FOUND_NOTIFICATION
),
CMD
(
SCAN_OFFLOAD_REQUEST_CMD
),
CMD
(
SCAN_OFFLOAD_ABORT_CMD
),
CMD
(
HOT_SPOT_CMD
),
CMD
(
SCAN_OFFLOAD_COMPLETE
),
CMD
(
SCAN_OFFLOAD_UPDATE_PROFILES_CMD
),
CMD
(
SCAN_ITERATION_COMPLETE
),
...
...
@@ -391,6 +392,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
if
(
!
hw
)
return
NULL
;
if
(
cfg
->
max_rx_agg_size
)
hw
->
max_rx_aggregation_subframes
=
cfg
->
max_rx_agg_size
;
op_mode
=
hw
->
priv
;
op_mode
->
ops
=
&
iwl_mvm_ops
;
...
...
@@ -416,6 +420,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mutex_init
(
&
mvm
->
d0i3_suspend_mutex
);
spin_lock_init
(
&
mvm
->
async_handlers_lock
);
INIT_LIST_HEAD
(
&
mvm
->
time_event_list
);
INIT_LIST_HEAD
(
&
mvm
->
aux_roc_te_list
);
INIT_LIST_HEAD
(
&
mvm
->
async_handlers_list
);
spin_lock_init
(
&
mvm
->
time_event_lock
);
...
...
@@ -425,6 +430,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
INIT_WORK
(
&
mvm
->
d0i3_exit_work
,
iwl_mvm_d0i3_exit_work
);
spin_lock_init
(
&
mvm
->
d0i3_tx_lock
);
spin_lock_init
(
&
mvm
->
refs_lock
);
skb_queue_head_init
(
&
mvm
->
d0i3_tx
);
init_waitqueue_head
(
&
mvm
->
d0i3_exit_waitq
);
...
...
@@ -539,7 +545,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
memset
(
&
mvm
->
rx_stats
,
0
,
sizeof
(
struct
mvm_statistics_rx
));
/* rpm starts with a taken ref. only set the appropriate bit here. */
set_bit
(
IWL_MVM_REF_UCODE_DOWN
,
mvm
->
ref_bitmap
)
;
mvm
->
refs
[
IWL_MVM_REF_UCODE_DOWN
]
=
1
;
return
op_mode
;
...
...
@@ -567,7 +573,11 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
ieee80211_unregister_hw
(
mvm
->
hw
);
kfree
(
mvm
->
scan_cmd
);
vfree
(
mvm
->
fw_error_dump
);
if
(
mvm
->
fw_error_dump
)
{
vfree
(
mvm
->
fw_error_dump
->
op_mode_ptr
);
vfree
(
mvm
->
fw_error_dump
->
trans_ptr
);
kfree
(
mvm
->
fw_error_dump
);
}
kfree
(
mvm
->
mcast_filter_cmd
);
mvm
->
mcast_filter_cmd
=
NULL
;
...
...
drivers/net/wireless/iwlwifi/mvm/sta.c
View file @
d878b3af
...
...
@@ -98,23 +98,21 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
bool
update
)
{
struct
iwl_mvm_sta
*
mvm_sta
=
(
void
*
)
sta
->
drv_priv
;
struct
iwl_mvm_add_sta_cmd
add_sta_cmd
;
struct
iwl_mvm_add_sta_cmd
add_sta_cmd
=
{
.
sta_id
=
mvm_sta
->
sta_id
,
.
mac_id_n_color
=
cpu_to_le32
(
mvm_sta
->
mac_id_n_color
),
.
add_modify
=
update
?
1
:
0
,
.
station_flags_msk
=
cpu_to_le32
(
STA_FLG_FAT_EN_MSK
|
STA_FLG_MIMO_EN_MSK
),
};
int
ret
;
u32
status
;
u32
agg_size
=
0
,
mpdu_dens
=
0
;
memset
(
&
add_sta_cmd
,
0
,
sizeof
(
add_sta_cmd
));
add_sta_cmd
.
sta_id
=
mvm_sta
->
sta_id
;
add_sta_cmd
.
mac_id_n_color
=
cpu_to_le32
(
mvm_sta
->
mac_id_n_color
);
if
(
!
update
)
{
add_sta_cmd
.
tfd_queue_msk
=
cpu_to_le32
(
mvm_sta
->
tfd_queue_msk
);
memcpy
(
&
add_sta_cmd
.
addr
,
sta
->
addr
,
ETH_ALEN
);
}
add_sta_cmd
.
add_modify
=
update
?
1
:
0
;
add_sta_cmd
.
station_flags_msk
|=
cpu_to_le32
(
STA_FLG_FAT_EN_MSK
|
STA_FLG_MIMO_EN_MSK
);
switch
(
sta
->
bandwidth
)
{
case
IEEE80211_STA_RX_BW_160
:
...
...
@@ -528,8 +526,12 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
lockdep_assert_held
(
&
mvm
->
mutex
);
/* Add the aux station, but without any queues */
ret
=
iwl_mvm_allocate_int_sta
(
mvm
,
&
mvm
->
aux_sta
,
0
,
/* Map Aux queue to fifo - needs to happen before adding Aux station */
iwl_trans_ac_txq_enable
(
mvm
->
trans
,
mvm
->
aux_queue
,
IWL_MVM_TX_FIFO_MCAST
);
/* Allocate aux station and assign to it the aux queue */
ret
=
iwl_mvm_allocate_int_sta
(
mvm
,
&
mvm
->
aux_sta
,
BIT
(
mvm
->
aux_queue
),
NL80211_IFTYPE_UNSPECIFIED
);
if
(
ret
)
return
ret
;
...
...
drivers/net/wireless/iwlwifi/mvm/time-event.c
View file @
d878b3af
...
...
@@ -72,9 +72,6 @@
#include "iwl-io.h"
#include "iwl-prph.h"
/* A TimeUnit is 1024 microsecond */
#define MSEC_TO_TU(_msec) (_msec*1000/1024)
/*
* For the high priority TE use a time event type that has similar priority to
* the FW's action scan priority.
...
...
@@ -100,6 +97,21 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
void
iwl_mvm_roc_done_wk
(
struct
work_struct
*
wk
)
{
struct
iwl_mvm
*
mvm
=
container_of
(
wk
,
struct
iwl_mvm
,
roc_done_wk
);
u32
queues
=
0
;
/*
* Clear the ROC_RUNNING /ROC_AUX_RUNNING status bit.
* This will cause the TX path to drop offchannel transmissions.
* That would also be done by mac80211, but it is racy, in particular
* in the case that the time event actually completed in the firmware
* (which is handled in iwl_mvm_te_handle_notif).
*/
if
(
test_and_clear_bit
(
IWL_MVM_STATUS_ROC_RUNNING
,
&
mvm
->
status
))
queues
|=
BIT
(
IWL_MVM_OFFCHANNEL_QUEUE
);
if
(
test_and_clear_bit
(
IWL_MVM_STATUS_ROC_AUX_RUNNING
,
&
mvm
->
status
))
queues
|=
BIT
(
mvm
->
aux_queue
);
iwl_mvm_unref
(
mvm
,
IWL_MVM_REF_ROC
);
synchronize_net
();
...
...
@@ -113,21 +125,11 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
* issue as it will have to complete before the next command is
* executed, and a new time event means a new command.
*/
iwl_mvm_flush_tx_path
(
mvm
,
BIT
(
IWL_MVM_OFFCHANNEL_QUEUE
)
,
false
);
iwl_mvm_flush_tx_path
(
mvm
,
queues
,
false
);
}
static
void
iwl_mvm_roc_finished
(
struct
iwl_mvm
*
mvm
)
{
/*
* First, clear the ROC_RUNNING status bit. This will cause the TX
* path to drop offchannel transmissions. That would also be done
* by mac80211, but it is racy, in particular in the case that the
* time event actually completed in the firmware (which is handled
* in iwl_mvm_te_handle_notif).
*/
clear_bit
(
IWL_MVM_STATUS_ROC_RUNNING
,
&
mvm
->
status
);
iwl_mvm_unref
(
mvm
,
IWL_MVM_REF_ROC
);
/*
* Of course, our status bit is just as racy as mac80211, so in
* addition, fire off the work struct which will drop all frames
...
...
@@ -262,6 +264,60 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
}
}
/*
* Handle A Aux ROC time event
*/
static
int
iwl_mvm_aux_roc_te_handle_notif
(
struct
iwl_mvm
*
mvm
,
struct
iwl_time_event_notif
*
notif
)
{
struct
iwl_mvm_time_event_data
*
te_data
,
*
tmp
;
bool
aux_roc_te
=
false
;
list_for_each_entry_safe
(
te_data
,
tmp
,
&
mvm
->
aux_roc_te_list
,
list
)
{
if
(
le32_to_cpu
(
notif
->
unique_id
)
==
te_data
->
uid
)
{
aux_roc_te
=
true
;
break
;
}
}
if
(
!
aux_roc_te
)
/* Not a Aux ROC time event */
return
-
EINVAL
;
if
(
!
le32_to_cpu
(
notif
->
status
))
{
IWL_DEBUG_TE
(
mvm
,
"ERROR: Aux ROC Time Event %s notification failure
\n
"
,
(
le32_to_cpu
(
notif
->
action
)
&
TE_V2_NOTIF_HOST_EVENT_START
)
?
"start"
:
"end"
);
return
-
EINVAL
;
}
IWL_DEBUG_TE
(
mvm
,
"Aux ROC time event notification - UID = 0x%x action %d
\n
"
,
le32_to_cpu
(
notif
->
unique_id
),
le32_to_cpu
(
notif
->
action
));
if
(
le32_to_cpu
(
notif
->
action
)
==
TE_V2_NOTIF_HOST_EVENT_END
)
{
/* End TE, notify mac80211 */
ieee80211_remain_on_channel_expired
(
mvm
->
hw
);
iwl_mvm_roc_finished
(
mvm
);
/* flush aux queue */
list_del
(
&
te_data
->
list
);
/* remove from list */
te_data
->
running
=
false
;
te_data
->
vif
=
NULL
;
te_data
->
uid
=
0
;
}
else
if
(
le32_to_cpu
(
notif
->
action
)
==
TE_V2_NOTIF_HOST_EVENT_START
)
{
set_bit
(
IWL_MVM_STATUS_ROC_RUNNING
,
&
mvm
->
status
);
set_bit
(
IWL_MVM_STATUS_ROC_AUX_RUNNING
,
&
mvm
->
status
);
te_data
->
running
=
true
;
ieee80211_ready_on_channel
(
mvm
->
hw
);
/* Start TE */
}
else
{
IWL_DEBUG_TE
(
mvm
,
"ERROR: Unknown Aux ROC Time Event (action = %d)
\n
"
,
le32_to_cpu
(
notif
->
action
));
return
-
EINVAL
;
}
return
0
;
}
/*
* The Rx handler for time event notifications
*/
...
...
@@ -278,10 +334,15 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
le32_to_cpu
(
notif
->
action
));
spin_lock_bh
(
&
mvm
->
time_event_lock
);
/* This time event is triggered for Aux ROC request */
if
(
!
iwl_mvm_aux_roc_te_handle_notif
(
mvm
,
notif
))
goto
unlock
;
list_for_each_entry_safe
(
te_data
,
tmp
,
&
mvm
->
time_event_list
,
list
)
{
if
(
le32_to_cpu
(
notif
->
unique_id
)
==
te_data
->
uid
)
iwl_mvm_te_handle_notif
(
mvm
,
te_data
,
notif
);
}
unlock:
spin_unlock_bh
(
&
mvm
->
time_event_lock
);
return
0
;
...
...
drivers/net/wireless/iwlwifi/mvm/tt.c
View file @
d878b3af
...
...
@@ -140,9 +140,9 @@ static u16 iwl_mvm_dts_get_ptat_deviation_offset(struct iwl_mvm *mvm)
/* TODO: move parsing to NVM code */
calib
=
mvm
->
nvm_sections
[
NVM_SECTION_TYPE_CALIBRATION
].
data
;
ptat
=
calib
[
OTP_DTS_DIODE_DEVIATION
];
pa1
=
calib
[
OTP_DTS_DIODE_DEVIATION
+
1
];
pa2
=
calib
[
OTP_DTS_DIODE_DEVIATION
+
2
];
ptat
=
calib
[
OTP_DTS_DIODE_DEVIATION
*
2
];
pa1
=
calib
[
OTP_DTS_DIODE_DEVIATION
*
2
+
1
];
pa2
=
calib
[
OTP_DTS_DIODE_DEVIATION
*
2
+
2
];
/* get the median: */
if
(
ptat
>
pa1
)
{
...
...
@@ -338,10 +338,16 @@ static void check_exit_ctkill(struct work_struct *work)
duration
=
tt
->
params
->
ct_kill_duration
;
/* make sure the device is available for direct read/writes */
if
(
iwl_mvm_ref_sync
(
mvm
,
IWL_MVM_REF_CHECK_CTKILL
))
goto
reschedule
;
iwl_trans_start_hw
(
mvm
->
trans
);
temp
=
check_nic_temperature
(
mvm
);
iwl_trans_stop_device
(
mvm
->
trans
);
iwl_mvm_unref
(
mvm
,
IWL_MVM_REF_CHECK_CTKILL
);
if
(
temp
<
MIN_TEMPERATURE
||
temp
>
MAX_TEMPERATURE
)
{
IWL_DEBUG_TEMP
(
mvm
,
"Failed to measure NIC temperature
\n
"
);
goto
reschedule
;
...
...
drivers/net/wireless/iwlwifi/mvm/tx.c
View file @
d878b3af
...
...
@@ -310,6 +310,16 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
info
->
hw_queue
!=
info
->
control
.
vif
->
cab_queue
)))
return
-
1
;
/*
* IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used
* in 2 different types of vifs, P2P & STATION. P2P uses the offchannel
* queue. STATION (HS2.0) uses the auxiliary context of the FW,
* and hence needs to be sent on the aux queue
*/
if
(
IEEE80211_SKB_CB
(
skb
)
->
hw_queue
==
IWL_MVM_OFFCHANNEL_QUEUE
&&
info
->
control
.
vif
->
type
==
NL80211_IFTYPE_STATION
)
IEEE80211_SKB_CB
(
skb
)
->
hw_queue
=
mvm
->
aux_queue
;
/*
* If the interface on which frame is sent is the P2P_DEVICE
* or an AP/GO interface use the broadcast station associated
...
...
drivers/net/wireless/iwlwifi/pcie/trans.c
View file @
d878b3af
...
...
@@ -67,6 +67,7 @@
#include <linux/sched.h>
#include <linux/bitops.h>
#include <linux/gfp.h>
#include <linux/vmalloc.h>
#include "iwl-drv.h"
#include "iwl-trans.h"
...
...
@@ -1773,28 +1774,207 @@ static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd)
return
cmdlen
;
}
static
u32
iwl_trans_pcie_dump_data
(
struct
iwl_trans
*
trans
,
void
*
buf
,
u32
buflen
)
static
const
struct
{
u32
start
,
end
;
}
iwl_prph_dump_addr
[]
=
{
{
.
start
=
0x00a00000
,
.
end
=
0x00a00000
},
{
.
start
=
0x00a0000c
,
.
end
=
0x00a00024
},
{
.
start
=
0x00a0002c
,
.
end
=
0x00a0003c
},
{
.
start
=
0x00a00410
,
.
end
=
0x00a00418
},
{
.
start
=
0x00a00420
,
.
end
=
0x00a00420
},
{
.
start
=
0x00a00428
,
.
end
=
0x00a00428
},
{
.
start
=
0x00a00430
,
.
end
=
0x00a0043c
},
{
.
start
=
0x00a00444
,
.
end
=
0x00a00444
},
{
.
start
=
0x00a004c0
,
.
end
=
0x00a004cc
},
{
.
start
=
0x00a004d8
,
.
end
=
0x00a004d8
},
{
.
start
=
0x00a004e0
,
.
end
=
0x00a004f0
},
{
.
start
=
0x00a00840
,
.
end
=
0x00a00840
},
{
.
start
=
0x00a00850
,
.
end
=
0x00a00858
},
{
.
start
=
0x00a01004
,
.
end
=
0x00a01008
},
{
.
start
=
0x00a01010
,
.
end
=
0x00a01010
},
{
.
start
=
0x00a01018
,
.
end
=
0x00a01018
},
{
.
start
=
0x00a01024
,
.
end
=
0x00a01024
},
{
.
start
=
0x00a0102c
,
.
end
=
0x00a01034
},
{
.
start
=
0x00a0103c
,
.
end
=
0x00a01040
},
{
.
start
=
0x00a01048
,
.
end
=
0x00a01094
},
{
.
start
=
0x00a01c00
,
.
end
=
0x00a01c20
},
{
.
start
=
0x00a01c58
,
.
end
=
0x00a01c58
},
{
.
start
=
0x00a01c7c
,
.
end
=
0x00a01c7c
},
{
.
start
=
0x00a01c28
,
.
end
=
0x00a01c54
},
{
.
start
=
0x00a01c5c
,
.
end
=
0x00a01c5c
},
{
.
start
=
0x00a01c84
,
.
end
=
0x00a01c84
},
{
.
start
=
0x00a01ce0
,
.
end
=
0x00a01d0c
},
{
.
start
=
0x00a01d18
,
.
end
=
0x00a01d20
},
{
.
start
=
0x00a01d2c
,
.
end
=
0x00a01d30
},
{
.
start
=
0x00a01d40
,
.
end
=
0x00a01d5c
},
{
.
start
=
0x00a01d80
,
.
end
=
0x00a01d80
},
{
.
start
=
0x00a01d98
,
.
end
=
0x00a01d98
},
{
.
start
=
0x00a01dc0
,
.
end
=
0x00a01dfc
},
{
.
start
=
0x00a01e00
,
.
end
=
0x00a01e2c
},
{
.
start
=
0x00a01e40
,
.
end
=
0x00a01e60
},
{
.
start
=
0x00a01e84
,
.
end
=
0x00a01e90
},
{
.
start
=
0x00a01e9c
,
.
end
=
0x00a01ec4
},
{
.
start
=
0x00a01ed0
,
.
end
=
0x00a01ed0
},
{
.
start
=
0x00a01f00
,
.
end
=
0x00a01f14
},
{
.
start
=
0x00a01f44
,
.
end
=
0x00a01f58
},
{
.
start
=
0x00a01f80
,
.
end
=
0x00a01fa8
},
{
.
start
=
0x00a01fb0
,
.
end
=
0x00a01fbc
},
{
.
start
=
0x00a01ff8
,
.
end
=
0x00a01ffc
},
{
.
start
=
0x00a02000
,
.
end
=
0x00a02048
},
{
.
start
=
0x00a02068
,
.
end
=
0x00a020f0
},
{
.
start
=
0x00a02100
,
.
end
=
0x00a02118
},
{
.
start
=
0x00a02140
,
.
end
=
0x00a0214c
},
{
.
start
=
0x00a02168
,
.
end
=
0x00a0218c
},
{
.
start
=
0x00a021c0
,
.
end
=
0x00a021c0
},
{
.
start
=
0x00a02400
,
.
end
=
0x00a02410
},
{
.
start
=
0x00a02418
,
.
end
=
0x00a02420
},
{
.
start
=
0x00a02428
,
.
end
=
0x00a0242c
},
{
.
start
=
0x00a02434
,
.
end
=
0x00a02434
},
{
.
start
=
0x00a02440
,
.
end
=
0x00a02460
},
{
.
start
=
0x00a02468
,
.
end
=
0x00a024b0
},
{
.
start
=
0x00a024c8
,
.
end
=
0x00a024cc
},
{
.
start
=
0x00a02500
,
.
end
=
0x00a02504
},
{
.
start
=
0x00a0250c
,
.
end
=
0x00a02510
},
{
.
start
=
0x00a02540
,
.
end
=
0x00a02554
},
{
.
start
=
0x00a02580
,
.
end
=
0x00a025f4
},
{
.
start
=
0x00a02600
,
.
end
=
0x00a0260c
},
{
.
start
=
0x00a02648
,
.
end
=
0x00a02650
},
{
.
start
=
0x00a02680
,
.
end
=
0x00a02680
},
{
.
start
=
0x00a026c0
,
.
end
=
0x00a026d0
},
{
.
start
=
0x00a02700
,
.
end
=
0x00a0270c
},
{
.
start
=
0x00a02804
,
.
end
=
0x00a02804
},
{
.
start
=
0x00a02818
,
.
end
=
0x00a0281c
},
{
.
start
=
0x00a02c00
,
.
end
=
0x00a02db4
},
{
.
start
=
0x00a02df4
,
.
end
=
0x00a02fb0
},
{
.
start
=
0x00a03000
,
.
end
=
0x00a03014
},
{
.
start
=
0x00a0301c
,
.
end
=
0x00a0302c
},
{
.
start
=
0x00a03034
,
.
end
=
0x00a03038
},
{
.
start
=
0x00a03040
,
.
end
=
0x00a03048
},
{
.
start
=
0x00a03060
,
.
end
=
0x00a03068
},
{
.
start
=
0x00a03070
,
.
end
=
0x00a03074
},
{
.
start
=
0x00a0307c
,
.
end
=
0x00a0307c
},
{
.
start
=
0x00a03080
,
.
end
=
0x00a03084
},
{
.
start
=
0x00a0308c
,
.
end
=
0x00a03090
},
{
.
start
=
0x00a03098
,
.
end
=
0x00a03098
},
{
.
start
=
0x00a030a0
,
.
end
=
0x00a030a0
},
{
.
start
=
0x00a030a8
,
.
end
=
0x00a030b4
},
{
.
start
=
0x00a030bc
,
.
end
=
0x00a030bc
},
{
.
start
=
0x00a030c0
,
.
end
=
0x00a0312c
},
{
.
start
=
0x00a03c00
,
.
end
=
0x00a03c5c
},
{
.
start
=
0x00a04400
,
.
end
=
0x00a04454
},
{
.
start
=
0x00a04460
,
.
end
=
0x00a04474
},
{
.
start
=
0x00a044c0
,
.
end
=
0x00a044ec
},
{
.
start
=
0x00a04500
,
.
end
=
0x00a04504
},
{
.
start
=
0x00a04510
,
.
end
=
0x00a04538
},
{
.
start
=
0x00a04540
,
.
end
=
0x00a04548
},
{
.
start
=
0x00a04560
,
.
end
=
0x00a0457c
},
{
.
start
=
0x00a04590
,
.
end
=
0x00a04598
},
{
.
start
=
0x00a045c0
,
.
end
=
0x00a045f4
},
};
static
u32
iwl_trans_pcie_dump_prph
(
struct
iwl_trans
*
trans
,
struct
iwl_fw_error_dump_data
**
data
)
{
struct
iwl_fw_error_dump_prph
*
prph
;
unsigned
long
flags
;
u32
prph_len
=
0
,
i
;
if
(
!
iwl_trans_grab_nic_access
(
trans
,
false
,
&
flags
))
return
0
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
iwl_prph_dump_addr
);
i
++
)
{
/* The range includes both boundaries */
int
num_bytes_in_chunk
=
iwl_prph_dump_addr
[
i
].
end
-
iwl_prph_dump_addr
[
i
].
start
+
4
;
int
reg
;
__le32
*
val
;
prph_len
+=
sizeof
(
*
data
)
+
sizeof
(
*
prph
)
+
num_bytes_in_chunk
;
(
*
data
)
->
type
=
cpu_to_le32
(
IWL_FW_ERROR_DUMP_PRPH
);
(
*
data
)
->
len
=
cpu_to_le32
(
sizeof
(
*
prph
)
+
num_bytes_in_chunk
);
prph
=
(
void
*
)(
*
data
)
->
data
;
prph
->
prph_start
=
cpu_to_le32
(
iwl_prph_dump_addr
[
i
].
start
);
val
=
(
void
*
)
prph
->
data
;
for
(
reg
=
iwl_prph_dump_addr
[
i
].
start
;
reg
<=
iwl_prph_dump_addr
[
i
].
end
;
reg
+=
4
)
*
val
++
=
cpu_to_le32
(
iwl_trans_pcie_read_prph
(
trans
,
reg
));
*
data
=
iwl_fw_error_next_data
(
*
data
);
}
iwl_trans_release_nic_access
(
trans
,
&
flags
);
return
prph_len
;
}
#define IWL_CSR_TO_DUMP (0x250)
static
u32
iwl_trans_pcie_dump_csr
(
struct
iwl_trans
*
trans
,
struct
iwl_fw_error_dump_data
**
data
)
{
u32
csr_len
=
sizeof
(
**
data
)
+
IWL_CSR_TO_DUMP
;
__le32
*
val
;
int
i
;
(
*
data
)
->
type
=
cpu_to_le32
(
IWL_FW_ERROR_DUMP_CSR
);
(
*
data
)
->
len
=
cpu_to_le32
(
IWL_CSR_TO_DUMP
);
val
=
(
void
*
)(
*
data
)
->
data
;
for
(
i
=
0
;
i
<
IWL_CSR_TO_DUMP
;
i
+=
4
)
*
val
++
=
cpu_to_le32
(
iwl_trans_pcie_read32
(
trans
,
i
));
*
data
=
iwl_fw_error_next_data
(
*
data
);
return
csr_len
;
}
static
struct
iwl_trans_dump_data
*
iwl_trans_pcie_dump_data
(
struct
iwl_trans
*
trans
)
{
struct
iwl_trans_pcie
*
trans_pcie
=
IWL_TRANS_GET_PCIE_TRANS
(
trans
);
struct
iwl_fw_error_dump_data
*
data
;
struct
iwl_txq
*
cmdq
=
&
trans_pcie
->
txq
[
trans_pcie
->
cmd_queue
];
struct
iwl_fw_error_dump_txcmd
*
txcmd
;
struct
iwl_trans_dump_data
*
dump_data
;
u32
len
;
int
i
,
ptr
;
len
=
sizeof
(
*
data
)
+
/* transport dump header */
len
=
sizeof
(
*
dump_data
);
/* host commands */
len
+=
sizeof
(
*
data
)
+
cmdq
->
q
.
n_window
*
(
sizeof
(
*
txcmd
)
+
TFD_MAX_PAYLOAD_SIZE
);
/* CSR registers */
len
+=
sizeof
(
*
data
)
+
IWL_CSR_TO_DUMP
;
/* PRPH registers */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
iwl_prph_dump_addr
);
i
++
)
{
/* The range includes both boundaries */
int
num_bytes_in_chunk
=
iwl_prph_dump_addr
[
i
].
end
-
iwl_prph_dump_addr
[
i
].
start
+
4
;
len
+=
sizeof
(
*
data
)
+
sizeof
(
struct
iwl_fw_error_dump_prph
)
+
num_bytes_in_chunk
;
}
/* FW monitor */
if
(
trans_pcie
->
fw_mon_page
)
len
+=
sizeof
(
*
data
)
+
sizeof
(
struct
iwl_fw_error_dump_fw_mon
)
+
trans_pcie
->
fw_mon_size
;
if
(
!
buf
)
return
len
;
dump_data
=
vzalloc
(
len
);
if
(
!
dump_data
)
return
NULL
;
len
=
0
;
data
=
buf
;
data
=
(
void
*
)
dump_data
->
data
;
data
->
type
=
cpu_to_le32
(
IWL_FW_ERROR_DUMP_TXCMD
);
txcmd
=
(
void
*
)
data
->
data
;
spin_lock_bh
(
&
cmdq
->
lock
);
...
...
@@ -1820,11 +2000,15 @@ static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans,
data
->
len
=
cpu_to_le32
(
len
);
len
+=
sizeof
(
*
data
);
data
=
iwl_fw_error_next_data
(
data
);
len
+=
iwl_trans_pcie_dump_prph
(
trans
,
&
data
);
len
+=
iwl_trans_pcie_dump_csr
(
trans
,
&
data
);
/* data is already pointing to the next section */
if
(
trans_pcie
->
fw_mon_page
)
{
struct
iwl_fw_error_dump_fw_mon
*
fw_mon_data
;
data
=
iwl_fw_error_next_data
(
data
);
data
->
type
=
cpu_to_le32
(
IWL_FW_ERROR_DUMP_FW_MONITOR
);
data
->
len
=
cpu_to_le32
(
trans_pcie
->
fw_mon_size
+
sizeof
(
*
fw_mon_data
));
...
...
@@ -1852,7 +2036,9 @@ static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans,
trans_pcie
->
fw_mon_size
;
}
return
len
;
dump_data
->
len
=
len
;
return
dump_data
;
}
#else
static
int
iwl_trans_pcie_dbgfs_register
(
struct
iwl_trans
*
trans
,
...
...
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