diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2008-04-19 12:17:34 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-04-19 12:17:34 -0400 |
commit | cf816ecb533ab96b883dfdc0db174598b5b5c4d2 (patch) | |
tree | 1b7705db288ae2917105e624b01fdf81e0882bf1 /drivers/net/wireless/libertas/scan.c | |
parent | adf6d34e460387ee3e8f1e1875d52bff51212c7d (diff) | |
parent | 15f7d677ccff6f0f5de8a1ee43a792567e9f9de9 (diff) |
Merge branch 'merge-fixes' into devel
Diffstat (limited to 'drivers/net/wireless/libertas/scan.c')
-rw-r--r-- | drivers/net/wireless/libertas/scan.c | 877 |
1 files changed, 214 insertions, 663 deletions
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 69f94c92b32d..e72c97a0d6c1 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
@@ -4,22 +4,14 @@ | |||
4 | * IOCTL handlers as well as command preperation and response routines | 4 | * IOCTL handlers as well as command preperation and response routines |
5 | * for sending scan commands to the firmware. | 5 | * for sending scan commands to the firmware. |
6 | */ | 6 | */ |
7 | #include <linux/ctype.h> | ||
8 | #include <linux/if.h> | ||
9 | #include <linux/netdevice.h> | ||
10 | #include <linux/wireless.h> | ||
11 | #include <linux/etherdevice.h> | 7 | #include <linux/etherdevice.h> |
12 | |||
13 | #include <net/ieee80211.h> | ||
14 | #include <net/iw_handler.h> | ||
15 | |||
16 | #include <asm/unaligned.h> | 8 | #include <asm/unaligned.h> |
17 | 9 | ||
18 | #include "host.h" | 10 | #include "host.h" |
19 | #include "decl.h" | 11 | #include "decl.h" |
20 | #include "dev.h" | 12 | #include "dev.h" |
21 | #include "scan.h" | 13 | #include "scan.h" |
22 | #include "join.h" | 14 | #include "cmd.h" |
23 | 15 | ||
24 | //! Approximate amount of data needed to pass a scan result back to iwlist | 16 | //! Approximate amount of data needed to pass a scan result back to iwlist |
25 | #define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \ | 17 | #define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \ |
@@ -39,10 +31,9 @@ | |||
39 | //! Memory needed to store a max number/size SSID TLV for a firmware scan | 31 | //! Memory needed to store a max number/size SSID TLV for a firmware scan |
40 | #define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvlietypes_ssidparamset)) | 32 | #define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvlietypes_ssidparamset)) |
41 | 33 | ||
42 | //! Maximum memory needed for a lbs_scan_cmd_config with all TLVs at max | 34 | //! Maximum memory needed for a cmd_ds_802_11_scan with all TLVs at max |
43 | #define MAX_SCAN_CFG_ALLOC (sizeof(struct lbs_scan_cmd_config) \ | 35 | #define MAX_SCAN_CFG_ALLOC (sizeof(struct cmd_ds_802_11_scan) \ |
44 | + CHAN_TLV_MAX_SIZE \ | 36 | + CHAN_TLV_MAX_SIZE + SSID_TLV_MAX_SIZE) |
45 | + SSID_TLV_MAX_SIZE) | ||
46 | 37 | ||
47 | //! The maximum number of channels the firmware can scan per command | 38 | //! The maximum number of channels the firmware can scan per command |
48 | #define MRVDRV_MAX_CHANNELS_PER_SCAN 14 | 39 | #define MRVDRV_MAX_CHANNELS_PER_SCAN 14 |
@@ -61,11 +52,8 @@ | |||
61 | //! Scan time specified in the channel TLV for each channel for active scans | 52 | //! Scan time specified in the channel TLV for each channel for active scans |
62 | #define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100 | 53 | #define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100 |
63 | 54 | ||
64 | static const u8 zeromac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | 55 | static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, |
65 | static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 56 | struct cmd_header *resp); |
66 | |||
67 | |||
68 | |||
69 | 57 | ||
70 | /*********************************************************************/ | 58 | /*********************************************************************/ |
71 | /* */ | 59 | /* */ |
@@ -73,7 +61,24 @@ static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | |||
73 | /* */ | 61 | /* */ |
74 | /*********************************************************************/ | 62 | /*********************************************************************/ |
75 | 63 | ||
76 | static inline void clear_bss_descriptor (struct bss_descriptor * bss) | 64 | /** |
65 | * @brief Unsets the MSB on basic rates | ||
66 | * | ||
67 | * Scan through an array and unset the MSB for basic data rates. | ||
68 | * | ||
69 | * @param rates buffer of data rates | ||
70 | * @param len size of buffer | ||
71 | */ | ||
72 | static void lbs_unset_basic_rate_flags(u8 *rates, size_t len) | ||
73 | { | ||
74 | int i; | ||
75 | |||
76 | for (i = 0; i < len; i++) | ||
77 | rates[i] &= 0x7f; | ||
78 | } | ||
79 | |||
80 | |||
81 | static inline void clear_bss_descriptor(struct bss_descriptor *bss) | ||
77 | { | 82 | { |
78 | /* Don't blow away ->list, just BSS data */ | 83 | /* Don't blow away ->list, just BSS data */ |
79 | memset(bss, 0, offsetof(struct bss_descriptor, list)); | 84 | memset(bss, 0, offsetof(struct bss_descriptor, list)); |
@@ -87,7 +92,8 @@ static inline void clear_bss_descriptor (struct bss_descriptor * bss) | |||
87 | * | 92 | * |
88 | * @return 0: ssid is same, otherwise is different | 93 | * @return 0: ssid is same, otherwise is different |
89 | */ | 94 | */ |
90 | int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len) | 95 | int lbs_ssid_cmp(uint8_t *ssid1, uint8_t ssid1_len, uint8_t *ssid2, |
96 | uint8_t ssid2_len) | ||
91 | { | 97 | { |
92 | if (ssid1_len != ssid2_len) | 98 | if (ssid1_len != ssid2_len) |
93 | return -1; | 99 | return -1; |
@@ -95,76 +101,6 @@ int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len) | |||
95 | return memcmp(ssid1, ssid2, ssid1_len); | 101 | return memcmp(ssid1, ssid2, ssid1_len); |
96 | } | 102 | } |
97 | 103 | ||
98 | static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, | ||
99 | struct bss_descriptor * match_bss) | ||
100 | { | ||
101 | if ( !secinfo->wep_enabled | ||
102 | && !secinfo->WPAenabled | ||
103 | && !secinfo->WPA2enabled | ||
104 | && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC | ||
105 | && match_bss->rsn_ie[0] != MFIE_TYPE_RSN | ||
106 | && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { | ||
107 | return 1; | ||
108 | } | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, | ||
113 | struct bss_descriptor * match_bss) | ||
114 | { | ||
115 | if ( secinfo->wep_enabled | ||
116 | && !secinfo->WPAenabled | ||
117 | && !secinfo->WPA2enabled | ||
118 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { | ||
119 | return 1; | ||
120 | } | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static inline int match_bss_wpa(struct lbs_802_11_security *secinfo, | ||
125 | struct bss_descriptor * match_bss) | ||
126 | { | ||
127 | if ( !secinfo->wep_enabled | ||
128 | && secinfo->WPAenabled | ||
129 | && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC) | ||
130 | /* privacy bit may NOT be set in some APs like LinkSys WRT54G | ||
131 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { | ||
132 | */ | ||
133 | ) { | ||
134 | return 1; | ||
135 | } | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo, | ||
140 | struct bss_descriptor * match_bss) | ||
141 | { | ||
142 | if ( !secinfo->wep_enabled | ||
143 | && secinfo->WPA2enabled | ||
144 | && (match_bss->rsn_ie[0] == MFIE_TYPE_RSN) | ||
145 | /* privacy bit may NOT be set in some APs like LinkSys WRT54G | ||
146 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { | ||
147 | */ | ||
148 | ) { | ||
149 | return 1; | ||
150 | } | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, | ||
155 | struct bss_descriptor * match_bss) | ||
156 | { | ||
157 | if ( !secinfo->wep_enabled | ||
158 | && !secinfo->WPAenabled | ||
159 | && !secinfo->WPA2enabled | ||
160 | && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC) | ||
161 | && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN) | ||
162 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { | ||
163 | return 1; | ||
164 | } | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static inline int is_same_network(struct bss_descriptor *src, | 104 | static inline int is_same_network(struct bss_descriptor *src, |
169 | struct bss_descriptor *dst) | 105 | struct bss_descriptor *dst) |
170 | { | 106 | { |
@@ -177,83 +113,6 @@ static inline int is_same_network(struct bss_descriptor *src, | |||
177 | !memcmp(src->ssid, dst->ssid, src->ssid_len)); | 113 | !memcmp(src->ssid, dst->ssid, src->ssid_len)); |
178 | } | 114 | } |
179 | 115 | ||
180 | /** | ||
181 | * @brief Check if a scanned network compatible with the driver settings | ||
182 | * | ||
183 | * WEP WPA WPA2 ad-hoc encrypt Network | ||
184 | * enabled enabled enabled AES mode privacy WPA WPA2 Compatible | ||
185 | * 0 0 0 0 NONE 0 0 0 yes No security | ||
186 | * 1 0 0 0 NONE 1 0 0 yes Static WEP | ||
187 | * 0 1 0 0 x 1x 1 x yes WPA | ||
188 | * 0 0 1 0 x 1x x 1 yes WPA2 | ||
189 | * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES | ||
190 | * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP | ||
191 | * | ||
192 | * | ||
193 | * @param priv A pointer to struct lbs_private | ||
194 | * @param index Index in scantable to check against current driver settings | ||
195 | * @param mode Network mode: Infrastructure or IBSS | ||
196 | * | ||
197 | * @return Index in scantable, or error code if negative | ||
198 | */ | ||
199 | static int is_network_compatible(struct lbs_private *priv, | ||
200 | struct bss_descriptor * bss, u8 mode) | ||
201 | { | ||
202 | int matched = 0; | ||
203 | |||
204 | lbs_deb_enter(LBS_DEB_SCAN); | ||
205 | |||
206 | if (bss->mode != mode) | ||
207 | goto done; | ||
208 | |||
209 | if ((matched = match_bss_no_security(&priv->secinfo, bss))) { | ||
210 | goto done; | ||
211 | } else if ((matched = match_bss_static_wep(&priv->secinfo, bss))) { | ||
212 | goto done; | ||
213 | } else if ((matched = match_bss_wpa(&priv->secinfo, bss))) { | ||
214 | lbs_deb_scan( | ||
215 | "is_network_compatible() WPA: wpa_ie 0x%x " | ||
216 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " | ||
217 | "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], | ||
218 | priv->secinfo.wep_enabled ? "e" : "d", | ||
219 | priv->secinfo.WPAenabled ? "e" : "d", | ||
220 | priv->secinfo.WPA2enabled ? "e" : "d", | ||
221 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); | ||
222 | goto done; | ||
223 | } else if ((matched = match_bss_wpa2(&priv->secinfo, bss))) { | ||
224 | lbs_deb_scan( | ||
225 | "is_network_compatible() WPA2: wpa_ie 0x%x " | ||
226 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " | ||
227 | "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], | ||
228 | priv->secinfo.wep_enabled ? "e" : "d", | ||
229 | priv->secinfo.WPAenabled ? "e" : "d", | ||
230 | priv->secinfo.WPA2enabled ? "e" : "d", | ||
231 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); | ||
232 | goto done; | ||
233 | } else if ((matched = match_bss_dynamic_wep(&priv->secinfo, bss))) { | ||
234 | lbs_deb_scan( | ||
235 | "is_network_compatible() dynamic WEP: " | ||
236 | "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n", | ||
237 | bss->wpa_ie[0], bss->rsn_ie[0], | ||
238 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); | ||
239 | goto done; | ||
240 | } | ||
241 | |||
242 | /* bss security settings don't match those configured on card */ | ||
243 | lbs_deb_scan( | ||
244 | "is_network_compatible() FAILED: wpa_ie 0x%x " | ||
245 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n", | ||
246 | bss->wpa_ie[0], bss->rsn_ie[0], | ||
247 | priv->secinfo.wep_enabled ? "e" : "d", | ||
248 | priv->secinfo.WPAenabled ? "e" : "d", | ||
249 | priv->secinfo.WPA2enabled ? "e" : "d", | ||
250 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); | ||
251 | |||
252 | done: | ||
253 | lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched); | ||
254 | return matched; | ||
255 | } | ||
256 | |||
257 | 116 | ||
258 | 117 | ||
259 | 118 | ||
@@ -263,17 +122,6 @@ done: | |||
263 | /* */ | 122 | /* */ |
264 | /*********************************************************************/ | 123 | /*********************************************************************/ |
265 | 124 | ||
266 | void lbs_scan_worker(struct work_struct *work) | ||
267 | { | ||
268 | struct lbs_private *priv = | ||
269 | container_of(work, struct lbs_private, scan_work.work); | ||
270 | |||
271 | lbs_deb_enter(LBS_DEB_SCAN); | ||
272 | lbs_scan_networks(priv, NULL, 0); | ||
273 | lbs_deb_leave(LBS_DEB_SCAN); | ||
274 | } | ||
275 | |||
276 | |||
277 | /** | 125 | /** |
278 | * @brief Create a channel list for the driver to scan based on region info | 126 | * @brief Create a channel list for the driver to scan based on region info |
279 | * | 127 | * |
@@ -285,25 +133,18 @@ void lbs_scan_worker(struct work_struct *work) | |||
285 | * | 133 | * |
286 | * @param priv A pointer to struct lbs_private structure | 134 | * @param priv A pointer to struct lbs_private structure |
287 | * @param scanchanlist Output parameter: resulting channel list to scan | 135 | * @param scanchanlist Output parameter: resulting channel list to scan |
288 | * @param filteredscan Flag indicating whether or not a BSSID or SSID filter | ||
289 | * is being sent in the command to firmware. Used to | ||
290 | * increase the number of channels sent in a scan | ||
291 | * command and to disable the firmware channel scan | ||
292 | * filter. | ||
293 | * | 136 | * |
294 | * @return void | 137 | * @return void |
295 | */ | 138 | */ |
296 | static int lbs_scan_create_channel_list(struct lbs_private *priv, | 139 | static int lbs_scan_create_channel_list(struct lbs_private *priv, |
297 | struct chanscanparamset * scanchanlist, | 140 | struct chanscanparamset *scanchanlist) |
298 | u8 filteredscan) | ||
299 | { | 141 | { |
300 | |||
301 | struct region_channel *scanregion; | 142 | struct region_channel *scanregion; |
302 | struct chan_freq_power *cfp; | 143 | struct chan_freq_power *cfp; |
303 | int rgnidx; | 144 | int rgnidx; |
304 | int chanidx; | 145 | int chanidx; |
305 | int nextchan; | 146 | int nextchan; |
306 | u8 scantype; | 147 | uint8_t scantype; |
307 | 148 | ||
308 | chanidx = 0; | 149 | chanidx = 0; |
309 | 150 | ||
@@ -314,9 +155,8 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, | |||
314 | scantype = CMD_SCAN_TYPE_ACTIVE; | 155 | scantype = CMD_SCAN_TYPE_ACTIVE; |
315 | 156 | ||
316 | for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) { | 157 | for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) { |
317 | if (priv->enable11d && | 158 | if (priv->enable11d && (priv->connect_status != LBS_CONNECTED) |
318 | (priv->connect_status != LBS_CONNECTED) && | 159 | && (priv->mesh_connect_status != LBS_CONNECTED)) { |
319 | (priv->mesh_connect_status != LBS_CONNECTED)) { | ||
320 | /* Scan all the supported chan for the first scan */ | 160 | /* Scan all the supported chan for the first scan */ |
321 | if (!priv->universal_channel[rgnidx].valid) | 161 | if (!priv->universal_channel[rgnidx].valid) |
322 | continue; | 162 | continue; |
@@ -331,51 +171,32 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, | |||
331 | scanregion = &priv->region_channel[rgnidx]; | 171 | scanregion = &priv->region_channel[rgnidx]; |
332 | } | 172 | } |
333 | 173 | ||
334 | for (nextchan = 0; | 174 | for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) { |
335 | nextchan < scanregion->nrcfp; nextchan++, chanidx++) { | 175 | struct chanscanparamset *chan = &scanchanlist[chanidx]; |
336 | 176 | ||
337 | cfp = scanregion->CFP + nextchan; | 177 | cfp = scanregion->CFP + nextchan; |
338 | 178 | ||
339 | if (priv->enable11d) { | 179 | if (priv->enable11d) |
340 | scantype = | 180 | scantype = lbs_get_scan_type_11d(cfp->channel, |
341 | lbs_get_scan_type_11d(cfp->channel, | 181 | &priv->parsed_region_chan); |
342 | &priv-> | ||
343 | parsed_region_chan); | ||
344 | } | ||
345 | 182 | ||
346 | switch (scanregion->band) { | 183 | if (scanregion->band == BAND_B || scanregion->band == BAND_G) |
347 | case BAND_B: | 184 | chan->radiotype = CMD_SCAN_RADIO_TYPE_BG; |
348 | case BAND_G: | ||
349 | default: | ||
350 | scanchanlist[chanidx].radiotype = | ||
351 | CMD_SCAN_RADIO_TYPE_BG; | ||
352 | break; | ||
353 | } | ||
354 | 185 | ||
355 | if (scantype == CMD_SCAN_TYPE_PASSIVE) { | 186 | if (scantype == CMD_SCAN_TYPE_PASSIVE) { |
356 | scanchanlist[chanidx].maxscantime = | 187 | chan->maxscantime = cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME); |
357 | cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME); | 188 | chan->chanscanmode.passivescan = 1; |
358 | scanchanlist[chanidx].chanscanmode.passivescan = | ||
359 | 1; | ||
360 | } else { | 189 | } else { |
361 | scanchanlist[chanidx].maxscantime = | 190 | chan->maxscantime = cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME); |
362 | cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME); | 191 | chan->chanscanmode.passivescan = 0; |
363 | scanchanlist[chanidx].chanscanmode.passivescan = | ||
364 | 0; | ||
365 | } | 192 | } |
366 | 193 | ||
367 | scanchanlist[chanidx].channumber = cfp->channel; | 194 | chan->channumber = cfp->channel; |
368 | |||
369 | if (filteredscan) { | ||
370 | scanchanlist[chanidx].chanscanmode. | ||
371 | disablechanfilt = 1; | ||
372 | } | ||
373 | } | 195 | } |
374 | } | 196 | } |
375 | return chanidx; | 197 | return chanidx; |
376 | } | 198 | } |
377 | 199 | ||
378 | |||
379 | /* | 200 | /* |
380 | * Add SSID TLV of the form: | 201 | * Add SSID TLV of the form: |
381 | * | 202 | * |
@@ -383,18 +204,16 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, | |||
383 | * length 06 00 | 204 | * length 06 00 |
384 | * ssid 4d 4e 54 45 53 54 | 205 | * ssid 4d 4e 54 45 53 54 |
385 | */ | 206 | */ |
386 | static int lbs_scan_add_ssid_tlv(u8 *tlv, | 207 | static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv) |
387 | const struct lbs_ioctl_user_scan_cfg *user_cfg) | ||
388 | { | 208 | { |
389 | struct mrvlietypes_ssidparamset *ssid_tlv = | 209 | struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv; |
390 | (struct mrvlietypes_ssidparamset *)tlv; | 210 | |
391 | ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); | 211 | ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); |
392 | ssid_tlv->header.len = cpu_to_le16(user_cfg->ssid_len); | 212 | ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len); |
393 | memcpy(ssid_tlv->ssid, user_cfg->ssid, user_cfg->ssid_len); | 213 | memcpy(ssid_tlv->ssid, priv->scan_ssid, priv->scan_ssid_len); |
394 | return sizeof(ssid_tlv->header) + user_cfg->ssid_len; | 214 | return sizeof(ssid_tlv->header) + priv->scan_ssid_len; |
395 | } | 215 | } |
396 | 216 | ||
397 | |||
398 | /* | 217 | /* |
399 | * Add CHANLIST TLV of the form | 218 | * Add CHANLIST TLV of the form |
400 | * | 219 | * |
@@ -420,13 +239,12 @@ static int lbs_scan_add_ssid_tlv(u8 *tlv, | |||
420 | * channel 13 00 0d 00 00 00 64 00 | 239 | * channel 13 00 0d 00 00 00 64 00 |
421 | * | 240 | * |
422 | */ | 241 | */ |
423 | static int lbs_scan_add_chanlist_tlv(u8 *tlv, | 242 | static int lbs_scan_add_chanlist_tlv(uint8_t *tlv, |
424 | struct chanscanparamset *chan_list, | 243 | struct chanscanparamset *chan_list, |
425 | int chan_count) | 244 | int chan_count) |
426 | { | 245 | { |
427 | size_t size = sizeof(struct chanscanparamset) * chan_count; | 246 | size_t size = sizeof(struct chanscanparamset) *chan_count; |
428 | struct mrvlietypes_chanlistparamset *chan_tlv = | 247 | struct mrvlietypes_chanlistparamset *chan_tlv = (void *)tlv; |
429 | (struct mrvlietypes_chanlistparamset *) tlv; | ||
430 | 248 | ||
431 | chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); | 249 | chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); |
432 | memcpy(chan_tlv->chanscanparam, chan_list, size); | 250 | memcpy(chan_tlv->chanscanparam, chan_list, size); |
@@ -434,7 +252,6 @@ static int lbs_scan_add_chanlist_tlv(u8 *tlv, | |||
434 | return sizeof(chan_tlv->header) + size; | 252 | return sizeof(chan_tlv->header) + size; |
435 | } | 253 | } |
436 | 254 | ||
437 | |||
438 | /* | 255 | /* |
439 | * Add RATES TLV of the form | 256 | * Add RATES TLV of the form |
440 | * | 257 | * |
@@ -445,11 +262,10 @@ static int lbs_scan_add_chanlist_tlv(u8 *tlv, | |||
445 | * The rates are in lbs_bg_rates[], but for the 802.11b | 262 | * The rates are in lbs_bg_rates[], but for the 802.11b |
446 | * rates the high bit isn't set. | 263 | * rates the high bit isn't set. |
447 | */ | 264 | */ |
448 | static int lbs_scan_add_rates_tlv(u8 *tlv) | 265 | static int lbs_scan_add_rates_tlv(uint8_t *tlv) |
449 | { | 266 | { |
450 | int i; | 267 | int i; |
451 | struct mrvlietypes_ratesparamset *rate_tlv = | 268 | struct mrvlietypes_ratesparamset *rate_tlv = (void *)tlv; |
452 | (struct mrvlietypes_ratesparamset *) tlv; | ||
453 | 269 | ||
454 | rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES); | 270 | rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES); |
455 | tlv += sizeof(rate_tlv->header); | 271 | tlv += sizeof(rate_tlv->header); |
@@ -470,82 +286,74 @@ static int lbs_scan_add_rates_tlv(u8 *tlv) | |||
470 | return sizeof(rate_tlv->header) + i; | 286 | return sizeof(rate_tlv->header) + i; |
471 | } | 287 | } |
472 | 288 | ||
473 | |||
474 | /* | 289 | /* |
475 | * Generate the CMD_802_11_SCAN command with the proper tlv | 290 | * Generate the CMD_802_11_SCAN command with the proper tlv |
476 | * for a bunch of channels. | 291 | * for a bunch of channels. |
477 | */ | 292 | */ |
478 | static int lbs_do_scan(struct lbs_private *priv, | 293 | static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype, |
479 | u8 bsstype, | 294 | struct chanscanparamset *chan_list, int chan_count) |
480 | struct chanscanparamset *chan_list, | ||
481 | int chan_count, | ||
482 | const struct lbs_ioctl_user_scan_cfg *user_cfg) | ||
483 | { | 295 | { |
484 | int ret = -ENOMEM; | 296 | int ret = -ENOMEM; |
485 | struct lbs_scan_cmd_config *scan_cmd; | 297 | struct cmd_ds_802_11_scan *scan_cmd; |
486 | u8 *tlv; /* pointer into our current, growing TLV storage area */ | 298 | uint8_t *tlv; /* pointer into our current, growing TLV storage area */ |
487 | 299 | ||
488 | lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, " | 300 | lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, chan_count %d", |
489 | "chan_count %d", | 301 | bsstype, chan_list[0].channumber, chan_count); |
490 | bsstype, chan_list[0].channumber, chan_count); | ||
491 | 302 | ||
492 | /* create the fixed part for scan command */ | 303 | /* create the fixed part for scan command */ |
493 | scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL); | 304 | scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL); |
494 | if (scan_cmd == NULL) | 305 | if (scan_cmd == NULL) |
495 | goto out; | 306 | goto out; |
307 | |||
496 | tlv = scan_cmd->tlvbuffer; | 308 | tlv = scan_cmd->tlvbuffer; |
497 | if (user_cfg) | 309 | /* TODO: do we need to scan for a specific BSSID? |
498 | memcpy(scan_cmd->bssid, user_cfg->bssid, ETH_ALEN); | 310 | memcpy(scan_cmd->bssid, priv->scan_bssid, ETH_ALEN); */ |
499 | scan_cmd->bsstype = bsstype; | 311 | scan_cmd->bsstype = bsstype; |
500 | 312 | ||
501 | /* add TLVs */ | 313 | /* add TLVs */ |
502 | if (user_cfg && user_cfg->ssid_len) | 314 | if (priv->scan_ssid_len) |
503 | tlv += lbs_scan_add_ssid_tlv(tlv, user_cfg); | 315 | tlv += lbs_scan_add_ssid_tlv(priv, tlv); |
504 | if (chan_list && chan_count) | 316 | if (chan_list && chan_count) |
505 | tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count); | 317 | tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count); |
506 | tlv += lbs_scan_add_rates_tlv(tlv); | 318 | tlv += lbs_scan_add_rates_tlv(tlv); |
507 | 319 | ||
508 | /* This is the final data we are about to send */ | 320 | /* This is the final data we are about to send */ |
509 | scan_cmd->tlvbufferlen = tlv - scan_cmd->tlvbuffer; | 321 | scan_cmd->hdr.size = cpu_to_le16(tlv - (uint8_t *)scan_cmd); |
510 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd, 1+6); | 322 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd, |
323 | sizeof(*scan_cmd)); | ||
511 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer, | 324 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer, |
512 | scan_cmd->tlvbufferlen); | 325 | tlv - scan_cmd->tlvbuffer); |
326 | |||
327 | ret = __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr, | ||
328 | le16_to_cpu(scan_cmd->hdr.size), | ||
329 | lbs_ret_80211_scan, 0); | ||
513 | 330 | ||
514 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, 0, | ||
515 | CMD_OPTION_WAITFORRSP, 0, scan_cmd); | ||
516 | out: | 331 | out: |
517 | kfree(scan_cmd); | 332 | kfree(scan_cmd); |
518 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | 333 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); |
519 | return ret; | 334 | return ret; |
520 | } | 335 | } |
521 | 336 | ||
522 | |||
523 | /** | 337 | /** |
524 | * @brief Internal function used to start a scan based on an input config | 338 | * @brief Internal function used to start a scan based on an input config |
525 | * | 339 | * |
526 | * Also used from debugfs | ||
527 | * | ||
528 | * Use the input user scan configuration information when provided in | 340 | * Use the input user scan configuration information when provided in |
529 | * order to send the appropriate scan commands to firmware to populate or | 341 | * order to send the appropriate scan commands to firmware to populate or |
530 | * update the internal driver scan table | 342 | * update the internal driver scan table |
531 | * | 343 | * |
532 | * @param priv A pointer to struct lbs_private structure | 344 | * @param priv A pointer to struct lbs_private structure |
533 | * @param puserscanin Pointer to the input configuration for the requested | 345 | * @param full_scan Do a full-scan (blocking) |
534 | * scan. | ||
535 | * | 346 | * |
536 | * @return 0 or < 0 if error | 347 | * @return 0 or < 0 if error |
537 | */ | 348 | */ |
538 | int lbs_scan_networks(struct lbs_private *priv, | 349 | int lbs_scan_networks(struct lbs_private *priv, int full_scan) |
539 | const struct lbs_ioctl_user_scan_cfg *user_cfg, | ||
540 | int full_scan) | ||
541 | { | 350 | { |
542 | int ret = -ENOMEM; | 351 | int ret = -ENOMEM; |
543 | struct chanscanparamset *chan_list; | 352 | struct chanscanparamset *chan_list; |
544 | struct chanscanparamset *curr_chans; | 353 | struct chanscanparamset *curr_chans; |
545 | int chan_count; | 354 | int chan_count; |
546 | u8 bsstype = CMD_BSS_TYPE_ANY; | 355 | uint8_t bsstype = CMD_BSS_TYPE_ANY; |
547 | int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD; | 356 | int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD; |
548 | int filteredscan = 0; | ||
549 | union iwreq_data wrqu; | 357 | union iwreq_data wrqu; |
550 | #ifdef CONFIG_LIBERTAS_DEBUG | 358 | #ifdef CONFIG_LIBERTAS_DEBUG |
551 | struct bss_descriptor *iter; | 359 | struct bss_descriptor *iter; |
@@ -553,8 +361,7 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
553 | DECLARE_MAC_BUF(mac); | 361 | DECLARE_MAC_BUF(mac); |
554 | #endif | 362 | #endif |
555 | 363 | ||
556 | lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", | 364 | lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan); |
557 | full_scan); | ||
558 | 365 | ||
559 | /* Cancel any partial outstanding partial scans if this scan | 366 | /* Cancel any partial outstanding partial scans if this scan |
560 | * is a full scan. | 367 | * is a full scan. |
@@ -562,30 +369,27 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
562 | if (full_scan && delayed_work_pending(&priv->scan_work)) | 369 | if (full_scan && delayed_work_pending(&priv->scan_work)) |
563 | cancel_delayed_work(&priv->scan_work); | 370 | cancel_delayed_work(&priv->scan_work); |
564 | 371 | ||
565 | /* Determine same scan parameters */ | 372 | /* User-specified bsstype or channel list |
373 | TODO: this can be implemented if some user-space application | ||
374 | need the feature. Formerly, it was accessible from debugfs, | ||
375 | but then nowhere used. | ||
566 | if (user_cfg) { | 376 | if (user_cfg) { |
567 | if (user_cfg->bsstype) | 377 | if (user_cfg->bsstype) |
568 | bsstype = user_cfg->bsstype; | 378 | bsstype = user_cfg->bsstype; |
569 | if (compare_ether_addr(user_cfg->bssid, &zeromac[0]) != 0) { | 379 | } */ |
570 | numchannels = MRVDRV_MAX_CHANNELS_PER_SCAN; | 380 | |
571 | filteredscan = 1; | 381 | lbs_deb_scan("numchannels %d, bsstype %d\n", numchannels, bsstype); |
572 | } | ||
573 | } | ||
574 | lbs_deb_scan("numchannels %d, bsstype %d, " | ||
575 | "filteredscan %d\n", | ||
576 | numchannels, bsstype, filteredscan); | ||
577 | 382 | ||
578 | /* Create list of channels to scan */ | 383 | /* Create list of channels to scan */ |
579 | chan_list = kzalloc(sizeof(struct chanscanparamset) * | 384 | chan_list = kzalloc(sizeof(struct chanscanparamset) * |
580 | LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL); | 385 | LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL); |
581 | if (!chan_list) { | 386 | if (!chan_list) { |
582 | lbs_pr_alert("SCAN: chan_list empty\n"); | 387 | lbs_pr_alert("SCAN: chan_list empty\n"); |
583 | goto out; | 388 | goto out; |
584 | } | 389 | } |
585 | 390 | ||
586 | /* We want to scan all channels */ | 391 | /* We want to scan all channels */ |
587 | chan_count = lbs_scan_create_channel_list(priv, chan_list, | 392 | chan_count = lbs_scan_create_channel_list(priv, chan_list); |
588 | filteredscan); | ||
589 | 393 | ||
590 | netif_stop_queue(priv->dev); | 394 | netif_stop_queue(priv->dev); |
591 | netif_carrier_off(priv->dev); | 395 | netif_carrier_off(priv->dev); |
@@ -595,13 +399,13 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
595 | } | 399 | } |
596 | 400 | ||
597 | /* Prepare to continue an interrupted scan */ | 401 | /* Prepare to continue an interrupted scan */ |
598 | lbs_deb_scan("chan_count %d, last_scanned_channel %d\n", | 402 | lbs_deb_scan("chan_count %d, scan_channel %d\n", |
599 | chan_count, priv->last_scanned_channel); | 403 | chan_count, priv->scan_channel); |
600 | curr_chans = chan_list; | 404 | curr_chans = chan_list; |
601 | /* advance channel list by already-scanned-channels */ | 405 | /* advance channel list by already-scanned-channels */ |
602 | if (priv->last_scanned_channel > 0) { | 406 | if (priv->scan_channel > 0) { |
603 | curr_chans += priv->last_scanned_channel; | 407 | curr_chans += priv->scan_channel; |
604 | chan_count -= priv->last_scanned_channel; | 408 | chan_count -= priv->scan_channel; |
605 | } | 409 | } |
606 | 410 | ||
607 | /* Send scan command(s) | 411 | /* Send scan command(s) |
@@ -612,9 +416,9 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
612 | while (chan_count) { | 416 | while (chan_count) { |
613 | int to_scan = min(numchannels, chan_count); | 417 | int to_scan = min(numchannels, chan_count); |
614 | lbs_deb_scan("scanning %d of %d channels\n", | 418 | lbs_deb_scan("scanning %d of %d channels\n", |
615 | to_scan, chan_count); | 419 | to_scan, chan_count); |
616 | ret = lbs_do_scan(priv, bsstype, curr_chans, | 420 | ret = lbs_do_scan(priv, bsstype, curr_chans, |
617 | to_scan, user_cfg); | 421 | to_scan); |
618 | if (ret) { | 422 | if (ret) { |
619 | lbs_pr_err("SCAN_CMD failed\n"); | 423 | lbs_pr_err("SCAN_CMD failed\n"); |
620 | goto out2; | 424 | goto out2; |
@@ -623,17 +427,16 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
623 | chan_count -= to_scan; | 427 | chan_count -= to_scan; |
624 | 428 | ||
625 | /* somehow schedule the next part of the scan */ | 429 | /* somehow schedule the next part of the scan */ |
626 | if (chan_count && | 430 | if (chan_count && !full_scan && |
627 | !full_scan && | ||
628 | !priv->surpriseremoved) { | 431 | !priv->surpriseremoved) { |
629 | /* -1 marks just that we're currently scanning */ | 432 | /* -1 marks just that we're currently scanning */ |
630 | if (priv->last_scanned_channel < 0) | 433 | if (priv->scan_channel < 0) |
631 | priv->last_scanned_channel = to_scan; | 434 | priv->scan_channel = to_scan; |
632 | else | 435 | else |
633 | priv->last_scanned_channel += to_scan; | 436 | priv->scan_channel += to_scan; |
634 | cancel_delayed_work(&priv->scan_work); | 437 | cancel_delayed_work(&priv->scan_work); |
635 | queue_delayed_work(priv->work_thread, &priv->scan_work, | 438 | queue_delayed_work(priv->work_thread, &priv->scan_work, |
636 | msecs_to_jiffies(300)); | 439 | msecs_to_jiffies(300)); |
637 | /* skip over GIWSCAN event */ | 440 | /* skip over GIWSCAN event */ |
638 | goto out; | 441 | goto out; |
639 | } | 442 | } |
@@ -648,13 +451,13 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
648 | lbs_deb_scan("scan table:\n"); | 451 | lbs_deb_scan("scan table:\n"); |
649 | list_for_each_entry(iter, &priv->network_list, list) | 452 | list_for_each_entry(iter, &priv->network_list, list) |
650 | lbs_deb_scan("%02d: BSSID %s, RSSI %d, SSID '%s'\n", | 453 | lbs_deb_scan("%02d: BSSID %s, RSSI %d, SSID '%s'\n", |
651 | i++, print_mac(mac, iter->bssid), (s32) iter->rssi, | 454 | i++, print_mac(mac, iter->bssid), iter->rssi, |
652 | escape_essid(iter->ssid, iter->ssid_len)); | 455 | escape_essid(iter->ssid, iter->ssid_len)); |
653 | mutex_unlock(&priv->lock); | 456 | mutex_unlock(&priv->lock); |
654 | #endif | 457 | #endif |
655 | 458 | ||
656 | out2: | 459 | out2: |
657 | priv->last_scanned_channel = 0; | 460 | priv->scan_channel = 0; |
658 | 461 | ||
659 | out: | 462 | out: |
660 | if (priv->connect_status == LBS_CONNECTED) { | 463 | if (priv->connect_status == LBS_CONNECTED) { |
@@ -673,7 +476,15 @@ out: | |||
673 | return ret; | 476 | return ret; |
674 | } | 477 | } |
675 | 478 | ||
479 | void lbs_scan_worker(struct work_struct *work) | ||
480 | { | ||
481 | struct lbs_private *priv = | ||
482 | container_of(work, struct lbs_private, scan_work.work); | ||
676 | 483 | ||
484 | lbs_deb_enter(LBS_DEB_SCAN); | ||
485 | lbs_scan_networks(priv, 0); | ||
486 | lbs_deb_leave(LBS_DEB_SCAN); | ||
487 | } | ||
677 | 488 | ||
678 | 489 | ||
679 | /*********************************************************************/ | 490 | /*********************************************************************/ |
@@ -694,7 +505,7 @@ out: | |||
694 | * @return 0 or -1 | 505 | * @return 0 or -1 |
695 | */ | 506 | */ |
696 | static int lbs_process_bss(struct bss_descriptor *bss, | 507 | static int lbs_process_bss(struct bss_descriptor *bss, |
697 | u8 ** pbeaconinfo, int *bytesleft) | 508 | uint8_t **pbeaconinfo, int *bytesleft) |
698 | { | 509 | { |
699 | struct ieeetypes_fhparamset *pFH; | 510 | struct ieeetypes_fhparamset *pFH; |
700 | struct ieeetypes_dsparamset *pDS; | 511 | struct ieeetypes_dsparamset *pDS; |
@@ -702,9 +513,9 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
702 | struct ieeetypes_ibssparamset *pibss; | 513 | struct ieeetypes_ibssparamset *pibss; |
703 | DECLARE_MAC_BUF(mac); | 514 | DECLARE_MAC_BUF(mac); |
704 | struct ieeetypes_countryinfoset *pcountryinfo; | 515 | struct ieeetypes_countryinfoset *pcountryinfo; |
705 | u8 *pos, *end, *p; | 516 | uint8_t *pos, *end, *p; |
706 | u8 n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; | 517 | uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; |
707 | u16 beaconsize = 0; | 518 | uint16_t beaconsize = 0; |
708 | int ret; | 519 | int ret; |
709 | 520 | ||
710 | lbs_deb_enter(LBS_DEB_SCAN); | 521 | lbs_deb_enter(LBS_DEB_SCAN); |
@@ -776,12 +587,11 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
776 | 587 | ||
777 | /* process variable IE */ | 588 | /* process variable IE */ |
778 | while (pos <= end - 2) { | 589 | while (pos <= end - 2) { |
779 | struct ieee80211_info_element * elem = | 590 | struct ieee80211_info_element * elem = (void *)pos; |
780 | (struct ieee80211_info_element *) pos; | ||
781 | 591 | ||
782 | if (pos + elem->len > end) { | 592 | if (pos + elem->len > end) { |
783 | lbs_deb_scan("process_bss: error in processing IE, " | 593 | lbs_deb_scan("process_bss: error in processing IE, " |
784 | "bytes left < IE length\n"); | 594 | "bytes left < IE length\n"); |
785 | break; | 595 | break; |
786 | } | 596 | } |
787 | 597 | ||
@@ -795,7 +605,7 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
795 | break; | 605 | break; |
796 | 606 | ||
797 | case MFIE_TYPE_RATES: | 607 | case MFIE_TYPE_RATES: |
798 | n_basic_rates = min_t(u8, MAX_RATES, elem->len); | 608 | n_basic_rates = min_t(uint8_t, MAX_RATES, elem->len); |
799 | memcpy(bss->rates, elem->data, n_basic_rates); | 609 | memcpy(bss->rates, elem->data, n_basic_rates); |
800 | got_basic_rates = 1; | 610 | got_basic_rates = 1; |
801 | lbs_deb_scan("got RATES IE\n"); | 611 | lbs_deb_scan("got RATES IE\n"); |
@@ -836,19 +646,16 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
836 | lbs_deb_scan("got COUNTRY IE\n"); | 646 | lbs_deb_scan("got COUNTRY IE\n"); |
837 | if (pcountryinfo->len < sizeof(pcountryinfo->countrycode) | 647 | if (pcountryinfo->len < sizeof(pcountryinfo->countrycode) |
838 | || pcountryinfo->len > 254) { | 648 | || pcountryinfo->len > 254) { |
839 | lbs_deb_scan("process_bss: 11D- Err " | 649 | lbs_deb_scan("process_bss: 11D- Err CountryInfo len %d, min %zd, max 254\n", |
840 | "CountryInfo len %d, min %zd, max 254\n", | 650 | pcountryinfo->len, sizeof(pcountryinfo->countrycode)); |
841 | pcountryinfo->len, | ||
842 | sizeof(pcountryinfo->countrycode)); | ||
843 | ret = -1; | 651 | ret = -1; |
844 | goto done; | 652 | goto done; |
845 | } | 653 | } |
846 | 654 | ||
847 | memcpy(&bss->countryinfo, | 655 | memcpy(&bss->countryinfo, pcountryinfo, pcountryinfo->len + 2); |
848 | pcountryinfo, pcountryinfo->len + 2); | ||
849 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo", | 656 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo", |
850 | (u8 *) pcountryinfo, | 657 | (uint8_t *) pcountryinfo, |
851 | (u32) (pcountryinfo->len + 2)); | 658 | (int) (pcountryinfo->len + 2)); |
852 | break; | 659 | break; |
853 | 660 | ||
854 | case MFIE_TYPE_RATES_EX: | 661 | case MFIE_TYPE_RATES_EX: |
@@ -872,26 +679,19 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
872 | 679 | ||
873 | case MFIE_TYPE_GENERIC: | 680 | case MFIE_TYPE_GENERIC: |
874 | if (elem->len >= 4 && | 681 | if (elem->len >= 4 && |
875 | elem->data[0] == 0x00 && | 682 | elem->data[0] == 0x00 && elem->data[1] == 0x50 && |
876 | elem->data[1] == 0x50 && | 683 | elem->data[2] == 0xf2 && elem->data[3] == 0x01) { |
877 | elem->data[2] == 0xf2 && | 684 | bss->wpa_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN); |
878 | elem->data[3] == 0x01) { | ||
879 | bss->wpa_ie_len = min(elem->len + 2, | ||
880 | MAX_WPA_IE_LEN); | ||
881 | memcpy(bss->wpa_ie, elem, bss->wpa_ie_len); | 685 | memcpy(bss->wpa_ie, elem, bss->wpa_ie_len); |
882 | lbs_deb_scan("got WPA IE\n"); | 686 | lbs_deb_scan("got WPA IE\n"); |
883 | lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, | 687 | lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, elem->len); |
884 | elem->len); | ||
885 | } else if (elem->len >= MARVELL_MESH_IE_LENGTH && | 688 | } else if (elem->len >= MARVELL_MESH_IE_LENGTH && |
886 | elem->data[0] == 0x00 && | 689 | elem->data[0] == 0x00 && elem->data[1] == 0x50 && |
887 | elem->data[1] == 0x50 && | 690 | elem->data[2] == 0x43 && elem->data[3] == 0x04) { |
888 | elem->data[2] == 0x43 && | ||
889 | elem->data[3] == 0x04) { | ||
890 | lbs_deb_scan("got mesh IE\n"); | 691 | lbs_deb_scan("got mesh IE\n"); |
891 | bss->mesh = 1; | 692 | bss->mesh = 1; |
892 | } else { | 693 | } else { |
893 | lbs_deb_scan("got generiec IE: " | 694 | lbs_deb_scan("got generic IE: %02x:%02x:%02x:%02x, len %d\n", |
894 | "%02x:%02x:%02x:%02x, len %d\n", | ||
895 | elem->data[0], elem->data[1], | 695 | elem->data[0], elem->data[1], |
896 | elem->data[2], elem->data[3], | 696 | elem->data[2], elem->data[3], |
897 | elem->len); | 697 | elem->len); |
@@ -903,12 +703,12 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
903 | bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN); | 703 | bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN); |
904 | memcpy(bss->rsn_ie, elem, bss->rsn_ie_len); | 704 | memcpy(bss->rsn_ie, elem, bss->rsn_ie_len); |
905 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE", | 705 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE", |
906 | bss->rsn_ie, elem->len); | 706 | bss->rsn_ie, elem->len); |
907 | break; | 707 | break; |
908 | 708 | ||
909 | default: | 709 | default: |
910 | lbs_deb_scan("got IE 0x%04x, len %d\n", | 710 | lbs_deb_scan("got IE 0x%04x, len %d\n", |
911 | elem->id, elem->len); | 711 | elem->id, elem->len); |
912 | break; | 712 | break; |
913 | } | 713 | } |
914 | 714 | ||
@@ -927,213 +727,6 @@ done: | |||
927 | } | 727 | } |
928 | 728 | ||
929 | /** | 729 | /** |
930 | * @brief This function finds a specific compatible BSSID in the scan list | ||
931 | * | ||
932 | * Used in association code | ||
933 | * | ||
934 | * @param priv A pointer to struct lbs_private | ||
935 | * @param bssid BSSID to find in the scan list | ||
936 | * @param mode Network mode: Infrastructure or IBSS | ||
937 | * | ||
938 | * @return index in BSSID list, or error return code (< 0) | ||
939 | */ | ||
940 | struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv, | ||
941 | u8 * bssid, u8 mode) | ||
942 | { | ||
943 | struct bss_descriptor * iter_bss; | ||
944 | struct bss_descriptor * found_bss = NULL; | ||
945 | |||
946 | lbs_deb_enter(LBS_DEB_SCAN); | ||
947 | |||
948 | if (!bssid) | ||
949 | goto out; | ||
950 | |||
951 | lbs_deb_hex(LBS_DEB_SCAN, "looking for", | ||
952 | bssid, ETH_ALEN); | ||
953 | |||
954 | /* Look through the scan table for a compatible match. The loop will | ||
955 | * continue past a matched bssid that is not compatible in case there | ||
956 | * is an AP with multiple SSIDs assigned to the same BSSID | ||
957 | */ | ||
958 | mutex_lock(&priv->lock); | ||
959 | list_for_each_entry (iter_bss, &priv->network_list, list) { | ||
960 | if (compare_ether_addr(iter_bss->bssid, bssid)) | ||
961 | continue; /* bssid doesn't match */ | ||
962 | switch (mode) { | ||
963 | case IW_MODE_INFRA: | ||
964 | case IW_MODE_ADHOC: | ||
965 | if (!is_network_compatible(priv, iter_bss, mode)) | ||
966 | break; | ||
967 | found_bss = iter_bss; | ||
968 | break; | ||
969 | default: | ||
970 | found_bss = iter_bss; | ||
971 | break; | ||
972 | } | ||
973 | } | ||
974 | mutex_unlock(&priv->lock); | ||
975 | |||
976 | out: | ||
977 | lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss); | ||
978 | return found_bss; | ||
979 | } | ||
980 | |||
981 | /** | ||
982 | * @brief This function finds ssid in ssid list. | ||
983 | * | ||
984 | * Used in association code | ||
985 | * | ||
986 | * @param priv A pointer to struct lbs_private | ||
987 | * @param ssid SSID to find in the list | ||
988 | * @param bssid BSSID to qualify the SSID selection (if provided) | ||
989 | * @param mode Network mode: Infrastructure or IBSS | ||
990 | * | ||
991 | * @return index in BSSID list | ||
992 | */ | ||
993 | struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv, | ||
994 | u8 *ssid, u8 ssid_len, u8 * bssid, u8 mode, | ||
995 | int channel) | ||
996 | { | ||
997 | u8 bestrssi = 0; | ||
998 | struct bss_descriptor * iter_bss = NULL; | ||
999 | struct bss_descriptor * found_bss = NULL; | ||
1000 | struct bss_descriptor * tmp_oldest = NULL; | ||
1001 | |||
1002 | lbs_deb_enter(LBS_DEB_SCAN); | ||
1003 | |||
1004 | mutex_lock(&priv->lock); | ||
1005 | |||
1006 | list_for_each_entry (iter_bss, &priv->network_list, list) { | ||
1007 | if ( !tmp_oldest | ||
1008 | || (iter_bss->last_scanned < tmp_oldest->last_scanned)) | ||
1009 | tmp_oldest = iter_bss; | ||
1010 | |||
1011 | if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len, | ||
1012 | ssid, ssid_len) != 0) | ||
1013 | continue; /* ssid doesn't match */ | ||
1014 | if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0) | ||
1015 | continue; /* bssid doesn't match */ | ||
1016 | if ((channel > 0) && (iter_bss->channel != channel)) | ||
1017 | continue; /* channel doesn't match */ | ||
1018 | |||
1019 | switch (mode) { | ||
1020 | case IW_MODE_INFRA: | ||
1021 | case IW_MODE_ADHOC: | ||
1022 | if (!is_network_compatible(priv, iter_bss, mode)) | ||
1023 | break; | ||
1024 | |||
1025 | if (bssid) { | ||
1026 | /* Found requested BSSID */ | ||
1027 | found_bss = iter_bss; | ||
1028 | goto out; | ||
1029 | } | ||
1030 | |||
1031 | if (SCAN_RSSI(iter_bss->rssi) > bestrssi) { | ||
1032 | bestrssi = SCAN_RSSI(iter_bss->rssi); | ||
1033 | found_bss = iter_bss; | ||
1034 | } | ||
1035 | break; | ||
1036 | case IW_MODE_AUTO: | ||
1037 | default: | ||
1038 | if (SCAN_RSSI(iter_bss->rssi) > bestrssi) { | ||
1039 | bestrssi = SCAN_RSSI(iter_bss->rssi); | ||
1040 | found_bss = iter_bss; | ||
1041 | } | ||
1042 | break; | ||
1043 | } | ||
1044 | } | ||
1045 | |||
1046 | out: | ||
1047 | mutex_unlock(&priv->lock); | ||
1048 | lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss); | ||
1049 | return found_bss; | ||
1050 | } | ||
1051 | |||
1052 | /** | ||
1053 | * @brief This function finds the best SSID in the Scan List | ||
1054 | * | ||
1055 | * Search the scan table for the best SSID that also matches the current | ||
1056 | * adapter network preference (infrastructure or adhoc) | ||
1057 | * | ||
1058 | * @param priv A pointer to struct lbs_private | ||
1059 | * | ||
1060 | * @return index in BSSID list | ||
1061 | */ | ||
1062 | static struct bss_descriptor *lbs_find_best_ssid_in_list( | ||
1063 | struct lbs_private *priv, | ||
1064 | u8 mode) | ||
1065 | { | ||
1066 | u8 bestrssi = 0; | ||
1067 | struct bss_descriptor * iter_bss; | ||
1068 | struct bss_descriptor * best_bss = NULL; | ||
1069 | |||
1070 | lbs_deb_enter(LBS_DEB_SCAN); | ||
1071 | |||
1072 | mutex_lock(&priv->lock); | ||
1073 | |||
1074 | list_for_each_entry (iter_bss, &priv->network_list, list) { | ||
1075 | switch (mode) { | ||
1076 | case IW_MODE_INFRA: | ||
1077 | case IW_MODE_ADHOC: | ||
1078 | if (!is_network_compatible(priv, iter_bss, mode)) | ||
1079 | break; | ||
1080 | if (SCAN_RSSI(iter_bss->rssi) <= bestrssi) | ||
1081 | break; | ||
1082 | bestrssi = SCAN_RSSI(iter_bss->rssi); | ||
1083 | best_bss = iter_bss; | ||
1084 | break; | ||
1085 | case IW_MODE_AUTO: | ||
1086 | default: | ||
1087 | if (SCAN_RSSI(iter_bss->rssi) <= bestrssi) | ||
1088 | break; | ||
1089 | bestrssi = SCAN_RSSI(iter_bss->rssi); | ||
1090 | best_bss = iter_bss; | ||
1091 | break; | ||
1092 | } | ||
1093 | } | ||
1094 | |||
1095 | mutex_unlock(&priv->lock); | ||
1096 | lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss); | ||
1097 | return best_bss; | ||
1098 | } | ||
1099 | |||
1100 | /** | ||
1101 | * @brief Find the AP with specific ssid in the scan list | ||
1102 | * | ||
1103 | * Used from association worker. | ||
1104 | * | ||
1105 | * @param priv A pointer to struct lbs_private structure | ||
1106 | * @param pSSID A pointer to AP's ssid | ||
1107 | * | ||
1108 | * @return 0--success, otherwise--fail | ||
1109 | */ | ||
1110 | int lbs_find_best_network_ssid(struct lbs_private *priv, | ||
1111 | u8 *out_ssid, u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode) | ||
1112 | { | ||
1113 | int ret = -1; | ||
1114 | struct bss_descriptor * found; | ||
1115 | |||
1116 | lbs_deb_enter(LBS_DEB_SCAN); | ||
1117 | |||
1118 | lbs_scan_networks(priv, NULL, 1); | ||
1119 | if (priv->surpriseremoved) | ||
1120 | goto out; | ||
1121 | |||
1122 | found = lbs_find_best_ssid_in_list(priv, preferred_mode); | ||
1123 | if (found && (found->ssid_len > 0)) { | ||
1124 | memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE); | ||
1125 | *out_ssid_len = found->ssid_len; | ||
1126 | *out_mode = found->mode; | ||
1127 | ret = 0; | ||
1128 | } | ||
1129 | |||
1130 | out: | ||
1131 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | ||
1132 | return ret; | ||
1133 | } | ||
1134 | |||
1135 | |||
1136 | /** | ||
1137 | * @brief Send a scan command for all available channels filtered on a spec | 730 | * @brief Send a scan command for all available channels filtered on a spec |
1138 | * | 731 | * |
1139 | * Used in association code and from debugfs | 732 | * Used in association code and from debugfs |
@@ -1141,29 +734,24 @@ out: | |||
1141 | * @param priv A pointer to struct lbs_private structure | 734 | * @param priv A pointer to struct lbs_private structure |
1142 | * @param ssid A pointer to the SSID to scan for | 735 | * @param ssid A pointer to the SSID to scan for |
1143 | * @param ssid_len Length of the SSID | 736 | * @param ssid_len Length of the SSID |
1144 | * @param clear_ssid Should existing scan results with this SSID | ||
1145 | * be cleared? | ||
1146 | * | 737 | * |
1147 | * @return 0-success, otherwise fail | 738 | * @return 0-success, otherwise fail |
1148 | */ | 739 | */ |
1149 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, | 740 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid, |
1150 | u8 *ssid, u8 ssid_len, u8 clear_ssid) | 741 | uint8_t ssid_len) |
1151 | { | 742 | { |
1152 | struct lbs_ioctl_user_scan_cfg scancfg; | ||
1153 | int ret = 0; | 743 | int ret = 0; |
1154 | 744 | ||
1155 | lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s', clear %d", | 745 | lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n", |
1156 | escape_essid(ssid, ssid_len), clear_ssid); | 746 | escape_essid(ssid, ssid_len)); |
1157 | 747 | ||
1158 | if (!ssid_len) | 748 | if (!ssid_len) |
1159 | goto out; | 749 | goto out; |
1160 | 750 | ||
1161 | memset(&scancfg, 0x00, sizeof(scancfg)); | 751 | memcpy(priv->scan_ssid, ssid, ssid_len); |
1162 | memcpy(scancfg.ssid, ssid, ssid_len); | 752 | priv->scan_ssid_len = ssid_len; |
1163 | scancfg.ssid_len = ssid_len; | ||
1164 | scancfg.clear_ssid = clear_ssid; | ||
1165 | 753 | ||
1166 | lbs_scan_networks(priv, &scancfg, 1); | 754 | lbs_scan_networks(priv, 1); |
1167 | if (priv->surpriseremoved) { | 755 | if (priv->surpriseremoved) { |
1168 | ret = -1; | 756 | ret = -1; |
1169 | goto out; | 757 | goto out; |
@@ -1187,17 +775,17 @@ out: | |||
1187 | #define MAX_CUSTOM_LEN 64 | 775 | #define MAX_CUSTOM_LEN 64 |
1188 | 776 | ||
1189 | static inline char *lbs_translate_scan(struct lbs_private *priv, | 777 | static inline char *lbs_translate_scan(struct lbs_private *priv, |
1190 | char *start, char *stop, | 778 | char *start, char *stop, |
1191 | struct bss_descriptor *bss) | 779 | struct bss_descriptor *bss) |
1192 | { | 780 | { |
1193 | struct chan_freq_power *cfp; | 781 | struct chan_freq_power *cfp; |
1194 | char *current_val; /* For rates */ | 782 | char *current_val; /* For rates */ |
1195 | struct iw_event iwe; /* Temporary buffer */ | 783 | struct iw_event iwe; /* Temporary buffer */ |
1196 | int j; | 784 | int j; |
1197 | #define PERFECT_RSSI ((u8)50) | 785 | #define PERFECT_RSSI ((uint8_t)50) |
1198 | #define WORST_RSSI ((u8)0) | 786 | #define WORST_RSSI ((uint8_t)0) |
1199 | #define RSSI_DIFF ((u8)(PERFECT_RSSI - WORST_RSSI)) | 787 | #define RSSI_DIFF ((uint8_t)(PERFECT_RSSI - WORST_RSSI)) |
1200 | u8 rssi; | 788 | uint8_t rssi; |
1201 | 789 | ||
1202 | lbs_deb_enter(LBS_DEB_SCAN); | 790 | lbs_deb_enter(LBS_DEB_SCAN); |
1203 | 791 | ||
@@ -1217,7 +805,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
1217 | /* SSID */ | 805 | /* SSID */ |
1218 | iwe.cmd = SIOCGIWESSID; | 806 | iwe.cmd = SIOCGIWESSID; |
1219 | iwe.u.data.flags = 1; | 807 | iwe.u.data.flags = 1; |
1220 | iwe.u.data.length = min((u32) bss->ssid_len, (u32) IW_ESSID_MAX_SIZE); | 808 | iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE); |
1221 | start = iwe_stream_add_point(start, stop, &iwe, bss->ssid); | 809 | start = iwe_stream_add_point(start, stop, &iwe, bss->ssid); |
1222 | 810 | ||
1223 | /* Mode */ | 811 | /* Mode */ |
@@ -1238,28 +826,26 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
1238 | 826 | ||
1239 | rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE; | 827 | rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE; |
1240 | iwe.u.qual.qual = | 828 | iwe.u.qual.qual = |
1241 | (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) * | 829 | (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) * |
1242 | (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) / | 830 | (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) / |
1243 | (RSSI_DIFF * RSSI_DIFF); | 831 | (RSSI_DIFF * RSSI_DIFF); |
1244 | if (iwe.u.qual.qual > 100) | 832 | if (iwe.u.qual.qual > 100) |
1245 | iwe.u.qual.qual = 100; | 833 | iwe.u.qual.qual = 100; |
1246 | 834 | ||
1247 | if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) { | 835 | if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) { |
1248 | iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; | 836 | iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; |
1249 | } else { | 837 | } else { |
1250 | iwe.u.qual.noise = | 838 | iwe.u.qual.noise = CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]); |
1251 | CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]); | ||
1252 | } | 839 | } |
1253 | 840 | ||
1254 | /* Locally created ad-hoc BSSs won't have beacons if this is the | 841 | /* Locally created ad-hoc BSSs won't have beacons if this is the |
1255 | * only station in the adhoc network; so get signal strength | 842 | * only station in the adhoc network; so get signal strength |
1256 | * from receive statistics. | 843 | * from receive statistics. |
1257 | */ | 844 | */ |
1258 | if ((priv->mode == IW_MODE_ADHOC) | 845 | if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate |
1259 | && priv->adhoccreate | ||
1260 | && !lbs_ssid_cmp(priv->curbssparams.ssid, | 846 | && !lbs_ssid_cmp(priv->curbssparams.ssid, |
1261 | priv->curbssparams.ssid_len, | 847 | priv->curbssparams.ssid_len, |
1262 | bss->ssid, bss->ssid_len)) { | 848 | bss->ssid, bss->ssid_len)) { |
1263 | int snr, nf; | 849 | int snr, nf; |
1264 | snr = priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; | 850 | snr = priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; |
1265 | nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; | 851 | nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; |
@@ -1290,14 +876,13 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
1290 | current_val = iwe_stream_add_value(start, current_val, | 876 | current_val = iwe_stream_add_value(start, current_val, |
1291 | stop, &iwe, IW_EV_PARAM_LEN); | 877 | stop, &iwe, IW_EV_PARAM_LEN); |
1292 | } | 878 | } |
1293 | if ((bss->mode == IW_MODE_ADHOC) | 879 | if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate |
1294 | && !lbs_ssid_cmp(priv->curbssparams.ssid, | 880 | && !lbs_ssid_cmp(priv->curbssparams.ssid, |
1295 | priv->curbssparams.ssid_len, | 881 | priv->curbssparams.ssid_len, |
1296 | bss->ssid, bss->ssid_len) | 882 | bss->ssid, bss->ssid_len)) { |
1297 | && priv->adhoccreate) { | ||
1298 | iwe.u.bitrate.value = 22 * 500000; | 883 | iwe.u.bitrate.value = 22 * 500000; |
1299 | current_val = iwe_stream_add_value(start, current_val, | 884 | current_val = iwe_stream_add_value(start, current_val, |
1300 | stop, &iwe, IW_EV_PARAM_LEN); | 885 | stop, &iwe, IW_EV_PARAM_LEN); |
1301 | } | 886 | } |
1302 | /* Check if we added any event */ | 887 | /* Check if we added any event */ |
1303 | if((current_val - start) > IW_EV_LCP_LEN) | 888 | if((current_val - start) > IW_EV_LCP_LEN) |
@@ -1326,8 +911,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
1326 | char *p = custom; | 911 | char *p = custom; |
1327 | 912 | ||
1328 | iwe.cmd = IWEVCUSTOM; | 913 | iwe.cmd = IWEVCUSTOM; |
1329 | p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), | 914 | p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc"); |
1330 | "mesh-type: olpc"); | ||
1331 | iwe.u.data.length = p - custom; | 915 | iwe.u.data.length = p - custom; |
1332 | if (iwe.u.data.length) | 916 | if (iwe.u.data.length) |
1333 | start = iwe_stream_add_point(start, stop, &iwe, custom); | 917 | start = iwe_stream_add_point(start, stop, &iwe, custom); |
@@ -1350,39 +934,49 @@ out: | |||
1350 | * @return 0 --success, otherwise fail | 934 | * @return 0 --success, otherwise fail |
1351 | */ | 935 | */ |
1352 | int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | 936 | int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, |
1353 | struct iw_param *wrqu, char *extra) | 937 | union iwreq_data *wrqu, char *extra) |
1354 | { | 938 | { |
1355 | struct lbs_private *priv = dev->priv; | 939 | struct lbs_private *priv = dev->priv; |
940 | int ret = 0; | ||
1356 | 941 | ||
1357 | lbs_deb_enter(LBS_DEB_SCAN); | 942 | lbs_deb_enter(LBS_DEB_WEXT); |
1358 | 943 | ||
1359 | if (!netif_running(dev)) | 944 | if (!netif_running(dev)) { |
1360 | return -ENETDOWN; | 945 | ret = -ENETDOWN; |
946 | goto out; | ||
947 | } | ||
1361 | 948 | ||
1362 | /* mac80211 does this: | 949 | /* mac80211 does this: |
1363 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 950 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1364 | if (sdata->type != IEEE80211_IF_TYPE_xxx) | 951 | if (sdata->type != IEEE80211_IF_TYPE_xxx) { |
1365 | return -EOPNOTSUPP; | 952 | ret = -EOPNOTSUPP; |
953 | goto out; | ||
954 | } | ||
955 | */ | ||
1366 | 956 | ||
1367 | if (wrqu->data.length == sizeof(struct iw_scan_req) && | 957 | if (wrqu->data.length == sizeof(struct iw_scan_req) && |
1368 | wrqu->data.flags & IW_SCAN_THIS_ESSID) { | 958 | wrqu->data.flags & IW_SCAN_THIS_ESSID) { |
1369 | req = (struct iw_scan_req *)extra; | 959 | struct iw_scan_req *req = (struct iw_scan_req *)extra; |
1370 | ssid = req->essid; | 960 | priv->scan_ssid_len = req->essid_len; |
1371 | ssid_len = req->essid_len; | 961 | memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len); |
962 | lbs_deb_wext("set_scan, essid '%s'\n", | ||
963 | escape_essid(priv->scan_ssid, priv->scan_ssid_len)); | ||
964 | } else { | ||
965 | priv->scan_ssid_len = 0; | ||
1372 | } | 966 | } |
1373 | */ | ||
1374 | 967 | ||
1375 | if (!delayed_work_pending(&priv->scan_work)) | 968 | if (!delayed_work_pending(&priv->scan_work)) |
1376 | queue_delayed_work(priv->work_thread, &priv->scan_work, | 969 | queue_delayed_work(priv->work_thread, &priv->scan_work, |
1377 | msecs_to_jiffies(50)); | 970 | msecs_to_jiffies(50)); |
1378 | /* set marker that currently a scan is taking place */ | 971 | /* set marker that currently a scan is taking place */ |
1379 | priv->last_scanned_channel = -1; | 972 | priv->scan_channel = -1; |
1380 | 973 | ||
1381 | if (priv->surpriseremoved) | 974 | if (priv->surpriseremoved) |
1382 | return -EIO; | 975 | ret = -EIO; |
1383 | 976 | ||
1384 | lbs_deb_leave(LBS_DEB_SCAN); | 977 | out: |
1385 | return 0; | 978 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); |
979 | return ret; | ||
1386 | } | 980 | } |
1387 | 981 | ||
1388 | 982 | ||
@@ -1397,31 +991,30 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | |||
1397 | * @return 0 --success, otherwise fail | 991 | * @return 0 --success, otherwise fail |
1398 | */ | 992 | */ |
1399 | int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | 993 | int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, |
1400 | struct iw_point *dwrq, char *extra) | 994 | struct iw_point *dwrq, char *extra) |
1401 | { | 995 | { |
1402 | #define SCAN_ITEM_SIZE 128 | 996 | #define SCAN_ITEM_SIZE 128 |
1403 | struct lbs_private *priv = dev->priv; | 997 | struct lbs_private *priv = dev->priv; |
1404 | int err = 0; | 998 | int err = 0; |
1405 | char *ev = extra; | 999 | char *ev = extra; |
1406 | char *stop = ev + dwrq->length; | 1000 | char *stop = ev + dwrq->length; |
1407 | struct bss_descriptor * iter_bss; | 1001 | struct bss_descriptor *iter_bss; |
1408 | struct bss_descriptor * safe; | 1002 | struct bss_descriptor *safe; |
1409 | 1003 | ||
1410 | lbs_deb_enter(LBS_DEB_SCAN); | 1004 | lbs_deb_enter(LBS_DEB_WEXT); |
1411 | 1005 | ||
1412 | /* iwlist should wait until the current scan is finished */ | 1006 | /* iwlist should wait until the current scan is finished */ |
1413 | if (priv->last_scanned_channel) | 1007 | if (priv->scan_channel) |
1414 | return -EAGAIN; | 1008 | return -EAGAIN; |
1415 | 1009 | ||
1416 | /* Update RSSI if current BSS is a locally created ad-hoc BSS */ | 1010 | /* Update RSSI if current BSS is a locally created ad-hoc BSS */ |
1417 | if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) { | 1011 | if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) |
1418 | lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, | 1012 | lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, |
1419 | CMD_OPTION_WAITFORRSP, 0, NULL); | 1013 | CMD_OPTION_WAITFORRSP, 0, NULL); |
1420 | } | ||
1421 | 1014 | ||
1422 | mutex_lock(&priv->lock); | 1015 | mutex_lock(&priv->lock); |
1423 | list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) { | 1016 | list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) { |
1424 | char * next_ev; | 1017 | char *next_ev; |
1425 | unsigned long stale_time; | 1018 | unsigned long stale_time; |
1426 | 1019 | ||
1427 | if (stop - ev < SCAN_ITEM_SIZE) { | 1020 | if (stop - ev < SCAN_ITEM_SIZE) { |
@@ -1436,8 +1029,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1436 | /* Prune old an old scan result */ | 1029 | /* Prune old an old scan result */ |
1437 | stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE; | 1030 | stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE; |
1438 | if (time_after(jiffies, stale_time)) { | 1031 | if (time_after(jiffies, stale_time)) { |
1439 | list_move_tail (&iter_bss->list, | 1032 | list_move_tail(&iter_bss->list, &priv->network_free_list); |
1440 | &priv->network_free_list); | ||
1441 | clear_bss_descriptor(iter_bss); | 1033 | clear_bss_descriptor(iter_bss); |
1442 | continue; | 1034 | continue; |
1443 | } | 1035 | } |
@@ -1453,7 +1045,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1453 | dwrq->length = (ev - extra); | 1045 | dwrq->length = (ev - extra); |
1454 | dwrq->flags = 0; | 1046 | dwrq->flags = 0; |
1455 | 1047 | ||
1456 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", err); | 1048 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err); |
1457 | return err; | 1049 | return err; |
1458 | } | 1050 | } |
1459 | 1051 | ||
@@ -1468,44 +1060,6 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1468 | 1060 | ||
1469 | 1061 | ||
1470 | /** | 1062 | /** |
1471 | * @brief Prepare a scan command to be sent to the firmware | ||
1472 | * | ||
1473 | * Called via lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, ...) | ||
1474 | * from cmd.c | ||
1475 | * | ||
1476 | * Sends a fixed length data part (specifying the BSS type and BSSID filters) | ||
1477 | * as well as a variable number/length of TLVs to the firmware. | ||
1478 | * | ||
1479 | * @param priv A pointer to struct lbs_private structure | ||
1480 | * @param cmd A pointer to cmd_ds_command structure to be sent to | ||
1481 | * firmware with the cmd_DS_801_11_SCAN structure | ||
1482 | * @param pdata_buf Void pointer cast of a lbs_scan_cmd_config struct used | ||
1483 | * to set the fields/TLVs for the command sent to firmware | ||
1484 | * | ||
1485 | * @return 0 or -1 | ||
1486 | */ | ||
1487 | int lbs_cmd_80211_scan(struct lbs_private *priv, | ||
1488 | struct cmd_ds_command *cmd, void *pdata_buf) | ||
1489 | { | ||
1490 | struct cmd_ds_802_11_scan *pscan = &cmd->params.scan; | ||
1491 | struct lbs_scan_cmd_config *pscancfg = pdata_buf; | ||
1492 | |||
1493 | lbs_deb_enter(LBS_DEB_SCAN); | ||
1494 | |||
1495 | /* Set fixed field variables in scan command */ | ||
1496 | pscan->bsstype = pscancfg->bsstype; | ||
1497 | memcpy(pscan->bssid, pscancfg->bssid, ETH_ALEN); | ||
1498 | memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen); | ||
1499 | |||
1500 | /* size is equal to the sizeof(fixed portions) + the TLV len + header */ | ||
1501 | cmd->size = cpu_to_le16(sizeof(pscan->bsstype) + ETH_ALEN | ||
1502 | + pscancfg->tlvbufferlen + S_DS_GEN); | ||
1503 | |||
1504 | lbs_deb_leave(LBS_DEB_SCAN); | ||
1505 | return 0; | ||
1506 | } | ||
1507 | |||
1508 | /** | ||
1509 | * @brief This function handles the command response of scan | 1063 | * @brief This function handles the command response of scan |
1510 | * | 1064 | * |
1511 | * Called from handle_cmd_response() in cmdrespc. | 1065 | * Called from handle_cmd_response() in cmdrespc. |
@@ -1531,13 +1085,14 @@ int lbs_cmd_80211_scan(struct lbs_private *priv, | |||
1531 | * | 1085 | * |
1532 | * @return 0 or -1 | 1086 | * @return 0 or -1 |
1533 | */ | 1087 | */ |
1534 | int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp) | 1088 | static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, |
1089 | struct cmd_header *resp) | ||
1535 | { | 1090 | { |
1536 | struct cmd_ds_802_11_scan_rsp *pscan; | 1091 | struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp; |
1537 | struct bss_descriptor * iter_bss; | 1092 | struct bss_descriptor *iter_bss; |
1538 | struct bss_descriptor * safe; | 1093 | struct bss_descriptor *safe; |
1539 | u8 *pbssinfo; | 1094 | uint8_t *bssinfo; |
1540 | u16 scanrespsize; | 1095 | uint16_t scanrespsize; |
1541 | int bytesleft; | 1096 | int bytesleft; |
1542 | int idx; | 1097 | int idx; |
1543 | int tlvbufsize; | 1098 | int tlvbufsize; |
@@ -1554,48 +1109,45 @@ int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp) | |||
1554 | clear_bss_descriptor(iter_bss); | 1109 | clear_bss_descriptor(iter_bss); |
1555 | } | 1110 | } |
1556 | 1111 | ||
1557 | pscan = &resp->params.scanresp; | 1112 | if (scanresp->nr_sets > MAX_NETWORK_COUNT) { |
1558 | 1113 | lbs_deb_scan("SCAN_RESP: too many scan results (%d, max %d)\n", | |
1559 | if (pscan->nr_sets > MAX_NETWORK_COUNT) { | 1114 | scanresp->nr_sets, MAX_NETWORK_COUNT); |
1560 | lbs_deb_scan( | ||
1561 | "SCAN_RESP: too many scan results (%d, max %d)!!\n", | ||
1562 | pscan->nr_sets, MAX_NETWORK_COUNT); | ||
1563 | ret = -1; | 1115 | ret = -1; |
1564 | goto done; | 1116 | goto done; |
1565 | } | 1117 | } |
1566 | 1118 | ||
1567 | bytesleft = le16_to_cpu(pscan->bssdescriptsize); | 1119 | bytesleft = le16_to_cpu(scanresp->bssdescriptsize); |
1568 | lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft); | 1120 | lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft); |
1569 | 1121 | ||
1570 | scanrespsize = le16_to_cpu(resp->size); | 1122 | scanrespsize = le16_to_cpu(resp->size); |
1571 | lbs_deb_scan("SCAN_RESP: scan results %d\n", pscan->nr_sets); | 1123 | lbs_deb_scan("SCAN_RESP: scan results %d\n", scanresp->nr_sets); |
1572 | 1124 | ||
1573 | pbssinfo = pscan->bssdesc_and_tlvbuffer; | 1125 | bssinfo = scanresp->bssdesc_and_tlvbuffer; |
1574 | 1126 | ||
1575 | /* The size of the TLV buffer is equal to the entire command response | 1127 | /* The size of the TLV buffer is equal to the entire command response |
1576 | * size (scanrespsize) minus the fixed fields (sizeof()'s), the | 1128 | * size (scanrespsize) minus the fixed fields (sizeof()'s), the |
1577 | * BSS Descriptions (bssdescriptsize as bytesLef) and the command | 1129 | * BSS Descriptions (bssdescriptsize as bytesLef) and the command |
1578 | * response header (S_DS_GEN) | 1130 | * response header (S_DS_GEN) |
1579 | */ | 1131 | */ |
1580 | tlvbufsize = scanrespsize - (bytesleft + sizeof(pscan->bssdescriptsize) | 1132 | tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize) |
1581 | + sizeof(pscan->nr_sets) | 1133 | + sizeof(scanresp->nr_sets) |
1582 | + S_DS_GEN); | 1134 | + S_DS_GEN); |
1583 | 1135 | ||
1584 | /* | 1136 | /* |
1585 | * Process each scan response returned (pscan->nr_sets). Save | 1137 | * Process each scan response returned (scanresp->nr_sets). Save |
1586 | * the information in the newbssentry and then insert into the | 1138 | * the information in the newbssentry and then insert into the |
1587 | * driver scan table either as an update to an existing entry | 1139 | * driver scan table either as an update to an existing entry |
1588 | * or as an addition at the end of the table | 1140 | * or as an addition at the end of the table |
1589 | */ | 1141 | */ |
1590 | for (idx = 0; idx < pscan->nr_sets && bytesleft; idx++) { | 1142 | for (idx = 0; idx < scanresp->nr_sets && bytesleft; idx++) { |
1591 | struct bss_descriptor new; | 1143 | struct bss_descriptor new; |
1592 | struct bss_descriptor * found = NULL; | 1144 | struct bss_descriptor *found = NULL; |
1593 | struct bss_descriptor * oldest = NULL; | 1145 | struct bss_descriptor *oldest = NULL; |
1594 | DECLARE_MAC_BUF(mac); | 1146 | DECLARE_MAC_BUF(mac); |
1595 | 1147 | ||
1596 | /* Process the data fields and IEs returned for this BSS */ | 1148 | /* Process the data fields and IEs returned for this BSS */ |
1597 | memset(&new, 0, sizeof (struct bss_descriptor)); | 1149 | memset(&new, 0, sizeof (struct bss_descriptor)); |
1598 | if (lbs_process_bss(&new, &pbssinfo, &bytesleft) != 0) { | 1150 | if (lbs_process_bss(&new, &bssinfo, &bytesleft) != 0) { |
1599 | /* error parsing the scan response, skipped */ | 1151 | /* error parsing the scan response, skipped */ |
1600 | lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n"); | 1152 | lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n"); |
1601 | continue; | 1153 | continue; |
@@ -1630,8 +1182,7 @@ int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp) | |||
1630 | continue; | 1182 | continue; |
1631 | } | 1183 | } |
1632 | 1184 | ||
1633 | lbs_deb_scan("SCAN_RESP: BSSID %s\n", | 1185 | lbs_deb_scan("SCAN_RESP: BSSID %s\n", print_mac(mac, new.bssid)); |
1634 | print_mac(mac, new.bssid)); | ||
1635 | 1186 | ||
1636 | /* Copy the locally created newbssentry to the scan table */ | 1187 | /* Copy the locally created newbssentry to the scan table */ |
1637 | memcpy(found, &new, offsetof(struct bss_descriptor, list)); | 1188 | memcpy(found, &new, offsetof(struct bss_descriptor, list)); |