xref: /openbmc/linux/net/mac80211/util.c (revision e039fa4a)
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) */
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:
156ef269254SLuis Carlos Cobo 		return 6;
157ee385855SLuis Carlos Cobo 	case 1:
158ef269254SLuis Carlos Cobo 		return 12;
159ee385855SLuis Carlos Cobo 	case 2:
160ef269254SLuis Carlos Cobo 		return 18;
161ee385855SLuis Carlos Cobo 	case 3:
162ef269254SLuis Carlos Cobo 		return 24;
163ee385855SLuis Carlos Cobo 	default:
164ef269254SLuis Carlos Cobo 		return 6;
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,
261e039fa4aSJohannes Berg 			      const struct ieee80211_tx_info *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;
2692e92e6f2SJohannes Berg 	struct ieee80211_supported_band *sband;
2702e92e6f2SJohannes Berg 
2712e92e6f2SJohannes Berg 	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
272c2d1560aSJohannes Berg 
273471b3efdSJohannes Berg 	short_preamble = sdata->bss_conf.use_short_preamble;
2747e9ed188SDaniel Drake 
275e039fa4aSJohannes Berg 	rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx];
2768318d78aSJohannes Berg 
2778318d78aSJohannes Berg 	erp = 0;
2788318d78aSJohannes Berg 	if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
2798318d78aSJohannes Berg 		erp = rate->flags & IEEE80211_RATE_ERP_G;
280c2d1560aSJohannes Berg 
281c2d1560aSJohannes Berg 	/* CTS duration */
2828318d78aSJohannes Berg 	dur = ieee80211_frame_duration(local, 10, rate->bitrate,
283c2d1560aSJohannes Berg 				       erp, short_preamble);
284c2d1560aSJohannes Berg 	/* Data frame duration */
2858318d78aSJohannes Berg 	dur += ieee80211_frame_duration(local, frame_len, rate->bitrate,
286c2d1560aSJohannes Berg 					erp, short_preamble);
287c2d1560aSJohannes Berg 	/* ACK duration */
2888318d78aSJohannes Berg 	dur += ieee80211_frame_duration(local, 10, rate->bitrate,
289c2d1560aSJohannes Berg 					erp, short_preamble);
290c2d1560aSJohannes Berg 
291c2d1560aSJohannes Berg 	return cpu_to_le16(dur);
292c2d1560aSJohannes Berg }
293c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_rts_duration);
294c2d1560aSJohannes Berg 
29532bfd35dSJohannes Berg __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
29632bfd35dSJohannes Berg 				    struct ieee80211_vif *vif,
297c2d1560aSJohannes Berg 				    size_t frame_len,
298e039fa4aSJohannes Berg 				    const struct ieee80211_tx_info *frame_txctl)
299c2d1560aSJohannes Berg {
300c2d1560aSJohannes Berg 	struct ieee80211_local *local = hw_to_local(hw);
301c2d1560aSJohannes Berg 	struct ieee80211_rate *rate;
30232bfd35dSJohannes Berg 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
303471b3efdSJohannes Berg 	bool short_preamble;
304c2d1560aSJohannes Berg 	int erp;
305c2d1560aSJohannes Berg 	u16 dur;
3062e92e6f2SJohannes Berg 	struct ieee80211_supported_band *sband;
3072e92e6f2SJohannes Berg 
3082e92e6f2SJohannes Berg 	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
309c2d1560aSJohannes Berg 
310471b3efdSJohannes Berg 	short_preamble = sdata->bss_conf.use_short_preamble;
3117e9ed188SDaniel Drake 
312e039fa4aSJohannes Berg 	rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx];
3138318d78aSJohannes Berg 	erp = 0;
3148318d78aSJohannes Berg 	if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
3158318d78aSJohannes Berg 		erp = rate->flags & IEEE80211_RATE_ERP_G;
316c2d1560aSJohannes Berg 
317c2d1560aSJohannes Berg 	/* Data frame duration */
3188318d78aSJohannes Berg 	dur = ieee80211_frame_duration(local, frame_len, rate->bitrate,
319c2d1560aSJohannes Berg 				       erp, short_preamble);
320e039fa4aSJohannes Berg 	if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) {
321c2d1560aSJohannes Berg 		/* ACK duration */
3228318d78aSJohannes Berg 		dur += ieee80211_frame_duration(local, 10, rate->bitrate,
323c2d1560aSJohannes Berg 						erp, short_preamble);
324c2d1560aSJohannes Berg 	}
325c2d1560aSJohannes Berg 
326c2d1560aSJohannes Berg 	return cpu_to_le16(dur);
327c2d1560aSJohannes Berg }
328c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_ctstoself_duration);
329c2d1560aSJohannes Berg 
330c2d1560aSJohannes Berg void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
331c2d1560aSJohannes Berg {
332c2d1560aSJohannes Berg 	struct ieee80211_local *local = hw_to_local(hw);
333c2d1560aSJohannes Berg 
334c2d1560aSJohannes Berg 	if (test_and_clear_bit(IEEE80211_LINK_STATE_XOFF,
335c2d1560aSJohannes Berg 			       &local->state[queue])) {
336c2d1560aSJohannes Berg 		if (test_bit(IEEE80211_LINK_STATE_PENDING,
337c2d1560aSJohannes Berg 			     &local->state[queue]))
338c2d1560aSJohannes Berg 			tasklet_schedule(&local->tx_pending_tasklet);
339c2d1560aSJohannes Berg 		else
340c2d1560aSJohannes Berg 			if (!ieee80211_qdisc_installed(local->mdev)) {
341c2d1560aSJohannes Berg 				if (queue == 0)
342c2d1560aSJohannes Berg 					netif_wake_queue(local->mdev);
343c2d1560aSJohannes Berg 			} else
344c2d1560aSJohannes Berg 				__netif_schedule(local->mdev);
345c2d1560aSJohannes Berg 	}
346c2d1560aSJohannes Berg }
347c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_wake_queue);
348c2d1560aSJohannes Berg 
349c2d1560aSJohannes Berg void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue)
350c2d1560aSJohannes Berg {
351c2d1560aSJohannes Berg 	struct ieee80211_local *local = hw_to_local(hw);
352c2d1560aSJohannes Berg 
353c2d1560aSJohannes Berg 	if (!ieee80211_qdisc_installed(local->mdev) && queue == 0)
354c2d1560aSJohannes Berg 		netif_stop_queue(local->mdev);
355c2d1560aSJohannes Berg 	set_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]);
356c2d1560aSJohannes Berg }
357c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_stop_queue);
358c2d1560aSJohannes Berg 
359c2d1560aSJohannes Berg void ieee80211_stop_queues(struct ieee80211_hw *hw)
360c2d1560aSJohannes Berg {
361c2d1560aSJohannes Berg 	int i;
362c2d1560aSJohannes Berg 
363c4680470SJohannes Berg 	for (i = 0; i < hw->queues + hw->ampdu_queues; i++)
364c2d1560aSJohannes Berg 		ieee80211_stop_queue(hw, i);
365c2d1560aSJohannes Berg }
366c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_stop_queues);
367c2d1560aSJohannes Berg 
368c2d1560aSJohannes Berg void ieee80211_wake_queues(struct ieee80211_hw *hw)
369c2d1560aSJohannes Berg {
370c2d1560aSJohannes Berg 	int i;
371c2d1560aSJohannes Berg 
372c4680470SJohannes Berg 	for (i = 0; i < hw->queues + hw->ampdu_queues; i++)
373c2d1560aSJohannes Berg 		ieee80211_wake_queue(hw, i);
374c2d1560aSJohannes Berg }
375c2d1560aSJohannes Berg EXPORT_SYMBOL(ieee80211_wake_queues);
376dabeb344SJohannes Berg 
37732bfd35dSJohannes Berg void ieee80211_iterate_active_interfaces(
37832bfd35dSJohannes Berg 	struct ieee80211_hw *hw,
379dabeb344SJohannes Berg 	void (*iterator)(void *data, u8 *mac,
38032bfd35dSJohannes Berg 			 struct ieee80211_vif *vif),
381dabeb344SJohannes Berg 	void *data)
382dabeb344SJohannes Berg {
383dabeb344SJohannes Berg 	struct ieee80211_local *local = hw_to_local(hw);
384dabeb344SJohannes Berg 	struct ieee80211_sub_if_data *sdata;
385dabeb344SJohannes Berg 
386e38bad47SJohannes Berg 	rcu_read_lock();
387dabeb344SJohannes Berg 
388e38bad47SJohannes Berg 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
38951fb61e7SJohannes Berg 		switch (sdata->vif.type) {
390dabeb344SJohannes Berg 		case IEEE80211_IF_TYPE_INVALID:
391dabeb344SJohannes Berg 		case IEEE80211_IF_TYPE_MNTR:
392dabeb344SJohannes Berg 		case IEEE80211_IF_TYPE_VLAN:
393dabeb344SJohannes Berg 			continue;
394dabeb344SJohannes Berg 		case IEEE80211_IF_TYPE_AP:
395dabeb344SJohannes Berg 		case IEEE80211_IF_TYPE_STA:
396dabeb344SJohannes Berg 		case IEEE80211_IF_TYPE_IBSS:
397dabeb344SJohannes Berg 		case IEEE80211_IF_TYPE_WDS:
3986032f934SJohannes Berg 		case IEEE80211_IF_TYPE_MESH_POINT:
399dabeb344SJohannes Berg 			break;
400dabeb344SJohannes Berg 		}
401dabeb344SJohannes Berg 		if (sdata->dev == local->mdev)
402dabeb344SJohannes Berg 			continue;
403dabeb344SJohannes Berg 		if (netif_running(sdata->dev))
404dabeb344SJohannes Berg 			iterator(data, sdata->dev->dev_addr,
40532bfd35dSJohannes Berg 				 &sdata->vif);
406dabeb344SJohannes Berg 	}
407e38bad47SJohannes Berg 
408e38bad47SJohannes Berg 	rcu_read_unlock();
409dabeb344SJohannes Berg }
410dabeb344SJohannes Berg EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces);
411