]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: iwlwifi: add NAN schedule command support
authorJohannes Berg <johannes.berg@intel.com>
Sun, 10 May 2026 20:48:31 +0000 (23:48 +0300)
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>
Tue, 26 May 2026 12:17:09 +0000 (15:17 +0300)
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>
drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
drivers/net/wireless/intel/iwlwifi/mld/mld.c
drivers/net/wireless/intel/iwlwifi/mld/nan.c

index b398c582b8670c1c8c54dc4996ad4efe771c2855..d98c6d991a8881b572d05fde6d719268d6a97800 100644 (file)
@@ -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
@@ -71,6 +72,10 @@ enum iwl_mac_conf_subcmd_ids {
         * @NAN_CFG_CMD: &struct iwl_nan_config_cmd
         */
        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
         */
@@ -1244,6 +1249,25 @@ struct iwl_nan_config_cmd {
        u8 beacon_data[];
 } __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
  *
index 9af79297c3b6ae3689d3c76a76bdbe4728361d59..c038a0cde36bdb72fcb407faf798e3e460effb16 100644 (file)
@@ -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),
index 6ea11b66a5453242c66ad40e32a165a2276b5877..eba79aca8c062e4e726f68ccfb571d06e6bea9f0 100644 (file)
@@ -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);
        }
 }