Skip to content

Commit 41901c2

Browse files
committed
Merge tag 'wireless-2024-08-28' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless
Johannes Berg says: ==================== Regressions: * wfx: fix for open network connection * iwlwifi: fix for hibernate (due to fast resume feature) * iwlwifi: fix for a few warnings that were recently added (had previously been messages not warnings) Previously broken: * mwifiex: fix static structures used for per-device data * iwlwifi: some harmless FW related messages were tagged too high priority * iwlwifi: scan buffers weren't checked correctly * mac80211: SKB leak on beacon error path * iwlwifi: fix ACPI table interop with certain BIOSes * iwlwifi: fix locking for link selection * mac80211: fix SSID comparison in beacon validation * tag 'wireless-2024-08-28' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless: wifi: iwlwifi: clear trans->state earlier upon error wifi: wfx: repair open network AP mode wifi: mac80211: free skb on error path in ieee80211_beacon_get_ap() wifi: iwlwifi: mvm: don't wait for tx queues if firmware is dead wifi: iwlwifi: mvm: allow 6 GHz channels in MLO scan wifi: iwlwifi: mvm: pause TCM when the firmware is stopped wifi: iwlwifi: fw: fix wgds rev 3 exact size wifi: iwlwifi: mvm: take the mutex before running link selection wifi: iwlwifi: mvm: fix iwl_mvm_max_scan_ie_fw_cmd_room() wifi: iwlwifi: mvm: fix iwl_mvm_scan_fits() calculation wifi: iwlwifi: lower message level for FW buffer destination wifi: iwlwifi: mvm: fix hibernation wifi: mac80211: fix beacon SSID mismatch handling wifi: mwifiex: duplicate static structs used in driver instances ==================== Link: https://patch.msgid.link/20240828100151.23662-3-johannes@sipsolutions.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 3a0504d + 094513f commit 41901c2

14 files changed

Lines changed: 161 additions & 37 deletions

File tree

drivers/net/wireless/intel/iwlwifi/fw/acpi.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -725,22 +725,25 @@ int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt)
725725
entry = &wifi_pkg->package.elements[entry_idx];
726726
entry_idx++;
727727
if (entry->type != ACPI_TYPE_INTEGER ||
728-
entry->integer.value > num_profiles) {
728+
entry->integer.value > num_profiles ||
729+
entry->integer.value <
730+
rev_data[idx].min_profiles) {
729731
ret = -EINVAL;
730732
goto out_free;
731733
}
732-
num_profiles = entry->integer.value;
733734

734735
/*
735-
* this also validates >= min_profiles since we
736-
* otherwise wouldn't have gotten the data when
737-
* looking up in ACPI
736+
* Check to see if we received package count
737+
* same as max # of profiles
738738
*/
739739
if (wifi_pkg->package.count !=
740740
hdr_size + profile_size * num_profiles) {
741741
ret = -EINVAL;
742742
goto out_free;
743743
}
744+
745+
/* Number of valid profiles */
746+
num_profiles = entry->integer.value;
744747
}
745748
goto read_table;
746749
}

drivers/net/wireless/intel/iwlwifi/fw/dbg.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3348,7 +3348,7 @@ void iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
33483348
{
33493349
int ret __maybe_unused = 0;
33503350

3351-
if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status))
3351+
if (!iwl_trans_fw_running(fwrt->trans))
33523352
return;
33533353

