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_modes
**mode
,
28 struct ieee80211_channel
**chan
)
32 for (m
= 0; m
< local
->hw
.num_modes
; m
++) {
33 *mode
= &local
->hw
.modes
[m
];
34 if ((*mode
)->mode
== local
->hw
.conf
.phymode
)
37 local
->scan
.mode_idx
= m
;
38 local
->scan
.chan_idx
= 0;
40 *chan
= &(*mode
)->channels
[local
->scan
.chan_idx
];
41 if ((*chan
)->chan
== channel
) {
44 local
->scan
.chan_idx
++;
45 } while (local
->scan
.chan_idx
< (*mode
)->num_channels
);
50 static void next_chan_same_mode(struct ieee80211_local
*local
,
51 struct ieee80211_hw_modes
**mode
,
52 struct ieee80211_channel
**chan
)
56 for (m
= 0; m
< local
->hw
.num_modes
; m
++) {
57 *mode
= &local
->hw
.modes
[m
];
58 if ((*mode
)->mode
== local
->hw
.conf
.phymode
)
61 local
->scan
.mode_idx
= m
;
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
>= (*mode
)->num_channels
)
68 local
->scan
.chan_idx
= 0;
69 *chan
= &(*mode
)->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_modes
**mode
,
78 struct ieee80211_channel
**chan
)
82 if (local
->scan
.mode_idx
>= local
->hw
.num_modes
) {
83 local
->scan
.mode_idx
= 0;
84 local
->scan
.chan_idx
= 0;
87 /* Select next channel - scan only channels marked with W_SCAN flag */
88 prev
= local
->scan
.chan_idx
;
89 prev_m
= local
->scan
.mode_idx
;
91 *mode
= &local
->hw
.modes
[local
->scan
.mode_idx
];
92 local
->scan
.chan_idx
++;
93 if (local
->scan
.chan_idx
>= (*mode
)->num_channels
) {
94 local
->scan
.chan_idx
= 0;
95 local
->scan
.mode_idx
++;
96 if (local
->scan
.mode_idx
>= local
->hw
.num_modes
)
97 local
->scan
.mode_idx
= 0;
98 *mode
= &local
->hw
.modes
[local
->scan
.mode_idx
];
100 *chan
= &(*mode
)->channels
[local
->scan
.chan_idx
];
101 if ((*chan
)->flag
& IEEE80211_CHAN_W_SCAN
)
103 } while (local
->scan
.chan_idx
!= prev
||
104 local
->scan
.mode_idx
!= prev_m
);
108 static void ieee80211_scan_start(struct ieee80211_local
*local
,
109 struct ieee80211_scan_conf
*conf
)
111 int old_mode_idx
= local
->scan
.mode_idx
;
112 int old_chan_idx
= local
->scan
.chan_idx
;
113 struct ieee80211_hw_modes
*mode
= NULL
;
114 struct ieee80211_channel
*chan
= NULL
;
117 if (!local
->ops
->passive_scan
) {
118 printk(KERN_DEBUG
"%s: Scan handler called, yet the hardware "
119 "does not support passive scanning. Disabled.\n",
124 if ((local
->scan
.tries
< MAX_SCAN_WAIT
&&
125 local
->scan
.txrx_count
> SCAN_TXRX_THRESHOLD
)) {
127 /* Count TX/RX packets during one second interval and allow
128 * scan to start only if the number of packets is below the
130 local
->scan
.txrx_count
= 0;
131 local
->scan
.timer
.expires
= jiffies
+ HZ
;
132 add_timer(&local
->scan
.timer
);
136 if (!local
->scan
.skb
) {
137 printk(KERN_DEBUG
"%s: Scan start called even though scan.skb "
138 "is not set\n", local
->mdev
->name
);
141 if (local
->scan
.our_mode_only
) {
142 if (local
->scan
.channel
> 0) {
143 get_channel_params(local
, local
->scan
.channel
, &mode
,
146 next_chan_same_mode(local
, &mode
, &chan
);
149 next_chan_all_modes(local
, &mode
, &chan
);
151 conf
->scan_channel
= chan
->chan
;
152 conf
->scan_freq
= chan
->freq
;
153 conf
->scan_channel_val
= chan
->val
;
154 conf
->scan_phymode
= mode
->mode
;
155 conf
->scan_power_level
= chan
->power_level
;
156 conf
->scan_antenna_max
= chan
->antenna_max
;
157 conf
->scan_time
= 2 * local
->hw
.channel_change_time
+
158 local
->scan
.time
; /* 10ms scan time+hardware changes */
159 conf
->skb
= local
->scan
.skb
?
160 skb_clone(local
->scan
.skb
, GFP_ATOMIC
) : NULL
;
161 conf
->tx_control
= &local
->scan
.tx_control
;
163 printk(KERN_DEBUG
"%s: Doing scan on mode: %d freq: %d chan: %d "
165 local
->mdev
->name
, conf
->scan_phymode
, conf
->scan_freq
,
166 conf
->scan_channel
, conf
->scan_time
);
168 local
->scan
.rx_packets
= 0;
169 local
->scan
.rx_beacon
= 0;
170 local
->scan
.freq
= chan
->freq
;
171 local
->scan
.in_scan
= 1;
173 ieee80211_netif_oper(local_to_hw(local
), NETIF_STOP
);
175 ret
= local
->ops
->passive_scan(local_to_hw(local
),
176 IEEE80211_SCAN_START
, conf
);
179 long usec
= local
->hw
.channel_change_time
+
181 usec
+= 1000000L / HZ
- 1;
182 usec
/= 1000000L / HZ
;
183 local
->scan
.timer
.expires
= jiffies
+ usec
;
185 local
->scan
.in_scan
= 0;
187 dev_kfree_skb(conf
->skb
);
188 ieee80211_netif_oper(local_to_hw(local
), NETIF_WAKE
);
189 if (ret
== -EAGAIN
) {
190 local
->scan
.timer
.expires
= jiffies
+
191 (local
->scan
.interval
* HZ
/ 100);
192 local
->scan
.mode_idx
= old_mode_idx
;
193 local
->scan
.chan_idx
= old_chan_idx
;
195 printk(KERN_DEBUG
"%s: Got unknown error from "
196 "passive_scan %d\n", local
->mdev
->name
, ret
);
197 local
->scan
.timer
.expires
= jiffies
+
198 (local
->scan
.interval
* HZ
);
200 local
->scan
.in_scan
= 0;
203 add_timer(&local
->scan
.timer
);
207 static void ieee80211_scan_stop(struct ieee80211_local
*local
,
208 struct ieee80211_scan_conf
*conf
)
210 struct ieee80211_hw_modes
*mode
;
211 struct ieee80211_channel
*chan
;
214 if (!local
->ops
->passive_scan
)
217 if (local
->scan
.mode_idx
>= local
->hw
.num_modes
) {
218 local
->scan
.mode_idx
= 0;
219 local
->scan
.chan_idx
= 0;
222 mode
= &local
->hw
.modes
[local
->scan
.mode_idx
];
224 if (local
->scan
.chan_idx
>= mode
->num_channels
) {
225 local
->scan
.chan_idx
= 0;
228 chan
= &mode
->channels
[local
->scan
.chan_idx
];
230 local
->ops
->passive_scan(local_to_hw(local
), IEEE80211_SCAN_END
,
233 #ifdef CONFIG_D80211_VERBOSE_DEBUG
234 printk(KERN_DEBUG
"%s: Did scan on mode: %d freq: %d chan: %d "
235 "GOT: %d Beacon: %d (%d)\n",
237 mode
->mode
, chan
->freq
, chan
->chan
,
238 local
->scan
.rx_packets
, local
->scan
.rx_beacon
,
240 #endif /* CONFIG_D80211_VERBOSE_DEBUG */
241 local
->scan
.num_scans
++;
243 local
->scan
.in_scan
= 0;
244 ieee80211_netif_oper(local_to_hw(local
), NETIF_WAKE
);
246 local
->scan
.tries
= 0;
247 /* Use random interval of scan.interval .. 2 * scan.interval */
248 wait
= (local
->scan
.interval
* HZ
* ((net_random() & 127) + 128)) /
250 local
->scan
.timer
.expires
= jiffies
+ wait
;
252 add_timer(&local
->scan
.timer
);
256 static void ieee80211_scan_handler(unsigned long ullocal
)
258 struct ieee80211_local
*local
= (struct ieee80211_local
*) ullocal
;
259 struct ieee80211_scan_conf conf
;
261 if (local
->scan
.interval
== 0 && !local
->scan
.in_scan
) {
262 /* Passive scanning is disabled - keep the timer always
263 * running to make code cleaner. */
264 local
->scan
.timer
.expires
= jiffies
+ 10 * HZ
;
265 add_timer(&local
->scan
.timer
);
269 memset(&conf
, 0, sizeof(struct ieee80211_scan_conf
));
270 conf
.running_freq
= local
->hw
.conf
.freq
;
271 conf
.running_channel
= local
->hw
.conf
.channel
;
272 conf
.running_phymode
= local
->hw
.conf
.phymode
;
273 conf
.running_channel_val
= local
->hw
.conf
.channel_val
;
274 conf
.running_power_level
= local
->hw
.conf
.power_level
;
275 conf
.running_antenna_max
= local
->hw
.conf
.antenna_max
;
277 if (local
->scan
.in_scan
== 0)
278 ieee80211_scan_start(local
, &conf
);
280 ieee80211_scan_stop(local
, &conf
);
284 void ieee80211_init_scan(struct ieee80211_local
*local
)
286 struct ieee80211_hdr hdr
;
289 struct rate_control_extra extra
;
291 /* Only initialize passive scanning if the hardware supports it */
292 if (!local
->ops
->passive_scan
) {
293 local
->scan
.skb
= NULL
;
294 memset(&local
->scan
.tx_control
, 0,
295 sizeof(local
->scan
.tx_control
));
296 printk(KERN_DEBUG
"%s: Does not support passive scan, "
297 "disabled\n", local
->mdev
->name
);
301 local
->scan
.interval
= 0;
302 local
->scan
.our_mode_only
= 1;
303 local
->scan
.time
= 10000;
304 local
->scan
.timer
.function
= ieee80211_scan_handler
;
305 local
->scan
.timer
.data
= (unsigned long) local
;
306 local
->scan
.timer
.expires
= jiffies
+ local
->scan
.interval
* HZ
;
307 add_timer(&local
->scan
.timer
);
309 /* Create a CTS from for broadcasting before
310 * the low level changes channels */
311 local
->scan
.skb
= alloc_skb(len
, GFP_KERNEL
);
312 if (!local
->scan
.skb
) {
313 printk(KERN_WARNING
"%s: Failed to allocate CTS packet for "
314 "passive scan\n", local
->mdev
->name
);
318 fc
= IEEE80211_FTYPE_CTL
| IEEE80211_STYPE_CTS
;
319 hdr
.frame_control
= cpu_to_le16(fc
);
321 cpu_to_le16(2 * local
->hw
.channel_change_time
+
323 memcpy(hdr
.addr1
, local
->mdev
->dev_addr
, ETH_ALEN
); /* DA */
326 memcpy(skb_put(local
->scan
.skb
, len
), &hdr
, len
);
328 memset(&local
->scan
.tx_control
, 0, sizeof(local
->scan
.tx_control
));
329 local
->scan
.tx_control
.key_idx
= HW_KEY_IDX_INVALID
;
330 local
->scan
.tx_control
.flags
|= IEEE80211_TXCTL_DO_NOT_ENCRYPT
;
331 memset(&extra
, 0, sizeof(extra
));
332 extra
.endidx
= local
->num_curr_rates
;
333 local
->scan
.tx_control
.tx_rate
=
334 rate_control_get_rate(local
, local
->mdev
,
335 local
->scan
.skb
, &extra
)->val
;
336 local
->scan
.tx_control
.flags
|= IEEE80211_TXCTL_NO_ACK
;
340 void ieee80211_stop_scan(struct ieee80211_local
*local
)
342 if (local
->ops
->passive_scan
) {
343 del_timer_sync(&local
->scan
.timer
);
344 dev_kfree_skb(local
->scan
.skb
);
345 local
->scan
.skb
= NULL
;