xref: /openbmc/linux/net/mac80211/iface.c (revision 699cb58c8a52ff39bf659bff7971893ebe111bf2)
12c8dccc7SJohannes Berg /*
2c5d54fbfSJohannes Berg  * Interface handling
30d143fe1SJohannes Berg  *
42c8dccc7SJohannes Berg  * Copyright 2002-2005, Instant802 Networks, Inc.
52c8dccc7SJohannes Berg  * Copyright 2005-2006, Devicescape Software, Inc.
62c8dccc7SJohannes Berg  * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
775636525SJohannes Berg  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
8d98ad83eSJohannes Berg  * Copyright 2013-2014  Intel Mobile Communications GmbH
9d2941df8SJohannes Berg  * Copyright (c) 2016        Intel Deutschland GmbH
102c8dccc7SJohannes Berg  *
112c8dccc7SJohannes Berg  * This program is free software; you can redistribute it and/or modify
122c8dccc7SJohannes Berg  * it under the terms of the GNU General Public License version 2 as
132c8dccc7SJohannes Berg  * published by the Free Software Foundation.
142c8dccc7SJohannes Berg  */
155a0e3ad6STejun Heo #include <linux/slab.h>
162c8dccc7SJohannes Berg #include <linux/kernel.h>
172c8dccc7SJohannes Berg #include <linux/if_arp.h>
182c8dccc7SJohannes Berg #include <linux/netdevice.h>
192c8dccc7SJohannes Berg #include <linux/rtnetlink.h>
202c8dccc7SJohannes Berg #include <net/mac80211.h>
21cf0277e7SJohannes Berg #include <net/ieee80211_radiotap.h>
222c8dccc7SJohannes Berg #include "ieee80211_i.h"
232c8dccc7SJohannes Berg #include "sta_info.h"
242c8dccc7SJohannes Berg #include "debugfs_netdev.h"
252c8dccc7SJohannes Berg #include "mesh.h"
260d143fe1SJohannes Berg #include "led.h"
2724487981SJohannes Berg #include "driver-ops.h"
28cf0277e7SJohannes Berg #include "wme.h"
291be7fe8dSBill Jordan #include "rate.h"
302c8dccc7SJohannes Berg 
31c771c9d8SJohannes Berg /**
32c771c9d8SJohannes Berg  * DOC: Interface list locking
33c771c9d8SJohannes Berg  *
34c771c9d8SJohannes Berg  * The interface list in each struct ieee80211_local is protected
35c771c9d8SJohannes Berg  * three-fold:
36c771c9d8SJohannes Berg  *
37c771c9d8SJohannes Berg  * (1) modifications may only be done under the RTNL
38c771c9d8SJohannes Berg  * (2) modifications and readers are protected against each other by
39c771c9d8SJohannes Berg  *     the iflist_mtx.
40c771c9d8SJohannes Berg  * (3) modifications are done in an RCU manner so atomic readers
41c771c9d8SJohannes Berg  *     can traverse the list in RCU-safe blocks.
42c771c9d8SJohannes Berg  *
43c771c9d8SJohannes Berg  * As a consequence, reads (traversals) of the list can be protected
44c771c9d8SJohannes Berg  * by either the RTNL, the iflist_mtx or RCU.
45c771c9d8SJohannes Berg  */
46c771c9d8SJohannes Berg 
4742bd20d9SAviya Erenfeld static void ieee80211_iface_work(struct work_struct *work);
4842bd20d9SAviya Erenfeld 
491ea6f9c0SJohannes Berg bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
501ea6f9c0SJohannes Berg {
511ea6f9c0SJohannes Berg 	struct ieee80211_chanctx_conf *chanctx_conf;
521ea6f9c0SJohannes Berg 	int power;
531ea6f9c0SJohannes Berg 
541ea6f9c0SJohannes Berg 	rcu_read_lock();
551ea6f9c0SJohannes Berg 	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
561ea6f9c0SJohannes Berg 	if (!chanctx_conf) {
571ea6f9c0SJohannes Berg 		rcu_read_unlock();
581ea6f9c0SJohannes Berg 		return false;
591ea6f9c0SJohannes Berg 	}
601ea6f9c0SJohannes Berg 
610430c883SSimon Wunderlich 	power = ieee80211_chandef_max_power(&chanctx_conf->def);
621ea6f9c0SJohannes Berg 	rcu_read_unlock();
631ea6f9c0SJohannes Berg 
641ea6f9c0SJohannes Berg 	if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL)
651ea6f9c0SJohannes Berg 		power = min(power, sdata->user_power_level);
661ea6f9c0SJohannes Berg 
671ea6f9c0SJohannes Berg 	if (sdata->ap_power_level != IEEE80211_UNSET_POWER_LEVEL)
681ea6f9c0SJohannes Berg 		power = min(power, sdata->ap_power_level);
691ea6f9c0SJohannes Berg 
701ea6f9c0SJohannes Berg 	if (power != sdata->vif.bss_conf.txpower) {
711ea6f9c0SJohannes Berg 		sdata->vif.bss_conf.txpower = power;
721ea6f9c0SJohannes Berg 		ieee80211_hw_config(sdata->local, 0);
731ea6f9c0SJohannes Berg 		return true;
741ea6f9c0SJohannes Berg 	}
751ea6f9c0SJohannes Berg 
761ea6f9c0SJohannes Berg 	return false;
771ea6f9c0SJohannes Berg }
781ea6f9c0SJohannes Berg 
79db82d8a9SLorenzo Bianconi void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata,
80db82d8a9SLorenzo Bianconi 			      bool update_bss)
811ea6f9c0SJohannes Berg {
825ad11b50SEmmanuel Grumbach 	if (__ieee80211_recalc_txpower(sdata) ||
835ad11b50SEmmanuel Grumbach 	    (update_bss && ieee80211_sdata_running(sdata)))
841ea6f9c0SJohannes Berg 		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER);
851ea6f9c0SJohannes Berg }
86c771c9d8SJohannes Berg 
8762a40a15SJohannes Berg static u32 __ieee80211_idle_off(struct ieee80211_local *local)
88cc45ae54SJohannes Berg {
89cc45ae54SJohannes Berg 	if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE))
90cc45ae54SJohannes Berg 		return 0;
91cc45ae54SJohannes Berg 
92cc45ae54SJohannes Berg 	local->hw.conf.flags &= ~IEEE80211_CONF_IDLE;
93cc45ae54SJohannes Berg 	return IEEE80211_CONF_CHANGE_IDLE;
94cc45ae54SJohannes Berg }
95cc45ae54SJohannes Berg 
9662a40a15SJohannes Berg static u32 __ieee80211_idle_on(struct ieee80211_local *local)
97cc45ae54SJohannes Berg {
98cc45ae54SJohannes Berg 	if (local->hw.conf.flags & IEEE80211_CONF_IDLE)
99cc45ae54SJohannes Berg 		return 0;
100cc45ae54SJohannes Berg 
1013b24f4c6SEmmanuel Grumbach 	ieee80211_flush_queues(local, NULL, false);
102cc45ae54SJohannes Berg 
103cc45ae54SJohannes Berg 	local->hw.conf.flags |= IEEE80211_CONF_IDLE;
104cc45ae54SJohannes Berg 	return IEEE80211_CONF_CHANGE_IDLE;
105cc45ae54SJohannes Berg }
106cc45ae54SJohannes Berg 
10762a40a15SJohannes Berg static u32 __ieee80211_recalc_idle(struct ieee80211_local *local,
10862a40a15SJohannes Berg 				   bool force_active)
109cc45ae54SJohannes Berg {
1101d5e1266SJohannes Berg 	bool working, scanning, active;
111cc45ae54SJohannes Berg 	unsigned int led_trig_start = 0, led_trig_stop = 0;
112cc45ae54SJohannes Berg 
113cc45ae54SJohannes Berg 	lockdep_assert_held(&local->mtx);
114cc45ae54SJohannes Berg 
11562a40a15SJohannes Berg 	active = force_active ||
11662a40a15SJohannes Berg 		 !list_empty(&local->chanctx_list) ||
11762a40a15SJohannes Berg 		 local->monitors;
118cc45ae54SJohannes Berg 
1191d5e1266SJohannes Berg 	working = !local->ops->remain_on_channel &&
1201d5e1266SJohannes Berg 		  !list_empty(&local->roc_list);
121cc45ae54SJohannes Berg 
122f1e3e051SJohannes Berg 	scanning = test_bit(SCAN_SW_SCANNING, &local->scanning) ||
123f1e3e051SJohannes Berg 		   test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning);
124cc45ae54SJohannes Berg 
125cc45ae54SJohannes Berg 	if (working || scanning)
126cc45ae54SJohannes Berg 		led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK;
127cc45ae54SJohannes Berg 	else
128cc45ae54SJohannes Berg 		led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK;
129cc45ae54SJohannes Berg 
130fd0f979aSJohannes Berg 	if (active)
131cc45ae54SJohannes Berg 		led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
132cc45ae54SJohannes Berg 	else
133cc45ae54SJohannes Berg 		led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
134cc45ae54SJohannes Berg 
135cc45ae54SJohannes Berg 	ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop);
136cc45ae54SJohannes Berg 
137fd0f979aSJohannes Berg 	if (working || scanning || active)
13862a40a15SJohannes Berg 		return __ieee80211_idle_off(local);
13962a40a15SJohannes Berg 	return __ieee80211_idle_on(local);
14062a40a15SJohannes Berg }
14162a40a15SJohannes Berg 
14262a40a15SJohannes Berg u32 ieee80211_idle_off(struct ieee80211_local *local)
14362a40a15SJohannes Berg {
14462a40a15SJohannes Berg 	return __ieee80211_recalc_idle(local, true);
14562a40a15SJohannes Berg }
14662a40a15SJohannes Berg 
14762a40a15SJohannes Berg void ieee80211_recalc_idle(struct ieee80211_local *local)
14862a40a15SJohannes Berg {
14962a40a15SJohannes Berg 	u32 change = __ieee80211_recalc_idle(local, false);
150fd0f979aSJohannes Berg 	if (change)
151fd0f979aSJohannes Berg 		ieee80211_hw_config(local, change);
152cc45ae54SJohannes Berg }
153cc45ae54SJohannes Berg 
1543899ba90SJohn W. Linville static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr,
15531eba5bcSFelix Fietkau 				bool check_dup)
156478622e8SHelmut Schaa {
157ac20976dSHelmut Schaa 	struct ieee80211_local *local = sdata->local;
158ac20976dSHelmut Schaa 	struct ieee80211_sub_if_data *iter;
159478622e8SHelmut Schaa 	u64 new, mask, tmp;
160478622e8SHelmut Schaa 	u8 *m;
161478622e8SHelmut Schaa 	int ret = 0;
162478622e8SHelmut Schaa 
163478622e8SHelmut Schaa 	if (is_zero_ether_addr(local->hw.wiphy->addr_mask))
164478622e8SHelmut Schaa 		return 0;
165478622e8SHelmut Schaa 
166478622e8SHelmut Schaa 	m = addr;
167478622e8SHelmut Schaa 	new =	((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
168478622e8SHelmut Schaa 		((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
169478622e8SHelmut Schaa 		((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
170478622e8SHelmut Schaa 
171478622e8SHelmut Schaa 	m = local->hw.wiphy->addr_mask;
172478622e8SHelmut Schaa 	mask =	((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
173478622e8SHelmut Schaa 		((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
174478622e8SHelmut Schaa 		((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
175478622e8SHelmut Schaa 
17631eba5bcSFelix Fietkau 	if (!check_dup)
17731eba5bcSFelix Fietkau 		return ret;
178478622e8SHelmut Schaa 
179478622e8SHelmut Schaa 	mutex_lock(&local->iflist_mtx);
180ac20976dSHelmut Schaa 	list_for_each_entry(iter, &local->interfaces, list) {
181ac20976dSHelmut Schaa 		if (iter == sdata)
182478622e8SHelmut Schaa 			continue;
183478622e8SHelmut Schaa 
1843899ba90SJohn W. Linville 		if (iter->vif.type == NL80211_IFTYPE_MONITOR &&
185d8212184SAviya Erenfeld 		    !(iter->u.mntr.flags & MONITOR_FLAG_ACTIVE))
186ac20976dSHelmut Schaa 			continue;
187ac20976dSHelmut Schaa 
188ac20976dSHelmut Schaa 		m = iter->vif.addr;
189478622e8SHelmut Schaa 		tmp =	((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
190478622e8SHelmut Schaa 			((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
191478622e8SHelmut Schaa 			((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
192478622e8SHelmut Schaa 
193478622e8SHelmut Schaa 		if ((new & ~mask) != (tmp & ~mask)) {
194478622e8SHelmut Schaa 			ret = -EINVAL;
195478622e8SHelmut Schaa 			break;
196478622e8SHelmut Schaa 		}
197478622e8SHelmut Schaa 	}
198478622e8SHelmut Schaa 	mutex_unlock(&local->iflist_mtx);
199478622e8SHelmut Schaa 
200478622e8SHelmut Schaa 	return ret;
201478622e8SHelmut Schaa }
202478622e8SHelmut Schaa 
20347846c9bSJohannes Berg static int ieee80211_change_mac(struct net_device *dev, void *addr)
20447846c9bSJohannes Berg {
20547846c9bSJohannes Berg 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
206fc5f7577SKalle Valo 	struct sockaddr *sa = addr;
20731eba5bcSFelix Fietkau 	bool check_dup = true;
20847846c9bSJohannes Berg 	int ret;
20947846c9bSJohannes Berg 
2109607e6b6SJohannes Berg 	if (ieee80211_sdata_running(sdata))
21147846c9bSJohannes Berg 		return -EBUSY;
21247846c9bSJohannes Berg 
21331eba5bcSFelix Fietkau 	if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
214d8212184SAviya Erenfeld 	    !(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
21531eba5bcSFelix Fietkau 		check_dup = false;
21631eba5bcSFelix Fietkau 
2173899ba90SJohn W. Linville 	ret = ieee80211_verify_mac(sdata, sa->sa_data, check_dup);
218478622e8SHelmut Schaa 	if (ret)
219478622e8SHelmut Schaa 		return ret;
220478622e8SHelmut Schaa 
221fc5f7577SKalle Valo 	ret = eth_mac_addr(dev, sa);
22247846c9bSJohannes Berg 
22347846c9bSJohannes Berg 	if (ret == 0)
224fc5f7577SKalle Valo 		memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
22547846c9bSJohannes Berg 
22647846c9bSJohannes Berg 	return ret;
22747846c9bSJohannes Berg }
22847846c9bSJohannes Berg 
2290d143fe1SJohannes Berg static inline int identical_mac_addr_allowed(int type1, int type2)
2300d143fe1SJohannes Berg {
2310d143fe1SJohannes Berg 	return type1 == NL80211_IFTYPE_MONITOR ||
2320d143fe1SJohannes Berg 		type2 == NL80211_IFTYPE_MONITOR ||
233f142c6b9SJohannes Berg 		type1 == NL80211_IFTYPE_P2P_DEVICE ||
234f142c6b9SJohannes Berg 		type2 == NL80211_IFTYPE_P2P_DEVICE ||
2350d143fe1SJohannes Berg 		(type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_WDS) ||
2360d143fe1SJohannes Berg 		(type1 == NL80211_IFTYPE_WDS &&
2370d143fe1SJohannes Berg 			(type2 == NL80211_IFTYPE_WDS ||
2380d143fe1SJohannes Berg 			 type2 == NL80211_IFTYPE_AP)) ||
2390d143fe1SJohannes Berg 		(type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_AP_VLAN) ||
2400d143fe1SJohannes Berg 		(type1 == NL80211_IFTYPE_AP_VLAN &&
2410d143fe1SJohannes Berg 			(type2 == NL80211_IFTYPE_AP ||
2420d143fe1SJohannes Berg 			 type2 == NL80211_IFTYPE_AP_VLAN));
2430d143fe1SJohannes Berg }
2440d143fe1SJohannes Berg 
24587490f6dSJohannes Berg static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
24687490f6dSJohannes Berg 					    enum nl80211_iftype iftype)
2470d143fe1SJohannes Berg {
248b4a4bf5dSJohannes Berg 	struct ieee80211_local *local = sdata->local;
24987490f6dSJohannes Berg 	struct ieee80211_sub_if_data *nsdata;
250b6a55015SLuciano Coelho 	int ret;
2510d143fe1SJohannes Berg 
25287490f6dSJohannes Berg 	ASSERT_RTNL();
2530d143fe1SJohannes Berg 
2540d143fe1SJohannes Berg 	/* we hold the RTNL here so can safely walk the list */
2550d143fe1SJohannes Berg 	list_for_each_entry(nsdata, &local->interfaces, list) {
256371a255eSJohannes Berg 		if (nsdata != sdata && ieee80211_sdata_running(nsdata)) {
2570d143fe1SJohannes Berg 			/*
258239281f8SRostislav Lisovy 			 * Only OCB and monitor mode may coexist
259239281f8SRostislav Lisovy 			 */
260239281f8SRostislav Lisovy 			if ((sdata->vif.type == NL80211_IFTYPE_OCB &&
261239281f8SRostislav Lisovy 			     nsdata->vif.type != NL80211_IFTYPE_MONITOR) ||
262239281f8SRostislav Lisovy 			    (sdata->vif.type != NL80211_IFTYPE_MONITOR &&
263239281f8SRostislav Lisovy 			     nsdata->vif.type == NL80211_IFTYPE_OCB))
264239281f8SRostislav Lisovy 				return -EBUSY;
265239281f8SRostislav Lisovy 
266239281f8SRostislav Lisovy 			/*
2670d143fe1SJohannes Berg 			 * Allow only a single IBSS interface to be up at any
2680d143fe1SJohannes Berg 			 * time. This is restricted because beacon distribution
2690d143fe1SJohannes Berg 			 * cannot work properly if both are in the same IBSS.
2700d143fe1SJohannes Berg 			 *
2710d143fe1SJohannes Berg 			 * To remove this restriction we'd have to disallow them
2720d143fe1SJohannes Berg 			 * from setting the same SSID on different IBSS interfaces
2730d143fe1SJohannes Berg 			 * belonging to the same hardware. Then, however, we're
2740d143fe1SJohannes Berg 			 * faced with having to adopt two different TSF timers...
2750d143fe1SJohannes Berg 			 */
27687490f6dSJohannes Berg 			if (iftype == NL80211_IFTYPE_ADHOC &&
2770d143fe1SJohannes Berg 			    nsdata->vif.type == NL80211_IFTYPE_ADHOC)
2780d143fe1SJohannes Berg 				return -EBUSY;
27973da7d5bSSimon Wunderlich 			/*
28073da7d5bSSimon Wunderlich 			 * will not add another interface while any channel
28173da7d5bSSimon Wunderlich 			 * switch is active.
28273da7d5bSSimon Wunderlich 			 */
28373da7d5bSSimon Wunderlich 			if (nsdata->vif.csa_active)
28473da7d5bSSimon Wunderlich 				return -EBUSY;
2850d143fe1SJohannes Berg 
2860d143fe1SJohannes Berg 			/*
2870d143fe1SJohannes Berg 			 * The remaining checks are only performed for interfaces
2880d143fe1SJohannes Berg 			 * with the same MAC address.
2890d143fe1SJohannes Berg 			 */
290371a255eSJohannes Berg 			if (!ether_addr_equal(sdata->vif.addr,
291371a255eSJohannes Berg 					      nsdata->vif.addr))
2920d143fe1SJohannes Berg 				continue;
2930d143fe1SJohannes Berg 
2940d143fe1SJohannes Berg 			/*
2950d143fe1SJohannes Berg 			 * check whether it may have the same address
2960d143fe1SJohannes Berg 			 */
29787490f6dSJohannes Berg 			if (!identical_mac_addr_allowed(iftype,
2980d143fe1SJohannes Berg 							nsdata->vif.type))
2990d143fe1SJohannes Berg 				return -ENOTUNIQ;
3000d143fe1SJohannes Berg 
3010d143fe1SJohannes Berg 			/*
3020d143fe1SJohannes Berg 			 * can only add VLANs to enabled APs
3030d143fe1SJohannes Berg 			 */
30487490f6dSJohannes Berg 			if (iftype == NL80211_IFTYPE_AP_VLAN &&
3050d143fe1SJohannes Berg 			    nsdata->vif.type == NL80211_IFTYPE_AP)
3060d143fe1SJohannes Berg 				sdata->bss = &nsdata->u.ap;
3070d143fe1SJohannes Berg 		}
3080d143fe1SJohannes Berg 	}
3090d143fe1SJohannes Berg 
310b6a55015SLuciano Coelho 	mutex_lock(&local->chanctx_mtx);
311b6a55015SLuciano Coelho 	ret = ieee80211_check_combinations(sdata, NULL, 0, 0);
312b6a55015SLuciano Coelho 	mutex_unlock(&local->chanctx_mtx);
313b6a55015SLuciano Coelho 	return ret;
31487490f6dSJohannes Berg }
31587490f6dSJohannes Berg 
316a9865538SJohannes Berg static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata,
317a9865538SJohannes Berg 				  enum nl80211_iftype iftype)
3183a25a8c8SJohannes Berg {
3193a25a8c8SJohannes Berg 	int n_queues = sdata->local->hw.queues;
3203a25a8c8SJohannes Berg 	int i;
3213a25a8c8SJohannes Berg 
322708d50edSAyala Beker 	if (iftype == NL80211_IFTYPE_NAN)
323708d50edSAyala Beker 		return 0;
324708d50edSAyala Beker 
325a9865538SJohannes Berg 	if (iftype != NL80211_IFTYPE_P2P_DEVICE) {
3263a25a8c8SJohannes Berg 		for (i = 0; i < IEEE80211_NUM_ACS; i++) {
3273a25a8c8SJohannes Berg 			if (WARN_ON_ONCE(sdata->vif.hw_queue[i] ==
3283a25a8c8SJohannes Berg 					 IEEE80211_INVAL_HW_QUEUE))
3293a25a8c8SJohannes Berg 				return -EINVAL;
3303a25a8c8SJohannes Berg 			if (WARN_ON_ONCE(sdata->vif.hw_queue[i] >=
3313a25a8c8SJohannes Berg 					 n_queues))
3323a25a8c8SJohannes Berg 				return -EINVAL;
3333a25a8c8SJohannes Berg 		}
3340ef24e52SIlan Peer 	}
3353a25a8c8SJohannes Berg 
336a9865538SJohannes Berg 	if ((iftype != NL80211_IFTYPE_AP &&
337a9865538SJohannes Berg 	     iftype != NL80211_IFTYPE_P2P_GO &&
338a9865538SJohannes Berg 	     iftype != NL80211_IFTYPE_MESH_POINT) ||
33930686bf7SJohannes Berg 	    !ieee80211_hw_check(&sdata->local->hw, QUEUE_CONTROL)) {
3403a25a8c8SJohannes Berg 		sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;
3413a25a8c8SJohannes Berg 		return 0;
3423a25a8c8SJohannes Berg 	}
3433a25a8c8SJohannes Berg 
3443a25a8c8SJohannes Berg 	if (WARN_ON_ONCE(sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE))
3453a25a8c8SJohannes Berg 		return -EINVAL;
3463a25a8c8SJohannes Berg 
3473a25a8c8SJohannes Berg 	if (WARN_ON_ONCE(sdata->vif.cab_queue >= n_queues))
3483a25a8c8SJohannes Berg 		return -EINVAL;
3493a25a8c8SJohannes Berg 
3503a25a8c8SJohannes Berg 	return 0;
3513a25a8c8SJohannes Berg }
3523a25a8c8SJohannes Berg 
35385416a4fSChristian Lamparter void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
35485416a4fSChristian Lamparter 				    const int offset)
35585416a4fSChristian Lamparter {
35685416a4fSChristian Lamparter 	struct ieee80211_local *local = sdata->local;
357d8212184SAviya Erenfeld 	u32 flags = sdata->u.mntr.flags;
35885416a4fSChristian Lamparter 
35985416a4fSChristian Lamparter #define ADJUST(_f, _s)	do {					\
36085416a4fSChristian Lamparter 	if (flags & MONITOR_FLAG_##_f)				\
36185416a4fSChristian Lamparter 		local->fif_##_s += offset;			\
36285416a4fSChristian Lamparter 	} while (0)
36385416a4fSChristian Lamparter 
36485416a4fSChristian Lamparter 	ADJUST(FCSFAIL, fcsfail);
36585416a4fSChristian Lamparter 	ADJUST(PLCPFAIL, plcpfail);
36685416a4fSChristian Lamparter 	ADJUST(CONTROL, control);
36785416a4fSChristian Lamparter 	ADJUST(CONTROL, pspoll);
36885416a4fSChristian Lamparter 	ADJUST(OTHER_BSS, other_bss);
36985416a4fSChristian Lamparter 
37085416a4fSChristian Lamparter #undef ADJUST
37185416a4fSChristian Lamparter }
37285416a4fSChristian Lamparter 
3733a25a8c8SJohannes Berg static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
3743a25a8c8SJohannes Berg {
3753a25a8c8SJohannes Berg 	struct ieee80211_local *local = sdata->local;
3763a25a8c8SJohannes Berg 	int i;
3773a25a8c8SJohannes Berg 
3783a25a8c8SJohannes Berg 	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
37930686bf7SJohannes Berg 		if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL))
3803a25a8c8SJohannes Berg 			sdata->vif.hw_queue[i] = IEEE80211_INVAL_HW_QUEUE;
381a9d3c05cSJohannes Berg 		else if (local->hw.queues >= IEEE80211_NUM_ACS)
3823a25a8c8SJohannes Berg 			sdata->vif.hw_queue[i] = i;
383a9d3c05cSJohannes Berg 		else
384a9d3c05cSJohannes Berg 			sdata->vif.hw_queue[i] = 0;
3853a25a8c8SJohannes Berg 	}
3863a25a8c8SJohannes Berg 	sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;
3873a25a8c8SJohannes Berg }
3883a25a8c8SJohannes Berg 
3893c3e21e7SJohannes Berg int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
3904b6f1dd6SJohannes Berg {
3914b6f1dd6SJohannes Berg 	struct ieee80211_sub_if_data *sdata;
3928b305780SJohannes Berg 	int ret;
3934b6f1dd6SJohannes Berg 
39430686bf7SJohannes Berg 	if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
3954b6f1dd6SJohannes Berg 		return 0;
3964b6f1dd6SJohannes Berg 
3978b305780SJohannes Berg 	ASSERT_RTNL();
398685fb72bSJohannes Berg 
3994b6f1dd6SJohannes Berg 	if (local->monitor_sdata)
4008b305780SJohannes Berg 		return 0;
4014b6f1dd6SJohannes Berg 
4024b6f1dd6SJohannes Berg 	sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);
4038b305780SJohannes Berg 	if (!sdata)
4048b305780SJohannes Berg 		return -ENOMEM;
4054b6f1dd6SJohannes Berg 
4064b6f1dd6SJohannes Berg 	/* set up data */
4074b6f1dd6SJohannes Berg 	sdata->local = local;
4084b6f1dd6SJohannes Berg 	sdata->vif.type = NL80211_IFTYPE_MONITOR;
4094b6f1dd6SJohannes Berg 	snprintf(sdata->name, IFNAMSIZ, "%s-monitor",
4104b6f1dd6SJohannes Berg 		 wiphy_name(local->hw.wiphy));
41134171dc0SEmmanuel Grumbach 	sdata->wdev.iftype = NL80211_IFTYPE_MONITOR;
4124b6f1dd6SJohannes Berg 
4132475b1ccSMax Stepanov 	sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
4142475b1ccSMax Stepanov 
4153a25a8c8SJohannes Berg 	ieee80211_set_default_queues(sdata);
4163a25a8c8SJohannes Berg 
4174b6f1dd6SJohannes Berg 	ret = drv_add_interface(local, sdata);
4184b6f1dd6SJohannes Berg 	if (WARN_ON(ret)) {
4194b6f1dd6SJohannes Berg 		/* ok .. stupid driver, it asked for this! */
4204b6f1dd6SJohannes Berg 		kfree(sdata);
4218b305780SJohannes Berg 		return ret;
4224b6f1dd6SJohannes Berg 	}
4234b6f1dd6SJohannes Berg 
424a9865538SJohannes Berg 	ret = ieee80211_check_queues(sdata, NL80211_IFTYPE_MONITOR);
4253a25a8c8SJohannes Berg 	if (ret) {
4263a25a8c8SJohannes Berg 		kfree(sdata);
4278b305780SJohannes Berg 		return ret;
4283a25a8c8SJohannes Berg 	}
4293a25a8c8SJohannes Berg 
430fab57a6cSJohannes Berg 	mutex_lock(&local->iflist_mtx);
431fab57a6cSJohannes Berg 	rcu_assign_pointer(local->monitor_sdata, sdata);
432fab57a6cSJohannes Berg 	mutex_unlock(&local->iflist_mtx);
433fab57a6cSJohannes Berg 
43434a3740dSJohannes Berg 	mutex_lock(&local->mtx);
4354bf88530SJohannes Berg 	ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
43655de908aSJohannes Berg 					IEEE80211_CHANCTX_EXCLUSIVE);
43734a3740dSJohannes Berg 	mutex_unlock(&local->mtx);
43855de908aSJohannes Berg 	if (ret) {
439fab57a6cSJohannes Berg 		mutex_lock(&local->iflist_mtx);
4400c2bef46SMonam Agarwal 		RCU_INIT_POINTER(local->monitor_sdata, NULL);
441fab57a6cSJohannes Berg 		mutex_unlock(&local->iflist_mtx);
442fab57a6cSJohannes Berg 		synchronize_net();
44355de908aSJohannes Berg 		drv_remove_interface(local, sdata);
44455de908aSJohannes Berg 		kfree(sdata);
4458b305780SJohannes Berg 		return ret;
44655de908aSJohannes Berg 	}
44755de908aSJohannes Berg 
44842bd20d9SAviya Erenfeld 	skb_queue_head_init(&sdata->skb_queue);
44942bd20d9SAviya Erenfeld 	INIT_WORK(&sdata->work, ieee80211_iface_work);
45042bd20d9SAviya Erenfeld 
4518b305780SJohannes Berg 	return 0;
4524b6f1dd6SJohannes Berg }
4534b6f1dd6SJohannes Berg 
4543c3e21e7SJohannes Berg void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
4554b6f1dd6SJohannes Berg {
4564b6f1dd6SJohannes Berg 	struct ieee80211_sub_if_data *sdata;
4574b6f1dd6SJohannes Berg 
45830686bf7SJohannes Berg 	if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
4594b6f1dd6SJohannes Berg 		return;
4604b6f1dd6SJohannes Berg 
4618b305780SJohannes Berg 	ASSERT_RTNL();
4628b305780SJohannes Berg 
463685fb72bSJohannes Berg 	mutex_lock(&local->iflist_mtx);
4644b6f1dd6SJohannes Berg 
465685fb72bSJohannes Berg 	sdata = rcu_dereference_protected(local->monitor_sdata,
466685fb72bSJohannes Berg 					  lockdep_is_held(&local->iflist_mtx));
4678b305780SJohannes Berg 	if (!sdata) {
4688b305780SJohannes Berg 		mutex_unlock(&local->iflist_mtx);
4698b305780SJohannes Berg 		return;
4708b305780SJohannes Berg 	}
4714b6f1dd6SJohannes Berg 
4720c2bef46SMonam Agarwal 	RCU_INIT_POINTER(local->monitor_sdata, NULL);
4738b305780SJohannes Berg 	mutex_unlock(&local->iflist_mtx);
4748b305780SJohannes Berg 
4754b6f1dd6SJohannes Berg 	synchronize_net();
4764b6f1dd6SJohannes Berg 
47734a3740dSJohannes Berg 	mutex_lock(&local->mtx);
47855de908aSJohannes Berg 	ieee80211_vif_release_channel(sdata);
47934a3740dSJohannes Berg 	mutex_unlock(&local->mtx);
48055de908aSJohannes Berg 
4814b6f1dd6SJohannes Berg 	drv_remove_interface(local, sdata);
4824b6f1dd6SJohannes Berg 
4834b6f1dd6SJohannes Berg 	kfree(sdata);
4844b6f1dd6SJohannes Berg }
4854b6f1dd6SJohannes Berg 
48634d4bc4dSJohannes Berg /*
48734d4bc4dSJohannes Berg  * NOTE: Be very careful when changing this function, it must NOT return
48834d4bc4dSJohannes Berg  * an error on interface type changes that have been pre-checked, so most
48934d4bc4dSJohannes Berg  * checks should be in ieee80211_check_concurrent_iface.
49034d4bc4dSJohannes Berg  */
491f142c6b9SJohannes Berg int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
49287490f6dSJohannes Berg {
493f142c6b9SJohannes Berg 	struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
494f142c6b9SJohannes Berg 	struct net_device *dev = wdev->netdev;
49587490f6dSJohannes Berg 	struct ieee80211_local *local = sdata->local;
49687490f6dSJohannes Berg 	struct sta_info *sta;
49787490f6dSJohannes Berg 	u32 changed = 0;
49887490f6dSJohannes Berg 	int res;
49987490f6dSJohannes Berg 	u32 hw_reconf_flags = 0;
50087490f6dSJohannes Berg 
5010d143fe1SJohannes Berg 	switch (sdata->vif.type) {
5020d143fe1SJohannes Berg 	case NL80211_IFTYPE_WDS:
5030d143fe1SJohannes Berg 		if (!is_valid_ether_addr(sdata->u.wds.remote_addr))
5040d143fe1SJohannes Berg 			return -ENOLINK;
5050d143fe1SJohannes Berg 		break;
506665c93a9SJohannes Berg 	case NL80211_IFTYPE_AP_VLAN: {
507665c93a9SJohannes Berg 		struct ieee80211_sub_if_data *master;
508665c93a9SJohannes Berg 
5090d143fe1SJohannes Berg 		if (!sdata->bss)
5100d143fe1SJohannes Berg 			return -ENOLINK;
511665c93a9SJohannes Berg 
5124e141dadSMichal Kazior 		mutex_lock(&local->mtx);
5130d143fe1SJohannes Berg 		list_add(&sdata->u.vlan.list, &sdata->bss->vlans);
5144e141dadSMichal Kazior 		mutex_unlock(&local->mtx);
515665c93a9SJohannes Berg 
516665c93a9SJohannes Berg 		master = container_of(sdata->bss,
517665c93a9SJohannes Berg 				      struct ieee80211_sub_if_data, u.ap);
518665c93a9SJohannes Berg 		sdata->control_port_protocol =
519665c93a9SJohannes Berg 			master->control_port_protocol;
520665c93a9SJohannes Berg 		sdata->control_port_no_encrypt =
521665c93a9SJohannes Berg 			master->control_port_no_encrypt;
5221351c5d3SJohannes Berg 		sdata->vif.cab_queue = master->vif.cab_queue;
5231351c5d3SJohannes Berg 		memcpy(sdata->vif.hw_queue, master->vif.hw_queue,
5241351c5d3SJohannes Berg 		       sizeof(sdata->vif.hw_queue));
5252967e031SFelix Fietkau 		sdata->vif.bss_conf.chandef = master->vif.bss_conf.chandef;
526f9dca80bSMichal Kazior 
527f9dca80bSMichal Kazior 		mutex_lock(&local->key_mtx);
528f9dca80bSMichal Kazior 		sdata->crypto_tx_tailroom_needed_cnt +=
529f9dca80bSMichal Kazior 			master->crypto_tx_tailroom_needed_cnt;
530f9dca80bSMichal Kazior 		mutex_unlock(&local->key_mtx);
531f9dca80bSMichal Kazior 
5320d143fe1SJohannes Berg 		break;
533665c93a9SJohannes Berg 		}
5340d143fe1SJohannes Berg 	case NL80211_IFTYPE_AP:
5350d143fe1SJohannes Berg 		sdata->bss = &sdata->u.ap;
5360d143fe1SJohannes Berg 		break;
5370d143fe1SJohannes Berg 	case NL80211_IFTYPE_MESH_POINT:
5380d143fe1SJohannes Berg 	case NL80211_IFTYPE_STATION:
5390d143fe1SJohannes Berg 	case NL80211_IFTYPE_MONITOR:
5400d143fe1SJohannes Berg 	case NL80211_IFTYPE_ADHOC:
541f142c6b9SJohannes Berg 	case NL80211_IFTYPE_P2P_DEVICE:
5426e0bd6c3SRostislav Lisovy 	case NL80211_IFTYPE_OCB:
543cb3b7d87SAyala Beker 	case NL80211_IFTYPE_NAN:
5440d143fe1SJohannes Berg 		/* no special treatment */
5450d143fe1SJohannes Berg 		break;
5460d143fe1SJohannes Berg 	case NL80211_IFTYPE_UNSPECIFIED:
5472e161f78SJohannes Berg 	case NUM_NL80211_IFTYPES:
5482ca27bcfSJohannes Berg 	case NL80211_IFTYPE_P2P_CLIENT:
5492ca27bcfSJohannes Berg 	case NL80211_IFTYPE_P2P_GO:
5500d143fe1SJohannes Berg 		/* cannot happen */
5510d143fe1SJohannes Berg 		WARN_ON(1);
5520d143fe1SJohannes Berg 		break;
5530d143fe1SJohannes Berg 	}
5540d143fe1SJohannes Berg 
5550d143fe1SJohannes Berg 	if (local->open_count == 0) {
55624487981SJohannes Berg 		res = drv_start(local);
5570d143fe1SJohannes Berg 		if (res)
5580d143fe1SJohannes Berg 			goto err_del_bss;
559e8975581SJohannes Berg 		/* we're brought up, everything changes */
560e8975581SJohannes Berg 		hw_reconf_flags = ~0;
5611f87f7d3SJohannes Berg 		ieee80211_led_radio(local, true);
56267408c8cSJohannes Berg 		ieee80211_mod_tpt_led_trig(local,
56367408c8cSJohannes Berg 					   IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
5640d143fe1SJohannes Berg 	}
5650d143fe1SJohannes Berg 
5660d143fe1SJohannes Berg 	/*
567bf533e0bSJohannes Berg 	 * Copy the hopefully now-present MAC address to
568bf533e0bSJohannes Berg 	 * this interface, if it has the special null one.
5690d143fe1SJohannes Berg 	 */
570f142c6b9SJohannes Berg 	if (dev && is_zero_ether_addr(dev->dev_addr)) {
571bf533e0bSJohannes Berg 		memcpy(dev->dev_addr,
5720d143fe1SJohannes Berg 		       local->hw.wiphy->perm_addr,
5730d143fe1SJohannes Berg 		       ETH_ALEN);
574bf533e0bSJohannes Berg 		memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN);
5750d143fe1SJohannes Berg 
5760d143fe1SJohannes Berg 		if (!is_valid_ether_addr(dev->dev_addr)) {
5774d6c36faSJohannes Berg 			res = -EADDRNOTAVAIL;
5784d6c36faSJohannes Berg 			goto err_stop;
5790d143fe1SJohannes Berg 		}
580bf533e0bSJohannes Berg 	}
5810d143fe1SJohannes Berg 
5820d143fe1SJohannes Berg 	switch (sdata->vif.type) {
5830d143fe1SJohannes Berg 	case NL80211_IFTYPE_AP_VLAN:
5844d76d21bSJohannes Berg 		/* no need to tell driver, but set carrier and chanctx */
5854d76d21bSJohannes Berg 		if (rtnl_dereference(sdata->bss->beacon)) {
5864d76d21bSJohannes Berg 			ieee80211_vif_vlan_copy_chanctx(sdata);
5873edaf3e6SJohannes Berg 			netif_carrier_on(dev);
5884d76d21bSJohannes Berg 		} else {
5893edaf3e6SJohannes Berg 			netif_carrier_off(dev);
5904d76d21bSJohannes Berg 		}
5910d143fe1SJohannes Berg 		break;
5920d143fe1SJohannes Berg 	case NL80211_IFTYPE_MONITOR:
593d8212184SAviya Erenfeld 		if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) {
5940d143fe1SJohannes Berg 			local->cooked_mntrs++;
5950d143fe1SJohannes Berg 			break;
5960d143fe1SJohannes Berg 		}
5970d143fe1SJohannes Berg 
598d8212184SAviya Erenfeld 		if (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
59931eba5bcSFelix Fietkau 			res = drv_add_interface(local, sdata);
60031eba5bcSFelix Fietkau 			if (res)
60131eba5bcSFelix Fietkau 				goto err_stop;
60231eba5bcSFelix Fietkau 		} else if (local->monitors == 0 && local->open_count == 0) {
603075e0847SJohannes Berg 			res = ieee80211_add_virtual_monitor(local);
604075e0847SJohannes Berg 			if (res)
605075e0847SJohannes Berg 				goto err_stop;
606075e0847SJohannes Berg 		}
607075e0847SJohannes Berg 
6080d143fe1SJohannes Berg 		/* must be before the call to ieee80211_configure_filter */
6090d143fe1SJohannes Berg 		local->monitors++;
610e8975581SJohannes Berg 		if (local->monitors == 1) {
6110869aea0SJohannes Berg 			local->hw.conf.flags |= IEEE80211_CONF_MONITOR;
6120869aea0SJohannes Berg 			hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
613e8975581SJohannes Berg 		}
6140d143fe1SJohannes Berg 
61585416a4fSChristian Lamparter 		ieee80211_adjust_monitor_flags(sdata, 1);
6160d143fe1SJohannes Berg 		ieee80211_configure_filter(local);
617801d929cSFelix Fietkau 		mutex_lock(&local->mtx);
618801d929cSFelix Fietkau 		ieee80211_recalc_idle(local);
619801d929cSFelix Fietkau 		mutex_unlock(&local->mtx);
62053e9b1deSDavid Gnedt 
62153e9b1deSDavid Gnedt 		netif_carrier_on(dev);
6220d143fe1SJohannes Berg 		break;
6230d143fe1SJohannes Berg 	default:
62434d4bc4dSJohannes Berg 		if (coming_up) {
625075e0847SJohannes Berg 			ieee80211_del_virtual_monitor(local);
626075e0847SJohannes Berg 
6277b7eab6fSJohannes Berg 			res = drv_add_interface(local, sdata);
6280d143fe1SJohannes Berg 			if (res)
6290d143fe1SJohannes Berg 				goto err_stop;
630a9865538SJohannes Berg 			res = ieee80211_check_queues(sdata,
631a9865538SJohannes Berg 				ieee80211_vif_type_p2p(&sdata->vif));
6323a25a8c8SJohannes Berg 			if (res)
6333a25a8c8SJohannes Berg 				goto err_del_interface;
63434d4bc4dSJohannes Berg 		}
6350d143fe1SJohannes Berg 
63629cbe68cSJohannes Berg 		if (sdata->vif.type == NL80211_IFTYPE_AP) {
637e3b90ca2SIgor Perminov 			local->fif_pspoll++;
6387be5086dSJohannes Berg 			local->fif_probe_req++;
639e3b90ca2SIgor Perminov 
640e3b90ca2SIgor Perminov 			ieee80211_configure_filter(local);
6417be5086dSJohannes Berg 		} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
6427be5086dSJohannes Berg 			local->fif_probe_req++;
643a3c9aa51SAndrey Yurovsky 		}
644e3b90ca2SIgor Perminov 
645708d50edSAyala Beker 		if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
646708d50edSAyala Beker 		    sdata->vif.type != NL80211_IFTYPE_NAN)
6470d143fe1SJohannes Berg 			changed |= ieee80211_reset_erp_info(sdata);
6480d143fe1SJohannes Berg 		ieee80211_bss_info_change_notify(sdata, changed);
6490d143fe1SJohannes Berg 
650c405c629SJohannes Berg 		switch (sdata->vif.type) {
651c405c629SJohannes Berg 		case NL80211_IFTYPE_STATION:
652c405c629SJohannes Berg 		case NL80211_IFTYPE_ADHOC:
653c405c629SJohannes Berg 		case NL80211_IFTYPE_AP:
654c405c629SJohannes Berg 		case NL80211_IFTYPE_MESH_POINT:
6556e0bd6c3SRostislav Lisovy 		case NL80211_IFTYPE_OCB:
6560d143fe1SJohannes Berg 			netif_carrier_off(dev);
657c405c629SJohannes Berg 			break;
6581411af15SJohannes Berg 		case NL80211_IFTYPE_WDS:
659f142c6b9SJohannes Berg 		case NL80211_IFTYPE_P2P_DEVICE:
660cb3b7d87SAyala Beker 		case NL80211_IFTYPE_NAN:
6611411af15SJohannes Berg 			break;
662c405c629SJohannes Berg 		default:
663a2310824SJohannes Berg 			/* not reached */
664a2310824SJohannes Berg 			WARN_ON(1);
665c405c629SJohannes Berg 		}
66659034591SEliad Peller 
66759034591SEliad Peller 		/*
668cec66283SJohannes Berg 		 * Set default queue parameters so drivers don't
66959034591SEliad Peller 		 * need to initialise the hardware if the hardware
670cec66283SJohannes Berg 		 * doesn't start up with sane defaults.
671cec66283SJohannes Berg 		 * Enable QoS for anything but station interfaces.
67259034591SEliad Peller 		 */
673cec66283SJohannes Berg 		ieee80211_set_wmm_default(sdata, true,
674cec66283SJohannes Berg 			sdata->vif.type != NL80211_IFTYPE_STATION);
6750d143fe1SJohannes Berg 	}
6760d143fe1SJohannes Berg 
6772d2080c3SJohannes Berg 	set_bit(SDATA_STATE_RUNNING, &sdata->state);
6782d2080c3SJohannes Berg 
679f64331d5SJohannes Berg 	switch (sdata->vif.type) {
680f64331d5SJohannes Berg 	case NL80211_IFTYPE_WDS:
6810d143fe1SJohannes Berg 		/* Create STA entry for the WDS peer */
6820d143fe1SJohannes Berg 		sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
6830d143fe1SJohannes Berg 				     GFP_KERNEL);
6840d143fe1SJohannes Berg 		if (!sta) {
6850d143fe1SJohannes Berg 			res = -ENOMEM;
6860d143fe1SJohannes Berg 			goto err_del_interface;
6870d143fe1SJohannes Berg 		}
6880d143fe1SJohannes Berg 
68983d5cc01SJohannes Berg 		sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
69083d5cc01SJohannes Berg 		sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
69183d5cc01SJohannes Berg 		sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
6920d143fe1SJohannes Berg 
6930d143fe1SJohannes Berg 		res = sta_info_insert(sta);
6940d143fe1SJohannes Berg 		if (res) {
6950d143fe1SJohannes Berg 			/* STA has been freed */
6960d143fe1SJohannes Berg 			goto err_del_interface;
6970d143fe1SJohannes Berg 		}
6981be7fe8dSBill Jordan 
6991be7fe8dSBill Jordan 		rate_control_rate_init(sta);
7001411af15SJohannes Berg 		netif_carrier_on(dev);
701f64331d5SJohannes Berg 		break;
702f64331d5SJohannes Berg 	case NL80211_IFTYPE_P2P_DEVICE:
703f142c6b9SJohannes Berg 		rcu_assign_pointer(local->p2p_sdata, sdata);
704f64331d5SJohannes Berg 		break;
705f64331d5SJohannes Berg 	case NL80211_IFTYPE_MONITOR:
706f64331d5SJohannes Berg 		if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES)
707f64331d5SJohannes Berg 			break;
708f64331d5SJohannes Berg 		list_add_tail_rcu(&sdata->u.mntr.list, &local->mon_list);
709f64331d5SJohannes Berg 		break;
710f64331d5SJohannes Berg 	default:
711f64331d5SJohannes Berg 		break;
7120d143fe1SJohannes Berg 	}
7130d143fe1SJohannes Berg 
7140d143fe1SJohannes Berg 	/*
7150d143fe1SJohannes Berg 	 * set_multicast_list will be invoked by the networking core
7160d143fe1SJohannes Berg 	 * which will check whether any increments here were done in
7170d143fe1SJohannes Berg 	 * error and sync them down to the hardware as filter flags.
7180d143fe1SJohannes Berg 	 */
7190d143fe1SJohannes Berg 	if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
7200d143fe1SJohannes Berg 		atomic_inc(&local->iff_allmultis);
7210d143fe1SJohannes Berg 
72234d4bc4dSJohannes Berg 	if (coming_up)
7230d143fe1SJohannes Berg 		local->open_count++;
72434d4bc4dSJohannes Berg 
72559034591SEliad Peller 	if (hw_reconf_flags)
726e8975581SJohannes Berg 		ieee80211_hw_config(local, hw_reconf_flags);
7270d143fe1SJohannes Berg 
7284a733ef1SJohannes Berg 	ieee80211_recalc_ps(local);
729965bedadSJohannes Berg 
7302b436312SJohannes Berg 	if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
7317d65f829SJohannes Berg 	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
7327d65f829SJohannes Berg 	    local->ops->wake_tx_queue) {
7332b436312SJohannes Berg 		/* XXX: for AP_VLAN, actually track AP queues */
7342b436312SJohannes Berg 		netif_tx_start_all_queues(dev);
7352b436312SJohannes Berg 	} else if (dev) {
7362b730daaSJohannes Berg 		unsigned long flags;
7372b730daaSJohannes Berg 		int n_acs = IEEE80211_NUM_ACS;
7382b730daaSJohannes Berg 		int ac;
7392b730daaSJohannes Berg 
7402b730daaSJohannes Berg 		if (local->hw.queues < IEEE80211_NUM_ACS)
7412b730daaSJohannes Berg 			n_acs = 1;
7422b730daaSJohannes Berg 
7432b730daaSJohannes Berg 		spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
7442b730daaSJohannes Berg 		if (sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE ||
7452b730daaSJohannes Berg 		    (local->queue_stop_reasons[sdata->vif.cab_queue] == 0 &&
7462b730daaSJohannes Berg 		     skb_queue_empty(&local->pending[sdata->vif.cab_queue]))) {
7472b730daaSJohannes Berg 			for (ac = 0; ac < n_acs; ac++) {
7482b730daaSJohannes Berg 				int ac_queue = sdata->vif.hw_queue[ac];
7492b730daaSJohannes Berg 
7502b730daaSJohannes Berg 				if (local->queue_stop_reasons[ac_queue] == 0 &&
7512b730daaSJohannes Berg 				    skb_queue_empty(&local->pending[ac_queue]))
7522b730daaSJohannes Berg 					netif_start_subqueue(dev, ac);
7532b730daaSJohannes Berg 			}
7542b730daaSJohannes Berg 		}
7552b730daaSJohannes Berg 		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
7562b730daaSJohannes Berg 	}
7570d143fe1SJohannes Berg 
7580d143fe1SJohannes Berg 	return 0;
7590d143fe1SJohannes Berg  err_del_interface:
7607b7eab6fSJohannes Berg 	drv_remove_interface(local, sdata);
7610d143fe1SJohannes Berg  err_stop:
76224487981SJohannes Berg 	if (!local->open_count)
76324487981SJohannes Berg 		drv_stop(local);
7640d143fe1SJohannes Berg  err_del_bss:
7650d143fe1SJohannes Berg 	sdata->bss = NULL;
7664e141dadSMichal Kazior 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
7674e141dadSMichal Kazior 		mutex_lock(&local->mtx);
7680d143fe1SJohannes Berg 		list_del(&sdata->u.vlan.list);
7694e141dadSMichal Kazior 		mutex_unlock(&local->mtx);
7704e141dadSMichal Kazior 	}
7714d6c36faSJohannes Berg 	/* might already be clear but that doesn't matter */
7722d2080c3SJohannes Berg 	clear_bit(SDATA_STATE_RUNNING, &sdata->state);
7730d143fe1SJohannes Berg 	return res;
7740d143fe1SJohannes Berg }
7750d143fe1SJohannes Berg 
77634d4bc4dSJohannes Berg static int ieee80211_open(struct net_device *dev)
7770d143fe1SJohannes Berg {
7780d143fe1SJohannes Berg 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
77934d4bc4dSJohannes Berg 	int err;
78034d4bc4dSJohannes Berg 
78134d4bc4dSJohannes Berg 	/* fail early if user set an invalid address */
7822fcf2824SMohammed Shafi Shajakhan 	if (!is_valid_ether_addr(dev->dev_addr))
78334d4bc4dSJohannes Berg 		return -EADDRNOTAVAIL;
78434d4bc4dSJohannes Berg 
78534d4bc4dSJohannes Berg 	err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type);
78634d4bc4dSJohannes Berg 	if (err)
78734d4bc4dSJohannes Berg 		return err;
78834d4bc4dSJohannes Berg 
789f142c6b9SJohannes Berg 	return ieee80211_do_open(&sdata->wdev, true);
79034d4bc4dSJohannes Berg }
79134d4bc4dSJohannes Berg 
79234d4bc4dSJohannes Berg static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
79334d4bc4dSJohannes Berg 			      bool going_down)
79434d4bc4dSJohannes Berg {
7950d143fe1SJohannes Berg 	struct ieee80211_local *local = sdata->local;
796fa962b92SMichal Kazior 	struct fq *fq = &local->fq;
7975061b0c2SJohannes Berg 	unsigned long flags;
7985061b0c2SJohannes Berg 	struct sk_buff *skb, *tmp;
799e8975581SJohannes Berg 	u32 hw_reconf_flags = 0;
80009f4114eSJohannes Berg 	int i, flushed;
801397a7a24SMichael Braun 	struct ps_data *ps;
802d2859df5SJanusz Dziedzic 	struct cfg80211_chan_def chandef;
80346238845SJohannes Berg 	bool cancel_scan;
804167e33f4SAyala Beker 	struct cfg80211_nan_func *func;
8050d143fe1SJohannes Berg 
806c29acf20SRajkumar Manoharan 	clear_bit(SDATA_STATE_RUNNING, &sdata->state);
807c29acf20SRajkumar Manoharan 
80846238845SJohannes Berg 	cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata;
80946238845SJohannes Berg 	if (cancel_scan)
810352ffad6SBrian Cavagnolo 		ieee80211_scan_cancel(local);
811352ffad6SBrian Cavagnolo 
8120d143fe1SJohannes Berg 	/*
8130d143fe1SJohannes Berg 	 * Stop TX on this interface first.
8140d143fe1SJohannes Berg 	 */
815f142c6b9SJohannes Berg 	if (sdata->dev)
81634d4bc4dSJohannes Berg 		netif_tx_stop_all_queues(sdata->dev);
8170d143fe1SJohannes Berg 
818c8f994eeSJohannes Berg 	ieee80211_roc_purge(local, sdata);
819af6b6374SJohannes Berg 
8208ffcc704SEmmanuel Grumbach 	switch (sdata->vif.type) {
8218ffcc704SEmmanuel Grumbach 	case NL80211_IFTYPE_STATION:
822572078beSJohannes Berg 		ieee80211_mgd_stop(sdata);
8238ffcc704SEmmanuel Grumbach 		break;
8248ffcc704SEmmanuel Grumbach 	case NL80211_IFTYPE_ADHOC:
825cd7760e6SSimon Wunderlich 		ieee80211_ibss_stop(sdata);
8268ffcc704SEmmanuel Grumbach 		break;
8278ffcc704SEmmanuel Grumbach 	case NL80211_IFTYPE_AP:
8288ffcc704SEmmanuel Grumbach 		cancel_work_sync(&sdata->u.ap.request_smps_work);
8298ffcc704SEmmanuel Grumbach 		break;
830f64331d5SJohannes Berg 	case NL80211_IFTYPE_MONITOR:
831f64331d5SJohannes Berg 		if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES)
832f64331d5SJohannes Berg 			break;
833f64331d5SJohannes Berg 		list_del_rcu(&sdata->u.mntr.list);
834f64331d5SJohannes Berg 		break;
8358ffcc704SEmmanuel Grumbach 	default:
8368ffcc704SEmmanuel Grumbach 		break;
8378ffcc704SEmmanuel Grumbach 	}
838cd7760e6SSimon Wunderlich 
839af6b6374SJohannes Berg 	/*
8400d143fe1SJohannes Berg 	 * Remove all stations associated with this interface.
8410d143fe1SJohannes Berg 	 *
8420d143fe1SJohannes Berg 	 * This must be done before calling ops->remove_interface()
8430d143fe1SJohannes Berg 	 * because otherwise we can later invoke ops->sta_notify()
8440d143fe1SJohannes Berg 	 * whenever the STAs are removed, and that invalidates driver
8450d143fe1SJohannes Berg 	 * assumptions about always getting a vif pointer that is valid
8460d143fe1SJohannes Berg 	 * (because if we remove a STA after ops->remove_interface()
8470d143fe1SJohannes Berg 	 * the driver will have removed the vif info already!)
8480d143fe1SJohannes Berg 	 *
8495eb8f4d7SJohannes Berg 	 * In WDS mode a station must exist here and be flushed, for
8505eb8f4d7SJohannes Berg 	 * AP_VLANs stations may exist since there's nothing else that
8515eb8f4d7SJohannes Berg 	 * would have removed them, but in other modes there shouldn't
8525eb8f4d7SJohannes Berg 	 * be any stations.
8530d143fe1SJohannes Berg 	 */
854d34ba216SJohannes Berg 	flushed = sta_info_flush(sdata);
8555eb8f4d7SJohannes Berg 	WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
8565eb8f4d7SJohannes Berg 		     ((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) ||
8575eb8f4d7SJohannes Berg 		      (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)));
8580d143fe1SJohannes Berg 
859df140465SJohannes Berg 	/* don't count this interface for allmulti while it is down */
8600d143fe1SJohannes Berg 	if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
8610d143fe1SJohannes Berg 		atomic_dec(&local->iff_allmultis);
8620d143fe1SJohannes Berg 
8637be5086dSJohannes Berg 	if (sdata->vif.type == NL80211_IFTYPE_AP) {
864e3b90ca2SIgor Perminov 		local->fif_pspoll--;
8657be5086dSJohannes Berg 		local->fif_probe_req--;
8667be5086dSJohannes Berg 	} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
8677be5086dSJohannes Berg 		local->fif_probe_req--;
8687be5086dSJohannes Berg 	}
869e3b90ca2SIgor Perminov 
870f142c6b9SJohannes Berg 	if (sdata->dev) {
87134d4bc4dSJohannes Berg 		netif_addr_lock_bh(sdata->dev);
8723b8d81e0SJohannes Berg 		spin_lock_bh(&local->filter_lock);
87334d4bc4dSJohannes Berg 		__hw_addr_unsync(&local->mc_list, &sdata->dev->mc,
87434d4bc4dSJohannes Berg 				 sdata->dev->addr_len);
8753b8d81e0SJohannes Berg 		spin_unlock_bh(&local->filter_lock);
87634d4bc4dSJohannes Berg 		netif_addr_unlock_bh(sdata->dev);
877f142c6b9SJohannes Berg 	}
8783ac64beeSJohannes Berg 
8797cbf0ba5SVivek Natarajan 	del_timer_sync(&local->dynamic_ps_timer);
8807cbf0ba5SVivek Natarajan 	cancel_work_sync(&local->dynamic_ps_enable_work);
8810d143fe1SJohannes Berg 
88204ecd257SJohannes Berg 	cancel_work_sync(&sdata->recalc_smps);
883dbd72850SMichal Kazior 	sdata_lock(sdata);
88459af6928SMichal Kazior 	mutex_lock(&local->mtx);
88573da7d5bSSimon Wunderlich 	sdata->vif.csa_active = false;
8860c21e632SLuciano Coelho 	if (sdata->vif.type == NL80211_IFTYPE_STATION)
8870c21e632SLuciano Coelho 		sdata->u.mgd.csa_waiting_bcn = false;
888a46992b4SLuciano Coelho 	if (sdata->csa_block_tx) {
889a46992b4SLuciano Coelho 		ieee80211_wake_vif_queues(local, sdata,
890a46992b4SLuciano Coelho 					  IEEE80211_QUEUE_STOP_REASON_CSA);
891a46992b4SLuciano Coelho 		sdata->csa_block_tx = false;
892a46992b4SLuciano Coelho 	}
89359af6928SMichal Kazior 	mutex_unlock(&local->mtx);
894dbd72850SMichal Kazior 	sdata_unlock(sdata);
89559af6928SMichal Kazior 
89673da7d5bSSimon Wunderlich 	cancel_work_sync(&sdata->csa_finalize_work);
89704ecd257SJohannes Berg 
898164eb02dSSimon Wunderlich 	cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
899164eb02dSSimon Wunderlich 
900164eb02dSSimon Wunderlich 	if (sdata->wdev.cac_started) {
901d2859df5SJanusz Dziedzic 		chandef = sdata->vif.bss_conf.chandef;
902b2c0958bSJohannes Berg 		WARN_ON(local->suspended);
90334a3740dSJohannes Berg 		mutex_lock(&local->mtx);
904164eb02dSSimon Wunderlich 		ieee80211_vif_release_channel(sdata);
90534a3740dSJohannes Berg 		mutex_unlock(&local->mtx);
906d2859df5SJanusz Dziedzic 		cfg80211_cac_event(sdata->dev, &chandef,
907d2859df5SJanusz Dziedzic 				   NL80211_RADAR_CAC_ABORTED,
908164eb02dSSimon Wunderlich 				   GFP_KERNEL);
909164eb02dSSimon Wunderlich 	}
910164eb02dSSimon Wunderlich 
9110d143fe1SJohannes Berg 	/* APs need special treatment */
9120d143fe1SJohannes Berg 	if (sdata->vif.type == NL80211_IFTYPE_AP) {
91357c9fff3SJohannes Berg 		struct ieee80211_sub_if_data *vlan, *tmpsdata;
9140d143fe1SJohannes Berg 
9150d143fe1SJohannes Berg 		/* down all dependent devices, that is VLANs */
91657c9fff3SJohannes Berg 		list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans,
9170d143fe1SJohannes Berg 					 u.vlan.list)
9180d143fe1SJohannes Berg 			dev_close(vlan->dev);
9190d143fe1SJohannes Berg 		WARN_ON(!list_empty(&sdata->u.ap.vlans));
920397a7a24SMichael Braun 	} else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
921397a7a24SMichael Braun 		/* remove all packets in parent bc_buf pointing to this dev */
922397a7a24SMichael Braun 		ps = &sdata->bss->ps;
923397a7a24SMichael Braun 
924397a7a24SMichael Braun 		spin_lock_irqsave(&ps->bc_buf.lock, flags);
925397a7a24SMichael Braun 		skb_queue_walk_safe(&ps->bc_buf, skb, tmp) {
926397a7a24SMichael Braun 			if (skb->dev == sdata->dev) {
927397a7a24SMichael Braun 				__skb_unlink(skb, &ps->bc_buf);
928397a7a24SMichael Braun 				local->total_ps_buffered--;
929397a7a24SMichael Braun 				ieee80211_free_txskb(&local->hw, skb);
930397a7a24SMichael Braun 			}
931397a7a24SMichael Braun 		}
932397a7a24SMichael Braun 		spin_unlock_irqrestore(&ps->bc_buf.lock, flags);
9330d143fe1SJohannes Berg 	}
9340d143fe1SJohannes Berg 
93534d4bc4dSJohannes Berg 	if (going_down)
9360d143fe1SJohannes Berg 		local->open_count--;
9370d143fe1SJohannes Berg 
9380d143fe1SJohannes Berg 	switch (sdata->vif.type) {
9390d143fe1SJohannes Berg 	case NL80211_IFTYPE_AP_VLAN:
9404e141dadSMichal Kazior 		mutex_lock(&local->mtx);
9410d143fe1SJohannes Berg 		list_del(&sdata->u.vlan.list);
9424e141dadSMichal Kazior 		mutex_unlock(&local->mtx);
9430c2bef46SMonam Agarwal 		RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL);
94410b68487SFelix Fietkau 		/* see comment in the default case below */
94510b68487SFelix Fietkau 		ieee80211_free_keys(sdata, true);
9460d143fe1SJohannes Berg 		/* no need to tell driver */
9470d143fe1SJohannes Berg 		break;
9480d143fe1SJohannes Berg 	case NL80211_IFTYPE_MONITOR:
949d8212184SAviya Erenfeld 		if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) {
9500d143fe1SJohannes Berg 			local->cooked_mntrs--;
9510d143fe1SJohannes Berg 			break;
9520d143fe1SJohannes Berg 		}
9530d143fe1SJohannes Berg 
9540d143fe1SJohannes Berg 		local->monitors--;
955e8975581SJohannes Berg 		if (local->monitors == 0) {
9560869aea0SJohannes Berg 			local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR;
9570869aea0SJohannes Berg 			hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
958e8975581SJohannes Berg 		}
9590d143fe1SJohannes Berg 
96085416a4fSChristian Lamparter 		ieee80211_adjust_monitor_flags(sdata, -1);
9610d143fe1SJohannes Berg 		break;
962167e33f4SAyala Beker 	case NL80211_IFTYPE_NAN:
963167e33f4SAyala Beker 		/* clean all the functions */
964167e33f4SAyala Beker 		spin_lock_bh(&sdata->u.nan.func_lock);
965167e33f4SAyala Beker 
966167e33f4SAyala Beker 		idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, i) {
967167e33f4SAyala Beker 			idr_remove(&sdata->u.nan.function_inst_ids, i);
968167e33f4SAyala Beker 			cfg80211_free_nan_func(func);
969167e33f4SAyala Beker 		}
970167e33f4SAyala Beker 		idr_destroy(&sdata->u.nan.function_inst_ids);
971167e33f4SAyala Beker 
972167e33f4SAyala Beker 		spin_unlock_bh(&sdata->u.nan.func_lock);
973167e33f4SAyala Beker 		break;
974f142c6b9SJohannes Berg 	case NL80211_IFTYPE_P2P_DEVICE:
975f142c6b9SJohannes Berg 		/* relies on synchronize_rcu() below */
9760c2bef46SMonam Agarwal 		RCU_INIT_POINTER(local->p2p_sdata, NULL);
977f142c6b9SJohannes Berg 		/* fall through */
9780d143fe1SJohannes Berg 	default:
9790b7dff4fSJohannes Berg 		cancel_work_sync(&sdata->work);
98035f20c14SJohannes Berg 		/*
98135f20c14SJohannes Berg 		 * When we get here, the interface is marked down.
9827907c7d3SJohannes Berg 		 * Free the remaining keys, if there are any
98310b68487SFelix Fietkau 		 * (which can happen in AP mode if userspace sets
98410b68487SFelix Fietkau 		 * keys before the interface is operating, and maybe
98510b68487SFelix Fietkau 		 * also in WDS mode)
98675de9113SJohannes Berg 		 *
9877907c7d3SJohannes Berg 		 * Force the key freeing to always synchronize_net()
9887907c7d3SJohannes Berg 		 * to wait for the RX path in case it is using this
98910b68487SFelix Fietkau 		 * interface enqueuing frames at this very time on
99075de9113SJohannes Berg 		 * another CPU.
99135f20c14SJohannes Berg 		 */
9927907c7d3SJohannes Berg 		ieee80211_free_keys(sdata, true);
9931861b845SJohannes Berg 		skb_queue_purge(&sdata->skb_queue);
9940d143fe1SJohannes Berg 	}
9950d143fe1SJohannes Berg 
9960d143fe1SJohannes Berg 	sdata->bss = NULL;
9970d143fe1SJohannes Berg 
9985061b0c2SJohannes Berg 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
9995061b0c2SJohannes Berg 	for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
10005061b0c2SJohannes Berg 		skb_queue_walk_safe(&local->pending[i], skb, tmp) {
10015061b0c2SJohannes Berg 			struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
10025061b0c2SJohannes Berg 			if (info->control.vif == &sdata->vif) {
10035061b0c2SJohannes Berg 				__skb_unlink(skb, &local->pending[i]);
1004d4fa14cdSFelix Fietkau 				ieee80211_free_txskb(&local->hw, skb);
10055061b0c2SJohannes Berg 			}
10065061b0c2SJohannes Berg 		}
10075061b0c2SJohannes Berg 	}
10085061b0c2SJohannes Berg 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
1009075e0847SJohannes Berg 
1010ba8c3d6fSFelix Fietkau 	if (sdata->vif.txq) {
1011ba8c3d6fSFelix Fietkau 		struct txq_info *txqi = to_txq_info(sdata->vif.txq);
1012ba8c3d6fSFelix Fietkau 
1013fa962b92SMichal Kazior 		spin_lock_bh(&fq->lock);
1014fa962b92SMichal Kazior 		ieee80211_txq_purge(local, txqi);
1015fa962b92SMichal Kazior 		spin_unlock_bh(&fq->lock);
1016ba8c3d6fSFelix Fietkau 	}
1017ba8c3d6fSFelix Fietkau 
1018b2c0958bSJohannes Berg 	if (local->open_count == 0)
1019b2c0958bSJohannes Berg 		ieee80211_clear_tx_pending(local);
1020b2c0958bSJohannes Berg 
1021b2c0958bSJohannes Berg 	/*
1022b2c0958bSJohannes Berg 	 * If the interface goes down while suspended, presumably because
1023b2c0958bSJohannes Berg 	 * the device was unplugged and that happens before our resume,
1024b2c0958bSJohannes Berg 	 * then the driver is already unconfigured and the remainder of
1025b2c0958bSJohannes Berg 	 * this function isn't needed.
1026b2c0958bSJohannes Berg 	 * XXX: what about WoWLAN? If the device has software state, e.g.
1027b2c0958bSJohannes Berg 	 *	memory allocated, it might expect teardown commands from
1028b2c0958bSJohannes Berg 	 *	mac80211 here?
1029b2c0958bSJohannes Berg 	 */
1030b2c0958bSJohannes Berg 	if (local->suspended) {
1031b2c0958bSJohannes Berg 		WARN_ON(local->wowlan);
1032b2c0958bSJohannes Berg 		WARN_ON(rtnl_dereference(local->monitor_sdata));
1033b2c0958bSJohannes Berg 		return;
1034b2c0958bSJohannes Berg 	}
1035b2c0958bSJohannes Berg 
1036b2c0958bSJohannes Berg 	switch (sdata->vif.type) {
1037b2c0958bSJohannes Berg 	case NL80211_IFTYPE_AP_VLAN:
1038b2c0958bSJohannes Berg 		break;
1039b2c0958bSJohannes Berg 	case NL80211_IFTYPE_MONITOR:
1040b2c0958bSJohannes Berg 		if (local->monitors == 0)
1041b2c0958bSJohannes Berg 			ieee80211_del_virtual_monitor(local);
1042b2c0958bSJohannes Berg 
1043b2c0958bSJohannes Berg 		mutex_lock(&local->mtx);
1044b2c0958bSJohannes Berg 		ieee80211_recalc_idle(local);
1045b2c0958bSJohannes Berg 		mutex_unlock(&local->mtx);
104631eba5bcSFelix Fietkau 
1047d8212184SAviya Erenfeld 		if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
1048b2c0958bSJohannes Berg 			break;
104931eba5bcSFelix Fietkau 
105031eba5bcSFelix Fietkau 		/* fall through */
1051b2c0958bSJohannes Berg 	default:
1052b2c0958bSJohannes Berg 		if (going_down)
1053b2c0958bSJohannes Berg 			drv_remove_interface(local, sdata);
1054b2c0958bSJohannes Berg 	}
1055b2c0958bSJohannes Berg 
10564a733ef1SJohannes Berg 	ieee80211_recalc_ps(local);
1057b2c0958bSJohannes Berg 
105846238845SJohannes Berg 	if (cancel_scan)
105946238845SJohannes Berg 		flush_delayed_work(&local->scan_work);
106046238845SJohannes Berg 
1061b2c0958bSJohannes Berg 	if (local->open_count == 0) {
1062b2c0958bSJohannes Berg 		ieee80211_stop_device(local);
1063b2c0958bSJohannes Berg 
1064b2c0958bSJohannes Berg 		/* no reconfiguring after stop! */
1065b2c0958bSJohannes Berg 		return;
1066b2c0958bSJohannes Berg 	}
1067b2c0958bSJohannes Berg 
1068b2c0958bSJohannes Berg 	/* do after stop to avoid reconfiguring when we stop anyway */
1069b2c0958bSJohannes Berg 	ieee80211_configure_filter(local);
1070b2c0958bSJohannes Berg 	ieee80211_hw_config(local, hw_reconf_flags);
1071b2c0958bSJohannes Berg 
1072b2c0958bSJohannes Berg 	if (local->monitors == local->open_count)
1073075e0847SJohannes Berg 		ieee80211_add_virtual_monitor(local);
107434d4bc4dSJohannes Berg }
107534d4bc4dSJohannes Berg 
107634d4bc4dSJohannes Berg static int ieee80211_stop(struct net_device *dev)
107734d4bc4dSJohannes Berg {
107834d4bc4dSJohannes Berg 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
107934d4bc4dSJohannes Berg 
108034d4bc4dSJohannes Berg 	ieee80211_do_stop(sdata, true);
10815061b0c2SJohannes Berg 
10820d143fe1SJohannes Berg 	return 0;
10830d143fe1SJohannes Berg }
10840d143fe1SJohannes Berg 
10850d143fe1SJohannes Berg static void ieee80211_set_multicast_list(struct net_device *dev)
10860d143fe1SJohannes Berg {
10870d143fe1SJohannes Berg 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1088b4a4bf5dSJohannes Berg 	struct ieee80211_local *local = sdata->local;
1089df140465SJohannes Berg 	int allmulti, sdata_allmulti;
10900d143fe1SJohannes Berg 
10910d143fe1SJohannes Berg 	allmulti = !!(dev->flags & IFF_ALLMULTI);
10920d143fe1SJohannes Berg 	sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI);
10930d143fe1SJohannes Berg 
10940d143fe1SJohannes Berg 	if (allmulti != sdata_allmulti) {
10950d143fe1SJohannes Berg 		if (dev->flags & IFF_ALLMULTI)
10960d143fe1SJohannes Berg 			atomic_inc(&local->iff_allmultis);
10970d143fe1SJohannes Berg 		else
10980d143fe1SJohannes Berg 			atomic_dec(&local->iff_allmultis);
10990d143fe1SJohannes Berg 		sdata->flags ^= IEEE80211_SDATA_ALLMULTI;
11000d143fe1SJohannes Berg 	}
11010d143fe1SJohannes Berg 
11023b8d81e0SJohannes Berg 	spin_lock_bh(&local->filter_lock);
110322bedad3SJiri Pirko 	__hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len);
11043b8d81e0SJohannes Berg 	spin_unlock_bh(&local->filter_lock);
11053ac64beeSJohannes Berg 	ieee80211_queue_work(&local->hw, &local->reconfig_filter);
11060d143fe1SJohannes Berg }
11070d143fe1SJohannes Berg 
110875636525SJohannes Berg /*
110975636525SJohannes Berg  * Called when the netdev is removed or, by the code below, before
111075636525SJohannes Berg  * the interface type changes.
111175636525SJohannes Berg  */
1112f142c6b9SJohannes Berg static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
11132c8dccc7SJohannes Berg {
11142c8dccc7SJohannes Berg 	int i;
11152c8dccc7SJohannes Berg 
111675636525SJohannes Berg 	/* free extra data */
11177907c7d3SJohannes Berg 	ieee80211_free_keys(sdata, false);
11182c8dccc7SJohannes Berg 
1119aee14cebSJouni Malinen 	ieee80211_debugfs_remove_netdev(sdata);
1120aee14cebSJouni Malinen 
1121988c0f72SJohannes Berg 	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
11222c8dccc7SJohannes Berg 		__skb_queue_purge(&sdata->fragments[i].skb_list);
112375636525SJohannes Berg 	sdata->fragment_next = 0;
112475636525SJohannes Berg 
112575636525SJohannes Berg 	if (ieee80211_vif_is_mesh(&sdata->vif))
11260371a08fSBob Copeland 		ieee80211_mesh_teardown_sdata(sdata);
112775636525SJohannes Berg }
112875636525SJohannes Berg 
1129f142c6b9SJohannes Berg static void ieee80211_uninit(struct net_device *dev)
1130f142c6b9SJohannes Berg {
1131f142c6b9SJohannes Berg 	ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev));
1132f142c6b9SJohannes Berg }
1133f142c6b9SJohannes Berg 
1134cf0277e7SJohannes Berg static u16 ieee80211_netdev_select_queue(struct net_device *dev,
1135f663dd9aSJason Wang 					 struct sk_buff *skb,
113699932d4fSDaniel Borkmann 					 void *accel_priv,
113799932d4fSDaniel Borkmann 					 select_queue_fallback_t fallback)
1138cf0277e7SJohannes Berg {
1139cf0277e7SJohannes Berg 	return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
1140cf0277e7SJohannes Berg }
1141cf0277e7SJohannes Berg 
1142bc1f4470Sstephen hemminger static void
11435a490510SJohannes Berg ieee80211_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
11445a490510SJohannes Berg {
11455a490510SJohannes Berg 	int i;
11465a490510SJohannes Berg 
11475a490510SJohannes Berg 	for_each_possible_cpu(i) {
11485a490510SJohannes Berg 		const struct pcpu_sw_netstats *tstats;
11495a490510SJohannes Berg 		u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
11505a490510SJohannes Berg 		unsigned int start;
11515a490510SJohannes Berg 
11525a490510SJohannes Berg 		tstats = per_cpu_ptr(dev->tstats, i);
11535a490510SJohannes Berg 
11545a490510SJohannes Berg 		do {
11555a490510SJohannes Berg 			start = u64_stats_fetch_begin_irq(&tstats->syncp);
11565a490510SJohannes Berg 			rx_packets = tstats->rx_packets;
11575a490510SJohannes Berg 			tx_packets = tstats->tx_packets;
11585a490510SJohannes Berg 			rx_bytes = tstats->rx_bytes;
11595a490510SJohannes Berg 			tx_bytes = tstats->tx_bytes;
11605a490510SJohannes Berg 		} while (u64_stats_fetch_retry_irq(&tstats->syncp, start));
11615a490510SJohannes Berg 
11625a490510SJohannes Berg 		stats->rx_packets += rx_packets;
11635a490510SJohannes Berg 		stats->tx_packets += tx_packets;
11645a490510SJohannes Berg 		stats->rx_bytes   += rx_bytes;
11655a490510SJohannes Berg 		stats->tx_bytes   += tx_bytes;
11665a490510SJohannes Berg 	}
11675a490510SJohannes Berg }
11685a490510SJohannes Berg 
1169587e729eSJohannes Berg static const struct net_device_ops ieee80211_dataif_ops = {
1170587e729eSJohannes Berg 	.ndo_open		= ieee80211_open,
1171587e729eSJohannes Berg 	.ndo_stop		= ieee80211_stop,
1172f142c6b9SJohannes Berg 	.ndo_uninit		= ieee80211_uninit,
1173587e729eSJohannes Berg 	.ndo_start_xmit		= ieee80211_subif_start_xmit,
1174afc4b13dSJiri Pirko 	.ndo_set_rx_mode	= ieee80211_set_multicast_list,
117547846c9bSJohannes Berg 	.ndo_set_mac_address 	= ieee80211_change_mac,
1176cf0277e7SJohannes Berg 	.ndo_select_queue	= ieee80211_netdev_select_queue,
11775a490510SJohannes Berg 	.ndo_get_stats64	= ieee80211_get_stats64,
1178587e729eSJohannes Berg };
1179587e729eSJohannes Berg 
1180cf0277e7SJohannes Berg static u16 ieee80211_monitor_select_queue(struct net_device *dev,
1181f663dd9aSJason Wang 					  struct sk_buff *skb,
118299932d4fSDaniel Borkmann 					  void *accel_priv,
118399932d4fSDaniel Borkmann 					  select_queue_fallback_t fallback)
1184cf0277e7SJohannes Berg {
1185cf0277e7SJohannes Berg 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1186cf0277e7SJohannes Berg 	struct ieee80211_local *local = sdata->local;
1187cf0277e7SJohannes Berg 	struct ieee80211_hdr *hdr;
1188cf0277e7SJohannes Berg 	struct ieee80211_radiotap_header *rtap = (void *)skb->data;
1189cf0277e7SJohannes Berg 
119032c5057bSJohannes Berg 	if (local->hw.queues < IEEE80211_NUM_ACS)
1191cf0277e7SJohannes Berg 		return 0;
1192cf0277e7SJohannes Berg 
1193cf0277e7SJohannes Berg 	if (skb->len < 4 ||
1194b49bb574SJohannes Berg 	    skb->len < le16_to_cpu(rtap->it_len) + 2 /* frame control */)
1195cf0277e7SJohannes Berg 		return 0; /* doesn't matter, frame will be dropped */
1196cf0277e7SJohannes Berg 
1197b49bb574SJohannes Berg 	hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
1198cf0277e7SJohannes Berg 
119900e96decSYoni Divinsky 	return ieee80211_select_queue_80211(sdata, skb, hdr);
1200cf0277e7SJohannes Berg }
1201cf0277e7SJohannes Berg 
1202587e729eSJohannes Berg static const struct net_device_ops ieee80211_monitorif_ops = {
1203587e729eSJohannes Berg 	.ndo_open		= ieee80211_open,
1204587e729eSJohannes Berg 	.ndo_stop		= ieee80211_stop,
1205f142c6b9SJohannes Berg 	.ndo_uninit		= ieee80211_uninit,
1206587e729eSJohannes Berg 	.ndo_start_xmit		= ieee80211_monitor_start_xmit,
1207afc4b13dSJiri Pirko 	.ndo_set_rx_mode	= ieee80211_set_multicast_list,
120831eba5bcSFelix Fietkau 	.ndo_set_mac_address 	= ieee80211_change_mac,
1209cf0277e7SJohannes Berg 	.ndo_select_queue	= ieee80211_monitor_select_queue,
12105a490510SJohannes Berg 	.ndo_get_stats64	= ieee80211_get_stats64,
1211587e729eSJohannes Berg };
1212587e729eSJohannes Berg 
12135a490510SJohannes Berg static void ieee80211_if_free(struct net_device *dev)
12145a490510SJohannes Berg {
12155a490510SJohannes Berg 	free_percpu(dev->tstats);
12165a490510SJohannes Berg 	free_netdev(dev);
12175a490510SJohannes Berg }
12185a490510SJohannes Berg 
1219587e729eSJohannes Berg static void ieee80211_if_setup(struct net_device *dev)
1220587e729eSJohannes Berg {
1221587e729eSJohannes Berg 	ether_setup(dev);
1222550fd08cSNeil Horman 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
1223587e729eSJohannes Berg 	dev->netdev_ops = &ieee80211_dataif_ops;
12245a490510SJohannes Berg 	dev->destructor = ieee80211_if_free;
1225587e729eSJohannes Berg }
1226587e729eSJohannes Berg 
122780a83cfcSMichal Kazior static void ieee80211_if_setup_no_queue(struct net_device *dev)
122880a83cfcSMichal Kazior {
122980a83cfcSMichal Kazior 	ieee80211_if_setup(dev);
123080a83cfcSMichal Kazior 	dev->priv_flags |= IFF_NO_QUEUE;
123180a83cfcSMichal Kazior }
123280a83cfcSMichal Kazior 
12331fa57d01SJohannes Berg static void ieee80211_iface_work(struct work_struct *work)
12341fa57d01SJohannes Berg {
12351fa57d01SJohannes Berg 	struct ieee80211_sub_if_data *sdata =
12361fa57d01SJohannes Berg 		container_of(work, struct ieee80211_sub_if_data, work);
12371fa57d01SJohannes Berg 	struct ieee80211_local *local = sdata->local;
12381fa57d01SJohannes Berg 	struct sk_buff *skb;
1239344eec67SJohannes Berg 	struct sta_info *sta;
12401fa57d01SJohannes Berg 
12411fa57d01SJohannes Berg 	if (!ieee80211_sdata_running(sdata))
12421fa57d01SJohannes Berg 		return;
12431fa57d01SJohannes Berg 
1244fc58c47eSAndrei Otcheretianski 	if (test_bit(SCAN_SW_SCANNING, &local->scanning))
12451fa57d01SJohannes Berg 		return;
12461fa57d01SJohannes Berg 
12474afaff17SEmmanuel Grumbach 	if (!ieee80211_can_run_worker(local))
12481fa57d01SJohannes Berg 		return;
12491fa57d01SJohannes Berg 
12501fa57d01SJohannes Berg 	/* first process frames */
12511fa57d01SJohannes Berg 	while ((skb = skb_dequeue(&sdata->skb_queue))) {
1252bed7ee6eSJohannes Berg 		struct ieee80211_mgmt *mgmt = (void *)skb->data;
1253bed7ee6eSJohannes Berg 
1254*699cb58cSJohannes Berg 		if (ieee80211_is_action(mgmt->frame_control) &&
1255bed7ee6eSJohannes Berg 		    mgmt->u.action.category == WLAN_CATEGORY_BACK) {
1256bed7ee6eSJohannes Berg 			int len = skb->len;
1257bed7ee6eSJohannes Berg 
1258a93e3644SJohannes Berg 			mutex_lock(&local->sta_mtx);
1259875ae5f6SFelix Fietkau 			sta = sta_info_get_bss(sdata, mgmt->sa);
1260bed7ee6eSJohannes Berg 			if (sta) {
1261bed7ee6eSJohannes Berg 				switch (mgmt->u.action.u.addba_req.action_code) {
1262bed7ee6eSJohannes Berg 				case WLAN_ACTION_ADDBA_REQ:
1263bed7ee6eSJohannes Berg 					ieee80211_process_addba_request(
1264bed7ee6eSJohannes Berg 							local, sta, mgmt, len);
1265bed7ee6eSJohannes Berg 					break;
1266bed7ee6eSJohannes Berg 				case WLAN_ACTION_ADDBA_RESP:
1267bed7ee6eSJohannes Berg 					ieee80211_process_addba_resp(local, sta,
1268bed7ee6eSJohannes Berg 								     mgmt, len);
1269bed7ee6eSJohannes Berg 					break;
1270bed7ee6eSJohannes Berg 				case WLAN_ACTION_DELBA:
1271bed7ee6eSJohannes Berg 					ieee80211_process_delba(sdata, sta,
1272bed7ee6eSJohannes Berg 								mgmt, len);
1273bed7ee6eSJohannes Berg 					break;
1274bed7ee6eSJohannes Berg 				default:
1275bed7ee6eSJohannes Berg 					WARN_ON(1);
1276bed7ee6eSJohannes Berg 					break;
1277bed7ee6eSJohannes Berg 				}
1278bed7ee6eSJohannes Berg 			}
1279a93e3644SJohannes Berg 			mutex_unlock(&local->sta_mtx);
128023a1f8d4SSara Sharon 		} else if (ieee80211_is_action(mgmt->frame_control) &&
128123a1f8d4SSara Sharon 			   mgmt->u.action.category == WLAN_CATEGORY_VHT) {
128223a1f8d4SSara Sharon 			switch (mgmt->u.action.u.vht_group_notif.action_code) {
1283d2941df8SJohannes Berg 			case WLAN_VHT_ACTION_OPMODE_NOTIF: {
1284d2941df8SJohannes Berg 				struct ieee80211_rx_status *status;
1285d2941df8SJohannes Berg 				enum nl80211_band band;
1286d2941df8SJohannes Berg 				u8 opmode;
1287d2941df8SJohannes Berg 
1288d2941df8SJohannes Berg 				status = IEEE80211_SKB_RXCB(skb);
1289d2941df8SJohannes Berg 				band = status->band;
1290d2941df8SJohannes Berg 				opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
1291d2941df8SJohannes Berg 
1292d2941df8SJohannes Berg 				mutex_lock(&local->sta_mtx);
1293d2941df8SJohannes Berg 				sta = sta_info_get_bss(sdata, mgmt->sa);
1294d2941df8SJohannes Berg 
1295d2941df8SJohannes Berg 				if (sta)
1296d2941df8SJohannes Berg 					ieee80211_vht_handle_opmode(sdata, sta,
1297d2941df8SJohannes Berg 								    opmode,
1298d2941df8SJohannes Berg 								    band);
1299d2941df8SJohannes Berg 
1300d2941df8SJohannes Berg 				mutex_unlock(&local->sta_mtx);
1301d2941df8SJohannes Berg 				break;
1302d2941df8SJohannes Berg 			}
130323a1f8d4SSara Sharon 			case WLAN_VHT_ACTION_GROUPID_MGMT:
130423a1f8d4SSara Sharon 				ieee80211_process_mu_groups(sdata, mgmt);
130523a1f8d4SSara Sharon 				break;
130623a1f8d4SSara Sharon 			default:
130723a1f8d4SSara Sharon 				WARN_ON(1);
130823a1f8d4SSara Sharon 				break;
130923a1f8d4SSara Sharon 			}
1310344eec67SJohannes Berg 		} else if (ieee80211_is_data_qos(mgmt->frame_control)) {
1311344eec67SJohannes Berg 			struct ieee80211_hdr *hdr = (void *)mgmt;
1312344eec67SJohannes Berg 			/*
1313344eec67SJohannes Berg 			 * So the frame isn't mgmt, but frame_control
1314344eec67SJohannes Berg 			 * is at the right place anyway, of course, so
1315344eec67SJohannes Berg 			 * the if statement is correct.
1316344eec67SJohannes Berg 			 *
1317344eec67SJohannes Berg 			 * Warn if we have other data frame types here,
1318344eec67SJohannes Berg 			 * they must not get here.
1319344eec67SJohannes Berg 			 */
1320344eec67SJohannes Berg 			WARN_ON(hdr->frame_control &
1321344eec67SJohannes Berg 					cpu_to_le16(IEEE80211_STYPE_NULLFUNC));
1322344eec67SJohannes Berg 			WARN_ON(!(hdr->seq_ctrl &
1323344eec67SJohannes Berg 					cpu_to_le16(IEEE80211_SCTL_FRAG)));
1324344eec67SJohannes Berg 			/*
1325344eec67SJohannes Berg 			 * This was a fragment of a frame, received while
1326344eec67SJohannes Berg 			 * a block-ack session was active. That cannot be
1327344eec67SJohannes Berg 			 * right, so terminate the session.
1328344eec67SJohannes Berg 			 */
1329a93e3644SJohannes Berg 			mutex_lock(&local->sta_mtx);
1330875ae5f6SFelix Fietkau 			sta = sta_info_get_bss(sdata, mgmt->sa);
1331344eec67SJohannes Berg 			if (sta) {
1332344eec67SJohannes Berg 				u16 tid = *ieee80211_get_qos_ctl(hdr) &
1333344eec67SJohannes Berg 						IEEE80211_QOS_CTL_TID_MASK;
1334344eec67SJohannes Berg 
1335344eec67SJohannes Berg 				__ieee80211_stop_rx_ba_session(
1336344eec67SJohannes Berg 					sta, tid, WLAN_BACK_RECIPIENT,
133753f73c09SJohannes Berg 					WLAN_REASON_QSTA_REQUIRE_SETUP,
133853f73c09SJohannes Berg 					true);
1339344eec67SJohannes Berg 			}
1340a93e3644SJohannes Berg 			mutex_unlock(&local->sta_mtx);
1341bed7ee6eSJohannes Berg 		} else switch (sdata->vif.type) {
13421fa57d01SJohannes Berg 		case NL80211_IFTYPE_STATION:
13431fa57d01SJohannes Berg 			ieee80211_sta_rx_queued_mgmt(sdata, skb);
13441fa57d01SJohannes Berg 			break;
13451fa57d01SJohannes Berg 		case NL80211_IFTYPE_ADHOC:
13461fa57d01SJohannes Berg 			ieee80211_ibss_rx_queued_mgmt(sdata, skb);
13471fa57d01SJohannes Berg 			break;
13481fa57d01SJohannes Berg 		case NL80211_IFTYPE_MESH_POINT:
13491fa57d01SJohannes Berg 			if (!ieee80211_vif_is_mesh(&sdata->vif))
13501fa57d01SJohannes Berg 				break;
13511fa57d01SJohannes Berg 			ieee80211_mesh_rx_queued_mgmt(sdata, skb);
13521fa57d01SJohannes Berg 			break;
13531fa57d01SJohannes Berg 		default:
13541fa57d01SJohannes Berg 			WARN(1, "frame for unexpected interface type");
13551fa57d01SJohannes Berg 			break;
13561fa57d01SJohannes Berg 		}
135736b3a628SJohannes Berg 
135836b3a628SJohannes Berg 		kfree_skb(skb);
13591fa57d01SJohannes Berg 	}
13601fa57d01SJohannes Berg 
13611fa57d01SJohannes Berg 	/* then other type-dependent work */
13621fa57d01SJohannes Berg 	switch (sdata->vif.type) {
13631fa57d01SJohannes Berg 	case NL80211_IFTYPE_STATION:
13641fa57d01SJohannes Berg 		ieee80211_sta_work(sdata);
13651fa57d01SJohannes Berg 		break;
13661fa57d01SJohannes Berg 	case NL80211_IFTYPE_ADHOC:
13671fa57d01SJohannes Berg 		ieee80211_ibss_work(sdata);
13681fa57d01SJohannes Berg 		break;
13691fa57d01SJohannes Berg 	case NL80211_IFTYPE_MESH_POINT:
13701fa57d01SJohannes Berg 		if (!ieee80211_vif_is_mesh(&sdata->vif))
13711fa57d01SJohannes Berg 			break;
13721fa57d01SJohannes Berg 		ieee80211_mesh_work(sdata);
13731fa57d01SJohannes Berg 		break;
1374239281f8SRostislav Lisovy 	case NL80211_IFTYPE_OCB:
1375239281f8SRostislav Lisovy 		ieee80211_ocb_work(sdata);
1376239281f8SRostislav Lisovy 		break;
13771fa57d01SJohannes Berg 	default:
13781fa57d01SJohannes Berg 		break;
13791fa57d01SJohannes Berg 	}
13801fa57d01SJohannes Berg }
13811fa57d01SJohannes Berg 
138204ecd257SJohannes Berg static void ieee80211_recalc_smps_work(struct work_struct *work)
138304ecd257SJohannes Berg {
138404ecd257SJohannes Berg 	struct ieee80211_sub_if_data *sdata =
138504ecd257SJohannes Berg 		container_of(work, struct ieee80211_sub_if_data, recalc_smps);
138604ecd257SJohannes Berg 
138704ecd257SJohannes Berg 	ieee80211_recalc_smps(sdata);
138804ecd257SJohannes Berg }
13891fa57d01SJohannes Berg 
139075636525SJohannes Berg /*
139175636525SJohannes Berg  * Helper function to initialise an interface to a specific type.
139275636525SJohannes Berg  */
139375636525SJohannes Berg static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
139405c914feSJohannes Berg 				  enum nl80211_iftype type)
139575636525SJohannes Berg {
1396239281f8SRostislav Lisovy 	static const u8 bssid_wildcard[ETH_ALEN] = {0xff, 0xff, 0xff,
1397239281f8SRostislav Lisovy 						    0xff, 0xff, 0xff};
1398239281f8SRostislav Lisovy 
139975636525SJohannes Berg 	/* clear type-dependent union */
140075636525SJohannes Berg 	memset(&sdata->u, 0, sizeof(sdata->u));
140175636525SJohannes Berg 
140275636525SJohannes Berg 	/* and set some type-dependent values */
140375636525SJohannes Berg 	sdata->vif.type = type;
14042ca27bcfSJohannes Berg 	sdata->vif.p2p = false;
140560719ffdSJohannes Berg 	sdata->wdev.iftype = type;
140675636525SJohannes Berg 
1407a621fa4dSJohannes Berg 	sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE);
1408a621fa4dSJohannes Berg 	sdata->control_port_no_encrypt = false;
14092475b1ccSMax Stepanov 	sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
1410d3a58df8SAvraham Stern 	sdata->vif.bss_conf.idle = true;
1411a621fa4dSJohannes Berg 
1412b53be792SSimon Wunderlich 	sdata->noack_map = 0;
1413b53be792SSimon Wunderlich 
1414f142c6b9SJohannes Berg 	/* only monitor/p2p-device differ */
1415f142c6b9SJohannes Berg 	if (sdata->dev) {
1416f142c6b9SJohannes Berg 		sdata->dev->netdev_ops = &ieee80211_dataif_ops;
141775636525SJohannes Berg 		sdata->dev->type = ARPHRD_ETHER;
1418f142c6b9SJohannes Berg 	}
141975636525SJohannes Berg 
142035f20c14SJohannes Berg 	skb_queue_head_init(&sdata->skb_queue);
14211fa57d01SJohannes Berg 	INIT_WORK(&sdata->work, ieee80211_iface_work);
142204ecd257SJohannes Berg 	INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work);
142373da7d5bSSimon Wunderlich 	INIT_WORK(&sdata->csa_finalize_work, ieee80211_csa_finalize_work);
1424484298adSMichal Kazior 	INIT_LIST_HEAD(&sdata->assigned_chanctx_list);
1425e3afb920SMichal Kazior 	INIT_LIST_HEAD(&sdata->reserved_chanctx_list);
142635f20c14SJohannes Berg 
142775636525SJohannes Berg 	switch (type) {
14282ca27bcfSJohannes Berg 	case NL80211_IFTYPE_P2P_GO:
14292ca27bcfSJohannes Berg 		type = NL80211_IFTYPE_AP;
14302ca27bcfSJohannes Berg 		sdata->vif.type = type;
14312ca27bcfSJohannes Berg 		sdata->vif.p2p = true;
14322ca27bcfSJohannes Berg 		/* fall through */
143305c914feSJohannes Berg 	case NL80211_IFTYPE_AP:
1434d012a605SMarco Porsch 		skb_queue_head_init(&sdata->u.ap.ps.bc_buf);
143575636525SJohannes Berg 		INIT_LIST_HEAD(&sdata->u.ap.vlans);
1436687da132SEmmanuel Grumbach 		INIT_WORK(&sdata->u.ap.request_smps_work,
1437687da132SEmmanuel Grumbach 			  ieee80211_request_smps_ap_work);
1438ad2d223aSJohannes Berg 		sdata->vif.bss_conf.bssid = sdata->vif.addr;
1439687da132SEmmanuel Grumbach 		sdata->u.ap.req_smps = IEEE80211_SMPS_OFF;
144075636525SJohannes Berg 		break;
14412ca27bcfSJohannes Berg 	case NL80211_IFTYPE_P2P_CLIENT:
14422ca27bcfSJohannes Berg 		type = NL80211_IFTYPE_STATION;
14432ca27bcfSJohannes Berg 		sdata->vif.type = type;
14442ca27bcfSJohannes Berg 		sdata->vif.p2p = true;
14452ca27bcfSJohannes Berg 		/* fall through */
144605c914feSJohannes Berg 	case NL80211_IFTYPE_STATION:
1447ad2d223aSJohannes Berg 		sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid;
14489c6bd790SJohannes Berg 		ieee80211_sta_setup_sdata(sdata);
1449472dbc45SJohannes Berg 		break;
14506e0bd6c3SRostislav Lisovy 	case NL80211_IFTYPE_OCB:
1451239281f8SRostislav Lisovy 		sdata->vif.bss_conf.bssid = bssid_wildcard;
1452239281f8SRostislav Lisovy 		ieee80211_ocb_setup_sdata(sdata);
14536e0bd6c3SRostislav Lisovy 		break;
145446900298SJohannes Berg 	case NL80211_IFTYPE_ADHOC:
1455ad2d223aSJohannes Berg 		sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
145646900298SJohannes Berg 		ieee80211_ibss_setup_sdata(sdata);
145746900298SJohannes Berg 		break;
145805c914feSJohannes Berg 	case NL80211_IFTYPE_MESH_POINT:
145975636525SJohannes Berg 		if (ieee80211_vif_is_mesh(&sdata->vif))
146075636525SJohannes Berg 			ieee80211_mesh_init_sdata(sdata);
146175636525SJohannes Berg 		break;
146205c914feSJohannes Berg 	case NL80211_IFTYPE_MONITOR:
146375636525SJohannes Berg 		sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP;
1464587e729eSJohannes Berg 		sdata->dev->netdev_ops = &ieee80211_monitorif_ops;
1465d8212184SAviya Erenfeld 		sdata->u.mntr.flags = MONITOR_FLAG_CONTROL |
146675636525SJohannes Berg 				      MONITOR_FLAG_OTHER_BSS;
146775636525SJohannes Berg 		break;
146805c914feSJohannes Berg 	case NL80211_IFTYPE_WDS:
1469ad2d223aSJohannes Berg 		sdata->vif.bss_conf.bssid = NULL;
1470ad2d223aSJohannes Berg 		break;
1471167e33f4SAyala Beker 	case NL80211_IFTYPE_NAN:
1472167e33f4SAyala Beker 		idr_init(&sdata->u.nan.function_inst_ids);
1473167e33f4SAyala Beker 		spin_lock_init(&sdata->u.nan.func_lock);
1474167e33f4SAyala Beker 		sdata->vif.bss_conf.bssid = sdata->vif.addr;
1475167e33f4SAyala Beker 		break;
147605c914feSJohannes Berg 	case NL80211_IFTYPE_AP_VLAN:
147798104fdeSJohannes Berg 	case NL80211_IFTYPE_P2P_DEVICE:
1478ad2d223aSJohannes Berg 		sdata->vif.bss_conf.bssid = sdata->vif.addr;
1479f142c6b9SJohannes Berg 		break;
148005c914feSJohannes Berg 	case NL80211_IFTYPE_UNSPECIFIED:
14812e161f78SJohannes Berg 	case NUM_NL80211_IFTYPES:
148275636525SJohannes Berg 		BUG();
148375636525SJohannes Berg 		break;
148475636525SJohannes Berg 	}
148575636525SJohannes Berg 
148675636525SJohannes Berg 	ieee80211_debugfs_add_netdev(sdata);
148775636525SJohannes Berg }
148875636525SJohannes Berg 
148934d4bc4dSJohannes Berg static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata,
149034d4bc4dSJohannes Berg 					   enum nl80211_iftype type)
149134d4bc4dSJohannes Berg {
149234d4bc4dSJohannes Berg 	struct ieee80211_local *local = sdata->local;
149334d4bc4dSJohannes Berg 	int ret, err;
14942ca27bcfSJohannes Berg 	enum nl80211_iftype internal_type = type;
14952ca27bcfSJohannes Berg 	bool p2p = false;
149634d4bc4dSJohannes Berg 
149734d4bc4dSJohannes Berg 	ASSERT_RTNL();
149834d4bc4dSJohannes Berg 
149934d4bc4dSJohannes Berg 	if (!local->ops->change_interface)
150034d4bc4dSJohannes Berg 		return -EBUSY;
150134d4bc4dSJohannes Berg 
150234d4bc4dSJohannes Berg 	switch (sdata->vif.type) {
150334d4bc4dSJohannes Berg 	case NL80211_IFTYPE_AP:
150434d4bc4dSJohannes Berg 	case NL80211_IFTYPE_STATION:
150534d4bc4dSJohannes Berg 	case NL80211_IFTYPE_ADHOC:
1506239281f8SRostislav Lisovy 	case NL80211_IFTYPE_OCB:
150734d4bc4dSJohannes Berg 		/*
150834d4bc4dSJohannes Berg 		 * Could maybe also all others here?
150934d4bc4dSJohannes Berg 		 * Just not sure how that interacts
151034d4bc4dSJohannes Berg 		 * with the RX/config path e.g. for
151134d4bc4dSJohannes Berg 		 * mesh.
151234d4bc4dSJohannes Berg 		 */
151334d4bc4dSJohannes Berg 		break;
151434d4bc4dSJohannes Berg 	default:
151534d4bc4dSJohannes Berg 		return -EBUSY;
151634d4bc4dSJohannes Berg 	}
151734d4bc4dSJohannes Berg 
151834d4bc4dSJohannes Berg 	switch (type) {
151934d4bc4dSJohannes Berg 	case NL80211_IFTYPE_AP:
152034d4bc4dSJohannes Berg 	case NL80211_IFTYPE_STATION:
152134d4bc4dSJohannes Berg 	case NL80211_IFTYPE_ADHOC:
1522239281f8SRostislav Lisovy 	case NL80211_IFTYPE_OCB:
152334d4bc4dSJohannes Berg 		/*
152434d4bc4dSJohannes Berg 		 * Could probably support everything
152534d4bc4dSJohannes Berg 		 * but WDS here (WDS do_open can fail
152634d4bc4dSJohannes Berg 		 * under memory pressure, which this
152734d4bc4dSJohannes Berg 		 * code isn't prepared to handle).
152834d4bc4dSJohannes Berg 		 */
152934d4bc4dSJohannes Berg 		break;
15302ca27bcfSJohannes Berg 	case NL80211_IFTYPE_P2P_CLIENT:
15312ca27bcfSJohannes Berg 		p2p = true;
15322ca27bcfSJohannes Berg 		internal_type = NL80211_IFTYPE_STATION;
15332ca27bcfSJohannes Berg 		break;
15342ca27bcfSJohannes Berg 	case NL80211_IFTYPE_P2P_GO:
15352ca27bcfSJohannes Berg 		p2p = true;
15362ca27bcfSJohannes Berg 		internal_type = NL80211_IFTYPE_AP;
15372ca27bcfSJohannes Berg 		break;
153834d4bc4dSJohannes Berg 	default:
153934d4bc4dSJohannes Berg 		return -EBUSY;
154034d4bc4dSJohannes Berg 	}
154134d4bc4dSJohannes Berg 
15422ca27bcfSJohannes Berg 	ret = ieee80211_check_concurrent_iface(sdata, internal_type);
154334d4bc4dSJohannes Berg 	if (ret)
154434d4bc4dSJohannes Berg 		return ret;
154534d4bc4dSJohannes Berg 
154634d4bc4dSJohannes Berg 	ieee80211_do_stop(sdata, false);
154734d4bc4dSJohannes Berg 
1548f142c6b9SJohannes Berg 	ieee80211_teardown_sdata(sdata);
154934d4bc4dSJohannes Berg 
15502ca27bcfSJohannes Berg 	ret = drv_change_interface(local, sdata, internal_type, p2p);
155134d4bc4dSJohannes Berg 	if (ret)
1552a9865538SJohannes Berg 		type = ieee80211_vif_type_p2p(&sdata->vif);
155334d4bc4dSJohannes Berg 
15543a25a8c8SJohannes Berg 	/*
15553a25a8c8SJohannes Berg 	 * Ignore return value here, there's not much we can do since
15563a25a8c8SJohannes Berg 	 * the driver changed the interface type internally already.
15573a25a8c8SJohannes Berg 	 * The warnings will hopefully make driver authors fix it :-)
15583a25a8c8SJohannes Berg 	 */
1559a9865538SJohannes Berg 	ieee80211_check_queues(sdata, type);
15603a25a8c8SJohannes Berg 
156134d4bc4dSJohannes Berg 	ieee80211_setup_sdata(sdata, type);
156234d4bc4dSJohannes Berg 
1563f142c6b9SJohannes Berg 	err = ieee80211_do_open(&sdata->wdev, false);
156434d4bc4dSJohannes Berg 	WARN(err, "type change: do_open returned %d", err);
156534d4bc4dSJohannes Berg 
156634d4bc4dSJohannes Berg 	return ret;
156734d4bc4dSJohannes Berg }
156834d4bc4dSJohannes Berg 
1569f3947e2dSJohannes Berg int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
157005c914feSJohannes Berg 			     enum nl80211_iftype type)
157175636525SJohannes Berg {
157234d4bc4dSJohannes Berg 	int ret;
157334d4bc4dSJohannes Berg 
1574f3947e2dSJohannes Berg 	ASSERT_RTNL();
1575f3947e2dSJohannes Berg 
15762ca27bcfSJohannes Berg 	if (type == ieee80211_vif_type_p2p(&sdata->vif))
1577f3947e2dSJohannes Berg 		return 0;
1578f3947e2dSJohannes Berg 
157934d4bc4dSJohannes Berg 	if (ieee80211_sdata_running(sdata)) {
158034d4bc4dSJohannes Berg 		ret = ieee80211_runtime_change_iftype(sdata, type);
158134d4bc4dSJohannes Berg 		if (ret)
158234d4bc4dSJohannes Berg 			return ret;
158334d4bc4dSJohannes Berg 	} else {
158475636525SJohannes Berg 		/* Purge and reset type-dependent state. */
1585f142c6b9SJohannes Berg 		ieee80211_teardown_sdata(sdata);
158675636525SJohannes Berg 		ieee80211_setup_sdata(sdata, type);
158734d4bc4dSJohannes Berg 	}
158875636525SJohannes Berg 
158975636525SJohannes Berg 	/* reset some values that shouldn't be kept across type changes */
15909bc383deSJohannes Berg 	if (type == NL80211_IFTYPE_STATION)
15919bc383deSJohannes Berg 		sdata->u.mgd.use_4addr = false;
1592f3947e2dSJohannes Berg 
1593f3947e2dSJohannes Berg 	return 0;
159475636525SJohannes Berg }
159575636525SJohannes Berg 
1596fa9029f8SJohannes Berg static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
1597f142c6b9SJohannes Berg 				       u8 *perm_addr, enum nl80211_iftype type)
1598fa9029f8SJohannes Berg {
1599fa9029f8SJohannes Berg 	struct ieee80211_sub_if_data *sdata;
1600fa9029f8SJohannes Berg 	u64 mask, start, addr, val, inc;
1601fa9029f8SJohannes Berg 	u8 *m;
1602fa9029f8SJohannes Berg 	u8 tmp_addr[ETH_ALEN];
1603fa9029f8SJohannes Berg 	int i;
1604fa9029f8SJohannes Berg 
1605fa9029f8SJohannes Berg 	/* default ... something at least */
1606f142c6b9SJohannes Berg 	memcpy(perm_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
1607fa9029f8SJohannes Berg 
1608fa9029f8SJohannes Berg 	if (is_zero_ether_addr(local->hw.wiphy->addr_mask) &&
1609fa9029f8SJohannes Berg 	    local->hw.wiphy->n_addresses <= 1)
1610fa9029f8SJohannes Berg 		return;
1611fa9029f8SJohannes Berg 
1612fa9029f8SJohannes Berg 	mutex_lock(&local->iflist_mtx);
1613fa9029f8SJohannes Berg 
1614fa9029f8SJohannes Berg 	switch (type) {
1615fa9029f8SJohannes Berg 	case NL80211_IFTYPE_MONITOR:
1616fa9029f8SJohannes Berg 		/* doesn't matter */
1617fa9029f8SJohannes Berg 		break;
1618fa9029f8SJohannes Berg 	case NL80211_IFTYPE_WDS:
1619fa9029f8SJohannes Berg 	case NL80211_IFTYPE_AP_VLAN:
1620fa9029f8SJohannes Berg 		/* match up with an AP interface */
1621fa9029f8SJohannes Berg 		list_for_each_entry(sdata, &local->interfaces, list) {
1622fa9029f8SJohannes Berg 			if (sdata->vif.type != NL80211_IFTYPE_AP)
1623fa9029f8SJohannes Berg 				continue;
1624f142c6b9SJohannes Berg 			memcpy(perm_addr, sdata->vif.addr, ETH_ALEN);
1625fa9029f8SJohannes Berg 			break;
1626fa9029f8SJohannes Berg 		}
1627fa9029f8SJohannes Berg 		/* keep default if no AP interface present */
1628fa9029f8SJohannes Berg 		break;
16296d71117aSJohannes Berg 	case NL80211_IFTYPE_P2P_CLIENT:
16306d71117aSJohannes Berg 	case NL80211_IFTYPE_P2P_GO:
163130686bf7SJohannes Berg 		if (ieee80211_hw_check(&local->hw, P2P_DEV_ADDR_FOR_INTF)) {
16326d71117aSJohannes Berg 			list_for_each_entry(sdata, &local->interfaces, list) {
16336d71117aSJohannes Berg 				if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE)
16346d71117aSJohannes Berg 					continue;
16356d71117aSJohannes Berg 				if (!ieee80211_sdata_running(sdata))
16366d71117aSJohannes Berg 					continue;
16376d71117aSJohannes Berg 				memcpy(perm_addr, sdata->vif.addr, ETH_ALEN);
16386d71117aSJohannes Berg 				goto out_unlock;
16396d71117aSJohannes Berg 			}
16406d71117aSJohannes Berg 		}
16416d71117aSJohannes Berg 		/* otherwise fall through */
1642fa9029f8SJohannes Berg 	default:
1643fa9029f8SJohannes Berg 		/* assign a new address if possible -- try n_addresses first */
1644fa9029f8SJohannes Berg 		for (i = 0; i < local->hw.wiphy->n_addresses; i++) {
1645fa9029f8SJohannes Berg 			bool used = false;
1646fa9029f8SJohannes Berg 
1647fa9029f8SJohannes Berg 			list_for_each_entry(sdata, &local->interfaces, list) {
1648496d7e8eSdingtianhong 				if (ether_addr_equal(local->hw.wiphy->addresses[i].addr,
1649496d7e8eSdingtianhong 						     sdata->vif.addr)) {
1650fa9029f8SJohannes Berg 					used = true;
1651fa9029f8SJohannes Berg 					break;
1652fa9029f8SJohannes Berg 				}
1653fa9029f8SJohannes Berg 			}
1654fa9029f8SJohannes Berg 
1655fa9029f8SJohannes Berg 			if (!used) {
1656f142c6b9SJohannes Berg 				memcpy(perm_addr,
1657fa9029f8SJohannes Berg 				       local->hw.wiphy->addresses[i].addr,
1658fa9029f8SJohannes Berg 				       ETH_ALEN);
1659fa9029f8SJohannes Berg 				break;
1660fa9029f8SJohannes Berg 			}
1661fa9029f8SJohannes Berg 		}
1662fa9029f8SJohannes Berg 
1663fa9029f8SJohannes Berg 		/* try mask if available */
1664fa9029f8SJohannes Berg 		if (is_zero_ether_addr(local->hw.wiphy->addr_mask))
1665fa9029f8SJohannes Berg 			break;
1666fa9029f8SJohannes Berg 
1667fa9029f8SJohannes Berg 		m = local->hw.wiphy->addr_mask;
1668fa9029f8SJohannes Berg 		mask =	((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
1669fa9029f8SJohannes Berg 			((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
1670fa9029f8SJohannes Berg 			((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
1671fa9029f8SJohannes Berg 
1672fa9029f8SJohannes Berg 		if (__ffs64(mask) + hweight64(mask) != fls64(mask)) {
1673fa9029f8SJohannes Berg 			/* not a contiguous mask ... not handled now! */
1674bdcbd8e0SJohannes Berg 			pr_info("not contiguous\n");
1675fa9029f8SJohannes Berg 			break;
1676fa9029f8SJohannes Berg 		}
1677fa9029f8SJohannes Berg 
1678ac20976dSHelmut Schaa 		/*
1679ac20976dSHelmut Schaa 		 * Pick address of existing interface in case user changed
1680ac20976dSHelmut Schaa 		 * MAC address manually, default to perm_addr.
1681ac20976dSHelmut Schaa 		 */
1682fa9029f8SJohannes Berg 		m = local->hw.wiphy->perm_addr;
1683ac20976dSHelmut Schaa 		list_for_each_entry(sdata, &local->interfaces, list) {
1684ac20976dSHelmut Schaa 			if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
1685ac20976dSHelmut Schaa 				continue;
1686ac20976dSHelmut Schaa 			m = sdata->vif.addr;
1687ac20976dSHelmut Schaa 			break;
1688ac20976dSHelmut Schaa 		}
1689fa9029f8SJohannes Berg 		start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
1690fa9029f8SJohannes Berg 			((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
1691fa9029f8SJohannes Berg 			((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
1692fa9029f8SJohannes Berg 
1693fa9029f8SJohannes Berg 		inc = 1ULL<<__ffs64(mask);
1694fa9029f8SJohannes Berg 		val = (start & mask);
1695fa9029f8SJohannes Berg 		addr = (start & ~mask) | (val & mask);
1696fa9029f8SJohannes Berg 		do {
1697fa9029f8SJohannes Berg 			bool used = false;
1698fa9029f8SJohannes Berg 
1699fa9029f8SJohannes Berg 			tmp_addr[5] = addr >> 0*8;
1700fa9029f8SJohannes Berg 			tmp_addr[4] = addr >> 1*8;
1701fa9029f8SJohannes Berg 			tmp_addr[3] = addr >> 2*8;
1702fa9029f8SJohannes Berg 			tmp_addr[2] = addr >> 3*8;
1703fa9029f8SJohannes Berg 			tmp_addr[1] = addr >> 4*8;
1704fa9029f8SJohannes Berg 			tmp_addr[0] = addr >> 5*8;
1705fa9029f8SJohannes Berg 
1706fa9029f8SJohannes Berg 			val += inc;
1707fa9029f8SJohannes Berg 
1708fa9029f8SJohannes Berg 			list_for_each_entry(sdata, &local->interfaces, list) {
1709496d7e8eSdingtianhong 				if (ether_addr_equal(tmp_addr, sdata->vif.addr)) {
1710fa9029f8SJohannes Berg 					used = true;
1711fa9029f8SJohannes Berg 					break;
1712fa9029f8SJohannes Berg 				}
1713fa9029f8SJohannes Berg 			}
1714fa9029f8SJohannes Berg 
1715fa9029f8SJohannes Berg 			if (!used) {
1716f142c6b9SJohannes Berg 				memcpy(perm_addr, tmp_addr, ETH_ALEN);
1717fa9029f8SJohannes Berg 				break;
1718fa9029f8SJohannes Berg 			}
1719fa9029f8SJohannes Berg 			addr = (start & ~mask) | (val & mask);
1720fa9029f8SJohannes Berg 		} while (addr != start);
1721fa9029f8SJohannes Berg 
1722fa9029f8SJohannes Berg 		break;
1723fa9029f8SJohannes Berg 	}
1724fa9029f8SJohannes Berg 
17256d71117aSJohannes Berg  out_unlock:
1726fa9029f8SJohannes Berg 	mutex_unlock(&local->iflist_mtx);
1727fa9029f8SJohannes Berg }
1728fa9029f8SJohannes Berg 
17293e122be0SJohannes Berg int ieee80211_if_add(struct ieee80211_local *local, const char *name,
17306bab2e19STom Gundersen 		     unsigned char name_assign_type,
173184efbb84SJohannes Berg 		     struct wireless_dev **new_wdev, enum nl80211_iftype type,
17322c8dccc7SJohannes Berg 		     struct vif_params *params)
17332c8dccc7SJohannes Berg {
1734f142c6b9SJohannes Berg 	struct net_device *ndev = NULL;
17352c8dccc7SJohannes Berg 	struct ieee80211_sub_if_data *sdata = NULL;
1736ba8c3d6fSFelix Fietkau 	struct txq_info *txqi;
173780a83cfcSMichal Kazior 	void (*if_setup)(struct net_device *dev);
173875636525SJohannes Berg 	int ret, i;
1739ded81f6bSJohannes Berg 	int txqs = 1;
17402c8dccc7SJohannes Berg 
17412c8dccc7SJohannes Berg 	ASSERT_RTNL();
174275636525SJohannes Berg 
1743708d50edSAyala Beker 	if (type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN) {
1744f142c6b9SJohannes Berg 		struct wireless_dev *wdev;
1745f142c6b9SJohannes Berg 
1746f142c6b9SJohannes Berg 		sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size,
1747f142c6b9SJohannes Berg 				GFP_KERNEL);
1748f142c6b9SJohannes Berg 		if (!sdata)
1749f142c6b9SJohannes Berg 			return -ENOMEM;
1750f142c6b9SJohannes Berg 		wdev = &sdata->wdev;
1751f142c6b9SJohannes Berg 
1752f142c6b9SJohannes Berg 		sdata->dev = NULL;
1753f142c6b9SJohannes Berg 		strlcpy(sdata->name, name, IFNAMSIZ);
1754f142c6b9SJohannes Berg 		ieee80211_assign_perm_addr(local, wdev->address, type);
1755f142c6b9SJohannes Berg 		memcpy(sdata->vif.addr, wdev->address, ETH_ALEN);
1756f142c6b9SJohannes Berg 	} else {
1757ba8c3d6fSFelix Fietkau 		int size = ALIGN(sizeof(*sdata) + local->hw.vif_data_size,
1758ba8c3d6fSFelix Fietkau 				 sizeof(void *));
1759ba8c3d6fSFelix Fietkau 		int txq_size = 0;
1760ba8c3d6fSFelix Fietkau 
1761ba8c3d6fSFelix Fietkau 		if (local->ops->wake_tx_queue)
1762ba8c3d6fSFelix Fietkau 			txq_size += sizeof(struct txq_info) +
1763ba8c3d6fSFelix Fietkau 				    local->hw.txq_data_size;
1764ba8c3d6fSFelix Fietkau 
176580a83cfcSMichal Kazior 		if (local->ops->wake_tx_queue)
176680a83cfcSMichal Kazior 			if_setup = ieee80211_if_setup_no_queue;
176780a83cfcSMichal Kazior 		else
176880a83cfcSMichal Kazior 			if_setup = ieee80211_if_setup;
176980a83cfcSMichal Kazior 
1770ded81f6bSJohannes Berg 		if (local->hw.queues >= IEEE80211_NUM_ACS)
1771ded81f6bSJohannes Berg 			txqs = IEEE80211_NUM_ACS;
1772ded81f6bSJohannes Berg 
1773ba8c3d6fSFelix Fietkau 		ndev = alloc_netdev_mqs(size + txq_size,
17746bab2e19STom Gundersen 					name, name_assign_type,
177580a83cfcSMichal Kazior 					if_setup, txqs, 1);
17762c8dccc7SJohannes Berg 		if (!ndev)
17772c8dccc7SJohannes Berg 			return -ENOMEM;
1778a272a720SJohannes Berg 		dev_net_set(ndev, wiphy_net(local->hw.wiphy));
17792c8dccc7SJohannes Berg 
17805a490510SJohannes Berg 		ndev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
17815a490510SJohannes Berg 		if (!ndev->tstats) {
17825a490510SJohannes Berg 			free_netdev(ndev);
17835a490510SJohannes Berg 			return -ENOMEM;
17845a490510SJohannes Berg 		}
17855a490510SJohannes Berg 
1786f3994eceSJohannes Berg 		ndev->needed_headroom = local->tx_headroom +
1787f3994eceSJohannes Berg 					4*6 /* four MAC addresses */
1788f3994eceSJohannes Berg 					+ 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */
1789f3994eceSJohannes Berg 					+ 6 /* mesh */
1790f3994eceSJohannes Berg 					+ 8 /* rfc1042/bridge tunnel */
1791f3994eceSJohannes Berg 					- ETH_HLEN /* ethernet hard_header_len */
1792f3994eceSJohannes Berg 					+ IEEE80211_ENCRYPT_HEADROOM;
1793f3994eceSJohannes Berg 		ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM;
1794f3994eceSJohannes Berg 
179559e7e707SThadeu Lima de Souza Cascardo 		ret = dev_alloc_name(ndev, ndev->name);
1796f142c6b9SJohannes Berg 		if (ret < 0) {
1797e6436be2SJohannes Berg 			ieee80211_if_free(ndev);
1798f142c6b9SJohannes Berg 			return ret;
1799f142c6b9SJohannes Berg 		}
180059e7e707SThadeu Lima de Souza Cascardo 
1801f142c6b9SJohannes Berg 		ieee80211_assign_perm_addr(local, ndev->perm_addr, type);
1802b5dfae02SBen Greear 		if (params && is_valid_ether_addr(params->macaddr))
1803b5dfae02SBen Greear 			memcpy(ndev->dev_addr, params->macaddr, ETH_ALEN);
1804b5dfae02SBen Greear 		else
1805fa9029f8SJohannes Berg 			memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN);
18062c8dccc7SJohannes Berg 		SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
18072c8dccc7SJohannes Berg 
1808f142c6b9SJohannes Berg 		/* don't use IEEE80211_DEV_TO_SUB_IF -- it checks too much */
18093e122be0SJohannes Berg 		sdata = netdev_priv(ndev);
18102c8dccc7SJohannes Berg 		ndev->ieee80211_ptr = &sdata->wdev;
181147846c9bSJohannes Berg 		memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN);
181247846c9bSJohannes Berg 		memcpy(sdata->name, ndev->name, IFNAMSIZ);
181375636525SJohannes Berg 
1814ba8c3d6fSFelix Fietkau 		if (txq_size) {
1815ba8c3d6fSFelix Fietkau 			txqi = netdev_priv(ndev) + size;
1816fa962b92SMichal Kazior 			ieee80211_txq_init(sdata, NULL, txqi, 0);
1817ba8c3d6fSFelix Fietkau 		}
1818ba8c3d6fSFelix Fietkau 
1819f142c6b9SJohannes Berg 		sdata->dev = ndev;
1820f142c6b9SJohannes Berg 	}
1821f142c6b9SJohannes Berg 
182275636525SJohannes Berg 	/* initialise type-independent data */
18232c8dccc7SJohannes Berg 	sdata->wdev.wiphy = local->hw.wiphy;
18242c8dccc7SJohannes Berg 	sdata->local = local;
182575636525SJohannes Berg 
182675636525SJohannes Berg 	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
182775636525SJohannes Berg 		skb_queue_head_init(&sdata->fragments[i].skb_list);
182875636525SJohannes Berg 
182975636525SJohannes Berg 	INIT_LIST_HEAD(&sdata->key_list);
183075636525SJohannes Berg 
1831164eb02dSSimon Wunderlich 	INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work,
1832164eb02dSSimon Wunderlich 			  ieee80211_dfs_cac_timer_work);
18338d1f7ecdSJohannes Berg 	INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk,
18348d1f7ecdSJohannes Berg 			  ieee80211_delayed_tailroom_dec);
183597f97b1fSJohannes Berg 
183657fbcce3SJohannes Berg 	for (i = 0; i < NUM_NL80211_BANDS; i++) {
183737eb0b16SJouni Malinen 		struct ieee80211_supported_band *sband;
183837eb0b16SJouni Malinen 		sband = local->hw.wiphy->bands[i];
183937eb0b16SJouni Malinen 		sdata->rc_rateidx_mask[i] =
184037eb0b16SJouni Malinen 			sband ? (1 << sband->n_bitrates) - 1 : 0;
1841b119ad6eSLorenzo Bianconi 		if (sband) {
1842b119ad6eSLorenzo Bianconi 			__le16 cap;
1843b119ad6eSLorenzo Bianconi 			u16 *vht_rate_mask;
1844b119ad6eSLorenzo Bianconi 
184519468413SSimon Wunderlich 			memcpy(sdata->rc_rateidx_mcs_mask[i],
184619468413SSimon Wunderlich 			       sband->ht_cap.mcs.rx_mask,
184719468413SSimon Wunderlich 			       sizeof(sdata->rc_rateidx_mcs_mask[i]));
1848b119ad6eSLorenzo Bianconi 
1849b119ad6eSLorenzo Bianconi 			cap = sband->vht_cap.vht_mcs.rx_mcs_map;
1850b119ad6eSLorenzo Bianconi 			vht_rate_mask = sdata->rc_rateidx_vht_mcs_mask[i];
1851b119ad6eSLorenzo Bianconi 			ieee80211_get_vht_mask_from_cap(cap, vht_rate_mask);
1852b119ad6eSLorenzo Bianconi 		} else {
185319468413SSimon Wunderlich 			memset(sdata->rc_rateidx_mcs_mask[i], 0,
185419468413SSimon Wunderlich 			       sizeof(sdata->rc_rateidx_mcs_mask[i]));
1855b119ad6eSLorenzo Bianconi 			memset(sdata->rc_rateidx_vht_mcs_mask[i], 0,
1856b119ad6eSLorenzo Bianconi 			       sizeof(sdata->rc_rateidx_vht_mcs_mask[i]));
1857b119ad6eSLorenzo Bianconi 		}
185837eb0b16SJouni Malinen 	}
185975636525SJohannes Berg 
18603a25a8c8SJohannes Berg 	ieee80211_set_default_queues(sdata);
18613a25a8c8SJohannes Berg 
18621ea6f9c0SJohannes Berg 	sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
18631ea6f9c0SJohannes Berg 	sdata->user_power_level = local->user_power_level;
18641ea6f9c0SJohannes Berg 
18652475b1ccSMax Stepanov 	sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
18662475b1ccSMax Stepanov 
186775636525SJohannes Berg 	/* setup type-dependent data */
186875636525SJohannes Berg 	ieee80211_setup_sdata(sdata, type);
18692c8dccc7SJohannes Berg 
1870f142c6b9SJohannes Berg 	if (ndev) {
18719bc383deSJohannes Berg 		if (params) {
18729bc383deSJohannes Berg 			ndev->ieee80211_ptr->use_4addr = params->use_4addr;
18739bc383deSJohannes Berg 			if (type == NL80211_IFTYPE_STATION)
18749bc383deSJohannes Berg 				sdata->u.mgd.use_4addr = params->use_4addr;
18759bc383deSJohannes Berg 		}
18769bc383deSJohannes Berg 
187772d78728SArik Nemtsov 		ndev->features |= local->hw.netdev_features;
187872d78728SArik Nemtsov 
1879b7ffbd7eSJohannes Berg 		netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops);
1880b7ffbd7eSJohannes Berg 
18819c22b4a3SJarod Wilson 		/* MTU range: 256 - 2304 */
18829c22b4a3SJarod Wilson 		ndev->min_mtu = 256;
18839c22b4a3SJarod Wilson 		ndev->max_mtu = IEEE80211_MAX_DATA_LEN;
18849c22b4a3SJarod Wilson 
18852c8dccc7SJohannes Berg 		ret = register_netdevice(ndev);
1886f142c6b9SJohannes Berg 		if (ret) {
1887e6436be2SJohannes Berg 			ieee80211_if_free(ndev);
1888f142c6b9SJohannes Berg 			return ret;
1889f142c6b9SJohannes Berg 		}
1890f142c6b9SJohannes Berg 	}
18912c8dccc7SJohannes Berg 
1892c771c9d8SJohannes Berg 	mutex_lock(&local->iflist_mtx);
18932c8dccc7SJohannes Berg 	list_add_tail_rcu(&sdata->list, &local->interfaces);
1894c771c9d8SJohannes Berg 	mutex_unlock(&local->iflist_mtx);
18952c8dccc7SJohannes Berg 
189684efbb84SJohannes Berg 	if (new_wdev)
189784efbb84SJohannes Berg 		*new_wdev = &sdata->wdev;
18982c8dccc7SJohannes Berg 
18992c8dccc7SJohannes Berg 	return 0;
19002c8dccc7SJohannes Berg }
19012c8dccc7SJohannes Berg 
1902f698d856SJasper Bryant-Greene void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata)
19032c8dccc7SJohannes Berg {
19042c8dccc7SJohannes Berg 	ASSERT_RTNL();
19052c8dccc7SJohannes Berg 
1906c771c9d8SJohannes Berg 	mutex_lock(&sdata->local->iflist_mtx);
19072c8dccc7SJohannes Berg 	list_del_rcu(&sdata->list);
1908c771c9d8SJohannes Berg 	mutex_unlock(&sdata->local->iflist_mtx);
1909c771c9d8SJohannes Berg 
19102c8dccc7SJohannes Berg 	synchronize_rcu();
1911f142c6b9SJohannes Berg 
1912f142c6b9SJohannes Berg 	if (sdata->dev) {
1913f698d856SJasper Bryant-Greene 		unregister_netdevice(sdata->dev);
1914f142c6b9SJohannes Berg 	} else {
1915f142c6b9SJohannes Berg 		cfg80211_unregister_wdev(&sdata->wdev);
1916835112b2SEliad Peller 		ieee80211_teardown_sdata(sdata);
1917f142c6b9SJohannes Berg 		kfree(sdata);
1918f142c6b9SJohannes Berg 	}
1919f142c6b9SJohannes Berg }
1920f142c6b9SJohannes Berg 
1921f142c6b9SJohannes Berg void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata)
1922f142c6b9SJohannes Berg {
1923f142c6b9SJohannes Berg 	if (WARN_ON_ONCE(!test_bit(SDATA_STATE_RUNNING, &sdata->state)))
1924f142c6b9SJohannes Berg 		return;
1925f142c6b9SJohannes Berg 	ieee80211_do_stop(sdata, true);
19262c8dccc7SJohannes Berg }
19272c8dccc7SJohannes Berg 
192875636525SJohannes Berg void ieee80211_remove_interfaces(struct ieee80211_local *local)
19292c8dccc7SJohannes Berg {
193075636525SJohannes Berg 	struct ieee80211_sub_if_data *sdata, *tmp;
1931efe117abSEric Dumazet 	LIST_HEAD(unreg_list);
1932f142c6b9SJohannes Berg 	LIST_HEAD(wdev_list);
19332c8dccc7SJohannes Berg 
193475636525SJohannes Berg 	ASSERT_RTNL();
193575636525SJohannes Berg 
1936d8d9008cSJohannes Berg 	/* Before destroying the interfaces, make sure they're all stopped so
1937d8d9008cSJohannes Berg 	 * that the hardware is stopped. Otherwise, the driver might still be
1938d8d9008cSJohannes Berg 	 * iterating the interfaces during the shutdown, e.g. from a worker
1939d8d9008cSJohannes Berg 	 * or from RX processing or similar, and if it does so (using atomic
1940d8d9008cSJohannes Berg 	 * iteration) while we're manipulating the list, the iteration will
1941d8d9008cSJohannes Berg 	 * crash.
1942d8d9008cSJohannes Berg 	 *
1943d8d9008cSJohannes Berg 	 * After this, the hardware should be stopped and the driver should
1944d8d9008cSJohannes Berg 	 * have stopped all of its activities, so that we can do RCU-unaware
1945d8d9008cSJohannes Berg 	 * manipulations of the interface list below.
1946c8aa22dbSJohannes Berg 	 */
1947d8d9008cSJohannes Berg 	cfg80211_shutdown_all_interfaces(local->hw.wiphy);
1948d8d9008cSJohannes Berg 
1949d8d9008cSJohannes Berg 	WARN(local->open_count, "%s: open count remains %d\n",
1950d8d9008cSJohannes Berg 	     wiphy_name(local->hw.wiphy), local->open_count);
1951c8aa22dbSJohannes Berg 
1952c771c9d8SJohannes Berg 	mutex_lock(&local->iflist_mtx);
1953efe117abSEric Dumazet 	list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
195475636525SJohannes Berg 		list_del(&sdata->list);
1955c771c9d8SJohannes Berg 
1956f142c6b9SJohannes Berg 		if (sdata->dev)
1957efe117abSEric Dumazet 			unregister_netdevice_queue(sdata->dev, &unreg_list);
1958f142c6b9SJohannes Berg 		else
1959f142c6b9SJohannes Berg 			list_add(&sdata->list, &wdev_list);
196075636525SJohannes Berg 	}
1961efe117abSEric Dumazet 	mutex_unlock(&local->iflist_mtx);
1962efe117abSEric Dumazet 	unregister_netdevice_many(&unreg_list);
1963f142c6b9SJohannes Berg 
1964f142c6b9SJohannes Berg 	list_for_each_entry_safe(sdata, tmp, &wdev_list, list) {
1965f142c6b9SJohannes Berg 		list_del(&sdata->list);
1966f142c6b9SJohannes Berg 		cfg80211_unregister_wdev(&sdata->wdev);
1967f142c6b9SJohannes Berg 		kfree(sdata);
1968f142c6b9SJohannes Berg 	}
19692c8dccc7SJohannes Berg }
19705cff20e6SJohannes Berg 
197147846c9bSJohannes Berg static int netdev_notify(struct notifier_block *nb,
1972351638e7SJiri Pirko 			 unsigned long state, void *ptr)
197347846c9bSJohannes Berg {
1974351638e7SJiri Pirko 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
197547846c9bSJohannes Berg 	struct ieee80211_sub_if_data *sdata;
197647846c9bSJohannes Berg 
197747846c9bSJohannes Berg 	if (state != NETDEV_CHANGENAME)
19788bd811aaSZhao, Gang 		return NOTIFY_DONE;
197947846c9bSJohannes Berg 
198047846c9bSJohannes Berg 	if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
19818bd811aaSZhao, Gang 		return NOTIFY_DONE;
198247846c9bSJohannes Berg 
198347846c9bSJohannes Berg 	if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
19848bd811aaSZhao, Gang 		return NOTIFY_DONE;
198547846c9bSJohannes Berg 
198647846c9bSJohannes Berg 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
19872f5265e6SJohannes Berg 	memcpy(sdata->name, dev->name, IFNAMSIZ);
198847846c9bSJohannes Berg 	ieee80211_debugfs_rename_netdev(sdata);
19898bd811aaSZhao, Gang 
19908bd811aaSZhao, Gang 	return NOTIFY_OK;
199147846c9bSJohannes Berg }
199247846c9bSJohannes Berg 
199347846c9bSJohannes Berg static struct notifier_block mac80211_netdev_notifier = {
199447846c9bSJohannes Berg 	.notifier_call = netdev_notify,
199547846c9bSJohannes Berg };
199647846c9bSJohannes Berg 
199747846c9bSJohannes Berg int ieee80211_iface_init(void)
199847846c9bSJohannes Berg {
199947846c9bSJohannes Berg 	return register_netdevice_notifier(&mac80211_netdev_notifier);
200047846c9bSJohannes Berg }
200147846c9bSJohannes Berg 
200247846c9bSJohannes Berg void ieee80211_iface_exit(void)
200347846c9bSJohannes Berg {
200447846c9bSJohannes Berg 	unregister_netdevice_notifier(&mac80211_netdev_notifier);
200547846c9bSJohannes Berg }
200672f15d53SMichael Braun 
200772f15d53SMichael Braun void ieee80211_vif_inc_num_mcast(struct ieee80211_sub_if_data *sdata)
200872f15d53SMichael Braun {
200972f15d53SMichael Braun 	if (sdata->vif.type == NL80211_IFTYPE_AP)
201072f15d53SMichael Braun 		atomic_inc(&sdata->u.ap.num_mcast_sta);
201172f15d53SMichael Braun 	else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
201272f15d53SMichael Braun 		atomic_inc(&sdata->u.vlan.num_mcast_sta);
201372f15d53SMichael Braun }
201472f15d53SMichael Braun 
201572f15d53SMichael Braun void ieee80211_vif_dec_num_mcast(struct ieee80211_sub_if_data *sdata)
201672f15d53SMichael Braun {
201772f15d53SMichael Braun 	if (sdata->vif.type == NL80211_IFTYPE_AP)
201872f15d53SMichael Braun 		atomic_dec(&sdata->u.ap.num_mcast_sta);
201972f15d53SMichael Braun 	else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
202072f15d53SMichael Braun 		atomic_dec(&sdata->u.vlan.num_mcast_sta);
202172f15d53SMichael Braun }
2022