main.c revision 2a577d98712a284a612dd51d69db5cb989810dc2
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; 44e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg u8 rate; 45e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg u8 padding_for_rate; 46b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg __le16 tx_flags; 47b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg u8 data_retries; 48b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg} __attribute__ ((packed)); 49b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 50f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 514150c57212ad134765dd78c654a4b9906252b66dJohannes Berg/* must be called under mdev tx lock */ 520d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Bergvoid ieee80211_configure_filter(struct ieee80211_local *local) 534150c57212ad134765dd78c654a4b9906252b66dJohannes Berg{ 544150c57212ad134765dd78c654a4b9906252b66dJohannes Berg unsigned int changed_flags; 554150c57212ad134765dd78c654a4b9906252b66dJohannes Berg unsigned int new_flags = 0; 564150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 5753918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg if (atomic_read(&local->iff_promiscs)) 584150c57212ad134765dd78c654a4b9906252b66dJohannes Berg new_flags |= FIF_PROMISC_IN_BSS; 594150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 6053918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg if (atomic_read(&local->iff_allmultis)) 614150c57212ad134765dd78c654a4b9906252b66dJohannes Berg new_flags |= FIF_ALLMULTI; 624150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 634150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (local->monitors) 648cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu new_flags |= FIF_BCN_PRBRESP_PROMISC; 658cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 668cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (local->fif_fcsfail) 678cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu new_flags |= FIF_FCSFAIL; 688cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 698cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (local->fif_plcpfail) 708cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu new_flags |= FIF_PLCPFAIL; 718cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 728cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (local->fif_control) 738cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu new_flags |= FIF_CONTROL; 748cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 758cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (local->fif_other_bss) 768cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu new_flags |= FIF_OTHER_BSS; 774150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 784150c57212ad134765dd78c654a4b9906252b66dJohannes Berg changed_flags = local->filter_flags ^ new_flags; 794150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 804150c57212ad134765dd78c654a4b9906252b66dJohannes Berg /* be a bit nasty */ 814150c57212ad134765dd78c654a4b9906252b66dJohannes Berg new_flags |= (1<<31); 824150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 834150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->ops->configure_filter(local_to_hw(local), 844150c57212ad134765dd78c654a4b9906252b66dJohannes Berg changed_flags, &new_flags, 854150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->mdev->mc_count, 864150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->mdev->mc_list); 874150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 884150c57212ad134765dd78c654a4b9906252b66dJohannes Berg WARN_ON(new_flags & (1<<31)); 894150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 904150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->filter_flags = new_flags & ~(1<<31); 914150c57212ad134765dd78c654a4b9906252b66dJohannes Berg} 924150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 93b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg/* master interface */ 94f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 950d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Bergstatic int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr) 960d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg{ 970d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */ 980d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg return ETH_ALEN; 990d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg} 1000d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg 1010d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Bergstatic const struct header_ops ieee80211_header_ops = { 1020d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg .create = eth_header, 1030d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg .parse = header_parse_80211, 1040d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg .rebuild = eth_rebuild_header, 1050d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg .cache = eth_header_cache, 1060d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg .cache_update = eth_header_cache_update, 1070d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg}; 1080d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1Johannes Berg 109b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic int ieee80211_master_open(struct net_device *dev) 110b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{ 111133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg struct ieee80211_master_priv *mpriv = netdev_priv(dev); 112133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg struct ieee80211_local *local = mpriv->local; 113b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_sub_if_data *sdata; 114b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg int res = -EOPNOTSUPP; 115f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 11679010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg /* we hold the RTNL here so can safely walk the list */ 11779010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg list_for_each_entry(sdata, &local->interfaces, list) { 1183e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg if (netif_running(sdata->dev)) { 119b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg res = 0; 120b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg break; 121b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 122b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 12336d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg 12436d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg if (res) 12536d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg return res; 12636d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg 12751cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller netif_tx_start_all_queues(local->mdev); 12836d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg 12936d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg return 0; 130b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 131f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 132b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic int ieee80211_master_stop(struct net_device *dev) 133f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 134133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg struct ieee80211_master_priv *mpriv = netdev_priv(dev); 135133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg struct ieee80211_local *local = mpriv->local; 136b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_sub_if_data *sdata; 137f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 13879010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg /* we hold the RTNL here so can safely walk the list */ 13979010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg list_for_each_entry(sdata, &local->interfaces, list) 1403e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg if (netif_running(sdata->dev)) 141b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev_close(sdata->dev); 142f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 143b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return 0; 144b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 145f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1464150c57212ad134765dd78c654a4b9906252b66dJohannes Bergstatic void ieee80211_master_set_multicast_list(struct net_device *dev) 1474150c57212ad134765dd78c654a4b9906252b66dJohannes Berg{ 148133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg struct ieee80211_master_priv *mpriv = netdev_priv(dev); 149133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg struct ieee80211_local *local = mpriv->local; 1504150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 1514150c57212ad134765dd78c654a4b9906252b66dJohannes Berg ieee80211_configure_filter(local); 1524150c57212ad134765dd78c654a4b9906252b66dJohannes Berg} 1534150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 154b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg/* everything else */ 155b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg 1569d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Bergint ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) 157b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{ 1589d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg struct ieee80211_local *local = sdata->local; 159b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_if_conf conf; 160b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg 1619d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg if (WARN_ON(!netif_running(sdata->dev))) 1629d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg return 0; 1639d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg 164b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg memset(&conf, 0, sizeof(conf)); 1659d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg 166469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (sdata->vif.type == NL80211_IFTYPE_STATION) 167469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg conf.bssid = sdata->u.mgd.bssid; 168469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) 169469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg conf.bssid = sdata->u.ibss.bssid; 17041bb73eeac5ff5fb217257ba33b654747b3abf11Johannes Berg else if (sdata->vif.type == NL80211_IFTYPE_AP) 1719d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg conf.bssid = sdata->dev->dev_addr; 17241bb73eeac5ff5fb217257ba33b654747b3abf11Johannes Berg else if (ieee80211_vif_is_mesh(&sdata->vif)) { 1735f936f11613c32ca7f8ed5fa333bb38a4501deebJohannes Berg static const u8 zero[ETH_ALEN] = { 0 }; 1749d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg conf.bssid = zero; 1759d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg } else { 1769d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg WARN_ON(1); 1779d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg return -EINVAL; 178f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 179f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 180b5bde374f0f61f5d97114d400ade8fc96bf6f10dJohannes Berg if (!local->ops->config_interface) 181b5bde374f0f61f5d97114d400ade8fc96bf6f10dJohannes Berg return 0; 182b5bde374f0f61f5d97114d400ade8fc96bf6f10dJohannes Berg 183078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg switch (sdata->vif.type) { 184078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg case NL80211_IFTYPE_AP: 185078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg case NL80211_IFTYPE_ADHOC: 186078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg case NL80211_IFTYPE_MESH_POINT: 187078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg break; 188078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg default: 189078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg /* do not warn to simplify caller in scan.c */ 190078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg changed &= ~IEEE80211_IFCC_BEACON_ENABLED; 191078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg if (WARN_ON(changed & IEEE80211_IFCC_BEACON)) 192078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg return -EINVAL; 193078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg changed &= ~IEEE80211_IFCC_BEACON; 194078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg break; 195078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg } 196078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg 197078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg if (changed & IEEE80211_IFCC_BEACON_ENABLED) { 198078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg if (local->sw_scanning) { 199078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg conf.enable_beacon = false; 200078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg } else { 201078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg /* 202078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg * Beacon should be enabled, but AP mode must 203078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg * check whether there is a beacon configured. 204078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg */ 205078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg switch (sdata->vif.type) { 206078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg case NL80211_IFTYPE_AP: 207078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg conf.enable_beacon = 208078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg !!rcu_dereference(sdata->u.ap.beacon); 209078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg break; 210078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg case NL80211_IFTYPE_ADHOC: 211469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg conf.enable_beacon = !!sdata->u.ibss.probe_resp; 2125e1333624827e7a91b2d2cc04ce978f050cae15eJohannes Berg break; 213078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg case NL80211_IFTYPE_MESH_POINT: 214078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg conf.enable_beacon = true; 215078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg break; 216078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg default: 217078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg /* not reached */ 218078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg WARN_ON(1); 219078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg break; 220078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg } 221078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg } 222078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg } 223078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg 224078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg conf.changed = changed; 225078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ffJohannes Berg 2269d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg return local->ops->config_interface(local_to_hw(local), 2279d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg &sdata->vif, &conf); 228b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 229f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 230e8975581f63870be42ff4662b293d1b0c8c21350Johannes Bergint ieee80211_hw_config(struct ieee80211_local *local, u32 changed) 231b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{ 232b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_channel *chan; 233b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg int ret = 0; 234e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg int power; 235094d05dc32fc2930e381189a942016e5561775d9Sujith enum nl80211_channel_type channel_type; 236f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 237cb121bad67a32cde37adc2729b7e18aa4fd3063eJohannes Berg might_sleep(); 238cb121bad67a32cde37adc2729b7e18aa4fd3063eJohannes Berg 23972bdcf34380917260da41e3c49e10edee04bc5cdJouni Malinen if (local->sw_scanning) { 240b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg chan = local->scan_channel; 241094d05dc32fc2930e381189a942016e5561775d9Sujith channel_type = NL80211_CHAN_NO_HT; 24272bdcf34380917260da41e3c49e10edee04bc5cdJouni Malinen } else { 243b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg chan = local->oper_channel; 244094d05dc32fc2930e381189a942016e5561775d9Sujith channel_type = local->oper_channel_type; 24572bdcf34380917260da41e3c49e10edee04bc5cdJouni Malinen } 246f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 24772bdcf34380917260da41e3c49e10edee04bc5cdJouni Malinen if (chan != local->hw.conf.channel || 2484797938c5dfa22af30fd16679192972f878419a1Johannes Berg channel_type != local->hw.conf.channel_type) { 249e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg local->hw.conf.channel = chan; 2504797938c5dfa22af30fd16679192972f878419a1Johannes Berg local->hw.conf.channel_type = channel_type; 251e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg changed |= IEEE80211_CONF_CHANGE_CHANNEL; 252e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg } 2538318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 254a8302de934b5d1897ff146cd0c7ab87d1417c092Vasanthakumar Thiagarajan if (local->sw_scanning) 255e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg power = chan->max_power; 2568318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg else 257a8302de934b5d1897ff146cd0c7ab87d1417c092Vasanthakumar Thiagarajan power = local->power_constr_level ? 258a8302de934b5d1897ff146cd0c7ab87d1417c092Vasanthakumar Thiagarajan (chan->max_power - local->power_constr_level) : 259a8302de934b5d1897ff146cd0c7ab87d1417c092Vasanthakumar Thiagarajan chan->max_power; 260a8302de934b5d1897ff146cd0c7ab87d1417c092Vasanthakumar Thiagarajan 261a8302de934b5d1897ff146cd0c7ab87d1417c092Vasanthakumar Thiagarajan if (local->user_power_level) 262a8302de934b5d1897ff146cd0c7ab87d1417c092Vasanthakumar Thiagarajan power = min(power, local->user_power_level); 263a8302de934b5d1897ff146cd0c7ab87d1417c092Vasanthakumar Thiagarajan 264e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg if (local->hw.conf.power_level != power) { 265e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg changed |= IEEE80211_CONF_CHANGE_POWER; 266e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg local->hw.conf.power_level = power; 267e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg } 268b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg 269e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg if (changed && local->open_count) { 270e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg ret = local->ops->config(local_to_hw(local), changed); 271d73782fdde76554016abf73b46f843b29f520848Johannes Berg /* 272447107fb32d75425c95a33f58e6b4b760b470092Reinette Chatre * Goal: 273d73782fdde76554016abf73b46f843b29f520848Johannes Berg * HW reconfiguration should never fail, the driver has told 274d73782fdde76554016abf73b46f843b29f520848Johannes Berg * us what it can support so it should live up to that promise. 275447107fb32d75425c95a33f58e6b4b760b470092Reinette Chatre * 276447107fb32d75425c95a33f58e6b4b760b470092Reinette Chatre * Current status: 277447107fb32d75425c95a33f58e6b4b760b470092Reinette Chatre * rfkill is not integrated with mac80211 and a 278447107fb32d75425c95a33f58e6b4b760b470092Reinette Chatre * configuration command can thus fail if hardware rfkill 279447107fb32d75425c95a33f58e6b4b760b470092Reinette Chatre * is enabled 280447107fb32d75425c95a33f58e6b4b760b470092Reinette Chatre * 281447107fb32d75425c95a33f58e6b4b760b470092Reinette Chatre * FIXME: integrate rfkill with mac80211 and then add this 282447107fb32d75425c95a33f58e6b4b760b470092Reinette Chatre * WARN_ON() back 283447107fb32d75425c95a33f58e6b4b760b470092Reinette Chatre * 284d73782fdde76554016abf73b46f843b29f520848Johannes Berg */ 285447107fb32d75425c95a33f58e6b4b760b470092Reinette Chatre /* WARN_ON(ret); */ 286d73782fdde76554016abf73b46f843b29f520848Johannes Berg } 287f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 288b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return ret; 289b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 290f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 291471b3efdfccc257591331724145f8ccf8b3217e1Johannes Bergvoid ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, 292471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg u32 changed) 293d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake{ 294471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg struct ieee80211_local *local = sdata->local; 295471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg 2967a725f73403e874ec52c58741e9b98cd604dbd03Johannes Berg if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) 2977a725f73403e874ec52c58741e9b98cd604dbd03Johannes Berg return; 2987a725f73403e874ec52c58741e9b98cd604dbd03Johannes Berg 299471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg if (!changed) 300471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg return; 301471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg 302471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg if (local->ops->bss_info_changed) 303471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg local->ops->bss_info_changed(local_to_hw(local), 304471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg &sdata->vif, 305bda3933a8aceedd03e0dd410844bd310033ca756Johannes Berg &sdata->vif.bss_conf, 306471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg changed); 307d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake} 308d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake 309f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greeneu32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) 310d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake{ 311bda3933a8aceedd03e0dd410844bd310033ca756Johannes Berg sdata->vif.bss_conf.use_cts_prot = false; 312bda3933a8aceedd03e0dd410844bd310033ca756Johannes Berg sdata->vif.bss_conf.use_short_preamble = false; 313bda3933a8aceedd03e0dd410844bd310033ca756Johannes Berg sdata->vif.bss_conf.use_short_slot = false; 3147a5158ef8da70fdedeb0530faaa8128aa645be3cJohannes Berg return BSS_CHANGED_ERP_CTS_PROT | 3157a5158ef8da70fdedeb0530faaa8128aa645be3cJohannes Berg BSS_CHANGED_ERP_PREAMBLE | 3167a5158ef8da70fdedeb0530faaa8128aa645be3cJohannes Berg BSS_CHANGED_ERP_SLOT; 317d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake} 318d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake 319f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, 320e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct sk_buff *skb) 321f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 322f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 323e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 324f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc int tmp; 325f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 326f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb->dev = local->mdev; 327f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb->pkt_type = IEEE80211_TX_STATUS_MSG; 328e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ? 329f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc &local->skb_queue : &local->skb_queue_unreliable, skb); 330f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tmp = skb_queue_len(&local->skb_queue) + 331f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_len(&local->skb_queue_unreliable); 332f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT && 333f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc (skb = skb_dequeue(&local->skb_queue_unreliable))) { 334f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb_irq(skb); 335f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tmp--; 336f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc I802_DEBUG_INC(local->tx_status_drop); 337f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 338f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_schedule(&local->tasklet); 339f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 340f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_tx_status_irqsafe); 341f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 342f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void ieee80211_tasklet_handler(unsigned long data) 343f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 344f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = (struct ieee80211_local *) data; 345f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sk_buff *skb; 346f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_rx_status rx_status; 347eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_ra_tid *ra_tid; 348f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 349f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc while ((skb = skb_dequeue(&local->skb_queue)) || 350f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc (skb = skb_dequeue(&local->skb_queue_unreliable))) { 351f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc switch (skb->pkt_type) { 352f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case IEEE80211_RX_MSG: 353f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* status is in skb->cb */ 354f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memcpy(&rx_status, skb->cb, sizeof(rx_status)); 35551fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg /* Clear skb->pkt_type in order to not confuse kernel 356f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * netstack. */ 357f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb->pkt_type = 0; 358f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc __ieee80211_rx(local_to_hw(local), skb, &rx_status); 359f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 360f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case IEEE80211_TX_STATUS_MSG: 361f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb->pkt_type = 0; 362e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_tx_status(local_to_hw(local), skb); 363f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 364eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky case IEEE80211_DELBA_MSG: 365eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid = (struct ieee80211_ra_tid *) &skb->cb; 366eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ieee80211_stop_tx_ba_cb(local_to_hw(local), 367eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid->ra, ra_tid->tid); 368eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky dev_kfree_skb(skb); 369eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky break; 370eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky case IEEE80211_ADDBA_MSG: 371eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid = (struct ieee80211_ra_tid *) &skb->cb; 372eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ieee80211_start_tx_ba_cb(local_to_hw(local), 373eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid->ra, ra_tid->tid); 374eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky dev_kfree_skb(skb); 375eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky break ; 376f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg default: 3775e3f308997f53d00e8cbebdb89d4f6e347aa963aLarry Finger WARN(1, "mac80211: Packet is of unknown type %d\n", 3785e3f308997f53d00e8cbebdb89d4f6e347aa963aLarry Finger skb->pkt_type); 379f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb(skb); 380f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 381f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 382f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 383f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 384f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 385f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to 386f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * make a prepared TX frame (one that has been given to hw) to look like brand 387f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * new IEEE 802.11 frame that is ready to go through TX processing again. 388d0f09804144fd9471a13cf4d80e66842c7fa114fJohannes Berg */ 389f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void ieee80211_remove_tx_extra(struct ieee80211_local *local, 390f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_key *key, 391e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct sk_buff *skb) 392f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 39362bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison unsigned int hdrlen, iv_len, mic_len; 39462bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 395f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 39662bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison hdrlen = ieee80211_hdrlen(hdr->frame_control); 397f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 398f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (!key) 399f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto no_key; 400f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 4018f20fc24986a083228823d9b68adca20714b254eJohannes Berg switch (key->conf.alg) { 402f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case ALG_WEP: 403f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc iv_len = WEP_IV_LEN; 404f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc mic_len = WEP_ICV_LEN; 405f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 406f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case ALG_TKIP: 407f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc iv_len = TKIP_IV_LEN; 408f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc mic_len = TKIP_ICV_LEN; 409f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 410f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case ALG_CCMP: 411f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc iv_len = CCMP_HDR_LEN; 412f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc mic_len = CCMP_MIC_LEN; 413f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 414f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc default: 415f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto no_key; 416f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 417f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 41862bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison if (skb->len >= hdrlen + mic_len && 41911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) 420f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_trim(skb, skb->len - mic_len); 42162bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison if (skb->len >= hdrlen + iv_len) { 422f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memmove(skb->data + iv_len, skb->data, hdrlen); 42362bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison hdr = (struct ieee80211_hdr *)skb_pull(skb, iv_len); 424f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 425f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 426f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencno_key: 42762bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison if (ieee80211_is_data_qos(hdr->frame_control)) { 42862bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); 42962bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison memmove(skb->data + IEEE80211_QOS_CTL_LEN, skb->data, 43062bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison hdrlen - IEEE80211_QOS_CTL_LEN); 43162bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison skb_pull(skb, IEEE80211_QOS_CTL_LEN); 432f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 433f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 434f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 435d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Bergstatic void ieee80211_handle_filtered_frame(struct ieee80211_local *local, 436d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg struct sta_info *sta, 437e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct sk_buff *skb) 438d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg{ 439d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg sta->tx_filtered_count++; 440d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 441d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg /* 442d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * Clear the TX filter mask for this STA when sending the next 443d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * packet. If the STA went to power save mode, this will happen 444f6d97104890203ba9c2cf8e34894c4c8e64cb880Yi Zhu * when it wakes up for the next time. 445d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg */ 44607346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg set_sta_flags(sta, WLAN_STA_CLEAR_PS_FILT); 447d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 448d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg /* 449d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * This code races in the following way: 450d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * 451d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (1) STA sends frame indicating it will go to sleep and does so 452d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (2) hardware/firmware adds STA to filter list, passes frame up 453d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (3) hardware/firmware processes TX fifo and suppresses a frame 454d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (4) we get TX status before having processed the frame and 455d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * knowing that the STA has gone to sleep. 456d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * 457d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * This is actually quite unlikely even when both those events are 458d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * processed from interrupts coming in quickly after one another or 459d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * even at the same time because we queue both TX status events and 460d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * RX frames to be processed by a tasklet and process them in the 461d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * same order that they were received or TX status last. Hence, there 462d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * is no race as long as the frame RX is processed before the next TX 463d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * status, which drivers can ensure, see below. 464d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * 465d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * Note that this can only happen if the hardware or firmware can 466d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * actually add STAs to the filter list, if this is done by the 467d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * driver in response to set_tim() (which will only reduce the race 468d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * this whole filtering tries to solve, not completely solve it) 469d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * this situation cannot happen. 470d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * 471d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * To completely solve this race drivers need to make sure that they 472d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (a) don't mix the irq-safe/not irq-safe TX status/RX processing 473d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * functions and 474d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (b) always process RX events before TX status events if ordering 475d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * can be unknown, for example with different interrupt status 476d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * bits. 477d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg */ 47807346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg if (test_sta_flags(sta, WLAN_STA_PS) && 479d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { 480e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_remove_tx_extra(local, sta->key, skb); 481d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg skb_queue_tail(&sta->tx_filtered, skb); 482d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg return; 483d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg } 484d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 4858b30b1fe368ab03049435884c11c5c50e4c4ef0bSujith if (!test_sta_flags(sta, WLAN_STA_PS) && !skb->requeue) { 486d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg /* Software retry the packet once */ 4878b30b1fe368ab03049435884c11c5c50e4c4ef0bSujith skb->requeue = 1; 488e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_remove_tx_extra(local, sta->key, skb); 489d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg dev_queue_xmit(skb); 490d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg return; 491d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg } 492d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 493f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 494d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg if (net_ratelimit()) 495d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg printk(KERN_DEBUG "%s: dropped TX filtered frame, " 496d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg "queue_len=%d PS=%d @%lu\n", 497d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg wiphy_name(local->hw.wiphy), 498d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg skb_queue_len(&sta->tx_filtered), 49907346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg !!test_sta_flags(sta, WLAN_STA_PS), jiffies); 500f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#endif 501d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg dev_kfree_skb(skb); 502d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg} 503d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 504e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Bergvoid ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) 505f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 506f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sk_buff *skb2; 507f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 508f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 509e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 510f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc u16 frag, type; 511429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky __le16 fc; 5124b7679a561e552eeda1e3567119bef2bca99b66eJohannes Berg struct ieee80211_supported_band *sband; 513b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg struct ieee80211_tx_status_rtap_hdr *rthdr; 514b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg struct ieee80211_sub_if_data *sdata; 5153d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu struct net_device *prev_dev = NULL; 516429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky struct sta_info *sta; 517e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg int retry_count = -1, i; 518e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg 519e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { 520e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg /* the HW cannot have attempted that rate */ 521e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg if (i >= hw->max_rates) { 522e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg info->status.rates[i].idx = -1; 523e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg info->status.rates[i].count = 0; 524e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg } 525e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg 526e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg retry_count += info->status.rates[i].count; 527e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg } 528e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg if (retry_count < 0) 529e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg retry_count = 0; 530f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 531d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_lock(); 532d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg 533e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg sband = local->hw.wiphy->bands[info->band]; 534e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg 53595dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg sta = sta_info_get(local, hdr->addr1); 53695dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg 53795dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg if (sta) { 538e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg if (!(info->flags & IEEE80211_TX_STAT_ACK) && 53995dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg test_sta_flags(sta, WLAN_STA_PS)) { 54095dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg /* 54195dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg * The STA is in power save mode, so assume 54295dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg * that this TX packet failed because of that. 54395dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg */ 54495dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg ieee80211_handle_filtered_frame(local, sta, skb); 54595dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg rcu_read_unlock(); 54695dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg return; 547f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 548f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 54995dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg fc = hdr->frame_control; 55095dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg 55195dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && 55295dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg (ieee80211_is_data_qos(fc))) { 55395dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg u16 tid, ssn; 55495dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg u8 *qc; 555429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky 556429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky qc = ieee80211_get_qos_ctl(hdr); 557429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky tid = qc[0] & 0xf; 558429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10) 559429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky & IEEE80211_SCTL_SEQ); 560f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greene ieee80211_send_bar(sta->sdata, hdr->addr1, 561429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky tid, ssn); 562429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky } 563429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky 56495dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { 565e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_handle_filtered_frame(local, sta, skb); 566d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 567f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return; 56895dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg } else { 569e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg if (!(info->flags & IEEE80211_TX_STAT_ACK)) 57095dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg sta->tx_retry_failed++; 571e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg sta->tx_retry_count += retry_count; 572f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 57395dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg 5744b7679a561e552eeda1e3567119bef2bca99b66eJohannes Berg rate_control_tx_status(local, sband, sta, skb); 57595dac040041723d0c0ab245642c1b9802f12cc8dJohannes Berg } 576f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 577d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 578d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg 579f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_led_tx(local, 0); 580f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 581f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* SNMP counters 582f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * Fragments are passed to low-level drivers as separate skbs, so these 583f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * are actually fragments, not frames. Update frame counters only for 584f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * the first fragment of the frame. */ 585f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 586f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; 587f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE; 588f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 589e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->flags & IEEE80211_TX_STAT_ACK) { 590f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (frag == 0) { 591f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11TransmittedFrameCount++; 592f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (is_multicast_ether_addr(hdr->addr1)) 593f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11MulticastTransmittedFrameCount++; 594e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg if (retry_count > 0) 595f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11RetryCount++; 596e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg if (retry_count > 1) 597f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11MultipleRetryCount++; 598f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 599f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 600f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* This counter shall be incremented for an acknowledged MPDU 601f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * with an individual address in the address 1 field or an MPDU 602f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * with a multicast address in the address 1 field of type Data 603f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * or Management. */ 604f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (!is_multicast_ether_addr(hdr->addr1) || 605f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc type == IEEE80211_FTYPE_DATA || 606f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc type == IEEE80211_FTYPE_MGMT) 607f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11TransmittedFragmentCount++; 608f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } else { 609f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (frag == 0) 610f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11FailedCount++; 611f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 612f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 613b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg /* this was a transmitted frame, but now we want to reuse it */ 614b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg skb_orphan(skb); 615b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 6163d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu /* 6173d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu * This is a bit racy but we can avoid a lot of work 6183d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu * with this test... 6193d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu */ 6203d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (!local->monitors && !local->cooked_mntrs) { 621f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb(skb); 622f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return; 623f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 624f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 625b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg /* send frame to monitor interfaces now */ 626f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 627b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg if (skb_headroom(skb) < sizeof(*rthdr)) { 628b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg printk(KERN_ERR "ieee80211_tx_status: headroom too small\n"); 629f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb(skb); 630f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return; 631f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 632f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 633988c0f723d0b1abb399e6e71d8bf3f8bf1949a70Johannes Berg rthdr = (struct ieee80211_tx_status_rtap_hdr *) 634b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg skb_push(skb, sizeof(*rthdr)); 635b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 636b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg memset(rthdr, 0, sizeof(*rthdr)); 637b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); 638b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->hdr.it_present = 639b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | 640e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg (1 << IEEE80211_RADIOTAP_DATA_RETRIES) | 641e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg (1 << IEEE80211_RADIOTAP_RATE)); 642b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 643e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (!(info->flags & IEEE80211_TX_STAT_ACK) && 644b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg !is_multicast_ether_addr(hdr->addr1)) 645b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); 646b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 647e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg /* 648e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg * XXX: Once radiotap gets the bitmap reset thing the vendor 649e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg * extensions proposal contains, we can actually report 650e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg * the whole set of tries we did. 651e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg */ 652e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || 653e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) 654b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); 655e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) 656b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); 657e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg if (info->status.rates[0].idx >= 0 && 658e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) 659e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg rthdr->rate = sband->bitrates[ 660e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg info->status.rates[0].idx].bitrate / 5; 661b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 662e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg /* for now report the total retry_count */ 663e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg rthdr->data_retries = retry_count; 664b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 6653d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu /* XXX: is this sufficient for BPF? */ 6663d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb_set_mac_header(skb, 0); 6673d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb->ip_summed = CHECKSUM_UNNECESSARY; 6683d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb->pkt_type = PACKET_OTHERHOST; 6693d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb->protocol = htons(ETH_P_802_2); 6703d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu memset(skb->cb, 0, sizeof(skb->cb)); 6713d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 67279010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg rcu_read_lock(); 67379010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg list_for_each_entry_rcu(sdata, &local->interfaces, list) { 67405c914fe330fa8e1cc67870dc0d3809dfd96c107Johannes Berg if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { 675b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg if (!netif_running(sdata->dev)) 676b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg continue; 6773d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 6783d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (prev_dev) { 67979010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg skb2 = skb_clone(skb, GFP_ATOMIC); 6803d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (skb2) { 6813d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb2->dev = prev_dev; 6823d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu netif_rx(skb2); 6833d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 6843d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 6853d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 6863d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu prev_dev = sdata->dev; 687b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg } 688b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg } 6893d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (prev_dev) { 6903d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb->dev = prev_dev; 6913d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu netif_rx(skb); 6923d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb = NULL; 6933d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 69479010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg rcu_read_unlock(); 6953d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu dev_kfree_skb(skb); 696f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 697f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_tx_status); 698f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 699f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstruct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, 700f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc const struct ieee80211_ops *ops) 701f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 702f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local; 70396f5e66e8a79810e2982cdcfa28e554f3d97da21Johannes Berg int priv_size, i; 704f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct wiphy *wiphy; 705f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 706f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* Ensure 32-byte alignment of our private data and hw private data. 707f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * We use the wiphy priv data for both our ieee80211_local and for 708f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * the driver's private data 709f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * 710f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * In memory it'll be like this: 711f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * 712f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * +-------------------------+ 713f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * | struct wiphy | 714f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * +-------------------------+ 715f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * | struct ieee80211_local | 716f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * +-------------------------+ 717f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * | driver's private data | 718f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * +-------------------------+ 719f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * 720f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc */ 721f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc priv_size = ((sizeof(struct ieee80211_local) + 722f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) + 723f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc priv_data_len; 724f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 725f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy = wiphy_new(&mac80211_config_ops, priv_size); 726f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 727f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (!wiphy) 728f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return NULL; 729f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 730f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy->privid = mac80211_wiphy_privid; 7312a5193119269062608582418deba7af82844159aJohannes Berg wiphy->max_scan_ssids = 4; 73200d3f14cf9f12c21428121026a5e1d5f65926447Johannes Berg /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ 73300d3f14cf9f12c21428121026a5e1d5f65926447Johannes Berg wiphy->bss_priv_size = sizeof(struct ieee80211_bss) - 73400d3f14cf9f12c21428121026a5e1d5f65926447Johannes Berg sizeof(struct cfg80211_bss); 735f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 736f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local = wiphy_priv(wiphy); 737f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.wiphy = wiphy; 738f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 739f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.priv = (char *)local + 740f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ((sizeof(struct ieee80211_local) + 741f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); 742f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 7434480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg BUG_ON(!ops->tx); 7444150c57212ad134765dd78c654a4b9906252b66dJohannes Berg BUG_ON(!ops->start); 7454150c57212ad134765dd78c654a4b9906252b66dJohannes Berg BUG_ON(!ops->stop); 7464480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg BUG_ON(!ops->config); 7474480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg BUG_ON(!ops->add_interface); 7484150c57212ad134765dd78c654a4b9906252b66dJohannes Berg BUG_ON(!ops->remove_interface); 7494150c57212ad134765dd78c654a4b9906252b66dJohannes Berg BUG_ON(!ops->configure_filter); 750f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->ops = ops; 751f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 752e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg /* set up some defaults */ 753e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg local->hw.queues = 1; 754e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg local->hw.max_rates = 1; 755f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; 756f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; 7579124b07740c51cbc6e358dd0c4abc6ee8ded084dJohannes Berg local->hw.conf.long_frame_max_tx_count = 4; 7589124b07740c51cbc6e358dd0c4abc6ee8ded084dJohannes Berg local->hw.conf.short_frame_max_tx_count = 7; 759e8975581f63870be42ff4662b293d1b0c8c21350Johannes Berg local->hw.conf.radio_enabled = true; 760f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 76179010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg INIT_LIST_HEAD(&local->interfaces); 762c771c9d8da1e8292ef8bf7fd4ce135dacc650130Johannes Berg mutex_init(&local->iflist_mtx); 763f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 764b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg spin_lock_init(&local->key_lock); 765b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg 766ce7c9111a97492d04c504f40736a669c235d664aKalle Valo spin_lock_init(&local->queue_stop_reason_lock); 767ce7c9111a97492d04c504f40736a669c235d664aKalle Valo 768c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); 769f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 770520eb82076993b7f55ef9b80771d264272e5127bKalle Valo INIT_WORK(&local->dynamic_ps_enable_work, 771520eb82076993b7f55ef9b80771d264272e5127bKalle Valo ieee80211_dynamic_ps_enable_work); 772520eb82076993b7f55ef9b80771d264272e5127bKalle Valo INIT_WORK(&local->dynamic_ps_disable_work, 773520eb82076993b7f55ef9b80771d264272e5127bKalle Valo ieee80211_dynamic_ps_disable_work); 774520eb82076993b7f55ef9b80771d264272e5127bKalle Valo setup_timer(&local->dynamic_ps_timer, 775520eb82076993b7f55ef9b80771d264272e5127bKalle Valo ieee80211_dynamic_ps_timer, (unsigned long) local); 776520eb82076993b7f55ef9b80771d264272e5127bKalle Valo 77796f5e66e8a79810e2982cdcfa28e554f3d97da21Johannes Berg for (i = 0; i < IEEE80211_MAX_AMPDU_QUEUES; i++) 77896f5e66e8a79810e2982cdcfa28e554f3d97da21Johannes Berg local->ampdu_ac_queue[i] = -1; 77996f5e66e8a79810e2982cdcfa28e554f3d97da21Johannes Berg /* using an s8 won't work with more than that */ 78096f5e66e8a79810e2982cdcfa28e554f3d97da21Johannes Berg BUILD_BUG_ON(IEEE80211_MAX_AMPDU_QUEUES > 127); 78196f5e66e8a79810e2982cdcfa28e554f3d97da21Johannes Berg 782f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta_info_init(local); 783f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 7842a577d98712a284a612dd51d69db5cb989810dc2Johannes Berg for (i = 0; i < IEEE80211_MAX_QUEUES; i++) 7852a577d98712a284a612dd51d69db5cb989810dc2Johannes Berg skb_queue_head_init(&local->pending[i]); 786f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, 787f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc (unsigned long)local); 788f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_disable(&local->tx_pending_tasklet); 789f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 790f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_init(&local->tasklet, 791f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_tasklet_handler, 792f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc (unsigned long) local); 793f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_disable(&local->tasklet); 794f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 795f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_head_init(&local->skb_queue); 796f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_head_init(&local->skb_queue_unreliable); 797f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 798f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return local_to_hw(local); 799f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 800f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_alloc_hw); 801f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 8027230645e329b4a9c566fefa9327eb8734c7d392cJohannes Bergstatic const struct net_device_ops ieee80211_master_ops = { 8037230645e329b4a9c566fefa9327eb8734c7d392cJohannes Berg .ndo_start_xmit = ieee80211_master_start_xmit, 8047230645e329b4a9c566fefa9327eb8734c7d392cJohannes Berg .ndo_open = ieee80211_master_open, 8057230645e329b4a9c566fefa9327eb8734c7d392cJohannes Berg .ndo_stop = ieee80211_master_stop, 8067230645e329b4a9c566fefa9327eb8734c7d392cJohannes Berg .ndo_set_multicast_list = ieee80211_master_set_multicast_list, 8077230645e329b4a9c566fefa9327eb8734c7d392cJohannes Berg .ndo_select_queue = ieee80211_select_queue, 8087230645e329b4a9c566fefa9327eb8734c7d392cJohannes Berg}; 8097230645e329b4a9c566fefa9327eb8734c7d392cJohannes Berg 8107230645e329b4a9c566fefa9327eb8734c7d392cJohannes Bergstatic void ieee80211_master_setup(struct net_device *mdev) 8117230645e329b4a9c566fefa9327eb8734c7d392cJohannes Berg{ 8127230645e329b4a9c566fefa9327eb8734c7d392cJohannes Berg mdev->type = ARPHRD_IEEE80211; 8137230645e329b4a9c566fefa9327eb8734c7d392cJohannes Berg mdev->netdev_ops = &ieee80211_master_ops; 8147230645e329b4a9c566fefa9327eb8734c7d392cJohannes Berg mdev->header_ops = &ieee80211_header_ops; 8157230645e329b4a9c566fefa9327eb8734c7d392cJohannes Berg mdev->tx_queue_len = 1000; 8167230645e329b4a9c566fefa9327eb8734c7d392cJohannes Berg mdev->addr_len = ETH_ALEN; 8177230645e329b4a9c566fefa9327eb8734c7d392cJohannes Berg} 8187230645e329b4a9c566fefa9327eb8734c7d392cJohannes Berg 819f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencint ieee80211_register_hw(struct ieee80211_hw *hw) 820f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 821f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 822f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc int result; 8238318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg enum ieee80211_band band; 82496d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg struct net_device *mdev; 825133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg struct ieee80211_master_priv *mpriv; 8262a5193119269062608582418deba7af82844159aJohannes Berg int channels, i, j; 8278318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 8288318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg /* 8298318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg * generic code guarantees at least one band, 8308318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg * set this very early because much code assumes 8318318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg * that hw.conf.channel is assigned 8328318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg */ 8332a5193119269062608582418deba7af82844159aJohannes Berg channels = 0; 8348318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 8358318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg struct ieee80211_supported_band *sband; 8368318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 8378318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg sband = local->hw.wiphy->bands[band]; 8382a5193119269062608582418deba7af82844159aJohannes Berg if (sband && !local->oper_channel) { 8398318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg /* init channel we're on */ 8408318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.channel = 8418318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->oper_channel = 8428318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->scan_channel = &sband->channels[0]; 8438318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg } 8442a5193119269062608582418deba7af82844159aJohannes Berg if (sband) 8452a5193119269062608582418deba7af82844159aJohannes Berg channels += sband->n_channels; 8468318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg } 847f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 8482a5193119269062608582418deba7af82844159aJohannes Berg local->int_scan_req.n_channels = channels; 8492a5193119269062608582418deba7af82844159aJohannes Berg local->int_scan_req.channels = kzalloc(sizeof(void *) * channels, GFP_KERNEL); 8502a5193119269062608582418deba7af82844159aJohannes Berg if (!local->int_scan_req.channels) 8512a5193119269062608582418deba7af82844159aJohannes Berg return -ENOMEM; 8522a5193119269062608582418deba7af82844159aJohannes Berg 853f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez /* if low-level driver supports AP, we also support VLAN */ 854f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) 855f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); 856f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez 857f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez /* mac80211 always supports monitor */ 858f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); 859f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez 86077965c970d7da9c9b6349ff2b1d9adecf54c403bJohannes Berg if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) 86177965c970d7da9c9b6349ff2b1d9adecf54c403bJohannes Berg local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; 86277965c970d7da9c9b6349ff2b1d9adecf54c403bJohannes Berg else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) 86377965c970d7da9c9b6349ff2b1d9adecf54c403bJohannes Berg local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; 86477965c970d7da9c9b6349ff2b1d9adecf54c403bJohannes Berg 865f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = wiphy_register(local->hw.wiphy); 866f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) 8672a5193119269062608582418deba7af82844159aJohannes Berg goto fail_wiphy_register; 868f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 869e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg /* 870e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg * We use the number of queues for feature tests (QoS, HT) internally 871e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg * so restrict them appropriately. 872e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg */ 873e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg if (hw->queues > IEEE80211_MAX_QUEUES) 874e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg hw->queues = IEEE80211_MAX_QUEUES; 875e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES) 876e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES; 877e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg if (hw->queues < 4) 878e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg hw->ampdu_queues = 0; 879e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg 880133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), 8817230645e329b4a9c566fefa9327eb8734c7d392cJohannes Berg "wmaster%d", ieee80211_master_setup, 88296f5e66e8a79810e2982cdcfa28e554f3d97da21Johannes Berg hw->queues); 88396d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg if (!mdev) 88496d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg goto fail_mdev_alloc; 88596d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 886133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg mpriv = netdev_priv(mdev); 887133b822638ff01eb1e32e1917b197c40ed095dddJohannes Berg mpriv->local = local; 88896d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg local->mdev = mdev; 88996d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 8904ada424db196c78746fec255d493cacb1c9feddfLuis R. Rodriguez local->hw.workqueue = 89130d3ef41b4395d9bee5f481395eef2d3b8b6ee50Bob Copeland create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); 892f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (!local->hw.workqueue) { 893f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = -ENOMEM; 894f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_workqueue; 895f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 896f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 897b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg /* 898b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg * The hardware needs headroom for sending the frame, 899b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg * and we need some headroom for passing the frame to monitor 900b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg * interfaces, but never both at the same time. 901b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg */ 90233ccad35a21df51c0d23f3e3e88688524e7b51edJiri Benc local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom, 90333ccad35a21df51c0d23f3e3e88688524e7b51edJiri Benc sizeof(struct ieee80211_tx_status_rtap_hdr)); 904b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 905e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc debugfs_hw_add(local); 906e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 907dc0ae30c31ee6ef83992bb692f37dfbba08a2ef6Tomas Winkler if (local->hw.conf.beacon_int < 10) 908dc0ae30c31ee6ef83992bb692f37dfbba08a2ef6Tomas Winkler local->hw.conf.beacon_int = 100; 909f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 910ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler if (local->hw.max_listen_interval == 0) 911ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler local->hw.max_listen_interval = 1; 912ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler 913ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler local->hw.conf.listen_interval = local->hw.max_listen_interval; 914ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler 915f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = sta_info_start(local); 916f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) 917f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_sta_info; 918f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 919f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_lock(); 920f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = dev_alloc_name(local->mdev, local->mdev->name); 921f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) 922f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_dev; 923f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 924f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); 925f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy)); 926076ae609d20901b5fd9bc19fc4c245624c423970Johannes Berg local->mdev->features |= NETIF_F_NETNS_LOCAL; 927f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 928f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = register_netdevice(local->mdev); 929f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) 930f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_dev; 931f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 932830f903866a1611e9ce53f3e35202302bb938946Johannes Berg result = ieee80211_init_rate_ctrl_alg(local, 933830f903866a1611e9ce53f3e35202302bb938946Johannes Berg hw->rate_control_algorithm); 934f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) { 935f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_DEBUG "%s: Failed to initialize rate control " 936dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg "algorithm\n", wiphy_name(local->hw.wiphy)); 937f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_rate; 938f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 939f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 940f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = ieee80211_wep_init(local); 941f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 942f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) { 943023a04bebe7030c1e6d5347bd3f27a3e49a1f222Jeremy Fitzhardinge printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n", 944023a04bebe7030c1e6d5347bd3f27a3e49a1f222Jeremy Fitzhardinge wiphy_name(local->hw.wiphy), result); 945f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_wep; 946f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 947f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 9488dffff216fcac4f79078478085e86d68db64922eJohannes Berg /* add one default STA interface if supported */ 9498dffff216fcac4f79078478085e86d68db64922eJohannes Berg if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) { 9508dffff216fcac4f79078478085e86d68db64922eJohannes Berg result = ieee80211_if_add(local, "wlan%d", NULL, 9518dffff216fcac4f79078478085e86d68db64922eJohannes Berg NL80211_IFTYPE_STATION, NULL); 9528dffff216fcac4f79078478085e86d68db64922eJohannes Berg if (result) 9538dffff216fcac4f79078478085e86d68db64922eJohannes Berg printk(KERN_WARNING "%s: Failed to add default virtual iface\n", 9548dffff216fcac4f79078478085e86d68db64922eJohannes Berg wiphy_name(local->hw.wiphy)); 9558dffff216fcac4f79078478085e86d68db64922eJohannes Berg } 956f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 957f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_unlock(); 958f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 959f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_led_init(local); 960f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 9612a5193119269062608582418deba7af82844159aJohannes Berg /* alloc internal scan request */ 9622a5193119269062608582418deba7af82844159aJohannes Berg i = 0; 9632a5193119269062608582418deba7af82844159aJohannes Berg local->int_scan_req.ssids = &local->scan_ssid; 9642a5193119269062608582418deba7af82844159aJohannes Berg local->int_scan_req.n_ssids = 1; 9652a5193119269062608582418deba7af82844159aJohannes Berg for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 9662a5193119269062608582418deba7af82844159aJohannes Berg if (!hw->wiphy->bands[band]) 9672a5193119269062608582418deba7af82844159aJohannes Berg continue; 9682a5193119269062608582418deba7af82844159aJohannes Berg for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) { 9692a5193119269062608582418deba7af82844159aJohannes Berg local->int_scan_req.channels[i] = 9702a5193119269062608582418deba7af82844159aJohannes Berg &hw->wiphy->bands[band]->channels[j]; 9712a5193119269062608582418deba7af82844159aJohannes Berg i++; 9722a5193119269062608582418deba7af82844159aJohannes Berg } 9732a5193119269062608582418deba7af82844159aJohannes Berg } 9742a5193119269062608582418deba7af82844159aJohannes Berg 975f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 976f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 977f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_wep: 978f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rate_control_deinitialize(local); 979f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_rate: 980f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc unregister_netdevice(local->mdev); 981339a7c41c913035bf58579f6e47b4ba29da83795Pavel Emelyanov local->mdev = NULL; 982f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_dev: 983f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_unlock(); 984f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta_info_stop(local); 985f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_sta_info: 986e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc debugfs_hw_del(local); 987f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc destroy_workqueue(local->hw.workqueue); 988f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_workqueue: 9893e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg if (local->mdev) 9903e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg free_netdev(local->mdev); 99196d510566e4908f77f03ff1436c78ae7162a17d0Johannes Bergfail_mdev_alloc: 992f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy_unregister(local->hw.wiphy); 9932a5193119269062608582418deba7af82844159aJohannes Bergfail_wiphy_register: 9942a5193119269062608582418deba7af82844159aJohannes Berg kfree(local->int_scan_req.channels); 995f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return result; 996f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 997f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_register_hw); 998f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 999f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_unregister_hw(struct ieee80211_hw *hw) 1000f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1001f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 1002f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1003f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_kill(&local->tx_pending_tasklet); 1004f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_kill(&local->tasklet); 1005f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1006f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_lock(); 1007f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 100879010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg /* 100979010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * At this point, interface list manipulations are fine 101079010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * because the driver cannot be handing us frames any 101179010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * more and the tasklet is killed. 101279010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg */ 10135b2812e925c8e976852867f8d760637c5926d817Johannes Berg 101475636525fbfa78fa33fd754c89785cfde750acd3Johannes Berg /* First, we remove all virtual interfaces. */ 101575636525fbfa78fa33fd754c89785cfde750acd3Johannes Berg ieee80211_remove_interfaces(local); 10165b2812e925c8e976852867f8d760637c5926d817Johannes Berg 10175b2812e925c8e976852867f8d760637c5926d817Johannes Berg /* then, finally, remove the master interface */ 10183e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg unregister_netdevice(local->mdev); 1019f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1020f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_unlock(); 1021f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1022f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_clear_tx_pending(local); 1023f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta_info_stop(local); 1024f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rate_control_deinitialize(local); 1025e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc debugfs_hw_del(local); 1026f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1027f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (skb_queue_len(&local->skb_queue) 1028f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc || skb_queue_len(&local->skb_queue_unreliable)) 1029f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_WARNING "%s: skb_queue not empty\n", 1030dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg wiphy_name(local->hw.wiphy)); 1031f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_purge(&local->skb_queue); 1032f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_purge(&local->skb_queue_unreliable); 1033f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1034f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc destroy_workqueue(local->hw.workqueue); 1035f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy_unregister(local->hw.wiphy); 1036f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_wep_free(local); 1037f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_led_exit(local); 10383e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg free_netdev(local->mdev); 10392a5193119269062608582418deba7af82844159aJohannes Berg kfree(local->int_scan_req.channels); 1040f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1041f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_unregister_hw); 1042f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1043f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_free_hw(struct ieee80211_hw *hw) 1044f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1045f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 1046f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1047c771c9d8da1e8292ef8bf7fd4ce135dacc650130Johannes Berg mutex_destroy(&local->iflist_mtx); 1048c771c9d8da1e8292ef8bf7fd4ce135dacc650130Johannes Berg 1049f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy_free(local->hw.wiphy); 1050f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1051f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_free_hw); 1052f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1053f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic int __init ieee80211_init(void) 1054f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1055f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sk_buff *skb; 1056f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc int ret; 1057f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1058e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg BUILD_BUG_ON(sizeof(struct ieee80211_tx_info) > sizeof(skb->cb)); 1059e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) + 1060c6a1fa12d206882757264869f8e32d606b930e2aJohannes Berg IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb)); 1061f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1062cccf129f820e431d84690729254a32f1709328fbFelix Fietkau ret = rc80211_minstrel_init(); 1063cccf129f820e431d84690729254a32f1709328fbFelix Fietkau if (ret) 1064cccf129f820e431d84690729254a32f1709328fbFelix Fietkau return ret; 1065cccf129f820e431d84690729254a32f1709328fbFelix Fietkau 10664b475898ec9dc6e62cebcb8fc0b3495c986a4590Johannes Berg ret = rc80211_pid_init(); 1067ad01837593338f13508463fa11c8dbf8109a1e5dMattias Nissler if (ret) 106851cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller return ret; 1069f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1070e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc ieee80211_debugfs_netdev_init(); 1071e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 1072f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 1073f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1074f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1075f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void __exit ieee80211_exit(void) 1076f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 10774b475898ec9dc6e62cebcb8fc0b3495c986a4590Johannes Berg rc80211_pid_exit(); 1078cccf129f820e431d84690729254a32f1709328fbFelix Fietkau rc80211_minstrel_exit(); 1079ac71c691e6a5ce991fe221d3bdb0c972f617aa37Johannes Berg 10803b96766f0e643f52ae19e134664df6730c737e87Johannes Berg /* 10813b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * For key todo, it'll be empty by now but the work 10823b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * might still be scheduled. 10833b96766f0e643f52ae19e134664df6730c737e87Johannes Berg */ 10843b96766f0e643f52ae19e134664df6730c737e87Johannes Berg flush_scheduled_work(); 10853b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 1086f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo if (mesh_allocated) 1087f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo ieee80211s_stop(); 1088902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg 1089e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc ieee80211_debugfs_netdev_exit(); 1090f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1091f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1092f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1093ca9938fea576ebbb8d8c4fbe8a5bcc937e49e1caJohannes Bergsubsys_initcall(ieee80211_init); 1094f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencmodule_exit(ieee80211_exit); 1095f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1096f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencMODULE_DESCRIPTION("IEEE 802.11 subsystem"); 1097f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencMODULE_LICENSE("GPL"); 1098