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" 28c2d1560aSJohannes Berg #include "ieee80211_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) */ 37c2d1560aSJohannes Berg const unsigned char rfc1042_header[] = 38c2d1560aSJohannes Berg { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; 39c2d1560aSJohannes Berg 40c2d1560aSJohannes Berg /* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ 41c2d1560aSJohannes Berg const unsigned char bridge_tunnel_header[] = 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, 4671364716SRon Rindjunsky enum ieee80211_if_types type) 47c2d1560aSJohannes Berg { 48c2d1560aSJohannes Berg u16 fc; 49c2d1560aSJohannes Berg 5098f0b0a3SRon Rindjunsky /* drop ACK/CTS frames and incorrect hdr len (ctrl) */ 5198f0b0a3SRon Rindjunsky if (len < 16) 52c2d1560aSJohannes Berg return NULL; 53c2d1560aSJohannes Berg 54c2d1560aSJohannes Berg fc = le16_to_cpu(hdr->frame_control); 55c2d1560aSJohannes Berg 56c2d1560aSJohannes Berg switch (fc & IEEE80211_FCTL_FTYPE) { 57c2d1560aSJohannes Berg case IEEE80211_FTYPE_DATA: 5898f0b0a3SRon Rindjunsky if (len < 24) /* drop incorrect hdr len (data) */ 5998f0b0a3SRon Rindjunsky return NULL; 60c2d1560aSJohannes Berg switch (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { 61c2d1560aSJohannes Berg case IEEE80211_FCTL_TODS: 62c2d1560aSJohannes Berg return hdr->addr1; 63c2d1560aSJohannes Berg case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): 64c2d1560aSJohannes Berg return NULL; 65c2d1560aSJohannes Berg case IEEE80211_FCTL_FROMDS: 66c2d1560aSJohannes Berg return hdr->addr2; 67c2d1560aSJohannes Berg case 0: 68c2d1560aSJohannes Berg return hdr->addr3; 69c2d1560aSJohannes Berg } 70c2d1560aSJohannes Berg break; 71c2d1560aSJohannes Berg case IEEE80211_FTYPE_MGMT: 7298f0b0a3SRon Rindjunsky if (len < 24) /* drop incorrect hdr len (mgmt) */ 7398f0b0a3SRon Rindjunsky return NULL; 74c2d1560aSJohannes Berg return hdr->addr3; 75c2d1560aSJohannes Berg case IEEE80211_FTYPE_CTL: 76c2d1560aSJohannes Berg if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL) 77c2d1560aSJohannes Berg return hdr->addr1; 7871364716SRon Rindjunsky else if ((fc & IEEE80211_FCTL_STYPE) == 7971364716SRon Rindjunsky IEEE80211_STYPE_BACK_REQ) { 8071364716SRon Rindjunsky switch (type) { 8171364716SRon Rindjunsky case IEEE80211_IF_TYPE_STA: 8271364716SRon Rindjunsky return hdr->addr2; 8371364716SRon Rindjunsky case IEEE80211_IF_TYPE_AP: 8471364716SRon Rindjunsky case IEEE80211_IF_TYPE_VLAN: 8571364716SRon Rindjunsky return hdr->addr1; 8671364716SRon Rindjunsky default: 8771364716SRon Rindjunsky return NULL; 8871364716SRon Rindjunsky } 8971364716SRon Rindjunsky } 90c2d1560aSJohannes Berg else 91c2d1560aSJohannes Berg return NULL; 92c2d1560aSJohannes Berg } 93c2d1560aSJohannes Berg 94c2d1560aSJohannes Berg return NULL; 95c2d1560aSJohannes Berg } 96c2d1560aSJohannes Berg 97c2d1560aSJohannes Berg int ieee80211_get_hdrlen(u16 fc) 98c2d1560aSJohannes Berg { 99c2d1560aSJohannes Berg int hdrlen = 24; 100c2d1560aSJohannes Berg 101c2d1560aSJohannes Berg switch (fc & IEEE80211_FCTL_FTYPE) { 102c2d1560aSJohannes Berg case IEEE80211_FTYPE_DATA: 103c2d1560aSJohannes Berg if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) 104c2d1560aSJohannes Berg hdrlen = 30; /* Addr4 */ 105c2d1560aSJohannes Berg /* 106c2d1560aSJohannes Berg * The QoS Control field is two bytes and its presence is 107c2d1560aSJohannes Berg * indicated by the IEEE80211_STYPE_QOS_DATA bit. Add 2 to 108c2d1560aSJohannes Berg * hdrlen if that bit is set. 109c2d1560aSJohannes Berg * This works by masking out the bit and shifting it to 110c2d1560aSJohannes Berg * bit position 1 so the result has the value 0 or 2. 111c2d1560aSJohannes Berg */ 112c2d1560aSJohannes Berg hdrlen += (fc & IEEE80211_STYPE_QOS_DATA) 113c2d1560aSJohannes Berg >> (ilog2(IEEE80211_STYPE_QOS_DATA)-1); 114c2d1560aSJohannes Berg break; 115c2d1560aSJohannes Berg case IEEE80211_FTYPE_CTL: 116c2d1560aSJohannes Berg /* 117c2d1560aSJohannes Berg * ACK and CTS are 10 bytes, all others 16. To see how 118c2d1560aSJohannes Berg * to get this condition consider 119c2d1560aSJohannes Berg * subtype mask: 0b0000000011110000 (0x00F0) 120c2d1560aSJohannes Berg * ACK subtype: 0b0000000011010000 (0x00D0) 121c2d1560aSJohannes Berg * CTS subtype: 0b0000000011000000 (0x00C0) 122c2d1560aSJohannes Berg * bits that matter: ^^^ (0x00E0) 123c2d1560aSJohannes Berg * value of those: 0b0000000011000000 (0x00C0) 124c2d1560aSJohannes Berg */ 125c2d1560aSJohannes Berg if ((fc & 0xE0) == 0xC0) 126c2d1560aSJohannes Berg hdrlen = 10; 127c2d1560aSJohannes Berg else 128c2d1560aSJohannes Berg hdrlen = 16; 129c2d1560aSJohannes Berg break; 130c2d1560aSJohannes Berg } 131c2d1560aSJohannes Berg 132c2d1560aSJohannes Berg return hdrlen; 133c2d1560aSJohannes Berg } 134c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_get_hdrlen); 135c2d1560aSJohannes Berg 136c2d1560aSJohannes Berg int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb) 137c2d1560aSJohannes Berg { 138c2d1560aSJohannes Berg const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) skb->data; 139c2d1560aSJohannes Berg int hdrlen; 140c2d1560aSJohannes Berg 141c2d1560aSJohannes Berg if (unlikely(skb->len < 10)) 142c2d1560aSJohannes Berg return 0; 143c2d1560aSJohannes Berg hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)); 144c2d1560aSJohannes Berg if (unlikely(hdrlen > skb->len)) 145c2d1560aSJohannes Berg return 0; 146c2d1560aSJohannes Berg return hdrlen; 147c2d1560aSJohannes Berg } 148c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); 149c2d1560aSJohannes Berg 150ee385855SLuis Carlos Cobo int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) 151ee385855SLuis Carlos Cobo { 152ee385855SLuis Carlos Cobo int ae = meshhdr->flags & IEEE80211S_FLAGS_AE; 153ee385855SLuis Carlos Cobo /* 7.1.3.5a.2 */ 154ee385855SLuis Carlos Cobo switch (ae) { 155ee385855SLuis Carlos Cobo case 0: 156ee385855SLuis Carlos Cobo return 5; 157ee385855SLuis Carlos Cobo case 1: 158ee385855SLuis Carlos Cobo return 11; 159ee385855SLuis Carlos Cobo case 2: 160ee385855SLuis Carlos Cobo return 17; 161ee385855SLuis Carlos Cobo case 3: 162ee385855SLuis Carlos Cobo return 23; 163ee385855SLuis Carlos Cobo default: 164ee385855SLuis Carlos Cobo return 5; 165ee385855SLuis Carlos Cobo } 166ee385855SLuis Carlos Cobo } 167ee385855SLuis Carlos Cobo 1685cf121c3SJohannes Berg void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) 169c2d1560aSJohannes Berg { 170c2d1560aSJohannes Berg struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; 171c2d1560aSJohannes Berg 172c2d1560aSJohannes Berg hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); 1735cf121c3SJohannes Berg if (tx->extra_frag) { 174c2d1560aSJohannes Berg struct ieee80211_hdr *fhdr; 175c2d1560aSJohannes Berg int i; 1765cf121c3SJohannes Berg for (i = 0; i < tx->num_extra_frag; i++) { 177c2d1560aSJohannes Berg fhdr = (struct ieee80211_hdr *) 1785cf121c3SJohannes Berg tx->extra_frag[i]->data; 179c2d1560aSJohannes Berg fhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); 180c2d1560aSJohannes Berg } 181c2d1560aSJohannes Berg } 182c2d1560aSJohannes Berg } 183c2d1560aSJohannes Berg 184c2d1560aSJohannes Berg int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, 185c2d1560aSJohannes Berg int rate, int erp, int short_preamble) 186c2d1560aSJohannes Berg { 187c2d1560aSJohannes Berg int dur; 188c2d1560aSJohannes Berg 189c2d1560aSJohannes Berg /* calculate duration (in microseconds, rounded up to next higher 190c2d1560aSJohannes Berg * integer if it includes a fractional microsecond) to send frame of 191c2d1560aSJohannes Berg * len bytes (does not include FCS) at the given rate. Duration will 192c2d1560aSJohannes Berg * also include SIFS. 193c2d1560aSJohannes Berg * 194c2d1560aSJohannes Berg * rate is in 100 kbps, so divident is multiplied by 10 in the 195c2d1560aSJohannes Berg * DIV_ROUND_UP() operations. 196c2d1560aSJohannes Berg */ 197c2d1560aSJohannes Berg 1988318d78aSJohannes Berg if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ || erp) { 199c2d1560aSJohannes Berg /* 200c2d1560aSJohannes Berg * OFDM: 201c2d1560aSJohannes Berg * 202c2d1560aSJohannes Berg * N_DBPS = DATARATE x 4 203c2d1560aSJohannes Berg * N_SYM = Ceiling((16+8xLENGTH+6) / N_DBPS) 204c2d1560aSJohannes Berg * (16 = SIGNAL time, 6 = tail bits) 205c2d1560aSJohannes Berg * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext 206c2d1560aSJohannes Berg * 207c2d1560aSJohannes Berg * T_SYM = 4 usec 208c2d1560aSJohannes Berg * 802.11a - 17.5.2: aSIFSTime = 16 usec 209c2d1560aSJohannes Berg * 802.11g - 19.8.4: aSIFSTime = 10 usec + 210c2d1560aSJohannes Berg * signal ext = 6 usec 211c2d1560aSJohannes Berg */ 212c2d1560aSJohannes Berg dur = 16; /* SIFS + signal ext */ 213c2d1560aSJohannes Berg dur += 16; /* 17.3.2.3: T_PREAMBLE = 16 usec */ 214c2d1560aSJohannes Berg dur += 4; /* 17.3.2.3: T_SIGNAL = 4 usec */ 215c2d1560aSJohannes Berg dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10, 216c2d1560aSJohannes Berg 4 * rate); /* T_SYM x N_SYM */ 217c2d1560aSJohannes Berg } else { 218c2d1560aSJohannes Berg /* 219c2d1560aSJohannes Berg * 802.11b or 802.11g with 802.11b compatibility: 220c2d1560aSJohannes Berg * 18.3.4: TXTIME = PreambleLength + PLCPHeaderTime + 221c2d1560aSJohannes Berg * Ceiling(((LENGTH+PBCC)x8)/DATARATE). PBCC=0. 222c2d1560aSJohannes Berg * 223c2d1560aSJohannes Berg * 802.11 (DS): 15.3.3, 802.11b: 18.3.4 224c2d1560aSJohannes Berg * aSIFSTime = 10 usec 225c2d1560aSJohannes Berg * aPreambleLength = 144 usec or 72 usec with short preamble 226c2d1560aSJohannes Berg * aPLCPHeaderLength = 48 usec or 24 usec with short preamble 227c2d1560aSJohannes Berg */ 228c2d1560aSJohannes Berg dur = 10; /* aSIFSTime = 10 usec */ 229c2d1560aSJohannes Berg dur += short_preamble ? (72 + 24) : (144 + 48); 230c2d1560aSJohannes Berg 231c2d1560aSJohannes Berg dur += DIV_ROUND_UP(8 * (len + 4) * 10, rate); 232c2d1560aSJohannes Berg } 233c2d1560aSJohannes Berg 234c2d1560aSJohannes Berg return dur; 235c2d1560aSJohannes Berg } 236c2d1560aSJohannes Berg 237c2d1560aSJohannes Berg /* Exported duration function for driver use */ 23832bfd35dSJohannes Berg __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, 23932bfd35dSJohannes Berg struct ieee80211_vif *vif, 2408318d78aSJohannes Berg size_t frame_len, 2418318d78aSJohannes Berg struct ieee80211_rate *rate) 242c2d1560aSJohannes Berg { 243c2d1560aSJohannes Berg struct ieee80211_local *local = hw_to_local(hw); 24432bfd35dSJohannes Berg struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 245c2d1560aSJohannes Berg u16 dur; 246c2d1560aSJohannes Berg int erp; 247c2d1560aSJohannes Berg 2488318d78aSJohannes Berg erp = 0; 2498318d78aSJohannes Berg if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) 2508318d78aSJohannes Berg erp = rate->flags & IEEE80211_RATE_ERP_G; 2518318d78aSJohannes Berg 2528318d78aSJohannes Berg dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, 253471b3efdSJohannes Berg sdata->bss_conf.use_short_preamble); 254c2d1560aSJohannes Berg 255c2d1560aSJohannes Berg return cpu_to_le16(dur); 256c2d1560aSJohannes Berg } 257c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_generic_frame_duration); 258c2d1560aSJohannes Berg 25932bfd35dSJohannes Berg __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, 26032bfd35dSJohannes Berg struct ieee80211_vif *vif, size_t frame_len, 261c2d1560aSJohannes Berg const struct ieee80211_tx_control *frame_txctl) 262c2d1560aSJohannes Berg { 263c2d1560aSJohannes Berg struct ieee80211_local *local = hw_to_local(hw); 264c2d1560aSJohannes Berg struct ieee80211_rate *rate; 26532bfd35dSJohannes Berg struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 266471b3efdSJohannes Berg bool short_preamble; 267c2d1560aSJohannes Berg int erp; 268c2d1560aSJohannes Berg u16 dur; 269c2d1560aSJohannes Berg 270471b3efdSJohannes Berg short_preamble = sdata->bss_conf.use_short_preamble; 2717e9ed188SDaniel Drake 2728318d78aSJohannes Berg rate = frame_txctl->rts_cts_rate; 2738318d78aSJohannes Berg 2748318d78aSJohannes Berg erp = 0; 2758318d78aSJohannes Berg if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) 2768318d78aSJohannes Berg erp = rate->flags & IEEE80211_RATE_ERP_G; 277c2d1560aSJohannes Berg 278c2d1560aSJohannes Berg /* CTS duration */ 2798318d78aSJohannes Berg dur = ieee80211_frame_duration(local, 10, rate->bitrate, 280c2d1560aSJohannes Berg erp, short_preamble); 281c2d1560aSJohannes Berg /* Data frame duration */ 2828318d78aSJohannes Berg dur += ieee80211_frame_duration(local, frame_len, rate->bitrate, 283c2d1560aSJohannes Berg erp, short_preamble); 284c2d1560aSJohannes Berg /* ACK duration */ 2858318d78aSJohannes Berg dur += ieee80211_frame_duration(local, 10, rate->bitrate, 286c2d1560aSJohannes Berg erp, short_preamble); 287c2d1560aSJohannes Berg 288c2d1560aSJohannes Berg return cpu_to_le16(dur); 289c2d1560aSJohannes Berg } 290c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_rts_duration); 291c2d1560aSJohannes Berg 29232bfd35dSJohannes Berg __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, 29332bfd35dSJohannes Berg struct ieee80211_vif *vif, 294c2d1560aSJohannes Berg size_t frame_len, 295c2d1560aSJohannes Berg const struct ieee80211_tx_control *frame_txctl) 296c2d1560aSJohannes Berg { 297c2d1560aSJohannes Berg struct ieee80211_local *local = hw_to_local(hw); 298c2d1560aSJohannes Berg struct ieee80211_rate *rate; 29932bfd35dSJohannes Berg struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 300471b3efdSJohannes Berg bool short_preamble; 301c2d1560aSJohannes Berg int erp; 302c2d1560aSJohannes Berg u16 dur; 303c2d1560aSJohannes Berg 304471b3efdSJohannes Berg short_preamble = sdata->bss_conf.use_short_preamble; 3057e9ed188SDaniel Drake 3068318d78aSJohannes Berg rate = frame_txctl->rts_cts_rate; 3078318d78aSJohannes Berg erp = 0; 3088318d78aSJohannes Berg if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) 3098318d78aSJohannes Berg erp = rate->flags & IEEE80211_RATE_ERP_G; 310c2d1560aSJohannes Berg 311c2d1560aSJohannes Berg /* Data frame duration */ 3128318d78aSJohannes Berg dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, 313c2d1560aSJohannes Berg erp, short_preamble); 314c2d1560aSJohannes Berg if (!(frame_txctl->flags & IEEE80211_TXCTL_NO_ACK)) { 315c2d1560aSJohannes Berg /* ACK duration */ 3168318d78aSJohannes Berg dur += ieee80211_frame_duration(local, 10, rate->bitrate, 317c2d1560aSJohannes Berg erp, short_preamble); 318c2d1560aSJohannes Berg } 319c2d1560aSJohannes Berg 320c2d1560aSJohannes Berg return cpu_to_le16(dur); 321c2d1560aSJohannes Berg } 322c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_ctstoself_duration); 323c2d1560aSJohannes Berg 324c2d1560aSJohannes Berg void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) 325c2d1560aSJohannes Berg { 326c2d1560aSJohannes Berg struct ieee80211_local *local = hw_to_local(hw); 327c2d1560aSJohannes Berg 328c2d1560aSJohannes Berg if (test_and_clear_bit(IEEE80211_LINK_STATE_XOFF, 329c2d1560aSJohannes Berg &local->state[queue])) { 330c2d1560aSJohannes Berg if (test_bit(IEEE80211_LINK_STATE_PENDING, 331c2d1560aSJohannes Berg &local->state[queue])) 332c2d1560aSJohannes Berg tasklet_schedule(&local->tx_pending_tasklet); 333c2d1560aSJohannes Berg else 334c2d1560aSJohannes Berg if (!ieee80211_qdisc_installed(local->mdev)) { 335c2d1560aSJohannes Berg if (queue == 0) 336c2d1560aSJohannes Berg netif_wake_queue(local->mdev); 337c2d1560aSJohannes Berg } else 338c2d1560aSJohannes Berg __netif_schedule(local->mdev); 339c2d1560aSJohannes Berg } 340c2d1560aSJohannes Berg } 341c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_wake_queue); 342c2d1560aSJohannes Berg 343c2d1560aSJohannes Berg void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) 344c2d1560aSJohannes Berg { 345c2d1560aSJohannes Berg struct ieee80211_local *local = hw_to_local(hw); 346c2d1560aSJohannes Berg 347c2d1560aSJohannes Berg if (!ieee80211_qdisc_installed(local->mdev) && queue == 0) 348c2d1560aSJohannes Berg netif_stop_queue(local->mdev); 349c2d1560aSJohannes Berg set_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]); 350c2d1560aSJohannes Berg } 351c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_stop_queue); 352c2d1560aSJohannes Berg 353c2d1560aSJohannes Berg void ieee80211_start_queues(struct ieee80211_hw *hw) 354c2d1560aSJohannes Berg { 355c2d1560aSJohannes Berg struct ieee80211_local *local = hw_to_local(hw); 356c2d1560aSJohannes Berg int i; 357c2d1560aSJohannes Berg 358c2d1560aSJohannes Berg for (i = 0; i < local->hw.queues; i++) 359c2d1560aSJohannes Berg clear_bit(IEEE80211_LINK_STATE_XOFF, &local->state[i]); 360c2d1560aSJohannes Berg if (!ieee80211_qdisc_installed(local->mdev)) 361c2d1560aSJohannes Berg netif_start_queue(local->mdev); 362c2d1560aSJohannes Berg } 363c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_start_queues); 364c2d1560aSJohannes Berg 365c2d1560aSJohannes Berg void ieee80211_stop_queues(struct ieee80211_hw *hw) 366c2d1560aSJohannes Berg { 367c2d1560aSJohannes Berg int i; 368c2d1560aSJohannes Berg 369c2d1560aSJohannes Berg for (i = 0; i < hw->queues; i++) 370c2d1560aSJohannes Berg ieee80211_stop_queue(hw, i); 371c2d1560aSJohannes Berg } 372c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_stop_queues); 373c2d1560aSJohannes Berg 374c2d1560aSJohannes Berg void ieee80211_wake_queues(struct ieee80211_hw *hw) 375c2d1560aSJohannes Berg { 376c2d1560aSJohannes Berg int i; 377c2d1560aSJohannes Berg 378c2d1560aSJohannes Berg for (i = 0; i < hw->queues; i++) 379c2d1560aSJohannes Berg ieee80211_wake_queue(hw, i); 380c2d1560aSJohannes Berg } 381c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_wake_queues); 382dabeb344SJohannes Berg 38332bfd35dSJohannes Berg void ieee80211_iterate_active_interfaces( 38432bfd35dSJohannes Berg struct ieee80211_hw *hw, 385dabeb344SJohannes Berg void (*iterator)(void *data, u8 *mac, 38632bfd35dSJohannes Berg struct ieee80211_vif *vif), 387dabeb344SJohannes Berg void *data) 388dabeb344SJohannes Berg { 389dabeb344SJohannes Berg struct ieee80211_local *local = hw_to_local(hw); 390dabeb344SJohannes Berg struct ieee80211_sub_if_data *sdata; 391dabeb344SJohannes Berg 392e38bad47SJohannes Berg rcu_read_lock(); 393dabeb344SJohannes Berg 394e38bad47SJohannes Berg list_for_each_entry_rcu(sdata, &local->interfaces, list) { 39551fb61e7SJohannes Berg switch (sdata->vif.type) { 396dabeb344SJohannes Berg case IEEE80211_IF_TYPE_INVALID: 397dabeb344SJohannes Berg case IEEE80211_IF_TYPE_MNTR: 398dabeb344SJohannes Berg case IEEE80211_IF_TYPE_VLAN: 399dabeb344SJohannes Berg continue; 400dabeb344SJohannes Berg case IEEE80211_IF_TYPE_AP: 401dabeb344SJohannes Berg case IEEE80211_IF_TYPE_STA: 402dabeb344SJohannes Berg case IEEE80211_IF_TYPE_IBSS: 403dabeb344SJohannes Berg case IEEE80211_IF_TYPE_WDS: 4046032f934SJohannes Berg case IEEE80211_IF_TYPE_MESH_POINT: 405dabeb344SJohannes Berg break; 406dabeb344SJohannes Berg } 407dabeb344SJohannes Berg if (sdata->dev == local->mdev) 408dabeb344SJohannes Berg continue; 409dabeb344SJohannes Berg if (netif_running(sdata->dev)) 410dabeb344SJohannes Berg iterator(data, sdata->dev->dev_addr, 41132bfd35dSJohannes Berg &sdata->vif); 412dabeb344SJohannes Berg } 413e38bad47SJohannes Berg 414e38bad47SJohannes Berg rcu_read_unlock(); 415dabeb344SJohannes Berg } 416dabeb344SJohannes Berg EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); 417