summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/intel
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/intel')
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2100.c6
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2200.c2
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw_crypto.c4
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw_module.c2
-rw-r--r--drivers/net/wireless/intel/iwlegacy/3945-rs.c3
-rw-r--r--drivers/net/wireless/intel/iwlegacy/4965-mac.c9
-rw-r--r--drivers/net/wireless/intel/iwlegacy/4965-rs.c3
-rw-r--r--drivers/net/wireless/intel/iwlegacy/commands.h2
-rw-r--r--drivers/net/wireless/intel/iwlegacy/common.c4
-rw-r--r--drivers/net/wireless/intel/iwlegacy/common.h2
-rw-r--r--drivers/net/wireless/intel/iwlegacy/iwl-spectrum.h24
-rw-r--r--drivers/net/wireless/intel/iwlwifi/Kconfig1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/Makefile24
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/1000.c51
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/2000.c90
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/22000.c395
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/5000.c83
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/6000.c227
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/7000.c173
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/8000.c91
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/9000.c167
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/ax210.c261
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/bz.c192
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/dr.c174
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c52
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/rf-gf.c85
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/rf-hr.c89
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/rf-jf.c111
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/rf-pe.c17
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/rf-wh.c39
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/sc.c176
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/agn.h10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/commands.h16
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/dev.h7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/devices.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c88
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/led.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/lib.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c20
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/main.c95
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/power.c36
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/power.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/rs.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/rx.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/rxon.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/tt.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/tx.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/ucode.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/acpi.c59
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/acpi.h14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/alive.h27
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/cmdhdr.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/coex.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/commands.h13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/d3.h242
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h27
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/debug.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/location.h97
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h195
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/mac.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h137
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/offload.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/power.h111
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/rs.h118
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/rx.h340
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/scan.h78
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/sta.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/stats.h44
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/tx.h69
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.c191
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/debugfs.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dump.c70
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/error-dump.h12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/file.h98
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/img.h21
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/init.c20
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/paging.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/pnvm.c154
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/pnvm.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/regulatory.c131
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/regulatory.h28
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/rs.c137
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/runtime.h41
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/smem.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/uefi.c81
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/uefi.h37
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-config.h542
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-csr.h30
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.c241
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.h13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-fh.h30
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-io.c121
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-io.h25
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-modparams.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c268
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h107
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-utils.c17
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h28
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-prph.h10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.c324
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.h324
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-utils.c114
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-utils.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mei/sap.h32
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/Makefile4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/agg.c21
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/ap.c31
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/constants.h11
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/d3.c716
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/debugfs.c38
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/fw.c137
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/iface.c74
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/iface.h31
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/key.c50
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/key.h7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/link.c432
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/link.h48
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/low_latency.c15
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/mac80211.c346
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/mcc.c70
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/mld.c127
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/mld.h48
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/mlo.c291
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/mlo.h14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/notif.c92
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/notif.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/phy.c43
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/phy.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/power.c13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/ptp.c21
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/regulatory.c136
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/roc.c119
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/rx.c1838
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/rx.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/scan.c179
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/scan.h39
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/sta.c48
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/sta.h7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/stats.c42
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/tests/agg.c14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/tests/hcmd.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c138
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/tests/link.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c39
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/tests/utils.h84
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/thermal.c89
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/tlc.c83
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/tx.c122
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/coex.c137
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/constants.h20
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c843
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c94
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c147
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/led.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/link.c869
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c88
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c340
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c55
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c156
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h245
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/nvm.c42
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c243
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c24
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/power.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ptp.c21
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/quota.c43
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c23
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.c40
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rx.c161
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c202
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c222
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c127
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h34
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tests/Makefile2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tests/hcmd.c38
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tests/links.c433
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.c54
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.h8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tt.c93
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c287
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/utils.c186
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c (renamed from drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c)206
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c29
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/drv.c2576
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h (renamed from drivers/net/wireless/intel/iwlwifi/pcie/internal.h)219
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c (renamed from drivers/net/wireless/intel/iwlwifi/pcie/rx.c)217
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c (renamed from drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c)173
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c (renamed from drivers/net/wireless/intel/iwlwifi/pcie/trans.c)1057
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx-gen2.c (renamed from drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c)76
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c (renamed from drivers/net/wireless/intel/iwlwifi/pcie/tx.c)257
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info-v2.h (renamed from drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h)65
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info.h (renamed from drivers/net/wireless/intel/iwlwifi/iwl-context-info.h)14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/utils.c104
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/utils.h40
-rw-r--r--drivers/net/wireless/intel/iwlwifi/tests/Makefile2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/tests/devinfo.c256
-rw-r--r--drivers/net/wireless/intel/iwlwifi/tests/nvm_parse.c72
-rw-r--r--drivers/net/wireless/intel/iwlwifi/tests/utils.c (renamed from drivers/net/wireless/intel/iwlwifi/mvm/tests/scan.c)43
211 files changed, 11461 insertions, 12783 deletions
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
index 215814861cbd..c7c5bc0f1650 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
@@ -2143,7 +2143,7 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status)
/* Make sure the RF Kill check timer is running */
priv->stop_rf_kill = 0;
- mod_delayed_work(system_wq, &priv->rf_kill, round_jiffies_relative(HZ));
+ mod_delayed_work(system_percpu_wq, &priv->rf_kill, round_jiffies_relative(HZ));
}
static void ipw2100_scan_event(struct work_struct *work)
@@ -2170,7 +2170,7 @@ static void isr_scan_complete(struct ipw2100_priv *priv, u32 status)
round_jiffies_relative(msecs_to_jiffies(4000)));
} else {
priv->user_requested_scan = 0;
- mod_delayed_work(system_wq, &priv->scan_event, 0);
+ mod_delayed_work(system_percpu_wq, &priv->scan_event, 0);
}
}
@@ -4252,7 +4252,7 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio)
"disabled by HW switch\n");
/* Make sure the RF_KILL check timer is running */
priv->stop_rf_kill = 0;
- mod_delayed_work(system_wq, &priv->rf_kill,
+ mod_delayed_work(system_percpu_wq, &priv->rf_kill,
round_jiffies_relative(HZ));
} else
schedule_reset(priv);
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
index 24a5624ef207..09035a77e775 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
@@ -4415,7 +4415,7 @@ static void handle_scan_event(struct ipw_priv *priv)
round_jiffies_relative(msecs_to_jiffies(4000)));
} else {
priv->user_requested_scan = 0;
- mod_delayed_work(system_wq, &priv->scan_event, 0);
+ mod_delayed_work(system_percpu_wq, &priv->scan_event, 0);
}
}
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_crypto.c b/drivers/net/wireless/intel/ipw2x00/libipw_crypto.c
index dfcc12aa8620..243d0c5928a2 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw_crypto.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_crypto.c
@@ -110,8 +110,8 @@ static void libipw_crypt_quiescing(struct libipw_crypt_info *info)
static void libipw_crypt_deinit_handler(struct timer_list *t)
{
- struct libipw_crypt_info *info = from_timer(info, t,
- crypt_deinit_timer);
+ struct libipw_crypt_info *info = timer_container_of(info, t,
+ crypt_deinit_timer);
unsigned long flags;
libipw_crypt_deinit_entries(info, 0);
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_module.c b/drivers/net/wireless/intel/ipw2x00/libipw_module.c
index 0a16127bfd68..2ad085b1f492 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw_module.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_module.c
@@ -83,7 +83,7 @@ void libipw_networks_age(struct libipw_device *ieee,
{
struct libipw_network *network = NULL;
unsigned long flags;
- unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
+ unsigned long age_jiffies = secs_to_jiffies(age_secs);
spin_lock_irqsave(&ieee->lock, flags);
list_for_each_entry(network, &ieee->network_list, list) {
diff --git a/drivers/net/wireless/intel/iwlegacy/3945-rs.c b/drivers/net/wireless/intel/iwlegacy/3945-rs.c
index df1b8ec86651..1826c37c090c 100644
--- a/drivers/net/wireless/intel/iwlegacy/3945-rs.c
+++ b/drivers/net/wireless/intel/iwlegacy/3945-rs.c
@@ -168,7 +168,8 @@ il3945_rate_scale_flush_wins(struct il3945_rs_sta *rs_sta)
static void
il3945_bg_rate_scale_flush(struct timer_list *t)
{
- struct il3945_rs_sta *rs_sta = from_timer(rs_sta, t, rate_scale_flush);
+ struct il3945_rs_sta *rs_sta = timer_container_of(rs_sta, t,
+ rate_scale_flush);
struct il_priv *il __maybe_unused = rs_sta->il;
int unflushed = 0;
unsigned long flags;
diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
index dc8c408902e6..3588dec75ebd 100644
--- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
@@ -1382,7 +1382,7 @@ il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb)
* we get a thermal update even if the uCode doesn't give us one
*/
mod_timer(&il->stats_periodic,
- jiffies + msecs_to_jiffies(recalib_seconds * 1000));
+ jiffies + secs_to_jiffies(recalib_seconds));
if (unlikely(!test_bit(S_SCANNING, &il->status)) &&
(pkt->hdr.cmd == N_STATS)) {
@@ -1575,8 +1575,11 @@ il4965_tx_cmd_build_rate(struct il_priv *il,
|| rate_idx > RATE_COUNT_LEGACY)
rate_idx = rate_lowest_index(&il->bands[info->band], sta);
/* For 5 GHZ band, remap mac80211 rate indices into driver indices */
- if (info->band == NL80211_BAND_5GHZ)
+ if (info->band == NL80211_BAND_5GHZ) {
rate_idx += IL_FIRST_OFDM_RATE;
+ if (rate_idx > IL_LAST_OFDM_RATE)
+ rate_idx = IL_LAST_OFDM_RATE;
+ }
/* Get PLCP rate for tx_cmd->rate_n_flags */
rate_plcp = il_rates[rate_idx].plcp;
/* Zero out flags for this packet */
@@ -4051,7 +4054,7 @@ il4965_hdl_alive(struct il_priv *il, struct il_rx_buf *rxb)
static void
il4965_bg_stats_periodic(struct timer_list *t)
{
- struct il_priv *il = from_timer(il, t, stats_periodic);
+ struct il_priv *il = timer_container_of(il, t, stats_periodic);
if (test_bit(S_EXIT_PENDING, &il->status))
return;
diff --git a/drivers/net/wireless/intel/iwlegacy/4965-rs.c b/drivers/net/wireless/intel/iwlegacy/4965-rs.c
index 0e5130d1fccd..031d88bf6393 100644
--- a/drivers/net/wireless/intel/iwlegacy/4965-rs.c
+++ b/drivers/net/wireless/intel/iwlegacy/4965-rs.c
@@ -203,7 +203,8 @@ il4965_rs_extract_rate(u32 rate_n_flags)
return (u8) (rate_n_flags & 0xFF);
}
-static void
+/* noinline works around https://github.com/llvm/llvm-project/issues/143908 */
+static noinline_for_stack void
il4965_rs_rate_scale_clear_win(struct il_rate_scale_data *win)
{
win->data = 0;
diff --git a/drivers/net/wireless/intel/iwlegacy/commands.h b/drivers/net/wireless/intel/iwlegacy/commands.h
index 4a9fa8b83f0f..b61b8f377702 100644
--- a/drivers/net/wireless/intel/iwlegacy/commands.h
+++ b/drivers/net/wireless/intel/iwlegacy/commands.h
@@ -2229,7 +2229,7 @@ struct il_spectrum_notification {
u8 channel;
u8 type; /* see enum il_measurement_type */
u8 reserved1;
- /* NOTE: cca_ofdm, cca_cck, basic_type, and histogram are only only
+ /* NOTE: cca_ofdm, cca_cck, basic_type, and histogram are only
* valid if applicable for measurement type requested. */
__le32 cca_ofdm; /* cca fraction time in 40Mhz clock periods */
__le32 cca_cck; /* cca fraction time in 44Mhz clock periods */
diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c
index 09fb4b758704..b7bd3ec4cc50 100644
--- a/drivers/net/wireless/intel/iwlegacy/common.c
+++ b/drivers/net/wireless/intel/iwlegacy/common.c
@@ -4804,7 +4804,7 @@ il_check_stuck_queue(struct il_priv *il, int cnt)
void
il_bg_watchdog(struct timer_list *t)
{
- struct il_priv *il = from_timer(il, t, watchdog);
+ struct il_priv *il = timer_container_of(il, t, watchdog);
int cnt;
unsigned long timeout;
@@ -4990,7 +4990,7 @@ il_update_qos(struct il_priv *il)
* il_mac_config - mac80211 config callback
*/
int
-il_mac_config(struct ieee80211_hw *hw, u32 changed)
+il_mac_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
struct il_priv *il = hw->priv;
const struct il_channel_info *ch_info;
diff --git a/drivers/net/wireless/intel/iwlegacy/common.h b/drivers/net/wireless/intel/iwlegacy/common.h
index 52610f5e57a3..4c9836ab11dd 100644
--- a/drivers/net/wireless/intel/iwlegacy/common.h
+++ b/drivers/net/wireless/intel/iwlegacy/common.h
@@ -1956,7 +1956,7 @@ il_get_hw_mode(struct il_priv *il, enum nl80211_band band)
}
/* mac80211 handlers */
-int il_mac_config(struct ieee80211_hw *hw, u32 changed);
+int il_mac_config(struct ieee80211_hw *hw, int radio_idx, u32 changed);
void il_mac_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
void il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf, u64 changes);
diff --git a/drivers/net/wireless/intel/iwlegacy/iwl-spectrum.h b/drivers/net/wireless/intel/iwlegacy/iwl-spectrum.h
index 1e8ab704dbfb..f00eb878b94b 100644
--- a/drivers/net/wireless/intel/iwlegacy/iwl-spectrum.h
+++ b/drivers/net/wireless/intel/iwlegacy/iwl-spectrum.h
@@ -50,28 +50,4 @@ struct ieee80211_measurement_params {
__le16 duration;
} __packed;
-struct ieee80211_info_element {
- u8 id;
- u8 len;
- u8 data[];
-} __packed;
-
-struct ieee80211_measurement_request {
- struct ieee80211_info_element ie;
- u8 token;
- u8 mode;
- u8 type;
- struct ieee80211_measurement_params params[];
-} __packed;
-
-struct ieee80211_measurement_report {
- struct ieee80211_info_element ie;
- u8 token;
- u8 mode;
- u8 type;
- union {
- struct ieee80211_basic_report basic[0];
- } u;
-} __packed;
-
#endif
diff --git a/drivers/net/wireless/intel/iwlwifi/Kconfig b/drivers/net/wireless/intel/iwlwifi/Kconfig
index 82f577da1a8b..153a8368b412 100644
--- a/drivers/net/wireless/intel/iwlwifi/Kconfig
+++ b/drivers/net/wireless/intel/iwlwifi/Kconfig
@@ -97,6 +97,7 @@ config IWLWIFI_OPMODE_MODULAR
default y if IWLDVM=m
default y if IWLMVM=m
default y if IWLMLD=m
+ default y if IWLWIFI_KUNIT_TESTS=m
comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM or IWLMLD"
depends on IWLDVM=n && IWLMVM=n && IWLMLD=n
diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile
index 9546ceeaf5e3..941257b811b4 100644
--- a/drivers/net/wireless/intel/iwlwifi/Makefile
+++ b/drivers/net/wireless/intel/iwlwifi/Makefile
@@ -7,13 +7,27 @@ iwlwifi-objs += iwl-debug.o
iwlwifi-objs += iwl-nvm-utils.o
iwlwifi-objs += iwl-utils.o
iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o
-iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
-iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-gen3.o
-iwlwifi-objs += pcie/trans-gen2.o pcie/tx-gen2.o
-iwlwifi-$(CONFIG_IWLDVM) += cfg/1000.o cfg/2000.o cfg/5000.o cfg/6000.o
-iwlwifi-$(CONFIG_IWLMVM) += cfg/7000.o cfg/8000.o cfg/9000.o cfg/22000.o
+
+# Bus
+iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-v2.o pcie/drv.o pcie/utils.o
+iwlwifi-objs += pcie/gen1_2/rx.o pcie/gen1_2/tx.o pcie/gen1_2/trans.o
+iwlwifi-objs += pcie/gen1_2/trans-gen2.o pcie/gen1_2/tx-gen2.o
+
+CFLAGS_pcie/drv.o += -Wno-override-init
+
+# combined MAC/RF configurations
+iwlwifi-$(CONFIG_IWLDVM) += cfg/1000.o cfg/2000.o
+iwlwifi-$(CONFIG_IWLDVM) += cfg/5000.o cfg/6000.o
+iwlwifi-$(CONFIG_IWLMVM) += cfg/7000.o cfg/8000.o
+# MAC configurations
+iwlwifi-$(CONFIG_IWLMVM) += cfg/9000.o cfg/22000.o
iwlwifi-$(CONFIG_IWLMVM) += cfg/ax210.o
+iwlwifi-$(CONFIG_IWLMVM) += cfg/bz.o cfg/sc.o
iwlwifi-$(CONFIG_IWLMLD) += cfg/bz.o cfg/sc.o cfg/dr.o
+# RF configurations
+iwlwifi-$(CONFIG_IWLMVM) += cfg/rf-jf.o cfg/rf-hr.o cfg/rf-gf.o
+iwlwifi-$(CONFIG_IWLMLD) += cfg/rf-fm.o cfg/rf-wh.o cfg/rf-pe.o
+
iwlwifi-objs += iwl-dbg-tlv.o
iwlwifi-objs += iwl-trans.o
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c
index f172ffd2a841..c029e595e7c2 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2018 - 2020, 2023 Intel Corporation
+ * Copyright(c) 2018 - 2020, 2023, 2025 Intel Corporation
*****************************************************************************/
#include <linux/module.h>
@@ -29,7 +29,7 @@
#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE "-" __stringify(api) ".ucode"
-static const struct iwl_base_params iwl1000_base_params = {
+static const struct iwl_family_base_params iwl1000_base = {
.num_of_queues = IWLAGN_NUM_QUEUES,
.max_tfd_queue_size = 256,
.eeprom_size = OTP_LOW_IMAGE_SIZE_2K,
@@ -42,12 +42,6 @@ static const struct iwl_base_params iwl1000_base_params = {
.scd_chain_ext_wa = true,
};
-static const struct iwl_ht_params iwl1000_ht_params = {
- .ht_greenfield_support = true,
- .use_rts_for_aggregation = true, /* use rts/cts protection */
- .ht40_bands = BIT(NL80211_BAND_2GHZ),
-};
-
static const struct iwl_eeprom_params iwl1000_eeprom_params = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@@ -60,54 +54,67 @@ static const struct iwl_eeprom_params iwl1000_eeprom_params = {
}
};
+const struct iwl_mac_cfg iwl1000_mac_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_1000,
+ .base = &iwl1000_base,
+};
+
#define IWL_DEVICE_1000 \
.fw_name_pre = IWL1000_FW_PRE, \
.ucode_api_max = IWL1000_UCODE_API_MAX, \
.ucode_api_min = IWL1000_UCODE_API_MIN, \
- .trans.device_family = IWL_DEVICE_FAMILY_1000, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_1000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
- .trans.base_params = &iwl1000_base_params, \
.eeprom_params = &iwl1000_eeprom_params, \
.led_mode = IWL_LED_BLINK
-const struct iwl_cfg iwl1000_bgn_cfg = {
- .name = "Intel(R) Centrino(R) Wireless-N 1000 BGN",
+const struct iwl_rf_cfg iwl1000_bgn_cfg = {
IWL_DEVICE_1000,
- .ht_params = &iwl1000_ht_params,
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .use_rts_for_aggregation = true, /* use rts/cts protection */
+ .ht40_bands = BIT(NL80211_BAND_2GHZ),
+ },
};
-const struct iwl_cfg iwl1000_bg_cfg = {
- .name = "Intel(R) Centrino(R) Wireless-N 1000 BG",
+const char iwl1000_bgn_name[] = "Intel(R) Centrino(R) Wireless-N 1000 BGN";
+
+const struct iwl_rf_cfg iwl1000_bg_cfg = {
IWL_DEVICE_1000,
};
+const char iwl1000_bg_name[] = "Intel(R) Centrino(R) Wireless-N 1000 BG";
+
#define IWL_DEVICE_100 \
.fw_name_pre = IWL100_FW_PRE, \
.ucode_api_max = IWL100_UCODE_API_MAX, \
.ucode_api_min = IWL100_UCODE_API_MIN, \
- .trans.device_family = IWL_DEVICE_FAMILY_100, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_1000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
- .trans.base_params = &iwl1000_base_params, \
.eeprom_params = &iwl1000_eeprom_params, \
.led_mode = IWL_LED_RF_STATE, \
.rx_with_siso_diversity = true
-const struct iwl_cfg iwl100_bgn_cfg = {
- .name = "Intel(R) Centrino(R) Wireless-N 100 BGN",
+const struct iwl_rf_cfg iwl100_bgn_cfg = {
IWL_DEVICE_100,
- .ht_params = &iwl1000_ht_params,
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .use_rts_for_aggregation = true, /* use rts/cts protection */
+ .ht40_bands = BIT(NL80211_BAND_2GHZ),
+ },
};
-const struct iwl_cfg iwl100_bg_cfg = {
- .name = "Intel(R) Centrino(R) Wireless-N 100 BG",
+const char iwl100_bgn_name[] = "Intel(R) Centrino(R) Wireless-N 100 BGN";
+
+const struct iwl_rf_cfg iwl100_bg_cfg = {
IWL_DEVICE_100,
};
+const char iwl100_bg_name[] = "Intel(R) Centrino(R) Wireless-N 100 BG";
+
MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL100_MODULE_FIRMWARE(IWL100_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c
index 6f3f26da0ad5..47554a5f406e 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2018 - 2020, 2023 Intel Corporation
+ * Copyright(c) 2018 - 2020, 2023, 2025 Intel Corporation
*****************************************************************************/
#include <linux/module.h>
@@ -40,7 +40,7 @@
#define IWL135_FW_PRE "iwlwifi-135"
#define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE "-" __stringify(api) ".ucode"
-static const struct iwl_base_params iwl2000_base_params = {
+static const struct iwl_family_base_params iwl2000_base = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_2K,
.num_of_queues = IWLAGN_NUM_QUEUES,
.max_tfd_queue_size = 256,
@@ -54,7 +54,7 @@ static const struct iwl_base_params iwl2000_base_params = {
};
-static const struct iwl_base_params iwl2030_base_params = {
+static const struct iwl_family_base_params iwl2030_base = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_2K,
.num_of_queues = IWLAGN_NUM_QUEUES,
.max_tfd_queue_size = 256,
@@ -67,12 +67,6 @@ static const struct iwl_base_params iwl2030_base_params = {
.scd_chain_ext_wa = true,
};
-static const struct iwl_ht_params iwl2000_ht_params = {
- .ht_greenfield_support = true,
- .use_rts_for_aggregation = true, /* use rts/cts protection */
- .ht40_bands = BIT(NL80211_BAND_2GHZ),
-};
-
static const struct iwl_eeprom_params iwl20x0_eeprom_params = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@@ -86,97 +80,119 @@ static const struct iwl_eeprom_params iwl20x0_eeprom_params = {
.enhanced_txpower = true,
};
+const struct iwl_mac_cfg iwl2000_mac_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_2000,
+ .base = &iwl2000_base,
+};
+
#define IWL_DEVICE_2000 \
.fw_name_pre = IWL2000_FW_PRE, \
.ucode_api_max = IWL2000_UCODE_API_MAX, \
.ucode_api_min = IWL2000_UCODE_API_MIN, \
- .trans.device_family = IWL_DEVICE_FAMILY_2000, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_2000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
- .trans.base_params = &iwl2000_base_params, \
.eeprom_params = &iwl20x0_eeprom_params, \
.led_mode = IWL_LED_RF_STATE
-const struct iwl_cfg iwl2000_2bgn_cfg = {
- .name = "Intel(R) Centrino(R) Wireless-N 2200 BGN",
+const struct iwl_rf_cfg iwl2000_2bgn_cfg = {
IWL_DEVICE_2000,
- .ht_params = &iwl2000_ht_params,
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .use_rts_for_aggregation = true, /* use rts/cts protection */
+ .ht40_bands = BIT(NL80211_BAND_2GHZ),
+ },
};
-const struct iwl_cfg iwl2000_2bgn_d_cfg = {
- .name = "Intel(R) Centrino(R) Wireless-N 2200D BGN",
- IWL_DEVICE_2000,
- .ht_params = &iwl2000_ht_params,
+const char iwl2000_2bgn_name[] = "Intel(R) Centrino(R) Wireless-N 2200 BGN";
+const char iwl2000_2bgn_d_name[] = "Intel(R) Centrino(R) Wireless-N 2200D BGN";
+
+const struct iwl_mac_cfg iwl2030_mac_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_2030,
+ .base = &iwl2030_base,
};
#define IWL_DEVICE_2030 \
.fw_name_pre = IWL2030_FW_PRE, \
.ucode_api_max = IWL2030_UCODE_API_MAX, \
.ucode_api_min = IWL2030_UCODE_API_MIN, \
- .trans.device_family = IWL_DEVICE_FAMILY_2030, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_2000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
- .trans.base_params = &iwl2030_base_params, \
.eeprom_params = &iwl20x0_eeprom_params, \
.led_mode = IWL_LED_RF_STATE
-const struct iwl_cfg iwl2030_2bgn_cfg = {
- .name = "Intel(R) Centrino(R) Wireless-N 2230 BGN",
+const struct iwl_rf_cfg iwl2030_2bgn_cfg = {
IWL_DEVICE_2030,
- .ht_params = &iwl2000_ht_params,
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .use_rts_for_aggregation = true, /* use rts/cts protection */
+ .ht40_bands = BIT(NL80211_BAND_2GHZ),
+ },
+};
+
+const char iwl2030_2bgn_name[] = "Intel(R) Centrino(R) Wireless-N 2230 BGN";
+
+const struct iwl_mac_cfg iwl105_mac_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_105,
+ .base = &iwl2000_base,
};
#define IWL_DEVICE_105 \
.fw_name_pre = IWL105_FW_PRE, \
.ucode_api_max = IWL105_UCODE_API_MAX, \
.ucode_api_min = IWL105_UCODE_API_MIN, \
- .trans.device_family = IWL_DEVICE_FAMILY_105, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_2000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
- .trans.base_params = &iwl2000_base_params, \
.eeprom_params = &iwl20x0_eeprom_params, \
.led_mode = IWL_LED_RF_STATE, \
.rx_with_siso_diversity = true
-const struct iwl_cfg iwl105_bgn_cfg = {
- .name = "Intel(R) Centrino(R) Wireless-N 105 BGN",
+const struct iwl_rf_cfg iwl105_bgn_cfg = {
IWL_DEVICE_105,
- .ht_params = &iwl2000_ht_params,
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .use_rts_for_aggregation = true, /* use rts/cts protection */
+ .ht40_bands = BIT(NL80211_BAND_2GHZ),
+ },
};
-const struct iwl_cfg iwl105_bgn_d_cfg = {
- .name = "Intel(R) Centrino(R) Wireless-N 105D BGN",
- IWL_DEVICE_105,
- .ht_params = &iwl2000_ht_params,
+const char iwl105_bgn_name[] = "Intel(R) Centrino(R) Wireless-N 105 BGN";
+const char iwl105_bgn_d_name[] = "Intel(R) Centrino(R) Wireless-N 105D BGN";
+
+const struct iwl_mac_cfg iwl135_mac_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_135,
+ .base = &iwl2030_base,
};
#define IWL_DEVICE_135 \
.fw_name_pre = IWL135_FW_PRE, \
.ucode_api_max = IWL135_UCODE_API_MAX, \
.ucode_api_min = IWL135_UCODE_API_MIN, \
- .trans.device_family = IWL_DEVICE_FAMILY_135, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_2000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
- .trans.base_params = &iwl2030_base_params, \
.eeprom_params = &iwl20x0_eeprom_params, \
.led_mode = IWL_LED_RF_STATE, \
.rx_with_siso_diversity = true
-const struct iwl_cfg iwl135_bgn_cfg = {
- .name = "Intel(R) Centrino(R) Wireless-N 135 BGN",
+const struct iwl_rf_cfg iwl135_bgn_cfg = {
IWL_DEVICE_135,
- .ht_params = &iwl2000_ht_params,
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .use_rts_for_aggregation = true, /* use rts/cts protection */
+ .ht40_bands = BIT(NL80211_BAND_2GHZ),
+ },
};
+const char iwl135_bgn_name[] = "Intel(R) Centrino(R) Wireless-N 135 BGN";
+
MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_MAX));
MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
index 130b9a8aa7eb..f0453f3f6ba6 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.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-2025 Intel Corporation
*/
#include <linux/module.h>
#include <linux/stringify.h>
@@ -15,40 +15,16 @@
/* Lowest firmware API version supported */
#define IWL_22000_UCODE_API_MIN 77
-/* NVM versions */
-#define IWL_22000_NVM_VERSION 0x0a1d
-
/* Memory offsets and lengths */
-#define IWL_22000_DCCM_OFFSET 0x800000 /* LMAC1 */
-#define IWL_22000_DCCM_LEN 0x10000 /* LMAC1 */
-#define IWL_22000_DCCM2_OFFSET 0x880000
-#define IWL_22000_DCCM2_LEN 0x8000
#define IWL_22000_SMEM_OFFSET 0x400000
#define IWL_22000_SMEM_LEN 0xD0000
-#define IWL_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0"
-#define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0"
-#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0"
-#define IWL_QU_C_JF_B_FW_PRE "iwlwifi-Qu-c0-jf-b0"
-#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0"
-#define IWL_QUZ_A_JF_B_FW_PRE "iwlwifi-QuZ-a0-jf-b0"
#define IWL_CC_A_FW_PRE "iwlwifi-cc-a0"
-#define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \
- IWL_QU_B_HR_B_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL_QUZ_A_HR_B_MODULE_FIRMWARE(api) \
- IWL_QUZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL_QUZ_A_JF_B_MODULE_FIRMWARE(api) \
- IWL_QUZ_A_JF_B_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL_QU_C_HR_B_MODULE_FIRMWARE(api) \
- IWL_QU_C_HR_B_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \
- IWL_QU_B_JF_B_FW_PRE "-" __stringify(api) ".ucode"
#define IWL_CC_A_MODULE_FIRMWARE(api) \
IWL_CC_A_FW_PRE "-" __stringify(api) ".ucode"
-static const struct iwl_base_params iwl_22000_base_params = {
- .eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
+static const struct iwl_family_base_params iwl_22000_base = {
.num_of_queues = 512,
.max_tfd_queue_size = 256,
.shadow_ram_support = true,
@@ -57,155 +33,77 @@ static const struct iwl_base_params iwl_22000_base_params = {
.max_event_log_size = 512,
.shadow_reg_enable = true,
.pcie_l1_allowed = true,
-};
-
-const struct iwl_ht_params iwl_22000_ht_params = {
- .stbc = true,
- .ldpc = true,
- .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ) |
- BIT(NL80211_BAND_6GHZ),
-};
-
-#define IWL_DEVICE_22000_COMMON \
- .ucode_api_min = IWL_22000_UCODE_API_MIN, \
- .led_mode = IWL_LED_RF_STATE, \
- .nvm_hw_section_num = 10, \
- .non_shared_ant = ANT_B, \
- .dccm_offset = IWL_22000_DCCM_OFFSET, \
- .dccm_len = IWL_22000_DCCM_LEN, \
- .dccm2_offset = IWL_22000_DCCM2_OFFSET, \
- .dccm2_len = IWL_22000_DCCM2_LEN, \
- .smem_offset = IWL_22000_SMEM_OFFSET, \
- .smem_len = IWL_22000_SMEM_LEN, \
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
- .apmg_not_supported = true, \
- .trans.mq_rx_supported = true, \
- .vht_mu_mimo_supported = true, \
- .mac_addr_from_csr = 0x380, \
- .ht_params = &iwl_22000_ht_params, \
- .nvm_ver = IWL_22000_NVM_VERSION, \
- .trans.rf_id = true, \
- .trans.gen2 = true, \
- .nvm_type = IWL_NVM_EXT, \
- .dbgc_supported = true, \
- .min_umac_error_event_table = 0x400000, \
- .d3_debug_data_base_addr = 0x401000, \
- .d3_debug_data_length = 60 * 1024, \
- .mon_smem_regs = { \
- .write_ptr = { \
- .addr = LDBG_M2S_BUF_WPTR, \
- .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
- }, \
- .cycle_cnt = { \
- .addr = LDBG_M2S_BUF_WRAP_CNT, \
- .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
- }, \
- }
-
-#define IWL_DEVICE_22500 \
- IWL_DEVICE_22000_COMMON, \
- .ucode_api_max = IWL_22000_UCODE_API_MAX, \
- .trans.device_family = IWL_DEVICE_FAMILY_22000, \
- .trans.base_params = &iwl_22000_base_params, \
- .gp2_reg_addr = 0xa02c68, \
- .mon_dram_regs = { \
- .write_ptr = { \
- .addr = MON_BUFF_WRPTR_VER2, \
- .mask = 0xffffffff, \
- }, \
- .cycle_cnt = { \
- .addr = MON_BUFF_CYCLE_CNT_VER2, \
- .mask = 0xffffffff, \
- }, \
- }
-
-const struct iwl_cfg_trans_params iwl_qu_trans_cfg = {
+ .smem_offset = IWL_22000_SMEM_OFFSET,
+ .smem_len = IWL_22000_SMEM_LEN,
+ .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
+ .apmg_not_supported = true,
+ .mac_addr_from_csr = 0x380,
+ .d3_debug_data_base_addr = 0x401000,
+ .d3_debug_data_length = 60 * 1024,
+ .mon_smem_regs = {
+ .write_ptr = {
+ .addr = LDBG_M2S_BUF_WPTR,
+ .mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
+ },
+ .cycle_cnt = {
+ .addr = LDBG_M2S_BUF_WRAP_CNT,
+ .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
+ },
+ },
+ .gp2_reg_addr = 0xa02c68,
+ .mon_dram_regs = {
+ .write_ptr = {
+ .addr = MON_BUFF_WRPTR_VER2,
+ .mask = 0xffffffff,
+ },
+ .cycle_cnt = {
+ .addr = MON_BUFF_CYCLE_CNT_VER2,
+ .mask = 0xffffffff,
+ },
+ },
+ .ucode_api_min = IWL_22000_UCODE_API_MIN,
+ .ucode_api_max = IWL_22000_UCODE_API_MAX,
+};
+
+const struct iwl_mac_cfg iwl_qu_mac_cfg = {
.mq_rx_supported = true,
- .rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_22000,
- .base_params = &iwl_22000_base_params,
+ .base = &iwl_22000_base,
.integrated = true,
.xtal_latency = 500,
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_200US,
};
-const struct iwl_cfg_trans_params iwl_qu_medium_latency_trans_cfg = {
+const struct iwl_mac_cfg iwl_qu_medium_latency_mac_cfg = {
.mq_rx_supported = true,
- .rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_22000,
- .base_params = &iwl_22000_base_params,
+ .base = &iwl_22000_base,
.integrated = true,
.xtal_latency = 1820,
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_1820US,
};
-const struct iwl_cfg_trans_params iwl_qu_long_latency_trans_cfg = {
+const struct iwl_mac_cfg iwl_qu_long_latency_mac_cfg = {
.mq_rx_supported = true,
- .rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_22000,
- .base_params = &iwl_22000_base_params,
+ .base = &iwl_22000_base,
.integrated = true,
.xtal_latency = 12000,
.low_latency_xtal = true,
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
};
-/*
- * If the device doesn't support HE, no need to have that many buffers.
- * 22000 devices can split multiple frames into a single RB, so fewer are
- * needed; AX210 cannot (but use smaller RBs by default) - these sizes
- * were picked according to 8 MSDUs inside 256 A-MSDUs in an A-MPDU, with
- * additional overhead to account for processing time.
- */
-#define IWL_NUM_RBDS_NON_HE 512
-#define IWL_NUM_RBDS_22000_HE 2048
-
-/*
- * All JF radio modules are part of the 9000 series, but the MAC part
- * looks more like 22000. That's why this device is here, but called
- * 9560 nevertheless.
- */
-const struct iwl_cfg iwl9560_qu_b0_jf_b0_cfg = {
- .fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
- IWL_DEVICE_22500,
- .num_rbds = IWL_NUM_RBDS_NON_HE,
-};
-
-const struct iwl_cfg iwl9560_qu_c0_jf_b0_cfg = {
- .fw_name_pre = IWL_QU_C_JF_B_FW_PRE,
- IWL_DEVICE_22500,
- .num_rbds = IWL_NUM_RBDS_NON_HE,
-};
-
-const struct iwl_cfg iwl9560_quz_a0_jf_b0_cfg = {
- .fw_name_pre = IWL_QUZ_A_JF_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_NON_HE,
-};
-
-const struct iwl_cfg_trans_params iwl_ax200_trans_cfg = {
+const struct iwl_mac_cfg iwl_ax200_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_22000,
- .base_params = &iwl_22000_base_params,
+ .base = &iwl_22000_base,
.mq_rx_supported = true,
- .rf_id = true,
.gen2 = true,
.bisr_workaround = 1,
};
-const char iwl_ax101_name[] = "Intel(R) Wi-Fi 6 AX101";
-const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz";
-const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz";
-const char iwl_ax203_name[] = "Intel(R) Wi-Fi 6 AX203";
-
const char iwl_ax200_killer_1650w_name[] =
"Killer(R) Wi-Fi 6 AX1650w 160MHz Wireless Network Adapter (200D2W)";
const char iwl_ax200_killer_1650x_name[] =
@@ -215,213 +113,4 @@ const char iwl_ax201_killer_1650s_name[] =
const char iwl_ax201_killer_1650i_name[] =
"Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)";
-const struct iwl_cfg iwl_qu_b0_hr1_b0 = {
- .fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .tx_with_siso_diversity = true,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-const struct iwl_cfg iwl_qu_b0_hr_b0 = {
- .fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-const struct iwl_cfg iwl_ax201_cfg_qu_hr = {
- .name = "Intel(R) Wi-Fi 6 AX201 160MHz",
- .fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-const struct iwl_cfg iwl_qu_c0_hr1_b0 = {
- .fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .tx_with_siso_diversity = true,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-const struct iwl_cfg iwl_qu_c0_hr_b0 = {
- .fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-const struct iwl_cfg iwl_ax201_cfg_qu_c0_hr_b0 = {
- .name = "Intel(R) Wi-Fi 6 AX201 160MHz",
- .fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-const struct iwl_cfg iwl_quz_a0_hr1_b0 = {
- .fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .tx_with_siso_diversity = true,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-const struct iwl_cfg iwl_ax201_cfg_quz_hr = {
- .name = "Intel(R) Wi-Fi 6 AX201 160MHz",
- .fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-const struct iwl_cfg iwl_ax1650s_cfg_quz_hr = {
- .name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)",
- .fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-const struct iwl_cfg iwl_ax1650i_cfg_quz_hr = {
- .name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)",
- .fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-const struct iwl_cfg iwl_ax200_cfg_cc = {
- .fw_name_pre = IWL_CC_A_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = {
- .name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201NGW)",
- .fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = {
- .name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201D2W)",
- .fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0 = {
- .name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201NGW)",
- .fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0 = {
- .name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201D2W)",
- .fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-const struct iwl_cfg iwl_cfg_quz_a0_hr_b0 = {
- .fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_QUZ_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c
index de7ede59a994..aaae3b1f5433 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2018 - 2020, 2023 Intel Corporation
+ * Copyright(c) 2018 - 2020, 2023, 2025 Intel Corporation
*****************************************************************************/
#include <linux/module.h>
@@ -30,7 +30,7 @@
#define IWL5150_FW_PRE "iwlwifi-5150"
#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE "-" __stringify(api) ".ucode"
-static const struct iwl_base_params iwl5000_base_params = {
+static const struct iwl_family_base_params iwl5000_base = {
.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
.num_of_queues = IWLAGN_NUM_QUEUES,
.max_tfd_queue_size = 256,
@@ -41,11 +41,6 @@ static const struct iwl_base_params iwl5000_base_params = {
.scd_chain_ext_wa = true,
};
-static const struct iwl_ht_params iwl5000_ht_params = {
- .ht_greenfield_support = true,
- .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
-};
-
static const struct iwl_eeprom_params iwl5000_eeprom_params = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@@ -58,93 +53,107 @@ static const struct iwl_eeprom_params iwl5000_eeprom_params = {
},
};
+const struct iwl_mac_cfg iwl5000_mac_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_5000,
+ .base = &iwl5000_base,
+};
+
#define IWL_DEVICE_5000 \
.fw_name_pre = IWL5000_FW_PRE, \
.ucode_api_max = IWL5000_UCODE_API_MAX, \
.ucode_api_min = IWL5000_UCODE_API_MIN, \
- .trans.device_family = IWL_DEVICE_FAMILY_5000, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_5000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_5000_TX_POWER_VERSION, \
- .trans.base_params = &iwl5000_base_params, \
.eeprom_params = &iwl5000_eeprom_params, \
.led_mode = IWL_LED_BLINK
-const struct iwl_cfg iwl5300_agn_cfg = {
- .name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
+const struct iwl_rf_cfg iwl5300_agn_cfg = {
IWL_DEVICE_5000,
/* at least EEPROM 0x11A has wrong info */
.valid_tx_ant = ANT_ABC, /* .cfg overwrite */
.valid_rx_ant = ANT_ABC, /* .cfg overwrite */
- .ht_params = &iwl5000_ht_params,
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
};
-const struct iwl_cfg iwl5100_bgn_cfg = {
- .name = "Intel(R) WiFi Link 5100 BGN",
- IWL_DEVICE_5000,
- .valid_tx_ant = ANT_B, /* .cfg overwrite */
- .valid_rx_ant = ANT_AB, /* .cfg overwrite */
- .ht_params = &iwl5000_ht_params,
-};
+const char iwl5300_agn_name[] = "Intel(R) Ultimate N WiFi Link 5300 AGN";
-const struct iwl_cfg iwl5100_abg_cfg = {
- .name = "Intel(R) WiFi Link 5100 ABG",
+const struct iwl_rf_cfg iwl5100_n_cfg = {
IWL_DEVICE_5000,
.valid_tx_ant = ANT_B, /* .cfg overwrite */
.valid_rx_ant = ANT_AB, /* .cfg overwrite */
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
};
-const struct iwl_cfg iwl5100_agn_cfg = {
- .name = "Intel(R) WiFi Link 5100 AGN",
+const char iwl5100_bgn_name[] = "Intel(R) WiFi Link 5100 BGN";
+
+const struct iwl_rf_cfg iwl5100_abg_cfg = {
IWL_DEVICE_5000,
.valid_tx_ant = ANT_B, /* .cfg overwrite */
.valid_rx_ant = ANT_AB, /* .cfg overwrite */
- .ht_params = &iwl5000_ht_params,
};
-const struct iwl_cfg iwl5350_agn_cfg = {
- .name = "Intel(R) WiMAX/WiFi Link 5350 AGN",
+const char iwl5100_abg_name[] = "Intel(R) WiFi Link 5100 ABG";
+const char iwl5100_agn_name[] = "Intel(R) WiFi Link 5100 AGN";
+
+const struct iwl_rf_cfg iwl5350_agn_cfg = {
.fw_name_pre = IWL5000_FW_PRE,
.ucode_api_max = IWL5000_UCODE_API_MAX,
.ucode_api_min = IWL5000_UCODE_API_MIN,
- .trans.device_family = IWL_DEVICE_FAMILY_5000,
.max_inst_size = IWLAGN_RTC_INST_SIZE,
.max_data_size = IWLAGN_RTC_DATA_SIZE,
.nvm_ver = EEPROM_5050_EEPROM_VERSION,
.nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION,
- .trans.base_params = &iwl5000_base_params,
.eeprom_params = &iwl5000_eeprom_params,
- .ht_params = &iwl5000_ht_params,
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
.led_mode = IWL_LED_BLINK,
.internal_wimax_coex = true,
};
+const char iwl5350_agn_name[] = "Intel(R) WiMAX/WiFi Link 5350 AGN";
+
+const struct iwl_mac_cfg iwl5150_mac_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_5150,
+ .base = &iwl5000_base,
+};
+
#define IWL_DEVICE_5150 \
.fw_name_pre = IWL5150_FW_PRE, \
.ucode_api_max = IWL5150_UCODE_API_MAX, \
.ucode_api_min = IWL5150_UCODE_API_MIN, \
- .trans.device_family = IWL_DEVICE_FAMILY_5150, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_5050_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION, \
- .trans.base_params = &iwl5000_base_params, \
.eeprom_params = &iwl5000_eeprom_params, \
.led_mode = IWL_LED_BLINK, \
.internal_wimax_coex = true
-const struct iwl_cfg iwl5150_agn_cfg = {
- .name = "Intel(R) WiMAX/WiFi Link 5150 AGN",
+const struct iwl_rf_cfg iwl5150_agn_cfg = {
IWL_DEVICE_5150,
- .ht_params = &iwl5000_ht_params,
-
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
};
-const struct iwl_cfg iwl5150_abg_cfg = {
- .name = "Intel(R) WiMAX/WiFi Link 5150 ABG",
+const char iwl5150_agn_name[] = "Intel(R) WiMAX/WiFi Link 5150 AGN";
+
+const struct iwl_rf_cfg iwl5150_abg_cfg = {
IWL_DEVICE_5150,
};
+const char iwl5150_abg_name[] = "Intel(R) WiMAX/WiFi Link 5150 ABG";
+
MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
index f013cf420569..ab13394896e0 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2018 - 2020, 2023 Intel Corporation
+ * Copyright(c) 2018 - 2020, 2023, 2025 Intel Corporation
*****************************************************************************/
#include <linux/module.h>
@@ -49,7 +49,7 @@
#define IWL6030_FW_PRE "iwlwifi-6000g2b"
#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE "-" __stringify(api) ".ucode"
-static const struct iwl_base_params iwl6000_base_params = {
+static const struct iwl_family_base_params iwl6000_base = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_2K,
.num_of_queues = IWLAGN_NUM_QUEUES,
.max_tfd_queue_size = 256,
@@ -62,7 +62,7 @@ static const struct iwl_base_params iwl6000_base_params = {
.scd_chain_ext_wa = true,
};
-static const struct iwl_base_params iwl6050_base_params = {
+static const struct iwl_family_base_params iwl6050_base = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_2K,
.num_of_queues = IWLAGN_NUM_QUEUES,
.max_tfd_queue_size = 256,
@@ -75,7 +75,7 @@ static const struct iwl_base_params iwl6050_base_params = {
.scd_chain_ext_wa = true,
};
-static const struct iwl_base_params iwl6000_g2_base_params = {
+static const struct iwl_family_base_params iwl6000_g2_base = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_2K,
.num_of_queues = IWLAGN_NUM_QUEUES,
.max_tfd_queue_size = 256,
@@ -88,12 +88,6 @@ static const struct iwl_base_params iwl6000_g2_base_params = {
.scd_chain_ext_wa = true,
};
-static const struct iwl_ht_params iwl6000_ht_params = {
- .ht_greenfield_support = true,
- .use_rts_for_aggregation = true, /* use rts/cts protection */
- .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
-};
-
static const struct iwl_eeprom_params iwl6000_eeprom_params = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@@ -107,141 +101,126 @@ static const struct iwl_eeprom_params iwl6000_eeprom_params = {
.enhanced_txpower = true,
};
+const struct iwl_mac_cfg iwl6005_mac_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_6005,
+ .base = &iwl6000_g2_base,
+};
+
#define IWL_DEVICE_6005 \
.fw_name_pre = IWL6005_FW_PRE, \
.ucode_api_max = IWL6000G2_UCODE_API_MAX, \
.ucode_api_min = IWL6000G2_UCODE_API_MIN, \
- .trans.device_family = IWL_DEVICE_FAMILY_6005, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_6005_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6005_TX_POWER_VERSION, \
- .trans.base_params = &iwl6000_g2_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_RF_STATE
-const struct iwl_cfg iwl6005_2agn_cfg = {
- .name = "Intel(R) Centrino(R) Advanced-N 6205 AGN",
- IWL_DEVICE_6005,
- .ht_params = &iwl6000_ht_params,
-};
-
-const struct iwl_cfg iwl6005_2abg_cfg = {
- .name = "Intel(R) Centrino(R) Advanced-N 6205 ABG",
- IWL_DEVICE_6005,
-};
-
-const struct iwl_cfg iwl6005_2bg_cfg = {
- .name = "Intel(R) Centrino(R) Advanced-N 6205 BG",
+const struct iwl_rf_cfg iwl6005_n_cfg = {
IWL_DEVICE_6005,
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .use_rts_for_aggregation = true, /* use rts/cts protection */
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
};
-const struct iwl_cfg iwl6005_2agn_sff_cfg = {
- .name = "Intel(R) Centrino(R) Advanced-N 6205S AGN",
- IWL_DEVICE_6005,
- .ht_params = &iwl6000_ht_params,
-};
+const char iwl6005_2agn_name[] = "Intel(R) Centrino(R) Advanced-N 6205 AGN";
+const char iwl6005_2agn_sff_name[] = "Intel(R) Centrino(R) Advanced-N 6205S AGN";
+const char iwl6005_2agn_d_name[] = "Intel(R) Centrino(R) Advanced-N 6205D AGN";
+const char iwl6005_2agn_mow1_name[] = "Intel(R) Centrino(R) Advanced-N 6206 AGN";
+const char iwl6005_2agn_mow2_name[] = "Intel(R) Centrino(R) Advanced-N 6207 AGN";
-const struct iwl_cfg iwl6005_2agn_d_cfg = {
- .name = "Intel(R) Centrino(R) Advanced-N 6205D AGN",
+const struct iwl_rf_cfg iwl6005_non_n_cfg = {
IWL_DEVICE_6005,
- .ht_params = &iwl6000_ht_params,
};
-const struct iwl_cfg iwl6005_2agn_mow1_cfg = {
- .name = "Intel(R) Centrino(R) Advanced-N 6206 AGN",
- IWL_DEVICE_6005,
- .ht_params = &iwl6000_ht_params,
-};
+const char iwl6005_2abg_name[] = "Intel(R) Centrino(R) Advanced-N 6205 ABG";
+const char iwl6005_2bg_name[] = "Intel(R) Centrino(R) Advanced-N 6205 BG";
-const struct iwl_cfg iwl6005_2agn_mow2_cfg = {
- .name = "Intel(R) Centrino(R) Advanced-N 6207 AGN",
- IWL_DEVICE_6005,
- .ht_params = &iwl6000_ht_params,
+const struct iwl_mac_cfg iwl6030_mac_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_6030,
+ .base = &iwl6000_g2_base,
};
#define IWL_DEVICE_6030 \
.fw_name_pre = IWL6030_FW_PRE, \
.ucode_api_max = IWL6000G2_UCODE_API_MAX, \
.ucode_api_min = IWL6000G2_UCODE_API_MIN, \
- .trans.device_family = IWL_DEVICE_FAMILY_6030, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_6030_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \
- .trans.base_params = &iwl6000_g2_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_RF_STATE
-const struct iwl_cfg iwl6030_2agn_cfg = {
- .name = "Intel(R) Centrino(R) Advanced-N 6230 AGN",
+const struct iwl_rf_cfg iwl6030_n_cfg = {
IWL_DEVICE_6030,
- .ht_params = &iwl6000_ht_params,
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .use_rts_for_aggregation = true, /* use rts/cts protection */
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
};
-const struct iwl_cfg iwl6030_2abg_cfg = {
- .name = "Intel(R) Centrino(R) Advanced-N 6230 ABG",
- IWL_DEVICE_6030,
-};
+const char iwl6030_2agn_name[] = "Intel(R) Centrino(R) Advanced-N 6230 AGN";
+const char iwl6030_2bgn_name[] = "Intel(R) Centrino(R) Advanced-N 6230 BGN";
+const char iwl1030_bgn_name[] = "Intel(R) Centrino(R) Wireless-N 1030 BGN";
+const char iwl1030_bg_name[] = "Intel(R) Centrino(R) Wireless-N 1030 BG";
-const struct iwl_cfg iwl6030_2bgn_cfg = {
- .name = "Intel(R) Centrino(R) Advanced-N 6230 BGN",
+const struct iwl_rf_cfg iwl6030_non_n_cfg = {
IWL_DEVICE_6030,
- .ht_params = &iwl6000_ht_params,
};
-const struct iwl_cfg iwl6030_2bg_cfg = {
- .name = "Intel(R) Centrino(R) Advanced-N 6230 BG",
- IWL_DEVICE_6030,
-};
+const char iwl6030_2abg_name[] = "Intel(R) Centrino(R) Advanced-N 6230 ABG";
+const char iwl6030_2bg_name[] = "Intel(R) Centrino(R) Advanced-N 6230 BG";
#define IWL_DEVICE_6035 \
.fw_name_pre = IWL6030_FW_PRE, \
.ucode_api_max = IWL6035_UCODE_API_MAX, \
.ucode_api_min = IWL6035_UCODE_API_MIN, \
- .trans.device_family = IWL_DEVICE_FAMILY_6030, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_6030_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \
- .trans.base_params = &iwl6000_g2_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_RF_STATE
-const struct iwl_cfg iwl6035_2agn_cfg = {
- .name = "Intel(R) Centrino(R) Advanced-N 6235 AGN",
+const struct iwl_rf_cfg iwl6035_2agn_cfg = {
IWL_DEVICE_6035,
- .ht_params = &iwl6000_ht_params,
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .use_rts_for_aggregation = true, /* use rts/cts protection */
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
};
-const struct iwl_cfg iwl6035_2agn_sff_cfg = {
- .name = "Intel(R) Centrino(R) Ultimate-N 6235 AGN",
- IWL_DEVICE_6035,
- .ht_params = &iwl6000_ht_params,
-};
+const char iwl6035_2agn_name[] = "Intel(R) Centrino(R) Advanced-N 6235 AGN";
+const char iwl6035_2agn_sff_name[] = "Intel(R) Centrino(R) Ultimate-N 6235 AGN";
-const struct iwl_cfg iwl1030_bgn_cfg = {
- .name = "Intel(R) Centrino(R) Wireless-N 1030 BGN",
+const struct iwl_rf_cfg iwl130_bgn_cfg = {
IWL_DEVICE_6030,
- .ht_params = &iwl6000_ht_params,
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .use_rts_for_aggregation = true, /* use rts/cts protection */
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
+ .rx_with_siso_diversity = true,
};
-const struct iwl_cfg iwl1030_bg_cfg = {
- .name = "Intel(R) Centrino(R) Wireless-N 1030 BG",
- IWL_DEVICE_6030,
-};
+const char iwl130_bgn_name[] = "Intel(R) Centrino(R) Wireless-N 130 BGN";
-const struct iwl_cfg iwl130_bgn_cfg = {
- .name = "Intel(R) Centrino(R) Wireless-N 130 BGN",
+const struct iwl_rf_cfg iwl130_bg_cfg = {
IWL_DEVICE_6030,
- .ht_params = &iwl6000_ht_params,
.rx_with_siso_diversity = true,
};
-const struct iwl_cfg iwl130_bg_cfg = {
- .name = "Intel(R) Centrino(R) Wireless-N 130 BG",
- IWL_DEVICE_6030,
- .rx_with_siso_diversity = true,
+const char iwl130_bg_name[] = "Intel(R) Centrino(R) Wireless-N 130 BG";
+
+const struct iwl_mac_cfg iwl6000i_mac_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_6000i,
+ .base = &iwl6000_base,
};
/*
@@ -251,101 +230,127 @@ const struct iwl_cfg iwl130_bg_cfg = {
.fw_name_pre = IWL6000_FW_PRE, \
.ucode_api_max = IWL6000_UCODE_API_MAX, \
.ucode_api_min = IWL6000_UCODE_API_MIN, \
- .trans.device_family = IWL_DEVICE_FAMILY_6000i, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.valid_tx_ant = ANT_BC, /* .cfg overwrite */ \
.valid_rx_ant = ANT_BC, /* .cfg overwrite */ \
.nvm_ver = EEPROM_6000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6000_TX_POWER_VERSION, \
- .trans.base_params = &iwl6000_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_BLINK
-const struct iwl_cfg iwl6000i_2agn_cfg = {
- .name = "Intel(R) Centrino(R) Advanced-N 6200 AGN",
+const struct iwl_rf_cfg iwl6000i_2agn_cfg = {
IWL_DEVICE_6000i,
- .ht_params = &iwl6000_ht_params,
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .use_rts_for_aggregation = true, /* use rts/cts protection */
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
};
-const struct iwl_cfg iwl6000i_2abg_cfg = {
- .name = "Intel(R) Centrino(R) Advanced-N 6200 ABG",
+const char iwl6000i_2agn_name[] = "Intel(R) Centrino(R) Advanced-N 6200 AGN";
+
+const struct iwl_rf_cfg iwl6000i_non_n_cfg = {
IWL_DEVICE_6000i,
};
-const struct iwl_cfg iwl6000i_2bg_cfg = {
- .name = "Intel(R) Centrino(R) Advanced-N 6200 BG",
- IWL_DEVICE_6000i,
+const char iwl6000i_2abg_name[] = "Intel(R) Centrino(R) Advanced-N 6200 ABG";
+const char iwl6000i_2bg_name[] = "Intel(R) Centrino(R) Advanced-N 6200 BG";
+
+const struct iwl_mac_cfg iwl6050_mac_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_6050,
+ .base = &iwl6050_base,
};
#define IWL_DEVICE_6050 \
.fw_name_pre = IWL6050_FW_PRE, \
.ucode_api_max = IWL6050_UCODE_API_MAX, \
.ucode_api_min = IWL6050_UCODE_API_MIN, \
- .trans.device_family = IWL_DEVICE_FAMILY_6050, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.valid_tx_ant = ANT_AB, /* .cfg overwrite */ \
.valid_rx_ant = ANT_AB, /* .cfg overwrite */ \
.nvm_ver = EEPROM_6050_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6050_TX_POWER_VERSION, \
- .trans.base_params = &iwl6050_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_BLINK, \
.internal_wimax_coex = true
-const struct iwl_cfg iwl6050_2agn_cfg = {
- .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN",
+const struct iwl_rf_cfg iwl6050_2agn_cfg = {
IWL_DEVICE_6050,
- .ht_params = &iwl6000_ht_params,
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .use_rts_for_aggregation = true, /* use rts/cts protection */
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
};
-const struct iwl_cfg iwl6050_2abg_cfg = {
- .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG",
+const char iwl6050_2agn_name[] = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN";
+
+const struct iwl_rf_cfg iwl6050_2abg_cfg = {
IWL_DEVICE_6050,
};
+const char iwl6050_2abg_name[] = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG";
+
+const struct iwl_mac_cfg iwl6150_mac_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_6150,
+ .base = &iwl6050_base,
+};
+
#define IWL_DEVICE_6150 \
.fw_name_pre = IWL6050_FW_PRE, \
.ucode_api_max = IWL6050_UCODE_API_MAX, \
.ucode_api_min = IWL6050_UCODE_API_MIN, \
- .trans.device_family = IWL_DEVICE_FAMILY_6150, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_6150_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6150_TX_POWER_VERSION, \
- .trans.base_params = &iwl6050_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_BLINK, \
.internal_wimax_coex = true
-const struct iwl_cfg iwl6150_bgn_cfg = {
- .name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN",
+const struct iwl_rf_cfg iwl6150_bgn_cfg = {
IWL_DEVICE_6150,
- .ht_params = &iwl6000_ht_params,
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .use_rts_for_aggregation = true, /* use rts/cts protection */
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
};
-const struct iwl_cfg iwl6150_bg_cfg = {
- .name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BG",
+const char iwl6150_bgn_name[] = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN";
+
+const struct iwl_rf_cfg iwl6150_bg_cfg = {
IWL_DEVICE_6150,
};
-const struct iwl_cfg iwl6000_3agn_cfg = {
- .name = "Intel(R) Centrino(R) Ultimate-N 6300 AGN",
+const char iwl6150_bg_name[] = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BG";
+
+const struct iwl_mac_cfg iwl6000_mac_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_6000,
+ .base = &iwl6000_base,
+};
+
+const struct iwl_rf_cfg iwl6000_3agn_cfg = {
.fw_name_pre = IWL6000_FW_PRE,
.ucode_api_max = IWL6000_UCODE_API_MAX,
.ucode_api_min = IWL6000_UCODE_API_MIN,
- .trans.device_family = IWL_DEVICE_FAMILY_6000,
.max_inst_size = IWL60_RTC_INST_SIZE,
.max_data_size = IWL60_RTC_DATA_SIZE,
.nvm_ver = EEPROM_6000_EEPROM_VERSION,
.nvm_calib_ver = EEPROM_6000_TX_POWER_VERSION,
- .trans.base_params = &iwl6000_base_params,
.eeprom_params = &iwl6000_eeprom_params,
- .ht_params = &iwl6000_ht_params,
+ .ht_params = {
+ .ht_greenfield_support = true,
+ .use_rts_for_aggregation = true, /* use rts/cts protection */
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
.led_mode = IWL_LED_BLINK,
};
+const char iwl6000_3agn_name[] = "Intel(R) Centrino(R) Ultimate-N 6300 AGN";
+
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX));
MODULE_FIRMWARE(IWL6005_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c
index 4e2afdedf4c6..f987ad3192c1 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2020, 2023 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2020, 2023, 2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015 Intel Deutschland GmbH
*/
@@ -49,7 +49,7 @@
#define IWL7265D_FW_PRE "iwlwifi-7265D"
#define IWL7265D_MODULE_FIRMWARE(api) IWL7265D_FW_PRE "-" __stringify(api) ".ucode"
-static const struct iwl_base_params iwl7000_base_params = {
+static const struct iwl_family_base_params iwl7000_base = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_16K,
.num_of_queues = 31,
.max_tfd_queue_size = 256,
@@ -60,6 +60,7 @@ static const struct iwl_base_params iwl7000_base_params = {
.shadow_reg_enable = true,
.pcie_l1_allowed = true,
.apmg_wake_up_wa = true,
+ .nvm_hw_section_num = 0,
};
static const struct iwl_tt_params iwl7000_high_temp_tt_params = {
@@ -84,16 +85,13 @@ static const struct iwl_tt_params iwl7000_high_temp_tt_params = {
.support_tx_backoff = true,
};
-static const struct iwl_ht_params iwl7000_ht_params = {
- .stbc = true,
- .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+const struct iwl_mac_cfg iwl7000_mac_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_7000,
+ .base = &iwl7000_base,
};
#define IWL_DEVICE_7000_COMMON \
- .trans.device_family = IWL_DEVICE_FAMILY_7000, \
- .trans.base_params = &iwl7000_base_params, \
.led_mode = IWL_LED_RF_STATE, \
- .nvm_hw_section_num = 0, \
.non_shared_ant = ANT_A, \
.dccm_offset = IWL7000_DCCM_OFFSET
@@ -117,77 +115,52 @@ static const struct iwl_ht_params iwl7000_ht_params = {
.ucode_api_max = IWL7265D_UCODE_API_MAX, \
.ucode_api_min = IWL7265D_UCODE_API_MIN
-const struct iwl_cfg iwl7260_2ac_cfg = {
- .name = "Intel(R) Dual Band Wireless AC 7260",
+const char iwl7260_2ac_name[] = "Intel(R) Dual Band Wireless AC 7260";
+const char iwl7260_2n_name[] = "Intel(R) Dual Band Wireless N 7260";
+const char iwl7260_n_name[] = "Intel(R) Wireless N 7260";
+const char iwl3160_2ac_name[] = "Intel(R) Dual Band Wireless AC 3160";
+const char iwl3160_2n_name[] = "Intel(R) Dual Band Wireless N 3160";
+const char iwl3160_n_name[] = "Intel(R) Wireless N 3160";
+const char iwl3165_2ac_name[] = "Intel(R) Dual Band Wireless-AC 3165";
+const char iwl3168_2ac_name[] = "Intel(R) Dual Band Wireless-AC 3168";
+const char iwl7265_2ac_name[] = "Intel(R) Dual Band Wireless-AC 7265";
+const char iwl7265_2n_name[] = "Intel(R) Dual Band Wireless-N 7265";
+const char iwl7265_n_name[] = "Intel(R) Wireless-N 7265";
+
+const struct iwl_rf_cfg iwl7260_cfg = {
.fw_name_pre = IWL7260_FW_PRE,
IWL_DEVICE_7000,
- .ht_params = &iwl7000_ht_params,
+ .ht_params = {
+ .stbc = true,
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
.nvm_ver = IWL7260_NVM_VERSION,
.host_interrupt_operation_mode = true,
.lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
};
-const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
- .name = "Intel(R) Dual Band Wireless AC 7260",
+const struct iwl_rf_cfg iwl7260_high_temp_cfg = {
.fw_name_pre = IWL7260_FW_PRE,
IWL_DEVICE_7000,
- .ht_params = &iwl7000_ht_params,
+ .ht_params = {
+ .stbc = true,
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
.nvm_ver = IWL7260_NVM_VERSION,
- .high_temp = true,
.host_interrupt_operation_mode = true,
.lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
.thermal_params = &iwl7000_high_temp_tt_params,
};
-const struct iwl_cfg iwl7260_2n_cfg = {
- .name = "Intel(R) Dual Band Wireless N 7260",
- .fw_name_pre = IWL7260_FW_PRE,
- IWL_DEVICE_7000,
- .ht_params = &iwl7000_ht_params,
- .nvm_ver = IWL7260_NVM_VERSION,
- .host_interrupt_operation_mode = true,
- .lp_xtal_workaround = true,
- .dccm_len = IWL7260_DCCM_LEN,
-};
-
-const struct iwl_cfg iwl7260_n_cfg = {
- .name = "Intel(R) Wireless N 7260",
- .fw_name_pre = IWL7260_FW_PRE,
- IWL_DEVICE_7000,
- .ht_params = &iwl7000_ht_params,
- .nvm_ver = IWL7260_NVM_VERSION,
- .host_interrupt_operation_mode = true,
- .lp_xtal_workaround = true,
- .dccm_len = IWL7260_DCCM_LEN,
-};
-
-const struct iwl_cfg iwl3160_2ac_cfg = {
- .name = "Intel(R) Dual Band Wireless AC 3160",
+const struct iwl_rf_cfg iwl3160_cfg = {
.fw_name_pre = IWL3160_FW_PRE,
IWL_DEVICE_7000,
- .ht_params = &iwl7000_ht_params,
- .nvm_ver = IWL3160_NVM_VERSION,
- .host_interrupt_operation_mode = true,
- .dccm_len = IWL3160_DCCM_LEN,
-};
-
-const struct iwl_cfg iwl3160_2n_cfg = {
- .name = "Intel(R) Dual Band Wireless N 3160",
- .fw_name_pre = IWL3160_FW_PRE,
- IWL_DEVICE_7000,
- .ht_params = &iwl7000_ht_params,
- .nvm_ver = IWL3160_NVM_VERSION,
- .host_interrupt_operation_mode = true,
- .dccm_len = IWL3160_DCCM_LEN,
-};
-
-const struct iwl_cfg iwl3160_n_cfg = {
- .name = "Intel(R) Wireless N 3160",
- .fw_name_pre = IWL3160_FW_PRE,
- IWL_DEVICE_7000,
- .ht_params = &iwl7000_ht_params,
+ .ht_params = {
+ .stbc = true,
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
.nvm_ver = IWL3160_NVM_VERSION,
.host_interrupt_operation_mode = true,
.dccm_len = IWL3160_DCCM_LEN,
@@ -204,88 +177,52 @@ static const struct iwl_pwr_tx_backoff iwl7265_pwr_tx_backoffs[] = {
{0},
};
-static const struct iwl_ht_params iwl7265_ht_params = {
- .stbc = true,
- .ldpc = true,
- .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
-};
-
-const struct iwl_cfg iwl3165_2ac_cfg = {
- .name = "Intel(R) Dual Band Wireless AC 3165",
+const struct iwl_rf_cfg iwl3165_2ac_cfg = {
.fw_name_pre = IWL7265D_FW_PRE,
IWL_DEVICE_7005D,
- .ht_params = &iwl7000_ht_params,
+ .ht_params = {
+ .stbc = true,
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
.nvm_ver = IWL3165_NVM_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
-const struct iwl_cfg iwl3168_2ac_cfg = {
- .name = "Intel(R) Dual Band Wireless AC 3168",
+const struct iwl_rf_cfg iwl3168_2ac_cfg = {
.fw_name_pre = IWL3168_FW_PRE,
IWL_DEVICE_3008,
- .ht_params = &iwl7000_ht_params,
+ .ht_params = {
+ .stbc = true,
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
.nvm_ver = IWL3168_NVM_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
.nvm_type = IWL_NVM_SDP,
};
-const struct iwl_cfg iwl7265_2ac_cfg = {
- .name = "Intel(R) Dual Band Wireless AC 7265",
- .fw_name_pre = IWL7265_FW_PRE,
- IWL_DEVICE_7005,
- .ht_params = &iwl7265_ht_params,
- .nvm_ver = IWL7265_NVM_VERSION,
- .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
- .dccm_len = IWL7265_DCCM_LEN,
-};
-
-const struct iwl_cfg iwl7265_2n_cfg = {
- .name = "Intel(R) Dual Band Wireless N 7265",
- .fw_name_pre = IWL7265_FW_PRE,
- IWL_DEVICE_7005,
- .ht_params = &iwl7265_ht_params,
- .nvm_ver = IWL7265_NVM_VERSION,
- .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
- .dccm_len = IWL7265_DCCM_LEN,
-};
-
-const struct iwl_cfg iwl7265_n_cfg = {
- .name = "Intel(R) Wireless N 7265",
+const struct iwl_rf_cfg iwl7265_cfg = {
.fw_name_pre = IWL7265_FW_PRE,
IWL_DEVICE_7005,
- .ht_params = &iwl7265_ht_params,
+ .ht_params = {
+ .stbc = true,
+ .ldpc = true,
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
.nvm_ver = IWL7265_NVM_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
-const struct iwl_cfg iwl7265d_2ac_cfg = {
- .name = "Intel(R) Dual Band Wireless AC 7265",
- .fw_name_pre = IWL7265D_FW_PRE,
- IWL_DEVICE_7005D,
- .ht_params = &iwl7265_ht_params,
- .nvm_ver = IWL7265D_NVM_VERSION,
- .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
- .dccm_len = IWL7265_DCCM_LEN,
-};
-
-const struct iwl_cfg iwl7265d_2n_cfg = {
- .name = "Intel(R) Dual Band Wireless N 7265",
+const struct iwl_rf_cfg iwl7265d_cfg = {
.fw_name_pre = IWL7265D_FW_PRE,
IWL_DEVICE_7005D,
- .ht_params = &iwl7265_ht_params,
- .nvm_ver = IWL7265D_NVM_VERSION,
- .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
- .dccm_len = IWL7265_DCCM_LEN,
-};
-
-const struct iwl_cfg iwl7265d_n_cfg = {
- .name = "Intel(R) Wireless N 7265",
- .fw_name_pre = IWL7265D_FW_PRE,
- IWL_DEVICE_7005D,
- .ht_params = &iwl7265_ht_params,
+ .ht_params = {
+ .stbc = true,
+ .ldpc = true,
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
.nvm_ver = IWL7265D_NVM_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c
index d09cf8d7dc01..3c844cd419e8 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2014, 2018-2020, 2023 Intel Corporation
+ * Copyright (C) 2014, 2018-2020, 2023, 2025 Intel Corporation
* Copyright (C) 2014-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016 Intel Deutschland GmbH
*/
@@ -35,9 +35,7 @@
#define IWL8265_MODULE_FIRMWARE(api) \
IWL8265_FW_PRE "-" __stringify(api) ".ucode"
-#define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C"
-
-static const struct iwl_base_params iwl8000_base_params = {
+static const struct iwl_family_base_params iwl8000_base = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
.num_of_queues = 31,
.max_tfd_queue_size = 256,
@@ -47,12 +45,11 @@ static const struct iwl_base_params iwl8000_base_params = {
.max_event_log_size = 512,
.shadow_reg_enable = true,
.pcie_l1_allowed = true,
-};
-
-static const struct iwl_ht_params iwl8000_ht_params = {
- .stbc = true,
- .ldpc = true,
- .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ .nvm_hw_section_num = 10,
+ .features = NETIF_F_RXCSUM,
+ .smem_offset = IWL8260_SMEM_OFFSET,
+ .smem_len = IWL8260_SMEM_LEN,
+ .apmg_not_supported = true,
};
static const struct iwl_tt_params iwl8000_tt_params = {
@@ -76,30 +73,20 @@ static const struct iwl_tt_params iwl8000_tt_params = {
.support_tx_backoff = true,
};
+const struct iwl_mac_cfg iwl8000_mac_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_8000,
+ .base = &iwl8000_base,
+};
+
#define IWL_DEVICE_8000_COMMON \
- .trans.device_family = IWL_DEVICE_FAMILY_8000, \
- .trans.base_params = &iwl8000_base_params, \
.led_mode = IWL_LED_RF_STATE, \
- .nvm_hw_section_num = 10, \
- .features = NETIF_F_RXCSUM, \
.non_shared_ant = ANT_A, \
.dccm_offset = IWL8260_DCCM_OFFSET, \
.dccm_len = IWL8260_DCCM_LEN, \
.dccm2_offset = IWL8260_DCCM2_OFFSET, \
.dccm2_len = IWL8260_DCCM2_LEN, \
- .smem_offset = IWL8260_SMEM_OFFSET, \
- .smem_len = IWL8260_SMEM_LEN, \
- .default_nvm_file_C_step = DEFAULT_NVM_FILE_FAMILY_8000C, \
.thermal_params = &iwl8000_tt_params, \
- .apmg_not_supported = true, \
- .nvm_type = IWL_NVM_EXT, \
- .dbgc_supported = true, \
- .min_umac_error_event_table = 0x800000
-
-#define IWL_DEVICE_8000 \
- IWL_DEVICE_8000_COMMON, \
- .ucode_api_max = IWL8000_UCODE_API_MAX, \
- .ucode_api_min = IWL8000_UCODE_API_MIN \
+ .nvm_type = IWL_NVM_EXT
#define IWL_DEVICE_8260 \
IWL_DEVICE_8000_COMMON, \
@@ -111,47 +98,39 @@ static const struct iwl_tt_params iwl8000_tt_params = {
.ucode_api_max = IWL8265_UCODE_API_MAX, \
.ucode_api_min = IWL8265_UCODE_API_MIN \
-const struct iwl_cfg iwl8260_2n_cfg = {
- .name = "Intel(R) Dual Band Wireless N 8260",
- .fw_name_pre = IWL8000_FW_PRE,
- IWL_DEVICE_8260,
- .ht_params = &iwl8000_ht_params,
- .nvm_ver = IWL8000_NVM_VERSION,
-};
+const char iwl8260_2n_name[] = "Intel(R) Dual Band Wireless-N 8260";
+const char iwl8260_2ac_name[] = "Intel(R) Dual Band Wireless-AC 8260";
+const char iwl8265_2ac_name[] = "Intel(R) Dual Band Wireless-AC 8265";
+const char iwl8275_2ac_name[] = "Intel(R) Dual Band Wireless-AC 8275";
+const char iwl4165_2ac_name[] = "Intel(R) Dual Band Wireless-AC 4165";
-const struct iwl_cfg iwl8260_2ac_cfg = {
- .name = "Intel(R) Dual Band Wireless AC 8260",
+const char iwl_killer_1435i_name[] =
+ "Killer(R) Wireless-AC 1435i Wireless Network Adapter (8265D2W)";
+const char iwl_killer_1434_kix_name[] =
+ "Killer(R) Wireless-AC 1435-KIX Wireless Network Adapter (8265NGW)";
+
+const struct iwl_rf_cfg iwl8260_cfg = {
.fw_name_pre = IWL8000_FW_PRE,
IWL_DEVICE_8260,
- .ht_params = &iwl8000_ht_params,
+ .ht_params = {
+ .stbc = true,
+ .ldpc = true,
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
.nvm_ver = IWL8000_NVM_VERSION,
};
-const struct iwl_cfg iwl8265_2ac_cfg = {
- .name = "Intel(R) Dual Band Wireless AC 8265",
+const struct iwl_rf_cfg iwl8265_cfg = {
.fw_name_pre = IWL8265_FW_PRE,
IWL_DEVICE_8265,
- .ht_params = &iwl8000_ht_params,
- .nvm_ver = IWL8000_NVM_VERSION,
- .vht_mu_mimo_supported = true,
-};
-
-const struct iwl_cfg iwl8275_2ac_cfg = {
- .name = "Intel(R) Dual Band Wireless AC 8275",
- .fw_name_pre = IWL8265_FW_PRE,
- IWL_DEVICE_8265,
- .ht_params = &iwl8000_ht_params,
+ .ht_params = {
+ .stbc = true,
+ .ldpc = true,
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
+ },
.nvm_ver = IWL8000_NVM_VERSION,
.vht_mu_mimo_supported = true,
};
-const struct iwl_cfg iwl4165_2ac_cfg = {
- .name = "Intel(R) Dual Band Wireless AC 4165",
- .fw_name_pre = IWL8000_FW_PRE,
- IWL_DEVICE_8000,
- .ht_params = &iwl8000_ht_params,
- .nvm_ver = IWL8000_NVM_VERSION,
-};
-
MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL8265_MODULE_FIRMWARE(IWL8265_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
index 0130d9a9b78b..5872fc9b8caf 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.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-2021, 2023 Intel Corporation
+ * Copyright (C) 2018-2021, 2023, 2025 Intel Corporation
*/
#include <linux/module.h>
#include <linux/stringify.h>
@@ -15,14 +15,7 @@
/* Lowest firmware API version supported */
#define IWL9000_UCODE_API_MIN 30
-/* NVM versions */
-#define IWL9000_NVM_VERSION 0x0a1d
-
/* Memory offsets and lengths */
-#define IWL9000_DCCM_OFFSET 0x800000
-#define IWL9000_DCCM_LEN 0x18000
-#define IWL9000_DCCM2_OFFSET 0x880000
-#define IWL9000_DCCM2_LEN 0x8000
#define IWL9000_SMEM_OFFSET 0x400000
#define IWL9000_SMEM_LEN 0x68000
@@ -33,7 +26,7 @@
#define IWL9260_MODULE_FIRMWARE(api) \
IWL9260_FW_PRE "-" __stringify(api) ".ucode"
-static const struct iwl_base_params iwl9000_base_params = {
+static const struct iwl_family_base_params iwl9000_base = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
.num_of_queues = 31,
.max_tfd_queue_size = 256,
@@ -43,150 +36,68 @@ static const struct iwl_base_params iwl9000_base_params = {
.max_event_log_size = 512,
.shadow_reg_enable = true,
.pcie_l1_allowed = true,
-};
-
-static const struct iwl_ht_params iwl9000_ht_params = {
- .stbc = true,
- .ldpc = true,
- .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
-};
-
-static const struct iwl_tt_params iwl9000_tt_params = {
- .ct_kill_entry = 115,
- .ct_kill_exit = 93,
- .ct_kill_duration = 5,
- .dynamic_smps_entry = 111,
- .dynamic_smps_exit = 107,
- .tx_protection_entry = 112,
- .tx_protection_exit = 105,
- .tx_backoff = {
- {.temperature = 110, .backoff = 200},
- {.temperature = 111, .backoff = 600},
- {.temperature = 112, .backoff = 1200},
- {.temperature = 113, .backoff = 2000},
- {.temperature = 114, .backoff = 4000},
+ .smem_offset = IWL9000_SMEM_OFFSET,
+ .smem_len = IWL9000_SMEM_LEN,
+ .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
+ .apmg_not_supported = true,
+ .mac_addr_from_csr = 0x380,
+ .d3_debug_data_base_addr = 0x401000,
+ .d3_debug_data_length = 92 * 1024,
+ .nvm_hw_section_num = 10,
+ .mon_smem_regs = {
+ .write_ptr = {
+ .addr = LDBG_M2S_BUF_WPTR,
+ .mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
+ },
+ .cycle_cnt = {
+ .addr = LDBG_M2S_BUF_WRAP_CNT,
+ .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
+ },
+ },
+ .mon_dram_regs = {
+ .write_ptr = {
+ .addr = MON_BUFF_WRPTR_VER2,
+ .mask = 0xffffffff,
+ },
+ .cycle_cnt = {
+ .addr = MON_BUFF_CYCLE_CNT_VER2,
+ .mask = 0xffffffff,
+ },
},
- .support_ct_kill = true,
- .support_dynamic_smps = true,
- .support_tx_protection = true,
- .support_tx_backoff = true,
+ .ucode_api_max = IWL9000_UCODE_API_MAX,
+ .ucode_api_min = IWL9000_UCODE_API_MIN,
};
-#define IWL_DEVICE_9000 \
- .ucode_api_max = IWL9000_UCODE_API_MAX, \
- .ucode_api_min = IWL9000_UCODE_API_MIN, \
- .led_mode = IWL_LED_RF_STATE, \
- .nvm_hw_section_num = 10, \
- .non_shared_ant = ANT_B, \
- .dccm_offset = IWL9000_DCCM_OFFSET, \
- .dccm_len = IWL9000_DCCM_LEN, \
- .dccm2_offset = IWL9000_DCCM2_OFFSET, \
- .dccm2_len = IWL9000_DCCM2_LEN, \
- .smem_offset = IWL9000_SMEM_OFFSET, \
- .smem_len = IWL9000_SMEM_LEN, \
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
- .thermal_params = &iwl9000_tt_params, \
- .apmg_not_supported = true, \
- .num_rbds = 512, \
- .vht_mu_mimo_supported = true, \
- .mac_addr_from_csr = 0x380, \
- .nvm_type = IWL_NVM_EXT, \
- .dbgc_supported = true, \
- .min_umac_error_event_table = 0x800000, \
- .d3_debug_data_base_addr = 0x401000, \
- .d3_debug_data_length = 92 * 1024, \
- .ht_params = &iwl9000_ht_params, \
- .nvm_ver = IWL9000_NVM_VERSION, \
- .mon_smem_regs = { \
- .write_ptr = { \
- .addr = LDBG_M2S_BUF_WPTR, \
- .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
- }, \
- .cycle_cnt = { \
- .addr = LDBG_M2S_BUF_WRAP_CNT, \
- .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
- }, \
- }, \
- .mon_dram_regs = { \
- .write_ptr = { \
- .addr = MON_BUFF_WRPTR_VER2, \
- .mask = 0xffffffff, \
- }, \
- .cycle_cnt = { \
- .addr = MON_BUFF_CYCLE_CNT_VER2, \
- .mask = 0xffffffff, \
- }, \
- }
-
-const struct iwl_cfg_trans_params iwl9000_trans_cfg = {
+const struct iwl_mac_cfg iwl9000_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_9000,
- .base_params = &iwl9000_base_params,
+ .base = &iwl9000_base,
.mq_rx_supported = true,
- .rf_id = true,
};
-const struct iwl_cfg_trans_params iwl9560_trans_cfg = {
+const struct iwl_mac_cfg iwl9560_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_9000,
- .base_params = &iwl9000_base_params,
+ .base = &iwl9000_base,
.mq_rx_supported = true,
- .rf_id = true,
.integrated = true,
.xtal_latency = 650,
};
-const struct iwl_cfg_trans_params iwl9560_long_latency_trans_cfg = {
+const struct iwl_mac_cfg iwl9560_long_latency_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_9000,
- .base_params = &iwl9000_base_params,
+ .base = &iwl9000_base,
.mq_rx_supported = true,
- .rf_id = true,
.integrated = true,
.xtal_latency = 2820,
};
-const struct iwl_cfg_trans_params iwl9560_shared_clk_trans_cfg = {
+const struct iwl_mac_cfg iwl9560_shared_clk_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_9000,
- .base_params = &iwl9000_base_params,
+ .base = &iwl9000_base,
.mq_rx_supported = true,
- .rf_id = true,
.integrated = true,
.xtal_latency = 670,
.extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK
};
-const char iwl9162_name[] = "Intel(R) Wireless-AC 9162";
-const char iwl9260_name[] = "Intel(R) Wireless-AC 9260";
-const char iwl9260_1_name[] = "Intel(R) Wireless-AC 9260-1";
-const char iwl9270_name[] = "Intel(R) Wireless-AC 9270";
-const char iwl9461_name[] = "Intel(R) Wireless-AC 9461";
-const char iwl9462_name[] = "Intel(R) Wireless-AC 9462";
-const char iwl9560_name[] = "Intel(R) Wireless-AC 9560";
-const char iwl9162_160_name[] = "Intel(R) Wireless-AC 9162 160MHz";
-const char iwl9260_160_name[] = "Intel(R) Wireless-AC 9260 160MHz";
-const char iwl9270_160_name[] = "Intel(R) Wireless-AC 9270 160MHz";
-const char iwl9461_160_name[] = "Intel(R) Wireless-AC 9461 160MHz";
-const char iwl9462_160_name[] = "Intel(R) Wireless-AC 9462 160MHz";
-const char iwl9560_160_name[] = "Intel(R) Wireless-AC 9560 160MHz";
-
-const char iwl9260_killer_1550_name[] =
- "Killer (R) Wireless-AC 1550 Wireless Network Adapter (9260NGW) 160MHz";
-const char iwl9560_killer_1550i_name[] =
- "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)";
-const char iwl9560_killer_1550i_160_name[] =
- "Killer(R) Wireless-AC 1550i Wireless Network Adapter (9560NGW) 160MHz";
-const char iwl9560_killer_1550s_name[] =
- "Killer (R) Wireless-AC 1550s Wireless Network Adapter (9560NGW)";
-const char iwl9560_killer_1550s_160_name[] =
- "Killer(R) Wireless-AC 1550s Wireless Network Adapter (9560D2W) 160MHz";
-
-const struct iwl_cfg iwl9260_2ac_cfg = {
- .fw_name_pre = IWL9260_FW_PRE,
- IWL_DEVICE_9000,
-};
-
-const struct iwl_cfg iwl9560_2ac_cfg_soc = {
- .fw_name_pre = IWL9000_FW_PRE,
- IWL_DEVICE_9000,
-};
-
MODULE_FIRMWARE(IWL9000_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL9260_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c
index e87b57b9e2c0..582f61661062 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.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-2025 Intel Corporation
*/
#include <linux/module.h>
#include <linux/stringify.h>
@@ -13,42 +13,13 @@
#define IWL_AX210_UCODE_API_MAX 89
/* Lowest firmware API version supported */
-#define IWL_AX210_UCODE_API_MIN 77
-
-/* NVM versions */
-#define IWL_AX210_NVM_VERSION 0x0a1d
+#define IWL_AX210_UCODE_API_MIN 89
/* Memory offsets and lengths */
-#define IWL_AX210_DCCM_OFFSET 0x800000 /* LMAC1 */
-#define IWL_AX210_DCCM_LEN 0x10000 /* LMAC1 */
-#define IWL_AX210_DCCM2_OFFSET 0x880000
-#define IWL_AX210_DCCM2_LEN 0x8000
#define IWL_AX210_SMEM_OFFSET 0x400000
#define IWL_AX210_SMEM_LEN 0xD0000
-#define IWL_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0"
-#define IWL_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0"
-#define IWL_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0"
-#define IWL_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0"
-#define IWL_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0"
-#define IWL_MA_A_HR_B_FW_PRE "iwlwifi-ma-a0-hr-b0"
-#define IWL_MA_A_GF_A_FW_PRE "iwlwifi-ma-a0-gf-a0"
-#define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0"
-#define IWL_MA_B_HR_B_FW_PRE "iwlwifi-ma-b0-hr-b0"
-#define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0"
-#define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0"
-
-#define IWL_SO_A_JF_B_MODULE_FIRMWARE(api) \
- IWL_SO_A_JF_B_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL_SO_A_HR_B_MODULE_FIRMWARE(api) \
- IWL_SO_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(api) \
- IWL_MA_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(api) \
- IWL_MA_B_HR_B_FW_PRE "-" __stringify(api) ".ucode"
-
-static const struct iwl_base_params iwl_ax210_base_params = {
- .eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
+static const struct iwl_family_base_params iwl_ax210_base = {
.num_of_queues = 512,
.max_tfd_queue_size = 65536,
.shadow_ram_support = true,
@@ -57,74 +28,59 @@ static const struct iwl_base_params iwl_ax210_base_params = {
.max_event_log_size = 512,
.shadow_reg_enable = true,
.pcie_l1_allowed = true,
+ .smem_offset = IWL_AX210_SMEM_OFFSET,
+ .smem_len = IWL_AX210_SMEM_LEN,
+ .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
+ .apmg_not_supported = true,
+ .mac_addr_from_csr = 0x380,
+ .d3_debug_data_base_addr = 0x401000,
+ .d3_debug_data_length = 60 * 1024,
+ .mon_smem_regs = {
+ .write_ptr = {
+ .addr = LDBG_M2S_BUF_WPTR,
+ .mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
+ },
+ .cycle_cnt = {
+ .addr = LDBG_M2S_BUF_WRAP_CNT,
+ .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
+ },
+ },
+ .min_txq_size = 128,
+ .gp2_reg_addr = 0xd02c68,
+ .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_HE,
+ .mon_dram_regs = {
+ .write_ptr = {
+ .addr = DBGC_CUR_DBGBUF_STATUS,
+ .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK,
+ },
+ .cycle_cnt = {
+ .addr = DBGC_DBGBUF_WRAP_AROUND,
+ .mask = 0xffffffff,
+ },
+ .cur_frag = {
+ .addr = DBGC_CUR_DBGBUF_STATUS,
+ .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK,
+ },
+ },
+ .ucode_api_min = IWL_AX210_UCODE_API_MIN,
+ .ucode_api_max = IWL_AX210_UCODE_API_MAX,
};
-#define IWL_DEVICE_AX210_COMMON \
- .ucode_api_min = IWL_AX210_UCODE_API_MIN, \
- .led_mode = IWL_LED_RF_STATE, \
- .nvm_hw_section_num = 10, \
- .non_shared_ant = ANT_B, \
- .dccm_offset = IWL_AX210_DCCM_OFFSET, \
- .dccm_len = IWL_AX210_DCCM_LEN, \
- .dccm2_offset = IWL_AX210_DCCM2_OFFSET, \
- .dccm2_len = IWL_AX210_DCCM2_LEN, \
- .smem_offset = IWL_AX210_SMEM_OFFSET, \
- .smem_len = IWL_AX210_SMEM_LEN, \
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
- .apmg_not_supported = true, \
- .trans.mq_rx_supported = true, \
- .vht_mu_mimo_supported = true, \
- .mac_addr_from_csr = 0x380, \
- .ht_params = &iwl_22000_ht_params, \
- .nvm_ver = IWL_AX210_NVM_VERSION, \
- .trans.rf_id = true, \
- .trans.gen2 = true, \
- .nvm_type = IWL_NVM_EXT, \
- .dbgc_supported = true, \
- .min_umac_error_event_table = 0x400000, \
- .d3_debug_data_base_addr = 0x401000, \
- .d3_debug_data_length = 60 * 1024, \
- .mon_smem_regs = { \
- .write_ptr = { \
- .addr = LDBG_M2S_BUF_WPTR, \
- .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
- }, \
- .cycle_cnt = { \
- .addr = LDBG_M2S_BUF_WRAP_CNT, \
- .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
- }, \
- }
-
-#define IWL_DEVICE_AX210 \
- IWL_DEVICE_AX210_COMMON, \
- .ucode_api_max = IWL_AX210_UCODE_API_MAX, \
- .trans.umac_prph_offset = 0x300000, \
- .trans.device_family = IWL_DEVICE_FAMILY_AX210, \
- .trans.base_params = &iwl_ax210_base_params, \
- .min_txq_size = 128, \
- .gp2_reg_addr = 0xd02c68, \
- .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_HE, \
- .mon_dram_regs = { \
- .write_ptr = { \
- .addr = DBGC_CUR_DBGBUF_STATUS, \
- .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
- }, \
- .cycle_cnt = { \
- .addr = DBGC_DBGBUF_WRAP_AROUND, \
- .mask = 0xffffffff, \
- }, \
- .cur_frag = { \
- .addr = DBGC_CUR_DBGBUF_STATUS, \
- .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
- }, \
- }
+const struct iwl_mac_cfg iwl_ty_mac_cfg = {
+ .mq_rx_supported = true,
+ .gen2 = true,
+ .device_family = IWL_DEVICE_FAMILY_AX210,
+ .base = &iwl_ax210_base,
+ .umac_prph_offset = 0x300000,
+ /* TODO: the following values need to be checked */
+ .xtal_latency = 500,
+};
-const struct iwl_cfg_trans_params iwl_so_trans_cfg = {
+const struct iwl_mac_cfg iwl_so_mac_cfg = {
.mq_rx_supported = true,
- .rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_AX210,
- .base_params = &iwl_ax210_base_params,
+ .base = &iwl_ax210_base,
.umac_prph_offset = 0x300000,
.integrated = true,
/* TODO: the following values need to be checked */
@@ -132,12 +88,11 @@ const struct iwl_cfg_trans_params iwl_so_trans_cfg = {
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_200US,
};
-const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg = {
+const struct iwl_mac_cfg iwl_so_long_latency_mac_cfg = {
.mq_rx_supported = true,
- .rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_AX210,
- .base_params = &iwl_ax210_base_params,
+ .base = &iwl_ax210_base,
.umac_prph_offset = 0x300000,
.integrated = true,
.low_latency_xtal = true,
@@ -145,12 +100,11 @@ const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg = {
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
};
-const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg = {
+const struct iwl_mac_cfg iwl_so_long_latency_imr_mac_cfg = {
.mq_rx_supported = true,
- .rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_AX210,
- .base_params = &iwl_ax210_base_params,
+ .base = &iwl_ax210_base,
.umac_prph_offset = 0x300000,
.integrated = true,
.low_latency_xtal = true,
@@ -159,114 +113,11 @@ const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg = {
.imr_enabled = true,
};
-/*
- * If the device doesn't support HE, no need to have that many buffers.
- * AX210 devices can split multiple frames into a single RB, so fewer are
- * needed; AX210 cannot (but use smaller RBs by default) - these sizes
- * were picked according to 8 MSDUs inside 256 A-MSDUs in an A-MPDU, with
- * additional overhead to account for processing time.
- */
-#define IWL_NUM_RBDS_NON_HE 512
-#define IWL_NUM_RBDS_AX210_HE 4096
-
-const struct iwl_cfg_trans_params iwl_ma_trans_cfg = {
+const struct iwl_mac_cfg iwl_ma_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_AX210,
- .base_params = &iwl_ax210_base_params,
+ .base = &iwl_ax210_base,
.mq_rx_supported = true,
- .rf_id = true,
.gen2 = true,
.integrated = true,
.umac_prph_offset = 0x300000
};
-
-const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz";
-const char iwl_ax231_name[] = "Intel(R) Wi-Fi 6E AX231 160MHz";
-const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6E AX411 160MHz";
-
-const char iwl_ax210_killer_1675w_name[] =
- "Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)";
-const char iwl_ax210_killer_1675x_name[] =
- "Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)";
-const char iwl_ax211_killer_1675s_name[] =
- "Killer(R) Wi-Fi 6E AX1675s 160MHz Wireless Network Adapter (211NGW)";
-const char iwl_ax211_killer_1675i_name[] =
- "Killer(R) Wi-Fi 6E AX1675i 160MHz Wireless Network Adapter (211NGW)";
-const char iwl_ax411_killer_1690s_name[] =
- "Killer(R) Wi-Fi 6E AX1690s 160MHz Wireless Network Adapter (411D2W)";
-const char iwl_ax411_killer_1690i_name[] =
- "Killer(R) Wi-Fi 6E AX1690i 160MHz Wireless Network Adapter (411NGW)";
-
-const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0 = {
- .name = "Intel(R) Wireless-AC 9560 160MHz",
- .fw_name_pre = IWL_SO_A_JF_B_FW_PRE,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_NON_HE,
-};
-
-const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0 = {
- .name = iwl_ax211_name,
- .fw_name_pre = IWL_SO_A_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long = {
- .name = iwl_ax211_name,
- .fw_name_pre = IWL_SO_A_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
- .trans.xtal_latency = 12000,
- .trans.low_latency_xtal = true,
-};
-
-const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = {
- .name = "Intel(R) Wi-Fi 6 AX210 160MHz",
- .fw_name_pre = IWL_TY_A_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0 = {
- .name = iwl_ax411_name,
- .fw_name_pre = IWL_SO_A_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0_long = {
- .name = iwl_ax411_name,
- .fw_name_pre = IWL_SO_A_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
- .trans.xtal_latency = 12000,
- .trans.low_latency_xtal = true,
-};
-
-const struct iwl_cfg iwl_cfg_ma = {
- .fw_name_mac = "ma",
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_so_a0_hr_a0 = {
- .fw_name_pre = IWL_SO_A_HR_B_FW_PRE,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
-IWL_FW_AND_PNVM(IWL_SO_A_GF_A_FW_PRE, IWL_AX210_UCODE_API_MAX);
-IWL_FW_AND_PNVM(IWL_TY_A_GF_A_FW_PRE, IWL_AX210_UCODE_API_MAX);
-MODULE_FIRMWARE(IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
-IWL_FW_AND_PNVM(IWL_MA_A_GF_A_FW_PRE, IWL_AX210_UCODE_API_MAX);
-IWL_FW_AND_PNVM(IWL_MA_A_GF4_A_FW_PRE, IWL_AX210_UCODE_API_MAX);
-MODULE_FIRMWARE(IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
-IWL_FW_AND_PNVM(IWL_MA_B_GF_A_FW_PRE, IWL_AX210_UCODE_API_MAX);
-IWL_FW_AND_PNVM(IWL_MA_B_GF4_A_FW_PRE, IWL_AX210_UCODE_API_MAX);
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
index f055255a7c93..d25445bd1e5c 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
@@ -9,42 +9,23 @@
#include "iwl-prph.h"
#include "fw/api/txq.h"
-/* Highest firmware API version supported */
-#define IWL_BZ_UCODE_API_MAX 98
+/* Highest firmware core release supported */
+#define IWL_BZ_UCODE_CORE_MAX 101
/* Lowest firmware API version supported */
-#define IWL_BZ_UCODE_API_MIN 93
-
-/* NVM versions */
-#define IWL_BZ_NVM_VERSION 0x0a1d
+#define IWL_BZ_UCODE_API_MIN 100
/* Memory offsets and lengths */
-#define IWL_BZ_DCCM_OFFSET 0x800000 /* LMAC1 */
-#define IWL_BZ_DCCM_LEN 0x10000 /* LMAC1 */
-#define IWL_BZ_DCCM2_OFFSET 0x880000
-#define IWL_BZ_DCCM2_LEN 0x8000
#define IWL_BZ_SMEM_OFFSET 0x400000
#define IWL_BZ_SMEM_LEN 0xD0000
-#define IWL_BZ_A_HR_B_FW_PRE "iwlwifi-bz-a0-hr-b0"
-#define IWL_BZ_A_GF_A_FW_PRE "iwlwifi-bz-a0-gf-a0"
-#define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0"
#define IWL_BZ_A_FM_B_FW_PRE "iwlwifi-bz-a0-fm-b0"
#define IWL_BZ_A_FM_C_FW_PRE "iwlwifi-bz-a0-fm-c0"
#define IWL_BZ_A_FM4_B_FW_PRE "iwlwifi-bz-a0-fm4-b0"
#define IWL_GL_B_FM_B_FW_PRE "iwlwifi-gl-b0-fm-b0"
#define IWL_GL_C_FM_C_FW_PRE "iwlwifi-gl-c0-fm-c0"
-#define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \
- IWL_BZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
-
-#if !IS_ENABLED(CONFIG_IWLMVM)
-const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz";
-const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz";
-#endif
-
-static const struct iwl_base_params iwl_bz_base_params = {
- .eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
+static const struct iwl_family_base_params iwl_bz_base = {
.num_of_queues = 512,
.max_tfd_queue_size = 65536,
.shadow_ram_support = true,
@@ -53,91 +34,54 @@ static const struct iwl_base_params iwl_bz_base_params = {
.max_event_log_size = 512,
.shadow_reg_enable = true,
.pcie_l1_allowed = true,
+ .smem_offset = IWL_BZ_SMEM_OFFSET,
+ .smem_len = IWL_BZ_SMEM_LEN,
+ .apmg_not_supported = true,
+ .mac_addr_from_csr = 0x30,
+ .d3_debug_data_base_addr = 0x401000,
+ .d3_debug_data_length = 60 * 1024,
+ .mon_smem_regs = {
+ .write_ptr = {
+ .addr = LDBG_M2S_BUF_WPTR,
+ .mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
+ },
+ .cycle_cnt = {
+ .addr = LDBG_M2S_BUF_WRAP_CNT,
+ .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
+ },
+ },
+ .min_txq_size = 128,
+ .gp2_reg_addr = 0xd02c68,
+ .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT,
+ .mon_dram_regs = {
+ .write_ptr = {
+ .addr = DBGC_CUR_DBGBUF_STATUS,
+ .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK,
+ },
+ .cycle_cnt = {
+ .addr = DBGC_DBGBUF_WRAP_AROUND,
+ .mask = 0xffffffff,
+ },
+ .cur_frag = {
+ .addr = DBGC_CUR_DBGBUF_STATUS,
+ .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK,
+ },
+ },
+ .mon_dbgi_regs = {
+ .write_ptr = {
+ .addr = DBGI_SRAM_FIFO_POINTERS,
+ .mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK,
+ },
+ },
+ .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
+ .ucode_api_max = ENCODE_CORE_AS_API(IWL_BZ_UCODE_CORE_MAX),
+ .ucode_api_min = IWL_BZ_UCODE_API_MIN,
};
-const struct iwl_ht_params iwl_bz_ht_params = {
- .stbc = true,
- .ldpc = true,
- .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ) |
- BIT(NL80211_BAND_6GHZ),
-};
-
-#define IWL_DEVICE_BZ_COMMON \
- .ucode_api_max = IWL_BZ_UCODE_API_MAX, \
- .ucode_api_min = IWL_BZ_UCODE_API_MIN, \
- .led_mode = IWL_LED_RF_STATE, \
- .nvm_hw_section_num = 10, \
- .non_shared_ant = ANT_B, \
- .dccm_offset = IWL_BZ_DCCM_OFFSET, \
- .dccm_len = IWL_BZ_DCCM_LEN, \
- .dccm2_offset = IWL_BZ_DCCM2_OFFSET, \
- .dccm2_len = IWL_BZ_DCCM2_LEN, \
- .smem_offset = IWL_BZ_SMEM_OFFSET, \
- .smem_len = IWL_BZ_SMEM_LEN, \
- .apmg_not_supported = true, \
- .trans.mq_rx_supported = true, \
- .vht_mu_mimo_supported = true, \
- .mac_addr_from_csr = 0x30, \
- .nvm_ver = IWL_BZ_NVM_VERSION, \
- .trans.rf_id = true, \
- .trans.gen2 = true, \
- .nvm_type = IWL_NVM_EXT, \
- .dbgc_supported = true, \
- .min_umac_error_event_table = 0xD0000, \
- .d3_debug_data_base_addr = 0x401000, \
- .d3_debug_data_length = 60 * 1024, \
- .mon_smem_regs = { \
- .write_ptr = { \
- .addr = LDBG_M2S_BUF_WPTR, \
- .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
- }, \
- .cycle_cnt = { \
- .addr = LDBG_M2S_BUF_WRAP_CNT, \
- .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
- }, \
- }, \
- .trans.umac_prph_offset = 0x300000, \
- .trans.device_family = IWL_DEVICE_FAMILY_BZ, \
- .trans.base_params = &iwl_bz_base_params, \
- .min_txq_size = 128, \
- .gp2_reg_addr = 0xd02c68, \
- .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT, \
- .mon_dram_regs = { \
- .write_ptr = { \
- .addr = DBGC_CUR_DBGBUF_STATUS, \
- .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
- }, \
- .cycle_cnt = { \
- .addr = DBGC_DBGBUF_WRAP_AROUND, \
- .mask = 0xffffffff, \
- }, \
- .cur_frag = { \
- .addr = DBGC_CUR_DBGBUF_STATUS, \
- .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
- }, \
- }, \
- .mon_dbgi_regs = { \
- .write_ptr = { \
- .addr = DBGI_SRAM_FIFO_POINTERS, \
- .mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK, \
- }, \
- }
-
-#define IWL_DEVICE_BZ \
- IWL_DEVICE_BZ_COMMON, \
- .ht_params = &iwl_bz_ht_params
-
-/*
- * This size was picked according to 8 MSDUs inside 512 A-MSDUs in an
- * A-MPDU, with additional overhead to account for processing time.
- */
-#define IWL_NUM_RBDS_BZ_EHT (512 * 16)
-
-const struct iwl_cfg_trans_params iwl_bz_trans_cfg = {
+const struct iwl_mac_cfg iwl_bz_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_BZ,
- .base_params = &iwl_bz_base_params,
+ .base = &iwl_bz_base,
.mq_rx_supported = true,
- .rf_id = true,
.gen2 = true,
.integrated = true,
.umac_prph_offset = 0x300000,
@@ -145,44 +89,20 @@ const struct iwl_cfg_trans_params iwl_bz_trans_cfg = {
.low_latency_xtal = true,
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
};
+EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_bz_mac_cfg);
-const struct iwl_cfg_trans_params iwl_gl_trans_cfg = {
+const struct iwl_mac_cfg iwl_gl_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_BZ,
- .base_params = &iwl_bz_base_params,
+ .base = &iwl_bz_base,
.mq_rx_supported = true,
- .rf_id = true,
.gen2 = true,
.umac_prph_offset = 0x300000,
.xtal_latency = 12000,
.low_latency_xtal = true,
};
-const char iwl_fm_name[] = "Intel(R) Wi-Fi 7 BE201 320MHz";
-const char iwl_wh_name[] = "Intel(R) Wi-Fi 7 BE211 320MHz";
-const char iwl_gl_name[] = "Intel(R) Wi-Fi 7 BE200 320MHz";
-const char iwl_mtp_name[] = "Intel(R) Wi-Fi 7 BE202 160MHz";
-
-const struct iwl_cfg iwl_cfg_bz = {
- .fw_name_mac = "bz",
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_BZ_EHT,
-};
-
-const struct iwl_cfg iwl_cfg_gl = {
- .fw_name_mac = "gl",
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_BZ_EHT,
-};
-
-MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
-IWL_FW_AND_PNVM(IWL_BZ_A_GF_A_FW_PRE, IWL_BZ_UCODE_API_MAX);
-IWL_FW_AND_PNVM(IWL_BZ_A_GF4_A_FW_PRE, IWL_BZ_UCODE_API_MAX);
-IWL_FW_AND_PNVM(IWL_BZ_A_FM_B_FW_PRE, IWL_BZ_UCODE_API_MAX);
-IWL_FW_AND_PNVM(IWL_BZ_A_FM_C_FW_PRE, IWL_BZ_UCODE_API_MAX);
-IWL_FW_AND_PNVM(IWL_BZ_A_FM4_B_FW_PRE, IWL_BZ_UCODE_API_MAX);
-IWL_FW_AND_PNVM(IWL_GL_B_FM_B_FW_PRE, IWL_BZ_UCODE_API_MAX);
-IWL_FW_AND_PNVM(IWL_GL_C_FM_C_FW_PRE, IWL_BZ_UCODE_API_MAX);
+IWL_CORE_FW(IWL_BZ_A_FM_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
+IWL_CORE_FW(IWL_BZ_A_FM_C_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
+IWL_CORE_FW(IWL_BZ_A_FM4_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
+IWL_CORE_FW(IWL_GL_B_FM_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
+IWL_CORE_FW(IWL_GL_C_FM_C_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
index 282b9b846c3a..a279dcfd3083 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
@@ -8,36 +8,19 @@
#include "iwl-prph.h"
#include "fw/api/txq.h"
-/* Highest firmware API version supported */
-#define IWL_DR_UCODE_API_MAX 98
+/* Highest firmware core release supported */
+#define IWL_DR_UCODE_CORE_MAX 101
/* Lowest firmware API version supported */
-#define IWL_DR_UCODE_API_MIN 96
-
-/* NVM versions */
-#define IWL_DR_NVM_VERSION 0x0a1d
+#define IWL_DR_UCODE_API_MIN 100
/* Memory offsets and lengths */
-#define IWL_DR_DCCM_OFFSET 0x800000 /* LMAC1 */
-#define IWL_DR_DCCM_LEN 0x10000 /* LMAC1 */
-#define IWL_DR_DCCM2_OFFSET 0x880000
-#define IWL_DR_DCCM2_LEN 0x8000
#define IWL_DR_SMEM_OFFSET 0x400000
#define IWL_DR_SMEM_LEN 0xD0000
#define IWL_DR_A_PE_A_FW_PRE "iwlwifi-dr-a0-pe-a0"
-#define IWL_BR_A_PET_A_FW_PRE "iwlwifi-br-a0-petc-a0"
-#define IWL_BR_A_PE_A_FW_PRE "iwlwifi-br-a0-pe-a0"
-
-#define IWL_DR_A_PE_A_FW_MODULE_FIRMWARE(api) \
- IWL_DR_A_PE_A_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL_BR_A_PET_A_FW_MODULE_FIRMWARE(api) \
- IWL_BR_A_PET_A_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL_BR_A_PE_A_FW_MODULE_FIRMWARE(api) \
- IWL_BR_A_PE_A_FW_PRE "-" __stringify(api) ".ucode"
-static const struct iwl_base_params iwl_dr_base_params = {
- .eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
+static const struct iwl_family_base_params iwl_dr_base = {
.num_of_queues = 512,
.max_tfd_queue_size = 65536,
.shadow_ram_support = true,
@@ -46,87 +29,54 @@ static const struct iwl_base_params iwl_dr_base_params = {
.max_event_log_size = 512,
.shadow_reg_enable = true,
.pcie_l1_allowed = true,
+ .smem_offset = IWL_DR_SMEM_OFFSET,
+ .smem_len = IWL_DR_SMEM_LEN,
+ .apmg_not_supported = true,
+ .mac_addr_from_csr = 0x30,
+ .d3_debug_data_base_addr = 0x401000,
+ .d3_debug_data_length = 60 * 1024,
+ .mon_smem_regs = {
+ .write_ptr = {
+ .addr = LDBG_M2S_BUF_WPTR,
+ .mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
+ },
+ .cycle_cnt = {
+ .addr = LDBG_M2S_BUF_WRAP_CNT,
+ .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
+ },
+ },
+ .min_txq_size = 128,
+ .gp2_reg_addr = 0xd02c68,
+ .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT,
+ .mon_dram_regs = {
+ .write_ptr = {
+ .addr = DBGC_CUR_DBGBUF_STATUS,
+ .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK,
+ },
+ .cycle_cnt = {
+ .addr = DBGC_DBGBUF_WRAP_AROUND,
+ .mask = 0xffffffff,
+ },
+ .cur_frag = {
+ .addr = DBGC_CUR_DBGBUF_STATUS,
+ .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK,
+ },
+ },
+ .mon_dbgi_regs = {
+ .write_ptr = {
+ .addr = DBGI_SRAM_FIFO_POINTERS,
+ .mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK,
+ },
+ },
+ .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
+ .ucode_api_max = ENCODE_CORE_AS_API(IWL_DR_UCODE_CORE_MAX),
+ .ucode_api_min = IWL_DR_UCODE_API_MIN,
};
-#define IWL_DEVICE_DR_COMMON \
- .ucode_api_max = IWL_DR_UCODE_API_MAX, \
- .ucode_api_min = IWL_DR_UCODE_API_MIN, \
- .led_mode = IWL_LED_RF_STATE, \
- .nvm_hw_section_num = 10, \
- .non_shared_ant = ANT_B, \
- .dccm_offset = IWL_DR_DCCM_OFFSET, \
- .dccm_len = IWL_DR_DCCM_LEN, \
- .dccm2_offset = IWL_DR_DCCM2_OFFSET, \
- .dccm2_len = IWL_DR_DCCM2_LEN, \
- .smem_offset = IWL_DR_SMEM_OFFSET, \
- .smem_len = IWL_DR_SMEM_LEN, \
- .apmg_not_supported = true, \
- .trans.mq_rx_supported = true, \
- .vht_mu_mimo_supported = true, \
- .mac_addr_from_csr = 0x30, \
- .nvm_ver = IWL_DR_NVM_VERSION, \
- .trans.rf_id = true, \
- .trans.gen2 = true, \
- .nvm_type = IWL_NVM_EXT, \
- .dbgc_supported = true, \
- .min_umac_error_event_table = 0xD0000, \
- .d3_debug_data_base_addr = 0x401000, \
- .d3_debug_data_length = 60 * 1024, \
- .mon_smem_regs = { \
- .write_ptr = { \
- .addr = LDBG_M2S_BUF_WPTR, \
- .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
- }, \
- .cycle_cnt = { \
- .addr = LDBG_M2S_BUF_WRAP_CNT, \
- .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
- }, \
- }, \
- .trans.umac_prph_offset = 0x300000, \
- .trans.device_family = IWL_DEVICE_FAMILY_DR, \
- .trans.base_params = &iwl_dr_base_params, \
- .min_txq_size = 128, \
- .gp2_reg_addr = 0xd02c68, \
- .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT, \
- .mon_dram_regs = { \
- .write_ptr = { \
- .addr = DBGC_CUR_DBGBUF_STATUS, \
- .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
- }, \
- .cycle_cnt = { \
- .addr = DBGC_DBGBUF_WRAP_AROUND, \
- .mask = 0xffffffff, \
- }, \
- .cur_frag = { \
- .addr = DBGC_CUR_DBGBUF_STATUS, \
- .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
- }, \
- }, \
- .mon_dbgi_regs = { \
- .write_ptr = { \
- .addr = DBGI_SRAM_FIFO_POINTERS, \
- .mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK, \
- }, \
- }
-
-#define IWL_DEVICE_DR \
- IWL_DEVICE_DR_COMMON, \
- .uhb_supported = true, \
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
- .num_rbds = IWL_NUM_RBDS_DR_EHT, \
- .ht_params = &iwl_bz_ht_params
-
-/*
- * This size was picked according to 8 MSDUs inside 512 A-MSDUs in an
- * A-MPDU, with additional overhead to account for processing time.
- */
-#define IWL_NUM_RBDS_DR_EHT (512 * 16)
-
-const struct iwl_cfg_trans_params iwl_dr_trans_cfg = {
+const struct iwl_mac_cfg iwl_dr_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_DR,
- .base_params = &iwl_dr_base_params,
+ .base = &iwl_dr_base,
.mq_rx_supported = true,
- .rf_id = true,
.gen2 = true,
.integrated = true,
.umac_prph_offset = 0x300000,
@@ -135,31 +85,5 @@ const struct iwl_cfg_trans_params iwl_dr_trans_cfg = {
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
};
-const char iwl_dr_name[] = "Intel(R) TBD Dr device";
-
-const struct iwl_cfg iwl_cfg_dr = {
- .fw_name_mac = "dr",
- IWL_DEVICE_DR,
-};
-
-const struct iwl_cfg_trans_params iwl_br_trans_cfg = {
- .device_family = IWL_DEVICE_FAMILY_DR,
- .base_params = &iwl_dr_base_params,
- .mq_rx_supported = true,
- .rf_id = true,
- .gen2 = true,
- .umac_prph_offset = 0x300000,
- .xtal_latency = 12000,
- .low_latency_xtal = true,
-};
-
-const char iwl_br_name[] = "Intel(R) TBD Br device";
-
-const struct iwl_cfg iwl_cfg_br = {
- .fw_name_mac = "br",
- IWL_DEVICE_DR,
-};
+IWL_CORE_FW(IWL_DR_A_PE_A_FW_PRE, IWL_DR_UCODE_CORE_MAX);
-MODULE_FIRMWARE(IWL_DR_A_PE_A_FW_MODULE_FIRMWARE(IWL_DR_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BR_A_PET_A_FW_MODULE_FIRMWARE(IWL_DR_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BR_A_PE_A_FW_MODULE_FIRMWARE(IWL_DR_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c
new file mode 100644
index 000000000000..fd82050e33a3
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2015-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018-2025 Intel Corporation
+ */
+#include "iwl-config.h"
+
+/* NVM versions */
+#define IWL_FM_NVM_VERSION 0x0a1d
+
+#define IWL_DEVICE_FM \
+ .ht_params = { \
+ .stbc = true, \
+ .ldpc = true, \
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | \
+ BIT(NL80211_BAND_5GHZ), \
+ }, \
+ .led_mode = IWL_LED_RF_STATE, \
+ .non_shared_ant = ANT_B, \
+ .vht_mu_mimo_supported = true, \
+ .uhb_supported = true, \
+ .eht_supported = true, \
+ .num_rbds = IWL_NUM_RBDS_EHT, \
+ .nvm_ver = IWL_FM_NVM_VERSION, \
+ .nvm_type = IWL_NVM_EXT
+
+const struct iwl_rf_cfg iwl_rf_fm = {
+ IWL_DEVICE_FM,
+};
+
+const struct iwl_rf_cfg iwl_rf_fm_160mhz = {
+ IWL_DEVICE_FM,
+ .bw_limit = 160,
+};
+
+const char iwl_killer_be1750s_name[] =
+ "Killer(R) Wi-Fi 7 BE1750s 320MHz Wireless Network Adapter (BE201D2W)";
+const char iwl_killer_be1750i_name[] =
+ "Killer(R) Wi-Fi 7 BE1750i 320MHz Wireless Network Adapter (BE201NGW)";
+const char iwl_killer_be1750w_name[] =
+ "Killer(TM) Wi-Fi 7 BE1750w 320MHz Wireless Network Adapter (BE200D2W)";
+const char iwl_killer_be1750x_name[] =
+ "Killer(TM) Wi-Fi 7 BE1750x 320MHz Wireless Network Adapter (BE200NGW)";
+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_be201_name[] = "Intel(R) Wi-Fi 7 BE201 320MHz";
+const char iwl_be200_name[] = "Intel(R) Wi-Fi 7 BE200 320MHz";
+const char iwl_be202_name[] = "Intel(R) Wi-Fi 7 BE202 160MHz";
+const char iwl_be401_name[] = "Intel(R) Wi-Fi 7 BE401 320MHz";
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-gf.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-gf.c
new file mode 100644
index 000000000000..c16cda087a7c
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-gf.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2015-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018-2025 Intel Corporation
+ */
+#include "iwl-config.h"
+
+/* Highest firmware API version supported */
+#define IWL_GF_UCODE_API_MAX 100
+
+/* Lowest firmware API version supported */
+#define IWL_GF_UCODE_API_MIN 100
+
+#define IWL_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0"
+#define IWL_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0"
+#define IWL_MA_A_GF_A_FW_PRE "iwlwifi-ma-a0-gf-a0"
+#define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0"
+#define IWL_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0"
+#define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0"
+#define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0"
+#define IWL_BZ_A_GF_A_FW_PRE "iwlwifi-bz-a0-gf-a0"
+#define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0"
+#define IWL_SC_A_GF_A_FW_PRE "iwlwifi-sc-a0-gf-a0"
+#define IWL_SC_A_GF4_A_FW_PRE "iwlwifi-sc-a0-gf4-a0"
+
+#define IWL_BZ_A_GF_A_MODULE_FIRMWARE(api) \
+ IWL_BZ_A_GF_A_FW_PRE "-" __stringify(api) ".ucode"
+
+#define IWL_BZ_A_GF4_A_MODULE_FIRMWARE(api) \
+ IWL_BZ_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode"
+
+#define IWL_SC_A_GF_A_MODULE_FIRMWARE(api) \
+ IWL_SC_A_GF_A_FW_PRE "-" __stringify(api) ".ucode"
+
+#define IWL_SC_A_GF4_A_MODULE_FIRMWARE(api) \
+ IWL_SC_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode"
+
+/* NVM versions */
+#define IWL_GF_NVM_VERSION 0x0a1d
+
+const struct iwl_rf_cfg iwl_rf_gf = {
+ .uhb_supported = true,
+ .led_mode = IWL_LED_RF_STATE,
+ .non_shared_ant = ANT_B,
+ .vht_mu_mimo_supported = true,
+ .ht_params = {
+ .stbc = true,
+ .ldpc = true,
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) |
+ BIT(NL80211_BAND_5GHZ),
+ },
+ .nvm_ver = IWL_GF_NVM_VERSION,
+ .nvm_type = IWL_NVM_EXT,
+ .num_rbds = IWL_NUM_RBDS_HE,
+ .ucode_api_min = IWL_GF_UCODE_API_MIN,
+ .ucode_api_max = IWL_GF_UCODE_API_MAX,
+};
+
+const char iwl_ax210_killer_1675w_name[] =
+ "Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)";
+const char iwl_ax210_killer_1675x_name[] =
+ "Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)";
+const char iwl_ax211_killer_1675s_name[] =
+ "Killer(R) Wi-Fi 6E AX1675s 160MHz Wireless Network Adapter (211D2W)";
+const char iwl_ax211_killer_1675i_name[] =
+ "Killer(R) Wi-Fi 6E AX1675i 160MHz Wireless Network Adapter (211NGW)";
+const char iwl_ax411_killer_1690s_name[] =
+ "Killer(R) Wi-Fi 6E AX1690s 160MHz Wireless Network Adapter (411D2W)";
+const char iwl_ax411_killer_1690i_name[] =
+ "Killer(R) Wi-Fi 6E AX1690i 160MHz Wireless Network Adapter (411NGW)";
+
+const char iwl_ax210_name[] = "Intel(R) Wi-Fi 6E AX210 160MHz";
+const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz";
+const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6E AX411 160MHz";
+
+IWL_FW_AND_PNVM(IWL_SO_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX);
+IWL_FW_AND_PNVM(IWL_TY_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX);
+IWL_FW_AND_PNVM(IWL_MA_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX);
+IWL_FW_AND_PNVM(IWL_MA_B_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX);
+IWL_FW_AND_PNVM(IWL_MA_A_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX);
+IWL_FW_AND_PNVM(IWL_MA_B_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX);
+MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_GF_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_GF_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SC_A_GF_A_MODULE_FIRMWARE(IWL_GF_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SC_A_GF4_A_MODULE_FIRMWARE(IWL_GF_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-hr.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-hr.c
new file mode 100644
index 000000000000..6cf187d92dbf
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-hr.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2015-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018-2025 Intel Corporation
+ */
+#include "iwl-config.h"
+
+/* Highest firmware API version supported */
+#define IWL_HR_UCODE_API_MAX 100
+
+/* Lowest firmware API version supported */
+#define IWL_HR_UCODE_API_MIN 100
+
+#define IWL_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0"
+#define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0"
+#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0"
+#define IWL_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0"
+#define IWL_MA_A_HR_B_FW_PRE "iwlwifi-ma-a0-hr-b0"
+#define IWL_MA_B_HR_B_FW_PRE "iwlwifi-ma-b0-hr-b0"
+#define IWL_BZ_A_HR_B_FW_PRE "iwlwifi-bz-a0-hr-b0"
+#define IWL_SC_A_HR_A_FW_PRE "iwlwifi-sc-a0-hr-b0"
+#define IWL_SC_A_HR_B_FW_PRE "iwlwifi-sc-a0-hr-b0"
+
+#define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \
+ IWL_QU_B_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_QUZ_A_HR_B_MODULE_FIRMWARE(api) \
+ IWL_QUZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_QU_C_HR_B_MODULE_FIRMWARE(api) \
+ IWL_QU_C_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SO_A_HR_B_MODULE_FIRMWARE(api) \
+ IWL_SO_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_B_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \
+ IWL_BZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_HR_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+
+/* NVM versions */
+#define IWL_HR_NVM_VERSION 0x0a1d
+
+#define IWL_DEVICE_HR \
+ .led_mode = IWL_LED_RF_STATE, \
+ .non_shared_ant = ANT_B, \
+ .vht_mu_mimo_supported = true, \
+ .ht_params = { \
+ .stbc = true, \
+ .ldpc = true, \
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | \
+ BIT(NL80211_BAND_5GHZ), \
+ }, \
+ .num_rbds = IWL_NUM_RBDS_HE, \
+ .nvm_ver = IWL_HR_NVM_VERSION, \
+ .nvm_type = IWL_NVM_EXT, \
+ .ucode_api_min = IWL_HR_UCODE_API_MIN, \
+ .ucode_api_max = IWL_HR_UCODE_API_MAX
+
+const struct iwl_rf_cfg iwl_rf_hr1 = {
+ IWL_DEVICE_HR,
+ .tx_with_siso_diversity = true,
+};
+
+const struct iwl_rf_cfg iwl_rf_hr = {
+ IWL_DEVICE_HR,
+};
+
+const struct iwl_rf_cfg iwl_rf_hr_80mhz = {
+ IWL_DEVICE_HR,
+ .bw_limit = 80,
+};
+
+const char iwl_ax101_name[] = "Intel(R) Wi-Fi 6 AX101";
+const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz";
+const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz";
+const char iwl_ax203_name[] = "Intel(R) Wi-Fi 6 AX203";
+
+MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-jf.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-jf.c
new file mode 100644
index 000000000000..0a074e0a3bc6
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-jf.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2015-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018-2021, 2023, 2025 Intel Corporation
+ */
+#include "iwl-config.h"
+
+/* Highest firmware API version supported */
+#define IWL_JF_UCODE_API_MAX 77
+
+/* Lowest firmware API version supported */
+#define IWL_JF_UCODE_API_MIN 77
+
+#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0"
+#define IWL_QU_C_JF_B_FW_PRE "iwlwifi-Qu-c0-jf-b0"
+#define IWL_QUZ_A_JF_B_FW_PRE "iwlwifi-QuZ-a0-jf-b0"
+#define IWL_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0"
+
+#define IWL_QUZ_A_JF_B_MODULE_FIRMWARE(api) \
+ IWL_QUZ_A_JF_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \
+ IWL_QU_B_JF_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_QU_C_JF_B_MODULE_FIRMWARE(api) \
+ IWL_QU_C_JF_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SO_A_JF_B_MODULE_FIRMWARE(api) \
+ IWL_SO_A_JF_B_FW_PRE "-" __stringify(api) ".ucode"
+
+/* NVM versions */
+#define IWL_JF_NVM_VERSION 0x0a1d
+
+/* Memory offsets and lengths */
+#define IWL9000_DCCM_OFFSET 0x800000
+#define IWL9000_DCCM_LEN 0x18000
+#define IWL9000_DCCM2_OFFSET 0x880000
+#define IWL9000_DCCM2_LEN 0x8000
+
+static const struct iwl_tt_params iwl_jf_tt_params = {
+ .ct_kill_entry = 115,
+ .ct_kill_exit = 93,
+ .ct_kill_duration = 5,
+ .dynamic_smps_entry = 111,
+ .dynamic_smps_exit = 107,
+ .tx_protection_entry = 112,
+ .tx_protection_exit = 105,
+ .tx_backoff = {
+ {.temperature = 110, .backoff = 200},
+ {.temperature = 111, .backoff = 600},
+ {.temperature = 112, .backoff = 1200},
+ {.temperature = 113, .backoff = 2000},
+ {.temperature = 114, .backoff = 4000},
+ },
+ .support_ct_kill = true,
+ .support_dynamic_smps = true,
+ .support_tx_protection = true,
+ .support_tx_backoff = true,
+};
+
+/* these values are ignored if not with Pu/Th MAC firmware, due to offload */
+#define IWL_DEVICE_JF_PU \
+ .dccm_offset = IWL9000_DCCM_OFFSET, \
+ .dccm_len = IWL9000_DCCM_LEN, \
+ .dccm2_offset = IWL9000_DCCM2_OFFSET, \
+ .dccm2_len = IWL9000_DCCM2_LEN, \
+ .thermal_params = &iwl_jf_tt_params
+
+#define IWL_DEVICE_JF \
+ IWL_DEVICE_JF_PU, \
+ .led_mode = IWL_LED_RF_STATE, \
+ .non_shared_ant = ANT_B, \
+ .num_rbds = IWL_NUM_RBDS_NON_HE, \
+ .vht_mu_mimo_supported = true, \
+ .ht_params = { \
+ .stbc = true, \
+ .ldpc = true, \
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | \
+ BIT(NL80211_BAND_5GHZ), \
+ }, \
+ .nvm_ver = IWL_JF_NVM_VERSION, \
+ .nvm_type = IWL_NVM_EXT, \
+ .ucode_api_min = IWL_JF_UCODE_API_MIN, \
+ .ucode_api_max = IWL_JF_UCODE_API_MAX
+
+const struct iwl_rf_cfg iwl_rf_jf = {
+ IWL_DEVICE_JF,
+};
+
+const struct iwl_rf_cfg iwl_rf_jf_80mhz = {
+ IWL_DEVICE_JF,
+ .bw_limit = 80,
+};
+
+const char iwl9260_name[] = "Intel(R) Wireless-AC 9260";
+const char iwl9461_name[] = "Intel(R) Wireless-AC 9461";
+const char iwl9462_name[] = "Intel(R) Wireless-AC 9462";
+const char iwl9560_name[] = "Intel(R) Wireless-AC 9560";
+const char iwl9260_160_name[] = "Intel(R) Wireless-AC 9260 160MHz";
+const char iwl9461_160_name[] = "Intel(R) Wireless-AC 9461 160MHz";
+const char iwl9462_160_name[] = "Intel(R) Wireless-AC 9462 160MHz";
+const char iwl9560_160_name[] = "Intel(R) Wireless-AC 9560 160MHz";
+
+const char iwl9260_killer_1550_name[] =
+ "Killer(R) Wireless-AC 1550 Wireless Network Adapter (9260NGW) 160MHz";
+const char iwl9560_killer_1550i_name[] =
+ "Killer(R) Wireless-AC 1550i Wireless Network Adapter (9560NGW) 160MHz";
+const char iwl9560_killer_1550s_name[] =
+ "Killer(R) Wireless-AC 1550s Wireless Network Adapter (9560D2W) 160MHz";
+
+MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_JF_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_QU_C_JF_B_MODULE_FIRMWARE(IWL_JF_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_QUZ_A_JF_B_MODULE_FIRMWARE(IWL_JF_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_JF_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-pe.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-pe.c
new file mode 100644
index 000000000000..408b9850bd10
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-pe.c
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2025 Intel Corporation
+ */
+#include "iwl-config.h"
+
+/* currently iwl_rf_wh/iwl_rf_wh_160mhz are just defines for the FM ones */
+
+const char iwl_killer_bn1850w2_name[] =
+ "Killer(R) Wi-Fi 8 BN1850w2 320MHz Wireless Network Adapter (BN201.D2W)";
+const char iwl_killer_bn1850i_name[] =
+ "Killer(R) Wi-Fi 8 BN1850i 320MHz Wireless Network Adapter (BN201.NGW)";
+
+const char iwl_bn201_name[] = "Intel(R) Wi-Fi 8 BN201";
+const char iwl_bn203_name[] = "Intel(R) Wi-Fi 8 BN203";
+const char iwl_be221_name[] = "Intel(R) Wi-Fi 7 BE221";
+const char iwl_be223_name[] = "Intel(R) Wi-Fi 7 BE223";
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-wh.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-wh.c
new file mode 100644
index 000000000000..b5803ea1eb78
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-wh.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2025 Intel Corporation
+ */
+#include "iwl-config.h"
+
+/* NVM versions */
+#define IWL_WH_NVM_VERSION 0x0a1d
+
+#define IWL_DEVICE_WH \
+ .ht_params = { \
+ .stbc = true, \
+ .ldpc = true, \
+ .ht40_bands = BIT(NL80211_BAND_2GHZ) | \
+ BIT(NL80211_BAND_5GHZ), \
+ }, \
+ .led_mode = IWL_LED_RF_STATE, \
+ .non_shared_ant = ANT_B, \
+ .vht_mu_mimo_supported = true, \
+ .uhb_supported = true, \
+ .num_rbds = IWL_NUM_RBDS_EHT, \
+ .nvm_ver = IWL_WH_NVM_VERSION, \
+ .nvm_type = IWL_NVM_EXT
+
+/* currently iwl_rf_wh/iwl_rf_wh_160mhz are just defines for the FM ones */
+
+const struct iwl_rf_cfg iwl_rf_wh_non_eht = {
+ IWL_DEVICE_WH,
+ .eht_supported = false,
+};
+
+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_be211_name[] = "Intel(R) Wi-Fi 7 BE211 320MHz";
+const char iwl_be213_name[] = "Intel(R) Wi-Fi 7 BE213 160MHz";
+const char iwl_ax221_name[] = "Intel(R) Wi-Fi 6E AX221 160MHz";
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
index 59af36960f9c..ee00b2af7a1d 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
@@ -9,42 +9,26 @@
#include "iwl-prph.h"
#include "fw/api/txq.h"
-/* Highest firmware API version supported */
-#define IWL_SC_UCODE_API_MAX 98
+/* Highest firmware core release supported */
+#define IWL_SC_UCODE_CORE_MAX 101
/* Lowest firmware API version supported */
-#define IWL_SC_UCODE_API_MIN 93
+#define IWL_SC_UCODE_API_MIN 100
/* NVM versions */
#define IWL_SC_NVM_VERSION 0x0a1d
/* Memory offsets and lengths */
-#define IWL_SC_DCCM_OFFSET 0x800000 /* LMAC1 */
-#define IWL_SC_DCCM_LEN 0x10000 /* LMAC1 */
-#define IWL_SC_DCCM2_OFFSET 0x880000
-#define IWL_SC_DCCM2_LEN 0x8000
#define IWL_SC_SMEM_OFFSET 0x400000
#define IWL_SC_SMEM_LEN 0xD0000
#define IWL_SC_A_FM_B_FW_PRE "iwlwifi-sc-a0-fm-b0"
#define IWL_SC_A_FM_C_FW_PRE "iwlwifi-sc-a0-fm-c0"
-#define IWL_SC_A_HR_A_FW_PRE "iwlwifi-sc-a0-hr-b0"
-#define IWL_SC_A_HR_B_FW_PRE "iwlwifi-sc-a0-hr-b0"
-#define IWL_SC_A_GF_A_FW_PRE "iwlwifi-sc-a0-gf-a0"
-#define IWL_SC_A_GF4_A_FW_PRE "iwlwifi-sc-a0-gf4-a0"
#define IWL_SC_A_WH_A_FW_PRE "iwlwifi-sc-a0-wh-a0"
#define IWL_SC2_A_FM_C_FW_PRE "iwlwifi-sc2-a0-fm-c0"
#define IWL_SC2_A_WH_A_FW_PRE "iwlwifi-sc2-a0-wh-a0"
-#define IWL_SC2F_A_FM_C_FW_PRE "iwlwifi-sc2f-a0-fm-c0"
-#define IWL_SC2F_A_WH_A_FW_PRE "iwlwifi-sc2f-a0-wh-a0"
-#define IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(api) \
- IWL_SC_A_HR_A_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(api) \
- IWL_SC_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
-
-static const struct iwl_base_params iwl_sc_base_params = {
- .eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
+static const struct iwl_family_base_params iwl_sc_base = {
.num_of_queues = 512,
.max_tfd_queue_size = 65536,
.shadow_ram_support = true,
@@ -53,87 +37,54 @@ static const struct iwl_base_params iwl_sc_base_params = {
.max_event_log_size = 512,
.shadow_reg_enable = true,
.pcie_l1_allowed = true,
+ .smem_offset = IWL_SC_SMEM_OFFSET,
+ .smem_len = IWL_SC_SMEM_LEN,
+ .apmg_not_supported = true,
+ .mac_addr_from_csr = 0x30,
+ .d3_debug_data_base_addr = 0x401000,
+ .d3_debug_data_length = 60 * 1024,
+ .mon_smem_regs = {
+ .write_ptr = {
+ .addr = LDBG_M2S_BUF_WPTR,
+ .mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
+ },
+ .cycle_cnt = {
+ .addr = LDBG_M2S_BUF_WRAP_CNT,
+ .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
+ },
+ },
+ .min_txq_size = 128,
+ .gp2_reg_addr = 0xd02c68,
+ .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT,
+ .mon_dram_regs = {
+ .write_ptr = {
+ .addr = DBGC_CUR_DBGBUF_STATUS,
+ .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK,
+ },
+ .cycle_cnt = {
+ .addr = DBGC_DBGBUF_WRAP_AROUND,
+ .mask = 0xffffffff,
+ },
+ .cur_frag = {
+ .addr = DBGC_CUR_DBGBUF_STATUS,
+ .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK,
+ },
+ },
+ .mon_dbgi_regs = {
+ .write_ptr = {
+ .addr = DBGI_SRAM_FIFO_POINTERS,
+ .mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK,
+ },
+ },
+ .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
+ .ucode_api_max = ENCODE_CORE_AS_API(IWL_SC_UCODE_CORE_MAX),
+ .ucode_api_min = IWL_SC_UCODE_API_MIN,
};
-#define IWL_DEVICE_BZ_COMMON \
- .ucode_api_max = IWL_SC_UCODE_API_MAX, \
- .ucode_api_min = IWL_SC_UCODE_API_MIN, \
- .led_mode = IWL_LED_RF_STATE, \
- .nvm_hw_section_num = 10, \
- .non_shared_ant = ANT_B, \
- .dccm_offset = IWL_SC_DCCM_OFFSET, \
- .dccm_len = IWL_SC_DCCM_LEN, \
- .dccm2_offset = IWL_SC_DCCM2_OFFSET, \
- .dccm2_len = IWL_SC_DCCM2_LEN, \
- .smem_offset = IWL_SC_SMEM_OFFSET, \
- .smem_len = IWL_SC_SMEM_LEN, \
- .apmg_not_supported = true, \
- .trans.mq_rx_supported = true, \
- .vht_mu_mimo_supported = true, \
- .mac_addr_from_csr = 0x30, \
- .nvm_ver = IWL_SC_NVM_VERSION, \
- .trans.rf_id = true, \
- .trans.gen2 = true, \
- .nvm_type = IWL_NVM_EXT, \
- .dbgc_supported = true, \
- .min_umac_error_event_table = 0xD0000, \
- .d3_debug_data_base_addr = 0x401000, \
- .d3_debug_data_length = 60 * 1024, \
- .mon_smem_regs = { \
- .write_ptr = { \
- .addr = LDBG_M2S_BUF_WPTR, \
- .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
- }, \
- .cycle_cnt = { \
- .addr = LDBG_M2S_BUF_WRAP_CNT, \
- .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
- }, \
- }, \
- .trans.umac_prph_offset = 0x300000, \
- .trans.device_family = IWL_DEVICE_FAMILY_SC, \
- .trans.base_params = &iwl_sc_base_params, \
- .min_txq_size = 128, \
- .gp2_reg_addr = 0xd02c68, \
- .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT, \
- .mon_dram_regs = { \
- .write_ptr = { \
- .addr = DBGC_CUR_DBGBUF_STATUS, \
- .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
- }, \
- .cycle_cnt = { \
- .addr = DBGC_DBGBUF_WRAP_AROUND, \
- .mask = 0xffffffff, \
- }, \
- .cur_frag = { \
- .addr = DBGC_CUR_DBGBUF_STATUS, \
- .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
- }, \
- }, \
- .mon_dbgi_regs = { \
- .write_ptr = { \
- .addr = DBGI_SRAM_FIFO_POINTERS, \
- .mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK, \
- }, \
- }
-
-#define IWL_DEVICE_SC \
- IWL_DEVICE_BZ_COMMON, \
- .uhb_supported = true, \
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
- .num_rbds = IWL_NUM_RBDS_SC_EHT, \
- .ht_params = &iwl_bz_ht_params
-
-/*
- * This size was picked according to 8 MSDUs inside 512 A-MSDUs in an
- * A-MPDU, with additional overhead to account for processing time.
- */
-#define IWL_NUM_RBDS_SC_EHT (512 * 16)
-
-const struct iwl_cfg_trans_params iwl_sc_trans_cfg = {
+const struct iwl_mac_cfg iwl_sc_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_SC,
- .base_params = &iwl_sc_base_params,
+ .base = &iwl_sc_base,
.mq_rx_supported = true,
- .rf_id = true,
.gen2 = true,
.integrated = true,
.umac_prph_offset = 0x300000,
@@ -142,29 +93,8 @@ const struct iwl_cfg_trans_params iwl_sc_trans_cfg = {
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
};
-const struct iwl_cfg iwl_cfg_sc = {
- .fw_name_mac = "sc",
- IWL_DEVICE_SC,
-};
-
-const struct iwl_cfg iwl_cfg_sc2 = {
- .fw_name_mac = "sc2",
- IWL_DEVICE_SC,
-};
-
-const struct iwl_cfg iwl_cfg_sc2f = {
- .fw_name_mac = "sc2f",
- IWL_DEVICE_SC,
-};
-
-IWL_FW_AND_PNVM(IWL_SC_A_FM_B_FW_PRE, IWL_SC_UCODE_API_MAX);
-IWL_FW_AND_PNVM(IWL_SC_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX);
-MODULE_FIRMWARE(IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
-IWL_FW_AND_PNVM(IWL_SC_A_GF_A_FW_PRE, IWL_SC_UCODE_API_MAX);
-IWL_FW_AND_PNVM(IWL_SC_A_GF4_A_FW_PRE, IWL_SC_UCODE_API_MAX);
-IWL_FW_AND_PNVM(IWL_SC_A_WH_A_FW_PRE, IWL_SC_UCODE_API_MAX);
-IWL_FW_AND_PNVM(IWL_SC2_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX);
-IWL_FW_AND_PNVM(IWL_SC2_A_WH_A_FW_PRE, IWL_SC_UCODE_API_MAX);
-IWL_FW_AND_PNVM(IWL_SC2F_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX);
-IWL_FW_AND_PNVM(IWL_SC2F_A_WH_A_FW_PRE, IWL_SC_UCODE_API_MAX);
+IWL_CORE_FW(IWL_SC_A_FM_B_FW_PRE, IWL_SC_UCODE_CORE_MAX);
+IWL_CORE_FW(IWL_SC_A_FM_C_FW_PRE, IWL_SC_UCODE_CORE_MAX);
+IWL_CORE_FW(IWL_SC_A_WH_A_FW_PRE, IWL_SC_UCODE_CORE_MAX);
+IWL_CORE_FW(IWL_SC2_A_FM_C_FW_PRE, IWL_SC_UCODE_CORE_MAX);
+IWL_CORE_FW(IWL_SC2_A_WH_A_FW_PRE, IWL_SC_UCODE_CORE_MAX);
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h
index a13add556a7b..9d99374ee093 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2021, 2024 Intel Corporation
+ * Copyright (C) 2005-2014, 2021, 2024-2025 Intel Corporation
*/
#ifndef __iwl_agn_h__
#define __iwl_agn_h__
@@ -88,7 +88,7 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv,
int iwlagn_set_pan_params(struct iwl_priv *priv);
int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
-int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed);
+int iwlagn_mac_config(struct ieee80211_hw *hw, int radio_idx, u32 changed);
void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
@@ -388,7 +388,7 @@ static inline void iwl_dvm_set_pmi(struct iwl_priv *priv, bool state)
/**
* iwl_parse_eeprom_data - parse EEPROM data and return values
*
- * @trans: ransport we're parsing for, for debug only
+ * @trans: transport we're parsing for, for debug only
* @cfg: device configuration for parsing and overrides
* @eeprom: the EEPROM data
* @eeprom_size: length of the EEPROM data
@@ -397,9 +397,11 @@ static inline void iwl_dvm_set_pmi(struct iwl_priv *priv, bool state)
* returns a (newly allocated) struct containing all the
* relevant values for driver use. The struct must be freed
* later with iwl_free_nvm_data().
+ *
+ * Return: the parsed NVM data
*/
struct iwl_nvm_data *
-iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
+iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
const u8 *eeprom, size_t eeprom_size);
int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size);
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/commands.h b/drivers/net/wireless/intel/iwlwifi/dvm/commands.h
index 96ea6c8dfc89..138b11f51d00 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/commands.h
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/commands.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2023-2024 Intel Corporation
+ * Copyright (C) 2005-2014, 2023-2025 Intel Corporation
*/
/*
* Please use this file (commands.h) only for uCode API definitions.
@@ -614,7 +614,7 @@ struct iwl_rxon_time_cmd {
* REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response)
*/
/**
- * struct iwl5000_channel_switch_cmd
+ * struct iwl5000_channel_switch_cmd - channel switch command (5000 series)
* @band: 0- 5.2GHz, 1- 2.4GHz
* @expect_beacon: 0- resume transmits after channel switch
* 1- wait for beacon to resume transmits
@@ -635,7 +635,7 @@ struct iwl5000_channel_switch_cmd {
} __packed;
/**
- * struct iwl6000_channel_switch_cmd
+ * struct iwl6000_channel_switch_cmd - channel switch command (6000 series)
* @band: 0- 5.2GHz, 1- 2.4GHz
* @expect_beacon: 0- resume transmits after channel switch
* 1- wait for beacon to resume transmits
@@ -791,7 +791,7 @@ struct iwl_keyinfo {
} __packed;
/**
- * struct sta_id_modify
+ * struct sta_id_modify - station modify command
* @addr: station's MAC address
* @reserved1: reserved for alignment
* @sta_id: index of station in uCode's station table
@@ -2026,7 +2026,7 @@ struct iwl_spectrum_notification {
u8 channel;
u8 type; /* see enum iwl_measurement_type */
u8 reserved1;
- /* NOTE: cca_ofdm, cca_cck, basic_type, and histogram are only only
+ /* NOTE: cca_ofdm, cca_cck, basic_type, and histogram are only
* valid if applicable for measurement type requested. */
__le32 cca_ofdm; /* cca fraction time in 40Mhz clock periods */
__le32 cca_cck; /* cca fraction time in 44Mhz clock periods */
@@ -2992,7 +2992,7 @@ struct iwl_missed_beacon_notif {
#define SENSITIVITY_CMD_CONTROL_WORK_TABLE cpu_to_le16(1)
/**
- * struct iwl_sensitivity_cmd
+ * struct iwl_sensitivity_cmd - sensitivity configuration command
* @control: (1) updates working table, (0) updates default table
* @table: energy threshold values, use HD_* as index into table
*
@@ -3848,7 +3848,7 @@ struct iwlagn_wowlan_status {
#define IWL_MIN_SLOT_TIME 20
/**
- * struct iwl_wipan_slot
+ * struct iwl_wipan_slot - WiPAN slot configuration
* @width: Time in TU
* @type:
* 0 - BSS
@@ -3868,7 +3868,7 @@ struct iwl_wipan_slot {
#define IWL_WIPAN_PARAMS_FLG_FULL_SLOTTED_MODE BIT(5)
/**
- * struct iwl_wipan_params_cmd
+ * struct iwl_wipan_params_cmd - WiPAN parameters
* @flags:
* bit0: reserved
* bit1: CP leave channel with CTS
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c
index 2ed4b6e798ab..ec94c43ba28c 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018, 2025 Intel Corporation
*****************************************************************************/
#include <linux/slab.h>
@@ -2097,7 +2097,8 @@ static ssize_t iwl_dbgfs_protection_mode_read(struct file *file,
char buf[40];
const size_t bufsz = sizeof(buf);
- if (priv->cfg->ht_params)
+ /* HT devices also have at least one HT40 band */
+ if (priv->cfg->ht_params.ht40_bands)
pos += scnprintf(buf + pos, bufsz - pos,
"use %s for aggregation\n",
(priv->hw_params.use_rts_for_aggregation) ?
@@ -2117,7 +2118,8 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,
int buf_size;
int rts;
- if (!priv->cfg->ht_params)
+ /* HT devices also have at least one HT40 band */
+ if (!priv->cfg->ht_params.ht40_bands)
return -EINVAL;
memset(buf, 0, sizeof(buf));
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/dev.h b/drivers/net/wireless/intel/iwlwifi/dvm/dev.h
index 4ac8b862ad41..4d12bf901703 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/dev.h
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/dev.h
@@ -2,6 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014, 2020, 2023 Intel Corporation. All rights reserved.
+ * Copyright (C) 2025 Intel Corporation
*****************************************************************************/
/*
* Please use this file (dev.h) for driver implementation definitions.
@@ -103,7 +104,7 @@ struct iwl_qos_info {
};
/**
- * enum iwl_agg_state
+ * enum iwl_agg_state - aggregation state
*
* The state machine of the BA agreement establishment / tear down.
* These states relate to a specific RA / TID.
@@ -518,7 +519,7 @@ enum iwl_scan_type {
};
/**
- * struct iwl_hw_params
+ * struct iwl_hw_params - HW parameters
*
* Holds the module parameters
*
@@ -627,7 +628,7 @@ struct iwl_priv {
struct iwl_trans *trans;
struct device *dev; /* for debug prints only */
- const struct iwl_cfg *cfg;
+ const struct iwl_rf_cfg *cfg;
const struct iwl_fw *fw;
const struct iwl_dvm_cfg *lib;
unsigned long status;
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c
index 48a8349680fc..be7e61e2b291 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
- * Copyright (C) 2019 Intel Corporation
+ * Copyright (C) 2019, 2025 Intel Corporation
*****************************************************************************/
#include <linux/units.h>
@@ -55,6 +55,7 @@ static void iwl1000_nic_config(struct iwl_priv *priv)
* iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time
* @priv: pointer to iwl_priv data structure
* @tsf_bits: number of bits need to shift for masking)
+ * Return: low 32 bits of beacon time mask
*/
static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv,
u16 tsf_bits)
@@ -66,6 +67,7 @@ static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv,
* iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time
* @priv: pointer to iwl_priv data structure
* @tsf_bits: number of bits need to shift for masking)
+ * Return: high 32 bits of beacon time mask
*/
static inline u32 iwl_beacon_time_mask_high(struct iwl_priv *priv,
u16 tsf_bits)
@@ -481,7 +483,7 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
/* NIC configuration for 6000 series */
static void iwl6000_nic_config(struct iwl_priv *priv)
{
- switch (priv->trans->trans_cfg->device_family) {
+ switch (priv->trans->mac_cfg->device_family) {
case IWL_DEVICE_FAMILY_6005:
case IWL_DEVICE_FAMILY_6030:
case IWL_DEVICE_FAMILY_6000:
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c b/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c
index cdc05f7e75a6..d337ab543eb0 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2005-2014, 2018-2019, 2021, 2024 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2019, 2021, 2024-2025 Intel Corporation
*/
#include <linux/types.h>
#include <linux/slab.h>
@@ -151,7 +151,7 @@ static u16 iwl_eeprom_query16(const u8 *eeprom, size_t eeprom_size, int offset)
{
if (WARN_ON(offset + sizeof(u16) > eeprom_size))
return 0;
- return le16_to_cpup((__le16 *)(eeprom + offset));
+ return le16_to_cpup((const __le16 *)(eeprom + offset));
}
static u32 eeprom_indirect_address(const u8 *eeprom, size_t eeprom_size,
@@ -204,8 +204,8 @@ static u32 eeprom_indirect_address(const u8 *eeprom, size_t eeprom_size,
return (address & ADDRESS_MSK) + (offset << 1);
}
-static const u8 *iwl_eeprom_query_addr(const u8 *eeprom, size_t eeprom_size,
- u32 offset)
+static const void *iwl_eeprom_query_addr(const u8 *eeprom, size_t eeprom_size,
+ u32 offset)
{
u32 address = eeprom_indirect_address(eeprom, eeprom_size, offset);
@@ -218,10 +218,9 @@ static const u8 *iwl_eeprom_query_addr(const u8 *eeprom, size_t eeprom_size,
static int iwl_eeprom_read_calib(const u8 *eeprom, size_t eeprom_size,
struct iwl_nvm_data *data)
{
- struct iwl_eeprom_calib_hdr *hdr;
+ const struct iwl_eeprom_calib_hdr *hdr;
- hdr = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size,
- EEPROM_CALIB_ALL);
+ hdr = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_CALIB_ALL);
if (!hdr)
return -ENODATA;
data->calib_version = hdr->version;
@@ -295,7 +294,7 @@ struct iwl_eeprom_enhanced_txpwr {
} __packed;
static s8 iwl_get_max_txpwr_half_dbm(const struct iwl_nvm_data *data,
- struct iwl_eeprom_enhanced_txpwr *txp)
+ const struct iwl_eeprom_enhanced_txpwr *txp)
{
s8 result = 0; /* (.5 dBm) */
@@ -329,7 +328,7 @@ static s8 iwl_get_max_txpwr_half_dbm(const struct iwl_nvm_data *data,
static void
iwl_eeprom_enh_txp_read_element(struct iwl_nvm_data *data,
- struct iwl_eeprom_enhanced_txpwr *txp,
+ const struct iwl_eeprom_enhanced_txpwr *txp,
int n_channels, s8 max_txpower_avg)
{
int ch_idx;
@@ -360,20 +359,18 @@ static void iwl_eeprom_enhanced_txpower(struct device *dev,
const u8 *eeprom, size_t eeprom_size,
int n_channels)
{
- struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
+ const struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
int idx, entries;
- __le16 *txp_len;
+ const __le16 *txp_len;
s8 max_txp_avg_halfdbm;
BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);
/* the length is in 16-bit words, but we want entries */
- txp_len = (__le16 *)iwl_eeprom_query_addr(eeprom, eeprom_size,
- EEPROM_TXP_SZ_OFFS);
+ txp_len = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_TXP_SZ_OFFS);
entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
- txp_array = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size,
- EEPROM_TXP_OFFS);
+ txp_array = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_TXP_OFFS);
for (idx = 0; idx < entries; idx++) {
txp = &txp_array[idx];
@@ -416,7 +413,7 @@ static void iwl_eeprom_enhanced_txpower(struct device *dev,
}
}
-static void iwl_init_band_reference(const struct iwl_cfg *cfg,
+static void iwl_init_band_reference(const struct iwl_rf_cfg *cfg,
const u8 *eeprom, size_t eeprom_size,
int eeprom_band, int *eeprom_ch_count,
const struct iwl_eeprom_channel **ch_info,
@@ -426,7 +423,7 @@ static void iwl_init_band_reference(const struct iwl_cfg *cfg,
offset |= INDIRECT_ADDRESS | INDIRECT_REGULATORY;
- *ch_info = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size, offset);
+ *ch_info = iwl_eeprom_query_addr(eeprom, eeprom_size, offset);
switch (eeprom_band) {
case 1: /* 2.4GHz band */
@@ -510,7 +507,7 @@ static void iwl_mod_ht40_chan_info(struct device *dev,
#define CHECK_AND_PRINT_I(x) \
((eeprom_ch_info[ch_idx].flags & EEPROM_CHANNEL_##x) ? # x " " : "")
-static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
+static int iwl_init_channel_map(struct device *dev, const struct iwl_rf_cfg *cfg,
struct iwl_nvm_data *data,
const u8 *eeprom, size_t eeprom_size)
{
@@ -679,15 +676,14 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans)
CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM);
/* See if we got it */
- ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG,
- CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM,
- CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM,
- IWL_EEPROM_SEM_TIMEOUT);
- if (ret >= 0) {
+ ret = iwl_poll_bits(trans, CSR_HW_IF_CONFIG_REG,
+ CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM,
+ IWL_EEPROM_SEM_TIMEOUT);
+ if (!ret) {
IWL_DEBUG_EEPROM(trans->dev,
"Acquired semaphore after %d tries.\n",
count+1);
- return ret;
+ return 0;
}
}
@@ -749,7 +745,7 @@ static int iwl_nvm_is_otp(struct iwl_trans *trans)
u32 otpgp;
/* OTP only valid for CP/PP and after */
- switch (trans->hw_rev & CSR_HW_REV_TYPE_MSK) {
+ switch (trans->info.hw_rev & CSR_HW_REV_TYPE_MSK) {
case CSR_HW_REV_TYPE_NONE:
IWL_ERR(trans, "Unknown hardware type\n");
return -EIO;
@@ -770,7 +766,7 @@ static int iwl_init_otp_access(struct iwl_trans *trans)
{
int ret;
- ret = iwl_finish_nic_init(trans);
+ ret = iwl_trans_activate_nic(trans);
if (ret)
return ret;
@@ -784,7 +780,7 @@ static int iwl_init_otp_access(struct iwl_trans *trans)
* CSR auto clock gate disable bit -
* this is only applicable for HW with OTP shadow RAM
*/
- if (trans->trans_cfg->base_params->shadow_ram_support)
+ if (trans->mac_cfg->base->shadow_ram_support)
iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
CSR_RESET_LINK_PWR_MGMT_DISABLED);
@@ -800,11 +796,10 @@ static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr,
iwl_write32(trans, CSR_EEPROM_REG,
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
- ret = iwl_poll_bit(trans, CSR_EEPROM_REG,
- CSR_EEPROM_REG_READ_VALID_MSK,
- CSR_EEPROM_REG_READ_VALID_MSK,
- IWL_EEPROM_ACCESS_TIMEOUT);
- if (ret < 0) {
+ ret = iwl_poll_bits(trans, CSR_EEPROM_REG,
+ CSR_EEPROM_REG_READ_VALID_MSK,
+ IWL_EEPROM_ACCESS_TIMEOUT);
+ if (ret) {
IWL_ERR(trans, "Time out reading OTP[%d]\n", addr);
return ret;
}
@@ -905,7 +900,7 @@ static int iwl_find_otp_image(struct iwl_trans *trans,
}
/* more in the link list, continue */
usedblocks++;
- } while (usedblocks <= trans->trans_cfg->base_params->max_ll_items);
+ } while (usedblocks <= trans->mac_cfg->base->max_ll_items);
/* OTP has no valid blocks */
IWL_DEBUG_EEPROM(trans->dev, "OTP has no valid blocks\n");
@@ -938,7 +933,7 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
if (nvm_is_otp < 0)
return nvm_is_otp;
- sz = trans->trans_cfg->base_params->eeprom_size;
+ sz = trans->mac_cfg->base->eeprom_size;
IWL_DEBUG_EEPROM(trans->dev, "NVM size = %d\n", sz);
e = kmalloc(sz, GFP_KERNEL);
@@ -946,14 +941,14 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
return -ENOMEM;
ret = iwl_eeprom_verify_signature(trans, nvm_is_otp);
- if (ret < 0) {
+ if (ret) {
IWL_ERR(trans, "EEPROM not found, EEPROM_GP=0x%08x\n", gp);
goto err_free;
}
/* Make sure driver (instead of uCode) is allowed to read EEPROM */
ret = iwl_eeprom_acquire_semaphore(trans);
- if (ret < 0) {
+ if (ret) {
IWL_ERR(trans, "Failed to acquire EEPROM semaphore.\n");
goto err_free;
}
@@ -973,7 +968,7 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
/* traversing the linked list if no shadow ram supported */
- if (!trans->trans_cfg->base_params->shadow_ram_support) {
+ if (!trans->mac_cfg->base->shadow_ram_support) {
ret = iwl_find_otp_image(trans, &validblockaddr);
if (ret)
goto err_unlock;
@@ -996,11 +991,10 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
iwl_write32(trans, CSR_EEPROM_REG,
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
- ret = iwl_poll_bit(trans, CSR_EEPROM_REG,
- CSR_EEPROM_REG_READ_VALID_MSK,
- CSR_EEPROM_REG_READ_VALID_MSK,
- IWL_EEPROM_ACCESS_TIMEOUT);
- if (ret < 0) {
+ ret = iwl_poll_bits(trans, CSR_EEPROM_REG,
+ CSR_EEPROM_REG_READ_VALID_MSK,
+ IWL_EEPROM_ACCESS_TIMEOUT);
+ if (ret) {
IWL_ERR(trans,
"Time out reading EEPROM[%d]\n", addr);
goto err_unlock;
@@ -1027,7 +1021,7 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
return ret;
}
-static void iwl_init_sbands(struct iwl_trans *trans, const struct iwl_cfg *cfg,
+static void iwl_init_sbands(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
struct iwl_nvm_data *data,
const u8 *eeprom, size_t eeprom_size)
{
@@ -1062,7 +1056,7 @@ static void iwl_init_sbands(struct iwl_trans *trans, const struct iwl_cfg *cfg,
/* EEPROM data functions */
struct iwl_nvm_data *
-iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
+iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
const u8 *eeprom, size_t eeprom_size)
{
struct iwl_nvm_data *data;
@@ -1098,14 +1092,14 @@ iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
EEPROM_RAW_TEMPERATURE);
if (!tmp)
goto err_free;
- data->raw_temperature = *(__le16 *)tmp;
+ data->raw_temperature = *(const __le16 *)tmp;
tmp = iwl_eeprom_query_addr(eeprom, eeprom_size,
EEPROM_KELVIN_TEMPERATURE);
if (!tmp)
goto err_free;
- data->kelvin_temperature = *(__le16 *)tmp;
- data->kelvin_voltage = *((__le16 *)tmp + 1);
+ data->kelvin_temperature = *(const __le16 *)tmp;
+ data->kelvin_voltage = *((const __le16 *)tmp + 1);
radio_cfg =
iwl_eeprom_query16(eeprom, eeprom_size, EEPROM_RADIO_CONFIG);
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/led.c b/drivers/net/wireless/intel/iwlwifi/dvm/led.c
index 5ca85d90a8d6..cec2ebdfd651 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/led.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/led.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
- * Copyright (C) 2019 Intel Corporation
+ * Copyright (C) 2019, 2025 Intel Corporation
*****************************************************************************/
@@ -116,9 +116,9 @@ static int iwl_led_cmd(struct iwl_priv *priv,
}
led_cmd.on = iwl_blink_compensation(priv, on,
- priv->trans->trans_cfg->base_params->led_compensation);
+ priv->trans->mac_cfg->base->led_compensation);
led_cmd.off = iwl_blink_compensation(priv, off,
- priv->trans->trans_cfg->base_params->led_compensation);
+ priv->trans->mac_cfg->base->led_compensation);
ret = iwl_send_led_cmd(priv, &led_cmd);
if (!ret) {
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c
index 1dc974e2c511..48711dbcfa5a 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c
@@ -586,7 +586,7 @@ static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv,
return false;
}
- ave_rssi = ieee80211_ave_rssi(ctx->vif);
+ ave_rssi = ieee80211_ave_rssi(ctx->vif, -1);
if (!ave_rssi) {
/* no rssi data, no changes to reduce tx power */
IWL_DEBUG_COEX(priv, "no rssi data available\n");
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
index 56d19a034c24..a0a26ef482a5 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
- * Copyright(C) 2018 - 2019, 2022 - 2024 Intel Corporation
+ * Copyright(C) 2018 - 2019, 2022 - 2025 Intel Corporation
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@@ -96,7 +96,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
- if (priv->trans->max_skb_frags)
+ if (priv->trans->info.max_skb_frags)
hw->netdev_features = NETIF_F_HIGHDMA | NETIF_F_SG;
hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE;
@@ -188,7 +188,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
priv->hw->wiphy->bands[NL80211_BAND_5GHZ] =
&priv->nvm_data->bands[NL80211_BAND_5GHZ];
- hw->wiphy->hw_version = priv->trans->hw_id;
+ hw->wiphy->hw_version = priv->trans->info.hw_id;
iwl_leds_init(priv);
@@ -378,7 +378,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
- iwl_trans_d3_suspend(priv->trans, false, true);
+ iwl_trans_d3_suspend(priv->trans, true);
goto out;
@@ -422,7 +422,6 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
struct ieee80211_vif *vif;
u32 base;
int ret;
- enum iwl_d3_status d3_status;
struct error_table_start {
/* cf. struct iwl_error_event_table */
u32 valid;
@@ -451,15 +450,10 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
/* we'll clear ctx->vif during iwlagn_prepare_restart() */
vif = ctx->vif;
- ret = iwl_trans_d3_resume(priv->trans, &d3_status, false, true);
+ ret = iwl_trans_d3_resume(priv->trans, true);
if (ret)
goto out_unlock;
- if (d3_status != IWL_D3_STATUS_ALIVE) {
- IWL_INFO(priv, "Device was reset during suspend\n");
- goto out_unlock;
- }
-
/* uCode is no longer operating by itself */
iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
@@ -549,7 +543,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
iwlagn_prepare_restart(priv);
- memset((void *)&ctx->active, 0, sizeof(ctx->active));
+ memset((void *)(uintptr_t)&ctx->active, 0, sizeof(ctx->active));
iwl_connection_init_rx_config(priv, ctx);
iwlagn_set_rxon_chain(priv, ctx);
@@ -1091,7 +1085,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
goto done;
}
- scd_queues = BIT(priv->trans->trans_cfg->base_params->num_of_queues) - 1;
+ scd_queues = BIT(priv->trans->mac_cfg->base->num_of_queues) - 1;
scd_queues &= ~(BIT(IWL_IPAN_CMD_QUEUE_NUM) |
BIT(IWL_DEFAULT_CMD_QUEUE_NUM));
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c
index a27a72cc017a..2b4dbebc71c2 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014, 2018 - 2022 Intel Corporation. All rights reserved.
- * Copyright(c) 2024 Intel Corporation. All rights reserved.
+ * Copyright(c) 2024-2025 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
*
* Portions of this file are derived from the ipw3945 project, as well
@@ -381,7 +381,8 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
*/
static void iwl_bg_statistics_periodic(struct timer_list *t)
{
- struct iwl_priv *priv = from_timer(priv, t, statistics_periodic);
+ struct iwl_priv *priv = timer_container_of(priv, t,
+ statistics_periodic);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
@@ -537,7 +538,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
*/
static void iwl_bg_ucode_trace(struct timer_list *t)
{
- struct iwl_priv *priv = from_timer(priv, t, ucode_trace);
+ struct iwl_priv *priv = timer_container_of(priv, t, ucode_trace);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
@@ -824,11 +825,11 @@ int iwl_alive_start(struct iwl_priv *priv)
iwlagn_send_tx_ant_config(priv, priv->nvm_data->valid_tx_ant);
if (iwl_is_associated_ctx(ctx) && !priv->wowlan) {
- struct iwl_rxon_cmd *active_rxon =
- (struct iwl_rxon_cmd *)&ctx->active;
+ struct iwl_rxon_cmd *active = (void *)(uintptr_t)&ctx->active;
+
/* apply any changes in staging */
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
- active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ active->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
} else {
struct iwl_rxon_context *tmp;
/* Initialize our rx_config data */
@@ -1048,9 +1049,11 @@ static void iwl_bg_restart(struct work_struct *data)
*
*****************************************************************************/
-static void iwl_setup_deferred_work(struct iwl_priv *priv)
+static int iwl_setup_deferred_work(struct iwl_priv *priv)
{
priv->workqueue = alloc_ordered_workqueue(DRV_NAME, 0);
+ if (!priv->workqueue)
+ return -ENOMEM;
INIT_WORK(&priv->restart, iwl_bg_restart);
INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
@@ -1067,6 +1070,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
timer_setup(&priv->statistics_periodic, iwl_bg_statistics_periodic, 0);
timer_setup(&priv->ucode_trace, iwl_bg_ucode_trace, 0);
+
+ return 0;
}
void iwl_cancel_deferred_work(struct iwl_priv *priv)
@@ -1137,9 +1142,10 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
static void iwl_set_hw_params(struct iwl_priv *priv)
{
- if (priv->cfg->ht_params)
+ /* there are no devices with HT but without HT40 on all bands */
+ if (priv->cfg->ht_params.ht40_bands)
priv->hw_params.use_rts_for_aggregation =
- priv->cfg->ht_params->use_rts_for_aggregation;
+ priv->cfg->ht_params.use_rts_for_aggregation;
/* Device-specific setup */
priv->lib->set_hw_params(priv);
@@ -1173,8 +1179,9 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
{
struct iwl_nvm_data *data = priv->nvm_data;
+ /* all HT devices also have HT40 on at least one band */
if (data->sku_cap_11n_enable &&
- !priv->cfg->ht_params) {
+ !priv->cfg->ht_params.ht40_bands) {
IWL_ERR(priv, "Invalid 11n configuration\n");
return -EINVAL;
}
@@ -1224,7 +1231,7 @@ static int iwl_nvm_check_version(struct iwl_nvm_data *data,
}
static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
- const struct iwl_cfg *cfg,
+ const struct iwl_rf_cfg *cfg,
const struct iwl_fw *fw,
struct dentry *dbgfs_dir)
{
@@ -1233,7 +1240,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
struct iwl_op_mode *op_mode;
u16 num_mac;
u32 ucode_flags;
- struct iwl_trans_config trans_cfg = {};
static const u8 no_reclaim_cmds[] = {
REPLY_RX_PHY_CMD,
REPLY_RX_MPDU_CMD,
@@ -1248,7 +1254,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
************************/
hw = iwl_alloc_all();
if (!hw) {
- pr_err("%s: Cannot allocate network device\n", trans->name);
+ pr_err("%s: Cannot allocate network device\n",
+ trans->info.name);
err = -ENOMEM;
goto out;
}
@@ -1261,7 +1268,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
priv->cfg = cfg;
priv->fw = fw;
- switch (priv->trans->trans_cfg->device_family) {
+ switch (priv->trans->mac_cfg->device_family) {
case IWL_DEVICE_FAMILY_1000:
case IWL_DEVICE_FAMILY_100:
priv->lib = &iwl_dvm_1000_cfg;
@@ -1309,52 +1316,51 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
* Populate the state variables that the transport layer needs
* to know about.
*/
- trans_cfg.op_mode = op_mode;
- trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
- trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
+ BUILD_BUG_ON(sizeof(no_reclaim_cmds) >
+ sizeof(trans->conf.no_reclaim_cmds));
+ memcpy(trans->conf.no_reclaim_cmds, no_reclaim_cmds,
+ sizeof(no_reclaim_cmds));
+ trans->conf.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
switch (iwlwifi_mod_params.amsdu_size) {
case IWL_AMSDU_DEF:
case IWL_AMSDU_4K:
- trans_cfg.rx_buf_size = IWL_AMSDU_4K;
+ trans->conf.rx_buf_size = IWL_AMSDU_4K;
break;
case IWL_AMSDU_8K:
- trans_cfg.rx_buf_size = IWL_AMSDU_8K;
+ trans->conf.rx_buf_size = IWL_AMSDU_8K;
break;
case IWL_AMSDU_12K:
default:
- trans_cfg.rx_buf_size = IWL_AMSDU_4K;
+ trans->conf.rx_buf_size = IWL_AMSDU_4K;
pr_err("Unsupported amsdu_size: %d\n",
iwlwifi_mod_params.amsdu_size);
}
- trans_cfg.command_groups = iwl_dvm_groups;
- trans_cfg.command_groups_size = ARRAY_SIZE(iwl_dvm_groups);
+ trans->conf.command_groups = iwl_dvm_groups;
+ trans->conf.command_groups_size = ARRAY_SIZE(iwl_dvm_groups);
- trans_cfg.cmd_fifo = IWLAGN_CMD_FIFO_NUM;
- trans_cfg.cb_data_offs = offsetof(struct ieee80211_tx_info,
- driver_data[2]);
+ trans->conf.cmd_fifo = IWLAGN_CMD_FIFO_NUM;
+ trans->conf.cb_data_offs = offsetof(struct ieee80211_tx_info,
+ driver_data[2]);
WARN_ON(sizeof(priv->transport_queue_stop) * BITS_PER_BYTE <
- priv->trans->trans_cfg->base_params->num_of_queues);
+ priv->trans->mac_cfg->base->num_of_queues);
ucode_flags = fw->ucode_capa.flags;
if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) {
priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
- trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
+ trans->conf.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
} else {
priv->sta_key_max_num = STA_KEY_MAX_NUM;
- trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
+ trans->conf.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
}
- /* Configure transport layer */
- iwl_trans_configure(priv->trans, &trans_cfg);
+ trans->conf.rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
+ trans->conf.rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start);
- trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
- trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start);
- trans->command_groups = trans_cfg.command_groups;
- trans->command_groups_size = trans_cfg.command_groups_size;
+ iwl_trans_op_mode_enter(priv->trans, op_mode);
/* At this point both hw and priv are allocated. */
@@ -1378,18 +1384,18 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
* 2. Read REV register
***********************/
IWL_INFO(priv, "Detected %s, REV=0x%X\n",
- priv->trans->name, priv->trans->hw_rev);
+ priv->trans->info.name, priv->trans->info.hw_rev);
err = iwl_trans_start_hw(priv->trans);
if (err)
- goto out_free_hw;
+ goto out_leave_trans;
/* Read the EEPROM */
err = iwl_read_eeprom(priv->trans, &priv->eeprom_blob,
&priv->eeprom_blob_size);
if (err) {
IWL_ERR(priv, "Unable to init EEPROM\n");
- goto out_free_hw;
+ goto out_leave_trans;
}
/* Reset chip to save power until we load uCode during "up". */
@@ -1437,10 +1443,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
* packaging bug or due to the eeprom check above
*/
priv->sta_key_max_num = STA_KEY_MAX_NUM;
- trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
-
- /* Configure transport layer again*/
- iwl_trans_configure(priv->trans, &trans_cfg);
+ trans->conf.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
}
/*******************
@@ -1464,7 +1467,10 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
/********************
* 6. Setup services
********************/
- iwl_setup_deferred_work(priv);
+ err = iwl_setup_deferred_work(priv);
+ if (err)
+ goto out_uninit_drv;
+
iwl_setup_rx_handlers(priv);
iwl_power_initialize(priv);
@@ -1503,11 +1509,14 @@ out_destroy_workqueue:
iwl_cancel_deferred_work(priv);
destroy_workqueue(priv->workqueue);
priv->workqueue = NULL;
+out_uninit_drv:
iwl_uninit_drv(priv);
out_free_eeprom_blob:
kfree(priv->eeprom_blob);
out_free_eeprom:
kfree(priv->nvm_data);
+out_leave_trans:
+ iwl_trans_op_mode_leave(priv->trans);
out_free_hw:
ieee80211_free_hw(priv->hw);
out:
@@ -1992,7 +2001,7 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode)
/* SKU Control */
iwl_trans_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP_DASH,
- CSR_HW_REV_STEP_DASH(priv->trans->hw_rev));
+ CSR_HW_REV_STEP_DASH(priv->trans->info.hw_rev));
/* write radio config values to register */
if (priv->nvm_data->radio_cfg_type <= EEPROM_RF_CONFIG_TYPE_MAX) {
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/power.c b/drivers/net/wireless/intel/iwlwifi/dvm/power.c
index 6d16a7105656..e7dbba7134f7 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/power.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/power.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
- * Copyright (C) 2019 Intel Corporation
+ * Copyright (C) 2019, 2025 Intel Corporation
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@@ -64,32 +64,32 @@ struct iwl_power_vec_entry {
/* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */
/* DTIM 0 - 2 */
static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
- {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 1, 2, 2, 0xFF)}, 0},
- {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
- {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0},
- {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF)}, 1},
- {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 2, 4, 6, 0xFF)}, 2}
+ {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 1, 2, 2, 0xFF), 0}, 0},
+ {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF), 0}, 0},
+ {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF), 0}, 0},
+ {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF), 0}, 1},
+ {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 2, 4, 6, 0xFF), 0}, 2}
};
/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */
/* DTIM 3 - 10 */
static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
- {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
- {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0},
- {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0},
- {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10)}, 1},
- {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 6, 10, 10)}, 2}
+ {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4), 0}, 0},
+ {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7), 0}, 0},
+ {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9), 0}, 0},
+ {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10), 0}, 1},
+ {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 6, 10, 10), 0}, 2}
};
/* for DTIM period > IWL_DTIM_RANGE_1_MAX */
/* DTIM 11 - */
static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
- {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
- {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
- {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
- {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
- {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
+ {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF), 0}, 0},
+ {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF), 0}, 0},
+ {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF), 0}, 0},
+ {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF), 0}, 0},
+ {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF), 0}, 0}
};
/* advance power management */
@@ -196,7 +196,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
else
cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
- if (priv->trans->trans_cfg->base_params->shadow_reg_enable)
+ if (priv->trans->mac_cfg->base->shadow_reg_enable)
cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
else
cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
@@ -368,7 +368,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
/* initialize to default */
void iwl_power_initialize(struct iwl_priv *priv)
{
- priv->power_data.bus_pm = priv->trans->pm_support;
+ priv->power_data.bus_pm = iwl_trans_is_pm_supported(priv->trans);
priv->power_data.debug_sleep_level_override = -1;
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/power.h b/drivers/net/wireless/intel/iwlwifi/dvm/power.h
index f38201ce1e99..1a688d942bca 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/power.h
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/power.h
@@ -23,6 +23,4 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
int iwl_power_update_mode(struct iwl_priv *priv, bool force);
void iwl_power_initialize(struct iwl_priv *priv);
-extern bool no_sleep_autoadjust;
-
#endif /* __iwl_power_setting_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c
index 8879e668ef0d..ed964103281e 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c
@@ -2899,7 +2899,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
/* Repeat initial/next rate.
* For legacy IWL_NUMBER_TRY == 1, this loop will not execute.
* For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */
- while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) {
+ while (repeat_rate > 0 && index < (LINK_QUAL_MAX_RETRY_NUM - 1)) {
if (is_legacy(tbl_type.lq_type)) {
if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
ant_toggle_cnt++;
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c
index 7f67e602940c..b34ee68f3dce 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c
@@ -3,7 +3,7 @@
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
- * Copyright(c) 2018, 2020-2021 Intel Corporation
+ * Copyright(c) 2018, 2020-2021, 2025 Intel Corporation
*
* Portions of this file are derived from the ipw3945 project, as well
* as portionhelp of the ieee80211 subsystem header files.
@@ -50,7 +50,7 @@ static void iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb)
* See iwlagn_mac_channel_switch.
*/
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
- struct iwl_rxon_cmd *rxon = (void *)&ctx->active;
+ struct iwl_rxon_cmd *rxon = (void *)(uintptr_t)&ctx->active;
if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
return;
@@ -429,7 +429,7 @@ static void iwlagn_rx_statistics(struct iwl_priv *priv,
* thermal update even if the uCode doesn't give
* us one */
mod_timer(&priv->statistics_periodic, jiffies +
- msecs_to_jiffies(reg_recalib_period * 1000));
+ secs_to_jiffies(reg_recalib_period));
if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
(pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
@@ -643,8 +643,8 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
fraglen = len - hdrlen;
if (fraglen) {
- int offset = (void *)hdr + hdrlen -
- rxb_addr(rxb) + rxb_offset(rxb);
+ int offset = (u8 *)hdr + hdrlen -
+ (u8 *)rxb_addr(rxb) + rxb_offset(rxb);
skb_add_rx_frag(skb, 0, rxb_steal_page(rxb), offset,
fraglen, rxb->truesize);
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c b/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c
index f80cce37e2c0..e08e44cae434 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/******************************************************************************
*
- * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2014, 2025 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
*****************************************************************************/
@@ -341,7 +341,7 @@ static int iwlagn_rxon_disconn(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
{
int ret;
- struct iwl_rxon_cmd *active = (void *)&ctx->active;
+ struct iwl_rxon_cmd *active = (void *)(uintptr_t)&ctx->active;
if (ctx->ctxid == IWL_RXON_CTX_BSS) {
ret = iwlagn_disable_bss(priv, ctx, &ctx->staging);
@@ -441,7 +441,7 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
{
int ret;
- struct iwl_rxon_cmd *active = (void *)&ctx->active;
+ struct iwl_rxon_cmd *active = (void *)(uintptr_t)&ctx->active;
/* RXON timing must be before associated RXON */
if (ctx->ctxid == IWL_RXON_CTX_BSS) {
@@ -1023,7 +1023,7 @@ static void iwl_calc_basic_rates(struct iwl_priv *priv,
int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{
/* cast away the const for active_rxon in this function */
- struct iwl_rxon_cmd *active = (void *)&ctx->active;
+ struct iwl_rxon_cmd *active = (void *)(uintptr_t)&ctx->active;
bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
int ret;
@@ -1149,7 +1149,7 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf,
}
}
-int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
+int iwlagn_mac_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_rxon_context *ctx;
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c
index 98f0949b3683..96831ce8da6f 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c
@@ -137,8 +137,8 @@ enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv)
*/
static void iwl_tt_check_exit_ct_kill(struct timer_list *t)
{
- struct iwl_priv *priv = from_timer(priv, t,
- thermal_throttle.ct_kill_exit_tm);
+ struct iwl_priv *priv = timer_container_of(priv, t,
+ thermal_throttle.ct_kill_exit_tm);
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
@@ -187,8 +187,8 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
static void iwl_tt_ready_for_ct_kill(struct timer_list *t)
{
- struct iwl_priv *priv = from_timer(priv, t,
- thermal_throttle.ct_kill_waiting_tm);
+ struct iwl_priv *priv = timer_container_of(priv, t,
+ thermal_throttle.ct_kill_waiting_tm);
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c
index 111ed1873006..a7806776a51e 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c
@@ -3,7 +3,7 @@
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright (C) 2019 Intel Corporation
- * Copyright (C) 2023 Intel Corporation
+ * Copyright (C) 2023, 2025 Intel Corporation
*****************************************************************************/
#include <linux/kernel.h>
@@ -232,6 +232,8 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
* that may be %NULL, for example during TX or key setup. In
* that case, we need to use the broadcast station, so this
* inline wraps that pattern.
+ *
+ * Return: station ID for mac80211 station (or broadcast if %NULL)
*/
static int iwl_sta_id_or_broadcast(struct iwl_rxon_context *context,
struct ieee80211_sta *sta)
@@ -463,7 +465,7 @@ static int iwlagn_alloc_agg_txq(struct iwl_priv *priv, int mq)
int q;
for (q = IWLAGN_FIRST_AMPDU_QUEUE;
- q < priv->trans->trans_cfg->base_params->num_of_queues; q++) {
+ q < priv->trans->mac_cfg->base->num_of_queues; q++) {
if (!test_and_set_bit(q, priv->agg_q_alloc)) {
priv->queue_to_mac80211[q] = mq;
return q;
@@ -1277,7 +1279,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
* (in Tx queue's circular buffer) of first TFD/frame in window */
u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
- if (scd_flow >= priv->trans->trans_cfg->base_params->num_of_queues) {
+ if (scd_flow >= priv->trans->mac_cfg->base->num_of_queues) {
IWL_ERR(priv,
"BUG_ON scd_flow is bigger than number of queues\n");
return;
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c b/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c
index bb13ca5d666c..ac90191a3973 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c
@@ -3,6 +3,7 @@
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
+ * Copyright (C) 2025 Intel Corporation
*****************************************************************************/
#include <linux/kernel.h>
@@ -222,7 +223,7 @@ static int iwl_alive_notify(struct iwl_priv *priv)
int ret;
int i;
- iwl_trans_fw_alive(priv->trans, 0);
+ iwl_trans_fw_alive(priv->trans);
if (priv->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN &&
priv->nvm_data->sku_cap_ipan_enable) {
@@ -293,15 +294,10 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
{
struct iwl_notification_wait alive_wait;
struct iwl_alive_data alive_data;
- const struct fw_img *fw;
int ret;
enum iwl_ucode_type old_type;
static const u16 alive_cmd[] = { REPLY_ALIVE };
- fw = iwl_get_ucode_image(priv->fw, ucode_type);
- if (WARN_ON(!fw))
- return -EINVAL;
-
old_type = priv->cur_ucode;
priv->cur_ucode = ucode_type;
priv->ucode_loaded = false;
@@ -310,7 +306,7 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
alive_cmd, ARRAY_SIZE(alive_cmd),
iwl_alive_fn, &alive_data);
- ret = iwl_trans_start_fw(priv->trans, fw, false);
+ ret = iwl_trans_start_fw(priv->trans, priv->fw, ucode_type, false);
if (ret) {
priv->cur_ucode = old_type;
iwl_remove_notification(&priv->notif_wait, &alive_wait);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
index efa7b673ebc7..52edc19d8cdd 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2019-2024 Intel Corporation
+ * Copyright (C) 2019-2025 Intel Corporation
*/
#include <linux/uuid.h>
#include "iwl-drv.h"
@@ -9,9 +9,9 @@
#include "acpi.h"
#include "fw/runtime.h"
-const guid_t iwl_guid = GUID_INIT(0xF21202BF, 0x8F78, 0x4DC6,
- 0xA5, 0xB3, 0x1F, 0x73,
- 0x8E, 0x28, 0x5A, 0xDE);
+static const guid_t iwl_guid = GUID_INIT(0xF21202BF, 0x8F78, 0x4DC6,
+ 0xA5, 0xB3, 0x1F, 0x73,
+ 0x8E, 0x28, 0x5A, 0xDE);
static const size_t acpi_dsm_size[DSM_FUNC_NUM_FUNCS] = {
[DSM_FUNC_QUERY] = sizeof(u32),
@@ -169,7 +169,7 @@ int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
BUILD_BUG_ON(ARRAY_SIZE(acpi_dsm_size) != DSM_FUNC_NUM_FUNCS);
- if (WARN_ON(func >= ARRAY_SIZE(acpi_dsm_size)))
+ if (WARN_ON(func >= ARRAY_SIZE(acpi_dsm_size) || !func))
return -EINVAL;
expected_size = acpi_dsm_size[func];
@@ -178,6 +178,29 @@ int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
if (expected_size != sizeof(u8) && expected_size != sizeof(u32))
return -EOPNOTSUPP;
+ if (!fwrt->acpi_dsm_funcs_valid) {
+ ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV,
+ DSM_FUNC_QUERY,
+ &iwl_guid, &tmp,
+ acpi_dsm_size[DSM_FUNC_QUERY]);
+ if (ret) {
+ /* always indicate BIT(0) to avoid re-reading */
+ fwrt->acpi_dsm_funcs_valid = BIT(0);
+ return ret;
+ }
+
+ IWL_DEBUG_RADIO(fwrt, "ACPI DSM validity bitmap 0x%x\n",
+ (u32)tmp);
+ /* always indicate BIT(0) to avoid re-reading */
+ fwrt->acpi_dsm_funcs_valid = tmp | BIT(0);
+ }
+
+ if (!(fwrt->acpi_dsm_funcs_valid & BIT(func))) {
+ IWL_DEBUG_RADIO(fwrt, "ACPI DSM %d not indicated as valid\n",
+ func);
+ return -ENODATA;
+ }
+
ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV, func,
&iwl_guid, &tmp, expected_size);
if (ret)
@@ -847,12 +870,12 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
if (IS_ERR(data))
return PTR_ERR(data);
- /* try to read ppag table rev 3, 2 or 1 (all have the same data size) */
+ /* try to read ppag table rev 1 to 4 (all have the same data size) */
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
ACPI_PPAG_WIFI_DATA_SIZE_V2, &tbl_rev);
if (!IS_ERR(wifi_pkg)) {
- if (tbl_rev >= 1 && tbl_rev <= 3) {
+ if (tbl_rev >= 1 && tbl_rev <= 4) {
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
IWL_DEBUG_RADIO(fwrt,
"Reading PPAG table (tbl_rev=%d)\n",
@@ -882,7 +905,7 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
goto out_free;
read_table:
- fwrt->ppag_ver = tbl_rev;
+ fwrt->ppag_bios_rev = tbl_rev;
flags = &wifi_pkg->package.elements[1];
if (flags->type != ACPI_TYPE_INTEGER) {
@@ -891,7 +914,7 @@ read_table:
}
fwrt->ppag_flags = iwl_bios_get_ppag_flags(flags->integer.value,
- fwrt->ppag_ver);
+ fwrt->ppag_bios_rev);
/*
* read, verify gain values and save them into the PPAG table.
@@ -912,6 +935,7 @@ read_table:
}
}
+ fwrt->ppag_bios_source = BIOS_SOURCE_ACPI;
ret = 0;
out_free:
@@ -919,40 +943,39 @@ out_free:
return ret;
}
-void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
- struct iwl_phy_specific_cfg *filters)
+int iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt)
{
+ struct iwl_phy_specific_cfg *filters = &fwrt->phy_filters;
struct iwl_phy_specific_cfg tmp = {};
- union acpi_object *wifi_pkg, *data;
+ union acpi_object *wifi_pkg, *data __free(kfree);
int tbl_rev, i;
data = iwl_acpi_get_object(fwrt->dev, ACPI_WPFC_METHOD);
if (IS_ERR(data))
- return;
+ return PTR_ERR(data);
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
ACPI_WPFC_WIFI_DATA_SIZE,
&tbl_rev);
if (IS_ERR(wifi_pkg))
- goto out_free;
+ return PTR_ERR(wifi_pkg);
if (tbl_rev != 0)
- goto out_free;
+ return -EINVAL;
BUILD_BUG_ON(ARRAY_SIZE(filters->filter_cfg_chains) !=
ACPI_WPFC_WIFI_DATA_SIZE - 1);
for (i = 0; i < ARRAY_SIZE(filters->filter_cfg_chains); i++) {
if (wifi_pkg->package.elements[i + 1].type != ACPI_TYPE_INTEGER)
- goto out_free;
+ return -EINVAL;
tmp.filter_cfg_chains[i] =
cpu_to_le32(wifi_pkg->package.elements[i + 1].integer.value);
}
IWL_DEBUG_RADIO(fwrt, "Loaded WPFC filter config from ACPI\n");
*filters = tmp;
-out_free:
- kfree(data);
+ return 0;
}
IWL_EXPORT_SYMBOL(iwl_acpi_get_phy_filters);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
index e50b93472dd2..06cece4ea6d9 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2023 Intel Corporation
+ * Copyright (C) 2018-2023, 2025 Intel Corporation
*/
#ifndef __iwl_fw_acpi__
#define __iwl_fw_acpi__
@@ -140,8 +140,6 @@ struct iwl_dsm_internal_product_reset_cmd {
struct iwl_fw_runtime;
-extern const guid_t iwl_guid;
-
union acpi_object *iwl_acpi_get_dsm_object(struct device *dev, int rev,
int func, union acpi_object *args,
const guid_t *guid);
@@ -153,6 +151,7 @@ union acpi_object *iwl_acpi_get_dsm_object(struct device *dev, int rev,
* @mcc: output buffer (3 bytes) that will get the MCC
*
* This function tries to read the current MCC from ACPI if available.
+ * Return: 0 on success, or a negative error code
*/
int iwl_acpi_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc);
@@ -180,8 +179,7 @@ int iwl_acpi_get_tas_table(struct iwl_fw_runtime *fwrt,
int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt);
-void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
- struct iwl_phy_specific_cfg *filters);
+int iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt);
void iwl_acpi_get_guid_lock_status(struct iwl_fw_runtime *fwrt);
@@ -244,8 +242,10 @@ static inline int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
return -ENOENT;
}
-/* macro since the second argument doesn't always exist */
-#define iwl_acpi_get_phy_filters(fwrt, filters) do { } while (0)
+static inline int iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt)
+{
+ return -ENOENT;
+}
static inline void iwl_acpi_get_guid_lock_status(struct iwl_fw_runtime *fwrt)
{
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h b/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h
index 42360a8f23aa..ea2ba4b4cb7b 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h
@@ -82,28 +82,13 @@ struct iwl_alive_ntf_v3 {
struct iwl_umac_alive umac_data;
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_3 */
-struct iwl_alive_ntf_v4 {
- __le16 status;
- __le16 flags;
- struct iwl_lmac_alive lmac_data[2];
- struct iwl_umac_alive umac_data;
-} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_4 */
-
-struct iwl_alive_ntf_v5 {
- __le16 status;
- __le16 flags;
- struct iwl_lmac_alive lmac_data[2];
- struct iwl_umac_alive umac_data;
- struct iwl_sku_id sku_id;
-} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_5 */
-
struct iwl_imr_alive_info {
__le64 base_addr;
__le32 size;
__le32 enabled;
} __packed; /* IMR_ALIVE_INFO_API_S_VER_1 */
-struct iwl_alive_ntf_v6 {
+struct iwl_alive_ntf_v7 {
__le16 status;
__le16 flags;
struct iwl_lmac_alive lmac_data[2];
@@ -112,6 +97,16 @@ struct iwl_alive_ntf_v6 {
struct iwl_imr_alive_info imr;
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_6 */
+struct iwl_alive_ntf {
+ __le16 status;
+ __le16 flags;
+ struct iwl_lmac_alive lmac_data[2];
+ struct iwl_umac_alive umac_data;
+ struct iwl_sku_id sku_id;
+ struct iwl_imr_alive_info imr;
+ __le64 platform_id;
+} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_8 */
+
/**
* enum iwl_extended_cfg_flags - commands driver may send before
* finishing init flow
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/cmdhdr.h b/drivers/net/wireless/intel/iwlwifi/fw/api/cmdhdr.h
index d130d4f85444..073f003bdc5d 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/cmdhdr.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/cmdhdr.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014 Intel Corporation
+ * Copyright (C) 2005-2014, 2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -98,7 +98,7 @@ struct iwl_cmd_header {
} __packed;
/**
- * struct iwl_cmd_header_wide
+ * struct iwl_cmd_header_wide - wide command header
*
* This header format appears in the beginning of each command sent from the
* driver, and each response/notification received from uCode.
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/coex.h b/drivers/net/wireless/intel/iwlwifi/fw/api/coex.h
index ddc84430d895..616f00a8b603 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/coex.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/coex.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2023-2024 Intel Corporation
+ * Copyright (C) 2023-2025 Intel Corporation
* Copyright (C) 2013-2014, 2018-2019 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2017 Intel Deutschland GmbH
@@ -52,7 +52,7 @@ struct iwl_bt_coex_cmd {
} __packed; /* BT_COEX_CMD_API_S_VER_6 */
/**
- * struct iwl_bt_coex_reduced_txp_update_cmd
+ * struct iwl_bt_coex_reduced_txp_update_cmd - reduced TX power command
* @reduced_txp: bit BT_REDUCED_TX_POWER_BIT to enable / disable, rest of the
* bits are the sta_id (value)
*/
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h
index d43adb6f9220..8d64a271bb94 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2022, 2024 Intel Corporation
+ * Copyright (C) 2018-2022, 2024-2025 Intel Corporation
*/
#ifndef __iwl_fw_api_commands_h__
#define __iwl_fw_api_commands_h__
@@ -60,7 +60,7 @@ enum iwl_legacy_cmds {
* @UCODE_ALIVE_NTFY:
* Alive data from the firmware, as described in
* &struct iwl_alive_ntf_v3 or &struct iwl_alive_ntf_v4 or
- * &struct iwl_alive_ntf_v5 or &struct iwl_alive_ntf_v6.
+ * &struct iwl_alive_ntf_v5 or &struct iwl_alive_ntf_v7.
*/
UCODE_ALIVE_NTFY = 0x1,
@@ -145,8 +145,8 @@ enum iwl_legacy_cmds {
REMOVE_STA = 0x19,
/**
- * @TX_CMD: uses &struct iwl_tx_cmd or &struct iwl_tx_cmd_gen2 or
- * &struct iwl_tx_cmd_gen3,
+ * @TX_CMD: uses &struct iwl_tx_cmd_v6 or &struct iwl_tx_cmd_v9 or
+ * &struct iwl_tx_cmd,
* response in &struct iwl_tx_resp or
* &struct iwl_tx_resp_v3
*/
@@ -573,9 +573,8 @@ enum iwl_legacy_cmds {
WOWLAN_KEK_KCK_MATERIAL = 0xe4,
/**
- * @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status_v6,
- * &struct iwl_wowlan_status_v7, &struct iwl_wowlan_status_v9 or
- * &struct iwl_wowlan_status_v12
+ * @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status_v6 or
+ * &struct iwl_wowlan_status_v7
*/
WOWLAN_GET_STATUSES = 0xe5,
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
index 9c271ea67155..d3bed0216df4 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -19,9 +19,11 @@ enum iwl_d0i3_flags {
/**
* enum iwl_d3_wakeup_flags - D3 manager wakeup flags
* @IWL_WAKEUP_D3_CONFIG_FW_ERROR: wake up on firmware sysassert
+ * @IWL_WAKEUP_D3_HOST_TIMER: wake up on host timer expiry
*/
enum iwl_d3_wakeup_flags {
- IWL_WAKEUP_D3_CONFIG_FW_ERROR = BIT(0),
+ IWL_WAKEUP_D3_CONFIG_FW_ERROR = BIT(0),
+ IWL_WAKEUP_D3_HOST_TIMER = BIT(1),
}; /* D3_MANAGER_WAKEUP_CONFIG_API_E_VER_3 */
/**
@@ -365,6 +367,7 @@ enum iwl_wowlan_flags {
ENABLE_NBNS_FILTERING = BIT(2),
ENABLE_DHCP_FILTERING = BIT(3),
ENABLE_STORE_BEACON = BIT(4),
+ HAS_BEACON_PROTECTION = BIT(5),
};
/**
@@ -454,11 +457,6 @@ struct iwl_wowlan_rsc_tsc_params_cmd_ver_2 {
union iwl_all_tsc_rsc all_tsc_rsc;
} __packed; /* ALL_TSC_RSC_API_S_VER_2 */
-struct iwl_wowlan_rsc_tsc_params_cmd_v4 {
- struct iwl_wowlan_rsc_tsc_params_cmd_ver_2 params;
- __le32 sta_id;
-} __packed; /* ALL_TSC_RSC_API_S_VER_4 */
-
struct iwl_wowlan_rsc_tsc_params_cmd {
__le64 ucast_rsc[IWL_MAX_TID_COUNT];
__le64 mcast_rsc[WOWLAN_GTK_KEYS_NUM][IWL_MAX_TID_COUNT];
@@ -634,10 +632,65 @@ struct iwl_wowlan_gtk_status_v3 {
struct iwl_wowlan_all_rsc_tsc_v5 sc;
} __packed; /* WOWLAN_GTK_MATERIAL_VER_3 */
+/**
+ * enum iwl_wowlan_key_status - Status of security keys in WoWLAN notifications
+ * @IWL_WOWLAN_NOTIF_NO_KEY: No key is present; this entry should be ignored.
+ * @IWL_WOWLAN_STATUS_OLD_KEY: old key exists; no rekey occurred, and only
+ * metadata is available.
+ * @IWL_WOWLAN_STATUS_NEW_KEY: A new key was created after a rekey; new key
+ * material is available.
+ */
+enum iwl_wowlan_key_status {
+ IWL_WOWLAN_NOTIF_NO_KEY = 0,
+ IWL_WOWLAN_STATUS_OLD_KEY = 1,
+ IWL_WOWLAN_STATUS_NEW_KEY = 2
+};
+
+/**
+ * struct iwl_wowlan_gtk_status - GTK status
+ * @key: GTK material
+ * @key_len: GTK length, if set to 0, the key is not available
+ * @key_flags: information about the key:
+ * bits[0:1]: key index assigned by the AP
+ * bits[2:6]: GTK index of the key in the internal DB
+ * bit[7]: Set iff this is the currently used GTK
+ * @key_status: key status, see &enum iwl_wowlan_key_status
+ * @reserved: padding
+ * @tkip_mic_key: TKIP RX MIC key
+ * @sc: RSC/TSC counters
+ */
+struct iwl_wowlan_gtk_status {
+ u8 key[WOWLAN_KEY_MAX_SIZE];
+ u8 key_len;
+ u8 key_flags;
+ u8 key_status;
+ u8 reserved;
+ u8 tkip_mic_key[IWL_MIC_KEY_SIZE];
+ struct iwl_wowlan_all_rsc_tsc_v5 sc;
+} __packed; /* WOWLAN_GTK_MATERIAL_VER_4 */
+
#define IWL_WOWLAN_GTK_IDX_MASK (BIT(0) | BIT(1))
#define IWL_WOWLAN_IGTK_BIGTK_IDX_MASK (BIT(0))
/**
+ * struct iwl_wowlan_igtk_status_v1 - IGTK status
+ * @key: IGTK material
+ * @ipn: the IGTK packet number (replay counter)
+ * @key_len: IGTK length, if set to 0, the key is not available
+ * @key_flags: information about the key:
+ * bits[0]: key index assigned by the AP (0: index 4, 1: index 5)
+ * (0: index 6, 1: index 7 with bigtk)
+ * bits[1:5]: IGTK index of the key in the internal DB
+ * bit[6]: Set iff this is the currently used IGTK
+ */
+struct iwl_wowlan_igtk_status_v1 {
+ u8 key[WOWLAN_KEY_MAX_SIZE];
+ u8 ipn[6];
+ u8 key_len;
+ u8 key_flags;
+} __packed; /* WOWLAN_IGTK_MATERIAL_VER_1 */
+
+/**
* struct iwl_wowlan_igtk_status - IGTK status
* @key: IGTK material
* @ipn: the IGTK packet number (replay counter)
@@ -647,13 +700,17 @@ struct iwl_wowlan_gtk_status_v3 {
* (0: index 6, 1: index 7 with bigtk)
* bits[1:5]: IGTK index of the key in the internal DB
* bit[6]: Set iff this is the currently used IGTK
+ * @key_status: key status, see &enum iwl_wowlan_key_status
+ * @reserved: padding
*/
struct iwl_wowlan_igtk_status {
u8 key[WOWLAN_KEY_MAX_SIZE];
u8 ipn[6];
u8 key_len;
u8 key_flags;
-} __packed; /* WOWLAN_IGTK_MATERIAL_VER_1 */
+ u8 key_status;
+ u8 reserved[3];
+} __packed; /* WOWLAN_IGTK_MATERIAL_VER_2 */
/**
* struct iwl_wowlan_status_v6 - WoWLAN status
@@ -703,7 +760,7 @@ struct iwl_wowlan_status_v6 {
*/
struct iwl_wowlan_status_v7 {
struct iwl_wowlan_gtk_status_v2 gtk[WOWLAN_GTK_KEYS_NUM];
- struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
+ struct iwl_wowlan_igtk_status_v1 igtk[WOWLAN_IGTK_KEYS_NUM];
__le64 replay_ctr;
__le16 pattern_number;
__le16 non_qos_seq_ctr;
@@ -718,82 +775,6 @@ struct iwl_wowlan_status_v7 {
} __packed; /* WOWLAN_STATUSES_API_S_VER_7 */
/**
- * struct iwl_wowlan_status_v9 - WoWLAN status (versions 9 and 10)
- * @gtk: GTK data
- * @igtk: IGTK data
- * @replay_ctr: GTK rekey replay counter
- * @pattern_number: number of the matched pattern
- * @non_qos_seq_ctr: non-QoS sequence counter to use next.
- * Reserved if the struct has version >= 10.
- * @qos_seq_ctr: QoS sequence counters to use next
- * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
- * @num_of_gtk_rekeys: number of GTK rekeys
- * @transmitted_ndps: number of transmitted neighbor discovery packets
- * @received_beacons: number of received beacons
- * @wake_packet_length: wakeup packet length
- * @wake_packet_bufsize: wakeup packet buffer size
- * @tid_tear_down: bit mask of tids whose BA sessions were closed
- * in suspend state
- * @reserved: unused
- * @wake_packet: wakeup packet
- */
-struct iwl_wowlan_status_v9 {
- struct iwl_wowlan_gtk_status_v2 gtk[WOWLAN_GTK_KEYS_NUM];
- struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
- __le64 replay_ctr;
- __le16 pattern_number;
- __le16 non_qos_seq_ctr;
- __le16 qos_seq_ctr[8];
- __le32 wakeup_reasons;
- __le32 num_of_gtk_rekeys;
- __le32 transmitted_ndps;
- __le32 received_beacons;
- __le32 wake_packet_length;
- __le32 wake_packet_bufsize;
- u8 tid_tear_down;
- u8 reserved[3];
- u8 wake_packet[]; /* can be truncated from _length to _bufsize */
-} __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_9 */
-
-/**
- * struct iwl_wowlan_status_v12 - WoWLAN status
- * @gtk: GTK data
- * @igtk: IGTK data
- * @replay_ctr: GTK rekey replay counter
- * @pattern_number: number of the matched pattern
- * @non_qos_seq_ctr: non-QoS sequence counter to use next.
- * Reserved if the struct has version >= 10.
- * @qos_seq_ctr: QoS sequence counters to use next
- * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
- * @num_of_gtk_rekeys: number of GTK rekeys
- * @transmitted_ndps: number of transmitted neighbor discovery packets
- * @received_beacons: number of received beacons
- * @wake_packet_length: wakeup packet length
- * @wake_packet_bufsize: wakeup packet buffer size
- * @tid_tear_down: bit mask of tids whose BA sessions were closed
- * in suspend state
- * @reserved: unused
- * @wake_packet: wakeup packet
- */
-struct iwl_wowlan_status_v12 {
- struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
- struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
- __le64 replay_ctr;
- __le16 pattern_number;
- __le16 non_qos_seq_ctr;
- __le16 qos_seq_ctr[8];
- __le32 wakeup_reasons;
- __le32 num_of_gtk_rekeys;
- __le32 transmitted_ndps;
- __le32 received_beacons;
- __le32 wake_packet_length;
- __le32 wake_packet_bufsize;
- u8 tid_tear_down;
- u8 reserved[3];
- u8 wake_packet[]; /* can be truncated from _length to _bufsize */
-} __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_12 */
-
-/**
* struct iwl_wowlan_info_notif_v1 - WoWLAN information notification
* @gtk: GTK data
* @igtk: IGTK data
@@ -814,7 +795,7 @@ struct iwl_wowlan_status_v12 {
*/
struct iwl_wowlan_info_notif_v1 {
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
- struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
+ struct iwl_wowlan_igtk_status_v1 igtk[WOWLAN_IGTK_KEYS_NUM];
__le64 replay_ctr;
__le16 pattern_number;
__le16 reserved1;
@@ -830,39 +811,6 @@ struct iwl_wowlan_info_notif_v1 {
u8 reserved2[2];
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_1 */
-/**
- * struct iwl_wowlan_info_notif_v2 - WoWLAN information notification
- * @gtk: GTK data
- * @igtk: IGTK data
- * @replay_ctr: GTK rekey replay counter
- * @pattern_number: number of the matched patterns
- * @reserved1: reserved
- * @qos_seq_ctr: QoS sequence counters to use next
- * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
- * @num_of_gtk_rekeys: number of GTK rekeys
- * @transmitted_ndps: number of transmitted neighbor discovery packets
- * @received_beacons: number of received beacons
- * @tid_tear_down: bit mask of tids whose BA sessions were closed
- * in suspend state
- * @station_id: station id
- * @reserved2: reserved
- */
-struct iwl_wowlan_info_notif_v2 {
- struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
- struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
- __le64 replay_ctr;
- __le16 pattern_number;
- __le16 reserved1;
- __le16 qos_seq_ctr[8];
- __le32 wakeup_reasons;
- __le32 num_of_gtk_rekeys;
- __le32 transmitted_ndps;
- __le32 received_beacons;
- u8 tid_tear_down;
- u8 station_id;
- u8 reserved2[2];
-} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_2 */
-
/* MAX MLO keys of non-active links that can arrive in the notification */
#define WOWLAN_MAX_MLO_KEYS 18
@@ -910,7 +858,7 @@ struct iwl_wowlan_mlo_gtk {
} __packed; /* WOWLAN_MLO_GTK_KEY_API_S_VER_1 */
/**
- * struct iwl_wowlan_info_notif_v4 - WoWLAN information notification
+ * struct iwl_wowlan_info_notif_v3 - WoWLAN information notification
* @gtk: GTK data
* @igtk: IGTK data
* @bigtk: BIGTK data
@@ -925,15 +873,12 @@ struct iwl_wowlan_mlo_gtk {
* @tid_tear_down: bit mask of tids whose BA sessions were closed
* in suspend state
* @station_id: station id
- * @num_mlo_link_keys: number of &struct iwl_wowlan_mlo_gtk structs
- * following this notif, or reserved in version < 4
* @reserved2: reserved
- * @mlo_gtks: array of GTKs of size num_mlo_link_keys for version >= 4
*/
-struct iwl_wowlan_info_notif_v4 {
+struct iwl_wowlan_info_notif_v3 {
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
- struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
- struct iwl_wowlan_igtk_status bigtk[WOWLAN_BIGTK_KEYS_NUM];
+ struct iwl_wowlan_igtk_status_v1 igtk[WOWLAN_IGTK_KEYS_NUM];
+ struct iwl_wowlan_igtk_status_v1 bigtk[WOWLAN_BIGTK_KEYS_NUM];
__le64 replay_ctr;
__le16 pattern_number;
__le16 reserved1;
@@ -944,10 +889,47 @@ struct iwl_wowlan_info_notif_v4 {
__le32 received_beacons;
u8 tid_tear_down;
u8 station_id;
+ u8 reserved2[2];
+} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_3 */
+
+/**
+ * struct iwl_wowlan_info_notif_v5 - WoWLAN information notification
+ * @gtk: GTK data
+ * @igtk: IGTK data
+ * @bigtk: BIGTK data
+ * @replay_ctr: GTK rekey replay counter
+ * @pattern_number: number of the matched patterns
+ * @qos_seq_ctr: QoS sequence counters to use next
+ * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
+ * @num_of_gtk_rekeys: number of GTK rekeys
+ * @transmitted_ndps: number of transmitted neighbor discovery packets
+ * @received_beacons: number of received beacons
+ * @tid_tear_down: bit mask of tids whose BA sessions were closed
+ * in suspend state
+ * @station_id: station id
+ * @num_mlo_link_keys: number of &struct iwl_wowlan_mlo_gtk structs
+ * following this notif
+ * @tid_offloaded_tx: tid used by the firmware to transmit data packets
+ * while in wowlan
+ * @mlo_gtks: array of GTKs of size num_mlo_link_keys
+ */
+struct iwl_wowlan_info_notif_v5 {
+ struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
+ struct iwl_wowlan_igtk_status_v1 igtk[WOWLAN_IGTK_KEYS_NUM];
+ struct iwl_wowlan_igtk_status_v1 bigtk[WOWLAN_BIGTK_KEYS_NUM];
+ __le64 replay_ctr;
+ __le16 pattern_number;
+ __le16 qos_seq_ctr;
+ __le32 wakeup_reasons;
+ __le32 num_of_gtk_rekeys;
+ __le32 transmitted_ndps;
+ __le32 received_beacons;
+ u8 tid_tear_down;
+ u8 station_id;
u8 num_mlo_link_keys;
- u8 reserved2;
+ u8 tid_offloaded_tx;
struct iwl_wowlan_mlo_gtk mlo_gtks[];
-} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_3, _VER_4 */
+} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_5 */
/**
* struct iwl_wowlan_info_notif - WoWLAN information notification
@@ -971,7 +953,7 @@ struct iwl_wowlan_info_notif_v4 {
* @mlo_gtks: array of GTKs of size num_mlo_link_keys
*/
struct iwl_wowlan_info_notif {
- struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
+ struct iwl_wowlan_gtk_status gtk[WOWLAN_GTK_KEYS_NUM];
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
struct iwl_wowlan_igtk_status bigtk[WOWLAN_BIGTK_KEYS_NUM];
__le64 replay_ctr;
@@ -986,7 +968,7 @@ struct iwl_wowlan_info_notif {
u8 num_mlo_link_keys;
u8 tid_offloaded_tx;
struct iwl_wowlan_mlo_gtk mlo_gtks[];
-} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_5 */
+} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_6 */
/**
* struct iwl_wowlan_wake_pkt_notif - WoWLAN wake packet notification
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
index c139b965980d..6a6e11a57dbf 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
@@ -91,14 +91,8 @@ enum iwl_data_path_subcmd_ids {
SEC_KEY_CMD = 0x18,
/**
- * @OMI_SEND_STATUS_NOTIF: notification after OMI was sent
- * uses &struct iwl_omi_send_status_notif
- */
- OMI_SEND_STATUS_NOTIF = 0xF2,
-
- /**
* @ESR_MODE_NOTIF: notification to recommend/force a wanted esr mode,
- * uses &struct iwl_esr_mode_notif
+ * uses &struct iwl_esr_mode_notif or &struct iwl_esr_mode_notif_v1
*/
ESR_MODE_NOTIF = 0xF3,
@@ -125,6 +119,16 @@ enum iwl_data_path_subcmd_ids {
TLC_MNG_UPDATE_NOTIF = 0xF7,
/**
+ * @BEACON_FILTER_IN_NOTIF: &struct iwl_beacon_filter_notif
+ */
+ BEACON_FILTER_IN_NOTIF = 0xF8,
+
+ /**
+ * @PHY_AIR_SNIFFER_NOTIF: &struct iwl_rx_phy_air_sniffer_ntfy
+ */
+ PHY_AIR_SNIFFER_NOTIF = 0xF9,
+
+ /**
* @STA_PM_NOTIF: &struct iwl_mvm_pm_state_notification
*/
STA_PM_NOTIF = 0xFD,
@@ -694,13 +698,4 @@ struct iwl_sec_key_cmd {
} __packed u; /* SEC_KEY_OPERATION_API_U_VER_1 */
} __packed; /* SEC_KEY_CMD_API_S_VER_1 */
-/**
- * struct iwl_omi_send_status_notif - OMI status notification
- * @success: indicates that the OMI was sent successfully
- * (currently always set)
- */
-struct iwl_omi_send_status_notif {
- __le32 success;
-} __packed; /* OMI_SEND_STATUS_NTFY_API_S_VER_1 */
-
#endif /* __iwl_fw_api_datapath_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
index 4fab6c66994e..b62f0687327a 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
@@ -16,7 +16,7 @@
#define IWL_FW_INI_PRESET_DISABLE 0xff
/**
- * struct iwl_fw_ini_hcmd
+ * struct iwl_fw_ini_hcmd - debug configuration host command
*
* @id: the debug configuration command type for instance: 0xf6 / 0xf5 / DHC
* @group: the desired cmd group
@@ -199,7 +199,7 @@ struct iwl_fw_ini_region_tlv {
} __packed; /* FW_TLV_DEBUG_REGION_API_S_VER_1 */
/**
- * struct iwl_fw_ini_debug_info_tlv
+ * struct iwl_fw_ini_debug_info_tlv - debug info TLV
*
* debug configuration name for a specific image
*
@@ -311,7 +311,7 @@ struct iwl_fw_ini_conf_set_tlv {
} __packed; /* FW_TLV_DEBUG_CONFIG_SET_API_S_VER_1 */
/**
- * enum iwl_fw_ini_config_set_type
+ * enum iwl_fw_ini_config_set_type - configuration set type
*
* @IWL_FW_INI_CONFIG_SET_TYPE_INVALID: invalid config set
* @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_MAC: for PERIPHERY MAC configuration
@@ -337,7 +337,7 @@ enum iwl_fw_ini_config_set_type {
} __packed;
/**
- * enum iwl_fw_ini_allocation_id
+ * enum iwl_fw_ini_allocation_id - allocation ID
*
* @IWL_FW_INI_ALLOCATION_INVALID: invalid
* @IWL_FW_INI_ALLOCATION_ID_DBGC1: allocation meant for DBGC1 configuration
@@ -356,7 +356,7 @@ enum iwl_fw_ini_allocation_id {
}; /* FW_DEBUG_TLV_ALLOCATION_ID_E_VER_1 */
/**
- * enum iwl_fw_ini_buffer_location
+ * enum iwl_fw_ini_buffer_location - buffer location
*
* @IWL_FW_INI_LOCATION_INVALID: invalid
* @IWL_FW_INI_LOCATION_SRAM_PATH: SRAM location
@@ -373,7 +373,7 @@ enum iwl_fw_ini_buffer_location {
}; /* FW_DEBUG_TLV_BUFFER_LOCATION_E_VER_1 */
/**
- * enum iwl_fw_ini_region_type
+ * enum iwl_fw_ini_region_type - region type
*
* @IWL_FW_INI_REGION_INVALID: invalid
* @IWL_FW_INI_REGION_TLV: uCode and debug TLVs
@@ -437,7 +437,7 @@ enum iwl_fw_ini_region_device_memory_subtype {
}; /* FW_TLV_DEBUG_REGION_DEVICE_MEMORY_SUBTYPE_API_E */
/**
- * enum iwl_fw_ini_time_point
+ * enum iwl_fw_ini_time_point - time point type
*
* Hard coded time points in which the driver can send hcmd or perform dump
* collection
@@ -527,8 +527,8 @@ enum iwl_fw_ini_time_point {
* @IWL_FW_INI_APPLY_POLICY_OVERRIDE_DATA: override trigger data.
* Append otherwise
* @IWL_FW_INI_APPLY_POLICY_DUMP_COMPLETE_CMD: send cmd once dump collected
- * @IWL_FW_INI_APPLY_POLICY_RESET_HANDSHAKE: perform reset handshake and
- * split dump to before/after with region marking
+ * @IWL_FW_INI_APPLY_POLICY_SPLIT_DUMP_RESET: split this dump into regions
+ * before and after the reset handshake
*/
enum iwl_fw_ini_trigger_apply_policy {
IWL_FW_INI_APPLY_POLICY_MATCH_TIME_POINT = BIT(0),
@@ -537,7 +537,7 @@ enum iwl_fw_ini_trigger_apply_policy {
IWL_FW_INI_APPLY_POLICY_OVERRIDE_CFG = BIT(9),
IWL_FW_INI_APPLY_POLICY_OVERRIDE_DATA = BIT(10),
IWL_FW_INI_APPLY_POLICY_DUMP_COMPLETE_CMD = BIT(16),
- IWL_FW_INI_APPLY_POLICY_RESET_HANDSHAKE = BIT(17),
+ IWL_FW_INI_APPLY_POLICY_SPLIT_DUMP_RESET = BIT(17),
};
/**
@@ -560,7 +560,7 @@ enum iwl_fw_ini_trigger_reset_fw_policy {
* @IWL_FW_INI_DEBUG_DUMP_POLICY_MAX_LIMIT_600KB: mini dump only 600KB region dump
* @IWL_FW_IWL_DEBUG_DUMP_POLICY_MAX_LIMIT_5MB: mini dump 5MB size dump
* @IWL_FW_IWL_DEBUG_DUMP_POLICY_BEFORE_RESET: dump this region before reset
- * handshake (if requested by %IWL_FW_INI_APPLY_POLICY_RESET_HANDSHAKE)
+ * handshake (if requested by %IWL_FW_INI_APPLY_POLICY_SPLIT_DUMP_RESET)
*/
enum iwl_fw_ini_dump_policy {
IWL_FW_INI_DEBUG_DUMP_POLICY_NO_LIMIT = BIT(0),
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h
index 0cf1e5124fba..61a850de26fc 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h
@@ -421,7 +421,7 @@ struct iwl_dbgc1_info {
} __packed; /* INIT_DRAM_FRAGS_ALLOCATIONS_S_VER_1 */
/**
- * struct iwl_dbg_host_event_cfg_cmd
+ * struct iwl_dbg_host_event_cfg_cmd - host event config command
* @enabled_severities: enabled severities
*/
struct iwl_dbg_host_event_cfg_cmd {
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
index e1952fc6d149..2ee3a48aa5df 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
@@ -6,6 +6,11 @@
*/
#ifndef __iwl_fw_api_location_h__
#define __iwl_fw_api_location_h__
+#include <linux/ieee80211.h>
+#include <linux/if_ether.h>
+#include <linux/types.h>
+#include <linux/bits.h>
+#include "rs.h"
/**
* enum iwl_location_subcmd_ids - location group command IDs
@@ -1087,7 +1092,7 @@ struct iwl_tof_range_req_ap_entry {
} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_9 */
/**
- * enum iwl_tof_response_mode
+ * enum iwl_tof_response_mode - TOF response mode
* @IWL_MVM_TOF_RESPONSE_ASAP: report each AP measurement separately as soon as
* possible (not supported for this release)
* @IWL_MVM_TOF_RESPONSE_TIMEOUT: report all AP measurements as a batch upon
@@ -1103,7 +1108,7 @@ enum iwl_tof_response_mode {
};
/**
- * enum iwl_tof_initiator_flags
+ * enum iwl_tof_initiator_flags - TOF initiator flags
*
* @IWL_TOF_INITIATOR_FLAGS_FAST_ALGO_DISABLED: disable fast algo, meaning run
* the algo on ant A+B, instead of only one of them.
@@ -1404,7 +1409,7 @@ enum iwl_tof_range_request_status {
};
/**
- * enum iwl_tof_entry_status
+ * enum iwl_tof_entry_status - TOF entry status
*
* @IWL_TOF_ENTRY_SUCCESS: successful measurement.
* @IWL_TOF_ENTRY_GENERAL_FAILURE: General failure.
@@ -1609,7 +1614,7 @@ struct iwl_tof_range_rsp_ap_entry_ntfy_v5 {
} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_5 */
/**
- * struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response)
+ * struct iwl_tof_range_rsp_ap_entry_ntfy_v7 - AP parameters (response)
* @bssid: BSSID of the AP
* @measure_status: current APs measurement status, one of
* &enum iwl_tof_entry_status.
@@ -1645,7 +1650,7 @@ struct iwl_tof_range_rsp_ap_entry_ntfy_v5 {
* @tx_pn: the last PN used for this responder Tx in case PMF is configured in
* LE byte order.
*/
-struct iwl_tof_range_rsp_ap_entry_ntfy {
+struct iwl_tof_range_rsp_ap_entry_ntfy_v7 {
u8 bssid[ETH_ALEN];
u8 measure_status;
u8 measure_bw;
@@ -1672,6 +1677,65 @@ struct iwl_tof_range_rsp_ap_entry_ntfy {
} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_6,
LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_7 */
+/**
+ * struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response)
+ * @bssid: BSSID of the AP
+ * @measure_status: current APs measurement status, one of
+ * &enum iwl_tof_entry_status.
+ * @measure_bw: Current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz
+ * @rtt: The Round Trip Time that took for the last measurement for
+ * current AP [pSec]
+ * @rtt_variance: The Variance of the RTT values measured for current AP
+ * @rtt_spread: The Difference between the maximum and the minimum RTT
+ * values measured for current AP in the current session [pSec]
+ * @rssi: RSSI as uploaded in the Channel Estimation notification
+ * @rssi_spread: The Difference between the maximum and the minimum RSSI values
+ * measured for current AP in the current session
+ * @last_burst: 1 if no more FTM sessions are scheduled for this responder
+ * @refusal_period: refusal period in case of
+ * @IWL_TOF_ENTRY_RESPONDER_CANNOT_COLABORATE [sec]
+ * @timestamp: The GP2 Clock [usec] where Channel Estimation notification was
+ * uploaded by the LMAC
+ * @start_tsf: measurement start time in TSF of the mac specified in the range
+ * request
+ * @reserved1: reserved, for backwards compatibility
+ * @t2t3_initiator: as calculated from the algo in the initiator
+ * @t1t4_responder: as calculated from the algo in the responder
+ * @common_calib: Calib val that was used in for this AP measurement
+ * @specific_calib: val that was used in for this AP measurement
+ * @papd_calib_output: The result of the tof papd calibration that was injected
+ * into the algorithm.
+ * @rttConfidence: a value between 0 - 31 that represents the rtt accuracy.
+ * @reserved: for alignment
+ * @rx_pn: the last PN used for this responder Rx in case PMF is configured in
+ * LE byte order.
+ * @tx_pn: the last PN used for this responder Tx in case PMF is configured in
+ * LE byte order.
+ */
+struct iwl_tof_range_rsp_ap_entry_ntfy {
+ u8 bssid[ETH_ALEN];
+ u8 measure_status;
+ u8 measure_bw;
+ __le32 rtt;
+ __le32 rtt_variance;
+ __le32 rtt_spread;
+ s8 rssi;
+ u8 rssi_spread;
+ u8 last_burst;
+ u8 refusal_period;
+ __le32 timestamp;
+ __le32 start_tsf;
+ __le32 reserved1[2];
+ __le32 t2t3_initiator;
+ __le32 t1t4_responder;
+ __le16 common_calib;
+ __le16 specific_calib;
+ __le32 papd_calib_output;
+ u8 rttConfidence;
+ u8 reserved[3];
+ u8 rx_pn[IEEE80211_CCMP_PN_LEN];
+ u8 tx_pn[IEEE80211_CCMP_PN_LEN];
+} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_8 */
/**
* enum iwl_tof_response_status - tof response status
@@ -1739,6 +1803,24 @@ struct iwl_tof_range_rsp_ntfy_v7 {
} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_7 */
/**
+ * struct iwl_tof_range_rsp_ntfy_v9 - ranging response notification
+ * @request_id: A Token ID of the corresponding Range request
+ * @num_of_aps: Number of APs results
+ * @last_report: 1 if no more FTM sessions are scheduled, 0 otherwise.
+ * @reserved: reserved
+ * @ap: per-AP data
+ */
+struct iwl_tof_range_rsp_ntfy_v9 {
+ u8 request_id;
+ u8 num_of_aps;
+ u8 last_report;
+ u8 reserved;
+ struct iwl_tof_range_rsp_ap_entry_ntfy_v7 ap[IWL_TOF_MAX_APS];
+} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_8,
+ * LOCATION_RANGE_RSP_NTFY_API_S_VER_9
+ */
+
+/**
* struct iwl_tof_range_rsp_ntfy - ranging response notification
* @request_id: A Token ID of the corresponding Range request
* @num_of_aps: Number of APs results
@@ -1752,8 +1834,7 @@ struct iwl_tof_range_rsp_ntfy {
u8 last_report;
u8 reserved;
struct iwl_tof_range_rsp_ap_entry_ntfy ap[IWL_TOF_MAX_APS];
-} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_8,
- LOCATION_RANGE_RSP_NTFY_API_S_VER_9 */
+} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_10 */
#define IWL_MVM_TOF_MCSI_BUF_SIZE (245)
/**
@@ -1775,7 +1856,7 @@ struct iwl_tof_mcsi_notif {
} __packed;
/**
- * struct iwl_tof_range_abort_cmd
+ * struct iwl_tof_range_abort_cmd - TOF range abort command
* @request_id: corresponds to a range request
* @reserved: reserved
*/
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
index b511e3aa6bb2..f76cea6e9ec8 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
@@ -311,8 +311,41 @@ enum iwl_mac_config_filter_flags {
}; /* MAC_FILTER_FLAGS_MASK_E_VER_1 */
/**
+ * struct iwl_mac_wifi_gen_support_v2 - parameters of iwl_mac_config_cmd
+ * with support up to eht as in version 2 of the command
+ *
+ * @he_support: does this MAC support HE
+ * @he_ap_support: HE AP enabled, "pseudo HE", no trigger frame handling
+ * @eht_support: does this MAC support EHT. Requires he_support
+ */
+struct iwl_mac_wifi_gen_support_v2 {
+ __le16 he_support;
+ __le16 he_ap_support;
+ __le32 eht_support;
+} __packed;
+
+/**
+ * struct iwl_mac_wifi_gen_support - parameters of iwl_mac_config_cmd
+ * with support up to uhr as in version 3 of the command
+ * ( MAC_CONTEXT_CONFIG_CMD = 0x8 )
+ *
+ * @he_support: does this MAC support HE
+ * @he_ap_support: HE AP enabled, "pseudo HE", no trigger frame handling
+ * @eht_support: does this MAC support EHT. Requires he_support
+ * @uhr_support: does this MAC support UHR. Requires eht_support
+ * @reserved: reserved for alignment and to match version 2's size
+ */
+struct iwl_mac_wifi_gen_support {
+ u8 he_support;
+ u8 he_ap_support;
+ u8 eht_support;
+ u8 uhr_support;
+ __le32 reserved;
+} __packed;
+
+/**
* struct iwl_mac_config_cmd - command structure to configure MAC contexts in
- * MLD API
+ * MLD API for versions 2 and 3
* ( MAC_CONTEXT_CONFIG_CMD = 0x8 )
*
* @id_and_color: ID and color of the MAC
@@ -321,9 +354,8 @@ enum iwl_mac_config_filter_flags {
* @local_mld_addr: mld address
* @reserved_for_local_mld_addr: reserved
* @filter_flags: combination of &enum iwl_mac_config_filter_flags
- * @he_support: does this MAC support HE
- * @he_ap_support: HE AP enabled, "pseudo HE", no trigger frame handling
- * @eht_support: does this MAC support EHT. Requires he_support
+ * @wifi_gen_v2: he/eht parameters as in cmd version 2
+ * @wifi_gen: he/eht/uhr parameters as in cmd version 3
* @nic_not_ack_enabled: mark that the NIC doesn't support receiving
* ACK-enabled AGG, (i.e. both BACK and non-BACK frames in single AGG).
* If the NIC is not ACK_ENABLED it may use the EOF-bit in first non-0
@@ -332,7 +364,6 @@ enum iwl_mac_config_filter_flags {
* @p2p_dev: mac data for p2p device
*/
struct iwl_mac_config_cmd {
- /* COMMON_INDEX_HDR_API_S_VER_1 */
__le32 id_and_color;
__le32 action;
/* MAC_CONTEXT_TYPE_API_E */
@@ -340,16 +371,17 @@ struct iwl_mac_config_cmd {
u8 local_mld_addr[6];
__le16 reserved_for_local_mld_addr;
__le32 filter_flags;
- __le16 he_support;
- __le16 he_ap_support;
- __le32 eht_support;
+ union {
+ struct iwl_mac_wifi_gen_support_v2 wifi_gen_v2;
+ struct iwl_mac_wifi_gen_support wifi_gen;
+ };
__le32 nic_not_ack_enabled;
/* MAC_CONTEXT_CONFIG_SPECIFIC_DATA_API_U_VER_2 */
union {
struct iwl_mac_client_data client;
struct iwl_mac_p2p_dev_data p2p_dev;
};
-} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_2 */
+} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_2_VER_3 */
/**
* enum iwl_link_ctx_modify_flags - indicate to the fw what fields are being
@@ -388,6 +420,8 @@ struct iwl_mac_config_cmd {
* eht_support set to true. No longer used since _VER_3 of this command.
* @LINK_CONTEXT_MODIFY_BANDWIDTH: Covers iwl_link_ctx_cfg_cmd::modify_bandwidth.
* Request RX OMI to the AP to modify bandwidth of this link.
+ * @LINK_CONTEXT_MODIFY_UHR_PARAMS: covers iwl_link_ctx_cfg_cmd::npca_params and
+ * iwl_link_ctx_cfg_cmd::prio_edca_params. Since _VER_7.
* @LINK_CONTEXT_MODIFY_ALL: set all above flags
*/
enum iwl_link_ctx_modify_flags {
@@ -400,6 +434,7 @@ enum iwl_link_ctx_modify_flags {
LINK_CONTEXT_MODIFY_BSS_COLOR_DISABLE = BIT(6),
LINK_CONTEXT_MODIFY_EHT_PARAMS = BIT(7),
LINK_CONTEXT_MODIFY_BANDWIDTH = BIT(8),
+ LINK_CONTEXT_MODIFY_UHR_PARAMS = BIT(9),
LINK_CONTEXT_MODIFY_ALL = 0xff,
}; /* LINK_CONTEXT_MODIFY_MASK_E_VER_1 */
@@ -457,6 +492,24 @@ enum iwl_link_modify_bandwidth {
};
/**
+ * struct iwl_npca_params - NPCA parameters (non-primary channel access)
+ *
+ * @switch_delay: after switch, delay TX according to destination AP
+ * @switch_back_delay: switch back to control channel before OBSS frame end
+ * @min_dur_threshold: minimum PPDU time to switch to the non-primary
+ * NPCA channel
+ * @flags: NPCA flags - bit 0: puncturing allowed, bit 1: new TX allowed
+ * @reserved: reserved for alignment purposes
+ */
+struct iwl_npca_params {
+ u8 switch_delay;
+ u8 switch_back_delay;
+ __le16 min_dur_threshold;
+ __le16 flags;
+ __le16 reserved;
+} __packed; /* NPCA_PARAM_API_S_VER_1 */
+
+/**
* struct iwl_link_config_cmd - command structure to configure the LINK context
* in MLD API
* ( LINK_CONFIG_CMD =0x9 )
@@ -513,6 +566,8 @@ enum iwl_link_modify_bandwidth {
* IEEE802.11REVme-D5.0
* @ibss_bssid_addr: bssid for ibss
* @reserved_for_ibss_bssid_addr: reserved
+ * @npca_params: NPCA parameters
+ * @prio_edca_params: priority EDCA parameters for enhanced QoS
* @reserved3: reserved for future use
*/
struct iwl_link_config_cmd {
@@ -560,8 +615,10 @@ struct iwl_link_config_cmd {
u8 ul_mu_data_disable;
u8 ibss_bssid_addr[6];
__le16 reserved_for_ibss_bssid_addr;
- __le32 reserved3[8];
-} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1, _VER_2, _VER_3, _VER_4, _VER_5, _VER_6 */
+ struct iwl_npca_params npca_params; /* since _VER_7 */
+ struct iwl_ac_qos prio_edca_params; /* since _VER_7 */
+ __le32 reserved3[4];
+} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1, _VER_2, _VER_3, _VER_4, _VER_5, _VER_6, _VER_7 */
/* Currently FW supports link ids in the range 0-3 and can have
* at most two active links for each vif.
@@ -589,6 +646,62 @@ enum iwl_fw_sta_type {
}; /* STATION_TYPE_E_VER_1 */
/**
+ * struct iwl_sta_cfg_cmd_v1 - cmd structure to add a peer sta to the uCode's
+ * station table
+ * ( STA_CONFIG_CMD = 0xA )
+ *
+ * @sta_id: index of station in uCode's station table
+ * @link_id: the id of the link that is used to communicate with this sta
+ * @peer_mld_address: the peers mld address
+ * @reserved_for_peer_mld_address: reserved
+ * @peer_link_address: the address of the link that is used to communicate
+ * with this sta
+ * @reserved_for_peer_link_address: reserved
+ * @station_type: type of this station. See &enum iwl_fw_sta_type
+ * @assoc_id: for GO only
+ * @beamform_flags: beam forming controls
+ * @mfp: indicates whether the STA uses management frame protection or not.
+ * @mimo: indicates whether the sta uses mimo or not
+ * @mimo_protection: indicates whether the sta uses mimo protection or not
+ * @ack_enabled: indicates that the AP supports receiving ACK-
+ * enabled AGG, i.e. both BACK and non-BACK frames in a single AGG
+ * @trig_rnd_alloc: indicates that trigger based random allocation
+ * is enabled according to UORA element existence
+ * @tx_ampdu_spacing: minimum A-MPDU spacing:
+ * 4 - 2us density, 5 - 4us density, 6 - 8us density, 7 - 16us density
+ * @tx_ampdu_max_size: maximum A-MPDU length: 0 - 8K, 1 - 16K, 2 - 32K,
+ * 3 - 64K, 4 - 128K, 5 - 256K, 6 - 512K, 7 - 1024K.
+ * @sp_length: the size of the SP in actual number of frames
+ * @uapsd_acs: 4 LS bits are trigger enabled ACs, 4 MS bits are the deliver
+ * enabled ACs.
+ * @pkt_ext: optional, exists according to PPE-present bit in the HE/EHT-PHY
+ * capa
+ * @htc_flags: which features are supported in HTC
+ */
+struct iwl_sta_cfg_cmd_v1 {
+ __le32 sta_id;
+ __le32 link_id;
+ u8 peer_mld_address[ETH_ALEN];
+ __le16 reserved_for_peer_mld_address;
+ u8 peer_link_address[ETH_ALEN];
+ __le16 reserved_for_peer_link_address;
+ __le32 station_type;
+ __le32 assoc_id;
+ __le32 beamform_flags;
+ __le32 mfp;
+ __le32 mimo;
+ __le32 mimo_protection;
+ __le32 ack_enabled;
+ __le32 trig_rnd_alloc;
+ __le32 tx_ampdu_spacing;
+ __le32 tx_ampdu_max_size;
+ __le32 sp_length;
+ __le32 uapsd_acs;
+ struct iwl_he_pkt_ext_v2 pkt_ext;
+ __le32 htc_flags;
+} __packed; /* STA_CMD_API_S_VER_1 */
+
+/**
* struct iwl_sta_cfg_cmd - cmd structure to add a peer sta to the uCode's
* station table
* ( STA_CONFIG_CMD = 0xA )
@@ -620,6 +733,14 @@ enum iwl_fw_sta_type {
* @pkt_ext: optional, exists according to PPE-present bit in the HE/EHT-PHY
* capa
* @htc_flags: which features are supported in HTC
+ * @use_ldpc_x2_cw: Indicates whether to use LDPC with double CW
+ * @use_icf: Indicates whether to use ICF instead of RTS
+ * @dps_pad_time: DPS (Dynamic Power Save) padding delay resolution to ensure
+ * proper timing alignment
+ * @dps_trans_delay: DPS minimal time that takes the peer to return to low power
+ * @mic_prep_pad_delay: MIC prep time padding
+ * @mic_compute_pad_delay: MIC compute time padding
+ * @reserved: Reserved for alignment
*/
struct iwl_sta_cfg_cmd {
__le32 sta_id;
@@ -642,7 +763,14 @@ struct iwl_sta_cfg_cmd {
__le32 uapsd_acs;
struct iwl_he_pkt_ext_v2 pkt_ext;
__le32 htc_flags;
-} __packed; /* STA_CMD_API_S_VER_1 */
+ u8 use_ldpc_x2_cw;
+ u8 use_icf;
+ u8 dps_pad_time;
+ u8 dps_trans_delay;
+ u8 mic_prep_pad_delay;
+ u8 mic_compute_pad_delay;
+ u8 reserved[2];
+} __packed; /* STA_CMD_API_S_VER_2 */
/**
* struct iwl_aux_sta_cmd - command for AUX STA configuration
@@ -686,9 +814,9 @@ struct iwl_mvm_sta_disable_tx_cmd {
/**
* enum iwl_mvm_fw_esr_recommendation - FW recommendation code
- * @ESR_RECOMMEND_LEAVE: recommendation to leave esr
- * @ESR_FORCE_LEAVE: force exiting esr
- * @ESR_RECOMMEND_ENTER: recommendation to enter esr
+ * @ESR_RECOMMEND_LEAVE: recommendation to leave EMLSR
+ * @ESR_FORCE_LEAVE: force exiting EMLSR
+ * @ESR_RECOMMEND_ENTER: recommendation to enter EMLSR
*/
enum iwl_mvm_fw_esr_recommendation {
ESR_RECOMMEND_LEAVE,
@@ -697,15 +825,46 @@ enum iwl_mvm_fw_esr_recommendation {
}; /* ESR_MODE_RECOMMENDATION_CODE_API_E_VER_1 */
/**
- * struct iwl_esr_mode_notif - FWs recommendation/force for esr mode
+ * struct iwl_esr_mode_notif_v1 - FW recommendation/force for EMLSR mode
*
- * @action: the action to apply on esr state. See &iwl_mvm_fw_esr_recommendation
+ * @action: the action to apply on EMLSR state.
+ * See &iwl_mvm_fw_esr_recommendation
*/
-struct iwl_esr_mode_notif {
+struct iwl_esr_mode_notif_v1 {
__le32 action;
} __packed; /* ESR_MODE_RECOMMENDATION_NTFY_API_S_VER_1 */
/**
+ * enum iwl_esr_leave_reason - reasons for leaving EMLSR mode
+ *
+ * @ESR_LEAVE_REASON_OMI_MU_UL_DISALLOWED: OMI MU UL disallowed
+ * @ESR_LEAVE_REASON_NO_TRIG_FOR_ESR_STA: No trigger for EMLSR station
+ * @ESR_LEAVE_REASON_NO_ESR_STA_IN_MU_DL: No EMLSR station in MU DL
+ * @ESR_LEAVE_REASON_BAD_ACTIV_FRAME_TH: Bad activation frame threshold
+ * @ESR_LEAVE_REASON_RTS_IN_DUAL_LISTEN: RTS in dual listen
+ */
+enum iwl_esr_leave_reason {
+ ESR_LEAVE_REASON_OMI_MU_UL_DISALLOWED = BIT(0),
+ ESR_LEAVE_REASON_NO_TRIG_FOR_ESR_STA = BIT(1),
+ ESR_LEAVE_REASON_NO_ESR_STA_IN_MU_DL = BIT(2),
+ ESR_LEAVE_REASON_BAD_ACTIV_FRAME_TH = BIT(3),
+ ESR_LEAVE_REASON_RTS_IN_DUAL_LISTEN = BIT(4),
+};
+
+/**
+ * struct iwl_esr_mode_notif - FW recommendation/force for EMLSR mode
+ *
+ * @action: the action to apply on EMLSR state.
+ * See &iwl_mvm_fw_esr_recommendation
+ * @leave_reason_mask: mask for various reasons to leave EMLSR mode.
+ * See &iwl_esr_leave_reason
+ */
+struct iwl_esr_mode_notif {
+ __le32 action;
+ __le32 leave_reason_mask;
+} __packed; /* ESR_MODE_RECOMMENDATION_NTFY_API_S_VER_2 */
+
+/**
* struct iwl_missed_beacons_notif - sent when by the firmware upon beacon loss
* ( MISSED_BEACONS_NOTIF = 0xF6 )
* @link_id: fw link ID
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
index 26301c0b06a1..2a174c00b712 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2022, 2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2022, 2024-2025 Intel Corporation
* Copyright (C) 2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_mac_h__
@@ -287,9 +287,9 @@ struct iwl_ac_qos {
__le16 cw_min;
__le16 cw_max;
u8 aifsn;
- u8 fifos_mask;
+ u8 fifos_mask; /* not in use since _VER_3 */
__le16 edca_txop;
-} __packed; /* AC_QOS_API_S_VER_2 */
+} __packed; /* AC_QOS_API_S_VER_2, _VER_3 */
/**
* struct iwl_mac_ctx_cmd - command structure to configure MAC contexts
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
index 5cdc09d465d4..4644fc1aa1ec 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -18,13 +18,8 @@ enum iwl_regulatory_and_nvm_subcmd_ids {
/**
* @LARI_CONFIG_CHANGE: &struct iwl_lari_config_change_cmd_v1,
- * &struct iwl_lari_config_change_cmd_v2,
- * &struct iwl_lari_config_change_cmd_v3,
- * &struct iwl_lari_config_change_cmd_v4,
- * &struct iwl_lari_config_change_cmd_v5,
* &struct iwl_lari_config_change_cmd_v6,
- * &struct iwl_lari_config_change_cmd_v7,
- * &struct iwl_lari_config_change_cmd_v10 or
+ * &struct iwl_lari_config_change_cmd_v8,
* &struct iwl_lari_config_change_cmd
*/
LARI_CONFIG_CHANGE = 0x1,
@@ -565,74 +560,6 @@ struct iwl_lari_config_change_cmd_v1 {
} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_1 */
/**
- * struct iwl_lari_config_change_cmd_v2 - change LARI configuration
- * @config_bitmap: bit map of the config commands. each bit will trigger a
- * different predefined FW config operation
- * @oem_uhb_allow_bitmap: bitmap of UHB enabled MCC sets
- */
-struct iwl_lari_config_change_cmd_v2 {
- __le32 config_bitmap;
- __le32 oem_uhb_allow_bitmap;
-} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_2 */
-
-/**
- * struct iwl_lari_config_change_cmd_v3 - change LARI configuration
- * @config_bitmap: bit map of the config commands. each bit will trigger a
- * different predefined FW config operation
- * @oem_uhb_allow_bitmap: bitmap of UHB enabled MCC sets
- * @oem_11ax_allow_bitmap: bitmap of 11ax allowed MCCs.
- * For each supported country, a pair of regulatory override bit and 11ax mode exist
- * in the bit field.
- */
-struct iwl_lari_config_change_cmd_v3 {
- __le32 config_bitmap;
- __le32 oem_uhb_allow_bitmap;
- __le32 oem_11ax_allow_bitmap;
-} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_3 */
-
-/**
- * struct iwl_lari_config_change_cmd_v4 - change LARI configuration
- * @config_bitmap: Bitmap of the config commands. Each bit will trigger a
- * different predefined FW config operation.
- * @oem_uhb_allow_bitmap: Bitmap of UHB enabled MCC sets.
- * @oem_11ax_allow_bitmap: Bitmap of 11ax allowed MCCs. There are two bits
- * per country, one to indicate whether to override and the other to
- * indicate the value to use.
- * @oem_unii4_allow_bitmap: Bitmap of unii4 allowed MCCs.There are two bits
- * per country, one to indicate whether to override and the other to
- * indicate allow/disallow unii4 channels.
- */
-struct iwl_lari_config_change_cmd_v4 {
- __le32 config_bitmap;
- __le32 oem_uhb_allow_bitmap;
- __le32 oem_11ax_allow_bitmap;
- __le32 oem_unii4_allow_bitmap;
-} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_4 */
-
-/**
- * struct iwl_lari_config_change_cmd_v5 - change LARI configuration
- * @config_bitmap: Bitmap of the config commands. Each bit will trigger a
- * different predefined FW config operation.
- * @oem_uhb_allow_bitmap: Bitmap of UHB enabled MCC sets.
- * @oem_11ax_allow_bitmap: Bitmap of 11ax allowed MCCs. There are two bits
- * per country, one to indicate whether to override and the other to
- * indicate the value to use.
- * @oem_unii4_allow_bitmap: Bitmap of unii4 allowed MCCs.There are two bits
- * per country, one to indicate whether to override and the other to
- * indicate allow/disallow unii4 channels.
- * @chan_state_active_bitmap: Bitmap for overriding channel state to active.
- * Each bit represents a country or region to activate, according to the BIOS
- * definitions.
- */
-struct iwl_lari_config_change_cmd_v5 {
- __le32 config_bitmap;
- __le32 oem_uhb_allow_bitmap;
- __le32 oem_11ax_allow_bitmap;
- __le32 oem_unii4_allow_bitmap;
- __le32 chan_state_active_bitmap;
-} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_5 */
-
-/**
* struct iwl_lari_config_change_cmd_v6 - change LARI configuration
* @config_bitmap: Bitmap of the config commands. Each bit will trigger a
* different predefined FW config operation.
@@ -659,8 +586,7 @@ struct iwl_lari_config_change_cmd_v6 {
} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_6 */
/**
- * struct iwl_lari_config_change_cmd_v7 - change LARI configuration
- * This structure is used also for lari cmd version 8 and 9.
+ * struct iwl_lari_config_change_cmd_v8 - change LARI configuration
* @config_bitmap: Bitmap of the config commands. Each bit will trigger a
* different predefined FW config operation.
* @oem_uhb_allow_bitmap: Bitmap of UHB enabled MCC sets.
@@ -670,21 +596,19 @@ struct iwl_lari_config_change_cmd_v6 {
* @oem_unii4_allow_bitmap: Bitmap of unii4 allowed MCCs.There are two bits
* per country, one to indicate whether to override and the other to
* indicate allow/disallow unii4 channels.
- * For LARI cmd version 4 to 8 - bits 0:3 are supported.
- * For LARI cmd version 9 - bits 0:5 are supported.
+ * bit 0 - 3: supported.
* @chan_state_active_bitmap: Bitmap to enable different bands per country
* or region.
* Each bit represents a country or region, and a band to activate
* according to the BIOS definitions.
- * For LARI cmd version 7 - bits 0:3 are supported.
- * For LARI cmd version 8 - bits 0:4 are supported.
+ * bit 0 - 4: supported.
* @force_disable_channels_bitmap: Bitmap of disabled bands/channels.
* Each bit represents a set of channels in a specific band that should be
* disabled
* @edt_bitmap: Bitmap of energy detection threshold table.
* Disable/enable the EDT optimization method for different band.
*/
-struct iwl_lari_config_change_cmd_v7 {
+struct iwl_lari_config_change_cmd_v8 {
__le32 config_bitmap;
__le32 oem_uhb_allow_bitmap;
__le32 oem_11ax_allow_bitmap;
@@ -693,48 +617,8 @@ struct iwl_lari_config_change_cmd_v7 {
__le32 force_disable_channels_bitmap;
__le32 edt_bitmap;
} __packed;
-/* LARI_CHANGE_CONF_CMD_S_VER_7 */
/* LARI_CHANGE_CONF_CMD_S_VER_8 */
-/* LARI_CHANGE_CONF_CMD_S_VER_9 */
-/**
- * struct iwl_lari_config_change_cmd_v10 - change LARI configuration
- * @config_bitmap: Bitmap of the config commands. Each bit will trigger a
- * different predefined FW config operation.
- * @oem_uhb_allow_bitmap: Bitmap of UHB enabled MCC sets.
- * @oem_11ax_allow_bitmap: Bitmap of 11ax allowed MCCs. There are two bits
- * per country, one to indicate whether to override and the other to
- * indicate the value to use.
- * @oem_unii4_allow_bitmap: Bitmap of unii4 allowed MCCs.There are two bits
- * per country, one to indicate whether to override and the other to
- * indicate allow/disallow unii4 channels.
- * For LARI cmd version 10 - bits 0:5 are supported.
- * @chan_state_active_bitmap: Bitmap to enable different bands per country
- * or region.
- * Each bit represents a country or region, and a band to activate
- * according to the BIOS definitions.
- * For LARI cmd version 10 - bits 0:4 are supported.
- * @force_disable_channels_bitmap: Bitmap of disabled bands/channels.
- * Each bit represents a set of channels in a specific band that should be
- * disabled
- * @edt_bitmap: Bitmap of energy detection threshold table.
- * Disable/enable the EDT optimization method for different band.
- * @oem_320mhz_allow_bitmap: 320Mhz bandwidth enablement bitmap per MCC.
- * bit0: enable 320Mhz in Japan.
- * bit1: enable 320Mhz in South Korea.
- * bit 2 - 31: reserved.
- */
-struct iwl_lari_config_change_cmd_v10 {
- __le32 config_bitmap;
- __le32 oem_uhb_allow_bitmap;
- __le32 oem_11ax_allow_bitmap;
- __le32 oem_unii4_allow_bitmap;
- __le32 chan_state_active_bitmap;
- __le32 force_disable_channels_bitmap;
- __le32 edt_bitmap;
- __le32 oem_320mhz_allow_bitmap;
-} __packed;
-/* LARI_CHANGE_CONF_CMD_S_VER_10 */
/**
* struct iwl_lari_config_change_cmd - change LARI configuration
@@ -747,14 +631,11 @@ struct iwl_lari_config_change_cmd_v10 {
* @oem_unii4_allow_bitmap: Bitmap of unii4 allowed MCCs.There are two bits
* per country, one to indicate whether to override and the other to
* indicate allow/disallow unii4 channels.
- * For LARI cmd version 11 - bits 0:5 are supported.
* @chan_state_active_bitmap: Bitmap to enable different bands per country
* or region.
* Each bit represents a country or region, and a band to activate
* according to the BIOS definitions.
- * For LARI cmd version 11 - bits 0:4 are supported.
- * For LARI cmd version 12 - bits 0:6 are supported and bits 7:31 are
- * reserved. No need to mask out the reserved bits.
+ * bit 0 - 6: supported.
* @force_disable_channels_bitmap: Bitmap of disabled bands/channels.
* Each bit represents a set of channels in a specific band that should be
* disabled
@@ -781,12 +662,12 @@ struct iwl_lari_config_change_cmd {
__le32 oem_320mhz_allow_bitmap;
__le32 oem_11be_allow_bitmap;
} __packed;
-/* LARI_CHANGE_CONF_CMD_S_VER_11 */
/* LARI_CHANGE_CONF_CMD_S_VER_12 */
/* Activate UNII-1 (5.2GHz) for World Wide */
#define ACTIVATE_5G2_IN_WW_MASK BIT(4)
-#define CHAN_STATE_ACTIVE_BITMAP_CMD_V11 0x1F
+#define CHAN_STATE_ACTIVE_BITMAP_CMD_V8 0x1F
+#define CHAN_STATE_ACTIVE_BITMAP_CMD_V12 0x7F
/**
* struct iwl_pnvm_init_complete_ntfy - PNVM initialization complete
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h
index 9b09b835560b..bb801650a565 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h
@@ -3,7 +3,7 @@
* Copyright (C) 2012-2014 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
- * Copyright (C) 2021-2024 Intel Corporation
+ * Copyright (C) 2021-2025 Intel Corporation
*/
#ifndef __iwl_fw_api_offload_h__
#define __iwl_fw_api_offload_h__
@@ -19,8 +19,8 @@ enum iwl_prot_offload_subcmd_ids {
/**
* @WOWLAN_INFO_NOTIFICATION: Notification in
- * &struct iwl_wowlan_info_notif_v1, &struct iwl_wowlan_info_notif_v2,
- * or &struct iwl_wowlan_info_notif
+ * &struct iwl_wowlan_info_notif_v1, iwl_wowlan_info_notif_v3,
+ * &struct iwl_wowlan_info_notif_v5 or &struct iwl_wowlan_info_notif
*/
WOWLAN_INFO_NOTIFICATION = 0xFD,
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h b/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h
index 4d8a12799c4d..4594a7c94bd6 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018, 2020-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018, 2020-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -146,6 +146,7 @@ struct iwl_phy_context_cmd_v1 {
* @sbb_ctrl_channel_loc: location of the control channel
* @puncture_mask: bitmap of punctured subchannels
* @dsp_cfg_flags: set to 0
+ * @secondary_ctrl_chnl_loc: location of secondary control channel
* @reserved: reserved to align to 64 bit
*/
struct iwl_phy_context_cmd {
@@ -164,11 +165,13 @@ struct iwl_phy_context_cmd {
};
};
__le32 dsp_cfg_flags;
- __le32 reserved;
+ u8 secondary_ctrl_chnl_loc;
+ u8 reserved[3];
} __packed; /* PHY_CONTEXT_CMD_API_VER_3,
* PHY_CONTEXT_CMD_API_VER_4,
* PHY_CONTEXT_CMD_API_VER_5,
- * PHY_CONTEXT_CMD_API_VER_6
+ * PHY_CONTEXT_CMD_API_VER_6,
+ * PHY_CONTEXT_CMD_API_S_VER_7
*/
#endif /* __iwl_fw_api_phy_ctxt_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
index 37ec26596ee7..535864e22626 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
@@ -1,12 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_power_h__
#define __iwl_fw_api_power_h__
+#include "nvm-reg.h"
+
/* Power Management Commands, Responses, Notifications */
/**
@@ -54,7 +56,7 @@ struct iwl_ltr_config_cmd_v1 {
* @flags: See &enum iwl_ltr_config_flags
* @static_long: static LTR Long register value.
* @static_short: static LTR Short register value.
- * @ltr_cfg_values: LTR parameters table values (in usec) in folowing order:
+ * @ltr_cfg_values: LTR parameters table values (in usec) in following order:
* TX, RX, Short Idle, Long Idle. Used only if %LTR_CFG_FLAG_UPDATE_VALUES
* is set.
* @ltr_short_idle_timeout: LTR Short Idle timeout (in usec). Used only if
@@ -89,6 +91,7 @@ struct iwl_ltr_config_cmd {
* @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
* @POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK: AP/GO's uAPSD misbehaving
* detection enablement
+ * @POWER_FLAGS_ENABLE_SMPS_MSK: SMPS is allowed for this vif
*/
enum iwl_power_flags {
POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0),
@@ -99,6 +102,7 @@ enum iwl_power_flags {
POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(9),
POWER_FLAGS_LPRX_ENA_MSK = BIT(11),
POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK = BIT(12),
+ POWER_FLAGS_ENABLE_SMPS_MSK = BIT(14),
};
#define IWL_POWER_VEC_SIZE 5
@@ -216,7 +220,6 @@ struct iwl_mac_power_cmd {
/* CONTEXT_DESC_API_T_VER_1 */
__le32 id_and_color;
- /* CLIENT_PM_POWER_TABLE_S_VER_1 */
__le16 flags;
__le16 keep_alive_seconds;
__le32 rx_data_timeout;
@@ -237,7 +240,7 @@ struct iwl_mac_power_cmd {
u8 heavy_rx_thld_percentage;
u8 limited_ps_threshold;
u8 reserved;
-} __packed;
+} __packed; /* CLIENT_PM_POWER_TABLE_S_VER_1, VER_2 */
/*
* struct iwl_uapsd_misbehaving_ap_notif - FW sends this notification when
@@ -252,19 +255,6 @@ struct iwl_uapsd_misbehaving_ap_notif {
u8 reserved[3];
} __packed;
-/**
- * struct iwl_reduce_tx_power_cmd - TX power reduction command
- * REDUCE_TX_POWER_CMD = 0x9f
- * @flags: (reserved for future implementation)
- * @mac_context_id: id of the mac ctx for which we are reducing TX power.
- * @pwr_restriction: TX power restriction in dBms.
- */
-struct iwl_reduce_tx_power_cmd {
- u8 flags;
- u8 mac_context_id;
- __le16 pwr_restriction;
-} __packed; /* TX_REDUCED_POWER_API_S_VER_1 */
-
enum iwl_dev_tx_power_cmd_mode {
IWL_TX_POWER_MODE_SET_LINK = 0,
IWL_TX_POWER_MODE_SET_DEVICE = 1,
@@ -339,50 +329,6 @@ struct iwl_dev_tx_power_cmd_v5 {
} __packed; /* TX_REDUCED_POWER_API_S_VER_5 */
/**
- * struct iwl_dev_tx_power_cmd_v6 - TX power reduction command version 6
- * @per_chain: per chain restrictions
- * @enable_ack_reduction: enable or disable close range ack TX power
- * reduction.
- * @per_chain_restriction_changed: is per_chain_restriction has changed
- * from last command. used if set_mode is
- * IWL_TX_POWER_MODE_SET_SAR_TIMER.
- * note: if not changed, the command is used for keep alive only.
- * @reserved: reserved (padding)
- * @timer_period: timer in milliseconds. if expires FW will change to default
- * BIOS values. relevant if setMode is IWL_TX_POWER_MODE_SET_SAR_TIMER
- */
-struct iwl_dev_tx_power_cmd_v6 {
- __le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
- u8 enable_ack_reduction;
- u8 per_chain_restriction_changed;
- u8 reserved[2];
- __le32 timer_period;
-} __packed; /* TX_REDUCED_POWER_API_S_VER_6 */
-
-/**
- * struct iwl_dev_tx_power_cmd_v7 - TX power reduction command version 7
- * @per_chain: per chain restrictions
- * @enable_ack_reduction: enable or disable close range ack TX power
- * reduction.
- * @per_chain_restriction_changed: is per_chain_restriction has changed
- * from last command. used if set_mode is
- * IWL_TX_POWER_MODE_SET_SAR_TIMER.
- * note: if not changed, the command is used for keep alive only.
- * @reserved: reserved (padding)
- * @timer_period: timer in milliseconds. if expires FW will change to default
- * BIOS values. relevant if setMode is IWL_TX_POWER_MODE_SET_SAR_TIMER
- * @flags: reduce power flags.
- */
-struct iwl_dev_tx_power_cmd_v7 {
- __le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
- u8 enable_ack_reduction;
- u8 per_chain_restriction_changed;
- u8 reserved[2];
- __le32 timer_period;
- __le32 flags;
-} __packed; /* TX_REDUCED_POWER_API_S_VER_7 */
-
-/**
* struct iwl_dev_tx_power_cmd_v8 - TX power reduction command version 8
* @per_chain: per chain restrictions
* @enable_ack_reduction: enable or disable close range ack TX power
@@ -426,8 +372,6 @@ struct iwl_dev_tx_power_cmd_per_band {
* @v3: version 3 part of the command
* @v4: version 4 part of the command
* @v5: version 5 part of the command
- * @v6: version 6 part of the command
- * @v7: version 7 part of the command
* @v8: version 8 part of the command
*/
struct iwl_dev_tx_power_cmd_v3_v8 {
@@ -437,8 +381,6 @@ struct iwl_dev_tx_power_cmd_v3_v8 {
struct iwl_dev_tx_power_cmd_v3 v3;
struct iwl_dev_tx_power_cmd_v4 v4;
struct iwl_dev_tx_power_cmd_v5 v5;
- struct iwl_dev_tx_power_cmd_v6 v6;
- struct iwl_dev_tx_power_cmd_v7 v7;
struct iwl_dev_tx_power_cmd_v8 v8;
};
};
@@ -628,32 +570,38 @@ enum iwl_ppag_flags {
/**
* union iwl_ppag_table_cmd - union for all versions of PPAG command
- * @v1: version 1
- * @v2: version 2
- * version 3, 4, 5 and 6 are the same structure as v2,
- * but has a different format of the flags bitmap
+ * @v1: command version 1 structure.
+ * @v5: command version 5 structure.
+ * @v7: command version 7 structure.
* @v1.flags: values from &enum iwl_ppag_flags
* @v1.gain: table of antenna gain values per chain and sub-band
* @v1.reserved: reserved
- * @v2.flags: values from &enum iwl_ppag_flags
- * @v2.gain: table of antenna gain values per chain and sub-band
- * @v2.reserved: reserved
+ * @v5.flags: values from &enum iwl_ppag_flags
+ * @v5.gain: table of antenna gain values per chain and sub-band
+ * @v7.ppag_config_info: see @struct bios_value_u32
+ * @v7.gain: table of antenna gain values per chain and sub-band
+ * @v7.reserved: reserved
*/
union iwl_ppag_table_cmd {
struct {
__le32 flags;
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V1];
s8 reserved[2];
- } v1;
+ } __packed v1; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_1 */
struct {
__le32 flags;
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
s8 reserved[2];
- } v2;
+ } __packed v5; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_5 */
+ struct {
+ struct bios_value_u32 ppag_config_info;
+ s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
+ s8 reserved[2];
+ } __packed v7; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_7 */
} __packed;
-#define IWL_PPAG_CMD_V4_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK)
-#define IWL_PPAG_CMD_V5_MASK (IWL_PPAG_CMD_V4_MASK | \
+#define IWL_PPAG_CMD_V1_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK)
+#define IWL_PPAG_CMD_V5_MASK (IWL_PPAG_CMD_V1_MASK | \
IWL_PPAG_ETSI_LPI_UHB_MASK | \
IWL_PPAG_USA_LPI_UHB_MASK)
@@ -672,7 +620,7 @@ struct iwl_sar_offset_mapping_cmd {
} __packed; /*SAR_OFFSET_MAPPING_TABLE_CMD_API_S*/
/**
- * struct iwl_beacon_filter_cmd
+ * struct iwl_beacon_filter_cmd - beacon filter command
* REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
* @bf_energy_delta: Used for RSSI filtering, if in 'normal' state. Send beacon
* to driver if delta in Energy values calculated for this and last
@@ -690,7 +638,7 @@ struct iwl_sar_offset_mapping_cmd {
* Roaming Energy Delta Threshold, otherwise use normal Energy Delta
* Threshold. Typical energy threshold is -72dBm.
* @bf_temp_threshold: This threshold determines the type of temperature
- * filtering (Slow or Fast) that is selected (Units are in Celsuis):
+ * filtering (Slow or Fast) that is selected (Units are in Celsius):
* If the current temperature is above this threshold - Fast filter
* will be used, If the current temperature is below this threshold -
* Slow filter will be used.
@@ -698,12 +646,12 @@ struct iwl_sar_offset_mapping_cmd {
* calculated for this and the last passed beacon is greater than this
* threshold. Zero value means that the temperature change is ignored for
* beacon filtering; beacons will not be forced to be sent to driver
- * regardless of whether its temerature has been changed.
+ * regardless of whether its temperature has been changed.
* @bf_temp_slow_filter: Send Beacon to driver if delta in temperature values
* calculated for this and the last passed beacon is greater than this
* threshold. Zero value means that the temperature change is ignored for
* beacon filtering; beacons will not be forced to be sent to driver
- * regardless of whether its temerature has been changed.
+ * regardless of whether its temperature has been changed.
* @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled.
* @bf_debug_flag: beacon filtering debug configuration
* @bf_escape_timer: Send beacons to to driver if no beacons were passed
@@ -814,7 +762,7 @@ enum iwl_6ghz_ap_type {
}; /* PHY_AP_TYPE_API_E_VER_1 */
/**
- * struct iwl_txpower_constraints_cmd
+ * struct iwl_txpower_constraints_cmd - TX power constraints command
* AP_TX_POWER_CONSTRAINTS_CMD
* Used for VLP/LPI/AFC Access Point power constraints for 6GHz channels
* @link_id: linkId
@@ -838,4 +786,5 @@ struct iwl_txpower_constraints_cmd {
__s8 psd_pwr[IWL_MAX_TX_EIRP_PSD_PWR_MAX_SIZE];
u8 reserved[3];
} __packed; /* PHY_AP_TX_POWER_CONSTRAINTS_CMD_API_S_VER_1 */
+
#endif /* __iwl_fw_api_power_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
index c2f806cbab59..9c464e7aba10 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
@@ -1,11 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2022, 2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2022, 2024-2025 Intel Corporation
* Copyright (C) 2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_rs_h__
#define __iwl_fw_api_rs_h__
-
+#include <linux/bitfield.h>
+#include <linux/types.h>
+#include <linux/bits.h>
#include "mac.h"
/**
@@ -22,6 +24,8 @@
* for BPSK (MCS 0) with 2 spatial
* streams
* @IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK: enable support for EHT extra LTF
+ * @IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_1_5_MBPS_MSK: support ELR 1.5 Mbps
+ * @IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_3_MBPS_MSK: support ELR 3 Mbps
*/
enum iwl_tlc_mng_cfg_flags {
IWL_TLC_MNG_CFG_FLAGS_STBC_MSK = BIT(0),
@@ -30,6 +34,8 @@ enum iwl_tlc_mng_cfg_flags {
IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK = BIT(3),
IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_2_MSK = BIT(4),
IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK = BIT(6),
+ IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_1_5_MBPS_MSK = BIT(7),
+ IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_3_MBPS_MSK = BIT(8),
};
/**
@@ -199,6 +205,37 @@ struct iwl_tlc_config_cmd_v4 {
} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_4 */
/**
+ * struct iwl_tlc_config_cmd - TLC configuration
+ * @sta_id: station id
+ * @reserved1: reserved
+ * @max_ch_width: max supported channel width from &enum iwl_tlc_mng_cfg_cw
+ * @mode: &enum iwl_tlc_mng_cfg_mode
+ * @chains: bitmask of &enum iwl_tlc_mng_cfg_chains
+ * @sgi_ch_width_supp: bitmap of SGI support per channel width
+ * use BIT(&enum iwl_tlc_mng_cfg_cw)
+ * @flags: bitmask of &enum iwl_tlc_mng_cfg_flags
+ * @non_ht_rates: bitmap of supported legacy rates
+ * @ht_rates: bitmap of &enum iwl_tlc_mng_ht_rates, per <nss, channel-width>
+ * pair (0 - 80mhz width and below, 1 - 160mhz, 2 - 320mhz).
+ * @max_mpdu_len: max MPDU length, in bytes
+ * @max_tx_op: max TXOP in uSecs for all AC (BK, BE, VO, VI),
+ * set zero for no limit.
+ */
+struct iwl_tlc_config_cmd {
+ u8 sta_id;
+ u8 reserved1[3];
+ u8 max_ch_width;
+ u8 mode;
+ u8 chains;
+ u8 sgi_ch_width_supp;
+ __le16 flags;
+ __le16 non_ht_rates;
+ __le32 ht_rates[IWL_TLC_NSS_MAX][IWL_TLC_MCS_PER_BW_NUM_V4];
+ __le16 max_mpdu_len;
+ __le16 max_tx_op;
+} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_5 */
+
+/**
* enum iwl_tlc_update_flags - updated fields
* @IWL_TLC_NOTIF_FLAG_RATE: last initial rate update
* @IWL_TLC_NOTIF_FLAG_AMSDU: umsdu parameters update
@@ -213,7 +250,8 @@ enum iwl_tlc_update_flags {
* @sta_id: station id
* @reserved: reserved
* @flags: bitmap of notifications reported
- * @rate: current initial rate
+ * @rate: current initial rate, format depends on the notification
+ * version
* @amsdu_size: Max AMSDU size, in bytes
* @amsdu_enabled: bitmap for per-TID AMSDU enablement
*/
@@ -224,7 +262,7 @@ struct iwl_tlc_update_notif {
__le32 rate;
__le32 amsdu_size;
__le32 amsdu_enabled;
-} __packed; /* TLC_MNG_UPDATE_NTFY_API_S_VER_2 */
+} __packed; /* TLC_MNG_UPDATE_NTFY_API_S_VER_2, _VER_3, _VER_4 */
/**
* enum iwl_tlc_debug_types - debug options
@@ -427,6 +465,7 @@ enum {
/* Bit 4-5: (0) SISO, (1) MIMO2 (2) MIMO3 */
#define RATE_VHT_MCS_RATE_CODE_MSK 0xf
+#define RATE_VHT_MCS_NSS_MSK 0x30
/*
* Legacy OFDM rate format for bits 7:0
@@ -541,7 +580,7 @@ enum {
#define RATE_MCS_CTS_REQUIRED_POS (31)
#define RATE_MCS_CTS_REQUIRED_MSK (0x1 << RATE_MCS_CTS_REQUIRED_POS)
-/* rate_n_flags bit field version 2
+/* rate_n_flags bit field version 2 and 3
*
* The 32-bit value has different layouts in the low 8 bits depending on the
* format. There are three formats, HT, VHT and legacy (11abg, with subformats
@@ -553,23 +592,25 @@ enum {
* (0) Legacy CCK (1) Legacy OFDM (2) High-throughput (HT)
* (3) Very High-throughput (VHT) (4) High-efficiency (HE)
* (5) Extremely High-throughput (EHT)
+ * (6) Ultra High Reliability (UHR) (v3 rate format only)
*/
#define RATE_MCS_MOD_TYPE_POS 8
#define RATE_MCS_MOD_TYPE_MSK (0x7 << RATE_MCS_MOD_TYPE_POS)
-#define RATE_MCS_CCK_MSK (0 << RATE_MCS_MOD_TYPE_POS)
-#define RATE_MCS_LEGACY_OFDM_MSK (1 << RATE_MCS_MOD_TYPE_POS)
-#define RATE_MCS_HT_MSK (2 << RATE_MCS_MOD_TYPE_POS)
-#define RATE_MCS_VHT_MSK (3 << RATE_MCS_MOD_TYPE_POS)
-#define RATE_MCS_HE_MSK (4 << RATE_MCS_MOD_TYPE_POS)
-#define RATE_MCS_EHT_MSK (5 << RATE_MCS_MOD_TYPE_POS)
+#define RATE_MCS_MOD_TYPE_CCK (0 << RATE_MCS_MOD_TYPE_POS)
+#define RATE_MCS_MOD_TYPE_LEGACY_OFDM (1 << RATE_MCS_MOD_TYPE_POS)
+#define RATE_MCS_MOD_TYPE_HT (2 << RATE_MCS_MOD_TYPE_POS)
+#define RATE_MCS_MOD_TYPE_VHT (3 << RATE_MCS_MOD_TYPE_POS)
+#define RATE_MCS_MOD_TYPE_HE (4 << RATE_MCS_MOD_TYPE_POS)
+#define RATE_MCS_MOD_TYPE_EHT (5 << RATE_MCS_MOD_TYPE_POS)
+#define RATE_MCS_MOD_TYPE_UHR (6 << RATE_MCS_MOD_TYPE_POS)
/*
* Legacy CCK rate format for bits 0:3:
*
- * (0) 0xa - 1 Mbps
- * (1) 0x14 - 2 Mbps
- * (2) 0x37 - 5.5 Mbps
- * (3) 0x6e - 11 nbps
+ * (0) 1 Mbps
+ * (1) 2 Mbps
+ * (2) 5.5 Mbps
+ * (3) 11 Mbps
*
* Legacy OFDM rate format for bis 3:0:
*
@@ -586,15 +627,19 @@ enum {
#define RATE_LEGACY_RATE_MSK 0x7
/*
- * HT, VHT, HE, EHT rate format for bits 3:0
- * 3-0: MCS
- *
+ * HT, VHT, HE, EHT, UHR rate format
+ * Version 2: (not applicable for UHR)
+ * 3-0: MCS
+ * 4: NSS==2 indicator
+ * Version 3:
+ * 4-0: MCS
+ * 5: NSS==2 indicator
*/
#define RATE_HT_MCS_CODE_MSK 0x7
-#define RATE_MCS_NSS_POS 4
-#define RATE_MCS_NSS_MSK (1 << RATE_MCS_NSS_POS)
-#define RATE_MCS_CODE_MSK 0xf
-#define RATE_HT_MCS_INDEX(r) ((((r) & RATE_MCS_NSS_MSK) >> 1) | \
+#define RATE_MCS_NSS_MSK_V2 0x10
+#define RATE_MCS_NSS_MSK 0x20
+#define RATE_MCS_CODE_MSK 0x1f
+#define RATE_HT_MCS_INDEX(r) ((((r) & RATE_MCS_NSS_MSK) >> 2) | \
((r) & RATE_HT_MCS_CODE_MSK))
/* Bits 7-5: reserved */
@@ -810,11 +855,38 @@ struct iwl_lq_cmd {
}; /* LINK_QUALITY_CMD_API_S_VER_1 */
u8 iwl_fw_rate_idx_to_plcp(int idx);
-u32 iwl_new_rate_from_v1(u32 rate_v1);
const struct iwl_rate_mcs_info *iwl_rate_mcs(int idx);
const char *iwl_rs_pretty_ant(u8 ant);
const char *iwl_rs_pretty_bw(int bw);
int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate);
bool iwl_he_is_sgi(u32 rate_n_flags);
+static inline u32 iwl_v3_rate_from_v2_v3(__le32 rate, bool fw_v3)
+{
+ u32 val;
+
+ if (fw_v3)
+ return le32_to_cpu(rate);
+
+ val = le32_to_cpu(rate) & ~RATE_MCS_NSS_MSK_V2;
+ val |= u32_encode_bits(le32_get_bits(rate, RATE_MCS_NSS_MSK_V2),
+ RATE_MCS_NSS_MSK);
+
+ return val;
+}
+
+static inline __le32 iwl_v3_rate_to_v2_v3(u32 rate, bool fw_v3)
+{
+ __le32 val;
+
+ if (fw_v3)
+ return cpu_to_le32(rate);
+
+ val = cpu_to_le32(rate & ~RATE_MCS_NSS_MSK);
+ val |= le32_encode_bits(u32_get_bits(rate, RATE_MCS_NSS_MSK),
+ RATE_MCS_NSS_MSK_V2);
+
+ return val;
+}
+
#endif /* __iwl_fw_api_rs_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
index 691c879cb90d..3ed7e0807b90 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -193,10 +193,13 @@ enum iwl_rx_mpdu_amsdu_info {
IWL_RX_MPDU_AMSDU_LAST_SUBFRAME = 0x80,
};
-#define RX_MPDU_BAND_POS 6
-#define RX_MPDU_BAND_MASK 0xC0
-#define BAND_IN_RX_STATUS(_val) \
- (((_val) & RX_MPDU_BAND_MASK) >> RX_MPDU_BAND_POS)
+enum iwl_rx_mpdu_mac_phy_band {
+ /* whether or not this is MAC or LINK depends on the API */
+ IWL_RX_MPDU_MAC_PHY_BAND_MAC_MASK = 0x0f,
+ IWL_RX_MPDU_MAC_PHY_BAND_LINK_MASK = 0x0f,
+ IWL_RX_MPDU_MAC_PHY_BAND_PHY_MASK = 0x30,
+ IWL_RX_MPDU_MAC_PHY_BAND_BAND_MASK = 0xc0,
+};
enum iwl_rx_l3_proto_values {
IWL_RX_L3_TYPE_NONE,
@@ -259,6 +262,7 @@ enum iwl_rx_mpdu_reorder_data {
};
enum iwl_rx_mpdu_phy_info {
+ IWL_RX_MPDU_PHY_EOF_INDICATION = BIT(0),
IWL_RX_MPDU_PHY_AMPDU = BIT(5),
IWL_RX_MPDU_PHY_AMPDU_TOGGLE = BIT(6),
IWL_RX_MPDU_PHY_SHORT_PREAMBLE = BIT(7),
@@ -639,7 +643,9 @@ struct iwl_rx_mpdu_desc_v3 {
*/
__le32 reserved[1];
} __packed; /* RX_MPDU_RES_START_API_S_VER_3,
- RX_MPDU_RES_START_API_S_VER_5 */
+ * RX_MPDU_RES_START_API_S_VER_5,
+ * RX_MPDU_RES_START_API_S_VER_6
+ */
/**
* struct iwl_rx_mpdu_desc - RX MPDU descriptor
@@ -668,9 +674,10 @@ struct iwl_rx_mpdu_desc {
*/
__le16 phy_info;
/**
- * @mac_phy_idx: MAC/PHY index
+ * @mac_phy_band: MAC/link ID, PHY ID, band;
+ * see &enum iwl_rx_mpdu_mac_phy_band
*/
- u8 mac_phy_idx;
+ u8 mac_phy_band;
/* DW4 */
union {
struct {
@@ -722,8 +729,10 @@ struct iwl_rx_mpdu_desc {
struct iwl_rx_mpdu_desc_v3 v3;
};
} __packed; /* RX_MPDU_RES_START_API_S_VER_3,
- RX_MPDU_RES_START_API_S_VER_4,
- RX_MPDU_RES_START_API_S_VER_5 */
+ * RX_MPDU_RES_START_API_S_VER_4,
+ * RX_MPDU_RES_START_API_S_VER_5,
+ * RX_MPDU_RES_START_API_S_VER_6
+ */
#define IWL_RX_DESC_SIZE_V1 offsetofend(struct iwl_rx_mpdu_desc, v1)
@@ -819,7 +828,7 @@ struct iwl_rx_no_data {
* 15:8 chain-B, measured at FINA time (FINA_ENERGY), 16:23 channel
* @on_air_rise_time: GP2 during on air rise
* @fr_time: frame time
- * @rate: rate/mcs of frame
+ * @rate: rate/mcs of frame, format depends on the notification version
* @phy_info: &enum iwl_rx_phy_eht_data0 and &enum iwl_rx_phy_info_type
* @rx_vec: DW-12:9 raw RX vectors from DSP according to modulation type.
* for VHT: OFDM_RX_VECTOR_SIGA1_OUT, OFDM_RX_VECTOR_SIGA2_OUT
@@ -835,9 +844,7 @@ struct iwl_rx_no_data_ver_3 {
__le32 rate;
__le32 phy_info[2];
__le32 rx_vec[4];
-} __packed; /* RX_NO_DATA_NTFY_API_S_VER_1,
- RX_NO_DATA_NTFY_API_S_VER_2
- RX_NO_DATA_NTFY_API_S_VER_3 */
+} __packed; /* RX_NO_DATA_NTFY_API_S_VER_3, _VER_4 */
struct iwl_frame_release {
u8 baid;
@@ -1015,4 +1022,309 @@ struct iwl_rfh_queue_config {
struct iwl_rfh_queue_data data[];
} __packed; /* RFH_QUEUE_CONFIG_API_S_VER_1 */
+/**
+ * struct iwl_beacon_filter_notif_v1 - beacon filter notification
+ * @average_energy: average energy for the received beacon
+ * @mac_id: MAC ID the beacon was received for
+ */
+struct iwl_beacon_filter_notif_v1 {
+ __le32 average_energy;
+ __le32 mac_id;
+} __packed; /* BEACON_FILTER_IN_NTFY_API_S_VER_1 */
+
+/**
+ * struct iwl_beacon_filter_notif - beacon filter notification
+ * @average_energy: average energy for the received beacon
+ * @link_id: link ID the beacon was received for
+ */
+struct iwl_beacon_filter_notif {
+ __le32 average_energy;
+ __le32 link_id;
+} __packed; /* BEACON_FILTER_IN_NTFY_API_S_VER_2 */
+
+union iwl_legacy_sig {
+#define OFDM_RX_LEGACY_LENGTH 0x00000fff
+#define OFDM_RX_RATE 0x0000f000
+ __le32 ofdm;
+#define CCK_CRFR_SHORT_PREAMBLE 0x00000040
+ __le32 cck;
+};
+
+struct iwl_ht_sigs {
+#define OFDM_RX_FRAME_HT_MCS 0x0000007f
+#define OFDM_RX_FRAME_HT_BANDWIDTH 0x00000080
+#define OFDM_RX_FRAME_HT_LENGTH 0x03ffff00
+ __le32 a1;
+ __le32 a2;
+};
+
+struct iwl_vht_sigs {
+#define OFDM_RX_FRAME_VHT_NUM_OF_DATA_SYM 0x000007ff
+#define OFDM_RX_FRAME_VHT_NUM_OF_DATA_SYM_VALID 0x80000000
+ __le32 a0;
+ __le32 a1, a2;
+};
+
+struct iwl_he_sigs {
+#define OFDM_RX_FRAME_HE_BEAM_CHANGE 0x00000001
+#define OFDM_RX_FRAME_HE_UL_FLAG 0x00000002
+#define OFDM_RX_FRAME_HE_MCS 0x0000003c
+#define OFDM_RX_FRAME_HE_DCM 0x00000040
+#define OFDM_RX_FRAME_HE_BSS_COLOR 0x00001f80
+#define OFDM_RX_FRAME_HE_SPATIAL_REUSE 0x0001e000
+#define OFDM_RX_FRAME_HE_BANDWIDTH 0x00060000
+#define OFDM_RX_FRAME_HE_SU_EXT_BW10 0x00080000
+#define OFDM_RX_FRAME_HE_GI_LTF_TYPE 0x00700000
+#define OFDM_RX_FRAME_HE_NSTS 0x03800000
+#define OFDM_RX_FRAME_HE_PRMBL_PUNC_TYPE 0x0c000000
+ __le32 a1;
+#define OFDM_RX_FRAME_HE_TXOP_DURATION 0x0000007f
+#define OFDM_RX_FRAME_HE_CODING 0x00000080
+#define OFDM_RX_FRAME_HE_CODING_EXTRA_SYM 0x00000100
+#define OFDM_RX_FRAME_HE_STBC 0x00000200
+#define OFDM_RX_FRAME_HE_BF 0x00000400
+#define OFDM_RX_FRAME_HE_PRE_FEC_PAD_FACTOR 0x00001800
+#define OFDM_RX_FRAME_HE_PE_DISAMBIG 0x00002000
+#define OFDM_RX_FRAME_HE_DOPPLER 0x00004000
+#define OFDM_RX_FRAME_HE_TYPE 0x00038000
+#define OFDM_RX_FRAME_HE_MU_NUM_OF_SIGB_SYM_OR_USER_NUM 0x003c0000
+#define OFDM_RX_FRAME_HE_MU_SIGB_COMP 0x00400000
+#define OFDM_RX_FRAME_HE_MU_NUM_OF_LTF_SYM 0x03800000
+ __le32 a2;
+#define OFDM_RX_FRAME_HE_NUM_OF_DATA_SYM 0x000007ff
+#define OFDM_RX_FRAME_HE_PE_DURATION 0x00003800
+#define OFDM_RX_FRAME_HE_NUM_OF_DATA_SYM_VALID 0x80000000
+ __le32 a3;
+#define OFDM_RX_FRAME_HE_SIGB_STA_ID_FOUND 0x00000001
+#define OFDM_RX_FRAME_HE_SIGB_STA_ID_INDX 0x0000000e
+#define OFDM_RX_FRAME_HE_SIGB_NSTS 0x00000070
+#define OFDM_RX_FRAME_HE_SIGB_BF 0x00000080
+#define OFDM_RX_FRAME_HE_SIGB_MCS 0x00000f00
+#define OFDM_RX_FRAME_HE_SIGB_DCM 0x00001000
+#define OFDM_RX_FRAME_HE_SIGB_CODING 0x00002000
+#define OFDM_RX_FRAME_HE_SIGB_SPATIAL_CONFIG 0x0003c000
+#define OFDM_RX_FRAME_HE_SIGB_STA_RU 0x03fc0000
+#define OFDM_RX_FRAME_HE_SIGB_NUM_OF_SYM 0x3c000000
+#define OFDM_RX_FRAME_HE_SIGB_CRC_OK 0x40000000
+ __le32 b;
+/* index 0 */
+#define OFDM_RX_FRAME_HE_RU_ALLOC_0_A1 0x000000ff
+#define OFDM_RX_FRAME_HE_RU_ALLOC_0_A2 0x0000ff00
+#define OFDM_RX_FRAME_HE_RU_ALLOC_0_B1 0x00ff0000
+#define OFDM_RX_FRAME_HE_RU_ALLOC_0_B2 0xff000000
+/* index 1 */
+#define OFDM_RX_FRAME_HE_RU_ALLOC_1_C1 0x000000ff
+#define OFDM_RX_FRAME_HE_RU_ALLOC_1_C2 0x0000ff00
+#define OFDM_RX_FRAME_HE_RU_ALLOC_1_D1 0x00ff0000
+#define OFDM_RX_FRAME_HE_RU_ALLOC_1_D2 0xff000000
+/* index 2 */
+#define OFDM_RX_FRAME_HE_CENTER_RU_CC1 0x00000001
+#define OFDM_RX_FRAME_HE_CENTER_RU_CC2 0x00000002
+#define OFDM_RX_FRAME_HE_COMMON_CC1_CRC_OK 0x00000004
+#define OFDM_RX_FRAME_HE_COMMON_CC2_CRC_OK 0x00000008
+ __le32 cmn[3];
+};
+
+struct iwl_he_tb_sigs {
+#define OFDM_RX_HE_TRIG_FORMAT 0x00000001
+#define OFDM_RX_HE_TRIG_BSS_COLOR 0x0000007e
+#define OFDM_RX_HE_TRIG_SPATIAL_REUSE_1 0x00000780
+#define OFDM_RX_HE_TRIG_SPATIAL_REUSE_2 0x00007800
+#define OFDM_RX_HE_TRIG_SPATIAL_REUSE_3 0x00078000
+#define OFDM_RX_HE_TRIG_SPATIAL_REUSE_4 0x00780000
+#define OFDM_RX_HE_TRIG_BANDWIDTH 0x03000000
+ __le32 a1;
+#define OFDM_RX_HE_TRIG_TXOP_DURATION 0x0000007f
+#define OFDM_RX_HE_TRIG_SIG2_RESERVED 0x0000ff80
+#define OFDM_RX_HE_TRIG_FORMAT_ERR 0x08000000
+#define OFDM_RX_HE_TRIG_BW_ERR 0x10000000
+#define OFDM_RX_HE_TRIG_LEGACY_LENGTH_ERR 0x20000000
+#define OFDM_RX_HE_TRIG_CRC_OK 0x40000000
+ __le32 a2;
+#define OFDM_UCODE_TRIG_BASE_RX_LGCY_LENGTH 0x00000fff
+#define OFDM_UCODE_TRIG_BASE_RX_BANDWIDTH 0x00007000
+#define OFDM_UCODE_TRIG_BASE_PS160 0x00008000
+#define OFDM_UCODE_EHT_TRIG_CONTROL_CHANNEL 0x000f0000
+ __le32 tb_rx0;
+#define OFDM_UCODE_TRIG_BASE_RX_MCS 0x0000000f
+#define OFDM_UCODE_TRIG_BASE_RX_DCM 0x00000010
+#define OFDM_UCODE_TRIG_BASE_RX_GI_LTF_TYPE 0x00000060
+#define OFDM_UCODE_TRIG_BASE_RX_NSTS 0x00000380
+#define OFDM_UCODE_TRIG_BASE_RX_CODING 0x00000400
+#define OFDM_UCODE_TRIG_BASE_RX_CODING_EXTRA_SYM 0x00000800
+#define OFDM_UCODE_TRIG_BASE_RX_STBC 0x00001000
+#define OFDM_UCODE_TRIG_BASE_RX_PRE_FEC_PAD_FACTOR 0x00006000
+#define OFDM_UCODE_TRIG_BASE_RX_PE_DISAMBIG 0x00008000
+#define OFDM_UCODE_TRIG_BASE_RX_DOPPLER 0x00010000
+#define OFDM_UCODE_TRIG_BASE_RX_RU 0x01fe0000
+#define OFDM_UCODE_TRIG_BASE_RX_RU_P80 0x00020000
+#define OFDM_UCODE_TRIG_BASE_RX_NUM_OF_LTF_SYM 0x0e000000
+#define OFDM_UCODE_TRIG_BASE_RX_LTF_PILOT_TYPE 0x10000000
+#define OFDM_UCODE_TRIG_BASE_RX_LOWEST_SS_ALLOCATION 0xe0000000
+ __le32 tb_rx1;
+};
+
+struct iwl_eht_sigs {
+#define OFDM_RX_FRAME_ENHANCED_WIFI_VER_ID 0x00000007
+#define OFDM_RX_FRAME_ENHANCED_WIFI_BANDWIDTH 0x00000038
+#define OFDM_RX_FRAME_ENHANCED_WIFI_UL_FLAG 0x00000040
+#define OFDM_RX_FRAME_ENHANCED_WIFI_BSS_COLOR 0x00001f80
+#define OFDM_RX_FRAME_ENHANCED_WIFI_TXOP_DURATION 0x000fe000
+#define OFDM_RX_FRAME_EHT_USIG1_DISREGARD 0x01f00000
+#define OFDM_RX_FRAME_EHT_USIG1_VALIDATE 0x02000000
+#define OFDM_RX_FRAME_EHT_BW320_SLOT 0x04000000
+#define OFDM_RX_FRAME_EHT_TYPE 0x18000000
+#define OFDM_RX_FRAME_ENHANCED_ER_NO_STREAMS 0x20000000
+ __le32 usig_a1;
+#define OFDM_RX_FRAME_EHT_PPDU_TYPE 0x00000003
+#define OFDM_RX_FRAME_EHT_USIG2_VALIDATE_B2 0x00000004
+#define OFDM_RX_FRAME_EHT_PUNC_CHANNEL 0x000000f8
+#define OFDM_RX_FRAME_EHT_USIG2_VALIDATE_B8 0x00000100
+#define OFDM_RX_FRAME_EHT_SIG_MCS 0x00000600
+#define OFDM_RX_FRAME_EHT_SIG_SYM_NUM 0x0000f800
+#define OFDM_RX_FRAME_EHT_TRIG_SPATIAL_REUSE_1 0x000f0000
+#define OFDM_RX_FRAME_EHT_TRIG_SPATIAL_REUSE_2 0x00f00000
+#define OFDM_RX_FRAME_EHT_TRIG_USIG2_DISREGARD 0x1f000000
+#define OFDM_RX_FRAME_EHT_TRIG_NO_STREAMS 0x20000000
+#define OFDM_RX_USIG_CRC_OK 0x40000000
+ __le32 usig_a2_eht;
+#define OFDM_RX_FRAME_EHT_SPATIAL_REUSE 0x0000000f
+#define OFDM_RX_FRAME_EHT_GI_LTF_TYPE 0x00000030
+#define OFDM_RX_FRAME_EHT_NUM_OF_LTF_SYM 0x000001c0
+#define OFDM_RX_FRAME_EHT_CODING_EXTRA_SYM 0x00000200
+#define OFDM_RX_FRAME_EHT_PRE_FEC_PAD_FACTOR 0x00000c00
+#define OFDM_RX_FRAME_EHT_PE_DISAMBIG 0x00001000
+#define OFDM_RX_FRAME_EHT_USIG_OVF_DISREGARD 0x0001e000
+#define OFDM_RX_FRAME_EHT_NUM_OF_USERS 0x000e0000
+#define OFDM_RX_FRAME_EHT_NSTS 0x00f00000
+#define OFDM_RX_FRAME_EHT_BF 0x01000000
+#define OFDM_RX_FRAME_EHT_USIG_OVF_NDP_DISREGARD 0x06000000
+#define OFDM_RX_FRAME_EHTSIG_COMM_CC1_CRC_OK 0x08000000
+#define OFDM_RX_FRAME_EHTSIG_COMM_CC2_CRC_OK 0x10000000
+#define OFDM_RX_FRAME_EHT_NON_VALID_RU_ALLOC 0x20000000
+#define OFDM_RX_FRAME_EHT_NO_STREAMS 0x40000000
+ __le32 b1;
+#define OFDM_RX_FRAME_EHT_MATCH_ID_FOUND 0x00000001
+#define OFDM_RX_FRAME_EHT_ID_INDX 0x0000000e
+#define OFDM_RX_FRAME_EHT_MCS 0x000000f0
+#define OFDM_RX_FRAME_EHT_CODING 0x00000100
+#define OFDM_RX_FRAME_EHT_SPATIAL_CONFIG 0x00007e00
+#define OFDM_RX_FRAME_EHT_STA_RU 0x007f8000
+#define OFDM_RX_FRAME_EHT_STA_RU_P80 0x00008000
+#define OFDM_RX_FRAME_EHT_STA_RU_PS160 0x00800000
+#define OFDM_RX_FRAME_EHT_USER_FIELD_CRC_OK 0x40000000
+ __le32 b2;
+#define OFDM_RX_FRAME_EHT_NUM_OF_DATA_SYM 0x000007ff
+#define OFDM_RX_FRAME_EHT_PE_DURATION 0x00003800
+#define OFDM_RX_FRAME_EHT_NUM_OF_DATA_SYM_VALID 0x80000000
+ __le32 sig2;
+#define OFDM_RX_FRAME_EHT_RU_ALLOC_0_A1 0x000001ff
+#define OFDM_RX_FRAME_EHT_RU_ALLOC_0_A2 0x0003fe00
+#define OFDM_RX_FRAME_EHT_RU_ALLOC_0_A3 0x07fc0000
+#define OFDM_RX_FRAME_EHT_RU_ALLOC_1_B1 0x000001ff
+#define OFDM_RX_FRAME_EHT_RU_ALLOC_1_B2 0x0003fe00
+#define OFDM_RX_FRAME_EHT_RU_ALLOC_1_B3 0x07fc0000
+#define OFDM_RX_FRAME_EHT_RU_ALLOC_2_C1 0x000001ff
+#define OFDM_RX_FRAME_EHT_RU_ALLOC_2_C2 0x0003fe00
+#define OFDM_RX_FRAME_EHT_RU_ALLOC_2_C3 0x07fc0000
+#define OFDM_RX_FRAME_EHT_RU_ALLOC_3_D1 0x000001ff
+#define OFDM_RX_FRAME_EHT_RU_ALLOC_3_D2 0x0003fe00
+#define OFDM_RX_FRAME_EHT_RU_ALLOC_3_D3 0x07fc0000
+#define OFDM_RX_FRAME_EHT_RU_ALLOC_4_A4 0x000001ff
+#define OFDM_RX_FRAME_EHT_RU_ALLOC_4_B4 0x0003fe00
+#define OFDM_RX_FRAME_EHT_RU_ALLOC_5_C4 0x000001ff
+#define OFDM_RX_FRAME_EHT_RU_ALLOC_5_D4 0x0003fe00
+ __le32 cmn[6];
+#define OFDM_RX_FRAME_EHT_USER_FIELD_ID 0x000007ff
+ __le32 user_id;
+};
+
+struct iwl_eht_tb_sigs {
+ /* same as non-TB above */
+ __le32 usig_a1, usig_a2_eht;
+ /* same as HE TB above */
+ __le32 tb_rx0, tb_rx1;
+};
+
+struct iwl_uhr_sigs {
+ __le32 usig_a1, usig_a1_uhr, usig_a2_uhr, b1, b2;
+ __le32 sig2;
+ __le32 cmn[6];
+ __le32 user_id;
+};
+
+struct iwl_uhr_tb_sigs {
+ __le32 usig_a1, usig_a2_uhr, tb_rx0, tb_rx1;
+};
+
+struct iwl_uhr_elr_sigs {
+ __le32 usig_a1, usig_a2_uhr;
+ __le32 uhr_sig_elr1, uhr_sig_elr2;
+};
+
+union iwl_sigs {
+ struct iwl_ht_sigs ht;
+ struct iwl_vht_sigs vht;
+ struct iwl_he_sigs he;
+ struct iwl_he_tb_sigs he_tb;
+ struct iwl_eht_sigs eht;
+ struct iwl_eht_tb_sigs eht_tb;
+ struct iwl_uhr_sigs uhr;
+ struct iwl_uhr_tb_sigs uhr_tb;
+ struct iwl_uhr_elr_sigs uhr_elr;
+};
+
+enum iwl_sniffer_status {
+ IWL_SNIF_STAT_PLCP_RX_OK = 0,
+ IWL_SNIF_STAT_AID_NOT_FOR_US = 1,
+ IWL_SNIF_STAT_PLCP_RX_LSIG_ERR = 2,
+ IWL_SNIF_STAT_PLCP_RX_SIGA_ERR = 3,
+ IWL_SNIF_STAT_PLCP_RX_SIGB_ERR = 4,
+ IWL_SNIF_STAT_UNEXPECTED_TB = 5,
+ IWL_SNIF_STAT_UNSUPPORTED_RATE = 6,
+ IWL_SNIF_STAT_UNKNOWN_ERROR = 7,
+}; /* AIR_SNIFFER_STATUS_E_VER_1 */
+
+enum iwl_sniffer_flags {
+ IWL_SNIF_FLAG_VALID_TB_RX = BIT(0),
+ IWL_SNIF_FLAG_VALID_RU = BIT(1),
+}; /* AIR_SNIFFER_FLAGS_E_VER_1 */
+
+/**
+ * struct iwl_rx_phy_air_sniffer_ntfy - air sniffer notification
+ *
+ * @status: &enum iwl_sniffer_status
+ * @flags: &enum iwl_sniffer_flags
+ * @reserved1: reserved
+ * @rssi_a: energy chain-A in negative dBm, measured at FINA time
+ * @rssi_b: energy chain-B in negative dBm, measured at FINA time
+ * @channel: channel number
+ * @band: band information, PHY_BAND_*
+ * @on_air_rise_time: GP2 at on air rise
+ * @frame_time: frame time in us
+ * @rate: RATE_MCS_*
+ * @bytecount: byte count for legay and HT, otherwise number of symbols
+ * @legacy_sig: CCK signal information if %RATE_MCS_MOD_TYPE_MSK in @rate is
+ * %RATE_MCS_MOD_TYPE_CCK, otherwise OFDM signal information
+ * @sigs: PHY signal information, depending on %RATE_MCS_MOD_TYPE_MSK in @rate
+ * @reserved2: reserved
+ *
+ * Sent for every frame and before the normal RX command if data is included.
+ */
+struct iwl_rx_phy_air_sniffer_ntfy {
+ u8 status;
+ u8 flags;
+ u8 reserved1[2];
+ u8 rssi_a, rssi_b;
+ u8 channel, band;
+ __le32 on_air_rise_time;
+ __le32 frame_time;
+ /* note: MCS in rate is not valid for MU-VHT */
+ __le32 rate;
+ __le32 bytecount;
+ union iwl_legacy_sig legacy_sig;
+ union iwl_sigs sigs;
+ __le32 reserved2;
+}; /* RX_PHY_AIR_SNIFFER_NTFY_API_S_VER_1 */
+
#endif /* __iwl_fw_api_rx_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
index f486d624500b..60f0a4924ddf 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -129,7 +129,7 @@ struct iwl_scan_offload_profile {
} __packed;
/**
- * struct iwl_scan_offload_profile_cfg_data
+ * struct iwl_scan_offload_profile_cfg_data - scan offload profile configs
* @blocklist_len: length of blocklist
* @num_profiles: num of profiles in the list
* @match_notify: clients waiting for match found notification
@@ -159,7 +159,7 @@ struct iwl_scan_offload_profile_cfg_v1 {
} __packed; /* SCAN_OFFLOAD_PROFILES_CFG_API_S_VER_1-2*/
/**
- * struct iwl_scan_offload_profile_cfg
+ * struct iwl_scan_offload_profile_cfg - scan offload profile config
* @profiles: profiles to search for match
* @data: the rest of the data for profile_cfg
*/
@@ -507,7 +507,7 @@ enum iwl_uhb_chan_cfg_flags {
IWL_UHB_CHAN_CFG_FLAG_FORCE_PASSIVE = BIT(26),
};
/**
- * struct iwl_scan_dwell
+ * struct iwl_scan_dwell - scan dwell configuration
* @active: default dwell time for active scan
* @passive: default dwell time for passive scan
* @fragmented: default dwell time for fragmented scan
@@ -728,7 +728,7 @@ enum iwl_umac_scan_general_params_flags2 {
};
/**
- * struct iwl_scan_channel_cfg_umac
+ * struct iwl_scan_channel_cfg_umac - scan channel config
* @flags: bitmap - 0-19: directed scan to i'th ssid.
* @channel_num: channel number 1-13 etc.
* @v1: command version 1
@@ -774,7 +774,7 @@ struct iwl_scan_channel_cfg_umac {
} __packed;
/**
- * struct iwl_scan_umac_schedule
+ * struct iwl_scan_umac_schedule - scan schedule parameters
* @interval: interval in seconds between scan iterations
* @iter_count: num of scan iterations for schedule plan, 0xff for infinite loop
* @reserved: for alignment and future use
@@ -815,7 +815,7 @@ struct iwl_scan_req_umac_tail_v2 {
} __packed;
/**
- * struct iwl_scan_umac_chan_param
+ * struct iwl_scan_umac_chan_param - scan channel parameters
* @flags: channel flags &enum iwl_scan_channel_flags
* @count: num of channels in scan request
* @reserved: for future use and alignment
@@ -827,33 +827,37 @@ struct iwl_scan_umac_chan_param {
} __packed; /*SCAN_CHANNEL_PARAMS_API_S_VER_1 */
/**
- * struct iwl_scan_req_umac
+ * struct iwl_scan_req_umac - scan request command
* @flags: &enum iwl_umac_scan_flags
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
* @ooc_priority: out of channel priority - &enum iwl_scan_priority
* @general_flags: &enum iwl_umac_scan_general_flags
+ * @reserved: reserved
* @scan_start_mac_id: report the scan start TSF time according to this mac TSF
- * @extended_dwell: dwell time for channels 1, 6 and 11
- * @active_dwell: dwell time for active scan per LMAC
- * @passive_dwell: dwell time for passive scan per LMAC
- * @fragmented_dwell: dwell time for fragmented passive scan
- * @adwell_default_n_aps: for adaptive dwell the default number of APs
+ * @v1: version 1 command data
+ * @v6: version 6 command data
+ * @v7: version 7 command data
+ * @v8: version 8 command data
+ * @v9: version 9 command data
+ * @v1.extended_dwell: dwell time for channels 1, 6 and 11
+ * @v1.active_dwell: dwell time for active scan per LMAC
+ * @v1.passive_dwell: dwell time for passive scan per LMAC
+ * @v1.fragmented_dwell: dwell time for fragmented passive scan
+ * @v7.adwell_default_n_aps: for adaptive dwell the default number of APs
* per channel
- * @adwell_default_n_aps_social: for adaptive dwell the default
+ * @v7.adwell_default_n_aps_social: for adaptive dwell the default
* number of APs per social (1,6,11) channel
- * @general_flags2: &enum iwl_umac_scan_general_flags2
- * @adwell_max_budget: for adaptive dwell the maximal budget of TU to be added
- * to total scan time
- * @max_out_time: max out of serving channel time, per LMAC - for CDB there
- * are 2 LMACs
- * @suspend_time: max suspend time, per LMAC - for CDB there are 2 LMACs
- * @scan_priority: scan internal prioritization &enum iwl_scan_priority
- * @num_of_fragments: Number of fragments needed for full coverage per band.
+ * @v8.general_flags2: &enum iwl_umac_scan_general_flags2
+ * @v7.adwell_max_budget: for adaptive dwell the maximal budget of TU to be
+ * added to total scan time
+ * @v1.max_out_time: max out of serving channel time, per LMAC - for CDB
+ * there are 2 LMACs
+ * @v1.suspend_time: max suspend time, per LMAC - for CDB there are 2 LMACs
+ * @v1.scan_priority: scan internal prioritization &enum iwl_scan_priority
+ * @v8.num_of_fragments: Number of fragments needed for full coverage per band.
* Relevant only for fragmented scan.
- * @channel: &struct iwl_scan_umac_chan_param
- * @reserved: for future use and alignment
- * @reserved3: for future use and alignment
- * @data: &struct iwl_scan_channel_cfg_umac and
+ * @v1.channel: &struct iwl_scan_umac_chan_param
+ * @v1.data: &struct iwl_scan_channel_cfg_umac and
* &struct iwl_scan_req_umac_tail
*/
struct iwl_scan_req_umac {
@@ -939,7 +943,7 @@ struct iwl_scan_req_umac {
#define IWL_SCAN_REQ_UMAC_SIZE_V1 36
/**
- * struct iwl_scan_probe_params_v3
+ * struct iwl_scan_probe_params_v3 - scan probe parameters
* @preq: scan probe request params
* @ssid_num: number of valid SSIDs in direct scan array
* @short_ssid_num: number of valid short SSIDs in short ssid array
@@ -961,7 +965,7 @@ struct iwl_scan_probe_params_v3 {
} __packed; /* SCAN_PROBE_PARAMS_API_S_VER_3 */
/**
- * struct iwl_scan_probe_params_v4
+ * struct iwl_scan_probe_params_v4 - scan probe parameters
* @preq: scan probe request params
* @short_ssid_num: number of valid short SSIDs in short ssid array
* @bssid_num: number of valid bssid in bssids array
@@ -983,7 +987,7 @@ struct iwl_scan_probe_params_v4 {
#define SCAN_MAX_NUM_CHANS_V3 67
/**
- * struct iwl_scan_channel_params_v4
+ * struct iwl_scan_channel_params_v4 - channel params
* @flags: channel flags &enum iwl_scan_channel_flags
* @count: num of channels in scan request
* @num_of_aps_override: override the number of APs the FW uses to calculate
@@ -1006,7 +1010,7 @@ struct iwl_scan_channel_params_v4 {
SCAN_CHANNEL_PARAMS_API_S_VER_5 */
/**
- * struct iwl_scan_channel_params_v7
+ * struct iwl_scan_channel_params_v7 - channel params
* @flags: channel flags &enum iwl_scan_channel_flags
* @count: num of channels in scan request
* @n_aps_override: override the number of APs the FW uses to calculate dwell
@@ -1024,7 +1028,7 @@ struct iwl_scan_channel_params_v7 {
} __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_6 */
/**
- * struct iwl_scan_general_params_v11
+ * struct iwl_scan_general_params_v11 - channel params
* @flags: &enum iwl_umac_scan_general_flags_v2
* @reserved: reserved for future
* @scan_start_mac_or_link_id: report the scan start TSF time according to this
@@ -1066,7 +1070,7 @@ struct iwl_scan_general_params_v11 {
} __packed; /* SCAN_GENERAL_PARAMS_API_S_VER_12, *_VER_11 and *_VER_10 */
/**
- * struct iwl_scan_periodic_parms_v1
+ * struct iwl_scan_periodic_parms_v1 - periodicity parameters
* @schedule: can scheduling parameter
* @delay: initial delay of the periodic scan in seconds
* @reserved: reserved for future
@@ -1078,7 +1082,7 @@ struct iwl_scan_periodic_parms_v1 {
} __packed; /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */
/**
- * struct iwl_scan_req_params_v12
+ * struct iwl_scan_req_params_v12 - scan request parameters (v12)
* @general_params: &struct iwl_scan_general_params_v11
* @channel_params: &struct iwl_scan_channel_params_v4
* @periodic_params: &struct iwl_scan_periodic_parms_v1
@@ -1106,7 +1110,7 @@ struct iwl_scan_req_params_v17 {
} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_17 - 14 */
/**
- * struct iwl_scan_req_umac_v12
+ * struct iwl_scan_req_umac_v12 - scan request command (v12)
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
* @ooc_priority: out of channel priority - &enum iwl_scan_priority
* @scan_params: scan parameters
@@ -1130,7 +1134,7 @@ struct iwl_scan_req_umac_v17 {
} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_17 - 14 */
/**
- * struct iwl_umac_scan_abort
+ * struct iwl_umac_scan_abort - scan abort command
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
* @flags: reserved
*/
@@ -1140,7 +1144,7 @@ struct iwl_umac_scan_abort {
} __packed; /* SCAN_ABORT_CMD_UMAC_API_S_VER_1 */
/**
- * enum iwl_umac_scan_abort_status
+ * enum iwl_umac_scan_abort_status - scan abort status
*
* @IWL_UMAC_SCAN_ABORT_STATUS_SUCCESS: scan was successfully aborted
* @IWL_UMAC_SCAN_ABORT_STATUS_IN_PROGRESS: scan abort is in progress
@@ -1153,7 +1157,7 @@ enum iwl_umac_scan_abort_status {
};
/**
- * struct iwl_umac_scan_complete
+ * struct iwl_umac_scan_complete - scan complete notification
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
* @last_schedule: last scheduling line
* @last_iter: last scan iteration number
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/sta.h b/drivers/net/wireless/intel/iwlwifi/fw/api/sta.h
index ecbcd5084cd8..e6f9abdfa546 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/sta.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2021, 2023 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2021, 2023, 2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -428,7 +428,7 @@ struct iwl_mvm_rm_sta_cmd {
} __packed; /* REMOVE_STA_CMD_API_S_VER_2 */
/**
- * struct iwl_mvm_mgmt_mcast_key_cmd_v1
+ * struct iwl_mvm_mgmt_mcast_key_cmd_v1 - IGTK command
* ( MGMT_MCAST_KEY = 0x1f )
* @ctrl_flags: &enum iwl_sta_key_flag
* @igtk: IGTK key material
@@ -449,7 +449,7 @@ struct iwl_mvm_mgmt_mcast_key_cmd_v1 {
} __packed; /* SEC_MGMT_MULTICAST_KEY_CMD_API_S_VER_1 */
/**
- * struct iwl_mvm_mgmt_mcast_key_cmd
+ * struct iwl_mvm_mgmt_mcast_key_cmd - IGTK command
* ( MGMT_MCAST_KEY = 0x1f )
* @ctrl_flags: &enum iwl_sta_key_flag
* @igtk: IGTK master key
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/stats.h b/drivers/net/wireless/intel/iwlwifi/fw/api/stats.h
index 0a9f14fb04be..8d9a5058d5a5 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/stats.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/stats.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018, 2020 - 2021, 2023 - 2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018, 2020-2021, 2023-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -26,7 +26,7 @@ struct mvm_statistics_div {
} __packed; /* STATISTICS_SLOW_DIV_API_S_VER_2 */
/**
- * struct mvm_statistics_rx_non_phy
+ * struct mvm_statistics_rx_non_phy - non-PHY RX statistics
* @bogus_cts: CTS received when not expecting CTS
* @bogus_ack: ACK received when not expecting ACK
* @non_channel_beacons: beacons with our bss id but not on our serving channel
@@ -456,7 +456,7 @@ struct iwl_system_statistics_cmd {
} __packed; /* STATISTICS_FW_CMD_API_S_VER_1 */
/**
- * enum iwl_fw_statistics_type
+ * enum iwl_fw_statistics_type - statistics type
*
* @FW_STATISTICS_OPERATIONAL: operational statistics
* @FW_STATISTICS_PHY: phy statistics
@@ -478,7 +478,7 @@ enum iwl_fw_statistics_type {
#define IWL_STATISTICS_TYPE_MSK 0x7f
/**
- * struct iwl_statistics_ntfy_hdr
+ * struct iwl_statistics_ntfy_hdr - statistics notification header
*
* @type: struct type
* @version: version of the struct
@@ -491,7 +491,7 @@ struct iwl_statistics_ntfy_hdr {
}; /* STATISTICS_NTFY_HDR_API_S_VER_1 */
/**
- * struct iwl_stats_ntfy_per_link
+ * struct iwl_stats_ntfy_per_link - per-link statistics
*
* @beacon_filter_average_energy: Average energy [-dBm] of the 2
* antennas.
@@ -514,7 +514,7 @@ struct iwl_stats_ntfy_per_link {
} __packed; /* STATISTICS_NTFY_PER_LINK_API_S_VER_1 */
/**
- * struct iwl_stats_ntfy_part1_per_link
+ * struct iwl_stats_ntfy_part1_per_link - part1 per link statistics
*
* @rx_time: rx time
* @tx_time: tx time
@@ -533,7 +533,7 @@ struct iwl_stats_ntfy_part1_per_link {
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_PART1_PER_LINK_API_S_VER_1 */
/**
- * struct iwl_stats_ntfy_per_mac
+ * struct iwl_stats_ntfy_per_mac - per MAC statistics
*
* @beacon_filter_average_energy: Average energy [-dBm] of the 2
* antennas.
@@ -556,7 +556,8 @@ struct iwl_stats_ntfy_per_mac {
} __packed; /* STATISTICS_NTFY_PER_MAC_API_S_VER_1 */
#define IWL_STATS_MAX_BW_INDEX 5
-/** struct iwl_stats_ntfy_per_phy
+/**
+ * struct iwl_stats_ntfy_per_phy - per PHY statistics
* @channel_load: channel load
* @channel_load_by_us: device contribution to MCLM
* @channel_load_not_by_us: other devices' contribution to MCLM
@@ -584,8 +585,11 @@ struct iwl_stats_ntfy_per_phy {
__le32 last_tx_ch_width_indx;
} __packed; /* STATISTICS_NTFY_PER_PHY_API_S_VER_1 */
+/* unknown channel load (due to not being active on channel) */
+#define IWL_STATS_UNKNOWN_CHANNEL_LOAD 0xffffffff
+
/**
- * struct iwl_stats_ntfy_per_sta
+ * struct iwl_stats_ntfy_per_sta - per STA statistics
*
* @average_energy: in fact it is minus the energy..
*/
@@ -597,7 +601,7 @@ struct iwl_stats_ntfy_per_sta {
#define IWL_STATS_MAX_FW_LINKS (IWL_FW_MAX_LINK_ID + 1)
/**
- * struct iwl_system_statistics_notif_oper
+ * struct iwl_system_statistics_notif_oper - statistics notification
*
* @time_stamp: time when the notification is sent from firmware
* @per_link: per link statistics, &struct iwl_stats_ntfy_per_link
@@ -612,7 +616,7 @@ struct iwl_system_statistics_notif_oper {
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_3 */
/**
- * struct iwl_system_statistics_part1_notif_oper
+ * struct iwl_system_statistics_part1_notif_oper - part1 stats notification
*
* @time_stamp: time when the notification is sent from firmware
* @per_link: per link statistics &struct iwl_stats_ntfy_part1_per_link
@@ -625,7 +629,7 @@ struct iwl_system_statistics_part1_notif_oper {
} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_PART1_API_S_VER_4 */
/**
- * struct iwl_system_statistics_end_notif
+ * struct iwl_system_statistics_end_notif - statistics end notification
*
* @time_stamp: time when the notification is sent from firmware
*/
@@ -634,7 +638,7 @@ struct iwl_system_statistics_end_notif {
} __packed; /* STATISTICS_FW_NTFY_END_API_S_VER_1 */
/**
- * struct iwl_statistics_operational_ntfy
+ * struct iwl_statistics_operational_ntfy - operational stats notification
*
* @hdr: general statistics header
* @flags: bitmap of possible notification structures
@@ -659,7 +663,7 @@ struct iwl_statistics_operational_ntfy {
} __packed; /* STATISTICS_OPERATIONAL_NTFY_API_S_VER_15 */
/**
- * struct iwl_statistics_operational_ntfy_ver_14
+ * struct iwl_statistics_operational_ntfy_ver_14 - operational stats notification
*
* @hdr: general statistics header
* @flags: bitmap of possible notification structures
@@ -704,7 +708,7 @@ struct iwl_statistics_operational_ntfy_ver_14 {
} __packed; /* STATISTICS_OPERATIONAL_NTFY_API_S_VER_14 */
/**
- * struct iwl_statistics_phy_ntfy
+ * struct iwl_statistics_phy_ntfy - PHY statistics notification
*
* @hdr: general statistics header
* RX PHY related statistics
@@ -805,7 +809,7 @@ struct iwl_statistics_phy_ntfy {
} __packed; /* STATISTICS_PHY_NTFY_API_S_VER_1 */
/**
- * struct iwl_statistics_mac_ntfy
+ * struct iwl_statistics_mac_ntfy - MAC statistics notification
*
* @hdr: general statistics header
* @bcast_filter_passed_per_mac: bcast filter passed per mac
@@ -824,7 +828,7 @@ struct iwl_statistics_mac_ntfy {
} __packed; /* STATISTICS_MAC_NTFY_API_S_VER_1 */
/**
- * struct iwl_statistics_rx_ntfy
+ * struct iwl_statistics_rx_ntfy - RX statistics notification
*
* @hdr: general statistics header
* @rx_agg_mpdu_cnt: aggregation frame count (number of
@@ -864,7 +868,7 @@ struct iwl_statistics_rx_ntfy {
} __packed; /* STATISTICS_RX_NTFY_API_S_VER_1 */
/**
- * struct iwl_statistics_tx_ntfy
+ * struct iwl_statistics_tx_ntfy - TX statistics notification
*
* @hdr: general statistics header
* @cts_timeout: timeout when waiting for CTS
@@ -973,7 +977,7 @@ struct iwl_statistics_tx_ntfy {
} __packed; /* STATISTICS_TX_NTFY_API_S_VER_1 */
/**
- * struct iwl_statistics_duration_ntfy
+ * struct iwl_statistics_duration_ntfy - burst/duration statistics
*
* @hdr: general statistics header
* @cont_burst_chk_cnt: number of times continuation or
@@ -992,7 +996,7 @@ struct iwl_statistics_duration_ntfy {
} __packed; /* STATISTICS_DURATION_NTFY_API_S_VER_1 */
/**
- * struct iwl_statistics_he_ntfy
+ * struct iwl_statistics_he_ntfy - HE statistics
*
* @hdr: general statistics header
* received HE frames
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h
index cfa6532a3cdd..08edd1d99992 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018, 2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018, 2024-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -50,7 +50,7 @@ struct iwl_tdls_channel_switch_timing {
*/
struct iwl_tdls_channel_switch_frame {
__le32 switch_time_offset;
- struct iwl_tx_cmd tx_cmd;
+ struct iwl_tx_cmd_v6_params tx_cmd;
u8 data[IWL_TDLS_CH_SW_FRAME_MAX_SIZE];
} __packed; /* TDLS_STA_CHANNEL_SWITCH_FRAME_API_S_VER_1 */
@@ -131,7 +131,7 @@ struct iwl_tdls_config_cmd {
struct iwl_tdls_sta_info sta_info[IWL_TDLS_STA_COUNT];
__le32 pti_req_data_offset;
- struct iwl_tx_cmd pti_req_tx_cmd;
+ struct iwl_tx_cmd_v6_params pti_req_tx_cmd;
u8 pti_req_template[];
} __packed; /* TDLS_CONFIG_CMD_API_S_VER_1 */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h
index f586379d66dd..46d35ef4751e 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h
@@ -452,7 +452,7 @@ struct iwl_roc_notif {
* listen mode. Will be fragmented. Valid only on the P2P Device MAC.
* Valid only on the P2P Device MAC. The firmware will take into account
* the duration, the interval and the repetition count.
- * @SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION: Schedule the P2P Device to be be
+ * @SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION: Schedule the P2P Device to be
* able to run the GO Negotiation. Will not be fragmented and not
* repetitive. Valid only on the P2P Device MAC. Only the duration will
* be taken into account.
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
index 0a39e4b6eb62..31d3336726b4 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_tx_h__
@@ -151,7 +151,7 @@ enum iwl_tx_cmd_sec_ctrl {
#define IWL_LOW_RETRY_LIMIT 7
/**
- * enum iwl_tx_offload_assist_flags_pos - set %iwl_tx_cmd offload_assist values
+ * enum iwl_tx_offload_assist_flags_pos - set %iwl_tx_cmd_v6 offload_assist values
* @TX_CMD_OFFLD_IP_HDR: offset to start of IP header (in words)
* from mac header end. For normal case it is 4 words for SNAP.
* note: tx_cmd, mac header and pad are not counted in the offset.
@@ -181,8 +181,8 @@ enum iwl_tx_offload_assist_flags_pos {
/* TODO: complete documentation for try_cnt and btkill_cnt */
/**
- * struct iwl_tx_cmd - TX command struct to FW
- * ( TX_CMD = 0x1c )
+ * struct iwl_tx_cmd_v6_params - parameters of the TX
+ *
* @len: in bytes of the payload, see below for details
* @offload_assist: TX offload configuration
* @tx_flags: combination of TX_CMD_FLG_*, see &enum iwl_tx_flags
@@ -205,8 +205,6 @@ enum iwl_tx_offload_assist_flags_pos {
* @tid_tspec: TID/tspec
* @pm_frame_timeout: PM TX frame timeout
* @reserved4: reserved
- * @payload: payload (same as @hdr)
- * @hdr: 802.11 header (same as @payload)
*
* The byte count (both len and next_frame_len) includes MAC header
* (24/26/30/32 bytes)
@@ -217,11 +215,8 @@ enum iwl_tx_offload_assist_flags_pos {
* It does not include post-MAC padding, i.e.,
* MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.
* Range of len: 14-2342 bytes.
- *
- * After the struct fields the MAC header is placed, plus any padding,
- * and then the actial payload.
*/
-struct iwl_tx_cmd {
+struct iwl_tx_cmd_v6_params {
__le16 len;
__le16 offload_assist;
__le32 tx_flags;
@@ -245,10 +240,20 @@ struct iwl_tx_cmd {
u8 tid_tspec;
__le16 pm_frame_timeout;
__le16 reserved4;
- union {
- DECLARE_FLEX_ARRAY(u8, payload);
- DECLARE_FLEX_ARRAY(struct ieee80211_hdr, hdr);
- };
+} __packed; /* TX_CMD_API_S_VER_6 */
+
+/**
+ * struct iwl_tx_cmd_v6 - TX command struct to FW
+ * ( TX_CMD = 0x1c )
+ * @params: parameters of the TX, see &struct iwl_tx_cmd_v6_tx_params
+ * @hdr: 802.11 header
+ *
+ * After &params, the MAC header is placed, plus any padding,
+ * and then the actual payload.
+ */
+struct iwl_tx_cmd_v6 {
+ struct iwl_tx_cmd_v6_params params;
+ struct ieee80211_hdr hdr[];
} __packed; /* TX_CMD_API_S_VER_6 */
struct iwl_dram_sec_info {
@@ -258,7 +263,7 @@ struct iwl_dram_sec_info {
} __packed; /* DRAM_SEC_INFO_API_S_VER_1 */
/**
- * struct iwl_tx_cmd_gen2 - TX command struct to FW for 22000 devices
+ * struct iwl_tx_cmd_v9 - TX command struct to FW for 22000 devices
* ( TX_CMD = 0x1c )
* @len: in bytes of the payload, see below for details
* @offload_assist: TX offload configuration
@@ -268,7 +273,7 @@ struct iwl_dram_sec_info {
* cleared. Combination of RATE_MCS_*
* @hdr: 802.11 header
*/
-struct iwl_tx_cmd_gen2 {
+struct iwl_tx_cmd_v9 {
__le16 len;
__le16 offload_assist;
__le32 flags;
@@ -279,18 +284,18 @@ struct iwl_tx_cmd_gen2 {
TX_CMD_API_S_VER_9 */
/**
- * struct iwl_tx_cmd_gen3 - TX command struct to FW for AX210+ devices
+ * struct iwl_tx_cmd - TX command struct to FW for AX210+ devices
* ( TX_CMD = 0x1c )
* @len: in bytes of the payload, see below for details
* @flags: combination of &enum iwl_tx_cmd_flags
* @offload_assist: TX offload configuration
* @dram_info: FW internal DRAM storage
* @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
- * cleared. Combination of RATE_MCS_*
+ * cleared. Combination of RATE_MCS_*; format depends on version
* @reserved: reserved
* @hdr: 802.11 header
*/
-struct iwl_tx_cmd_gen3 {
+struct iwl_tx_cmd {
__le16 len;
__le16 flags;
__le32 offload_assist;
@@ -298,7 +303,9 @@ struct iwl_tx_cmd_gen3 {
__le32 rate_n_flags;
u8 reserved[8];
struct ieee80211_hdr hdr[];
-} __packed; /* TX_CMD_API_S_VER_8, TX_CMD_API_S_VER_10 */
+} __packed; /* TX_CMD_API_S_VER_10,
+ * TX_CMD_API_S_VER_11
+ */
/*
* TX response related data
@@ -549,7 +556,7 @@ struct iwl_tx_resp_v3 {
* @failure_rts: num of failures due to unsuccessful RTS
* @failure_frame: num failures due to no ACK (unused for agg)
* @initial_rate: for non-agg: rate of the successful Tx. For agg: rate of the
- * Tx of all the batch. RATE_MCS_*
+ * Tx of all the batch. RATE_MCS_*; format depends on command version
* @wireless_media_time: for non-agg: RTS + CTS + frame tx attempts time + ACK.
* for agg: RTS + CTS + aggregation tx time + block-ack time.
* in usec.
@@ -600,8 +607,10 @@ struct iwl_tx_resp {
__le16 reserved2;
struct agg_tx_status status;
} __packed; /* TX_RSP_API_S_VER_6,
- TX_RSP_API_S_VER_7,
- TX_RSP_API_S_VER_8 */
+ * TX_RSP_API_S_VER_7,
+ * TX_RSP_API_S_VER_8,
+ * TX_RSP_API_S_VER_9
+ */
/**
* struct iwl_mvm_ba_notif - notifies about reception of BA
@@ -701,7 +710,8 @@ enum iwl_mvm_ba_resp_flags {
* @rts_retry_cnt: RTS retry count
* @reserved: reserved (for alignment)
* @wireless_time: Wireless-media time
- * @tx_rate: the rate the aggregation was sent at
+ * @tx_rate: the rate the aggregation was sent at. Format depends on command
+ * version.
* @tfd_cnt: number of TFD-Q elements
* @ra_tid_cnt: number of RATID-Q elements
* @tfd: array of TFD queue status updates. See &iwl_compressed_ba_tfd
@@ -730,7 +740,8 @@ struct iwl_compressed_ba_notif {
DECLARE_FLEX_ARRAY(struct iwl_compressed_ba_tfd, tfd);
};
} __packed; /* COMPRESSED_BA_RES_API_S_VER_4,
- COMPRESSED_BA_RES_API_S_VER_5 */
+ COMPRESSED_BA_RES_API_S_VER_6,
+ COMPRESSED_BA_RES_API_S_VER_7 */
/**
* struct iwl_mac_beacon_cmd_v6 - beacon template command
@@ -742,7 +753,7 @@ struct iwl_compressed_ba_notif {
* @frame: the template of the beacon frame
*/
struct iwl_mac_beacon_cmd_v6 {
- struct iwl_tx_cmd tx;
+ struct iwl_tx_cmd_v6_params tx;
__le32 template_id;
__le32 tim_idx;
__le32 tim_size;
@@ -761,7 +772,7 @@ struct iwl_mac_beacon_cmd_v6 {
* @frame: the template of the beacon frame
*/
struct iwl_mac_beacon_cmd_v7 {
- struct iwl_tx_cmd tx;
+ struct iwl_tx_cmd_v6_params tx;
__le32 template_id;
__le32 tim_idx;
__le32 tim_size;
@@ -858,7 +869,7 @@ struct iwl_extended_beacon_notif {
/**
* enum iwl_dump_control - dump (flush) control flags
- * @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty
+ * @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the FIFO is empty
* and the TFD queues are empty.
*/
enum iwl_dump_control {
@@ -952,7 +963,7 @@ struct iwl_scd_txq_cfg_cmd {
} __packed; /* SCD_QUEUE_CFG_CMD_API_S_VER_1 */
/**
- * struct iwl_scd_txq_cfg_rsp
+ * struct iwl_scd_txq_cfg_rsp - scheduler TXQ configuration response
* @token: taken from the command
* @sta_id: station id from the command
* @tid: tid from the command
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 03f639fbf9b6..2ce55859641c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -187,7 +187,7 @@ static void iwl_fw_dump_rxf(struct iwl_fw_runtime *fwrt,
/* Pull RXF2 */
iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size,
RXF_DIFF_FROM_PREV +
- fwrt->trans->trans_cfg->umac_prph_offset, 1);
+ 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,
@@ -654,10 +654,10 @@ static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr,
{
u32 range_len;
- if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ 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->trans_cfg->device_family >=
+ } 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);
@@ -665,7 +665,7 @@ static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr,
range_len = ARRAY_SIZE(iwl_prph_dump_addr_comm);
handler(fwrt, iwl_prph_dump_addr_comm, range_len, ptr);
- if (fwrt->trans->trans_cfg->mq_rx_supported) {
+ 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);
}
@@ -809,13 +809,14 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
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->cfg->smem_len;
+ 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) {
+ 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)
@@ -829,7 +830,7 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
}
/* reading RXF/TXF sizes */
- if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) {
+ 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);
@@ -838,7 +839,7 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
iwl_fw_prph_handler(fwrt, &prph_len,
iwl_fw_get_prph_len);
- if (fwrt->trans->trans_cfg->device_family ==
+ 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;
@@ -876,7 +877,7 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
if (iwl_fw_dbg_is_d3_debug_enabled(fwrt) && fwrt->dump.d3_debug_data) {
file_len += sizeof(*dump_data) +
- fwrt->trans->cfg->d3_debug_data_length * 2;
+ fwrt->trans->mac_cfg->base->d3_debug_data_length * 2;
}
/* If we only want a monitor dump, reset the file length */
@@ -904,13 +905,14 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
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->hw_rev));
+ cpu_to_le32(CSR_HW_REV_TYPE(fwrt->trans->info.hw_rev));
dump_info->hw_step =
- cpu_to_le32(fwrt->trans->hw_rev_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->name,
- sizeof(dump_info->dev_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;
@@ -996,7 +998,7 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
}
iwl_fw_dump_mem(fwrt, &dump_data, smem_len,
- fwrt->trans->cfg->smem_offset,
+ fwrt->trans->mac_cfg->base->smem_offset,
IWL_FW_ERROR_DUMP_MEM_SMEM);
iwl_fw_dump_mem(fwrt, &dump_data, sram2_len,
@@ -1005,8 +1007,8 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
}
if (iwl_fw_dbg_is_d3_debug_enabled(fwrt) && fwrt->dump.d3_debug_data) {
- u32 addr = fwrt->trans->cfg->d3_debug_data_base_addr;
- size_t data_size = fwrt->trans->cfg->d3_debug_data_length;
+ 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);
@@ -1104,12 +1106,13 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt,
u32 prph_val;
u32 dphy_state;
u32 dphy_addr;
+ u32 prph_stts;
int i;
range->internal_base_addr = cpu_to_le32(addr);
range->range_data_size = size;
- if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ if (fwrt->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
indirect_wr_addr = WMAL_INDRCT_CMD1;
indirect_wr_addr += le32_to_cpu(offset);
@@ -1131,6 +1134,21 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt,
iwl_write_prph_no_grab(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);
+
+ /* Abort dump if status is 0xA5A5A5A2 or FIFO1 empty */
+ if (prph_stts == WMAL_TIMEOUT_VAL ||
+ !WMAL_MRSPF_STTS_IS_FIFO1_NOT_EMPTY(prph_stts))
+ break;
+ }
+
prph_val = iwl_read_prph_no_grab(fwrt->trans,
indirect_rd_addr);
*val++ = cpu_to_le32(prph_val);
@@ -1266,7 +1284,7 @@ static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
/* all paged index start from 1 to skip CSS section */
idx++;
- if (!fwrt->trans->trans_cfg->gen2)
+ if (!fwrt->trans->mac_cfg->gen2)
return _iwl_dump_ini_paging_iter(fwrt, range_ptr, range_len, idx);
range = range_ptr;
@@ -1790,7 +1808,7 @@ iwl_dump_ini_mon_fill_header(struct iwl_fw_runtime *fwrt, u32 alloc_id,
data->write_ptr = iwl_get_mon_reg(fwrt, alloc_id,
&addrs->write_ptr);
- if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
u32 wrt_ptr = le32_to_cpu(data->write_ptr);
data->write_ptr = cpu_to_le32(wrt_ptr >> 2);
@@ -1817,7 +1835,7 @@ iwl_dump_ini_mon_dram_fill_header(struct iwl_fw_runtime *fwrt,
u32 alloc_id = le32_to_cpu(reg->dram_alloc_id);
return iwl_dump_ini_mon_fill_header(fwrt, alloc_id, mon_dump,
- &fwrt->trans->cfg->mon_dram_regs);
+ &fwrt->trans->mac_cfg->base->mon_dram_regs);
}
static void *
@@ -1830,7 +1848,7 @@ iwl_dump_ini_mon_smem_fill_header(struct iwl_fw_runtime *fwrt,
u32 alloc_id = le32_to_cpu(reg->internal_buffer.alloc_id);
return iwl_dump_ini_mon_fill_header(fwrt, alloc_id, mon_dump,
- &fwrt->trans->cfg->mon_smem_regs);
+ &fwrt->trans->mac_cfg->base->mon_smem_regs);
}
static void *
@@ -1844,7 +1862,7 @@ iwl_dump_ini_mon_dbgi_fill_header(struct iwl_fw_runtime *fwrt,
/* no offset calculation later */
IWL_FW_INI_ALLOCATION_ID_DBGC1,
mon_dump,
- &fwrt->trans->cfg->mon_dbgi_regs);
+ &fwrt->trans->mac_cfg->base->mon_dbgi_regs);
}
static void *
@@ -1909,7 +1927,7 @@ iwl_dump_ini_mem_block_ranges(struct iwl_fw_runtime *fwrt,
static u32 iwl_dump_ini_paging_ranges(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data)
{
- if (fwrt->trans->trans_cfg->gen2) {
+ if (fwrt->trans->mac_cfg->gen2) {
if (fwrt->trans->init_dram.paging_cnt)
return fwrt->trans->init_dram.paging_cnt - 1;
else
@@ -2021,7 +2039,7 @@ iwl_dump_ini_paging_get_size(struct iwl_fw_runtime *fwrt,
/* start from 1 to skip CSS section */
for (i = 1; i <= iwl_dump_ini_paging_ranges(fwrt, reg_data); i++) {
size += range_header_len;
- if (fwrt->trans->trans_cfg->gen2)
+ if (fwrt->trans->mac_cfg->gen2)
size += fwrt->trans->init_dram.paging[i].size;
else
size += fwrt->fw_paging_db[i].fw_paging_size;
@@ -2375,7 +2393,7 @@ static u32 iwl_dump_ini_info(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_dump_cfg_name *cfg_name;
u32 size = sizeof(*tlv) + sizeof(*dump);
u32 num_of_cfg_names = 0;
- u32 hw_type;
+ u32 hw_type, is_cdb;
list_for_each_entry(node, &fwrt->trans->dbg.debug_info_tlv_list, list) {
size += sizeof(*cfg_name);
@@ -2403,33 +2421,20 @@ static u32 iwl_dump_ini_info(struct iwl_fw_runtime *fwrt,
dump->ver_type = cpu_to_le32(fwrt->dump.fw_ver.type);
dump->ver_subtype = cpu_to_le32(fwrt->dump.fw_ver.subtype);
- dump->hw_step = cpu_to_le32(fwrt->trans->hw_rev_step);
+ dump->hw_step = cpu_to_le32(fwrt->trans->info.hw_rev_step);
- /*
- * Several HWs all have type == 0x42, so we'll override this value
- * according to the detected HW
- */
- hw_type = CSR_HW_REV_TYPE(fwrt->trans->hw_rev);
- if (hw_type == IWL_AX210_HW_TYPE) {
- u32 prph_val = iwl_read_umac_prph(fwrt->trans, WFPM_OTP_CFG1_ADDR);
- u32 is_jacket = !!(prph_val & WFPM_OTP_CFG1_IS_JACKET_BIT);
- u32 is_cdb = !!(prph_val & WFPM_OTP_CFG1_IS_CDB_BIT);
- u32 masked_bits = is_jacket | (is_cdb << 1);
+ hw_type = CSR_HW_REV_TYPE(fwrt->trans->info.hw_rev);
+
+ is_cdb = CSR_HW_RFID_IS_CDB(fwrt->trans->info.hw_rf_id);
+ hw_type |= IWL_CDB_MASK(is_cdb);
- /*
- * The HW type depends on certain bits in this case, so add
- * these bits to the HW type. We won't have collisions since we
- * add these bits after the highest possible bit in the mask.
- */
- hw_type |= masked_bits << IWL_AX210_HW_TYPE_ADDITION_SHIFT;
- }
dump->hw_type = cpu_to_le32(hw_type);
dump->rf_id_flavor =
- cpu_to_le32(CSR_HW_RFID_FLAVOR(fwrt->trans->hw_rf_id));
- dump->rf_id_dash = cpu_to_le32(CSR_HW_RFID_DASH(fwrt->trans->hw_rf_id));
- dump->rf_id_step = cpu_to_le32(CSR_HW_RFID_STEP(fwrt->trans->hw_rf_id));
- dump->rf_id_type = cpu_to_le32(CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id));
+ cpu_to_le32(CSR_HW_RFID_FLAVOR(fwrt->trans->info.hw_rf_id));
+ dump->rf_id_dash = cpu_to_le32(CSR_HW_RFID_DASH(fwrt->trans->info.hw_rf_id));
+ dump->rf_id_step = cpu_to_le32(CSR_HW_RFID_STEP(fwrt->trans->info.hw_rf_id));
+ dump->rf_id_type = cpu_to_le32(CSR_HW_RFID_TYPE(fwrt->trans->info.hw_rf_id));
dump->lmac_major = cpu_to_le32(fwrt->dump.fw_ver.lmac_major);
dump->lmac_minor = cpu_to_le32(fwrt->dump.fw_ver.lmac_minor);
@@ -2469,36 +2474,6 @@ static u32 iwl_dump_ini_info(struct iwl_fw_runtime *fwrt,
return entry->size;
}
-static u32 iwl_dump_ini_file_name_info(struct iwl_fw_runtime *fwrt,
- struct list_head *list)
-{
- struct iwl_fw_ini_dump_entry *entry;
- struct iwl_dump_file_name_info *tlv;
- u32 len = strnlen(fwrt->trans->dbg.dump_file_name_ext,
- IWL_FW_INI_MAX_NAME);
-
- if (!fwrt->trans->dbg.dump_file_name_ext_valid)
- return 0;
-
- entry = vzalloc(sizeof(*entry) + sizeof(*tlv) + len);
- if (!entry)
- return 0;
-
- entry->size = sizeof(*tlv) + len;
-
- tlv = (void *)entry->data;
- tlv->type = cpu_to_le32(IWL_INI_DUMP_NAME_TYPE);
- tlv->len = cpu_to_le32(len);
- memcpy(tlv->data, fwrt->trans->dbg.dump_file_name_ext, len);
-
- /* add the dump file name extension tlv to the list */
- list_add_tail(&entry->list, list);
-
- fwrt->trans->dbg.dump_file_name_ext_valid = false;
-
- return entry->size;
-}
-
static const struct iwl_dump_ini_mem_ops iwl_dump_ini_region_ops[] = {
[IWL_FW_INI_REGION_INVALID] = {},
[IWL_FW_INI_REGION_INTERNAL_BUFFER] = {
@@ -2624,6 +2599,12 @@ enum iwl_dump_ini_region_selector {
IWL_INI_DUMP_LATE_REGIONS,
};
+static bool iwl_dump_due_to_error(enum iwl_fw_ini_time_point tp_id)
+{
+ return tp_id == IWL_FW_INI_TIME_POINT_FW_ASSERT ||
+ 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,
@@ -2689,8 +2670,7 @@ iwl_dump_ini_dump_regions(struct iwl_fw_runtime *fwrt,
* debug data which also need to be collected.
*/
if (reg_type == IWL_FW_INI_REGION_DRAM_IMR) {
- if (tp_id == IWL_FW_INI_TIME_POINT_FW_ASSERT ||
- tp_id == IWL_FW_INI_TIME_POINT_FW_HW_ERROR)
+ if (iwl_dump_due_to_error(tp_id))
imr_reg_data->reg_tlv =
fwrt->trans->dbg.active_regions[i];
else
@@ -2726,8 +2706,8 @@ 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));
- if (trigger->time_point &
- cpu_to_le32(IWL_FW_INI_APPLY_POLICY_RESET_HANDSHAKE)) {
+ 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,
IWL_INI_DUMP_EARLY_REGIONS);
@@ -2736,6 +2716,10 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
regions_mask, &imr_reg_data,
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,
IWL_INI_DUMP_ALL_REGIONS);
@@ -2746,7 +2730,6 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
&iwl_dump_ini_region_ops[IWL_FW_INI_REGION_DRAM_IMR]);
if (size) {
- size += iwl_dump_ini_file_name_info(fwrt, list);
size += iwl_dump_ini_info(fwrt, trigger, list);
}
@@ -2960,7 +2943,7 @@ IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_desc);
int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt,
enum iwl_fw_dbg_trigger trig_type)
{
- if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status))
+ if (!iwl_trans_device_enabled(fwrt->trans))
return -EIO;
if (iwl_trans_dbg_ini_valid(fwrt->trans)) {
@@ -3006,6 +2989,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dump_desc *desc;
unsigned int delay = 0;
bool monitor_only = false;
+ int ret;
if (trigger) {
u16 occurrences = le16_to_cpu(trigger->occurrences) - 1;
@@ -3036,7 +3020,11 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
desc->trig_desc.type = cpu_to_le32(trig);
memcpy(desc->trig_desc.data, str, len);
- return iwl_fw_dbg_collect_desc(fwrt, desc, monitor_only, delay);
+ ret = iwl_fw_dbg_collect_desc(fwrt, desc, monitor_only, delay);
+ if (ret)
+ kfree(desc);
+
+ return ret;
}
IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect);
@@ -3044,7 +3032,7 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_trigger_tlv *trigger,
const char *fmt, ...)
{
- int ret, len = 0;
+ int len = 0;
char buf[64];
if (iwl_trans_dbg_ini_valid(fwrt->trans))
@@ -3066,13 +3054,8 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
len = strlen(buf) + 1;
}
- ret = iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len,
- trigger);
-
- if (ret)
- return ret;
-
- return 0;
+ return iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len,
+ trigger);
}
IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_trig);
@@ -3133,7 +3116,7 @@ static void iwl_send_dbg_dump_complete_cmd(struct iwl_fw_runtime *fwrt,
.len[0] = sizeof(hcmd_data),
};
- if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status))
+ if (iwl_trans_is_fw_error(fwrt->trans))
return;
if (fw_has_capa(&fwrt->fw->ucode_capa,
@@ -3162,13 +3145,13 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
goto out;
}
- if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status)) {
+ if (!iwl_trans_device_enabled(fwrt->trans)) {
IWL_ERR(fwrt, "Device is not enabled - cannot dump error\n");
goto out;
}
/* there's no point in fw dump if the bus is dead */
- if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) {
+ if (iwl_trans_is_dead(fwrt->trans)) {
IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n");
goto out;
}
@@ -3282,13 +3265,13 @@ void iwl_fw_error_dump_wk(struct work_struct *work)
void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt)
{
- const struct iwl_cfg *cfg = fwrt->trans->cfg;
+ const struct iwl_mac_cfg *mac_cfg = fwrt->trans->mac_cfg;
if (!iwl_fw_dbg_is_d3_debug_enabled(fwrt))
return;
if (!fwrt->dump.d3_debug_data) {
- fwrt->dump.d3_debug_data = kmalloc(cfg->d3_debug_data_length,
+ fwrt->dump.d3_debug_data = kmalloc(mac_cfg->base->d3_debug_data_length,
GFP_KERNEL);
if (!fwrt->dump.d3_debug_data) {
IWL_ERR(fwrt,
@@ -3298,15 +3281,15 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt)
}
/* if the buffer holds previous debug data it is overwritten */
- iwl_trans_read_mem_bytes(fwrt->trans, cfg->d3_debug_data_base_addr,
+ iwl_trans_read_mem_bytes(fwrt->trans, mac_cfg->base->d3_debug_data_base_addr,
fwrt->dump.d3_debug_data,
- cfg->d3_debug_data_length);
+ mac_cfg->base->d3_debug_data_length);
if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx,
- cfg->d3_debug_data_base_addr,
+ mac_cfg->base->d3_debug_data_base_addr,
fwrt->dump.d3_debug_data,
- cfg->d3_debug_data_length);
+ mac_cfg->base->d3_debug_data_length);
}
IWL_EXPORT_SYMBOL(iwl_fw_dbg_read_d3_debug_data);
@@ -3341,7 +3324,7 @@ static int iwl_fw_dbg_suspend_resume_hcmd(struct iwl_trans *trans, bool suspend)
static void iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
struct iwl_fw_dbg_params *params)
{
- if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
+ if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
return;
}
@@ -3365,7 +3348,7 @@ static int iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
if (!params)
return -EIO;
- if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
+ if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
@@ -3467,7 +3450,7 @@ void iwl_fw_disable_dbg_asserts(struct iwl_fw_runtime *fwrt)
GENMASK(31, IWL_FW_DBG_DOMAIN_POS + 1));
/* supported starting from 9000 devices */
- if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000)
+ if (fwrt->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_9000)
return;
if (fwrt->trans->dbg.yoyo_bin_loaded || (preset && preset != 1))
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
index 35e30e5db462..8034c9ecba69 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-2024 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2019, 2021-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -201,7 +201,7 @@ static inline bool iwl_fw_dbg_is_d3_debug_enabled(struct iwl_fw_runtime *fwrt)
{
return fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_D3_DEBUG) &&
- fwrt->trans->cfg->d3_debug_data_length && fwrt->ops &&
+ fwrt->trans->mac_cfg->base->d3_debug_data_length && fwrt->ops &&
fwrt->ops->d3_debug_enable &&
fwrt->ops->d3_debug_enable(fwrt->ops_ctx) &&
iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_D3_DEBUG_DATA);
@@ -210,7 +210,7 @@ static inline bool iwl_fw_dbg_is_d3_debug_enabled(struct iwl_fw_runtime *fwrt)
static inline bool iwl_fw_dbg_is_paging_enabled(struct iwl_fw_runtime *fwrt)
{
return iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_PAGING) &&
- !fwrt->trans->trans_cfg->gen2 &&
+ !fwrt->trans->mac_cfg->gen2 &&
fwrt->cur_fw_img < IWL_UCODE_TYPE_MAX &&
fwrt->fw->img[fwrt->cur_fw_img].paging_mem_size &&
fwrt->fw_paging_db[0].fw_paging_block;
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
index f0c813d675f4..3b0e8c43ba4a 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
@@ -198,7 +198,7 @@ void iwl_fw_trigger_timestamp(struct iwl_fw_runtime *fwrt, u32 delay)
iwl_fw_cancel_timestamp(fwrt);
- fwrt->timestamp.delay = msecs_to_jiffies(delay * 1000);
+ fwrt->timestamp.delay = secs_to_jiffies(delay);
schedule_delayed_work(&fwrt->timestamp.wk,
round_jiffies_relative(fwrt->timestamp.delay));
@@ -311,7 +311,7 @@ static ssize_t iwl_dbgfs_fw_ver_read(struct iwl_fw_runtime *fwrt,
pos += scnprintf(pos, endpos - pos, "FW: %s\n",
fwrt->fw->human_readable);
pos += scnprintf(pos, endpos - pos, "Device: %s\n",
- fwrt->trans->name);
+ fwrt->trans->info.name);
pos += scnprintf(pos, endpos - pos, "Bus: %s\n",
fwrt->dev->bus->name);
@@ -389,6 +389,12 @@ static int iwl_dbgfs_fw_info_seq_show(struct seq_file *seq, void *v)
" %d: %d\n",
IWL_UCODE_TLV_CAPA_CHINA_22_REG_SUPPORT,
has_capa);
+ has_capa = fw_has_capa(&fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE) ? 1 : 0;
+ seq_printf(seq,
+ " %d: %d\n",
+ IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE,
+ has_capa);
seq_puts(seq, "fw_api_ver:\n");
}
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c
index c7b261c8ec96..ddd714cff2f4 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -14,13 +14,6 @@
#include "iwl-csr.h"
#include "pnvm.h"
-#define FW_ASSERT_LMAC_FATAL 0x70
-#define FW_ASSERT_LMAC2_FATAL 0x72
-#define FW_ASSERT_UMAC_FATAL 0x71
-#define UMAC_RT_NMI_LMAC2_FATAL 0x72
-#define RT_NMI_INTERRUPT_OTHER_LMAC_FATAL 0x73
-#define FW_ASSERT_NMI_UNKNOWN 0x84
-
/*
* Note: This structure is read from the device with IO accesses,
* and the reading already does the endian conversion. As it is
@@ -103,17 +96,6 @@ struct iwl_umac_error_event_table {
#define ERROR_START_OFFSET (1 * sizeof(u32))
#define ERROR_ELEM_SIZE (7 * sizeof(u32))
-static bool iwl_fwrt_if_errorid_other_cpu(u32 err_id)
-{
- err_id &= 0xFF;
-
- if ((err_id >= FW_ASSERT_LMAC_FATAL &&
- err_id <= RT_NMI_INTERRUPT_OTHER_LMAC_FATAL) ||
- err_id == FW_ASSERT_NMI_UNKNOWN)
- return true;
- return false;
-}
-
static void iwl_fwrt_dump_umac_error_log(struct iwl_fw_runtime *fwrt)
{
struct iwl_trans *trans = fwrt->trans;
@@ -131,13 +113,6 @@ static void iwl_fwrt_dump_umac_error_log(struct iwl_fw_runtime *fwrt)
if (table.valid)
fwrt->dump.umac_err_id = table.error_id;
- if (!iwl_fwrt_if_errorid_other_cpu(fwrt->dump.umac_err_id) &&
- !fwrt->trans->dbg.dump_file_name_ext_valid) {
- fwrt->trans->dbg.dump_file_name_ext_valid = true;
- snprintf(fwrt->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME,
- "0x%x", fwrt->dump.umac_err_id);
- }
-
if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
IWL_ERR(trans, "Start IWL Error Log Dump:\n");
IWL_ERR(trans, "Transport status: 0x%08lX, valid: %d\n",
@@ -199,11 +174,11 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu
IWL_ERR(trans, "HW error, resetting before reading\n");
/* reset the device */
- err = iwl_trans_sw_reset(trans, true);
+ err = iwl_trans_sw_reset(trans);
if (err)
return;
- err = iwl_finish_nic_init(trans);
+ err = iwl_trans_activate_nic(trans);
if (err)
return;
}
@@ -213,13 +188,6 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu
if (table.valid)
fwrt->dump.lmac_err_id[lmac_num] = table.error_id;
- if (!iwl_fwrt_if_errorid_other_cpu(fwrt->dump.lmac_err_id[lmac_num]) &&
- !fwrt->trans->dbg.dump_file_name_ext_valid) {
- fwrt->trans->dbg.dump_file_name_ext_valid = true;
- snprintf(fwrt->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME,
- "0x%x", fwrt->dump.lmac_err_id[lmac_num]);
- }
-
if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
IWL_ERR(trans, "Start IWL Error Log Dump:\n");
IWL_ERR(trans, "Transport status: 0x%08lX, valid: %d\n",
@@ -305,16 +273,6 @@ static void iwl_fwrt_dump_tcm_error_log(struct iwl_fw_runtime *fwrt, int idx)
iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
- if (table.valid)
- fwrt->dump.tcm_err_id[idx] = table.error_id;
-
- if (!iwl_fwrt_if_errorid_other_cpu(fwrt->dump.tcm_err_id[idx]) &&
- !fwrt->trans->dbg.dump_file_name_ext_valid) {
- fwrt->trans->dbg.dump_file_name_ext_valid = true;
- snprintf(fwrt->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME,
- "0x%x", fwrt->dump.tcm_err_id[idx]);
- }
-
IWL_ERR(fwrt, "TCM%d status:\n", idx + 1);
IWL_ERR(fwrt, "0x%08X | error ID\n", table.error_id);
IWL_ERR(fwrt, "0x%08X | tcm branchlink2\n", table.blink2);
@@ -378,16 +336,6 @@ static void iwl_fwrt_dump_rcm_error_log(struct iwl_fw_runtime *fwrt, int idx)
iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
- if (table.valid)
- fwrt->dump.rcm_err_id[idx] = table.error_id;
-
- if (!iwl_fwrt_if_errorid_other_cpu(fwrt->dump.rcm_err_id[idx]) &&
- !fwrt->trans->dbg.dump_file_name_ext_valid) {
- fwrt->trans->dbg.dump_file_name_ext_valid = true;
- snprintf(fwrt->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME,
- "0x%x", fwrt->dump.rcm_err_id[idx]);
- }
-
IWL_ERR(fwrt, "RCM%d status:\n", idx + 1);
IWL_ERR(fwrt, "0x%08X | error ID\n", table.error_id);
IWL_ERR(fwrt, "0x%08X | rcm branchlink2\n", table.blink2);
@@ -417,10 +365,10 @@ static void iwl_fwrt_dump_iml_error_log(struct iwl_fw_runtime *fwrt)
struct iwl_trans *trans = fwrt->trans;
u32 error, data1;
- if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
+ if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
error = UMAG_SB_CPU_2_STATUS;
data1 = UMAG_SB_CPU_1_STATUS;
- } else if (fwrt->trans->trans_cfg->device_family >=
+ } else if (fwrt->trans->mac_cfg->device_family >=
IWL_DEVICE_FAMILY_8000) {
error = SB_CPU_2_STATUS;
data1 = SB_CPU_1_STATUS;
@@ -439,7 +387,7 @@ static void iwl_fwrt_dump_iml_error_log(struct iwl_fw_runtime *fwrt)
IWL_ERR(fwrt, "0x%08X | IML/ROM data1\n",
iwl_read_umac_prph(trans, data1));
- if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000)
+ if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000)
IWL_ERR(fwrt, "0x%08X | IML/ROM WFPM_AUTH_KEY_0\n",
iwl_read_umac_prph(trans, SB_MODIFY_CFG_FLAG));
}
@@ -490,7 +438,7 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
struct iwl_pc_data *pc_data;
u8 count;
- if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status)) {
+ if (!iwl_trans_device_enabled(fwrt->trans)) {
IWL_ERR(fwrt,
"DEVICE_ENABLED bit is not set. Aborting dump.\n");
return;
@@ -508,7 +456,7 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
iwl_fwrt_dump_rcm_error_log(fwrt, 1);
iwl_fwrt_dump_iml_error_log(fwrt);
iwl_fwrt_dump_fseq_regs(fwrt);
- if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
+ if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
pc_data = fwrt->trans->dbg.pc_data;
if (!iwl_trans_grab_nic_access(fwrt->trans))
@@ -522,7 +470,7 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
iwl_trans_release_nic_access(fwrt->trans);
}
- if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
+ if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
u32 scratch = iwl_read32(fwrt->trans, CSR_FUNC_SCRATCH);
IWL_ERR(fwrt, "Function Scratch status:\n");
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
index 3af275133da0..525a82030daa 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-2024 Intel Corporation
+ * Copyright (C) 2014, 2018-2025 Intel Corporation
* Copyright (C) 2014-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -266,7 +266,7 @@ struct iwl_fw_ini_error_dump_data {
} __packed;
/**
- * struct iwl_fw_ini_dump_entry
+ * struct iwl_fw_ini_dump_entry - dump entry descriptor
* @list: list of dump entries
* @size: size of the data
* @data: entry data
@@ -305,7 +305,7 @@ struct iwl_fw_ini_fifo_hdr {
* @dram_base_addr: base address of dram monitor range
* @page_num: page number of memory range
* @fifo_hdr: fifo header of memory range
- * @fw_pkt: FW packet header of memory range
+ * @fw_pkt_hdr: FW packet header of memory range
* @data: the actual memory
*/
struct iwl_fw_ini_error_dump_range {
@@ -372,10 +372,8 @@ struct iwl_fw_ini_dump_cfg_name {
u8 cfg_name[IWL_FW_INI_MAX_CFG_NAME];
} __packed;
-/* AX210's HW type */
-#define IWL_AX210_HW_TYPE 0x42
-/* How many bits to roll when adding to the HW type of AX210 HW */
-#define IWL_AX210_HW_TYPE_ADDITION_SHIFT 12
+#define IWL_CDB_MASK(val) val << 13
+
/* struct iwl_fw_ini_dump_info - ini dump information
* @version: dump version
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h
index 9860903ecd3f..b9e0b69c6680 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/file.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h
@@ -102,6 +102,10 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_SEC_TABLE_ADDR = 66,
IWL_UCODE_TLV_D3_KEK_KCK_ADDR = 67,
IWL_UCODE_TLV_CURRENT_PC = 68,
+ IWL_UCODE_TLV_FSEQ_BIN_VERSION = 72,
+
+ /* contains sub-sections like PNVM file does (did) */
+ IWL_UCODE_TLV_PNVM_DATA = 74,
IWL_UCODE_TLV_FW_NUM_STATIONS = IWL_UCODE_TLV_CONST_BASE + 0,
IWL_UCODE_TLV_FW_NUM_LINKS = IWL_UCODE_TLV_CONST_BASE + 1,
@@ -218,7 +222,10 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
* @IWL_UCODE_TLV_API_STA_TYPE: This ucode supports station type assignement.
* @IWL_UCODE_TLV_API_NAN2_VER2: This ucode supports NAN API version 2
* @IWL_UCODE_TLV_API_ADAPTIVE_DWELL: support for adaptive dwell in scanning
+ * @IWL_UCODE_TLV_API_OCE: support for OCE
+ * @IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE: new beacon template
* @IWL_UCODE_TLV_API_NEW_RX_STATS: should new RX STATISTICS API be used
+ * @IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL: WoWLAN key material support
* @IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY: Quota command includes a field
* indicating low latency direction.
* @IWL_UCODE_TLV_API_DEPRECATE_TTAK: RX status flag TTAK ok (bit 7) is
@@ -241,6 +248,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S.
* @IWL_UCODE_TLV_API_MBSSID_HE: This ucode supports v2 of
* STA_CONTEXT_DOT11AX_API_S
+ * @IWL_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE: WoWLAN TCP-SYN wake support
* @IWL_UCODE_TLV_API_FTM_RTT_ACCURACY: version 7 of the range response API
* is supported by FW, this indicates the RTT confidence value
* @IWL_UCODE_TLV_API_SAR_TABLE_VER: This ucode supports different sar
@@ -249,6 +257,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
* SCAN_CONFIG_DB_CMD_API_S.
* @IWL_UCODE_TLV_API_ADWELL_HB_DEF_N_AP: support for setting adaptive dwell
* number of APs in the 5 GHz band
+ * @IWL_UCODE_TLV_API_SCAN_EXT_CHAN_VER: extended channel config in scan
* @IWL_UCODE_TLV_API_BAND_IN_RX_DATA: FW reports band number in RX notification
* @IWL_UCODE_TLV_API_NO_HOST_DISABLE_TX: Firmware offloaded the station disable tx
* logic.
@@ -348,16 +357,24 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
* @IWL_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT: the firmware supports setting
* stabilization latency for SoCs.
* @IWL_UCODE_TLV_CAPA_STA_PM_NOTIF: firmware will send STA PM notification
+ * @IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT: binding CDB support
+ * @IWL_UCODE_TLV_CAPA_CDB_SUPPORT: CDB support
+ * @IWL_UCODE_TLV_CAPA_D0I3_END_FIRST: D0I3 end command comes first
* @IWL_UCODE_TLV_CAPA_TLC_OFFLOAD: firmware implements rate scaling algorithm
* @IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA: firmware implements quota related
* @IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2: firmware implements Coex Schema 2
- * IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD: firmware supports CSA command
+ * @IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD: firmware supports CSA command
* @IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS: firmware supports ultra high band
* (6 GHz).
* @IWL_UCODE_TLV_CAPA_CS_MODIFY: firmware supports modify action CSA command
+ * @IWL_UCODE_TLV_CAPA_SET_LTR_GEN2: LTR gen2 support
+ * @IWL_UCODE_TLV_CAPA_TAS_CFG: TAS configuration support
+ * @IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD: session protection command
+ * @IWL_UCODE_TLV_CAPA_SET_PPAG: PPAG support
* @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement
* @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts
* @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT
+ * @IWL_UCODE_TLV_CAPA_MULTI_QUEUE_RX_SUPPORT: MQ RX support
* @IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD: the firmware supports CSA
* countdown offloading. Beacon notifications are not sent to the host.
* The fw also offloads TBTT alignment.
@@ -379,29 +396,57 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
* command size (command version 4) that supports toggling ACK TX
* power reduction.
* @IWL_UCODE_TLV_CAPA_D3_DEBUG: supports debug recording during D3
+ * @IWL_UCODE_TLV_CAPA_LED_CMD_SUPPORT: LED command support
* @IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT: MCC response support 11ax
* capability.
* @IWL_UCODE_TLV_CAPA_CSI_REPORTING: firmware is capable of being configured
* to report the CSI information with (certain) RX frames
+ * @IWL_UCODE_TLV_CAPA_DBG_SUSPEND_RESUME_CMD_SUPP: suspend/resume command
+ * @IWL_UCODE_TLV_CAPA_DBG_BUF_ALLOC_CMD_SUPP: support for DBGC
+ * buffer allocation command
* @IWL_UCODE_TLV_CAPA_FTM_CALIBRATED: has FTM calibrated and thus supports both
* initiator and responder
* @IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_UNII4_US_CA: supports (de)activating UNII-4
* for US/CA/WW from BIOS
+ * @IWL_UCODE_TLV_CAPA_PSC_CHAN_SUPPORT: supports PSC channels
+ * @IWL_UCODE_TLV_CAPA_BIGTK_SUPPORT: BIGTK support
* @IWL_UCODE_TLV_CAPA_PROTECTED_TWT: Supports protection of TWT action frames
* @IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE: Supports the firmware handshake in
* reset flow
* @IWL_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN: Support for passive scan on 6GHz PSC
* channels even when these are not enabled.
+ * @IWL_UCODE_TLV_CAPA_HIDDEN_6GHZ_SCAN: hidden SSID 6 GHz scan support
+ * @IWL_UCODE_TLV_CAPA_BROADCAST_TWT: broadcast TWT support
+ * @IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO: support for BT-coex high
+ * priority for 802.1X/4-way-HS
+ * @IWL_UCODE_TLV_CAPA_BAID_ML_SUPPORT: multi-link BAID support
+ * @IWL_UCODE_TLV_CAPA_SYNCED_TIME: synced time command support
+ * @IWL_UCODE_TLV_CAPA_TIME_SYNC_BOTH_FTM_TM: time sync support
+ * @IWL_UCODE_TLV_CAPA_BIGTK_TX_SUPPORT: BIGTK TX support
+ * @IWL_UCODE_TLV_CAPA_MLD_API_SUPPORT: MLD API support
+ * @IWL_UCODE_TLV_CAPA_SCAN_DONT_TOGGLE_ANT: fixed antenna scan support
+ * @IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT: PPAG China BIOS support
+ * @IWL_UCODE_TLV_CAPA_OFFLOAD_BTM_SUPPORT: BTM protocol offload support
+ * @IWL_UCODE_TLV_CAPA_STA_EXP_MFP_SUPPORT: STA command MFP support
+ * @IWL_UCODE_TLV_CAPA_SNIFF_VALIDATE_SUPPORT: sniffer validate bits support
+ * @IWL_UCODE_TLV_CAPA_CHINA_22_REG_SUPPORT: China 2022 regulator support
* @IWL_UCODE_TLV_CAPA_DUMP_COMPLETE_SUPPORT: Support for indicating dump collection
* complete to FW.
* @IWL_UCODE_TLV_CAPA_SPP_AMSDU_SUPPORT: Support SPP (signaling and payload
* protected) A-MSDU.
+ * @IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT: support for DBGC fragmented
+ * DRAM buffers
* @IWL_UCODE_TLV_CAPA_SECURE_LTF_SUPPORT: Support secure LTF measurement.
* @IWL_UCODE_TLV_CAPA_MONITOR_PASSIVE_CHANS: Support monitor mode on otherwise
* passive channels
* @IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_5G9_FOR_CA: supports (de)activating 5G9
* for CA from BIOS.
* @IWL_UCODE_TLV_CAPA_UHB_CANADA_TAS_SUPPORT: supports %TAS_UHB_ALLOWED_CANADA
+ * @IWL_UCODE_TLV_CAPA_EXT_FSEQ_IMAGE_SUPPORT: external FSEQ image support
+ * @IWL_UCODE_TLV_CAPA_RESET_DURING_ASSERT: FW reset handshake is needed
+ * during assert handling even if the dump isn't split
+ * @IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE: Firmware has capability of
+ * handling raw DSM table data.
*
* @NUM_IWL_UCODE_TLV_CAPA: number of bits used
*/
@@ -480,12 +525,7 @@ enum iwl_ucode_tlv_capa {
/* set 3 */
IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_UNII4_US_CA = (__force iwl_ucode_tlv_capa_t)96,
-
- /*
- * @IWL_UCODE_TLV_CAPA_PSC_CHAN_SUPPORT: supports PSC channels
- */
IWL_UCODE_TLV_CAPA_PSC_CHAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)98,
-
IWL_UCODE_TLV_CAPA_BIGTK_SUPPORT = (__force iwl_ucode_tlv_capa_t)100,
IWL_UCODE_TLV_CAPA_SPP_AMSDU_SUPPORT = (__force iwl_ucode_tlv_capa_t)103,
IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT = (__force iwl_ucode_tlv_capa_t)104,
@@ -504,6 +544,12 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_MONITOR_PASSIVE_CHANS = (__force iwl_ucode_tlv_capa_t)122,
IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_5G9_FOR_CA = (__force iwl_ucode_tlv_capa_t)123,
IWL_UCODE_TLV_CAPA_UHB_CANADA_TAS_SUPPORT = (__force iwl_ucode_tlv_capa_t)124,
+ IWL_UCODE_TLV_CAPA_EXT_FSEQ_IMAGE_SUPPORT = (__force iwl_ucode_tlv_capa_t)125,
+
+ /* set 4 */
+
+ IWL_UCODE_TLV_CAPA_RESET_DURING_ASSERT = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 0),
+ IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 1),
NUM_IWL_UCODE_TLV_CAPA
/*
* This construction make both sparse (which cannot increment the previous
@@ -836,6 +882,8 @@ struct iwl_fw_dbg_trigger_low_rssi {
* @start_assoc_denied: number of denied association to start recording
* @start_assoc_timeout: number of association timeout to start recording
* @start_connection_loss: number of connection loss to start recording
+ * @reserved: reserved
+ * @reserved2: reserved
*/
struct iwl_fw_dbg_trigger_mlme {
u8 stop_auth_denied;
@@ -869,6 +917,7 @@ struct iwl_fw_dbg_trigger_mlme {
* @p2p_device: timeout for the queues of a P2P device in ms
* @ibss: timeout for the queues of an IBSS in ms
* @tdls: timeout for the queues of a TDLS station in ms
+ * @reserved: reserved
*/
struct iwl_fw_dbg_trigger_txq_timer {
__le32 command_queue;
@@ -884,7 +933,7 @@ struct iwl_fw_dbg_trigger_txq_timer {
/**
* struct iwl_fw_dbg_trigger_time_event - configures a time event trigger
- * time_Events: a list of tuples <id, action_bitmap>. The driver will issue a
+ * @time_events: a list of tuples <id, action_bitmap>. The driver will issue a
* trigger each time a time event notification that relates to time event
* id with one of the actions in the bitmap is received and
* BIT(notif->status) is set in status_bitmap.
@@ -900,19 +949,19 @@ struct iwl_fw_dbg_trigger_time_event {
/**
* struct iwl_fw_dbg_trigger_ba - configures BlockAck related trigger
- * rx_ba_start: tid bitmap to configure on what tid the trigger should occur
+ * @rx_ba_start: tid bitmap to configure on what tid the trigger should occur
* when an Rx BlockAck session is started.
- * rx_ba_stop: tid bitmap to configure on what tid the trigger should occur
+ * @rx_ba_stop: tid bitmap to configure on what tid the trigger should occur
* when an Rx BlockAck session is stopped.
- * tx_ba_start: tid bitmap to configure on what tid the trigger should occur
+ * @tx_ba_start: tid bitmap to configure on what tid the trigger should occur
* when a Tx BlockAck session is started.
- * tx_ba_stop: tid bitmap to configure on what tid the trigger should occur
+ * @tx_ba_stop: tid bitmap to configure on what tid the trigger should occur
* when a Tx BlockAck session is stopped.
- * rx_bar: tid bitmap to configure on what tid the trigger should occur
+ * @rx_bar: tid bitmap to configure on what tid the trigger should occur
* when a BAR is received (for a Tx BlockAck session).
- * tx_bar: tid bitmap to configure on what tid the trigger should occur
+ * @tx_bar: tid bitmap to configure on what tid the trigger should occur
* when a BAR is send (for an Rx BlocAck session).
- * frame_timeout: tid bitmap to configure on what tid the trigger should occur
+ * @frame_timeout: tid bitmap to configure on what tid the trigger should occur
* when a frame times out in the reordering buffer.
*/
struct iwl_fw_dbg_trigger_ba {
@@ -930,6 +979,7 @@ struct iwl_fw_dbg_trigger_ba {
* @action_bitmap: the TDLS action to trigger the collection upon
* @peer_mode: trigger on specific peer or all
* @peer: the TDLS peer to trigger the collection on
+ * @reserved: reserved
*/
struct iwl_fw_dbg_trigger_tdls {
u8 action_bitmap;
@@ -942,6 +992,7 @@ struct iwl_fw_dbg_trigger_tdls {
* struct iwl_fw_dbg_trigger_tx_status - configures trigger for tx response
* status.
* @statuses: the list of statuses to trigger the collection on
+ * @reserved: reserved
*/
struct iwl_fw_dbg_trigger_tx_status {
struct tx_status {
@@ -955,6 +1006,7 @@ struct iwl_fw_dbg_trigger_tx_status {
* struct iwl_fw_dbg_conf_tlv - a TLV that describes a debug configuration.
* @id: conf id
* @usniffer: should the uSniffer image be used
+ * @reserved: reserved
* @num_of_hcmds: how many HCMDs to send are present here
* @hcmd: a variable length host command to be sent to apply the configuration.
* If there is more than one HCMD to send, they will appear one after the
@@ -994,6 +1046,10 @@ struct iwl_fw_dump_exclude {
__le32 addr, size;
};
+struct iwl_fw_fseq_bin_version {
+ __le32 major, minor;
+}; /* FW_TLV_FSEQ_BIN_VERSION_S */
+
static inline size_t _iwl_tlv_array_len(const struct iwl_ucode_tlv *tlv,
size_t fixed_size, size_t var_size)
{
@@ -1011,4 +1067,18 @@ static inline size_t _iwl_tlv_array_len(const struct iwl_ucode_tlv *tlv,
#define iwl_tlv_array_len_with_size(_tlv_ptr, _struct_ptr, _size) \
_iwl_tlv_array_len((_tlv_ptr), sizeof(*(_struct_ptr)), _size)
+
+/* external FSEQ file */
+#define IWL_FSEQ_FILE "intel/fseq-%04x-%04x"
+#define IWL_FSEQ_MAGIC "INTEL-CNV-FSEQ\n\0"
+
+struct iwl_fseq_file {
+ char magic[16];
+ char version[16];
+ __le32 bt_len;
+ __le32 wifi_len;
+ u8 reserved[8];
+ u8 data[];
+} __packed;
+
#endif /* __iwl_fw_file_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h
index f9de139561a0..045a3e009429 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/img.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h
@@ -14,14 +14,13 @@
#include "error-dump.h"
/**
- * enum iwl_ucode_type
- *
- * The type of ucode.
+ * enum iwl_ucode_type - type of ucode
*
* @IWL_UCODE_REGULAR: Normal runtime ucode
* @IWL_UCODE_INIT: Initial ucode
* @IWL_UCODE_WOWLAN: Wake on Wireless enabled ucode
* @IWL_UCODE_REGULAR_USNIFFER: Normal runtime ucode when using usniffer image
+ * @IWL_UCODE_TYPE_MAX: (internal value)
*/
enum iwl_ucode_type {
IWL_UCODE_REGULAR,
@@ -53,8 +52,8 @@ struct iwl_ucode_capabilities {
u32 num_stations;
u32 num_links;
u32 num_beacons;
- unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)];
- unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)];
+ DECLARE_BITMAP(_api, NUM_IWL_UCODE_TLV_API);
+ DECLARE_BITMAP(_capa, NUM_IWL_UCODE_TLV_CAPA);
const struct iwl_fw_cmd_version *cmd_versions;
u32 n_cmd_versions;
@@ -122,7 +121,7 @@ struct fw_img {
#define FW_ADDR_CACHE_CONTROL 0xC0000000UL
/**
- * struct iwl_fw_paging
+ * struct iwl_fw_paging - FW paging descriptor
* @fw_paging_phys: page phy pointer
* @fw_paging_block: pointer to the allocated block
* @fw_paging_size: page size
@@ -195,6 +194,13 @@ struct iwl_dump_exclude {
* @phy_integration_ver_len: length of @phy_integration_ver
* @dump_excl: image dump exclusion areas for RT image
* @dump_excl_wowlan: image dump exclusion areas for WoWLAN image
+ * @pnvm_data: PNVM data embedded in the .ucode file, if any
+ * @pnvm_size: size of the embedded PNVM data
+ * @dbg: debug data, see &struct iwl_fw_dbg
+ * @default_calib: default calibration data
+ * @phy_config: PHY configuration flags
+ * @valid_rx_ant: valid RX antenna bitmap
+ * @valid_tx_ant: valid TX antenna bitmap
*/
struct iwl_fw {
u32 ucode_ver;
@@ -227,6 +233,9 @@ struct iwl_fw {
u32 phy_integration_ver_len;
struct iwl_dump_exclude dump_excl[2], dump_excl_wowlan[2];
+
+ const void *pnvm_data;
+ u32 pnvm_size;
};
static inline const char *get_fw_dbg_mode_string(int mode)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c
index de87e0e3e072..d1d8058ad29f 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/init.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2019-2021, 2024 Intel Corporation
+ * Copyright (C) 2019-2021, 2024-2025 Intel Corporation
*/
#include "iwl-drv.h"
#include "runtime.h"
@@ -72,7 +72,7 @@ int iwl_set_soc_latency(struct iwl_fw_runtime *fwrt)
* values in VER_1, this is backwards-compatible with VER_2,
* as long as we don't set any other bits.
*/
- if (!fwrt->trans->trans_cfg->integrated)
+ if (!fwrt->trans->mac_cfg->integrated)
cmd.flags = cpu_to_le32(SOC_CONFIG_CMD_FLAGS_DISCRETE);
BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_NONE !=
@@ -84,17 +84,17 @@ int iwl_set_soc_latency(struct iwl_fw_runtime *fwrt)
BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_1820US !=
SOC_FLAGS_LTR_APPLY_DELAY_1820);
- if (fwrt->trans->trans_cfg->ltr_delay != IWL_CFG_TRANS_LTR_DELAY_NONE &&
- !WARN_ON(!fwrt->trans->trans_cfg->integrated))
- cmd.flags |= le32_encode_bits(fwrt->trans->trans_cfg->ltr_delay,
+ if (fwrt->trans->mac_cfg->ltr_delay != IWL_CFG_TRANS_LTR_DELAY_NONE &&
+ !WARN_ON(!fwrt->trans->mac_cfg->integrated))
+ cmd.flags |= le32_encode_bits(fwrt->trans->mac_cfg->ltr_delay,
SOC_FLAGS_LTR_APPLY_DELAY_MASK);
if (iwl_fw_lookup_cmd_ver(fwrt->fw, SCAN_REQ_UMAC,
IWL_FW_CMD_VER_UNKNOWN) >= 2 &&
- fwrt->trans->trans_cfg->low_latency_xtal)
+ fwrt->trans->mac_cfg->low_latency_xtal)
cmd.flags |= cpu_to_le32(SOC_CONFIG_CMD_FLAGS_LOW_LATENCY);
- cmd.latency = cpu_to_le32(fwrt->trans->trans_cfg->xtal_latency);
+ cmd.latency = cpu_to_le32(fwrt->trans->mac_cfg->xtal_latency);
ret = iwl_trans_send_cmd(fwrt->trans, &hcmd);
if (ret)
@@ -116,14 +116,14 @@ int iwl_configure_rxq(struct iwl_fw_runtime *fwrt)
* The default queue is configured via context info, so if we
* have a single queue, there's nothing to do here.
*/
- if (fwrt->trans->num_rx_queues == 1)
+ if (fwrt->trans->info.num_rxqs == 1)
return 0;
- if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_22000)
+ if (fwrt->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_22000)
return 0;
/* skip the default queue */
- num_queues = fwrt->trans->num_rx_queues - 1;
+ num_queues = fwrt->trans->info.num_rxqs - 1;
size = struct_size(cmd, data, num_queues);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/paging.c b/drivers/net/wireless/intel/iwlwifi/fw/paging.c
index a7b7cae874a2..826409f6f710 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/paging.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/paging.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2019, 2021, 2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -267,7 +267,7 @@ int iwl_init_paging(struct iwl_fw_runtime *fwrt, enum iwl_ucode_type type)
const struct fw_img *fw = &fwrt->fw->img[type];
int ret;
- if (fwrt->trans->trans_cfg->gen2)
+ if (fwrt->trans->mac_cfg->gen2)
return 0;
/*
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
index 1195e708caa9..f297e82d63d2 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright(c) 2020-2024 Intel Corporation
+ * Copyright(c) 2020-2025 Intel Corporation
*/
#include "iwl-drv.h"
@@ -11,6 +11,7 @@
#include "fw/api/nvm-reg.h"
#include "fw/api/alive.h"
#include "fw/uefi.h"
+#include "fw/img.h"
#define IWL_PNVM_REDUCED_CAP_BIT BIT(25)
@@ -96,8 +97,8 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
"Got IWL_UCODE_TLV_HW_TYPE mac_type 0x%0x rf_id 0x%0x\n",
mac_type, rf_id);
- if (mac_type == CSR_HW_REV_TYPE(trans->hw_rev) &&
- rf_id == CSR_HW_RFID_TYPE(trans->hw_rf_id))
+ if (mac_type == CSR_HW_REV_TYPE(trans->info.hw_rev) &&
+ rf_id == CSR_HW_RFID_TYPE(trans->info.hw_rf_id))
hw_match = true;
break;
case IWL_UCODE_TLV_SEC_RT: {
@@ -152,8 +153,8 @@ done:
if (!hw_match) {
IWL_DEBUG_FW(trans,
"HW mismatch, skipping PNVM section (need mac_type 0x%x rf_id 0x%x)\n",
- CSR_HW_REV_TYPE(trans->hw_rev),
- CSR_HW_RFID_TYPE(trans->hw_rf_id));
+ CSR_HW_REV_TYPE(trans->info.hw_rev),
+ CSR_HW_RFID_TYPE(trans->info.hw_rf_id));
return -ENOENT;
}
@@ -167,7 +168,8 @@ done:
static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
size_t len,
- struct iwl_pnvm_image *pnvm_data)
+ struct iwl_pnvm_image *pnvm_data,
+ __le32 sku_id[3])
{
const struct iwl_ucode_tlv *tlv;
@@ -190,23 +192,23 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
}
if (tlv_type == IWL_UCODE_TLV_PNVM_SKU) {
- const struct iwl_sku_id *sku_id =
+ const struct iwl_sku_id *tlv_sku_id =
(const void *)(data + sizeof(*tlv));
IWL_DEBUG_FW(trans,
"Got IWL_UCODE_TLV_PNVM_SKU len %d\n",
tlv_len);
IWL_DEBUG_FW(trans, "sku_id 0x%0x 0x%0x 0x%0x\n",
- le32_to_cpu(sku_id->data[0]),
- le32_to_cpu(sku_id->data[1]),
- le32_to_cpu(sku_id->data[2]));
+ le32_to_cpu(tlv_sku_id->data[0]),
+ le32_to_cpu(tlv_sku_id->data[1]),
+ le32_to_cpu(tlv_sku_id->data[2]));
data += sizeof(*tlv) + ALIGN(tlv_len, 4);
len -= ALIGN(tlv_len, 4);
trans->reduced_cap_sku = false;
- rf_type = CSR_HW_RFID_TYPE(trans->hw_rf_id);
- if ((trans->sku_id[0] & IWL_PNVM_REDUCED_CAP_BIT) &&
+ rf_type = CSR_HW_RFID_TYPE(trans->info.hw_rf_id);
+ if ((sku_id[0] & cpu_to_le32(IWL_PNVM_REDUCED_CAP_BIT)) &&
rf_type == IWL_CFG_RF_TYPE_FM)
trans->reduced_cap_sku = true;
@@ -214,9 +216,9 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
"Reduced SKU device %d\n",
trans->reduced_cap_sku);
- if (trans->sku_id[0] == le32_to_cpu(sku_id->data[0]) &&
- trans->sku_id[1] == le32_to_cpu(sku_id->data[1]) &&
- trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) {
+ if (sku_id[0] == tlv_sku_id->data[0] &&
+ sku_id[1] == tlv_sku_id->data[1] &&
+ sku_id[2] == tlv_sku_id->data[2]) {
int ret;
ret = iwl_pnvm_handle_section(trans, data, len,
@@ -235,11 +237,12 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
return -ENOENT;
}
-static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len)
+static u8 *iwl_pnvm_get_from_fs(struct iwl_trans *trans, size_t *len)
{
const struct firmware *pnvm;
char pnvm_name[MAX_PNVM_NAME];
size_t new_len;
+ u8 *data;
int ret;
iwl_pnvm_get_fs_name(trans, pnvm_name, sizeof(pnvm_name));
@@ -248,28 +251,73 @@ static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len)
if (ret) {
IWL_DEBUG_FW(trans, "PNVM file %s not found %d\n",
pnvm_name, ret);
- return ret;
+ return NULL;
}
new_len = pnvm->size;
- *data = kvmemdup(pnvm->data, pnvm->size, GFP_KERNEL);
+ data = kvmemdup(pnvm->data, pnvm->size, GFP_KERNEL);
release_firmware(pnvm);
- if (!*data)
- return -ENOMEM;
+ if (!data)
+ return NULL;
*len = new_len;
- return 0;
+ return data;
+}
+
+/**
+ * enum iwl_pnvm_source - different PNVM possible sources
+ *
+ * @IWL_PNVM_SOURCE_NONE: No PNVM.
+ * @IWL_PNVM_SOURCE_BIOS: PNVM should be read from BIOS.
+ * @IWL_PNVM_SOURCE_EXTERNAL: read .pnvm external file
+ * @IWL_PNVM_SOURCE_EMBEDDED: PNVM is embedded in the .ucode file.
+ */
+enum iwl_pnvm_source {
+ IWL_PNVM_SOURCE_NONE,
+ IWL_PNVM_SOURCE_BIOS,
+ IWL_PNVM_SOURCE_EXTERNAL,
+ IWL_PNVM_SOURCE_EMBEDDED
+};
+
+static enum iwl_pnvm_source iwl_select_pnvm_source(struct iwl_trans *trans,
+ bool intel_sku)
+{
+
+ /* Get PNVM from BIOS for non-Intel SKU */
+ if (!intel_sku)
+ return IWL_PNVM_SOURCE_BIOS;
+
+ /* Before those devices, PNVM didn't exist at all */
+ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ return IWL_PNVM_SOURCE_NONE;
+
+ /* After those devices, we moved to embedded PNVM */
+ if (trans->mac_cfg->device_family > IWL_DEVICE_FAMILY_AX210)
+ return IWL_PNVM_SOURCE_EMBEDDED;
+
+ /* For IWL_DEVICE_FAMILY_AX210, depends on the CRF */
+ if (CSR_HW_RFID_TYPE(trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_GF)
+ return IWL_PNVM_SOURCE_EXTERNAL;
+
+ return IWL_PNVM_SOURCE_NONE;
}
-static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len)
+static const u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len,
+ __le32 sku_id[3], const struct iwl_fw *fw)
{
struct pnvm_sku_package *package;
+ enum iwl_pnvm_source pnvm_src =
+ iwl_select_pnvm_source(trans_p, sku_id[2] == 0);
u8 *image = NULL;
- /* Get PNVM from BIOS for non-Intel SKU */
- if (trans_p->sku_id[2]) {
+ IWL_DEBUG_FW(trans_p, "PNVM source %d\n", pnvm_src);
+
+ if (pnvm_src == IWL_PNVM_SOURCE_NONE)
+ return NULL;
+
+ if (pnvm_src == IWL_PNVM_SOURCE_BIOS) {
package = iwl_uefi_get_pnvm(trans_p, len);
if (!IS_ERR_OR_NULL(package)) {
if (*len >= sizeof(*package)) {
@@ -286,19 +334,35 @@ static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len)
if (image)
return image;
}
+
+ /* PNVM doesn't exist in BIOS. Find the fallback source */
+ pnvm_src = iwl_select_pnvm_source(trans_p, true);
+ IWL_DEBUG_FW(trans_p, "PNVM in BIOS doesn't exist, try %d\n",
+ pnvm_src);
}
- /* If it's not available, or for Intel SKU, try from the filesystem */
- if (iwl_pnvm_get_from_fs(trans_p, &image, len))
- return NULL;
- return image;
+ if (pnvm_src == IWL_PNVM_SOURCE_EXTERNAL) {
+ image = iwl_pnvm_get_from_fs(trans_p, len);
+ if (image)
+ return image;
+ }
+
+ if (pnvm_src == IWL_PNVM_SOURCE_EMBEDDED && fw->pnvm_data) {
+ *len = fw->pnvm_size;
+ return fw->pnvm_data;
+ }
+
+ IWL_ERR(trans_p, "Couldn't get PNVM from required source: %d\n", pnvm_src);
+ return NULL;
}
-static void iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans,
- const struct iwl_ucode_capabilities *capa)
+static void
+iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans,
+ const struct iwl_fw *fw,
+ __le32 sku_id[3])
{
struct iwl_pnvm_image *pnvm_data = NULL;
- u8 *data = NULL;
+ const u8 *data = NULL;
size_t length;
int ret;
@@ -309,7 +373,7 @@ static void iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans,
if (trans->pnvm_loaded)
goto set;
- data = iwl_get_pnvm_image(trans, &length);
+ data = iwl_get_pnvm_image(trans, &length, sku_id, fw);
if (!data) {
trans->fail_to_parse_pnvm_image = true;
return;
@@ -319,27 +383,30 @@ static void iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans,
if (!pnvm_data)
goto free;
- ret = iwl_pnvm_parse(trans, data, length, pnvm_data);
+ ret = iwl_pnvm_parse(trans, data, length, pnvm_data, sku_id);
if (ret) {
trans->fail_to_parse_pnvm_image = true;
goto free;
}
- ret = iwl_trans_load_pnvm(trans, pnvm_data, capa);
+ ret = iwl_trans_load_pnvm(trans, pnvm_data, &fw->ucode_capa);
if (ret)
goto free;
- IWL_INFO(trans, "loaded PNVM version %08x\n", pnvm_data->version);
+ IWL_DEBUG_INFO(trans, "loaded PNVM version %08x\n", pnvm_data->version);
set:
- iwl_trans_set_pnvm(trans, capa);
+ iwl_trans_set_pnvm(trans, &fw->ucode_capa);
free:
- kvfree(data);
+ /* free only if it was allocated, i.e. not just embedded PNVM data */
+ if (data != fw->pnvm_data)
+ kvfree(data);
kfree(pnvm_data);
}
static void
iwl_pnvm_load_reduce_power_to_trans(struct iwl_trans *trans,
- const struct iwl_ucode_capabilities *capa)
+ const struct iwl_ucode_capabilities *capa,
+ __le32 sku_id[3])
{
struct iwl_pnvm_image *pnvm_data = NULL;
u8 *data = NULL;
@@ -362,7 +429,8 @@ iwl_pnvm_load_reduce_power_to_trans(struct iwl_trans *trans,
if (!pnvm_data)
goto free;
- ret = iwl_uefi_reduce_power_parse(trans, data, length, pnvm_data);
+ ret = iwl_uefi_reduce_power_parse(trans, data, length, pnvm_data,
+ sku_id);
if (ret) {
trans->failed_to_load_reduce_power_image = true;
goto free;
@@ -386,18 +454,18 @@ free:
int iwl_pnvm_load(struct iwl_trans *trans,
struct iwl_notif_wait_data *notif_wait,
- const struct iwl_ucode_capabilities *capa)
+ const struct iwl_fw *fw, __le32 sku_id[3])
{
struct iwl_notification_wait pnvm_wait;
static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP,
PNVM_INIT_COMPLETE_NTFY) };
/* if the SKU_ID is empty, there's nothing to do */
- if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2])
+ if (!sku_id[0] && !sku_id[1] && !sku_id[2])
return 0;
- iwl_pnvm_load_pnvm_to_trans(trans, capa);
- iwl_pnvm_load_reduce_power_to_trans(trans, capa);
+ iwl_pnvm_load_pnvm_to_trans(trans, fw, sku_id);
+ iwl_pnvm_load_reduce_power_to_trans(trans, &fw->ucode_capa, sku_id);
iwl_init_notification_wait(notif_wait, &pnvm_wait,
ntf_cmds, ARRAY_SIZE(ntf_cmds),
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h
index 1bac3466154c..ad3b7e2423ac 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h
@@ -1,12 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright(c) 2020-2023 Intel Corporation
+ * Copyright(c) 2020-2023, 2025 Intel Corporation
*/
#ifndef __IWL_PNVM_H__
#define __IWL_PNVM_H__
#include "iwl-drv.h"
#include "fw/notif-wait.h"
+#include "fw/img.h"
#define MVM_UCODE_PNVM_TIMEOUT (HZ / 4)
@@ -14,7 +15,7 @@
int iwl_pnvm_load(struct iwl_trans *trans,
struct iwl_notif_wait_data *notif_wait,
- const struct iwl_ucode_capabilities *capa);
+ const struct iwl_fw *fw, __le32 sku_id[3]);
static inline
void iwl_pnvm_get_fs_name(struct iwl_trans *trans,
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c
index 6adcfa6e214a..d2ad169ae880 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2023 Intel Corporation
+ * Copyright (C) 2023, 2025 Intel Corporation
*/
#include <linux/dmi.h>
#include "iwl-drv.h"
@@ -34,6 +34,7 @@ IWL_BIOS_TABLE_LOADER(wrds_table);
IWL_BIOS_TABLE_LOADER(ewrd_table);
IWL_BIOS_TABLE_LOADER(wgds_table);
IWL_BIOS_TABLE_LOADER(ppag_table);
+IWL_BIOS_TABLE_LOADER(phy_filters);
IWL_BIOS_TABLE_LOADER_DATA(tas_table, struct iwl_tas_data);
IWL_BIOS_TABLE_LOADER_DATA(pwr_limit, u64);
IWL_BIOS_TABLE_LOADER_DATA(mcc, char);
@@ -58,11 +59,16 @@ static const struct dmi_system_id dmi_ppag_approved_list[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
},
},
- { .ident = "ASUS",
+ { .ident = "ASUSTEK",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
},
},
+ { .ident = "ASUS",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUS"),
+ },
+ },
{ .ident = "GOOGLE-HP",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
@@ -140,11 +146,16 @@ static const struct dmi_system_id dmi_tas_approved_list[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
},
},
- { .ident = "ASUS",
+ { .ident = "ASUSTEK",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
},
},
+ { .ident = "ASUS",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUS"),
+ },
+ },
{ .ident = "GOOGLE-HP",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
@@ -180,9 +191,9 @@ bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
*/
return IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) >= 38 ||
(IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 17 &&
- fwrt->trans->hw_rev != CSR_HW_REV_TYPE_3160) ||
+ fwrt->trans->info.hw_rev != CSR_HW_REV_TYPE_3160) ||
(IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 29 &&
- ((fwrt->trans->hw_rev & CSR_HW_REV_TYPE_MSK) ==
+ ((fwrt->trans->info.hw_rev & CSR_HW_REV_TYPE_MSK) ==
CSR_HW_REV_TYPE_7265D));
}
IWL_EXPORT_SYMBOL(iwl_sar_geo_support);
@@ -304,6 +315,7 @@ static bool iwl_ppag_value_valid(struct iwl_fw_runtime *fwrt, int chain,
return true;
}
+/* Utility function for iwlmvm and iwlxvt */
int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
union iwl_ppag_table_cmd *cmd, int *cmd_size)
{
@@ -313,7 +325,7 @@ int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
bool send_ppag_always;
/* many firmware images for JF lie about this */
- if (CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id) ==
+ if (CSR_HW_RFID_TYPE(fwrt->trans->info.hw_rf_id) ==
CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_JF))
return -EOPNOTSUPP;
@@ -338,31 +350,35 @@ int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
return -EINVAL;
}
- /* The 'flags' field is the same in v1 and in v2 so we can just
- * use v1 to access it.
- */
- cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags);
-
IWL_DEBUG_RADIO(fwrt, "PPAG cmd ver is %d\n", cmd_ver);
if (cmd_ver == 1) {
num_sub_bands = IWL_NUM_SUB_BANDS_V1;
gain = cmd->v1.gain[0];
*cmd_size = sizeof(cmd->v1);
- if (fwrt->ppag_ver >= 1) {
+ cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V1_MASK);
+ if (fwrt->ppag_bios_rev >= 1) {
/* in this case FW supports revision 0 */
IWL_DEBUG_RADIO(fwrt,
"PPAG table rev is %d, send truncated table\n",
- fwrt->ppag_ver);
+ fwrt->ppag_bios_rev);
}
- } else if (cmd_ver >= 2 && cmd_ver <= 6) {
+ } else if (cmd_ver == 5) {
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
- gain = cmd->v2.gain[0];
- *cmd_size = sizeof(cmd->v2);
- if (fwrt->ppag_ver == 0) {
+ gain = cmd->v5.gain[0];
+ *cmd_size = sizeof(cmd->v5);
+ cmd->v5.flags = cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V5_MASK);
+ if (fwrt->ppag_bios_rev == 0) {
/* in this case FW supports revisions 1,2 or 3 */
IWL_DEBUG_RADIO(fwrt,
"PPAG table rev is 0, send padded table\n");
}
+ } else if (cmd_ver == 7) {
+ num_sub_bands = IWL_NUM_SUB_BANDS_V2;
+ gain = cmd->v7.gain[0];
+ *cmd_size = sizeof(cmd->v7);
+ cmd->v7.ppag_config_info.table_source = fwrt->ppag_bios_source;
+ cmd->v7.ppag_config_info.table_revision = fwrt->ppag_bios_rev;
+ cmd->v7.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags);
} else {
IWL_DEBUG_RADIO(fwrt, "Unsupported PPAG command version\n");
return -EINVAL;
@@ -371,26 +387,24 @@ int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
/* ppag mode */
IWL_DEBUG_RADIO(fwrt,
"PPAG MODE bits were read from bios: %d\n",
- le32_to_cpu(cmd->v1.flags));
+ fwrt->ppag_flags);
- if (cmd_ver == 5)
- cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V5_MASK);
- else if (cmd_ver < 5)
- cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V4_MASK);
-
- if ((cmd_ver == 1 &&
- !fw_has_capa(&fwrt->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) ||
- (cmd_ver == 2 && fwrt->ppag_ver >= 2)) {
+ if (cmd_ver == 1 &&
+ !fw_has_capa(&fwrt->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) {
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n");
} else {
IWL_DEBUG_RADIO(fwrt, "isn't masking ppag China bit\n");
}
+ /* The 'flags' field is the same in v1 and v5 so we can just
+ * use v1 to access it.
+ */
IWL_DEBUG_RADIO(fwrt,
"PPAG MODE bits going to be sent: %d\n",
- le32_to_cpu(cmd->v1.flags));
+ (cmd_ver < 7) ? le32_to_cpu(cmd->v1.flags) :
+ le32_to_cpu(cmd->v7.ppag_config_info.value));
for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
for (j = 0; j < num_sub_bands; j++) {
@@ -480,7 +494,7 @@ __le32 iwl_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
u32 val;
__le32 config_bitmap = 0;
- switch (CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id)) {
+ switch (CSR_HW_RFID_TYPE(fwrt->trans->info.hw_rf_id)) {
case IWL_CFG_RF_TYPE_HR1:
case IWL_CFG_RF_TYPE_HR2:
case IWL_CFG_RF_TYPE_JF1:
@@ -529,32 +543,14 @@ static size_t iwl_get_lari_config_cmd_size(u8 cmd_ver)
switch (cmd_ver) {
case 12:
- case 11:
cmd_size = sizeof(struct iwl_lari_config_change_cmd);
break;
- case 10:
- cmd_size = sizeof(struct iwl_lari_config_change_cmd_v10);
- break;
- case 9:
case 8:
- case 7:
- cmd_size = sizeof(struct iwl_lari_config_change_cmd_v7);
+ cmd_size = sizeof(struct iwl_lari_config_change_cmd_v8);
break;
case 6:
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v6);
break;
- case 5:
- cmd_size = sizeof(struct iwl_lari_config_change_cmd_v5);
- break;
- case 4:
- cmd_size = sizeof(struct iwl_lari_config_change_cmd_v4);
- break;
- case 3:
- cmd_size = sizeof(struct iwl_lari_config_change_cmd_v3);
- break;
- case 2:
- cmd_size = sizeof(struct iwl_lari_config_change_cmd_v2);
- break;
default:
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v1);
break;
@@ -568,6 +564,8 @@ int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt,
{
int ret;
u32 value;
+ bool has_raw_dsm_capa = fw_has_capa(&fwrt->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE);
u8 cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
WIDE_ID(REGULATORY_AND_NVM_GROUP,
LARI_CONFIG_CHANGE), 1);
@@ -582,17 +580,22 @@ int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt,
cmd->config_bitmap = iwl_get_lari_config_bitmap(fwrt);
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_11AX_ENABLEMENT, &value);
- if (!ret)
+ if (!ret) {
+ if (!has_raw_dsm_capa)
+ value &= DSM_11AX_ALLOW_BITMAP;
cmd->oem_11ax_allow_bitmap = cpu_to_le32(value);
+ }
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_UNII4_CHAN, &value);
if (!ret) {
- value &= DSM_UNII4_ALLOW_BITMAP;
+ if (!has_raw_dsm_capa)
+ value &= DSM_UNII4_ALLOW_BITMAP;
- /* Since version 9, bits 4 and 5 are supported
- * regardless of this capability.
+ /* Since version 12, bits 4 and 5 are supported
+ * regardless of this capability, By pass this masking
+ * if firmware has capability of accepting raw DSM table.
*/
- if (cmd_ver < 9 &&
+ if (!has_raw_dsm_capa && cmd_ver < 12 &&
!fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_5G9_FOR_CA))
value &= ~(DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK |
@@ -603,16 +606,20 @@ int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt,
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value);
if (!ret) {
- if (cmd_ver < 8)
+ if (!has_raw_dsm_capa)
+ value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V12;
+
+ if (!has_raw_dsm_capa && cmd_ver < 8)
value &= ~ACTIVATE_5G2_IN_WW_MASK;
/* Since version 12, bits 5 and 6 are supported
- * regardless of this capability.
+ * regardless of this capability, By pass this masking
+ * if firmware has capability of accepting raw DSM table.
*/
- if (cmd_ver < 12 &&
+ if (!has_raw_dsm_capa && cmd_ver < 12 &&
!fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_UNII4_US_CA))
- value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V11;
+ value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V8;
cmd->chan_state_active_bitmap = cpu_to_le32(value);
}
@@ -622,13 +629,19 @@ int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt,
cmd->oem_uhb_allow_bitmap = cpu_to_le32(value);
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_FORCE_DISABLE_CHANNELS, &value);
- if (!ret)
+ if (!ret) {
+ if (!has_raw_dsm_capa)
+ value &= DSM_FORCE_DISABLE_CHANNELS_ALLOWED_BITMAP;
cmd->force_disable_channels_bitmap = cpu_to_le32(value);
+ }
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENERGY_DETECTION_THRESHOLD,
&value);
- if (!ret)
+ if (!ret) {
+ if (!has_raw_dsm_capa)
+ value &= DSM_EDT_ALLOWED_BITMAP;
cmd->edt_bitmap = cpu_to_le32(value);
+ }
ret = iwl_bios_get_wbem(fwrt, &value);
if (!ret)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
index 53693314d505..735482e7adf5 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2023-2024 Intel Corporation
+ * Copyright (C) 2023-2025 Intel Corporation
*/
#ifndef __fw_regulatory_h__
@@ -12,7 +12,6 @@
#include "fw/api/phy.h"
#include "fw/api/config.h"
#include "fw/api/nvm-reg.h"
-#include "fw/img.h"
#include "iwl-trans.h"
#define BIOS_SAR_MAX_PROFILE_NUM 4
@@ -159,6 +158,10 @@ enum iwl_dsm_unii4_bitmap {
DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK |\
DSM_VALUE_UNII4_CANADA_EN_MSK)
+#define DSM_11AX_ALLOW_BITMAP 0xF
+#define DSM_EDT_ALLOWED_BITMAP 0x7ffff0
+#define DSM_FORCE_DISABLE_CHANNELS_ALLOWED_BITMAP 0x7FF
+
enum iwl_dsm_values_rfi {
DSM_VALUE_RFI_DLVR_DISABLE = BIT(0),
DSM_VALUE_RFI_DDR_DISABLE = BIT(1),
@@ -224,10 +227,14 @@ int iwl_bios_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
u32 *value);
static inline u32 iwl_bios_get_ppag_flags(const u32 ppag_modes,
- const u8 ppag_ver)
+ const u8 ppag_bios_rev)
{
- return ppag_modes & (ppag_ver < 3 ? IWL_PPAG_ETSI_CHINA_MASK :
- IWL_PPAG_REV3_MASK);
+ /* For revision 4 and above driver is pipe */
+ if (ppag_bios_rev >= 4)
+ return ppag_modes;
+
+ return ppag_modes & (ppag_bios_rev < 3 ? IWL_PPAG_ETSI_CHINA_MASK :
+ IWL_PPAG_REV3_MASK);
}
bool iwl_puncturing_is_allowed_in_bios(u32 puncturing, u16 mcc);
@@ -236,22 +243,25 @@ bool iwl_puncturing_is_allowed_in_bios(u32 puncturing, u16 mcc);
#define IWL_DSBR_PERMANENT_URM_MASK BIT(9)
int iwl_bios_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value);
+int iwl_bios_get_phy_filters(struct iwl_fw_runtime *fwrt);
static inline void iwl_bios_setup_step(struct iwl_trans *trans,
struct iwl_fw_runtime *fwrt)
{
u32 dsbr;
- if (!trans->trans_cfg->integrated)
+ if (!trans->mac_cfg->integrated)
return;
- if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
+ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
return;
if (iwl_bios_get_dsbr(fwrt, &dsbr))
dsbr = 0;
- trans->dsbr_urm_fw_dependent = !!(dsbr & IWL_DSBR_FW_MODIFIED_URM_MASK);
- trans->dsbr_urm_permanent = !!(dsbr & IWL_DSBR_PERMANENT_URM_MASK);
+ trans->conf.dsbr_urm_fw_dependent =
+ !!(dsbr & IWL_DSBR_FW_MODIFIED_URM_MASK);
+ trans->conf.dsbr_urm_permanent =
+ !!(dsbr & IWL_DSBR_PERMANENT_URM_MASK);
}
#endif /* __fw_regulatory_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/rs.c b/drivers/net/wireless/intel/iwlwifi/fw/rs.c
index 8f99e501629e..746f2acffb8f 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/rs.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2021-2022 Intel Corporation
+ * Copyright (C) 2021-2022, 2025 Intel Corporation
*/
#include <net/mac80211.h>
@@ -91,104 +91,6 @@ const char *iwl_rs_pretty_bw(int bw)
}
IWL_EXPORT_SYMBOL(iwl_rs_pretty_bw);
-static u32 iwl_legacy_rate_to_fw_idx(u32 rate_n_flags)
-{
- int rate = rate_n_flags & RATE_LEGACY_RATE_MSK_V1;
- int idx;
- bool ofdm = !(rate_n_flags & RATE_MCS_CCK_MSK_V1);
- int offset = ofdm ? IWL_FIRST_OFDM_RATE : 0;
- int last = ofdm ? IWL_RATE_COUNT_LEGACY : IWL_FIRST_OFDM_RATE;
-
- for (idx = offset; idx < last; idx++)
- if (iwl_fw_rate_idx_to_plcp(idx) == rate)
- return idx - offset;
- return IWL_RATE_INVALID;
-}
-
-u32 iwl_new_rate_from_v1(u32 rate_v1)
-{
- u32 rate_v2 = 0;
- u32 dup = 0;
-
- if (rate_v1 == 0)
- return rate_v1;
- /* convert rate */
- if (rate_v1 & RATE_MCS_HT_MSK_V1) {
- u32 nss = 0;
-
- rate_v2 |= RATE_MCS_HT_MSK;
- rate_v2 |=
- rate_v1 & RATE_HT_MCS_RATE_CODE_MSK_V1;
- nss = (rate_v1 & RATE_HT_MCS_MIMO2_MSK) >>
- RATE_HT_MCS_NSS_POS_V1;
- rate_v2 |= nss << RATE_MCS_NSS_POS;
- } else if (rate_v1 & RATE_MCS_VHT_MSK_V1 ||
- rate_v1 & RATE_MCS_HE_MSK_V1) {
- rate_v2 |= rate_v1 & RATE_VHT_MCS_RATE_CODE_MSK;
-
- rate_v2 |= rate_v1 & RATE_MCS_NSS_MSK;
-
- if (rate_v1 & RATE_MCS_HE_MSK_V1) {
- u32 he_type_bits = rate_v1 & RATE_MCS_HE_TYPE_MSK_V1;
- u32 he_type = he_type_bits >> RATE_MCS_HE_TYPE_POS_V1;
- u32 he_106t = (rate_v1 & RATE_MCS_HE_106T_MSK_V1) >>
- RATE_MCS_HE_106T_POS_V1;
- u32 he_gi_ltf = (rate_v1 & RATE_MCS_HE_GI_LTF_MSK_V1) >>
- RATE_MCS_HE_GI_LTF_POS;
-
- if ((he_type_bits == RATE_MCS_HE_TYPE_SU ||
- he_type_bits == RATE_MCS_HE_TYPE_EXT_SU) &&
- he_gi_ltf == RATE_MCS_HE_SU_4_LTF)
- /* the new rate have an additional bit to
- * represent the value 4 rather then using SGI
- * bit for this purpose - as it was done in the old
- * rate */
- he_gi_ltf += (rate_v1 & RATE_MCS_SGI_MSK_V1) >>
- RATE_MCS_SGI_POS_V1;
-
- rate_v2 |= he_gi_ltf << RATE_MCS_HE_GI_LTF_POS;
- rate_v2 |= he_type << RATE_MCS_HE_TYPE_POS;
- rate_v2 |= he_106t << RATE_MCS_HE_106T_POS;
- rate_v2 |= rate_v1 & RATE_HE_DUAL_CARRIER_MODE_MSK;
- rate_v2 |= RATE_MCS_HE_MSK;
- } else {
- rate_v2 |= RATE_MCS_VHT_MSK;
- }
- /* if legacy format */
- } else {
- u32 legacy_rate = iwl_legacy_rate_to_fw_idx(rate_v1);
-
- if (WARN_ON_ONCE(legacy_rate == IWL_RATE_INVALID))
- legacy_rate = (rate_v1 & RATE_MCS_CCK_MSK_V1) ?
- IWL_FIRST_CCK_RATE : IWL_FIRST_OFDM_RATE;
-
- rate_v2 |= legacy_rate;
- if (!(rate_v1 & RATE_MCS_CCK_MSK_V1))
- rate_v2 |= RATE_MCS_LEGACY_OFDM_MSK;
- }
-
- /* convert flags */
- if (rate_v1 & RATE_MCS_LDPC_MSK_V1)
- rate_v2 |= RATE_MCS_LDPC_MSK;
- rate_v2 |= (rate_v1 & RATE_MCS_CHAN_WIDTH_MSK_V1) |
- (rate_v1 & RATE_MCS_ANT_AB_MSK) |
- (rate_v1 & RATE_MCS_STBC_MSK) |
- (rate_v1 & RATE_MCS_BF_MSK);
-
- dup = (rate_v1 & RATE_MCS_DUP_MSK_V1) >> RATE_MCS_DUP_POS_V1;
- if (dup) {
- rate_v2 |= RATE_MCS_DUP_MSK;
- rate_v2 |= dup << RATE_MCS_CHAN_WIDTH_POS;
- }
-
- if ((!(rate_v1 & RATE_MCS_HE_MSK_V1)) &&
- (rate_v1 & RATE_MCS_SGI_MSK_V1))
- rate_v2 |= RATE_MCS_SGI_MSK;
-
- return rate_v2;
-}
-IWL_EXPORT_SYMBOL(iwl_new_rate_from_v1);
-
int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)
{
char *type;
@@ -197,37 +99,40 @@ int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)
u32 bw = (rate & RATE_MCS_CHAN_WIDTH_MSK) >>
RATE_MCS_CHAN_WIDTH_POS;
u32 format = rate & RATE_MCS_MOD_TYPE_MSK;
+ int index = 0;
bool sgi;
- if (format == RATE_MCS_CCK_MSK ||
- format == RATE_MCS_LEGACY_OFDM_MSK) {
- int legacy_rate = rate & RATE_LEGACY_RATE_MSK;
- int index = format == RATE_MCS_CCK_MSK ?
- legacy_rate :
- legacy_rate + IWL_FIRST_OFDM_RATE;
+ switch (format) {
+ case RATE_MCS_MOD_TYPE_LEGACY_OFDM:
+ index = IWL_FIRST_OFDM_RATE;
+ fallthrough;
+ case RATE_MCS_MOD_TYPE_CCK:
+ index += rate & RATE_LEGACY_RATE_MSK;
return scnprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps",
iwl_rs_pretty_ant(ant),
iwl_rate_mcs(index)->mbps);
- }
-
- if (format == RATE_MCS_VHT_MSK)
+ case RATE_MCS_MOD_TYPE_VHT:
type = "VHT";
- else if (format == RATE_MCS_HT_MSK)
+ break;
+ case RATE_MCS_MOD_TYPE_HT:
type = "HT";
- else if (format == RATE_MCS_HE_MSK)
+ break;
+ case RATE_MCS_MOD_TYPE_HE:
type = "HE";
- else if (format == RATE_MCS_EHT_MSK)
+ break;
+ case RATE_MCS_MOD_TYPE_EHT:
type = "EHT";
- else
+ break;
+ default:
type = "Unknown"; /* shouldn't happen */
+ }
- mcs = format == RATE_MCS_HT_MSK ?
+ mcs = format == RATE_MCS_MOD_TYPE_HT ?
RATE_HT_MCS_INDEX(rate) :
rate & RATE_MCS_CODE_MSK;
- nss = ((rate & RATE_MCS_NSS_MSK)
- >> RATE_MCS_NSS_POS) + 1;
- sgi = format == RATE_MCS_HE_MSK ?
+ nss = u32_get_bits(rate, RATE_MCS_NSS_MSK);
+ sgi = format == RATE_MCS_MOD_TYPE_HE ?
iwl_he_is_sgi(rate) :
rate & RATE_MCS_SGI_MSK;
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
index a9e6bba2419e..57570ff15622 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2024 Intel Corporation
+ * Copyright (C) 2018-2025 Intel Corporation
*/
#ifndef __iwl_fw_runtime_h__
#define __iwl_fw_runtime_h__
@@ -45,6 +45,8 @@ struct iwl_fwrt_shared_mem_cfg {
* struct iwl_fwrt_dump_data - dump data
* @trig: trigger the worker was scheduled upon
* @fw_pkt: packet received from FW
+ * @desc: dump descriptor
+ * @monitor_only: only dump for monitor
*
* Note that the decision which part of the union is used
* is based on iwl_trans_dbg_ini_valid(): the 'trig' part
@@ -68,6 +70,7 @@ struct iwl_fwrt_dump_data {
* struct iwl_fwrt_wk_data - dump worker data struct
* @idx: index of the worker
* @wk: worker
+ * @dump_data: dump data
*/
struct iwl_fwrt_wk_data {
u8 idx;
@@ -91,8 +94,8 @@ struct iwl_txf_iter_data {
/**
* struct iwl_fw_runtime - runtime data for firmware
+ * @trans: transport pointer
* @fw: firmware image
- * @cfg: NIC configuration
* @dev: device pointer
* @ops: user ops
* @ops_ctx: user ops context
@@ -110,6 +113,30 @@ struct iwl_txf_iter_data {
* Only read the UEFI variables if locked.
* @sar_profiles: sar profiles as read from WRDS/EWRD BIOS tables
* @geo_profiles: geographic profiles as read from WGDS BIOS table
+ * @phy_filters: specific phy filters as read from WPFC BIOS table
+ * @ppag_bios_rev: PPAG BIOS revision
+ * @ppag_bios_source: see &enum bios_source
+ * @acpi_dsm_funcs_valid: bitmap indicating which DSM values are valid,
+ * zero (default initialization) means it hasn't been read yet,
+ * and BIT(0) is set when it has since function 0 also has this
+ * bitmap and is always supported
+ * @geo_enabled: WGDS table is present
+ * @geo_num_profiles: number of geo profiles
+ * @geo_rev: geo profiles table revision
+ * @ppag_chains: PPAG table data
+ * @ppag_flags: PPAG flags
+ * @reduced_power_flags: reduced power flags
+ * @sanitize_ctx: context for dump sanitizer
+ * @sanitize_ops: dump sanitizer ops
+ * @sar_chain_a_profile: SAR chain A profile
+ * @sar_chain_b_profile: SAR chain B profile
+ * @sgom_enabled: SGOM enabled
+ * @sgom_table: SGOM table
+ * @timestamp: timestamp marker data
+ * @timestamp.wk: timestamp marking worker
+ * @timestamp.seq: timestamp marking sequence
+ * @timestamp.delay: timestamp marking worker delay
+ * @tpc_enabled: TPC enabled
*/
struct iwl_fw_runtime {
struct iwl_trans *trans;
@@ -143,8 +170,6 @@ struct iwl_fw_runtime {
unsigned long non_collect_ts_start[IWL_FW_INI_TIME_POINT_NUM];
u32 *d3_debug_data;
u32 lmac_err_id[MAX_NUM_LMAC];
- u32 tcm_err_id[MAX_NUM_TCM];
- u32 rcm_err_id[MAX_NUM_RCM];
u32 umac_err_id;
struct iwl_txf_iter_data txf_iter_data;
@@ -178,12 +203,18 @@ struct iwl_fw_runtime {
bool geo_enabled;
struct iwl_ppag_chain ppag_chains[IWL_NUM_CHAIN_LIMITS];
u32 ppag_flags;
- u8 ppag_ver;
+ u8 ppag_bios_rev;
+ u8 ppag_bios_source;
struct iwl_sar_offset_mapping_cmd sgom_table;
bool sgom_enabled;
struct iwl_mcc_allowed_ap_type_cmd uats_table;
bool uats_valid;
u8 uefi_tables_lock_status;
+ struct iwl_phy_specific_cfg phy_filters;
+
+#ifdef CONFIG_ACPI
+ u32 acpi_dsm_funcs_valid;
+#endif
};
void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/smem.c b/drivers/net/wireless/intel/iwlwifi/fw/smem.c
index 3f1272014daf..90fd69b4860c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/smem.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/smem.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2021, 2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -102,7 +102,7 @@ void iwl_get_shared_mem_conf(struct iwl_fw_runtime *fwrt)
}
pkt = cmd.resp_pkt;
- if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000)
+ if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000)
iwl_parse_shared_mem_22000(fwrt, pkt);
else
iwl_parse_shared_mem(fwrt, pkt);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
index 386aadbce2a2..4ae4d215e633 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
@@ -219,7 +219,8 @@ done:
int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
const u8 *data, size_t len,
- struct iwl_pnvm_image *pnvm_data)
+ struct iwl_pnvm_image *pnvm_data,
+ __le32 sku_id[3])
{
const struct iwl_ucode_tlv *tlv;
@@ -241,23 +242,23 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
}
if (tlv_type == IWL_UCODE_TLV_PNVM_SKU) {
- const struct iwl_sku_id *sku_id =
+ const struct iwl_sku_id *tlv_sku_id =
(const void *)(data + sizeof(*tlv));
IWL_DEBUG_FW(trans,
"Got IWL_UCODE_TLV_PNVM_SKU len %d\n",
tlv_len);
IWL_DEBUG_FW(trans, "sku_id 0x%0x 0x%0x 0x%0x\n",
- le32_to_cpu(sku_id->data[0]),
- le32_to_cpu(sku_id->data[1]),
- le32_to_cpu(sku_id->data[2]));
+ le32_to_cpu(tlv_sku_id->data[0]),
+ le32_to_cpu(tlv_sku_id->data[1]),
+ le32_to_cpu(tlv_sku_id->data[2]));
data += sizeof(*tlv) + ALIGN(tlv_len, 4);
len -= ALIGN(tlv_len, 4);
- if (trans->sku_id[0] == le32_to_cpu(sku_id->data[0]) &&
- trans->sku_id[1] == le32_to_cpu(sku_id->data[1]) &&
- trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) {
+ if (sku_id[0] == tlv_sku_id->data[0] &&
+ sku_id[1] == tlv_sku_id->data[1] &&
+ sku_id[2] == tlv_sku_id->data[2]) {
int ret = iwl_uefi_reduce_power_section(trans,
data, len,
pnvm_data);
@@ -310,11 +311,12 @@ static int iwl_uefi_step_parse(struct uefi_cnv_common_step_data *common_step_dat
if (common_step_data->revision != 1)
return -EINVAL;
- trans->mbx_addr_0_step = (u32)common_step_data->revision |
+ trans->conf.mbx_addr_0_step =
+ (u32)common_step_data->revision |
(u32)common_step_data->cnvi_eq_channel << 8 |
(u32)common_step_data->cnvr_eq_channel << 16 |
(u32)common_step_data->radio1 << 24;
- trans->mbx_addr_1_step = (u32)common_step_data->radio2;
+ trans->conf.mbx_addr_1_step = (u32)common_step_data->radio2;
return 0;
}
@@ -323,7 +325,7 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans)
struct uefi_cnv_common_step_data *data;
int ret;
- if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
return;
data = iwl_uefi_get_verified_variable_guid(trans, &IWL_EFI_WIFI_BT_GUID,
@@ -408,8 +410,8 @@ static int iwl_uefi_uats_parse(struct uefi_cnv_wlan_uats_data *uats_data,
return 0;
}
-int iwl_uefi_get_uats_table(struct iwl_trans *trans,
- struct iwl_fw_runtime *fwrt)
+void iwl_uefi_get_uats_table(struct iwl_trans *trans,
+ struct iwl_fw_runtime *fwrt)
{
struct uefi_cnv_wlan_uats_data *data;
int ret;
@@ -417,17 +419,12 @@ int iwl_uefi_get_uats_table(struct iwl_trans *trans,
data = iwl_uefi_get_verified_variable(trans, IWL_UEFI_UATS_NAME,
"UATS", sizeof(*data), NULL);
if (IS_ERR(data))
- return -EINVAL;
+ return;
ret = iwl_uefi_uats_parse(data, fwrt);
- if (ret < 0) {
+ if (ret < 0)
IWL_DEBUG_FW(trans, "Cannot read UATS table. rev is invalid\n");
- kfree(data);
- return ret;
- }
-
kfree(data);
- return 0;
}
IWL_EXPORT_SYMBOL(iwl_uefi_get_uats_table);
@@ -557,13 +554,14 @@ int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt)
goto out;
}
- fwrt->ppag_ver = data->revision;
+ fwrt->ppag_bios_rev = data->revision;
fwrt->ppag_flags = iwl_bios_get_ppag_flags(data->ppag_modes,
- fwrt->ppag_ver);
+ fwrt->ppag_bios_rev);
BUILD_BUG_ON(sizeof(fwrt->ppag_chains) != sizeof(data->ppag_chains));
memcpy(&fwrt->ppag_chains, &data->ppag_chains,
sizeof(data->ppag_chains));
+ fwrt->ppag_bios_source = BIOS_SOURCE_UEFI;
out:
kfree(data);
return ret;
@@ -729,6 +727,8 @@ int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
struct uefi_cnv_var_general_cfg *data;
int ret = -EINVAL;
+ BUILD_BUG_ON(ARRAY_SIZE(data->functions) < DSM_FUNC_NUM_FUNCS);
+
/* Not supported function index */
if (func >= DSM_FUNC_NUM_FUNCS || func == 5)
return -EOPNOTSUPP;
@@ -744,12 +744,17 @@ int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
goto out;
}
- if (ARRAY_SIZE(data->functions) != UEFI_MAX_DSM_FUNCS) {
- IWL_DEBUG_RADIO(fwrt, "Invalid size of DSM functions array\n");
+ if (!(data->functions[DSM_FUNC_QUERY] & BIT(func))) {
+ IWL_DEBUG_RADIO(fwrt, "DSM func %d not in 0x%x\n",
+ func, data->functions[DSM_FUNC_QUERY]);
goto out;
}
*value = data->functions[func];
+
+ IWL_DEBUG_RADIO(fwrt,
+ "UEFI: DSM func=%d: value=%d\n", func, *value);
+
ret = 0;
out:
kfree(data);
@@ -810,3 +815,31 @@ out:
kfree(data);
return ret;
}
+
+int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt)
+{
+ struct uefi_cnv_wpfc_data *data __free(kfree);
+ struct iwl_phy_specific_cfg *filters = &fwrt->phy_filters;
+
+ data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WPFC_NAME,
+ "WPFC", sizeof(*data), NULL);
+ if (IS_ERR(data))
+ return -EINVAL;
+
+ if (data->revision != 0) {
+ IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WPFC revision:%d\n",
+ data->revision);
+ return -EINVAL;
+ }
+
+ BUILD_BUG_ON(ARRAY_SIZE(filters->filter_cfg_chains) !=
+ ARRAY_SIZE(data->chains));
+
+ for (int i = 0; i < ARRAY_SIZE(filters->filter_cfg_chains); i++) {
+ filters->filter_cfg_chains[i] = cpu_to_le32(data->chains[i]);
+ IWL_DEBUG_RADIO(fwrt, "WPFC: chain %d: %u\n", i, data->chains[i]);
+ }
+
+ IWL_DEBUG_RADIO(fwrt, "Loaded WPFC config from UEFI\n");
+ return 0;
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
index eb3c05417da3..5a4c557e47c7 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
@@ -24,6 +24,7 @@
#define IWL_UEFI_WBEM_NAME L"UefiCnvWlanWBEM"
#define IWL_UEFI_PUNCTURING_NAME L"UefiCnvWlanPuncturing"
#define IWL_UEFI_DSBR_NAME L"UefiCnvCommonDSBR"
+#define IWL_UEFI_WPFC_NAME L"WPFC"
#define IWL_SGOM_MAP_SIZE 339
@@ -33,7 +34,7 @@
#define IWL_UEFI_EWRD_REVISION 2
#define IWL_UEFI_WGDS_REVISION 3
#define IWL_UEFI_MIN_PPAG_REV 1
-#define IWL_UEFI_MAX_PPAG_REV 3
+#define IWL_UEFI_MAX_PPAG_REV 4
#define IWL_UEFI_MIN_WTAS_REVISION 1
#define IWL_UEFI_MAX_WTAS_REVISION 2
#define IWL_UEFI_SPLC_REVISION 0
@@ -230,6 +231,18 @@ struct uefi_cnv_wlan_dsbr_data {
u32 config;
} __packed;
+/**
+ * struct uefi_cnv_wpfc_data - BIOS Wi-Fi PHY filter Configuration
+ * @revision: the revision of the table
+ * @chains: configuration of each of the chains (a-d)
+ *
+ * specific PHY filter configuration
+ */
+struct uefi_cnv_wpfc_data {
+ u8 revision;
+ u32 chains[4];
+} __packed;
+
/*
* This is known to be broken on v4.19 and to work on v5.4. Until we
* figure out why this is the case and how to make it work, simply
@@ -240,7 +253,8 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len);
u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len);
int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
const u8 *data, size_t len,
- struct iwl_pnvm_image *pnvm_data);
+ struct iwl_pnvm_image *pnvm_data,
+ __le32 sku_id[3]);
void iwl_uefi_get_step_table(struct iwl_trans *trans);
int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data,
u32 tlv_len, struct iwl_pnvm_image *pnvm_data);
@@ -258,10 +272,11 @@ int iwl_uefi_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value);
int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
u32 *value);
void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt);
-int iwl_uefi_get_uats_table(struct iwl_trans *trans,
- struct iwl_fw_runtime *fwrt);
+void iwl_uefi_get_uats_table(struct iwl_trans *trans,
+ struct iwl_fw_runtime *fwrt);
int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt);
int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value);
+int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt);
#else /* CONFIG_EFI */
static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
{
@@ -271,7 +286,8 @@ static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
static inline int
iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
const u8 *data, size_t len,
- struct iwl_pnvm_image *pnvm_data)
+ struct iwl_pnvm_image *pnvm_data,
+ __le32 sku_id[3])
{
return -EOPNOTSUPP;
}
@@ -352,11 +368,9 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwr
{
}
-static inline
-int iwl_uefi_get_uats_table(struct iwl_trans *trans,
- struct iwl_fw_runtime *fwrt)
+static inline void
+iwl_uefi_get_uats_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt)
{
- return 0;
}
static inline
@@ -370,5 +384,10 @@ int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value)
{
return -ENOENT;
}
+
+static inline int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt)
+{
+ return -ENOENT;
+}
#endif /* CONFIG_EFI */
#endif /* __iwl_fw_uefi__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index acafee538b8a..076810ee5d34 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
* Copyright (C) 2016-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2024 Intel Corporation
+ * Copyright (C) 2018-2025 Intel Corporation
*/
#ifndef __IWL_CONFIG_H__
#define __IWL_CONFIG_H__
@@ -11,6 +11,7 @@
#include <linux/netdevice.h>
#include <linux/ieee80211.h>
#include <linux/nl80211.h>
+#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include "iwl-csr.h"
#include "iwl-drv.h"
@@ -107,6 +108,9 @@ enum iwl_nvm_type {
MODULE_FIRMWARE(pfx "-" __stringify(api) ".ucode"); \
MODULE_FIRMWARE(pfx ".pnvm")
+#define IWL_CORE_FW(pfx, core) \
+ MODULE_FIRMWARE(pfx "-c" __stringify(core) ".ucode")
+
static inline u8 num_of_ant(u8 mask)
{
return !!((mask) & ANT_A) +
@@ -115,7 +119,29 @@ static inline u8 num_of_ant(u8 mask)
}
/**
- * struct iwl_base_params - params not likely to change within a device family
+ * struct iwl_fw_mon_reg - FW monitor register info
+ * @addr: register address
+ * @mask: register mask
+ */
+struct iwl_fw_mon_reg {
+ u32 addr;
+ u32 mask;
+};
+
+/**
+ * struct iwl_fw_mon_regs - FW monitor registers
+ * @write_ptr: write pointer register
+ * @cycle_cnt: cycle count register
+ * @cur_frag: current fragment in use
+ */
+struct iwl_fw_mon_regs {
+ struct iwl_fw_mon_reg write_ptr;
+ struct iwl_fw_mon_reg cycle_cnt;
+ struct iwl_fw_mon_reg cur_frag;
+};
+
+/**
+ * struct iwl_family_base_params - base parameters for an entire family
* @max_ll_items: max number of OTP blocks
* @shadow_ram_support: shadow support for OTP memory
* @led_compensation: compensate on the led on/off time per HW according
@@ -124,12 +150,33 @@ static inline u8 num_of_ant(u8 mask)
* @wd_timeout: TX queues watchdog timeout
* @max_event_log_size: size of event log buffer size for ucode event logging
* @shadow_reg_enable: HW shadow register support
+ * @apmg_not_supported: there's no APMG
* @apmg_wake_up_wa: should the MAC access REQ be asserted when a command
* is in flight. This is due to a HW bug in 7260, 3160 and 7265.
* @scd_chain_ext_wa: should the chain extension feature in SCD be disabled.
* @max_tfd_queue_size: max number of entries in tfd queue.
+ * @eeprom_size: EEPROM size
+ * @num_of_queues: number of HW TX queues supported
+ * @pcie_l1_allowed: PCIe L1 state is allowed
+ * @pll_cfg: PLL configuration needed
+ * @nvm_hw_section_num: the ID of the HW NVM section
+ * @features: hw features, any combination of feature_passlist
+ * @smem_offset: offset from which the SMEM begins
+ * @smem_len: the length of SMEM
+ * @mac_addr_from_csr: read HW address from CSR registers at this offset
+ * @d3_debug_data_base_addr: base address where D3 debug data is stored
+ * @d3_debug_data_length: length of the D3 debug data
+ * @min_ba_txq_size: minimum number of slots required in a TX queue used
+ * for aggregation
+ * @min_txq_size: minimum number of slots required in a TX queue
+ * @gp2_reg_addr: GP2 (timer) register address
+ * @mon_dbgi_regs: monitor DBGI registers
+ * @mon_dram_regs: monitor DRAM registers
+ * @mon_smem_regs: monitor SMEM registers
+ * @ucode_api_max: Highest version of uCode API supported by driver.
+ * @ucode_api_min: Lowest version of uCode API supported by driver.
*/
-struct iwl_base_params {
+struct iwl_family_base_params {
unsigned int wd_timeout;
u16 eeprom_size;
@@ -140,6 +187,7 @@ struct iwl_base_params {
shadow_reg_enable:1,
pcie_l1_allowed:1,
apmg_wake_up_wa:1,
+ apmg_not_supported:1,
scd_chain_ext_wa:1;
u16 num_of_queues; /* def: HW dependent */
@@ -147,9 +195,52 @@ struct iwl_base_params {
u8 max_ll_items;
u8 led_compensation;
+ u16 ucode_api_max;
+ u16 ucode_api_min;
+ u32 mac_addr_from_csr:10;
+ u8 nvm_hw_section_num;
+ netdev_features_t features;
+ u32 smem_offset;
+ u32 smem_len;
+ u32 d3_debug_data_base_addr;
+ u32 d3_debug_data_length;
+ u32 min_txq_size;
+ u32 gp2_reg_addr;
+ u32 min_ba_txq_size;
+ const struct iwl_fw_mon_regs mon_dram_regs;
+ const struct iwl_fw_mon_regs mon_smem_regs;
+ const struct iwl_fw_mon_regs mon_dbgi_regs;
};
/*
+ * FW is released as "core N release", and we used to have a
+ * gap of 3 between the API version and core number. Now the
+ * reported API version will be 1000 + core and we encode it
+ * in the filename as "c<core>".
+ */
+#define API_IS_CORE_START 1000
+#define API_TO_CORE_OFFS 3
+#define ENCODE_CORE_AS_API(core) (API_IS_CORE_START + (core))
+
+static inline bool iwl_api_is_core_number(int api)
+{
+ return api >= API_IS_CORE_START;
+}
+
+static inline int iwl_api_to_core(int api)
+{
+ if (iwl_api_is_core_number(api))
+ return api - API_IS_CORE_START;
+
+ return api - API_TO_CORE_OFFS;
+}
+
+#define FW_API_FMT "%s%d"
+#define FW_API_ARG(n) \
+ iwl_api_is_core_number(n) ? "c" : "", \
+ iwl_api_is_core_number(n) ? (n) - API_IS_CORE_START : (n)
+
+/*
* @stbc: support Tx STBC and 1*SS Rx STBC
* @ldpc: support Tx/Rx with LDPC
* @use_rts_for_aggregation: use rts/cts protection for HT traffic
@@ -238,7 +329,7 @@ struct iwl_pwr_tx_backoff {
u32 backoff;
};
-enum iwl_cfg_trans_ltr_delay {
+enum iwl_mac_cfg_ltr_delay {
IWL_CFG_TRANS_LTR_DELAY_NONE = 0,
IWL_CFG_TRANS_LTR_DELAY_200US = 1,
IWL_CFG_TRANS_LTR_DELAY_2500US = 2,
@@ -246,35 +337,33 @@ enum iwl_cfg_trans_ltr_delay {
};
/**
- * struct iwl_cfg_trans_params - information needed to start the trans
+ * struct iwl_mac_cfg - information about the MAC-specific device part
*
* These values are specific to the device ID and do not change when
* multiple configs are used for a single device ID. They values are
* used, among other things, to boot the NIC so that the HW REV or
* RFID can be read before deciding the remaining parameters to use.
*
- * @base_params: pointer to basic parameters
+ * @base: pointer to basic parameters
* @device_family: the device family
* @umac_prph_offset: offset to add to UMAC periphery address
* @xtal_latency: power up latency to get the xtal stabilized
* @extra_phy_cfg_flags: extra configuration flags to pass to the PHY
- * @rf_id: need to read rf_id to determine the firmware image
* @gen2: 22000 and on transport operation
* @mq_rx_supported: multi-queue rx support
* @integrated: discrete or integrated
* @low_latency_xtal: use the low latency xtal if supported
* @bisr_workaround: BISR hardware workaround (for 22260 series devices)
- * @ltr_delay: LTR delay parameter, &enum iwl_cfg_trans_ltr_delay.
+ * @ltr_delay: LTR delay parameter, &enum iwl_mac_cfg_ltr_delay.
* @imr_enabled: use the IMR if supported.
*/
-struct iwl_cfg_trans_params {
- const struct iwl_base_params *base_params;
+struct iwl_mac_cfg {
+ const struct iwl_family_base_params *base;
enum iwl_device_family device_family;
u32 umac_prph_offset;
u32 xtal_latency;
u32 extra_phy_cfg_flags;
- u32 rf_id:1,
- gen2:1,
+ u32 gen2:1,
mq_rx_supported:1,
integrated:1,
low_latency_xtal:1,
@@ -283,36 +372,21 @@ struct iwl_cfg_trans_params {
imr_enabled:1;
};
-/**
- * struct iwl_fw_mon_reg - FW monitor register info
- * @addr: register address
- * @mask: register mask
- */
-struct iwl_fw_mon_reg {
- u32 addr;
- u32 mask;
-};
-
-/**
- * struct iwl_fw_mon_regs - FW monitor registers
- * @write_ptr: write pointer register
- * @cycle_cnt: cycle count register
- * @cur_frag: current fragment in use
+/*
+ * These sizes were picked according to 8 MSDUs inside 64/256/612 A-MSDUs
+ * in an A-MPDU, with additional overhead to account for processing time.
+ * They will be doubled for MACs starting from So/Ty that don't support
+ * putting multiple frames into a single buffer.
*/
-struct iwl_fw_mon_regs {
- struct iwl_fw_mon_reg write_ptr;
- struct iwl_fw_mon_reg cycle_cnt;
- struct iwl_fw_mon_reg cur_frag;
-};
+#define IWL_NUM_RBDS_NON_HE (64 * 8)
+#define IWL_NUM_RBDS_HE (256 * 8)
+#define IWL_NUM_RBDS_EHT (512 * 8)
/**
- * struct iwl_cfg
- * @trans: the trans-specific configuration part
- * @name: Official name of the device
+ * struct iwl_rf_cfg - RF/CRF configuration data
* @fw_name_pre: Firmware filename prefix. The api version and extension
* (.ucode) will be added to filename before loading from disk. The
* filename is constructed as <fw_name_pre>-<api>.ucode.
- * @fw_name_mac: MAC name for this config, the remaining pieces of the
* name will be generated dynamically
* @ucode_api_max: Highest version of uCode API supported by driver.
* @ucode_api_min: Lowest version of uCode API supported by driver.
@@ -323,34 +397,26 @@ struct iwl_fw_mon_regs {
* @non_shared_ant: the antenna that is for WiFi only
* @nvm_ver: NVM version
* @nvm_calib_ver: NVM calibration version
+ * @bw_limit: bandwidth limit for this device, if non-zero
* @ht_params: point to ht parameters
+ * @eeprom_params: EEPROM parameters (old devices)
+ * @thermal_params: Thermal throttling parameters
+ * @lp_xtal_workaround: low-power crystal workaround needed
* @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
* @rx_with_siso_diversity: 1x1 device with rx antenna diversity
* @tx_with_siso_diversity: 1x1 device with tx antenna diversity
* @internal_wimax_coex: internal wifi/wimax combo device
- * @high_temp: Is this NIC is designated to be in high temperature.
* @host_interrupt_operation_mode: device needs host interrupt operation
* mode set
- * @nvm_hw_section_num: the ID of the HW NVM section
- * @mac_addr_from_csr: read HW address from CSR registers at this offset
- * @features: hw features, any combination of feature_passlist
* @pwr_tx_backoffs: translation table between power limits and backoffs
- * @max_tx_agg_size: max TX aggregation size of the ADDBA request/response
* @dccm_offset: offset from which DCCM begins
* @dccm_len: length of DCCM (including runtime stack CCM)
* @dccm2_offset: offset from which the second DCCM begins
* @dccm2_len: length of the second DCCM
- * @smem_offset: offset from which the SMEM begins
- * @smem_len: the length of SMEM
* @vht_mu_mimo_supported: VHT MU-MIMO support
- * @cdb: CDB support
* @nvm_type: see &enum iwl_nvm_type
- * @d3_debug_data_base_addr: base address where D3 debug data is stored
- * @d3_debug_data_length: length of the D3 debug data
- * @min_txq_size: minimum number of slots required in a TX queue
* @uhb_supported: ultra high band channels supported
- * @min_ba_txq_size: minimum number of slots required in a TX queue which
- * based on hardware support (HE - 256, EHT - 1K).
+ * @eht_supported: EHT supported
* @num_rbds: number of receive buffer descriptors to use
* (only used for multi-queue capable devices)
*
@@ -358,60 +424,39 @@ struct iwl_fw_mon_regs {
* API differences in uCode shouldn't be handled here but through TLVs
* and/or the uCode API version instead.
*/
-struct iwl_cfg {
- struct iwl_cfg_trans_params trans;
+struct iwl_rf_cfg {
/* params specific to an individual device within a device family */
- const char *name;
const char *fw_name_pre;
- const char *fw_name_mac;
/* params likely to change within a device family */
- const struct iwl_ht_params *ht_params;
+ const struct iwl_ht_params ht_params;
const struct iwl_eeprom_params *eeprom_params;
const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
- const char *default_nvm_file_C_step;
const struct iwl_tt_params *thermal_params;
enum iwl_led_mode led_mode;
enum iwl_nvm_type nvm_type;
u32 max_data_size;
u32 max_inst_size;
- netdev_features_t features;
u32 dccm_offset;
u32 dccm_len;
u32 dccm2_offset;
u32 dccm2_len;
- u32 smem_offset;
- u32 smem_len;
u16 nvm_ver;
u16 nvm_calib_ver;
+ u16 bw_limit;
u32 rx_with_siso_diversity:1,
tx_with_siso_diversity:1,
internal_wimax_coex:1,
host_interrupt_operation_mode:1,
- high_temp:1,
- mac_addr_from_csr:10,
lp_xtal_workaround:1,
- apmg_not_supported:1,
vht_mu_mimo_supported:1,
- cdb:1,
- dbgc_supported:1,
- uhb_supported:1;
+ uhb_supported:1,
+ eht_supported:1;
u8 valid_tx_ant;
u8 valid_rx_ant;
u8 non_shared_ant;
- u8 nvm_hw_section_num;
- u8 max_tx_agg_size;
- u8 ucode_api_max;
- u8 ucode_api_min;
+ u16 ucode_api_max;
+ u16 ucode_api_min;
u16 num_rbds;
- u32 min_umac_error_event_table;
- u32 d3_debug_data_base_addr;
- u32 d3_debug_data_length;
- u32 min_txq_size;
- u32 gp2_reg_addr;
- u32 min_ba_txq_size;
- const struct iwl_fw_mon_regs mon_dram_regs;
- const struct iwl_fw_mon_regs mon_smem_regs;
- const struct iwl_fw_mon_regs mon_dbgi_regs;
};
#define IWL_CFG_ANY (~0)
@@ -419,8 +464,10 @@ struct iwl_cfg {
#define IWL_CFG_MAC_TYPE_PU 0x31
#define IWL_CFG_MAC_TYPE_TH 0x32
#define IWL_CFG_MAC_TYPE_QU 0x33
+#define IWL_CFG_MAC_TYPE_CC 0x34
#define IWL_CFG_MAC_TYPE_QUZ 0x35
#define IWL_CFG_MAC_TYPE_SO 0x37
+#define IWL_CFG_MAC_TYPE_TY 0x42
#define IWL_CFG_MAC_TYPE_SOF 0x43
#define IWL_CFG_MAC_TYPE_MA 0x44
#define IWL_CFG_MAC_TYPE_BZ 0x46
@@ -432,8 +479,6 @@ struct iwl_cfg {
#define IWL_CFG_MAC_TYPE_BR 0x4C
#define IWL_CFG_MAC_TYPE_DR 0x4D
-#define IWL_CFG_RF_TYPE_TH 0x105
-#define IWL_CFG_RF_TYPE_TH1 0x108
#define IWL_CFG_RF_TYPE_JF2 0x105
#define IWL_CFG_RF_TYPE_JF1 0x108
#define IWL_CFG_RF_TYPE_HR2 0x10A
@@ -451,12 +496,6 @@ struct iwl_cfg {
#define IWL_CFG_RF_ID_HR 0x7
#define IWL_CFG_RF_ID_HR1 0x4
-#define IWL_CFG_NO_160 0x1
-#define IWL_CFG_160 0x0
-
-#define IWL_CFG_NO_320 0x1
-#define IWL_CFG_320 0x0
-
#define IWL_CFG_CORES_BT 0x0
#define IWL_CFG_CORES_BT_GNSS 0x5
@@ -467,55 +506,134 @@ struct iwl_cfg {
#define IWL_CFG_IS_JACKET 0x1
#define IWL_SUBDEVICE_RF_ID(subdevice) ((u16)((subdevice) & 0x00F0) >> 4)
-#define IWL_SUBDEVICE_NO_160(subdevice) ((u16)((subdevice) & 0x0200) >> 9)
+#define IWL_SUBDEVICE_BW_LIM(subdevice) ((u16)((subdevice) & 0x0200) >> 9)
#define IWL_SUBDEVICE_CORES(subdevice) ((u16)((subdevice) & 0x1C00) >> 10)
struct iwl_dev_info {
+ const struct iwl_rf_cfg *cfg;
+ const char *name;
u16 device;
u16 subdevice;
- u16 mac_type;
- u16 rf_type;
- u8 mac_step;
- u8 rf_step;
- u8 rf_id;
- u8 no_160;
- u8 cores;
- u8 cdb;
- u8 jacket;
- const struct iwl_cfg *cfg;
- const char *name;
+ u32 subdevice_m_l:4,
+ subdevice_m_h:4,
+ match_rf_type:1,
+ rf_type:9,
+ match_bw_limit:1,
+ bw_limit:1,
+ match_discrete:1,
+ discrete:1,
+ match_rf_id:1,
+ rf_id:4,
+ match_cdb:1,
+ cdb:1;
};
#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
extern const struct iwl_dev_info iwl_dev_info_table[];
extern const unsigned int iwl_dev_info_table_size;
-const struct iwl_dev_info *
-iwl_pci_find_dev_info(u16 device, u16 subsystem_device,
- u16 mac_type, u8 mac_step, u16 rf_type, u8 cdb,
- u8 jacket, u8 rf_id, u8 no_160, u8 cores, u8 rf_step);
extern const struct pci_device_id iwl_hw_card_ids[];
#endif
+const struct iwl_dev_info *
+iwl_pci_find_dev_info(u16 device, u16 subsystem_device, u16 rf_type, u8 cdb,
+ u8 rf_id, u8 bw_limit, bool discrete);
+
/*
* This list declares the config structures for all devices.
*/
-extern const struct iwl_cfg_trans_params iwl9000_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl9560_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl9560_long_latency_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl9560_shared_clk_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl_qu_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl_qu_medium_latency_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl_qu_long_latency_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl_ax200_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl_so_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl_ma_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl_bz_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl_gl_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl_sc_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl_dr_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl_br_trans_cfg;
+extern const struct iwl_mac_cfg iwl1000_mac_cfg;
+extern const struct iwl_mac_cfg iwl5000_mac_cfg;
+extern const struct iwl_mac_cfg iwl2000_mac_cfg;
+extern const struct iwl_mac_cfg iwl2030_mac_cfg;
+extern const struct iwl_mac_cfg iwl105_mac_cfg;
+extern const struct iwl_mac_cfg iwl135_mac_cfg;
+extern const struct iwl_mac_cfg iwl5150_mac_cfg;
+extern const struct iwl_mac_cfg iwl6005_mac_cfg;
+extern const struct iwl_mac_cfg iwl6030_mac_cfg;
+extern const struct iwl_mac_cfg iwl6000i_mac_cfg;
+extern const struct iwl_mac_cfg iwl6050_mac_cfg;
+extern const struct iwl_mac_cfg iwl6150_mac_cfg;
+extern const struct iwl_mac_cfg iwl6000_mac_cfg;
+extern const struct iwl_mac_cfg iwl7000_mac_cfg;
+extern const struct iwl_mac_cfg iwl8000_mac_cfg;
+extern const struct iwl_mac_cfg iwl9000_mac_cfg;
+extern const struct iwl_mac_cfg iwl9560_mac_cfg;
+extern const struct iwl_mac_cfg iwl9560_long_latency_mac_cfg;
+extern const struct iwl_mac_cfg iwl9560_shared_clk_mac_cfg;
+extern const struct iwl_mac_cfg iwl_qu_mac_cfg;
+extern const struct iwl_mac_cfg iwl_qu_medium_latency_mac_cfg;
+extern const struct iwl_mac_cfg iwl_qu_long_latency_mac_cfg;
+extern const struct iwl_mac_cfg iwl_ax200_mac_cfg;
+extern const struct iwl_mac_cfg iwl_ty_mac_cfg;
+extern const struct iwl_mac_cfg iwl_so_mac_cfg;
+extern const struct iwl_mac_cfg iwl_so_long_latency_mac_cfg;
+extern const struct iwl_mac_cfg iwl_so_long_latency_imr_mac_cfg;
+extern const struct iwl_mac_cfg iwl_ma_mac_cfg;
+extern const struct iwl_mac_cfg iwl_bz_mac_cfg;
+extern const struct iwl_mac_cfg iwl_gl_mac_cfg;
+extern const struct iwl_mac_cfg iwl_sc_mac_cfg;
+extern const struct iwl_mac_cfg iwl_dr_mac_cfg;
+
+extern const char iwl1000_bgn_name[];
+extern const char iwl1000_bg_name[];
+extern const char iwl100_bgn_name[];
+extern const char iwl100_bg_name[];
+extern const char iwl2000_2bgn_name[];
+extern const char iwl2000_2bgn_d_name[];
+extern const char iwl2030_2bgn_name[];
+extern const char iwl105_bgn_name[];
+extern const char iwl105_bgn_d_name[];
+extern const char iwl135_bgn_name[];
+extern const char iwl5300_agn_name[];
+extern const char iwl5100_bgn_name[];
+extern const char iwl5100_abg_name[];
+extern const char iwl5100_agn_name[];
+extern const char iwl5350_agn_name[];
+extern const char iwl5150_agn_name[];
+extern const char iwl5150_abg_name[];
+extern const char iwl6005_2agn_name[];
+extern const char iwl6005_2abg_name[];
+extern const char iwl6005_2bg_name[];
+extern const char iwl6005_2agn_sff_name[];
+extern const char iwl6005_2agn_d_name[];
+extern const char iwl6005_2agn_mow1_name[];
+extern const char iwl6005_2agn_mow2_name[];
+extern const char iwl6030_2agn_name[];
+extern const char iwl6030_2abg_name[];
+extern const char iwl6030_2bgn_name[];
+extern const char iwl6030_2bg_name[];
+extern const char iwl6035_2agn_name[];
+extern const char iwl6035_2agn_sff_name[];
+extern const char iwl1030_bgn_name[];
+extern const char iwl1030_bg_name[];
+extern const char iwl130_bgn_name[];
+extern const char iwl130_bg_name[];
+extern const char iwl6000i_2agn_name[];
+extern const char iwl6000i_2abg_name[];
+extern const char iwl6000i_2bg_name[];
+extern const char iwl6050_2agn_name[];
+extern const char iwl6050_2abg_name[];
+extern const char iwl6150_bgn_name[];
+extern const char iwl6150_bg_name[];
+extern const char iwl6000_3agn_name[];
+extern const char iwl7260_2ac_name[];
+extern const char iwl7260_2n_name[];
+extern const char iwl7260_n_name[];
+extern const char iwl3160_2ac_name[];
+extern const char iwl3160_2n_name[];
+extern const char iwl3160_n_name[];
+extern const char iwl3165_2ac_name[];
+extern const char iwl3168_2ac_name[];
+extern const char iwl7265_2ac_name[];
+extern const char iwl7265_2n_name[];
+extern const char iwl7265_n_name[];
+extern const char iwl8260_2n_name[];
+extern const char iwl8260_2ac_name[];
+extern const char iwl8265_2ac_name[];
+extern const char iwl8275_2ac_name[];
+extern const char iwl4165_2ac_name[];
+extern const char iwl_killer_1435i_name[];
+extern const char iwl_killer_1434_kix_name[];
extern const char iwl9162_name[];
extern const char iwl9260_name[];
extern const char iwl9260_1_name[];
@@ -548,129 +666,87 @@ extern const char iwl_ax211_killer_1675s_name[];
extern const char iwl_ax211_killer_1675i_name[];
extern const char iwl_ax411_killer_1690s_name[];
extern const char iwl_ax411_killer_1690i_name[];
+extern const char iwl_ax210_name[];
extern const char iwl_ax211_name[];
-extern const char iwl_ax231_name[];
extern const char iwl_ax411_name[];
-extern const char iwl_fm_name[];
-extern const char iwl_wh_name[];
-extern const char iwl_gl_name[];
-extern const char iwl_mtp_name[];
-extern const char iwl_dr_name[];
-extern const char iwl_br_name[];
+extern const char iwl_killer_be1750s_name[];
+extern const char iwl_killer_be1750i_name[];
+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_be201_name[];
+extern const char iwl_be200_name[];
+extern const char iwl_be202_name[];
+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_be211_name[];
+extern const char iwl_killer_bn1850w2_name[];
+extern const char iwl_killer_bn1850i_name[];
+extern const char iwl_bn201_name[];
+extern const char iwl_bn203_name[];
+extern const char iwl_be221_name[];
+extern const char iwl_be223_name[];
+extern const char iwl_ax221_name[];
#if IS_ENABLED(CONFIG_IWLDVM)
-extern const struct iwl_cfg iwl5300_agn_cfg;
-extern const struct iwl_cfg iwl5100_agn_cfg;
-extern const struct iwl_cfg iwl5350_agn_cfg;
-extern const struct iwl_cfg iwl5100_bgn_cfg;
-extern const struct iwl_cfg iwl5100_abg_cfg;
-extern const struct iwl_cfg iwl5150_agn_cfg;
-extern const struct iwl_cfg iwl5150_abg_cfg;
-extern const struct iwl_cfg iwl6005_2agn_cfg;
-extern const struct iwl_cfg iwl6005_2abg_cfg;
-extern const struct iwl_cfg iwl6005_2bg_cfg;
-extern const struct iwl_cfg iwl6005_2agn_sff_cfg;
-extern const struct iwl_cfg iwl6005_2agn_d_cfg;
-extern const struct iwl_cfg iwl6005_2agn_mow1_cfg;
-extern const struct iwl_cfg iwl6005_2agn_mow2_cfg;
-extern const struct iwl_cfg iwl1030_bgn_cfg;
-extern const struct iwl_cfg iwl1030_bg_cfg;
-extern const struct iwl_cfg iwl6030_2agn_cfg;
-extern const struct iwl_cfg iwl6030_2abg_cfg;
-extern const struct iwl_cfg iwl6030_2bgn_cfg;
-extern const struct iwl_cfg iwl6030_2bg_cfg;
-extern const struct iwl_cfg iwl6000i_2agn_cfg;
-extern const struct iwl_cfg iwl6000i_2abg_cfg;
-extern const struct iwl_cfg iwl6000i_2bg_cfg;
-extern const struct iwl_cfg iwl6000_3agn_cfg;
-extern const struct iwl_cfg iwl6050_2agn_cfg;
-extern const struct iwl_cfg iwl6050_2abg_cfg;
-extern const struct iwl_cfg iwl6150_bgn_cfg;
-extern const struct iwl_cfg iwl6150_bg_cfg;
-extern const struct iwl_cfg iwl1000_bgn_cfg;
-extern const struct iwl_cfg iwl1000_bg_cfg;
-extern const struct iwl_cfg iwl100_bgn_cfg;
-extern const struct iwl_cfg iwl100_bg_cfg;
-extern const struct iwl_cfg iwl130_bgn_cfg;
-extern const struct iwl_cfg iwl130_bg_cfg;
-extern const struct iwl_cfg iwl2000_2bgn_cfg;
-extern const struct iwl_cfg iwl2000_2bgn_d_cfg;
-extern const struct iwl_cfg iwl2030_2bgn_cfg;
-extern const struct iwl_cfg iwl6035_2agn_cfg;
-extern const struct iwl_cfg iwl6035_2agn_sff_cfg;
-extern const struct iwl_cfg iwl105_bgn_cfg;
-extern const struct iwl_cfg iwl105_bgn_d_cfg;
-extern const struct iwl_cfg iwl135_bgn_cfg;
+extern const struct iwl_rf_cfg iwl5300_agn_cfg;
+extern const struct iwl_rf_cfg iwl5350_agn_cfg;
+extern const struct iwl_rf_cfg iwl5100_n_cfg;
+extern const struct iwl_rf_cfg iwl5100_abg_cfg;
+extern const struct iwl_rf_cfg iwl5150_agn_cfg;
+extern const struct iwl_rf_cfg iwl5150_abg_cfg;
+extern const struct iwl_rf_cfg iwl6005_non_n_cfg;
+extern const struct iwl_rf_cfg iwl6005_n_cfg;
+extern const struct iwl_rf_cfg iwl6030_n_cfg;
+extern const struct iwl_rf_cfg iwl6030_non_n_cfg;
+extern const struct iwl_rf_cfg iwl6000i_2agn_cfg;
+extern const struct iwl_rf_cfg iwl6000i_non_n_cfg;
+extern const struct iwl_rf_cfg iwl6000i_non_n_cfg;
+extern const struct iwl_rf_cfg iwl6000_3agn_cfg;
+extern const struct iwl_rf_cfg iwl6050_2agn_cfg;
+extern const struct iwl_rf_cfg iwl6050_2abg_cfg;
+extern const struct iwl_rf_cfg iwl6150_bgn_cfg;
+extern const struct iwl_rf_cfg iwl6150_bg_cfg;
+extern const struct iwl_rf_cfg iwl1000_bgn_cfg;
+extern const struct iwl_rf_cfg iwl1000_bg_cfg;
+extern const struct iwl_rf_cfg iwl100_bgn_cfg;
+extern const struct iwl_rf_cfg iwl100_bg_cfg;
+extern const struct iwl_rf_cfg iwl130_bgn_cfg;
+extern const struct iwl_rf_cfg iwl130_bg_cfg;
+extern const struct iwl_rf_cfg iwl2000_2bgn_cfg;
+extern const struct iwl_rf_cfg iwl2030_2bgn_cfg;
+extern const struct iwl_rf_cfg iwl6035_2agn_cfg;
+extern const struct iwl_rf_cfg iwl105_bgn_cfg;
+extern const struct iwl_rf_cfg iwl135_bgn_cfg;
#endif /* CONFIG_IWLDVM */
#if IS_ENABLED(CONFIG_IWLMVM)
-extern const struct iwl_ht_params iwl_22000_ht_params;
-extern const struct iwl_cfg iwl7260_2ac_cfg;
-extern const struct iwl_cfg iwl7260_2ac_cfg_high_temp;
-extern const struct iwl_cfg iwl7260_2n_cfg;
-extern const struct iwl_cfg iwl7260_n_cfg;
-extern const struct iwl_cfg iwl3160_2ac_cfg;
-extern const struct iwl_cfg iwl3160_2n_cfg;
-extern const struct iwl_cfg iwl3160_n_cfg;
-extern const struct iwl_cfg iwl3165_2ac_cfg;
-extern const struct iwl_cfg iwl3168_2ac_cfg;
-extern const struct iwl_cfg iwl7265_2ac_cfg;
-extern const struct iwl_cfg iwl7265_2n_cfg;
-extern const struct iwl_cfg iwl7265_n_cfg;
-extern const struct iwl_cfg iwl7265d_2ac_cfg;
-extern const struct iwl_cfg iwl7265d_2n_cfg;
-extern const struct iwl_cfg iwl7265d_n_cfg;
-extern const struct iwl_cfg iwl8260_2n_cfg;
-extern const struct iwl_cfg iwl8260_2ac_cfg;
-extern const struct iwl_cfg iwl8265_2ac_cfg;
-extern const struct iwl_cfg iwl8275_2ac_cfg;
-extern const struct iwl_cfg iwl4165_2ac_cfg;
-extern const struct iwl_cfg iwl9260_2ac_cfg;
-extern const struct iwl_cfg iwl9560_qu_b0_jf_b0_cfg;
-extern const struct iwl_cfg iwl9560_qu_c0_jf_b0_cfg;
-extern const struct iwl_cfg iwl9560_quz_a0_jf_b0_cfg;
-extern const struct iwl_cfg iwl9560_2ac_cfg_soc;
-extern const struct iwl_cfg iwl_qu_b0_hr1_b0;
-extern const struct iwl_cfg iwl_qu_c0_hr1_b0;
-extern const struct iwl_cfg iwl_quz_a0_hr1_b0;
-extern const struct iwl_cfg iwl_qu_b0_hr_b0;
-extern const struct iwl_cfg iwl_qu_c0_hr_b0;
-extern const struct iwl_cfg iwl_ax200_cfg_cc;
-extern const struct iwl_cfg iwl_ax201_cfg_qu_hr;
-extern const struct iwl_cfg iwl_ax201_cfg_qu_c0_hr_b0;
-extern const struct iwl_cfg iwl_ax201_cfg_quz_hr;
-extern const struct iwl_cfg iwl_ax1650i_cfg_quz_hr;
-extern const struct iwl_cfg iwl_ax1650s_cfg_quz_hr;
-extern const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0;
-extern const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0;
-extern const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0;
-extern const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0;
-extern const struct iwl_cfg killer1650x_2ax_cfg;
-extern const struct iwl_cfg killer1650w_2ax_cfg;
-extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0;
-extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0;
-extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long;
-extern const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0;
-extern const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0;
-extern const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0_long;
-
-extern const struct iwl_cfg iwl_cfg_ma;
-
-extern const struct iwl_cfg iwl_cfg_so_a0_hr_a0;
-extern const struct iwl_cfg iwl_cfg_quz_a0_hr_b0;
+extern const struct iwl_rf_cfg iwl7260_cfg;
+extern const struct iwl_rf_cfg iwl7260_high_temp_cfg;
+extern const struct iwl_rf_cfg iwl3160_cfg;
+extern const struct iwl_rf_cfg iwl3165_2ac_cfg;
+extern const struct iwl_rf_cfg iwl3168_2ac_cfg;
+extern const struct iwl_rf_cfg iwl7265_cfg;
+extern const struct iwl_rf_cfg iwl7265d_cfg;
+extern const struct iwl_rf_cfg iwl8260_cfg;
+extern const struct iwl_rf_cfg iwl8265_cfg;
+extern const struct iwl_rf_cfg iwl_rf_jf;
+extern const struct iwl_rf_cfg iwl_rf_jf_80mhz;
+extern const struct iwl_rf_cfg iwl_rf_hr1;
+extern const struct iwl_rf_cfg iwl_rf_hr;
+extern const struct iwl_rf_cfg iwl_rf_hr_80mhz;
+
+extern const struct iwl_rf_cfg iwl_rf_gf;
#endif /* CONFIG_IWLMVM */
#if IS_ENABLED(CONFIG_IWLMLD)
-extern const struct iwl_ht_params iwl_bz_ht_params;
-
-extern const struct iwl_ht_params iwl_bz_ht_params;
-
-extern const struct iwl_cfg iwl_cfg_bz;
-extern const struct iwl_cfg iwl_cfg_gl;
-
-extern const struct iwl_cfg iwl_cfg_sc;
-extern const struct iwl_cfg iwl_cfg_sc2;
-extern const struct iwl_cfg iwl_cfg_sc2f;
-extern const struct iwl_cfg iwl_cfg_dr;
-extern const struct iwl_cfg iwl_cfg_br;
+extern const struct iwl_rf_cfg iwl_rf_fm;
+extern const struct iwl_rf_cfg iwl_rf_fm_160mhz;
+#define iwl_rf_wh iwl_rf_fm
+#define iwl_rf_wh_160mhz iwl_rf_fm_160mhz
+extern const struct iwl_rf_cfg iwl_rf_wh_non_eht;
+#define iwl_rf_pe iwl_rf_fm
#endif /* CONFIG_IWLMLD */
#endif /* __IWL_CONFIG_H__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
index 3ff493e920d2..f3fa37fee2e4 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2016 Intel Deutschland GmbH
*/
@@ -107,6 +107,14 @@
/* GIO Chicken Bits (PCI Express bus link power management) */
#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
+#define CSR_IPC_STATE (CSR_BASE + 0x110)
+#define CSR_IPC_STATE_RESET 0x00000030
+#define CSR_IPC_STATE_RESET_NONE 0
+#define CSR_IPC_STATE_RESET_SW_READY 1
+#define CSR_IPC_STATE_RESET_TOP_READY 2
+#define CSR_IPC_STATE_RESET_TOP_FOLLOWER 3
+#define CSR_IPC_STATE_TOP_RESET_REQ BIT(6)
+
#define CSR_IPC_SLEEP_CONTROL (CSR_BASE + 0x114)
#define CSR_IPC_SLEEP_CONTROL_SUSPEND 0x3
#define CSR_IPC_SLEEP_CONTROL_RESUME 0
@@ -194,17 +202,19 @@
#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */
#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */
#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses */
+#define CSR_INT_BIT_RESET_DONE (1 << 2) /* reset handshake with firmware is done */
#define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */
#define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */
-#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \
- CSR_INT_BIT_HW_ERR | \
- CSR_INT_BIT_FH_TX | \
- CSR_INT_BIT_SW_ERR | \
- CSR_INT_BIT_RF_KILL | \
- CSR_INT_BIT_SW_RX | \
- CSR_INT_BIT_WAKEUP | \
- CSR_INT_BIT_ALIVE | \
+#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \
+ CSR_INT_BIT_HW_ERR | \
+ CSR_INT_BIT_FH_TX | \
+ CSR_INT_BIT_SW_ERR | \
+ CSR_INT_BIT_RF_KILL | \
+ CSR_INT_BIT_SW_RX | \
+ CSR_INT_BIT_WAKEUP | \
+ CSR_INT_BIT_RESET_DONE | \
+ CSR_INT_BIT_ALIVE | \
CSR_INT_BIT_RX_PERIODIC)
/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
@@ -641,7 +651,7 @@ enum msix_hw_int_causes {
* HW address related registers *
*****************************************************************************/
-#define CSR_ADDR_BASE(trans) ((trans)->cfg->mac_addr_from_csr)
+#define CSR_ADDR_BASE(trans) ((trans)->mac_cfg->base->mac_addr_from_csr)
#define CSR_MAC_ADDR0_OTP(trans) (CSR_ADDR_BASE(trans) + 0x00)
#define CSR_MAC_ADDR1_OTP(trans) (CSR_ADDR_BASE(trans) + 0x04)
#define CSR_MAC_ADDR0_STRAP(trans) (CSR_ADDR_BASE(trans) + 0x08)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
index ce787326aa69..5240dacf1360 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
@@ -503,7 +503,7 @@ void iwl_dbg_tlv_load_bin(struct device *dev, struct iwl_trans *trans)
int res;
if (!iwlwifi_mod_params.enable_ini ||
- trans->trans_cfg->device_family <= IWL_DEVICE_FAMILY_8000)
+ trans->mac_cfg->device_family <= IWL_DEVICE_FAMILY_8000)
return;
res = firmware_request_nowarn(&fw, yoyo_bin, dev);
@@ -603,11 +603,11 @@ static int iwl_dbg_tlv_alloc_fragments(struct iwl_fw_runtime *fwrt,
return 0;
num_frags = le32_to_cpu(fw_mon_cfg->max_frags_num);
- if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
+ if (fwrt->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
if (alloc_id != IWL_FW_INI_ALLOCATION_ID_DBGC1)
return -EIO;
num_frags = 1;
- } else if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ &&
+ } else if (fwrt->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ &&
alloc_id > IWL_FW_INI_ALLOCATION_ID_DBGC3) {
return -EIO;
}
@@ -949,7 +949,7 @@ static void iwl_dbg_tlv_apply_config(struct iwl_fw_runtime *fwrt,
static void iwl_dbg_tlv_periodic_trig_handler(struct timer_list *t)
{
struct iwl_dbg_tlv_timer_node *timer_node =
- from_timer(timer_node, t, timer);
+ timer_container_of(timer_node, t, timer);
struct iwl_fwrt_dump_data dump_data = {
.trig = (void *)timer_node->tlv->data,
};
@@ -1241,7 +1241,7 @@ iwl_dbg_tlv_tp_trigger(struct iwl_fw_runtime *fwrt, bool sync,
fwrt->trans->dbg.restart_required = false;
- if (fwrt->trans->trans_cfg->device_family ==
+ if (fwrt->trans->mac_cfg->device_family ==
IWL_DEVICE_FAMILY_9000) {
fwrt->trans->dbg.restart_required = true;
} else if (tp == IWL_FW_INI_TIME_POINT_FW_ASSERT &&
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h
index 7ed6329fd8ca..fe4e46a0edbd 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2018-2023 Intel Corporation
+ * Copyright (C) 2018-2023, 2025 Intel Corporation
*/
#ifndef __iwl_dbg_tlv_h__
#define __iwl_dbg_tlv_h__
@@ -32,7 +32,7 @@ union iwl_dbg_tlv_tp_data {
};
/**
- * struct iwl_dbg_tlv_time_point_data
+ * struct iwl_dbg_tlv_time_point_data - debug time point data
* @trig_list: list of triggers
* @active_trig_list: list of active triggers
* @hcmd_list: list of host commands
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h
index 76166e1b10e5..99789c7cef3b 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h
@@ -3,7 +3,7 @@
*
* Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
* Copyright(C) 2016 Intel Deutschland GmbH
- * Copyright(c) 2018, 2023 Intel Corporation
+ * Copyright(c) 2018, 2023, 2025 Intel Corporation
*****************************************************************************/
#ifndef __IWLWIFI_DEVICE_TRACE
@@ -54,11 +54,11 @@ static inline size_t iwl_rx_trace_len(const struct iwl_trans *trans,
struct ieee80211_hdr *hdr = NULL;
size_t hdr_offset;
- if (cmd->cmd != trans->rx_mpdu_cmd)
+ if (cmd->cmd != trans->conf.rx_mpdu_cmd)
return len;
hdr_offset = sizeof(struct iwl_cmd_header) +
- trans->rx_mpdu_cmd_hdr_size;
+ trans->conf.rx_mpdu_cmd_hdr_size;
if (out_hdr_offset)
*out_hdr_offset = hdr_offset;
@@ -67,7 +67,8 @@ static inline size_t iwl_rx_trace_len(const struct iwl_trans *trans,
if (!ieee80211_is_data(hdr->frame_control))
return len;
/* maybe try to identify EAPOL frames? */
- return sizeof(__le32) + sizeof(*cmd) + trans->rx_mpdu_cmd_hdr_size +
+ return sizeof(__le32) + sizeof(*cmd) +
+ trans->conf.rx_mpdu_cmd_hdr_size +
ieee80211_hdrlen(hdr->frame_control);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index d36837501e08..f8fc6f30fbe5 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -136,6 +136,9 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)
kfree(drv->fw.phy_integration_ver);
kfree(drv->trans->dbg.pc_data);
drv->trans->dbg.pc_data = NULL;
+ kvfree(drv->fw.pnvm_data);
+ drv->fw.pnvm_data = NULL;
+ drv->fw.pnvm_size = 0;
for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
iwl_free_fw_img(drv, drv->fw.img + i);
@@ -174,27 +177,88 @@ static inline char iwl_drv_get_step(int step)
return 'a' + step;
}
-static bool iwl_drv_is_wifi7_supported(struct iwl_trans *trans)
+bool iwl_drv_is_wifi7_supported(struct iwl_trans *trans)
{
- return CSR_HW_RFID_TYPE(trans->hw_rf_id) >= IWL_CFG_RF_TYPE_FM;
+ return trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ &&
+ CSR_HW_RFID_TYPE(trans->info.hw_rf_id) >= IWL_CFG_RF_TYPE_FM;
}
const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf)
{
char mac_step, rf_step;
- const char *rf, *cdb;
+ const char *mac, *rf, *cdb;
if (trans->cfg->fw_name_pre)
return trans->cfg->fw_name_pre;
- if (WARN_ON(!trans->cfg->fw_name_mac))
- return "unconfigured";
+ mac_step = iwl_drv_get_step(trans->info.hw_rev_step);
- mac_step = iwl_drv_get_step(trans->hw_rev_step);
+ switch (CSR_HW_REV_TYPE(trans->info.hw_rev)) {
+ case IWL_CFG_MAC_TYPE_PU:
+ mac = "9000-pu";
+ mac_step = 'b';
+ break;
+ case IWL_CFG_MAC_TYPE_TH:
+ mac = "9260-th";
+ mac_step = 'b';
+ break;
+ case IWL_CFG_MAC_TYPE_QU:
+ mac = "Qu";
+ break;
+ case IWL_CFG_MAC_TYPE_CC:
+ /* special case - no RF since it's fixed (discrete) */
+ scnprintf(buf, FW_NAME_PRE_BUFSIZE, "iwlwifi-cc-a0");
+ return buf;
+ case IWL_CFG_MAC_TYPE_QUZ:
+ mac = "QuZ";
+ /* all QuZ use A0 firmware */
+ mac_step = 'a';
+ break;
+ case IWL_CFG_MAC_TYPE_SO:
+ case IWL_CFG_MAC_TYPE_SOF:
+ mac = "so";
+ mac_step = 'a';
+ break;
+ case IWL_CFG_MAC_TYPE_TY:
+ mac = "ty";
+ mac_step = 'a';
+ break;
+ case IWL_CFG_MAC_TYPE_MA:
+ mac = "ma";
+ break;
+ case IWL_CFG_MAC_TYPE_BZ:
+ case IWL_CFG_MAC_TYPE_BZ_W:
+ mac = "bz";
+ break;
+ case IWL_CFG_MAC_TYPE_GL:
+ mac = "gl";
+ break;
+ case IWL_CFG_MAC_TYPE_SC:
+ mac = "sc";
+ break;
+ case IWL_CFG_MAC_TYPE_SC2:
+ /* Uses the same firmware as SC2 */
+ case IWL_CFG_MAC_TYPE_SC2F:
+ mac = "sc2";
+ break;
+ case IWL_CFG_MAC_TYPE_BR:
+ mac = "br";
+ break;
+ case IWL_CFG_MAC_TYPE_DR:
+ mac = "dr";
+ break;
+ default:
+ return "unknown-mac";
+ }
- rf_step = iwl_drv_get_step(CSR_HW_RFID_STEP(trans->hw_rf_id));
+ rf_step = iwl_drv_get_step(CSR_HW_RFID_STEP(trans->info.hw_rf_id));
- switch (CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
+ switch (CSR_HW_RFID_TYPE(trans->info.hw_rf_id)) {
+ case IWL_CFG_RF_TYPE_JF1:
+ case IWL_CFG_RF_TYPE_JF2:
+ rf = "jf";
+ rf_step = 'b';
+ break;
case IWL_CFG_RF_TYPE_HR1:
case IWL_CFG_RF_TYPE_HR2:
rf = "hr";
@@ -202,29 +266,26 @@ const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf)
break;
case IWL_CFG_RF_TYPE_GF:
rf = "gf";
+ rf_step = 'a';
break;
case IWL_CFG_RF_TYPE_FM:
rf = "fm";
break;
case IWL_CFG_RF_TYPE_WH:
- if (SILICON_Z_STEP ==
- CSR_HW_RFID_STEP(trans->hw_rf_id)) {
- rf = "whtc";
- rf_step = 'a';
- } else {
- rf = "wh";
- }
+ rf = "wh";
+ break;
+ case IWL_CFG_RF_TYPE_PE:
+ rf = "pe";
break;
default:
return "unknown-rf";
}
- cdb = CSR_HW_RFID_IS_CDB(trans->hw_rf_id) ? "4" : "";
+ cdb = CSR_HW_RFID_IS_CDB(trans->info.hw_rf_id) ? "4" : "";
scnprintf(buf, FW_NAME_PRE_BUFSIZE,
"iwlwifi-%s-%c0-%s%s-%c0",
- trans->cfg->fw_name_mac, mac_step,
- rf, cdb, rf_step);
+ mac, mac_step, rf, cdb, rf_step);
return buf;
}
@@ -233,39 +294,78 @@ IWL_EXPORT_SYMBOL(iwl_drv_get_fwname_pre);
static void iwl_req_fw_callback(const struct firmware *ucode_raw,
void *context);
+static void iwl_get_ucode_api_versions(struct iwl_trans *trans,
+ unsigned int *api_min,
+ unsigned int *api_max)
+{
+ const struct iwl_family_base_params *base = trans->mac_cfg->base;
+ const struct iwl_rf_cfg *cfg = trans->cfg;
+
+ /* if the MAC doesn't have range or if its range it higher than the RF's */
+ if (!base->ucode_api_max ||
+ (cfg->ucode_api_max && base->ucode_api_min > cfg->ucode_api_max)) {
+ *api_min = cfg->ucode_api_min;
+ *api_max = cfg->ucode_api_max;
+ return;
+ }
+
+ /* if the RF doesn't have range or if its range it higher than the MAC's */
+ if (!cfg->ucode_api_max ||
+ (base->ucode_api_max && cfg->ucode_api_min > base->ucode_api_max)) {
+ *api_min = base->ucode_api_min;
+ *api_max = base->ucode_api_max;
+ return;
+ }
+
+ *api_min = max(cfg->ucode_api_min, base->ucode_api_min);
+ *api_max = min(cfg->ucode_api_max, base->ucode_api_max);
+}
+
static int iwl_request_firmware(struct iwl_drv *drv, bool first)
{
- const struct iwl_cfg *cfg = drv->trans->cfg;
char _fw_name_pre[FW_NAME_PRE_BUFSIZE];
+ unsigned int ucode_api_max, ucode_api_min;
const char *fw_name_pre;
- if (drv->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
- (drv->trans->hw_rev_step != SILICON_B_STEP &&
- drv->trans->hw_rev_step != SILICON_C_STEP)) {
+ iwl_get_ucode_api_versions(drv->trans, &ucode_api_min, &ucode_api_max);
+
+ if (drv->trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
+ (drv->trans->info.hw_rev_step != SILICON_B_STEP &&
+ drv->trans->info.hw_rev_step != SILICON_C_STEP)) {
IWL_ERR(drv,
"Only HW steps B and C are currently supported (0x%0x)\n",
- drv->trans->hw_rev);
+ drv->trans->info.hw_rev);
+ return -EINVAL;
+ }
+
+ if (CSR_HW_RFID_TYPE(drv->trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_WH &&
+ CSR_HW_RFID_STEP(drv->trans->info.hw_rf_id) == SILICON_A_STEP) {
+ IWL_ERR(drv, "WH A step is not supported\n");
return -EINVAL;
}
fw_name_pre = iwl_drv_get_fwname_pre(drv->trans, _fw_name_pre);
if (first)
- drv->fw_index = cfg->ucode_api_max;
+ drv->fw_index = ucode_api_max;
+ else if (drv->fw_index == ENCODE_CORE_AS_API(100))
+ drv->fw_index = 102; /* last API-scheme number below core 100 */
else
drv->fw_index--;
- if (drv->fw_index < cfg->ucode_api_min) {
+ if (drv->fw_index < ucode_api_min) {
IWL_ERR(drv, "no suitable firmware found!\n");
- if (cfg->ucode_api_min == cfg->ucode_api_max) {
- IWL_ERR(drv, "%s-%d is required\n", fw_name_pre,
- cfg->ucode_api_max);
+ if (ucode_api_min == ucode_api_max) {
+ IWL_ERR(drv, "%s-" FW_API_FMT " is required\n",
+ fw_name_pre, FW_API_ARG(ucode_api_max));
} else {
- IWL_ERR(drv, "minimum version required: %s-%d\n",
- fw_name_pre, cfg->ucode_api_min);
- IWL_ERR(drv, "maximum version supported: %s-%d\n",
- fw_name_pre, cfg->ucode_api_max);
+ IWL_ERR(drv,
+ "minimum version required: %s-" FW_API_FMT "\n",
+ fw_name_pre, FW_API_ARG(ucode_api_min));
+ IWL_ERR(drv,
+ "maximum version supported: %s-" FW_API_FMT "\n",
+ fw_name_pre, FW_API_ARG(ucode_api_max));
}
IWL_ERR(drv,
@@ -273,8 +373,9 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
return -ENOENT;
}
- snprintf(drv->firmware_name, sizeof(drv->firmware_name), "%s-%d.ucode",
- fw_name_pre, drv->fw_index);
+ snprintf(drv->firmware_name, sizeof(drv->firmware_name),
+ "%s-" FW_API_FMT ".ucode",
+ fw_name_pre, FW_API_ARG(drv->fw_index));
IWL_DEBUG_FW_INFO(drv, "attempting to load firmware '%s'\n",
drv->firmware_name);
@@ -327,7 +428,6 @@ struct iwl_firmware_pieces {
size_t dbg_trigger_tlv_len[FW_DBG_TRIGGER_MAX];
struct iwl_fw_dbg_mem_seg_tlv *dbg_mem_tlv;
size_t n_mem_tlv;
- u32 major;
};
static void alloc_sec_data(struct iwl_firmware_pieces *pieces,
@@ -969,19 +1069,19 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
break;
case IWL_UCODE_TLV_FW_VERSION: {
const __le32 *ptr = (const void *)tlv_data;
- u32 minor;
+ u32 major, minor;
u8 local_comp;
if (tlv_len != sizeof(u32) * 3)
goto invalid_tlv_len;
- pieces->major = le32_to_cpup(ptr++);
+ major = le32_to_cpup(ptr++);
minor = le32_to_cpup(ptr++);
local_comp = le32_to_cpup(ptr);
snprintf(drv->fw.fw_version,
sizeof(drv->fw.fw_version),
- "%u.%08x.%u %s", pieces->major, minor,
+ "%u.%08x.%u %s", major, minor,
local_comp, iwl_reduced_fw_name(drv));
break;
}
@@ -1193,8 +1293,8 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
if (tlv_len != sizeof(*fseq_ver))
goto invalid_tlv_len;
- IWL_INFO(drv, "TLV_FW_FSEQ_VERSION: %.32s\n",
- fseq_ver->version);
+ IWL_DEBUG_INFO(drv, "TLV_FW_FSEQ_VERSION: %.32s\n",
+ fseq_ver->version);
}
break;
case IWL_UCODE_TLV_FW_NUM_STATIONS:
@@ -1235,7 +1335,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
if (tlv_len != sizeof(*dbg_ptrs))
goto invalid_tlv_len;
- if (drv->trans->trans_cfg->device_family <
+ if (drv->trans->mac_cfg->device_family <
IWL_DEVICE_FAMILY_22000)
break;
drv->trans->dbg.umac_error_event_table =
@@ -1251,7 +1351,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
if (tlv_len != sizeof(*dbg_ptrs))
goto invalid_tlv_len;
- if (drv->trans->trans_cfg->device_family <
+ if (drv->trans->mac_cfg->device_family <
IWL_DEVICE_FAMILY_22000)
break;
drv->trans->dbg.lmac_error_event_table[0] =
@@ -1317,6 +1417,15 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
drv->trans->dbg.num_pc =
tlv_len / sizeof(struct iwl_pc_data);
break;
+ case IWL_UCODE_TLV_PNVM_DATA:
+ if (drv->fw.pnvm_data)
+ break;
+ drv->fw.pnvm_data =
+ kvmemdup(tlv_data, tlv_len, GFP_KERNEL);
+ if (!drv->fw.pnvm_data)
+ return -ENOMEM;
+ drv->fw.pnvm_size = tlv_len;
+ break;
default:
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
break;
@@ -1373,7 +1482,7 @@ static int iwl_alloc_ucode(struct iwl_drv *drv,
static int validate_sec_sizes(struct iwl_drv *drv,
struct iwl_firmware_pieces *pieces,
- const struct iwl_cfg *cfg)
+ const struct iwl_rf_cfg *cfg)
{
IWL_DEBUG_INFO(drv, "f/w package hdr runtime inst size = %zd\n",
get_sec_size(pieces, IWL_UCODE_REGULAR,
@@ -1446,7 +1555,7 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
if (!IS_ERR(op_mode))
return op_mode;
- if (test_bit(STATUS_TRANS_DEAD, &drv->trans->status))
+ if (iwl_trans_is_dead(drv->trans))
break;
#ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -1480,8 +1589,6 @@ static void _iwl_op_mode_stop(struct iwl_drv *drv)
}
}
-#define IWL_MLD_SUPPORTED_FW_VERSION 97
-
/*
* iwl_req_fw_callback - callback when firmware was loaded
*
@@ -1490,20 +1597,22 @@ static void _iwl_op_mode_stop(struct iwl_drv *drv)
*/
static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
{
+ int min_core, max_core, loaded_core;
struct iwl_drv *drv = context;
struct iwl_fw *fw = &drv->fw;
const struct iwl_ucode_header *ucode;
struct iwlwifi_opmode_table *op;
int err;
struct iwl_firmware_pieces *pieces;
- const unsigned int api_max = drv->trans->cfg->ucode_api_max;
- const unsigned int api_min = drv->trans->cfg->ucode_api_min;
+ unsigned int api_min, api_max;
size_t trigger_tlv_sz[FW_DBG_TRIGGER_MAX];
u32 api_ver;
int i;
bool usniffer_images = false;
bool failure = true;
+ iwl_get_ucode_api_versions(drv->trans, &api_min, &api_max);
+
fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH;
fw->ucode_capa.standard_phy_calibration_size =
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
@@ -1551,11 +1660,24 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
* firmware filename ... but we don't check for that and only rely
* on the API version read from firmware header from here on forward
*/
- if (api_ver < api_min || api_ver > api_max) {
+
+ /*
+ * if -cN.ucode file was loaded, core version == file version,
+ * otherwise core version == file version (API version) - 3
+ */
+ if (iwl_api_is_core_number(drv->fw_index))
+ loaded_core = api_ver;
+ else
+ loaded_core = api_ver - API_TO_CORE_OFFS;
+
+ min_core = iwl_api_to_core(api_min);
+ max_core = iwl_api_to_core(api_max);
+
+ if (loaded_core < min_core || loaded_core > max_core) {
IWL_ERR(drv,
"Driver unable to support your firmware API. "
- "Driver supports v%u, firmware is v%u.\n",
- api_max, api_ver);
+ "Driver supports FW core %d..%d, firmware is %d.\n",
+ min_core, max_core, loaded_core);
goto try_again;
}
@@ -1697,14 +1819,14 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
fw->init_evtlog_size = (pieces->init_evtlog_size - 16)/12;
else
fw->init_evtlog_size =
- drv->trans->trans_cfg->base_params->max_event_log_size;
+ drv->trans->mac_cfg->base->max_event_log_size;
fw->init_errlog_ptr = pieces->init_errlog_ptr;
fw->inst_evtlog_ptr = pieces->inst_evtlog_ptr;
if (pieces->inst_evtlog_size)
fw->inst_evtlog_size = (pieces->inst_evtlog_size - 16)/12;
else
fw->inst_evtlog_size =
- drv->trans->trans_cfg->base_params->max_event_log_size;
+ drv->trans->mac_cfg->base->max_event_log_size;
fw->inst_errlog_ptr = pieces->inst_errlog_ptr;
/*
@@ -1735,17 +1857,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
}
#if IS_ENABLED(CONFIG_IWLMLD)
- if (pieces->major >= IWL_MLD_SUPPORTED_FW_VERSION &&
- iwl_drv_is_wifi7_supported(drv->trans))
+ if (iwl_drv_is_wifi7_supported(drv->trans))
op = &iwlwifi_opmode_table[MLD_OP_MODE];
-#else
- if (pieces->major >= IWL_MLD_SUPPORTED_FW_VERSION &&
- iwl_drv_is_wifi7_supported(drv->trans)) {
- IWL_ERR(drv,
- "IWLMLD needs to be compiled to support this firmware\n");
- mutex_unlock(&iwlwifi_opmode_table_mtx);
- goto out_unbind;
- }
#endif
IWL_INFO(drv, "loaded firmware version %s op_mode %s\n",
@@ -1953,8 +2066,6 @@ static int __init iwl_drv_init(void)
for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++)
INIT_LIST_HEAD(&iwlwifi_opmode_table[i].drv);
- pr_info(DRV_DESCRIPTION "\n");
-
#ifdef CONFIG_IWLWIFI_DEBUGFS
/* Create the root of iwlwifi debugfs subsystem. */
iwl_dbgfs_root = debugfs_create_dir(DRV_NAME, NULL);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
index 854957bdf79d..6e60953de2ec 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2020-2021, 2023 Intel Corporation
+ * Copyright (C) 2005-2014, 2020-2021, 2023, 2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
*/
#ifndef __iwl_drv_h__
@@ -53,7 +53,7 @@
struct iwl_drv;
struct iwl_trans;
-struct iwl_cfg;
+struct iwl_rf_cfg;
/**
* iwl_drv_start - start the drv
*
@@ -62,7 +62,8 @@ struct iwl_cfg;
* starts the driver: fetches the firmware. This should be called by bus
* specific system flows implementations. For example, the bus specific probe
* function should do bus related operations only, and then call to this
- * function. It returns the driver object or %NULL if an error occurred.
+ * function.
+ * Return: the driver object or %NULL if an error occurred.
*/
struct iwl_drv *iwl_drv_start(struct iwl_trans *trans);
@@ -78,6 +79,12 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans);
void iwl_drv_stop(struct iwl_drv *drv);
/*
+ * iwl_drv_is_wifi7_supported - returns if wifi7 is supported
+ * If yes, iwlmld needs to be used to drive the device.
+ */
+bool iwl_drv_is_wifi7_supported(struct iwl_trans *trans);
+
+/*
* exported symbol management
*
* The driver can be split into multiple modules, in which case some symbols
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h
index 5c8f1868db64..0f6de08b7473 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2018-2021, 2023-2024 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2021, 2023-2025 Intel Corporation
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fh_h__
@@ -71,7 +71,7 @@
static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
unsigned int chnl)
{
- if (trans->trans_cfg->gen2) {
+ if (trans->mac_cfg->gen2) {
WARN_ON_ONCE(chnl >= 64);
return TFH_TFDQ_CBB_TABLE + 8 * chnl;
}
@@ -378,14 +378,14 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
* Once the RXF-to-DRAM DMA is active, this flag is immediately turned off.
*/
#define RFH_GEN_STATUS 0xA09808
-#define RFH_GEN_STATUS_GEN3 0xA07824
+#define RFH_GEN_STATUS_AX210 0xA07824
#define RBD_FETCH_IDLE BIT(29)
#define SRAM_DMA_IDLE BIT(30)
#define RXF_DMA_IDLE BIT(31)
/* DMA configuration */
#define RFH_RXF_DMA_CFG 0xA09820
-#define RFH_RXF_DMA_CFG_GEN3 0xA07880
+#define RFH_RXF_DMA_CFG_AX210 0xA07880
/* RB size */
#define RFH_RXF_DMA_RB_SIZE_MASK (0x000F0000) /* bits 16-19 */
#define RFH_RXF_DMA_RB_SIZE_POS 16
@@ -588,13 +588,12 @@ struct iwl_rb_status {
#define TFD_QUEUE_SIZE_MAX (256)
-#define TFD_QUEUE_SIZE_MAX_GEN3 (65536)
/* cb size is the exponent - 3 */
#define TFD_QUEUE_CB_SIZE(x) (ilog2(x) - 3)
#define TFD_QUEUE_SIZE_BC_DUP (64)
#define TFD_QUEUE_BC_SIZE (TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP)
-#define TFD_QUEUE_BC_SIZE_GEN3_AX210 1024
-#define TFD_QUEUE_BC_SIZE_GEN3_BZ (1024 * 4)
+#define TFD_QUEUE_BC_SIZE_AX210 1024
+#define TFD_QUEUE_BC_SIZE_BZ (1024 * 4)
#define IWL_TX_DMA_MASK DMA_BIT_MASK(36)
#define IWL_NUM_OF_TBS 20
#define IWL_TFH_NUM_TBS 25
@@ -717,30 +716,19 @@ struct iwl_tfh_tfd {
/* Fixed (non-configurable) rx data from phy */
/**
- * struct iwlagn_scd_bc_tbl - scheduler byte count table
+ * struct iwl_bc_tbl_entry - scheduler byte count table entry
* base physical address provided by SCD_DRAM_BASE_ADDR
* For devices up to 22000:
* @tfd_offset:
* For devices up to 22000:
* 0-12 - tx command byte count
* 12-16 - station index
- * For 22000:
+ * For 22000 and on:
* 0-12 - tx command byte count
* 12-13 - number of 64 byte chunks
* 14-16 - reserved
*/
-struct iwlagn_scd_bc_tbl {
- __le16 tfd_offset[TFD_QUEUE_BC_SIZE];
-} __packed;
-
-/**
- * struct iwl_gen3_bc_tbl_entry - scheduler byte count table entry gen3
- * For AX210 and on:
- * @tfd_offset: 0-12 - tx command byte count
- * 12-13 - number of 64 byte chunks
- * 14-16 - reserved
- */
-struct iwl_gen3_bc_tbl_entry {
+struct iwl_bc_tbl_entry {
__le16 tfd_offset;
} __packed;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c
index 0653ca8b974a..b1944584c693 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c
@@ -1,9 +1,8 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2003-2014, 2018-2022, 2024 Intel Corporation
+ * Copyright (C) 2003-2014, 2018-2022, 2024-2025 Intel Corporation
* Copyright (C) 2015-2016 Intel Deutschland GmbH
*/
-#include <linux/delay.h>
#include <linux/device.h>
#include <linux/export.h>
@@ -13,6 +12,7 @@
#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)
{
@@ -47,21 +47,21 @@ IWL_EXPORT_SYMBOL(iwl_read32);
#define IWL_POLL_INTERVAL 10 /* microseconds */
-int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
- u32 bits, u32 mask, int timeout)
+int iwl_poll_bits_mask(struct iwl_trans *trans, u32 addr,
+ u32 bits, u32 mask, int timeout)
{
int t = 0;
do {
if ((iwl_read32(trans, addr) & mask) == (bits & mask))
- return t;
+ return 0;
udelay(IWL_POLL_INTERVAL);
t += IWL_POLL_INTERVAL;
} while (t < timeout);
return -ETIMEDOUT;
}
-IWL_EXPORT_SYMBOL(iwl_poll_bit);
+IWL_EXPORT_SYMBOL(iwl_poll_bits_mask);
u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
{
@@ -75,7 +75,6 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
/* return as if we have a HW timeout/failure */
return 0x5a5a5a5a;
}
-IWL_EXPORT_SYMBOL(iwl_read_direct32);
void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
{
@@ -93,7 +92,6 @@ void iwl_write_direct64(struct iwl_trans *trans, u64 reg, u64 value)
iwl_trans_release_nic_access(trans);
}
}
-IWL_EXPORT_SYMBOL(iwl_write_direct64);
int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
int timeout)
@@ -109,7 +107,6 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
return -ETIMEDOUT;
}
-IWL_EXPORT_SYMBOL(iwl_poll_direct_bit);
u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs)
{
@@ -117,14 +114,12 @@ u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs)
trace_iwlwifi_dev_ioread_prph32(trans->dev, ofs, val);
return val;
}
-IWL_EXPORT_SYMBOL(iwl_read_prph_no_grab);
void iwl_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val)
{
trace_iwlwifi_dev_iowrite_prph32(trans->dev, ofs, val);
iwl_trans_write_prph(trans, ofs, val);
}
-IWL_EXPORT_SYMBOL(iwl_write_prph_no_grab);
void iwl_write_prph64_no_grab(struct iwl_trans *trans, u64 ofs, u64 val)
{
@@ -132,7 +127,6 @@ void iwl_write_prph64_no_grab(struct iwl_trans *trans, u64 ofs, u64 val)
iwl_write_prph_no_grab(trans, ofs, val & 0xffffffff);
iwl_write_prph_no_grab(trans, ofs + 4, val >> 32);
}
-IWL_EXPORT_SYMBOL(iwl_write_prph64_no_grab);
u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
{
@@ -166,7 +160,7 @@ int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr,
do {
if ((iwl_read_prph(trans, addr) & mask) == (bits & mask))
- return t;
+ return 0;
udelay(IWL_POLL_INTERVAL);
t += IWL_POLL_INTERVAL;
} while (t < timeout);
@@ -211,13 +205,13 @@ IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);
void iwl_force_nmi(struct iwl_trans *trans)
{
- if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000)
+ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_9000)
iwl_write_prph_delay(trans, DEVICE_SET_NMI_REG,
DEVICE_SET_NMI_VAL_DRV, 1);
- else if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER,
UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER);
- else if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
+ else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
UREG_DOORBELL_TO_ISR6_NMI_BIT);
else
@@ -260,7 +254,7 @@ struct reg {
static int iwl_dump_rfh(struct iwl_trans *trans, char **buf)
{
int i, q;
- int num_q = trans->num_rx_queues;
+ int num_q = trans->info.num_rxqs;
static const u32 rfh_tbl[] = {
RFH_RXF_DMA_CFG,
RFH_GEN_CFG,
@@ -368,7 +362,7 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf)
FH_TSSR_TX_ERROR_REG
};
- if (trans->trans_cfg->mq_rx_supported)
+ if (trans->mac_cfg->mq_rx_supported)
return iwl_dump_rfh(trans, buf);
#ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -402,96 +396,11 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf)
return 0;
}
-#define IWL_HOST_MON_BLOCK_PEMON 0x00
-#define IWL_HOST_MON_BLOCK_HIPM 0x22
-
-#define IWL_HOST_MON_BLOCK_PEMON_VEC0 0x00
-#define IWL_HOST_MON_BLOCK_PEMON_VEC1 0x01
-#define IWL_HOST_MON_BLOCK_PEMON_WFPM 0x06
-
-static void iwl_dump_host_monitor_block(struct iwl_trans *trans,
- u32 block, u32 vec, u32 iter)
-{
- int i;
-
- IWL_ERR(trans, "Host monitor block 0x%x vector 0x%x\n", block, vec);
- iwl_write32(trans, CSR_MONITOR_CFG_REG, (block << 8) | vec);
- for (i = 0; i < iter; i++)
- IWL_ERR(trans, " value [iter %d]: 0x%08x\n",
- i, iwl_read32(trans, CSR_MONITOR_STATUS_REG));
-}
-
-static void iwl_dump_host_monitor(struct iwl_trans *trans)
-{
- switch (trans->trans_cfg->device_family) {
- case IWL_DEVICE_FAMILY_22000:
- case IWL_DEVICE_FAMILY_AX210:
- IWL_ERR(trans, "CSR_RESET = 0x%x\n",
- iwl_read32(trans, CSR_RESET));
- iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON,
- IWL_HOST_MON_BLOCK_PEMON_VEC0, 15);
- iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON,
- IWL_HOST_MON_BLOCK_PEMON_VEC1, 15);
- iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON,
- IWL_HOST_MON_BLOCK_PEMON_WFPM, 15);
- iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_HIPM,
- IWL_HOST_MON_BLOCK_PEMON_VEC0, 1);
- break;
- default:
- /* not supported yet */
- return;
- }
-}
-
-int iwl_finish_nic_init(struct iwl_trans *trans)
+int iwl_trans_activate_nic(struct iwl_trans *trans)
{
- const struct iwl_cfg_trans_params *cfg_trans = trans->trans_cfg;
- u32 poll_ready;
- int err;
-
- if (cfg_trans->bisr_workaround) {
- /* ensure the TOP FSM isn't still in previous reset */
- mdelay(2);
- }
-
- /*
- * Set "initialization complete" bit to move adapter from
- * D0U* --> D0A* (powered-up active) state.
- */
- if (cfg_trans->device_family >= IWL_DEVICE_FAMILY_BZ) {
- iwl_set_bit(trans, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ |
- CSR_GP_CNTRL_REG_FLAG_MAC_INIT);
- poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_STATUS;
- } else {
- iwl_set_bit(trans, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
- poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY;
- }
-
- if (cfg_trans->device_family == IWL_DEVICE_FAMILY_8000)
- udelay(2);
-
- /*
- * Wait for clock stabilization; once stabilized, access to
- * device-internal resources is supported, e.g. iwl_write_prph()
- * and accesses to uCode SRAM.
- */
- err = iwl_poll_bit(trans, CSR_GP_CNTRL, poll_ready, poll_ready, 25000);
- if (err < 0) {
- IWL_DEBUG_INFO(trans, "Failed to wake NIC\n");
-
- iwl_dump_host_monitor(trans);
- }
-
- if (cfg_trans->bisr_workaround) {
- /* ensure BISR shift has finished */
- udelay(200);
- }
-
- return err < 0 ? err : 0;
+ return iwl_pcie_gen1_2_activate_nic(trans);
}
-IWL_EXPORT_SYMBOL(iwl_finish_nic_init);
+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 37b3bd62897e..5bcec239ffc4 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2018-2021 Intel Corporation
+ * Copyright (C) 2018-2021, 2025 Intel Corporation
*/
#ifndef __iwl_io_h__
#define __iwl_io_h__
@@ -23,8 +23,13 @@ static inline void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
iwl_trans_set_bits_mask(trans, reg, mask, 0);
}
-int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
- u32 bits, u32 mask, int timeout);
+int iwl_poll_bits_mask(struct iwl_trans *trans, u32 addr,
+ u32 bits, u32 mask, int timeout);
+static inline int iwl_poll_bits(struct iwl_trans *trans, u32 addr, u32 bits,
+ int timeout)
+{
+ return iwl_poll_bits_mask(trans, addr, bits, bits, timeout);
+}
int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
int timeout);
@@ -52,7 +57,7 @@ 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_finish_nic_init(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);
@@ -64,38 +69,38 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf);
*/
static inline u32 iwl_umac_prph(struct iwl_trans *trans, u32 ofs)
{
- return ofs + trans->trans_cfg->umac_prph_offset;
+ return ofs + trans->mac_cfg->umac_prph_offset;
}
static inline u32 iwl_read_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs)
{
return iwl_read_prph_no_grab(trans, ofs +
- trans->trans_cfg->umac_prph_offset);
+ trans->mac_cfg->umac_prph_offset);
}
static inline u32 iwl_read_umac_prph(struct iwl_trans *trans, u32 ofs)
{
- return iwl_read_prph(trans, ofs + trans->trans_cfg->umac_prph_offset);
+ return iwl_read_prph(trans, ofs + trans->mac_cfg->umac_prph_offset);
}
static inline void iwl_write_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs,
u32 val)
{
- iwl_write_prph_no_grab(trans, ofs + trans->trans_cfg->umac_prph_offset,
+ iwl_write_prph_no_grab(trans, ofs + trans->mac_cfg->umac_prph_offset,
val);
}
static inline void iwl_write_umac_prph(struct iwl_trans *trans, u32 ofs,
u32 val)
{
- iwl_write_prph(trans, ofs + trans->trans_cfg->umac_prph_offset, val);
+ iwl_write_prph(trans, ofs + trans->mac_cfg->umac_prph_offset, val);
}
static inline int iwl_poll_umac_prph_bit(struct iwl_trans *trans, u32 addr,
u32 bits, u32 mask, int timeout)
{
return iwl_poll_prph_bit(trans, addr +
- trans->trans_cfg->umac_prph_offset,
+ trans->mac_cfg->umac_prph_offset,
bits, mask, timeout);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h
index 21eabfc3ffc8..0476df7b7f17 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2018-2022, 2024 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2022, 2024-2025 Intel Corporation
*/
#ifndef __iwl_modparams_h__
#define __iwl_modparams_h__
@@ -42,7 +42,7 @@ enum iwl_uapsd_disable {
};
/**
- * struct iwl_mod_params
+ * struct iwl_mod_params - module parameters for iwlwifi
*
* Holds the module parameters
*
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index c381511e9ec6..e021fc57d85d 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -1,10 +1,11 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2005-2014, 2018-2023 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2023, 2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#include <linux/types.h>
+#include <linux/fips.h>
#include <linux/slab.h>
#include <linux/export.h>
#include <linux/etherdevice.h>
@@ -139,43 +140,6 @@ static struct ieee80211_rate iwl_cfg80211_rates[] = {
#define N_RATES_52 (N_RATES_24 - RATES_52_OFFS)
/**
- * enum iwl_nvm_channel_flags - channel flags in NVM
- * @NVM_CHANNEL_VALID: channel is usable for this SKU/geo
- * @NVM_CHANNEL_IBSS: usable as an IBSS channel and deprecated
- * when %IWL_NVM_SBANDS_FLAGS_LAR enabled.
- * @NVM_CHANNEL_ACTIVE: active scanning allowed and allows IBSS
- * when %IWL_NVM_SBANDS_FLAGS_LAR enabled.
- * @NVM_CHANNEL_RADAR: radar detection required
- * @NVM_CHANNEL_INDOOR_ONLY: only indoor use is allowed
- * @NVM_CHANNEL_GO_CONCURRENT: GO operation is allowed when connected to BSS
- * on same channel on 2.4 or same UNII band on 5.2
- * @NVM_CHANNEL_UNIFORM: uniform spreading required
- * @NVM_CHANNEL_20MHZ: 20 MHz channel okay
- * @NVM_CHANNEL_40MHZ: 40 MHz channel okay
- * @NVM_CHANNEL_80MHZ: 80 MHz channel okay
- * @NVM_CHANNEL_160MHZ: 160 MHz channel okay
- * @NVM_CHANNEL_DC_HIGH: DC HIGH required/allowed (?)
- * @NVM_CHANNEL_VLP: client support connection to UHB VLP AP
- * @NVM_CHANNEL_AFC: client support connection to UHB AFC AP
- */
-enum iwl_nvm_channel_flags {
- NVM_CHANNEL_VALID = BIT(0),
- NVM_CHANNEL_IBSS = BIT(1),
- NVM_CHANNEL_ACTIVE = BIT(3),
- NVM_CHANNEL_RADAR = BIT(4),
- NVM_CHANNEL_INDOOR_ONLY = BIT(5),
- NVM_CHANNEL_GO_CONCURRENT = BIT(6),
- NVM_CHANNEL_UNIFORM = BIT(7),
- NVM_CHANNEL_20MHZ = BIT(8),
- NVM_CHANNEL_40MHZ = BIT(9),
- NVM_CHANNEL_80MHZ = BIT(10),
- NVM_CHANNEL_160MHZ = BIT(11),
- NVM_CHANNEL_DC_HIGH = BIT(12),
- NVM_CHANNEL_VLP = BIT(13),
- NVM_CHANNEL_AFC = BIT(14),
-};
-
-/**
* enum iwl_reg_capa_flags_v1 - global flags applied for the whole regulatory
* domain.
* @REG_CAPA_V1_BF_CCD_LOW_BAND: Beam-forming or Cyclic Delay Diversity in the
@@ -274,30 +238,6 @@ enum iwl_reg_capa_flags_v4 {
*/
#define REG_CAPA_V4_RESP_VER 8
-/**
- * struct iwl_reg_capa - struct for global regulatory capabilities, Used for
- * handling the different APIs of reg_capa_flags.
- *
- * @allow_40mhz: 11n channel with a width of 40Mhz is allowed
- * for this regulatory domain.
- * @allow_80mhz: 11ac channel with a width of 80Mhz is allowed
- * for this regulatory domain (valid only in 5 and 6 Ghz).
- * @allow_160mhz: 11ac channel with a width of 160Mhz is allowed
- * for this regulatory domain (valid only in 5 and 6 Ghz).
- * @allow_320mhz: 11be channel with a width of 320Mhz is allowed
- * for this regulatory domain (valid only in 6 Ghz).
- * @disable_11ax: 11ax is forbidden for this regulatory domain.
- * @disable_11be: 11be is forbidden for this regulatory domain.
- */
-struct iwl_reg_capa {
- bool allow_40mhz;
- bool allow_80mhz;
- bool allow_160mhz;
- bool allow_320mhz;
- bool disable_11ax;
- bool disable_11be;
-};
-
static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
int chan, u32 flags)
{
@@ -332,7 +272,7 @@ static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
}
static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, enum nl80211_band band,
- u32 nvm_flags, const struct iwl_cfg *cfg)
+ u32 nvm_flags, const struct iwl_rf_cfg *cfg)
{
u32 flags = IEEE80211_CHAN_NO_HT40;
@@ -399,7 +339,7 @@ static int iwl_init_channel_map(struct iwl_trans *trans,
const void * const nvm_ch_flags,
u32 sbands_flags, bool v4)
{
- const struct iwl_cfg *cfg = trans->cfg;
+ const struct iwl_rf_cfg *cfg = trans->cfg;
struct device *dev = trans->dev;
int ch_idx;
int n_channels = 0;
@@ -500,7 +440,7 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans,
struct ieee80211_sta_vht_cap *vht_cap,
u8 tx_chains, u8 rx_chains)
{
- const struct iwl_cfg *cfg = trans->cfg;
+ const struct iwl_rf_cfg *cfg = trans->cfg;
int num_rx_ants = num_of_ant(rx_chains);
int num_tx_ants = num_of_ant(tx_chains);
@@ -513,7 +453,7 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans,
IEEE80211_VHT_MAX_AMPDU_1024K <<
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
- if (!trans->cfg->ht_params->stbc)
+ if (!trans->cfg->ht_params.stbc)
vht_cap->cap &= ~IEEE80211_VHT_CAP_RXSTBC_MASK;
if (data->vht160_supported)
@@ -523,7 +463,7 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans,
if (cfg->vht_mu_mimo_supported)
vht_cap->cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
- if (cfg->ht_params->ldpc)
+ if (cfg->ht_params.ldpc)
vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC;
if (data->sku_cap_mimo_disabled) {
@@ -531,21 +471,27 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans,
num_tx_ants = 1;
}
- if (trans->cfg->ht_params->stbc && num_tx_ants > 1)
+ if (trans->cfg->ht_params.stbc && num_tx_ants > 1)
vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC;
else
vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
+ /*
+ * With fips_enabled crypto is done by software, so the HW cannot
+ * split up A-MSDUs and the real limit that was set applies.
+ * Note that EHT doesn't honour this (HE copies the VHT value),
+ * but EHT is also entirely disabled for fips_enabled.
+ */
switch (iwlwifi_mod_params.amsdu_size) {
case IWL_AMSDU_DEF:
- if (trans->trans_cfg->mq_rx_supported)
+ if (trans->mac_cfg->mq_rx_supported && !fips_enabled)
vht_cap->cap |=
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
else
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
break;
case IWL_AMSDU_2K:
- if (trans->trans_cfg->mq_rx_supported)
+ if (trans->mac_cfg->mq_rx_supported && !fips_enabled)
vht_cap->cap |=
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
else
@@ -656,6 +602,8 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
.phy_cap_info[9] =
IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB |
+ IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
+ IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU |
(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED <<
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_POS),
.phy_cap_info[10] =
@@ -684,44 +632,26 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
.has_eht = true,
.eht_cap_elem = {
.mac_cap_info[0] =
- IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
- IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
- IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
- IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2 |
- IEEE80211_EHT_MAC_CAP0_SCS_TRAFFIC_DESC,
- .mac_cap_info[1] =
- IEEE80211_EHT_MAC_CAP1_UNSOL_EPCS_PRIO_ACCESS,
+ IEEE80211_EHT_MAC_CAP0_OM_CONTROL,
.phy_cap_info[0] =
IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ |
IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI |
- IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO |
IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE |
IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK,
.phy_cap_info[1] =
IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK |
IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK,
.phy_cap_info[3] =
- IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK |
- IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |
- IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK |
- IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK |
- IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK |
- IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK |
- IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK,
+ IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK,
.phy_cap_info[4] =
- IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO |
- IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP |
IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI,
.phy_cap_info[5] =
FIELD_PREP_CONST(IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK,
IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US) |
- IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK |
IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP |
- IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP,
- .phy_cap_info[6] =
- IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK |
- IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP,
+ IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP |
+ IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF,
.phy_cap_info[8] =
IEEE80211_EHT_PHY_CAP8_RX_1024QAM_WIDER_BW_DL_OFDMA |
IEEE80211_EHT_PHY_CAP8_RX_4096QAM_WIDER_BW_DL_OFDMA,
@@ -789,6 +719,7 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |
IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242,
.phy_cap_info[9] =
+ IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED
<< IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_POS,
},
@@ -815,9 +746,7 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
.has_eht = true,
.eht_cap_elem = {
.mac_cap_info[0] =
- IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
- IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
- IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2,
+ IEEE80211_EHT_MAC_CAP0_OM_CONTROL,
.phy_cap_info[0] =
IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ |
IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI,
@@ -916,10 +845,12 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
{
bool is_ap = iftype_data->types_mask & (BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_GO));
- bool slow_pcie = (!trans->trans_cfg->integrated &&
- trans->pcie_link_speed < PCI_EXP_LNKSTA_CLS_8_0GB);
+ bool slow_pcie = (!trans->mac_cfg->integrated &&
+ trans->info.pcie_link_speed < PCI_EXP_LNKSTA_CLS_8_0GB);
- if (!data->sku_cap_11be_enable || iwlwifi_mod_params.disable_11be)
+ /* EHT needs WPA3/MFP so cannot do it for fips_enabled */
+ if (!data->sku_cap_11be_enable || iwlwifi_mod_params.disable_11be ||
+ fips_enabled)
iftype_data->eht_cap.has_eht = false;
/* Advertise an A-MPDU exponent extension based on
@@ -944,7 +875,8 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK);
break;
case NL80211_BAND_6GHZ:
- if (!trans->reduced_cap_sku) {
+ if (!trans->reduced_cap_sku &&
+ (!trans->cfg->bw_limit || trans->cfg->bw_limit >= 320)) {
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[0] |=
IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[1] |=
@@ -1031,58 +963,24 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << 2);
}
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210 && !is_ap)
+ /* prior RFs don't have HE, HR RF doesn't have this, later have it */
+ if (CSR_HW_RFID_TYPE(trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_HR1 ||
+ CSR_HW_RFID_TYPE(trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_HR2)
+ iftype_data->he_cap.he_cap_elem.phy_cap_info[9] &=
+ ~(IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
+ IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU);
+
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210 && !is_ap)
iftype_data->he_cap.he_cap_elem.phy_cap_info[2] |=
IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO;
- switch (CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
- case IWL_CFG_RF_TYPE_GF:
- case IWL_CFG_RF_TYPE_FM:
- case IWL_CFG_RF_TYPE_WH:
- iftype_data->he_cap.he_cap_elem.phy_cap_info[9] |=
- IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
- if (!is_ap)
- iftype_data->he_cap.he_cap_elem.phy_cap_info[9] |=
- IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
- break;
- }
-
- if (CSR_HW_REV_TYPE(trans->hw_rev) == IWL_CFG_MAC_TYPE_GL &&
- iftype_data->eht_cap.has_eht) {
- iftype_data->eht_cap.eht_cap_elem.mac_cap_info[0] &=
- ~(IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 |
- IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2);
- iftype_data->eht_cap.eht_cap_elem.phy_cap_info[3] &=
- ~(IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO |
- IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK |
- IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |
- IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK |
- IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK |
- IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK |
- IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK);
- iftype_data->eht_cap.eht_cap_elem.phy_cap_info[4] &=
- ~(IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO |
- IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP);
- iftype_data->eht_cap.eht_cap_elem.phy_cap_info[5] &=
- ~IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK;
- iftype_data->eht_cap.eht_cap_elem.phy_cap_info[6] &=
- ~(IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK |
- IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP);
- iftype_data->eht_cap.eht_cap_elem.phy_cap_info[5] |=
- IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF;
- }
-
- if (fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_BROADCAST_TWT))
- iftype_data->he_cap.he_cap_elem.mac_cap_info[2] |=
- IEEE80211_HE_MAC_CAP2_BCAST_TWT;
-
- if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
+ if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
!is_ap) {
iftype_data->vendor_elems.data = iwl_vendor_caps;
iftype_data->vendor_elems.len = ARRAY_SIZE(iwl_vendor_caps);
}
- if (!trans->cfg->ht_params->stbc) {
+ if (!trans->cfg->ht_params.stbc) {
iftype_data->he_cap.he_cap_elem.phy_cap_info[2] &=
~IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;
iftype_data->he_cap.he_cap_elem.phy_cap_info[7] &=
@@ -1094,19 +992,23 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
iftype_data->eht_cap.eht_mcs_nss_supp.bw._320.rx_tx_mcs13_max_nss = 0;
}
- if (trans->no_160)
+ if (trans->cfg->bw_limit && trans->cfg->bw_limit < 160)
iftype_data->he_cap.he_cap_elem.phy_cap_info[0] &=
~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
- if (trans->reduced_cap_sku) {
+ if ((trans->cfg->bw_limit && trans->cfg->bw_limit < 320) ||
+ trans->reduced_cap_sku) {
memset(&iftype_data->eht_cap.eht_mcs_nss_supp.bw._320, 0,
sizeof(iftype_data->eht_cap.eht_mcs_nss_supp.bw._320));
+ iftype_data->eht_cap.eht_cap_elem.phy_cap_info[2] &=
+ ~IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK;
+ }
+
+ if (trans->reduced_cap_sku) {
iftype_data->eht_cap.eht_mcs_nss_supp.bw._80.rx_tx_mcs13_max_nss = 0;
iftype_data->eht_cap.eht_mcs_nss_supp.bw._160.rx_tx_mcs13_max_nss = 0;
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[8] &=
~IEEE80211_EHT_PHY_CAP8_RX_4096QAM_WIDER_BW_DL_OFDMA;
- iftype_data->eht_cap.eht_cap_elem.phy_cap_info[2] &=
- ~IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK;
}
}
@@ -1232,17 +1134,25 @@ static void iwl_init_sbands(struct iwl_trans *trans,
n_used += iwl_init_sband_channels(data, sband, n_channels,
NL80211_BAND_6GHZ);
- if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax)
+ /*
+ * 6 GHz requires WPA3 which requires MFP, which FW cannot do
+ * when fips_enabled, so don't advertise any 6 GHz channels to
+ * avoid spending time on scanning those channels and perhaps
+ * even finding APs there that cannot be used.
+ */
+ if (!fips_enabled && data->sku_cap_11ax_enable &&
+ !iwlwifi_mod_params.disable_11ax)
iwl_init_he_hw_capab(trans, data, sband, tx_chains, rx_chains,
fw);
else
sband->n_channels = 0;
+
if (n_channels != n_used)
IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n",
n_used, n_channels);
}
-static int iwl_get_sku(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
+static int iwl_get_sku(const struct iwl_rf_cfg *cfg, const __le16 *nvm_sw,
const __le16 *phy_sku)
{
if (cfg->nvm_type != IWL_NVM_EXT)
@@ -1251,7 +1161,7 @@ static int iwl_get_sku(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
return le32_to_cpup((const __le32 *)(phy_sku + SKU_FAMILY_8000));
}
-static int iwl_get_nvm_version(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
+static int iwl_get_nvm_version(const struct iwl_rf_cfg *cfg, const __le16 *nvm_sw)
{
if (cfg->nvm_type != IWL_NVM_EXT)
return le16_to_cpup(nvm_sw + NVM_VERSION);
@@ -1260,7 +1170,7 @@ static int iwl_get_nvm_version(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
NVM_VERSION_EXT_NVM));
}
-static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
+static int iwl_get_radio_cfg(const struct iwl_rf_cfg *cfg, const __le16 *nvm_sw,
const __le16 *phy_sku)
{
if (cfg->nvm_type != IWL_NVM_EXT)
@@ -1270,7 +1180,7 @@ static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
}
-static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
+static int iwl_get_n_hw_addrs(const struct iwl_rf_cfg *cfg, const __le16 *nvm_sw)
{
int n_hw_addr;
@@ -1282,7 +1192,7 @@ static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
return n_hw_addr & N_HW_ADDR_MASK;
}
-static void iwl_set_radio_cfg(const struct iwl_cfg *cfg,
+static void iwl_set_radio_cfg(const struct iwl_rf_cfg *cfg,
struct iwl_nvm_data *data,
u32 radio_cfg)
{
@@ -1341,7 +1251,7 @@ static void iwl_set_hw_address_from_csr(struct iwl_trans *trans,
}
static void iwl_set_hw_address_family_8000(struct iwl_trans *trans,
- const struct iwl_cfg *cfg,
+ const struct iwl_rf_cfg *cfg,
struct iwl_nvm_data *data,
const __le16 *mac_override,
const __be16 *nvm_hw)
@@ -1390,11 +1300,12 @@ static void iwl_set_hw_address_family_8000(struct iwl_trans *trans,
}
static int iwl_set_hw_address(struct iwl_trans *trans,
- const struct iwl_cfg *cfg,
+ const struct iwl_rf_cfg *cfg,
struct iwl_nvm_data *data, const __be16 *nvm_hw,
const __le16 *mac_override)
{
- if (cfg->mac_addr_from_csr) {
+ const struct iwl_mac_cfg *mac_cfg = trans->mac_cfg;
+ if (mac_cfg->base->mac_addr_from_csr) {
iwl_set_hw_address_from_csr(trans, data);
} else if (cfg->nvm_type != IWL_NVM_EXT) {
const u8 *hw_addr = (const u8 *)(nvm_hw + HW_ADDR);
@@ -1424,7 +1335,7 @@ static int iwl_set_hw_address(struct iwl_trans *trans,
}
static bool
-iwl_nvm_no_wide_in_5ghz(struct iwl_trans *trans, const struct iwl_cfg *cfg,
+iwl_nvm_no_wide_in_5ghz(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
const __be16 *nvm_hw)
{
/*
@@ -1436,7 +1347,7 @@ iwl_nvm_no_wide_in_5ghz(struct iwl_trans *trans, const struct iwl_cfg *cfg,
* in 5GHz otherwise the FW will throw a sysassert when we try
* to use them.
*/
- if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
+ if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
/*
* Unlike the other sections in the NVM, the hw
* section uses big-endian.
@@ -1456,7 +1367,7 @@ iwl_nvm_no_wide_in_5ghz(struct iwl_trans *trans, const struct iwl_cfg *cfg,
}
struct iwl_nvm_data *
-iwl_parse_mei_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
+iwl_parse_mei_nvm_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
const struct iwl_mei_nvm *mei_nvm,
const struct iwl_fw *fw, u8 tx_ant, u8 rx_ant)
{
@@ -1520,7 +1431,7 @@ iwl_parse_mei_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
IWL_EXPORT_SYMBOL(iwl_parse_mei_nvm_data);
struct iwl_nvm_data *
-iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
+iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
const struct iwl_fw *fw,
const __be16 *nvm_hw, const __le16 *nvm_sw,
const __le16 *nvm_calib, const __le16 *regulatory,
@@ -1617,10 +1528,10 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
}
IWL_EXPORT_SYMBOL(iwl_parse_nvm_data);
-static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
- int ch_idx, u16 nvm_flags,
- struct iwl_reg_capa reg_capa,
- const struct iwl_cfg *cfg)
+VISIBLE_IF_IWLWIFI_KUNIT
+u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
+ int ch_idx, u16 nvm_flags,
+ struct iwl_reg_capa reg_capa)
{
u32 flags = NL80211_RRF_NO_HT40;
@@ -1655,6 +1566,10 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
if (nvm_flags & NVM_CHANNEL_INDOOR_ONLY)
flags |= NL80211_RRF_NO_OUTDOOR;
+ if (nvm_flags & NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY &&
+ flags & NL80211_RRF_NO_IR)
+ flags |= NL80211_RRF_ALLOW_20MHZ_ACTIVITY;
+
/* Set the GO concurrent flag only in case that NO_IR is set.
* Otherwise it is meaningless
*/
@@ -1671,10 +1586,12 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
}
/* Set the AP type for the UHB case. */
- if (nvm_flags & NVM_CHANNEL_VLP)
- flags |= NL80211_RRF_ALLOW_6GHZ_VLP_AP;
- else
+ if (nvm_flags & NVM_CHANNEL_VLP) {
+ if (!(nvm_flags & NVM_CHANNEL_VLP_AP_NOT_ALLOWED))
+ flags |= NL80211_RRF_ALLOW_6GHZ_VLP_AP;
+ } else {
flags |= NL80211_RRF_NO_6GHZ_VLP_CLIENT;
+ }
if (!(nvm_flags & NVM_CHANNEL_AFC))
flags |= NL80211_RRF_NO_6GHZ_AFC_CLIENT;
@@ -1704,6 +1621,7 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
return flags;
}
+EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_nvm_get_regdom_bw_flags);
static struct iwl_reg_capa iwl_get_reg_capa(u32 flags, u8 resp_ver)
{
@@ -1731,10 +1649,12 @@ static struct iwl_reg_capa iwl_get_reg_capa(u32 flags, u8 resp_ver)
}
struct ieee80211_regdomain *
-iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
+iwl_parse_nvm_mcc_info(struct iwl_trans *trans,
int num_of_ch, __le32 *channels, u16 fw_mcc,
u16 geo_info, u32 cap, u8 resp_ver)
{
+ const struct iwl_rf_cfg *cfg = trans->cfg;
+ struct device *dev = trans->dev;
int ch_idx;
u16 ch_flags;
u32 reg_rule_flags, prev_reg_rule_flags = 0;
@@ -1799,8 +1719,8 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
}
reg_rule_flags = iwl_nvm_get_regdom_bw_flags(nvm_chan, ch_idx,
- ch_flags, reg_capa,
- cfg);
+ ch_flags,
+ reg_capa);
/* we can't continue the same rule */
if (ch_idx == 0 || prev_reg_rule_flags != reg_rule_flags ||
@@ -1989,8 +1909,8 @@ int iwl_read_external_nvm(struct iwl_trans *trans,
le32_to_cpu(dword_buff[3]));
/* nvm file validation, dword_buff[2] holds the file version */
- if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
- trans->hw_rev_step == SILICON_C_STEP &&
+ if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
+ trans->info.hw_rev_step == SILICON_C_STEP &&
le32_to_cpu(dword_buff[2]) < 0xE4A) {
ret = -EFAULT;
goto out;
@@ -2057,7 +1977,7 @@ int iwl_read_external_nvm(struct iwl_trans *trans,
break;
}
- iwl_nvm_fixups(trans->hw_id, section_id, temp, section_size);
+ iwl_nvm_fixups(trans->info.hw_id, section_id, temp, section_size);
kfree(nvm_sections[section_id].data);
nvm_sections[section_id].data = temp;
@@ -2160,7 +2080,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
!!(mac_flags & NVM_MAC_SKU_FLAGS_BAND_5_2_ENABLED);
nvm->sku_cap_mimo_disabled =
!!(mac_flags & NVM_MAC_SKU_FLAGS_MIMO_DISABLED);
- if (CSR_HW_RFID_TYPE(trans->hw_rf_id) >= IWL_CFG_RF_TYPE_FM)
+ if (trans->cfg->eht_supported)
nvm->sku_cap_11be_enable = true;
/* Initialize PHY sku data */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h
index 0c6c3fb8c6dd..12f28bb0e859 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2015, 2018-2024 Intel Corporation
+ * Copyright (C) 2005-2015, 2018-2025 Intel Corporation
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_nvm_parse_h__
@@ -21,6 +21,80 @@ enum iwl_nvm_sbands_flags {
IWL_NVM_SBANDS_FLAGS_NO_WIDE_IN_5GHZ = BIT(1),
};
+/**
+ * struct iwl_reg_capa - struct for global regulatory capabilities, Used for
+ * handling the different APIs of reg_capa_flags.
+ *
+ * @allow_40mhz: 11n channel with a width of 40Mhz is allowed
+ * for this regulatory domain.
+ * @allow_80mhz: 11ac channel with a width of 80Mhz is allowed
+ * for this regulatory domain (valid only in 5 and 6 Ghz).
+ * @allow_160mhz: 11ac channel with a width of 160Mhz is allowed
+ * for this regulatory domain (valid only in 5 and 6 Ghz).
+ * @allow_320mhz: 11be channel with a width of 320Mhz is allowed
+ * for this regulatory domain (valid only in 6 Ghz).
+ * @disable_11ax: 11ax is forbidden for this regulatory domain.
+ * @disable_11be: 11be is forbidden for this regulatory domain.
+ */
+struct iwl_reg_capa {
+ bool allow_40mhz;
+ bool allow_80mhz;
+ bool allow_160mhz;
+ bool allow_320mhz;
+ bool disable_11ax;
+ bool disable_11be;
+};
+
+/**
+ * enum iwl_nvm_channel_flags - channel flags in NVM
+ * @NVM_CHANNEL_VALID: channel is usable for this SKU/geo
+ * @NVM_CHANNEL_IBSS: usable as an IBSS channel and deprecated
+ * when %IWL_NVM_SBANDS_FLAGS_LAR enabled.
+ * @NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY: active scanning allowed and
+ * AP allowed only in 20 MHz. Valid only
+ * when %IWL_NVM_SBANDS_FLAGS_LAR enabled.
+ * @NVM_CHANNEL_ACTIVE: active scanning allowed and allows IBSS
+ * when %IWL_NVM_SBANDS_FLAGS_LAR enabled.
+ * @NVM_CHANNEL_RADAR: radar detection required
+ * @NVM_CHANNEL_INDOOR_ONLY: only indoor use is allowed
+ * @NVM_CHANNEL_GO_CONCURRENT: GO operation is allowed when connected to BSS
+ * on same channel on 2.4 or same UNII band on 5.2
+ * @NVM_CHANNEL_UNIFORM: uniform spreading required
+ * @NVM_CHANNEL_20MHZ: 20 MHz channel okay
+ * @NVM_CHANNEL_40MHZ: 40 MHz channel okay
+ * @NVM_CHANNEL_80MHZ: 80 MHz channel okay
+ * @NVM_CHANNEL_160MHZ: 160 MHz channel okay
+ * @NVM_CHANNEL_DC_HIGH: DC HIGH required/allowed (?)
+ * @NVM_CHANNEL_VLP: client support connection to UHB VLP AP
+ * @NVM_CHANNEL_AFC: client support connection to UHB AFC AP
+ * @NVM_CHANNEL_VLP_AP_NOT_ALLOWED: UHB VLP AP not allowed,
+ * Valid only when %NVM_CHANNEL_VLP is enabled.
+ */
+enum iwl_nvm_channel_flags {
+ NVM_CHANNEL_VALID = BIT(0),
+ NVM_CHANNEL_IBSS = BIT(1),
+ NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY = BIT(2),
+ NVM_CHANNEL_ACTIVE = BIT(3),
+ NVM_CHANNEL_RADAR = BIT(4),
+ NVM_CHANNEL_INDOOR_ONLY = BIT(5),
+ NVM_CHANNEL_GO_CONCURRENT = BIT(6),
+ NVM_CHANNEL_UNIFORM = BIT(7),
+ NVM_CHANNEL_20MHZ = BIT(8),
+ NVM_CHANNEL_40MHZ = BIT(9),
+ NVM_CHANNEL_80MHZ = BIT(10),
+ NVM_CHANNEL_160MHZ = BIT(11),
+ NVM_CHANNEL_DC_HIGH = BIT(12),
+ NVM_CHANNEL_VLP = BIT(13),
+ NVM_CHANNEL_AFC = BIT(14),
+ NVM_CHANNEL_VLP_AP_NOT_ALLOWED = BIT(15),
+};
+
+#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
+u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
+ int ch_idx, u16 nvm_flags,
+ struct iwl_reg_capa reg_capa);
+#endif
+
/*
* iwl_parse_nvm_data - parse NVM data and return values
*
@@ -30,7 +104,7 @@ enum iwl_nvm_sbands_flags {
* later with iwl_free_nvm_data().
*/
struct iwl_nvm_data *
-iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
+iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
const struct iwl_fw *fw,
const __be16 *nvm_hw, const __le16 *nvm_sw,
const __le16 *nvm_calib, const __le16 *regulatory,
@@ -41,14 +115,23 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
* iwl_parse_nvm_mcc_info - parse MCC (mobile country code) info coming from FW
*
* This function parses the regulatory channel data received as a
- * MCC_UPDATE_CMD command. It returns a newly allocation regulatory domain,
- * to be fed into the regulatory core. In case the geo_info is set handle
- * accordingly. An ERR_PTR is returned on error.
- * If not given to the regulatory core, the user is responsible for freeing
- * the regdomain returned here with kfree.
+ * MCC_UPDATE_CMD command.
+ *
+ * Return: a newly allocation regulatory domain, to be given to the regulatory
+ * core. In case the geo_info is set handle accordingly. An ERR_PTR is
+ * returned on error. If not given to the regulatory core, the user is
+ * responsible for freeing the regdomain returned here with kfree().
+ *
+ * @trans: the transport
+ * @num_of_ch: the number of channels
+ * @channels: channel map
+ * @fw_mcc: firmware country code
+ * @geo_info: geo info value
+ * @cap: capability
+ * @resp_ver: FW response version
*/
struct ieee80211_regdomain *
-iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
+iwl_parse_nvm_mcc_info(struct iwl_trans *trans,
int num_of_ch, __le32 *channels, u16 fw_mcc,
u16 geo_info, u32 cap, u8 resp_ver);
@@ -58,6 +141,8 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
* This struct holds an NVM section read from the NIC using NVM_ACCESS_CMD,
* and saved for later use by the driver. Not all NVM sections are saved
* this way, only the needed ones.
+ * @length: length of the section
+ * @data: section data
*/
struct iwl_nvm_section {
u16 length;
@@ -66,6 +151,10 @@ struct iwl_nvm_section {
/**
* iwl_read_external_nvm - Reads external NVM from a file into nvm_sections
+ * @trans: the transport
+ * @nvm_file_name: the filename to request
+ * @nvm_sections: sections data to fill
+ * Return: 0 on success or an error code
*/
int iwl_read_external_nvm(struct iwl_trans *trans,
const char *nvm_file_name,
@@ -87,7 +176,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
* iwl_parse_mei_nvm_data - parse the mei_nvm_data and get an iwl_nvm_data
*/
struct iwl_nvm_data *
-iwl_parse_mei_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
+iwl_parse_mei_nvm_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
const struct iwl_mei_nvm *mei_nvm,
const struct iwl_fw *fw, u8 set_tx_ant, u8 set_rx_ant);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-utils.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-utils.c
index b3c25acd3691..ec312c90ff85 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-utils.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2005-2014, 2018-2021, 2023 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2021, 2023, 2025 Intel Corporation
* Copyright (C) 2015 Intel Mobile Communications GmbH
*/
#include <linux/types.h>
@@ -42,7 +42,7 @@ void iwl_init_ht_hw_capab(struct iwl_trans *trans,
enum nl80211_band band,
u8 tx_chains, u8 rx_chains)
{
- const struct iwl_cfg *cfg = trans->cfg;
+ const struct iwl_rf_cfg *cfg = trans->cfg;
int max_bit_rate = 0;
tx_chains = hweight8(tx_chains);
@@ -53,7 +53,8 @@ void iwl_init_ht_hw_capab(struct iwl_trans *trans,
if (!(data->sku_cap_11n_enable) ||
(iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL) ||
- !cfg->ht_params) {
+ /* there are no devices with HT but without HT40 entirely */
+ !cfg->ht_params.ht40_bands) {
ht_info->ht_supported = false;
return;
}
@@ -64,17 +65,17 @@ void iwl_init_ht_hw_capab(struct iwl_trans *trans,
ht_info->ht_supported = true;
ht_info->cap = IEEE80211_HT_CAP_DSSSCCK40;
- if (cfg->ht_params->stbc) {
+ if (cfg->ht_params.stbc) {
ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
if (tx_chains > 1)
ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
}
- if (cfg->ht_params->ldpc)
+ if (cfg->ht_params.ldpc)
ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
- if (trans->trans_cfg->mq_rx_supported ||
+ if (trans->mac_cfg->mq_rx_supported ||
iwlwifi_mod_params.amsdu_size >= IWL_AMSDU_8K)
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
@@ -90,13 +91,13 @@ void iwl_init_ht_hw_capab(struct iwl_trans *trans,
if (rx_chains >= 3)
ht_info->mcs.rx_mask[2] = 0xFF;
- if (cfg->ht_params->ht_greenfield_support)
+ if (cfg->ht_params.ht_greenfield_support)
ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
max_bit_rate = MAX_BIT_RATE_20_MHZ;
- if (cfg->ht_params->ht40_bands & BIT(band)) {
+ if (cfg->ht_params.ht40_bands & BIT(band)) {
ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
max_bit_rate = MAX_BIT_RATE_40_MHZ;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h
index 34eca1a568ea..df6341dfc4a1 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2018-2021, 2024 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2021, 2024-2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015 Intel Deutschland GmbH
*/
@@ -17,7 +17,7 @@ struct sk_buff;
struct iwl_device_cmd;
struct iwl_rx_cmd_buffer;
struct iwl_fw;
-struct iwl_cfg;
+struct iwl_rf_cfg;
/**
* DOC: Operational mode - what is it ?
@@ -52,12 +52,20 @@ struct iwl_cfg;
* any debug collection must happen synchronously as
* the device will be shut down
* @IWL_ERR_TYPE_CMD_QUEUE_FULL: command queue was full
+ * @IWL_ERR_TYPE_TOP_RESET_BY_BT: TOP reset initiated by BT
+ * @IWL_ERR_TYPE_TOP_FATAL_ERROR: TOP fatal error
+ * @IWL_ERR_TYPE_TOP_RESET_FAILED: TOP reset failed
+ * @IWL_ERR_TYPE_DEBUGFS: error/reset indication from debugfs
*/
enum iwl_fw_error_type {
IWL_ERR_TYPE_IRQ,
IWL_ERR_TYPE_NMI_FORCED,
IWL_ERR_TYPE_RESET_HS_TIMEOUT,
IWL_ERR_TYPE_CMD_QUEUE_FULL,
+ IWL_ERR_TYPE_TOP_RESET_BY_BT,
+ IWL_ERR_TYPE_TOP_FATAL_ERROR,
+ IWL_ERR_TYPE_TOP_RESET_FAILED,
+ IWL_ERR_TYPE_DEBUGFS,
};
/**
@@ -139,10 +147,12 @@ struct iwl_fw_error_dump_mode {
* Op_mode needs to reset its internal state because the device did not
* survive the system state transition. The firmware is no longer running,
* etc...
+ * @dump: Op_mode needs to collect the firmware dump upon this handler
+ * being called.
*/
struct iwl_op_mode_ops {
struct iwl_op_mode *(*start)(struct iwl_trans *trans,
- const struct iwl_cfg *cfg,
+ const struct iwl_rf_cfg *cfg,
const struct iwl_fw *fw,
struct dentry *dbgfs_dir);
void (*stop)(struct iwl_op_mode *op_mode);
@@ -166,6 +176,7 @@ struct iwl_op_mode_ops {
enum iwl_fw_ini_time_point tp_id,
union iwl_dbg_tlv_tp_data *tp_data);
void (*device_powered_off)(struct iwl_op_mode *op_mode);
+ void (*dump)(struct iwl_op_mode *op_mode);
};
int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops);
@@ -174,6 +185,7 @@ void iwl_opmode_deregister(const char *name);
/**
* struct iwl_op_mode - operational mode
* @ops: pointer to its own ops
+ * @op_mode_specific: per-opmode data
*
* This holds an implementation of the mac80211 / fw API.
*/
@@ -242,6 +254,9 @@ static inline void iwl_op_mode_dump_error(struct iwl_op_mode *op_mode,
{
might_sleep();
+ if (WARN_ON(mode->type == IWL_ERR_TYPE_TOP_RESET_BY_BT))
+ return;
+
if (op_mode->ops->dump_error)
op_mode->ops->dump_error(op_mode, mode);
}
@@ -275,4 +290,11 @@ static inline void iwl_op_mode_device_powered_off(struct iwl_op_mode *op_mode)
op_mode->ops->device_powered_off(op_mode);
}
+static inline void iwl_op_mode_dump(struct iwl_op_mode *op_mode)
+{
+ if (!op_mode || !op_mode->ops || !op_mode->ops->dump)
+ return;
+ op_mode->ops->dump(op_mode);
+}
+
#endif /* __iwl_op_mode_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
index 23b2009fbb28..a7214ddcfaf5 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016 Intel Deutschland GmbH
*/
@@ -514,6 +514,14 @@ enum {
#define WMAL_INDRCT_CMD(addr) \
((WMAL_CMD_READ_BURST_ACCESS << WMAL_INDRCT_RD_CMD1_OPMOD_POS) | \
((addr) & WMAL_INDRCT_RD_CMD1_BYTE_ADDRESS_MSK))
+#define WMAL_MRSPF_STTS 0xADFC24
+#define WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_POS 15
+#define WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_MSK 0x8000
+#define WMAL_TIMEOUT_VAL 0xA5A5A5A2
+#define WMAL_MRSPF_STTS_IS_FIFO1_NOT_EMPTY(val) \
+ (((val) >> (WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_POS)) & \
+ ((WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_MSK) >> \
+ (WMAL_MRSPF_STTS_FIFO1_NOT_EMPTY_POS)))
#define WFPM_LMAC1_PS_CTL_RW 0xA03380
#define WFPM_LMAC2_PS_CTL_RW 0xA033C0
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
index e7b2e08645ef..cc8a84018f70 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
@@ -14,8 +14,8 @@
#include "iwl-fh.h"
#include <linux/dmapool.h>
#include "fw/api/commands.h"
-#include "pcie/internal.h"
-#include "iwl-context-info-gen3.h"
+#include "pcie/gen1_2/internal.h"
+#include "pcie/iwl-context-info-v2.h"
struct iwl_trans_dev_restart_data {
struct list_head list;
@@ -82,14 +82,14 @@ void iwl_trans_free_restart_list(void)
struct iwl_trans_reprobe {
struct device *dev;
- struct work_struct work;
+ struct delayed_work work;
};
static void iwl_trans_reprobe_wk(struct work_struct *wk)
{
struct iwl_trans_reprobe *reprobe;
- reprobe = container_of(wk, typeof(*reprobe), work);
+ reprobe = container_of(wk, typeof(*reprobe), work.work);
if (device_reprobe(reprobe->dev))
dev_err(reprobe->dev, "reprobe failed!\n");
@@ -98,33 +98,86 @@ static void iwl_trans_reprobe_wk(struct work_struct *wk)
module_put(THIS_MODULE);
}
+static void iwl_trans_schedule_reprobe(struct iwl_trans *trans,
+ unsigned int delay_ms)
+{
+ struct iwl_trans_reprobe *reprobe;
+
+ /*
+ * get a module reference to avoid doing this while unloading
+ * anyway and to avoid scheduling a work with code that's
+ * being removed.
+ */
+ if (!try_module_get(THIS_MODULE)) {
+ IWL_ERR(trans, "Module is being unloaded - abort\n");
+ return;
+ }
+
+ reprobe = kzalloc(sizeof(*reprobe), GFP_KERNEL);
+ if (!reprobe) {
+ module_put(THIS_MODULE);
+ return;
+ }
+ reprobe->dev = get_device(trans->dev);
+ INIT_DELAYED_WORK(&reprobe->work, iwl_trans_reprobe_wk);
+ schedule_delayed_work(&reprobe->work, msecs_to_jiffies(delay_ms));
+}
+
#define IWL_TRANS_RESET_OK_TIME 7 /* seconds */
static enum iwl_reset_mode
iwl_trans_determine_restart_mode(struct iwl_trans *trans)
{
struct iwl_trans_dev_restart_data *data;
- enum iwl_reset_mode at_least = 0;
+ enum iwl_reset_mode min_mode = 0;
unsigned int index;
- static const enum iwl_reset_mode escalation_list[] = {
+ static const enum iwl_reset_mode escalation_list_old[] = {
+ IWL_RESET_MODE_SW_RESET,
+ IWL_RESET_MODE_REPROBE,
+ IWL_RESET_MODE_REPROBE,
+ IWL_RESET_MODE_FUNC_RESET,
+ IWL_RESET_MODE_PROD_RESET,
+ };
+ static const enum iwl_reset_mode escalation_list_sc[] = {
IWL_RESET_MODE_SW_RESET,
IWL_RESET_MODE_REPROBE,
IWL_RESET_MODE_REPROBE,
IWL_RESET_MODE_FUNC_RESET,
- /* FIXME: add TOP reset */
+ IWL_RESET_MODE_TOP_RESET,
IWL_RESET_MODE_PROD_RESET,
- /* FIXME: add TOP reset */
+ IWL_RESET_MODE_TOP_RESET,
IWL_RESET_MODE_PROD_RESET,
- /* FIXME: add TOP reset */
+ IWL_RESET_MODE_TOP_RESET,
IWL_RESET_MODE_PROD_RESET,
};
+ const enum iwl_reset_mode *escalation_list;
+ size_t escalation_list_size;
+
+ /* used by TOP fatal error/TOP reset */
+ if (trans->restart.mode.type == IWL_ERR_TYPE_TOP_RESET_FAILED)
+ return IWL_RESET_MODE_PROD_RESET;
+
+ if (trans->request_top_reset) {
+ trans->request_top_reset = 0;
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_SC)
+ return IWL_RESET_MODE_TOP_RESET;
+ return IWL_RESET_MODE_PROD_RESET;
+ }
+
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_SC) {
+ escalation_list = escalation_list_sc;
+ escalation_list_size = ARRAY_SIZE(escalation_list_sc);
+ } else {
+ escalation_list = escalation_list_old;
+ escalation_list_size = ARRAY_SIZE(escalation_list_old);
+ }
if (trans->restart.during_reset)
- at_least = IWL_RESET_MODE_REPROBE;
+ min_mode = IWL_RESET_MODE_REPROBE;
data = iwl_trans_get_restart_data(trans->dev);
if (!data)
- return at_least;
+ return min_mode;
if (!data->backoff &&
ktime_get_boottime_seconds() - data->last_error >=
@@ -132,8 +185,8 @@ iwl_trans_determine_restart_mode(struct iwl_trans *trans)
data->restart_count = 0;
index = data->restart_count;
- if (index >= ARRAY_SIZE(escalation_list)) {
- index = ARRAY_SIZE(escalation_list) - 1;
+ if (index >= escalation_list_size) {
+ index = escalation_list_size - 1;
if (!data->backoff) {
data->backoff = true;
return IWL_RESET_MODE_BACKOFF;
@@ -141,18 +194,24 @@ iwl_trans_determine_restart_mode(struct iwl_trans *trans)
data->backoff = false;
}
- return max(at_least, escalation_list[index]);
+ return max(min_mode, escalation_list[index]);
}
+#define IWL_TRANS_TOP_FOLLOWER_WAIT 180 /* ms */
+
#define IWL_TRANS_RESET_DELAY (HZ * 60)
static void iwl_trans_restart_wk(struct work_struct *wk)
{
struct iwl_trans *trans = container_of(wk, typeof(*trans),
restart.wk.work);
- struct iwl_trans_reprobe *reprobe;
enum iwl_reset_mode mode;
+ if (trans->restart.mode.type == IWL_ERR_TYPE_TOP_RESET_BY_BT) {
+ iwl_trans_schedule_reprobe(trans, IWL_TRANS_TOP_FOLLOWER_WAIT);
+ return;
+ }
+
if (!trans->op_mode)
return;
@@ -187,31 +246,19 @@ static void iwl_trans_restart_wk(struct work_struct *wk)
iwl_trans_inc_restart_count(trans->dev);
switch (mode) {
+ case IWL_RESET_MODE_TOP_RESET:
+ trans->do_top_reset = 1;
+ IWL_ERR(trans, "Device error - TOP reset\n");
+ fallthrough;
case IWL_RESET_MODE_SW_RESET:
- IWL_ERR(trans, "Device error - SW reset\n");
+ if (mode == IWL_RESET_MODE_SW_RESET)
+ IWL_ERR(trans, "Device error - SW reset\n");
iwl_trans_opmode_sw_reset(trans, trans->restart.mode.type);
break;
case IWL_RESET_MODE_REPROBE:
IWL_ERR(trans, "Device error - reprobe!\n");
- /*
- * get a module reference to avoid doing this while unloading
- * anyway and to avoid scheduling a work with code that's
- * being removed.
- */
- if (!try_module_get(THIS_MODULE)) {
- IWL_ERR(trans, "Module is being unloaded - abort\n");
- return;
- }
-
- reprobe = kzalloc(sizeof(*reprobe), GFP_KERNEL);
- if (!reprobe) {
- module_put(THIS_MODULE);
- return;
- }
- reprobe->dev = get_device(trans->dev);
- INIT_WORK(&reprobe->work, iwl_trans_reprobe_wk);
- schedule_work(&reprobe->work);
+ iwl_trans_schedule_reprobe(trans, 0);
break;
default:
iwl_trans_pcie_reset(trans, mode);
@@ -221,7 +268,7 @@ static void iwl_trans_restart_wk(struct work_struct *wk)
struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
struct device *dev,
- const struct iwl_cfg_trans_params *cfg_trans)
+ const struct iwl_mac_cfg *mac_cfg)
{
struct iwl_trans *trans;
#ifdef CONFIG_LOCKDEP
@@ -232,7 +279,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
if (!trans)
return NULL;
- trans->trans_cfg = cfg_trans;
+ trans->mac_cfg = mac_cfg;
#ifdef CONFIG_LOCKDEP
lockdep_init_map(&trans->sync_cmd_lockdep_map, "sync_cmd_lockdep_map",
@@ -240,54 +287,15 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
#endif
trans->dev = dev;
- trans->num_rx_queues = 1;
INIT_DELAYED_WORK(&trans->restart.wk, iwl_trans_restart_wk);
return trans;
}
-int iwl_trans_init(struct iwl_trans *trans)
-{
- int txcmd_size, txcmd_align;
-
- if (!trans->trans_cfg->gen2) {
- txcmd_size = sizeof(struct iwl_tx_cmd);
- txcmd_align = sizeof(void *);
- } else if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
- txcmd_size = sizeof(struct iwl_tx_cmd_gen2);
- txcmd_align = 64;
- } else {
- txcmd_size = sizeof(struct iwl_tx_cmd_gen3);
- txcmd_align = 128;
- }
-
- txcmd_size += sizeof(struct iwl_cmd_header);
- txcmd_size += 36; /* biggest possible 802.11 header */
-
- /* Ensure device TX cmd cannot reach/cross a page boundary in gen2 */
- if (WARN_ON(trans->trans_cfg->gen2 && txcmd_size >= txcmd_align))
- return -EINVAL;
-
- snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name),
- "iwl_cmd_pool:%s", dev_name(trans->dev));
- trans->dev_cmd_pool =
- kmem_cache_create(trans->dev_cmd_pool_name,
- txcmd_size, txcmd_align,
- SLAB_HWCACHE_ALIGN, NULL);
- if (!trans->dev_cmd_pool)
- return -ENOMEM;
-
- /* Initialize the wait queue for commands */
- init_waitqueue_head(&trans->wait_command_queue);
-
- return 0;
-}
-
void iwl_trans_free(struct iwl_trans *trans)
{
cancel_delayed_work_sync(&trans->restart.wk);
- kmem_cache_destroy(trans->dev_cmd_pool);
}
int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
@@ -298,19 +306,6 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
test_bit(STATUS_RFKILL_OPMODE, &trans->status)))
return -ERFKILL;
- /*
- * We can't test IWL_MVM_STATUS_IN_D3 in mvm->status because this
- * bit is set early in the D3 flow, before we send all the commands
- * that configure the firmware for D3 operation (power, patterns, ...)
- * and we don't want to flag all those with CMD_SEND_IN_D3.
- * So use the system_pm_mode instead. The only command sent after
- * we set system_pm_mode is D3_CONFIG_CMD, which we now flag with
- * CMD_SEND_IN_D3.
- */
- if (unlikely(trans->system_pm_mode == IWL_PLAT_PM_MODE_D3 &&
- !(cmd->flags & CMD_SEND_IN_D3)))
- return -EHOSTDOWN;
-
if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
return -EIO;
@@ -321,7 +316,7 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
if (!(cmd->flags & CMD_ASYNC))
lock_map_acquire_read(&trans->sync_cmd_lockdep_map);
- if (trans->wide_cmd_header && !iwl_cmd_groupid(cmd->id)) {
+ if (trans->conf.wide_cmd_header && !iwl_cmd_groupid(cmd->id)) {
if (cmd->id != REPLY_ERROR)
cmd->id = DEF_ID(cmd->id);
}
@@ -338,6 +333,19 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
}
IWL_EXPORT_SYMBOL(iwl_trans_send_cmd);
+struct iwl_device_tx_cmd *iwl_trans_alloc_tx_cmd(struct iwl_trans *trans)
+{
+ return iwl_pcie_gen1_2_alloc_tx_cmd(trans);
+}
+IWL_EXPORT_SYMBOL(iwl_trans_alloc_tx_cmd);
+
+void iwl_trans_free_tx_cmd(struct iwl_trans *trans,
+ struct iwl_device_tx_cmd *dev_cmd)
+{
+ iwl_pcie_gen1_2_free_tx_cmd(trans, dev_cmd);
+}
+IWL_EXPORT_SYMBOL(iwl_trans_free_tx_cmd);
+
/* Comparator for struct iwl_hcmd_names.
* Used in the binary search over a list of host commands.
*
@@ -365,11 +373,12 @@ const char *iwl_get_cmd_string(struct iwl_trans *trans, u32 id)
grp = iwl_cmd_groupid(id);
cmd = iwl_cmd_opcode(id);
- if (!trans->command_groups || grp >= trans->command_groups_size ||
- !trans->command_groups[grp].arr)
+ if (!trans->conf.command_groups ||
+ grp >= trans->conf.command_groups_size ||
+ !trans->conf.command_groups[grp].arr)
return "UNKNOWN";
- arr = &trans->command_groups[grp];
+ arr = &trans->conf.command_groups[grp];
ret = bsearch(&cmd, arr->arr, arr->size, size, iwl_hcmd_names_cmp);
if (!ret)
return "UNKNOWN";
@@ -377,37 +386,27 @@ const char *iwl_get_cmd_string(struct iwl_trans *trans, u32 id)
}
IWL_EXPORT_SYMBOL(iwl_get_cmd_string);
-int iwl_cmd_groups_verify_sorted(const struct iwl_trans_config *trans)
+void iwl_trans_op_mode_enter(struct iwl_trans *trans,
+ struct iwl_op_mode *op_mode)
{
- int i, j;
- const struct iwl_hcmd_arr *arr;
+ trans->op_mode = op_mode;
- for (i = 0; i < trans->command_groups_size; i++) {
- arr = &trans->command_groups[i];
- if (!arr->arr)
- continue;
- for (j = 0; j < arr->size - 1; j++)
- if (arr->arr[j].cmd_id > arr->arr[j + 1].cmd_id)
- return -1;
- }
- return 0;
-}
-IWL_EXPORT_SYMBOL(iwl_cmd_groups_verify_sorted);
+ if (WARN_ON(trans->conf.n_no_reclaim_cmds > MAX_NO_RECLAIM_CMDS))
+ trans->conf.n_no_reclaim_cmds =
+ ARRAY_SIZE(trans->conf.no_reclaim_cmds);
-void iwl_trans_configure(struct iwl_trans *trans,
- const struct iwl_trans_config *trans_cfg)
-{
- trans->op_mode = trans_cfg->op_mode;
+ WARN_ON_ONCE(!trans->conf.rx_mpdu_cmd);
- iwl_trans_pcie_configure(trans, trans_cfg);
- WARN_ON(iwl_cmd_groups_verify_sorted(trans_cfg));
+ iwl_pcie_gen1_2_op_mode_enter(trans);
}
-IWL_EXPORT_SYMBOL(iwl_trans_configure);
+IWL_EXPORT_SYMBOL(iwl_trans_op_mode_enter);
int iwl_trans_start_hw(struct iwl_trans *trans)
{
might_sleep();
+ clear_bit(STATUS_TRANS_RESET_IN_PROGRESS, &trans->status);
+
return iwl_trans_pcie_start_hw(trans);
}
IWL_EXPORT_SYMBOL(iwl_trans_start_hw);
@@ -416,11 +415,15 @@ void iwl_trans_op_mode_leave(struct iwl_trans *trans)
{
might_sleep();
- iwl_trans_pcie_op_mode_leave(trans);
+ if (trans->mac_cfg->gen2)
+ iwl_trans_pcie_gen2_op_mode_leave(trans);
+ else
+ iwl_trans_pcie_op_mode_leave(trans);
cancel_delayed_work_sync(&trans->restart.wk);
trans->op_mode = NULL;
+ memset(&trans->conf, 0, sizeof(trans->conf));
trans->state = IWL_TRANS_NO_FW;
}
@@ -430,31 +433,26 @@ void iwl_trans_write8(struct iwl_trans *trans, u32 ofs, u8 val)
{
iwl_trans_pcie_write8(trans, ofs, val);
}
-IWL_EXPORT_SYMBOL(iwl_trans_write8);
void iwl_trans_write32(struct iwl_trans *trans, u32 ofs, u32 val)
{
iwl_trans_pcie_write32(trans, ofs, val);
}
-IWL_EXPORT_SYMBOL(iwl_trans_write32);
u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs)
{
return iwl_trans_pcie_read32(trans, ofs);
}
-IWL_EXPORT_SYMBOL(iwl_trans_read32);
u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs)
{
return iwl_trans_pcie_read_prph(trans, ofs);
}
-IWL_EXPORT_SYMBOL(iwl_trans_read_prph);
void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
{
return iwl_trans_pcie_write_prph(trans, ofs, val);
}
-IWL_EXPORT_SYMBOL(iwl_trans_write_prph);
int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr,
void *buf, int dwords)
@@ -466,7 +464,19 @@ IWL_EXPORT_SYMBOL(iwl_trans_read_mem);
int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr,
const void *buf, int dwords)
{
- return iwl_trans_pcie_write_mem(trans, addr, buf, dwords);
+ int offs, ret = 0;
+ const u32 *vals = buf;
+
+ if (iwl_trans_grab_nic_access(trans)) {
+ iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr);
+ for (offs = 0; offs < dwords; offs++)
+ iwl_write32(trans, HBUS_TARG_MEM_WDAT,
+ vals ? vals[offs] : 0);
+ iwl_trans_release_nic_access(trans);
+ } else {
+ ret = -EBUSY;
+ }
+ return ret;
}
IWL_EXPORT_SYMBOL(iwl_trans_write_mem);
@@ -479,11 +489,10 @@ void iwl_trans_set_pmi(struct iwl_trans *trans, bool state)
}
IWL_EXPORT_SYMBOL(iwl_trans_set_pmi);
-int iwl_trans_sw_reset(struct iwl_trans *trans, bool retake_ownership)
+int iwl_trans_sw_reset(struct iwl_trans *trans)
{
- return iwl_trans_pcie_sw_reset(trans, retake_ownership);
+ return iwl_trans_pcie_sw_reset(trans, true);
}
-IWL_EXPORT_SYMBOL(iwl_trans_sw_reset);
struct iwl_trans_dump_data *
iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask,
@@ -493,22 +502,20 @@ iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask,
return iwl_trans_pcie_dump_data(trans, dump_mask,
sanitize_ops, sanitize_ctx);
}
-IWL_EXPORT_SYMBOL(iwl_trans_dump_data);
-int iwl_trans_d3_suspend(struct iwl_trans *trans, bool test, bool reset)
+int iwl_trans_d3_suspend(struct iwl_trans *trans, bool reset)
{
might_sleep();
- return iwl_trans_pcie_d3_suspend(trans, test, reset);
+ return iwl_trans_pcie_d3_suspend(trans, reset);
}
IWL_EXPORT_SYMBOL(iwl_trans_d3_suspend);
-int iwl_trans_d3_resume(struct iwl_trans *trans, enum iwl_d3_status *status,
- bool test, bool reset)
+int iwl_trans_d3_resume(struct iwl_trans *trans, bool reset)
{
might_sleep();
- return iwl_trans_pcie_d3_resume(trans, status, test, reset);
+ return iwl_trans_pcie_d3_resume(trans, reset);
}
IWL_EXPORT_SYMBOL(iwl_trans_d3_resume);
@@ -516,20 +523,17 @@ void iwl_trans_interrupts(struct iwl_trans *trans, bool enable)
{
iwl_trans_pci_interrupts(trans, enable);
}
-IWL_EXPORT_SYMBOL(iwl_trans_interrupts);
void iwl_trans_sync_nmi(struct iwl_trans *trans)
{
iwl_trans_pcie_sync_nmi(trans);
}
-IWL_EXPORT_SYMBOL(iwl_trans_sync_nmi);
int iwl_trans_write_imr_mem(struct iwl_trans *trans, u32 dst_addr,
u64 src_addr, u32 byte_cnt)
{
return iwl_trans_pcie_copy_imr(trans, dst_addr, src_addr, byte_cnt);
}
-IWL_EXPORT_SYMBOL(iwl_trans_write_imr_mem);
void iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg,
u32 mask, u32 value)
@@ -543,7 +547,6 @@ int iwl_trans_read_config32(struct iwl_trans *trans, u32 ofs,
{
return iwl_trans_pcie_read_config32(trans, ofs, val);
}
-IWL_EXPORT_SYMBOL(iwl_trans_read_config32);
bool _iwl_trans_grab_nic_access(struct iwl_trans *trans)
{
@@ -558,34 +561,39 @@ iwl_trans_release_nic_access(struct iwl_trans *trans)
}
IWL_EXPORT_SYMBOL(iwl_trans_release_nic_access);
-void iwl_trans_fw_alive(struct iwl_trans *trans, u32 scd_addr)
+void iwl_trans_fw_alive(struct iwl_trans *trans)
{
might_sleep();
trans->state = IWL_TRANS_FW_ALIVE;
- if (trans->trans_cfg->gen2)
+ if (trans->mac_cfg->gen2)
iwl_trans_pcie_gen2_fw_alive(trans);
else
- iwl_trans_pcie_fw_alive(trans, scd_addr);
+ iwl_trans_pcie_fw_alive(trans);
}
IWL_EXPORT_SYMBOL(iwl_trans_fw_alive);
-int iwl_trans_start_fw(struct iwl_trans *trans, const struct fw_img *fw,
- bool run_in_rfkill)
+int iwl_trans_start_fw(struct iwl_trans *trans, const struct iwl_fw *fw,
+ enum iwl_ucode_type ucode_type, bool run_in_rfkill)
{
+ const struct fw_img *img;
int ret;
might_sleep();
- WARN_ON_ONCE(!trans->rx_mpdu_cmd);
+ img = iwl_get_ucode_image(fw, ucode_type);
+ if (!img)
+ return -EINVAL;
clear_bit(STATUS_FW_ERROR, &trans->status);
- if (trans->trans_cfg->gen2)
- ret = iwl_trans_pcie_gen2_start_fw(trans, fw, run_in_rfkill);
+ if (trans->mac_cfg->gen2)
+ ret = iwl_trans_pcie_gen2_start_fw(trans, fw, img,
+ run_in_rfkill);
else
- ret = iwl_trans_pcie_start_fw(trans, fw, run_in_rfkill);
+ ret = iwl_trans_pcie_start_fw(trans, fw, img,
+ run_in_rfkill);
if (ret == 0)
trans->state = IWL_TRANS_FW_STARTED;
@@ -626,7 +634,7 @@ void iwl_trans_stop_device(struct iwl_trans *trans)
iwl_op_mode_dump_error(trans->op_mode, &mode);
}
- if (trans->trans_cfg->gen2)
+ if (trans->mac_cfg->gen2)
iwl_trans_pcie_gen2_stop_device(trans);
else
iwl_trans_pcie_stop_device(trans);
@@ -645,7 +653,7 @@ int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
"bad state = %d\n", trans->state))
return -EIO;
- if (trans->trans_cfg->gen2)
+ if (trans->mac_cfg->gen2)
return iwl_txq_gen2_tx(trans, skb, dev_cmd, queue);
return iwl_trans_pcie_tx(trans, skb, dev_cmd, queue);
@@ -734,7 +742,6 @@ void iwl_trans_debugfs_cleanup(struct iwl_trans *trans)
{
iwl_trans_pcie_debugfs_cleanup(trans);
}
-IWL_EXPORT_SYMBOL(iwl_trans_debugfs_cleanup);
#endif
void iwl_trans_set_q_ptrs(struct iwl_trans *trans, int queue, int ptr)
@@ -772,35 +779,46 @@ int iwl_trans_get_rxq_dma_data(struct iwl_trans *trans, int queue,
{
return iwl_trans_pcie_rxq_dma_data(trans, queue, data);
}
-IWL_EXPORT_SYMBOL(iwl_trans_get_rxq_dma_data);
int iwl_trans_load_pnvm(struct iwl_trans *trans,
const struct iwl_pnvm_image *pnvm_data,
const struct iwl_ucode_capabilities *capa)
{
- return iwl_trans_pcie_ctx_info_gen3_load_pnvm(trans, pnvm_data, capa);
+ return iwl_trans_pcie_ctx_info_v2_load_pnvm(trans, pnvm_data, capa);
}
IWL_EXPORT_SYMBOL(iwl_trans_load_pnvm);
void iwl_trans_set_pnvm(struct iwl_trans *trans,
const struct iwl_ucode_capabilities *capa)
{
- iwl_trans_pcie_ctx_info_gen3_set_pnvm(trans, capa);
+ iwl_trans_pcie_ctx_info_v2_set_pnvm(trans, capa);
}
-IWL_EXPORT_SYMBOL(iwl_trans_set_pnvm);
int iwl_trans_load_reduce_power(struct iwl_trans *trans,
const struct iwl_pnvm_image *payloads,
const struct iwl_ucode_capabilities *capa)
{
- return iwl_trans_pcie_ctx_info_gen3_load_reduce_power(trans, payloads,
+ return iwl_trans_pcie_ctx_info_v2_load_reduce_power(trans, payloads,
capa);
}
-IWL_EXPORT_SYMBOL(iwl_trans_load_reduce_power);
void iwl_trans_set_reduce_power(struct iwl_trans *trans,
const struct iwl_ucode_capabilities *capa)
{
- iwl_trans_pcie_ctx_info_gen3_set_reduce_power(trans, capa);
+ iwl_trans_pcie_ctx_info_v2_set_reduce_power(trans, capa);
+}
+
+bool iwl_trans_is_pm_supported(struct iwl_trans *trans)
+{
+ if (WARN_ON(trans->mac_cfg->gen2))
+ return false;
+
+ return iwl_pcie_gen1_is_pm_supported(trans);
+}
+IWL_EXPORT_SYMBOL(iwl_trans_is_pm_supported);
+
+bool iwl_trans_is_ltr_enabled(struct iwl_trans *trans)
+{
+ return iwl_pcie_gen1_2_is_ltr_enabled(trans);
}
-IWL_EXPORT_SYMBOL(iwl_trans_set_reduce_power);
+IWL_EXPORT_SYMBOL(iwl_trans_is_ltr_enabled);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index ce4954b0d524..a552669db6e2 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-2023 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -109,23 +109,19 @@ static inline u32 iwl_rx_packet_payload_len(const struct iwl_rx_packet *pkt)
* the response. The caller needs to call iwl_free_resp when done.
* @CMD_SEND_IN_RFKILL: Send the command even if the NIC is in RF-kill.
* @CMD_BLOCK_TXQS: Block TXQs while the comment is executing.
- * @CMD_SEND_IN_D3: Allow the command to be sent in D3 mode, relevant to
- * SUSPEND and RESUME commands. We are in D3 mode when we set
- * trans->system_pm_mode to IWL_PLAT_PM_MODE_D3.
*/
enum CMD_MODE {
CMD_ASYNC = BIT(0),
CMD_WANT_SKB = BIT(1),
CMD_SEND_IN_RFKILL = BIT(2),
CMD_BLOCK_TXQS = BIT(3),
- CMD_SEND_IN_D3 = BIT(4),
};
#define CMD_MODE_BITS 5
#define DEF_CMD_PAYLOAD_SIZE 320
/**
- * struct iwl_device_cmd
+ * struct iwl_device_cmd - device command structure
*
* For allocation of the command and tx queues, this establishes the overall
* size of the largest command we send to uCode, except for commands that
@@ -279,16 +275,6 @@ static inline void iwl_free_rxb(struct iwl_rx_cmd_buffer *r)
#define IWL_9000_MAX_RX_HW_QUEUES 1
/**
- * enum iwl_d3_status - WoWLAN image/device status
- * @IWL_D3_STATUS_ALIVE: firmware is still running after resume
- * @IWL_D3_STATUS_RESET: device was reset while suspended
- */
-enum iwl_d3_status {
- IWL_D3_STATUS_ALIVE,
- IWL_D3_STATUS_RESET,
-};
-
-/**
* enum iwl_trans_status: transport status flags
* @STATUS_SYNC_HCMD_ACTIVE: a SYNC command is being processed
* @STATUS_DEVICE_ENABLED: APM is enabled
@@ -298,12 +284,12 @@ enum iwl_d3_status {
* @STATUS_RFKILL_OPMODE: RF-kill state reported to opmode
* @STATUS_FW_ERROR: the fw is in error state
* @STATUS_TRANS_DEAD: trans is dead - avoid any read/write operation
- * @STATUS_SUPPRESS_CMD_ERROR_ONCE: suppress "FW error in SYNC CMD" once,
- * e.g. for testing
* @STATUS_IN_SW_RESET: device is undergoing reset, cleared by opmode
* via iwl_trans_finish_sw_reset()
* @STATUS_RESET_PENDING: reset worker was scheduled, but didn't dump
* the firmware state yet
+ * @STATUS_TRANS_RESET_IN_PROGRESS: reset is still in progress, don't
+ * attempt another reset yet
*/
enum iwl_trans_status {
STATUS_SYNC_HCMD_ACTIVE,
@@ -314,9 +300,9 @@ enum iwl_trans_status {
STATUS_RFKILL_OPMODE,
STATUS_FW_ERROR,
STATUS_TRANS_DEAD,
- STATUS_SUPPRESS_CMD_ERROR_ONCE,
STATUS_IN_SW_RESET,
STATUS_RESET_PENDING,
+ STATUS_TRANS_RESET_IN_PROGRESS,
};
static inline int
@@ -328,6 +314,7 @@ iwl_trans_get_rb_size_order(enum iwl_amsdu_size rb_size)
case IWL_AMSDU_4K:
return get_order(4 * 1024);
case IWL_AMSDU_8K:
+ return get_order(8 * 1024);
case IWL_AMSDU_12K:
return get_order(16 * 1024);
default:
@@ -387,7 +374,8 @@ struct iwl_dump_sanitize_ops {
/**
* struct iwl_trans_config - transport configuration
*
- * @op_mode: pointer to the upper layer.
+ * These values should be set before iwl_trans_op_mode_enter().
+ *
* @cmd_queue: the index of the command queue.
* Must be set before start_fw.
* @cmd_fifo: the fifo for host commands
@@ -398,8 +386,6 @@ struct iwl_dump_sanitize_ops {
* @n_no_reclaim_cmds: # of commands in list
* @rx_buf_size: RX buffer size needed for A-MSDUs
* if unset 4k will be the RX buffer size
- * @bc_table_dword: set to true if the BC table expects the byte count to be
- * in DWORD (as opposed to bytes)
* @scd_set_active: should the transport configure the SCD for HCMD queue
* @command_groups: array of command groups, each member is an array of the
* commands in the group; for debugging only
@@ -410,17 +396,24 @@ struct iwl_dump_sanitize_ops {
* @queue_alloc_cmd_ver: queue allocation command version, set to 0
* for using the older SCD_QUEUE_CFG, set to the version of
* SCD_QUEUE_CONFIG_CMD otherwise.
+ * @wide_cmd_header: true when ucode supports wide command header format
+ * @rx_mpdu_cmd: MPDU RX command ID, must be assigned by opmode before
+ * starting the firmware, used for tracing
+ * @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the
+ * start of the 802.11 header in the @rx_mpdu_cmd
+ * @dsbr_urm_fw_dependent: switch to URM based on fw settings
+ * @dsbr_urm_permanent: switch to URM permanently
+ * @mbx_addr_0_step: step address data 0
+ * @mbx_addr_1_step: step address data 1
+ * @ext_32khz_clock_valid: if true, the external 32 KHz clock can be used
*/
struct iwl_trans_config {
- struct iwl_op_mode *op_mode;
-
u8 cmd_queue;
u8 cmd_fifo;
- const u8 *no_reclaim_cmds;
- unsigned int n_no_reclaim_cmds;
+ u8 n_no_reclaim_cmds;
+ u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS];
enum iwl_amsdu_size rx_buf_size;
- bool bc_table_dword;
bool scd_set_active;
const struct iwl_hcmd_arr *command_groups;
int command_groups_size;
@@ -428,6 +421,16 @@ struct iwl_trans_config {
u8 cb_data_offs;
bool fw_reset_handshake;
u8 queue_alloc_cmd_ver;
+
+ bool wide_cmd_header;
+ u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size;
+
+ u8 dsbr_urm_fw_dependent:1,
+ dsbr_urm_permanent:1,
+ ext_32khz_clock_valid:1;
+
+ u32 mbx_addr_0_step;
+ u32 mbx_addr_1_step;
};
struct iwl_trans_dump_data {
@@ -513,24 +516,7 @@ enum iwl_trans_state {
*/
/**
- * enum iwl_plat_pm_mode - platform power management mode
- *
- * This enumeration describes the device's platform power management
- * behavior when in system-wide suspend (i.e WoWLAN).
- *
- * @IWL_PLAT_PM_MODE_DISABLED: power management is disabled for this
- * device. In system-wide suspend mode, it means that the all
- * connections will be closed automatically by mac80211 before
- * the platform is suspended.
- * @IWL_PLAT_PM_MODE_D3: the device goes into D3 mode (i.e. WoWLAN).
- */
-enum iwl_plat_pm_mode {
- IWL_PLAT_PM_MODE_DISABLED,
- IWL_PLAT_PM_MODE_D3,
-};
-
-/**
- * enum iwl_ini_cfg_state
+ * enum iwl_ini_cfg_state - debug config state
* @IWL_INI_CFG_STATE_NOT_LOADED: no debug cfg was given
* @IWL_INI_CFG_STATE_LOADED: debug cfg was found and loaded
* @IWL_INI_CFG_STATE_CORRUPTED: debug cfg was found and some of the TLVs
@@ -546,7 +532,7 @@ enum iwl_ini_cfg_state {
#define IWL_TRANS_NMI_TIMEOUT (HZ / 4)
/**
- * struct iwl_dram_data
+ * struct iwl_dram_data - DRAM data descriptor
* @physical: page phy pointer
* @block: pointer to the allocated block/page
* @size: size of the block/page
@@ -656,8 +642,6 @@ struct iwl_pc_data {
* @restart_required: indicates debug restart is required
* @last_tp_resetfw: last handling of reset during debug timepoint
* @imr_data: IMR debug data allocation
- * @dump_file_name_ext: dump file name extension
- * @dump_file_name_ext_valid: dump file name extension if valid or not
* @num_pc: number of program counter for cpu
* @pc_data: details of the program counter
* @yoyo_bin_loaded: tells if a yoyo debug file has been loaded
@@ -696,8 +680,6 @@ struct iwl_trans_debug {
bool restart_required;
u32 last_tp_resetfw;
struct iwl_imr_data imr_data;
- u8 dump_file_name_ext[IWL_FW_INI_MAX_NAME];
- bool dump_file_name_ext_valid;
u32 num_pc;
struct iwl_pc_data *pc_data;
bool yoyo_bin_loaded;
@@ -819,128 +801,92 @@ struct iwl_txq {
};
/**
+ * struct iwl_trans_info - transport info for outside use
+ * @name: the device name
+ * @max_skb_frags: maximum number of fragments an SKB can have when transmitted.
+ * 0 indicates that frag SKBs (NETIF_F_SG) aren't supported.
+ * @hw_rev: the revision data of the HW
+ * @hw_rev_step: The mac step of the HW
+ * @hw_rf_id: the device RF ID
+ * @hw_cnv_id: the device CNV ID
+ * @hw_crf_id: the device CRF ID
+ * @hw_id: the ID of the device / sub-device
+ * Bits 0:15 represent the sub-device ID
+ * Bits 16:31 represent the device ID.
+ * @pcie_link_speed: current PCIe link speed (%PCI_EXP_LNKSTA_CLS_*),
+ * only valid for discrete (not integrated) NICs
+ * @num_rxqs: number of RX queues allocated by the transport
+ */
+struct iwl_trans_info {
+ const char *name;
+ u32 max_skb_frags;
+ u32 hw_rev;
+ u32 hw_rev_step;
+ u32 hw_rf_id;
+ u32 hw_crf_id;
+ u32 hw_cnv_id;
+ u32 hw_id;
+ u8 pcie_link_speed;
+ u8 num_rxqs;
+};
+
+/**
* struct iwl_trans - transport common data
*
* @csme_own: true if we couldn't get ownership on the device
* @op_mode: pointer to the op_mode
- * @trans_cfg: the trans-specific configuration part
+ * @mac_cfg: the trans-specific configuration part
* @cfg: pointer to the configuration
* @drv: pointer to iwl_drv
+ * @conf: configuration set by the opmode before enter
* @state: current device state
* @status: a bit-mask of transport status flags
* @dev: pointer to struct device * that represents the device
- * @max_skb_frags: maximum number of fragments an SKB can have when transmitted.
- * 0 indicates that frag SKBs (NETIF_F_SG) aren't supported.
- * @hw_rf_id: a u32 with the device RF ID
- * @hw_cnv_id: a u32 with the device CNV ID
- * @hw_crf_id: a u32 with the device CRF ID
- * @hw_wfpm_id: a u32 with the device wfpm ID
- * @hw_id: a u32 with the ID of the device / sub-device.
- * Set during transport allocation.
- * @hw_id_str: a string with info about HW ID. Set during transport allocation.
- * @sku_id: the SKU identifier (for PNVM matching)
+ * @info: device information for use by other layers
* @pnvm_loaded: indicates PNVM was loaded
- * @hw_rev: the revision data of the HW
- * @hw_rev_step: The mac step of the HW
- * @pm_support: set to true in start_hw if link pm is supported
- * @ltr_enabled: set to true if the LTR is enabled
+ * @suppress_cmd_error_once: suppress "FW error in SYNC CMD" once,
+ * e.g. for testing
* @fail_to_parse_pnvm_image: set to true if pnvm parsing failed
* @reduce_power_loaded: indicates reduced power section was loaded
* @failed_to_load_reduce_power_image: set to true if pnvm loading failed
- * @command_groups: pointer to command group name list array
- * @command_groups_size: array size of @command_groups
- * @wide_cmd_header: true when ucode supports wide command header format
- * @wait_command_queue: wait queue for sync commands
- * @num_rx_queues: number of RX queues allocated by the transport;
- * the transport must set this before calling iwl_drv_start()
- * @iml_len: the length of the image loader
- * @iml: a pointer to the image loader itself
- * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
- * The user should use iwl_trans_{alloc,free}_tx_cmd.
- * @dev_cmd_pool_name: name for the TX command allocation pool
* @dbgfs_dir: iwlwifi debugfs base dir for this device
* @sync_cmd_lockdep_map: lockdep map for checking sync commands
- * @rx_mpdu_cmd: MPDU RX command ID, must be assigned by opmode before
- * starting the firmware, used for tracing
- * @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the
- * start of the 802.11 header in the @rx_mpdu_cmd
* @dbg: additional debug data, see &struct iwl_trans_debug
* @init_dram: FW initialization DMA data
- * @system_pm_mode: the system-wide power management mode in use.
- * This mode is set dynamically, depending on the WoWLAN values
- * configured from the userspace at runtime.
- * @name: the device name
- * @mbx_addr_0_step: step address data 0
- * @mbx_addr_1_step: step address data 1
- * @pcie_link_speed: current PCIe link speed (%PCI_EXP_LNKSTA_CLS_*),
- * only valid for discrete (not integrated) NICs
- * @invalid_tx_cmd: invalid TX command buffer
* @reduced_cap_sku: reduced capability supported SKU
- * @no_160: device not supporting 160 MHz
* @step_urm: STEP is in URM, no support for MCS>9 in 320 MHz
* @restart: restart worker data
* @restart.wk: restart worker
* @restart.mode: reset/restart error mode information
* @restart.during_reset: error occurred during previous software reset
- * @me_recheck_wk: worker to recheck WiAMT/CSME presence
- * @me_present: WiAMT/CSME is detected as present (1), not present (0)
- * or unknown (-1, so can still use it as a boolean safely)
* @trans_specific: data for the specific transport this is allocated for/with
- * @dsbr_urm_fw_dependent: switch to URM based on fw settings
- * @dsbr_urm_permanent: switch to URM permanently
- * @ext_32khz_clock_valid: if true, the external 32 KHz clock can be used
+ * @request_top_reset: TOP reset was requested, used by the reset
+ * worker that should be scheduled (with appropriate reason)
+ * @do_top_reset: indication to the (PCIe) transport/context-info
+ * to do the TOP reset
*/
struct iwl_trans {
bool csme_own;
struct iwl_op_mode *op_mode;
- const struct iwl_cfg_trans_params *trans_cfg;
- const struct iwl_cfg *cfg;
+ const struct iwl_mac_cfg *mac_cfg;
+ const struct iwl_rf_cfg *cfg;
struct iwl_drv *drv;
+ struct iwl_trans_config conf;
enum iwl_trans_state state;
unsigned long status;
struct device *dev;
- u32 max_skb_frags;
- u32 hw_rev;
- u32 hw_rev_step;
- u32 hw_rf_id;
- u32 hw_crf_id;
- u32 hw_cnv_id;
- u32 hw_wfpm_id;
- u32 hw_id;
- char hw_id_str[52];
- u32 sku_id[3];
- bool reduced_cap_sku;
- u8 no_160:1, step_urm:1;
-
- u8 dsbr_urm_fw_dependent:1,
- dsbr_urm_permanent:1;
- bool ext_32khz_clock_valid;
-
- u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size;
+ const struct iwl_trans_info info;
+ bool reduced_cap_sku;
+ bool step_urm;
+ bool suppress_cmd_error_once;
- bool pm_support;
- bool ltr_enabled;
u8 pnvm_loaded:1;
u8 fail_to_parse_pnvm_image:1;
u8 reduce_power_loaded:1;
u8 failed_to_load_reduce_power_image:1;
- const struct iwl_hcmd_arr *command_groups;
- int command_groups_size;
- bool wide_cmd_header;
-
- wait_queue_head_t wait_command_queue;
- u8 num_rx_queues;
-
- size_t iml_len;
- u8 *iml;
-
- /* The following fields are internal only */
- struct kmem_cache *dev_cmd_pool;
- char dev_cmd_pool_name[50];
-
struct dentry *dbgfs_dir;
#ifdef CONFIG_LOCKDEP
@@ -950,24 +896,14 @@ struct iwl_trans {
struct iwl_trans_debug dbg;
struct iwl_self_init_dram init_dram;
- enum iwl_plat_pm_mode system_pm_mode;
-
- const char *name;
- u32 mbx_addr_0_step;
- u32 mbx_addr_1_step;
-
- u8 pcie_link_speed;
-
- struct iwl_dma_ptr invalid_tx_cmd;
-
struct {
struct delayed_work wk;
struct iwl_fw_error_dump_mode mode;
bool during_reset;
} restart;
- struct delayed_work me_recheck_wk;
- s8 me_present;
+ u8 request_top_reset:1,
+ do_top_reset:1;
/* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */
@@ -975,45 +911,36 @@ struct iwl_trans {
};
const char *iwl_get_cmd_string(struct iwl_trans *trans, u32 id);
-int iwl_cmd_groups_verify_sorted(const struct iwl_trans_config *trans);
-void iwl_trans_configure(struct iwl_trans *trans,
- const struct iwl_trans_config *trans_cfg);
+void iwl_trans_op_mode_enter(struct iwl_trans *trans,
+ struct iwl_op_mode *op_mode);
int iwl_trans_start_hw(struct iwl_trans *trans);
void iwl_trans_op_mode_leave(struct iwl_trans *trans);
-void iwl_trans_fw_alive(struct iwl_trans *trans, u32 scd_addr);
+void iwl_trans_fw_alive(struct iwl_trans *trans);
-int iwl_trans_start_fw(struct iwl_trans *trans, const struct fw_img *fw,
- bool run_in_rfkill);
+int iwl_trans_start_fw(struct iwl_trans *trans, const struct iwl_fw *fw,
+ enum iwl_ucode_type ucode_type, bool run_in_rfkill);
void iwl_trans_stop_device(struct iwl_trans *trans);
-int iwl_trans_d3_suspend(struct iwl_trans *trans, bool test, bool reset);
+int iwl_trans_d3_suspend(struct iwl_trans *trans, bool reset);
-int iwl_trans_d3_resume(struct iwl_trans *trans, enum iwl_d3_status *status,
- bool test, bool reset);
+int iwl_trans_d3_resume(struct iwl_trans *trans, bool reset);
struct iwl_trans_dump_data *
iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask,
const struct iwl_dump_sanitize_ops *sanitize_ops,
void *sanitize_ctx);
-static inline struct iwl_device_tx_cmd *
-iwl_trans_alloc_tx_cmd(struct iwl_trans *trans)
-{
- return kmem_cache_zalloc(trans->dev_cmd_pool, GFP_ATOMIC);
-}
+struct iwl_device_tx_cmd *iwl_trans_alloc_tx_cmd(struct iwl_trans *trans);
int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
-static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans,
- struct iwl_device_tx_cmd *dev_cmd)
-{
- kmem_cache_free(trans->dev_cmd_pool, dev_cmd);
-}
+void iwl_trans_free_tx_cmd(struct iwl_trans *trans,
+ struct iwl_device_tx_cmd *dev_cmd);
int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
struct iwl_device_tx_cmd *dev_cmd, int queue);
@@ -1131,7 +1058,7 @@ static inline u32 iwl_trans_write_mem32(struct iwl_trans *trans, u32 addr,
void iwl_trans_set_pmi(struct iwl_trans *trans, bool state);
-int iwl_trans_sw_reset(struct iwl_trans *trans, bool retake_ownership);
+int iwl_trans_sw_reset(struct iwl_trans *trans);
void iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg,
u32 mask, u32 value);
@@ -1150,6 +1077,9 @@ static inline void iwl_trans_schedule_reset(struct iwl_trans *trans,
{
if (test_bit(STATUS_TRANS_DEAD, &trans->status))
return;
+ /* clear this on device init, not cleared on any unbind/reprobe */
+ if (test_and_set_bit(STATUS_TRANS_RESET_IN_PROGRESS, &trans->status))
+ return;
trans->restart.mode.type = type;
trans->restart.mode.context = IWL_ERR_CONTEXT_WORKER;
@@ -1187,6 +1117,9 @@ static inline void iwl_trans_opmode_sw_reset(struct iwl_trans *trans,
set_bit(STATUS_IN_SW_RESET, &trans->status);
+ if (WARN_ON(type == IWL_ERR_TYPE_TOP_RESET_BY_BT))
+ return;
+
if (!trans->op_mode->ops->sw_reset ||
!trans->op_mode->ops->sw_reset(trans->op_mode, type))
clear_bit(STATUS_IN_SW_RESET, &trans->status);
@@ -1233,9 +1166,8 @@ static inline void iwl_trans_finish_sw_reset(struct iwl_trans *trans)
* transport helper functions
*****************************************************/
struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
- struct device *dev,
- const struct iwl_cfg_trans_params *cfg_trans);
-int iwl_trans_init(struct iwl_trans *trans);
+ struct device *dev,
+ const struct iwl_mac_cfg *mac_cfg);
void iwl_trans_free(struct iwl_trans *trans);
static inline bool iwl_trans_is_hw_error_value(u32 val)
@@ -1245,6 +1177,43 @@ static inline bool iwl_trans_is_hw_error_value(u32 val)
void iwl_trans_free_restart_list(void);
+static inline u16 iwl_trans_get_num_rbds(struct iwl_trans *trans)
+{
+ u16 result = trans->cfg->num_rbds;
+
+ /*
+ * Since AX210 family (So/Ty) the device cannot put mutliple
+ * frames into the same buffer, so double the value for them.
+ */
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ return 2 * result;
+ return result;
+}
+
+static inline bool iwl_trans_device_enabled(struct iwl_trans *trans)
+{
+ return test_bit(STATUS_DEVICE_ENABLED, &trans->status);
+}
+
+static inline bool iwl_trans_is_dead(struct iwl_trans *trans)
+{
+ return test_bit(STATUS_TRANS_DEAD, &trans->status);
+}
+
+static inline bool iwl_trans_is_fw_error(struct iwl_trans *trans)
+{
+ return test_bit(STATUS_FW_ERROR, &trans->status);
+}
+
+/*
+ * This function notifies the transport layer of firmware error, the recovery
+ * will be handled by the op mode
+ */
+static inline void iwl_trans_notify_fw_error(struct iwl_trans *trans)
+{
+ trans->state = IWL_TRANS_NO_FW;
+ set_bit(STATUS_FW_ERROR, &trans->status);
+}
/*****************************************************
* PCIe handling
*****************************************************/
@@ -1256,6 +1225,8 @@ enum iwl_reset_mode {
/* upper level modes: */
IWL_RESET_MODE_SW_RESET,
IWL_RESET_MODE_REPROBE,
+ /* TOP reset doesn't require PCIe remove */
+ IWL_RESET_MODE_TOP_RESET,
/* PCIE level modes: */
IWL_RESET_MODE_REMOVE_ONLY,
IWL_RESET_MODE_RESCAN,
@@ -1272,4 +1243,23 @@ 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)
+{
+ struct iwl_trans_info *write;
+
+ write = (void *)(uintptr_t)&trans->info;
+ *write = *info;
+}
+
+static inline u16 iwl_trans_get_device_id(struct iwl_trans *trans)
+{
+ return u32_get_bits(trans->info.hw_id, GENMASK(31, 16));
+}
+
+bool iwl_trans_is_pm_supported(struct iwl_trans *trans);
+
+bool iwl_trans_is_ltr_enabled(struct iwl_trans *trans);
+
#endif /* __iwl_trans_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-utils.c b/drivers/net/wireless/intel/iwlwifi/iwl-utils.c
index b14ec98e28b6..d503544fda40 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-utils.c
@@ -1,10 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2024 Intel Corporation
+ * Copyright (C) 2024-2025 Intel Corporation
*/
#include <net/gso.h>
#include <linux/ieee80211.h>
-#include <net/gso.h>
#include <net/ip.h>
#include "iwl-drv.h"
@@ -83,3 +82,114 @@ int iwl_tx_tso_segment(struct sk_buff *skb, unsigned int num_subframes,
}
IWL_EXPORT_SYMBOL(iwl_tx_tso_segment);
#endif /* CONFIG_INET */
+
+static u32 iwl_div_by_db(u32 value, u8 db)
+{
+ /*
+ * 2^32 * 10**(i / 10) for i = [1, 10], skipping 0 and simply stopping
+ * at 10 dB and looping instead of using a much larger table.
+ *
+ * Using 64 bit math is overkill, but means the helper does not require
+ * a limit on the input range.
+ */
+ static const u32 db_to_val[] = {
+ 0xcb59185e, 0xa1866ba8, 0x804dce7a, 0x65ea59fe, 0x50f44d89,
+ 0x404de61f, 0x331426af, 0x2892c18b, 0x203a7e5b, 0x1999999a,
+ };
+
+ while (value && db > 0) {
+ u8 change = min_t(u8, db, ARRAY_SIZE(db_to_val));
+
+ value = (((u64)value) * db_to_val[change - 1]) >> 32;
+
+ db -= change;
+ }
+
+ return value;
+}
+
+s8 iwl_average_neg_dbm(const u8 *neg_dbm_values, u8 len)
+{
+ int average_magnitude;
+ u32 average_factor;
+ int sum_magnitude = -128;
+ u32 sum_factor = 0;
+ int i, count = 0;
+
+ /*
+ * To properly average the decibel values (signal values given in dBm)
+ * we need to do the math in linear space. Doing a linear average of
+ * dB (dBm) values is a bit annoying though due to the large range of
+ * at least -10 to -110 dBm that will not fit into a 32 bit integer.
+ *
+ * A 64 bit integer should be sufficient, but then we still have the
+ * problem that there are no directly usable utility functions
+ * available.
+ *
+ * So, lets not deal with that and instead do much of the calculation
+ * with a 16.16 fixed point integer along with a base in dBm. 16.16 bit
+ * gives us plenty of head-room for adding up a few values and even
+ * doing some math on it. And the tail should be accurate enough too
+ * (1/2^16 is somewhere around -48 dB, so effectively zero).
+ *
+ * i.e. the real value of sum is:
+ * sum = sum_factor / 2^16 * 10^(sum_magnitude / 10) mW
+ *
+ * However, that does mean we need to be able to bring two values to
+ * a common base, so we need a helper for that.
+ *
+ * Note that this function takes an input with unsigned negative dBm
+ * values but returns a signed dBm (i.e. a negative value).
+ */
+
+ for (i = 0; i < len; i++) {
+ int val_magnitude;
+ u32 val_factor;
+
+ /* Assume invalid */
+ if (neg_dbm_values[i] == 0xff)
+ continue;
+
+ val_factor = 0x10000;
+ val_magnitude = -neg_dbm_values[i];
+
+ if (val_magnitude <= sum_magnitude) {
+ u8 div_db = sum_magnitude - val_magnitude;
+
+ val_factor = iwl_div_by_db(val_factor, div_db);
+ val_magnitude = sum_magnitude;
+ } else {
+ u8 div_db = val_magnitude - sum_magnitude;
+
+ sum_factor = iwl_div_by_db(sum_factor, div_db);
+ sum_magnitude = val_magnitude;
+ }
+
+ sum_factor += val_factor;
+ count++;
+ }
+
+ /* No valid noise measurement, return a very high noise level */
+ if (count == 0)
+ return 0;
+
+ average_magnitude = sum_magnitude;
+ average_factor = sum_factor / count;
+
+ /*
+ * average_factor will be a number smaller than 1.0 (0x10000) at this
+ * point. What we need to do now is to adjust average_magnitude so that
+ * average_factor is between -0.5 dB and 0.5 dB.
+ *
+ * Just do -1 dB steps and find the point where
+ * -0.5 dB * -i dB = 0x10000 * 10^(-0.5/10) / i dB
+ * = div_by_db(0xe429, i)
+ * is smaller than average_factor.
+ */
+ for (i = 0; average_factor < iwl_div_by_db(0xe429, i); i++) {
+ /* nothing */
+ }
+
+ return clamp(average_magnitude - i, -128, 0);
+}
+IWL_EXPORT_SYMBOL(iwl_average_neg_dbm);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-utils.h b/drivers/net/wireless/intel/iwlwifi/iwl-utils.h
index 8f1f11d06fbe..5172035e4d26 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-utils.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-utils.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2024 Intel Corporation
+ * Copyright (C) 2024-2025 Intel Corporation
*/
#ifndef __iwl_utils_h__
#define __iwl_utils_h__
@@ -53,4 +53,6 @@ u32 iwl_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size)
return ie - beacon;
}
+s8 iwl_average_neg_dbm(const u8 *neg_dbm_values, u8 len);
+
#endif /* __iwl_utils_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mei/sap.h b/drivers/net/wireless/intel/iwlwifi/mei/sap.h
index 3b56637b9697..f985ab90d41c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mei/sap.h
+++ b/drivers/net/wireless/intel/iwlwifi/mei/sap.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (C) 2021 - 2022 Intel Corporation
+ * Copyright (C) 2021 - 2022, 2025 Intel Corporation
*/
#ifndef __sap_h__
@@ -300,13 +300,11 @@ enum iwl_sap_msg {
* @type: See &enum iwl_sap_msg.
* @len: The length of the message (header not included).
* @seq_num: For debug.
- * @payload: The payload of the message.
*/
struct iwl_sap_hdr {
__le16 type;
__le16 len;
__le32 seq_num;
- u8 payload[];
};
/**
@@ -340,12 +338,12 @@ enum iwl_sap_wifi_auth_type {
};
/**
- * enum iwl_sap_wifi_cipher_alg
- * @SAP_WIFI_CIPHER_ALG_NONE: TBD
- * @SAP_WIFI_CIPHER_ALG_TKIP: TBD
- * @SAP_WIFI_CIPHER_ALG_CCMP: TBD
- * @SAP_WIFI_CIPHER_ALG_GCMP: TBD
- * @SAP_WIFI_CIPHER_ALG_GCMP_256: TBD
+ * enum iwl_sap_wifi_cipher_alg - MEI WiFi cipher algorithm IDs
+ * @SAP_WIFI_CIPHER_ALG_NONE: No encryption
+ * @SAP_WIFI_CIPHER_ALG_TKIP: TKIPO
+ * @SAP_WIFI_CIPHER_ALG_CCMP: CCMP
+ * @SAP_WIFI_CIPHER_ALG_GCMP: GCMP-128
+ * @SAP_WIFI_CIPHER_ALG_GCMP_256: GCMP-256
*/
enum iwl_sap_wifi_cipher_alg {
SAP_WIFI_CIPHER_ALG_NONE = IWL_MEI_CIPHER_NONE,
@@ -601,7 +599,7 @@ enum iwl_sap_flex_filter_flags {
};
/**
- * struct iwl_sap_flex_filter -
+ * struct iwl_sap_flex_filter - filter configuration
* @src_port: Source port in network format.
* @dst_port: Destination port in network format.
* @flags: Flags and protocol, see &enum iwl_sap_flex_filter_flags.
@@ -633,7 +631,7 @@ enum iwl_sap_ipv4_filter_flags {
};
/**
- * struct iwl_sap_ipv4_filter-
+ * struct iwl_sap_ipv4_filter - IPv4 filter configuration
* @ipv4_addr: The IP address to filer.
* @flags: See &enum iwl_sap_ipv4_filter_flags.
*/
@@ -643,7 +641,7 @@ struct iwl_sap_ipv4_filter {
} __packed;
/**
- * enum iwl_sap_ipv6_filter_flags -
+ * enum iwl_sap_ipv6_filter_flags - IPv6 filter flags
* @SAP_IPV6_ADDR_FILTER_COPY: Pass packets to the host.
* @SAP_IPV6_ADDR_FILTER_ENABLED: If false, the filter should be ignored.
*/
@@ -653,7 +651,7 @@ enum iwl_sap_ipv6_filter_flags {
};
/**
- * struct iwl_sap_ipv6_filter -
+ * struct iwl_sap_ipv6_filter - IPv6 filter configuration
* @addr_lo24: Lowest 24 bits of the IPv6 address.
* @flags: See &enum iwl_sap_ipv6_filter_flags.
*/
@@ -663,7 +661,7 @@ struct iwl_sap_ipv6_filter {
} __packed;
/**
- * enum iwl_sap_icmpv6_filter_flags -
+ * enum iwl_sap_icmpv6_filter_flags - ICMPv6 filter flags
* @SAP_ICMPV6_FILTER_ENABLED: If false, the filter should be ignored.
* @SAP_ICMPV6_FILTER_COPY: Pass packets to the host.
*/
@@ -673,8 +671,8 @@ enum iwl_sap_icmpv6_filter_flags {
};
/**
- * enum iwl_sap_vlan_filter_flags -
- * @SAP_VLAN_FILTER_VLAN_ID_MSK: TBD
+ * enum iwl_sap_vlan_filter_flags - VLAN filter flags
+ * @SAP_VLAN_FILTER_VLAN_ID_MSK: VLAN ID
* @SAP_VLAN_FILTER_ENABLED: If false, the filter should be ignored.
*/
enum iwl_sap_vlan_filter_flags {
@@ -751,7 +749,7 @@ struct iwl_sap_pldr_data {
} __packed;
/**
- * enum iwl_sap_pldr_status -
+ * enum iwl_sap_pldr_status - product reset status
* @SAP_PLDR_STATUS_SUCCESS: PLDR started/ended successfully
* @SAP_PLDR_STATUS_FAILURE: PLDR failed to start/end
*/
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/Makefile b/drivers/net/wireless/intel/iwlwifi/mld/Makefile
index ece66e7a9be4..c966e573f430 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/Makefile
+++ b/drivers/net/wireless/intel/iwlwifi/mld/Makefile
@@ -9,8 +9,4 @@ iwlmld-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
iwlmld-$(CONFIG_IWLWIFI_LEDS) += led.o
iwlmld-$(CONFIG_PM_SLEEP) += d3.o
-# non-upstream things
-iwlmld-$(CONFIG_IWL_VENDOR_CMDS) += vendor-cmd.o
-iwlmld-$(CONFIG_IWLMVM_AX_SOFTAP_TESTMODE) += ax-softap-testmode.o
-
subdir-ccflags-y += -I$(src)/../
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/agg.c b/drivers/net/wireless/intel/iwlwifi/mld/agg.c
index 687a9450ac98..3bf36f8f6874 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/agg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/agg.c
@@ -124,10 +124,12 @@ void iwl_mld_handle_bar_frame_release_notif(struct iwl_mld *mld,
rcu_read_lock();
baid_data = rcu_dereference(mld->fw_id_to_ba[baid]);
- if (IWL_FW_CHECK(mld, !baid_data,
- "Got valid BAID %d but not allocated, invalid BAR release!\n",
- baid))
+ if (!baid_data) {
+ IWL_DEBUG_HT(mld,
+ "Got valid BAID %d but not allocated\n",
+ baid);
goto out_unlock;
+ }
if (IWL_FW_CHECK(mld, tid != baid_data->tid ||
sta_id > mld->fw->ucode_capa.num_stations ||
@@ -303,10 +305,15 @@ iwl_mld_reorder(struct iwl_mld *mld, struct napi_struct *napi,
* already ahead and it will be dropped.
* If the last sub-frame is not on this queue - we will get frame
* release notification with up to date NSSN.
+ * If this is the first frame that is stored in the buffer, the head_sn
+ * may be outdated. Update it based on the last NSSN to make sure it
+ * will be released when the frame release notification arrives.
*/
if (!amsdu || last_subframe)
iwl_mld_reorder_release_frames(mld, sta, napi, baid_data,
buffer, nssn);
+ else if (buffer->num_stored == 1)
+ buffer->head_sn = nssn;
return IWL_MLD_BUFFERED_SKB;
}
@@ -315,7 +322,7 @@ EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_reorder);
static void iwl_mld_rx_agg_session_expired(struct timer_list *t)
{
struct iwl_mld_baid_data *data =
- from_timer(data, t, session_timer);
+ timer_container_of(data, t, session_timer);
struct iwl_mld_baid_data __rcu **rcu_ptr = data->rcu_ptr;
struct iwl_mld_baid_data *ba_data;
struct ieee80211_link_sta *link_sta;
@@ -444,7 +451,7 @@ static void iwl_mld_init_reorder_buffer(struct iwl_mld *mld,
struct iwl_mld_baid_data *data,
u16 ssn)
{
- for (int i = 0; i < mld->trans->num_rx_queues; i++) {
+ for (int i = 0; i < mld->trans->info.num_rxqs; i++) {
struct iwl_mld_reorder_buffer *reorder_buf =
&data->reorder_buf[i];
struct iwl_mld_reorder_buf_entry *entries =
@@ -468,7 +475,7 @@ static void iwl_mld_free_reorder_buffer(struct iwl_mld *mld,
iwl_mld_sync_rx_queues(mld, IWL_MLD_RXQ_NOTIF_DEL_BA,
&delba_data, sizeof(delba_data));
- for (int i = 0; i < mld->trans->num_rx_queues; i++) {
+ for (int i = 0; i < mld->trans->info.num_rxqs; i++) {
struct iwl_mld_reorder_buffer *reorder_buf =
&data->reorder_buf[i];
struct iwl_mld_reorder_buf_entry *entries =
@@ -530,7 +537,7 @@ int iwl_mld_ampdu_rx_start(struct iwl_mld *mld, struct ieee80211_sta *sta,
* before starting the BA session in the firmware
*/
baid_data = kzalloc(sizeof(*baid_data) +
- mld->trans->num_rx_queues * reorder_buf_size,
+ mld->trans->info.num_rxqs * reorder_buf_size,
GFP_KERNEL);
if (!baid_data)
return -ENOMEM;
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/ap.c b/drivers/net/wireless/intel/iwlwifi/mld/ap.c
index 571eabd0b511..5c59acc8c4c5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/ap.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/ap.c
@@ -11,6 +11,7 @@
#include "tx.h"
#include "power.h"
#include "key.h"
+#include "phy.h"
#include "iwl-utils.h"
#include "fw/api/sta.h"
@@ -269,6 +270,7 @@ int iwl_mld_start_ap_ibss(struct ieee80211_hw *hw,
{
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
+ struct ieee80211_chanctx_conf *ctx;
int ret;
if (vif->type == NL80211_IFTYPE_AP)
@@ -292,9 +294,20 @@ int iwl_mld_start_ap_ibss(struct ieee80211_hw *hw,
if (ret)
return ret;
+ mld_vif->ap_ibss_active = true;
+
+ if (vif->p2p && mld->p2p_device_vif) {
+ ret = iwl_mld_mac_fw_action(mld, mld->p2p_device_vif,
+ FW_CTXT_ACTION_MODIFY);
+ if (ret) {
+ mld_vif->ap_ibss_active = false;
+ goto rm_mcast;
+ }
+ }
+
ret = iwl_mld_add_bcast_sta(mld, vif, link);
if (ret)
- goto rm_mcast;
+ goto update_p2p_dev;
/* Those keys were configured by the upper layers before starting the
* AP. Now that it is started and the bcast and mcast sta were added to
@@ -308,15 +321,21 @@ int iwl_mld_start_ap_ibss(struct ieee80211_hw *hw,
iwl_mld_vif_update_low_latency(mld, vif, true,
LOW_LATENCY_VIF_TYPE);
- mld_vif->ap_ibss_active = true;
-
- if (vif->p2p && mld->p2p_device_vif)
- return iwl_mld_mac_fw_action(mld, mld->p2p_device_vif,
- FW_CTXT_ACTION_MODIFY);
+ /* When the channel context was added, the link is not yet active, so
+ * min_def is always used. Update the PHY again here in case def should
+ * actually be used.
+ */
+ ctx = wiphy_dereference(mld->wiphy, link->chanctx_conf);
+ iwl_mld_update_phy_chandef(mld, ctx);
return 0;
rm_bcast:
iwl_mld_remove_bcast_sta(mld, vif, link);
+update_p2p_dev:
+ mld_vif->ap_ibss_active = false;
+ if (vif->p2p && mld->p2p_device_vif)
+ iwl_mld_mac_fw_action(mld, mld->p2p_device_vif,
+ FW_CTXT_ACTION_MODIFY);
rm_mcast:
iwl_mld_remove_mcast_sta(mld, vif, link);
return ret;
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/constants.h b/drivers/net/wireless/intel/iwlwifi/mld/constants.h
index 2a59b29b75cb..5d23a618ae3c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/constants.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/constants.h
@@ -40,15 +40,6 @@
#define IWL_MLD_TPT_COUNT_WINDOW (5 * HZ)
-/* OMI reduced BW thresholds (channel load percentage) */
-#define IWL_MLD_OMI_ENTER_CHAN_LOAD 10
-#define IWL_MLD_OMI_EXIT_CHAN_LOAD_160 20
-#define IWL_MLD_OMI_EXIT_CHAN_LOAD_320 30
-/* time (in milliseconds) to let AP "settle" the OMI */
-#define IWL_MLD_OMI_AP_SETTLE_DELAY 27
-/* time (in milliseconds) to not enter OMI reduced BW after leaving */
-#define IWL_MLD_OMI_EXIT_PROTECTION 5000
-
#define IWL_MLD_DIS_RANDOM_FW_ID false
#define IWL_MLD_D3_DEBUG false
#define IWL_MLD_NON_TRANSMITTING_AP false
@@ -84,5 +75,7 @@
#define IWL_MLD_FTM_RESP_LMR_FEEDBACK_SUPPORT true
#define IWL_MLD_FTM_NON_TB_MIN_TIME_BETWEEN_MSR 7
#define IWL_MLD_FTM_NON_TB_MAX_TIME_BETWEEN_MSR 1000
+#define IWL_MLD_STA_EXT_CAPA_SIZE 9
+#define IWL_MLD_EXT_CAPA_NUM_IFTYPES 1
#endif /* __iwl_mld_constants_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/d3.c b/drivers/net/wireless/intel/iwlwifi/mld/d3.c
index ee99298eebf5..dd85be94433c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/d3.c
@@ -11,6 +11,7 @@
#include "mcc.h"
#include "sta.h"
#include "mlo.h"
+#include "key.h"
#include "fw/api/d3.h"
#include "fw/api/offload.h"
@@ -40,8 +41,6 @@ enum iwl_mld_d3_notif {
struct iwl_mld_resume_key_iter_data {
struct iwl_mld *mld;
struct iwl_mld_wowlan_status *wowlan_status;
- u32 num_keys, gtk_cipher, igtk_cipher, bigtk_cipher;
- bool unhandled_cipher;
};
struct iwl_mld_suspend_key_iter_data {
@@ -71,6 +70,12 @@ struct iwl_mld_mcast_key_data {
};
+struct iwl_mld_wowlan_mlo_key {
+ u8 key[WOWLAN_KEY_MAX_SIZE];
+ u8 idx, type, link_id;
+ u8 pn[6];
+};
+
/**
* struct iwl_mld_wowlan_status - contains wowlan status data from
* all wowlan notifications
@@ -89,6 +94,8 @@ struct iwl_mld_mcast_key_data {
* @bigtk: data of the last two used gtk's by the FW upon resume
* @ptk: last seq numbers per tid passed by the FW,
* holds both in tkip and aes formats
+ * @num_mlo_keys: number of &struct iwl_mld_wowlan_mlo_key structs
+ * @mlo_keys: array of MLO keys
*/
struct iwl_mld_wowlan_status {
u32 wakeup_reasons;
@@ -108,6 +115,9 @@ struct iwl_mld_wowlan_status {
struct ieee80211_key_seq tkip_seq[IWL_MAX_TID_COUNT];
} ptk;
+
+ int num_mlo_keys;
+ struct iwl_mld_wowlan_mlo_key mlo_keys[WOWLAN_MAX_MLO_KEYS];
};
#define NETDETECT_QUERY_BUF_LEN \
@@ -204,66 +214,6 @@ void iwl_mld_ipv6_addr_change(struct ieee80211_hw *hw,
}
#endif
-enum rt_status {
- FW_ALIVE,
- FW_NEEDS_RESET,
- FW_ERROR,
-};
-
-static enum rt_status iwl_mld_check_err_tables(struct iwl_mld *mld,
- struct ieee80211_vif *vif)
-{
- u32 err_id;
-
- /* check for lmac1 error */
- if (iwl_fwrt_read_err_table(mld->trans,
- mld->trans->dbg.lmac_error_event_table[0],
- &err_id)) {
- if (err_id == RF_KILL_INDICATOR_FOR_WOWLAN && vif) {
- struct cfg80211_wowlan_wakeup wakeup = {
- .rfkill_release = true,
- };
- ieee80211_report_wowlan_wakeup(vif, &wakeup,
- GFP_KERNEL);
-
- return FW_NEEDS_RESET;
- }
- return FW_ERROR;
- }
-
- /* check if we have lmac2 set and check for error */
- if (iwl_fwrt_read_err_table(mld->trans,
- mld->trans->dbg.lmac_error_event_table[1],
- NULL))
- return FW_ERROR;
-
- /* check for umac error */
- if (iwl_fwrt_read_err_table(mld->trans,
- mld->trans->dbg.umac_error_event_table,
- NULL))
- return FW_ERROR;
-
- return FW_ALIVE;
-}
-
-static bool iwl_mld_fw_needs_restart(struct iwl_mld *mld,
- struct ieee80211_vif *vif)
-{
- enum rt_status rt_status = iwl_mld_check_err_tables(mld, vif);
-
- if (rt_status == FW_ALIVE)
- return false;
-
- if (rt_status == FW_ERROR) {
- IWL_ERR(mld, "FW Error occurred during suspend\n");
- iwl_fwrt_dump_error_logs(&mld->fwrt);
- iwl_dbg_tlv_time_point(&mld->fwrt,
- IWL_FW_INI_TIME_POINT_FW_ASSERT, NULL);
- }
-
- return true;
-}
-
static int
iwl_mld_netdetect_config(struct iwl_mld *mld,
struct ieee80211_vif *vif,
@@ -331,7 +281,7 @@ iwl_mld_convert_gtk_resume_seq(struct iwl_mld_mcast_key_data *gtk_data,
static void
iwl_mld_convert_gtk_resume_data(struct iwl_mld *mld,
struct iwl_mld_wowlan_status *wowlan_status,
- const struct iwl_wowlan_gtk_status_v3 *gtk_data,
+ const struct iwl_wowlan_gtk_status *gtk_data,
const struct iwl_wowlan_all_rsc_tsc_v5 *sc)
{
int status_idx = 0;
@@ -343,8 +293,9 @@ iwl_mld_convert_gtk_resume_data(struct iwl_mld *mld,
for (int notif_idx = 0; notif_idx < ARRAY_SIZE(wowlan_status->gtk);
notif_idx++) {
int rsc_idx;
+ u8 key_status = gtk_data[notif_idx].key_status;
- if (!(gtk_data[notif_idx].key_len))
+ if (!key_status)
continue;
wowlan_status->gtk[status_idx].len =
@@ -354,10 +305,6 @@ iwl_mld_convert_gtk_resume_data(struct iwl_mld *mld,
wowlan_status->gtk[status_idx].id =
wowlan_status->gtk[status_idx].flags &
IWL_WOWLAN_GTK_IDX_MASK;
- memcpy(wowlan_status->gtk[status_idx].key,
- gtk_data[notif_idx].key,
- sizeof(gtk_data[notif_idx].key));
-
/* The rsc for both gtk keys are stored in gtk[0]->sc->mcast_rsc
* The gtk ids can be any two numbers between 0 and 3,
* the id_map maps between the key id and the index in sc->mcast
@@ -367,13 +314,27 @@ iwl_mld_convert_gtk_resume_data(struct iwl_mld *mld,
iwl_mld_convert_gtk_resume_seq(&wowlan_status->gtk[status_idx],
sc, rsc_idx);
- /* if it's as long as the TKIP encryption key, copy MIC key */
- if (wowlan_status->gtk[status_idx].len ==
- NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
- memcpy(wowlan_status->gtk[status_idx].key +
- NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
- gtk_data[notif_idx].tkip_mic_key,
- sizeof(gtk_data[notif_idx].tkip_mic_key));
+ if (key_status == IWL_WOWLAN_STATUS_NEW_KEY) {
+ memcpy(wowlan_status->gtk[status_idx].key,
+ gtk_data[notif_idx].key,
+ sizeof(gtk_data[notif_idx].key));
+
+ /* if it's as long as the TKIP encryption key,
+ * copy MIC key
+ */
+ if (wowlan_status->gtk[status_idx].len ==
+ NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
+ memcpy(wowlan_status->gtk[status_idx].key +
+ NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
+ gtk_data[notif_idx].tkip_mic_key,
+ sizeof(gtk_data[notif_idx].tkip_mic_key));
+ } else {
+ /* If the key status is WOWLAN_STATUS_OLD_KEY, it
+ * indicates that no key material is present, Set the
+ * key length to 0 as an indication
+ */
+ wowlan_status->gtk[status_idx].len = 0;
+ }
status_idx++;
}
}
@@ -420,11 +381,11 @@ static void
iwl_mld_convert_igtk_resume_data(struct iwl_mld_wowlan_status *wowlan_status,
const struct iwl_wowlan_igtk_status *igtk)
{
- BUILD_BUG_ON(sizeof(wowlan_status->igtk.key) < sizeof(igtk->key));
-
- if (!igtk->key_len)
+ if (!igtk->key_status)
return;
+ BUILD_BUG_ON(sizeof(wowlan_status->igtk.key) < sizeof(igtk->key));
+
wowlan_status->igtk.len = igtk->key_len;
wowlan_status->igtk.flags = igtk->key_flags;
wowlan_status->igtk.id =
@@ -432,7 +393,15 @@ iwl_mld_convert_igtk_resume_data(struct iwl_mld_wowlan_status *wowlan_status,
IWL_WOWLAN_IGTK_BIGTK_IDX_MASK) +
WOWLAN_IGTK_MIN_INDEX;
- memcpy(wowlan_status->igtk.key, igtk->key, sizeof(igtk->key));
+ if (igtk->key_status == IWL_WOWLAN_STATUS_NEW_KEY)
+ memcpy(wowlan_status->igtk.key, igtk->key, sizeof(igtk->key));
+ else
+ /* If the key status is WOWLAN_STATUS_OLD_KEY, it indicates
+ * that no key material is present. Set the key length to 0
+ * as an indication.
+ */
+ wowlan_status->igtk.len = 0;
+
iwl_mld_convert_mcast_ipn(&wowlan_status->igtk, igtk);
}
@@ -446,7 +415,7 @@ iwl_mld_convert_bigtk_resume_data(struct iwl_mld_wowlan_status *wowlan_status,
for (int notif_idx = 0; notif_idx < WOWLAN_BIGTK_KEYS_NUM;
notif_idx++) {
- if (!bigtk[notif_idx].key_len)
+ if (!bigtk[notif_idx].key_status)
continue;
wowlan_status->bigtk[status_idx].len = bigtk[notif_idx].key_len;
@@ -459,32 +428,218 @@ iwl_mld_convert_bigtk_resume_data(struct iwl_mld_wowlan_status *wowlan_status,
BUILD_BUG_ON(sizeof(wowlan_status->bigtk[status_idx].key) <
sizeof(bigtk[notif_idx].key));
- memcpy(wowlan_status->bigtk[status_idx].key,
- bigtk[notif_idx].key, sizeof(bigtk[notif_idx].key));
+ if (bigtk[notif_idx].key_status == IWL_WOWLAN_STATUS_NEW_KEY)
+ memcpy(wowlan_status->bigtk[status_idx].key,
+ bigtk[notif_idx].key,
+ sizeof(bigtk[notif_idx].key));
+ else
+ /* If the key status is WOWLAN_STATUS_OLD_KEY, it
+ * indicates that no key material is present. Set the
+ * key length to 0 as an indication.
+ */
+ wowlan_status->bigtk[status_idx].len = 0;
+
iwl_mld_convert_mcast_ipn(&wowlan_status->bigtk[status_idx],
&bigtk[notif_idx]);
status_idx++;
}
}
+static void
+iwl_mld_convert_mlo_keys(struct iwl_mld *mld,
+ const struct iwl_wowlan_info_notif *notif,
+ struct iwl_mld_wowlan_status *wowlan_status)
+{
+ if (!notif->num_mlo_link_keys)
+ return;
+
+ wowlan_status->num_mlo_keys = notif->num_mlo_link_keys;
+
+ if (IWL_FW_CHECK(mld, wowlan_status->num_mlo_keys > WOWLAN_MAX_MLO_KEYS,
+ "Too many MLO keys: %d, max %d\n",
+ wowlan_status->num_mlo_keys, WOWLAN_MAX_MLO_KEYS))
+ wowlan_status->num_mlo_keys = WOWLAN_MAX_MLO_KEYS;
+
+ for (int i = 0; i < wowlan_status->num_mlo_keys; i++) {
+ const struct iwl_wowlan_mlo_gtk *fw_mlo_key = &notif->mlo_gtks[i];
+ struct iwl_mld_wowlan_mlo_key *driver_mlo_key =
+ &wowlan_status->mlo_keys[i];
+ u16 flags = le16_to_cpu(fw_mlo_key->flags);
+
+ driver_mlo_key->link_id =
+ u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_LINK_ID_MSK);
+ driver_mlo_key->type =
+ u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_KEY_TYPE_MSK);
+ driver_mlo_key->idx =
+ u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_KEY_ID_MSK);
+
+ BUILD_BUG_ON(sizeof(driver_mlo_key->key) != sizeof(fw_mlo_key->key));
+ BUILD_BUG_ON(sizeof(driver_mlo_key->pn) != sizeof(fw_mlo_key->pn));
+
+ memcpy(driver_mlo_key->key, fw_mlo_key->key, sizeof(fw_mlo_key->key));
+ memcpy(driver_mlo_key->pn, fw_mlo_key->pn, sizeof(fw_mlo_key->pn));
+ }
+}
+
+static void
+iwl_mld_convert_wowlan_notif_v5(const struct iwl_wowlan_info_notif_v5 *notif_v5,
+ struct iwl_wowlan_info_notif *notif)
+{
+ /* Convert GTK from v3 to the new format */
+ BUILD_BUG_ON(ARRAY_SIZE(notif->gtk) != ARRAY_SIZE(notif_v5->gtk));
+
+ for (int i = 0; i < ARRAY_SIZE(notif_v5->gtk); i++) {
+ const struct iwl_wowlan_gtk_status_v3 *gtk_v3 = &notif_v5->gtk[i];
+ struct iwl_wowlan_gtk_status *gtk = &notif->gtk[i];
+
+ /* Copy key material and metadata */
+ BUILD_BUG_ON(sizeof(gtk->key) != sizeof(gtk_v3->key));
+ BUILD_BUG_ON(sizeof(gtk->tkip_mic_key) != sizeof(gtk_v3->tkip_mic_key));
+
+ memcpy(gtk->key, gtk_v3->key, sizeof(gtk_v3->key));
+
+ gtk->key_len = gtk_v3->key_len;
+ gtk->key_flags = gtk_v3->key_flags;
+
+ memcpy(gtk->tkip_mic_key, gtk_v3->tkip_mic_key,
+ sizeof(gtk_v3->tkip_mic_key));
+ gtk->sc = gtk_v3->sc;
+
+ /* Set key_status based on whether key material is present.
+ * in v5, a key is either invalid (should be skipped) or has
+ * both meta data and the key itself.
+ */
+ if (gtk_v3->key_len)
+ gtk->key_status = IWL_WOWLAN_STATUS_NEW_KEY;
+ }
+
+ /* Convert IGTK from v1 to the new format, only one IGTK is passed by FW */
+ BUILD_BUG_ON(offsetof(struct iwl_wowlan_igtk_status, key_status) !=
+ sizeof(struct iwl_wowlan_igtk_status_v1));
+
+ memcpy(&notif->igtk[0], &notif_v5->igtk[0],
+ offsetof(struct iwl_wowlan_igtk_status, key_status));
+
+ /* Set key_status based on whether key material is present.
+ * in v5, a key is either invalid (should be skipped) or has
+ * both meta data and the key itself.
+ */
+ if (notif_v5->igtk[0].key_len)
+ notif->igtk[0].key_status = IWL_WOWLAN_STATUS_NEW_KEY;
+
+ /* Convert BIGTK from v1 to the new format */
+ BUILD_BUG_ON(ARRAY_SIZE(notif->bigtk) != ARRAY_SIZE(notif_v5->bigtk));
+
+ for (int i = 0; i < ARRAY_SIZE(notif_v5->bigtk); i++) {
+ /* Copy everything until key_status */
+ memcpy(&notif->bigtk[i], &notif_v5->bigtk[i],
+ offsetof(struct iwl_wowlan_igtk_status, key_status));
+
+ /* Set key_status based on whether key material is present.
+ * in v5, a key is either invalid (should be skipped) or has
+ * both meta data and the key itself.
+ */
+ if (notif_v5->bigtk[i].key_len)
+ notif->bigtk[i].key_status = IWL_WOWLAN_STATUS_NEW_KEY;
+ }
+
+ notif->replay_ctr = notif_v5->replay_ctr;
+ notif->pattern_number = notif_v5->pattern_number;
+ notif->qos_seq_ctr = notif_v5->qos_seq_ctr;
+ notif->wakeup_reasons = notif_v5->wakeup_reasons;
+ notif->num_of_gtk_rekeys = notif_v5->num_of_gtk_rekeys;
+ notif->transmitted_ndps = notif_v5->transmitted_ndps;
+ notif->received_beacons = notif_v5->received_beacons;
+ notif->tid_tear_down = notif_v5->tid_tear_down;
+ notif->station_id = notif_v5->station_id;
+ notif->num_mlo_link_keys = notif_v5->num_mlo_link_keys;
+ notif->tid_offloaded_tx = notif_v5->tid_offloaded_tx;
+
+ /* Copy MLO GTK keys */
+ if (notif_v5->num_mlo_link_keys) {
+ memcpy(notif->mlo_gtks, notif_v5->mlo_gtks,
+ notif_v5->num_mlo_link_keys * sizeof(struct iwl_wowlan_mlo_gtk));
+ }
+}
+
+static bool iwl_mld_validate_wowlan_notif_size(struct iwl_mld *mld,
+ u32 len,
+ u32 expected_len,
+ u8 num_mlo_keys,
+ int version)
+{
+ u32 len_with_mlo_keys;
+
+ if (IWL_FW_CHECK(mld, len < expected_len,
+ "Invalid wowlan_info_notif v%d (expected=%u got=%u)\n",
+ version, expected_len, len))
+ return false;
+
+ len_with_mlo_keys = expected_len +
+ (num_mlo_keys * sizeof(struct iwl_wowlan_mlo_gtk));
+
+ if (IWL_FW_CHECK(mld, len < len_with_mlo_keys,
+ "Invalid wowlan_info_notif v%d with MLO keys (expected=%u got=%u)\n",
+ version, len_with_mlo_keys, len))
+ return false;
+
+ return true;
+}
+
static bool
iwl_mld_handle_wowlan_info_notif(struct iwl_mld *mld,
struct iwl_mld_wowlan_status *wowlan_status,
struct iwl_rx_packet *pkt)
{
- const struct iwl_wowlan_info_notif *notif = (void *)pkt->data;
- u32 expected_len, len = iwl_rx_packet_payload_len(pkt);
-
- expected_len = sizeof(*notif);
+ const struct iwl_wowlan_info_notif *notif;
+ struct iwl_wowlan_info_notif *converted_notif __free(kfree) = NULL;
+ u32 len = iwl_rx_packet_payload_len(pkt);
+ int wowlan_info_ver = iwl_fw_lookup_notif_ver(mld->fw,
+ PROT_OFFLOAD_GROUP,
+ WOWLAN_INFO_NOTIFICATION,
+ IWL_FW_CMD_VER_UNKNOWN);
+
+ if (wowlan_info_ver == 5) {
+ /* v5 format - validate before conversion */
+ const struct iwl_wowlan_info_notif_v5 *notif_v5 = (void *)pkt->data;
+
+ if (!iwl_mld_validate_wowlan_notif_size(mld, len,
+ sizeof(*notif_v5),
+ notif_v5->num_mlo_link_keys,
+ 5))
+ return true;
+
+ converted_notif = kzalloc(struct_size(converted_notif,
+ mlo_gtks,
+ notif_v5->num_mlo_link_keys),
+ GFP_ATOMIC);
+ if (!converted_notif) {
+ IWL_ERR(mld,
+ "Failed to allocate memory for converted wowlan_info_notif\n");
+ return true;
+ }
- if (IWL_FW_CHECK(mld, len < expected_len,
- "Invalid wowlan_info_notif (expected=%ud got=%ud)\n",
- expected_len, len))
+ iwl_mld_convert_wowlan_notif_v5(notif_v5,
+ converted_notif);
+ notif = converted_notif;
+ } else if (wowlan_info_ver == 6) {
+ notif = (void *)pkt->data;
+ if (!iwl_mld_validate_wowlan_notif_size(mld, len,
+ sizeof(*notif),
+ notif->num_mlo_link_keys,
+ 6))
+ return true;
+ } else {
+ /* smaller versions are not supported */
+ IWL_WARN(mld,
+ "Unsupported wowlan_info_notif version %d\n",
+ wowlan_info_ver);
return true;
+ }
if (IWL_FW_CHECK(mld, notif->tid_offloaded_tx != IWL_WOWLAN_OFFLOAD_TID,
"Invalid tid_offloaded_tx %d\n",
- wowlan_status->tid_offloaded_tx))
+ notif->tid_offloaded_tx))
return true;
iwl_mld_convert_gtk_resume_data(mld, wowlan_status, notif->gtk,
@@ -502,8 +657,10 @@ iwl_mld_handle_wowlan_info_notif(struct iwl_mld *mld,
wowlan_status->num_of_gtk_rekeys =
le32_to_cpu(notif->num_of_gtk_rekeys);
wowlan_status->wakeup_reasons = le32_to_cpu(notif->wakeup_reasons);
+
+ iwl_mld_convert_mlo_keys(mld, notif, wowlan_status);
+
return false;
- /* TODO: mlo_links (task=MLO)*/
}
static bool
@@ -679,8 +836,8 @@ iwl_mld_set_key_rx_seq_tids(struct ieee80211_key_conf *key,
}
static void
-iwl_mld_set_key_rx_seq(struct ieee80211_key_conf *key,
- struct iwl_mld_mcast_key_data *key_data)
+iwl_mld_update_mcast_rx_seq(struct ieee80211_key_conf *key,
+ struct iwl_mld_mcast_key_data *key_data)
{
switch (key->cipher) {
case WLAN_CIPHER_SUITE_CCMP:
@@ -707,51 +864,6 @@ iwl_mld_set_key_rx_seq(struct ieee80211_key_conf *key,
}
static void
-iwl_mld_d3_update_mcast_key(struct iwl_mld *mld,
- struct ieee80211_vif *vif,
- struct iwl_mld_wowlan_status *wowlan_status,
- struct ieee80211_key_conf *key,
- struct iwl_mld_mcast_key_data *key_data)
-{
- if (key->keyidx != key_data->id &&
- (key->keyidx < 4 || key->keyidx > 5)) {
- IWL_ERR(mld,
- "Unexpected keyId mismatch. Old keyId:%d, New keyId:%d\n",
- key->keyidx, key_data->id);
- return;
- }
-
- /* All installed keys are sent by the FW, even weren't
- * rekeyed during D3.
- * We remove an existing key if it has the same index as
- * a new key and a rekey has occurred during d3
- */
- if (wowlan_status->num_of_gtk_rekeys && key_data->len) {
- if (key->keyidx == 4 || key->keyidx == 5) {
- struct iwl_mld_vif *mld_vif =
- iwl_mld_vif_from_mac80211(vif);
- struct iwl_mld_link *mld_link;
- int link_id = vif->active_links ?
- __ffs(vif->active_links) : 0;
-
- mld_link = iwl_mld_link_dereference_check(mld_vif,
- link_id);
- if (WARN_ON(!mld_link))
- return;
-
- if (mld_link->igtk == key)
- mld_link->igtk = NULL;
- mld->num_igtks--;
- }
-
- ieee80211_remove_key(key);
- return;
- }
-
- iwl_mld_set_key_rx_seq(key, key_data);
-}
-
-static void
iwl_mld_update_ptk_rx_seq(struct iwl_mld *mld,
struct iwl_mld_wowlan_status *wowlan_status,
struct ieee80211_sta *sta,
@@ -774,7 +886,7 @@ iwl_mld_update_ptk_rx_seq(struct iwl_mld *mld,
return;
for (int tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
- for (int i = 1; i < mld->trans->num_rx_queues; i++)
+ for (int i = 1; i < mld->trans->info.num_rxqs; i++)
memcpy(mld_ptk_pn->q[i].pn[tid],
wowlan_status->ptk.aes_seq[tid].ccmp.pn,
IEEE80211_CCMP_PN_LEN);
@@ -792,170 +904,143 @@ iwl_mld_resume_keys_iter(struct ieee80211_hw *hw,
struct iwl_mld_wowlan_status *wowlan_status = data->wowlan_status;
u8 status_idx;
- /* TODO: check key link id (task=MLO) */
- if (data->unhandled_cipher)
- return;
-
- switch (key->cipher) {
- case WLAN_CIPHER_SUITE_WEP40:
- case WLAN_CIPHER_SUITE_WEP104:
- /* ignore WEP completely, nothing to do */
- return;
- case WLAN_CIPHER_SUITE_CCMP:
- case WLAN_CIPHER_SUITE_GCMP:
- case WLAN_CIPHER_SUITE_GCMP_256:
- case WLAN_CIPHER_SUITE_TKIP:
+ if (key->keyidx >= 0 && key->keyidx <= 3) {
+ /* PTK */
if (sta) {
iwl_mld_update_ptk_rx_seq(data->mld, wowlan_status,
sta, key,
key->cipher ==
WLAN_CIPHER_SUITE_TKIP);
- return;
+ /* GTK */
+ } else {
+ status_idx = key->keyidx == wowlan_status->gtk[1].id;
+ iwl_mld_update_mcast_rx_seq(key,
+ &wowlan_status->gtk[status_idx]);
}
+ }
- if (WARN_ON(data->gtk_cipher &&
- data->gtk_cipher != key->cipher))
- return;
+ /* IGTK */
+ if (key->keyidx == 4 || key->keyidx == 5) {
+ if (key->keyidx == wowlan_status->igtk.id)
+ iwl_mld_update_mcast_rx_seq(key, &wowlan_status->igtk);
+ }
- data->gtk_cipher = key->cipher;
- status_idx = key->keyidx == wowlan_status->gtk[1].id;
- iwl_mld_d3_update_mcast_key(data->mld, vif, wowlan_status, key,
- &wowlan_status->gtk[status_idx]);
- break;
- case WLAN_CIPHER_SUITE_BIP_GMAC_128:
- case WLAN_CIPHER_SUITE_BIP_GMAC_256:
- case WLAN_CIPHER_SUITE_BIP_CMAC_256:
- case WLAN_CIPHER_SUITE_AES_CMAC:
- if (key->keyidx == 4 || key->keyidx == 5) {
- if (WARN_ON(data->igtk_cipher &&
- data->igtk_cipher != key->cipher))
- return;
-
- data->igtk_cipher = key->cipher;
- iwl_mld_d3_update_mcast_key(data->mld, vif,
- wowlan_status,
- key, &wowlan_status->igtk);
- }
- if (key->keyidx == 6 || key->keyidx == 7) {
- if (WARN_ON(data->bigtk_cipher &&
- data->bigtk_cipher != key->cipher))
- return;
-
- data->bigtk_cipher = key->cipher;
- status_idx = key->keyidx == wowlan_status->bigtk[1].id;
- iwl_mld_d3_update_mcast_key(data->mld, vif,
- wowlan_status, key,
- &wowlan_status->bigtk[status_idx]);
- }
- break;
- default:
- data->unhandled_cipher = true;
- return;
+ /* BIGTK */
+ if (key->keyidx == 6 || key->keyidx == 7) {
+ status_idx = key->keyidx == wowlan_status->bigtk[1].id;
+ iwl_mld_update_mcast_rx_seq(key,
+ &wowlan_status->bigtk[status_idx]);
}
- data->num_keys++;
}
-static bool
+static void
iwl_mld_add_mcast_rekey(struct ieee80211_vif *vif,
struct iwl_mld *mld,
struct iwl_mld_mcast_key_data *key_data,
- struct ieee80211_bss_conf *link_conf,
- u32 cipher)
+ struct ieee80211_bss_conf *link_conf)
{
struct ieee80211_key_conf *key_config;
- struct {
- struct ieee80211_key_conf conf;
- u8 key[WOWLAN_KEY_MAX_SIZE];
- } conf = {
- .conf.cipher = cipher,
- .conf.keyidx = key_data->id,
- };
int link_id = vif->active_links ? __ffs(vif->active_links) : -1;
- BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_BIP_GMAC_128);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_BIP_GMAC_256);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_AES_CMAC);
- BUILD_BUG_ON(sizeof(conf.key) < sizeof(key_data->key));
-
if (!key_data->len)
- return true;
-
- switch (cipher) {
- case WLAN_CIPHER_SUITE_CCMP:
- case WLAN_CIPHER_SUITE_GCMP:
- conf.conf.keylen = WLAN_KEY_LEN_CCMP;
- break;
- case WLAN_CIPHER_SUITE_GCMP_256:
- conf.conf.keylen = WLAN_KEY_LEN_GCMP_256;
- break;
- case WLAN_CIPHER_SUITE_TKIP:
- conf.conf.keylen = WLAN_KEY_LEN_TKIP;
- break;
- case WLAN_CIPHER_SUITE_BIP_GMAC_128:
- conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_128;
- break;
- case WLAN_CIPHER_SUITE_BIP_GMAC_256:
- conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_256;
- break;
- case WLAN_CIPHER_SUITE_AES_CMAC:
- conf.conf.keylen = WLAN_KEY_LEN_AES_CMAC;
- break;
- case WLAN_CIPHER_SUITE_BIP_CMAC_256:
- conf.conf.keylen = WLAN_KEY_LEN_BIP_CMAC_256;
- break;
- default:
- WARN_ON(1);
- }
+ return;
- memcpy(conf.conf.key, key_data->key, conf.conf.keylen);
- key_config = ieee80211_gtk_rekey_add(vif, &conf.conf, link_id);
+ key_config = ieee80211_gtk_rekey_add(vif, key_data->id, key_data->key,
+ sizeof(key_data->key), link_id);
if (IS_ERR(key_config))
- return false;
+ return;
- iwl_mld_set_key_rx_seq(key_config, key_data);
+ iwl_mld_update_mcast_rx_seq(key_config, key_data);
/* The FW holds only one igtk so we keep track of the valid one */
if (key_config->keyidx == 4 || key_config->keyidx == 5) {
struct iwl_mld_link *mld_link =
iwl_mld_link_from_mac80211(link_conf);
- mld_link->igtk = key_config;
- mld->num_igtks++;
+
+ /* If we had more than one rekey, mac80211 will tell us to
+ * remove the old and add the new so we will update the IGTK in
+ * drv_set_key
+ */
+ if (mld_link->igtk && mld_link->igtk != key_config) {
+ /* mark the old IGTK as not in FW */
+ mld_link->igtk->hw_key_idx = STA_KEY_IDX_INVALID;
+ mld_link->igtk = key_config;
+ }
}
- return true;
+
+ /* Also keep track of the new BIGTK */
+ if (key_config->keyidx == 6 || key_config->keyidx == 7)
+ iwl_mld_track_bigtk(mld, vif, key_config, true);
}
-static bool
-iwl_mld_add_all_rekeys(struct ieee80211_vif *vif,
+static void
+iwl_mld_add_all_rekeys(struct iwl_mld *mld,
+ struct ieee80211_vif *vif,
struct iwl_mld_wowlan_status *wowlan_status,
- struct iwl_mld_resume_key_iter_data *key_iter_data,
struct ieee80211_bss_conf *link_conf)
{
int i;
for (i = 0; i < ARRAY_SIZE(wowlan_status->gtk); i++)
- if (!iwl_mld_add_mcast_rekey(vif, key_iter_data->mld,
- &wowlan_status->gtk[i],
- link_conf,
- key_iter_data->gtk_cipher))
- return false;
-
- if (!iwl_mld_add_mcast_rekey(vif, key_iter_data->mld,
- &wowlan_status->igtk,
- link_conf, key_iter_data->igtk_cipher))
- return false;
+ iwl_mld_add_mcast_rekey(vif, mld, &wowlan_status->gtk[i],
+ link_conf);
+
+ iwl_mld_add_mcast_rekey(vif, mld, &wowlan_status->igtk, link_conf);
for (i = 0; i < ARRAY_SIZE(wowlan_status->bigtk); i++)
- if (!iwl_mld_add_mcast_rekey(vif, key_iter_data->mld,
- &wowlan_status->bigtk[i],
- link_conf,
- key_iter_data->bigtk_cipher))
- return false;
+ iwl_mld_add_mcast_rekey(vif, mld, &wowlan_status->bigtk[i],
+ link_conf);
+}
- return true;
+static void iwl_mld_mlo_rekey(struct iwl_mld *mld,
+ struct iwl_mld_wowlan_status *wowlan_status,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mld_old_mlo_keys *old_keys __free(kfree) = NULL;
+
+ IWL_DEBUG_WOWLAN(mld, "Num of MLO Keys: %d\n", wowlan_status->num_mlo_keys);
+
+ if (!wowlan_status->num_mlo_keys)
+ return;
+
+ for (int i = 0; i < wowlan_status->num_mlo_keys; i++) {
+ struct iwl_mld_wowlan_mlo_key *mlo_key = &wowlan_status->mlo_keys[i];
+ struct ieee80211_key_conf *key;
+ struct ieee80211_key_seq seq;
+ u8 link_id = mlo_key->link_id;
+
+ if (IWL_FW_CHECK(mld, mlo_key->link_id >= IEEE80211_MLD_MAX_NUM_LINKS ||
+ mlo_key->idx >= 8 ||
+ mlo_key->type >= WOWLAN_MLO_GTK_KEY_NUM_TYPES,
+ "Invalid MLO key link_id %d, idx %d, type %d\n",
+ mlo_key->link_id, mlo_key->idx, mlo_key->type))
+ continue;
+
+ if (!(vif->valid_links & BIT(link_id)) ||
+ (vif->active_links & BIT(link_id)))
+ continue;
+
+ IWL_DEBUG_WOWLAN(mld, "Add MLO key id %d, link id %d\n",
+ mlo_key->idx, link_id);
+
+ key = ieee80211_gtk_rekey_add(vif, mlo_key->idx, mlo_key->key,
+ sizeof(mlo_key->key), link_id);
+
+ if (IS_ERR(key))
+ continue;
+
+ /*
+ * mac80211 expects the PN in big-endian
+ * also note that seq is a union of all cipher types
+ * (ccmp, gcmp, cmac, gmac), and they all have the same
+ * pn field (of length 6) so just copy it to ccmp.pn.
+ */
+ for (int j = 5; j >= 0; j--)
+ seq.ccmp.pn[5 - j] = mlo_key->pn[j];
+
+ /* group keys are non-QoS and use TID 0 */
+ ieee80211_set_key_rx_seq(key, 0, &seq);
+ }
}
static bool
@@ -978,23 +1063,19 @@ iwl_mld_update_sec_keys(struct iwl_mld *mld,
ieee80211_iter_keys(mld->hw, vif, iwl_mld_resume_keys_iter,
&key_iter_data);
- if (key_iter_data.unhandled_cipher)
- return false;
-
- IWL_DEBUG_WOWLAN(mld,
- "Number of installed keys: %d, Number of rekeys: %d\n",
- key_iter_data.num_keys,
+ IWL_DEBUG_WOWLAN(mld, "Number of rekeys: %d\n",
wowlan_status->num_of_gtk_rekeys);
- if (!key_iter_data.num_keys || !wowlan_status->num_of_gtk_rekeys)
+ if (!wowlan_status->num_of_gtk_rekeys)
return true;
- iwl_mld_add_all_rekeys(vif, wowlan_status, &key_iter_data,
+ iwl_mld_add_all_rekeys(mld, vif, wowlan_status,
link_conf);
+ iwl_mld_mlo_rekey(mld, wowlan_status, vif);
+
ieee80211_gtk_rekey_notify(vif, link_conf->bssid,
(void *)&replay_ctr, GFP_KERNEL);
- /* TODO: MLO rekey (task=MLO) */
return true;
}
@@ -1273,7 +1354,6 @@ static int iwl_mld_wait_d3_notif(struct iwl_mld *mld,
WIDE_ID(PROT_OFFLOAD_GROUP, D3_END_NOTIFICATION)
};
struct iwl_notification_wait wait_d3_notif;
- enum iwl_d3_status d3_status;
int ret;
if (with_wowlan)
@@ -1289,14 +1369,10 @@ static int iwl_mld_wait_d3_notif(struct iwl_mld *mld,
iwl_mld_handle_d3_notif,
resume_data);
- ret = iwl_trans_d3_resume(mld->trans, &d3_status, false, false);
- if (ret || d3_status != IWL_D3_STATUS_ALIVE) {
- if (d3_status != IWL_D3_STATUS_ALIVE) {
- IWL_INFO(mld, "Device was reset during suspend\n");
- ret = -ENOENT;
- } else {
- IWL_ERR(mld, "Transport resume failed\n");
- }
+ ret = iwl_trans_d3_resume(mld->trans, false);
+ if (ret) {
+ /* Avoid sending commands if the FW is dead */
+ iwl_trans_notify_fw_error(mld->trans);
iwl_remove_notification(&mld->notif_wait, &wait_d3_notif);
return ret;
}
@@ -1317,22 +1393,24 @@ int iwl_mld_no_wowlan_suspend(struct iwl_mld *mld)
struct iwl_d3_manager_config d3_cfg_cmd_data = {};
int ret;
+ if (mld->debug_max_sleep) {
+ d3_cfg_cmd_data.wakeup_host_timer =
+ cpu_to_le32(mld->debug_max_sleep);
+ d3_cfg_cmd_data.wakeup_flags =
+ cpu_to_le32(IWL_WAKEUP_D3_HOST_TIMER);
+ }
+
lockdep_assert_wiphy(mld->wiphy);
IWL_DEBUG_WOWLAN(mld, "Starting the no wowlan suspend flow\n");
iwl_mld_low_latency_stop(mld);
- /* This will happen if iwl_mld_supsend failed with FW error */
- if (mld->trans->state == IWL_TRANS_NO_FW &&
- test_bit(STATUS_FW_ERROR, &mld->trans->status))
- return -ENODEV;
-
ret = iwl_mld_update_device_power(mld, true);
if (ret) {
IWL_ERR(mld,
"d3 suspend: couldn't send power_device %d\n", ret);
- goto out;
+ return ret;
}
ret = iwl_mld_send_cmd_pdu(mld, D3_CONFIG_CMD,
@@ -1340,23 +1418,20 @@ int iwl_mld_no_wowlan_suspend(struct iwl_mld *mld)
if (ret) {
IWL_ERR(mld,
"d3 suspend: couldn't send D3_CONFIG_CMD %d\n", ret);
- goto out;
+ return ret;
}
- ret = iwl_trans_d3_suspend(mld->trans, false, false);
+ ret = iwl_trans_d3_suspend(mld->trans, false);
if (ret) {
IWL_ERR(mld, "d3 suspend: trans_d3_suspend failed %d\n", ret);
+ /* We are going to stop the FW. Avoid sending commands in that flow */
+ iwl_trans_notify_fw_error(mld->trans);
} else {
- mld->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;
+ /* Async notification might send hcmds, which is not allowed in suspend */
+ iwl_mld_cancel_async_notifications(mld);
mld->fw_status.in_d3 = true;
}
- out:
- if (ret) {
- mld->trans->state = IWL_TRANS_NO_FW;
- set_bit(STATUS_FW_ERROR, &mld->trans->status);
- }
-
return ret;
}
@@ -1372,23 +1447,16 @@ int iwl_mld_no_wowlan_resume(struct iwl_mld *mld)
IWL_DEBUG_WOWLAN(mld, "Starting the no wowlan resume flow\n");
- mld->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
mld->fw_status.in_d3 = false;
iwl_fw_dbg_read_d3_debug_data(&mld->fwrt);
- if (iwl_mld_fw_needs_restart(mld, NULL))
- ret = -ENODEV;
- else
- ret = iwl_mld_wait_d3_notif(mld, &resume_data, false);
+ ret = iwl_mld_wait_d3_notif(mld, &resume_data, false);
+ if (ret)
+ return ret;
if (!ret && (resume_data.d3_end_flags & IWL_D0I3_RESET_REQUIRE))
return -ENODEV;
- if (ret) {
- mld->trans->state = IWL_TRANS_NO_FW;
- set_bit(STATUS_FW_ERROR, &mld->trans->status);
- return ret;
- }
iwl_mld_low_latency_restart(mld);
return iwl_mld_update_device_power(mld, false);
@@ -1437,7 +1505,7 @@ iwl_mld_suspend_set_ucast_pn(struct iwl_mld *mld, struct ieee80211_sta *sta,
ieee80211_get_key_rx_seq(key, tid, &seq);
/* and use the internal data for all queues */
- for (int que = 1; que < mld->trans->num_rx_queues; que++) {
+ for (int que = 1; que < mld->trans->info.num_rxqs; que++) {
u8 *cur_pn = mld_ptk_pn->q[que].pn[tid];
if (memcmp(max_pn, cur_pn, IEEE80211_CCMP_PN_LEN) < 0)
@@ -1620,7 +1688,8 @@ static void
iwl_mld_set_wowlan_config_cmd(struct iwl_mld *mld,
struct cfg80211_wowlan *wowlan,
struct iwl_wowlan_config_cmd *wowlan_config_cmd,
- struct ieee80211_sta *ap_sta)
+ struct ieee80211_sta *ap_sta,
+ struct ieee80211_bss_conf *link)
{
wowlan_config_cmd->is_11n_connection =
ap_sta->deflink.ht_cap.ht_supported;
@@ -1630,6 +1699,9 @@ iwl_mld_set_wowlan_config_cmd(struct iwl_mld *mld,
if (ap_sta->mfp)
wowlan_config_cmd->flags |= IS_11W_ASSOC;
+ if (iwl_mld_beacon_protection_enabled(mld, link))
+ wowlan_config_cmd->flags |= HAS_BEACON_PROTECTION;
+
if (wowlan->disconnect)
wowlan_config_cmd->wakeup_filter |=
cpu_to_le32(IWL_WOWLAN_WAKEUP_BEACON_MISS |
@@ -1722,6 +1794,10 @@ iwl_mld_send_proto_offload(struct iwl_mld *mld,
u32 enabled = 0;
cmd = kzalloc(hcmd.len[0], GFP_KERNEL);
+ if (!cmd) {
+ IWL_DEBUG_WOWLAN(mld, "Failed to allocate proto offload cmd\n");
+ return -ENOMEM;
+ }
#if IS_ENABLED(CONFIG_IPV6)
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
@@ -1757,7 +1833,7 @@ iwl_mld_send_proto_offload(struct iwl_mld *mld,
addrconf_addr_solict_mult(&wowlan_data->target_ipv6_addrs[i],
&solicited_addr);
- for (j = 0; j < c; j++)
+ for (j = 0; j < n_nsc && j < c; j++)
if (ipv6_addr_cmp(&nsc[j].dest_ipv6_addr,
&solicited_addr) == 0)
break;
@@ -1827,7 +1903,7 @@ iwl_mld_wowlan_config(struct iwl_mld *mld, struct ieee80211_vif *bss_vif,
return ret;
iwl_mld_set_wowlan_config_cmd(mld, wowlan,
- &wowlan_config_cmd, ap_sta);
+ &wowlan_config_cmd, ap_sta, link_conf);
ret = iwl_mld_send_cmd_pdu(mld, WOWLAN_CONFIGURATION,
&wowlan_config_cmd);
if (ret)
@@ -1897,19 +1973,18 @@ int iwl_mld_wowlan_resume(struct iwl_mld *mld)
};
int link_id;
int ret;
- bool fw_err = false;
lockdep_assert_wiphy(mld->wiphy);
IWL_DEBUG_WOWLAN(mld, "Starting the wowlan resume flow\n");
- mld->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
if (!mld->fw_status.in_d3) {
IWL_DEBUG_WOWLAN(mld,
"Device_powered_off() was called during wowlan\n");
goto err;
}
+ mld->fw_status.resuming = true;
mld->fw_status.in_d3 = false;
mld->scan.last_start_time_jiffies = jiffies;
@@ -1929,15 +2004,10 @@ int iwl_mld_wowlan_resume(struct iwl_mld *mld)
iwl_fw_dbg_read_d3_debug_data(&mld->fwrt);
- if (iwl_mld_fw_needs_restart(mld, bss_vif)) {
- fw_err = true;
- goto err;
- }
-
resume_data.wowlan_status = kzalloc(sizeof(*resume_data.wowlan_status),
GFP_KERNEL);
if (!resume_data.wowlan_status)
- return -1;
+ return -ENOMEM;
if (mld->netdetect)
resume_data.notifs_expected |= IWL_D3_ND_MATCH_INFO;
@@ -1945,7 +2015,6 @@ int iwl_mld_wowlan_resume(struct iwl_mld *mld)
ret = iwl_mld_wait_d3_notif(mld, &resume_data, true);
if (ret) {
IWL_ERR(mld, "Couldn't get the d3 notifs %d\n", ret);
- fw_err = true;
goto err;
}
@@ -1982,14 +2051,11 @@ int iwl_mld_wowlan_resume(struct iwl_mld *mld)
goto out;
err:
- if (fw_err) {
- mld->trans->state = IWL_TRANS_NO_FW;
- set_bit(STATUS_FW_ERROR, &mld->trans->status);
- }
-
mld->fw_status.in_hw_restart = true;
ret = 1;
out:
+ mld->fw_status.resuming = false;
+
if (resume_data.wowlan_status) {
kfree(resume_data.wowlan_status->wake_packet);
kfree(resume_data.wowlan_status);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c
index 93f9f78e4276..b9c9cd3f44e4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c
@@ -86,7 +86,7 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mld *mld, char *buf,
if (count == 6 && !strcmp(buf, "nolog\n")) {
mld->fw_status.do_not_dump_once = true;
- set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &mld->trans->status);
+ mld->trans->suppress_cmd_error_once = true;
}
/* take the return value to make compiler happy - it will
@@ -546,6 +546,14 @@ iwl_mld_add_debugfs_files(struct iwl_mld *mld, struct dentry *debugfs_dir)
#endif
MLD_DEBUGFS_ADD_FILE(inject_packet, debugfs_dir, 0200);
+#ifdef CONFIG_PM_SLEEP
+ debugfs_create_u32("max_sleep", 0600, debugfs_dir,
+ &mld->debug_max_sleep);
+#endif
+
+ debugfs_create_bool("rx_ts_ptp", 0600, debugfs_dir,
+ &mld->monitor.ptp_time);
+
/* Create a symlink with mac80211. It will be removed when mac80211
* exits (before the opmode exits which removes the target.)
*/
@@ -993,12 +1001,16 @@ void iwl_mld_add_link_debugfs(struct ieee80211_hw *hw,
* If not, this is a per-link dir of a MLO vif, add in it the iwlmld
* dir.
*/
- if (!mld_link_dir)
+ if (!mld_link_dir) {
mld_link_dir = debugfs_create_dir("iwlmld", dir);
+ } else {
+ /* Release the reference from debugfs_lookup */
+ dput(mld_link_dir);
+ }
}
-static ssize_t iwl_dbgfs_fixed_rate_write(struct iwl_mld *mld, char *buf,
- size_t count, void *data)
+static ssize_t _iwl_dbgfs_fixed_rate_write(struct iwl_mld *mld, char *buf,
+ size_t count, void *data, bool v3)
{
struct ieee80211_link_sta *link_sta = data;
struct iwl_mld_link_sta *mld_link_sta;
@@ -1020,6 +1032,10 @@ static ssize_t iwl_dbgfs_fixed_rate_write(struct iwl_mld *mld, char *buf,
if (iwl_mld_dbgfs_fw_cmd_disabled(mld))
return -EIO;
+ /* input is in FW format (v2 or v3) so convert to v3 */
+ rate = iwl_v3_rate_from_v2_v3(cpu_to_le32(rate), v3);
+ rate = le32_to_cpu(iwl_v3_rate_to_v2_v3(rate, mld->fw_rates_ver_3));
+
ret = iwl_mld_send_tlc_dhc(mld, fw_sta_id,
partial ? IWL_TLC_DEBUG_PARTIAL_FIXED_RATE :
IWL_TLC_DEBUG_FIXED_RATE,
@@ -1033,6 +1049,18 @@ static ssize_t iwl_dbgfs_fixed_rate_write(struct iwl_mld *mld, char *buf,
return ret ? : count;
}
+static ssize_t iwl_dbgfs_fixed_rate_write(struct iwl_mld *mld, char *buf,
+ size_t count, void *data)
+{
+ return _iwl_dbgfs_fixed_rate_write(mld, buf, count, data, false);
+}
+
+static ssize_t iwl_dbgfs_fixed_rate_v3_write(struct iwl_mld *mld, char *buf,
+ size_t count, void *data)
+{
+ return _iwl_dbgfs_fixed_rate_write(mld, buf, count, data, true);
+}
+
static ssize_t iwl_dbgfs_tlc_dhc_write(struct iwl_mld *mld, char *buf,
size_t count, void *data)
{
@@ -1072,6 +1100,7 @@ static ssize_t iwl_dbgfs_tlc_dhc_write(struct iwl_mld *mld, char *buf,
LINK_STA_WIPHY_DEBUGFS_WRITE_OPS(tlc_dhc, 64);
LINK_STA_WIPHY_DEBUGFS_WRITE_OPS(fixed_rate, 64);
+LINK_STA_WIPHY_DEBUGFS_WRITE_OPS(fixed_rate_v3, 64);
void iwl_mld_add_link_sta_debugfs(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -1079,5 +1108,6 @@ void iwl_mld_add_link_sta_debugfs(struct ieee80211_hw *hw,
struct dentry *dir)
{
LINK_STA_DEBUGFS_ADD_FILE(fixed_rate, dir, 0200);
+ LINK_STA_DEBUGFS_ADD_FILE(fixed_rate_v3, dir, 0200);
LINK_STA_DEBUGFS_ADD_FILE(tlc_dhc, dir, 0200);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c
index f77ba21a174d..3464b3268712 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c
@@ -94,7 +94,7 @@ iwl_mld_ftm_set_target_chandef(struct iwl_mld *mld,
IWL_ERR(mld, "Unsupported BW in FTM request (%d)\n",
peer->chandef.width);
return -EINVAL;
-}
+ }
/* non EDCA based measurement must use HE preamble */
if (peer->ftm.trigger_based || peer->ftm.non_trigger_based)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/fw.c b/drivers/net/wireless/intel/iwlwifi/mld/fw.c
index 4b083d447ee2..19da521a4bab 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/fw.c
@@ -8,10 +8,10 @@
#include "fw/api/alive.h"
#include "fw/api/scan.h"
#include "fw/api/rx.h"
+#include "phy.h"
#include "fw/dbg.h"
#include "fw/pnvm.h"
#include "hcmd.h"
-#include "iwl-nvm-parse.h"
#include "power.h"
#include "mcc.h"
#include "led.h"
@@ -49,7 +49,7 @@ static int iwl_mld_send_rss_cfg_cmd(struct iwl_mld *mld)
/* Do not direct RSS traffic to Q 0 which is our fallback queue */
for (int i = 0; i < ARRAY_SIZE(cmd.indirection_table); i++)
cmd.indirection_table[i] =
- 1 + (i % (mld->trans->num_rx_queues - 1));
+ 1 + (i % (mld->trans->info.num_rxqs - 1));
netdev_rss_key_fill(cmd.secret_key, sizeof(cmd.secret_key));
return iwl_mld_send_cmd_pdu(mld, RSS_CONFIG_CMD, &cmd);
@@ -99,17 +99,23 @@ static void iwl_mld_alive_imr_data(struct iwl_trans *trans,
}
}
+struct iwl_mld_alive_data {
+ __le32 sku_id[3];
+ bool valid;
+};
+
static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
struct iwl_rx_packet *pkt, void *data)
{
unsigned int pkt_len = iwl_rx_packet_payload_len(pkt);
+ unsigned int expected_sz;
struct iwl_mld *mld =
container_of(notif_wait, struct iwl_mld, notif_wait);
struct iwl_trans *trans = mld->trans;
u32 version = iwl_fw_lookup_notif_ver(mld->fw, LEGACY_GROUP,
UCODE_ALIVE_NTFY, 0);
- struct iwl_alive_ntf_v6 *palive;
- bool *alive_valid = data;
+ struct iwl_mld_alive_data *alive_data = data;
+ struct iwl_alive_ntf *palive;
struct iwl_umac_alive *umac;
struct iwl_lmac_alive *lmac1;
struct iwl_lmac_alive *lmac2 = NULL;
@@ -117,7 +123,18 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
u32 umac_error_table;
u16 status;
- if (version < 6 || version > 7 || pkt_len != sizeof(*palive))
+ switch (version) {
+ case 7:
+ expected_sz = sizeof(struct iwl_alive_ntf_v7);
+ break;
+ case 8:
+ expected_sz = sizeof(struct iwl_alive_ntf);
+ break;
+ default:
+ return false;
+ }
+
+ if (pkt_len != expected_sz)
return false;
palive = (void *)pkt->data;
@@ -129,12 +146,15 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
lmac2 = &palive->lmac_data[1];
status = le16_to_cpu(palive->status);
- trans->sku_id[0] = le32_to_cpu(palive->sku_id.data[0]);
- trans->sku_id[1] = le32_to_cpu(palive->sku_id.data[1]);
- trans->sku_id[2] = le32_to_cpu(palive->sku_id.data[2]);
+ BUILD_BUG_ON(sizeof(alive_data->sku_id) !=
+ sizeof(palive->sku_id.data));
+ memcpy(alive_data->sku_id, palive->sku_id.data,
+ sizeof(palive->sku_id.data));
IWL_DEBUG_FW(mld, "Got sku_id: 0x0%x 0x0%x 0x0%x\n",
- trans->sku_id[0], trans->sku_id[1], trans->sku_id[2]);
+ le32_to_cpu(alive_data->sku_id[0]),
+ le32_to_cpu(alive_data->sku_id[1]),
+ le32_to_cpu(alive_data->sku_id[2]));
lmac_error_event_table =
le32_to_cpu(lmac1->dbg_ptrs.error_event_table_ptr);
@@ -147,13 +167,9 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
umac_error_table = le32_to_cpu(umac->dbg_ptrs.error_info_addr) &
~FW_ADDR_CACHE_CONTROL;
- if (umac_error_table >= trans->cfg->min_umac_error_event_table)
- iwl_fw_umac_set_alive_err_table(trans, umac_error_table);
- else
- IWL_ERR(mld, "Not valid error log pointer 0x%08X\n",
- umac_error_table);
+ iwl_fw_umac_set_alive_err_table(trans, umac_error_table);
- *alive_valid = status == IWL_ALIVE_STATUS_OK;
+ alive_data->valid = status == IWL_ALIVE_STATUS_OK;
IWL_DEBUG_FW(mld,
"Alive ucode status 0x%04x revision 0x%01X 0x%01X\n",
@@ -167,9 +183,12 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
le32_to_cpu(umac->umac_major),
le32_to_cpu(umac->umac_minor));
- if (version >= 7)
- IWL_DEBUG_FW(mld, "FW alive flags 0x%x\n",
- le16_to_cpu(palive->flags));
+ IWL_DEBUG_FW(mld, "FW alive flags 0x%x\n",
+ le16_to_cpu(palive->flags));
+
+ if (version >= 8)
+ IWL_DEBUG_FW(mld, "platform_id 0x%llx\n",
+ le64_to_cpu(palive->platform_id));
iwl_fwrt_update_fw_versions(&mld->fwrt, lmac1, umac);
@@ -208,24 +227,22 @@ static void iwl_mld_print_alive_notif_timeout(struct iwl_mld *mld)
pc_data->pc_address);
}
-static int iwl_mld_load_fw_wait_alive(struct iwl_mld *mld)
+static int iwl_mld_load_fw_wait_alive(struct iwl_mld *mld,
+ struct iwl_mld_alive_data *alive_data)
{
- const struct fw_img *fw =
- iwl_get_ucode_image(mld->fw, IWL_UCODE_REGULAR);
static const u16 alive_cmd[] = { UCODE_ALIVE_NTFY };
struct iwl_notification_wait alive_wait;
- bool alive_valid = false;
int ret;
lockdep_assert_wiphy(mld->wiphy);
iwl_init_notification_wait(&mld->notif_wait, &alive_wait,
alive_cmd, ARRAY_SIZE(alive_cmd),
- iwl_alive_fn, &alive_valid);
+ iwl_alive_fn, alive_data);
iwl_dbg_tlv_time_point(&mld->fwrt, IWL_FW_INI_TIME_POINT_EARLY, NULL);
- ret = iwl_trans_start_fw(mld->trans, fw, true);
+ ret = iwl_trans_start_fw(mld->trans, mld->fw, IWL_UCODE_REGULAR, true);
if (ret) {
iwl_remove_notification(&mld->notif_wait, &alive_wait);
return ret;
@@ -239,28 +256,26 @@ static int iwl_mld_load_fw_wait_alive(struct iwl_mld *mld)
iwl_fw_dbg_error_collect(&mld->fwrt,
FW_DBG_TRIGGER_ALIVE_TIMEOUT);
iwl_mld_print_alive_notif_timeout(mld);
- goto alive_failure;
+ return ret;
}
- if (!alive_valid) {
+ if (!alive_data->valid) {
IWL_ERR(mld, "Loaded firmware is not valid!\n");
- ret = -EIO;
- goto alive_failure;
+ return -EIO;
}
- iwl_trans_fw_alive(mld->trans, 0);
+ iwl_trans_fw_alive(mld->trans);
return 0;
-
-alive_failure:
- iwl_trans_stop_device(mld->trans);
- return ret;
}
static int iwl_mld_run_fw_init_sequence(struct iwl_mld *mld)
{
struct iwl_notification_wait init_wait;
- struct iwl_init_extended_cfg_cmd init_cfg = {};
+ struct iwl_init_extended_cfg_cmd init_cfg = {
+ .init_flags = cpu_to_le32(BIT(IWL_INIT_PHY)),
+ };
+ struct iwl_mld_alive_data alive_data = {};
static const u16 init_complete[] = {
INIT_COMPLETE_NOTIF,
};
@@ -268,19 +283,15 @@ static int iwl_mld_run_fw_init_sequence(struct iwl_mld *mld)
lockdep_assert_wiphy(mld->wiphy);
- ret = iwl_mld_load_fw_wait_alive(mld);
+ ret = iwl_mld_load_fw_wait_alive(mld, &alive_data);
if (ret)
return ret;
- mld->trans->step_urm =
- !!(iwl_read_umac_prph(mld->trans, CNVI_PMU_STEP_FLOW) &
- CNVI_PMU_STEP_FLOW_FORCE_URM);
-
ret = iwl_pnvm_load(mld->trans, &mld->notif_wait,
- &mld->fw->ucode_capa);
+ mld->fw, alive_data.sku_id);
if (ret) {
IWL_ERR(mld, "Timeout waiting for PNVM load %d\n", ret);
- goto init_failure;
+ return ret;
}
iwl_dbg_tlv_time_point(&mld->fwrt, IWL_FW_INI_TIME_POINT_AFTER_ALIVE,
@@ -298,31 +309,24 @@ static int iwl_mld_run_fw_init_sequence(struct iwl_mld *mld)
if (ret) {
IWL_ERR(mld, "Failed to send init config command: %d\n", ret);
iwl_remove_notification(&mld->notif_wait, &init_wait);
- goto init_failure;
+ return ret;
+ }
+
+ ret = iwl_mld_send_phy_cfg_cmd(mld);
+ if (ret) {
+ IWL_ERR(mld, "Failed to send PHY config command: %d\n", ret);
+ iwl_remove_notification(&mld->notif_wait, &init_wait);
+ return ret;
}
ret = iwl_wait_notification(&mld->notif_wait, &init_wait,
MLD_INIT_COMPLETE_TIMEOUT);
if (ret) {
IWL_ERR(mld, "Failed to get INIT_COMPLETE %d\n", ret);
- goto init_failure;
- }
-
- if (!mld->nvm_data) {
- mld->nvm_data = iwl_get_nvm(mld->trans, mld->fw, 0, 0);
- if (IS_ERR(mld->nvm_data)) {
- ret = PTR_ERR(mld->nvm_data);
- mld->nvm_data = NULL;
- IWL_ERR(mld, "Failed to read NVM: %d\n", ret);
- goto init_failure;
- }
+ return ret;
}
return 0;
-
-init_failure:
- iwl_trans_stop_device(mld->trans);
- return ret;
}
int iwl_mld_load_fw(struct iwl_mld *mld)
@@ -333,16 +337,12 @@ int iwl_mld_load_fw(struct iwl_mld *mld)
ret = iwl_trans_start_hw(mld->trans);
if (ret)
- goto err;
+ return ret;
ret = iwl_mld_run_fw_init_sequence(mld);
if (ret)
goto err;
- ret = iwl_mld_init_mcc(mld);
- if (ret)
- goto err;
-
mld->fw_status.running = true;
return 0;
@@ -361,9 +361,10 @@ void iwl_mld_stop_fw(struct iwl_mld *mld)
iwl_trans_stop_device(mld->trans);
- wiphy_work_cancel(mld->wiphy, &mld->async_handlers_wk);
-
- iwl_mld_purge_async_handlers_list(mld);
+ /* HW is stopped, no more coming RX. Cancel all notifications in
+ * case they were sent just before stopping the HW.
+ */
+ iwl_mld_cancel_async_notifications(mld);
mld->fw_status.running = false;
}
@@ -526,7 +527,7 @@ int iwl_mld_start_fw(struct iwl_mld *mld)
ret = iwl_mld_load_fw(mld);
if (IWL_FW_CHECK(mld, ret, "Failed to start firmware %d\n", ret)) {
iwl_fw_dbg_error_collect(&mld->fwrt, FW_DBG_TRIGGER_DRIVER);
- goto error;
+ return ret;
}
IWL_DEBUG_INFO(mld, "uCode started.\n");
@@ -535,6 +536,10 @@ int iwl_mld_start_fw(struct iwl_mld *mld)
if (ret)
goto error;
+ ret = iwl_mld_init_mcc(mld);
+ if (ret)
+ goto error;
+
return 0;
error:
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.c b/drivers/net/wireless/intel/iwlwifi/mld/iface.c
index e49e2260ac05..a5ececfc13e4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/iface.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.c
@@ -22,9 +22,17 @@ void iwl_mld_cleanup_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
struct iwl_mld *mld = mld_vif->mld;
struct iwl_mld_link *link;
+ mld_vif->emlsr.blocked_reasons &= ~IWL_MLD_EMLSR_BLOCKED_ROC;
+
+ if (mld_vif->aux_sta.sta_id != IWL_INVALID_STA)
+ iwl_mld_free_internal_sta(mld, &mld_vif->aux_sta);
+
/* EMLSR is turned back on during recovery */
vif->driver_flags &= ~IEEE80211_VIF_EML_ACTIVE;
+ if (mld_vif->roc_activity != ROC_NUM_ACTIVITIES)
+ ieee80211_remain_on_channel_expired(mld->hw);
+
mld_vif->roc_activity = ROC_NUM_ACTIVITIES;
for_each_mld_vif_valid_link(mld_vif, link) {
@@ -47,6 +55,8 @@ void iwl_mld_cleanup_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
ieee80211_iter_keys(mld->hw, vif, iwl_mld_cleanup_keys_iter, NULL);
+ wiphy_delayed_work_cancel(mld->wiphy, &mld_vif->mlo_scan_start_wk);
+
CLEANUP_STRUCT(mld_vif);
}
@@ -103,6 +113,16 @@ static bool iwl_mld_is_nic_ack_enabled(struct iwl_mld *mld,
IEEE80211_HE_MAC_CAP2_ACK_EN);
}
+static void iwl_mld_set_he_support(struct iwl_mld *mld,
+ struct ieee80211_vif *vif,
+ struct iwl_mac_config_cmd *cmd)
+{
+ if (vif->type == NL80211_IFTYPE_AP)
+ cmd->wifi_gen.he_ap_support = 1;
+ else
+ cmd->wifi_gen.he_support = 1;
+}
+
/* fill the common part for all interface types */
static void iwl_mld_mac_cmd_fill_common(struct iwl_mld *mld,
struct ieee80211_vif *vif,
@@ -138,12 +158,8 @@ static void iwl_mld_mac_cmd_fill_common(struct iwl_mld *mld,
* and enable both when we have MLO.
*/
if (ieee80211_vif_is_mld(vif)) {
- if (vif->type == NL80211_IFTYPE_AP)
- cmd->he_ap_support = cpu_to_le16(1);
- else
- cmd->he_support = cpu_to_le16(1);
-
- cmd->eht_support = cpu_to_le32(1);
+ iwl_mld_set_he_support(mld, vif, cmd);
+ cmd->wifi_gen.eht_support = 1;
return;
}
@@ -151,10 +167,7 @@ static void iwl_mld_mac_cmd_fill_common(struct iwl_mld *mld,
if (!link_conf->he_support)
continue;
- if (vif->type == NL80211_IFTYPE_AP)
- cmd->he_ap_support = cpu_to_le16(1);
- else
- cmd->he_support = cpu_to_le16(1);
+ iwl_mld_set_he_support(mld, vif, cmd);
/* EHT, if supported, was already set above */
break;
@@ -226,11 +239,6 @@ static void iwl_mld_fill_mac_cmd_sta(struct iwl_mld *mld,
if (vif->probe_req_reg && vif->cfg.assoc && vif->p2p)
cmd->filter_flags |=
cpu_to_le32(MAC_CFG_FILTER_ACCEPT_PROBE_REQ);
-
- if (vif->p2p)
- cmd->client.ctwin =
- cpu_to_le32(vif->bss_conf.p2p_noa_attr.oppps_ctwindow &
- IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
}
static void iwl_mld_fill_mac_cmd_ap(struct iwl_mld *mld,
@@ -365,6 +373,17 @@ int iwl_mld_mac_fw_action(struct iwl_mld *mld, struct ieee80211_vif *vif,
return iwl_mld_send_mac_cmd(mld, &cmd);
}
+static void iwl_mld_mlo_scan_start_wk(struct wiphy *wiphy,
+ struct wiphy_work *wk)
+{
+ struct iwl_mld_vif *mld_vif = container_of(wk, struct iwl_mld_vif,
+ mlo_scan_start_wk.work);
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
+
+ iwl_mld_int_mlo_scan(mld, iwl_mld_vif_to_mac80211(mld_vif));
+}
+
IWL_MLD_ALLOC_FN(vif, vif)
/* Constructor function for struct iwl_mld_vif */
@@ -392,7 +411,10 @@ iwl_mld_init_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
iwl_mld_emlsr_prevent_done_wk);
wiphy_delayed_work_init(&mld_vif->emlsr.tmp_non_bss_done_wk,
iwl_mld_emlsr_tmp_non_bss_done_wk);
+ wiphy_delayed_work_init(&mld_vif->mlo_scan_start_wk,
+ iwl_mld_mlo_scan_start_wk);
}
+ iwl_mld_init_internal_sta(&mld_vif->aux_sta);
return 0;
}
@@ -415,24 +437,21 @@ int iwl_mld_add_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
return ret;
}
-int iwl_mld_rm_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
+void iwl_mld_rm_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
{
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
- int ret;
lockdep_assert_wiphy(mld->wiphy);
- ret = iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_REMOVE);
+ iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_REMOVE);
if (WARN_ON(mld_vif->fw_id >= ARRAY_SIZE(mld->fw_id_to_vif)))
- return -EINVAL;
+ return;
RCU_INIT_POINTER(mld->fw_id_to_vif[mld_vif->fw_id], NULL);
iwl_mld_cancel_notifications_of_object(mld, IWL_MLD_OBJECT_TYPE_VIF,
mld_vif->fw_id);
-
- return ret;
}
void iwl_mld_set_vif_associated(struct iwl_mld *mld,
@@ -509,6 +528,19 @@ void iwl_mld_handle_probe_resp_data_notif(struct iwl_mld *mld,
mld_link = &iwl_mld_vif_from_mac80211(vif)->deflink;
+ /* len_low should be 2 + n*13 (where n is the number of descriptors.
+ * 13 is the size of a NoA descriptor). We can have either one or two
+ * descriptors.
+ */
+ if (IWL_FW_CHECK(mld, notif->noa_active &&
+ notif->noa_attr.len_low != 2 +
+ sizeof(struct ieee80211_p2p_noa_desc) &&
+ notif->noa_attr.len_low != 2 +
+ sizeof(struct ieee80211_p2p_noa_desc) * 2,
+ "Invalid noa_attr.len_low (%d)\n",
+ notif->noa_attr.len_low))
+ return;
+
new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
if (!new_data)
return;
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.h b/drivers/net/wireless/intel/iwlwifi/mld/iface.h
index ec14d0736cee..a3573d20f214 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/iface.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.h
@@ -10,6 +10,7 @@
#include "link.h"
#include "session-protect.h"
#include "d3.h"
+#include "fw/api/time-event.h"
enum iwl_mld_cca_40mhz_wa_status {
CCA_40_MHZ_WA_NONE,
@@ -59,6 +60,7 @@ enum iwl_mld_emlsr_blocked {
* loaded enough to justify EMLSR.
* @IWL_MLD_EMLSR_EXIT_RFI: Exit EMLSR due to RFI
* @IWL_MLD_EMLSR_EXIT_FW_REQUEST: Exit EMLSR because the FW requested it
+ * @IWL_MLD_EMLSR_EXIT_INVALID: internal exit reason due to invalid data
*/
enum iwl_mld_emlsr_exit {
IWL_MLD_EMLSR_EXIT_BLOCK = 0x1,
@@ -72,6 +74,7 @@ enum iwl_mld_emlsr_exit {
IWL_MLD_EMLSR_EXIT_CHAN_LOAD = 0x100,
IWL_MLD_EMLSR_EXIT_RFI = 0x200,
IWL_MLD_EMLSR_EXIT_FW_REQUEST = 0x400,
+ IWL_MLD_EMLSR_EXIT_INVALID = 0x800,
};
/**
@@ -84,6 +87,8 @@ enum iwl_mld_emlsr_exit {
* @last_exit_reason: Reason for the last EMLSR exit
* @last_exit_ts: Time of the last EMLSR exit (if @last_exit_reason is non-zero)
* @exit_repeat_count: Number of times EMLSR was exited for the same reason
+ * @last_entry_ts: the time of the last EMLSR entry (if iwl_mld_emlsr_active()
+ * is true)
* @unblock_tpt_wk: Unblock EMLSR because the throughput limit was reached
* @check_tpt_wk: a worker to check if IWL_MLD_EMLSR_BLOCKED_TPT should be
* added, for example if there is no longer enough traffic.
@@ -102,6 +107,7 @@ struct iwl_mld_emlsr {
enum iwl_mld_emlsr_exit last_exit_reason;
unsigned long last_exit_ts;
u8 exit_repeat_count;
+ unsigned long last_entry_ts;
);
struct wiphy_work unblock_tpt_wk;
@@ -119,12 +125,8 @@ struct iwl_mld_emlsr {
* @ap_sta: pointer to AP sta, for easier access to it.
* Relevant only for STA vifs.
* @authorized: indicates the AP station was set to authorized
- * @bigtks: BIGTKs of the AP, for beacon protection.
- * Only valid for STA. (FIXME: needs to be per link)
* @num_associated_stas: number of associated STAs. Relevant only for AP mode.
* @ap_ibss_active: whether the AP/IBSS was started
- * @roc_activity: the id of the roc_activity running. Relevant for p2p device
- * only. Set to %ROC_NUM_ACTIVITIES when not in use.
* @cca_40mhz_workaround: When we are connected in 2.4 GHz and 40 MHz, and the
* environment is too loaded, we work around this by reconnecting to the
* same AP with 20 MHz. This manages the status of the workaround.
@@ -132,6 +134,8 @@ struct iwl_mld_emlsr {
* @low_latency_causes: bit flags, indicating the causes for low-latency,
* see @iwl_mld_low_latency_cause.
* @ps_disabled: indicates that PS is disabled for this interface
+ * @last_link_activation_time: last time a link was activated, for
+ * deferring MLO scans (to make them more reliable)
* @mld: pointer to the mld structure.
* @deflink: default link data, for use in non-MLO,
* @link: reference to link data for each valid link, for use in MLO.
@@ -140,6 +144,10 @@ struct iwl_mld_emlsr {
* @use_ps_poll: use ps_poll frames
* @disable_bf: disable beacon filter
* @dbgfs_slink: debugfs symlink for this interface
+ * @roc_activity: the id of the roc_activity running. Relevant for STA and
+ * p2p device only. Set to %ROC_NUM_ACTIVITIES when not in use.
+ * @aux_sta: station used for remain on channel. Used in P2P device.
+ * @mlo_scan_start_wk: worker to start a deferred MLO scan
*/
struct iwl_mld_vif {
/* Add here fields that need clean up on restart */
@@ -148,16 +156,15 @@ struct iwl_mld_vif {
struct iwl_mld_session_protect session_protect;
struct ieee80211_sta *ap_sta;
bool authorized;
- struct ieee80211_key_conf __rcu *bigtks[2];
u8 num_associated_stas;
bool ap_ibss_active;
- u32 roc_activity;
enum iwl_mld_cca_40mhz_wa_status cca_40mhz_workaround;
#ifdef CONFIG_IWLWIFI_DEBUGFS
bool beacon_inject_active;
#endif
u8 low_latency_causes;
bool ps_disabled;
+ time64_t last_link_activation_time;
);
/* And here fields that survive a fw restart */
struct iwl_mld *mld;
@@ -174,6 +181,10 @@ struct iwl_mld_vif {
bool disable_bf;
struct dentry *dbgfs_slink;
#endif
+ enum iwl_roc_activity roc_activity;
+ struct iwl_mld_int_sta aux_sta;
+
+ struct wiphy_delayed_work mlo_scan_start_wk;
};
static inline struct iwl_mld_vif *
@@ -182,6 +193,12 @@ iwl_mld_vif_from_mac80211(struct ieee80211_vif *vif)
return (void *)vif->drv_priv;
}
+static inline struct ieee80211_vif *
+iwl_mld_vif_to_mac80211(struct iwl_mld_vif *mld_vif)
+{
+ return container_of((void *)mld_vif, struct ieee80211_vif, drv_priv);
+}
+
#define iwl_mld_link_dereference_check(mld_vif, link_id) \
rcu_dereference_check((mld_vif)->link[link_id], \
lockdep_is_held(&mld_vif->mld->wiphy->mtx))
@@ -207,7 +224,7 @@ void iwl_mld_cleanup_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
int iwl_mld_mac_fw_action(struct iwl_mld *mld, struct ieee80211_vif *vif,
u32 action);
int iwl_mld_add_vif(struct iwl_mld *mld, struct ieee80211_vif *vif);
-int iwl_mld_rm_vif(struct iwl_mld *mld, struct ieee80211_vif *vif);
+void iwl_mld_rm_vif(struct iwl_mld *mld, struct ieee80211_vif *vif);
void iwl_mld_set_vif_associated(struct iwl_mld *mld,
struct ieee80211_vif *vif);
u8 iwl_mld_get_fw_bss_vifs_ids(struct iwl_mld *mld);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/key.c b/drivers/net/wireless/intel/iwlwifi/mld/key.c
index 0eff13e5ffd5..04192c5f07ff 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/key.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/key.c
@@ -129,6 +129,12 @@ static int iwl_mld_add_key_to_fw(struct iwl_mld *mld, u32 sta_mask,
bool tkip = key->cipher == WLAN_CIPHER_SUITE_TKIP;
int max_key_len = sizeof(cmd.u.add.key);
+#ifdef CONFIG_PM_SLEEP
+ /* If there was a rekey in wowlan, FW already has the key */
+ if (mld->fw_status.resuming)
+ return 0;
+#endif
+
if (WARN_ON(!sta_mask))
return -EINVAL;
@@ -160,6 +166,12 @@ static void iwl_mld_remove_key_from_fw(struct iwl_mld *mld, u32 sta_mask,
.u.remove.key_flags = cpu_to_le32(key_flags),
};
+#ifdef CONFIG_PM_SLEEP
+ /* If there was a rekey in wowlan, FW already removed the key */
+ if (mld->fw_status.resuming)
+ return;
+#endif
+
if (WARN_ON(!sta_mask))
return;
@@ -356,3 +368,41 @@ int iwl_mld_update_sta_keys(struct iwl_mld *mld,
&data);
return data.err;
}
+
+void iwl_mld_track_bigtk(struct iwl_mld *mld,
+ struct ieee80211_vif *vif,
+ struct ieee80211_key_conf *key, bool add)
+{
+ struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
+ struct iwl_mld_link *link;
+
+ if (vif->type != NL80211_IFTYPE_STATION)
+ return;
+
+ if (WARN_ON(key->keyidx < 6 || key->keyidx > 7))
+ return;
+
+ if (WARN_ON(key->link_id < 0))
+ return;
+
+ link = iwl_mld_link_dereference_check(mld_vif, key->link_id);
+ if (WARN_ON(!link))
+ return;
+
+ if (add)
+ rcu_assign_pointer(link->bigtks[key->keyidx - 6], key);
+ else
+ RCU_INIT_POINTER(link->bigtks[key->keyidx - 6], NULL);
+}
+
+bool iwl_mld_beacon_protection_enabled(struct iwl_mld *mld,
+ struct ieee80211_bss_conf *link)
+{
+ struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link);
+
+ if (WARN_ON(!mld_link))
+ return false;
+
+ return rcu_access_pointer(mld_link->bigtks[0]) ||
+ rcu_access_pointer(mld_link->bigtks[1]);
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/key.h b/drivers/net/wireless/intel/iwlwifi/mld/key.h
index a68ea48913be..5a9efdaa3b03 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/key.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/key.h
@@ -36,4 +36,11 @@ iwl_mld_cleanup_keys_iter(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
key->hw_key_idx = STA_KEY_IDX_INVALID;
}
+void iwl_mld_track_bigtk(struct iwl_mld *mld,
+ struct ieee80211_vif *vif,
+ struct ieee80211_key_conf *key, bool add);
+
+bool iwl_mld_beacon_protection_enabled(struct iwl_mld *mld,
+ struct ieee80211_bss_conf *link);
+
#endif /* __iwl_mld_key_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c
index 82a4979a3af3..d89840a1152b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c
@@ -242,27 +242,9 @@ static bool iwl_mld_fill_mu_edca(struct iwl_mld *mld,
return true;
}
-static u8 iwl_mld_sta_rx_bw_to_fw(enum ieee80211_sta_rx_bandwidth bw)
-{
- switch (bw) {
- default: /* potential future values not supported by this hw/driver */
- case IEEE80211_STA_RX_BW_20:
- return IWL_LINK_MODIFY_BW_20;
- case IEEE80211_STA_RX_BW_40:
- return IWL_LINK_MODIFY_BW_40;
- case IEEE80211_STA_RX_BW_80:
- return IWL_LINK_MODIFY_BW_80;
- case IEEE80211_STA_RX_BW_160:
- return IWL_LINK_MODIFY_BW_160;
- case IEEE80211_STA_RX_BW_320:
- return IWL_LINK_MODIFY_BW_320;
- }
-}
-
-static int _iwl_mld_change_link_in_fw(struct iwl_mld *mld,
- struct ieee80211_bss_conf *link,
- enum ieee80211_sta_rx_bandwidth bw,
- u32 changes)
+int
+iwl_mld_change_link_in_fw(struct iwl_mld *mld, struct ieee80211_bss_conf *link,
+ u32 changes)
{
struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link);
struct ieee80211_vif *vif = link->vif;
@@ -318,9 +300,6 @@ static int _iwl_mld_change_link_in_fw(struct iwl_mld *mld,
cmd.bi = cpu_to_le32(link->beacon_int);
cmd.dtim_interval = cpu_to_le32(link->beacon_int * link->dtim_period);
- if (changes & LINK_CONTEXT_MODIFY_BANDWIDTH)
- cmd.modify_bandwidth = iwl_mld_sta_rx_bw_to_fw(bw);
-
/* Configure HE parameters only if HE is supported, and only after
* the parameters are set in mac80211 (meaning after assoc)
*/
@@ -382,28 +361,11 @@ send_cmd:
return iwl_mld_send_link_cmd(mld, &cmd, FW_CTXT_ACTION_MODIFY);
}
-int iwl_mld_change_link_in_fw(struct iwl_mld *mld,
- struct ieee80211_bss_conf *link,
- u32 changes)
-{
- if (WARN_ON(changes & LINK_CONTEXT_MODIFY_BANDWIDTH))
- changes &= ~LINK_CONTEXT_MODIFY_BANDWIDTH;
-
- return _iwl_mld_change_link_in_fw(mld, link, 0, changes);
-}
-
-int iwl_mld_change_link_omi_bw(struct iwl_mld *mld,
- struct ieee80211_bss_conf *link,
- enum ieee80211_sta_rx_bandwidth bw)
-{
- return _iwl_mld_change_link_in_fw(mld, link, bw,
- LINK_CONTEXT_MODIFY_BANDWIDTH);
-}
-
int iwl_mld_activate_link(struct iwl_mld *mld,
struct ieee80211_bss_conf *link)
{
struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link);
+ struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(link->vif);
int ret;
lockdep_assert_wiphy(mld->wiphy);
@@ -411,13 +373,15 @@ int iwl_mld_activate_link(struct iwl_mld *mld,
if (WARN_ON(!mld_link || mld_link->active))
return -EINVAL;
- mld_link->rx_omi.exit_ts = jiffies;
mld_link->active = true;
ret = iwl_mld_change_link_in_fw(mld, link,
LINK_CONTEXT_MODIFY_ACTIVE);
if (ret)
mld_link->active = false;
+ else
+ mld_vif->last_link_activation_time =
+ ktime_get_boottime_seconds();
return ret;
}
@@ -473,303 +437,6 @@ iwl_mld_rm_link_from_fw(struct iwl_mld *mld, struct ieee80211_bss_conf *link)
iwl_mld_send_link_cmd(mld, &cmd, FW_CTXT_ACTION_REMOVE);
}
-static void iwl_mld_omi_bw_update(struct iwl_mld *mld,
- struct ieee80211_bss_conf *link_conf,
- struct iwl_mld_link *mld_link,
- struct ieee80211_link_sta *link_sta,
- enum ieee80211_sta_rx_bandwidth bw,
- bool ap_update)
-{
- enum ieee80211_sta_rx_bandwidth apply_bw;
-
- mld_link->rx_omi.desired_bw = bw;
-
- /* Can't update OMI while already in progress, desired_bw was
- * set so on FW notification the worker will see the change
- * and apply new the new desired bw.
- */
- if (mld_link->rx_omi.bw_in_progress)
- return;
-
- if (bw == IEEE80211_STA_RX_BW_MAX)
- apply_bw = ieee80211_chan_width_to_rx_bw(link_conf->chanreq.oper.width);
- else
- apply_bw = bw;
-
- if (!ap_update) {
- /* The update isn't due to AP tracking after leaving OMI,
- * where the AP could increase BW and then we must tell
- * it that we can do the increased BW as well, if we did
- * update the chandef.
- * In this case, if we want MAX, then we will need to send
- * a new OMI to the AP if it increases its own bandwidth as
- * we can (due to internal and FW limitations, and being
- * worried the AP might break) only send to what we're doing
- * at the moment. In this case, set last_max_bw; otherwise
- * if we really want to decrease our bandwidth set it to 0
- * to indicate no updates are needed if the AP changes.
- */
- if (bw != IEEE80211_STA_RX_BW_MAX)
- mld_link->rx_omi.last_max_bw = apply_bw;
- else
- mld_link->rx_omi.last_max_bw = 0;
- } else {
- /* Otherwise, if we're already trying to do maximum and
- * the AP is changing, set last_max_bw to the new max the
- * AP is using, we'll only get to this code path if the
- * new bandwidth of the AP is bigger than what we sent it
- * previously. This avoids repeatedly sending updates if
- * it changes bandwidth, only doing it once on an increase.
- */
- mld_link->rx_omi.last_max_bw = apply_bw;
- }
-
- if (ieee80211_prepare_rx_omi_bw(link_sta, bw)) {
- mld_link->rx_omi.bw_in_progress = apply_bw;
- iwl_mld_change_link_omi_bw(mld, link_conf, apply_bw);
- }
-}
-
-static void iwl_mld_omi_bw_finished_work(struct wiphy *wiphy,
- struct wiphy_work *work)
-{
- struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
- struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
- struct iwl_mld_link *mld_link =
- container_of(work, typeof(*mld_link), rx_omi.finished_work.work);
- enum ieee80211_sta_rx_bandwidth desired_bw, switched_to_bw;
- struct ieee80211_vif *vif = mld_link->vif;
- struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
- struct ieee80211_bss_conf *link_conf;
- struct ieee80211_link_sta *link_sta;
-
- if (!mld_vif->ap_sta)
- return;
-
- link_sta = wiphy_dereference(mld->wiphy,
- mld_vif->ap_sta->link[mld_link->link_id]);
- if (WARN_ON_ONCE(!link_sta))
- return;
-
- link_conf = link_conf_dereference_protected(vif, link_sta->link_id);
- if (WARN_ON_ONCE(!link_conf))
- return;
-
- if (WARN_ON(!mld_link->rx_omi.bw_in_progress))
- return;
-
- desired_bw = mld_link->rx_omi.desired_bw;
- switched_to_bw = mld_link->rx_omi.bw_in_progress;
-
- ieee80211_finalize_rx_omi_bw(link_sta);
- mld_link->rx_omi.bw_in_progress = 0;
-
- if (desired_bw != switched_to_bw)
- iwl_mld_omi_bw_update(mld, link_conf, mld_link, link_sta,
- desired_bw, false);
-}
-
-static struct ieee80211_vif *
-iwl_mld_get_omi_bw_reduction_pointers(struct iwl_mld *mld,
- struct ieee80211_link_sta **link_sta,
- struct iwl_mld_link **mld_link)
-{
- struct iwl_mld_vif *mld_vif;
- struct ieee80211_vif *vif;
- int n_link_stas = 0;
-
- *link_sta = NULL;
-
- if (mld->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_SC)
- return NULL;
-
- vif = iwl_mld_get_bss_vif(mld);
- if (!vif)
- return NULL;
-
- for (int i = 0; i < ARRAY_SIZE(mld->fw_id_to_link_sta); i++) {
- struct ieee80211_link_sta *tmp;
-
- tmp = wiphy_dereference(mld->wiphy, mld->fw_id_to_link_sta[i]);
- if (IS_ERR_OR_NULL(tmp))
- continue;
-
- n_link_stas++;
- *link_sta = tmp;
- }
-
- /* can't do anything if we have TDLS peers or EMLSR */
- if (n_link_stas != 1)
- return NULL;
-
- mld_vif = iwl_mld_vif_from_mac80211(vif);
- *mld_link = iwl_mld_link_dereference_check(mld_vif,
- (*link_sta)->link_id);
- if (WARN_ON(!*mld_link))
- return NULL;
-
- return vif;
-}
-
-void iwl_mld_omi_ap_changed_bw(struct iwl_mld *mld,
- struct ieee80211_bss_conf *link_conf,
- enum ieee80211_sta_rx_bandwidth bw)
-{
- struct ieee80211_link_sta *link_sta;
- struct iwl_mld_link *mld_link;
- struct ieee80211_vif *vif;
-
- vif = iwl_mld_get_omi_bw_reduction_pointers(mld, &link_sta, &mld_link);
- if (!vif)
- return;
-
- if (WARN_ON(link_conf->vif != vif))
- return;
-
- /* This is 0 if we requested an OMI BW reduction and don't want to
- * be sending an OMI when the AP's bandwidth changes.
- */
- if (!mld_link->rx_omi.last_max_bw)
- return;
-
- /* We only need to tell the AP if it increases BW over what we last
- * told it we were using, if it reduces then our last OMI to it will
- * not get used anyway (e.g. we said we want 160 but it's doing 80.)
- */
- if (bw < mld_link->rx_omi.last_max_bw)
- return;
-
- iwl_mld_omi_bw_update(mld, link_conf, mld_link, link_sta, bw, true);
-}
-
-void iwl_mld_handle_omi_status_notif(struct iwl_mld *mld,
- struct iwl_rx_packet *pkt)
-{
- struct ieee80211_link_sta *link_sta;
- struct iwl_mld_link *mld_link;
- struct ieee80211_vif *vif;
-
- vif = iwl_mld_get_omi_bw_reduction_pointers(mld, &link_sta, &mld_link);
- if (IWL_FW_CHECK(mld, !vif, "unexpected OMI notification\n"))
- return;
-
- if (IWL_FW_CHECK(mld, !mld_link->rx_omi.bw_in_progress,
- "OMI notification when not requested\n"))
- return;
-
- wiphy_delayed_work_queue(mld->hw->wiphy,
- &mld_link->rx_omi.finished_work,
- msecs_to_jiffies(IWL_MLD_OMI_AP_SETTLE_DELAY));
-}
-
-void iwl_mld_leave_omi_bw_reduction(struct iwl_mld *mld)
-{
- struct ieee80211_bss_conf *link_conf;
- struct ieee80211_link_sta *link_sta;
- struct iwl_mld_link *mld_link;
- struct ieee80211_vif *vif;
-
- vif = iwl_mld_get_omi_bw_reduction_pointers(mld, &link_sta, &mld_link);
- if (!vif)
- return;
-
- link_conf = link_conf_dereference_protected(vif, link_sta->link_id);
- if (WARN_ON_ONCE(!link_conf))
- return;
-
- if (!link_conf->he_support)
- return;
-
- mld_link->rx_omi.exit_ts = jiffies;
-
- iwl_mld_omi_bw_update(mld, link_conf, mld_link, link_sta,
- IEEE80211_STA_RX_BW_MAX, false);
-}
-
-void iwl_mld_check_omi_bw_reduction(struct iwl_mld *mld)
-{
- enum ieee80211_sta_rx_bandwidth bw = IEEE80211_STA_RX_BW_MAX;
- struct ieee80211_chanctx_conf *chanctx;
- struct ieee80211_bss_conf *link_conf;
- struct ieee80211_link_sta *link_sta;
- struct cfg80211_chan_def chandef;
- struct iwl_mld_link *mld_link;
- struct iwl_mld_vif *mld_vif;
- struct ieee80211_vif *vif;
- struct iwl_mld_phy *phy;
- u16 punctured;
- int exit_thr;
-
- /* not allowed in CAM mode */
- if (iwlmld_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
- return;
-
- /* must have one BSS connection (no P2P), no TDLS, nor EMLSR */
- vif = iwl_mld_get_omi_bw_reduction_pointers(mld, &link_sta, &mld_link);
- if (!vif)
- return;
-
- link_conf = link_conf_dereference_protected(vif, link_sta->link_id);
- if (WARN_ON_ONCE(!link_conf))
- return;
-
- if (!link_conf->he_support)
- return;
-
- chanctx = wiphy_dereference(mld->wiphy, mld_link->chan_ctx);
- if (WARN_ON(!chanctx))
- return;
-
- mld_vif = iwl_mld_vif_from_mac80211(vif);
- if (!mld_vif->authorized)
- goto apply;
-
- /* must not be in low-latency mode */
- if (iwl_mld_vif_low_latency(mld_vif))
- goto apply;
-
- chandef = link_conf->chanreq.oper;
-
- switch (chandef.width) {
- case NL80211_CHAN_WIDTH_320:
- exit_thr = IWL_MLD_OMI_EXIT_CHAN_LOAD_320;
- break;
- case NL80211_CHAN_WIDTH_160:
- exit_thr = IWL_MLD_OMI_EXIT_CHAN_LOAD_160;
- break;
- default:
- /* since we reduce to 80 MHz, must have more to start with */
- goto apply;
- }
-
- /* not to be done if primary 80 MHz is punctured */
- if (cfg80211_chandef_primary(&chandef, NL80211_CHAN_WIDTH_80,
- &punctured) < 0 ||
- punctured != 0)
- goto apply;
-
- phy = iwl_mld_phy_from_mac80211(chanctx);
-
- if (phy->channel_load_by_us > exit_thr) {
- /* send OMI for max bandwidth */
- goto apply;
- }
-
- if (phy->channel_load_by_us > IWL_MLD_OMI_ENTER_CHAN_LOAD) {
- /* no changes between enter/exit thresholds */
- return;
- }
-
- if (time_is_after_jiffies(mld_link->rx_omi.exit_ts +
- msecs_to_jiffies(IWL_MLD_OMI_EXIT_PROTECTION)))
- return;
-
- /* reduce bandwidth to 80 MHz to save power */
- bw = IEEE80211_STA_RX_BW_80;
-apply:
- iwl_mld_omi_bw_update(mld, link_conf, mld_link, link_sta, bw, false);
-}
-
IWL_MLD_ALLOC_FN(link, bss_conf)
/* Constructor function for struct iwl_mld_link */
@@ -777,15 +444,11 @@ static int
iwl_mld_init_link(struct iwl_mld *mld, struct ieee80211_bss_conf *link,
struct iwl_mld_link *mld_link)
{
- mld_link->vif = link->vif;
- mld_link->link_id = link->link_id;
+ mld_link->average_beacon_energy = 0;
iwl_mld_init_internal_sta(&mld_link->bcast_sta);
iwl_mld_init_internal_sta(&mld_link->mcast_sta);
- iwl_mld_init_internal_sta(&mld_link->aux_sta);
-
- wiphy_delayed_work_init(&mld_link->rx_omi.finished_work,
- iwl_mld_omi_bw_finished_work);
+ iwl_mld_init_internal_sta(&mld_link->mon_sta);
return iwl_mld_allocate_link_fw_id(mld, &mld_link->fw_id, link);
}
@@ -802,10 +465,13 @@ int iwl_mld_add_link(struct iwl_mld *mld,
int ret;
if (!link) {
- if (is_deflink)
+ if (is_deflink) {
link = &mld_vif->deflink;
- else
+ } else {
link = kzalloc(sizeof(*link), GFP_KERNEL);
+ if (!link)
+ return -ENOMEM;
+ }
} else {
WARN_ON(!mld->fw_status.in_hw_restart);
}
@@ -838,6 +504,7 @@ void iwl_mld_remove_link(struct iwl_mld *mld,
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(bss_conf->vif);
struct iwl_mld_link *link = iwl_mld_link_from_mac80211(bss_conf);
bool is_deflink = link == &mld_vif->deflink;
+ u8 fw_id = link->fw_id;
if (WARN_ON(!link || link->active))
return;
@@ -850,12 +517,10 @@ void iwl_mld_remove_link(struct iwl_mld *mld,
RCU_INIT_POINTER(mld_vif->link[bss_conf->link_id], NULL);
- wiphy_delayed_work_cancel(mld->wiphy, &link->rx_omi.finished_work);
-
- if (WARN_ON(link->fw_id >= mld->fw->ucode_capa.num_links))
+ if (WARN_ON(fw_id >= mld->fw->ucode_capa.num_links))
return;
- RCU_INIT_POINTER(mld->fw_id_to_bss_conf[link->fw_id], NULL);
+ RCU_INIT_POINTER(mld->fw_id_to_bss_conf[fw_id], NULL);
}
void iwl_mld_handle_missed_beacon_notif(struct iwl_mld *mld,
@@ -863,21 +528,24 @@ void iwl_mld_handle_missed_beacon_notif(struct iwl_mld *mld,
{
const struct iwl_missed_beacons_notif *notif = (const void *)pkt->data;
union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt };
- u32 link_id = le32_to_cpu(notif->link_id);
+ u32 fw_link_id = le32_to_cpu(notif->link_id);
u32 missed_bcon = le32_to_cpu(notif->consec_missed_beacons);
u32 missed_bcon_since_rx =
le32_to_cpu(notif->consec_missed_beacons_since_last_rx);
u32 scnd_lnk_bcn_lost =
le32_to_cpu(notif->consec_missed_beacons_other_link);
struct ieee80211_bss_conf *link_conf =
- iwl_mld_fw_id_to_link_conf(mld, link_id);
- u32 bss_param_ch_cnt_link_id;
+ iwl_mld_fw_id_to_link_conf(mld, fw_link_id);
+ struct ieee80211_bss_conf *other_link;
+ u32 bss_param_ch_cnt_link_id, other_link_fw_id;
struct ieee80211_vif *vif;
+ u8 link_id;
if (WARN_ON(!link_conf))
return;
vif = link_conf->vif;
+ link_id = link_conf->link_id;
bss_param_ch_cnt_link_id = link_conf->bss_param_ch_cnt_link_id;
IWL_DEBUG_INFO(mld,
@@ -887,11 +555,6 @@ void iwl_mld_handle_missed_beacon_notif(struct iwl_mld *mld,
if (WARN_ON(!vif))
return;
- mld->trans->dbg.dump_file_name_ext_valid = true;
- snprintf(mld->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME,
- "LinkId_%d_MacType_%d", link_id,
- iwl_mld_mac80211_iftype_to_fw(vif));
-
iwl_dbg_tlv_time_point(&mld->fwrt,
IWL_FW_INI_TIME_POINT_MISSED_BEACONS, &tp_data);
@@ -909,8 +572,15 @@ void iwl_mld_handle_missed_beacon_notif(struct iwl_mld *mld,
if (missed_bcon_since_rx > IWL_MLD_MISSED_BEACONS_THRESHOLD) {
ieee80211_cqm_beacon_loss_notify(vif, GFP_ATOMIC);
- /* try to switch links, no-op if we don't have MLO */
- iwl_mld_int_mlo_scan(mld, vif);
+ /* Not in EMLSR and we can't hear the link.
+ * Try to switch to a better link. EMLSR case is handled below.
+ */
+ if (!iwl_mld_emlsr_active(vif)) {
+ IWL_DEBUG_EHT(mld,
+ "missed beacons exceeds threshold. link_id=%u. Try to switch to a better link.\n",
+ link_id);
+ iwl_mld_int_mlo_scan(mld, vif);
+ }
}
/* no more logic if we're not in EMLSR */
@@ -921,6 +591,18 @@ void iwl_mld_handle_missed_beacon_notif(struct iwl_mld *mld,
if (le32_to_cpu(notif->other_link_id) == FW_CTXT_ID_INVALID)
return;
+ other_link_fw_id = le32_to_cpu(notif->other_link_id);
+ other_link = iwl_mld_fw_id_to_link_conf(mld, other_link_fw_id);
+
+ if (IWL_FW_CHECK(mld, !other_link, "link doesn't exist for: %d\n",
+ other_link_fw_id))
+ return;
+
+ IWL_DEBUG_EHT(mld,
+ "missed bcn link_id=%u: %u consecutive=%u, other link_id=%u: %u\n",
+ link_id, missed_bcon, missed_bcon_since_rx,
+ other_link->link_id, scnd_lnk_bcn_lost);
+
/* Exit EMLSR if we lost more than
* IWL_MLD_MISSED_BEACONS_EXIT_ESR_THRESH beacons on boths links
* OR more than IWL_MLD_BCN_LOSS_EXIT_ESR_THRESH on current link.
@@ -1034,18 +716,13 @@ static int
iwl_mld_get_chan_load_from_element(struct iwl_mld *mld,
struct ieee80211_bss_conf *link_conf)
{
- struct ieee80211_vif *vif = link_conf->vif;
const struct cfg80211_bss_ies *ies;
const struct element *bss_load_elem = NULL;
const struct ieee80211_bss_load_elem *bss_load;
guard(rcu)();
- if (ieee80211_vif_link_active(vif, link_conf->link_id))
- ies = rcu_dereference(link_conf->bss->beacon_ies);
- else
- ies = rcu_dereference(link_conf->bss->ies);
-
+ ies = rcu_dereference(link_conf->bss->beacon_ies);
if (ies)
bss_load_elem = cfg80211_find_elem(WLAN_EID_QBSS_LOAD,
ies->data, ies->len);
@@ -1211,3 +888,22 @@ unsigned int iwl_mld_get_link_grade(struct iwl_mld *mld,
return grade;
}
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_get_link_grade);
+
+void iwl_mld_handle_beacon_filter_notif(struct iwl_mld *mld,
+ struct iwl_rx_packet *pkt)
+{
+ const struct iwl_beacon_filter_notif *notif = (const void *)pkt->data;
+ u32 link_id = le32_to_cpu(notif->link_id);
+ struct ieee80211_bss_conf *link_conf =
+ iwl_mld_fw_id_to_link_conf(mld, link_id);
+ struct iwl_mld_link *mld_link;
+
+ if (IWL_FW_CHECK(mld, !link_conf, "invalid link ID %d\n", link_id))
+ return;
+
+ mld_link = iwl_mld_link_from_mac80211(link_conf);
+ if (WARN_ON_ONCE(!mld_link))
+ return;
+
+ mld_link->average_beacon_energy = le32_to_cpu(notif->average_energy);
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.h b/drivers/net/wireless/intel/iwlwifi/mld/link.h
index 42b7bdcbd741..9e4da8e4de93 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/link.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/link.h
@@ -36,25 +36,18 @@ struct iwl_probe_resp_data {
* @he_ru_2mhz_block: 26-tone RU OFDMA transmissions should be blocked.
* @igtk: fw can only have one IGTK at a time, whereas mac80211 can have two.
* This tracks the one IGTK that currently exists in FW.
- * @vif: the vif this link belongs to
+ * @bigtks: BIGTKs of the AP. Only valid for STA mode.
* @bcast_sta: station used for broadcast packets. Used in AP, GO and IBSS.
* @mcast_sta: station used for multicast packets. Used in AP, GO and IBSS.
- * @aux_sta: station used for remain on channel. Used in P2P device.
- * @link_id: over the air link ID
+ * @mon_sta: station used for TX injection in monitor interface.
+ * @average_beacon_energy: average beacon energy for beacons received during
+ * client connections
* @ap_early_keys: The firmware cannot install keys before bcast/mcast STAs,
* but higher layers work differently, so we store the keys here for
* later installation.
* @silent_deactivation: next deactivation needs to be silent.
* @probe_resp_data: data from FW notification to store NOA related data to be
* inserted into probe response.
- * @rx_omi: data for BW reduction with OMI
- * @rx_omi.bw_in_progress: update is in progress (indicates target BW)
- * @rx_omi.exit_ts: timestamp of last exit
- * @rx_omi.finished_work: work for the delayed reaction to the firmware saying
- * the change was applied, and for then applying a new mode if it was
- * updated while waiting for firmware/AP settle delay.
- * @rx_omi.desired_bw: desired bandwidth
- * @rx_omi.last_max_bw: last maximum BW used by firmware, for AP BW changes
*/
struct iwl_mld_link {
struct rcu_head rcu_head;
@@ -67,29 +60,21 @@ struct iwl_mld_link {
struct ieee80211_chanctx_conf __rcu *chan_ctx;
bool he_ru_2mhz_block;
struct ieee80211_key_conf *igtk;
+ struct ieee80211_key_conf __rcu *bigtks[2];
);
/* And here fields that survive a fw restart */
- struct ieee80211_vif *vif;
struct iwl_mld_int_sta bcast_sta;
struct iwl_mld_int_sta mcast_sta;
- struct iwl_mld_int_sta aux_sta;
- u8 link_id;
-
- struct {
- struct wiphy_delayed_work finished_work;
- unsigned long exit_ts;
- enum ieee80211_sta_rx_bandwidth bw_in_progress,
- desired_bw,
- last_max_bw;
- } rx_omi;
+ struct iwl_mld_int_sta mon_sta;
/* we can only have 2 GTK + 2 IGTK + 2 BIGTK active at a time */
struct ieee80211_key_conf *ap_early_keys[6];
+ u32 average_beacon_energy;
bool silent_deactivation;
struct iwl_probe_resp_data __rcu *probe_resp_data;
};
-/* Cleanup function for struct iwl_mld_phy, will be called in restart */
+/* Cleanup function for struct iwl_mld_link, will be called in restart */
static inline void
iwl_mld_cleanup_link(struct iwl_mld *mld, struct iwl_mld_link *link)
{
@@ -105,8 +90,8 @@ iwl_mld_cleanup_link(struct iwl_mld *mld, struct iwl_mld_link *link)
iwl_mld_free_internal_sta(mld, &link->bcast_sta);
if (link->mcast_sta.sta_id != IWL_INVALID_STA)
iwl_mld_free_internal_sta(mld, &link->mcast_sta);
- if (link->aux_sta.sta_id != IWL_INVALID_STA)
- iwl_mld_free_internal_sta(mld, &link->aux_sta);
+ if (link->mon_sta.sta_id != IWL_INVALID_STA)
+ iwl_mld_free_internal_sta(mld, &link->mon_sta);
}
/* Convert a percentage from [0,100] to [0,255] */
@@ -120,9 +105,6 @@ int iwl_mld_activate_link(struct iwl_mld *mld,
struct ieee80211_bss_conf *link);
void iwl_mld_deactivate_link(struct iwl_mld *mld,
struct ieee80211_bss_conf *link);
-int iwl_mld_change_link_omi_bw(struct iwl_mld *mld,
- struct ieee80211_bss_conf *link,
- enum ieee80211_sta_rx_bandwidth bw);
int iwl_mld_change_link_in_fw(struct iwl_mld *mld,
struct ieee80211_bss_conf *link, u32 changes);
void iwl_mld_handle_missed_beacon_notif(struct iwl_mld *mld,
@@ -142,12 +124,8 @@ unsigned int iwl_mld_get_chan_load(struct iwl_mld *mld,
int iwl_mld_get_chan_load_by_others(struct iwl_mld *mld,
struct ieee80211_bss_conf *link_conf,
bool expect_active_link);
-void iwl_mld_handle_omi_status_notif(struct iwl_mld *mld,
- struct iwl_rx_packet *pkt);
-void iwl_mld_leave_omi_bw_reduction(struct iwl_mld *mld);
-void iwl_mld_check_omi_bw_reduction(struct iwl_mld *mld);
-void iwl_mld_omi_ap_changed_bw(struct iwl_mld *mld,
- struct ieee80211_bss_conf *link_conf,
- enum ieee80211_sta_rx_bandwidth bw);
+
+void iwl_mld_handle_beacon_filter_notif(struct iwl_mld *mld,
+ struct iwl_rx_packet *pkt);
#endif /* __iwl_mld_link_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/low_latency.c b/drivers/net/wireless/intel/iwlwifi/mld/low_latency.c
index a4a612afb3b3..23362867b400 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/low_latency.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/low_latency.c
@@ -21,7 +21,7 @@ static bool iwl_mld_calc_low_latency(struct iwl_mld *mld,
{
struct iwl_mld_low_latency *ll = &mld->low_latency;
bool global_low_latency = false;
- u8 num_rx_q = mld->trans->num_rx_queues;
+ u8 num_rx_q = mld->trans->info.num_rxqs;
for (int mac_id = 0; mac_id < NUM_MAC_INDEX_DRIVER; mac_id++) {
u32 total_vo_vi_pkts = 0;
@@ -131,12 +131,12 @@ int iwl_mld_low_latency_init(struct iwl_mld *mld)
struct iwl_mld_low_latency *ll = &mld->low_latency;
unsigned long ts = jiffies;
- ll->pkts_counters = kcalloc(mld->trans->num_rx_queues,
+ ll->pkts_counters = kcalloc(mld->trans->info.num_rxqs,
sizeof(*ll->pkts_counters), GFP_KERNEL);
if (!ll->pkts_counters)
return -ENOMEM;
- for (int q = 0; q < mld->trans->num_rx_queues; q++)
+ for (int q = 0; q < mld->trans->info.num_rxqs; q++)
spin_lock_init(&ll->pkts_counters[q].lock);
wiphy_delayed_work_init(&ll->work, iwl_mld_low_latency_wk);
@@ -167,7 +167,7 @@ void iwl_mld_low_latency_restart_cleanup(struct iwl_mld *mld)
memset(ll->window_start, 0, sizeof(ll->window_start));
memset(ll->result, 0, sizeof(ll->result));
- for (int q = 0; q < mld->trans->num_rx_queues; q++)
+ for (int q = 0; q < mld->trans->info.num_rxqs; q++)
memset(ll->pkts_counters[q].vo_vi, 0,
sizeof(ll->pkts_counters[q].vo_vi));
}
@@ -224,9 +224,6 @@ void iwl_mld_vif_update_low_latency(struct iwl_mld *mld,
return;
}
- if (low_latency)
- iwl_mld_leave_omi_bw_reduction(mld);
-
if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_P2P_CLIENT)
return;
@@ -276,7 +273,7 @@ void iwl_mld_low_latency_update_counters(struct iwl_mld *mld,
return;
if (WARN_ON_ONCE(fw_id >= ARRAY_SIZE(counters->vo_vi) ||
- queue >= mld->trans->num_rx_queues))
+ queue >= mld->trans->info.num_rxqs))
return;
if (mld->low_latency.stopped)
@@ -324,7 +321,7 @@ void iwl_mld_low_latency_restart(struct iwl_mld *mld)
ll->window_start[mac] = 0;
low_latency |= ll->result[mac];
- for (int q = 0; q < mld->trans->num_rx_queues; q++) {
+ for (int q = 0; q < mld->trans->info.num_rxqs; q++) {
spin_lock_bh(&ll->pkts_counters[q].lock);
ll->pkts_counters[q].vo_vi[mac] = 0;
spin_unlock_bh(&ll->pkts_counters[q].lock);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
index 68d97d3b8f02..55b484c16280 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
@@ -4,6 +4,7 @@
*/
#include <net/mac80211.h>
+#include <linux/fips.h>
#include <linux/ip.h>
#include "mld.h"
@@ -22,6 +23,7 @@
#include "roc.h"
#include "mlo.h"
#include "stats.h"
+#include "iwl-nvm-parse.h"
#include "ftm-initiator.h"
#include "low_latency.h"
#include "fw/api/scan.h"
@@ -74,13 +76,12 @@ iwl_mld_iface_combinations[] = {
},
};
-static const u8 if_types_ext_capa_sta[] = {
- [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
- [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
- [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF |
- WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB,
- [8] = WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB,
- [9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
+static const u8 ext_capa_base[IWL_MLD_STA_EXT_CAPA_SIZE] = {
+ [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
+ [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
+ [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF |
+ WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB,
+ [8] = WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB,
};
#define IWL_MLD_EMLSR_CAPA (IEEE80211_EML_CAP_EMLSR_SUPP | \
@@ -93,18 +94,6 @@ static const u8 if_types_ext_capa_sta[] = {
IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP_SAME) | \
IEEE80211_MLD_CAP_OP_LINK_RECONF_SUPPORT)
-static const struct wiphy_iftype_ext_capab iftypes_ext_capa[] = {
- {
- .iftype = NL80211_IFTYPE_STATION,
- .extended_capabilities = if_types_ext_capa_sta,
- .extended_capabilities_mask = if_types_ext_capa_sta,
- .extended_capabilities_len = sizeof(if_types_ext_capa_sta),
- /* relevant only if EHT is supported */
- .eml_capabilities = IWL_MLD_EMLSR_CAPA,
- .mld_capa_and_ops = IWL_MLD_CAPA_OPS,
- },
-};
-
static void iwl_mld_hw_set_addresses(struct iwl_mld *mld)
{
struct wiphy *wiphy = mld->wiphy;
@@ -156,6 +145,9 @@ static void iwl_mld_hw_set_security(struct iwl_mld *mld)
WLAN_CIPHER_SUITE_BIP_GMAC_256
};
+ if (fips_enabled)
+ return;
+
hw->wiphy->n_cipher_suites = ARRAY_SIZE(mld_ciphers);
hw->wiphy->cipher_suites = mld_ciphers;
@@ -180,6 +172,9 @@ static void iwl_mld_hw_set_pm(struct iwl_mld *mld)
if (!device_can_wakeup(mld->trans->dev))
return;
+ if (fips_enabled)
+ return;
+
mld->wowlan.flags |= WIPHY_WOWLAN_MAGIC_PKT |
WIPHY_WOWLAN_DISCONNECT |
WIPHY_WOWLAN_EAP_IDENTITY_REQ |
@@ -243,7 +238,6 @@ static void iwl_mac_hw_set_flags(struct iwl_mld *mld)
ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
- ieee80211_hw_set(hw, DISALLOW_PUNCTURING_5GHZ);
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
ieee80211_hw_set(hw, TDLS_WIDER_BW);
@@ -285,9 +279,11 @@ static void iwl_mac_hw_set_wiphy(struct iwl_mld *mld)
WIPHY_FLAG_SUPPORTS_TDLS |
WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK;
+ /* For fips_enabled, don't support WiFi7 due to WPA3/MFP requirements */
if (mld->nvm_data->sku_cap_11be_enable &&
!iwlwifi_mod_params.disable_11ax &&
- !iwlwifi_mod_params.disable_11be)
+ !iwlwifi_mod_params.disable_11be &&
+ !fips_enabled)
wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO;
/* the firmware uses u8 for num of iterations, but 0xff is saved for
@@ -305,7 +301,7 @@ static void iwl_mac_hw_set_wiphy(struct iwl_mld *mld)
wiphy->max_remain_on_channel_duration = 10000;
- wiphy->hw_version = mld->trans->hw_id;
+ wiphy->hw_version = mld->trans->info.hw_id;
wiphy->hw_timestamp_max_peers = 1;
@@ -327,21 +323,37 @@ static void iwl_mac_hw_set_wiphy(struct iwl_mld *mld)
if (fw_has_capa(ucode_capa, IWL_UCODE_TLV_CAPA_PROTECTED_TWT))
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_PROTECTED_TWT);
- wiphy->iftype_ext_capab = NULL;
- wiphy->num_iftype_ext_capab = 0;
-
- if (!iwlwifi_mod_params.disable_11ax) {
- wiphy->iftype_ext_capab = iftypes_ext_capa;
- wiphy->num_iftype_ext_capab = ARRAY_SIZE(iftypes_ext_capa);
-
- ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
- ieee80211_hw_set(hw, SUPPORTS_ONLY_HE_MULTI_BSSID);
- }
-
if (iwlmld_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
else
wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
+ /* We are done for non-HE */
+ if (iwlwifi_mod_params.disable_11ax)
+ return;
+
+ ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
+ ieee80211_hw_set(hw, SUPPORTS_ONLY_HE_MULTI_BSSID);
+
+ wiphy->iftype_ext_capab = mld->ext_capab;
+ wiphy->num_iftype_ext_capab = ARRAY_SIZE(mld->ext_capab);
+
+ BUILD_BUG_ON(sizeof(mld->sta_ext_capab) < sizeof(ext_capa_base));
+
+ memcpy(mld->sta_ext_capab, ext_capa_base, sizeof(ext_capa_base));
+
+ mld->ext_capab[0].iftype = NL80211_IFTYPE_STATION;
+ mld->ext_capab[0].extended_capabilities = mld->sta_ext_capab;
+ mld->ext_capab[0].extended_capabilities_mask = mld->sta_ext_capab;
+ mld->ext_capab[0].extended_capabilities_len = sizeof(mld->sta_ext_capab);
+
+ if (!mld->nvm_data->sku_cap_11be_enable ||
+ iwlwifi_mod_params.disable_11be)
+ return;
+
+ mld->ext_capab[0].eml_capabilities = IWL_MLD_EMLSR_CAPA;
+ mld->ext_capab[0].mld_capa_and_ops = IWL_MLD_CAPA_OPS;
+
}
static void iwl_mac_hw_set_misc(struct iwl_mld *mld)
@@ -351,9 +363,9 @@ static void iwl_mac_hw_set_misc(struct iwl_mld *mld)
hw->queues = IEEE80211_NUM_ACS;
hw->netdev_features = NETIF_F_HIGHDMA | NETIF_F_SG;
- hw->netdev_features |= mld->cfg->features;
+ hw->netdev_features |= mld->trans->mac_cfg->base->features;
- hw->max_tx_fragments = mld->trans->max_skb_frags;
+ hw->max_tx_fragments = mld->trans->info.max_skb_frags;
hw->max_listen_interval = IWL_MLD_CONN_LISTEN_INTERVAL;
hw->uapsd_max_sp_len = IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL;
@@ -376,6 +388,22 @@ static void iwl_mac_hw_set_misc(struct iwl_mld *mld)
static int iwl_mld_hw_verify_preconditions(struct iwl_mld *mld)
{
+ int ratecheck;
+
+ /* check for rates version 3 */
+ ratecheck =
+ (iwl_fw_lookup_cmd_ver(mld->fw, TX_CMD, 0) >= 11) +
+ (iwl_fw_lookup_notif_ver(mld->fw, DATA_PATH_GROUP,
+ TLC_MNG_UPDATE_NOTIF, 0) >= 4) +
+ (iwl_fw_lookup_notif_ver(mld->fw, LEGACY_GROUP,
+ REPLY_RX_MPDU_CMD, 0) >= 6) +
+ (iwl_fw_lookup_notif_ver(mld->fw, LONG_GROUP, TX_CMD, 0) >= 9);
+
+ if (ratecheck != 0 && ratecheck != 4) {
+ IWL_ERR(mld, "Firmware has inconsistent rates\n");
+ return -EINVAL;
+ }
+
/* 11ax is expected to be enabled for all supported devices */
if (WARN_ON(!mld->nvm_data->sku_cap_11ax_enable))
return -EINVAL;
@@ -491,8 +519,15 @@ int iwl_mld_mac80211_start(struct ieee80211_hw *hw)
if (in_d3) {
/* mac80211 already cleaned up the state, no need for cleanup */
ret = iwl_mld_no_wowlan_resume(mld);
- if (ret)
+ if (ret) {
iwl_mld_stop_fw(mld);
+ /* We're not really restarting in the sense of
+ * in_hw_restart even if we got an error during
+ * this. We'll just start again below and have
+ * nothing to recover, mac80211 will do anyway.
+ */
+ mld->fw_status.in_hw_restart = false;
+ }
}
#endif /* CONFIG_PM_SLEEP */
@@ -541,15 +576,6 @@ void iwl_mld_mac80211_stop(struct ieee80211_hw *hw, bool suspend)
(IS_ENABLED(CONFIG_PM_SLEEP) && iwl_mld_no_wowlan_suspend(mld)))
iwl_mld_stop_fw(mld);
- /* HW is stopped, no more coming RX. OTOH, the worker can't run as the
- * wiphy lock is held. Cancel it in case it was scheduled just before
- * we stopped the HW.
- */
- wiphy_work_cancel(mld->wiphy, &mld->async_handlers_wk);
-
- /* Empty out the list, as the worker won't do that */
- iwl_mld_purge_async_handlers_list(mld);
-
/* Clear in_hw_restart flag when stopping the hw, as mac80211 won't
* execute the restart.
*/
@@ -566,7 +592,8 @@ void iwl_mld_mac80211_stop(struct ieee80211_hw *hw, bool suspend)
}
static
-int iwl_mld_mac80211_config(struct ieee80211_hw *hw, u32 changed)
+int iwl_mld_mac80211_config(struct ieee80211_hw *hw, int radio_idx,
+ u32 changed)
{
return 0;
}
@@ -601,7 +628,7 @@ int iwl_mld_mac80211_add_interface(struct ieee80211_hw *hw,
IEEE80211_VIF_SUPPORTS_CQM_RSSI;
}
- if (vif->p2p || iwl_fw_lookup_cmd_ver(mld->fw, PHY_CONTEXT_CMD, 0) < 5)
+ if (vif->p2p)
vif->driver_flags |= IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW;
/*
@@ -655,6 +682,8 @@ void iwl_mld_mac80211_remove_interface(struct ieee80211_hw *hw,
#endif
iwl_mld_rm_vif(mld, vif);
+
+ mld->monitor.phy.valid = false;
}
struct iwl_mld_mc_iter_data {
@@ -897,9 +926,8 @@ void iwl_mld_change_chanctx(struct ieee80211_hw *hw,
return;
}
update:
- phy->chandef = *chandef;
- iwl_mld_phy_fw_action(mld, ctx, FW_CTXT_ACTION_MODIFY);
+ iwl_mld_update_phy_chandef(mld, ctx);
}
static u8
@@ -991,10 +1019,9 @@ int iwl_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
if (n_active > 1) {
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
- iwl_mld_leave_omi_bw_reduction(mld);
-
/* Indicate to mac80211 that EML is enabled */
vif->driver_flags |= IEEE80211_VIF_EML_ACTIVE;
+ mld_vif->emlsr.last_entry_ts = jiffies;
if (vif->active_links & BIT(mld_vif->emlsr.selected_links))
mld_vif->emlsr.primary = mld_vif->emlsr.selected_primary;
@@ -1031,12 +1058,19 @@ int iwl_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
iwl_mld_send_ap_tx_power_constraint_cmd(mld, vif, link);
if (vif->type == NL80211_IFTYPE_MONITOR) {
- /* TODO: task=sniffer add sniffer station */
+ ret = iwl_mld_add_mon_sta(mld, vif, link);
+ if (ret)
+ goto deactivate_link;
+
mld->monitor.p80 =
iwl_mld_chandef_get_primary_80(&vif->bss_conf.chanreq.oper);
}
return 0;
+
+deactivate_link:
+ if (mld_link->active)
+ iwl_mld_deactivate_link(mld, link);
err:
RCU_INIT_POINTER(mld_link->chan_ctx, NULL);
return ret;
@@ -1062,7 +1096,8 @@ void iwl_mld_unassign_vif_chanctx(struct ieee80211_hw *hw,
iwl_mld_deactivate_link(mld, link);
- /* TODO: task=sniffer remove sniffer station */
+ if (vif->type == NL80211_IFTYPE_MONITOR)
+ iwl_mld_remove_mon_sta(mld, vif, link);
if (n_active > 1) {
/* Indicate to mac80211 that EML is disabled */
@@ -1087,7 +1122,8 @@ void iwl_mld_unassign_vif_chanctx(struct ieee80211_hw *hw,
}
static
-int iwl_mld_mac80211_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+int iwl_mld_mac80211_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx,
+ u32 value)
{
return 0;
}
@@ -1178,20 +1214,6 @@ iwl_mld_mac80211_link_info_changed_sta(struct iwl_mld *mld,
if (changes & (BSS_CHANGED_CQM | BSS_CHANGED_BEACON_INFO))
iwl_mld_enable_beacon_filter(mld, link_conf, false);
- /* If we have used OMI before to reduce bandwidth to 80 MHz and then
- * increased to 160 MHz again, and then the AP changes to 320 MHz, it
- * will think that we're limited to 160 MHz right now. Update it by
- * requesting a new OMI bandwidth.
- */
- if (changes & BSS_CHANGED_BANDWIDTH) {
- enum ieee80211_sta_rx_bandwidth bw;
-
- bw = ieee80211_chan_width_to_rx_bw(link_conf->chanreq.oper.width);
-
- iwl_mld_omi_ap_changed_bw(mld, link_conf, bw);
-
- }
-
if (changes & BSS_CHANGED_BANDWIDTH)
iwl_mld_retry_emlsr(mld, vif);
}
@@ -1258,9 +1280,14 @@ iwl_mld_mac80211_link_info_changed(struct ieee80211_hw *hw,
}
static void
-iwl_mld_smps_wa(struct iwl_mld *mld, struct ieee80211_vif *vif, bool enable)
+iwl_mld_smps_workaround(struct iwl_mld *mld, struct ieee80211_vif *vif, bool enable)
{
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
+ bool workaround_required =
+ iwl_fw_lookup_cmd_ver(mld->fw, MAC_PM_POWER_TABLE, 0) < 2;
+
+ if (!workaround_required)
+ return;
/* Send the device-level power commands since the
* firmware checks the POWER_TABLE_CMD's POWER_SAVE_EN bit to
@@ -1307,7 +1334,7 @@ void iwl_mld_mac80211_vif_cfg_changed(struct ieee80211_hw *hw,
}
if (changes & BSS_CHANGED_PS) {
- iwl_mld_smps_wa(mld, vif, vif->cfg.ps);
+ iwl_mld_smps_workaround(mld, vif, vif->cfg.ps);
iwl_mld_update_mac_power(mld, vif, false);
}
@@ -1320,13 +1347,22 @@ iwl_mld_mac80211_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_scan_request *hw_req)
{
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
+ int ret;
if (WARN_ON(!hw_req->req.n_channels ||
hw_req->req.n_channels >
mld->fw->ucode_capa.n_scan_channels))
return -EINVAL;
- return iwl_mld_regular_scan_start(mld, vif, &hw_req->req, &hw_req->ies);
+ ret = iwl_mld_regular_scan_start(mld, vif, &hw_req->req, &hw_req->ies);
+ if (!ret) {
+ /* We will be busy with scanning, so the counters may not reflect the
+ * reality. Stop checking the counters until the scan ends
+ */
+ iwl_mld_start_ignoring_tpt_updates(mld);
+ }
+
+ return ret;
}
static void
@@ -1342,8 +1378,11 @@ iwl_mld_mac80211_cancel_hw_scan(struct ieee80211_hw *hw,
* cancel scan before ieee80211_scan_work() could run.
* To handle that, simply return if the scan is not running.
*/
- if (mld->scan.status & IWL_MLD_SCAN_REGULAR)
+ if (mld->scan.status & IWL_MLD_SCAN_REGULAR) {
iwl_mld_scan_stop(mld, IWL_MLD_SCAN_REGULAR, true);
+ /* Scan is over, we can check again the tpt counters */
+ iwl_mld_stop_ignoring_tpt_updates(mld);
+ }
}
static int
@@ -1378,30 +1417,6 @@ iwl_mld_mac80211_sched_scan_stop(struct ieee80211_hw *hw,
}
static void
-iwl_mld_restart_complete_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
-{
- struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
- struct ieee80211_bss_conf *link_conf;
- struct iwl_mld *mld = data;
- int link_id;
-
- for_each_vif_active_link(vif, link_conf, link_id) {
- enum ieee80211_sta_rx_bandwidth bw;
- struct iwl_mld_link *mld_link;
-
- mld_link = wiphy_dereference(mld->wiphy,
- mld_vif->link[link_id]);
-
- if (WARN_ON_ONCE(!mld_link))
- continue;
-
- bw = mld_link->rx_omi.bw_in_progress;
- if (bw)
- iwl_mld_change_link_omi_bw(mld, link_conf, bw);
- }
-}
-
-static void
iwl_mld_mac80211_reconfig_complete(struct ieee80211_hw *hw,
enum ieee80211_reconfig_type reconfig_type)
{
@@ -1411,11 +1426,6 @@ iwl_mld_mac80211_reconfig_complete(struct ieee80211_hw *hw,
case IEEE80211_RECONFIG_TYPE_RESTART:
mld->fw_status.in_hw_restart = false;
iwl_mld_send_recovery_cmd(mld, ERROR_RECOVERY_END_OF_RECOVERY);
-
- ieee80211_iterate_interfaces(mld->hw,
- IEEE80211_IFACE_ITER_NORMAL,
- iwl_mld_restart_complete_vif, mld);
-
iwl_trans_finish_sw_reset(mld->trans);
/* no need to lock, adding in parallel would schedule too */
if (!list_empty(&mld->txqs_to_add))
@@ -1436,7 +1446,7 @@ void iwl_mld_mac80211_mgd_prepare_tx(struct ieee80211_hw *hw,
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
u32 duration = IWL_MLD_SESSION_PROTECTION_ASSOC_TIME_MS;
- /* After a successful association the connection is etalibeshed
+ /* After a successful association the connection is established
* and we can rely on the quota to send the disassociation frame.
*/
if (info->was_assoc)
@@ -1639,18 +1649,6 @@ static int iwl_mld_move_sta_state_up(struct iwl_mld *mld,
return -EBUSY;
}
- /*
- * If this is the first STA (i.e. the AP) it won't do
- * anything, otherwise must leave for any new STA on
- * any other interface, or for TDLS, etc.
- * Need to call this _before_ adding the STA so it can
- * look up the one STA to use to ask mac80211 to leave
- * OMI; in the unlikely event that adding the new STA
- * then fails we'll just re-enter OMI later (via the
- * statistics notification handling.)
- */
- iwl_mld_leave_omi_bw_reduction(mld);
-
ret = iwl_mld_add_sta(mld, sta, vif, STATION_TYPE_PEER);
if (ret)
return ret;
@@ -1720,7 +1718,7 @@ static int iwl_mld_move_sta_state_up(struct iwl_mld *mld,
FW_CTXT_ACTION_MODIFY);
if (ret)
return ret;
- iwl_mld_smps_wa(mld, vif, vif->cfg.ps);
+ iwl_mld_smps_workaround(mld, vif, vif->cfg.ps);
}
/* MFP is set by default before the station is authorized.
@@ -1763,7 +1761,7 @@ static int iwl_mld_move_sta_state_down(struct iwl_mld *mld,
&mld_vif->emlsr.check_tpt_wk);
iwl_mld_reset_cca_40mhz_workaround(mld, vif);
- iwl_mld_smps_wa(mld, vif, true);
+ iwl_mld_smps_workaround(mld, vif, true);
}
/* once we move into assoc state, need to update the FW to
@@ -1876,6 +1874,10 @@ iwl_mld_mac80211_ampdu_action(struct ieee80211_hw *hw,
switch (action) {
case IEEE80211_AMPDU_RX_START:
+ if (!iwl_enable_rx_ampdu()) {
+ ret = -EINVAL;
+ break;
+ }
ret = iwl_mld_ampdu_rx_start(mld, sta, tid, ssn, buf_size,
timeout);
break;
@@ -1968,13 +1970,8 @@ iwl_mld_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
iwl_fw_runtime_suspend(&mld->fwrt);
ret = iwl_mld_wowlan_suspend(mld, wowlan);
- if (ret) {
- if (ret < 0) {
- mld->trans->state = IWL_TRANS_NO_FW;
- set_bit(STATUS_FW_ERROR, &mld->trans->status);
- }
+ if (ret)
return 1;
- }
if (iwl_mld_no_wowlan_suspend(mld))
return 1;
@@ -2004,7 +2001,7 @@ static int iwl_mld_alloc_ptk_pn(struct iwl_mld *mld,
struct ieee80211_key_conf *key,
struct iwl_mld_ptk_pn **ptk_pn)
{
- u8 num_rx_queues = mld->trans->num_rx_queues;
+ u8 num_rx_queues = mld->trans->info.num_rxqs;
int keyidx = key->keyidx;
struct ieee80211_key_seq seq;
@@ -2067,9 +2064,8 @@ static int iwl_mld_set_key_add(struct iwl_mld *mld,
return -EOPNOTSUPP;
}
- if (vif->type == NL80211_IFTYPE_STATION &&
- (keyidx == 6 || keyidx == 7))
- rcu_assign_pointer(mld_vif->bigtks[keyidx - 6], key);
+ if (keyidx == 6 || keyidx == 7)
+ iwl_mld_track_bigtk(mld, vif, key, true);
/* After exiting from RFKILL, hostapd configures GTK/ITGK before the
* AP is started, but those keys can't be sent to the FW before the
@@ -2118,9 +2114,8 @@ static void iwl_mld_set_key_remove(struct iwl_mld *mld,
sta ? iwl_mld_sta_from_mac80211(sta) : NULL;
int keyidx = key->keyidx;
- if (vif->type == NL80211_IFTYPE_STATION &&
- (keyidx == 6 || keyidx == 7))
- RCU_INIT_POINTER(mld_vif->bigtks[keyidx - 6], NULL);
+ if (keyidx == 6 || keyidx == 7)
+ iwl_mld_track_bigtk(mld, vif, key, false);
if (mld_sta && key->flags & IEEE80211_KEY_FLAG_PAIRWISE &&
(key->cipher == WLAN_CIPHER_SUITE_CCMP ||
@@ -2460,15 +2455,17 @@ iwl_mld_change_vif_links(struct ieee80211_hw *hw,
added |= BIT(0);
for (int i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
- if (removed & BIT(i))
+ if (removed & BIT(i) && !WARN_ON(!old[i]))
iwl_mld_remove_link(mld, old[i]);
}
for (int i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
if (added & BIT(i)) {
link_conf = link_conf_dereference_protected(vif, i);
- if (WARN_ON(!link_conf))
- return -EINVAL;
+ if (!link_conf) {
+ err = -EINVAL;
+ goto remove_added_links;
+ }
err = iwl_mld_add_link(mld, link_conf);
if (err)
@@ -2503,7 +2500,11 @@ remove_added_links:
iwl_mld_remove_link(mld, link_conf);
}
- return err;
+ if (WARN_ON(!iwl_mld_error_before_recovery(mld)))
+ return err;
+
+ /* reconfig will fix us anyway */
+ return 0;
}
static int iwl_mld_change_sta_links(struct ieee80211_hw *hw,
@@ -2535,28 +2536,6 @@ static int iwl_mld_mac80211_tx_last_beacon(struct ieee80211_hw *hw)
return mld->ibss_manager;
}
-#define IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS_TIMEOUT (5 * HZ)
-
-static void iwl_mld_vif_iter_emlsr_block_tmp_non_bss(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
-{
- struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
- int ret;
-
- if (!iwl_mld_vif_has_emlsr_cap(vif))
- return;
-
- ret = iwl_mld_block_emlsr_sync(mld_vif->mld, vif,
- IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS,
- iwl_mld_get_primary_link(vif));
- if (ret)
- return;
-
- wiphy_delayed_work_queue(mld_vif->mld->wiphy,
- &mld_vif->emlsr.tmp_non_bss_done_wk,
- IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS_TIMEOUT);
-}
-
static void iwl_mld_prep_add_interface(struct ieee80211_hw *hw,
enum nl80211_iftype type)
{
@@ -2569,10 +2548,7 @@ static void iwl_mld_prep_add_interface(struct ieee80211_hw *hw,
type == NL80211_IFTYPE_P2P_CLIENT))
return;
- ieee80211_iterate_active_interfaces_mtx(mld->hw,
- IEEE80211_IFACE_ITER_NORMAL,
- iwl_mld_vif_iter_emlsr_block_tmp_non_bss,
- NULL);
+ iwl_mld_emlsr_block_tmp_non_bss(mld);
}
static int iwl_mld_set_hw_timestamp(struct ieee80211_hw *hw,
@@ -2602,11 +2578,61 @@ static int iwl_mld_start_pmsr(struct ieee80211_hw *hw,
return iwl_mld_ftm_start(mld, vif, request);
}
+static enum ieee80211_neg_ttlm_res
+iwl_mld_can_neg_ttlm(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_neg_ttlm *neg_ttlm)
+{
+ u16 map;
+
+ /* Verify all TIDs are mapped to the same links set */
+ map = neg_ttlm->downlink[0];
+ for (int i = 0; i < IEEE80211_TTLM_NUM_TIDS; i++) {
+ if (neg_ttlm->downlink[i] != neg_ttlm->uplink[i] ||
+ neg_ttlm->uplink[i] != map)
+ return NEG_TTLM_RES_REJECT;
+ }
+
+ return NEG_TTLM_RES_ACCEPT;
+}
+
+static int iwl_mld_get_antenna(struct ieee80211_hw *hw, int radio_idx,
+ u32 *tx_ant, u32 *rx_ant)
+{
+ struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
+
+ *tx_ant = iwl_mld_get_valid_tx_ant(mld);
+ *rx_ant = iwl_mld_get_valid_rx_ant(mld);
+
+ return 0;
+}
+
+static int iwl_mld_set_antenna(struct ieee80211_hw *hw, int radio_idx,
+ u32 tx_ant, u32 rx_ant)
+{
+ struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
+
+ if (WARN_ON(!mld->nvm_data))
+ return -EBUSY;
+
+ /* mac80211 ensures the device is not started,
+ * so the firmware cannot be running
+ */
+
+ mld->set_tx_ant = tx_ant;
+ mld->set_rx_ant = rx_ant;
+
+ iwl_reinit_cab(mld->trans, mld->nvm_data, tx_ant, rx_ant, mld->fw);
+
+ return 0;
+}
+
const struct ieee80211_ops iwl_mld_hw_ops = {
.tx = iwl_mld_mac80211_tx,
.start = iwl_mld_mac80211_start,
.stop = iwl_mld_mac80211_stop,
.config = iwl_mld_mac80211_config,
+ .get_antenna = iwl_mld_get_antenna,
+ .set_antenna = iwl_mld_set_antenna,
.add_interface = iwl_mld_mac80211_add_interface,
.remove_interface = iwl_mld_mac80211_remove_interface,
.conf_tx = iwl_mld_mac80211_conf_tx,
@@ -2631,6 +2657,7 @@ const struct ieee80211_ops iwl_mld_hw_ops = {
.mgd_complete_tx = iwl_mld_mac_mgd_complete_tx,
.sta_state = iwl_mld_mac80211_sta_state,
.sta_statistics = iwl_mld_mac80211_sta_statistics,
+ .get_survey = iwl_mld_mac80211_get_survey,
.flush = iwl_mld_mac80211_flush,
.flush_sta = iwl_mld_mac80211_flush_sta,
.ampdu_action = iwl_mld_mac80211_ampdu_action,
@@ -2671,4 +2698,5 @@ const struct ieee80211_ops iwl_mld_hw_ops = {
.prep_add_interface = iwl_mld_prep_add_interface,
.set_hw_timestamp = iwl_mld_set_hw_timestamp,
.start_pmsr = iwl_mld_start_pmsr,
+ .can_neg_ttlm = iwl_mld_can_neg_ttlm,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mcc.c b/drivers/net/wireless/intel/iwlwifi/mld/mcc.c
index daca14e208bd..16bb1b4904f9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mcc.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mcc.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2024 Intel Corporation
+ * Copyright (C) 2024-2025 Intel Corporation
*/
#include <net/cfg80211.h>
@@ -15,7 +15,7 @@
/* It is the caller's responsibility to free the pointer returned here */
static struct iwl_mcc_update_resp_v8 *
-iwl_mld_parse_mcc_update_resp_v8(const struct iwl_rx_packet *pkt)
+iwl_mld_copy_mcc_resp(const struct iwl_rx_packet *pkt)
{
const struct iwl_mcc_update_resp_v8 *mcc_resp_v8 = (const void *)pkt->data;
int n_channels = __le32_to_cpu(mcc_resp_v8->n_channels);
@@ -34,41 +34,9 @@ iwl_mld_parse_mcc_update_resp_v8(const struct iwl_rx_packet *pkt)
/* It is the caller's responsibility to free the pointer returned here */
static struct iwl_mcc_update_resp_v8 *
-iwl_mld_parse_mcc_update_resp_v5_v6(const struct iwl_rx_packet *pkt)
-{
- const struct iwl_mcc_update_resp_v4 *mcc_resp_v4 = (const void *)pkt->data;
- struct iwl_mcc_update_resp_v8 *resp_cp;
- int n_channels = __le32_to_cpu(mcc_resp_v4->n_channels);
- int resp_len;
-
- if (iwl_rx_packet_payload_len(pkt) !=
- struct_size(mcc_resp_v4, channels, n_channels))
- return ERR_PTR(-EINVAL);
-
- resp_len = struct_size(resp_cp, channels, n_channels);
- resp_cp = kzalloc(resp_len, GFP_KERNEL);
- if (!resp_cp)
- return ERR_PTR(-ENOMEM);
-
- resp_cp->status = mcc_resp_v4->status;
- resp_cp->mcc = mcc_resp_v4->mcc;
- resp_cp->cap = cpu_to_le32(le16_to_cpu(mcc_resp_v4->cap));
- resp_cp->source_id = mcc_resp_v4->source_id;
- resp_cp->geo_info = mcc_resp_v4->geo_info;
- resp_cp->n_channels = mcc_resp_v4->n_channels;
- memcpy(resp_cp->channels, mcc_resp_v4->channels,
- n_channels * sizeof(__le32));
-
- return resp_cp;
-}
-
-/* It is the caller's responsibility to free the pointer returned here */
-static struct iwl_mcc_update_resp_v8 *
iwl_mld_update_mcc(struct iwl_mld *mld, const char *alpha2,
enum iwl_mcc_source src_id)
{
- int resp_ver = iwl_fw_lookup_notif_ver(mld->fw, LONG_GROUP,
- MCC_UPDATE_CMD, 0);
struct iwl_mcc_update_cmd mcc_update_cmd = {
.mcc = cpu_to_le16(alpha2[0] << 8 | alpha2[1]),
.source_id = (u8)src_id,
@@ -93,23 +61,7 @@ iwl_mld_update_mcc(struct iwl_mld *mld, const char *alpha2,
pkt = cmd.resp_pkt;
- /* For Wifi-7 radios, we get version 8
- * For Wifi-6E radios, we get version 6
- * For Wifi-6 radios, we get version 5, but 5, 6, and 4 are compatible.
- */
- switch (resp_ver) {
- case 5:
- case 6:
- resp_cp = iwl_mld_parse_mcc_update_resp_v5_v6(pkt);
- break;
- case 8:
- resp_cp = iwl_mld_parse_mcc_update_resp_v8(pkt);
- break;
- default:
- IWL_FW_CHECK_FAILED(mld, "Unknown MCC_UPDATE_CMD version %d\n", resp_ver);
- resp_cp = ERR_PTR(-EINVAL);
- }
-
+ resp_cp = iwl_mld_copy_mcc_resp(pkt);
if (IS_ERR(resp_cp))
goto exit;
@@ -158,7 +110,7 @@ iwl_mld_get_regdomain(struct iwl_mld *mld,
}
IWL_DEBUG_LAR(mld, "MCC update response version: %d\n", resp_ver);
- regd = iwl_parse_nvm_mcc_info(mld->trans->dev, mld->cfg,
+ regd = iwl_parse_nvm_mcc_info(mld->trans,
__le32_to_cpu(resp->n_channels),
resp->channels,
__le16_to_cpu(resp->mcc),
@@ -177,11 +129,15 @@ iwl_mld_get_regdomain(struct iwl_mld *mld,
mld->mcc_src = resp->source_id;
- if (!iwl_puncturing_is_allowed_in_bios(mld->bios_enable_puncturing,
- le16_to_cpu(resp->mcc)))
- ieee80211_hw_set(mld->hw, DISALLOW_PUNCTURING);
- else
- __clear_bit(IEEE80211_HW_DISALLOW_PUNCTURING, mld->hw->flags);
+ /* FM is the earliest supported and later always do puncturing */
+ if (CSR_HW_RFID_TYPE(mld->trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_FM) {
+ if (!iwl_puncturing_is_allowed_in_bios(mld->bios_enable_puncturing,
+ le16_to_cpu(resp->mcc)))
+ ieee80211_hw_set(mld->hw, DISALLOW_PUNCTURING);
+ else
+ __clear_bit(IEEE80211_HW_DISALLOW_PUNCTURING,
+ mld->hw->flags);
+ }
out:
kfree(resp);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.c b/drivers/net/wireless/intel/iwlwifi/mld/mld.c
index 73d2166a4c25..8a4c96385640 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mld.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.c
@@ -26,6 +26,8 @@
#include "hcmd.h"
#include "fw/api/location.h"
+#include "iwl-nvm-parse.h"
+
#define DRV_DESCRIPTION "Intel(R) MLD wireless driver for Linux"
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_LICENSE("GPL");
@@ -60,7 +62,7 @@ static void iwl_mld_hw_set_regulatory(struct iwl_mld *mld)
VISIBLE_IF_IWLWIFI_KUNIT
void iwl_construct_mld(struct iwl_mld *mld, struct iwl_trans *trans,
- const struct iwl_cfg *cfg, const struct iwl_fw *fw,
+ const struct iwl_rf_cfg *cfg, const struct iwl_fw *fw,
struct ieee80211_hw *hw, struct dentry *dbgfs_dir)
{
mld->dev = trans->dev;
@@ -145,6 +147,7 @@ iwl_mld_construct_fw_runtime(struct iwl_mld *mld, struct iwl_trans *trans,
*/
static const struct iwl_hcmd_names iwl_mld_legacy_names[] = {
HCMD_NAME(UCODE_ALIVE_NTFY),
+ HCMD_NAME(REPLY_ERROR),
HCMD_NAME(INIT_COMPLETE_NOTIF),
HCMD_NAME(PHY_CONTEXT_CMD),
HCMD_NAME(SCAN_CFG_CMD),
@@ -156,12 +159,14 @@ static const struct iwl_hcmd_names iwl_mld_legacy_names[] = {
HCMD_NAME(LEDS_CMD),
HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_NOTIFICATION),
HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_CONFIRM_NOTIFICATION),
+ HCMD_NAME(PHY_CONFIGURATION_CMD),
HCMD_NAME(SCAN_OFFLOAD_UPDATE_PROFILES_CMD),
HCMD_NAME(POWER_TABLE_CMD),
HCMD_NAME(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION),
HCMD_NAME(BEACON_NOTIFICATION),
HCMD_NAME(BEACON_TEMPLATE_CMD),
HCMD_NAME(TX_ANT_CONFIGURATION_CMD),
+ HCMD_NAME(BT_CONFIG),
HCMD_NAME(REDUCE_TX_POWER_CMD),
HCMD_NAME(MISSED_BEACONS_NOTIFICATION),
HCMD_NAME(MAC_PM_POWER_TABLE),
@@ -192,6 +197,7 @@ static const struct iwl_hcmd_names iwl_mld_system_names[] = {
HCMD_NAME(SOC_CONFIGURATION_CMD),
HCMD_NAME(INIT_EXTENDED_CFG_CMD),
HCMD_NAME(FW_ERROR_RECOVERY_CMD),
+ HCMD_NAME(RFI_CONFIG_CMD),
HCMD_NAME(RFI_GET_FREQ_TABLE_CMD),
HCMD_NAME(SYSTEM_STATISTICS_CMD),
HCMD_NAME(SYSTEM_STATISTICS_END_NOTIF),
@@ -248,16 +254,25 @@ static const struct iwl_hcmd_names iwl_mld_data_path_names[] = {
HCMD_NAME(TLC_MNG_CONFIG_CMD),
HCMD_NAME(RX_BAID_ALLOCATION_CONFIG_CMD),
HCMD_NAME(SCD_QUEUE_CONFIG_CMD),
- HCMD_NAME(OMI_SEND_STATUS_NOTIF),
+ HCMD_NAME(SEC_KEY_CMD),
HCMD_NAME(ESR_MODE_NOTIF),
HCMD_NAME(MONITOR_NOTIF),
HCMD_NAME(TLC_MNG_UPDATE_NOTIF),
+ HCMD_NAME(BEACON_FILTER_IN_NOTIF),
+ HCMD_NAME(PHY_AIR_SNIFFER_NOTIF),
HCMD_NAME(MU_GROUP_MGMT_NOTIF),
};
/* Please keep this array *SORTED* by hex value.
* Access is done through binary search
*/
+static const struct iwl_hcmd_names iwl_mld_scan_names[] = {
+ HCMD_NAME(CHANNEL_SURVEY_NOTIF),
+};
+
+/* Please keep this array *SORTED* by hex value.
+ * Access is done through binary search
+ */
static const struct iwl_hcmd_names iwl_mld_location_names[] = {
HCMD_NAME(TOF_RANGE_REQ_CMD),
HCMD_NAME(TOF_RANGE_RESPONSE_NOTIF),
@@ -287,7 +302,9 @@ static const struct iwl_hcmd_names iwl_mld_statistics_names[] = {
* Access is done through binary search
*/
static const struct iwl_hcmd_names iwl_mld_prot_offload_names[] = {
- HCMD_NAME(STORED_BEACON_NTF),
+ HCMD_NAME(WOWLAN_WAKE_PKT_NOTIFICATION),
+ HCMD_NAME(WOWLAN_INFO_NOTIFICATION),
+ HCMD_NAME(D3_END_NOTIFICATION),
};
/* Please keep this array *SORTED* by hex value.
@@ -304,6 +321,7 @@ const struct iwl_hcmd_arr iwl_mld_groups[] = {
[SYSTEM_GROUP] = HCMD_ARR(iwl_mld_system_names),
[MAC_CONF_GROUP] = HCMD_ARR(iwl_mld_mac_conf_names),
[DATA_PATH_GROUP] = HCMD_ARR(iwl_mld_data_path_names),
+ [SCAN_GROUP] = HCMD_ARR(iwl_mld_scan_names),
[LOCATION_GROUP] = HCMD_ARR(iwl_mld_location_names),
[REGULATORY_AND_NVM_GROUP] = HCMD_ARR(iwl_mld_reg_and_nvm_names),
[DEBUG_GROUP] = HCMD_ARR(iwl_mld_debug_names),
@@ -322,33 +340,40 @@ EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(global_iwl_mld_goups_size);
static void
iwl_mld_configure_trans(struct iwl_op_mode *op_mode)
{
- const struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
+ struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
static const u8 no_reclaim_cmds[] = {TX_CMD};
- struct iwl_trans_config trans_cfg = {
- .op_mode = op_mode,
- /* Rx is not supported yet, but add it to avoid warnings */
- .rx_buf_size = iwl_amsdu_size_to_rxb_size(),
- .command_groups = iwl_mld_groups,
- .command_groups_size = ARRAY_SIZE(iwl_mld_groups),
- .fw_reset_handshake = true,
- .queue_alloc_cmd_ver =
- iwl_fw_lookup_cmd_ver(mld->fw,
- WIDE_ID(DATA_PATH_GROUP,
- SCD_QUEUE_CONFIG_CMD),
- 0),
- .no_reclaim_cmds = no_reclaim_cmds,
- .n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds),
- .cb_data_offs = offsetof(struct ieee80211_tx_info,
- driver_data[2]),
- };
struct iwl_trans *trans = mld->trans;
+ u32 eckv_value;
- trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
- trans->iml = mld->fw->iml;
- trans->iml_len = mld->fw->iml_len;
- trans->wide_cmd_header = true;
+ iwl_bios_setup_step(trans, &mld->fwrt);
+ iwl_uefi_get_step_table(trans);
- iwl_trans_configure(trans, &trans_cfg);
+ if (iwl_bios_get_eckv(&mld->fwrt, &eckv_value))
+ IWL_DEBUG_RADIO(mld, "ECKV table doesn't exist in BIOS\n");
+ else
+ trans->conf.ext_32khz_clock_valid = !!eckv_value;
+
+ trans->conf.rx_buf_size = iwl_amsdu_size_to_rxb_size();
+ trans->conf.command_groups = iwl_mld_groups;
+ trans->conf.command_groups_size = ARRAY_SIZE(iwl_mld_groups);
+ trans->conf.fw_reset_handshake = true;
+ trans->conf.queue_alloc_cmd_ver =
+ iwl_fw_lookup_cmd_ver(mld->fw, WIDE_ID(DATA_PATH_GROUP,
+ SCD_QUEUE_CONFIG_CMD),
+ 0);
+ trans->conf.cb_data_offs = offsetof(struct ieee80211_tx_info,
+ driver_data[2]);
+ BUILD_BUG_ON(sizeof(no_reclaim_cmds) >
+ sizeof(trans->conf.no_reclaim_cmds));
+ memcpy(trans->conf.no_reclaim_cmds, no_reclaim_cmds,
+ sizeof(no_reclaim_cmds));
+ trans->conf.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
+
+ trans->conf.rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
+ trans->conf.rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_desc);
+ trans->conf.wide_cmd_header = true;
+
+ iwl_trans_op_mode_enter(trans, op_mode);
}
/*
@@ -359,13 +384,12 @@ iwl_mld_configure_trans(struct iwl_op_mode *op_mode)
#define NUM_FW_LOAD_RETRIES 3
static struct iwl_op_mode *
-iwl_op_mode_mld_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
+iwl_op_mode_mld_start(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
const struct iwl_fw *fw, struct dentry *dbgfs_dir)
{
struct ieee80211_hw *hw;
struct iwl_op_mode *op_mode;
struct iwl_mld *mld;
- u32 eckv_value;
int ret;
/* Allocate and initialize a new hardware device */
@@ -383,16 +407,13 @@ iwl_op_mode_mld_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
iwl_construct_mld(mld, trans, cfg, fw, hw, dbgfs_dir);
+ /* we'll verify later it matches between commands */
+ mld->fw_rates_ver_3 = iwl_fw_lookup_cmd_ver(mld->fw, TX_CMD, 0) >= 11;
+
iwl_mld_construct_fw_runtime(mld, trans, fw, dbgfs_dir);
iwl_mld_get_bios_tables(mld);
iwl_uefi_get_sgom_table(trans, &mld->fwrt);
- iwl_uefi_get_step_table(trans);
- if (iwl_bios_get_eckv(&mld->fwrt, &eckv_value))
- IWL_DEBUG_RADIO(mld, "ECKV table doesn't exist in BIOS\n");
- else
- trans->ext_32khz_clock_valid = !!eckv_value;
- iwl_bios_setup_step(trans, &mld->fwrt);
mld->bios_enable_puncturing = iwl_uefi_get_puncturing(&mld->fwrt);
iwl_mld_hw_set_regulatory(mld);
@@ -411,10 +432,17 @@ iwl_op_mode_mld_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
break;
}
+ if (!ret) {
+ mld->nvm_data = iwl_get_nvm(mld->trans, mld->fw, 0, 0);
+ if (IS_ERR(mld->nvm_data)) {
+ IWL_ERR(mld, "Failed to read NVM: %d\n", ret);
+ ret = PTR_ERR(mld->nvm_data);
+ }
+ }
+
if (ret) {
wiphy_unlock(mld->wiphy);
rtnl_unlock();
- iwl_fw_flush_dumps(&mld->fwrt);
goto err;
}
@@ -475,8 +503,9 @@ iwl_op_mode_mld_stop(struct iwl_op_mode *op_mode)
iwl_mld_ptp_remove(mld);
iwl_mld_leds_exit(mld);
- wiphy_lock(mld->wiphy);
iwl_mld_thermal_exit(mld);
+
+ wiphy_lock(mld->wiphy);
iwl_mld_low_latency_stop(mld);
iwl_mld_deinit_time_sync(mld);
wiphy_unlock(mld->wiphy);
@@ -490,6 +519,7 @@ iwl_op_mode_mld_stop(struct iwl_op_mode *op_mode)
kfree(mld->nvm_data);
kfree(mld->scan.cmd);
+ kfree(mld->channel_survey);
kfree(mld->error_recovery_buf);
kfree(mld->mcast_filter_cmd);
@@ -614,7 +644,7 @@ iwl_mld_nic_error(struct iwl_op_mode *op_mode,
enum iwl_fw_error_type type)
{
struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
- bool trans_dead = test_bit(STATUS_TRANS_DEAD, &mld->trans->status);
+ bool trans_dead = iwl_trans_is_dead(mld->trans);
if (type == IWL_ERR_TYPE_CMD_QUEUE_FULL)
IWL_ERR(mld, "Command queue full!\n");
@@ -638,7 +668,8 @@ iwl_mld_nic_error(struct iwl_op_mode *op_mode,
* It might not actually be true that we'll restart, but the
* setting doesn't matter if we're going to be unbound either.
*/
- if (type != IWL_ERR_TYPE_RESET_HS_TIMEOUT)
+ if (type != IWL_ERR_TYPE_RESET_HS_TIMEOUT &&
+ mld->fw_status.running)
mld->fw_status.in_hw_restart = true;
}
@@ -664,6 +695,13 @@ static bool iwl_mld_sw_reset(struct iwl_op_mode *op_mode,
{
struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
+ /* SW reset can happen for TOP error w/o NIC error, so
+ * also abort scan here and set in_hw_restart, when we
+ * had a NIC error both were already done.
+ */
+ iwl_mld_report_scan_aborted(mld);
+ mld->fw_status.in_hw_restart = true;
+
/* Do restart only in the following conditions are met:
* - we consider the FW as running
* - The trigger that brought us here is defined as one that requires
@@ -692,7 +730,6 @@ static void iwl_mld_device_powered_off(struct iwl_op_mode *op_mode)
struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
wiphy_lock(mld->wiphy);
- mld->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
iwl_mld_stop_fw(mld);
mld->fw_status.in_d3 = false;
wiphy_unlock(mld->wiphy);
@@ -702,6 +739,17 @@ static void iwl_mld_device_powered_off(struct iwl_op_mode *op_mode)
{}
#endif
+static void iwl_mld_dump(struct iwl_op_mode *op_mode)
+{
+ struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
+ struct iwl_fw_runtime *fwrt = &mld->fwrt;
+
+ if (!iwl_trans_fw_running(fwrt->trans))
+ return;
+
+ iwl_dbg_tlv_time_point(fwrt, IWL_FW_INI_TIME_POINT_USER_TRIGGER, NULL);
+}
+
static const struct iwl_op_mode_ops iwl_mld_ops = {
.start = iwl_op_mode_mld_start,
.stop = iwl_op_mode_mld_stop,
@@ -716,6 +764,7 @@ static const struct iwl_op_mode_ops iwl_mld_ops = {
.sw_reset = iwl_mld_sw_reset,
.time_point = iwl_mld_time_point,
.device_powered_off = pm_sleep_ptr(iwl_mld_device_powered_off),
+ .dump = iwl_mld_dump,
};
struct iwl_mld_mod_params iwlmld_mod_params = {
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.h b/drivers/net/wireless/intel/iwlwifi/mld/mld.h
index a4a16da6ebf3..22efe8e10f53 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mld.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.h
@@ -116,8 +116,13 @@
* @monitor.ampdu_toggle: the state of the previous packet to track A-MPDU
* @monitor.cur_aid: current association id tracked by the sniffer
* @monitor.cur_bssid: current bssid tracked by the sniffer
+ * @monitor.ptp_time: set the Rx mactime using the device's PTP clock time
* @monitor.p80: primary channel position relative to he whole bandwidth, in
- * steps of 80 MHz
+ * steps of 80 MHz
+ * @monitor.phy: PHY data information
+ * @monitor.phy.data: PHY data (&struct iwl_rx_phy_air_sniffer_ntfy) received
+ * @monitor.phy.valid: PHY data is valid (was received)
+ * @monitor.phy.used: PHY data was used by an RX
* @fw_id_to_link_sta: maps a fw id of a sta to the corresponding
* ieee80211_link_sta. This is not cleaned up on restart since we want to
* preserve the fw sta ids during a restart (for SN/PN restoring).
@@ -133,6 +138,8 @@
* @fw: a pointer to the fw object
* @hw: pointer to the hw object.
* @wiphy: a pointer to the wiphy struct, for easier access to it.
+ * @ext_capab: extended capabilities that will be set to wiphy on registration.
+ * @sta_ext_capab: extended capabilities for the station interface.
* @nvm_data: pointer to the nvm_data that includes all our capabilities
* @fwrt: fw runtime data
* @debugfs_dir: debugfs directory
@@ -149,14 +156,19 @@
* @running: true if the firmware is running
* @do_not_dump_once: true if firmware dump must be prevented once
* @in_d3: indicates FW is in suspend mode and should be resumed
+ * @resuming: indicates the driver is resuming from wowlan
* @in_hw_restart: indicates that we are currently in restart flow.
* rather than restarted. Should be unset upon restart.
* @radio_kill: bitmap of radio kill status
* @radio_kill.hw: radio is killed by hw switch
* @radio_kill.ct: radio is killed because the device it too hot
+ * @power_budget_mw: maximum cTDP power budget as defined for this system and
+ * device
* @addresses: device MAC addresses.
* @scan: instance of the scan object
+ * @channel_survey: channel survey information collected during scan
* @wowlan: WoWLAN support data.
+ * @debug_max_sleep: maximum sleep time in D3 (for debug purposes)
* @led: the led device
* @mcc_src: the source id of the MCC, comes from the firmware
* @bios_enable_puncturing: is puncturing enabled by bios
@@ -174,6 +186,9 @@
* @mcast_filter_cmd: pointer to the multicast filter command.
* @mgmt_tx_ant: stores the last TX antenna index; used for setting
* TX rate_n_flags for non-STA mgmt frames (toggles on every TX failure).
+ * @set_tx_ant: stores the last TX antenna bitmask set by user space (if any)
+ * @set_rx_ant: stores the last RX antenna bitmask set by user space (if any)
+ * @fw_rates_ver_3: FW rates are in version 3
* @low_latency: low-latency manager.
* @tzone: thermal zone device's data
* @cooling_dev: cooling device's related data
@@ -198,9 +213,14 @@ struct iwl_mld {
u32 ampdu_ref;
bool ampdu_toggle;
u8 p80;
+ struct {
+ struct iwl_rx_phy_air_sniffer_ntfy data;
+ u8 valid:1, used:1;
+ } phy;
#ifdef CONFIG_IWLWIFI_DEBUGFS
__le16 cur_aid;
u8 cur_bssid[ETH_ALEN];
+ bool ptp_time;
#endif
} monitor;
#ifdef CONFIG_PM_SLEEP
@@ -213,10 +233,12 @@ struct iwl_mld {
/* And here fields that survive a fw restart */
struct device *dev;
struct iwl_trans *trans;
- const struct iwl_cfg *cfg;
+ const struct iwl_rf_cfg *cfg;
const struct iwl_fw *fw;
struct ieee80211_hw *hw;
struct wiphy *wiphy;
+ struct wiphy_iftype_ext_capab ext_capab[IWL_MLD_EXT_CAPA_NUM_IFTYPES];
+ u8 sta_ext_capab[IWL_MLD_STA_EXT_CAPA_SIZE];
struct iwl_nvm_data *nvm_data;
struct iwl_fw_runtime fwrt;
struct dentry *debugfs_dir;
@@ -231,6 +253,7 @@ struct iwl_mld {
do_not_dump_once:1,
#ifdef CONFIG_PM_SLEEP
in_d3:1,
+ resuming:1,
#endif
in_hw_restart:1;
@@ -241,10 +264,14 @@ struct iwl_mld {
ct:1;
} radio_kill;
+ u32 power_budget_mw;
+
struct mac_address addresses[IWL_MLD_MAX_ADDRESSES];
struct iwl_mld_scan scan;
+ struct iwl_mld_survey *channel_survey;
#ifdef CONFIG_PM_SLEEP
struct wiphy_wowlan_support wowlan;
+ u32 debug_max_sleep;
#endif /* CONFIG_PM_SLEEP */
#ifdef CONFIG_IWLWIFI_LEDS
struct led_classdev led;
@@ -266,6 +293,11 @@ struct iwl_mld {
u8 mgmt_tx_ant;
+ u8 set_tx_ant;
+ u8 set_rx_ant;
+
+ bool fw_rates_ver_3;
+
struct iwl_mld_low_latency low_latency;
bool ibss_manager;
@@ -286,7 +318,7 @@ struct iwl_mld {
memset((void *)&(_ptr)->zeroed_on_hw_restart, 0, \
sizeof((_ptr)->zeroed_on_hw_restart))
-/* Cleanup function for struct iwl_mld_vif, will be called in restart */
+/* Cleanup function for struct iwl_mld, will be called in restart */
static inline void
iwl_cleanup_mld(struct iwl_mld *mld)
{
@@ -359,6 +391,9 @@ static inline u8 iwl_mld_get_valid_tx_ant(const struct iwl_mld *mld)
if (mld->nvm_data && mld->nvm_data->valid_tx_ant)
tx_ant &= mld->nvm_data->valid_tx_ant;
+ if (mld->set_tx_ant)
+ tx_ant &= mld->set_tx_ant;
+
return tx_ant;
}
@@ -369,6 +404,9 @@ static inline u8 iwl_mld_get_valid_rx_ant(const struct iwl_mld *mld)
if (mld->nvm_data && mld->nvm_data->valid_rx_ant)
rx_ant &= mld->nvm_data->valid_rx_ant;
+ if (mld->set_rx_ant)
+ rx_ant &= mld->set_rx_ant;
+
return rx_ant;
}
@@ -410,7 +448,7 @@ iwl_mld_legacy_hw_idx_to_mac80211_idx(u32 rate_n_flags,
int rate = rate_n_flags & RATE_LEGACY_RATE_MSK;
bool is_lb = band == NL80211_BAND_2GHZ;
- if (format == RATE_MCS_LEGACY_OFDM_MSK)
+ if (format == RATE_MCS_MOD_TYPE_LEGACY_OFDM)
return is_lb ? rate + IWL_FIRST_OFDM_RATE : rate;
/* CCK is not allowed in 5 GHz */
@@ -482,7 +520,7 @@ iwl_mld_is_dup(struct iwl_mld *mld, struct ieee80211_sta *sta,
struct ieee80211_rx_status *rx_status, int queue);
void iwl_construct_mld(struct iwl_mld *mld, struct iwl_trans *trans,
- const struct iwl_cfg *cfg, const struct iwl_fw *fw,
+ const struct iwl_rf_cfg *cfg, const struct iwl_fw *fw,
struct ieee80211_hw *hw, struct dentry *dbgfs_dir);
#endif
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
index a870e169e265..c6b151f26921 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
@@ -31,11 +31,9 @@ static void iwl_mld_print_emlsr_blocked(struct iwl_mld *mld, u32 mask)
{
#define NAME_FMT(x) "%s"
#define NAME_PR(x) (mask & IWL_MLD_EMLSR_BLOCKED_##x) ? "[" #x "]" : "",
- IWL_DEBUG_INFO(mld,
- "EMLSR blocked = " HANDLE_EMLSR_BLOCKED_REASONS(NAME_FMT)
- " (0x%x)\n",
- HANDLE_EMLSR_BLOCKED_REASONS(NAME_PR)
- mask);
+ IWL_DEBUG_EHT(mld,
+ "EMLSR blocked = " HANDLE_EMLSR_BLOCKED_REASONS(NAME_FMT)
+ " (0x%x)\n", HANDLE_EMLSR_BLOCKED_REASONS(NAME_PR) mask);
#undef NAME_FMT
#undef NAME_PR
}
@@ -52,7 +50,8 @@ static void iwl_mld_print_emlsr_blocked(struct iwl_mld *mld, u32 mask)
HOW(BT_COEX) \
HOW(CHAN_LOAD) \
HOW(RFI) \
- HOW(FW_REQUEST)
+ HOW(FW_REQUEST) \
+ HOW(INVALID)
static const char *
iwl_mld_get_emlsr_exit_string(enum iwl_mld_emlsr_exit exit)
@@ -71,11 +70,9 @@ static void iwl_mld_print_emlsr_exit(struct iwl_mld *mld, u32 mask)
{
#define NAME_FMT(x) "%s"
#define NAME_PR(x) (mask & IWL_MLD_EMLSR_EXIT_##x) ? "[" #x "]" : "",
- IWL_DEBUG_INFO(mld,
- "EMLSR exit = " HANDLE_EMLSR_EXIT_REASONS(NAME_FMT)
- " (0x%x)\n",
- HANDLE_EMLSR_EXIT_REASONS(NAME_PR)
- mask);
+ IWL_DEBUG_EHT(mld,
+ "EMLSR exit = " HANDLE_EMLSR_EXIT_REASONS(NAME_FMT)
+ " (0x%x)\n", HANDLE_EMLSR_EXIT_REASONS(NAME_PR) mask);
#undef NAME_FMT
#undef NAME_PR
}
@@ -169,10 +166,10 @@ static void iwl_mld_check_emlsr_prevention(struct iwl_mld *mld,
WARN_ON(mld_vif->emlsr.exit_repeat_count > 3);
}
- IWL_DEBUG_INFO(mld,
- "Preventing EMLSR for %ld seconds due to %u exits with the reason = %s (0x%x)\n",
- delay / HZ, mld_vif->emlsr.exit_repeat_count,
- iwl_mld_get_emlsr_exit_string(reason), reason);
+ IWL_DEBUG_EHT(mld,
+ "Preventing EMLSR for %ld seconds due to %u exits with the reason = %s (0x%x)\n",
+ delay / HZ, mld_vif->emlsr.exit_repeat_count,
+ iwl_mld_get_emlsr_exit_string(reason), reason);
wiphy_delayed_work_queue(mld->wiphy,
&mld_vif->emlsr.prevent_done_wk, delay);
@@ -216,10 +213,10 @@ static int _iwl_mld_exit_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif,
link_to_keep = __ffs(vif->active_links);
new_active_links = BIT(link_to_keep);
- IWL_DEBUG_INFO(mld,
- "Exiting EMLSR. reason = %s (0x%x). Current active links=0x%x, new active links = 0x%x\n",
- iwl_mld_get_emlsr_exit_string(exit), exit,
- vif->active_links, new_active_links);
+ IWL_DEBUG_EHT(mld,
+ "Exiting EMLSR. reason = %s (0x%x). Current active links=0x%x, new active links = 0x%x\n",
+ iwl_mld_get_emlsr_exit_string(exit), exit,
+ vif->active_links, new_active_links);
if (sync)
ret = ieee80211_set_active_links(vif, new_active_links);
@@ -261,9 +258,8 @@ static int _iwl_mld_emlsr_block(struct iwl_mld *mld, struct ieee80211_vif *vif,
mld_vif->emlsr.blocked_reasons |= reason;
- IWL_DEBUG_INFO(mld,
- "Blocking EMLSR mode. reason = %s (0x%x)\n",
- iwl_mld_get_emlsr_blocked_string(reason), reason);
+ IWL_DEBUG_EHT(mld, "Blocking EMLSR mode. reason = %s (0x%x)\n",
+ iwl_mld_get_emlsr_blocked_string(reason), reason);
iwl_mld_print_emlsr_blocked(mld, mld_vif->emlsr.blocked_reasons);
if (reason == IWL_MLD_EMLSR_BLOCKED_TPT)
@@ -286,6 +282,36 @@ int iwl_mld_block_emlsr_sync(struct iwl_mld *mld, struct ieee80211_vif *vif,
return _iwl_mld_emlsr_block(mld, vif, reason, link_to_keep, true);
}
+#define IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS_TIMEOUT (10 * HZ)
+
+static void iwl_mld_vif_iter_emlsr_block_tmp_non_bss(void *_data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
+ int ret;
+
+ if (!iwl_mld_vif_has_emlsr_cap(vif))
+ return;
+
+ ret = iwl_mld_block_emlsr_sync(mld_vif->mld, vif,
+ IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS,
+ iwl_mld_get_primary_link(vif));
+ if (ret)
+ return;
+
+ wiphy_delayed_work_queue(mld_vif->mld->wiphy,
+ &mld_vif->emlsr.tmp_non_bss_done_wk,
+ IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS_TIMEOUT);
+}
+
+void iwl_mld_emlsr_block_tmp_non_bss(struct iwl_mld *mld)
+{
+ ieee80211_iterate_active_interfaces_mtx(mld->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mld_vif_iter_emlsr_block_tmp_non_bss,
+ NULL);
+}
+
static void _iwl_mld_select_links(struct iwl_mld *mld,
struct ieee80211_vif *vif);
@@ -304,9 +330,8 @@ void iwl_mld_unblock_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif,
mld_vif->emlsr.blocked_reasons &= ~reason;
- IWL_DEBUG_INFO(mld,
- "Unblocking EMLSR mode. reason = %s (0x%x)\n",
- iwl_mld_get_emlsr_blocked_string(reason), reason);
+ IWL_DEBUG_EHT(mld, "Unblocking EMLSR mode. reason = %s (0x%x)\n",
+ iwl_mld_get_emlsr_blocked_string(reason), reason);
iwl_mld_print_emlsr_blocked(mld, mld_vif->emlsr.blocked_reasons);
if (reason == IWL_MLD_EMLSR_BLOCKED_TPT)
@@ -317,7 +342,7 @@ void iwl_mld_unblock_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif,
if (mld_vif->emlsr.blocked_reasons)
return;
- IWL_DEBUG_INFO(mld, "EMLSR is unblocked\n");
+ IWL_DEBUG_EHT(mld, "EMLSR is unblocked\n");
iwl_mld_int_mlo_scan(mld, vif);
}
@@ -325,23 +350,31 @@ static void
iwl_mld_vif_iter_emlsr_mode_notif(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
- struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
- struct iwl_esr_mode_notif *notif = (void *)data;
+ const struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
+ const struct iwl_esr_mode_notif *notif = (void *)data;
+ enum iwl_mvm_fw_esr_recommendation action = le32_to_cpu(notif->action);
if (!iwl_mld_vif_has_emlsr_cap(vif))
return;
- switch (le32_to_cpu(notif->action)) {
+ switch (action) {
case ESR_RECOMMEND_LEAVE:
+ IWL_DEBUG_EHT(mld_vif->mld,
+ "FW recommend leave reason = 0x%x\n",
+ le32_to_cpu(notif->leave_reason_mask));
+
iwl_mld_exit_emlsr(mld_vif->mld, vif,
IWL_MLD_EMLSR_EXIT_FW_REQUEST,
iwl_mld_get_primary_link(vif));
break;
- case ESR_RECOMMEND_ENTER:
case ESR_FORCE_LEAVE:
+ IWL_DEBUG_EHT(mld_vif->mld, "FW force leave reason = 0x%x\n",
+ le32_to_cpu(notif->leave_reason_mask));
+ fallthrough;
+ case ESR_RECOMMEND_ENTER:
default:
IWL_WARN(mld_vif->mld, "Unexpected EMLSR notification: %d\n",
- le32_to_cpu(notif->action));
+ action);
}
}
@@ -372,11 +405,12 @@ void iwl_mld_handle_emlsr_trans_fail_notif(struct iwl_mld *mld,
struct ieee80211_bss_conf *bss_conf =
iwl_mld_fw_id_to_link_conf(mld, fw_link_id);
- IWL_DEBUG_INFO(mld, "Failed to %s EMLSR on link %d (FW: %d), reason %d\n",
- le32_to_cpu(notif->activation) ? "enter" : "exit",
- bss_conf ? bss_conf->link_id : -1,
- le32_to_cpu(notif->link_id),
- le32_to_cpu(notif->err_code));
+ IWL_DEBUG_EHT(mld,
+ "Failed to %s EMLSR on link %d (FW: %d), reason %d\n",
+ le32_to_cpu(notif->activation) ? "enter" : "exit",
+ bss_conf ? bss_conf->link_id : -1,
+ le32_to_cpu(notif->link_id),
+ le32_to_cpu(notif->err_code));
if (IWL_FW_CHECK(mld, !bss_conf,
"FW reported failure to %sactivate EMLSR on a non-existing link: %d\n",
@@ -508,10 +542,12 @@ void iwl_mld_emlsr_check_tpt(struct wiphy *wiphy, struct wiphy_work *wk)
/*
* TPT is unblocked, need to check if the TPT criteria is still met.
*
- * If EMLSR is active, then we also need to check the secondar link
- * requirements.
+ * If EMLSR is active for at least 5 seconds, then we also
+ * need to check the secondary link requirements.
*/
- if (iwl_mld_emlsr_active(vif)) {
+ if (iwl_mld_emlsr_active(vif) &&
+ time_is_before_jiffies(mld_vif->emlsr.last_entry_ts +
+ IWL_MLD_TPT_COUNT_WINDOW)) {
sec_link_id = iwl_mld_get_other_link(vif, iwl_mld_get_primary_link(vif));
sec_link = iwl_mld_link_dereference_check(mld_vif, sec_link_id);
if (WARN_ON_ONCE(!sec_link))
@@ -523,7 +559,7 @@ void iwl_mld_emlsr_check_tpt(struct wiphy *wiphy, struct wiphy_work *wk)
}
/* Sum up RX and TX MPDUs from the different queues/links */
- for (int q = 0; q < mld->trans->num_rx_queues; q++) {
+ for (int q = 0; q < mld->trans->info.num_rxqs; q++) {
struct iwl_mld_per_q_mpdu_counter *queue_counter =
&mld_sta->mpdu_counters[q];
@@ -548,8 +584,8 @@ void iwl_mld_emlsr_check_tpt(struct wiphy *wiphy, struct wiphy_work *wk)
spin_unlock_bh(&queue_counter->lock);
}
- IWL_DEBUG_INFO(mld, "total Tx MPDUs: %ld. total Rx MPDUs: %ld\n",
- total_tx, total_rx);
+ IWL_DEBUG_EHT(mld, "total Tx MPDUs: %ld. total Rx MPDUs: %ld\n",
+ total_tx, total_rx);
/* If we don't have enough MPDUs - exit EMLSR */
if (total_tx < IWL_MLD_ENTER_EMLSR_TPT_THRESH &&
@@ -561,10 +597,10 @@ void iwl_mld_emlsr_check_tpt(struct wiphy *wiphy, struct wiphy_work *wk)
/* EMLSR is not active */
if (sec_link_id == -1)
- return;
+ goto schedule;
- IWL_DEBUG_INFO(mld, "Secondary Link %d: Tx MPDUs: %ld. Rx MPDUs: %ld\n",
- sec_link_id, sec_link_tx, sec_link_rx);
+ IWL_DEBUG_EHT(mld, "Secondary Link %d: Tx MPDUs: %ld. Rx MPDUs: %ld\n",
+ sec_link_id, sec_link_tx, sec_link_rx);
/* Calculate the percentage of the secondary link TX/RX */
sec_link_tx_perc = total_tx ? sec_link_tx * 100 / total_tx : 0;
@@ -583,6 +619,7 @@ void iwl_mld_emlsr_check_tpt(struct wiphy *wiphy, struct wiphy_work *wk)
return;
}
+schedule:
/* Check again when the next window ends */
wiphy_delayed_work_queue(mld_vif->mld->wiphy,
&mld_vif->emlsr.check_tpt_wk,
@@ -643,11 +680,11 @@ iwl_mld_emlsr_disallowed_with_link(struct iwl_mld *mld,
{
struct wiphy *wiphy = mld->wiphy;
struct ieee80211_bss_conf *conf;
- enum iwl_mld_emlsr_exit ret = 0;
+ u32 ret = 0;
conf = wiphy_dereference(wiphy, vif->link_conf[link->link_id]);
if (WARN_ON_ONCE(!conf))
- return false;
+ return IWL_MLD_EMLSR_EXIT_INVALID;
if (link->chandef->chan->band == NL80211_BAND_2GHZ && mld->bt_is_active)
ret |= IWL_MLD_EMLSR_EXIT_BT_COEX;
@@ -660,10 +697,8 @@ iwl_mld_emlsr_disallowed_with_link(struct iwl_mld *mld,
ret |= IWL_MLD_EMLSR_EXIT_CSA;
if (ret) {
- IWL_DEBUG_INFO(mld,
- "Link %d is not allowed for EMLSR as %s\n",
- link->link_id,
- primary ? "primary" : "secondary");
+ IWL_DEBUG_EHT(mld, "Link %d is not allowed for EMLSR as %s\n",
+ link->link_id, primary ? "primary" : "secondary");
iwl_mld_print_emlsr_exit(mld, ret);
}
@@ -681,12 +716,6 @@ iwl_mld_set_link_sel_data(struct iwl_mld *mld,
u16 max_grade = 0;
unsigned long link_id;
- /*
- * TODO: don't select links that weren't discovered in the last scan
- * This requires mac80211 (or cfg80211) changes to forward/track when
- * a BSS was last updated. cfg80211 already tracks this information but
- * it is not exposed within the kernel.
- */
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
struct ieee80211_bss_conf *link_conf =
link_conf_dereference_protected(vif, link_id);
@@ -731,7 +760,7 @@ iwl_mld_get_min_chan_load_thresh(struct ieee80211_chanctx_conf *chanctx)
return 10;
}
-VISIBLE_IF_IWLWIFI_KUNIT bool
+static bool
iwl_mld_channel_load_allows_emlsr(struct iwl_mld *mld,
struct ieee80211_vif *vif,
const struct iwl_mld_link_sel_data *a,
@@ -772,8 +801,8 @@ iwl_mld_channel_load_allows_emlsr(struct iwl_mld *mld,
if (a->chandef->width <= b->chandef->width)
return true;
- bw_a = nl80211_chan_width_to_mhz(a->chandef->width);
- bw_b = nl80211_chan_width_to_mhz(b->chandef->width);
+ bw_a = cfg80211_chandef_get_width(a->chandef);
+ bw_b = cfg80211_chandef_get_width(b->chandef);
ratio = bw_a / bw_b;
switch (ratio) {
@@ -788,10 +817,9 @@ iwl_mld_channel_load_allows_emlsr(struct iwl_mld *mld,
return false;
}
-EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_channel_load_allows_emlsr);
-static bool
-iwl_mld_valid_emlsr_pair(struct ieee80211_vif *vif,
+VISIBLE_IF_IWLWIFI_KUNIT u32
+iwl_mld_emlsr_pair_state(struct ieee80211_vif *vif,
struct iwl_mld_link_sel_data *a,
struct iwl_mld_link_sel_data *b)
{
@@ -800,29 +828,52 @@ iwl_mld_valid_emlsr_pair(struct ieee80211_vif *vif,
u32 reason_mask = 0;
/* Per-link considerations */
- if (iwl_mld_emlsr_disallowed_with_link(mld, vif, a, true) ||
- iwl_mld_emlsr_disallowed_with_link(mld, vif, b, false))
- return false;
-
- if (a->chandef->chan->band == b->chandef->chan->band)
- reason_mask |= IWL_MLD_EMLSR_EXIT_EQUAL_BAND;
+ reason_mask = iwl_mld_emlsr_disallowed_with_link(mld, vif, a, true);
+ if (reason_mask)
+ return reason_mask;
+
+ reason_mask = iwl_mld_emlsr_disallowed_with_link(mld, vif, b, false);
+ if (reason_mask)
+ return reason_mask;
+
+ if (a->chandef->chan->band == b->chandef->chan->band) {
+ const struct cfg80211_chan_def *c_low = a->chandef;
+ const struct cfg80211_chan_def *c_high = b->chandef;
+ u32 c_low_upper_edge, c_high_lower_edge;
+
+ if (c_low->chan->center_freq > c_high->chan->center_freq)
+ swap(c_low, c_high);
+
+ c_low_upper_edge = c_low->chan->center_freq +
+ cfg80211_chandef_get_width(c_low) / 2;
+ c_high_lower_edge = c_high->chan->center_freq -
+ cfg80211_chandef_get_width(c_high) / 2;
+
+ if (a->chandef->chan->band == NL80211_BAND_5GHZ &&
+ c_low_upper_edge <= 5330 && c_high_lower_edge >= 5490) {
+ /* This case is fine - HW/FW can deal with it, there's
+ * enough separation between the two channels.
+ */
+ } else {
+ reason_mask |= IWL_MLD_EMLSR_EXIT_EQUAL_BAND;
+ }
+ }
if (!iwl_mld_channel_load_allows_emlsr(mld, vif, a, b))
reason_mask |= IWL_MLD_EMLSR_EXIT_CHAN_LOAD;
if (reason_mask) {
- IWL_DEBUG_INFO(mld,
- "Links %d and %d are not a valid pair for EMLSR\n",
- a->link_id, b->link_id);
- IWL_DEBUG_INFO(mld,
- "Links bandwidth are: %d and %d\n",
- nl80211_chan_width_to_mhz(a->chandef->width),
- nl80211_chan_width_to_mhz(b->chandef->width));
+ IWL_DEBUG_EHT(mld,
+ "Links %d and %d are not a valid pair for EMLSR\n",
+ a->link_id, b->link_id);
+ IWL_DEBUG_EHT(mld, "Links bandwidth are: %d and %d\n",
+ nl80211_chan_width_to_mhz(a->chandef->width),
+ nl80211_chan_width_to_mhz(b->chandef->width));
iwl_mld_print_emlsr_exit(mld, reason_mask);
- return false;
}
- return true;
+ return reason_mask;
}
+EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_emlsr_pair_state);
/* Calculation is done with fixed-point with a scaling factor of 1/256 */
#define SCALE_FACTOR 256
@@ -850,7 +901,7 @@ unsigned int iwl_mld_get_emlsr_grade(struct iwl_mld *mld,
*primary_id = a->link_id;
- if (!iwl_mld_valid_emlsr_pair(vif, a, b))
+ if (iwl_mld_emlsr_pair_state(vif, a, b))
return 0;
primary_conf = wiphy_dereference(wiphy, vif->link_conf[*primary_id]);
@@ -892,8 +943,11 @@ static void _iwl_mld_select_links(struct iwl_mld *mld,
n_data = iwl_mld_set_link_sel_data(mld, vif, data, usable_links,
&best_idx);
- if (WARN(!n_data, "Couldn't find a valid grade for any link!\n"))
+ if (!n_data) {
+ IWL_DEBUG_EHT(mld,
+ "Couldn't find a valid grade for any link!\n");
return;
+ }
/* Default to selecting the single best link */
best_link = &data[best_idx];
@@ -931,8 +985,8 @@ static void _iwl_mld_select_links(struct iwl_mld *mld,
}
set_active:
- IWL_DEBUG_INFO(mld, "Link selection result: 0x%x. Primary = %d\n",
- new_active, new_primary);
+ IWL_DEBUG_EHT(mld, "Link selection result: 0x%x. Primary = %d\n",
+ new_active, new_primary);
mld_vif->emlsr.selected_primary = new_primary;
mld_vif->emlsr.selected_links = new_active;
@@ -965,6 +1019,9 @@ static void iwl_mld_emlsr_check_bt_iter(void *_data, u8 *mac,
struct ieee80211_bss_conf *link;
unsigned int link_id;
+ if (!iwl_mld_vif_has_emlsr_cap(vif))
+ return;
+
if (!mld->bt_is_active) {
iwl_mld_retry_emlsr(mld, vif);
return;
@@ -1068,9 +1125,75 @@ void iwl_mld_retry_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif)
{
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
- if (!iwl_mld_vif_has_emlsr_cap(vif) || iwl_mld_emlsr_active(vif) ||
- mld_vif->emlsr.blocked_reasons)
+ if (!IWL_MLD_AUTO_EML_ENABLE || !iwl_mld_vif_has_emlsr_cap(vif) ||
+ iwl_mld_emlsr_active(vif) || mld_vif->emlsr.blocked_reasons)
return;
iwl_mld_int_mlo_scan(mld, vif);
}
+
+static void iwl_mld_ignore_tpt_iter(void *data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
+ struct iwl_mld *mld = mld_vif->mld;
+ struct iwl_mld_sta *mld_sta;
+ bool *start = (void *)data;
+
+ /* check_tpt_wk is only used when TPT block isn't set */
+ if (mld_vif->emlsr.blocked_reasons & IWL_MLD_EMLSR_BLOCKED_TPT ||
+ !IWL_MLD_AUTO_EML_ENABLE || !mld_vif->ap_sta)
+ return;
+
+ mld_sta = iwl_mld_sta_from_mac80211(mld_vif->ap_sta);
+
+ /* We only count for the AP sta in a MLO connection */
+ if (!mld_sta->mpdu_counters)
+ return;
+
+ if (*start) {
+ wiphy_delayed_work_cancel(mld_vif->mld->wiphy,
+ &mld_vif->emlsr.check_tpt_wk);
+ IWL_DEBUG_EHT(mld, "TPT check disabled\n");
+ return;
+ }
+
+ /* Clear the counters so we start from the beginning */
+ for (int q = 0; q < mld->trans->info.num_rxqs; q++) {
+ struct iwl_mld_per_q_mpdu_counter *queue_counter =
+ &mld_sta->mpdu_counters[q];
+
+ spin_lock_bh(&queue_counter->lock);
+
+ memset(queue_counter->per_link, 0,
+ sizeof(queue_counter->per_link));
+
+ spin_unlock_bh(&queue_counter->lock);
+ }
+
+ /* Schedule the check in 5 seconds */
+ wiphy_delayed_work_queue(mld_vif->mld->wiphy,
+ &mld_vif->emlsr.check_tpt_wk,
+ round_jiffies_relative(IWL_MLD_TPT_COUNT_WINDOW));
+ IWL_DEBUG_EHT(mld, "TPT check enabled\n");
+}
+
+void iwl_mld_start_ignoring_tpt_updates(struct iwl_mld *mld)
+{
+ bool start = true;
+
+ ieee80211_iterate_active_interfaces_mtx(mld->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mld_ignore_tpt_iter,
+ &start);
+}
+
+void iwl_mld_stop_ignoring_tpt_updates(struct iwl_mld *mld)
+{
+ bool start = false;
+
+ ieee80211_iterate_active_interfaces_mtx(mld->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mld_ignore_tpt_iter,
+ &start);
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.h b/drivers/net/wireless/intel/iwlwifi/mld/mlo.h
index 4fb1fdbe3df9..d936589fe39d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.h
@@ -37,7 +37,7 @@ static inline bool iwl_mld_vif_has_emlsr_cap(struct ieee80211_vif *vif)
return ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION &&
ieee80211_vif_is_mld(vif) &&
vif->cfg.eml_cap & IEEE80211_EML_CAP_EMLSR_SUPP &&
- !CSR_HW_RFID_IS_CDB(mld_vif->mld->trans->hw_rf_id);
+ !CSR_HW_RFID_IS_CDB(mld_vif->mld->trans->info.hw_rf_id);
}
static inline int
@@ -157,11 +157,15 @@ struct iwl_mld_link_sel_data {
u16 grade;
};
+void iwl_mld_emlsr_block_tmp_non_bss(struct iwl_mld *mld);
+
#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
-bool iwl_mld_channel_load_allows_emlsr(struct iwl_mld *mld,
- struct ieee80211_vif *vif,
- const struct iwl_mld_link_sel_data *a,
- const struct iwl_mld_link_sel_data *b);
+u32 iwl_mld_emlsr_pair_state(struct ieee80211_vif *vif,
+ struct iwl_mld_link_sel_data *a,
+ struct iwl_mld_link_sel_data *b);
#endif
+void iwl_mld_start_ignoring_tpt_updates(struct iwl_mld *mld);
+void iwl_mld_stop_ignoring_tpt_updates(struct iwl_mld *mld);
+
#endif /* __iwl_mld_mlo_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/notif.c b/drivers/net/wireless/intel/iwlwifi/mld/notif.c
index fc18cba8aaa8..4cf3920b005f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/notif.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/notif.c
@@ -78,13 +78,6 @@ static bool iwl_mld_cancel_##name##_notif(struct iwl_mld *mld, \
u8: (notif)->id_member); \
}
-static bool iwl_mld_always_cancel(struct iwl_mld *mld,
- struct iwl_rx_packet *pkt,
- u32 obj_id)
-{
- return true;
-}
-
/* Currently only defined for the RX_HANDLER_SIZES options. Use this for
* notifications that belong to a specific object, and that should be
* canceled when the object is removed
@@ -183,47 +176,6 @@ static void iwl_mld_handle_mu_mimo_grp_notif(struct iwl_mld *mld,
}
static void
-iwl_mld_handle_stored_beacon_notif(struct iwl_mld *mld,
- struct iwl_rx_packet *pkt)
-{
- unsigned int pkt_len = iwl_rx_packet_payload_len(pkt);
- struct iwl_stored_beacon_notif *sb = (void *)pkt->data;
- struct ieee80211_rx_status rx_status = {};
- struct sk_buff *skb;
- u32 size = le32_to_cpu(sb->common.byte_count);
-
- if (size == 0)
- return;
-
- if (pkt_len < struct_size(sb, data, size))
- return;
-
- skb = alloc_skb(size, GFP_ATOMIC);
- if (!skb) {
- IWL_ERR(mld, "alloc_skb failed\n");
- return;
- }
-
- /* update rx_status according to the notification's metadata */
- rx_status.mactime = le64_to_cpu(sb->common.tsf);
- /* TSF as indicated by the firmware is at INA time */
- rx_status.flag |= RX_FLAG_MACTIME_PLCP_START;
- rx_status.device_timestamp = le32_to_cpu(sb->common.system_time);
- rx_status.band =
- iwl_mld_phy_band_to_nl80211(le16_to_cpu(sb->common.band));
- rx_status.freq =
- ieee80211_channel_to_frequency(le16_to_cpu(sb->common.channel),
- rx_status.band);
-
- /* copy the data */
- skb_put_data(skb, sb->data, size);
- memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
-
- /* pass it as regular rx to mac80211 */
- ieee80211_rx_napi(mld->hw, NULL, skb, NULL);
-}
-
-static void
iwl_mld_handle_channel_switch_start_notif(struct iwl_mld *mld,
struct iwl_rx_packet *pkt)
{
@@ -336,6 +288,8 @@ CMD_VERSIONS(scan_complete_notif,
CMD_VER_ENTRY(1, iwl_umac_scan_complete))
CMD_VERSIONS(scan_iter_complete_notif,
CMD_VER_ENTRY(2, iwl_umac_scan_iter_complete_notif))
+CMD_VERSIONS(channel_survey_notif,
+ CMD_VER_ENTRY(1, iwl_umac_scan_channel_survey_notif))
CMD_VERSIONS(mfuart_notif,
CMD_VER_ENTRY(2, iwl_mfuart_load_notif))
CMD_VERSIONS(update_mcc,
@@ -345,12 +299,15 @@ CMD_VERSIONS(session_prot_notif,
CMD_VERSIONS(missed_beacon_notif,
CMD_VER_ENTRY(5, iwl_missed_beacons_notif))
CMD_VERSIONS(tx_resp_notif,
- CMD_VER_ENTRY(8, iwl_tx_resp))
+ CMD_VER_ENTRY(8, iwl_tx_resp)
+ CMD_VER_ENTRY(9, iwl_tx_resp))
CMD_VERSIONS(compressed_ba_notif,
CMD_VER_ENTRY(5, iwl_compressed_ba_notif)
- CMD_VER_ENTRY(6, iwl_compressed_ba_notif))
+ CMD_VER_ENTRY(6, iwl_compressed_ba_notif)
+ CMD_VER_ENTRY(7, iwl_compressed_ba_notif))
CMD_VERSIONS(tlc_notif,
- CMD_VER_ENTRY(3, iwl_tlc_update_notif))
+ CMD_VER_ENTRY(3, iwl_tlc_update_notif)
+ CMD_VER_ENTRY(4, iwl_tlc_update_notif))
CMD_VERSIONS(mu_mimo_grp_notif,
CMD_VER_ENTRY(1, iwl_mu_group_mgmt_notif))
CMD_VERSIONS(channel_switch_start_notif,
@@ -361,8 +318,6 @@ CMD_VERSIONS(ct_kill_notif,
CMD_VER_ENTRY(2, ct_kill_notif))
CMD_VERSIONS(temp_notif,
CMD_VER_ENTRY(2, iwl_dts_measurement_notif))
-CMD_VERSIONS(stored_beacon_notif,
- CMD_VER_ENTRY(4, iwl_stored_beacon_notif))
CMD_VERSIONS(roc_notif,
CMD_VER_ENTRY(1, iwl_roc_notif))
CMD_VERSIONS(probe_resp_data_notif,
@@ -378,7 +333,7 @@ CMD_VERSIONS(bt_coex_notif,
CMD_VERSIONS(beacon_notification,
CMD_VER_ENTRY(6, iwl_extended_beacon_notif))
CMD_VERSIONS(emlsr_mode_notif,
- CMD_VER_ENTRY(1, iwl_esr_mode_notif))
+ CMD_VER_ENTRY(2, iwl_esr_mode_notif))
CMD_VERSIONS(emlsr_trans_fail_notif,
CMD_VER_ENTRY(1, iwl_esr_trans_fail_notif))
CMD_VERSIONS(uapsd_misbehaving_ap_notif,
@@ -387,9 +342,8 @@ CMD_VERSIONS(time_msmt_notif,
CMD_VER_ENTRY(1, iwl_time_msmt_notify))
CMD_VERSIONS(time_sync_confirm_notif,
CMD_VER_ENTRY(1, iwl_time_msmt_cfm_notify))
-CMD_VERSIONS(omi_status_notif,
- CMD_VER_ENTRY(1, iwl_omi_send_status_notif))
-CMD_VERSIONS(ftm_resp_notif, CMD_VER_ENTRY(9, iwl_tof_range_rsp_ntfy))
+CMD_VERSIONS(ftm_resp_notif, CMD_VER_ENTRY(10, iwl_tof_range_rsp_ntfy))
+CMD_VERSIONS(beacon_filter_notif, CMD_VER_ENTRY(2, iwl_beacon_filter_notif))
DEFINE_SIMPLE_CANCELLATION(session_prot, iwl_session_prot_notif, mac_link_id)
DEFINE_SIMPLE_CANCELLATION(tlc, iwl_tlc_update_notif, sta_id)
@@ -405,8 +359,8 @@ DEFINE_SIMPLE_CANCELLATION(probe_resp_data, iwl_probe_resp_data_notif,
mac_id)
DEFINE_SIMPLE_CANCELLATION(uapsd_misbehaving_ap, iwl_uapsd_misbehaving_ap_notif,
mac_id)
-#define iwl_mld_cancel_omi_status_notif iwl_mld_always_cancel
DEFINE_SIMPLE_CANCELLATION(ftm_resp, iwl_tof_range_rsp_ntfy, request_id)
+DEFINE_SIMPLE_CANCELLATION(beacon_filter, iwl_beacon_filter_notif, link_id)
/**
* DOC: Handlers for fw notifications
@@ -451,6 +405,10 @@ const struct iwl_rx_handler iwl_mld_rx_handlers[] = {
RX_HANDLER_NO_VAL(LEGACY_GROUP, MATCH_FOUND_NOTIFICATION,
match_found_notif, RX_HANDLER_SYNC)
+ RX_HANDLER_NO_OBJECT(SCAN_GROUP, CHANNEL_SURVEY_NOTIF,
+ channel_survey_notif,
+ RX_HANDLER_ASYNC)
+
RX_HANDLER_NO_OBJECT(STATISTICS_GROUP, STATISTICS_OPER_NOTIF,
stats_oper_notif, RX_HANDLER_ASYNC)
RX_HANDLER_NO_OBJECT(STATISTICS_GROUP, STATISTICS_OPER_PART1_NOTIF,
@@ -473,8 +431,6 @@ const struct iwl_rx_handler iwl_mld_rx_handlers[] = {
RX_HANDLER_OF_ROC(MAC_CONF_GROUP, ROC_NOTIF, roc_notif)
RX_HANDLER_NO_OBJECT(DATA_PATH_GROUP, MU_GROUP_MGMT_NOTIF,
mu_mimo_grp_notif, RX_HANDLER_SYNC)
- RX_HANDLER_NO_OBJECT(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF,
- stored_beacon_notif, RX_HANDLER_SYNC)
RX_HANDLER_OF_VIF(MAC_CONF_GROUP, PROBE_RESPONSE_DATA_NOTIF,
probe_resp_data_notif)
RX_HANDLER_NO_OBJECT(PHY_OPS_GROUP, CT_KILL_NOTIFICATION,
@@ -499,8 +455,8 @@ const struct iwl_rx_handler iwl_mld_rx_handlers[] = {
RX_HANDLER_NO_OBJECT(LEGACY_GROUP,
WNM_80211V_TIMING_MEASUREMENT_CONFIRM_NOTIFICATION,
time_sync_confirm_notif, RX_HANDLER_ASYNC)
- RX_HANDLER_OF_LINK(DATA_PATH_GROUP, OMI_SEND_STATUS_NOTIF,
- omi_status_notif)
+ RX_HANDLER_OF_LINK(DATA_PATH_GROUP, BEACON_FILTER_IN_NOTIF,
+ beacon_filter_notif)
RX_HANDLER_OF_FTM_REQ(LOCATION_GROUP, TOF_RANGE_RESPONSE_NOTIF,
ftm_resp_notif)
};
@@ -633,8 +589,8 @@ void iwl_mld_rx(struct iwl_op_mode *op_mode, struct napi_struct *napi,
else if (unlikely(cmd_id == WIDE_ID(DATA_PATH_GROUP,
RX_QUEUES_NOTIFICATION)))
iwl_mld_handle_rx_queues_sync_notif(mld, napi, pkt, 0);
- else if (cmd_id == WIDE_ID(DATA_PATH_GROUP, RX_NO_DATA_NOTIF))
- iwl_mld_rx_monitor_no_data(mld, napi, pkt, 0);
+ else if (cmd_id == WIDE_ID(DATA_PATH_GROUP, PHY_AIR_SNIFFER_NOTIF))
+ iwl_mld_handle_phy_air_sniffer_notif(mld, napi, pkt);
else
iwl_mld_rx_notif(mld, rxb, pkt);
}
@@ -646,7 +602,7 @@ void iwl_mld_rx_rss(struct iwl_op_mode *op_mode, struct napi_struct *napi,
struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
u16 cmd_id = WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd);
- if (unlikely(queue >= mld->trans->num_rx_queues))
+ if (unlikely(queue >= mld->trans->info.num_rxqs))
return;
if (likely(cmd_id == WIDE_ID(LEGACY_GROUP, REPLY_RX_MPDU_CMD)))
@@ -707,10 +663,14 @@ void iwl_mld_async_handlers_wk(struct wiphy *wiphy, struct wiphy_work *wk)
}
}
-void iwl_mld_purge_async_handlers_list(struct iwl_mld *mld)
+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);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/notif.h b/drivers/net/wireless/intel/iwlwifi/mld/notif.h
index 2eaa1d4e138e..adcdd9dec192 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/notif.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/notif.h
@@ -15,7 +15,7 @@ void iwl_mld_rx_rss(struct iwl_op_mode *op_mode, struct napi_struct *napi,
void iwl_mld_async_handlers_wk(struct wiphy *wiphy, struct wiphy_work *wk);
-void iwl_mld_purge_async_handlers_list(struct iwl_mld *mld);
+void iwl_mld_cancel_async_notifications(struct iwl_mld *mld);
enum iwl_mld_object_type {
IWL_MLD_OBJECT_TYPE_NONE,
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/phy.c b/drivers/net/wireless/intel/iwlwifi/mld/phy.c
index 2fbc8090088b..1d93fb9e4dbf 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/phy.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/phy.c
@@ -50,6 +50,9 @@ static void iwl_mld_chanctx_usage_iter(void *_data, u8 *mac,
if (rcu_access_pointer(link_conf->chanctx_conf) != data->ctx)
continue;
+ if (vif->type == NL80211_IFTYPE_AP && link_conf->ftm_responder)
+ data->use_def = true;
+
if (iwl_mld_chanctx_fils_enabled(vif, data->ctx))
data->use_def = true;
}
@@ -153,3 +156,43 @@ int iwl_mld_phy_fw_action(struct iwl_mld *mld,
return ret;
}
+
+static u32 iwl_mld_get_phy_config(struct iwl_mld *mld)
+{
+ u32 phy_config = ~(FW_PHY_CFG_TX_CHAIN |
+ FW_PHY_CFG_RX_CHAIN);
+ u32 valid_rx_ant = iwl_mld_get_valid_rx_ant(mld);
+ u32 valid_tx_ant = iwl_mld_get_valid_tx_ant(mld);
+
+ phy_config |= valid_tx_ant << FW_PHY_CFG_TX_CHAIN_POS |
+ valid_rx_ant << FW_PHY_CFG_RX_CHAIN_POS;
+
+ return mld->fw->phy_config & phy_config;
+}
+
+int iwl_mld_send_phy_cfg_cmd(struct iwl_mld *mld)
+{
+ const struct iwl_tlv_calib_ctrl *default_calib =
+ &mld->fw->default_calib[IWL_UCODE_REGULAR];
+ struct iwl_phy_cfg_cmd_v3 cmd = {
+ .phy_cfg = cpu_to_le32(iwl_mld_get_phy_config(mld)),
+ .calib_control.event_trigger = default_calib->event_trigger,
+ .calib_control.flow_trigger = default_calib->flow_trigger,
+ .phy_specific_cfg = mld->fwrt.phy_filters,
+ };
+
+ IWL_DEBUG_INFO(mld, "Sending Phy CFG command: 0x%x\n", cmd.phy_cfg);
+
+ return iwl_mld_send_cmd_pdu(mld, PHY_CONFIGURATION_CMD, &cmd);
+}
+
+void iwl_mld_update_phy_chandef(struct iwl_mld *mld,
+ struct ieee80211_chanctx_conf *ctx)
+{
+ struct iwl_mld_phy *phy = iwl_mld_phy_from_mac80211(ctx);
+ struct cfg80211_chan_def *chandef =
+ iwl_mld_get_chandef_from_chanctx(mld, ctx);
+
+ phy->chandef = *chandef;
+ iwl_mld_phy_fw_action(mld, ctx, FW_CTXT_ACTION_MODIFY);
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/phy.h b/drivers/net/wireless/intel/iwlwifi/mld/phy.h
index 2212a89321b7..0deaf179f07c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/phy.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/phy.h
@@ -52,4 +52,9 @@ iwl_mld_get_chandef_from_chanctx(struct iwl_mld *mld,
struct ieee80211_chanctx_conf *ctx);
u8 iwl_mld_get_fw_ctrl_pos(const struct cfg80211_chan_def *chandef);
+int iwl_mld_send_phy_cfg_cmd(struct iwl_mld *mld);
+
+void iwl_mld_update_phy_chandef(struct iwl_mld *mld,
+ struct ieee80211_chanctx_conf *ctx);
+
#endif /* __iwl_mld_phy_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/power.c b/drivers/net/wireless/intel/iwlwifi/mld/power.c
index 2f16c174b57e..f664b277adf7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/power.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/power.c
@@ -253,6 +253,9 @@ static void iwl_mld_power_build_cmd(struct iwl_mld *mld,
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
+ if (iwl_fw_lookup_cmd_ver(mld->fw, MAC_PM_POWER_TABLE, 0) >= 2)
+ cmd->flags |= cpu_to_le16(POWER_FLAGS_ENABLE_SMPS_MSK);
+
/* firmware supports LPRX for beacons at rate 1 Mbps or 6 Mbps only */
if (link_conf->beacon_rate &&
(link_conf->beacon_rate->bitrate == 10 ||
@@ -374,23 +377,15 @@ int iwl_mld_set_tx_power(struct iwl_mld *mld,
u16 u_tx_power = tx_power == IWL_DEFAULT_MAX_TX_POWER ?
IWL_DEV_MAX_TX_POWER : 8 * tx_power;
struct iwl_dev_tx_power_cmd cmd = {
- /* Those fields sit on the same place for v9 and v10 */
.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_LINK),
.common.pwr_restriction = cpu_to_le16(u_tx_power),
};
- u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id,
- IWL_FW_CMD_VER_UNKNOWN);
- int len = sizeof(cmd.common);
+ int len = sizeof(cmd.common) + sizeof(cmd.v10);
if (WARN_ON(!mld_link))
return -ENODEV;
cmd.common.link_id = cpu_to_le32(mld_link->fw_id);
- if (cmd_ver == 10)
- len += sizeof(cmd.v10);
- else if (cmd_ver == 9)
- len += sizeof(cmd.v9);
-
return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, len);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/ptp.c b/drivers/net/wireless/intel/iwlwifi/mld/ptp.c
index d5c3f853d96c..231920425c06 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/ptp.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/ptp.c
@@ -21,7 +21,7 @@
static int iwl_mld_get_systime(struct iwl_mld *mld, u32 *gp2)
{
- *gp2 = iwl_read_prph(mld->trans, mld->trans->cfg->gp2_reg_addr);
+ *gp2 = iwl_read_prph(mld->trans, mld->trans->mac_cfg->base->gp2_reg_addr);
if (*gp2 == 0x5a5a5a5a)
return -EINVAL;
@@ -121,6 +121,12 @@ static int iwl_mld_ptp_gettime(struct ptp_clock_info *ptp,
return 0;
}
+static int iwl_mld_ptp_settime(struct ptp_clock_info *ptp,
+ const struct timespec64 *ts)
+{
+ return -EOPNOTSUPP;
+}
+
static int iwl_mld_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{
struct iwl_mld *mld = container_of(ptp, struct iwl_mld,
@@ -279,6 +285,7 @@ void iwl_mld_ptp_init(struct iwl_mld *mld)
mld->ptp_data.ptp_clock_info.owner = THIS_MODULE;
mld->ptp_data.ptp_clock_info.gettime64 = iwl_mld_ptp_gettime;
+ mld->ptp_data.ptp_clock_info.settime64 = iwl_mld_ptp_settime;
mld->ptp_data.ptp_clock_info.max_adj = 0x7fffffff;
mld->ptp_data.ptp_clock_info.adjtime = iwl_mld_ptp_adjtime;
mld->ptp_data.ptp_clock_info.adjfine = iwl_mld_ptp_adjfine;
@@ -299,18 +306,18 @@ void iwl_mld_ptp_init(struct iwl_mld *mld)
PTR_ERR(mld->ptp_data.ptp_clock));
mld->ptp_data.ptp_clock = NULL;
} else {
- IWL_INFO(mld, "Registered PHC clock: %s, with index: %d\n",
- mld->ptp_data.ptp_clock_info.name,
- ptp_clock_index(mld->ptp_data.ptp_clock));
+ IWL_DEBUG_INFO(mld, "Registered PHC clock: %s, with index: %d\n",
+ mld->ptp_data.ptp_clock_info.name,
+ ptp_clock_index(mld->ptp_data.ptp_clock));
}
}
void iwl_mld_ptp_remove(struct iwl_mld *mld)
{
if (mld->ptp_data.ptp_clock) {
- IWL_INFO(mld, "Unregistering PHC clock: %s, with index: %d\n",
- mld->ptp_data.ptp_clock_info.name,
- ptp_clock_index(mld->ptp_data.ptp_clock));
+ IWL_DEBUG_INFO(mld, "Unregistering PHC clock: %s, with index: %d\n",
+ mld->ptp_data.ptp_clock_info.name,
+ ptp_clock_index(mld->ptp_data.ptp_clock));
ptp_clock_unregister(mld->ptp_data.ptp_clock);
mld->ptp_data.ptp_clock = NULL;
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c
index a75af8c1e8ab..40571125b3ab 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c
@@ -63,48 +63,25 @@ void iwl_mld_get_bios_tables(struct iwl_mld *mld)
/* we don't fail if the table is not available */
}
- ret = iwl_uefi_get_uats_table(mld->trans, &mld->fwrt);
- if (ret)
- IWL_DEBUG_RADIO(mld, "failed to read UATS table (%d)\n", ret);
+ iwl_uefi_get_uats_table(mld->trans, &mld->fwrt);
+
+ iwl_bios_get_phy_filters(&mld->fwrt);
}
static int iwl_mld_geo_sar_init(struct iwl_mld *mld)
{
u32 cmd_id = WIDE_ID(PHY_OPS_GROUP, PER_CHAIN_LIMIT_OFFSET_CMD);
- union iwl_geo_tx_power_profiles_cmd cmd;
- u16 len;
- u32 n_bands;
- __le32 sk = cpu_to_le32(0);
- int ret;
- u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id,
- IWL_FW_CMD_VER_UNKNOWN);
-
- BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, ops) !=
- offsetof(struct iwl_geo_tx_power_profiles_cmd_v5, ops));
-
- cmd.v4.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES);
-
/* Only set to South Korea if the table revision is 1 */
- if (mld->fwrt.geo_rev == 1)
- sk = cpu_to_le32(1);
-
- if (cmd_ver == 5) {
- len = sizeof(cmd.v5);
- n_bands = ARRAY_SIZE(cmd.v5.table[0]);
- cmd.v5.table_revision = sk;
- } else if (cmd_ver == 4) {
- len = sizeof(cmd.v4);
- n_bands = ARRAY_SIZE(cmd.v4.table[0]);
- cmd.v4.table_revision = sk;
- } else {
- return -EOPNOTSUPP;
- }
+ __le32 sk = cpu_to_le32(mld->fwrt.geo_rev == 1 ? 1 : 0);
+ union iwl_geo_tx_power_profiles_cmd cmd = {
+ .v5.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES),
+ .v5.table_revision = sk,
+ };
+ int ret;
- BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, table) !=
- offsetof(struct iwl_geo_tx_power_profiles_cmd_v5, table));
- /* the table is at the same position for all versions, so set use v4 */
- ret = iwl_sar_geo_fill_table(&mld->fwrt, &cmd.v4.table[0][0],
- n_bands, BIOS_GEO_MAX_PROFILE_NUM);
+ ret = iwl_sar_geo_fill_table(&mld->fwrt, &cmd.v5.table[0][0],
+ ARRAY_SIZE(cmd.v5.table[0]),
+ BIOS_GEO_MAX_PROFILE_NUM);
/* It is a valid scenario to not support SAR, or miss wgds table,
* but in that case there is no need to send the command.
@@ -112,7 +89,7 @@ static int iwl_mld_geo_sar_init(struct iwl_mld *mld)
if (ret)
return 0;
- return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, len);
+ return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, sizeof(cmd.v5));
}
int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)
@@ -120,37 +97,20 @@ int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)
u32 cmd_id = REDUCE_TX_POWER_CMD;
struct iwl_dev_tx_power_cmd cmd = {
.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS),
+ .v10.flags = cpu_to_le32(mld->fwrt.reduced_power_flags),
};
- __le16 *per_chain;
int ret;
- u16 len = sizeof(cmd.common);
- u32 n_subbands;
- u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id,
- IWL_FW_CMD_VER_UNKNOWN);
-
- if (cmd_ver == 10) {
- len += sizeof(cmd.v10);
- n_subbands = IWL_NUM_SUB_BANDS_V2;
- per_chain = &cmd.v10.per_chain[0][0][0];
- cmd.v10.flags =
- cpu_to_le32(mld->fwrt.reduced_power_flags);
- } else if (cmd_ver == 9) {
- len += sizeof(cmd.v9);
- n_subbands = IWL_NUM_SUB_BANDS_V1;
- per_chain = &cmd.v9.per_chain[0][0];
- } else {
- return -EOPNOTSUPP;
- }
/* TODO: CDB - support IWL_NUM_CHAIN_TABLES_V2 */
- ret = iwl_sar_fill_profile(&mld->fwrt, per_chain,
- IWL_NUM_CHAIN_TABLES,
- n_subbands, prof_a, prof_b);
+ ret = iwl_sar_fill_profile(&mld->fwrt, &cmd.v10.per_chain[0][0][0],
+ IWL_NUM_CHAIN_TABLES, IWL_NUM_SUB_BANDS_V2,
+ prof_a, prof_b);
/* return on error or if the profile is disabled (positive number) */
if (ret)
return ret;
- return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, len);
+ return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd,
+ sizeof(cmd.common) + sizeof(cmd.v10));
}
int iwl_mld_init_sar(struct iwl_mld *mld)
@@ -203,18 +163,32 @@ int iwl_mld_init_sgom(struct iwl_mld *mld)
static int iwl_mld_ppag_send_cmd(struct iwl_mld *mld)
{
- union iwl_ppag_table_cmd cmd = {};
- int ret, len;
+ struct iwl_fw_runtime *fwrt = &mld->fwrt;
+ union iwl_ppag_table_cmd cmd = {
+ .v7.ppag_config_info.table_source = fwrt->ppag_bios_source,
+ .v7.ppag_config_info.table_revision = fwrt->ppag_bios_rev,
+ .v7.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags),
+ };
+ int ret;
- ret = iwl_fill_ppag_table(&mld->fwrt, &cmd, &len);
- /* Not supporting PPAG table is a valid scenario */
- if (ret < 0)
- return 0;
+ IWL_DEBUG_RADIO(fwrt,
+ "PPAG MODE bits going to be sent: %d\n",
+ fwrt->ppag_flags);
+
+ for (int chain = 0; chain < IWL_NUM_CHAIN_LIMITS; chain++) {
+ for (int subband = 0; subband < IWL_NUM_SUB_BANDS_V2; subband++) {
+ cmd.v7.gain[chain][subband] =
+ fwrt->ppag_chains[chain].subbands[subband];
+ IWL_DEBUG_RADIO(fwrt,
+ "PPAG table: chain[%d] band[%d]: gain = %d\n",
+ chain, subband, cmd.v7.gain[chain][subband]);
+ }
+ }
IWL_DEBUG_RADIO(mld, "Sending PER_PLATFORM_ANT_GAIN_CMD\n");
ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(PHY_OPS_GROUP,
PER_PLATFORM_ANT_GAIN_CMD),
- &cmd, len);
+ &cmd, sizeof(cmd.v7));
if (ret < 0)
IWL_ERR(mld, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n",
ret);
@@ -238,34 +212,50 @@ void iwl_mld_configure_lari(struct iwl_mld *mld)
struct iwl_lari_config_change_cmd cmd = {
.config_bitmap = iwl_get_lari_config_bitmap(fwrt),
};
+ bool has_raw_dsm_capa = fw_has_capa(&fwrt->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE);
int ret;
u32 value;
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_11AX_ENABLEMENT, &value);
- if (!ret)
+ if (!ret) {
+ if (!has_raw_dsm_capa)
+ value &= DSM_11AX_ALLOW_BITMAP;
cmd.oem_11ax_allow_bitmap = cpu_to_le32(value);
+ }
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_UNII4_CHAN, &value);
- if (!ret)
- cmd.oem_unii4_allow_bitmap =
- cpu_to_le32(value &= DSM_UNII4_ALLOW_BITMAP);
+ if (!ret) {
+ if (!has_raw_dsm_capa)
+ value &= DSM_UNII4_ALLOW_BITMAP;
+ cmd.oem_unii4_allow_bitmap = cpu_to_le32(value);
+ }
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value);
- if (!ret)
+ if (!ret) {
+ if (!has_raw_dsm_capa)
+ value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V12;
cmd.chan_state_active_bitmap = cpu_to_le32(value);
+ }
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_6E, &value);
if (!ret)
cmd.oem_uhb_allow_bitmap = cpu_to_le32(value);
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_FORCE_DISABLE_CHANNELS, &value);
- if (!ret)
+ if (!ret) {
+ if (!has_raw_dsm_capa)
+ value &= DSM_FORCE_DISABLE_CHANNELS_ALLOWED_BITMAP;
cmd.force_disable_channels_bitmap = cpu_to_le32(value);
+ }
ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENERGY_DETECTION_THRESHOLD,
&value);
- if (!ret)
+ if (!ret) {
+ if (!has_raw_dsm_capa)
+ value &= DSM_EDT_ALLOWED_BITMAP;
cmd.edt_bitmap = cpu_to_le32(value);
+ }
ret = iwl_bios_get_wbem(fwrt, &value);
if (!ret)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/roc.c b/drivers/net/wireless/intel/iwlwifi/mld/roc.c
index b87faca23ceb..4e37a288471e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/roc.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/roc.c
@@ -31,56 +31,96 @@ iwl_mld_vif_iter_emlsr_block_roc(void *data, u8 *mac, struct ieee80211_vif *vif)
*result = ret;
}
+struct iwl_mld_roc_iter_data {
+ enum iwl_roc_activity activity;
+ struct ieee80211_vif *vif;
+ bool found;
+};
+
+static void iwl_mld_find_roc_vif_iter(void *data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
+ struct iwl_mld_roc_iter_data *roc_data = data;
+
+ if (mld_vif->roc_activity != roc_data->activity)
+ return;
+
+ /* The FW supports one ROC of each type simultaneously */
+ if (WARN_ON(roc_data->found)) {
+ roc_data->vif = NULL;
+ return;
+ }
+
+ roc_data->found = true;
+ roc_data->vif = vif;
+}
+
+static struct ieee80211_vif *
+iwl_mld_find_roc_vif(struct iwl_mld *mld, enum iwl_roc_activity activity)
+{
+ struct iwl_mld_roc_iter_data roc_data = {
+ .activity = activity,
+ .found = false,
+ };
+
+ ieee80211_iterate_active_interfaces_mtx(mld->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mld_find_roc_vif_iter,
+ &roc_data);
+
+ return roc_data.vif;
+}
+
int iwl_mld_start_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_channel *channel, int duration,
enum ieee80211_roc_type type)
{
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
- struct iwl_mld_int_sta *aux_sta;
+ struct iwl_mld_int_sta *aux_sta = &mld_vif->aux_sta;
struct iwl_roc_req cmd = {
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
};
- u8 ver = iwl_fw_lookup_cmd_ver(mld->fw,
- WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 0);
- u16 cmd_len = ver < 6 ? sizeof(struct iwl_roc_req_v5) : sizeof(cmd);
enum iwl_roc_activity activity;
int ret = 0;
lockdep_assert_wiphy(mld->wiphy);
- ieee80211_iterate_active_interfaces_mtx(mld->hw,
- IEEE80211_IFACE_ITER_NORMAL,
- iwl_mld_vif_iter_emlsr_block_roc,
- &ret);
- if (ret)
- return ret;
-
- /* TODO: task=Hotspot 2.0 */
- if (vif->type != NL80211_IFTYPE_P2P_DEVICE) {
+ if (vif->type != NL80211_IFTYPE_P2P_DEVICE &&
+ vif->type != NL80211_IFTYPE_STATION) {
IWL_ERR(mld, "NOT SUPPORTED: ROC on vif->type %d\n",
vif->type);
return -EOPNOTSUPP;
}
- switch (type) {
- case IEEE80211_ROC_TYPE_NORMAL:
- activity = ROC_ACTIVITY_P2P_DISC;
- break;
- case IEEE80211_ROC_TYPE_MGMT_TX:
- activity = ROC_ACTIVITY_P2P_NEG;
- break;
- default:
- WARN_ONCE(1, "Got an invalid P2P ROC type\n");
- return -EINVAL;
+ if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
+ switch (type) {
+ case IEEE80211_ROC_TYPE_NORMAL:
+ activity = ROC_ACTIVITY_P2P_DISC;
+ break;
+ case IEEE80211_ROC_TYPE_MGMT_TX:
+ activity = ROC_ACTIVITY_P2P_NEG;
+ break;
+ default:
+ WARN_ONCE(1, "Got an invalid P2P ROC type\n");
+ return -EINVAL;
+ }
+ } else {
+ activity = ROC_ACTIVITY_HOTSPOT;
}
- if (WARN_ON(mld_vif->roc_activity != ROC_NUM_ACTIVITIES))
+ /* The FW supports one ROC of each type simultaneously */
+ if (WARN_ON(iwl_mld_find_roc_vif(mld, activity)))
return -EBUSY;
- /* No MLO on P2P device */
- aux_sta = &mld_vif->deflink.aux_sta;
+ ieee80211_iterate_active_interfaces_mtx(mld->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mld_vif_iter_emlsr_block_roc,
+ &ret);
+ if (ret)
+ return ret;
ret = iwl_mld_add_aux_sta(mld, aux_sta);
if (ret)
@@ -91,20 +131,18 @@ int iwl_mld_start_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
cmd.channel_info.channel = cpu_to_le32(channel->hw_value);
cmd.channel_info.band = iwl_mld_nl80211_band_to_fw(channel->band);
cmd.channel_info.width = IWL_PHY_CHANNEL_MODE20;
- /* TODO: task=Hotspot 2.0, revisit those parameters when we add an ROC
- * on the BSS vif
- */
cmd.max_delay = cpu_to_le32(AUX_ROC_MAX_DELAY);
cmd.duration = cpu_to_le32(MSEC_TO_TU(duration));
memcpy(cmd.node_addr, vif->addr, ETH_ALEN);
ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(MAC_CONF_GROUP, ROC_CMD),
- &cmd, cmd_len);
+ &cmd);
if (ret) {
IWL_ERR(mld, "Couldn't send the ROC_CMD\n");
return ret;
}
+
mld_vif->roc_activity = activity;
return 0;
@@ -136,9 +174,9 @@ static void iwl_mld_destroy_roc(struct iwl_mld *mld,
* we can flush the Tx on the queues
*/
- iwl_mld_flush_link_sta_txqs(mld, mld_vif->deflink.aux_sta.sta_id);
+ iwl_mld_flush_link_sta_txqs(mld, mld_vif->aux_sta.sta_id);
- iwl_mld_remove_aux_sta(mld, vif, &vif->bss_conf);
+ iwl_mld_remove_aux_sta(mld, vif);
}
int iwl_mld_cancel_roc(struct ieee80211_hw *hw,
@@ -149,15 +187,12 @@ int iwl_mld_cancel_roc(struct ieee80211_hw *hw,
struct iwl_roc_req cmd = {
.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
};
- u8 ver = iwl_fw_lookup_cmd_ver(mld->fw,
- WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 0);
- u16 cmd_len = ver < 6 ? sizeof(struct iwl_roc_req_v5) : sizeof(cmd);
int ret;
lockdep_assert_wiphy(mld->wiphy);
- /* TODO: task=Hotspot 2.0 */
- if (WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE))
+ if (WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE &&
+ vif->type != NL80211_IFTYPE_STATION))
return -EOPNOTSUPP;
/* No roc activity running it's probably already done */
@@ -167,7 +202,7 @@ int iwl_mld_cancel_roc(struct ieee80211_hw *hw,
cmd.activity = cpu_to_le32(mld_vif->roc_activity);
ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(MAC_CONF_GROUP, ROC_CMD),
- &cmd, cmd_len);
+ &cmd);
if (ret)
IWL_ERR(mld, "Couldn't send the command to cancel the ROC\n");
@@ -192,11 +227,13 @@ void iwl_mld_handle_roc_notif(struct iwl_mld *mld,
{
const struct iwl_roc_notif *notif = (void *)pkt->data;
u32 activity = le32_to_cpu(notif->activity);
- /* TODO: task=Hotspot 2.0 - roc can run on BSS */
- struct ieee80211_vif *vif = mld->p2p_device_vif;
struct iwl_mld_vif *mld_vif;
+ struct ieee80211_vif *vif;
- if (WARN_ON(!vif))
+ vif = iwl_mld_find_roc_vif(mld, activity);
+ if (IWL_FW_CHECK(mld, !vif,
+ "unexpected ROC notif from FW for activity %d\n",
+ activity))
return;
mld_vif = iwl_mld_vif_from_mac80211(vif);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c
index c4f189bcece2..6a76e3fcb581 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c
@@ -18,41 +18,32 @@
/* stores relevant PHY data fields extracted from iwl_rx_mpdu_desc */
struct iwl_mld_rx_phy_data {
- enum iwl_rx_phy_info_type info_type;
- __le32 data0;
- __le32 data1;
- __le32 data2;
- __le32 data3;
- __le32 eht_data4;
- __le32 data5;
- __le16 data4;
+ struct iwl_rx_phy_air_sniffer_ntfy *ntfy;
bool first_subframe;
bool with_data;
- __le32 rx_vec[4];
u32 rate_n_flags;
u32 gp2_on_air_rise;
+ /* phy_info is only valid when we have a frame, i.e. with_data=true */
u16 phy_info;
u8 energy_a, energy_b;
- u8 channel;
};
static void
-iwl_mld_fill_phy_data(struct iwl_rx_mpdu_desc *desc,
- struct iwl_mld_rx_phy_data *phy_data)
+iwl_mld_fill_phy_data_from_mpdu(struct iwl_mld *mld,
+ struct iwl_rx_mpdu_desc *desc,
+ struct iwl_mld_rx_phy_data *phy_data)
{
+ if (unlikely(mld->monitor.phy.valid)) {
+ mld->monitor.phy.used = true;
+ phy_data->ntfy = &mld->monitor.phy.data;
+ }
+
phy_data->phy_info = le16_to_cpu(desc->phy_info);
- phy_data->rate_n_flags = le32_to_cpu(desc->v3.rate_n_flags);
+ phy_data->rate_n_flags = iwl_v3_rate_from_v2_v3(desc->v3.rate_n_flags,
+ mld->fw_rates_ver_3);
phy_data->gp2_on_air_rise = le32_to_cpu(desc->v3.gp2_on_air_rise);
- phy_data->channel = desc->v3.channel;
phy_data->energy_a = desc->v3.energy_a;
phy_data->energy_b = desc->v3.energy_b;
- phy_data->data0 = desc->v3.phy_data0;
- phy_data->data1 = desc->v3.phy_data1;
- phy_data->data2 = desc->v3.phy_data2;
- phy_data->data3 = desc->v3.phy_data3;
- phy_data->data4 = desc->phy_data4;
- phy_data->eht_data4 = desc->phy_eht_data4;
- phy_data->data5 = desc->v3.phy_data5;
phy_data->with_data = true;
}
@@ -143,7 +134,55 @@ void iwl_mld_pass_packet_to_mac80211(struct iwl_mld *mld,
}
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_pass_packet_to_mac80211);
-static void iwl_mld_fill_signal(struct iwl_mld *mld,
+static bool iwl_mld_used_average_energy(struct iwl_mld *mld, int link_id,
+ struct ieee80211_hdr *hdr,
+ struct ieee80211_rx_status *rx_status)
+{
+ struct ieee80211_bss_conf *link_conf;
+ struct iwl_mld_link *mld_link;
+
+ if (unlikely(!hdr || link_id < 0))
+ return false;
+
+ if (likely(!ieee80211_is_beacon(hdr->frame_control)))
+ return false;
+
+ /*
+ * if link ID is >= valid ones then that means the RX
+ * was on the AUX link and no correction is needed
+ */
+ if (link_id >= mld->fw->ucode_capa.num_links)
+ return false;
+
+ /* for the link conf lookup */
+ guard(rcu)();
+
+ link_conf = rcu_dereference(mld->fw_id_to_bss_conf[link_id]);
+ if (!link_conf)
+ return false;
+
+ mld_link = iwl_mld_link_from_mac80211(link_conf);
+ if (!mld_link)
+ return false;
+
+ /*
+ * If we know the link by link ID then the frame was
+ * received for the link, so by filtering it means it
+ * was from the AP the link is connected to.
+ */
+
+ /* skip also in case we don't have it (yet) */
+ if (!mld_link->average_beacon_energy)
+ return false;
+
+ IWL_DEBUG_STATS(mld, "energy override by average %d\n",
+ mld_link->average_beacon_energy);
+ rx_status->signal = -mld_link->average_beacon_energy;
+ return true;
+}
+
+static void iwl_mld_fill_signal(struct iwl_mld *mld, int link_id,
+ struct ieee80211_hdr *hdr,
struct ieee80211_rx_status *rx_status,
struct iwl_mld_rx_phy_data *phy_data)
{
@@ -159,34 +198,29 @@ static void iwl_mld_fill_signal(struct iwl_mld *mld,
IWL_DEBUG_STATS(mld, "energy in A %d B %d, and max %d\n",
energy_a, energy_b, max_energy);
+ if (iwl_mld_used_average_energy(mld, link_id, hdr, rx_status))
+ return;
+
rx_status->signal = max_energy;
- rx_status->chains =
- (rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;
+ rx_status->chains = u32_get_bits(rate_n_flags, RATE_MCS_ANT_AB_MSK);
rx_status->chain_signal[0] = energy_a;
rx_status->chain_signal[1] = energy_b;
}
static void
-iwl_mld_decode_he_phy_ru_alloc(struct iwl_mld_rx_phy_data *phy_data,
- struct ieee80211_radiotap_he *he,
- struct ieee80211_radiotap_he_mu *he_mu,
- struct ieee80211_rx_status *rx_status)
+iwl_mld_he_set_ru_alloc(struct ieee80211_rx_status *rx_status,
+ struct ieee80211_radiotap_he *he,
+ u8 ru_with_p80)
{
- /* Unfortunately, we have to leave the mac80211 data
- * incorrect for the case that we receive an HE-MU
- * transmission and *don't* have the HE phy data (due
- * to the bits being used for TSF). This shouldn't
- * happen though as management frames where we need
- * the TSF/timers are not be transmitted in HE-MU.
- */
- u8 ru = le32_get_bits(phy_data->data1, IWL_RX_PHY_DATA1_HE_RU_ALLOC_MASK);
- u32 rate_n_flags = phy_data->rate_n_flags;
- u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
+ u8 ru = ru_with_p80 >> 1;
+ u8 p80 = ru_with_p80 & 1;
u8 offs = 0;
rx_status->bw = RATE_INFO_BW_HE_RU;
he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN);
+ he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN);
switch (ru) {
case 0 ... 36:
@@ -216,227 +250,262 @@ iwl_mld_decode_he_phy_ru_alloc(struct iwl_mld_rx_phy_data *phy_data,
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
break;
}
+
he->data2 |= le16_encode_bits(offs,
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
- he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN |
- IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN);
- if (phy_data->data1 & cpu_to_le32(IWL_RX_PHY_DATA1_HE_RU_ALLOC_SEC80))
- he->data2 |=
- cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC);
-
-#define CHECK_BW(bw) \
- BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_ ## bw ## MHZ != \
- RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS); \
- BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_ ## bw ## MHZ != \
- RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS)
- CHECK_BW(20);
- CHECK_BW(40);
- CHECK_BW(80);
- CHECK_BW(160);
- if (he_mu)
- he_mu->flags2 |=
- le16_encode_bits(u32_get_bits(rate_n_flags,
- RATE_MCS_CHAN_WIDTH_MSK),
- IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW);
- else if (he_type == RATE_MCS_HE_TYPE_TRIG)
- he->data6 |=
- cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_KNOWN) |
- le16_encode_bits(u32_get_bits(rate_n_flags,
- RATE_MCS_CHAN_WIDTH_MSK),
- IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW);
+ he->data2 |= le16_encode_bits(p80, IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC);
}
+#define RTAP_ENC_HE(src, src_msk, dst_msk) \
+ le16_encode_bits(le32_get_bits(src, src_msk), dst_msk)
+
static void
-iwl_mld_decode_he_mu_ext(struct iwl_mld_rx_phy_data *phy_data,
- struct ieee80211_radiotap_he_mu *he_mu)
+iwl_mld_decode_he_mu(struct iwl_mld_rx_phy_data *phy_data,
+ struct ieee80211_radiotap_he *he,
+ struct ieee80211_radiotap_he_mu *he_mu,
+ struct ieee80211_rx_status *rx_status)
{
- u32 phy_data2 = le32_to_cpu(phy_data->data2);
- u32 phy_data3 = le32_to_cpu(phy_data->data3);
- u16 phy_data4 = le16_to_cpu(phy_data->data4);
u32 rate_n_flags = phy_data->rate_n_flags;
- if (u32_get_bits(phy_data4, IWL_RX_PHY_DATA4_HE_MU_EXT_CH1_CRC_OK)) {
+ he_mu->flags1 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.b,
+ OFDM_RX_FRAME_HE_SIGB_DCM,
+ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM);
+ he_mu->flags1 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.b,
+ OFDM_RX_FRAME_HE_SIGB_MCS,
+ IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS);
+ he_mu->flags2 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.a1,
+ OFDM_RX_FRAME_HE_PRMBL_PUNC_TYPE,
+ IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW);
+ he_mu->flags2 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.a2,
+ OFDM_RX_FRAME_HE_MU_NUM_OF_SIGB_SYM_OR_USER_NUM,
+ IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS);
+ he_mu->flags2 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.b,
+ OFDM_RX_FRAME_HE_MU_SIGB_COMP,
+ IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP);
+
+ if (phy_data->ntfy->flags & IWL_SNIF_FLAG_VALID_RU &&
+ le32_get_bits(phy_data->ntfy->sigs.he.cmn[2],
+ OFDM_RX_FRAME_HE_COMMON_CC1_CRC_OK)) {
he_mu->flags1 |=
cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_RU_KNOWN |
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU_KNOWN);
he_mu->flags1 |=
- le16_encode_bits(u32_get_bits(phy_data4,
- IWL_RX_PHY_DATA4_HE_MU_EXT_CH1_CTR_RU),
- IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU);
-
- he_mu->ru_ch1[0] = u32_get_bits(phy_data2,
- IWL_RX_PHY_DATA2_HE_MU_EXT_CH1_RU0);
- he_mu->ru_ch1[1] = u32_get_bits(phy_data3,
- IWL_RX_PHY_DATA3_HE_MU_EXT_CH1_RU1);
- he_mu->ru_ch1[2] = u32_get_bits(phy_data2,
- IWL_RX_PHY_DATA2_HE_MU_EXT_CH1_RU2);
- he_mu->ru_ch1[3] = u32_get_bits(phy_data3,
- IWL_RX_PHY_DATA3_HE_MU_EXT_CH1_RU3);
+ RTAP_ENC_HE(phy_data->ntfy->sigs.he.cmn[2],
+ OFDM_RX_FRAME_HE_CENTER_RU_CC1,
+ IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU);
+
+ he_mu->ru_ch1[0] = le32_get_bits(phy_data->ntfy->sigs.he.cmn[0],
+ OFDM_RX_FRAME_HE_RU_ALLOC_0_A1);
+ he_mu->ru_ch1[1] = le32_get_bits(phy_data->ntfy->sigs.he.cmn[1],
+ OFDM_RX_FRAME_HE_RU_ALLOC_1_C1);
+ he_mu->ru_ch1[2] = le32_get_bits(phy_data->ntfy->sigs.he.cmn[0],
+ OFDM_RX_FRAME_HE_RU_ALLOC_0_A2);
+ he_mu->ru_ch1[3] = le32_get_bits(phy_data->ntfy->sigs.he.cmn[1],
+ OFDM_RX_FRAME_HE_RU_ALLOC_1_C2);
}
- if (u32_get_bits(phy_data4, IWL_RX_PHY_DATA4_HE_MU_EXT_CH2_CRC_OK) &&
+ if (phy_data->ntfy->flags & IWL_SNIF_FLAG_VALID_RU &&
+ le32_get_bits(phy_data->ntfy->sigs.he.cmn[2],
+ OFDM_RX_FRAME_HE_COMMON_CC2_CRC_OK) &&
(rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) != RATE_MCS_CHAN_WIDTH_20) {
he_mu->flags1 |=
cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_RU_KNOWN |
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_CTR_26T_RU_KNOWN);
he_mu->flags2 |=
- le16_encode_bits(u32_get_bits(phy_data4,
- IWL_RX_PHY_DATA4_HE_MU_EXT_CH2_CTR_RU),
- IEEE80211_RADIOTAP_HE_MU_FLAGS2_CH2_CTR_26T_RU);
-
- he_mu->ru_ch2[0] = u32_get_bits(phy_data2,
- IWL_RX_PHY_DATA2_HE_MU_EXT_CH2_RU0);
- he_mu->ru_ch2[1] = u32_get_bits(phy_data3,
- IWL_RX_PHY_DATA3_HE_MU_EXT_CH2_RU1);
- he_mu->ru_ch2[2] = u32_get_bits(phy_data2,
- IWL_RX_PHY_DATA2_HE_MU_EXT_CH2_RU2);
- he_mu->ru_ch2[3] = u32_get_bits(phy_data3,
- IWL_RX_PHY_DATA3_HE_MU_EXT_CH2_RU3);
+ RTAP_ENC_HE(phy_data->ntfy->sigs.he.cmn[2],
+ OFDM_RX_FRAME_HE_CENTER_RU_CC2,
+ IEEE80211_RADIOTAP_HE_MU_FLAGS2_CH2_CTR_26T_RU);
+
+ he_mu->ru_ch2[0] = le32_get_bits(phy_data->ntfy->sigs.he.cmn[0],
+ OFDM_RX_FRAME_HE_RU_ALLOC_0_B1);
+ he_mu->ru_ch2[1] = le32_get_bits(phy_data->ntfy->sigs.he.cmn[1],
+ OFDM_RX_FRAME_HE_RU_ALLOC_1_D1);
+ he_mu->ru_ch2[2] = le32_get_bits(phy_data->ntfy->sigs.he.cmn[0],
+ OFDM_RX_FRAME_HE_RU_ALLOC_0_B2);
+ he_mu->ru_ch2[3] = le32_get_bits(phy_data->ntfy->sigs.he.cmn[1],
+ OFDM_RX_FRAME_HE_RU_ALLOC_1_D2);
}
+
+#define CHECK_BW(bw) \
+ BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_ ## bw ## MHZ != \
+ RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS)
+ CHECK_BW(20);
+ CHECK_BW(40);
+ CHECK_BW(80);
+ CHECK_BW(160);
+#undef CHECK_BW
+
+ he_mu->flags2 |=
+ le16_encode_bits(u32_get_bits(rate_n_flags, RATE_MCS_CHAN_WIDTH_MSK),
+ IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW);
+
+ iwl_mld_he_set_ru_alloc(rx_status, he,
+ le32_get_bits(phy_data->ntfy->sigs.he.b,
+ OFDM_RX_FRAME_HE_SIGB_STA_RU));
+}
+
+static void
+iwl_mld_decode_he_tb_phy_data(struct iwl_mld_rx_phy_data *phy_data,
+ struct ieee80211_radiotap_he *he,
+ struct ieee80211_rx_status *rx_status)
+{
+ u32 rate_n_flags = phy_data->rate_n_flags;
+ u32 nsts;
+
+ he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN);
+
+ he->data4 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he_tb.a1,
+ OFDM_RX_HE_TRIG_SPATIAL_REUSE_1,
+ IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1);
+ he->data4 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he_tb.a1,
+ OFDM_RX_HE_TRIG_SPATIAL_REUSE_2,
+ IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2);
+ he->data4 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he_tb.a1,
+ OFDM_RX_HE_TRIG_SPATIAL_REUSE_3,
+ IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3);
+ he->data4 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he_tb.a1,
+ OFDM_RX_HE_TRIG_SPATIAL_REUSE_4,
+ IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4);
+ he->data3 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he_tb.a1,
+ OFDM_RX_HE_TRIG_BSS_COLOR,
+ IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR);
+
+#define CHECK_BW(bw) \
+ BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_ ## bw ## MHZ != \
+ RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS)
+ CHECK_BW(20);
+ CHECK_BW(40);
+ CHECK_BW(80);
+ CHECK_BW(160);
+#undef CHECK_BW
+
+ he->data6 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_KNOWN) |
+ le16_encode_bits(u32_get_bits(rate_n_flags, RATE_MCS_CHAN_WIDTH_MSK),
+ IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW);
+
+ if (!(phy_data->ntfy->flags & IWL_SNIF_FLAG_VALID_TB_RX))
+ return;
+
+ he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN);
+ he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN);
+
+ he->data3 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he_tb.tb_rx1,
+ OFDM_UCODE_TRIG_BASE_RX_CODING_EXTRA_SYM,
+ IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG);
+ he->data6 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he_tb.tb_rx1,
+ OFDM_UCODE_TRIG_BASE_RX_DOPPLER,
+ IEEE80211_RADIOTAP_HE_DATA6_DOPPLER);
+ he->data5 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he_tb.tb_rx1,
+ OFDM_UCODE_TRIG_BASE_RX_PRE_FEC_PAD_FACTOR,
+ IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD);
+ he->data5 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he_tb.tb_rx1,
+ OFDM_UCODE_TRIG_BASE_RX_PE_DISAMBIG,
+ IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG);
+ he->data5 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he_tb.tb_rx1,
+ OFDM_UCODE_TRIG_BASE_RX_NUM_OF_LTF_SYM,
+ IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS);
+ he->data6 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he_tb.a2,
+ OFDM_RX_HE_TRIG_TXOP_DURATION,
+ IEEE80211_RADIOTAP_HE_DATA6_TXOP);
+
+ iwl_mld_he_set_ru_alloc(rx_status, he,
+ le32_get_bits(phy_data->ntfy->sigs.he_tb.tb_rx1,
+ OFDM_UCODE_TRIG_BASE_RX_RU));
+
+ nsts = le32_get_bits(phy_data->ntfy->sigs.he_tb.tb_rx1,
+ OFDM_UCODE_TRIG_BASE_RX_NSTS) + 1;
+ rx_status->nss = nsts >> !!(rate_n_flags & RATE_MCS_STBC_MSK);
}
static void
iwl_mld_decode_he_phy_data(struct iwl_mld_rx_phy_data *phy_data,
struct ieee80211_radiotap_he *he,
struct ieee80211_radiotap_he_mu *he_mu,
- struct ieee80211_rx_status *rx_status,
- int queue)
+ struct ieee80211_rx_status *rx_status)
{
- switch (phy_data->info_type) {
- case IWL_RX_PHY_INFO_TYPE_NONE:
- case IWL_RX_PHY_INFO_TYPE_CCK:
- case IWL_RX_PHY_INFO_TYPE_OFDM_LGCY:
- case IWL_RX_PHY_INFO_TYPE_HT:
- case IWL_RX_PHY_INFO_TYPE_VHT_SU:
- case IWL_RX_PHY_INFO_TYPE_VHT_MU:
- case IWL_RX_PHY_INFO_TYPE_EHT_MU:
- case IWL_RX_PHY_INFO_TYPE_EHT_TB:
- case IWL_RX_PHY_INFO_TYPE_EHT_MU_EXT:
- case IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT:
- return;
- case IWL_RX_PHY_INFO_TYPE_HE_TB_EXT:
- he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN |
- IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN |
- IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN |
- IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN);
- he->data4 |= le16_encode_bits(le32_get_bits(phy_data->data2,
- IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE1),
- IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1);
- he->data4 |= le16_encode_bits(le32_get_bits(phy_data->data2,
- IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE2),
- IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2);
- he->data4 |= le16_encode_bits(le32_get_bits(phy_data->data2,
- IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE3),
- IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3);
- he->data4 |= le16_encode_bits(le32_get_bits(phy_data->data2,
- IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE4),
- IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4);
- fallthrough;
- case IWL_RX_PHY_INFO_TYPE_HE_SU:
- case IWL_RX_PHY_INFO_TYPE_HE_MU:
- case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:
- case IWL_RX_PHY_INFO_TYPE_HE_TB:
- /* HE common */
- he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN |
- IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN |
- IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN);
- he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN |
- IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN |
- IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN |
- IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN);
- he->data3 |= le16_encode_bits(le32_get_bits(phy_data->data0,
- IWL_RX_PHY_DATA0_HE_BSS_COLOR_MASK),
- IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR);
- if (phy_data->info_type != IWL_RX_PHY_INFO_TYPE_HE_TB &&
- phy_data->info_type != IWL_RX_PHY_INFO_TYPE_HE_TB_EXT) {
- he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN);
- he->data3 |= le16_encode_bits(le32_get_bits(phy_data->data0,
- IWL_RX_PHY_DATA0_HE_UPLINK),
- IEEE80211_RADIOTAP_HE_DATA3_UL_DL);
- }
- he->data3 |= le16_encode_bits(le32_get_bits(phy_data->data0,
- IWL_RX_PHY_DATA0_HE_LDPC_EXT_SYM),
- IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG);
- he->data5 |= le16_encode_bits(le32_get_bits(phy_data->data0,
- IWL_RX_PHY_DATA0_HE_PRE_FEC_PAD_MASK),
- IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD);
- he->data5 |= le16_encode_bits(le32_get_bits(phy_data->data0,
- IWL_RX_PHY_DATA0_HE_PE_DISAMBIG),
- IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG);
- he->data5 |= le16_encode_bits(le32_get_bits(phy_data->data1,
- IWL_RX_PHY_DATA1_HE_LTF_NUM_MASK),
- IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS);
- he->data6 |= le16_encode_bits(le32_get_bits(phy_data->data0,
- IWL_RX_PHY_DATA0_HE_TXOP_DUR_MASK),
- IEEE80211_RADIOTAP_HE_DATA6_TXOP);
- he->data6 |= le16_encode_bits(le32_get_bits(phy_data->data0,
- IWL_RX_PHY_DATA0_HE_DOPPLER),
- IEEE80211_RADIOTAP_HE_DATA6_DOPPLER);
- break;
- }
+ u32 rate_n_flags = phy_data->rate_n_flags;
+ u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
+ u32 nsts;
- switch (phy_data->info_type) {
- case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:
- case IWL_RX_PHY_INFO_TYPE_HE_MU:
- case IWL_RX_PHY_INFO_TYPE_HE_SU:
- he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN);
- he->data4 |= le16_encode_bits(le32_get_bits(phy_data->data0,
- IWL_RX_PHY_DATA0_HE_SPATIAL_REUSE_MASK),
- IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE);
- break;
- default:
- /* nothing here */
- break;
- }
+ switch (he_type) {
+ case RATE_MCS_HE_TYPE_TRIG:
+ iwl_mld_decode_he_tb_phy_data(phy_data, he, rx_status);
+ /* that's it, below is only for SU/MU */
+ return;
+ case RATE_MCS_HE_TYPE_MU:
+ iwl_mld_decode_he_mu(phy_data, he, he_mu, rx_status);
- switch (phy_data->info_type) {
- case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:
- he_mu->flags1 |=
- le16_encode_bits(le16_get_bits(phy_data->data4,
- IWL_RX_PHY_DATA4_HE_MU_EXT_SIGB_DCM),
- IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM);
- he_mu->flags1 |=
- le16_encode_bits(le16_get_bits(phy_data->data4,
- IWL_RX_PHY_DATA4_HE_MU_EXT_SIGB_MCS_MASK),
- IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS);
- he_mu->flags2 |=
- le16_encode_bits(le16_get_bits(phy_data->data4,
- IWL_RX_PHY_DATA4_HE_MU_EXT_PREAMBLE_PUNC_TYPE_MASK),
- IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW);
- iwl_mld_decode_he_mu_ext(phy_data, he_mu);
- fallthrough;
- case IWL_RX_PHY_INFO_TYPE_HE_MU:
- he_mu->flags2 |=
- le16_encode_bits(le32_get_bits(phy_data->data1,
- IWL_RX_PHY_DATA1_HE_MU_SIBG_SYM_OR_USER_NUM_MASK),
- IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS);
- he_mu->flags2 |=
- le16_encode_bits(le32_get_bits(phy_data->data1,
- IWL_RX_PHY_DATA1_HE_MU_SIGB_COMPRESSION),
- IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP);
- fallthrough;
- case IWL_RX_PHY_INFO_TYPE_HE_TB:
- case IWL_RX_PHY_INFO_TYPE_HE_TB_EXT:
- iwl_mld_decode_he_phy_ru_alloc(phy_data, he, he_mu, rx_status);
+ nsts = le32_get_bits(phy_data->ntfy->sigs.he.b,
+ OFDM_RX_FRAME_HE_SIGB_NSTS) + 1;
break;
- case IWL_RX_PHY_INFO_TYPE_HE_SU:
+ case RATE_MCS_HE_TYPE_SU:
+ case RATE_MCS_HE_TYPE_EXT_SU:
he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN);
- he->data3 |= le16_encode_bits(le32_get_bits(phy_data->data0,
- IWL_RX_PHY_DATA0_HE_BEAM_CHNG),
- IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE);
- break;
- default:
- /* nothing */
+ he->data3 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.a1,
+ OFDM_RX_FRAME_HE_BEAM_CHANGE,
+ IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE);
+
+ nsts = le32_get_bits(phy_data->ntfy->sigs.he.a1,
+ OFDM_RX_FRAME_HE_NSTS) + 1;
break;
}
+
+ rx_status->nss = nsts >> !!(rate_n_flags & RATE_MCS_STBC_MSK);
+
+ he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN);
+ he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN);
+
+ he->data3 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.a2,
+ OFDM_RX_FRAME_HE_CODING_EXTRA_SYM,
+ IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG);
+ he->data5 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.a2,
+ OFDM_RX_FRAME_HE_PRE_FEC_PAD_FACTOR,
+ IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD);
+ he->data5 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.a2,
+ OFDM_RX_FRAME_HE_PE_DISAMBIG,
+ IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG);
+ he->data5 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.a2,
+ OFDM_RX_FRAME_HE_MU_NUM_OF_LTF_SYM,
+ IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS);
+ he->data6 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.a2,
+ OFDM_RX_FRAME_HE_TXOP_DURATION,
+ IEEE80211_RADIOTAP_HE_DATA6_TXOP);
+ he->data6 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.a2,
+ OFDM_RX_FRAME_HE_DOPPLER,
+ IEEE80211_RADIOTAP_HE_DATA6_DOPPLER);
+
+ he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN |
+ IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN);
+
+ he->data3 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.a1,
+ OFDM_RX_FRAME_HE_BSS_COLOR,
+ IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR);
+ he->data3 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.a1,
+ OFDM_RX_FRAME_HE_UL_FLAG,
+ IEEE80211_RADIOTAP_HE_DATA3_UL_DL);
+ he->data4 |= RTAP_ENC_HE(phy_data->ntfy->sigs.he.a1,
+ OFDM_RX_FRAME_HE_SPATIAL_REUSE,
+ IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE);
}
-static void iwl_mld_rx_he(struct iwl_mld *mld, struct sk_buff *skb,
- struct iwl_mld_rx_phy_data *phy_data,
- int queue)
+static void iwl_mld_rx_he(struct sk_buff *skb,
+ struct iwl_mld_rx_phy_data *phy_data)
{
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_radiotap_he *he = NULL;
@@ -460,48 +529,28 @@ static void iwl_mld_rx_he(struct iwl_mld *mld, struct sk_buff *skb,
.flags2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN |
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
};
- u16 phy_info = phy_data->phy_info;
he = skb_put_data(skb, &known, sizeof(known));
rx_status->flag |= RX_FLAG_RADIOTAP_HE;
- if (phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU ||
- phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU_EXT) {
- he_mu = skb_put_data(skb, &mu_known, sizeof(mu_known));
- rx_status->flag |= RX_FLAG_RADIOTAP_HE_MU;
- }
-
- /* report the AMPDU-EOF bit on single frames */
- if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
- rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
- rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
- if (phy_data->data0 & cpu_to_le32(IWL_RX_PHY_DATA0_HE_DELIM_EOF))
- rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
- }
-
- if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD)
- iwl_mld_decode_he_phy_data(phy_data, he, he_mu, rx_status,
- queue);
-
- /* update aggregation data for monitor sake on default queue */
- if (!queue && (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) &&
- (phy_info & IWL_RX_MPDU_PHY_AMPDU) && phy_data->first_subframe) {
- rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
- if (phy_data->data0 & cpu_to_le32(IWL_RX_PHY_DATA0_EHT_DELIM_EOF))
- rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
- }
-
- if (he_type == RATE_MCS_HE_TYPE_EXT_SU &&
- rate_n_flags & RATE_MCS_HE_106T_MSK) {
- rx_status->bw = RATE_INFO_BW_HE_RU;
- rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
- }
-
- /* actually data is filled in mac80211 */
- if (he_type == RATE_MCS_HE_TYPE_SU ||
- he_type == RATE_MCS_HE_TYPE_EXT_SU)
+ switch (he_type) {
+ case RATE_MCS_HE_TYPE_EXT_SU:
+ /*
+ * Except for this special case we won't have
+ * HE RU allocation info outside of monitor mode
+ * since we don't get the PHY notif.
+ */
+ if (rate_n_flags & RATE_MCS_HE_106T_MSK) {
+ rx_status->bw = RATE_INFO_BW_HE_RU;
+ rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
+ }
+ fallthrough;
+ case RATE_MCS_HE_TYPE_SU:
+ /* actual data is filled in mac80211 */
he->data1 |=
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN);
+ break;
+ }
#define CHECK_TYPE(F) \
BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA1_FORMAT_ ## F != \
@@ -517,8 +566,7 @@ static void iwl_mld_rx_he(struct iwl_mld *mld, struct sk_buff *skb,
if (rate_n_flags & RATE_MCS_BF_MSK)
he->data5 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA5_TXBF);
- switch ((rate_n_flags & RATE_MCS_HE_GI_LTF_MSK) >>
- RATE_MCS_HE_GI_LTF_POS) {
+ switch (u32_get_bits(rate_n_flags, RATE_MCS_HE_GI_LTF_MSK)) {
case 0:
if (he_type == RATE_MCS_HE_TYPE_TRIG)
rx_status->he_gi = NL80211_RATE_INFO_HE_GI_1_6;
@@ -559,37 +607,52 @@ static void iwl_mld_rx_he(struct iwl_mld *mld, struct sk_buff *skb,
he->data5 |= le16_encode_bits(ltf,
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
+
+ if (likely(!phy_data->ntfy))
+ return;
+
+ if (he_type == RATE_MCS_HE_TYPE_MU) {
+ he_mu = skb_put_data(skb, &mu_known, sizeof(mu_known));
+ rx_status->flag |= RX_FLAG_RADIOTAP_HE_MU;
+ }
+
+ iwl_mld_decode_he_phy_data(phy_data, he, he_mu, rx_status);
}
static void iwl_mld_decode_lsig(struct sk_buff *skb,
struct iwl_mld_rx_phy_data *phy_data)
{
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
+ u32 format = phy_data->rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
struct ieee80211_radiotap_lsig *lsig;
+ u32 lsig_len, rate;
- switch (phy_data->info_type) {
- case IWL_RX_PHY_INFO_TYPE_HT:
- case IWL_RX_PHY_INFO_TYPE_VHT_SU:
- case IWL_RX_PHY_INFO_TYPE_VHT_MU:
- case IWL_RX_PHY_INFO_TYPE_HE_TB_EXT:
- case IWL_RX_PHY_INFO_TYPE_HE_SU:
- case IWL_RX_PHY_INFO_TYPE_HE_MU:
- case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:
- case IWL_RX_PHY_INFO_TYPE_HE_TB:
- case IWL_RX_PHY_INFO_TYPE_EHT_MU:
- case IWL_RX_PHY_INFO_TYPE_EHT_TB:
- case IWL_RX_PHY_INFO_TYPE_EHT_MU_EXT:
- case IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT:
- lsig = skb_put(skb, sizeof(*lsig));
- lsig->data1 = cpu_to_le16(IEEE80211_RADIOTAP_LSIG_DATA1_LENGTH_KNOWN);
- lsig->data2 = le16_encode_bits(le32_get_bits(phy_data->data1,
- IWL_RX_PHY_DATA1_LSIG_LEN_MASK),
- IEEE80211_RADIOTAP_LSIG_DATA2_LENGTH);
- rx_status->flag |= RX_FLAG_RADIOTAP_LSIG;
- break;
- default:
- break;
- }
+ if (likely(!phy_data->ntfy))
+ return;
+
+ /*
+ * Technically legacy CCK/OFDM frames don't have an L-SIG
+ * since that's the compat format for HT (non-greenfield)
+ * and up. However, it's meant to be compatible with the
+ * LENGTH and RATE fields in Clause 17 and 18 OFDM frames
+ * so include the field for any non-CCK frame. For CCK it
+ * cannot work, since the LENGTH field for them is 16-bit
+ * and the radiotap field only has 12 bits.
+ */
+ if (format == RATE_MCS_MOD_TYPE_CCK)
+ return;
+
+ lsig_len = le32_get_bits(phy_data->ntfy->legacy_sig.ofdm,
+ OFDM_RX_LEGACY_LENGTH);
+ rate = le32_get_bits(phy_data->ntfy->legacy_sig.ofdm, OFDM_RX_RATE);
+
+ lsig = skb_put(skb, sizeof(*lsig));
+ lsig->data1 = cpu_to_le16(IEEE80211_RADIOTAP_LSIG_DATA1_LENGTH_KNOWN) |
+ cpu_to_le16(IEEE80211_RADIOTAP_LSIG_DATA1_RATE_KNOWN);
+ lsig->data2 = le16_encode_bits(lsig_len,
+ IEEE80211_RADIOTAP_LSIG_DATA2_LENGTH) |
+ le16_encode_bits(rate, IEEE80211_RADIOTAP_LSIG_DATA2_RATE);
+ rx_status->flag |= RX_FLAG_RADIOTAP_LSIG;
}
/* Put a TLV on the skb and return data pointer
@@ -617,209 +680,144 @@ iwl_mld_radiotap_put_tlv(struct sk_buff *skb, u16 type, u16 len)
(_usig)->value |= LE32_DEC_ENC(in_value, dec_bits, _enc_bits); \
} while (0)
-#define __IWL_MLD_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru) \
- eht->data[(rt_data)] |= \
- (cpu_to_le32 \
- (IEEE80211_RADIOTAP_EHT_DATA ## rt_data ## _RU_ALLOC_CC_ ## rt_ru ## _KNOWN) | \
- LE32_DEC_ENC(data ## fw_data, \
- IWL_RX_PHY_DATA ## fw_data ## _EHT_MU_EXT_RU_ALLOC_ ## fw_ru, \
- IEEE80211_RADIOTAP_EHT_DATA ## rt_data ## _RU_ALLOC_CC_ ## rt_ru))
+static void iwl_mld_decode_eht_usig_tb(struct iwl_mld_rx_phy_data *phy_data,
+ struct ieee80211_radiotap_eht_usig *usig)
+{
+ __le32 usig_a1 = phy_data->ntfy->sigs.eht_tb.usig_a1;
+ __le32 usig_a2 = phy_data->ntfy->sigs.eht_tb.usig_a2_eht;
+
+ IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1,
+ OFDM_RX_FRAME_EHT_USIG1_DISREGARD,
+ IEEE80211_RADIOTAP_EHT_USIG1_TB_B20_B25_DISREGARD);
+ IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
+ OFDM_RX_FRAME_EHT_PPDU_TYPE,
+ IEEE80211_RADIOTAP_EHT_USIG2_TB_B0_B1_PPDU_TYPE);
+ IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
+ OFDM_RX_FRAME_EHT_USIG2_VALIDATE_B2,
+ IEEE80211_RADIOTAP_EHT_USIG2_TB_B2_VALIDATE);
+ IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
+ OFDM_RX_FRAME_EHT_TRIG_SPATIAL_REUSE_1,
+ IEEE80211_RADIOTAP_EHT_USIG2_TB_B3_B6_SPATIAL_REUSE_1);
+ IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
+ OFDM_RX_FRAME_EHT_TRIG_SPATIAL_REUSE_2,
+ IEEE80211_RADIOTAP_EHT_USIG2_TB_B7_B10_SPATIAL_REUSE_2);
+ IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
+ OFDM_RX_FRAME_EHT_TRIG_USIG2_DISREGARD,
+ IEEE80211_RADIOTAP_EHT_USIG2_TB_B11_B15_DISREGARD);
+}
-#define _IWL_MLD_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru) \
- __IWL_MLD_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru)
+static void iwl_mld_decode_eht_usig_non_tb(struct iwl_mld_rx_phy_data *phy_data,
+ struct ieee80211_radiotap_eht_usig *usig)
+{
+ __le32 usig_a1 = phy_data->ntfy->sigs.eht.usig_a1;
+ __le32 usig_a2 = phy_data->ntfy->sigs.eht.usig_a2_eht;
+
+ IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1,
+ OFDM_RX_FRAME_EHT_USIG1_DISREGARD,
+ IEEE80211_RADIOTAP_EHT_USIG1_MU_B20_B24_DISREGARD);
+ IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1,
+ OFDM_RX_FRAME_EHT_USIG1_VALIDATE,
+ IEEE80211_RADIOTAP_EHT_USIG1_MU_B25_VALIDATE);
+ IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
+ OFDM_RX_FRAME_EHT_PPDU_TYPE,
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B0_B1_PPDU_TYPE);
+ IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
+ OFDM_RX_FRAME_EHT_USIG2_VALIDATE_B2,
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B2_VALIDATE);
+ IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
+ OFDM_RX_FRAME_EHT_PUNC_CHANNEL,
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B3_B7_PUNCTURED_INFO);
+ IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
+ OFDM_RX_FRAME_EHT_USIG2_VALIDATE_B8,
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B8_VALIDATE);
+ IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
+ OFDM_RX_FRAME_EHT_SIG_MCS,
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B9_B10_SIG_MCS);
+ IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
+ OFDM_RX_FRAME_EHT_SIG_SYM_NUM,
+ IEEE80211_RADIOTAP_EHT_USIG2_MU_B11_B15_EHT_SIG_SYMBOLS);
+}
-#define IEEE80211_RADIOTAP_RU_DATA_1_1_1 1
-#define IEEE80211_RADIOTAP_RU_DATA_2_1_1 2
-#define IEEE80211_RADIOTAP_RU_DATA_1_1_2 2
-#define IEEE80211_RADIOTAP_RU_DATA_2_1_2 2
-#define IEEE80211_RADIOTAP_RU_DATA_1_2_1 3
-#define IEEE80211_RADIOTAP_RU_DATA_2_2_1 3
-#define IEEE80211_RADIOTAP_RU_DATA_1_2_2 3
-#define IEEE80211_RADIOTAP_RU_DATA_2_2_2 4
+static void iwl_mld_decode_eht_usig(struct iwl_mld_rx_phy_data *phy_data,
+ struct sk_buff *skb)
+{
+ u32 he_type = phy_data->rate_n_flags & RATE_MCS_HE_TYPE_MSK;
+ __le32 usig_a1 = phy_data->ntfy->sigs.eht.usig_a1;
+ __le32 usig_a2 = phy_data->ntfy->sigs.eht.usig_a2_eht;
+ struct ieee80211_radiotap_eht_usig *usig;
+ u32 bw;
-#define IWL_RX_RU_DATA_A1 2
-#define IWL_RX_RU_DATA_A2 2
-#define IWL_RX_RU_DATA_B1 2
-#define IWL_RX_RU_DATA_B2 4
-#define IWL_RX_RU_DATA_C1 3
-#define IWL_RX_RU_DATA_C2 3
-#define IWL_RX_RU_DATA_D1 4
-#define IWL_RX_RU_DATA_D2 4
+ usig = iwl_mld_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT_USIG,
+ sizeof(*usig));
-#define IWL_MLD_ENC_EHT_RU(rt_ru, fw_ru) \
- _IWL_MLD_ENC_EHT_RU(IEEE80211_RADIOTAP_RU_DATA_ ## rt_ru, \
- rt_ru, \
- IWL_RX_RU_DATA_ ## fw_ru, \
- fw_ru)
+ BUILD_BUG_ON(offsetof(union iwl_sigs, eht.usig_a1) !=
+ offsetof(union iwl_sigs, eht_tb.usig_a1));
+ BUILD_BUG_ON(offsetof(union iwl_sigs, eht.usig_a2_eht) !=
+ offsetof(union iwl_sigs, eht_tb.usig_a2_eht));
-static void iwl_mld_decode_eht_ext_mu(struct iwl_mld *mld,
- struct iwl_mld_rx_phy_data *phy_data,
- struct ieee80211_rx_status *rx_status,
- struct ieee80211_radiotap_eht *eht,
- struct ieee80211_radiotap_eht_usig *usig)
-{
- if (phy_data->with_data) {
- __le32 data1 = phy_data->data1;
- __le32 data2 = phy_data->data2;
- __le32 data3 = phy_data->data3;
- __le32 data4 = phy_data->eht_data4;
- __le32 data5 = phy_data->data5;
- u32 phy_bw = phy_data->rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK;
-
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, data5,
- IWL_RX_PHY_DATA5_EHT_TYPE_AND_COMP,
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B0_B1_PPDU_TYPE);
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, data5,
- IWL_RX_PHY_DATA5_EHT_MU_PUNC_CH_CODE,
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B3_B7_PUNCTURED_INFO);
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, data4,
- IWL_RX_PHY_DATA4_EHT_MU_EXT_SIGB_MCS,
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B9_B10_SIG_MCS);
- IWL_MLD_ENC_USIG_VALUE_MASK
- (usig, data1, IWL_RX_PHY_DATA1_EHT_MU_NUM_SIG_SYM_USIGA2,
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B11_B15_EHT_SIG_SYMBOLS);
+ usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL_KNOWN |
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR_KNOWN |
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_CHECKED |
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_KNOWN |
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP_KNOWN);
- eht->user_info[0] |=
- cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID_KNOWN) |
- LE32_DEC_ENC(data5, IWL_RX_PHY_DATA5_EHT_MU_STA_ID_USR,
- IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID);
+#define CHECK_BW(bw) \
+ BUILD_BUG_ON(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_ ## bw ## MHZ != \
+ RATE_MCS_CHAN_WIDTH_ ## bw ## _VAL)
+ CHECK_BW(20);
+ CHECK_BW(40);
+ CHECK_BW(80);
+ CHECK_BW(160);
+#undef CHECK_BW
+ BUILD_BUG_ON(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_320MHZ_1 !=
+ RATE_MCS_CHAN_WIDTH_320_VAL);
+ bw = u32_get_bits(phy_data->rate_n_flags, RATE_MCS_CHAN_WIDTH_MSK);
+ /* specific handling for 320MHz-1/320MHz-2 */
+ if (bw == RATE_MCS_CHAN_WIDTH_320_VAL)
+ bw += le32_get_bits(usig_a1, OFDM_RX_FRAME_EHT_BW320_SLOT);
+ usig->common |= le32_encode_bits(bw,
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW);
- eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_NR_NON_OFDMA_USERS_M);
- eht->data[7] |= LE32_DEC_ENC
- (data5, IWL_RX_PHY_DATA5_EHT_MU_NUM_USR_NON_OFDMA,
- IEEE80211_RADIOTAP_EHT_DATA7_NUM_OF_NON_OFDMA_USERS);
+ usig->common |= LE32_DEC_ENC(usig_a1, OFDM_RX_FRAME_ENHANCED_WIFI_UL_FLAG,
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL);
+ usig->common |= LE32_DEC_ENC(usig_a1, OFDM_RX_FRAME_ENHANCED_WIFI_BSS_COLOR,
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR);
- /*
- * Hardware labels the content channels/RU allocation values
- * as follows:
- * Content Channel 1 Content Channel 2
- * 20 MHz: A1
- * 40 MHz: A1 B1
- * 80 MHz: A1 C1 B1 D1
- * 160 MHz: A1 C1 A2 C2 B1 D1 B2 D2
- * 320 MHz: A1 C1 A2 C2 A3 C3 A4 C4 B1 D1 B2 D2 B3 D3 B4 D4
- *
- * However firmware can only give us A1-D2, so the higher
- * frequencies are missing.
- */
+ if (le32_get_bits(usig_a1, OFDM_RX_FRAME_EHT_USIG1_VALIDATE) &&
+ le32_get_bits(usig_a2, OFDM_RX_FRAME_EHT_USIG2_VALIDATE_B2) &&
+ le32_get_bits(usig_a2, OFDM_RX_FRAME_EHT_USIG2_VALIDATE_B8))
+ usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_OK);
- switch (phy_bw) {
- case RATE_MCS_CHAN_WIDTH_320:
- /* additional values are missing in RX metadata */
- fallthrough;
- case RATE_MCS_CHAN_WIDTH_160:
- /* content channel 1 */
- IWL_MLD_ENC_EHT_RU(1_2_1, A2);
- IWL_MLD_ENC_EHT_RU(1_2_2, C2);
- /* content channel 2 */
- IWL_MLD_ENC_EHT_RU(2_2_1, B2);
- IWL_MLD_ENC_EHT_RU(2_2_2, D2);
- fallthrough;
- case RATE_MCS_CHAN_WIDTH_80:
- /* content channel 1 */
- IWL_MLD_ENC_EHT_RU(1_1_2, C1);
- /* content channel 2 */
- IWL_MLD_ENC_EHT_RU(2_1_2, D1);
- fallthrough;
- case RATE_MCS_CHAN_WIDTH_40:
- /* content channel 2 */
- IWL_MLD_ENC_EHT_RU(2_1_1, B1);
- fallthrough;
- case RATE_MCS_CHAN_WIDTH_20:
- IWL_MLD_ENC_EHT_RU(1_1_1, A1);
- break;
- }
- } else {
- __le32 usig_a1 = phy_data->rx_vec[0];
- __le32 usig_a2 = phy_data->rx_vec[1];
-
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1,
- IWL_RX_USIG_A1_DISREGARD,
- IEEE80211_RADIOTAP_EHT_USIG1_MU_B20_B24_DISREGARD);
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1,
- IWL_RX_USIG_A1_VALIDATE,
- IEEE80211_RADIOTAP_EHT_USIG1_MU_B25_VALIDATE);
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
- IWL_RX_USIG_A2_EHT_PPDU_TYPE,
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B0_B1_PPDU_TYPE);
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
- IWL_RX_USIG_A2_EHT_USIG2_VALIDATE_B2,
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B2_VALIDATE);
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
- IWL_RX_USIG_A2_EHT_PUNC_CHANNEL,
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B3_B7_PUNCTURED_INFO);
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
- IWL_RX_USIG_A2_EHT_USIG2_VALIDATE_B8,
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B8_VALIDATE);
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
- IWL_RX_USIG_A2_EHT_SIG_MCS,
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B9_B10_SIG_MCS);
- IWL_MLD_ENC_USIG_VALUE_MASK
- (usig, usig_a2, IWL_RX_USIG_A2_EHT_SIG_SYM_NUM,
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B11_B15_EHT_SIG_SYMBOLS);
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
- IWL_RX_USIG_A2_EHT_CRC_OK,
- IEEE80211_RADIOTAP_EHT_USIG2_MU_B16_B19_CRC);
- }
-}
+ usig->common |= LE32_DEC_ENC(usig_a1,
+ OFDM_RX_FRAME_ENHANCED_WIFI_TXOP_DURATION,
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP);
-static void iwl_mld_decode_eht_ext_tb(struct iwl_mld *mld,
- struct iwl_mld_rx_phy_data *phy_data,
- struct ieee80211_rx_status *rx_status,
- struct ieee80211_radiotap_eht *eht,
- struct ieee80211_radiotap_eht_usig *usig)
-{
- if (phy_data->with_data) {
- __le32 data5 = phy_data->data5;
-
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, data5,
- IWL_RX_PHY_DATA5_EHT_TYPE_AND_COMP,
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B0_B1_PPDU_TYPE);
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, data5,
- IWL_RX_PHY_DATA5_EHT_TB_SPATIAL_REUSE1,
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B3_B6_SPATIAL_REUSE_1);
-
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, data5,
- IWL_RX_PHY_DATA5_EHT_TB_SPATIAL_REUSE2,
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B7_B10_SPATIAL_REUSE_2);
- } else {
- __le32 usig_a1 = phy_data->rx_vec[0];
- __le32 usig_a2 = phy_data->rx_vec[1];
-
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1,
- IWL_RX_USIG_A1_DISREGARD,
- IEEE80211_RADIOTAP_EHT_USIG1_TB_B20_B25_DISREGARD);
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
- IWL_RX_USIG_A2_EHT_PPDU_TYPE,
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B0_B1_PPDU_TYPE);
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
- IWL_RX_USIG_A2_EHT_USIG2_VALIDATE_B2,
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B2_VALIDATE);
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
- IWL_RX_USIG_A2_EHT_TRIG_SPATIAL_REUSE_1,
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B3_B6_SPATIAL_REUSE_1);
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
- IWL_RX_USIG_A2_EHT_TRIG_SPATIAL_REUSE_2,
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B7_B10_SPATIAL_REUSE_2);
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
- IWL_RX_USIG_A2_EHT_TRIG_USIG2_DISREGARD,
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B11_B15_DISREGARD);
- IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2,
- IWL_RX_USIG_A2_EHT_CRC_OK,
- IEEE80211_RADIOTAP_EHT_USIG2_TB_B16_B19_CRC);
- }
+ if (!le32_get_bits(usig_a2, OFDM_RX_USIG_CRC_OK))
+ usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC);
+
+ usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER_KNOWN);
+ usig->common |= LE32_DEC_ENC(usig_a1,
+ OFDM_RX_FRAME_ENHANCED_WIFI_VER_ID,
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER);
+
+ if (he_type == RATE_MCS_HE_TYPE_TRIG)
+ iwl_mld_decode_eht_usig_tb(phy_data, usig);
+ else
+ iwl_mld_decode_eht_usig_non_tb(phy_data, usig);
}
-static void iwl_mld_decode_eht_ru(struct iwl_mld *mld,
- struct ieee80211_rx_status *rx_status,
- struct ieee80211_radiotap_eht *eht)
+static void
+iwl_mld_eht_set_ru_alloc(struct ieee80211_rx_status *rx_status,
+ u32 ru_with_p80)
{
- u32 ru = le32_get_bits(eht->data[8],
- IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B7_B1);
enum nl80211_eht_ru_alloc nl_ru;
+ u32 ru = ru_with_p80 >> 1;
- /* Using D1.5 Table 9-53a - Encoding of PS160 and RU Allocation subfields
- * in an EHT variant User Info field
+ /*
+ * HW always uses trigger frame format:
+ *
+ * Draft PIEEE802.11be D7.0 Table 9-46l - Encoding of the PS160 and
+ * RU Allocation subfields in an EHT variant User Info field
*/
switch (ru) {
@@ -879,135 +877,228 @@ static void iwl_mld_decode_eht_ru(struct iwl_mld *mld,
rx_status->eht.ru = nl_ru;
}
-static void iwl_mld_decode_eht_phy_data(struct iwl_mld *mld,
- struct iwl_mld_rx_phy_data *phy_data,
- struct ieee80211_rx_status *rx_status,
- struct ieee80211_radiotap_eht *eht,
- struct ieee80211_radiotap_eht_usig *usig)
-
+static void iwl_mld_decode_eht_tb(struct iwl_mld_rx_phy_data *phy_data,
+ struct ieee80211_rx_status *rx_status,
+ struct ieee80211_radiotap_eht *eht)
{
- __le32 data0 = phy_data->data0;
- __le32 data1 = phy_data->data1;
- __le32 usig_a1 = phy_data->rx_vec[0];
- u8 info_type = phy_data->info_type;
-
- /* Not in EHT range */
- if (info_type < IWL_RX_PHY_INFO_TYPE_EHT_MU ||
- info_type > IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT)
+ if (!(phy_data->ntfy->flags & IWL_SNIF_FLAG_VALID_TB_RX))
return;
- usig->common |= cpu_to_le32
- (IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL_KNOWN |
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR_KNOWN);
- if (phy_data->with_data) {
- usig->common |= LE32_DEC_ENC(data0,
- IWL_RX_PHY_DATA0_EHT_UPLINK,
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL);
- usig->common |= LE32_DEC_ENC(data0,
- IWL_RX_PHY_DATA0_EHT_BSS_COLOR_MASK,
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR);
- } else {
- usig->common |= LE32_DEC_ENC(usig_a1,
- IWL_RX_USIG_A1_UL_FLAG,
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL);
- usig->common |= LE32_DEC_ENC(usig_a1,
- IWL_RX_USIG_A1_BSS_COLOR,
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR);
- }
-
- usig->common |=
- cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_CHECKED);
- usig->common |=
- LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_VALIDATE,
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_OK);
-
- eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_SPATIAL_REUSE);
- eht->data[0] |= LE32_DEC_ENC(data0,
- IWL_RX_PHY_DATA0_ETH_SPATIAL_REUSE_MASK,
- IEEE80211_RADIOTAP_EHT_DATA0_SPATIAL_REUSE);
+ eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_RU_ALLOC_TB_FMT |
+ IEEE80211_RADIOTAP_EHT_KNOWN_LDPC_EXTRA_SYM_OM |
+ IEEE80211_RADIOTAP_EHT_KNOWN_PRE_PADD_FACOR_OM |
+ IEEE80211_RADIOTAP_EHT_KNOWN_PE_DISAMBIGUITY_OM |
+ IEEE80211_RADIOTAP_EHT_KNOWN_EHT_LTF |
+ IEEE80211_RADIOTAP_EHT_KNOWN_PRIMARY_80);
- /* All RU allocating size/index is in TB format */
- eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_RU_ALLOC_TB_FMT);
- eht->data[8] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PS160,
+ eht->data[8] |= LE32_DEC_ENC(phy_data->ntfy->sigs.eht_tb.tb_rx0,
+ OFDM_UCODE_TRIG_BASE_PS160,
IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_PS_160);
- eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B0,
- IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B0);
- eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B1_B7,
+ eht->data[8] |= LE32_DEC_ENC(phy_data->ntfy->sigs.eht_tb.tb_rx1,
+ OFDM_UCODE_TRIG_BASE_RX_RU,
+ IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B0 |
IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B7_B1);
+ eht->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.eht_tb.tb_rx1,
+ OFDM_UCODE_TRIG_BASE_RX_CODING_EXTRA_SYM,
+ IEEE80211_RADIOTAP_EHT_DATA0_LDPC_EXTRA_SYM_OM);
+ eht->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.eht_tb.tb_rx1,
+ OFDM_UCODE_TRIG_BASE_RX_PRE_FEC_PAD_FACTOR,
+ IEEE80211_RADIOTAP_EHT_DATA0_PRE_PADD_FACOR_OM);
+ eht->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.eht_tb.tb_rx1,
+ OFDM_UCODE_TRIG_BASE_RX_PE_DISAMBIG,
+ IEEE80211_RADIOTAP_EHT_DATA0_PE_DISAMBIGUITY_OM);
+ eht->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.eht_tb.tb_rx1,
+ OFDM_UCODE_TRIG_BASE_RX_NUM_OF_LTF_SYM,
+ IEEE80211_RADIOTAP_EHT_DATA0_EHT_LTF);
+ eht->data[1] |= LE32_DEC_ENC(phy_data->ntfy->sigs.eht_tb.tb_rx0,
+ OFDM_UCODE_TRIG_BASE_RX_RU_P80,
+ IEEE80211_RADIOTAP_EHT_DATA1_PRIMARY_80);
- iwl_mld_decode_eht_ru(mld, rx_status, eht);
-
- /* We only get here in case of IWL_RX_MPDU_PHY_TSF_OVERLOAD is set
- * which is on only in case of monitor mode so no need to check monitor
- * mode
- */
- eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_PRIMARY_80);
- eht->data[1] |=
- le32_encode_bits(mld->monitor.p80,
- IEEE80211_RADIOTAP_EHT_DATA1_PRIMARY_80);
-
- usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP_KNOWN);
- if (phy_data->with_data)
- usig->common |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_TXOP_DUR_MASK,
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP);
- else
- usig->common |= LE32_DEC_ENC(usig_a1, IWL_RX_USIG_A1_TXOP_DURATION,
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP);
+ iwl_mld_eht_set_ru_alloc(rx_status,
+ le32_get_bits(phy_data->ntfy->sigs.eht_tb.tb_rx1,
+ OFDM_UCODE_TRIG_BASE_RX_RU));
+}
- eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_LDPC_EXTRA_SYM_OM);
- eht->data[0] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_LDPC_EXT_SYM,
- IEEE80211_RADIOTAP_EHT_DATA0_LDPC_EXTRA_SYM_OM);
+static void iwl_mld_eht_decode_user_ru(struct iwl_mld_rx_phy_data *phy_data,
+ struct ieee80211_radiotap_eht *eht)
+{
+ u32 phy_bw = phy_data->rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK;
- eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_PRE_PADD_FACOR_OM);
- eht->data[0] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PRE_FEC_PAD_MASK,
- IEEE80211_RADIOTAP_EHT_DATA0_PRE_PADD_FACOR_OM);
+ if (!(phy_data->ntfy->flags & IWL_SNIF_FLAG_VALID_RU))
+ return;
- eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_PE_DISAMBIGUITY_OM);
- eht->data[0] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PE_DISAMBIG,
- IEEE80211_RADIOTAP_EHT_DATA0_PE_DISAMBIGUITY_OM);
+#define __IWL_MLD_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru) \
+ eht->data[(rt_data)] |= \
+ (cpu_to_le32(IEEE80211_RADIOTAP_EHT_DATA ## rt_data ## _RU_ALLOC_CC_ ## rt_ru ## _KNOWN) | \
+ LE32_DEC_ENC(phy_data->ntfy->sigs.eht.cmn[fw_data], \
+ OFDM_RX_FRAME_EHT_RU_ALLOC_ ## fw_data ## _ ## fw_ru, \
+ IEEE80211_RADIOTAP_EHT_DATA ## rt_data ## _RU_ALLOC_CC_ ## rt_ru))
- /* TODO: what about IWL_RX_PHY_DATA0_EHT_BW320_SLOT */
+#define _IWL_MLD_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru) \
+ __IWL_MLD_ENC_EHT_RU(rt_data, rt_ru, fw_data, fw_ru)
- if (!le32_get_bits(data0, IWL_RX_PHY_DATA0_EHT_SIGA_CRC_OK))
- usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC);
+#define IEEE80211_RADIOTAP_RU_DATA_1_1_1 1
+#define IEEE80211_RADIOTAP_RU_DATA_2_1_1 2
+#define IEEE80211_RADIOTAP_RU_DATA_1_1_2 2
+#define IEEE80211_RADIOTAP_RU_DATA_2_1_2 2
+#define IEEE80211_RADIOTAP_RU_DATA_1_2_1 3
+#define IEEE80211_RADIOTAP_RU_DATA_2_2_1 3
+#define IEEE80211_RADIOTAP_RU_DATA_1_2_2 3
+#define IEEE80211_RADIOTAP_RU_DATA_2_2_2 4
+#define IEEE80211_RADIOTAP_RU_DATA_1_2_3 4
+#define IEEE80211_RADIOTAP_RU_DATA_2_2_3 4
+#define IEEE80211_RADIOTAP_RU_DATA_1_2_4 5
+#define IEEE80211_RADIOTAP_RU_DATA_2_2_4 5
+#define IEEE80211_RADIOTAP_RU_DATA_1_2_5 5
+#define IEEE80211_RADIOTAP_RU_DATA_2_2_5 6
+#define IEEE80211_RADIOTAP_RU_DATA_1_2_6 6
+#define IEEE80211_RADIOTAP_RU_DATA_2_2_6 6
+
+#define IWL_RX_RU_DATA_A1 0
+#define IWL_RX_RU_DATA_A2 0
+#define IWL_RX_RU_DATA_A3 0
+#define IWL_RX_RU_DATA_A4 4
+#define IWL_RX_RU_DATA_B1 1
+#define IWL_RX_RU_DATA_B2 1
+#define IWL_RX_RU_DATA_B3 1
+#define IWL_RX_RU_DATA_B4 4
+#define IWL_RX_RU_DATA_C1 2
+#define IWL_RX_RU_DATA_C2 2
+#define IWL_RX_RU_DATA_C3 2
+#define IWL_RX_RU_DATA_C4 5
+#define IWL_RX_RU_DATA_D1 3
+#define IWL_RX_RU_DATA_D2 3
+#define IWL_RX_RU_DATA_D3 3
+#define IWL_RX_RU_DATA_D4 5
- usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER_KNOWN);
- usig->common |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PHY_VER,
- IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER);
+#define IWL_MLD_ENC_EHT_RU(rt_ru, fw_ru) \
+ _IWL_MLD_ENC_EHT_RU(IEEE80211_RADIOTAP_RU_DATA_ ## rt_ru, \
+ rt_ru, \
+ IWL_RX_RU_DATA_ ## fw_ru, \
+ fw_ru)
/*
- * TODO: what about TB - IWL_RX_PHY_DATA1_EHT_TB_PILOT_TYPE,
- * IWL_RX_PHY_DATA1_EHT_TB_LOW_SS
+ * Hardware labels the content channels/RU allocation values
+ * as follows:
+ *
+ * Content Channel 1 Content Channel 2
+ * 20 MHz: A1
+ * 40 MHz: A1 B1
+ * 80 MHz: A1 C1 B1 D1
+ * 160 MHz: A1 C1 A2 C2 B1 D1 B2 D2
+ * 320 MHz: A1 C1 A2 C2 A3 C3 A4 C4 B1 D1 B2 D2 B3 D3 B4 D4
*/
- eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_EHT_LTF);
- eht->data[0] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_SIG_LTF_NUM,
+ switch (phy_bw) {
+ case RATE_MCS_CHAN_WIDTH_320:
+ /* content channel 1 */
+ IWL_MLD_ENC_EHT_RU(1_2_3, A3);
+ IWL_MLD_ENC_EHT_RU(1_2_4, C3);
+ IWL_MLD_ENC_EHT_RU(1_2_5, A4);
+ IWL_MLD_ENC_EHT_RU(1_2_6, C4);
+ /* content channel 2 */
+ IWL_MLD_ENC_EHT_RU(2_2_3, B3);
+ IWL_MLD_ENC_EHT_RU(2_2_4, D3);
+ IWL_MLD_ENC_EHT_RU(2_2_5, B4);
+ IWL_MLD_ENC_EHT_RU(2_2_6, D4);
+ fallthrough;
+ case RATE_MCS_CHAN_WIDTH_160:
+ /* content channel 1 */
+ IWL_MLD_ENC_EHT_RU(1_2_1, A2);
+ IWL_MLD_ENC_EHT_RU(1_2_2, C2);
+ /* content channel 2 */
+ IWL_MLD_ENC_EHT_RU(2_2_1, B2);
+ IWL_MLD_ENC_EHT_RU(2_2_2, D2);
+ fallthrough;
+ case RATE_MCS_CHAN_WIDTH_80:
+ /* content channel 1 */
+ IWL_MLD_ENC_EHT_RU(1_1_2, C1);
+ /* content channel 2 */
+ IWL_MLD_ENC_EHT_RU(2_1_2, D1);
+ fallthrough;
+ case RATE_MCS_CHAN_WIDTH_40:
+ /* content channel 2 */
+ IWL_MLD_ENC_EHT_RU(2_1_1, B1);
+ fallthrough;
+ case RATE_MCS_CHAN_WIDTH_20:
+ /* content channel 1 */
+ IWL_MLD_ENC_EHT_RU(1_1_1, A1);
+ break;
+ }
+}
+
+static void iwl_mld_decode_eht_non_tb(struct iwl_mld_rx_phy_data *phy_data,
+ struct ieee80211_rx_status *rx_status,
+ struct ieee80211_radiotap_eht *eht)
+{
+ eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_SPATIAL_REUSE |
+ /* All RU allocating size/index is in TB format */
+ IEEE80211_RADIOTAP_EHT_KNOWN_RU_ALLOC_TB_FMT |
+ IEEE80211_RADIOTAP_EHT_KNOWN_LDPC_EXTRA_SYM_OM |
+ IEEE80211_RADIOTAP_EHT_KNOWN_PRE_PADD_FACOR_OM |
+ IEEE80211_RADIOTAP_EHT_KNOWN_PE_DISAMBIGUITY_OM |
+ IEEE80211_RADIOTAP_EHT_KNOWN_EHT_LTF |
+ IEEE80211_RADIOTAP_EHT_KNOWN_PRIMARY_80 |
+ IEEE80211_RADIOTAP_EHT_KNOWN_NR_NON_OFDMA_USERS_M);
+
+ eht->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.eht.b1,
+ OFDM_RX_FRAME_EHT_SPATIAL_REUSE,
+ IEEE80211_RADIOTAP_EHT_DATA0_SPATIAL_REUSE);
+ eht->data[8] |= LE32_DEC_ENC(phy_data->ntfy->sigs.eht.b2,
+ OFDM_RX_FRAME_EHT_STA_RU_PS160,
+ IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_PS_160);
+ eht->data[8] |= LE32_DEC_ENC(phy_data->ntfy->sigs.eht.b2,
+ OFDM_RX_FRAME_EHT_STA_RU,
+ IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B0 |
+ IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B7_B1);
+ eht->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.eht.b1,
+ OFDM_RX_FRAME_EHT_CODING_EXTRA_SYM,
+ IEEE80211_RADIOTAP_EHT_DATA0_LDPC_EXTRA_SYM_OM);
+ eht->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.eht.b1,
+ OFDM_RX_FRAME_EHT_PRE_FEC_PAD_FACTOR,
+ IEEE80211_RADIOTAP_EHT_DATA0_PRE_PADD_FACOR_OM);
+ eht->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.eht.b1,
+ OFDM_RX_FRAME_EHT_PE_DISAMBIG,
+ IEEE80211_RADIOTAP_EHT_DATA0_PE_DISAMBIGUITY_OM);
+ eht->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.eht.b1,
+ OFDM_RX_FRAME_EHT_NUM_OF_LTF_SYM,
IEEE80211_RADIOTAP_EHT_DATA0_EHT_LTF);
+ eht->data[1] |= LE32_DEC_ENC(phy_data->ntfy->sigs.eht.b2,
+ OFDM_RX_FRAME_EHT_STA_RU_P80,
+ IEEE80211_RADIOTAP_EHT_DATA1_PRIMARY_80);
+ eht->data[7] |= LE32_DEC_ENC(phy_data->ntfy->sigs.eht.b1,
+ OFDM_RX_FRAME_EHT_NUM_OF_USERS,
+ IEEE80211_RADIOTAP_EHT_DATA7_NUM_OF_NON_OFDMA_USERS);
+
+ iwl_mld_eht_decode_user_ru(phy_data, eht);
+
+ iwl_mld_eht_set_ru_alloc(rx_status,
+ le32_get_bits(phy_data->ntfy->sigs.eht.b2,
+ OFDM_RX_FRAME_EHT_STA_RU));
+}
- if (info_type == IWL_RX_PHY_INFO_TYPE_EHT_TB_EXT ||
- info_type == IWL_RX_PHY_INFO_TYPE_EHT_TB)
- iwl_mld_decode_eht_ext_tb(mld, phy_data, rx_status, eht, usig);
+static void iwl_mld_decode_eht_phy_data(struct iwl_mld_rx_phy_data *phy_data,
+ struct ieee80211_rx_status *rx_status,
+ struct ieee80211_radiotap_eht *eht)
+{
+ u32 he_type = phy_data->rate_n_flags & RATE_MCS_HE_TYPE_MSK;
- if (info_type == IWL_RX_PHY_INFO_TYPE_EHT_MU_EXT ||
- info_type == IWL_RX_PHY_INFO_TYPE_EHT_MU)
- iwl_mld_decode_eht_ext_mu(mld, phy_data, rx_status, eht, usig);
+ if (he_type == RATE_MCS_HE_TYPE_TRIG)
+ iwl_mld_decode_eht_tb(phy_data, rx_status, eht);
+ else
+ iwl_mld_decode_eht_non_tb(phy_data, rx_status, eht);
}
static void iwl_mld_rx_eht(struct iwl_mld *mld, struct sk_buff *skb,
- struct iwl_mld_rx_phy_data *phy_data,
- int queue)
+ struct iwl_mld_rx_phy_data *phy_data)
{
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_radiotap_eht *eht;
- struct ieee80211_radiotap_eht_usig *usig;
size_t eht_len = sizeof(*eht);
-
u32 rate_n_flags = phy_data->rate_n_flags;
u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
/* EHT and HE have the same values for LTF */
u8 ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN;
- u16 phy_info = phy_data->phy_info;
- u32 bw;
/* u32 for 1 user_info */
if (phy_data->with_data)
@@ -1015,41 +1106,7 @@ static void iwl_mld_rx_eht(struct iwl_mld *mld, struct sk_buff *skb,
eht = iwl_mld_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT, eht_len);
- usig = iwl_mld_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT_USIG,
- sizeof(*usig));
rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;
- usig->common |=
- cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_KNOWN);
-
- /* specific handling for 320MHz */
- bw = u32_get_bits(rate_n_flags, RATE_MCS_CHAN_WIDTH_MSK);
- if (bw == RATE_MCS_CHAN_WIDTH_320_VAL)
- bw += le32_get_bits(phy_data->data0,
- IWL_RX_PHY_DATA0_EHT_BW320_SLOT);
-
- usig->common |= cpu_to_le32
- (FIELD_PREP(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW, bw));
-
- /* report the AMPDU-EOF bit on single frames */
- if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
- rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
- rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
- if (phy_data->data0 &
- cpu_to_le32(IWL_RX_PHY_DATA0_EHT_DELIM_EOF))
- rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
- }
-
- if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD)
- iwl_mld_decode_eht_phy_data(mld, phy_data, rx_status, eht, usig);
-
-#define CHECK_TYPE(F) \
- BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA1_FORMAT_ ## F != \
- (RATE_MCS_HE_TYPE_ ## F >> RATE_MCS_HE_TYPE_POS))
-
- CHECK_TYPE(SU);
- CHECK_TYPE(EXT_SU);
- CHECK_TYPE(MU);
- CHECK_TYPE(TRIG);
switch (u32_get_bits(rate_n_flags, RATE_MCS_HE_GI_LTF_MSK)) {
case 0:
@@ -1085,20 +1142,18 @@ static void iwl_mld_rx_eht(struct iwl_mld *mld, struct sk_buff *skb,
if (ltf != IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN) {
eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_GI);
- eht->data[0] |= cpu_to_le32
- (FIELD_PREP(IEEE80211_RADIOTAP_EHT_DATA0_LTF,
- ltf) |
- FIELD_PREP(IEEE80211_RADIOTAP_EHT_DATA0_GI,
- rx_status->eht.gi));
+ eht->data[0] |= le32_encode_bits(ltf,
+ IEEE80211_RADIOTAP_EHT_DATA0_LTF) |
+ le32_encode_bits(rx_status->eht.gi,
+ IEEE80211_RADIOTAP_EHT_DATA0_GI);
}
if (!phy_data->with_data) {
eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_NSS_S |
IEEE80211_RADIOTAP_EHT_KNOWN_BEAMFORMED_S);
- eht->data[7] |=
- le32_encode_bits(le32_get_bits(phy_data->rx_vec[2],
- RX_NO_DATA_RX_VEC2_EHT_NSTS_MSK),
- IEEE80211_RADIOTAP_EHT_DATA7_NSS_S);
+ eht->data[7] |= LE32_DEC_ENC(phy_data->ntfy->sigs.eht.b1,
+ OFDM_RX_FRAME_EHT_NSTS,
+ IEEE80211_RADIOTAP_EHT_DATA7_NSS_S);
if (rate_n_flags & RATE_MCS_BF_MSK)
eht->data[7] |=
cpu_to_le32(IEEE80211_RADIOTAP_EHT_DATA7_BEAMFORMED_S);
@@ -1118,14 +1173,28 @@ static void iwl_mld_rx_eht(struct iwl_mld *mld, struct sk_buff *skb,
eht->user_info[0] |=
cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_CODING);
- eht->user_info[0] |= cpu_to_le32
- (FIELD_PREP(IEEE80211_RADIOTAP_EHT_USER_INFO_MCS,
- u32_get_bits(rate_n_flags,
- RATE_VHT_MCS_RATE_CODE_MSK)) |
- FIELD_PREP(IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_O,
- u32_get_bits(rate_n_flags,
- RATE_MCS_NSS_MSK)));
+ eht->user_info[0] |=
+ le32_encode_bits(u32_get_bits(rate_n_flags,
+ RATE_VHT_MCS_RATE_CODE_MSK),
+ IEEE80211_RADIOTAP_EHT_USER_INFO_MCS) |
+ le32_encode_bits(u32_get_bits(rate_n_flags,
+ RATE_MCS_NSS_MSK),
+ IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_O);
+ }
+
+ if (likely(!phy_data->ntfy))
+ return;
+
+ if (phy_data->with_data) {
+ eht->user_info[0] |=
+ cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID_KNOWN) |
+ LE32_DEC_ENC(phy_data->ntfy->sigs.eht.user_id,
+ OFDM_RX_FRAME_EHT_USER_FIELD_ID,
+ IEEE80211_RADIOTAP_EHT_USER_INFO_STA_ID);
}
+
+ iwl_mld_decode_eht_usig(phy_data, skb);
+ iwl_mld_decode_eht_phy_data(phy_data, rx_status, eht);
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -1148,8 +1217,9 @@ static void iwl_mld_add_rtap_sniffer_config(struct iwl_mld *mld,
radiotap->oui[0] = 0xf6;
radiotap->oui[1] = 0x54;
radiotap->oui[2] = 0x25;
- /* radiotap sniffer config sub-namespace */
+ /* Intel OUI default radiotap subtype */
radiotap->oui_subtype = 1;
+ /* Sniffer config element type */
radiotap->vendor_type = 0;
/* fill the data now */
@@ -1160,65 +1230,58 @@ static void iwl_mld_add_rtap_sniffer_config(struct iwl_mld *mld,
}
#endif
-static void iwl_mld_rx_fill_status(struct iwl_mld *mld, struct sk_buff *skb,
- struct iwl_mld_rx_phy_data *phy_data,
- struct iwl_rx_mpdu_desc *mpdu_desc,
- struct ieee80211_hdr *hdr,
- int queue)
+static void iwl_mld_add_rtap_sniffer_phy_data(struct iwl_mld *mld,
+ struct sk_buff *skb,
+ struct iwl_rx_phy_air_sniffer_ntfy *ntfy)
{
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
- u32 format = phy_data->rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
- u32 rate_n_flags = phy_data->rate_n_flags;
- u8 stbc = u32_get_bits(rate_n_flags, RATE_MCS_STBC_MSK);
- bool is_sgi = rate_n_flags & RATE_MCS_SGI_MSK;
-
- if (WARN_ON_ONCE(phy_data->with_data && (!mpdu_desc || !hdr)))
- return;
-
- /* Keep packets with CRC errors (and with overrun) for monitor mode
- * (otherwise the firmware discards them) but mark them as bad.
- */
- if (phy_data->with_data &&
- (!(mpdu_desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_CRC_OK)) ||
- !(mpdu_desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_OVERRUN_OK)))) {
- IWL_DEBUG_RX(mld, "Bad CRC or FIFO: 0x%08X.\n",
- le32_to_cpu(mpdu_desc->status));
- rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
- }
+ struct ieee80211_radiotap_vendor_content *radiotap;
+ const u16 vendor_data_len = sizeof(*ntfy);
- phy_data->info_type = IWL_RX_PHY_INFO_TYPE_NONE;
+ radiotap =
+ iwl_mld_radiotap_put_tlv(skb,
+ IEEE80211_RADIOTAP_VENDOR_NAMESPACE,
+ sizeof(*radiotap) + vendor_data_len);
- if (phy_data->with_data &&
- likely(!(phy_data->phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD))) {
- rx_status->mactime =
- le64_to_cpu(mpdu_desc->v3.tsf_on_air_rise);
+ /* Intel OUI */
+ radiotap->oui[0] = 0xf6;
+ radiotap->oui[1] = 0x54;
+ radiotap->oui[2] = 0x25;
+ /* Intel OUI default radiotap subtype */
+ radiotap->oui_subtype = 1;
+ /* PHY data element type */
+ radiotap->vendor_type = cpu_to_le16(1);
- /* TSF as indicated by the firmware is at INA time */
- rx_status->flag |= RX_FLAG_MACTIME_PLCP_START;
- } else {
- phy_data->info_type =
- le32_get_bits(phy_data->data1,
- IWL_RX_PHY_DATA1_INFO_TYPE_MASK);
- }
+ /* fill the data now */
+ memcpy(radiotap->data, ntfy, vendor_data_len);
- /* management stuff on default queue */
- if (!queue && phy_data->with_data &&
- unlikely(ieee80211_is_beacon(hdr->frame_control) ||
- ieee80211_is_probe_resp(hdr->frame_control))) {
- rx_status->boottime_ns = ktime_get_boottime_ns();
+ rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;
+}
- if (mld->scan.pass_all_sched_res == SCHED_SCAN_PASS_ALL_STATE_ENABLED)
- mld->scan.pass_all_sched_res = SCHED_SCAN_PASS_ALL_STATE_FOUND;
- }
+static void
+iwl_mld_set_rx_nonlegacy_rate_info(u32 rate_n_flags,
+ struct ieee80211_rx_status *rx_status)
+{
+ u8 stbc = u32_get_bits(rate_n_flags, RATE_MCS_STBC_MSK);
- /* set the preamble flag if appropriate */
- if (format == RATE_MCS_CCK_MSK &&
- phy_data->phy_info & IWL_RX_MPDU_PHY_SHORT_PREAMBLE)
- rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE;
+ /* NSS may be overridden by PHY ntfy with full value */
+ rx_status->nss = u32_get_bits(rate_n_flags, RATE_MCS_NSS_MSK) + 1;
+ rx_status->rate_idx = rate_n_flags & RATE_MCS_CODE_MSK;
+ rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
+ if (rate_n_flags & RATE_MCS_LDPC_MSK)
+ rx_status->enc_flags |= RX_ENC_FLAG_LDPC;
+}
- iwl_mld_fill_signal(mld, rx_status, phy_data);
+static void iwl_mld_set_rx_rate(struct iwl_mld *mld,
+ struct iwl_mld_rx_phy_data *phy_data,
+ struct ieee80211_rx_status *rx_status)
+{
+ u32 rate_n_flags = phy_data->rate_n_flags;
+ u8 stbc = u32_get_bits(rate_n_flags, RATE_MCS_STBC_MSK);
+ u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
+ bool is_sgi = rate_n_flags & RATE_MCS_SGI_MSK;
- /* This may be overridden by iwl_mld_rx_he() to HE_RU */
+ /* bandwidth may be overridden to RU by PHY ntfy */
switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {
case RATE_MCS_CHAN_WIDTH_20:
break;
@@ -1236,57 +1299,19 @@ static void iwl_mld_rx_fill_status(struct iwl_mld *mld, struct sk_buff *skb,
break;
}
- /* must be before L-SIG data */
- if (format == RATE_MCS_HE_MSK)
- iwl_mld_rx_he(mld, skb, phy_data, queue);
-
- iwl_mld_decode_lsig(skb, phy_data);
-
- rx_status->device_timestamp = phy_data->gp2_on_air_rise;
-
- /* using TLV format and must be after all fixed len fields */
- if (format == RATE_MCS_EHT_MSK)
- iwl_mld_rx_eht(mld, skb, phy_data, queue);
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
- if (unlikely(mld->monitor.on))
- iwl_mld_add_rtap_sniffer_config(mld, skb);
-#endif
-
- if (format != RATE_MCS_CCK_MSK && is_sgi)
- rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
-
- if (rate_n_flags & RATE_MCS_LDPC_MSK)
- rx_status->enc_flags |= RX_ENC_FLAG_LDPC;
-
switch (format) {
- case RATE_MCS_HT_MSK:
- rx_status->encoding = RX_ENC_HT;
- rx_status->rate_idx = RATE_HT_MCS_INDEX(rate_n_flags);
- rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
- break;
- case RATE_MCS_VHT_MSK:
- case RATE_MCS_HE_MSK:
- case RATE_MCS_EHT_MSK:
- if (format == RATE_MCS_VHT_MSK) {
- rx_status->encoding = RX_ENC_VHT;
- } else if (format == RATE_MCS_HE_MSK) {
- rx_status->encoding = RX_ENC_HE;
- rx_status->he_dcm =
- !!(rate_n_flags & RATE_HE_DUAL_CARRIER_MODE_MSK);
- } else if (format == RATE_MCS_EHT_MSK) {
- rx_status->encoding = RX_ENC_EHT;
- }
-
- rx_status->nss = u32_get_bits(rate_n_flags, RATE_MCS_NSS_MSK) + 1;
- rx_status->rate_idx = rate_n_flags & RATE_MCS_CODE_MSK;
- rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
- break;
- default: {
+ case RATE_MCS_MOD_TYPE_CCK:
+ if (phy_data->phy_info & IWL_RX_MPDU_PHY_SHORT_PREAMBLE)
+ rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE;
+ fallthrough;
+ case RATE_MCS_MOD_TYPE_LEGACY_OFDM: {
int rate =
iwl_mld_legacy_hw_idx_to_mac80211_idx(rate_n_flags,
rx_status->band);
+ /* override BW - it could be DUP and indicate the wrong BW */
+ rx_status->bw = RATE_INFO_BW_20;
+
/* valid rate */
if (rate >= 0 && rate <= 0xFF) {
rx_status->rate_idx = rate;
@@ -1296,12 +1321,91 @@ static void iwl_mld_rx_fill_status(struct iwl_mld *mld, struct sk_buff *skb,
/* invalid rate */
rx_status->rate_idx = 0;
- if (net_ratelimit())
+ /*
+ * In monitor mode we can see CCK frames on 5 or 6 GHz, usually
+ * just the (possibly malformed) PHY header by accident, since
+ * the decoder doesn't seem to turn off CCK. We cannot correctly
+ * encode the rate to mac80211 (and therefore not in radiotap)
+ * since we give the per-band index which doesn't cover those
+ * rates.
+ */
+ if (!mld->monitor.on && net_ratelimit())
IWL_ERR(mld, "invalid rate_n_flags=0x%x, band=%d\n",
rate_n_flags, rx_status->band);
break;
}
+ case RATE_MCS_MOD_TYPE_HT:
+ rx_status->encoding = RX_ENC_HT;
+ rx_status->rate_idx = RATE_HT_MCS_INDEX(rate_n_flags);
+ rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
+ break;
+ case RATE_MCS_MOD_TYPE_VHT:
+ rx_status->encoding = RX_ENC_VHT;
+ iwl_mld_set_rx_nonlegacy_rate_info(rate_n_flags, rx_status);
+ break;
+ case RATE_MCS_MOD_TYPE_HE:
+ rx_status->encoding = RX_ENC_HE;
+ rx_status->he_dcm =
+ !!(rate_n_flags & RATE_HE_DUAL_CARRIER_MODE_MSK);
+ iwl_mld_set_rx_nonlegacy_rate_info(rate_n_flags, rx_status);
+ break;
+ case RATE_MCS_MOD_TYPE_EHT:
+ rx_status->encoding = RX_ENC_EHT;
+ iwl_mld_set_rx_nonlegacy_rate_info(rate_n_flags, rx_status);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ }
+
+ if (format != RATE_MCS_MOD_TYPE_CCK && is_sgi)
+ rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
+}
+
+/* Note: hdr can be NULL */
+static void iwl_mld_rx_fill_status(struct iwl_mld *mld, int link_id,
+ struct ieee80211_hdr *hdr,
+ struct sk_buff *skb,
+ struct iwl_mld_rx_phy_data *phy_data)
+{
+ struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
+ u32 rate_n_flags = phy_data->rate_n_flags;
+ u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
+
+ iwl_mld_fill_signal(mld, link_id, hdr, rx_status, phy_data);
+
+ rx_status->device_timestamp = phy_data->gp2_on_air_rise;
+
+ iwl_mld_set_rx_rate(mld, phy_data, rx_status);
+
+ /* must be before L-SIG data (radiotap field order) */
+ if (format == RATE_MCS_MOD_TYPE_HE)
+ iwl_mld_rx_he(skb, phy_data);
+
+ iwl_mld_decode_lsig(skb, phy_data);
+
+ /* TLVs - must be after radiotap fixed fields */
+ if (format == RATE_MCS_MOD_TYPE_EHT)
+ iwl_mld_rx_eht(mld, skb, phy_data);
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ if (unlikely(mld->monitor.on)) {
+ iwl_mld_add_rtap_sniffer_config(mld, skb);
+
+ if (mld->monitor.ptp_time) {
+ u64 adj_time =
+ iwl_mld_ptp_get_adj_time(mld,
+ phy_data->gp2_on_air_rise *
+ NSEC_PER_USEC);
+
+ rx_status->mactime = div64_u64(adj_time, NSEC_PER_USEC);
+ rx_status->flag |= RX_FLAG_MACTIME_IS_RTAP_TS64;
+ rx_status->flag &= ~RX_FLAG_MACTIME;
+ }
}
+#endif
+
+ if (phy_data->ntfy)
+ iwl_mld_add_rtap_sniffer_phy_data(mld, skb, phy_data->ntfy);
}
/* iwl_mld_create_skb adds the rxb to a new skb */
@@ -1570,20 +1674,21 @@ iwl_mld_rx_with_sta(struct iwl_mld *mld, struct ieee80211_hdr *hdr,
return sta;
}
-#define KEY_IDX_LEN 2
-
static int iwl_mld_rx_mgmt_prot(struct ieee80211_sta *sta,
struct ieee80211_hdr *hdr,
struct ieee80211_rx_status *rx_status,
u32 mpdu_status,
u32 mpdu_len)
{
+ struct iwl_mld_link *link;
struct wireless_dev *wdev;
struct iwl_mld_sta *mld_sta;
struct iwl_mld_vif *mld_vif;
u8 keyidx;
struct ieee80211_key_conf *key;
const u8 *frame = (void *)hdr;
+ const u8 *mmie;
+ u8 link_id;
if ((mpdu_status & IWL_RX_MPDU_STATUS_SEC_MASK) ==
IWL_RX_MPDU_STATUS_SEC_NONE)
@@ -1616,21 +1721,30 @@ static int iwl_mld_rx_mgmt_prot(struct ieee80211_sta *sta,
return 0;
}
+ link_id = rx_status->link_valid ? rx_status->link_id : 0;
+ link = rcu_dereference(mld_vif->link[link_id]);
+ if (WARN_ON_ONCE(!link))
+ return -1;
+
/* both keys will have the same cipher and MIC length, use
* whichever one is available
*/
- key = rcu_dereference(mld_vif->bigtks[0]);
+ key = rcu_dereference(link->bigtks[0]);
if (!key) {
- key = rcu_dereference(mld_vif->bigtks[1]);
+ key = rcu_dereference(link->bigtks[1]);
if (!key)
goto report;
}
- if (mpdu_len < key->icv_len + IEEE80211_GMAC_PN_LEN + KEY_IDX_LEN)
+ /* get the real key ID */
+ if (mpdu_len < key->icv_len)
goto report;
- /* get the real key ID */
- keyidx = frame[mpdu_len - key->icv_len - IEEE80211_GMAC_PN_LEN - KEY_IDX_LEN];
+ mmie = frame + (mpdu_len - key->icv_len);
+
+ /* the position of the key_id in ieee80211_mmie_16 is the same */
+ keyidx = le16_to_cpu(((const struct ieee80211_mmie *) mmie)->key_id);
+
/* and if that's the other key, look it up */
if (keyidx != key->keyidx) {
/* shouldn't happen since firmware checked, but be safe
@@ -1639,7 +1753,7 @@ static int iwl_mld_rx_mgmt_prot(struct ieee80211_sta *sta,
if (keyidx != 6 && keyidx != 7)
return -1;
- key = rcu_dereference(mld_vif->bigtks[keyidx - 6]);
+ key = rcu_dereference(link->bigtks[keyidx - 6]);
if (!key)
goto report;
}
@@ -1712,13 +1826,36 @@ static int iwl_mld_rx_crypto(struct iwl_mld *mld,
return 0;
}
-static void iwl_mld_rx_update_ampdu_ref(struct iwl_mld *mld,
- struct iwl_mld_rx_phy_data *phy_data,
- struct ieee80211_rx_status *rx_status)
+static void iwl_mld_rx_update_ampdu_data(struct iwl_mld *mld,
+ struct iwl_mld_rx_phy_data *phy_data,
+ struct ieee80211_rx_status *rx_status)
{
+ u32 format = phy_data->rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
bool toggle_bit =
phy_data->phy_info & IWL_RX_MPDU_PHY_AMPDU_TOGGLE;
+ switch (format) {
+ case RATE_MCS_MOD_TYPE_CCK:
+ case RATE_MCS_MOD_TYPE_LEGACY_OFDM:
+ /* no aggregation possible */
+ return;
+ case RATE_MCS_MOD_TYPE_HT:
+ case RATE_MCS_MOD_TYPE_VHT:
+ /* single frames are not A-MPDU format */
+ if (!(phy_data->phy_info & IWL_RX_MPDU_PHY_AMPDU))
+ return;
+ break;
+ default:
+ /* HE/EHT/UHR have A-MPDU format for single frames */
+ if (!(phy_data->phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
+ rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
+ rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
+ if (phy_data->phy_info & IWL_RX_MPDU_PHY_EOF_INDICATION)
+ rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
+ return;
+ }
+ }
+
rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
/* Toggle is switched whenever new aggregation starts. Make
* sure ampdu_reference is never 0 so we can later use it to
@@ -1730,20 +1867,21 @@ static void iwl_mld_rx_update_ampdu_ref(struct iwl_mld *mld,
mld->monitor.ampdu_ref++;
mld->monitor.ampdu_toggle = toggle_bit;
phy_data->first_subframe = true;
+
+ /* report EOF bit on the first subframe */
+ rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
+ if (phy_data->phy_info & IWL_RX_MPDU_PHY_EOF_INDICATION)
+ rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
}
rx_status->ampdu_reference = mld->monitor.ampdu_ref;
}
static void
-iwl_mld_fill_rx_status_band_freq(struct iwl_mld_rx_phy_data *phy_data,
- struct iwl_rx_mpdu_desc *mpdu_desc,
- struct ieee80211_rx_status *rx_status)
+iwl_mld_fill_rx_status_band_freq(struct ieee80211_rx_status *rx_status,
+ u8 band, u8 channel)
{
- enum nl80211_band band;
-
- band = BAND_IN_RX_STATUS(mpdu_desc->mac_phy_idx);
rx_status->band = iwl_mld_phy_band_to_nl80211(band);
- rx_status->freq = ieee80211_channel_to_frequency(phy_data->channel,
+ rx_status->freq = ieee80211_channel_to_frequency(channel,
rx_status->band);
}
@@ -1758,11 +1896,12 @@ void iwl_mld_rx_mpdu(struct iwl_mld *mld, struct napi_struct *napi,
struct sk_buff *skb;
size_t mpdu_desc_size = sizeof(*mpdu_desc);
bool drop = false;
- u8 crypto_len = 0;
+ u8 crypto_len = 0, band, link_id;
u32 pkt_len = iwl_rx_packet_payload_len(pkt);
u32 mpdu_len;
enum iwl_mld_reorder_result reorder_res;
struct ieee80211_rx_status *rx_status;
+ unsigned int alloc_size = 128;
if (unlikely(mld->fw_status.in_hw_restart))
return;
@@ -1777,10 +1916,17 @@ void iwl_mld_rx_mpdu(struct iwl_mld *mld, struct napi_struct *napi,
"FW lied about packet len (%d)\n", pkt_len))
return;
+ iwl_mld_fill_phy_data_from_mpdu(mld, mpdu_desc, &phy_data);
+
/* Don't use dev_alloc_skb(), we'll have enough headroom once
* ieee80211_hdr pulled.
+ *
+ * For monitor mode we need more space to include the full PHY
+ * notification data.
*/
- skb = alloc_skb(128, GFP_ATOMIC);
+ if (unlikely(mld->monitor.on) && phy_data.ntfy)
+ alloc_size += sizeof(struct iwl_rx_phy_air_sniffer_ntfy);
+ skb = alloc_skb(alloc_size, GFP_ATOMIC);
if (!skb) {
IWL_ERR(mld, "alloc_skb failed\n");
return;
@@ -1788,8 +1934,6 @@ void iwl_mld_rx_mpdu(struct iwl_mld *mld, struct napi_struct *napi,
hdr = (void *)(pkt->data + mpdu_desc_size);
- iwl_mld_fill_phy_data(mpdu_desc, &phy_data);
-
if (mpdu_desc->mac_flags2 & IWL_RX_MPDU_MFLG2_PAD) {
/* If the device inserted padding it means that (it thought)
* the 802.11 header wasn't a multiple of 4 bytes long. In
@@ -1802,7 +1946,11 @@ void iwl_mld_rx_mpdu(struct iwl_mld *mld, struct napi_struct *napi,
rx_status = IEEE80211_SKB_RXCB(skb);
/* this is needed early */
- iwl_mld_fill_rx_status_band_freq(&phy_data, mpdu_desc, rx_status);
+ band = u8_get_bits(mpdu_desc->mac_phy_band,
+ IWL_RX_MPDU_MAC_PHY_BAND_BAND_MASK);
+ iwl_mld_fill_rx_status_band_freq(rx_status, band,
+ mpdu_desc->v3.channel);
+
rcu_read_lock();
@@ -1810,11 +1958,42 @@ void iwl_mld_rx_mpdu(struct iwl_mld *mld, struct napi_struct *napi,
if (drop)
goto drop;
- /* update aggregation data for monitor sake on default queue */
- if (!queue && (phy_data.phy_info & IWL_RX_MPDU_PHY_AMPDU))
- iwl_mld_rx_update_ampdu_ref(mld, &phy_data, rx_status);
+ if (unlikely(mld->monitor.on))
+ iwl_mld_rx_update_ampdu_data(mld, &phy_data, rx_status);
- iwl_mld_rx_fill_status(mld, skb, &phy_data, mpdu_desc, hdr, queue);
+ /* Keep packets with CRC errors (and with overrun) for monitor mode
+ * (otherwise the firmware discards them) but mark them as bad.
+ */
+ if (!(mpdu_desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_CRC_OK)) ||
+ !(mpdu_desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_OVERRUN_OK))) {
+ IWL_DEBUG_RX(mld, "Bad CRC or FIFO: 0x%08X.\n",
+ le32_to_cpu(mpdu_desc->status));
+ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+ }
+
+ if (likely(!(phy_data.phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD))) {
+ rx_status->mactime =
+ le64_to_cpu(mpdu_desc->v3.tsf_on_air_rise);
+
+ /* TSF as indicated by the firmware is at INA time */
+ rx_status->flag |= RX_FLAG_MACTIME_PLCP_START;
+ }
+
+ /* management stuff on default queue */
+ if (!queue && unlikely(ieee80211_is_beacon(hdr->frame_control) ||
+ ieee80211_is_probe_resp(hdr->frame_control))) {
+ rx_status->boottime_ns = ktime_get_boottime_ns();
+
+ if (mld->scan.pass_all_sched_res ==
+ SCHED_SCAN_PASS_ALL_STATE_ENABLED)
+ mld->scan.pass_all_sched_res =
+ SCHED_SCAN_PASS_ALL_STATE_FOUND;
+ }
+
+ link_id = u8_get_bits(mpdu_desc->mac_phy_band,
+ IWL_RX_MPDU_MAC_PHY_BAND_LINK_MASK);
+
+ iwl_mld_rx_fill_status(mld, link_id, hdr, skb, &phy_data);
if (iwl_mld_rx_crypto(mld, sta, hdr, rx_status, mpdu_desc, queue,
le32_to_cpu(pkt->len_n_flags), &crypto_len))
@@ -1857,7 +2036,7 @@ void iwl_mld_sync_rx_queues(struct iwl_mld *mld,
enum iwl_mld_internal_rxq_notif_type type,
const void *notif_payload, u32 notif_payload_size)
{
- u8 num_rx_queues = mld->trans->num_rx_queues;
+ u8 num_rx_queues = mld->trans->info.num_rxqs;
struct {
struct iwl_rxq_sync_cmd sync_cmd;
struct iwl_mld_internal_rxq_notif notif;
@@ -1948,83 +2127,65 @@ void iwl_mld_handle_rx_queues_sync_notif(struct iwl_mld *mld,
wake_up(&mld->rxq_sync.waitq);
}
-void iwl_mld_rx_monitor_no_data(struct iwl_mld *mld, struct napi_struct *napi,
- struct iwl_rx_packet *pkt, int queue)
+static void iwl_mld_no_data_rx(struct iwl_mld *mld,
+ struct napi_struct *napi,
+ struct iwl_rx_phy_air_sniffer_ntfy *ntfy)
{
- struct iwl_rx_no_data_ver_3 *desc;
- struct iwl_mld_rx_phy_data phy_data;
struct ieee80211_rx_status *rx_status;
+ struct iwl_mld_rx_phy_data phy_data = {
+ .ntfy = ntfy,
+ .phy_info = 0, /* short preamble set below */
+ .rate_n_flags = le32_to_cpu(ntfy->rate),
+ .gp2_on_air_rise = le32_to_cpu(ntfy->on_air_rise_time),
+ .energy_a = ntfy->rssi_a,
+ .energy_b = ntfy->rssi_b,
+ };
+ u32 format = phy_data.rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
struct sk_buff *skb;
- u32 format, rssi;
-
- if (unlikely(mld->fw_status.in_hw_restart))
- return;
- if (IWL_FW_CHECK(mld, iwl_rx_packet_payload_len(pkt) < sizeof(*desc),
- "Bad RX_NO_DATA_NOTIF size (%d)\n",
- iwl_rx_packet_payload_len(pkt)))
+ skb = alloc_skb(128 + sizeof(struct iwl_rx_phy_air_sniffer_ntfy),
+ GFP_ATOMIC);
+ if (!skb)
return;
- desc = (void *)pkt->data;
-
- rssi = le32_to_cpu(desc->rssi);
- phy_data.energy_a = u32_get_bits(rssi, RX_NO_DATA_CHAIN_A_MSK);
- phy_data.energy_b = u32_get_bits(rssi, RX_NO_DATA_CHAIN_B_MSK);
- phy_data.channel = u32_get_bits(rssi, RX_NO_DATA_CHANNEL_MSK);
- phy_data.data0 = desc->phy_info[0];
- phy_data.data1 = desc->phy_info[1];
- phy_data.phy_info = IWL_RX_MPDU_PHY_TSF_OVERLOAD;
- phy_data.gp2_on_air_rise = le32_to_cpu(desc->on_air_rise_time);
- phy_data.rate_n_flags = le32_to_cpu(desc->rate);
- phy_data.with_data = false;
-
- BUILD_BUG_ON(sizeof(phy_data.rx_vec) != sizeof(desc->rx_vec));
- memcpy(phy_data.rx_vec, desc->rx_vec, sizeof(phy_data.rx_vec));
-
- format = phy_data.rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
-
- /* Don't use dev_alloc_skb(), we'll have enough headroom once
- * ieee80211_hdr pulled.
- */
- skb = alloc_skb(128, GFP_ATOMIC);
- if (!skb) {
- IWL_ERR(mld, "alloc_skb failed\n");
- return;
- }
-
rx_status = IEEE80211_SKB_RXCB(skb);
/* 0-length PSDU */
rx_status->flag |= RX_FLAG_NO_PSDU;
- /* mark as failed PLCP on any errors to skip checks in mac80211 */
- if (le32_get_bits(desc->info, RX_NO_DATA_INFO_ERR_MSK) !=
- RX_NO_DATA_INFO_ERR_NONE)
- rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC;
-
- switch (le32_get_bits(desc->info, RX_NO_DATA_INFO_TYPE_MSK)) {
- case RX_NO_DATA_INFO_TYPE_NDP:
+ switch (ntfy->status) {
+ case IWL_SNIF_STAT_PLCP_RX_OK:
+ /* we only get here with sounding PPDUs */
rx_status->zero_length_psdu_type =
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING;
break;
- case RX_NO_DATA_INFO_TYPE_MU_UNMATCHED:
- case RX_NO_DATA_INFO_TYPE_TB_UNMATCHED:
+ case IWL_SNIF_STAT_AID_NOT_FOR_US:
rx_status->zero_length_psdu_type =
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED;
break;
+ case IWL_SNIF_STAT_PLCP_RX_LSIG_ERR:
+ case IWL_SNIF_STAT_PLCP_RX_SIGA_ERR:
+ case IWL_SNIF_STAT_PLCP_RX_SIGB_ERR:
+ case IWL_SNIF_STAT_UNKNOWN_ERROR:
default:
+ rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC;
+ fallthrough;
+ case IWL_SNIF_STAT_UNEXPECTED_TB:
+ case IWL_SNIF_STAT_UNSUPPORTED_RATE:
rx_status->zero_length_psdu_type =
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_VENDOR;
- break;
+ /* we could include the real reason in a vendor TLV */
}
- rx_status->band = phy_data.channel > 14 ? NL80211_BAND_5GHZ :
- NL80211_BAND_2GHZ;
+ if (format == RATE_MCS_MOD_TYPE_CCK &&
+ ntfy->legacy_sig.cck & cpu_to_le32(CCK_CRFR_SHORT_PREAMBLE))
+ phy_data.phy_info |= IWL_RX_MPDU_PHY_SHORT_PREAMBLE;
- rx_status->freq = ieee80211_channel_to_frequency(phy_data.channel,
- rx_status->band);
+ iwl_mld_fill_rx_status_band_freq(IEEE80211_SKB_RXCB(skb),
+ ntfy->band, ntfy->channel);
- iwl_mld_rx_fill_status(mld, skb, &phy_data, NULL, NULL, queue);
+ /* link ID is ignored for NULL header */
+ iwl_mld_rx_fill_status(mld, -1, NULL, skb, &phy_data);
/* No more radiotap info should be added after this point.
* Mark it as mac header for upper layers to know where
@@ -2032,29 +2193,72 @@ void iwl_mld_rx_monitor_no_data(struct iwl_mld *mld, struct napi_struct *napi,
*/
skb_set_mac_header(skb, skb->len);
- /* Override the nss from the rx_vec since the rate_n_flags has
- * only 1 bit for the nss which gives a max of 2 ss but there
- * may be up to 8 spatial streams.
- */
- switch (format) {
- case RATE_MCS_VHT_MSK:
- rx_status->nss =
- le32_get_bits(desc->rx_vec[0],
- RX_NO_DATA_RX_VEC0_VHT_NSTS_MSK) + 1;
- break;
- case RATE_MCS_HE_MSK:
- rx_status->nss =
- le32_get_bits(desc->rx_vec[0],
- RX_NO_DATA_RX_VEC0_HE_NSTS_MSK) + 1;
- break;
- case RATE_MCS_EHT_MSK:
- rx_status->nss =
- le32_get_bits(desc->rx_vec[2],
- RX_NO_DATA_RX_VEC2_EHT_NSTS_MSK) + 1;
- }
-
/* pass the packet to mac80211 */
rcu_read_lock();
ieee80211_rx_napi(mld->hw, NULL, skb, napi);
rcu_read_unlock();
}
+
+void iwl_mld_handle_phy_air_sniffer_notif(struct iwl_mld *mld,
+ struct napi_struct *napi,
+ struct iwl_rx_packet *pkt)
+{
+ struct iwl_rx_phy_air_sniffer_ntfy *ntfy = (void *)pkt->data;
+ bool is_ndp = false;
+ u32 he_type;
+
+ if (IWL_FW_CHECK(mld, iwl_rx_packet_payload_len(pkt) < sizeof(*ntfy),
+ "invalid air sniffer notification size\n"))
+ return;
+
+ /* check if there's an old one to release as errored */
+ if (mld->monitor.phy.valid && !mld->monitor.phy.used) {
+ /* didn't capture data, so override status */
+ mld->monitor.phy.data.status = IWL_SNIF_STAT_AID_NOT_FOR_US;
+ iwl_mld_no_data_rx(mld, napi, &mld->monitor.phy.data);
+ }
+
+ /* old data is no longer valid now */
+ mld->monitor.phy.valid = false;
+
+ he_type = le32_to_cpu(ntfy->rate) & RATE_MCS_HE_TYPE_MSK;
+
+ switch (le32_to_cpu(ntfy->rate) & RATE_MCS_MOD_TYPE_MSK) {
+ case RATE_MCS_MOD_TYPE_HT:
+ is_ndp = !le32_get_bits(ntfy->sigs.ht.a1,
+ OFDM_RX_FRAME_HT_LENGTH);
+ break;
+ case RATE_MCS_MOD_TYPE_VHT:
+ is_ndp = le32_get_bits(ntfy->sigs.vht.a0,
+ OFDM_RX_FRAME_VHT_NUM_OF_DATA_SYM_VALID) &&
+ !le32_get_bits(ntfy->sigs.vht.a0,
+ OFDM_RX_FRAME_VHT_NUM_OF_DATA_SYM);
+ break;
+ case RATE_MCS_MOD_TYPE_HE:
+ if (he_type == RATE_MCS_HE_TYPE_TRIG)
+ break;
+ is_ndp = le32_get_bits(ntfy->sigs.he.a3,
+ OFDM_RX_FRAME_HE_NUM_OF_DATA_SYM_VALID) &&
+ !le32_get_bits(ntfy->sigs.he.a3,
+ OFDM_RX_FRAME_HE_NUM_OF_DATA_SYM);
+ break;
+ case RATE_MCS_MOD_TYPE_EHT:
+ if (he_type == RATE_MCS_HE_TYPE_TRIG)
+ break;
+ is_ndp = le32_get_bits(ntfy->sigs.eht.sig2,
+ OFDM_RX_FRAME_EHT_NUM_OF_DATA_SYM_VALID) &&
+ !le32_get_bits(ntfy->sigs.eht.sig2,
+ OFDM_RX_FRAME_EHT_NUM_OF_DATA_SYM);
+ break;
+ }
+
+ if (ntfy->status != IWL_SNIF_STAT_PLCP_RX_OK || is_ndp) {
+ iwl_mld_no_data_rx(mld, napi, ntfy);
+ return;
+ }
+
+ /* hang on to it for the RX_MPDU data packet(s) */
+ mld->monitor.phy.data = *ntfy;
+ mld->monitor.phy.valid = true;
+ mld->monitor.phy.used = false;
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.h b/drivers/net/wireless/intel/iwlwifi/mld/rx.h
index 2beabd7e70b1..09dddbd40f55 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/rx.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.h
@@ -66,7 +66,8 @@ void iwl_mld_pass_packet_to_mac80211(struct iwl_mld *mld,
struct sk_buff *skb, int queue,
struct ieee80211_sta *sta);
-void iwl_mld_rx_monitor_no_data(struct iwl_mld *mld, struct napi_struct *napi,
- struct iwl_rx_packet *pkt, int queue);
+void iwl_mld_handle_phy_air_sniffer_notif(struct iwl_mld *mld,
+ struct napi_struct *napi,
+ struct iwl_rx_packet *pkt);
#endif /* __iwl_mld_agg_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/scan.c b/drivers/net/wireless/intel/iwlwifi/mld/scan.c
index 7ec04318ec2f..fd1022ddc912 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/scan.c
@@ -4,6 +4,8 @@
*/
#include <linux/crc32.h>
+#include "iwl-utils.h"
+
#include "mld.h"
#include "scan.h"
#include "hcmd.h"
@@ -359,7 +361,7 @@ iwl_mld_scan_fits(struct iwl_mld *mld, int n_ssids,
struct ieee80211_scan_ies *ies, int n_channels)
{
return ((n_ssids <= PROBE_OPTION_MAX) &&
- (n_channels <= mld->fw->ucode_capa.n_scan_channels) &
+ (n_channels <= mld->fw->ucode_capa.n_scan_channels) &&
(ies->common_ie_len + ies->len[NL80211_BAND_2GHZ] +
ies->len[NL80211_BAND_5GHZ] + ies->len[NL80211_BAND_6GHZ] <=
iwl_mld_scan_max_template_size()));
@@ -482,7 +484,9 @@ iwl_mld_scan_get_cmd_gen_flags(struct iwl_mld *mld,
static u8
iwl_mld_scan_get_cmd_gen_flags2(struct iwl_mld *mld,
struct iwl_mld_scan_params *params,
- struct ieee80211_vif *vif, u16 gen_flags)
+ struct ieee80211_vif *vif,
+ enum iwl_mld_scan_status scan_status,
+ u16 gen_flags)
{
u8 flags = 0;
@@ -494,6 +498,15 @@ iwl_mld_scan_get_cmd_gen_flags2(struct iwl_mld *mld,
if (params->scan_6ghz)
flags |= IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_DONT_TOGGLE_ANT;
+ /* For AP interfaces, request survey data for regular scans and if
+ * it is supported. For non-AP interfaces, EBS will be enabled and
+ * the results may be missing information for some channels.
+ */
+ if (scan_status == IWL_MLD_SCAN_REGULAR &&
+ ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_AP &&
+ gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE)
+ flags |= IWL_UMAC_SCAN_GEN_FLAGS2_COLLECT_CHANNEL_STATS;
+
return flags;
}
@@ -544,6 +557,7 @@ iwl_mld_scan_cmd_set_gen_params(struct iwl_mld *mld,
u16 gen_flags = iwl_mld_scan_get_cmd_gen_flags(mld, params, vif,
scan_status);
u8 gen_flags2 = iwl_mld_scan_get_cmd_gen_flags2(mld, params, vif,
+ scan_status,
gen_flags);
IWL_DEBUG_SCAN(mld, "General: flags=0x%x, flags2=0x%x\n",
@@ -1752,6 +1766,15 @@ int iwl_mld_regular_scan_start(struct iwl_mld *mld, struct ieee80211_vif *vif,
struct cfg80211_scan_request *req,
struct ieee80211_scan_ies *ies)
{
+ /* Clear survey data when starting the first part of a regular scan */
+ if (req->first_part && mld->channel_survey)
+ memset(mld->channel_survey->channels, 0,
+ sizeof(mld->channel_survey->channels[0]) *
+ mld->channel_survey->n_channels);
+
+ if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
+ iwl_mld_emlsr_block_tmp_non_bss(mld);
+
return _iwl_mld_single_scan_start(mld, vif, req, ies,
IWL_MLD_SCAN_REGULAR);
}
@@ -1800,17 +1823,20 @@ static void iwl_mld_int_mlo_scan_start(struct iwl_mld *mld,
IWL_DEBUG_SCAN(mld, "Internal MLO scan: ret=%d\n", ret);
}
+#define IWL_MLD_MLO_SCAN_BLOCKOUT_TIME 5 /* seconds */
+
void iwl_mld_int_mlo_scan(struct iwl_mld *mld, struct ieee80211_vif *vif)
{
struct ieee80211_channel *channels[IEEE80211_MLD_MAX_NUM_LINKS];
+ struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
unsigned long usable_links = ieee80211_vif_usable_links(vif);
size_t n_channels = 0;
u8 link_id;
lockdep_assert_wiphy(mld->wiphy);
- if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif) ||
- hweight16(vif->valid_links) == 1)
+ if (!IWL_MLD_AUTO_EML_ENABLE || !vif->cfg.assoc ||
+ !ieee80211_vif_is_mld(vif) || hweight16(vif->valid_links) == 1)
return;
if (mld->scan.status & IWL_MLD_SCAN_INT_MLO) {
@@ -1818,6 +1844,15 @@ void iwl_mld_int_mlo_scan(struct iwl_mld *mld, struct ieee80211_vif *vif)
return;
}
+ if (mld_vif->last_link_activation_time > ktime_get_boottime_seconds() -
+ IWL_MLD_MLO_SCAN_BLOCKOUT_TIME) {
+ /* timing doesn't matter much, so use the blockout time */
+ wiphy_delayed_work_queue(mld->wiphy,
+ &mld_vif->mlo_scan_start_wk,
+ IWL_MLD_MLO_SCAN_BLOCKOUT_TIME);
+ return;
+ }
+
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
struct ieee80211_bss_conf *link_conf =
link_conf_dereference_check(vif, link_id);
@@ -1920,6 +1955,9 @@ void iwl_mld_handle_scan_complete_notif(struct iwl_mld *mld,
IWL_DEBUG_SCAN(mld, "Scan link is no longer valid\n");
ieee80211_scan_completed(mld->hw, &info);
+
+ /* Scan is over, we can check again the tpt counters */
+ iwl_mld_stop_ignoring_tpt_updates(mld);
} else if (mld->scan.uid_status[uid] == IWL_MLD_SCAN_SCHED) {
ieee80211_sched_scan_stopped(mld->hw);
mld->scan.pass_all_sched_res = SCHED_SCAN_PASS_ALL_STATE_DISABLED;
@@ -2006,3 +2044,136 @@ int iwl_mld_alloc_scan_cmd(struct iwl_mld *mld)
return 0;
}
+
+static int iwl_mld_chanidx_from_phy(struct iwl_mld *mld,
+ enum nl80211_band band,
+ u16 phy_chan_num)
+{
+ struct ieee80211_supported_band *sband = mld->wiphy->bands[band];
+
+ if (WARN_ON_ONCE(!sband))
+ return -EINVAL;
+
+ for (int chan_idx = 0; chan_idx < sband->n_channels; chan_idx++) {
+ struct ieee80211_channel *channel = &sband->channels[chan_idx];
+
+ if (channel->hw_value == phy_chan_num)
+ return chan_idx;
+ }
+
+ return -EINVAL;
+}
+
+void iwl_mld_handle_channel_survey_notif(struct iwl_mld *mld,
+ struct iwl_rx_packet *pkt)
+{
+ const struct iwl_umac_scan_channel_survey_notif *notif =
+ (void *)pkt->data;
+ struct iwl_mld_survey_channel *info;
+ enum nl80211_band band;
+ int chan_idx;
+
+ if (!mld->channel_survey) {
+ size_t n_channels = 0;
+
+ for (band = 0; band < NUM_NL80211_BANDS; band++) {
+ if (!mld->wiphy->bands[band])
+ continue;
+
+ n_channels += mld->wiphy->bands[band]->n_channels;
+ }
+
+ mld->channel_survey = kzalloc(struct_size(mld->channel_survey,
+ channels, n_channels),
+ GFP_KERNEL);
+
+ if (!mld->channel_survey)
+ return;
+
+ mld->channel_survey->n_channels = n_channels;
+ n_channels = 0;
+ for (band = 0; band < NUM_NL80211_BANDS; band++) {
+ if (!mld->wiphy->bands[band])
+ continue;
+
+ mld->channel_survey->bands[band] =
+ &mld->channel_survey->channels[n_channels];
+ n_channels += mld->wiphy->bands[band]->n_channels;
+ }
+ }
+
+ band = iwl_mld_phy_band_to_nl80211(le32_to_cpu(notif->band));
+ chan_idx = iwl_mld_chanidx_from_phy(mld, band,
+ le32_to_cpu(notif->channel));
+ if (WARN_ON_ONCE(chan_idx < 0))
+ return;
+
+ IWL_DEBUG_SCAN(mld, "channel survey received for freq %d\n",
+ mld->wiphy->bands[band]->channels[chan_idx].center_freq);
+
+ info = &mld->channel_survey->bands[band][chan_idx];
+
+ /* Times are all in ms */
+ info->time = le32_to_cpu(notif->active_time);
+ info->time_busy = le32_to_cpu(notif->busy_time);
+ info->noise =
+ iwl_average_neg_dbm(notif->noise, ARRAY_SIZE(notif->noise));
+}
+
+int iwl_mld_mac80211_get_survey(struct ieee80211_hw *hw, int idx,
+ struct survey_info *survey)
+{
+ struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
+ int curr_idx = 0;
+
+ if (!mld->channel_survey)
+ return -ENOENT;
+
+ /* Iterate bands/channels to find the requested index.
+ * Logically this returns the entry with index "idx" from a flattened
+ * survey result array that only contains channels with information.
+ * The current index into this flattened array is tracked in curr_idx.
+ */
+ for (enum nl80211_band band = 0; band < NUM_NL80211_BANDS; band++) {
+ struct ieee80211_supported_band *sband =
+ mld->wiphy->bands[band];
+
+ if (!sband)
+ continue;
+
+ for (int per_band_idx = 0;
+ per_band_idx < sband->n_channels;
+ per_band_idx++) {
+ struct iwl_mld_survey_channel *info =
+ &mld->channel_survey->bands[band][per_band_idx];
+
+ /* Skip entry entirely, it was not reported/scanned,
+ * do not increase curr_idx for this entry.
+ */
+ if (!info->time)
+ continue;
+
+ /* Search did not reach the requested entry yet,
+ * increment curr_idx and continue.
+ */
+ if (idx != curr_idx) {
+ curr_idx++;
+ continue;
+ }
+
+ /* Found (the next) channel to report */
+ survey->channel = &sband->channels[per_band_idx];
+ survey->filled = SURVEY_INFO_TIME |
+ SURVEY_INFO_TIME_BUSY;
+ survey->time = info->time;
+ survey->time_busy = info->time_busy;
+ survey->noise = info->noise;
+ if (survey->noise < 0)
+ survey->filled |= SURVEY_INFO_NOISE_DBM;
+
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/scan.h b/drivers/net/wireless/intel/iwlwifi/mld/scan.h
index 3ae940d55065..69110f0cfc8e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/scan.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/scan.h
@@ -30,6 +30,12 @@ void iwl_mld_handle_match_found_notif(struct iwl_mld *mld,
void iwl_mld_handle_scan_complete_notif(struct iwl_mld *mld,
struct iwl_rx_packet *pkt);
+int iwl_mld_mac80211_get_survey(struct ieee80211_hw *hw, int idx,
+ struct survey_info *survey);
+
+void iwl_mld_handle_channel_survey_notif(struct iwl_mld *mld,
+ struct iwl_rx_packet *pkt);
+
#define WFA_TPC_IE_LEN 9
static inline int iwl_mld_scan_max_template_size(void)
@@ -130,7 +136,38 @@ struct iwl_mld_scan {
void *cmd;
unsigned long last_6ghz_passive_jiffies;
unsigned long last_start_time_jiffies;
- unsigned long last_mlo_scan_time;
+ u64 last_mlo_scan_time;
+};
+
+/**
+ * struct iwl_mld_survey_channel - per-channel survey information
+ *
+ * Driver version of &struct survey_info with just the data we want to report.
+ *
+ * @time: time in ms the radio was on the channel
+ * @time_busy: time in ms the channel was sensed busy
+ * @noise: channel noise in dBm
+ */
+struct iwl_mld_survey_channel {
+ u32 time;
+ u32 time_busy;
+ s8 noise;
+};
+
+/**
+ * struct iwl_mld_survey - survey information
+ *
+ * Survey information for all available channels.
+ *
+ * @bands: per-band array for per-channel survey data, points into @channels
+ * @n_channels: Number of @channels entries that are allocated
+ * @channels: per-channel information
+ */
+struct iwl_mld_survey {
+ struct iwl_mld_survey_channel *bands[NUM_NL80211_BANDS];
+
+ int n_channels;
+ struct iwl_mld_survey_channel channels[] __counted_by(n_channels);
};
#endif /* __iwl_mld_scan_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/sta.c b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
index 332a7aecec2d..61ecc33116cf 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
@@ -660,7 +660,7 @@ iwl_mld_alloc_dup_data(struct iwl_mld *mld, struct iwl_mld_sta *mld_sta)
if (mld->fw_status.in_hw_restart)
return 0;
- dup_data = kcalloc(mld->trans->num_rx_queues, sizeof(*dup_data),
+ dup_data = kcalloc(mld->trans->info.num_rxqs, sizeof(*dup_data),
GFP_KERNEL);
if (!dup_data)
return -ENOMEM;
@@ -673,7 +673,7 @@ iwl_mld_alloc_dup_data(struct iwl_mld *mld, struct iwl_mld_sta *mld_sta)
* This thus allows receiving a packet with seqno 0 and the
* retry bit set as the very first packet on a new TID.
*/
- for (int q = 0; q < mld->trans->num_rx_queues; q++)
+ for (int q = 0; q < mld->trans->info.num_rxqs; q++)
memset(dup_data[q].last_seq, 0xff,
sizeof(dup_data[q].last_seq));
mld_sta->dup_data = dup_data;
@@ -695,13 +695,13 @@ static void iwl_mld_alloc_mpdu_counters(struct iwl_mld *mld,
sta->tdls || !ieee80211_vif_is_mld(vif))
return;
- mld_sta->mpdu_counters = kcalloc(mld->trans->num_rx_queues,
+ mld_sta->mpdu_counters = kcalloc(mld->trans->info.num_rxqs,
sizeof(*mld_sta->mpdu_counters),
GFP_KERNEL);
if (!mld_sta->mpdu_counters)
return;
- for (int q = 0; q < mld->trans->num_rx_queues; q++)
+ for (int q = 0; q < mld->trans->info.num_rxqs; q++)
spin_lock_init(&mld_sta->mpdu_counters[q].lock);
}
@@ -890,7 +890,7 @@ static void iwl_mld_count_mpdu(struct ieee80211_link_sta *link_sta, int queue,
sizeof(queue_counter->per_link));
queue_counter->window_start_time = jiffies;
- IWL_DEBUG_INFO(mld, "MPDU counters are cleared\n");
+ IWL_DEBUG_EHT(mld, "MPDU counters are cleared\n");
}
link_counter = &queue_counter->per_link[mld_link->fw_id];
@@ -947,7 +947,7 @@ static int iwl_mld_allocate_internal_txq(struct iwl_mld *mld,
int queue, size;
size = max_t(u32, IWL_MGMT_QUEUE_SIZE,
- mld->trans->cfg->min_txq_size);
+ mld->trans->mac_cfg->base->min_txq_size);
queue = iwl_trans_txq_alloc(mld->trans, 0, sta_mask, tid, size,
IWL_WATCHDOG_DISABLED);
@@ -1087,6 +1087,24 @@ int iwl_mld_add_aux_sta(struct iwl_mld *mld,
0, NULL, IWL_MAX_TID_COUNT);
}
+int iwl_mld_add_mon_sta(struct iwl_mld *mld,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link)
+{
+ struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link);
+
+ if (WARN_ON(!mld_link))
+ return -EINVAL;
+
+ if (WARN_ON(vif->type != NL80211_IFTYPE_MONITOR))
+ return -EINVAL;
+
+ return iwl_mld_add_internal_sta(mld, &mld_link->mon_sta,
+ STATION_TYPE_BCAST_MGMT,
+ mld_link->fw_id, NULL,
+ IWL_MAX_TID_COUNT);
+}
+
static void iwl_mld_remove_internal_sta(struct iwl_mld *mld,
struct iwl_mld_int_sta *internal_sta,
bool flush, u8 tid)
@@ -1140,6 +1158,19 @@ void iwl_mld_remove_mcast_sta(struct iwl_mld *mld,
}
void iwl_mld_remove_aux_sta(struct iwl_mld *mld,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
+
+ if (WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE &&
+ vif->type != NL80211_IFTYPE_STATION))
+ return;
+
+ iwl_mld_remove_internal_sta(mld, &mld_vif->aux_sta, false,
+ IWL_MAX_TID_COUNT);
+}
+
+void iwl_mld_remove_mon_sta(struct iwl_mld *mld,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link)
{
@@ -1148,11 +1179,10 @@ void iwl_mld_remove_aux_sta(struct iwl_mld *mld,
if (WARN_ON(!mld_link))
return;
- /* TODO: Hotspot 2.0 */
- if (WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE))
+ if (WARN_ON(vif->type != NL80211_IFTYPE_MONITOR))
return;
- iwl_mld_remove_internal_sta(mld, &mld_link->aux_sta, false,
+ iwl_mld_remove_internal_sta(mld, &mld_link->mon_sta, false,
IWL_MAX_TID_COUNT);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/sta.h b/drivers/net/wireless/intel/iwlwifi/mld/sta.h
index ddcffd7b9fde..1897b121aae2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/sta.h
@@ -247,6 +247,10 @@ int iwl_mld_add_mcast_sta(struct iwl_mld *mld,
int iwl_mld_add_aux_sta(struct iwl_mld *mld,
struct iwl_mld_int_sta *internal_sta);
+int iwl_mld_add_mon_sta(struct iwl_mld *mld,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link);
+
void iwl_mld_remove_bcast_sta(struct iwl_mld *mld,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link);
@@ -256,6 +260,9 @@ void iwl_mld_remove_mcast_sta(struct iwl_mld *mld,
struct ieee80211_bss_conf *link);
void iwl_mld_remove_aux_sta(struct iwl_mld *mld,
+ struct ieee80211_vif *vif);
+
+void iwl_mld_remove_mon_sta(struct iwl_mld *mld,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/stats.c b/drivers/net/wireless/intel/iwlwifi/mld/stats.c
index 0715bbc31031..7b8709716324 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/stats.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/stats.c
@@ -191,11 +191,12 @@ static void iwl_mld_sta_stats_fill_txrate(struct iwl_mld_sta *mld_sta,
break;
}
- if (format == RATE_MCS_CCK_MSK || format == RATE_MCS_LEGACY_OFDM_MSK) {
+ if (format == RATE_MCS_MOD_TYPE_CCK ||
+ format == RATE_MCS_MOD_TYPE_LEGACY_OFDM) {
int rate = u32_get_bits(rate_n_flags, RATE_LEGACY_RATE_MSK);
/* add the offset needed to get to the legacy ofdm indices */
- if (format == RATE_MCS_LEGACY_OFDM_MSK)
+ if (format == RATE_MCS_MOD_TYPE_LEGACY_OFDM)
rate += IWL_FIRST_OFDM_RATE;
switch (rate) {
@@ -240,7 +241,7 @@ static void iwl_mld_sta_stats_fill_txrate(struct iwl_mld_sta *mld_sta,
rinfo->nss = u32_get_bits(rate_n_flags, RATE_MCS_NSS_MSK) + 1;
- if (format == RATE_MCS_HT_MSK)
+ if (format == RATE_MCS_MOD_TYPE_HT)
rinfo->mcs = RATE_HT_MCS_INDEX(rate_n_flags);
else
rinfo->mcs = u32_get_bits(rate_n_flags, RATE_MCS_CODE_MSK);
@@ -249,10 +250,10 @@ static void iwl_mld_sta_stats_fill_txrate(struct iwl_mld_sta *mld_sta,
rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
switch (format) {
- case RATE_MCS_EHT_MSK:
+ case RATE_MCS_MOD_TYPE_EHT:
rinfo->flags |= RATE_INFO_FLAGS_EHT_MCS;
break;
- case RATE_MCS_HE_MSK:
+ case RATE_MCS_MOD_TYPE_HE:
gi_ltf = u32_get_bits(rate_n_flags, RATE_MCS_HE_GI_LTF_MSK);
rinfo->flags |= RATE_INFO_FLAGS_HE_MCS;
@@ -293,10 +294,10 @@ static void iwl_mld_sta_stats_fill_txrate(struct iwl_mld_sta *mld_sta,
if (rate_n_flags & RATE_HE_DUAL_CARRIER_MODE_MSK)
rinfo->he_dcm = 1;
break;
- case RATE_MCS_HT_MSK:
+ case RATE_MCS_MOD_TYPE_HT:
rinfo->flags |= RATE_INFO_FLAGS_MCS;
break;
- case RATE_MCS_VHT_MSK:
+ case RATE_MCS_MOD_TYPE_VHT:
rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
break;
}
@@ -378,11 +379,14 @@ static void iwl_mld_update_link_sig(struct ieee80211_vif *vif, int sig,
/* TODO: task=statistics handle CQM notifications */
- if (sig < IWL_MLD_LOW_RSSI_MLO_SCAN_THRESH)
- iwl_mld_int_mlo_scan(mld, vif);
-
- if (!iwl_mld_emlsr_active(vif))
+ if (!iwl_mld_emlsr_active(vif)) {
+ /* We're not in EMLSR and our signal is bad,
+ * try to switch link maybe. EMLSR will be handled below.
+ */
+ if (sig < IWL_MLD_LOW_RSSI_MLO_SCAN_THRESH)
+ iwl_mld_int_mlo_scan(mld, vif);
return;
+ }
/* We are in EMLSR, check if we need to exit */
exit_emlsr_thresh =
@@ -467,12 +471,18 @@ static void iwl_mld_fill_chanctx_stats(struct ieee80211_hw *hw,
old_load = phy->avg_channel_load_not_by_us;
new_load = le32_to_cpu(per_phy[phy->fw_id].channel_load_not_by_us);
- if (IWL_FW_CHECK(phy->mld, new_load > 100, "Invalid channel load %u\n",
- new_load))
+
+ if (IWL_FW_CHECK(phy->mld,
+ new_load != IWL_STATS_UNKNOWN_CHANNEL_LOAD &&
+ new_load > 100,
+ "Invalid channel load %u\n", new_load))
return;
- /* give a weight of 0.5 for the old value */
- phy->avg_channel_load_not_by_us = (new_load >> 1) + (old_load >> 1);
+ if (new_load != IWL_STATS_UNKNOWN_CHANNEL_LOAD) {
+ /* update giving a weight of 0.5 for the old value */
+ phy->avg_channel_load_not_by_us = (new_load >> 1) +
+ (old_load >> 1);
+ }
iwl_mld_emlsr_check_chan_load(hw, phy, old_load);
}
@@ -501,8 +511,6 @@ void iwl_mld_handle_stats_oper_notif(struct iwl_mld *mld,
iwl_mld_process_per_link_stats(mld, stats->per_link, curr_ts_usec);
iwl_mld_process_per_sta_stats(mld, stats->per_sta);
iwl_mld_process_per_phy_stats(mld, stats->per_phy);
-
- iwl_mld_check_omi_bw_reduction(mld);
}
void iwl_mld_handle_stats_oper_part1_notif(struct iwl_mld *mld,
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/agg.c b/drivers/net/wireless/intel/iwlwifi/mld/tests/agg.c
index 1fd664be1a7c..29b0248cec3d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tests/agg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/agg.c
@@ -2,7 +2,7 @@
/*
* KUnit tests for channel helper functions
*
- * Copyright (C) 2024 Intel Corporation
+ * Copyright (C) 2024-2025 Intel Corporation
*/
#include <kunit/test.h>
#include <kunit/static_stub.h>
@@ -474,14 +474,14 @@ static struct iwl_rx_mpdu_desc *setup_mpdu_desc(void)
KUNIT_ALLOC_AND_ASSERT(test, mpdu_desc);
mpdu_desc->reorder_data |=
- cpu_to_le32(FIELD_PREP(IWL_RX_MPDU_REORDER_BAID_MASK,
- param->rx_pkt.baid));
+ le32_encode_bits(param->rx_pkt.baid,
+ IWL_RX_MPDU_REORDER_BAID_MASK);
mpdu_desc->reorder_data |=
- cpu_to_le32(FIELD_PREP(IWL_RX_MPDU_REORDER_SN_MASK,
- param->rx_pkt.sn));
+ le32_encode_bits(param->rx_pkt.sn,
+ IWL_RX_MPDU_REORDER_SN_MASK);
mpdu_desc->reorder_data |=
- cpu_to_le32(FIELD_PREP(IWL_RX_MPDU_REORDER_NSSN_MASK,
- param->rx_pkt.nssn));
+ le32_encode_bits(param->rx_pkt.nssn,
+ IWL_RX_MPDU_REORDER_NSSN_MASK);
if (param->rx_pkt.old_sn)
mpdu_desc->reorder_data |=
cpu_to_le32(IWL_RX_MPDU_REORDER_BA_OLD_SN);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/hcmd.c b/drivers/net/wireless/intel/iwlwifi/mld/tests/hcmd.c
index 4e189bf8b3fb..0e3b9417dd63 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tests/hcmd.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/hcmd.c
@@ -2,7 +2,7 @@
/*
* KUnit tests for channel helper functions
*
- * Copyright (C) 2024 Intel Corporation
+ * Copyright (C) 2024-2025 Intel Corporation
*/
#include <kunit/test.h>
@@ -30,10 +30,10 @@ static void test_hcmd_names_sorted(struct kunit *test)
static void test_hcmd_names_for_rx(struct kunit *test)
{
static struct iwl_trans t = {
- .command_groups = iwl_mld_groups,
+ .conf.command_groups = iwl_mld_groups,
};
- t.command_groups_size = global_iwl_mld_goups_size;
+ t.conf.command_groups_size = global_iwl_mld_goups_size;
for (unsigned int i = 0; i < iwl_mld_rx_handlers_num; i++) {
const struct iwl_rx_handler *rxh;
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c b/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c
index 295dcfd3f85d..766c24db3613 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c
@@ -32,7 +32,7 @@ static const struct link_grading_test_case {
.desc = "channel util of 128 (50%)",
.input.link = {
.link_id = 0,
- .chandef = &chandef_2ghz,
+ .chandef = &chandef_2ghz_20mhz,
.active = false,
.has_chan_util_elem = true,
.chan_util = 128,
@@ -43,7 +43,7 @@ static const struct link_grading_test_case {
.desc = "channel util of 180 (70%)",
.input.link = {
.link_id = 0,
- .chandef = &chandef_2ghz,
+ .chandef = &chandef_2ghz_20mhz,
.active = false,
.has_chan_util_elem = true,
.chan_util = 180,
@@ -54,7 +54,7 @@ static const struct link_grading_test_case {
.desc = "channel util of 180 (70%), channel load by us of 10%",
.input.link = {
.link_id = 0,
- .chandef = &chandef_2ghz,
+ .chandef = &chandef_2ghz_20mhz,
.has_chan_util_elem = true,
.chan_util = 180,
.active = true,
@@ -66,7 +66,7 @@ static const struct link_grading_test_case {
.desc = "no channel util element",
.input.link = {
.link_id = 0,
- .chandef = &chandef_2ghz,
+ .chandef = &chandef_2ghz_20mhz,
.active = true,
},
.expected_grade = 120,
@@ -132,7 +132,7 @@ static void test_link_grading(struct kunit *test)
bool active = test_param->input.link.active;
u16 valid_links;
struct iwl_mld_kunit_link assoc_link = {
- .band = test_param->input.link.chandef->chan->band,
+ .chandef = test_param->input.link.chandef,
};
/* If the link is not active, use a different link as the assoc link */
@@ -172,103 +172,139 @@ static struct kunit_suite link_selection = {
kunit_test_suite(link_selection);
-static const struct channel_load_case {
+static const struct link_pair_case {
const char *desc;
+ const struct cfg80211_chan_def *chandef_a, *chandef_b;
bool low_latency_vif;
u32 chan_load_not_by_us;
- enum nl80211_chan_width bw_a;
- enum nl80211_chan_width bw_b;
bool primary_link_active;
- bool expected_result;
-} channel_load_cases[] = {
+ u32 expected_result;
+} link_pair_cases[] = {
{
.desc = "Unequal bandwidth, primary link inactive, EMLSR not allowed",
.low_latency_vif = false,
.primary_link_active = false,
- .bw_a = NL80211_CHAN_WIDTH_40,
- .bw_b = NL80211_CHAN_WIDTH_20,
- .expected_result = false,
+ .chandef_a = &chandef_5ghz_40mhz,
+ .chandef_b = &chandef_6ghz_20mhz,
+ .expected_result = IWL_MLD_EMLSR_EXIT_CHAN_LOAD,
},
{
.desc = "Equal bandwidths, sufficient channel load, EMLSR allowed",
.low_latency_vif = false,
.primary_link_active = true,
.chan_load_not_by_us = 11,
- .bw_a = NL80211_CHAN_WIDTH_40,
- .bw_b = NL80211_CHAN_WIDTH_40,
- .expected_result = true,
+ .chandef_a = &chandef_5ghz_40mhz,
+ .chandef_b = &chandef_6ghz_40mhz,
+ .expected_result = 0,
},
{
.desc = "Equal bandwidths, insufficient channel load, EMLSR not allowed",
.low_latency_vif = false,
.primary_link_active = true,
.chan_load_not_by_us = 6,
- .bw_a = NL80211_CHAN_WIDTH_80,
- .bw_b = NL80211_CHAN_WIDTH_80,
- .expected_result = false,
+ .chandef_a = &chandef_5ghz_80mhz,
+ .chandef_b = &chandef_6ghz_80mhz,
+ .expected_result = IWL_MLD_EMLSR_EXIT_CHAN_LOAD,
},
{
.desc = "Low latency VIF, sufficient channel load, EMLSR allowed",
.low_latency_vif = true,
.primary_link_active = true,
.chan_load_not_by_us = 6,
- .bw_a = NL80211_CHAN_WIDTH_160,
- .bw_b = NL80211_CHAN_WIDTH_160,
- .expected_result = true,
+ .chandef_a = &chandef_5ghz_160mhz,
+ .chandef_b = &chandef_6ghz_160mhz,
+ .expected_result = 0,
},
{
.desc = "Different bandwidths (2x ratio), primary link load permits EMLSR",
.low_latency_vif = false,
.primary_link_active = true,
.chan_load_not_by_us = 30,
- .bw_a = NL80211_CHAN_WIDTH_40,
- .bw_b = NL80211_CHAN_WIDTH_20,
- .expected_result = true,
+ .chandef_a = &chandef_5ghz_40mhz,
+ .chandef_b = &chandef_6ghz_20mhz,
+ .expected_result = 0,
},
{
.desc = "Different bandwidths (4x ratio), primary link load permits EMLSR",
.low_latency_vif = false,
.primary_link_active = true,
.chan_load_not_by_us = 45,
- .bw_a = NL80211_CHAN_WIDTH_80,
- .bw_b = NL80211_CHAN_WIDTH_20,
- .expected_result = true,
+ .chandef_a = &chandef_5ghz_80mhz,
+ .chandef_b = &chandef_6ghz_20mhz,
+ .expected_result = 0,
},
{
.desc = "Different bandwidths (16x ratio), primary link load insufficient",
.low_latency_vif = false,
.primary_link_active = true,
.chan_load_not_by_us = 45,
- .bw_a = NL80211_CHAN_WIDTH_320,
- .bw_b = NL80211_CHAN_WIDTH_20,
- .expected_result = false,
+ .chandef_a = &chandef_6ghz_320mhz,
+ .chandef_b = &chandef_5ghz_20mhz,
+ .expected_result = IWL_MLD_EMLSR_EXIT_CHAN_LOAD,
+ },
+ {
+ .desc = "Same band not allowed (2.4 GHz)",
+ .low_latency_vif = false,
+ .primary_link_active = true,
+ .chan_load_not_by_us = 30,
+ .chandef_a = &chandef_2ghz_20mhz,
+ .chandef_b = &chandef_2ghz_11_20mhz,
+ .expected_result = IWL_MLD_EMLSR_EXIT_EQUAL_BAND,
+ },
+ {
+ .desc = "Same band not allowed (5 GHz)",
+ .low_latency_vif = false,
+ .primary_link_active = true,
+ .chan_load_not_by_us = 30,
+ .chandef_a = &chandef_5ghz_40mhz,
+ .chandef_b = &chandef_5ghz_40mhz,
+ .expected_result = IWL_MLD_EMLSR_EXIT_EQUAL_BAND,
+ },
+ {
+ .desc = "Same band allowed (5 GHz separated)",
+ .low_latency_vif = false,
+ .primary_link_active = true,
+ .chan_load_not_by_us = 30,
+ .chandef_a = &chandef_5ghz_40mhz,
+ .chandef_b = &chandef_5ghz_120_40mhz,
+ .expected_result = 0,
+ },
+ {
+ .desc = "Same band not allowed (6 GHz)",
+ .low_latency_vif = false,
+ .primary_link_active = true,
+ .chan_load_not_by_us = 30,
+ .chandef_a = &chandef_6ghz_160mhz,
+ .chandef_b = &chandef_6ghz_221_160mhz,
+ .expected_result = IWL_MLD_EMLSR_EXIT_EQUAL_BAND,
},
};
-KUNIT_ARRAY_PARAM_DESC(channel_load, channel_load_cases, desc);
+KUNIT_ARRAY_PARAM_DESC(link_pair, link_pair_cases, desc);
-static void test_iwl_mld_channel_load_allows_emlsr(struct kunit *test)
+static void test_iwl_mld_link_pair_allows_emlsr(struct kunit *test)
{
- const struct channel_load_case *params = test->param_value;
+ const struct link_pair_case *params = test->param_value;
struct iwl_mld *mld = test->priv;
struct ieee80211_vif *vif;
- struct cfg80211_chan_def chandef_a, chandef_b;
- struct iwl_mld_link_sel_data a = {.chandef = &chandef_a,
- .link_id = 4};
- struct iwl_mld_link_sel_data b = {.chandef = &chandef_b,
- .link_id = 5};
+ /* link A is the primary and link B is the secondary */
+ struct iwl_mld_link_sel_data a = {
+ .chandef = params->chandef_a,
+ .link_id = 4,
+ };
+ struct iwl_mld_link_sel_data b = {
+ .chandef = params->chandef_b,
+ .link_id = 5,
+ };
struct iwl_mld_kunit_link assoc_link = {
+ .chandef = params->primary_link_active ? a.chandef : b.chandef,
.id = params->primary_link_active ? a.link_id : b.link_id,
- .bandwidth = params->primary_link_active ? params->bw_a : params->bw_b,
};
- bool result;
+ u32 result;
vif = iwlmld_kunit_setup_mlo_assoc(BIT(a.link_id) | BIT(b.link_id),
&assoc_link);
- chandef_a.width = params->bw_a;
- chandef_b.width = params->bw_b;
-
if (params->low_latency_vif)
iwl_mld_vif_from_mac80211(vif)->low_latency_causes = 1;
@@ -282,22 +318,22 @@ static void test_iwl_mld_channel_load_allows_emlsr(struct kunit *test)
phy->avg_channel_load_not_by_us = params->chan_load_not_by_us;
}
- result = iwl_mld_channel_load_allows_emlsr(mld, vif, &a, &b);
+ result = iwl_mld_emlsr_pair_state(vif, &a, &b);
wiphy_unlock(mld->wiphy);
KUNIT_EXPECT_EQ(test, result, params->expected_result);
}
-static struct kunit_case channel_load_criteria_test_cases[] = {
- KUNIT_CASE_PARAM(test_iwl_mld_channel_load_allows_emlsr, channel_load_gen_params),
+static struct kunit_case link_pair_criteria_test_cases[] = {
+ KUNIT_CASE_PARAM(test_iwl_mld_link_pair_allows_emlsr, link_pair_gen_params),
{}
};
-static struct kunit_suite channel_load_criteria_tests = {
- .name = "iwlmld_channel_load_allows_emlsr",
- .test_cases = channel_load_criteria_test_cases,
+static struct kunit_suite link_pair_criteria_tests = {
+ .name = "iwlmld_link_pair_allows_emlsr",
+ .test_cases = link_pair_criteria_test_cases,
.init = iwlmld_kunit_test_init,
};
-kunit_test_suite(channel_load_criteria_tests);
+kunit_test_suite(link_pair_criteria_tests);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/link.c b/drivers/net/wireless/intel/iwlwifi/mld/tests/link.c
index 4a4eaa134bd3..69a0d67858bf 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tests/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/link.c
@@ -63,11 +63,11 @@ static void test_missed_beacon(struct kunit *test)
struct iwl_rx_packet *pkt;
struct iwl_mld_kunit_link link1 = {
.id = 0,
- .band = NL80211_BAND_6GHZ,
+ .chandef = &chandef_6ghz_160mhz,
};
struct iwl_mld_kunit_link link2 = {
.id = 1,
- .band = NL80211_BAND_5GHZ,
+ .chandef = &chandef_5ghz_80mhz,
};
kunit_activate_static_stub(test, ieee80211_connection_loss,
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c b/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c
index 9712ee696509..26cf27be762d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c
@@ -24,7 +24,7 @@ int iwlmld_kunit_test_init(struct kunit *test)
{
struct iwl_mld *mld;
struct iwl_trans *trans;
- const struct iwl_cfg *cfg;
+ const struct iwl_rf_cfg *cfg;
struct iwl_fw *fw;
struct ieee80211_hw *hw;
@@ -146,7 +146,7 @@ iwlmld_kunit_add_link(struct ieee80211_vif *vif, int link_id)
}
struct ieee80211_chanctx_conf *
-iwlmld_kunit_add_chanctx_from_def(struct cfg80211_chan_def *def)
+iwlmld_kunit_add_chanctx(const struct cfg80211_chan_def *def)
{
struct kunit *test = kunit_get_current_test();
struct iwl_mld *mld = test->priv;
@@ -346,8 +346,7 @@ iwlmld_kunit_setup_assoc(bool mlo, struct iwl_mld_kunit_link *assoc_link)
else
link = &vif->bss_conf;
- chan_ctx = iwlmld_kunit_add_chanctx(assoc_link->band,
- assoc_link->bandwidth);
+ chan_ctx = iwlmld_kunit_add_chanctx(assoc_link->chandef);
wiphy_lock(mld->wiphy);
iwlmld_kunit_assign_chanctx_to_link(vif, link, chan_ctx);
@@ -428,7 +427,7 @@ struct ieee80211_vif *iwlmld_kunit_assoc_emlsr(struct iwl_mld_kunit_link *link1,
link = wiphy_dereference(mld->wiphy, vif->link_conf[link2->id]);
KUNIT_EXPECT_NOT_NULL(test, link);
- chan_ctx = iwlmld_kunit_add_chanctx(link2->band, link2->bandwidth);
+ chan_ctx = iwlmld_kunit_add_chanctx(link2->chandef);
iwlmld_kunit_assign_chanctx_to_link(vif, link, chan_ctx);
wiphy_unlock(mld->wiphy);
@@ -472,3 +471,33 @@ struct iwl_mld_phy *iwlmld_kunit_get_phy_of_link(struct ieee80211_vif *vif,
return iwl_mld_phy_from_mac80211(chanctx);
}
+
+static const struct chandef_case {
+ const char *desc;
+ const struct cfg80211_chan_def *chandef;
+} chandef_cases[] = {
+#define CHANDEF(c, ...) { .desc = "chandef " #c " valid", .chandef = &c, },
+ CHANDEF_LIST
+#undef CHANDEF
+};
+
+KUNIT_ARRAY_PARAM_DESC(chandef, chandef_cases, desc);
+
+static void test_iwl_mld_chandef_valid(struct kunit *test)
+{
+ const struct chandef_case *params = test->param_value;
+
+ KUNIT_EXPECT_EQ(test, true, cfg80211_chandef_valid(params->chandef));
+}
+
+static struct kunit_case chandef_test_cases[] = {
+ KUNIT_CASE_PARAM(test_iwl_mld_chandef_valid, chandef_gen_params),
+ {}
+};
+
+static struct kunit_suite chandef_tests = {
+ .name = "iwlmld_valid_test_chandefs",
+ .test_cases = chandef_test_cases,
+};
+
+kunit_test_suite(chandef_tests);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.h b/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.h
index d3723653cf1b..edf8eef4e81a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.h
@@ -14,9 +14,8 @@ struct iwl_mld;
int iwlmld_kunit_test_init(struct kunit *test);
struct iwl_mld_kunit_link {
+ const struct cfg80211_chan_def *chandef;
u8 id;
- enum nl80211_band band;
- enum nl80211_chan_width bandwidth;
};
enum nl80211_iftype;
@@ -42,50 +41,57 @@ static struct ieee80211_channel _name = { \
.hw_value = (_freq), \
}
-#define CHANDEF(_name, _channel, _freq1, _width) \
-__maybe_unused static struct cfg80211_chan_def _name = { \
- .chan = &(_channel), \
- .center_freq1 = (_freq1), \
- .width = (_width), \
-}
-
CHANNEL(chan_2ghz, NL80211_BAND_2GHZ, 2412);
+CHANNEL(chan_2ghz_11, NL80211_BAND_2GHZ, 2462);
CHANNEL(chan_5ghz, NL80211_BAND_5GHZ, 5200);
+CHANNEL(chan_5ghz_120, NL80211_BAND_5GHZ, 5600);
CHANNEL(chan_6ghz, NL80211_BAND_6GHZ, 6115);
+CHANNEL(chan_6ghz_221, NL80211_BAND_6GHZ, 7055);
/* Feel free to add more */
+#undef CHANNEL
+
+#define CHANDEF_LIST \
+ CHANDEF(chandef_2ghz_20mhz, chan_2ghz, 2412, \
+ NL80211_CHAN_WIDTH_20) \
+ CHANDEF(chandef_2ghz_40mhz, chan_2ghz, 2422, \
+ NL80211_CHAN_WIDTH_40) \
+ CHANDEF(chandef_2ghz_11_20mhz, chan_2ghz_11, 2462, \
+ NL80211_CHAN_WIDTH_20) \
+ CHANDEF(chandef_5ghz_20mhz, chan_5ghz, 5200, \
+ NL80211_CHAN_WIDTH_20) \
+ CHANDEF(chandef_5ghz_40mhz, chan_5ghz, 5210, \
+ NL80211_CHAN_WIDTH_40) \
+ CHANDEF(chandef_5ghz_80mhz, chan_5ghz, 5210, \
+ NL80211_CHAN_WIDTH_80) \
+ CHANDEF(chandef_5ghz_160mhz, chan_5ghz, 5250, \
+ NL80211_CHAN_WIDTH_160) \
+ CHANDEF(chandef_5ghz_120_40mhz, chan_5ghz_120, 5610, \
+ NL80211_CHAN_WIDTH_40) \
+ CHANDEF(chandef_6ghz_20mhz, chan_6ghz, 6115, \
+ NL80211_CHAN_WIDTH_20) \
+ CHANDEF(chandef_6ghz_40mhz, chan_6ghz, 6125, \
+ NL80211_CHAN_WIDTH_40) \
+ CHANDEF(chandef_6ghz_80mhz, chan_6ghz, 6145, \
+ NL80211_CHAN_WIDTH_80) \
+ CHANDEF(chandef_6ghz_160mhz, chan_6ghz, 6185, \
+ NL80211_CHAN_WIDTH_160) \
+ CHANDEF(chandef_6ghz_320mhz, chan_6ghz, 6105, \
+ NL80211_CHAN_WIDTH_320) \
+ CHANDEF(chandef_6ghz_221_160mhz, chan_6ghz_221, 6985, \
+ NL80211_CHAN_WIDTH_160) \
+ /* Feel free to add more */
-CHANDEF(chandef_2ghz, chan_2ghz, 2412, NL80211_CHAN_WIDTH_20);
-CHANDEF(chandef_5ghz, chan_5ghz, 5200, NL80211_CHAN_WIDTH_40);
-CHANDEF(chandef_6ghz, chan_6ghz, 6115, NL80211_CHAN_WIDTH_160);
-/* Feel free to add more */
-
-//struct cfg80211_chan_def;
+#define CHANDEF(_name, _channel, _freq1, _width) \
+__maybe_unused static const struct cfg80211_chan_def _name = { \
+ .chan = &(_channel), \
+ .center_freq1 = (_freq1), \
+ .width = (_width), \
+};
+CHANDEF_LIST
+#undef CHANDEF
struct ieee80211_chanctx_conf *
-iwlmld_kunit_add_chanctx_from_def(struct cfg80211_chan_def *def);
-
-static inline struct ieee80211_chanctx_conf *
-iwlmld_kunit_add_chanctx(enum nl80211_band band, enum nl80211_chan_width width)
-{
- struct cfg80211_chan_def chandef;
-
- switch (band) {
- case NL80211_BAND_2GHZ:
- chandef = chandef_2ghz;
- break;
- case NL80211_BAND_5GHZ:
- chandef = chandef_5ghz;
- break;
- default:
- case NL80211_BAND_6GHZ:
- chandef = chandef_6ghz;
- break;
- }
-
- chandef.width = width;
-
- return iwlmld_kunit_add_chanctx_from_def(&chandef);
-}
+iwlmld_kunit_add_chanctx(const struct cfg80211_chan_def *def);
void iwlmld_kunit_assign_chanctx_to_link(struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link,
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/thermal.c b/drivers/net/wireless/intel/iwlwifi/mld/thermal.c
index 1909953a9be9..f8a8c35066be 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/thermal.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/thermal.c
@@ -13,6 +13,9 @@
#include "mld.h"
#include "hcmd.h"
+#define IWL_MLD_NUM_CTDP_STEPS 20
+#define IWL_MLD_MIN_CTDP_BUDGET_MW 150
+
#define IWL_MLD_CT_KILL_DURATION (5 * HZ)
void iwl_mld_handle_ct_kill_notif(struct iwl_mld *mld,
@@ -116,8 +119,8 @@ free_resp:
static int compare_temps(const void *a, const void *b)
{
- return ((s16)le16_to_cpu(*(__le16 *)a) -
- (s16)le16_to_cpu(*(__le16 *)b));
+ return ((s16)le16_to_cpu(*(const __le16 *)a) -
+ (s16)le16_to_cpu(*(const __le16 *)b));
}
struct iwl_trip_walk_data {
@@ -272,43 +275,27 @@ static void iwl_mld_thermal_zone_register(struct iwl_mld *mld)
}
}
-/* budget in mWatt */
-static const u32 iwl_mld_cdev_budgets[] = {
- 2400, /* cooling state 0 */
- 2000, /* cooling state 1 */
- 1800, /* cooling state 2 */
- 1600, /* cooling state 3 */
- 1400, /* cooling state 4 */
- 1200, /* cooling state 5 */
- 1000, /* cooling state 6 */
- 900, /* cooling state 7 */
- 800, /* cooling state 8 */
- 700, /* cooling state 9 */
- 650, /* cooling state 10 */
- 600, /* cooling state 11 */
- 550, /* cooling state 12 */
- 500, /* cooling state 13 */
- 450, /* cooling state 14 */
- 400, /* cooling state 15 */
- 350, /* cooling state 16 */
- 300, /* cooling state 17 */
- 250, /* cooling state 18 */
- 200, /* cooling state 19 */
- 150, /* cooling state 20 */
-};
-
int iwl_mld_config_ctdp(struct iwl_mld *mld, u32 state,
enum iwl_ctdp_cmd_operation op)
{
struct iwl_ctdp_cmd cmd = {
.operation = cpu_to_le32(op),
- .budget = cpu_to_le32(iwl_mld_cdev_budgets[state]),
.window_size = 0,
};
+ u32 budget;
int ret;
lockdep_assert_wiphy(mld->wiphy);
+ /* Do a linear scale from IWL_MLD_MIN_CTDP_BUDGET_MW to the configured
+ * maximum in the predefined number of steps.
+ */
+ budget = ((mld->power_budget_mw - IWL_MLD_MIN_CTDP_BUDGET_MW) *
+ (IWL_MLD_NUM_CTDP_STEPS - 1 - state)) /
+ (IWL_MLD_NUM_CTDP_STEPS - 1) +
+ IWL_MLD_MIN_CTDP_BUDGET_MW;
+ cmd.budget = cpu_to_le32(budget);
+
ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(PHY_OPS_GROUP, CTDP_CONFIG_CMD),
&cmd);
@@ -326,7 +313,7 @@ int iwl_mld_config_ctdp(struct iwl_mld *mld, u32 state,
static int iwl_mld_tcool_get_max_state(struct thermal_cooling_device *cdev,
unsigned long *state)
{
- *state = ARRAY_SIZE(iwl_mld_cdev_budgets) - 1;
+ *state = IWL_MLD_NUM_CTDP_STEPS - 1;
return 0;
}
@@ -354,7 +341,7 @@ static int iwl_mld_tcool_set_cur_state(struct thermal_cooling_device *cdev,
goto unlock;
}
- if (new_state >= ARRAY_SIZE(iwl_mld_cdev_budgets)) {
+ if (new_state >= IWL_MLD_NUM_CTDP_STEPS) {
ret = -EINVAL;
goto unlock;
}
@@ -417,10 +404,50 @@ static void iwl_mld_cooling_device_unregister(struct iwl_mld *mld)
}
#endif /* CONFIG_THERMAL */
+static u32 iwl_mld_ctdp_get_max_budget(struct iwl_mld *mld)
+{
+ u64 bios_power_budget = 0;
+ u32 default_power_budget;
+
+ switch (CSR_HW_RFID_TYPE(mld->trans->info.hw_rf_id)) {
+ case IWL_CFG_RF_TYPE_GF:
+ /* dual-radio devices have a higher budget */
+ if (CSR_HW_RFID_IS_CDB(mld->trans->info.hw_rf_id))
+ default_power_budget = 5200;
+ else
+ default_power_budget = 2880;
+ break;
+ case IWL_CFG_RF_TYPE_FM:
+ default_power_budget = 3450;
+ break;
+ case IWL_CFG_RF_TYPE_WH:
+ case IWL_CFG_RF_TYPE_PE:
+ default:
+ default_power_budget = 5550;
+ break;
+ }
+
+ iwl_bios_get_pwr_limit(&mld->fwrt, &bios_power_budget);
+
+ /* 32bit in UEFI, 16bit in ACPI; use BIOS value if it is in range */
+ if (bios_power_budget &&
+ bios_power_budget != 0xffff && bios_power_budget != 0xffffffff &&
+ bios_power_budget >= IWL_MLD_MIN_CTDP_BUDGET_MW &&
+ bios_power_budget <= default_power_budget)
+ return (u32)bios_power_budget;
+
+ return default_power_budget;
+}
+
void iwl_mld_thermal_initialize(struct iwl_mld *mld)
{
+ lockdep_assert_not_held(&mld->wiphy->mtx);
+
wiphy_delayed_work_init(&mld->ct_kill_exit_wk, iwl_mld_exit_ctkill);
+ mld->power_budget_mw = iwl_mld_ctdp_get_max_budget(mld);
+ IWL_DEBUG_TEMP(mld, "cTDP power budget: %d mW\n", mld->power_budget_mw);
+
#ifdef CONFIG_THERMAL
iwl_mld_cooling_device_register(mld);
iwl_mld_thermal_zone_register(mld);
@@ -429,7 +456,9 @@ void iwl_mld_thermal_initialize(struct iwl_mld *mld)
void iwl_mld_thermal_exit(struct iwl_mld *mld)
{
+ wiphy_lock(mld->wiphy);
wiphy_delayed_work_cancel(mld->wiphy, &mld->ct_kill_exit_wk);
+ wiphy_unlock(mld->wiphy);
#ifdef CONFIG_THERMAL
iwl_mld_cooling_device_unregister(mld);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tlc.c b/drivers/net/wireless/intel/iwlwifi/mld/tlc.c
index f054cc921d9d..0e172281b0c8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tlc.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tlc.c
@@ -44,7 +44,7 @@ iwl_mld_get_tlc_cmd_flags(struct iwl_mld *mld,
u16 flags = 0;
/* STBC flags */
- if (mld->cfg->ht_params->stbc &&
+ if (mld->cfg->ht_params.stbc &&
(hweight8(iwl_mld_get_valid_tx_ant(mld)) > 1)) {
if (he_cap->has_he && he_cap->he_cap_elem.phy_cap_info[2] &
IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ)
@@ -56,7 +56,7 @@ iwl_mld_get_tlc_cmd_flags(struct iwl_mld *mld,
}
/* LDPC */
- if (mld->cfg->ht_params->ldpc &&
+ if (mld->cfg->ht_params.ldpc &&
((ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING) ||
(has_vht && (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC))))
flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
@@ -157,9 +157,9 @@ iwl_mld_get_highest_fw_mcs(const struct ieee80211_sta_vht_cap *vht_cap,
static void
iwl_mld_fill_vht_rates(const struct ieee80211_link_sta *link_sta,
const struct ieee80211_sta_vht_cap *vht_cap,
- struct iwl_tlc_config_cmd_v4 *cmd)
+ struct iwl_tlc_config_cmd *cmd)
{
- u16 supp;
+ u32 supp;
int i, highest_mcs;
u8 max_nss = link_sta->rx_nss;
struct ieee80211_vht_cap ieee_vht_cap = {
@@ -182,7 +182,7 @@ iwl_mld_fill_vht_rates(const struct ieee80211_link_sta *link_sta,
if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20)
supp &= ~BIT(IWL_TLC_MNG_HT_RATE_MCS9);
- cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_80] = cpu_to_le16(supp);
+ cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_80] = cpu_to_le32(supp);
/* Check if VHT extended NSS indicates that the bandwidth/NSS
* configuration is supported - only for MCS 0 since we already
* decoded the MCS bits anyway ourselves.
@@ -196,7 +196,7 @@ iwl_mld_fill_vht_rates(const struct ieee80211_link_sta *link_sta,
}
}
-static u16 iwl_mld_he_mac80211_mcs_to_fw_mcs(u16 mcs)
+static u32 iwl_mld_he_mac80211_mcs_to_fw_mcs(u16 mcs)
{
switch (mcs) {
case IEEE80211_HE_MCS_SUPPORT_0_7:
@@ -216,7 +216,7 @@ static u16 iwl_mld_he_mac80211_mcs_to_fw_mcs(u16 mcs)
static void
iwl_mld_fill_he_rates(const struct ieee80211_link_sta *link_sta,
const struct ieee80211_sta_he_cap *own_he_cap,
- struct iwl_tlc_config_cmd_v4 *cmd)
+ struct iwl_tlc_config_cmd *cmd)
{
const struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap;
u16 mcs_160 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
@@ -245,7 +245,7 @@ iwl_mld_fill_he_rates(const struct ieee80211_link_sta *link_sta,
if (_mcs_80 > _tx_mcs_80)
_mcs_80 = _tx_mcs_80;
cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_80] =
- cpu_to_le16(iwl_mld_he_mac80211_mcs_to_fw_mcs(_mcs_80));
+ cpu_to_le32(iwl_mld_he_mac80211_mcs_to_fw_mcs(_mcs_80));
/* If one side doesn't support - mark both as not supporting */
if (_mcs_160 == IEEE80211_HE_MCS_NOT_SUPPORTED ||
@@ -256,19 +256,19 @@ iwl_mld_fill_he_rates(const struct ieee80211_link_sta *link_sta,
if (_mcs_160 > _tx_mcs_160)
_mcs_160 = _tx_mcs_160;
cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_160] =
- cpu_to_le16(iwl_mld_he_mac80211_mcs_to_fw_mcs(_mcs_160));
+ cpu_to_le32(iwl_mld_he_mac80211_mcs_to_fw_mcs(_mcs_160));
}
}
-static void iwl_mld_set_eht_mcs(__le16 ht_rates[][3],
+static void iwl_mld_set_eht_mcs(__le32 ht_rates[][3],
enum IWL_TLC_MCS_PER_BW bw,
- u8 max_nss, u16 mcs_msk)
+ u8 max_nss, u32 mcs_msk)
{
if (max_nss >= 2)
- ht_rates[IWL_TLC_NSS_2][bw] |= cpu_to_le16(mcs_msk);
+ ht_rates[IWL_TLC_NSS_2][bw] |= cpu_to_le32(mcs_msk);
if (max_nss >= 1)
- ht_rates[IWL_TLC_NSS_1][bw] |= cpu_to_le16(mcs_msk);
+ ht_rates[IWL_TLC_NSS_1][bw] |= cpu_to_le32(mcs_msk);
}
static const
@@ -307,7 +307,7 @@ iwl_mld_fill_eht_rates(struct ieee80211_vif *vif,
const struct ieee80211_link_sta *link_sta,
const struct ieee80211_sta_he_cap *own_he_cap,
const struct ieee80211_sta_eht_cap *own_eht_cap,
- struct iwl_tlc_config_cmd_v4 *cmd)
+ struct iwl_tlc_config_cmd *cmd)
{
/* peer RX mcs capa */
const struct ieee80211_eht_mcs_nss_supp *eht_rx_mcs =
@@ -405,7 +405,7 @@ iwl_mld_fill_supp_rates(struct iwl_mld *mld, struct ieee80211_vif *vif,
struct ieee80211_supported_band *sband,
const struct ieee80211_sta_he_cap *own_he_cap,
const struct ieee80211_sta_eht_cap *own_eht_cap,
- struct iwl_tlc_config_cmd_v4 *cmd)
+ struct iwl_tlc_config_cmd *cmd)
{
int i;
u16 non_ht_rates = 0;
@@ -435,7 +435,7 @@ iwl_mld_fill_supp_rates(struct iwl_mld *mld, struct ieee80211_vif *vif,
} else if (ht_cap->ht_supported) {
cmd->mode = IWL_TLC_MNG_MODE_HT;
cmd->ht_rates[IWL_TLC_NSS_1][IWL_TLC_MCS_PER_BW_80] =
- cpu_to_le16(ht_cap->mcs.rx_mask[0]);
+ cpu_to_le32(ht_cap->mcs.rx_mask[0]);
/* the station support only a single receive chain */
if (link_sta->smps_mode == IEEE80211_SMPS_STATIC)
@@ -443,10 +443,30 @@ iwl_mld_fill_supp_rates(struct iwl_mld *mld, struct ieee80211_vif *vif,
0;
else
cmd->ht_rates[IWL_TLC_NSS_2][IWL_TLC_MCS_PER_BW_80] =
- cpu_to_le16(ht_cap->mcs.rx_mask[1]);
+ cpu_to_le32(ht_cap->mcs.rx_mask[1]);
}
}
+static void iwl_mld_convert_tlc_cmd_to_v4(struct iwl_tlc_config_cmd *cmd,
+ struct iwl_tlc_config_cmd_v4 *cmd_v4)
+{
+ /* Copy everything until ht_rates */
+ memcpy(cmd_v4, cmd, offsetof(struct iwl_tlc_config_cmd, ht_rates));
+
+ /* Convert ht_rates from __le32 to __le16 */
+ BUILD_BUG_ON(ARRAY_SIZE(cmd_v4->ht_rates) != ARRAY_SIZE(cmd->ht_rates));
+ BUILD_BUG_ON(ARRAY_SIZE(cmd_v4->ht_rates[0]) != ARRAY_SIZE(cmd->ht_rates[0]));
+
+ for (int nss = 0; nss < ARRAY_SIZE(cmd->ht_rates); nss++)
+ for (int bw = 0; bw < ARRAY_SIZE(cmd->ht_rates[nss]); bw++)
+ cmd_v4->ht_rates[nss][bw] =
+ cpu_to_le16(le32_to_cpu(cmd->ht_rates[nss][bw]));
+
+ /* Copy the rest */
+ cmd_v4->max_mpdu_len = cmd->max_mpdu_len;
+ cmd_v4->max_tx_op = cmd->max_tx_op;
+}
+
static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld,
struct ieee80211_vif *vif,
struct ieee80211_link_sta *link_sta,
@@ -458,7 +478,7 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld,
ieee80211_get_he_iftype_cap_vif(sband, vif);
const struct ieee80211_sta_eht_cap *own_eht_cap =
ieee80211_get_eht_iftype_cap_vif(sband, vif);
- struct iwl_tlc_config_cmd_v4 cmd = {
+ struct iwl_tlc_config_cmd cmd = {
/* For AP mode, use 20 MHz until the STA is authorized */
.max_ch_width = mld_sta->sta_state > IEEE80211_STA_ASSOC ?
iwl_mld_fw_bw_from_sta_bw(link_sta) :
@@ -470,6 +490,11 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld,
.max_mpdu_len = cpu_to_le16(link_sta->agg.max_amsdu_len),
};
int fw_sta_id = iwl_mld_fw_sta_id_from_link_sta(mld, link_sta);
+ u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, TLC_MNG_CONFIG_CMD);
+ u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 0);
+ struct iwl_tlc_config_cmd_v4 cmd_v4;
+ void *cmd_ptr;
+ u8 cmd_size;
int ret;
if (fw_sta_id < 0)
@@ -481,14 +506,26 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld,
own_he_cap, own_eht_cap,
&cmd);
+ if (cmd_ver == 5) {
+ cmd_ptr = &cmd;
+ cmd_size = sizeof(cmd);
+ } else if (cmd_ver == 4) {
+ iwl_mld_convert_tlc_cmd_to_v4(&cmd, &cmd_v4);
+ cmd_ptr = &cmd_v4;
+ cmd_size = sizeof(cmd_v4);
+ } else {
+ IWL_ERR(mld, "Unsupported TLC config cmd version %d\n",
+ cmd_ver);
+ return;
+ }
+
IWL_DEBUG_RATE(mld,
"TLC CONFIG CMD, sta_id=%d, max_ch_width=%d, mode=%d\n",
cmd.sta_id, cmd.max_ch_width, cmd.mode);
/* Send async since this can be called within a RCU-read section */
- ret = iwl_mld_send_cmd_with_flags_pdu(mld, WIDE_ID(DATA_PATH_GROUP,
- TLC_MNG_CONFIG_CMD),
- CMD_ASYNC, &cmd);
+ ret = iwl_mld_send_cmd_with_flags_pdu(mld, cmd_id, CMD_ASYNC, cmd_ptr,
+ cmd_size);
if (ret)
IWL_ERR(mld, "Failed to send TLC cmd (%d)\n", ret);
}
@@ -658,7 +695,9 @@ void iwl_mld_handle_tlc_notif(struct iwl_mld *mld,
if (WARN_ON(!mld_link_sta))
return;
- mld_link_sta->last_rate_n_flags = le32_to_cpu(notif->rate);
+ mld_link_sta->last_rate_n_flags =
+ iwl_v3_rate_from_v2_v3(notif->rate,
+ mld->fw_rates_ver_3);
rs_pretty_print_rate(pretty_rate, sizeof(pretty_rate),
mld_link_sta->last_rate_n_flags);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tx.c b/drivers/net/wireless/intel/iwlwifi/mld/tx.c
index 543abe72e465..3b4b575aadaa 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tx.c
@@ -76,14 +76,14 @@ static int iwl_mld_allocate_txq(struct iwl_mld *mld, struct ieee80211_txq *txq)
*/
unsigned int watchdog_timeout = txq->vif->type == NL80211_IFTYPE_AP ?
IWL_WATCHDOG_DISABLED :
- mld->trans->trans_cfg->base_params->wd_timeout;
+ mld->trans->mac_cfg->base->wd_timeout;
int queue, size;
lockdep_assert_wiphy(mld->wiphy);
if (tid == IWL_MGMT_TID)
size = max_t(u32, IWL_MGMT_QUEUE_SIZE,
- mld->trans->cfg->min_txq_size);
+ mld->trans->mac_cfg->base->min_txq_size);
else
size = iwl_mld_get_queue_size(mld, txq);
@@ -391,9 +391,9 @@ static u32 iwl_mld_mac80211_rate_idx_to_fw(struct iwl_mld *mld,
/* Set CCK or OFDM flag */
if (rate_idx <= IWL_LAST_CCK_RATE)
- rate_flags |= RATE_MCS_CCK_MSK;
+ rate_flags |= RATE_MCS_MOD_TYPE_CCK;
else
- rate_flags |= RATE_MCS_LEGACY_OFDM_MSK;
+ rate_flags |= RATE_MCS_MOD_TYPE_LEGACY_OFDM;
/* Legacy rates are indexed:
* 0 - 3 for CCK and 0 - 7 for OFDM
@@ -425,47 +425,40 @@ static u32 iwl_mld_get_inject_tx_rate(struct iwl_mld *mld,
struct ieee80211_tx_rate *rate = &info->control.rates[0];
u32 result;
- /* we only care about legacy/HT/VHT so far, so we can
- * build in v1 and use iwl_new_rate_from_v1()
- * FIXME: in newer devices we only support the new rates, build
- * the rate_n_flags in the new format here instead of using v1 and
- * converting it.
- */
-
if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
u8 mcs = ieee80211_rate_get_vht_mcs(rate);
u8 nss = ieee80211_rate_get_vht_nss(rate);
- result = RATE_MCS_VHT_MSK_V1;
- result |= u32_encode_bits(mcs, RATE_VHT_MCS_RATE_CODE_MSK);
+ result = RATE_MCS_MOD_TYPE_VHT;
+ result |= u32_encode_bits(mcs, RATE_MCS_CODE_MSK);
result |= u32_encode_bits(nss, RATE_MCS_NSS_MSK);
if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
- result |= RATE_MCS_SGI_MSK_V1;
+ result |= RATE_MCS_SGI_MSK;
if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
- result |= u32_encode_bits(1, RATE_MCS_CHAN_WIDTH_MSK_V1);
+ result |= RATE_MCS_CHAN_WIDTH_40;
else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
- result |= u32_encode_bits(2, RATE_MCS_CHAN_WIDTH_MSK_V1);
+ result |= RATE_MCS_CHAN_WIDTH_80;
else if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
- result |= u32_encode_bits(3, RATE_MCS_CHAN_WIDTH_MSK_V1);
-
- result = iwl_new_rate_from_v1(result);
+ result |= RATE_MCS_CHAN_WIDTH_160;
} else if (rate->flags & IEEE80211_TX_RC_MCS) {
- result = RATE_MCS_HT_MSK_V1;
- result |= u32_encode_bits(rate->idx,
- RATE_HT_MCS_RATE_CODE_MSK_V1 |
- RATE_HT_MCS_NSS_MSK_V1);
+ /* only MCS 0-15 are supported */
+ u8 mcs = rate->idx & 7;
+ u8 nss = rate->idx > 7;
+
+ result = RATE_MCS_MOD_TYPE_HT;
+ result |= u32_encode_bits(mcs, RATE_MCS_CODE_MSK);
+ result |= u32_encode_bits(nss, RATE_MCS_NSS_MSK);
+
if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
- result |= RATE_MCS_SGI_MSK_V1;
+ result |= RATE_MCS_SGI_MSK;
if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
- result |= u32_encode_bits(1, RATE_MCS_CHAN_WIDTH_MSK_V1);
+ result |= RATE_MCS_CHAN_WIDTH_40;
if (info->flags & IEEE80211_TX_CTL_LDPC)
- result |= RATE_MCS_LDPC_MSK_V1;
+ result |= RATE_MCS_LDPC_MSK;
if (u32_get_bits(info->flags, IEEE80211_TX_CTL_STBC))
result |= RATE_MCS_STBC_MSK;
-
- result = iwl_new_rate_from_v1(result);
} else {
result = iwl_mld_mac80211_rate_idx_to_fw(mld, info, rate->idx);
}
@@ -479,19 +472,23 @@ static u32 iwl_mld_get_inject_tx_rate(struct iwl_mld *mld,
return result;
}
-static u32 iwl_mld_get_tx_rate_n_flags(struct iwl_mld *mld,
- struct ieee80211_tx_info *info,
- struct ieee80211_sta *sta, __le16 fc)
+static __le32 iwl_mld_get_tx_rate_n_flags(struct iwl_mld *mld,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_sta *sta, __le16 fc)
{
+ u32 rate;
+
if (unlikely(info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT))
- return iwl_mld_get_inject_tx_rate(mld, info, sta, fc);
+ rate = iwl_mld_get_inject_tx_rate(mld, info, sta, fc);
+ else
+ rate = iwl_mld_mac80211_rate_idx_to_fw(mld, info, -1) |
+ iwl_mld_get_tx_ant(mld, info, sta, fc);
- return iwl_mld_mac80211_rate_idx_to_fw(mld, info, -1) |
- iwl_mld_get_tx_ant(mld, info, sta, fc);
+ return iwl_v3_rate_to_v2_v3(rate, mld->fw_rates_ver_3);
}
static void
-iwl_mld_fill_tx_cmd_hdr(struct iwl_tx_cmd_gen3 *tx_cmd,
+iwl_mld_fill_tx_cmd_hdr(struct iwl_tx_cmd *tx_cmd,
struct sk_buff *skb, bool amsdu)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -537,11 +534,11 @@ iwl_mld_fill_tx_cmd(struct iwl_mld *mld, struct sk_buff *skb,
struct ieee80211_hdr *hdr = (void *)skb->data;
struct iwl_mld_sta *mld_sta = sta ? iwl_mld_sta_from_mac80211(sta) :
NULL;
- struct iwl_tx_cmd_gen3 *tx_cmd;
+ struct iwl_tx_cmd *tx_cmd;
bool amsdu = ieee80211_is_data_qos(hdr->frame_control) &&
(*ieee80211_get_qos_ctl(hdr) &
IEEE80211_QOS_CTL_A_MSDU_PRESENT);
- u32 rate_n_flags = 0;
+ __le32 rate_n_flags = 0;
u16 flags = 0;
dev_tx_cmd->hdr.cmd = TX_CMD;
@@ -576,7 +573,7 @@ iwl_mld_fill_tx_cmd(struct iwl_mld *mld, struct sk_buff *skb,
tx_cmd->flags = cpu_to_le16(flags);
- tx_cmd->rate_n_flags = cpu_to_le32(rate_n_flags);
+ tx_cmd->rate_n_flags = rate_n_flags;
}
/* Caller of this need to check that info->control.vif is not NULL */
@@ -641,16 +638,36 @@ iwl_mld_get_tx_queue_id(struct iwl_mld *mld, struct ieee80211_txq *txq,
case NL80211_IFTYPE_P2P_DEVICE:
mld_vif = iwl_mld_vif_from_mac80211(info->control.vif);
- if (mld_vif->roc_activity == ROC_NUM_ACTIVITIES) {
- IWL_DEBUG_DROP(mld, "Drop tx outside ROC\n");
+ if (mld_vif->roc_activity != ROC_ACTIVITY_P2P_DISC &&
+ mld_vif->roc_activity != ROC_ACTIVITY_P2P_NEG) {
+ IWL_DEBUG_DROP(mld,
+ "Drop tx outside ROC with activity %d\n",
+ mld_vif->roc_activity);
return IWL_MLD_INVALID_DROP_TX;
}
WARN_ON(!ieee80211_is_mgmt(fc));
- return mld_vif->deflink.aux_sta.queue_id;
+ return mld_vif->aux_sta.queue_id;
+ case NL80211_IFTYPE_MONITOR:
+ mld_vif = iwl_mld_vif_from_mac80211(info->control.vif);
+ return mld_vif->deflink.mon_sta.queue_id;
+ case NL80211_IFTYPE_STATION:
+ mld_vif = iwl_mld_vif_from_mac80211(info->control.vif);
+
+ if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)) {
+ IWL_DEBUG_DROP(mld, "Drop tx not off-channel\n");
+ return IWL_MLD_INVALID_DROP_TX;
+ }
+
+ if (mld_vif->roc_activity != ROC_ACTIVITY_HOTSPOT) {
+ IWL_DEBUG_DROP(mld, "Drop tx outside ROC\n");
+ return IWL_MLD_INVALID_DROP_TX;
+ }
+
+ WARN_ON(!ieee80211_is_mgmt(fc));
+ return mld_vif->aux_sta.queue_id;
default:
- /* TODO: consider monitor (task=monitor) */
WARN_ONCE(1, "Unsupported vif type\n");
break;
}
@@ -831,7 +848,7 @@ static int iwl_mld_tx_tso_segment(struct iwl_mld *mld, struct sk_buff *skb,
* 1 more for the potential data in the header
*/
if ((num_subframes * 2 + skb_shinfo(skb)->nr_frags + 1) >
- mld->trans->max_skb_frags)
+ mld->trans->info.max_skb_frags)
num_subframes = 1;
if (num_subframes > 1)
@@ -977,11 +994,14 @@ void iwl_mld_tx_from_txq(struct iwl_mld *mld, struct ieee80211_txq *txq)
rcu_read_unlock();
}
-static void iwl_mld_hwrate_to_tx_rate(u32 rate_n_flags,
+static void iwl_mld_hwrate_to_tx_rate(struct iwl_mld *mld,
+ __le32 rate_n_flags_fw,
struct ieee80211_tx_info *info)
{
enum nl80211_band band = info->band;
struct ieee80211_tx_rate *tx_rate = &info->status.rates[0];
+ u32 rate_n_flags = iwl_v3_rate_from_v2_v3(rate_n_flags_fw,
+ mld->fw_rates_ver_3);
u32 sgi = rate_n_flags & RATE_MCS_SGI_MSK;
u32 chan_width = rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK;
u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
@@ -1006,18 +1026,19 @@ static void iwl_mld_hwrate_to_tx_rate(u32 rate_n_flags,
}
switch (format) {
- case RATE_MCS_HT_MSK:
+ case RATE_MCS_MOD_TYPE_HT:
tx_rate->flags |= IEEE80211_TX_RC_MCS;
tx_rate->idx = RATE_HT_MCS_INDEX(rate_n_flags);
break;
- case RATE_MCS_VHT_MSK:
+ case RATE_MCS_MOD_TYPE_VHT:
ieee80211_rate_set_vht(tx_rate,
rate_n_flags & RATE_MCS_CODE_MSK,
- FIELD_GET(RATE_MCS_NSS_MSK,
- rate_n_flags) + 1);
+ u32_get_bits(rate_n_flags,
+ RATE_MCS_NSS_MSK) + 1);
tx_rate->flags |= IEEE80211_TX_RC_VHT_MCS;
break;
- case RATE_MCS_HE_MSK:
+ case RATE_MCS_MOD_TYPE_HE:
+ case RATE_MCS_MOD_TYPE_EHT:
/* mac80211 cannot do this without ieee80211_tx_status_ext()
* but it only matters for radiotap
*/
@@ -1111,8 +1132,7 @@ void iwl_mld_handle_tx_resp_notif(struct iwl_mld *mld,
iwl_dbg_tlv_time_point(&mld->fwrt, tp, NULL);
}
- iwl_mld_hwrate_to_tx_rate(le32_to_cpu(tx_resp->initial_rate),
- info);
+ iwl_mld_hwrate_to_tx_rate(mld, tx_resp->initial_rate, info);
if (likely(!iwl_mld_time_sync_frame(mld, skb, hdr->addr1)))
ieee80211_tx_status_skb(mld->hw, skb);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
index 21641d41a958..ca63f780140f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2013-2014, 2018-2020, 2022-2024 Intel Corporation
+ * Copyright (C) 2013-2014, 2018-2020, 2022-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
*/
#include <linux/ieee80211.h>
@@ -181,7 +181,7 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
struct iwl_mvm_sta *mvmsta;
u32 value;
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
return 0;
mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
@@ -253,93 +253,6 @@ static void iwl_mvm_bt_coex_tcm_based_ci(struct iwl_mvm *mvm,
swap(data->primary, data->secondary);
}
-/*
- * This function receives the LB link id and checks if eSR should be
- * enabled or disabled (due to BT coex)
- */
-bool
-iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- s32 link_rssi,
- bool primary)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- bool have_wifi_loss_rate =
- iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
- BT_PROFILE_NOTIFICATION, 0) > 4 ||
- iwl_fw_lookup_notif_ver(mvm->fw, BT_COEX_GROUP,
- PROFILE_NOTIF, 0) >= 1;
- u8 wifi_loss_mid_high_rssi;
- u8 wifi_loss_low_rssi;
- u8 wifi_loss_rate;
-
- if (iwl_fw_lookup_notif_ver(mvm->fw, BT_COEX_GROUP,
- PROFILE_NOTIF, 0) >= 1) {
- /* For now, we consider 2.4 GHz band / ANT_A only */
- wifi_loss_mid_high_rssi =
- mvm->last_bt_wifi_loss.wifi_loss_mid_high_rssi[PHY_BAND_24][0];
- wifi_loss_low_rssi =
- mvm->last_bt_wifi_loss.wifi_loss_low_rssi[PHY_BAND_24][0];
- } else {
- wifi_loss_mid_high_rssi = mvm->last_bt_notif.wifi_loss_mid_high_rssi;
- wifi_loss_low_rssi = mvm->last_bt_notif.wifi_loss_low_rssi;
- }
-
- if (wifi_loss_low_rssi == BT_OFF)
- return true;
-
- if (primary)
- return false;
-
- /* The feature is not supported */
- if (!have_wifi_loss_rate)
- return true;
-
-
- /*
- * In case we don't know the RSSI - take the lower wifi loss,
- * so we will more likely enter eSR, and if RSSI is low -
- * we will get an update on this and exit eSR.
- */
- if (!link_rssi)
- wifi_loss_rate = wifi_loss_mid_high_rssi;
-
- else if (mvmvif->esr_active)
- /* RSSI needs to get really low to disable eSR... */
- wifi_loss_rate =
- link_rssi <= -IWL_MVM_BT_COEX_DISABLE_ESR_THRESH ?
- wifi_loss_low_rssi :
- wifi_loss_mid_high_rssi;
- else
- /* ...And really high before we enable it back */
- wifi_loss_rate =
- link_rssi <= -IWL_MVM_BT_COEX_ENABLE_ESR_THRESH ?
- wifi_loss_low_rssi :
- wifi_loss_mid_high_rssi;
-
- return wifi_loss_rate <= IWL_MVM_BT_COEX_WIFI_LOSS_THRESH;
-}
-
-void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- int link_id)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm_vif_link_info *link = mvmvif->link[link_id];
-
- if (!ieee80211_vif_is_mld(vif) ||
- !iwl_mvm_vif_from_mac80211(vif)->authorized ||
- WARN_ON(!link))
- return;
-
- if (!iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif,
- (s8)link->beacon_stats.avg_signal,
- link_id == iwl_mvm_get_primary_link(vif)))
- /* In case we decided to exit eSR - stay with the primary */
- iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_COEX,
- iwl_mvm_get_primary_link(vif));
-}
-
static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_bt_iterator_data *data,
@@ -385,8 +298,6 @@ static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm,
return;
}
- iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id);
-
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2))
min_ag_for_static_smps = BT_VERY_HIGH_TRAFFIC;
else
@@ -525,32 +436,6 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
iwl_mvm_bt_notif_per_link(mvm, vif, data, link_id);
}
-/* must be called under rcu_read_lock */
-static void iwl_mvm_bt_coex_notif_iterator(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
-{
- struct iwl_mvm *mvm = _data;
- struct ieee80211_bss_conf *link_conf;
- unsigned int link_id;
-
- lockdep_assert_held(&mvm->mutex);
-
- if (vif->type != NL80211_IFTYPE_STATION)
- return;
-
- for_each_vif_active_link(vif, link_conf, link_id) {
- struct ieee80211_chanctx_conf *chanctx_conf =
- rcu_dereference_check(link_conf->chanctx_conf,
- lockdep_is_held(&mvm->mutex));
-
- if ((!chanctx_conf ||
- chanctx_conf->def.chan->band != NL80211_BAND_2GHZ))
- continue;
-
- iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id);
- }
-}
-
static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
{
struct iwl_bt_iterator_data data = {
@@ -569,7 +454,7 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_bt_notif_iterator, &data);
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
rcu_read_unlock();
return;
}
@@ -654,22 +539,6 @@ void iwl_mvm_rx_bt_coex_old_notif(struct iwl_mvm *mvm,
iwl_mvm_bt_coex_notif_handle(mvm);
}
-void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb)
-{
- const struct iwl_rx_packet *pkt = rxb_addr(rxb);
- const struct iwl_bt_coex_profile_notif *notif = (const void *)pkt->data;
-
- lockdep_assert_held(&mvm->mutex);
-
- mvm->last_bt_wifi_loss = *notif;
-
- ieee80211_iterate_active_interfaces(mvm->hw,
- IEEE80211_IFACE_ITER_NORMAL,
- iwl_mvm_bt_coex_notif_iterator,
- mvm);
-}
-
void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum ieee80211_rssi_event_data rssi_event)
{
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
index 776600ddaea6..17f94663c941 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
- * Copyright (C) 2013-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2013-2014, 2018-2025 Intel Corporation
* Copyright (C) 2015 Intel Deutschland GmbH
*/
#ifndef __MVM_CONSTANTS_H
@@ -11,15 +11,7 @@
#include "fw-api.h"
#define IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM 20
-#define IWL_MVM_BT_COEX_DISABLE_ESR_THRESH 69
-#define IWL_MVM_BT_COEX_ENABLE_ESR_THRESH 63
-#define IWL_MVM_BT_COEX_WIFI_LOSS_THRESH 0
#define IWL_MVM_TRIGGER_LINK_SEL_TIME_SEC 30
-#define IWL_MVM_TPT_COUNT_WINDOW_SEC 5
-#define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS 5
-#define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH 15
-#define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED 11
-#define IWL_MVM_LOW_RSSI_MLO_SCAN_THRESH -72
#define IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
#define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
@@ -129,14 +121,4 @@
#define IWL_MVM_MIN_BEACON_INTERVAL_TU 16
#define IWL_MVM_AUTO_EML_ENABLE true
-#define IWL_MVM_HIGH_RSSI_THRESH_20MHZ -67
-#define IWL_MVM_LOW_RSSI_THRESH_20MHZ -71
-#define IWL_MVM_HIGH_RSSI_THRESH_40MHZ -64
-#define IWL_MVM_LOW_RSSI_THRESH_40MHZ -67
-#define IWL_MVM_HIGH_RSSI_THRESH_80MHZ -61
-#define IWL_MVM_LOW_RSSI_THRESH_80MHZ -74
-#define IWL_MVM_HIGH_RSSI_THRESH_160MHZ -58
-#define IWL_MVM_LOW_RSSI_THRESH_160MHZ -61
-
-#define IWL_MVM_ENTER_ESR_TPT_THRESH 400
#endif /* __MVM_CONSTANTS_H */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index 3e8b7168af01..07f1a84c274e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -120,19 +120,17 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
switch (key->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104: { /* hack it for now */
- struct {
- struct iwl_mvm_wep_key_cmd wep_key_cmd;
- struct iwl_mvm_wep_key wep_key;
- } __packed wkc = {
- .wep_key_cmd.mac_id_n_color =
- cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
- mvmvif->color)),
- .wep_key_cmd.num_keys = 1,
- /* firmware sets STA_KEY_FLG_WEP_13BYTES */
- .wep_key_cmd.decryption_type = STA_KEY_FLG_WEP,
- .wep_key.key_index = key->keyidx,
- .wep_key.key_size = key->keylen,
- };
+ DEFINE_RAW_FLEX(struct iwl_mvm_wep_key_cmd, wkc, wep_key, 1);
+ struct iwl_mvm_wep_key *wep_key = wkc->wep_key;
+
+ wkc->mac_id_n_color =
+ cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
+ mvmvif->color));
+ wkc->num_keys = 1;
+ /* firmware sets STA_KEY_FLG_WEP_13BYTES */
+ wkc->decryption_type = STA_KEY_FLG_WEP;
+ wep_key->key_index = key->keyidx;
+ wep_key->key_size = key->keylen;
/*
* This will fail -- the key functions don't set support
@@ -142,18 +140,19 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
break;
- memcpy(&wkc.wep_key.key[3], key->key, key->keylen);
+ memcpy(&wep_key->key[3], key->key, key->keylen);
if (key->keyidx == mvmvif->tx_key_idx) {
/* TX key must be at offset 0 */
- wkc.wep_key.key_offset = 0;
+ wep_key->key_offset = 0;
} else {
/* others start at 1 */
data->wep_key_idx++;
- wkc.wep_key.key_offset = data->wep_key_idx;
+ wep_key->key_offset = data->wep_key_idx;
}
mutex_lock(&mvm->mutex);
- ret = iwl_mvm_send_cmd_pdu(mvm, WEP_KEY, 0, sizeof(wkc), &wkc);
+ ret = iwl_mvm_send_cmd_pdu(mvm, WEP_KEY, 0,
+ __struct_size(wkc), wkc);
data->error = ret != 0;
mvm->ptk_ivlen = key->iv_len;
@@ -212,7 +211,7 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
}
struct wowlan_key_rsc_tsc_data {
- struct iwl_wowlan_rsc_tsc_params_cmd_v4 *rsc_tsc;
+ struct iwl_wowlan_rsc_tsc_params_cmd_ver_2 *rsc_tsc;
bool have_rsc_tsc;
};
@@ -237,21 +236,21 @@ static void iwl_mvm_wowlan_get_rsc_tsc_data(struct ieee80211_hw *hw,
u64 pn64;
tkip_sc =
- data->rsc_tsc->params.all_tsc_rsc.tkip.unicast_rsc;
+ data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc;
tkip_tx_sc =
- &data->rsc_tsc->params.all_tsc_rsc.tkip.tsc;
+ &data->rsc_tsc->all_tsc_rsc.tkip.tsc;
pn64 = atomic64_read(&key->tx_pn);
tkip_tx_sc->iv16 = cpu_to_le16(TKIP_PN_TO_IV16(pn64));
tkip_tx_sc->iv32 = cpu_to_le32(TKIP_PN_TO_IV32(pn64));
} else {
tkip_sc =
- data->rsc_tsc->params.all_tsc_rsc.tkip.multicast_rsc;
+ data->rsc_tsc->all_tsc_rsc.tkip.multicast_rsc;
}
/*
* For non-QoS this relies on the fact that both the uCode and
- * mac80211 use TID 0 (as they need to to avoid replay attacks)
+ * mac80211 use TID 0 (as they need to avoid replay attacks)
* for checking the IV in the frames.
*/
for (i = 0; i < IWL_NUM_RSC; i++) {
@@ -270,15 +269,15 @@ static void iwl_mvm_wowlan_get_rsc_tsc_data(struct ieee80211_hw *hw,
u64 pn64;
aes_sc =
- data->rsc_tsc->params.all_tsc_rsc.aes.unicast_rsc;
+ data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc;
aes_tx_sc =
- &data->rsc_tsc->params.all_tsc_rsc.aes.tsc;
+ &data->rsc_tsc->all_tsc_rsc.aes.tsc;
pn64 = atomic64_read(&key->tx_pn);
aes_tx_sc->pn = cpu_to_le64(pn64);
} else {
aes_sc =
- data->rsc_tsc->params.all_tsc_rsc.aes.multicast_rsc;
+ data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc;
}
/*
@@ -300,7 +299,7 @@ static void iwl_mvm_wowlan_get_rsc_tsc_data(struct ieee80211_hw *hw,
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
pn = iwl_mvm_find_max_pn(key, ptk_pn, &seq, i,
- mvm->trans->num_rx_queues);
+ mvm->trans->info.num_rxqs);
aes_sc[i].pn = cpu_to_le64((u64)pn[5] |
((u64)pn[4] << 8) |
((u64)pn[3] << 16) |
@@ -387,7 +386,7 @@ static void iwl_mvm_wowlan_get_rsc_v5_data(struct ieee80211_hw *hw,
/*
* For non-QoS this relies on the fact that both the uCode and
- * mac80211 use TID 0 (as they need to to avoid replay attacks)
+ * mac80211 use TID 0 (as they need to avoid replay attacks)
* for checking the IV in the frames.
*/
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
@@ -421,7 +420,7 @@ static void iwl_mvm_wowlan_get_rsc_v5_data(struct ieee80211_hw *hw,
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
pn = iwl_mvm_find_max_pn(key, ptk_pn, &seq, i,
- mvm->trans->num_rx_queues);
+ mvm->trans->info.num_rxqs);
rsc[i] = cpu_to_le64((u64)pn[5] |
((u64)pn[4] << 8) |
((u64)pn[3] << 16) |
@@ -481,30 +480,21 @@ static int iwl_mvm_wowlan_config_rsc_tsc(struct iwl_mvm *mvm,
else
ret = 0;
kfree(data.rsc);
- } else if (ver == 4 || ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN) {
+ } else if (ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN) {
struct wowlan_key_rsc_tsc_data data = {};
- int size;
data.rsc_tsc = kzalloc(sizeof(*data.rsc_tsc), GFP_KERNEL);
if (!data.rsc_tsc)
return -ENOMEM;
- if (ver == 4) {
- size = sizeof(*data.rsc_tsc);
- data.rsc_tsc->sta_id =
- cpu_to_le32(mvm_link->ap_sta_id);
- } else {
- /* ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN */
- size = sizeof(data.rsc_tsc->params);
- }
-
ieee80211_iter_keys(mvm->hw, vif,
iwl_mvm_wowlan_get_rsc_tsc_data,
&data);
if (data.have_rsc_tsc)
ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_TSC_RSC_PARAM,
- CMD_ASYNC, size,
+ CMD_ASYNC,
+ sizeof(*data.rsc_tsc),
data.rsc_tsc);
else
ret = 0;
@@ -938,6 +928,10 @@ iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,
if (ap_sta->mfp)
wowlan_config_cmd->flags |= IS_11W_ASSOC;
+ if (rcu_access_pointer(mvmvif->bcn_prot.keys[0]) ||
+ rcu_access_pointer(mvmvif->bcn_prot.keys[1]))
+ wowlan_config_cmd->flags |= HAS_BEACON_PROTECTION;
+
if (iwl_fw_lookup_cmd_ver(mvm->fw, WOWLAN_CONFIGURATION, 0) < 6) {
/* Query the last used seqno and set it */
int ret = iwl_mvm_get_last_nonqos_seq(mvm, vif);
@@ -1248,15 +1242,14 @@ static void iwl_mvm_free_nd(struct iwl_mvm *mvm)
}
static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
- struct cfg80211_wowlan *wowlan,
- bool test)
+ struct cfg80211_wowlan *wowlan)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct ieee80211_vif *vif = NULL;
struct iwl_mvm_vif *mvmvif = NULL;
struct ieee80211_sta *ap_sta = NULL;
struct iwl_mvm_vif_link_info *mvm_link;
- struct iwl_d3_manager_config d3_cfg_cmd_data = {
+ struct iwl_d3_manager_config d3_cfg_cmd = {
/*
* Program the minimum sleep time to 10 seconds, as many
* platforms have issues processing a wakeup signal while
@@ -1264,23 +1257,14 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
*/
.min_sleep_time = cpu_to_le32(10 * 1000 * 1000),
};
- struct iwl_host_cmd d3_cfg_cmd = {
- .id = D3_CONFIG_CMD,
- .flags = CMD_WANT_SKB | CMD_SEND_IN_D3,
- .data[0] = &d3_cfg_cmd_data,
- .len[0] = sizeof(d3_cfg_cmd_data),
- };
int ret;
int len __maybe_unused;
bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
if (!wowlan) {
- /*
- * mac80211 shouldn't get here, but for D3 test
- * it doesn't warrant a warning
- */
- WARN_ON(!test);
+ /* mac80211 shouldn't get here */
+ WARN_ON(1);
return -EINVAL;
}
@@ -1288,10 +1272,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
if (IS_ERR_OR_NULL(vif))
return 1;
- ret = iwl_mvm_block_esr_sync(mvm, vif, IWL_MVM_ESR_BLOCKED_WOWLAN);
- if (ret)
- return ret;
-
mutex_lock(&mvm->mutex);
set_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);
@@ -1361,7 +1341,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
#ifdef CONFIG_IWLWIFI_DEBUGFS
if (mvm->d3_wake_sysassert)
- d3_cfg_cmd_data.wakeup_flags |=
+ d3_cfg_cmd.wakeup_flags |=
cpu_to_le32(IWL_WAKEUP_D3_CONFIG_FW_ERROR);
#endif
@@ -1370,27 +1350,18 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
* recording before entering D3. In later devices the FW stops the
* recording automatically.
*/
- if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000)
+ if (mvm->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_9000)
iwl_fw_dbg_stop_restart_recording(&mvm->fwrt, NULL, true);
- mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;
-
/* must be last -- this switches firmware state */
- ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd);
+ ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, 0, sizeof(d3_cfg_cmd),
+ &d3_cfg_cmd);
if (ret)
goto out;
-#ifdef CONFIG_IWLWIFI_DEBUGFS
- len = iwl_rx_packet_payload_len(d3_cfg_cmd.resp_pkt);
- if (len >= sizeof(u32)) {
- mvm->d3_test_pme_ptr =
- le32_to_cpup((__le32 *)d3_cfg_cmd.resp_pkt->data);
- }
-#endif
- iwl_free_resp(&d3_cfg_cmd);
clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
- ret = iwl_trans_d3_suspend(mvm->trans, test, !unified_image);
+ ret = iwl_trans_d3_suspend(mvm->trans, !unified_image);
out:
if (ret < 0) {
iwl_mvm_free_nd(mvm);
@@ -1413,7 +1384,7 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
iwl_fw_runtime_suspend(&mvm->fwrt);
mutex_unlock(&mvm->mutex);
- return __iwl_mvm_suspend(hw, wowlan, false);
+ return __iwl_mvm_suspend(hw, wowlan);
}
struct iwl_multicast_key_data {
@@ -1477,9 +1448,6 @@ struct iwl_wowlan_status_data {
struct iwl_multicast_key_data igtk;
struct iwl_multicast_key_data bigtk[WOWLAN_BIGTK_KEYS_NUM];
- int num_mlo_keys;
- struct iwl_wowlan_mlo_gtk mlo_keys[WOWLAN_MAX_MLO_KEYS];
-
u8 *wake_packet;
};
@@ -1686,7 +1654,7 @@ static void iwl_mvm_set_aes_ptk_rx_seq(struct iwl_mvm *mvm,
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
int i;
- for (i = 1; i < mvm->trans->num_rx_queues; i++)
+ for (i = 1; i < mvm->trans->info.num_rxqs; i++)
memcpy(ptk_pn->q[i].pn[tid],
status->ptk.aes.seq[tid].ccmp.pn,
IEEE80211_CCMP_PN_LEN);
@@ -1695,7 +1663,7 @@ static void iwl_mvm_set_aes_ptk_rx_seq(struct iwl_mvm *mvm,
}
static void iwl_mvm_convert_key_counters(struct iwl_wowlan_status_data *status,
- union iwl_all_tsc_rsc *sc)
+ union iwl_all_tsc_rsc *sc, u8 key_idx)
{
int i;
@@ -1710,7 +1678,7 @@ static void iwl_mvm_convert_key_counters(struct iwl_wowlan_status_data *status,
&status->gtk_seq[0].aes.seq[i]);
}
status->gtk_seq[0].valid = true;
- status->gtk_seq[0].key_id = -1;
+ status->gtk_seq[0].key_id = key_idx;
/* PTK TX counter */
status->ptk.tkip.tx_pn = (u64)le16_to_cpu(sc->tkip.tsc.iv16) |
@@ -1793,8 +1761,7 @@ static void iwl_mvm_set_key_rx_seq_idx(struct ieee80211_key_conf *key,
}
static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,
- struct iwl_wowlan_status_data *status,
- bool installed)
+ struct iwl_wowlan_status_data *status)
{
int i;
@@ -1802,23 +1769,7 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,
if (!status->gtk_seq[i].valid)
continue;
- /* Handle the case where we know the key ID */
- if (status->gtk_seq[i].key_id == key->keyidx) {
- s8 new_key_id = -1;
-
- if (status->num_of_gtk_rekeys)
- new_key_id = status->gtk[0].flags &
- IWL_WOWLAN_GTK_IDX_MASK;
-
- /* Don't install a new key's value to an old key */
- if (new_key_id != key->keyidx)
- iwl_mvm_set_key_rx_seq_idx(key, status, i);
- continue;
- }
-
- /* handle the case where we didn't, last key only */
- if (status->gtk_seq[i].key_id == -1 &&
- (!status->num_of_gtk_rekeys || installed))
+ if (status->gtk_seq[i].key_id == key->keyidx)
iwl_mvm_set_key_rx_seq_idx(key, status, i);
}
}
@@ -1826,63 +1777,8 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,
struct iwl_mvm_d3_gtk_iter_data {
struct iwl_mvm *mvm;
struct iwl_wowlan_status_data *status;
- u32 gtk_cipher, igtk_cipher, bigtk_cipher;
- bool unhandled_cipher, igtk_support, bigtk_support;
- int num_keys;
};
-static void iwl_mvm_d3_find_last_keys(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key,
- void *_data)
-{
- struct iwl_mvm_d3_gtk_iter_data *data = _data;
- int link_id = vif->active_links ? __ffs(vif->active_links) : -1;
-
- if (link_id >= 0 && key->link_id >= 0 && link_id != key->link_id)
- return;
-
- if (data->unhandled_cipher)
- return;
-
- switch (key->cipher) {
- case WLAN_CIPHER_SUITE_WEP40:
- case WLAN_CIPHER_SUITE_WEP104:
- /* ignore WEP completely, nothing to do */
- return;
- case WLAN_CIPHER_SUITE_CCMP:
- case WLAN_CIPHER_SUITE_GCMP:
- case WLAN_CIPHER_SUITE_GCMP_256:
- case WLAN_CIPHER_SUITE_TKIP:
- /* we support these */
- data->gtk_cipher = key->cipher;
- break;
- case WLAN_CIPHER_SUITE_BIP_GMAC_128:
- case WLAN_CIPHER_SUITE_BIP_GMAC_256:
- case WLAN_CIPHER_SUITE_BIP_CMAC_256:
- case WLAN_CIPHER_SUITE_AES_CMAC:
- /* we support these */
- if (data->igtk_support &&
- (key->keyidx == 4 || key->keyidx == 5)) {
- data->igtk_cipher = key->cipher;
- } else if (data->bigtk_support &&
- (key->keyidx == 6 || key->keyidx == 7)) {
- data->bigtk_cipher = key->cipher;
- } else {
- data->unhandled_cipher = true;
- return;
- }
- break;
- default:
- /* everything else - disconnect from AP */
- data->unhandled_cipher = true;
- return;
- }
-
- data->num_keys++;
-}
-
static void
iwl_mvm_d3_set_igtk_bigtk_ipn(const struct iwl_multicast_key_data *key,
struct ieee80211_key_seq *seq, u32 cipher)
@@ -1908,17 +1804,10 @@ iwl_mvm_d3_update_igtk_bigtk(struct iwl_wowlan_status_data *status,
struct ieee80211_key_conf *key,
struct iwl_multicast_key_data *key_data)
{
- if (status->num_of_gtk_rekeys && key_data->len) {
- /* remove rekeyed key */
- ieee80211_remove_key(key);
- } else {
- struct ieee80211_key_seq seq;
+ struct ieee80211_key_seq seq;
- iwl_mvm_d3_set_igtk_bigtk_ipn(key_data,
- &seq,
- key->cipher);
- ieee80211_set_key_rx_seq(key, 0, &seq);
- }
+ iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, key->cipher);
+ ieee80211_set_key_rx_seq(key, 0, &seq);
}
static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
@@ -1935,9 +1824,6 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
if (link_id >= 0 && key->link_id >= 0 && link_id != key->link_id)
return;
- if (data->unhandled_cipher)
- return;
-
switch (key->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
@@ -1959,18 +1845,13 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
return;
}
keyidx = key->keyidx;
- /* The current key is always sent by the FW, even if it wasn't
- * rekeyed during D3.
- * We remove an existing key if it has the same index as
- * a new key
+ /*
+ * Update the seq even if there was a rekey. If there was a
+ * rekey, we will update again after replacing the key
*/
- if (status->num_of_gtk_rekeys &&
- ((status->gtk[0].len && keyidx == status->gtk[0].id) ||
- (status->gtk[1].len && keyidx == status->gtk[1].id))) {
- ieee80211_remove_key(key);
- } else {
- iwl_mvm_set_key_rx_seq(key, data->status, false);
- }
+ if ((status->gtk[0].len && keyidx == status->gtk[0].id) ||
+ (status->gtk[1].len && keyidx == status->gtk[1].id))
+ iwl_mvm_set_key_rx_seq(key, status);
break;
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
@@ -1989,218 +1870,32 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
}
}
-struct iwl_mvm_d3_mlo_old_keys {
- u32 cipher[IEEE80211_MLD_MAX_NUM_LINKS][WOWLAN_MLO_GTK_KEY_NUM_TYPES];
- struct ieee80211_key_conf *key[IEEE80211_MLD_MAX_NUM_LINKS][8];
-};
-
-static void iwl_mvm_mlo_key_ciphers(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key,
- void *data)
-{
- struct iwl_mvm_d3_mlo_old_keys *old_keys = data;
- enum iwl_wowlan_mlo_gtk_type key_type;
-
- if (key->link_id < 0)
- return;
-
- if (WARN_ON(key->link_id >= IEEE80211_MLD_MAX_NUM_LINKS ||
- key->keyidx >= 8))
- return;
-
- if (WARN_ON(old_keys->key[key->link_id][key->keyidx]))
- return;
-
- switch (key->cipher) {
- case WLAN_CIPHER_SUITE_CCMP:
- case WLAN_CIPHER_SUITE_GCMP:
- case WLAN_CIPHER_SUITE_GCMP_256:
- key_type = WOWLAN_MLO_GTK_KEY_TYPE_GTK;
- break;
- case WLAN_CIPHER_SUITE_BIP_GMAC_128:
- case WLAN_CIPHER_SUITE_BIP_GMAC_256:
- case WLAN_CIPHER_SUITE_BIP_CMAC_256:
- case WLAN_CIPHER_SUITE_AES_CMAC:
- if (key->keyidx == 4 || key->keyidx == 5) {
- key_type = WOWLAN_MLO_GTK_KEY_TYPE_IGTK;
- break;
- } else if (key->keyidx == 6 || key->keyidx == 7) {
- key_type = WOWLAN_MLO_GTK_KEY_TYPE_BIGTK;
- break;
- }
- return;
- default:
- /* ignore WEP/TKIP or unknown ciphers */
- return;
- }
-
- old_keys->cipher[key->link_id][key_type] = key->cipher;
- old_keys->key[key->link_id][key->keyidx] = key;
-}
-
-static bool iwl_mvm_mlo_gtk_rekey(struct iwl_wowlan_status_data *status,
- struct ieee80211_vif *vif,
- struct iwl_mvm *mvm)
-{
- int i;
- struct iwl_mvm_d3_mlo_old_keys *old_keys;
- bool ret = true;
-
- IWL_DEBUG_WOWLAN(mvm, "Num of MLO Keys: %d\n", status->num_mlo_keys);
- if (!status->num_mlo_keys)
- return true;
-
- old_keys = kzalloc(sizeof(*old_keys), GFP_KERNEL);
- if (!old_keys)
- return false;
-
- /* find the cipher for each mlo key */
- ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_mlo_key_ciphers, old_keys);
-
- for (i = 0; i < status->num_mlo_keys; i++) {
- struct iwl_wowlan_mlo_gtk *mlo_key = &status->mlo_keys[i];
- struct ieee80211_key_conf *key, *old_key;
- struct ieee80211_key_seq seq;
- struct {
- struct ieee80211_key_conf conf;
- u8 key[32];
- } conf = {};
- u16 flags = le16_to_cpu(mlo_key->flags);
- int j, link_id, key_id, key_type;
-
- link_id = u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_LINK_ID_MSK);
- key_id = u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_KEY_ID_MSK);
- key_type = u16_get_bits(flags,
- WOWLAN_MLO_GTK_FLAG_KEY_TYPE_MSK);
-
- if (!(vif->valid_links & BIT(link_id)))
- continue;
-
- if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS ||
- key_id >= 8 ||
- key_type >= WOWLAN_MLO_GTK_KEY_NUM_TYPES))
- continue;
-
- conf.conf.cipher = old_keys->cipher[link_id][key_type];
- /* WARN_ON? */
- if (!conf.conf.cipher)
- continue;
-
- conf.conf.keylen = 0;
- switch (conf.conf.cipher) {
- case WLAN_CIPHER_SUITE_CCMP:
- case WLAN_CIPHER_SUITE_GCMP:
- conf.conf.keylen = WLAN_KEY_LEN_CCMP;
- break;
- case WLAN_CIPHER_SUITE_GCMP_256:
- conf.conf.keylen = WLAN_KEY_LEN_GCMP_256;
- break;
- case WLAN_CIPHER_SUITE_BIP_GMAC_128:
- conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_128;
- break;
- case WLAN_CIPHER_SUITE_BIP_GMAC_256:
- conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_256;
- break;
- case WLAN_CIPHER_SUITE_AES_CMAC:
- conf.conf.keylen = WLAN_KEY_LEN_AES_CMAC;
- break;
- case WLAN_CIPHER_SUITE_BIP_CMAC_256:
- conf.conf.keylen = WLAN_KEY_LEN_BIP_CMAC_256;
- break;
- }
-
- if (WARN_ON(!conf.conf.keylen ||
- conf.conf.keylen > sizeof(conf.key)))
- continue;
-
- memcpy(conf.conf.key, mlo_key->key, conf.conf.keylen);
- conf.conf.keyidx = key_id;
-
- old_key = old_keys->key[link_id][key_id];
- if (old_key) {
- IWL_DEBUG_WOWLAN(mvm,
- "Remove MLO key id %d, link id %d\n",
- key_id, link_id);
- ieee80211_remove_key(old_key);
- }
-
- IWL_DEBUG_WOWLAN(mvm, "Add MLO key id %d, link id %d\n",
- key_id, link_id);
- key = ieee80211_gtk_rekey_add(vif, &conf.conf, link_id);
- if (WARN_ON(IS_ERR(key))) {
- ret = false;
- goto out;
- }
-
- /*
- * mac80211 expects the pn in big-endian
- * also note that seq is a union of all cipher types
- * (ccmp, gcmp, cmac, gmac), and they all have the same
- * pn field (of length 6) so just copy it to ccmp.pn.
- */
- for (j = 5; j >= 0; j--)
- seq.ccmp.pn[5 - j] = mlo_key->pn[j];
-
- /* group keys are non-QoS and use TID 0 */
- ieee80211_set_key_rx_seq(key, 0, &seq);
- }
-
-out:
- kfree(old_keys);
- return ret;
-}
-
static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status,
struct ieee80211_vif *vif,
- struct iwl_mvm *mvm, u32 gtk_cipher)
+ struct iwl_mvm *mvm)
{
int i, j;
struct ieee80211_key_conf *key;
- struct {
- struct ieee80211_key_conf conf;
- u8 key[32];
- } conf = {
- .conf.cipher = gtk_cipher,
- };
int link_id = vif->active_links ? __ffs(vif->active_links) : -1;
- BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP);
- BUILD_BUG_ON(sizeof(conf.key) < sizeof(status->gtk[0].key));
-
- switch (gtk_cipher) {
- case WLAN_CIPHER_SUITE_CCMP:
- case WLAN_CIPHER_SUITE_GCMP:
- conf.conf.keylen = WLAN_KEY_LEN_CCMP;
- break;
- case WLAN_CIPHER_SUITE_GCMP_256:
- conf.conf.keylen = WLAN_KEY_LEN_GCMP_256;
- break;
- case WLAN_CIPHER_SUITE_TKIP:
- conf.conf.keylen = WLAN_KEY_LEN_TKIP;
- break;
- default:
- WARN_ON(1);
- }
-
for (i = 0; i < ARRAY_SIZE(status->gtk); i++) {
if (!status->gtk[i].len)
continue;
- conf.conf.keyidx = status->gtk[i].id;
IWL_DEBUG_WOWLAN(mvm,
- "Received from FW GTK cipher %d, key index %d\n",
- conf.conf.cipher, conf.conf.keyidx);
- memcpy(conf.conf.key, status->gtk[i].key,
- sizeof(status->gtk[i].key));
-
- key = ieee80211_gtk_rekey_add(vif, &conf.conf, link_id);
- if (IS_ERR(key))
+ "Received from FW GTK: key index %d\n",
+ status->gtk[i].id);
+
+ key = ieee80211_gtk_rekey_add(vif, status->gtk[i].id,
+ status->gtk[i].key,
+ sizeof(status->gtk[i].key),
+ link_id);
+ if (IS_ERR(key)) {
+ /* FW may send also the old keys */
+ if (PTR_ERR(key) == -EALREADY)
+ continue;
return false;
+ }
for (j = 0; j < ARRAY_SIZE(status->gtk_seq); j++) {
if (!status->gtk_seq[j].valid ||
@@ -2217,58 +1912,42 @@ static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status,
static bool
iwl_mvm_d3_igtk_bigtk_rekey_add(struct iwl_wowlan_status_data *status,
- struct ieee80211_vif *vif, u32 cipher,
+ struct ieee80211_vif *vif,
struct iwl_multicast_key_data *key_data)
{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_key_conf *key_config;
- struct {
- struct ieee80211_key_conf conf;
- u8 key[WOWLAN_KEY_MAX_SIZE];
- } conf = {
- .conf.cipher = cipher,
- .conf.keyidx = key_data->id,
- };
struct ieee80211_key_seq seq;
int link_id = vif->active_links ? __ffs(vif->active_links) : -1;
+ s8 keyidx = key_data->id;
if (!key_data->len)
return true;
- iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, conf.conf.cipher);
-
- switch (cipher) {
- case WLAN_CIPHER_SUITE_BIP_GMAC_128:
- conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_128;
- break;
- case WLAN_CIPHER_SUITE_BIP_GMAC_256:
- conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_256;
- break;
- case WLAN_CIPHER_SUITE_AES_CMAC:
- conf.conf.keylen = WLAN_KEY_LEN_AES_CMAC;
- break;
- case WLAN_CIPHER_SUITE_BIP_CMAC_256:
- conf.conf.keylen = WLAN_KEY_LEN_BIP_CMAC_256;
- break;
- default:
- WARN_ON(1);
+ key_config = ieee80211_gtk_rekey_add(vif, keyidx, key_data->key,
+ sizeof(key_data->key), link_id);
+ if (IS_ERR(key_config)) {
+ /* FW may send also the old keys */
+ return PTR_ERR(key_config) == -EALREADY;
}
- BUILD_BUG_ON(sizeof(conf.key) < sizeof(key_data->key));
- memcpy(conf.conf.key, key_data->key, conf.conf.keylen);
- key_config = ieee80211_gtk_rekey_add(vif, &conf.conf, link_id);
- if (IS_ERR(key_config))
- return false;
+ iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, key_config->cipher);
ieee80211_set_key_rx_seq(key_config, 0, &seq);
- if (key_config->keyidx == 4 || key_config->keyidx == 5) {
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ if (keyidx == 4 || keyidx == 5) {
struct iwl_mvm_vif_link_info *mvm_link;
link_id = link_id < 0 ? 0 : link_id;
mvm_link = mvmvif->link[link_id];
+ if (mvm_link->igtk)
+ mvm_link->igtk->hw_key_idx = STA_KEY_IDX_INVALID;
mvm_link->igtk = key_config;
}
+ if (vif->type == NL80211_IFTYPE_STATION && (keyidx == 6 || keyidx == 7))
+ rcu_assign_pointer(mvmvif->bcn_prot.keys[keyidx - 6],
+ key_config);
+
return true;
}
@@ -2306,27 +1985,6 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
if (!status || !vif->bss_conf.bssid)
return false;
-
- if (iwl_mvm_lookup_wowlan_status_ver(mvm) > 6 ||
- iwl_fw_lookup_notif_ver(mvm->fw, PROT_OFFLOAD_GROUP,
- WOWLAN_INFO_NOTIFICATION,
- 0))
- gtkdata.igtk_support = true;
-
- if (iwl_fw_lookup_notif_ver(mvm->fw, PROT_OFFLOAD_GROUP,
- WOWLAN_INFO_NOTIFICATION,
- 0) >= 3)
- gtkdata.bigtk_support = true;
-
- /* find last GTK that we used initially, if any */
- ieee80211_iter_keys(mvm->hw, vif,
- iwl_mvm_d3_find_last_keys, &gtkdata);
- /* not trying to keep connections with MFP/unhandled ciphers */
- if (gtkdata.unhandled_cipher)
- return false;
- if (!gtkdata.num_keys)
- goto out;
-
/*
* invalidate all other GTKs that might still exist and update
* the one that we used
@@ -2340,29 +1998,23 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
IWL_DEBUG_WOWLAN(mvm, "num of GTK rekeying %d\n",
status->num_of_gtk_rekeys);
- if (!iwl_mvm_gtk_rekey(status, vif, mvm, gtkdata.gtk_cipher))
+ if (!iwl_mvm_gtk_rekey(status, vif, mvm))
return false;
if (!iwl_mvm_d3_igtk_bigtk_rekey_add(status, vif,
- gtkdata.igtk_cipher,
&status->igtk))
return false;
for (i = 0; i < ARRAY_SIZE(status->bigtk); i++) {
if (!iwl_mvm_d3_igtk_bigtk_rekey_add(status, vif,
- gtkdata.bigtk_cipher,
&status->bigtk[i]))
return false;
}
- if (!iwl_mvm_mlo_gtk_rekey(status, vif, mvm))
- return false;
-
ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,
(void *)&replay_ctr, GFP_KERNEL);
}
-out:
if (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP,
WOWLAN_GET_STATUSES,
IWL_FW_CMD_VER_UNKNOWN) < 10) {
@@ -2387,6 +2039,7 @@ static void iwl_mvm_convert_gtk_v2(struct iwl_wowlan_status_data *status,
status->gtk[0].len = data->key_len;
status->gtk[0].flags = data->key_flags;
+ status->gtk[0].id = status->gtk[0].flags & IWL_WOWLAN_GTK_IDX_MASK;
memcpy(status->gtk[0].key, data->key, sizeof(data->key));
@@ -2429,7 +2082,7 @@ static void iwl_mvm_convert_gtk_v3(struct iwl_wowlan_status_data *status,
}
static void iwl_mvm_convert_igtk(struct iwl_wowlan_status_data *status,
- struct iwl_wowlan_igtk_status *data)
+ struct iwl_wowlan_igtk_status_v1 *data)
{
int i;
@@ -2453,7 +2106,7 @@ static void iwl_mvm_convert_igtk(struct iwl_wowlan_status_data *status,
}
static void iwl_mvm_convert_bigtk(struct iwl_wowlan_status_data *status,
- const struct iwl_wowlan_igtk_status *data)
+ const struct iwl_wowlan_igtk_status_v1 *data)
{
int data_idx, status_idx = 0;
@@ -2484,14 +2137,15 @@ static void iwl_mvm_convert_bigtk(struct iwl_wowlan_status_data *status,
}
static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
- struct iwl_wowlan_info_notif *data,
+ struct iwl_wowlan_info_notif_v5 *data,
struct iwl_wowlan_status_data *status,
u32 len)
{
- u32 expected_len = sizeof(*data) +
- data->num_mlo_link_keys * sizeof(status->mlo_keys[0]);
+ if (IWL_FW_CHECK(mvm, data->num_mlo_link_keys,
+ "MLO is not supported, shouldn't receive MLO keys\n"))
+ return;
- if (len < expected_len) {
+ if (len < sizeof(*data)) {
IWL_ERR(mvm, "Invalid WoWLAN info notification!\n");
status = NULL;
return;
@@ -2520,33 +2174,17 @@ static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
le32_to_cpu(data->num_of_gtk_rekeys);
status->received_beacons = le32_to_cpu(data->received_beacons);
status->tid_tear_down = data->tid_tear_down;
-
- if (data->num_mlo_link_keys) {
- status->num_mlo_keys = data->num_mlo_link_keys;
- if (IWL_FW_CHECK(mvm,
- status->num_mlo_keys > WOWLAN_MAX_MLO_KEYS,
- "Too many mlo keys: %d, max %d\n",
- status->num_mlo_keys, WOWLAN_MAX_MLO_KEYS))
- status->num_mlo_keys = WOWLAN_MAX_MLO_KEYS;
- memcpy(status->mlo_keys, data->mlo_gtks,
- status->num_mlo_keys * sizeof(status->mlo_keys[0]));
- }
}
static void
-iwl_mvm_parse_wowlan_info_notif_v4(struct iwl_mvm *mvm,
- struct iwl_wowlan_info_notif_v4 *data,
+iwl_mvm_parse_wowlan_info_notif_v3(struct iwl_mvm *mvm,
+ struct iwl_wowlan_info_notif_v3 *data,
struct iwl_wowlan_status_data *status,
- u32 len, bool has_mlo_keys)
+ u32 len)
{
u32 i;
- u32 expected_len = sizeof(*data);
-
- if (has_mlo_keys)
- expected_len += (data->num_mlo_link_keys *
- sizeof(status->mlo_keys[0]));
- if (len < expected_len) {
+ if (len < sizeof(*data)) {
IWL_ERR(mvm, "Invalid WoWLAN info notification!\n");
status = NULL;
return;
@@ -2569,22 +2207,11 @@ iwl_mvm_parse_wowlan_info_notif_v4(struct iwl_mvm *mvm,
le32_to_cpu(data->num_of_gtk_rekeys);
status->received_beacons = le32_to_cpu(data->received_beacons);
status->tid_tear_down = data->tid_tear_down;
-
- if (has_mlo_keys && data->num_mlo_link_keys) {
- status->num_mlo_keys = data->num_mlo_link_keys;
- if (IWL_FW_CHECK(mvm,
- status->num_mlo_keys > WOWLAN_MAX_MLO_KEYS,
- "Too many mlo keys: %d, max %d\n",
- status->num_mlo_keys, WOWLAN_MAX_MLO_KEYS))
- status->num_mlo_keys = WOWLAN_MAX_MLO_KEYS;
- memcpy(status->mlo_keys, data->mlo_gtks,
- status->num_mlo_keys * sizeof(status->mlo_keys[0]));
- }
}
static void
-iwl_mvm_parse_wowlan_info_notif_v2(struct iwl_mvm *mvm,
- struct iwl_wowlan_info_notif_v2 *data,
+iwl_mvm_parse_wowlan_info_notif_v1(struct iwl_mvm *mvm,
+ struct iwl_wowlan_info_notif_v1 *data,
struct iwl_wowlan_status_data *status,
u32 len)
{
@@ -2669,8 +2296,6 @@ iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm, \
iwl_mvm_parse_wowlan_status_common(v6)
iwl_mvm_parse_wowlan_status_common(v7)
-iwl_mvm_parse_wowlan_status_common(v9)
-iwl_mvm_parse_wowlan_status_common(v12)
static struct iwl_wowlan_status_data *
iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
@@ -2726,7 +2351,8 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
v6->gtk.tkip_mic_key,
sizeof(v6->gtk.tkip_mic_key));
- iwl_mvm_convert_key_counters(status, &v6->gtk.rsc.all_tsc_rsc);
+ iwl_mvm_convert_key_counters(status, &v6->gtk.rsc.all_tsc_rsc,
+ v6->gtk.key_index);
/* hardcode the key length to 16 since v6 only supports 16 */
status->gtk[0].len = 16;
@@ -2737,6 +2363,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
* currently used key.
*/
status->gtk[0].flags = v6->gtk.key_index | BIT(7);
+ status->gtk[0].id = v6->gtk.key_index;
} else if (notif_ver == 7) {
struct iwl_wowlan_status_v7 *v7 = (void *)cmd.resp_pkt->data;
@@ -2744,36 +2371,10 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
if (!status)
goto out_free_resp;
- iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc);
+ iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc,
+ v7->gtk[0].key_flags & IWL_WOWLAN_GTK_IDX_MASK);
iwl_mvm_convert_gtk_v2(status, &v7->gtk[0]);
iwl_mvm_convert_igtk(status, &v7->igtk[0]);
- } else if (notif_ver == 9 || notif_ver == 10 || notif_ver == 11) {
- struct iwl_wowlan_status_v9 *v9 = (void *)cmd.resp_pkt->data;
-
- /* these three command versions have same layout and size, the
- * difference is only in a few not used (reserved) fields.
- */
- status = iwl_mvm_parse_wowlan_status_common_v9(mvm, v9, len);
- if (!status)
- goto out_free_resp;
-
- iwl_mvm_convert_key_counters(status, &v9->gtk[0].rsc.all_tsc_rsc);
- iwl_mvm_convert_gtk_v2(status, &v9->gtk[0]);
- iwl_mvm_convert_igtk(status, &v9->igtk[0]);
-
- status->tid_tear_down = v9->tid_tear_down;
- } else if (notif_ver == 12) {
- struct iwl_wowlan_status_v12 *v12 = (void *)cmd.resp_pkt->data;
-
- status = iwl_mvm_parse_wowlan_status_common_v12(mvm, v12, len);
- if (!status)
- goto out_free_resp;
-
- iwl_mvm_convert_key_counters_v5(status, &v12->gtk[0].sc);
- iwl_mvm_convert_gtk_v3(status, v12->gtk);
- iwl_mvm_convert_igtk(status, &v12->igtk[0]);
-
- status->tid_tear_down = v12->tid_tear_down;
} else {
IWL_ERR(mvm,
"Firmware advertises unknown WoWLAN status response %d!\n",
@@ -2825,7 +2426,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
status->qos_seq_ctr[i] + 0x10;
}
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
+ if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
i = mvm->offload_tid;
iwl_trans_set_q_ptrs(mvm->trans,
mvm_ap_sta->tid_data[i].txq_id,
@@ -2972,7 +2573,6 @@ enum iwl_d3_notif {
/* manage d3 resume data */
struct iwl_d3_data {
struct iwl_wowlan_status_data *status;
- bool test;
u32 d3_end_flags;
u32 notif_expected; /* bitmap - see &enum iwl_d3_notif */
u32 notif_received; /* bitmap - see &enum iwl_d3_notif */
@@ -3164,18 +2764,11 @@ iwl_mvm_choose_query_wakeup_reasons(struct iwl_mvm *mvm,
if (mvm->net_detect) {
iwl_mvm_query_netdetect_reasons(mvm, vif, d3_data);
- } else {
- bool keep = iwl_mvm_query_wakeup_reasons(mvm, vif,
- d3_data->status);
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
- if (keep)
- mvm->keep_vif = vif;
-#endif
-
- return keep;
+ return false;
}
- return false;
+
+ return iwl_mvm_query_wakeup_reasons(mvm, vif,
+ d3_data->status);
}
#define IWL_WOWLAN_WAKEUP_REASON_HAS_WAKEUP_PKT (IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET | \
@@ -3300,44 +2893,30 @@ static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait,
break;
}
- if (wowlan_info_ver < 2) {
+ if (wowlan_info_ver == 1) {
struct iwl_wowlan_info_notif_v1 *notif_v1 =
(void *)pkt->data;
- struct iwl_wowlan_info_notif_v2 *notif_v2;
-
- notif_v2 = kmemdup(notif_v1, sizeof(*notif_v2), GFP_ATOMIC);
-
- if (!notif_v2)
- return false;
-
- notif_v2->tid_tear_down = notif_v1->tid_tear_down;
- notif_v2->station_id = notif_v1->station_id;
- memset_after(notif_v2, 0, station_id);
- iwl_mvm_parse_wowlan_info_notif_v2(mvm, notif_v2,
- d3_data->status,
- len);
- kfree(notif_v2);
-
- } else if (wowlan_info_ver == 2) {
- struct iwl_wowlan_info_notif_v2 *notif_v2 =
- (void *)pkt->data;
- iwl_mvm_parse_wowlan_info_notif_v2(mvm, notif_v2,
+ iwl_mvm_parse_wowlan_info_notif_v1(mvm, notif_v1,
d3_data->status,
len);
- } else if (wowlan_info_ver < 5) {
- struct iwl_wowlan_info_notif_v4 *notif =
+ } else if (wowlan_info_ver == 3) {
+ struct iwl_wowlan_info_notif_v3 *notif =
(void *)pkt->data;
- iwl_mvm_parse_wowlan_info_notif_v4(mvm, notif,
- d3_data->status, len,
- wowlan_info_ver > 3);
- } else {
- struct iwl_wowlan_info_notif *notif =
+ iwl_mvm_parse_wowlan_info_notif_v3(mvm, notif,
+ d3_data->status, len);
+ } else if (wowlan_info_ver == 5) {
+ struct iwl_wowlan_info_notif_v5 *notif =
(void *)pkt->data;
iwl_mvm_parse_wowlan_info_notif(mvm, notif,
d3_data->status, len);
+ } else {
+ IWL_FW_CHECK(mvm, 1,
+ "Firmware advertises unknown WoWLAN info notification %d!\n",
+ wowlan_info_ver);
+ return false;
}
d3_data->notif_received |= IWL_D3_NOTIF_WOWLAN_INFO;
@@ -3402,32 +2981,26 @@ static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait,
return d3_data->notif_received == d3_data->notif_expected;
}
-static int iwl_mvm_resume_firmware(struct iwl_mvm *mvm, bool test)
+static int iwl_mvm_resume_firmware(struct iwl_mvm *mvm)
{
int ret;
- enum iwl_d3_status d3_status;
struct iwl_host_cmd cmd = {
- .id = D0I3_END_CMD,
- .flags = CMD_WANT_SKB | CMD_SEND_IN_D3,
- };
+ .id = D0I3_END_CMD,
+ .flags = CMD_WANT_SKB,
+ };
bool reset = fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
- ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test, !reset);
+ ret = iwl_trans_d3_resume(mvm->trans, !reset);
if (ret)
return ret;
- if (d3_status != IWL_D3_STATUS_ALIVE) {
- IWL_INFO(mvm, "Device was reset during suspend\n");
- return -ENOENT;
- }
-
/*
* We should trigger resume flow using command only for 22000 family
* AX210 and above don't need the command since they have
* the doorbell interrupt.
*/
- if (mvm->trans->trans_cfg->device_family <= IWL_DEVICE_FAMILY_22000 &&
+ if (mvm->trans->mac_cfg->device_family <= IWL_DEVICE_FAMILY_22000 &&
fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_D0I3_END_FIRST)) {
ret = iwl_mvm_send_cmd(mvm, &cmd);
if (ret < 0)
@@ -3466,7 +3039,7 @@ static int iwl_mvm_d3_notif_wait(struct iwl_mvm *mvm,
ARRAY_SIZE(d3_resume_notif),
iwl_mvm_wait_d3_notif, d3_data);
- ret = iwl_mvm_resume_firmware(mvm, d3_data->test);
+ ret = iwl_mvm_resume_firmware(mvm);
if (ret) {
iwl_remove_notification(&mvm->notif_wait, &wait_d3_notif);
return ret;
@@ -3486,13 +3059,12 @@ static inline bool iwl_mvm_d3_resume_notif_based(struct iwl_mvm *mvm)
D3_END_NOTIFICATION, 0);
}
-static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
+static int __iwl_mvm_resume(struct iwl_mvm *mvm)
{
struct ieee80211_vif *vif = NULL;
int ret = 1;
struct iwl_mvm_nd_results results = {};
struct iwl_d3_data d3_data = {
- .test = test,
.notif_expected =
IWL_D3_NOTIF_WOWLAN_INFO |
IWL_D3_NOTIF_D3_END_NOTIF,
@@ -3530,7 +3102,7 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
rt_status = iwl_mvm_check_rt_status(mvm, vif);
if (rt_status != FW_ALIVE) {
- set_bit(STATUS_FW_ERROR, &mvm->trans->status);
+ iwl_trans_notify_fw_error(mvm->trans);
if (rt_status == FW_ERROR) {
IWL_ERR(mvm, "FW Error occurred during suspend. Restarting.\n");
iwl_mvm_dump_nic_error_log(mvm);
@@ -3557,16 +3129,11 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
if (ret)
goto err;
} else {
- ret = iwl_mvm_resume_firmware(mvm, test);
+ ret = iwl_mvm_resume_firmware(mvm);
if (ret < 0)
goto err;
}
- iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_WOWLAN);
-
- /* after the successful handshake, we're out of D3 */
- mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
-
/* when reset is required we can't send these following commands */
if (d3_data.d3_end_flags & IWL_D0I3_RESET_REQUIRE)
goto query_wakeup_reasons;
@@ -3608,7 +3175,7 @@ out:
kfree(d3_data.status);
iwl_mvm_free_nd(mvm);
- if (!d3_data.test && !mvm->net_detect)
+ if (!mvm->net_detect)
ieee80211_iterate_active_interfaces_mtx(mvm->hw,
IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_d3_disconnect_iter,
@@ -3639,9 +3206,6 @@ out:
*/
set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
- /* regardless of what happened, we're now out of D3 */
- mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
-
return 1;
}
@@ -3650,7 +3214,7 @@ int iwl_mvm_resume(struct ieee80211_hw *hw)
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
- ret = __iwl_mvm_resume(mvm, false);
+ ret = __iwl_mvm_resume(mvm);
iwl_mvm_resume_tcm(mvm);
@@ -3679,14 +3243,13 @@ void iwl_mvm_fast_suspend(struct iwl_mvm *mvm)
set_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);
WARN_ON(iwl_mvm_power_update_device(mvm));
- mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;
- ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, CMD_SEND_IN_D3,
+ ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, 0,
sizeof(d3_cfg_cmd_data), &d3_cfg_cmd_data);
if (ret)
IWL_ERR(mvm,
"fast suspend: couldn't send D3_CONFIG_CMD %d\n", ret);
- ret = iwl_trans_d3_suspend(mvm->trans, false, false);
+ ret = iwl_trans_d3_suspend(mvm->trans, false);
if (ret)
IWL_ERR(mvm, "fast suspend: trans_d3_suspend failed %d\n", ret);
}
@@ -3709,7 +3272,7 @@ int iwl_mvm_fast_resume(struct iwl_mvm *mvm)
rt_status = iwl_mvm_check_rt_status(mvm, NULL);
if (rt_status != FW_ALIVE) {
- set_bit(STATUS_FW_ERROR, &mvm->trans->status);
+ iwl_trans_notify_fw_error(mvm->trans);
if (rt_status == FW_ERROR) {
IWL_ERR(mvm,
"iwl_mvm_check_rt_status failed, device is gone during suspend\n");
@@ -3721,7 +3284,6 @@ int iwl_mvm_fast_resume(struct iwl_mvm *mvm)
&iwl_dump_desc_assert,
false, 0);
}
- mvm->trans->state = IWL_TRANS_NO_FW;
ret = -ENODEV;
goto out;
@@ -3735,130 +3297,7 @@ int iwl_mvm_fast_resume(struct iwl_mvm *mvm)
out:
clear_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);
- mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
mvm->fast_resume = false;
return ret;
}
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file)
-{
- struct iwl_mvm *mvm = inode->i_private;
- int err;
-
- if (mvm->d3_test_active)
- return -EBUSY;
-
- file->private_data = inode->i_private;
-
- iwl_mvm_pause_tcm(mvm, true);
-
- iwl_fw_runtime_suspend(&mvm->fwrt);
-
- /* start pseudo D3 */
- rtnl_lock();
- wiphy_lock(mvm->hw->wiphy);
- err = __iwl_mvm_suspend(mvm->hw, mvm->hw->wiphy->wowlan_config, true);
- wiphy_unlock(mvm->hw->wiphy);
- rtnl_unlock();
- if (err > 0)
- err = -EINVAL;
- if (err)
- return err;
-
- mvm->d3_test_active = true;
- mvm->keep_vif = NULL;
- return 0;
-}
-
-static ssize_t iwl_mvm_d3_test_read(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_mvm *mvm = file->private_data;
- unsigned long end = jiffies + 60 * HZ;
- u32 pme_asserted;
-
- while (true) {
- /* read pme_ptr if available */
- if (mvm->d3_test_pme_ptr) {
- pme_asserted = iwl_trans_read_mem32(mvm->trans,
- mvm->d3_test_pme_ptr);
- if (pme_asserted)
- break;
- }
-
- if (msleep_interruptible(100))
- break;
-
- if (time_is_before_jiffies(end)) {
- IWL_ERR(mvm,
- "ending pseudo-D3 with timeout after ~60 seconds\n");
- return -ETIMEDOUT;
- }
- }
-
- return 0;
-}
-
-static void iwl_mvm_d3_test_disconn_work_iter(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
-{
- /* skip the one we keep connection on */
- if (_data == vif)
- return;
-
- if (vif->type == NL80211_IFTYPE_STATION)
- ieee80211_connection_loss(vif);
-}
-
-static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file)
-{
- struct iwl_mvm *mvm = inode->i_private;
- bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
-
- mvm->d3_test_active = false;
-
- iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt);
-
- rtnl_lock();
- wiphy_lock(mvm->hw->wiphy);
- __iwl_mvm_resume(mvm, true);
- wiphy_unlock(mvm->hw->wiphy);
- rtnl_unlock();
-
- iwl_mvm_resume_tcm(mvm);
-
- iwl_fw_runtime_resume(&mvm->fwrt);
-
- iwl_abort_notification_waits(&mvm->notif_wait);
- if (!unified_image) {
- int remaining_time = 10;
-
- ieee80211_restart_hw(mvm->hw);
-
- /* wait for restart and disconnect all interfaces */
- while (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
- remaining_time > 0) {
- remaining_time--;
- msleep(1000);
- }
-
- if (remaining_time == 0)
- IWL_ERR(mvm, "Timed out waiting for HW restart!\n");
- }
-
- ieee80211_iterate_active_interfaces_atomic(
- mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
- iwl_mvm_d3_test_disconn_work_iter, mvm->keep_vif);
-
- return 0;
-}
-
-const struct file_operations iwl_dbgfs_d3_test_ops = {
- .open = iwl_mvm_d3_test_open,
- .read = iwl_mvm_d3_test_read,
- .release = iwl_mvm_d3_test_release,
-};
-#endif
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
index fbe4e4a50852..a56c352a459a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
@@ -762,96 +762,6 @@ static ssize_t iwl_dbgfs_max_tx_op_read(struct file *file,
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
-static ssize_t iwl_dbgfs_int_mlo_scan_write(struct ieee80211_vif *vif,
- char *buf, size_t count,
- loff_t *ppos)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
- u32 action;
- int ret;
-
- if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif))
- return -EINVAL;
-
- if (kstrtou32(buf, 0, &action))
- return -EINVAL;
-
- mutex_lock(&mvm->mutex);
-
- if (!action) {
- ret = iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_INT_MLO, false);
- } else if (action == 1) {
- ret = iwl_mvm_int_mlo_scan(mvm, vif);
- } else {
- ret = -EINVAL;
- }
-
- mutex_unlock(&mvm->mutex);
-
- return ret ?: count;
-}
-
-static ssize_t iwl_dbgfs_esr_disable_reason_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ieee80211_vif *vif = file->private_data;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
- unsigned long esr_mask;
- char *buf;
- int bufsz, pos, i;
- ssize_t rv;
-
- mutex_lock(&mvm->mutex);
- esr_mask = mvmvif->esr_disable_reason;
- mutex_unlock(&mvm->mutex);
-
- bufsz = hweight32(esr_mask) * 32 + 40;
- buf = kmalloc(bufsz, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- pos = scnprintf(buf, bufsz, "EMLSR state: '0x%lx'\nreasons:\n",
- esr_mask);
- for_each_set_bit(i, &esr_mask, BITS_PER_LONG)
- pos += scnprintf(buf + pos, bufsz - pos, " - %s\n",
- iwl_get_esr_state_string(BIT(i)));
-
- rv = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
- kfree(buf);
- return rv;
-}
-
-static ssize_t iwl_dbgfs_esr_disable_reason_write(struct ieee80211_vif *vif,
- char *buf, size_t count,
- loff_t *ppos)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
- u32 reason;
- u8 block;
- int ret;
-
- ret = sscanf(buf, "%u %hhu", &reason, &block);
- if (ret < 0)
- return ret;
-
- if (hweight16(reason) != 1 || !(reason & IWL_MVM_BLOCK_ESR_REASONS))
- return -EINVAL;
-
- mutex_lock(&mvm->mutex);
- if (block)
- iwl_mvm_block_esr(mvm, vif, reason,
- iwl_mvm_get_primary_link(vif));
- else
- iwl_mvm_unblock_esr(mvm, vif, reason);
- mutex_unlock(&mvm->mutex);
-
- return count;
-}
-
#define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
_MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
@@ -884,8 +794,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(rx_phyinfo, 10);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32);
MVM_DEBUGFS_READ_FILE_OPS(os_device_timediff);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(max_tx_op, 10);
-MVM_DEBUGFS_WRITE_FILE_OPS(int_mlo_scan, 32);
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(esr_disable_reason, 32);
void iwl_mvm_vif_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
@@ -916,8 +824,6 @@ void iwl_mvm_vif_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
MVM_DEBUGFS_ADD_FILE_VIF(max_tx_op, mvmvif->dbgfs_dir, 0600);
debugfs_create_bool("ftm_unprotected", 0200, mvmvif->dbgfs_dir,
&mvmvif->ftm_unprotected);
- MVM_DEBUGFS_ADD_FILE_VIF(int_mlo_scan, mvmvif->dbgfs_dir, 0200);
- MVM_DEBUGFS_ADD_FILE_VIF(esr_disable_reason, mvmvif->dbgfs_dir, 0600);
if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
mvmvif == mvm->bf_allowed_vif)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index 671d3f8d79c1..683c0ba5fb39 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -1134,7 +1134,7 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
if (count == 6 && !strcmp(buf, "nolog\n")) {
set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status);
- set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &mvm->trans->status);
+ mvm->trans->suppress_cmd_error_once = true;
}
/* take the return value to make compiler happy - it will fail anyway */
@@ -1277,7 +1277,7 @@ static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
return -EIO;
/* supporting only MQ RX */
- if (!mvm->trans->trans_cfg->mq_rx_supported)
+ if (!mvm->trans->mac_cfg->mq_rx_supported)
return -EOPNOTSUPP;
rxb._page = alloc_pages(GFP_ATOMIC, 0);
@@ -1468,7 +1468,7 @@ static ssize_t iwl_dbgfs_fw_dbg_clear_write(struct iwl_mvm *mvm,
char *buf, size_t count,
loff_t *ppos)
{
- if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000)
+ if (mvm->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_9000)
return -EOPNOTSUPP;
/*
@@ -2159,7 +2159,6 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm)
MVM_DEBUGFS_ADD_FILE(uapsd_noagg_bssids, mvm->debugfs_dir, S_IRUSR);
#ifdef CONFIG_PM_SLEEP
- MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, 0400);
debugfs_create_bool("d3_wake_sysassert", 0600, mvm->debugfs_dir,
&mvm->d3_wake_sysassert);
debugfs_create_u32("last_netdetect_scans", 0400, mvm->debugfs_dir,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 2b5a62604fc4..edae13755ee6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -29,8 +29,8 @@
#define MVM_UCODE_CALIB_TIMEOUT (2 * HZ)
struct iwl_mvm_alive_data {
+ __le32 sku_id[3];
bool valid;
- u32 scd_base_addr;
};
static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant)
@@ -57,13 +57,13 @@ static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm)
BIT(IWL_RSS_HASH_TYPE_IPV6_PAYLOAD),
};
- if (mvm->trans->num_rx_queues == 1)
+ if (mvm->trans->info.num_rxqs == 1)
return 0;
/* Do not direct RSS traffic to Q 0 which is our fallback queue */
for (i = 0; i < ARRAY_SIZE(cmd.indirection_table); i++)
cmd.indirection_table[i] =
- 1 + (i % (mvm->trans->num_rx_queues - 1));
+ 1 + (i % (mvm->trans->info.num_rxqs - 1));
netdev_rss_key_fill(cmd.secret_key, sizeof(cmd.secret_key));
return iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd);
@@ -114,13 +114,29 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
u32 i;
- if (version == 6) {
- struct iwl_alive_ntf_v6 *palive;
+ if (version >= 6) {
+ struct iwl_alive_ntf_v7 *palive;
if (pkt_len < sizeof(*palive))
return false;
palive = (void *)pkt->data;
+
+ umac = &palive->umac_data;
+ lmac1 = &palive->lmac_data[0];
+ lmac2 = &palive->lmac_data[1];
+ status = le16_to_cpu(palive->status);
+
+ BUILD_BUG_ON(sizeof(palive->sku_id.data) !=
+ sizeof(alive_data->sku_id));
+ memcpy(alive_data->sku_id, palive->sku_id.data,
+ sizeof(palive->sku_id.data));
+
+ IWL_DEBUG_FW(mvm, "Got sku_id: 0x0%x 0x0%x 0x0%x\n",
+ le32_to_cpu(alive_data->sku_id[0]),
+ le32_to_cpu(alive_data->sku_id[1]),
+ le32_to_cpu(alive_data->sku_id[2]));
+
mvm->trans->dbg.imr_data.imr_enable =
le32_to_cpu(palive->imr.enabled);
mvm->trans->dbg.imr_data.imr_size =
@@ -157,39 +173,17 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
}
}
}
- }
- if (version >= 5) {
- struct iwl_alive_ntf_v5 *palive;
+ if (version >= 8) {
+ const struct iwl_alive_ntf *palive_v8 =
+ (void *)pkt->data;
- if (pkt_len < sizeof(*palive))
- return false;
-
- palive = (void *)pkt->data;
- umac = &palive->umac_data;
- lmac1 = &palive->lmac_data[0];
- lmac2 = &palive->lmac_data[1];
- status = le16_to_cpu(palive->status);
+ if (pkt_len < sizeof(*palive_v8))
+ return false;
- mvm->trans->sku_id[0] = le32_to_cpu(palive->sku_id.data[0]);
- mvm->trans->sku_id[1] = le32_to_cpu(palive->sku_id.data[1]);
- mvm->trans->sku_id[2] = le32_to_cpu(palive->sku_id.data[2]);
-
- IWL_DEBUG_FW(mvm, "Got sku_id: 0x0%x 0x0%x 0x0%x\n",
- mvm->trans->sku_id[0],
- mvm->trans->sku_id[1],
- mvm->trans->sku_id[2]);
- } else if (iwl_rx_packet_payload_len(pkt) == sizeof(struct iwl_alive_ntf_v4)) {
- struct iwl_alive_ntf_v4 *palive;
-
- if (pkt_len < sizeof(*palive))
- return false;
-
- palive = (void *)pkt->data;
- umac = &palive->umac_data;
- lmac1 = &palive->lmac_data[0];
- lmac2 = &palive->lmac_data[1];
- status = le16_to_cpu(palive->status);
+ IWL_DEBUG_FW(mvm, "platform id: 0x%llx\n",
+ palive_v8->platform_id);
+ }
} else if (iwl_rx_packet_payload_len(pkt) ==
sizeof(struct iwl_alive_ntf_v3)) {
struct iwl_alive_ntf_v3 *palive3;
@@ -220,20 +214,10 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
~FW_ADDR_CACHE_CONTROL;
if (umac_error_table) {
- if (umac_error_table >=
- mvm->trans->cfg->min_umac_error_event_table) {
- iwl_fw_umac_set_alive_err_table(mvm->trans,
- umac_error_table);
- } else {
- IWL_ERR(mvm,
- "Not valid error log pointer 0x%08X for %s uCode\n",
- umac_error_table,
- (mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) ?
- "Init" : "RT");
- }
+ iwl_fw_umac_set_alive_err_table(mvm->trans,
+ umac_error_table);
}
- alive_data->scd_base_addr = le32_to_cpu(lmac1->dbg_ptrs.scd_base_ptr);
alive_data->valid = status == IWL_ALIVE_STATUS_OK;
IWL_DEBUG_FW(mvm,
@@ -282,7 +266,7 @@ static void iwl_mvm_print_pd_notification(struct iwl_mvm *mvm)
IWL_ERR(mvm, #reg_name ": 0x%x\n", iwl_read_umac_prph(trans, reg_name))
struct iwl_trans *trans = mvm->trans;
- enum iwl_device_family device_family = trans->trans_cfg->device_family;
+ enum iwl_device_family device_family = trans->mac_cfg->device_family;
if (device_family < IWL_DEVICE_FAMILY_8000)
return;
@@ -304,7 +288,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
{
struct iwl_notification_wait alive_wait;
struct iwl_mvm_alive_data alive_data = {};
- const struct fw_img *fw;
int ret;
enum iwl_ucode_type old_type = mvm->fwrt.cur_fw_img;
static const u16 alive_cmd[] = { UCODE_ALIVE_NTFY };
@@ -317,11 +300,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE) &&
!(fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_USNIFFER_UNIFIED)))
- fw = iwl_get_ucode_image(mvm->fw, IWL_UCODE_REGULAR_USNIFFER);
- else
- fw = iwl_get_ucode_image(mvm->fw, ucode_type);
- if (WARN_ON(!fw))
- return -EINVAL;
+ ucode_type = IWL_UCODE_REGULAR_USNIFFER;
iwl_fw_set_current_image(&mvm->fwrt, ucode_type);
clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
@@ -334,7 +313,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
* For the unified firmware case, the ucode_type is not
* INIT, but we still need to run it.
*/
- ret = iwl_trans_start_fw(mvm->trans, fw, run_in_rfkill);
+ ret = iwl_trans_start_fw(mvm->trans, mvm->fw, ucode_type,
+ run_in_rfkill);
if (ret) {
iwl_fw_set_current_image(&mvm->fwrt, old_type);
iwl_remove_notification(&mvm->notif_wait, &alive_wait);
@@ -348,7 +328,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
ret = iwl_wait_notification(&mvm->notif_wait, &alive_wait,
MVM_UCODE_ALIVE_TIMEOUT);
- if (mvm->trans->trans_cfg->device_family ==
+ if (mvm->trans->mac_cfg->device_family ==
IWL_DEVICE_FAMILY_AX210) {
/* print these registers regardless of alive fail/success */
IWL_INFO(mvm, "WFPM_UMAC_PD_NOTIFICATION: 0x%x\n",
@@ -365,14 +345,14 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
struct iwl_trans *trans = mvm->trans;
/* SecBoot info */
- if (trans->trans_cfg->device_family >=
+ if (trans->mac_cfg->device_family >=
IWL_DEVICE_FAMILY_22000) {
IWL_ERR(mvm,
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS),
iwl_read_umac_prph(trans,
UMAG_SB_CPU_2_STATUS));
- } else if (trans->trans_cfg->device_family >=
+ } else if (trans->mac_cfg->device_family >=
IWL_DEVICE_FAMILY_8000) {
IWL_ERR(mvm,
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
@@ -383,7 +363,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
iwl_mvm_print_pd_notification(mvm);
/* LMAC/UMAC PC info */
- if (trans->trans_cfg->device_family >=
+ if (trans->mac_cfg->device_family >=
IWL_DEVICE_FAMILY_22000) {
pc_data = trans->dbg.pc_data;
for (count = 0; count < trans->dbg.num_pc;
@@ -391,7 +371,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
IWL_ERR(mvm, "%s: 0x%x\n",
pc_data->pc_name,
pc_data->pc_address);
- } else if (trans->trans_cfg->device_family >=
+ } else if (trans->mac_cfg->device_family >=
IWL_DEVICE_FAMILY_9000) {
IWL_ERR(mvm, "UMAC PC: 0x%x\n",
iwl_read_umac_prph(trans,
@@ -422,10 +402,10 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
/* if reached this point, Alive notification was received */
iwl_mei_alive_notif(true);
- iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);
+ iwl_trans_fw_alive(mvm->trans);
ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait,
- &mvm->fw->ucode_capa);
+ mvm->fw, alive_data.sku_id);
if (ret) {
IWL_ERR(mvm, "Timeout waiting for PNVM load!\n");
iwl_fw_set_current_image(&mvm->fwrt, old_type);
@@ -473,7 +453,7 @@ static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
struct iwl_phy_specific_cfg *phy_filters)
{
#ifdef CONFIG_ACPI
- *phy_filters = mvm->phy_filters;
+ *phy_filters = mvm->fwrt.phy_filters;
#endif /* CONFIG_ACPI */
}
@@ -490,7 +470,7 @@ static void iwl_mvm_uats_init(struct iwl_mvm *mvm)
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
};
- if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
+ if (mvm->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
IWL_DEBUG_RADIO(mvm, "UATS feature is not supported\n");
return;
}
@@ -504,11 +484,10 @@ static void iwl_mvm_uats_init(struct iwl_mvm *mvm)
return;
}
- ret = iwl_uefi_get_uats_table(mvm->trans, &mvm->fwrt);
- if (ret < 0) {
- IWL_DEBUG_FW(mvm, "failed to read UATS table (%d)\n", ret);
+ iwl_uefi_get_uats_table(mvm->trans, &mvm->fwrt);
+
+ if (!mvm->fwrt.uats_valid)
return;
- }
ret = iwl_mvm_send_cmd(mvm, &cmd);
if (ret < 0)
@@ -578,7 +557,7 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
/* set flags extra PHY configuration flags from the device's cfg */
phy_cfg_cmd.phy_cfg |=
- cpu_to_le32(mvm->trans->trans_cfg->extra_phy_cfg_flags);
+ cpu_to_le32(mvm->trans->mac_cfg->extra_phy_cfg_flags);
phy_cfg_cmd.calib_control.event_trigger =
mvm->fw->default_calib[ucode_type].event_trigger;
@@ -617,7 +596,7 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm)
mvm->rfkill_safe_init_done = false;
- if (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210) {
+ if (mvm->trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_AX210) {
sb_cfg = iwl_read_umac_prph(mvm->trans, SB_MODIFY_CFG_FLAG);
/* if needed, we'll reset this on our way out later */
mvm->fw_product_reset = sb_cfg == SB_CFG_RESIDES_IN_ROM;
@@ -651,11 +630,6 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm)
iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_AFTER_ALIVE,
NULL);
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
- mvm->trans->step_urm = !!(iwl_read_umac_prph(mvm->trans,
- CNVI_PMU_STEP_FLOW) &
- CNVI_PMU_STEP_FLOW_FORCE_URM);
-
/* Send init config command to mark that we are sending NVM access
* commands
*/
@@ -756,7 +730,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm)
goto remove_notif;
}
- if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000) {
+ if (mvm->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_8000) {
ret = iwl_mvm_send_bt_init_conf(mvm);
if (ret)
goto remove_notif;
@@ -854,7 +828,7 @@ static int iwl_mvm_config_ltr(struct iwl_mvm *mvm)
.flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE),
};
- if (!mvm->trans->ltr_enabled)
+ if (!iwl_trans_is_ltr_enabled(mvm->trans))
return 0;
return iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0,
@@ -887,17 +861,11 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
len = sizeof(cmd_v9_v10.v9);
n_subbands = IWL_NUM_SUB_BANDS_V1;
per_chain = &cmd_v9_v10.v9.per_chain[0][0];
- } else if (cmd_ver >= 7) {
- len = sizeof(cmd.v7);
+ } else if (cmd_ver == 8) {
+ len = sizeof(cmd.v8);
n_subbands = IWL_NUM_SUB_BANDS_V2;
- per_chain = cmd.v7.per_chain[0][0];
- cmd.v7.flags = cpu_to_le32(mvm->fwrt.reduced_power_flags);
- if (cmd_ver == 8)
- len = sizeof(cmd.v8);
- } else if (cmd_ver == 6) {
- len = sizeof(cmd.v6);
- n_subbands = IWL_NUM_SUB_BANDS_V2;
- per_chain = cmd.v6.per_chain[0][0];
+ per_chain = cmd.v8.per_chain[0][0];
+ cmd.v8.flags = cpu_to_le32(mvm->fwrt.reduced_power_flags);
} else if (fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_REDUCE_TX_POWER)) {
len = sizeof(cmd.v5);
@@ -1270,7 +1238,7 @@ void iwl_mvm_get_bios_tables(struct iwl_mvm *mvm)
}
}
- iwl_acpi_get_phy_filters(&mvm->fwrt, &mvm->phy_filters);
+ iwl_acpi_get_phy_filters(&mvm->fwrt);
if (iwl_bios_get_eckv(&mvm->fwrt, &mvm->ext_clock_valid))
IWL_DEBUG_RADIO(mvm, "ECKV table doesn't exist in BIOS\n");
@@ -1461,9 +1429,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
RCU_INIT_POINTER(mvm->fw_id_to_link_sta[i], NULL);
}
- for (i = 0; i < IWL_FW_MAX_LINK_ID + 1; i++)
- RCU_INIT_POINTER(mvm->link_id_to_link_conf[i], NULL);
-
mvm->tdls_cs.peer.sta_id = IWL_INVALID_STA;
/* reset quota debouncing buffer - 0xff will yield invalid data */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/led.c b/drivers/net/wireless/intel/iwlwifi/mvm/led.c
index 1ea7c44250d4..c3cc1ea3ccc9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/led.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/led.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2019 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2019, 2025 Intel Corporation
* Copyright (C) 2017 Intel Deutschland GmbH
*/
#include <linux/leds.h>
@@ -102,7 +102,7 @@ void iwl_mvm_leds_sync(struct iwl_mvm *mvm)
* if we control through the register, we're doing it
* even when the firmware isn't up, so no need to sync
*/
- if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000)
+ if (mvm->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_8000)
return;
iwl_mvm_led_set(mvm, mvm->led.brightness > 0);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
index 851869c0bd50..738facceb240 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
@@ -5,65 +5,6 @@
#include "mvm.h"
#include "time-event.h"
-#define HANDLE_ESR_REASONS(HOW) \
- HOW(BLOCKED_PREVENTION) \
- HOW(BLOCKED_WOWLAN) \
- HOW(BLOCKED_TPT) \
- HOW(BLOCKED_FW) \
- HOW(BLOCKED_NON_BSS) \
- HOW(BLOCKED_ROC) \
- HOW(BLOCKED_TMP_NON_BSS) \
- HOW(EXIT_MISSED_BEACON) \
- HOW(EXIT_LOW_RSSI) \
- HOW(EXIT_COEX) \
- HOW(EXIT_BANDWIDTH) \
- HOW(EXIT_CSA) \
- HOW(EXIT_LINK_USAGE) \
- HOW(EXIT_FAIL_ENTRY)
-
-static const char *const iwl_mvm_esr_states_names[] = {
-#define NAME_ENTRY(x) [ilog2(IWL_MVM_ESR_##x)] = #x,
- HANDLE_ESR_REASONS(NAME_ENTRY)
-};
-
-const char *iwl_get_esr_state_string(enum iwl_mvm_esr_state state)
-{
- int offs = ilog2(state);
-
- if (offs >= ARRAY_SIZE(iwl_mvm_esr_states_names) ||
- !iwl_mvm_esr_states_names[offs])
- return "UNKNOWN";
-
- return iwl_mvm_esr_states_names[offs];
-}
-
-static void iwl_mvm_print_esr_state(struct iwl_mvm *mvm, u32 mask)
-{
-#define NAME_FMT(x) "%s"
-#define NAME_PR(x) (mask & IWL_MVM_ESR_##x) ? "[" #x "]" : "",
- IWL_DEBUG_INFO(mvm,
- "EMLSR state = " HANDLE_ESR_REASONS(NAME_FMT)
- " (0x%x)\n",
- HANDLE_ESR_REASONS(NAME_PR)
- mask);
-#undef NAME_FMT
-#undef NAME_PR
-}
-
-static u32 iwl_mvm_get_free_fw_link_id(struct iwl_mvm *mvm,
- struct iwl_mvm_vif *mvm_vif)
-{
- u32 i;
-
- lockdep_assert_held(&mvm->mutex);
-
- for (i = 0; i < ARRAY_SIZE(mvm->link_id_to_link_conf); i++)
- if (!rcu_access_pointer(mvm->link_id_to_link_conf[i]))
- return i;
-
- return IWL_MVM_FW_LINK_ID_INVALID;
-}
-
static int iwl_mvm_link_cmd_send(struct iwl_mvm *mvm,
struct iwl_link_config_cmd *cmd,
enum iwl_ctxt_action action)
@@ -80,25 +21,15 @@ static int iwl_mvm_link_cmd_send(struct iwl_mvm *mvm,
return ret;
}
-int iwl_mvm_set_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *link_conf)
+void iwl_mvm_set_link_fw_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_vif_link_info *link_info =
mvmvif->link[link_conf->link_id];
- if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID) {
- link_info->fw_link_id = iwl_mvm_get_free_fw_link_id(mvm,
- mvmvif);
- if (link_info->fw_link_id >=
- ARRAY_SIZE(mvm->link_id_to_link_conf))
- return -EINVAL;
-
- rcu_assign_pointer(mvm->link_id_to_link_conf[link_info->fw_link_id],
- link_conf);
- }
-
- return 0;
+ if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID)
+ link_info->fw_link_id = mvmvif->id;
}
int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -110,14 +41,11 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_link_config_cmd cmd = {};
unsigned int cmd_id = WIDE_ID(MAC_CONF_GROUP, LINK_CONFIG_CMD);
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 1);
- int ret;
if (WARN_ON_ONCE(!link_info))
return -EINVAL;
- ret = iwl_mvm_set_link_mapping(mvm, vif, link_conf);
- if (ret)
- return ret;
+ iwl_mvm_set_link_fw_id(mvm, vif, link_conf);
/* Update SF - Disable if needed. if this fails, SF might still be on
* while many macs are bound, which is forbidden - so fail the binding.
@@ -142,65 +70,6 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_ADD);
}
-struct iwl_mvm_esr_iter_data {
- struct ieee80211_vif *vif;
- unsigned int link_id;
- bool lift_block;
-};
-
-static void iwl_mvm_esr_vif_iterator(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
-{
- struct iwl_mvm_esr_iter_data *data = _data;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- int link_id;
-
- if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION)
- return;
-
- for_each_mvm_vif_valid_link(mvmvif, link_id) {
- struct iwl_mvm_vif_link_info *link_info =
- mvmvif->link[link_id];
- if (vif == data->vif && link_id == data->link_id)
- continue;
- if (link_info->active)
- data->lift_block = false;
- }
-}
-
-int iwl_mvm_esr_non_bss_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- unsigned int link_id, bool active)
-{
- /* An active link of a non-station vif blocks EMLSR. Upon activation
- * block EMLSR on the bss vif. Upon deactivation, check if this link
- * was the last non-station link active, and if so unblock the bss vif
- */
- struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm);
- struct iwl_mvm_esr_iter_data data = {
- .vif = vif,
- .link_id = link_id,
- .lift_block = true,
- };
-
- if (IS_ERR_OR_NULL(bss_vif))
- return 0;
-
- if (active)
- return iwl_mvm_block_esr_sync(mvm, bss_vif,
- IWL_MVM_ESR_BLOCKED_NON_BSS);
-
- ieee80211_iterate_active_interfaces(mvm->hw,
- IEEE80211_IFACE_ITER_NORMAL,
- iwl_mvm_esr_vif_iterator, &data);
- if (data.lift_block) {
- mutex_lock(&mvm->mutex);
- iwl_mvm_unblock_esr(mvm, bss_vif, IWL_MVM_ESR_BLOCKED_NON_BSS);
- mutex_unlock(&mvm->mutex);
- }
-
- return 0;
-}
-
int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
u32 changes, bool active)
@@ -374,24 +243,6 @@ send_cmd:
return ret;
}
-int iwl_mvm_unset_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *link_conf)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm_vif_link_info *link_info =
- mvmvif->link[link_conf->link_id];
-
- /* mac80211 thought we have the link, but it was never configured */
- if (WARN_ON(!link_info ||
- link_info->fw_link_id >=
- ARRAY_SIZE(mvm->link_id_to_link_conf)))
- return -EINVAL;
-
- RCU_INIT_POINTER(mvm->link_id_to_link_conf[link_info->fw_link_id],
- NULL);
- return 0;
-}
-
int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf)
{
@@ -401,10 +252,6 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_link_config_cmd cmd = {};
int ret;
- ret = iwl_mvm_unset_link_mapping(mvm, vif, link_conf);
- if (ret)
- return 0;
-
cmd.link_id = cpu_to_le32(link_info->fw_link_id);
link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
cmd.spec_link_id = link_conf->link_id;
@@ -438,452 +285,6 @@ int iwl_mvm_disable_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return ret;
}
-struct iwl_mvm_rssi_to_grade {
- s8 rssi[2];
- u16 grade;
-};
-
-#define RSSI_TO_GRADE_LINE(_lb, _hb_uhb, _grade) \
- { \
- .rssi = {_lb, _hb_uhb}, \
- .grade = _grade \
- }
-
-/*
- * This array must be sorted by increasing RSSI for proper functionality.
- * The grades are actually estimated throughput, represented as fixed-point
- * with a scale factor of 1/10.
- */
-static const struct iwl_mvm_rssi_to_grade rssi_to_grade_map[] = {
- RSSI_TO_GRADE_LINE(-85, -89, 177),
- RSSI_TO_GRADE_LINE(-83, -86, 344),
- RSSI_TO_GRADE_LINE(-82, -85, 516),
- RSSI_TO_GRADE_LINE(-80, -83, 688),
- RSSI_TO_GRADE_LINE(-77, -79, 1032),
- RSSI_TO_GRADE_LINE(-73, -76, 1376),
- RSSI_TO_GRADE_LINE(-70, -74, 1548),
- RSSI_TO_GRADE_LINE(-69, -72, 1750),
- RSSI_TO_GRADE_LINE(-65, -68, 2064),
- RSSI_TO_GRADE_LINE(-61, -66, 2294),
- RSSI_TO_GRADE_LINE(-58, -61, 2580),
- RSSI_TO_GRADE_LINE(-55, -58, 2868),
- RSSI_TO_GRADE_LINE(-46, -55, 3098),
- RSSI_TO_GRADE_LINE(-43, -54, 3442)
-};
-
-#define MAX_GRADE (rssi_to_grade_map[ARRAY_SIZE(rssi_to_grade_map) - 1].grade)
-
-#define DEFAULT_CHAN_LOAD_LB 30
-#define DEFAULT_CHAN_LOAD_HB 15
-#define DEFAULT_CHAN_LOAD_UHB 0
-
-/* Factors calculation is done with fixed-point with a scaling factor of 1/256 */
-#define SCALE_FACTOR 256
-
-/* Convert a percentage from [0,100] to [0,255] */
-#define NORMALIZE_PERCENT_TO_255(percentage) ((percentage) * SCALE_FACTOR / 100)
-
-static unsigned int
-iwl_mvm_get_puncturing_factor(const struct ieee80211_bss_conf *link_conf)
-{
- enum nl80211_chan_width chan_width =
- link_conf->chanreq.oper.width;
- int mhz = nl80211_chan_width_to_mhz(chan_width);
- unsigned int n_subchannels, n_punctured, puncturing_penalty;
-
- if (WARN_ONCE(mhz < 20 || mhz > 320,
- "Invalid channel width : (%d)\n", mhz))
- return SCALE_FACTOR;
-
- /* No puncturing, no penalty */
- if (mhz < 80)
- return SCALE_FACTOR;
-
- /* total number of subchannels */
- n_subchannels = mhz / 20;
- /* how many of these are punctured */
- n_punctured = hweight16(link_conf->chanreq.oper.punctured);
-
- puncturing_penalty = n_punctured * SCALE_FACTOR / n_subchannels;
- return SCALE_FACTOR - puncturing_penalty;
-}
-
-static unsigned int
-iwl_mvm_get_chan_load(struct ieee80211_bss_conf *link_conf)
-{
- struct ieee80211_vif *vif = link_conf->vif;
- struct iwl_mvm_vif_link_info *mvm_link =
- iwl_mvm_vif_from_mac80211(link_conf->vif)->link[link_conf->link_id];
- const struct element *bss_load_elem;
- const struct ieee80211_bss_load_elem *bss_load;
- enum nl80211_band band = link_conf->chanreq.oper.chan->band;
- const struct cfg80211_bss_ies *ies;
- unsigned int chan_load;
- u32 chan_load_by_us;
-
- rcu_read_lock();
- if (ieee80211_vif_link_active(vif, link_conf->link_id))
- ies = rcu_dereference(link_conf->bss->beacon_ies);
- else
- ies = rcu_dereference(link_conf->bss->ies);
-
- if (ies)
- bss_load_elem = cfg80211_find_elem(WLAN_EID_QBSS_LOAD,
- ies->data, ies->len);
- else
- bss_load_elem = NULL;
-
- /* If there isn't BSS Load element, take the defaults */
- if (!bss_load_elem ||
- bss_load_elem->datalen != sizeof(*bss_load)) {
- rcu_read_unlock();
- switch (band) {
- case NL80211_BAND_2GHZ:
- chan_load = DEFAULT_CHAN_LOAD_LB;
- break;
- case NL80211_BAND_5GHZ:
- chan_load = DEFAULT_CHAN_LOAD_HB;
- break;
- case NL80211_BAND_6GHZ:
- chan_load = DEFAULT_CHAN_LOAD_UHB;
- break;
- default:
- chan_load = 0;
- break;
- }
- /* The defaults are given in percentage */
- return NORMALIZE_PERCENT_TO_255(chan_load);
- }
-
- bss_load = (const void *)bss_load_elem->data;
- /* Channel util is in range 0-255 */
- chan_load = bss_load->channel_util;
- rcu_read_unlock();
-
- if (!mvm_link || !mvm_link->active)
- return chan_load;
-
- if (WARN_ONCE(!mvm_link->phy_ctxt,
- "Active link (%u) without phy ctxt assigned!\n",
- link_conf->link_id))
- return chan_load;
-
- /* channel load by us is given in percentage */
- chan_load_by_us =
- NORMALIZE_PERCENT_TO_255(mvm_link->phy_ctxt->channel_load_by_us);
-
- /* Use only values that firmware sends that can possibly be valid */
- if (chan_load_by_us <= chan_load)
- chan_load -= chan_load_by_us;
-
- return chan_load;
-}
-
-static unsigned int
-iwl_mvm_get_chan_load_factor(struct ieee80211_bss_conf *link_conf)
-{
- return SCALE_FACTOR - iwl_mvm_get_chan_load(link_conf);
-}
-
-/* This function calculates the grade of a link. Returns 0 in error case */
-VISIBLE_IF_IWLWIFI_KUNIT
-unsigned int iwl_mvm_get_link_grade(struct ieee80211_bss_conf *link_conf)
-{
- enum nl80211_band band;
- int i, rssi_idx;
- s32 link_rssi;
- unsigned int grade = MAX_GRADE;
-
- if (WARN_ON_ONCE(!link_conf))
- return 0;
-
- band = link_conf->chanreq.oper.chan->band;
- if (WARN_ONCE(band != NL80211_BAND_2GHZ &&
- band != NL80211_BAND_5GHZ &&
- band != NL80211_BAND_6GHZ,
- "Invalid band (%u)\n", band))
- return 0;
-
- link_rssi = MBM_TO_DBM(link_conf->bss->signal);
- /*
- * For 6 GHz the RSSI of the beacons is lower than
- * the RSSI of the data.
- */
- if (band == NL80211_BAND_6GHZ)
- link_rssi += 4;
-
- rssi_idx = band == NL80211_BAND_2GHZ ? 0 : 1;
-
- /* No valid RSSI - take the lowest grade */
- if (!link_rssi)
- link_rssi = rssi_to_grade_map[0].rssi[rssi_idx];
-
- /* Get grade based on RSSI */
- for (i = 0; i < ARRAY_SIZE(rssi_to_grade_map); i++) {
- const struct iwl_mvm_rssi_to_grade *line =
- &rssi_to_grade_map[i];
-
- if (link_rssi > line->rssi[rssi_idx])
- continue;
- grade = line->grade;
- break;
- }
-
- /* apply the channel load and puncturing factors */
- grade = grade * iwl_mvm_get_chan_load_factor(link_conf) / SCALE_FACTOR;
- grade = grade * iwl_mvm_get_puncturing_factor(link_conf) / SCALE_FACTOR;
- return grade;
-}
-EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mvm_get_link_grade);
-
-static
-u8 iwl_mvm_set_link_selection_data(struct ieee80211_vif *vif,
- struct iwl_mvm_link_sel_data *data,
- unsigned long usable_links,
- u8 *best_link_idx)
-{
- u8 n_data = 0;
- u16 max_grade = 0;
- unsigned long link_id;
-
- /* TODO: don't select links that weren't discovered in the last scan */
- for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
- struct ieee80211_bss_conf *link_conf =
- link_conf_dereference_protected(vif, link_id);
-
- if (WARN_ON_ONCE(!link_conf))
- continue;
-
- data[n_data].link_id = link_id;
- data[n_data].chandef = &link_conf->chanreq.oper;
- data[n_data].signal = link_conf->bss->signal / 100;
- data[n_data].grade = iwl_mvm_get_link_grade(link_conf);
-
- if (data[n_data].grade > max_grade) {
- max_grade = data[n_data].grade;
- *best_link_idx = n_data;
- }
- n_data++;
- }
-
- return n_data;
-}
-
-struct iwl_mvm_bw_to_rssi_threshs {
- s8 low;
- s8 high;
-};
-
-#define BW_TO_RSSI_THRESHOLDS(_bw) \
- [IWL_PHY_CHANNEL_MODE ## _bw] = { \
- .low = IWL_MVM_LOW_RSSI_THRESH_##_bw##MHZ, \
- .high = IWL_MVM_HIGH_RSSI_THRESH_##_bw##MHZ \
- }
-
-s8 iwl_mvm_get_esr_rssi_thresh(struct iwl_mvm *mvm,
- const struct cfg80211_chan_def *chandef,
- bool low)
-{
- const struct iwl_mvm_bw_to_rssi_threshs bw_to_rssi_threshs_map[] = {
- BW_TO_RSSI_THRESHOLDS(20),
- BW_TO_RSSI_THRESHOLDS(40),
- BW_TO_RSSI_THRESHOLDS(80),
- BW_TO_RSSI_THRESHOLDS(160)
- /* 320 MHz has the same thresholds as 20 MHz */
- };
- const struct iwl_mvm_bw_to_rssi_threshs *threshs;
- u8 chan_width = iwl_mvm_get_channel_width(chandef);
-
- if (WARN_ON(chandef->chan->band != NL80211_BAND_2GHZ &&
- chandef->chan->band != NL80211_BAND_5GHZ &&
- chandef->chan->band != NL80211_BAND_6GHZ))
- return S8_MAX;
-
- /* 6 GHz will always use 20 MHz thresholds, regardless of the BW */
- if (chan_width == IWL_PHY_CHANNEL_MODE320)
- chan_width = IWL_PHY_CHANNEL_MODE20;
-
- threshs = &bw_to_rssi_threshs_map[chan_width];
-
- return low ? threshs->low : threshs->high;
-}
-
-static u32
-iwl_mvm_esr_disallowed_with_link(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- const struct iwl_mvm_link_sel_data *link,
- bool primary)
-{
- struct wiphy *wiphy = mvm->hw->wiphy;
- struct ieee80211_bss_conf *conf;
- enum iwl_mvm_esr_state ret = 0;
- s8 thresh;
-
- conf = wiphy_dereference(wiphy, vif->link_conf[link->link_id]);
- if (WARN_ON_ONCE(!conf))
- return false;
-
- /* BT Coex effects eSR mode only if one of the links is on LB */
- if (link->chandef->chan->band == NL80211_BAND_2GHZ &&
- (!iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif, link->signal,
- primary)))
- ret |= IWL_MVM_ESR_EXIT_COEX;
-
- thresh = iwl_mvm_get_esr_rssi_thresh(mvm, link->chandef,
- false);
-
- if (link->signal < thresh)
- ret |= IWL_MVM_ESR_EXIT_LOW_RSSI;
-
- if (conf->csa_active)
- ret |= IWL_MVM_ESR_EXIT_CSA;
-
- if (ret) {
- IWL_DEBUG_INFO(mvm,
- "Link %d is not allowed for esr\n",
- link->link_id);
- iwl_mvm_print_esr_state(mvm, ret);
- }
- return ret;
-}
-
-VISIBLE_IF_IWLWIFI_KUNIT
-bool iwl_mvm_mld_valid_link_pair(struct ieee80211_vif *vif,
- const struct iwl_mvm_link_sel_data *a,
- const struct iwl_mvm_link_sel_data *b)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
- enum iwl_mvm_esr_state ret = 0;
-
- /* Per-link considerations */
- if (iwl_mvm_esr_disallowed_with_link(mvm, vif, a, true) ||
- iwl_mvm_esr_disallowed_with_link(mvm, vif, b, false))
- return false;
-
- if (a->chandef->chan->band == b->chandef->chan->band ||
- a->chandef->width != b->chandef->width)
- ret |= IWL_MVM_ESR_EXIT_BANDWIDTH;
-
- if (ret) {
- IWL_DEBUG_INFO(mvm,
- "Links %d and %d are not a valid pair for EMLSR\n",
- a->link_id, b->link_id);
- iwl_mvm_print_esr_state(mvm, ret);
- return false;
- }
-
- return true;
-
-}
-EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mvm_mld_valid_link_pair);
-
-/*
- * Returns the combined eSR grade of two given links.
- * Returns 0 if eSR is not allowed with these 2 links.
- */
-static
-unsigned int iwl_mvm_get_esr_grade(struct ieee80211_vif *vif,
- const struct iwl_mvm_link_sel_data *a,
- const struct iwl_mvm_link_sel_data *b,
- u8 *primary_id)
-{
- struct ieee80211_bss_conf *primary_conf;
- struct wiphy *wiphy = ieee80211_vif_to_wdev(vif)->wiphy;
- unsigned int primary_load;
-
- lockdep_assert_wiphy(wiphy);
-
- /* a is always primary, b is always secondary */
- if (b->grade > a->grade)
- swap(a, b);
-
- *primary_id = a->link_id;
-
- if (!iwl_mvm_mld_valid_link_pair(vif, a, b))
- return 0;
-
- primary_conf = wiphy_dereference(wiphy, vif->link_conf[*primary_id]);
-
- if (WARN_ON_ONCE(!primary_conf))
- return 0;
-
- primary_load = iwl_mvm_get_chan_load(primary_conf);
-
- return a->grade +
- ((b->grade * primary_load) / SCALE_FACTOR);
-}
-
-void iwl_mvm_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
-{
- struct iwl_mvm_link_sel_data data[IEEE80211_MLD_MAX_NUM_LINKS];
- struct iwl_mvm_link_sel_data *best_link;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- u32 max_active_links = iwl_mvm_max_active_links(mvm, vif);
- u16 usable_links = ieee80211_vif_usable_links(vif);
- u8 best, primary_link, best_in_pair, n_data;
- u16 max_esr_grade = 0, new_active_links;
-
- lockdep_assert_wiphy(mvm->hw->wiphy);
-
- if (!mvmvif->authorized || !ieee80211_vif_is_mld(vif))
- return;
-
- if (!IWL_MVM_AUTO_EML_ENABLE)
- return;
-
- /* The logic below is a simple version that doesn't suit more than 2
- * links
- */
- WARN_ON_ONCE(max_active_links > 2);
-
- n_data = iwl_mvm_set_link_selection_data(vif, data, usable_links,
- &best);
-
- if (WARN(!n_data, "Couldn't find a valid grade for any link!\n"))
- return;
-
- best_link = &data[best];
- primary_link = best_link->link_id;
- new_active_links = BIT(best_link->link_id);
-
- /* eSR is not supported/blocked, or only one usable link */
- if (max_active_links == 1 || !iwl_mvm_vif_has_esr_cap(mvm, vif) ||
- mvmvif->esr_disable_reason || n_data == 1)
- goto set_active;
-
- for (u8 a = 0; a < n_data; a++)
- for (u8 b = a + 1; b < n_data; b++) {
- u16 esr_grade = iwl_mvm_get_esr_grade(vif, &data[a],
- &data[b],
- &best_in_pair);
-
- if (esr_grade <= max_esr_grade)
- continue;
-
- max_esr_grade = esr_grade;
- primary_link = best_in_pair;
- new_active_links = BIT(data[a].link_id) |
- BIT(data[b].link_id);
- }
-
- /* No valid pair was found, go with the best link */
- if (hweight16(new_active_links) <= 1)
- goto set_active;
-
- /* For equal grade - prefer EMLSR */
- if (best_link->grade > max_esr_grade) {
- primary_link = best_link->link_id;
- new_active_links = BIT(best_link->link_id);
- }
-set_active:
- IWL_DEBUG_INFO(mvm, "Link selection result: 0x%x. Primary = %d\n",
- new_active_links, primary_link);
- ieee80211_set_active_links_async(vif, new_active_links);
- mvmvif->link_selection_res = new_active_links;
- mvmvif->link_selection_primary = primary_link;
-}
-
u8 iwl_mvm_get_primary_link(struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -906,266 +307,6 @@ u8 iwl_mvm_get_primary_link(struct ieee80211_vif *vif)
return __ffs(vif->active_links);
}
-/*
- * For non-MLO/single link, this will return the deflink/single active link,
- * respectively
- */
-u8 iwl_mvm_get_other_link(struct ieee80211_vif *vif, u8 link_id)
-{
- switch (hweight16(vif->active_links)) {
- case 0:
- return 0;
- default:
- WARN_ON(1);
- fallthrough;
- case 1:
- return __ffs(vif->active_links);
- case 2:
- return __ffs(vif->active_links & ~BIT(link_id));
- }
-}
-
-/* Reasons that can cause esr prevention */
-#define IWL_MVM_ESR_PREVENT_REASONS IWL_MVM_ESR_EXIT_MISSED_BEACON
-#define IWL_MVM_PREVENT_ESR_TIMEOUT (HZ * 400)
-#define IWL_MVM_ESR_PREVENT_SHORT (HZ * 300)
-#define IWL_MVM_ESR_PREVENT_LONG (HZ * 600)
-
-static bool iwl_mvm_check_esr_prevention(struct iwl_mvm *mvm,
- struct iwl_mvm_vif *mvmvif,
- enum iwl_mvm_esr_state reason)
-{
- bool timeout_expired = time_after(jiffies,
- mvmvif->last_esr_exit.ts +
- IWL_MVM_PREVENT_ESR_TIMEOUT);
- unsigned long delay;
-
- lockdep_assert_held(&mvm->mutex);
-
- /* Only handle reasons that can cause prevention */
- if (!(reason & IWL_MVM_ESR_PREVENT_REASONS))
- return false;
-
- /*
- * Reset the counter if more than 400 seconds have passed between one
- * exit and the other, or if we exited due to a different reason.
- * Will also reset the counter after the long prevention is done.
- */
- if (timeout_expired || mvmvif->last_esr_exit.reason != reason) {
- mvmvif->exit_same_reason_count = 1;
- return false;
- }
-
- mvmvif->exit_same_reason_count++;
- if (WARN_ON(mvmvif->exit_same_reason_count < 2 ||
- mvmvif->exit_same_reason_count > 3))
- return false;
-
- mvmvif->esr_disable_reason |= IWL_MVM_ESR_BLOCKED_PREVENTION;
-
- /*
- * For the second exit, use a short prevention, and for the third one,
- * use a long prevention.
- */
- delay = mvmvif->exit_same_reason_count == 2 ?
- IWL_MVM_ESR_PREVENT_SHORT :
- IWL_MVM_ESR_PREVENT_LONG;
-
- IWL_DEBUG_INFO(mvm,
- "Preventing EMLSR for %ld seconds due to %u exits with the reason = %s (0x%x)\n",
- delay / HZ, mvmvif->exit_same_reason_count,
- iwl_get_esr_state_string(reason), reason);
-
- wiphy_delayed_work_queue(mvm->hw->wiphy,
- &mvmvif->prevent_esr_done_wk, delay);
- return true;
-}
-
-#define IWL_MVM_TRIGGER_LINK_SEL_TIME (IWL_MVM_TRIGGER_LINK_SEL_TIME_SEC * HZ)
-
-/* API to exit eSR mode */
-void iwl_mvm_exit_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- enum iwl_mvm_esr_state reason,
- u8 link_to_keep)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- u16 new_active_links;
- bool prevented;
-
- lockdep_assert_held(&mvm->mutex);
-
- if (!IWL_MVM_AUTO_EML_ENABLE)
- return;
-
- /* Nothing to do */
- if (!mvmvif->esr_active)
- return;
-
- if (WARN_ON(!ieee80211_vif_is_mld(vif) || !mvmvif->authorized))
- return;
-
- if (WARN_ON(!(vif->active_links & BIT(link_to_keep))))
- link_to_keep = __ffs(vif->active_links);
-
- new_active_links = BIT(link_to_keep);
- IWL_DEBUG_INFO(mvm,
- "Exiting EMLSR. reason = %s (0x%x). Current active links=0x%x, new active links = 0x%x\n",
- iwl_get_esr_state_string(reason), reason,
- vif->active_links, new_active_links);
-
- ieee80211_set_active_links_async(vif, new_active_links);
-
- /* Prevent EMLSR if needed */
- prevented = iwl_mvm_check_esr_prevention(mvm, mvmvif, reason);
-
- /* Remember why and when we exited EMLSR */
- mvmvif->last_esr_exit.ts = jiffies;
- mvmvif->last_esr_exit.reason = reason;
-
- /*
- * If EMLSR is prevented now - don't try to get back to EMLSR.
- * If we exited due to a blocking event, we will try to get back to
- * EMLSR when the corresponding unblocking event will happen.
- */
- if (prevented || reason & IWL_MVM_BLOCK_ESR_REASONS)
- return;
-
- /* If EMLSR is not blocked - try enabling it again in 30 seconds */
- wiphy_delayed_work_queue(mvm->hw->wiphy,
- &mvmvif->mlo_int_scan_wk,
- round_jiffies_relative(IWL_MVM_TRIGGER_LINK_SEL_TIME));
-}
-
-void iwl_mvm_block_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- enum iwl_mvm_esr_state reason,
- u8 link_to_keep)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
- lockdep_assert_held(&mvm->mutex);
-
- if (!IWL_MVM_AUTO_EML_ENABLE)
- return;
-
- /* This should be called only with disable reasons */
- if (WARN_ON(!(reason & IWL_MVM_BLOCK_ESR_REASONS)))
- return;
-
- if (mvmvif->esr_disable_reason & reason)
- return;
-
- IWL_DEBUG_INFO(mvm,
- "Blocking EMLSR mode. reason = %s (0x%x)\n",
- iwl_get_esr_state_string(reason), reason);
-
- mvmvif->esr_disable_reason |= reason;
-
- iwl_mvm_print_esr_state(mvm, mvmvif->esr_disable_reason);
-
- iwl_mvm_exit_esr(mvm, vif, reason, link_to_keep);
-}
-
-int iwl_mvm_block_esr_sync(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- enum iwl_mvm_esr_state reason)
-{
- int primary_link = iwl_mvm_get_primary_link(vif);
- int ret;
-
- if (!IWL_MVM_AUTO_EML_ENABLE || !ieee80211_vif_is_mld(vif))
- return 0;
-
- /* This should be called only with blocking reasons */
- if (WARN_ON(!(reason & IWL_MVM_BLOCK_ESR_REASONS)))
- return 0;
-
- /* leave ESR immediately, not only async with iwl_mvm_block_esr() */
- ret = ieee80211_set_active_links(vif, BIT(primary_link));
- if (ret)
- return ret;
-
- mutex_lock(&mvm->mutex);
- /* only additionally block for consistency and to avoid concurrency */
- iwl_mvm_block_esr(mvm, vif, reason, primary_link);
- mutex_unlock(&mvm->mutex);
-
- return 0;
-}
-
-static void iwl_mvm_esr_unblocked(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- bool need_new_sel = time_after(jiffies, mvmvif->last_esr_exit.ts +
- IWL_MVM_TRIGGER_LINK_SEL_TIME);
-
- lockdep_assert_held(&mvm->mutex);
-
- if (!ieee80211_vif_is_mld(vif) || !mvmvif->authorized ||
- mvmvif->esr_active)
- return;
-
- IWL_DEBUG_INFO(mvm, "EMLSR is unblocked\n");
-
- /* If we exited due to an EXIT reason, and the exit was in less than
- * 30 seconds, then a MLO scan was scheduled already.
- */
- if (!need_new_sel &&
- !(mvmvif->last_esr_exit.reason & IWL_MVM_BLOCK_ESR_REASONS)) {
- IWL_DEBUG_INFO(mvm, "Wait for MLO scan\n");
- return;
- }
-
- /*
- * If EMLSR was blocked for more than 30 seconds, or the last link
- * selection decided to not enter EMLSR, trigger a new scan.
- */
- if (need_new_sel || hweight16(mvmvif->link_selection_res) < 2) {
- IWL_DEBUG_INFO(mvm, "Trigger MLO scan\n");
- wiphy_delayed_work_queue(mvm->hw->wiphy,
- &mvmvif->mlo_int_scan_wk, 0);
- /*
- * If EMLSR was blocked for less than 30 seconds, and the last link
- * selection decided to use EMLSR, activate EMLSR using the previous
- * link selection result.
- */
- } else {
- IWL_DEBUG_INFO(mvm,
- "Use the latest link selection result: 0x%x\n",
- mvmvif->link_selection_res);
- ieee80211_set_active_links_async(vif,
- mvmvif->link_selection_res);
- }
-}
-
-void iwl_mvm_unblock_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- enum iwl_mvm_esr_state reason)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
- lockdep_assert_held(&mvm->mutex);
-
- if (!IWL_MVM_AUTO_EML_ENABLE)
- return;
-
- /* This should be called only with disable reasons */
- if (WARN_ON(!(reason & IWL_MVM_BLOCK_ESR_REASONS)))
- return;
-
- /* No Change */
- if (!(mvmvif->esr_disable_reason & reason))
- return;
-
- mvmvif->esr_disable_reason &= ~reason;
-
- IWL_DEBUG_INFO(mvm,
- "Unblocking EMLSR mode. reason = %s (0x%x)\n",
- iwl_get_esr_state_string(reason), reason);
- iwl_mvm_print_esr_state(mvm, mvmvif->esr_disable_reason);
-
- if (!mvmvif->esr_disable_reason)
- iwl_mvm_esr_unblocked(mvm, vif);
-}
-
void iwl_mvm_init_link(struct iwl_mvm_vif_link_info *link)
{
link->bcast_sta.sta_id = IWL_INVALID_STA;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index bec18d197f31..867807abde66 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -301,7 +301,7 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
iwl_mvm_init_link(&mvmvif->deflink);
- /* No need to allocate data queues to P2P Device MAC and NAN.*/
+ /* No need to allocate data queues to P2P Device MAC */
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
return 0;
@@ -941,7 +941,7 @@ u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx)
u16 flags = iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx);
bool is_new_rate = iwl_fw_lookup_cmd_ver(fw, BEACON_TEMPLATE_CMD, 0) > 10;
- if (rate_idx <= IWL_FIRST_CCK_RATE)
+ if (rate_idx <= IWL_LAST_CCK_RATE)
flags |= is_new_rate ? IWL_MAC_BEACON_CCK
: IWL_MAC_BEACON_CCK_V1;
@@ -969,7 +969,7 @@ u8 iwl_mvm_mac_ctxt_get_beacon_rate(struct iwl_mvm *mvm,
static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct sk_buff *beacon,
- struct iwl_tx_cmd *tx)
+ struct iwl_tx_cmd_v6_params *tx_params)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_tx_info *info;
@@ -979,30 +979,30 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
info = IEEE80211_SKB_CB(beacon);
/* Set up TX command fields */
- tx->len = cpu_to_le16((u16)beacon->len);
- tx->sta_id = mvmvif->deflink.bcast_sta.sta_id;
- tx->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
+ tx_params->len = cpu_to_le16((u16)beacon->len);
+ tx_params->sta_id = mvmvif->deflink.bcast_sta.sta_id;
+ tx_params->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
tx_flags = TX_CMD_FLG_SEQ_CTL | TX_CMD_FLG_TSF;
tx_flags |=
iwl_mvm_bt_coex_tx_prio(mvm, (void *)beacon->data, info, 0) <<
TX_CMD_FLG_BT_PRIO_POS;
- tx->tx_flags = cpu_to_le32(tx_flags);
+ tx_params->tx_flags = cpu_to_le32(tx_flags);
if (!fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION)) {
iwl_mvm_toggle_tx_ant(mvm, &mvm->mgmt_last_antenna_idx);
- tx->rate_n_flags =
+ tx_params->rate_n_flags =
cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
RATE_MCS_ANT_POS);
}
rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
- tx->rate_n_flags |=
+ tx_params->rate_n_flags |=
cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate));
if (rate == IWL_FIRST_CCK_RATE)
- tx->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK_V1);
+ tx_params->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK_V1);
}
@@ -1579,13 +1579,11 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
u32 id = le32_to_cpu(mb->link_id);
union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt };
u32 mac_type;
- int link_id = -1;
u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
MISSED_BEACONS_NOTIFICATION,
0);
u8 new_notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP,
MISSED_BEACONS_NOTIF, 0);
- struct ieee80211_bss_conf *bss_conf;
/* If the firmware uses the new notification (from MAC_CONF_GROUP),
* refer to that notification's version.
@@ -1595,20 +1593,6 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
if (new_notif_ver)
notif_ver = new_notif_ver;
- /* before version four the ID in the notification refers to mac ID */
- if (notif_ver < 4) {
- vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false);
- bss_conf = &vif->bss_conf;
- } else {
- bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, false);
-
- if (!bss_conf)
- return;
-
- vif = bss_conf->vif;
- link_id = bss_conf->link_id;
- }
-
IWL_DEBUG_INFO(mvm,
"missed bcn %s_id=%u, consecutive=%u (%u)\n",
notif_ver < 4 ? "mac" : "link",
@@ -1616,6 +1600,11 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
le32_to_cpu(mb->consec_missed_beacons),
le32_to_cpu(mb->consec_missed_beacons_since_last_rx));
+ /*
+ * starting from version 4 the ID is link ID, but driver
+ * uses link ID == MAC ID, so always treat as MAC ID
+ */
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false);
if (!vif)
return;
@@ -1623,10 +1612,6 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
IWL_DEBUG_INFO(mvm, "missed beacon mac_type=%u,\n", mac_type);
- mvm->trans->dbg.dump_file_name_ext_valid = true;
- snprintf(mvm->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME,
- "MacId_%d_MacType_%d", id, mac_type);
-
rx_missed_bcon = le32_to_cpu(mb->consec_missed_beacons);
rx_missed_bcon_since_rx =
le32_to_cpu(mb->consec_missed_beacons_since_last_rx);
@@ -1644,41 +1629,11 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
"missed_beacons:%d, missed_beacons_since_rx:%d\n",
rx_missed_bcon, rx_missed_bcon_since_rx);
}
- } else if (link_id >= 0 && hweight16(vif->active_links) > 1) {
- u32 bss_param_ch_cnt_link_id =
- bss_conf->bss_param_ch_cnt_link_id;
- u32 scnd_lnk_bcn_lost = 0;
-
- if (notif_ver >= 5 &&
- !IWL_FW_CHECK(mvm,
- le32_to_cpu(mb->other_link_id) == IWL_MVM_FW_LINK_ID_INVALID,
- "No data for other link id but we are in EMLSR active_links: 0x%x\n",
- vif->active_links))
- scnd_lnk_bcn_lost =
- le32_to_cpu(mb->consec_missed_beacons_other_link);
-
- /* Exit EMLSR if we lost more than
- * IWL_MVM_MISSED_BEACONS_EXIT_ESR_THRESH beacons on boths links
- * OR more than IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH on any link.
- * OR more than IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED
- * and the link's bss_param_ch_count has changed.
- */
- if ((rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS &&
- scnd_lnk_bcn_lost >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS) ||
- rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH ||
- (bss_param_ch_cnt_link_id != link_id &&
- rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED))
- iwl_mvm_exit_esr(mvm, vif,
- IWL_MVM_ESR_EXIT_MISSED_BEACON,
- iwl_mvm_get_primary_link(vif));
} else if (rx_missed_bcon_since_rx > IWL_MVM_MISSED_BEACONS_THRESHOLD) {
if (!iwl_mvm_has_new_tx_api(mvm))
ieee80211_beacon_loss(vif);
else
ieee80211_cqm_beacon_loss_notify(vif, GFP_ATOMIC);
-
- /* try to switch links, no-op if we don't have MLO */
- iwl_mvm_int_mlo_scan(mvm, vif);
}
iwl_dbg_tlv_time_point(&mvm->fwrt,
@@ -1868,16 +1823,15 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
} else {
struct iwl_channel_switch_start_notif *notif = (void *)pkt->data;
u32 link_id = le32_to_cpu(notif->link_id);
- struct ieee80211_bss_conf *bss_conf =
- iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, link_id, true);
- if (!bss_conf)
+ /* we use link ID == MAC ID */
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, link_id, true);
+ if (!vif)
goto out_unlock;
id = link_id;
- mac_link_id = bss_conf->link_id;
- vif = bss_conf->vif;
- csa_active = bss_conf->csa_active;
+ mac_link_id = vif->bss_conf.link_id;
+ csa_active = vif->bss_conf.csa_active;
}
mvmvif = iwl_mvm_vif_from_mac80211(vif);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 1e916a0ce082..44029ceb8f77 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -5,6 +5,7 @@
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#include <linux/kernel.h>
+#include <linux/fips.h>
#include <linux/slab.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -146,7 +147,7 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
MCC_UPDATE_CMD, 0);
IWL_DEBUG_LAR(mvm, "MCC update response version: %d\n", resp_ver);
- regd = iwl_parse_nvm_mcc_info(mvm->trans->dev, mvm->cfg,
+ regd = iwl_parse_nvm_mcc_info(mvm->trans,
__le32_to_cpu(resp->n_channels),
resp->channels,
__le16_to_cpu(resp->mcc),
@@ -165,12 +166,6 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
mvm->lar_regdom_set = true;
mvm->mcc_src = src_id;
- if (!iwl_puncturing_is_allowed_in_bios(mvm->bios_enable_puncturing,
- le16_to_cpu(resp->mcc)))
- ieee80211_hw_set(mvm->hw, DISALLOW_PUNCTURING);
- else
- __clear_bit(IEEE80211_HW_DISALLOW_PUNCTURING, mvm->hw->flags);
-
iwl_mei_set_country_code(__le16_to_cpu(resp->mcc));
out:
@@ -298,7 +293,8 @@ static const struct wiphy_iftype_ext_capab add_iftypes_ext_capa[] = {
},
};
-int iwl_mvm_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+int iwl_mvm_op_get_antenna(struct ieee80211_hw *hw, int radio_idx,
+ u32 *tx_ant, u32 *rx_ant)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
*tx_ant = iwl_mvm_get_valid_tx_ant(mvm);
@@ -306,13 +302,15 @@ int iwl_mvm_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
return 0;
}
-int iwl_mvm_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+int iwl_mvm_op_set_antenna(struct ieee80211_hw *hw, int radio_idx, u32 tx_ant,
+ u32 rx_ant)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
/* This has been tested on those devices only */
- if (mvm->trans->trans_cfg->device_family != IWL_DEVICE_FAMILY_9000 &&
- mvm->trans->trans_cfg->device_family != IWL_DEVICE_FAMILY_22000)
+ if (mvm->trans->mac_cfg->device_family != IWL_DEVICE_FAMILY_9000 &&
+ mvm->trans->mac_cfg->device_family != IWL_DEVICE_FAMILY_22000 &&
+ mvm->trans->mac_cfg->device_family != IWL_DEVICE_FAMILY_AX210)
return -EOPNOTSUPP;
if (!mvm->nvm_data)
@@ -391,7 +389,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
* for older devices. We also don't see this issue on any newer
* devices.
*/
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_9000)
+ if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_9000)
ieee80211_hw_set(hw, TX_AMSDU);
ieee80211_hw_set(hw, TX_FRAG_LIST);
@@ -402,7 +400,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
/* We want to use the mac80211's reorder buffer for 9000 */
if (iwl_mvm_has_new_rx_api(mvm) &&
- mvm->trans->trans_cfg->device_family > IWL_DEVICE_FAMILY_9000)
+ mvm->trans->mac_cfg->device_family > IWL_DEVICE_FAMILY_9000)
ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
if (fw_has_capa(&mvm->fw->ucode_capa,
@@ -417,10 +415,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
return -EINVAL;
}
- if (mvm->trans->num_rx_queues > 1)
+ if (mvm->trans->info.num_rxqs > 1)
ieee80211_hw_set(hw, USES_RSS);
- if (mvm->trans->max_skb_frags)
+ if (mvm->trans->info.max_skb_frags)
hw->netdev_features = NETIF_F_HIGHDMA | NETIF_F_SG;
hw->queues = IEEE80211_NUM_ACS;
@@ -441,7 +439,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES;
hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
- hw->max_tx_fragments = mvm->trans->max_skb_frags;
+ hw->max_tx_fragments = mvm->trans->info.max_skb_frags;
BUILD_BUG_ON(ARRAY_SIZE(mvm->ciphers) < ARRAY_SIZE(mvm_ciphers) + 6);
memcpy(mvm->ciphers, mvm_ciphers, sizeof(mvm_ciphers));
@@ -464,7 +462,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
IWL_ERR(mvm,
"iwlmvm doesn't allow to disable BT Coex, check bt_coex_active module parameter\n");
- ieee80211_hw_set(hw, MFP_CAPABLE);
+ if (!fips_enabled)
+ ieee80211_hw_set(hw, MFP_CAPABLE);
+
mvm->ciphers[hw->wiphy->n_cipher_suites] = WLAN_CIPHER_SUITE_AES_CMAC;
hw->wiphy->n_cipher_suites++;
if (iwl_mvm_has_new_rx_api(mvm)) {
@@ -488,12 +488,17 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->pmsr_capa = &iwl_mvm_pmsr_capa;
}
- if (sec_key_ver &&
+ /*
+ * beacon protection must be handled by firmware,
+ * so cannot be done with fips_enabled
+ */
+ if (!fips_enabled && sec_key_ver &&
fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BIGTK_TX_SUPPORT))
wiphy_ext_feature_set(hw->wiphy,
NL80211_EXT_FEATURE_BEACON_PROTECTION);
- else if (fw_has_capa(&mvm->fw->ucode_capa,
+ else if (!fips_enabled &&
+ fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BIGTK_SUPPORT))
wiphy_ext_feature_set(hw->wiphy,
NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT);
@@ -544,7 +549,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
REGULATORY_DISABLE_BEACON_HINTS;
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
wiphy_ext_feature_set(hw->wiphy,
NL80211_EXT_FEATURE_DFS_CONCURRENT);
@@ -610,7 +615,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->bands[NL80211_BAND_6GHZ] =
&mvm->nvm_data->bands[NL80211_BAND_6GHZ];
- hw->wiphy->hw_version = mvm->trans->hw_id;
+ hw->wiphy->hw_version = mvm->trans->info.hw_id;
if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
@@ -731,11 +736,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
- ieee80211_hw_set(hw, DISALLOW_PUNCTURING_5GHZ);
-
#ifdef CONFIG_PM_SLEEP
if ((unified || mvm->fw->img[IWL_UCODE_WOWLAN].num_sec) &&
- device_can_wakeup(mvm->trans->dev)) {
+ device_can_wakeup(mvm->trans->dev) && !fips_enabled) {
mvm->wowlan.flags |= WIPHY_WOWLAN_MAGIC_PKT |
WIPHY_WOWLAN_DISCONNECT |
WIPHY_WOWLAN_EAP_IDENTITY_REQ |
@@ -771,7 +774,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
}
- hw->netdev_features |= mvm->cfg->features;
+ hw->netdev_features |= mvm->trans->mac_cfg->base->features;
if (!iwl_mvm_is_csum_supported(mvm))
hw->netdev_features &= ~IWL_CSUM_NETIF_FLAGS_MASK;
@@ -1379,7 +1382,7 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm, bool suspend)
iwl_mvm_rm_aux_sta(mvm);
if (suspend &&
- mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
+ mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
iwl_mvm_fast_suspend(mvm);
/* From this point on, we won't touch the device */
iwl_mvm_mei_device_state(mvm, false);
@@ -1422,12 +1425,6 @@ void iwl_mvm_mac_stop(struct ieee80211_hw *hw, bool suspend)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- /* Stop internal MLO scan, if running */
- mutex_lock(&mvm->mutex);
- iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_INT_MLO, false);
- mutex_unlock(&mvm->mutex);
-
- wiphy_work_cancel(mvm->hw->wiphy, &mvm->trig_link_selection_wk);
wiphy_work_flush(mvm->hw->wiphy, &mvm->async_handlers_wiphy_wk);
flush_work(&mvm->async_handlers_wk);
flush_work(&mvm->add_stream_wk);
@@ -1520,10 +1517,6 @@ int iwl_mvm_set_tx_power(struct iwl_mvm *mvm,
len = sizeof(cmd_v9_v10.v9);
else if (cmd_ver == 8)
len = sizeof(cmd.v8);
- else if (cmd_ver == 7)
- len = sizeof(cmd.v7);
- else if (cmd_ver == 6)
- len = sizeof(cmd.v6);
else if (fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_REDUCE_TX_POWER))
len = sizeof(cmd.v5);
@@ -1716,57 +1709,6 @@ static int iwl_mvm_alloc_bcast_mcast_sta(struct iwl_mvm *mvm,
IWL_STA_MULTICAST);
}
-static void iwl_mvm_prevent_esr_done_wk(struct wiphy *wiphy,
- struct wiphy_work *wk)
-{
- struct iwl_mvm_vif *mvmvif =
- container_of(wk, struct iwl_mvm_vif, prevent_esr_done_wk.work);
- struct iwl_mvm *mvm = mvmvif->mvm;
- struct ieee80211_vif *vif =
- container_of((void *)mvmvif, struct ieee80211_vif, drv_priv);
-
- guard(mvm)(mvm);
- iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_PREVENTION);
-}
-
-static void iwl_mvm_mlo_int_scan_wk(struct wiphy *wiphy, struct wiphy_work *wk)
-{
- struct iwl_mvm_vif *mvmvif = container_of(wk, struct iwl_mvm_vif,
- mlo_int_scan_wk.work);
- struct ieee80211_vif *vif =
- container_of((void *)mvmvif, struct ieee80211_vif, drv_priv);
-
- guard(mvm)(mvmvif->mvm);
- iwl_mvm_int_mlo_scan(mvmvif->mvm, vif);
-}
-
-static void iwl_mvm_unblock_esr_tpt(struct wiphy *wiphy, struct wiphy_work *wk)
-{
- struct iwl_mvm_vif *mvmvif =
- container_of(wk, struct iwl_mvm_vif, unblock_esr_tpt_wk);
- struct iwl_mvm *mvm = mvmvif->mvm;
- struct ieee80211_vif *vif =
- container_of((void *)mvmvif, struct ieee80211_vif, drv_priv);
-
- guard(mvm)(mvm);
- iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_TPT);
-}
-
-static void iwl_mvm_unblock_esr_tmp_non_bss(struct wiphy *wiphy,
- struct wiphy_work *wk)
-{
- struct iwl_mvm_vif *mvmvif =
- container_of(wk, struct iwl_mvm_vif,
- unblock_esr_tmp_non_bss_wk.work);
- struct iwl_mvm *mvm = mvmvif->mvm;
- struct ieee80211_vif *vif =
- container_of((void *)mvmvif, struct ieee80211_vif, drv_priv);
-
- mutex_lock(&mvm->mutex);
- iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_TMP_NON_BSS);
- mutex_unlock(&mvm->mutex);
-}
-
void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif)
{
lockdep_assert_held(&mvm->mutex);
@@ -1774,20 +1716,10 @@ void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif)
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
return;
+ mvmvif->deflink.average_beacon_energy = 0;
+
INIT_DELAYED_WORK(&mvmvif->csa_work,
iwl_mvm_channel_switch_disconnect_wk);
-
- wiphy_delayed_work_init(&mvmvif->prevent_esr_done_wk,
- iwl_mvm_prevent_esr_done_wk);
-
- wiphy_delayed_work_init(&mvmvif->mlo_int_scan_wk,
- iwl_mvm_mlo_int_scan_wk);
-
- wiphy_work_init(&mvmvif->unblock_esr_tpt_wk,
- iwl_mvm_unblock_esr_tpt);
-
- wiphy_delayed_work_init(&mvmvif->unblock_esr_tmp_non_bss_wk,
- iwl_mvm_unblock_esr_tmp_non_bss);
}
static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
@@ -1811,9 +1743,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
vif->driver_flags = IEEE80211_VIF_REMOVE_AP_AFTER_DISASSOC;
- ret = iwl_mvm_set_link_mapping(mvm, vif, &vif->bss_conf);
- if (ret)
- goto out;
+ iwl_mvm_set_link_fw_id(mvm, vif, &vif->bss_conf);
/*
* Not much to do here. The stack will not allow interface
@@ -1834,12 +1764,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif);
- /* Currently not much to do for NAN */
- if (vif->type == NL80211_IFTYPE_NAN) {
- ret = 0;
- goto out;
- }
-
/*
* The AP binding flow can be done only after the beacon
* template is configured (which happens only in the mac80211
@@ -1933,16 +1857,6 @@ void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
flush_work(&mvm->roc_done_wk);
}
- wiphy_delayed_work_cancel(mvm->hw->wiphy,
- &mvmvif->prevent_esr_done_wk);
-
- wiphy_delayed_work_cancel(mvm->hw->wiphy,
- &mvmvif->mlo_int_scan_wk);
-
- wiphy_work_cancel(mvm->hw->wiphy, &mvmvif->unblock_esr_tpt_wk);
- wiphy_delayed_work_cancel(mvm->hw->wiphy,
- &mvmvif->unblock_esr_tmp_non_bss_wk);
-
cancel_delayed_work_sync(&mvmvif->csa_work);
}
@@ -1988,15 +1902,8 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
* interface is be handled as part of the stop_ap flow.
*/
if (vif->type == NL80211_IFTYPE_AP ||
- vif->type == NL80211_IFTYPE_ADHOC) {
-#ifdef CONFIG_NL80211_TESTMODE
- if (vif == mvm->noa_vif) {
- mvm->noa_vif = NULL;
- mvm->noa_duration = 0;
- }
-#endif
+ vif->type == NL80211_IFTYPE_ADHOC)
goto out;
- }
iwl_mvm_power_update_mac(mvm);
@@ -2021,7 +1928,6 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
mvm->monitor_on = false;
out:
- iwl_mvm_unset_link_mapping(mvm, vif, &vif->bss_conf);
if (vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_ADHOC) {
iwl_mvm_dealloc_int_sta(mvm, &mvmvif->deflink.mcast_sta);
@@ -3059,7 +2965,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
* context. For the newer, the beacon is a resource that belongs to a
* MAC, so need to send beacon template after adding the mac.
*/
- if (mvm->trans->trans_cfg->device_family > IWL_DEVICE_FAMILY_22000) {
+ if (mvm->trans->mac_cfg->device_family > IWL_DEVICE_FAMILY_22000) {
/* Add the mac context */
ret = iwl_mvm_mac_ctxt_add(mvm, vif);
if (ret)
@@ -3347,7 +3253,7 @@ void iwl_mvm_mac_cancel_hw_scan(struct ieee80211_hw *hw,
* us to stop a hw_scan when it's already stopped. This can
* happen, for instance, if we stopped the scan ourselves,
* called ieee80211_scan_completed() and the userspace called
- * cancel scan scan before ieee80211_scan_work() could run.
+ * cancel scan before ieee80211_scan_work() could run.
* To handle that, simply return if the scan is not running.
*/
if (mvm->scan_status & IWL_MVM_SCAN_REGULAR)
@@ -4023,21 +3929,6 @@ iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm,
callbacks->mac_ctxt_changed(mvm, vif, false);
iwl_mvm_mei_host_associated(mvm, vif, mvm_sta);
-
- memset(&mvmvif->last_esr_exit, 0,
- sizeof(mvmvif->last_esr_exit));
-
- iwl_mvm_block_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_TPT, 0);
-
- /* Block until FW notif will arrive */
- iwl_mvm_block_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_FW, 0);
-
- /* when client is authorized (AP station marked as such),
- * try to enable the best link(s).
- */
- if (vif->type == NL80211_IFTYPE_STATION &&
- !test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
- iwl_mvm_select_links(mvm, vif);
}
mvm_sta->authorized = true;
@@ -4085,16 +3976,6 @@ iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm,
/* disable beacon filtering */
iwl_mvm_disable_beacon_filter(mvm, vif);
-
- wiphy_delayed_work_cancel(mvm->hw->wiphy,
- &mvmvif->prevent_esr_done_wk);
-
- wiphy_delayed_work_cancel(mvm->hw->wiphy,
- &mvmvif->mlo_int_scan_wk);
-
- wiphy_work_cancel(mvm->hw->wiphy, &mvmvif->unblock_esr_tpt_wk);
- wiphy_delayed_work_cancel(mvm->hw->wiphy,
- &mvmvif->unblock_esr_tmp_non_bss_wk);
}
return 0;
@@ -4105,7 +3986,8 @@ void iwl_mvm_smps_workaround(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- if (!iwl_mvm_has_rlc_offload(mvm))
+ if (!iwl_mvm_has_rlc_offload(mvm) ||
+ iwl_fw_lookup_cmd_ver(mvm->fw, MAC_PM_POWER_TABLE, 0) >= 2)
return;
mvmvif->ps_disabled = !vif->cfg.ps;
@@ -4257,7 +4139,8 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
return ret;
}
-int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx,
+ u32 value)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
@@ -4358,7 +4241,7 @@ int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
* us to stop a sched_scan when it's already stopped. This
* can happen, for instance, if we stopped the scan ourselves,
* called ieee80211_sched_scan_stopped() and the userspace called
- * stop sched scan scan before ieee80211_sched_scan_stopped_work()
+ * stop sched scan before ieee80211_sched_scan_stopped_work()
* could run. To handle this, simply return if the scan is
* not running.
*/
@@ -4395,7 +4278,7 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
switch (key->cipher) {
case WLAN_CIPHER_SUITE_TKIP:
- if (!mvm->trans->trans_cfg->gen2) {
+ if (!mvm->trans->mac_cfg->gen2) {
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
} else if (vif->type == NL80211_IFTYPE_STATION) {
@@ -4512,7 +4395,7 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
WARN_ON(rcu_access_pointer(mvmsta->ptk_pn[keyidx]));
ptk_pn = kzalloc(struct_size(ptk_pn, q,
- mvm->trans->num_rx_queues),
+ mvm->trans->info.num_rxqs),
GFP_KERNEL);
if (!ptk_pn) {
ret = -ENOMEM;
@@ -4521,7 +4404,7 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
ieee80211_get_key_rx_seq(key, tid, &seq);
- for (q = 0; q < mvm->trans->num_rx_queues; q++)
+ for (q = 0; q < mvm->trans->info.num_rxqs; q++)
memcpy(ptk_pn->q[q].pn[tid],
seq.ccmp.pn,
IEEE80211_CCMP_PN_LEN);
@@ -4622,6 +4505,10 @@ int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ /* When resuming from wowlan, FW already knows about the newest keys */
+ if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))
+ return 0;
+
guard(mvm)(mvm);
return __iwl_mvm_mac_set_key(hw, cmd, vif, sta, key);
}
@@ -4929,7 +4816,6 @@ int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
const struct iwl_mvm_roc_ops *ops)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm);
u32 lmac_id;
int ret;
@@ -4942,13 +4828,6 @@ int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
*/
flush_work(&mvm->roc_done_wk);
- if (!IS_ERR_OR_NULL(bss_vif)) {
- ret = iwl_mvm_block_esr_sync(mvm, bss_vif,
- IWL_MVM_ESR_BLOCKED_ROC);
- if (ret)
- return ret;
- }
-
guard(mvm)(mvm);
switch (vif->type) {
@@ -5525,70 +5404,6 @@ static int iwl_mvm_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
&mvm_sta->vif->bss_conf);
}
-#ifdef CONFIG_NL80211_TESTMODE
-static const struct nla_policy iwl_mvm_tm_policy[IWL_MVM_TM_ATTR_MAX + 1] = {
- [IWL_MVM_TM_ATTR_CMD] = { .type = NLA_U32 },
- [IWL_MVM_TM_ATTR_NOA_DURATION] = { .type = NLA_U32 },
- [IWL_MVM_TM_ATTR_BEACON_FILTER_STATE] = { .type = NLA_U32 },
-};
-
-static int __iwl_mvm_mac_testmode_cmd(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- void *data, int len)
-{
- struct nlattr *tb[IWL_MVM_TM_ATTR_MAX + 1];
- int err;
- u32 noa_duration;
-
- err = nla_parse_deprecated(tb, IWL_MVM_TM_ATTR_MAX, data, len,
- iwl_mvm_tm_policy, NULL);
- if (err)
- return err;
-
- if (!tb[IWL_MVM_TM_ATTR_CMD])
- return -EINVAL;
-
- switch (nla_get_u32(tb[IWL_MVM_TM_ATTR_CMD])) {
- case IWL_MVM_TM_CMD_SET_NOA:
- if (!vif || vif->type != NL80211_IFTYPE_AP || !vif->p2p ||
- !vif->bss_conf.enable_beacon ||
- !tb[IWL_MVM_TM_ATTR_NOA_DURATION])
- return -EINVAL;
-
- noa_duration = nla_get_u32(tb[IWL_MVM_TM_ATTR_NOA_DURATION]);
- if (noa_duration >= vif->bss_conf.beacon_int)
- return -EINVAL;
-
- mvm->noa_duration = noa_duration;
- mvm->noa_vif = vif;
-
- return iwl_mvm_update_quotas(mvm, true, NULL);
- case IWL_MVM_TM_CMD_SET_BEACON_FILTER:
- /* must be associated client vif - ignore authorized */
- if (!vif || vif->type != NL80211_IFTYPE_STATION ||
- !vif->cfg.assoc || !vif->bss_conf.dtim_period ||
- !tb[IWL_MVM_TM_ATTR_BEACON_FILTER_STATE])
- return -EINVAL;
-
- if (nla_get_u32(tb[IWL_MVM_TM_ATTR_BEACON_FILTER_STATE]))
- return iwl_mvm_enable_beacon_filter(mvm, vif);
- return iwl_mvm_disable_beacon_filter(mvm, vif);
- }
-
- return -EOPNOTSUPP;
-}
-
-int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- void *data, int len)
-{
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
-
- guard(mvm)(mvm);
- return __iwl_mvm_mac_testmode_cmd(mvm, vif, data, len);
-}
-#endif
-
void iwl_mvm_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_channel_switch *chsw)
{
@@ -5677,9 +5492,9 @@ static void iwl_mvm_csa_block_txqs(void *data, struct ieee80211_sta *sta)
}
#define IWL_MAX_CSA_BLOCK_TX 1500
-int iwl_mvm_pre_channel_switch(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct ieee80211_channel_switch *chsw)
+static int iwl_mvm_pre_channel_switch(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel_switch *chsw)
{
struct ieee80211_vif *csa_vif;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -5797,9 +5612,9 @@ int iwl_mvm_pre_channel_switch(struct iwl_mvm *mvm,
return ret;
}
-static int iwl_mvm_mac_pre_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_channel_switch *chsw)
+int iwl_mvm_mac_pre_channel_switch(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel_switch *chsw)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
@@ -6140,12 +5955,12 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)
break;
}
- if (format == RATE_MCS_CCK_MSK ||
- format == RATE_MCS_LEGACY_OFDM_MSK) {
+ if (format == RATE_MCS_MOD_TYPE_CCK ||
+ format == RATE_MCS_MOD_TYPE_LEGACY_OFDM) {
int rate = u32_get_bits(rate_n_flags, RATE_LEGACY_RATE_MSK);
/* add the offset needed to get to the legacy ofdm indices */
- if (format == RATE_MCS_LEGACY_OFDM_MSK)
+ if (format == RATE_MCS_MOD_TYPE_LEGACY_OFDM)
rate += IWL_FIRST_OFDM_RATE;
switch (rate) {
@@ -6190,7 +6005,7 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)
rinfo->nss = u32_get_bits(rate_n_flags,
RATE_MCS_NSS_MSK) + 1;
- rinfo->mcs = format == RATE_MCS_HT_MSK ?
+ rinfo->mcs = format == RATE_MCS_MOD_TYPE_HT ?
RATE_HT_MCS_INDEX(rate_n_flags) :
u32_get_bits(rate_n_flags, RATE_MCS_CODE_MSK);
@@ -6198,11 +6013,11 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)
rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
switch (format) {
- case RATE_MCS_EHT_MSK:
+ case RATE_MCS_MOD_TYPE_EHT:
/* TODO: GI/LTF/RU. How does the firmware encode them? */
rinfo->flags |= RATE_INFO_FLAGS_EHT_MCS;
break;
- case RATE_MCS_HE_MSK:
+ case RATE_MCS_MOD_TYPE_HE:
gi_ltf = u32_get_bits(rate_n_flags, RATE_MCS_HE_GI_LTF_MSK);
rinfo->flags |= RATE_INFO_FLAGS_HE_MCS;
@@ -6243,10 +6058,10 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)
if (rate_n_flags & RATE_HE_DUAL_CARRIER_MODE_MSK)
rinfo->he_dcm = 1;
break;
- case RATE_MCS_HT_MSK:
+ case RATE_MCS_MOD_TYPE_HT:
rinfo->flags |= RATE_INFO_FLAGS_MCS;
break;
- case RATE_MCS_VHT_MSK:
+ case RATE_MCS_MOD_TYPE_VHT:
rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
break;
}
@@ -6426,37 +6241,36 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
bool sync,
const void *data, u32 size)
{
- struct {
- struct iwl_rxq_sync_cmd cmd;
- struct iwl_mvm_internal_rxq_notif notif;
- } __packed cmd = {
- .cmd.rxq_mask = cpu_to_le32(BIT(mvm->trans->num_rx_queues) - 1),
- .cmd.count =
- cpu_to_le32(sizeof(struct iwl_mvm_internal_rxq_notif) +
- size),
- .notif.type = type,
- .notif.sync = sync,
- };
+ DEFINE_RAW_FLEX(struct iwl_rxq_sync_cmd, cmd, payload,
+ sizeof(struct iwl_mvm_internal_rxq_notif));
+ struct iwl_mvm_internal_rxq_notif *notif =
+ (struct iwl_mvm_internal_rxq_notif *)cmd->payload;
struct iwl_host_cmd hcmd = {
.id = WIDE_ID(DATA_PATH_GROUP, TRIGGER_RX_QUEUES_NOTIF_CMD),
- .data[0] = &cmd,
- .len[0] = sizeof(cmd),
+ .data[0] = cmd,
+ .len[0] = __struct_size(cmd),
.data[1] = data,
.len[1] = size,
.flags = CMD_SEND_IN_RFKILL | (sync ? 0 : CMD_ASYNC),
};
int ret;
+ cmd->rxq_mask = cpu_to_le32(BIT(mvm->trans->info.num_rxqs) - 1);
+ cmd->count = cpu_to_le32(sizeof(struct iwl_mvm_internal_rxq_notif) +
+ size);
+ notif->type = type;
+ notif->sync = sync;
+
/* size must be a multiple of DWORD */
- if (WARN_ON(cmd.cmd.count & cpu_to_le32(3)))
+ if (WARN_ON(cmd->count & cpu_to_le32(3)))
return;
if (!iwl_mvm_has_new_rx_api(mvm))
return;
if (sync) {
- cmd.notif.cookie = mvm->queue_sync_cookie;
- mvm->queue_sync_state = (1 << mvm->trans->num_rx_queues) - 1;
+ notif->cookie = mvm->queue_sync_cookie;
+ mvm->queue_sync_state = (1 << mvm->trans->info.num_rxqs) - 1;
}
ret = iwl_mvm_send_cmd(mvm, &hcmd);
@@ -6649,8 +6463,6 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.sync_rx_queues = iwl_mvm_sync_rx_queues,
- CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd)
-
#ifdef CONFIG_PM_SLEEP
/* look at d3.c */
.suspend = iwl_mvm_suspend,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
index bb7851042177..2d116a41913c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
@@ -1,17 +1,25 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2022 - 2024 Intel Corporation
+ * Copyright (C) 2022 - 2025 Intel Corporation
*/
#include "mvm.h"
static void iwl_mvm_mld_set_he_support(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- struct iwl_mac_config_cmd *cmd)
+ struct iwl_mac_config_cmd *cmd,
+ int cmd_ver)
{
- if (vif->type == NL80211_IFTYPE_AP)
- cmd->he_ap_support = cpu_to_le16(1);
- else
- cmd->he_support = cpu_to_le16(1);
+ if (vif->type == NL80211_IFTYPE_AP) {
+ if (cmd_ver == 2)
+ cmd->wifi_gen_v2.he_ap_support = cpu_to_le16(1);
+ else
+ cmd->wifi_gen.he_ap_support = 1;
+ } else {
+ if (cmd_ver == 2)
+ cmd->wifi_gen_v2.he_support = cpu_to_le16(1);
+ else
+ cmd->wifi_gen.he_support = 1;
+ }
}
static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
@@ -22,6 +30,12 @@ static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_bss_conf *link_conf;
unsigned int link_id;
+ int cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
+ WIDE_ID(MAC_CONF_GROUP,
+ MAC_CONFIG_CMD), 1);
+
+ if (WARN_ON(cmd_ver > 3))
+ return;
cmd->id_and_color = cpu_to_le32(mvmvif->id);
cmd->action = cpu_to_le32(action);
@@ -30,8 +44,8 @@ static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
memcpy(cmd->local_mld_addr, vif->addr, ETH_ALEN);
- cmd->he_support = 0;
- cmd->eht_support = 0;
+ cmd->wifi_gen_v2.he_support = 0;
+ cmd->wifi_gen_v2.eht_support = 0;
/* should be set by specific context type handler */
cmd->filter_flags = 0;
@@ -51,8 +65,11 @@ static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
* and enable both when we have MLO.
*/
if (ieee80211_vif_is_mld(vif)) {
- iwl_mvm_mld_set_he_support(mvm, vif, cmd);
- cmd->eht_support = cpu_to_le32(1);
+ iwl_mvm_mld_set_he_support(mvm, vif, cmd, cmd_ver);
+ if (cmd_ver == 2)
+ cmd->wifi_gen_v2.eht_support = cpu_to_le32(1);
+ else
+ cmd->wifi_gen.eht_support = 1;
return;
}
@@ -63,16 +80,19 @@ static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
continue;
if (link_conf->he_support)
- iwl_mvm_mld_set_he_support(mvm, vif, cmd);
+ iwl_mvm_mld_set_he_support(mvm, vif, cmd, cmd_ver);
- /* it's not reasonable to have EHT without HE and FW API doesn't
+ /* It's not reasonable to have EHT without HE and FW API doesn't
* support it. Ignore EHT in this case.
*/
if (!link_conf->he_support && link_conf->eht_support)
continue;
if (link_conf->eht_support) {
- cmd->eht_support = cpu_to_le32(1);
+ if (cmd_ver == 2)
+ cmd->wifi_gen_v2.eht_support = cpu_to_le32(1);
+ else
+ cmd->wifi_gen.eht_support = 1;
break;
}
}
@@ -262,9 +282,6 @@ int iwl_mvm_mld_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
- if (WARN_ON_ONCE(vif->type == NL80211_IFTYPE_NAN))
- return -EOPNOTSUPP;
-
if (WARN_ONCE(mvmvif->uploaded, "Adding active MAC %pM/%d\n",
vif->addr, ieee80211_vif_type_p2p(vif)))
return -EIO;
@@ -287,9 +304,6 @@ int iwl_mvm_mld_mac_ctxt_changed(struct iwl_mvm *mvm,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- if (WARN_ON_ONCE(vif->type == NL80211_IFTYPE_NAN))
- return -EOPNOTSUPP;
-
if (WARN_ONCE(!mvmvif->uploaded, "Changing inactive MAC %pM/%d\n",
vif->addr, ieee80211_vif_type_p2p(vif)))
return -EIO;
@@ -307,9 +321,6 @@ int iwl_mvm_mld_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
};
int ret;
- if (WARN_ON_ONCE(vif->type == NL80211_IFTYPE_NAN))
- return -EOPNOTSUPP;
-
if (WARN_ONCE(!mvmvif->uploaded, "Removing inactive MAC %pM/%d\n",
vif->addr, ieee80211_vif_type_p2p(vif)))
return -EIO;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 78d7153a0cfc..380b6f8a53fd 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -102,9 +102,6 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
mvm->csme_vif = vif;
}
- if (vif->p2p || iwl_fw_lookup_cmd_ver(mvm->fw, PHY_CONTEXT_CMD, 1) < 5)
- vif->driver_flags |= IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW;
-
return 0;
out_free_bf:
@@ -150,19 +147,6 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
iwl_mvm_vif_dbgfs_rm_link(mvm, vif);
- /* For AP/GO interface, the tear down of the resources allocated to the
- * interface is be handled as part of the stop_ap flow.
- */
- if (vif->type == NL80211_IFTYPE_AP ||
- vif->type == NL80211_IFTYPE_ADHOC) {
-#ifdef CONFIG_NL80211_TESTMODE
- if (vif == mvm->noa_vif) {
- mvm->noa_vif = NULL;
- mvm->noa_duration = 0;
- }
-#endif
- }
-
iwl_mvm_power_update_mac(mvm);
/* Before the interface removal, mac80211 would cancel the ROC, and the
@@ -353,20 +337,6 @@ static int iwl_mvm_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- /* update EMLSR mode */
- if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_STATION) {
- int ret;
-
- ret = iwl_mvm_esr_non_bss_link(mvm, vif, link_conf->link_id,
- true);
- /*
- * Don't activate this link if failed to exit EMLSR in
- * the BSS interface
- */
- if (ret)
- return ret;
- }
-
guard(mvm)(mvm);
return __iwl_mvm_mld_assign_vif_chanctx(mvm, vif, link_conf, ctx, false);
}
@@ -485,10 +455,6 @@ static void iwl_mvm_mld_unassign_vif_chanctx(struct ieee80211_hw *hw,
iwl_mvm_add_link(mvm, vif, link_conf);
}
mutex_unlock(&mvm->mutex);
-
- /* update EMLSR mode */
- if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_STATION)
- iwl_mvm_esr_non_bss_link(mvm, vif, link_conf->link_id, false);
}
static void
@@ -697,25 +663,6 @@ static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw,
&callbacks);
}
-static bool iwl_mvm_esr_bw_criteria(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *link_conf)
-{
- struct ieee80211_bss_conf *other_link;
- int link_id;
-
- /* Exit EMLSR if links don't have equal bandwidths */
- for_each_vif_active_link(vif, other_link, link_id) {
- if (link_id == link_conf->link_id)
- continue;
- if (link_conf->chanreq.oper.width ==
- other_link->chanreq.oper.width)
- return true;
- }
-
- return false;
-}
-
static void
iwl_mvm_mld_link_info_changed_station(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
@@ -750,14 +697,6 @@ iwl_mvm_mld_link_info_changed_station(struct iwl_mvm *mvm,
link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
}
- if ((changes & BSS_CHANGED_BANDWIDTH) &&
- ieee80211_vif_link_active(vif, link_conf->link_id) &&
- mvmvif->esr_active &&
- !iwl_mvm_esr_bw_criteria(mvm, vif, link_conf))
- iwl_mvm_exit_esr(mvm, vif,
- IWL_MVM_ESR_EXIT_BANDWIDTH,
- iwl_mvm_get_primary_link(vif));
-
/* if associated, maybe puncturing changed - we'll check later */
if (vif->cfg.assoc)
link_changes |= LINK_CONTEXT_MODIFY_EHT_PARAMS;
@@ -892,11 +831,6 @@ static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm,
if (ret)
IWL_ERR(mvm, "failed to update power mode\n");
}
-
- if (changes & (BSS_CHANGED_MLD_VALID_LINKS | BSS_CHANGED_MLD_TTLM) &&
- ieee80211_vif_is_mld(vif) && mvmvif->authorized)
- wiphy_delayed_work_queue(mvm->hw->wiphy,
- &mvmvif->mlo_int_scan_wk, 0);
}
static void
@@ -1252,91 +1186,6 @@ iwl_mvm_mld_can_neg_ttlm(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
return NEG_TTLM_RES_ACCEPT;
}
-static int
-iwl_mvm_mld_mac_pre_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_channel_switch *chsw)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- int ret;
-
- mutex_lock(&mvm->mutex);
- if (mvmvif->esr_active) {
- u8 primary = iwl_mvm_get_primary_link(vif);
- int selected;
-
- /* prefer primary unless quiet CSA on it */
- if (chsw->link_id == primary && chsw->block_tx)
- selected = iwl_mvm_get_other_link(vif, primary);
- else
- selected = primary;
-
- /*
- * remembers to tell the firmware that this link can't tx
- * Note that this logic seems to be unrelated to esr, but it
- * really is needed only when esr is active. When we have a
- * single link, the firmware will handle all this on its own.
- * In multi-link scenarios, we can learn about the CSA from
- * another link and this logic is too complex for the firmware
- * to track.
- * Since we want to de-activate the link that got a CSA, we
- * need to tell the firmware not to send any frame on that link
- * as the firmware may not be aware that link is under a CSA
- * with mode=1 (no Tx allowed).
- */
- if (chsw->block_tx && mvmvif->link[chsw->link_id])
- mvmvif->link[chsw->link_id]->csa_block_tx = true;
-
- iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_CSA, selected);
- mutex_unlock(&mvm->mutex);
-
- /*
- * If we've not kept the link active that's doing the CSA
- * then we don't need to do anything else, just return.
- */
- if (selected != chsw->link_id)
- return 0;
-
- mutex_lock(&mvm->mutex);
- }
-
- ret = iwl_mvm_pre_channel_switch(mvm, vif, chsw);
- mutex_unlock(&mvm->mutex);
-
- return ret;
-}
-
-#define IWL_MVM_MLD_UNBLOCK_ESR_NON_BSS_TIMEOUT (5 * HZ)
-
-static void iwl_mvm_mld_prep_add_interface(struct ieee80211_hw *hw,
- enum nl80211_iftype type)
-{
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm);
- struct iwl_mvm_vif *mvmvif;
- int ret;
-
- IWL_DEBUG_MAC80211(mvm, "prep_add_interface: type=%u\n",
- type);
-
- if (IS_ERR_OR_NULL(bss_vif) ||
- !(type == NL80211_IFTYPE_AP ||
- type == NL80211_IFTYPE_P2P_GO ||
- type == NL80211_IFTYPE_P2P_CLIENT))
- return;
-
- mvmvif = iwl_mvm_vif_from_mac80211(bss_vif);
- ret = iwl_mvm_block_esr_sync(mvm, bss_vif,
- IWL_MVM_ESR_BLOCKED_TMP_NON_BSS);
- if (ret)
- return;
-
- wiphy_delayed_work_queue(mvmvif->mvm->hw->wiphy,
- &mvmvif->unblock_esr_tmp_non_bss_wk,
- IWL_MVM_MLD_UNBLOCK_ESR_NON_BSS_TIMEOUT);
-}
-
const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.tx = iwl_mvm_mac_tx,
.wake_tx_queue = iwl_mvm_mac_wake_tx_queue,
@@ -1390,7 +1239,7 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.tx_last_beacon = iwl_mvm_tx_last_beacon,
.channel_switch = iwl_mvm_channel_switch,
- .pre_channel_switch = iwl_mvm_mld_mac_pre_channel_switch,
+ .pre_channel_switch = iwl_mvm_mac_pre_channel_switch,
.post_channel_switch = iwl_mvm_post_channel_switch,
.abort_channel_switch = iwl_mvm_abort_channel_switch,
.channel_switch_rx_beacon = iwl_mvm_channel_switch_rx_beacon,
@@ -1403,8 +1252,6 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.sync_rx_queues = iwl_mvm_sync_rx_queues,
- CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd)
-
#ifdef CONFIG_PM_SLEEP
/* look at d3.c */
.suspend = iwl_mvm_suspend,
@@ -1433,5 +1280,4 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.change_sta_links = iwl_mvm_mld_change_sta_links,
.can_activate_links = iwl_mvm_mld_can_activate_links,
.can_neg_ttlm = iwl_mvm_mld_can_neg_ttlm,
- .prep_add_interface = iwl_mvm_mld_prep_add_interface,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index 9dd670041137..d9a2801636cf 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2022-2024 Intel Corporation
+ * Copyright (C) 2022-2025 Intel Corporation
*/
#include "mvm.h"
#include "time-sync.h"
@@ -48,9 +48,13 @@ u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
static int iwl_mvm_mld_send_sta_cmd(struct iwl_mvm *mvm,
struct iwl_sta_cfg_cmd *cmd)
{
+ u32 cmd_id = WIDE_ID(MAC_CONF_GROUP, STA_CONFIG_CMD);
+ int cmd_len = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 0) > 1 ?
+ sizeof(*cmd) :
+ sizeof(struct iwl_sta_cfg_cmd_v1);
int ret = iwl_mvm_send_cmd_pdu(mvm,
WIDE_ID(MAC_CONF_GROUP, STA_CONFIG_CMD),
- 0, sizeof(*cmd), cmd);
+ 0, cmd_len, cmd);
if (ret)
IWL_ERR(mvm, "STA_CONFIG_CMD send failed, ret=0x%x\n", ret);
return ret;
@@ -144,7 +148,7 @@ int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm,
{
int ret, txq;
unsigned int wdg_timeout = _wdg_timeout ? *_wdg_timeout :
- mvm->trans->trans_cfg->base_params->wd_timeout;
+ mvm->trans->mac_cfg->base->wd_timeout;
if (WARN_ON_ONCE(sta->sta_id == IWL_INVALID_STA))
return -ENOSPC;
@@ -848,8 +852,6 @@ int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_mld_free_sta_link(mvm, mvm_sta, mvm_link_sta, link_id);
}
- kfree(mvm_sta->mpdu_counters);
- mvm_sta->mpdu_counters = NULL;
return ret;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index f6391c7a3e29..301d590fe0bd 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -126,7 +126,7 @@ struct iwl_mvm_time_event_data {
/* Power management */
/**
- * enum iwl_power_scheme
+ * enum iwl_power_scheme - iwl power schemes
* @IWL_POWER_SCHEME_CAM: Continuously Active Mode
* @IWL_POWER_SCHEME_BPS: Balanced Power Save (default)
* @IWL_POWER_SCHEME_LP: Low Power
@@ -304,6 +304,8 @@ struct iwl_probe_resp_data {
* @mcast_sta: multicast station
* @phy_ctxt: phy context allocated to this link, if any
* @bf_data: beacon filtering data
+ * @average_beacon_energy: average beacon energy for beacons received during
+ * client connections
*/
struct iwl_mvm_vif_link_info {
u8 bssid[ETH_ALEN];
@@ -342,70 +344,7 @@ struct iwl_mvm_vif_link_info {
u16 mgmt_queue;
struct iwl_mvm_link_bf_data bf_data;
-};
-
-/**
- * enum iwl_mvm_esr_state - defines reasons for which the EMLSR is exited or
- * blocked.
- * The low 16 bits are used for blocking reasons, and the 16 higher bits
- * are used for exit reasons.
- * For the blocking reasons - use iwl_mvm_(un)block_esr(), and for the exit
- * reasons - use iwl_mvm_exit_esr().
- *
- * Note: new reasons shall be added to HANDLE_ESR_REASONS as well (for logs)
- *
- * @IWL_MVM_ESR_BLOCKED_PREVENTION: Prevent EMLSR to avoid entering and exiting
- * in a loop.
- * @IWL_MVM_ESR_BLOCKED_WOWLAN: WOWLAN is preventing the enablement of EMLSR
- * @IWL_MVM_ESR_BLOCKED_TPT: block EMLSR when there is not enough traffic
- * @IWL_MVM_ESR_BLOCKED_FW: FW didn't recommended/forced exit from EMLSR
- * @IWL_MVM_ESR_BLOCKED_NON_BSS: An active non-BSS interface's link is
- * preventing EMLSR
- * @IWL_MVM_ESR_BLOCKED_ROC: remain-on-channel is preventing EMLSR
- * @IWL_MVM_ESR_BLOCKED_TMP_NON_BSS: An expected active non-BSS interface's link
- * is preventing EMLSR. This is a temporary blocking that is set when there
- * is an indication that a non-BSS interface is to be added.
- * @IWL_MVM_ESR_EXIT_MISSED_BEACON: exited EMLSR due to missed beacons
- * @IWL_MVM_ESR_EXIT_LOW_RSSI: link is deactivated/not allowed for EMLSR
- * due to low RSSI.
- * @IWL_MVM_ESR_EXIT_COEX: link is deactivated/not allowed for EMLSR
- * due to BT Coex.
- * @IWL_MVM_ESR_EXIT_BANDWIDTH: Bandwidths of primary and secondry links
- * preventing the enablement of EMLSR
- * @IWL_MVM_ESR_EXIT_CSA: CSA happened, so exit EMLSR
- * @IWL_MVM_ESR_EXIT_LINK_USAGE: Exit EMLSR due to low tpt on secondary link
- * @IWL_MVM_ESR_EXIT_FAIL_ENTRY: Exit EMLSR due to entry failure
- */
-enum iwl_mvm_esr_state {
- IWL_MVM_ESR_BLOCKED_PREVENTION = 0x1,
- IWL_MVM_ESR_BLOCKED_WOWLAN = 0x2,
- IWL_MVM_ESR_BLOCKED_TPT = 0x4,
- IWL_MVM_ESR_BLOCKED_FW = 0x8,
- IWL_MVM_ESR_BLOCKED_NON_BSS = 0x10,
- IWL_MVM_ESR_BLOCKED_ROC = 0x20,
- IWL_MVM_ESR_BLOCKED_TMP_NON_BSS = 0x40,
- IWL_MVM_ESR_EXIT_MISSED_BEACON = 0x10000,
- IWL_MVM_ESR_EXIT_LOW_RSSI = 0x20000,
- IWL_MVM_ESR_EXIT_COEX = 0x40000,
- IWL_MVM_ESR_EXIT_BANDWIDTH = 0x80000,
- IWL_MVM_ESR_EXIT_CSA = 0x100000,
- IWL_MVM_ESR_EXIT_LINK_USAGE = 0x200000,
- IWL_MVM_ESR_EXIT_FAIL_ENTRY = 0x400000,
-};
-
-#define IWL_MVM_BLOCK_ESR_REASONS 0xffff
-
-const char *iwl_get_esr_state_string(enum iwl_mvm_esr_state state);
-
-/**
- * struct iwl_mvm_esr_exit - details of the last exit from EMLSR mode.
- * @reason: The reason for the last exit from EMLSR.
- * &iwl_mvm_prevent_esr_reasons. Will be 0 before exiting EMLSR.
- * @ts: the time stamp of the last time we existed EMLSR.
- */
-struct iwl_mvm_esr_exit {
- unsigned long ts;
- enum iwl_mvm_esr_state reason;
+ u32 average_beacon_energy;
};
/**
@@ -442,7 +381,6 @@ struct iwl_mvm_esr_exit {
* @deflink: default link data for use in non-MLO
* @link: link data for each link in MLO
* @esr_active: indicates eSR mode is active
- * @esr_disable_reason: a bitmap of &enum iwl_mvm_esr_state
* @pm_enabled: indicates powersave is enabled
* @link_selection_res: bitmap of active links as it was decided in the last
* link selection. Valid only for a MLO vif after assoc. 0 if there wasn't
@@ -450,15 +388,6 @@ struct iwl_mvm_esr_exit {
* @link_selection_primary: primary link selected by link selection
* @primary_link: primary link in eSR. Valid only for an associated MLD vif,
* and in eSR mode. Valid only for a STA.
- * @last_esr_exit: Details of the last exit from EMLSR.
- * @exit_same_reason_count: The number of times we exited due to the specified
- * @last_esr_exit::reason, only counting exits due to
- * &IWL_MVM_ESR_PREVENT_REASONS.
- * @prevent_esr_done_wk: work that should be done when esr prevention ends.
- * @mlo_int_scan_wk: work for the internal MLO scan.
- * @unblock_esr_tpt_wk: work for unblocking EMLSR when tpt is high enough.
- * @unblock_esr_tmp_non_bss_wk: work for removing the
- * IWL_MVM_ESR_BLOCKED_TMP_NON_BSS blocking for EMLSR.
* @roc_activity: currently running ROC activity for this vif (or
* ROC_NUM_ACTIVITIES if no activity is running).
* @session_prot_connection_loss: the connection was lost due to session
@@ -514,7 +443,6 @@ struct iwl_mvm_vif {
u8 authorized:1;
bool ps_disabled;
- u32 esr_disable_reason;
u32 ap_beacon_time;
bool bf_enabled;
bool ba_enabled;
@@ -590,12 +518,6 @@ struct iwl_mvm_vif {
u16 link_selection_res;
u8 link_selection_primary;
u8 primary_link;
- struct iwl_mvm_esr_exit last_esr_exit;
- u8 exit_same_reason_count;
- struct wiphy_delayed_work prevent_esr_done_wk;
- struct wiphy_delayed_work mlo_int_scan_wk;
- struct wiphy_work unblock_esr_tpt_wk;
- struct wiphy_delayed_work unblock_esr_tmp_non_bss_wk;
struct iwl_mvm_vif_link_info deflink;
struct iwl_mvm_vif_link_info *link[IEEE80211_MLD_MAX_NUM_LINKS];
@@ -621,7 +543,6 @@ enum iwl_scan_status {
IWL_MVM_SCAN_REGULAR = BIT(0),
IWL_MVM_SCAN_SCHED = BIT(1),
IWL_MVM_SCAN_NETDETECT = BIT(2),
- IWL_MVM_SCAN_INT_MLO = BIT(3),
IWL_MVM_SCAN_STOPPING_REGULAR = BIT(8),
IWL_MVM_SCAN_STOPPING_SCHED = BIT(9),
@@ -634,8 +555,6 @@ enum iwl_scan_status {
IWL_MVM_SCAN_STOPPING_SCHED,
IWL_MVM_SCAN_NETDETECT_MASK = IWL_MVM_SCAN_NETDETECT |
IWL_MVM_SCAN_STOPPING_NETDETECT,
- IWL_MVM_SCAN_INT_MLO_MASK = IWL_MVM_SCAN_INT_MLO |
- IWL_MVM_SCAN_STOPPING_INT_MLO,
IWL_MVM_SCAN_STOPPING_MASK = 0xff << IWL_MVM_SCAN_STOPPING_SHIFT,
IWL_MVM_SCAN_MASK = 0xff,
@@ -664,6 +583,8 @@ enum iwl_mvm_sched_scan_pass_all_states {
* @min_backoff: The minimal tx backoff due to power restrictions
* @params: Parameters to configure the thermal throttling algorithm.
* @throttle: Is thermal throttling is active?
+ * @power_budget_mw: maximum cTDP power budget as defined for this system and
+ * device
*/
struct iwl_mvm_tt_mgmt {
struct delayed_work ct_kill_exit;
@@ -672,6 +593,8 @@ struct iwl_mvm_tt_mgmt {
u32 min_backoff;
struct iwl_tt_params params;
bool throttle;
+
+ u32 power_budget_mw;
};
#ifdef CONFIG_THERMAL
@@ -999,7 +922,7 @@ struct iwl_mvm {
struct iwl_trans *trans;
const struct iwl_fw *fw;
- const struct iwl_cfg *cfg;
+ const struct iwl_rf_cfg *cfg;
struct iwl_phy_db *phy_db;
struct ieee80211_hw *hw;
@@ -1012,8 +935,6 @@ struct iwl_mvm {
/* For async rx handlers that require the wiphy lock */
struct wiphy_work async_handlers_wiphy_wk;
- struct wiphy_work trig_link_selection_wk;
-
struct work_struct roc_done_wk;
unsigned long init_status;
@@ -1033,6 +954,8 @@ struct iwl_mvm {
u8 cca_40mhz_workaround;
+ u8 fw_rates_ver;
+
u32 ampdu_ref;
bool ampdu_toggle;
@@ -1173,8 +1096,6 @@ struct iwl_mvm {
struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER];
- struct ieee80211_bss_conf __rcu *link_id_to_link_conf[IWL_FW_MAX_LINK_ID + 1];
-
u8 *error_recovery_buf;
#ifdef CONFIG_IWLWIFI_LEDS
@@ -1198,20 +1119,13 @@ struct iwl_mvm {
u8 offload_tid;
#ifdef CONFIG_IWLWIFI_DEBUGFS
bool d3_wake_sysassert;
- bool d3_test_active;
- u32 d3_test_pme_ptr;
- struct ieee80211_vif *keep_vif;
u32 last_netdetect_scans; /* no. of scans in the last net-detect wake */
#endif
#endif
wait_queue_head_t rx_sync_waitq;
- /* BT-Coex - only one of those will be used */
- union {
- struct iwl_bt_coex_prof_old_notif last_bt_notif;
- struct iwl_bt_coex_profile_notif last_bt_wifi_loss;
- };
+ struct iwl_bt_coex_prof_old_notif last_bt_notif;
struct iwl_bt_coex_ci_cmd last_bt_ci_cmd;
u8 bt_tx_prio;
@@ -1246,11 +1160,6 @@ struct iwl_mvm {
struct iwl_time_quota_cmd last_quota_cmd;
-#ifdef CONFIG_NL80211_TESTMODE
- u32 noa_duration;
- struct ieee80211_vif *noa_vif;
-#endif
-
/* Tx queues */
u16 aux_queue;
u16 snif_queue;
@@ -1325,7 +1234,6 @@ struct iwl_mvm {
u8 range_resp;
} cmd_ver;
- struct ieee80211_vif *nan_vif;
struct iwl_mvm_baid_data __rcu *baid_map[IWL_MAX_BAID];
/*
@@ -1348,10 +1256,6 @@ struct iwl_mvm {
__le16 cur_aid;
u8 cur_bssid[ETH_ALEN];
-#ifdef CONFIG_ACPI
- struct iwl_phy_specific_cfg phy_filters;
-#endif
-
/* report rx timestamp in ptp clock time */
bool rx_ts_ptp;
@@ -1375,7 +1279,6 @@ struct iwl_mvm {
struct iwl_mvm_acs_survey *acs_survey;
bool statistics_clear;
- u32 bios_enable_puncturing;
};
/* Extract MVM priv from op_mode and _hw */
@@ -1491,20 +1394,6 @@ iwl_mvm_rcu_dereference_vif_id(struct iwl_mvm *mvm, u8 vif_id, bool rcu)
lockdep_is_held(&mvm->mutex));
}
-static inline struct ieee80211_bss_conf *
-iwl_mvm_rcu_fw_link_id_to_link_conf(struct iwl_mvm *mvm, u8 link_id, bool rcu)
-{
- if (IWL_FW_CHECK(mvm, link_id >= ARRAY_SIZE(mvm->link_id_to_link_conf),
- "erroneous FW link ID: %d\n", link_id))
- return NULL;
-
- if (rcu)
- return rcu_dereference(mvm->link_id_to_link_conf[link_id]);
-
- return rcu_dereference_protected(mvm->link_id_to_link_conf[link_id],
- lockdep_is_held(&mvm->mutex));
-}
-
static inline bool iwl_mvm_is_adaptive_dwell_supported(struct iwl_mvm *mvm)
{
return fw_has_api(&mvm->fw->ucode_capa,
@@ -1562,7 +1451,7 @@ static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm)
* Enable LAR only if it is supported by the FW (TLV) &&
* enabled in the NVM
*/
- if (mvm->cfg->nvm_type == IWL_NVM_EXT)
+ if (mvm->trans->cfg->nvm_type == IWL_NVM_EXT)
return nvm_lar && tlv_lar;
else
return tlv_lar;
@@ -1626,13 +1515,13 @@ static inline bool iwl_mvm_has_new_station_api(const struct iwl_fw *fw)
static inline bool iwl_mvm_has_new_tx_api(struct iwl_mvm *mvm)
{
/* TODO - replace with TLV once defined */
- return mvm->trans->trans_cfg->gen2;
+ return mvm->trans->mac_cfg->gen2;
}
static inline bool iwl_mvm_has_unified_ucode(struct iwl_mvm *mvm)
{
/* TODO - better define this */
- return mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000;
+ return mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000;
}
static inline bool iwl_mvm_is_cdb_supported(struct iwl_mvm *mvm)
@@ -1657,7 +1546,7 @@ static inline bool iwl_mvm_cdb_scan_api(struct iwl_mvm *mvm)
* but then there's a little bit of code in scan that won't make
* any sense...
*/
- return mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000;
+ return mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000;
}
static inline bool iwl_mvm_is_scan_ext_chan_supported(struct iwl_mvm *mvm)
@@ -1732,13 +1621,13 @@ static inline bool iwl_mvm_is_ctdp_supported(struct iwl_mvm *mvm)
static inline bool iwl_mvm_is_esr_supported(struct iwl_trans *trans)
{
- if (CSR_HW_RFID_IS_CDB(trans->hw_rf_id))
+ if (CSR_HW_RFID_IS_CDB(trans->info.hw_rf_id))
return false;
- switch (CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
+ switch (CSR_HW_RFID_TYPE(trans->info.hw_rf_id)) {
case IWL_CFG_RF_TYPE_FM:
/* Step A doesn't support eSR */
- return CSR_HW_RFID_STEP(trans->hw_rf_id);
+ return CSR_HW_RFID_STEP(trans->info.hw_rf_id);
case IWL_CFG_RF_TYPE_WH:
case IWL_CFG_RF_TYPE_PE:
return true;
@@ -1757,8 +1646,8 @@ static inline int iwl_mvm_max_active_links(struct iwl_mvm *mvm,
/* Check if HW supports eSR or STR */
if (iwl_mvm_is_esr_supported(trans) ||
- (CSR_HW_RFID_TYPE(trans->hw_rf_id) == IWL_CFG_RF_TYPE_FM &&
- CSR_HW_RFID_IS_CDB(trans->hw_rf_id)))
+ (CSR_HW_RFID_TYPE(trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_FM &&
+ CSR_HW_RFID_IS_CDB(trans->info.hw_rf_id)))
return IWL_FW_MAX_ACTIVE_LINKS_NUM;
return 1;
@@ -1771,7 +1660,7 @@ extern const u8 iwl_mvm_ac_to_bz_tx_fifo[];
static inline u8 iwl_mvm_mac_ac_to_tx_fifo(struct iwl_mvm *mvm,
enum ieee80211_ac_numbers ac)
{
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
return iwl_mvm_ac_to_bz_tx_fifo[ac];
if (iwl_mvm_has_new_tx_api(mvm))
return iwl_mvm_ac_to_gen2_tx_fifo[ac];
@@ -1810,9 +1699,6 @@ int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
enum nl80211_band band,
struct ieee80211_tx_rate *r);
-void iwl_mvm_hwrate_to_tx_rate_v1(u32 rate_n_flags,
- enum nl80211_band band,
- struct ieee80211_tx_rate *r);
u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx);
u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac);
bool iwl_mvm_is_nic_ack_enabled(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
@@ -1843,11 +1729,12 @@ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_sta *sta);
int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb);
void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
- struct iwl_tx_cmd *tx_cmd,
+ struct iwl_tx_cmd_v6_params *tx_cmd_params,
struct ieee80211_tx_info *info, u8 sta_id);
-void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd,
- struct ieee80211_tx_info *info,
- struct ieee80211_sta *sta, __le16 fc);
+void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
+ struct iwl_tx_cmd_v6_params *tx_cmd_params,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_sta *sta, __le16 fc);
void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
@@ -1876,12 +1763,12 @@ int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm,
void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm);
static inline void iwl_mvm_set_tx_cmd_ccmp(struct ieee80211_tx_info *info,
- struct iwl_tx_cmd *tx_cmd)
+ struct iwl_tx_cmd_v6_params *tx_cmd_params)
{
struct ieee80211_key_conf *keyconf = info->control.hw_key;
- tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
- memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
+ tx_cmd_params->sec_ctl = TX_CMD_SEC_CCM;
+ memcpy(tx_cmd_params->key, keyconf->key, keyconf->keylen);
}
static inline void iwl_mvm_wait_for_async_handlers(struct iwl_mvm *mvm)
@@ -2099,6 +1986,9 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
+void iwl_mvm_rx_beacon_filter_notif(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb);
+
/* Bindings */
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
@@ -2106,23 +1996,19 @@ u32 iwl_mvm_get_lmac_id(struct iwl_mvm *mvm, enum nl80211_band band);
/* Links */
void iwl_mvm_init_link(struct iwl_mvm_vif_link_info *link);
-int iwl_mvm_set_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *link_conf);
+void iwl_mvm_set_link_fw_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf);
int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf);
int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
u32 changes, bool active);
-int iwl_mvm_unset_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *link_conf);
int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf);
int iwl_mvm_disable_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf);
-void iwl_mvm_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
u8 iwl_mvm_get_primary_link(struct ieee80211_vif *vif);
-u8 iwl_mvm_get_other_link(struct ieee80211_vif *vif, u8 link_id);
struct iwl_mvm_link_sel_data {
u8 link_id;
@@ -2132,12 +2018,8 @@ struct iwl_mvm_link_sel_data {
};
#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
-unsigned int iwl_mvm_get_link_grade(struct ieee80211_bss_conf *link_conf);
-bool iwl_mvm_mld_valid_link_pair(struct ieee80211_vif *vif,
- const struct iwl_mvm_link_sel_data *a,
- const struct iwl_mvm_link_sel_data *b);
-
-s8 iwl_mvm_average_dbm_values(const struct iwl_umac_scan_channel_survey_notif *notif);
+extern const struct iwl_hcmd_arr iwl_mvm_groups[];
+extern const unsigned int iwl_mvm_groups_size;
#endif
/* AP and IBSS */
@@ -2219,7 +2101,6 @@ int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify);
int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm);
void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm);
void iwl_mvm_scan_timeout_wk(struct work_struct *work);
-int iwl_mvm_int_mlo_scan(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
void iwl_mvm_rx_channel_survey_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
@@ -2345,8 +2226,6 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
int iwl_mvm_send_bt_init_conf(struct iwl_mvm *mvm);
void iwl_mvm_rx_bt_coex_old_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
-void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum ieee80211_rssi_event_data);
void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm);
@@ -2459,7 +2338,7 @@ void iwl_mvm_vif_set_low_latency(struct iwl_mvm_vif *mvmvif, bool set,
*/
static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm)
{
- return ((BIT(mvm->trans->trans_cfg->base_params->num_of_queues) - 1) &
+ return ((BIT(mvm->trans->mac_cfg->base->num_of_queues) - 1) &
~BIT(IWL_MVM_DQA_CMD_QUEUE));
}
@@ -2868,13 +2747,16 @@ void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw,
int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_ampdu_params *params);
-int iwl_mvm_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
-int iwl_mvm_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
+int iwl_mvm_op_get_antenna(struct ieee80211_hw *hw, int radio_idx, u32 *tx_ant,
+ u32 *rx_ant);
+int iwl_mvm_op_set_antenna(struct ieee80211_hw *hw, int radio_idx, u32 tx_ant,
+ u32 rx_ant);
int iwl_mvm_mac_start(struct ieee80211_hw *hw);
void iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
enum ieee80211_reconfig_type reconfig_type);
void iwl_mvm_mac_stop(struct ieee80211_hw *hw, bool suspend);
-static inline int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed)
+static inline int iwl_mvm_mac_config(struct ieee80211_hw *hw, int radio_idx,
+ u32 changed)
{
return 0;
}
@@ -2907,7 +2789,8 @@ iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw,
int num_frames,
enum ieee80211_frame_release_type reason,
bool more_data);
-int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
+int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx,
+ u32 value);
void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_link_sta *link_sta, u32 changed);
void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
@@ -2943,9 +2826,10 @@ void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
int iwl_mvm_tx_last_beacon(struct ieee80211_hw *hw);
void iwl_mvm_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_channel_switch *chsw);
-int iwl_mvm_pre_channel_switch(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct ieee80211_channel_switch *chsw);
+int iwl_mvm_mac_pre_channel_switch(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel_switch *chsw);
+
void iwl_mvm_abort_channel_switch(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf);
@@ -3002,30 +2886,6 @@ int iwl_mvm_roc_add_cmd(struct iwl_mvm *mvm,
/* EMLSR */
bool iwl_mvm_vif_has_esr_cap(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
-void iwl_mvm_block_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- enum iwl_mvm_esr_state reason,
- u8 link_to_keep);
-int iwl_mvm_block_esr_sync(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- enum iwl_mvm_esr_state reason);
-void iwl_mvm_unblock_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- enum iwl_mvm_esr_state reason);
-void iwl_mvm_exit_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- enum iwl_mvm_esr_state reason,
- u8 link_to_keep);
-s8 iwl_mvm_get_esr_rssi_thresh(struct iwl_mvm *mvm,
- const struct cfg80211_chan_def *chandef,
- bool low);
-void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- int link_id);
-bool
-iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- s32 link_rssi,
- bool primary);
-int iwl_mvm_esr_non_bss_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- unsigned int link_id, bool active);
-
void
iwl_mvm_send_ap_tx_power_constraint_cmd(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
@@ -3034,4 +2894,9 @@ iwl_mvm_send_ap_tx_power_constraint_cmd(struct iwl_mvm *mvm,
void iwl_mvm_smps_workaround(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool update);
+
+/* rate_n_flags conversion */
+u32 iwl_mvm_v3_rate_from_fw(__le32 rate, u8 rate_ver);
+__le32 iwl_mvm_v3_rate_to_fw(u32 rate, u8 rate_ver);
+
#endif /* __IWL_MVM_H__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
index 80ec59c58ae4..953218f1e025 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2019, 2021-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2019, 2021-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -120,7 +120,7 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
} else {
IWL_DEBUG_EEPROM(mvm->trans->dev,
"NVM access command failed with status %d (device: %s)\n",
- ret, mvm->trans->name);
+ ret, mvm->trans->info.name);
ret = -ENODATA;
}
goto exit;
@@ -191,7 +191,7 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
while (ret == length) {
/* Check no memory assumptions fail and cause an overflow */
if ((size_read + offset + length) >
- mvm->trans->trans_cfg->base_params->eeprom_size) {
+ mvm->trans->mac_cfg->base->eeprom_size) {
IWL_ERR(mvm, "EEPROM size is too small for NVM\n");
return -ENOBUFS;
}
@@ -206,7 +206,7 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
offset += ret;
}
- iwl_nvm_fixups(mvm->trans->hw_id, section, data, offset);
+ iwl_nvm_fixups(mvm->trans->info.hw_id, section, data, offset);
IWL_DEBUG_EEPROM(mvm->trans->dev,
"NVM section %d read completed\n", section);
@@ -226,7 +226,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
/* Checking for required sections */
if (mvm->trans->cfg->nvm_type == IWL_NVM) {
if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
- !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {
+ !mvm->nvm_sections[mvm->trans->mac_cfg->base->nvm_hw_section_num].data) {
IWL_ERR(mvm, "Can't parse empty OTP/NVM sections\n");
return NULL;
}
@@ -244,7 +244,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
return NULL;
}
/* MAC_OVERRIDE or at least HW section must exist */
- if (!mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data &&
+ if (!mvm->nvm_sections[mvm->trans->mac_cfg->base->nvm_hw_section_num].data &&
!mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data) {
IWL_ERR(mvm,
"Can't parse mac_address, empty sections\n");
@@ -260,7 +260,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
}
}
- hw = (const __be16 *)sections[mvm->cfg->nvm_hw_section_num].data;
+ hw = (const __be16 *)sections[mvm->trans->mac_cfg->base->nvm_hw_section_num].data;
sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data;
calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data;
mac_override =
@@ -308,16 +308,15 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
int ret, section;
u32 size_read = 0;
u8 *nvm_buffer, *temp;
- const char *nvm_file_C = mvm->cfg->default_nvm_file_C_step;
- if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS))
+ if (WARN_ON_ONCE(mvm->trans->mac_cfg->base->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS))
return -EINVAL;
/* load NVM values from nic */
/* Read From FW NVM */
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n");
- nvm_buffer = kmalloc(mvm->trans->trans_cfg->base_params->eeprom_size,
+ nvm_buffer = kmalloc(mvm->trans->mac_cfg->base->eeprom_size,
GFP_KERNEL);
if (!nvm_buffer)
return -ENOMEM;
@@ -338,7 +337,7 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
break;
}
- iwl_nvm_fixups(mvm->trans->hw_id, section, temp, ret);
+ iwl_nvm_fixups(mvm->trans->info.hw_id, section, temp, ret);
mvm->nvm_sections[section].data = temp;
mvm->nvm_sections[section].length = ret;
@@ -367,7 +366,7 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
mvm->nvm_reg_blob.size = ret;
break;
default:
- if (section == mvm->cfg->nvm_hw_section_num) {
+ if (section == mvm->trans->mac_cfg->base->nvm_hw_section_num) {
mvm->nvm_hw_blob.data = temp;
mvm->nvm_hw_blob.size = ret;
break;
@@ -384,21 +383,8 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
/* read External NVM file from the mod param */
ret = iwl_read_external_nvm(mvm->trans, mvm->nvm_file_name,
mvm->nvm_sections);
- if (ret) {
- mvm->nvm_file_name = nvm_file_C;
-
- if ((ret == -EFAULT || ret == -ENOENT) &&
- mvm->nvm_file_name) {
- /* in case nvm file was failed try again */
- ret = iwl_read_external_nvm(mvm->trans,
- mvm->nvm_file_name,
- mvm->nvm_sections);
- if (ret)
- return ret;
- } else {
- return ret;
- }
- }
+ if (ret)
+ return ret;
}
/* parse the relevant nvm sections */
@@ -554,7 +540,7 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
struct ieee80211_regdomain *regd;
char mcc[3];
- if (mvm->cfg->nvm_type == IWL_NVM_EXT) {
+ if (mvm->trans->cfg->nvm_type == IWL_NVM_EXT) {
tlv_lar = fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
nvm_lar = mvm->nvm_data->lar_enabled;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 76603ef02704..5ebd046371f5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -61,8 +61,10 @@ static int __init iwl_mvm_init(void)
}
ret = iwl_opmode_register("iwlmvm", &iwl_mvm_ops);
- if (ret)
+ if (ret) {
pr_err("Unable to register MVM op_mode: %d\n", ret);
+ iwl_mvm_rate_control_unregister();
+ }
return ret;
}
@@ -92,11 +94,11 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
IWL_DEBUG_INFO(mvm, "Radio type=0x%x-0x%x-0x%x\n", radio_cfg_type,
radio_cfg_step, radio_cfg_dash);
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
return;
/* SKU control */
- reg_val = CSR_HW_REV_STEP_DASH(mvm->trans->hw_rev);
+ reg_val = CSR_HW_REV_STEP_DASH(mvm->trans->info.hw_rev);
/* radio configuration */
reg_val |= radio_cfg_type << CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE;
@@ -114,7 +116,7 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
* unrelated errors. Need to further investigate this, but for now
* we'll separate cases.
*/
- if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000)
+ if (mvm->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_8000)
reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI;
if (iwl_fw_dbg_is_d3_debug_enabled(&mvm->fwrt))
@@ -135,67 +137,12 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
* (PCIe power is lost before PERST# is asserted), causing ME FW
* to lose ownership and not being able to obtain it back.
*/
- if (!mvm->trans->cfg->apmg_not_supported)
+ if (!mvm->trans->mac_cfg->base->apmg_not_supported)
iwl_set_bits_mask_prph(mvm->trans, APMG_PS_CTRL_REG,
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
}
-static void iwl_mvm_rx_esr_mode_notif(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb)
-{
- struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_esr_mode_notif *notif = (void *)pkt->data;
- struct ieee80211_vif *vif = iwl_mvm_get_bss_vif(mvm);
-
- /* FW recommendations is only for entering EMLSR */
- if (IS_ERR_OR_NULL(vif) || iwl_mvm_vif_from_mac80211(vif)->esr_active)
- return;
-
- if (le32_to_cpu(notif->action) == ESR_RECOMMEND_ENTER)
- iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_FW);
- else
- iwl_mvm_block_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_FW,
- iwl_mvm_get_primary_link(vif));
-}
-
-static void iwl_mvm_rx_esr_trans_fail_notif(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb)
-{
- struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_esr_trans_fail_notif *notif = (void *)pkt->data;
- struct ieee80211_vif *vif = iwl_mvm_get_bss_vif(mvm);
- u8 fw_link_id = le32_to_cpu(notif->link_id);
- struct ieee80211_bss_conf *bss_conf;
-
- if (IS_ERR_OR_NULL(vif))
- return;
-
- IWL_DEBUG_INFO(mvm, "Failed to %s eSR on link %d, reason %d\n",
- le32_to_cpu(notif->activation) ? "enter" : "exit",
- le32_to_cpu(notif->link_id),
- le32_to_cpu(notif->err_code));
-
- /* we couldn't go back to single link, disconnect */
- if (!le32_to_cpu(notif->activation)) {
- iwl_mvm_connection_loss(mvm, vif, "emlsr exit failed");
- return;
- }
-
- bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, fw_link_id, false);
- if (IWL_FW_CHECK(mvm, !bss_conf,
- "FW reported failure to activate EMLSR on a non-existing link: %d\n",
- fw_link_id))
- return;
-
- /*
- * We failed to activate the second link and enter EMLSR, we need to go
- * back to single link.
- */
- iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_FAIL_ENTRY,
- bss_conf->link_id);
-}
-
static void iwl_mvm_rx_monitor_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb)
{
@@ -380,9 +327,6 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_old_notif,
RX_HANDLER_ASYNC_LOCKED_WIPHY,
struct iwl_bt_coex_prof_old_notif),
- RX_HANDLER_GRP(BT_COEX_GROUP, PROFILE_NOTIF, iwl_mvm_rx_bt_coex_notif,
- RX_HANDLER_ASYNC_LOCKED_WIPHY,
- struct iwl_bt_coex_profile_notif),
RX_HANDLER_NO_SIZE(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif,
RX_HANDLER_ASYNC_LOCKED),
RX_HANDLER_NO_SIZE(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics,
@@ -492,11 +436,6 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
RX_HANDLER_ASYNC_UNLOCKED,
struct iwl_channel_switch_error_notif),
- RX_HANDLER_GRP(DATA_PATH_GROUP, ESR_MODE_NOTIF,
- iwl_mvm_rx_esr_mode_notif,
- RX_HANDLER_ASYNC_LOCKED_WIPHY,
- struct iwl_esr_mode_notif),
-
RX_HANDLER_GRP(DATA_PATH_GROUP, MONITOR_NOTIF,
iwl_mvm_rx_monitor_notif, RX_HANDLER_ASYNC_LOCKED,
struct iwl_datapath_monitor_notif),
@@ -524,10 +463,11 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
RX_HANDLER_GRP(SCAN_GROUP, CHANNEL_SURVEY_NOTIF,
iwl_mvm_rx_channel_survey_notif, RX_HANDLER_ASYNC_LOCKED,
struct iwl_umac_scan_channel_survey_notif),
- RX_HANDLER_GRP(MAC_CONF_GROUP, EMLSR_TRANS_FAIL_NOTIF,
- iwl_mvm_rx_esr_trans_fail_notif,
- RX_HANDLER_ASYNC_LOCKED_WIPHY,
- struct iwl_esr_trans_fail_notif),
+ RX_HANDLER_GRP(DATA_PATH_GROUP, BEACON_FILTER_IN_NOTIF,
+ iwl_mvm_rx_beacon_filter_notif,
+ RX_HANDLER_ASYNC_LOCKED,
+ /* same size as v1 */
+ struct iwl_beacon_filter_notif),
};
#undef RX_HANDLER
#undef RX_HANDLER_GRP
@@ -658,7 +598,6 @@ static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = {
HCMD_NAME(STA_REMOVE_CMD),
HCMD_NAME(STA_DISABLE_TX_CMD),
HCMD_NAME(ROC_CMD),
- HCMD_NAME(EMLSR_TRANS_FAIL_NOTIF),
HCMD_NAME(ROC_NOTIF),
HCMD_NAME(CHANNEL_SWITCH_ERROR_NOTIF),
HCMD_NAME(MISSED_VAP_NOTIF),
@@ -696,9 +635,9 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
HCMD_NAME(CHEST_COLLECTOR_FILTER_CONFIG_CMD),
HCMD_NAME(SCD_QUEUE_CONFIG_CMD),
HCMD_NAME(SEC_KEY_CMD),
- HCMD_NAME(ESR_MODE_NOTIF),
HCMD_NAME(MONITOR_NOTIF),
HCMD_NAME(THERMAL_DUAL_CHAIN_REQUEST),
+ HCMD_NAME(BEACON_FILTER_IN_NOTIF),
HCMD_NAME(STA_PM_NOTIF),
HCMD_NAME(MU_GROUP_MGMT_NOTIF),
HCMD_NAME(RX_QUEUES_NOTIFICATION),
@@ -777,7 +716,8 @@ static const struct iwl_hcmd_names iwl_mvm_bt_coex_names[] = {
HCMD_NAME(PROFILE_NOTIF),
};
-static const struct iwl_hcmd_arr iwl_mvm_groups[] = {
+VISIBLE_IF_IWLWIFI_KUNIT
+const struct iwl_hcmd_arr iwl_mvm_groups[] = {
[LEGACY_GROUP] = HCMD_ARR(iwl_mvm_legacy_names),
[LONG_GROUP] = HCMD_ARR(iwl_mvm_legacy_names),
[SYSTEM_GROUP] = HCMD_ARR(iwl_mvm_system_names),
@@ -793,6 +733,11 @@ static const struct iwl_hcmd_arr iwl_mvm_groups[] = {
[DEBUG_GROUP] = HCMD_ARR(iwl_mvm_debug_names),
[STATISTICS_GROUP] = HCMD_ARR(iwl_mvm_statistics_names),
};
+EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mvm_groups);
+#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
+const unsigned int iwl_mvm_groups_size = ARRAY_SIZE(iwl_mvm_groups);
+EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mvm_groups_size);
+#endif
/* this forward declaration can avoid to export the function */
static void iwl_mvm_async_handlers_wk(struct work_struct *wk);
@@ -1248,37 +1193,13 @@ static const struct iwl_mei_ops mei_ops = {
.nic_stolen = iwl_mvm_mei_nic_stolen,
};
-static void iwl_mvm_find_link_selection_vif(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
- if (ieee80211_vif_is_mld(vif) && mvmvif->authorized)
- iwl_mvm_select_links(mvmvif->mvm, vif);
-}
-
-static void iwl_mvm_trig_link_selection(struct wiphy *wiphy,
- struct wiphy_work *wk)
-{
- struct iwl_mvm *mvm =
- container_of(wk, struct iwl_mvm, trig_link_selection_wk);
-
- mutex_lock(&mvm->mutex);
- ieee80211_iterate_active_interfaces(mvm->hw,
- IEEE80211_IFACE_ITER_NORMAL,
- iwl_mvm_find_link_selection_vif,
- NULL);
- mutex_unlock(&mvm->mutex);
-}
-
static struct iwl_op_mode *
-iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
+iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
const struct iwl_fw *fw, struct dentry *dbgfs_dir)
{
struct ieee80211_hw *hw;
struct iwl_op_mode *op_mode;
struct iwl_mvm *mvm;
- struct iwl_trans_config trans_cfg = {};
static const u8 no_reclaim_cmds[] = {
TX_CMD,
};
@@ -1286,6 +1207,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
size_t scan_size;
u32 min_backoff;
struct iwl_mvm_csme_conn_info *csme_conn_info __maybe_unused;
+ int ratecheck;
int err;
/*
@@ -1306,18 +1228,13 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
if (!hw)
return ERR_PTR(-ENOMEM);
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
max_agg = 512;
else
max_agg = IEEE80211_MAX_AMPDU_BUF_HE;
hw->max_rx_aggregation_subframes = max_agg;
- if (cfg->max_tx_agg_size)
- hw->max_tx_aggregation_subframes = cfg->max_tx_agg_size;
- else
- hw->max_tx_aggregation_subframes = max_agg;
-
op_mode = hw->priv;
mvm = IWL_OP_MODE_GET_MVM(op_mode);
@@ -1337,26 +1254,63 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mvm->init_status = 0;
+ /* start with v1 rates */
+ mvm->fw_rates_ver = 1;
+
+ /* check for rates version 2 */
+ ratecheck =
+ (iwl_fw_lookup_cmd_ver(mvm->fw, TX_CMD, 0) >= 8) +
+ (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP,
+ TLC_MNG_UPDATE_NOTIF, 0) >= 3) +
+ (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
+ REPLY_RX_MPDU_CMD, 0) >= 4) +
+ (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP, TX_CMD, 0) >= 6);
+ if (ratecheck != 0 && ratecheck != 4) {
+ IWL_ERR(mvm, "Firmware has inconsistent rates\n");
+ err = -EINVAL;
+ goto out_free;
+ }
+ if (ratecheck == 4)
+ mvm->fw_rates_ver = 2;
+
+ /* check for rates version 3 */
+ ratecheck =
+ (iwl_fw_lookup_cmd_ver(mvm->fw, TX_CMD, 0) >= 11) +
+ (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP,
+ TLC_MNG_UPDATE_NOTIF, 0) >= 4) +
+ (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
+ REPLY_RX_MPDU_CMD, 0) >= 6) +
+ (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP,
+ RX_NO_DATA_NOTIF, 0) >= 4) +
+ (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP, TX_CMD, 0) >= 9);
+ if (ratecheck != 0 && ratecheck != 5) {
+ IWL_ERR(mvm, "Firmware has inconsistent rates\n");
+ err = -EINVAL;
+ goto out_free;
+ }
+ if (ratecheck == 5)
+ mvm->fw_rates_ver = 3;
+
+ trans->conf.rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
+
if (iwl_mvm_has_new_rx_api(mvm)) {
op_mode->ops = &iwl_mvm_ops_mq;
- trans->rx_mpdu_cmd_hdr_size =
- (trans->trans_cfg->device_family >=
+ trans->conf.rx_mpdu_cmd_hdr_size =
+ (trans->mac_cfg->device_family >=
IWL_DEVICE_FAMILY_AX210) ?
sizeof(struct iwl_rx_mpdu_desc) :
IWL_RX_DESC_SIZE_V1;
} else {
op_mode->ops = &iwl_mvm_ops;
- trans->rx_mpdu_cmd_hdr_size =
+ trans->conf.rx_mpdu_cmd_hdr_size =
sizeof(struct iwl_rx_mpdu_res_start);
- if (WARN_ON(trans->num_rx_queues > 1)) {
+ if (WARN_ON(trans->info.num_rxqs > 1)) {
err = -EINVAL;
goto out_free;
}
}
- mvm->bios_enable_puncturing = iwl_uefi_get_puncturing(&mvm->fwrt);
-
if (iwl_mvm_has_new_tx_api(mvm)) {
/*
* If we have the new TX/queue allocation API initialize them
@@ -1407,9 +1361,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
wiphy_work_init(&mvm->async_handlers_wiphy_wk,
iwl_mvm_async_handlers_wiphy_wk);
- wiphy_work_init(&mvm->trig_link_selection_wk,
- iwl_mvm_trig_link_selection);
-
init_waitqueue_head(&mvm->rx_sync_waitq);
mvm->queue_sync_state = 0;
@@ -1437,53 +1388,50 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
* Populate the state variables that the transport layer needs
* to know about.
*/
- trans_cfg.op_mode = op_mode;
- trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
- trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
+ BUILD_BUG_ON(sizeof(no_reclaim_cmds) >
+ sizeof(trans->conf.no_reclaim_cmds));
+ memcpy(trans->conf.no_reclaim_cmds, no_reclaim_cmds,
+ sizeof(no_reclaim_cmds));
+ trans->conf.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
- trans_cfg.rx_buf_size = iwl_amsdu_size_to_rxb_size();
+ trans->conf.rx_buf_size = iwl_amsdu_size_to_rxb_size();
- trans->wide_cmd_header = true;
- trans_cfg.bc_table_dword =
- mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210;
+ trans->conf.wide_cmd_header = true;
- trans_cfg.command_groups = iwl_mvm_groups;
- trans_cfg.command_groups_size = ARRAY_SIZE(iwl_mvm_groups);
+ trans->conf.command_groups = iwl_mvm_groups;
+ trans->conf.command_groups_size = ARRAY_SIZE(iwl_mvm_groups);
- trans_cfg.cmd_queue = IWL_MVM_DQA_CMD_QUEUE;
- trans_cfg.cmd_fifo = IWL_MVM_TX_FIFO_CMD;
- trans_cfg.scd_set_active = true;
+ trans->conf.cmd_queue = IWL_MVM_DQA_CMD_QUEUE;
+ trans->conf.cmd_fifo = IWL_MVM_TX_FIFO_CMD;
+ trans->conf.scd_set_active = true;
- trans_cfg.cb_data_offs = offsetof(struct ieee80211_tx_info,
- driver_data[2]);
+ trans->conf.cb_data_offs = offsetof(struct ieee80211_tx_info,
+ driver_data[2]);
snprintf(mvm->hw->wiphy->fw_version,
sizeof(mvm->hw->wiphy->fw_version),
"%.31s", fw->fw_version);
- trans_cfg.fw_reset_handshake = fw_has_capa(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE);
+ trans->conf.fw_reset_handshake =
+ fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE);
- trans_cfg.queue_alloc_cmd_ver =
+ trans->conf.queue_alloc_cmd_ver =
iwl_fw_lookup_cmd_ver(mvm->fw,
WIDE_ID(DATA_PATH_GROUP,
SCD_QUEUE_CONFIG_CMD),
0);
mvm->sta_remove_requires_queue_remove =
- trans_cfg.queue_alloc_cmd_ver > 0;
+ trans->conf.queue_alloc_cmd_ver > 0;
mvm->mld_api_is_used = iwl_mvm_has_mld_api(mvm->fw);
/* Configure transport layer */
- iwl_trans_configure(mvm->trans, &trans_cfg);
+ iwl_trans_op_mode_enter(mvm->trans, op_mode);
- trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
trans->dbg.dest_tlv = mvm->fw->dbg.dest_tlv;
trans->dbg.n_dest_reg = mvm->fw->dbg.n_dest_reg;
- trans->iml = mvm->fw->iml;
- trans->iml_len = mvm->fw->iml_len;
-
/* set up notification wait support */
iwl_notification_wait_init(&mvm->notif_wait);
@@ -2016,7 +1964,7 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode,
if (type == IWL_ERR_TYPE_CMD_QUEUE_FULL)
IWL_ERR(mvm, "Command queue full!\n");
- else if (!test_bit(STATUS_TRANS_DEAD, &mvm->trans->status) &&
+ else if (!iwl_trans_is_dead(mvm->trans) &&
!test_and_clear_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE,
&mvm->status))
iwl_mvm_dump_nic_error_log(mvm);
@@ -2100,7 +2048,7 @@ static bool iwl_mvm_sw_reset(struct iwl_op_mode *op_mode,
mvm->fwrt.trans->dbg.restart_required = false;
ieee80211_restart_hw(mvm->hw);
return true;
- } else if (mvm->trans->trans_cfg->device_family <= IWL_DEVICE_FAMILY_8000) {
+ } else if (mvm->trans->mac_cfg->device_family <= IWL_DEVICE_FAMILY_8000) {
ieee80211_restart_hw(mvm->hw);
return true;
}
@@ -2118,6 +2066,17 @@ static void iwl_op_mode_mvm_time_point(struct iwl_op_mode *op_mode,
iwl_dbg_tlv_time_point(&mvm->fwrt, tp_id, tp_data);
}
+static void iwl_mvm_dump(struct iwl_op_mode *op_mode)
+{
+ struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+ struct iwl_fw_runtime *fwrt = &mvm->fwrt;
+
+ if (!iwl_trans_fw_running(fwrt->trans))
+ return;
+
+ iwl_dbg_tlv_time_point(fwrt, IWL_FW_INI_TIME_POINT_USER_TRIGGER, NULL);
+}
+
#ifdef CONFIG_PM_SLEEP
static void iwl_op_mode_mvm_device_powered_off(struct iwl_op_mode *op_mode)
{
@@ -2125,7 +2084,6 @@ static void iwl_op_mode_mvm_device_powered_off(struct iwl_op_mode *op_mode)
mutex_lock(&mvm->mutex);
clear_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);
- mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
iwl_mvm_stop_device(mvm);
mvm->fast_resume = false;
mutex_unlock(&mvm->mutex);
@@ -2165,7 +2123,7 @@ static void iwl_mvm_rx_mq_rss(struct iwl_op_mode *op_mode,
struct iwl_rx_packet *pkt = rxb_addr(rxb);
u16 cmd = WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd);
- if (unlikely(queue >= mvm->trans->num_rx_queues))
+ if (unlikely(queue >= mvm->trans->info.num_rxqs))
return;
if (unlikely(cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE)))
@@ -2181,4 +2139,5 @@ static const struct iwl_op_mode_ops iwl_mvm_ops_mq = {
IWL_MVM_COMMON_OPS,
.rx = iwl_mvm_rx_mq,
.rx_rss = iwl_mvm_rx_mq_rss,
+ .dump = iwl_mvm_dump,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
index 5e7e2926be0c..4f4111055ddd 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2017 Intel Deutschland GmbH
*/
@@ -202,17 +202,13 @@ int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm,
struct iwl_mvm_phy_ctxt *ctxt,
const struct cfg80211_chan_def *chandef,
- const struct cfg80211_chan_def *ap,
u8 chains_static, u8 chains_dynamic,
u32 action)
{
int ret;
int ver = iwl_fw_lookup_cmd_ver(mvm->fw, PHY_CONTEXT_CMD, 1);
- if (ver < 5 || !ap || !ap->chan)
- ap = NULL;
-
- if (ver >= 3 && ver <= 6) {
+ if (ver >= 3 && ver <= 4) {
struct iwl_phy_context_cmd cmd = {};
/* Set the command header fields */
@@ -223,14 +219,6 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm,
chains_static,
chains_dynamic);
- if (ap) {
- cmd.sbb_bandwidth = iwl_mvm_get_channel_width(ap);
- cmd.sbb_ctrl_channel_loc = iwl_mvm_get_ctrl_pos(ap);
- }
-
- if (ver == 6)
- cmd.puncture_mask = cpu_to_le16(chandef->punctured);
-
ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD,
0, sizeof(cmd), &cmd);
} else if (ver < 3) {
@@ -284,7 +272,7 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
ctxt->width = chandef->width;
ctxt->center_freq1 = chandef->center_freq1;
- ret = iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef, ap,
+ ret = iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
chains_static, chains_dynamic,
FW_CTXT_ACTION_ADD);
@@ -342,7 +330,7 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
int ret;
/* ... remove it here ...*/
- ret = iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef, NULL,
+ ret = iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
chains_static, chains_dynamic,
FW_CTXT_ACTION_REMOVE);
if (ret)
@@ -356,7 +344,7 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
ctxt->width = chandef->width;
ctxt->center_freq1 = chandef->center_freq1;
- return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef, ap,
+ return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
chains_static, chains_dynamic,
action);
}
@@ -376,7 +364,7 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
cfg80211_chandef_create(&chandef, ctxt->channel, NL80211_CHAN_NO_HT);
- iwl_mvm_phy_ctxt_apply(mvm, ctxt, &chandef, NULL, 1, 1,
+ iwl_mvm_phy_ctxt_apply(mvm, ctxt, &chandef, 1, 1,
FW_CTXT_ACTION_REMOVE);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
index a386b315e52f..610de29b7be0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2019, 2021-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2019, 2021-2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -231,7 +231,6 @@ static void iwl_mvm_allow_uapsd_iterator(void *_data, u8 *mac,
switch (vif->type) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_ADHOC:
- case NL80211_IFTYPE_NAN:
data->allow_uapsd = false;
break;
case NL80211_IFTYPE_STATION:
@@ -376,6 +375,9 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
if (!vif->cfg.ps || !mvmvif->pm_enabled)
return;
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, MAC_PM_POWER_TABLE, 0) >= 2)
+ cmd->flags |= cpu_to_le16(POWER_FLAGS_ENABLE_SMPS_MSK);
+
if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
(!fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS) ||
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c b/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
index e89259de6f4c..ad156b82eaa9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2021 - 2023 Intel Corporation
+ * Copyright (C) 2021 - 2023, 2025 Intel Corporation
*/
#include "mvm.h"
@@ -220,6 +220,12 @@ static int iwl_mvm_ptp_gettime(struct ptp_clock_info *ptp,
return 0;
}
+static int iwl_mvm_ptp_settime(struct ptp_clock_info *ptp,
+ const struct timespec64 *ts)
+{
+ return -EOPNOTSUPP;
+}
+
static int iwl_mvm_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{
struct iwl_mvm *mvm = container_of(ptp, struct iwl_mvm,
@@ -281,6 +287,7 @@ void iwl_mvm_ptp_init(struct iwl_mvm *mvm)
mvm->ptp_data.ptp_clock_info.adjfine = iwl_mvm_ptp_adjfine;
mvm->ptp_data.ptp_clock_info.adjtime = iwl_mvm_ptp_adjtime;
mvm->ptp_data.ptp_clock_info.gettime64 = iwl_mvm_ptp_gettime;
+ mvm->ptp_data.ptp_clock_info.settime64 = iwl_mvm_ptp_settime;
mvm->ptp_data.scaled_freq = SCALE_FACTOR;
/* Give a short 'friendly name' to identify the PHC clock */
@@ -298,9 +305,9 @@ void iwl_mvm_ptp_init(struct iwl_mvm *mvm)
PTR_ERR(mvm->ptp_data.ptp_clock));
mvm->ptp_data.ptp_clock = NULL;
} else if (mvm->ptp_data.ptp_clock) {
- IWL_INFO(mvm, "Registered PHC clock: %s, with index: %d\n",
- mvm->ptp_data.ptp_clock_info.name,
- ptp_clock_index(mvm->ptp_data.ptp_clock));
+ IWL_DEBUG_INFO(mvm, "Registered PHC clock: %s, with index: %d\n",
+ mvm->ptp_data.ptp_clock_info.name,
+ ptp_clock_index(mvm->ptp_data.ptp_clock));
}
}
@@ -312,9 +319,9 @@ void iwl_mvm_ptp_init(struct iwl_mvm *mvm)
void iwl_mvm_ptp_remove(struct iwl_mvm *mvm)
{
if (mvm->ptp_data.ptp_clock) {
- IWL_INFO(mvm, "Unregistering PHC clock: %s, with index: %d\n",
- mvm->ptp_data.ptp_clock_info.name,
- ptp_clock_index(mvm->ptp_data.ptp_clock));
+ IWL_DEBUG_INFO(mvm, "Unregistering PHC clock: %s, with index: %d\n",
+ mvm->ptp_data.ptp_clock_info.name,
+ ptp_clock_index(mvm->ptp_data.ptp_clock));
ptp_clock_unregister(mvm->ptp_data.ptp_clock);
mvm->ptp_data.ptp_clock = NULL;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/quota.c b/drivers/net/wireless/intel/iwlwifi/mvm/quota.c
index aad2614af9ad..798a7e4bea83 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/quota.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/quota.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018, 2021-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018, 2021-2022, 2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -86,45 +86,6 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
}
}
-static void iwl_mvm_adjust_quota_for_noa(struct iwl_mvm *mvm,
- struct iwl_time_quota_cmd *cmd)
-{
-#ifdef CONFIG_NL80211_TESTMODE
- struct iwl_mvm_vif *mvmvif;
- int i, phy_id = -1, beacon_int = 0;
-
- if (!mvm->noa_duration || !mvm->noa_vif)
- return;
-
- mvmvif = iwl_mvm_vif_from_mac80211(mvm->noa_vif);
- if (!mvmvif->ap_ibss_active)
- return;
-
- phy_id = mvmvif->deflink.phy_ctxt->id;
- beacon_int = mvm->noa_vif->bss_conf.beacon_int;
-
- for (i = 0; i < MAX_BINDINGS; i++) {
- struct iwl_time_quota_data *data =
- iwl_mvm_quota_cmd_get_quota(mvm, cmd,
- i);
- u32 id_n_c = le32_to_cpu(data->id_and_color);
- u32 id = (id_n_c & FW_CTXT_ID_MSK) >> FW_CTXT_ID_POS;
- u32 quota = le32_to_cpu(data->quota);
-
- if (id != phy_id)
- continue;
-
- quota *= (beacon_int - mvm->noa_duration);
- quota /= beacon_int;
-
- IWL_DEBUG_QUOTA(mvm, "quota: adjust for NoA from %d to %d\n",
- le32_to_cpu(data->quota), quota);
-
- data->quota = cpu_to_le32(quota);
- }
-#endif
-}
-
int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
bool force_update,
struct ieee80211_vif *disabled_vif)
@@ -260,8 +221,6 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
}
}
- iwl_mvm_adjust_quota_for_noa(mvm, &cmd);
-
/* check that we have non-zero quota for all valid bindings */
for (i = 0; i < MAX_BINDINGS; i++) {
qdata = iwl_mvm_quota_cmd_get_quota(mvm, &cmd, i);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
index de5ac000272e..89ac4c6b3e54 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2024 Intel Corporation
+ * Copyright (C) 2018-2025 Intel Corporation
*/
#include "rs.h"
#include "fw-api.h"
@@ -72,7 +72,7 @@ static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
u16 flags = 0;
/* get STBC flags */
- if (mvm->cfg->ht_params->stbc &&
+ if (mvm->cfg->ht_params.stbc &&
(num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1)) {
if (he_cap->has_he && he_cap->he_cap_elem.phy_cap_info[2] &
IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ)
@@ -83,7 +83,7 @@ static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
}
- if (mvm->cfg->ht_params->ldpc &&
+ if (mvm->cfg->ht_params.ldpc &&
((ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING) ||
(vht_ena && (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC))))
flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
@@ -454,22 +454,11 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
if (flags & IWL_TLC_NOTIF_FLAG_RATE) {
char pretty_rate[100];
- if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP,
- TLC_MNG_UPDATE_NOTIF, 0) < 3) {
- rs_pretty_print_rate_v1(pretty_rate,
- sizeof(pretty_rate),
- le32_to_cpu(notif->rate));
- IWL_DEBUG_RATE(mvm,
- "Got rate in old format. Rate: %s. Converting.\n",
- pretty_rate);
- lq_sta->last_rate_n_flags =
- iwl_new_rate_from_v1(le32_to_cpu(notif->rate));
- } else {
- lq_sta->last_rate_n_flags = le32_to_cpu(notif->rate);
- }
+ lq_sta->last_rate_n_flags =
+ iwl_mvm_v3_rate_from_fw(notif->rate, mvm->fw_rates_ver);
rs_pretty_print_rate(pretty_rate, sizeof(pretty_rate),
lq_sta->last_rate_n_flags);
- IWL_DEBUG_RATE(mvm, "new rate: %s\n", pretty_rate);
+ IWL_DEBUG_RATE(mvm, "rate: %s\n", pretty_rate);
}
if (flags & IWL_TLC_NOTIF_FLAG_AMSDU && !mvm_link_sta->orig_amsdu_len) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
index 068c58e9c1eb..d1619a229d8f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
@@ -2,6 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2005 - 2014, 2018 - 2023 Intel Corporation. All rights reserved.
+ * Copyright(c) 2025 Intel Corporation
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*****************************************************************************/
@@ -895,7 +896,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
WARN_ON_ONCE(1);
}
} else if (ucode_rate & RATE_MCS_VHT_MSK_V1) {
- nss = FIELD_GET(RATE_MCS_NSS_MSK, ucode_rate) + 1;
+ nss = FIELD_GET(RATE_VHT_MCS_NSS_MSK, ucode_rate) + 1;
if (nss == 1) {
rate->type = LQ_VHT_SISO;
@@ -909,7 +910,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
WARN_ON_ONCE(1);
}
} else if (ucode_rate & RATE_MCS_HE_MSK_V1) {
- nss = FIELD_GET(RATE_MCS_NSS_MSK, ucode_rate) + 1;
+ nss = FIELD_GET(RATE_VHT_MCS_NSS_MSK, ucode_rate) + 1;
if (nss == 1) {
rate->type = LQ_HE_SISO;
@@ -2696,8 +2697,10 @@ static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta,
lq_sta = mvm_sta;
spin_lock_bh(&lq_sta->pers.lock);
- iwl_mvm_hwrate_to_tx_rate_v1(lq_sta->last_rate_n_flags,
- info->band, &info->control.rates[0]);
+ iwl_mvm_hwrate_to_tx_rate(iwl_mvm_v3_rate_from_fw(
+ cpu_to_le32(lq_sta->last_rate_n_flags),
+ 1),
+ info->band, &info->control.rates[0]);
info->control.rates[0].count = 1;
/* Report the optimal rate based on rssi and STA caps if we haven't
@@ -2707,8 +2710,12 @@ static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta,
optimal_rate = rs_get_optimal_rate(mvm, lq_sta);
last_ucode_rate = ucode_rate_from_rs_rate(mvm,
optimal_rate);
- iwl_mvm_hwrate_to_tx_rate_v1(last_ucode_rate, info->band,
- &txrc->reported_rate);
+ last_ucode_rate =
+ iwl_mvm_v3_rate_from_fw(cpu_to_le32(last_ucode_rate),
+ 1);
+ iwl_mvm_hwrate_to_tx_rate(last_ucode_rate, info->band,
+ &txrc->reported_rate);
+ txrc->reported_rate.count = 1;
}
spin_unlock_bh(&lq_sta->pers.lock);
}
@@ -2813,11 +2820,11 @@ static void rs_ht_init(struct iwl_mvm *mvm,
lq_sta->active_mimo2_rate &= ~((u16)0x2);
lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE;
- if (mvm->cfg->ht_params->ldpc &&
+ if (mvm->cfg->ht_params.ldpc &&
(ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING))
lq_sta->ldpc = true;
- if (mvm->cfg->ht_params->stbc &&
+ if (mvm->cfg->ht_params.stbc &&
(num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) &&
(ht_cap->cap & IEEE80211_HT_CAP_RX_STBC))
lq_sta->stbc_capable = true;
@@ -2832,11 +2839,11 @@ static void rs_vht_init(struct iwl_mvm *mvm,
{
rs_vht_set_enabled_rates(sta, vht_cap, lq_sta);
- if (mvm->cfg->ht_params->ldpc &&
+ if (mvm->cfg->ht_params.ldpc &&
(vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC))
lq_sta->ldpc = true;
- if (mvm->cfg->ht_params->stbc &&
+ if (mvm->cfg->ht_params.stbc &&
(num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) &&
(vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK))
lq_sta->stbc_capable = true;
@@ -2887,10 +2894,10 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg)
if (rate & RATE_MCS_HT_MSK_V1) {
mvm->drv_rx_stats.ht_frames++;
- nss = ((rate & RATE_HT_MCS_NSS_MSK_V1) >> RATE_HT_MCS_NSS_POS_V1) + 1;
+ nss = FIELD_GET(RATE_HT_MCS_MIMO2_MSK, rate) + 1;
} else if (rate & RATE_MCS_VHT_MSK_V1) {
mvm->drv_rx_stats.vht_frames++;
- nss = FIELD_GET(RATE_MCS_NSS_MSK, rate) + 1;
+ nss = FIELD_GET(RATE_VHT_MCS_NSS_MSK, rate) + 1;
} else {
mvm->drv_rx_stats.legacy_frames++;
}
@@ -3304,7 +3311,7 @@ static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm,
if (num_of_ant(ant) == 1)
lq_cmd->single_stream_ant_msk = ant;
- if (!mvm->trans->trans_cfg->gen2)
+ if (!mvm->trans->mac_cfg->gen2)
lq_cmd->agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
else
lq_cmd->agg_frame_cnt_limit =
@@ -3673,16 +3680,15 @@ int rs_pretty_print_rate_v1(char *buf, int bufsz, const u32 rate)
if (rate & RATE_MCS_VHT_MSK_V1) {
type = "VHT";
mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK;
- nss = FIELD_GET(RATE_MCS_NSS_MSK, rate) + 1;
+ nss = FIELD_GET(RATE_VHT_MCS_NSS_MSK, rate) + 1;
} else if (rate & RATE_MCS_HT_MSK_V1) {
type = "HT";
mcs = rate & RATE_HT_MCS_INDEX_MSK_V1;
- nss = ((rate & RATE_HT_MCS_NSS_MSK_V1)
- >> RATE_HT_MCS_NSS_POS_V1) + 1;
+ nss = FIELD_GET(RATE_HT_MCS_MIMO2_MSK, rate) + 1;
} else if (rate & RATE_MCS_HE_MSK_V1) {
type = "HE";
mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK;
- nss = FIELD_GET(RATE_MCS_NSS_MSK, rate) + 1;
+ nss = FIELD_GET(RATE_VHT_MCS_NSS_MSK, rate) + 1;
} else {
type = "Unknown"; /* shouldn't happen */
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
index ea81cb236d5c..34c957bef6f8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
@@ -3,7 +3,7 @@
*
* Copyright(c) 2015 Intel Mobile Communications GmbH
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright (C) 2003 - 2014, 2018 - 2024 Intel Corporation
+ * Copyright (C) 2003 - 2014, 2018 - 2025 Intel Corporation
*****************************************************************************/
#ifndef __rs_h__
@@ -411,6 +411,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
* with the mac80211 subsystem. This should be performed prior to calling
* ieee80211_register_hw
*
+ * Return: negative error code, or 0 on success
*/
int iwl_mvm_rate_control_register(void);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index 2dbef7b46355..d0c0faae0122 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -490,8 +490,6 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
if (!(rate_n_flags & RATE_MCS_CCK_MSK_V1) &&
rate_n_flags & RATE_MCS_SGI_MSK_V1)
rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
- if (rate_n_flags & RATE_HT_MCS_GF_MSK)
- rx_status->enc_flags |= RX_ENC_FLAG_HT_GF;
if (rate_n_flags & RATE_MCS_LDPC_MSK_V1)
rx_status->enc_flags |= RX_ENC_FLAG_LDPC;
if (rate_n_flags & RATE_MCS_HT_MSK_V1) {
@@ -521,6 +519,8 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
return;
}
rx_status->rate_idx = rate;
+ /* override BW - it could be DUP and indicate the wrong BW */
+ rx_status->bw = RATE_INFO_BW_20;
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -565,7 +565,6 @@ static void iwl_mvm_update_link_sig(struct ieee80211_vif *vif, int sig,
int thold = bss_conf->cqm_rssi_thold;
int hyst = bss_conf->cqm_rssi_hyst;
int last_event;
- s8 exit_esr_thresh;
if (sig == 0) {
IWL_DEBUG_RX(mvm, "RSSI is 0 - skip signal based decision\n");
@@ -621,27 +620,6 @@ static void iwl_mvm_update_link_sig(struct ieee80211_vif *vif, int sig,
sig,
GFP_KERNEL);
}
-
- /* ESR recalculation */
- if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif))
- return;
-
- /* We're not in EMLSR and our signal is bad, try to switch link maybe */
- if (sig < IWL_MVM_LOW_RSSI_MLO_SCAN_THRESH && !mvmvif->esr_active) {
- iwl_mvm_int_mlo_scan(mvm, vif);
- return;
- }
-
- /* We are in EMLSR, check if we need to exit */
- exit_esr_thresh =
- iwl_mvm_get_esr_rssi_thresh(mvm,
- &bss_conf->chanreq.oper,
- true);
-
- if (sig < exit_esr_thresh)
- iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_LOW_RSSI,
- iwl_mvm_get_other_link(vif,
- bss_conf->link_id));
}
static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
@@ -879,28 +857,28 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm,
u32 rx_bytes[MAC_INDEX_AUX] = {};
int fw_link_id;
- for (fw_link_id = 0; fw_link_id < ARRAY_SIZE(mvm->link_id_to_link_conf);
+ /* driver uses link ID == MAC ID */
+ for (fw_link_id = 0; fw_link_id < ARRAY_SIZE(mvm->vif_id_to_mac);
fw_link_id++) {
struct iwl_stats_ntfy_per_link *link_stats;
- struct ieee80211_bss_conf *bss_conf;
- struct iwl_mvm_vif *mvmvif;
struct iwl_mvm_vif_link_info *link_info;
+ struct iwl_mvm_vif *mvmvif;
+ struct ieee80211_vif *vif;
int link_id;
int sig;
- bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, fw_link_id,
- false);
- if (!bss_conf)
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, fw_link_id, false);
+ if (!vif)
continue;
- if (bss_conf->vif->type != NL80211_IFTYPE_STATION)
+ if (vif->type != NL80211_IFTYPE_STATION)
continue;
- link_id = bss_conf->link_id;
+ link_id = vif->bss_conf.link_id;
if (link_id >= ARRAY_SIZE(mvmvif->link))
continue;
- mvmvif = iwl_mvm_vif_from_mac80211(bss_conf->vif);
+ mvmvif = iwl_mvm_vif_from_mac80211(vif);
link_info = mvmvif->link[link_id];
if (!link_info)
continue;
@@ -916,11 +894,6 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm,
link_info->beacon_stats.avg_signal =
-le32_to_cpu(link_stats->beacon_average_energy);
- if (link_info->phy_ctxt &&
- link_info->phy_ctxt->channel->band == NL80211_BAND_2GHZ)
- iwl_mvm_bt_coex_update_link_esr(mvm, bss_conf->vif,
- link_id);
-
/* make sure that beacon statistics don't go backwards with TCM
* request to clear statistics
*/
@@ -929,8 +902,7 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm,
mvmvif->link[link_id]->beacon_stats.num_beacons;
sig = -le32_to_cpu(link_stats->beacon_filter_average_energy);
- iwl_mvm_update_link_sig(bss_conf->vif, sig, link_info,
- bss_conf);
+ iwl_mvm_update_link_sig(vif, sig, link_info, &vif->bss_conf);
if (WARN_ONCE(mvmvif->id >= MAC_INDEX_AUX,
"invalid mvmvif id: %d", mvmvif->id))
@@ -960,111 +932,6 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm,
}
}
-#define SEC_LINK_MIN_PERC 10
-#define SEC_LINK_MIN_TX 3000
-#define SEC_LINK_MIN_RX 400
-
-/* Accept a ~20% short window to avoid issues due to jitter */
-#define IWL_MVM_TPT_MIN_COUNT_WINDOW (IWL_MVM_TPT_COUNT_WINDOW_SEC * HZ * 4 / 5)
-
-static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm)
-{
- struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm);
- struct iwl_mvm_vif *mvmvif;
- struct iwl_mvm_sta *mvmsta;
- unsigned long total_tx = 0, total_rx = 0;
- unsigned long sec_link_tx = 0, sec_link_rx = 0;
- u8 sec_link_tx_perc, sec_link_rx_perc;
- u8 sec_link;
- bool skip = false;
-
- lockdep_assert_held(&mvm->mutex);
-
- if (IS_ERR_OR_NULL(bss_vif))
- return;
-
- mvmvif = iwl_mvm_vif_from_mac80211(bss_vif);
-
- if (!mvmvif->esr_active || !mvmvif->ap_sta)
- return;
-
- mvmsta = iwl_mvm_sta_from_mac80211(mvmvif->ap_sta);
- /* We only count for the AP sta in a MLO connection */
- if (!mvmsta->mpdu_counters)
- return;
-
- /* Get the FW ID of the secondary link */
- sec_link = iwl_mvm_get_other_link(bss_vif,
- iwl_mvm_get_primary_link(bss_vif));
- if (WARN_ON(!mvmvif->link[sec_link]))
- return;
- sec_link = mvmvif->link[sec_link]->fw_link_id;
-
- /* Sum up RX and TX MPDUs from the different queues/links */
- for (int q = 0; q < mvm->trans->num_rx_queues; q++) {
- spin_lock_bh(&mvmsta->mpdu_counters[q].lock);
-
- /* The link IDs that doesn't exist will contain 0 */
- for (int link = 0; link < IWL_FW_MAX_LINK_ID; link++) {
- total_tx += mvmsta->mpdu_counters[q].per_link[link].tx;
- total_rx += mvmsta->mpdu_counters[q].per_link[link].rx;
- }
-
- sec_link_tx += mvmsta->mpdu_counters[q].per_link[sec_link].tx;
- sec_link_rx += mvmsta->mpdu_counters[q].per_link[sec_link].rx;
-
- /*
- * In EMLSR we have statistics every 5 seconds, so we can reset
- * the counters upon every statistics notification.
- * The FW sends the notification regularly, but it will be
- * misaligned at the start. Skipping the measurement if it is
- * short will synchronize us.
- */
- if (jiffies - mvmsta->mpdu_counters[q].window_start <
- IWL_MVM_TPT_MIN_COUNT_WINDOW)
- skip = true;
- mvmsta->mpdu_counters[q].window_start = jiffies;
- memset(mvmsta->mpdu_counters[q].per_link, 0,
- sizeof(mvmsta->mpdu_counters[q].per_link));
-
- spin_unlock_bh(&mvmsta->mpdu_counters[q].lock);
- }
-
- if (skip) {
- IWL_DEBUG_INFO(mvm, "MPDU statistics window was short\n");
- return;
- }
-
- IWL_DEBUG_INFO(mvm, "total Tx MPDUs: %ld. total Rx MPDUs: %ld\n",
- total_tx, total_rx);
-
- /* If we don't have enough MPDUs - exit EMLSR */
- if (total_tx < IWL_MVM_ENTER_ESR_TPT_THRESH &&
- total_rx < IWL_MVM_ENTER_ESR_TPT_THRESH) {
- iwl_mvm_block_esr(mvm, bss_vif, IWL_MVM_ESR_BLOCKED_TPT,
- iwl_mvm_get_primary_link(bss_vif));
- return;
- }
-
- IWL_DEBUG_INFO(mvm, "Secondary Link %d: Tx MPDUs: %ld. Rx MPDUs: %ld\n",
- sec_link, sec_link_tx, sec_link_rx);
-
- /* Calculate the percentage of the secondary link TX/RX */
- sec_link_tx_perc = total_tx ? sec_link_tx * 100 / total_tx : 0;
- sec_link_rx_perc = total_rx ? sec_link_rx * 100 / total_rx : 0;
-
- /*
- * The TX/RX percentage is checked only if it exceeds the required
- * minimum. In addition, RX is checked only if the TX check failed.
- */
- if ((total_tx > SEC_LINK_MIN_TX &&
- sec_link_tx_perc < SEC_LINK_MIN_PERC) ||
- (total_rx > SEC_LINK_MIN_RX &&
- sec_link_rx_perc < SEC_LINK_MIN_PERC))
- iwl_mvm_exit_esr(mvm, bss_vif, IWL_MVM_ESR_EXIT_LINK_USAGE,
- iwl_mvm_get_primary_link(bss_vif));
-}
-
void iwl_mvm_handle_rx_system_oper_stats(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb)
{
@@ -1092,8 +959,6 @@ void iwl_mvm_handle_rx_system_oper_stats(struct iwl_mvm *mvm,
ieee80211_iterate_stations_atomic(mvm->hw, iwl_mvm_stats_energy_iter,
average_energy);
iwl_mvm_handle_per_phy_stats(mvm, stats->per_phy);
-
- iwl_mvm_update_esr_mode_tpt(mvm);
}
void iwl_mvm_handle_rx_system_oper_part1_stats(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index 14ea89f931bb..d35c63a673b6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -171,7 +171,7 @@ static int iwl_mvm_create_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
shdr->type != htons(ETH_P_PAE) &&
shdr->type != htons(ETH_P_TDLS))))
skb->ip_summed = CHECKSUM_NONE;
- else if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
+ else if (mvm->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
/* mac80211 assumes full CSUM including SNAP header */
skb_postpush_rcsum(skb, shdr, sizeof(*shdr));
}
@@ -246,13 +246,62 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
ieee80211_rx_napi(mvm->hw, sta, skb, napi);
}
+static bool iwl_mvm_used_average_energy(struct iwl_mvm *mvm,
+ struct iwl_rx_mpdu_desc *desc,
+ struct ieee80211_hdr *hdr,
+ struct ieee80211_rx_status *rx_status)
+{
+ struct iwl_mvm_vif *mvm_vif;
+ struct ieee80211_vif *vif;
+ u32 id;
+
+ if (unlikely(!hdr || !desc))
+ return false;
+
+ if (likely(!ieee80211_is_beacon(hdr->frame_control)))
+ return false;
+
+ /* for the link conf lookup */
+ guard(rcu)();
+
+ /* MAC or link ID depending on FW, but driver has them equal */
+ id = u8_get_bits(desc->mac_phy_band,
+ IWL_RX_MPDU_MAC_PHY_BAND_MAC_MASK);
+
+ /* >= means AUX MAC/link ID, no energy correction needed then */
+ if (id >= ARRAY_SIZE(mvm->vif_id_to_mac))
+ return false;
+
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
+ if (!vif)
+ return false;
+
+ mvm_vif = iwl_mvm_vif_from_mac80211(vif);
+
+ /*
+ * If we know the MAC by MAC or link ID then the frame was
+ * received for the link, so by filtering it means it was
+ * from the AP the link is connected to.
+ */
+
+ /* skip also in case we don't have it (yet) */
+ if (!mvm_vif->deflink.average_beacon_energy)
+ return false;
+
+ IWL_DEBUG_STATS(mvm, "energy override by average %d\n",
+ mvm_vif->deflink.average_beacon_energy);
+ rx_status->signal = -mvm_vif->deflink.average_beacon_energy;
+ return true;
+}
+
static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
+ struct iwl_rx_mpdu_desc *desc,
+ struct ieee80211_hdr *hdr,
struct ieee80211_rx_status *rx_status,
u32 rate_n_flags, int energy_a,
int energy_b)
{
int max_energy;
- u32 rate_flags = rate_n_flags;
energy_a = energy_a ? -energy_a : S8_MIN;
energy_b = energy_b ? -energy_b : S8_MIN;
@@ -261,9 +310,11 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
IWL_DEBUG_STATS(mvm, "energy In A %d B %d, and max %d\n",
energy_a, energy_b, max_energy);
+ if (iwl_mvm_used_average_energy(mvm, desc, hdr, rx_status))
+ return;
+
rx_status->signal = max_energy;
- rx_status->chains =
- (rate_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;
+ rx_status->chains = u32_get_bits(rate_n_flags, RATE_MCS_ANT_AB_MSK);
rx_status->chain_signal[0] = energy_a;
rx_status->chain_signal[1] = energy_b;
}
@@ -281,6 +332,7 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
struct ieee80211_key_conf *key;
u32 len = le16_to_cpu(desc->mpdu_len);
const u8 *frame = (void *)hdr;
+ const u8 *mmie;
if ((status & IWL_RX_MPDU_STATUS_SEC_MASK) == IWL_RX_MPDU_STATUS_SEC_NONE)
return 0;
@@ -324,11 +376,15 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
goto report;
}
- if (len < key->icv_len + IEEE80211_GMAC_PN_LEN + 2)
+ if (len < key->icv_len)
goto report;
/* get the real key ID */
- keyid = frame[len - key->icv_len - IEEE80211_GMAC_PN_LEN - 2];
+ mmie = frame + (len - key->icv_len);
+
+ /* the position of the key_id in ieee80211_mmie_16 is the same */
+ keyid = le16_to_cpu(((const struct ieee80211_mmie *) mmie)->key_id);
+
/* and if that's the other key, look it up */
if (keyid != key->keyidx) {
/*
@@ -409,7 +465,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
!(status & IWL_RX_MPDU_RES_STATUS_TTAK_OK))
return 0;
- if (mvm->trans->trans_cfg->gen2 &&
+ if (mvm->trans->mac_cfg->gen2 &&
!(status & RX_MPDU_RES_STATUS_MIC_OK))
stats->flag |= RX_FLAG_MMIC_ERROR;
@@ -426,7 +482,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
if (pkt_flags & FH_RSCSR_RADA_EN) {
stats->flag |= RX_FLAG_ICV_STRIPPED;
- if (mvm->trans->trans_cfg->gen2)
+ if (mvm->trans->mac_cfg->gen2)
stats->flag |= RX_FLAG_MMIC_STRIPPED;
}
@@ -462,7 +518,7 @@ static void iwl_mvm_rx_csum(struct iwl_mvm *mvm,
{
struct iwl_rx_mpdu_desc *desc = (void *)pkt->data;
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
if (pkt->len_n_flags & cpu_to_le32(FH_RSCSR_RPA_EN)) {
u16 hwsum = be16_to_cpu(desc->v3.raw_xsum);
@@ -744,7 +800,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
baid = (reorder & IWL_RX_MPDU_REORDER_BAID_MASK) >>
IWL_RX_MPDU_REORDER_BAID_SHIFT;
- if (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_9000)
+ if (mvm->trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_9000)
return false;
/*
@@ -854,10 +910,15 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
* already ahead and it will be dropped.
* If the last sub-frame is not on this queue - we will get frame
* release notification with up to date NSSN.
+ * If this is the first frame that is stored in the buffer, the head_sn
+ * may be outdated. Update it based on the last NSSN to make sure it
+ * will be released when the frame release notification arrives.
*/
if (!amsdu || last_subframe)
iwl_mvm_release_frames(mvm, sta, napi, baid_data,
buffer, nssn);
+ else if (buffer->num_stored == 1)
+ buffer->head_sn = nssn;
spin_unlock_bh(&buffer->lock);
return true;
@@ -1906,8 +1967,11 @@ static void iwl_mvm_rx_get_sta_block_tx(void *data, struct ieee80211_sta *sta)
/*
* Note: requires also rx_status->band to be prefilled, as well
* as phy_data (apart from phy_data->info_type)
+ * Note: desc/hdr may be NULL
*/
static void iwl_mvm_rx_fill_status(struct iwl_mvm *mvm,
+ struct iwl_rx_mpdu_desc *desc,
+ struct ieee80211_hdr *hdr,
struct sk_buff *skb,
struct iwl_mvm_rx_phy_data *phy_data,
int queue)
@@ -1944,7 +2008,7 @@ static void iwl_mvm_rx_fill_status(struct iwl_mvm *mvm,
}
/* must be before L-SIG data */
- if (format == RATE_MCS_HE_MSK)
+ if (format == RATE_MCS_MOD_TYPE_HE)
iwl_mvm_rx_he(mvm, skb, phy_data, queue);
iwl_mvm_decode_lsig(skb, phy_data);
@@ -1962,49 +2026,49 @@ static void iwl_mvm_rx_fill_status(struct iwl_mvm *mvm,
rx_status->freq = ieee80211_channel_to_frequency(phy_data->channel,
rx_status->band);
- iwl_mvm_get_signal_strength(mvm, rx_status, rate_n_flags,
+ iwl_mvm_get_signal_strength(mvm, desc, hdr, rx_status, rate_n_flags,
phy_data->energy_a, phy_data->energy_b);
/* using TLV format and must be after all fixed len fields */
- if (format == RATE_MCS_EHT_MSK)
+ if (format == RATE_MCS_MOD_TYPE_EHT)
iwl_mvm_rx_eht(mvm, skb, phy_data, queue);
if (unlikely(mvm->monitor_on))
iwl_mvm_add_rtap_sniffer_config(mvm, skb);
- is_sgi = format == RATE_MCS_HE_MSK ?
+ is_sgi = format == RATE_MCS_MOD_TYPE_HE ?
iwl_he_is_sgi(rate_n_flags) :
rate_n_flags & RATE_MCS_SGI_MSK;
- if (!(format == RATE_MCS_CCK_MSK) && is_sgi)
+ if (!(format == RATE_MCS_MOD_TYPE_CCK) && is_sgi)
rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
if (rate_n_flags & RATE_MCS_LDPC_MSK)
rx_status->enc_flags |= RX_ENC_FLAG_LDPC;
switch (format) {
- case RATE_MCS_VHT_MSK:
+ case RATE_MCS_MOD_TYPE_VHT:
rx_status->encoding = RX_ENC_VHT;
break;
- case RATE_MCS_HE_MSK:
+ case RATE_MCS_MOD_TYPE_HE:
rx_status->encoding = RX_ENC_HE;
rx_status->he_dcm =
!!(rate_n_flags & RATE_HE_DUAL_CARRIER_MODE_MSK);
break;
- case RATE_MCS_EHT_MSK:
+ case RATE_MCS_MOD_TYPE_EHT:
rx_status->encoding = RX_ENC_EHT;
break;
}
switch (format) {
- case RATE_MCS_HT_MSK:
+ case RATE_MCS_MOD_TYPE_HT:
rx_status->encoding = RX_ENC_HT;
rx_status->rate_idx = RATE_HT_MCS_INDEX(rate_n_flags);
rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
break;
- case RATE_MCS_VHT_MSK:
- case RATE_MCS_HE_MSK:
- case RATE_MCS_EHT_MSK:
+ case RATE_MCS_MOD_TYPE_VHT:
+ case RATE_MCS_MOD_TYPE_HE:
+ case RATE_MCS_MOD_TYPE_EHT:
rx_status->nss =
u32_get_bits(rate_n_flags, RATE_MCS_NSS_MSK) + 1;
rx_status->rate_idx = rate_n_flags & RATE_MCS_CODE_MSK;
@@ -2040,7 +2104,6 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
struct ieee80211_sta *sta = NULL;
struct sk_buff *skb;
u8 crypt_len = 0;
- u8 sta_id = le32_get_bits(desc->status, IWL_RX_MPDU_STATUS_STA_ID);
size_t desc_size;
struct iwl_mvm_rx_phy_data phy_data = {};
u32 format;
@@ -2048,7 +2111,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
return;
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
desc_size = sizeof(*desc);
else
desc_size = IWL_RX_DESC_SIZE_V1;
@@ -2058,8 +2121,10 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
return;
}
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
- phy_data.rate_n_flags = le32_to_cpu(desc->v3.rate_n_flags);
+ if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ phy_data.rate_n_flags =
+ iwl_mvm_v3_rate_from_fw(desc->v3.rate_n_flags,
+ mvm->fw_rates_ver);
phy_data.channel = desc->v3.channel;
phy_data.gp2_on_air_rise = le32_to_cpu(desc->v3.gp2_on_air_rise);
phy_data.energy_a = desc->v3.energy_a;
@@ -2072,7 +2137,9 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
phy_data.eht_d4 = desc->phy_eht_data4;
phy_data.d5 = desc->v3.phy_data5;
} else {
- phy_data.rate_n_flags = le32_to_cpu(desc->v1.rate_n_flags);
+ phy_data.rate_n_flags =
+ iwl_mvm_v3_rate_from_fw(desc->v1.rate_n_flags,
+ mvm->fw_rates_ver);
phy_data.channel = desc->v1.channel;
phy_data.gp2_on_air_rise = le32_to_cpu(desc->v1.gp2_on_air_rise);
phy_data.energy_a = desc->v1.energy_a;
@@ -2084,13 +2151,6 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
phy_data.d3 = desc->v1.phy_data3;
}
- if (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
- REPLY_RX_MPDU_CMD, 0) < 4) {
- phy_data.rate_n_flags = iwl_new_rate_from_v1(phy_data.rate_n_flags);
- IWL_DEBUG_DROP(mvm, "Got old format rate, converting. New rate: 0x%x\n",
- phy_data.rate_n_flags);
- }
-
format = phy_data.rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
len = le16_to_cpu(desc->mpdu_len);
@@ -2138,14 +2198,14 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
}
/* set the preamble flag if appropriate */
- if (format == RATE_MCS_CCK_MSK &&
+ if (format == RATE_MCS_MOD_TYPE_CCK &&
phy_data.phy_info & IWL_RX_MPDU_PHY_SHORT_PREAMBLE)
rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE;
if (likely(!(phy_data.phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD))) {
u64 tsf_on_air_rise;
- if (mvm->trans->trans_cfg->device_family >=
+ if (mvm->trans->mac_cfg->device_family >=
IWL_DEVICE_FAMILY_AX210)
tsf_on_air_rise = le64_to_cpu(desc->v3.tsf_on_air_rise);
else
@@ -2157,7 +2217,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
}
if (iwl_mvm_is_band_in_rx_supported(mvm)) {
- u8 band = BAND_IN_RX_STATUS(desc->mac_phy_idx);
+ u8 band = u8_get_bits(desc->mac_phy_band,
+ IWL_RX_MPDU_MAC_PHY_BAND_BAND_MASK);
rx_status->band = iwl_mvm_nl80211_band_from_phy(band);
} else {
@@ -2189,6 +2250,9 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
rcu_read_lock();
if (desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_SRC_STA_FOUND)) {
+ u8 sta_id = le32_get_bits(desc->status,
+ IWL_RX_MPDU_STATUS_STA_ID);
+
if (!WARN_ON_ONCE(sta_id >= mvm->fw->ucode_capa.num_stations)) {
struct ieee80211_link_sta *link_sta;
@@ -2217,7 +2281,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
goto out;
}
- iwl_mvm_rx_fill_status(mvm, skb, &phy_data, queue);
+ iwl_mvm_rx_fill_status(mvm, desc, hdr, skb, &phy_data, queue);
if (sta) {
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
@@ -2303,7 +2367,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
*qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
- if (mvm->trans->trans_cfg->device_family ==
+ if (mvm->trans->mac_cfg->device_family ==
IWL_DEVICE_FAMILY_9000) {
iwl_mvm_flip_address(hdr->addr3);
@@ -2316,16 +2380,6 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
iwl_mvm_agg_rx_received(mvm, reorder_data, baid);
}
-
- if (ieee80211_is_data(hdr->frame_control)) {
- u8 sub_frame_idx = desc->amsdu_info &
- IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;
-
- /* 0 means not an A-MSDU, and 1 means a new A-MSDU */
- if (!sub_frame_idx || sub_frame_idx == 1)
- iwl_mvm_count_mpdu(mvmsta, sta_id, 1, false,
- queue);
- }
}
/* management stuff on default queue */
@@ -2349,7 +2403,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc) &&
likely(!iwl_mvm_time_sync_frame(mvm, skb, hdr->addr2)) &&
likely(!iwl_mvm_mei_filter_scan(mvm, skb))) {
- if (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
+ if (mvm->trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
(desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU) &&
!(desc->amsdu_info & IWL_RX_MPDU_AMSDU_LAST_SUBFRAME))
rx_status->flag |= RX_FLAG_AMSDU_MORE;
@@ -2383,7 +2437,6 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
phy_data.d1 = desc->phy_info[1];
phy_data.phy_info = IWL_RX_MPDU_PHY_TSF_OVERLOAD;
phy_data.gp2_on_air_rise = le32_to_cpu(desc->on_air_rise_time);
- phy_data.rate_n_flags = le32_to_cpu(desc->rate);
phy_data.energy_a = u32_get_bits(rssi, RX_NO_DATA_CHAIN_A_MSK);
phy_data.energy_b = u32_get_bits(rssi, RX_NO_DATA_CHAIN_B_MSK);
phy_data.channel = u32_get_bits(rssi, RX_NO_DATA_CHANNEL_MSK);
@@ -2391,14 +2444,8 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
phy_data.rx_vec[0] = desc->rx_vec[0];
phy_data.rx_vec[1] = desc->rx_vec[1];
- if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP,
- RX_NO_DATA_NOTIF, 0) < 2) {
- IWL_DEBUG_DROP(mvm, "Got an old rate format. Old rate: 0x%x\n",
- phy_data.rate_n_flags);
- phy_data.rate_n_flags = iwl_new_rate_from_v1(phy_data.rate_n_flags);
- IWL_DEBUG_DROP(mvm, " Rate after conversion to the new format: 0x%x\n",
- phy_data.rate_n_flags);
- }
+ phy_data.rate_n_flags = iwl_mvm_v3_rate_from_fw(desc->rate,
+ mvm->fw_rates_ver);
format = phy_data.rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
@@ -2411,7 +2458,7 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
phy_data.rx_vec[2] = desc->rx_vec[2];
phy_data.rx_vec[3] = desc->rx_vec[3];
} else {
- if (format == RATE_MCS_EHT_MSK)
+ if (format == RATE_MCS_MOD_TYPE_EHT)
/* no support for EHT before version 3 API */
return;
}
@@ -2454,7 +2501,7 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
rx_status->band = phy_data.channel > 14 ? NL80211_BAND_5GHZ :
NL80211_BAND_2GHZ;
- iwl_mvm_rx_fill_status(mvm, skb, &phy_data, queue);
+ iwl_mvm_rx_fill_status(mvm, NULL, NULL, skb, &phy_data, queue);
/* no more radio tap info should be put after this point.
*
@@ -2472,17 +2519,17 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
* may be up to 8 spatial streams.
*/
switch (format) {
- case RATE_MCS_VHT_MSK:
+ case RATE_MCS_MOD_TYPE_VHT:
rx_status->nss =
le32_get_bits(desc->rx_vec[0],
RX_NO_DATA_RX_VEC0_VHT_NSTS_MSK) + 1;
break;
- case RATE_MCS_HE_MSK:
+ case RATE_MCS_MOD_TYPE_HE:
rx_status->nss =
le32_get_bits(desc->rx_vec[0],
RX_NO_DATA_RX_VEC0_HE_NSTS_MSK) + 1;
break;
- case RATE_MCS_EHT_MSK:
+ case RATE_MCS_MOD_TYPE_EHT:
rx_status->nss =
le32_get_bits(desc->rx_vec[2],
RX_NO_DATA_RX_VEC2_EHT_NSTS_MSK) + 1;
@@ -2557,3 +2604,28 @@ void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
out:
rcu_read_unlock();
}
+
+void iwl_mvm_rx_beacon_filter_notif(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ /* MAC or link ID in v1/v2, but driver has the IDs equal */
+ struct iwl_beacon_filter_notif *notif = (void *)pkt->data;
+ u32 id = le32_to_cpu(notif->link_id);
+ struct iwl_mvm_vif *mvm_vif;
+ struct ieee80211_vif *vif;
+
+ /* >= means AUX MAC/link ID, no energy correction needed then */
+ if (IWL_FW_CHECK(mvm, id >= ARRAY_SIZE(mvm->vif_id_to_mac),
+ "invalid link ID %d\n", id))
+ return;
+
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false);
+ if (!vif)
+ return;
+
+ mvm_vif = iwl_mvm_vif_from_mac80211(vif);
+
+ mvm_vif->deflink.average_beacon_energy =
+ le32_to_cpu(notif->average_energy);
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index 60bd9c7e5f03..b588f1dcf20d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -11,6 +11,7 @@
#include "mvm.h"
#include "fw/api/scan.h"
#include "iwl-io.h"
+#include "iwl-utils.h"
#define IWL_DENSE_EBS_SCAN_RATIO 5
#define IWL_SPARSE_EBS_SCAN_RATIO 1
@@ -835,7 +836,7 @@ static inline bool iwl_mvm_scan_fits(struct iwl_mvm *mvm, int n_ssids,
int n_channels)
{
return ((n_ssids <= PROBE_OPTION_MAX) &&
- (n_channels <= mvm->fw->ucode_capa.n_scan_channels) &
+ (n_channels <= mvm->fw->ucode_capa.n_scan_channels) &&
(ies->common_ie_len +
ies->len[NL80211_BAND_2GHZ] + ies->len[NL80211_BAND_5GHZ] +
ies->len[NL80211_BAND_6GHZ] <=
@@ -1391,8 +1392,6 @@ static u32 iwl_mvm_scan_umac_ooc_priority(int type)
{
if (type == IWL_MVM_SCAN_REGULAR)
return IWL_SCAN_PRIORITY_EXT_6;
- if (type == IWL_MVM_SCAN_INT_MLO)
- return IWL_SCAN_PRIORITY_EXT_4;
return IWL_SCAN_PRIORITY_EXT_2;
}
@@ -3219,7 +3218,6 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
struct iwl_umac_scan_complete *notif = (void *)pkt->data;
u32 uid = __le32_to_cpu(notif->uid);
bool aborted = (notif->status == IWL_SCAN_OFFLOAD_ABORTED);
- bool select_links = false;
mvm->mei_scan_filter.is_mei_limited_scan = false;
@@ -3266,13 +3264,6 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
} else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) {
ieee80211_sched_scan_stopped(mvm->hw);
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
- } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_INT_MLO) {
- IWL_DEBUG_SCAN(mvm, "Internal MLO scan completed\n");
- /*
- * Other scan types won't necessarily scan for the MLD links channels.
- * Therefore, only select links after successful internal scan.
- */
- select_links = notif->status == IWL_SCAN_OFFLOAD_COMPLETED;
}
mvm->scan_status &= ~mvm->scan_uid_status[uid];
@@ -3285,9 +3276,6 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
mvm->last_ebs_successful = false;
mvm->scan_uid_status[uid] = 0;
-
- if (select_links)
- wiphy_work_queue(mvm->hw->wiphy, &mvm->trig_link_selection_wk);
}
void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
@@ -3482,11 +3470,6 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
mvm->scan_uid_status[uid] = 0;
}
- uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_INT_MLO);
- if (uid >= 0) {
- IWL_DEBUG_SCAN(mvm, "Internal MLO scan aborted\n");
- mvm->scan_uid_status[uid] = 0;
- }
uid = iwl_mvm_scan_uid_by_status(mvm,
IWL_MVM_SCAN_STOPPING_REGULAR);
@@ -3546,7 +3529,7 @@ int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify)
if (!(mvm->scan_status & type))
return 0;
- if (!test_bit(STATUS_DEVICE_ENABLED, &mvm->trans->status)) {
+ if (!iwl_trans_device_enabled(mvm->trans)) {
ret = 0;
goto out;
}
@@ -3582,89 +3565,6 @@ out:
return ret;
}
-static int iwl_mvm_int_mlo_scan_start(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct ieee80211_channel **channels,
- size_t n_channels)
-{
- struct cfg80211_scan_request *req = NULL;
- struct ieee80211_scan_ies ies = {};
- size_t size, i;
- int ret;
-
- lockdep_assert_held(&mvm->mutex);
-
- IWL_DEBUG_SCAN(mvm, "Starting Internal MLO scan: n_channels=%zu\n",
- n_channels);
-
- if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif) ||
- hweight16(vif->valid_links) == 1)
- return -EINVAL;
-
- size = struct_size(req, channels, n_channels);
- req = kzalloc(size, GFP_KERNEL);
- if (!req)
- return -ENOMEM;
-
- /* set the requested channels */
- for (i = 0; i < n_channels; i++)
- req->channels[i] = channels[i];
-
- req->n_channels = n_channels;
-
- /* set the rates */
- for (i = 0; i < NUM_NL80211_BANDS; i++)
- if (mvm->hw->wiphy->bands[i])
- req->rates[i] =
- (1 << mvm->hw->wiphy->bands[i]->n_bitrates) - 1;
-
- req->wdev = ieee80211_vif_to_wdev(vif);
- req->wiphy = mvm->hw->wiphy;
- req->scan_start = jiffies;
- req->tsf_report_link_id = -1;
-
- ret = _iwl_mvm_single_scan_start(mvm, vif, req, &ies,
- IWL_MVM_SCAN_INT_MLO);
- kfree(req);
-
- IWL_DEBUG_SCAN(mvm, "Internal MLO scan: ret=%d\n", ret);
- return ret;
-}
-
-int iwl_mvm_int_mlo_scan(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
-{
- struct ieee80211_channel *channels[IEEE80211_MLD_MAX_NUM_LINKS];
- unsigned long usable_links = ieee80211_vif_usable_links(vif);
- size_t n_channels = 0;
- u8 link_id;
-
- lockdep_assert_held(&mvm->mutex);
-
- if (mvm->scan_status & IWL_MVM_SCAN_INT_MLO) {
- IWL_DEBUG_SCAN(mvm, "Internal MLO scan is already running\n");
- return -EBUSY;
- }
-
- rcu_read_lock();
-
- for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
- struct ieee80211_bss_conf *link_conf =
- rcu_dereference(vif->link_conf[link_id]);
-
- if (WARN_ON_ONCE(!link_conf))
- continue;
-
- channels[n_channels++] = link_conf->chanreq.oper.chan;
- }
-
- rcu_read_unlock();
-
- if (!n_channels)
- return -EINVAL;
-
- return iwl_mvm_int_mlo_scan_start(mvm, vif, channels, n_channels);
-}
-
static int iwl_mvm_chanidx_from_phy(struct iwl_mvm *mvm,
enum nl80211_band band,
u16 phy_chan_num)
@@ -3685,117 +3585,6 @@ static int iwl_mvm_chanidx_from_phy(struct iwl_mvm *mvm,
return -EINVAL;
}
-static u32 iwl_mvm_div_by_db(u32 value, u8 db)
-{
- /*
- * 2^32 * 10**(i / 10) for i = [1, 10], skipping 0 and simply stopping
- * at 10 dB and looping instead of using a much larger table.
- *
- * Using 64 bit math is overkill, but means the helper does not require
- * a limit on the input range.
- */
- static const u32 db_to_val[] = {
- 0xcb59185e, 0xa1866ba8, 0x804dce7a, 0x65ea59fe, 0x50f44d89,
- 0x404de61f, 0x331426af, 0x2892c18b, 0x203a7e5b, 0x1999999a,
- };
-
- while (value && db > 0) {
- u8 change = min_t(u8, db, ARRAY_SIZE(db_to_val));
-
- value = (((u64)value) * db_to_val[change - 1]) >> 32;
-
- db -= change;
- }
-
- return value;
-}
-
-VISIBLE_IF_IWLWIFI_KUNIT s8
-iwl_mvm_average_dbm_values(const struct iwl_umac_scan_channel_survey_notif *notif)
-{
- s8 average_magnitude;
- u32 average_factor;
- s8 sum_magnitude = -128;
- u32 sum_factor = 0;
- int i, count = 0;
-
- /*
- * To properly average the decibel values (signal values given in dBm)
- * we need to do the math in linear space. Doing a linear average of
- * dB (dBm) values is a bit annoying though due to the large range of
- * at least -10 to -110 dBm that will not fit into a 32 bit integer.
- *
- * A 64 bit integer should be sufficient, but then we still have the
- * problem that there are no directly usable utility functions
- * available.
- *
- * So, lets not deal with that and instead do much of the calculation
- * with a 16.16 fixed point integer along with a base in dBm. 16.16 bit
- * gives us plenty of head-room for adding up a few values and even
- * doing some math on it. And the tail should be accurate enough too
- * (1/2^16 is somewhere around -48 dB, so effectively zero).
- *
- * i.e. the real value of sum is:
- * sum = sum_factor / 2^16 * 10^(sum_magnitude / 10) mW
- *
- * However, that does mean we need to be able to bring two values to
- * a common base, so we need a helper for that.
- *
- * Note that this function takes an input with unsigned negative dBm
- * values but returns a signed dBm (i.e. a negative value).
- */
-
- for (i = 0; i < ARRAY_SIZE(notif->noise); i++) {
- s8 val_magnitude;
- u32 val_factor;
-
- if (notif->noise[i] == 0xff)
- continue;
-
- val_factor = 0x10000;
- val_magnitude = -notif->noise[i];
-
- if (val_magnitude <= sum_magnitude) {
- u8 div_db = sum_magnitude - val_magnitude;
-
- val_factor = iwl_mvm_div_by_db(val_factor, div_db);
- val_magnitude = sum_magnitude;
- } else {
- u8 div_db = val_magnitude - sum_magnitude;
-
- sum_factor = iwl_mvm_div_by_db(sum_factor, div_db);
- sum_magnitude = val_magnitude;
- }
-
- sum_factor += val_factor;
- count++;
- }
-
- /* No valid noise measurement, return a very high noise level */
- if (count == 0)
- return 0;
-
- average_magnitude = sum_magnitude;
- average_factor = sum_factor / count;
-
- /*
- * average_factor will be a number smaller than 1.0 (0x10000) at this
- * point. What we need to do now is to adjust average_magnitude so that
- * average_factor is between -0.5 dB and 0.5 dB.
- *
- * Just do -1 dB steps and find the point where
- * -0.5 dB * -i dB = 0x10000 * 10^(-0.5/10) / i dB
- * = div_by_db(0xe429, i)
- * is smaller than average_factor.
- */
- for (i = 0; average_factor < iwl_mvm_div_by_db(0xe429, i); i++) {
- /* nothing */
- }
-
- return average_magnitude - i;
-}
-EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mvm_average_dbm_values);
-
void iwl_mvm_rx_channel_survey_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb)
{
@@ -3853,5 +3642,6 @@ void iwl_mvm_rx_channel_survey_notif(struct iwl_mvm *mvm,
info->time_busy = le32_to_cpu(notif->busy_time);
info->time_rx = le32_to_cpu(notif->rx_time);
info->time_tx = le32_to_cpu(notif->tx_time);
- info->noise = iwl_mvm_average_dbm_values(notif);
+ info->noise =
+ iwl_average_neg_dbm(notif->noise, ARRAY_SIZE(notif->noise));
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 78fd7faaed97..363232bb74fa 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2015, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2015, 2018-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -253,7 +253,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
static void iwl_mvm_rx_agg_session_expired(struct timer_list *t)
{
struct iwl_mvm_baid_data *data =
- from_timer(data, t, session_timer);
+ timer_container_of(data, t, session_timer);
struct iwl_mvm_baid_data __rcu **rcu_ptr = data->rcu_ptr;
struct iwl_mvm_baid_data *ba_data;
struct ieee80211_sta *sta;
@@ -791,10 +791,10 @@ static int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id,
lockdep_assert_held(&mvm->mutex);
- if (WARN(maxq >= mvm->trans->trans_cfg->base_params->num_of_queues,
+ if (WARN(maxq >= mvm->trans->mac_cfg->base->num_of_queues,
"max queue %d >= num_of_queues (%d)", maxq,
- mvm->trans->trans_cfg->base_params->num_of_queues))
- maxq = mvm->trans->trans_cfg->base_params->num_of_queues - 1;
+ mvm->trans->mac_cfg->base->num_of_queues))
+ maxq = mvm->trans->mac_cfg->base->num_of_queues - 1;
/* This should not be hit with new TX path */
if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
@@ -852,7 +852,7 @@ int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm,
if (tid == IWL_MAX_TID_COUNT) {
tid = IWL_MGMT_TID;
size = max_t(u32, IWL_MGMT_QUEUE_SIZE,
- mvm->trans->cfg->min_txq_size);
+ mvm->trans->mac_cfg->base->min_txq_size);
} else {
size = iwl_mvm_get_queue_size(sta);
}
@@ -1765,7 +1765,7 @@ int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvm_sta->deflink.sta_id = sta_id;
rcu_assign_pointer(mvm_sta->link[0], &mvm_sta->deflink);
- if (!mvm->trans->trans_cfg->gen2)
+ if (!mvm->trans->mac_cfg->gen2)
mvm_sta->deflink.lq_sta.rs_drv.pers.max_agg_bufsize =
LINK_QUAL_AGG_FRAME_LIMIT_DEF;
else
@@ -1798,7 +1798,7 @@ int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (iwl_mvm_has_new_rx_api(mvm)) {
int q;
- dup_data = kcalloc(mvm->trans->num_rx_queues,
+ dup_data = kcalloc(mvm->trans->info.num_rxqs,
sizeof(*dup_data), GFP_KERNEL);
if (!dup_data)
return -ENOMEM;
@@ -1811,7 +1811,7 @@ int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* This thus allows receiving a packet with seqno 0 and the
* retry bit set as the very first packet on a new TID.
*/
- for (q = 0; q < mvm->trans->num_rx_queues; q++)
+ for (q = 0; q < mvm->trans->info.num_rxqs; q++)
memset(dup_data[q].last_seq, 0xff,
sizeof(dup_data[q].last_seq));
mvm_sta->dup_data = dup_data;
@@ -1835,18 +1835,6 @@ int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_toggle_tx_ant(mvm, &mvm_sta->tx_ant);
- /* MPDUs are counted only when EMLSR is possible */
- if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
- !sta->tdls && ieee80211_vif_is_mld(vif)) {
- mvm_sta->mpdu_counters =
- kcalloc(mvm->trans->num_rx_queues,
- sizeof(*mvm_sta->mpdu_counters),
- GFP_KERNEL);
- if (mvm_sta->mpdu_counters)
- for (int q = 0; q < mvm->trans->num_rx_queues; q++)
- spin_lock_init(&mvm_sta->mpdu_counters[q].lock);
- }
-
return 0;
}
@@ -2189,7 +2177,7 @@ static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 queue,
u8 sta_id, u8 fifo)
{
unsigned int wdg_timeout =
- mvm->trans->trans_cfg->base_params->wd_timeout;
+ mvm->trans->mac_cfg->base->wd_timeout;
struct iwl_trans_txq_scd_cfg cfg = {
.fifo = fifo,
.sta_id = sta_id,
@@ -2206,7 +2194,7 @@ static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 queue,
static int iwl_mvm_enable_aux_snif_queue_tvqm(struct iwl_mvm *mvm, u8 sta_id)
{
unsigned int wdg_timeout =
- mvm->trans->trans_cfg->base_params->wd_timeout;
+ mvm->trans->mac_cfg->base->wd_timeout;
WARN_ON(!iwl_mvm_has_new_tx_api(mvm));
@@ -2461,7 +2449,7 @@ void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm,
mvmvif->deflink.bcast_sta.tfd_queue_msk &= ~BIT(queue);
}
-/* Send the FW a request to remove the station from it's internal data
+/* Send the FW a request to remove the station from its internal data
* structures, but DO NOT remove the entry from the local data structures. */
int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
@@ -2524,7 +2512,7 @@ void iwl_mvm_dealloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
}
/*
- * Send the FW a request to remove the station from it's internal data
+ * Send the FW a request to remove the station from its internal data
* structures, and in addition remove it from the local data structure.
*/
int iwl_mvm_rm_p2p_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
@@ -2677,7 +2665,7 @@ static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
}
/*
- * Send the FW a request to remove the station from it's internal data
+ * Send the FW a request to remove the station from its internal data
* structures, and in addition remove it from the local data structure.
*/
int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
@@ -2717,7 +2705,7 @@ static void iwl_mvm_free_reorder(struct iwl_mvm *mvm,
iwl_mvm_sync_rxq_del_ba(mvm, data->baid);
- for (i = 0; i < mvm->trans->num_rx_queues; i++) {
+ for (i = 0; i < mvm->trans->info.num_rxqs; i++) {
int j;
struct iwl_mvm_reorder_buffer *reorder_buf =
&data->reorder_buf[i];
@@ -2750,7 +2738,7 @@ static void iwl_mvm_init_reorder_buffer(struct iwl_mvm *mvm,
{
int i;
- for (i = 0; i < mvm->trans->num_rx_queues; i++) {
+ for (i = 0; i < mvm->trans->info.num_rxqs; i++) {
struct iwl_mvm_reorder_buffer *reorder_buf =
&data->reorder_buf[i];
struct iwl_mvm_reorder_buf_entry *entries =
@@ -2925,7 +2913,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
* before starting the BA session in the firmware
*/
baid_data = kzalloc(sizeof(*baid_data) +
- mvm->trans->num_rx_queues *
+ mvm->trans->info.num_rxqs *
reorder_buf_size,
GFP_KERNEL);
if (!baid_data)
@@ -3177,7 +3165,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* to align the wrap around of ssn so we compare relevant values.
*/
normalized_ssn = tid_data->ssn;
- if (mvm->trans->trans_cfg->gen2)
+ if (mvm->trans->mac_cfg->gen2)
normalized_ssn &= 0xff;
if (normalized_ssn == tid_data->next_reclaimed) {
@@ -4305,7 +4293,7 @@ u16 iwl_mvm_tid_queued(struct iwl_mvm *mvm, struct iwl_mvm_tid_data *tid_data)
* In 22000 HW, the next_reclaimed index is only 8 bit, so we'll need
* to align the wrap around of ssn so we compare relevant values.
*/
- if (mvm->trans->trans_cfg->gen2)
+ if (mvm->trans->mac_cfg->gen2)
sn &= 0xff;
return ieee80211_sn_sub(sn, tid_data->next_reclaimed);
@@ -4328,80 +4316,3 @@ void iwl_mvm_cancel_channel_switch(struct iwl_mvm *mvm,
if (ret)
IWL_ERR(mvm, "Failed to cancel the channel switch\n");
}
-
-static int iwl_mvm_fw_sta_id_to_fw_link_id(struct iwl_mvm_vif *mvmvif,
- u8 fw_sta_id)
-{
- struct ieee80211_link_sta *link_sta =
- rcu_dereference(mvmvif->mvm->fw_id_to_link_sta[fw_sta_id]);
- struct iwl_mvm_vif_link_info *link;
-
- if (WARN_ON_ONCE(!link_sta))
- return -EINVAL;
-
- link = mvmvif->link[link_sta->link_id];
-
- if (WARN_ON_ONCE(!link))
- return -EINVAL;
-
- return link->fw_link_id;
-}
-
-#define IWL_MVM_TPT_COUNT_WINDOW (IWL_MVM_TPT_COUNT_WINDOW_SEC * HZ)
-
-void iwl_mvm_count_mpdu(struct iwl_mvm_sta *mvm_sta, u8 fw_sta_id, u32 count,
- bool tx, int queue)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvm_sta->vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
- struct iwl_mvm_tpt_counter *queue_counter;
- struct iwl_mvm_mpdu_counter *link_counter;
- u32 total_mpdus = 0;
- int fw_link_id;
-
- /* Count only for a BSS sta, and only when EMLSR is possible */
- if (!mvm_sta->mpdu_counters)
- return;
-
- /* Map sta id to link id */
- fw_link_id = iwl_mvm_fw_sta_id_to_fw_link_id(mvmvif, fw_sta_id);
- if (fw_link_id < 0)
- return;
-
- queue_counter = &mvm_sta->mpdu_counters[queue];
- link_counter = &queue_counter->per_link[fw_link_id];
-
- spin_lock_bh(&queue_counter->lock);
-
- if (tx)
- link_counter->tx += count;
- else
- link_counter->rx += count;
-
- /*
- * When not in EMLSR, the window and the decision to enter EMLSR are
- * handled during counting, when in EMLSR - in the statistics flow
- */
- if (mvmvif->esr_active)
- goto out;
-
- if (time_is_before_jiffies(queue_counter->window_start +
- IWL_MVM_TPT_COUNT_WINDOW)) {
- memset(queue_counter->per_link, 0,
- sizeof(queue_counter->per_link));
- queue_counter->window_start = jiffies;
-
- IWL_DEBUG_INFO(mvm, "MPDU counters are cleared\n");
- }
-
- for (int i = 0; i < IWL_FW_MAX_LINK_ID; i++)
- total_mpdus += tx ? queue_counter->per_link[i].tx :
- queue_counter->per_link[i].rx;
-
- if (total_mpdus > IWL_MVM_ENTER_ESR_TPT_THRESH)
- wiphy_work_queue(mvmvif->mvm->hw->wiphy,
- &mvmvif->unblock_esr_tpt_wk);
-
-out:
- spin_unlock_bh(&queue_counter->lock);
-}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index 19c905b641e2..c25edc7c1813 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2016 Intel Deutschland GmbH
*/
@@ -214,7 +214,7 @@ struct iwl_mvm_vif;
*/
/**
- * enum iwl_mvm_agg_state
+ * enum iwl_mvm_agg_state - aggregation session state
*
* The state machine of the BA agreement establishment / tear down.
* These states relate to a specific RA / TID.
@@ -225,8 +225,6 @@ struct iwl_mvm_vif;
* @IWL_AGG_ON: aggregation session is up
* @IWL_EMPTYING_HW_QUEUE_ADDBA: establishing a BA session - waiting for the
* HW queue to be empty from packets for this RA /TID.
- * @IWL_EMPTYING_HW_QUEUE_DELBA: tearing down a BA session - waiting for the
- * HW queue to be empty from packets for this RA /TID.
*/
enum iwl_mvm_agg_state {
IWL_AGG_OFF = 0,
@@ -234,7 +232,6 @@ enum iwl_mvm_agg_state {
IWL_AGG_STARTING,
IWL_AGG_ON,
IWL_EMPTYING_HW_QUEUE_ADDBA,
- IWL_EMPTYING_HW_QUEUE_DELBA,
};
/**
@@ -262,7 +259,7 @@ struct iwl_mvm_tid_data {
u16 seq_number;
u16 next_reclaimed;
/* The rest is Tx AGG related */
- u32 rate_n_flags;
+ __le32 rate_n_flags;
u8 lq_color;
bool amsdu_in_ampdu_allowed;
enum iwl_mvm_agg_state state;
@@ -347,24 +344,6 @@ struct iwl_mvm_link_sta {
u8 avg_energy;
};
-struct iwl_mvm_mpdu_counter {
- u32 tx;
- u32 rx;
-};
-
-/**
- * struct iwl_mvm_tpt_counter - per-queue MPDU counter
- *
- * @lock: Needed to protect the counters when modified from statistics.
- * @per_link: per-link counters.
- * @window_start: timestamp of the counting-window start
- */
-struct iwl_mvm_tpt_counter {
- spinlock_t lock;
- struct iwl_mvm_mpdu_counter per_link[IWL_FW_MAX_LINK_ID];
- unsigned long window_start;
-} ____cacheline_aligned_in_smp;
-
/**
* struct iwl_mvm_sta - representation of a station in the driver
* @vif: the interface the station belongs to
@@ -412,7 +391,6 @@ struct iwl_mvm_tpt_counter {
* @link: per link sta entries. For non-MLO only link[0] holds data. For MLO,
* link[0] points to deflink and link[link_id] is allocated when new link
* sta is added.
- * @mpdu_counters: RX/TX MPDUs counters for each queue.
*
* When mac80211 creates a station it reserves some space (hw->sta_data_size)
* in the structure for use by driver. This structure is placed in that
@@ -452,8 +430,6 @@ struct iwl_mvm_sta {
struct iwl_mvm_link_sta deflink;
struct iwl_mvm_link_sta __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
-
- struct iwl_mvm_tpt_counter *mpdu_counters;
};
u16 iwl_mvm_tid_queued(struct iwl_mvm *mvm, struct iwl_mvm_tid_data *tid_data);
@@ -486,6 +462,7 @@ struct iwl_mvm_int_sta {
* about. Otherwise (if this is a new STA), this should be false.
* @flags: if update==true, this marks what is being changed via ORs of values
* from enum iwl_sta_modify_flag. Otherwise, this is ignored.
+ * Return: negative error code or 0 on success
*/
int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
bool update, unsigned int flags);
@@ -535,9 +512,6 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
void iwl_mvm_rx_eosp_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
-void iwl_mvm_count_mpdu(struct iwl_mvm_sta *mvm_sta, u8 fw_sta_id, u32 count,
- bool tx, int queue);
-
/* AMPDU */
int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
int tid, u16 ssn, bool start, u16 buf_size, u16 timeout);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tests/Makefile b/drivers/net/wireless/intel/iwlwifi/mvm/tests/Makefile
index 6bd56a28cffd..2267be4cfb44 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tests/Makefile
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tests/Makefile
@@ -1,3 +1,3 @@
-iwlmvm-tests-y += module.o links.o scan.o
+iwlmvm-tests-y += module.o hcmd.o
obj-$(CONFIG_IWLWIFI_KUNIT_TESTS) += iwlmvm-tests.o
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tests/hcmd.c b/drivers/net/wireless/intel/iwlwifi/mvm/tests/hcmd.c
new file mode 100644
index 000000000000..1fee0320c756
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tests/hcmd.c
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * KUnit tests for channel helper functions
+ *
+ * Copyright (C) 2025 Intel Corporation
+ */
+#include <kunit/test.h>
+
+#include <iwl-trans.h>
+#include "../mvm.h"
+
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
+
+static void test_hcmd_names_sorted(struct kunit *test)
+{
+ for (int i = 0; i < iwl_mvm_groups_size; i++) {
+ const struct iwl_hcmd_arr *arr = &iwl_mvm_groups[i];
+
+ if (!arr->arr)
+ continue;
+
+ for (int j = 0; j < arr->size - 1; j++)
+ KUNIT_EXPECT_LE(test, arr->arr[j].cmd_id,
+ arr->arr[j + 1].cmd_id);
+ }
+}
+
+static struct kunit_case hcmd_names_cases[] = {
+ KUNIT_CASE(test_hcmd_names_sorted),
+ {},
+};
+
+static struct kunit_suite hcmd_names = {
+ .name = "iwlmvm-hcmd-names",
+ .test_cases = hcmd_names_cases,
+};
+
+kunit_test_suite(hcmd_names);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tests/links.c b/drivers/net/wireless/intel/iwlwifi/mvm/tests/links.c
deleted file mode 100644
index d692f1813d44..000000000000
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tests/links.c
+++ /dev/null
@@ -1,433 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * KUnit tests for channel helper functions
- *
- * Copyright (C) 2024 Intel Corporation
- */
-#include <net/mac80211.h>
-#include "../mvm.h"
-#include <kunit/test.h>
-
-MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
-
-static struct wiphy wiphy = {
- .mtx = __MUTEX_INITIALIZER(wiphy.mtx),
-};
-
-static struct ieee80211_hw hw = {
- .wiphy = &wiphy,
-};
-
-static struct ieee80211_channel chan_5ghz = {
- .band = NL80211_BAND_5GHZ,
-};
-
-static struct ieee80211_channel chan_6ghz = {
- .band = NL80211_BAND_6GHZ,
-};
-
-static struct ieee80211_channel chan_2ghz = {
- .band = NL80211_BAND_2GHZ,
-};
-
-static struct cfg80211_chan_def chandef_a = {};
-
-static struct cfg80211_chan_def chandef_b = {};
-
-static struct iwl_mvm_phy_ctxt ctx = {};
-
-static struct iwl_mvm_vif_link_info mvm_link = {
- .phy_ctxt = &ctx,
- .active = true
-};
-
-static struct cfg80211_bss bss = {};
-
-static struct ieee80211_bss_conf link_conf = {.bss = &bss};
-
-static const struct iwl_fw_cmd_version entry = {
- .group = LEGACY_GROUP,
- .cmd = BT_PROFILE_NOTIFICATION,
- .notif_ver = 4
-};
-
-static struct iwl_fw fw = {
- .ucode_capa = {
- .n_cmd_versions = 1,
- .cmd_versions = &entry,
- },
-};
-
-static struct iwl_mvm mvm = {
- .hw = &hw,
- .fw = &fw,
-};
-
-static const struct link_grading_case {
- const char *desc;
- const struct cfg80211_chan_def chandef;
- s32 signal;
- s16 channel_util;
- int chan_load_by_us;
- unsigned int grade;
-} link_grading_cases[] = {
- {
- .desc = "UHB, RSSI below range, no factors",
- .chandef = {
- .chan = &chan_6ghz,
- .width = NL80211_CHAN_WIDTH_20,
- },
- .signal = -100,
- .grade = 177,
- },
- {
- .desc = "LB, RSSI in range, no factors",
- .chandef = {
- .chan = &chan_2ghz,
- .width = NL80211_CHAN_WIDTH_20,
- },
- .signal = -84,
- .grade = 344,
- },
- {
- .desc = "HB, RSSI above range, no factors",
- .chandef = {
- .chan = &chan_5ghz,
- .width = NL80211_CHAN_WIDTH_20,
- },
- .signal = -50,
- .grade = 3442,
- },
- {
- .desc = "HB, BSS Load IE (20 percent), inactive link, no puncturing factor",
- .chandef = {
- .chan = &chan_5ghz,
- .width = NL80211_CHAN_WIDTH_20,
- },
- .signal = -66,
- .channel_util = 51,
- .grade = 1836,
- },
- {
- .desc = "LB, BSS Load IE (20 percent), active link, chan_load_by_us=10 percent. No puncturing factor",
- .chandef = {
- .chan = &chan_2ghz,
- .width = NL80211_CHAN_WIDTH_20,
- },
- .signal = -61,
- .channel_util = 51,
- .chan_load_by_us = 10,
- .grade = 2061,
- },
- {
- .desc = "UHB, BSS Load IE (40 percent), active link, chan_load_by_us=50 (invalid) percent. No puncturing factor",
- .chandef = {
- .chan = &chan_6ghz,
- .width = NL80211_CHAN_WIDTH_20,
- },
- .signal = -66,
- .channel_util = 102,
- .chan_load_by_us = 50,
- .grade = 1552,
- },
- { .desc = "HB, 80 MHz, no channel load factor, punctured percentage 0",
- .chandef = {
- .chan = &chan_5ghz,
- .width = NL80211_CHAN_WIDTH_80,
- .punctured = 0x0000
- },
- .signal = -72,
- .grade = 1750,
- },
- { .desc = "HB, 160 MHz, no channel load factor, punctured percentage 25",
- .chandef = {
- .chan = &chan_5ghz,
- .width = NL80211_CHAN_WIDTH_160,
- .punctured = 0x3
- },
- .signal = -72,
- .grade = 1312,
- },
- { .desc = "UHB, 320 MHz, no channel load factor, punctured percentage 12.5 (2/16)",
- .chandef = {
- .chan = &chan_6ghz,
- .width = NL80211_CHAN_WIDTH_320,
- .punctured = 0x3
- },
- .signal = -72,
- .grade = 1806,
- },
- { .desc = "HB, 160 MHz, channel load 20, channel load by us 10, punctured percentage 25",
- .chandef = {
- .chan = &chan_5ghz,
- .width = NL80211_CHAN_WIDTH_160,
- .punctured = 0x3
- },
- .channel_util = 51,
- .chan_load_by_us = 10,
- .signal = -72,
- .grade = 1179,
- },
-};
-
-KUNIT_ARRAY_PARAM_DESC(link_grading, link_grading_cases, desc)
-
-static void setup_link_conf(struct kunit *test)
-{
- const struct link_grading_case *params = test->param_value;
- size_t vif_size = sizeof(struct ieee80211_vif) +
- sizeof(struct iwl_mvm_vif);
- struct ieee80211_vif *vif = kunit_kzalloc(test, vif_size, GFP_KERNEL);
- struct ieee80211_bss_load_elem *bss_load;
- struct element *element;
- size_t ies_size = sizeof(struct cfg80211_bss_ies) + sizeof(*bss_load) + sizeof(element);
- struct cfg80211_bss_ies *ies;
- struct iwl_mvm_vif *mvmvif;
-
- KUNIT_ASSERT_NOT_NULL(test, vif);
-
- mvmvif = iwl_mvm_vif_from_mac80211(vif);
- if (params->chan_load_by_us > 0) {
- ctx.channel_load_by_us = params->chan_load_by_us;
- mvmvif->link[0] = &mvm_link;
- }
-
- link_conf.vif = vif;
- link_conf.chanreq.oper = params->chandef;
- bss.signal = DBM_TO_MBM(params->signal);
-
- ies = kunit_kzalloc(test, ies_size, GFP_KERNEL);
- KUNIT_ASSERT_NOT_NULL(test, ies);
- ies->len = sizeof(*bss_load) + sizeof(struct element);
-
- element = (void *)ies->data;
- element->datalen = sizeof(*bss_load);
- element->id = 11;
-
- bss_load = (void *)element->data;
- bss_load->channel_util = params->channel_util;
-
- rcu_assign_pointer(bss.ies, ies);
- rcu_assign_pointer(bss.beacon_ies, ies);
-}
-
-static void test_link_grading(struct kunit *test)
-{
- const struct link_grading_case *params = test->param_value;
- unsigned int ret;
-
- setup_link_conf(test);
-
- rcu_read_lock();
- ret = iwl_mvm_get_link_grade(&link_conf);
- rcu_read_unlock();
-
- KUNIT_EXPECT_EQ(test, ret, params->grade);
-
- kunit_kfree(test, link_conf.vif);
- RCU_INIT_POINTER(bss.ies, NULL);
-}
-
-static struct kunit_case link_grading_test_cases[] = {
- KUNIT_CASE_PARAM(test_link_grading, link_grading_gen_params),
- {}
-};
-
-static struct kunit_suite link_grading = {
- .name = "iwlmvm-link-grading",
- .test_cases = link_grading_test_cases,
-};
-
-kunit_test_suite(link_grading);
-
-static const struct valid_link_pair_case {
- const char *desc;
- bool bt;
- struct ieee80211_channel *chan_a;
- struct ieee80211_channel *chan_b;
- enum nl80211_chan_width cw_a;
- enum nl80211_chan_width cw_b;
- s32 sig_a;
- s32 sig_b;
- bool csa_a;
- bool valid;
-} valid_link_pair_cases[] = {
- {
- .desc = "HB + UHB, valid.",
- .chan_a = &chan_6ghz,
- .chan_b = &chan_5ghz,
- .valid = true,
- },
- {
- .desc = "LB + HB, no BT.",
- .chan_a = &chan_2ghz,
- .chan_b = &chan_5ghz,
- .valid = true,
- },
- {
- .desc = "LB + HB, with BT.",
- .bt = true,
- .chan_a = &chan_2ghz,
- .chan_b = &chan_5ghz,
- .valid = false,
- },
- {
- .desc = "Same band",
- .chan_a = &chan_2ghz,
- .chan_b = &chan_2ghz,
- .valid = false,
- },
- {
- .desc = "RSSI: LB, 20 MHz, low",
- .chan_a = &chan_2ghz,
- .cw_a = NL80211_CHAN_WIDTH_20,
- .sig_a = -68,
- .chan_b = &chan_5ghz,
- .valid = false,
- },
- {
- .desc = "RSSI: UHB, 20 MHz, high",
- .chan_a = &chan_6ghz,
- .cw_a = NL80211_CHAN_WIDTH_20,
- .sig_a = -66,
- .chan_b = &chan_5ghz,
- .cw_b = NL80211_CHAN_WIDTH_20,
- .valid = true,
- },
- {
- .desc = "RSSI: UHB, 40 MHz, low",
- .chan_a = &chan_6ghz,
- .cw_a = NL80211_CHAN_WIDTH_40,
- .sig_a = -65,
- .chan_b = &chan_5ghz,
- .cw_b = NL80211_CHAN_WIDTH_40,
- .valid = false,
- },
- {
- .desc = "RSSI: UHB, 40 MHz, high",
- .chan_a = &chan_6ghz,
- .cw_a = NL80211_CHAN_WIDTH_40,
- .sig_a = -63,
- .chan_b = &chan_5ghz,
- .cw_b = NL80211_CHAN_WIDTH_40,
- .valid = true,
- },
- {
- .desc = "RSSI: UHB, 80 MHz, low",
- .chan_a = &chan_6ghz,
- .cw_a = NL80211_CHAN_WIDTH_80,
- .sig_a = -62,
- .chan_b = &chan_5ghz,
- .cw_b = NL80211_CHAN_WIDTH_80,
- .valid = false,
- },
- {
- .desc = "RSSI: UHB, 80 MHz, high",
- .chan_a = &chan_6ghz,
- .cw_a = NL80211_CHAN_WIDTH_80,
- .sig_a = -60,
- .chan_b = &chan_5ghz,
- .cw_b = NL80211_CHAN_WIDTH_80,
- .valid = true,
- },
- {
- .desc = "RSSI: UHB, 160 MHz, low",
- .chan_a = &chan_6ghz,
- .cw_a = NL80211_CHAN_WIDTH_160,
- .sig_a = -59,
- .chan_b = &chan_5ghz,
- .cw_b = NL80211_CHAN_WIDTH_160,
- .valid = false,
- },
- {
- .desc = "RSSI: HB, 160 MHz, high",
- .chan_a = &chan_6ghz,
- .cw_a = NL80211_CHAN_WIDTH_160,
- .sig_a = -5,
- .chan_b = &chan_5ghz,
- .cw_b = NL80211_CHAN_WIDTH_160,
- .valid = true,
- },
- {
- .desc = "CSA active",
- .chan_a = &chan_6ghz,
- .cw_a = NL80211_CHAN_WIDTH_160,
- .sig_a = -5,
- .chan_b = &chan_5ghz,
- .cw_b = NL80211_CHAN_WIDTH_160,
- .valid = false,
- /* same as previous entry with valid=true except for CSA */
- .csa_a = true,
- },
-};
-
-KUNIT_ARRAY_PARAM_DESC(valid_link_pair, valid_link_pair_cases, desc)
-
-static void test_valid_link_pair(struct kunit *test)
-{
- const struct valid_link_pair_case *params = test->param_value;
- size_t vif_size = sizeof(struct ieee80211_vif) +
- sizeof(struct iwl_mvm_vif);
- struct ieee80211_vif *vif = kunit_kzalloc(test, vif_size, GFP_KERNEL);
- struct iwl_trans *trans = kunit_kzalloc(test, sizeof(struct iwl_trans),
- GFP_KERNEL);
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm_link_sel_data link_a = {
- .chandef = &chandef_a,
- .link_id = 1,
- .signal = params->sig_a,
- };
- struct iwl_mvm_link_sel_data link_b = {
- .chandef = &chandef_b,
- .link_id = 5,
- .signal = params->sig_b,
- };
- struct ieee80211_bss_conf *conf;
- bool result;
-
- KUNIT_ASSERT_NOT_NULL(test, vif);
- KUNIT_ASSERT_NOT_NULL(test, trans);
-
- chandef_a.chan = params->chan_a;
- chandef_b.chan = params->chan_b;
-
- chandef_a.width = params->cw_a ?: NL80211_CHAN_WIDTH_20;
- chandef_b.width = params->cw_b ?: NL80211_CHAN_WIDTH_20;
-
- mvm.trans = trans;
-
- mvm.last_bt_notif.wifi_loss_low_rssi = params->bt;
- mvmvif->mvm = &mvm;
-
- conf = kunit_kzalloc(test, sizeof(*vif->link_conf[0]), GFP_KERNEL);
- KUNIT_ASSERT_NOT_NULL(test, conf);
- conf->chanreq.oper = chandef_a;
- conf->csa_active = params->csa_a;
- vif->link_conf[link_a.link_id] = (void __rcu *)conf;
-
- conf = kunit_kzalloc(test, sizeof(*vif->link_conf[0]), GFP_KERNEL);
- KUNIT_ASSERT_NOT_NULL(test, conf);
- conf->chanreq.oper = chandef_b;
- vif->link_conf[link_b.link_id] = (void __rcu *)conf;
-
- wiphy_lock(&wiphy);
- result = iwl_mvm_mld_valid_link_pair(vif, &link_a, &link_b);
- wiphy_unlock(&wiphy);
-
- KUNIT_EXPECT_EQ(test, result, params->valid);
-
- kunit_kfree(test, vif);
- kunit_kfree(test, trans);
-}
-
-static struct kunit_case valid_link_pair_test_cases[] = {
- KUNIT_CASE_PARAM(test_valid_link_pair, valid_link_pair_gen_params),
- {},
-};
-
-static struct kunit_suite valid_link_pair = {
- .name = "iwlmvm-valid-link-pair",
- .test_cases = valid_link_pair_test_cases,
-};
-
-kunit_test_suite(valid_link_pair);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
index 1a30bb1ff8ca..0b12ee8ad618 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
@@ -47,7 +47,6 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
static void iwl_mvm_cleanup_roc(struct iwl_mvm *mvm)
{
- struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm);
struct ieee80211_vif *vif = mvm->p2p_device_vif;
lockdep_assert_held(&mvm->mutex);
@@ -125,8 +124,6 @@ static void iwl_mvm_cleanup_roc(struct iwl_mvm *mvm)
iwl_mvm_rm_aux_sta(mvm);
}
- if (!IS_ERR_OR_NULL(bss_vif))
- iwl_mvm_unblock_esr(mvm, bss_vif, IWL_MVM_ESR_BLOCKED_ROC);
mutex_unlock(&mvm->mutex);
}
@@ -466,7 +463,7 @@ static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
if (!aux_roc_te) /* Not a Aux ROC time event */
return -EINVAL;
- iwl_mvm_te_check_trigger(mvm, notif, te_data);
+ iwl_mvm_te_check_trigger(mvm, notif, aux_roc_te);
IWL_DEBUG_TE(mvm,
"Aux ROC time event notification - UID = 0x%x action %d (error = %d)\n",
@@ -478,14 +475,14 @@ static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
/* End TE, notify mac80211 */
ieee80211_remain_on_channel_expired(mvm->hw);
iwl_mvm_roc_finished(mvm); /* flush aux queue */
- list_del(&te_data->list); /* remove from list */
- te_data->running = false;
- te_data->vif = NULL;
- te_data->uid = 0;
- te_data->id = TE_MAX;
+ list_del(&aux_roc_te->list); /* remove from list */
+ aux_roc_te->running = false;
+ aux_roc_te->vif = NULL;
+ aux_roc_te->uid = 0;
+ aux_roc_te->id = TE_MAX;
} else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) {
set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
- te_data->running = true;
+ aux_roc_te->running = true;
ieee80211_ready_on_channel(mvm->hw); /* Start TE */
} else {
IWL_DEBUG_TE(mvm,
@@ -771,15 +768,17 @@ static void iwl_mvm_cancel_session_protection(struct iwl_mvm *mvm,
static void iwl_mvm_roc_rm_cmd(struct iwl_mvm *mvm, u32 activity)
{
- struct iwl_roc_req_v5 roc_cmd = {
+ struct iwl_roc_req roc_cmd = {
.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
.activity = cpu_to_le32(activity),
};
+ u8 ver = iwl_fw_lookup_cmd_ver(mvm->fw, WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 0);
+ u16 cmd_len = ver < 6 ? sizeof(struct iwl_roc_req_v5) : sizeof(roc_cmd);
int ret;
lockdep_assert_held(&mvm->mutex);
ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 0,
- sizeof(roc_cmd), &roc_cmd);
+ cmd_len, &roc_cmd);
if (ret)
IWL_ERR(mvm, "Couldn't send the ROC_CMD: %d\n", ret);
}
@@ -956,40 +955,19 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_session_prot_notif *notif = (void *)pkt->data;
- unsigned int ver =
- iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP,
- SESSION_PROTECTION_NOTIF, 2);
int id = le32_to_cpu(notif->mac_link_id);
struct ieee80211_vif *vif;
struct iwl_mvm_vif *mvmvif;
- unsigned int notif_link_id;
rcu_read_lock();
- if (ver <= 2) {
- vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
- } else {
- struct ieee80211_bss_conf *link_conf =
- iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, true);
-
- if (!link_conf)
- goto out_unlock;
-
- notif_link_id = link_conf->link_id;
- vif = link_conf->vif;
- }
-
+ /* note we use link ID == MAC ID */
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
if (!vif)
goto out_unlock;
mvmvif = iwl_mvm_vif_from_mac80211(vif);
- if (WARN(ver > 2 && mvmvif->time_event_data.link_id >= 0 &&
- mvmvif->time_event_data.link_id != notif_link_id,
- "SESSION_PROTECTION_NOTIF was received for link %u, while the current time event is on link %u\n",
- notif_link_id, mvmvif->time_event_data.link_id))
- goto out_unlock;
-
/* The vif is not a P2P_DEVICE, maintain its time_event_data */
if (vif->type != NL80211_IFTYPE_P2P_DEVICE) {
struct iwl_mvm_time_event_data *te_data =
@@ -1102,11 +1080,13 @@ int iwl_mvm_roc_add_cmd(struct iwl_mvm *mvm,
{
int res;
u32 duration_tu, delay;
- struct iwl_roc_req_v5 roc_req = {
+ struct iwl_roc_req roc_req = {
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
.activity = cpu_to_le32(activity),
.sta_id = cpu_to_le32(mvm->aux_sta.sta_id),
};
+ u8 ver = iwl_fw_lookup_cmd_ver(mvm->fw, WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 0);
+ u16 cmd_len = ver < 6 ? sizeof(struct iwl_roc_req_v5) : sizeof(roc_req);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
lockdep_assert_held(&mvm->mutex);
@@ -1136,7 +1116,7 @@ int iwl_mvm_roc_add_cmd(struct iwl_mvm *mvm,
memcpy(roc_req.node_addr, vif->addr, ETH_ALEN);
res = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(MAC_CONF_GROUP, ROC_CMD),
- 0, sizeof(roc_req), &roc_req);
+ 0, cmd_len, &roc_req);
if (!res)
mvmvif->roc_activity = activity;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.h b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.h
index 49256ba4cf58..1ef8768756db 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2019-2020, 2023 Intel Corporation
+ * Copyright (C) 2012-2014, 2019-2020, 2023, 2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
*/
#ifndef __time_event_h__
@@ -124,6 +124,8 @@ void iwl_mvm_rx_roc_notif(struct iwl_mvm *mvm,
* ROC request, it will issue a notification to the driver that it is on the
* requested channel. Once the FW completes the ROC request it will issue
* another notification to the driver.
+ *
+ * Return: negative error code or 0 on success
*/
int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
int duration, enum ieee80211_roc_type type);
@@ -179,6 +181,8 @@ void iwl_mvm_remove_csa_period(struct iwl_mvm *mvm,
*
* This function is used to schedule NoA time event and is used to perform
* the channel switch flow.
+ *
+ * Return: negative error code or 0 on success
*/
int iwl_mvm_schedule_csa_period(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
@@ -188,7 +192,7 @@ int iwl_mvm_schedule_csa_period(struct iwl_mvm *mvm,
* iwl_mvm_te_scheduled - check if the fw received the TE cmd
* @te_data: the time event data that corresponds to that time event
*
- * This function returns true iff this TE is added to the fw.
+ * Return: %true if this TE is added to the fw, %false otherwise
*/
static inline bool
iwl_mvm_te_scheduled(struct iwl_mvm_time_event_data *te_data)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
index c851290e75a2..53bab21ebae2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2019-2022, 2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2019-2022, 2024-2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2016 Intel Deutschland GmbH
*/
@@ -8,6 +8,9 @@
#include "mvm.h"
+#define IWL_MVM_NUM_CTDP_STEPS 20
+#define IWL_MVM_MIN_CTDP_BUDGET_MW 150
+
#define IWL_MVM_TEMP_NOTIF_WAIT_TIMEOUT HZ
void iwl_mvm_enter_ctkill(struct iwl_mvm *mvm)
@@ -479,43 +482,28 @@ static const struct iwl_tt_params iwl_mvm_default_tt_params = {
.support_tx_backoff = true,
};
-/* budget in mWatt */
-static const u32 iwl_mvm_cdev_budgets[] = {
- 2400, /* cooling state 0 */
- 2000, /* cooling state 1 */
- 1800, /* cooling state 2 */
- 1600, /* cooling state 3 */
- 1400, /* cooling state 4 */
- 1200, /* cooling state 5 */
- 1000, /* cooling state 6 */
- 900, /* cooling state 7 */
- 800, /* cooling state 8 */
- 700, /* cooling state 9 */
- 650, /* cooling state 10 */
- 600, /* cooling state 11 */
- 550, /* cooling state 12 */
- 500, /* cooling state 13 */
- 450, /* cooling state 14 */
- 400, /* cooling state 15 */
- 350, /* cooling state 16 */
- 300, /* cooling state 17 */
- 250, /* cooling state 18 */
- 200, /* cooling state 19 */
- 150, /* cooling state 20 */
-};
-
int iwl_mvm_ctdp_command(struct iwl_mvm *mvm, u32 op, u32 state)
{
struct iwl_ctdp_cmd cmd = {
.operation = cpu_to_le32(op),
- .budget = cpu_to_le32(iwl_mvm_cdev_budgets[state]),
.window_size = 0,
};
+ u32 budget;
int ret;
u32 status;
lockdep_assert_held(&mvm->mutex);
+ /* Do a linear scale from IWL_MVM_MIN_CTDP_BUDGET_MW to the configured
+ * maximum in the predefined number of steps.
+ */
+ budget = ((mvm->thermal_throttle.power_budget_mw -
+ IWL_MVM_MIN_CTDP_BUDGET_MW) *
+ (IWL_MVM_NUM_CTDP_STEPS - 1 - state)) /
+ (IWL_MVM_NUM_CTDP_STEPS - 1) +
+ IWL_MVM_MIN_CTDP_BUDGET_MW;
+ cmd.budget = cpu_to_le32(budget);
+
status = 0;
ret = iwl_mvm_send_cmd_pdu_status(mvm, WIDE_ID(PHY_OPS_GROUP,
CTDP_CONFIG_CMD),
@@ -552,8 +540,8 @@ int iwl_mvm_ctdp_command(struct iwl_mvm *mvm, u32 op, u32 state)
#ifdef CONFIG_THERMAL
static int compare_temps(const void *a, const void *b)
{
- return ((s16)le16_to_cpu(*(__le16 *)a) -
- (s16)le16_to_cpu(*(__le16 *)b));
+ return ((s16)le16_to_cpu(*(const __le16 *)a) -
+ (s16)le16_to_cpu(*(const __le16 *)b));
}
struct iwl_trip_walk_data {
@@ -707,7 +695,7 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)
static int iwl_mvm_tcool_get_max_state(struct thermal_cooling_device *cdev,
unsigned long *state)
{
- *state = ARRAY_SIZE(iwl_mvm_cdev_budgets) - 1;
+ *state = IWL_MVM_NUM_CTDP_STEPS - 1;
return 0;
}
@@ -733,7 +721,7 @@ static int iwl_mvm_tcool_set_cur_state(struct thermal_cooling_device *cdev,
mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
return -EIO;
- if (new_state >= ARRAY_SIZE(iwl_mvm_cdev_budgets))
+ if (new_state >= IWL_MVM_NUM_CTDP_STEPS)
return -EINVAL;
return iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_START,
@@ -794,6 +782,47 @@ static void iwl_mvm_cooling_device_unregister(struct iwl_mvm *mvm)
}
#endif /* CONFIG_THERMAL */
+static u32 iwl_mvm_ctdp_get_max_budget(struct iwl_mvm *mvm)
+{
+ u64 bios_power_budget = 0;
+ u32 default_power_budget;
+
+ switch (CSR_HW_RFID_TYPE(mvm->trans->info.hw_rf_id)) {
+ case IWL_CFG_RF_TYPE_JF2:
+ case IWL_CFG_RF_TYPE_JF1:
+ default_power_budget = 2000;
+ break;
+ case IWL_CFG_RF_TYPE_HR2:
+ case IWL_CFG_RF_TYPE_HR1:
+ default_power_budget = 2400;
+ break;
+ case IWL_CFG_RF_TYPE_GF:
+ /* dual-radio devices have a higher budget */
+ if (CSR_HW_RFID_IS_CDB(mvm->trans->info.hw_rf_id))
+ default_power_budget = 5200;
+ else
+ default_power_budget = 2880;
+ break;
+ case IWL_CFG_RF_TYPE_FM:
+ default_power_budget = 3450;
+ break;
+ default:
+ default_power_budget = 5550;
+ break;
+ }
+
+ iwl_bios_get_pwr_limit(&mvm->fwrt, &bios_power_budget);
+
+ /* 32bit in UEFI, 16bit in ACPI; use BIOS value if it is in range */
+ if (bios_power_budget &&
+ bios_power_budget != 0xffff && bios_power_budget != 0xffffffff &&
+ bios_power_budget >= IWL_MVM_MIN_CTDP_BUDGET_MW &&
+ bios_power_budget <= default_power_budget)
+ return (u32)bios_power_budget;
+
+ return default_power_budget;
+}
+
void iwl_mvm_thermal_initialize(struct iwl_mvm *mvm, u32 min_backoff)
{
struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle;
@@ -805,6 +834,8 @@ void iwl_mvm_thermal_initialize(struct iwl_mvm *mvm, u32 min_backoff)
else
tt->params = iwl_mvm_default_tt_params;
+ tt->power_budget_mw = iwl_mvm_ctdp_get_max_budget(mvm);
+ IWL_DEBUG_TEMP(mvm, "cTDP power budget: %d mW\n", tt->power_budget_mw);
tt->throttle = false;
tt->dynamic_smps = false;
tt->min_backoff = min_backoff;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index f67afb66ef2b..bb97837baeda 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -148,12 +148,12 @@ out:
* Sets most of the Tx cmd's fields
*/
void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
- struct iwl_tx_cmd *tx_cmd,
+ struct iwl_tx_cmd_v6_params *tx_cmd_params,
struct ieee80211_tx_info *info, u8 sta_id)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
__le16 fc = hdr->frame_control;
- u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags);
+ u32 tx_flags = le32_to_cpu(tx_cmd_params->tx_flags);
u32 len = skb->len + FCS_LEN;
bool amsdu = false;
u8 ac;
@@ -173,7 +173,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
if (ieee80211_is_data_qos(fc)) {
u8 *qc = ieee80211_get_qos_ctl(hdr);
- tx_cmd->tid_tspec = qc[0] & 0xf;
+ tx_cmd_params->tid_tspec = qc[0] & 0xf;
tx_flags &= ~TX_CMD_FLG_SEQ_CTL;
amsdu = *qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT;
} else if (ieee80211_is_back_req(fc)) {
@@ -182,17 +182,17 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
u16 ssn = le16_to_cpu(bar->start_seq_num);
tx_flags |= TX_CMD_FLG_ACK | TX_CMD_FLG_BAR;
- tx_cmd->tid_tspec = (control &
+ tx_cmd_params->tid_tspec = (control &
IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
- WARN_ON_ONCE(tx_cmd->tid_tspec >= IWL_MAX_TID_COUNT);
- iwl_mvm_bar_check_trigger(mvm, bar->ra, tx_cmd->tid_tspec,
+ WARN_ON_ONCE(tx_cmd_params->tid_tspec >= IWL_MAX_TID_COUNT);
+ iwl_mvm_bar_check_trigger(mvm, bar->ra, tx_cmd_params->tid_tspec,
ssn);
} else {
if (ieee80211_is_data(fc))
- tx_cmd->tid_tspec = IWL_TID_NON_QOS;
+ tx_cmd_params->tid_tspec = IWL_TID_NON_QOS;
else
- tx_cmd->tid_tspec = IWL_MAX_TID_COUNT;
+ tx_cmd_params->tid_tspec = IWL_MAX_TID_COUNT;
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
tx_flags |= TX_CMD_FLG_SEQ_CTL;
@@ -201,8 +201,8 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
}
/* Default to 0 (BE) when tid_spec is set to IWL_MAX_TID_COUNT */
- if (tx_cmd->tid_tspec < IWL_MAX_TID_COUNT)
- ac = tid_to_mac80211_ac[tx_cmd->tid_tspec];
+ if (tx_cmd_params->tid_tspec < IWL_MAX_TID_COUNT)
+ ac = tid_to_mac80211_ac[tx_cmd_params->tid_tspec];
else
ac = tid_to_mac80211_ac[0];
@@ -211,20 +211,20 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
if (ieee80211_is_mgmt(fc)) {
if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
- tx_cmd->pm_frame_timeout = cpu_to_le16(PM_FRAME_ASSOC);
+ tx_cmd_params->pm_frame_timeout = cpu_to_le16(PM_FRAME_ASSOC);
else if (ieee80211_is_action(fc))
- tx_cmd->pm_frame_timeout = cpu_to_le16(PM_FRAME_NONE);
+ tx_cmd_params->pm_frame_timeout = cpu_to_le16(PM_FRAME_NONE);
else
- tx_cmd->pm_frame_timeout = cpu_to_le16(PM_FRAME_MGMT);
+ tx_cmd_params->pm_frame_timeout = cpu_to_le16(PM_FRAME_MGMT);
/* The spec allows Action frames in A-MPDU, we don't support
* it
*/
WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU);
} else if (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO) {
- tx_cmd->pm_frame_timeout = cpu_to_le16(PM_FRAME_MGMT);
+ tx_cmd_params->pm_frame_timeout = cpu_to_le16(PM_FRAME_MGMT);
} else {
- tx_cmd->pm_frame_timeout = cpu_to_le16(PM_FRAME_NONE);
+ tx_cmd_params->pm_frame_timeout = cpu_to_le16(PM_FRAME_NONE);
}
if (ieee80211_is_data(fc) && len > mvm->rts_threshold &&
@@ -236,13 +236,13 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
ieee80211_action_contains_tpc(skb))
tx_flags |= TX_CMD_FLG_WRITE_TX_POWER;
- tx_cmd->tx_flags = cpu_to_le32(tx_flags);
+ tx_cmd_params->tx_flags = cpu_to_le32(tx_flags);
/* Total # bytes to be transmitted - PCIe code will adjust for A-MSDU */
- tx_cmd->len = cpu_to_le16((u16)skb->len);
- tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
- tx_cmd->sta_id = sta_id;
+ tx_cmd_params->len = cpu_to_le16((u16)skb->len);
+ tx_cmd_params->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
+ tx_cmd_params->sta_id = sta_id;
- tx_cmd->offload_assist =
+ tx_cmd_params->offload_assist =
cpu_to_le16(iwl_mvm_tx_csum(mvm, skb, info, amsdu));
}
@@ -283,14 +283,10 @@ static u32 iwl_mvm_convert_rate_idx(struct iwl_mvm *mvm,
(rate_idx <= IWL_LAST_CCK_RATE);
/* Set CCK or OFDM flag */
- if (iwl_fw_lookup_cmd_ver(mvm->fw, TX_CMD, 0) > 8) {
- if (!is_cck)
- rate_flags |= RATE_MCS_LEGACY_OFDM_MSK;
- else
- rate_flags |= RATE_MCS_CCK_MSK;
- } else if (is_cck) {
- rate_flags |= RATE_MCS_CCK_MSK_V1;
- }
+ if (!is_cck)
+ rate_flags |= RATE_MCS_MOD_TYPE_LEGACY_OFDM;
+ else
+ rate_flags |= RATE_MCS_MOD_TYPE_CCK;
return (u32)rate_plcp | rate_flags;
}
@@ -303,45 +299,35 @@ static u32 iwl_mvm_get_inject_tx_rate(struct iwl_mvm *mvm,
struct ieee80211_tx_rate *rate = &info->control.rates[0];
u32 result;
- /*
- * we only care about legacy/HT/VHT so far, so we can
- * build in v1 and use iwl_new_rate_from_v1()
- */
-
if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
u8 mcs = ieee80211_rate_get_vht_mcs(rate);
u8 nss = ieee80211_rate_get_vht_nss(rate);
- result = RATE_MCS_VHT_MSK_V1;
+ result = RATE_MCS_MOD_TYPE_VHT;
result |= u32_encode_bits(mcs, RATE_VHT_MCS_RATE_CODE_MSK);
result |= u32_encode_bits(nss, RATE_MCS_NSS_MSK);
if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
- result |= RATE_MCS_SGI_MSK_V1;
+ result |= RATE_MCS_SGI_MSK;
if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
- result |= u32_encode_bits(1, RATE_MCS_CHAN_WIDTH_MSK_V1);
+ result |= RATE_MCS_CHAN_WIDTH_40;
else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
- result |= u32_encode_bits(2, RATE_MCS_CHAN_WIDTH_MSK_V1);
+ result |= RATE_MCS_CHAN_WIDTH_80;
else if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
- result |= u32_encode_bits(3, RATE_MCS_CHAN_WIDTH_MSK_V1);
-
- if (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP, TX_CMD, 0) > 6)
- result = iwl_new_rate_from_v1(result);
+ result |= RATE_MCS_CHAN_WIDTH_160;
} else if (rate->flags & IEEE80211_TX_RC_MCS) {
- result = RATE_MCS_HT_MSK_V1;
- result |= u32_encode_bits(rate->idx,
- RATE_HT_MCS_RATE_CODE_MSK_V1 |
- RATE_HT_MCS_NSS_MSK_V1);
+ result = RATE_MCS_MOD_TYPE_HT;
+ result |= u32_encode_bits(rate->idx & 0x7,
+ RATE_HT_MCS_CODE_MSK);
+ result |= u32_encode_bits(rate->idx >> 3,
+ RATE_MCS_NSS_MSK);
if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
- result |= RATE_MCS_SGI_MSK_V1;
+ result |= RATE_MCS_SGI_MSK;
if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
- result |= u32_encode_bits(1, RATE_MCS_CHAN_WIDTH_MSK_V1);
+ result |= RATE_MCS_CHAN_WIDTH_40;
if (info->flags & IEEE80211_TX_CTL_LDPC)
- result |= RATE_MCS_LDPC_MSK_V1;
+ result |= RATE_MCS_LDPC_MSK;
if (u32_get_bits(info->flags, IEEE80211_TX_CTL_STBC))
result |= RATE_MCS_STBC_MSK;
-
- if (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP, TX_CMD, 0) > 6)
- result = iwl_new_rate_from_v1(result);
} else {
int rate_idx = info->control.rates[0].idx;
@@ -391,36 +377,41 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,
return iwl_mvm_convert_rate_idx(mvm, info, rate_idx);
}
-static u32 iwl_mvm_get_tx_rate_n_flags(struct iwl_mvm *mvm,
- struct ieee80211_tx_info *info,
- struct ieee80211_sta *sta, __le16 fc)
+static __le32 iwl_mvm_get_tx_rate_n_flags(struct iwl_mvm *mvm,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_sta *sta, __le16 fc)
{
+ u32 rate;
+
if (unlikely(info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT))
- return iwl_mvm_get_inject_tx_rate(mvm, info, sta, fc);
+ rate = iwl_mvm_get_inject_tx_rate(mvm, info, sta, fc);
+ else
+ rate = iwl_mvm_get_tx_rate(mvm, info, sta, fc) |
+ iwl_mvm_get_tx_ant(mvm, info, sta, fc);
- return iwl_mvm_get_tx_rate(mvm, info, sta, fc) |
- iwl_mvm_get_tx_ant(mvm, info, sta, fc);
+ return iwl_mvm_v3_rate_to_fw(rate, mvm->fw_rates_ver);
}
/*
* Sets the fields in the Tx cmd that are rate related
*/
-void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd,
- struct ieee80211_tx_info *info,
- struct ieee80211_sta *sta, __le16 fc)
+void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
+ struct iwl_tx_cmd_v6_params *tx_cmd_params,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_sta *sta, __le16 fc)
{
/* Set retry limit on RTS packets */
- tx_cmd->rts_retry_limit = IWL_RTS_DFAULT_RETRY_LIMIT;
+ tx_cmd_params->rts_retry_limit = IWL_RTS_DFAULT_RETRY_LIMIT;
/* Set retry limit on DATA packets and Probe Responses*/
if (ieee80211_is_probe_resp(fc)) {
- tx_cmd->data_retry_limit = IWL_MGMT_DFAULT_RETRY_LIMIT;
- tx_cmd->rts_retry_limit =
- min(tx_cmd->data_retry_limit, tx_cmd->rts_retry_limit);
+ tx_cmd_params->data_retry_limit = IWL_MGMT_DFAULT_RETRY_LIMIT;
+ tx_cmd_params->rts_retry_limit =
+ min(tx_cmd_params->data_retry_limit, tx_cmd_params->rts_retry_limit);
} else if (ieee80211_is_back_req(fc)) {
- tx_cmd->data_retry_limit = IWL_BAR_DFAULT_RETRY_LIMIT;
+ tx_cmd_params->data_retry_limit = IWL_BAR_DFAULT_RETRY_LIMIT;
} else {
- tx_cmd->data_retry_limit = IWL_DEFAULT_TX_RETRY;
+ tx_cmd_params->data_retry_limit = IWL_DEFAULT_TX_RETRY;
}
/*
@@ -433,18 +424,17 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd,
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
if (mvmsta->sta_state >= IEEE80211_STA_AUTHORIZED) {
- tx_cmd->initial_rate_index = 0;
- tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
+ tx_cmd_params->initial_rate_index = 0;
+ tx_cmd_params->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
return;
}
} else if (ieee80211_is_back_req(fc)) {
- tx_cmd->tx_flags |=
+ tx_cmd_params->tx_flags |=
cpu_to_le32(TX_CMD_FLG_ACK | TX_CMD_FLG_BAR);
}
/* Set the rate in the TX cmd */
- tx_cmd->rate_n_flags =
- cpu_to_le32(iwl_mvm_get_tx_rate_n_flags(mvm, info, sta, fc));
+ tx_cmd_params->rate_n_flags = iwl_mvm_get_tx_rate_n_flags(mvm, info, sta, fc);
}
static inline void iwl_mvm_set_tx_cmd_pn(struct ieee80211_tx_info *info,
@@ -469,7 +459,7 @@ static inline void iwl_mvm_set_tx_cmd_pn(struct ieee80211_tx_info *info,
*/
static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
struct ieee80211_tx_info *info,
- struct iwl_tx_cmd *tx_cmd,
+ struct iwl_tx_cmd_v6_params *tx_cmd_params,
struct sk_buff *skb_frag,
int hdrlen)
{
@@ -480,26 +470,26 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
switch (keyconf->cipher) {
case WLAN_CIPHER_SUITE_CCMP:
- iwl_mvm_set_tx_cmd_ccmp(info, tx_cmd);
+ iwl_mvm_set_tx_cmd_ccmp(info, tx_cmd_params);
iwl_mvm_set_tx_cmd_pn(info, crypto_hdr);
break;
case WLAN_CIPHER_SUITE_TKIP:
- tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
+ tx_cmd_params->sec_ctl = TX_CMD_SEC_TKIP;
pn = atomic64_inc_return(&keyconf->tx_pn);
ieee80211_tkip_add_iv(crypto_hdr, keyconf, pn);
- ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
+ ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd_params->key);
break;
case WLAN_CIPHER_SUITE_WEP104:
- tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
+ tx_cmd_params->sec_ctl |= TX_CMD_SEC_KEY128;
fallthrough;
case WLAN_CIPHER_SUITE_WEP40:
- tx_cmd->sec_ctl |= TX_CMD_SEC_WEP |
+ tx_cmd_params->sec_ctl |= TX_CMD_SEC_WEP |
((keyconf->keyidx << TX_CMD_SEC_WEP_KEY_IDX_POS) &
TX_CMD_SEC_WEP_KEY_IDX_MSK);
- memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen);
+ memcpy(&tx_cmd_params->key[3], keyconf->key, keyconf->keylen);
break;
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
@@ -512,12 +502,12 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
* one.
* Need to handle this.
*/
- tx_cmd->sec_ctl |= type | TX_CMD_SEC_KEY_FROM_TABLE;
- tx_cmd->key[0] = keyconf->hw_key_idx;
+ tx_cmd_params->sec_ctl |= type | TX_CMD_SEC_KEY_FROM_TABLE;
+ tx_cmd_params->key[0] = keyconf->hw_key_idx;
iwl_mvm_set_tx_cmd_pn(info, crypto_hdr);
break;
default:
- tx_cmd->sec_ctl |= TX_CMD_SEC_EXT;
+ tx_cmd_params->sec_ctl |= TX_CMD_SEC_EXT;
}
}
@@ -543,7 +533,7 @@ static bool iwl_mvm_use_host_rate(struct iwl_mvm *mvm,
* (since we don't necesarily know the link), but FW rate
* selection was fixed.
*/
- return mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ;
+ return mvm->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ;
}
static void iwl_mvm_copy_hdr(void *cmd, const void *hdr, int hdrlen,
@@ -567,7 +557,7 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct iwl_device_tx_cmd *dev_cmd;
- struct iwl_tx_cmd *tx_cmd;
+ struct iwl_tx_cmd_v6 *tx_cmd;
dev_cmd = iwl_trans_alloc_tx_cmd(mvm->trans);
@@ -577,7 +567,7 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
dev_cmd->hdr.cmd = TX_CMD;
if (iwl_mvm_has_new_tx_api(mvm)) {
- u32 rate_n_flags = 0;
+ __le32 rate_n_flags = 0;
u16 flags = 0;
struct iwl_mvm_sta *mvmsta = sta ?
iwl_mvm_sta_from_mac80211(sta) : NULL;
@@ -609,9 +599,9 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
flags |= IWL_TX_FLAGS_HIGH_PRI;
}
- if (mvm->trans->trans_cfg->device_family >=
+ if (mvm->trans->mac_cfg->device_family >=
IWL_DEVICE_FAMILY_AX210) {
- struct iwl_tx_cmd_gen3 *cmd = (void *)dev_cmd->payload;
+ struct iwl_tx_cmd *cmd = (void *)dev_cmd->payload;
u32 offload_assist = iwl_mvm_tx_csum(mvm, skb,
info, amsdu);
@@ -624,9 +614,9 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
iwl_mvm_copy_hdr(cmd->hdr, hdr, hdrlen, addr3_override);
cmd->flags = cpu_to_le16(flags);
- cmd->rate_n_flags = cpu_to_le32(rate_n_flags);
+ cmd->rate_n_flags = rate_n_flags;
} else {
- struct iwl_tx_cmd_gen2 *cmd = (void *)dev_cmd->payload;
+ struct iwl_tx_cmd_v9 *cmd = (void *)dev_cmd->payload;
u16 offload_assist = iwl_mvm_tx_csum(mvm, skb,
info, amsdu);
@@ -639,19 +629,19 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
iwl_mvm_copy_hdr(cmd->hdr, hdr, hdrlen, addr3_override);
cmd->flags = cpu_to_le32(flags);
- cmd->rate_n_flags = cpu_to_le32(rate_n_flags);
+ cmd->rate_n_flags = rate_n_flags;
}
goto out;
}
- tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;
+ tx_cmd = (struct iwl_tx_cmd_v6 *)dev_cmd->payload;
if (info->control.hw_key)
- iwl_mvm_set_tx_cmd_crypto(mvm, info, tx_cmd, skb, hdrlen);
+ iwl_mvm_set_tx_cmd_crypto(mvm, info, &tx_cmd->params, skb, hdrlen);
- iwl_mvm_set_tx_cmd(mvm, skb, tx_cmd, info, sta_id);
+ iwl_mvm_set_tx_cmd(mvm, skb, &tx_cmd->params, info, sta_id);
- iwl_mvm_set_tx_cmd_rate(mvm, tx_cmd, info, sta, hdr->frame_control);
+ iwl_mvm_set_tx_cmd_rate(mvm, &tx_cmd->params, info, sta, hdr->frame_control);
/* Copy MAC header from skb into command buffer */
iwl_mvm_copy_hdr(tx_cmd->hdr, hdr, hdrlen, addr3_override);
@@ -1023,7 +1013,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
* 1 more for the potential data in the header
*/
if ((num_subframes * 2 + skb_shinfo(skb)->nr_frags + 1) >
- mvm->trans->max_skb_frags)
+ mvm->trans->info.max_skb_frags)
num_subframes = 1;
if (num_subframes > 1)
@@ -1185,7 +1175,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
seq_number &= IEEE80211_SCTL_SEQ;
if (!iwl_mvm_has_new_tx_api(mvm)) {
- struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload;
+ struct iwl_tx_cmd_v6 *tx_cmd = (void *)dev_cmd->payload;
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
hdr->seq_ctrl |= cpu_to_le16(seq_number);
@@ -1372,8 +1362,7 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm,
lockdep_assert_held(&mvmsta->lock);
- if ((tid_data->state == IWL_AGG_ON ||
- tid_data->state == IWL_EMPTYING_HW_QUEUE_DELBA) &&
+ if (tid_data->state == IWL_AGG_ON &&
iwl_mvm_tid_queued(mvm, tid_data) == 0) {
/*
* Now that this aggregation or DQA queue is empty tell
@@ -1388,7 +1377,7 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm,
* to align the wrap around of ssn so we compare relevant values.
*/
normalized_ssn = tid_data->ssn;
- if (mvm->trans->trans_cfg->gen2)
+ if (mvm->trans->mac_cfg->gen2)
normalized_ssn &= 0xff;
if (normalized_ssn != tid_data->next_reclaimed)
@@ -1402,15 +1391,6 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm,
tid_data->state = IWL_AGG_STARTING;
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
-
- case IWL_EMPTYING_HW_QUEUE_DELBA:
- IWL_DEBUG_TX_QUEUES(mvm,
- "Can continue DELBA flow ssn = next_recl = %d\n",
- tid_data->next_reclaimed);
- tid_data->state = IWL_AGG_OFF;
- ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
- break;
-
default:
break;
}
@@ -1477,7 +1457,7 @@ void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
struct ieee80211_tx_rate *r)
{
u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
- u32 rate = format == RATE_MCS_HT_MSK ?
+ u32 rate = format == RATE_MCS_MOD_TYPE_HT ?
RATE_HT_MCS_INDEX(rate_n_flags) :
rate_n_flags & RATE_MCS_CODE_MSK;
@@ -1487,68 +1467,51 @@ void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
if (rate_n_flags & RATE_MCS_SGI_MSK)
r->flags |= IEEE80211_TX_RC_SHORT_GI;
- if (format == RATE_MCS_HT_MSK) {
+ switch (format) {
+ case RATE_MCS_MOD_TYPE_HT:
r->flags |= IEEE80211_TX_RC_MCS;
r->idx = rate;
- } else if (format == RATE_MCS_VHT_MSK) {
+ break;
+ case RATE_MCS_MOD_TYPE_VHT:
ieee80211_rate_set_vht(r, rate,
FIELD_GET(RATE_MCS_NSS_MSK,
rate_n_flags) + 1);
r->flags |= IEEE80211_TX_RC_VHT_MCS;
- } else if (format == RATE_MCS_HE_MSK) {
+ break;
+ case RATE_MCS_MOD_TYPE_HE:
+ case RATE_MCS_MOD_TYPE_EHT:
/* mac80211 cannot do this without ieee80211_tx_status_ext()
* but it only matters for radiotap */
r->idx = 0;
- } else {
+ break;
+ default:
r->idx = iwl_mvm_legacy_hw_idx_to_mac80211_idx(rate_n_flags,
band);
}
}
-void iwl_mvm_hwrate_to_tx_rate_v1(u32 rate_n_flags,
- enum nl80211_band band,
- struct ieee80211_tx_rate *r)
-{
- if (rate_n_flags & RATE_HT_MCS_GF_MSK)
- r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
-
- r->flags |=
- iwl_mvm_get_hwrate_chan_width(rate_n_flags &
- RATE_MCS_CHAN_WIDTH_MSK_V1);
-
- if (rate_n_flags & RATE_MCS_SGI_MSK_V1)
- r->flags |= IEEE80211_TX_RC_SHORT_GI;
- if (rate_n_flags & RATE_MCS_HT_MSK_V1) {
- r->flags |= IEEE80211_TX_RC_MCS;
- r->idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK_V1;
- } else if (rate_n_flags & RATE_MCS_VHT_MSK_V1) {
- ieee80211_rate_set_vht(
- r, rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK,
- FIELD_GET(RATE_MCS_NSS_MSK, rate_n_flags) + 1);
- r->flags |= IEEE80211_TX_RC_VHT_MCS;
- } else {
- r->idx = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,
- band);
- }
-}
-
/*
* translate ucode response to mac80211 tx status control values
*/
-static void iwl_mvm_hwrate_to_tx_status(const struct iwl_fw *fw,
- u32 rate_n_flags,
+static void iwl_mvm_hwrate_to_tx_status(struct iwl_mvm *mvm,
+ __le32 rate_n_flags,
struct ieee80211_tx_info *info)
{
struct ieee80211_tx_rate *r = &info->status.rates[0];
+ u32 rate;
- if (iwl_fw_lookup_notif_ver(fw, LONG_GROUP,
- TX_CMD, 0) <= 6)
- rate_n_flags = iwl_new_rate_from_v1(rate_n_flags);
+ /*
+ * Technically this conversion is incorrect for BA status, however:
+ * - we only use the BA notif data for older firmware that have
+ * host rate scaling and don't use newer rate formats
+ * - the firmware API changed together for BA notif and TX CMD
+ * as well
+ */
+ rate = iwl_mvm_v3_rate_from_fw(rate_n_flags, mvm->fw_rates_ver);
info->status.antenna =
- ((rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS);
- iwl_mvm_hwrate_to_tx_rate(rate_n_flags,
- info->band, r);
+ ((rate & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS);
+ iwl_mvm_hwrate_to_tx_rate(rate, info->band, r);
}
static void iwl_mvm_tx_status_check_trigger(struct iwl_mvm *mvm,
@@ -1613,7 +1576,7 @@ static inline u32 iwl_mvm_get_scd_ssn(struct iwl_mvm *mvm,
u32 val = le32_to_cpup((__le32 *)iwl_mvm_get_agg_status(mvm, tx_resp) +
tx_resp->frame_count);
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
return val & 0xFFFF;
return val & 0xFFF;
}
@@ -1700,9 +1663,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
info->status.rates[0].count = tx_resp->failure_frame + 1;
- iwl_mvm_hwrate_to_tx_status(mvm->fw,
- le32_to_cpu(tx_resp->initial_rate),
- info);
+ iwl_mvm_hwrate_to_tx_status(mvm, tx_resp->initial_rate, info);
/* Don't assign the converted initial_rate, because driver
* TLC uses this and doesn't support the new FW rate
@@ -1808,9 +1769,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
IWL_DEBUG_TX_REPLY(mvm,
"Next reclaimed packet:%d\n",
next_reclaimed);
- if (tid < IWL_MAX_TID_COUNT)
- iwl_mvm_count_mpdu(mvmsta, sta_id, 1,
- true, 0);
} else {
IWL_DEBUG_TX_REPLY(mvm,
"NDP - don't update next_reclaimed\n");
@@ -1944,7 +1902,7 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm,
if (!WARN_ON_ONCE(!mvmsta)) {
mvmsta->tid_data[tid].rate_n_flags =
- le32_to_cpu(tx_resp->initial_rate);
+ tx_resp->initial_rate;
mvmsta->tid_data[tid].tx_time =
le16_to_cpu(tx_resp->wireless_media_time);
mvmsta->tid_data[tid].lq_color =
@@ -1969,7 +1927,7 @@ void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
int txq, int index,
- struct ieee80211_tx_info *tx_info, u32 rate,
+ struct ieee80211_tx_info *tx_info, __le32 rate,
bool is_flush)
{
struct sk_buff_head reclaimed_skbs;
@@ -2053,7 +2011,9 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
tx_info->status.status_driver_data[0] =
RS_DRV_DATA_PACK(tid_data->lq_color,
tx_info->status.status_driver_data[0]);
- tx_info->status.status_driver_data[1] = (void *)(uintptr_t)rate;
+ /* the value is only consumed for old FW that has v1 rates anyway */
+ tx_info->status.status_driver_data[1] =
+ (void *)(uintptr_t)le32_to_cpu(rate);
skb_queue_walk(&reclaimed_skbs, skb) {
struct ieee80211_hdr *hdr = (void *)skb->data;
@@ -2072,7 +2032,7 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
info->flags |= IEEE80211_TX_STAT_AMPDU;
memcpy(&info->status, &tx_info->status,
sizeof(tx_info->status));
- iwl_mvm_hwrate_to_tx_status(mvm->fw, rate, info);
+ iwl_mvm_hwrate_to_tx_status(mvm, rate, info);
}
}
@@ -2095,7 +2055,7 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
goto out;
tx_info->band = chanctx_conf->def.chan->band;
- iwl_mvm_hwrate_to_tx_status(mvm->fw, rate, tx_info);
+ iwl_mvm_hwrate_to_tx_status(mvm, rate, tx_info);
IWL_DEBUG_TX_REPLY(mvm, "No reclaim. Update rs directly\n");
iwl_mvm_rs_tx_status(mvm, sta, tid, tx_info, false);
@@ -2184,16 +2144,13 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
(int)(le16_to_cpu(ba_tfd->q_num)),
le16_to_cpu(ba_tfd->tfd_index),
&ba_info,
- le32_to_cpu(ba_res->tx_rate), false);
+ ba_res->tx_rate, false);
}
- if (mvmsta) {
+ if (mvmsta)
iwl_mvm_tx_airtime(mvm, mvmsta,
le32_to_cpu(ba_res->wireless_time));
- iwl_mvm_count_mpdu(mvmsta, sta_id,
- le16_to_cpu(ba_res->txed), true, 0);
- }
rcu_read_unlock();
return;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index dd890dcd1505..1a6c1f8706e1 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -22,11 +22,6 @@ int iwl_mvm_send_cmd(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd)
{
int ret;
-#if defined(CONFIG_IWLWIFI_DEBUGFS) && defined(CONFIG_PM_SLEEP)
- if (WARN_ON(mvm->d3_test_active))
- return -EIO;
-#endif
-
/*
* Synchronous commands from this op-mode must hold
* the mutex, this ensures we don't try to send two
@@ -79,11 +74,6 @@ int iwl_mvm_send_cmd_status(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd,
lockdep_assert_held(&mvm->mutex);
-#if defined(CONFIG_IWLWIFI_DEBUGFS) && defined(CONFIG_PM_SLEEP)
- if (WARN_ON(mvm->d3_test_active))
- return -EIO;
-#endif
-
/*
* Only synchronous commands can wait for status,
* we use WANT_SKB so the caller can't.
@@ -142,7 +132,7 @@ int iwl_mvm_legacy_hw_idx_to_mac80211_idx(u32 rate_n_flags,
int rate = rate_n_flags & RATE_LEGACY_RATE_MSK;
bool is_LB = band == NL80211_BAND_2GHZ;
- if (format == RATE_MCS_LEGACY_OFDM_MSK)
+ if (format == RATE_MCS_MOD_TYPE_LEGACY_OFDM)
return is_LB ? rate + IWL_FIRST_OFDM_RATE :
rate;
@@ -748,7 +738,7 @@ unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
unsigned int default_timeout =
- mvm->trans->trans_cfg->base_params->wd_timeout;
+ mvm->trans->mac_cfg->base->wd_timeout;
/*
* We can't know when the station is asleep or awake, so we
@@ -1187,9 +1177,9 @@ u32 iwl_mvm_get_systime(struct iwl_mvm *mvm)
{
u32 reg_addr = DEVICE_SYSTEM_TIME_REG;
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000 &&
- mvm->trans->cfg->gp2_reg_addr)
- reg_addr = mvm->trans->cfg->gp2_reg_addr;
+ if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000 &&
+ mvm->trans->mac_cfg->base->gp2_reg_addr)
+ reg_addr = mvm->trans->mac_cfg->base->gp2_reg_addr;
return iwl_read_prph(mvm->trans, reg_addr);
}
@@ -1253,3 +1243,167 @@ bool iwl_mvm_vif_is_active(struct iwl_mvm_vif *mvmvif)
return false;
}
+
+static u32 iwl_legacy_rate_to_fw_idx(u32 rate_n_flags)
+{
+ int rate = rate_n_flags & RATE_LEGACY_RATE_MSK_V1;
+ int idx;
+ bool ofdm = !(rate_n_flags & RATE_MCS_CCK_MSK_V1);
+ int offset = ofdm ? IWL_FIRST_OFDM_RATE : 0;
+ int last = ofdm ? IWL_RATE_COUNT_LEGACY : IWL_FIRST_OFDM_RATE;
+
+ for (idx = offset; idx < last; idx++)
+ if (iwl_fw_rate_idx_to_plcp(idx) == rate)
+ return idx - offset;
+ return IWL_RATE_INVALID;
+}
+
+u32 iwl_mvm_v3_rate_from_fw(__le32 rate, u8 rate_ver)
+{
+ u32 rate_v3 = 0, rate_v1;
+ u32 dup = 0;
+
+ if (rate_ver > 1)
+ return iwl_v3_rate_from_v2_v3(rate, rate_ver >= 3);
+
+ rate_v1 = le32_to_cpu(rate);
+ if (rate_v1 == 0)
+ return rate_v1;
+ /* convert rate */
+ if (rate_v1 & RATE_MCS_HT_MSK_V1) {
+ u32 nss;
+
+ rate_v3 |= RATE_MCS_MOD_TYPE_HT;
+ rate_v3 |=
+ rate_v1 & RATE_HT_MCS_RATE_CODE_MSK_V1;
+ nss = u32_get_bits(rate_v1, RATE_HT_MCS_MIMO2_MSK);
+ rate_v3 |= u32_encode_bits(nss, RATE_MCS_NSS_MSK);
+ } else if (rate_v1 & RATE_MCS_VHT_MSK_V1 ||
+ rate_v1 & RATE_MCS_HE_MSK_V1) {
+ u32 nss = u32_get_bits(rate_v1, RATE_VHT_MCS_NSS_MSK);
+
+ rate_v3 |= rate_v1 & RATE_VHT_MCS_RATE_CODE_MSK;
+
+ rate_v3 |= u32_encode_bits(nss, RATE_MCS_NSS_MSK);
+
+ if (rate_v1 & RATE_MCS_HE_MSK_V1) {
+ u32 he_type_bits = rate_v1 & RATE_MCS_HE_TYPE_MSK_V1;
+ u32 he_type = he_type_bits >> RATE_MCS_HE_TYPE_POS_V1;
+ u32 he_106t = (rate_v1 & RATE_MCS_HE_106T_MSK_V1) >>
+ RATE_MCS_HE_106T_POS_V1;
+ u32 he_gi_ltf = (rate_v1 & RATE_MCS_HE_GI_LTF_MSK_V1) >>
+ RATE_MCS_HE_GI_LTF_POS;
+
+ if ((he_type_bits == RATE_MCS_HE_TYPE_SU ||
+ he_type_bits == RATE_MCS_HE_TYPE_EXT_SU) &&
+ he_gi_ltf == RATE_MCS_HE_SU_4_LTF)
+ /* the new rate have an additional bit to
+ * represent the value 4 rather then using SGI
+ * bit for this purpose - as it was done in the
+ * old rate
+ */
+ he_gi_ltf += (rate_v1 & RATE_MCS_SGI_MSK_V1) >>
+ RATE_MCS_SGI_POS_V1;
+
+ rate_v3 |= he_gi_ltf << RATE_MCS_HE_GI_LTF_POS;
+ rate_v3 |= he_type << RATE_MCS_HE_TYPE_POS;
+ rate_v3 |= he_106t << RATE_MCS_HE_106T_POS;
+ rate_v3 |= rate_v1 & RATE_HE_DUAL_CARRIER_MODE_MSK;
+ rate_v3 |= RATE_MCS_MOD_TYPE_HE;
+ } else {
+ rate_v3 |= RATE_MCS_MOD_TYPE_VHT;
+ }
+ /* if legacy format */
+ } else {
+ u32 legacy_rate = iwl_legacy_rate_to_fw_idx(rate_v1);
+
+ if (WARN_ON_ONCE(legacy_rate == IWL_RATE_INVALID))
+ legacy_rate = (rate_v1 & RATE_MCS_CCK_MSK_V1) ?
+ IWL_FIRST_CCK_RATE : IWL_FIRST_OFDM_RATE;
+
+ rate_v3 |= legacy_rate;
+ if (!(rate_v1 & RATE_MCS_CCK_MSK_V1))
+ rate_v3 |= RATE_MCS_MOD_TYPE_LEGACY_OFDM;
+ }
+
+ /* convert flags */
+ if (rate_v1 & RATE_MCS_LDPC_MSK_V1)
+ rate_v3 |= RATE_MCS_LDPC_MSK;
+ rate_v3 |= (rate_v1 & RATE_MCS_CHAN_WIDTH_MSK_V1) |
+ (rate_v1 & RATE_MCS_ANT_AB_MSK) |
+ (rate_v1 & RATE_MCS_STBC_MSK) |
+ (rate_v1 & RATE_MCS_BF_MSK);
+
+ dup = (rate_v1 & RATE_MCS_DUP_MSK_V1) >> RATE_MCS_DUP_POS_V1;
+ if (dup) {
+ rate_v3 |= RATE_MCS_DUP_MSK;
+ rate_v3 |= dup << RATE_MCS_CHAN_WIDTH_POS;
+ }
+
+ if ((!(rate_v1 & RATE_MCS_HE_MSK_V1)) &&
+ (rate_v1 & RATE_MCS_SGI_MSK_V1))
+ rate_v3 |= RATE_MCS_SGI_MSK;
+
+ return rate_v3;
+}
+
+__le32 iwl_mvm_v3_rate_to_fw(u32 rate, u8 rate_ver)
+{
+ u32 result = 0;
+ int rate_idx;
+
+ if (rate_ver > 1)
+ return iwl_v3_rate_to_v2_v3(rate, rate_ver > 2);
+
+ switch (rate & RATE_MCS_MOD_TYPE_MSK) {
+ case RATE_MCS_MOD_TYPE_CCK:
+ result = RATE_MCS_CCK_MSK_V1;
+ fallthrough;
+ case RATE_MCS_MOD_TYPE_LEGACY_OFDM:
+ rate_idx = u32_get_bits(rate, RATE_LEGACY_RATE_MSK);
+ if (!(result & RATE_MCS_CCK_MSK_V1))
+ rate_idx += IWL_FIRST_OFDM_RATE;
+ result |= u32_encode_bits(iwl_fw_rate_idx_to_plcp(rate_idx),
+ RATE_LEGACY_RATE_MSK_V1);
+ break;
+ case RATE_MCS_MOD_TYPE_HT:
+ result = RATE_MCS_HT_MSK_V1;
+ result |= u32_encode_bits(u32_get_bits(rate,
+ RATE_HT_MCS_CODE_MSK),
+ RATE_HT_MCS_RATE_CODE_MSK_V1);
+ result |= u32_encode_bits(u32_get_bits(rate,
+ RATE_MCS_NSS_MSK),
+ RATE_HT_MCS_MIMO2_MSK);
+ break;
+ case RATE_MCS_MOD_TYPE_VHT:
+ result = RATE_MCS_VHT_MSK_V1;
+ result |= u32_encode_bits(u32_get_bits(rate,
+ RATE_VHT_MCS_NSS_MSK),
+ RATE_MCS_CODE_MSK);
+ result |= u32_encode_bits(u32_get_bits(rate, RATE_MCS_NSS_MSK),
+ RATE_VHT_MCS_NSS_MSK);
+ break;
+ case RATE_MCS_MOD_TYPE_HE: /* not generated */
+ default:
+ WARN_ONCE(1, "bad modulation type %d\n",
+ u32_get_bits(rate, RATE_MCS_MOD_TYPE_MSK));
+ return 0;
+ }
+
+ if (rate & RATE_MCS_LDPC_MSK)
+ result |= RATE_MCS_LDPC_MSK_V1;
+ WARN_ON_ONCE(u32_get_bits(rate, RATE_MCS_CHAN_WIDTH_MSK) >
+ RATE_MCS_CHAN_WIDTH_160_VAL);
+ result |= (rate & RATE_MCS_CHAN_WIDTH_MSK_V1) |
+ (rate & RATE_MCS_ANT_AB_MSK) |
+ (rate & RATE_MCS_STBC_MSK) |
+ (rate & RATE_MCS_BF_MSK);
+
+ /* not handling DUP since we don't use it */
+ WARN_ON_ONCE(rate & RATE_MCS_DUP_MSK);
+
+ if (rate & RATE_MCS_SGI_MSK)
+ result |= RATE_MCS_SGI_MSK_V1;
+
+ return cpu_to_le32(result);
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c
index 8aa7c455bdee..06be929a3ca5 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c
@@ -5,8 +5,8 @@
#include <linux/dmi.h>
#include "iwl-trans.h"
#include "iwl-fh.h"
-#include "iwl-context-info-gen3.h"
-#include "internal.h"
+#include "iwl-context-info-v2.h"
+#include "gen1_2/internal.h"
#include "iwl-prph.h"
static const struct dmi_system_id dmi_force_scu_active_approved_list[] = {
@@ -97,11 +97,12 @@ out:
*control_flags |= IWL_PRPH_SCRATCH_EARLY_DEBUG_EN | dbg_flags;
}
-int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
- const struct fw_img *fw)
+int iwl_pcie_ctxt_info_v2_alloc(struct iwl_trans *trans,
+ const struct iwl_fw *fw,
+ const struct fw_img *img)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_context_info_gen3 *ctxt_info_gen3;
+ struct iwl_context_info_v2 *ctxt_info_v2;
struct iwl_prph_scratch *prph_scratch;
struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl;
struct iwl_prph_info *prph_info;
@@ -109,9 +110,9 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
u32 control_flags_ext = 0;
int ret;
int cmdq_size = max_t(u32, IWL_CMD_QUEUE_SIZE,
- trans->cfg->min_txq_size);
+ trans->mac_cfg->base->min_txq_size);
- switch (trans_pcie->rx_buf_size) {
+ switch (trans->conf.rx_buf_size) {
case IWL_AMSDU_DEF:
return -EINVAL;
case IWL_AMSDU_2K:
@@ -131,13 +132,13 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
break;
}
- if (trans->dsbr_urm_fw_dependent)
+ if (trans->conf.dsbr_urm_fw_dependent)
control_flags_ext |= IWL_PRPH_SCRATCH_EXT_URM_FW;
- if (trans->dsbr_urm_permanent)
+ if (trans->conf.dsbr_urm_permanent)
control_flags_ext |= IWL_PRPH_SCRATCH_EXT_URM_PERM;
- if (trans->ext_32khz_clock_valid)
+ if (trans->conf.ext_32khz_clock_valid)
control_flags_ext |= IWL_PRPH_SCRATCH_EXT_32KHZ_CLK_VALID;
/* Allocate prph scratch */
@@ -151,16 +152,16 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
prph_sc_ctrl->version.version = 0;
prph_sc_ctrl->version.mac_id =
- cpu_to_le16((u16)trans->hw_rev);
+ cpu_to_le16((u16)trans->info.hw_rev);
prph_sc_ctrl->version.size = cpu_to_le16(sizeof(*prph_scratch) / 4);
control_flags |= IWL_PRPH_SCRATCH_MTR_MODE;
control_flags |= IWL_PRPH_MTR_FORMAT_256B & IWL_PRPH_SCRATCH_MTR_FORMAT;
- if (trans->trans_cfg->imr_enabled)
+ if (trans->mac_cfg->imr_enabled)
control_flags |= IWL_PRPH_SCRATCH_IMR_DEBUG_EN;
- if (CSR_HW_REV_TYPE(trans->hw_rev) == IWL_CFG_MAC_TYPE_GL &&
+ if (CSR_HW_REV_TYPE(trans->info.hw_rev) == IWL_CFG_MAC_TYPE_GL &&
iwl_is_force_scu_active_approved()) {
control_flags |= IWL_PRPH_SCRATCH_SCU_FORCE_ACTIVE;
IWL_DEBUG_FW(trans,
@@ -168,6 +169,11 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
IWL_PRPH_SCRATCH_SCU_FORCE_ACTIVE);
}
+ if (trans->do_top_reset) {
+ WARN_ON(trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_SC);
+ control_flags |= IWL_PRPH_SCRATCH_TOP_RESET;
+ }
+
/* initialize RX default queue */
prph_sc_ctrl->rbd_cfg.free_rbd_addr =
cpu_to_le64(trans_pcie->rxq->bd_dma);
@@ -178,15 +184,16 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
prph_sc_ctrl->control.control_flags_ext = cpu_to_le32(control_flags_ext);
/* initialize the Step equalizer data */
- prph_sc_ctrl->step_cfg.mbx_addr_0 = cpu_to_le32(trans->mbx_addr_0_step);
- prph_sc_ctrl->step_cfg.mbx_addr_1 = cpu_to_le32(trans->mbx_addr_1_step);
+ prph_sc_ctrl->step_cfg.mbx_addr_0 =
+ cpu_to_le32(trans->conf.mbx_addr_0_step);
+ prph_sc_ctrl->step_cfg.mbx_addr_1 =
+ cpu_to_le32(trans->conf.mbx_addr_1_step);
/* allocate ucode sections in dram and set addresses */
- ret = iwl_pcie_init_fw_sec(trans, fw, &prph_scratch->dram);
+ ret = iwl_pcie_init_fw_sec(trans, img, &prph_scratch->dram.common);
if (ret)
goto err_free_prph_scratch;
-
/* Allocate prph information
* currently we don't assign to the prph info anything, but it would get
* assigned later
@@ -206,42 +213,58 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
}
/* Allocate context info */
- ctxt_info_gen3 = dma_alloc_coherent(trans->dev,
- sizeof(*ctxt_info_gen3),
- &trans_pcie->ctxt_info_dma_addr,
- GFP_KERNEL);
- if (!ctxt_info_gen3) {
+ ctxt_info_v2 = dma_alloc_coherent(trans->dev,
+ sizeof(*ctxt_info_v2),
+ &trans_pcie->ctxt_info_dma_addr,
+ GFP_KERNEL);
+ if (!ctxt_info_v2) {
ret = -ENOMEM;
goto err_free_prph_info;
}
- ctxt_info_gen3->prph_info_base_addr =
+ ctxt_info_v2->prph_info_base_addr =
cpu_to_le64(trans_pcie->prph_info_dma_addr);
- ctxt_info_gen3->prph_scratch_base_addr =
+ ctxt_info_v2->prph_scratch_base_addr =
cpu_to_le64(trans_pcie->prph_scratch_dma_addr);
- ctxt_info_gen3->prph_scratch_size =
- cpu_to_le32(sizeof(*prph_scratch));
- ctxt_info_gen3->cr_head_idx_arr_base_addr =
+
+ /*
+ * This code assumes the FSEQ is last and we can make that
+ * optional; old devices _should_ be fine with a bigger size,
+ * but in simulation we check the size more precisely.
+ */
+ BUILD_BUG_ON(offsetofend(typeof(*prph_scratch), dram.common) +
+ sizeof(prph_scratch->dram.fseq_img) !=
+ sizeof(*prph_scratch));
+ if (control_flags_ext & IWL_PRPH_SCRATCH_EXT_EXT_FSEQ)
+ ctxt_info_v2->prph_scratch_size =
+ cpu_to_le32(sizeof(*prph_scratch));
+ else
+ ctxt_info_v2->prph_scratch_size =
+ cpu_to_le32(offsetofend(typeof(*prph_scratch),
+ dram.common));
+
+ ctxt_info_v2->cr_head_idx_arr_base_addr =
cpu_to_le64(trans_pcie->rxq->rb_stts_dma);
- ctxt_info_gen3->tr_tail_idx_arr_base_addr =
+ ctxt_info_v2->tr_tail_idx_arr_base_addr =
cpu_to_le64(trans_pcie->prph_info_dma_addr + PAGE_SIZE / 2);
- ctxt_info_gen3->cr_tail_idx_arr_base_addr =
+ ctxt_info_v2->cr_tail_idx_arr_base_addr =
cpu_to_le64(trans_pcie->prph_info_dma_addr + 3 * PAGE_SIZE / 4);
- ctxt_info_gen3->mtr_base_addr =
- cpu_to_le64(trans_pcie->txqs.txq[trans_pcie->txqs.cmd.q_id]->dma_addr);
- ctxt_info_gen3->mcr_base_addr =
+ ctxt_info_v2->mtr_base_addr =
+ cpu_to_le64(trans_pcie->txqs.txq[trans->conf.cmd_queue]->dma_addr);
+ ctxt_info_v2->mcr_base_addr =
cpu_to_le64(trans_pcie->rxq->used_bd_dma);
- ctxt_info_gen3->mtr_size =
+ ctxt_info_v2->mtr_size =
cpu_to_le16(TFD_QUEUE_CB_SIZE(cmdq_size));
- ctxt_info_gen3->mcr_size =
- cpu_to_le16(RX_QUEUE_CB_SIZE(trans->cfg->num_rbds));
+ ctxt_info_v2->mcr_size =
+ cpu_to_le16(RX_QUEUE_CB_SIZE(iwl_trans_get_num_rbds(trans)));
- trans_pcie->ctxt_info_gen3 = ctxt_info_gen3;
+ trans_pcie->ctxt_info_v2 = ctxt_info_v2;
trans_pcie->prph_info = prph_info;
trans_pcie->prph_scratch = prph_scratch;
/* Allocate IML */
- trans_pcie->iml = dma_alloc_coherent(trans->dev, trans->iml_len,
+ trans_pcie->iml_len = fw->iml_len;
+ trans_pcie->iml = dma_alloc_coherent(trans->dev, fw->iml_len,
&trans_pcie->iml_dma_addr,
GFP_KERNEL);
if (!trans_pcie->iml) {
@@ -249,27 +272,15 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
goto err_free_ctxt_info;
}
- memcpy(trans_pcie->iml, trans->iml, trans->iml_len);
-
- iwl_enable_fw_load_int_ctx_info(trans);
-
- /* kick FW self load */
- iwl_write64(trans, CSR_CTXT_INFO_ADDR,
- trans_pcie->ctxt_info_dma_addr);
- iwl_write64(trans, CSR_IML_DATA_ADDR,
- trans_pcie->iml_dma_addr);
- iwl_write32(trans, CSR_IML_SIZE_ADDR, trans->iml_len);
-
- iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL,
- CSR_AUTO_FUNC_BOOT_ENA);
+ memcpy(trans_pcie->iml, fw->iml, fw->iml_len);
return 0;
err_free_ctxt_info:
- dma_free_coherent(trans->dev, sizeof(*trans_pcie->ctxt_info_gen3),
- trans_pcie->ctxt_info_gen3,
+ dma_free_coherent(trans->dev, sizeof(*trans_pcie->ctxt_info_v2),
+ trans_pcie->ctxt_info_v2,
trans_pcie->ctxt_info_dma_addr);
- trans_pcie->ctxt_info_gen3 = NULL;
+ trans_pcie->ctxt_info_v2 = NULL;
err_free_prph_info:
dma_free_coherent(trans->dev, PAGE_SIZE, prph_info,
trans_pcie->prph_info_dma_addr);
@@ -283,14 +294,31 @@ err_free_prph_scratch:
}
-void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive)
+void iwl_pcie_ctxt_info_v2_kick(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ iwl_enable_fw_load_int_ctx_info(trans, trans->do_top_reset);
+
+ /* kick FW self load */
+ iwl_write64(trans, CSR_CTXT_INFO_ADDR, trans_pcie->ctxt_info_dma_addr);
+ iwl_write64(trans, CSR_IML_DATA_ADDR, trans_pcie->iml_dma_addr);
+ iwl_write32(trans, CSR_IML_SIZE_ADDR, trans_pcie->iml_len);
+
+ iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL,
+ CSR_AUTO_FUNC_BOOT_ENA);
+}
+
+void iwl_pcie_ctxt_info_v2_free(struct iwl_trans *trans, bool alive)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
if (trans_pcie->iml) {
- dma_free_coherent(trans->dev, trans->iml_len, trans_pcie->iml,
+ dma_free_coherent(trans->dev, trans_pcie->iml_len,
+ trans_pcie->iml,
trans_pcie->iml_dma_addr);
trans_pcie->iml_dma_addr = 0;
+ trans_pcie->iml_len = 0;
trans_pcie->iml = NULL;
}
@@ -299,15 +327,15 @@ void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive)
if (alive)
return;
- if (!trans_pcie->ctxt_info_gen3)
+ if (!trans_pcie->ctxt_info_v2)
return;
- /* ctxt_info_gen3 and prph_scratch are still needed for PNVM load */
- dma_free_coherent(trans->dev, sizeof(*trans_pcie->ctxt_info_gen3),
- trans_pcie->ctxt_info_gen3,
+ /* ctxt_info_v2 and prph_scratch are still needed for PNVM load */
+ dma_free_coherent(trans->dev, sizeof(*trans_pcie->ctxt_info_v2),
+ trans_pcie->ctxt_info_v2,
trans_pcie->ctxt_info_dma_addr);
trans_pcie->ctxt_info_dma_addr = 0;
- trans_pcie->ctxt_info_gen3 = NULL;
+ trans_pcie->ctxt_info_v2 = NULL;
dma_free_coherent(trans->dev, sizeof(*trans_pcie->prph_scratch),
trans_pcie->prph_scratch,
@@ -322,9 +350,9 @@ void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive)
trans_pcie->prph_info = NULL;
}
-static int iwl_pcie_load_payloads_continuously(struct iwl_trans *trans,
- const struct iwl_pnvm_image *pnvm_data,
- struct iwl_dram_data *dram)
+static int iwl_pcie_load_payloads_contig(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *pnvm_data,
+ struct iwl_dram_data *dram)
{
u32 len, len0, len1;
@@ -363,13 +391,13 @@ static int iwl_pcie_load_payloads_segments
{
struct iwl_dram_data *cur_payload_dram = &dram_regions->drams[0];
struct iwl_dram_data *desc_dram = &dram_regions->prph_scratch_mem_desc;
- struct iwl_prph_scrath_mem_desc_addr_array *addresses;
+ struct iwl_prph_scratch_mem_desc_addr_array *addresses;
const void *data;
u32 len;
int i;
/* allocate and init DRAM descriptors array */
- len = sizeof(struct iwl_prph_scrath_mem_desc_addr_array);
+ len = sizeof(struct iwl_prph_scratch_mem_desc_addr_array);
desc_dram->block = iwl_pcie_ctxt_info_dma_alloc_coherent
(trans,
len,
@@ -411,9 +439,9 @@ static int iwl_pcie_load_payloads_segments
}
-int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans,
- const struct iwl_pnvm_image *pnvm_payloads,
- const struct iwl_ucode_capabilities *capa)
+int iwl_trans_pcie_ctx_info_v2_load_pnvm(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *pnvm_payloads,
+ const struct iwl_ucode_capabilities *capa)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
@@ -428,7 +456,7 @@ int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans,
if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size))
return -EBUSY;
- if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
return 0;
if (!pnvm_payloads->n_chunks) {
@@ -445,10 +473,8 @@ int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans,
trans->pnvm_loaded = true;
} else {
/* save only in one DRAM section */
- ret = iwl_pcie_load_payloads_continuously
- (trans,
- pnvm_payloads,
- &dram_regions->drams[0]);
+ ret = iwl_pcie_load_payloads_contig(trans, pnvm_payloads,
+ &dram_regions->drams[0]);
if (!ret) {
dram_regions->n_regions = 1;
trans->pnvm_loaded = true;
@@ -483,7 +509,7 @@ static void iwl_pcie_set_pnvm_segments(struct iwl_trans *trans)
cpu_to_le32(iwl_dram_regions_size(dram_regions));
}
-static void iwl_pcie_set_continuous_pnvm(struct iwl_trans *trans)
+static void iwl_pcie_set_contig_pnvm(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
@@ -495,21 +521,21 @@ static void iwl_pcie_set_continuous_pnvm(struct iwl_trans *trans)
cpu_to_le32(trans_pcie->pnvm_data.drams[0].size);
}
-void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
- const struct iwl_ucode_capabilities *capa)
+void iwl_trans_pcie_ctx_info_v2_set_pnvm(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa)
{
- if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
return;
if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG))
iwl_pcie_set_pnvm_segments(trans);
else
- iwl_pcie_set_continuous_pnvm(trans);
+ iwl_pcie_set_contig_pnvm(trans);
}
-int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans,
- const struct iwl_pnvm_image *payloads,
- const struct iwl_ucode_capabilities *capa)
+int iwl_trans_pcie_ctx_info_v2_load_reduce_power(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *payloads,
+ const struct iwl_ucode_capabilities *capa)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
@@ -521,7 +547,7 @@ int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans,
if (trans->reduce_power_loaded)
return 0;
- if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
return 0;
if (WARN_ON(prph_sc_ctrl->reduce_power_cfg.size))
@@ -541,10 +567,8 @@ int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans,
trans->reduce_power_loaded = true;
} else {
/* save only in one DRAM section */
- ret = iwl_pcie_load_payloads_continuously
- (trans,
- payloads,
- &dram_regions->drams[0]);
+ ret = iwl_pcie_load_payloads_contig(trans, payloads,
+ &dram_regions->drams[0]);
if (!ret) {
dram_regions->n_regions = 1;
trans->reduce_power_loaded = true;
@@ -567,7 +591,7 @@ static void iwl_pcie_set_reduce_power_segments(struct iwl_trans *trans)
cpu_to_le32(iwl_dram_regions_size(dram_regions));
}
-static void iwl_pcie_set_continuous_reduce_power(struct iwl_trans *trans)
+static void iwl_pcie_set_contig_reduce_power(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
@@ -580,15 +604,15 @@ static void iwl_pcie_set_continuous_reduce_power(struct iwl_trans *trans)
}
void
-iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans,
- const struct iwl_ucode_capabilities *capa)
+iwl_trans_pcie_ctx_info_v2_set_reduce_power(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa)
{
- if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
return;
if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG))
iwl_pcie_set_reduce_power_segments(trans);
else
- iwl_pcie_set_continuous_reduce_power(trans);
+ iwl_pcie_set_contig_reduce_power(trans);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
index 344e4d5a1c6e..0957223c776d 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
@@ -1,12 +1,12 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2024 Intel Corporation
+ * Copyright (C) 2018-2025 Intel Corporation
*/
#include "iwl-trans.h"
#include "iwl-fh.h"
#include "iwl-context-info.h"
-#include "internal.h"
+#include "gen1_2/internal.h"
#include "iwl-prph.h"
static void *_iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans,
@@ -83,7 +83,7 @@ void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans)
int iwl_pcie_init_fw_sec(struct iwl_trans *trans,
const struct fw_img *fw,
- struct iwl_context_info_dram *ctxt_dram)
+ struct iwl_context_info_dram_nonfseq *ctxt_dram)
{
struct iwl_self_init_dram *dram = &trans->init_dram;
int i, ret, lmac_cnt, umac_cnt, paging_cnt;
@@ -161,12 +161,12 @@ int iwl_pcie_init_fw_sec(struct iwl_trans *trans,
}
int iwl_pcie_ctxt_info_init(struct iwl_trans *trans,
- const struct fw_img *fw)
+ const struct fw_img *img)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_context_info *ctxt_info;
struct iwl_context_info_rbd_cfg *rx_cfg;
- u32 control_flags = 0, rb_size;
+ u32 control_flags = 0, rb_size, cb_size;
dma_addr_t phys;
int ret;
@@ -180,11 +180,11 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans,
ctxt_info->version.version = 0;
ctxt_info->version.mac_id =
- cpu_to_le16((u16)trans->hw_rev);
+ cpu_to_le16((u16)trans->info.hw_rev);
/* size is in DWs */
ctxt_info->version.size = cpu_to_le16(sizeof(*ctxt_info) / 4);
- switch (trans_pcie->rx_buf_size) {
+ switch (trans->conf.rx_buf_size) {
case IWL_AMSDU_2K:
rb_size = IWL_CTXT_INFO_RB_SIZE_2K;
break;
@@ -202,11 +202,12 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans,
rb_size = IWL_CTXT_INFO_RB_SIZE_4K;
}
- WARN_ON(RX_QUEUE_CB_SIZE(trans->cfg->num_rbds) > 12);
+ cb_size = RX_QUEUE_CB_SIZE(iwl_trans_get_num_rbds(trans));
+ if (WARN_ON(cb_size > 12))
+ cb_size = 12;
+
control_flags = IWL_CTXT_INFO_TFD_FORMAT_LONG;
- control_flags |=
- u32_encode_bits(RX_QUEUE_CB_SIZE(trans->cfg->num_rbds),
- IWL_CTXT_INFO_RB_CB_SIZE);
+ control_flags |= u32_encode_bits(cb_size, IWL_CTXT_INFO_RB_CB_SIZE);
control_flags |= u32_encode_bits(rb_size, IWL_CTXT_INFO_RB_SIZE);
ctxt_info->control.control_flags = cpu_to_le32(control_flags);
@@ -218,12 +219,12 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans,
/* initialize TX command queue */
ctxt_info->hcmd_cfg.cmd_queue_addr =
- cpu_to_le64(trans_pcie->txqs.txq[trans_pcie->txqs.cmd.q_id]->dma_addr);
+ cpu_to_le64(trans_pcie->txqs.txq[trans->conf.cmd_queue]->dma_addr);
ctxt_info->hcmd_cfg.cmd_queue_size =
TFD_QUEUE_CB_SIZE(IWL_CMD_QUEUE_SIZE);
/* allocate ucode sections in dram and set addresses */
- ret = iwl_pcie_init_fw_sec(trans, fw, &ctxt_info->dram);
+ ret = iwl_pcie_init_fw_sec(trans, img, &ctxt_info->dram);
if (ret) {
dma_free_coherent(trans->dev, sizeof(*trans_pcie->ctxt_info),
ctxt_info, trans_pcie->ctxt_info_dma_addr);
@@ -232,7 +233,7 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans,
trans_pcie->ctxt_info = ctxt_info;
- iwl_enable_fw_load_int_ctx_info(trans);
+ iwl_enable_fw_load_int_ctx_info(trans, false);
/* Configure debug, if exists */
if (iwl_pcie_dbg_on(trans))
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 00056e76ea3d..dc99e7ac4726 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2005-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -15,17 +15,15 @@
#include "iwl-trans.h"
#include "iwl-drv.h"
#include "iwl-prph.h"
-#include "internal.h"
+#include "gen1_2/internal.h"
-#define TRANS_CFG_MARKER BIT(0)
#define _IS_A(cfg, _struct) __builtin_types_compatible_p(typeof(cfg), \
struct _struct)
extern int _invalid_type;
-#define _TRANS_CFG_MARKER(cfg) \
- (__builtin_choose_expr(_IS_A(cfg, iwl_cfg_trans_params), \
- TRANS_CFG_MARKER, \
- __builtin_choose_expr(_IS_A(cfg, iwl_cfg), 0, _invalid_type)))
-#define _ASSIGN_CFG(cfg) (_TRANS_CFG_MARKER(cfg) + (kernel_ulong_t)&(cfg))
+#define _TRANS_CFG_CHECK(cfg) \
+ (__builtin_choose_expr(_IS_A(cfg, iwl_mac_cfg), \
+ 0, _invalid_type))
+#define _ASSIGN_CFG(cfg) (_TRANS_CFG_CHECK(cfg) + (kernel_ulong_t)&(cfg))
#define IWL_PCI_DEVICE(dev, subdev, cfg) \
.vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
@@ -35,1356 +33,1068 @@ extern int _invalid_type;
/* Hardware specific file defines the PCI IDs table for that hardware module */
VISIBLE_IF_IWLWIFI_KUNIT const struct pci_device_id iwl_hw_card_ids[] = {
#if IS_ENABLED(CONFIG_IWLDVM)
- {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5000_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1304, iwl5000_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5000_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5000_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1221, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1321, iwl5000_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1224, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1324, iwl5000_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1225, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1325, iwl5000_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1226, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5000_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1211, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1311, iwl5000_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1214, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1314, iwl5000_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1215, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1315, iwl5000_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4237, 0x1316, iwl5000_mac_cfg)}, /* Half Mini Card */
/* 5300 Series WiFi */
- {IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1021, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1121, iwl5000_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1024, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1124, iwl5000_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1001, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1101, iwl5000_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1004, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4235, 0x1104, iwl5000_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4236, 0x1011, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4236, 0x1111, iwl5000_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x4236, 0x1014, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x4236, 0x1114, iwl5000_mac_cfg)}, /* Half Mini Card */
/* 5350 Series WiFi/WiMax */
- {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5000_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5000_mac_cfg)}, /* Mini Card */
/* 5150 Series Wifi/WiMax */
- {IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x423C, 0x1326, iwl5150_abg_cfg)}, /* Half Mini Card */
-
- {IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */
- {IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */
- {IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x423C, 0x1326, iwl5150_mac_cfg)}, /* Half Mini Card */
+
+ {IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_mac_cfg)}, /* Half Mini Card */
+ {IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_mac_cfg)}, /* Mini Card */
+ {IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_mac_cfg)}, /* Half Mini Card */
/* 6x00 Series */
- {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
- {IWL_PCI_DEVICE(0x422B, 0x1108, iwl6000_3agn_cfg)},
- {IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
- {IWL_PCI_DEVICE(0x422B, 0x1128, iwl6000_3agn_cfg)},
- {IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},
- {IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)},
- {IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)},
- {IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)},
- {IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)},
- {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
- {IWL_PCI_DEVICE(0x4238, 0x1118, iwl6000_3agn_cfg)},
- {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
- {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x422B, 0x1108, iwl6000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x422B, 0x1128, iwl6000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_mac_cfg)},
+ {IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_mac_cfg)},
+ {IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_mac_cfg)},
+ {IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_mac_cfg)},
+ {IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_mac_cfg)},
+ {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x4238, 0x1118, iwl6000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_mac_cfg)},
+ {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_mac_cfg)},
/* 6x05 Series */
- {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1308, iwl6005_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1328, iwl6005_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0085, 0x1318, iwl6005_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_2agn_sff_cfg)},
- {IWL_PCI_DEVICE(0x0085, 0xC220, iwl6005_2agn_sff_cfg)},
- {IWL_PCI_DEVICE(0x0085, 0xC228, iwl6005_2agn_sff_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x4820, iwl6005_2agn_d_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1304, iwl6005_2agn_mow1_cfg)},/* low 5GHz active */
- {IWL_PCI_DEVICE(0x0082, 0x1305, iwl6005_2agn_mow2_cfg)},/* high 5GHz active */
-
-/* 6x30 Series */
- {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)},
- {IWL_PCI_DEVICE(0x008A, 0x5307, iwl1030_bg_cfg)},
- {IWL_PCI_DEVICE(0x008A, 0x5325, iwl1030_bgn_cfg)},
- {IWL_PCI_DEVICE(0x008A, 0x5327, iwl1030_bg_cfg)},
- {IWL_PCI_DEVICE(0x008B, 0x5315, iwl1030_bgn_cfg)},
- {IWL_PCI_DEVICE(0x008B, 0x5317, iwl1030_bg_cfg)},
- {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5201, iwl6030_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5205, iwl6030_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5206, iwl6030_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5207, iwl6030_2bg_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5221, iwl6030_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5225, iwl6030_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0091, 0x5226, iwl6030_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1308, iwl6005_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1328, iwl6005_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0085, 0x1318, iwl6005_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0085, 0xC220, iwl6005_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0085, 0xC228, iwl6005_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x4820, iwl6005_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1304, iwl6005_mac_cfg)},/* low 5GHz active */
+ {IWL_PCI_DEVICE(0x0082, 0x1305, iwl6005_mac_cfg)},/* high 5GHz active */
+
+/* 1030/6x30 Series */
+ {IWL_PCI_DEVICE(0x008A, 0x5305, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x008A, 0x5307, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x008A, 0x5325, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x008A, 0x5327, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x008B, 0x5315, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x008B, 0x5317, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5201, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5205, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5206, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5207, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5221, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5225, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0091, 0x5226, iwl6030_mac_cfg)},
/* 6x50 WiFi/WiMax Series */
- {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)},
- {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_mac_cfg)},
/* 6150 WiFi/WiMax Series */
- {IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0885, 0x1307, iwl6150_bg_cfg)},
- {IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0885, 0x1327, iwl6150_bg_cfg)},
- {IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0886, 0x1317, iwl6150_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0885, 0x1307, iwl6150_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0885, 0x1327, iwl6150_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0886, 0x1317, iwl6150_mac_cfg)},
/* 1000 Series WiFi */
- {IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1225, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1325, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0084, 0x1215, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0084, 0x1315, iwl1000_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1206, iwl1000_bg_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1306, iwl1000_bg_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1226, iwl1000_bg_cfg)},
- {IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)},
- {IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)},
- {IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1225, iwl1000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1325, iwl1000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0084, 0x1215, iwl1000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0084, 0x1315, iwl1000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1206, iwl1000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1306, iwl1000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1226, iwl1000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_mac_cfg)},
/* 100 Series WiFi */
- {IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
- {IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
- {IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
- {IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)},
- {IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
- {IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)},
+ {IWL_PCI_DEVICE(0x08AE, 0x1005, iwl1000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08AE, 0x1007, iwl1000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08AF, 0x1015, iwl1000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08AF, 0x1017, iwl1000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08AE, 0x1025, iwl1000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08AE, 0x1027, iwl1000_mac_cfg)},
/* 130 Series WiFi */
- {IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0896, 0x5007, iwl130_bg_cfg)},
- {IWL_PCI_DEVICE(0x0897, 0x5015, iwl130_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0897, 0x5017, iwl130_bg_cfg)},
- {IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0896, 0x5005, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0896, 0x5007, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0897, 0x5015, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0897, 0x5017, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0896, 0x5025, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0896, 0x5027, iwl6030_mac_cfg)},
/* 2x00 Series */
- {IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0890, 0x4822, iwl2000_2bgn_d_cfg)},
+ {IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0890, 0x4822, iwl2000_mac_cfg)},
/* 2x30 Series */
- {IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_2bgn_cfg)},
- {IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_2bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_mac_cfg)},
/* 6x35 Series */
- {IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
- {IWL_PCI_DEVICE(0x088E, 0x406A, iwl6035_2agn_sff_cfg)},
- {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
- {IWL_PCI_DEVICE(0x088F, 0x426A, iwl6035_2agn_sff_cfg)},
- {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
- {IWL_PCI_DEVICE(0x088E, 0x446A, iwl6035_2agn_sff_cfg)},
- {IWL_PCI_DEVICE(0x088E, 0x4860, iwl6035_2agn_cfg)},
- {IWL_PCI_DEVICE(0x088F, 0x5260, iwl6035_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x4060, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x406A, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x088F, 0x426A, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x446A, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x4860, iwl6030_mac_cfg)},
+ {IWL_PCI_DEVICE(0x088F, 0x5260, iwl6030_mac_cfg)},
/* 105 Series */
- {IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0895, 0x0222, iwl105_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0894, 0x0422, iwl105_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0894, 0x0822, iwl105_bgn_d_cfg)},
+ {IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0895, 0x0222, iwl105_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0894, 0x0422, iwl105_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0894, 0x0822, iwl105_mac_cfg)},
/* 135 Series */
- {IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0893, 0x0262, iwl135_bgn_cfg)},
- {IWL_PCI_DEVICE(0x0892, 0x0462, iwl135_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0893, 0x0262, iwl135_mac_cfg)},
+ {IWL_PCI_DEVICE(0x0892, 0x0462, iwl135_mac_cfg)},
#endif /* CONFIG_IWLDVM */
#if IS_ENABLED(CONFIG_IWLMVM)
/* 7260 Series */
- {IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x4072, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x4C60, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x4C70, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x4060, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x406A, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x4160, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x4062, iwl7260_n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x4162, iwl7260_n_cfg)},
- {IWL_PCI_DEVICE(0x08B2, 0x4270, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B2, 0x4272, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B2, 0x4260, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B2, 0x426A, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B2, 0x4262, iwl7260_n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x4470, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x4472, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x4460, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x446A, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x4462, iwl7260_n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x4870, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x486E, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7260_2ac_cfg_high_temp)},
- {IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7260_2ac_cfg_high_temp)},
- {IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7260_2ac_cfg_high_temp)},
- {IWL_PCI_DEVICE(0x08B1, 0x4570, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x4560, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B2, 0x4370, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B2, 0x4360, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x5070, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x5072, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x5170, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x5770, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x402A, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0x4420, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC070, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC072, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC170, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC060, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC06A, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC160, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC062, iwl7260_n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC162, iwl7260_n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC770, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC760, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B2, 0xC270, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xCC70, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xCC60, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B2, 0xC272, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B2, 0xC260, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B2, 0xC26A, iwl7260_n_cfg)},
- {IWL_PCI_DEVICE(0x08B2, 0xC262, iwl7260_n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC470, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC472, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC460, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC462, iwl7260_n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC570, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC560, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B2, 0xC370, iwl7260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC360, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC020, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC02A, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B2, 0xC220, iwl7260_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B1, 0xC420, iwl7260_2n_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4072, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4C60, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4C70, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4060, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x406A, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4160, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4062, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4162, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0x4270, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0x4272, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0x4260, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0x426A, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0x4262, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4470, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4472, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4460, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x446A, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4462, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4870, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x486E, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4570, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4560, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0x4370, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0x4360, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x5070, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x5072, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x5170, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x5770, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x402A, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0x4420, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC070, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC072, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC170, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC060, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC06A, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC160, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC062, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC162, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC770, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC760, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0xC270, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xCC70, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xCC60, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0xC272, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0xC260, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0xC26A, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0xC262, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC470, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC472, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC460, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC462, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC570, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC560, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0xC370, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC360, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC020, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC02A, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B2, 0xC220, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B1, 0xC420, iwl7000_mac_cfg)},
/* 3160 Series */
- {IWL_PCI_DEVICE(0x08B3, 0x0070, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B3, 0x0072, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B3, 0x0170, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B3, 0x0172, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B3, 0x0060, iwl3160_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B3, 0x0062, iwl3160_n_cfg)},
- {IWL_PCI_DEVICE(0x08B4, 0x0270, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B4, 0x0272, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B3, 0x0470, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B3, 0x0472, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B4, 0x0370, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B3, 0x8070, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B3, 0x8072, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B3, 0x8170, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B3, 0x8172, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B3, 0x8060, iwl3160_2n_cfg)},
- {IWL_PCI_DEVICE(0x08B3, 0x8062, iwl3160_n_cfg)},
- {IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B4, 0x8370, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B4, 0x8272, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B3, 0x8570, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B3, 0x1070, iwl3160_2ac_cfg)},
- {IWL_PCI_DEVICE(0x08B3, 0x1170, iwl3160_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x0070, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x0072, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x0170, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x0172, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x0060, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x0062, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B4, 0x0270, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B4, 0x0272, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x0470, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x0472, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B4, 0x0370, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x8070, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x8072, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x8170, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x8172, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x8060, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x8062, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B4, 0x8270, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B4, 0x8370, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B4, 0x8272, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x8470, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x8570, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x1070, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x08B3, 0x1170, iwl7000_mac_cfg)},
/* 3165 Series */
- {IWL_PCI_DEVICE(0x3165, 0x4010, iwl3165_2ac_cfg)},
- {IWL_PCI_DEVICE(0x3165, 0x4012, iwl3165_2ac_cfg)},
- {IWL_PCI_DEVICE(0x3166, 0x4212, iwl3165_2ac_cfg)},
- {IWL_PCI_DEVICE(0x3165, 0x4410, iwl3165_2ac_cfg)},
- {IWL_PCI_DEVICE(0x3165, 0x4510, iwl3165_2ac_cfg)},
- {IWL_PCI_DEVICE(0x3165, 0x4110, iwl3165_2ac_cfg)},
- {IWL_PCI_DEVICE(0x3166, 0x4310, iwl3165_2ac_cfg)},
- {IWL_PCI_DEVICE(0x3166, 0x4210, iwl3165_2ac_cfg)},
- {IWL_PCI_DEVICE(0x3165, 0x8010, iwl3165_2ac_cfg)},
- {IWL_PCI_DEVICE(0x3165, 0x8110, iwl3165_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x3165, 0x4010, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x3165, 0x4012, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x3166, 0x4212, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x3165, 0x4410, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x3165, 0x4510, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x3165, 0x4110, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x3166, 0x4310, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x3166, 0x4210, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x3165, 0x8010, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x3165, 0x8110, iwl7000_mac_cfg)},
/* 3168 Series */
- {IWL_PCI_DEVICE(0x24FB, 0x2010, iwl3168_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FB, 0x2110, iwl3168_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FB, 0x2050, iwl3168_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FB, 0x2150, iwl3168_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FB, 0x0000, iwl3168_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x24FB, 0x2010, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FB, 0x2110, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FB, 0x2050, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FB, 0x2150, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FB, 0x0000, iwl7000_mac_cfg)},
/* 7265 Series */
- {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5110, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5100, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095B, 0x5310, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095B, 0x5302, iwl7265_n_cfg)},
- {IWL_PCI_DEVICE(0x095B, 0x5210, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5C10, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5012, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5412, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5410, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5510, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5400, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x1010, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5000, iwl7265_2n_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2n_cfg)},
- {IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5102, iwl7265_n_cfg)},
- {IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x9012, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x900A, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095B, 0x9210, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095B, 0x9200, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095B, 0x9310, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5020, iwl7265_2n_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x502A, iwl7265_2n_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5420, iwl7265_2n_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5090, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5190, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5590, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095B, 0x5290, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5490, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x5F10, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095B, 0x5212, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095B, 0x520A, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x9000, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x9400, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x9E10, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5110, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5100, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x5310, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x5302, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x5210, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5C10, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5012, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5412, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5410, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5510, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5400, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x1010, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5000, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x500A, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x5200, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5002, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5102, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x5202, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9010, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9012, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x900A, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9110, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9112, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x9210, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x9200, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9510, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x9310, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9410, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5020, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x502A, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5420, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5090, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5190, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5590, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x5290, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5490, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5F10, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x5212, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x520A, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9000, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9400, iwl7000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9E10, iwl7000_mac_cfg)},
/* 8000 Series */
- {IWL_PCI_DEVICE(0x24F3, 0x0010, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x1010, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x10B0, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x0130, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x1130, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x0132, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x1132, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x0110, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x01F0, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x0012, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x1012, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x1110, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x0050, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x0250, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x1050, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x0150, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x1150, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F4, 0x0030, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F4, 0x1030, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0xC010, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0xC110, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0xD010, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0xC050, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0xD050, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0xD0B0, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0xB0B0, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x8010, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x8110, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x9010, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x9110, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F4, 0x8030, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F4, 0x9030, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F4, 0xC030, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F4, 0xD030, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x8130, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x9130, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x8132, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x9132, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x8050, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x8150, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x9050, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x9150, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x0004, iwl8260_2n_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x0044, iwl8260_2n_cfg)},
- {IWL_PCI_DEVICE(0x24F5, 0x0010, iwl4165_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F6, 0x0030, iwl4165_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x0810, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x0910, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x0850, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x0950, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x0930, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x0000, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F3, 0x4010, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x0010, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x0110, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x1110, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x1130, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x0130, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x1010, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x10D0, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x0050, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x0150, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x9010, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x8110, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x8050, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x8010, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x0810, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x9110, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x8130, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x0910, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x0930, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x0950, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x0850, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x1014, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x3E02, iwl8275_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x3E01, iwl8275_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x1012, iwl8275_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x0012, iwl8275_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x0014, iwl8265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24FD, 0x9074, iwl8265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x0010, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x1010, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x10B0, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x0130, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x1130, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x0132, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x1132, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x0110, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x01F0, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x0012, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x1012, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x1110, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x0050, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x0250, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x1050, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x0150, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x1150, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F4, 0x0030, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F4, 0x1030, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0xC010, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0xC110, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0xD010, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0xC050, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0xD050, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0xD0B0, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0xB0B0, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x8010, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x8110, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x9010, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x9110, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F4, 0x8030, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F4, 0x9030, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F4, 0xC030, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F4, 0xD030, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x8130, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x9130, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x8132, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x9132, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x8050, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x8150, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x9050, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x9150, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x0004, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x0044, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F5, 0x0010, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F6, 0x0030, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x0810, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x0910, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x0850, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x0950, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x0930, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x0000, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0x4010, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0xC030, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0xD030, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x0010, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x0110, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x1110, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x1130, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x0130, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x1010, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x10D0, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x0050, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x0150, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x9010, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x8110, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x8050, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x8010, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x0810, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x9110, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x8130, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x0910, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x0930, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x0950, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x0850, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x1014, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x3E02, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x3E01, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x1012, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x0012, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x0014, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x9074, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x1431, iwl8000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x1432, iwl8000_mac_cfg)},
/* 9000 Series */
- {IWL_PCI_DEVICE(0x2526, PCI_ANY_ID, iwl9000_trans_cfg)},
- {IWL_PCI_DEVICE(0x271B, PCI_ANY_ID, iwl9000_trans_cfg)},
- {IWL_PCI_DEVICE(0x271C, PCI_ANY_ID, iwl9000_trans_cfg)},
- {IWL_PCI_DEVICE(0x30DC, PCI_ANY_ID, iwl9560_long_latency_trans_cfg)},
- {IWL_PCI_DEVICE(0x31DC, PCI_ANY_ID, iwl9560_shared_clk_trans_cfg)},
- {IWL_PCI_DEVICE(0x9DF0, PCI_ANY_ID, iwl9560_trans_cfg)},
- {IWL_PCI_DEVICE(0xA370, PCI_ANY_ID, iwl9560_trans_cfg)},
+ {IWL_PCI_DEVICE(0x2526, PCI_ANY_ID, iwl9000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x271B, PCI_ANY_ID, iwl9000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x271C, PCI_ANY_ID, iwl9000_mac_cfg)},
+ {IWL_PCI_DEVICE(0x30DC, PCI_ANY_ID, iwl9560_long_latency_mac_cfg)},
+ {IWL_PCI_DEVICE(0x31DC, PCI_ANY_ID, iwl9560_shared_clk_mac_cfg)},
+ {IWL_PCI_DEVICE(0x9DF0, PCI_ANY_ID, iwl9560_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA370, PCI_ANY_ID, iwl9560_mac_cfg)},
/* Qu devices */
- {IWL_PCI_DEVICE(0x02F0, PCI_ANY_ID, iwl_qu_trans_cfg)},
- {IWL_PCI_DEVICE(0x06F0, PCI_ANY_ID, iwl_qu_trans_cfg)},
+ {IWL_PCI_DEVICE(0x02F0, PCI_ANY_ID, iwl_qu_mac_cfg)},
+ {IWL_PCI_DEVICE(0x06F0, PCI_ANY_ID, iwl_qu_mac_cfg)},
- {IWL_PCI_DEVICE(0x34F0, PCI_ANY_ID, iwl_qu_medium_latency_trans_cfg)},
- {IWL_PCI_DEVICE(0x3DF0, PCI_ANY_ID, iwl_qu_medium_latency_trans_cfg)},
- {IWL_PCI_DEVICE(0x4DF0, PCI_ANY_ID, iwl_qu_medium_latency_trans_cfg)},
+ {IWL_PCI_DEVICE(0x34F0, PCI_ANY_ID, iwl_qu_medium_latency_mac_cfg)},
+ {IWL_PCI_DEVICE(0x3DF0, PCI_ANY_ID, iwl_qu_medium_latency_mac_cfg)},
+ {IWL_PCI_DEVICE(0x4DF0, PCI_ANY_ID, iwl_qu_medium_latency_mac_cfg)},
- {IWL_PCI_DEVICE(0x43F0, PCI_ANY_ID, iwl_qu_long_latency_trans_cfg)},
- {IWL_PCI_DEVICE(0xA0F0, PCI_ANY_ID, iwl_qu_long_latency_trans_cfg)},
+ {IWL_PCI_DEVICE(0x43F0, PCI_ANY_ID, iwl_qu_long_latency_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA0F0, PCI_ANY_ID, iwl_qu_long_latency_mac_cfg)},
- {IWL_PCI_DEVICE(0x2723, PCI_ANY_ID, iwl_ax200_trans_cfg)},
+ {IWL_PCI_DEVICE(0x2723, PCI_ANY_ID, iwl_ax200_mac_cfg)},
-/* So devices */
- {IWL_PCI_DEVICE(0x2725, PCI_ANY_ID, iwl_so_trans_cfg)},
- {IWL_PCI_DEVICE(0x7A70, PCI_ANY_ID, iwl_so_long_latency_imr_trans_cfg)},
- {IWL_PCI_DEVICE(0x7AF0, PCI_ANY_ID, iwl_so_trans_cfg)},
- {IWL_PCI_DEVICE(0x51F0, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)},
- {IWL_PCI_DEVICE(0x51F1, PCI_ANY_ID, iwl_so_long_latency_imr_trans_cfg)},
- {IWL_PCI_DEVICE(0x54F0, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)},
- {IWL_PCI_DEVICE(0x7F70, PCI_ANY_ID, iwl_so_trans_cfg)},
+/* Ty/So devices */
+ {IWL_PCI_DEVICE(0x2725, PCI_ANY_ID, iwl_ty_mac_cfg)},
+ {IWL_PCI_DEVICE(0x7A70, PCI_ANY_ID, iwl_so_long_latency_imr_mac_cfg)},
+ {IWL_PCI_DEVICE(0x7AF0, PCI_ANY_ID, iwl_so_mac_cfg)},
+ {IWL_PCI_DEVICE(0x51F0, PCI_ANY_ID, iwl_so_long_latency_mac_cfg)},
+ {IWL_PCI_DEVICE(0x51F1, PCI_ANY_ID, iwl_so_long_latency_imr_mac_cfg)},
+ {IWL_PCI_DEVICE(0x54F0, PCI_ANY_ID, iwl_so_long_latency_mac_cfg)},
+ {IWL_PCI_DEVICE(0x7F70, PCI_ANY_ID, iwl_so_mac_cfg)},
/* Ma devices */
- {IWL_PCI_DEVICE(0x2729, PCI_ANY_ID, iwl_ma_trans_cfg)},
- {IWL_PCI_DEVICE(0x7E40, PCI_ANY_ID, iwl_ma_trans_cfg)},
+ {IWL_PCI_DEVICE(0x2729, PCI_ANY_ID, iwl_ma_mac_cfg)},
+ {IWL_PCI_DEVICE(0x7E40, PCI_ANY_ID, iwl_ma_mac_cfg)},
#endif /* CONFIG_IWLMVM */
-#if IS_ENABLED(CONFIG_IWLMLD)
+#if IS_ENABLED(CONFIG_IWLMVM) || IS_ENABLED(CONFIG_IWLMLD)
/* Bz devices */
- {IWL_PCI_DEVICE(0x272b, PCI_ANY_ID, iwl_gl_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x0000, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x0090, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x0094, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x0098, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x009C, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x00C0, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x00C4, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x00E0, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x00E4, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x00E8, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x00EC, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x0100, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x0110, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x0114, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x0118, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x011C, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x0310, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x0314, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x0510, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x0A10, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x1671, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x1672, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x1771, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x1772, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x1791, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x1792, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x4090, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x40C4, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x40E0, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x4110, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0xA840, 0x4314, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0x7740, PCI_ANY_ID, iwl_bz_trans_cfg)},
- {IWL_PCI_DEVICE(0x4D40, PCI_ANY_ID, iwl_bz_trans_cfg)},
+ {IWL_PCI_DEVICE(0x272b, PCI_ANY_ID, iwl_gl_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x0000, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x0090, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x0094, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x0098, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x009C, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x00C0, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x00C4, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x00E0, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x00E4, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x00E8, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x00EC, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x0100, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x0110, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x0114, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x0118, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x011C, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x0310, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x0314, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x0510, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x0A10, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x1671, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x1672, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x1771, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x1772, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x1791, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x1792, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x4090, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x40C4, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x40E0, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x4110, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x4314, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x1775, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0xA840, 0x1776, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0x7740, PCI_ANY_ID, iwl_bz_mac_cfg)},
+ {IWL_PCI_DEVICE(0x4D40, PCI_ANY_ID, iwl_bz_mac_cfg)},
/* Sc devices */
- {IWL_PCI_DEVICE(0xE440, PCI_ANY_ID, iwl_sc_trans_cfg)},
- {IWL_PCI_DEVICE(0xE340, PCI_ANY_ID, iwl_sc_trans_cfg)},
- {IWL_PCI_DEVICE(0xD340, PCI_ANY_ID, iwl_sc_trans_cfg)},
- {IWL_PCI_DEVICE(0x6E70, PCI_ANY_ID, iwl_sc_trans_cfg)},
-
-/* Dr devices */
- {IWL_PCI_DEVICE(0x272F, PCI_ANY_ID, iwl_dr_trans_cfg)},
-#endif /* CONFIG_IWLMLD */
+ {IWL_PCI_DEVICE(0xE440, PCI_ANY_ID, iwl_sc_mac_cfg)},
+ {IWL_PCI_DEVICE(0xE340, PCI_ANY_ID, iwl_sc_mac_cfg)},
+ {IWL_PCI_DEVICE(0xD340, PCI_ANY_ID, iwl_sc_mac_cfg)},
+ {IWL_PCI_DEVICE(0x6E70, PCI_ANY_ID, iwl_sc_mac_cfg)},
+ {IWL_PCI_DEVICE(0xD240, PCI_ANY_ID, iwl_sc_mac_cfg)},
+#endif /* CONFIG_IWLMVM || CONFIG_IWLMLD */
{0}
};
MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_hw_card_ids);
-#define _IWL_DEV_INFO(_device, _subdevice, _mac_type, _mac_step, _rf_type, \
- _rf_id, _rf_step, _no_160, _cores, _cdb, _cfg, _name) \
- { .device = (_device), .subdevice = (_subdevice), .cfg = &(_cfg), \
- .name = _name, .mac_type = _mac_type, .rf_type = _rf_type, .rf_step = _rf_step, \
- .no_160 = _no_160, .cores = _cores, .rf_id = _rf_id, \
- .mac_step = _mac_step, .cdb = _cdb, .jacket = IWL_CFG_ANY }
-
-#define IWL_DEV_INFO(_device, _subdevice, _cfg, _name) \
- _IWL_DEV_INFO(_device, _subdevice, IWL_CFG_ANY, IWL_CFG_ANY, \
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, \
- IWL_CFG_ANY, _cfg, _name)
+#define _IWL_DEV_INFO(_cfg, _name, ...) { \
+ .cfg = &_cfg, \
+ .name = _name, \
+ .device = IWL_CFG_ANY, \
+ .subdevice = IWL_CFG_ANY, \
+ .subdevice_m_h = 15, \
+ __VA_ARGS__ \
+}
+#define IWL_DEV_INFO(_cfg, _name, ...) \
+ _IWL_DEV_INFO(_cfg, _name, __VA_ARGS__)
+
+#define DEVICE(n) .device = (n)
+#define SUBDEV(n) .subdevice = (n)
+#define _LOWEST_BIT(n) (__builtin_ffs(n) - 1)
+#define _BIT_ABOVE_MASK(n) ((n) + (1 << _LOWEST_BIT(n)))
+#define _HIGHEST_BIT(n) (__builtin_ffs(_BIT_ABOVE_MASK(n)) - 2)
+#define _IS_POW2(n) (((n) & ((n) - 1)) == 0)
+#define _IS_CONTIG(n) _IS_POW2(_BIT_ABOVE_MASK(n))
+#define _CHECK_MASK(m) BUILD_BUG_ON_ZERO(!_IS_CONTIG(m))
+#define SUBDEV_MASKED(v, m) .subdevice = (v) + _CHECK_MASK(m), \
+ .subdevice_m_l = _LOWEST_BIT(m), \
+ .subdevice_m_h = _HIGHEST_BIT(m)
+#define RF_TYPE(n) .match_rf_type = 1, \
+ .rf_type = IWL_CFG_RF_TYPE_##n
+#define DISCRETE .match_discrete = 1, \
+ .discrete = 1
+#define INTEGRATED .match_discrete = 1, \
+ .discrete = 0
+#define RF_ID(n) .match_rf_id = 1, \
+ .rf_id = IWL_CFG_RF_ID_##n
+#define NO_CDB .match_cdb = 1, .cdb = 0
+#define CDB .match_cdb = 1, .cdb = 1
+#define BW_NOT_LIMITED .match_bw_limit = 1, .bw_limit = 0
+#define BW_LIMITED .match_bw_limit = 1, .bw_limit = 1
VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = {
-#if IS_ENABLED(CONFIG_IWLMVM)
-/* 9000 */
- IWL_DEV_INFO(0x2526, 0x1550, iwl9260_2ac_cfg, iwl9260_killer_1550_name),
- IWL_DEV_INFO(0x2526, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_name),
- IWL_DEV_INFO(0x2526, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name),
- IWL_DEV_INFO(0x30DC, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_name),
- IWL_DEV_INFO(0x30DC, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name),
- IWL_DEV_INFO(0x31DC, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_name),
- IWL_DEV_INFO(0x31DC, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name),
- IWL_DEV_INFO(0xA370, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_name),
- IWL_DEV_INFO(0xA370, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name),
- IWL_DEV_INFO(0x54F0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name),
- IWL_DEV_INFO(0x54F0, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name),
- IWL_DEV_INFO(0x51F0, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name),
- IWL_DEV_INFO(0x51F0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name),
- IWL_DEV_INFO(0x51F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
- IWL_DEV_INFO(0x51F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
- IWL_DEV_INFO(0x51F1, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
- IWL_DEV_INFO(0x54F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
- IWL_DEV_INFO(0x54F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
- IWL_DEV_INFO(0x7A70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
- IWL_DEV_INFO(0x7A70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
- IWL_DEV_INFO(0x7AF0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
- IWL_DEV_INFO(0x7AF0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
- IWL_DEV_INFO(0x7F70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
- IWL_DEV_INFO(0x7F70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
-
- IWL_DEV_INFO(0x271C, 0x0214, iwl9260_2ac_cfg, iwl9260_1_name),
- IWL_DEV_INFO(0x7E40, 0x1691, iwl_cfg_ma, iwl_ax411_killer_1690s_name),
- IWL_DEV_INFO(0x7E40, 0x1692, iwl_cfg_ma, iwl_ax411_killer_1690i_name),
-
-/* AX200 */
- IWL_DEV_INFO(0x2723, IWL_CFG_ANY, iwl_ax200_cfg_cc, iwl_ax200_name),
- IWL_DEV_INFO(0x2723, 0x1653, iwl_ax200_cfg_cc, iwl_ax200_killer_1650w_name),
- IWL_DEV_INFO(0x2723, 0x1654, iwl_ax200_cfg_cc, iwl_ax200_killer_1650x_name),
-
- /* Qu with Hr */
- IWL_DEV_INFO(0x43F0, 0x0070, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x43F0, 0x0074, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x43F0, 0x0078, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x43F0, 0x007C, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x43F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, iwl_ax201_killer_1650s_name),
- IWL_DEV_INFO(0x43F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, iwl_ax201_killer_1650i_name),
- IWL_DEV_INFO(0x43F0, 0x2074, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x43F0, 0x4070, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0xA0F0, 0x0070, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0xA0F0, 0x0074, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0xA0F0, 0x0078, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0xA0F0, 0x007C, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0xA0F0, 0x0A10, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0xA0F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, NULL),
- IWL_DEV_INFO(0xA0F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, NULL),
- IWL_DEV_INFO(0xA0F0, 0x2074, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0xA0F0, 0x4070, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0xA0F0, 0x6074, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x02F0, 0x0070, iwl_ax201_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x02F0, 0x0074, iwl_ax201_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x02F0, 0x6074, iwl_ax201_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x02F0, 0x0078, iwl_ax201_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x02F0, 0x007C, iwl_ax201_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x02F0, 0x0310, iwl_ax201_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x02F0, 0x1651, iwl_ax1650s_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x02F0, 0x1652, iwl_ax1650i_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x02F0, 0x2074, iwl_ax201_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x02F0, 0x4070, iwl_ax201_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x06F0, 0x0070, iwl_ax201_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x06F0, 0x0074, iwl_ax201_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x06F0, 0x0078, iwl_ax201_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x06F0, 0x007C, iwl_ax201_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x06F0, 0x0310, iwl_ax201_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x06F0, 0x1651, iwl_ax1650s_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x06F0, 0x1652, iwl_ax1650i_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x06F0, 0x2074, iwl_ax201_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x06F0, 0x4070, iwl_ax201_cfg_quz_hr, NULL),
- IWL_DEV_INFO(0x34F0, 0x0070, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x34F0, 0x0074, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x34F0, 0x0078, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x34F0, 0x007C, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x34F0, 0x0310, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x34F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, NULL),
- IWL_DEV_INFO(0x34F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, NULL),
- IWL_DEV_INFO(0x34F0, 0x2074, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x34F0, 0x4070, iwl_ax201_cfg_qu_hr, NULL),
-
- IWL_DEV_INFO(0x3DF0, 0x0070, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x3DF0, 0x0074, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x3DF0, 0x0078, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x3DF0, 0x007C, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x3DF0, 0x0310, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x3DF0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, NULL),
- IWL_DEV_INFO(0x3DF0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, NULL),
- IWL_DEV_INFO(0x3DF0, 0x2074, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x3DF0, 0x4070, iwl_ax201_cfg_qu_hr, NULL),
-
- IWL_DEV_INFO(0x4DF0, 0x0070, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x4DF0, 0x0074, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x4DF0, 0x0078, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x4DF0, 0x007C, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x4DF0, 0x0310, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x4DF0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, NULL),
- IWL_DEV_INFO(0x4DF0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, NULL),
- IWL_DEV_INFO(0x4DF0, 0x2074, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x4DF0, 0x4070, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x4DF0, 0x6074, iwl_ax201_cfg_qu_hr, NULL),
-
- /* So with HR */
- IWL_DEV_INFO(0x2725, 0x0090, iwlax211_2ax_cfg_so_gf_a0, NULL),
- IWL_DEV_INFO(0x2725, 0x0020, iwlax210_2ax_cfg_ty_gf_a0, NULL),
- IWL_DEV_INFO(0x2725, 0x2020, iwlax210_2ax_cfg_ty_gf_a0, NULL),
- IWL_DEV_INFO(0x2725, 0x0024, iwlax210_2ax_cfg_ty_gf_a0, NULL),
- IWL_DEV_INFO(0x2725, 0x0310, iwlax210_2ax_cfg_ty_gf_a0, NULL),
- IWL_DEV_INFO(0x2725, 0x0510, iwlax210_2ax_cfg_ty_gf_a0, NULL),
- IWL_DEV_INFO(0x2725, 0x0A10, iwlax210_2ax_cfg_ty_gf_a0, NULL),
- IWL_DEV_INFO(0x2725, 0xE020, iwlax210_2ax_cfg_ty_gf_a0, NULL),
- IWL_DEV_INFO(0x2725, 0xE024, iwlax210_2ax_cfg_ty_gf_a0, NULL),
- IWL_DEV_INFO(0x2725, 0x4020, iwlax210_2ax_cfg_ty_gf_a0, NULL),
- IWL_DEV_INFO(0x2725, 0x6020, iwlax210_2ax_cfg_ty_gf_a0, NULL),
- IWL_DEV_INFO(0x2725, 0x6024, iwlax210_2ax_cfg_ty_gf_a0, NULL),
- IWL_DEV_INFO(0x2725, 0x1673, iwlax210_2ax_cfg_ty_gf_a0, iwl_ax210_killer_1675w_name),
- IWL_DEV_INFO(0x2725, 0x1674, iwlax210_2ax_cfg_ty_gf_a0, iwl_ax210_killer_1675x_name),
- IWL_DEV_INFO(0x7A70, 0x0090, iwlax211_2ax_cfg_so_gf_a0_long, NULL),
- IWL_DEV_INFO(0x7A70, 0x0098, iwlax211_2ax_cfg_so_gf_a0_long, NULL),
- IWL_DEV_INFO(0x7A70, 0x00B0, iwlax411_2ax_cfg_so_gf4_a0_long, NULL),
- IWL_DEV_INFO(0x7A70, 0x0310, iwlax211_2ax_cfg_so_gf_a0_long, NULL),
- IWL_DEV_INFO(0x7A70, 0x0510, iwlax211_2ax_cfg_so_gf_a0_long, NULL),
- IWL_DEV_INFO(0x7A70, 0x0A10, iwlax211_2ax_cfg_so_gf_a0_long, NULL),
- IWL_DEV_INFO(0x7AF0, 0x0090, iwlax211_2ax_cfg_so_gf_a0, NULL),
- IWL_DEV_INFO(0x7AF0, 0x0098, iwlax211_2ax_cfg_so_gf_a0, NULL),
- IWL_DEV_INFO(0x7AF0, 0x00B0, iwlax411_2ax_cfg_so_gf4_a0, NULL),
- IWL_DEV_INFO(0x7AF0, 0x0310, iwlax211_2ax_cfg_so_gf_a0, NULL),
- IWL_DEV_INFO(0x7AF0, 0x0510, iwlax211_2ax_cfg_so_gf_a0, NULL),
- IWL_DEV_INFO(0x7AF0, 0x0A10, iwlax211_2ax_cfg_so_gf_a0, NULL),
-
- /* So with JF */
- IWL_DEV_INFO(0x7A70, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name),
- IWL_DEV_INFO(0x7A70, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name),
- IWL_DEV_INFO(0x7AF0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name),
- IWL_DEV_INFO(0x7AF0, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name),
-
- /* SO with GF2 */
- IWL_DEV_INFO(0x2726, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),
- IWL_DEV_INFO(0x2726, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),
- IWL_DEV_INFO(0x51F0, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),
- IWL_DEV_INFO(0x51F0, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),
- IWL_DEV_INFO(0x51F1, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),
- IWL_DEV_INFO(0x51F1, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),
- IWL_DEV_INFO(0x54F0, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),
- IWL_DEV_INFO(0x54F0, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),
- IWL_DEV_INFO(0x7A70, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),
- IWL_DEV_INFO(0x7A70, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),
- IWL_DEV_INFO(0x7AF0, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),
- IWL_DEV_INFO(0x7AF0, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),
- IWL_DEV_INFO(0x7F70, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),
- IWL_DEV_INFO(0x7F70, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),
-
- /* MA with GF2 */
- IWL_DEV_INFO(0x7E40, 0x1671, iwl_cfg_ma, iwl_ax211_killer_1675s_name),
- IWL_DEV_INFO(0x7E40, 0x1672, iwl_cfg_ma, iwl_ax211_killer_1675i_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_2ac_cfg_soc, iwl9461_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_2ac_cfg_soc, iwl9461_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_2ac_cfg_soc, iwl9462_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_2ac_cfg_soc, iwl9462_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_2ac_cfg_soc, iwl9560_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_2ac_cfg_soc, iwl9560_name),
-
- _IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB,
- iwl9260_2ac_cfg, iwl9270_160_name),
- _IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB,
- iwl9260_2ac_cfg, iwl9270_name),
-
- _IWL_DEV_INFO(0x271B, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_TH1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9260_2ac_cfg, iwl9162_160_name),
- _IWL_DEV_INFO(0x271B, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_TH1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9260_2ac_cfg, iwl9162_name),
-
- _IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9260_2ac_cfg, iwl9260_160_name),
- _IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9260_2ac_cfg, iwl9260_name),
-
-/* Qu with Jf */
- /* Qu B step */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_qu_b0_jf_b0_cfg, iwl9461_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_qu_b0_jf_b0_cfg, iwl9461_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_qu_b0_jf_b0_cfg, iwl9462_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_qu_b0_jf_b0_cfg, iwl9462_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_qu_b0_jf_b0_cfg, iwl9560_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_qu_b0_jf_b0_cfg, iwl9560_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,
- IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_qu_b0_jf_b0_cfg, iwl9560_killer_1550s_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,
- IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_qu_b0_jf_b0_cfg, iwl9560_killer_1550i_name),
-
- /* Qu C step */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_qu_c0_jf_b0_cfg, iwl9461_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_qu_c0_jf_b0_cfg, iwl9461_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_qu_c0_jf_b0_cfg, iwl9462_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_qu_c0_jf_b0_cfg, iwl9462_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_qu_c0_jf_b0_cfg, iwl9560_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_qu_c0_jf_b0_cfg, iwl9560_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,
- IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_qu_c0_jf_b0_cfg, iwl9560_killer_1550s_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,
- IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_qu_c0_jf_b0_cfg, iwl9560_killer_1550i_name),
-
- /* QuZ */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_quz_a0_jf_b0_cfg, iwl9461_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_quz_a0_jf_b0_cfg, iwl9461_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_quz_a0_jf_b0_cfg, iwl9462_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_quz_a0_jf_b0_cfg, iwl9462_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_quz_a0_jf_b0_cfg, iwl9560_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_quz_a0_jf_b0_cfg, iwl9560_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,
- IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_quz_a0_jf_b0_cfg, iwl9560_killer_1550s_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,
- IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwl9560_quz_a0_jf_b0_cfg, iwl9560_killer_1550i_name),
-
-/* Qu with Hr */
- /* Qu B step */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_qu_b0_hr1_b0, iwl_ax101_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_qu_b0_hr_b0, iwl_ax203_name),
-
- /* Qu C step */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_qu_c0_hr1_b0, iwl_ax101_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_qu_c0_hr_b0, iwl_ax203_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_qu_c0_hr_b0, iwl_ax201_name),
-
- /* QuZ */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_quz_a0_hr1_b0, iwl_ax101_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QUZ, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_cfg_quz_a0_hr_b0, iwl_ax203_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QUZ, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_cfg_quz_a0_hr_b0, iwl_ax201_name),
-
-/* Ma */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_cfg_ma, iwl_ax201_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_ma, iwl_ax211_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_cfg_ma, iwl_ax231_name),
-
-/* So with Hr */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_cfg_so_a0_hr_a0, iwl_ax203_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_cfg_so_a0_hr_a0, iwl_ax101_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_cfg_so_a0_hr_a0, iwl_ax201_name),
-
-/* So-F with Hr */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_cfg_so_a0_hr_a0, iwl_ax203_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_cfg_so_a0_hr_a0, iwl_ax101_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_cfg_so_a0_hr_a0, iwl_ax201_name),
-
-/* So-F with Gf */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB,
- iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_name),
-
-/* SoF with JF2 */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwlax210_2ax_cfg_so_jf_b0, iwl9560_name),
-
-/* SoF with JF */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwlax210_2ax_cfg_so_jf_b0, iwl9461_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwlax210_2ax_cfg_so_jf_b0, iwl9462_name),
-
-/* So with GF */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB,
- iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_name),
-
-/* So with JF2 */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwlax210_2ax_cfg_so_jf_b0, iwl9560_name),
-
-/* So with JF */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwlax210_2ax_cfg_so_jf_b0, iwl9461_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
- iwlax210_2ax_cfg_so_jf_b0, iwl9462_name),
+#if IS_ENABLED(CONFIG_IWLDVM)
+ IWL_DEV_INFO(iwl5100_n_cfg, iwl5100_agn_name,
+ DEVICE(0x4232), SUBDEV_MASKED(0x1, 0xF)),
+ IWL_DEV_INFO(iwl5100_n_cfg, iwl5100_agn_name,
+ DEVICE(0x4232), SUBDEV_MASKED(0x4, 0xF)),
+ IWL_DEV_INFO(iwl5100_n_cfg, iwl5100_bgn_name,
+ DEVICE(0x4232), SUBDEV_MASKED(0x5, 0xF)),
+ IWL_DEV_INFO(iwl5100_abg_cfg, iwl5100_abg_name,
+ DEVICE(0x4232), SUBDEV_MASKED(0x6, 0xF)),
+ IWL_DEV_INFO(iwl5100_n_cfg, iwl5100_agn_name,
+ DEVICE(0x4237), SUBDEV_MASKED(0x1, 0xF)),
+ IWL_DEV_INFO(iwl5100_n_cfg, iwl5100_agn_name,
+ DEVICE(0x4237), SUBDEV_MASKED(0x4, 0xF)),
+ IWL_DEV_INFO(iwl5100_n_cfg, iwl5100_bgn_name,
+ DEVICE(0x4237), SUBDEV_MASKED(0x5, 0xF)),
+ IWL_DEV_INFO(iwl5100_abg_cfg, iwl5100_abg_name,
+ DEVICE(0x4237), SUBDEV_MASKED(0x6, 0xF)),
-#endif /* CONFIG_IWLMVM */
-#if IS_ENABLED(CONFIG_IWLMLD)
-/* Bz */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_bz, iwl_ax201_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_bz, iwl_ax211_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_bz, iwl_fm_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_WH, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_bz, iwl_wh_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ_W, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_bz, iwl_ax201_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ_W, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_bz, iwl_ax211_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ_W, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_bz, iwl_fm_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ_W, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_WH, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_bz, iwl_wh_name),
-
-/* Ga (Gl) */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_320, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_cfg_gl, iwl_gl_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_320, IWL_CFG_ANY, IWL_CFG_NO_CDB,
- iwl_cfg_gl, iwl_mtp_name),
-
-/* Sc */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SC, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_sc, iwl_ax211_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SC, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_sc, iwl_fm_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SC, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_WH, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_sc, iwl_wh_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SC2, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_sc2, iwl_ax211_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SC2, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_sc2, iwl_fm_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SC2, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_WH, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_sc2, iwl_wh_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SC2F, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_sc2f, iwl_ax211_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SC2F, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_sc2f, iwl_fm_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SC2F, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_WH, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_sc2f, iwl_wh_name),
-
-/* Dr */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_DR, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_dr, iwl_dr_name),
-
-/* Br */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BR, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
- iwl_cfg_br, iwl_br_name),
-#endif /* CONFIG_IWLMLD */
-};
-EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_dev_info_table);
+/* 5300 Series WiFi */
+ IWL_DEV_INFO(iwl5300_agn_cfg, iwl5300_agn_name,
+ DEVICE(0x4235), SUBDEV_MASKED(0x1, 0xF)),
+ IWL_DEV_INFO(iwl5300_agn_cfg, iwl5300_agn_name,
+ DEVICE(0x4235), SUBDEV_MASKED(0x4, 0xF)),
+ IWL_DEV_INFO(iwl5300_agn_cfg, iwl5300_agn_name,
+ DEVICE(0x4236), SUBDEV_MASKED(0x1, 0xF)),
+ IWL_DEV_INFO(iwl5300_agn_cfg, iwl5300_agn_name,
+ DEVICE(0x4236), SUBDEV_MASKED(0x4, 0xF)),
-#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
-const unsigned int iwl_dev_info_table_size = ARRAY_SIZE(iwl_dev_info_table);
-EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_dev_info_table_size);
-#endif
+/* 5350 Series WiFi/WiMax */
+ IWL_DEV_INFO(iwl5350_agn_cfg, iwl5350_agn_name,
+ DEVICE(0x423A)),
+ IWL_DEV_INFO(iwl5350_agn_cfg, iwl5350_agn_name,
+ DEVICE(0x423B)),
-/*
- * Read rf id and cdb info from prph register and store it
- */
-static void get_crf_id(struct iwl_trans *iwl_trans)
-{
- u32 sd_reg_ver_addr;
- u32 val = 0;
- u8 step;
-
- if (iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
- sd_reg_ver_addr = SD_REG_VER_GEN2;
- else
- sd_reg_ver_addr = SD_REG_VER;
-
- /* Enable access to peripheral registers */
- val = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG);
- val |= WFPM_AUX_CTL_AUX_IF_MAC_OWNER_MSK;
- iwl_write_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG, val);
-
- /* Read crf info */
- iwl_trans->hw_crf_id = iwl_read_prph_no_grab(iwl_trans, sd_reg_ver_addr);
-
- /* Read cnv info */
- iwl_trans->hw_cnv_id =
- iwl_read_prph_no_grab(iwl_trans, CNVI_AUX_MISC_CHIP);
-
- /* For BZ-W, take B step also when A step is indicated */
- if (CSR_HW_REV_TYPE(iwl_trans->hw_rev) == IWL_CFG_MAC_TYPE_BZ_W)
- step = SILICON_B_STEP;
-
- /* In BZ, the MAC step must be read from the CNVI aux register */
- if (CSR_HW_REV_TYPE(iwl_trans->hw_rev) == IWL_CFG_MAC_TYPE_BZ) {
- step = CNVI_AUX_MISC_CHIP_MAC_STEP(iwl_trans->hw_cnv_id);
-
- /* For BZ-U, take B step also when A step is indicated */
- if ((CNVI_AUX_MISC_CHIP_PROD_TYPE(iwl_trans->hw_cnv_id) ==
- CNVI_AUX_MISC_CHIP_PROD_TYPE_BZ_U) &&
- step == SILICON_A_STEP)
- step = SILICON_B_STEP;
- }
+/* 5150 Series Wifi/WiMax */
+ IWL_DEV_INFO(iwl5150_agn_cfg, iwl5150_agn_name,
+ DEVICE(0x423C), SUBDEV_MASKED(0x1, 0xF)),
+ IWL_DEV_INFO(iwl5150_abg_cfg, iwl5150_abg_name,
+ DEVICE(0x423C), SUBDEV_MASKED(0x6, 0xF)),
- if (CSR_HW_REV_TYPE(iwl_trans->hw_rev) == IWL_CFG_MAC_TYPE_BZ ||
- CSR_HW_REV_TYPE(iwl_trans->hw_rev) == IWL_CFG_MAC_TYPE_BZ_W) {
- iwl_trans->hw_rev_step = step;
- iwl_trans->hw_rev |= step;
- }
+ IWL_DEV_INFO(iwl5150_agn_cfg, iwl5150_agn_name,
+ DEVICE(0x423D), SUBDEV_MASKED(0x1, 0xF)),
+ IWL_DEV_INFO(iwl5150_abg_cfg, iwl5150_abg_name,
+ DEVICE(0x423D), SUBDEV_MASKED(0x6, 0xF)),
- /* Read cdb info (also contains the jacket info if needed in the future */
- iwl_trans->hw_wfpm_id =
- iwl_read_umac_prph_no_grab(iwl_trans, WFPM_OTP_CFG1_ADDR);
- IWL_INFO(iwl_trans, "Detected crf-id 0x%x, cnv-id 0x%x wfpm id 0x%x\n",
- iwl_trans->hw_crf_id, iwl_trans->hw_cnv_id,
- iwl_trans->hw_wfpm_id);
-}
+/* 6x00 Series */
+ IWL_DEV_INFO(iwl6000_3agn_cfg, iwl6000_3agn_name,
+ DEVICE(0x422B), SUBDEV_MASKED(0x1, 0xF)),
+ IWL_DEV_INFO(iwl6000_3agn_cfg, iwl6000_3agn_name,
+ DEVICE(0x422B), SUBDEV_MASKED(0x8, 0xF)),
+ IWL_DEV_INFO(iwl6000i_2agn_cfg, iwl6000i_2agn_name,
+ DEVICE(0x422C), SUBDEV_MASKED(0x1, 0xF)),
+ IWL_DEV_INFO(iwl6000i_non_n_cfg, iwl6000i_2abg_name,
+ DEVICE(0x422C), SUBDEV_MASKED(0x6, 0xF)),
+ IWL_DEV_INFO(iwl6000i_non_n_cfg, iwl6000i_2bg_name,
+ DEVICE(0x422C), SUBDEV_MASKED(0x7, 0xF)),
+ IWL_DEV_INFO(iwl6000_3agn_cfg, iwl6000_3agn_name,
+ DEVICE(0x4238), SUBDEV(0x1111)),
+ IWL_DEV_INFO(iwl6000_3agn_cfg, iwl6000_3agn_name,
+ DEVICE(0x4238), SUBDEV(0x1118)),
+ IWL_DEV_INFO(iwl6000i_2agn_cfg, iwl6000i_2agn_name,
+ DEVICE(0x4239), SUBDEV(0x1311)),
+ IWL_DEV_INFO(iwl6000i_non_n_cfg, iwl6000i_2abg_name,
+ DEVICE(0x4239), SUBDEV(0x1316)),
-/*
- * In case that there is no OTP on the NIC, map the rf id and cdb info
- * from the prph registers.
- */
-static int map_crf_id(struct iwl_trans *iwl_trans)
-{
- int ret = 0;
- u32 val = iwl_trans->hw_crf_id;
- u32 step_id = REG_CRF_ID_STEP(val);
- u32 slave_id = REG_CRF_ID_SLAVE(val);
- u32 jacket_id_cnv = REG_CRF_ID_SLAVE(iwl_trans->hw_cnv_id);
- u32 jacket_id_wfpm = WFPM_OTP_CFG1_IS_JACKET(iwl_trans->hw_wfpm_id);
- u32 cdb_id_wfpm = WFPM_OTP_CFG1_IS_CDB(iwl_trans->hw_wfpm_id);
-
- /* Map between crf id to rf id */
- switch (REG_CRF_ID_TYPE(val)) {
- case REG_CRF_ID_TYPE_JF_1:
- iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_JF1 << 12);
- break;
- case REG_CRF_ID_TYPE_JF_2:
- iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_JF2 << 12);
- break;
- case REG_CRF_ID_TYPE_HR_NONE_CDB_1X1:
- iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_HR1 << 12);
- break;
- case REG_CRF_ID_TYPE_HR_NONE_CDB:
- iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_HR2 << 12);
- break;
- case REG_CRF_ID_TYPE_HR_CDB:
- iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_HR2 << 12);
- break;
- case REG_CRF_ID_TYPE_GF:
- iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_GF << 12);
- break;
- case REG_CRF_ID_TYPE_FM:
- iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_FM << 12);
- break;
- case REG_CRF_ID_TYPE_WHP:
- iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_WH << 12);
- break;
- case REG_CRF_ID_TYPE_PE:
- iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_PE << 12);
- break;
- default:
- ret = -EIO;
- IWL_ERR(iwl_trans,
- "Can't find a correct rfid for crf id 0x%x\n",
- REG_CRF_ID_TYPE(val));
- goto out;
+/* 6x05 Series */
+ IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_name,
+ DEVICE(0x0082), SUBDEV_MASKED(0x1, 0xF)),
+ IWL_DEV_INFO(iwl6005_non_n_cfg, iwl6005_2abg_name,
+ DEVICE(0x0082), SUBDEV_MASKED(0x6, 0xF)),
+ IWL_DEV_INFO(iwl6005_non_n_cfg, iwl6005_2bg_name,
+ DEVICE(0x0082), SUBDEV_MASKED(0x7, 0xF)),
+ IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_name,
+ DEVICE(0x0082), SUBDEV_MASKED(0x8, 0xF)),
+
+ IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_name,
+ DEVICE(0x0085), SUBDEV_MASKED(0x1, 0xF)),
+ IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_name,
+ DEVICE(0x0085), SUBDEV_MASKED(0x8, 0xF)),
+ IWL_DEV_INFO(iwl6005_non_n_cfg, iwl6005_2abg_name,
+ DEVICE(0x0085), SUBDEV_MASKED(0x6, 0xF)),
+
+ IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_sff_name,
+ DEVICE(0x0082), SUBDEV_MASKED(0xC000, 0xF000)),
+ IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_sff_name,
+ DEVICE(0x0085), SUBDEV_MASKED(0xC000, 0xF000)),
+ IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_d_name,
+ DEVICE(0x0082), SUBDEV(0x4820)),
+ IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_mow1_name,
+ DEVICE(0x0082), SUBDEV(0x1304)),/* low 5GHz active */
+ IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_mow2_name,
+ DEVICE(0x0082), SUBDEV(0x1305)),/* high 5GHz active */
- }
+/* 6x30 Series */
+ IWL_DEV_INFO(iwl6030_n_cfg, iwl1030_bgn_name,
+ DEVICE(0x008A), SUBDEV_MASKED(0x5, 0xF)),
+ IWL_DEV_INFO(iwl6030_non_n_cfg, iwl1030_bg_name,
+ DEVICE(0x008A), SUBDEV_MASKED(0x7, 0xF)),
+ IWL_DEV_INFO(iwl6030_n_cfg, iwl1030_bgn_name,
+ DEVICE(0x008B), SUBDEV(0x5315)),
+ IWL_DEV_INFO(iwl6030_non_n_cfg, iwl1030_bg_name,
+ DEVICE(0x008B), SUBDEV(0x5317)),
+ IWL_DEV_INFO(iwl6030_n_cfg, iwl6030_2agn_name,
+ DEVICE(0x0090), SUBDEV(0x5211)),
+ IWL_DEV_INFO(iwl6030_n_cfg, iwl6030_2bgn_name,
+ DEVICE(0x0090), SUBDEV(0x5215)),
+ IWL_DEV_INFO(iwl6030_non_n_cfg, iwl6030_2abg_name,
+ DEVICE(0x0090), SUBDEV(0x5216)),
+ IWL_DEV_INFO(iwl6030_n_cfg, iwl6030_2agn_name,
+ DEVICE(0x0091), SUBDEV_MASKED(0x1, 0xF)),
+ IWL_DEV_INFO(iwl6030_n_cfg, iwl6030_2bgn_name,
+ DEVICE(0x0091), SUBDEV_MASKED(0x5, 0xF)),
+ IWL_DEV_INFO(iwl6030_non_n_cfg, iwl6030_2abg_name,
+ DEVICE(0x0091), SUBDEV_MASKED(0x6, 0xF)),
+ IWL_DEV_INFO(iwl6030_non_n_cfg, iwl6030_2bg_name,
+ DEVICE(0x0091), SUBDEV(0x5207)),
- /* Set Step-id */
- iwl_trans->hw_rf_id |= (step_id << 8);
+/* 6x50 WiFi/WiMax Series */
+ IWL_DEV_INFO(iwl6050_2agn_cfg, iwl6050_2agn_name,
+ DEVICE(0x0087), SUBDEV_MASKED(0x1, 0xF)),
+ IWL_DEV_INFO(iwl6050_2abg_cfg, iwl6050_2abg_name,
+ DEVICE(0x0087), SUBDEV_MASKED(0x6, 0xF)),
+ IWL_DEV_INFO(iwl6050_2agn_cfg, iwl6050_2agn_name,
+ DEVICE(0x0089), SUBDEV(0x1311)),
+ IWL_DEV_INFO(iwl6050_2abg_cfg, iwl6050_2abg_name,
+ DEVICE(0x0089), SUBDEV(0x1316)),
- /* Set CDB capabilities */
- if (cdb_id_wfpm || slave_id) {
- iwl_trans->hw_rf_id += BIT(28);
- IWL_INFO(iwl_trans, "Adding cdb to rf id\n");
- }
+/* 6150 WiFi/WiMax Series */
+ IWL_DEV_INFO(iwl6150_bgn_cfg, iwl6150_bgn_name,
+ DEVICE(0x0885), SUBDEV_MASKED(0x5, 0xF)),
+ IWL_DEV_INFO(iwl6150_bg_cfg, iwl6150_bg_name,
+ DEVICE(0x0885), SUBDEV_MASKED(0x7, 0xF)),
+ IWL_DEV_INFO(iwl6150_bgn_cfg, iwl6150_bgn_name,
+ DEVICE(0x0886), SUBDEV(0x1315)),
+ IWL_DEV_INFO(iwl6150_bg_cfg, iwl6150_bg_name,
+ DEVICE(0x0886), SUBDEV(0x1317)),
- /* Set Jacket capabilities */
- if (jacket_id_wfpm || jacket_id_cnv) {
- iwl_trans->hw_rf_id += BIT(29);
- IWL_INFO(iwl_trans, "Adding jacket to rf id\n");
- }
+/* 1000 Series WiFi */
+ IWL_DEV_INFO(iwl1000_bgn_cfg, iwl1000_bgn_name,
+ DEVICE(0x0083), SUBDEV_MASKED(0x5, 0xF)),
+ IWL_DEV_INFO(iwl1000_bg_cfg, iwl1000_bg_name,
+ DEVICE(0x0083), SUBDEV_MASKED(0x6, 0xF)),
+ IWL_DEV_INFO(iwl1000_bgn_cfg, iwl1000_bgn_name,
+ DEVICE(0x0084), SUBDEV_MASKED(0x5, 0xF)),
+ IWL_DEV_INFO(iwl1000_bg_cfg, iwl1000_bg_name,
+ DEVICE(0x0084), SUBDEV_MASKED(0x6, 0xF)),
- IWL_INFO(iwl_trans,
- "Detected rf-type 0x%x step-id 0x%x slave-id 0x%x from crf id 0x%x\n",
- REG_CRF_ID_TYPE(val), step_id, slave_id, iwl_trans->hw_rf_id);
- IWL_INFO(iwl_trans,
- "Detected cdb-id 0x%x jacket-id 0x%x from wfpm id 0x%x\n",
- cdb_id_wfpm, jacket_id_wfpm, iwl_trans->hw_wfpm_id);
- IWL_INFO(iwl_trans, "Detected jacket-id 0x%x from cnvi id 0x%x\n",
- jacket_id_cnv, iwl_trans->hw_cnv_id);
+/* 100 Series WiFi */
+ IWL_DEV_INFO(iwl100_bgn_cfg, iwl100_bgn_name,
+ DEVICE(0x08AE), SUBDEV_MASKED(0x5, 0xF)),
+ IWL_DEV_INFO(iwl100_bg_cfg, iwl100_bg_name,
+ DEVICE(0x08AE), SUBDEV_MASKED(0x7, 0xF)),
+ IWL_DEV_INFO(iwl100_bgn_cfg, iwl100_bgn_name,
+ DEVICE(0x08AF), SUBDEV(0x1015)),
+ IWL_DEV_INFO(iwl100_bg_cfg, iwl100_bg_name,
+ DEVICE(0x08AF), SUBDEV(0x1017)),
-out:
- return ret;
-}
+/* 130 Series WiFi */
+ IWL_DEV_INFO(iwl130_bgn_cfg, iwl130_bgn_name,
+ DEVICE(0x0896), SUBDEV_MASKED(0x5, 0xF)),
+ IWL_DEV_INFO(iwl130_bg_cfg, iwl130_bg_name,
+ DEVICE(0x0896), SUBDEV_MASKED(0x7, 0xF)),
+ IWL_DEV_INFO(iwl130_bgn_cfg, iwl130_bgn_name,
+ DEVICE(0x0897), SUBDEV(0x5015)),
+ IWL_DEV_INFO(iwl130_bg_cfg, iwl130_bg_name,
+ DEVICE(0x0897), SUBDEV(0x5017)),
+
+/* 2x00 Series */
+ IWL_DEV_INFO(iwl2000_2bgn_cfg, iwl2000_2bgn_name,
+ DEVICE(0x0890), SUBDEV(0x4022)),
+ IWL_DEV_INFO(iwl2000_2bgn_cfg, iwl2000_2bgn_name,
+ DEVICE(0x0891), SUBDEV(0x4222)),
+ IWL_DEV_INFO(iwl2000_2bgn_cfg, iwl2000_2bgn_name,
+ DEVICE(0x0890), SUBDEV(0x4422)),
+ IWL_DEV_INFO(iwl2000_2bgn_cfg, iwl2000_2bgn_d_name,
+ DEVICE(0x0890), SUBDEV(0x4822)),
+
+/* 2x30 Series */
+ IWL_DEV_INFO(iwl2030_2bgn_cfg, iwl2030_2bgn_name,
+ DEVICE(0x0887)),
+ IWL_DEV_INFO(iwl2030_2bgn_cfg, iwl2030_2bgn_name,
+ DEVICE(0x0888), SUBDEV(0x4262)),
+
+/* 6x35 Series */
+ IWL_DEV_INFO(iwl6035_2agn_cfg, iwl6035_2agn_name,
+ DEVICE(0x088E), SUBDEV_MASKED(0x0, 0xF)),
+ IWL_DEV_INFO(iwl6035_2agn_cfg, iwl6035_2agn_sff_name,
+ DEVICE(0x088E), SUBDEV_MASKED(0xA, 0xF)),
+ IWL_DEV_INFO(iwl6035_2agn_cfg, iwl6035_2agn_name,
+ DEVICE(0x088F), SUBDEV_MASKED(0x0, 0xF)),
+ IWL_DEV_INFO(iwl6035_2agn_cfg, iwl6035_2agn_sff_name,
+ DEVICE(0x088F), SUBDEV_MASKED(0xA, 0xF)),
+
+/* 105 Series */
+ IWL_DEV_INFO(iwl105_bgn_cfg, iwl105_bgn_name,
+ DEVICE(0x0894)),
+ IWL_DEV_INFO(iwl105_bgn_cfg, iwl105_bgn_name,
+ DEVICE(0x0895), SUBDEV(0x0222)),
+
+/* 135 Series */
+ IWL_DEV_INFO(iwl135_bgn_cfg, iwl135_bgn_name,
+ DEVICE(0x0892)),
+ IWL_DEV_INFO(iwl135_bgn_cfg, iwl135_bgn_name,
+ DEVICE(0x0893), SUBDEV(0x0262)),
+#endif /* CONFIG_IWLDVM */
+
+#if IS_ENABLED(CONFIG_IWLMVM)
+/* 7260 Series */
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2ac_name,
+ DEVICE(0x08B1)), // unlisted ones fall through to here
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0x4060)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0x406A)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0x4160)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_n_name,
+ DEVICE(0x08B1), SUBDEV(0x4062)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_n_name,
+ DEVICE(0x08B1), SUBDEV(0x4162)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0x4460)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0x446A)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_n_name,
+ DEVICE(0x08B1), SUBDEV(0x4462)),
+ IWL_DEV_INFO(iwl7260_high_temp_cfg, iwl7260_2ac_name,
+ DEVICE(0x08B1), SUBDEV(0x4A70)),
+ IWL_DEV_INFO(iwl7260_high_temp_cfg, iwl7260_2ac_name,
+ DEVICE(0x08B1), SUBDEV(0x4A6E)),
+ IWL_DEV_INFO(iwl7260_high_temp_cfg, iwl7260_2ac_name,
+ DEVICE(0x08B1), SUBDEV(0x4A6C)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0x4560)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0x4020)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0x402A)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0x4420)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0xC060)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0xC06A)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0xC160)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_n_name,
+ DEVICE(0x08B1), SUBDEV(0xC062)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_n_name,
+ DEVICE(0x08B1), SUBDEV(0xC162)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0xC760)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0xC460)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_n_name,
+ DEVICE(0x08B1), SUBDEV(0xC462)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0xC560)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0xC360)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0xC020)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0xC02A)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B1), SUBDEV(0xC420)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2ac_name,
+ DEVICE(0x08B2), SUBDEV(0x4270)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2ac_name,
+ DEVICE(0x08B2), SUBDEV(0x4272)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B2), SUBDEV(0x4260)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B2), SUBDEV(0x426A)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_n_name,
+ DEVICE(0x08B2), SUBDEV(0x4262)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2ac_name,
+ DEVICE(0x08B2), SUBDEV(0x4370)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B2), SUBDEV(0x4360)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B2), SUBDEV(0x4220)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2ac_name,
+ DEVICE(0x08B2), SUBDEV(0xC270)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2ac_name,
+ DEVICE(0x08B2), SUBDEV(0xC272)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B2), SUBDEV(0xC260)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_n_name,
+ DEVICE(0x08B2), SUBDEV(0xC26A)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_n_name,
+ DEVICE(0x08B2), SUBDEV(0xC262)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2ac_name,
+ DEVICE(0x08B2), SUBDEV(0xC370)),
+ IWL_DEV_INFO(iwl7260_cfg, iwl7260_2n_name,
+ DEVICE(0x08B2), SUBDEV(0xC220)),
+
+/* 3160 Series */
+ IWL_DEV_INFO(iwl3160_cfg, iwl3160_2ac_name,
+ DEVICE(0x08B3)),
+
+ IWL_DEV_INFO(iwl3160_cfg, iwl3160_n_name,
+ DEVICE(0x08B3), SUBDEV_MASKED(0x62, 0xFF)),
+ IWL_DEV_INFO(iwl3160_cfg, iwl3160_2n_name,
+ DEVICE(0x08B3), SUBDEV_MASKED(0x60, 0xFF)),
+
+ IWL_DEV_INFO(iwl3160_cfg, iwl3160_2ac_name,
+ DEVICE(0x08B4)),
+
+/* 3165 Series */
+ IWL_DEV_INFO(iwl3165_2ac_cfg, iwl3165_2ac_name,
+ DEVICE(0x3165)),
+ IWL_DEV_INFO(iwl3165_2ac_cfg, iwl3165_2ac_name,
+ DEVICE(0x3166)),
+
+/* 3168 Series */
+ IWL_DEV_INFO(iwl3168_2ac_cfg, iwl3168_2ac_name,
+ DEVICE(0x24FB)),
+
+/* 7265 Series */
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2ac_name,
+ DEVICE(0x095A)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095A), SUBDEV(0x5000)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095A), SUBDEV(0x500A)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_n_name,
+ DEVICE(0x095A), SUBDEV(0x5002)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_n_name,
+ DEVICE(0x095A), SUBDEV(0x5102)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095A), SUBDEV(0x5020)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095A), SUBDEV(0x502A)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095A), SUBDEV(0x5090)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095A), SUBDEV(0x5190)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095A), SUBDEV(0x5100)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095A), SUBDEV(0x5400)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095A), SUBDEV(0x5420)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095A), SUBDEV(0x5490)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095A), SUBDEV(0x5C10)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095A), SUBDEV(0x5590)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095A), SUBDEV(0x9000)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095A), SUBDEV(0x900A)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095A), SUBDEV(0x9400)),
+
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2ac_name,
+ DEVICE(0x095B)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095B), SUBDEV(0x520A)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_n_name,
+ DEVICE(0x095B), SUBDEV(0x5302)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095B), SUBDEV(0x5200)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_n_name,
+ DEVICE(0x095B), SUBDEV(0x5202)),
+ IWL_DEV_INFO(iwl7265_cfg, iwl7265_2n_name,
+ DEVICE(0x095B), SUBDEV(0x9200)),
+
+/* 8000 Series */
+ IWL_DEV_INFO(iwl8260_cfg, iwl8260_2ac_name,
+ DEVICE(0x24F3)),
+ IWL_DEV_INFO(iwl8260_cfg, iwl8260_2n_name,
+ DEVICE(0x24F3), SUBDEV(0x0004)),
+ IWL_DEV_INFO(iwl8260_cfg, iwl8260_2n_name,
+ DEVICE(0x24F3), SUBDEV(0x0044)),
+ IWL_DEV_INFO(iwl8260_cfg, iwl8260_2ac_name,
+ DEVICE(0x24F4)),
+ IWL_DEV_INFO(iwl8260_cfg, iwl4165_2ac_name,
+ DEVICE(0x24F5)),
+ IWL_DEV_INFO(iwl8260_cfg, iwl4165_2ac_name,
+ DEVICE(0x24F6)),
+ IWL_DEV_INFO(iwl8265_cfg, iwl8265_2ac_name,
+ DEVICE(0x24FD)),
+ IWL_DEV_INFO(iwl8265_cfg, iwl8275_2ac_name,
+ DEVICE(0x24FD), SUBDEV(0x3E02)),
+ IWL_DEV_INFO(iwl8265_cfg, iwl8275_2ac_name,
+ DEVICE(0x24FD), SUBDEV(0x3E01)),
+ IWL_DEV_INFO(iwl8265_cfg, iwl8275_2ac_name,
+ DEVICE(0x24FD), SUBDEV(0x1012)),
+ IWL_DEV_INFO(iwl8265_cfg, iwl8275_2ac_name,
+ DEVICE(0x24FD), SUBDEV(0x0012)),
+ IWL_DEV_INFO(iwl8265_cfg, iwl_killer_1435i_name,
+ DEVICE(0x24FD), SUBDEV(0x1431)),
+ IWL_DEV_INFO(iwl8265_cfg, iwl_killer_1434_kix_name,
+ DEVICE(0x24FD), SUBDEV(0x1432)),
+
+/* JF1 RF */
+ IWL_DEV_INFO(iwl_rf_jf, iwl9461_160_name,
+ RF_TYPE(JF1)),
+ IWL_DEV_INFO(iwl_rf_jf_80mhz, iwl9461_name,
+ RF_TYPE(JF1), BW_LIMITED),
+ IWL_DEV_INFO(iwl_rf_jf, iwl9462_160_name,
+ RF_TYPE(JF1), RF_ID(JF1_DIV)),
+ IWL_DEV_INFO(iwl_rf_jf_80mhz, iwl9462_name,
+ RF_TYPE(JF1), RF_ID(JF1_DIV), BW_LIMITED),
+/* JF2 RF */
+ IWL_DEV_INFO(iwl_rf_jf, iwl9260_160_name,
+ RF_TYPE(JF2)),
+ IWL_DEV_INFO(iwl_rf_jf_80mhz, iwl9260_name,
+ RF_TYPE(JF2), BW_LIMITED),
+ IWL_DEV_INFO(iwl_rf_jf, iwl9560_160_name,
+ RF_TYPE(JF2), RF_ID(JF)),
+ IWL_DEV_INFO(iwl_rf_jf_80mhz, iwl9560_name,
+ RF_TYPE(JF2), RF_ID(JF), BW_LIMITED),
+
+/* HR RF */
+ IWL_DEV_INFO(iwl_rf_hr, iwl_ax201_name, RF_TYPE(HR2)),
+ IWL_DEV_INFO(iwl_rf_hr_80mhz, iwl_ax101_name, RF_TYPE(HR1)),
+ IWL_DEV_INFO(iwl_rf_hr_80mhz, iwl_ax203_name, RF_TYPE(HR2), BW_LIMITED),
+ IWL_DEV_INFO(iwl_rf_hr, iwl_ax200_name, DEVICE(0x2723)),
+
+/* GF RF */
+ IWL_DEV_INFO(iwl_rf_gf, iwl_ax211_name, RF_TYPE(GF)),
+ IWL_DEV_INFO(iwl_rf_gf, iwl_ax411_name, RF_TYPE(GF), CDB),
+ IWL_DEV_INFO(iwl_rf_gf, iwl_ax210_name, DEVICE(0x2725)),
+
+/* Killer CRFs */
+ IWL_DEV_INFO(iwl_rf_jf, iwl9260_killer_1550_name, SUBDEV(0x1550)),
+ IWL_DEV_INFO(iwl_rf_jf, iwl9560_killer_1550s_name, SUBDEV(0x1551)),
+ IWL_DEV_INFO(iwl_rf_jf, iwl9560_killer_1550i_name, SUBDEV(0x1552)),
+
+ IWL_DEV_INFO(iwl_rf_hr, iwl_ax201_killer_1650s_name, SUBDEV(0x1651)),
+ IWL_DEV_INFO(iwl_rf_hr, iwl_ax201_killer_1650i_name, SUBDEV(0x1652)),
+
+ IWL_DEV_INFO(iwl_rf_gf, iwl_ax211_killer_1675s_name, SUBDEV(0x1671)),
+ IWL_DEV_INFO(iwl_rf_gf, iwl_ax211_killer_1675i_name, SUBDEV(0x1672)),
+ IWL_DEV_INFO(iwl_rf_gf, iwl_ax210_killer_1675w_name, SUBDEV(0x1673)),
+ IWL_DEV_INFO(iwl_rf_gf, iwl_ax210_killer_1675x_name, SUBDEV(0x1674)),
+ IWL_DEV_INFO(iwl_rf_gf, iwl_ax411_killer_1690s_name, SUBDEV(0x1691)),
+ IWL_DEV_INFO(iwl_rf_gf, iwl_ax411_killer_1690i_name, SUBDEV(0x1692)),
+
+/* Killer discrete */
+ IWL_DEV_INFO(iwl_rf_hr, iwl_ax200_killer_1650w_name,
+ DEVICE(0x2723), SUBDEV(0x1653)),
+ IWL_DEV_INFO(iwl_rf_hr, iwl_ax200_killer_1650x_name,
+ DEVICE(0x2723), SUBDEV(0x1654)),
+#endif /* CONFIG_IWLMVM */
+#if IS_ENABLED(CONFIG_IWLMLD)
+/* FM RF */
+ IWL_DEV_INFO(iwl_rf_fm, iwl_be201_name, RF_TYPE(FM)),
+ IWL_DEV_INFO(iwl_rf_fm, iwl_be401_name, RF_TYPE(FM), CDB),
+ IWL_DEV_INFO(iwl_rf_fm, iwl_be200_name, RF_TYPE(FM),
+ DEVICE(0x272B), DISCRETE),
+ IWL_DEV_INFO(iwl_rf_fm_160mhz, iwl_be202_name,
+ RF_TYPE(FM), BW_LIMITED),
+
+/* Killer CRFs */
+ IWL_DEV_INFO(iwl_rf_fm, iwl_killer_be1750s_name, SUBDEV(0x1771)),
+ 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)),
+
+/* Killer discrete */
+ IWL_DEV_INFO(iwl_rf_fm, iwl_killer_be1750w_name,
+ DEVICE(0x272B), SUBDEV(0x1773)),
+ IWL_DEV_INFO(iwl_rf_fm, iwl_killer_be1750x_name,
+ DEVICE(0x272B), SUBDEV(0x1774)),
+
+/* WH RF */
+ IWL_DEV_INFO(iwl_rf_wh, iwl_be211_name, RF_TYPE(WH)),
+ IWL_DEV_INFO(iwl_rf_wh_non_eht, iwl_ax221_name, RF_TYPE(WH),
+ SUBDEV(0x0514)),
+ IWL_DEV_INFO(iwl_rf_wh_non_eht, iwl_ax221_name, RF_TYPE(WH),
+ SUBDEV(0x4514)),
+ IWL_DEV_INFO(iwl_rf_wh_160mhz, iwl_be213_name, RF_TYPE(WH), BW_LIMITED),
+
+/* PE RF */
+ IWL_DEV_INFO(iwl_rf_pe, iwl_bn201_name, RF_TYPE(PE)),
+ IWL_DEV_INFO(iwl_rf_pe, iwl_be223_name, RF_TYPE(PE),
+ SUBDEV_MASKED(0x0524, 0xFFF)),
+ IWL_DEV_INFO(iwl_rf_pe, iwl_bn203_name, RF_TYPE(PE),
+ SUBDEV_MASKED(0x0324, 0xFFF)),
+
+/* 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_pe, iwl_killer_bn1850w2_name, SUBDEV(0x1851)),
+ IWL_DEV_INFO(iwl_rf_pe, iwl_killer_bn1850i_name, SUBDEV(0x1852)),
+#endif /* CONFIG_IWLMLD */
+};
+EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_dev_info_table);
+
+#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
+const unsigned int iwl_dev_info_table_size = ARRAY_SIZE(iwl_dev_info_table);
+EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_dev_info_table_size);
+#endif
/* PCI registers */
#define PCI_CFG_RETRY_TIMEOUT 0x041
-VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info *
-iwl_pci_find_dev_info(u16 device, u16 subsystem_device,
- u16 mac_type, u8 mac_step, u16 rf_type, u8 cdb,
- u8 jacket, u8 rf_id, u8 no_160, u8 cores, u8 rf_step)
+const struct iwl_dev_info *
+iwl_pci_find_dev_info(u16 device, u16 subsystem_device, u16 rf_type, u8 cdb,
+ u8 rf_id, u8 bw_limit, bool discrete)
{
int num_devices = ARRAY_SIZE(iwl_dev_info_table);
int i;
@@ -1394,49 +1104,32 @@ iwl_pci_find_dev_info(u16 device, u16 subsystem_device,
for (i = num_devices - 1; i >= 0; i--) {
const struct iwl_dev_info *dev_info = &iwl_dev_info_table[i];
+ u16 subdevice_mask;
if (dev_info->device != (u16)IWL_CFG_ANY &&
dev_info->device != device)
continue;
- if (dev_info->subdevice != (u16)IWL_CFG_ANY &&
- dev_info->subdevice != subsystem_device)
- continue;
-
- if (dev_info->mac_type != (u16)IWL_CFG_ANY &&
- dev_info->mac_type != mac_type)
- continue;
+ subdevice_mask = GENMASK(dev_info->subdevice_m_h,
+ dev_info->subdevice_m_l);
- if (dev_info->mac_step != (u8)IWL_CFG_ANY &&
- dev_info->mac_step != mac_step)
- continue;
-
- if (dev_info->rf_type != (u16)IWL_CFG_ANY &&
- dev_info->rf_type != rf_type)
- continue;
-
- if (dev_info->cdb != (u8)IWL_CFG_ANY &&
- dev_info->cdb != cdb)
+ if (dev_info->subdevice != (u16)IWL_CFG_ANY &&
+ dev_info->subdevice != (subsystem_device & subdevice_mask))
continue;
- if (dev_info->jacket != (u8)IWL_CFG_ANY &&
- dev_info->jacket != jacket)
+ if (dev_info->match_rf_type && dev_info->rf_type != rf_type)
continue;
- if (dev_info->rf_id != (u8)IWL_CFG_ANY &&
- dev_info->rf_id != rf_id)
+ if (dev_info->match_cdb && dev_info->cdb != cdb)
continue;
- if (dev_info->no_160 != (u8)IWL_CFG_ANY &&
- dev_info->no_160 != no_160)
+ if (dev_info->match_rf_id && dev_info->rf_id != rf_id)
continue;
- if (dev_info->cores != (u8)IWL_CFG_ANY &&
- dev_info->cores != cores)
+ if (dev_info->match_bw_limit && dev_info->bw_limit != bw_limit)
continue;
- if (dev_info->rf_step != (u8)IWL_CFG_ANY &&
- dev_info->rf_step != rf_step)
+ if (dev_info->match_discrete && dev_info->discrete != discrete)
continue;
return dev_info;
@@ -1446,245 +1139,47 @@ iwl_pci_find_dev_info(u16 device, u16 subsystem_device,
}
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_pci_find_dev_info);
-static void iwl_pcie_recheck_me_status(struct work_struct *wk)
-{
- struct iwl_trans *trans = container_of(wk, typeof(*trans),
- me_recheck_wk.work);
- u32 val;
-
- val = iwl_read32(trans, CSR_HW_IF_CONFIG_REG);
- trans->me_present = !!(val & CSR_HW_IF_CONFIG_REG_IAMT_UP);
-}
-
-static void iwl_pcie_check_me_status(struct iwl_trans *trans)
-{
- u32 val;
-
- trans->me_present = -1;
-
- INIT_DELAYED_WORK(&trans->me_recheck_wk,
- iwl_pcie_recheck_me_status);
-
- /* we don't have a good way of determining this until BZ */
- if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
- return;
-
- val = iwl_read_prph(trans, CNVI_SCU_REG_FOR_ECO_1);
- if (val & CNVI_SCU_REG_FOR_ECO_1_WIAMT_KNOWN) {
- trans->me_present =
- !!(val & CNVI_SCU_REG_FOR_ECO_1_WIAMT_PRESENT);
- return;
- }
-
- val = iwl_read32(trans, CSR_HW_IF_CONFIG_REG);
- if (val & (CSR_HW_IF_CONFIG_REG_ME_OWN |
- CSR_HW_IF_CONFIG_REG_IAMT_UP)) {
- trans->me_present = 1;
- return;
- }
-
- /* recheck again later, ME might still be initializing */
- schedule_delayed_work(&trans->me_recheck_wk, HZ);
-}
-
static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- const struct iwl_cfg_trans_params *trans;
- const struct iwl_cfg *cfg_7265d __maybe_unused = NULL;
- const struct iwl_dev_info *dev_info;
- struct iwl_trans *iwl_trans;
- struct iwl_trans_pcie *trans_pcie;
+ const struct iwl_mac_cfg *mac_cfg = (void *)ent->driver_data;
+ u8 __iomem *hw_base;
+ u32 bar0, hw_rev;
int ret;
- const struct iwl_cfg *cfg;
-
- trans = (void *)(ent->driver_data & ~TRANS_CFG_MARKER);
-
- /*
- * This is needed for backwards compatibility with the old
- * tables, so we don't need to change all the config structs
- * at the same time. The cfg is used to compare with the old
- * full cfg structs.
- */
- cfg = (void *)(ent->driver_data & ~TRANS_CFG_MARKER);
-
- /* make sure trans is the first element in iwl_cfg */
- BUILD_BUG_ON(offsetof(struct iwl_cfg, trans));
-
- iwl_trans = iwl_trans_pcie_alloc(pdev, ent, trans);
- if (IS_ERR(iwl_trans))
- return PTR_ERR(iwl_trans);
-
- trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans);
-
- iwl_trans_pcie_check_product_reset_status(pdev);
- iwl_trans_pcie_check_product_reset_mode(pdev);
- /*
- * Let's try to grab NIC access early here. Sometimes, NICs may
- * fail to initialize, and if that happens it's better if we see
- * issues early on (and can reprobe, per the logic inside), than
- * first trying to load the firmware etc. and potentially only
- * detecting any problems when the first interface is brought up.
- */
- ret = iwl_pcie_prepare_card_hw(iwl_trans);
- if (!ret) {
- ret = iwl_finish_nic_init(iwl_trans);
+ /* reassign our BAR 0 if invalid due to possible runtime PM races */
+ pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &bar0);
+ if (bar0 == PCI_BASE_ADDRESS_MEM_TYPE_64) {
+ ret = pci_assign_resource(pdev, 0);
if (ret)
- goto out_free_trans;
- if (iwl_trans_grab_nic_access(iwl_trans)) {
- get_crf_id(iwl_trans);
- /* all good */
- iwl_trans_release_nic_access(iwl_trans);
- } else {
- ret = -EIO;
- goto out_free_trans;
- }
- }
-
- iwl_trans->hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID);
-
- /*
- * The RF_ID is set to zero in blank OTP so read version to
- * extract the RF_ID.
- * This is relevant only for family 9000 and up.
- */
- if (iwl_trans->trans_cfg->rf_id &&
- iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_9000 &&
- !CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) && map_crf_id(iwl_trans)) {
- ret = -EINVAL;
- goto out_free_trans;
- }
-
- IWL_INFO(iwl_trans, "PCI dev %04x/%04x, rev=0x%x, rfid=0x%x\n",
- pdev->device, pdev->subsystem_device,
- iwl_trans->hw_rev, iwl_trans->hw_rf_id);
-
- dev_info = iwl_pci_find_dev_info(pdev->device, pdev->subsystem_device,
- CSR_HW_REV_TYPE(iwl_trans->hw_rev),
- iwl_trans->hw_rev_step,
- CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id),
- CSR_HW_RFID_IS_CDB(iwl_trans->hw_rf_id),
- CSR_HW_RFID_IS_JACKET(iwl_trans->hw_rf_id),
- IWL_SUBDEVICE_RF_ID(pdev->subsystem_device),
- IWL_SUBDEVICE_NO_160(pdev->subsystem_device),
- IWL_SUBDEVICE_CORES(pdev->subsystem_device),
- CSR_HW_RFID_STEP(iwl_trans->hw_rf_id));
- if (dev_info) {
- iwl_trans->cfg = dev_info->cfg;
- iwl_trans->name = dev_info->name;
- iwl_trans->no_160 = dev_info->no_160 == IWL_CFG_NO_160;
+ return ret;
}
-#if IS_ENABLED(CONFIG_IWLMVM)
- /*
- * special-case 7265D, it has the same PCI IDs.
- *
- * Note that because we already pass the cfg to the transport above,
- * all the parameters that the transport uses must, until that is
- * changed, be identical to the ones in the 7265D configuration.
- */
- if (cfg == &iwl7265_2ac_cfg)
- cfg_7265d = &iwl7265d_2ac_cfg;
- else if (cfg == &iwl7265_2n_cfg)
- cfg_7265d = &iwl7265d_2n_cfg;
- else if (cfg == &iwl7265_n_cfg)
- cfg_7265d = &iwl7265d_n_cfg;
- if (cfg_7265d &&
- (iwl_trans->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D)
- iwl_trans->cfg = cfg_7265d;
+ ret = pcim_enable_device(pdev);
+ if (ret)
+ return ret;
- /*
- * This is a hack to switch from Qu B0 to Qu C0. We need to
- * do this for all cfgs that use Qu B0, except for those using
- * Jf, which have already been moved to the new table. The
- * rest must be removed once we convert Qu with Hr as well.
- */
- if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QU_C0) {
- if (iwl_trans->cfg == &iwl_ax201_cfg_qu_hr)
- iwl_trans->cfg = &iwl_ax201_cfg_qu_c0_hr_b0;
- else if (iwl_trans->cfg == &killer1650s_2ax_cfg_qu_b0_hr_b0)
- iwl_trans->cfg = &killer1650s_2ax_cfg_qu_c0_hr_b0;
- else if (iwl_trans->cfg == &killer1650i_2ax_cfg_qu_b0_hr_b0)
- iwl_trans->cfg = &killer1650i_2ax_cfg_qu_c0_hr_b0;
- }
+ pci_set_master(pdev);
- /* same thing for QuZ... */
- if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QUZ) {
- if (iwl_trans->cfg == &iwl_ax201_cfg_qu_hr)
- iwl_trans->cfg = &iwl_ax201_cfg_quz_hr;
- else if (iwl_trans->cfg == &killer1650s_2ax_cfg_qu_b0_hr_b0)
- iwl_trans->cfg = &iwl_ax1650s_cfg_quz_hr;
- else if (iwl_trans->cfg == &killer1650i_2ax_cfg_qu_b0_hr_b0)
- iwl_trans->cfg = &iwl_ax1650i_cfg_quz_hr;
+ ret = pcim_request_all_regions(pdev, DRV_NAME);
+ if (ret) {
+ dev_err(&pdev->dev, "Requesting all PCI BARs failed.\n");
+ return ret;
}
-#endif
- /*
- * If we didn't set the cfg yet, the PCI ID table entry should have
- * been a full config - if yes, use it, otherwise fail.
- */
- if (!iwl_trans->cfg) {
- if (ent->driver_data & TRANS_CFG_MARKER) {
- pr_err("No config found for PCI dev %04x/%04x, rev=0x%x, rfid=0x%x\n",
- pdev->device, pdev->subsystem_device,
- iwl_trans->hw_rev, iwl_trans->hw_rf_id);
- ret = -EINVAL;
- goto out_free_trans;
- }
- iwl_trans->cfg = cfg;
- }
-
- /* if we don't have a name yet, copy name from the old cfg */
- if (!iwl_trans->name)
- iwl_trans->name = iwl_trans->cfg->name;
-
- IWL_INFO(iwl_trans, "Detected %s\n", iwl_trans->name);
-
- if (iwl_trans->trans_cfg->mq_rx_supported) {
- if (WARN_ON(!iwl_trans->cfg->num_rbds)) {
- ret = -EINVAL;
- goto out_free_trans;
- }
- trans_pcie->num_rx_bufs = iwl_trans->cfg->num_rbds;
- } else {
- trans_pcie->num_rx_bufs = RX_QUEUE_SIZE;
+ hw_base = pcim_iomap(pdev, 0, 0);
+ if (!hw_base) {
+ dev_err(&pdev->dev, "Failed to map BAR 0.\n");
+ return -ENOMEM;
}
- if (!iwl_trans->trans_cfg->integrated) {
- u16 link_status;
-
- pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &link_status);
-
- iwl_trans->pcie_link_speed =
- u16_get_bits(link_status, PCI_EXP_LNKSTA_CLS);
+ /* We can't use iwl_read32 because trans wasn't allocated */
+ hw_rev = readl(hw_base + CSR_HW_REV);
+ if (hw_rev == 0xffffffff) {
+ dev_err(&pdev->dev, "HW_REV=0xFFFFFFFF, PCI issues?\n");
+ return -EIO;
}
- ret = iwl_trans_init(iwl_trans);
- if (ret)
- goto out_free_trans;
-
- pci_set_drvdata(pdev, iwl_trans);
-
- iwl_pcie_check_me_status(iwl_trans);
-
- /* try to get ownership so that we'll know if we don't own it */
- iwl_pcie_prepare_card_hw(iwl_trans);
-
- iwl_trans->drv = iwl_drv_start(iwl_trans);
-
- if (IS_ERR(iwl_trans->drv)) {
- ret = PTR_ERR(iwl_trans->drv);
- goto out_free_trans;
- }
-
- /* register transport layer debugfs here */
- iwl_trans_pcie_dbgfs_register(iwl_trans);
-
- return 0;
-
-out_free_trans:
- iwl_trans_pcie_free(iwl_trans);
- return ret;
+ return iwl_pci_gen1_2_probe(pdev, ent, mac_cfg, hw_base, hw_rev);
}
static void iwl_pci_remove(struct pci_dev *pdev)
@@ -1694,11 +1189,7 @@ static void iwl_pci_remove(struct pci_dev *pdev)
if (!trans)
return;
- cancel_delayed_work_sync(&trans->me_recheck_wk);
-
- iwl_drv_stop(trans->drv);
-
- iwl_trans_pcie_free(trans);
+ iwl_pcie_gen1_2_remove(trans);
}
#ifdef CONFIG_PM_SLEEP
@@ -1740,11 +1231,15 @@ static int _iwl_pci_resume(struct device *device, bool restore)
* Note: MAC (bits 0:7) will be cleared upon suspend even with wowlan,
* but not bits [15:8]. So if we have bits set in lower word, assume
* the device is alive.
+ * Alternatively, if the scratch value is 0xFFFFFFFF, then we no longer
+ * have access to the device and consider it powered off.
* For older devices, just try silently to grab the NIC.
*/
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
- if (!(iwl_read32(trans, CSR_FUNC_SCRATCH) &
- CSR_FUNC_SCRATCH_POWER_OFF_MASK))
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
+ u32 scratch = iwl_read32(trans, CSR_FUNC_SCRATCH);
+
+ if (!(scratch & CSR_FUNC_SCRATCH_POWER_OFF_MASK) ||
+ scratch == ~0U)
device_was_powered_off = true;
} else {
/*
@@ -1766,7 +1261,7 @@ static int _iwl_pci_resume(struct device *device, bool restore)
* won't really know how to recover.
*/
iwl_pcie_prepare_card_hw(trans);
- iwl_finish_nic_init(trans);
+ iwl_trans_activate_nic(trans);
iwl_op_mode_device_powered_off(trans->op_mode);
}
@@ -1817,12 +1312,21 @@ static const struct dev_pm_ops iwl_dev_pm_ops = {
#endif /* CONFIG_PM_SLEEP */
+static void iwl_pci_dump(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+ struct iwl_trans *trans = pci_get_drvdata(pdev);
+
+ iwl_op_mode_dump(trans->op_mode);
+}
+
static struct pci_driver iwl_pci_driver = {
.name = DRV_NAME,
.id_table = iwl_hw_card_ids,
.probe = iwl_pci_probe,
.remove = iwl_pci_remove,
.driver.pm = IWL_PM_OPS,
+ .driver.coredump = iwl_pci_dump,
};
int __must_check iwl_pci_register_driver(void)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h
index 114a9195ad7f..207c56e338dd 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h
@@ -22,7 +22,7 @@
#include "iwl-io.h"
#include "iwl-op-mode.h"
#include "iwl-drv.h"
-#include "iwl-context-info.h"
+#include "pcie/iwl-context-info.h"
/*
* RX related structures and functions
@@ -39,7 +39,7 @@ struct iwl_host_cmd;
* trans_pcie layer */
/**
- * struct iwl_rx_mem_buffer
+ * struct iwl_rx_mem_buffer - driver-side RX buffer descriptor
* @page_dma: bus address of rxb page
* @page: driver's pointer to the rxb page
* @list: list entry for the membuffer
@@ -190,11 +190,12 @@ struct iwl_rb_allocator {
* iwl_get_closed_rb_stts - get closed rb stts from different structs
* @trans: transport pointer (for configuration)
* @rxq: the rxq to get the rb stts from
+ * Return: last closed RB index
*/
static inline u16 iwl_get_closed_rb_stts(struct iwl_trans *trans,
struct iwl_rxq *rxq)
{
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
__le16 *rb_stts = rxq->rb_stts;
return le16_to_cpu(READ_ONCE(*rb_stts));
@@ -269,6 +270,7 @@ enum iwl_pcie_fw_reset_state {
FW_RESET_REQUESTED,
FW_RESET_OK,
FW_RESET_ERROR,
+ FW_RESET_TOP_REQUESTED,
};
/**
@@ -288,22 +290,14 @@ enum iwl_pcie_imr_status {
/**
* struct iwl_pcie_txqs - TX queues data
*
- * @bc_table_dword: true if the BC table expects DWORD (as opposed to bytes)
- * @page_offs: offset from skb->cb to mac header page pointer
- * @dev_cmd_offs: offset from skb->cb to iwl_device_tx_cmd pointer
* @queue_used: bit mask of used queues
* @queue_stopped: bit mask of stopped queues
* @txq: array of TXQ data structures representing the TXQs
* @scd_bc_tbls: gen1 pointer to the byte count table of the scheduler
- * @queue_alloc_cmd_ver: queue allocation command version
* @bc_pool: bytecount DMA allocations pool
* @bc_tbl_size: bytecount table size
* @tso_hdr_page: page allocated (per CPU) for A-MSDU headers when doing TSO
* (and similar usage)
- * @cmd: command queue data
- * @cmd.fifo: FIFO number
- * @cmd.q_id: queue ID
- * @cmd.wdg_timeout: watchdog timeout
* @tfd: TFD data
* @tfd.max_tbs: max number of buffers per TFD
* @tfd.size: TFD size
@@ -315,26 +309,15 @@ struct iwl_pcie_txqs {
struct iwl_txq *txq[IWL_MAX_TVQM_QUEUES];
struct dma_pool *bc_pool;
size_t bc_tbl_size;
- bool bc_table_dword;
- u8 page_offs;
- u8 dev_cmd_offs;
struct iwl_tso_hdr_page __percpu *tso_hdr_page;
struct {
- u8 fifo;
- u8 q_id;
- unsigned int wdg_timeout;
- } cmd;
-
- struct {
u8 max_tbs;
u16 size;
u8 addr_size;
} tfd;
struct iwl_dma_ptr scd_bc_tbls;
-
- u8 queue_alloc_cmd_ver;
};
/**
@@ -344,7 +327,7 @@ struct iwl_pcie_txqs {
* @global_table: table mapping received VID from hw to rxb
* @rba: allocator for RX replenishing
* @ctxt_info: context information for FW self init
- * @ctxt_info_gen3: context information for gen3 devices
+ * @ctxt_info_v2: context information for v1 devices
* @prph_info: prph info for self init
* @prph_scratch: prph scratch for self init
* @ctxt_info_dma_addr: dma addr of context information
@@ -352,6 +335,7 @@ struct iwl_pcie_txqs {
* @prph_scratch_dma_addr: dma addr of prph scratch
* @ctxt_info_dma_addr: dma addr of context information
* @iml: image loader image virtual address
+ * @iml_len: image loader image size
* @iml_dma_addr: image loader image DMA address
* @trans: pointer to the generic transport area
* @scd_base_addr: scheduler sram base address in SRAM
@@ -363,9 +347,6 @@ struct iwl_pcie_txqs {
* @hw_base: pci hardware address support
* @ucode_write_complete: indicates that the ucode has been copied.
* @ucode_write_waitq: wait queue for uCode load
- * @cmd_queue - command queue number
- * @rx_buf_size: Rx buffer size
- * @scd_set_active: should the transport configure the SCD for HCMD queue
* @rx_page_order: page order for receive buffer size
* @rx_buf_bytes: RX buffer (RB) size in bytes
* @reg_lock: protect hw register access
@@ -402,23 +383,28 @@ struct iwl_pcie_txqs {
* @irq_lock: lock to synchronize IRQ handling
* @txq_memory: TXQ allocation array
* @sx_waitq: waitqueue for Sx transitions
- * @sx_complete: completion for Sx transitions
- * @pcie_dbg_dumped_once: indicates PCIe regs were dumped already
+ * @sx_state: state tracking Sx transitions
* @opmode_down: indicates opmode went away
* @num_rx_bufs: number of RX buffers to allocate/use
- * @no_reclaim_cmds: special commands not using reclaim flow
- * (firmware workaround)
- * @n_no_reclaim_cmds: number of special commands not using reclaim flow
* @affinity_mask: IRQ affinity mask for each RX queue
* @debug_rfkill: RF-kill debugging state, -1 for unset, 0/1 for radio
* enable/disable
- * @fw_reset_handshake: indicates FW reset handshake is needed
* @fw_reset_state: state of FW reset handshake
* @fw_reset_waitq: waitqueue for FW reset handshake
* @is_down: indicates the NIC is down
* @isr_stats: interrupt statistics
* @napi_dev: (fake) netdev for NAPI registration
* @txqs: transport tx queues data.
+ * @me_present: WiAMT/CSME is detected as present (1), not present (0)
+ * or unknown (-1, so can still use it as a boolean safely)
+ * @me_recheck_wk: worker to recheck WiAMT/CSME presence
+ * @invalid_tx_cmd: invalid TX command buffer
+ * @wait_command_queue: wait queue for sync commands
+ * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
+ * The user should use iwl_trans_{alloc,free}_tx_cmd.
+ * @dev_cmd_pool_name: name for the TX command allocation pool
+ * @pm_support: set to true in start_hw if link pm is supported
+ * @ltr_enabled: set to true if the LTR is enabled
*/
struct iwl_trans_pcie {
struct iwl_rxq *rxq;
@@ -427,11 +413,12 @@ struct iwl_trans_pcie {
struct iwl_rb_allocator rba;
union {
struct iwl_context_info *ctxt_info;
- struct iwl_context_info_gen3 *ctxt_info_gen3;
+ struct iwl_context_info_v2 *ctxt_info_v2;
};
struct iwl_prph_info *prph_info;
struct iwl_prph_scratch *prph_scratch;
void *iml;
+ size_t iml_len;
dma_addr_t ctxt_info_dma_addr;
dma_addr_t prph_info_dma_addr;
dma_addr_t prph_scratch_dma_addr;
@@ -466,17 +453,17 @@ struct iwl_trans_pcie {
u8 __iomem *hw_base;
bool ucode_write_complete;
- bool sx_complete;
+ enum {
+ IWL_SX_INVALID = 0,
+ IWL_SX_WAITING,
+ IWL_SX_ERROR,
+ IWL_SX_COMPLETE,
+ } sx_state;
wait_queue_head_t ucode_write_waitq;
wait_queue_head_t sx_waitq;
- u8 n_no_reclaim_cmds;
- u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS];
u16 num_rx_bufs;
- enum iwl_amsdu_size rx_buf_size;
- bool scd_set_active;
- bool pcie_dbg_dumped_once;
u32 rx_page_order;
u32 rx_buf_bytes;
u32 supported_dma_mask;
@@ -510,7 +497,6 @@ struct iwl_trans_pcie {
void *base_rb_stts;
dma_addr_t base_rb_stts_dma;
- bool fw_reset_handshake;
enum iwl_pcie_fw_reset_state fw_reset_state;
wait_queue_head_t fw_reset_waitq;
enum iwl_pcie_imr_status imr_status;
@@ -518,6 +504,19 @@ struct iwl_trans_pcie {
char rf_name[32];
struct iwl_pcie_txqs txqs;
+
+ s8 me_present;
+ struct delayed_work me_recheck_wk;
+
+ struct iwl_dma_ptr invalid_tx_cmd;
+
+ wait_queue_head_t wait_command_queue;
+
+ struct kmem_cache *dev_cmd_pool;
+ char dev_cmd_pool_name[50];
+
+ bool pm_support;
+ bool ltr_enabled;
};
static inline struct iwl_trans_pcie *
@@ -550,10 +549,6 @@ iwl_trans_pcie_get_trans(struct iwl_trans_pcie *trans_pcie)
* Convention: trans API functions: iwl_trans_pcie_XXX
* Other functions: iwl_pcie_XXX
*/
-struct iwl_trans
-*iwl_trans_pcie_alloc(struct pci_dev *pdev,
- const struct pci_device_id *ent,
- const struct iwl_cfg_trans_params *cfg_trans);
void iwl_trans_pcie_free(struct iwl_trans *trans);
void iwl_trans_pcie_free_pnvm_dram_regions(struct iwl_dram_regions *dram_regions,
struct device *dev);
@@ -623,7 +618,7 @@ struct iwl_tso_page_info {
IWL_TSO_PAGE_DATA_SIZE))
int iwl_pcie_tx_init(struct iwl_trans *trans);
-void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr);
+void iwl_pcie_tx_start(struct iwl_trans *trans);
int iwl_pcie_tx_stop(struct iwl_trans *trans);
void iwl_pcie_tx_free(struct iwl_trans *trans);
bool iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int queue, u16 ssn,
@@ -679,7 +674,7 @@ static inline void *iwl_txq_get_tfd(struct iwl_trans *trans,
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- if (trans->trans_cfg->gen2)
+ if (trans->mac_cfg->gen2)
idx = iwl_txq_get_cmd_index(txq, idx);
return (u8 *)txq->tfds + trans_pcie->txqs.tfd.size * idx;
@@ -714,22 +709,24 @@ static inline void iwl_txq_stop(struct iwl_trans *trans, struct iwl_txq *txq)
* iwl_txq_inc_wrap - increment queue index, wrap back to beginning
* @trans: the transport (for configuration data)
* @index: current index
+ * Return: the queue index incremented, subject to wrapping
*/
static inline int iwl_txq_inc_wrap(struct iwl_trans *trans, int index)
{
return ++index &
- (trans->trans_cfg->base_params->max_tfd_queue_size - 1);
+ (trans->mac_cfg->base->max_tfd_queue_size - 1);
}
/**
* iwl_txq_dec_wrap - decrement queue index, wrap back to end
* @trans: the transport (for configuration data)
* @index: current index
+ * Return: the queue index decremented, subject to wrapping
*/
static inline int iwl_txq_dec_wrap(struct iwl_trans *trans, int index)
{
return --index &
- (trans->trans_cfg->base_params->max_tfd_queue_size - 1);
+ (trans->mac_cfg->base->max_tfd_queue_size - 1);
}
void iwl_txq_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq);
@@ -752,10 +749,12 @@ int iwl_txq_gen2_set_tb(struct iwl_trans *trans,
static inline void iwl_txq_set_tfd_invalid_gen2(struct iwl_trans *trans,
struct iwl_tfh_tfd *tfd)
{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
tfd->num_tbs = 0;
- iwl_txq_gen2_set_tb(trans, tfd, trans->invalid_tx_cmd.dma,
- trans->invalid_tx_cmd.size);
+ iwl_txq_gen2_set_tb(trans, tfd, trans_pcie->invalid_tx_cmd.dma,
+ trans_pcie->invalid_tx_cmd.size);
}
void iwl_txq_gen2_tfd_unmap(struct iwl_trans *trans,
@@ -782,7 +781,7 @@ static inline u16 iwl_txq_gen1_tfd_tb_get_len(struct iwl_trans *trans,
struct iwl_tfd *tfd;
struct iwl_tfd_tb *tb;
- if (trans->trans_cfg->gen2) {
+ if (trans->mac_cfg->gen2) {
struct iwl_tfh_tfd *tfh_tfd = _tfd;
struct iwl_tfh_tb *tfh_tb = &tfh_tfd->tbs[idx];
@@ -795,6 +794,23 @@ static inline u16 iwl_txq_gen1_tfd_tb_get_len(struct iwl_trans *trans,
return le16_to_cpu(tb->hi_n_len) >> 4;
}
+static inline struct iwl_device_tx_cmd *
+iwl_pcie_gen1_2_alloc_tx_cmd(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ return kmem_cache_zalloc(trans_pcie->dev_cmd_pool, GFP_ATOMIC);
+}
+
+static inline void
+iwl_pcie_gen1_2_free_tx_cmd(struct iwl_trans *trans,
+ struct iwl_device_tx_cmd *dev_cmd)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ kmem_cache_free(trans_pcie->dev_cmd_pool, dev_cmd);
+}
+
void iwl_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
struct sk_buff_head *skbs, bool is_flush);
void iwl_pcie_set_q_ptrs(struct iwl_trans *trans, int txq_id, int ptr);
@@ -830,6 +846,8 @@ static inline void _iwl_disable_interrupts(struct iwl_trans *trans)
trans_pcie->fh_init_mask);
iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD,
trans_pcie->hw_init_mask);
+ trans_pcie->fh_mask = 0;
+ trans_pcie->hw_mask = 0;
}
IWL_DEBUG_ISR(trans, "Disabled interrupts\n");
}
@@ -940,11 +958,13 @@ static inline void iwl_enable_fw_load_int(struct iwl_trans *trans)
}
}
-static inline void iwl_enable_fw_load_int_ctx_info(struct iwl_trans *trans)
+static inline void iwl_enable_fw_load_int_ctx_info(struct iwl_trans *trans,
+ bool top_reset)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- IWL_DEBUG_ISR(trans, "Enabling ALIVE interrupt only\n");
+ IWL_DEBUG_ISR(trans, "Enabling %s interrupt only\n",
+ top_reset ? "RESET" : "ALIVE");
if (!trans_pcie->msix_enabled) {
/*
@@ -954,11 +974,20 @@ static inline void iwl_enable_fw_load_int_ctx_info(struct iwl_trans *trans)
* RX interrupt which will allow us to receive the ALIVE
* notification (which is Rx) and continue the flow.
*/
- trans_pcie->inta_mask = CSR_INT_BIT_ALIVE | CSR_INT_BIT_FH_RX;
+ if (top_reset)
+ trans_pcie->inta_mask = CSR_INT_BIT_RESET_DONE;
+ else
+ trans_pcie->inta_mask = CSR_INT_BIT_ALIVE |
+ CSR_INT_BIT_FH_RX;
iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
} else {
- iwl_enable_hw_int_msk_msix(trans,
- MSIX_HW_INT_CAUSES_REG_ALIVE);
+ u32 val = top_reset ? MSIX_HW_INT_CAUSES_REG_RESET_DONE
+ : MSIX_HW_INT_CAUSES_REG_ALIVE;
+
+ iwl_enable_hw_int_msk_msix(trans, val);
+
+ if (top_reset)
+ return;
/*
* Leave all the FH causes enabled to get the ALIVE
* notification.
@@ -1001,11 +1030,12 @@ static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
} else {
iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD,
trans_pcie->fh_init_mask);
+ trans_pcie->fh_mask = 0;
iwl_enable_hw_int_msk_msix(trans,
MSIX_HW_INT_CAUSES_REG_RF_KILL);
}
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_9000) {
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_9000) {
/*
* On 9000-series devices this bit isn't enabled by default, so
* when we power down the device we need set the bit to allow it
@@ -1031,40 +1061,12 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
}
-static inline void __iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans,
- u32 reg, u32 mask, u32 value)
-{
- u32 v;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
- WARN_ON_ONCE(value & ~mask);
-#endif
-
- v = iwl_read32(trans, reg);
- v &= ~mask;
- v |= value;
- iwl_write32(trans, reg, v);
-}
-
-static inline void __iwl_trans_pcie_clear_bit(struct iwl_trans *trans,
- u32 reg, u32 mask)
-{
- __iwl_trans_pcie_set_bits_mask(trans, reg, mask, 0);
-}
-
-static inline void __iwl_trans_pcie_set_bit(struct iwl_trans *trans,
- u32 reg, u32 mask)
-{
- __iwl_trans_pcie_set_bits_mask(trans, reg, mask, mask);
-}
-
static inline bool iwl_pcie_dbg_on(struct iwl_trans *trans)
{
return (trans->dbg.dest_tlv || iwl_trans_dbg_ini_valid(trans));
}
void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state, bool from_irq);
-void iwl_trans_pcie_dump_regs(struct iwl_trans *trans);
#ifdef CONFIG_IWLWIFI_DEBUGFS
void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans);
@@ -1076,8 +1078,8 @@ static inline void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) { }
void iwl_pcie_rx_allocator_work(struct work_struct *data);
/* common trans ops for all generations transports */
-void iwl_trans_pcie_configure(struct iwl_trans *trans,
- const struct iwl_trans_config *trans_cfg);
+void iwl_pcie_gen1_2_op_mode_enter(struct iwl_trans *trans);
+int _iwl_trans_pcie_start_hw(struct iwl_trans *trans);
int iwl_trans_pcie_start_hw(struct iwl_trans *trans);
void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans);
void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val);
@@ -1087,17 +1089,14 @@ 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_write_mem(struct iwl_trans *trans, u32 addr,
- const void *buf, int 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,
const struct iwl_dump_sanitize_ops *sanitize_ops,
void *sanitize_ctx);
int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
- enum iwl_d3_status *status,
- bool test, bool reset);
-int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test, bool reset);
+ bool reset);
+int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool reset);
void iwl_trans_pci_interrupts(struct iwl_trans *trans, bool enable);
void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans);
void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg,
@@ -1107,14 +1106,23 @@ int iwl_trans_pcie_read_config32(struct iwl_trans *trans, u32 ofs,
bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans);
void __releases(nic_access_nobh)
iwl_trans_pcie_release_nic_access(struct iwl_trans *trans);
+void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power);
+int iwl_pci_gen1_2_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent,
+ const struct iwl_mac_cfg *mac_cfg,
+ u8 __iomem *hw_base, u32 hw_rev);
+void iwl_pcie_gen1_2_remove(struct iwl_trans *trans);
/* transport gen 1 exported functions */
-void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr);
+void iwl_trans_pcie_fw_alive(struct iwl_trans *trans);
int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
- const struct fw_img *fw, bool run_in_rfkill);
+ const struct iwl_fw *fw,
+ const struct fw_img *img,
+ bool run_in_rfkill);
void iwl_trans_pcie_stop_device(struct iwl_trans *trans);
/* common functions that are used by gen2 transport */
+void iwl_trans_pcie_gen2_op_mode_leave(struct iwl_trans *trans);
int iwl_pcie_gen2_apm_init(struct iwl_trans *trans);
void iwl_pcie_apm_config(struct iwl_trans *trans);
int iwl_pcie_prepare_card_hw(struct iwl_trans *trans);
@@ -1128,16 +1136,14 @@ int iwl_pcie_alloc_dma_ptr(struct iwl_trans *trans,
struct iwl_dma_ptr *ptr, size_t size);
void iwl_pcie_free_dma_ptr(struct iwl_trans *trans, struct iwl_dma_ptr *ptr);
void iwl_pcie_apply_destination(struct iwl_trans *trans);
-
-/* common functions that are used by gen3 transport */
-void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power);
+int iwl_pcie_gen1_2_activate_nic(struct iwl_trans *trans);
/* transport gen 2 exported functions */
int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
- const struct fw_img *fw, bool run_in_rfkill);
+ const struct iwl_fw *fw,
+ const struct fw_img *img,
+ bool run_in_rfkill);
void iwl_trans_pcie_gen2_fw_alive(struct iwl_trans *trans);
-int iwl_trans_pcie_gen2_send_hcmd(struct iwl_trans *trans,
- struct iwl_host_cmd *cmd);
void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans);
int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd);
@@ -1150,4 +1156,17 @@ 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);
+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);
+
+ return trans_pcie->pm_support;
+}
+
+static inline bool iwl_pcie_gen1_2_is_ltr_enabled(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ return trans_pcie->ltr_enabled;
+}
#endif /* __iwl_trans_int_pcie_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c
index 4a4f8de4efe2..619a9505e6d9 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c
@@ -12,7 +12,8 @@
#include "iwl-io.h"
#include "internal.h"
#include "iwl-op-mode.h"
-#include "iwl-context-info-gen3.h"
+#include "pcie/iwl-context-info-v2.h"
+#include "fw/dbg.h"
/******************************************************************************
*
@@ -143,12 +144,12 @@ static inline __le32 iwl_pcie_dma_addr2rbd_ptr(dma_addr_t dma_addr)
*/
int iwl_pcie_rx_stop(struct iwl_trans *trans)
{
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
/* TODO: remove this once fw does it */
- iwl_write_umac_prph(trans, RFH_RXF_DMA_CFG_GEN3, 0);
- return iwl_poll_umac_prph_bit(trans, RFH_GEN_STATUS_GEN3,
+ iwl_write_umac_prph(trans, RFH_RXF_DMA_CFG_AX210, 0);
+ return iwl_poll_umac_prph_bit(trans, RFH_GEN_STATUS_AX210,
RXF_DMA_IDLE, RXF_DMA_IDLE, 1000);
- } else if (trans->trans_cfg->mq_rx_supported) {
+ } else if (trans->mac_cfg->mq_rx_supported) {
iwl_write_prph(trans, RFH_RXF_DMA_CFG, 0);
return iwl_poll_prph_bit(trans, RFH_GEN_STATUS,
RXF_DMA_IDLE, RXF_DMA_IDLE, 1000);
@@ -175,7 +176,7 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
* 1. shadow registers aren't enabled
* 2. there is a chance that the NIC is asleep
*/
- if (!trans->trans_cfg->base_params->shadow_reg_enable &&
+ if (!trans->mac_cfg->base->shadow_reg_enable &&
test_bit(STATUS_TPOWER_PMI, &trans->status)) {
reg = iwl_read32(trans, CSR_UCODE_DRV_GP1);
@@ -190,9 +191,9 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
}
rxq->write_actual = round_down(rxq->write, 8);
- if (!trans->trans_cfg->mq_rx_supported)
+ if (!trans->mac_cfg->mq_rx_supported)
iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual);
- else if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ else if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
iwl_write32(trans, HBUS_TARG_WRPTR, rxq->write_actual |
HBUS_TARG_WRPTR_RX_Q(rxq->id));
else
@@ -205,7 +206,7 @@ static void iwl_pcie_rxq_check_wrptr(struct iwl_trans *trans)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int i;
- for (i = 0; i < trans->num_rx_queues; i++) {
+ for (i = 0; i < trans->info.num_rxqs; i++) {
struct iwl_rxq *rxq = &trans_pcie->rxq[i];
if (!rxq->need_update)
@@ -221,7 +222,7 @@ static void iwl_pcie_restock_bd(struct iwl_trans *trans,
struct iwl_rxq *rxq,
struct iwl_rx_mem_buffer *rxb)
{
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
struct iwl_rx_transfer_desc *bd = rxq->bd;
BUILD_BUG_ON(sizeof(*bd) != 2 * sizeof(u64));
@@ -348,7 +349,7 @@ static void iwl_pcie_rxsq_restock(struct iwl_trans *trans,
static
void iwl_pcie_rxq_restock(struct iwl_trans *trans, struct iwl_rxq *rxq)
{
- if (trans->trans_cfg->mq_rx_supported)
+ if (trans->mac_cfg->mq_rx_supported)
iwl_pcie_rxmq_restock(trans, rxq);
else
iwl_pcie_rxsq_restock(trans, rxq);
@@ -362,8 +363,8 @@ static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans,
u32 *offset, gfp_t priority)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- unsigned int rbsize = iwl_trans_get_rb_size(trans_pcie->rx_buf_size);
unsigned int allocsize = PAGE_SIZE << trans_pcie->rx_page_order;
+ unsigned int rbsize = trans_pcie->rx_buf_bytes;
struct page *page;
gfp_t gfp_mask = priority;
@@ -657,19 +658,19 @@ void iwl_pcie_rx_allocator_work(struct work_struct *data)
static int iwl_pcie_free_bd_size(struct iwl_trans *trans)
{
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
return sizeof(struct iwl_rx_transfer_desc);
- return trans->trans_cfg->mq_rx_supported ?
+ return trans->mac_cfg->mq_rx_supported ?
sizeof(__le64) : sizeof(__le32);
}
static int iwl_pcie_used_bd_size(struct iwl_trans *trans)
{
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
return sizeof(struct iwl_rx_completion_desc_bz);
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
return sizeof(struct iwl_rx_completion_desc);
return sizeof(__le32);
@@ -701,7 +702,7 @@ static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans,
static size_t iwl_pcie_rb_stts_size(struct iwl_trans *trans)
{
- bool use_rx_td = (trans->trans_cfg->device_family >=
+ bool use_rx_td = (trans->mac_cfg->device_family >=
IWL_DEVICE_FAMILY_AX210);
if (use_rx_td)
@@ -720,8 +721,8 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
int free_size;
spin_lock_init(&rxq->lock);
- if (trans->trans_cfg->mq_rx_supported)
- rxq->queue_size = trans->cfg->num_rbds;
+ if (trans->mac_cfg->mq_rx_supported)
+ rxq->queue_size = iwl_trans_get_num_rbds(trans);
else
rxq->queue_size = RX_QUEUE_SIZE;
@@ -736,7 +737,7 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
if (!rxq->bd)
goto err;
- if (trans->trans_cfg->mq_rx_supported) {
+ if (trans->mac_cfg->mq_rx_supported) {
rxq->used_bd = dma_alloc_coherent(dev,
iwl_pcie_used_bd_size(trans) *
rxq->queue_size,
@@ -753,7 +754,7 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
return 0;
err:
- for (i = 0; i < trans->num_rx_queues; i++) {
+ for (i = 0; i < trans->info.num_rxqs; i++) {
struct iwl_rxq *rxq = &trans_pcie->rxq[i];
iwl_pcie_free_rxq_dma(trans, rxq);
@@ -772,7 +773,7 @@ static int iwl_pcie_rx_alloc(struct iwl_trans *trans)
if (WARN_ON(trans_pcie->rxq))
return -EINVAL;
- trans_pcie->rxq = kcalloc(trans->num_rx_queues, sizeof(struct iwl_rxq),
+ trans_pcie->rxq = kcalloc(trans->info.num_rxqs, sizeof(struct iwl_rxq),
GFP_KERNEL);
trans_pcie->rx_pool = kcalloc(RX_POOL_SIZE(trans_pcie->num_rx_bufs),
sizeof(trans_pcie->rx_pool[0]),
@@ -795,7 +796,7 @@ static int iwl_pcie_rx_alloc(struct iwl_trans *trans)
*/
trans_pcie->base_rb_stts =
dma_alloc_coherent(trans->dev,
- rb_stts_size * trans->num_rx_queues,
+ rb_stts_size * trans->info.num_rxqs,
&trans_pcie->base_rb_stts_dma,
GFP_KERNEL);
if (!trans_pcie->base_rb_stts) {
@@ -803,7 +804,7 @@ static int iwl_pcie_rx_alloc(struct iwl_trans *trans)
goto err;
}
- for (i = 0; i < trans->num_rx_queues; i++) {
+ for (i = 0; i < trans->info.num_rxqs; i++) {
struct iwl_rxq *rxq = &trans_pcie->rxq[i];
rxq->id = i;
@@ -816,7 +817,7 @@ static int iwl_pcie_rx_alloc(struct iwl_trans *trans)
err:
if (trans_pcie->base_rb_stts) {
dma_free_coherent(trans->dev,
- rb_stts_size * trans->num_rx_queues,
+ rb_stts_size * trans->info.num_rxqs,
trans_pcie->base_rb_stts,
trans_pcie->base_rb_stts_dma);
trans_pcie->base_rb_stts = NULL;
@@ -834,11 +835,10 @@ err:
static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
u32 rb_size;
const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
- switch (trans_pcie->rx_buf_size) {
+ switch (trans->conf.rx_buf_size) {
case IWL_AMSDU_4K:
rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
break;
@@ -906,7 +906,7 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans)
u32 rb_size, enabled = 0;
int i;
- switch (trans_pcie->rx_buf_size) {
+ switch (trans->conf.rx_buf_size) {
case IWL_AMSDU_2K:
rb_size = RFH_RXF_DMA_RB_SIZE_2K;
break;
@@ -932,7 +932,7 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans)
/* disable free amd used rx queue operation */
iwl_write_prph_no_grab(trans, RFH_RXF_RXQ_ACTIVE, 0);
- for (i = 0; i < trans->num_rx_queues; i++) {
+ for (i = 0; i < trans->info.num_rxqs; i++) {
/* Tell device where to find RBD free table in DRAM */
iwl_write_prph64_no_grab(trans,
RFH_Q_FRBDCB_BA_LSB(i),
@@ -976,7 +976,7 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans)
RFH_GEN_CFG_VAL(DEFAULT_RXQ_NUM, 0) |
RFH_GEN_CFG_SERVICE_DMA_SNOOP |
RFH_GEN_CFG_VAL(RB_CHUNK_SIZE,
- trans->trans_cfg->integrated ?
+ trans->mac_cfg->integrated ?
RFH_GEN_CFG_RB_CHUNK_SIZE_64 :
RFH_GEN_CFG_RB_CHUNK_SIZE_128));
/* Enable the relevant rx queues */
@@ -1072,7 +1072,7 @@ void iwl_pcie_rx_napi_sync(struct iwl_trans *trans)
if (unlikely(!trans_pcie->rxq))
return;
- for (i = 0; i < trans->num_rx_queues; i++) {
+ for (i = 0; i < trans->info.num_rxqs; i++) {
struct iwl_rxq *rxq = &trans_pcie->rxq[i];
if (rxq && rxq->napi.poll)
@@ -1109,7 +1109,7 @@ static int _iwl_pcie_rx_init(struct iwl_trans *trans)
for (i = 0; i < RX_QUEUE_SIZE; i++)
def_rxq->queue[i] = NULL;
- for (i = 0; i < trans->num_rx_queues; i++) {
+ for (i = 0; i < trans->info.num_rxqs; i++) {
struct iwl_rxq *rxq = &trans_pcie->rxq[i];
spin_lock_bh(&rxq->lock);
@@ -1122,7 +1122,7 @@ static int _iwl_pcie_rx_init(struct iwl_trans *trans)
rxq->write = 0;
rxq->write_actual = 0;
memset(rxq->rb_stts, 0,
- (trans->trans_cfg->device_family >=
+ (trans->mac_cfg->device_family >=
IWL_DEVICE_FAMILY_AX210) ?
sizeof(__le16) : sizeof(struct iwl_rb_status));
@@ -1144,9 +1144,9 @@ static int _iwl_pcie_rx_init(struct iwl_trans *trans)
}
/* move the pool to the default queue and allocator ownerships */
- queue_size = trans->trans_cfg->mq_rx_supported ?
+ queue_size = trans->mac_cfg->mq_rx_supported ?
trans_pcie->num_rx_bufs - 1 : RX_QUEUE_SIZE;
- allocator_pool_size = trans->num_rx_queues *
+ allocator_pool_size = trans->info.num_rxqs *
(RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC);
num_alloc = queue_size + allocator_pool_size;
@@ -1175,7 +1175,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)
if (ret)
return ret;
- if (trans->trans_cfg->mq_rx_supported)
+ if (trans->mac_cfg->mq_rx_supported)
iwl_pcie_rx_mq_hw_init(trans);
else
iwl_pcie_rx_hw_init(trans, trans_pcie->rxq);
@@ -1223,14 +1223,14 @@ void iwl_pcie_rx_free(struct iwl_trans *trans)
if (trans_pcie->base_rb_stts) {
dma_free_coherent(trans->dev,
- rb_stts_size * trans->num_rx_queues,
+ rb_stts_size * trans->info.num_rxqs,
trans_pcie->base_rb_stts,
trans_pcie->base_rb_stts_dma);
trans_pcie->base_rb_stts = NULL;
trans_pcie->base_rb_stts_dma = 0;
}
- for (i = 0; i < trans->num_rx_queues; i++) {
+ for (i = 0; i < trans->info.num_rxqs; i++) {
struct iwl_rxq *rxq = &trans_pcie->rxq[i];
iwl_pcie_free_rxq_dma(trans, rxq);
@@ -1301,7 +1301,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
int i)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txqs.txq[trans_pcie->txqs.cmd.q_id];
+ struct iwl_txq *txq = trans_pcie->txqs.txq[trans->conf.cmd_queue];
bool page_stolen = false;
int max_len = trans_pcie->rx_buf_bytes;
u32 offset = 0;
@@ -1368,8 +1368,8 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
if (reclaim && !pkt->hdr.group_id) {
int i;
- for (i = 0; i < trans_pcie->n_no_reclaim_cmds; i++) {
- if (trans_pcie->no_reclaim_cmds[i] ==
+ for (i = 0; i < trans->conf.n_no_reclaim_cmds; i++) {
+ if (trans->conf.no_reclaim_cmds[i] ==
pkt->hdr.cmd) {
reclaim = false;
break;
@@ -1408,7 +1408,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
}
page_stolen |= rxcb._page_stolen;
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
break;
}
@@ -1454,18 +1454,18 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans,
BUILD_BUG_ON(sizeof(struct iwl_rx_completion_desc) != 32);
BUILD_BUG_ON(sizeof(struct iwl_rx_completion_desc_bz) != 4);
- if (!trans->trans_cfg->mq_rx_supported) {
+ if (!trans->mac_cfg->mq_rx_supported) {
rxb = rxq->queue[i];
rxq->queue[i] = NULL;
return rxb;
}
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
struct iwl_rx_completion_desc_bz *cd = rxq->used_bd;
vid = le16_to_cpu(cd[i].rbid);
*join = cd[i].flags & IWL_RX_CD_FLAGS_FRAGMENTED;
- } else if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ } else if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
struct iwl_rx_completion_desc *cd = rxq->used_bd;
vid = le16_to_cpu(cd[i].rbid);
@@ -1648,7 +1648,7 @@ irqreturn_t iwl_pcie_irq_rx_msix_handler(int irq, void *dev_id)
trace_iwlwifi_dev_irq_msix(trans->dev, entry, false, 0, 0);
- if (WARN_ON(entry->entry >= trans->num_rx_queues))
+ if (WARN_ON(entry->entry >= trans->info.num_rxqs))
return IRQ_NONE;
if (!trans_pcie->rxq) {
@@ -1683,29 +1683,38 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
/* W/A for WiFi/WiMAX coex and WiMAX own the RF */
if (trans->cfg->internal_wimax_coex &&
- !trans->cfg->apmg_not_supported &&
+ !trans->mac_cfg->base->apmg_not_supported &&
(!(iwl_read_prph(trans, APMG_CLK_CTRL_REG) &
APMS_CLK_VAL_MRB_FUNC_MODE) ||
(iwl_read_prph(trans, APMG_PS_CTRL_REG) &
APMG_PS_CTRL_VAL_RESET_REQ))) {
clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
iwl_op_mode_wimax_active(trans->op_mode);
- wake_up(&trans->wait_command_queue);
+ wake_up(&trans_pcie->wait_command_queue);
return;
}
- for (i = 0; i < trans->trans_cfg->base_params->num_of_queues; i++) {
+ for (i = 0; i < trans->mac_cfg->base->num_of_queues; i++) {
if (!trans_pcie->txqs.txq[i])
continue;
timer_delete(&trans_pcie->txqs.txq[i]->stuck_timer);
}
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_SC) {
+ u32 val = iwl_read32(trans, CSR_IPC_STATE);
+
+ if (val & CSR_IPC_STATE_TOP_RESET_REQ) {
+ IWL_ERR(trans, "FW requested TOP reset for FSEQ\n");
+ trans->do_top_reset = 1;
+ }
+ }
+
/* The STATUS_FW_ERROR bit is set in this function. This must happen
* before we wake up the command caller, to ensure a proper cleanup. */
iwl_trans_fw_error(trans, IWL_ERR_TYPE_IRQ);
clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
- wake_up(&trans->wait_command_queue);
+ wake_up(&trans_pcie->wait_command_queue);
}
static u32 iwl_pcie_int_cause_non_ict(struct iwl_trans *trans)
@@ -1820,7 +1829,7 @@ void iwl_pcie_handle_rfkill_irq(struct iwl_trans *trans, bool from_irq)
&trans->status))
IWL_DEBUG_RF_KILL(trans,
"Rfkill while SYNC HCMD in flight\n");
- wake_up(&trans->wait_command_queue);
+ wake_up(&trans_pcie->wait_command_queue);
} else {
clear_bit(STATUS_RFKILL_HW, &trans->status);
if (trans_pcie->opmode_down)
@@ -1828,6 +1837,59 @@ void iwl_pcie_handle_rfkill_irq(struct iwl_trans *trans, bool from_irq)
}
}
+static void iwl_trans_pcie_handle_reset_interrupt(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ u32 state;
+
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_SC) {
+ u32 val = iwl_read32(trans, CSR_IPC_STATE);
+
+ state = u32_get_bits(val, CSR_IPC_STATE_RESET);
+ IWL_DEBUG_ISR(trans, "IPC state = 0x%x/%d\n", val, state);
+ } else {
+ state = CSR_IPC_STATE_RESET_SW_READY;
+ }
+
+ switch (state) {
+ case CSR_IPC_STATE_RESET_SW_READY:
+ if (trans_pcie->fw_reset_state == FW_RESET_REQUESTED) {
+ IWL_DEBUG_ISR(trans, "Reset flow completed\n");
+ trans_pcie->fw_reset_state = FW_RESET_OK;
+ wake_up(&trans_pcie->fw_reset_waitq);
+ break;
+ }
+ fallthrough;
+ case CSR_IPC_STATE_RESET_TOP_READY:
+ if (trans_pcie->fw_reset_state == FW_RESET_TOP_REQUESTED) {
+ IWL_DEBUG_ISR(trans, "TOP Reset continues\n");
+ trans_pcie->fw_reset_state = FW_RESET_OK;
+ wake_up(&trans_pcie->fw_reset_waitq);
+ break;
+ }
+ fallthrough;
+ case CSR_IPC_STATE_RESET_NONE:
+ IWL_FW_CHECK_FAILED(trans,
+ "Invalid reset interrupt (state=%d)!\n",
+ state);
+ break;
+ case CSR_IPC_STATE_RESET_TOP_FOLLOWER:
+ if (trans_pcie->fw_reset_state == FW_RESET_REQUESTED) {
+ /* if we were in reset, wake that up */
+ IWL_INFO(trans,
+ "TOP reset from BT while doing reset\n");
+ trans_pcie->fw_reset_state = FW_RESET_OK;
+ wake_up(&trans_pcie->fw_reset_waitq);
+ } else {
+ IWL_INFO(trans, "TOP reset from BT\n");
+ trans->state = IWL_TRANS_NO_FW;
+ iwl_trans_schedule_reset(trans,
+ IWL_ERR_TYPE_TOP_RESET_BY_BT);
+ }
+ break;
+ }
+}
+
irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
{
struct iwl_trans *trans = dev_id;
@@ -1936,7 +1998,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
if (inta & CSR_INT_BIT_ALIVE) {
IWL_DEBUG_ISR(trans, "Alive interrupt\n");
isr_stats->alive++;
- if (trans->trans_cfg->gen2) {
+ if (trans->mac_cfg->gen2) {
/*
* We can restock, since firmware configured
* the RFH
@@ -1947,6 +2009,11 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
handled |= CSR_INT_BIT_ALIVE;
}
+ if (inta & CSR_INT_BIT_RESET_DONE) {
+ iwl_trans_pcie_handle_reset_interrupt(trans);
+ handled |= CSR_INT_BIT_RESET_DONE;
+ }
+
/* Safely ignore these bits for debug checks below */
inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
@@ -1968,7 +2035,12 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
IWL_ERR(trans, "Microcode SW error detected. "
" Restarting 0x%X.\n", inta);
isr_stats->sw++;
- iwl_pcie_irq_handle_error(trans);
+ if (trans_pcie->fw_reset_state == FW_RESET_REQUESTED) {
+ trans_pcie->fw_reset_state = FW_RESET_ERROR;
+ wake_up(&trans_pcie->fw_reset_waitq);
+ } else {
+ iwl_pcie_irq_handle_error(trans);
+ }
handled |= CSR_INT_BIT_SW_ERR;
}
@@ -2074,7 +2146,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
iwl_enable_rfkill_int(trans);
/* Re-enable the ALIVE / Rx interrupt if it occurred */
else if (handled & (CSR_INT_BIT_ALIVE | CSR_INT_BIT_FH_RX))
- iwl_enable_fw_load_int_ctx_info(trans);
+ iwl_enable_fw_load_int_ctx_info(trans, false);
spin_unlock_bh(&trans_pcie->irq_lock);
}
@@ -2289,7 +2361,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
}
}
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
sw_err = inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ;
else
sw_err = inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR;
@@ -2297,9 +2369,13 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
if (inta_hw & MSIX_HW_INT_CAUSES_REG_TOP_FATAL_ERR) {
IWL_ERR(trans, "TOP Fatal error detected, inta_hw=0x%x.\n",
inta_hw);
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
- iwl_trans_pcie_reset(trans,
- IWL_RESET_MODE_PROD_RESET);
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
+ trans->request_top_reset = 1;
+ iwl_op_mode_nic_error(trans->op_mode,
+ IWL_ERR_TYPE_TOP_FATAL_ERROR);
+ iwl_trans_schedule_reset(trans,
+ IWL_ERR_TYPE_TOP_FATAL_ERROR);
+ }
}
/* Error detected by uCode */
@@ -2318,6 +2394,11 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
} else {
iwl_pcie_irq_handle_error(trans);
}
+
+ if (trans_pcie->sx_state == IWL_SX_WAITING) {
+ trans_pcie->sx_state = IWL_SX_ERROR;
+ wake_up(&trans_pcie->sx_waitq);
+ }
}
/* After checking FH register check HW register */
@@ -2338,7 +2419,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
if (inta_hw & MSIX_HW_INT_CAUSES_REG_ALIVE) {
IWL_DEBUG_ISR(trans, "Alive interrupt\n");
isr_stats->alive++;
- if (trans->trans_cfg->gen2) {
+ if (trans->mac_cfg->gen2) {
/* We can restock, since firmware configured the RFH */
iwl_pcie_rxmq_restock(trans, trans_pcie->rxq);
}
@@ -2352,13 +2433,20 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
if (inta_hw & MSIX_HW_INT_CAUSES_REG_WAKEUP && trans_pcie->prph_info) {
u32 sleep_notif =
le32_to_cpu(trans_pcie->prph_info->sleep_notif);
+
if (sleep_notif == IWL_D3_SLEEP_STATUS_SUSPEND ||
sleep_notif == IWL_D3_SLEEP_STATUS_RESUME) {
IWL_DEBUG_ISR(trans,
"Sx interrupt: sleep notification = 0x%x\n",
sleep_notif);
- trans_pcie->sx_complete = true;
- wake_up(&trans_pcie->sx_waitq);
+ if (trans_pcie->sx_state == IWL_SX_WAITING) {
+ trans_pcie->sx_state = IWL_SX_COMPLETE;
+ wake_up(&trans_pcie->sx_waitq);
+ } else {
+ IWL_ERR(trans,
+ "unexpected Sx interrupt (0x%x)\n",
+ sleep_notif);
+ }
} else {
/* uCode wakes up after power-down sleep */
IWL_DEBUG_ISR(trans, "Wakeup interrupt\n");
@@ -2388,11 +2476,8 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
iwl_pcie_irq_handle_error(trans);
}
- if (inta_hw & MSIX_HW_INT_CAUSES_REG_RESET_DONE) {
- IWL_DEBUG_ISR(trans, "Reset flow completed\n");
- trans_pcie->fw_reset_state = FW_RESET_OK;
- wake_up(&trans_pcie->fw_reset_waitq);
- }
+ if (inta_hw & MSIX_HW_INT_CAUSES_REG_RESET_DONE)
+ iwl_trans_pcie_handle_reset_interrupt(trans);
if (!polling)
iwl_pcie_clear_irq(trans, entry->entry);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c
index 472f26f83ba8..b15c5d486527 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c
@@ -5,8 +5,8 @@
*/
#include "iwl-trans.h"
#include "iwl-prph.h"
-#include "iwl-context-info.h"
-#include "iwl-context-info-gen3.h"
+#include "pcie/iwl-context-info.h"
+#include "pcie/iwl-context-info-v2.h"
#include "internal.h"
#include "fw/dbg.h"
@@ -47,7 +47,7 @@ int iwl_pcie_gen2_apm_init(struct iwl_trans *trans)
iwl_pcie_apm_config(trans);
- ret = iwl_finish_nic_init(trans);
+ ret = iwl_trans_activate_nic(trans);
if (ret)
return ret;
@@ -81,13 +81,13 @@ static void iwl_pcie_gen2_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
/* Stop device's DMA activity */
iwl_pcie_apm_stop_master(trans);
- iwl_trans_sw_reset(trans, false);
+ iwl_trans_pcie_sw_reset(trans, false);
/*
* Clear "initialization complete" bit to move adapter from
* D0A* (powered-up Active) --> D0U* (Uninitialized) state.
*/
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
iwl_clear_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_INIT);
else
@@ -102,10 +102,10 @@ void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans)
trans_pcie->fw_reset_state = FW_RESET_REQUESTED;
- if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER,
UREG_NIC_SET_NMI_DRIVER_RESET_HANDSHAKE);
- else if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210)
+ else if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_AX210)
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
UREG_DOORBELL_TO_ISR6_RESET_HANDSHAKE);
else
@@ -117,13 +117,23 @@ void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans)
trans_pcie->fw_reset_state != FW_RESET_REQUESTED,
FW_RESET_TIMEOUT);
if (!ret || trans_pcie->fw_reset_state == FW_RESET_ERROR) {
- u32 inta_hw = iwl_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD);
+ bool reset_done;
+ u32 inta_hw;
+
+ if (trans_pcie->msix_enabled) {
+ inta_hw = iwl_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD);
+ reset_done =
+ inta_hw & MSIX_HW_INT_CAUSES_REG_RESET_DONE;
+ } else {
+ inta_hw = iwl_read32(trans, CSR_INT);
+ reset_done = inta_hw & CSR_INT_BIT_RESET_DONE;
+ }
IWL_ERR(trans,
- "timeout waiting for FW reset ACK (inta_hw=0x%x)\n",
- inta_hw);
+ "timeout waiting for FW reset ACK (inta_hw=0x%x, reset_done %d)\n",
+ inta_hw, reset_done);
- if (!(inta_hw & MSIX_HW_INT_CAUSES_REG_RESET_DONE)) {
+ if (!reset_done) {
struct iwl_fw_error_dump_mode mode = {
.type = IWL_ERR_TYPE_RESET_HS_TIMEOUT,
.context = IWL_ERR_CONTEXT_FROM_OPMODE,
@@ -147,7 +157,7 @@ static void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
return;
if (trans->state >= IWL_TRANS_FW_STARTED &&
- trans_pcie->fw_reset_handshake) {
+ trans->conf.fw_reset_handshake) {
/*
* Reset handshake can dump firmware on timeout, but that
* should assume that the firmware is already dead.
@@ -181,8 +191,8 @@ static void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
}
iwl_pcie_ctxt_info_free_paging(trans);
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
- iwl_pcie_ctxt_info_gen3_free(trans, false);
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ iwl_pcie_ctxt_info_v2_free(trans, false);
else
iwl_pcie_ctxt_info_free(trans);
@@ -190,7 +200,7 @@ static void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
iwl_pcie_gen2_apm_stop(trans, false);
/* re-take ownership to prevent other users from stealing the device */
- iwl_trans_sw_reset(trans, true);
+ iwl_trans_pcie_sw_reset(trans, true);
/*
* Upon stop, the IVAR table gets erased, so msi-x won't
@@ -243,7 +253,7 @@ static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int queue_size = max_t(u32, IWL_CMD_QUEUE_SIZE,
- trans->cfg->min_txq_size);
+ trans->mac_cfg->base->min_txq_size);
int ret;
/* TODO: most of the logic can be removed in A0 - but not in Z0 */
@@ -260,7 +270,7 @@ static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans)
return -ENOMEM;
/* Allocate or reset and init all Tx and Command queues */
- if (iwl_txq_gen2_init(trans, trans_pcie->txqs.cmd.q_id, queue_size))
+ if (iwl_txq_gen2_init(trans, trans->conf.cmd_queue, queue_size))
return -ENOMEM;
/* enable shadow regs in HW */
@@ -281,7 +291,7 @@ static void iwl_pcie_get_rf_name(struct iwl_trans *trans)
if (buf[0])
return;
- switch (CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
+ switch (CSR_HW_RFID_TYPE(trans->info.hw_rf_id)) {
case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_JF):
pos = scnprintf(buf, buflen, "JF");
break;
@@ -305,7 +315,7 @@ static void iwl_pcie_get_rf_name(struct iwl_trans *trans)
break;
case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_WP):
if (SILICON_Z_STEP ==
- CSR_HW_RFID_STEP(trans->hw_rf_id))
+ CSR_HW_RFID_STEP(trans->info.hw_rf_id))
pos = scnprintf(buf, buflen, "WHTC");
else
pos = scnprintf(buf, buflen, "WH");
@@ -314,7 +324,7 @@ static void iwl_pcie_get_rf_name(struct iwl_trans *trans)
return;
}
- switch (CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
+ switch (CSR_HW_RFID_TYPE(trans->info.hw_rf_id)) {
case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_HR):
case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_HR1):
case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_HRCDB):
@@ -337,7 +347,7 @@ static void iwl_pcie_get_rf_name(struct iwl_trans *trans)
}
pos += scnprintf(buf + pos, buflen - pos, ", rfid=0x%x",
- trans->hw_rf_id);
+ trans->info.hw_rf_id);
IWL_INFO(trans, "Detected RF %s\n", buf);
@@ -364,8 +374,8 @@ void iwl_trans_pcie_gen2_fw_alive(struct iwl_trans *trans)
/* now that we got alive we can free the fw image & the context info.
* paging memory cannot be freed included since FW will still use it
*/
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
- iwl_pcie_ctxt_info_gen3_free(trans, true);
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ iwl_pcie_ctxt_info_v2_free(trans, true);
else
iwl_pcie_ctxt_info_free(trans);
@@ -379,6 +389,11 @@ void iwl_trans_pcie_gen2_fw_alive(struct iwl_trans *trans)
iwl_pcie_get_rf_name(trans);
mutex_unlock(&trans_pcie->mutex);
+
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ trans->step_urm = !!(iwl_read_umac_prph(trans,
+ CNVI_PMU_STEP_FLOW) &
+ CNVI_PMU_STEP_FLOW_FORCE_URM);
}
static bool iwl_pcie_set_ltr(struct iwl_trans *trans)
@@ -398,21 +413,21 @@ static bool iwl_pcie_set_ltr(struct iwl_trans *trans)
* initialize the LTR to ~250 usec (see ltr_val above).
* The firmware initializes this again later (to a smaller value).
*/
- if ((trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210 ||
- trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) &&
- !trans->trans_cfg->integrated) {
+ if ((trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_AX210 ||
+ trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_22000) &&
+ !trans->mac_cfg->integrated) {
iwl_write32(trans, CSR_LTR_LONG_VAL_AD, ltr_val);
return true;
}
- if (trans->trans_cfg->integrated &&
- trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) {
+ if (trans->mac_cfg->integrated &&
+ trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_22000) {
iwl_write_prph(trans, HPM_MAC_LTR_CSR, HPM_MAC_LRT_ENABLE_ALL);
iwl_write_prph(trans, HPM_UMAC_LTR, ltr_val);
return true;
}
- if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210) {
+ if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_AX210) {
/* First clear the interrupt, just in case */
iwl_write32(trans, CSR_MSIX_HW_INT_CAUSES_AD,
MSIX_HW_INT_CAUSES_REG_IML);
@@ -469,16 +484,22 @@ static void iwl_pcie_spin_for_iml(struct iwl_trans *trans)
}
int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
- const struct fw_img *fw, bool run_in_rfkill)
+ const struct iwl_fw *fw,
+ const struct fw_img *img,
+ bool run_in_rfkill)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
bool hw_rfkill, keep_ram_busy;
+ bool top_reset_done = false;
int ret;
+ mutex_lock(&trans_pcie->mutex);
+again:
/* This may fail if AMT took ownership of the device */
if (iwl_pcie_prepare_card_hw(trans)) {
IWL_WARN(trans, "Exit HW not ready\n");
- return -EIO;
+ ret = -EIO;
+ goto out;
}
iwl_enable_rfkill_int(trans);
@@ -495,8 +516,6 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
/* Make sure it finished running */
iwl_pcie_synchronize_irqs(trans);
- mutex_lock(&trans_pcie->mutex);
-
/* If platform's RF_KILL switch is NOT set to KILL */
hw_rfkill = iwl_pcie_check_hw_rf_kill(trans);
if (hw_rfkill && !run_in_rfkill) {
@@ -526,22 +545,39 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
goto out;
}
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
- ret = iwl_pcie_ctxt_info_gen3_init(trans, fw);
- else
- ret = iwl_pcie_ctxt_info_init(trans, fw);
- if (ret)
+ if (WARN_ON(trans->do_top_reset &&
+ trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_SC)) {
+ ret = -EINVAL;
goto out;
+ }
+
+ /* we need to wait later - set state */
+ if (trans->do_top_reset)
+ trans_pcie->fw_reset_state = FW_RESET_TOP_REQUESTED;
+
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ if (!top_reset_done) {
+ ret = iwl_pcie_ctxt_info_v2_alloc(trans, fw, img);
+ if (ret)
+ goto out;
+ }
+
+ iwl_pcie_ctxt_info_v2_kick(trans);
+ } else {
+ ret = iwl_pcie_ctxt_info_init(trans, img);
+ if (ret)
+ goto out;
+ }
keep_ram_busy = !iwl_pcie_set_ltr(trans);
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
IWL_DEBUG_POWER(trans, "function scratch register value is 0x%08x\n",
iwl_read32(trans, CSR_FUNC_SCRATCH));
iwl_write32(trans, CSR_FUNC_SCRATCH, CSR_FUNC_SCRATCH_INIT_VALUE);
iwl_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_ROM_START);
- } else if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ } else if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1);
} else {
iwl_write_prph(trans, UREG_CPU_INIT_RUN, 1);
@@ -550,6 +586,43 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
if (keep_ram_busy)
iwl_pcie_spin_for_iml(trans);
+ if (trans->do_top_reset) {
+ trans->do_top_reset = 0;
+
+#define FW_TOP_RESET_TIMEOUT (HZ / 4)
+ ret = wait_event_timeout(trans_pcie->fw_reset_waitq,
+ trans_pcie->fw_reset_state != FW_RESET_TOP_REQUESTED,
+ FW_TOP_RESET_TIMEOUT);
+
+ if (trans_pcie->fw_reset_state != FW_RESET_OK) {
+ if (trans_pcie->fw_reset_state != FW_RESET_TOP_REQUESTED)
+ IWL_ERR(trans,
+ "TOP reset interrupted by error (state %d)!\n",
+ trans_pcie->fw_reset_state);
+ else
+ IWL_ERR(trans, "TOP reset timed out!\n");
+ iwl_op_mode_nic_error(trans->op_mode,
+ IWL_ERR_TYPE_TOP_RESET_FAILED);
+ iwl_trans_schedule_reset(trans,
+ IWL_ERR_TYPE_TOP_RESET_FAILED);
+ ret = -EIO;
+ goto out;
+ }
+
+ msleep(10);
+ IWL_INFO(trans, "TOP reset successful, reinit now\n");
+ /* now load the firmware again properly */
+ ret = _iwl_trans_pcie_start_hw(trans);
+ if (ret) {
+ IWL_ERR(trans, "failed to start HW after TOP reset\n");
+ goto out;
+ }
+ trans_pcie->prph_scratch->ctrl_cfg.control.control_flags &=
+ ~cpu_to_le32(IWL_PRPH_SCRATCH_TOP_RESET);
+ top_reset_done = true;
+ goto again;
+ }
+
/* re-check RF-Kill state since we may have missed the interrupt */
hw_rfkill = iwl_pcie_check_hw_rf_kill(trans);
if (hw_rfkill && !run_in_rfkill)
@@ -559,3 +632,23 @@ out:
mutex_unlock(&trans_pcie->mutex);
return ret;
}
+
+void iwl_trans_pcie_gen2_op_mode_leave(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ mutex_lock(&trans_pcie->mutex);
+
+ /* disable interrupts - don't enable HW RF kill interrupt */
+ iwl_disable_interrupts(trans);
+
+ iwl_pcie_gen2_apm_stop(trans, true);
+
+ iwl_disable_interrupts(trans);
+
+ iwl_pcie_disable_ict(trans);
+
+ mutex_unlock(&trans_pcie->mutex);
+
+ iwl_pcie_synchronize_irqs(trans);
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
index 102a6123bba0..164d060ec617 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
@@ -28,110 +28,57 @@
#include "mei/iwl-mei.h"
#include "internal.h"
#include "iwl-fh.h"
-#include "iwl-context-info-gen3.h"
+#include "pcie/iwl-context-info-v2.h"
+#include "pcie/utils.h"
-/* extended range in FW SRAM */
-#define IWL_FW_MEM_EXTENDED_START 0x40000
-#define IWL_FW_MEM_EXTENDED_END 0x57FFF
+#define IWL_HOST_MON_BLOCK_PEMON 0x00
+#define IWL_HOST_MON_BLOCK_HIPM 0x22
-void iwl_trans_pcie_dump_regs(struct iwl_trans *trans)
-{
-#define PCI_DUMP_SIZE 352
-#define PCI_MEM_DUMP_SIZE 64
-#define PCI_PARENT_DUMP_SIZE 524
-#define PREFIX_LEN 32
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct pci_dev *pdev = trans_pcie->pci_dev;
- u32 i, pos, alloc_size, *ptr, *buf;
- char *prefix;
+#define IWL_HOST_MON_BLOCK_PEMON_VEC0 0x00
+#define IWL_HOST_MON_BLOCK_PEMON_VEC1 0x01
+#define IWL_HOST_MON_BLOCK_PEMON_WFPM 0x06
- if (trans_pcie->pcie_dbg_dumped_once)
- return;
-
- /* Should be a multiple of 4 */
- BUILD_BUG_ON(PCI_DUMP_SIZE > 4096 || PCI_DUMP_SIZE & 0x3);
- BUILD_BUG_ON(PCI_MEM_DUMP_SIZE > 4096 || PCI_MEM_DUMP_SIZE & 0x3);
- BUILD_BUG_ON(PCI_PARENT_DUMP_SIZE > 4096 || PCI_PARENT_DUMP_SIZE & 0x3);
+static void iwl_dump_host_monitor_block(struct iwl_trans *trans,
+ u32 block, u32 vec, u32 iter)
+{
+ int i;
- /* Alloc a max size buffer */
- alloc_size = PCI_ERR_ROOT_ERR_SRC + 4 + PREFIX_LEN;
- alloc_size = max_t(u32, alloc_size, PCI_DUMP_SIZE + PREFIX_LEN);
- alloc_size = max_t(u32, alloc_size, PCI_MEM_DUMP_SIZE + PREFIX_LEN);
- alloc_size = max_t(u32, alloc_size, PCI_PARENT_DUMP_SIZE + PREFIX_LEN);
+ IWL_ERR(trans, "Host monitor block 0x%x vector 0x%x\n", block, vec);
+ iwl_write32(trans, CSR_MONITOR_CFG_REG, (block << 8) | vec);
+ for (i = 0; i < iter; i++)
+ IWL_ERR(trans, " value [iter %d]: 0x%08x\n",
+ i, iwl_read32(trans, CSR_MONITOR_STATUS_REG));
+}
- buf = kmalloc(alloc_size, GFP_ATOMIC);
- if (!buf)
+static void iwl_pcie_dump_host_monitor(struct iwl_trans *trans)
+{
+ switch (trans->mac_cfg->device_family) {
+ case IWL_DEVICE_FAMILY_22000:
+ case IWL_DEVICE_FAMILY_AX210:
+ IWL_ERR(trans, "CSR_RESET = 0x%x\n",
+ iwl_read32(trans, CSR_RESET));
+ iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON,
+ IWL_HOST_MON_BLOCK_PEMON_VEC0, 15);
+ iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON,
+ IWL_HOST_MON_BLOCK_PEMON_VEC1, 15);
+ iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON,
+ IWL_HOST_MON_BLOCK_PEMON_WFPM, 15);
+ iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_HIPM,
+ IWL_HOST_MON_BLOCK_PEMON_VEC0, 1);
+ break;
+ default:
return;
- prefix = (char *)buf + alloc_size - PREFIX_LEN;
-
- IWL_ERR(trans, "iwlwifi transaction failed, dumping registers\n");
-
- /* Print wifi device registers */
- sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));
- IWL_ERR(trans, "iwlwifi device config registers:\n");
- for (i = 0, ptr = buf; i < PCI_DUMP_SIZE; i += 4, ptr++)
- if (pci_read_config_dword(pdev, i, ptr))
- goto err_read;
- print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
-
- IWL_ERR(trans, "iwlwifi device memory mapped registers:\n");
- for (i = 0, ptr = buf; i < PCI_MEM_DUMP_SIZE; i += 4, ptr++)
- *ptr = iwl_read32(trans, i);
- print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
-
- pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
- if (pos) {
- IWL_ERR(trans, "iwlwifi device AER capability structure:\n");
- for (i = 0, ptr = buf; i < PCI_ERR_ROOT_COMMAND; i += 4, ptr++)
- if (pci_read_config_dword(pdev, pos + i, ptr))
- goto err_read;
- print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET,
- 32, 4, buf, i, 0);
- }
-
- /* Print parent device registers next */
- if (!pdev->bus->self)
- goto out;
-
- pdev = pdev->bus->self;
- sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));
-
- IWL_ERR(trans, "iwlwifi parent port (%s) config registers:\n",
- pci_name(pdev));
- for (i = 0, ptr = buf; i < PCI_PARENT_DUMP_SIZE; i += 4, ptr++)
- if (pci_read_config_dword(pdev, i, ptr))
- goto err_read;
- print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
-
- /* Print root port AER registers */
- pos = 0;
- pdev = pcie_find_root_port(pdev);
- if (pdev)
- pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
- if (pos) {
- IWL_ERR(trans, "iwlwifi root port (%s) AER cap structure:\n",
- pci_name(pdev));
- sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));
- for (i = 0, ptr = buf; i <= PCI_ERR_ROOT_ERR_SRC; i += 4, ptr++)
- if (pci_read_config_dword(pdev, pos + i, ptr))
- goto err_read;
- print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32,
- 4, buf, i, 0);
- }
- goto out;
-
-err_read:
- print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
- IWL_ERR(trans, "Read failed at 0x%X\n", i);
-out:
- trans_pcie->pcie_dbg_dumped_once = 1;
- kfree(buf);
+ }
}
+/* extended range in FW SRAM */
+#define IWL_FW_MEM_EXTENDED_START 0x40000
+#define IWL_FW_MEM_EXTENDED_END 0x57FFF
+
int iwl_trans_pcie_sw_reset(struct iwl_trans *trans, bool retake_ownership)
{
/* Reset entire device - do controller reset (results in SHRD_HW_RST) */
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
iwl_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_SW_RESET);
usleep_range(10000, 20000);
@@ -237,7 +184,7 @@ static void iwl_trans_pcie_write_shr(struct iwl_trans *trans, u32 reg, u32 val)
static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux)
{
- if (trans->cfg->apmg_not_supported)
+ if (trans->mac_cfg->base->apmg_not_supported)
return;
if (vaux && pci_pme_capable(to_pci_dev(trans->dev), PCI_D3cold))
@@ -267,13 +214,13 @@ void iwl_pcie_apm_config(struct iwl_trans *trans)
iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_DISABLED);
pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl);
- trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S);
+ trans_pcie->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S);
pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_DEVCTL2, &cap);
- trans->ltr_enabled = cap & PCI_EXP_DEVCTL2_LTR_EN;
+ trans_pcie->ltr_enabled = cap & PCI_EXP_DEVCTL2_LTR_EN;
IWL_DEBUG_POWER(trans, "L1 %sabled - LTR %sabled\n",
(lctl & PCI_EXP_LNKCTL_ASPM_L1) ? "En" : "Dis",
- trans->ltr_enabled ? "En" : "Dis");
+ trans_pcie->ltr_enabled ? "En" : "Dis");
}
/*
@@ -293,7 +240,7 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
*/
/* Disable L0S exit timer (platform NMI Work/Around) */
- if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000)
+ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_8000)
iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS,
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
@@ -317,10 +264,10 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
iwl_pcie_apm_config(trans);
/* Configure analog phase-lock-loop before activating to D0A */
- if (trans->trans_cfg->base_params->pll_cfg)
+ if (trans->mac_cfg->base->pll_cfg)
iwl_set_bit(trans, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL);
- ret = iwl_finish_nic_init(trans);
+ ret = iwl_trans_activate_nic(trans);
if (ret)
return ret;
@@ -353,7 +300,7 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
* bits do not disable clocks. This preserves any hardware
* bits already set by default in "CLK_CTRL_REG" after reset.
*/
- if (!trans->cfg->apmg_not_supported) {
+ if (!trans->mac_cfg->base->apmg_not_supported) {
iwl_write_prph(trans, APMG_CLK_EN_REG,
APMG_CLK_VAL_DMA_CLK_RQT);
udelay(20);
@@ -387,18 +334,18 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
u32 dl_cfg_reg;
/* Force XTAL ON */
- __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_XTAL_ON);
+ iwl_trans_set_bit(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_XTAL_ON);
ret = iwl_trans_pcie_sw_reset(trans, true);
if (!ret)
- ret = iwl_finish_nic_init(trans);
+ ret = iwl_trans_activate_nic(trans);
if (WARN_ON(ret)) {
/* Release XTAL ON request */
- __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_XTAL_ON);
+ iwl_trans_clear_bit(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_XTAL_ON);
return;
}
@@ -449,12 +396,12 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
/* Activates XTAL resources monitor */
- __iwl_trans_pcie_set_bit(trans, CSR_MONITOR_CFG_REG,
- CSR_MONITOR_XTAL_RESOURCES);
+ iwl_trans_set_bit(trans, CSR_MONITOR_CFG_REG,
+ CSR_MONITOR_XTAL_RESOURCES);
/* Release XTAL ON request */
- __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_XTAL_ON);
+ iwl_trans_clear_bit(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_XTAL_ON);
udelay(10);
/* Release APMG XTAL */
@@ -469,24 +416,22 @@ void iwl_pcie_apm_stop_master(struct iwl_trans *trans)
/* stop device's busmaster DMA activity */
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
iwl_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_REQ);
- ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,
- CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,
- 100);
+ ret = iwl_poll_bits(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,
+ 100);
usleep_range(10000, 20000);
} else {
iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
- ret = iwl_poll_bit(trans, CSR_RESET,
- CSR_RESET_REG_FLAG_MASTER_DISABLED,
- CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
+ ret = iwl_poll_bits(trans, CSR_RESET,
+ CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
}
- if (ret < 0)
+ if (ret)
IWL_WARN(trans, "Master Disable Timed Out, 100 usec\n");
IWL_DEBUG_INFO(trans, "stop master\n");
@@ -501,10 +446,10 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
iwl_pcie_apm_init(trans);
/* inform ME that we are leaving */
- if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_7000)
+ if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_7000)
iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_WAKE_ME);
- else if (trans->trans_cfg->device_family >=
+ else if (trans->mac_cfg->device_family >=
IWL_DEVICE_FAMILY_8000) {
iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
CSR_RESET_LINK_PWR_MGMT_DISABLED);
@@ -565,7 +510,7 @@ static int iwl_pcie_nic_init(struct iwl_trans *trans)
return -ENOMEM;
}
- if (trans->trans_cfg->base_params->shadow_reg_enable) {
+ if (trans->mac_cfg->base->shadow_reg_enable) {
/* enable shadow regs in HW */
iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL, 0x800FFFFF);
IWL_DEBUG_INFO(trans, "Enabling shadow registers in device\n");
@@ -585,15 +530,14 @@ static int iwl_pcie_set_hw_ready(struct iwl_trans *trans)
CSR_HW_IF_CONFIG_REG_PCI_OWN_SET);
/* See if we got it */
- ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG,
- CSR_HW_IF_CONFIG_REG_PCI_OWN_SET,
- CSR_HW_IF_CONFIG_REG_PCI_OWN_SET,
- HW_READY_TIMEOUT);
+ ret = iwl_poll_bits(trans, CSR_HW_IF_CONFIG_REG,
+ CSR_HW_IF_CONFIG_REG_PCI_OWN_SET,
+ HW_READY_TIMEOUT);
- if (ret >= 0)
+ if (!ret)
iwl_set_bit(trans, CSR_MBOX_SET_REG, CSR_MBOX_SET_REG_OS_ALIVE);
- IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret < 0 ? " not" : "");
+ IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret ? " not" : "");
return ret;
}
@@ -607,7 +551,7 @@ int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
ret = iwl_pcie_set_hw_ready(trans);
/* If the card is ready, exit 0 */
- if (ret >= 0) {
+ if (!ret) {
trans->csme_own = false;
return 0;
}
@@ -625,7 +569,7 @@ int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
do {
ret = iwl_pcie_set_hw_ready(trans);
- if (ret >= 0) {
+ if (!ret) {
trans->csme_own = false;
return 0;
}
@@ -634,7 +578,7 @@ int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
IWL_DEBUG_INFO(trans,
"Couldn't prepare the card but SAP is connected\n");
trans->csme_own = true;
- if (trans->trans_cfg->device_family !=
+ if (trans->mac_cfg->device_family !=
IWL_DEVICE_FAMILY_9000)
IWL_ERR(trans,
"SAP not supported for this NIC family\n");
@@ -704,7 +648,7 @@ static int iwl_pcie_load_firmware_chunk(struct iwl_trans *trans,
trans_pcie->ucode_write_complete, 5 * HZ);
if (!ret) {
IWL_ERR(trans, "Failed to load firmware chunk!\n");
- iwl_trans_pcie_dump_regs(trans);
+ iwl_trans_pcie_dump_regs(trans, trans_pcie->pci_dev);
return -ETIMEDOUT;
}
@@ -819,7 +763,7 @@ static int iwl_pcie_load_cpu_sections_8000(struct iwl_trans *trans,
iwl_enable_interrupts(trans);
- if (trans->trans_cfg->gen2) {
+ if (trans->mac_cfg->gen2) {
if (cpu == 1)
iwl_write_prph(trans, UREG_UCODE_LOAD_STATUS,
0xFFFF);
@@ -977,7 +921,7 @@ monitor:
if (dest->monitor_mode == EXTERNAL_MODE && fw_mon->size) {
iwl_write_prph(trans, le32_to_cpu(dest->base_reg),
fw_mon->physical >> dest->base_shift);
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_8000)
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_8000)
iwl_write_prph(trans, le32_to_cpu(dest->end_reg),
(fw_mon->physical + fw_mon->size -
256) >> dest->end_shift);
@@ -1153,7 +1097,7 @@ static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans)
*/
iwl_pcie_map_list(trans, causes_list_common,
ARRAY_SIZE(causes_list_common), val);
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
iwl_pcie_map_list(trans, causes_list_bz,
ARRAY_SIZE(causes_list_bz), val);
else
@@ -1175,7 +1119,7 @@ static void iwl_pcie_map_rx_causes(struct iwl_trans *trans)
* the other (N - 2) interrupt vectors.
*/
val = BIT(MSIX_FH_INT_CAUSES_Q(0));
- for (idx = 1; idx < trans->num_rx_queues; idx++) {
+ for (idx = 1; idx < trans->info.num_rxqs; idx++) {
iwl_write8(trans, CSR_MSIX_RX_IVAR(idx),
MSIX_FH_INT_CAUSES_Q(idx - offset));
val |= BIT(MSIX_FH_INT_CAUSES_Q(idx));
@@ -1196,7 +1140,7 @@ void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie)
struct iwl_trans *trans = trans_pcie->trans;
if (!trans_pcie->msix_enabled) {
- if (trans->trans_cfg->mq_rx_supported &&
+ if (trans->mac_cfg->mq_rx_supported &&
test_bit(STATUS_DEVICE_ENABLED, &trans->status))
iwl_write_umac_prph(trans, UREG_CHICK,
UREG_CHICK_MSI_ENABLE);
@@ -1271,7 +1215,7 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool from_irq)
iwl_pcie_rx_stop(trans);
/* Power-down device's busmaster DMA clocks */
- if (!trans->cfg->apmg_not_supported) {
+ if (!trans->mac_cfg->base->apmg_not_supported) {
iwl_write_prph(trans, APMG_CLK_DIS_REG,
APMG_CLK_VAL_DMA_CLK_RQT);
udelay(5);
@@ -1279,7 +1223,7 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool from_irq)
}
/* Make sure (redundant) we've released our request to stay awake */
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
iwl_clear_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ);
else
@@ -1337,7 +1281,9 @@ void iwl_pcie_synchronize_irqs(struct iwl_trans *trans)
}
int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
- const struct fw_img *fw, bool run_in_rfkill)
+ const struct iwl_fw *fw,
+ const struct fw_img *img,
+ bool run_in_rfkill)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
bool hw_rfkill;
@@ -1408,10 +1354,10 @@ int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
/* Load the given image to the HW */
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_8000)
- ret = iwl_pcie_load_given_ucode_8000(trans, fw);
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_8000)
+ ret = iwl_pcie_load_given_ucode_8000(trans, img);
else
- ret = iwl_pcie_load_given_ucode(trans, fw);
+ ret = iwl_pcie_load_given_ucode(trans, img);
/* re-check RF-Kill state since we may have missed the interrupt */
hw_rfkill = iwl_pcie_check_hw_rf_kill(trans);
@@ -1423,10 +1369,10 @@ out:
return ret;
}
-void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr)
+void iwl_trans_pcie_fw_alive(struct iwl_trans *trans)
{
iwl_pcie_reset_ict(trans);
- iwl_pcie_tx_start(trans, scd_addr);
+ iwl_pcie_tx_start(trans);
}
void iwl_trans_pcie_handle_stop_rfkill(struct iwl_trans *trans,
@@ -1485,27 +1431,20 @@ void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state, bool from_irq)
IWL_WARN(trans, "reporting RF_KILL (radio %s)\n",
state ? "disabled" : "enabled");
if (iwl_op_mode_hw_rf_kill(trans->op_mode, state) &&
- !WARN_ON(trans->trans_cfg->gen2))
+ !WARN_ON(trans->mac_cfg->gen2))
_iwl_trans_pcie_stop_device(trans, from_irq);
}
static void iwl_pcie_d3_complete_suspend(struct iwl_trans *trans,
- bool test, bool reset)
+ bool reset)
{
iwl_disable_interrupts(trans);
- /*
- * in testing mode, the host stays awake and the
- * hardware won't be reset (not even partially)
- */
- if (test)
- return;
-
iwl_pcie_disable_ict(trans);
iwl_pcie_synchronize_irqs(trans);
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
iwl_clear_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ);
iwl_clear_bit(trans, CSR_GP_CNTRL,
@@ -1534,33 +1473,44 @@ static int iwl_pcie_d3_handshake(struct iwl_trans *trans, bool suspend)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int ret;
- if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210)
+ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ return 0;
+
+ trans_pcie->sx_state = IWL_SX_WAITING;
+
+ if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_AX210)
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
suspend ? UREG_DOORBELL_TO_ISR6_SUSPEND :
UREG_DOORBELL_TO_ISR6_RESUME);
- else if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ else
iwl_write32(trans, CSR_IPC_SLEEP_CONTROL,
suspend ? CSR_IPC_SLEEP_CONTROL_SUSPEND :
CSR_IPC_SLEEP_CONTROL_RESUME);
- else
- return 0;
ret = wait_event_timeout(trans_pcie->sx_waitq,
- trans_pcie->sx_complete, 2 * HZ);
-
- /* Invalidate it toward next suspend or resume */
- trans_pcie->sx_complete = false;
-
+ trans_pcie->sx_state != IWL_SX_WAITING,
+ 2 * HZ);
if (!ret) {
IWL_ERR(trans, "Timeout %s D3\n",
suspend ? "entering" : "exiting");
- return -ETIMEDOUT;
+ ret = -ETIMEDOUT;
+ } else {
+ ret = 0;
}
- return 0;
+ if (trans_pcie->sx_state == IWL_SX_ERROR) {
+ IWL_ERR(trans, "FW error while %s D3\n",
+ suspend ? "entering" : "exiting");
+ ret = -EIO;
+ }
+
+ /* Invalidate it toward next suspend or resume */
+ trans_pcie->sx_state = IWL_SX_INVALID;
+
+ return ret;
}
-int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test, bool reset)
+int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool reset)
{
int ret;
@@ -1573,36 +1523,31 @@ int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test, bool reset)
if (ret)
return ret;
- iwl_pcie_d3_complete_suspend(trans, test, reset);
+ iwl_pcie_d3_complete_suspend(trans, reset);
return 0;
}
int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
- enum iwl_d3_status *status,
- bool test, bool reset)
+ bool reset)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
u32 val;
int ret;
- if (test) {
- iwl_enable_interrupts(trans);
- *status = IWL_D3_STATUS_ALIVE;
- ret = 0;
- goto out;
- }
-
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
iwl_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ);
else
iwl_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- ret = iwl_finish_nic_init(trans);
- if (ret)
+ ret = iwl_trans_activate_nic(trans);
+ if (ret) {
+ IWL_ERR(trans, "Failed to init nic upon resume. err = %d\n",
+ ret);
return ret;
+ }
/*
* Reconfigure IVAR table in case of MSIX or reset ict table in
@@ -1636,34 +1581,30 @@ int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
iwl_read_umac_prph(trans, WFPM_GP2));
val = iwl_read32(trans, CSR_RESET);
- if (val & CSR_RESET_REG_FLAG_NEVO_RESET)
- *status = IWL_D3_STATUS_RESET;
- else
- *status = IWL_D3_STATUS_ALIVE;
-
-out:
- if (*status == IWL_D3_STATUS_ALIVE)
- ret = iwl_pcie_d3_handshake(trans, false);
- else
+ if (val & CSR_RESET_REG_FLAG_NEVO_RESET) {
+ IWL_INFO(trans, "Device was reset during suspend\n");
trans->state = IWL_TRANS_NO_FW;
+ return -ENOENT;
+ }
- return ret;
+ return iwl_pcie_d3_handshake(trans, false);
}
static void
iwl_pcie_set_interrupt_capa(struct pci_dev *pdev,
struct iwl_trans *trans,
- const struct iwl_cfg_trans_params *cfg_trans)
+ const struct iwl_mac_cfg *mac_cfg,
+ struct iwl_trans_info *info)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int max_irqs, num_irqs, i, ret;
u16 pci_cmd;
u32 max_rx_queues = IWL_MAX_RX_HW_QUEUES;
- if (!cfg_trans->mq_rx_supported)
+ if (!mac_cfg->mq_rx_supported)
goto enable_msi;
- if (cfg_trans->device_family <= IWL_DEVICE_FAMILY_9000)
+ if (mac_cfg->device_family <= IWL_DEVICE_FAMILY_9000)
max_rx_queues = IWL_9000_MAX_RX_HW_QUEUES;
max_irqs = min_t(u32, num_online_cpus() + 2, max_rx_queues);
@@ -1693,27 +1634,28 @@ iwl_pcie_set_interrupt_capa(struct pci_dev *pdev,
* More than two interrupts: we will use fewer RSS queues.
*/
if (num_irqs <= max_irqs - 2) {
- trans_pcie->trans->num_rx_queues = num_irqs + 1;
+ info->num_rxqs = num_irqs + 1;
trans_pcie->shared_vec_mask = IWL_SHARED_IRQ_NON_RX |
IWL_SHARED_IRQ_FIRST_RSS;
} else if (num_irqs == max_irqs - 1) {
- trans_pcie->trans->num_rx_queues = num_irqs;
+ info->num_rxqs = num_irqs;
trans_pcie->shared_vec_mask = IWL_SHARED_IRQ_NON_RX;
} else {
- trans_pcie->trans->num_rx_queues = num_irqs - 1;
+ info->num_rxqs = num_irqs - 1;
}
IWL_DEBUG_INFO(trans,
"MSI-X enabled with rx queues %d, vec mask 0x%x\n",
- trans_pcie->trans->num_rx_queues, trans_pcie->shared_vec_mask);
+ info->num_rxqs, trans_pcie->shared_vec_mask);
- WARN_ON(trans_pcie->trans->num_rx_queues > IWL_MAX_RX_HW_QUEUES);
+ WARN_ON(info->num_rxqs > IWL_MAX_RX_HW_QUEUES);
trans_pcie->alloc_vecs = num_irqs;
trans_pcie->msix_enabled = true;
return;
enable_msi:
+ info->num_rxqs = 1;
ret = pci_enable_msi(pdev);
if (ret) {
dev_err(&pdev->dev, "pci_enable_msi failed - %d\n", ret);
@@ -1726,14 +1668,15 @@ enable_msi:
}
}
-static void iwl_pcie_irq_set_affinity(struct iwl_trans *trans)
+static void iwl_pcie_irq_set_affinity(struct iwl_trans *trans,
+ struct iwl_trans_info *info)
{
#if defined(CONFIG_SMP)
int iter_rx_q, i, ret, cpu, offset;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
i = trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_FIRST_RSS ? 0 : 1;
- iter_rx_q = trans_pcie->trans->num_rx_queues - 1 + i;
+ iter_rx_q = info->num_rxqs - 1 + i;
offset = 1 + i;
for (; i < iter_rx_q ; i++) {
/*
@@ -1753,7 +1696,8 @@ static void iwl_pcie_irq_set_affinity(struct iwl_trans *trans)
}
static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
- struct iwl_trans_pcie *trans_pcie)
+ struct iwl_trans_pcie *trans_pcie,
+ struct iwl_trans_info *info)
{
int i;
@@ -1782,7 +1726,7 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
return ret;
}
}
- iwl_pcie_irq_set_affinity(trans_pcie->trans);
+ iwl_pcie_irq_set_affinity(trans_pcie->trans, info);
return 0;
}
@@ -1791,7 +1735,7 @@ static int iwl_trans_pcie_clear_persistence_bit(struct iwl_trans *trans)
{
u32 hpm, wprot;
- switch (trans->trans_cfg->device_family) {
+ switch (trans->mac_cfg->device_family) {
case IWL_DEVICE_FAMILY_9000:
wprot = PREG_PRPH_WPROT_9000;
break;
@@ -1822,7 +1766,7 @@ static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
{
int ret;
- ret = iwl_finish_nic_init(trans);
+ ret = iwl_trans_activate_nic(trans);
if (ret < 0)
return ret;
@@ -1839,7 +1783,7 @@ static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
return iwl_trans_pcie_sw_reset(trans, true);
}
-static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
+int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int err;
@@ -1860,8 +1804,8 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
if (err)
return err;
- if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
- trans->trans_cfg->integrated) {
+ if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
+ trans->mac_cfg->integrated) {
err = iwl_pcie_gen2_force_power_gating(trans);
if (err)
return err;
@@ -1936,7 +1880,7 @@ u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs)
static u32 iwl_trans_pcie_prph_msk(struct iwl_trans *trans)
{
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
return 0x00FFFFFF;
else
return 0x000FFFFF;
@@ -1960,45 +1904,17 @@ void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr, u32 val)
iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val);
}
-void iwl_trans_pcie_configure(struct iwl_trans *trans,
- const struct iwl_trans_config *trans_cfg)
+void iwl_pcie_gen1_2_op_mode_enter(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
/* free all first - we might be reconfigured for a different size */
iwl_pcie_free_rbs_pool(trans);
- trans_pcie->txqs.cmd.q_id = trans_cfg->cmd_queue;
- trans_pcie->txqs.cmd.fifo = trans_cfg->cmd_fifo;
- trans_pcie->txqs.page_offs = trans_cfg->cb_data_offs;
- trans_pcie->txqs.dev_cmd_offs = trans_cfg->cb_data_offs + sizeof(void *);
- trans_pcie->txqs.queue_alloc_cmd_ver = trans_cfg->queue_alloc_cmd_ver;
-
- if (WARN_ON(trans_cfg->n_no_reclaim_cmds > MAX_NO_RECLAIM_CMDS))
- trans_pcie->n_no_reclaim_cmds = 0;
- else
- trans_pcie->n_no_reclaim_cmds = trans_cfg->n_no_reclaim_cmds;
- if (trans_pcie->n_no_reclaim_cmds)
- memcpy(trans_pcie->no_reclaim_cmds, trans_cfg->no_reclaim_cmds,
- trans_pcie->n_no_reclaim_cmds * sizeof(u8));
-
- trans_pcie->rx_buf_size = trans_cfg->rx_buf_size;
trans_pcie->rx_page_order =
- iwl_trans_get_rb_size_order(trans_pcie->rx_buf_size);
+ iwl_trans_get_rb_size_order(trans->conf.rx_buf_size);
trans_pcie->rx_buf_bytes =
- iwl_trans_get_rb_size(trans_pcie->rx_buf_size);
- trans_pcie->supported_dma_mask = DMA_BIT_MASK(12);
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
- trans_pcie->supported_dma_mask = DMA_BIT_MASK(11);
-
- trans_pcie->txqs.bc_table_dword = trans_cfg->bc_table_dword;
- trans_pcie->scd_set_active = trans_cfg->scd_set_active;
-
- trans->command_groups = trans_cfg->command_groups;
- trans->command_groups_size = trans_cfg->command_groups_size;
-
-
- trans_pcie->fw_reset_handshake = trans_cfg->fw_reset_handshake;
+ iwl_trans_get_rb_size(trans->conf.rx_buf_size);
}
void iwl_trans_pcie_free_pnvm_dram_regions(struct iwl_dram_regions *dram_regions,
@@ -2026,11 +1942,14 @@ void iwl_trans_pcie_free_pnvm_dram_regions(struct iwl_dram_regions *dram_regions
static void iwl_pcie_free_invalid_tx_cmd(struct iwl_trans *trans)
{
- iwl_pcie_free_dma_ptr(trans, &trans->invalid_tx_cmd);
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ iwl_pcie_free_dma_ptr(trans, &trans_pcie->invalid_tx_cmd);
}
static int iwl_pcie_alloc_invalid_tx_cmd(struct iwl_trans *trans)
{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_cmd_header_wide bad_cmd = {
.cmd = INVALID_WR_PTR_CMD,
.group_id = DEBUG_GROUP,
@@ -2040,11 +1959,11 @@ static int iwl_pcie_alloc_invalid_tx_cmd(struct iwl_trans *trans)
};
int ret;
- ret = iwl_pcie_alloc_dma_ptr(trans, &trans->invalid_tx_cmd,
+ ret = iwl_pcie_alloc_dma_ptr(trans, &trans_pcie->invalid_tx_cmd,
sizeof(bad_cmd));
if (ret)
return ret;
- memcpy(trans->invalid_tx_cmd.addr, &bad_cmd, sizeof(bad_cmd));
+ memcpy(trans_pcie->invalid_tx_cmd.addr, &bad_cmd, sizeof(bad_cmd));
return 0;
}
@@ -2055,7 +1974,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
iwl_pcie_synchronize_irqs(trans);
- if (trans->trans_cfg->gen2)
+ if (trans->mac_cfg->gen2)
iwl_txq_gen2_tx_free(trans);
else
iwl_pcie_tx_free(trans);
@@ -2103,6 +2022,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
free_percpu(trans_pcie->txqs.tso_hdr_page);
}
+ kmem_cache_destroy(trans_pcie->dev_cmd_pool);
iwl_trans_free(trans);
}
@@ -2348,6 +2268,7 @@ out:
void iwl_trans_pcie_reset(struct iwl_trans *trans, enum iwl_reset_mode mode)
{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_trans_pcie_removal *removal;
char _msg = 0, *msg = &_msg;
@@ -2358,9 +2279,9 @@ void iwl_trans_pcie_reset(struct iwl_trans *trans, enum iwl_reset_mode mode)
if (test_bit(STATUS_TRANS_DEAD, &trans->status))
return;
- if (trans->me_present && mode == IWL_RESET_MODE_PROD_RESET) {
+ if (trans_pcie->me_present && mode == IWL_RESET_MODE_PROD_RESET) {
mode = IWL_RESET_MODE_FUNC_RESET;
- if (trans->me_present < 0)
+ if (trans_pcie->me_present < 0)
msg = " instead of product reset as ME may be present";
else
msg = " instead of product reset as ME is present";
@@ -2395,7 +2316,7 @@ void iwl_trans_pcie_reset(struct iwl_trans *trans, enum iwl_reset_mode mode)
removal->pdev = to_pci_dev(trans->dev);
removal->mode = mode;
- removal->integrated = trans->trans_cfg->integrated;
+ removal->integrated = trans->mac_cfg->integrated;
INIT_WORK(&removal->work, iwl_trans_pcie_removal_wk);
pci_dev_get(removal->pdev);
schedule_work(&removal->work);
@@ -2423,15 +2344,15 @@ bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent)
if (trans_pcie->cmd_hold_nic_awake)
goto out;
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
write = CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ;
mask = CSR_GP_CNTRL_REG_FLAG_MAC_STATUS;
poll = CSR_GP_CNTRL_REG_FLAG_MAC_STATUS;
}
/* this bit wakes up the NIC */
- __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, write);
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_8000)
+ iwl_trans_set_bit(trans, CSR_GP_CNTRL, write);
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_8000)
udelay(2);
/*
@@ -2454,8 +2375,8 @@ bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent)
* 5000 series and later (including 1000 series) have non-volatile SRAM,
* and do not save/restore SRAM when power cycling.
*/
- ret = iwl_poll_bit(trans, CSR_GP_CNTRL, poll, mask, 15000);
- if (unlikely(ret < 0)) {
+ ret = iwl_poll_bits_mask(trans, CSR_GP_CNTRL, poll, mask, 15000);
+ if (unlikely(ret)) {
u32 cntrl = iwl_read32(trans, CSR_GP_CNTRL);
if (silent) {
@@ -2467,7 +2388,7 @@ bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent)
"Timeout waiting for hardware access (CSR_GP_CNTRL 0x%08x)\n",
cntrl);
- iwl_trans_pcie_dump_regs(trans);
+ iwl_trans_pcie_dump_regs(trans, trans_pcie->pci_dev);
if (iwlwifi_mod_params.remove_when_gone && cntrl == ~0U)
iwl_trans_pcie_reset(trans,
@@ -2518,12 +2439,12 @@ iwl_trans_pcie_release_nic_access(struct iwl_trans *trans)
if (trans_pcie->cmd_hold_nic_awake)
goto out;
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
- __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ);
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ iwl_trans_clear_bit(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ);
else
- __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ iwl_trans_clear_bit(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
/*
* Above we read the CSR_GP_CNTRL register, which will flush
* any previous writes, but we need the write that clears the
@@ -2585,24 +2506,6 @@ int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr,
return 0;
}
-int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr,
- const void *buf, int dwords)
-{
- int offs, ret = 0;
- const u32 *vals = buf;
-
- if (iwl_trans_grab_nic_access(trans)) {
- iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr);
- for (offs = 0; offs < dwords; offs++)
- iwl_write32(trans, HBUS_TARG_MEM_WDAT,
- vals ? vals[offs] : 0);
- iwl_trans_release_nic_access(trans);
- } else {
- ret = -EBUSY;
- }
- return ret;
-}
-
int iwl_trans_pcie_read_config32(struct iwl_trans *trans, u32 ofs,
u32 *val)
{
@@ -2617,7 +2520,7 @@ int iwl_trans_pcie_rxq_dma_data(struct iwl_trans *trans, int queue,
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- if (queue >= trans->num_rx_queues || !trans_pcie->rxq)
+ if (queue >= trans->info.num_rxqs || !trans_pcie->rxq)
return -EINVAL;
data->fr_bd_cb = trans_pcie->rxq[queue].bd_dma;
@@ -2698,10 +2601,10 @@ int iwl_trans_pcie_wait_txqs_empty(struct iwl_trans *trans, u32 txq_bm)
/* waiting for all the tx frames complete might take a while */
for (cnt = 0;
- cnt < trans->trans_cfg->base_params->num_of_queues;
+ cnt < trans->mac_cfg->base->num_of_queues;
cnt++) {
- if (cnt == trans_pcie->txqs.cmd.q_id)
+ if (cnt == trans->conf.cmd_queue)
continue;
if (!test_bit(cnt, trans_pcie->txqs.queue_used))
continue;
@@ -2722,7 +2625,7 @@ void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg,
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
spin_lock_bh(&trans_pcie->reg_lock);
- __iwl_trans_pcie_set_bits_mask(trans, reg, mask, value);
+ _iwl_trans_set_bits_mask(trans, reg, mask, value);
spin_unlock_bh(&trans_pcie->reg_lock);
}
@@ -2842,7 +2745,7 @@ static void *iwl_dbgfs_tx_queue_seq_start(struct seq_file *seq, loff_t *pos)
struct iwl_dbgfs_tx_queue_priv *priv = seq->private;
struct iwl_dbgfs_tx_queue_state *state;
- if (*pos >= priv->trans->trans_cfg->base_params->num_of_queues)
+ if (*pos >= priv->trans->mac_cfg->base->num_of_queues)
return NULL;
state = kmalloc(sizeof(*state), GFP_KERNEL);
@@ -2860,7 +2763,7 @@ static void *iwl_dbgfs_tx_queue_seq_next(struct seq_file *seq,
*pos = ++state->pos;
- if (*pos >= priv->trans->trans_cfg->base_params->num_of_queues)
+ if (*pos >= priv->trans->mac_cfg->base->num_of_queues)
return NULL;
return state;
@@ -2892,7 +2795,7 @@ static int iwl_dbgfs_tx_queue_seq_show(struct seq_file *seq, void *v)
else
seq_puts(seq, "(unallocated)");
- if (state->pos == trans_pcie->txqs.cmd.q_id)
+ if (state->pos == trans->conf.cmd_queue)
seq_puts(seq, " (HCMD)");
seq_puts(seq, "\n");
@@ -2930,7 +2833,7 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
int pos = 0, i, ret;
size_t bufsz;
- bufsz = sizeof(char) * 121 * trans->num_rx_queues;
+ bufsz = sizeof(char) * 121 * trans->info.num_rxqs;
if (!trans_pcie->rxq)
return -EAGAIN;
@@ -2939,9 +2842,11 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
if (!buf)
return -ENOMEM;
- for (i = 0; i < trans->num_rx_queues && pos < bufsz; i++) {
+ for (i = 0; i < trans->info.num_rxqs && pos < bufsz; i++) {
struct iwl_rxq *rxq = &trans_pcie->rxq[i];
+ spin_lock_bh(&rxq->lock);
+
pos += scnprintf(buf + pos, bufsz - pos, "queue#: %2d\n",
i);
pos += scnprintf(buf + pos, bufsz - pos, "\tread: %u\n",
@@ -2962,6 +2867,7 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
pos += scnprintf(buf + pos, bufsz - pos,
"\tclosed_rb_num: Not Allocated\n");
}
+ spin_unlock_bh(&rxq->lock);
}
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
@@ -3266,8 +3172,9 @@ static ssize_t iwl_dbgfs_reset_write(struct file *file,
{
struct iwl_trans *trans = file->private_data;
static const char * const modes[] = {
- [IWL_RESET_MODE_SW_RESET] = "n/a",
- [IWL_RESET_MODE_REPROBE] = "n/a",
+ [IWL_RESET_MODE_SW_RESET] = "sw",
+ [IWL_RESET_MODE_REPROBE] = "reprobe",
+ [IWL_RESET_MODE_TOP_RESET] = "top",
[IWL_RESET_MODE_REMOVE_ONLY] = "remove",
[IWL_RESET_MODE_RESCAN] = "rescan",
[IWL_RESET_MODE_FUNC_RESET] = "function",
@@ -3286,8 +3193,18 @@ static ssize_t iwl_dbgfs_reset_write(struct file *file,
if (mode < 0)
return mode;
- if (mode < IWL_RESET_MODE_REMOVE_ONLY)
- return -EINVAL;
+ if (mode < IWL_RESET_MODE_REMOVE_ONLY) {
+ if (!test_bit(STATUS_DEVICE_ENABLED, &trans->status))
+ return -EINVAL;
+ if (mode == IWL_RESET_MODE_TOP_RESET) {
+ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_SC)
+ return -EINVAL;
+ trans->request_top_reset = 1;
+ }
+ iwl_op_mode_nic_error(trans->op_mode, IWL_ERR_TYPE_DEBUGFS);
+ iwl_trans_schedule_reset(trans, IWL_ERR_TYPE_DEBUGFS);
+ return count;
+ }
iwl_trans_pcie_reset(trans, mode);
@@ -3428,7 +3345,7 @@ static u32 iwl_trans_pcie_fh_regs_dump(struct iwl_trans *trans,
(*data)->len = cpu_to_le32(fh_regs_len);
val = (void *)(*data)->data;
- if (!trans->trans_cfg->gen2)
+ if (!trans->mac_cfg->gen2)
for (i = FH_MEM_LOWER_BOUND; i < FH_MEM_UPPER_BOUND;
i += sizeof(u32))
*val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i));
@@ -3475,7 +3392,7 @@ iwl_trans_pcie_dump_pointers(struct iwl_trans *trans,
{
u32 base, base_high, write_ptr, write_ptr_val, wrap_cnt;
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
base = DBGC_CUR_DBGBUF_BASE_ADDR_LSB;
base_high = DBGC_CUR_DBGBUF_BASE_ADDR_MSB;
write_ptr = DBGC_CUR_DBGBUF_STATUS;
@@ -3495,7 +3412,7 @@ iwl_trans_pcie_dump_pointers(struct iwl_trans *trans,
cpu_to_le32(iwl_read_prph(trans, wrap_cnt));
fw_mon_data->fw_mon_base_ptr =
cpu_to_le32(iwl_read_prph(trans, base));
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
fw_mon_data->fw_mon_base_high_ptr =
cpu_to_le32(iwl_read_prph(trans, base_high));
write_ptr_val &= DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK;
@@ -3515,8 +3432,8 @@ iwl_trans_pcie_dump_monitor(struct iwl_trans *trans,
if (trans->dbg.dest_tlv ||
(fw_mon->size &&
- (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_7000 ||
- trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210))) {
+ (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_7000 ||
+ trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210))) {
struct iwl_fw_error_dump_fw_mon *fw_mon_data;
(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR);
@@ -3539,14 +3456,14 @@ iwl_trans_pcie_dump_monitor(struct iwl_trans *trans,
IWL_LDBG_M2S_BUF_BA_MSK) <<
trans->dbg.dest_tlv->base_shift;
base *= IWL_M2S_UNIT_SIZE;
- base += trans->cfg->smem_offset;
+ base += trans->mac_cfg->base->smem_offset;
} else {
base = iwl_read_prph(trans, base) <<
trans->dbg.dest_tlv->base_shift;
}
- iwl_trans_read_mem(trans, base, fw_mon_data->data,
- monitor_len / sizeof(u32));
+ iwl_trans_pcie_read_mem(trans, base, fw_mon_data->data,
+ monitor_len / sizeof(u32));
} else if (trans->dbg.dest_tlv->monitor_mode == MARBH_MODE) {
monitor_len =
iwl_trans_pci_dump_marbh_monitor(trans,
@@ -3580,7 +3497,7 @@ static int iwl_trans_get_fw_monitor_len(struct iwl_trans *trans, u32 *len)
base = (cfg_reg & IWL_LDBG_M2S_BUF_BA_MSK) <<
trans->dbg.dest_tlv->base_shift;
base *= IWL_M2S_UNIT_SIZE;
- base += trans->cfg->smem_offset;
+ base += trans->mac_cfg->base->smem_offset;
monitor_len =
(cfg_reg & IWL_LDBG_M2S_BUF_SIZE_MSK) >>
@@ -3596,7 +3513,7 @@ static int iwl_trans_get_fw_monitor_len(struct iwl_trans *trans, u32 *len)
trans->dbg.dest_tlv->end_shift;
/* Make "end" point to the actual end */
- if (trans->trans_cfg->device_family >=
+ if (trans->mac_cfg->device_family >=
IWL_DEVICE_FAMILY_8000 ||
trans->dbg.dest_tlv->monitor_mode == MARBH_MODE)
end += (1 << trans->dbg.dest_tlv->end_shift);
@@ -3617,13 +3534,13 @@ iwl_trans_pcie_dump_data(struct iwl_trans *trans, u32 dump_mask,
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_fw_error_dump_data *data;
- struct iwl_txq *cmdq = trans_pcie->txqs.txq[trans_pcie->txqs.cmd.q_id];
+ struct iwl_txq *cmdq = trans_pcie->txqs.txq[trans->conf.cmd_queue];
struct iwl_fw_error_dump_txcmd *txcmd;
struct iwl_trans_dump_data *dump_data;
u32 len, num_rbs = 0, monitor_len = 0;
int i, ptr;
- bool dump_rbs = test_bit(STATUS_FW_ERROR, &trans->status) &&
- !trans->trans_cfg->mq_rx_supported &&
+ bool dump_rbs = iwl_trans_is_fw_error(trans) &&
+ !trans->mac_cfg->mq_rx_supported &&
dump_mask & BIT(IWL_FW_ERROR_DUMP_RB);
if (!dump_mask)
@@ -3648,7 +3565,7 @@ iwl_trans_pcie_dump_data(struct iwl_trans *trans, u32 dump_mask,
/* FH registers */
if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) {
- if (trans->trans_cfg->gen2)
+ if (trans->mac_cfg->gen2)
len += sizeof(*data) +
(iwl_umac_prph(trans, FH_MEM_UPPER_BOUND_GEN2) -
iwl_umac_prph(trans, FH_MEM_LOWER_BOUND_GEN2));
@@ -3662,15 +3579,18 @@ iwl_trans_pcie_dump_data(struct iwl_trans *trans, u32 dump_mask,
/* Dump RBs is supported only for pre-9000 devices (1 queue) */
struct iwl_rxq *rxq = &trans_pcie->rxq[0];
/* RBs */
+ spin_lock_bh(&rxq->lock);
num_rbs = iwl_get_closed_rb_stts(trans, rxq);
num_rbs = (num_rbs - rxq->read) & RX_QUEUE_MASK;
+ spin_unlock_bh(&rxq->lock);
+
len += num_rbs * (sizeof(*data) +
sizeof(struct iwl_fw_error_dump_rb) +
(PAGE_SIZE << trans_pcie->rx_page_order));
}
/* Paged memory for gen2 HW */
- if (trans->trans_cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING))
+ if (trans->mac_cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING))
for (i = 0; i < trans->init_dram.paging_cnt; i++)
len += sizeof(*data) +
sizeof(struct iwl_fw_error_dump_paging) +
@@ -3695,7 +3615,7 @@ iwl_trans_pcie_dump_data(struct iwl_trans *trans, u32 dump_mask,
u8 tfdidx;
u32 caplen, cmdlen;
- if (trans->trans_cfg->gen2)
+ if (trans->mac_cfg->gen2)
tfdidx = idx;
else
tfdidx = ptr;
@@ -3735,7 +3655,7 @@ iwl_trans_pcie_dump_data(struct iwl_trans *trans, u32 dump_mask,
len += iwl_trans_pcie_dump_rbs(trans, &data, num_rbs);
/* Paged memory for gen2 HW */
- if (trans->trans_cfg->gen2 &&
+ if (trans->mac_cfg->gen2 &&
dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) {
for (i = 0; i < trans->init_dram.paging_cnt; i++) {
struct iwl_fw_error_dump_paging *paging;
@@ -3775,7 +3695,7 @@ void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)
if (trans_pcie->msix_enabled) {
inta_addr = CSR_MSIX_HW_INT_CAUSES_AD;
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
sw_err_bit = MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ;
else
sw_err_bit = MSIX_HW_INT_CAUSES_REG_SW_ERR;
@@ -3787,35 +3707,70 @@ void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)
iwl_trans_sync_nmi_with_addr(trans, inta_addr, sw_err_bit);
}
-struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
- const struct pci_device_id *ent,
- const struct iwl_cfg_trans_params *cfg_trans)
+static int iwl_trans_pcie_alloc_txcmd_pool(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ unsigned int txcmd_size, txcmd_align;
+
+ if (!trans->mac_cfg->gen2) {
+ txcmd_size = sizeof(struct iwl_tx_cmd_v6);
+ txcmd_align = sizeof(void *);
+ } else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
+ txcmd_size = sizeof(struct iwl_tx_cmd_v9);
+ txcmd_align = 64;
+ } else {
+ txcmd_size = sizeof(struct iwl_tx_cmd);
+ txcmd_align = 128;
+ }
+
+ txcmd_size += sizeof(struct iwl_cmd_header);
+ txcmd_size += 36; /* biggest possible 802.11 header */
+
+ /* Ensure device TX cmd cannot reach/cross a page boundary in gen2 */
+ if (WARN_ON((trans->mac_cfg->gen2 && txcmd_size >= txcmd_align)))
+ return -EINVAL;
+
+ snprintf(trans_pcie->dev_cmd_pool_name,
+ sizeof(trans_pcie->dev_cmd_pool_name),
+ "iwl_cmd_pool:%s", dev_name(trans->dev));
+
+ trans_pcie->dev_cmd_pool =
+ kmem_cache_create(trans_pcie->dev_cmd_pool_name,
+ txcmd_size, txcmd_align,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (!trans_pcie->dev_cmd_pool)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static struct iwl_trans *
+iwl_trans_pcie_alloc(struct pci_dev *pdev,
+ const struct iwl_mac_cfg *mac_cfg,
+ struct iwl_trans_info *info, u8 __iomem *hw_base)
{
struct iwl_trans_pcie *trans_pcie, **priv;
struct iwl_trans *trans;
+ unsigned int bc_tbl_n_entries;
int ret, addr_size;
- u32 bar0;
-
- /* reassign our BAR 0 if invalid due to possible runtime PM races */
- pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &bar0);
- if (bar0 == PCI_BASE_ADDRESS_MEM_TYPE_64) {
- ret = pci_assign_resource(pdev, 0);
- if (ret)
- return ERR_PTR(ret);
- }
-
- ret = pcim_enable_device(pdev);
- if (ret)
- return ERR_PTR(ret);
trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), &pdev->dev,
- cfg_trans);
+ mac_cfg);
if (!trans)
return ERR_PTR(-ENOMEM);
trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- if (trans->trans_cfg->gen2) {
+ trans_pcie->hw_base = hw_base;
+
+ /* Initialize the wait queue for commands */
+ init_waitqueue_head(&trans_pcie->wait_command_queue);
+
+ ret = iwl_trans_pcie_alloc_txcmd_pool(trans);
+ if (ret)
+ goto out_free_trans;
+
+ if (trans->mac_cfg->gen2) {
trans_pcie->txqs.tfd.addr_size = 64;
trans_pcie->txqs.tfd.max_tbs = IWL_TFH_NUM_TBS;
trans_pcie->txqs.tfd.size = sizeof(struct iwl_tfh_tfd);
@@ -3824,31 +3779,34 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
trans_pcie->txqs.tfd.max_tbs = IWL_NUM_OF_TBS;
trans_pcie->txqs.tfd.size = sizeof(struct iwl_tfd);
}
- trans->max_skb_frags = IWL_TRANS_PCIE_MAX_FRAGS(trans_pcie);
- /* Set a short watchdog for the command queue */
- trans_pcie->txqs.cmd.wdg_timeout = IWL_DEF_WD_TIMEOUT;
+ trans_pcie->supported_dma_mask = (u32)DMA_BIT_MASK(12);
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ trans_pcie->supported_dma_mask = (u32)DMA_BIT_MASK(11);
+
+ info->max_skb_frags = IWL_TRANS_PCIE_MAX_FRAGS(trans_pcie);
trans_pcie->txqs.tso_hdr_page = alloc_percpu(struct iwl_tso_hdr_page);
if (!trans_pcie->txqs.tso_hdr_page) {
ret = -ENOMEM;
- goto out_free_trans;
+ goto out_free_txcmd_pool;
}
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
- trans_pcie->txqs.bc_tbl_size =
- sizeof(struct iwl_gen3_bc_tbl_entry) * TFD_QUEUE_BC_SIZE_GEN3_BZ;
- else if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
- trans_pcie->txqs.bc_tbl_size =
- sizeof(struct iwl_gen3_bc_tbl_entry) * TFD_QUEUE_BC_SIZE_GEN3_AX210;
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ bc_tbl_n_entries = TFD_QUEUE_BC_SIZE_BZ;
+ else if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ bc_tbl_n_entries = TFD_QUEUE_BC_SIZE_AX210;
else
- trans_pcie->txqs.bc_tbl_size = sizeof(struct iwlagn_scd_bc_tbl);
+ bc_tbl_n_entries = TFD_QUEUE_BC_SIZE;
+
+ trans_pcie->txqs.bc_tbl_size =
+ sizeof(struct iwl_bc_tbl_entry) * bc_tbl_n_entries;
/*
* For gen2 devices, we use a single allocation for each byte-count
* table, but they're pretty small (1k) so use a DMA pool that we
* allocate here.
*/
- if (trans->trans_cfg->gen2) {
+ if (trans->mac_cfg->gen2) {
trans_pcie->txqs.bc_pool =
dmam_pool_create("iwlwifi:bc", trans->dev,
trans_pcie->txqs.bc_tbl_size,
@@ -3861,7 +3819,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
/* Some things must not change even if the config does */
WARN_ON(trans_pcie->txqs.tfd.addr_size !=
- (trans->trans_cfg->gen2 ? 64 : 36));
+ (trans->mac_cfg->gen2 ? 64 : 36));
/* Initialize NAPI here - it should be before registering to mac80211
* in the opmode but after the HW struct is allocated.
@@ -3895,7 +3853,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
trans_pcie->debug_rfkill = -1;
- if (!cfg_trans->base_params->pcie_l1_allowed) {
+ if (!mac_cfg->base->pcie_l1_allowed) {
/*
* W/A - seems to solve weird behavior. We need to remove this
* if we don't want to stay in L1 all the time. This wastes a
@@ -3906,8 +3864,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
PCIE_LINK_STATE_CLKPM);
}
- pci_set_master(pdev);
-
addr_size = trans_pcie->txqs.tfd.addr_size;
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(addr_size));
if (ret) {
@@ -3919,19 +3875,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
}
}
- ret = pcim_request_all_regions(pdev, DRV_NAME);
- if (ret) {
- dev_err(&pdev->dev, "Requesting all PCI BARs failed.\n");
- goto out_no_pci;
- }
-
- trans_pcie->hw_base = pcim_iomap(pdev, 0, 0);
- if (!trans_pcie->hw_base) {
- dev_err(&pdev->dev, "Could not ioremap PCI BAR 0.\n");
- ret = -ENODEV;
- goto out_no_pci;
- }
-
/* We disable the RETRY_TIMEOUT register (0x41) to keep
* PCI Tx retries from interfering with C3 CPU state */
pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
@@ -3939,30 +3882,20 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
trans_pcie->pci_dev = pdev;
iwl_disable_interrupts(trans);
- trans->hw_rev = iwl_read32(trans, CSR_HW_REV);
- if (trans->hw_rev == 0xffffffff) {
- dev_err(&pdev->dev, "HW_REV=0xFFFFFFFF, PCI issues?\n");
- ret = -EIO;
- goto out_no_pci;
- }
-
/*
* In the 8000 HW family the format of the 4 bytes of CSR_HW_REV have
* changed, and now the revision step also includes bit 0-1 (no more
* "dash" value). To keep hw_rev backwards compatible - we'll store it
* in the old format.
*/
- if (cfg_trans->device_family >= IWL_DEVICE_FAMILY_8000)
- trans->hw_rev_step = trans->hw_rev & 0xF;
+ if (mac_cfg->device_family >= IWL_DEVICE_FAMILY_8000)
+ info->hw_rev_step = info->hw_rev & 0xF;
else
- trans->hw_rev_step = (trans->hw_rev & 0xC) >> 2;
+ info->hw_rev_step = (info->hw_rev & 0xC) >> 2;
- IWL_DEBUG_INFO(trans, "HW REV: 0x%0x\n", trans->hw_rev);
+ IWL_DEBUG_INFO(trans, "HW REV: 0x%0x\n", info->hw_rev);
- iwl_pcie_set_interrupt_capa(pdev, trans, cfg_trans);
- trans->hw_id = (pdev->device << 16) + pdev->subsystem_device;
- snprintf(trans->hw_id_str, sizeof(trans->hw_id_str),
- "PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device);
+ iwl_pcie_set_interrupt_capa(pdev, trans, mac_cfg, info);
init_waitqueue_head(&trans_pcie->sx_waitq);
@@ -3971,7 +3904,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
goto out_no_pci;
if (trans_pcie->msix_enabled) {
- ret = iwl_pcie_init_msix_handler(pdev, trans_pcie);
+ ret = iwl_pcie_init_msix_handler(pdev, trans_pcie, info);
if (ret)
goto out_no_pci;
} else {
@@ -4006,6 +3939,8 @@ out_free_ndev:
free_netdev(trans_pcie->napi_dev);
out_free_tso:
free_percpu(trans_pcie->txqs.tso_hdr_page);
+out_free_txcmd_pool:
+ kmem_cache_destroy(trans_pcie->dev_cmd_pool);
out_free_trans:
iwl_trans_free(trans);
return ERR_PTR(ret);
@@ -4042,9 +3977,391 @@ int iwl_trans_pcie_copy_imr(struct iwl_trans *trans,
IMR_D2S_REQUESTED, 5 * HZ);
if (!ret || trans_pcie->imr_status == IMR_D2S_ERROR) {
IWL_ERR(trans, "Failed to copy IMR Memory chunk!\n");
- iwl_trans_pcie_dump_regs(trans);
+ iwl_trans_pcie_dump_regs(trans, trans_pcie->pci_dev);
return -ETIMEDOUT;
}
trans_pcie->imr_status = IMR_D2S_IDLE;
return 0;
}
+
+/*
+ * Read rf id and cdb info from prph register and store it
+ */
+static void get_crf_id(struct iwl_trans *iwl_trans,
+ struct iwl_trans_info *info)
+{
+ u32 sd_reg_ver_addr;
+ u32 hw_wfpm_id;
+ u32 val = 0;
+ u8 step;
+
+ if (iwl_trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ sd_reg_ver_addr = SD_REG_VER_GEN2;
+ else
+ sd_reg_ver_addr = SD_REG_VER;
+
+ /* Enable access to peripheral registers */
+ val = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG);
+ val |= WFPM_AUX_CTL_AUX_IF_MAC_OWNER_MSK;
+ iwl_write_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG, val);
+
+ /* Read crf info */
+ info->hw_crf_id = iwl_read_prph_no_grab(iwl_trans, sd_reg_ver_addr);
+
+ /* Read cnv info */
+ info->hw_cnv_id = iwl_read_prph_no_grab(iwl_trans, CNVI_AUX_MISC_CHIP);
+
+ /* For BZ-W, take B step also when A step is indicated */
+ if (CSR_HW_REV_TYPE(info->hw_rev) == IWL_CFG_MAC_TYPE_BZ_W)
+ step = SILICON_B_STEP;
+
+ /* In BZ, the MAC step must be read from the CNVI aux register */
+ if (CSR_HW_REV_TYPE(info->hw_rev) == IWL_CFG_MAC_TYPE_BZ) {
+ step = CNVI_AUX_MISC_CHIP_MAC_STEP(info->hw_cnv_id);
+
+ /* For BZ-U, take B step also when A step is indicated */
+ if ((CNVI_AUX_MISC_CHIP_PROD_TYPE(info->hw_cnv_id) ==
+ CNVI_AUX_MISC_CHIP_PROD_TYPE_BZ_U) &&
+ step == SILICON_A_STEP)
+ step = SILICON_B_STEP;
+ }
+
+ if (CSR_HW_REV_TYPE(info->hw_rev) == IWL_CFG_MAC_TYPE_BZ ||
+ CSR_HW_REV_TYPE(info->hw_rev) == IWL_CFG_MAC_TYPE_BZ_W) {
+ info->hw_rev_step = step;
+ info->hw_rev |= step;
+ }
+
+ /* Read cdb info (also contains the jacket info if needed in the future */
+ hw_wfpm_id = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_OTP_CFG1_ADDR);
+
+ IWL_INFO(iwl_trans, "Detected crf-id 0x%x, cnv-id 0x%x wfpm id 0x%x\n",
+ info->hw_crf_id, info->hw_cnv_id, hw_wfpm_id);
+}
+
+/*
+ * In case that there is no OTP on the NIC, map the rf id and cdb info
+ * from the prph registers.
+ */
+static int map_crf_id(struct iwl_trans *iwl_trans,
+ struct iwl_trans_info *info)
+{
+ int ret = 0;
+ u32 val = info->hw_crf_id;
+ u32 step_id = REG_CRF_ID_STEP(val);
+ u32 slave_id = REG_CRF_ID_SLAVE(val);
+ u32 hw_wfpm_id = iwl_read_umac_prph_no_grab(iwl_trans,
+ WFPM_OTP_CFG1_ADDR);
+ u32 cdb_id_wfpm = WFPM_OTP_CFG1_IS_CDB(hw_wfpm_id);
+
+ /* Map between crf id to rf id */
+ switch (REG_CRF_ID_TYPE(val)) {
+ case REG_CRF_ID_TYPE_JF_1:
+ info->hw_rf_id = (IWL_CFG_RF_TYPE_JF1 << 12);
+ break;
+ case REG_CRF_ID_TYPE_JF_2:
+ info->hw_rf_id = (IWL_CFG_RF_TYPE_JF2 << 12);
+ break;
+ case REG_CRF_ID_TYPE_HR_NONE_CDB_1X1:
+ info->hw_rf_id = (IWL_CFG_RF_TYPE_HR1 << 12);
+ break;
+ case REG_CRF_ID_TYPE_HR_NONE_CDB:
+ info->hw_rf_id = (IWL_CFG_RF_TYPE_HR2 << 12);
+ break;
+ case REG_CRF_ID_TYPE_HR_CDB:
+ info->hw_rf_id = (IWL_CFG_RF_TYPE_HR2 << 12);
+ break;
+ case REG_CRF_ID_TYPE_GF:
+ info->hw_rf_id = (IWL_CFG_RF_TYPE_GF << 12);
+ break;
+ case REG_CRF_ID_TYPE_FM:
+ info->hw_rf_id = (IWL_CFG_RF_TYPE_FM << 12);
+ break;
+ case REG_CRF_ID_TYPE_WHP:
+ info->hw_rf_id = (IWL_CFG_RF_TYPE_WH << 12);
+ break;
+ case REG_CRF_ID_TYPE_PE:
+ info->hw_rf_id = (IWL_CFG_RF_TYPE_PE << 12);
+ break;
+ default:
+ ret = -EIO;
+ IWL_ERR(iwl_trans,
+ "Can't find a correct rfid for crf id 0x%x\n",
+ REG_CRF_ID_TYPE(val));
+ goto out;
+ }
+
+ /* Set Step-id */
+ info->hw_rf_id |= (step_id << 8);
+
+ /* Set CDB capabilities */
+ if (cdb_id_wfpm || slave_id) {
+ info->hw_rf_id += BIT(28);
+ IWL_INFO(iwl_trans, "Adding cdb to rf id\n");
+ }
+
+ IWL_INFO(iwl_trans,
+ "Detected rf-type 0x%x step-id 0x%x slave-id 0x%x from crf id 0x%x\n",
+ REG_CRF_ID_TYPE(val), step_id, slave_id, info->hw_rf_id);
+ IWL_INFO(iwl_trans,
+ "Detected cdb-id 0x%x from wfpm id 0x%x\n",
+ cdb_id_wfpm, hw_wfpm_id);
+out:
+ return ret;
+}
+
+static void iwl_pcie_recheck_me_status(struct work_struct *wk)
+{
+ struct iwl_trans_pcie *trans_pcie = container_of(wk,
+ typeof(*trans_pcie),
+ me_recheck_wk.work);
+ u32 val;
+
+ val = iwl_read32(trans_pcie->trans, CSR_HW_IF_CONFIG_REG);
+ trans_pcie->me_present = !!(val & CSR_HW_IF_CONFIG_REG_IAMT_UP);
+}
+
+static void iwl_pcie_check_me_status(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ u32 val;
+
+ trans_pcie->me_present = -1;
+
+ INIT_DELAYED_WORK(&trans_pcie->me_recheck_wk,
+ iwl_pcie_recheck_me_status);
+
+ /* we don't have a good way of determining this until BZ */
+ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
+ return;
+
+ val = iwl_read_prph(trans, CNVI_SCU_REG_FOR_ECO_1);
+ if (val & CNVI_SCU_REG_FOR_ECO_1_WIAMT_KNOWN) {
+ trans_pcie->me_present =
+ !!(val & CNVI_SCU_REG_FOR_ECO_1_WIAMT_PRESENT);
+ return;
+ }
+
+ val = iwl_read32(trans, CSR_HW_IF_CONFIG_REG);
+ if (val & (CSR_HW_IF_CONFIG_REG_ME_OWN |
+ CSR_HW_IF_CONFIG_REG_IAMT_UP)) {
+ trans_pcie->me_present = 1;
+ return;
+ }
+
+ /* recheck again later, ME might still be initializing */
+ schedule_delayed_work(&trans_pcie->me_recheck_wk, HZ);
+}
+
+int iwl_pci_gen1_2_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent,
+ const struct iwl_mac_cfg *mac_cfg,
+ u8 __iomem *hw_base, u32 hw_rev)
+{
+ const struct iwl_dev_info *dev_info;
+ struct iwl_trans_info info = {
+ .hw_id = (pdev->device << 16) + pdev->subsystem_device,
+ .hw_rev = hw_rev,
+ };
+ struct iwl_trans *iwl_trans;
+ struct iwl_trans_pcie *trans_pcie;
+ int ret;
+
+ iwl_trans = iwl_trans_pcie_alloc(pdev, mac_cfg, &info, hw_base);
+ if (IS_ERR(iwl_trans))
+ return PTR_ERR(iwl_trans);
+
+ trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans);
+
+ iwl_trans_pcie_check_product_reset_status(pdev);
+ iwl_trans_pcie_check_product_reset_mode(pdev);
+
+ /* set the things we know so far for the grab NIC access */
+ iwl_trans_set_info(iwl_trans, &info);
+
+ /*
+ * Let's try to grab NIC access early here. Sometimes, NICs may
+ * fail to initialize, and if that happens it's better if we see
+ * issues early on (and can reprobe, per the logic inside), than
+ * first trying to load the firmware etc. and potentially only
+ * detecting any problems when the first interface is brought up.
+ */
+ ret = iwl_pcie_prepare_card_hw(iwl_trans);
+ if (!ret) {
+ ret = iwl_trans_activate_nic(iwl_trans);
+ if (ret)
+ goto out_free_trans;
+ if (iwl_trans_grab_nic_access(iwl_trans)) {
+ get_crf_id(iwl_trans, &info);
+ /* all good */
+ iwl_trans_release_nic_access(iwl_trans);
+ } else {
+ ret = -EIO;
+ goto out_free_trans;
+ }
+ }
+
+ info.hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID);
+
+ /*
+ * The RF_ID is set to zero in blank OTP so read version to
+ * extract the RF_ID.
+ * This is relevant only for family 9000 and up.
+ */
+ if (iwl_trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_9000 &&
+ !CSR_HW_RFID_TYPE(info.hw_rf_id) && map_crf_id(iwl_trans, &info)) {
+ ret = -EINVAL;
+ goto out_free_trans;
+ }
+
+ IWL_INFO(iwl_trans, "PCI dev %04x/%04x, rev=0x%x, rfid=0x%x\n",
+ pdev->device, pdev->subsystem_device,
+ info.hw_rev, info.hw_rf_id);
+
+#if !IS_ENABLED(CONFIG_IWLMLD)
+ if (iwl_drv_is_wifi7_supported(iwl_trans)) {
+ IWL_ERR(iwl_trans,
+ "IWLMLD needs to be compiled to support this device\n");
+ ret = -EOPNOTSUPP;
+ goto out_free_trans;
+ }
+#endif
+
+ dev_info = iwl_pci_find_dev_info(pdev->device, pdev->subsystem_device,
+ CSR_HW_RFID_TYPE(info.hw_rf_id),
+ CSR_HW_RFID_IS_CDB(info.hw_rf_id),
+ IWL_SUBDEVICE_RF_ID(pdev->subsystem_device),
+ IWL_SUBDEVICE_BW_LIM(pdev->subsystem_device),
+ !iwl_trans->mac_cfg->integrated);
+ if (dev_info) {
+ iwl_trans->cfg = dev_info->cfg;
+ info.name = dev_info->name;
+ }
+
+#if IS_ENABLED(CONFIG_IWLMVM)
+
+ /*
+ * special-case 7265D, it has the same PCI IDs.
+ *
+ * Note that because we already pass the cfg to the transport above,
+ * all the parameters that the transport uses must, until that is
+ * changed, be identical to the ones in the 7265D configuration.
+ */
+ if (iwl_trans->cfg == &iwl7265_cfg &&
+ (info.hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D)
+ iwl_trans->cfg = &iwl7265d_cfg;
+#endif
+ if (!iwl_trans->cfg) {
+ pr_err("No config found for PCI dev %04x/%04x, rev=0x%x, rfid=0x%x\n",
+ pdev->device, pdev->subsystem_device,
+ info.hw_rev, info.hw_rf_id);
+ ret = -EINVAL;
+ goto out_free_trans;
+ }
+
+ IWL_INFO(iwl_trans, "Detected %s\n", info.name);
+
+ if (iwl_trans->mac_cfg->mq_rx_supported) {
+ if (WARN_ON(!iwl_trans->cfg->num_rbds)) {
+ ret = -EINVAL;
+ goto out_free_trans;
+ }
+ trans_pcie->num_rx_bufs = iwl_trans_get_num_rbds(iwl_trans);
+ } else {
+ trans_pcie->num_rx_bufs = RX_QUEUE_SIZE;
+ }
+
+ if (!iwl_trans->mac_cfg->integrated) {
+ u16 link_status;
+
+ pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &link_status);
+
+ info.pcie_link_speed =
+ u16_get_bits(link_status, PCI_EXP_LNKSTA_CLS);
+ }
+
+ iwl_trans_set_info(iwl_trans, &info);
+
+ pci_set_drvdata(pdev, iwl_trans);
+
+ iwl_pcie_check_me_status(iwl_trans);
+
+ /* try to get ownership so that we'll know if we don't own it */
+ iwl_pcie_prepare_card_hw(iwl_trans);
+
+ iwl_trans->drv = iwl_drv_start(iwl_trans);
+
+ if (IS_ERR(iwl_trans->drv)) {
+ ret = PTR_ERR(iwl_trans->drv);
+ goto out_free_trans;
+ }
+
+ /* register transport layer debugfs here */
+ iwl_trans_pcie_dbgfs_register(iwl_trans);
+
+ return 0;
+
+out_free_trans:
+ iwl_trans_pcie_free(iwl_trans);
+ return ret;
+}
+
+void iwl_pcie_gen1_2_remove(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ cancel_delayed_work_sync(&trans_pcie->me_recheck_wk);
+
+ iwl_drv_stop(trans->drv);
+
+ iwl_trans_pcie_free(trans);
+}
+
+int iwl_pcie_gen1_2_activate_nic(struct iwl_trans *trans)
+{
+ const struct iwl_mac_cfg *mac_cfg = trans->mac_cfg;
+ u32 poll_ready;
+ int err;
+
+ if (mac_cfg->bisr_workaround) {
+ /* ensure the TOP FSM isn't still in previous reset */
+ mdelay(2);
+ }
+
+ /*
+ * Set "initialization complete" bit to move adapter from
+ * D0U* --> D0A* (powered-up active) state.
+ */
+ if (mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
+ iwl_set_bit(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ |
+ CSR_GP_CNTRL_REG_FLAG_MAC_INIT);
+ poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_STATUS;
+ } else {
+ iwl_set_bit(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+ poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY;
+ }
+
+ if (mac_cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ udelay(2);
+
+ /*
+ * Wait for clock stabilization; once stabilized, access to
+ * device-internal resources is supported, e.g. iwl_write_prph()
+ * and accesses to uCode SRAM.
+ */
+ err = iwl_poll_bits(trans, CSR_GP_CNTRL, poll_ready, 25000);
+ if (err < 0) {
+ IWL_DEBUG_INFO(trans, "Failed to wake NIC\n");
+
+ iwl_pcie_dump_host_monitor(trans);
+ }
+
+ if (mac_cfg->bisr_workaround) {
+ /* ensure BISR shift has finished */
+ udelay(200);
+ }
+
+ return err;
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx-gen2.c
index 71227fd3dac0..df0545f09da9 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx-gen2.c
@@ -18,13 +18,12 @@
static struct page *get_workaround_page(struct iwl_trans *trans,
struct sk_buff *skb)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_tso_page_info *info;
struct page **page_ptr;
struct page *ret;
dma_addr_t phys;
- page_ptr = (void *)((u8 *)skb->cb + trans_pcie->txqs.page_offs);
+ page_ptr = (void *)((u8 *)skb->cb + trans->conf.cb_data_offs);
ret = alloc_page(GFP_ATOMIC);
if (!ret)
@@ -164,7 +163,7 @@ static int iwl_txq_gen2_build_amsdu(struct iwl_trans *trans,
struct iwl_device_tx_cmd *dev_cmd)
{
#ifdef CONFIG_INET
- struct iwl_tx_cmd_gen2 *tx_cmd = (void *)dev_cmd->payload;
+ struct iwl_tx_cmd_v9 *tx_cmd = (void *)dev_cmd->payload;
struct ieee80211_hdr *hdr = (void *)skb->data;
unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room;
unsigned int mss = skb_shinfo(skb)->gso_size;
@@ -491,21 +490,21 @@ struct iwl_tfh_tfd *iwl_txq_gen2_build_tfd(struct iwl_trans *trans,
bool amsdu;
/* There must be data left over for TB1 or this code must be changed */
- BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen2) < IWL_FIRST_TB_SIZE);
+ BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_v9) < IWL_FIRST_TB_SIZE);
BUILD_BUG_ON(sizeof(struct iwl_cmd_header) +
- offsetofend(struct iwl_tx_cmd_gen2, dram_info) >
+ offsetofend(struct iwl_tx_cmd_v9, dram_info) >
IWL_FIRST_TB_SIZE);
- BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen3) < IWL_FIRST_TB_SIZE);
+ BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_FIRST_TB_SIZE);
BUILD_BUG_ON(sizeof(struct iwl_cmd_header) +
- offsetofend(struct iwl_tx_cmd_gen3, dram_info) >
+ offsetofend(struct iwl_tx_cmd, dram_info) >
IWL_FIRST_TB_SIZE);
memset(tfd, 0, sizeof(*tfd));
- if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
- len = sizeof(struct iwl_tx_cmd_gen2);
+ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ len = sizeof(struct iwl_tx_cmd_v9);
else
- len = sizeof(struct iwl_tx_cmd_gen3);
+ len = sizeof(struct iwl_tx_cmd);
amsdu = ieee80211_is_data_qos(hdr->frame_control) &&
(*ieee80211_get_qos_ctl(hdr) &
@@ -536,17 +535,17 @@ int iwl_txq_space(struct iwl_trans *trans, const struct iwl_txq *q)
* If q->n_window is smaller than max_tfd_queue_size, there is no need
* to reserve any queue entries for this purpose.
*/
- if (q->n_window < trans->trans_cfg->base_params->max_tfd_queue_size)
+ if (q->n_window < trans->mac_cfg->base->max_tfd_queue_size)
max = q->n_window;
else
- max = trans->trans_cfg->base_params->max_tfd_queue_size - 1;
+ max = trans->mac_cfg->base->max_tfd_queue_size - 1;
/*
* max_tfd_queue_size is a power of 2, so the following is equivalent to
* modulo by max_tfd_queue_size and is well defined.
*/
used = (q->write_ptr - q->read_ptr) &
- (trans->trans_cfg->base_params->max_tfd_queue_size - 1);
+ (trans->mac_cfg->base->max_tfd_queue_size - 1);
if (WARN_ON(used > max))
return 0;
@@ -561,8 +560,8 @@ static void iwl_pcie_gen2_update_byte_tbl(struct iwl_trans *trans,
struct iwl_txq *txq, u16 byte_cnt,
int num_tbs)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int idx = iwl_txq_get_cmd_index(txq, txq->write_ptr);
+ struct iwl_bc_tbl_entry *scd_bc_tbl = txq->bc_tbl.addr;
u8 filled_tfd_size, num_fetch_chunks;
u16 len = byte_cnt;
__le16 bc_ent;
@@ -582,24 +581,16 @@ static void iwl_pcie_gen2_update_byte_tbl(struct iwl_trans *trans,
*/
num_fetch_chunks = DIV_ROUND_UP(filled_tfd_size, 64) - 1;
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
- struct iwl_gen3_bc_tbl_entry *scd_bc_tbl_gen3 = txq->bc_tbl.addr;
-
- /* Starting from AX210, the HW expects bytes */
- WARN_ON(trans_pcie->txqs.bc_table_dword);
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
WARN_ON(len > 0x3FFF);
bc_ent = cpu_to_le16(len | (num_fetch_chunks << 14));
- scd_bc_tbl_gen3[idx].tfd_offset = bc_ent;
} else {
- struct iwlagn_scd_bc_tbl *scd_bc_tbl = txq->bc_tbl.addr;
-
- /* Before AX210, the HW expects DW */
- WARN_ON(!trans_pcie->txqs.bc_table_dword);
len = DIV_ROUND_UP(len, 4);
WARN_ON(len > 0xFFF);
bc_ent = cpu_to_le16(len | (num_fetch_chunks << 12));
- scd_bc_tbl->tfd_offset[idx] = bc_ent;
}
+
+ scd_bc_tbl[idx].tfd_offset = bc_ent;
}
static u8 iwl_txq_gen2_get_num_tbs(struct iwl_tfh_tfd *tfd)
@@ -756,7 +747,8 @@ int iwl_txq_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
struct iwl_device_tx_cmd **dev_cmd_ptr;
dev_cmd_ptr = (void *)((u8 *)skb->cb +
- trans_pcie->txqs.dev_cmd_offs);
+ trans->conf.cb_data_offs +
+ sizeof(void *));
*dev_cmd_ptr = dev_cmd;
__skb_queue_tail(&txq->overflow_q, skb);
@@ -785,16 +777,16 @@ int iwl_txq_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
return -1;
}
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
- struct iwl_tx_cmd_gen3 *tx_cmd_gen3 =
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+ struct iwl_tx_cmd *tx_cmd =
(void *)dev_cmd->payload;
- cmd_len = le16_to_cpu(tx_cmd_gen3->len);
+ cmd_len = le16_to_cpu(tx_cmd->len);
} else {
- struct iwl_tx_cmd_gen2 *tx_cmd_gen2 =
+ struct iwl_tx_cmd_v9 *tx_cmd_v9 =
(void *)dev_cmd->payload;
- cmd_len = le16_to_cpu(tx_cmd_gen2->len);
+ cmd_len = le16_to_cpu(tx_cmd_v9->len);
}
/* Set up entry for this TFD in Tx byte-count array */
@@ -832,7 +824,7 @@ static void iwl_txq_gen2_unmap(struct iwl_trans *trans, int txq_id)
IWL_DEBUG_TX_REPLY(trans, "Q %d Free %d\n",
txq_id, txq->read_ptr);
- if (txq_id != trans_pcie->txqs.cmd.q_id) {
+ if (txq_id != trans->conf.cmd_queue) {
int idx = iwl_txq_get_cmd_index(txq, txq->read_ptr);
struct iwl_cmd_meta *cmd_meta = &txq->entries[idx].meta;
struct sk_buff *skb = txq->entries[idx].skb;
@@ -906,7 +898,7 @@ static void iwl_txq_gen2_free(struct iwl_trans *trans, int txq_id)
iwl_txq_gen2_unmap(trans, txq_id);
/* De-alloc array of command/tx buffers */
- if (txq_id == trans_pcie->txqs.cmd.q_id)
+ if (txq_id == trans->conf.cmd_queue)
for (i = 0; i < txq->n_window; i++) {
kfree_sensitive(txq->entries[i].cmd);
kfree_sensitive(txq->entries[i].free_buf);
@@ -1007,7 +999,7 @@ static int iwl_pcie_txq_alloc_response(struct iwl_trans *trans,
txq->id = qid;
trans_pcie->txqs.txq[qid] = txq;
- wr_ptr &= (trans->trans_cfg->base_params->max_tfd_queue_size - 1);
+ wr_ptr &= (trans->mac_cfg->base->max_tfd_queue_size - 1);
/* Place first TFD at index corresponding to start sequence number */
txq->read_ptr = wr_ptr;
@@ -1043,8 +1035,8 @@ int iwl_txq_dyn_alloc(struct iwl_trans *trans, u32 flags, u32 sta_mask,
/* but must be power of 2 values for calculating read/write pointers */
size = rounddown_pow_of_two(size);
- if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_BZ &&
- trans->hw_rev_step == SILICON_A_STEP) {
+ if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_BZ &&
+ trans->info.hw_rev_step == SILICON_A_STEP) {
size = 4096;
txq = iwl_txq_dyn_alloc_dma(trans, size, timeout);
} else {
@@ -1064,7 +1056,7 @@ int iwl_txq_dyn_alloc(struct iwl_trans *trans, u32 flags, u32 sta_mask,
if (IS_ERR(txq))
return PTR_ERR(txq);
- if (trans_pcie->txqs.queue_alloc_cmd_ver == 0) {
+ if (trans->conf.queue_alloc_cmd_ver == 0) {
memset(&cmd.old, 0, sizeof(cmd.old));
cmd.old.tfdq_addr = cpu_to_le64(txq->dma_addr);
cmd.old.byte_cnt_addr = cpu_to_le64(txq->bc_tbl.dma);
@@ -1081,7 +1073,7 @@ int iwl_txq_dyn_alloc(struct iwl_trans *trans, u32 flags, u32 sta_mask,
hcmd.id = SCD_QUEUE_CFG;
hcmd.len[0] = sizeof(cmd.old);
hcmd.data[0] = &cmd.old;
- } else if (trans_pcie->txqs.queue_alloc_cmd_ver == 3) {
+ } else if (trans->conf.queue_alloc_cmd_ver == 3) {
memset(&cmd.new, 0, sizeof(cmd.new));
cmd.new.operation = cpu_to_le32(IWL_SCD_QUEUE_ADD);
cmd.new.u.add.tfdq_dram_addr = cpu_to_le64(txq->dma_addr);
@@ -1176,7 +1168,7 @@ int iwl_txq_gen2_init(struct iwl_trans *trans, int txq_id, int queue_size)
}
ret = iwl_txq_init(trans, queue, queue_size,
- (txq_id == trans_pcie->txqs.cmd.q_id));
+ (txq_id == trans->conf.cmd_queue));
if (ret) {
IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id);
goto error;
@@ -1206,7 +1198,7 @@ int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txqs.txq[trans_pcie->txqs.cmd.q_id];
+ struct iwl_txq *txq = trans_pcie->txqs.txq[trans->conf.cmd_queue];
struct iwl_device_cmd *out_cmd;
struct iwl_cmd_meta *out_meta;
void *dup_buf = NULL;
@@ -1323,7 +1315,7 @@ int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans,
cpu_to_le16(cmd_size - sizeof(struct iwl_cmd_header_wide));
out_cmd->hdr_wide.reserved = 0;
out_cmd->hdr_wide.sequence =
- cpu_to_le16(QUEUE_TO_SEQ(trans_pcie->txqs.cmd.q_id) |
+ cpu_to_le16(QUEUE_TO_SEQ(trans->conf.cmd_queue) |
INDEX_TO_SEQ(txq->write_ptr));
cmd_pos = sizeof(struct iwl_cmd_header_wide);
@@ -1371,7 +1363,7 @@ int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans,
"Sending command %s (%.2x.%.2x), seq: 0x%04X, %d bytes at %d[%d]:%d\n",
iwl_get_cmd_string(trans, cmd->id), group_id,
out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
- cmd_size, txq->write_ptr, idx, trans_pcie->txqs.cmd.q_id);
+ cmd_size, txq->write_ptr, idx, trans->conf.cmd_queue);
/* start the TFD with the minimum copy bytes */
tb0_size = min_t(int, copy_size, IWL_FIRST_TB_SIZE);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c
index 9fc4e98693eb..6e85aa519e1b 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c
@@ -25,6 +25,8 @@
#include "iwl-op-mode.h"
#include "internal.h"
#include "fw/api/tx.h"
+#include "fw/dbg.h"
+#include "pcie/utils.h"
/*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
* DMA services
@@ -78,7 +80,6 @@ void iwl_pcie_free_dma_ptr(struct iwl_trans *trans, struct iwl_dma_ptr *ptr)
static void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans,
struct iwl_txq *txq)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
u32 reg = 0;
int txq_id = txq->id;
@@ -90,8 +91,8 @@ static void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans,
* 2. NIC is woken up for CMD regardless of shadow outside this function
* 3. there is a chance that the NIC is asleep
*/
- if (!trans->trans_cfg->base_params->shadow_reg_enable &&
- txq_id != trans_pcie->txqs.cmd.q_id &&
+ if (!trans->mac_cfg->base->shadow_reg_enable &&
+ txq_id != trans->conf.cmd_queue &&
test_bit(STATUS_TPOWER_PMI, &trans->status)) {
/*
* wake up nic if it's powered down ...
@@ -125,7 +126,7 @@ void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int i;
- for (i = 0; i < trans->trans_cfg->base_params->num_of_queues; i++) {
+ for (i = 0; i < trans->mac_cfg->base->num_of_queues; i++) {
struct iwl_txq *txq = trans_pcie->txqs.txq[i];
if (!test_bit(i, trans_pcie->txqs.queue_used))
@@ -193,7 +194,7 @@ static void iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- if (!trans->trans_cfg->base_params->apmg_wake_up_wa)
+ if (!trans->mac_cfg->base->apmg_wake_up_wa)
return;
spin_lock(&trans_pcie->reg_lock);
@@ -204,8 +205,8 @@ static void iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans)
}
trans_pcie->cmd_hold_nic_awake = false;
- __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ iwl_trans_clear_bit(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
spin_unlock(&trans_pcie->reg_lock);
}
@@ -226,11 +227,10 @@ static void iwl_pcie_free_and_unmap_tso_page(struct iwl_trans *trans,
void iwl_pcie_free_tso_pages(struct iwl_trans *trans, struct sk_buff *skb,
struct iwl_cmd_meta *cmd_meta)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct page **page_ptr;
struct page *next;
- page_ptr = (void *)((u8 *)skb->cb + trans_pcie->txqs.page_offs);
+ page_ptr = (void *)((u8 *)skb->cb + trans->conf.cb_data_offs);
next = *page_ptr;
*page_ptr = NULL;
@@ -280,10 +280,12 @@ iwl_txq_gen1_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
static void iwl_txq_set_tfd_invalid_gen1(struct iwl_trans *trans,
struct iwl_tfd *tfd)
{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
tfd->num_tbs = 0;
- iwl_pcie_gen1_tfd_set_tb(tfd, 0, trans->invalid_tx_cmd.dma,
- trans->invalid_tx_cmd.size);
+ iwl_pcie_gen1_tfd_set_tb(tfd, 0, trans_pcie->invalid_tx_cmd.dma,
+ trans_pcie->invalid_tx_cmd.size);
}
static void iwl_txq_gen1_tfd_unmap(struct iwl_trans *trans,
@@ -355,7 +357,7 @@ static void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq,
/* We have only q->n_window txq->entries, but we use
* TFD_QUEUE_SIZE_MAX tfds
*/
- if (trans->trans_cfg->gen2)
+ if (trans->mac_cfg->gen2)
iwl_txq_gen2_tfd_unmap(trans, &txq->entries[idx].meta,
iwl_txq_get_tfd(trans, txq, read_ptr));
else
@@ -394,7 +396,7 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
IWL_DEBUG_TX_REPLY(trans, "Q %d Free %d\n",
txq_id, txq->read_ptr);
- if (txq_id != trans_pcie->txqs.cmd.q_id) {
+ if (txq_id != trans->conf.cmd_queue) {
struct sk_buff *skb = txq->entries[txq->read_ptr].skb;
struct iwl_cmd_meta *cmd_meta =
&txq->entries[txq->read_ptr].meta;
@@ -408,7 +410,7 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
txq->read_ptr = iwl_txq_inc_wrap(trans, txq->read_ptr);
if (txq->read_ptr == txq->write_ptr &&
- txq_id == trans_pcie->txqs.cmd.q_id)
+ txq_id == trans->conf.cmd_queue)
iwl_pcie_clear_cmd_in_flight(trans);
}
@@ -446,7 +448,7 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
iwl_pcie_txq_unmap(trans, txq_id);
/* De-alloc array of command/tx buffers */
- if (txq_id == trans_pcie->txqs.cmd.q_id)
+ if (txq_id == trans->conf.cmd_queue)
for (i = 0; i < txq->n_window; i++) {
kfree_sensitive(txq->entries[i].cmd);
kfree_sensitive(txq->entries[i].free_buf);
@@ -456,7 +458,7 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
if (txq->tfds) {
dma_free_coherent(dev,
trans_pcie->txqs.tfd.size *
- trans->trans_cfg->base_params->max_tfd_queue_size,
+ trans->mac_cfg->base->max_tfd_queue_size,
txq->tfds, txq->dma_addr);
txq->dma_addr = 0;
txq->tfds = NULL;
@@ -475,10 +477,10 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
memset(txq, 0, sizeof(*txq));
}
-void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
+void iwl_pcie_tx_start(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- int nq = trans->trans_cfg->base_params->num_of_queues;
+ int nq = trans->mac_cfg->base->num_of_queues;
int chan;
u32 reg_val;
int clear_dwords = (SCD_TRANS_TBL_OFFSET_QUEUE(nq) -
@@ -493,9 +495,6 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
trans_pcie->scd_base_addr =
iwl_read_prph(trans, SCD_SRAM_BASE_ADDR);
- WARN_ON(scd_base_addr != 0 &&
- scd_base_addr != trans_pcie->scd_base_addr);
-
/* reset context data, TX status and translation data */
iwl_trans_write_mem(trans, trans_pcie->scd_base_addr +
SCD_CONTEXT_MEM_LOWER_BOUND,
@@ -507,12 +506,12 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
/* The chain extension of the SCD doesn't work well. This feature is
* enabled by default by the HW, so we need to disable it manually.
*/
- if (trans->trans_cfg->base_params->scd_chain_ext_wa)
+ if (trans->mac_cfg->base->scd_chain_ext_wa)
iwl_write_prph(trans, SCD_CHAINEXT_EN, 0);
- iwl_trans_ac_txq_enable(trans, trans_pcie->txqs.cmd.q_id,
- trans_pcie->txqs.cmd.fifo,
- trans_pcie->txqs.cmd.wdg_timeout);
+ iwl_trans_ac_txq_enable(trans, trans->conf.cmd_queue,
+ trans->conf.cmd_fifo,
+ IWL_DEF_WD_TIMEOUT);
/* Activate all Tx DMA/FIFO channels */
iwl_scd_activate_fifos(trans);
@@ -529,7 +528,7 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
/* Enable L1-Active */
- if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000)
+ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_8000)
iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
}
@@ -543,13 +542,13 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans)
* we should never get here in gen2 trans mode return early to avoid
* having invalid accesses
*/
- if (WARN_ON_ONCE(trans->trans_cfg->gen2))
+ if (WARN_ON_ONCE(trans->mac_cfg->gen2))
return;
- for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues;
+ for (txq_id = 0; txq_id < trans->mac_cfg->base->num_of_queues;
txq_id++) {
struct iwl_txq *txq = trans_pcie->txqs.txq[txq_id];
- if (trans->trans_cfg->gen2)
+ if (trans->mac_cfg->gen2)
iwl_write_direct64(trans,
FH_MEM_CBBC_QUEUE(trans, txq_id),
txq->dma_addr);
@@ -571,7 +570,7 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans)
* while we were in WoWLAN in which case SCD_SRAM_BASE_ADDR will
* contain garbage.
*/
- iwl_pcie_tx_start(trans, 0);
+ iwl_pcie_tx_start(trans);
}
static void iwl_pcie_tx_stop_fh(struct iwl_trans *trans)
@@ -592,8 +591,8 @@ static void iwl_pcie_tx_stop_fh(struct iwl_trans *trans)
}
/* Wait for DMA channels to be idle */
- ret = iwl_poll_bit(trans, FH_TSSR_TX_STATUS_REG, mask, mask, 5000);
- if (ret < 0)
+ ret = iwl_poll_bits(trans, FH_TSSR_TX_STATUS_REG, mask, 5000);
+ if (ret)
IWL_ERR(trans,
"Failing on timeout while stopping DMA channel %d [0x%08x]\n",
ch, iwl_read32(trans, FH_TSSR_TX_STATUS_REG));
@@ -633,7 +632,7 @@ int iwl_pcie_tx_stop(struct iwl_trans *trans)
return 0;
/* Unmap DMA from host system and free skb's */
- for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues;
+ for (txq_id = 0; txq_id < trans->mac_cfg->base->num_of_queues;
txq_id++)
iwl_pcie_txq_unmap(trans, txq_id);
@@ -656,7 +655,7 @@ void iwl_pcie_tx_free(struct iwl_trans *trans)
/* Tx queues */
if (trans_pcie->txq_memory) {
for (txq_id = 0;
- txq_id < trans->trans_cfg->base_params->num_of_queues;
+ txq_id < trans->mac_cfg->base->num_of_queues;
txq_id++) {
iwl_pcie_txq_free(trans, txq_id);
trans_pcie->txqs.txq[txq_id] = NULL;
@@ -678,7 +677,7 @@ void iwl_txq_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq)
bool active;
u8 fifo;
- if (trans->trans_cfg->gen2) {
+ if (trans->mac_cfg->gen2) {
IWL_ERR(trans, "Queue %d is stuck %d %d\n", txq_id,
txq->read_ptr, txq->write_ptr);
/* TODO: access new SCD registers and dump them */
@@ -695,15 +694,15 @@ void iwl_txq_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq)
jiffies_to_msecs(txq->wd_timeout),
txq->read_ptr, txq->write_ptr,
iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) &
- (trans->trans_cfg->base_params->max_tfd_queue_size - 1),
+ (trans->mac_cfg->base->max_tfd_queue_size - 1),
iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)) &
- (trans->trans_cfg->base_params->max_tfd_queue_size - 1),
+ (trans->mac_cfg->base->max_tfd_queue_size - 1),
iwl_read_direct32(trans, FH_TX_TRB_REG(fifo)));
}
static void iwl_txq_stuck_timer(struct timer_list *t)
{
- struct iwl_txq *txq = from_timer(txq, t, stuck_timer);
+ struct iwl_txq *txq = timer_container_of(txq, t, stuck_timer);
struct iwl_trans *trans = txq->trans;
spin_lock(&txq->lock);
@@ -723,8 +722,8 @@ int iwl_pcie_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq,
int slots_num, bool cmd_queue)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- size_t num_entries = trans->trans_cfg->gen2 ?
- slots_num : trans->trans_cfg->base_params->max_tfd_queue_size;
+ size_t num_entries = trans->mac_cfg->gen2 ?
+ slots_num : trans->mac_cfg->base->max_tfd_queue_size;
size_t tfd_sz;
size_t tb0_buf_sz;
int i;
@@ -779,7 +778,7 @@ int iwl_pcie_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq,
for (i = 0; i < num_entries; i++) {
void *tfd = iwl_txq_get_tfd(trans, txq, i);
- if (trans->trans_cfg->gen2)
+ if (trans->mac_cfg->gen2)
iwl_txq_set_tfd_invalid_gen2(trans, tfd);
else
iwl_txq_set_tfd_invalid_gen1(trans, tfd);
@@ -799,6 +798,8 @@ error:
return -ENOMEM;
}
+#define BC_TABLE_SIZE (sizeof(struct iwl_bc_tbl_entry) * TFD_QUEUE_BC_SIZE)
+
/*
* iwl_pcie_tx_alloc - allocate TX context
* Allocate all Tx DMA structures and initialize them
@@ -808,12 +809,12 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
int ret;
int txq_id, slots_num;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- u16 bc_tbls_size = trans->trans_cfg->base_params->num_of_queues;
+ u16 bc_tbls_size = trans->mac_cfg->base->num_of_queues;
- if (WARN_ON(trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210))
+ if (WARN_ON(trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210))
return -EINVAL;
- bc_tbls_size *= sizeof(struct iwlagn_scd_bc_tbl);
+ bc_tbls_size *= BC_TABLE_SIZE;
/*It is not allowed to alloc twice, so warn when this happens.
* We cannot rely on the previous allocation, so free and fail */
@@ -837,7 +838,7 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
}
trans_pcie->txq_memory =
- kcalloc(trans->trans_cfg->base_params->num_of_queues,
+ kcalloc(trans->mac_cfg->base->num_of_queues,
sizeof(struct iwl_txq), GFP_KERNEL);
if (!trans_pcie->txq_memory) {
IWL_ERR(trans, "Not enough memory for txq\n");
@@ -846,16 +847,16 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
}
/* Alloc and init all Tx queues, including the command queue (#4/#9) */
- for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues;
+ for (txq_id = 0; txq_id < trans->mac_cfg->base->num_of_queues;
txq_id++) {
- bool cmd_queue = (txq_id == trans_pcie->txqs.cmd.q_id);
+ bool cmd_queue = (txq_id == trans->conf.cmd_queue);
if (cmd_queue)
slots_num = max_t(u32, IWL_CMD_QUEUE_SIZE,
- trans->cfg->min_txq_size);
+ trans->mac_cfg->base->min_txq_size);
else
slots_num = max_t(u32, IWL_DEFAULT_QUEUE_SIZE,
- trans->cfg->min_ba_txq_size);
+ trans->mac_cfg->base->min_ba_txq_size);
trans_pcie->txqs.txq[txq_id] = &trans_pcie->txq_memory[txq_id];
ret = iwl_pcie_txq_alloc(trans, trans_pcie->txqs.txq[txq_id],
slots_num, cmd_queue);
@@ -905,7 +906,7 @@ int iwl_txq_init(struct iwl_trans *trans, struct iwl_txq *txq,
int slots_num, bool cmd_queue)
{
u32 tfd_queue_max_size =
- trans->trans_cfg->base_params->max_tfd_queue_size;
+ trans->mac_cfg->base->max_tfd_queue_size;
int ret;
txq->need_update = false;
@@ -963,16 +964,16 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
spin_unlock_bh(&trans_pcie->irq_lock);
/* Alloc and init all Tx queues, including the command queue (#4/#9) */
- for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues;
+ for (txq_id = 0; txq_id < trans->mac_cfg->base->num_of_queues;
txq_id++) {
- bool cmd_queue = (txq_id == trans_pcie->txqs.cmd.q_id);
+ bool cmd_queue = (txq_id == trans->conf.cmd_queue);
if (cmd_queue)
slots_num = max_t(u32, IWL_CMD_QUEUE_SIZE,
- trans->cfg->min_txq_size);
+ trans->mac_cfg->base->min_txq_size);
else
slots_num = max_t(u32, IWL_DEFAULT_QUEUE_SIZE,
- trans->cfg->min_ba_txq_size);
+ trans->mac_cfg->base->min_ba_txq_size);
ret = iwl_txq_init(trans, trans_pcie->txqs.txq[txq_id], slots_num,
cmd_queue);
if (ret) {
@@ -991,7 +992,7 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
}
iwl_set_bits_prph(trans, SCD_GP_CTRL, SCD_GP_CTRL_AUTO_ACTIVE_MODE);
- if (trans->trans_cfg->base_params->num_of_queues > 20)
+ if (trans->mac_cfg->base->num_of_queues > 20)
iwl_set_bits_prph(trans, SCD_GP_CTRL,
SCD_GP_CTRL_ENABLE_31_QUEUES);
@@ -1012,7 +1013,7 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
if (test_bit(STATUS_TRANS_DEAD, &trans->status))
return -ENODEV;
- if (!trans->trans_cfg->base_params->apmg_wake_up_wa)
+ if (!trans->mac_cfg->base->apmg_wake_up_wa)
return 0;
/*
@@ -1090,12 +1091,12 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
idx = iwl_txq_get_cmd_index(txq, idx);
r = iwl_txq_get_cmd_index(txq, txq->read_ptr);
- if (idx >= trans->trans_cfg->base_params->max_tfd_queue_size ||
+ if (idx >= trans->mac_cfg->base->max_tfd_queue_size ||
(!iwl_txq_used(txq, idx, txq->read_ptr, txq->write_ptr))) {
WARN_ONCE(test_bit(txq_id, trans_pcie->txqs.queue_used),
"%s: Read index for DMA queue txq id (%d), index %d is out of range [0-%d] %d %d.\n",
__func__, txq_id, idx,
- trans->trans_cfg->base_params->max_tfd_queue_size,
+ trans->mac_cfg->base->max_tfd_queue_size,
txq->write_ptr, txq->read_ptr);
return;
}
@@ -1164,15 +1165,15 @@ bool iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
fifo = cfg->fifo;
/* Disable the scheduler prior configuring the cmd queue */
- if (txq_id == trans_pcie->txqs.cmd.q_id &&
- trans_pcie->scd_set_active)
+ if (txq_id == trans->conf.cmd_queue &&
+ trans->conf.scd_set_active)
iwl_scd_enable_set_active(trans, 0);
/* Stop this Tx queue before configuring it */
iwl_scd_txq_set_inactive(trans, txq_id);
/* Set this queue as a chain-building queue unless it is CMD */
- if (txq_id != trans_pcie->txqs.cmd.q_id)
+ if (txq_id != trans->conf.cmd_queue)
iwl_scd_txq_set_chain(trans, txq_id);
if (cfg->aggregate) {
@@ -1206,7 +1207,7 @@ bool iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
* this sad hardware issue.
* This bug has been fixed on devices 9000 and up.
*/
- scd_bug = !trans->trans_cfg->mq_rx_supported &&
+ scd_bug = !trans->mac_cfg->mq_rx_supported &&
!((ssn - txq->write_ptr) & 0x3f) &&
(ssn != txq->write_ptr);
if (scd_bug)
@@ -1242,8 +1243,8 @@ bool iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
SCD_QUEUE_STTS_REG_MSK);
/* enable the scheduler for this queue (only) */
- if (txq_id == trans_pcie->txqs.cmd.q_id &&
- trans_pcie->scd_set_active)
+ if (txq_id == trans->conf.cmd_queue &&
+ trans->conf.scd_set_active)
iwl_scd_enable_set_active(trans, BIT(txq_id));
IWL_DEBUG_TX_QUEUES(trans,
@@ -1310,10 +1311,10 @@ static void iwl_trans_pcie_block_txq_ptrs(struct iwl_trans *trans, bool block)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int i;
- for (i = 0; i < trans->trans_cfg->base_params->num_of_queues; i++) {
+ for (i = 0; i < trans->mac_cfg->base->num_of_queues; i++) {
struct iwl_txq *txq = trans_pcie->txqs.txq[i];
- if (i == trans_pcie->txqs.cmd.q_id)
+ if (i == trans->conf.cmd_queue)
continue;
/* we skip the command queue (obviously) so it's OK to nest */
@@ -1346,7 +1347,7 @@ int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txqs.txq[trans_pcie->txqs.cmd.q_id];
+ struct iwl_txq *txq = trans_pcie->txqs.txq[trans->conf.cmd_queue];
struct iwl_device_cmd *out_cmd;
struct iwl_cmd_meta *out_meta;
void *dup_buf = NULL;
@@ -1361,7 +1362,7 @@ int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD];
unsigned long flags;
- if (WARN(!trans->wide_cmd_header &&
+ if (WARN(!trans->conf.wide_cmd_header &&
group_id > IWL_ALWAYS_LONG_GROUP,
"unsupported wide command %#x\n", cmd->id))
return -EINVAL;
@@ -1475,7 +1476,7 @@ int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
sizeof(struct iwl_cmd_header_wide));
out_cmd->hdr_wide.reserved = 0;
out_cmd->hdr_wide.sequence =
- cpu_to_le16(QUEUE_TO_SEQ(trans_pcie->txqs.cmd.q_id) |
+ cpu_to_le16(QUEUE_TO_SEQ(trans->conf.cmd_queue) |
INDEX_TO_SEQ(txq->write_ptr));
cmd_pos = sizeof(struct iwl_cmd_header_wide);
@@ -1483,7 +1484,7 @@ int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
} else {
out_cmd->hdr.cmd = iwl_cmd_opcode(cmd->id);
out_cmd->hdr.sequence =
- cpu_to_le16(QUEUE_TO_SEQ(trans_pcie->txqs.cmd.q_id) |
+ cpu_to_le16(QUEUE_TO_SEQ(trans->conf.cmd_queue) |
INDEX_TO_SEQ(txq->write_ptr));
out_cmd->hdr.group_id = 0;
@@ -1534,7 +1535,7 @@ int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
iwl_get_cmd_string(trans, cmd->id),
group_id, out_cmd->hdr.cmd,
le16_to_cpu(out_cmd->hdr.sequence),
- cmd_size, txq->write_ptr, idx, trans_pcie->txqs.cmd.q_id);
+ cmd_size, txq->write_ptr, idx, trans->conf.cmd_queue);
/* start the TFD with the minimum copy bytes */
tb0_size = min_t(int, copy_size, IWL_FIRST_TB_SIZE);
@@ -1633,18 +1634,16 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
struct iwl_device_cmd *cmd;
struct iwl_cmd_meta *meta;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txqs.txq[trans_pcie->txqs.cmd.q_id];
+ struct iwl_txq *txq = trans_pcie->txqs.txq[trans->conf.cmd_queue];
/* If a Tx command is being handled and it isn't in the actual
* command queue then there a command routing bug has been introduced
* in the queue management code. */
- if (WARN(txq_id != trans_pcie->txqs.cmd.q_id,
- "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
- txq_id, trans_pcie->txqs.cmd.q_id, sequence, txq->read_ptr,
- txq->write_ptr)) {
- iwl_print_hex_error(trans, pkt, 32);
+ if (IWL_FW_CHECK(trans, txq_id != trans->conf.cmd_queue,
+ "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d pkt=%*phN\n",
+ txq_id, trans->conf.cmd_queue, sequence, txq->read_ptr,
+ txq->write_ptr, 32, pkt))
return;
- }
spin_lock_bh(&txq->lock);
@@ -1654,7 +1653,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
group_id = cmd->hdr.group_id;
cmd_id = WIDE_ID(group_id, cmd->hdr.cmd);
- if (trans->trans_cfg->gen2)
+ if (trans->mac_cfg->gen2)
iwl_txq_gen2_tfd_unmap(trans, meta,
iwl_txq_get_tfd(trans, txq, index));
else
@@ -1683,7 +1682,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n",
iwl_get_cmd_string(trans, cmd_id));
- wake_up(&trans->wait_command_queue);
+ wake_up(&trans_pcie->wait_command_queue);
}
meta->flags = 0;
@@ -1753,7 +1752,7 @@ static void *iwl_pcie_get_page_hdr(struct iwl_trans *trans,
dma_addr_t phys;
void *ret;
- page_ptr = (void *)((u8 *)skb->cb + trans_pcie->txqs.page_offs);
+ page_ptr = (void *)((u8 *)skb->cb + trans->conf.cb_data_offs);
if (WARN_ON(*page_ptr))
return NULL;
@@ -1912,7 +1911,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
u16 tb1_len)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload;
+ struct iwl_tx_cmd_v6 *tx_cmd = (void *)dev_cmd->payload;
struct ieee80211_hdr *hdr = (void *)skb->data;
unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room;
unsigned int mss = skb_shinfo(skb)->gso_size;
@@ -1964,7 +1963,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
* have in the MPDU by themselves, but that we duplicate into
* all the different MSDUs inside the A-MSDU.
*/
- le16_add_cpu(&tx_cmd->len, -snap_ip_tcp_hdrlen);
+ le16_add_cpu(&tx_cmd->params.len, -snap_ip_tcp_hdrlen);
tso_start(skb, &tso);
@@ -2007,7 +2006,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
trace_iwlwifi_dev_tx_tb(trans->dev, skb, start_hdr,
hdr_tb_phys, hdr_tb_len);
/* add this subframe's headers' length to the tx_cmd */
- le16_add_cpu(&tx_cmd->len, pos_hdr - subf_hdrs_start);
+ le16_add_cpu(&tx_cmd->params.len, pos_hdr - subf_hdrs_start);
/* prepare the start_hdr for the next subframe */
start_hdr = pos_hdr;
@@ -2067,19 +2066,19 @@ static void iwl_txq_gen1_update_byte_cnt_tbl(struct iwl_trans *trans,
int num_tbs)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwlagn_scd_bc_tbl *scd_bc_tbl;
+ struct iwl_bc_tbl_entry *scd_bc_tbl;
int write_ptr = txq->write_ptr;
int txq_id = txq->id;
u8 sec_ctl = 0;
u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
__le16 bc_ent;
struct iwl_device_tx_cmd *dev_cmd = txq->entries[txq->write_ptr].cmd;
- struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload;
- u8 sta_id = tx_cmd->sta_id;
+ struct iwl_tx_cmd_v6 *tx_cmd = (void *)dev_cmd->payload;
+ u8 sta_id = tx_cmd->params.sta_id;
scd_bc_tbl = trans_pcie->txqs.scd_bc_tbls.addr;
- sec_ctl = tx_cmd->sec_ctl;
+ sec_ctl = tx_cmd->params.sec_ctl;
switch (sec_ctl & TX_CMD_SEC_MSK) {
case TX_CMD_SEC_CCM:
@@ -2092,7 +2091,9 @@ static void iwl_txq_gen1_update_byte_cnt_tbl(struct iwl_trans *trans,
len += IEEE80211_WEP_IV_LEN + IEEE80211_WEP_ICV_LEN;
break;
}
- if (trans_pcie->txqs.bc_table_dword)
+
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_7000 &&
+ trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
len = DIV_ROUND_UP(len, 4);
if (WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX))
@@ -2100,10 +2101,10 @@ static void iwl_txq_gen1_update_byte_cnt_tbl(struct iwl_trans *trans,
bc_ent = cpu_to_le16(len | (sta_id << 12));
- scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
+ scd_bc_tbl[txq_id * TFD_QUEUE_BC_SIZE + write_ptr].tfd_offset = bc_ent;
if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
- scd_bc_tbl[txq_id].tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] =
+ scd_bc_tbl[txq_id * TFD_QUEUE_BC_SIZE + TFD_QUEUE_SIZE_MAX + write_ptr].tfd_offset =
bc_ent;
}
@@ -2112,7 +2113,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct ieee80211_hdr *hdr;
- struct iwl_tx_cmd *tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;
+ struct iwl_tx_cmd_v6 *tx_cmd = (struct iwl_tx_cmd_v6 *)dev_cmd->payload;
struct iwl_cmd_meta *out_meta;
struct iwl_txq *txq;
dma_addr_t tb0_phys, tb1_phys, scratch_phys;
@@ -2153,7 +2154,8 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
struct iwl_device_tx_cmd **dev_cmd_ptr;
dev_cmd_ptr = (void *)((u8 *)skb->cb +
- trans_pcie->txqs.dev_cmd_offs);
+ trans->conf.cb_data_offs +
+ sizeof(void *));
*dev_cmd_ptr = dev_cmd;
__skb_queue_tail(&txq->overflow_q, skb);
@@ -2184,10 +2186,10 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
tb0_phys = iwl_txq_get_first_tb_dma(txq, txq->write_ptr);
scratch_phys = tb0_phys + sizeof(struct iwl_cmd_header) +
- offsetof(struct iwl_tx_cmd, scratch);
+ offsetof(struct iwl_tx_cmd_v6_params, scratch);
- tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
- tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
+ tx_cmd->params.dram_lsb_ptr = cpu_to_le32(scratch_phys);
+ tx_cmd->params.dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
/* Set up first empty entry in queue's array of Tx/cmd buffers */
out_meta = &txq->entries[txq->write_ptr].meta;
@@ -2199,7 +2201,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
* (This calculation modifies the TX command, so do it before the
* setup of the first TB)
*/
- len = sizeof(struct iwl_tx_cmd) + sizeof(struct iwl_cmd_header) +
+ len = sizeof(struct iwl_tx_cmd_v6) + sizeof(struct iwl_cmd_header) +
hdr_len - IWL_FIRST_TB_SIZE;
/* do not align A-MSDU to dword as the subframe header aligns it */
amsdu = ieee80211_is_data_qos(fc) &&
@@ -2209,7 +2211,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
tb1_len = ALIGN(len, 4);
/* Tell NIC about any 2-byte padding after MAC header */
if (tb1_len != len)
- tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_MH_PAD);
+ tx_cmd->params.tx_flags |= cpu_to_le32(TX_CMD_FLG_MH_PAD);
} else {
tb1_len = len;
}
@@ -2222,9 +2224,9 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
IWL_FIRST_TB_SIZE, true);
/* there must be data left over for TB1 or this code must be changed */
- BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_FIRST_TB_SIZE);
+ BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_v6) < IWL_FIRST_TB_SIZE);
BUILD_BUG_ON(sizeof(struct iwl_cmd_header) +
- offsetofend(struct iwl_tx_cmd, scratch) >
+ offsetofend(struct iwl_tx_cmd_v6_params, scratch) >
IWL_FIRST_TB_SIZE);
/* map the data for TB1 */
@@ -2270,7 +2272,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
tfd = iwl_txq_get_tfd(trans, txq, txq->write_ptr);
/* Set up entry for this TFD in Tx byte-count array */
- iwl_txq_gen1_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len),
+ iwl_txq_gen1_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->params.len),
iwl_txq_gen1_tfd_get_num_tbs(tfd));
wait_write_ptr = ieee80211_has_morefrags(fc);
@@ -2312,24 +2314,24 @@ static void iwl_txq_gen1_inval_byte_cnt_tbl(struct iwl_trans *trans,
int read_ptr)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwlagn_scd_bc_tbl *scd_bc_tbl = trans_pcie->txqs.scd_bc_tbls.addr;
+ struct iwl_bc_tbl_entry *scd_bc_tbl = trans_pcie->txqs.scd_bc_tbls.addr;
int txq_id = txq->id;
u8 sta_id = 0;
__le16 bc_ent;
struct iwl_device_tx_cmd *dev_cmd = txq->entries[read_ptr].cmd;
- struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload;
+ struct iwl_tx_cmd_v6 *tx_cmd = (void *)dev_cmd->payload;
WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
- if (txq_id != trans_pcie->txqs.cmd.q_id)
- sta_id = tx_cmd->sta_id;
+ if (txq_id != trans->conf.cmd_queue)
+ sta_id = tx_cmd->params.sta_id;
bc_ent = cpu_to_le16(1 | (sta_id << 12));
- scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
+ scd_bc_tbl[txq_id * TFD_QUEUE_BC_SIZE + read_ptr].tfd_offset = bc_ent;
if (read_ptr < TFD_QUEUE_SIZE_BC_DUP)
- scd_bc_tbl[txq_id].tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] =
+ scd_bc_tbl[txq_id * TFD_QUEUE_BC_SIZE + TFD_QUEUE_SIZE_MAX + read_ptr].tfd_offset =
bc_ent;
}
@@ -2343,7 +2345,7 @@ void iwl_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
int txq_read_ptr, txq_write_ptr;
/* This function is not meant to release cmd queue*/
- if (WARN_ON(txq_id == trans_pcie->txqs.cmd.q_id))
+ if (WARN_ON(txq_id == trans->conf.cmd_queue))
return;
if (WARN_ON(!txq))
@@ -2385,7 +2387,7 @@ void iwl_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
IWL_ERR(trans,
"%s: Read index for txq id (%d), last_to_free %d is out of range [0-%d] %d %d.\n",
__func__, txq_id, last_to_free,
- trans->trans_cfg->base_params->max_tfd_queue_size,
+ trans->mac_cfg->base->max_tfd_queue_size,
txq_write_ptr, txq_read_ptr);
iwl_op_mode_time_point(trans->op_mode,
@@ -2414,7 +2416,7 @@ void iwl_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
txq->entries[read_ptr].skb = NULL;
- if (!trans->trans_cfg->gen2)
+ if (!trans->mac_cfg->gen2)
iwl_txq_gen1_inval_byte_cnt_tbl(trans, txq,
txq_read_ptr);
@@ -2456,7 +2458,8 @@ void iwl_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
struct iwl_device_tx_cmd *dev_cmd_ptr;
dev_cmd_ptr = *(void **)((u8 *)skb->cb +
- trans_pcie->txqs.dev_cmd_offs);
+ trans->conf.cb_data_offs +
+ sizeof(void *));
/*
* Note that we can very well be overflowing again.
@@ -2548,11 +2551,11 @@ next_queue:
#define HOST_COMPLETE_TIMEOUT (2 * HZ)
static int iwl_trans_pcie_send_hcmd_sync(struct iwl_trans *trans,
- struct iwl_host_cmd *cmd)
+ struct iwl_host_cmd *cmd,
+ const char *cmd_str)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- const char *cmd_str = iwl_get_cmd_string(trans, cmd->id);
- struct iwl_txq *txq = trans_pcie->txqs.txq[trans_pcie->txqs.cmd.q_id];
+ struct iwl_txq *txq = trans_pcie->txqs.txq[trans->conf.cmd_queue];
int cmd_idx;
int ret;
@@ -2565,7 +2568,7 @@ static int iwl_trans_pcie_send_hcmd_sync(struct iwl_trans *trans,
IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n", cmd_str);
- if (trans->trans_cfg->gen2)
+ if (trans->mac_cfg->gen2)
cmd_idx = iwl_pcie_gen2_enqueue_hcmd(trans, cmd);
else
cmd_idx = iwl_pcie_enqueue_hcmd(trans, cmd);
@@ -2578,7 +2581,7 @@ static int iwl_trans_pcie_send_hcmd_sync(struct iwl_trans *trans,
return ret;
}
- ret = wait_event_timeout(trans->wait_command_queue,
+ ret = wait_event_timeout(trans_pcie->wait_command_queue,
!test_bit(STATUS_SYNC_HCMD_ACTIVE,
&trans->status),
HOST_COMPLETE_TIMEOUT);
@@ -2594,13 +2597,14 @@ static int iwl_trans_pcie_send_hcmd_sync(struct iwl_trans *trans,
cmd_str);
ret = -ETIMEDOUT;
- iwl_trans_sync_nmi(trans);
+ iwl_trans_pcie_sync_nmi(trans);
goto cancel;
}
if (test_bit(STATUS_FW_ERROR, &trans->status)) {
- if (!test_and_clear_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE,
- &trans->status)) {
+ if (trans->suppress_cmd_error_once) {
+ trans->suppress_cmd_error_once = false;
+ } else {
IWL_ERR(trans, "FW error in SYNC CMD %s\n", cmd_str);
dump_stack();
}
@@ -2645,6 +2649,8 @@ cancel:
int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd)
{
+ const char *cmd_str = iwl_get_cmd_string(trans, cmd->id);
+
/* Make sure the NIC is still alive in the bus */
if (test_bit(STATUS_TRANS_DEAD, &trans->status))
return -ENODEV;
@@ -2656,20 +2662,16 @@ int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans,
return -ERFKILL;
}
- if (unlikely(trans->system_pm_mode == IWL_PLAT_PM_MODE_D3 &&
- !(cmd->flags & CMD_SEND_IN_D3))) {
- IWL_DEBUG_WOWLAN(trans, "Dropping CMD 0x%x: D3\n", cmd->id);
- return -EHOSTDOWN;
- }
-
if (cmd->flags & CMD_ASYNC) {
int ret;
+ IWL_DEBUG_INFO(trans, "Sending async command %s\n", cmd_str);
+
/* An asynchronous command can not expect an SKB to be set. */
if (WARN_ON(cmd->flags & CMD_WANT_SKB))
return -EINVAL;
- if (trans->trans_cfg->gen2)
+ if (trans->mac_cfg->gen2)
ret = iwl_pcie_gen2_enqueue_hcmd(trans, cmd);
else
ret = iwl_pcie_enqueue_hcmd(trans, cmd);
@@ -2683,6 +2685,5 @@ int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans,
return 0;
}
- return iwl_trans_pcie_send_hcmd_sync(trans, cmd);
+ return iwl_trans_pcie_send_hcmd_sync(trans, cmd, cmd_str);
}
-IWL_EXPORT_SYMBOL(iwl_trans_pcie_send_hcmd);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h b/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info-v2.h
index 20563a32a21a..416baadc5017 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info-v2.h
@@ -2,8 +2,8 @@
/*
* Copyright (C) 2018, 2020-2025 Intel Corporation
*/
-#ifndef __iwl_context_info_file_gen3_h__
-#define __iwl_context_info_file_gen3_h__
+#ifndef __iwl_context_info_file_v2_h__
+#define __iwl_context_info_file_v2_h__
#include "iwl-context-info.h"
@@ -58,6 +58,7 @@ enum iwl_prph_scratch_mtr_format {
* @IWL_PRPH_SCRATCH_RB_SIZE_EXT_16K: 16kB RB size
* @IWL_PRPH_SCRATCH_SCU_FORCE_ACTIVE: Indicate fw to set SCU_FORCE_ACTIVE
* upon reset.
+ * @IWL_PRPH_SCRATCH_TOP_RESET: request TOP reset
*/
enum iwl_prph_scratch_flags {
IWL_PRPH_SCRATCH_IMR_DEBUG_EN = BIT(1),
@@ -74,15 +75,18 @@ enum iwl_prph_scratch_flags {
IWL_PRPH_SCRATCH_RB_SIZE_EXT_12K = 9 << 20,
IWL_PRPH_SCRATCH_RB_SIZE_EXT_16K = 10 << 20,
IWL_PRPH_SCRATCH_SCU_FORCE_ACTIVE = BIT(29),
+ IWL_PRPH_SCRATCH_TOP_RESET = BIT(30),
};
/**
* enum iwl_prph_scratch_ext_flags - PRPH scratch control ext flags
+ * @IWL_PRPH_SCRATCH_EXT_EXT_FSEQ: external FSEQ image provided
* @IWL_PRPH_SCRATCH_EXT_URM_FW: switch to URM mode based on fw setting
* @IWL_PRPH_SCRATCH_EXT_URM_PERM: switch to permanent URM mode
* @IWL_PRPH_SCRATCH_EXT_32KHZ_CLK_VALID: use external 32 KHz clock
*/
enum iwl_prph_scratch_ext_flags {
+ IWL_PRPH_SCRATCH_EXT_EXT_FSEQ = BIT(0),
IWL_PRPH_SCRATCH_EXT_URM_FW = BIT(4),
IWL_PRPH_SCRATCH_EXT_URM_PERM = BIT(5),
IWL_PRPH_SCRATCH_EXT_32KHZ_CLK_VALID = BIT(8),
@@ -126,11 +130,11 @@ struct iwl_prph_scratch_pnvm_cfg {
} __packed; /* PERIPH_SCRATCH_PNVM_CFG_S */
/**
- * struct iwl_prph_scrath_mem_desc_addr_array
+ * struct iwl_prph_scratch_mem_desc_addr_array - DRAM
* @mem_descs: array of dram addresses.
- * Each address is the beggining of a pnvm payload.
+ * Each address is the beginning of a PNVM payload.
*/
-struct iwl_prph_scrath_mem_desc_addr_array {
+struct iwl_prph_scratch_mem_desc_addr_array {
__le64 mem_descs[IPC_DRAM_MAP_ENTRY_NUM_MAX];
} __packed; /* PERIPH_SCRATCH_MEM_DESC_ADDR_ARRAY_S_VER_1 */
@@ -202,6 +206,19 @@ struct iwl_prph_scratch_ctrl_cfg {
struct iwl_prph_scratch_step_cfg step_cfg;
} __packed; /* PERIPH_SCRATCH_CTRL_CFG_S */
+#define IWL_NUM_DRAM_FSEQ_ENTRIES 8
+
+/**
+ * struct iwl_context_info_dram_fseq - images DRAM map (with fseq)
+ * each entry in the map represents a DRAM chunk of up to 32 KB
+ * @common: UMAC/LMAC/virtual images
+ * @fseq_img: FSEQ image DRAM map
+ */
+struct iwl_context_info_dram_fseq {
+ struct iwl_context_info_dram_nonfseq common;
+ __le64 fseq_img[IWL_NUM_DRAM_FSEQ_ENTRIES];
+} __packed; /* PERIPH_SCRATCH_DRAM_MAP_S */
+
/**
* struct iwl_prph_scratch - peripheral scratch mapping
* @ctrl_cfg: control and configuration of prph scratch
@@ -215,7 +232,7 @@ struct iwl_prph_scratch {
__le32 fseq_override;
__le32 step_analog_params;
__le32 reserved[8];
- struct iwl_context_info_dram dram;
+ struct iwl_context_info_dram_fseq dram;
} __packed; /* PERIPH_SCRATCH_S */
/**
@@ -233,7 +250,7 @@ struct iwl_prph_info {
} __packed; /* PERIPH_INFO_S */
/**
- * struct iwl_context_info_gen3 - device INIT configuration
+ * struct iwl_context_info_v2 - device INIT configuration
* @version: version of the context information
* @size: size of context information in DWs
* @config: context in which the peripheral would execute - a subset of
@@ -276,7 +293,7 @@ struct iwl_prph_info {
* @prph_scratch_size: the size of the peripheral scratch structure in DWs
* @reserved: reserved
*/
-struct iwl_context_info_gen3 {
+struct iwl_context_info_v2 {
__le16 version;
__le16 size;
__le32 config;
@@ -306,22 +323,22 @@ struct iwl_context_info_gen3 {
__le32 reserved;
} __packed; /* IPC_CONTEXT_INFO_S */
-int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
- const struct fw_img *fw);
-void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive);
+int iwl_pcie_ctxt_info_v2_alloc(struct iwl_trans *trans,
+ const struct iwl_fw *fw,
+ const struct fw_img *img);
+void iwl_pcie_ctxt_info_v2_kick(struct iwl_trans *trans);
+void iwl_pcie_ctxt_info_v2_free(struct iwl_trans *trans, bool alive);
-int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans,
- const struct iwl_pnvm_image *pnvm_payloads,
- const struct iwl_ucode_capabilities *capa);
-void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
- const struct iwl_ucode_capabilities *capa);
+int iwl_trans_pcie_ctx_info_v2_load_pnvm(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *pnvm_payloads,
+ const struct iwl_ucode_capabilities *capa);
+void iwl_trans_pcie_ctx_info_v2_set_pnvm(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa);
int
-iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans,
- const struct iwl_pnvm_image *payloads,
- const struct iwl_ucode_capabilities *capa);
+iwl_trans_pcie_ctx_info_v2_load_reduce_power(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *payloads,
+ const struct iwl_ucode_capabilities *capa);
void
-iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans,
- const struct iwl_ucode_capabilities *capa);
-int iwl_trans_pcie_ctx_info_gen3_set_step(struct iwl_trans *trans,
- u32 mbx_addr_0_step, u32 mbx_addr_1_step);
-#endif /* __iwl_context_info_file_gen3_h__ */
+iwl_trans_pcie_ctx_info_v2_set_reduce_power(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa);
+#endif /* __iwl_context_info_file_v2_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h b/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info.h
index dfd44fabf237..7ae0fbdef208 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2020, 2022, 2024 Intel Corporation
+ * Copyright (C) 2018-2020, 2022, 2024-2025 Intel Corporation
*/
#ifndef __iwl_context_info_file_h__
#define __iwl_context_info_file_h__
@@ -78,13 +78,13 @@ struct iwl_context_info_control {
} __packed;
/**
- * struct iwl_context_info_dram - images DRAM map
+ * struct iwl_context_info_dram_nonfseq - images DRAM map
* each entry in the map represents a DRAM chunk of up to 32 KB
* @umac_img: UMAC image DRAM map
* @lmac_img: LMAC image DRAM map
* @virtual_img: paged image DRAM map
*/
-struct iwl_context_info_dram {
+struct iwl_context_info_dram_nonfseq {
__le64 umac_img[IWL_MAX_DRAM_ENTRY];
__le64 lmac_img[IWL_MAX_DRAM_ENTRY];
__le64 virtual_img[IWL_MAX_DRAM_ENTRY];
@@ -177,16 +177,16 @@ struct iwl_context_info {
struct iwl_context_info_early_dbg_cfg edbg_cfg;
struct iwl_context_info_pnvm_cfg pnvm_cfg;
__le32 reserved2[16];
- struct iwl_context_info_dram dram;
+ struct iwl_context_info_dram_nonfseq dram;
__le32 reserved3[16];
-} __packed;
+} __packed; /* BOOT_LOADER_CONTEXT_INFO_S */
-int iwl_pcie_ctxt_info_init(struct iwl_trans *trans, const struct fw_img *fw);
+int iwl_pcie_ctxt_info_init(struct iwl_trans *trans, const struct fw_img *img);
void iwl_pcie_ctxt_info_free(struct iwl_trans *trans);
void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans);
int iwl_pcie_init_fw_sec(struct iwl_trans *trans,
const struct fw_img *fw,
- struct iwl_context_info_dram *ctxt_dram);
+ struct iwl_context_info_dram_nonfseq *ctxt_dram);
void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans,
size_t size,
dma_addr_t *phys);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/utils.c b/drivers/net/wireless/intel/iwlwifi/pcie/utils.c
new file mode 100644
index 000000000000..1bb274d8390c
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/utils.c
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2025 Intel Corporation
+ */
+
+#include <linux/pci.h>
+#include <linux/gfp.h>
+
+#include "iwl-io.h"
+#include "pcie/utils.h"
+
+void iwl_trans_pcie_dump_regs(struct iwl_trans *trans, struct pci_dev *pdev)
+{
+#define PCI_DUMP_SIZE 352
+#define PCI_MEM_DUMP_SIZE 64
+#define PCI_PARENT_DUMP_SIZE 524
+#define PREFIX_LEN 32
+
+ static bool pcie_dbg_dumped_once = 0;
+ u32 i, pos, alloc_size, *ptr, *buf;
+ char *prefix;
+
+ if (pcie_dbg_dumped_once)
+ return;
+
+ /* Should be a multiple of 4 */
+ BUILD_BUG_ON(PCI_DUMP_SIZE > 4096 || PCI_DUMP_SIZE & 0x3);
+ BUILD_BUG_ON(PCI_MEM_DUMP_SIZE > 4096 || PCI_MEM_DUMP_SIZE & 0x3);
+ BUILD_BUG_ON(PCI_PARENT_DUMP_SIZE > 4096 || PCI_PARENT_DUMP_SIZE & 0x3);
+
+ /* Alloc a max size buffer */
+ alloc_size = PCI_ERR_ROOT_ERR_SRC + 4 + PREFIX_LEN;
+ alloc_size = max_t(u32, alloc_size, PCI_DUMP_SIZE + PREFIX_LEN);
+ alloc_size = max_t(u32, alloc_size, PCI_MEM_DUMP_SIZE + PREFIX_LEN);
+ alloc_size = max_t(u32, alloc_size, PCI_PARENT_DUMP_SIZE + PREFIX_LEN);
+
+ buf = kmalloc(alloc_size, GFP_ATOMIC);
+ if (!buf)
+ return;
+ prefix = (char *)buf + alloc_size - PREFIX_LEN;
+
+ IWL_ERR(trans, "iwlwifi transaction failed, dumping registers\n");
+
+ /* Print wifi device registers */
+ sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));
+ IWL_ERR(trans, "iwlwifi device config registers:\n");
+ for (i = 0, ptr = buf; i < PCI_DUMP_SIZE; i += 4, ptr++)
+ if (pci_read_config_dword(pdev, i, ptr))
+ goto err_read;
+ print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
+
+ IWL_ERR(trans, "iwlwifi device memory mapped registers:\n");
+ for (i = 0, ptr = buf; i < PCI_MEM_DUMP_SIZE; i += 4, ptr++)
+ *ptr = iwl_read32(trans, i);
+ print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
+
+ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
+ if (pos) {
+ IWL_ERR(trans, "iwlwifi device AER capability structure:\n");
+ for (i = 0, ptr = buf; i < PCI_ERR_ROOT_COMMAND; i += 4, ptr++)
+ if (pci_read_config_dword(pdev, pos + i, ptr))
+ goto err_read;
+ print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET,
+ 32, 4, buf, i, 0);
+ }
+
+ /* Print parent device registers next */
+ if (!pdev->bus->self)
+ goto out;
+
+ pdev = pdev->bus->self;
+ sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));
+
+ IWL_ERR(trans, "iwlwifi parent port (%s) config registers:\n",
+ pci_name(pdev));
+ for (i = 0, ptr = buf; i < PCI_PARENT_DUMP_SIZE; i += 4, ptr++)
+ if (pci_read_config_dword(pdev, i, ptr))
+ goto err_read;
+ print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
+
+ /* Print root port AER registers */
+ pos = 0;
+ pdev = pcie_find_root_port(pdev);
+ if (pdev)
+ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
+ if (pos) {
+ IWL_ERR(trans, "iwlwifi root port (%s) AER cap structure:\n",
+ pci_name(pdev));
+ sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));
+ for (i = 0, ptr = buf; i <= PCI_ERR_ROOT_ERR_SRC; i += 4, ptr++)
+ if (pci_read_config_dword(pdev, pos + i, ptr))
+ goto err_read;
+ print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32,
+ 4, buf, i, 0);
+ }
+ goto out;
+
+err_read:
+ print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
+ IWL_ERR(trans, "Read failed at 0x%X\n", i);
+out:
+ pcie_dbg_dumped_once = 1;
+ kfree(buf);
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/utils.h b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h
new file mode 100644
index 000000000000..27437d5e099b
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2025 Intel Corporation
+ */
+
+#ifndef __iwl_pcie_utils_h__
+#define __iwl_pcie_utils_h__
+
+#include "iwl-io.h"
+
+void iwl_trans_pcie_dump_regs(struct iwl_trans *trans, struct pci_dev *pdev);
+
+static inline void _iwl_trans_set_bits_mask(struct iwl_trans *trans,
+ u32 reg, u32 mask, u32 value)
+{
+ u32 v;
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+ WARN_ON_ONCE(value & ~mask);
+#endif
+
+ v = iwl_read32(trans, reg);
+ v &= ~mask;
+ v |= value;
+ iwl_write32(trans, reg, v);
+}
+
+static inline void iwl_trans_clear_bit(struct iwl_trans *trans,
+ u32 reg, u32 mask)
+{
+ _iwl_trans_set_bits_mask(trans, reg, mask, 0);
+}
+
+static inline void iwl_trans_set_bit(struct iwl_trans *trans,
+ u32 reg, u32 mask)
+{
+ _iwl_trans_set_bits_mask(trans, reg, mask, mask);
+}
+
+#endif /* __iwl_pcie_utils_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/tests/Makefile b/drivers/net/wireless/intel/iwlwifi/tests/Makefile
index 84491488f589..b996c45d43e7 100644
--- a/drivers/net/wireless/intel/iwlwifi/tests/Makefile
+++ b/drivers/net/wireless/intel/iwlwifi/tests/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
-iwlwifi-tests-y += module.o devinfo.o
+iwlwifi-tests-y += module.o devinfo.o utils.o nvm_parse.o
ccflags-y += -I$(src)/../
diff --git a/drivers/net/wireless/intel/iwlwifi/tests/devinfo.c b/drivers/net/wireless/intel/iwlwifi/tests/devinfo.c
index d0bda23c628a..6bf2ad18b009 100644
--- a/drivers/net/wireless/intel/iwlwifi/tests/devinfo.c
+++ b/drivers/net/wireless/intel/iwlwifi/tests/devinfo.c
@@ -2,7 +2,7 @@
/*
* KUnit tests for the iwlwifi device info table
*
- * Copyright (C) 2023-2024 Intel Corporation
+ * Copyright (C) 2023-2025 Intel Corporation
*/
#include <kunit/test.h>
#include <linux/pci.h>
@@ -13,10 +13,48 @@ MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
static void iwl_pci_print_dev_info(const char *pfx, const struct iwl_dev_info *di)
{
- printk(KERN_DEBUG "%sdev=%.4x,subdev=%.4x,mac_type=%.4x,mac_step=%.4x,rf_type=%.4x,cdb=%d,jacket=%d,rf_id=%.2x,no_160=%d,cores=%.2x\n",
- pfx, di->device, di->subdevice, di->mac_type, di->mac_step,
- di->rf_type, di->cdb, di->jacket, di->rf_id, di->no_160,
- di->cores);
+ u16 subdevice_mask = GENMASK(di->subdevice_m_h, di->subdevice_m_l);
+ char buf[100] = {};
+ int pos = 0;
+
+ if (di->match_rf_type)
+ pos += scnprintf(buf + pos, sizeof(buf) - pos,
+ " rf_type=%03x", di->rf_type);
+ else
+ pos += scnprintf(buf + pos, sizeof(buf) - pos,
+ " rf_type=*");
+
+ if (di->match_bw_limit)
+ pos += scnprintf(buf + pos, sizeof(buf) - pos,
+ " bw_limit=%d", di->bw_limit);
+ else
+ pos += scnprintf(buf + pos, sizeof(buf) - pos,
+ " bw_limit=*");
+
+ if (di->match_rf_id)
+ pos += scnprintf(buf + pos, sizeof(buf) - pos,
+ " rf_id=0x%x", di->rf_id);
+ else
+ pos += scnprintf(buf + pos, sizeof(buf) - pos,
+ " rf_id=*");
+
+ if (di->match_cdb)
+ pos += scnprintf(buf + pos, sizeof(buf) - pos,
+ " cdb=%d", di->cdb);
+ else
+ pos += scnprintf(buf + pos, sizeof(buf) - pos,
+ " cdb=*");
+
+ if (di->match_discrete)
+ pos += scnprintf(buf + pos, sizeof(buf) - pos,
+ " discrete=%d",
+ di->discrete);
+ else
+ pos += scnprintf(buf + pos, sizeof(buf) - pos,
+ " discrete=*");
+
+ printk(KERN_DEBUG "%sdev=%04x subdev=%04x/%04x%s\n",
+ pfx, di->device, di->subdevice, subdevice_mask, buf);
}
static void devinfo_table_order(struct kunit *test)
@@ -28,11 +66,14 @@ static void devinfo_table_order(struct kunit *test)
const struct iwl_dev_info *ret;
ret = iwl_pci_find_dev_info(di->device, di->subdevice,
- di->mac_type, di->mac_step,
di->rf_type, di->cdb,
- di->jacket, di->rf_id,
- di->no_160, di->cores, di->rf_step);
- if (ret != di) {
+ di->rf_id, di->bw_limit,
+ di->discrete);
+ if (!ret) {
+ iwl_pci_print_dev_info("No entry found for: ", di);
+ KUNIT_FAIL(test,
+ "No entry found for entry at index %d\n", idx);
+ } else if (ret != di) {
iwl_pci_print_dev_info("searched: ", di);
iwl_pci_print_dev_info("found: ", ret);
KUNIT_FAIL(test,
@@ -42,6 +83,118 @@ static void devinfo_table_order(struct kunit *test)
}
}
+static void devinfo_discrete_match(struct kunit *test)
+{
+ /*
+ * Validate that any entries with discrete/integrated match have
+ * the same config with the value inverted (if they match at all.)
+ */
+
+ for (int idx = 0; idx < iwl_dev_info_table_size; idx++) {
+ const struct iwl_dev_info *di = &iwl_dev_info_table[idx];
+ const struct iwl_dev_info *ret;
+
+ if (!di->match_discrete)
+ continue;
+
+ ret = iwl_pci_find_dev_info(di->device, di->subdevice,
+ di->rf_type, di->cdb,
+ di->rf_id, di->bw_limit,
+ !di->discrete);
+ if (!ret)
+ continue;
+ KUNIT_EXPECT_PTR_EQ(test, di->cfg, ret->cfg);
+ /* and check the name is different, that'd be the point of it */
+ KUNIT_EXPECT_NE(test, strcmp(di->name, ret->name), 0);
+ }
+}
+
+static void devinfo_names(struct kunit *test)
+{
+ int idx;
+
+ for (idx = 0; idx < iwl_dev_info_table_size; idx++) {
+ const struct iwl_dev_info *di = &iwl_dev_info_table[idx];
+
+ KUNIT_ASSERT_TRUE(test, di->name);
+ }
+}
+
+static void devinfo_no_cfg_dups(struct kunit *test)
+{
+ for (int i = 0; i < iwl_dev_info_table_size; i++) {
+ const struct iwl_rf_cfg *cfg_i = iwl_dev_info_table[i].cfg;
+
+ for (int j = 0; j < i; j++) {
+ const struct iwl_rf_cfg *cfg_j = iwl_dev_info_table[j].cfg;
+
+ if (cfg_i == cfg_j)
+ continue;
+
+ KUNIT_EXPECT_NE_MSG(test, memcmp(cfg_i, cfg_j,
+ sizeof(*cfg_i)), 0,
+ "identical configs: %ps and %ps\n",
+ cfg_i, cfg_j);
+ }
+ }
+}
+
+static void devinfo_no_name_dups(struct kunit *test)
+{
+ for (int i = 0; i < iwl_dev_info_table_size; i++) {
+ for (int j = 0; j < i; j++) {
+ if (iwl_dev_info_table[i].name == iwl_dev_info_table[j].name)
+ continue;
+
+ KUNIT_EXPECT_NE_MSG(test,
+ strcmp(iwl_dev_info_table[i].name,
+ iwl_dev_info_table[j].name),
+ 0,
+ "name dup: %ps/%ps",
+ iwl_dev_info_table[i].name,
+ iwl_dev_info_table[j].name);
+ }
+ }
+}
+
+static void devinfo_check_subdev_match(struct kunit *test)
+{
+ for (int i = 0; i < iwl_dev_info_table_size; i++) {
+ const struct iwl_dev_info *di = &iwl_dev_info_table[i];
+ u16 subdevice_mask = GENMASK(di->subdevice_m_h,
+ di->subdevice_m_l);
+
+ /* if BW limit bit is matched then must have a limit */
+ if (di->match_bw_limit == 1 && di->bw_limit == 1)
+ KUNIT_EXPECT_NE(test, di->cfg->bw_limit, 0);
+
+ /* if subdevice is ANY we can have RF ID/BW limit */
+ if (di->subdevice == (u16)IWL_CFG_ANY)
+ continue;
+
+ /* same if the subdevice mask doesn't overlap them */
+ if (IWL_SUBDEVICE_RF_ID(subdevice_mask) == 0 &&
+ IWL_SUBDEVICE_BW_LIM(subdevice_mask) == 0)
+ continue;
+
+ /* but otherwise they shouldn't be used */
+ KUNIT_EXPECT_EQ(test, (int)di->match_rf_id, 0);
+ KUNIT_EXPECT_EQ(test, (int)di->match_bw_limit, 0);
+ }
+}
+
+static void devinfo_check_killer_subdev(struct kunit *test)
+{
+ for (int i = 0; i < iwl_dev_info_table_size; i++) {
+ const struct iwl_dev_info *di = &iwl_dev_info_table[i];
+
+ if (!strstr(di->name, "Killer"))
+ continue;
+
+ KUNIT_EXPECT_NE(test, di->subdevice, (u16)IWL_CFG_ANY);
+ }
+}
+
static void devinfo_pci_ids(struct kunit *test)
{
struct pci_dev *dev;
@@ -64,9 +217,94 @@ static void devinfo_pci_ids(struct kunit *test)
}
}
+static void devinfo_no_mac_cfg_dups(struct kunit *test)
+{
+ for (int i = 0; iwl_hw_card_ids[i].vendor; i++) {
+ const struct iwl_mac_cfg *cfg_i =
+ (void *)iwl_hw_card_ids[i].driver_data;
+
+ for (int j = 0; j < i; j++) {
+ const struct iwl_mac_cfg *cfg_j =
+ (void *)iwl_hw_card_ids[j].driver_data;
+
+ if (cfg_i == cfg_j)
+ continue;
+
+ KUNIT_EXPECT_NE_MSG(test, memcmp(cfg_j, cfg_i,
+ sizeof(*cfg_i)), 0,
+ "identical configs: %ps and %ps\n",
+ cfg_i, cfg_j);
+ }
+ }
+}
+
+static void devinfo_api_range(struct kunit *test)
+{
+ /* Check that all iwl_mac_cfg's have either both min and max set, or neither */
+ for (int i = 0; iwl_hw_card_ids[i].vendor; i++) {
+ const struct iwl_mac_cfg *mac_cfg =
+ (void *)iwl_hw_card_ids[i].driver_data;
+ const struct iwl_family_base_params *base = mac_cfg->base;
+
+ KUNIT_EXPECT_EQ_MSG(test, !!base->ucode_api_min,
+ !!base->ucode_api_max,
+ "%ps: ucode_api_min (%u) and ucode_api_min (%u) should be both set or neither.\n",
+ base, base->ucode_api_min,
+ base->ucode_api_max);
+ }
+
+ /* Check the same for the iwl_rf_cfg's */
+ for (int i = 0; i < iwl_dev_info_table_size; i++) {
+ const struct iwl_rf_cfg *rf_cfg = iwl_dev_info_table[i].cfg;
+
+ KUNIT_EXPECT_EQ_MSG(test, !!rf_cfg->ucode_api_min,
+ !!rf_cfg->ucode_api_max,
+ "%ps: ucode_api_min (%u) and ucode_api_min (%u) should be both set or neither.\n",
+ rf_cfg, rf_cfg->ucode_api_min,
+ rf_cfg->ucode_api_max);
+ }
+}
+
+static void devinfo_pci_ids_config(struct kunit *test)
+{
+ for (int i = 0; iwl_hw_card_ids[i].vendor; i++) {
+ const struct pci_device_id *s = &iwl_hw_card_ids[i];
+ const struct iwl_dev_info *di;
+
+ if (s->device == PCI_ANY_ID || s->subdevice == PCI_ANY_ID)
+ continue;
+
+#if IS_ENABLED(CONFIG_IWLMVM) || IS_ENABLED(CONFIG_IWLMLD)
+ /*
+ * The check below only works for old (pre-CNVI) devices. Most
+ * new have subdevice==ANY, so are already skipped, but for some
+ * Bz platform(s) we list all the RF PCI IDs. Skip those too.
+ */
+ if (s->driver_data == (kernel_ulong_t)&iwl_bz_mac_cfg)
+ continue;
+#endif
+
+ di = iwl_pci_find_dev_info(s->device, s->subdevice,
+ 0, 0, 0, 0, true);
+
+ KUNIT_EXPECT_PTR_NE_MSG(test, di, NULL,
+ "PCI ID %04x:%04x not found\n",
+ s->device, s->subdevice);
+ }
+}
+
static struct kunit_case devinfo_test_cases[] = {
KUNIT_CASE(devinfo_table_order),
+ KUNIT_CASE(devinfo_discrete_match),
+ KUNIT_CASE(devinfo_names),
+ KUNIT_CASE(devinfo_no_cfg_dups),
+ KUNIT_CASE(devinfo_no_name_dups),
+ KUNIT_CASE(devinfo_check_subdev_match),
+ KUNIT_CASE(devinfo_check_killer_subdev),
KUNIT_CASE(devinfo_pci_ids),
+ KUNIT_CASE(devinfo_no_mac_cfg_dups),
+ KUNIT_CASE(devinfo_api_range),
+ KUNIT_CASE(devinfo_pci_ids_config),
{}
};
diff --git a/drivers/net/wireless/intel/iwlwifi/tests/nvm_parse.c b/drivers/net/wireless/intel/iwlwifi/tests/nvm_parse.c
new file mode 100644
index 000000000000..853911900bfd
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/tests/nvm_parse.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * KUnit tests for NVM parse
+ *
+ * Copyright (C) 2025 Intel Corporation
+ */
+#include <kunit/static_stub.h>
+#include <kunit/test.h>
+#include <iwl-nvm-parse.h>
+
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
+
+static const struct nvm_flag_case {
+ const char *desc;
+ u16 nvm_flags;
+ u32 reg_rule_flags;
+ u32 set_reg_rule_flags;
+ u32 clear_reg_rule_flags;
+} nvm_flag_cases[] = {
+ {
+ .desc = "Restricting VLP client and AP access",
+ .nvm_flags = 0,
+ .set_reg_rule_flags = NL80211_RRF_NO_6GHZ_VLP_CLIENT,
+ .clear_reg_rule_flags = NL80211_RRF_ALLOW_6GHZ_VLP_AP,
+ },
+ {
+ .desc = "Allow VLP client and AP access",
+ .nvm_flags = NVM_CHANNEL_VLP,
+ .set_reg_rule_flags = NL80211_RRF_ALLOW_6GHZ_VLP_AP,
+ .clear_reg_rule_flags = NL80211_RRF_NO_6GHZ_VLP_CLIENT,
+ },
+ {
+ .desc = "Allow VLP client access, while restricting AP access",
+ .nvm_flags = NVM_CHANNEL_VLP | NVM_CHANNEL_VLP_AP_NOT_ALLOWED,
+ .set_reg_rule_flags = 0,
+ .clear_reg_rule_flags = NL80211_RRF_ALLOW_6GHZ_VLP_AP |
+ NL80211_RRF_NO_6GHZ_VLP_CLIENT,
+ },
+};
+
+KUNIT_ARRAY_PARAM_DESC(nvm_flag, nvm_flag_cases, desc)
+
+static void test_nvm_flags(struct kunit *test)
+{
+ const struct nvm_flag_case *params = test->param_value;
+ struct iwl_reg_capa reg_capa = {};
+ u32 flags = 0;
+
+ flags = iwl_nvm_get_regdom_bw_flags(NULL, 0, params->nvm_flags,
+ reg_capa);
+
+ if ((params->set_reg_rule_flags & flags) != params->set_reg_rule_flags)
+ KUNIT_FAIL(test, "Expected set bits:0x%08x flags:0x%08x\n",
+ params->set_reg_rule_flags, flags);
+
+ if (params->clear_reg_rule_flags & flags)
+ KUNIT_FAIL(test, "Expected clear bits:0x%08x flags:0x%08x\n",
+ params->clear_reg_rule_flags, flags);
+}
+
+static struct kunit_case nvm_flags_test_cases[] = {
+ KUNIT_CASE_PARAM(test_nvm_flags,
+ nvm_flag_gen_params),
+ {},
+};
+
+static struct kunit_suite nvm_flags_suite = {
+ .name = "iwlwifi-nvm_flags",
+ .test_cases = nvm_flags_test_cases,
+};
+
+kunit_test_suite(nvm_flags_suite);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tests/scan.c b/drivers/net/wireless/intel/iwlwifi/tests/utils.c
index 7a3275199ace..df2c3a891e7e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tests/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/tests/utils.c
@@ -1,20 +1,19 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * KUnit tests for channel helper functions
+ * KUnit tests for utilities
*
- * Copyright (C) 2024 Intel Corporation
+ * Copyright (C) 2024-2025 Intel Corporation
*/
-#include <net/mac80211.h>
-#include "../mvm.h"
+#include "../iwl-utils.h"
#include <kunit/test.h>
-MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
+MODULE_IMPORT_NS("IWLWIFI");
-static const struct acs_average_db_case {
+static const struct average_neg_db_case {
const char *desc;
u8 neg_dbm[22];
s8 result;
-} acs_average_db_cases[] = {
+} average_neg_db_cases[] = {
{
.desc = "Smallest possible value, all filled",
.neg_dbm = {
@@ -73,38 +72,38 @@ static const struct acs_average_db_case {
},
};
-KUNIT_ARRAY_PARAM_DESC(acs_average_db, acs_average_db_cases, desc)
+KUNIT_ARRAY_PARAM_DESC(average_neg_db, average_neg_db_cases, desc)
-static void test_acs_average_db(struct kunit *test)
+static void test_average_neg_db(struct kunit *test)
{
- const struct acs_average_db_case *params = test->param_value;
- struct iwl_umac_scan_channel_survey_notif notif;
+ const struct average_neg_db_case *params = test->param_value;
+ u8 reversed[ARRAY_SIZE(params->neg_dbm)];
int i;
/* Test the values in the given order */
- for (i = 0; i < ARRAY_SIZE(params->neg_dbm); i++)
- notif.noise[i] = params->neg_dbm[i];
KUNIT_ASSERT_EQ(test,
- iwl_mvm_average_dbm_values(&notif),
+ iwl_average_neg_dbm(params->neg_dbm,
+ ARRAY_SIZE(params->neg_dbm)),
params->result);
/* Test in reverse order */
for (i = 0; i < ARRAY_SIZE(params->neg_dbm); i++)
- notif.noise[ARRAY_SIZE(params->neg_dbm) - i - 1] =
+ reversed[ARRAY_SIZE(params->neg_dbm) - i - 1] =
params->neg_dbm[i];
KUNIT_ASSERT_EQ(test,
- iwl_mvm_average_dbm_values(&notif),
+ iwl_average_neg_dbm(reversed,
+ ARRAY_SIZE(params->neg_dbm)),
params->result);
}
-static struct kunit_case acs_average_db_case[] = {
- KUNIT_CASE_PARAM(test_acs_average_db, acs_average_db_gen_params),
+static struct kunit_case average_db_case[] = {
+ KUNIT_CASE_PARAM(test_average_neg_db, average_neg_db_gen_params),
{}
};
-static struct kunit_suite acs_average_db = {
- .name = "iwlmvm-acs-average-db",
- .test_cases = acs_average_db_case,
+static struct kunit_suite average_db = {
+ .name = "iwl-average-db",
+ .test_cases = average_db_case,
};
-kunit_test_suite(acs_average_db);
+kunit_test_suite(average_db);