main.c revision c2b13452b283f9c4a5b02a6b53ed6416ebf4c03c
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; 190bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo u8 null_addr[ETH_ALEN] = {0}; 191f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 192b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1930ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg 194bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo /* fail early if user set an invalid address */ 195bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo if (compare_ether_addr(dev->dev_addr, null_addr) && 196bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo !is_valid_ether_addr(dev->dev_addr)) 197bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo return -EADDRNOTAVAIL; 198bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo 19979010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg /* we hold the RTNL here so can safely walk the list */ 20079010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg list_for_each_entry(nsdata, &local->interfaces, list) { 201b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct net_device *ndev = nsdata->dev; 202e2ebc74d7e3d71600640db6fbb28cc2f362184c1Johannes Berg 2033e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg if (ndev != dev && netif_running(ndev)) { 204665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg /* 205665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * Allow only a single IBSS interface to be up at any 206665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * time. This is restricted because beacon distribution 207665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * cannot work properly if both are in the same IBSS. 208665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * 209665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * To remove this restriction we'd have to disallow them 210665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * from setting the same SSID on different IBSS interfaces 211665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * belonging to the same hardware. Then, however, we're 212665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * faced with having to adopt two different TSF timers... 213665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg */ 214665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && 215665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg nsdata->vif.type == IEEE80211_IF_TYPE_IBSS) 216665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg return -EBUSY; 217665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg 218665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg /* 219665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * The remaining checks are only performed for interfaces 220665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * with the same MAC address. 221665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg */ 222665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg if (compare_ether_addr(dev->dev_addr, ndev->dev_addr)) 223665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg continue; 224665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg 2250ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg /* 2260ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg * check whether it may have the same address 2270ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg */ 22851fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (!identical_mac_addr_allowed(sdata->vif.type, 22951fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg nsdata->vif.type)) 2300ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg return -ENOTUNIQ; 2310ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg 2320ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg /* 2330ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg * can only add VLANs to enabled APs 2340ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg */ 23551fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN && 236665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg nsdata->vif.type == IEEE80211_IF_TYPE_AP) 2373e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg sdata->bss = &nsdata->u.ap; 238b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 239b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 240f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 24151fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg switch (sdata->vif.type) { 2420ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg case IEEE80211_IF_TYPE_WDS: 243e94e106831403d5028e7bb73c3163951134de1baJohannes Berg if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) 2440ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg return -ENOLINK; 2450ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg break; 2460ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg case IEEE80211_IF_TYPE_VLAN: 2473e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg if (!sdata->bss) 2480ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg return -ENOLINK; 2493e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg list_add(&sdata->u.vlan.list, &sdata->bss->vlans); 2500ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg break; 251fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg case IEEE80211_IF_TYPE_AP: 2523e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg sdata->bss = &sdata->u.ap; 2533e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg break; 2548dbc1722a78343eb80f0ce1a3ef1965a9774ad5bLuis Carlos Cobo case IEEE80211_IF_TYPE_MESH_POINT: 255472dbc45dc1966284de72d7de15690c17ed2cf33Johannes Berg if (!ieee80211_vif_is_mesh(&sdata->vif)) 256472dbc45dc1966284de72d7de15690c17ed2cf33Johannes Berg break; 2578dbc1722a78343eb80f0ce1a3ef1965a9774ad5bLuis Carlos Cobo /* mesh ifaces must set allmulti to forward mcast traffic */ 2588dbc1722a78343eb80f0ce1a3ef1965a9774ad5bLuis Carlos Cobo atomic_inc(&local->iff_allmultis); 2598dbc1722a78343eb80f0ce1a3ef1965a9774ad5bLuis Carlos Cobo break; 260fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg case IEEE80211_IF_TYPE_STA: 261fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg case IEEE80211_IF_TYPE_MNTR: 262fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg case IEEE80211_IF_TYPE_IBSS: 263fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg /* no special treatment */ 264fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg break; 265a28975525016ddcbdaab8225666df1cf2dc9cb2dJohannes Berg case IEEE80211_IF_TYPE_INVALID: 266a28975525016ddcbdaab8225666df1cf2dc9cb2dJohannes Berg /* cannot happen */ 267a28975525016ddcbdaab8225666df1cf2dc9cb2dJohannes Berg WARN_ON(1); 268a28975525016ddcbdaab8225666df1cf2dc9cb2dJohannes Berg break; 2690ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg } 270f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 271b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (local->open_count == 0) { 272b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg res = 0; 2734150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (local->ops->start) 2744150c57212ad134765dd78c654a4b9906252b66dJohannes Berg res = local->ops->start(local_to_hw(local)); 2754150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (res) 2763e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg goto err_del_bss; 277ceffefd15aac78841432230627308b8a382dbcfcMichael Buesch need_hw_reconfig = 1; 278cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn ieee80211_led_radio(local, local->hw.conf.radio_enabled); 279b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 280f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 281bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo /* 282bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo * Check all interfaces and copy the hopefully now-present 283bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo * MAC address to those that have the special null one. 284bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo */ 285bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo list_for_each_entry(nsdata, &local->interfaces, list) { 286bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo struct net_device *ndev = nsdata->dev; 287bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo 288bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo /* 289bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo * No need to check netif_running since we do not allow 290bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo * it to start up with this invalid address. 291bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo */ 292bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) 293bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo memcpy(ndev->dev_addr, 294bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo local->hw.wiphy->perm_addr, 295bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo ETH_ALEN); 296bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo } 297bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo 298bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo if (compare_ether_addr(null_addr, local->mdev->dev_addr) == 0) 299bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, 300bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo ETH_ALEN); 301bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo 302bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo /* 303bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo * Validate the MAC address for this device. 304bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo */ 305bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo if (!is_valid_ether_addr(dev->dev_addr)) { 306bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo if (!local->open_count && local->ops->stop) 307bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo local->ops->stop(local_to_hw(local)); 308bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo return -EADDRNOTAVAIL; 309bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo } 310bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo 31151fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg switch (sdata->vif.type) { 3120ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg case IEEE80211_IF_TYPE_VLAN: 3130ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg /* no need to tell driver */ 3140ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg break; 3154150c57212ad134765dd78c654a4b9906252b66dJohannes Berg case IEEE80211_IF_TYPE_MNTR: 3163d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { 3173d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu local->cooked_mntrs++; 3183d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu break; 3193d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 3203d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 3214150c57212ad134765dd78c654a4b9906252b66dJohannes Berg /* must be before the call to ieee80211_configure_filter */ 322b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg local->monitors++; 3238cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (local->monitors == 1) 3244150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; 3258cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 3268cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) 3278cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_fcsfail++; 3288cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) 3298cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_plcpfail++; 3308cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) 3318cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_control++; 3328cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) 3338cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_other_bss++; 3348cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 335b9e40857682ecfc5bcd0356a23ff409883ffb982David S. Miller netif_addr_lock_bh(local->mdev); 3368cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu ieee80211_configure_filter(local); 337b9e40857682ecfc5bcd0356a23ff409883ffb982David S. Miller netif_addr_unlock_bh(local->mdev); 3384150c57212ad134765dd78c654a4b9906252b66dJohannes Berg break; 3394150c57212ad134765dd78c654a4b9906252b66dJohannes Berg case IEEE80211_IF_TYPE_STA: 3404150c57212ad134765dd78c654a4b9906252b66dJohannes Berg case IEEE80211_IF_TYPE_IBSS: 3414150c57212ad134765dd78c654a4b9906252b66dJohannes Berg sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET; 3424150c57212ad134765dd78c654a4b9906252b66dJohannes Berg /* fall through */ 3434150c57212ad134765dd78c654a4b9906252b66dJohannes Berg default: 34432bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg conf.vif = &sdata->vif; 34551fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg conf.type = sdata->vif.type; 3464150c57212ad134765dd78c654a4b9906252b66dJohannes Berg conf.mac_addr = dev->dev_addr; 3474150c57212ad134765dd78c654a4b9906252b66dJohannes Berg res = local->ops->add_interface(local_to_hw(local), &conf); 3484150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (res) 349636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg goto err_stop; 3504150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 3519d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg if (ieee80211_vif_is_mesh(&sdata->vif)) 352f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greene ieee80211_start_mesh(sdata); 353f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greene changed |= ieee80211_reset_erp_info(sdata); 354fc32f9243dc93e75f81457e95d9cb90ee6136d94Tomas Winkler ieee80211_bss_info_change_notify(sdata, changed); 35511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg ieee80211_enable_keys(sdata); 3564150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 35751fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_STA && 358ddd3d2be85e3207c47f2b3c431723e6c758b4b0dJohannes Berg !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) 3594150c57212ad134765dd78c654a4b9906252b66dJohannes Berg netif_carrier_off(dev); 3604150c57212ad134765dd78c654a4b9906252b66dJohannes Berg else 3614150c57212ad134765dd78c654a4b9906252b66dJohannes Berg netif_carrier_on(dev); 362d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake } 363f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 364636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) { 365636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg /* Create STA entry for the WDS peer */ 366636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, 367636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg GFP_KERNEL); 368636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg if (!sta) { 369636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg res = -ENOMEM; 370636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg goto err_del_interface; 371636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg } 372636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg 37307346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg /* no locking required since STA is not live yet */ 374636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg sta->flags |= WLAN_STA_AUTHORIZED; 375636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg 376636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg res = sta_info_insert(sta); 377636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg if (res) { 378636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg /* STA has been freed */ 379636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg goto err_del_interface; 380636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg } 381636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg } 382636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg 3834150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (local->open_count == 0) { 3844150c57212ad134765dd78c654a4b9906252b66dJohannes Berg res = dev_open(local->mdev); 3854150c57212ad134765dd78c654a4b9906252b66dJohannes Berg WARN_ON(res); 386636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg if (res) 387636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg goto err_del_interface; 3884150c57212ad134765dd78c654a4b9906252b66dJohannes Berg tasklet_enable(&local->tx_pending_tasklet); 3894150c57212ad134765dd78c654a4b9906252b66dJohannes Berg tasklet_enable(&local->tasklet); 3904150c57212ad134765dd78c654a4b9906252b66dJohannes Berg } 3914150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 392c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg /* 393c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * set_multicast_list will be invoked by the networking core 394c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * which will check whether any increments here were done in 395c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * error and sync them down to the hardware as filter flags. 396c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg */ 397c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg if (sdata->flags & IEEE80211_SDATA_ALLMULTI) 398c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg atomic_inc(&local->iff_allmultis); 399c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg 400c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg if (sdata->flags & IEEE80211_SDATA_PROMISC) 401c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg atomic_inc(&local->iff_promiscs); 402c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg 4034150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->open_count++; 4045825fe100d654fff89aa67a1e202af1f8a7f0ad0Johannes Berg if (need_hw_reconfig) { 405ceffefd15aac78841432230627308b8a382dbcfcMichael Buesch ieee80211_hw_config(local); 4065825fe100d654fff89aa67a1e202af1f8a7f0ad0Johannes Berg /* 4075825fe100d654fff89aa67a1e202af1f8a7f0ad0Johannes Berg * set default queue parameters so drivers don't 4085825fe100d654fff89aa67a1e202af1f8a7f0ad0Johannes Berg * need to initialise the hardware if the hardware 4095825fe100d654fff89aa67a1e202af1f8a7f0ad0Johannes Berg * doesn't start up with sane defaults 4105825fe100d654fff89aa67a1e202af1f8a7f0ad0Johannes Berg */ 4115825fe100d654fff89aa67a1e202af1f8a7f0ad0Johannes Berg ieee80211_set_wmm_default(sdata); 4125825fe100d654fff89aa67a1e202af1f8a7f0ad0Johannes Berg } 413f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 41464f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann /* 41564f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann * ieee80211_sta_work is disabled while network interface 41664f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann * is down. Therefore, some configuration changes may not 41764f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann * yet be effective. Trigger execution of ieee80211_sta_work 41864f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann * to fix this. 41964f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann */ 420988c0f723d0b1abb399e6e71d8bf3f8bf1949a70Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_STA || 421988c0f723d0b1abb399e6e71d8bf3f8bf1949a70Johannes Berg sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { 42264f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann struct ieee80211_if_sta *ifsta = &sdata->u.sta; 42364f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann queue_work(local->hw.workqueue, &ifsta->work); 42464f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann } 42564f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann 42651cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller netif_tx_start_all_queues(dev); 4274150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 428b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return 0; 429636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg err_del_interface: 430636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg local->ops->remove_interface(local_to_hw(local), &conf); 431636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg err_stop: 432636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg if (!local->open_count && local->ops->stop) 433636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg local->ops->stop(local_to_hw(local)); 4343e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg err_del_bss: 4353e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg sdata->bss = NULL; 4363e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) 4373e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg list_del(&sdata->u.vlan.list); 438636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg return res; 439f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 440f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 4414150c57212ad134765dd78c654a4b9906252b66dJohannes Bergstatic int ieee80211_stop(struct net_device *dev) 442f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 44344213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 44444213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg struct ieee80211_local *local = sdata->local; 4454150c57212ad134765dd78c654a4b9906252b66dJohannes Berg struct ieee80211_if_init_conf conf; 44607db218396650933abff3c5c1ad1e2a6e0cfedebRon Rindjunsky struct sta_info *sta; 4474150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 44844213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg /* 44944213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * Stop TX on this interface first. 45044213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg */ 45151cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller netif_tx_stop_all_queues(dev); 4524150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 45344213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg /* 45444213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * Now delete all active aggregation sessions. 45544213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg */ 456d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_lock(); 457d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg 458d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg list_for_each_entry_rcu(sta, &local->sta_list, list) { 459d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg if (sta->sdata == sdata) 460f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greene ieee80211_sta_tear_down_BA_sessions(sdata, sta->addr); 46107db218396650933abff3c5c1ad1e2a6e0cfedebRon Rindjunsky } 46207db218396650933abff3c5c1ad1e2a6e0cfedebRon Rindjunsky 463d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 464d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg 46544213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg /* 46644213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * Remove all stations associated with this interface. 46744213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * 46844213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * This must be done before calling ops->remove_interface() 46944213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * because otherwise we can later invoke ops->sta_notify() 47044213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * whenever the STAs are removed, and that invalidates driver 47144213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * assumptions about always getting a vif pointer that is valid 47244213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * (because if we remove a STA after ops->remove_interface() 47344213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * the driver will have removed the vif info already!) 47444213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * 47544213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * We could relax this and only unlink the stations from the 47644213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * hash table and list but keep them on a per-sdata list that 47744213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * will be inserted back again when the interface is brought 47844213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * up again, but I don't currently see a use case for that, 47944213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * except with WDS which gets a STA entry created when it is 48044213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * brought up. 48144213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg */ 48244213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg sta_info_flush(local, sdata); 4834150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 484c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg /* 485c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * Don't count this interface for promisc/allmulti while it 486c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * is down. dev_mc_unsync() will invoke set_multicast_list 487c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * on the master interface which will sync these down to the 488c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * hardware as filter flags. 489c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg */ 490c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg if (sdata->flags & IEEE80211_SDATA_ALLMULTI) 491c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg atomic_dec(&local->iff_allmultis); 492c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg 493c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg if (sdata->flags & IEEE80211_SDATA_PROMISC) 494c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg atomic_dec(&local->iff_promiscs); 495c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg 4964150c57212ad134765dd78c654a4b9906252b66dJohannes Berg dev_mc_unsync(local->mdev, dev); 4974150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 4985dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg /* APs need special treatment */ 49951fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { 5000ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg struct ieee80211_sub_if_data *vlan, *tmp; 5015dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg struct beacon_data *old_beacon = sdata->u.ap.beacon; 5020ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg 5035dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg /* remove beacon */ 5045dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg rcu_assign_pointer(sdata->u.ap.beacon, NULL); 5055dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg synchronize_rcu(); 5065dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg kfree(old_beacon); 5075dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg 5085dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg /* down all dependent devices, that is VLANs */ 5090ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans, 5100ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg u.vlan.list) 5110ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg dev_close(vlan->dev); 5120ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg WARN_ON(!list_empty(&sdata->u.ap.vlans)); 5130ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg } 5140ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg 5154150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->open_count--; 516f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 51751fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg switch (sdata->vif.type) { 5180ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg case IEEE80211_IF_TYPE_VLAN: 5190ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg list_del(&sdata->u.vlan.list); 5200ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg /* no need to tell driver */ 5210ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg break; 5224150c57212ad134765dd78c654a4b9906252b66dJohannes Berg case IEEE80211_IF_TYPE_MNTR: 5233d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { 5243d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu local->cooked_mntrs--; 5253d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu break; 5263d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 5273d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 5284150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->monitors--; 5298cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (local->monitors == 0) 5308b393f1dc76acbe65a97a4e51f8144f4a65fa1c9Michael Wu local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; 5318cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 5328cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) 5338cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_fcsfail--; 5348cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) 5358cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_plcpfail--; 5368cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) 5378cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_control--; 5388cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) 5398cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_other_bss--; 5408cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 541b9e40857682ecfc5bcd0356a23ff409883ffb982David S. Miller netif_addr_lock_bh(local->mdev); 5428cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu ieee80211_configure_filter(local); 543b9e40857682ecfc5bcd0356a23ff409883ffb982David S. Miller netif_addr_unlock_bh(local->mdev); 5444150c57212ad134765dd78c654a4b9906252b66dJohannes Berg break; 545b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg case IEEE80211_IF_TYPE_STA: 546b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg case IEEE80211_IF_TYPE_IBSS: 54748c2fc59aa415ba92be0ad3a7e741c46883e3944Tomas Winkler sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED; 548ad81b2f97d42e13ef78bb3798e046cd5f0492980Assaf Krauss memset(sdata->u.sta.bssid, 0, ETH_ALEN); 549b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg del_timer_sync(&sdata->u.sta.timer); 5502a8a9a88fc1b18f5c45244d0ef8a5352f6cf761fJohannes Berg /* 551b7413430d4d2a6168e68231d9f93763047b6d60cJohannes Berg * If the timer fired while we waited for it, it will have 552b7413430d4d2a6168e68231d9f93763047b6d60cJohannes Berg * requeued the work. Now the work will be running again 553b7413430d4d2a6168e68231d9f93763047b6d60cJohannes Berg * but will not rearm the timer again because it checks 554b7413430d4d2a6168e68231d9f93763047b6d60cJohannes Berg * whether the interface is running, which, at this point, 555b7413430d4d2a6168e68231d9f93763047b6d60cJohannes Berg * it no longer is. 556b7413430d4d2a6168e68231d9f93763047b6d60cJohannes Berg */ 557b7413430d4d2a6168e68231d9f93763047b6d60cJohannes Berg cancel_work_sync(&sdata->u.sta.work); 558b7413430d4d2a6168e68231d9f93763047b6d60cJohannes Berg /* 55979010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * When we get here, the interface is marked down. 56079010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * Call synchronize_rcu() to wait for the RX path 56179010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * should it be using the interface and enqueuing 56279010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * frames at this very time on another CPU. 5632a8a9a88fc1b18f5c45244d0ef8a5352f6cf761fJohannes Berg */ 56479010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg synchronize_rcu(); 565b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg skb_queue_purge(&sdata->u.sta.skb_queue); 5662a8a9a88fc1b18f5c45244d0ef8a5352f6cf761fJohannes Berg 567a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; 568a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi kfree(sdata->u.sta.extra_ie); 569a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi sdata->u.sta.extra_ie = NULL; 570a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi sdata->u.sta.extra_ie_len = 0; 5714150c57212ad134765dd78c654a4b9906252b66dJohannes Berg /* fall through */ 572472dbc45dc1966284de72d7de15690c17ed2cf33Johannes Berg case IEEE80211_IF_TYPE_MESH_POINT: 573472dbc45dc1966284de72d7de15690c17ed2cf33Johannes Berg if (ieee80211_vif_is_mesh(&sdata->vif)) { 574472dbc45dc1966284de72d7de15690c17ed2cf33Johannes Berg /* allmulti is always set on mesh ifaces */ 575472dbc45dc1966284de72d7de15690c17ed2cf33Johannes Berg atomic_dec(&local->iff_allmultis); 576472dbc45dc1966284de72d7de15690c17ed2cf33Johannes Berg ieee80211_stop_mesh(sdata); 577472dbc45dc1966284de72d7de15690c17ed2cf33Johannes Berg } 578472dbc45dc1966284de72d7de15690c17ed2cf33Johannes Berg /* fall through */ 5794150c57212ad134765dd78c654a4b9906252b66dJohannes Berg default: 5805bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg if (local->scan_sdata == sdata) { 5815bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg if (!local->ops->hw_scan) 5825bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg cancel_delayed_work_sync(&local->scan_work); 5835bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg /* 5845bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg * The software scan can no longer run now, so we can 5855bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg * clear out the scan_sdata reference. However, the 5865bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg * hardware scan may still be running. The complete 5875bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg * function must be prepared to handle a NULL value. 5885bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg */ 5895bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg local->scan_sdata = NULL; 5905bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg /* 5915bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg * The memory barrier guarantees that another CPU 5925bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg * that is hardware-scanning will now see the fact 5935bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg * that this interface is gone. 5945bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg */ 5955bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg smp_mb(); 5965bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg /* 5975bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg * If software scanning, complete the scan but since 5985bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg * the scan_sdata is NULL already don't send out a 5995bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg * scan event to userspace -- the scan is incomplete. 6005bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg */ 601c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg if (local->sw_scanning) 6025bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg ieee80211_scan_completed(&local->hw); 6035bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg } 6045bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg 60532bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg conf.vif = &sdata->vif; 60651fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg conf.type = sdata->vif.type; 6074150c57212ad134765dd78c654a4b9906252b66dJohannes Berg conf.mac_addr = dev->dev_addr; 60811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg /* disable all keys for as long as this netdev is down */ 60911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg ieee80211_disable_keys(sdata); 6104150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->ops->remove_interface(local_to_hw(local), &conf); 611f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 612f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 6133e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg sdata->bss = NULL; 6143e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg 615b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (local->open_count == 0) { 616b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (netif_running(local->mdev)) 617b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev_close(local->mdev); 6184150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 619b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (local->ops->stop) 620b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg local->ops->stop(local_to_hw(local)); 6214150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 622cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn ieee80211_led_radio(local, 0); 623cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn 624ea0c925370b33baf168bb33782c613468c1aa119Ivo van Doorn flush_workqueue(local->hw.workqueue); 625ea0c925370b33baf168bb33782c613468c1aa119Ivo van Doorn 626b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg tasklet_disable(&local->tx_pending_tasklet); 627b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg tasklet_disable(&local->tasklet); 628b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 629b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg 630f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 631f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 632f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 633f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void ieee80211_set_multicast_list(struct net_device *dev) 634f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 635f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 636f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 6374150c57212ad134765dd78c654a4b9906252b66dJohannes Berg int allmulti, promisc, sdata_allmulti, sdata_promisc; 638f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 6394150c57212ad134765dd78c654a4b9906252b66dJohannes Berg allmulti = !!(dev->flags & IFF_ALLMULTI); 6404150c57212ad134765dd78c654a4b9906252b66dJohannes Berg promisc = !!(dev->flags & IFF_PROMISC); 641b52f2198ac889561d341c6990d669a671f93f450Johannes Berg sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); 642b52f2198ac889561d341c6990d669a671f93f450Johannes Berg sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC); 6434150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 6444150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (allmulti != sdata_allmulti) { 6454150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (dev->flags & IFF_ALLMULTI) 64653918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg atomic_inc(&local->iff_allmultis); 6474150c57212ad134765dd78c654a4b9906252b66dJohannes Berg else 64853918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg atomic_dec(&local->iff_allmultis); 64913262ffd4902805acad2618c12b41fcaa6c50791Jiri Slaby sdata->flags ^= IEEE80211_SDATA_ALLMULTI; 650f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 6514150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 6524150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (promisc != sdata_promisc) { 6534150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (dev->flags & IFF_PROMISC) 65453918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg atomic_inc(&local->iff_promiscs); 6554150c57212ad134765dd78c654a4b9906252b66dJohannes Berg else 65653918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg atomic_dec(&local->iff_promiscs); 65713262ffd4902805acad2618c12b41fcaa6c50791Jiri Slaby sdata->flags ^= IEEE80211_SDATA_PROMISC; 658f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 6594150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 6604150c57212ad134765dd78c654a4b9906252b66dJohannes Berg dev_mc_sync(local->mdev, dev); 661f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 662f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 6633b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemmingerstatic const struct header_ops ieee80211_header_ops = { 6643b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger .create = eth_header, 6653b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger .parse = header_parse_80211, 6663b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger .rebuild = eth_rebuild_header, 6673b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger .cache = eth_header_cache, 6683b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger .cache_update = eth_header_cache_update, 6693b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger}; 6703b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger 671b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergvoid ieee80211_if_setup(struct net_device *dev) 672f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 673b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg ether_setup(dev); 674b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->hard_start_xmit = ieee80211_subif_start_xmit; 675b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->wireless_handlers = &ieee80211_iw_handler_def; 676b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->set_multicast_list = ieee80211_set_multicast_list; 677b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->change_mtu = ieee80211_change_mtu; 678b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->open = ieee80211_open; 679b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->stop = ieee80211_stop; 68075636525fbfa78fa33fd754c89785cfde750acd3Johannes Berg dev->destructor = free_netdev; 681bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo /* we will validate the address ourselves in ->open */ 682bdbe819540f3365249095692118dbfeee308140dLuis Carlos Cobo dev->validate_addr = NULL; 683b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 684f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 685b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg/* everything else */ 686b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg 6879d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Bergint ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) 688b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{ 6899d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg struct ieee80211_local *local = sdata->local; 690b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_if_conf conf; 691b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg 6929d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg if (WARN_ON(!netif_running(sdata->dev))) 6939d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg return 0; 6949d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg 6959d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg if (!local->ops->config_interface) 696f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 697f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 698b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg memset(&conf, 0, sizeof(conf)); 6999d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg conf.changed = changed; 7009d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg 70151fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_STA || 70251fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { 7034150c57212ad134765dd78c654a4b9906252b66dJohannes Berg conf.bssid = sdata->u.sta.bssid; 704b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg conf.ssid = sdata->u.sta.ssid; 705b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg conf.ssid_len = sdata->u.sta.ssid_len; 70651fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { 7079d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg conf.bssid = sdata->dev->dev_addr; 708b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg conf.ssid = sdata->u.ap.ssid; 709b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg conf.ssid_len = sdata->u.ap.ssid_len; 7109d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg } else if (ieee80211_vif_is_mesh(&sdata->vif)) { 7119d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg u8 zero[ETH_ALEN] = { 0 }; 7129d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg conf.bssid = zero; 7139d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg conf.ssid = zero; 7149d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg conf.ssid_len = 0; 7159d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg } else { 7169d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg WARN_ON(1); 7179d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg return -EINVAL; 718f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 719f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 7209d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID))) 7219d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg return -EINVAL; 722f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 7239d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg if (WARN_ON(!conf.ssid && (changed & IEEE80211_IFCC_SSID))) 7249d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg return -EINVAL; 725f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 7269d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg return local->ops->config_interface(local_to_hw(local), 7279d139c810a2aa17365cc548d0cd2a189d8433c65Johannes Berg &sdata->vif, &conf); 728b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 729f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 730b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergint ieee80211_hw_config(struct ieee80211_local *local) 731b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{ 732b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_channel *chan; 733b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg int ret = 0; 734f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 735c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg if (local->sw_scanning) 736b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg chan = local->scan_channel; 7378318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg else 738b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg chan = local->oper_channel; 739f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 7408318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.channel = chan; 7418318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 7428318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg if (!local->hw.conf.power_level) 7438318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.power_level = chan->max_power; 7448318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg else 7458318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.power_level = min(chan->max_power, 7468318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.power_level); 7478318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 7488318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.max_antenna_gain = chan->max_antenna_gain; 749f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 750b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 7518318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg printk(KERN_DEBUG "%s: HW CONFIG: freq=%d\n", 7528318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg wiphy_name(local->hw.wiphy), chan->center_freq); 7538318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg#endif 754b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg 755f7c4daed99fba15e4e48df464031f4ac7c32e4c9Michael Buesch if (local->open_count) 756b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg ret = local->ops->config(local_to_hw(local), &local->hw.conf); 757f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 758b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return ret; 759b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 760f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 761d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky/** 76238668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler * ieee80211_handle_ht should be used only after legacy configuration 76338668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler * has been determined namely band, as ht configuration depends upon 76438668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler * the hardware's HT abilities for a _specific_ band. 765d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky */ 76638668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkleru32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, 767d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky struct ieee80211_ht_info *req_ht_cap, 768d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky struct ieee80211_ht_bss_info *req_bss_cap) 769d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky{ 770d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky struct ieee80211_conf *conf = &local->hw.conf; 7718318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg struct ieee80211_supported_band *sband; 77238668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler struct ieee80211_ht_info ht_conf; 77338668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler struct ieee80211_ht_bss_info ht_bss_conf; 77438668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler u32 changed = 0; 775edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky int i; 776edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky u8 max_tx_streams = IEEE80211_HT_CAP_MAX_STREAMS; 777edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky u8 tx_mcs_set_cap; 778d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky 7798318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg sband = local->hw.wiphy->bands[conf->channel->band]; 7808318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 781edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info)); 782edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info)); 783edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky 784d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky /* HT is not supported */ 7858318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg if (!sband->ht_info.ht_supported) { 786d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; 787edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky goto out; 788d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky } 789d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky 790edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky /* disable HT */ 791edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky if (!enable_ht) { 792edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) 79338668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler changed |= BSS_CHANGED_HT; 794edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; 795edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky conf->ht_conf.ht_supported = 0; 796edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky goto out; 797edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky } 79838668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 79938668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 800edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) 801edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky changed |= BSS_CHANGED_HT; 80238668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 803edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE; 804edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_conf.ht_supported = 1; 80538668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 806edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; 80700c5ae2fa0f8191a1b204e71f0ee11359e3b2c06Tomas Winkler ht_conf.cap &= ~(IEEE80211_HT_CAP_SM_PS); 80800c5ae2fa0f8191a1b204e71f0ee11359e3b2c06Tomas Winkler ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_SM_PS; 809edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_bss_conf.primary_channel = req_bss_cap->primary_channel; 810edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_bss_conf.bss_cap = req_bss_cap->bss_cap; 811edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; 81238668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 813edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_conf.ampdu_factor = req_ht_cap->ampdu_factor; 814edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_conf.ampdu_density = req_ht_cap->ampdu_density; 81538668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 816edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky /* Bits 96-100 */ 817edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky tx_mcs_set_cap = sband->ht_info.supp_mcs_set[12]; 818edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky 819edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky /* configure suppoerted Tx MCS according to requested MCS 820edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky * (based in most cases on Rx capabilities of peer) and self 821edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky * Tx MCS capabilities (as defined by low level driver HW 822edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky * Tx capabilities) */ 823edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky if (!(tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_DEFINED)) 824edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky goto check_changed; 825d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky 826edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky /* Counting from 0 therfore + 1 */ 827edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_RX_DIFF) 828edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky max_tx_streams = ((tx_mcs_set_cap & 829edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky IEEE80211_HT_CAP_MCS_TX_STREAMS) >> 2) + 1; 830edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky 831edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky for (i = 0; i < max_tx_streams; i++) 832edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_conf.supp_mcs_set[i] = 833edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky sband->ht_info.supp_mcs_set[i] & 834edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky req_ht_cap->supp_mcs_set[i]; 835edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky 836edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_UEQM) 837edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky for (i = IEEE80211_SUPP_MCS_SET_UEQM; 838edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky i < IEEE80211_SUPP_MCS_SET_LEN; i++) 839edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_conf.supp_mcs_set[i] = 840edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky sband->ht_info.supp_mcs_set[i] & 841edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky req_ht_cap->supp_mcs_set[i]; 842edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky 843edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunskycheck_changed: 844edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky /* if bss configuration changed store the new one */ 845edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) || 846edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) { 847edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky changed |= BSS_CHANGED_HT; 848edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf)); 849edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf)); 850edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky } 851edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunskyout: 85238668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler return changed; 853d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky} 854d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky 855471b3efdfccc257591331724145f8ccf8b3217e1Johannes Bergvoid ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, 856471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg u32 changed) 857d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake{ 858471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg struct ieee80211_local *local = sdata->local; 859471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg 860471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg if (!changed) 861471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg return; 862471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg 863471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg if (local->ops->bss_info_changed) 864471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg local->ops->bss_info_changed(local_to_hw(local), 865471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg &sdata->vif, 866471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg &sdata->bss_conf, 867471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg changed); 868d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake} 869d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake 870f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greeneu32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) 871d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake{ 872471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg sdata->bss_conf.use_cts_prot = 0; 873471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg sdata->bss_conf.use_short_preamble = 0; 874fc32f9243dc93e75f81457e95d9cb90ee6136d94Tomas Winkler return BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE; 875d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake} 876d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake 877f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, 878e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct sk_buff *skb) 879f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 880f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 881e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 882f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc int tmp; 883f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 884f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb->dev = local->mdev; 885f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb->pkt_type = IEEE80211_TX_STATUS_MSG; 886e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ? 887f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc &local->skb_queue : &local->skb_queue_unreliable, skb); 888f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tmp = skb_queue_len(&local->skb_queue) + 889f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_len(&local->skb_queue_unreliable); 890f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT && 891f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc (skb = skb_dequeue(&local->skb_queue_unreliable))) { 892f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb_irq(skb); 893f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tmp--; 894f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc I802_DEBUG_INC(local->tx_status_drop); 895f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 896f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_schedule(&local->tasklet); 897f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 898f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_tx_status_irqsafe); 899f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 900f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void ieee80211_tasklet_handler(unsigned long data) 901f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 902f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = (struct ieee80211_local *) data; 903f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sk_buff *skb; 904f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_rx_status rx_status; 905eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_ra_tid *ra_tid; 906f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 907f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc while ((skb = skb_dequeue(&local->skb_queue)) || 908f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc (skb = skb_dequeue(&local->skb_queue_unreliable))) { 909f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc switch (skb->pkt_type) { 910f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case IEEE80211_RX_MSG: 911f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* status is in skb->cb */ 912f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memcpy(&rx_status, skb->cb, sizeof(rx_status)); 91351fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg /* Clear skb->pkt_type in order to not confuse kernel 914f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * netstack. */ 915f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb->pkt_type = 0; 916f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc __ieee80211_rx(local_to_hw(local), skb, &rx_status); 917f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 918f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case IEEE80211_TX_STATUS_MSG: 919f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb->pkt_type = 0; 920e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_tx_status(local_to_hw(local), skb); 921f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 922eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky case IEEE80211_DELBA_MSG: 923eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid = (struct ieee80211_ra_tid *) &skb->cb; 924eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ieee80211_stop_tx_ba_cb(local_to_hw(local), 925eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid->ra, ra_tid->tid); 926eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky dev_kfree_skb(skb); 927eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky break; 928eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky case IEEE80211_ADDBA_MSG: 929eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid = (struct ieee80211_ra_tid *) &skb->cb; 930eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ieee80211_start_tx_ba_cb(local_to_hw(local), 931eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid->ra, ra_tid->tid); 932eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky dev_kfree_skb(skb); 933eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky break ; 934f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg default: 935f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg WARN_ON(1); 936f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb(skb); 937f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 938f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 939f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 940f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 941f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 942f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to 943f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * make a prepared TX frame (one that has been given to hw) to look like brand 944f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * new IEEE 802.11 frame that is ready to go through TX processing again. 945d0f09804144fd9471a13cf4d80e66842c7fa114fJohannes Berg */ 946f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void ieee80211_remove_tx_extra(struct ieee80211_local *local, 947f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_key *key, 948e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct sk_buff *skb) 949f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 95062bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison unsigned int hdrlen, iv_len, mic_len; 95162bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 952f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 95362bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison hdrlen = ieee80211_hdrlen(hdr->frame_control); 954f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 955f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (!key) 956f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto no_key; 957f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 9588f20fc24986a083228823d9b68adca20714b254eJohannes Berg switch (key->conf.alg) { 959f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case ALG_WEP: 960f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc iv_len = WEP_IV_LEN; 961f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc mic_len = WEP_ICV_LEN; 962f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 963f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case ALG_TKIP: 964f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc iv_len = TKIP_IV_LEN; 965f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc mic_len = TKIP_ICV_LEN; 966f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 967f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case ALG_CCMP: 968f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc iv_len = CCMP_HDR_LEN; 969f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc mic_len = CCMP_MIC_LEN; 970f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 971f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc default: 972f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto no_key; 973f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 974f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 97562bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison if (skb->len >= hdrlen + mic_len && 97611a843b7e16062389c53ba393c7913956e034eb2Johannes Berg !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) 977f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_trim(skb, skb->len - mic_len); 97862bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison if (skb->len >= hdrlen + iv_len) { 979f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memmove(skb->data + iv_len, skb->data, hdrlen); 98062bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison hdr = (struct ieee80211_hdr *)skb_pull(skb, iv_len); 981f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 982f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 983f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencno_key: 98462bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison if (ieee80211_is_data_qos(hdr->frame_control)) { 98562bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); 98662bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison memmove(skb->data + IEEE80211_QOS_CTL_LEN, skb->data, 98762bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison hdrlen - IEEE80211_QOS_CTL_LEN); 98862bf1d762e24006fa9b6c8d56a22cf47a2310af3Harvey Harrison skb_pull(skb, IEEE80211_QOS_CTL_LEN); 989f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 990f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 991f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 992d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Bergstatic void ieee80211_handle_filtered_frame(struct ieee80211_local *local, 993d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg struct sta_info *sta, 994e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct sk_buff *skb) 995d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg{ 996e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 997e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg 998d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg sta->tx_filtered_count++; 999d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 1000d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg /* 1001d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * Clear the TX filter mask for this STA when sending the next 1002d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * packet. If the STA went to power save mode, this will happen 1003f6d97104890203ba9c2cf8e34894c4c8e64cb880Yi Zhu * when it wakes up for the next time. 1004d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg */ 100507346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg set_sta_flags(sta, WLAN_STA_CLEAR_PS_FILT); 1006d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 1007d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg /* 1008d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * This code races in the following way: 1009d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * 1010d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (1) STA sends frame indicating it will go to sleep and does so 1011d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (2) hardware/firmware adds STA to filter list, passes frame up 1012d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (3) hardware/firmware processes TX fifo and suppresses a frame 1013d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (4) we get TX status before having processed the frame and 1014d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * knowing that the STA has gone to sleep. 1015d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * 1016d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * This is actually quite unlikely even when both those events are 1017d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * processed from interrupts coming in quickly after one another or 1018d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * even at the same time because we queue both TX status events and 1019d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * RX frames to be processed by a tasklet and process them in the 1020d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * same order that they were received or TX status last. Hence, there 1021d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * is no race as long as the frame RX is processed before the next TX 1022d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * status, which drivers can ensure, see below. 1023d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * 1024d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * Note that this can only happen if the hardware or firmware can 1025d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * actually add STAs to the filter list, if this is done by the 1026d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * driver in response to set_tim() (which will only reduce the race 1027d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * this whole filtering tries to solve, not completely solve it) 1028d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * this situation cannot happen. 1029d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * 1030d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * To completely solve this race drivers need to make sure that they 1031d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (a) don't mix the irq-safe/not irq-safe TX status/RX processing 1032d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * functions and 1033d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (b) always process RX events before TX status events if ordering 1034d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * can be unknown, for example with different interrupt status 1035d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * bits. 1036d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg */ 103707346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg if (test_sta_flags(sta, WLAN_STA_PS) && 1038d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { 1039e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_remove_tx_extra(local, sta->key, skb); 1040d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg skb_queue_tail(&sta->tx_filtered, skb); 1041d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg return; 1042d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg } 1043d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 104407346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg if (!test_sta_flags(sta, WLAN_STA_PS) && 1045e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg !(info->flags & IEEE80211_TX_CTL_REQUEUE)) { 1046d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg /* Software retry the packet once */ 1047e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg info->flags |= IEEE80211_TX_CTL_REQUEUE; 1048e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_remove_tx_extra(local, sta->key, skb); 1049d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg dev_queue_xmit(skb); 1050d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg return; 1051d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg } 1052d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 1053f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 1054d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg if (net_ratelimit()) 1055d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg printk(KERN_DEBUG "%s: dropped TX filtered frame, " 1056d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg "queue_len=%d PS=%d @%lu\n", 1057d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg wiphy_name(local->hw.wiphy), 1058d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg skb_queue_len(&sta->tx_filtered), 105907346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg !!test_sta_flags(sta, WLAN_STA_PS), jiffies); 1060f4ea83dd743d3e1bec8fdf954ac911c6b12ae87aJohannes Berg#endif 1061d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg dev_kfree_skb(skb); 1062d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg} 1063d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 1064e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Bergvoid ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) 1065f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1066f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sk_buff *skb2; 1067f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 1068f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 1069e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1070f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc u16 frag, type; 1071429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky __le16 fc; 1072b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg struct ieee80211_tx_status_rtap_hdr *rthdr; 1073b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg struct ieee80211_sub_if_data *sdata; 10743d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu struct net_device *prev_dev = NULL; 1075429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky struct sta_info *sta; 1076f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1077d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_lock(); 1078d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg 1079e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->status.excessive_retries) { 1080f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta = sta_info_get(local, hdr->addr1); 1081f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (sta) { 108207346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg if (test_sta_flags(sta, WLAN_STA_PS)) { 1083d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg /* 1084d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * The STA is in power save mode, so assume 1085f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * that this TX packet failed because of that. 1086f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc */ 1087e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_handle_filtered_frame(local, sta, skb); 1088d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 1089d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg return; 1090f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1091f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1092f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1093f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1094429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky fc = hdr->frame_control; 1095429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky 1096429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && 1097429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky (ieee80211_is_data_qos(fc))) { 1098429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky u16 tid, ssn; 1099429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky u8 *qc; 1100429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky sta = sta_info_get(local, hdr->addr1); 1101429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky if (sta) { 1102429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky qc = ieee80211_get_qos_ctl(hdr); 1103429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky tid = qc[0] & 0xf; 1104429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10) 1105429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky & IEEE80211_SCTL_SEQ); 1106f698d856f65c3fea091cc303a135967965c5b880Jasper Bryant-Greene ieee80211_send_bar(sta->sdata, hdr->addr1, 1107429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky tid, ssn); 1108429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky } 1109429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky } 1110429a380571a6e6b8525b93161544eafc9b227e44Ron Rindjunsky 1111e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { 1112f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta = sta_info_get(local, hdr->addr1); 1113f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (sta) { 1114e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_handle_filtered_frame(local, sta, skb); 1115d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 1116f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return; 1117f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 11181abbe498e4b5e4f2000dfc30a0fa25be9553530eMattias Nissler } else 1119e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg rate_control_tx_status(local->mdev, skb); 1120f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1121d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 1122d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg 1123f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_led_tx(local, 0); 1124f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1125f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* SNMP counters 1126f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * Fragments are passed to low-level drivers as separate skbs, so these 1127f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * are actually fragments, not frames. Update frame counters only for 1128f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * the first fragment of the frame. */ 1129f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1130f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; 1131f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE; 1132f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1133e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->flags & IEEE80211_TX_STAT_ACK) { 1134f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (frag == 0) { 1135f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11TransmittedFrameCount++; 1136f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (is_multicast_ether_addr(hdr->addr1)) 1137f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11MulticastTransmittedFrameCount++; 1138e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->status.retry_count > 0) 1139f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11RetryCount++; 1140e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->status.retry_count > 1) 1141f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11MultipleRetryCount++; 1142f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1143f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1144f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* This counter shall be incremented for an acknowledged MPDU 1145f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * with an individual address in the address 1 field or an MPDU 1146f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * with a multicast address in the address 1 field of type Data 1147f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * or Management. */ 1148f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (!is_multicast_ether_addr(hdr->addr1) || 1149f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc type == IEEE80211_FTYPE_DATA || 1150f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc type == IEEE80211_FTYPE_MGMT) 1151f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11TransmittedFragmentCount++; 1152f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } else { 1153f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (frag == 0) 1154f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11FailedCount++; 1155f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1156f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1157b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg /* this was a transmitted frame, but now we want to reuse it */ 1158b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg skb_orphan(skb); 1159b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 11603d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu /* 11613d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu * This is a bit racy but we can avoid a lot of work 11623d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu * with this test... 11633d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu */ 11643d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (!local->monitors && !local->cooked_mntrs) { 1165f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb(skb); 1166f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return; 1167f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1168f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1169b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg /* send frame to monitor interfaces now */ 1170f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1171b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg if (skb_headroom(skb) < sizeof(*rthdr)) { 1172b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg printk(KERN_ERR "ieee80211_tx_status: headroom too small\n"); 1173f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb(skb); 1174f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return; 1175f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1176f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1177988c0f723d0b1abb399e6e71d8bf3f8bf1949a70Johannes Berg rthdr = (struct ieee80211_tx_status_rtap_hdr *) 1178b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg skb_push(skb, sizeof(*rthdr)); 1179b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 1180b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg memset(rthdr, 0, sizeof(*rthdr)); 1181b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); 1182b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->hdr.it_present = 1183b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | 1184b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg (1 << IEEE80211_RADIOTAP_DATA_RETRIES)); 1185b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 1186e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (!(info->flags & IEEE80211_TX_STAT_ACK) && 1187b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg !is_multicast_ether_addr(hdr->addr1)) 1188b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); 1189b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 1190e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) && 1191e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) 1192b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); 1193e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg else if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) 1194b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); 1195b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 1196e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg rthdr->data_retries = info->status.retry_count; 1197b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 11983d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu /* XXX: is this sufficient for BPF? */ 11993d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb_set_mac_header(skb, 0); 12003d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb->ip_summed = CHECKSUM_UNNECESSARY; 12013d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb->pkt_type = PACKET_OTHERHOST; 12023d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb->protocol = htons(ETH_P_802_2); 12033d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu memset(skb->cb, 0, sizeof(skb->cb)); 12043d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 120579010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg rcu_read_lock(); 120679010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg list_for_each_entry_rcu(sdata, &local->interfaces, list) { 120751fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) { 1208b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg if (!netif_running(sdata->dev)) 1209b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg continue; 12103d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 12113d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (prev_dev) { 121279010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg skb2 = skb_clone(skb, GFP_ATOMIC); 12133d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (skb2) { 12143d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb2->dev = prev_dev; 12153d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu netif_rx(skb2); 12163d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 12173d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 12183d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 12193d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu prev_dev = sdata->dev; 1220b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg } 1221b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg } 12223d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (prev_dev) { 12233d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb->dev = prev_dev; 12243d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu netif_rx(skb); 12253d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb = NULL; 12263d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 122779010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg rcu_read_unlock(); 12283d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu dev_kfree_skb(skb); 1229f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1230f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_tx_status); 1231f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1232f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstruct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, 1233f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc const struct ieee80211_ops *ops) 1234f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1235f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local; 1236f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc int priv_size; 1237f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct wiphy *wiphy; 1238f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1239f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* Ensure 32-byte alignment of our private data and hw private data. 1240f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * We use the wiphy priv data for both our ieee80211_local and for 1241f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * the driver's private data 1242f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * 1243f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * In memory it'll be like this: 1244f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * 1245f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * +-------------------------+ 1246f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * | struct wiphy | 1247f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * +-------------------------+ 1248f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * | struct ieee80211_local | 1249f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * +-------------------------+ 1250f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * | driver's private data | 1251f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * +-------------------------+ 1252f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * 1253f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc */ 1254f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc priv_size = ((sizeof(struct ieee80211_local) + 1255f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) + 1256f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc priv_data_len; 1257f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1258f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy = wiphy_new(&mac80211_config_ops, priv_size); 1259f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1260f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (!wiphy) 1261f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return NULL; 1262f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1263f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy->privid = mac80211_wiphy_privid; 1264f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1265f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local = wiphy_priv(wiphy); 1266f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.wiphy = wiphy; 1267f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1268f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.priv = (char *)local + 1269f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ((sizeof(struct ieee80211_local) + 1270f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); 1271f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 12724480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg BUG_ON(!ops->tx); 12734150c57212ad134765dd78c654a4b9906252b66dJohannes Berg BUG_ON(!ops->start); 12744150c57212ad134765dd78c654a4b9906252b66dJohannes Berg BUG_ON(!ops->stop); 12754480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg BUG_ON(!ops->config); 12764480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg BUG_ON(!ops->add_interface); 12774150c57212ad134765dd78c654a4b9906252b66dJohannes Berg BUG_ON(!ops->remove_interface); 12784150c57212ad134765dd78c654a4b9906252b66dJohannes Berg BUG_ON(!ops->configure_filter); 1279f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->ops = ops; 1280f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1281f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.queues = 1; /* default */ 1282f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1283f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; 1284f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; 1285f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->short_retry_limit = 7; 1286f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->long_retry_limit = 4; 1287f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.conf.radio_enabled = 1; 1288f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 128979010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg INIT_LIST_HEAD(&local->interfaces); 1290f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1291b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg spin_lock_init(&local->key_lock); 1292b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg 1293c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); 1294f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1295f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta_info_init(local); 1296f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1297f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, 1298f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc (unsigned long)local); 1299f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_disable(&local->tx_pending_tasklet); 1300f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1301f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_init(&local->tasklet, 1302f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_tasklet_handler, 1303f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc (unsigned long) local); 1304f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_disable(&local->tasklet); 1305f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1306f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_head_init(&local->skb_queue); 1307f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_head_init(&local->skb_queue_unreliable); 1308f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1309f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return local_to_hw(local); 1310f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1311f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_alloc_hw); 1312f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1313f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencint ieee80211_register_hw(struct ieee80211_hw *hw) 1314f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1315f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 1316f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc const char *name; 1317f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc int result; 13188318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg enum ieee80211_band band; 131996d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg struct net_device *mdev; 13203e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg struct wireless_dev *mwdev; 13218318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 13228318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg /* 13238318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg * generic code guarantees at least one band, 13248318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg * set this very early because much code assumes 13258318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg * that hw.conf.channel is assigned 13268318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg */ 13278318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 13288318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg struct ieee80211_supported_band *sband; 13298318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 13308318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg sband = local->hw.wiphy->bands[band]; 13318318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg if (sband) { 13328318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg /* init channel we're on */ 13338318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.channel = 13348318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->oper_channel = 13358318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->scan_channel = &sband->channels[0]; 13368318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg break; 13378318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg } 13388318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg } 1339f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1340f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez /* if low-level driver supports AP, we also support VLAN */ 1341f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) 1342f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); 1343f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez 1344f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez /* mac80211 always supports monitor */ 1345f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); 1346f59ac0481660e66cec67f1d6b024e78b9dc715feLuis R. Rodriguez 1347f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = wiphy_register(local->hw.wiphy); 1348f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) 1349f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return result; 1350f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1351e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg /* 1352e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg * We use the number of queues for feature tests (QoS, HT) internally 1353e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg * so restrict them appropriately. 1354e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg */ 1355e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg if (hw->queues > IEEE80211_MAX_QUEUES) 1356e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg hw->queues = IEEE80211_MAX_QUEUES; 1357e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES) 1358e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES; 1359e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg if (hw->queues < 4) 1360e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg hw->ampdu_queues = 0; 1361e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg 13623e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg mdev = alloc_netdev_mq(sizeof(struct wireless_dev), 1363e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg "wmaster%d", ether_setup, 1364e2530083609148a7835b54c431f6b8956407c1f6Johannes Berg ieee80211_num_queues(hw)); 136596d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg if (!mdev) 136696d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg goto fail_mdev_alloc; 136796d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 13683e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg mwdev = netdev_priv(mdev); 13693e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg mdev->ieee80211_ptr = mwdev; 13703e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg mwdev->wiphy = local->hw.wiphy; 137196d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 137296d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg local->mdev = mdev; 137396d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 13743e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg ieee80211_rx_bss_list_init(local); 137596d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 137696d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->hard_start_xmit = ieee80211_master_start_xmit; 137796d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->open = ieee80211_master_open; 137896d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->stop = ieee80211_master_stop; 137996d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->type = ARPHRD_IEEE80211; 138096d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->header_ops = &ieee80211_header_ops; 138196d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->set_multicast_list = ieee80211_master_set_multicast_list; 138296d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 1383f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc name = wiphy_dev(local->hw.wiphy)->driver->name; 138459959a6150c8af737898e83f727e824dbed7b0faJohannes Berg local->hw.workqueue = create_freezeable_workqueue(name); 1385f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (!local->hw.workqueue) { 1386f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = -ENOMEM; 1387f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_workqueue; 1388f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1389f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1390b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg /* 1391b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg * The hardware needs headroom for sending the frame, 1392b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg * and we need some headroom for passing the frame to monitor 1393b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg * interfaces, but never both at the same time. 1394b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg */ 139533ccad35a21df51c0d23f3e3e88688524e7b51edJiri Benc local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom, 139633ccad35a21df51c0d23f3e3e88688524e7b51edJiri Benc sizeof(struct ieee80211_tx_status_rtap_hdr)); 1397b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 1398e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc debugfs_hw_add(local); 1399e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 1400dc0ae30c31ee6ef83992bb692f37dfbba08a2ef6Tomas Winkler if (local->hw.conf.beacon_int < 10) 1401dc0ae30c31ee6ef83992bb692f37dfbba08a2ef6Tomas Winkler local->hw.conf.beacon_int = 100; 1402f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1403ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler if (local->hw.max_listen_interval == 0) 1404ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler local->hw.max_listen_interval = 1; 1405ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler 1406ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler local->hw.conf.listen_interval = local->hw.max_listen_interval; 1407ea95bba41e69c616bb1512cf59d22f33266b8568Tomas Winkler 1408566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf local->wstats_flags |= local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC | 1409566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf IEEE80211_HW_SIGNAL_DB | 1410566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf IEEE80211_HW_SIGNAL_DBM) ? 1411f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID; 1412566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf local->wstats_flags |= local->hw.flags & IEEE80211_HW_NOISE_DBM ? 1413f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID; 1414566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) 1415f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->wstats_flags |= IW_QUAL_DBM; 1416f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1417f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = sta_info_start(local); 1418f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) 1419f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_sta_info; 1420f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1421f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_lock(); 1422f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = dev_alloc_name(local->mdev, local->mdev->name); 1423f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) 1424f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_dev; 1425f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1426f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); 1427f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy)); 1428f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1429f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = register_netdevice(local->mdev); 1430f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) 1431f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_dev; 1432f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1433830f903866a1611e9ce53f3e35202302bb938946Johannes Berg result = ieee80211_init_rate_ctrl_alg(local, 1434830f903866a1611e9ce53f3e35202302bb938946Johannes Berg hw->rate_control_algorithm); 1435f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) { 1436f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_DEBUG "%s: Failed to initialize rate control " 1437dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg "algorithm\n", wiphy_name(local->hw.wiphy)); 1438f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_rate; 1439f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1440f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1441f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = ieee80211_wep_init(local); 1442f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1443f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) { 1444023a04bebe7030c1e6d5347bd3f27a3e49a1f222Jeremy Fitzhardinge printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n", 1445023a04bebe7030c1e6d5347bd3f27a3e49a1f222Jeremy Fitzhardinge wiphy_name(local->hw.wiphy), result); 1446f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_wep; 1447f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1448f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 144951cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller local->mdev->select_queue = ieee80211_select_queue; 1450f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1451f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* add one default STA interface */ 14523e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg result = ieee80211_if_add(local, "wlan%d", NULL, 1453ee3858551ae6d044578f598f8001db5f1a9fd52eLuis Carlos Cobo IEEE80211_IF_TYPE_STA, NULL); 1454f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result) 1455f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_WARNING "%s: Failed to add default virtual iface\n", 1456dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg wiphy_name(local->hw.wiphy)); 1457f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1458f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_unlock(); 1459f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1460f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_led_init(local); 1461f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1462f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 1463f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1464f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_wep: 1465f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rate_control_deinitialize(local); 1466f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_rate: 1467f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc unregister_netdevice(local->mdev); 1468339a7c41c913035bf58579f6e47b4ba29da83795Pavel Emelyanov local->mdev = NULL; 1469f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_dev: 1470f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_unlock(); 1471f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta_info_stop(local); 1472f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_sta_info: 1473e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc debugfs_hw_del(local); 1474f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc destroy_workqueue(local->hw.workqueue); 1475f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_workqueue: 14763e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg if (local->mdev) 14773e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg free_netdev(local->mdev); 147896d510566e4908f77f03ff1436c78ae7162a17d0Johannes Bergfail_mdev_alloc: 1479f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy_unregister(local->hw.wiphy); 1480f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return result; 1481f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1482f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_register_hw); 1483f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1484f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_unregister_hw(struct ieee80211_hw *hw) 1485f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1486f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 1487f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1488f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_kill(&local->tx_pending_tasklet); 1489f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_kill(&local->tasklet); 1490f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1491f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_lock(); 1492f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 149379010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg /* 149479010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * At this point, interface list manipulations are fine 149579010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * because the driver cannot be handing us frames any 149679010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * more and the tasklet is killed. 149779010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg */ 14985b2812e925c8e976852867f8d760637c5926d817Johannes Berg 149975636525fbfa78fa33fd754c89785cfde750acd3Johannes Berg /* First, we remove all virtual interfaces. */ 150075636525fbfa78fa33fd754c89785cfde750acd3Johannes Berg ieee80211_remove_interfaces(local); 15015b2812e925c8e976852867f8d760637c5926d817Johannes Berg 15025b2812e925c8e976852867f8d760637c5926d817Johannes Berg /* then, finally, remove the master interface */ 15033e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg unregister_netdevice(local->mdev); 1504f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1505f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_unlock(); 1506f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 15073e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg ieee80211_rx_bss_list_deinit(local); 1508f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_clear_tx_pending(local); 1509f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta_info_stop(local); 1510f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rate_control_deinitialize(local); 1511e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc debugfs_hw_del(local); 1512f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1513f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (skb_queue_len(&local->skb_queue) 1514f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc || skb_queue_len(&local->skb_queue_unreliable)) 1515f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_WARNING "%s: skb_queue not empty\n", 1516dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg wiphy_name(local->hw.wiphy)); 1517f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_purge(&local->skb_queue); 1518f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_purge(&local->skb_queue_unreliable); 1519f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1520f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc destroy_workqueue(local->hw.workqueue); 1521f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy_unregister(local->hw.wiphy); 1522f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_wep_free(local); 1523f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_led_exit(local); 15243e122be089e6fb8d3f322416da4cdbb80ce12927Johannes Berg free_netdev(local->mdev); 1525f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1526f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_unregister_hw); 1527f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1528f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_free_hw(struct ieee80211_hw *hw) 1529f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1530f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 1531f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1532f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy_free(local->hw.wiphy); 1533f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1534f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_free_hw); 1535f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1536f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic int __init ieee80211_init(void) 1537f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1538f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sk_buff *skb; 1539f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc int ret; 1540f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1541e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg BUILD_BUG_ON(sizeof(struct ieee80211_tx_info) > sizeof(skb->cb)); 1542e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) + 1543e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb)); 1544f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 15454b475898ec9dc6e62cebcb8fc0b3495c986a4590Johannes Berg ret = rc80211_pid_init(); 1546ad01837593338f13508463fa11c8dbf8109a1e5dMattias Nissler if (ret) 154751cb6db0f5654f08a4a6bfa3888dc36a51c2df3eDavid S. Miller return ret; 1548f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1549e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc ieee80211_debugfs_netdev_init(); 1550e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 1551f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 1552f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1553f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1554f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void __exit ieee80211_exit(void) 1555f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 15564b475898ec9dc6e62cebcb8fc0b3495c986a4590Johannes Berg rc80211_pid_exit(); 1557ac71c691e6a5ce991fe221d3bdb0c972f617aa37Johannes Berg 15583b96766f0e643f52ae19e134664df6730c737e87Johannes Berg /* 15593b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * For key todo, it'll be empty by now but the work 15603b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * might still be scheduled. 15613b96766f0e643f52ae19e134664df6730c737e87Johannes Berg */ 15623b96766f0e643f52ae19e134664df6730c737e87Johannes Berg flush_scheduled_work(); 15633b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 1564f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo if (mesh_allocated) 1565f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo ieee80211s_stop(); 1566902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg 1567e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc ieee80211_debugfs_netdev_exit(); 1568f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1569f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1570f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1571ca9938fea576ebbb8d8c4fbe8a5bcc937e49e1caJohannes Bergsubsys_initcall(ieee80211_init); 1572f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencmodule_exit(ieee80211_exit); 1573f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1574f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencMODULE_DESCRIPTION("IEEE 802.11 subsystem"); 1575f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencMODULE_LICENSE("GPL"); 1576