Commit 1d04fad3 authored by Ilan Peer's avatar Ilan Peer Committed by Johannes Berg
Browse files

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: default avatarIlan Peer <ilan.peer@intel.com>
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250908140015.92b530ddaedf.I2b6d6f6074e25487303fde573ce764a64f87bdcd@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 04f17cfe
Loading
Loading
Loading
Loading
+113 −23
Original line number Diff line number Diff line
@@ -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,24 +430,13 @@ 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;

	return 0;
	ret = ieee80211_nan_conf_copy(&sdata->u.nan.conf, conf, 0xFFFFFFFF);
	if (ret) {
		ieee80211_stop_nan(wiphy, wdev);
		return ret;
	}

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);
	return 0;
}

static int ieee80211_nan_change_conf(struct wiphy *wiphy,
@@ -366,7 +445,7 @@ static int ieee80211_nan_change_conf(struct wiphy *wiphy,
				     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;
}