* Re: linux-next: build failure after merge of the tip tree
From: Kalle Valo @ 2019-06-25 7:47 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Stephen Rothwell, Ingo Molnar, H. Peter Anvin, Peter Zijlstra,
Wireless, Linux Next Mailing List, Linux Kernel Mailing List,
Christian Lamparter, Jason A. Donenfeld
In-Reply-To: <alpine.DEB.2.21.1906250856050.32342@nanos.tec.linutronix.de>
Thomas Gleixner <tglx@linutronix.de> writes:
> On Tue, 25 Jun 2019, Stephen Rothwell wrote:
>
>> Hi Kalle,
>>
>> On Tue, 25 Jun 2019 09:23:33 +0300 Kalle Valo <kvalo@codeaurora.org> wrote:
>> >
>> > Thanks for the report. Any suggestions how to handle this? Or do we let
>> > Linus take care of this?
>>
>> Just let Linus take care of it ... mention it in the pull request ... I
>> guess DaveM needs to know, right?
>
> Ah. I didn't realize that this is a new commit in Kalle's tree. So yes
> that's the right thing to do.
Good, I'll do that then.
--
Kalle Valo
^ permalink raw reply
* Re: nl80211 wlcore regression in next
From: Tony Lindgren @ 2019-06-25 8:00 UTC (permalink / raw)
To: Johannes Berg
Cc: Kalle Valo, Eyal Reizer, linux-wireless, linux-kernel, linux-omap
In-Reply-To: <2570f4087d6e3356df34635a0380ec8ce06c9159.camel@sipsolutions.net>
Hi,
* Johannes Berg <johannes@sipsolutions.net> [190625 07:47]:
> On Tue, 2019-06-25 at 00:38 -0700, Tony Lindgren wrote:
> > Hi,
> >
> > Looks like at least drivers/net/wireless/ti wlcore driver has stopped
> > working in Linux next with commit 901bb9891855 ("nl80211: require and
> > validate vendor command policy"). Reverting the commit above makes it
> > work again.
> >
> > It fails with the warning below, any ideas what goes wrong?
>
> Oops. For some reason, I neglected to check the vendor command usage
> beyond hwsim.
>
> The patch below should work?
Yeah thanks that fixes the issue for me:
Tested-by: Tony Lindgren <tony@atomide.com>
^ permalink raw reply
* Re: nl80211 wlcore regression in next
From: Johannes Berg @ 2019-06-25 8:02 UTC (permalink / raw)
To: Tony Lindgren
Cc: Kalle Valo, Eyal Reizer, linux-wireless, linux-kernel, linux-omap
In-Reply-To: <20190625080019.GH5447@atomide.com>
On Tue, 2019-06-25 at 01:00 -0700, Tony Lindgren wrote:
> Hi,
>
> * Johannes Berg <johannes@sipsolutions.net> [190625 07:47]:
> > On Tue, 2019-06-25 at 00:38 -0700, Tony Lindgren wrote:
> > > Hi,
> > >
> > > Looks like at least drivers/net/wireless/ti wlcore driver has stopped
> > > working in Linux next with commit 901bb9891855 ("nl80211: require and
> > > validate vendor command policy"). Reverting the commit above makes it
> > > work again.
> > >
> > > It fails with the warning below, any ideas what goes wrong?
> >
> > Oops. For some reason, I neglected to check the vendor command usage
> > beyond hwsim.
> >
> > The patch below should work?
>
> Yeah thanks that fixes the issue for me:
>
> Tested-by: Tony Lindgren <tony@atomide.com>
Thanks, I'll drop that into my tree and hopefully will remember to send
it on soon.
johannes
^ permalink raw reply
* [PATCH] wireless: fix netlink vendor commands
From: Johannes Berg @ 2019-06-25 8:08 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
In my previous commit to validate a policy I neglected to
actually add one to the few drivers using vendor commands,
fix that now.
Reported-by: Tony Lindgren <tony@atomide.com>
Tested-by: Tony Lindgren <tony@atomide.com>
Fixes: 901bb9891855 ("nl80211: require and validate vendor command policy")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
drivers/net/wireless/ath/wil6210/cfg80211.c | 4 ++++
drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c | 1 +
drivers/net/wireless/ti/wlcore/vendor_cmd.c | 3 +++
3 files changed, 8 insertions(+)
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 804955d24b30..37ac95940c22 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -177,6 +177,7 @@ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = {
.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG,
.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .policy = wil_rf_sector_policy,
.doit = wil_rf_sector_get_cfg
},
{
@@ -184,6 +185,7 @@ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = {
.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG,
.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .policy = wil_rf_sector_policy,
.doit = wil_rf_sector_set_cfg
},
{
@@ -192,6 +194,7 @@ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = {
QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR,
.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .policy = wil_rf_sector_policy,
.doit = wil_rf_sector_get_selected
},
{
@@ -200,6 +203,7 @@ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = {
QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR,
.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .policy = wil_rf_sector_policy,
.doit = wil_rf_sector_set_selected
},
};
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
index d493021f6031..30ebadc5e5bb 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
@@ -123,6 +123,7 @@ const struct wiphy_vendor_command brcmf_vendor_cmds[] = {
},
.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .policy = VENDOR_CMD_RAW_DATA,
.doit = brcmf_cfg80211_vndr_cmds_dcmd_handler
},
};
diff --git a/drivers/net/wireless/ti/wlcore/vendor_cmd.c b/drivers/net/wireless/ti/wlcore/vendor_cmd.c
index 5cf0b32c413b..e1bd344c4ebc 100644
--- a/drivers/net/wireless/ti/wlcore/vendor_cmd.c
+++ b/drivers/net/wireless/ti/wlcore/vendor_cmd.c
@@ -163,6 +163,7 @@ static const struct wiphy_vendor_command wlcore_vendor_commands[] = {
.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
WIPHY_VENDOR_CMD_NEED_RUNNING,
.doit = wlcore_vendor_cmd_smart_config_start,
+ .policy = wlcore_vendor_attr_policy,
},
{
.info = {
@@ -172,6 +173,7 @@ static const struct wiphy_vendor_command wlcore_vendor_commands[] = {
.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
WIPHY_VENDOR_CMD_NEED_RUNNING,
.doit = wlcore_vendor_cmd_smart_config_stop,
+ .policy = wlcore_vendor_attr_policy,
},
{
.info = {
@@ -181,6 +183,7 @@ static const struct wiphy_vendor_command wlcore_vendor_commands[] = {
.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
WIPHY_VENDOR_CMD_NEED_RUNNING,
.doit = wlcore_vendor_cmd_smart_config_set_group_key,
+ .policy = wlcore_vendor_attr_policy,
},
};
--
2.17.2
^ permalink raw reply related
* Re: nl80211 wlcore regression in next
From: Arend Van Spriel @ 2019-06-25 8:56 UTC (permalink / raw)
To: Johannes Berg, Tony Lindgren
Cc: Kalle Valo, Eyal Reizer, linux-wireless, linux-kernel, linux-omap
In-Reply-To: <7f74087fef1e554e0aeb82a6cec4113727487928.camel@sipsolutions.net>
On 6/25/2019 10:02 AM, Johannes Berg wrote:
> On Tue, 2019-06-25 at 01:00 -0700, Tony Lindgren wrote:
>> Hi,
>>
>> * Johannes Berg <johannes@sipsolutions.net> [190625 07:47]:
>>> On Tue, 2019-06-25 at 00:38 -0700, Tony Lindgren wrote:
>>>> Hi,
>>>>
>>>> Looks like at least drivers/net/wireless/ti wlcore driver has stopped
>>>> working in Linux next with commit 901bb9891855 ("nl80211: require and
>>>> validate vendor command policy"). Reverting the commit above makes it
>>>> work again.
>>>>
>>>> It fails with the warning below, any ideas what goes wrong?
>>>
>>> Oops. For some reason, I neglected to check the vendor command usage
>>> beyond hwsim.
>>>
>>> The patch below should work?
>>
>> Yeah thanks that fixes the issue for me:
>>
>> Tested-by: Tony Lindgren <tony@atomide.com>
>
> Thanks, I'll drop that into my tree and hopefully will remember to send
> it on soon.
Hi Johannes,
By chance noticed the patch included brcmfmac. So I tried, but I get
compile issue below. It is because ERR_PTR really is an inline function
so that is not working. So also need to patch that. I left the extra
braces around the error code although not strictly necessary.
Regards,
Arend
---
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 2d17e32..da8249b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4172,7 +4172,7 @@ struct sta_opmode_info {
u8 rx_nss;
};
-#define VENDOR_CMD_RAW_DATA ((const struct nla_policy *)ERR_PTR(-ENODATA))
+#define VENDOR_CMD_RAW_DATA ((const struct nla_policy *)(-ENODATA))
/**
* struct wiphy_vendor_command - vendor command definition
---8<--------------------------------------------------------------------
CC [M] drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.o
In file included from
drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c:18:0:
./include/net/cfg80211.h:4175:29: error: initializer element is not constant
#define VENDOR_CMD_RAW_DATA ((const struct nla_policy *)ERR_PTR(-ENODATA))
^
drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c:126:13: note:
in expansion of macro \u2018VENDOR_CMD_RAW_DATA\u2019
.policy = VENDOR_CMD_RAW_DATA,
^
./include/net/cfg80211.h:4175:29: note: (near initialization for
\u2018brcmf_vendor_cmds[0].policy\u2019)
#define VENDOR_CMD_RAW_DATA ((const struct nla_policy *)ERR_PTR(-ENODATA))
^
drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c:126:13: note:
in expansion of macro \u2018VENDOR_CMD_RAW_DATA\u2019
.policy = VENDOR_CMD_RAW_DATA,
^
make[3]: *** [drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.o]
Error 1
^ permalink raw reply related
* Re: nl80211 wlcore regression in next
From: Johannes Berg @ 2019-06-25 8:57 UTC (permalink / raw)
To: Arend Van Spriel, Tony Lindgren
Cc: Kalle Valo, Eyal Reizer, linux-wireless, linux-kernel, linux-omap
In-Reply-To: <a863a74f-c6a9-b862-d17e-bc5f1dbe980a@broadcom.com>
Hi Arend,
> By chance noticed the patch included brcmfmac. So I tried, but I get
> compile issue below. It is because ERR_PTR really is an inline function
> so that is not working. So also need to patch that. I left the extra
> braces around the error code although not strictly necessary.
D'oh. I'll check that out, thanks for the report/patch!
johannes
^ permalink raw reply
* [PATCH] nl80211: fix VENDOR_CMD_RAW_DATA
From: Johannes Berg @ 2019-06-25 9:03 UTC (permalink / raw)
To: linux-wireless; +Cc: Arend Van Spriel, Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
Since ERR_PTR() is an inline, not a macro, just open-code it
here so it's usable as an initializer, fixing the build in
brcmfmac.
Reported-by: Arend Van Spriel <arend.vanspriel@broadcom.com>
Fixes: 901bb9891855 ("nl80211: require and validate vendor command policy")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/net/cfg80211.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 8419195dfb99..21c3e3428c88 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4170,7 +4170,7 @@ struct sta_opmode_info {
u8 rx_nss;
};
-#define VENDOR_CMD_RAW_DATA ((const struct nla_policy *)ERR_PTR(-ENODATA))
+#define VENDOR_CMD_RAW_DATA ((const struct nla_policy *)(long)(-ENODATA))
/**
* struct wiphy_vendor_command - vendor command definition
--
2.17.2
^ permalink raw reply related
* Re: nl80211 wlcore regression in next
From: Kalle Valo @ 2019-06-25 9:18 UTC (permalink / raw)
To: Tony Lindgren
Cc: Johannes Berg, Eyal Reizer, linux-wireless, linux-kernel,
linux-omap
In-Reply-To: <20190625080019.GH5447@atomide.com>
Tony Lindgren <tony@atomide.com> writes:
> Hi,
>
> * Johannes Berg <johannes@sipsolutions.net> [190625 07:47]:
>> On Tue, 2019-06-25 at 00:38 -0700, Tony Lindgren wrote:
>> > Hi,
>> >
>> > Looks like at least drivers/net/wireless/ti wlcore driver has stopped
>> > working in Linux next with commit 901bb9891855 ("nl80211: require and
>> > validate vendor command policy"). Reverting the commit above makes it
>> > work again.
>> >
>> > It fails with the warning below, any ideas what goes wrong?
>>
>> Oops. For some reason, I neglected to check the vendor command usage
>> beyond hwsim.
>>
>> The patch below should work?
>
> Yeah thanks that fixes the issue for me:
>
> Tested-by: Tony Lindgren <tony@atomide.com>
Acked-by: Kalle Valo <kvalo@codeaurora.org>
--
Kalle Valo
^ permalink raw reply
* [PATCH 00/12] iwlwifi: updates intended for v5.3 2019-06-25
From: Luca Coelho @ 2019-06-25 9:44 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Luca Coelho
From: Luca Coelho <luciano.coelho@intel.com>
Hi,
Here's the first set of patches intended for v5.3. It's the usual
development, new features, cleanups and bugfixes.
The changes are:
* Work on the new debugging framework continues;
* Update the FW API for CSI;
* Other small fixes and improvements;
As usual, I'm pushing this to a pending branch, for kbuild bot, and
will send a pull-request later.
Please review.
Cheers,
Luca.
Jiri Kosina (1):
iwlwifi: iwl_mvm_tx_mpdu() must be called with BH disabled
Johannes Berg (1):
iwlwifi: update CSI API
Mordechay Goodstein (2):
iwlwifi: mvm: add a debugfs entry to set a fixed size AMSDU for all TX
packets
iwlwifi: mvm: remove multiple debugfs entries
Shahar S Matityahu (8):
iwlwifi: dbg: allow dump collection in case of an early error
iwlwifi: dbg_ini: dump headers cleanup
iwlwifi: dbg_ini: abort region collection in case the size is 0
iwlwifi: dbg_ini: add consecutive trigger firing support
iwlwifi: dbg_ini: use different barker for ini dump
iwlwifi: dbg_ini: support debug info TLV
iwlwifi: dbg_ini: implement dump info collection
iwlwifi: fw api: support adwell HB default APs number api
.../wireless/intel/iwlwifi/fw/api/dbg-tlv.h | 22 ++
.../wireless/intel/iwlwifi/fw/api/location.h | 11 +-
.../net/wireless/intel/iwlwifi/fw/api/scan.h | 15 +
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 329 +++++++++++++-----
drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 40 ++-
.../wireless/intel/iwlwifi/fw/error-dump.h | 111 ++++--
drivers/net/wireless/intel/iwlwifi/fw/file.h | 14 +-
drivers/net/wireless/intel/iwlwifi/fw/init.c | 7 +-
.../net/wireless/intel/iwlwifi/fw/runtime.h | 28 +-
.../net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 1 +
drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 1 +
.../net/wireless/intel/iwlwifi/mvm/debugfs.c | 66 ++--
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 2 +
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 7 +-
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 16 +-
.../net/wireless/intel/iwlwifi/mvm/rs-fw.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 12 +-
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 4 +
drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 13 +-
.../net/wireless/intel/iwlwifi/pcie/trans.c | 21 +-
21 files changed, 529 insertions(+), 195 deletions(-)
--
2.20.1
^ permalink raw reply
* [PATCH 01/12] iwlwifi: iwl_mvm_tx_mpdu() must be called with BH disabled
From: Luca Coelho @ 2019-06-25 9:44 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Jiri Kosina, Johannes Berg, Luca Coelho
In-Reply-To: <20190625094452.19034-1-luca@coelho.fi>
From: Jiri Kosina <jkosina@suse.cz>
As iwl_mvm_tx_mpdu() is not disabling BH while obtaining iwl_mvm_sta->lock
(which is being taken from BH context as well), it has to be always
invoked with BH disabled. Make that clear in a comment.
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 0c2aabc842f9..ad4760307726 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -1063,7 +1063,9 @@ static int iwl_mvm_tx_pkt_queued(struct iwl_mvm *mvm,
}
/*
- * Sets the fields in the Tx cmd that are crypto related
+ * Sets the fields in the Tx cmd that are crypto related.
+ *
+ * This function must be called with BHs disabled.
*/
static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_tx_info *info,
--
2.20.1
^ permalink raw reply related
* [PATCH 04/12] iwlwifi: update CSI API
From: Luca Coelho @ 2019-06-25 9:44 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Johannes Berg, Luca Coelho
In-Reply-To: <20190625094452.19034-1-luca@coelho.fi>
From: Johannes Berg <johannes.berg@intel.com>
Update the CSI API to the new version supported by the firmware.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/fw/api/location.h | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
index 8d78b0e671c0..ec864c7b497f 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
@@ -937,8 +937,13 @@ struct iwl_ftm_responder_stats {
__le16 reserved;
} __packed; /* TOF_RESPONDER_STATISTICS_NTFY_S_VER_2 */
-#define IWL_CSI_CHUNK_CTL_NUM_MASK 0x3
-#define IWL_CSI_CHUNK_CTL_IDX_MASK 0xc
+#define IWL_CSI_MAX_EXPECTED_CHUNKS 16
+
+#define IWL_CSI_CHUNK_CTL_NUM_MASK_VER_1 0x0003
+#define IWL_CSI_CHUNK_CTL_IDX_MASK_VER_1 0x000c
+
+#define IWL_CSI_CHUNK_CTL_NUM_MASK_VER_2 0x00ff
+#define IWL_CSI_CHUNK_CTL_IDX_MASK_VER_2 0xff00
struct iwl_csi_chunk_notification {
__le32 token;
@@ -946,6 +951,6 @@ struct iwl_csi_chunk_notification {
__le16 ctl;
__le32 size;
u8 data[];
-} __packed; /* CSI_CHUNKS_HDR_NTFY_API_S_VER_1 */
+} __packed; /* CSI_CHUNKS_HDR_NTFY_API_S_VER_1/VER_2 */
#endif /* __iwl_fw_api_location_h__ */
--
2.20.1
^ permalink raw reply related
* [PATCH 07/12] iwlwifi: dbg_ini: use different barker for ini dump
From: Luca Coelho @ 2019-06-25 9:44 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Shahar S Matityahu, Luca Coelho
In-Reply-To: <20190625094452.19034-1-luca@coelho.fi>
From: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Use a different barker for ini dump to allow differentiation from legacy
dump. Also it allows to remove INI_BIT from dump TLVs.
Signed-off-by: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 4 ++--
drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | 4 +---
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 030889e3a10f..2f6881bfcde6 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -1690,7 +1690,7 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
num_of_ranges = ops->get_num_of_ranges(fwrt, reg);
- (*data)->type = cpu_to_le32(type | INI_DUMP_BIT);
+ (*data)->type = cpu_to_le32(type);
(*data)->len = cpu_to_le32(size);
header->region_id = reg->region_id;
@@ -1935,7 +1935,7 @@ iwl_fw_error_ini_dump_file(struct iwl_fw_runtime *fwrt,
if (!dump_file)
return NULL;
- dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
+ dump_file->barker = cpu_to_le32(IWL_FW_INI_ERROR_DUMP_BARKER);
dump_data = (void *)dump_file->data;
dump_file->file_len = cpu_to_le32(size);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
index 4ee9418c949b..50c5840644d0 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
@@ -67,6 +67,7 @@
#include <linux/types.h>
#define IWL_FW_ERROR_DUMP_BARKER 0x14789632
+#define IWL_FW_INI_ERROR_DUMP_BARKER 0x14789633
/**
* enum iwl_fw_error_dump_type - types of data in the dump file
@@ -283,9 +284,6 @@ struct iwl_fw_error_dump_mem {
*/
#define IWL_INI_DUMP_VER 1
-/* This bit is used to differentiate the legacy dump from the ini dump */
-#define INI_DUMP_BIT BIT(31)
-
/**
* struct iwl_fw_ini_fifo_hdr - fifo range header
* @fifo_num: the fifo number. In case of umac rx fifo, set BIT(31) to
--
2.20.1
^ permalink raw reply related
* [PATCH 08/12] iwlwifi: dbg_ini: support debug info TLV
From: Luca Coelho @ 2019-06-25 9:44 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Shahar S Matityahu, Luca Coelho
In-Reply-To: <20190625094452.19034-1-luca@coelho.fi>
From: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Add support to debug info TLV.
The TLV contains human readable naming of the FW image and the
debug configuration.
Signed-off-by: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
.../wireless/intel/iwlwifi/fw/api/dbg-tlv.h | 22 +++++++
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 65 ++++++++++++++++---
drivers/net/wireless/intel/iwlwifi/fw/file.h | 13 ++--
.../net/wireless/intel/iwlwifi/fw/runtime.h | 4 ++
.../net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 1 +
drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 1 +
6 files changed, 91 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
index f4202bc231a6..aaf3974a9a20 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
@@ -291,6 +291,28 @@ struct iwl_fw_ini_trigger_tlv {
struct iwl_fw_ini_trigger trigger_config[];
} __packed; /* FW_TLV_DEBUG_TRIGGERS_API_S_VER_1 */
+#define IWL_FW_INI_MAX_IMG_NAME_LEN 32
+#define IWL_FW_INI_MAX_DBG_CFG_NAME_LEN 64
+
+/**
+ * struct iwl_fw_ini_debug_info_tlv - (IWL_UCODE_TLV_TYPE_DEBUG_INFO)
+ *
+ * holds image name and debug configuration name
+ *
+ * @header: header
+ * @img_name_len: length of the image name string
+ * @img_name: image name string
+ * @dbg_cfg_name_len : length of the debug configuration name string
+ * @dbg_cfg_name: debug configuration name string
+ */
+struct iwl_fw_ini_debug_info_tlv {
+ struct iwl_fw_ini_header header;
+ __le32 img_name_len;
+ u8 img_name[IWL_FW_INI_MAX_IMG_NAME_LEN];
+ __le32 dbg_cfg_name_len;
+ u8 dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
+} __packed; /* FW_DEBUG_TLV_INFO_API_S_VER_1 */
+
/**
* enum iwl_fw_ini_trigger_id
*
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 2f6881bfcde6..806eb9847f72 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -2373,6 +2373,38 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt)
}
IWL_EXPORT_SYMBOL(iwl_fw_dbg_read_d3_debug_data);
+static void iwl_fw_dbg_info_apply(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_debug_info_tlv *dbg_info,
+ bool ext, enum iwl_fw_ini_apply_point pnt)
+{
+ u32 img_name_len = le32_to_cpu(dbg_info->img_name_len);
+ u32 dbg_cfg_name_len = le32_to_cpu(dbg_info->dbg_cfg_name_len);
+ const char err_str[] =
+ "WRT: ext=%d. Invalid %s name length %d, expected %d\n";
+
+ if (img_name_len != IWL_FW_INI_MAX_IMG_NAME_LEN) {
+ IWL_WARN(fwrt, err_str, ext, "image", img_name_len,
+ IWL_FW_INI_MAX_IMG_NAME_LEN);
+ return;
+ }
+
+ if (dbg_cfg_name_len != IWL_FW_INI_MAX_DBG_CFG_NAME_LEN) {
+ IWL_WARN(fwrt, err_str, ext, "debug cfg", dbg_cfg_name_len,
+ IWL_FW_INI_MAX_DBG_CFG_NAME_LEN);
+ return;
+ }
+
+ if (ext) {
+ memcpy(fwrt->dump.external_dbg_cfg_name, dbg_info->dbg_cfg_name,
+ sizeof(fwrt->dump.external_dbg_cfg_name));
+ } else {
+ memcpy(fwrt->dump.img_name, dbg_info->img_name,
+ sizeof(fwrt->dump.img_name));
+ memcpy(fwrt->dump.internal_dbg_cfg_name, dbg_info->dbg_cfg_name,
+ sizeof(fwrt->dump.internal_dbg_cfg_name));
+ }
+}
+
static void
iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, u32 size)
{
@@ -2679,6 +2711,9 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
u32 type = le32_to_cpu(tlv->type);
switch (type) {
+ case IWL_UCODE_TLV_TYPE_DEBUG_INFO:
+ iwl_fw_dbg_info_apply(fwrt, ini_tlv, ext, pnt);
+ break;
case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION: {
struct iwl_fw_ini_allocation_data *buf_alloc = ini_tlv;
@@ -2714,22 +2749,34 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
}
}
+static void iwl_fw_dbg_ini_reset_cfg(struct iwl_fw_runtime *fwrt)
+{
+ int i;
+
+ for (i = 0; i < IWL_FW_INI_MAX_REGION_ID; i++)
+ fwrt->dump.active_regs[i] = NULL;
+
+ /* disable the triggers, used in recovery flow */
+ for (i = 0; i < IWL_FW_TRIGGER_ID_NUM; i++)
+ fwrt->dump.active_trigs[i].active = false;
+
+ memset(fwrt->dump.img_name, 0,
+ sizeof(fwrt->dump.img_name));
+ memset(fwrt->dump.internal_dbg_cfg_name, 0,
+ sizeof(fwrt->dump.internal_dbg_cfg_name));
+ memset(fwrt->dump.external_dbg_cfg_name, 0,
+ sizeof(fwrt->dump.external_dbg_cfg_name));
+}
+
void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
enum iwl_fw_ini_apply_point apply_point)
{
void *data = &fwrt->trans->apply_points[apply_point];
- int i;
IWL_DEBUG_FW(fwrt, "WRT: enabling apply point %d\n", apply_point);
- if (apply_point == IWL_FW_INI_APPLY_EARLY) {
- for (i = 0; i < IWL_FW_INI_MAX_REGION_ID; i++)
- fwrt->dump.active_regs[i] = NULL;
-
- /* disable the triggers, used in recovery flow */
- for (i = 0; i < IWL_FW_TRIGGER_ID_NUM; i++)
- fwrt->dump.active_trigs[i].active = false;
- }
+ if (apply_point == IWL_FW_INI_APPLY_EARLY)
+ iwl_fw_dbg_ini_reset_cfg(fwrt);
_iwl_fw_dbg_apply_point(fwrt, data, apply_point, false);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h
index de9243d30135..71438c40a637 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/file.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h
@@ -151,12 +151,13 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_FW_RECOVERY_INFO = 57,
IWL_UCODE_TLV_FW_FSEQ_VERSION = 60,
- IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_INI_TLV_GROUP + 0x1,
- IWL_UCODE_TLV_DEBUG_BASE = IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION,
- IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_INI_TLV_GROUP + 0x2,
- IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_INI_TLV_GROUP + 0x3,
- IWL_UCODE_TLV_TYPE_TRIGGERS = IWL_UCODE_INI_TLV_GROUP + 0x4,
- IWL_UCODE_TLV_TYPE_DEBUG_FLOW = IWL_UCODE_INI_TLV_GROUP + 0x5,
+ IWL_UCODE_TLV_DEBUG_BASE = IWL_UCODE_INI_TLV_GROUP,
+ IWL_UCODE_TLV_TYPE_DEBUG_INFO = IWL_UCODE_TLV_DEBUG_BASE + 0,
+ IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_TLV_DEBUG_BASE + 1,
+ IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_TLV_DEBUG_BASE + 2,
+ IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_TLV_DEBUG_BASE + 3,
+ IWL_UCODE_TLV_TYPE_TRIGGERS = IWL_UCODE_TLV_DEBUG_BASE + 4,
+ IWL_UCODE_TLV_TYPE_DEBUG_FLOW = IWL_UCODE_TLV_DEBUG_BASE + 5,
IWL_UCODE_TLV_DEBUG_MAX = IWL_UCODE_TLV_TYPE_DEBUG_FLOW,
/* TLVs 0x1000-0x2000 are for internal driver usage */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
index e351ac7ae53b..07196a9fa5db 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
@@ -146,6 +146,10 @@ struct iwl_fw_runtime {
u32 umac_err_id;
void *fifo_iter;
struct timer_list periodic_trig;
+
+ u8 img_name[IWL_FW_INI_MAX_IMG_NAME_LEN];
+ u8 internal_dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
+ u8 external_dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
} dump;
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct {
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
index ba66f7fba064..fcc1c5c1d013 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
@@ -221,6 +221,7 @@ static int iwl_parse_fw_dbg_tlv(struct iwl_trans *trans, const u8 *data,
data += sizeof(*tlv) + ALIGN(tlv_len, 4);
switch (tlv_type) {
+ case IWL_UCODE_TLV_TYPE_DEBUG_INFO:
case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
case IWL_UCODE_TLV_TYPE_HCMD:
case IWL_UCODE_TLV_TYPE_REGIONS:
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index 852d3cbfc719..e14811ca75b3 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -1137,6 +1137,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
IWL_ERROR_EVENT_TABLE_LMAC1;
break;
}
+ case IWL_UCODE_TLV_TYPE_DEBUG_INFO:
case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
case IWL_UCODE_TLV_TYPE_HCMD:
case IWL_UCODE_TLV_TYPE_REGIONS:
--
2.20.1
^ permalink raw reply related
* [PATCH 09/12] iwlwifi: mvm: add a debugfs entry to set a fixed size AMSDU for all TX packets
From: Luca Coelho @ 2019-06-25 9:44 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Mordechay Goodstein, Luca Coelho
In-Reply-To: <20190625094452.19034-1-luca@coelho.fi>
From: Mordechay Goodstein <mordechay.goodstein@intel.com>
The current debugfs entry only limits the max AMSDU for TCP. Add a new
debugfs entry to allow setting a fixed AMSDU size for all TX packets,
including UDP and ICMP
Signed-off-by: Mordechay Goodstein <mordechay.goodstein@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
.../net/wireless/intel/iwlwifi/mvm/debugfs.c | 46 ++++++++++++++++++-
.../net/wireless/intel/iwlwifi/mvm/rs-fw.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 4 ++
3 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index d4ff6b44de2c..fb2fd89270ed 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -467,6 +467,46 @@ static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf,
return ret;
}
+static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_sta *sta,
+ char *buf, size_t count,
+ loff_t *ppos)
+{
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ int i;
+ u16 amsdu_len;
+
+ if (kstrtou16(buf, 0, &amsdu_len))
+ return -EINVAL;
+
+ if (amsdu_len) {
+ mvmsta->orig_amsdu_len = sta->max_amsdu_len;
+ sta->max_amsdu_len = amsdu_len;
+ for (i = 0; i < ARRAY_SIZE(sta->max_tid_amsdu_len); i++)
+ sta->max_tid_amsdu_len[i] = amsdu_len;
+ } else {
+ sta->max_amsdu_len = mvmsta->orig_amsdu_len;
+ mvmsta->orig_amsdu_len = 0;
+ }
+ return count;
+}
+
+static ssize_t iwl_dbgfs_amsdu_len_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_sta *sta = file->private_data;
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+
+ char buf[32];
+ int pos;
+
+ pos = scnprintf(buf, sizeof(buf), "current %d ", sta->max_amsdu_len);
+ pos += scnprintf(buf + pos, sizeof(buf) - pos, "stored %d\n",
+ mvmsta->orig_amsdu_len);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
static ssize_t iwl_dbgfs_disable_power_off_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
@@ -1947,6 +1987,8 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile);
#endif
+MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(amsdu_len, 16);
+
MVM_DEBUGFS_READ_WRITE_FILE_OPS(he_sniffer_params, 32);
static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf,
@@ -2088,8 +2130,10 @@ void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- if (iwl_mvm_has_tlc_offload(mvm))
+ if (iwl_mvm_has_tlc_offload(mvm)) {
MVM_DEBUGFS_ADD_STA_FILE(rs_data, dir, 0400);
+ }
+ MVM_DEBUGFS_ADD_STA_FILE(amsdu_len, dir, 0600);
}
void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
index 659e21b2d4e7..1cfd550c1ecb 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
@@ -344,7 +344,7 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
lq_sta->last_rate_n_flags);
}
- if (flags & IWL_TLC_NOTIF_FLAG_AMSDU) {
+ if (flags & IWL_TLC_NOTIF_FLAG_AMSDU && !mvmsta->orig_amsdu_len) {
u16 size = le32_to_cpu(notif->amsdu_size);
int i;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index b4d4071b865d..4487cc3e07c1 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -386,6 +386,9 @@ struct iwl_mvm_rxq_dup_data {
* @amsdu_enabled: bitmap of TX AMSDU allowed TIDs.
* In case TLC offload is not active it is either 0xFFFF or 0.
* @max_amsdu_len: max AMSDU length
+ * @orig_amsdu_len: used to save the original amsdu_len when it is changed via
+ * debugfs. If it's set to 0, it means that it is it's not set via
+ * debugfs.
* @agg_tids: bitmap of tids whose status is operational aggregated (IWL_AGG_ON)
* @sleep_tx_count: the number of frames that we told the firmware to let out
* even when that station is asleep. This is useful in case the queue
@@ -434,6 +437,7 @@ struct iwl_mvm_sta {
bool disable_tx;
u16 amsdu_enabled;
u16 max_amsdu_len;
+ u16 orig_amsdu_len;
bool sleeping;
u8 agg_tids;
u8 sleep_tx_count;
--
2.20.1
^ permalink raw reply related
* [PATCH 06/12] iwlwifi: dbg_ini: add consecutive trigger firing support
From: Luca Coelho @ 2019-06-25 9:44 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Shahar S Matityahu, Luca Coelho
In-Reply-To: <20190625094452.19034-1-luca@coelho.fi>
From: Shahar S Matityahu <shahar.s.matityahu@intel.com>
When a dump trigger is fired, the driver sets IWL_FWRT_STATUS_DUMPING and
aborts any consecutive dump collection.
To allow consecutive triggers firing, use 5 dump workers and allocate
them upon incoming dump collection requests.
This functionality is needed since in ini debug mode each trigger may
have entirely different memory regions to collect unlike the legacy
mode in which all the triggers dump the same memory regions.
Signed-off-by: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 76 ++++++++++++-------
drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 19 +++--
drivers/net/wireless/intel/iwlwifi/fw/init.c | 7 +-
.../net/wireless/intel/iwlwifi/fw/runtime.h | 15 ++--
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 16 ++--
6 files changed, 84 insertions(+), 51 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 8e2cf7141f0a..030889e3a10f 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -1912,18 +1912,18 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
}
static struct iwl_fw_error_dump_file *
-iwl_fw_error_ini_dump_file(struct iwl_fw_runtime *fwrt)
+iwl_fw_error_ini_dump_file(struct iwl_fw_runtime *fwrt,
+ enum iwl_fw_ini_trigger_id trig_id)
{
int size;
struct iwl_fw_error_dump_data *dump_data;
struct iwl_fw_error_dump_file *dump_file;
struct iwl_fw_ini_trigger *trigger;
- enum iwl_fw_ini_trigger_id id = fwrt->dump.ini_trig_id;
- if (!iwl_fw_ini_trigger_on(fwrt, id))
+ if (!iwl_fw_ini_trigger_on(fwrt, trig_id))
return NULL;
- trigger = fwrt->dump.active_trigs[id].trig;
+ trigger = fwrt->dump.active_trigs[trig_id].trig;
size = iwl_fw_ini_get_trigger_len(fwrt, trigger);
if (!size)
@@ -1988,16 +1988,16 @@ static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
out:
iwl_fw_free_dump_desc(fwrt);
- clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status);
}
-static void iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt)
+static void iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, u8 wk_idx)
{
+ enum iwl_fw_ini_trigger_id trig_id = fwrt->dump.wks[wk_idx].ini_trig_id;
struct iwl_fw_error_dump_file *dump_file;
struct scatterlist *sg_dump_data;
u32 file_len;
- dump_file = iwl_fw_error_ini_dump_file(fwrt);
+ dump_file = iwl_fw_error_ini_dump_file(fwrt, trig_id);
if (!dump_file)
goto out;
@@ -2012,8 +2012,7 @@ static void iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt)
}
vfree(dump_file);
out:
- fwrt->dump.ini_trig_id = IWL_FW_TRIGGER_ID_INVALID;
- clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status);
+ fwrt->dump.wks[wk_idx].ini_trig_id = IWL_FW_TRIGGER_ID_INVALID;
}
const struct iwl_fw_dump_desc iwl_dump_desc_assert = {
@@ -2039,7 +2038,10 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
return ret;
}
- if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status))
+ /* use wks[0] since dump flow prior to ini does not need to support
+ * consecutive triggers collection
+ */
+ if (test_and_set_bit(fwrt->dump.wks[0].idx, &fwrt->dump.active_wks))
return -EBUSY;
if (WARN_ON(fwrt->dump.desc))
@@ -2051,7 +2053,7 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
fwrt->dump.desc = desc;
fwrt->dump.monitor_only = monitor_only;
- schedule_delayed_work(&fwrt->dump.wk, usecs_to_jiffies(delay));
+ schedule_delayed_work(&fwrt->dump.wks[0].wk, usecs_to_jiffies(delay));
return 0;
}
@@ -2130,13 +2132,11 @@ int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt,
{
struct iwl_fw_ini_active_triggers *active;
u32 occur, delay;
+ unsigned long idx;
if (WARN_ON(!iwl_fw_ini_trigger_on(fwrt, id)))
return -EINVAL;
- if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status))
- return -EBUSY;
-
if (!iwl_fw_ini_trigger_on(fwrt, id)) {
IWL_WARN(fwrt, "WRT: Trigger %d is not active, aborting dump\n",
id);
@@ -2157,14 +2157,24 @@ int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt,
return 0;
}
- if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status))
+ /* Check there is an available worker.
+ * ffz return value is undefined if no zero exists,
+ * so check against ~0UL first.
+ */
+ if (fwrt->dump.active_wks == ~0UL)
return -EBUSY;
- fwrt->dump.ini_trig_id = id;
+ idx = ffz(fwrt->dump.active_wks);
+
+ if (idx >= IWL_FW_RUNTIME_DUMP_WK_NUM ||
+ test_and_set_bit(fwrt->dump.wks[idx].idx, &fwrt->dump.active_wks))
+ return -EBUSY;
+
+ fwrt->dump.wks[idx].ini_trig_id = id;
IWL_WARN(fwrt, "WRT: collecting data: ini trigger %d fired.\n", id);
- schedule_delayed_work(&fwrt->dump.wk, usecs_to_jiffies(delay));
+ schedule_delayed_work(&fwrt->dump.wks[idx].wk, usecs_to_jiffies(delay));
return 0;
}
@@ -2277,32 +2287,31 @@ IWL_EXPORT_SYMBOL(iwl_fw_start_dbg_conf);
/* this function assumes dump_start was called beforehand and dump_end will be
* called afterwards
*/
-void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt)
+static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
{
struct iwl_fw_dbg_params params = {0};
- if (!test_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status))
+ if (!test_bit(wk_idx, &fwrt->dump.active_wks))
return;
if (fwrt->ops && fwrt->ops->fw_running &&
!fwrt->ops->fw_running(fwrt->ops_ctx)) {
IWL_ERR(fwrt, "Firmware not running - cannot dump error\n");
iwl_fw_free_dump_desc(fwrt);
- clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status);
- return;
+ goto out;
}
/* there's no point in fw dump if the bus is dead */
if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) {
IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n");
- return;
+ goto out;
}
iwl_fw_dbg_stop_recording(fwrt, ¶ms);
IWL_DEBUG_FW_INFO(fwrt, "WRT: data collection start\n");
if (fwrt->trans->ini_valid)
- iwl_fw_error_ini_dump(fwrt);
+ iwl_fw_error_ini_dump(fwrt, wk_idx);
else
iwl_fw_error_dump(fwrt);
IWL_DEBUG_FW_INFO(fwrt, "WRT: data collection done\n");
@@ -2314,19 +2323,27 @@ void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt)
udelay(500);
iwl_fw_dbg_restart_recording(fwrt, ¶ms);
}
+
+out:
+ clear_bit(wk_idx, &fwrt->dump.active_wks);
}
-IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_sync);
void iwl_fw_error_dump_wk(struct work_struct *work)
{
- struct iwl_fw_runtime *fwrt =
- container_of(work, struct iwl_fw_runtime, dump.wk.work);
+ struct iwl_fw_runtime *fwrt;
+ typeof(fwrt->dump.wks[0]) *wks;
+ wks = container_of(work, typeof(fwrt->dump.wks[0]), wk.work);
+ fwrt = container_of(wks, struct iwl_fw_runtime, dump.wks[wks->idx]);
+
+ /* assumes the op mode mutex is locked in dump_start since
+ * iwl_fw_dbg_collect_sync can't run in parallel
+ */
if (fwrt->ops && fwrt->ops->dump_start &&
fwrt->ops->dump_start(fwrt->ops_ctx))
return;
- iwl_fw_dbg_collect_sync(fwrt);
+ iwl_fw_dbg_collect_sync(fwrt, wks->idx);
if (fwrt->ops && fwrt->ops->dump_end)
fwrt->ops->dump_end(fwrt->ops_ctx);
@@ -2723,8 +2740,11 @@ IWL_EXPORT_SYMBOL(iwl_fw_dbg_apply_point);
void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt)
{
+ int i;
+
del_timer(&fwrt->dump.periodic_trig);
- iwl_fw_dbg_collect_sync(fwrt);
+ for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++)
+ iwl_fw_dbg_collect_sync(fwrt, i);
iwl_trans_stop_device(fwrt->trans);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
index 4a66d6f48d60..37d5171213c2 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
@@ -383,16 +383,26 @@ static inline bool iwl_fw_dbg_is_paging_enabled(struct iwl_fw_runtime *fwrt)
void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt);
-static inline void iwl_fw_flush_dump(struct iwl_fw_runtime *fwrt)
+static inline void iwl_fw_flush_dumps(struct iwl_fw_runtime *fwrt)
{
+ int i;
+
del_timer(&fwrt->dump.periodic_trig);
- flush_delayed_work(&fwrt->dump.wk);
+ for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) {
+ flush_delayed_work(&fwrt->dump.wks[i].wk);
+ fwrt->dump.wks[i].ini_trig_id = IWL_FW_TRIGGER_ID_INVALID;
+ }
}
-static inline void iwl_fw_cancel_dump(struct iwl_fw_runtime *fwrt)
+static inline void iwl_fw_cancel_dumps(struct iwl_fw_runtime *fwrt)
{
+ int i;
+
del_timer(&fwrt->dump.periodic_trig);
- cancel_delayed_work_sync(&fwrt->dump.wk);
+ for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) {
+ cancel_delayed_work_sync(&fwrt->dump.wks[i].wk);
+ fwrt->dump.wks[i].ini_trig_id = IWL_FW_TRIGGER_ID_INVALID;
+ }
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -431,7 +441,6 @@ static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) {}
#endif /* CONFIG_IWLWIFI_DEBUGFS */
-void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt);
void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
enum iwl_fw_ini_apply_point apply_point);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c
index 4435c0ce3013..c16d6e126e3c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/init.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c
@@ -67,6 +67,8 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
const struct iwl_fw_runtime_ops *ops, void *ops_ctx,
struct dentry *dbgfs_dir)
{
+ int i;
+
memset(fwrt, 0, sizeof(*fwrt));
fwrt->trans = trans;
fwrt->fw = fw;
@@ -74,7 +76,10 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
fwrt->dump.conf = FW_DBG_INVALID;
fwrt->ops = ops;
fwrt->ops_ctx = ops_ctx;
- INIT_DELAYED_WORK(&fwrt->dump.wk, iwl_fw_error_dump_wk);
+ for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) {
+ fwrt->dump.wks[i].idx = i;
+ INIT_DELAYED_WORK(&fwrt->dump.wks[i].wk, iwl_fw_error_dump_wk);
+ }
iwl_fwrt_dbgfs_register(fwrt, dbgfs_dir);
timer_setup(&fwrt->dump.periodic_trig,
iwl_fw_dbg_periodic_trig_handler, 0);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
index a6402a0b3854..e351ac7ae53b 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
@@ -89,9 +89,7 @@ struct iwl_fwrt_shared_mem_cfg {
u32 internal_txfifo_size[TX_FIFO_INTERNAL_MAX_NUM];
};
-enum iwl_fw_runtime_status {
- IWL_FWRT_STATUS_DUMPING = 0,
-};
+#define IWL_FW_RUNTIME_DUMP_WK_NUM 5
/**
* struct iwl_fw_runtime - runtime data for firmware
@@ -100,7 +98,6 @@ enum iwl_fw_runtime_status {
* @dev: device pointer
* @ops: user ops
* @ops_ctx: user ops context
- * @status: status flags
* @fw_paging_db: paging database
* @num_of_paging_blk: number of paging blocks
* @num_of_pages_in_last_blk: number of pages in the last block
@@ -117,8 +114,6 @@ struct iwl_fw_runtime {
const struct iwl_fw_runtime_ops *ops;
void *ops_ctx;
- unsigned long status;
-
/* Paging */
struct iwl_fw_paging fw_paging_db[NUM_OF_FW_PAGING_BLOCKS];
u16 num_of_paging_blk;
@@ -133,7 +128,12 @@ struct iwl_fw_runtime {
struct {
const struct iwl_fw_dump_desc *desc;
bool monitor_only;
- struct delayed_work wk;
+ struct {
+ u8 idx;
+ enum iwl_fw_ini_trigger_id ini_trig_id;
+ struct delayed_work wk;
+ } wks[IWL_FW_RUNTIME_DUMP_WK_NUM];
+ unsigned long active_wks;
u8 conf;
@@ -145,7 +145,6 @@ struct iwl_fw_runtime {
u32 lmac_err_id[MAX_NUM_LMAC];
u32 umac_err_id;
void *fifo_iter;
- enum iwl_fw_ini_trigger_id ini_trig_id;
struct timer_list periodic_trig;
} dump;
#ifdef CONFIG_IWLWIFI_DEBUGFS
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 5c52469288be..5f7ed51c96ab 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1439,7 +1439,7 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
*/
clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
- iwl_fw_cancel_dump(&mvm->fwrt);
+ iwl_fw_cancel_dumps(&mvm->fwrt);
cancel_delayed_work_sync(&mvm->cs_tx_unblock_dwork);
cancel_delayed_work_sync(&mvm->scan_timeout_dwork);
iwl_fw_free_dump_desc(&mvm->fwrt);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index acd2fda12466..6514e045c901 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -564,24 +564,24 @@ static void iwl_mvm_tx_unblock_dwork(struct work_struct *work)
static int iwl_mvm_fwrt_dump_start(void *ctx)
{
struct iwl_mvm *mvm = ctx;
- int ret;
+ int ret = 0;
+
+ mutex_lock(&mvm->mutex);
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_FW_DBG_COLLECT);
if (ret)
- return ret;
-
- mutex_lock(&mvm->mutex);
+ mutex_unlock(&mvm->mutex);
- return 0;
+ return ret;
}
static void iwl_mvm_fwrt_dump_end(void *ctx)
{
struct iwl_mvm *mvm = ctx;
- mutex_unlock(&mvm->mutex);
-
iwl_mvm_unref(mvm, IWL_MVM_REF_FW_DBG_COLLECT);
+
+ mutex_unlock(&mvm->mutex);
}
static bool iwl_mvm_fwrt_fw_running(void *ctx)
@@ -880,7 +880,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
return op_mode;
out_free:
- iwl_fw_flush_dump(&mvm->fwrt);
+ iwl_fw_flush_dumps(&mvm->fwrt);
iwl_fw_runtime_free(&mvm->fwrt);
if (iwlmvm_mod_params.init_dbg)
--
2.20.1
^ permalink raw reply related
* [PATCH 05/12] iwlwifi: dbg_ini: abort region collection in case the size is 0
From: Luca Coelho @ 2019-06-25 9:44 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Shahar S Matityahu, Luca Coelho
In-Reply-To: <20190625094452.19034-1-luca@coelho.fi>
From: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Allows to abort region collection in case the region size is 0.
It is needed for future regions that their size might be 0.
Signed-off-by: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 53 +++++++++++++--------
1 file changed, 33 insertions(+), 20 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index ca4dea1dceba..8e2cf7141f0a 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -1674,20 +1674,24 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_mem_ops *ops)
{
struct iwl_fw_ini_error_dump_header *header = (void *)(*data)->data;
- u32 num_of_ranges, i, type = le32_to_cpu(reg->region_type);
+ u32 num_of_ranges, i, type = le32_to_cpu(reg->region_type), size;
void *range;
if (WARN_ON(!ops || !ops->get_num_of_ranges || !ops->get_size ||
!ops->fill_mem_hdr || !ops->fill_range))
return;
+ size = ops->get_size(fwrt, reg);
+ if (!size)
+ return;
+
IWL_DEBUG_FW(fwrt, "WRT: collecting region: id=%d, type=%d\n",
le32_to_cpu(reg->region_id), type);
num_of_ranges = ops->get_num_of_ranges(fwrt, reg);
(*data)->type = cpu_to_le32(type | INI_DUMP_BIT);
- (*data)->len = cpu_to_le32(ops->get_size(fwrt, reg));
+ (*data)->len = cpu_to_le32(size);
header->region_id = reg->region_id;
header->num_of_ranges = cpu_to_le32(num_of_ranges);
@@ -1700,7 +1704,7 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
IWL_ERR(fwrt,
"WRT: failed to fill region header: id=%d, type=%d\n",
le32_to_cpu(reg->region_id), type);
- memset(*data, 0, le32_to_cpu((*data)->len));
+ memset(*data, 0, size);
return;
}
@@ -1711,7 +1715,7 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
IWL_ERR(fwrt,
"WRT: failed to dump region: id=%d, type=%d\n",
le32_to_cpu(reg->region_id), type);
- memset(*data, 0, le32_to_cpu((*data)->len));
+ memset(*data, 0, size);
return;
}
range = range + range_size;
@@ -1722,7 +1726,8 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_trigger *trigger)
{
- int i, size = 0, hdr_len = sizeof(struct iwl_fw_error_dump_data);
+ int i, ret_size = 0, hdr_len = sizeof(struct iwl_fw_error_dump_data);
+ u32 size;
if (!trigger || !trigger->num_regions)
return 0;
@@ -1754,32 +1759,40 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
case IWL_FW_INI_REGION_CSR:
case IWL_FW_INI_REGION_LMAC_ERROR_TABLE:
case IWL_FW_INI_REGION_UMAC_ERROR_TABLE:
- size += hdr_len + iwl_dump_ini_mem_get_size(fwrt, reg);
+ size = iwl_dump_ini_mem_get_size(fwrt, reg);
+ if (size)
+ ret_size += hdr_len + size;
break;
case IWL_FW_INI_REGION_TXF:
- size += hdr_len + iwl_dump_ini_txf_get_size(fwrt, reg);
+ size = iwl_dump_ini_txf_get_size(fwrt, reg);
+ if (size)
+ ret_size += hdr_len + size;
break;
case IWL_FW_INI_REGION_RXF:
- size += hdr_len + iwl_dump_ini_rxf_get_size(fwrt, reg);
+ size = iwl_dump_ini_rxf_get_size(fwrt, reg);
+ if (size)
+ ret_size += hdr_len + size;
break;
case IWL_FW_INI_REGION_PAGING:
- size += hdr_len;
- if (iwl_fw_dbg_is_paging_enabled(fwrt)) {
- size += iwl_dump_ini_paging_get_size(fwrt, reg);
- } else {
- size += iwl_dump_ini_paging_gen2_get_size(fwrt,
- reg);
- }
+ if (iwl_fw_dbg_is_paging_enabled(fwrt))
+ size = iwl_dump_ini_paging_get_size(fwrt, reg);
+ else
+ size = iwl_dump_ini_paging_gen2_get_size(fwrt,
+ reg);
+ if (size)
+ ret_size += hdr_len + size;
break;
case IWL_FW_INI_REGION_DRAM_BUFFER:
if (!fwrt->trans->num_blocks)
break;
- size += hdr_len +
- iwl_dump_ini_mon_dram_get_size(fwrt, reg);
+ size = iwl_dump_ini_mon_dram_get_size(fwrt, reg);
+ if (size)
+ ret_size += hdr_len + size;
break;
case IWL_FW_INI_REGION_INTERNAL_BUFFER:
- size += hdr_len +
- iwl_dump_ini_mon_smem_get_size(fwrt, reg);
+ size = iwl_dump_ini_mon_smem_get_size(fwrt, reg);
+ if (size)
+ ret_size += hdr_len + size;
break;
case IWL_FW_INI_REGION_DRAM_IMR:
/* Undefined yet */
@@ -1787,7 +1800,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
break;
}
}
- return size;
+ return ret_size;
}
static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
--
2.20.1
^ permalink raw reply related
* [PATCH 03/12] iwlwifi: dbg_ini: dump headers cleanup
From: Luca Coelho @ 2019-06-25 9:44 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Shahar S Matityahu, Luca Coelho
In-Reply-To: <20190625094452.19034-1-luca@coelho.fi>
From: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Unite dump memory ranges under a single struct and add a specific header
for each type of memory.
Also, maintain a single version to all dump structures.
This cleanup is also needed for the future addition of FW notification
regions and others.
Signed-off-by: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 57 ++++++++----------
drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 3 -
.../wireless/intel/iwlwifi/fw/error-dump.h | 59 +++++++++----------
3 files changed, 52 insertions(+), 67 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 5650b57a64e9..ca4dea1dceba 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -1059,7 +1059,7 @@ static int iwl_dump_ini_prph_iter(struct iwl_fw_runtime *fwrt,
u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset);
int i;
- range->start_addr = cpu_to_le64(addr);
+ range->internal_base_addr = cpu_to_le32(addr);
range->range_data_size = reg->internal.range_data_size;
for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) {
prph_val = iwl_read_prph(fwrt->trans, addr + i);
@@ -1080,7 +1080,7 @@ static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt,
u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset);
int i;
- range->start_addr = cpu_to_le64(addr);
+ range->internal_base_addr = cpu_to_le32(addr);
range->range_data_size = reg->internal.range_data_size;
for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4)
*val++ = cpu_to_le32(iwl_trans_read32(fwrt->trans, addr + i));
@@ -1095,7 +1095,7 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_error_dump_range *range = range_ptr;
u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset);
- range->start_addr = cpu_to_le64(addr);
+ range->internal_base_addr = cpu_to_le32(addr);
range->range_data_size = reg->internal.range_data_size;
iwl_trans_read_mem_bytes(fwrt->trans, addr, range->data,
le32_to_cpu(reg->internal.range_data_size));
@@ -1111,7 +1111,7 @@ iwl_dump_ini_paging_gen2_iter(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_error_dump_range *range = range_ptr;
u32 page_size = fwrt->trans->init_dram.paging[idx].size;
- range->start_addr = cpu_to_le64(idx);
+ range->page_num = cpu_to_le32(idx);
range->range_data_size = cpu_to_le32(page_size);
memcpy(range->data, fwrt->trans->init_dram.paging[idx].block,
page_size);
@@ -1131,7 +1131,7 @@ static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
dma_addr_t addr = fwrt->fw_paging_db[idx].fw_paging_phys;
u32 page_size = fwrt->fw_paging_db[idx].fw_paging_size;
- range->start_addr = cpu_to_le64(idx);
+ range->page_num = cpu_to_le32(idx);
range->range_data_size = cpu_to_le32(page_size);
dma_sync_single_for_cpu(fwrt->trans->dev, addr, page_size,
DMA_BIDIRECTIONAL);
@@ -1154,7 +1154,7 @@ iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt,
if (start_addr == 0x5a5a5a5a)
return -EBUSY;
- range->start_addr = cpu_to_le64(start_addr);
+ range->dram_base_addr = cpu_to_le64(start_addr);
range->range_data_size = cpu_to_le32(fwrt->trans->fw_mon[idx].size);
memcpy(range->data, fwrt->trans->fw_mon[idx].block,
@@ -1228,7 +1228,7 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_region_cfg *reg,
void *range_ptr, int idx)
{
- struct iwl_fw_ini_fifo_error_dump_range *range = range_ptr;
+ struct iwl_fw_ini_error_dump_range *range = range_ptr;
struct iwl_ini_txf_iter_data *iter;
struct iwl_fw_ini_error_dump_register *reg_dump = (void *)range->data;
u32 offs = le32_to_cpu(reg->offset), addr;
@@ -1246,8 +1246,8 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
iter = fwrt->dump.fifo_iter;
- range->fifo_num = cpu_to_le32(iter->fifo);
- range->num_of_registers = reg->fifos.num_of_registers;
+ range->fifo_hdr.fifo_num = cpu_to_le32(iter->fifo);
+ range->fifo_hdr.num_of_registers = reg->fifos.num_of_registers;
range->range_data_size = cpu_to_le32(iter->fifo_size + registers_size);
iwl_write_prph_no_grab(fwrt->trans, TXF_LARC_NUM + offs, iter->fifo);
@@ -1336,7 +1336,7 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_region_cfg *reg,
void *range_ptr, int idx)
{
- struct iwl_fw_ini_fifo_error_dump_range *range = range_ptr;
+ struct iwl_fw_ini_error_dump_range *range = range_ptr;
struct iwl_ini_rxf_data rxf_data;
struct iwl_fw_ini_error_dump_register *reg_dump = (void *)range->data;
u32 offs = le32_to_cpu(reg->offset), addr;
@@ -1353,8 +1353,8 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
if (!iwl_trans_grab_nic_access(fwrt->trans, &flags))
return -EBUSY;
- range->fifo_num = cpu_to_le32(rxf_data.fifo_num);
- range->num_of_registers = reg->fifos.num_of_registers;
+ range->fifo_hdr.fifo_num = cpu_to_le32(rxf_data.fifo_num);
+ range->fifo_hdr.num_of_registers = reg->fifos.num_of_registers;
range->range_data_size = cpu_to_le32(rxf_data.size + registers_size);
/*
@@ -1408,7 +1408,7 @@ static void *iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt,
{
struct iwl_fw_ini_error_dump *dump = data;
- dump->header.version = cpu_to_le32(IWL_INI_DUMP_MEM_VER);
+ dump->header.version = cpu_to_le32(IWL_INI_DUMP_VER);
return dump->ranges;
}
@@ -1433,7 +1433,7 @@ static void
iwl_trans_release_nic_access(fwrt->trans, &flags);
- data->header.version = cpu_to_le32(IWL_INI_DUMP_MONITOR_VER);
+ data->header.version = cpu_to_le32(IWL_INI_DUMP_VER);
data->write_ptr = cpu_to_le32(write_ptr & write_ptr_msk);
data->cycle_cnt = cpu_to_le32(cycle_cnt & cycle_cnt_msk);
@@ -1490,17 +1490,6 @@ static void
}
-static void *iwl_dump_ini_fifo_fill_header(struct iwl_fw_runtime *fwrt,
- struct iwl_fw_ini_region_cfg *reg,
- void *data)
-{
- struct iwl_fw_ini_fifo_error_dump *dump = data;
-
- dump->header.version = cpu_to_le32(IWL_INI_DUMP_FIFO_VER);
-
- return dump->ranges;
-}
-
static u32 iwl_dump_ini_mem_ranges(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_region_cfg *reg)
{
@@ -1613,8 +1602,9 @@ static u32 iwl_dump_ini_txf_get_size(struct iwl_fw_runtime *fwrt,
struct iwl_ini_txf_iter_data iter = { .init = true };
void *fifo_iter = fwrt->dump.fifo_iter;
u32 size = 0;
- u32 fifo_hdr = sizeof(struct iwl_fw_ini_fifo_error_dump_range) +
- le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32) * 2;
+ u32 fifo_hdr = sizeof(struct iwl_fw_ini_error_dump_range) +
+ le32_to_cpu(reg->fifos.num_of_registers) *
+ sizeof(struct iwl_fw_ini_error_dump_register);
fwrt->dump.fifo_iter = &iter;
while (iwl_ini_txf_iter(fwrt, reg)) {
@@ -1624,7 +1614,7 @@ static u32 iwl_dump_ini_txf_get_size(struct iwl_fw_runtime *fwrt,
}
if (size)
- size += sizeof(struct iwl_fw_ini_fifo_error_dump);
+ size += sizeof(struct iwl_fw_ini_error_dump);
fwrt->dump.fifo_iter = fifo_iter;
@@ -1635,9 +1625,10 @@ static u32 iwl_dump_ini_rxf_get_size(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_region_cfg *reg)
{
struct iwl_ini_rxf_data rx_data;
- u32 size = sizeof(struct iwl_fw_ini_fifo_error_dump) +
- sizeof(struct iwl_fw_ini_fifo_error_dump_range) +
- le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32) * 2;
+ u32 size = sizeof(struct iwl_fw_ini_error_dump) +
+ sizeof(struct iwl_fw_ini_error_dump_range) +
+ le32_to_cpu(reg->fifos.num_of_registers) *
+ sizeof(struct iwl_fw_ini_error_dump_register);
if (reg->fifos.header_only)
return size;
@@ -1879,7 +1870,7 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
fwrt->dump.fifo_iter = &iter;
ops.get_num_of_ranges = iwl_dump_ini_txf_ranges;
ops.get_size = iwl_dump_ini_txf_get_size;
- ops.fill_mem_hdr = iwl_dump_ini_fifo_fill_header;
+ ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
ops.fill_range = iwl_dump_ini_txf_iter;
iwl_dump_ini_mem(fwrt, data, reg, &ops);
fwrt->dump.fifo_iter = fifo_iter;
@@ -1888,7 +1879,7 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
case IWL_FW_INI_REGION_RXF:
ops.get_num_of_ranges = iwl_dump_ini_rxf_ranges;
ops.get_size = iwl_dump_ini_rxf_get_size;
- ops.fill_mem_hdr = iwl_dump_ini_fifo_fill_header;
+ ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
ops.fill_range = iwl_dump_ini_rxf_iter;
iwl_dump_ini_mem(fwrt, data, reg, &ops);
break;
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
index 2a9e560a906b..4a66d6f48d60 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
@@ -457,9 +457,6 @@ static inline void iwl_fw_umac_set_alive_err_table(struct iwl_trans *trans,
trans->umac_error_event_table = umac_error_event_table;
}
-/* This bit is used to differentiate the legacy dump from the ini dump */
-#define INI_DUMP_BIT BIT(31)
-
static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt)
{
if (fwrt->trans->ini_valid && fwrt->trans->hw_error) {
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
index 0feff4c33e39..4ee9418c949b 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
@@ -278,19 +278,42 @@ struct iwl_fw_error_dump_mem {
u8 data[];
};
-#define IWL_INI_DUMP_MEM_VER 1
-#define IWL_INI_DUMP_MONITOR_VER 1
-#define IWL_INI_DUMP_FIFO_VER 1
+/* Dump version, used by the dump parser to differentiate between
+ * different dump formats
+ */
+#define IWL_INI_DUMP_VER 1
+
+/* This bit is used to differentiate the legacy dump from the ini dump */
+#define INI_DUMP_BIT BIT(31)
+
+/**
+ * struct iwl_fw_ini_fifo_hdr - fifo range header
+ * @fifo_num: the fifo number. In case of umac rx fifo, set BIT(31) to
+ * distinguish between lmac and umac rx fifos
+ * @num_of_registers: num of registers to dump, dword size each
+ */
+struct iwl_fw_ini_fifo_hdr {
+ __le32 fifo_num;
+ __le32 num_of_registers;
+} __packed;
/**
* struct iwl_fw_ini_error_dump_range - range of memory
* @range_data_size: the size of this range, in bytes
- * @start_addr: the start address of this range
+ * @internal_base_addr - base address of internal memory range
+ * @dram_base_addr - base address of dram monitor range
+ * @page_num - page number of memory range
+ * @fifo_hdr - fifo header of memory range
* @data: the actual memory
*/
struct iwl_fw_ini_error_dump_range {
__le32 range_data_size;
- __le64 start_addr;
+ union {
+ __le32 internal_base_addr;
+ __le64 dram_base_addr;
+ __le32 page_num;
+ struct iwl_fw_ini_fifo_hdr fifo_hdr;
+ };
__le32 data[];
} __packed;
@@ -333,32 +356,6 @@ struct iwl_fw_ini_error_dump_register {
__le32 data;
} __packed;
-/**
- * struct iwl_fw_ini_fifo_error_dump_range - ini fifo range dump
- * @fifo_num: the fifo num. In case of rxf and umac rxf, set BIT(31) to
- * distinguish between lmac and umac
- * @num_of_registers: num of registers to dump, dword size each
- * @range_data_size: the size of the data
- * @data: consist of
- * num_of_registers * (register address + register value) + fifo data
- */
-struct iwl_fw_ini_fifo_error_dump_range {
- __le32 fifo_num;
- __le32 num_of_registers;
- __le32 range_data_size;
- __le32 data[];
-} __packed;
-
-/**
- * struct iwl_fw_ini_fifo_error_dump - ini fifo region dump
- * @header: the header of this region
- * @ranges: the memory ranges of this region
- */
-struct iwl_fw_ini_fifo_error_dump {
- struct iwl_fw_ini_error_dump_header header;
- struct iwl_fw_ini_fifo_error_dump_range ranges[];
-} __packed;
-
/**
* struct iwl_fw_error_dump_rb - content of an Receive Buffer
* @index: the index of the Receive Buffer in the Rx queue
--
2.20.1
^ permalink raw reply related
* [PATCH 02/12] iwlwifi: dbg: allow dump collection in case of an early error
From: Luca Coelho @ 2019-06-25 9:44 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Shahar S Matityahu, Luca Coelho
In-Reply-To: <20190625094452.19034-1-luca@coelho.fi>
From: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Improve the robustness of the dump collection flow in case of an early
error:
1. in iwl_trans_pcie_sync_nmi, disable and enable interrupts only if
they were already enabled
2. attempt to initiate dump collection in iwl_fw_dbg_error_collect only
if the device is enabled
3. check Tx command queue was already allocated before trying to collect it
Signed-off-by: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 7 +++++--
.../net/wireless/intel/iwlwifi/pcie/trans.c | 21 +++++++++++++++----
2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 5f52e40a2903..5650b57a64e9 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -2057,9 +2057,12 @@ int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt,
enum iwl_fw_dbg_trigger trig_type)
{
int ret;
- struct iwl_fw_dump_desc *iwl_dump_error_desc =
- kmalloc(sizeof(*iwl_dump_error_desc), GFP_KERNEL);
+ struct iwl_fw_dump_desc *iwl_dump_error_desc;
+ if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status))
+ return -EIO;
+
+ iwl_dump_error_desc = kmalloc(sizeof(*iwl_dump_error_desc), GFP_KERNEL);
if (!iwl_dump_error_desc)
return -ENOMEM;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index 803fcbac4152..ca486a7af602 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -3172,7 +3172,7 @@ static struct iwl_trans_dump_data
len = sizeof(*dump_data);
/* host commands */
- if (dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD))
+ if (dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD) && cmdq)
len += sizeof(*data) +
cmdq->n_window * (sizeof(*txcmd) +
TFD_MAX_PAYLOAD_SIZE);
@@ -3224,7 +3224,7 @@ static struct iwl_trans_dump_data
len = 0;
data = (void *)dump_data->data;
- if (dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD)) {
+ if (dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD) && cmdq) {
u16 tfd_size = trans_pcie->tfd_size;
data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD);
@@ -3658,6 +3658,7 @@ void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT;
+ bool interrupts_enabled = test_bit(STATUS_INT_ENABLED, &trans->status);
u32 inta_addr, sw_err_bit;
if (trans_pcie->msix_enabled) {
@@ -3668,7 +3669,12 @@ void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)
sw_err_bit = CSR_INT_BIT_SW_ERR;
}
- iwl_disable_interrupts(trans);
+ /* if the interrupts were already disabled, there is no point in
+ * calling iwl_disable_interrupts
+ */
+ if (interrupts_enabled)
+ iwl_disable_interrupts(trans);
+
iwl_force_nmi(trans);
while (time_after(timeout, jiffies)) {
u32 inta_hw = iwl_read32(trans, inta_addr);
@@ -3682,6 +3688,13 @@ void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)
mdelay(1);
}
- iwl_enable_interrupts(trans);
+
+ /* enable interrupts only if there were already enabled before this
+ * function to avoid a case were the driver enable interrupts before
+ * proper configurations were made
+ */
+ if (interrupts_enabled)
+ iwl_enable_interrupts(trans);
+
iwl_trans_fw_error(trans);
}
--
2.20.1
^ permalink raw reply related
* [PATCH 10/12] iwlwifi: dbg_ini: implement dump info collection
From: Luca Coelho @ 2019-06-25 9:44 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Shahar S Matityahu, Luca Coelho
In-Reply-To: <20190625094452.19034-1-luca@coelho.fi>
From: Shahar S Matityahu <shahar.s.matityahu@intel.com>
The info struct contains data about the FW, HW, RF and the debug
configuration.
Signed-off-by: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 67 +++++++++++++++++++
drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 18 +++++
.../wireless/intel/iwlwifi/fw/error-dump.h | 62 +++++++++++++++++
.../net/wireless/intel/iwlwifi/fw/runtime.h | 9 +++
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 2 +
5 files changed, 158 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 806eb9847f72..0c366009389e 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -1723,6 +1723,65 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
*data = iwl_fw_error_next_data(*data);
}
+static void iwl_dump_ini_info(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_trigger *trigger,
+ struct iwl_fw_error_dump_data **data)
+{
+ struct iwl_fw_ini_dump_info *dump = (void *)(*data)->data;
+ u32 reg_ids_size = le32_to_cpu(trigger->num_regions) * sizeof(__le32);
+
+ (*data)->type = cpu_to_le32(IWL_INI_DUMP_INFO_TYPE);
+ (*data)->len = cpu_to_le32(sizeof(*dump) + reg_ids_size);
+
+ dump->version = cpu_to_le32(IWL_INI_DUMP_VER);
+ dump->trigger_id = trigger->trigger_id;
+ dump->is_external_cfg = cpu_to_le32(fwrt->trans->external_ini_loaded);
+
+ dump->ver_type = cpu_to_le32(fwrt->dump.fw_ver.type);
+ dump->ver_subtype = cpu_to_le32(fwrt->dump.fw_ver.subtype);
+
+ dump->hw_step = cpu_to_le32(CSR_HW_REV_STEP(fwrt->trans->hw_rev));
+ dump->hw_type = cpu_to_le32(CSR_HW_REV_TYPE(fwrt->trans->hw_rev));
+
+ dump->rf_id_flavor =
+ cpu_to_le32(CSR_HW_RFID_FLAVOR(fwrt->trans->hw_rf_id));
+ dump->rf_id_dash = cpu_to_le32(CSR_HW_RFID_DASH(fwrt->trans->hw_rf_id));
+ dump->rf_id_step = cpu_to_le32(CSR_HW_RFID_STEP(fwrt->trans->hw_rf_id));
+ dump->rf_id_type = cpu_to_le32(CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id));
+
+ dump->lmac_major = cpu_to_le32(fwrt->dump.fw_ver.lmac_major);
+ dump->lmac_minor = cpu_to_le32(fwrt->dump.fw_ver.lmac_minor);
+ dump->umac_major = cpu_to_le32(fwrt->dump.fw_ver.umac_major);
+ dump->umac_minor = cpu_to_le32(fwrt->dump.fw_ver.umac_minor);
+
+ dump->build_tag_len = cpu_to_le32(sizeof(dump->build_tag));
+ memcpy(dump->build_tag, fwrt->fw->human_readable,
+ sizeof(dump->build_tag));
+
+ dump->img_name_len = cpu_to_le32(sizeof(dump->img_name));
+ memcpy(dump->img_name, fwrt->dump.img_name, sizeof(dump->img_name));
+
+ dump->internal_dbg_cfg_name_len =
+ cpu_to_le32(sizeof(dump->internal_dbg_cfg_name));
+ memcpy(dump->internal_dbg_cfg_name, fwrt->dump.internal_dbg_cfg_name,
+ sizeof(dump->internal_dbg_cfg_name));
+
+ dump->external_dbg_cfg_name_len =
+ cpu_to_le32(sizeof(dump->external_dbg_cfg_name));
+
+ /* dump info size is allocated in iwl_fw_ini_get_trigger_len.
+ * The driver allocates (sizeof(*dump) + reg_ids_size) so it is safe to
+ * use reg_ids_size
+ */
+ memcpy(dump->external_dbg_cfg_name, fwrt->dump.external_dbg_cfg_name,
+ sizeof(dump->external_dbg_cfg_name));
+
+ dump->regions_num = trigger->num_regions;
+ memcpy(dump->region_ids, trigger->data, reg_ids_size);
+
+ *data = iwl_fw_error_next_data(*data);
+}
+
static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_trigger *trigger)
{
@@ -1800,6 +1859,12 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
break;
}
}
+
+ /* add dump info size */
+ if (ret_size)
+ ret_size += hdr_len + sizeof(struct iwl_fw_ini_dump_info) +
+ (le32_to_cpu(trigger->num_regions) * sizeof(__le32));
+
return ret_size;
}
@@ -1809,6 +1874,8 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,
{
int i, num = le32_to_cpu(trigger->num_regions);
+ iwl_dump_ini_info(fwrt, trigger, data);
+
for (i = 0; i < num; i++) {
u32 reg_id = le32_to_cpu(trigger->data[i]);
struct iwl_fw_ini_region_cfg *reg;
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
index 37d5171213c2..d009c0aa95d7 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
@@ -73,6 +73,7 @@
#include "error-dump.h"
#include "api/commands.h"
#include "api/dbg-tlv.h"
+#include "api/alive.h"
/**
* struct iwl_fw_dump_desc - describes the dump
@@ -477,4 +478,21 @@ static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt)
}
void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t);
+
+static inline void iwl_fwrt_update_fw_versions(struct iwl_fw_runtime *fwrt,
+ struct iwl_lmac_alive *lmac,
+ struct iwl_umac_alive *umac)
+{
+ if (lmac) {
+ fwrt->dump.fw_ver.type = lmac->ver_type;
+ fwrt->dump.fw_ver.subtype = lmac->ver_subtype;
+ fwrt->dump.fw_ver.lmac_major = le32_to_cpu(lmac->ucode_major);
+ fwrt->dump.fw_ver.lmac_minor = le32_to_cpu(lmac->ucode_minor);
+ }
+
+ if (umac) {
+ fwrt->dump.fw_ver.umac_major = le32_to_cpu(umac->umac_major);
+ fwrt->dump.fw_ver.umac_minor = le32_to_cpu(umac->umac_minor);
+ }
+}
#endif /* __iwl_fw_dbg_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
index 50c5840644d0..00a45ea85b69 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
@@ -284,6 +284,9 @@ struct iwl_fw_error_dump_mem {
*/
#define IWL_INI_DUMP_VER 1
+/* Use bit 31 as dump info type to avoid colliding with region types */
+#define IWL_INI_DUMP_INFO_TYPE BIT(31)
+
/**
* struct iwl_fw_ini_fifo_hdr - fifo range header
* @fifo_num: the fifo number. In case of umac rx fifo, set BIT(31) to
@@ -354,6 +357,65 @@ struct iwl_fw_ini_error_dump_register {
__le32 data;
} __packed;
+/* struct iwl_fw_ini_dump_info - ini dump information
+ * @version: dump version
+ * @trigger_id: trigger id that caused the dump collection
+ * @trigger_reason: not supported yet
+ * @is_external_cfg: 1 if an external debug configuration was loaded
+ * and 0 otherwise
+ * @ver_type: FW version type
+ * @ver_subtype: FW version subype
+ * @hw_step: HW step
+ * @hw_type: HW type
+ * @rf_id_flavor: HW RF id flavor
+ * @rf_id_dash: HW RF id dash
+ * @rf_id_step: HW RF id step
+ * @rf_id_type: HW RF id type
+ * @lmac_major: lmac major version
+ * @lmac_minor: lmac minor version
+ * @umac_major: umac major version
+ * @umac_minor: umac minor version
+ * @build_tag_len: length of the build tag
+ * @build_tag: build tag string
+ * @img_name_len: length of the FW image name
+ * @img_name: FW image name
+ * @internal_dbg_cfg_name_len: length of the internal debug configuration name
+ * @internal_dbg_cfg_name: internal debug configuration name
+ * @external_dbg_cfg_name_len: length of the external debug configuration name
+ * @external_dbg_cfg_name: external debug configuration name
+ * @regions_num: number of region ids
+ * @region_ids: region ids the trigger configured to collect
+ */
+struct iwl_fw_ini_dump_info {
+ __le32 version;
+ __le32 trigger_id;
+ __le32 trigger_reason;
+ __le32 is_external_cfg;
+ __le32 ver_type;
+ __le32 ver_subtype;
+ __le32 hw_step;
+ __le32 hw_type;
+ __le32 rf_id_flavor;
+ __le32 rf_id_dash;
+ __le32 rf_id_step;
+ __le32 rf_id_type;
+ __le32 lmac_major;
+ __le32 lmac_minor;
+ __le32 umac_major;
+ __le32 umac_minor;
+ __le32 build_tag_len;
+ u8 build_tag[FW_VER_HUMAN_READABLE_SZ];
+ __le32 img_name_len;
+ u8 img_name[IWL_FW_INI_MAX_IMG_NAME_LEN];
+ __le32 internal_dbg_cfg_name_len;
+ u8 internal_dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
+ __le32 external_dbg_cfg_name_len;
+ u8 external_dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
+ __le32 regions_num;
+ __le32 region_ids[];
+
+} __packed;
+
/**
* struct iwl_fw_error_dump_rb - content of an Receive Buffer
* @index: the index of the Receive Buffer in the Rx queue
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
index 07196a9fa5db..406ef73992c1 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
@@ -150,6 +150,15 @@ struct iwl_fw_runtime {
u8 img_name[IWL_FW_INI_MAX_IMG_NAME_LEN];
u8 internal_dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
u8 external_dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
+
+ struct {
+ u8 type;
+ u8 subtype;
+ u32 lmac_major;
+ u32 lmac_minor;
+ u32 umac_major;
+ u32 umac_minor;
+ } fw_ver;
} dump;
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index ab68b5d53ec9..78dc37bf4fa7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -276,6 +276,8 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
le32_to_cpu(umac->umac_major),
le32_to_cpu(umac->umac_minor));
+ iwl_fwrt_update_fw_versions(&mvm->fwrt, lmac1, umac);
+
return true;
}
--
2.20.1
^ permalink raw reply related
* [PATCH 12/12] iwlwifi: fw api: support adwell HB default APs number api
From: Luca Coelho @ 2019-06-25 9:44 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Shahar S Matityahu, Luca Coelho
In-Reply-To: <20190625094452.19034-1-luca@coelho.fi>
From: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Support adaptive dwell high band default number of APs new api.
Signed-off-by: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/fw/api/scan.h | 15 +++++++++++++++
drivers/net/wireless/intel/iwlwifi/fw/file.h | 1 +
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 6 ++++++
drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 12 +++++++++---
4 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
index 1a67a2a439ab..c4960f045415 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
@@ -750,6 +750,21 @@ struct iwl_scan_req_umac {
struct iwl_scan_umac_chan_param channel;
u8 data[];
} v8; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_8 */
+ struct {
+ u8 active_dwell[SCAN_TWO_LMACS];
+ u8 adwell_default_hb_n_aps;
+ u8 adwell_default_lb_n_aps;
+ u8 adwell_default_n_aps_social;
+ u8 general_flags2;
+ __le16 adwell_max_budget;
+ __le32 max_out_time[SCAN_TWO_LMACS];
+ __le32 suspend_time[SCAN_TWO_LMACS];
+ __le32 scan_priority;
+ u8 passive_dwell[SCAN_TWO_LMACS];
+ u8 num_of_fragments[SCAN_TWO_LMACS];
+ struct iwl_scan_umac_chan_param channel;
+ u8 data[];
+ } v9; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_9 */
};
} __packed;
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h
index 71438c40a637..7b65a94ba7dd 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/file.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h
@@ -319,6 +319,7 @@ enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_MBSSID_HE = (__force iwl_ucode_tlv_api_t)52,
IWL_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE = (__force iwl_ucode_tlv_api_t)53,
IWL_UCODE_TLV_API_FTM_RTT_ACCURACY = (__force iwl_ucode_tlv_api_t)54,
+ IWL_UCODE_TLV_API_ADWELL_HB_DEF_N_AP = (__force iwl_ucode_tlv_api_t)57,
NUM_IWL_UCODE_TLV_API
#ifdef __CHECKER__
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 0c938fe4cbe7..e3614f59d274 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1308,6 +1308,12 @@ static inline bool iwl_mvm_is_adaptive_dwell_v2_supported(struct iwl_mvm *mvm)
IWL_UCODE_TLV_API_ADAPTIVE_DWELL_V2);
}
+static inline bool iwl_mvm_is_adwell_hb_ap_num_supported(struct iwl_mvm *mvm)
+{
+ return fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_ADWELL_HB_DEF_N_AP);
+}
+
static inline bool iwl_mvm_is_oce_supported(struct iwl_mvm *mvm)
{
/* OCE should never be enabled for LMAC scan FWs */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index d9ddf9ff6428..c284e6975b1b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -83,8 +83,10 @@
#define IWL_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN 300
/* adaptive dwell max budget time [TU] for directed scan */
#define IWL_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN 100
-/* adaptive dwell default APs number */
-#define IWL_SCAN_ADWELL_DEFAULT_N_APS 2
+/* adaptive dwell default high band APs number */
+#define IWL_SCAN_ADWELL_DEFAULT_HB_N_APS 8
+/* adaptive dwell default low band APs number */
+#define IWL_SCAN_ADWELL_DEFAULT_LB_N_APS 2
/* adaptive dwell default APs number in social channels (1, 6, 11) */
#define IWL_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL 10
@@ -1288,7 +1290,11 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
cmd->v7.adwell_default_n_aps_social =
IWL_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL;
cmd->v7.adwell_default_n_aps =
- IWL_SCAN_ADWELL_DEFAULT_N_APS;
+ IWL_SCAN_ADWELL_DEFAULT_LB_N_APS;
+
+ if (iwl_mvm_is_adwell_hb_ap_num_supported(mvm))
+ cmd->v9.adwell_default_hb_n_aps =
+ IWL_SCAN_ADWELL_DEFAULT_HB_N_APS;
/* if custom max budget was configured with debugfs */
if (IWL_MVM_ADWELL_MAX_BUDGET)
--
2.20.1
^ permalink raw reply related
* [PATCH 11/12] iwlwifi: mvm: remove multiple debugfs entries
From: Luca Coelho @ 2019-06-25 9:44 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Mordechay Goodstein, Luca Coelho
In-Reply-To: <20190625094452.19034-1-luca@coelho.fi>
From: Mordechay Goodstein <mordechay.goodstein@intel.com>
Now that we have per station control over amsdu size no need for
multiple entries, especially that the old one is misleading due to not
setting it for all protocols as a limit.
Signed-off-by: Mordechay Goodstein <mordechay.goodstein@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
.../net/wireless/intel/iwlwifi/mvm/debugfs.c | 20 -------------------
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 -
drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 9 +--------
3 files changed, 1 insertion(+), 29 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index fb2fd89270ed..8260da314721 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -1396,24 +1396,6 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
return count;
}
-static ssize_t iwl_dbgfs_max_amsdu_len_write(struct iwl_mvm *mvm,
- char *buf, size_t count,
- loff_t *ppos)
-{
- unsigned int max_amsdu_len;
- int ret;
-
- ret = kstrtouint(buf, 0, &max_amsdu_len);
- if (ret)
- return ret;
-
- if (max_amsdu_len > IEEE80211_MAX_MPDU_LEN_VHT_11454)
- return -EINVAL;
- mvm->max_amsdu_len = max_amsdu_len;
-
- return count;
-}
-
#define ADD_TEXT(...) pos += scnprintf(buf + pos, bufsz - pos, __VA_ARGS__)
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
static ssize_t iwl_dbgfs_bcast_filters_read(struct file *file,
@@ -1966,7 +1948,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64);
-MVM_DEBUGFS_WRITE_FILE_OPS(max_amsdu_len, 8);
MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
(IWL_RSS_INDIRECTION_TABLE_SIZE * 2));
MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512);
@@ -2169,7 +2150,6 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, 0600);
MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, 0600);
MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, 0200);
- MVM_DEBUGFS_ADD_FILE(max_amsdu_len, mvm->debugfs_dir, 0200);
MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200);
MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200);
MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 8dc2a9850bc5..0c938fe4cbe7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1109,7 +1109,6 @@ struct iwl_mvm {
u8 ps_disabled; /* u8 instead of bool to ease debugfs_create_* usage */
/* Indicate if 32Khz external clock is valid */
u32 ext_clock_valid;
- unsigned int max_amsdu_len; /* used for debugfs only */
struct ieee80211_vif __rcu *csa_vif;
struct ieee80211_vif __rcu *csa_tx_blocked_vif;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index ad4760307726..16f7458e2e81 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -893,18 +893,15 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
unsigned int mss = skb_shinfo(skb)->gso_size;
unsigned int num_subframes, tcp_payload_len, subf_len, max_amsdu_len;
u16 snap_ip_tcp, pad;
- unsigned int dbg_max_amsdu_len;
netdev_features_t netdev_flags = NETIF_F_CSUM_MASK | NETIF_F_SG;
u8 tid;
snap_ip_tcp = 8 + skb_transport_header(skb) - skb_network_header(skb) +
tcp_hdrlen(skb);
- dbg_max_amsdu_len = READ_ONCE(mvm->max_amsdu_len);
-
if (!mvmsta->max_amsdu_len ||
!ieee80211_is_data_qos(hdr->frame_control) ||
- (!mvmsta->amsdu_enabled && !dbg_max_amsdu_len))
+ !mvmsta->amsdu_enabled)
return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb);
/*
@@ -936,10 +933,6 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
max_amsdu_len = iwl_mvm_max_amsdu_size(mvm, sta, tid);
- if (unlikely(dbg_max_amsdu_len))
- max_amsdu_len = min_t(unsigned int, max_amsdu_len,
- dbg_max_amsdu_len);
-
/*
* Limit A-MSDU in A-MPDU to 4095 bytes when VHT is not
* supported. This is a spec requirement (IEEE 802.11-2015
--
2.20.1
^ permalink raw reply related
* Re: [PATCH] rt2x00: fix rx queue hang
From: Stanislaw Gruszka @ 2019-06-25 9:57 UTC (permalink / raw)
To: Soeren Moch
Cc: Helmut Schaa, Kalle Valo, David S. Miller, linux-wireless, netdev,
linux-kernel, stable
In-Reply-To: <b6899d78-447c-3cb3-4bec-e4050660ccaa@web.de>
Hello
On Fri, Jun 21, 2019 at 01:30:01PM +0200, Soeren Moch wrote:
> On 18.06.19 11:34, Stanislaw Gruszka wrote:
> > Hi
> >
> > On Mon, Jun 17, 2019 at 11:46:56AM +0200, Soeren Moch wrote:
> >> Since commit ed194d136769 ("usb: core: remove local_irq_save() around
> >> ->complete() handler") the handlers rt2x00usb_interrupt_rxdone() and
> >> rt2x00usb_interrupt_txdone() are not running with interrupts disabled
> >> anymore. So these handlers are not guaranteed to run completely before
> >> workqueue processing starts. So only mark entries ready for workqueue
> >> processing after proper accounting in the dma done queue.
> > It was always the case on SMP machines that rt2x00usb_interrupt_{tx/rx}done
> > can run concurrently with rt2x00_work_{rx,tx}done, so I do not
> > understand how removing local_irq_save() around complete handler broke
> > things.
> I think because completion handlers can be interrupted now and scheduled
> away
> in the middle of processing.
> > Have you reverted commit ed194d136769 and the revert does solve the problem ?
> Yes, I already sent a patch for this, see [1]. But this was not considered
> an acceptablesolution. Especially RT folks do not like code running with
> interrupts disabled,particularly when trying to acquire spinlocks then.
>
> [1] https://lkml.org/lkml/2019/5/31/863
> > Between 4.19 and 4.20 we have some quite big changes in rt2x00 driver:
> >
> > 0240564430c0 rt2800: flush and txstatus rework for rt2800mmio
> > adf26a356f13 rt2x00: use different txstatus timeouts when flushing
> > 5022efb50f62 rt2x00: do not check for txstatus timeout every time on tasklet
> > 0b0d556e0ebb rt2800mmio: use txdone/txstatus routines from lib
> > 5c656c71b1bf rt2800: move usb specific txdone/txstatus routines to rt2800lib
> >
> > so I'm a bit afraid that one of those changes is real cause of
> > the issue not ed194d136769 .
> I tested 4.20 and 5.1 and see the exact same behavior. Reverting this
> usb core patchsolves the problem.
> 4.19.x (before this usb core patch) is running fine.
> >> Note that rt2x00usb_work_rxdone() processes all available entries, not
> >> only such for which queue_work() was called.
> >>
> >> This fixes a regression on a RT5370 based wifi stick in AP mode, which
> >> suddenly stopped data transmission after some period of heavy load. Also
> >> stopping the hanging hostapd resulted in the error message "ieee80211
> >> phy0: rt2x00queue_flush_queue: Warning - Queue 14 failed to flush".
> >> Other operation modes are probably affected as well, this just was
> >> the used testcase.
> > Do you know what actually make the traffic stop,
> > TX queue hung or RX queue hung?
> I think RX queue hang, as stated in the patch title. "Queue 14" means QID_RX
> (rt2x00queue.h, enum data_queue_qid).
> I also tried to re-add local_irq_save() in only one of the handlers. Adding
> this tort2x00usb_interrupt_rxdone() alone solved the issue, while doing so
> for tx alonedid not.
>
> Note that this doesn't mean there is no problem for tx, that's maybe
> just more
> difficult to trigger.
> >> diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
> >> index 1b08b01db27b..9c102a501ee6 100644
> >> --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
> >> +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
> >> @@ -263,9 +263,9 @@ EXPORT_SYMBOL_GPL(rt2x00lib_dmastart);
> >>
> >> void rt2x00lib_dmadone(struct queue_entry *entry)
> >> {
> >> - set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);
> >> clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
> >> rt2x00queue_index_inc(entry, Q_INDEX_DMA_DONE);
> >> + set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);
> > Unfortunately I do not understand how this suppose to fix the problem,
> > could you elaborate more about this change?
> >
> Re-adding local_irq_save() around thisrt2x00lib_dmadone()solved
> the issue. So I also tried to reverse the order of these calls.
> It seems totally plausible to me, that the correct sequence is to
> first clear the device assignment, then to set the status to dma_done,
> then to trigger the workqueue processing for this entry. When the handler
> is scheduled away in the middle of this sequence, now there is no
> strange state where the entry can be processed by the workqueue while
> not declared dma_done for it.
> With this changed sequence there is no need anymore to disable interrupts
> for solving the hang issue.
Thanks very much for explanations. However I still do not fully
understand the issue. Q_INDEX_DMA_DONE index is only checked on TX
processing (on RX we use only Q_INDEX_DONE and Q_INDEX) and
ENTRY_OWNER_DEVICE_DATA is already cleared before rt2x00lib_dmadone()
in rt2x00usb_interrupt_rxdone() .
So I'm not sure how changing the order solve the problem. Looks
for me that the issue is triggered by some rt2x00lib_dmadone()
call done on error path (not in rt2x00usb_interrupt_rxdone())
and it race with this check:
if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
return false;
in rt2x00usb_kick_rx_entry() - we return instead of submit urb.
I'm somewhat reluctant to change the order, because TX processing
might relay on it (we first mark we wait for TX status and
then mark entry is no longer owned by hardware). However on RX
side ENTRY_DATA_STATUS_PENDING bit make no sense as we do not
wait for status. We should remove ENTRY_DATA_STATUS_PENDING on
RX side and perhaps this also will solve issue you observe.
Could you please check below patch, if it fixes the problem as well?
Stanislaw
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
index b6c1344..731e633 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
@@ -360,8 +360,7 @@ static void rt2x00usb_work_rxdone(struct work_struct *work)
while (!rt2x00queue_empty(rt2x00dev->rx)) {
entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE);
- if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
- !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
+ if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
break;
/*
@@ -413,8 +412,7 @@ static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void *data)
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
int status;
- if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
- test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
+ if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
return false;
rt2x00lib_dmastart(entry);
^ permalink raw reply related
* Re: [PATCH v3 1/2] nl80211: Add support for EDMG channels
From: Alexei Lazar @ 2019-06-25 10:21 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, wil6210
In-Reply-To: <d1c2fd8d99d8f8420ba265f31709da9326ad38f1.camel@sipsolutions.net>
On 2019-06-14 15:31, Johannes Berg wrote:
> Hi Alexei,
>
> Sorry for the long delay here.
>
> I have a few questions.
>
> Looking at this:
Hi Johannes,
Thank you for the review, comments inline.
Thanks,
Alex.
>
>> /**
>> + * struct ieee80211_sta_edmg_cap - EDMG capabilities
>> + *
>> + * This structure describes most essential parameters needed
>> + * to describe 802.11ay EDMG capabilities
>> + *
>> + * @channels: bitmap that indicates the 2.16 GHz channel(s)
>> + * that are allowed to be used for transmissions in the BSS.
>> + * Set to 0 indicate EDMG not supported.
>> + * @bw_config: Channel BW Configuration subfield encodes
>> + * the allowed channel bandwidth configurations
>> + */
>> +struct ieee80211_sta_edmg_cap {
>> + u8 channels;
>> + u8 bw_config;
>> +};
>
> What are the bits actually? Seems you should define some enum or so
> that
> shows which bits are used here?
Enum is not needed in this case, Each bit in the channels represent
legacy
channel, bit 0 represent channel 1, bit 1 represent channel 2 and so
on...
till bit 5 that represent channel 6.
I will update the description to make it more clear.
>
>> * @center_freq1: center frequency of first segment
>> * @center_freq2: center frequency of second segment
>> * (only with 80+80 MHz)
>> + * @edmg_channels: bitmap that indicates the 2.16 GHz channel(s)
>> + * that are allowed to be used for transmissions in the BSS.
>> + * @edmg_bw_config: Channel BW Configuration subfield encodes
>> + * the allowed channel bandwidth configurations
>> */
>> struct cfg80211_chan_def {
>> struct ieee80211_channel *chan;
>> enum nl80211_chan_width width;
>> u32 center_freq1;
>> u32 center_freq2;
>> + u8 edmg_channels;
>> + u8 edmg_bw_config;
>> };
>
> This isn't clear to me. How can the capability and the configuration be
> exactly the same? In the capability, you should be able to capture
> multiple possible things, and in the setting only choose one?
edmg_channels can specify multiple channels and edmg_bw_config can
specify
multiple bonding options. For example edmg_bw_config = 15 means that
association is allowed/requested with bonding of 1, 2, 3 or 4 channels.
When driver reports capability - it obviously can report multiple
options.
For the setting (connect command or start AP), kernel can request
multiple
options (subset of reported capabilities) and the driver will choose one
of
them, based on BSS configuration and resource availability.
>
> And if they really are the same, why not use the struct
> ieee80211_sta_edmg_cap here? Seems weird to me, but I don't know 11ay.
Good comment, will use the ieee80211_sta_edmg_cap struct.
>
>
> Also, I think you should describe a bit more how this plays together
> with the existing settings. Will ->chan still be set, to something like
> the control channel?
Updated cfg80211.h
wil->chan in case of 11ay is the primary channel and other setting being
ignored.
>
>> /**
>> @@ -1144,15 +1169,17 @@ int cfg80211_check_station_change(struct wiphy
>> *wiphy,
>> * @RATE_INFO_FLAGS_MCS: mcs field filled with HT MCS
>> * @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS
>> * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
>> - * @RATE_INFO_FLAGS_60G: 60GHz MCS
>> + * @RATE_INFO_FLAGS_DMG: 60GHz MCS
>> * @RATE_INFO_FLAGS_HE_MCS: HE MCS information
>> + * @RATE_INFO_FLAGS_EDMG: 60GHz MCS in EDMG mode
>> */
>> enum rate_info_flags {
>> RATE_INFO_FLAGS_MCS = BIT(0),
>> RATE_INFO_FLAGS_VHT_MCS = BIT(1),
>> RATE_INFO_FLAGS_SHORT_GI = BIT(2),
>> - RATE_INFO_FLAGS_60G = BIT(3),
>> + RATE_INFO_FLAGS_DMG = BIT(3),
>> RATE_INFO_FLAGS_HE_MCS = BIT(4),
>> + RATE_INFO_FLAGS_EDMG = BIT(5),
>> };
>>
>> /**
>> @@ -1192,6 +1219,7 @@ enum rate_info_bw {
>> * @he_dcm: HE DCM value
>> * @he_ru_alloc: HE RU allocation (from &enum nl80211_he_ru_alloc,
>> * only valid if bw is %RATE_INFO_BW_HE_RU)
>> + * @n_bonded_ch: In case of EDMG the number of bonded channels (1-4)
>> */
>> struct rate_info {
>> u8 flags;
>> @@ -1202,6 +1230,7 @@ struct rate_info {
>> u8 he_gi;
>> u8 he_dcm;
>> u8 he_ru_alloc;
>> + u8 n_bonded_ch;
>> };
>
>
> It seems like this is missing corresponding nl80211.h changes?
n_bonded_ch not exposed to the userspace, like flags.
>
>> @@ -2436,6 +2469,8 @@ struct cfg80211_connect_params {
>> const u8 *fils_erp_rrk;
>> size_t fils_erp_rrk_len;
>> bool want_1x;
>> + u8 edmg_channels;
>> + u8 edmg_bw_config;
>> };
>
> Same question as above, why not embed the struct if it's the same?
Done.
>
> Again it seems like it shouldn't be the same though.
>
>> + * @NL80211_ATTR_WIPHY_EDMG_CHANNELS: bitmap that indicates the 2.16
>> GHz
>> + * channel(s) that are allowed to be used for EDMG transmissions in
>> the
>> + * BSS as defined by IEEE 802.11 section 9.4.2.251.
>> + * @NL80211_ATTR_WIPHY_EDMG_BW_CONFIG: Channel BW Configuration
>> subfield encodes
>> + * the allowed channel bandwidth configurations as defined by IEEE
>> 802.11
>> + * section 9.4.2.251, Table 13.
>
> This is unclear - "in the BSS" means nothing in this context, since
> you're using this to advertise capabilities?
>
> This isn't a BSS attribute, after all.
>
> Ah - but looking further, you use this to *set* the channel, not for
> capabilities... I guess that makes sense.
You are correct, this is for setting the channel, I've updated the
description.
>
>
>> * @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT
>> information IE
>> * @NL80211_BAND_ATTR_IFTYPE_DATA: nested array attribute, with each
>> entry using
>> * attributes from &enum nl80211_band_iftype_attr
>> + * @NL80211_BAND_ATTR_EDMG_CHANNELS: bitmap that indicates the 2.16
>> GHz
>> + * channel(s) that are allowed to be used for EDMG transmissions in
>> the
>> + * BSS as defined by IEEE 802.11 section 9.4.2.251.
>> + * @NL80211_BAND_ATTR_EDMG_BW_CONFIG: Channel BW Configuration
>> subfield
>> + * encodes the allowed channel bandwidth configurations as defined by
>> + * IEEE 802.11 section 9.4.2.251, Table 13.
>> * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined
>> * @__NL80211_BAND_ATTR_AFTER_LAST: internal use
>
> And ... that makes more sense than the global attribute I guess?
We feel it belongs to the BAND attributes because for example also VHT
capability is there. There are however 2 other options:
1. Move the attribute to the NL80211_FREQUENCY_ATTR
2. Move them to the global attributes
Any preference?
>
>> +static bool cfg80211_edmg_chandef_valid(const struct
>> cfg80211_chan_def *chandef)
>> +{
>> + int max_continuous = 0;
>> + int num_of_enabled = 0;
>> + int continuous = 0;
>
> do you mean "contiguous"? "continuous" doesn't make much sense?
Updated , contiguous.
>
>> + int i;
>> +
>> + if (!chandef->edmg_channels && !chandef->edmg_bw_config)
>> + return true;
>> +
>> + if ((!chandef->edmg_channels && chandef->edmg_bw_config) ||
>> + (chandef->edmg_channels && !chandef->edmg_bw_config))
>> + return false;
>
> There probably should be some kind of WARN_ON() check that validates
> you
> get here only if the ->chan is actually 60GHz?
Added 60GHz check.
>
>> +++ b/net/wireless/nl80211.c
>> @@ -288,6 +288,9 @@ static int validate_ie_attr(const struct nlattr
>> *attr,
>>
>> [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
>> [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
>> + [NL80211_ATTR_WIPHY_EDMG_CHANNELS] = { .type = NLA_U8 },
>> + [NL80211_ATTR_WIPHY_EDMG_BW_CONFIG] = { .type = NLA_U8 },
>
> You probably want something like NLA_POLICY_RANGE() here? This was only
> 1-4 IIRC?
Updated to NLA_POLICY_RANGE, the range value is 4-15, align with the
Spec.
>
>> + if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
>> + chandef->edmg_channels =
>> + nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
>> +
>> + if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
>> + chandef->edmg_bw_config =
>> + nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
>> + } else {
>> + chandef->edmg_bw_config = 0;
>> + chandef->edmg_channels = 0;
>> + }
>> +
>> if (!cfg80211_chandef_valid(chandef)) {
>
> So I guess what I suggested above shouldn't actually be a WARN_ON() but
> just a check w/o WARN_ON()?
Added 60GHz check.
>
> johannes
--
Alexei Lazar
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum a
Linux Foundation Collaborative Project
^ permalink raw reply
* [PATCH 4/4] b43: simplify engine type / DMA mask selection
From: Christoph Hellwig @ 2019-06-25 10:29 UTC (permalink / raw)
To: Larry Finger, Kalle Valo; +Cc: b43-dev, linux-wireless, netdev, linux-kernel
In-Reply-To: <20190625102932.32257-1-hch@lst.de>
Return the engine type from the function looking at the registers, and
just derive the DMA mask from that in the one place we care.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/net/wireless/broadcom/b43/dma.c | 28 ++++++-------------------
1 file changed, 6 insertions(+), 22 deletions(-)
diff --git a/drivers/net/wireless/broadcom/b43/dma.c b/drivers/net/wireless/broadcom/b43/dma.c
index 1d5ace4d3372..e8958edb9094 100644
--- a/drivers/net/wireless/broadcom/b43/dma.c
+++ b/drivers/net/wireless/broadcom/b43/dma.c
@@ -810,7 +810,7 @@ static void free_all_descbuffers(struct b43_dmaring *ring)
}
}
-static u64 supported_dma_mask(struct b43_wldev *dev)
+static enum b43_dmatype b43_engine_type(struct b43_wldev *dev)
{
u32 tmp;
u16 mmio_base;
@@ -820,14 +820,14 @@ static u64 supported_dma_mask(struct b43_wldev *dev)
case B43_BUS_BCMA:
tmp = bcma_aread32(dev->dev->bdev, BCMA_IOST);
if (tmp & BCMA_IOST_DMA64)
- return DMA_BIT_MASK(64);
+ return B43_DMA_64BIT;
break;
#endif
#ifdef CONFIG_B43_SSB
case B43_BUS_SSB:
tmp = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
if (tmp & SSB_TMSHIGH_DMA64)
- return DMA_BIT_MASK(64);
+ return B43_DMA_64BIT;
break;
#endif
}
@@ -836,20 +836,7 @@ static u64 supported_dma_mask(struct b43_wldev *dev)
b43_write32(dev, mmio_base + B43_DMA32_TXCTL, B43_DMA32_TXADDREXT_MASK);
tmp = b43_read32(dev, mmio_base + B43_DMA32_TXCTL);
if (tmp & B43_DMA32_TXADDREXT_MASK)
- return DMA_BIT_MASK(32);
-
- return DMA_BIT_MASK(30);
-}
-
-static enum b43_dmatype dma_mask_to_engine_type(u64 dmamask)
-{
- if (dmamask == DMA_BIT_MASK(30))
- return B43_DMA_30BIT;
- if (dmamask == DMA_BIT_MASK(32))
return B43_DMA_32BIT;
- if (dmamask == DMA_BIT_MASK(64))
- return B43_DMA_64BIT;
- B43_WARN_ON(1);
return B43_DMA_30BIT;
}
@@ -1078,13 +1065,10 @@ static bool b43_dma_translation_in_low_word(struct b43_wldev *dev,
int b43_dma_init(struct b43_wldev *dev)
{
struct b43_dma *dma = &dev->dma;
+ enum b43_dmatype type = b43_engine_type(dev);
int err;
- u64 dmamask;
- enum b43_dmatype type;
- dmamask = supported_dma_mask(dev);
- type = dma_mask_to_engine_type(dmamask);
- err = dma_set_mask_and_coherent(dev->dev->dma_dev, dmamask);
+ err = dma_set_mask_and_coherent(dev->dev->dma_dev, DMA_BIT_MASK(type));
if (err) {
b43err(dev->wl, "The machine/kernel does not support "
"the required %u-bit DMA mask\n", type);
@@ -1793,7 +1777,7 @@ void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
enum b43_dmatype type;
u16 mmio_base;
- type = dma_mask_to_engine_type(supported_dma_mask(dev));
+ type = b43_engine_type(dev);
mmio_base = b43_dmacontroller_base(type, engine_index);
direct_fifo_rx(dev, type, mmio_base, enable);
--
2.20.1
^ permalink raw reply related
* [PATCH 3/4] b43: remove b43_dma_set_mask
From: Christoph Hellwig @ 2019-06-25 10:29 UTC (permalink / raw)
To: Larry Finger, Kalle Valo; +Cc: b43-dev, linux-wireless, netdev, linux-kernel
In-Reply-To: <20190625102932.32257-1-hch@lst.de>
These days drivers are not required to fallback to smaller DMA masks,
but can just set the largest mask they support, removing the need for
this trial and error logic.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/net/wireless/broadcom/b43/dma.c | 43 +++----------------------
1 file changed, 5 insertions(+), 38 deletions(-)
diff --git a/drivers/net/wireless/broadcom/b43/dma.c b/drivers/net/wireless/broadcom/b43/dma.c
index b34e51933257..1d5ace4d3372 100644
--- a/drivers/net/wireless/broadcom/b43/dma.c
+++ b/drivers/net/wireless/broadcom/b43/dma.c
@@ -1056,42 +1056,6 @@ void b43_dma_free(struct b43_wldev *dev)
destroy_ring(dma, tx_ring_mcast);
}
-static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
-{
- u64 orig_mask = mask;
- bool fallback = false;
- int err;
-
- /* Try to set the DMA mask. If it fails, try falling back to a
- * lower mask, as we can always also support a lower one. */
- while (1) {
- err = dma_set_mask_and_coherent(dev->dev->dma_dev, mask);
- if (!err)
- break;
- if (mask == DMA_BIT_MASK(64)) {
- mask = DMA_BIT_MASK(32);
- fallback = true;
- continue;
- }
- if (mask == DMA_BIT_MASK(32)) {
- mask = DMA_BIT_MASK(30);
- fallback = true;
- continue;
- }
- b43err(dev->wl, "The machine/kernel does not support "
- "the required %u-bit DMA mask\n",
- (unsigned int)dma_mask_to_engine_type(orig_mask));
- return -EOPNOTSUPP;
- }
- if (fallback) {
- b43info(dev->wl, "DMA mask fallback from %u-bit to %u-bit\n",
- (unsigned int)dma_mask_to_engine_type(orig_mask),
- (unsigned int)dma_mask_to_engine_type(mask));
- }
-
- return 0;
-}
-
/* Some hardware with 64-bit DMA seems to be bugged and looks for translation
* bit in low address word instead of high one.
*/
@@ -1120,9 +1084,12 @@ int b43_dma_init(struct b43_wldev *dev)
dmamask = supported_dma_mask(dev);
type = dma_mask_to_engine_type(dmamask);
- err = b43_dma_set_mask(dev, dmamask);
- if (err)
+ err = dma_set_mask_and_coherent(dev->dev->dma_dev, dmamask);
+ if (err) {
+ b43err(dev->wl, "The machine/kernel does not support "
+ "the required %u-bit DMA mask\n", type);
return err;
+ }
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
--
2.20.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox