diff options
| author | Johannes Berg <johannes.berg@intel.com> | 2026-05-10 23:48:31 +0300 |
|---|---|---|
| committer | Miri Korenblit <miriam.rachel.korenblit@intel.com> | 2026-05-26 15:17:09 +0300 |
| commit | cfc84d1710f331e47e09f337b07e0207a5ae9a14 (patch) | |
| tree | c794db55e5ec027f59ead38f2843c5e42b9058e8 /drivers | |
| parent | ef9d9c1c1609c425d78bba8457fc710e0f66eedd (diff) | |
wifi: iwlwifi: add NAN schedule command support
Add the NAN schedule command API definition and implementation
of the schedule updates.
Co-developed-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20260510234534.95fabd44a598.I7cbe877f3b13a44554d95e56b10d930dde4704c9@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h | 24 | ||||
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mld/mld.c | 3 | ||||
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mld/nan.c | 58 |
3 files changed, 78 insertions, 7 deletions
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 b398c582b867..d98c6d991a88 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h @@ -8,6 +8,7 @@ #define __iwl_fw_api_mac_cfg_h__ #include "mac.h" +#include "phy-ctxt.h" /** * enum iwl_mac_conf_subcmd_ids - mac configuration command IDs @@ -72,6 +73,10 @@ enum iwl_mac_conf_subcmd_ids { */ NAN_CFG_CMD = 0x12, /** + * @NAN_SCHEDULE_CMD: &struct iwl_nan_schedule_cmd + */ + NAN_SCHEDULE_CMD = 0x13, + /** * @NAN_DW_END_NOTIF: &struct iwl_nan_dw_end_notif */ NAN_DW_END_NOTIF = 0xf4, @@ -1245,6 +1250,25 @@ struct iwl_nan_config_cmd { } __packed; /* NAN_CONFIG_CMD_API_S_VER_1 */ /** + * struct iwl_nan_schedule_cmd - NAN schedule command + * @channels: per channel information + * @channels.availability_map: bitmap of slots this channel is advertising + * availability on, will be ULW'ed out if no link/inactive link is + * referenced by the link ID below + * @channels.channel_entry: NAN channel entry descriptor + * @channels.link_id: FW link ID, or %0xFF for unset + * @channels.reserved: (reserved) + */ +struct iwl_nan_schedule_cmd { + struct { + __le32 availability_map; + u8 channel_entry[6]; + u8 link_id; + u8 reserved; + } __packed channels[NUM_PHY_CTX]; +} __packed; /* NAN_SCHEDULE_CMD_API_S_VER_1 */ + +/** * enum iwl_nan_cluster_notif_flags - flags for the cluster notification * * @IWL_NAN_CLUSTER_NOTIF_FLAG_NEW_CLUSTER: indicates that the device has diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.c b/drivers/net/wireless/intel/iwlwifi/mld/mld.c index 9af79297c3b6..c038a0cde36b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mld.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2024-2025 Intel Corporation + * Copyright (C) 2024-2026 Intel Corporation */ #include <linux/rtnetlink.h> #include <net/mac80211.h> @@ -236,6 +236,7 @@ static const struct iwl_hcmd_names iwl_mld_mac_conf_names[] = { HCMD_NAME(STA_REMOVE_CMD), HCMD_NAME(ROC_CMD), HCMD_NAME(NAN_CFG_CMD), + HCMD_NAME(NAN_SCHEDULE_CMD), HCMD_NAME(NAN_DW_END_NOTIF), HCMD_NAME(NAN_JOINED_CLUSTER_NOTIF), HCMD_NAME(MISSED_BEACONS_NOTIF), diff --git a/drivers/net/wireless/intel/iwlwifi/mld/nan.c b/drivers/net/wireless/intel/iwlwifi/mld/nan.c index 6ea11b66a545..eba79aca8c06 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/nan.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/nan.c @@ -401,8 +401,14 @@ iwl_mld_nan_link_add(struct iwl_mld *mld, u8 fw_id; int ret; + lockdep_assert_wiphy(mld->wiphy); + ret = iwl_mld_allocate_link_fw_id(mld, &fw_id, ERR_PTR(-ENODEV)); - if (ret < 0) + /* + * We should always have enough links. The schedule contains up to 3, + * and the BSS vif cannot do EMLSR - so can only have 1. + */ + if (WARN_ON(ret < 0)) return NULL; nan_link = &mld_vif->nan.links[fw_id]; @@ -504,19 +510,21 @@ void iwl_mld_nan_vif_cfg_changed(struct iwl_mld *mld, struct ieee80211_vif *vif, u64 changes) { + struct iwl_nan_schedule_cmd cmd = {}; struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); bool previously_empty_schedule = !iwl_mld_nan_have_links(mld_vif); struct ieee80211_nan_sched_cfg *sched_cfg = &vif->cfg.nan_sched; struct iwl_mld_nan_link *links[ARRAY_SIZE(sched_cfg->channels)] = {}; + struct ieee80211_nan_channel **slots = sched_cfg->schedule; bool link_used[ARRAY_SIZE(mld_vif->nan.links)] = {}; struct iwl_mld_nan_link *nan_link; bool empty_schedule = true; - int ret; + int ret, i; if (!(changes & BSS_CHANGED_NAN_LOCAL_SCHED)) return; - for (int i = 0; i < ARRAY_SIZE(sched_cfg->channels); i++) { + for (i = 0; i < ARRAY_SIZE(sched_cfg->channels); i++) { if (!sched_cfg->channels[i].chanreq.oper.chan) continue; empty_schedule = false; @@ -539,8 +547,12 @@ void iwl_mld_nan_vif_cfg_changed(struct iwl_mld *mld, return; } + /* this currently just uses the same index */ + BUILD_BUG_ON(ARRAY_SIZE(sched_cfg->channels) != + ARRAY_SIZE(cmd.channels)); + /* find links we can keep (same chanctx/PHY) */ - for (int i = 0; i < ARRAY_SIZE(sched_cfg->channels); i++) { + for (i = 0; i < ARRAY_SIZE(sched_cfg->channels); i++) { struct ieee80211_chanctx_conf *chanctx; struct iwl_mld_nan_link *link; @@ -556,7 +568,7 @@ void iwl_mld_nan_vif_cfg_changed(struct iwl_mld *mld, } /* add/reassign links for new channels */ - for (int i = 0; i < ARRAY_SIZE(sched_cfg->channels); i++) { + for (i = 0; i < ARRAY_SIZE(sched_cfg->channels); i++) { struct ieee80211_chanctx_conf *chanctx; /* already have an existing active link */ @@ -581,6 +593,39 @@ void iwl_mld_nan_vif_cfg_changed(struct iwl_mld *mld, } } + /* fill the command */ + for (i = 0; i < ARRAY_SIZE(sched_cfg->channels); i++) { + cmd.channels[i].link_id = FW_CTXT_ID_INVALID; + + if (!sched_cfg->channels[i].chanreq.oper.chan) + continue; + + memcpy(cmd.channels[i].channel_entry, + sched_cfg->channels[i].channel_entry, 6); + cmd.channels[i].link_id = + links[i] ? links[i]->fw_id : FW_CTXT_ID_INVALID; + } + + for (i = 0; i < CFG80211_NAN_SCHED_NUM_TIME_SLOTS; i++) { + int chan_idx; + + if (!slots[i]) + continue; + + chan_idx = slots[i] - sched_cfg->channels; + if (WARN_ON_ONCE(chan_idx < 0 || + chan_idx >= ARRAY_SIZE(cmd.channels))) + continue; + + cmd.channels[chan_idx].availability_map |= cpu_to_le32(BIT(i)); + } + + ret = iwl_mld_send_cmd_pdu(mld, + WIDE_ID(MAC_CONF_GROUP, NAN_SCHEDULE_CMD), + &cmd); + if (ret) + IWL_ERR(mld, "NAN: failed to update schedule (%d)\n", ret); + /* delete unused links */ for_each_mld_nan_valid_link(mld_vif, nan_link) { if (!link_used[nan_link->fw_id]) { @@ -595,7 +640,8 @@ void iwl_mld_nan_vif_cfg_changed(struct iwl_mld *mld, WARN_ON_ONCE(!mld_vif->nan.mac_added); /* mac80211 should reconfigure same state */ - if (!WARN_ON_ONCE(mld->fw_status.in_hw_restart)) + if (!WARN_ON_ONCE(mld->fw_status.in_hw_restart && + !iwl_mld_error_before_recovery(mld))) iwl_mld_rm_vif(mld, vif); } } |
