* Re: [PATCH v3] wifi: mac80211: fix monitor mode frame capture for real chanctx drivers
From: Johannes Berg @ 2026-05-19 7:02 UTC (permalink / raw)
To: Devin Wittmayer, linux-wireless
Cc: Felix Fietkau, Lorenzo Bianconi, linux-kernel, stable,
Oscar Alfonso Diaz, fjhhz1997
In-Reply-To: <20260518170147.13885-2-lucid_duck@justthetip.ca>
Hi Devin,
Please don't nest the threads - it gets confusing quickly.
> + } else if (local->emulate_chanctx) {
> chandef = &local->hw.conf.chandef;
> - else
> - goto fail_rcu;
> + } else {
> + struct ieee80211_chanctx *ctx;
> +
> + ctx = list_first_or_null_rcu(&local->chanctx_list,
> + struct ieee80211_chanctx, list);
> + if (!ctx ||
> + rcu_access_pointer(ctx->list.next) != &local->chanctx_list)
> + goto fail_rcu;
> + chandef = &ctx->conf.def;
> + }
I'm sure we can basically get rid of the "emulate" check now, because
emulation will always lead to exactly (zero or) one channel context(s)
being present.
And then it's equivalent to my original v2 patch:
https://lore.kernel.org/linux-wireless/20251216111909.25076-2-johannes@sipsolutions.net/
(even if that expressed the logic somewhat differently)
And that version was _definitely_ reported to crash. So what changed?
Could you do some investigation if mt76 got bugfixes in this area
perhaps? Or are you just using slightly different devices than Oscar?
johannes
^ permalink raw reply
* Re: [PATCH v3] wireless-regdb: Update regulatory rules for Sri Lanka (LK)
From: Chen-Yu Tsai @ 2026-05-19 6:51 UTC (permalink / raw)
To: Mohamed Aashif; +Cc: linux-wireless, wireless-regdb, pkshih
In-Reply-To: <20260518074743.179402-1-maashif011@gmail.com>
On Mon, May 18, 2026 at 3:48 PM Mohamed Aashif <maashif011@gmail.com> wrote:
>
> Update Sri Lanka regulatory domain based on the RTTE Type Approval
> Rules 2020 from the Telecommunications Regulatory Commission of
> Sri Lanka (TRC).
>
> Source: https://www.trc.gov.lk/content/files/licensing/RTTE_GAZETTE-English.pdf
>
> Key changes:
> - Change DFS region from FCC to ETSI (document references ETSI
> standards EN 300 328 and EN 301 893 as the applicable radio
> interface standards)
> - 2.4 GHz: expand to 2400-2483.5 MHz at 23 dBm
> - 5150-5250 MHz: 23 dBm
> - 5250-5350 MHz: 20 dBm with DFS (no TPC, 3 dB reduction per EN 301 893)
> - 5470-5725 MHz: 27 dBm with DFS (no TPC, per EN 301 893)
> - 5725-5875 MHz: 24 dBm with DFS (per ETSI EN 302 502)
The numbers and units should match the official regulations.
The official document you provided uses mW, so please use mW throughout,
unless there are dBm calculations like for the reduction due to no TPC
or adoption of dBm numbers from ETSI rules.
> Note: The TRC gazette conflicts internally by allowing 30 dBm for
> 5725-5875 MHz while citing EN 301 893 (which doesn't cover this band).
> Lacking TRC clarification, we conservatively default to the ETSI
> EN 302 502 limits (24 dBm).
^ TPC
Will fix up when applying.
>
> Signed-off-by: Mohamed Aashif <maashif011@gmail.com>
> ---
> Great, thanks. Removed DFS from 5150-5250 MHz.
>
> Changes in v3:
> - Corrected the table caption in the source comment to "Table 2 - Applicable Standards- Wireless"
> - Removed DFS flag from 5150-5250 MHz
>
> Changes in v2:
> - Split 5150-5350 MHz into 5150-5250 MHz (23 dBm) and 5250-5350 MHz
> (20 dBm), adding AUTO-BW to both.
> - Applied a 3 dB reduction to 5250-5350 MHz and 5470-5725 MHz (now
> 27 dBm) to comply with ETSI limits since TPC is unsupported.
> - Capped 5725-5875 MHz at 24 dBm per ETSI EN 302 502.
>
> db.txt | 15 +++++++++------
> 1 file changed, 9 insertions(+), 6 deletions(-)
>
> diff --git a/db.txt b/db.txt
> index fdc2c13..8038f5a 100644
> --- a/db.txt
> +++ b/db.txt
> @@ -1058,12 +1058,15 @@ country LI: DFS-ETSI
> # 60 GHz band channels 1-4 (ETSI EN 302 567)
> (57000 - 66000 @ 2160), (40)
>
> -country LK: DFS-FCC
> - (2402 - 2482 @ 40), (20)
> - (5170 - 5250 @ 20), (17)
> - (5250 - 5330 @ 20), (24), DFS
> - (5490 - 5730 @ 20), (24), DFS
> - (5735 - 5835 @ 20), (30)
> +# Source:
> +# https://www.trc.gov.lk/content/files/licensing/RTTE_GAZETTE-English.pdf
> +# Sri Lanka RTTE Type Approval Rules 2020, Table 2 - Applicable Standards- Wireless
> +country LK: DFS-ETSI
> + (2400 - 2483.5 @ 40), (23)
> + (5150 - 5250 @ 80), (23), AUTO-BW
> + (5250 - 5350 @ 80), (20), DFS, AUTO-BW
> + (5470 - 5725 @ 160), (27), DFS
> + (5725 - 5875 @ 80), (24), DFS
>
> # Source:
> # http://lca.org.ls/images/documents/lesotho_national_frequency_allocation_plan.pdf
> --
> 2.54.0
>
>
^ permalink raw reply
* Re: [PATCH wireless-next] wifi: mwifiex: Use flexible array for RX reorder table
From: Johannes Berg @ 2026-05-19 6:47 UTC (permalink / raw)
To: Rosen Penev, linux-wireless
Cc: Brian Norris, Francesco Dolcini, Kees Cook, Gustavo A. R. Silva,
open list,
open list:KERNEL HARDENING (not covered by other areas):Keyword:\b__counted_by(_le|_be|_ptr)?\b
In-Reply-To: <20260518211826.11245-1-rosenp@gmail.com>
Hi Rosen,
On Mon, 2026-05-18 at 14:18 -0700, Rosen Penev wrote:
> Embed the RX reorder pointer array in struct mwifiex_rx_reorder_tbl
> instead of allocating it separately.
Others might disagree, but personally, I think you should stop doing
this. Sure, it *might* (I've been bitten too much by __counted_by) be a
border-line improvement, but it's not _really_ all that useful,
especially on these older drivers.
Did you even test it at all?
And then especially
> Assisted-by: Codex:GPT-5.5
if you do it this way, you're going to be able to produce such changes
with way less effort than anyone can possibly review. And since for all
of the fringe drivers the review falls on me personally, well, I'm just
not going to keep up.
If you _really_ want to help, please help review changes rather than
producing more noise. Maybe even take over maintenance of some specific
driver that you can test.
johannes
^ permalink raw reply
* Re: [PATCH v2] wireless-regdb: Update regulatory info for Brunei Darussalam (BN) for 2022
From: Chen-Yu Tsai @ 2026-05-19 6:41 UTC (permalink / raw)
To: hfzz7; +Cc: linux-wireless, wireless-regdb
In-Reply-To: <BFBA868E-9B63-48A6-9B73-E749857BD106.1@smtp-inbound1.duck.com>
On Fri, May 1, 2026 at 11:41 PM <hfzz7@duck.com> wrote:
>
> In 2022, Authority for Info-communications Technology Industry of Brunei
> Darussalam (AITI) updated The Brunei Darussalam Radio Spectrum Plan. [1]
>
> * 2400-2483.5 MHz
> - 200 mW
>
> * 5150-5350 MHz
> - 1000 mW
> (For 5250-5.350 MHz, DFS and TPC are required)
>
> * 5470-5725 MHz
> - 1000 mW
> - DFS
> - TPC
>
> * 5725-5850 MHz
> - 4000 mW
>
> Also, add regulatory info for WiGig/60 GHz
> * 57000-66000 MHz
> - 10 W / 10000 mW
The power density should be mentioned, and there should be separate
entries for indoor use and outdoor use. I added them while applying.
> Note: According to the Telecommunications (Radio-communication) Regulations,
> 2013 of the Telecommunications Order, 2001 (S 38/2001), "non-localised use"
> refers to the operations of specified radio-communication equipment or network
> at a specific frequency or in any specified frequency within the whole of
> Brunei Darussalam. [2]
>
> [1] https://aiti.gov.bn/media/planjc1p/bd-radio-spectrum-plan-2019.pdf
> [2] https://www.agc.gov.bn/AGC%20Images/LAWS/Gazette_PDF/2013/EN/s086.pdf
>
> Signed-off-by: Hafiz Zafran <hfzz7@duck.com>
>
> ---
> Changes since v1:
> - fix grammar issues on the commit message
> - adjust transmit power limit to 500 mW for frequencies that
> require TPC
> - add INDOOR-ONLY flag to WiGig, as per review
> ---
> db.txt | 15 ++++++++++-----
> 1 file changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/db.txt b/db.txt
> index 3252521..2de3281 100644
> --- a/db.txt
> +++ b/db.txt
> @@ -326,11 +326,16 @@ country BM: DFS-FCC
> (5490 - 5730 @ 160), (24), DFS
> (5735 - 5835 @ 80), (30)
>
> -country BN: DFS-JP
> - (2402 - 2482 @ 40), (20)
> - (5170 - 5250 @ 80), (20), AUTO-BW
> - (5250 - 5330 @ 80), (20), DFS, AUTO-BW
> - (5735 - 5835 @ 80), (20)
> +# Source:
> +# https://aiti.gov.bn/media/planjc1p/bd-radio-spectrum-plan-2019.pdf
> +# Section 7.5, Page 244-251
> +country BN: DFS-FCC
> + (2400 - 2483.5 @ 40), (200 mW)
> + (5150 - 5250 @ 80), (1000 mW), AUTO-BW
> + (5250 - 5350 @ 80), (500 mW), DFS, AUTO-BW
> + (5470 - 5730 @ 160), (500 mW), DFS
> + (5725 - 5850 @ 80), (4000 mW), AUTO-BW
This should start at 5730 since the previous one end at 5730. Also,
AUTO-BW does nothing for this range now, as there is nothing to combine
it with after it.
> + (57000 - 66000 @ 2160), (10000 mW), INDOOR-ONLY
This should have been NO-OUTDOOR. I fixed it up while applying.
Please check the commit after I push it out.
Thanks
ChenYu
>
> country BO: DFS-JP
> (2402 - 2482 @ 40), (20)
> --
> 2.54.0
>
>
^ permalink raw reply
* [PATCH v3 iwlwifi-next 15/15] wifi: iwlwifi: transport: add memory read under NIC access
From: Miri Korenblit @ 2026-05-19 6:40 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260519064010.549003-1-miriam.rachel.korenblit@intel.com>
From: Johannes Berg <johannes.berg@intel.com>
Add functions to be able to do memory read under NIC access,
in order to use them later during firmware dump. These may
drop and re-acquire the spinlock, but will not acquire and
release the NIC access.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20260517100550.7bb1ea51c347.I91420a24fb0c481c75a2600d60e1365c15c1c5a9@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
.../net/wireless/intel/iwlwifi/iwl-trans.c | 6 +++
.../net/wireless/intel/iwlwifi/iwl-trans.h | 16 ++++++
.../intel/iwlwifi/pcie/gen1_2/internal.h | 2 +
.../intel/iwlwifi/pcie/gen1_2/trans.c | 54 +++++++++++++++++++
4 files changed, 78 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
index 5b44e15fe64d..0009488ca51b 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
@@ -459,6 +459,12 @@ int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr,
}
IWL_EXPORT_SYMBOL(iwl_trans_read_mem);
+int iwl_trans_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
+ void *buf, u32 dwords)
+{
+ return iwl_trans_pcie_read_mem_no_grab(trans, addr, buf, dwords);
+}
+
int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr,
const void *buf, int dwords)
{
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index 1ed6bcb7882c..3ae840e546e8 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -919,6 +919,14 @@ void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val);
int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr,
void *buf, int dwords);
+/*
+ * Note the special calling convention - it's allowed to drop the
+ * internal transport lock and re-enable BHs temporarily, but will
+ * not release NIC access.
+ */
+int iwl_trans_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
+ void *buf, u32 dwords);
+
int iwl_trans_read_config32(struct iwl_trans *trans, u32 ofs,
u32 *val);
@@ -934,6 +942,14 @@ void iwl_trans_debugfs_cleanup(struct iwl_trans *trans);
(bufsize) / sizeof(u32)); \
})
+static inline int
+iwl_trans_read_mem_bytes_no_grab(struct iwl_trans *trans,
+ u32 addr, void *buf, u32 bufsize)
+{
+ return iwl_trans_read_mem_no_grab(trans, addr, buf,
+ bufsize / sizeof(u32));
+}
+
int iwl_trans_write_imr_mem(struct iwl_trans *trans, u32 dst_addr,
u64 src_addr, u32 byte_cnt);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h
index 24f8714eae9f..abc0c831d1ca 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h
@@ -1186,6 +1186,8 @@ u32 iwl_trans_pcie_read_prph(struct iwl_trans *trans, u32 reg);
void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr, u32 val);
int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr,
void *buf, int dwords);
+int iwl_trans_pcie_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
+ void *buf, u32 dwords);
int iwl_trans_pcie_sw_reset(struct iwl_trans *trans, bool retake_ownership);
struct iwl_trans_dump_data *
iwl_trans_pcie_dump_data(struct iwl_trans *trans, u32 dump_mask,
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
index 50342604491d..1c4ee76d8387 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
@@ -2424,6 +2424,15 @@ bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans)
return false;
}
+static void iwl_trans_pcie_resched_with_nic_access(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ spin_unlock_bh(&trans_pcie->reg_lock);
+ cond_resched();
+ spin_lock_bh(&trans_pcie->reg_lock);
+}
+
void __releases(nic_access_nobh)
iwl_trans_pcie_release_nic_access(struct iwl_trans *trans)
{
@@ -2506,6 +2515,51 @@ int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr,
return 0;
}
+int iwl_trans_pcie_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
+ void *buf, u32 dwords)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+#define IWL_MAX_HW_ERRS 5
+ unsigned int num_consec_hw_errors = 0;
+ u32 offs = 0;
+ u32 *vals = buf;
+
+ lockdep_assert_held(&trans_pcie->reg_lock);
+
+ while (offs < dwords) {
+ /* limit the time we spin here under lock to 1/2s */
+ unsigned long end = jiffies + HZ / 2;
+ bool resched = false;
+
+ iwl_write32(trans, HBUS_TARG_MEM_RADDR,
+ addr + 4 * offs);
+
+ while (offs < dwords) {
+ vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
+
+ if (iwl_trans_is_hw_error_value(vals[offs]))
+ num_consec_hw_errors++;
+ else
+ num_consec_hw_errors = 0;
+
+ if (num_consec_hw_errors >= IWL_MAX_HW_ERRS)
+ return -EIO;
+
+ offs++;
+
+ if (time_after(jiffies, end)) {
+ resched = true;
+ break;
+ }
+ }
+
+ if (resched)
+ iwl_trans_pcie_resched_with_nic_access(trans);
+ }
+
+ return 0;
+}
+
int iwl_trans_pcie_read_config32(struct iwl_trans *trans, u32 ofs,
u32 *val)
{
--
2.34.1
^ permalink raw reply related
* [PATCH v3 iwlwifi-next 14/15] wifi: iwlwifi: dbg: remove unused 'range_len' arg from dump
From: Miri Korenblit @ 2026-05-19 6:40 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260519064010.549003-1-miriam.rachel.korenblit@intel.com>
From: Johannes Berg <johannes.berg@intel.com>
None of the functions use this, and it's not really passed the
length of the specific range anyway, but rather the entire
remaining size. Remove the unused argument.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20260517100550.ea3502f97c2a.I4ce08f0ea7ea3bacd4928b427c0710b77259d002@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 45 ++++++++++-----------
1 file changed, 22 insertions(+), 23 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 64ead8ecd52c..069c3bad6f29 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -111,7 +111,7 @@ static int iwl_dump_ini_prph_mac_iter_common(struct iwl_fw_runtime *fwrt,
static int
iwl_dump_ini_prph_mac_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
u32 addr = le32_to_cpu(reg->addrs[idx]) +
@@ -124,7 +124,7 @@ iwl_dump_ini_prph_mac_iter(struct iwl_fw_runtime *fwrt,
static int
iwl_dump_ini_prph_mac_block_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
struct iwl_fw_ini_addr_size *pairs = (void *)reg->addrs;
@@ -201,7 +201,7 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt,
static int
iwl_dump_ini_prph_phy_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
u32 addr = le32_to_cpu(reg->addrs[idx]);
@@ -214,7 +214,7 @@ iwl_dump_ini_prph_phy_iter(struct iwl_fw_runtime *fwrt,
static int
iwl_dump_ini_prph_phy_block_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
struct iwl_fw_ini_addr_size *pairs = (void *)reg->addrs;
@@ -227,7 +227,7 @@ iwl_dump_ini_prph_phy_block_iter(struct iwl_fw_runtime *fwrt,
static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -246,7 +246,7 @@ static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt,
static int iwl_dump_ini_config_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct iwl_trans *trans = fwrt->trans;
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
@@ -274,7 +274,7 @@ static int iwl_dump_ini_config_iter(struct iwl_fw_runtime *fwrt,
static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -296,7 +296,7 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt,
}
static int _iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct page *page = fwrt->fw_paging_db[idx].fw_paging_block;
struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -316,7 +316,7 @@ static int _iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct iwl_fw_ini_error_dump_range *range;
u32 page_size;
@@ -325,7 +325,7 @@ static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
idx++;
if (!fwrt->trans->mac_cfg->gen2)
- return _iwl_dump_ini_paging_iter(fwrt, range_ptr, range_len, idx);
+ return _iwl_dump_ini_paging_iter(fwrt, range_ptr, idx);
range = range_ptr;
page_size = fwrt->trans->init_dram.paging[idx].size;
@@ -341,7 +341,7 @@ static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
static int
iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -360,7 +360,7 @@ iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt,
static int iwl_dump_ini_mon_smem_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -428,7 +428,7 @@ static bool iwl_ini_txf_iter(struct iwl_fw_runtime *fwrt,
static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -497,7 +497,7 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
static int
iwl_dump_ini_prph_snps_dphyip_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -610,7 +610,7 @@ static void iwl_ini_get_rxf_data(struct iwl_fw_runtime *fwrt,
static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -676,7 +676,7 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
static int
iwl_dump_ini_err_table_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
struct iwl_fw_ini_region_err_table *err_table = ®->err_table;
@@ -695,7 +695,7 @@ iwl_dump_ini_err_table_iter(struct iwl_fw_runtime *fwrt,
static int
iwl_dump_ini_special_mem_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
struct iwl_fw_ini_region_special_device_memory *special_mem =
@@ -716,7 +716,7 @@ iwl_dump_ini_special_mem_iter(struct iwl_fw_runtime *fwrt,
static int
iwl_dump_ini_dbgi_sram_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -746,7 +746,7 @@ iwl_dump_ini_dbgi_sram_iter(struct iwl_fw_runtime *fwrt,
static int iwl_dump_ini_fw_pkt_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
struct iwl_fw_ini_error_dump_range *range = range_ptr;
struct iwl_rx_packet *pkt = reg_data->dump_data->fw_pkt;
@@ -767,7 +767,7 @@ static int iwl_dump_ini_fw_pkt_iter(struct iwl_fw_runtime *fwrt,
static int iwl_dump_ini_imr_iter(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range_ptr, u32 range_len, int idx)
+ void *range_ptr, int idx)
{
/* read the IMR memory and DMA it to SRAM */
struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -1277,7 +1277,7 @@ struct iwl_dump_ini_mem_ops {
void *data, u32 data_len);
int (*fill_range)(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data,
- void *range, u32 range_len, int idx);
+ void *range, int idx);
};
struct iwl_fw_ini_dump_entry {
@@ -1413,8 +1413,7 @@ static u32 iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
free_size -= header_size;
for (i = 0; i < le32_to_cpu(header->num_of_ranges); i++) {
- int range_size = ops->fill_range(fwrt, reg_data, range,
- free_size, i);
+ int range_size = ops->fill_range(fwrt, reg_data, range, i);
if (range_size < 0) {
IWL_ERR(fwrt,
--
2.34.1
^ permalink raw reply related
* [PATCH v3 iwlwifi-next 13/15] wifi: iwlwifi: fw: separate out old-style dump code
From: Miri Korenblit @ 2026-05-19 6:40 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260519064010.549003-1-miriam.rachel.korenblit@intel.com>
From: Johannes Berg <johannes.berg@intel.com>
There are two dump paths: new "ini" style, and the old,
more driver-centric, way. Separate out the code for the
old way into a separate dbg-legacy.c file, to simplify.
Fix a typo ('trasport') along the way.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20260517100550.1de0f1110d5a.I4faebe15192a1f27cb4b7270fb52154f06eb2a10@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/Makefile | 2 +-
.../wireless/intel/iwlwifi/fw/dbg-legacy.c | 1022 +++++++++++++++++
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 1012 +---------------
drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 7 +-
4 files changed, 1032 insertions(+), 1011 deletions(-)
create mode 100644 drivers/net/wireless/intel/iwlwifi/fw/dbg-legacy.c
diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile
index 941257b811b4..5caab593db8b 100644
--- a/drivers/net/wireless/intel/iwlwifi/Makefile
+++ b/drivers/net/wireless/intel/iwlwifi/Makefile
@@ -32,7 +32,7 @@ iwlwifi-objs += iwl-dbg-tlv.o
iwlwifi-objs += iwl-trans.o
iwlwifi-objs += fw/img.o fw/notif-wait.o fw/rs.o
-iwlwifi-objs += fw/dbg.o fw/pnvm.o fw/dump.o
+iwlwifi-objs += fw/dbg.o fw/dbg-legacy.o fw/pnvm.o fw/dump.o
iwlwifi-objs += fw/regulatory.o
iwlwifi-$(CONFIG_IWLMVM) += fw/paging.o fw/smem.o fw/init.o
iwlwifi-$(CONFIG_IWLMLD) += fw/smem.o fw/init.o
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg-legacy.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg-legacy.c
new file mode 100644
index 000000000000..19b1bfd0abee
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg-legacy.c
@@ -0,0 +1,1022 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2005-2014, 2018-2026 Intel Corporation
+ * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2015-2017 Intel Deutschland GmbH
+ */
+#include <linux/devcoredump.h>
+#include "iwl-drv.h"
+#include "runtime.h"
+#include "dbg.h"
+#include "debugfs.h"
+#include "iwl-io.h"
+#include "iwl-prph.h"
+#include "iwl-csr.h"
+#include "iwl-fh.h"
+
+/**
+ * struct iwl_fw_dump_ptrs - set of pointers needed for the fw-error-dump
+ *
+ * @fwrt_ptr: pointer to the buffer coming from fwrt
+ * @trans_ptr: pointer to struct %iwl_trans_dump_data which contains the
+ * transport's data.
+ * @fwrt_len: length of the valid data in fwrt_ptr
+ */
+struct iwl_fw_dump_ptrs {
+ struct iwl_trans_dump_data *trans_ptr;
+ void *fwrt_ptr;
+ u32 fwrt_len;
+};
+
+#define RADIO_REG_MAX_READ 0x2ad
+static void iwl_read_radio_regs(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_error_dump_data **dump_data)
+{
+ u8 *pos = (void *)(*dump_data)->data;
+ int i;
+
+ IWL_DEBUG_INFO(fwrt, "WRT radio registers dump\n");
+
+ if (!iwl_trans_grab_nic_access(fwrt->trans))
+ return;
+
+ (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RADIO_REG);
+ (*dump_data)->len = cpu_to_le32(RADIO_REG_MAX_READ);
+
+ for (i = 0; i < RADIO_REG_MAX_READ; i++) {
+ u32 rd_cmd = RADIO_RSP_RD_CMD;
+
+ rd_cmd |= i << RADIO_RSP_ADDR_POS;
+ iwl_trans_write_prph(fwrt->trans, RSP_RADIO_CMD, rd_cmd);
+ *pos = (u8)iwl_trans_read_prph(fwrt->trans, RSP_RADIO_RDDAT);
+
+ pos++;
+ }
+
+ *dump_data = iwl_fw_error_next_data(*dump_data);
+
+ iwl_trans_release_nic_access(fwrt->trans);
+}
+
+static void iwl_fwrt_dump_rxf(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_error_dump_data **dump_data,
+ int size, u32 offset, int fifo_num)
+{
+ struct iwl_fw_error_dump_fifo *fifo_hdr;
+ u32 *fifo_data;
+ u32 fifo_len;
+ int i;
+
+ fifo_hdr = (void *)(*dump_data)->data;
+ fifo_data = (void *)fifo_hdr->data;
+ fifo_len = size;
+
+ /* No need to try to read the data if the length is 0 */
+ if (fifo_len == 0)
+ return;
+
+ /* Add a TLV for the RXF */
+ (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RXF);
+ (*dump_data)->len = cpu_to_le32(fifo_len + sizeof(*fifo_hdr));
+
+ fifo_hdr->fifo_num = cpu_to_le32(fifo_num);
+ fifo_hdr->available_bytes =
+ cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+ RXF_RD_D_SPACE + offset));
+ fifo_hdr->wr_ptr =
+ cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+ RXF_RD_WR_PTR + offset));
+ fifo_hdr->rd_ptr =
+ cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+ RXF_RD_RD_PTR + offset));
+ fifo_hdr->fence_ptr =
+ cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+ RXF_RD_FENCE_PTR + offset));
+ fifo_hdr->fence_mode =
+ cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+ RXF_SET_FENCE_MODE + offset));
+
+ /* Lock fence */
+ iwl_trans_write_prph(fwrt->trans, RXF_SET_FENCE_MODE + offset, 0x1);
+ /* Set fence pointer to the same place like WR pointer */
+ iwl_trans_write_prph(fwrt->trans, RXF_LD_WR2FENCE + offset, 0x1);
+ /* Set fence offset */
+ iwl_trans_write_prph(fwrt->trans,
+ RXF_LD_FENCE_OFFSET_ADDR + offset, 0x0);
+
+ /* Read FIFO */
+ fifo_len /= sizeof(u32); /* Size in DWORDS */
+ for (i = 0; i < fifo_len; i++)
+ fifo_data[i] = iwl_trans_read_prph(fwrt->trans,
+ RXF_FIFO_RD_FENCE_INC +
+ offset);
+ *dump_data = iwl_fw_error_next_data(*dump_data);
+}
+
+static void iwl_fwrt_dump_txf(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_error_dump_data **dump_data,
+ int size, u32 offset, int fifo_num)
+{
+ struct iwl_fw_error_dump_fifo *fifo_hdr;
+ u32 *fifo_data;
+ u32 fifo_len;
+ int i;
+
+ fifo_hdr = (void *)(*dump_data)->data;
+ fifo_data = (void *)fifo_hdr->data;
+ fifo_len = size;
+
+ /* No need to try to read the data if the length is 0 */
+ if (fifo_len == 0)
+ return;
+
+ /* Add a TLV for the FIFO */
+ (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXF);
+ (*dump_data)->len = cpu_to_le32(fifo_len + sizeof(*fifo_hdr));
+
+ fifo_hdr->fifo_num = cpu_to_le32(fifo_num);
+ fifo_hdr->available_bytes =
+ cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+ TXF_FIFO_ITEM_CNT + offset));
+ fifo_hdr->wr_ptr =
+ cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+ TXF_WR_PTR + offset));
+ fifo_hdr->rd_ptr =
+ cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+ TXF_RD_PTR + offset));
+ fifo_hdr->fence_ptr =
+ cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+ TXF_FENCE_PTR + offset));
+ fifo_hdr->fence_mode =
+ cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+ TXF_LOCK_FENCE + offset));
+
+ /* Set the TXF_READ_MODIFY_ADDR to TXF_WR_PTR */
+ iwl_trans_write_prph(fwrt->trans, TXF_READ_MODIFY_ADDR + offset,
+ TXF_WR_PTR + offset);
+
+ /* Dummy-read to advance the read pointer to the head */
+ iwl_trans_read_prph(fwrt->trans, TXF_READ_MODIFY_DATA + offset);
+
+ /* Read FIFO */
+ for (i = 0; i < fifo_len / sizeof(u32); i++)
+ fifo_data[i] = iwl_trans_read_prph(fwrt->trans,
+ TXF_READ_MODIFY_DATA +
+ offset);
+
+ if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf)
+ fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx,
+ fifo_data, fifo_len);
+
+ *dump_data = iwl_fw_error_next_data(*dump_data);
+}
+
+static void iwl_fw_dump_rxf(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_error_dump_data **dump_data)
+{
+ struct iwl_fwrt_shared_mem_cfg *cfg = &fwrt->smem_cfg;
+
+ IWL_DEBUG_INFO(fwrt, "WRT RX FIFO dump\n");
+
+ if (!iwl_trans_grab_nic_access(fwrt->trans))
+ return;
+
+ if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_RXF)) {
+ /* Pull RXF1 */
+ iwl_fwrt_dump_rxf(fwrt, dump_data,
+ cfg->lmac[0].rxfifo1_size, 0, 0);
+ /* Pull RXF2 */
+ iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size,
+ RXF_DIFF_FROM_PREV +
+ fwrt->trans->mac_cfg->umac_prph_offset, 1);
+ /* Pull LMAC2 RXF1 */
+ if (fwrt->smem_cfg.num_lmacs > 1)
+ iwl_fwrt_dump_rxf(fwrt, dump_data,
+ cfg->lmac[1].rxfifo1_size,
+ LMAC2_PRPH_OFFSET, 2);
+ }
+
+ iwl_trans_release_nic_access(fwrt->trans);
+}
+
+static void iwl_fw_dump_txf(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_error_dump_data **dump_data)
+{
+ struct iwl_fw_error_dump_fifo *fifo_hdr;
+ struct iwl_fwrt_shared_mem_cfg *cfg = &fwrt->smem_cfg;
+ u32 *fifo_data;
+ u32 fifo_len;
+ int i, j;
+
+ IWL_DEBUG_INFO(fwrt, "WRT TX FIFO dump\n");
+
+ if (!iwl_trans_grab_nic_access(fwrt->trans))
+ return;
+
+ if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_TXF)) {
+ /* Pull TXF data from LMAC1 */
+ for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries; i++) {
+ /* Mark the number of TXF we're pulling now */
+ iwl_trans_write_prph(fwrt->trans, TXF_LARC_NUM, i);
+ iwl_fwrt_dump_txf(fwrt, dump_data,
+ cfg->lmac[0].txfifo_size[i], 0, i);
+ }
+
+ /* Pull TXF data from LMAC2 */
+ if (fwrt->smem_cfg.num_lmacs > 1) {
+ for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries;
+ i++) {
+ /* Mark the number of TXF we're pulling now */
+ iwl_trans_write_prph(fwrt->trans,
+ TXF_LARC_NUM +
+ LMAC2_PRPH_OFFSET, i);
+ iwl_fwrt_dump_txf(fwrt, dump_data,
+ cfg->lmac[1].txfifo_size[i],
+ LMAC2_PRPH_OFFSET,
+ i + cfg->num_txfifo_entries);
+ }
+ }
+ }
+
+ if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_INTERNAL_TXF) &&
+ fw_has_capa(&fwrt->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
+ /* Pull UMAC internal TXF data from all TXFs */
+ for (i = 0;
+ i < ARRAY_SIZE(fwrt->smem_cfg.internal_txfifo_size);
+ i++) {
+ fifo_hdr = (void *)(*dump_data)->data;
+ fifo_data = (void *)fifo_hdr->data;
+ fifo_len = fwrt->smem_cfg.internal_txfifo_size[i];
+
+ /* No need to try to read the data if the length is 0 */
+ if (fifo_len == 0)
+ continue;
+
+ /* Add a TLV for the internal FIFOs */
+ (*dump_data)->type =
+ cpu_to_le32(IWL_FW_ERROR_DUMP_INTERNAL_TXF);
+ (*dump_data)->len =
+ cpu_to_le32(fifo_len + sizeof(*fifo_hdr));
+
+ fifo_hdr->fifo_num = cpu_to_le32(i);
+
+ /* Mark the number of TXF we're pulling now */
+ iwl_trans_write_prph(fwrt->trans, TXF_CPU2_NUM, i +
+ fwrt->smem_cfg.num_txfifo_entries);
+
+ fifo_hdr->available_bytes =
+ cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+ TXF_CPU2_FIFO_ITEM_CNT));
+ fifo_hdr->wr_ptr =
+ cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+ TXF_CPU2_WR_PTR));
+ fifo_hdr->rd_ptr =
+ cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+ TXF_CPU2_RD_PTR));
+ fifo_hdr->fence_ptr =
+ cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+ TXF_CPU2_FENCE_PTR));
+ fifo_hdr->fence_mode =
+ cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+ TXF_CPU2_LOCK_FENCE));
+
+ /* Set TXF_CPU2_READ_MODIFY_ADDR to TXF_CPU2_WR_PTR */
+ iwl_trans_write_prph(fwrt->trans,
+ TXF_CPU2_READ_MODIFY_ADDR,
+ TXF_CPU2_WR_PTR);
+
+ /* Dummy-read to advance the read pointer to head */
+ iwl_trans_read_prph(fwrt->trans,
+ TXF_CPU2_READ_MODIFY_DATA);
+
+ /* Read FIFO */
+ fifo_len /= sizeof(u32); /* Size in DWORDS */
+ for (j = 0; j < fifo_len; j++)
+ fifo_data[j] =
+ iwl_trans_read_prph(fwrt->trans,
+ TXF_CPU2_READ_MODIFY_DATA);
+ *dump_data = iwl_fw_error_next_data(*dump_data);
+ }
+ }
+
+ iwl_trans_release_nic_access(fwrt->trans);
+}
+
+struct iwl_prph_range {
+ u32 start, end;
+};
+
+static const struct iwl_prph_range iwl_prph_dump_addr_comm[] = {
+ { .start = 0x00a00000, .end = 0x00a00000 },
+ { .start = 0x00a0000c, .end = 0x00a00024 },
+ { .start = 0x00a0002c, .end = 0x00a0003c },
+ { .start = 0x00a00410, .end = 0x00a00418 },
+ { .start = 0x00a00420, .end = 0x00a00420 },
+ { .start = 0x00a00428, .end = 0x00a00428 },
+ { .start = 0x00a00430, .end = 0x00a0043c },
+ { .start = 0x00a00444, .end = 0x00a00444 },
+ { .start = 0x00a004c0, .end = 0x00a004cc },
+ { .start = 0x00a004d8, .end = 0x00a004d8 },
+ { .start = 0x00a004e0, .end = 0x00a004f0 },
+ { .start = 0x00a00840, .end = 0x00a00840 },
+ { .start = 0x00a00850, .end = 0x00a00858 },
+ { .start = 0x00a01004, .end = 0x00a01008 },
+ { .start = 0x00a01010, .end = 0x00a01010 },
+ { .start = 0x00a01018, .end = 0x00a01018 },
+ { .start = 0x00a01024, .end = 0x00a01024 },
+ { .start = 0x00a0102c, .end = 0x00a01034 },
+ { .start = 0x00a0103c, .end = 0x00a01040 },
+ { .start = 0x00a01048, .end = 0x00a01094 },
+ { .start = 0x00a01c00, .end = 0x00a01c20 },
+ { .start = 0x00a01c58, .end = 0x00a01c58 },
+ { .start = 0x00a01c7c, .end = 0x00a01c7c },
+ { .start = 0x00a01c28, .end = 0x00a01c54 },
+ { .start = 0x00a01c5c, .end = 0x00a01c5c },
+ { .start = 0x00a01c60, .end = 0x00a01cdc },
+ { .start = 0x00a01ce0, .end = 0x00a01d0c },
+ { .start = 0x00a01d18, .end = 0x00a01d20 },
+ { .start = 0x00a01d2c, .end = 0x00a01d30 },
+ { .start = 0x00a01d40, .end = 0x00a01d5c },
+ { .start = 0x00a01d80, .end = 0x00a01d80 },
+ { .start = 0x00a01d98, .end = 0x00a01d9c },
+ { .start = 0x00a01da8, .end = 0x00a01da8 },
+ { .start = 0x00a01db8, .end = 0x00a01df4 },
+ { .start = 0x00a01dc0, .end = 0x00a01dfc },
+ { .start = 0x00a01e00, .end = 0x00a01e2c },
+ { .start = 0x00a01e40, .end = 0x00a01e60 },
+ { .start = 0x00a01e68, .end = 0x00a01e6c },
+ { .start = 0x00a01e74, .end = 0x00a01e74 },
+ { .start = 0x00a01e84, .end = 0x00a01e90 },
+ { .start = 0x00a01e9c, .end = 0x00a01ec4 },
+ { .start = 0x00a01ed0, .end = 0x00a01ee0 },
+ { .start = 0x00a01f00, .end = 0x00a01f1c },
+ { .start = 0x00a01f44, .end = 0x00a01ffc },
+ { .start = 0x00a02000, .end = 0x00a02048 },
+ { .start = 0x00a02068, .end = 0x00a020f0 },
+ { .start = 0x00a02100, .end = 0x00a02118 },
+ { .start = 0x00a02140, .end = 0x00a0214c },
+ { .start = 0x00a02168, .end = 0x00a0218c },
+ { .start = 0x00a021c0, .end = 0x00a021c0 },
+ { .start = 0x00a02400, .end = 0x00a02410 },
+ { .start = 0x00a02418, .end = 0x00a02420 },
+ { .start = 0x00a02428, .end = 0x00a0242c },
+ { .start = 0x00a02434, .end = 0x00a02434 },
+ { .start = 0x00a02440, .end = 0x00a02460 },
+ { .start = 0x00a02468, .end = 0x00a024b0 },
+ { .start = 0x00a024c8, .end = 0x00a024cc },
+ { .start = 0x00a02500, .end = 0x00a02504 },
+ { .start = 0x00a0250c, .end = 0x00a02510 },
+ { .start = 0x00a02540, .end = 0x00a02554 },
+ { .start = 0x00a02580, .end = 0x00a025f4 },
+ { .start = 0x00a02600, .end = 0x00a0260c },
+ { .start = 0x00a02648, .end = 0x00a02650 },
+ { .start = 0x00a02680, .end = 0x00a02680 },
+ { .start = 0x00a026c0, .end = 0x00a026d0 },
+ { .start = 0x00a02700, .end = 0x00a0270c },
+ { .start = 0x00a02804, .end = 0x00a02804 },
+ { .start = 0x00a02818, .end = 0x00a0281c },
+ { .start = 0x00a02c00, .end = 0x00a02db4 },
+ { .start = 0x00a02df4, .end = 0x00a02fb0 },
+ { .start = 0x00a03000, .end = 0x00a03014 },
+ { .start = 0x00a0301c, .end = 0x00a0302c },
+ { .start = 0x00a03034, .end = 0x00a03038 },
+ { .start = 0x00a03040, .end = 0x00a03048 },
+ { .start = 0x00a03060, .end = 0x00a03068 },
+ { .start = 0x00a03070, .end = 0x00a03074 },
+ { .start = 0x00a0307c, .end = 0x00a0307c },
+ { .start = 0x00a03080, .end = 0x00a03084 },
+ { .start = 0x00a0308c, .end = 0x00a03090 },
+ { .start = 0x00a03098, .end = 0x00a03098 },
+ { .start = 0x00a030a0, .end = 0x00a030a0 },
+ { .start = 0x00a030a8, .end = 0x00a030b4 },
+ { .start = 0x00a030bc, .end = 0x00a030bc },
+ { .start = 0x00a030c0, .end = 0x00a0312c },
+ { .start = 0x00a03c00, .end = 0x00a03c5c },
+ { .start = 0x00a04400, .end = 0x00a04454 },
+ { .start = 0x00a04460, .end = 0x00a04474 },
+ { .start = 0x00a044c0, .end = 0x00a044ec },
+ { .start = 0x00a04500, .end = 0x00a04504 },
+ { .start = 0x00a04510, .end = 0x00a04538 },
+ { .start = 0x00a04540, .end = 0x00a04548 },
+ { .start = 0x00a04560, .end = 0x00a0457c },
+ { .start = 0x00a04590, .end = 0x00a04598 },
+ { .start = 0x00a045c0, .end = 0x00a045f4 },
+};
+
+static const struct iwl_prph_range iwl_prph_dump_addr_9000[] = {
+ { .start = 0x00a05c00, .end = 0x00a05c18 },
+ { .start = 0x00a05400, .end = 0x00a056e8 },
+ { .start = 0x00a08000, .end = 0x00a098bc },
+ { .start = 0x00a02400, .end = 0x00a02758 },
+ { .start = 0x00a04764, .end = 0x00a0476c },
+ { .start = 0x00a04770, .end = 0x00a04774 },
+ { .start = 0x00a04620, .end = 0x00a04624 },
+};
+
+static const struct iwl_prph_range iwl_prph_dump_addr_22000[] = {
+ { .start = 0x00a00000, .end = 0x00a00000 },
+ { .start = 0x00a0000c, .end = 0x00a00024 },
+ { .start = 0x00a0002c, .end = 0x00a00034 },
+ { .start = 0x00a0003c, .end = 0x00a0003c },
+ { .start = 0x00a00410, .end = 0x00a00418 },
+ { .start = 0x00a00420, .end = 0x00a00420 },
+ { .start = 0x00a00428, .end = 0x00a00428 },
+ { .start = 0x00a00430, .end = 0x00a0043c },
+ { .start = 0x00a00444, .end = 0x00a00444 },
+ { .start = 0x00a00840, .end = 0x00a00840 },
+ { .start = 0x00a00850, .end = 0x00a00858 },
+ { .start = 0x00a01004, .end = 0x00a01008 },
+ { .start = 0x00a01010, .end = 0x00a01010 },
+ { .start = 0x00a01018, .end = 0x00a01018 },
+ { .start = 0x00a01024, .end = 0x00a01024 },
+ { .start = 0x00a0102c, .end = 0x00a01034 },
+ { .start = 0x00a0103c, .end = 0x00a01040 },
+ { .start = 0x00a01048, .end = 0x00a01050 },
+ { .start = 0x00a01058, .end = 0x00a01058 },
+ { .start = 0x00a01060, .end = 0x00a01070 },
+ { .start = 0x00a0108c, .end = 0x00a0108c },
+ { .start = 0x00a01c20, .end = 0x00a01c28 },
+ { .start = 0x00a01d10, .end = 0x00a01d10 },
+ { .start = 0x00a01e28, .end = 0x00a01e2c },
+ { .start = 0x00a01e60, .end = 0x00a01e60 },
+ { .start = 0x00a01e80, .end = 0x00a01e80 },
+ { .start = 0x00a01ea0, .end = 0x00a01ea0 },
+ { .start = 0x00a02000, .end = 0x00a0201c },
+ { .start = 0x00a02024, .end = 0x00a02024 },
+ { .start = 0x00a02040, .end = 0x00a02048 },
+ { .start = 0x00a020c0, .end = 0x00a020e0 },
+ { .start = 0x00a02400, .end = 0x00a02404 },
+ { .start = 0x00a0240c, .end = 0x00a02414 },
+ { .start = 0x00a0241c, .end = 0x00a0243c },
+ { .start = 0x00a02448, .end = 0x00a024bc },
+ { .start = 0x00a024c4, .end = 0x00a024cc },
+ { .start = 0x00a02508, .end = 0x00a02508 },
+ { .start = 0x00a02510, .end = 0x00a02514 },
+ { .start = 0x00a0251c, .end = 0x00a0251c },
+ { .start = 0x00a0252c, .end = 0x00a0255c },
+ { .start = 0x00a02564, .end = 0x00a025a0 },
+ { .start = 0x00a025a8, .end = 0x00a025b4 },
+ { .start = 0x00a025c0, .end = 0x00a025c0 },
+ { .start = 0x00a025e8, .end = 0x00a025f4 },
+ { .start = 0x00a02c08, .end = 0x00a02c18 },
+ { .start = 0x00a02c2c, .end = 0x00a02c38 },
+ { .start = 0x00a02c68, .end = 0x00a02c78 },
+ { .start = 0x00a03000, .end = 0x00a03000 },
+ { .start = 0x00a03010, .end = 0x00a03014 },
+ { .start = 0x00a0301c, .end = 0x00a0302c },
+ { .start = 0x00a03034, .end = 0x00a03038 },
+ { .start = 0x00a03040, .end = 0x00a03044 },
+ { .start = 0x00a03060, .end = 0x00a03068 },
+ { .start = 0x00a03070, .end = 0x00a03070 },
+ { .start = 0x00a0307c, .end = 0x00a03084 },
+ { .start = 0x00a0308c, .end = 0x00a03090 },
+ { .start = 0x00a03098, .end = 0x00a03098 },
+ { .start = 0x00a030a0, .end = 0x00a030a0 },
+ { .start = 0x00a030a8, .end = 0x00a030b4 },
+ { .start = 0x00a030bc, .end = 0x00a030c0 },
+ { .start = 0x00a030c8, .end = 0x00a030f4 },
+ { .start = 0x00a03100, .end = 0x00a0312c },
+ { .start = 0x00a03c00, .end = 0x00a03c5c },
+ { .start = 0x00a04400, .end = 0x00a04454 },
+ { .start = 0x00a04460, .end = 0x00a04474 },
+ { .start = 0x00a044c0, .end = 0x00a044ec },
+ { .start = 0x00a04500, .end = 0x00a04504 },
+ { .start = 0x00a04510, .end = 0x00a04538 },
+ { .start = 0x00a04540, .end = 0x00a04548 },
+ { .start = 0x00a04560, .end = 0x00a04560 },
+ { .start = 0x00a04570, .end = 0x00a0457c },
+ { .start = 0x00a04590, .end = 0x00a04590 },
+ { .start = 0x00a04598, .end = 0x00a04598 },
+ { .start = 0x00a045c0, .end = 0x00a045f4 },
+ { .start = 0x00a05c18, .end = 0x00a05c1c },
+ { .start = 0x00a0c000, .end = 0x00a0c018 },
+ { .start = 0x00a0c020, .end = 0x00a0c028 },
+ { .start = 0x00a0c038, .end = 0x00a0c094 },
+ { .start = 0x00a0c0c0, .end = 0x00a0c104 },
+ { .start = 0x00a0c10c, .end = 0x00a0c118 },
+ { .start = 0x00a0c150, .end = 0x00a0c174 },
+ { .start = 0x00a0c17c, .end = 0x00a0c188 },
+ { .start = 0x00a0c190, .end = 0x00a0c198 },
+ { .start = 0x00a0c1a0, .end = 0x00a0c1a8 },
+ { .start = 0x00a0c1b0, .end = 0x00a0c1b8 },
+};
+
+static const struct iwl_prph_range iwl_prph_dump_addr_ax210[] = {
+ { .start = 0x00d03c00, .end = 0x00d03c64 },
+ { .start = 0x00d05c18, .end = 0x00d05c1c },
+ { .start = 0x00d0c000, .end = 0x00d0c174 },
+};
+
+static void iwl_read_prph_block(struct iwl_trans *trans, u32 start,
+ u32 len_bytes, __le32 *data)
+{
+ u32 i;
+
+ for (i = 0; i < len_bytes; i += 4)
+ *data++ = cpu_to_le32(iwl_trans_read_prph(trans, start + i));
+}
+
+static void iwl_dump_prph(struct iwl_fw_runtime *fwrt,
+ const struct iwl_prph_range *iwl_prph_dump_addr,
+ u32 range_len, void *ptr)
+{
+ struct iwl_fw_error_dump_prph *prph;
+ struct iwl_trans *trans = fwrt->trans;
+ struct iwl_fw_error_dump_data **data =
+ (struct iwl_fw_error_dump_data **)ptr;
+ u32 i;
+
+ if (!data)
+ return;
+
+ IWL_DEBUG_INFO(trans, "WRT PRPH dump\n");
+
+ if (!iwl_trans_grab_nic_access(trans))
+ return;
+
+ for (i = 0; i < range_len; i++) {
+ /* The range includes both boundaries */
+ int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
+ iwl_prph_dump_addr[i].start + 4;
+
+ (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
+ (*data)->len = cpu_to_le32(sizeof(*prph) +
+ num_bytes_in_chunk);
+ prph = (void *)(*data)->data;
+ prph->prph_start = cpu_to_le32(iwl_prph_dump_addr[i].start);
+
+ iwl_read_prph_block(trans, iwl_prph_dump_addr[i].start,
+ /* our range is inclusive, hence + 4 */
+ iwl_prph_dump_addr[i].end -
+ iwl_prph_dump_addr[i].start + 4,
+ (void *)prph->data);
+
+ *data = iwl_fw_error_next_data(*data);
+ }
+
+ iwl_trans_release_nic_access(trans);
+}
+
+static void iwl_fw_get_prph_len(struct iwl_fw_runtime *fwrt,
+ const struct iwl_prph_range *iwl_prph_dump_addr,
+ u32 range_len, void *ptr)
+{
+ u32 *prph_len = (u32 *)ptr;
+ int i, num_bytes_in_chunk;
+
+ if (!prph_len)
+ return;
+
+ for (i = 0; i < range_len; i++) {
+ /* The range includes both boundaries */
+ num_bytes_in_chunk =
+ iwl_prph_dump_addr[i].end -
+ iwl_prph_dump_addr[i].start + 4;
+
+ *prph_len += sizeof(struct iwl_fw_error_dump_data) +
+ sizeof(struct iwl_fw_error_dump_prph) +
+ num_bytes_in_chunk;
+ }
+}
+
+static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr,
+ void (*handler)(struct iwl_fw_runtime *,
+ const struct iwl_prph_range *,
+ u32, void *))
+{
+ u32 range_len;
+
+ if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ range_len = ARRAY_SIZE(iwl_prph_dump_addr_ax210);
+ handler(fwrt, iwl_prph_dump_addr_ax210, range_len, ptr);
+ } else if (fwrt->trans->mac_cfg->device_family >=
+ IWL_DEVICE_FAMILY_22000) {
+ range_len = ARRAY_SIZE(iwl_prph_dump_addr_22000);
+ handler(fwrt, iwl_prph_dump_addr_22000, range_len, ptr);
+ } else {
+ range_len = ARRAY_SIZE(iwl_prph_dump_addr_comm);
+ handler(fwrt, iwl_prph_dump_addr_comm, range_len, ptr);
+
+ if (fwrt->trans->mac_cfg->mq_rx_supported) {
+ range_len = ARRAY_SIZE(iwl_prph_dump_addr_9000);
+ handler(fwrt, iwl_prph_dump_addr_9000, range_len, ptr);
+ }
+ }
+}
+
+static void iwl_fw_dump_mem(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_error_dump_data **dump_data,
+ u32 len, u32 ofs, u32 type)
+{
+ struct iwl_fw_error_dump_mem *dump_mem;
+
+ if (!len)
+ return;
+
+ (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
+ (*dump_data)->len = cpu_to_le32(len + sizeof(*dump_mem));
+ dump_mem = (void *)(*dump_data)->data;
+ dump_mem->type = cpu_to_le32(type);
+ dump_mem->offset = cpu_to_le32(ofs);
+ iwl_trans_read_mem_bytes(fwrt->trans, ofs, dump_mem->data, len);
+ *dump_data = iwl_fw_error_next_data(*dump_data);
+
+ if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
+ fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, ofs,
+ dump_mem->data, len);
+
+ IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type);
+}
+
+#define ADD_LEN(len, item_len, const_len) \
+ do {size_t item = item_len; len += (!!item) * const_len + item; } \
+ while (0)
+
+static int iwl_fw_rxf_len(struct iwl_fw_runtime *fwrt,
+ struct iwl_fwrt_shared_mem_cfg *mem_cfg)
+{
+ size_t hdr_len = sizeof(struct iwl_fw_error_dump_data) +
+ sizeof(struct iwl_fw_error_dump_fifo);
+ u32 fifo_len = 0;
+ int i;
+
+ if (!iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_RXF))
+ return 0;
+
+ /* Count RXF2 size */
+ ADD_LEN(fifo_len, mem_cfg->rxfifo2_size, hdr_len);
+
+ /* Count RXF1 sizes */
+ if (WARN_ON(mem_cfg->num_lmacs > MAX_NUM_LMAC))
+ mem_cfg->num_lmacs = MAX_NUM_LMAC;
+
+ for (i = 0; i < mem_cfg->num_lmacs; i++)
+ ADD_LEN(fifo_len, mem_cfg->lmac[i].rxfifo1_size, hdr_len);
+
+ return fifo_len;
+}
+
+static int iwl_fw_txf_len(struct iwl_fw_runtime *fwrt,
+ struct iwl_fwrt_shared_mem_cfg *mem_cfg)
+{
+ size_t hdr_len = sizeof(struct iwl_fw_error_dump_data) +
+ sizeof(struct iwl_fw_error_dump_fifo);
+ u32 fifo_len = 0;
+ int i;
+
+ if (!iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_TXF))
+ goto dump_internal_txf;
+
+ /* Count TXF sizes */
+ if (WARN_ON(mem_cfg->num_lmacs > MAX_NUM_LMAC))
+ mem_cfg->num_lmacs = MAX_NUM_LMAC;
+
+ for (i = 0; i < mem_cfg->num_lmacs; i++) {
+ int j;
+
+ for (j = 0; j < mem_cfg->num_txfifo_entries; j++)
+ ADD_LEN(fifo_len, mem_cfg->lmac[i].txfifo_size[j],
+ hdr_len);
+ }
+
+dump_internal_txf:
+ if (!(iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_INTERNAL_TXF) &&
+ fw_has_capa(&fwrt->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)))
+ goto out;
+
+ for (i = 0; i < ARRAY_SIZE(mem_cfg->internal_txfifo_size); i++)
+ ADD_LEN(fifo_len, mem_cfg->internal_txfifo_size[i], hdr_len);
+
+out:
+ return fifo_len;
+}
+
+static void iwl_dump_paging(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_error_dump_data **data)
+{
+ int i;
+
+ IWL_DEBUG_INFO(fwrt, "WRT paging dump\n");
+ for (i = 1; i < fwrt->num_of_paging_blk + 1; i++) {
+ struct iwl_fw_error_dump_paging *paging;
+ struct page *pages =
+ fwrt->fw_paging_db[i].fw_paging_block;
+ dma_addr_t addr = fwrt->fw_paging_db[i].fw_paging_phys;
+
+ (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING);
+ (*data)->len = cpu_to_le32(sizeof(*paging) +
+ PAGING_BLOCK_SIZE);
+ paging = (void *)(*data)->data;
+ paging->index = cpu_to_le32(i);
+ dma_sync_single_for_cpu(fwrt->trans->dev, addr,
+ PAGING_BLOCK_SIZE,
+ DMA_BIDIRECTIONAL);
+ memcpy(paging->data, page_address(pages),
+ PAGING_BLOCK_SIZE);
+ dma_sync_single_for_device(fwrt->trans->dev, addr,
+ PAGING_BLOCK_SIZE,
+ DMA_BIDIRECTIONAL);
+ (*data) = iwl_fw_error_next_data(*data);
+
+ if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
+ fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx,
+ fwrt->fw_paging_db[i].fw_offs,
+ paging->data,
+ PAGING_BLOCK_SIZE);
+ }
+}
+
+static struct iwl_fw_error_dump_file *
+iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_dump_ptrs *fw_error_dump,
+ struct iwl_fwrt_dump_data *data)
+{
+ struct iwl_fw_error_dump_file *dump_file;
+ struct iwl_fw_error_dump_data *dump_data;
+ struct iwl_fw_error_dump_info *dump_info;
+ struct iwl_fw_error_dump_smem_cfg *dump_smem_cfg;
+ struct iwl_fw_error_dump_trigger_desc *dump_trig;
+ u32 sram_len, sram_ofs;
+ const struct iwl_fw_dbg_mem_seg_tlv *fw_mem = fwrt->fw->dbg.mem_tlv;
+ struct iwl_fwrt_shared_mem_cfg *mem_cfg = &fwrt->smem_cfg;
+ u32 file_len, fifo_len = 0, prph_len = 0, radio_len = 0;
+ u32 smem_len = fwrt->fw->dbg.n_mem_tlv ? 0 : fwrt->trans->mac_cfg->base->smem_len;
+ u32 sram2_len = fwrt->fw->dbg.n_mem_tlv ?
+ 0 : fwrt->trans->cfg->dccm2_len;
+ int i;
+
+ /* SRAM - include stack CCM if driver knows the values for it */
+ if (!fwrt->trans->cfg->dccm_offset ||
+ !fwrt->trans->cfg->dccm_len) {
+ const struct fw_img *img;
+
+ if (fwrt->cur_fw_img >= IWL_UCODE_TYPE_MAX)
+ return NULL;
+ img = &fwrt->fw->img[fwrt->cur_fw_img];
+ sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
+ sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
+ } else {
+ sram_ofs = fwrt->trans->cfg->dccm_offset;
+ sram_len = fwrt->trans->cfg->dccm_len;
+ }
+
+ /* reading RXF/TXF sizes */
+ if (iwl_trans_is_fw_error(fwrt->trans)) {
+ fifo_len = iwl_fw_rxf_len(fwrt, mem_cfg);
+ fifo_len += iwl_fw_txf_len(fwrt, mem_cfg);
+
+ /* Make room for PRPH registers */
+ if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_PRPH))
+ iwl_fw_prph_handler(fwrt, &prph_len,
+ iwl_fw_get_prph_len);
+
+ if (fwrt->trans->mac_cfg->device_family ==
+ IWL_DEVICE_FAMILY_7000 &&
+ iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_RADIO_REG))
+ radio_len = sizeof(*dump_data) + RADIO_REG_MAX_READ;
+ }
+
+ file_len = sizeof(*dump_file) + fifo_len + prph_len + radio_len;
+
+ if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_DEV_FW_INFO))
+ file_len += sizeof(*dump_data) + sizeof(*dump_info);
+ if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM_CFG))
+ file_len += sizeof(*dump_data) + sizeof(*dump_smem_cfg);
+
+ if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM)) {
+ size_t hdr_len = sizeof(*dump_data) +
+ sizeof(struct iwl_fw_error_dump_mem);
+
+ /* Dump SRAM only if no mem_tlvs */
+ if (!fwrt->fw->dbg.n_mem_tlv)
+ ADD_LEN(file_len, sram_len, hdr_len);
+
+ /* Make room for all mem types that exist */
+ ADD_LEN(file_len, smem_len, hdr_len);
+ ADD_LEN(file_len, sram2_len, hdr_len);
+
+ for (i = 0; i < fwrt->fw->dbg.n_mem_tlv; i++)
+ ADD_LEN(file_len, le32_to_cpu(fw_mem[i].len), hdr_len);
+ }
+
+ /* Make room for fw's virtual image pages, if it exists */
+ if (iwl_fw_dbg_is_paging_enabled(fwrt))
+ file_len += fwrt->num_of_paging_blk *
+ (sizeof(*dump_data) +
+ sizeof(struct iwl_fw_error_dump_paging) +
+ PAGING_BLOCK_SIZE);
+
+ if (iwl_fw_dbg_is_d3_debug_enabled(fwrt) && fwrt->dump.d3_debug_data) {
+ file_len += sizeof(*dump_data) +
+ fwrt->trans->mac_cfg->base->d3_debug_data_length * 2;
+ }
+
+ /* If we only want a monitor dump, reset the file length */
+ if (data->monitor_only) {
+ file_len = sizeof(*dump_file) + sizeof(*dump_data) * 2 +
+ sizeof(*dump_info) + sizeof(*dump_smem_cfg);
+ }
+
+ if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_ERROR_INFO) &&
+ data->desc)
+ file_len += sizeof(*dump_data) + sizeof(*dump_trig) +
+ data->desc->len;
+
+ dump_file = vzalloc(file_len);
+ if (!dump_file)
+ return NULL;
+
+ fw_error_dump->fwrt_ptr = dump_file;
+
+ dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
+ dump_data = (void *)dump_file->data;
+
+ if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_DEV_FW_INFO)) {
+ dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
+ dump_data->len = cpu_to_le32(sizeof(*dump_info));
+ dump_info = (void *)dump_data->data;
+ dump_info->hw_type =
+ cpu_to_le32(CSR_HW_REV_TYPE(fwrt->trans->info.hw_rev));
+ dump_info->hw_step =
+ cpu_to_le32(fwrt->trans->info.hw_rev_step);
+ memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable,
+ sizeof(dump_info->fw_human_readable));
+ strscpy_pad(dump_info->dev_human_readable,
+ fwrt->trans->info.name,
+ sizeof(dump_info->dev_human_readable));
+ strscpy_pad(dump_info->bus_human_readable, fwrt->dev->bus->name,
+ sizeof(dump_info->bus_human_readable));
+ dump_info->num_of_lmacs = fwrt->smem_cfg.num_lmacs;
+ dump_info->lmac_err_id[0] =
+ cpu_to_le32(fwrt->dump.lmac_err_id[0]);
+ if (fwrt->smem_cfg.num_lmacs > 1)
+ dump_info->lmac_err_id[1] =
+ cpu_to_le32(fwrt->dump.lmac_err_id[1]);
+ dump_info->umac_err_id = cpu_to_le32(fwrt->dump.umac_err_id);
+
+ dump_data = iwl_fw_error_next_data(dump_data);
+ }
+
+ if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM_CFG)) {
+ /* Dump shared memory configuration */
+ dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_CFG);
+ dump_data->len = cpu_to_le32(sizeof(*dump_smem_cfg));
+ dump_smem_cfg = (void *)dump_data->data;
+ dump_smem_cfg->num_lmacs = cpu_to_le32(mem_cfg->num_lmacs);
+ dump_smem_cfg->num_txfifo_entries =
+ cpu_to_le32(mem_cfg->num_txfifo_entries);
+ for (i = 0; i < MAX_NUM_LMAC; i++) {
+ int j;
+ u32 *txf_size = mem_cfg->lmac[i].txfifo_size;
+
+ for (j = 0; j < TX_FIFO_MAX_NUM; j++)
+ dump_smem_cfg->lmac[i].txfifo_size[j] =
+ cpu_to_le32(txf_size[j]);
+ dump_smem_cfg->lmac[i].rxfifo1_size =
+ cpu_to_le32(mem_cfg->lmac[i].rxfifo1_size);
+ }
+ dump_smem_cfg->rxfifo2_size =
+ cpu_to_le32(mem_cfg->rxfifo2_size);
+ dump_smem_cfg->internal_txfifo_addr =
+ cpu_to_le32(mem_cfg->internal_txfifo_addr);
+ for (i = 0; i < TX_FIFO_INTERNAL_MAX_NUM; i++) {
+ dump_smem_cfg->internal_txfifo_size[i] =
+ cpu_to_le32(mem_cfg->internal_txfifo_size[i]);
+ }
+
+ dump_data = iwl_fw_error_next_data(dump_data);
+ }
+
+ /* We only dump the FIFOs if the FW is in error state */
+ if (fifo_len) {
+ iwl_fw_dump_rxf(fwrt, &dump_data);
+ iwl_fw_dump_txf(fwrt, &dump_data);
+ }
+
+ if (radio_len)
+ iwl_read_radio_regs(fwrt, &dump_data);
+
+ if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_ERROR_INFO) &&
+ data->desc) {
+ dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_ERROR_INFO);
+ dump_data->len = cpu_to_le32(sizeof(*dump_trig) +
+ data->desc->len);
+ dump_trig = (void *)dump_data->data;
+ memcpy(dump_trig, &data->desc->trig_desc,
+ sizeof(*dump_trig) + data->desc->len);
+
+ dump_data = iwl_fw_error_next_data(dump_data);
+ }
+
+ /* In case we only want monitor dump, skip to dump transport data */
+ if (data->monitor_only)
+ goto out;
+
+ if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM)) {
+ const struct iwl_fw_dbg_mem_seg_tlv *fw_dbg_mem =
+ fwrt->fw->dbg.mem_tlv;
+
+ if (!fwrt->fw->dbg.n_mem_tlv)
+ iwl_fw_dump_mem(fwrt, &dump_data, sram_len, sram_ofs,
+ IWL_FW_ERROR_DUMP_MEM_SRAM);
+
+ for (i = 0; i < fwrt->fw->dbg.n_mem_tlv; i++) {
+ u32 len = le32_to_cpu(fw_dbg_mem[i].len);
+ u32 ofs = le32_to_cpu(fw_dbg_mem[i].ofs);
+
+ iwl_fw_dump_mem(fwrt, &dump_data, len, ofs,
+ le32_to_cpu(fw_dbg_mem[i].data_type));
+ }
+
+ iwl_fw_dump_mem(fwrt, &dump_data, smem_len,
+ fwrt->trans->mac_cfg->base->smem_offset,
+ IWL_FW_ERROR_DUMP_MEM_SMEM);
+
+ iwl_fw_dump_mem(fwrt, &dump_data, sram2_len,
+ fwrt->trans->cfg->dccm2_offset,
+ IWL_FW_ERROR_DUMP_MEM_SRAM);
+ }
+
+ if (iwl_fw_dbg_is_d3_debug_enabled(fwrt) && fwrt->dump.d3_debug_data) {
+ u32 addr = fwrt->trans->mac_cfg->base->d3_debug_data_base_addr;
+ size_t data_size = fwrt->trans->mac_cfg->base->d3_debug_data_length;
+
+ dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_D3_DEBUG_DATA);
+ dump_data->len = cpu_to_le32(data_size * 2);
+
+ memcpy(dump_data->data, fwrt->dump.d3_debug_data, data_size);
+
+ kfree(fwrt->dump.d3_debug_data);
+ fwrt->dump.d3_debug_data = NULL;
+
+ iwl_trans_read_mem_bytes(fwrt->trans, addr,
+ dump_data->data + data_size,
+ data_size);
+
+ if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
+ fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, addr,
+ dump_data->data + data_size,
+ data_size);
+
+ dump_data = iwl_fw_error_next_data(dump_data);
+ }
+
+ /* Dump fw's virtual image */
+ if (iwl_fw_dbg_is_paging_enabled(fwrt))
+ iwl_dump_paging(fwrt, &dump_data);
+
+ if (prph_len)
+ iwl_fw_prph_handler(fwrt, &dump_data, iwl_dump_prph);
+
+out:
+ dump_file->file_len = cpu_to_le32(file_len);
+ return dump_file;
+}
+
+void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
+ struct iwl_fwrt_dump_data *dump_data)
+{
+ struct iwl_fw_dump_ptrs fw_error_dump = {};
+ struct iwl_fw_error_dump_file *dump_file;
+ struct scatterlist *sg_dump_data;
+ u32 file_len;
+ u32 dump_mask = fwrt->fw->dbg.dump_mask;
+
+ dump_file = iwl_fw_error_dump_file(fwrt, &fw_error_dump, dump_data);
+ if (!dump_file)
+ return;
+
+ if (dump_data->monitor_only)
+ dump_mask &= BIT(IWL_FW_ERROR_DUMP_FW_MONITOR);
+
+ fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask,
+ fwrt->sanitize_ops,
+ fwrt->sanitize_ctx);
+ file_len = le32_to_cpu(dump_file->file_len);
+ fw_error_dump.fwrt_len = file_len;
+
+ if (fw_error_dump.trans_ptr) {
+ file_len += fw_error_dump.trans_ptr->len;
+ dump_file->file_len = cpu_to_le32(file_len);
+ }
+
+ sg_dump_data = iwl_fw_dbg_alloc_sgtable(file_len);
+ if (sg_dump_data) {
+ sg_pcopy_from_buffer(sg_dump_data,
+ sg_nents(sg_dump_data),
+ fw_error_dump.fwrt_ptr,
+ fw_error_dump.fwrt_len, 0);
+ if (fw_error_dump.trans_ptr)
+ sg_pcopy_from_buffer(sg_dump_data,
+ sg_nents(sg_dump_data),
+ fw_error_dump.trans_ptr->data,
+ fw_error_dump.trans_ptr->len,
+ fw_error_dump.fwrt_len);
+ dev_coredumpsg(fwrt->trans->dev, sg_dump_data, file_len,
+ GFP_KERNEL);
+ }
+ vfree(fw_error_dump.fwrt_ptr);
+ vfree(fw_error_dump.trans_ptr);
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 18667de4915f..64ead8ecd52c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -13,556 +13,13 @@
#include "iwl-prph.h"
#include "iwl-csr.h"
#include "iwl-fh.h"
-/**
- * struct iwl_fw_dump_ptrs - set of pointers needed for the fw-error-dump
- *
- * @fwrt_ptr: pointer to the buffer coming from fwrt
- * @trans_ptr: pointer to struct %iwl_trans_dump_data which contains the
- * transport's data.
- * @fwrt_len: length of the valid data in fwrt_ptr
- */
-struct iwl_fw_dump_ptrs {
- struct iwl_trans_dump_data *trans_ptr;
- void *fwrt_ptr;
- u32 fwrt_len;
-};
-
-#define RADIO_REG_MAX_READ 0x2ad
-static void iwl_read_radio_regs(struct iwl_fw_runtime *fwrt,
- struct iwl_fw_error_dump_data **dump_data)
-{
- u8 *pos = (void *)(*dump_data)->data;
- int i;
-
- IWL_DEBUG_INFO(fwrt, "WRT radio registers dump\n");
-
- if (!iwl_trans_grab_nic_access(fwrt->trans))
- return;
-
- (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RADIO_REG);
- (*dump_data)->len = cpu_to_le32(RADIO_REG_MAX_READ);
-
- for (i = 0; i < RADIO_REG_MAX_READ; i++) {
- u32 rd_cmd = RADIO_RSP_RD_CMD;
-
- rd_cmd |= i << RADIO_RSP_ADDR_POS;
- iwl_trans_write_prph(fwrt->trans, RSP_RADIO_CMD, rd_cmd);
- *pos = (u8)iwl_trans_read_prph(fwrt->trans, RSP_RADIO_RDDAT);
-
- pos++;
- }
-
- *dump_data = iwl_fw_error_next_data(*dump_data);
-
- iwl_trans_release_nic_access(fwrt->trans);
-}
-
-static void iwl_fwrt_dump_rxf(struct iwl_fw_runtime *fwrt,
- struct iwl_fw_error_dump_data **dump_data,
- int size, u32 offset, int fifo_num)
-{
- struct iwl_fw_error_dump_fifo *fifo_hdr;
- u32 *fifo_data;
- u32 fifo_len;
- int i;
-
- fifo_hdr = (void *)(*dump_data)->data;
- fifo_data = (void *)fifo_hdr->data;
- fifo_len = size;
-
- /* No need to try to read the data if the length is 0 */
- if (fifo_len == 0)
- return;
-
- /* Add a TLV for the RXF */
- (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RXF);
- (*dump_data)->len = cpu_to_le32(fifo_len + sizeof(*fifo_hdr));
-
- fifo_hdr->fifo_num = cpu_to_le32(fifo_num);
- fifo_hdr->available_bytes =
- cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
- RXF_RD_D_SPACE + offset));
- fifo_hdr->wr_ptr =
- cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
- RXF_RD_WR_PTR + offset));
- fifo_hdr->rd_ptr =
- cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
- RXF_RD_RD_PTR + offset));
- fifo_hdr->fence_ptr =
- cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
- RXF_RD_FENCE_PTR + offset));
- fifo_hdr->fence_mode =
- cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
- RXF_SET_FENCE_MODE + offset));
-
- /* Lock fence */
- iwl_trans_write_prph(fwrt->trans, RXF_SET_FENCE_MODE + offset, 0x1);
- /* Set fence pointer to the same place like WR pointer */
- iwl_trans_write_prph(fwrt->trans, RXF_LD_WR2FENCE + offset, 0x1);
- /* Set fence offset */
- iwl_trans_write_prph(fwrt->trans,
- RXF_LD_FENCE_OFFSET_ADDR + offset, 0x0);
-
- /* Read FIFO */
- fifo_len /= sizeof(u32); /* Size in DWORDS */
- for (i = 0; i < fifo_len; i++)
- fifo_data[i] = iwl_trans_read_prph(fwrt->trans,
- RXF_FIFO_RD_FENCE_INC +
- offset);
- *dump_data = iwl_fw_error_next_data(*dump_data);
-}
-
-static void iwl_fwrt_dump_txf(struct iwl_fw_runtime *fwrt,
- struct iwl_fw_error_dump_data **dump_data,
- int size, u32 offset, int fifo_num)
-{
- struct iwl_fw_error_dump_fifo *fifo_hdr;
- u32 *fifo_data;
- u32 fifo_len;
- int i;
-
- fifo_hdr = (void *)(*dump_data)->data;
- fifo_data = (void *)fifo_hdr->data;
- fifo_len = size;
-
- /* No need to try to read the data if the length is 0 */
- if (fifo_len == 0)
- return;
-
- /* Add a TLV for the FIFO */
- (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXF);
- (*dump_data)->len = cpu_to_le32(fifo_len + sizeof(*fifo_hdr));
-
- fifo_hdr->fifo_num = cpu_to_le32(fifo_num);
- fifo_hdr->available_bytes =
- cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
- TXF_FIFO_ITEM_CNT + offset));
- fifo_hdr->wr_ptr =
- cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
- TXF_WR_PTR + offset));
- fifo_hdr->rd_ptr =
- cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
- TXF_RD_PTR + offset));
- fifo_hdr->fence_ptr =
- cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
- TXF_FENCE_PTR + offset));
- fifo_hdr->fence_mode =
- cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
- TXF_LOCK_FENCE + offset));
-
- /* Set the TXF_READ_MODIFY_ADDR to TXF_WR_PTR */
- iwl_trans_write_prph(fwrt->trans, TXF_READ_MODIFY_ADDR + offset,
- TXF_WR_PTR + offset);
-
- /* Dummy-read to advance the read pointer to the head */
- iwl_trans_read_prph(fwrt->trans, TXF_READ_MODIFY_DATA + offset);
-
- /* Read FIFO */
- for (i = 0; i < fifo_len / sizeof(u32); i++)
- fifo_data[i] = iwl_trans_read_prph(fwrt->trans,
- TXF_READ_MODIFY_DATA +
- offset);
-
- if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf)
- fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx,
- fifo_data, fifo_len);
-
- *dump_data = iwl_fw_error_next_data(*dump_data);
-}
-
-static void iwl_fw_dump_rxf(struct iwl_fw_runtime *fwrt,
- struct iwl_fw_error_dump_data **dump_data)
-{
- struct iwl_fwrt_shared_mem_cfg *cfg = &fwrt->smem_cfg;
-
- IWL_DEBUG_INFO(fwrt, "WRT RX FIFO dump\n");
-
- if (!iwl_trans_grab_nic_access(fwrt->trans))
- return;
-
- if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_RXF)) {
- /* Pull RXF1 */
- iwl_fwrt_dump_rxf(fwrt, dump_data,
- cfg->lmac[0].rxfifo1_size, 0, 0);
- /* Pull RXF2 */
- iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size,
- RXF_DIFF_FROM_PREV +
- fwrt->trans->mac_cfg->umac_prph_offset, 1);
- /* Pull LMAC2 RXF1 */
- if (fwrt->smem_cfg.num_lmacs > 1)
- iwl_fwrt_dump_rxf(fwrt, dump_data,
- cfg->lmac[1].rxfifo1_size,
- LMAC2_PRPH_OFFSET, 2);
- }
-
- iwl_trans_release_nic_access(fwrt->trans);
-}
-
-static void iwl_fw_dump_txf(struct iwl_fw_runtime *fwrt,
- struct iwl_fw_error_dump_data **dump_data)
-{
- struct iwl_fw_error_dump_fifo *fifo_hdr;
- struct iwl_fwrt_shared_mem_cfg *cfg = &fwrt->smem_cfg;
- u32 *fifo_data;
- u32 fifo_len;
- int i, j;
-
- IWL_DEBUG_INFO(fwrt, "WRT TX FIFO dump\n");
-
- if (!iwl_trans_grab_nic_access(fwrt->trans))
- return;
-
- if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_TXF)) {
- /* Pull TXF data from LMAC1 */
- for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries; i++) {
- /* Mark the number of TXF we're pulling now */
- iwl_trans_write_prph(fwrt->trans, TXF_LARC_NUM, i);
- iwl_fwrt_dump_txf(fwrt, dump_data,
- cfg->lmac[0].txfifo_size[i], 0, i);
- }
-
- /* Pull TXF data from LMAC2 */
- if (fwrt->smem_cfg.num_lmacs > 1) {
- for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries;
- i++) {
- /* Mark the number of TXF we're pulling now */
- iwl_trans_write_prph(fwrt->trans,
- TXF_LARC_NUM +
- LMAC2_PRPH_OFFSET, i);
- iwl_fwrt_dump_txf(fwrt, dump_data,
- cfg->lmac[1].txfifo_size[i],
- LMAC2_PRPH_OFFSET,
- i + cfg->num_txfifo_entries);
- }
- }
- }
-
- if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_INTERNAL_TXF) &&
- fw_has_capa(&fwrt->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
- /* Pull UMAC internal TXF data from all TXFs */
- for (i = 0;
- i < ARRAY_SIZE(fwrt->smem_cfg.internal_txfifo_size);
- i++) {
- fifo_hdr = (void *)(*dump_data)->data;
- fifo_data = (void *)fifo_hdr->data;
- fifo_len = fwrt->smem_cfg.internal_txfifo_size[i];
-
- /* No need to try to read the data if the length is 0 */
- if (fifo_len == 0)
- continue;
-
- /* Add a TLV for the internal FIFOs */
- (*dump_data)->type =
- cpu_to_le32(IWL_FW_ERROR_DUMP_INTERNAL_TXF);
- (*dump_data)->len =
- cpu_to_le32(fifo_len + sizeof(*fifo_hdr));
-
- fifo_hdr->fifo_num = cpu_to_le32(i);
-
- /* Mark the number of TXF we're pulling now */
- iwl_trans_write_prph(fwrt->trans, TXF_CPU2_NUM, i +
- fwrt->smem_cfg.num_txfifo_entries);
-
- fifo_hdr->available_bytes =
- cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
- TXF_CPU2_FIFO_ITEM_CNT));
- fifo_hdr->wr_ptr =
- cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
- TXF_CPU2_WR_PTR));
- fifo_hdr->rd_ptr =
- cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
- TXF_CPU2_RD_PTR));
- fifo_hdr->fence_ptr =
- cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
- TXF_CPU2_FENCE_PTR));
- fifo_hdr->fence_mode =
- cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
- TXF_CPU2_LOCK_FENCE));
-
- /* Set TXF_CPU2_READ_MODIFY_ADDR to TXF_CPU2_WR_PTR */
- iwl_trans_write_prph(fwrt->trans,
- TXF_CPU2_READ_MODIFY_ADDR,
- TXF_CPU2_WR_PTR);
-
- /* Dummy-read to advance the read pointer to head */
- iwl_trans_read_prph(fwrt->trans,
- TXF_CPU2_READ_MODIFY_DATA);
-
- /* Read FIFO */
- fifo_len /= sizeof(u32); /* Size in DWORDS */
- for (j = 0; j < fifo_len; j++)
- fifo_data[j] =
- iwl_trans_read_prph(fwrt->trans,
- TXF_CPU2_READ_MODIFY_DATA);
- *dump_data = iwl_fw_error_next_data(*dump_data);
- }
- }
-
- iwl_trans_release_nic_access(fwrt->trans);
-}
-
-struct iwl_prph_range {
- u32 start, end;
-};
-
-static const struct iwl_prph_range iwl_prph_dump_addr_comm[] = {
- { .start = 0x00a00000, .end = 0x00a00000 },
- { .start = 0x00a0000c, .end = 0x00a00024 },
- { .start = 0x00a0002c, .end = 0x00a0003c },
- { .start = 0x00a00410, .end = 0x00a00418 },
- { .start = 0x00a00420, .end = 0x00a00420 },
- { .start = 0x00a00428, .end = 0x00a00428 },
- { .start = 0x00a00430, .end = 0x00a0043c },
- { .start = 0x00a00444, .end = 0x00a00444 },
- { .start = 0x00a004c0, .end = 0x00a004cc },
- { .start = 0x00a004d8, .end = 0x00a004d8 },
- { .start = 0x00a004e0, .end = 0x00a004f0 },
- { .start = 0x00a00840, .end = 0x00a00840 },
- { .start = 0x00a00850, .end = 0x00a00858 },
- { .start = 0x00a01004, .end = 0x00a01008 },
- { .start = 0x00a01010, .end = 0x00a01010 },
- { .start = 0x00a01018, .end = 0x00a01018 },
- { .start = 0x00a01024, .end = 0x00a01024 },
- { .start = 0x00a0102c, .end = 0x00a01034 },
- { .start = 0x00a0103c, .end = 0x00a01040 },
- { .start = 0x00a01048, .end = 0x00a01094 },
- { .start = 0x00a01c00, .end = 0x00a01c20 },
- { .start = 0x00a01c58, .end = 0x00a01c58 },
- { .start = 0x00a01c7c, .end = 0x00a01c7c },
- { .start = 0x00a01c28, .end = 0x00a01c54 },
- { .start = 0x00a01c5c, .end = 0x00a01c5c },
- { .start = 0x00a01c60, .end = 0x00a01cdc },
- { .start = 0x00a01ce0, .end = 0x00a01d0c },
- { .start = 0x00a01d18, .end = 0x00a01d20 },
- { .start = 0x00a01d2c, .end = 0x00a01d30 },
- { .start = 0x00a01d40, .end = 0x00a01d5c },
- { .start = 0x00a01d80, .end = 0x00a01d80 },
- { .start = 0x00a01d98, .end = 0x00a01d9c },
- { .start = 0x00a01da8, .end = 0x00a01da8 },
- { .start = 0x00a01db8, .end = 0x00a01df4 },
- { .start = 0x00a01dc0, .end = 0x00a01dfc },
- { .start = 0x00a01e00, .end = 0x00a01e2c },
- { .start = 0x00a01e40, .end = 0x00a01e60 },
- { .start = 0x00a01e68, .end = 0x00a01e6c },
- { .start = 0x00a01e74, .end = 0x00a01e74 },
- { .start = 0x00a01e84, .end = 0x00a01e90 },
- { .start = 0x00a01e9c, .end = 0x00a01ec4 },
- { .start = 0x00a01ed0, .end = 0x00a01ee0 },
- { .start = 0x00a01f00, .end = 0x00a01f1c },
- { .start = 0x00a01f44, .end = 0x00a01ffc },
- { .start = 0x00a02000, .end = 0x00a02048 },
- { .start = 0x00a02068, .end = 0x00a020f0 },
- { .start = 0x00a02100, .end = 0x00a02118 },
- { .start = 0x00a02140, .end = 0x00a0214c },
- { .start = 0x00a02168, .end = 0x00a0218c },
- { .start = 0x00a021c0, .end = 0x00a021c0 },
- { .start = 0x00a02400, .end = 0x00a02410 },
- { .start = 0x00a02418, .end = 0x00a02420 },
- { .start = 0x00a02428, .end = 0x00a0242c },
- { .start = 0x00a02434, .end = 0x00a02434 },
- { .start = 0x00a02440, .end = 0x00a02460 },
- { .start = 0x00a02468, .end = 0x00a024b0 },
- { .start = 0x00a024c8, .end = 0x00a024cc },
- { .start = 0x00a02500, .end = 0x00a02504 },
- { .start = 0x00a0250c, .end = 0x00a02510 },
- { .start = 0x00a02540, .end = 0x00a02554 },
- { .start = 0x00a02580, .end = 0x00a025f4 },
- { .start = 0x00a02600, .end = 0x00a0260c },
- { .start = 0x00a02648, .end = 0x00a02650 },
- { .start = 0x00a02680, .end = 0x00a02680 },
- { .start = 0x00a026c0, .end = 0x00a026d0 },
- { .start = 0x00a02700, .end = 0x00a0270c },
- { .start = 0x00a02804, .end = 0x00a02804 },
- { .start = 0x00a02818, .end = 0x00a0281c },
- { .start = 0x00a02c00, .end = 0x00a02db4 },
- { .start = 0x00a02df4, .end = 0x00a02fb0 },
- { .start = 0x00a03000, .end = 0x00a03014 },
- { .start = 0x00a0301c, .end = 0x00a0302c },
- { .start = 0x00a03034, .end = 0x00a03038 },
- { .start = 0x00a03040, .end = 0x00a03048 },
- { .start = 0x00a03060, .end = 0x00a03068 },
- { .start = 0x00a03070, .end = 0x00a03074 },
- { .start = 0x00a0307c, .end = 0x00a0307c },
- { .start = 0x00a03080, .end = 0x00a03084 },
- { .start = 0x00a0308c, .end = 0x00a03090 },
- { .start = 0x00a03098, .end = 0x00a03098 },
- { .start = 0x00a030a0, .end = 0x00a030a0 },
- { .start = 0x00a030a8, .end = 0x00a030b4 },
- { .start = 0x00a030bc, .end = 0x00a030bc },
- { .start = 0x00a030c0, .end = 0x00a0312c },
- { .start = 0x00a03c00, .end = 0x00a03c5c },
- { .start = 0x00a04400, .end = 0x00a04454 },
- { .start = 0x00a04460, .end = 0x00a04474 },
- { .start = 0x00a044c0, .end = 0x00a044ec },
- { .start = 0x00a04500, .end = 0x00a04504 },
- { .start = 0x00a04510, .end = 0x00a04538 },
- { .start = 0x00a04540, .end = 0x00a04548 },
- { .start = 0x00a04560, .end = 0x00a0457c },
- { .start = 0x00a04590, .end = 0x00a04598 },
- { .start = 0x00a045c0, .end = 0x00a045f4 },
-};
-
-static const struct iwl_prph_range iwl_prph_dump_addr_9000[] = {
- { .start = 0x00a05c00, .end = 0x00a05c18 },
- { .start = 0x00a05400, .end = 0x00a056e8 },
- { .start = 0x00a08000, .end = 0x00a098bc },
- { .start = 0x00a02400, .end = 0x00a02758 },
- { .start = 0x00a04764, .end = 0x00a0476c },
- { .start = 0x00a04770, .end = 0x00a04774 },
- { .start = 0x00a04620, .end = 0x00a04624 },
-};
-
-static const struct iwl_prph_range iwl_prph_dump_addr_22000[] = {
- { .start = 0x00a00000, .end = 0x00a00000 },
- { .start = 0x00a0000c, .end = 0x00a00024 },
- { .start = 0x00a0002c, .end = 0x00a00034 },
- { .start = 0x00a0003c, .end = 0x00a0003c },
- { .start = 0x00a00410, .end = 0x00a00418 },
- { .start = 0x00a00420, .end = 0x00a00420 },
- { .start = 0x00a00428, .end = 0x00a00428 },
- { .start = 0x00a00430, .end = 0x00a0043c },
- { .start = 0x00a00444, .end = 0x00a00444 },
- { .start = 0x00a00840, .end = 0x00a00840 },
- { .start = 0x00a00850, .end = 0x00a00858 },
- { .start = 0x00a01004, .end = 0x00a01008 },
- { .start = 0x00a01010, .end = 0x00a01010 },
- { .start = 0x00a01018, .end = 0x00a01018 },
- { .start = 0x00a01024, .end = 0x00a01024 },
- { .start = 0x00a0102c, .end = 0x00a01034 },
- { .start = 0x00a0103c, .end = 0x00a01040 },
- { .start = 0x00a01048, .end = 0x00a01050 },
- { .start = 0x00a01058, .end = 0x00a01058 },
- { .start = 0x00a01060, .end = 0x00a01070 },
- { .start = 0x00a0108c, .end = 0x00a0108c },
- { .start = 0x00a01c20, .end = 0x00a01c28 },
- { .start = 0x00a01d10, .end = 0x00a01d10 },
- { .start = 0x00a01e28, .end = 0x00a01e2c },
- { .start = 0x00a01e60, .end = 0x00a01e60 },
- { .start = 0x00a01e80, .end = 0x00a01e80 },
- { .start = 0x00a01ea0, .end = 0x00a01ea0 },
- { .start = 0x00a02000, .end = 0x00a0201c },
- { .start = 0x00a02024, .end = 0x00a02024 },
- { .start = 0x00a02040, .end = 0x00a02048 },
- { .start = 0x00a020c0, .end = 0x00a020e0 },
- { .start = 0x00a02400, .end = 0x00a02404 },
- { .start = 0x00a0240c, .end = 0x00a02414 },
- { .start = 0x00a0241c, .end = 0x00a0243c },
- { .start = 0x00a02448, .end = 0x00a024bc },
- { .start = 0x00a024c4, .end = 0x00a024cc },
- { .start = 0x00a02508, .end = 0x00a02508 },
- { .start = 0x00a02510, .end = 0x00a02514 },
- { .start = 0x00a0251c, .end = 0x00a0251c },
- { .start = 0x00a0252c, .end = 0x00a0255c },
- { .start = 0x00a02564, .end = 0x00a025a0 },
- { .start = 0x00a025a8, .end = 0x00a025b4 },
- { .start = 0x00a025c0, .end = 0x00a025c0 },
- { .start = 0x00a025e8, .end = 0x00a025f4 },
- { .start = 0x00a02c08, .end = 0x00a02c18 },
- { .start = 0x00a02c2c, .end = 0x00a02c38 },
- { .start = 0x00a02c68, .end = 0x00a02c78 },
- { .start = 0x00a03000, .end = 0x00a03000 },
- { .start = 0x00a03010, .end = 0x00a03014 },
- { .start = 0x00a0301c, .end = 0x00a0302c },
- { .start = 0x00a03034, .end = 0x00a03038 },
- { .start = 0x00a03040, .end = 0x00a03044 },
- { .start = 0x00a03060, .end = 0x00a03068 },
- { .start = 0x00a03070, .end = 0x00a03070 },
- { .start = 0x00a0307c, .end = 0x00a03084 },
- { .start = 0x00a0308c, .end = 0x00a03090 },
- { .start = 0x00a03098, .end = 0x00a03098 },
- { .start = 0x00a030a0, .end = 0x00a030a0 },
- { .start = 0x00a030a8, .end = 0x00a030b4 },
- { .start = 0x00a030bc, .end = 0x00a030c0 },
- { .start = 0x00a030c8, .end = 0x00a030f4 },
- { .start = 0x00a03100, .end = 0x00a0312c },
- { .start = 0x00a03c00, .end = 0x00a03c5c },
- { .start = 0x00a04400, .end = 0x00a04454 },
- { .start = 0x00a04460, .end = 0x00a04474 },
- { .start = 0x00a044c0, .end = 0x00a044ec },
- { .start = 0x00a04500, .end = 0x00a04504 },
- { .start = 0x00a04510, .end = 0x00a04538 },
- { .start = 0x00a04540, .end = 0x00a04548 },
- { .start = 0x00a04560, .end = 0x00a04560 },
- { .start = 0x00a04570, .end = 0x00a0457c },
- { .start = 0x00a04590, .end = 0x00a04590 },
- { .start = 0x00a04598, .end = 0x00a04598 },
- { .start = 0x00a045c0, .end = 0x00a045f4 },
- { .start = 0x00a05c18, .end = 0x00a05c1c },
- { .start = 0x00a0c000, .end = 0x00a0c018 },
- { .start = 0x00a0c020, .end = 0x00a0c028 },
- { .start = 0x00a0c038, .end = 0x00a0c094 },
- { .start = 0x00a0c0c0, .end = 0x00a0c104 },
- { .start = 0x00a0c10c, .end = 0x00a0c118 },
- { .start = 0x00a0c150, .end = 0x00a0c174 },
- { .start = 0x00a0c17c, .end = 0x00a0c188 },
- { .start = 0x00a0c190, .end = 0x00a0c198 },
- { .start = 0x00a0c1a0, .end = 0x00a0c1a8 },
- { .start = 0x00a0c1b0, .end = 0x00a0c1b8 },
-};
-
-static const struct iwl_prph_range iwl_prph_dump_addr_ax210[] = {
- { .start = 0x00d03c00, .end = 0x00d03c64 },
- { .start = 0x00d05c18, .end = 0x00d05c1c },
- { .start = 0x00d0c000, .end = 0x00d0c174 },
-};
-
-static void iwl_read_prph_block(struct iwl_trans *trans, u32 start,
- u32 len_bytes, __le32 *data)
-{
- u32 i;
-
- for (i = 0; i < len_bytes; i += 4)
- *data++ = cpu_to_le32(iwl_trans_read_prph(trans, start + i));
-}
-
-static void iwl_dump_prph(struct iwl_fw_runtime *fwrt,
- const struct iwl_prph_range *iwl_prph_dump_addr,
- u32 range_len, void *ptr)
-{
- struct iwl_fw_error_dump_prph *prph;
- struct iwl_trans *trans = fwrt->trans;
- struct iwl_fw_error_dump_data **data =
- (struct iwl_fw_error_dump_data **)ptr;
- u32 i;
-
- if (!data)
- return;
-
- IWL_DEBUG_INFO(trans, "WRT PRPH dump\n");
-
- if (!iwl_trans_grab_nic_access(trans))
- return;
-
- for (i = 0; i < range_len; i++) {
- /* The range includes both boundaries */
- int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
- iwl_prph_dump_addr[i].start + 4;
-
- (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
- (*data)->len = cpu_to_le32(sizeof(*prph) +
- num_bytes_in_chunk);
- prph = (void *)(*data)->data;
- prph->prph_start = cpu_to_le32(iwl_prph_dump_addr[i].start);
-
- iwl_read_prph_block(trans, iwl_prph_dump_addr[i].start,
- /* our range is inclusive, hence + 4 */
- iwl_prph_dump_addr[i].end -
- iwl_prph_dump_addr[i].start + 4,
- (void *)prph->data);
-
- *data = iwl_fw_error_next_data(*data);
- }
-
- iwl_trans_release_nic_access(trans);
-}
/*
- * alloc_sgtable - allocates (chained) scatterlist in the given size,
+ * iwl_fw_dbg_alloc_sgtable - allocates (chained) scatterlist in the given size,
* fills it with pages and returns it
* @size: the size (in bytes) of the table
*/
-static struct scatterlist *alloc_sgtable(ssize_t size)
+struct scatterlist *iwl_fw_dbg_alloc_sgtable(ssize_t size)
{
struct scatterlist *result = NULL, *prev;
int nents, i, n_prev;
@@ -625,423 +82,6 @@ static struct scatterlist *alloc_sgtable(ssize_t size)
return result;
}
-static void iwl_fw_get_prph_len(struct iwl_fw_runtime *fwrt,
- const struct iwl_prph_range *iwl_prph_dump_addr,
- u32 range_len, void *ptr)
-{
- u32 *prph_len = (u32 *)ptr;
- int i, num_bytes_in_chunk;
-
- if (!prph_len)
- return;
-
- for (i = 0; i < range_len; i++) {
- /* The range includes both boundaries */
- num_bytes_in_chunk =
- iwl_prph_dump_addr[i].end -
- iwl_prph_dump_addr[i].start + 4;
-
- *prph_len += sizeof(struct iwl_fw_error_dump_data) +
- sizeof(struct iwl_fw_error_dump_prph) +
- num_bytes_in_chunk;
- }
-}
-
-static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr,
- void (*handler)(struct iwl_fw_runtime *,
- const struct iwl_prph_range *,
- u32, void *))
-{
- u32 range_len;
-
- if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
- range_len = ARRAY_SIZE(iwl_prph_dump_addr_ax210);
- handler(fwrt, iwl_prph_dump_addr_ax210, range_len, ptr);
- } else if (fwrt->trans->mac_cfg->device_family >=
- IWL_DEVICE_FAMILY_22000) {
- range_len = ARRAY_SIZE(iwl_prph_dump_addr_22000);
- handler(fwrt, iwl_prph_dump_addr_22000, range_len, ptr);
- } else {
- range_len = ARRAY_SIZE(iwl_prph_dump_addr_comm);
- handler(fwrt, iwl_prph_dump_addr_comm, range_len, ptr);
-
- if (fwrt->trans->mac_cfg->mq_rx_supported) {
- range_len = ARRAY_SIZE(iwl_prph_dump_addr_9000);
- handler(fwrt, iwl_prph_dump_addr_9000, range_len, ptr);
- }
- }
-}
-
-static void iwl_fw_dump_mem(struct iwl_fw_runtime *fwrt,
- struct iwl_fw_error_dump_data **dump_data,
- u32 len, u32 ofs, u32 type)
-{
- struct iwl_fw_error_dump_mem *dump_mem;
-
- if (!len)
- return;
-
- (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
- (*dump_data)->len = cpu_to_le32(len + sizeof(*dump_mem));
- dump_mem = (void *)(*dump_data)->data;
- dump_mem->type = cpu_to_le32(type);
- dump_mem->offset = cpu_to_le32(ofs);
- iwl_trans_read_mem_bytes(fwrt->trans, ofs, dump_mem->data, len);
- *dump_data = iwl_fw_error_next_data(*dump_data);
-
- if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
- fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, ofs,
- dump_mem->data, len);
-
- IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type);
-}
-
-#define ADD_LEN(len, item_len, const_len) \
- do {size_t item = item_len; len += (!!item) * const_len + item; } \
- while (0)
-
-static int iwl_fw_rxf_len(struct iwl_fw_runtime *fwrt,
- struct iwl_fwrt_shared_mem_cfg *mem_cfg)
-{
- size_t hdr_len = sizeof(struct iwl_fw_error_dump_data) +
- sizeof(struct iwl_fw_error_dump_fifo);
- u32 fifo_len = 0;
- int i;
-
- if (!iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_RXF))
- return 0;
-
- /* Count RXF2 size */
- ADD_LEN(fifo_len, mem_cfg->rxfifo2_size, hdr_len);
-
- /* Count RXF1 sizes */
- if (WARN_ON(mem_cfg->num_lmacs > MAX_NUM_LMAC))
- mem_cfg->num_lmacs = MAX_NUM_LMAC;
-
- for (i = 0; i < mem_cfg->num_lmacs; i++)
- ADD_LEN(fifo_len, mem_cfg->lmac[i].rxfifo1_size, hdr_len);
-
- return fifo_len;
-}
-
-static int iwl_fw_txf_len(struct iwl_fw_runtime *fwrt,
- struct iwl_fwrt_shared_mem_cfg *mem_cfg)
-{
- size_t hdr_len = sizeof(struct iwl_fw_error_dump_data) +
- sizeof(struct iwl_fw_error_dump_fifo);
- u32 fifo_len = 0;
- int i;
-
- if (!iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_TXF))
- goto dump_internal_txf;
-
- /* Count TXF sizes */
- if (WARN_ON(mem_cfg->num_lmacs > MAX_NUM_LMAC))
- mem_cfg->num_lmacs = MAX_NUM_LMAC;
-
- for (i = 0; i < mem_cfg->num_lmacs; i++) {
- int j;
-
- for (j = 0; j < mem_cfg->num_txfifo_entries; j++)
- ADD_LEN(fifo_len, mem_cfg->lmac[i].txfifo_size[j],
- hdr_len);
- }
-
-dump_internal_txf:
- if (!(iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_INTERNAL_TXF) &&
- fw_has_capa(&fwrt->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)))
- goto out;
-
- for (i = 0; i < ARRAY_SIZE(mem_cfg->internal_txfifo_size); i++)
- ADD_LEN(fifo_len, mem_cfg->internal_txfifo_size[i], hdr_len);
-
-out:
- return fifo_len;
-}
-
-static void iwl_dump_paging(struct iwl_fw_runtime *fwrt,
- struct iwl_fw_error_dump_data **data)
-{
- int i;
-
- IWL_DEBUG_INFO(fwrt, "WRT paging dump\n");
- for (i = 1; i < fwrt->num_of_paging_blk + 1; i++) {
- struct iwl_fw_error_dump_paging *paging;
- struct page *pages =
- fwrt->fw_paging_db[i].fw_paging_block;
- dma_addr_t addr = fwrt->fw_paging_db[i].fw_paging_phys;
-
- (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING);
- (*data)->len = cpu_to_le32(sizeof(*paging) +
- PAGING_BLOCK_SIZE);
- paging = (void *)(*data)->data;
- paging->index = cpu_to_le32(i);
- dma_sync_single_for_cpu(fwrt->trans->dev, addr,
- PAGING_BLOCK_SIZE,
- DMA_BIDIRECTIONAL);
- memcpy(paging->data, page_address(pages),
- PAGING_BLOCK_SIZE);
- dma_sync_single_for_device(fwrt->trans->dev, addr,
- PAGING_BLOCK_SIZE,
- DMA_BIDIRECTIONAL);
- (*data) = iwl_fw_error_next_data(*data);
-
- if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
- fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx,
- fwrt->fw_paging_db[i].fw_offs,
- paging->data,
- PAGING_BLOCK_SIZE);
- }
-}
-
-static struct iwl_fw_error_dump_file *
-iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
- struct iwl_fw_dump_ptrs *fw_error_dump,
- struct iwl_fwrt_dump_data *data)
-{
- struct iwl_fw_error_dump_file *dump_file;
- struct iwl_fw_error_dump_data *dump_data;
- struct iwl_fw_error_dump_info *dump_info;
- struct iwl_fw_error_dump_smem_cfg *dump_smem_cfg;
- struct iwl_fw_error_dump_trigger_desc *dump_trig;
- u32 sram_len, sram_ofs;
- const struct iwl_fw_dbg_mem_seg_tlv *fw_mem = fwrt->fw->dbg.mem_tlv;
- struct iwl_fwrt_shared_mem_cfg *mem_cfg = &fwrt->smem_cfg;
- u32 file_len, fifo_len = 0, prph_len = 0, radio_len = 0;
- u32 smem_len = fwrt->fw->dbg.n_mem_tlv ? 0 : fwrt->trans->mac_cfg->base->smem_len;
- u32 sram2_len = fwrt->fw->dbg.n_mem_tlv ?
- 0 : fwrt->trans->cfg->dccm2_len;
- int i;
-
- /* SRAM - include stack CCM if driver knows the values for it */
- if (!fwrt->trans->cfg->dccm_offset ||
- !fwrt->trans->cfg->dccm_len) {
- const struct fw_img *img;
-
- if (fwrt->cur_fw_img >= IWL_UCODE_TYPE_MAX)
- return NULL;
- img = &fwrt->fw->img[fwrt->cur_fw_img];
- sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
- sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
- } else {
- sram_ofs = fwrt->trans->cfg->dccm_offset;
- sram_len = fwrt->trans->cfg->dccm_len;
- }
-
- /* reading RXF/TXF sizes */
- if (iwl_trans_is_fw_error(fwrt->trans)) {
- fifo_len = iwl_fw_rxf_len(fwrt, mem_cfg);
- fifo_len += iwl_fw_txf_len(fwrt, mem_cfg);
-
- /* Make room for PRPH registers */
- if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_PRPH))
- iwl_fw_prph_handler(fwrt, &prph_len,
- iwl_fw_get_prph_len);
-
- if (fwrt->trans->mac_cfg->device_family ==
- IWL_DEVICE_FAMILY_7000 &&
- iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_RADIO_REG))
- radio_len = sizeof(*dump_data) + RADIO_REG_MAX_READ;
- }
-
- file_len = sizeof(*dump_file) + fifo_len + prph_len + radio_len;
-
- if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_DEV_FW_INFO))
- file_len += sizeof(*dump_data) + sizeof(*dump_info);
- if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM_CFG))
- file_len += sizeof(*dump_data) + sizeof(*dump_smem_cfg);
-
- if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM)) {
- size_t hdr_len = sizeof(*dump_data) +
- sizeof(struct iwl_fw_error_dump_mem);
-
- /* Dump SRAM only if no mem_tlvs */
- if (!fwrt->fw->dbg.n_mem_tlv)
- ADD_LEN(file_len, sram_len, hdr_len);
-
- /* Make room for all mem types that exist */
- ADD_LEN(file_len, smem_len, hdr_len);
- ADD_LEN(file_len, sram2_len, hdr_len);
-
- for (i = 0; i < fwrt->fw->dbg.n_mem_tlv; i++)
- ADD_LEN(file_len, le32_to_cpu(fw_mem[i].len), hdr_len);
- }
-
- /* Make room for fw's virtual image pages, if it exists */
- if (iwl_fw_dbg_is_paging_enabled(fwrt))
- file_len += fwrt->num_of_paging_blk *
- (sizeof(*dump_data) +
- sizeof(struct iwl_fw_error_dump_paging) +
- PAGING_BLOCK_SIZE);
-
- if (iwl_fw_dbg_is_d3_debug_enabled(fwrt) && fwrt->dump.d3_debug_data) {
- file_len += sizeof(*dump_data) +
- fwrt->trans->mac_cfg->base->d3_debug_data_length * 2;
- }
-
- /* If we only want a monitor dump, reset the file length */
- if (data->monitor_only) {
- file_len = sizeof(*dump_file) + sizeof(*dump_data) * 2 +
- sizeof(*dump_info) + sizeof(*dump_smem_cfg);
- }
-
- if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_ERROR_INFO) &&
- data->desc)
- file_len += sizeof(*dump_data) + sizeof(*dump_trig) +
- data->desc->len;
-
- dump_file = vzalloc(file_len);
- if (!dump_file)
- return NULL;
-
- fw_error_dump->fwrt_ptr = dump_file;
-
- dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
- dump_data = (void *)dump_file->data;
-
- if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_DEV_FW_INFO)) {
- dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
- dump_data->len = cpu_to_le32(sizeof(*dump_info));
- dump_info = (void *)dump_data->data;
- dump_info->hw_type =
- cpu_to_le32(CSR_HW_REV_TYPE(fwrt->trans->info.hw_rev));
- dump_info->hw_step =
- cpu_to_le32(fwrt->trans->info.hw_rev_step);
- memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable,
- sizeof(dump_info->fw_human_readable));
- strscpy_pad(dump_info->dev_human_readable,
- fwrt->trans->info.name,
- sizeof(dump_info->dev_human_readable));
- strscpy_pad(dump_info->bus_human_readable, fwrt->dev->bus->name,
- sizeof(dump_info->bus_human_readable));
- dump_info->num_of_lmacs = fwrt->smem_cfg.num_lmacs;
- dump_info->lmac_err_id[0] =
- cpu_to_le32(fwrt->dump.lmac_err_id[0]);
- if (fwrt->smem_cfg.num_lmacs > 1)
- dump_info->lmac_err_id[1] =
- cpu_to_le32(fwrt->dump.lmac_err_id[1]);
- dump_info->umac_err_id = cpu_to_le32(fwrt->dump.umac_err_id);
-
- dump_data = iwl_fw_error_next_data(dump_data);
- }
-
- if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM_CFG)) {
- /* Dump shared memory configuration */
- dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_CFG);
- dump_data->len = cpu_to_le32(sizeof(*dump_smem_cfg));
- dump_smem_cfg = (void *)dump_data->data;
- dump_smem_cfg->num_lmacs = cpu_to_le32(mem_cfg->num_lmacs);
- dump_smem_cfg->num_txfifo_entries =
- cpu_to_le32(mem_cfg->num_txfifo_entries);
- for (i = 0; i < MAX_NUM_LMAC; i++) {
- int j;
- u32 *txf_size = mem_cfg->lmac[i].txfifo_size;
-
- for (j = 0; j < TX_FIFO_MAX_NUM; j++)
- dump_smem_cfg->lmac[i].txfifo_size[j] =
- cpu_to_le32(txf_size[j]);
- dump_smem_cfg->lmac[i].rxfifo1_size =
- cpu_to_le32(mem_cfg->lmac[i].rxfifo1_size);
- }
- dump_smem_cfg->rxfifo2_size =
- cpu_to_le32(mem_cfg->rxfifo2_size);
- dump_smem_cfg->internal_txfifo_addr =
- cpu_to_le32(mem_cfg->internal_txfifo_addr);
- for (i = 0; i < TX_FIFO_INTERNAL_MAX_NUM; i++) {
- dump_smem_cfg->internal_txfifo_size[i] =
- cpu_to_le32(mem_cfg->internal_txfifo_size[i]);
- }
-
- dump_data = iwl_fw_error_next_data(dump_data);
- }
-
- /* We only dump the FIFOs if the FW is in error state */
- if (fifo_len) {
- iwl_fw_dump_rxf(fwrt, &dump_data);
- iwl_fw_dump_txf(fwrt, &dump_data);
- }
-
- if (radio_len)
- iwl_read_radio_regs(fwrt, &dump_data);
-
- if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_ERROR_INFO) &&
- data->desc) {
- dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_ERROR_INFO);
- dump_data->len = cpu_to_le32(sizeof(*dump_trig) +
- data->desc->len);
- dump_trig = (void *)dump_data->data;
- memcpy(dump_trig, &data->desc->trig_desc,
- sizeof(*dump_trig) + data->desc->len);
-
- dump_data = iwl_fw_error_next_data(dump_data);
- }
-
- /* In case we only want monitor dump, skip to dump trasport data */
- if (data->monitor_only)
- goto out;
-
- if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM)) {
- const struct iwl_fw_dbg_mem_seg_tlv *fw_dbg_mem =
- fwrt->fw->dbg.mem_tlv;
-
- if (!fwrt->fw->dbg.n_mem_tlv)
- iwl_fw_dump_mem(fwrt, &dump_data, sram_len, sram_ofs,
- IWL_FW_ERROR_DUMP_MEM_SRAM);
-
- for (i = 0; i < fwrt->fw->dbg.n_mem_tlv; i++) {
- u32 len = le32_to_cpu(fw_dbg_mem[i].len);
- u32 ofs = le32_to_cpu(fw_dbg_mem[i].ofs);
-
- iwl_fw_dump_mem(fwrt, &dump_data, len, ofs,
- le32_to_cpu(fw_dbg_mem[i].data_type));
- }
-
- iwl_fw_dump_mem(fwrt, &dump_data, smem_len,
- fwrt->trans->mac_cfg->base->smem_offset,
- IWL_FW_ERROR_DUMP_MEM_SMEM);
-
- iwl_fw_dump_mem(fwrt, &dump_data, sram2_len,
- fwrt->trans->cfg->dccm2_offset,
- IWL_FW_ERROR_DUMP_MEM_SRAM);
- }
-
- if (iwl_fw_dbg_is_d3_debug_enabled(fwrt) && fwrt->dump.d3_debug_data) {
- u32 addr = fwrt->trans->mac_cfg->base->d3_debug_data_base_addr;
- size_t data_size = fwrt->trans->mac_cfg->base->d3_debug_data_length;
-
- dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_D3_DEBUG_DATA);
- dump_data->len = cpu_to_le32(data_size * 2);
-
- memcpy(dump_data->data, fwrt->dump.d3_debug_data, data_size);
-
- kfree(fwrt->dump.d3_debug_data);
- fwrt->dump.d3_debug_data = NULL;
-
- iwl_trans_read_mem_bytes(fwrt->trans, addr,
- dump_data->data + data_size,
- data_size);
-
- if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
- fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, addr,
- dump_data->data + data_size,
- data_size);
-
- dump_data = iwl_fw_error_next_data(dump_data);
- }
-
- /* Dump fw's virtual image */
- if (iwl_fw_dbg_is_paging_enabled(fwrt))
- iwl_dump_paging(fwrt, &dump_data);
-
- if (prph_len)
- iwl_fw_prph_handler(fwrt, &dump_data, iwl_dump_prph);
-
-out:
- dump_file->file_len = cpu_to_le32(file_len);
- return dump_file;
-}
-
/**
* struct iwl_dump_ini_region_data - region data
* @reg_tlv: region TLV
@@ -2826,52 +1866,6 @@ static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt,
fwrt->dump.umac_err_id = 0;
}
-static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
- struct iwl_fwrt_dump_data *dump_data)
-{
- struct iwl_fw_dump_ptrs fw_error_dump = {};
- struct iwl_fw_error_dump_file *dump_file;
- struct scatterlist *sg_dump_data;
- u32 file_len;
- u32 dump_mask = fwrt->fw->dbg.dump_mask;
-
- dump_file = iwl_fw_error_dump_file(fwrt, &fw_error_dump, dump_data);
- if (!dump_file)
- return;
-
- if (dump_data->monitor_only)
- dump_mask &= BIT(IWL_FW_ERROR_DUMP_FW_MONITOR);
-
- fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask,
- fwrt->sanitize_ops,
- fwrt->sanitize_ctx);
- file_len = le32_to_cpu(dump_file->file_len);
- fw_error_dump.fwrt_len = file_len;
-
- if (fw_error_dump.trans_ptr) {
- file_len += fw_error_dump.trans_ptr->len;
- dump_file->file_len = cpu_to_le32(file_len);
- }
-
- sg_dump_data = alloc_sgtable(file_len);
- if (sg_dump_data) {
- sg_pcopy_from_buffer(sg_dump_data,
- sg_nents(sg_dump_data),
- fw_error_dump.fwrt_ptr,
- fw_error_dump.fwrt_len, 0);
- if (fw_error_dump.trans_ptr)
- sg_pcopy_from_buffer(sg_dump_data,
- sg_nents(sg_dump_data),
- fw_error_dump.trans_ptr->data,
- fw_error_dump.trans_ptr->len,
- fw_error_dump.fwrt_len);
- dev_coredumpsg(fwrt->trans->dev, sg_dump_data, file_len,
- GFP_KERNEL);
- }
- vfree(fw_error_dump.fwrt_ptr);
- vfree(fw_error_dump.trans_ptr);
-}
-
static void iwl_dump_ini_list_free(struct list_head *list)
{
while (!list_empty(list)) {
@@ -2900,7 +1894,7 @@ static void iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt,
if (!file_len)
return;
- sg_dump_data = alloc_sgtable(file_len);
+ sg_dump_data = iwl_fw_dbg_alloc_sgtable(file_len);
if (sg_dump_data) {
struct iwl_fw_ini_dump_entry *entry;
int sg_entries = sg_nents(sg_dump_data);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
index 8034c9ecba69..fc962a320583 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2018-2019, 2021-2025 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2019, 2021-2026 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -38,6 +38,11 @@ struct iwl_fw_dbg_params {
u32 out_ctrl;
};
+/* old-style dump entry point */
+void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
+ struct iwl_fwrt_dump_data *dump_data);
+struct scatterlist *iwl_fw_dbg_alloc_sgtable(ssize_t size);
+
extern const struct iwl_fw_dump_desc iwl_dump_desc_assert;
int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
--
2.34.1
^ permalink raw reply related
* [PATCH v3 iwlwifi-next 12/15] wifi: iwlwifi: fw: dbg: always use non-tracing PRPH access
From: Miri Korenblit @ 2026-05-19 6:40 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260519064010.549003-1-miriam.rachel.korenblit@intel.com>
From: Johannes Berg <johannes.berg@intel.com>
The iwl_{read,write}_prph_no_grab() functions will trace each
access, but in debug dump a lot of accesses already use the
transport versions of these functions directly. Since the data
(register addresses and their content) is going into the dump
file, tracing isn't really needed. Use the transport functions
in all places.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20260517100550.bbc7623a0348.I827729916da8f264befbcb90ac6509c359ee97a3@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 63 +++++++++++----------
1 file changed, 32 insertions(+), 31 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 886c8e6ef48e..18667de4915f 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -46,8 +46,8 @@ static void iwl_read_radio_regs(struct iwl_fw_runtime *fwrt,
u32 rd_cmd = RADIO_RSP_RD_CMD;
rd_cmd |= i << RADIO_RSP_ADDR_POS;
- iwl_write_prph_no_grab(fwrt->trans, RSP_RADIO_CMD, rd_cmd);
- *pos = (u8)iwl_read_prph_no_grab(fwrt->trans, RSP_RADIO_RDDAT);
+ iwl_trans_write_prph(fwrt->trans, RSP_RADIO_CMD, rd_cmd);
+ *pos = (u8)iwl_trans_read_prph(fwrt->trans, RSP_RADIO_RDDAT);
pos++;
}
@@ -513,7 +513,7 @@ static void iwl_read_prph_block(struct iwl_trans *trans, u32 start,
u32 i;
for (i = 0; i < len_bytes; i += 4)
- *data++ = cpu_to_le32(iwl_read_prph_no_grab(trans, start + i));
+ *data++ = cpu_to_le32(iwl_trans_read_prph(trans, start + i));
}
static void iwl_dump_prph(struct iwl_fw_runtime *fwrt,
@@ -1132,16 +1132,16 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt,
continue;
}
- iwl_write_prph_no_grab(fwrt->trans, indirect_wr_addr,
- WMAL_INDRCT_CMD(addr + i));
+ iwl_trans_write_prph(fwrt->trans, indirect_wr_addr,
+ WMAL_INDRCT_CMD(addr + i));
if (fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_JF1 &&
fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_JF2 &&
fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_HR1 &&
fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_HR2) {
udelay(2);
- prph_stts = iwl_read_prph_no_grab(fwrt->trans,
- WMAL_MRSPF_STTS);
+ prph_stts = iwl_trans_read_prph(fwrt->trans,
+ WMAL_MRSPF_STTS);
/* Abort dump if status is 0xA5A5A5A2 or FIFO1 empty */
if (prph_stts == WMAL_TIMEOUT_VAL ||
@@ -1149,8 +1149,8 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt,
break;
}
- prph_val = iwl_read_prph_no_grab(fwrt->trans,
- indirect_rd_addr);
+ prph_val = iwl_trans_read_prph(fwrt->trans,
+ indirect_rd_addr);
*val++ = cpu_to_le32(prph_val);
}
@@ -1410,7 +1410,7 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
range->fifo_hdr.num_of_registers = cpu_to_le32(registers_num);
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);
+ iwl_trans_write_prph(fwrt->trans, TXF_LARC_NUM + offs, iter->fifo);
/*
* read txf registers. for each register, write to the dump the
@@ -1420,8 +1420,8 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
addr = le32_to_cpu(reg->addrs[i]) + offs;
reg_dump->addr = cpu_to_le32(addr);
- reg_dump->data = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans,
- addr));
+ reg_dump->data = cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+ addr));
reg_dump++;
}
@@ -1432,17 +1432,17 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
}
/* Set the TXF_READ_MODIFY_ADDR to TXF_WR_PTR */
- iwl_write_prph_no_grab(fwrt->trans, TXF_READ_MODIFY_ADDR + offs,
- TXF_WR_PTR + offs);
+ iwl_trans_write_prph(fwrt->trans, TXF_READ_MODIFY_ADDR + offs,
+ TXF_WR_PTR + offs);
/* Dummy-read to advance the read pointer to the head */
- iwl_read_prph_no_grab(fwrt->trans, TXF_READ_MODIFY_DATA + offs);
+ iwl_trans_read_prph(fwrt->trans, TXF_READ_MODIFY_DATA + offs);
/* Read FIFO */
addr = TXF_READ_MODIFY_DATA + offs;
data = (void *)reg_dump;
for (i = 0; i < iter->fifo_size; i += sizeof(*data))
- *data++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr));
+ *data++ = cpu_to_le32(iwl_trans_read_prph(fwrt->trans, addr));
if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf)
fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx,
@@ -1487,12 +1487,12 @@ iwl_dump_ini_prph_snps_dphyip_iter(struct iwl_fw_runtime *fwrt,
continue;
}
- iwl_write_prph_no_grab(fwrt->trans, indirect_rd_wr_addr,
- addr + i);
+ iwl_trans_write_prph(fwrt->trans, indirect_rd_wr_addr,
+ addr + i);
/* wait a bit for value to be ready in register */
udelay(1);
- prph_val = iwl_read_prph_no_grab(fwrt->trans,
- indirect_rd_wr_addr);
+ prph_val = iwl_trans_read_prph(fwrt->trans,
+ indirect_rd_wr_addr);
*val++ = cpu_to_le32((prph_val & DPHYIP_INDIRECT_RD_MSK) >>
DPHYIP_INDIRECT_RD_SHIFT);
}
@@ -1601,8 +1601,8 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
addr = le32_to_cpu(reg->addrs[i]) + offs;
reg_dump->addr = cpu_to_le32(addr);
- reg_dump->data = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans,
- addr));
+ reg_dump->data = cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+ addr));
reg_dump++;
}
@@ -1615,18 +1615,17 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
offs = rxf_data.offset;
/* Lock fence */
- iwl_write_prph_no_grab(fwrt->trans, RXF_SET_FENCE_MODE + offs, 0x1);
+ iwl_trans_write_prph(fwrt->trans, RXF_SET_FENCE_MODE + offs, 0x1);
/* Set fence pointer to the same place like WR pointer */
- iwl_write_prph_no_grab(fwrt->trans, RXF_LD_WR2FENCE + offs, 0x1);
+ iwl_trans_write_prph(fwrt->trans, RXF_LD_WR2FENCE + offs, 0x1);
/* Set fence offset */
- iwl_write_prph_no_grab(fwrt->trans, RXF_LD_FENCE_OFFSET_ADDR + offs,
- 0x0);
+ iwl_trans_write_prph(fwrt->trans, RXF_LD_FENCE_OFFSET_ADDR + offs, 0x0);
/* Read FIFO */
addr = RXF_FIFO_RD_FENCE_INC + offs;
data = (void *)reg_dump;
for (i = 0; i < rxf_data.size; i += sizeof(*data))
- *data++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr));
+ *data++ = cpu_to_le32(iwl_trans_read_prph(fwrt->trans, addr));
out:
iwl_trans_release_nic_access(fwrt->trans);
@@ -1690,9 +1689,11 @@ iwl_dump_ini_dbgi_sram_iter(struct iwl_fw_runtime *fwrt,
range->range_data_size = reg->dev_addr.size;
for (i = 0; i < (le32_to_cpu(reg->dev_addr.size) / 4); i++) {
- prph_data = iwl_read_prph_no_grab(fwrt->trans, (i % 2) ?
- DBGI_SRAM_TARGET_ACCESS_RDATA_MSB :
- DBGI_SRAM_TARGET_ACCESS_RDATA_LSB);
+ prph_data =
+ iwl_trans_read_prph(fwrt->trans,
+ (i % 2) ?
+ DBGI_SRAM_TARGET_ACCESS_RDATA_MSB :
+ DBGI_SRAM_TARGET_ACCESS_RDATA_LSB);
if (iwl_trans_is_hw_error_value(prph_data)) {
iwl_trans_release_nic_access(fwrt->trans);
return -EBUSY;
@@ -1791,7 +1792,7 @@ static __le32 iwl_get_mon_reg(struct iwl_fw_runtime *fwrt, u32 alloc_id,
if (!reg_info || !reg_info->addr || !reg_info->mask)
return 0;
- val = iwl_read_prph_no_grab(fwrt->trans, reg_info->addr + offs);
+ val = iwl_trans_read_prph(fwrt->trans, reg_info->addr + offs);
return cpu_to_le32(mask_apply_and_normalize(val, reg_info->mask));
}
--
2.34.1
^ permalink raw reply related
* [PATCH v3 iwlwifi-next 11/15] wifi: iwlwifi: fw: separate ini dump allocation
From: Miri Korenblit @ 2026-05-19 6:40 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260519064010.549003-1-miriam.rachel.korenblit@intel.com>
From: Johannes Berg <johannes.berg@intel.com>
Separate out the ini dump allocation to happen before the
actual dumping in preparation for better device MAC access.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20260517100550.01a65fd9e6de.If9b648a5565671801c15be898f2b89afdb878256@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 176 +++++++++++---------
1 file changed, 96 insertions(+), 80 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 4c41f042d6a0..886c8e6ef48e 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -2239,33 +2239,19 @@ struct iwl_dump_ini_mem_ops {
void *range, u32 range_len, int idx);
};
-/**
- * struct iwl_fw_ini_dump_entry - dump entry descriptor
- * @list: list of dump entries
- * @size: size of the data
- * @data: entry data
- */
struct iwl_fw_ini_dump_entry {
+ const struct iwl_dump_ini_mem_ops *ops;
+ struct iwl_dump_ini_region_data reg_data;
struct list_head list;
+ u32 region_dump_policy;
u32 size;
u8 data[];
} __packed;
-/**
- * iwl_dump_ini_mem - dump memory region
- *
- * @fwrt: fw runtime struct
- * @list: list to add the dump tlv to
- * @reg_data: memory region
- * @ops: memory dump operations
- *
- * Creates a dump tlv and copy a memory region into it.
- *
- * Returns: the size of the current dump tlv or 0 if failed
- */
-static u32 iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, struct list_head *list,
- struct iwl_dump_ini_region_data *reg_data,
- const struct iwl_dump_ini_mem_ops *ops)
+static void iwl_dump_ini_mem_prep(struct iwl_fw_runtime *fwrt,
+ struct list_head *list,
+ struct iwl_dump_ini_region_data *reg_data,
+ const struct iwl_dump_ini_mem_ops *ops)
{
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
struct iwl_fw_ini_dump_entry *entry;
@@ -2273,58 +2259,59 @@ static u32 iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, struct list_head *list,
struct iwl_fw_ini_error_dump_header *header;
u32 type = reg->type;
u32 id = le32_get_bits(reg->id, IWL_FW_INI_REGION_ID_MASK);
- u32 num_of_ranges, i, size;
- u8 *range;
- u32 free_size;
- u64 header_size;
+ u32 num_of_ranges, size;
u32 dump_policy = IWL_FW_INI_DUMP_VERBOSE;
+ u32 dp;
IWL_DEBUG_FW(fwrt, "WRT: Collecting region: dump type=%d, id=%d, type=%d\n",
dump_policy, id, type);
if (le32_to_cpu(reg->hdr.version) >= 2) {
- u32 dp = le32_get_bits(reg->id,
- IWL_FW_INI_REGION_DUMP_POLICY_MASK);
+ dp = le32_get_bits(reg->id, IWL_FW_INI_REGION_DUMP_POLICY_MASK);
if (dump_policy == IWL_FW_INI_DUMP_VERBOSE &&
!(dp & IWL_FW_INI_DEBUG_DUMP_POLICY_NO_LIMIT)) {
IWL_DEBUG_FW(fwrt,
"WRT: no dump - type %d and policy mismatch=%d\n",
dump_policy, dp);
- return 0;
+ return;
} else if (dump_policy == IWL_FW_INI_DUMP_MEDIUM &&
!(dp & IWL_FW_IWL_DEBUG_DUMP_POLICY_MAX_LIMIT_5MB)) {
IWL_DEBUG_FW(fwrt,
"WRT: no dump - type %d and policy mismatch=%d\n",
dump_policy, dp);
- return 0;
+ return;
} else if (dump_policy == IWL_FW_INI_DUMP_BRIEF &&
!(dp & IWL_FW_INI_DEBUG_DUMP_POLICY_MAX_LIMIT_600KB)) {
IWL_DEBUG_FW(fwrt,
"WRT: no dump - type %d and policy mismatch=%d\n",
dump_policy, dp);
- return 0;
+ return;
}
+ } else {
+ dp = 0;
}
if (!ops->get_num_of_ranges || !ops->get_size || !ops->fill_mem_hdr ||
!ops->fill_range) {
IWL_DEBUG_FW(fwrt, "WRT: no ops for collecting data\n");
- return 0;
+ return;
}
size = ops->get_size(fwrt, reg_data);
if (size < sizeof(*header)) {
IWL_DEBUG_FW(fwrt, "WRT: size didn't include space for header\n");
- return 0;
+ return;
}
entry = vzalloc(sizeof(*entry) + sizeof(*tlv) + size);
if (!entry)
- return 0;
+ return;
entry->size = sizeof(*tlv) + size;
+ entry->reg_data = *reg_data;
+ entry->region_dump_policy = dp;
tlv = (void *)entry->data;
tlv->type = reg->type;
@@ -2341,7 +2328,29 @@ static u32 iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, struct list_head *list,
header->name_len = cpu_to_le32(IWL_FW_INI_MAX_NAME);
memcpy(header->name, reg->name, IWL_FW_INI_MAX_NAME);
- free_size = size;
+ entry->ops = ops;
+ list_add_tail(&entry->list, list);
+}
+
+static u32 iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_ini_dump_entry *entry)
+{
+ struct iwl_dump_ini_region_data *reg_data = &entry->reg_data;
+ struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
+ const struct iwl_dump_ini_mem_ops *ops = entry->ops;
+ struct iwl_fw_ini_error_dump_data *tlv;
+ struct iwl_fw_ini_error_dump_header *header;
+ u32 type = reg->type;
+ u32 id = le32_get_bits(reg->id, IWL_FW_INI_REGION_ID_MASK);
+ u32 i;
+ u8 *range;
+ u32 free_size;
+ u64 header_size;
+
+ tlv = (void *)entry->data;
+ header = (void *)tlv->data;
+
+ free_size = entry->size - sizeof(*tlv);
range = ops->fill_mem_hdr(fwrt, reg_data, header, free_size);
if (!range) {
IWL_ERR(fwrt,
@@ -2362,7 +2371,7 @@ static u32 iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, struct list_head *list,
free_size -= header_size;
- for (i = 0; i < num_of_ranges; i++) {
+ for (i = 0; i < le32_to_cpu(header->num_of_ranges); i++) {
int range_size = ops->fill_range(fwrt, reg_data, range,
free_size, i);
@@ -2384,11 +2393,10 @@ static u32 iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, struct list_head *list,
range = range + range_size;
}
- list_add_tail(&entry->list, list);
-
return entry->size;
out_err:
+ list_del(&entry->list);
vfree(entry);
return 0;
@@ -2617,22 +2625,19 @@ static bool iwl_dump_due_to_error(enum iwl_fw_ini_time_point tp_id)
tp_id == IWL_FW_INI_TIME_POINT_FW_HW_ERROR;
}
-static u32
-iwl_dump_ini_dump_regions(struct iwl_fw_runtime *fwrt,
- struct iwl_fwrt_dump_data *dump_data,
- struct list_head *list,
- enum iwl_fw_ini_time_point tp_id,
- u64 regions_mask,
- struct iwl_dump_ini_region_data *imr_reg_data,
- enum iwl_dump_ini_region_selector which)
+static void
+iwl_dump_ini_dump_regions_prep(struct iwl_fw_runtime *fwrt,
+ struct iwl_fwrt_dump_data *dump_data,
+ struct list_head *list,
+ enum iwl_fw_ini_time_point tp_id,
+ u64 regions_mask,
+ struct iwl_ucode_tlv **imr_tlv)
{
- u32 size = 0;
-
for (int i = 0; i < ARRAY_SIZE(fwrt->trans->dbg.active_regions); i++) {
struct iwl_dump_ini_region_data reg_data = {
.dump_data = dump_data,
};
- u32 reg_type, dp;
+ u32 reg_type;
struct iwl_fw_ini_region_tlv *reg;
if (!(BIT_ULL(i) & regions_mask))
@@ -2650,8 +2655,6 @@ iwl_dump_ini_dump_regions(struct iwl_fw_runtime *fwrt,
if (reg_type >= ARRAY_SIZE(iwl_dump_ini_region_ops))
continue;
- dp = le32_get_bits(reg->id, IWL_FW_INI_REGION_DUMP_POLICY_MASK);
-
if ((reg_type == IWL_FW_INI_REGION_PERIPHERY_PHY ||
reg_type == IWL_FW_INI_REGION_PERIPHERY_PHY_RANGE ||
reg_type == IWL_FW_INI_REGION_PERIPHERY_SNPS_DPHYIP) &&
@@ -2662,19 +2665,6 @@ iwl_dump_ini_dump_regions(struct iwl_fw_runtime *fwrt,
continue;
}
- switch (which) {
- case IWL_INI_DUMP_ALL_REGIONS:
- break;
- case IWL_INI_DUMP_EARLY_REGIONS:
- if (!(dp & IWL_FW_IWL_DEBUG_DUMP_POLICY_BEFORE_RESET))
- continue;
- break;
- case IWL_INI_DUMP_LATE_REGIONS:
- if (dp & IWL_FW_IWL_DEBUG_DUMP_POLICY_BEFORE_RESET)
- continue;
- break;
- }
-
/*
* DRAM_IMR can be collected only for FW/HW error timepoint
* when fw is not alive. In addition, it must be collected
@@ -2683,19 +2673,45 @@ iwl_dump_ini_dump_regions(struct iwl_fw_runtime *fwrt,
*/
if (reg_type == IWL_FW_INI_REGION_DRAM_IMR) {
if (iwl_dump_due_to_error(tp_id))
- imr_reg_data->reg_tlv =
- fwrt->trans->dbg.active_regions[i];
+ *imr_tlv = fwrt->trans->dbg.active_regions[i];
else
IWL_INFO(fwrt,
"WRT: trying to collect DRAM_IMR at time point: %d, skipping\n",
tp_id);
- /* continue to next region */
+ /* continue to next region */
continue;
}
+ iwl_dump_ini_mem_prep(fwrt, list, ®_data,
+ &iwl_dump_ini_region_ops[reg_type]);
+ }
+}
+
+static u32
+iwl_dump_ini_dump_entries(struct iwl_fw_runtime *fwrt,
+ struct list_head *list,
+ enum iwl_dump_ini_region_selector which)
+{
+ struct iwl_fw_ini_dump_entry *entry, *tmp;
+ u32 size = 0;
+
+ list_for_each_entry_safe(entry, tmp, list, list) {
+ u32 dp = entry->region_dump_policy;
- size += iwl_dump_ini_mem(fwrt, list, ®_data,
- &iwl_dump_ini_region_ops[reg_type]);
+ switch (which) {
+ case IWL_INI_DUMP_ALL_REGIONS:
+ break;
+ case IWL_INI_DUMP_EARLY_REGIONS:
+ if (!(dp & IWL_FW_IWL_DEBUG_DUMP_POLICY_BEFORE_RESET))
+ continue;
+ break;
+ case IWL_INI_DUMP_LATE_REGIONS:
+ if (dp & IWL_FW_IWL_DEBUG_DUMP_POLICY_BEFORE_RESET)
+ continue;
+ break;
+ }
+
+ size += iwl_dump_ini_mem(fwrt, entry);
}
return size;
@@ -2718,32 +2734,32 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
BUILD_BUG_ON((sizeof(trigger->regions_mask) * BITS_PER_BYTE) <
ARRAY_SIZE(fwrt->trans->dbg.active_regions));
+ iwl_dump_ini_dump_regions_prep(fwrt, dump_data, list, tp_id,
+ regions_mask, &imr_reg_data.reg_tlv);
+
+ /* append DRAM_IMR region to be collected last */
+ if (imr_reg_data.reg_tlv)
+ iwl_dump_ini_mem_prep(fwrt, list, &imr_reg_data,
+ &iwl_dump_ini_region_ops[IWL_FW_INI_REGION_DRAM_IMR]);
+
if (trigger->apply_policy &
cpu_to_le32(IWL_FW_INI_APPLY_POLICY_SPLIT_DUMP_RESET)) {
- size += iwl_dump_ini_dump_regions(fwrt, dump_data, list, tp_id,
- regions_mask, &imr_reg_data,
+ size += iwl_dump_ini_dump_entries(fwrt, list,
IWL_INI_DUMP_EARLY_REGIONS);
iwl_trans_pcie_fw_reset_handshake(fwrt->trans);
- size += iwl_dump_ini_dump_regions(fwrt, dump_data, list, tp_id,
- regions_mask, &imr_reg_data,
+ size += iwl_dump_ini_dump_entries(fwrt, list,
IWL_INI_DUMP_LATE_REGIONS);
} else {
if (fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_RESET_DURING_ASSERT) &&
iwl_dump_due_to_error(tp_id))
iwl_trans_pcie_fw_reset_handshake(fwrt->trans);
- size += iwl_dump_ini_dump_regions(fwrt, dump_data, list, tp_id,
- regions_mask, &imr_reg_data,
+ size += iwl_dump_ini_dump_entries(fwrt, list,
IWL_INI_DUMP_ALL_REGIONS);
}
- /* collect DRAM_IMR region in the last */
- if (imr_reg_data.reg_tlv)
- size += iwl_dump_ini_mem(fwrt, list, &imr_reg_data,
- &iwl_dump_ini_region_ops[IWL_FW_INI_REGION_DRAM_IMR]);
- if (size) {
+ if (size)
size += iwl_dump_ini_info(fwrt, trigger, list);
- }
return size;
}
--
2.34.1
^ permalink raw reply related
* [PATCH v3 iwlwifi-next 10/15] wifi: iwlwifi: fw: move struct iwl_fw_ini_dump_entry to dbg.c
From: Miri Korenblit @ 2026-05-19 6:40 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260519064010.549003-1-miriam.rachel.korenblit@intel.com>
From: Johannes Berg <johannes.berg@intel.com>
This is only used/needed in this file, so move it to clarify
that it's not part of any external API.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20260517100550.72b02319e812.I5cf95f64e3c3c688871bfabbe4fd7393b63a7dc8@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 14 +++++++++++++-
drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | 14 +-------------
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 0cffa5493704..4c41f042d6a0 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2005-2014, 2018-2025 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2026 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -2239,6 +2239,18 @@ struct iwl_dump_ini_mem_ops {
void *range, u32 range_len, int idx);
};
+/**
+ * struct iwl_fw_ini_dump_entry - dump entry descriptor
+ * @list: list of dump entries
+ * @size: size of the data
+ * @data: entry data
+ */
+struct iwl_fw_ini_dump_entry {
+ struct list_head list;
+ u32 size;
+ u8 data[];
+} __packed;
+
/**
* iwl_dump_ini_mem - dump memory region
*
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
index 525a82030daa..07f1240df866 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2014, 2018-2025 Intel Corporation
+ * Copyright (C) 2014, 2018-2026 Intel Corporation
* Copyright (C) 2014-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -265,18 +265,6 @@ struct iwl_fw_ini_error_dump_data {
__u8 data[];
} __packed;
-/**
- * struct iwl_fw_ini_dump_entry - dump entry descriptor
- * @list: list of dump entries
- * @size: size of the data
- * @data: entry data
- */
-struct iwl_fw_ini_dump_entry {
- struct list_head list;
- u32 size;
- u8 data[];
-} __packed;
-
/**
* struct iwl_fw_ini_dump_file_hdr - header of dump file
* @barker: must be %IWL_FW_INI_ERROR_DUMP_BARKER
--
2.34.1
^ permalink raw reply related
* [PATCH v3 iwlwifi-next 09/15] wifi: iwlwifi: clean up location format/BW encoding
From: Miri Korenblit @ 2026-05-19 6:40 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260519064010.549003-1-miriam.rachel.korenblit@intel.com>
From: Johannes Berg <johannes.berg@intel.com>
This is all fairly manual, with the shifts etc., and
the documentation has to call out the specific bits
(which also isn't usable for our tracing data). Add
an enum that directly declares the bit masks for it
and then use the more modern u8_encode_bits().
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20260517100550.bc09f4f6fd29.I315f15856eb36f0490b8f5008537d3e0ffc215f2@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
.../wireless/intel/iwlwifi/fw/api/location.h | 100 +++++++++---------
.../intel/iwlwifi/mld/ftm-initiator.c | 30 ++++--
.../intel/iwlwifi/mvm/ftm-initiator.c | 30 ++++--
.../intel/iwlwifi/mvm/ftm-responder.c | 32 ++++--
4 files changed, 111 insertions(+), 81 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
index d3f774ffacde..421ea94ace01 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
@@ -88,6 +88,46 @@ enum iwl_location_subcmd_ids {
TOF_RANGE_RESPONSE_NOTIF = 0xFF,
};
+/**
+ * enum iwl_location_frame_format - location frame formats
+ * @IWL_LOCATION_FRAME_FORMAT_LEGACY: legacy
+ * @IWL_LOCATION_FRAME_FORMAT_HT: HT
+ * @IWL_LOCATION_FRAME_FORMAT_VHT: VHT
+ * @IWL_LOCATION_FRAME_FORMAT_HE: HE
+ */
+enum iwl_location_frame_format {
+ IWL_LOCATION_FRAME_FORMAT_LEGACY,
+ IWL_LOCATION_FRAME_FORMAT_HT,
+ IWL_LOCATION_FRAME_FORMAT_VHT,
+ IWL_LOCATION_FRAME_FORMAT_HE,
+};
+
+/**
+ * enum iwl_location_bw - location bandwidth selection
+ * @IWL_LOCATION_BW_20MHZ: 20 MHz
+ * @IWL_LOCATION_BW_40MHZ: 40 MHz
+ * @IWL_LOCATION_BW_80MHZ: 80 MHz
+ * @IWL_LOCATION_BW_160MHZ: 160 MHz
+ * @IWL_LOCATION_BW_320MHZ: 320 MHz
+ */
+enum iwl_location_bw {
+ IWL_LOCATION_BW_20MHZ,
+ IWL_LOCATION_BW_40MHZ,
+ IWL_LOCATION_BW_80MHZ,
+ IWL_LOCATION_BW_160MHZ,
+ IWL_LOCATION_BW_320MHZ,
+};
+
+/**
+ * enum iwl_location_format_bw - format/BW encoding
+ * @IWL_LOCATION_FMT_BW_FORMAT: &enum iwl_location_frame_format
+ * @IWL_LOCATION_FMT_BW_BANDWIDTH: &enum iwl_location_bw
+ */
+enum iwl_location_format_bw {
+ IWL_LOCATION_FMT_BW_FORMAT = 0x0f,
+ IWL_LOCATION_FMT_BW_BANDWIDTH = 0xf0,
+};
+
/**
* struct iwl_tof_config_cmd - ToF configuration
* @tof_disabled: indicates if ToF is disabled (or not)
@@ -264,8 +304,7 @@ struct iwl_tof_responder_config_cmd_v6 {
* struct iwl_tof_responder_config_cmd_v7 - ToF AP mode (for debug)
* @cmd_valid_fields: &iwl_tof_responder_cmd_valid_field
* @responder_cfg_flags: &iwl_tof_responder_cfg_flags
- * @format_bw: bits 0 - 3: &enum iwl_location_frame_format.
- * bits 4 - 7: &enum iwl_location_bw.
+ * @format_bw: &enum iwl_location_format_bw
* @rate: current AP rate
* @channel_num: current AP Channel
* @ctrl_ch_position: coding of the control channel position relative to
@@ -303,8 +342,7 @@ struct iwl_tof_responder_config_cmd_v7 {
* struct iwl_tof_responder_config_cmd_v8 - ToF AP mode (for debug)
* @cmd_valid_fields: &iwl_tof_responder_cmd_valid_field
* @responder_cfg_flags: &iwl_tof_responder_cfg_flags
- * @format_bw: bits 0 - 3: &enum iwl_location_frame_format.
- * bits 4 - 7: &enum iwl_location_bw.
+ * @format_bw: &enum iwl_location_format_bw
* @rate: current AP rate
* @channel_num: current AP Channel
* @ctrl_ch_position: coding of the control channel position relative to
@@ -349,8 +387,7 @@ struct iwl_tof_responder_config_cmd_v8 {
* struct iwl_tof_responder_config_cmd_v9 - ToF AP mode (for debug)
* @cmd_valid_fields: &iwl_tof_responder_cmd_valid_field
* @responder_cfg_flags: &iwl_tof_responder_cfg_flags
- * @format_bw: bits 0 - 3: &enum iwl_location_frame_format.
- * bits 4 - 7: &enum iwl_location_bw.
+ * @format_bw: &enum iwl_location_format_bw
* @bss_color: current AP bss_color
* @channel_num: current AP Channel
* @ctrl_ch_position: coding of the control channel position relative to
@@ -401,8 +438,7 @@ struct iwl_tof_responder_config_cmd_v9 {
* struct iwl_tof_responder_config_cmd - ToF AP mode
* @cmd_valid_fields: &iwl_tof_responder_cmd_valid_field
* @responder_cfg_flags: &iwl_tof_responder_cfg_flags
- * @format_bw: bits 0 - 3: &enum iwl_location_frame_format.
- * bits 4 - 7: &enum iwl_location_bw.
+ * @format_bw: &enum iwl_location_format_bw
* @bss_color: current AP bss_color
* @channel_num: current AP Channel
* @ctrl_ch_position: coding of the control channel position relative to
@@ -677,44 +713,13 @@ struct iwl_tof_range_req_ap_entry_v3 {
__le32 tsf_delta;
} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_3 */
-/**
- * enum iwl_location_frame_format - location frame formats
- * @IWL_LOCATION_FRAME_FORMAT_LEGACY: legacy
- * @IWL_LOCATION_FRAME_FORMAT_HT: HT
- * @IWL_LOCATION_FRAME_FORMAT_VHT: VHT
- * @IWL_LOCATION_FRAME_FORMAT_HE: HE
- */
-enum iwl_location_frame_format {
- IWL_LOCATION_FRAME_FORMAT_LEGACY,
- IWL_LOCATION_FRAME_FORMAT_HT,
- IWL_LOCATION_FRAME_FORMAT_VHT,
- IWL_LOCATION_FRAME_FORMAT_HE,
-};
-
-/**
- * enum iwl_location_bw - location bandwidth selection
- * @IWL_LOCATION_BW_20MHZ: 20MHz
- * @IWL_LOCATION_BW_40MHZ: 40MHz
- * @IWL_LOCATION_BW_80MHZ: 80MHz
- * @IWL_LOCATION_BW_160MHZ: 160MHz
- */
-enum iwl_location_bw {
- IWL_LOCATION_BW_20MHZ,
- IWL_LOCATION_BW_40MHZ,
- IWL_LOCATION_BW_80MHZ,
- IWL_LOCATION_BW_160MHZ,
-};
-
#define TK_11AZ_LEN 32
-#define LOCATION_BW_POS 4
-
/**
* struct iwl_tof_range_req_ap_entry_v4 - AP configuration parameters
* @initiator_ap_flags: see &enum iwl_initiator_ap_flags.
* @channel_num: AP Channel number
- * @format_bw: bits 0 - 3: &enum iwl_location_frame_format.
- * bits 4 - 7: &enum iwl_location_bw.
+ * @format_bw: &enum iwl_location_format_bw
* @ctrl_ch_position: Coding of the control channel position relative to the
* center frequency, see iwl_mvm_get_ctrl_pos().
* @ftmr_max_retries: Max number of retries to send the FTMR in case of no
@@ -764,8 +769,7 @@ enum iwl_location_cipher {
* struct iwl_tof_range_req_ap_entry_v6 - AP configuration parameters
* @initiator_ap_flags: see &enum iwl_initiator_ap_flags.
* @channel_num: AP Channel number
- * @format_bw: bits 0 - 3: &enum iwl_location_frame_format.
- * bits 4 - 7: &enum iwl_location_bw.
+ * @format_bw: &enum iwl_location_format_bw
* @ctrl_ch_position: Coding of the control channel position relative to the
* center frequency, see iwl_mvm_get_ctrl_pos().
* @ftmr_max_retries: Max number of retries to send the FTMR in case of no
@@ -811,8 +815,7 @@ struct iwl_tof_range_req_ap_entry_v6 {
* struct iwl_tof_range_req_ap_entry_v7 - AP configuration parameters
* @initiator_ap_flags: see &enum iwl_initiator_ap_flags.
* @channel_num: AP Channel number
- * @format_bw: bits 0 - 3: &enum iwl_location_frame_format.
- * bits 4 - 7: &enum iwl_location_bw.
+ * @format_bw: &enum iwl_location_format_bw
* @ctrl_ch_position: Coding of the control channel position relative to the
* center frequency, see iwl_mvm_get_ctrl_pos().
* @ftmr_max_retries: Max number of retries to send the FTMR in case of no
@@ -869,8 +872,7 @@ struct iwl_tof_range_req_ap_entry_v7 {
* struct iwl_tof_range_req_ap_entry_v8 - AP configuration parameters
* @initiator_ap_flags: see &enum iwl_initiator_ap_flags.
* @channel_num: AP Channel number
- * @format_bw: bits 0 - 3: &enum iwl_location_frame_format.
- * bits 4 - 7: &enum iwl_location_bw.
+ * @format_bw: &enum iwl_location_format_bw
* @ctrl_ch_position: Coding of the control channel position relative to the
* center frequency, see iwl_mvm_get_ctrl_pos().
* @ftmr_max_retries: Max number of retries to send the FTMR in case of no
@@ -940,8 +942,7 @@ struct iwl_tof_range_req_ap_entry_v8 {
* struct iwl_tof_range_req_ap_entry_v9 - AP configuration parameters
* @initiator_ap_flags: see &enum iwl_initiator_ap_flags.
* @channel_num: AP Channel number
- * @format_bw: bits 0 - 3: &enum iwl_location_frame_format.
- * bits 4 - 7: &enum iwl_location_bw.
+ * @format_bw: &enum iwl_location_format_bw
* @ctrl_ch_position: Coding of the control channel position relative to the
* center frequency, see iwl_mvm_get_ctrl_pos().
* @ftmr_max_retries: Max number of retries to send the FTMR in case of no
@@ -1025,8 +1026,7 @@ struct iwl_tof_range_req_ap_entry_v9 {
* @initiator_ap_flags: see &enum iwl_initiator_ap_flags.
* @band: 0 for 5.2 GHz, 1 for 2.4 GHz, 2 for 6GHz
* @channel_num: AP Channel number
- * @format_bw: bits 0 - 3: &enum iwl_location_frame_format.
- * bits 4 - 7: &enum iwl_location_bw.
+ * @format_bw: &enum iwl_location_format_bw
* @ctrl_ch_position: Coding of the control channel position relative to the
* center frequency, see iwl_mvm_get_ctrl_pos().
* @bssid: AP's BSSID
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c
index 3464b3268712..81df3fdfcbf5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c
@@ -71,24 +71,34 @@ iwl_mld_ftm_set_target_chandef(struct iwl_mld *mld,
switch (peer->chandef.width) {
case NL80211_CHAN_WIDTH_20_NOHT:
- target->format_bw = IWL_LOCATION_FRAME_FORMAT_LEGACY;
- target->format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS;
+ target->format_bw = u8_encode_bits(IWL_LOCATION_FRAME_FORMAT_LEGACY,
+ IWL_LOCATION_FMT_BW_FORMAT);
+ target->format_bw |= u8_encode_bits(IWL_LOCATION_BW_20MHZ,
+ IWL_LOCATION_FMT_BW_BANDWIDTH);
break;
case NL80211_CHAN_WIDTH_20:
- target->format_bw = IWL_LOCATION_FRAME_FORMAT_HT;
- target->format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS;
+ target->format_bw = u8_encode_bits(IWL_LOCATION_FRAME_FORMAT_HT,
+ IWL_LOCATION_FMT_BW_FORMAT);
+ target->format_bw |= u8_encode_bits(IWL_LOCATION_BW_20MHZ,
+ IWL_LOCATION_FMT_BW_BANDWIDTH);
break;
case NL80211_CHAN_WIDTH_40:
- target->format_bw = IWL_LOCATION_FRAME_FORMAT_HT;
- target->format_bw |= IWL_LOCATION_BW_40MHZ << LOCATION_BW_POS;
+ target->format_bw = u8_encode_bits(IWL_LOCATION_FRAME_FORMAT_HT,
+ IWL_LOCATION_FMT_BW_FORMAT);
+ target->format_bw |= u8_encode_bits(IWL_LOCATION_BW_40MHZ,
+ IWL_LOCATION_FMT_BW_BANDWIDTH);
break;
case NL80211_CHAN_WIDTH_80:
- target->format_bw = IWL_LOCATION_FRAME_FORMAT_VHT;
- target->format_bw |= IWL_LOCATION_BW_80MHZ << LOCATION_BW_POS;
+ target->format_bw = u8_encode_bits(IWL_LOCATION_FRAME_FORMAT_VHT,
+ IWL_LOCATION_FMT_BW_FORMAT);
+ target->format_bw |= u8_encode_bits(IWL_LOCATION_BW_80MHZ,
+ IWL_LOCATION_FMT_BW_BANDWIDTH);
break;
case NL80211_CHAN_WIDTH_160:
- target->format_bw = IWL_LOCATION_FRAME_FORMAT_HE;
- target->format_bw |= IWL_LOCATION_BW_160MHZ << LOCATION_BW_POS;
+ target->format_bw = u8_encode_bits(IWL_LOCATION_FRAME_FORMAT_HE,
+ IWL_LOCATION_FMT_BW_FORMAT);
+ target->format_bw |= u8_encode_bits(IWL_LOCATION_BW_160MHZ,
+ IWL_LOCATION_FMT_BW_BANDWIDTH);
break;
default:
IWL_ERR(mld, "Unsupported BW in FTM request (%d)\n",
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
index 1b67836b1fac..3a14ca5e512a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
@@ -261,20 +261,28 @@ iwl_mvm_ftm_target_chandef_v2(struct iwl_mvm *mvm,
switch (peer->chandef.width) {
case NL80211_CHAN_WIDTH_20_NOHT:
- *format_bw = IWL_LOCATION_FRAME_FORMAT_LEGACY;
- *format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS;
+ *format_bw = u8_encode_bits(IWL_LOCATION_FRAME_FORMAT_LEGACY,
+ IWL_LOCATION_FMT_BW_FORMAT);
+ *format_bw |= u8_encode_bits(IWL_LOCATION_BW_20MHZ,
+ IWL_LOCATION_FMT_BW_BANDWIDTH);
break;
case NL80211_CHAN_WIDTH_20:
- *format_bw = IWL_LOCATION_FRAME_FORMAT_HT;
- *format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS;
+ *format_bw = u8_encode_bits(IWL_LOCATION_FRAME_FORMAT_HT,
+ IWL_LOCATION_FMT_BW_FORMAT);
+ *format_bw |= u8_encode_bits(IWL_LOCATION_BW_20MHZ,
+ IWL_LOCATION_FMT_BW_BANDWIDTH);
break;
case NL80211_CHAN_WIDTH_40:
- *format_bw = IWL_LOCATION_FRAME_FORMAT_HT;
- *format_bw |= IWL_LOCATION_BW_40MHZ << LOCATION_BW_POS;
+ *format_bw = u8_encode_bits(IWL_LOCATION_FRAME_FORMAT_HT,
+ IWL_LOCATION_FMT_BW_FORMAT);
+ *format_bw |= u8_encode_bits(IWL_LOCATION_BW_40MHZ,
+ IWL_LOCATION_FMT_BW_BANDWIDTH);
break;
case NL80211_CHAN_WIDTH_80:
- *format_bw = IWL_LOCATION_FRAME_FORMAT_VHT;
- *format_bw |= IWL_LOCATION_BW_80MHZ << LOCATION_BW_POS;
+ *format_bw = u8_encode_bits(IWL_LOCATION_FRAME_FORMAT_VHT,
+ IWL_LOCATION_FMT_BW_FORMAT);
+ *format_bw |= u8_encode_bits(IWL_LOCATION_BW_80MHZ,
+ IWL_LOCATION_FMT_BW_BANDWIDTH);
break;
case NL80211_CHAN_WIDTH_160:
cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
@@ -282,8 +290,10 @@ iwl_mvm_ftm_target_chandef_v2(struct iwl_mvm *mvm,
IWL_FW_CMD_VER_UNKNOWN);
if (cmd_ver >= 13) {
- *format_bw = IWL_LOCATION_FRAME_FORMAT_HE;
- *format_bw |= IWL_LOCATION_BW_160MHZ << LOCATION_BW_POS;
+ *format_bw = u8_encode_bits(IWL_LOCATION_FRAME_FORMAT_HE,
+ IWL_LOCATION_FMT_BW_FORMAT);
+ *format_bw |= u8_encode_bits(IWL_LOCATION_BW_160MHZ,
+ IWL_LOCATION_FMT_BW_BANDWIDTH);
break;
}
fallthrough;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
index 83f6e508a094..ae7a163c81c9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2024 Intel Corporation
+ * Copyright (C) 2018-2024, 2026 Intel Corporation
*/
#include <net/cfg80211.h>
#include <linux/etherdevice.h>
@@ -54,27 +54,37 @@ static int iwl_mvm_ftm_responder_set_bw_v2(struct cfg80211_chan_def *chandef,
{
switch (chandef->width) {
case NL80211_CHAN_WIDTH_20_NOHT:
- *format_bw = IWL_LOCATION_FRAME_FORMAT_LEGACY;
- *format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS;
+ *format_bw = u8_encode_bits(IWL_LOCATION_FRAME_FORMAT_LEGACY,
+ IWL_LOCATION_FMT_BW_FORMAT);
+ *format_bw |= u8_encode_bits(IWL_LOCATION_BW_20MHZ,
+ IWL_LOCATION_FMT_BW_BANDWIDTH);
break;
case NL80211_CHAN_WIDTH_20:
- *format_bw = IWL_LOCATION_FRAME_FORMAT_HT;
- *format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS;
+ *format_bw = u8_encode_bits(IWL_LOCATION_FRAME_FORMAT_HT,
+ IWL_LOCATION_FMT_BW_FORMAT);
+ *format_bw |= u8_encode_bits(IWL_LOCATION_BW_20MHZ,
+ IWL_LOCATION_FMT_BW_BANDWIDTH);
break;
case NL80211_CHAN_WIDTH_40:
- *format_bw = IWL_LOCATION_FRAME_FORMAT_HT;
- *format_bw |= IWL_LOCATION_BW_40MHZ << LOCATION_BW_POS;
+ *format_bw = u8_encode_bits(IWL_LOCATION_FRAME_FORMAT_HT,
+ IWL_LOCATION_FMT_BW_FORMAT);
+ *format_bw |= u8_encode_bits(IWL_LOCATION_BW_40MHZ,
+ IWL_LOCATION_FMT_BW_BANDWIDTH);
*ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
break;
case NL80211_CHAN_WIDTH_80:
- *format_bw = IWL_LOCATION_FRAME_FORMAT_VHT;
- *format_bw |= IWL_LOCATION_BW_80MHZ << LOCATION_BW_POS;
+ *format_bw = u8_encode_bits(IWL_LOCATION_FRAME_FORMAT_VHT,
+ IWL_LOCATION_FMT_BW_FORMAT);
+ *format_bw |= u8_encode_bits(IWL_LOCATION_BW_80MHZ,
+ IWL_LOCATION_FMT_BW_BANDWIDTH);
*ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
break;
case NL80211_CHAN_WIDTH_160:
if (cmd_ver >= 9) {
- *format_bw = IWL_LOCATION_FRAME_FORMAT_HE;
- *format_bw |= IWL_LOCATION_BW_160MHZ << LOCATION_BW_POS;
+ *format_bw = u8_encode_bits(IWL_LOCATION_FRAME_FORMAT_HE,
+ IWL_LOCATION_FMT_BW_FORMAT);
+ *format_bw |= u8_encode_bits(IWL_LOCATION_BW_160MHZ,
+ IWL_LOCATION_FMT_BW_BANDWIDTH);
*ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
break;
}
--
2.34.1
^ permalink raw reply related
* [PATCH v3 iwlwifi-next 08/15] wifi: iwlwifi: Add names for Killer BE1735x and BE1730x
From: Miri Korenblit @ 2026-05-19 6:40 UTC (permalink / raw)
To: linux-wireless; +Cc: Shahar Tzarfati, Johannes Berg
In-Reply-To: <20260519064010.549003-1-miriam.rachel.korenblit@intel.com>
From: Shahar Tzarfati <shahar.tzarfati@intel.com>
The devices were supported but had no name in the driver.
Add the correct names for these devices.
Signed-off-by: Shahar Tzarfati <shahar.tzarfati@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20260517100550.359f865f0920.Ie73648dd75f9c7d9e9a707311bd4d724d83b8763@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c | 2 ++
drivers/net/wireless/intel/iwlwifi/cfg/rf-wh.c | 2 ++
drivers/net/wireless/intel/iwlwifi/iwl-config.h | 2 ++
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 4 ++++
4 files changed, 10 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c
index f482536e6b5e..294cf25ae2a6 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c
@@ -47,6 +47,8 @@ const char iwl_killer_be1790s_name[] =
"Killer(R) Wi-Fi 7 BE1790s 320MHz Wireless Network Adapter (BE401D2W)";
const char iwl_killer_be1790i_name[] =
"Killer(R) Wi-Fi 7 BE1790i 320MHz Wireless Network Adapter (BE401NGW)";
+const char iwl_killer_be1730x_name[] =
+ "Killer(TM) Wi-Fi 7 BE1730x 160MHz Wireless Network Adapter (BE202)";
const char iwl_be201_name[] = "Intel(R) Wi-Fi 7 BE201 320MHz";
const char iwl_be200_name[] = "Intel(R) Wi-Fi 7 BE200 320MHz";
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-wh.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-wh.c
index fa63a9a01264..c432aa1a0af6 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/rf-wh.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-wh.c
@@ -29,6 +29,8 @@ const char iwl_killer_be1775s_name[] =
"Killer(R) Wi-Fi 7 BE1775s 320MHz Wireless Network Adapter (BE211D2W)";
const char iwl_killer_be1775i_name[] =
"Killer(R) Wi-Fi 7 BE1775i 320MHz Wireless Network Adapter (BE211NGW)";
+const char iwl_killer_be1735x_name[] =
+ "Killer(TM) Wi-Fi 7 BE1735x 160MHz Wireless Network Adapter (BE213)";
const char iwl_be211_name[] = "Intel(R) Wi-Fi 7 BE211 320MHz";
const char iwl_be213_name[] = "Intel(R) Wi-Fi 7 BE213 160MHz";
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index da6d3686e7dd..30d5ec31b9c3 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -676,6 +676,7 @@ extern const char iwl_killer_be1750w_name[];
extern const char iwl_killer_be1750x_name[];
extern const char iwl_killer_be1790s_name[];
extern const char iwl_killer_be1790i_name[];
+extern const char iwl_killer_be1730x_name[];
extern const char iwl_be201_name[];
extern const char iwl_be200_name[];
extern const char iwl_be202_name[];
@@ -683,6 +684,7 @@ extern const char iwl_be401_name[];
extern const char iwl_be213_name[];
extern const char iwl_killer_be1775s_name[];
extern const char iwl_killer_be1775i_name[];
+extern const char iwl_killer_be1735x_name[];
extern const char iwl_be211_name[];
extern const char iwl_killer_bn1850w2_name[];
extern const char iwl_killer_bn1850i_name[];
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index b0c59181907e..608100bc6b11 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -1054,6 +1054,8 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_DEV_INFO(iwl_rf_fm, iwl_killer_be1750i_name, SUBDEV(0x1772)),
IWL_DEV_INFO(iwl_rf_fm, iwl_killer_be1790s_name, SUBDEV(0x1791)),
IWL_DEV_INFO(iwl_rf_fm, iwl_killer_be1790i_name, SUBDEV(0x1792)),
+ IWL_DEV_INFO(iwl_rf_fm_160mhz, iwl_killer_be1730x_name, SUBDEV(0x1730)),
+ IWL_DEV_INFO(iwl_rf_fm_160mhz, iwl_killer_be1730x_name, SUBDEV(0x1731)),
/* Killer discrete */
IWL_DEV_INFO(iwl_rf_fm, iwl_killer_be1750w_name,
@@ -1079,6 +1081,8 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = {
/* Killer */
IWL_DEV_INFO(iwl_rf_wh, iwl_killer_be1775s_name, SUBDEV(0x1776)),
IWL_DEV_INFO(iwl_rf_wh, iwl_killer_be1775i_name, SUBDEV(0x1775)),
+ IWL_DEV_INFO(iwl_rf_wh_160mhz, iwl_killer_be1735x_name, SUBDEV(0x1735)),
+ IWL_DEV_INFO(iwl_rf_wh_160mhz, iwl_killer_be1735x_name, SUBDEV(0x1736)),
IWL_DEV_INFO(iwl_rf_pe, iwl_killer_bn1850w2_name, SUBDEV(0x1851)),
IWL_DEV_INFO(iwl_rf_pe, iwl_killer_bn1850i_name, SUBDEV(0x1852)),
--
2.34.1
^ permalink raw reply related
* [PATCH v3 iwlwifi-next 07/15] wifi: iwlwifi: move iwl_trans_activate_nic to iwl-trans.c
From: Miri Korenblit @ 2026-05-19 6:40 UTC (permalink / raw)
To: linux-wireless; +Cc: Emmanuel Grumbach
In-Reply-To: <20260519064010.549003-1-miriam.rachel.korenblit@intel.com>
From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
This function reaches the transport eventually so move it to
iwl-trans.c. Now we can remove the include to the pcie transport's
internal header from iwl-io.c
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Link: https://patch.msgid.link/20260517100550.0d433fb04d51.I50c48e3f4abe23236d3735236dac250588780f6a@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/iwl-io.c | 7 -------
drivers/net/wireless/intel/iwlwifi/iwl-io.h | 2 --
drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 9 ++++++++-
drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 2 ++
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c
index c4ccfffdf6af..bb746112ddad 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c
@@ -12,7 +12,6 @@
#include "iwl-debug.h"
#include "iwl-prph.h"
#include "iwl-fh.h"
-#include "pcie/gen1_2/internal.h"
void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val)
{
@@ -412,12 +411,6 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf)
return 0;
}
-int iwl_trans_activate_nic(struct iwl_trans *trans)
-{
- return iwl_pcie_gen1_2_activate_nic(trans);
-}
-IWL_EXPORT_SYMBOL(iwl_trans_activate_nic);
-
void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr,
u32 sw_err_bit)
{
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h
index d920a32fc173..6dce2e5267a6 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h
@@ -59,8 +59,6 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
void iwl_force_nmi(struct iwl_trans *trans);
-int iwl_trans_activate_nic(struct iwl_trans *trans);
-
/* Error handling */
int iwl_dump_fh(struct iwl_trans *trans, char **buf);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
index db1db0a42928..5b44e15fe64d 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
- * Copyright (C) 2019-2021, 2023-2025 Intel Corporation
+ * Copyright (C) 2019-2021, 2023-2026 Intel Corporation
*/
#include <linux/kernel.h>
#include <linux/bsearch.h>
@@ -820,3 +820,10 @@ bool iwl_trans_is_ltr_enabled(struct iwl_trans *trans)
return iwl_pcie_gen1_2_is_ltr_enabled(trans);
}
IWL_EXPORT_SYMBOL(iwl_trans_is_ltr_enabled);
+
+int iwl_trans_activate_nic(struct iwl_trans *trans)
+{
+ return iwl_pcie_gen1_2_activate_nic(trans);
+}
+IWL_EXPORT_SYMBOL(iwl_trans_activate_nic);
+
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index c661807c6e6b..1ed6bcb7882c 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -1053,6 +1053,8 @@ static inline bool iwl_trans_dbg_ini_valid(struct iwl_trans *trans)
void iwl_trans_interrupts(struct iwl_trans *trans, bool enable);
+int iwl_trans_activate_nic(struct iwl_trans *trans);
+
static inline void iwl_trans_finish_sw_reset(struct iwl_trans *trans)
{
clear_bit(STATUS_IN_SW_RESET, &trans->status);
--
2.34.1
^ permalink raw reply related
* [PATCH v3 iwlwifi-next 06/15] wifi: iwlwifi: move pcie content to pcie internal transport
From: Miri Korenblit @ 2026-05-19 6:40 UTC (permalink / raw)
To: linux-wireless; +Cc: Emmanuel Grumbach
In-Reply-To: <20260519064010.549003-1-miriam.rachel.korenblit@intel.com>
From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
The iwl_txq, iwl_pcie_first_tb_buf and iwl_pcie_txq_entry don't need to
be exported to the op_mode in iwl-trans.h. Declare those in the
transport's internal header file to avoid pollution.
iwl_trans_pcie_send_hcmd can also be moved to the internal header file.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Link: https://patch.msgid.link/20260517100550.208921548b4b.I76b1ac8499275e6d231880861e3843278f278c34@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
.../net/wireless/intel/iwlwifi/iwl-trans.h | 105 +-----------------
.../intel/iwlwifi/pcie/gen1_2/internal.h | 105 +++++++++++++++++-
2 files changed, 105 insertions(+), 105 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index 61e4f4776dcb..c661807c6e6b 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2018-2025 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2026 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -700,106 +700,6 @@ struct iwl_cmd_meta {
u32 tbs;
};
-/*
- * The FH will write back to the first TB only, so we need to copy some data
- * into the buffer regardless of whether it should be mapped or not.
- * This indicates how big the first TB must be to include the scratch buffer
- * and the assigned PN.
- * Since PN location is 8 bytes at offset 12, it's 20 now.
- * If we make it bigger then allocations will be bigger and copy slower, so
- * that's probably not useful.
- */
-#define IWL_FIRST_TB_SIZE 20
-#define IWL_FIRST_TB_SIZE_ALIGN ALIGN(IWL_FIRST_TB_SIZE, 64)
-
-struct iwl_pcie_txq_entry {
- void *cmd;
- struct sk_buff *skb;
- /* buffer to free after command completes */
- const void *free_buf;
- struct iwl_cmd_meta meta;
-};
-
-struct iwl_pcie_first_tb_buf {
- u8 buf[IWL_FIRST_TB_SIZE_ALIGN];
-};
-
-/**
- * struct iwl_txq - Tx Queue for DMA
- * @tfds: transmit frame descriptors (DMA memory)
- * @first_tb_bufs: start of command headers, including scratch buffers, for
- * the writeback -- this is DMA memory and an array holding one buffer
- * for each command on the queue
- * @first_tb_dma: DMA address for the first_tb_bufs start
- * @entries: transmit entries (driver state)
- * @lock: queue lock
- * @reclaim_lock: reclaim lock
- * @stuck_timer: timer that fires if queue gets stuck
- * @trans: pointer back to transport (for timer)
- * @need_update: indicates need to update read/write index
- * @ampdu: true if this queue is an ampdu queue for an specific RA/TID
- * @wd_timeout: queue watchdog timeout (jiffies) - per queue
- * @frozen: tx stuck queue timer is frozen
- * @frozen_expiry_remainder: remember how long until the timer fires
- * @block: queue is blocked
- * @bc_tbl: byte count table of the queue (relevant only for gen2 transport)
- * @write_ptr: 1-st empty entry (index) host_w
- * @read_ptr: last used entry (index) host_r
- * @dma_addr: physical addr for BD's
- * @n_window: safe queue window
- * @id: queue id
- * @low_mark: low watermark, resume queue if free space more than this
- * @high_mark: high watermark, stop queue if free space less than this
- * @overflow_q: overflow queue for handling frames that didn't fit on HW queue
- * @overflow_tx: need to transmit from overflow
- *
- * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
- * descriptors) and required locking structures.
- *
- * Note the difference between TFD_QUEUE_SIZE_MAX and n_window: the hardware
- * always assumes 256 descriptors, so TFD_QUEUE_SIZE_MAX is always 256 (unless
- * there might be HW changes in the future). For the normal TX
- * queues, n_window, which is the size of the software queue data
- * is also 256; however, for the command queue, n_window is only
- * 32 since we don't need so many commands pending. Since the HW
- * still uses 256 BDs for DMA though, TFD_QUEUE_SIZE_MAX stays 256.
- * This means that we end up with the following:
- * HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 |
- * SW entries: | 0 | ... | 31 |
- * where N is a number between 0 and 7. This means that the SW
- * data is a window overlayed over the HW queue.
- */
-struct iwl_txq {
- void *tfds;
- struct iwl_pcie_first_tb_buf *first_tb_bufs;
- dma_addr_t first_tb_dma;
- struct iwl_pcie_txq_entry *entries;
- /* lock for syncing changes on the queue */
- spinlock_t lock;
- /* lock to prevent concurrent reclaim */
- spinlock_t reclaim_lock;
- unsigned long frozen_expiry_remainder;
- struct timer_list stuck_timer;
- struct iwl_trans *trans;
- bool need_update;
- bool frozen;
- bool ampdu;
- int block;
- unsigned long wd_timeout;
- struct sk_buff_head overflow_q;
- struct iwl_dma_ptr bc_tbl;
-
- int write_ptr;
- int read_ptr;
- dma_addr_t dma_addr;
- int n_window;
- u32 id;
- int low_mark;
- int high_mark;
-
- bool overflow_tx;
-};
-
/**
* struct iwl_trans_info - transport info for outside use
* @name: the device name
@@ -1236,9 +1136,6 @@ enum iwl_reset_mode {
void iwl_trans_pcie_reset(struct iwl_trans *trans, enum iwl_reset_mode mode);
void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans);
-int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans,
- struct iwl_host_cmd *cmd);
-
/* Internal helper */
static inline void iwl_trans_set_info(struct iwl_trans *trans,
struct iwl_trans_info *info)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h
index 7b7b35e442f9..24f8714eae9f 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2003-2015, 2018-2025 Intel Corporation
+ * Copyright (C) 2003-2015, 2018-2026 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -287,6 +287,106 @@ enum iwl_pcie_imr_status {
IMR_D2S_ERROR,
};
+/*
+ * The FH will write back to the first TB only, so we need to copy some data
+ * into the buffer regardless of whether it should be mapped or not.
+ * This indicates how big the first TB must be to include the scratch buffer
+ * and the assigned PN.
+ * Since PN location is 8 bytes at offset 12, it's 20 now.
+ * If we make it bigger then allocations will be bigger and copy slower, so
+ * that's probably not useful.
+ */
+#define IWL_FIRST_TB_SIZE 20
+#define IWL_FIRST_TB_SIZE_ALIGN ALIGN(IWL_FIRST_TB_SIZE, 64)
+
+struct iwl_pcie_txq_entry {
+ void *cmd;
+ struct sk_buff *skb;
+ /* buffer to free after command completes */
+ const void *free_buf;
+ struct iwl_cmd_meta meta;
+};
+
+struct iwl_pcie_first_tb_buf {
+ u8 buf[IWL_FIRST_TB_SIZE_ALIGN];
+};
+
+/**
+ * struct iwl_txq - Tx Queue for DMA
+ * @tfds: transmit frame descriptors (DMA memory)
+ * @first_tb_bufs: start of command headers, including scratch buffers, for
+ * the writeback -- this is DMA memory and an array holding one buffer
+ * for each command on the queue
+ * @first_tb_dma: DMA address for the first_tb_bufs start
+ * @entries: transmit entries (driver state)
+ * @lock: queue lock
+ * @reclaim_lock: reclaim lock
+ * @stuck_timer: timer that fires if queue gets stuck
+ * @trans: pointer back to transport (for timer)
+ * @need_update: indicates need to update read/write index
+ * @ampdu: true if this queue is an ampdu queue for a specific RA/TID
+ * @wd_timeout: queue watchdog timeout (jiffies) - per queue
+ * @frozen: tx stuck queue timer is frozen
+ * @frozen_expiry_remainder: remember how long until the timer fires
+ * @block: queue is blocked
+ * @bc_tbl: byte count table of the queue (relevant only for gen2 transport)
+ * @write_ptr: 1-st empty entry (index) host_w
+ * @read_ptr: last used entry (index) host_r
+ * @dma_addr: physical addr for BDs
+ * @n_window: safe queue window
+ * @id: queue id
+ * @low_mark: low watermark, resume queue if free space more than this
+ * @high_mark: high watermark, stop queue if free space less than this
+ * @overflow_q: overflow queue for handling frames that didn't fit on HW queue
+ * @overflow_tx: need to transmit from overflow
+ *
+ * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
+ * descriptors) and required locking structures.
+ *
+ * Note the difference between TFD_QUEUE_SIZE_MAX and n_window: the hardware
+ * always assumes 256 descriptors, so TFD_QUEUE_SIZE_MAX is always 256 (unless
+ * there might be HW changes in the future). For the normal TX
+ * queues, n_window, which is the size of the software queue data
+ * is also 256; however, for the command queue, n_window is only
+ * 32 since we don't need so many commands pending. Since the HW
+ * still uses 256 BDs for DMA though, TFD_QUEUE_SIZE_MAX stays 256.
+ * This means that we end up with the following:
+ * HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 |
+ * SW entries: | 0 | ... | 31 |
+ * where N is a number between 0 and 7. This means that the SW
+ * data is a window overlaid over the HW queue.
+ */
+struct iwl_txq {
+ void *tfds;
+ struct iwl_pcie_first_tb_buf *first_tb_bufs;
+ dma_addr_t first_tb_dma;
+ struct iwl_pcie_txq_entry *entries;
+ /* lock for syncing changes on the queue */
+ spinlock_t lock;
+ /* lock to prevent concurrent reclaim */
+ spinlock_t reclaim_lock;
+ unsigned long frozen_expiry_remainder;
+ struct timer_list stuck_timer;
+ struct iwl_trans *trans;
+ bool need_update;
+ bool frozen;
+ bool ampdu;
+ int block;
+ unsigned long wd_timeout;
+ struct sk_buff_head overflow_q;
+ struct iwl_dma_ptr bc_tbl;
+
+ int write_ptr;
+ int read_ptr;
+ dma_addr_t dma_addr;
+ int n_window;
+ u32 id;
+ int low_mark;
+ int high_mark;
+
+ bool overflow_tx;
+};
+
/**
* struct iwl_pcie_txqs - TX queues data
*
@@ -1153,6 +1253,9 @@ int iwl_trans_pcie_copy_imr(struct iwl_trans *trans,
int iwl_trans_pcie_rxq_dma_data(struct iwl_trans *trans, int queue,
struct iwl_trans_rxq_dma_data *data);
+int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans,
+ struct iwl_host_cmd *cmd);
+
static inline bool iwl_pcie_gen1_is_pm_supported(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
--
2.34.1
^ permalink raw reply related
* [PATCH v3 iwlwifi-next 05/15] wifi: iwlwifi: mld: keep healthy link on EMLSR missed beacon exit
From: Miri Korenblit @ 2026-05-19 6:40 UTC (permalink / raw)
To: linux-wireless; +Cc: Avinash Bhatt
In-Reply-To: <20260519064010.549003-1-miriam.rachel.korenblit@intel.com>
From: Avinash Bhatt <avinash.bhatt@intel.com>
When EMLSR exits due to beacon loss on the current link, the driver
should keep the link that is still receiving beacons. The previous
code always called get_primary_link(), keeping the primary link
regardless of which link is actually losing beacons. If the primary
link is the one losing beacons, the driver exits EMLSR onto the
degraded link and the connection is lost eventually.
When both links lose beacons, keep the primary link. When only the
current link loses beacons -- whether due to signal loss or a BSS
parameter change -- keep the other link.
Signed-off-by: Avinash Bhatt <avinash.bhatt@intel.com>
Link: https://patch.msgid.link/20260517100550.b2d700f7775e.I8e9189ce6cf4388878beab14e56341becd5f427c@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mld/link.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c
index 549f1c1ea22f..1bdfba6279e2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c
@@ -663,15 +663,20 @@ void iwl_mld_handle_missed_beacon_notif(struct iwl_mld *mld,
* OR more than IWL_MLD_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED
* on current link and the link's bss_param_ch_count has changed on
* the other link's beacon.
+ *
+ * When both links lose beacons, keep the primary (symmetric failure).
+ * When only the current link is sick, keep the other link.
*/
- if ((missed_bcon >= IWL_MLD_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS &&
- scnd_lnk_bcn_lost >= IWL_MLD_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS) ||
- missed_bcon >= IWL_MLD_BCN_LOSS_EXIT_ESR_THRESH ||
- (bss_param_ch_cnt_link_id != link_id &&
- missed_bcon >=
- IWL_MLD_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED)) {
+ if (missed_bcon >= IWL_MLD_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS &&
+ scnd_lnk_bcn_lost >= IWL_MLD_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS) {
iwl_mld_exit_emlsr(mld, vif, IWL_MLD_EMLSR_EXIT_MISSED_BEACON,
iwl_mld_get_primary_link(vif));
+ } else if (missed_bcon >= IWL_MLD_BCN_LOSS_EXIT_ESR_THRESH ||
+ (bss_param_ch_cnt_link_id != link_id &&
+ missed_bcon >=
+ IWL_MLD_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED)) {
+ iwl_mld_exit_emlsr(mld, vif, IWL_MLD_EMLSR_EXIT_MISSED_BEACON,
+ iwl_mld_get_other_link(vif, link_id));
}
}
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_handle_missed_beacon_notif);
--
2.34.1
^ permalink raw reply related
* [PATCH v3 iwlwifi-next 04/15] wifi: iwlwifi: mld: skip MLO scan trigger when AP has no QBSS Load IE
From: Miri Korenblit @ 2026-05-19 6:39 UTC (permalink / raw)
To: linux-wireless; +Cc: Avinash Bhatt
In-Reply-To: <20260519064010.549003-1-miriam.rachel.korenblit@intel.com>
From: Avinash Bhatt <avinash.bhatt@intel.com>
When FW PHY statistics report high channel load (MCLM), the driver
triggers an internal MLO scan to find a better link. However, link grade
computation uses the QBSS Load IE from AP beacons, not MCLM data. If
the AP does not broadcast a QBSS Load IE, the scan produces no benefit
as the grade falls back to static band defaults regardless, and the same
bad link will be selected anyway as the active link.
Skip the MLO scan trigger when the AP does not advertise a QBSS Load IE.
Signed-off-by: Avinash Bhatt <avinash.bhatt@intel.com>
Link: https://patch.msgid.link/20260517100550.621538e20244.I7fdccb759508f32991cc06774cc7621725a58bd3@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mld/link.c | 5 ++---
drivers/net/wireless/intel/iwlwifi/mld/link.h | 3 +++
drivers/net/wireless/intel/iwlwifi/mld/mlo.c | 7 +++++++
3 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c
index e5e9b7089c14..549f1c1ea22f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c
@@ -859,9 +859,8 @@ iwl_mld_apply_puncturing_penalty(const struct ieee80211_bss_conf *link_conf,
*grade = *grade * (n_subchannels - n_punctured) / n_subchannels;
}
-static int
-iwl_mld_get_chan_load_from_element(struct iwl_mld *mld,
- struct ieee80211_bss_conf *link_conf)
+int iwl_mld_get_chan_load_from_element(struct iwl_mld *mld,
+ struct ieee80211_bss_conf *link_conf)
{
const struct cfg80211_bss_ies *ies;
const struct element *bss_load_elem = NULL;
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.h b/drivers/net/wireless/intel/iwlwifi/mld/link.h
index 0b3974d86531..f1997e280058 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/link.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/link.h
@@ -145,6 +145,9 @@ unsigned int iwl_mld_get_link_grade(struct iwl_mld *mld,
unsigned int iwl_mld_get_chan_load(struct iwl_mld *mld,
struct ieee80211_bss_conf *link_conf);
+int iwl_mld_get_chan_load_from_element(struct iwl_mld *mld,
+ struct ieee80211_bss_conf *link_conf);
+
int iwl_mld_get_chan_load_by_others(struct iwl_mld *mld,
struct ieee80211_bss_conf *link_conf,
bool expect_active_link);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
index 2a3b2c883fc4..a2f8a6957535 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
@@ -1100,6 +1100,13 @@ static void iwl_mld_chan_load_update_iter(void *_data, u8 *mac,
if (rcu_access_pointer(link_conf->chanctx_conf) != chanctx)
continue;
+ /* No QBSS IE - links will be selected based on default channel
+ * load values, so the same link will be selected again.
+ * No point in scan.
+ */
+ if (iwl_mld_get_chan_load_from_element(mld, link_conf) < 0)
+ continue;
+
if (iwl_mld_chan_load_requires_scan(mld,
link_conf,
new_chan_load)) {
--
2.34.1
^ permalink raw reply related
* [PATCH v3 iwlwifi-next 03/15] wifi: iwlwifi: bump maximum core version for BZ/SC/DR to 105
From: Miri Korenblit @ 2026-05-19 6:39 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <20260519064010.549003-1-miriam.rachel.korenblit@intel.com>
Start supporting Core 105 FW on these devices.
Link: https://patch.msgid.link/20260517100550.8674feeafcad.I3d3ae3a7acb976a947cd7e65a8d7fb8199d2e1ab@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 2 +-
drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 2 +-
drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
index 51d7c599e998..ecb4f81a99f5 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
@@ -10,7 +10,7 @@
#include "fw/api/txq.h"
/* Highest firmware core release supported */
-#define IWL_BZ_UCODE_CORE_MAX 104
+#define IWL_BZ_UCODE_CORE_MAX 105
/* Lowest firmware core release supported */
#define IWL_BZ_UCODE_CORE_MIN 101
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
index 76fbc120a092..e8968b3051d3 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
@@ -9,7 +9,7 @@
#include "fw/api/txq.h"
/* Highest firmware core release supported */
-#define IWL_DR_UCODE_CORE_MAX 104
+#define IWL_DR_UCODE_CORE_MAX 105
/* Lowest firmware core release supported */
#define IWL_DR_UCODE_CORE_MIN 101
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
index db7858b2cb74..6aaa49aeec99 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
@@ -10,7 +10,7 @@
#include "fw/api/txq.h"
/* Highest firmware core release supported */
-#define IWL_SC_UCODE_CORE_MAX 104
+#define IWL_SC_UCODE_CORE_MAX 105
/* Lowest firmware core release supported */
#define IWL_SC_UCODE_CORE_MIN 101
--
2.34.1
^ permalink raw reply related
* [PATCH v3 iwlwifi-next 02/15] wifi: iwlwifi: mld: purge async notifications upon nic error
From: Miri Korenblit @ 2026-05-19 6:39 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260519064010.549003-1-miriam.rachel.korenblit@intel.com>
This fixes a kernel panic in reconfig failure:
1. we have a BSS connection
2. we have a NAN connection
3. FW error occurs
4. reconfig restores the BSS connection
5. however, restoring the NAN connection fails due to a FW error.
6. erroneously, ieee80211_handle_reconfig_failure is called and marks all
interfaces as not-in-driver (will be fixed in a different patch).
7. mac80211 frees the links of the BSS connection but doesn't tell the
driver about that, as it thinks that this vif is not in the driver.
8. in ieee80211_stop_device, *ALL* wiphy works are getting flushed
(erroneously?)
9. Therefore, async_handlers_wk is being executed, processing the
statistics notification that was received after we restored the BSS
connection.
10. the notification handler dereferences fw_id_to_bss_conf[id], which is
now a dangling pointer, as mac80211 already freed this link in (7).
11. On the first access to one of the links fields, we panic.
While this can and should be fixed by removing the call to
ieee80211_handle_reconfig_failure in (6), it is also not a good idea to
carry and maybe handle notifications from a dead FW.
We do purge the notifications when we stop the FW, but in reconfig
failure we stop the FW too late, after the notifications are processed.
In addition, async_handlers_wk can always be scheduled before the
reconfig work.
Purge the notifications immediately when transport notifies about a nic
error.
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20260517100550.4414228bf1d1.I1926a2b2e7827eaac22882699880ec04a3cb95f0@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mld/mld.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.c b/drivers/net/wireless/intel/iwlwifi/mld/mld.c
index 0ef7c24831d8..78c78cf891cd 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mld.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.c
@@ -676,6 +676,15 @@ iwl_mld_nic_error(struct iwl_op_mode *op_mode,
if (type != IWL_ERR_TYPE_RESET_HS_TIMEOUT &&
mld->fw_status.running)
mld->fw_status.in_hw_restart = true;
+
+ /* FW is dead. We don't want to process its notifications.
+ * Right, we cancel them also in iwl_mld_stop_fw, but
+ * iwl_mld_async_handlers_wk might be executed before
+ * ieee80211_restart_work.
+ * In addition, in case of an error during recovery,
+ * iwl_mld_stop_fw might be too late.
+ */
+ iwl_mld_cancel_async_notifications(mld);
}
static void iwl_mld_dump_error(struct iwl_op_mode *op_mode,
--
2.34.1
^ permalink raw reply related
* [PATCH v3 iwlwifi-next 01/15] wifi: iwlwifi: mld: don't flush async_handlers_wk when canceling notifications
From: Miri Korenblit @ 2026-05-19 6:39 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260519064010.549003-1-miriam.rachel.korenblit@intel.com>
iwl_mld_cancel_async_notifications does 2 things: it purges the list of
notifications and flushes the async_handlers_wk.
We call iwl_mld_cancel_async_notifications after we stopped or suspended
the fw. So in that stage we don't expect any new notification coming,
and if erroneously there are new notifications coming, the work will be
queued again anyway, so the flush is pretty much pointless.
iwl_mld_cancel_async_notifications will need to be called in a context
w/o the wiphy lock held, and the only reason why this function requires
the lock being held is for flushing the work.
Remove the flush.
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20260517100550.70dddca96191.I06d3c6433ec22f81f2fb3fb2ee43881e662c5212@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mld/notif.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/notif.c b/drivers/net/wireless/intel/iwlwifi/mld/notif.c
index d7383022a0ed..7574689e4088 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/notif.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/notif.c
@@ -694,10 +694,6 @@ void iwl_mld_cancel_async_notifications(struct iwl_mld *mld)
{
struct iwl_async_handler_entry *entry, *tmp;
- lockdep_assert_wiphy(mld->wiphy);
-
- wiphy_work_cancel(mld->wiphy, &mld->async_handlers_wk);
-
spin_lock_bh(&mld->async_handlers_lock);
list_for_each_entry_safe(entry, tmp, &mld->async_handlers_list, list) {
iwl_mld_log_async_handler_op(mld, "Purged", &entry->rxb);
--
2.34.1
^ permalink raw reply related
* [PATCH v3 iwlwifi-next 00/15] wifi: iwlwifi: updates - 2026-05-16
From: Miri Korenblit @ 2026-05-19 6:39 UTC (permalink / raw)
To: linux-wireless
Hi,
Renamed dbg-old.c to dbg-legacy.c (maintainers check fails for some
reason)
Miri
---
Avinash Bhatt (2):
wifi: iwlwifi: mld: skip MLO scan trigger when AP has no QBSS Load IE
wifi: iwlwifi: mld: keep healthy link on EMLSR missed beacon exit
Emmanuel Grumbach (2):
wifi: iwlwifi: move pcie content to pcie internal transport
wifi: iwlwifi: move iwl_trans_activate_nic to iwl-trans.c
Johannes Berg (7):
wifi: iwlwifi: clean up location format/BW encoding
wifi: iwlwifi: fw: move struct iwl_fw_ini_dump_entry to dbg.c
wifi: iwlwifi: fw: separate ini dump allocation
wifi: iwlwifi: fw: dbg: always use non-tracing PRPH access
wifi: iwlwifi: fw: separate out old-style dump code
wifi: iwlwifi: dbg: remove unused 'range_len' arg from dump
wifi: iwlwifi: transport: add memory read under NIC access
Miri Korenblit (3):
wifi: iwlwifi: mld: don't flush async_handlers_wk when canceling
notifications
wifi: iwlwifi: mld: purge async notifications upon nic error
wifi: iwlwifi: bump maximum core version for BZ/SC/DR to 105
Shahar Tzarfati (1):
wifi: iwlwifi: Add names for Killer BE1735x and BE1730x
drivers/net/wireless/intel/iwlwifi/Makefile | 2 +-
drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 2 +-
drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 2 +-
.../net/wireless/intel/iwlwifi/cfg/rf-fm.c | 2 +
.../net/wireless/intel/iwlwifi/cfg/rf-wh.c | 2 +
drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 2 +-
.../wireless/intel/iwlwifi/fw/api/location.h | 100 +-
.../wireless/intel/iwlwifi/fw/dbg-legacy.c | 1022 +++++++++++++
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 1292 ++---------------
drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 7 +-
.../wireless/intel/iwlwifi/fw/error-dump.h | 14 +-
.../net/wireless/intel/iwlwifi/iwl-config.h | 2 +
drivers/net/wireless/intel/iwlwifi/iwl-io.c | 7 -
drivers/net/wireless/intel/iwlwifi/iwl-io.h | 2 -
.../net/wireless/intel/iwlwifi/iwl-trans.c | 15 +-
.../net/wireless/intel/iwlwifi/iwl-trans.h | 123 +-
.../intel/iwlwifi/mld/ftm-initiator.c | 30 +-
drivers/net/wireless/intel/iwlwifi/mld/link.c | 22 +-
drivers/net/wireless/intel/iwlwifi/mld/link.h | 3 +
drivers/net/wireless/intel/iwlwifi/mld/mld.c | 9 +
drivers/net/wireless/intel/iwlwifi/mld/mlo.c | 7 +
.../net/wireless/intel/iwlwifi/mld/notif.c | 4 -
.../intel/iwlwifi/mvm/ftm-initiator.c | 30 +-
.../intel/iwlwifi/mvm/ftm-responder.c | 32 +-
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 4 +
.../intel/iwlwifi/pcie/gen1_2/internal.h | 107 +-
.../intel/iwlwifi/pcie/gen1_2/trans.c | 54 +
27 files changed, 1536 insertions(+), 1362 deletions(-)
create mode 100644 drivers/net/wireless/intel/iwlwifi/fw/dbg-legacy.c
--
2.34.1
^ permalink raw reply
* [PATCH] wifi: iwlwifi: mld: fix indentation in iwl_mld_fill_supp_rates()
From: Dongyang Jin @ 2026-05-19 6:02 UTC (permalink / raw)
To: miriam.rachel.korenblit, johannes.berg, emmanuel.grumbach
Cc: linux-wireless, linux-kernel, Dongyang Jin, kernel test robot
Fix the following inconsistent indentation warnings reported by smatch:
smatch warnings:
drivers/net/wireless/intel/iwlwifi/mld/tlc.c:454 iwl_mld_fill_supp_rates() warn: inconsistent indenting
There's an extra tab, remove it.
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202605170928.yPTN7kOn-lkp@intel.com/
Signed-off-by: Dongyang Jin <jindongyang@kylinos.cn>
---
drivers/net/wireless/intel/iwlwifi/mld/tlc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tlc.c b/drivers/net/wireless/intel/iwlwifi/mld/tlc.c
index fb68d8810e14..a03834d3ac65 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tlc.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tlc.c
@@ -451,7 +451,7 @@ iwl_mld_fill_supp_rates(struct iwl_mld *mld,
iwl_mld_fill_he_rates(capa, cmd);
} else if (capa->vht_cap && capa->vht_cap->vht_supported) {
cmd->mode = IWL_TLC_MNG_MODE_VHT;
- iwl_mld_fill_vht_rates(capa, cmd);
+ iwl_mld_fill_vht_rates(capa, cmd);
} else if (capa->ht_cap && capa->ht_cap->ht_supported) {
cmd->mode = IWL_TLC_MNG_MODE_HT;
cmd->ht_rates[IWL_TLC_NSS_1][IWL_TLC_MCS_PER_BW_80] =
--
2.25.1
^ permalink raw reply related
* Re: [PATCH rtw-next 01/11] wifi: rtw89: phy: define BB wrap data for RTL8922D variants
From: Ping-Ke Shih @ 2026-05-19 4:19 UTC (permalink / raw)
To: Ping-Ke Shih, linux-wireless
In-Reply-To: <20260511070148.25257-2-pkshih@realtek.com>
Ping-Ke Shih <pkshih@realtek.com> wrote:
> The BB wrap is a hardware block to control TX power. Since RTL8922D has
> many variants with different CID and RFE types, prepare flow and dummy
> struct adopt to configuration functions for coming patches.
>
> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
11 patch(es) applied to rtw-next branch of rtw.git, thanks.
695e7f2e7901 wifi: rtw89: phy: define BB wrap data for RTL8922D variants
99237c755c27 wifi: rtw89: phy: set BB wrap of out-of-band DPD
9adb75af3f5a wifi: rtw89: phy: set BB wrap of DPD by bandwidth
f791fe306078 wifi: rtw89: phy: set BB wrap of control options
7924c027474c wifi: rtw89: phy: set BB wrap of QAM threshold
7c4ef01bb3c3 wifi: rtw89: phy: set BB wrap of QAM options
ce23c529c722 wifi: rtw89: phy: set BB wrap of trigger-base partial band
89ff0338727f wifi: rtw89: phy: set BB wrap of CIM3K
a395d7eed2f8 wifi: rtw89: phy: change order to align register order
4f2b5c83657e wifi: rtw89: phy: configure control options of BB wrapper by RFSI band
7076af642955 wifi: rtw89: phy: add BB wrapper generation 3 for RTL8922D variant
---
https://github.com/pkshih/rtw.git
^ permalink raw reply
* [PATCH wireless-next] wifi: wcn36xx: allocate chan_surveys with main struct
From: Rosen Penev @ 2026-05-19 2:03 UTC (permalink / raw)
To: linux-wireless
Cc: Loic Poulain, open list:QUALCOMM WCN36XX WIRELESS DRIVER,
open list
Avoid allocating separately with a flexible array member. Simplifies
allocation slightly.
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
drivers/net/wireless/ath/wcn36xx/main.c | 13 ++-----------
drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 2 +-
2 files changed, 3 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index c3f0860873de..ad8a4bd910d2 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -1568,7 +1568,8 @@ static int wcn36xx_probe(struct platform_device *pdev)
wcnss = dev_get_drvdata(pdev->dev.parent);
- hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops);
+ n_channels = wcn_band_2ghz.n_channels + wcn_band_5ghz.n_channels;
+ hw = ieee80211_alloc_hw(struct_size(wcn, chan_survey, n_channels), &wcn36xx_ops);
if (!hw) {
wcn36xx_err("failed to alloc hw\n");
ret = -ENOMEM;
@@ -1590,16 +1591,6 @@ static int wcn36xx_probe(struct platform_device *pdev)
goto out_wq;
}
- n_channels = wcn_band_2ghz.n_channels + wcn_band_5ghz.n_channels;
- wcn->chan_survey = devm_kcalloc(wcn->dev,
- n_channels,
- sizeof(struct wcn36xx_chan_survey),
- GFP_KERNEL);
- if (!wcn->chan_survey) {
- ret = -ENOMEM;
- goto out_wq;
- }
-
ret = dma_set_mask_and_coherent(wcn->dev, DMA_BIT_MASK(32));
if (ret < 0) {
wcn36xx_err("failed to set DMA mask: %d\n", ret);
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index 7ee79593cd23..8c43f67bd780 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -298,7 +298,7 @@ struct wcn36xx {
struct ieee80211_channel *channel;
spinlock_t survey_lock; /* protects chan_survey */
- struct wcn36xx_chan_survey *chan_survey;
+ struct wcn36xx_chan_survey chan_survey[];
};
static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn,
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v5 0/2] genirq/ath12k: fallback to threaded NAPI when IRQ affinity is unavailable
From: Hangtian Zhu @ 2026-05-19 1:22 UTC (permalink / raw)
To: tglx, jjohnson; +Cc: linux-wireless, ath12k, linux-kernel
In-Reply-To: <20260519010758.712297-1-hangtian@qti.qualcomm.com>
On 5/19/2026 9:07, Hangtian Zhu wrote:
> From: Hangtian Zhu <hangtian.zhu@oss.qualcomm.com>
>
> This series improves ath12k datapath behavior on platforms where the
> effective IRQ path for WLAN MSI interrupts does not support affinity
> setting.
>
> In such setups, DP processing cannot be distributed as intended and can
> become CPU-constrained. The ath12k change switches to threaded NAPI when
> runtime IRQ capability indicates affinity is unavailable.
>
> Patch 1 exports irq_can_set_affinity() for module drivers so they can
> reuse the IRQ core helper instead of open-coding equivalent checks.
>
> Patch 2 uses irq_can_set_affinity() in ath12k PCI to enable threaded NAPI
> for DP interrupt groups only when affinity cannot be set.
>
> On RB3Gen2 with QCC2072, EHT160 UDP downlink throughput improved from
> 802 Mbps to 2.58 Gbps after enabling threaded NAPI.
>
> Tested-on: QCC2072 hw1.0 PCI WLAN.COL.1.0.c2-00074-QCACOLSWPL_V1_TO_SILICONZ-1
>
> Thanks,
> Hangtian Zhu
> ---
> v2: sanity check irq >=0 before irq_can_set_affinity in patch 2
> v1: initial post
>
> Hangtian Zhu (2):
> genirq: export irq_can_set_affinity() for module drivers
> wifi: ath12k: enable threaded NAPI when DP IRQ affinity is unavailable
>
> drivers/net/wireless/ath/ath12k/pci.c | 11 ++++++++++-
> kernel/irq/manage.c | 1 +
> 2 files changed, 11 insertions(+), 1 deletion(-)
>
>
> base-commit: e12d2d3983acb150fd987d19ec6a2a530da110df
ignore this series as wrong patch version, resend with "[RESEND PATCH
0/2] genirq/ath12k: fallback to threaded NAPI when IRQ affinity is
unavailable"
^ permalink raw reply
* [RESEND PATCH 2/2] wifi: ath12k: enable threaded NAPI when DP IRQ affinity is unavailable
From: Hangtian Zhu @ 2026-05-19 1:16 UTC (permalink / raw)
To: tglx, jjohnson; +Cc: linux-wireless, ath12k, linux-kernel
In-Reply-To: <20260519011627.713068-1-hangtian.zhu@oss.qualcomm.com>
Determine threaded NAPI policy from runtime IRQ capability of the DP MSI
IRQ.
If irq_can_set_affinity() reports that affinity cannot be set, enable
threaded NAPI for DP interrupt groups so datapath processing is not
constrained by a single-CPU softirq context.
On RB3Gen2, where IRQ affinity is unavailable in the effective IRQ path,
EHT160 UDP downlink throughput improved from 802 Mbps to 2.58 Gbps after
enabling threaded NAPI.
Tested-on: QCC2072 hw1.0 PCI WLAN.COL.1.0.c2-00074-QCACOLSWPL_V1_TO_SILICONZ-1
Signed-off-by: Hangtian Zhu <hangtian.zhu@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/pci.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
index 375277ca2b89..065449806ea9 100644
--- a/drivers/net/wireless/ath/ath12k/pci.c
+++ b/drivers/net/wireless/ath/ath12k/pci.c
@@ -5,6 +5,7 @@
*/
#include <linux/module.h>
+#include <linux/interrupt.h>
#include <linux/msi.h>
#include <linux/pci.h>
#include <linux/time.h>
@@ -537,6 +538,8 @@ static int ath12k_pci_ext_irq_config(struct ath12k_base *ab)
int i, j, n, ret, num_vectors = 0;
u32 user_base_data = 0, base_vector = 0, base_idx;
struct ath12k_ext_irq_grp *irq_grp;
+ bool threaded_napi = false;
+ int irq;
base_idx = ATH12K_PCI_IRQ_CE0_OFFSET + CE_COUNT_MAX;
ret = ath12k_pci_get_user_msi_assignment(ab, "DP",
@@ -546,6 +549,10 @@ static int ath12k_pci_ext_irq_config(struct ath12k_base *ab)
if (ret < 0)
return ret;
+ irq = ath12k_pci_get_msi_irq(ab->dev, base_vector);
+ if (irq >= 0)
+ threaded_napi = !irq_can_set_affinity(irq);
+
for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) {
irq_grp = &ab->ext_irq_grp[i];
u32 num_irq = 0;
@@ -560,6 +567,8 @@ static int ath12k_pci_ext_irq_config(struct ath12k_base *ab)
netif_napi_add(irq_grp->napi_ndev, &irq_grp->napi,
ath12k_pci_ext_grp_napi_poll);
+ if (threaded_napi)
+ netif_threaded_enable(irq_grp->napi_ndev);
if (ab->hw_params->ring_mask->tx[i] ||
ab->hw_params->ring_mask->rx[i] ||
@@ -578,7 +587,7 @@ static int ath12k_pci_ext_irq_config(struct ath12k_base *ab)
for (j = 0; j < irq_grp->num_irq; j++) {
int irq_idx = irq_grp->irqs[j];
int vector = (i % num_vectors) + base_vector;
- int irq = ath12k_pci_get_msi_irq(ab->dev, vector);
+ irq = ath12k_pci_get_msi_irq(ab->dev, vector);
ab->irq_num[irq_idx] = irq;
--
2.25.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