]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/net/wireless/libertas/assoc.c
[PATCH] libertas: remove adapter->prescan
[mv-sheeva.git] / drivers / net / wireless / libertas / assoc.c
1 /* Copyright (C) 2006, Red Hat, Inc. */
2
3 #include <linux/bitops.h>
4 #include <net/ieee80211.h>
5 #include <linux/etherdevice.h>
6
7 #include "assoc.h"
8 #include "join.h"
9 #include "decl.h"
10 #include "hostcmd.h"
11 #include "host.h"
12
13
14 static const u8 bssid_any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
15 static const u8 bssid_off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
16
17 static void print_assoc_req(const char * extra, struct assoc_request * assoc_req)
18 {
19         lbs_deb_assoc(
20                "#### Association Request: %s\n"
21                "       flags:      0x%08lX\n"
22                "       SSID:       '%s'\n"
23                "       channel:    %d\n"
24                "       band:       %d\n"
25                "       mode:       %d\n"
26                "       BSSID:      " MAC_FMT "\n"
27                "       Encryption:%s%s%s\n"
28                "       auth:       %d\n",
29                extra, assoc_req->flags,
30                escape_essid(assoc_req->ssid, assoc_req->ssid_len),
31                assoc_req->channel, assoc_req->band, assoc_req->mode,
32                MAC_ARG(assoc_req->bssid),
33                assoc_req->secinfo.WPAenabled ? " WPA" : "",
34                assoc_req->secinfo.WPA2enabled ? " WPA2" : "",
35                assoc_req->secinfo.wep_enabled ? " WEP" : "",
36                assoc_req->secinfo.auth_mode);
37 }
38
39
40 static int assoc_helper_essid(wlan_private *priv,
41                               struct assoc_request * assoc_req)
42 {
43         wlan_adapter *adapter = priv->adapter;
44         int ret = 0;
45         struct bss_descriptor * bss;
46         int channel = -1;
47
48         lbs_deb_enter(LBS_DEB_ASSOC);
49
50         /* FIXME: take channel into account when picking SSIDs if a channel
51          * is set.
52          */
53
54         if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
55                 channel = assoc_req->channel;
56
57         lbs_deb_assoc("New SSID requested: '%s'\n",
58                       escape_essid(assoc_req->ssid, assoc_req->ssid_len));
59         if (assoc_req->mode == IW_MODE_INFRA) {
60                 libertas_send_specific_ssid_scan(priv, assoc_req->ssid,
61                         assoc_req->ssid_len, 0);
62
63                 bss = libertas_find_ssid_in_list(adapter, assoc_req->ssid,
64                                 assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel);
65                 if (bss != NULL) {
66                         lbs_deb_assoc("SSID found in scan list, associating\n");
67                         memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
68                         ret = wlan_associate(priv, assoc_req);
69                 } else {
70                         lbs_deb_assoc("SSID not found; cannot associate\n");
71                 }
72         } else if (assoc_req->mode == IW_MODE_ADHOC) {
73                 /* Scan for the network, do not save previous results.  Stale
74                  *   scan data will cause us to join a non-existant adhoc network
75                  */
76                 libertas_send_specific_ssid_scan(priv, assoc_req->ssid,
77                         assoc_req->ssid_len, 1);
78
79                 /* Search for the requested SSID in the scan table */
80                 bss = libertas_find_ssid_in_list(adapter, assoc_req->ssid,
81                                 assoc_req->ssid_len, NULL, IW_MODE_ADHOC, channel);
82                 if (bss != NULL) {
83                         lbs_deb_assoc("SSID found, will join\n");
84                         memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
85                         libertas_join_adhoc_network(priv, assoc_req);
86                 } else {
87                         /* else send START command */
88                         lbs_deb_assoc("SSID not found, creating adhoc network\n");
89                         memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
90                                 IW_ESSID_MAX_SIZE);
91                         assoc_req->bss.ssid_len = assoc_req->ssid_len;
92                         libertas_start_adhoc_network(priv, assoc_req);
93                 }
94         }
95
96         lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
97         return ret;
98 }
99
100
101 static int assoc_helper_bssid(wlan_private *priv,
102                               struct assoc_request * assoc_req)
103 {
104         wlan_adapter *adapter = priv->adapter;
105         int ret = 0;
106         struct bss_descriptor * bss;
107
108         lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID " MAC_FMT,
109                 MAC_ARG(assoc_req->bssid));
110
111         /* Search for index position in list for requested MAC */
112         bss = libertas_find_bssid_in_list(adapter, assoc_req->bssid,
113                             assoc_req->mode);
114         if (bss == NULL) {
115                 lbs_deb_assoc("ASSOC: WAP: BSSID " MAC_FMT " not found, "
116                         "cannot associate.\n", MAC_ARG(assoc_req->bssid));
117                 goto out;
118         }
119
120         memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
121         if (assoc_req->mode == IW_MODE_INFRA) {
122                 ret = wlan_associate(priv, assoc_req);
123                 lbs_deb_assoc("ASSOC: wlan_associate(bssid) returned %d\n", ret);
124         } else if (assoc_req->mode == IW_MODE_ADHOC) {
125                 libertas_join_adhoc_network(priv, assoc_req);
126         }
127
128 out:
129         lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
130         return ret;
131 }
132
133
134 static int assoc_helper_associate(wlan_private *priv,
135                                   struct assoc_request * assoc_req)
136 {
137         int ret = 0, done = 0;
138
139         /* If we're given and 'any' BSSID, try associating based on SSID */
140
141         if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
142                 if (compare_ether_addr(bssid_any, assoc_req->bssid)
143                     && compare_ether_addr(bssid_off, assoc_req->bssid)) {
144                         ret = assoc_helper_bssid(priv, assoc_req);
145                         done = 1;
146                         if (ret) {
147                                 lbs_deb_assoc("ASSOC: bssid: ret = %d\n", ret);
148                         }
149                 }
150         }
151
152         if (!done && test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
153                 ret = assoc_helper_essid(priv, assoc_req);
154                 if (ret) {
155                         lbs_deb_assoc("ASSOC: bssid: ret = %d\n", ret);
156                 }
157         }
158
159         return ret;
160 }
161
162
163 static int assoc_helper_mode(wlan_private *priv,
164                              struct assoc_request * assoc_req)
165 {
166         wlan_adapter *adapter = priv->adapter;
167         int ret = 0;
168
169         lbs_deb_enter(LBS_DEB_ASSOC);
170
171         if (assoc_req->mode == adapter->mode)
172                 goto done;
173
174         if (assoc_req->mode == IW_MODE_INFRA) {
175                 if (adapter->psstate != PS_STATE_FULL_POWER)
176                         libertas_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
177                 adapter->psmode = WLAN802_11POWERMODECAM;
178         }
179
180         adapter->mode = assoc_req->mode;
181         ret = libertas_prepare_and_send_command(priv,
182                                     CMD_802_11_SNMP_MIB,
183                                     0, CMD_OPTION_WAITFORRSP,
184                                     OID_802_11_INFRASTRUCTURE_MODE,
185                 /* Shoot me now */  (void *) (size_t) assoc_req->mode);
186
187 done:
188         lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
189         return ret;
190 }
191
192
193 static int update_channel(wlan_private * priv)
194 {
195         /* the channel in f/w could be out of sync, get the current channel */
196         return libertas_prepare_and_send_command(priv, CMD_802_11_RF_CHANNEL,
197                                     CMD_OPT_802_11_RF_CHANNEL_GET,
198                                     CMD_OPTION_WAITFORRSP, 0, NULL);
199 }
200
201 void libertas_sync_channel(struct work_struct *work)
202 {
203         wlan_private *priv = container_of(work, wlan_private, sync_channel);
204
205         if (update_channel(priv) != 0)
206                 lbs_pr_info("Channel synchronization failed.");
207 }
208
209 static int assoc_helper_channel(wlan_private *priv,
210                                 struct assoc_request * assoc_req)
211 {
212         wlan_adapter *adapter = priv->adapter;
213         int ret = 0;
214
215         lbs_deb_enter(LBS_DEB_ASSOC);
216
217         ret = update_channel(priv);
218         if (ret < 0) {
219                 lbs_deb_assoc("ASSOC: channel: error getting channel.");
220         }
221
222         if (assoc_req->channel == adapter->curbssparams.channel)
223                 goto done;
224
225         lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
226                adapter->curbssparams.channel, assoc_req->channel);
227
228         ret = libertas_prepare_and_send_command(priv, CMD_802_11_RF_CHANNEL,
229                                 CMD_OPT_802_11_RF_CHANNEL_SET,
230                                 CMD_OPTION_WAITFORRSP, 0, &assoc_req->channel);
231         if (ret < 0) {
232                 lbs_deb_assoc("ASSOC: channel: error setting channel.");
233         }
234
235         ret = update_channel(priv);
236         if (ret < 0) {
237                 lbs_deb_assoc("ASSOC: channel: error getting channel.");
238         }
239
240         if (assoc_req->channel != adapter->curbssparams.channel) {
241                 lbs_deb_assoc("ASSOC: channel: failed to update channel to %d",
242                               assoc_req->channel);
243                 goto done;
244         }
245
246         if (   assoc_req->secinfo.wep_enabled
247             &&   (assoc_req->wep_keys[0].len
248                || assoc_req->wep_keys[1].len
249                || assoc_req->wep_keys[2].len
250                || assoc_req->wep_keys[3].len)) {
251                 /* Make sure WEP keys are re-sent to firmware */
252                 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
253         }
254
255         /* Must restart/rejoin adhoc networks after channel change */
256         set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
257
258 done:
259         lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
260         return ret;
261 }
262
263
264 static int assoc_helper_wep_keys(wlan_private *priv,
265                                  struct assoc_request * assoc_req)
266 {
267         wlan_adapter *adapter = priv->adapter;
268         int i;
269         int ret = 0;
270
271         lbs_deb_enter(LBS_DEB_ASSOC);
272
273         /* Set or remove WEP keys */
274         if (   assoc_req->wep_keys[0].len
275             || assoc_req->wep_keys[1].len
276             || assoc_req->wep_keys[2].len
277             || assoc_req->wep_keys[3].len) {
278                 ret = libertas_prepare_and_send_command(priv,
279                                             CMD_802_11_SET_WEP,
280                                             CMD_ACT_ADD,
281                                             CMD_OPTION_WAITFORRSP,
282                                             0, assoc_req);
283         } else {
284                 ret = libertas_prepare_and_send_command(priv,
285                                             CMD_802_11_SET_WEP,
286                                             CMD_ACT_REMOVE,
287                                             CMD_OPTION_WAITFORRSP,
288                                             0, NULL);
289         }
290
291         if (ret)
292                 goto out;
293
294         /* enable/disable the MAC's WEP packet filter */
295         if (assoc_req->secinfo.wep_enabled)
296                 adapter->currentpacketfilter |= CMD_ACT_MAC_WEP_ENABLE;
297         else
298                 adapter->currentpacketfilter &= ~CMD_ACT_MAC_WEP_ENABLE;
299         ret = libertas_set_mac_packet_filter(priv);
300         if (ret)
301                 goto out;
302
303         mutex_lock(&adapter->lock);
304
305         /* Copy WEP keys into adapter wep key fields */
306         for (i = 0; i < 4; i++) {
307                 memcpy(&adapter->wep_keys[i], &assoc_req->wep_keys[i],
308                         sizeof(struct enc_key));
309         }
310         adapter->wep_tx_keyidx = assoc_req->wep_tx_keyidx;
311
312         mutex_unlock(&adapter->lock);
313
314 out:
315         lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
316         return ret;
317 }
318
319 static int assoc_helper_secinfo(wlan_private *priv,
320                                 struct assoc_request * assoc_req)
321 {
322         wlan_adapter *adapter = priv->adapter;
323         int ret = 0;
324         u32 do_wpa;
325         u32 rsn = 0;
326
327         lbs_deb_enter(LBS_DEB_ASSOC);
328
329         memcpy(&adapter->secinfo, &assoc_req->secinfo,
330                 sizeof(struct wlan_802_11_security));
331
332         ret = libertas_set_mac_packet_filter(priv);
333         if (ret)
334                 goto out;
335
336         /* If RSN is already enabled, don't try to enable it again, since
337          * ENABLE_RSN resets internal state machines and will clobber the
338          * 4-way WPA handshake.
339          */
340
341         /* Get RSN enabled/disabled */
342         ret = libertas_prepare_and_send_command(priv,
343                                     CMD_802_11_ENABLE_RSN,
344                                     CMD_ACT_GET,
345                                     CMD_OPTION_WAITFORRSP,
346                                     0, &rsn);
347         if (ret) {
348                 lbs_deb_assoc("Failed to get RSN status: %d", ret);
349                 goto out;
350         }
351
352         /* Don't re-enable RSN if it's already enabled */
353         do_wpa = (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled);
354         if (do_wpa == rsn)
355                 goto out;
356
357         /* Set RSN enabled/disabled */
358         rsn = do_wpa;
359         ret = libertas_prepare_and_send_command(priv,
360                                     CMD_802_11_ENABLE_RSN,
361                                     CMD_ACT_SET,
362                                     CMD_OPTION_WAITFORRSP,
363                                     0, &rsn);
364
365 out:
366         lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
367         return ret;
368 }
369
370
371 static int assoc_helper_wpa_keys(wlan_private *priv,
372                                  struct assoc_request * assoc_req)
373 {
374         int ret = 0;
375
376         lbs_deb_enter(LBS_DEB_ASSOC);
377
378         ret = libertas_prepare_and_send_command(priv,
379                                     CMD_802_11_KEY_MATERIAL,
380                                     CMD_ACT_SET,
381                                     CMD_OPTION_WAITFORRSP,
382                                     0, assoc_req);
383
384         lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
385         return ret;
386 }
387
388
389 static int assoc_helper_wpa_ie(wlan_private *priv,
390                                struct assoc_request * assoc_req)
391 {
392         wlan_adapter *adapter = priv->adapter;
393         int ret = 0;
394
395         lbs_deb_enter(LBS_DEB_ASSOC);
396
397         if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
398                 memcpy(&adapter->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len);
399                 adapter->wpa_ie_len = assoc_req->wpa_ie_len;
400         } else {
401                 memset(&adapter->wpa_ie, 0, MAX_WPA_IE_LEN);
402                 adapter->wpa_ie_len = 0;
403         }
404
405         lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
406         return ret;
407 }
408
409
410 static int should_deauth_infrastructure(wlan_adapter *adapter,
411                                         struct assoc_request * assoc_req)
412 {
413         if (adapter->connect_status != LIBERTAS_CONNECTED)
414                 return 0;
415
416         if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
417                 lbs_deb_assoc("Deauthenticating due to new SSID in "
418                         " configuration request.\n");
419                 return 1;
420         }
421
422         if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
423                 if (adapter->secinfo.auth_mode != assoc_req->secinfo.auth_mode) {
424                         lbs_deb_assoc("Deauthenticating due to updated security "
425                                 "info in configuration request.\n");
426                         return 1;
427                 }
428         }
429
430         if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
431                 lbs_deb_assoc("Deauthenticating due to new BSSID in "
432                         " configuration request.\n");
433                 return 1;
434         }
435
436         if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
437                 lbs_deb_assoc("Deauthenticating due to channel switch.\n");
438                 return 1;
439         }
440
441         /* FIXME: deal with 'auto' mode somehow */
442         if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
443                 if (assoc_req->mode != IW_MODE_INFRA)
444                         return 1;
445         }
446
447         return 0;
448 }
449
450
451 static int should_stop_adhoc(wlan_adapter *adapter,
452                              struct assoc_request * assoc_req)
453 {
454         if (adapter->connect_status != LIBERTAS_CONNECTED)
455                 return 0;
456
457         if (libertas_ssid_cmp(adapter->curbssparams.ssid,
458                               adapter->curbssparams.ssid_len,
459                               assoc_req->ssid, assoc_req->ssid_len) != 0)
460                 return 1;
461
462         /* FIXME: deal with 'auto' mode somehow */
463         if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
464                 if (assoc_req->mode != IW_MODE_ADHOC)
465                         return 1;
466         }
467
468         if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
469                 if (assoc_req->channel != adapter->curbssparams.channel)
470                         return 1;
471         }
472
473         return 0;
474 }
475
476
477 void libertas_association_worker(struct work_struct *work)
478 {
479         wlan_private *priv = container_of(work, wlan_private, assoc_work.work);
480         wlan_adapter *adapter = priv->adapter;
481         struct assoc_request * assoc_req = NULL;
482         int ret = 0;
483         int find_any_ssid = 0;
484
485         lbs_deb_enter(LBS_DEB_ASSOC);
486
487         mutex_lock(&adapter->lock);
488         assoc_req = adapter->pending_assoc_req;
489         adapter->pending_assoc_req = NULL;
490         adapter->in_progress_assoc_req = assoc_req;
491         mutex_unlock(&adapter->lock);
492
493         if (!assoc_req)
494                 goto done;
495
496         print_assoc_req(__func__, assoc_req);
497
498         /* If 'any' SSID was specified, find an SSID to associate with */
499         if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)
500             && !assoc_req->ssid_len)
501                 find_any_ssid = 1;
502
503         /* But don't use 'any' SSID if there's a valid locked BSSID to use */
504         if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
505                 if (compare_ether_addr(assoc_req->bssid, bssid_any)
506                     && compare_ether_addr(assoc_req->bssid, bssid_off))
507                         find_any_ssid = 0;
508         }
509
510         if (find_any_ssid) {
511                 u8 new_mode;
512
513                 ret = libertas_find_best_network_ssid(priv, assoc_req->ssid,
514                                 &assoc_req->ssid_len, assoc_req->mode, &new_mode);
515                 if (ret) {
516                         lbs_deb_assoc("Could not find best network\n");
517                         ret = -ENETUNREACH;
518                         goto out;
519                 }
520
521                 /* Ensure we switch to the mode of the AP */
522                 if (assoc_req->mode == IW_MODE_AUTO) {
523                         set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
524                         assoc_req->mode = new_mode;
525                 }
526         }
527
528         /*
529          * Check if the attributes being changing require deauthentication
530          * from the currently associated infrastructure access point.
531          */
532         if (adapter->mode == IW_MODE_INFRA) {
533                 if (should_deauth_infrastructure(adapter, assoc_req)) {
534                         ret = libertas_send_deauthentication(priv);
535                         if (ret) {
536                                 lbs_deb_assoc("Deauthentication due to new "
537                                         "configuration request failed: %d\n",
538                                         ret);
539                         }
540                 }
541         } else if (adapter->mode == IW_MODE_ADHOC) {
542                 if (should_stop_adhoc(adapter, assoc_req)) {
543                         ret = libertas_stop_adhoc_network(priv);
544                         if (ret) {
545                                 lbs_deb_assoc("Teardown of AdHoc network due to "
546                                         "new configuration request failed: %d\n",
547                                         ret);
548                         }
549
550                 }
551         }
552
553         /* Send the various configuration bits to the firmware */
554         if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
555                 ret = assoc_helper_mode(priv, assoc_req);
556                 if (ret) {
557                         lbs_deb_assoc("ASSOC(:%d) mode: ret = %d\n",
558                                       __LINE__, ret);
559                         goto out;
560                 }
561         }
562
563         if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
564                 ret = assoc_helper_channel(priv, assoc_req);
565                 if (ret) {
566                         lbs_deb_assoc("ASSOC(:%d) channel: ret = %d\n",
567                                       __LINE__, ret);
568                         goto out;
569                 }
570         }
571
572         if (   test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)
573             || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
574                 ret = assoc_helper_wep_keys(priv, assoc_req);
575                 if (ret) {
576                         lbs_deb_assoc("ASSOC(:%d) wep_keys: ret = %d\n",
577                                       __LINE__, ret);
578                         goto out;
579                 }
580         }
581
582         if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
583                 ret = assoc_helper_secinfo(priv, assoc_req);
584                 if (ret) {
585                         lbs_deb_assoc("ASSOC(:%d) secinfo: ret = %d\n",
586                                       __LINE__, ret);
587                         goto out;
588                 }
589         }
590
591         if (test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
592                 ret = assoc_helper_wpa_ie(priv, assoc_req);
593                 if (ret) {
594                         lbs_deb_assoc("ASSOC(:%d) wpa_ie: ret = %d\n",
595                                       __LINE__, ret);
596                         goto out;
597                 }
598         }
599
600         if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)
601             || test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
602                 ret = assoc_helper_wpa_keys(priv, assoc_req);
603                 if (ret) {
604                         lbs_deb_assoc("ASSOC(:%d) wpa_keys: ret = %d\n",
605                                       __LINE__, ret);
606                         goto out;
607                 }
608         }
609
610         /* SSID/BSSID should be the _last_ config option set, because they
611          * trigger the association attempt.
612          */
613         if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)
614             || test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
615                 int success = 1;
616
617                 ret = assoc_helper_associate(priv, assoc_req);
618                 if (ret) {
619                         lbs_deb_assoc("ASSOC: association attempt unsuccessful: %d\n",
620                                 ret);
621                         success = 0;
622                 }
623
624                 if (adapter->connect_status != LIBERTAS_CONNECTED) {
625                         lbs_deb_assoc("ASSOC: assoication attempt unsuccessful, "
626                                 "not connected.\n");
627                         success = 0;
628                 }
629
630                 if (success) {
631                         lbs_deb_assoc("ASSOC: association attempt successful. "
632                                 "Associated to '%s' (" MAC_FMT ")\n",
633                                 escape_essid(adapter->curbssparams.ssid,
634                                              adapter->curbssparams.ssid_len),
635                                 MAC_ARG(adapter->curbssparams.bssid));
636                         libertas_prepare_and_send_command(priv,
637                                 CMD_802_11_RSSI,
638                                 0, CMD_OPTION_WAITFORRSP, 0, NULL);
639
640                         libertas_prepare_and_send_command(priv,
641                                 CMD_802_11_GET_LOG,
642                                 0, CMD_OPTION_WAITFORRSP, 0, NULL);
643                 } else {
644                         ret = -1;
645                 }
646         }
647
648 out:
649         if (ret) {
650                 lbs_deb_assoc("ASSOC: reconfiguration attempt unsuccessful: %d\n",
651                         ret);
652         }
653
654         mutex_lock(&adapter->lock);
655         adapter->in_progress_assoc_req = NULL;
656         mutex_unlock(&adapter->lock);
657         kfree(assoc_req);
658
659 done:
660         lbs_deb_leave(LBS_DEB_ASSOC);
661 }
662
663
664 /*
665  * Caller MUST hold any necessary locks
666  */
667 struct assoc_request * wlan_get_association_request(wlan_adapter *adapter)
668 {
669         struct assoc_request * assoc_req;
670
671         if (!adapter->pending_assoc_req) {
672                 adapter->pending_assoc_req = kzalloc(sizeof(struct assoc_request),
673                                                      GFP_KERNEL);
674                 if (!adapter->pending_assoc_req) {
675                         lbs_pr_info("Not enough memory to allocate association"
676                                 " request!\n");
677                         return NULL;
678                 }
679         }
680
681         /* Copy current configuration attributes to the association request,
682          * but don't overwrite any that are already set.
683          */
684         assoc_req = adapter->pending_assoc_req;
685         if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
686                 memcpy(&assoc_req->ssid, &adapter->curbssparams.ssid,
687                        IW_ESSID_MAX_SIZE);
688                 assoc_req->ssid_len = adapter->curbssparams.ssid_len;
689         }
690
691         if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
692                 assoc_req->channel = adapter->curbssparams.channel;
693
694         if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags))
695                 assoc_req->band = adapter->curbssparams.band;
696
697         if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags))
698                 assoc_req->mode = adapter->mode;
699
700         if (!test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
701                 memcpy(&assoc_req->bssid, adapter->curbssparams.bssid,
702                         ETH_ALEN);
703         }
704
705         if (!test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)) {
706                 int i;
707                 for (i = 0; i < 4; i++) {
708                         memcpy(&assoc_req->wep_keys[i], &adapter->wep_keys[i],
709                                 sizeof(struct enc_key));
710                 }
711         }
712
713         if (!test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags))
714                 assoc_req->wep_tx_keyidx = adapter->wep_tx_keyidx;
715
716         if (!test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
717                 memcpy(&assoc_req->wpa_mcast_key, &adapter->wpa_mcast_key,
718                         sizeof(struct enc_key));
719         }
720
721         if (!test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
722                 memcpy(&assoc_req->wpa_unicast_key, &adapter->wpa_unicast_key,
723                         sizeof(struct enc_key));
724         }
725
726         if (!test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
727                 memcpy(&assoc_req->secinfo, &adapter->secinfo,
728                         sizeof(struct wlan_802_11_security));
729         }
730
731         if (!test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
732                 memcpy(&assoc_req->wpa_ie, &adapter->wpa_ie,
733                         MAX_WPA_IE_LEN);
734                 assoc_req->wpa_ie_len = adapter->wpa_ie_len;
735         }
736
737         print_assoc_req(__func__, assoc_req);
738
739         return assoc_req;
740 }