mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 10:09:10 +02:00
wifi: iwlwifi: mld: support NAN and NAN_DATA interfaces
Until now we maintained the NAN vif in the driver only. The fw used the AUX MAC for sync and discovery operations. But when we want to configure a local schedule, we need to add the MAC first. NAN_DATA interfaces are not added to the FW. Instead, the local address of these interfaces are configured to the FW via the NAN MAC. Add the add/remove/update operations for the NAN interface, and fill the NAN special parameters in it. Note that this doesn't fully implement the schedule change, but only the addition/removal of the NAN MAC. The full schedule management implementation will come in a later patch. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Co-developed-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Link: https://patch.msgid.link/20260510234534.dd12944c140b.I3578198660a533faf9f6a94432ef2114f4a9dfae@changeid Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
This commit is contained in:
parent
ac25c51110
commit
6e373b916a
|
|
@ -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 <net/cfg80211.h>
|
||||
|
||||
|
|
@ -55,6 +55,9 @@ 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);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_NAN)
|
||||
mld_vif->nan.mac_added = false;
|
||||
|
||||
CLEANUP_STRUCT(mld_vif);
|
||||
}
|
||||
|
||||
|
|
@ -94,6 +97,8 @@ static int iwl_mld_mac80211_iftype_to_fw(const struct ieee80211_vif *vif)
|
|||
return FW_MAC_TYPE_P2P_DEVICE;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
return FW_MAC_TYPE_IBSS;
|
||||
case NL80211_IFTYPE_NAN:
|
||||
return FW_MAC_TYPE_NAN;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
|
|
@ -362,6 +367,42 @@ static void iwl_mld_fill_mac_cmd_ibss(struct iwl_mld *mld,
|
|||
MAC_CFG_FILTER_ACCEPT_GRP);
|
||||
}
|
||||
|
||||
static int iwl_mld_fill_mac_cmd_nan(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_vif *ndi_being_added,
|
||||
struct iwl_mac_config_cmd *cmd)
|
||||
{
|
||||
struct ieee80211_vif *iter;
|
||||
u32 idx = 0;
|
||||
|
||||
cmd->filter_flags = cpu_to_le32(MAC_CFG_FILTER_ACCEPT_CONTROL_AND_MGMT);
|
||||
|
||||
/*
|
||||
* A NAN_DATA vif might be in the process of being added - it won't
|
||||
* be found by the iteration below since it's not yet active/in-driver.
|
||||
* In hw restart, the iteration below will find the ndi_being_added.
|
||||
*/
|
||||
if (ndi_being_added && !mld->fw_status.in_hw_restart) {
|
||||
memcpy(cmd->nan.ndi_addrs[idx].addr, ndi_being_added->addr, ETH_ALEN);
|
||||
idx++;
|
||||
}
|
||||
|
||||
for_each_active_interface(iter, mld->hw) {
|
||||
if (iter->type != NL80211_IFTYPE_NAN_DATA)
|
||||
continue;
|
||||
|
||||
if (WARN_ON_ONCE(idx >= ARRAY_SIZE(cmd->nan.ndi_addrs)))
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(cmd->nan.ndi_addrs[idx].addr, iter->addr, ETH_ALEN);
|
||||
idx++;
|
||||
}
|
||||
|
||||
cmd->nan.ndi_addrs_count = cpu_to_le32(idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_mld_rm_mac_from_fw(struct iwl_mld *mld, struct ieee80211_vif *vif)
|
||||
{
|
||||
|
|
@ -374,16 +415,23 @@ iwl_mld_rm_mac_from_fw(struct iwl_mld *mld, struct ieee80211_vif *vif)
|
|||
return iwl_mld_send_mac_cmd(mld, &cmd);
|
||||
}
|
||||
|
||||
int iwl_mld_mac_fw_action(struct iwl_mld *mld, struct ieee80211_vif *vif,
|
||||
u32 action)
|
||||
static int
|
||||
__iwl_mld_mac_fw_action(struct iwl_mld *mld, struct ieee80211_vif *vif,
|
||||
u32 action, struct ieee80211_vif *ndi_being_added)
|
||||
{
|
||||
struct iwl_mac_config_cmd cmd = {};
|
||||
int ret;
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
/* NAN interface type is not known to FW */
|
||||
if (vif->type == NL80211_IFTYPE_NAN)
|
||||
return 0;
|
||||
/* NAN_DATA interface type is not known to FW */
|
||||
if (WARN_ON(vif->type == NL80211_IFTYPE_NAN_DATA))
|
||||
return -EINVAL;
|
||||
|
||||
/* ndi_being_added is only relevant for NAN and when adding a NAN_DATA interface */
|
||||
if (WARN_ON(ndi_being_added &&
|
||||
(vif->type != NL80211_IFTYPE_NAN || action != FW_CTXT_ACTION_MODIFY)))
|
||||
return -EINVAL;
|
||||
|
||||
if (action == FW_CTXT_ACTION_REMOVE)
|
||||
return iwl_mld_rm_mac_from_fw(mld, vif);
|
||||
|
|
@ -411,6 +459,11 @@ int iwl_mld_mac_fw_action(struct iwl_mld *mld, struct ieee80211_vif *vif,
|
|||
case NL80211_IFTYPE_ADHOC:
|
||||
iwl_mld_fill_mac_cmd_ibss(mld, vif, &cmd);
|
||||
break;
|
||||
case NL80211_IFTYPE_NAN:
|
||||
ret = iwl_mld_fill_mac_cmd_nan(mld, vif, ndi_being_added, &cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
WARN(1, "not supported yet\n");
|
||||
return -EOPNOTSUPP;
|
||||
|
|
@ -419,6 +472,12 @@ int iwl_mld_mac_fw_action(struct iwl_mld *mld, struct ieee80211_vif *vif,
|
|||
return iwl_mld_send_mac_cmd(mld, &cmd);
|
||||
}
|
||||
|
||||
int iwl_mld_mac_fw_action(struct iwl_mld *mld, struct ieee80211_vif *vif,
|
||||
u32 action)
|
||||
{
|
||||
return __iwl_mld_mac_fw_action(mld, vif, action, NULL);
|
||||
}
|
||||
|
||||
static void iwl_mld_mlo_scan_start_wk(struct wiphy *wiphy,
|
||||
struct wiphy_work *wk)
|
||||
{
|
||||
|
|
@ -459,6 +518,24 @@ iwl_mld_init_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
|
|||
iwl_mld_init_internal_sta(&mld_vif->aux_sta);
|
||||
}
|
||||
|
||||
static int iwl_mld_update_nan_mac(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *ndi_being_added)
|
||||
{
|
||||
struct ieee80211_vif *vif = mld->nan_device_vif;
|
||||
struct iwl_mld_vif *mld_vif;
|
||||
|
||||
if (WARN_ON_ONCE(!vif))
|
||||
return -ENODEV;
|
||||
|
||||
mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
|
||||
if (!iwl_mld_vif_fw_id_valid(mld_vif))
|
||||
return 0;
|
||||
|
||||
return __iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_MODIFY,
|
||||
ndi_being_added);
|
||||
}
|
||||
|
||||
int iwl_mld_add_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
|
|
@ -468,10 +545,14 @@ int iwl_mld_add_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
|
|||
|
||||
iwl_mld_init_vif(mld, vif);
|
||||
|
||||
/* NAN interface type is not known to FW */
|
||||
/* NAN MACs are added to FW only when a schedule is set */
|
||||
if (vif->type == NL80211_IFTYPE_NAN)
|
||||
return 0;
|
||||
|
||||
/* NAN_DATA interface type is not known to FW, but we need to update NAN MAC */
|
||||
if (vif->type == NL80211_IFTYPE_NAN_DATA)
|
||||
return iwl_mld_update_nan_mac(mld, vif);
|
||||
|
||||
ret = iwl_mld_allocate_vif_fw_id(mld, &mld_vif->fw_id, vif);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -483,23 +564,52 @@ int iwl_mld_add_vif(struct iwl_mld *mld, struct ieee80211_vif *vif)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mld_add_nan_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);
|
||||
|
||||
if (WARN_ON(vif->type != NL80211_IFTYPE_NAN))
|
||||
return -EINVAL;
|
||||
|
||||
ret = iwl_mld_allocate_vif_fw_id(mld, &mld_vif->fw_id, vif);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_ADD);
|
||||
if (ret) {
|
||||
RCU_INIT_POINTER(mld->fw_id_to_vif[mld_vif->fw_id], NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mld_vif->nan.mac_added = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
/* NAN interface type is not known to FW */
|
||||
if (vif->type == NL80211_IFTYPE_NAN)
|
||||
if (vif->type == NL80211_IFTYPE_NAN_DATA) {
|
||||
iwl_mld_update_nan_mac(mld, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!iwl_mld_vif_fw_id_valid(mld_vif))
|
||||
return;
|
||||
|
||||
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;
|
||||
|
||||
RCU_INIT_POINTER(mld->fw_id_to_vif[mld_vif->fw_id], NULL);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_NAN)
|
||||
mld_vif->nan.mac_added = false;
|
||||
|
||||
iwl_mld_cancel_notifications_of_object(mld, IWL_MLD_OBJECT_TYPE_VIF,
|
||||
mld_vif->fw_id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,6 +152,8 @@ struct iwl_mld_emlsr {
|
|||
* 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
|
||||
* @nan: NAN parameters
|
||||
* @nan.mac_added: track whether or not the MAC was added to FW
|
||||
*/
|
||||
struct iwl_mld_vif {
|
||||
/* Add here fields that need clean up on restart */
|
||||
|
|
@ -175,6 +177,11 @@ struct iwl_mld_vif {
|
|||
struct iwl_mld_link deflink;
|
||||
struct iwl_mld_link __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
|
||||
struct {
|
||||
/* use only with wiphy protection */
|
||||
bool mac_added;
|
||||
} nan;
|
||||
|
||||
struct iwl_mld_emlsr emlsr;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
@ -206,6 +213,20 @@ iwl_mld_vif_to_mac80211(struct iwl_mld_vif *mld_vif)
|
|||
/* Call only for interfaces that were added to the driver! */
|
||||
static inline bool iwl_mld_vif_fw_id_valid(struct iwl_mld_vif *mld_vif)
|
||||
{
|
||||
struct ieee80211_vif *vif = iwl_mld_vif_to_mac80211(mld_vif);
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_NAN_DATA:
|
||||
return false;
|
||||
case NL80211_IFTYPE_NAN:
|
||||
if (!mld_vif->nan.mac_added)
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Should be added to FW */
|
||||
if (WARN_ON(mld_vif->fw_id >= ARRAY_SIZE(mld_vif->mld->fw_id_to_vif)))
|
||||
return false;
|
||||
|
||||
|
|
@ -235,6 +256,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_add_nan_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);
|
||||
|
|
|
|||
|
|
@ -677,6 +677,9 @@ int iwl_mld_mac80211_add_interface(struct ieee80211_hw *hw,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_NAN_DATA)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Add the default link, but not if this is an MLD vif as that implies
|
||||
* the HW is restarting and it will be configured by change_vif_links.
|
||||
|
|
@ -745,7 +748,7 @@ void iwl_mld_mac80211_remove_interface(struct ieee80211_hw *hw,
|
|||
|
||||
if (vif->type == NL80211_IFTYPE_NAN)
|
||||
mld->nan_device_vif = NULL;
|
||||
else
|
||||
else if (vif->type != NL80211_IFTYPE_NAN_DATA)
|
||||
iwl_mld_remove_link(mld, &vif->bss_conf);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
|
|
@ -1371,6 +1374,10 @@ iwl_mld_mac80211_link_info_changed(struct ieee80211_hw *hw,
|
|||
if (changes & BSS_CHANGED_MU_GROUPS)
|
||||
iwl_mld_update_mu_groups(mld, link_conf);
|
||||
break;
|
||||
case NL80211_IFTYPE_NAN:
|
||||
case NL80211_IFTYPE_NAN_DATA:
|
||||
/* NAN has no links */
|
||||
break;
|
||||
default:
|
||||
/* shouldn't happen */
|
||||
WARN_ON_ONCE(1);
|
||||
|
|
@ -1418,6 +1425,11 @@ void iwl_mld_mac80211_vif_cfg_changed(struct ieee80211_hw *hw,
|
|||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_NAN) {
|
||||
iwl_mld_nan_vif_cfg_changed(mld, vif, changes);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
|
|
@ -1613,7 +1625,7 @@ iwl_mld_mac80211_conf_tx(struct ieee80211_hw *hw,
|
|||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_NAN)
|
||||
if (vif->type == NL80211_IFTYPE_NAN || vif->type == NL80211_IFTYPE_NAN_DATA)
|
||||
return 0;
|
||||
|
||||
link = iwl_mld_link_dereference_check(mld_vif, link_id);
|
||||
|
|
|
|||
|
|
@ -296,3 +296,25 @@ void iwl_mld_handle_nan_dw_end_notif(struct iwl_mld *mld,
|
|||
wdev = ieee80211_vif_to_wdev(mld->nan_device_vif);
|
||||
cfg80211_next_nan_dw_notif(wdev, chan, GFP_KERNEL);
|
||||
}
|
||||
|
||||
void iwl_mld_nan_vif_cfg_changed(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
u64 changes)
|
||||
{
|
||||
struct ieee80211_nan_sched_cfg *sched_cfg = &vif->cfg.nan_sched;
|
||||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
|
||||
bool has_sched = memchr_inv(sched_cfg->schedule, 0,
|
||||
sizeof(sched_cfg->schedule));
|
||||
|
||||
lockdep_assert_wiphy(mld->wiphy);
|
||||
|
||||
if (!(changes & BSS_CHANGED_NAN_LOCAL_SCHED))
|
||||
return;
|
||||
|
||||
if (has_sched && !mld_vif->nan.mac_added) {
|
||||
if (iwl_mld_add_nan_vif(mld, vif))
|
||||
IWL_ERR(mld, "Failed to add NAN vif\n");
|
||||
} else if (!has_sched && mld_vif->nan.mac_added) {
|
||||
iwl_mld_rm_vif(mld, vif);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2025 Intel Corporation
|
||||
* Copyright (C) 2025-2026 Intel Corporation
|
||||
*/
|
||||
#ifndef __iwl_mld_nan_h__
|
||||
#define __iwl_mld_nan_h__
|
||||
|
|
@ -27,5 +27,8 @@ bool iwl_mld_cancel_nan_cluster_notif(struct iwl_mld *mld,
|
|||
bool iwl_mld_cancel_nan_dw_end_notif(struct iwl_mld *mld,
|
||||
struct iwl_rx_packet *pkt,
|
||||
u32 obj_id);
|
||||
void iwl_mld_nan_vif_cfg_changed(struct iwl_mld *mld,
|
||||
struct ieee80211_vif *vif,
|
||||
u64 changes);
|
||||
|
||||
#endif /* __iwl_mld_nan_h__ */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user