main.c revision 2c8dccc77420fb7433da5674818959d3499d35be
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 38d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky#define SUPP_MCS_SET_LEN 16 39d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky 40b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg/* 41b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg * For seeing transmitted packets on monitor interfaces 42b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg * we have a radiotap header too. 43b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg */ 44b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Bergstruct ieee80211_tx_status_rtap_hdr { 45b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg struct ieee80211_radiotap_header hdr; 46b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg __le16 tx_flags; 47b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg u8 data_retries; 48b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg} __attribute__ ((packed)); 49b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 50b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg/* common interface routines */ 51b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 52b95cce3576813ac3f86bafa6b5daaaaf7574b0feStephen Hemmingerstatic int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr) 53b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{ 54b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */ 55b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return ETH_ALEN; 56b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 57f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 584150c57212ad134765dd78c654a4b9906252b66dJohannes Berg/* must be called under mdev tx lock */ 594150c57212ad134765dd78c654a4b9906252b66dJohannes Bergstatic void ieee80211_configure_filter(struct ieee80211_local *local) 604150c57212ad134765dd78c654a4b9906252b66dJohannes Berg{ 614150c57212ad134765dd78c654a4b9906252b66dJohannes Berg unsigned int changed_flags; 624150c57212ad134765dd78c654a4b9906252b66dJohannes Berg unsigned int new_flags = 0; 634150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 6453918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg if (atomic_read(&local->iff_promiscs)) 654150c57212ad134765dd78c654a4b9906252b66dJohannes Berg new_flags |= FIF_PROMISC_IN_BSS; 664150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 6753918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg if (atomic_read(&local->iff_allmultis)) 684150c57212ad134765dd78c654a4b9906252b66dJohannes Berg new_flags |= FIF_ALLMULTI; 694150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 704150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (local->monitors) 718cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu new_flags |= FIF_BCN_PRBRESP_PROMISC; 728cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 738cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (local->fif_fcsfail) 748cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu new_flags |= FIF_FCSFAIL; 758cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 768cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (local->fif_plcpfail) 778cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu new_flags |= FIF_PLCPFAIL; 788cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 798cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (local->fif_control) 808cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu new_flags |= FIF_CONTROL; 818cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 828cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (local->fif_other_bss) 838cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu new_flags |= FIF_OTHER_BSS; 844150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 854150c57212ad134765dd78c654a4b9906252b66dJohannes Berg changed_flags = local->filter_flags ^ new_flags; 864150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 874150c57212ad134765dd78c654a4b9906252b66dJohannes Berg /* be a bit nasty */ 884150c57212ad134765dd78c654a4b9906252b66dJohannes Berg new_flags |= (1<<31); 894150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 904150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->ops->configure_filter(local_to_hw(local), 914150c57212ad134765dd78c654a4b9906252b66dJohannes Berg changed_flags, &new_flags, 924150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->mdev->mc_count, 934150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->mdev->mc_list); 944150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 954150c57212ad134765dd78c654a4b9906252b66dJohannes Berg WARN_ON(new_flags & (1<<31)); 964150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 974150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->filter_flags = new_flags & ~(1<<31); 984150c57212ad134765dd78c654a4b9906252b66dJohannes Berg} 994150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 100b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg/* master interface */ 101f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 102b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic int ieee80211_master_open(struct net_device *dev) 103b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{ 104b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 105b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_sub_if_data *sdata; 106b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg int res = -EOPNOTSUPP; 107f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 10879010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg /* we hold the RTNL here so can safely walk the list */ 10979010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg list_for_each_entry(sdata, &local->interfaces, list) { 110b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (sdata->dev != dev && netif_running(sdata->dev)) { 111b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg res = 0; 112b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg break; 113b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 114b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 115b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return res; 116b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 117f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 118b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic int ieee80211_master_stop(struct net_device *dev) 119f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 120b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 121b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_sub_if_data *sdata; 122f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 12379010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg /* we hold the RTNL here so can safely walk the list */ 12479010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg list_for_each_entry(sdata, &local->interfaces, list) 125b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (sdata->dev != dev && netif_running(sdata->dev)) 126b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev_close(sdata->dev); 127f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 128b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return 0; 129b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 130f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1314150c57212ad134765dd78c654a4b9906252b66dJohannes Bergstatic void ieee80211_master_set_multicast_list(struct net_device *dev) 1324150c57212ad134765dd78c654a4b9906252b66dJohannes Berg{ 1334150c57212ad134765dd78c654a4b9906252b66dJohannes Berg struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 1344150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 1354150c57212ad134765dd78c654a4b9906252b66dJohannes Berg ieee80211_configure_filter(local); 1364150c57212ad134765dd78c654a4b9906252b66dJohannes Berg} 1374150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 138b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg/* regular interfaces */ 139f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 140b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic int ieee80211_change_mtu(struct net_device *dev, int new_mtu) 141f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 142f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo int meshhdrlen; 143f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 144f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo 145f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo meshhdrlen = (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) ? 5 : 0; 146f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo 147b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg /* FIX: what would be proper limits for MTU? 148b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg * This interface uses 802.3 frames. */ 149f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo if (new_mtu < 256 || 150f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) { 151b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg printk(KERN_WARNING "%s: invalid MTU %d\n", 152b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->name, new_mtu); 153b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return -EINVAL; 154b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 155f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 156b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 157b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu); 158b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ 159b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->mtu = new_mtu; 160f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 161f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 162f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 163b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic inline int identical_mac_addr_allowed(int type1, int type2) 164b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{ 165b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return (type1 == IEEE80211_IF_TYPE_MNTR || 166b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg type2 == IEEE80211_IF_TYPE_MNTR || 167b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg (type1 == IEEE80211_IF_TYPE_AP && 168b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg type2 == IEEE80211_IF_TYPE_WDS) || 169b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg (type1 == IEEE80211_IF_TYPE_WDS && 170b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg (type2 == IEEE80211_IF_TYPE_WDS || 171b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg type2 == IEEE80211_IF_TYPE_AP)) || 172b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg (type1 == IEEE80211_IF_TYPE_AP && 173b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg type2 == IEEE80211_IF_TYPE_VLAN) || 174b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg (type1 == IEEE80211_IF_TYPE_VLAN && 175b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg (type2 == IEEE80211_IF_TYPE_AP || 176b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg type2 == IEEE80211_IF_TYPE_VLAN))); 177b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 178f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 179b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic int ieee80211_open(struct net_device *dev) 180e2ebc74d7e3d71600640db6fbb28cc2f362184c1Johannes Berg{ 181b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_sub_if_data *sdata, *nsdata; 182b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 183b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_if_init_conf conf; 184b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg int res; 185ceffefd15aac78841432230627308b8a382dbcfcMichael Buesch bool need_hw_reconfig = 0; 18644213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg struct sta_info *sta; 187f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 188b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1890ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg 19079010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg /* we hold the RTNL here so can safely walk the list */ 19179010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg list_for_each_entry(nsdata, &local->interfaces, list) { 192b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct net_device *ndev = nsdata->dev; 193e2ebc74d7e3d71600640db6fbb28cc2f362184c1Johannes Berg 194665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg if (ndev != dev && ndev != local->mdev && netif_running(ndev)) { 195665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg /* 196665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * Allow only a single IBSS interface to be up at any 197665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * time. This is restricted because beacon distribution 198665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * cannot work properly if both are in the same IBSS. 199665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * 200665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * To remove this restriction we'd have to disallow them 201665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * from setting the same SSID on different IBSS interfaces 202665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * belonging to the same hardware. Then, however, we're 203665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * faced with having to adopt two different TSF timers... 204665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg */ 205665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && 206665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg nsdata->vif.type == IEEE80211_IF_TYPE_IBSS) 207665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg return -EBUSY; 208665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg 209665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg /* 210665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * Disallow multiple IBSS/STA mode interfaces. 211665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * 212665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * This is a technical restriction, it is possible although 213665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * most likely not IEEE 802.11 compliant to have multiple 214665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * STAs with just a single hardware (the TSF timer will not 215665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * be adjusted properly.) 216665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * 217665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * However, because mac80211 uses the master device's BSS 218665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * information for each STA/IBSS interface, doing this will 219665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * currently corrupt that BSS information completely, unless, 220665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * a not very useful case, both STAs are associated to the 221665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * same BSS. 222665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * 223665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * To remove this restriction, the BSS information needs to 224665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * be embedded in the STA/IBSS mode sdata instead of using 225665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * the master device's BSS structure. 226665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg */ 227665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg if ((sdata->vif.type == IEEE80211_IF_TYPE_STA || 228665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg sdata->vif.type == IEEE80211_IF_TYPE_IBSS) && 229665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg (nsdata->vif.type == IEEE80211_IF_TYPE_STA || 230665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg nsdata->vif.type == IEEE80211_IF_TYPE_IBSS)) 231665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg return -EBUSY; 232665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg 233665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg /* 234665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * The remaining checks are only performed for interfaces 235665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg * with the same MAC address. 236665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg */ 237665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg if (compare_ether_addr(dev->dev_addr, ndev->dev_addr)) 238665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg continue; 239665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg 2400ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg /* 2410ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg * check whether it may have the same address 2420ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg */ 24351fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (!identical_mac_addr_allowed(sdata->vif.type, 24451fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg nsdata->vif.type)) 2450ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg return -ENOTUNIQ; 2460ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg 2470ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg /* 2480ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg * can only add VLANs to enabled APs 2490ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg */ 25051fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN && 251665e8aafb4e0826caec9db25617b186ea3f3ec91Johannes Berg nsdata->vif.type == IEEE80211_IF_TYPE_AP) 2520ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg sdata->u.vlan.ap = nsdata; 253b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 254b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 255f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 25651fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg switch (sdata->vif.type) { 2570ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg case IEEE80211_IF_TYPE_WDS: 2580ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg if (is_zero_ether_addr(sdata->u.wds.remote_addr)) 2590ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg return -ENOLINK; 26044213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg 26144213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg /* Create STA entry for the WDS peer */ 26244213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, 26344213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg GFP_KERNEL); 26444213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg if (!sta) 26544213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg return -ENOMEM; 26644213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg 26744213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg sta->flags |= WLAN_STA_AUTHORIZED; 26844213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg 26944213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg res = sta_info_insert(sta); 27044213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg if (res) { 27193e5deb1ae39b56f4743955e76c72251256f23c1Johannes Berg /* STA has been freed */ 27244213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg return res; 27344213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg } 2740ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg break; 2750ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg case IEEE80211_IF_TYPE_VLAN: 2760ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg if (!sdata->u.vlan.ap) 2770ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg return -ENOLINK; 2780ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg break; 279fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg case IEEE80211_IF_TYPE_AP: 280fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg case IEEE80211_IF_TYPE_STA: 281fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg case IEEE80211_IF_TYPE_MNTR: 282fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg case IEEE80211_IF_TYPE_IBSS: 2836032f934c818e5c3435c9f17274fe1983f53c6b4Johannes Berg case IEEE80211_IF_TYPE_MESH_POINT: 284fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg /* no special treatment */ 285fb1c1cd6c5a8988b14c5c6c0dfe55542df3a34c6Johannes Berg break; 286a28975525016ddcbdaab8225666df1cf2dc9cb2dJohannes Berg case IEEE80211_IF_TYPE_INVALID: 287a28975525016ddcbdaab8225666df1cf2dc9cb2dJohannes Berg /* cannot happen */ 288a28975525016ddcbdaab8225666df1cf2dc9cb2dJohannes Berg WARN_ON(1); 289a28975525016ddcbdaab8225666df1cf2dc9cb2dJohannes Berg break; 2900ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg } 291f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 292b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (local->open_count == 0) { 293b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg res = 0; 2944150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (local->ops->start) 2954150c57212ad134765dd78c654a4b9906252b66dJohannes Berg res = local->ops->start(local_to_hw(local)); 2964150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (res) 297b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return res; 298ceffefd15aac78841432230627308b8a382dbcfcMichael Buesch need_hw_reconfig = 1; 299cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn ieee80211_led_radio(local, local->hw.conf.radio_enabled); 300b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 301f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 30251fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg switch (sdata->vif.type) { 3030ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg case IEEE80211_IF_TYPE_VLAN: 3040ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans); 3050ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg /* no need to tell driver */ 3060ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg break; 3074150c57212ad134765dd78c654a4b9906252b66dJohannes Berg case IEEE80211_IF_TYPE_MNTR: 3083d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { 3093d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu local->cooked_mntrs++; 3103d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu break; 3113d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 3123d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 3134150c57212ad134765dd78c654a4b9906252b66dJohannes Berg /* must be before the call to ieee80211_configure_filter */ 314b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg local->monitors++; 3158cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (local->monitors == 1) 3164150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; 3178cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 3188cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) 3198cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_fcsfail++; 3208cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) 3218cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_plcpfail++; 3228cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) 3238cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_control++; 3248cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) 3258cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_other_bss++; 3268cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 3278cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu netif_tx_lock_bh(local->mdev); 3288cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu ieee80211_configure_filter(local); 3298cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu netif_tx_unlock_bh(local->mdev); 3304150c57212ad134765dd78c654a4b9906252b66dJohannes Berg break; 3314150c57212ad134765dd78c654a4b9906252b66dJohannes Berg case IEEE80211_IF_TYPE_STA: 3324150c57212ad134765dd78c654a4b9906252b66dJohannes Berg case IEEE80211_IF_TYPE_IBSS: 3334150c57212ad134765dd78c654a4b9906252b66dJohannes Berg sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET; 3344150c57212ad134765dd78c654a4b9906252b66dJohannes Berg /* fall through */ 3354150c57212ad134765dd78c654a4b9906252b66dJohannes Berg default: 33632bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg conf.vif = &sdata->vif; 33751fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg conf.type = sdata->vif.type; 3384150c57212ad134765dd78c654a4b9906252b66dJohannes Berg conf.mac_addr = dev->dev_addr; 3394150c57212ad134765dd78c654a4b9906252b66dJohannes Berg res = local->ops->add_interface(local_to_hw(local), &conf); 3404150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (res && !local->open_count && local->ops->stop) 3414150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->ops->stop(local_to_hw(local)); 3424150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (res) 3434150c57212ad134765dd78c654a4b9906252b66dJohannes Berg return res; 3444150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 345b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg ieee80211_if_config(dev); 346d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake ieee80211_reset_erp_info(dev); 34711a843b7e16062389c53ba393c7913956e034eb2Johannes Berg ieee80211_enable_keys(sdata); 3484150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 34951fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_STA && 350ddd3d2be85e3207c47f2b3c431723e6c758b4b0dJohannes Berg !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) 3514150c57212ad134765dd78c654a4b9906252b66dJohannes Berg netif_carrier_off(dev); 3524150c57212ad134765dd78c654a4b9906252b66dJohannes Berg else 3534150c57212ad134765dd78c654a4b9906252b66dJohannes Berg netif_carrier_on(dev); 354d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake } 355f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 3564150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (local->open_count == 0) { 3574150c57212ad134765dd78c654a4b9906252b66dJohannes Berg res = dev_open(local->mdev); 3584150c57212ad134765dd78c654a4b9906252b66dJohannes Berg WARN_ON(res); 3594150c57212ad134765dd78c654a4b9906252b66dJohannes Berg tasklet_enable(&local->tx_pending_tasklet); 3604150c57212ad134765dd78c654a4b9906252b66dJohannes Berg tasklet_enable(&local->tasklet); 3614150c57212ad134765dd78c654a4b9906252b66dJohannes Berg } 3624150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 363c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg /* 364c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * set_multicast_list will be invoked by the networking core 365c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * which will check whether any increments here were done in 366c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * error and sync them down to the hardware as filter flags. 367c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg */ 368c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg if (sdata->flags & IEEE80211_SDATA_ALLMULTI) 369c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg atomic_inc(&local->iff_allmultis); 370c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg 371c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg if (sdata->flags & IEEE80211_SDATA_PROMISC) 372c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg atomic_inc(&local->iff_promiscs); 373c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg 3744150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->open_count++; 375ceffefd15aac78841432230627308b8a382dbcfcMichael Buesch if (need_hw_reconfig) 376ceffefd15aac78841432230627308b8a382dbcfcMichael Buesch ieee80211_hw_config(local); 377f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 37864f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann /* 37964f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann * ieee80211_sta_work is disabled while network interface 38064f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann * is down. Therefore, some configuration changes may not 38164f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann * yet be effective. Trigger execution of ieee80211_sta_work 38264f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann * to fix this. 38364f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann */ 38464f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann if(sdata->vif.type == IEEE80211_IF_TYPE_STA || 38564f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { 38664f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann struct ieee80211_if_sta *ifsta = &sdata->u.sta; 38764f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann queue_work(local->hw.workqueue, &ifsta->work); 38864f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann } 38964f851e410ae37a0990212ae34f0c96b641478f7Jan Niehusmann 390b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg netif_start_queue(dev); 3914150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 392b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return 0; 393f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 394f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 3954150c57212ad134765dd78c654a4b9906252b66dJohannes Bergstatic int ieee80211_stop(struct net_device *dev) 396f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 39744213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 39844213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg struct ieee80211_local *local = sdata->local; 3994150c57212ad134765dd78c654a4b9906252b66dJohannes Berg struct ieee80211_if_init_conf conf; 40007db218396650933abff3c5c1ad1e2a6e0cfedebRon Rindjunsky struct sta_info *sta; 4014150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 40244213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg /* 40344213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * Stop TX on this interface first. 40444213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg */ 40544213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg netif_stop_queue(dev); 4064150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 40744213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg /* 40844213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * Now delete all active aggregation sessions. 40944213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg */ 410d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_lock(); 411d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg 412d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg list_for_each_entry_rcu(sta, &local->sta_list, list) { 413d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg if (sta->sdata == sdata) 41485249e5fab13edb89258fa6d551cd4a3a4f0d569Ron Rindjunsky ieee80211_sta_tear_down_BA_sessions(dev, sta->addr); 41507db218396650933abff3c5c1ad1e2a6e0cfedebRon Rindjunsky } 41607db218396650933abff3c5c1ad1e2a6e0cfedebRon Rindjunsky 417d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 418d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg 41944213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg /* 42044213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * Remove all stations associated with this interface. 42144213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * 42244213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * This must be done before calling ops->remove_interface() 42344213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * because otherwise we can later invoke ops->sta_notify() 42444213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * whenever the STAs are removed, and that invalidates driver 42544213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * assumptions about always getting a vif pointer that is valid 42644213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * (because if we remove a STA after ops->remove_interface() 42744213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * the driver will have removed the vif info already!) 42844213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * 42944213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * We could relax this and only unlink the stations from the 43044213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * hash table and list but keep them on a per-sdata list that 43144213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * will be inserted back again when the interface is brought 43244213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * up again, but I don't currently see a use case for that, 43344213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * except with WDS which gets a STA entry created when it is 43444213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg * brought up. 43544213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg */ 43644213b5e13c907bf4aa2e73941944f90184c8772Johannes Berg sta_info_flush(local, sdata); 4374150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 438c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg /* 439c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * Don't count this interface for promisc/allmulti while it 440c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * is down. dev_mc_unsync() will invoke set_multicast_list 441c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * on the master interface which will sync these down to the 442c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg * hardware as filter flags. 443c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg */ 444c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg if (sdata->flags & IEEE80211_SDATA_ALLMULTI) 445c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg atomic_dec(&local->iff_allmultis); 446c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg 447c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg if (sdata->flags & IEEE80211_SDATA_PROMISC) 448c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg atomic_dec(&local->iff_promiscs); 449c1428b3f45d152a300e4f18638ebf30ceafda6c3Johannes Berg 4504150c57212ad134765dd78c654a4b9906252b66dJohannes Berg dev_mc_unsync(local->mdev, dev); 4514150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 4525dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg /* APs need special treatment */ 45351fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { 4540ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg struct ieee80211_sub_if_data *vlan, *tmp; 4555dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg struct beacon_data *old_beacon = sdata->u.ap.beacon; 4560ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg 4575dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg /* remove beacon */ 4585dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg rcu_assign_pointer(sdata->u.ap.beacon, NULL); 4595dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg synchronize_rcu(); 4605dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg kfree(old_beacon); 4615dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg 4625dfdaf58d61f06a458529430c24b1191ea4d1a27Johannes Berg /* down all dependent devices, that is VLANs */ 4630ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans, 4640ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg u.vlan.list) 4650ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg dev_close(vlan->dev); 4660ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg WARN_ON(!list_empty(&sdata->u.ap.vlans)); 4670ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg } 4680ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg 4694150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->open_count--; 470f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 47151fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg switch (sdata->vif.type) { 4720ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg case IEEE80211_IF_TYPE_VLAN: 4730ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg list_del(&sdata->u.vlan.list); 4740ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg sdata->u.vlan.ap = NULL; 4750ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg /* no need to tell driver */ 4760ec3ca445931ff0e7ad6ac61d6c5d2aaafe7a9f5Johannes Berg break; 4774150c57212ad134765dd78c654a4b9906252b66dJohannes Berg case IEEE80211_IF_TYPE_MNTR: 4783d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { 4793d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu local->cooked_mntrs--; 4803d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu break; 4813d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 4823d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 4834150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->monitors--; 4848cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (local->monitors == 0) 4858b393f1dc76acbe65a97a4e51f8144f4a65fa1c9Michael Wu local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; 4868cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 4878cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) 4888cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_fcsfail--; 4898cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) 4908cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_plcpfail--; 4918cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) 4928cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_control--; 4938cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) 4948cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu local->fif_other_bss--; 4958cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu 4968cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu netif_tx_lock_bh(local->mdev); 4978cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu ieee80211_configure_filter(local); 4988cc9a73914b07b5908d8a59320f4557fc9639f2eMichael Wu netif_tx_unlock_bh(local->mdev); 4994150c57212ad134765dd78c654a4b9906252b66dJohannes Berg break; 500f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo case IEEE80211_IF_TYPE_MESH_POINT: 501b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg case IEEE80211_IF_TYPE_STA: 502b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg case IEEE80211_IF_TYPE_IBSS: 503b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg sdata->u.sta.state = IEEE80211_DISABLED; 504b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg del_timer_sync(&sdata->u.sta.timer); 5052a8a9a88fc1b18f5c45244d0ef8a5352f6cf761fJohannes Berg /* 50679010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * When we get here, the interface is marked down. 50779010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * Call synchronize_rcu() to wait for the RX path 50879010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * should it be using the interface and enqueuing 50979010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * frames at this very time on another CPU. 5102a8a9a88fc1b18f5c45244d0ef8a5352f6cf761fJohannes Berg */ 51179010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg synchronize_rcu(); 512b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg skb_queue_purge(&sdata->u.sta.skb_queue); 5132a8a9a88fc1b18f5c45244d0ef8a5352f6cf761fJohannes Berg 514ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi if (local->scan_dev == sdata->dev) { 515ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi if (!local->ops->hw_scan) { 516ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi local->sta_sw_scanning = 0; 517ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi cancel_delayed_work(&local->scan_work); 518ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi } else 519ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi local->sta_hw_scanning = 0; 520b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 521ece8edddf067d21c4e5abfe3f1205da1588edbb2Zhu Yi 522b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg flush_workqueue(local->hw.workqueue); 523a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi 524a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; 525a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi kfree(sdata->u.sta.extra_ie); 526a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi sdata->u.sta.extra_ie = NULL; 527a10605e599a7873417043fe2bb559abe719f8a1aZhu Yi sdata->u.sta.extra_ie_len = 0; 5284150c57212ad134765dd78c654a4b9906252b66dJohannes Berg /* fall through */ 5294150c57212ad134765dd78c654a4b9906252b66dJohannes Berg default: 53032bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg conf.vif = &sdata->vif; 53151fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg conf.type = sdata->vif.type; 5324150c57212ad134765dd78c654a4b9906252b66dJohannes Berg conf.mac_addr = dev->dev_addr; 53311a843b7e16062389c53ba393c7913956e034eb2Johannes Berg /* disable all keys for as long as this netdev is down */ 53411a843b7e16062389c53ba393c7913956e034eb2Johannes Berg ieee80211_disable_keys(sdata); 5354150c57212ad134765dd78c654a4b9906252b66dJohannes Berg local->ops->remove_interface(local_to_hw(local), &conf); 536f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 537f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 538b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (local->open_count == 0) { 539b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (netif_running(local->mdev)) 540b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev_close(local->mdev); 5414150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 542b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (local->ops->stop) 543b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg local->ops->stop(local_to_hw(local)); 5444150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 545cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn ieee80211_led_radio(local, 0); 546cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn 547b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg tasklet_disable(&local->tx_pending_tasklet); 548b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg tasklet_disable(&local->tasklet); 549b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg } 550b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg 551f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 552f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 553f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 554eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyint ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) 555eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{ 556eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_local *local = hw_to_local(hw); 557eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct sta_info *sta; 558eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_sub_if_data *sdata; 559eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky u16 start_seq_num = 0; 560eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky u8 *state; 561eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky int ret; 562eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky DECLARE_MAC_BUF(mac); 563eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 564eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (tid >= STA_TID_NUM) 565eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return -EINVAL; 566eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 567eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG 568eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "Open BA session requested for %s tid %u\n", 569eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky print_mac(mac, ra), tid); 570eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */ 571eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 572d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_lock(); 573d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg 574eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky sta = sta_info_get(local, ra); 575eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (!sta) { 576eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "Could not find the station\n"); 577d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 578eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return -ENOENT; 579eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 580eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 581eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); 582eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 583eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* we have tried too many times, receiver does not want A-MPDU */ 584cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { 585eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ret = -EBUSY; 586eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky goto start_ba_exit; 587eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 588eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 589cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky state = &sta->ampdu_mlme.tid_state_tx[tid]; 590eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* check if the TID is not in aggregation flow already */ 591eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (*state != HT_AGG_STATE_IDLE) { 592eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG 593eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "BA request denied - session is not " 594eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky "idle on tid %u\n", tid); 595eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */ 596eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ret = -EAGAIN; 597eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky goto start_ba_exit; 598eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 599eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 600cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky /* prepare A-MPDU MLME for Tx aggregation */ 601cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid] = 602cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); 603cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky if (!sta->ampdu_mlme.tid_tx[tid]) { 604cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky if (net_ratelimit()) 605cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky printk(KERN_ERR "allocate tx mlme to tid %d failed\n", 606cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky tid); 607cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky ret = -ENOMEM; 608cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky goto start_ba_exit; 609cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky } 610cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky /* Tx timer */ 611cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = 612cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta_addba_resp_timer_expired; 613cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data = 614cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky (unsigned long)&sta->timer_to_tid[tid]; 615cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); 616cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky 617eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* ensure that TX flow won't interrupt us 618eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * until the end of the call to requeue function */ 619eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_lock_bh(&local->mdev->queue_lock); 620eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 621eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* create a new queue for this aggregation */ 6229e7234923789897858e1a475c579b5e2e6ad5b74Ron Rindjunsky ret = ieee80211_ht_agg_queue_add(local, sta, tid); 623eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 624eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* case no queue is available to aggregation 625eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * don't switch to aggregation */ 626eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (ret) { 627eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG 628cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky printk(KERN_DEBUG "BA request denied - queue unavailable for" 629eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky " tid %d\n", tid); 630eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */ 631cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky goto start_ba_err; 632eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 633d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg sdata = sta->sdata; 634eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 635eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the 636eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * call back right away, it must see that the flow has begun */ 637eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky *state |= HT_ADDBA_REQUESTED_MSK; 638eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 639eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (local->ops->ampdu_action) 640eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, 641eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra, tid, &start_seq_num); 642eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 643eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (ret) { 644eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* No need to requeue the packets in the agg queue, since we 645eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * held the tx lock: no packet could be enqueued to the newly 646eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * allocated queue */ 6479e7234923789897858e1a475c579b5e2e6ad5b74Ron Rindjunsky ieee80211_ht_agg_queue_remove(local, sta, tid, 0); 648eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG 649cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky printk(KERN_DEBUG "BA request denied - HW unavailable for" 650cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky " tid %d\n", tid); 651eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */ 652eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky *state = HT_AGG_STATE_IDLE; 653cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky goto start_ba_err; 654eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 655eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 656eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* Will put all the packets in the new SW queue */ 6579e7234923789897858e1a475c579b5e2e6ad5b74Ron Rindjunsky ieee80211_requeue(local, ieee802_1d_to_ac[tid]); 658eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_unlock_bh(&local->mdev->queue_lock); 659eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 660eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* send an addBA request */ 661eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky sta->ampdu_mlme.dialog_token_allocator++; 662cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid]->dialog_token = 663eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky sta->ampdu_mlme.dialog_token_allocator; 664cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; 665eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 666d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg ieee80211_send_addba_request(sta->sdata->dev, ra, tid, 667cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid]->dialog_token, 668cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid]->ssn, 669eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 0x40, 5000); 670eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 671eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* activate the timer for the recipient's addBA response */ 672cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = 673eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky jiffies + ADDBA_RESP_INTERVAL; 674cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); 675eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); 676cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky goto start_ba_exit; 677eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 678cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunskystart_ba_err: 679cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky kfree(sta->ampdu_mlme.tid_tx[tid]); 680cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid] = NULL; 681cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky spin_unlock_bh(&local->mdev->queue_lock); 682cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky ret = -EBUSY; 683eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskystart_ba_exit: 684eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 685d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 686eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return ret; 687eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky} 688eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_start_tx_ba_session); 689eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 690eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyint ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, 691eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky u8 *ra, u16 tid, 692eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky enum ieee80211_back_parties initiator) 693eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{ 694eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_local *local = hw_to_local(hw); 695eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct sta_info *sta; 696eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky u8 *state; 697eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky int ret = 0; 698eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky DECLARE_MAC_BUF(mac); 699eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 700eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (tid >= STA_TID_NUM) 701eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return -EINVAL; 702eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 703d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_lock(); 704eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky sta = sta_info_get(local, ra); 705d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg if (!sta) { 706d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 707eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return -ENOENT; 708d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg } 709eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 710eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* check if the TID is in aggregation */ 711cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky state = &sta->ampdu_mlme.tid_state_tx[tid]; 712eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); 713eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 714eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (*state != HT_AGG_STATE_OPERATIONAL) { 715eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ret = -ENOENT; 716eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky goto stop_BA_exit; 717eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 718eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 719513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG 720513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky printk(KERN_DEBUG "Tx BA session stop requested for %s tid %u\n", 721513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky print_mac(mac, ra), tid); 722513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */ 723513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky 724eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]); 725eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 726eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky *state = HT_AGG_STATE_REQ_STOP_BA_MSK | 727eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky (initiator << HT_AGG_STATE_INITIATOR_SHIFT); 728eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 729eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (local->ops->ampdu_action) 730eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP, 731eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra, tid, NULL); 732eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 733eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* case HW denied going back to legacy */ 734eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (ret) { 735eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky WARN_ON(ret != -EBUSY); 736eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky *state = HT_AGG_STATE_OPERATIONAL; 737eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); 738eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky goto stop_BA_exit; 739eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 740eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 741eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskystop_BA_exit: 742eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 743d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 744eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return ret; 745eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky} 746eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_stop_tx_ba_session); 747eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 748eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyvoid ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) 749eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{ 750eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_local *local = hw_to_local(hw); 751eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct sta_info *sta; 752eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky u8 *state; 753eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky DECLARE_MAC_BUF(mac); 754eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 755eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (tid >= STA_TID_NUM) { 756eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", 757eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky tid, STA_TID_NUM); 758eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return; 759eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 760eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 761d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_lock(); 762eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky sta = sta_info_get(local, ra); 763eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (!sta) { 764d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 765eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "Could not find station: %s\n", 766eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky print_mac(mac, ra)); 767eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return; 768eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 769eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 770cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky state = &sta->ampdu_mlme.tid_state_tx[tid]; 771eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); 772eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 773eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (!(*state & HT_ADDBA_REQUESTED_MSK)) { 774eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", 775eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky *state); 776eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 777d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 778eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return; 779eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 780eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 781eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK); 782eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 783eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky *state |= HT_ADDBA_DRV_READY_MSK; 784eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 785eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (*state == HT_AGG_STATE_OPERATIONAL) { 786eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); 787eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); 788eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 789eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 790d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 791eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky} 792eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_start_tx_ba_cb); 793eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 794eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyvoid ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) 795eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{ 796eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_local *local = hw_to_local(hw); 797eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct sta_info *sta; 798eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky u8 *state; 799eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky int agg_queue; 800eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky DECLARE_MAC_BUF(mac); 801eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 802eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (tid >= STA_TID_NUM) { 803eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", 804eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky tid, STA_TID_NUM); 805eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return; 806eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 807eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 808513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky#ifdef CONFIG_MAC80211_HT_DEBUG 809513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky printk(KERN_DEBUG "Stopping Tx BA session for %s tid %d\n", 810eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky print_mac(mac, ra), tid); 811513a1025fd91008316a8e9b4803d1bfcbb2bf256Ron Rindjunsky#endif /* CONFIG_MAC80211_HT_DEBUG */ 812eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 813d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_lock(); 814eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky sta = sta_info_get(local, ra); 815eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (!sta) { 816eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "Could not find station: %s\n", 817eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky print_mac(mac, ra)); 818d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 819eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return; 820eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 821cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky state = &sta->ampdu_mlme.tid_state_tx[tid]; 822eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 823eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); 824eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { 825eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); 826eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 827d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 828eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return; 829eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 830eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 831eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (*state & HT_AGG_STATE_INITIATOR_MSK) 832d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg ieee80211_send_delba(sta->sdata->dev, ra, tid, 833eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); 834eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 835eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky agg_queue = sta->tid_to_tx_q[tid]; 836eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 837eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* avoid ordering issues: we are the only one that can modify 838eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * the content of the qdiscs */ 839eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_lock_bh(&local->mdev->queue_lock); 840eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* remove the queue for this aggregation */ 8419e7234923789897858e1a475c579b5e2e6ad5b74Ron Rindjunsky ieee80211_ht_agg_queue_remove(local, sta, tid, 1); 842eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_unlock_bh(&local->mdev->queue_lock); 843eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 844eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky /* we just requeued the all the frames that were in the removed 845eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * queue, and since we might miss a softirq we do netif_schedule. 846eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * ieee80211_wake_queue is not used here as this queue is not 847eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky * necessarily stopped */ 848eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky netif_schedule(local->mdev); 849eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky *state = HT_AGG_STATE_IDLE; 850cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.addba_req_num[tid] = 0; 851cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky kfree(sta->ampdu_mlme.tid_tx[tid]); 852cee24a3e580f1062c8bb8b1692b95014d882bc7dRon Rindjunsky sta->ampdu_mlme.tid_tx[tid] = NULL; 853eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 854eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 855d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 856eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky} 857eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_stop_tx_ba_cb); 858eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 859eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyvoid ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, 860eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky const u8 *ra, u16 tid) 861eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{ 862eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_local *local = hw_to_local(hw); 863eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_ra_tid *ra_tid; 864eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct sk_buff *skb = dev_alloc_skb(0); 865eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 866eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (unlikely(!skb)) { 867eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (net_ratelimit()) 868eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_WARNING "%s: Not enough memory, " 869eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky "dropping start BA session", skb->dev->name); 870eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return; 871eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 872eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid = (struct ieee80211_ra_tid *) &skb->cb; 873eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky memcpy(&ra_tid->ra, ra, ETH_ALEN); 874eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid->tid = tid; 875eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 876eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky skb->pkt_type = IEEE80211_ADDBA_MSG; 877eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky skb_queue_tail(&local->skb_queue, skb); 878eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky tasklet_schedule(&local->tasklet); 879eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky} 880eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); 881eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 882eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunskyvoid ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, 883eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky const u8 *ra, u16 tid) 884eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky{ 885eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_local *local = hw_to_local(hw); 886eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_ra_tid *ra_tid; 887eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct sk_buff *skb = dev_alloc_skb(0); 888eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 889eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (unlikely(!skb)) { 890eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky if (net_ratelimit()) 891eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky printk(KERN_WARNING "%s: Not enough memory, " 892eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky "dropping stop BA session", skb->dev->name); 893eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky return; 894eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky } 895eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid = (struct ieee80211_ra_tid *) &skb->cb; 896eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky memcpy(&ra_tid->ra, ra, ETH_ALEN); 897eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid->tid = tid; 898eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 899eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky skb->pkt_type = IEEE80211_DELBA_MSG; 900eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky skb_queue_tail(&local->skb_queue, skb); 901eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky tasklet_schedule(&local->tasklet); 902eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky} 903eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron RindjunskyEXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe); 904eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky 905f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void ieee80211_set_multicast_list(struct net_device *dev) 906f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 907f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 908f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 9094150c57212ad134765dd78c654a4b9906252b66dJohannes Berg int allmulti, promisc, sdata_allmulti, sdata_promisc; 910f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 9114150c57212ad134765dd78c654a4b9906252b66dJohannes Berg allmulti = !!(dev->flags & IFF_ALLMULTI); 9124150c57212ad134765dd78c654a4b9906252b66dJohannes Berg promisc = !!(dev->flags & IFF_PROMISC); 913b52f2198ac889561d341c6990d669a671f93f450Johannes Berg sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); 914b52f2198ac889561d341c6990d669a671f93f450Johannes Berg sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC); 9154150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 9164150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (allmulti != sdata_allmulti) { 9174150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (dev->flags & IFF_ALLMULTI) 91853918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg atomic_inc(&local->iff_allmultis); 9194150c57212ad134765dd78c654a4b9906252b66dJohannes Berg else 92053918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg atomic_dec(&local->iff_allmultis); 92113262ffd4902805acad2618c12b41fcaa6c50791Jiri Slaby sdata->flags ^= IEEE80211_SDATA_ALLMULTI; 922f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 9234150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 9244150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (promisc != sdata_promisc) { 9254150c57212ad134765dd78c654a4b9906252b66dJohannes Berg if (dev->flags & IFF_PROMISC) 92653918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg atomic_inc(&local->iff_promiscs); 9274150c57212ad134765dd78c654a4b9906252b66dJohannes Berg else 92853918994b7c8c3bf0af5f641e1f299856799d883Johannes Berg atomic_dec(&local->iff_promiscs); 92913262ffd4902805acad2618c12b41fcaa6c50791Jiri Slaby sdata->flags ^= IEEE80211_SDATA_PROMISC; 930f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 9314150c57212ad134765dd78c654a4b9906252b66dJohannes Berg 9324150c57212ad134765dd78c654a4b9906252b66dJohannes Berg dev_mc_sync(local->mdev, dev); 933f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 934f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 9353b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemmingerstatic const struct header_ops ieee80211_header_ops = { 9363b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger .create = eth_header, 9373b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger .parse = header_parse_80211, 9383b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger .rebuild = eth_rebuild_header, 9393b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger .cache = eth_header_cache, 9403b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger .cache_update = eth_header_cache_update, 9413b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger}; 9423b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger 943f9d540ee5f7e480339911df8d7389ef4c435ab54Johannes Berg/* Must not be called for mdev */ 944b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergvoid ieee80211_if_setup(struct net_device *dev) 945f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 946b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg ether_setup(dev); 947b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->hard_start_xmit = ieee80211_subif_start_xmit; 948b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->wireless_handlers = &ieee80211_iw_handler_def; 949b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->set_multicast_list = ieee80211_set_multicast_list; 950b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->change_mtu = ieee80211_change_mtu; 951b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->open = ieee80211_open; 952b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->stop = ieee80211_stop; 953b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg dev->destructor = ieee80211_if_free; 954b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 955f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 956b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg/* everything else */ 957b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg 958b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergstatic int __ieee80211_if_config(struct net_device *dev, 959b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct sk_buff *beacon, 960b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_tx_control *control) 961b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{ 962b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 963b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 964b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_if_conf conf; 965b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg 966b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (!local->ops->config_interface || !netif_running(dev)) 967f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 968f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 969b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg memset(&conf, 0, sizeof(conf)); 97051fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg conf.type = sdata->vif.type; 97151fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_STA || 97251fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { 9734150c57212ad134765dd78c654a4b9906252b66dJohannes Berg conf.bssid = sdata->u.sta.bssid; 974b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg conf.ssid = sdata->u.sta.ssid; 975b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg conf.ssid_len = sdata->u.sta.ssid_len; 976902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg } else if (ieee80211_vif_is_mesh(&sdata->vif)) { 977f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo conf.beacon = beacon; 978f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo ieee80211_start_mesh(dev); 97951fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { 980b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg conf.ssid = sdata->u.ap.ssid; 981b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg conf.ssid_len = sdata->u.ap.ssid_len; 982b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg conf.beacon = beacon; 983b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg conf.beacon_control = control; 984f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 985b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return local->ops->config_interface(local_to_hw(local), 98632bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg &sdata->vif, &conf); 987f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 988f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 989b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergint ieee80211_if_config(struct net_device *dev) 990b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{ 991f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 992f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 993f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT && 994f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo (local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) 995f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo return ieee80211_if_config_beacon(dev); 996b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return __ieee80211_if_config(dev, NULL, NULL); 997b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 998f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 999b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergint ieee80211_if_config_beacon(struct net_device *dev) 1000f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1001f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 1002b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_tx_control control; 100332bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1004b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct sk_buff *skb; 1005f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1006b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) 1007f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 100832bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif, 100932bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg &control); 1010b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg if (!skb) 1011b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return -ENOMEM; 1012b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return __ieee80211_if_config(dev, skb, &control); 1013b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 1014f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1015b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Bergint ieee80211_hw_config(struct ieee80211_local *local) 1016b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg{ 1017b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg struct ieee80211_channel *chan; 1018b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg int ret = 0; 1019f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 10208318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg if (local->sta_sw_scanning) 1021b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg chan = local->scan_channel; 10228318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg else 1023b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg chan = local->oper_channel; 1024f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 10258318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.channel = chan; 10268318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 10278318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg if (!local->hw.conf.power_level) 10288318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.power_level = chan->max_power; 10298318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg else 10308318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.power_level = min(chan->max_power, 10318318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.power_level); 10328318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 10338318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.max_antenna_gain = chan->max_antenna_gain; 1034f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1035b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 10368318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg printk(KERN_DEBUG "%s: HW CONFIG: freq=%d\n", 10378318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg wiphy_name(local->hw.wiphy), chan->center_freq); 10388318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg#endif 1039b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg 1040f7c4daed99fba15e4e48df464031f4ac7c32e4c9Michael Buesch if (local->open_count) 1041b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg ret = local->ops->config(local_to_hw(local), &local->hw.conf); 1042f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1043b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg return ret; 1044b2c258fb11b3fc77a73f8b0453ff1256de812bc6Johannes Berg} 1045f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1046d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky/** 104738668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler * ieee80211_handle_ht should be used only after legacy configuration 104838668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler * has been determined namely band, as ht configuration depends upon 104938668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler * the hardware's HT abilities for a _specific_ band. 1050d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky */ 105138668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkleru32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, 1052d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky struct ieee80211_ht_info *req_ht_cap, 1053d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky struct ieee80211_ht_bss_info *req_bss_cap) 1054d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky{ 1055d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky struct ieee80211_conf *conf = &local->hw.conf; 10568318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg struct ieee80211_supported_band *sband; 105738668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler struct ieee80211_ht_info ht_conf; 105838668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler struct ieee80211_ht_bss_info ht_bss_conf; 1059d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky int i; 106038668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler u32 changed = 0; 1061d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky 10628318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg sband = local->hw.wiphy->bands[conf->channel->band]; 10638318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 1064d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky /* HT is not supported */ 10658318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg if (!sband->ht_info.ht_supported) { 1066d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; 106738668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler return 0; 1068d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky } 1069d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky 107038668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info)); 107138668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info)); 107238668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 107338668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler if (enable_ht) { 107438668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) 107538668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler changed |= BSS_CHANGED_HT; 107638668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 1077d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE; 107838668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler ht_conf.ht_supported = 1; 107938668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 108038668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; 108138668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS); 108238668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS; 108338668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 1084d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky for (i = 0; i < SUPP_MCS_SET_LEN; i++) 108538668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler ht_conf.supp_mcs_set[i] = 108638668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler sband->ht_info.supp_mcs_set[i] & 108738668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler req_ht_cap->supp_mcs_set[i]; 108838668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 108938668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler ht_bss_conf.primary_channel = req_bss_cap->primary_channel; 109038668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler ht_bss_conf.bss_cap = req_bss_cap->bss_cap; 109138668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; 109238668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 109338668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler ht_conf.ampdu_factor = req_ht_cap->ampdu_factor; 109438668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler ht_conf.ampdu_density = req_ht_cap->ampdu_density; 109538668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler 109638668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler /* if bss configuration changed store the new one */ 109738668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) || 109838668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) { 109938668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler changed |= BSS_CHANGED_HT; 110038668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf)); 110138668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf)); 110238668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler } 110338668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler } else { 110438668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) 110538668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler changed |= BSS_CHANGED_HT; 110638668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; 1107d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky } 1108d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky 110938668c059f5202f5fd9612391f9aa1b38a97241bTomas Winkler return changed; 1110d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky} 1111d3c990fb26b78f60614885d9ecaf7b7686b7b098Ron Rindjunsky 1112471b3efdfccc257591331724145f8ccf8b3217e1Johannes Bergvoid ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, 1113471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg u32 changed) 1114d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake{ 1115471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg struct ieee80211_local *local = sdata->local; 1116471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg 1117471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg if (!changed) 1118471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg return; 1119471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg 1120471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg if (local->ops->bss_info_changed) 1121471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg local->ops->bss_info_changed(local_to_hw(local), 1122471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg &sdata->vif, 1123471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg &sdata->bss_conf, 1124471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg changed); 1125d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake} 1126d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake 1127d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drakevoid ieee80211_reset_erp_info(struct net_device *dev) 1128d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake{ 1129d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1130d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake 1131471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg sdata->bss_conf.use_cts_prot = 0; 1132471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg sdata->bss_conf.use_short_preamble = 0; 1133471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg ieee80211_bss_info_change_notify(sdata, 1134471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg BSS_CHANGED_ERP_CTS_PROT | 1135471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg BSS_CHANGED_ERP_PREAMBLE); 1136d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake} 1137d9430a32886f70c0c16d67c525f6cda2df7906eeDaniel Drake 1138f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, 1139f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sk_buff *skb, 1140f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_tx_status *status) 1141f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1142f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 1143f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_tx_status *saved; 1144f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc int tmp; 1145f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1146f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb->dev = local->mdev; 1147f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc saved = kmalloc(sizeof(struct ieee80211_tx_status), GFP_ATOMIC); 1148f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (unlikely(!saved)) { 1149f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (net_ratelimit()) 1150f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_WARNING "%s: Not enough memory, " 1151f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc "dropping tx status", skb->dev->name); 1152f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* should be dev_kfree_skb_irq, but due to this function being 1153f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * named _irqsafe instead of just _irq we can't be sure that 1154f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * people won't call it from non-irq contexts */ 1155f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb_any(skb); 1156f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return; 1157f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1158f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memcpy(saved, status, sizeof(struct ieee80211_tx_status)); 1159f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* copy pointer to saved status into skb->cb for use by tasklet */ 1160f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memcpy(skb->cb, &saved, sizeof(saved)); 1161f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1162f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb->pkt_type = IEEE80211_TX_STATUS_MSG; 1163f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_tail(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS ? 1164f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc &local->skb_queue : &local->skb_queue_unreliable, skb); 1165f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tmp = skb_queue_len(&local->skb_queue) + 1166f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_len(&local->skb_queue_unreliable); 1167f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT && 1168f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc (skb = skb_dequeue(&local->skb_queue_unreliable))) { 1169f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memcpy(&saved, skb->cb, sizeof(saved)); 1170f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc kfree(saved); 1171f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb_irq(skb); 1172f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tmp--; 1173f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc I802_DEBUG_INC(local->tx_status_drop); 1174f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1175f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_schedule(&local->tasklet); 1176f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1177f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_tx_status_irqsafe); 1178f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1179f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void ieee80211_tasklet_handler(unsigned long data) 1180f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1181f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = (struct ieee80211_local *) data; 1182f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sk_buff *skb; 1183f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_rx_status rx_status; 1184f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_tx_status *tx_status; 1185eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky struct ieee80211_ra_tid *ra_tid; 1186f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1187f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc while ((skb = skb_dequeue(&local->skb_queue)) || 1188f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc (skb = skb_dequeue(&local->skb_queue_unreliable))) { 1189f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc switch (skb->pkt_type) { 1190f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case IEEE80211_RX_MSG: 1191f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* status is in skb->cb */ 1192f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memcpy(&rx_status, skb->cb, sizeof(rx_status)); 119351fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg /* Clear skb->pkt_type in order to not confuse kernel 1194f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * netstack. */ 1195f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb->pkt_type = 0; 1196f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc __ieee80211_rx(local_to_hw(local), skb, &rx_status); 1197f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 1198f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case IEEE80211_TX_STATUS_MSG: 1199f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* get pointer to saved status out of skb->cb */ 1200f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memcpy(&tx_status, skb->cb, sizeof(tx_status)); 1201f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb->pkt_type = 0; 1202f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_tx_status(local_to_hw(local), 1203f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb, tx_status); 1204f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc kfree(tx_status); 1205f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 1206eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky case IEEE80211_DELBA_MSG: 1207eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid = (struct ieee80211_ra_tid *) &skb->cb; 1208eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ieee80211_stop_tx_ba_cb(local_to_hw(local), 1209eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid->ra, ra_tid->tid); 1210eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky dev_kfree_skb(skb); 1211eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky break; 1212eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky case IEEE80211_ADDBA_MSG: 1213eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid = (struct ieee80211_ra_tid *) &skb->cb; 1214eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ieee80211_start_tx_ba_cb(local_to_hw(local), 1215eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky ra_tid->ra, ra_tid->tid); 1216eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky dev_kfree_skb(skb); 1217eadc8d9e9047266a8914eb2ed4d36e797ce540d1Ron Rindjunsky break ; 1218f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc default: /* should never get here! */ 1219f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_ERR "%s: Unknown message type (%d)\n", 1220dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg wiphy_name(local->hw.wiphy), skb->pkt_type); 1221f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb(skb); 1222f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 1223f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1224f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1225f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1226f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1227f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to 1228f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * make a prepared TX frame (one that has been given to hw) to look like brand 1229f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * new IEEE 802.11 frame that is ready to go through TX processing again. 1230f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * Also, tx_packet_data in cb is restored from tx_control. */ 1231f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void ieee80211_remove_tx_extra(struct ieee80211_local *local, 1232f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_key *key, 1233f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sk_buff *skb, 1234f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_tx_control *control) 1235f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1236f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc int hdrlen, iv_len, mic_len; 1237f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_tx_packet_data *pkt_data; 1238f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1239f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; 124032bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg pkt_data->ifindex = vif_to_sdata(control->vif)->dev->ifindex; 1241e8bf96495cd67090b4900ddaf8e8672a17ec39faJiri Slaby pkt_data->flags = 0; 1242e8bf96495cd67090b4900ddaf8e8672a17ec39faJiri Slaby if (control->flags & IEEE80211_TXCTL_REQ_TX_STATUS) 1243e8bf96495cd67090b4900ddaf8e8672a17ec39faJiri Slaby pkt_data->flags |= IEEE80211_TXPD_REQ_TX_STATUS; 1244e8bf96495cd67090b4900ddaf8e8672a17ec39faJiri Slaby if (control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT) 1245e8bf96495cd67090b4900ddaf8e8672a17ec39faJiri Slaby pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT; 1246e8bf96495cd67090b4900ddaf8e8672a17ec39faJiri Slaby if (control->flags & IEEE80211_TXCTL_REQUEUE) 1247e8bf96495cd67090b4900ddaf8e8672a17ec39faJiri Slaby pkt_data->flags |= IEEE80211_TXPD_REQUEUE; 1248678f5f7117d5780d3a51b201c9f44b7bf90f6a76Johannes Berg if (control->flags & IEEE80211_TXCTL_EAPOL_FRAME) 1249678f5f7117d5780d3a51b201c9f44b7bf90f6a76Johannes Berg pkt_data->flags |= IEEE80211_TXPD_EAPOL_FRAME; 1250f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc pkt_data->queue = control->queue; 1251f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1252f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc hdrlen = ieee80211_get_hdrlen_from_skb(skb); 1253f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1254f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (!key) 1255f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto no_key; 1256f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 12578f20fc24986a083228823d9b68adca20714b254eJohannes Berg switch (key->conf.alg) { 1258f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case ALG_WEP: 1259f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc iv_len = WEP_IV_LEN; 1260f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc mic_len = WEP_ICV_LEN; 1261f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 1262f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case ALG_TKIP: 1263f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc iv_len = TKIP_IV_LEN; 1264f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc mic_len = TKIP_ICV_LEN; 1265f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 1266f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc case ALG_CCMP: 1267f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc iv_len = CCMP_HDR_LEN; 1268f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc mic_len = CCMP_MIC_LEN; 1269f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc break; 1270f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc default: 1271f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto no_key; 1272f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1273f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 12748f20fc24986a083228823d9b68adca20714b254eJohannes Berg if (skb->len >= mic_len && 127511a843b7e16062389c53ba393c7913956e034eb2Johannes Berg !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) 1276f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_trim(skb, skb->len - mic_len); 1277f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (skb->len >= iv_len && skb->len > hdrlen) { 1278f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memmove(skb->data + iv_len, skb->data, hdrlen); 1279f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_pull(skb, iv_len); 1280f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1281f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1282f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencno_key: 1283f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc { 1284f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 1285f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc u16 fc = le16_to_cpu(hdr->frame_control); 1286f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if ((fc & 0x8C) == 0x88) /* QoS Control Field */ { 1287f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc fc &= ~IEEE80211_STYPE_QOS_DATA; 1288f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc hdr->frame_control = cpu_to_le16(fc); 1289f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memmove(skb->data + 2, skb->data, hdrlen - 2); 1290f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_pull(skb, 2); 1291f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1292f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1293f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1294f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1295d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Bergstatic void ieee80211_handle_filtered_frame(struct ieee80211_local *local, 1296d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg struct sta_info *sta, 1297d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg struct sk_buff *skb, 1298d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg struct ieee80211_tx_status *status) 1299d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg{ 1300d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg sta->tx_filtered_count++; 1301d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 1302d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg /* 1303d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * Clear the TX filter mask for this STA when sending the next 1304d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * packet. If the STA went to power save mode, this will happen 1305d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * happen when it wakes up for the next time. 1306d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg */ 1307d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg sta->flags |= WLAN_STA_CLEAR_PS_FILT; 1308d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 1309d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg /* 1310d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * This code races in the following way: 1311d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * 1312d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (1) STA sends frame indicating it will go to sleep and does so 1313d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (2) hardware/firmware adds STA to filter list, passes frame up 1314d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (3) hardware/firmware processes TX fifo and suppresses a frame 1315d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (4) we get TX status before having processed the frame and 1316d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * knowing that the STA has gone to sleep. 1317d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * 1318d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * This is actually quite unlikely even when both those events are 1319d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * processed from interrupts coming in quickly after one another or 1320d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * even at the same time because we queue both TX status events and 1321d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * RX frames to be processed by a tasklet and process them in the 1322d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * same order that they were received or TX status last. Hence, there 1323d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * is no race as long as the frame RX is processed before the next TX 1324d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * status, which drivers can ensure, see below. 1325d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * 1326d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * Note that this can only happen if the hardware or firmware can 1327d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * actually add STAs to the filter list, if this is done by the 1328d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * driver in response to set_tim() (which will only reduce the race 1329d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * this whole filtering tries to solve, not completely solve it) 1330d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * this situation cannot happen. 1331d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * 1332d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * To completely solve this race drivers need to make sure that they 1333d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (a) don't mix the irq-safe/not irq-safe TX status/RX processing 1334d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * functions and 1335d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * (b) always process RX events before TX status events if ordering 1336d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * can be unknown, for example with different interrupt status 1337d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * bits. 1338d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg */ 1339d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg if (sta->flags & WLAN_STA_PS && 1340d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { 1341d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg ieee80211_remove_tx_extra(local, sta->key, skb, 1342d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg &status->control); 1343d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg skb_queue_tail(&sta->tx_filtered, skb); 1344d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg return; 1345d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg } 1346d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 1347d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg if (!(sta->flags & WLAN_STA_PS) && 1348d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg !(status->control.flags & IEEE80211_TXCTL_REQUEUE)) { 1349d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg /* Software retry the packet once */ 1350d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg status->control.flags |= IEEE80211_TXCTL_REQUEUE; 1351d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg ieee80211_remove_tx_extra(local, sta->key, skb, 1352d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg &status->control); 1353d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg dev_queue_xmit(skb); 1354d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg return; 1355d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg } 1356d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 1357d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg if (net_ratelimit()) 1358d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg printk(KERN_DEBUG "%s: dropped TX filtered frame, " 1359d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg "queue_len=%d PS=%d @%lu\n", 1360d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg wiphy_name(local->hw.wiphy), 1361d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg skb_queue_len(&sta->tx_filtered), 1362d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg !!(sta->flags & WLAN_STA_PS), jiffies); 1363d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg dev_kfree_skb(skb); 1364d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg} 1365d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg 1366f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, 1367f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_tx_status *status) 1368f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1369f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sk_buff *skb2; 1370f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 1371f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 1372f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc u16 frag, type; 1373b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg struct ieee80211_tx_status_rtap_hdr *rthdr; 1374b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg struct ieee80211_sub_if_data *sdata; 13753d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu struct net_device *prev_dev = NULL; 1376f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1377f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (!status) { 1378f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_ERR 1379f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc "%s: ieee80211_tx_status called with NULL status\n", 1380dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg wiphy_name(local->hw.wiphy)); 1381f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb(skb); 1382f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return; 1383f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1384f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1385d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_lock(); 1386d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg 1387f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (status->excessive_retries) { 1388f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sta_info *sta; 1389f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta = sta_info_get(local, hdr->addr1); 1390f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (sta) { 1391f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (sta->flags & WLAN_STA_PS) { 1392d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg /* 1393d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg * The STA is in power save mode, so assume 1394f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * that this TX packet failed because of that. 1395f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc */ 1396f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc status->excessive_retries = 0; 1397f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc status->flags |= IEEE80211_TX_STATUS_TX_FILTERED; 1398d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg ieee80211_handle_filtered_frame(local, sta, 1399d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg skb, status); 1400d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 1401d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg return; 1402f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1403f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1404f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1405f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1406f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (status->flags & IEEE80211_TX_STATUS_TX_FILTERED) { 1407f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sta_info *sta; 1408f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta = sta_info_get(local, hdr->addr1); 1409f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (sta) { 1410d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg ieee80211_handle_filtered_frame(local, sta, skb, 1411d46e144b65bf053b25d134ec9f52a38e63e04bb4Johannes Berg status); 1412d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 1413f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return; 1414f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 14151abbe498e4b5e4f2000dfc30a0fa25be9553530eMattias Nissler } else 14161abbe498e4b5e4f2000dfc30a0fa25be9553530eMattias Nissler rate_control_tx_status(local->mdev, skb, status); 1417f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1418d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg rcu_read_unlock(); 1419d0709a65181beb787ef3f58cfe45536a2bb254c8Johannes Berg 1420f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_led_tx(local, 0); 1421f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1422f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* SNMP counters 1423f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * Fragments are passed to low-level drivers as separate skbs, so these 1424f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * are actually fragments, not frames. Update frame counters only for 1425f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * the first fragment of the frame. */ 1426f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1427f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; 1428f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE; 1429f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1430f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (status->flags & IEEE80211_TX_STATUS_ACK) { 1431f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (frag == 0) { 1432f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11TransmittedFrameCount++; 1433f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (is_multicast_ether_addr(hdr->addr1)) 1434f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11MulticastTransmittedFrameCount++; 1435f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (status->retry_count > 0) 1436f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11RetryCount++; 1437f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (status->retry_count > 1) 1438f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11MultipleRetryCount++; 1439f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1440f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1441f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* This counter shall be incremented for an acknowledged MPDU 1442f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * with an individual address in the address 1 field or an MPDU 1443f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * with a multicast address in the address 1 field of type Data 1444f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * or Management. */ 1445f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (!is_multicast_ether_addr(hdr->addr1) || 1446f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc type == IEEE80211_FTYPE_DATA || 1447f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc type == IEEE80211_FTYPE_MGMT) 1448f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11TransmittedFragmentCount++; 1449f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } else { 1450f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (frag == 0) 1451f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->dot11FailedCount++; 1452f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1453f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1454b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg /* this was a transmitted frame, but now we want to reuse it */ 1455b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg skb_orphan(skb); 1456b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 14573d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu /* 14583d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu * This is a bit racy but we can avoid a lot of work 14593d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu * with this test... 14603d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu */ 14613d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (!local->monitors && !local->cooked_mntrs) { 1462f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb(skb); 1463f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return; 1464f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1465f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1466b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg /* send frame to monitor interfaces now */ 1467f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1468b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg if (skb_headroom(skb) < sizeof(*rthdr)) { 1469b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg printk(KERN_ERR "ieee80211_tx_status: headroom too small\n"); 1470f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc dev_kfree_skb(skb); 1471f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return; 1472f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1473f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1474b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr = (struct ieee80211_tx_status_rtap_hdr*) 1475b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg skb_push(skb, sizeof(*rthdr)); 1476b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 1477b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg memset(rthdr, 0, sizeof(*rthdr)); 1478b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); 1479b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->hdr.it_present = 1480b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | 1481b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg (1 << IEEE80211_RADIOTAP_DATA_RETRIES)); 1482b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 1483b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg if (!(status->flags & IEEE80211_TX_STATUS_ACK) && 1484b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg !is_multicast_ether_addr(hdr->addr1)) 1485b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); 1486b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 1487b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg if ((status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) && 1488b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg (status->control.flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) 1489b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); 1490b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg else if (status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) 1491b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); 1492b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 1493b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg rthdr->data_retries = status->retry_count; 1494b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 14953d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu /* XXX: is this sufficient for BPF? */ 14963d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb_set_mac_header(skb, 0); 14973d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb->ip_summed = CHECKSUM_UNNECESSARY; 14983d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb->pkt_type = PACKET_OTHERHOST; 14993d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb->protocol = htons(ETH_P_802_2); 15003d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu memset(skb->cb, 0, sizeof(skb->cb)); 15013d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 150279010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg rcu_read_lock(); 150379010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg list_for_each_entry_rcu(sdata, &local->interfaces, list) { 150451fb61e76d952e6bc2fbdd9f0d38425fbab1cf31Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) { 1505b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg if (!netif_running(sdata->dev)) 1506b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg continue; 15073d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 15083d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (prev_dev) { 150979010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg skb2 = skb_clone(skb, GFP_ATOMIC); 15103d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (skb2) { 15113d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb2->dev = prev_dev; 15123d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu netif_rx(skb2); 15133d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 15143d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 15153d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu 15163d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu prev_dev = sdata->dev; 1517b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg } 1518b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg } 15193d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu if (prev_dev) { 15203d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb->dev = prev_dev; 15213d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu netif_rx(skb); 15223d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu skb = NULL; 15233d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu } 152479010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg rcu_read_unlock(); 15253d30d949cf3f9763393f3457721bca3ac2426e42Michael Wu dev_kfree_skb(skb); 1526f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1527f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_tx_status); 1528f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1529f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstruct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, 1530f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc const struct ieee80211_ops *ops) 1531f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1532f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local; 1533f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc int priv_size; 1534f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct wiphy *wiphy; 1535f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1536f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* Ensure 32-byte alignment of our private data and hw private data. 1537f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * We use the wiphy priv data for both our ieee80211_local and for 1538f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * the driver's private data 1539f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * 1540f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * In memory it'll be like this: 1541f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * 1542f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * +-------------------------+ 1543f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * | struct wiphy | 1544f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * +-------------------------+ 1545f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * | struct ieee80211_local | 1546f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * +-------------------------+ 1547f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * | driver's private data | 1548f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * +-------------------------+ 1549f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * 1550f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc */ 1551f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc priv_size = ((sizeof(struct ieee80211_local) + 1552f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) + 1553f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc priv_data_len; 1554f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1555f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy = wiphy_new(&mac80211_config_ops, priv_size); 1556f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1557f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (!wiphy) 1558f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return NULL; 1559f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1560f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy->privid = mac80211_wiphy_privid; 1561f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1562f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local = wiphy_priv(wiphy); 1563f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.wiphy = wiphy; 1564f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1565f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.priv = (char *)local + 1566f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ((sizeof(struct ieee80211_local) + 1567f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); 1568f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 15694480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg BUG_ON(!ops->tx); 15704150c57212ad134765dd78c654a4b9906252b66dJohannes Berg BUG_ON(!ops->start); 15714150c57212ad134765dd78c654a4b9906252b66dJohannes Berg BUG_ON(!ops->stop); 15724480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg BUG_ON(!ops->config); 15734480f15ca62a595248d6d8e2b3e75052113cde59Johannes Berg BUG_ON(!ops->add_interface); 15744150c57212ad134765dd78c654a4b9906252b66dJohannes Berg BUG_ON(!ops->remove_interface); 15754150c57212ad134765dd78c654a4b9906252b66dJohannes Berg BUG_ON(!ops->configure_filter); 1576f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->ops = ops; 1577f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1578f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.queues = 1; /* default */ 1579f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1580f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->bridge_packets = 1; 1581f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1582f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; 1583f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; 1584f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->short_retry_limit = 7; 1585f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->long_retry_limit = 4; 1586f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.conf.radio_enabled = 1; 1587f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 158879010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg INIT_LIST_HEAD(&local->interfaces); 1589f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1590f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work); 1591f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1592f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta_info_init(local); 1593f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1594f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, 1595f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc (unsigned long)local); 1596f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_disable(&local->tx_pending_tasklet); 1597f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1598f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_init(&local->tasklet, 1599f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_tasklet_handler, 1600f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc (unsigned long) local); 1601f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_disable(&local->tasklet); 1602f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1603f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_head_init(&local->skb_queue); 1604f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_head_init(&local->skb_queue_unreliable); 1605f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1606f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return local_to_hw(local); 1607f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1608f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_alloc_hw); 1609f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1610f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencint ieee80211_register_hw(struct ieee80211_hw *hw) 1611f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1612f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 1613f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc const char *name; 1614f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc int result; 16158318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg enum ieee80211_band band; 161696d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg struct net_device *mdev; 161796d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg struct ieee80211_sub_if_data *sdata; 16188318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 16198318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg /* 16208318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg * generic code guarantees at least one band, 16218318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg * set this very early because much code assumes 16228318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg * that hw.conf.channel is assigned 16238318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg */ 16248318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 16258318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg struct ieee80211_supported_band *sband; 16268318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 16278318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg sband = local->hw.wiphy->bands[band]; 16288318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg if (sband) { 16298318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg /* init channel we're on */ 16308318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->hw.conf.channel = 16318318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->oper_channel = 16328318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg local->scan_channel = &sband->channels[0]; 16338318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg break; 16348318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg } 16358318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg } 1636f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1637f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = wiphy_register(local->hw.wiphy); 1638f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) 1639f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return result; 1640f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 164196d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg /* for now, mdev needs sub_if_data :/ */ 164296d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev = alloc_netdev(sizeof(struct ieee80211_sub_if_data), 164396d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg "wmaster%d", ether_setup); 164496d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg if (!mdev) 164596d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg goto fail_mdev_alloc; 164696d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 164796d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg sdata = IEEE80211_DEV_TO_SUB_IF(mdev); 164896d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->ieee80211_ptr = &sdata->wdev; 164996d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg sdata->wdev.wiphy = local->hw.wiphy; 165096d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 165196d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg local->mdev = mdev; 165296d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 165396d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg ieee80211_rx_bss_list_init(mdev); 165496d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 165596d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->hard_start_xmit = ieee80211_master_start_xmit; 165696d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->open = ieee80211_master_open; 165796d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->stop = ieee80211_master_stop; 165896d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->type = ARPHRD_IEEE80211; 165996d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->header_ops = &ieee80211_header_ops; 166096d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg mdev->set_multicast_list = ieee80211_master_set_multicast_list; 166196d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 166296d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg sdata->vif.type = IEEE80211_IF_TYPE_AP; 166396d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg sdata->dev = mdev; 166496d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg sdata->local = local; 166596d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg sdata->u.ap.force_unicast_rateidx = -1; 166696d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg sdata->u.ap.max_ratectrl_rateidx = -1; 166796d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg ieee80211_if_sdata_init(sdata); 166896d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 166996d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg /* no RCU needed since we're still during init phase */ 167096d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg list_add_tail(&sdata->list, &local->interfaces); 167196d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg 1672f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc name = wiphy_dev(local->hw.wiphy)->driver->name; 1673f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.workqueue = create_singlethread_workqueue(name); 1674f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (!local->hw.workqueue) { 1675f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = -ENOMEM; 1676f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_workqueue; 1677f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1678f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1679b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg /* 1680b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg * The hardware needs headroom for sending the frame, 1681b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg * and we need some headroom for passing the frame to monitor 1682b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg * interfaces, but never both at the same time. 1683b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg */ 168433ccad35a21df51c0d23f3e3e88688524e7b51edJiri Benc local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom, 168533ccad35a21df51c0d23f3e3e88688524e7b51edJiri Benc sizeof(struct ieee80211_tx_status_rtap_hdr)); 1686b306f45300866adc01b84f7aa083bfcd9cbb89c4Johannes Berg 1687e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc debugfs_hw_add(local); 1688e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 1689f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->hw.conf.beacon_int = 1000; 1690f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1691f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->wstats_flags |= local->hw.max_rssi ? 1692f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc IW_QUAL_LEVEL_UPDATED : IW_QUAL_LEVEL_INVALID; 1693f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->wstats_flags |= local->hw.max_signal ? 1694f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID; 1695f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->wstats_flags |= local->hw.max_noise ? 1696f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID; 1697f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (local->hw.max_rssi < 0 || local->hw.max_noise < 0) 1698f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->wstats_flags |= IW_QUAL_DBM; 1699f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1700f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = sta_info_start(local); 1701f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) 1702f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_sta_info; 1703f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1704f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_lock(); 1705f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = dev_alloc_name(local->mdev, local->mdev->name); 1706f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) 1707f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_dev; 1708f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1709f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); 1710f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy)); 1711f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1712f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = register_netdevice(local->mdev); 1713f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) 1714f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_dev; 1715f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1716e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev)); 17175b2812e925c8e976852867f8d760637c5926d817Johannes Berg ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP); 1718e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 1719830f903866a1611e9ce53f3e35202302bb938946Johannes Berg result = ieee80211_init_rate_ctrl_alg(local, 1720830f903866a1611e9ce53f3e35202302bb938946Johannes Berg hw->rate_control_algorithm); 1721f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) { 1722f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_DEBUG "%s: Failed to initialize rate control " 1723dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg "algorithm\n", wiphy_name(local->hw.wiphy)); 1724f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_rate; 1725f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1726f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1727f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = ieee80211_wep_init(local); 1728f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1729f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result < 0) { 1730f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_DEBUG "%s: Failed to initialize wep\n", 1731dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg wiphy_name(local->hw.wiphy)); 1732f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc goto fail_wep; 1733f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1734f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1735f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_install_qdisc(local->mdev); 1736f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1737f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc /* add one default STA interface */ 1738f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc result = ieee80211_if_add(local->mdev, "wlan%d", NULL, 1739ee3858551ae6d044578f598f8001db5f1a9fd52eLuis Carlos Cobo IEEE80211_IF_TYPE_STA, NULL); 1740f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (result) 1741f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_WARNING "%s: Failed to add default virtual iface\n", 1742dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg wiphy_name(local->hw.wiphy)); 1743f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1744f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->reg_state = IEEE80211_DEV_REGISTERED; 1745f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_unlock(); 1746f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1747f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_led_init(local); 1748f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1749f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 1750f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1751f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_wep: 1752f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rate_control_deinitialize(local); 1753f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_rate: 1754e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev)); 1755f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc unregister_netdevice(local->mdev); 1756f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_dev: 1757f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_unlock(); 1758f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta_info_stop(local); 1759f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_sta_info: 1760e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc debugfs_hw_del(local); 1761f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc destroy_workqueue(local->hw.workqueue); 1762f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencfail_workqueue: 176396d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg ieee80211_if_free(local->mdev); 176496d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg local->mdev = NULL; 176596d510566e4908f77f03ff1436c78ae7162a17d0Johannes Bergfail_mdev_alloc: 1766f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy_unregister(local->hw.wiphy); 1767f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return result; 1768f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1769f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_register_hw); 1770f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1771f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_unregister_hw(struct ieee80211_hw *hw) 1772f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1773f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 1774f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_sub_if_data *sdata, *tmp; 1775f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1776f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_kill(&local->tx_pending_tasklet); 1777f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc tasklet_kill(&local->tasklet); 1778f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1779f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_lock(); 1780f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1781f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc BUG_ON(local->reg_state != IEEE80211_DEV_REGISTERED); 1782f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1783f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->reg_state = IEEE80211_DEV_UNREGISTERED; 1784f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 178579010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg /* 178679010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * At this point, interface list manipulations are fine 178779010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * because the driver cannot be handing us frames any 178879010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg * more and the tasklet is killed. 178979010420cc3f78eab911598bfdd29c4b06a83e1fJohannes Berg */ 17905b2812e925c8e976852867f8d760637c5926d817Johannes Berg 17915b2812e925c8e976852867f8d760637c5926d817Johannes Berg /* 17925b2812e925c8e976852867f8d760637c5926d817Johannes Berg * First, we remove all non-master interfaces. Do this because they 17935b2812e925c8e976852867f8d760637c5926d817Johannes Berg * may have bss pointer dependency on the master, and when we free 17945b2812e925c8e976852867f8d760637c5926d817Johannes Berg * the master these would be freed as well, breaking our list 17955b2812e925c8e976852867f8d760637c5926d817Johannes Berg * iteration completely. 17965b2812e925c8e976852867f8d760637c5926d817Johannes Berg */ 17975b2812e925c8e976852867f8d760637c5926d817Johannes Berg list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { 17985b2812e925c8e976852867f8d760637c5926d817Johannes Berg if (sdata->dev == local->mdev) 17995b2812e925c8e976852867f8d760637c5926d817Johannes Berg continue; 18005b2812e925c8e976852867f8d760637c5926d817Johannes Berg list_del(&sdata->list); 1801f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc __ieee80211_if_del(local, sdata); 18025b2812e925c8e976852867f8d760637c5926d817Johannes Berg } 18035b2812e925c8e976852867f8d760637c5926d817Johannes Berg 18045b2812e925c8e976852867f8d760637c5926d817Johannes Berg /* then, finally, remove the master interface */ 18055b2812e925c8e976852867f8d760637c5926d817Johannes Berg __ieee80211_if_del(local, IEEE80211_DEV_TO_SUB_IF(local->mdev)); 1806f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1807f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rtnl_unlock(); 1808f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1809f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_rx_bss_list_deinit(local->mdev); 1810f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_clear_tx_pending(local); 1811f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc sta_info_stop(local); 1812f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc rate_control_deinitialize(local); 1813e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc debugfs_hw_del(local); 1814f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1815f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (skb_queue_len(&local->skb_queue) 1816f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc || skb_queue_len(&local->skb_queue_unreliable)) 1817f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_WARNING "%s: skb_queue not empty\n", 1818dd1cd4c620c174ebbdf78dc01b924115a06de5d3Johannes Berg wiphy_name(local->hw.wiphy)); 1819f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_purge(&local->skb_queue); 1820f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc skb_queue_purge(&local->skb_queue_unreliable); 1821f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1822f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc destroy_workqueue(local->hw.workqueue); 1823f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy_unregister(local->hw.wiphy); 1824f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_wep_free(local); 1825f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_led_exit(local); 182696d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg ieee80211_if_free(local->mdev); 182796d510566e4908f77f03ff1436c78ae7162a17d0Johannes Berg local->mdev = NULL; 1828f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1829f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_unregister_hw); 1830f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1831f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_free_hw(struct ieee80211_hw *hw) 1832f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1833f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 1834f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1835f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc wiphy_free(local->hw.wiphy); 1836f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1837f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(ieee80211_free_hw); 1838f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1839f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic int __init ieee80211_init(void) 1840f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 1841f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct sk_buff *skb; 1842f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc int ret; 1843f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1844f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb)); 1845f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 18464b475898ec9dc6e62cebcb8fc0b3495c986a4590Johannes Berg ret = rc80211_pid_init(); 1847ad01837593338f13508463fa11c8dbf8109a1e5dMattias Nissler if (ret) 1848d9357136ac4729f589543afb6b1d17d443ae4f71Adrian Bunk goto out; 1849ac71c691e6a5ce991fe221d3bdb0c972f617aa37Johannes Berg 1850f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ret = ieee80211_wme_register(); 1851f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (ret) { 1852f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc printk(KERN_DEBUG "ieee80211_init: failed to " 1853f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc "initialize WME (err=%d)\n", ret); 18543eadf5f4f635ed6a6cd921195c320d58b5f9a185Johannes Berg goto out_cleanup_pid; 1855f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 1856f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1857e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc ieee80211_debugfs_netdev_init(); 1858e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 1859f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return 0; 1860ad01837593338f13508463fa11c8dbf8109a1e5dMattias Nissler 18613eadf5f4f635ed6a6cd921195c320d58b5f9a185Johannes Berg out_cleanup_pid: 18624b475898ec9dc6e62cebcb8fc0b3495c986a4590Johannes Berg rc80211_pid_exit(); 18633eadf5f4f635ed6a6cd921195c320d58b5f9a185Johannes Berg out: 1864ad01837593338f13508463fa11c8dbf8109a1e5dMattias Nissler return ret; 1865f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1866f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1867f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencstatic void __exit ieee80211_exit(void) 1868f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 18694b475898ec9dc6e62cebcb8fc0b3495c986a4590Johannes Berg rc80211_pid_exit(); 1870ac71c691e6a5ce991fe221d3bdb0c972f617aa37Johannes Berg 18713b96766f0e643f52ae19e134664df6730c737e87Johannes Berg /* 18723b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * For key todo, it'll be empty by now but the work 18733b96766f0e643f52ae19e134664df6730c737e87Johannes Berg * might still be scheduled. 18743b96766f0e643f52ae19e134664df6730c737e87Johannes Berg */ 18753b96766f0e643f52ae19e134664df6730c737e87Johannes Berg flush_scheduled_work(); 18763b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 1877f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo if (mesh_allocated) 1878f7a921443740d7dafc65b17aa32531730d358f50Luis Carlos Cobo ieee80211s_stop(); 1879902acc7896d7649fb30e4b22bd4e643c7f34b02cJohannes Berg 1880f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc ieee80211_wme_unregister(); 1881e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc ieee80211_debugfs_netdev_exit(); 1882f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 1883f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1884f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1885ca9938fea576ebbb8d8c4fbe8a5bcc937e49e1caJohannes Bergsubsys_initcall(ieee80211_init); 1886f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencmodule_exit(ieee80211_exit); 1887f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 1888f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencMODULE_DESCRIPTION("IEEE 802.11 subsystem"); 1889f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencMODULE_LICENSE("GPL"); 1890