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