main.c revision e039fa4a4195ac4ee895e6f3d1334beed63256fe
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) { 108b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (sdata->dev != dev && 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 11736d6825b91bc492b65b6333c369cd96a2fc8c903Johannes Berg netif_start_queue(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) 129b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (sdata->dev != dev && 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 || 154f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) { 155b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg printk(KERN_WARNING "%s: invalid MTU %d\n", 156b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->name, new_mtu); 157b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return -EINVAL; 158b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 159f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 160b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 161b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu); 162b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ 163b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->mtu = new_mtu; 164f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 165f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 166f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 167b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic inline int identical_mac_addr_allowed(int type1, int type2) 168b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{ 169b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return (type1 == IEEE80211_IF_TYPE_MNTR || 170b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg type2 == IEEE80211_IF_TYPE_MNTR || 171b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg (type1 == IEEE80211_IF_TYPE_AP && 172b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg type2 == IEEE80211_IF_TYPE_WDS) || 173b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg (type1 == IEEE80211_IF_TYPE_WDS && 174b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg (type2 == IEEE80211_IF_TYPE_WDS || 175b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg type2 == IEEE80211_IF_TYPE_AP)) || 176b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg (type1 == IEEE80211_IF_TYPE_AP && 177b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg type2 == IEEE80211_IF_TYPE_VLAN) || 178b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg (type1 == IEEE80211_IF_TYPE_VLAN && 179b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg (type2 == IEEE80211_IF_TYPE_AP || 180b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg type2 == IEEE80211_IF_TYPE_VLAN))); 181b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 182f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 183b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic int ieee80211_open(struct net_device *dev) 184e2ebc74d7e3d71600640db6fbb28cc2f362184c1Johannes Berg{ 185b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_sub_if_data *sdata, *nsdata; 186b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 187b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_if_init_conf conf; 188b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg int res; 189ceffefd15aac78841432230627308b8a382dbcfcMichael Buesch bool need_hw_reconfig = 0; 19044213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg struct sta_info *sta; 191f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 192b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1930ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg 19479010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg /* we hold the RTNL here so can safely walk the list */ 19579010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg list_for_each_entry(nsdata, &local->interfaces, list) { 196b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct net_device *ndev = nsdata->dev; 197e2ebc74d7e3d71600640db6fbb28cc2f362184c1Johannes Berg 198665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg if (ndev != dev && ndev != local->mdev && netif_running(ndev)) { 199665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg /* 200665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * Allow only a single IBSS interface to be up at any 201665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * time. This is restricted because beacon distribution 202665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * cannot work properly if both are in the same IBSS. 203665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * 204665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * To remove this restriction we'd have to disallow them 205665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * from setting the same SSID on different IBSS interfaces 206665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * belonging to the same hardware. Then, however, we're 207665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * faced with having to adopt two different TSF timers... 208665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg */ 209665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && 210665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg nsdata->vif.type == IEEE80211_IF_TYPE_IBSS) 211665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg return -EBUSY; 212665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg 213665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg /* 214665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * Disallow multiple IBSS/STA mode interfaces. 215665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * 216665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * This is a technical restriction, it is possible although 217665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * most likely not IEEE 802.11 compliant to have multiple 218665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * STAs with just a single hardware (the TSF timer will not 219665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * be adjusted properly.) 220665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * 221665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * However, because mac80211 uses the master device's BSS 222665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * information for each STA/IBSS interface, doing this will 223665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * currently corrupt that BSS information completely, unless, 224665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * a not very useful case, both STAs are associated to the 225665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * same BSS. 226665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * 227665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * To remove this restriction, the BSS information needs to 228665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * be embedded in the STA/IBSS mode sdata instead of using 229665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * the master device's BSS structure. 230665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg */ 231665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg if ((sdata->vif.type == IEEE80211_IF_TYPE_STA || 232665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg sdata->vif.type == IEEE80211_IF_TYPE_IBSS) && 233665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg (nsdata->vif.type == IEEE80211_IF_TYPE_STA || 234665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg nsdata->vif.type == IEEE80211_IF_TYPE_IBSS)) 235665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg return -EBUSY; 236665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg 237665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg /* 238665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * The remaining checks are only performed for interfaces 239665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * with the same MAC address. 240665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg */ 241665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg if (compare_ether_addr(dev->dev_addr, ndev->dev_addr)) 242665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg continue; 243665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg 2440ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg /* 2450ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg * check whether it may have the same address 2460ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg */ 24751fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (!identical_mac_addr_allowed(sdata->vif.type, 24851fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg nsdata->vif.type)) 2490ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg return -ENOTUNIQ; 2500ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg 2510ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg /* 2520ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg * can only add VLANs to enabled APs 2530ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg */ 25451fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN && 255665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg nsdata->vif.type == IEEE80211_IF_TYPE_AP) 2560ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg sdata->u.vlan.ap = nsdata; 257b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 258b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 259f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 26051fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg switch (sdata->vif.type) { 2610ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg case IEEE80211_IF_TYPE_WDS: 262e94e106831403d5028e7bb73c3163951134de1baJohannes Berg if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) 2630ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg return -ENOLINK; 2640ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg break; 2650ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg case IEEE80211_IF_TYPE_VLAN: 2660ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg if (!sdata->u.vlan.ap) 2670ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg return -ENOLINK; 2680ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg break; 269fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg case IEEE80211_IF_TYPE_AP: 270fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg case IEEE80211_IF_TYPE_STA: 271fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg case IEEE80211_IF_TYPE_MNTR: 272fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg case IEEE80211_IF_TYPE_IBSS: 2736032f934c818e5c3435c9f17274fe1983f53c6b4Johannes Berg case IEEE80211_IF_TYPE_MESH_POINT: 274fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg /* no special treatment */ 275fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg break; 276a28975525016ddcbdaab8225666df1cf2dc9cb2dJohannes Berg case IEEE80211_IF_TYPE_INVALID: 277a28975525016ddcbdaab8225666df1cf2dc9cb2dJohannes Berg /* cannot happen */ 278a28975525016ddcbdaab8225666df1cf2dc9cb2dJohannes Berg WARN_ON(1); 279a28975525016ddcbdaab8225666df1cf2dc9cb2dJohannes Berg break; 2800ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg } 281f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 282b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (local->open_count == 0) { 283b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg res = 0; 2844150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (local->ops->start) 2854150c57212ad134765dd78c654a4b9906252b66dJohannes Berg res = local->ops->start(local_to_hw(local)); 2864150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (res) 287b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return res; 288ceffefd15aac78841432230627308b8a382dbcfcMichael Buesch need_hw_reconfig = 1; 289cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn ieee80211_led_radio(local, local->hw.conf.radio_enabled); 290b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 291f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 29251fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg switch (sdata->vif.type) { 2930ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg case IEEE80211_IF_TYPE_VLAN: 2940ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans); 2950ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg /* no need to tell driver */ 2960ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg break; 2974150c57212ad134765dd78c654a4b9906252b66dJohannes Berg case IEEE80211_IF_TYPE_MNTR: 2983d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { 2993d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu local->cooked_mntrs++; 3003d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu break; 3013d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 3023d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 3034150c57212ad134765dd78c654a4b9906252b66dJohannes Berg /* must be before the call to ieee80211_configure_filter */ 304b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg local->monitors++; 3058cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (local->monitors == 1) 3064150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; 3078cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 3088cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) 3098cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_fcsfail++; 3108cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) 3118cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_plcpfail++; 3128cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) 3138cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_control++; 3148cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) 3158cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_other_bss++; 3168cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 3178cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu netif_tx_lock_bh(local->mdev); 3188cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu ieee80211_configure_filter(local); 3198cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu netif_tx_unlock_bh(local->mdev); 3204150c57212ad134765dd78c654a4b9906252b66dJohannes Berg break; 3214150c57212ad134765dd78c654a4b9906252b66dJohannes Berg case IEEE80211_IF_TYPE_STA: 3224150c57212ad134765dd78c654a4b9906252b66dJohannes Berg case IEEE80211_IF_TYPE_IBSS: 3234150c57212ad134765dd78c654a4b9906252b66dJohannes Berg sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET; 3244150c57212ad134765dd78c654a4b9906252b66dJohannes Berg /* fall through */ 3254150c57212ad134765dd78c654a4b9906252b66dJohannes Berg default: 32632bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg conf.vif = &sdata->vif; 32751fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg conf.type = sdata->vif.type; 3284150c57212ad134765dd78c654a4b9906252b66dJohannes Berg conf.mac_addr = dev->dev_addr; 3294150c57212ad134765dd78c654a4b9906252b66dJohannes Berg res = local->ops->add_interface(local_to_hw(local), &conf); 3304150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (res) 331636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg goto err_stop; 3324150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 333b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg ieee80211_if_config(dev); 334d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake ieee80211_reset_erp_info(dev); 33511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg ieee80211_enable_keys(sdata); 3364150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 33751fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_STA && 338ddd3d2be85e3207c47f2b3c431723e6c758b4b0dJohannes Berg !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) 3394150c57212ad134765dd78c654a4b9906252b66dJohannes Berg netif_carrier_off(dev); 3404150c57212ad134765dd78c654a4b9906252b66dJohannes Berg else 3414150c57212ad134765dd78c654a4b9906252b66dJohannes Berg netif_carrier_on(dev); 342d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake } 343f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 344636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) { 345636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg /* Create STA entry for the WDS peer */ 346636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, 347636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg GFP_KERNEL); 348636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg if (!sta) { 349636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg res = -ENOMEM; 350636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg goto err_del_interface; 351636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg } 352636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg 35307346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg /* no locking required since STA is not live yet */ 354636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg sta->flags |= WLAN_STA_AUTHORIZED; 355636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg 356636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg res = sta_info_insert(sta); 357636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg if (res) { 358636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg /* STA has been freed */ 359636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg goto err_del_interface; 360636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg } 361636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg } 362636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg 3634150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (local->open_count == 0) { 3644150c57212ad134765dd78c654a4b9906252b66dJohannes Berg res = dev_open(local->mdev); 3654150c57212ad134765dd78c654a4b9906252b66dJohannes Berg WARN_ON(res); 366636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg if (res) 367636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg goto err_del_interface; 3684150c57212ad134765dd78c654a4b9906252b66dJohannes Berg tasklet_enable(&local->tx_pending_tasklet); 3694150c57212ad134765dd78c654a4b9906252b66dJohannes Berg tasklet_enable(&local->tasklet); 3704150c57212ad134765dd78c654a4b9906252b66dJohannes Berg } 3714150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 372c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg /* 373c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * set_multicast_list will be invoked by the networking core 374c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * which will check whether any increments here were done in 375c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * error and sync them down to the hardware as filter flags. 376c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg */ 377c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg if (sdata->flags & IEEE80211_SDATA_ALLMULTI) 378c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg atomic_inc(&local->iff_allmultis); 379c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg 380c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg if (sdata->flags & IEEE80211_SDATA_PROMISC) 381c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg atomic_inc(&local->iff_promiscs); 382c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg 3834150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->open_count++; 384ceffefd15aac78841432230627308b8a382dbcfcMichael Buesch if (need_hw_reconfig) 385ceffefd15aac78841432230627308b8a382dbcfcMichael Buesch ieee80211_hw_config(local); 386f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 38764f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann /* 38864f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann * ieee80211_sta_work is disabled while network interface 38964f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann * is down. Therefore, some configuration changes may not 39064f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann * yet be effective. Trigger execution of ieee80211_sta_work 39164f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann * to fix this. 39264f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann */ 393988c0f723d0b1abb399e6e71d8bf3f8bf1949a70Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_STA || 394988c0f723d0b1abb399e6e71d8bf3f8bf1949a70Johannes Berg sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { 39564f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann struct ieee80211_if_sta *ifsta = &sdata->u.sta; 39664f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann queue_work(local->hw.workqueue, &ifsta->work); 39764f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann } 39864f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann 399b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg netif_start_queue(dev); 4004150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 401b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return 0; 402636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg err_del_interface: 403636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg local->ops->remove_interface(local_to_hw(local), &conf); 404636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg err_stop: 405636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg if (!local->open_count && local->ops->stop) 406636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg local->ops->stop(local_to_hw(local)); 407636c5d488bc0b349e01cf5bfbf85588134af70a0Johannes Berg return res; 408f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 409f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 4104150c57212ad134765dd78c654a4b9906252b66dJohannes Bergstatic int ieee80211_stop(struct net_device *dev) 411f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 41244213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 41344213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg struct ieee80211_local *local = sdata->local; 4144150c57212ad134765dd78c654a4b9906252b66dJohannes Berg struct ieee80211_if_init_conf conf; 41507db218396650933abff3c5c1ad1e2a6e0cfedebRon Rindjunsky struct sta_info *sta; 4164150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 41744213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg /* 41844213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * Stop TX on this interface first. 41944213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg */ 42044213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg netif_stop_queue(dev); 4214150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 42244213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg /* 42344213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * Now delete all active aggregation sessions. 42444213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg */ 425d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_lock(); 426d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg 427d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg list_for_each_entry_rcu(sta, &local->sta_list, list) { 428d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg if (sta->sdata == sdata) 42985249e5fab13edb89258fa6d551cd4a3a4f0d569Ron Rindjunsky ieee80211_sta_tear_down_BA_sessions(dev, sta->addr); 43007db218396650933abff3c5c1ad1e2a6e0cfedebRon Rindjunsky } 43107db218396650933abff3c5c1ad1e2a6e0cfedebRon Rindjunsky 432d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 433d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg 43444213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg /* 43544213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * Remove all stations associated with this interface. 43644213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * 43744213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * This must be done before calling ops->remove_interface() 43844213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * because otherwise we can later invoke ops->sta_notify() 43944213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * whenever the STAs are removed, and that invalidates driver 44044213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * assumptions about always getting a vif pointer that is valid 44144213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * (because if we remove a STA after ops->remove_interface() 44244213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * the driver will have removed the vif info already!) 44344213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * 44444213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * We could relax this and only unlink the stations from the 44544213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * hash table and list but keep them on a per-sdata list that 44644213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * will be inserted back again when the interface is brought 44744213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * up again, but I don't currently see a use case for that, 44844213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * except with WDS which gets a STA entry created when it is 44944213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * brought up. 45044213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg */ 45144213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg sta_info_flush(local, sdata); 4524150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 453c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg /* 454c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * Don't count this interface for promisc/allmulti while it 455c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * is down. dev_mc_unsync() will invoke set_multicast_list 456c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * on the master interface which will sync these down to the 457c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * hardware as filter flags. 458c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg */ 459c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg if (sdata->flags & IEEE80211_SDATA_ALLMULTI) 460c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg atomic_dec(&local->iff_allmultis); 461c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg 462c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg if (sdata->flags & IEEE80211_SDATA_PROMISC) 463c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg atomic_dec(&local->iff_promiscs); 464c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg 4654150c57212ad134765dd78c654a4b9906252b66dJohannes Berg dev_mc_unsync(local->mdev, dev); 4664150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 4675dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg /* APs need special treatment */ 46851fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { 4690ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg struct ieee80211_sub_if_data *vlan, *tmp; 4705dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg struct beacon_data *old_beacon = sdata->u.ap.beacon; 4710ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg 4725dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg /* remove beacon */ 4735dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg rcu_assign_pointer(sdata->u.ap.beacon, NULL); 4745dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg synchronize_rcu(); 4755dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg kfree(old_beacon); 4765dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg 4775dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg /* down all dependent devices, that is VLANs */ 4780ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans, 4790ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg u.vlan.list) 4800ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg dev_close(vlan->dev); 4810ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg WARN_ON(!list_empty(&sdata->u.ap.vlans)); 4820ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg } 4830ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg 4844150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->open_count--; 485f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 48651fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg switch (sdata->vif.type) { 4870ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg case IEEE80211_IF_TYPE_VLAN: 4880ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg list_del(&sdata->u.vlan.list); 4890ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg sdata->u.vlan.ap = NULL; 4900ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg /* no need to tell driver */ 4910ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg break; 4924150c57212ad134765dd78c654a4b9906252b66dJohannes Berg case IEEE80211_IF_TYPE_MNTR: 4933d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { 4943d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu local->cooked_mntrs--; 4953d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu break; 4963d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 4973d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 4984150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->monitors--; 4998cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (local->monitors == 0) 5008b393f1dc76acbe65a97a4e51f8144f4a65fa1c9Michael Wu local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; 5018cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 5028cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) 5038cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_fcsfail--; 5048cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) 5058cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_plcpfail--; 5068cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) 5078cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_control--; 5088cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) 5098cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_other_bss--; 5108cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 5118cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu netif_tx_lock_bh(local->mdev); 5128cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu ieee80211_configure_filter(local); 5138cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu netif_tx_unlock_bh(local->mdev); 5144150c57212ad134765dd78c654a4b9906252b66dJohannes Berg break; 515f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo case IEEE80211_IF_TYPE_MESH_POINT: 516b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg case IEEE80211_IF_TYPE_STA: 517b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg case IEEE80211_IF_TYPE_IBSS: 518b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg sdata->u.sta.state = IEEE80211_DISABLED; 519b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg del_timer_sync(&sdata->u.sta.timer); 5202a8a9a88fc1b18f5c45244d0ef8a5352f6cf761fJohannes Berg /* 52179010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * When we get here, the interface is marked down. 52279010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * Call synchronize_rcu() to wait for the RX path 52379010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * should it be using the interface and enqueuing 52479010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * frames at this very time on another CPU. 5252a8a9a88fc1b18f5c45244d0ef8a5352f6cf761fJohannes Berg */ 52679010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg synchronize_rcu(); 527b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg skb_queue_purge(&sdata->u.sta.skb_queue); 5282a8a9a88fc1b18f5c45244d0ef8a5352f6cf761fJohannes Berg 529ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi if (local->scan_dev == sdata->dev) { 530ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi if (!local->ops->hw_scan) { 531ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi local->sta_sw_scanning = 0; 532ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi cancel_delayed_work(&local->scan_work); 533ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi } else 534ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi local->sta_hw_scanning = 0; 535b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 536ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi 537b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg flush_workqueue(local->hw.workqueue); 538a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi 539a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; 540a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi kfree(sdata->u.sta.extra_ie); 541a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi sdata->u.sta.extra_ie = NULL; 542a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi sdata->u.sta.extra_ie_len = 0; 5434150c57212ad134765dd78c654a4b9906252b66dJohannes Berg /* fall through */ 5444150c57212ad134765dd78c654a4b9906252b66dJohannes Berg default: 54532bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg conf.vif = &sdata->vif; 54651fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg conf.type = sdata->vif.type; 5474150c57212ad134765dd78c654a4b9906252b66dJohannes Berg conf.mac_addr = dev->dev_addr; 54811a843b7e16062389c53ba393c7913956e034eb2Johannes Berg /* disable all keys for as long as this netdev is down */ 54911a843b7e16062389c53ba393c7913956e034eb2Johannes Berg ieee80211_disable_keys(sdata); 5504150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->ops->remove_interface(local_to_hw(local), &conf); 551f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 552f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 553b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (local->open_count == 0) { 554b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (netif_running(local->mdev)) 555b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev_close(local->mdev); 5564150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 557b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (local->ops->stop) 558b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg local->ops->stop(local_to_hw(local)); 5594150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 560cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn ieee80211_led_radio(local, 0); 561cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn 562b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg tasklet_disable(&local->tx_pending_tasklet); 563b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg tasklet_disable(&local->tasklet); 564b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 565b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg 566f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 567f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 568f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 569eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyint ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) 570eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{ 571eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_local *local = hw_to_local(hw); 572eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct sta_info *sta; 573eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_sub_if_data *sdata; 574eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky u16 start_seq_num = 0; 575eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky u8 *state; 576eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky int ret; 577eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky DECLARE_MAC_BUF(mac); 578eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 579eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (tid >= STA_TID_NUM) 580eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return -EINVAL; 581eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 582eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG 583eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "Open BA session requested for %s tid %u\n", 584eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky print_mac(mac, ra), tid); 585eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */ 586eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 587d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_lock(); 588d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg 589eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky sta = sta_info_get(local, ra); 590eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (!sta) { 591eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "Could not find the station\n"); 592d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 593eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return -ENOENT; 594eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 595eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 59607346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg spin_lock_bh(&sta->lock); 597eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 598eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* we have tried too many times, receiver does not want A-MPDU */ 599cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { 600eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ret = -EBUSY; 601eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky goto start_ba_exit; 602eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 603eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 604cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky state = &sta->ampdu_mlme.tid_state_tx[tid]; 605eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* check if the TID is not in aggregation flow already */ 606eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (*state != HT_AGG_STATE_IDLE) { 607eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG 608eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "BA request denied - session is not " 609eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky "idle on tid %u\n", tid); 610eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */ 611eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ret = -EAGAIN; 612eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky goto start_ba_exit; 613eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 614eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 615cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky /* prepare A-MPDU MLME for Tx aggregation */ 616cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid] = 617cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); 618cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky if (!sta->ampdu_mlme.tid_tx[tid]) { 619cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky if (net_ratelimit()) 620cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky printk(KERN_ERR "allocate tx mlme to tid %d failed\n", 621cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky tid); 622cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky ret = -ENOMEM; 623cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky goto start_ba_exit; 624cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky } 625cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky /* Tx timer */ 626cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = 627cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta_addba_resp_timer_expired; 628cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data = 629cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky (unsigned long)&sta->timer_to_tid[tid]; 630cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); 631cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky 632eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* ensure that TX flow won't interrupt us 633eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * until the end of the call to requeue function */ 634eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_lock_bh(&local->mdev->queue_lock); 635eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 636eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* create a new queue for this aggregation */ 6379e7234923789897858e1a475c579b5e2e6ad5b74Ron Rindjunsky ret = ieee80211_ht_agg_queue_add(local, sta, tid); 638eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 639eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* case no queue is available to aggregation 640eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * don't switch to aggregation */ 641eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (ret) { 642eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG 643cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky printk(KERN_DEBUG "BA request denied - queue unavailable for" 644eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky " tid %d\n", tid); 645eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */ 646cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky goto start_ba_err; 647eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 648d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg sdata = sta->sdata; 649eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 650eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the 651eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * call back right away, it must see that the flow has begun */ 652eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky *state |= HT_ADDBA_REQUESTED_MSK; 653eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 654eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (local->ops->ampdu_action) 655eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, 656eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra, tid, &start_seq_num); 657eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 658eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (ret) { 659eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* No need to requeue the packets in the agg queue, since we 660eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * held the tx lock: no packet could be enqueued to the newly 661eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * allocated queue */ 6629e7234923789897858e1a475c579b5e2e6ad5b74Ron Rindjunsky ieee80211_ht_agg_queue_remove(local, sta, tid, 0); 663eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG 664cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky printk(KERN_DEBUG "BA request denied - HW unavailable for" 665cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky " tid %d\n", tid); 666eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */ 667eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky *state = HT_AGG_STATE_IDLE; 668cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky goto start_ba_err; 669eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 670eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 671eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* Will put all the packets in the new SW queue */ 6729e7234923789897858e1a475c579b5e2e6ad5b74Ron Rindjunsky ieee80211_requeue(local, ieee802_1d_to_ac[tid]); 673eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_unlock_bh(&local->mdev->queue_lock); 674eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 675eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* send an addBA request */ 676eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky sta->ampdu_mlme.dialog_token_allocator++; 677cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid]->dialog_token = 678eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky sta->ampdu_mlme.dialog_token_allocator; 679cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; 680eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 681d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg ieee80211_send_addba_request(sta->sdata->dev, ra, tid, 682cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid]->dialog_token, 683cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid]->ssn, 684eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 0x40, 5000); 685eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 686eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* activate the timer for the recipient's addBA response */ 687cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = 688eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky jiffies + ADDBA_RESP_INTERVAL; 689cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); 690eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); 691cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky goto start_ba_exit; 692eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 693cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunskystart_ba_err: 694cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky kfree(sta->ampdu_mlme.tid_tx[tid]); 695cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid] = NULL; 696cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky spin_unlock_bh(&local->mdev->queue_lock); 697cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky ret = -EBUSY; 698eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskystart_ba_exit: 69907346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg spin_unlock_bh(&sta->lock); 700d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 701eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return ret; 702eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky} 703eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_start_tx_ba_session); 704eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 705eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyint ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, 706eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky u8 *ra, u16 tid, 707eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky enum ieee80211_back_parties initiator) 708eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{ 709eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_local *local = hw_to_local(hw); 710eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct sta_info *sta; 711eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky u8 *state; 712eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky int ret = 0; 713eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky DECLARE_MAC_BUF(mac); 714eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 715eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (tid >= STA_TID_NUM) 716eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return -EINVAL; 717eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 718d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_lock(); 719eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky sta = sta_info_get(local, ra); 720d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg if (!sta) { 721d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 722eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return -ENOENT; 723d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg } 724eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 725eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* check if the TID is in aggregation */ 726cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky state = &sta->ampdu_mlme.tid_state_tx[tid]; 72707346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg spin_lock_bh(&sta->lock); 728eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 729eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (*state != HT_AGG_STATE_OPERATIONAL) { 730eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ret = -ENOENT; 731eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky goto stop_BA_exit; 732eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 733eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 734513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG 735513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky printk(KERN_DEBUG "Tx BA session stop requested for %s tid %u\n", 736513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky print_mac(mac, ra), tid); 737513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */ 738513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky 739eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]); 740eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 741eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky *state = HT_AGG_STATE_REQ_STOP_BA_MSK | 742eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky (initiator << HT_AGG_STATE_INITIATOR_SHIFT); 743eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 744eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (local->ops->ampdu_action) 745eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP, 746eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra, tid, NULL); 747eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 748eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* case HW denied going back to legacy */ 749eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (ret) { 750eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky WARN_ON(ret != -EBUSY); 751eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky *state = HT_AGG_STATE_OPERATIONAL; 752eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); 753eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky goto stop_BA_exit; 754eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 755eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 756eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskystop_BA_exit: 75707346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg spin_unlock_bh(&sta->lock); 758d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 759eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return ret; 760eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky} 761eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_stop_tx_ba_session); 762eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 763eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyvoid ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) 764eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{ 765eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_local *local = hw_to_local(hw); 766eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct sta_info *sta; 767eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky u8 *state; 768eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky DECLARE_MAC_BUF(mac); 769eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 770eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (tid >= STA_TID_NUM) { 771eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", 772eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky tid, STA_TID_NUM); 773eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return; 774eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 775eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 776d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_lock(); 777eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky sta = sta_info_get(local, ra); 778eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (!sta) { 779d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 780eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "Could not find station: %s\n", 781eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky print_mac(mac, ra)); 782eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return; 783eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 784eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 785cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky state = &sta->ampdu_mlme.tid_state_tx[tid]; 78607346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg spin_lock_bh(&sta->lock); 787eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 788eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (!(*state & HT_ADDBA_REQUESTED_MSK)) { 789eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", 790eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky *state); 79107346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg spin_unlock_bh(&sta->lock); 792d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 793eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return; 794eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 795eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 796eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK); 797eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 798eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky *state |= HT_ADDBA_DRV_READY_MSK; 799eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 800eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (*state == HT_AGG_STATE_OPERATIONAL) { 801eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); 802eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); 803eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 80407346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg spin_unlock_bh(&sta->lock); 805d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 806eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky} 807eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_start_tx_ba_cb); 808eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 809eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyvoid ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) 810eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{ 811eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_local *local = hw_to_local(hw); 812eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct sta_info *sta; 813eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky u8 *state; 814eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky int agg_queue; 815eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky DECLARE_MAC_BUF(mac); 816eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 817eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (tid >= STA_TID_NUM) { 818eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", 819eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky tid, STA_TID_NUM); 820eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return; 821eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 822eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 823513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG 824513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky printk(KERN_DEBUG "Stopping Tx BA session for %s tid %d\n", 825eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky print_mac(mac, ra), tid); 826513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */ 827eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 828d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_lock(); 829eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky sta = sta_info_get(local, ra); 830eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (!sta) { 831eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "Could not find station: %s\n", 832eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky print_mac(mac, ra)); 833d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 834eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return; 835eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 836cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky state = &sta->ampdu_mlme.tid_state_tx[tid]; 837eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 83807346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg spin_lock_bh(&sta->lock); 839eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { 840eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); 84107346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg spin_unlock_bh(&sta->lock); 842d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 843eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return; 844eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 845eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 846eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (*state & HT_AGG_STATE_INITIATOR_MSK) 847d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg ieee80211_send_delba(sta->sdata->dev, ra, tid, 848eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); 849eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 850eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky agg_queue = sta->tid_to_tx_q[tid]; 851eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 852eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* avoid ordering issues: we are the only one that can modify 853eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * the content of the qdiscs */ 854eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_lock_bh(&local->mdev->queue_lock); 855eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* remove the queue for this aggregation */ 8569e7234923789897858e1a475c579b5e2e6ad5b74Ron Rindjunsky ieee80211_ht_agg_queue_remove(local, sta, tid, 1); 857eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_unlock_bh(&local->mdev->queue_lock); 858eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 859eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* we just requeued the all the frames that were in the removed 860eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * queue, and since we might miss a softirq we do netif_schedule. 861eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * ieee80211_wake_queue is not used here as this queue is not 862eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * necessarily stopped */ 863eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky netif_schedule(local->mdev); 864eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky *state = HT_AGG_STATE_IDLE; 865cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.addba_req_num[tid] = 0; 866cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky kfree(sta->ampdu_mlme.tid_tx[tid]); 867cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid] = NULL; 86807346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg spin_unlock_bh(&sta->lock); 869eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 870d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 871eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky} 872eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_stop_tx_ba_cb); 873eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 874eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyvoid ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, 875eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky const u8 *ra, u16 tid) 876eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{ 877eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_local *local = hw_to_local(hw); 878eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_ra_tid *ra_tid; 879eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct sk_buff *skb = dev_alloc_skb(0); 880eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 881eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (unlikely(!skb)) { 882eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (net_ratelimit()) 883eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_WARNING "%s: Not enough memory, " 884eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky "dropping start BA session", skb->dev->name); 885eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return; 886eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 887eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid = (struct ieee80211_ra_tid *) &skb->cb; 888eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky memcpy(&ra_tid->ra, ra, ETH_ALEN); 889eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid->tid = tid; 890eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 891eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky skb->pkt_type = IEEE80211_ADDBA_MSG; 892eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky skb_queue_tail(&local->skb_queue, skb); 893eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky tasklet_schedule(&local->tasklet); 894eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky} 895eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); 896eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 897eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyvoid ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, 898eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky const u8 *ra, u16 tid) 899eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{ 900eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_local *local = hw_to_local(hw); 901eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_ra_tid *ra_tid; 902eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct sk_buff *skb = dev_alloc_skb(0); 903eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 904eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (unlikely(!skb)) { 905eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (net_ratelimit()) 906eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_WARNING "%s: Not enough memory, " 907eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky "dropping stop BA session", skb->dev->name); 908eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return; 909eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 910eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid = (struct ieee80211_ra_tid *) &skb->cb; 911eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky memcpy(&ra_tid->ra, ra, ETH_ALEN); 912eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid->tid = tid; 913eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 914eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky skb->pkt_type = IEEE80211_DELBA_MSG; 915eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky skb_queue_tail(&local->skb_queue, skb); 916eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky tasklet_schedule(&local->tasklet); 917eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky} 918eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe); 919eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 920f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void ieee80211_set_multicast_list(struct net_device *dev) 921f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 922f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 923f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 9244150c57212ad134765dd78c654a4b9906252b66dJohannes Berg int allmulti, promisc, sdata_allmulti, sdata_promisc; 925f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 9264150c57212ad134765dd78c654a4b9906252b66dJohannes Berg allmulti = !!(dev->flags & IFF_ALLMULTI); 9274150c57212ad134765dd78c654a4b9906252b66dJohannes Berg promisc = !!(dev->flags & IFF_PROMISC); 928b52f2198ac889561d341c6990d669a671f93f450Johannes Berg sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); 929b52f2198ac889561d341c6990d669a671f93f450Johannes Berg sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC); 9304150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 9314150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (allmulti != sdata_allmulti) { 9324150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (dev->flags & IFF_ALLMULTI) 93353918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg atomic_inc(&local->iff_allmultis); 9344150c57212ad134765dd78c654a4b9906252b66dJohannes Berg else 93553918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg atomic_dec(&local->iff_allmultis); 93613262ffd4902805acad2618c12b41fcaa6c50791Jiri Slaby sdata->flags ^= IEEE80211_SDATA_ALLMULTI; 937f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 9384150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 9394150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (promisc != sdata_promisc) { 9404150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (dev->flags & IFF_PROMISC) 94153918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg atomic_inc(&local->iff_promiscs); 9424150c57212ad134765dd78c654a4b9906252b66dJohannes Berg else 94353918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg atomic_dec(&local->iff_promiscs); 94413262ffd4902805acad2618c12b41fcaa6c50791Jiri Slaby sdata->flags ^= IEEE80211_SDATA_PROMISC; 945f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 9464150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 9474150c57212ad134765dd78c654a4b9906252b66dJohannes Berg dev_mc_sync(local->mdev, dev); 948f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 949f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 9503b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemmingerstatic const struct header_ops ieee80211_header_ops = { 9513b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger .create = eth_header, 9523b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger .parse = header_parse_80211, 9533b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger .rebuild = eth_rebuild_header, 9543b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger .cache = eth_header_cache, 9553b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger .cache_update = eth_header_cache_update, 9563b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger}; 9573b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger 958f9d540ee5f7e480339911df8d7389ef4c435ab54Johannes Berg/* Must not be called for mdev */ 959b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergvoid ieee80211_if_setup(struct net_device *dev) 960f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 961b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg ether_setup(dev); 962b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->hard_start_xmit = ieee80211_subif_start_xmit; 963b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->wireless_handlers = &ieee80211_iw_handler_def; 964b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->set_multicast_list = ieee80211_set_multicast_list; 965b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->change_mtu = ieee80211_change_mtu; 966b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->open = ieee80211_open; 967b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->stop = ieee80211_stop; 968b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->destructor = ieee80211_if_free; 969b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 970f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 971b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg/* everything else */ 972b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg 973b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic int __ieee80211_if_config(struct net_device *dev, 974e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct sk_buff *beacon) 975b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{ 976b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 977b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 978b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_if_conf conf; 979b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg 980b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (!local->ops->config_interface || !netif_running(dev)) 981f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 982f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 983b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg memset(&conf, 0, sizeof(conf)); 98451fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg conf.type = sdata->vif.type; 98551fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_STA || 98651fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { 9874150c57212ad134765dd78c654a4b9906252b66dJohannes Berg conf.bssid = sdata->u.sta.bssid; 988b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg conf.ssid = sdata->u.sta.ssid; 989b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg conf.ssid_len = sdata->u.sta.ssid_len; 990902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg } else if (ieee80211_vif_is_mesh(&sdata->vif)) { 991f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo conf.beacon = beacon; 992f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo ieee80211_start_mesh(dev); 99351fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { 994b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg conf.ssid = sdata->u.ap.ssid; 995b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg conf.ssid_len = sdata->u.ap.ssid_len; 996b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg conf.beacon = beacon; 997f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 998b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return local->ops->config_interface(local_to_hw(local), 99932bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg &sdata->vif, &conf); 1000f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1001f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1002b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergint ieee80211_if_config(struct net_device *dev) 1003b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{ 1004f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1005f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 1006f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT && 1007f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo (local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) 1008f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo return ieee80211_if_config_beacon(dev); 1009e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg return __ieee80211_if_config(dev, NULL); 1010b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 1011f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1012b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergint ieee80211_if_config_beacon(struct net_device *dev) 1013f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1014f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 101532bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1016b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct sk_buff *skb; 1017f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1018b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) 1019f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 1020e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif); 1021b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (!skb) 1022b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return -ENOMEM; 1023e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg return __ieee80211_if_config(dev, skb); 1024b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 1025f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1026b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergint ieee80211_hw_config(struct ieee80211_local *local) 1027b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{ 1028b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_channel *chan; 1029b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg int ret = 0; 1030f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 10318318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg if (local->sta_sw_scanning) 1032b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg chan = local->scan_channel; 10338318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg else 1034b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg chan = local->oper_channel; 1035f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 10368318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.channel = chan; 10378318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 10388318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg if (!local->hw.conf.power_level) 10398318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.power_level = chan->max_power; 10408318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg else 10418318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.power_level = min(chan->max_power, 10428318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.power_level); 10438318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 10448318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.max_antenna_gain = chan->max_antenna_gain; 1045f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1046b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 10478318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg printk(KERN_DEBUG "%s: HW CONFIG: freq=%d\n", 10488318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg wiphy_name(local->hw.wiphy), chan->center_freq); 10498318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg#endif 1050b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg 1051f7c4daed99fba15e4e48df464031f4ac7c32e4c9Michael Buesch if (local->open_count) 1052b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg ret = local->ops->config(local_to_hw(local), &local->hw.conf); 1053f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1054b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return ret; 1055b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 1056f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1057d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky/** 105838668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler * ieee80211_handle_ht should be used only after legacy configuration 105938668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler * has been determined namely band, as ht configuration depends upon 106038668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler * the hardware's HT abilities for a _specific_ band. 1061d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky */ 106238668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkleru32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, 1063d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky struct ieee80211_ht_info *req_ht_cap, 1064d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky struct ieee80211_ht_bss_info *req_bss_cap) 1065d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky{ 1066d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky struct ieee80211_conf *conf = &local->hw.conf; 10678318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg struct ieee80211_supported_band *sband; 106838668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler struct ieee80211_ht_info ht_conf; 106938668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler struct ieee80211_ht_bss_info ht_bss_conf; 107038668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler u32 changed = 0; 1071edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky int i; 1072edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky u8 max_tx_streams = IEEE80211_HT_CAP_MAX_STREAMS; 1073edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky u8 tx_mcs_set_cap; 1074d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky 10758318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg sband = local->hw.wiphy->bands[conf->channel->band]; 10768318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 1077edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info)); 1078edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info)); 1079edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky 1080d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky /* HT is not supported */ 10818318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg if (!sband->ht_info.ht_supported) { 1082d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; 1083edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky goto out; 1084d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky } 1085d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky 1086edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky /* disable HT */ 1087edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky if (!enable_ht) { 1088edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) 108938668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler changed |= BSS_CHANGED_HT; 1090edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; 1091edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky conf->ht_conf.ht_supported = 0; 1092edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky goto out; 1093edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky } 109438668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 109538668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 1096edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) 1097edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky changed |= BSS_CHANGED_HT; 109838668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 1099edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE; 1100edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_conf.ht_supported = 1; 110138668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 1102edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; 1103edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS); 1104edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS; 1105edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_bss_conf.primary_channel = req_bss_cap->primary_channel; 1106edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_bss_conf.bss_cap = req_bss_cap->bss_cap; 1107edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; 110838668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 1109edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_conf.ampdu_factor = req_ht_cap->ampdu_factor; 1110edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_conf.ampdu_density = req_ht_cap->ampdu_density; 111138668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 1112edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky /* Bits 96-100 */ 1113edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky tx_mcs_set_cap = sband->ht_info.supp_mcs_set[12]; 1114edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky 1115edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky /* configure suppoerted Tx MCS according to requested MCS 1116edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky * (based in most cases on Rx capabilities of peer) and self 1117edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky * Tx MCS capabilities (as defined by low level driver HW 1118edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky * Tx capabilities) */ 1119edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky if (!(tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_DEFINED)) 1120edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky goto check_changed; 1121d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky 1122edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky /* Counting from 0 therfore + 1 */ 1123edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_RX_DIFF) 1124edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky max_tx_streams = ((tx_mcs_set_cap & 1125edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky IEEE80211_HT_CAP_MCS_TX_STREAMS) >> 2) + 1; 1126edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky 1127edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky for (i = 0; i < max_tx_streams; i++) 1128edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_conf.supp_mcs_set[i] = 1129edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky sband->ht_info.supp_mcs_set[i] & 1130edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky req_ht_cap->supp_mcs_set[i]; 1131edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky 1132edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_UEQM) 1133edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky for (i = IEEE80211_SUPP_MCS_SET_UEQM; 1134edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky i < IEEE80211_SUPP_MCS_SET_LEN; i++) 1135edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky ht_conf.supp_mcs_set[i] = 1136edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky sband->ht_info.supp_mcs_set[i] & 1137edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky req_ht_cap->supp_mcs_set[i]; 1138edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky 1139edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunskycheck_changed: 1140edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky /* if bss configuration changed store the new one */ 1141edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) || 1142edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) { 1143edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky changed |= BSS_CHANGED_HT; 1144edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf)); 1145edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf)); 1146edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunsky } 1147edcdf8b21ac920e06b4180246123fe43b022e020Ron Rindjunskyout: 114838668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler return changed; 1149d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky} 1150d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky 1151471b3efdfccc257591331724145f8ccf8b3217e1Johannes Bergvoid ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, 1152471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg u32 changed) 1153d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake{ 1154471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg struct ieee80211_local *local = sdata->local; 1155471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg 1156471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg if (!changed) 1157471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg return; 1158471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg 1159471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg if (local->ops->bss_info_changed) 1160471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg local->ops->bss_info_changed(local_to_hw(local), 1161471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg &sdata->vif, 1162471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg &sdata->bss_conf, 1163471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg changed); 1164d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake} 1165d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake 1166d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drakevoid ieee80211_reset_erp_info(struct net_device *dev) 1167d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake{ 1168d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1169d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake 1170471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg sdata->bss_conf.use_cts_prot = 0; 1171471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg sdata->bss_conf.use_short_preamble = 0; 1172471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg ieee80211_bss_info_change_notify(sdata, 1173471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg BSS_CHANGED_ERP_CTS_PROT | 1174471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg BSS_CHANGED_ERP_PREAMBLE); 1175d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake} 1176d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake 1177f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, 1178e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct sk_buff *skb) 1179f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1180f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 1181e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1182f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc int tmp; 1183f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1184f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb->dev = local->mdev; 1185f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb->pkt_type = IEEE80211_TX_STATUS_MSG; 1186e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ? 1187f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc &local->skb_queue : &local->skb_queue_unreliable, skb); 1188f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tmp = skb_queue_len(&local->skb_queue) + 1189f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_len(&local->skb_queue_unreliable); 1190f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT && 1191f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc (skb = skb_dequeue(&local->skb_queue_unreliable))) { 1192f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb_irq(skb); 1193f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tmp--; 1194f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc I802_DEBUG_INC(local->tx_status_drop); 1195f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1196f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_schedule(&local->tasklet); 1197f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1198f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_tx_status_irqsafe); 1199f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1200f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void ieee80211_tasklet_handler(unsigned long data) 1201f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1202f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = (struct ieee80211_local *) data; 1203f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sk_buff *skb; 1204f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_rx_status rx_status; 1205eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_ra_tid *ra_tid; 1206f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1207f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc while ((skb = skb_dequeue(&local->skb_queue)) || 1208f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc (skb = skb_dequeue(&local->skb_queue_unreliable))) { 1209f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc switch (skb->pkt_type) { 1210f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case IEEE80211_RX_MSG: 1211f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* status is in skb->cb */ 1212f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memcpy(&rx_status, skb->cb, sizeof(rx_status)); 121351fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg /* Clear skb->pkt_type in order to not confuse kernel 1214f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * netstack. */ 1215f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb->pkt_type = 0; 1216f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc __ieee80211_rx(local_to_hw(local), skb, &rx_status); 1217f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 1218f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case IEEE80211_TX_STATUS_MSG: 1219f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb->pkt_type = 0; 1220e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_tx_status(local_to_hw(local), skb); 1221f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 1222eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky case IEEE80211_DELBA_MSG: 1223eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid = (struct ieee80211_ra_tid *) &skb->cb; 1224eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ieee80211_stop_tx_ba_cb(local_to_hw(local), 1225eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid->ra, ra_tid->tid); 1226eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky dev_kfree_skb(skb); 1227eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky break; 1228eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky case IEEE80211_ADDBA_MSG: 1229eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid = (struct ieee80211_ra_tid *) &skb->cb; 1230eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ieee80211_start_tx_ba_cb(local_to_hw(local), 1231eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid->ra, ra_tid->tid); 1232eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky dev_kfree_skb(skb); 1233eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky break ; 1234f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc default: /* should never get here! */ 1235f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_ERR "%s: Unknown message type (%d)\n", 1236dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg wiphy_name(local->hw.wiphy), skb->pkt_type); 1237f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb(skb); 1238f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 1239f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1240f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1241f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1242f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1243f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to 1244f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * make a prepared TX frame (one that has been given to hw) to look like brand 1245f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * new IEEE 802.11 frame that is ready to go through TX processing again. 1246f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * Also, tx_packet_data in cb is restored from tx_control. */ 1247f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void ieee80211_remove_tx_extra(struct ieee80211_local *local, 1248f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_key *key, 1249e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct sk_buff *skb) 1250f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1251f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc int hdrlen, iv_len, mic_len; 1252e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1253e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg 1254e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg info->flags &= IEEE80211_TX_CTL_REQ_TX_STATUS | 1255e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg IEEE80211_TX_CTL_DO_NOT_ENCRYPT | 1256e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg IEEE80211_TX_CTL_REQUEUE | 1257e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg IEEE80211_TX_CTL_EAPOL_FRAME; 1258f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1259f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc hdrlen = ieee80211_get_hdrlen_from_skb(skb); 1260f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1261f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (!key) 1262f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto no_key; 1263f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 12648f20fc24986a083228823d9b68adca20714b254eJohannes Berg switch (key->conf.alg) { 1265f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case ALG_WEP: 1266f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc iv_len = WEP_IV_LEN; 1267f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc mic_len = WEP_ICV_LEN; 1268f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 1269f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case ALG_TKIP: 1270f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc iv_len = TKIP_IV_LEN; 1271f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc mic_len = TKIP_ICV_LEN; 1272f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 1273f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case ALG_CCMP: 1274f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc iv_len = CCMP_HDR_LEN; 1275f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc mic_len = CCMP_MIC_LEN; 1276f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 1277f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc default: 1278f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto no_key; 1279f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1280f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 12818f20fc24986a083228823d9b68adca20714b254eJohannes Berg if (skb->len >= mic_len && 128211a843b7e16062389c53ba393c7913956e034eb2Johannes Berg !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) 1283f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_trim(skb, skb->len - mic_len); 1284f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (skb->len >= iv_len && skb->len > hdrlen) { 1285f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memmove(skb->data + iv_len, skb->data, hdrlen); 1286f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_pull(skb, iv_len); 1287f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1288f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1289f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencno_key: 1290f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc { 1291f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 1292f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc u16 fc = le16_to_cpu(hdr->frame_control); 1293f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if ((fc & 0x8C) == 0x88) /* QoS Control Field */ { 1294f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc fc &= ~IEEE80211_STYPE_QOS_DATA; 1295f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc hdr->frame_control = cpu_to_le16(fc); 1296f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memmove(skb->data + 2, skb->data, hdrlen - 2); 1297f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_pull(skb, 2); 1298f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1299f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1300f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1301f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1302d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Bergstatic void ieee80211_handle_filtered_frame(struct ieee80211_local *local, 1303d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg struct sta_info *sta, 1304e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct sk_buff *skb) 1305d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg{ 1306e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1307e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg 1308d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg sta->tx_filtered_count++; 1309d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 1310d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg /* 1311d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * Clear the TX filter mask for this STA when sending the next 1312d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * packet. If the STA went to power save mode, this will happen 1313d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * happen when it wakes up for the next time. 1314d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg */ 131507346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg set_sta_flags(sta, WLAN_STA_CLEAR_PS_FILT); 1316d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 1317d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg /* 1318d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * This code races in the following way: 1319d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * 1320d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (1) STA sends frame indicating it will go to sleep and does so 1321d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (2) hardware/firmware adds STA to filter list, passes frame up 1322d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (3) hardware/firmware processes TX fifo and suppresses a frame 1323d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (4) we get TX status before having processed the frame and 1324d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * knowing that the STA has gone to sleep. 1325d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * 1326d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * This is actually quite unlikely even when both those events are 1327d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * processed from interrupts coming in quickly after one another or 1328d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * even at the same time because we queue both TX status events and 1329d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * RX frames to be processed by a tasklet and process them in the 1330d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * same order that they were received or TX status last. Hence, there 1331d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * is no race as long as the frame RX is processed before the next TX 1332d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * status, which drivers can ensure, see below. 1333d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * 1334d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * Note that this can only happen if the hardware or firmware can 1335d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * actually add STAs to the filter list, if this is done by the 1336d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * driver in response to set_tim() (which will only reduce the race 1337d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * this whole filtering tries to solve, not completely solve it) 1338d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * this situation cannot happen. 1339d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * 1340d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * To completely solve this race drivers need to make sure that they 1341d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (a) don't mix the irq-safe/not irq-safe TX status/RX processing 1342d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * functions and 1343d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (b) always process RX events before TX status events if ordering 1344d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * can be unknown, for example with different interrupt status 1345d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * bits. 1346d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg */ 134707346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg if (test_sta_flags(sta, WLAN_STA_PS) && 1348d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { 1349e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_remove_tx_extra(local, sta->key, skb); 1350d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg skb_queue_tail(&sta->tx_filtered, skb); 1351d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg return; 1352d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg } 1353d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 135407346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg if (!test_sta_flags(sta, WLAN_STA_PS) && 1355e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg !(info->flags & IEEE80211_TX_CTL_REQUEUE)) { 1356d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg /* Software retry the packet once */ 1357e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg info->flags |= IEEE80211_TX_CTL_REQUEUE; 1358e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_remove_tx_extra(local, sta->key, skb); 1359d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg dev_queue_xmit(skb); 1360d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg return; 1361d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg } 1362d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 1363d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg if (net_ratelimit()) 1364d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg printk(KERN_DEBUG "%s: dropped TX filtered frame, " 1365d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg "queue_len=%d PS=%d @%lu\n", 1366d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg wiphy_name(local->hw.wiphy), 1367d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg skb_queue_len(&sta->tx_filtered), 136807346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg !!test_sta_flags(sta, WLAN_STA_PS), jiffies); 1369d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg dev_kfree_skb(skb); 1370d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg} 1371d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 1372e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Bergvoid ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) 1373f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1374f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sk_buff *skb2; 1375f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 1376f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 1377e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1378f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc u16 frag, type; 1379b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg struct ieee80211_tx_status_rtap_hdr *rthdr; 1380b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg struct ieee80211_sub_if_data *sdata; 13813d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu struct net_device *prev_dev = NULL; 1382f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1383d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_lock(); 1384d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg 1385e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->status.excessive_retries) { 1386f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sta_info *sta; 1387f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta = sta_info_get(local, hdr->addr1); 1388f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (sta) { 138907346f81e87d6e4cca7ae9adfa711d0c61c87b56Johannes Berg if (test_sta_flags(sta, WLAN_STA_PS)) { 1390d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg /* 1391d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * The STA is in power save mode, so assume 1392f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * that this TX packet failed because of that. 1393f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc */ 1394e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_handle_filtered_frame(local, sta, skb); 1395d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 1396d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg return; 1397f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1398f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1399f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1400f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1401e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { 1402f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sta_info *sta; 1403f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta = sta_info_get(local, hdr->addr1); 1404f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (sta) { 1405e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_handle_filtered_frame(local, sta, skb); 1406d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 1407f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return; 1408f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 14091abbe498e4b5e4f2000dfc30a0fa25be9553530eMattias Nissler } else 1410e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg rate_control_tx_status(local->mdev, skb); 1411f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1412d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 1413d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg 1414f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_led_tx(local, 0); 1415f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1416f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* SNMP counters 1417f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * Fragments are passed to low-level drivers as separate skbs, so these 1418f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * are actually fragments, not frames. Update frame counters only for 1419f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * the first fragment of the frame. */ 1420f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1421f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; 1422f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE; 1423f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1424e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->flags & IEEE80211_TX_STAT_ACK) { 1425f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (frag == 0) { 1426f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11TransmittedFrameCount++; 1427f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (is_multicast_ether_addr(hdr->addr1)) 1428f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11MulticastTransmittedFrameCount++; 1429e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->status.retry_count > 0) 1430f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11RetryCount++; 1431e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->status.retry_count > 1) 1432f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11MultipleRetryCount++; 1433f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1434f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1435f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* This counter shall be incremented for an acknowledged MPDU 1436f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * with an individual address in the address 1 field or an MPDU 1437f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * with a multicast address in the address 1 field of type Data 1438f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * or Management. */ 1439f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (!is_multicast_ether_addr(hdr->addr1) || 1440f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc type == IEEE80211_FTYPE_DATA || 1441f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc type == IEEE80211_FTYPE_MGMT) 1442f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11TransmittedFragmentCount++; 1443f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } else { 1444f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (frag == 0) 1445f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11FailedCount++; 1446f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1447f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1448b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg /* this was a transmitted frame, but now we want to reuse it */ 1449b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg skb_orphan(skb); 1450b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 14513d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu /* 14523d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu * This is a bit racy but we can avoid a lot of work 14533d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu * with this test... 14543d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu */ 14553d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (!local->monitors && !local->cooked_mntrs) { 1456f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb(skb); 1457f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return; 1458f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1459f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1460b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg /* send frame to monitor interfaces now */ 1461f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1462b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg if (skb_headroom(skb) < sizeof(*rthdr)) { 1463b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg printk(KERN_ERR "ieee80211_tx_status: headroom too small\n"); 1464f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb(skb); 1465f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return; 1466f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1467f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1468988c0f723d0b1abb399e6e71d8bf3f8bf1949a70Johannes Berg rthdr = (struct ieee80211_tx_status_rtap_hdr *) 1469b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg skb_push(skb, sizeof(*rthdr)); 1470b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 1471b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg memset(rthdr, 0, sizeof(*rthdr)); 1472b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); 1473b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->hdr.it_present = 1474b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | 1475b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg (1 << IEEE80211_RADIOTAP_DATA_RETRIES)); 1476b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 1477e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (!(info->flags & IEEE80211_TX_STAT_ACK) && 1478b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg !is_multicast_ether_addr(hdr->addr1)) 1479b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); 1480b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 1481e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) && 1482e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) 1483b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); 1484e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg else if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) 1485b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); 1486b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 1487e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg rthdr->data_retries = info->status.retry_count; 1488b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 14893d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu /* XXX: is this sufficient for BPF? */ 14903d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb_set_mac_header(skb, 0); 14913d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb->ip_summed = CHECKSUM_UNNECESSARY; 14923d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb->pkt_type = PACKET_OTHERHOST; 14933d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb->protocol = htons(ETH_P_802_2); 14943d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu memset(skb->cb, 0, sizeof(skb->cb)); 14953d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 149679010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg rcu_read_lock(); 149779010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg list_for_each_entry_rcu(sdata, &local->interfaces, list) { 149851fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) { 1499b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg if (!netif_running(sdata->dev)) 1500b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg continue; 15013d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 15023d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (prev_dev) { 150379010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg skb2 = skb_clone(skb, GFP_ATOMIC); 15043d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (skb2) { 15053d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb2->dev = prev_dev; 15063d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu netif_rx(skb2); 15073d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 15083d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 15093d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 15103d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu prev_dev = sdata->dev; 1511b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg } 1512b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg } 15133d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (prev_dev) { 15143d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb->dev = prev_dev; 15153d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu netif_rx(skb); 15163d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb = NULL; 15173d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 151879010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg rcu_read_unlock(); 15193d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu dev_kfree_skb(skb); 1520f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1521f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_tx_status); 1522f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1523f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstruct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, 1524f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc const struct ieee80211_ops *ops) 1525f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1526f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local; 1527f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc int priv_size; 1528f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct wiphy *wiphy; 1529f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1530f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* Ensure 32-byte alignment of our private data and hw private data. 1531f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * We use the wiphy priv data for both our ieee80211_local and for 1532f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * the driver's private data 1533f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * 1534f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * In memory it'll be like this: 1535f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * 1536f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * +-------------------------+ 1537f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * | struct wiphy | 1538f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * +-------------------------+ 1539f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * | struct ieee80211_local | 1540f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * +-------------------------+ 1541f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * | driver's private data | 1542f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * +-------------------------+ 1543f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * 1544f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc */ 1545f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc priv_size = ((sizeof(struct ieee80211_local) + 1546f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) + 1547f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc priv_data_len; 1548f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1549f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy = wiphy_new(&mac80211_config_ops, priv_size); 1550f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1551f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (!wiphy) 1552f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return NULL; 1553f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1554f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy->privid = mac80211_wiphy_privid; 1555f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1556f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local = wiphy_priv(wiphy); 1557f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.wiphy = wiphy; 1558f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1559f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.priv = (char *)local + 1560f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ((sizeof(struct ieee80211_local) + 1561f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); 1562f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 15634480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg BUG_ON(!ops->tx); 15644150c57212ad134765dd78c654a4b9906252b66dJohannes Berg BUG_ON(!ops->start); 15654150c57212ad134765dd78c654a4b9906252b66dJohannes Berg BUG_ON(!ops->stop); 15664480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg BUG_ON(!ops->config); 15674480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg BUG_ON(!ops->add_interface); 15684150c57212ad134765dd78c654a4b9906252b66dJohannes Berg BUG_ON(!ops->remove_interface); 15694150c57212ad134765dd78c654a4b9906252b66dJohannes Berg BUG_ON(!ops->configure_filter); 1570f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->ops = ops; 1571f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1572f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.queues = 1; /* default */ 1573f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1574f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->bridge_packets = 1; 1575f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1576f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; 1577f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; 1578f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->short_retry_limit = 7; 1579f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->long_retry_limit = 4; 1580f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.conf.radio_enabled = 1; 1581f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 158279010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg INIT_LIST_HEAD(&local->interfaces); 1583f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1584b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg spin_lock_init(&local->key_lock); 1585b16bd15c379410f2aa47837aa4a0de5712856ad5Johannes Berg 1586f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work); 1587f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1588f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta_info_init(local); 1589f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1590f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, 1591f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc (unsigned long)local); 1592f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_disable(&local->tx_pending_tasklet); 1593f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1594f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_init(&local->tasklet, 1595f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_tasklet_handler, 1596f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc (unsigned long) local); 1597f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_disable(&local->tasklet); 1598f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1599f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_head_init(&local->skb_queue); 1600f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_head_init(&local->skb_queue_unreliable); 1601f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1602f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return local_to_hw(local); 1603f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1604f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_alloc_hw); 1605f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1606f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencint ieee80211_register_hw(struct ieee80211_hw *hw) 1607f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1608f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 1609f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc const char *name; 1610f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc int result; 16118318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg enum ieee80211_band band; 161296d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg struct net_device *mdev; 161396d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg struct ieee80211_sub_if_data *sdata; 16148318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 16158318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg /* 16168318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg * generic code guarantees at least one band, 16178318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg * set this very early because much code assumes 16188318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg * that hw.conf.channel is assigned 16198318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg */ 16208318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 16218318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg struct ieee80211_supported_band *sband; 16228318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 16238318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg sband = local->hw.wiphy->bands[band]; 16248318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg if (sband) { 16258318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg /* init channel we're on */ 16268318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.channel = 16278318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->oper_channel = 16288318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->scan_channel = &sband->channels[0]; 16298318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg break; 16308318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg } 16318318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg } 1632f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1633f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = wiphy_register(local->hw.wiphy); 1634f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) 1635f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return result; 1636f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 163796d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg /* for now, mdev needs sub_if_data :/ */ 163896d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev = alloc_netdev(sizeof(struct ieee80211_sub_if_data), 163996d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg "wmaster%d", ether_setup); 164096d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg if (!mdev) 164196d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg goto fail_mdev_alloc; 164296d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 164396d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg sdata = IEEE80211_DEV_TO_SUB_IF(mdev); 164496d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->ieee80211_ptr = &sdata->wdev; 164596d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg sdata->wdev.wiphy = local->hw.wiphy; 164696d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 164796d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg local->mdev = mdev; 164896d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 164996d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg ieee80211_rx_bss_list_init(mdev); 165096d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 165196d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->hard_start_xmit = ieee80211_master_start_xmit; 165296d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->open = ieee80211_master_open; 165396d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->stop = ieee80211_master_stop; 165496d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->type = ARPHRD_IEEE80211; 165596d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->header_ops = &ieee80211_header_ops; 165696d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->set_multicast_list = ieee80211_master_set_multicast_list; 165796d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 165896d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg sdata->vif.type = IEEE80211_IF_TYPE_AP; 165996d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg sdata->dev = mdev; 166096d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg sdata->local = local; 166196d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg sdata->u.ap.force_unicast_rateidx = -1; 166296d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg sdata->u.ap.max_ratectrl_rateidx = -1; 166396d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg ieee80211_if_sdata_init(sdata); 166496d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 166596d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg /* no RCU needed since we're still during init phase */ 166696d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg list_add_tail(&sdata->list, &local->interfaces); 166796d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 1668f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc name = wiphy_dev(local->hw.wiphy)->driver->name; 1669f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.workqueue = create_singlethread_workqueue(name); 1670f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (!local->hw.workqueue) { 1671f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = -ENOMEM; 1672f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_workqueue; 1673f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1674f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1675b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg /* 1676b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg * The hardware needs headroom for sending the frame, 1677b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg * and we need some headroom for passing the frame to monitor 1678b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg * interfaces, but never both at the same time. 1679b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg */ 168033ccad35a21df51c0d23f3e3e88688524e7b51edJiri Benc local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom, 168133ccad35a21df51c0d23f3e3e88688524e7b51edJiri Benc sizeof(struct ieee80211_tx_status_rtap_hdr)); 1682b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 1683e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc debugfs_hw_add(local); 1684e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 1685f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.conf.beacon_int = 1000; 1686f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1687566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf local->wstats_flags |= local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC | 1688566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf IEEE80211_HW_SIGNAL_DB | 1689566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf IEEE80211_HW_SIGNAL_DBM) ? 1690f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID; 1691566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf local->wstats_flags |= local->hw.flags & IEEE80211_HW_NOISE_DBM ? 1692f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID; 1693566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) 1694f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->wstats_flags |= IW_QUAL_DBM; 1695f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1696f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = sta_info_start(local); 1697f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) 1698f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_sta_info; 1699f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1700f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_lock(); 1701f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = dev_alloc_name(local->mdev, local->mdev->name); 1702f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) 1703f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_dev; 1704f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1705f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); 1706f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy)); 1707f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1708f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = register_netdevice(local->mdev); 1709f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) 1710f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_dev; 1711f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1712e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev)); 17135b2812e925c8e976852867f8d760637c5926d817Johannes Berg ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP); 1714e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 1715830f903866a1611e9ce53f3e35202302bb938946Johannes Berg result = ieee80211_init_rate_ctrl_alg(local, 1716830f903866a1611e9ce53f3e35202302bb938946Johannes Berg hw->rate_control_algorithm); 1717f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) { 1718f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_DEBUG "%s: Failed to initialize rate control " 1719dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg "algorithm\n", wiphy_name(local->hw.wiphy)); 1720f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_rate; 1721f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1722f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1723f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = ieee80211_wep_init(local); 1724f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1725f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) { 1726f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_DEBUG "%s: Failed to initialize wep\n", 1727dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg wiphy_name(local->hw.wiphy)); 1728f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_wep; 1729f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1730f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1731e100bb64bf7cdeae7f742a65ee1985649a7fd1b4Johannes Berg if (hw->queues > IEEE80211_MAX_QUEUES) 1732e100bb64bf7cdeae7f742a65ee1985649a7fd1b4Johannes Berg hw->queues = IEEE80211_MAX_QUEUES; 1733e100bb64bf7cdeae7f742a65ee1985649a7fd1b4Johannes Berg if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES) 1734e100bb64bf7cdeae7f742a65ee1985649a7fd1b4Johannes Berg hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES; 1735e100bb64bf7cdeae7f742a65ee1985649a7fd1b4Johannes Berg 1736f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_install_qdisc(local->mdev); 1737f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1738f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* add one default STA interface */ 1739f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = ieee80211_if_add(local->mdev, "wlan%d", NULL, 1740ee3858551ae6d044578f598f8001db5f1a9fd52eLuis Carlos Cobo IEEE80211_IF_TYPE_STA, NULL); 1741f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result) 1742f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_WARNING "%s: Failed to add default virtual iface\n", 1743dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg wiphy_name(local->hw.wiphy)); 1744f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1745f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->reg_state = IEEE80211_DEV_REGISTERED; 1746f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_unlock(); 1747f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1748f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_led_init(local); 1749f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1750f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 1751f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1752f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_wep: 1753f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rate_control_deinitialize(local); 1754f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_rate: 1755e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev)); 1756f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc unregister_netdevice(local->mdev); 1757339a7c41c913035bf58579f6e47b4ba29da83795Pavel Emelyanov local->mdev = NULL; 1758f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_dev: 1759f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_unlock(); 1760f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta_info_stop(local); 1761f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_sta_info: 1762e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc debugfs_hw_del(local); 1763f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc destroy_workqueue(local->hw.workqueue); 1764f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_workqueue: 1765339a7c41c913035bf58579f6e47b4ba29da83795Pavel Emelyanov if (local->mdev != NULL) { 1766339a7c41c913035bf58579f6e47b4ba29da83795Pavel Emelyanov ieee80211_if_free(local->mdev); 1767339a7c41c913035bf58579f6e47b4ba29da83795Pavel Emelyanov local->mdev = NULL; 1768339a7c41c913035bf58579f6e47b4ba29da83795Pavel Emelyanov } 176996d510566e4908f77f03ff1436c78ae7162a17d0Johannes Bergfail_mdev_alloc: 1770f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy_unregister(local->hw.wiphy); 1771f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return result; 1772f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1773f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_register_hw); 1774f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1775f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_unregister_hw(struct ieee80211_hw *hw) 1776f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1777f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 1778f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_sub_if_data *sdata, *tmp; 1779f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1780f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_kill(&local->tx_pending_tasklet); 1781f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_kill(&local->tasklet); 1782f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1783f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_lock(); 1784f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1785f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc BUG_ON(local->reg_state != IEEE80211_DEV_REGISTERED); 1786f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1787f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->reg_state = IEEE80211_DEV_UNREGISTERED; 1788f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 178979010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg /* 179079010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * At this point, interface list manipulations are fine 179179010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * because the driver cannot be handing us frames any 179279010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * more and the tasklet is killed. 179379010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg */ 17945b2812e925c8e976852867f8d760637c5926d817Johannes Berg 17955b2812e925c8e976852867f8d760637c5926d817Johannes Berg /* 17965b2812e925c8e976852867f8d760637c5926d817Johannes Berg * First, we remove all non-master interfaces. Do this because they 17975b2812e925c8e976852867f8d760637c5926d817Johannes Berg * may have bss pointer dependency on the master, and when we free 17985b2812e925c8e976852867f8d760637c5926d817Johannes Berg * the master these would be freed as well, breaking our list 17995b2812e925c8e976852867f8d760637c5926d817Johannes Berg * iteration completely. 18005b2812e925c8e976852867f8d760637c5926d817Johannes Berg */ 18015b2812e925c8e976852867f8d760637c5926d817Johannes Berg list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { 18025b2812e925c8e976852867f8d760637c5926d817Johannes Berg if (sdata->dev == local->mdev) 18035b2812e925c8e976852867f8d760637c5926d817Johannes Berg continue; 18045b2812e925c8e976852867f8d760637c5926d817Johannes Berg list_del(&sdata->list); 1805f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc __ieee80211_if_del(local, sdata); 18065b2812e925c8e976852867f8d760637c5926d817Johannes Berg } 18075b2812e925c8e976852867f8d760637c5926d817Johannes Berg 18085b2812e925c8e976852867f8d760637c5926d817Johannes Berg /* then, finally, remove the master interface */ 18095b2812e925c8e976852867f8d760637c5926d817Johannes Berg __ieee80211_if_del(local, IEEE80211_DEV_TO_SUB_IF(local->mdev)); 1810f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1811f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_unlock(); 1812f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1813f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_rx_bss_list_deinit(local->mdev); 1814f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_clear_tx_pending(local); 1815f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta_info_stop(local); 1816f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rate_control_deinitialize(local); 1817e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc debugfs_hw_del(local); 1818f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1819f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (skb_queue_len(&local->skb_queue) 1820f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc || skb_queue_len(&local->skb_queue_unreliable)) 1821f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_WARNING "%s: skb_queue not empty\n", 1822dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg wiphy_name(local->hw.wiphy)); 1823f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_purge(&local->skb_queue); 1824f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_purge(&local->skb_queue_unreliable); 1825f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1826f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc destroy_workqueue(local->hw.workqueue); 1827f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy_unregister(local->hw.wiphy); 1828f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_wep_free(local); 1829f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_led_exit(local); 183096d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg ieee80211_if_free(local->mdev); 183196d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg local->mdev = NULL; 1832f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1833f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_unregister_hw); 1834f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1835f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_free_hw(struct ieee80211_hw *hw) 1836f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1837f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 1838f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1839f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy_free(local->hw.wiphy); 1840f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1841f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_free_hw); 1842f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1843f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic int __init ieee80211_init(void) 1844f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1845f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sk_buff *skb; 1846f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc int ret; 1847f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1848e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg BUILD_BUG_ON(sizeof(struct ieee80211_tx_info) > sizeof(skb->cb)); 1849e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) + 1850e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb)); 1851f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 18524b475898ec9dc6e62cebcb8fc0b3495c986a4590Johannes Berg ret = rc80211_pid_init(); 1853ad01837593338f13508463fa11c8dbf8109a1e5dMattias Nissler if (ret) 1854d9357136ac4729f589543afb6b1d17d443ae4f71Adrian Bunk goto out; 1855ac71c691e6a5ce991fe221d3bdb0c972f617aa37Johannes Berg 1856f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ret = ieee80211_wme_register(); 1857f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (ret) { 1858f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_DEBUG "ieee80211_init: failed to " 1859f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc "initialize WME (err=%d)\n", ret); 18603eadf5f4f635ed6a6cd921195c320d58b5f9a185Johannes Berg goto out_cleanup_pid; 1861f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1862f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1863e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc ieee80211_debugfs_netdev_init(); 1864e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 1865f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 1866ad01837593338f13508463fa11c8dbf8109a1e5dMattias Nissler 18673eadf5f4f635ed6a6cd921195c320d58b5f9a185Johannes Berg out_cleanup_pid: 18684b475898ec9dc6e62cebcb8fc0b3495c986a4590Johannes Berg rc80211_pid_exit(); 18693eadf5f4f635ed6a6cd921195c320d58b5f9a185Johannes Berg out: 1870ad01837593338f13508463fa11c8dbf8109a1e5dMattias Nissler return ret; 1871f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1872f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1873f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void __exit ieee80211_exit(void) 1874f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 18754b475898ec9dc6e62cebcb8fc0b3495c986a4590Johannes Berg rc80211_pid_exit(); 1876ac71c691e6a5ce991fe221d3bdb0c972f617aa37Johannes Berg 18773b96766f0e643f52ae19e134664df6730c737e87Johannes Berg /* 18783b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * For key todo, it'll be empty by now but the work 18793b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * might still be scheduled. 18803b96766f0e643f52ae19e134664df6730c737e87Johannes Berg */ 18813b96766f0e643f52ae19e134664df6730c737e87Johannes Berg flush_scheduled_work(); 18823b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 1883f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo if (mesh_allocated) 1884f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo ieee80211s_stop(); 1885902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg 1886f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_wme_unregister(); 1887e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc ieee80211_debugfs_netdev_exit(); 1888f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1889f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1890f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1891ca9938fea576ebbb8d8c4fbe8a5bcc937e49e1caJohannes Bergsubsys_initcall(ieee80211_init); 1892f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencmodule_exit(ieee80211_exit); 1893f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1894f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencMODULE_DESCRIPTION("IEEE 802.11 subsystem"); 1895f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencMODULE_LICENSE("GPL"); 1896