33543354
if (fw_has_capa(&fwrt->fw->ucode_capa,

drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ struct iwl_cfg;
8585
* May sleep
8686
* @wimax_active: invoked when WiMax becomes active. May sleep
8787
* @time_point: called when transport layer wants to collect debug data
88+
* @device_powered_off: called upon resume from hibernation but not only.
89+
* Op_mode needs to reset its internal state because the device did not
90+
* survive the system state transition. The firmware is no longer running,
91+
* etc...
8892
*/
8993
struct iwl_op_mode_ops {
9094
struct iwl_op_mode *(*start)(struct iwl_trans *trans,
@@ -107,6 +111,7 @@ struct iwl_op_mode_ops {
107111
void (*time_point)(struct iwl_op_mode *op_mode,
108112
enum iwl_fw_ini_time_point tp_id,
109113
union iwl_dbg_tlv_tp_data *tp_data);
114+
void (*device_powered_off)(struct iwl_op_mode *op_mode);
110115
};
111116

112117
int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops);
@@ -204,4 +209,11 @@ static inline void iwl_op_mode_time_point(struct iwl_op_mode *op_mode,
204209
op_mode->ops->time_point(op_mode, tp_id, tp_data);
205210
}
206211

212+
static inline void iwl_op_mode_device_powered_off(struct iwl_op_mode *op_mode)
213+
{
214+
if (!op_mode || !op_mode->ops || !op_mode->ops->device_powered_off)
215+
return;
216+
op_mode->ops->device_powered_off(op_mode);
217+
}
218+
207219
#endif /* __iwl_op_mode_h__ */

drivers/net/wireless/intel/iwlwifi/iwl-trans.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1128,8 +1128,8 @@ static inline void iwl_trans_fw_error(struct iwl_trans *trans, bool sync)
11281128

11291129
/* prevent double restarts due to the same erroneous FW */
11301130
if (!test_and_set_bit(STATUS_FW_ERROR, &trans->status)) {
1131-
iwl_op_mode_nic_error(trans->op_mode, sync);
11321131
trans->state = IWL_TRANS_NO_FW;
1132+
iwl_op_mode_nic_error(trans->op_mode, sync);
11331133
}
11341134
}
11351135

drivers/net/wireless/intel/iwlwifi/mvm/d3.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3439,6 +3439,16 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
34393439

34403440
mutex_lock(&mvm->mutex);
34413441

3442+
/* Apparently, the device went away and device_powered_off() was called,
3443+
* don't even try to read the rt_status, the device is currently
3444+
* inaccessible.
3445+
*/
3446+
if (!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) {
3447+
IWL_INFO(mvm,
3448+
"Can't resume, device_powered_off() was called during wowlan\n");
3449+
goto err;
3450+
}
3451+
34423452
mvm->last_reset_or_resume_time_jiffies = jiffies;
34433453

34443454
/* get the BSS vif pointer again */

drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5818,6 +5818,10 @@ static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop)
58185818
int i;
58195819

58205820
if (!iwl_mvm_has_new_tx_api(mvm)) {
5821+
/* we can't ask the firmware anything if it is dead */
5822+
if (test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
5823+
&mvm->status))
5824+
return;
58215825
if (drop) {
58225826
guard(mvm)(mvm);
58235827
iwl_mvm_flush_tx_path(mvm,
@@ -5911,8 +5915,11 @@ void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
59115915

59125916
/* this can take a while, and we may need/want other operations
59135917
* to succeed while doing this, so do it without the mutex held
5918+
* If the firmware is dead, this can't work...
59145919
*/
5915-
if (!drop && !iwl_mvm_has_new_tx_api(mvm))
5920+
if (!drop && !iwl_mvm_has_new_tx_api(mvm) &&
5921+
!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
5922+
&mvm->status))
59165923
iwl_trans_wait_tx_queues_empty(mvm->trans, msk);
59175924
}
59185925

drivers/net/wireless/intel/iwlwifi/mvm/ops.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1198,10 +1198,12 @@ static void iwl_mvm_trig_link_selection(struct wiphy *wiphy,
11981198
struct iwl_mvm *mvm =
11991199
container_of(wk, struct iwl_mvm, trig_link_selection_wk);
12001200

1201+
mutex_lock(&mvm->mutex);
12011202
ieee80211_iterate_active_interfaces(mvm->hw,
12021203
IEEE80211_IFACE_ITER_NORMAL,
12031204
iwl_mvm_find_link_selection_vif,
12041205
NULL);
1206+
mutex_unlock(&mvm->mutex);
12051207
}
12061208

12071209
static struct iwl_op_mode *
@@ -1511,6 +1513,8 @@ void iwl_mvm_stop_device(struct iwl_mvm *mvm)
15111513

15121514
clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
15131515

1516+
iwl_mvm_pause_tcm(mvm, false);
1517+
15141518
iwl_fw_dbg_stop_sync(&mvm->fwrt);
15151519
iwl_trans_stop_device(mvm->trans);
15161520
iwl_free_fw_paging(&mvm->fwrt);
@@ -2090,6 +2094,20 @@ static void iwl_op_mode_mvm_time_point(struct iwl_op_mode *op_mode,
20902094
iwl_dbg_tlv_time_point(&mvm->fwrt, tp_id, tp_data);
20912095
}
20922096

2097+
static void iwl_op_mode_mvm_device_powered_off(struct iwl_op_mode *op_mode)
2098+
{
2099+
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
2100+
2101+
mutex_lock(&mvm->mutex);
2102+
clear_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);
2103+
mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
2104+
iwl_mvm_stop_device(mvm);
2105+
#ifdef CONFIG_PM
2106+
mvm->fast_resume = false;
2107+
#endif
2108+
mutex_unlock(&mvm->mutex);
2109+
}
2110+
20932111
#define IWL_MVM_COMMON_OPS \
20942112
/* these could be differentiated */ \
20952113
.queue_full = iwl_mvm_stop_sw_queue, \
@@ -2102,7 +2120,8 @@ static void iwl_op_mode_mvm_time_point(struct iwl_op_mode *op_mode,
21022120
/* as we only register one, these MUST be common! */ \
21032121
.start = iwl_op_mode_mvm_start, \
21042122
.stop = iwl_op_mode_mvm_stop, \
2105-
.time_point = iwl_op_mode_mvm_time_point
2123+
.time_point = iwl_op_mode_mvm_time_point, \
2124+
.device_powered_off = iwl_op_mode_mvm_device_powered_off
21062125

21072126
static const struct iwl_op_mode_ops iwl_mvm_ops = {
21082127
IWL_MVM_COMMON_OPS,

drivers/net/wireless/intel/iwlwifi/mvm/scan.c

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
/* Number of iterations on the channel for mei filtered scan */
4949
#define IWL_MEI_SCAN_NUM_ITER 5U
5050

51+
#define WFA_TPC_IE_LEN 9
52+
5153
struct iwl_mvm_scan_timing_params {
5254
u32 suspend_time;
5355
u32 max_out_time;
@@ -303,8 +305,8 @@ static int iwl_mvm_max_scan_ie_fw_cmd_room(struct iwl_mvm *mvm)
303305

304306
max_probe_len = SCAN_OFFLOAD_PROBE_REQ_SIZE;
305307

306-
/* we create the 802.11 header and SSID element */
307-
max_probe_len -= 24 + 2;
308+
/* we create the 802.11 header SSID element and WFA TPC element */
309+
max_probe_len -= 24 + 2 + WFA_TPC_IE_LEN;
308310

309311
/* DS parameter set element is added on 2.4GHZ band if required */
310312
if (iwl_mvm_rrm_scan_needed(mvm))
@@ -731,8 +733,6 @@ static u8 *iwl_mvm_copy_and_insert_ds_elem(struct iwl_mvm *mvm, const u8 *ies,
731733
return newpos;
732734
}
733735

734-
#define WFA_TPC_IE_LEN 9
735-
736736
static void iwl_mvm_add_tpc_report_ie(u8 *pos)
737737
{
738738
pos[0] = WLAN_EID_VENDOR_SPECIFIC;
@@ -837,8 +837,8 @@ static inline bool iwl_mvm_scan_fits(struct iwl_mvm *mvm, int n_ssids,
837837
return ((n_ssids <= PROBE_OPTION_MAX) &&
838838
(n_channels <= mvm->fw->ucode_capa.n_scan_channels) &
839839
(ies->common_ie_len +
840-
ies->len[NL80211_BAND_2GHZ] +
841-
ies->len[NL80211_BAND_5GHZ] <=
840+
ies->len[NL80211_BAND_2GHZ] + ies->len[NL80211_BAND_5GHZ] +
841+
ies->len[NL80211_BAND_6GHZ] <=
842842
iwl_mvm_max_scan_ie_fw_cmd_room(mvm)));
843843
}
844844

@@ -1659,6 +1659,17 @@ iwl_mvm_umac_scan_cfg_channels_v7(struct iwl_mvm *mvm,
16591659
cfg->v2.channel_num = channels[i]->hw_value;
16601660
if (cfg80211_channel_is_psc(channels[i]))
16611661
cfg->flags = 0;
1662+
1663+
if (band == NL80211_BAND_6GHZ) {
1664+
/* 6 GHz channels should only appear in a scan request
1665+
* that has scan_6ghz set. The only exception is MLO
1666+
* scan, which has to be passive.
1667+
*/
1668+
WARN_ON_ONCE(cfg->flags != 0);
1669+
cfg->flags =
1670+
cpu_to_le32(IWL_UHB_CHAN_CFG_FLAG_FORCE_PASSIVE);
1671+
}
1672+
16621673
cfg->v2.iter_count = 1;
16631674
cfg->v2.iter_interval = 0;
16641675
if (version < 17)
@@ -3168,18 +3179,16 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
31683179
params.n_channels = j;
31693180
}
31703181

3171-
if (non_psc_included &&
3172-
!iwl_mvm_scan_fits(mvm, req->n_ssids, ies, params.n_channels)) {
3173-
kfree(params.channels);
3174-
return -ENOBUFS;
3182+
if (!iwl_mvm_scan_fits(mvm, req->n_ssids, ies, params.n_channels)) {
3183+
ret = -ENOBUFS;
3184+
goto out;
31753185
}
31763186

31773187
uid = iwl_mvm_build_scan_cmd(mvm, vif, &hcmd, &params, type);
3178-
3179-
if (non_psc_included)
3180-
kfree(params.channels);
3181-
if (uid < 0)
3182-
return uid;
3188+
if (uid < 0) {
3189+
ret = uid;
3190+
goto out;
3191+
}
31833192

31843193
ret = iwl_mvm_send_cmd(mvm, &hcmd);
31853194
if (!ret) {
@@ -3197,6 +3206,9 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
31973206
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
31983207
}
31993208

3209+
out:
3210+
if (non_psc_included)
3211+
kfree(params.channels);
32003212
return ret;
32013213
}
32023214

drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ iwl_pcie_ctxt_info_dbg_enable(struct iwl_trans *trans,
8989
}
9090
break;
9191
default:
92-
IWL_ERR(trans, "WRT: Invalid buffer destination\n");
92+
IWL_DEBUG_FW(trans, "WRT: Invalid buffer destination (%d)\n",
93+
le32_to_cpu(fw_mon_cfg->buf_location));
9394
}
9495
out:
9596
if (dbg_flags)

drivers/net/wireless/intel/iwlwifi/pcie/drv.c

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1577,11 +1577,12 @@ static int iwl_pci_suspend(struct device *device)
15771577
return 0;
15781578
}
15791579

1580-
static int iwl_pci_resume(struct device *device)
1580+
static int _iwl_pci_resume(struct device *device, bool restore)
15811581
{
15821582
struct pci_dev *pdev = to_pci_dev(device);
15831583
struct iwl_trans *trans = pci_get_drvdata(pdev);
15841584
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
1585+
bool device_was_powered_off = false;
15851586

15861587
/* Before you put code here, think about WoWLAN. You cannot check here
15871588
* whether WoWLAN is enabled or not, and your code will run even if
@@ -1597,6 +1598,26 @@ static int iwl_pci_resume(struct device *device)
15971598
if (!trans->op_mode)
15981599
return 0;
15991600

1601+
/*
1602+
* Scratch value was altered, this means the device was powered off, we
1603+
* need to reset it completely.
1604+
* Note: MAC (bits 0:7) will be cleared upon suspend even with wowlan,
1605+
* so assume that any bits there mean that the device is usable.
1606+
*/
1607+
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ &&
1608+
!iwl_read32(trans, CSR_FUNC_SCRATCH))
1609+
device_was_powered_off = true;
1610+
1611+
if (restore || device_was_powered_off) {
1612+
trans->state = IWL_TRANS_NO_FW;
1613+
/* Hope for the best here ... If one of those steps fails we
1614+
* won't really know how to recover.
1615+
*/
1616+
iwl_pcie_prepare_card_hw(trans);
1617+
iwl_finish_nic_init(trans);
1618+
iwl_op_mode_device_powered_off(trans->op_mode);
1619+
}
1620+
16001621
/* In WOWLAN, let iwl_trans_pcie_d3_resume do the rest of the work */
16011622
if (test_bit(STATUS_DEVICE_ENABLED, &trans->status))
16021623
return 0;
@@ -1617,9 +1638,23 @@ static int iwl_pci_resume(struct device *device)
16171638
return 0;
16181639
}
16191640

1641+
static int iwl_pci_restore(struct device *device)
1642+
{
1643+
return _iwl_pci_resume(device, true);
1644+
}
1645+
1646+
static int iwl_pci_resume(struct device *device)
1647+
{
1648+
return _iwl_pci_resume(device, false);
1649+
}
1650+
16201651
static const struct dev_pm_ops iwl_dev_pm_ops = {
1621-
SET_SYSTEM_SLEEP_PM_OPS(iwl_pci_suspend,
1622-
iwl_pci_resume)
1652+
.suspend = pm_sleep_ptr(iwl_pci_suspend),
1653+
.resume = pm_sleep_ptr(iwl_pci_resume),
1654+
.freeze = pm_sleep_ptr(iwl_pci_suspend),
1655+
.thaw = pm_sleep_ptr(iwl_pci_resume),
1656+
.poweroff = pm_sleep_ptr(iwl_pci_suspend),
1657+
.restore = pm_sleep_ptr(iwl_pci_restore),
16231658
};
16241659

16251660
#define IWL_PM_OPS (&iwl_dev_pm_ops)

0 commit comments

Comments
 (0)