]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: iwlwifi: mld: Add support for multiple NAN Management stations
authorIlan Peer <ilan.peer@intel.com>
Tue, 12 May 2026 19:34:40 +0000 (22:34 +0300)
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>
Tue, 26 May 2026 12:17:11 +0000 (15:17 +0300)
The following limitations arise from the current FW support for NAN:

- While NAN synchronization and discovery beacons are sent
  internally by the firmware, the BIGTK is configured to the
  auxiliary station associated with the NAN operation. Thus,
  the beacons are transmitted unprotected.
- The auxiliary station cannot be configured with support for
  management frame protection as this is not supported by the
  firmware. Thus, there is no way to protect the SDFs and the
  NAFs.

To overcome the above limitations the firmware introduced the
following new station types:

- NAN broadcast station: Used for NAN synchronization and
  discovery. i.e., used for beacon transmissions. A BIGTK
  can be configured to this station and thus beacons can
  be transmitted with protection.
- NAN management station: Used for sending SDFs and NAFs.
  This station can be configured with support for management
  frame protection etc.

Modify the iwlmld logic to support the older and the newer
firmware designs. As no Tx queue is needed for the NAN
broadcast station, modify the internal station support
to allow adding/removing a station without a queue. In
addition, since no links are associated with these stations,
modify the internal station support to allow adding a station
without a link mask.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Link: https://patch.msgid.link/20260512222731.692bf627811d.I7170dbaa28a74519c012e2d7818e2999819dc478@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/iface.c
drivers/net/wireless/intel/iwlwifi/mld/iface.h
drivers/net/wireless/intel/iwlwifi/mld/nan.c
drivers/net/wireless/intel/iwlwifi/mld/nan.h
drivers/net/wireless/intel/iwlwifi/mld/sta.c
drivers/net/wireless/intel/iwlwifi/mld/sta.h
drivers/net/wireless/intel/iwlwifi/mld/tx.c

index dd850aeebdeccf1e6167b08102210a0f11b5b422..1df81df5830e3a461ccb9805fd98402963abd77a 100644 (file)
@@ -735,6 +735,10 @@ struct iwl_link_config_cmd {
  * @STATION_TYPE_NAN_PEER_NDI: NAN data peer station type. A station
  *     of this type can have any number of links (even none) set in the
  *     link_mask. (Supported since version 3.)
+ * @STATION_TYPE_NAN_BCAST: NAN station used for synchronization and
+ *     discovery. No queue is associated with this station.
+ * @STATION_TYPE_NAN_MGMT: NAN station used for NAN management frames, e.g.,
+ *     SDFs and NAFs.
  * @STATION_TYPE_MAX: maximum number of FW station types
  * @STATION_TYPE_AUX: aux sta. In the FW there is no need for a special type
  *     for the aux sta, so this type is only for driver - internal use.
@@ -745,6 +749,8 @@ enum iwl_fw_sta_type {
        STATION_TYPE_MCAST,
        STATION_TYPE_NAN_PEER_NMI,
        STATION_TYPE_NAN_PEER_NDI,
+       STATION_TYPE_NAN_BCAST,
+       STATION_TYPE_NAN_MGMT,
        STATION_TYPE_MAX,
        STATION_TYPE_AUX = STATION_TYPE_MAX /* this doesn't exist in FW */
 }; /* STATION_TYPE_E_VER_1, _VER_2 */
@@ -882,7 +888,9 @@ struct iwl_sta_cfg_cmd_v2 {
  * ( STA_CONFIG_CMD = 0xA )
  *
  * @sta_id: index of station in uCode's station table
- * @link_mask: bitmap of link FW IDs used with this STA
+ * @link_mask: bitmap of link FW IDs used with this STA. Should be set to 0
+ *     for STATION_TYPE_NAN_BCAST and STATION_TYPE_NAN_MGMT as they are not
+ *     associated with any link added by the driver.
  * @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
@@ -1213,7 +1221,8 @@ enum iwl_nan_flags {
  * @discovery_beacon_interval: discovery beacon interval in TUs
  * @cluster_id: lower last two bytes of the cluster ID, in case the local
  *     device starts a cluster
- * @sta_id: station ID of the NAN station
+ * @sta_id: station ID of the NAN station. Used only in version 1, in version 2
+ *     it is reserved.
  * @hb_channel: channel for 5 GHz if the device supports operation on 5 GHz.
  *     Valid values are 44 and 149, which correspond to the 5 GHz channel, and
  *     0 which means that NAN operation on the 5 GHz band is disabled.
@@ -1251,7 +1260,7 @@ struct iwl_nan_config_cmd {
        __le32 nan_attr_len;
        __le32 nan_vendor_elems_len;
        u8 beacon_data[];
-} __packed; /*  NAN_CONFIG_CMD_API_S_VER_1 */
+} __packed; /*  NAN_CONFIG_CMD_API_S_VER_1, NAN_CONFIG_CMD_API_S_VER_2 */
 
 /**
  * struct iwl_nan_schedule_cmd_v1 - NAN schedule command
index 6f2590f9a69b223f6dda3091a492dd7902d7a6c8..2a270d689de8929e3beb47f866e4b22811868d9d 100644 (file)
@@ -61,6 +61,11 @@ void iwl_mld_cleanup_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
                /* Clean up NAN links */
                for (int i = 0; i < ARRAY_SIZE(mld_vif->nan.links); i++)
                        iwl_mld_cleanup_nan_link(&mld_vif->nan.links[i]);
+
+               if (mld_vif->nan.bcast_sta.sta_id != IWL_INVALID_STA)
+                       iwl_mld_free_internal_sta(mld, &mld_vif->nan.bcast_sta);
+               if (mld_vif->nan.mgmt_sta.sta_id != IWL_INVALID_STA)
+                       iwl_mld_free_internal_sta(mld, &mld_vif->nan.mgmt_sta);
        }
 
        CLEANUP_STRUCT(mld_vif);
@@ -526,6 +531,9 @@ iwl_mld_init_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
                        memset(&mld_vif->nan.links[i], 0, sizeof(mld_vif->nan.links[i]));
                        mld_vif->nan.links[i].fw_id = FW_CTXT_ID_INVALID;
                }
