Commit 52b4810b authored by Ilan Peer's avatar Ilan Peer Committed by Johannes Berg
Browse files

mac80211: Remove support for changing AP SMPS mode



The SMPS feature is defined in the specification only to be
used by non-AP stations and not by APs, so remove the support
for changing the AP's SMPS mode dynamically.

Signed-off-by: default avatarIlan Peer <ilan.peer@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/20200131111300.891737-20-luca@coelho.fi


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent c4d800dc
Loading
Loading
Loading
Loading
+4 −97
Original line number Diff line number Diff line
@@ -990,20 +990,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
	if (old)
		return -EALREADY;

	switch (params->smps_mode) {
	case NL80211_SMPS_OFF:
	if (params->smps_mode != NL80211_SMPS_OFF)
		return -ENOTSUPP;

	sdata->smps_mode = IEEE80211_SMPS_OFF;
		break;
	case NL80211_SMPS_STATIC:
		sdata->smps_mode = IEEE80211_SMPS_STATIC;
		break;
	case NL80211_SMPS_DYNAMIC:
		sdata->smps_mode = IEEE80211_SMPS_DYNAMIC;
		break;
	default:
		return -EINVAL;
	}
	sdata->u.ap.req_smps = sdata->smps_mode;

	sdata->needed_rx_chains = sdata->local->rx_chains;

@@ -1169,7 +1159,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
	kfree_rcu(old_beacon, rcu_head);
	if (old_probe_resp)
		kfree_rcu(old_probe_resp, rcu_head);
	sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;

	kfree(sdata->vif.bss_conf.ftmr_params);
	sdata->vif.bss_conf.ftmr_params = NULL;
@@ -1694,20 +1683,6 @@ static int ieee80211_change_station(struct wiphy *wiphy,

	mutex_unlock(&local->sta_mtx);

	if ((sdata->vif.type == NL80211_IFTYPE_AP ||
	     sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
	    sta->known_smps_mode != sta->sdata->bss->req_smps &&
	    test_sta_flag(sta, WLAN_STA_AUTHORIZED) &&
	    sta_info_tx_streams(sta) != 1) {
		ht_dbg(sta->sdata,
		       "%pM just authorized and MIMO capable - update SMPS\n",
		       sta->sta.addr);
		ieee80211_send_smps_action(sta->sdata,
			sta->sdata->bss->req_smps,
			sta->sta.addr,
			sta->sdata->vif.bss_conf.bssid);
	}

	if (sdata->vif.type == NL80211_IFTYPE_STATION &&
	    params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
		ieee80211_recalc_ps(local);
@@ -2639,74 +2614,6 @@ static int ieee80211_testmode_dump(struct wiphy *wiphy,
}
#endif

int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
				enum ieee80211_smps_mode smps_mode)
{
	struct sta_info *sta;
	enum ieee80211_smps_mode old_req;

	if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP))
		return -EINVAL;

	if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
		return 0;

	old_req = sdata->u.ap.req_smps;
	sdata->u.ap.req_smps = smps_mode;

	/* AUTOMATIC doesn't mean much for AP - don't allow it */
	if (old_req == smps_mode ||
	    smps_mode == IEEE80211_SMPS_AUTOMATIC)
		return 0;

	ht_dbg(sdata,
	       "SMPS %d requested in AP mode, sending Action frame to %d stations\n",
	       smps_mode, atomic_read(&sdata->u.ap.num_mcast_sta));

	mutex_lock(&sdata->local->sta_mtx);
	list_for_each_entry(sta, &sdata->local->sta_list, list) {
		/*
		 * Only stations associated to our AP and
		 * associated VLANs
		 */
		if (sta->sdata->bss != &sdata->u.ap)
			continue;

		/* This station doesn't support MIMO - skip it */
		if (sta_info_tx_streams(sta) == 1)
			continue;

		/*
		 * Don't wake up a STA just to send the action frame
		 * unless we are getting more restrictive.
		 */
		if (test_sta_flag(sta, WLAN_STA_PS_STA) &&
		    !ieee80211_smps_is_restrictive(sta->known_smps_mode,
						   smps_mode)) {
			ht_dbg(sdata, "Won't send SMPS to sleeping STA %pM\n",
			       sta->sta.addr);
			continue;
		}

		/*
		 * If the STA is not authorized, wait until it gets
		 * authorized and the action frame will be sent then.
		 */
		if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED))
			continue;

		ht_dbg(sdata, "Sending SMPS to %pM\n", sta->sta.addr);
		ieee80211_send_smps_action(sdata, smps_mode, sta->sta.addr,
					   sdata->vif.bss_conf.bssid);
	}
	mutex_unlock(&sdata->local->sta_mtx);

	sdata->smps_mode = smps_mode;
	ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps);

	return 0;
}

