main.c revision ea95bba41e69c616bb1512cf59d22f33266b8568
1f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc/*
2f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * Copyright 2002-2005, Instant802 Networks, Inc.
3f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * Copyright 2005-2006, Devicescape Software, Inc.
4f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
5f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc *
6f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * This program is free software; you can redistribute it and/or modify
7f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * it under the terms of the GNU General Public License version 2 as
8f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * published by the Free Software Foundation.
9f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc */
10f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
11f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include <net/mac80211.h>
12f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include <net/ieee80211_radiotap.h>
13f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include <linux/module.h>
14f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include <linux/init.h>
15f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include <linux/netdevice.h>
16f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include <linux/types.h>
17f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include <linux/slab.h>
18f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include <linux/skbuff.h>
19f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include <linux/etherdevice.h>
20f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include <linux/if_arp.h>
21f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include <linux/wireless.h>
22f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include <linux/rtnetlink.h>
23f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include <linux/bitmap.h>
24881d966b48b035ab3f3aeaae0f3d3f9b584f45b2Eric W. Biederman#include <net/net_namespace.h>
25f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include <net/cfg80211.h>
26f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
27f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include "ieee80211_i.h"
282c8dccc77420fb7433da5674818959d3499d35beJohannes Berg#include "rate.h"
29f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo#include "mesh.h"
30f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include "wep.h"
31f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include "wme.h"
32f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include "aes_ccm.h"
332c8dccc77420fb7433da5674818959d3499d35beJohannes Berg#include "led.h"
34e0eb68596232788bc352368f2fbc3cb088e42e41Michael Wu#include "cfg.h"
35e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc#include "debugfs.h"
36e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc#include "debugfs_netdev.h"
37f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
38b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg/*
39b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg * For seeing transmitted packets on monitor interfaces
40b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg * we have a radiotap header too.
41b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg */
42b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Bergstruct ieee80211_tx_status_rtap_hdr {
43b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	struct ieee80211_radiotap_header hdr;
44b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	__le16 tx_flags;
45b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	u8 data_retries;
46b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg} __attribute__ ((packed));
47b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg
48b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg/* common interface routines */
49b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg
50b95cce3576813ac3f86bafa6b5daaaaf7574b0feStephen Hemmingerstatic int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr)
51b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{
52b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */
53b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	return ETH_ALEN;
54b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg}
55f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
564150c57212ad134765dd78c654a4b9906252b66dJohannes Berg/* must be called under mdev tx lock */
574150c57212ad134765dd78c654a4b9906252b66dJohannes Bergstatic void ieee80211_configure_filter(struct ieee80211_local *local)
584150c57212ad134765dd78c654a4b9906252b66dJohannes Berg{
594150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	unsigned int changed_flags;
604150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	unsigned int new_flags = 0;
614150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
6253918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg	if (atomic_read(&local->iff_promiscs))
634150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		new_flags |= FIF_PROMISC_IN_BSS;
644150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
6553918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg	if (atomic_read(&local->iff_allmultis))
664150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		new_flags |= FIF_ALLMULTI;
674150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
684150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	if (local->monitors)
698cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		new_flags |= FIF_BCN_PRBRESP_PROMISC;
708cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu
718cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu	if (local->fif_fcsfail)
728cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		new_flags |= FIF_FCSFAIL;
738cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu
748cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu	if (local->fif_plcpfail)
758cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		new_flags |= FIF_PLCPFAIL;
768cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu
778cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu	if (local->fif_control)
788cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		new_flags |= FIF_CONTROL;
798cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu
808cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu	if (local->fif_other_bss)
818cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		new_flags |= FIF_OTHER_BSS;
824150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
834150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	changed_flags = local->filter_flags ^ new_flags;
844150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
854150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	/* be a bit nasty */
864150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	new_flags |= (1<<31);
874150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
884150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	local->ops->configure_filter(local_to_hw(local),
894150c57212ad134765dd78c654a4b9906252b66dJohannes Berg				     changed_flags, &new_flags,
904150c57212ad134765dd78c654a4b9906252b66dJohannes Berg				     local->mdev->mc_count,
914150c57212ad134765dd78c654a4b9906252b66dJohannes Berg				     local->mdev->mc_list);
924150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
934150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	WARN_ON(new_flags & (1<<31));
944150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
954150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	local->filter_flags = new_flags & ~(1<<31);
964150c57212ad134765dd78c654a4b9906252b66dJohannes Berg}
974150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
98b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg/* master interface */
99f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
100b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic int ieee80211_master_open(struct net_device *dev)
101b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{
102b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
103b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	struct ieee80211_sub_if_data *sdata;
104b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	int res = -EOPNOTSUPP;
105f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
10679010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	/* we hold the RTNL here so can safely walk the list */
10779010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	list_for_each_entry(sdata, &local->interfaces, list) {
1083e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg		if (netif_running(sdata->dev)) {
109b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg			res = 0;
110b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg			break;
111b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		}
112b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	}
11336d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg
11436d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg	if (res)
11536d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg		return res;
11636d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg
11751cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller	netif_tx_start_all_queues(local->mdev);
11836d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg
11936d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg	return 0;
120b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg}
121f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
122b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic int ieee80211_master_stop(struct net_device *dev)
123f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
124b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
125b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	struct ieee80211_sub_if_data *sdata;
126f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
12779010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	/* we hold the RTNL here so can safely walk the list */
12879010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	list_for_each_entry(sdata, &local->interfaces, list)
1293e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg		if (netif_running(sdata->dev))
130b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg			dev_close(sdata->dev);
131f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
132b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	return 0;
133b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg}
134f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1354150c57212ad134765dd78c654a4b9906252b66dJohannes Bergstatic void ieee80211_master_set_multicast_list(struct net_device *dev)
1364150c57212ad134765dd78c654a4b9906252b66dJohannes Berg{
1374150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1384150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
1394150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	ieee80211_configure_filter(local);
1404150c57212ad134765dd78c654a4b9906252b66dJohannes Berg}
1414150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
142b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg/* regular interfaces */
143f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
144b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
145f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
146f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo	int meshhdrlen;
147f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
148f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo
149f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo	meshhdrlen = (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) ? 5 : 0;
150f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo
151b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	/* FIX: what would be proper limits for MTU?
152b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	 * This interface uses 802.3 frames. */
153f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo	if (new_mtu < 256 ||
154f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg	    new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) {
155b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		return -EINVAL;
156b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	}
157f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
158b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
159b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu);
160b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
161b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	dev->mtu = new_mtu;
162f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	return 0;
163f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
164f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
165b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic inline int identical_mac_addr_allowed(int type1, int type2)
166b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{
167b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	return (type1 == IEEE80211_IF_TYPE_MNTR ||
168b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		type2 == IEEE80211_IF_TYPE_MNTR ||
169b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		(type1 == IEEE80211_IF_TYPE_AP &&
170b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		 type2 == IEEE80211_IF_TYPE_WDS) ||
171b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		(type1 == IEEE80211_IF_TYPE_WDS &&
172b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		 (type2 == IEEE80211_IF_TYPE_WDS ||
173b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		  type2 == IEEE80211_IF_TYPE_AP)) ||
174b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		(type1 == IEEE80211_IF_TYPE_AP &&
175b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		 type2 == IEEE80211_IF_TYPE_VLAN) ||
176b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		(type1 == IEEE80211_IF_TYPE_VLAN &&
177b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		 (type2 == IEEE80211_IF_TYPE_AP ||
178b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		  type2 == IEEE80211_IF_TYPE_VLAN)));
179b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg}
180f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
181b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic int ieee80211_open(struct net_device *dev)
182e2ebc74d7e3d71600640db6fbb28cc2f362184c1Johannes Berg{
183b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	struct ieee80211_sub_if_data *sdata, *nsdata;
184b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
185fc32f9243dc93e75f81457e95d9cb90ee6136d94Tomas Winkler	struct sta_info *sta;
186b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	struct ieee80211_if_init_conf conf;
187fc32f9243dc93e75f81457e95d9cb90ee6136d94Tomas Winkler	u32 changed = 0;
188b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	int res;
189ceffefd15aac78841432230627308b8a382dbcfcMichael Buesch	bool need_hw_reconfig = 0;
190f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
191b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1920ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg
19379010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	/* we hold the RTNL here so can safely walk the list */
19479010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	list_for_each_entry(nsdata, &local->interfaces, list) {
195b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		struct net_device *ndev = nsdata->dev;
196e2ebc74d7e3d71600640db6fbb28cc2f362184c1Johannes Berg
1973e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg		if (ndev != dev && netif_running(ndev)) {
198665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			/*
199665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			 * Allow only a single IBSS interface to be up at any
200665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			 * time. This is restricted because beacon distribution
201665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			 * cannot work properly if both are in the same IBSS.
202665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			 *
203665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			 * To remove this restriction we'd have to disallow them
204665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			 * from setting the same SSID on different IBSS interfaces
205665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			 * belonging to the same hardware. Then, however, we're
206665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			 * faced with having to adopt two different TSF timers...
207665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			 */
208665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
209665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			    nsdata->vif.type == IEEE80211_IF_TYPE_IBSS)
210665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg				return -EBUSY;
211665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg
212665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			/*
213665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			 * The remaining checks are only performed for interfaces
214665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			 * with the same MAC address.
215665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			 */
216665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			if (compare_ether_addr(dev->dev_addr, ndev->dev_addr))
217665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg				continue;
218665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg
2190ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg			/*
2200ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg			 * check whether it may have the same address
2210ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg			 */
22251fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg			if (!identical_mac_addr_allowed(sdata->vif.type,
22351fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg							nsdata->vif.type))
2240ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg				return -ENOTUNIQ;
2250ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg
2260ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg			/*
2270ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg			 * can only add VLANs to enabled APs
2280ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg			 */
22951fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg			if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN &&
230665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg			    nsdata->vif.type == IEEE80211_IF_TYPE_AP)
2313e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg				sdata->bss = &nsdata->u.ap;
232b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		}
233b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	}
234f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
23551fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg	switch (sdata->vif.type) {
2360ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg	case IEEE80211_IF_TYPE_WDS:
237e94e106831403d5028e7bb73c3163951134de1baJohannes Berg		if (!is_valid_ether_addr(sdata->u.wds.remote_addr))
2380ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg			return -ENOLINK;
2390ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg		break;
2400ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg	case IEEE80211_IF_TYPE_VLAN:
2413e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg		if (!sdata->bss)
2420ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg			return -ENOLINK;
2433e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg		list_add(&sdata->u.vlan.list, &sdata->bss->vlans);
2440ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg		break;
245fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg	case IEEE80211_IF_TYPE_AP:
2463e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg		sdata->bss = &sdata->u.ap;
2473e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg		break;
248fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg	case IEEE80211_IF_TYPE_STA:
249fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg	case IEEE80211_IF_TYPE_MNTR:
250fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg	case IEEE80211_IF_TYPE_IBSS:
2516032f934c818e5c3435c9f17274fe1983f53c6b4Johannes Berg	case IEEE80211_IF_TYPE_MESH_POINT:
252fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg		/* no special treatment */
253fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg		break;
254a28975525016ddcbdaab8225666df1cf2dc9cb2dJohannes Berg	case IEEE80211_IF_TYPE_INVALID:
255a28975525016ddcbdaab8225666df1cf2dc9cb2dJohannes Berg		/* cannot happen */
256a28975525016ddcbdaab8225666df1cf2dc9cb2dJohannes Berg		WARN_ON(1);
257a28975525016ddcbdaab8225666df1cf2dc9cb2dJohannes Berg		break;
2580ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg	}
259f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
260b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	if (local->open_count == 0) {
261b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		res = 0;
2624150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		if (local->ops->start)
2634150c57212ad134765dd78c654a4b9906252b66dJohannes Berg			res = local->ops->start(local_to_hw(local));
2644150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		if (res)
2653e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg			goto err_del_bss;
266ceffefd15aac78841432230627308b8a382dbcfcMichael Buesch		need_hw_reconfig = 1;
267cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn		ieee80211_led_radio(local, local->hw.conf.radio_enabled);
268b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	}
269f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
27051fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg	switch (sdata->vif.type) {
2710ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg	case IEEE80211_IF_TYPE_VLAN:
2720ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg		/* no need to tell driver */
2730ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg		break;
2744150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	case IEEE80211_IF_TYPE_MNTR:
2753d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu		if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
2763d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu			local->cooked_mntrs++;
2773d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu			break;
2783d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu		}
2793d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu
2804150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		/* must be before the call to ieee80211_configure_filter */
281b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		local->monitors++;
2828cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		if (local->monitors == 1)
2834150c57212ad134765dd78c654a4b9906252b66dJohannes Berg			local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
2848cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu
2858cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
2868cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu			local->fif_fcsfail++;
2878cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
2888cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu			local->fif_plcpfail++;
2898cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
2908cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu			local->fif_control++;
2918cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
2928cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu			local->fif_other_bss++;
2938cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu
294b9e40857682ecfc5bcd0356a23ff409883ffb982David S. Miller		netif_addr_lock_bh(local->mdev);
2958cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		ieee80211_configure_filter(local);
296b9e40857682ecfc5bcd0356a23ff409883ffb982David S. Miller		netif_addr_unlock_bh(local->mdev);
2974150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		break;
2984150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	case IEEE80211_IF_TYPE_STA:
2994150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	case IEEE80211_IF_TYPE_IBSS:
3004150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET;
3014150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		/* fall through */
3024150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	default:
30332bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg		conf.vif = &sdata->vif;
30451fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg		conf.type = sdata->vif.type;
3054150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		conf.mac_addr = dev->dev_addr;
3064150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		res = local->ops->add_interface(local_to_hw(local), &conf);
3074150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		if (res)
308636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg			goto err_stop;
3094150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
3109d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		if (ieee80211_vif_is_mesh(&sdata->vif))
3119d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg			ieee80211_start_mesh(sdata->dev);
312fc32f9243dc93e75f81457e95d9cb90ee6136d94Tomas Winkler		changed |= ieee80211_reset_erp_info(dev);
313fc32f9243dc93e75f81457e95d9cb90ee6136d94Tomas Winkler		ieee80211_bss_info_change_notify(sdata, changed);
31411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		ieee80211_enable_keys(sdata);
3154150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
31651fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg		if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
317ddd3d2be85e3207c47f2b3c431723e6c758b4b0dJohannes Berg		    !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
3184150c57212ad134765dd78c654a4b9906252b66dJohannes Berg			netif_carrier_off(dev);
3194150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		else
3204150c57212ad134765dd78c654a4b9906252b66dJohannes Berg			netif_carrier_on(dev);
321d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake	}
322f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
323636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg	if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
324636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg		/* Create STA entry for the WDS peer */
325636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg		sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
326636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg				     GFP_KERNEL);
327636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg		if (!sta) {
328636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg			res = -ENOMEM;
329636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg			goto err_del_interface;
330636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg		}
331636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg
33207346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg		/* no locking required since STA is not live yet */
333636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg		sta->flags |= WLAN_STA_AUTHORIZED;
334636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg
335636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg		res = sta_info_insert(sta);
336636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg		if (res) {
337636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg			/* STA has been freed */
338636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg			goto err_del_interface;
339636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg		}
340636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg	}
341636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg
3424150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	if (local->open_count == 0) {
3434150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		res = dev_open(local->mdev);
3444150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		WARN_ON(res);
345636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg		if (res)
346636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg			goto err_del_interface;
3474150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		tasklet_enable(&local->tx_pending_tasklet);
3484150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		tasklet_enable(&local->tasklet);
3494150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	}
3504150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
351c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg	/*
352c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg	 * set_multicast_list will be invoked by the networking core
353c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg	 * which will check whether any increments here were done in
354c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg	 * error and sync them down to the hardware as filter flags.
355c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg	 */
356c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg	if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
357c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg		atomic_inc(&local->iff_allmultis);
358c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg
359c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg	if (sdata->flags & IEEE80211_SDATA_PROMISC)
360c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg		atomic_inc(&local->iff_promiscs);
361c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg
3624150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	local->open_count++;
363ceffefd15aac78841432230627308b8a382dbcfcMichael Buesch	if (need_hw_reconfig)
364ceffefd15aac78841432230627308b8a382dbcfcMichael Buesch		ieee80211_hw_config(local);
365f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
36664f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann	/*
36764f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann	 * ieee80211_sta_work is disabled while network interface
36864f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann	 * is down. Therefore, some configuration changes may not
36964f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann	 * yet be effective. Trigger execution of ieee80211_sta_work
37064f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann	 * to fix this.
37164f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann	 */
372988c0f723d0b1abb399e6e71d8bf3f8bf1949a70Johannes Berg	if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
373988c0f723d0b1abb399e6e71d8bf3f8bf1949a70Johannes Berg	    sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
37464f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann		struct ieee80211_if_sta *ifsta = &sdata->u.sta;
37564f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann		queue_work(local->hw.workqueue, &ifsta->work);
37664f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann	}
37764f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann
37851cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller	netif_tx_start_all_queues(dev);
3794150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
380b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	return 0;
381636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg err_del_interface:
382636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg	local->ops->remove_interface(local_to_hw(local), &conf);
383636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg err_stop:
384636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg	if (!local->open_count && local->ops->stop)
385636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg		local->ops->stop(local_to_hw(local));
3863e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg err_del_bss:
3873e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	sdata->bss = NULL;
3883e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
3893e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg		list_del(&sdata->u.vlan.list);
390636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg	return res;
391f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
392f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
3934150c57212ad134765dd78c654a4b9906252b66dJohannes Bergstatic int ieee80211_stop(struct net_device *dev)
394f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
39544213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
39644213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	struct ieee80211_local *local = sdata->local;
3974150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	struct ieee80211_if_init_conf conf;
39807db218396650933abff3c5c1ad1e2a6e0cfedebRon Rindjunsky	struct sta_info *sta;
3994150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
40044213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	/*
40144213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 * Stop TX on this interface first.
40244213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 */
40351cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller	netif_tx_stop_all_queues(dev);
4044150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
40544213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	/*
40644213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 * Now delete all active aggregation sessions.
40744213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 */
408d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	rcu_read_lock();
409d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg
410d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	list_for_each_entry_rcu(sta, &local->sta_list, list) {
411d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg		if (sta->sdata == sdata)
41285249e5fab13edb89258fa6d551cd4a3a4f0d569Ron Rindjunsky			ieee80211_sta_tear_down_BA_sessions(dev, sta->addr);
41307db218396650933abff3c5c1ad1e2a6e0cfedebRon Rindjunsky	}
41407db218396650933abff3c5c1ad1e2a6e0cfedebRon Rindjunsky
415d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	rcu_read_unlock();
416d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg
41744213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	/*
41844213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 * Remove all stations associated with this interface.
41944213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 *
42044213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 * This must be done before calling ops->remove_interface()
42144213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 * because otherwise we can later invoke ops->sta_notify()
42244213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 * whenever the STAs are removed, and that invalidates driver
42344213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 * assumptions about always getting a vif pointer that is valid
42444213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 * (because if we remove a STA after ops->remove_interface()
42544213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 * the driver will have removed the vif info already!)
42644213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 *
42744213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 * We could relax this and only unlink the stations from the
42844213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 * hash table and list but keep them on a per-sdata list that
42944213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 * will be inserted back again when the interface is brought
43044213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 * up again, but I don't currently see a use case for that,
43144213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 * except with WDS which gets a STA entry created when it is
43244213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 * brought up.
43344213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	 */
43444213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg	sta_info_flush(local, sdata);
4354150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
436c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg	/*
437c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg	 * Don't count this interface for promisc/allmulti while it
438c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg	 * is down. dev_mc_unsync() will invoke set_multicast_list
439c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg	 * on the master interface which will sync these down to the
440c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg	 * hardware as filter flags.
441c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg	 */
442c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg	if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
443c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg		atomic_dec(&local->iff_allmultis);
444c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg
445c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg	if (sdata->flags & IEEE80211_SDATA_PROMISC)
446c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg		atomic_dec(&local->iff_promiscs);
447c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg
4484150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	dev_mc_unsync(local->mdev, dev);
4494150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
4505dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg	/* APs need special treatment */
45151fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg	if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
4520ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg		struct ieee80211_sub_if_data *vlan, *tmp;
4535dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg		struct beacon_data *old_beacon = sdata->u.ap.beacon;
4540ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg
4555dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg		/* remove beacon */
4565dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg		rcu_assign_pointer(sdata->u.ap.beacon, NULL);
4575dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg		synchronize_rcu();
4585dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg		kfree(old_beacon);
4595dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg
4605dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg		/* down all dependent devices, that is VLANs */
4610ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg		list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans,
4620ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg					 u.vlan.list)
4630ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg			dev_close(vlan->dev);
4640ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg		WARN_ON(!list_empty(&sdata->u.ap.vlans));
4650ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg	}
4660ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg
4674150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	local->open_count--;
468f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
46951fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg	switch (sdata->vif.type) {
4700ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg	case IEEE80211_IF_TYPE_VLAN:
4710ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg		list_del(&sdata->u.vlan.list);
4720ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg		/* no need to tell driver */
4730ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg		break;
4744150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	case IEEE80211_IF_TYPE_MNTR:
4753d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu		if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
4763d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu			local->cooked_mntrs--;
4773d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu			break;
4783d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu		}
4793d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu
4804150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		local->monitors--;
4818cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		if (local->monitors == 0)
4828b393f1dc76acbe65a97a4e51f8144f4a65fa1c9Michael Wu			local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
4838cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu
4848cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
4858cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu			local->fif_fcsfail--;
4868cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
4878cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu			local->fif_plcpfail--;
4888cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
4898cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu			local->fif_control--;
4908cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
4918cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu			local->fif_other_bss--;
4928cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu
493b9e40857682ecfc5bcd0356a23ff409883ffb982David S. Miller		netif_addr_lock_bh(local->mdev);
4948cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		ieee80211_configure_filter(local);
495b9e40857682ecfc5bcd0356a23ff409883ffb982David S. Miller		netif_addr_unlock_bh(local->mdev);
4964150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		break;
497f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo	case IEEE80211_IF_TYPE_MESH_POINT:
498b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	case IEEE80211_IF_TYPE_STA:
499b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	case IEEE80211_IF_TYPE_IBSS:
500b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		sdata->u.sta.state = IEEE80211_DISABLED;
501ad81b2f97d42e13ef78bb3798e046cd5f0492980Assaf Krauss		memset(sdata->u.sta.bssid, 0, ETH_ALEN);
502b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		del_timer_sync(&sdata->u.sta.timer);
5032a8a9a88fc1b18f5c45244d0ef8a5352f6cf761fJohannes Berg		/*
50479010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg		 * When we get here, the interface is marked down.
50579010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg		 * Call synchronize_rcu() to wait for the RX path
50679010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg		 * should it be using the interface and enqueuing
50779010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg		 * frames at this very time on another CPU.
5082a8a9a88fc1b18f5c45244d0ef8a5352f6cf761fJohannes Berg		 */
50979010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg		synchronize_rcu();
510b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		skb_queue_purge(&sdata->u.sta.skb_queue);
5112a8a9a88fc1b18f5c45244d0ef8a5352f6cf761fJohannes Berg
512ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi		if (local->scan_dev == sdata->dev) {
513ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi			if (!local->ops->hw_scan) {
514ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi				local->sta_sw_scanning = 0;
515ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi				cancel_delayed_work(&local->scan_work);
516ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi			} else
517ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi				local->sta_hw_scanning = 0;
518b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		}
519ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi
520a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi		sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
521a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi		kfree(sdata->u.sta.extra_ie);
522a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi		sdata->u.sta.extra_ie = NULL;
523a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi		sdata->u.sta.extra_ie_len = 0;
5244150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		/* fall through */
5254150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	default:
52632bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg		conf.vif = &sdata->vif;
52751fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg		conf.type = sdata->vif.type;
5284150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		conf.mac_addr = dev->dev_addr;
52911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		/* disable all keys for as long as this netdev is down */
53011a843b7e16062389c53ba393c7913956e034eb2Johannes Berg		ieee80211_disable_keys(sdata);
5314150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		local->ops->remove_interface(local_to_hw(local), &conf);
532f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
533f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
5343e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	sdata->bss = NULL;
5353e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg
536b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	if (local->open_count == 0) {
537b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		if (netif_running(local->mdev))
538b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg			dev_close(local->mdev);
5394150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
540b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		if (local->ops->stop)
541b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg			local->ops->stop(local_to_hw(local));
5424150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
543cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn		ieee80211_led_radio(local, 0);
544cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn
545ea0c925370b33baf168bb33782c613468c1aa119Ivo van Doorn		flush_workqueue(local->hw.workqueue);
546ea0c925370b33baf168bb33782c613468c1aa119Ivo van Doorn
547b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		tasklet_disable(&local->tx_pending_tasklet);
548b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		tasklet_disable(&local->tasklet);
549b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	}
550b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg
551f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	return 0;
552f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
553f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
554eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyint ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
555eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{
556eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	struct ieee80211_local *local = hw_to_local(hw);
557eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	struct sta_info *sta;
558eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	struct ieee80211_sub_if_data *sdata;
559eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	u16 start_seq_num = 0;
560eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	u8 *state;
561eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	int ret;
562eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	DECLARE_MAC_BUF(mac);
563eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
564eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (tid >= STA_TID_NUM)
565eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		return -EINVAL;
566eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
567eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG
568eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	printk(KERN_DEBUG "Open BA session requested for %s tid %u\n",
569eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky				print_mac(mac, ra), tid);
570eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */
571eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
572d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	rcu_read_lock();
573d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg
574eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	sta = sta_info_get(local, ra);
575eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (!sta) {
576f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#ifdef CONFIG_MAC80211_HT_DEBUG
577eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		printk(KERN_DEBUG "Could not find the station\n");
578f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#endif
579b83f4e15e65d94f6f56924b0b06a77a7ca2b4d8aTomas Winkler		ret = -ENOENT;
580b83f4e15e65d94f6f56924b0b06a77a7ca2b4d8aTomas Winkler		goto exit;
581eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	}
582eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
58307346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg	spin_lock_bh(&sta->lock);
584eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
585eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	/* we have tried too many times, receiver does not want A-MPDU */
586cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
587eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		ret = -EBUSY;
588b83f4e15e65d94f6f56924b0b06a77a7ca2b4d8aTomas Winkler		goto err_unlock_sta;
589eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	}
590eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
591cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	state = &sta->ampdu_mlme.tid_state_tx[tid];
592eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	/* check if the TID is not in aggregation flow already */
593eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (*state != HT_AGG_STATE_IDLE) {
594eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG
595eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		printk(KERN_DEBUG "BA request denied - session is not "
596eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky				 "idle on tid %u\n", tid);
597eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */
598eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		ret = -EAGAIN;
599b83f4e15e65d94f6f56924b0b06a77a7ca2b4d8aTomas Winkler		goto err_unlock_sta;
600eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	}
601eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
602cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	/* prepare A-MPDU MLME for Tx aggregation */
603cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	sta->ampdu_mlme.tid_tx[tid] =
604cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky			kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
605cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	if (!sta->ampdu_mlme.tid_tx[tid]) {
606f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#ifdef CONFIG_MAC80211_HT_DEBUG
607cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky		if (net_ratelimit())
608cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky			printk(KERN_ERR "allocate tx mlme to tid %d failed\n",
609cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky					tid);
610f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#endif
611cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky		ret = -ENOMEM;
612b83f4e15e65d94f6f56924b0b06a77a7ca2b4d8aTomas Winkler		goto err_unlock_sta;
613cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	}
614cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	/* Tx timer */
615cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function =
616cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky			sta_addba_resp_timer_expired;
617cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data =
618cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky			(unsigned long)&sta->timer_to_tid[tid];
619cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
620cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky
621eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	/* create a new queue for this aggregation */
6229e7234923789897858e1a475c579b5e2e6ad5b74Ron Rindjunsky	ret = ieee80211_ht_agg_queue_add(local, sta, tid);
623eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
624eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	/* case no queue is available to aggregation
625eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	 * don't switch to aggregation */
626eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (ret) {
627eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG
628cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky		printk(KERN_DEBUG "BA request denied - queue unavailable for"
629eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky					" tid %d\n", tid);
630eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */
631b83f4e15e65d94f6f56924b0b06a77a7ca2b4d8aTomas Winkler		goto err_unlock_queue;
632eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	}
633d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	sdata = sta->sdata;
634eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
635eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	/* Ok, the Addba frame hasn't been sent yet, but if the driver calls the
636eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	 * call back right away, it must see that the flow has begun */
637eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	*state |= HT_ADDBA_REQUESTED_MSK;
638eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
639eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (local->ops->ampdu_action)
640eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START,
641eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky						ra, tid, &start_seq_num);
642eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
643eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (ret) {
644eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		/* No need to requeue the packets in the agg queue, since we
645eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		 * held the tx lock: no packet could be enqueued to the newly
646eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		 * allocated queue */
64751cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller		ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
648eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG
649cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky		printk(KERN_DEBUG "BA request denied - HW unavailable for"
650cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky					" tid %d\n", tid);
651eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */
652eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		*state = HT_AGG_STATE_IDLE;
653b83f4e15e65d94f6f56924b0b06a77a7ca2b4d8aTomas Winkler		goto err_unlock_queue;
654eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	}
655eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
656eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	/* Will put all the packets in the new SW queue */
6579e7234923789897858e1a475c579b5e2e6ad5b74Ron Rindjunsky	ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
658b83f4e15e65d94f6f56924b0b06a77a7ca2b4d8aTomas Winkler	spin_unlock_bh(&sta->lock);
659eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
660eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	/* send an addBA request */
661eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	sta->ampdu_mlme.dialog_token_allocator++;
662cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	sta->ampdu_mlme.tid_tx[tid]->dialog_token =
663eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			sta->ampdu_mlme.dialog_token_allocator;
664cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
665eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
666b83f4e15e65d94f6f56924b0b06a77a7ca2b4d8aTomas Winkler
667d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	ieee80211_send_addba_request(sta->sdata->dev, ra, tid,
668cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky			 sta->ampdu_mlme.tid_tx[tid]->dialog_token,
669cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky			 sta->ampdu_mlme.tid_tx[tid]->ssn,
670eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			 0x40, 5000);
671eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	/* activate the timer for the recipient's addBA response */
672cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires =
673eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky				jiffies + ADDBA_RESP_INTERVAL;
674cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
675f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#ifdef CONFIG_MAC80211_HT_DEBUG
676eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
677f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#endif
678b83f4e15e65d94f6f56924b0b06a77a7ca2b4d8aTomas Winkler	goto exit;
679eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
680b83f4e15e65d94f6f56924b0b06a77a7ca2b4d8aTomas Winklererr_unlock_queue:
681cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	kfree(sta->ampdu_mlme.tid_tx[tid]);
682cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	sta->ampdu_mlme.tid_tx[tid] = NULL;
683cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	ret = -EBUSY;
684b83f4e15e65d94f6f56924b0b06a77a7ca2b4d8aTomas Winklererr_unlock_sta:
68507346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg	spin_unlock_bh(&sta->lock);
686b83f4e15e65d94f6f56924b0b06a77a7ca2b4d8aTomas Winklerexit:
687d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	rcu_read_unlock();
688eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	return ret;
689eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky}
690eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_start_tx_ba_session);
691eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
692eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyint ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
693eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky				 u8 *ra, u16 tid,
694eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky				 enum ieee80211_back_parties initiator)
695eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{
696eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	struct ieee80211_local *local = hw_to_local(hw);
697eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	struct sta_info *sta;
698eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	u8 *state;
699eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	int ret = 0;
700eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	DECLARE_MAC_BUF(mac);
701eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
702eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (tid >= STA_TID_NUM)
703eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		return -EINVAL;
704eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
705d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	rcu_read_lock();
706eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	sta = sta_info_get(local, ra);
707d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	if (!sta) {
708d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg		rcu_read_unlock();
709eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		return -ENOENT;
710d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	}
711eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
712eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	/* check if the TID is in aggregation */
713cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	state = &sta->ampdu_mlme.tid_state_tx[tid];
71407346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg	spin_lock_bh(&sta->lock);
715eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
716eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (*state != HT_AGG_STATE_OPERATIONAL) {
717eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		ret = -ENOENT;
718eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		goto stop_BA_exit;
719eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	}
720eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
721513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG
722513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky	printk(KERN_DEBUG "Tx BA session stop requested for %s tid %u\n",
723513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky				print_mac(mac, ra), tid);
724513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */
725513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky
726eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]);
727eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
728eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	*state = HT_AGG_STATE_REQ_STOP_BA_MSK |
729eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		(initiator << HT_AGG_STATE_INITIATOR_SHIFT);
730eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
731eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (local->ops->ampdu_action)
732eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP,
733eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky						ra, tid, NULL);
734eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
735eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	/* case HW denied going back to legacy */
736eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (ret) {
737eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		WARN_ON(ret != -EBUSY);
738eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		*state = HT_AGG_STATE_OPERATIONAL;
739eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
740eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		goto stop_BA_exit;
741eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	}
742eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
743eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskystop_BA_exit:
74407346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg	spin_unlock_bh(&sta->lock);
745d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	rcu_read_unlock();
746eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	return ret;
747eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky}
748eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
749eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
750eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyvoid ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
751eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{
752eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	struct ieee80211_local *local = hw_to_local(hw);
753eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	struct sta_info *sta;
754eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	u8 *state;
755eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	DECLARE_MAC_BUF(mac);
756eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
757eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (tid >= STA_TID_NUM) {
758f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#ifdef CONFIG_MAC80211_HT_DEBUG
759eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
760eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky				tid, STA_TID_NUM);
761f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#endif
762eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		return;
763eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	}
764eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
765d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	rcu_read_lock();
766eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	sta = sta_info_get(local, ra);
767eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (!sta) {
768d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg		rcu_read_unlock();
769f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#ifdef CONFIG_MAC80211_HT_DEBUG
770eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		printk(KERN_DEBUG "Could not find station: %s\n",
771eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky				print_mac(mac, ra));
772f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#endif
773eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		return;
774eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	}
775eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
776cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	state = &sta->ampdu_mlme.tid_state_tx[tid];
77707346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg	spin_lock_bh(&sta->lock);
778eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
779eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
780f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#ifdef CONFIG_MAC80211_HT_DEBUG
781eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
782eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky				*state);
783f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#endif
78407346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg		spin_unlock_bh(&sta->lock);
785d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg		rcu_read_unlock();
786eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		return;
787eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	}
788eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
789eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK);
790eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
791eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	*state |= HT_ADDBA_DRV_READY_MSK;
792eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
793eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (*state == HT_AGG_STATE_OPERATIONAL) {
794f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#ifdef CONFIG_MAC80211_HT_DEBUG
795eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
796f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#endif
797eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
798eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	}
79907346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg	spin_unlock_bh(&sta->lock);
800d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	rcu_read_unlock();
801eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky}
802eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
803eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
804eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyvoid ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
805eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{
806eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	struct ieee80211_local *local = hw_to_local(hw);
807eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	struct sta_info *sta;
808eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	u8 *state;
809eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	int agg_queue;
810eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	DECLARE_MAC_BUF(mac);
811eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
812eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (tid >= STA_TID_NUM) {
813f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#ifdef CONFIG_MAC80211_HT_DEBUG
814eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
815eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky				tid, STA_TID_NUM);
816f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#endif
817eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		return;
818eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	}
819eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
820513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG
821513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky	printk(KERN_DEBUG "Stopping Tx BA session for %s tid %d\n",
822eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky				print_mac(mac, ra), tid);
823513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */
824eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
825d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	rcu_read_lock();
826eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	sta = sta_info_get(local, ra);
827eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (!sta) {
828f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#ifdef CONFIG_MAC80211_HT_DEBUG
829eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		printk(KERN_DEBUG "Could not find station: %s\n",
830eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky				print_mac(mac, ra));
831f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#endif
832d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg		rcu_read_unlock();
833eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		return;
834eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	}
835cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	state = &sta->ampdu_mlme.tid_state_tx[tid];
836eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
837b83f4e15e65d94f6f56924b0b06a77a7ca2b4d8aTomas Winkler	/* NOTE: no need to use sta->lock in this state check, as
83851cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller	 * ieee80211_stop_tx_ba_session will let only one stop call to
83951cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller	 * pass through per sta/tid
84051cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller	 */
841eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
842f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#ifdef CONFIG_MAC80211_HT_DEBUG
843eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
844f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#endif
845d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg		rcu_read_unlock();
846eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		return;
847eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	}
848eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
849eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (*state & HT_AGG_STATE_INITIATOR_MSK)
850d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg		ieee80211_send_delba(sta->sdata->dev, ra, tid,
851eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
852eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
853eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	agg_queue = sta->tid_to_tx_q[tid];
854eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
8559e7234923789897858e1a475c579b5e2e6ad5b74Ron Rindjunsky	ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
856eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
85751cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller	/* We just requeued the all the frames that were in the
85851cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller	 * removed queue, and since we might miss a softirq we do
85951cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller	 * netif_schedule_queue.  ieee80211_wake_queue is not used
86051cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller	 * here as this queue is not necessarily stopped
86151cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller	 */
86251cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller	netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue));
863b83f4e15e65d94f6f56924b0b06a77a7ca2b4d8aTomas Winkler	spin_lock_bh(&sta->lock);
864eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	*state = HT_AGG_STATE_IDLE;
865cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	sta->ampdu_mlme.addba_req_num[tid] = 0;
866cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	kfree(sta->ampdu_mlme.tid_tx[tid]);
867cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky	sta->ampdu_mlme.tid_tx[tid] = NULL;
86807346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg	spin_unlock_bh(&sta->lock);
869eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
870d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	rcu_read_unlock();
871eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky}
872eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_stop_tx_ba_cb);
873eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
874eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyvoid ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
875eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky				      const u8 *ra, u16 tid)
876eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{
877eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	struct ieee80211_local *local = hw_to_local(hw);
878eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	struct ieee80211_ra_tid *ra_tid;
879eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	struct sk_buff *skb = dev_alloc_skb(0);
880eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
881eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (unlikely(!skb)) {
882f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#ifdef CONFIG_MAC80211_HT_DEBUG
883eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		if (net_ratelimit())
884eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			printk(KERN_WARNING "%s: Not enough memory, "
885eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			       "dropping start BA session", skb->dev->name);
886f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#endif
887eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		return;
888eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	}
889eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
890eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	memcpy(&ra_tid->ra, ra, ETH_ALEN);
891eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	ra_tid->tid = tid;
892eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
893eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	skb->pkt_type = IEEE80211_ADDBA_MSG;
894eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	skb_queue_tail(&local->skb_queue, skb);
895eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	tasklet_schedule(&local->tasklet);
896eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky}
897eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
898eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
899eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyvoid ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
900eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky				     const u8 *ra, u16 tid)
901eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{
902eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	struct ieee80211_local *local = hw_to_local(hw);
903eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	struct ieee80211_ra_tid *ra_tid;
904eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	struct sk_buff *skb = dev_alloc_skb(0);
905eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
906eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	if (unlikely(!skb)) {
907f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#ifdef CONFIG_MAC80211_HT_DEBUG
908eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		if (net_ratelimit())
909eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			printk(KERN_WARNING "%s: Not enough memory, "
910eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			       "dropping stop BA session", skb->dev->name);
911f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#endif
912eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		return;
913eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	}
914eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
915eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	memcpy(&ra_tid->ra, ra, ETH_ALEN);
916eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	ra_tid->tid = tid;
917eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
918eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	skb->pkt_type = IEEE80211_DELBA_MSG;
919eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	skb_queue_tail(&local->skb_queue, skb);
920eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	tasklet_schedule(&local->tasklet);
921eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky}
922eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe);
923eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky
924f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void ieee80211_set_multicast_list(struct net_device *dev)
925f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
926f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
927f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
9284150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	int allmulti, promisc, sdata_allmulti, sdata_promisc;
929f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
9304150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	allmulti = !!(dev->flags & IFF_ALLMULTI);
9314150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	promisc = !!(dev->flags & IFF_PROMISC);
932b52f2198ac889561d341c6990d669a671f93f450Johannes Berg	sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI);
933b52f2198ac889561d341c6990d669a671f93f450Johannes Berg	sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC);
9344150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
9354150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	if (allmulti != sdata_allmulti) {
9364150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		if (dev->flags & IFF_ALLMULTI)
93753918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg			atomic_inc(&local->iff_allmultis);
9384150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		else
93953918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg			atomic_dec(&local->iff_allmultis);
94013262ffd4902805acad2618c12b41fcaa6c50791Jiri Slaby		sdata->flags ^= IEEE80211_SDATA_ALLMULTI;
941f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
9424150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
9434150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	if (promisc != sdata_promisc) {
9444150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		if (dev->flags & IFF_PROMISC)
94553918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg			atomic_inc(&local->iff_promiscs);
9464150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		else
94753918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg			atomic_dec(&local->iff_promiscs);
94813262ffd4902805acad2618c12b41fcaa6c50791Jiri Slaby		sdata->flags ^= IEEE80211_SDATA_PROMISC;
949f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
9504150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
9514150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	dev_mc_sync(local->mdev, dev);
952f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
953f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
9543b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemmingerstatic const struct header_ops ieee80211_header_ops = {
9553b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger	.create		= eth_header,
9563b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger	.parse		= header_parse_80211,
9573b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger	.rebuild	= eth_rebuild_header,
9583b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger	.cache		= eth_header_cache,
9593b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger	.cache_update	= eth_header_cache_update,
9603b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger};
9613b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger
962b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergvoid ieee80211_if_setup(struct net_device *dev)
963f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
964b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	ether_setup(dev);
965b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	dev->hard_start_xmit = ieee80211_subif_start_xmit;
966b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	dev->wireless_handlers = &ieee80211_iw_handler_def;
967b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	dev->set_multicast_list = ieee80211_set_multicast_list;
968b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	dev->change_mtu = ieee80211_change_mtu;
969b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	dev->open = ieee80211_open;
970b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	dev->stop = ieee80211_stop;
97175636525fbfa78fa33fd754c89785cfde750acd3Johannes Berg	dev->destructor = free_netdev;
972b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg}
973f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
974b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg/* everything else */
975b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg
9769d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Bergint ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed)
977b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{
9789d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	struct ieee80211_local *local = sdata->local;
979b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	struct ieee80211_if_conf conf;
980b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg
9819d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	if (WARN_ON(!netif_running(sdata->dev)))
9829d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		return 0;
9839d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg
9849d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	if (!local->ops->config_interface)
985f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		return 0;
986f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
987b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	memset(&conf, 0, sizeof(conf));
9889d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	conf.changed = changed;
9899d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg
99051fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg	if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
99151fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg	    sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
9924150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		conf.bssid = sdata->u.sta.bssid;
993b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		conf.ssid = sdata->u.sta.ssid;
994b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		conf.ssid_len = sdata->u.sta.ssid_len;
99551fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg	} else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
9969d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		conf.bssid = sdata->dev->dev_addr;
997b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		conf.ssid = sdata->u.ap.ssid;
998b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		conf.ssid_len = sdata->u.ap.ssid_len;
9999d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
10009d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		u8 zero[ETH_ALEN] = { 0 };
10019d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		conf.bssid = zero;
10029d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		conf.ssid = zero;
10039d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		conf.ssid_len = 0;
10049d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	} else {
10059d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		WARN_ON(1);
10069d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		return -EINVAL;
1007f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
1008f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
10099d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID)))
10109d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		return -EINVAL;
1011f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
10129d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	if (WARN_ON(!conf.ssid && (changed & IEEE80211_IFCC_SSID)))
10139d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		return -EINVAL;
1014f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
10159d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	return local->ops->config_interface(local_to_hw(local),
10169d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg					    &sdata->vif, &conf);
1017b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg}
1018f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1019b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergint ieee80211_hw_config(struct ieee80211_local *local)
1020b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{
1021b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	struct ieee80211_channel *chan;
1022b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	int ret = 0;
1023f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
10248318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	if (local->sta_sw_scanning)
1025b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		chan = local->scan_channel;
10268318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	else
1027b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		chan = local->oper_channel;
1028f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
10298318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	local->hw.conf.channel = chan;
10308318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg
10318318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	if (!local->hw.conf.power_level)
10328318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		local->hw.conf.power_level = chan->max_power;
10338318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	else
10348318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		local->hw.conf.power_level = min(chan->max_power,
10358318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg					       local->hw.conf.power_level);
10368318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg
10378318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	local->hw.conf.max_antenna_gain = chan->max_antenna_gain;
1038f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1039b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
10408318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	printk(KERN_DEBUG "%s: HW CONFIG: freq=%d\n",
10418318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	       wiphy_name(local->hw.wiphy), chan->center_freq);
10428318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg#endif
1043b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg
1044f7c4daed99fba15e4e48df464031f4ac7c32e4c9Michael Buesch	if (local->open_count)
1045b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		ret = local->ops->config(local_to_hw(local), &local->hw.conf);
1046f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1047b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	return ret;
1048b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg}
1049f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1050d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky/**
105138668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler * ieee80211_handle_ht should be used only after legacy configuration
105238668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler * has been determined namely band, as ht configuration depends upon
105338668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler * the hardware's HT abilities for a _specific_ band.
1054d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky */
105538668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkleru32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht,
1056d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky			   struct ieee80211_ht_info *req_ht_cap,
1057d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky			   struct ieee80211_ht_bss_info *req_bss_cap)
1058d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky{
1059d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky	struct ieee80211_conf *conf = &local->hw.conf;
10608318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	struct ieee80211_supported_band *sband;
106138668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler	struct ieee80211_ht_info ht_conf;
106238668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler	struct ieee80211_ht_bss_info ht_bss_conf;
106338668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler	u32 changed = 0;
1064edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	int i;
1065edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	u8 max_tx_streams = IEEE80211_HT_CAP_MAX_STREAMS;
1066edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	u8 tx_mcs_set_cap;
1067d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky
10688318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	sband = local->hw.wiphy->bands[conf->channel->band];
10698318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg
1070edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info));
1071edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info));
1072edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky
1073d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky	/* HT is not supported */
10748318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	if (!sband->ht_info.ht_supported) {
1075d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky		conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
1076edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky		goto out;
1077d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky	}
1078d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky
1079edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	/* disable HT */
1080edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	if (!enable_ht) {
1081edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky		if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)
108238668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler			changed |= BSS_CHANGED_HT;
1083edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky		conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
1084edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky		conf->ht_conf.ht_supported = 0;
1085edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky		goto out;
1086edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	}
108738668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler
108838668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler
1089edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE))
1090edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky		changed |= BSS_CHANGED_HT;
109138668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler
1092edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE;
1093edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	ht_conf.ht_supported = 1;
109438668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler
1095edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap;
1096edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS);
1097edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS;
1098edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	ht_bss_conf.primary_channel = req_bss_cap->primary_channel;
1099edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	ht_bss_conf.bss_cap = req_bss_cap->bss_cap;
1100edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode;
110138668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler
1102edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	ht_conf.ampdu_factor = req_ht_cap->ampdu_factor;
1103edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	ht_conf.ampdu_density = req_ht_cap->ampdu_density;
110438668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler
1105edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	/* Bits 96-100 */
1106edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	tx_mcs_set_cap = sband->ht_info.supp_mcs_set[12];
1107edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky
1108edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	/* configure suppoerted Tx MCS according to requested MCS
1109edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	 * (based in most cases on Rx capabilities of peer) and self
1110edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	 * Tx MCS capabilities (as defined by low level driver HW
1111edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	 * Tx capabilities) */
1112edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	if (!(tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_DEFINED))
1113edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky		goto check_changed;
1114d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky
1115edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	/* Counting from 0 therfore + 1 */
1116edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_RX_DIFF)
1117edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky		max_tx_streams = ((tx_mcs_set_cap &
1118edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky				IEEE80211_HT_CAP_MCS_TX_STREAMS) >> 2) + 1;
1119edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky
1120edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	for (i = 0; i < max_tx_streams; i++)
1121edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky		ht_conf.supp_mcs_set[i] =
1122edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky			sband->ht_info.supp_mcs_set[i] &
1123edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky					req_ht_cap->supp_mcs_set[i];
1124edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky
1125edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_UEQM)
1126edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky		for (i = IEEE80211_SUPP_MCS_SET_UEQM;
1127edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky		     i < IEEE80211_SUPP_MCS_SET_LEN; i++)
1128edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky			ht_conf.supp_mcs_set[i] =
1129edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky				sband->ht_info.supp_mcs_set[i] &
1130edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky					req_ht_cap->supp_mcs_set[i];
1131edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky
1132edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunskycheck_changed:
1133edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	/* if bss configuration changed store the new one */
1134edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) ||
1135edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	    memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) {
1136edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky		changed |= BSS_CHANGED_HT;
1137edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky		memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf));
1138edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky		memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf));
1139edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky	}
1140edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunskyout:
114138668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler	return changed;
1142d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky}
1143d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky
1144471b3efdfccc257591331724145f8ccf8b3217e1Johannes Bergvoid ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
1145471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg				      u32 changed)
1146d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake{
1147471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg	struct ieee80211_local *local = sdata->local;
1148471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg
1149471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg	if (!changed)
1150471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg		return;
1151471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg
1152471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg	if (local->ops->bss_info_changed)
1153471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg		local->ops->bss_info_changed(local_to_hw(local),
1154471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg					     &sdata->vif,
1155471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg					     &sdata->bss_conf,
1156471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg					     changed);
1157d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake}
1158d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake
1159fc32f9243dc93e75f81457e95d9cb90ee6136d94Tomas Winkleru32 ieee80211_reset_erp_info(struct net_device *dev)
1160d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake{
1161d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1162d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake
1163471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg	sdata->bss_conf.use_cts_prot = 0;
1164471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg	sdata->bss_conf.use_short_preamble = 0;
1165fc32f9243dc93e75f81457e95d9cb90ee6136d94Tomas Winkler	return BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE;
1166d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake}
1167d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake
1168f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
1169e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg				 struct sk_buff *skb)
1170f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
1171f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_local *local = hw_to_local(hw);
1172e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1173f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	int tmp;
1174f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1175f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	skb->dev = local->mdev;
1176f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	skb->pkt_type = IEEE80211_TX_STATUS_MSG;
1177e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ?
1178f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		       &local->skb_queue : &local->skb_queue_unreliable, skb);
1179f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	tmp = skb_queue_len(&local->skb_queue) +
1180f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		skb_queue_len(&local->skb_queue_unreliable);
1181f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT &&
1182f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	       (skb = skb_dequeue(&local->skb_queue_unreliable))) {
1183f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		dev_kfree_skb_irq(skb);
1184f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		tmp--;
1185f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		I802_DEBUG_INC(local->tx_status_drop);
1186f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
1187f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	tasklet_schedule(&local->tasklet);
1188f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
1189f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_tx_status_irqsafe);
1190f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1191f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void ieee80211_tasklet_handler(unsigned long data)
1192f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
1193f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_local *local = (struct ieee80211_local *) data;
1194f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct sk_buff *skb;
1195f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_rx_status rx_status;
1196eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	struct ieee80211_ra_tid *ra_tid;
1197f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1198f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	while ((skb = skb_dequeue(&local->skb_queue)) ||
1199f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	       (skb = skb_dequeue(&local->skb_queue_unreliable))) {
1200f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		switch (skb->pkt_type) {
1201f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		case IEEE80211_RX_MSG:
1202f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			/* status is in skb->cb */
1203f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			memcpy(&rx_status, skb->cb, sizeof(rx_status));
120451fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg			/* Clear skb->pkt_type in order to not confuse kernel
1205f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			 * netstack. */
1206f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			skb->pkt_type = 0;
1207f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			__ieee80211_rx(local_to_hw(local), skb, &rx_status);
1208f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			break;
1209f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		case IEEE80211_TX_STATUS_MSG:
1210f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			skb->pkt_type = 0;
1211e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			ieee80211_tx_status(local_to_hw(local), skb);
1212f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			break;
1213eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		case IEEE80211_DELBA_MSG:
1214eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
1215eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			ieee80211_stop_tx_ba_cb(local_to_hw(local),
1216eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky						ra_tid->ra, ra_tid->tid);
1217eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			dev_kfree_skb(skb);
1218eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			break;
1219eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		case IEEE80211_ADDBA_MSG:
1220eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
1221eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			ieee80211_start_tx_ba_cb(local_to_hw(local),
1222eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky						 ra_tid->ra, ra_tid->tid);
1223eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			dev_kfree_skb(skb);
1224eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			break ;
1225f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg		default:
1226f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg			WARN_ON(1);
1227f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			dev_kfree_skb(skb);
1228f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			break;
1229f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		}
1230f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
1231f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
1232f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1233f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to
1234f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * make a prepared TX frame (one that has been given to hw) to look like brand
1235f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * new IEEE 802.11 frame that is ready to go through TX processing again.
1236d0f09804144fd9471a13cf4d80e66842c7fa114fJohannes Berg */
1237f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void ieee80211_remove_tx_extra(struct ieee80211_local *local,
1238f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc				      struct ieee80211_key *key,
1239e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg				      struct sk_buff *skb)
1240f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
1241f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	int hdrlen, iv_len, mic_len;
1242f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1243f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
1244f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1245f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (!key)
1246f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		goto no_key;
1247f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
12488f20fc24986a083228823d9b68adca20714b254eJohannes Berg	switch (key->conf.alg) {
1249f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	case ALG_WEP:
1250f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		iv_len = WEP_IV_LEN;
1251f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		mic_len = WEP_ICV_LEN;
1252f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		break;
1253f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	case ALG_TKIP:
1254f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		iv_len = TKIP_IV_LEN;
1255f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		mic_len = TKIP_ICV_LEN;
1256f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		break;
1257f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	case ALG_CCMP:
1258f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		iv_len = CCMP_HDR_LEN;
1259f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		mic_len = CCMP_MIC_LEN;
1260f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		break;
1261f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	default:
1262f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		goto no_key;
1263f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
1264f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
12658f20fc24986a083228823d9b68adca20714b254eJohannes Berg	if (skb->len >= mic_len &&
126611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	    !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
1267f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		skb_trim(skb, skb->len - mic_len);
1268f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (skb->len >= iv_len && skb->len > hdrlen) {
1269f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		memmove(skb->data + iv_len, skb->data, hdrlen);
1270f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		skb_pull(skb, iv_len);
1271f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
1272f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1273f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencno_key:
1274f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	{
1275f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1276f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		u16 fc = le16_to_cpu(hdr->frame_control);
1277f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		if ((fc & 0x8C) == 0x88) /* QoS Control Field */ {
1278f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			fc &= ~IEEE80211_STYPE_QOS_DATA;
1279f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			hdr->frame_control = cpu_to_le16(fc);
1280f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			memmove(skb->data + 2, skb->data, hdrlen - 2);
1281f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			skb_pull(skb, 2);
1282f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		}
1283f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
1284f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
1285f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1286d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Bergstatic void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
1287d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg					    struct sta_info *sta,
1288e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg					    struct sk_buff *skb)
1289d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg{
1290e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1291e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg
1292d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	sta->tx_filtered_count++;
1293d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg
1294d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	/*
1295d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * Clear the TX filter mask for this STA when sending the next
1296d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * packet. If the STA went to power save mode, this will happen
1297f6d97104890203ba9c2cf8e34894c4c8e64cb880Yi Zhu	 * when it wakes up for the next time.
1298d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 */
129907346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg	set_sta_flags(sta, WLAN_STA_CLEAR_PS_FILT);
1300d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg
1301d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	/*
1302d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * This code races in the following way:
1303d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *
1304d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *  (1) STA sends frame indicating it will go to sleep and does so
1305d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *  (2) hardware/firmware adds STA to filter list, passes frame up
1306d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *  (3) hardware/firmware processes TX fifo and suppresses a frame
1307d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *  (4) we get TX status before having processed the frame and
1308d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *	knowing that the STA has gone to sleep.
1309d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *
1310d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * This is actually quite unlikely even when both those events are
1311d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * processed from interrupts coming in quickly after one another or
1312d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * even at the same time because we queue both TX status events and
1313d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * RX frames to be processed by a tasklet and process them in the
1314d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * same order that they were received or TX status last. Hence, there
1315d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * is no race as long as the frame RX is processed before the next TX
1316d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * status, which drivers can ensure, see below.
1317d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *
1318d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * Note that this can only happen if the hardware or firmware can
1319d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * actually add STAs to the filter list, if this is done by the
1320d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * driver in response to set_tim() (which will only reduce the race
1321d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * this whole filtering tries to solve, not completely solve it)
1322d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * this situation cannot happen.
1323d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *
1324d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * To completely solve this race drivers need to make sure that they
1325d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *  (a) don't mix the irq-safe/not irq-safe TX status/RX processing
1326d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *	functions and
1327d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *  (b) always process RX events before TX status events if ordering
1328d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *      can be unknown, for example with different interrupt status
1329d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *	bits.
1330d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 */
133107346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg	if (test_sta_flags(sta, WLAN_STA_PS) &&
1332d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	    skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) {
1333e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		ieee80211_remove_tx_extra(local, sta->key, skb);
1334d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		skb_queue_tail(&sta->tx_filtered, skb);
1335d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		return;
1336d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	}
1337d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg
133807346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg	if (!test_sta_flags(sta, WLAN_STA_PS) &&
1339e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	    !(info->flags & IEEE80211_TX_CTL_REQUEUE)) {
1340d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		/* Software retry the packet once */
1341e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		info->flags |= IEEE80211_TX_CTL_REQUEUE;
1342e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		ieee80211_remove_tx_extra(local, sta->key, skb);
1343d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		dev_queue_xmit(skb);
1344d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		return;
1345d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	}
1346d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg
1347f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1348d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	if (net_ratelimit())
1349d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		printk(KERN_DEBUG "%s: dropped TX filtered frame, "
1350d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		       "queue_len=%d PS=%d @%lu\n",
1351d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		       wiphy_name(local->hw.wiphy),
1352d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		       skb_queue_len(&sta->tx_filtered),
135307346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg		       !!test_sta_flags(sta, WLAN_STA_PS), jiffies);
1354f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#endif
1355d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	dev_kfree_skb(skb);
1356d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg}
1357d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg
1358e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Bergvoid ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
1359f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
1360f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct sk_buff *skb2;
1361f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1362f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_local *local = hw_to_local(hw);
1363e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1364f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	u16 frag, type;
1365429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky	__le16 fc;
1366b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	struct ieee80211_tx_status_rtap_hdr *rthdr;
1367b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	struct ieee80211_sub_if_data *sdata;
13683d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	struct net_device *prev_dev = NULL;
1369429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky	struct sta_info *sta;
1370f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1371d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	rcu_read_lock();
1372d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg
1373e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (info->status.excessive_retries) {
1374f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		sta = sta_info_get(local, hdr->addr1);
1375f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		if (sta) {
137607346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg			if (test_sta_flags(sta, WLAN_STA_PS)) {
1377d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg				/*
1378d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg				 * The STA is in power save mode, so assume
1379f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc				 * that this TX packet failed because of that.
1380f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc				 */
1381e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg				ieee80211_handle_filtered_frame(local, sta, skb);
1382d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg				rcu_read_unlock();
1383d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg				return;
1384f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			}
1385f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		}
1386f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
1387f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1388429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky	fc = hdr->frame_control;
1389429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky
1390429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky	if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&
1391429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky	    (ieee80211_is_data_qos(fc))) {
1392429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky		u16 tid, ssn;
1393429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky		u8 *qc;
1394429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky		sta = sta_info_get(local, hdr->addr1);
1395429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky		if (sta) {
1396429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky			qc = ieee80211_get_qos_ctl(hdr);
1397429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky			tid = qc[0] & 0xf;
1398429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky			ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10)
1399429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky						& IEEE80211_SCTL_SEQ);
1400429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky			ieee80211_send_bar(sta->sdata->dev, hdr->addr1,
1401429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky					   tid, ssn);
1402429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky		}
1403429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky	}
1404429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky
1405e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
1406f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		sta = sta_info_get(local, hdr->addr1);
1407f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		if (sta) {
1408e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			ieee80211_handle_filtered_frame(local, sta, skb);
1409d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg			rcu_read_unlock();
1410f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			return;
1411f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		}
14121abbe498e4b5e4f2000dfc30a0fa25be9553530eMattias Nissler	} else
1413e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		rate_control_tx_status(local->mdev, skb);
1414f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1415d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	rcu_read_unlock();
1416d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg
1417f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	ieee80211_led_tx(local, 0);
1418f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1419f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	/* SNMP counters
1420f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * Fragments are passed to low-level drivers as separate skbs, so these
1421f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * are actually fragments, not frames. Update frame counters only for
1422f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * the first fragment of the frame. */
1423f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1424f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
1425f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE;
1426f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1427e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (info->flags & IEEE80211_TX_STAT_ACK) {
1428f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		if (frag == 0) {
1429f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			local->dot11TransmittedFrameCount++;
1430f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			if (is_multicast_ether_addr(hdr->addr1))
1431f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc				local->dot11MulticastTransmittedFrameCount++;
1432e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			if (info->status.retry_count > 0)
1433f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc				local->dot11RetryCount++;
1434e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			if (info->status.retry_count > 1)
1435f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc				local->dot11MultipleRetryCount++;
1436f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		}
1437f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1438f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		/* This counter shall be incremented for an acknowledged MPDU
1439f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		 * with an individual address in the address 1 field or an MPDU
1440f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		 * with a multicast address in the address 1 field of type Data
1441f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		 * or Management. */
1442f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		if (!is_multicast_ether_addr(hdr->addr1) ||
1443f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		    type == IEEE80211_FTYPE_DATA ||
1444f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		    type == IEEE80211_FTYPE_MGMT)
1445f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			local->dot11TransmittedFragmentCount++;
1446f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	} else {
1447f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		if (frag == 0)
1448f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			local->dot11FailedCount++;
1449f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
1450f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1451b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	/* this was a transmitted frame, but now we want to reuse it */
1452b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	skb_orphan(skb);
1453b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg
14543d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	/*
14553d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	 * This is a bit racy but we can avoid a lot of work
14563d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	 * with this test...
14573d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	 */
14583d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	if (!local->monitors && !local->cooked_mntrs) {
1459f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		dev_kfree_skb(skb);
1460f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		return;
1461f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
1462f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1463b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	/* send frame to monitor interfaces now */
1464f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1465b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	if (skb_headroom(skb) < sizeof(*rthdr)) {
1466b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg		printk(KERN_ERR "ieee80211_tx_status: headroom too small\n");
1467f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		dev_kfree_skb(skb);
1468f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		return;
1469f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
1470f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1471988c0f723d0b1abb399e6e71d8bf3f8bf1949a70Johannes Berg	rthdr = (struct ieee80211_tx_status_rtap_hdr *)
1472b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg				skb_push(skb, sizeof(*rthdr));
1473b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg
1474b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	memset(rthdr, 0, sizeof(*rthdr));
1475b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
1476b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	rthdr->hdr.it_present =
1477b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg		cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
1478b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg			    (1 << IEEE80211_RADIOTAP_DATA_RETRIES));
1479b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg
1480e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
1481b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	    !is_multicast_ether_addr(hdr->addr1))
1482b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL);
1483b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg
1484e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) &&
1485e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	    (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT))
1486b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS);
1487e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	else if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
1488b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS);
1489b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg
1490e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	rthdr->data_retries = info->status.retry_count;
1491b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg
14923d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	/* XXX: is this sufficient for BPF? */
14933d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	skb_set_mac_header(skb, 0);
14943d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	skb->ip_summed = CHECKSUM_UNNECESSARY;
14953d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	skb->pkt_type = PACKET_OTHERHOST;
14963d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	skb->protocol = htons(ETH_P_802_2);
14973d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	memset(skb->cb, 0, sizeof(skb->cb));
14983d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu
149979010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	rcu_read_lock();
150079010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
150151fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg		if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) {
1502b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg			if (!netif_running(sdata->dev))
1503b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg				continue;
15043d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu
15053d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu			if (prev_dev) {
150679010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg				skb2 = skb_clone(skb, GFP_ATOMIC);
15073d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu				if (skb2) {
15083d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu					skb2->dev = prev_dev;
15093d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu					netif_rx(skb2);
15103d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu				}
15113d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu			}
15123d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu
15133d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu			prev_dev = sdata->dev;
1514b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg		}
1515b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	}
15163d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	if (prev_dev) {
15173d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu		skb->dev = prev_dev;
15183d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu		netif_rx(skb);
15193d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu		skb = NULL;
15203d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	}
152179010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	rcu_read_unlock();
15223d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	dev_kfree_skb(skb);
1523f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
1524f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_tx_status);
1525f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1526f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstruct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
1527f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc					const struct ieee80211_ops *ops)
1528f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
1529f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_local *local;
1530f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	int priv_size;
1531f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct wiphy *wiphy;
1532f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1533f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	/* Ensure 32-byte alignment of our private data and hw private data.
1534f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * We use the wiphy priv data for both our ieee80211_local and for
1535f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * the driver's private data
1536f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 *
1537f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * In memory it'll be like this:
1538f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 *
1539f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * +-------------------------+
1540f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * | struct wiphy	    |
1541f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * +-------------------------+
1542f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * | struct ieee80211_local  |
1543f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * +-------------------------+
1544f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * | driver's private data   |
1545f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * +-------------------------+
1546f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 *
1547f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 */
1548f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	priv_size = ((sizeof(struct ieee80211_local) +
1549f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		      NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) +
1550f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		    priv_data_len;
1551f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1552f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	wiphy = wiphy_new(&mac80211_config_ops, priv_size);
1553f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1554f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (!wiphy)
1555f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		return NULL;
1556f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1557f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	wiphy->privid = mac80211_wiphy_privid;
1558f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1559f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local = wiphy_priv(wiphy);
1560f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local->hw.wiphy = wiphy;
1561f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1562f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local->hw.priv = (char *)local +
1563f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			 ((sizeof(struct ieee80211_local) +
1564f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			   NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
1565f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
15664480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg	BUG_ON(!ops->tx);
15674150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	BUG_ON(!ops->start);
15684150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	BUG_ON(!ops->stop);
15694480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg	BUG_ON(!ops->config);
15704480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg	BUG_ON(!ops->add_interface);
15714150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	BUG_ON(!ops->remove_interface);
15724150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	BUG_ON(!ops->configure_filter);
1573f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local->ops = ops;
1574f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1575f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local->hw.queues = 1; /* default */
1576f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1577f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local->bridge_packets = 1;
1578f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1579f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
1580f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
1581f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local->short_retry_limit = 7;
1582f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local->long_retry_limit = 4;
1583f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local->hw.conf.radio_enabled = 1;
1584f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
158579010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	INIT_LIST_HEAD(&local->interfaces);
1586f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1587b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg	spin_lock_init(&local->key_lock);
1588b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg
1589f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work);
1590f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1591f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	sta_info_init(local);
1592f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1593f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
1594f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		     (unsigned long)local);
1595f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	tasklet_disable(&local->tx_pending_tasklet);
1596f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1597f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	tasklet_init(&local->tasklet,
1598f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		     ieee80211_tasklet_handler,
1599f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		     (unsigned long) local);
1600f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	tasklet_disable(&local->tasklet);
1601f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1602f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	skb_queue_head_init(&local->skb_queue);
1603f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	skb_queue_head_init(&local->skb_queue_unreliable);
1604f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1605f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	return local_to_hw(local);
1606f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
1607f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_alloc_hw);
1608f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1609f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencint ieee80211_register_hw(struct ieee80211_hw *hw)
1610f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
1611f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_local *local = hw_to_local(hw);
1612f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	const char *name;
1613f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	int result;
16148318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	enum ieee80211_band band;
161596d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	struct net_device *mdev;
16163e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	struct wireless_dev *mwdev;
16178318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg
16188318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	/*
16198318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	 * generic code guarantees at least one band,
16208318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	 * set this very early because much code assumes
16218318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	 * that hw.conf.channel is assigned
16228318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	 */
16238318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
16248318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		struct ieee80211_supported_band *sband;
16258318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg
16268318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		sband = local->hw.wiphy->bands[band];
16278318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		if (sband) {
16288318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			/* init channel we're on */
16298318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			local->hw.conf.channel =
16308318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			local->oper_channel =
16318318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			local->scan_channel = &sband->channels[0];
16328318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			break;
16338318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		}
16348318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	}
1635f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1636f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	result = wiphy_register(local->hw.wiphy);
1637f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (result < 0)
1638f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		return result;
1639f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1640e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg	/*
1641e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg	 * We use the number of queues for feature tests (QoS, HT) internally
1642e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg	 * so restrict them appropriately.
1643e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg	 */
1644e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg	if (hw->queues > IEEE80211_MAX_QUEUES)
1645e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg		hw->queues = IEEE80211_MAX_QUEUES;
1646e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg	if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES)
1647e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg		hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES;
1648e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg	if (hw->queues < 4)
1649e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg		hw->ampdu_queues = 0;
1650e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg
16513e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	mdev = alloc_netdev_mq(sizeof(struct wireless_dev),
1652e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg			       "wmaster%d", ether_setup,
1653e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg			       ieee80211_num_queues(hw));
165496d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	if (!mdev)
165596d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg		goto fail_mdev_alloc;
165696d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg
16573e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	mwdev = netdev_priv(mdev);
16583e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	mdev->ieee80211_ptr = mwdev;
16593e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	mwdev->wiphy = local->hw.wiphy;
166096d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg
166196d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	local->mdev = mdev;
166296d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg
16633e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	ieee80211_rx_bss_list_init(local);
166496d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg
166596d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	mdev->hard_start_xmit = ieee80211_master_start_xmit;
166696d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	mdev->open = ieee80211_master_open;
166796d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	mdev->stop = ieee80211_master_stop;
166896d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	mdev->type = ARPHRD_IEEE80211;
166996d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	mdev->header_ops = &ieee80211_header_ops;
167096d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	mdev->set_multicast_list = ieee80211_master_set_multicast_list;
167196d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg
1672f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	name = wiphy_dev(local->hw.wiphy)->driver->name;
167359959a6150c8af737898e83f727e824dbed7b0faJohannes Berg	local->hw.workqueue = create_freezeable_workqueue(name);
1674f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (!local->hw.workqueue) {
1675f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		result = -ENOMEM;
1676f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		goto fail_workqueue;
1677f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
1678f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1679b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	/*
1680b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	 * The hardware needs headroom for sending the frame,
1681b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	 * and we need some headroom for passing the frame to monitor
1682b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	 * interfaces, but never both at the same time.
1683b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	 */
168433ccad35a21df51c0d23f3e3e88688524e7b51edJiri Benc	local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
168533ccad35a21df51c0d23f3e3e88688524e7b51edJiri Benc				   sizeof(struct ieee80211_tx_status_rtap_hdr));
1686b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg
1687e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc	debugfs_hw_add(local);
1688e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc
1689dc0ae30c31ee6ef83992bb692f37dfbba08a2ef6Tomas Winkler	if (local->hw.conf.beacon_int < 10)
1690dc0ae30c31ee6ef83992bb692f37dfbba08a2ef6Tomas Winkler		local->hw.conf.beacon_int = 100;
1691f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1692ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler	if (local->hw.max_listen_interval == 0)
1693ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler		local->hw.max_listen_interval = 1;
1694ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler
1695ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler	local->hw.conf.listen_interval = local->hw.max_listen_interval;
1696ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler
1697566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf	local->wstats_flags |= local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC |
1698566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf						  IEEE80211_HW_SIGNAL_DB |
1699566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf						  IEEE80211_HW_SIGNAL_DBM) ?
1700f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			       IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID;
1701566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf	local->wstats_flags |= local->hw.flags & IEEE80211_HW_NOISE_DBM ?
1702f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			       IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID;
1703566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
1704f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		local->wstats_flags |= IW_QUAL_DBM;
1705f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1706f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	result = sta_info_start(local);
1707f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (result < 0)
1708f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		goto fail_sta_info;
1709f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1710f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	rtnl_lock();
1711f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	result = dev_alloc_name(local->mdev, local->mdev->name);
1712f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (result < 0)
1713f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		goto fail_dev;
1714f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1715f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
1716f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy));
1717f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1718f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	result = register_netdevice(local->mdev);
1719f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (result < 0)
1720f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		goto fail_dev;
1721f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1722830f903866a1611e9ce53f3e35202302bb938946Johannes Berg	result = ieee80211_init_rate_ctrl_alg(local,
1723830f903866a1611e9ce53f3e35202302bb938946Johannes Berg					      hw->rate_control_algorithm);
1724f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (result < 0) {
1725f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		printk(KERN_DEBUG "%s: Failed to initialize rate control "
1726dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg		       "algorithm\n", wiphy_name(local->hw.wiphy));
1727f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		goto fail_rate;
1728f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
1729f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1730f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	result = ieee80211_wep_init(local);
1731f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1732f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (result < 0) {
1733023a04bebe7030c1e6d5347bd3f27a3e49a1f222Jeremy Fitzhardinge		printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n",
1734023a04bebe7030c1e6d5347bd3f27a3e49a1f222Jeremy Fitzhardinge		       wiphy_name(local->hw.wiphy), result);
1735f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		goto fail_wep;
1736f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
1737f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
173851cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller	local->mdev->select_queue = ieee80211_select_queue;
1739f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1740f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	/* add one default STA interface */
17413e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	result = ieee80211_if_add(local, "wlan%d", NULL,
1742ee3858551ae6d044578f598f8001db5f1a9fd52eLuis Carlos Cobo				  IEEE80211_IF_TYPE_STA, NULL);
1743f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (result)
1744f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
1745dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg		       wiphy_name(local->hw.wiphy));
1746f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1747f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	rtnl_unlock();
1748f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1749f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	ieee80211_led_init(local);
1750f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1751f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	return 0;
1752f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1753f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_wep:
1754f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	rate_control_deinitialize(local);
1755f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_rate:
1756f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	unregister_netdevice(local->mdev);
1757339a7c41c913035bf58579f6e47b4ba29da83795Pavel Emelyanov	local->mdev = NULL;
1758f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_dev:
1759f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	rtnl_unlock();
1760f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	sta_info_stop(local);
1761f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_sta_info:
1762e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc	debugfs_hw_del(local);
1763f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	destroy_workqueue(local->hw.workqueue);
1764f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_workqueue:
17653e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	if (local->mdev)
17663e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg		free_netdev(local->mdev);
176796d510566e4908f77f03ff1436c78ae7162a17d0Johannes Bergfail_mdev_alloc:
1768f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	wiphy_unregister(local->hw.wiphy);
1769f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	return result;
1770f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
1771f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_register_hw);
1772f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1773f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_unregister_hw(struct ieee80211_hw *hw)
1774f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
1775f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_local *local = hw_to_local(hw);
1776f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1777f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	tasklet_kill(&local->tx_pending_tasklet);
1778f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	tasklet_kill(&local->tasklet);
1779f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1780f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	rtnl_lock();
1781f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
178279010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	/*
178379010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	 * At this point, interface list manipulations are fine
178479010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	 * because the driver cannot be handing us frames any
178579010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	 * more and the tasklet is killed.
178679010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	 */
17875b2812e925c8e976852867f8d760637c5926d817Johannes Berg
178875636525fbfa78fa33fd754c89785cfde750acd3Johannes Berg	/* First, we remove all virtual interfaces. */
178975636525fbfa78fa33fd754c89785cfde750acd3Johannes Berg	ieee80211_remove_interfaces(local);
17905b2812e925c8e976852867f8d760637c5926d817Johannes Berg
17915b2812e925c8e976852867f8d760637c5926d817Johannes Berg	/* then, finally, remove the master interface */
17923e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	unregister_netdevice(local->mdev);
1793f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1794f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	rtnl_unlock();
1795f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
17963e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	ieee80211_rx_bss_list_deinit(local);
1797f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	ieee80211_clear_tx_pending(local);
1798f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	sta_info_stop(local);
1799f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	rate_control_deinitialize(local);
1800e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc	debugfs_hw_del(local);
1801f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1802f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (skb_queue_len(&local->skb_queue)
1803f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			|| skb_queue_len(&local->skb_queue_unreliable))
1804f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		printk(KERN_WARNING "%s: skb_queue not empty\n",
1805dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg		       wiphy_name(local->hw.wiphy));
1806f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	skb_queue_purge(&local->skb_queue);
1807f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	skb_queue_purge(&local->skb_queue_unreliable);
1808f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1809f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	destroy_workqueue(local->hw.workqueue);
1810f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	wiphy_unregister(local->hw.wiphy);
1811f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	ieee80211_wep_free(local);
1812f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	ieee80211_led_exit(local);
18133e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	free_netdev(local->mdev);
1814f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
1815f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_unregister_hw);
1816f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1817f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_free_hw(struct ieee80211_hw *hw)
1818f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
1819f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_local *local = hw_to_local(hw);
1820f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1821f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	wiphy_free(local->hw.wiphy);
1822f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
1823f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_free_hw);
1824f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1825f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic int __init ieee80211_init(void)
1826f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
1827f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct sk_buff *skb;
1828f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	int ret;
1829f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1830e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	BUILD_BUG_ON(sizeof(struct ieee80211_tx_info) > sizeof(skb->cb));
1831e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) +
1832e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	             IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb));
1833f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
18344b475898ec9dc6e62cebcb8fc0b3495c986a4590Johannes Berg	ret = rc80211_pid_init();
1835ad01837593338f13508463fa11c8dbf8109a1e5dMattias Nissler	if (ret)
183651cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller		return ret;
1837f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1838e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc	ieee80211_debugfs_netdev_init();
1839e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc
1840f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	return 0;
1841f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
1842f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1843f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void __exit ieee80211_exit(void)
1844f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
18454b475898ec9dc6e62cebcb8fc0b3495c986a4590Johannes Berg	rc80211_pid_exit();
1846ac71c691e6a5ce991fe221d3bdb0c972f617aa37Johannes Berg
18473b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	/*
18483b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	 * For key todo, it'll be empty by now but the work
18493b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	 * might still be scheduled.
18503b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	 */
18513b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	flush_scheduled_work();
18523b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
1853f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo	if (mesh_allocated)
1854f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo		ieee80211s_stop();
1855902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg
1856e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc	ieee80211_debugfs_netdev_exit();
1857f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
1858f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1859f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1860ca9938fea576ebbb8d8c4fbe8a5bcc937e49e1caJohannes Bergsubsys_initcall(ieee80211_init);
1861f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencmodule_exit(ieee80211_exit);
1862f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1863f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencMODULE_DESCRIPTION("IEEE 802.11 subsystem");
1864f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencMODULE_LICENSE("GPL");
1865