1c2d1560aSJohannes Berg /* 2c2d1560aSJohannes Berg * Copyright 2002-2005, Instant802 Networks, Inc. 3c2d1560aSJohannes Berg * Copyright 2005-2006, Devicescape Software, Inc. 4c2d1560aSJohannes Berg * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 5c2d1560aSJohannes Berg * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 6c2d1560aSJohannes Berg * 7c2d1560aSJohannes Berg * This program is free software; you can redistribute it and/or modify 8c2d1560aSJohannes Berg * it under the terms of the GNU General Public License version 2 as 9c2d1560aSJohannes Berg * published by the Free Software Foundation. 10c2d1560aSJohannes Berg * 11c2d1560aSJohannes Berg * utilities for mac80211 12c2d1560aSJohannes Berg */ 13c2d1560aSJohannes Berg 14c2d1560aSJohannes Berg #include <net/mac80211.h> 15c2d1560aSJohannes Berg #include <linux/netdevice.h> 16c2d1560aSJohannes Berg #include <linux/types.h> 17c2d1560aSJohannes Berg #include <linux/slab.h> 18c2d1560aSJohannes Berg #include <linux/skbuff.h> 19c2d1560aSJohannes Berg #include <linux/etherdevice.h> 20c2d1560aSJohannes Berg #include <linux/if_arp.h> 21c2d1560aSJohannes Berg #include <linux/wireless.h> 22c2d1560aSJohannes Berg #include <linux/bitmap.h> 23881d966bSEric W. Biederman #include <net/net_namespace.h> 24c2d1560aSJohannes Berg #include <net/cfg80211.h> 25dabeb344SJohannes Berg #include <net/rtnetlink.h> 26c2d1560aSJohannes Berg 27c2d1560aSJohannes Berg #include "ieee80211_i.h" 282c8dccc7SJohannes Berg #include "rate.h" 29ee385855SLuis Carlos Cobo #include "mesh.h" 30c2d1560aSJohannes Berg #include "wme.h" 31c2d1560aSJohannes Berg 32c2d1560aSJohannes Berg /* privid for wiphys to determine whether they belong to us or not */ 33c2d1560aSJohannes Berg void *mac80211_wiphy_privid = &mac80211_wiphy_privid; 34c2d1560aSJohannes Berg 35c2d1560aSJohannes Berg /* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ 36c2d1560aSJohannes Berg /* Ethernet-II snap header (RFC1042 for most EtherTypes) */ 37c97c23e3SSenthil Balasubramanian const unsigned char rfc1042_header[] __aligned(2) = 38c2d1560aSJohannes Berg { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; 39c2d1560aSJohannes Berg 40c2d1560aSJohannes Berg /* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ 41c97c23e3SSenthil Balasubramanian const unsigned char bridge_tunnel_header[] __aligned(2) = 42c2d1560aSJohannes Berg { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; 43c2d1560aSJohannes Berg 44c2d1560aSJohannes Berg 4571364716SRon Rindjunsky u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, 4605c914feSJohannes Berg enum nl80211_iftype type) 47c2d1560aSJohannes Berg { 48a494bb1cSHarvey Harrison __le16 fc = hdr->frame_control; 49c2d1560aSJohannes Berg 5098f0b0a3SRon Rindjunsky /* drop ACK/CTS frames and incorrect hdr len (ctrl) */ 5198f0b0a3SRon Rindjunsky if (len < 16) 52c2d1560aSJohannes Berg return NULL; 53c2d1560aSJohannes Berg 54a494bb1cSHarvey Harrison if (ieee80211_is_data(fc)) { 5598f0b0a3SRon Rindjunsky if (len < 24) /* drop incorrect hdr len (data) */ 5698f0b0a3SRon Rindjunsky return NULL; 57a494bb1cSHarvey Harrison 58a494bb1cSHarvey Harrison if (ieee80211_has_a4(fc)) 59c2d1560aSJohannes Berg return NULL; 60a494bb1cSHarvey Harrison if (ieee80211_has_tods(fc)) 61a494bb1cSHarvey Harrison return hdr->addr1; 62a494bb1cSHarvey Harrison if (ieee80211_has_fromds(fc)) 63c2d1560aSJohannes Berg return hdr->addr2; 64a494bb1cSHarvey Harrison 65c2d1560aSJohannes Berg return hdr->addr3; 66c2d1560aSJohannes Berg } 67a494bb1cSHarvey Harrison 68a494bb1cSHarvey Harrison if (ieee80211_is_mgmt(fc)) { 6998f0b0a3SRon Rindjunsky if (len < 24) /* drop incorrect hdr len (mgmt) */ 7098f0b0a3SRon Rindjunsky return NULL; 71c2d1560aSJohannes Berg return hdr->addr3; 72a494bb1cSHarvey Harrison } 73a494bb1cSHarvey Harrison 74a494bb1cSHarvey Harrison if (ieee80211_is_ctl(fc)) { 75a494bb1cSHarvey Harrison if(ieee80211_is_pspoll(fc)) 76c2d1560aSJohannes Berg return hdr->addr1; 77a494bb1cSHarvey Harrison 78a494bb1cSHarvey Harrison if (ieee80211_is_back_req(fc)) { 7971364716SRon Rindjunsky switch (type) { 8005c914feSJohannes Berg case NL80211_IFTYPE_STATION: 8171364716SRon Rindjunsky return hdr->addr2; 8205c914feSJohannes Berg case NL80211_IFTYPE_AP: 8305c914feSJohannes Berg case NL80211_IFTYPE_AP_VLAN: 8471364716SRon Rindjunsky return hdr->addr1; 8571364716SRon Rindjunsky default: 86a494bb1cSHarvey Harrison break; /* fall through to the return */ 8771364716SRon Rindjunsky } 8871364716SRon Rindjunsky } 89c2d1560aSJohannes Berg } 90c2d1560aSJohannes Berg 91c2d1560aSJohannes Berg return NULL; 92c2d1560aSJohannes Berg } 93c2d1560aSJohannes Berg 946693be71SHarvey Harrison unsigned int ieee80211_hdrlen(__le16 fc) 956693be71SHarvey Harrison { 966693be71SHarvey Harrison unsigned int hdrlen = 24; 976693be71SHarvey Harrison 986693be71SHarvey Harrison if (ieee80211_is_data(fc)) { 996693be71SHarvey Harrison if (ieee80211_has_a4(fc)) 1006693be71SHarvey Harrison hdrlen = 30; 1016693be71SHarvey Harrison if (ieee80211_is_data_qos(fc)) 1026693be71SHarvey Harrison hdrlen += IEEE80211_QOS_CTL_LEN; 1036693be71SHarvey Harrison goto out; 1046693be71SHarvey Harrison } 1056693be71SHarvey Harrison 1066693be71SHarvey Harrison if (ieee80211_is_ctl(fc)) { 1076693be71SHarvey Harrison /* 1086693be71SHarvey Harrison * ACK and CTS are 10 bytes, all others 16. To see how 1096693be71SHarvey Harrison * to get this condition consider 1106693be71SHarvey Harrison * subtype mask: 0b0000000011110000 (0x00F0) 1116693be71SHarvey Harrison * ACK subtype: 0b0000000011010000 (0x00D0) 1126693be71SHarvey Harrison * CTS subtype: 0b0000000011000000 (0x00C0) 1136693be71SHarvey Harrison * bits that matter: ^^^ (0x00E0) 1146693be71SHarvey Harrison * value of those: 0b0000000011000000 (0x00C0) 1156693be71SHarvey Harrison */ 1166693be71SHarvey Harrison if ((fc & cpu_to_le16(0x00E0)) == cpu_to_le16(0x00C0)) 1176693be71SHarvey Harrison hdrlen = 10; 1186693be71SHarvey Harrison else 1196693be71SHarvey Harrison hdrlen = 16; 1206693be71SHarvey Harrison } 1216693be71SHarvey Harrison out: 1226693be71SHarvey Harrison return hdrlen; 1236693be71SHarvey Harrison } 1246693be71SHarvey Harrison EXPORT_SYMBOL(ieee80211_hdrlen); 1256693be71SHarvey Harrison 126c9c6950cSHarvey Harrison unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb) 127c2d1560aSJohannes Berg { 128c2d1560aSJohannes Berg const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *)skb->data; 129c9c6950cSHarvey Harrison unsigned int hdrlen; 130c2d1560aSJohannes Berg 131c2d1560aSJohannes Berg if (unlikely(skb->len < 10)) 132c2d1560aSJohannes Berg return 0; 133c9c6950cSHarvey Harrison hdrlen = ieee80211_hdrlen(hdr->frame_control); 134c2d1560aSJohannes Berg if (unlikely(hdrlen > skb->len)) 135c2d1560aSJohannes Berg return 0; 136c2d1560aSJohannes Berg return hdrlen; 137c2d1560aSJohannes Berg } 138c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); 139c2d1560aSJohannes Berg 140ee385855SLuis Carlos Cobo int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) 141ee385855SLuis Carlos Cobo { 142ee385855SLuis Carlos Cobo int ae = meshhdr->flags & IEEE80211S_FLAGS_AE; 143ee385855SLuis Carlos Cobo /* 7.1.3.5a.2 */ 144ee385855SLuis Carlos Cobo switch (ae) { 145ee385855SLuis Carlos Cobo case 0: 146ef269254SLuis Carlos Cobo return 6; 147ee385855SLuis Carlos Cobo case 1: 148ef269254SLuis Carlos Cobo return 12; 149ee385855SLuis Carlos Cobo case 2: 150ef269254SLuis Carlos Cobo return 18; 151ee385855SLuis Carlos Cobo case 3: 152ef269254SLuis Carlos Cobo return 24; 153ee385855SLuis Carlos Cobo default: 154ef269254SLuis Carlos Cobo return 6; 155ee385855SLuis Carlos Cobo } 156ee385855SLuis Carlos Cobo } 157ee385855SLuis Carlos Cobo 1585cf121c3SJohannes Berg void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) 159c2d1560aSJohannes Berg { 160c2d1560aSJohannes Berg struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; 161c2d1560aSJohannes Berg 162c2d1560aSJohannes Berg hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); 1635cf121c3SJohannes Berg if (tx->extra_frag) { 164c2d1560aSJohannes Berg struct ieee80211_hdr *fhdr; 165c2d1560aSJohannes Berg int i; 1665cf121c3SJohannes Berg for (i = 0; i < tx->num_extra_frag; i++) { 167c2d1560aSJohannes Berg fhdr = (struct ieee80211_hdr *) 1685cf121c3SJohannes Berg tx->extra_frag[i]->data; 169c2d1560aSJohannes Berg fhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); 170c2d1560aSJohannes Berg } 171c2d1560aSJohannes Berg } 172c2d1560aSJohannes Berg } 173c2d1560aSJohannes Berg 174c2d1560aSJohannes Berg int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, 175c2d1560aSJohannes Berg int rate, int erp, int short_preamble) 176c2d1560aSJohannes Berg { 177c2d1560aSJohannes Berg int dur; 178c2d1560aSJohannes Berg 179c2d1560aSJohannes Berg /* calculate duration (in microseconds, rounded up to next higher 180c2d1560aSJohannes Berg * integer if it includes a fractional microsecond) to send frame of 181c2d1560aSJohannes Berg * len bytes (does not include FCS) at the given rate. Duration will 182c2d1560aSJohannes Berg * also include SIFS. 183c2d1560aSJohannes Berg * 184c2d1560aSJohannes Berg * rate is in 100 kbps, so divident is multiplied by 10 in the 185c2d1560aSJohannes Berg * DIV_ROUND_UP() operations. 186c2d1560aSJohannes Berg */ 187c2d1560aSJohannes Berg 1888318d78aSJohannes Berg if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ || erp) { 189c2d1560aSJohannes Berg /* 190c2d1560aSJohannes Berg * OFDM: 191c2d1560aSJohannes Berg * 192c2d1560aSJohannes Berg * N_DBPS = DATARATE x 4 193c2d1560aSJohannes Berg * N_SYM = Ceiling((16+8xLENGTH+6) / N_DBPS) 194c2d1560aSJohannes Berg * (16 = SIGNAL time, 6 = tail bits) 195c2d1560aSJohannes Berg * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext 196c2d1560aSJohannes Berg * 197c2d1560aSJohannes Berg * T_SYM = 4 usec 198c2d1560aSJohannes Berg * 802.11a - 17.5.2: aSIFSTime = 16 usec 199c2d1560aSJohannes Berg * 802.11g - 19.8.4: aSIFSTime = 10 usec + 200c2d1560aSJohannes Berg * signal ext = 6 usec 201c2d1560aSJohannes Berg */ 202c2d1560aSJohannes Berg dur = 16; /* SIFS + signal ext */ 203c2d1560aSJohannes Berg dur += 16; /* 17.3.2.3: T_PREAMBLE = 16 usec */ 204c2d1560aSJohannes Berg dur += 4; /* 17.3.2.3: T_SIGNAL = 4 usec */ 205c2d1560aSJohannes Berg dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10, 206c2d1560aSJohannes Berg 4 * rate); /* T_SYM x N_SYM */ 207c2d1560aSJohannes Berg } else { 208c2d1560aSJohannes Berg /* 209c2d1560aSJohannes Berg * 802.11b or 802.11g with 802.11b compatibility: 210c2d1560aSJohannes Berg * 18.3.4: TXTIME = PreambleLength + PLCPHeaderTime + 211c2d1560aSJohannes Berg * Ceiling(((LENGTH+PBCC)x8)/DATARATE). PBCC=0. 212c2d1560aSJohannes Berg * 213c2d1560aSJohannes Berg * 802.11 (DS): 15.3.3, 802.11b: 18.3.4 214c2d1560aSJohannes Berg * aSIFSTime = 10 usec 215c2d1560aSJohannes Berg * aPreambleLength = 144 usec or 72 usec with short preamble 216c2d1560aSJohannes Berg * aPLCPHeaderLength = 48 usec or 24 usec with short preamble 217c2d1560aSJohannes Berg */ 218c2d1560aSJohannes Berg dur = 10; /* aSIFSTime = 10 usec */ 219c2d1560aSJohannes Berg dur += short_preamble ? (72 + 24) : (144 + 48); 220c2d1560aSJohannes Berg 221c2d1560aSJohannes Berg dur += DIV_ROUND_UP(8 * (len + 4) * 10, rate); 222c2d1560aSJohannes Berg } 223c2d1560aSJohannes Berg 224c2d1560aSJohannes Berg return dur; 225c2d1560aSJohannes Berg } 226c2d1560aSJohannes Berg 227c2d1560aSJohannes Berg /* Exported duration function for driver use */ 22832bfd35dSJohannes Berg __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, 22932bfd35dSJohannes Berg struct ieee80211_vif *vif, 2308318d78aSJohannes Berg size_t frame_len, 2318318d78aSJohannes Berg struct ieee80211_rate *rate) 232c2d1560aSJohannes Berg { 233c2d1560aSJohannes Berg struct ieee80211_local *local = hw_to_local(hw); 23425d834e1SJohannes Berg struct ieee80211_sub_if_data *sdata; 235c2d1560aSJohannes Berg u16 dur; 236c2d1560aSJohannes Berg int erp; 23725d834e1SJohannes Berg bool short_preamble = false; 238c2d1560aSJohannes Berg 2398318d78aSJohannes Berg erp = 0; 24025d834e1SJohannes Berg if (vif) { 24125d834e1SJohannes Berg sdata = vif_to_sdata(vif); 24225d834e1SJohannes Berg short_preamble = sdata->bss_conf.use_short_preamble; 2438318d78aSJohannes Berg if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) 2448318d78aSJohannes Berg erp = rate->flags & IEEE80211_RATE_ERP_G; 24525d834e1SJohannes Berg } 2468318d78aSJohannes Berg 2478318d78aSJohannes Berg dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, 24825d834e1SJohannes Berg short_preamble); 249c2d1560aSJohannes Berg 250c2d1560aSJohannes Berg return cpu_to_le16(dur); 251c2d1560aSJohannes Berg } 252c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_generic_frame_duration); 253c2d1560aSJohannes Berg 25432bfd35dSJohannes Berg __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, 25532bfd35dSJohannes Berg struct ieee80211_vif *vif, size_t frame_len, 256e039fa4aSJohannes Berg const struct ieee80211_tx_info *frame_txctl) 257c2d1560aSJohannes Berg { 258c2d1560aSJohannes Berg struct ieee80211_local *local = hw_to_local(hw); 259c2d1560aSJohannes Berg struct ieee80211_rate *rate; 26025d834e1SJohannes Berg struct ieee80211_sub_if_data *sdata; 261471b3efdSJohannes Berg bool short_preamble; 262c2d1560aSJohannes Berg int erp; 263c2d1560aSJohannes Berg u16 dur; 2642e92e6f2SJohannes Berg struct ieee80211_supported_band *sband; 2652e92e6f2SJohannes Berg 2662e92e6f2SJohannes Berg sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 267c2d1560aSJohannes Berg 26825d834e1SJohannes Berg short_preamble = false; 2697e9ed188SDaniel Drake 270e039fa4aSJohannes Berg rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; 2718318d78aSJohannes Berg 2728318d78aSJohannes Berg erp = 0; 27325d834e1SJohannes Berg if (vif) { 27425d834e1SJohannes Berg sdata = vif_to_sdata(vif); 27525d834e1SJohannes Berg short_preamble = sdata->bss_conf.use_short_preamble; 2768318d78aSJohannes Berg if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) 2778318d78aSJohannes Berg erp = rate->flags & IEEE80211_RATE_ERP_G; 27825d834e1SJohannes Berg } 279c2d1560aSJohannes Berg 280c2d1560aSJohannes Berg /* CTS duration */ 2818318d78aSJohannes Berg dur = ieee80211_frame_duration(local, 10, rate->bitrate, 282c2d1560aSJohannes Berg erp, short_preamble); 283c2d1560aSJohannes Berg /* Data frame duration */ 2848318d78aSJohannes Berg dur += ieee80211_frame_duration(local, frame_len, rate->bitrate, 285c2d1560aSJohannes Berg erp, short_preamble); 286c2d1560aSJohannes Berg /* ACK duration */ 2878318d78aSJohannes Berg dur += ieee80211_frame_duration(local, 10, rate->bitrate, 288c2d1560aSJohannes Berg erp, short_preamble); 289c2d1560aSJohannes Berg 290c2d1560aSJohannes Berg return cpu_to_le16(dur); 291c2d1560aSJohannes Berg } 292c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_rts_duration); 293c2d1560aSJohannes Berg 29432bfd35dSJohannes Berg __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, 29532bfd35dSJohannes Berg struct ieee80211_vif *vif, 296c2d1560aSJohannes Berg size_t frame_len, 297e039fa4aSJohannes Berg const struct ieee80211_tx_info *frame_txctl) 298c2d1560aSJohannes Berg { 299c2d1560aSJohannes Berg struct ieee80211_local *local = hw_to_local(hw); 300c2d1560aSJohannes Berg struct ieee80211_rate *rate; 30125d834e1SJohannes Berg struct ieee80211_sub_if_data *sdata; 302471b3efdSJohannes Berg bool short_preamble; 303c2d1560aSJohannes Berg int erp; 304c2d1560aSJohannes Berg u16 dur; 3052e92e6f2SJohannes Berg struct ieee80211_supported_band *sband; 3062e92e6f2SJohannes Berg 3072e92e6f2SJohannes Berg sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 308c2d1560aSJohannes Berg 30925d834e1SJohannes Berg short_preamble = false; 3107e9ed188SDaniel Drake 311e039fa4aSJohannes Berg rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; 3128318d78aSJohannes Berg erp = 0; 31325d834e1SJohannes Berg if (vif) { 31425d834e1SJohannes Berg sdata = vif_to_sdata(vif); 31525d834e1SJohannes Berg short_preamble = sdata->bss_conf.use_short_preamble; 3168318d78aSJohannes Berg if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) 3178318d78aSJohannes Berg erp = rate->flags & IEEE80211_RATE_ERP_G; 31825d834e1SJohannes Berg } 319c2d1560aSJohannes Berg 320c2d1560aSJohannes Berg /* Data frame duration */ 3218318d78aSJohannes Berg dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, 322c2d1560aSJohannes Berg erp, short_preamble); 323e039fa4aSJohannes Berg if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) { 324c2d1560aSJohannes Berg /* ACK duration */ 3258318d78aSJohannes Berg dur += ieee80211_frame_duration(local, 10, rate->bitrate, 326c2d1560aSJohannes Berg erp, short_preamble); 327c2d1560aSJohannes Berg } 328c2d1560aSJohannes Berg 329c2d1560aSJohannes Berg return cpu_to_le16(dur); 330c2d1560aSJohannes Berg } 331c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_ctstoself_duration); 332c2d1560aSJohannes Berg 333c2d1560aSJohannes Berg void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) 334c2d1560aSJohannes Berg { 335c2d1560aSJohannes Berg struct ieee80211_local *local = hw_to_local(hw); 336c2d1560aSJohannes Berg 337e2530083SJohannes Berg if (test_bit(queue, local->queues_pending)) { 338f8e79dddSTomas Winkler set_bit(queue, local->queues_pending_run); 339c2d1560aSJohannes Berg tasklet_schedule(&local->tx_pending_tasklet); 340e2530083SJohannes Berg } else { 341e2530083SJohannes Berg netif_wake_subqueue(local->mdev, queue); 342c2d1560aSJohannes Berg } 343c2d1560aSJohannes Berg } 344c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_wake_queue); 345c2d1560aSJohannes Berg 346c2d1560aSJohannes Berg void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) 347c2d1560aSJohannes Berg { 348c2d1560aSJohannes Berg struct ieee80211_local *local = hw_to_local(hw); 349c2d1560aSJohannes Berg 350e2530083SJohannes Berg netif_stop_subqueue(local->mdev, queue); 351c2d1560aSJohannes Berg } 352c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_stop_queue); 353c2d1560aSJohannes Berg 354c2d1560aSJohannes Berg void ieee80211_stop_queues(struct ieee80211_hw *hw) 355c2d1560aSJohannes Berg { 356c2d1560aSJohannes Berg int i; 357c2d1560aSJohannes Berg 358e2530083SJohannes Berg for (i = 0; i < ieee80211_num_queues(hw); i++) 359c2d1560aSJohannes Berg ieee80211_stop_queue(hw, i); 360c2d1560aSJohannes Berg } 361c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_stop_queues); 362c2d1560aSJohannes Berg 36392ab8535STomas Winkler int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) 36492ab8535STomas Winkler { 36592ab8535STomas Winkler struct ieee80211_local *local = hw_to_local(hw); 36692ab8535STomas Winkler return __netif_subqueue_stopped(local->mdev, queue); 36792ab8535STomas Winkler } 36892ab8535STomas Winkler EXPORT_SYMBOL(ieee80211_queue_stopped); 36992ab8535STomas Winkler 370c2d1560aSJohannes Berg void ieee80211_wake_queues(struct ieee80211_hw *hw) 371c2d1560aSJohannes Berg { 372c2d1560aSJohannes Berg int i; 373c2d1560aSJohannes Berg 374c4680470SJohannes Berg for (i = 0; i < hw->queues + hw->ampdu_queues; i++) 375c2d1560aSJohannes Berg ieee80211_wake_queue(hw, i); 376c2d1560aSJohannes Berg } 377c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_wake_queues); 378dabeb344SJohannes Berg 37932bfd35dSJohannes Berg void ieee80211_iterate_active_interfaces( 38032bfd35dSJohannes Berg struct ieee80211_hw *hw, 381dabeb344SJohannes Berg void (*iterator)(void *data, u8 *mac, 38232bfd35dSJohannes Berg struct ieee80211_vif *vif), 383dabeb344SJohannes Berg void *data) 384dabeb344SJohannes Berg { 385dabeb344SJohannes Berg struct ieee80211_local *local = hw_to_local(hw); 386dabeb344SJohannes Berg struct ieee80211_sub_if_data *sdata; 387dabeb344SJohannes Berg 3882f561febSIvo van Doorn rtnl_lock(); 3892f561febSIvo van Doorn 3902f561febSIvo van Doorn list_for_each_entry(sdata, &local->interfaces, list) { 3912f561febSIvo van Doorn switch (sdata->vif.type) { 39205c914feSJohannes Berg case __NL80211_IFTYPE_AFTER_LAST: 39305c914feSJohannes Berg case NL80211_IFTYPE_UNSPECIFIED: 39405c914feSJohannes Berg case NL80211_IFTYPE_MONITOR: 39505c914feSJohannes Berg case NL80211_IFTYPE_AP_VLAN: 3962f561febSIvo van Doorn continue; 39705c914feSJohannes Berg case NL80211_IFTYPE_AP: 39805c914feSJohannes Berg case NL80211_IFTYPE_STATION: 39905c914feSJohannes Berg case NL80211_IFTYPE_ADHOC: 40005c914feSJohannes Berg case NL80211_IFTYPE_WDS: 40105c914feSJohannes Berg case NL80211_IFTYPE_MESH_POINT: 4022f561febSIvo van Doorn break; 4032f561febSIvo van Doorn } 4042f561febSIvo van Doorn if (netif_running(sdata->dev)) 4052f561febSIvo van Doorn iterator(data, sdata->dev->dev_addr, 4062f561febSIvo van Doorn &sdata->vif); 4072f561febSIvo van Doorn } 4082f561febSIvo van Doorn 4092f561febSIvo van Doorn rtnl_unlock(); 4102f561febSIvo van Doorn } 4112f561febSIvo van Doorn EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); 4122f561febSIvo van Doorn 4132f561febSIvo van Doorn void ieee80211_iterate_active_interfaces_atomic( 4142f561febSIvo van Doorn struct ieee80211_hw *hw, 4152f561febSIvo van Doorn void (*iterator)(void *data, u8 *mac, 4162f561febSIvo van Doorn struct ieee80211_vif *vif), 4172f561febSIvo van Doorn void *data) 4182f561febSIvo van Doorn { 4192f561febSIvo van Doorn struct ieee80211_local *local = hw_to_local(hw); 4202f561febSIvo van Doorn struct ieee80211_sub_if_data *sdata; 4212f561febSIvo van Doorn 422e38bad47SJohannes Berg rcu_read_lock(); 423dabeb344SJohannes Berg 424e38bad47SJohannes Berg list_for_each_entry_rcu(sdata, &local->interfaces, list) { 42551fb61e7SJohannes Berg switch (sdata->vif.type) { 42605c914feSJohannes Berg case __NL80211_IFTYPE_AFTER_LAST: 42705c914feSJohannes Berg case NL80211_IFTYPE_UNSPECIFIED: 42805c914feSJohannes Berg case NL80211_IFTYPE_MONITOR: 42905c914feSJohannes Berg case NL80211_IFTYPE_AP_VLAN: 430dabeb344SJohannes Berg continue; 43105c914feSJohannes Berg case NL80211_IFTYPE_AP: 43205c914feSJohannes Berg case NL80211_IFTYPE_STATION: 43305c914feSJohannes Berg case NL80211_IFTYPE_ADHOC: 43405c914feSJohannes Berg case NL80211_IFTYPE_WDS: 43505c914feSJohannes Berg case NL80211_IFTYPE_MESH_POINT: 436dabeb344SJohannes Berg break; 437dabeb344SJohannes Berg } 438dabeb344SJohannes Berg if (netif_running(sdata->dev)) 439dabeb344SJohannes Berg iterator(data, sdata->dev->dev_addr, 44032bfd35dSJohannes Berg &sdata->vif); 441dabeb344SJohannes Berg } 442e38bad47SJohannes Berg 443e38bad47SJohannes Berg rcu_read_unlock(); 444dabeb344SJohannes Berg } 4452f561febSIvo van Doorn EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); 44637ffc8daSJohannes Berg 44737ffc8daSJohannes Berg void ieee802_11_parse_elems(u8 *start, size_t len, 44837ffc8daSJohannes Berg struct ieee802_11_elems *elems) 44937ffc8daSJohannes Berg { 45037ffc8daSJohannes Berg size_t left = len; 45137ffc8daSJohannes Berg u8 *pos = start; 45237ffc8daSJohannes Berg 45337ffc8daSJohannes Berg memset(elems, 0, sizeof(*elems)); 45437ffc8daSJohannes Berg elems->ie_start = start; 45537ffc8daSJohannes Berg elems->total_len = len; 45637ffc8daSJohannes Berg 45737ffc8daSJohannes Berg while (left >= 2) { 45837ffc8daSJohannes Berg u8 id, elen; 45937ffc8daSJohannes Berg 46037ffc8daSJohannes Berg id = *pos++; 46137ffc8daSJohannes Berg elen = *pos++; 46237ffc8daSJohannes Berg left -= 2; 46337ffc8daSJohannes Berg 46437ffc8daSJohannes Berg if (elen > left) 46537ffc8daSJohannes Berg return; 46637ffc8daSJohannes Berg 46737ffc8daSJohannes Berg switch (id) { 46837ffc8daSJohannes Berg case WLAN_EID_SSID: 46937ffc8daSJohannes Berg elems->ssid = pos; 47037ffc8daSJohannes Berg elems->ssid_len = elen; 47137ffc8daSJohannes Berg break; 47237ffc8daSJohannes Berg case WLAN_EID_SUPP_RATES: 47337ffc8daSJohannes Berg elems->supp_rates = pos; 47437ffc8daSJohannes Berg elems->supp_rates_len = elen; 47537ffc8daSJohannes Berg break; 47637ffc8daSJohannes Berg case WLAN_EID_FH_PARAMS: 47737ffc8daSJohannes Berg elems->fh_params = pos; 47837ffc8daSJohannes Berg elems->fh_params_len = elen; 47937ffc8daSJohannes Berg break; 48037ffc8daSJohannes Berg case WLAN_EID_DS_PARAMS: 48137ffc8daSJohannes Berg elems->ds_params = pos; 48237ffc8daSJohannes Berg elems->ds_params_len = elen; 48337ffc8daSJohannes Berg break; 48437ffc8daSJohannes Berg case WLAN_EID_CF_PARAMS: 48537ffc8daSJohannes Berg elems->cf_params = pos; 48637ffc8daSJohannes Berg elems->cf_params_len = elen; 48737ffc8daSJohannes Berg break; 48837ffc8daSJohannes Berg case WLAN_EID_TIM: 48937ffc8daSJohannes Berg elems->tim = pos; 49037ffc8daSJohannes Berg elems->tim_len = elen; 49137ffc8daSJohannes Berg break; 49237ffc8daSJohannes Berg case WLAN_EID_IBSS_PARAMS: 49337ffc8daSJohannes Berg elems->ibss_params = pos; 49437ffc8daSJohannes Berg elems->ibss_params_len = elen; 49537ffc8daSJohannes Berg break; 49637ffc8daSJohannes Berg case WLAN_EID_CHALLENGE: 49737ffc8daSJohannes Berg elems->challenge = pos; 49837ffc8daSJohannes Berg elems->challenge_len = elen; 49937ffc8daSJohannes Berg break; 50037ffc8daSJohannes Berg case WLAN_EID_WPA: 50137ffc8daSJohannes Berg if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && 50237ffc8daSJohannes Berg pos[2] == 0xf2) { 50337ffc8daSJohannes Berg /* Microsoft OUI (00:50:F2) */ 50437ffc8daSJohannes Berg if (pos[3] == 1) { 50537ffc8daSJohannes Berg /* OUI Type 1 - WPA IE */ 50637ffc8daSJohannes Berg elems->wpa = pos; 50737ffc8daSJohannes Berg elems->wpa_len = elen; 50837ffc8daSJohannes Berg } else if (elen >= 5 && pos[3] == 2) { 50937ffc8daSJohannes Berg if (pos[4] == 0) { 51037ffc8daSJohannes Berg elems->wmm_info = pos; 51137ffc8daSJohannes Berg elems->wmm_info_len = elen; 51237ffc8daSJohannes Berg } else if (pos[4] == 1) { 51337ffc8daSJohannes Berg elems->wmm_param = pos; 51437ffc8daSJohannes Berg elems->wmm_param_len = elen; 51537ffc8daSJohannes Berg } 51637ffc8daSJohannes Berg } 51737ffc8daSJohannes Berg } 51837ffc8daSJohannes Berg break; 51937ffc8daSJohannes Berg case WLAN_EID_RSN: 52037ffc8daSJohannes Berg elems->rsn = pos; 52137ffc8daSJohannes Berg elems->rsn_len = elen; 52237ffc8daSJohannes Berg break; 52337ffc8daSJohannes Berg case WLAN_EID_ERP_INFO: 52437ffc8daSJohannes Berg elems->erp_info = pos; 52537ffc8daSJohannes Berg elems->erp_info_len = elen; 52637ffc8daSJohannes Berg break; 52737ffc8daSJohannes Berg case WLAN_EID_EXT_SUPP_RATES: 52837ffc8daSJohannes Berg elems->ext_supp_rates = pos; 52937ffc8daSJohannes Berg elems->ext_supp_rates_len = elen; 53037ffc8daSJohannes Berg break; 53137ffc8daSJohannes Berg case WLAN_EID_HT_CAPABILITY: 53209914813SJohannes Berg if (elen >= sizeof(struct ieee80211_ht_cap)) 53309914813SJohannes Berg elems->ht_cap_elem = (void *)pos; 53437ffc8daSJohannes Berg break; 53537ffc8daSJohannes Berg case WLAN_EID_HT_EXTRA_INFO: 53609914813SJohannes Berg if (elen >= sizeof(struct ieee80211_ht_addt_info)) 53709914813SJohannes Berg elems->ht_info_elem = (void *)pos; 53837ffc8daSJohannes Berg break; 53937ffc8daSJohannes Berg case WLAN_EID_MESH_ID: 54037ffc8daSJohannes Berg elems->mesh_id = pos; 54137ffc8daSJohannes Berg elems->mesh_id_len = elen; 54237ffc8daSJohannes Berg break; 54337ffc8daSJohannes Berg case WLAN_EID_MESH_CONFIG: 54437ffc8daSJohannes Berg elems->mesh_config = pos; 54537ffc8daSJohannes Berg elems->mesh_config_len = elen; 54637ffc8daSJohannes Berg break; 54737ffc8daSJohannes Berg case WLAN_EID_PEER_LINK: 54837ffc8daSJohannes Berg elems->peer_link = pos; 54937ffc8daSJohannes Berg elems->peer_link_len = elen; 55037ffc8daSJohannes Berg break; 55137ffc8daSJohannes Berg case WLAN_EID_PREQ: 55237ffc8daSJohannes Berg elems->preq = pos; 55337ffc8daSJohannes Berg elems->preq_len = elen; 55437ffc8daSJohannes Berg break; 55537ffc8daSJohannes Berg case WLAN_EID_PREP: 55637ffc8daSJohannes Berg elems->prep = pos; 55737ffc8daSJohannes Berg elems->prep_len = elen; 55837ffc8daSJohannes Berg break; 55937ffc8daSJohannes Berg case WLAN_EID_PERR: 56037ffc8daSJohannes Berg elems->perr = pos; 56137ffc8daSJohannes Berg elems->perr_len = elen; 56237ffc8daSJohannes Berg break; 56337ffc8daSJohannes Berg case WLAN_EID_CHANNEL_SWITCH: 56437ffc8daSJohannes Berg elems->ch_switch_elem = pos; 56537ffc8daSJohannes Berg elems->ch_switch_elem_len = elen; 56637ffc8daSJohannes Berg break; 56737ffc8daSJohannes Berg case WLAN_EID_QUIET: 56837ffc8daSJohannes Berg if (!elems->quiet_elem) { 56937ffc8daSJohannes Berg elems->quiet_elem = pos; 57037ffc8daSJohannes Berg elems->quiet_elem_len = elen; 57137ffc8daSJohannes Berg } 57237ffc8daSJohannes Berg elems->num_of_quiet_elem++; 57337ffc8daSJohannes Berg break; 57437ffc8daSJohannes Berg case WLAN_EID_COUNTRY: 57537ffc8daSJohannes Berg elems->country_elem = pos; 57637ffc8daSJohannes Berg elems->country_elem_len = elen; 57737ffc8daSJohannes Berg break; 57837ffc8daSJohannes Berg case WLAN_EID_PWR_CONSTRAINT: 57937ffc8daSJohannes Berg elems->pwr_constr_elem = pos; 58037ffc8daSJohannes Berg elems->pwr_constr_elem_len = elen; 58137ffc8daSJohannes Berg break; 58237ffc8daSJohannes Berg default: 58337ffc8daSJohannes Berg break; 58437ffc8daSJohannes Berg } 58537ffc8daSJohannes Berg 58637ffc8daSJohannes Berg left -= elen; 58737ffc8daSJohannes Berg pos += elen; 58837ffc8daSJohannes Berg } 58937ffc8daSJohannes Berg } 5905825fe10SJohannes Berg 5915825fe10SJohannes Berg void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) 5925825fe10SJohannes Berg { 5935825fe10SJohannes Berg struct ieee80211_local *local = sdata->local; 5945825fe10SJohannes Berg struct ieee80211_tx_queue_params qparam; 5955825fe10SJohannes Berg int i; 5965825fe10SJohannes Berg 5975825fe10SJohannes Berg if (!local->ops->conf_tx) 5985825fe10SJohannes Berg return; 5995825fe10SJohannes Berg 6005825fe10SJohannes Berg memset(&qparam, 0, sizeof(qparam)); 6015825fe10SJohannes Berg 6025825fe10SJohannes Berg qparam.aifs = 2; 6035825fe10SJohannes Berg 6045825fe10SJohannes Berg if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && 6055825fe10SJohannes Berg !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)) 6065825fe10SJohannes Berg qparam.cw_min = 31; 6075825fe10SJohannes Berg else 6085825fe10SJohannes Berg qparam.cw_min = 15; 6095825fe10SJohannes Berg 6105825fe10SJohannes Berg qparam.cw_max = 1023; 6115825fe10SJohannes Berg qparam.txop = 0; 6125825fe10SJohannes Berg 6135825fe10SJohannes Berg for (i = 0; i < local_to_hw(local)->queues; i++) 6145825fe10SJohannes Berg local->ops->conf_tx(local_to_hw(local), i, &qparam); 6155825fe10SJohannes Berg } 616e50db65cSJohannes Berg 617e50db65cSJohannes Berg void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, 618e50db65cSJohannes Berg int encrypt) 619e50db65cSJohannes Berg { 620e50db65cSJohannes Berg skb->dev = sdata->local->mdev; 621e50db65cSJohannes Berg skb_set_mac_header(skb, 0); 622e50db65cSJohannes Berg skb_set_network_header(skb, 0); 623e50db65cSJohannes Berg skb_set_transport_header(skb, 0); 624e50db65cSJohannes Berg 625e50db65cSJohannes Berg skb->iif = sdata->dev->ifindex; 626e50db65cSJohannes Berg skb->do_not_encrypt = !encrypt; 627e50db65cSJohannes Berg 628e50db65cSJohannes Berg dev_queue_xmit(skb); 629e50db65cSJohannes Berg } 630e16751c3SJohannes Berg 631e16751c3SJohannes Berg int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) 632e16751c3SJohannes Berg { 633e16751c3SJohannes Berg int ret = -EINVAL; 634e16751c3SJohannes Berg struct ieee80211_channel *chan; 635e16751c3SJohannes Berg struct ieee80211_local *local = sdata->local; 636e16751c3SJohannes Berg 637e16751c3SJohannes Berg chan = ieee80211_get_channel(local->hw.wiphy, freqMHz); 638e16751c3SJohannes Berg 639e16751c3SJohannes Berg if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { 64005c914feSJohannes Berg if (sdata->vif.type == NL80211_IFTYPE_ADHOC && 641d73782fdSJohannes Berg chan->flags & IEEE80211_CHAN_NO_IBSS) 642e16751c3SJohannes Berg return ret; 643e16751c3SJohannes Berg local->oper_channel = chan; 644e16751c3SJohannes Berg 645c2b13452SJohannes Berg if (local->sw_scanning || local->hw_scanning) 646e16751c3SJohannes Berg ret = 0; 647e16751c3SJohannes Berg else 648e16751c3SJohannes Berg ret = ieee80211_hw_config(local); 649e16751c3SJohannes Berg 650e16751c3SJohannes Berg rate_control_clear(local); 651e16751c3SJohannes Berg } 652e16751c3SJohannes Berg 653e16751c3SJohannes Berg return ret; 654e16751c3SJohannes Berg } 65596dd22acSJohannes Berg 65696dd22acSJohannes Berg u64 ieee80211_mandatory_rates(struct ieee80211_local *local, 65796dd22acSJohannes Berg enum ieee80211_band band) 65896dd22acSJohannes Berg { 65996dd22acSJohannes Berg struct ieee80211_supported_band *sband; 66096dd22acSJohannes Berg struct ieee80211_rate *bitrates; 66196dd22acSJohannes Berg u64 mandatory_rates; 66296dd22acSJohannes Berg enum ieee80211_rate_flags mandatory_flag; 66396dd22acSJohannes Berg int i; 66496dd22acSJohannes Berg 66596dd22acSJohannes Berg sband = local->hw.wiphy->bands[band]; 66696dd22acSJohannes Berg if (!sband) { 66796dd22acSJohannes Berg WARN_ON(1); 66896dd22acSJohannes Berg sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 66996dd22acSJohannes Berg } 67096dd22acSJohannes Berg 67196dd22acSJohannes Berg if (band == IEEE80211_BAND_2GHZ) 67296dd22acSJohannes Berg mandatory_flag = IEEE80211_RATE_MANDATORY_B; 67396dd22acSJohannes Berg else 67496dd22acSJohannes Berg mandatory_flag = IEEE80211_RATE_MANDATORY_A; 67596dd22acSJohannes Berg 67696dd22acSJohannes Berg bitrates = sband->bitrates; 67796dd22acSJohannes Berg mandatory_rates = 0; 67896dd22acSJohannes Berg for (i = 0; i < sband->n_bitrates; i++) 67996dd22acSJohannes Berg if (bitrates[i].flags & mandatory_flag) 68096dd22acSJohannes Berg mandatory_rates |= BIT(i); 68196dd22acSJohannes Berg return mandatory_rates; 68296dd22acSJohannes Berg } 683