+
+               iwl_mld_init_internal_sta(&mld_vif->nan.bcast_sta);
+               iwl_mld_init_internal_sta(&mld_vif->nan.mgmt_sta);
        }
 
        iwl_mld_init_internal_sta(&mld_vif->aux_sta);
index d6fb58e785e5bb811124fb5fab45d14c0b3f04bc..75b6727503d3c3525e57cd14b1cd64ff76c2ce87 100644 (file)
@@ -155,6 +155,10 @@ struct iwl_mld_emlsr {
  * @nan: NAN parameters
  * @nan.links: NAN links for FW (indexed by FW link ID)
  * @nan.mac_added: track whether or not the MAC was added to FW
+ * @nan.bcast_sta: internal station used for NAN synchronization and discovery
+ *     activities. No queue is associated with it.
+ * @nan.mgmt_sta: internal station used for NAN management frames, e.g., SDFs
+ *     and NAFs.
  */
 struct iwl_mld_vif {
        /* Add here fields that need clean up on restart */
@@ -181,6 +185,8 @@ struct iwl_mld_vif {
                /* use only with wiphy protection */
                struct iwl_mld_nan_link links[IWL_FW_MAX_LINKS];
                bool mac_added;
+               struct iwl_mld_int_sta bcast_sta;
+               struct iwl_mld_int_sta mgmt_sta;
        } nan;
 
        struct iwl_mld_emlsr emlsr;
index 53a0c3b9bb33e1ca3e2c10a5d93d74d99e760c38..351c726be51f8d6457405481c785869145905132 100644 (file)
@@ -50,6 +50,98 @@ static int iwl_mld_nan_send_config_cmd(struct iwl_mld *mld,
        return iwl_mld_send_cmd(mld, &hcmd);
 }
 
+static bool iwl_mld_nan_use_nan_stations(struct iwl_mld *mld)
+{
+       /*
+        * If the FW supports version 1 of the NAN config command, it means that
+        * it needs to receive the station ID of the auxiliary station in the
+        * NAN configuration command. Otherwise, use the NAN dedicated station
+        * types.
+        */
+       return iwl_fw_lookup_cmd_ver(mld->fw,
+                                    WIDE_ID(MAC_CONF_GROUP,
+                                            NAN_CFG_CMD), 1) != 1;
+}
+
+static const struct iwl_mld_int_sta *
+iwl_mld_nan_get_mgmt_sta(struct iwl_mld *mld, struct ieee80211_vif *vif)
+{
+       struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
+       const struct iwl_mld_int_sta *sta;
+
+       if (iwl_mld_nan_use_nan_stations(mld))
+               sta = &mld_vif->nan.mgmt_sta;
+       else
+               sta = &mld_vif->aux_sta;
+
+       if (WARN_ON(sta->sta_id == IWL_INVALID_STA))
+               return NULL;
+
+       return sta;
+}
+
+int iwl_mld_nan_get_mgmt_queue(struct iwl_mld *mld, struct ieee80211_vif *vif)
+{
+       const struct iwl_mld_int_sta *sta = iwl_mld_nan_get_mgmt_sta(mld, vif);
+
+       if (!sta)
+               return IWL_MLD_INVALID_QUEUE;
+
+       return sta->queue_id;
+}
+
+static void iwl_mld_nan_flush(struct iwl_mld *mld, struct ieee80211_vif *vif)
+{
+       const struct iwl_mld_int_sta *sta = iwl_mld_nan_get_mgmt_sta(mld, vif);
+
+       if (!sta)
+               return;
+
+       if (WARN_ON(sta->queue_id == IWL_MLD_INVALID_QUEUE))
+               return;
+
+       IWL_DEBUG_INFO(mld, "NAN: flush queues for sta=%u\n",
+                      sta->sta_id);
+
+       iwl_mld_flush_link_sta_txqs(mld, sta->sta_id);
+}
+
+static void iwl_mld_nan_remove_stations(struct iwl_mld *mld,
+                                       struct ieee80211_vif *vif)
+{
+       struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
+
+       iwl_mld_nan_flush(mld, vif);
+
+       if (!iwl_mld_nan_use_nan_stations(mld)) {
+               iwl_mld_remove_aux_sta(mld, vif);
+               return;
+       }
+
+       iwl_mld_remove_nan_bcast_sta(mld, &mld_vif->nan.bcast_sta);
+       iwl_mld_remove_nan_mgmt_sta(mld, &mld_vif->nan.mgmt_sta);
+}
+
+static int iwl_mld_nan_add_stations(struct iwl_mld *mld,
+                                   struct ieee80211_vif *vif)
+{
+       struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
+       int ret;
+
+       if (!iwl_mld_nan_use_nan_stations(mld))
+               return iwl_mld_add_aux_sta(mld, &mld_vif->aux_sta);
+
+       ret = iwl_mld_add_nan_bcast_sta(mld, &mld_vif->nan.bcast_sta);
+       if (ret)
+               return ret;
+
+       ret = iwl_mld_add_nan_mgmt_sta(mld, &mld_vif->nan.mgmt_sta);
+       if (ret)
+               iwl_mld_remove_nan_bcast_sta(mld, &mld_vif->nan.bcast_sta);
+
+       return ret;
+}
+
 static int iwl_mld_nan_config(struct iwl_mld *mld,
                              struct ieee80211_vif *vif,
                              struct cfg80211_nan_conf *conf,
@@ -126,7 +218,12 @@ static int iwl_mld_nan_config(struct iwl_mld *mld,
                               conf->vendor_elems_len);
        }
 
-       cmd.sta_id = mld_vif->aux_sta.sta_id;
+       /* FW needs to know about the station ID only with version 1 of the
+        * NAN configuration command
+        */
+       if (!iwl_mld_nan_use_nan_stations(mld))
+               cmd.sta_id = mld_vif->aux_sta.sta_id;
+
        return iwl_mld_nan_send_config_cmd(mld, &cmd, data,
                                           conf->extra_nan_attrs_len +
                                           conf->vendor_elems_len);
@@ -136,8 +233,6 @@ int iwl_mld_start_nan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                      struct cfg80211_nan_conf *conf)
 {
        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 = &mld_vif->aux_sta;
        int ret;
 
        IWL_DEBUG_MAC80211(mld, "NAN: start: bands=0x%x\n", conf->bands);
@@ -146,19 +241,20 @@ int iwl_mld_start_nan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        if (ret)
                return ret;
 
-       ret = iwl_mld_add_aux_sta(mld, aux_sta);
+       ret = iwl_mld_nan_add_stations(mld, vif);
        if (ret)
                goto unblock_emlsr;
 
        ret = iwl_mld_nan_config(mld, vif, conf, FW_CTXT_ACTION_ADD);
        if (ret) {
                IWL_ERR(mld, "Failed to start NAN. ret=%d\n", ret);
-               goto remove_aux;
+               goto remove_stas;
        }
+
        return 0;
 
-remove_aux:
-       iwl_mld_remove_aux_sta(mld, vif);
+remove_stas:
+       iwl_mld_nan_remove_stations(mld, vif);
 unblock_emlsr:
        iwl_mld_update_emlsr_block(mld, false, IWL_MLD_EMLSR_BLOCKED_NAN);
 
@@ -186,7 +282,6 @@ int iwl_mld_stop_nan(struct ieee80211_hw *hw,
                     struct ieee80211_vif *vif)
 {
        struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
-       struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
        struct iwl_nan_config_cmd cmd = {
                .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
        };
@@ -203,9 +298,7 @@ int iwl_mld_stop_nan(struct ieee80211_hw *hw,
        /* assume that higher layer guarantees that no additional frames are
         * added before calling this callback
         */
-       if (!WARN_ON(mld_vif->aux_sta.sta_id == IWL_INVALID_STA))
-               iwl_mld_flush_link_sta_txqs(mld, mld_vif->aux_sta.sta_id);
-       iwl_mld_remove_aux_sta(mld, vif);
+       iwl_mld_nan_remove_stations(mld, vif);
 
        /* cancel based on object type being NAN, as the NAN objects do
         * not have a unique identifier associated with them
@@ -279,13 +372,7 @@ void iwl_mld_handle_nan_dw_end_notif(struct iwl_mld *mld,
                         "NAN: DW end without NAN started\n"))
                return;
 
-       if (WARN_ON(mld_vif->aux_sta.sta_id == IWL_INVALID_STA))
-               return;
-
-       IWL_DEBUG_INFO(mld, "NAN: flush queues for aux sta=%u\n",
-                      mld_vif->aux_sta.sta_id);
-
-       iwl_mld_flush_link_sta_txqs(mld, mld_vif->aux_sta.sta_id);
+       iwl_mld_nan_flush(mld, mld->nan_device_vif);
 
        /* TODO: currently the notification specified the band on which the DW
         * ended. Need to change that to the actual channel on which the next DW
index 80e18c4ddb33cd4cf40071d0a84f388eeeee6f0e..caa98dbb4a75752d9ae573e8e1b412c725482da8 100644 (file)
@@ -53,4 +53,6 @@ void iwl_mld_nan_vif_cfg_changed(struct iwl_mld *mld,
 int iwl_mld_mac802111_nan_peer_sched_changed(struct ieee80211_hw *hw,
                                             struct ieee80211_sta *sta);
 
+int iwl_mld_nan_get_mgmt_queue(struct iwl_mld *mld, struct ieee80211_vif *vif);
+
 #endif /* __iwl_mld_nan_h__ */
index f794f80b0fddf45e6991c207e416d9aa48ad2fa2..1fae5a6ba8d461209db722d38c2b939b9df63a3e 100644 (file)
@@ -430,6 +430,8 @@ static int iwl_mld_send_sta_cmd(struct iwl_mld *mld,
                cmd_v2->link_id = cpu_to_le32(__ffs(le32_to_cpu(cmd->link_mask)));
        } else if (WARN_ON(cmd->station_type != cpu_to_le32(STATION_TYPE_NAN_PEER_NMI) &&
                           cmd->station_type != cpu_to_le32(STATION_TYPE_NAN_PEER_NDI) &&
+                          cmd->station_type != cpu_to_le32(STATION_TYPE_NAN_BCAST) &&
+                          cmd->station_type != cpu_to_le32(STATION_TYPE_NAN_MGMT) &&
                           hweight32(le32_to_cpu(cmd->link_mask)) != 1)) {
                return -EINVAL;
        }
@@ -1063,8 +1065,7 @@ static int iwl_mld_send_aux_sta_cmd(struct iwl_mld *mld,
 static int
 iwl_mld_add_internal_sta_to_fw(struct iwl_mld *mld,
                               const struct iwl_mld_int_sta *internal_sta,
-                              u8 fw_link_id,
-                              const u8 *addr)
+                              u32 link_mask, const u8 *addr)
 {
        struct iwl_sta_cfg_cmd cmd = {};
 
@@ -1072,7 +1073,7 @@ iwl_mld_add_internal_sta_to_fw(struct iwl_mld *mld,
                return iwl_mld_send_aux_sta_cmd(mld, internal_sta);
 
        cmd.sta_id = cpu_to_le32((u8)internal_sta->sta_id);
-       cmd.link_mask = cpu_to_le32(BIT(fw_link_id));
+       cmd.link_mask = cpu_to_le32(link_mask);
        cmd.station_type = cpu_to_le32(internal_sta->sta_type);
 
        /* FW doesn't allow to add a IGTK/BIGTK if the sta isn't marked as MFP.
@@ -1094,7 +1095,8 @@ iwl_mld_add_internal_sta_to_fw(struct iwl_mld *mld,
 static int iwl_mld_add_internal_sta(struct iwl_mld *mld,
                                    struct iwl_mld_int_sta *internal_sta,
                                    enum iwl_fw_sta_type sta_type,
-                                   u8 fw_link_id, const u8 *addr, u8 tid)
+                                   u32 link_mask, const u8 *addr,
+                                   u8 tid, bool add_txq)
 {
        int ret, queue_id;
 
@@ -1106,11 +1108,14 @@ static int iwl_mld_add_internal_sta(struct iwl_mld *mld,
 
        internal_sta->sta_type = sta_type;
 
-       ret = iwl_mld_add_internal_sta_to_fw(mld, internal_sta, fw_link_id,
+       ret = iwl_mld_add_internal_sta_to_fw(mld, internal_sta, link_mask,
                                             addr);
        if (ret)
                goto err;
 
+       if (!add_txq)
+               return 0;
+
        queue_id = iwl_mld_allocate_internal_txq(mld, internal_sta, tid);
        if (queue_id < 0) {
                iwl_mld_rm_sta_from_fw(mld, internal_sta->sta_id);
@@ -1145,8 +1150,8 @@ int iwl_mld_add_bcast_sta(struct iwl_mld *mld,
 
        return iwl_mld_add_internal_sta(mld, &mld_link->bcast_sta,
                                        STATION_TYPE_BCAST_MGMT,
-                                       mld_link->fw_id, addr,
-                                       IWL_MGMT_TID);
+                                       BIT(mld_link->fw_id), addr,
+                                       IWL_MGMT_TID, true);
 }
 
 int iwl_mld_add_mcast_sta(struct iwl_mld *mld,
@@ -1165,14 +1170,16 @@ int iwl_mld_add_mcast_sta(struct iwl_mld *mld,
 
        return iwl_mld_add_internal_sta(mld, &mld_link->mcast_sta,
                                        STATION_TYPE_MCAST,
-                                       mld_link->fw_id, mcast_addr, 0);
+                                       BIT(mld_link->fw_id), mcast_addr,
+                                       0, true);
 }
 
 int iwl_mld_add_aux_sta(struct iwl_mld *mld,
                        struct iwl_mld_int_sta *internal_sta)
 {
        return iwl_mld_add_internal_sta(mld, internal_sta, STATION_TYPE_AUX,
-                                       0, NULL, IWL_MAX_TID_COUNT);
+                                       0, NULL, IWL_MAX_TID_COUNT,
+                                       true);
 }
 
 int iwl_mld_add_mon_sta(struct iwl_mld *mld,
@@ -1189,23 +1196,25 @@ int iwl_mld_add_mon_sta(struct iwl_mld *mld,
 
        return iwl_mld_add_internal_sta(mld, &mld_link->mon_sta,
                                        STATION_TYPE_BCAST_MGMT,
-                                       mld_link->fw_id, NULL,
-                                       IWL_MAX_TID_COUNT);
+                                       BIT(mld_link->fw_id), NULL,
+                                       IWL_MAX_TID_COUNT,
+                                       true);
 }
 
 static void iwl_mld_remove_internal_sta(struct iwl_mld *mld,
                                        struct iwl_mld_int_sta *internal_sta,
                                        bool flush, u8 tid)
 {
-       if (WARN_ON_ONCE(internal_sta->sta_id == IWL_INVALID_STA ||
-                        internal_sta->queue_id == IWL_MLD_INVALID_QUEUE))
+       if (WARN_ON_ONCE(internal_sta->sta_id == IWL_INVALID_STA))
                return;
 
-       if (flush)
+       if (flush && !WARN_ON_ONCE(internal_sta->queue_id ==
+                                  IWL_MLD_INVALID_QUEUE))
                iwl_mld_flush_link_sta_txqs(mld, internal_sta->sta_id);
 
-       iwl_mld_free_txq(mld, BIT(internal_sta->sta_id),
-                        tid, internal_sta->queue_id);
+       if (internal_sta->queue_id != IWL_MLD_INVALID_QUEUE)
+               iwl_mld_free_txq(mld, BIT(internal_sta->sta_id),
+                                tid, internal_sta->queue_id);
 
        iwl_mld_rm_sta_from_fw(mld, internal_sta->sta_id);
 
@@ -1406,3 +1415,31 @@ remove_added_link_stas:
 
        return ret;
 }
+
+int iwl_mld_add_nan_bcast_sta(struct iwl_mld *mld,
+                             struct iwl_mld_int_sta *sta)
+{
+       const u8 bcast_addr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+       return iwl_mld_add_internal_sta(mld, sta, STATION_TYPE_NAN_BCAST,
+                                       0, bcast_addr, 0, false);
+}
+
+int iwl_mld_add_nan_mgmt_sta(struct iwl_mld *mld,
+                            struct iwl_mld_int_sta *sta)
+{
+       return iwl_mld_add_internal_sta(mld, sta, STATION_TYPE_NAN_MGMT,
+                                       0, NULL, IWL_MAX_TID_COUNT, true);
+}
+
+void iwl_mld_remove_nan_bcast_sta(struct iwl_mld *mld,
+                                 struct iwl_mld_int_sta *sta)
+{
+       iwl_mld_remove_internal_sta(mld, sta, false, 0);
+}
+
+void iwl_mld_remove_nan_mgmt_sta(struct iwl_mld *mld,
+                                struct iwl_mld_int_sta *sta)
+{
+       iwl_mld_remove_internal_sta(mld, sta, true, IWL_MAX_TID_COUNT);
+}
index dff14ff0a5af23b1bd5e3c991524fcf52764b77a..df859a9e52300f2028d18722c21593bd048ee2a8 100644 (file)
@@ -276,4 +276,17 @@ int iwl_mld_update_link_stas(struct iwl_mld *mld,
                             struct ieee80211_vif *vif,
                             struct ieee80211_sta *sta,
                             u16 old_links, u16 new_links);
+
+int iwl_mld_add_nan_bcast_sta(struct iwl_mld *mld,
+                             struct iwl_mld_int_sta *sta);
+
+int iwl_mld_add_nan_mgmt_sta(struct iwl_mld *mld,
+                            struct iwl_mld_int_sta *sta);
+
+void iwl_mld_remove_nan_bcast_sta(struct iwl_mld *mld,
+                                 struct iwl_mld_int_sta *sta);
+
+void iwl_mld_remove_nan_mgmt_sta(struct iwl_mld *mld,
+                                struct iwl_mld_int_sta *sta);
+
 #endif /* __iwl_mld_sta_h__ */
index 636d24633e57aac5c666addd5618f462851408b5..39e1d959e42c2323f24b71852042c3bccd0765e8 100644 (file)
@@ -680,11 +680,8 @@ iwl_mld_get_tx_queue_id(struct iwl_mld *mld, struct ieee80211_txq *txq,
                WARN_ON(!ieee80211_is_mgmt(fc));
                return mld_vif->aux_sta.queue_id;
        case NL80211_IFTYPE_NAN:
-               mld_vif = iwl_mld_vif_from_mac80211(info->control.vif);
-
                WARN_ON(!ieee80211_is_mgmt(fc));
-
-               return mld_vif->aux_sta.queue_id;
+               return iwl_mld_nan_get_mgmt_queue(mld, info->control.vif);
        default:
                WARN_ONCE(1, "Unsupported vif type\n");
                break;