int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
				 enum ieee80211_smps_mode smps_mode)
{
+3 −10
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
/*
 * Copyright (c) 2006	Jiri Benc <jbenc@suse.cz>
 * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
 * Copyright (C) 2020 Intel Corporation
 */

#include <linux/kernel.h>
@@ -254,15 +255,11 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
	     smps_mode == IEEE80211_SMPS_AUTOMATIC))
		return -EINVAL;

	if (sdata->vif.type != NL80211_IFTYPE_STATION &&
	    sdata->vif.type != NL80211_IFTYPE_AP)
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
		return -EOPNOTSUPP;

	sdata_lock(sdata);
	if (sdata->vif.type == NL80211_IFTYPE_STATION)
	err = __ieee80211_request_smps_mgd(sdata, smps_mode);
	else
		err = __ieee80211_request_smps_ap(sdata, smps_mode);
	sdata_unlock(sdata);

	return err;
@@ -282,10 +279,6 @@ static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata,
		return snprintf(buf, buflen, "request: %s\nused: %s\n",
				smps_modes[sdata->u.mgd.req_smps],
				smps_modes[sdata->smps_mode]);
	if (sdata->vif.type == NL80211_IFTYPE_AP)
		return snprintf(buf, buflen, "request: %s\nused: %s\n",
				smps_modes[sdata->u.ap.req_smps],
				smps_modes[sdata->smps_mode]);
	return -EINVAL;
}

+0 −22
Original line number Diff line number Diff line
@@ -550,19 +550,6 @@ void ieee80211_request_smps_mgd_work(struct work_struct *work)
	sdata_unlock(sdata);
}

void ieee80211_request_smps_ap_work(struct work_struct *work)
{
	struct ieee80211_sub_if_data *sdata =
		container_of(work, struct ieee80211_sub_if_data,
			     u.ap.request_smps_work);

	sdata_lock(sdata);
	if (sdata_dereference(sdata->u.ap.beacon, sdata))
		__ieee80211_request_smps_ap(sdata,
					    sdata->u.ap.driver_smps_mode);
	sdata_unlock(sdata);
}

void ieee80211_request_smps(struct ieee80211_vif *vif,
			    enum ieee80211_smps_mode smps_mode)
{
@@ -578,15 +565,6 @@ void ieee80211_request_smps(struct ieee80211_vif *vif,
		sdata->u.mgd.driver_smps_mode = smps_mode;
		ieee80211_queue_work(&sdata->local->hw,
				     &sdata->u.mgd.request_smps_work);
	} else {
		/* AUTOMATIC is meaningless in AP mode */
		if (WARN_ON_ONCE(smps_mode == IEEE80211_SMPS_AUTOMATIC))
			return;
		if (sdata->u.ap.driver_smps_mode == smps_mode)
			return;
		sdata->u.ap.driver_smps_mode = smps_mode;
		ieee80211_queue_work(&sdata->local->hw,
				     &sdata->u.ap.request_smps_work);
	}
}
/* this might change ... don't want non-open drivers using it */
+1 −6
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
 * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
 * Copyright 2007-2010	Johannes Berg <johannes@sipsolutions.net>
 * Copyright 2013-2015  Intel Mobile Communications GmbH
 * Copyright (C) 2018-2019 Intel Corporation
 * Copyright (C) 2018-2020 Intel Corporation
 */

#ifndef IEEE80211_I_H
@@ -292,10 +292,7 @@ struct ieee80211_if_ap {

	struct ps_data ps;
	atomic_t num_mcast_sta; /* number of stations receiving multicast */
	enum ieee80211_smps_mode req_smps, /* requested smps mode */
			 driver_smps_mode; /* smps mode request */

	struct work_struct request_smps_work;
	bool multicast_to_unicast;
};

@@ -2148,8 +2145,6 @@ u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata,
			    enum nl80211_band band, u32 *basic_rates);
int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
				 enum ieee80211_smps_mode smps_mode);
int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
				enum ieee80211_smps_mode smps_mode);
void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata);
void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata);

+1 −7
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@
 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
 * Copyright 2013-2014  Intel Mobile Communications GmbH
 * Copyright (c) 2016        Intel Deutschland GmbH
 * Copyright (C) 2018-2019 Intel Corporation
 * Copyright (C) 2018-2020 Intel Corporation
 */
#include <linux/slab.h>
#include <linux/kernel.h>
@@ -824,9 +824,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
	case NL80211_IFTYPE_ADHOC:
		ieee80211_ibss_stop(sdata);
		break;
	case NL80211_IFTYPE_AP:
		cancel_work_sync(&sdata->u.ap.request_smps_work);
		break;
	case NL80211_IFTYPE_MONITOR:
		if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES)
			break;
@@ -1494,10 +1491,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
	case NL80211_IFTYPE_AP:
		skb_queue_head_init(&sdata->u.ap.ps.bc_buf);
		INIT_LIST_HEAD(&sdata->u.ap.vlans);
		INIT_WORK(&sdata->u.ap.request_smps_work,
			  ieee80211_request_smps_ap_work);
		sdata->vif.bss_conf.bssid = sdata->vif.addr;
		sdata->u.ap.req_smps = IEEE80211_SMPS_OFF;
		break;
	case NL80211_IFTYPE_P2P_CLIENT:
		type = NL80211_IFTYPE_STATION;
Loading