aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/libertas/assoc.c4
-rw-r--r--drivers/net/wireless/libertas/debugfs.c169
-rw-r--r--drivers/net/wireless/libertas/dev.h2
-rw-r--r--drivers/net/wireless/libertas/scan.c145
-rw-r--r--drivers/net/wireless/libertas/scan.h69
-rw-r--r--drivers/net/wireless/libertas/wext.c3
6 files changed, 76 insertions, 316 deletions
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index 7fe37bedf313..707b7ff592ec 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -38,7 +38,7 @@ static int assoc_helper_essid(struct lbs_private *priv,
38 escape_essid(assoc_req->ssid, assoc_req->ssid_len)); 38 escape_essid(assoc_req->ssid, assoc_req->ssid_len));
39 if (assoc_req->mode == IW_MODE_INFRA) { 39 if (assoc_req->mode == IW_MODE_INFRA) {
40 lbs_send_specific_ssid_scan(priv, assoc_req->ssid, 40 lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
41 assoc_req->ssid_len, 0); 41 assoc_req->ssid_len);
42 42
43 bss = lbs_find_ssid_in_list(priv, assoc_req->ssid, 43 bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
44 assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel); 44 assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel);
@@ -53,7 +53,7 @@ static int assoc_helper_essid(struct lbs_private *priv,
53 * scan data will cause us to join a non-existant adhoc network 53 * scan data will cause us to join a non-existant adhoc network
54 */ 54 */
55 lbs_send_specific_ssid_scan(priv, assoc_req->ssid, 55 lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
56 assoc_req->ssid_len, 1); 56 assoc_req->ssid_len);
57 57
58 /* Search for the requested SSID in the scan table */ 58 /* Search for the requested SSID in the scan table */
59 bss = lbs_find_ssid_in_list(priv, assoc_req->ssid, 59 bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index b600f2439b57..8f88786b036f 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -164,173 +164,6 @@ out_unlock:
164 return ret; 164 return ret;
165} 165}
166 166
167static ssize_t lbs_extscan(struct file *file, const char __user *userbuf,
168 size_t count, loff_t *ppos)
169{
170 struct lbs_private *priv = file->private_data;
171 ssize_t res, buf_size;
172 union iwreq_data wrqu;
173 unsigned long addr = get_zeroed_page(GFP_KERNEL);
174 char *buf = (char *)addr;
175
176 buf_size = min(count, len - 1);
177 if (copy_from_user(buf, userbuf, buf_size)) {
178 res = -EFAULT;
179 goto out_unlock;
180 }
181
182 lbs_send_specific_ssid_scan(priv, buf, strlen(buf)-1, 0);
183
184 memset(&wrqu, 0, sizeof(union iwreq_data));
185 wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
186
187out_unlock:
188 free_page(addr);
189 return count;
190}
191
192static void lbs_parse_bssid(char *buf, size_t count,
193 struct lbs_ioctl_user_scan_cfg *scan_cfg)
194{
195 char *hold;
196 unsigned int mac[ETH_ALEN];
197
198 hold = strstr(buf, "bssid=");
199 if (!hold)
200 return;
201 hold += 6;
202 sscanf(hold, "%02x:%02x:%02x:%02x:%02x:%02x",
203 mac, mac+1, mac+2, mac+3, mac+4, mac+5);
204 memcpy(scan_cfg->bssid, mac, ETH_ALEN);
205}
206
207static void lbs_parse_ssid(char *buf, size_t count,
208 struct lbs_ioctl_user_scan_cfg *scan_cfg)
209{
210 char *hold, *end;
211 ssize_t size;
212
213 hold = strstr(buf, "ssid=");
214 if (!hold)
215 return;
216 hold += 5;
217 end = strchr(hold, ' ');
218 if (!end)
219 end = buf + count - 1;
220
221 size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold));
222 strncpy(scan_cfg->ssid, hold, size);
223
224 return;
225}
226
227static int lbs_parse_clear(char *buf, size_t count, const char *tag)
228{
229 char *hold;
230 int val;
231
232 hold = strstr(buf, tag);
233 if (!hold)
234 return 0;
235 hold += strlen(tag);
236 sscanf(hold, "%d", &val);
237
238 if (val != 0)
239 val = 1;
240
241 return val;
242}
243
244static int lbs_parse_dur(char *buf, size_t count,
245 struct lbs_ioctl_user_scan_cfg *scan_cfg)
246{
247 char *hold;
248 int val;
249
250 hold = strstr(buf, "dur=");
251 if (!hold)
252 return 0;
253 hold += 4;
254 sscanf(hold, "%d", &val);
255
256 return val;
257}
258
259static void lbs_parse_type(char *buf, size_t count,
260 struct lbs_ioctl_user_scan_cfg *scan_cfg)
261{
262 char *hold;
263 int val;
264
265 hold = strstr(buf, "type=");
266 if (!hold)
267 return;
268 hold += 5;
269 sscanf(hold, "%d", &val);
270
271 /* type=1,2 or 3 */
272 if (val < 1 || val > 3)
273 return;
274
275 scan_cfg->bsstype = val;
276
277 return;
278}
279
280static ssize_t lbs_setuserscan(struct file *file,
281 const char __user *userbuf,
282 size_t count, loff_t *ppos)
283{
284 struct lbs_private *priv = file->private_data;
285 ssize_t res, buf_size;
286 struct lbs_ioctl_user_scan_cfg *scan_cfg;
287 union iwreq_data wrqu;
288 int dur;
289 char *buf = (char *)get_zeroed_page(GFP_KERNEL);
290
291 if (!buf)
292 return -ENOMEM;
293
294 buf_size = min(count, len - 1);
295 if (copy_from_user(buf, userbuf, buf_size)) {
296 res = -EFAULT;
297 goto out_buf;
298 }
299
300 scan_cfg = kzalloc(sizeof(struct lbs_ioctl_user_scan_cfg), GFP_KERNEL);
301 if (!scan_cfg) {
302 res = -ENOMEM;
303 goto out_buf;
304 }
305 res = count;
306
307 scan_cfg->bsstype = LBS_SCAN_BSS_TYPE_ANY;
308
309 dur = lbs_parse_dur(buf, count, scan_cfg);
310 lbs_parse_bssid(buf, count, scan_cfg);
311 scan_cfg->clear_bssid = lbs_parse_clear(buf, count, "clear_bssid=");
312 lbs_parse_ssid(buf, count, scan_cfg);
313 scan_cfg->clear_ssid = lbs_parse_clear(buf, count, "clear_ssid=");
314 lbs_parse_type(buf, count, scan_cfg);
315
316 lbs_scan_networks(priv, scan_cfg, 1);
317 wait_event_interruptible(priv->cmd_pending,
318 priv->surpriseremoved || !priv->scan_channel);
319
320 if (priv->surpriseremoved)
321 goto out_scan_cfg;
322
323 memset(&wrqu, 0x00, sizeof(union iwreq_data));
324 wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
325
326 out_scan_cfg:
327 kfree(scan_cfg);
328 out_buf:
329 free_page((unsigned long)buf);
330 return res;
331}
332
333
334/* 167/*
335 * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might 168 * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
336 * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the 169 * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
@@ -857,8 +690,6 @@ static struct lbs_debugfs_files debugfs_files[] = {
857 write_file_dummy), }, 690 write_file_dummy), },
858 { "sleepparams", 0644, FOPS(lbs_sleepparams_read, 691 { "sleepparams", 0644, FOPS(lbs_sleepparams_read,
859 lbs_sleepparams_write), }, 692 lbs_sleepparams_write), },
860 { "extscan", 0600, FOPS(NULL, lbs_extscan), },
861 { "setuserscan", 0600, FOPS(NULL, lbs_setuserscan), },
862}; 693};
863 694
864static struct lbs_debugfs_files debugfs_events_files[] = { 695static struct lbs_debugfs_files debugfs_events_files[] = {
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index fd1fcc748010..ff2c046ca73f 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -149,6 +149,8 @@ struct lbs_private {
149 struct work_struct sync_channel; 149 struct work_struct sync_channel;
150 /* remember which channel was scanned last, != 0 if currently scanning */ 150 /* remember which channel was scanned last, != 0 if currently scanning */
151 int scan_channel; 151 int scan_channel;
152 u8 scan_ssid[IW_ESSID_MAX_SIZE + 1];
153 u8 scan_ssid_len;
152 154
153 /** Hardware access */ 155 /** Hardware access */
154 int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); 156 int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 99f11a56d84e..0598541451d8 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -260,24 +260,12 @@ done:
260 260
261 261
262 262
263
264/*********************************************************************/ 263/*********************************************************************/
265/* */ 264/* */
266/* Main scanning support */ 265/* Main scanning support */
267/* */ 266/* */
268/*********************************************************************/ 267/*********************************************************************/
269 268
270void lbs_scan_worker(struct work_struct *work)
271{
272 struct lbs_private *priv =
273 container_of(work, struct lbs_private, scan_work.work);
274
275 lbs_deb_enter(LBS_DEB_SCAN);
276 lbs_scan_networks(priv, NULL, 0);
277 lbs_deb_leave(LBS_DEB_SCAN);
278}
279
280
281/** 269/**
282 * @brief Create a channel list for the driver to scan based on region info 270 * @brief Create a channel list for the driver to scan based on region info
283 * 271 *
@@ -289,17 +277,11 @@ void lbs_scan_worker(struct work_struct *work)
289 * 277 *
290 * @param priv A pointer to struct lbs_private structure 278 * @param priv A pointer to struct lbs_private structure
291 * @param scanchanlist Output parameter: resulting channel list to scan 279 * @param scanchanlist Output parameter: resulting channel list to scan
292 * @param filteredscan Flag indicating whether or not a BSSID or SSID filter
293 * is being sent in the command to firmware. Used to
294 * increase the number of channels sent in a scan
295 * command and to disable the firmware channel scan
296 * filter.
297 * 280 *
298 * @return void 281 * @return void
299 */ 282 */
300static int lbs_scan_create_channel_list(struct lbs_private *priv, 283static int lbs_scan_create_channel_list(struct lbs_private *priv,
301 struct chanscanparamset *scanchanlist, 284 struct chanscanparamset *scanchanlist)
302 uint8_t filteredscan)
303{ 285{
304 struct region_channel *scanregion; 286 struct region_channel *scanregion;
305 struct chan_freq_power *cfp; 287 struct chan_freq_power *cfp;
@@ -354,9 +336,6 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv,
354 } 336 }
355 337
356 chan->channumber = cfp->channel; 338 chan->channumber = cfp->channel;
357
358 if (filteredscan)
359 chan->chanscanmode.disablechanfilt = 1;
360 } 339 }
361 } 340 }
362 return chanidx; 341 return chanidx;
@@ -370,15 +349,14 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv,
370 * length 06 00 349 * length 06 00
371 * ssid 4d 4e 54 45 53 54 350 * ssid 4d 4e 54 45 53 54
372 */ 351 */
373static int lbs_scan_add_ssid_tlv(uint8_t *tlv, 352static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv)
374 const struct lbs_ioctl_user_scan_cfg *user_cfg)
375{ 353{
376 struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv; 354 struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv;
377 355
378 ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); 356 ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
379 ssid_tlv->header.len = cpu_to_le16(user_cfg->ssid_len); 357 ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len);
380 memcpy(ssid_tlv->ssid, user_cfg->ssid, user_cfg->ssid_len); 358 memcpy(ssid_tlv->ssid, priv->scan_ssid, priv->scan_ssid_len);
381 return sizeof(ssid_tlv->header) + user_cfg->ssid_len; 359 return sizeof(ssid_tlv->header) + priv->scan_ssid_len;
382} 360}
383 361
384 362
@@ -461,8 +439,7 @@ static int lbs_scan_add_rates_tlv(uint8_t *tlv)
461 * for a bunch of channels. 439 * for a bunch of channels.
462 */ 440 */
463static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype, 441static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype,
464 struct chanscanparamset *chan_list, int chan_count, 442 struct chanscanparamset *chan_list, int chan_count)
465 const struct lbs_ioctl_user_scan_cfg *user_cfg)
466{ 443{
467 int ret = -ENOMEM; 444 int ret = -ENOMEM;
468 struct cmd_ds_802_11_scan *scan_cmd; 445 struct cmd_ds_802_11_scan *scan_cmd;
@@ -477,13 +454,13 @@ static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype,
477 goto out; 454 goto out;
478 455
479 tlv = scan_cmd->tlvbuffer; 456 tlv = scan_cmd->tlvbuffer;
480 if (user_cfg) 457 /* TODO: do we need to scan for a specific BSSID?
481 memcpy(scan_cmd->bssid, user_cfg->bssid, ETH_ALEN); 458 memcpy(scan_cmd->bssid, priv->scan_bssid, ETH_ALEN); */
482 scan_cmd->bsstype = bsstype; 459 scan_cmd->bsstype = bsstype;
483 460
484 /* add TLVs */ 461 /* add TLVs */
485 if (user_cfg && user_cfg->ssid_len) 462 if (priv->scan_ssid_len)
486 tlv += lbs_scan_add_ssid_tlv(tlv, user_cfg); 463 tlv += lbs_scan_add_ssid_tlv(priv, tlv);
487 if (chan_list && chan_count) 464 if (chan_list && chan_count)
488 tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count); 465 tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count);
489 tlv += lbs_scan_add_rates_tlv(tlv); 466 tlv += lbs_scan_add_rates_tlv(tlv);
@@ -516,14 +493,11 @@ out:
516 * update the internal driver scan table 493 * update the internal driver scan table
517 * 494 *
518 * @param priv A pointer to struct lbs_private structure 495 * @param priv A pointer to struct lbs_private structure
519 * @param puserscanin Pointer to the input configuration for the requested 496 * @param full_scan Do a full-scan (blocking)
520 * scan.
521 * 497 *
522 * @return 0 or < 0 if error 498 * @return 0 or < 0 if error
523 */ 499 */
524int lbs_scan_networks(struct lbs_private *priv, 500static int lbs_scan_networks(struct lbs_private *priv, int full_scan)
525 const struct lbs_ioctl_user_scan_cfg *user_cfg,
526 int full_scan)
527{ 501{
528 int ret = -ENOMEM; 502 int ret = -ENOMEM;
529 struct chanscanparamset *chan_list; 503 struct chanscanparamset *chan_list;
@@ -531,7 +505,6 @@ int lbs_scan_networks(struct lbs_private *priv,
531 int chan_count; 505 int chan_count;
532 uint8_t bsstype = CMD_BSS_TYPE_ANY; 506 uint8_t bsstype = CMD_BSS_TYPE_ANY;
533 int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD; 507 int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD;
534 int filteredscan = 0;
535 union iwreq_data wrqu; 508 union iwreq_data wrqu;
536#ifdef CONFIG_LIBERTAS_DEBUG 509#ifdef CONFIG_LIBERTAS_DEBUG
537 struct bss_descriptor *iter; 510 struct bss_descriptor *iter;
@@ -547,17 +520,16 @@ int lbs_scan_networks(struct lbs_private *priv,
547 if (full_scan && delayed_work_pending(&priv->scan_work)) 520 if (full_scan && delayed_work_pending(&priv->scan_work))
548 cancel_delayed_work(&priv->scan_work); 521 cancel_delayed_work(&priv->scan_work);
549 522
550 /* Determine same scan parameters */ 523 /* User-specified bsstype or channel list
524 TODO: this can be implemented if some user-space application
525 need the feature. Formerly, it was accessible from debugfs,
526 but then nowhere used.
551 if (user_cfg) { 527 if (user_cfg) {
552 if (user_cfg->bsstype) 528 if (user_cfg->bsstype)
553 bsstype = user_cfg->bsstype; 529 bsstype = user_cfg->bsstype;
554 if (!is_zero_ether_addr(user_cfg->bssid)) { 530 } */
555 numchannels = MRVDRV_MAX_CHANNELS_PER_SCAN; 531
556 filteredscan = 1; 532 lbs_deb_scan("numchannels %d, bsstype %d\n", numchannels, bsstype);
557 }
558 }
559 lbs_deb_scan("numchannels %d, bsstype %d, filteredscan %d\n",
560 numchannels, bsstype, filteredscan);
561 533
562 /* Create list of channels to scan */ 534 /* Create list of channels to scan */
563 chan_list = kzalloc(sizeof(struct chanscanparamset) * 535 chan_list = kzalloc(sizeof(struct chanscanparamset) *
@@ -568,7 +540,7 @@ int lbs_scan_networks(struct lbs_private *priv,
568 } 540 }
569 541
570 /* We want to scan all channels */ 542 /* We want to scan all channels */
571 chan_count = lbs_scan_create_channel_list(priv, chan_list, filteredscan); 543 chan_count = lbs_scan_create_channel_list(priv, chan_list);
572 544
573 netif_stop_queue(priv->dev); 545 netif_stop_queue(priv->dev);
574 netif_carrier_off(priv->dev); 546 netif_carrier_off(priv->dev);
@@ -597,7 +569,7 @@ int lbs_scan_networks(struct lbs_private *priv,
597 lbs_deb_scan("scanning %d of %d channels\n", 569 lbs_deb_scan("scanning %d of %d channels\n",
598 to_scan, chan_count); 570 to_scan, chan_count);
599 ret = lbs_do_scan(priv, bsstype, curr_chans, 571 ret = lbs_do_scan(priv, bsstype, curr_chans,
600 to_scan, user_cfg); 572 to_scan);
601 if (ret) { 573 if (ret) {
602 lbs_pr_err("SCAN_CMD failed\n"); 574 lbs_pr_err("SCAN_CMD failed\n");
603 goto out2; 575 goto out2;
@@ -658,6 +630,17 @@ out:
658 630
659 631
660 632
633void lbs_scan_worker(struct work_struct *work)
634{
635 struct lbs_private *priv =
636 container_of(work, struct lbs_private, scan_work.work);
637
638 lbs_deb_enter(LBS_DEB_SCAN);
639 lbs_scan_networks(priv, 0);
640 lbs_deb_leave(LBS_DEB_SCAN);
641}
642
643
661/*********************************************************************/ 644/*********************************************************************/
662/* */ 645/* */
663/* Result interpretation */ 646/* Result interpretation */
@@ -1068,7 +1051,7 @@ static struct bss_descriptor *lbs_find_best_ssid_in_list(struct lbs_private *pri
1068} 1051}
1069 1052
1070/** 1053/**
1071 * @brief Find the AP with specific ssid in the scan list 1054 * @brief Find the best AP
1072 * 1055 *
1073 * Used from association worker. 1056 * Used from association worker.
1074 * 1057 *
@@ -1086,7 +1069,8 @@ int lbs_find_best_network_ssid(struct lbs_private *priv, uint8_t *out_ssid,
1086 1069
1087 lbs_deb_enter(LBS_DEB_SCAN); 1070 lbs_deb_enter(LBS_DEB_SCAN);
1088 1071
1089 lbs_scan_networks(priv, NULL, 1); 1072 priv->scan_ssid_len = 0;
1073 lbs_scan_networks(priv, 1);
1090 if (priv->surpriseremoved) 1074 if (priv->surpriseremoved)
1091 goto out; 1075 goto out;
1092 1076
@@ -1112,29 +1096,24 @@ out:
1112 * @param priv A pointer to struct lbs_private structure 1096 * @param priv A pointer to struct lbs_private structure
1113 * @param ssid A pointer to the SSID to scan for 1097 * @param ssid A pointer to the SSID to scan for
1114 * @param ssid_len Length of the SSID 1098 * @param ssid_len Length of the SSID
1115 * @param clear_ssid Should existing scan results with this SSID
1116 * be cleared?
1117 * 1099 *
1118 * @return 0-success, otherwise fail 1100 * @return 0-success, otherwise fail
1119 */ 1101 */
1120int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid, 1102int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid,
1121 uint8_t ssid_len, uint8_t clear_ssid) 1103 uint8_t ssid_len)
1122{ 1104{
1123 struct lbs_ioctl_user_scan_cfg scancfg;
1124 int ret = 0; 1105 int ret = 0;
1125 1106
1126 lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s', clear %d", 1107 lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n",
1127 escape_essid(ssid, ssid_len), clear_ssid); 1108 escape_essid(ssid, ssid_len));
1128 1109
1129 if (!ssid_len) 1110 if (!ssid_len)
1130 goto out; 1111 goto out;
1131 1112
1132 memset(&scancfg, 0x00, sizeof(scancfg)); 1113 memcpy(priv->scan_ssid, ssid, ssid_len);
1133 memcpy(scancfg.ssid, ssid, ssid_len); 1114 priv->scan_ssid_len = ssid_len;
1134 scancfg.ssid_len = ssid_len;
1135 scancfg.clear_ssid = clear_ssid;
1136 1115
1137 lbs_scan_networks(priv, &scancfg, 1); 1116 lbs_scan_networks(priv, 1);
1138 if (priv->surpriseremoved) { 1117 if (priv->surpriseremoved) {
1139 ret = -1; 1118 ret = -1;
1140 goto out; 1119 goto out;
@@ -1317,27 +1296,36 @@ out:
1317 * @return 0 --success, otherwise fail 1296 * @return 0 --success, otherwise fail
1318 */ 1297 */
1319int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, 1298int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
1320 struct iw_param *wrqu, char *extra) 1299 union iwreq_data *wrqu, char *extra)
1321{ 1300{
1322 struct lbs_private *priv = dev->priv; 1301 struct lbs_private *priv = dev->priv;
1302 int ret = 0;
1323 1303
1324 lbs_deb_enter(LBS_DEB_SCAN); 1304 lbs_deb_enter(LBS_DEB_WEXT);
1325 1305
1326 if (!netif_running(dev)) 1306 if (!netif_running(dev)) {
1327 return -ENETDOWN; 1307 ret = -ENETDOWN;
1308 goto out;
1309 }
1328 1310
1329 /* mac80211 does this: 1311 /* mac80211 does this:
1330 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1312 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1331 if (sdata->type != IEEE80211_IF_TYPE_xxx) 1313 if (sdata->type != IEEE80211_IF_TYPE_xxx) {
1332 return -EOPNOTSUPP; 1314 ret = -EOPNOTSUPP;
1315 goto out;
1316 }
1317 */
1333 1318
1334 if (wrqu->data.length == sizeof(struct iw_scan_req) && 1319 if (wrqu->data.length == sizeof(struct iw_scan_req) &&
1335 wrqu->data.flags & IW_SCAN_THIS_ESSID) { 1320 wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1336 req = (struct iw_scan_req *)extra; 1321 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1337 ssid = req->essid; 1322 priv->scan_ssid_len = req->essid_len;
1338 ssid_len = req->essid_len; 1323 memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len);
1324 lbs_deb_wext("set_scan, essid '%s'\n",
1325 escape_essid(priv->scan_ssid, priv->scan_ssid_len));
1326 } else {
1327 priv->scan_ssid_len = 0;
1339 } 1328 }
1340 */
1341 1329
1342 if (!delayed_work_pending(&priv->scan_work)) 1330 if (!delayed_work_pending(&priv->scan_work))
1343 queue_delayed_work(priv->work_thread, &priv->scan_work, 1331 queue_delayed_work(priv->work_thread, &priv->scan_work,
@@ -1346,10 +1334,11 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
1346 priv->scan_channel = -1; 1334 priv->scan_channel = -1;
1347 1335
1348 if (priv->surpriseremoved) 1336 if (priv->surpriseremoved)
1349 return -EIO; 1337 ret = -EIO;
1350 1338
1351 lbs_deb_leave(LBS_DEB_SCAN); 1339out:
1352 return 0; 1340 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1341 return ret;
1353} 1342}
1354 1343
1355 1344
@@ -1374,7 +1363,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
1374 struct bss_descriptor *iter_bss; 1363 struct bss_descriptor *iter_bss;
1375 struct bss_descriptor *safe; 1364 struct bss_descriptor *safe;
1376 1365
1377 lbs_deb_enter(LBS_DEB_SCAN); 1366 lbs_deb_enter(LBS_DEB_WEXT);
1378 1367
1379 /* iwlist should wait until the current scan is finished */ 1368 /* iwlist should wait until the current scan is finished */
1380 if (priv->scan_channel) 1369 if (priv->scan_channel)
@@ -1418,7 +1407,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
1418 dwrq->length = (ev - extra); 1407 dwrq->length = (ev - extra);
1419 dwrq->flags = 0; 1408 dwrq->flags = 0;
1420 1409
1421 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", err); 1410 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
1422 return err; 1411 return err;
1423} 1412}
1424 1413
diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h
index 10d1196acf78..c50c8b74714b 100644
--- a/drivers/net/wireless/libertas/scan.h
+++ b/drivers/net/wireless/libertas/scan.h
@@ -12,8 +12,6 @@
12 12
13/** 13/**
14 * @brief Maximum number of channels that can be sent in a setuserscan ioctl 14 * @brief Maximum number of channels that can be sent in a setuserscan ioctl
15 *
16 * @sa lbs_ioctl_user_scan_cfg
17 */ 15 */
18#define LBS_IOCTL_USER_SCAN_CHAN_MAX 50 16#define LBS_IOCTL_USER_SCAN_CHAN_MAX 50
19 17
@@ -27,60 +25,6 @@
27#define LBS_SCAN_BSS_TYPE_ANY 3 25#define LBS_SCAN_BSS_TYPE_ANY 3
28 26
29/** 27/**
30 * @brief IOCTL channel sub-structure sent in lbs_ioctl_user_scan_cfg
31 *
32 * Multiple instances of this structure are included in the IOCTL command
33 * to configure a instance of a scan on the specific channel.
34 */
35struct lbs_ioctl_user_scan_chan {
36 u8 channumber; //!< channel Number to scan
37 u8 radiotype; //!< Radio type: 'B/G' band = 0, 'A' band = 1
38 u8 scantype; //!< Scan type: Active = 0, Passive = 1
39 u16 scantime; //!< Scan duration in milliseconds; if 0 default used
40};
41
42/**
43 * @brief IOCTL input structure to configure an immediate scan cmd to firmware
44 *
45 * Used in the setuserscan (LBS_SET_USER_SCAN) private ioctl. Specifies
46 * a number of parameters to be used in general for the scan as well
47 * as a channel list (lbs_ioctl_user_scan_chan) for each scan period
48 * desired.
49 *
50 * @sa lbs_set_user_scan_ioctl
51 */
52struct lbs_ioctl_user_scan_cfg {
53 /**
54 * @brief BSS type to be sent in the firmware command
55 *
56 * Field can be used to restrict the types of networks returned in the
57 * scan. valid settings are:
58 *
59 * - LBS_SCAN_BSS_TYPE_BSS (infrastructure)
60 * - LBS_SCAN_BSS_TYPE_IBSS (adhoc)
61 * - LBS_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
62 */
63 u8 bsstype;
64
65 /**
66 * @brief BSSID filter sent in the firmware command to limit the results
67 */
68 u8 bssid[ETH_ALEN];
69
70 /* Clear existing scan results matching this BSSID */
71 u8 clear_bssid;
72
73 /**
74 * @brief SSID filter sent in the firmware command to limit the results
75 */
76 char ssid[IW_ESSID_MAX_SIZE];
77 u8 ssid_len;
78
79 /* Clear existing scan results matching this SSID */
80 u8 clear_ssid;
81};
82
83/**
84 * @brief Structure used to store information for each beacon/probe response 28 * @brief Structure used to store information for each beacon/probe response
85 */ 29 */
86struct bss_descriptor { 30struct bss_descriptor {
@@ -136,21 +80,12 @@ int lbs_find_best_network_ssid(struct lbs_private *priv, u8 *out_ssid,
136 u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode); 80 u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode);
137 81
138int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, 82int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
139 u8 ssid_len, u8 clear_ssid); 83 u8 ssid_len);
140
141int lbs_scan_networks(struct lbs_private *priv,
142 const struct lbs_ioctl_user_scan_cfg *puserscanin,
143 int full_scan);
144
145struct ifreq;
146 84
147struct iw_point;
148struct iw_param;
149struct iw_request_info;
150int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, 85int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
151 struct iw_point *dwrq, char *extra); 86 struct iw_point *dwrq, char *extra);
152int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, 87int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
153 struct iw_param *vwrq, char *extra); 88 union iwreq_data *wrqu, char *extra);
154 89
155void lbs_scan_worker(struct work_struct *work); 90void lbs_scan_worker(struct work_struct *work);
156 91
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index e8bfc26b10a4..cded4bb69164 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -579,6 +579,9 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
579 range->num_bitrates); 579 range->num_bitrates);
580 580
581 range->num_frequency = 0; 581 range->num_frequency = 0;
582
583 range->scan_capa = IW_SCAN_CAPA_ESSID;
584
582 if (priv->enable11d && 585 if (priv->enable11d &&
583 (priv->connect_status == LBS_CONNECTED || 586 (priv->connect_status == LBS_CONNECTED ||
584 priv->mesh_connect_status == LBS_CONNECTED)) { 587 priv->mesh_connect_status == LBS_CONNECTED)) {