Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d339fc89 authored by John W. Linville's avatar John W. Linville
Browse files
parents 9a6f7347 09b1426e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1009,6 +1009,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
	if (old_probe_resp)
		kfree_rcu(old_probe_resp, rcu_head);

	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
		sta_info_flush(local, vlan);
	sta_info_flush(local, sdata);
	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);

+38 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@

#include <linux/nl80211.h>
#include <linux/export.h>
#include <linux/rtnetlink.h>
#include <net/cfg80211.h>
#include "ieee80211_i.h"
#include "driver-ops.h"
@@ -197,6 +198,15 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)

	ctx = container_of(conf, struct ieee80211_chanctx, conf);

	if (sdata->vif.type == NL80211_IFTYPE_AP) {
		struct ieee80211_sub_if_data *vlan;

		/* for the VLAN list */
		ASSERT_RTNL();
		list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
			rcu_assign_pointer(vlan->vif.chanctx_conf, NULL);
	}

	ieee80211_unassign_vif_chanctx(sdata, ctx);
	if (ctx->refcount == 0)
		ieee80211_free_chanctx(local, ctx);
@@ -316,6 +326,15 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
		goto out;
	}

	if (sdata->vif.type == NL80211_IFTYPE_AP) {
		struct ieee80211_sub_if_data *vlan;

		/* for the VLAN list */
		ASSERT_RTNL();
		list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
			rcu_assign_pointer(vlan->vif.chanctx_conf, &ctx->conf);
	}

	ieee80211_recalc_smps_chanctx(local, ctx);
 out:
	mutex_unlock(&local->chanctx_mtx);
@@ -331,6 +350,25 @@ void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
	mutex_unlock(&sdata->local->chanctx_mtx);
}

void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_sub_if_data *ap;
	struct ieee80211_chanctx_conf *conf;

	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
		return;

	ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);

	mutex_lock(&local->chanctx_mtx);

	conf = rcu_dereference_protected(ap->vif.chanctx_conf,
					 lockdep_is_held(&local->chanctx_mtx));
	rcu_assign_pointer(sdata->vif.chanctx_conf, conf);
	mutex_unlock(&local->chanctx_mtx);
}

void ieee80211_iter_chan_contexts_atomic(
	struct ieee80211_hw *hw,
	void (*iter)(struct ieee80211_hw *hw,
+4 −5
Original line number Diff line number Diff line
@@ -703,8 +703,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
	sdata_info(sdata,
		   "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n");

	ieee80211_request_internal_scan(sdata,
			ifibss->ssid, ifibss->ssid_len, NULL);
	ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len,
				    NULL);
}

