2 * Copyright 2002-2004, Instant802 Networks, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
9 #include <linux/module.h>
10 #include <linux/netdevice.h>
11 #include <linux/types.h>
12 #include <linux/slab.h>
13 #include <linux/skbuff.h>
15 #include <net/d80211.h>
16 #include "ieee80211_i.h"
17 #include "ieee80211_rate.h"
20 /* Maximum number of seconds to wait for the traffic load to get below
21 * threshold before forcing a passive scan. */
22 #define MAX_SCAN_WAIT 60
23 /* Threshold (pkts/sec TX or RX) for delaying passive scan */
24 #define SCAN_TXRX_THRESHOLD 75
26 static void get_channel_params(struct ieee80211_local
*local
, int channel
,
27 struct ieee80211_hw_mode
**mode
,
28 struct ieee80211_channel
**chan
)
30 struct ieee80211_hw_mode
*m
;
32 list_for_each_entry(m
, &local
->modes_list
, list
) {
34 if (m
->mode
== local
->hw
.conf
.phymode
)
38 local
->scan
.chan_idx
= 0;
40 *chan
= &m
->channels
[local
->scan
.chan_idx
];
41 if ((*chan
)->chan
== channel
)
43 local
->scan
.chan_idx
++;
44 } while (local
->scan
.chan_idx
< m
->num_channels
);
49 static void next_chan_same_mode(struct ieee80211_local
*local
,
50 struct ieee80211_hw_mode
**mode
,
51 struct ieee80211_channel
**chan
)
53 struct ieee80211_hw_mode
*m
;
56 list_for_each_entry(m
, &local
->modes_list
, list
) {
58 if (m
->mode
== local
->hw
.conf
.phymode
)
63 /* Select next channel - scan only channels marked with W_SCAN flag */
64 prev
= local
->scan
.chan_idx
;
66 local
->scan
.chan_idx
++;
67 if (local
->scan
.chan_idx
>= m
->num_channels
)
68 local
->scan
.chan_idx
= 0;
69 *chan
= &m
->channels
[local
->scan
.chan_idx
];
70 if ((*chan
)->flag
& IEEE80211_CHAN_W_SCAN
)
72 } while (local
->scan
.chan_idx
!= prev
);
76 static void next_chan_all_modes(struct ieee80211_local
*local
,
77 struct ieee80211_hw_mode
**mode
,
78 struct ieee80211_channel
**chan
)
80 struct ieee80211_hw_mode
*prev_m
;
83 /* Select next channel - scan only channels marked with W_SCAN flag */
84 prev
= local
->scan
.chan_idx
;
85 prev_m
= local
->scan
.mode
;
87 *mode
= local
->scan
.mode
;
88 local
->scan
.chan_idx
++;
89 if (local
->scan
.chan_idx
>= (*mode
)->num_channels
) {
90 struct list_head
*next
;
92 local
->scan
.chan_idx
= 0;
93 next
= (*mode
)->list
.next
;
94 if (next
== &local
->modes_list
)
96 *mode
= list_entry(next
,
97 struct ieee80211_hw_mode
,
99 local
->scan
.mode
= *mode
;
101 *chan
= &(*mode
)->channels
[local
->scan
.chan_idx
];
102 if ((*chan
)->flag
& IEEE80211_CHAN_W_SCAN
)
104 } while (local
->scan
.chan_idx
!= prev
||
105 local
->scan
.mode
!= prev_m
);
109 static void ieee80211_scan_start(struct ieee80211_local
*local
,
110 struct ieee80211_scan_conf
*conf
)
112 struct ieee80211_hw_mode
*old_mode
= local
->scan
.mode
;
113 int old_chan_idx
= local
->scan
.chan_idx
;
114 struct ieee80211_hw_mode
*mode
= NULL
;
115 struct ieee80211_channel
*chan
= NULL
;
118 if (!local
->ops
->passive_scan
) {
119 printk(KERN_DEBUG
"%s: Scan handler called, yet the hardware "
120 "does not support passive scanning. Disabled.\n",
125 if ((local
->scan
.tries
< MAX_SCAN_WAIT
&&
126 local
->scan
.txrx_count
> SCAN_TXRX_THRESHOLD
)) {
128 /* Count TX/RX packets during one second interval and allow
129 * scan to start only if the number of packets is below the
131 local
->scan
.txrx_count
= 0;
132 local
->scan
.timer
.expires
= jiffies
+ HZ
;
133 add_timer(&local
->scan
.timer
);
137 if (!local
->scan
.skb
) {
138 printk(KERN_DEBUG
"%s: Scan start called even though scan.skb "
139 "is not set\n", local
->mdev
->name
);
142 if (local
->scan
.our_mode_only
) {
143 if (local
->scan
.channel
> 0) {
144 get_channel_params(local
, local
->scan
.channel
, &mode
,
147 next_chan_same_mode(local
, &mode
, &chan
);
150 next_chan_all_modes(local
, &mode
, &chan
);
152 conf
->scan_channel
= chan
->chan
;
153 conf
->scan_freq
= chan
->freq
;
154 conf
->scan_channel_val
= chan
->val
;
155 conf
->scan_phymode
= mode
->mode
;
156 conf
->scan_power_level
= chan
->power_level
;
157 conf
->scan_antenna_max
= chan
->antenna_max
;
158 conf
->scan_time
= 2 * local
->hw
.channel_change_time
+
159 local
->scan
.time
; /* 10ms scan time+hardware changes */
160 conf
->skb
= local
->scan
.skb
?
161 skb_clone(local
->scan
.skb
, GFP_ATOMIC
) : NULL
;
162 conf
->tx_control
= &local
->scan
.tx_control
;
164 printk(KERN_DEBUG
"%s: Doing scan on mode: %d freq: %d chan: %d "
166 local
->mdev
->name
, conf
->scan_phymode
, conf
->scan_freq
,
167 conf
->scan_channel
, conf
->scan_time
);
169 local
->scan
.rx_packets
= 0;
170 local
->scan
.rx_beacon
= 0;
171 local
->scan
.freq
= chan
->freq
;
172 local
->scan
.in_scan
= 1;
174 ieee80211_netif_oper(local_to_hw(local
), NETIF_STOP
);
176 ret
= local
->ops
->passive_scan(local_to_hw(local
),
177 IEEE80211_SCAN_START
, conf
);
180 long usec
= local
->hw
.channel_change_time
+
182 usec
+= 1000000L / HZ
- 1;
183 usec
/= 1000000L / HZ
;
184 local
->scan
.timer
.expires
= jiffies
+ usec
;
186 local
->scan
.in_scan
= 0;
188 dev_kfree_skb(conf
->skb
);
189 ieee80211_netif_oper(local_to_hw(local
), NETIF_WAKE
);
190 if (ret
== -EAGAIN
) {
191 local
->scan
.timer
.expires
= jiffies
+
192 (local
->scan
.interval
* HZ
/ 100);
193 local
->scan
.mode
= old_mode
;
194 local
->scan
.chan_idx
= old_chan_idx
;
196 printk(KERN_DEBUG
"%s: Got unknown error from "
197 "passive_scan %d\n", local
->mdev
->name
, ret
);
198 local
->scan
.timer
.expires
= jiffies
+
199 (local
->scan
.interval
* HZ
);
201 local
->scan
.in_scan
= 0;
204 add_timer(&local
->scan
.timer
);
208 static void ieee80211_scan_stop(struct ieee80211_local
*local
,
209 struct ieee80211_scan_conf
*conf
)
211 struct ieee80211_hw_mode
*mode
;
212 struct ieee80211_channel
*chan
;
215 if (!local
->ops
->passive_scan
)
218 mode
= local
->scan
.mode
;
220 if (local
->scan
.chan_idx
>= mode
->num_channels
)
221 local
->scan
.chan_idx
= 0;
223 chan
= &mode
->channels
[local
->scan
.chan_idx
];
225 local
->ops
->passive_scan(local_to_hw(local
), IEEE80211_SCAN_END
,
228 #ifdef CONFIG_D80211_VERBOSE_DEBUG
229 printk(KERN_DEBUG
"%s: Did scan on mode: %d freq: %d chan: %d "
230 "GOT: %d Beacon: %d (%d)\n",
232 mode
->mode
, chan
->freq
, chan
->chan
,
233 local
->scan
.rx_packets
, local
->scan
.rx_beacon
,
235 #endif /* CONFIG_D80211_VERBOSE_DEBUG */
236 local
->scan
.num_scans
++;
238 local
->scan
.in_scan
= 0;
239 ieee80211_netif_oper(local_to_hw(local
), NETIF_WAKE
);
241 local
->scan
.tries
= 0;
242 /* Use random interval of scan.interval .. 2 * scan.interval */
243 wait
= (local
->scan
.interval
* HZ
* ((net_random() & 127) + 128)) /
245 local
->scan
.timer
.expires
= jiffies
+ wait
;
247 add_timer(&local
->scan
.timer
);
251 static void ieee80211_scan_handler(unsigned long ullocal
)
253 struct ieee80211_local
*local
= (struct ieee80211_local
*) ullocal
;
254 struct ieee80211_scan_conf conf
;
256 if (local
->scan
.interval
== 0 && !local
->scan
.in_scan
) {
257 /* Passive scanning is disabled - keep the timer always
258 * running to make code cleaner. */
259 local
->scan
.timer
.expires
= jiffies
+ 10 * HZ
;
260 add_timer(&local
->scan
.timer
);
264 memset(&conf
, 0, sizeof(struct ieee80211_scan_conf
));
265 conf
.running_freq
= local
->hw
.conf
.freq
;
266 conf
.running_channel
= local
->hw
.conf
.channel
;
267 conf
.running_phymode
= local
->hw
.conf
.phymode
;
268 conf
.running_channel_val
= local
->hw
.conf
.channel_val
;
269 conf
.running_power_level
= local
->hw
.conf
.power_level
;
270 conf
.running_antenna_max
= local
->hw
.conf
.antenna_max
;
272 if (local
->scan
.in_scan
== 0)
273 ieee80211_scan_start(local
, &conf
);
275 ieee80211_scan_stop(local
, &conf
);
279 void ieee80211_init_scan(struct ieee80211_local
*local
)
281 struct ieee80211_hdr hdr
;
284 struct rate_control_extra extra
;
286 /* Only initialize passive scanning if the hardware supports it */
287 if (!local
->ops
->passive_scan
) {
288 local
->scan
.skb
= NULL
;
289 memset(&local
->scan
.tx_control
, 0,
290 sizeof(local
->scan
.tx_control
));
291 printk(KERN_DEBUG
"%s: Does not support passive scan, "
292 "disabled\n", local
->mdev
->name
);
296 local
->scan
.interval
= 0;
297 local
->scan
.our_mode_only
= 1;
298 local
->scan
.time
= 10000;
299 local
->scan
.timer
.function
= ieee80211_scan_handler
;
300 local
->scan
.timer
.data
= (unsigned long) local
;
301 local
->scan
.timer
.expires
= jiffies
+ local
->scan
.interval
* HZ
;
302 add_timer(&local
->scan
.timer
);
304 /* Create a CTS from for broadcasting before
305 * the low level changes channels */
306 local
->scan
.skb
= alloc_skb(len
, GFP_KERNEL
);
307 if (!local
->scan
.skb
) {
308 printk(KERN_WARNING
"%s: Failed to allocate CTS packet for "
309 "passive scan\n", local
->mdev
->name
);
313 fc
= IEEE80211_FTYPE_CTL
| IEEE80211_STYPE_CTS
;
314 hdr
.frame_control
= cpu_to_le16(fc
);
316 cpu_to_le16(2 * local
->hw
.channel_change_time
+
318 memcpy(hdr
.addr1
, local
->mdev
->dev_addr
, ETH_ALEN
); /* DA */
321 memcpy(skb_put(local
->scan
.skb
, len
), &hdr
, len
);
323 memset(&local
->scan
.tx_control
, 0, sizeof(local
->scan
.tx_control
));
324 local
->scan
.tx_control
.key_idx
= HW_KEY_IDX_INVALID
;
325 local
->scan
.tx_control
.flags
|= IEEE80211_TXCTL_DO_NOT_ENCRYPT
;
326 memset(&extra
, 0, sizeof(extra
));
327 extra
.endidx
= local
->num_curr_rates
;
328 local
->scan
.tx_control
.tx_rate
=
329 rate_control_get_rate(local
, local
->mdev
,
330 local
->scan
.skb
, &extra
)->val
;
331 local
->scan
.tx_control
.flags
|= IEEE80211_TXCTL_NO_ACK
;
335 void ieee80211_stop_scan(struct ieee80211_local
*local
)
337 if (local
->ops
->passive_scan
) {
338 del_timer_sync(&local
->scan
.timer
);
339 dev_kfree_skb(local
->scan
.skb
);
340 local
->scan
.skb
= NULL
;