main.c revision 9124b07740c51cbc6e358dd0c4abc6ee8ded084d
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
48f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
494150c57212ad134765dd78c654a4b9906252b66dJohannes Berg/* must be called under mdev tx lock */
500d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Bergvoid ieee80211_configure_filter(struct ieee80211_local *local)
514150c57212ad134765dd78c654a4b9906252b66dJohannes Berg{
524150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	unsigned int changed_flags;
534150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	unsigned int new_flags = 0;
544150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
5553918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg	if (atomic_read(&local->iff_promiscs))
564150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		new_flags |= FIF_PROMISC_IN_BSS;
574150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
5853918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg	if (atomic_read(&local->iff_allmultis))
594150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		new_flags |= FIF_ALLMULTI;
604150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
614150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	if (local->monitors)
628cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		new_flags |= FIF_BCN_PRBRESP_PROMISC;
638cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu
648cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu	if (local->fif_fcsfail)
658cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		new_flags |= FIF_FCSFAIL;
668cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu
678cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu	if (local->fif_plcpfail)
688cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		new_flags |= FIF_PLCPFAIL;
698cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu
708cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu	if (local->fif_control)
718cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		new_flags |= FIF_CONTROL;
728cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu
738cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu	if (local->fif_other_bss)
748cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu		new_flags |= FIF_OTHER_BSS;
754150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
764150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	changed_flags = local->filter_flags ^ new_flags;
774150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
784150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	/* be a bit nasty */
794150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	new_flags |= (1<<31);
804150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
814150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	local->ops->configure_filter(local_to_hw(local),
824150c57212ad134765dd78c654a4b9906252b66dJohannes Berg				     changed_flags, &new_flags,
834150c57212ad134765dd78c654a4b9906252b66dJohannes Berg				     local->mdev->mc_count,
844150c57212ad134765dd78c654a4b9906252b66dJohannes Berg				     local->mdev->mc_list);
854150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
864150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	WARN_ON(new_flags & (1<<31));
874150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
884150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	local->filter_flags = new_flags & ~(1<<31);
894150c57212ad134765dd78c654a4b9906252b66dJohannes Berg}
904150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
91b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg/* master interface */
92f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
930d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Bergstatic int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr)
940d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg{
950d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg	memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */
960d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg	return ETH_ALEN;
970d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg}
980d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg
990d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Bergstatic const struct header_ops ieee80211_header_ops = {
1000d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg	.create		= eth_header,
1010d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg	.parse		= header_parse_80211,
1020d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg	.rebuild	= eth_rebuild_header,
1030d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg	.cache		= eth_header_cache,
1040d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg	.cache_update	= eth_header_cache_update,
1050d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg};
1060d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg
107b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic int ieee80211_master_open(struct net_device *dev)
108b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{
109133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg	struct ieee80211_master_priv *mpriv = netdev_priv(dev);
110133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg	struct ieee80211_local *local = mpriv->local;
111b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	struct ieee80211_sub_if_data *sdata;
112b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	int res = -EOPNOTSUPP;
113f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
11479010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	/* we hold the RTNL here so can safely walk the list */
11579010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	list_for_each_entry(sdata, &local->interfaces, list) {
1163e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg		if (netif_running(sdata->dev)) {
117b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg			res = 0;
118b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg			break;
119b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		}
120b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	}
12136d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg
12236d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg	if (res)
12336d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg		return res;
12436d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg
12551cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller	netif_tx_start_all_queues(local->mdev);
12636d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg
12736d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg	return 0;
128b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg}
129f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
130b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic int ieee80211_master_stop(struct net_device *dev)
131f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
132133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg	struct ieee80211_master_priv *mpriv = netdev_priv(dev);
133133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg	struct ieee80211_local *local = mpriv->local;
134b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	struct ieee80211_sub_if_data *sdata;
135f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
13679010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	/* we hold the RTNL here so can safely walk the list */
13779010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	list_for_each_entry(sdata, &local->interfaces, list)
1383e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg		if (netif_running(sdata->dev))
139b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg			dev_close(sdata->dev);
140f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
141b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	return 0;
142b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg}
143f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1444150c57212ad134765dd78c654a4b9906252b66dJohannes Bergstatic void ieee80211_master_set_multicast_list(struct net_device *dev)
1454150c57212ad134765dd78c654a4b9906252b66dJohannes Berg{
146133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg	struct ieee80211_master_priv *mpriv = netdev_priv(dev);
147133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg	struct ieee80211_local *local = mpriv->local;
1484150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
1494150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	ieee80211_configure_filter(local);
1504150c57212ad134765dd78c654a4b9906252b66dJohannes Berg}
1514150c57212ad134765dd78c654a4b9906252b66dJohannes Berg
152b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg/* everything else */
153b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg
1549d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Bergint ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed)
155b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{
1569d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	struct ieee80211_local *local = sdata->local;
157b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	struct ieee80211_if_conf conf;
158b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg
1599d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	if (WARN_ON(!netif_running(sdata->dev)))
1609d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		return 0;
1619d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg
1627a725f73403e874ec52c58741e9b98cd604dbd03Johannes Berg	if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN))
1637a725f73403e874ec52c58741e9b98cd604dbd03Johannes Berg		return -EINVAL;
1647a725f73403e874ec52c58741e9b98cd604dbd03Johannes Berg
1659d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	if (!local->ops->config_interface)
166f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		return 0;
167f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
168b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	memset(&conf, 0, sizeof(conf));
1699d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	conf.changed = changed;
1709d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg
17105c914fe330fa8e1cc67870dc0d3809dfd96c107Johannes Berg	if (sdata->vif.type == NL80211_IFTYPE_STATION ||
17205c914fe330fa8e1cc67870dc0d3809dfd96c107Johannes Berg	    sdata->vif.type == NL80211_IFTYPE_ADHOC) {
1734150c57212ad134765dd78c654a4b9906252b66dJohannes Berg		conf.bssid = sdata->u.sta.bssid;
174b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		conf.ssid = sdata->u.sta.ssid;
175b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		conf.ssid_len = sdata->u.sta.ssid_len;
17605c914fe330fa8e1cc67870dc0d3809dfd96c107Johannes Berg	} else if (sdata->vif.type == NL80211_IFTYPE_AP) {
1779d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		conf.bssid = sdata->dev->dev_addr;
178b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		conf.ssid = sdata->u.ap.ssid;
179b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		conf.ssid_len = sdata->u.ap.ssid_len;
1809d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
1819d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		u8 zero[ETH_ALEN] = { 0 };
1829d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		conf.bssid = zero;
1839d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		conf.ssid = zero;
1849d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		conf.ssid_len = 0;
1859d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	} else {
1869d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		WARN_ON(1);
1879d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		return -EINVAL;
188f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
189f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1909d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID)))
1919d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		return -EINVAL;
192f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1939d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	if (WARN_ON(!conf.ssid && (changed & IEEE80211_IFCC_SSID)))
1949d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg		return -EINVAL;
195f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
1969d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg	return local->ops->config_interface(local_to_hw(local),
1979d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg					    &sdata->vif, &conf);
198b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg}
199f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
200e8975581f63870be42ff4662b293d1b0c8c21350Johannes Bergint ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
201b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{
202b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	struct ieee80211_channel *chan;
203b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	int ret = 0;
204e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg	int power;
205f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
206c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg	if (local->sw_scanning)
207b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		chan = local->scan_channel;
2088318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	else
209b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg		chan = local->oper_channel;
210f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
211e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg	if (chan != local->hw.conf.channel) {
212e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg		local->hw.conf.channel = chan;
213e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg		changed |= IEEE80211_CONF_CHANGE_CHANNEL;
214e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg	}
215e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg
2168318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg
2178318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	if (!local->hw.conf.power_level)
218e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg		power = chan->max_power;
2198318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	else
220e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg		power = min(chan->max_power, local->hw.conf.power_level);
221e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg	if (local->hw.conf.power_level != power) {
222e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg		changed |= IEEE80211_CONF_CHANGE_POWER;
223e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg		local->hw.conf.power_level = power;
224e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg	}
225b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg
226e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg	if (changed && local->open_count) {
227e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg		ret = local->ops->config(local_to_hw(local), changed);
228d73782fdde76554016abf73b46f843b29f520848Johannes Berg		/*
229d73782fdde76554016abf73b46f843b29f520848Johannes Berg		 * HW reconfiguration should never fail, the driver has told
230d73782fdde76554016abf73b46f843b29f520848Johannes Berg		 * us what it can support so it should live up to that promise.
231d73782fdde76554016abf73b46f843b29f520848Johannes Berg		 */
232d73782fdde76554016abf73b46f843b29f520848Johannes Berg		WARN_ON(ret);
233d73782fdde76554016abf73b46f843b29f520848Johannes Berg	}
234f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
235b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg	return ret;
236b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg}
237f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
238471b3efdfccc257591331724145f8ccf8b3217e1Johannes Bergvoid ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
239471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg				      u32 changed)
240d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake{
241471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg	struct ieee80211_local *local = sdata->local;
242471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg
2437a725f73403e874ec52c58741e9b98cd604dbd03Johannes Berg	if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN))
2447a725f73403e874ec52c58741e9b98cd604dbd03Johannes Berg		return;
2457a725f73403e874ec52c58741e9b98cd604dbd03Johannes Berg
246471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg	if (!changed)
247471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg		return;
248471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg
249471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg	if (local->ops->bss_info_changed)
250471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg		local->ops->bss_info_changed(local_to_hw(local),
251471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg					     &sdata->vif,
252471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg					     &sdata->bss_conf,
253471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg					     changed);
254d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake}
255d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake
256f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greeneu32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
257d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake{
2587a5158ef8da70fdedeb0530faaa8128aa645be3cJohannes Berg	sdata->bss_conf.use_cts_prot = false;
2597a5158ef8da70fdedeb0530faaa8128aa645be3cJohannes Berg	sdata->bss_conf.use_short_preamble = false;
2607a5158ef8da70fdedeb0530faaa8128aa645be3cJohannes Berg	sdata->bss_conf.use_short_slot = false;
2617a5158ef8da70fdedeb0530faaa8128aa645be3cJohannes Berg	return BSS_CHANGED_ERP_CTS_PROT |
2627a5158ef8da70fdedeb0530faaa8128aa645be3cJohannes Berg	       BSS_CHANGED_ERP_PREAMBLE |
2637a5158ef8da70fdedeb0530faaa8128aa645be3cJohannes Berg	       BSS_CHANGED_ERP_SLOT;
264d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake}
265d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake
266f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
267e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg				 struct sk_buff *skb)
268f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
269f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_local *local = hw_to_local(hw);
270e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
271f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	int tmp;
272f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
273f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	skb->dev = local->mdev;
274f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	skb->pkt_type = IEEE80211_TX_STATUS_MSG;
275e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ?
276f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		       &local->skb_queue : &local->skb_queue_unreliable, skb);
277f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	tmp = skb_queue_len(&local->skb_queue) +
278f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		skb_queue_len(&local->skb_queue_unreliable);
279f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT &&
280f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	       (skb = skb_dequeue(&local->skb_queue_unreliable))) {
281f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		dev_kfree_skb_irq(skb);
282f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		tmp--;
283f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		I802_DEBUG_INC(local->tx_status_drop);
284f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
285f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	tasklet_schedule(&local->tasklet);
286f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
287f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_tx_status_irqsafe);
288f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
289f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void ieee80211_tasklet_handler(unsigned long data)
290f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
291f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_local *local = (struct ieee80211_local *) data;
292f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct sk_buff *skb;
293f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_rx_status rx_status;
294eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky	struct ieee80211_ra_tid *ra_tid;
295f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
296f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	while ((skb = skb_dequeue(&local->skb_queue)) ||
297f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	       (skb = skb_dequeue(&local->skb_queue_unreliable))) {
298f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		switch (skb->pkt_type) {
299f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		case IEEE80211_RX_MSG:
300f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			/* status is in skb->cb */
301f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			memcpy(&rx_status, skb->cb, sizeof(rx_status));
30251fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg			/* Clear skb->pkt_type in order to not confuse kernel
303f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			 * netstack. */
304f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			skb->pkt_type = 0;
305f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			__ieee80211_rx(local_to_hw(local), skb, &rx_status);
306f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			break;
307f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		case IEEE80211_TX_STATUS_MSG:
308f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			skb->pkt_type = 0;
309e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			ieee80211_tx_status(local_to_hw(local), skb);
310f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			break;
311eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		case IEEE80211_DELBA_MSG:
312eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
313eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			ieee80211_stop_tx_ba_cb(local_to_hw(local),
314eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky						ra_tid->ra, ra_tid->tid);
315eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			dev_kfree_skb(skb);
316eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			break;
317eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky		case IEEE80211_ADDBA_MSG:
318eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
319eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			ieee80211_start_tx_ba_cb(local_to_hw(local),
320eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky						 ra_tid->ra, ra_tid->tid);
321eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			dev_kfree_skb(skb);
322eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky			break ;
323f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg		default:
324f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg			WARN_ON(1);
325f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			dev_kfree_skb(skb);
326f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			break;
327f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		}
328f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
329f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
330f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
331f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to
332f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * make a prepared TX frame (one that has been given to hw) to look like brand
333f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * new IEEE 802.11 frame that is ready to go through TX processing again.
334d0f09804144fd9471a13cf4d80e66842c7fa114fJohannes Berg */
335f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void ieee80211_remove_tx_extra(struct ieee80211_local *local,
336f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc				      struct ieee80211_key *key,
337e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg				      struct sk_buff *skb)
338f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
33962bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison	unsigned int hdrlen, iv_len, mic_len;
34062bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
341f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
34262bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison	hdrlen = ieee80211_hdrlen(hdr->frame_control);
343f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
344f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (!key)
345f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		goto no_key;
346f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
3478f20fc24986a083228823d9b68adca20714b254eJohannes Berg	switch (key->conf.alg) {
348f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	case ALG_WEP:
349f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		iv_len = WEP_IV_LEN;
350f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		mic_len = WEP_ICV_LEN;
351f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		break;
352f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	case ALG_TKIP:
353f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		iv_len = TKIP_IV_LEN;
354f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		mic_len = TKIP_ICV_LEN;
355f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		break;
356f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	case ALG_CCMP:
357f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		iv_len = CCMP_HDR_LEN;
358f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		mic_len = CCMP_MIC_LEN;
359f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		break;
360f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	default:
361f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		goto no_key;
362f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
363f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
36462bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison	if (skb->len >= hdrlen + mic_len &&
36511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg	    !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
366f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		skb_trim(skb, skb->len - mic_len);
36762bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison	if (skb->len >= hdrlen + iv_len) {
368f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		memmove(skb->data + iv_len, skb->data, hdrlen);
36962bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison		hdr = (struct ieee80211_hdr *)skb_pull(skb, iv_len);
370f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
371f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
372f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencno_key:
37362bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison	if (ieee80211_is_data_qos(hdr->frame_control)) {
37462bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison		hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
37562bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison		memmove(skb->data + IEEE80211_QOS_CTL_LEN, skb->data,
37662bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison			hdrlen - IEEE80211_QOS_CTL_LEN);
37762bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison		skb_pull(skb, IEEE80211_QOS_CTL_LEN);
378f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
379f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
380f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
381d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Bergstatic void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
382d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg					    struct sta_info *sta,
383e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg					    struct sk_buff *skb)
384d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg{
385e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
386e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg
387d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	sta->tx_filtered_count++;
388d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg
389d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	/*
390d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * Clear the TX filter mask for this STA when sending the next
391d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * packet. If the STA went to power save mode, this will happen
392f6d97104890203ba9c2cf8e34894c4c8e64cb880Yi Zhu	 * when it wakes up for the next time.
393d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 */
39407346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg	set_sta_flags(sta, WLAN_STA_CLEAR_PS_FILT);
395d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg
396d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	/*
397d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * This code races in the following way:
398d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *
399d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *  (1) STA sends frame indicating it will go to sleep and does so
400d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *  (2) hardware/firmware adds STA to filter list, passes frame up
401d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *  (3) hardware/firmware processes TX fifo and suppresses a frame
402d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *  (4) we get TX status before having processed the frame and
403d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *	knowing that the STA has gone to sleep.
404d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *
405d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * This is actually quite unlikely even when both those events are
406d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * processed from interrupts coming in quickly after one another or
407d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * even at the same time because we queue both TX status events and
408d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * RX frames to be processed by a tasklet and process them in the
409d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * same order that they were received or TX status last. Hence, there
410d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * is no race as long as the frame RX is processed before the next TX
411d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * status, which drivers can ensure, see below.
412d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *
413d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * Note that this can only happen if the hardware or firmware can
414d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * actually add STAs to the filter list, if this is done by the
415d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * driver in response to set_tim() (which will only reduce the race
416d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * this whole filtering tries to solve, not completely solve it)
417d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * this situation cannot happen.
418d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *
419d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 * To completely solve this race drivers need to make sure that they
420d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *  (a) don't mix the irq-safe/not irq-safe TX status/RX processing
421d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *	functions and
422d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *  (b) always process RX events before TX status events if ordering
423d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *      can be unknown, for example with different interrupt status
424d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 *	bits.
425d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	 */
42607346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg	if (test_sta_flags(sta, WLAN_STA_PS) &&
427d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	    skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) {
428e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		ieee80211_remove_tx_extra(local, sta->key, skb);
429d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		skb_queue_tail(&sta->tx_filtered, skb);
430d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		return;
431d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	}
432d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg
43307346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg	if (!test_sta_flags(sta, WLAN_STA_PS) &&
434e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	    !(info->flags & IEEE80211_TX_CTL_REQUEUE)) {
435d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		/* Software retry the packet once */
436e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		info->flags |= IEEE80211_TX_CTL_REQUEUE;
437e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		ieee80211_remove_tx_extra(local, sta->key, skb);
438d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		dev_queue_xmit(skb);
439d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		return;
440d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	}
441d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg
442f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
443d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	if (net_ratelimit())
444d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		printk(KERN_DEBUG "%s: dropped TX filtered frame, "
445d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		       "queue_len=%d PS=%d @%lu\n",
446d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		       wiphy_name(local->hw.wiphy),
447d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg		       skb_queue_len(&sta->tx_filtered),
44807346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg		       !!test_sta_flags(sta, WLAN_STA_PS), jiffies);
449f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#endif
450d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg	dev_kfree_skb(skb);
451d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg}
452d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg
453e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Bergvoid ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
454f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
455f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct sk_buff *skb2;
456f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
457f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_local *local = hw_to_local(hw);
458e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
459f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	u16 frag, type;
460429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky	__le16 fc;
4614b7679a561e552eeda1e3567119bef2bca99b66eJohannes Berg	struct ieee80211_supported_band *sband;
462b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	struct ieee80211_tx_status_rtap_hdr *rthdr;
463b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	struct ieee80211_sub_if_data *sdata;
4643d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	struct net_device *prev_dev = NULL;
465429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky	struct sta_info *sta;
466f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
467d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	rcu_read_lock();
468d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg
46995dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg	sta = sta_info_get(local, hdr->addr1);
47095dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg
47195dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg	if (sta) {
47295dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg		if (info->status.excessive_retries &&
47395dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg		    test_sta_flags(sta, WLAN_STA_PS)) {
47495dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg			/*
47595dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg			 * The STA is in power save mode, so assume
47695dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg			 * that this TX packet failed because of that.
47795dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg			 */
47895dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg			ieee80211_handle_filtered_frame(local, sta, skb);
47995dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg			rcu_read_unlock();
48095dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg			return;
481f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		}
482f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
48395dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg		fc = hdr->frame_control;
48495dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg
48595dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg		if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&
48695dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg		    (ieee80211_is_data_qos(fc))) {
48795dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg			u16 tid, ssn;
48895dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg			u8 *qc;
489429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky
490429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky			qc = ieee80211_get_qos_ctl(hdr);
491429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky			tid = qc[0] & 0xf;
492429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky			ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10)
493429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky						& IEEE80211_SCTL_SEQ);
494f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greene			ieee80211_send_bar(sta->sdata, hdr->addr1,
495429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky					   tid, ssn);
496429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky		}
497429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky
49895dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg		if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
499e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			ieee80211_handle_filtered_frame(local, sta, skb);
500d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg			rcu_read_unlock();
501f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			return;
50295dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg		} else {
50395dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg			if (info->status.excessive_retries)
50495dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg				sta->tx_retry_failed++;
50595dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg			sta->tx_retry_count += info->status.retry_count;
506f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		}
50795dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg
5084b7679a561e552eeda1e3567119bef2bca99b66eJohannes Berg		sband = local->hw.wiphy->bands[info->band];
5094b7679a561e552eeda1e3567119bef2bca99b66eJohannes Berg		rate_control_tx_status(local, sband, sta, skb);
51095dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg	}
511f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
512d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg	rcu_read_unlock();
513d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg
514f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	ieee80211_led_tx(local, 0);
515f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
516f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	/* SNMP counters
517f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * Fragments are passed to low-level drivers as separate skbs, so these
518f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * are actually fragments, not frames. Update frame counters only for
519f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * the first fragment of the frame. */
520f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
521f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
522f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE;
523f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
524e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (info->flags & IEEE80211_TX_STAT_ACK) {
525f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		if (frag == 0) {
526f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			local->dot11TransmittedFrameCount++;
527f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			if (is_multicast_ether_addr(hdr->addr1))
528f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc				local->dot11MulticastTransmittedFrameCount++;
529e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			if (info->status.retry_count > 0)
530f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc				local->dot11RetryCount++;
531e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			if (info->status.retry_count > 1)
532f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc				local->dot11MultipleRetryCount++;
533f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		}
534f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
535f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		/* This counter shall be incremented for an acknowledged MPDU
536f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		 * with an individual address in the address 1 field or an MPDU
537f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		 * with a multicast address in the address 1 field of type Data
538f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		 * or Management. */
539f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		if (!is_multicast_ether_addr(hdr->addr1) ||
540f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		    type == IEEE80211_FTYPE_DATA ||
541f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		    type == IEEE80211_FTYPE_MGMT)
542f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			local->dot11TransmittedFragmentCount++;
543f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	} else {
544f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		if (frag == 0)
545f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			local->dot11FailedCount++;
546f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
547f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
548b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	/* this was a transmitted frame, but now we want to reuse it */
549b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	skb_orphan(skb);
550b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg
5513d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	/*
5523d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	 * This is a bit racy but we can avoid a lot of work
5533d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	 * with this test...
5543d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	 */
5553d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	if (!local->monitors && !local->cooked_mntrs) {
556f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		dev_kfree_skb(skb);
557f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		return;
558f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
559f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
560b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	/* send frame to monitor interfaces now */
561f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
562b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	if (skb_headroom(skb) < sizeof(*rthdr)) {
563b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg		printk(KERN_ERR "ieee80211_tx_status: headroom too small\n");
564f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		dev_kfree_skb(skb);
565f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		return;
566f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
567f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
568988c0f723d0b1abb399e6e71d8bf3f8bf1949a70Johannes Berg	rthdr = (struct ieee80211_tx_status_rtap_hdr *)
569b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg				skb_push(skb, sizeof(*rthdr));
570b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg
571b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	memset(rthdr, 0, sizeof(*rthdr));
572b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
573b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	rthdr->hdr.it_present =
574b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg		cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
575b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg			    (1 << IEEE80211_RADIOTAP_DATA_RETRIES));
576b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg
577e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
578b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	    !is_multicast_ether_addr(hdr->addr1))
579b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL);
580b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg
581e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) &&
582e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	    (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT))
583b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS);
584e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	else if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
585b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS);
586b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg
587e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	rthdr->data_retries = info->status.retry_count;
588b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg
5893d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	/* XXX: is this sufficient for BPF? */
5903d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	skb_set_mac_header(skb, 0);
5913d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	skb->ip_summed = CHECKSUM_UNNECESSARY;
5923d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	skb->pkt_type = PACKET_OTHERHOST;
5933d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	skb->protocol = htons(ETH_P_802_2);
5943d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	memset(skb->cb, 0, sizeof(skb->cb));
5953d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu
59679010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	rcu_read_lock();
59779010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
59805c914fe330fa8e1cc67870dc0d3809dfd96c107Johannes Berg		if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
599b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg			if (!netif_running(sdata->dev))
600b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg				continue;
6013d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu
6023d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu			if (prev_dev) {
60379010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg				skb2 = skb_clone(skb, GFP_ATOMIC);
6043d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu				if (skb2) {
6053d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu					skb2->dev = prev_dev;
6063d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu					netif_rx(skb2);
6073d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu				}
6083d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu			}
6093d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu
6103d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu			prev_dev = sdata->dev;
611b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg		}
612b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	}
6133d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	if (prev_dev) {
6143d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu		skb->dev = prev_dev;
6153d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu		netif_rx(skb);
6163d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu		skb = NULL;
6173d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	}
61879010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	rcu_read_unlock();
6193d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu	dev_kfree_skb(skb);
620f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
621f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_tx_status);
622f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
623f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstruct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
624f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc					const struct ieee80211_ops *ops)
625f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
626f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_local *local;
627f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	int priv_size;
628f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct wiphy *wiphy;
629f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
630f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	/* Ensure 32-byte alignment of our private data and hw private data.
631f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * We use the wiphy priv data for both our ieee80211_local and for
632f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * the driver's private data
633f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 *
634f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * In memory it'll be like this:
635f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 *
636f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * +-------------------------+
637f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * | struct wiphy	    |
638f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * +-------------------------+
639f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * | struct ieee80211_local  |
640f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * +-------------------------+
641f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * | driver's private data   |
642f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 * +-------------------------+
643f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 *
644f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	 */
645f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	priv_size = ((sizeof(struct ieee80211_local) +
646f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		      NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) +
647f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		    priv_data_len;
648f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
649f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	wiphy = wiphy_new(&mac80211_config_ops, priv_size);
650f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
651f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (!wiphy)
652f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		return NULL;
653f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
654f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	wiphy->privid = mac80211_wiphy_privid;
655f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
656f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local = wiphy_priv(wiphy);
657f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local->hw.wiphy = wiphy;
658f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
659f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local->hw.priv = (char *)local +
660f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			 ((sizeof(struct ieee80211_local) +
661f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			   NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
662f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
6634480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg	BUG_ON(!ops->tx);
6644150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	BUG_ON(!ops->start);
6654150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	BUG_ON(!ops->stop);
6664480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg	BUG_ON(!ops->config);
6674480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg	BUG_ON(!ops->add_interface);
6684150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	BUG_ON(!ops->remove_interface);
6694150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	BUG_ON(!ops->configure_filter);
670f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local->ops = ops;
671f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
672f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local->hw.queues = 1; /* default */
673f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
674f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
675f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
6769124b07740c51cbc6e358dd0c4abc6ee8ded084dJohannes Berg	local->hw.conf.long_frame_max_tx_count = 4;
6779124b07740c51cbc6e358dd0c4abc6ee8ded084dJohannes Berg	local->hw.conf.short_frame_max_tx_count = 7;
678e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg	local->hw.conf.radio_enabled = true;
679f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
68079010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	INIT_LIST_HEAD(&local->interfaces);
681f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
682b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg	spin_lock_init(&local->key_lock);
683b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg
684c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg	INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
685f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
686f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	sta_info_init(local);
687f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
688f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
689f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		     (unsigned long)local);
690f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	tasklet_disable(&local->tx_pending_tasklet);
691f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
692f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	tasklet_init(&local->tasklet,
693f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		     ieee80211_tasklet_handler,
694f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		     (unsigned long) local);
695f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	tasklet_disable(&local->tasklet);
696f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
697f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	skb_queue_head_init(&local->skb_queue);
698f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	skb_queue_head_init(&local->skb_queue_unreliable);
699f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
700f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	return local_to_hw(local);
701f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
702f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_alloc_hw);
703f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
704f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencint ieee80211_register_hw(struct ieee80211_hw *hw)
705f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
706f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_local *local = hw_to_local(hw);
707f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	const char *name;
708f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	int result;
7098318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	enum ieee80211_band band;
71096d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	struct net_device *mdev;
711133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg	struct ieee80211_master_priv *mpriv;
7128318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg
7138318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	/*
7148318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	 * generic code guarantees at least one band,
7158318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	 * set this very early because much code assumes
7168318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	 * that hw.conf.channel is assigned
7178318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	 */
7188318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
7198318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		struct ieee80211_supported_band *sband;
7208318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg
7218318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		sband = local->hw.wiphy->bands[band];
7228318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		if (sband) {
7238318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			/* init channel we're on */
7248318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			local->hw.conf.channel =
7258318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			local->oper_channel =
7268318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			local->scan_channel = &sband->channels[0];
7278318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			break;
7288318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		}
7298318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	}
730f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
731f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez	/* if low-level driver supports AP, we also support VLAN */
732f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez	if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP))
733f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez		local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
734f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez
735f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez	/* mac80211 always supports monitor */
736f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez	local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
737f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez
738f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	result = wiphy_register(local->hw.wiphy);
739f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (result < 0)
740f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		return result;
741f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
742e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg	/*
743e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg	 * We use the number of queues for feature tests (QoS, HT) internally
744e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg	 * so restrict them appropriately.
745e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg	 */
746e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg	if (hw->queues > IEEE80211_MAX_QUEUES)
747e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg		hw->queues = IEEE80211_MAX_QUEUES;
748e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg	if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES)
749e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg		hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES;
750e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg	if (hw->queues < 4)
751e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg		hw->ampdu_queues = 0;
752e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg
753133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg	mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv),
754e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg			       "wmaster%d", ether_setup,
755e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg			       ieee80211_num_queues(hw));
75696d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	if (!mdev)
75796d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg		goto fail_mdev_alloc;
75896d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg
759133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg	mpriv = netdev_priv(mdev);
760133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg	mpriv->local = local;
76196d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	local->mdev = mdev;
76296d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg
7633e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	ieee80211_rx_bss_list_init(local);
76496d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg
76596d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	mdev->hard_start_xmit = ieee80211_master_start_xmit;
76696d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	mdev->open = ieee80211_master_open;
76796d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	mdev->stop = ieee80211_master_stop;
76896d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	mdev->type = ARPHRD_IEEE80211;
76996d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	mdev->header_ops = &ieee80211_header_ops;
77096d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg	mdev->set_multicast_list = ieee80211_master_set_multicast_list;
77196d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg
772f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	name = wiphy_dev(local->hw.wiphy)->driver->name;
77359959a6150c8af737898e83f727e824dbed7b0faJohannes Berg	local->hw.workqueue = create_freezeable_workqueue(name);
774f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (!local->hw.workqueue) {
775f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		result = -ENOMEM;
776f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		goto fail_workqueue;
777f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
778f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
779b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	/*
780b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	 * The hardware needs headroom for sending the frame,
781b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	 * and we need some headroom for passing the frame to monitor
782b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	 * interfaces, but never both at the same time.
783b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg	 */
78433ccad35a21df51c0d23f3e3e88688524e7b51edJiri Benc	local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
78533ccad35a21df51c0d23f3e3e88688524e7b51edJiri Benc				   sizeof(struct ieee80211_tx_status_rtap_hdr));
786b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg
787e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc	debugfs_hw_add(local);
788e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc
789dc0ae30c31ee6ef83992bb692f37dfbba08a2ef6Tomas Winkler	if (local->hw.conf.beacon_int < 10)
790dc0ae30c31ee6ef83992bb692f37dfbba08a2ef6Tomas Winkler		local->hw.conf.beacon_int = 100;
791f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
792ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler	if (local->hw.max_listen_interval == 0)
793ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler		local->hw.max_listen_interval = 1;
794ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler
795ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler	local->hw.conf.listen_interval = local->hw.max_listen_interval;
796ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler
797566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf	local->wstats_flags |= local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC |
798566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf						  IEEE80211_HW_SIGNAL_DB |
799566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf						  IEEE80211_HW_SIGNAL_DBM) ?
800f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			       IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID;
801566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf	local->wstats_flags |= local->hw.flags & IEEE80211_HW_NOISE_DBM ?
802f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			       IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID;
803566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
804f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		local->wstats_flags |= IW_QUAL_DBM;
805f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
806f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	result = sta_info_start(local);
807f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (result < 0)
808f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		goto fail_sta_info;
809f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
810f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	rtnl_lock();
811f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	result = dev_alloc_name(local->mdev, local->mdev->name);
812f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (result < 0)
813f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		goto fail_dev;
814f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
815f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
816f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy));
817f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
818f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	result = register_netdevice(local->mdev);
819f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (result < 0)
820f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		goto fail_dev;
821f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
822830f903866a1611e9ce53f3e35202302bb938946Johannes Berg	result = ieee80211_init_rate_ctrl_alg(local,
823830f903866a1611e9ce53f3e35202302bb938946Johannes Berg					      hw->rate_control_algorithm);
824f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (result < 0) {
825f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		printk(KERN_DEBUG "%s: Failed to initialize rate control "
826dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg		       "algorithm\n", wiphy_name(local->hw.wiphy));
827f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		goto fail_rate;
828f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
829f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
830f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	result = ieee80211_wep_init(local);
831f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
832f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (result < 0) {
833023a04bebe7030c1e6d5347bd3f27a3e49a1f222Jeremy Fitzhardinge		printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n",
834023a04bebe7030c1e6d5347bd3f27a3e49a1f222Jeremy Fitzhardinge		       wiphy_name(local->hw.wiphy), result);
835f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		goto fail_wep;
836f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	}
837f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
83851cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller	local->mdev->select_queue = ieee80211_select_queue;
839f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
840f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	/* add one default STA interface */
8413e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	result = ieee80211_if_add(local, "wlan%d", NULL,
84205c914fe330fa8e1cc67870dc0d3809dfd96c107Johannes Berg				  NL80211_IFTYPE_STATION, NULL);
843f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (result)
844f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
845dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg		       wiphy_name(local->hw.wiphy));
846f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
847f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	rtnl_unlock();
848f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
849f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	ieee80211_led_init(local);
850f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
851f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	return 0;
852f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
853f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_wep:
854f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	rate_control_deinitialize(local);
855f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_rate:
856f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	unregister_netdevice(local->mdev);
857339a7c41c913035bf58579f6e47b4ba29da83795Pavel Emelyanov	local->mdev = NULL;
858f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_dev:
859f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	rtnl_unlock();
860f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	sta_info_stop(local);
861f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_sta_info:
862e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc	debugfs_hw_del(local);
863f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	destroy_workqueue(local->hw.workqueue);
864f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_workqueue:
8653e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	if (local->mdev)
8663e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg		free_netdev(local->mdev);
86796d510566e4908f77f03ff1436c78ae7162a17d0Johannes Bergfail_mdev_alloc:
868f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	wiphy_unregister(local->hw.wiphy);
869f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	return result;
870f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
871f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_register_hw);
872f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
873f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_unregister_hw(struct ieee80211_hw *hw)
874f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
875f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_local *local = hw_to_local(hw);
876f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
877f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	tasklet_kill(&local->tx_pending_tasklet);
878f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	tasklet_kill(&local->tasklet);
879f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
880f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	rtnl_lock();
881f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
88279010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	/*
88379010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	 * At this point, interface list manipulations are fine
88479010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	 * because the driver cannot be handing us frames any
88579010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	 * more and the tasklet is killed.
88679010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg	 */
8875b2812e925c8e976852867f8d760637c5926d817Johannes Berg
88875636525fbfa78fa33fd754c89785cfde750acd3Johannes Berg	/* First, we remove all virtual interfaces. */
88975636525fbfa78fa33fd754c89785cfde750acd3Johannes Berg	ieee80211_remove_interfaces(local);
8905b2812e925c8e976852867f8d760637c5926d817Johannes Berg
8915b2812e925c8e976852867f8d760637c5926d817Johannes Berg	/* then, finally, remove the master interface */
8923e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	unregister_netdevice(local->mdev);
893f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
894f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	rtnl_unlock();
895f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
8963e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	ieee80211_rx_bss_list_deinit(local);
897f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	ieee80211_clear_tx_pending(local);
898f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	sta_info_stop(local);
899f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	rate_control_deinitialize(local);
900e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc	debugfs_hw_del(local);
901f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
902f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	if (skb_queue_len(&local->skb_queue)
903f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc			|| skb_queue_len(&local->skb_queue_unreliable))
904f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc		printk(KERN_WARNING "%s: skb_queue not empty\n",
905dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg		       wiphy_name(local->hw.wiphy));
906f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	skb_queue_purge(&local->skb_queue);
907f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	skb_queue_purge(&local->skb_queue_unreliable);
908f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
909f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	destroy_workqueue(local->hw.workqueue);
910f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	wiphy_unregister(local->hw.wiphy);
911f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	ieee80211_wep_free(local);
912f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	ieee80211_led_exit(local);
9133e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg	free_netdev(local->mdev);
914f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
915f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_unregister_hw);
916f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
917f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_free_hw(struct ieee80211_hw *hw)
918f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
919f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct ieee80211_local *local = hw_to_local(hw);
920f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
921f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	wiphy_free(local->hw.wiphy);
922f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
923f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_free_hw);
924f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
925f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic int __init ieee80211_init(void)
926f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
927f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	struct sk_buff *skb;
928f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	int ret;
929f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
930e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	BUILD_BUG_ON(sizeof(struct ieee80211_tx_info) > sizeof(skb->cb));
931e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) +
932c6a1fa12d206882757264869f8e32d606b930e2aJohannes Berg		     IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb));
933f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
934cccf129f820e431d84690729254a32f1709328fbFelix Fietkau	ret = rc80211_minstrel_init();
935cccf129f820e431d84690729254a32f1709328fbFelix Fietkau	if (ret)
936cccf129f820e431d84690729254a32f1709328fbFelix Fietkau		return ret;
937cccf129f820e431d84690729254a32f1709328fbFelix Fietkau
9384b475898ec9dc6e62cebcb8fc0b3495c986a4590Johannes Berg	ret = rc80211_pid_init();
939ad01837593338f13508463fa11c8dbf8109a1e5dMattias Nissler	if (ret)
94051cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller		return ret;
941f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
942e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc	ieee80211_debugfs_netdev_init();
943e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc
944f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc	return 0;
945f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
946f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
947f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void __exit ieee80211_exit(void)
948f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{
9494b475898ec9dc6e62cebcb8fc0b3495c986a4590Johannes Berg	rc80211_pid_exit();
950cccf129f820e431d84690729254a32f1709328fbFelix Fietkau	rc80211_minstrel_exit();
951ac71c691e6a5ce991fe221d3bdb0c972f617aa37Johannes Berg
9523b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	/*
9533b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	 * For key todo, it'll be empty by now but the work
9543b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	 * might still be scheduled.
9553b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	 */
9563b96766f0e643f52ae19e134664df6730c737e87Johannes Berg	flush_scheduled_work();
9573b96766f0e643f52ae19e134664df6730c737e87Johannes Berg
958f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo	if (mesh_allocated)
959f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo		ieee80211s_stop();
960902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg
961e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc	ieee80211_debugfs_netdev_exit();
962f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc}
963f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
964f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
965ca9938fea576ebbb8d8c4fbe8a5bcc937e49e1caJohannes Bergsubsys_initcall(ieee80211_init);
966f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencmodule_exit(ieee80211_exit);
967f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc
968f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencMODULE_DESCRIPTION("IEEE 802.11 subsystem");
969f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencMODULE_LICENSE("GPL");
970