static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
@@ -802,9 +802,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
					IEEE80211_SCAN_INTERVAL)) {
		sdata_info(sdata, "Trigger new scan to find an IBSS to join\n");

		ieee80211_request_internal_scan(sdata,
				ifibss->ssid, ifibss->ssid_len,
				ifibss->fixed_channel ? ifibss->channel : NULL);
		ieee80211_request_ibss_scan(sdata, ifibss->ssid,
					    ifibss->ssid_len, chan);
	} else {
		int interval = IEEE80211_SCAN_INTERVAL;

+9 −7
Original line number Diff line number Diff line
@@ -92,8 +92,6 @@ struct ieee80211_bss {

	u32 device_ts;

	u8 dtim_period;

	bool wmm_used;
	bool uapsd_supported;

@@ -140,7 +138,6 @@ enum ieee80211_bss_corrupt_data_flags {

/**
 * enum ieee80211_valid_data_flags - BSS valid data flags
 * @IEEE80211_BSS_VALID_DTIM: DTIM data was gathered from non-corrupt IE
 * @IEEE80211_BSS_VALID_WMM: WMM/UAPSD data was gathered from non-corrupt IE
 * @IEEE80211_BSS_VALID_RATES: Supported rates were gathered from non-corrupt IE
 * @IEEE80211_BSS_VALID_ERP: ERP flag was gathered from non-corrupt IE
@@ -151,7 +148,6 @@ enum ieee80211_bss_corrupt_data_flags {
 * beacon/probe response.
 */
enum ieee80211_bss_valid_data_flags {
	IEEE80211_BSS_VALID_DTIM		= BIT(0),
	IEEE80211_BSS_VALID_WMM			= BIT(1),
	IEEE80211_BSS_VALID_RATES		= BIT(2),
	IEEE80211_BSS_VALID_ERP			= BIT(3)
@@ -440,6 +436,7 @@ struct ieee80211_if_managed {
	unsigned long timers_running; /* used for quiesce/restart */
	bool powersave; /* powersave requested for this iface */
	bool broken_ap; /* AP is broken -- turn off powersave */
	u8 dtim_period;
	enum ieee80211_smps_mode req_smps, /* requested smps mode */
				 driver_smps_mode; /* smps mode request */

@@ -773,6 +770,10 @@ struct ieee80211_sub_if_data {
		u32 mntr_flags;
	} u;

	spinlock_t cleanup_stations_lock;
	struct list_head cleanup_stations;
	struct work_struct cleanup_stations_wk;

#ifdef CONFIG_MAC80211_DEBUGFS
	struct {
		struct dentry *dir;
@@ -1329,7 +1330,7 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,

/* scan/BSS handling */
void ieee80211_scan_work(struct work_struct *work);
int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
				const u8 *ssid, u8 ssid_len,
				struct ieee80211_channel *chan);
int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
@@ -1628,6 +1629,7 @@ ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
			  const struct cfg80211_chan_def *chandef,
			  enum ieee80211_chanctx_mode mode);
void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata);

void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
				   struct ieee80211_chanctx *chanctx);
+23 −25
Original line number Diff line number Diff line
@@ -207,17 +207,8 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)

static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
{
	int meshhdrlen;
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);

	meshhdrlen = (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) ? 5 : 0;

	/* FIX: what would be proper limits for MTU?
	 * This interface uses 802.3 frames. */
	if (new_mtu < 256 ||
	    new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) {
	if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN)
		return -EINVAL;
	}

	dev->mtu = new_mtu;
	return 0;
@@ -586,11 +577,13 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)

	switch (sdata->vif.type) {
	case NL80211_IFTYPE_AP_VLAN:
		/* no need to tell driver, but set carrier */
		if (rtnl_dereference(sdata->bss->beacon))
		/* no need to tell driver, but set carrier and chanctx */
		if (rtnl_dereference(sdata->bss->beacon)) {
			ieee80211_vif_vlan_copy_chanctx(sdata);
			netif_carrier_on(dev);
		else
		} else {
			netif_carrier_off(dev);
		}
		break;
	case NL80211_IFTYPE_MONITOR:
		if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
@@ -839,6 +832,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
	switch (sdata->vif.type) {
	case NL80211_IFTYPE_AP_VLAN:
		list_del(&sdata->u.vlan.list);
		rcu_assign_pointer(sdata->vif.chanctx_conf, NULL);
		/* no need to tell driver */
		break;
	case NL80211_IFTYPE_MONITOR:
@@ -865,20 +859,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
		cancel_work_sync(&sdata->work);
		/*
		 * When we get here, the interface is marked down.
		 * Call rcu_barrier() to wait both for the RX path
		 * Call synchronize_rcu() to wait for the RX path
		 * should it be using the interface and enqueuing
		 * frames at this very time on another CPU, and
		 * for the sta free call_rcu callbacks.
		 */
		rcu_barrier();

		/*
		 * free_sta_rcu() enqueues a work for the actual
		 * sta cleanup, so we need to flush it while
		 * sdata is still valid.
		 * frames at this very time on another CPU.
		 */
		flush_workqueue(local->workqueue);

		synchronize_rcu();
		skb_queue_purge(&sdata->skb_queue);

		/*
@@ -1498,6 +1483,15 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
	mutex_unlock(&local->iflist_mtx);
}

static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk)
{
	struct ieee80211_sub_if_data *sdata;

	sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk);

	ieee80211_cleanup_sdata_stas(sdata);
}

int ieee80211_if_add(struct ieee80211_local *local, const char *name,
		     struct wireless_dev **new_wdev, enum nl80211_iftype type,
		     struct vif_params *params)
@@ -1573,6 +1567,10 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,

	INIT_LIST_HEAD(&sdata->key_list);

	spin_lock_init(&sdata->cleanup_stations_lock);
	INIT_LIST_HEAD(&sdata->cleanup_stations);
	INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk);

	for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
		struct ieee80211_supported_band *sband;
		sband = local->hw.wiphy->bands[i];
Loading