wifi: mac80211: Extend support for changing NAN configuration

As 'struct cfg80211_nan_config' was updated, update the relevant
logic to accommodate these changes.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250908140015.92b530ddaedf.I2b6d6f6074e25487303fde573ce764a64f87bdcd@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Ilan Peer 2025-09-08 14:13:07 +03:00 committed by Johannes Berg
parent 04f17cfea2
commit 1d04fad3a4

View File

@ -311,6 +311,96 @@ static void ieee80211_stop_p2p_device(struct wiphy *wiphy,
ieee80211_sdata_stop(IEEE80211_WDEV_TO_SUB_IF(wdev));
}
static void ieee80211_nan_conf_free(struct cfg80211_nan_conf *conf)
{
kfree(conf->cluster_id);
kfree(conf->extra_nan_attrs);
kfree(conf->vendor_elems);
memset(conf, 0, sizeof(*conf));
}
static void ieee80211_stop_nan(struct wiphy *wiphy,
struct wireless_dev *wdev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
if (!sdata->u.nan.started)
return;
drv_stop_nan(sdata->local, sdata);
sdata->u.nan.started = false;
ieee80211_nan_conf_free(&sdata->u.nan.conf);
ieee80211_sdata_stop(sdata);
ieee80211_recalc_idle(sdata->local);
}
static int ieee80211_nan_conf_copy(struct cfg80211_nan_conf *dst,
struct cfg80211_nan_conf *src,
u32 changes)
{
if (changes & CFG80211_NAN_CONF_CHANGED_PREF)
dst->master_pref = src->master_pref;
if (changes & CFG80211_NAN_CONF_CHANGED_BANDS)
dst->bands = src->bands;
if (changes & CFG80211_NAN_CONF_CHANGED_CONFIG) {
dst->scan_period = src->scan_period;
dst->scan_dwell_time = src->scan_dwell_time;
dst->discovery_beacon_interval =
src->discovery_beacon_interval;
dst->enable_dw_notification = src->enable_dw_notification;
memcpy(&dst->band_cfgs, &src->band_cfgs,
sizeof(dst->band_cfgs));
kfree(dst->cluster_id);
dst->cluster_id = NULL;
kfree(dst->extra_nan_attrs);
dst->extra_nan_attrs = NULL;
dst->extra_nan_attrs_len = 0;
kfree(dst->vendor_elems);
dst->vendor_elems = NULL;
dst->vendor_elems_len = 0;
if (src->cluster_id) {
dst->cluster_id = kmemdup(src->cluster_id, ETH_ALEN,
GFP_KERNEL);
if (!dst->cluster_id)
goto no_mem;
}
if (src->extra_nan_attrs && src->extra_nan_attrs_len) {
dst->extra_nan_attrs = kmemdup(src->extra_nan_attrs,
src->extra_nan_attrs_len,
GFP_KERNEL);
if (!dst->extra_nan_attrs)
goto no_mem;
dst->extra_nan_attrs_len = src->extra_nan_attrs_len;
}
if (src->vendor_elems && src->vendor_elems_len) {
dst->vendor_elems = kmemdup(src->vendor_elems,
src->vendor_elems_len,
GFP_KERNEL);
if (!dst->vendor_elems)
goto no_mem;
dst->vendor_elems_len = src->vendor_elems_len;
}
}
return 0;
no_mem:
ieee80211_nan_conf_free(dst);
return -ENOMEM;
}
static int ieee80211_start_nan(struct wiphy *wiphy,
struct wireless_dev *wdev,
struct cfg80211_nan_conf *conf)
@ -340,33 +430,22 @@ static int ieee80211_start_nan(struct wiphy *wiphy,
sdata->u.nan.started = true;
ieee80211_recalc_idle(sdata->local);
sdata->u.nan.conf.master_pref = conf->master_pref;
sdata->u.nan.conf.bands = conf->bands;
ret = ieee80211_nan_conf_copy(&sdata->u.nan.conf, conf, 0xFFFFFFFF);
if (ret) {
ieee80211_stop_nan(wiphy, wdev);
return ret;
}
return 0;
}
static void ieee80211_stop_nan(struct wiphy *wiphy,
struct wireless_dev *wdev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
if (!sdata->u.nan.started)
return;
drv_stop_nan(sdata->local, sdata);
sdata->u.nan.started = false;
ieee80211_sdata_stop(sdata);
ieee80211_recalc_idle(sdata->local);
}
static int ieee80211_nan_change_conf(struct wiphy *wiphy,
struct wireless_dev *wdev,
struct cfg80211_nan_conf *conf,
u32 changes)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
struct cfg80211_nan_conf new_conf;
struct cfg80211_nan_conf new_conf = {};
int ret = 0;
if (sdata->vif.type != NL80211_IFTYPE_NAN)
@ -375,17 +454,28 @@ static int ieee80211_nan_change_conf(struct wiphy *wiphy,
if (!ieee80211_sdata_running(sdata))
return -ENETDOWN;
new_conf = sdata->u.nan.conf;
if (!changes)
return 0;
if (changes & CFG80211_NAN_CONF_CHANGED_PREF)
new_conf.master_pref = conf->master_pref;
/* First make a full copy of the previous configuration and then apply
* the changes. This might be a little wasteful, but it is simpler.
*/
ret = ieee80211_nan_conf_copy(&new_conf, &sdata->u.nan.conf,
0xFFFFFFFF);
if (ret < 0)
return ret;
if (changes & CFG80211_NAN_CONF_CHANGED_BANDS)
new_conf.bands = conf->bands;
ret = ieee80211_nan_conf_copy(&new_conf, conf, changes);
if (ret < 0)
return ret;
ret = drv_nan_change_conf(sdata->local, sdata, &new_conf, changes);
if (!ret)
if (ret) {
ieee80211_nan_conf_free(&new_conf);
} else {
ieee80211_nan_conf_free(&sdata->u.nan.conf);
sdata->u.nan.conf = new_conf;
}
return ret;
}