[PATCH] libertas: make association paths consistent

Dan Williams dcbw at redhat.com
Mon Mar 26 11:54:16 EDT 2007


The BSS to associate with (in either Infrastructure or IBSS join
operations) is now stored in _one_ place in the association request (the
bss member), not two places as before (pattemptedbss and
curbssparams->bssdescriptor).

Association requests are passed to the necessary association functions
to (a) give them access to the bss member and (b) ensure that
association/join/start setup uses settings from the request, not the
current adapter settings (which may not be valid for the requested
settings).

Because the 'bss' member of the association request is used now, the
command return functions from associate and adhoc join/start need access
to the in-progress association request to update curbssparams when
everything is done.  The association worker moves the request from
pending to in-progress for the duration of the association attempt.

As a side-effect, convert the idle on/off functions to use the
association request framework rather than directly manipulating hardware
and settings.

Signed-off-by: Dan Williams <dcbw at redhat.com>

diff --git a/drivers/net/wireless/libertas/11d.c b/drivers/net/wireless/libertas/11d.c
index 2d935b4..9bd8df3 100644
--- a/drivers/net/wireless/libertas/11d.c
+++ b/drivers/net/wireless/libertas/11d.c
@@ -654,7 +654,8 @@ int libertas_ret_802_11d_domain_info(wlan_private * priv,
  *  @param priv    pointer to wlan_private
  *  @return 	   0; -1
  */
-int libertas_parse_dnld_countryinfo_11d(wlan_private * priv)
+int libertas_parse_dnld_countryinfo_11d(wlan_private * priv,
+                                        struct bss_descriptor * bss)
 {
 	int ret;
 	wlan_adapter *adapter = priv->adapter;
@@ -663,8 +664,7 @@ int libertas_parse_dnld_countryinfo_11d(wlan_private * priv)
 	if (priv->adapter->enable11d) {
 		memset(&adapter->parsed_region_chan, 0,
 		       sizeof(struct parsed_region_chan_11d));
-		ret = parse_domain_info_11d(&adapter->pattemptedbssdesc->
-					       countryinfo, 0,
+		ret = parse_domain_info_11d(&bss->countryinfo, 0,
 					       &adapter->parsed_region_chan);
 
 		if (ret == -1) {
diff --git a/drivers/net/wireless/libertas/11d.h b/drivers/net/wireless/libertas/11d.h
index a5b99d4..5cda78c 100644
--- a/drivers/net/wireless/libertas/11d.h
+++ b/drivers/net/wireless/libertas/11d.h
@@ -98,7 +98,9 @@ int libertas_cmd_enable_11d(wlan_private * priv, struct iwreq *wrq);
 int libertas_ret_802_11d_domain_info(wlan_private * priv,
 				 struct cmd_ds_command *resp);
 
-int libertas_parse_dnld_countryinfo_11d(wlan_private * priv);
+struct bss_descriptor;
+int libertas_parse_dnld_countryinfo_11d(wlan_private * priv,
+                                        struct bss_descriptor * bss);
 
 int libertas_create_dnld_countryinfo_11d(wlan_private * priv);
 
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index 43505ee..18b8063 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -13,6 +13,56 @@
 static const u8 bssid_any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
 static const u8 bssid_off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
+/* From ieee80211_module.c */
+const char *escape_essid(const char *essid, u8 essid_len)
+{
+	static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
+	const char *s = essid;
+	char *d = escaped;
+
+	if (ieee80211_is_empty_essid(essid, essid_len))
+		return "";
+
+	essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
+	while (essid_len--) {
+		if (*s == '\0') {
+			*d++ = '\\';
+			*d++ = '0';
+			s++;
+		} else {
+			*d++ = *s++;
+		}
+	}
+	*d = '\0';
+	return escaped;
+}
+
+static void print_assoc_req(const char * extra, struct assoc_request * assoc_req)
+{
+	lbs_deb_assoc(
+	       "#### Association Request: %s\n"
+	       "       flags:      0x%08lX\n"
+	       "       SSID:       '%s'\n"
+	       "       channel:    %d\n"
+	       "       band:       %d\n"
+	       "       mode:       %d\n"
+	       "       BSSID:      " MAC_FMT "\n"
+	       "       WPA:        %d\n"
+	       "       WPA2:       %d\n"
+	       "       WEP status: %d\n"
+	       "       auth:       %d\n"
+	       "       auth_alg:   %d\n"
+	       "       encmode:    %d\n",
+	       extra, assoc_req->flags,
+	       escape_essid(assoc_req->ssid.ssid, assoc_req->ssid.ssidlength),
+	       assoc_req->channel, assoc_req->band, assoc_req->mode,
+	       MAC_ARG(assoc_req->bssid), assoc_req->secinfo.WPAenabled,
+	       assoc_req->secinfo.WPA2enabled, assoc_req->secinfo.WEPstatus,
+	       assoc_req->secinfo.authmode, assoc_req->secinfo.auth1xalg,
+	       assoc_req->secinfo.Encryptionmode);
+}
+
+
 static int assoc_helper_essid(wlan_private *priv,
                               struct assoc_request * assoc_req)
 {
@@ -36,10 +86,8 @@ static int assoc_helper_essid(wlan_private *priv,
 				NULL, wlan802_11infrastructure);
 		if (bss != NULL) {
 			lbs_deb_assoc("SSID found in scan list, associating\n");
-			ret = wlan_associate(priv, bss);
-			if (ret == 0) {
-				memcpy(&assoc_req->bssid, bss->bssid, ETH_ALEN);
-			}
+			memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
+			ret = wlan_associate(priv, assoc_req);
 		} else {
 			lbs_deb_assoc("SSID '%s' not found; cannot associate\n",
 				assoc_req->ssid.ssid);
@@ -55,14 +103,16 @@ static int assoc_helper_essid(wlan_private *priv,
 				wlan802_11ibss);
 		if (bss != NULL) {
 			lbs_deb_assoc("SSID found joining\n");
-			libertas_join_adhoc_network(priv, bss);
+			memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
+			libertas_join_adhoc_network(priv, assoc_req);
 		} else {
 			/* else send START command */
 			lbs_deb_assoc("SSID not found in list, so creating adhoc"
 				" with SSID '%s'\n", assoc_req->ssid.ssid);
-			libertas_start_adhoc_network(priv, &assoc_req->ssid);
+			memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
+				sizeof(struct WLAN_802_11_SSID));
+			libertas_start_adhoc_network(priv, assoc_req);
 		}
-		memcpy(&assoc_req->bssid, &adapter->current_addr, ETH_ALEN);
 	}
 
 	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
@@ -89,13 +139,13 @@ static int assoc_helper_bssid(wlan_private *priv,
 		goto out;
 	}
 
+	memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
 	if (assoc_req->mode == wlan802_11infrastructure) {
-		ret = wlan_associate(priv, bss);
+		ret = wlan_associate(priv, assoc_req);
 		lbs_deb_assoc("ASSOC: wlan_associate(bssid) returned %d\n", ret);
 	} else if (assoc_req->mode == wlan802_11ibss) {
-		libertas_join_adhoc_network(priv, bss);
+		libertas_join_adhoc_network(priv, assoc_req);
 	}
-	memcpy(&assoc_req->ssid, &bss->ssid, sizeof(struct WLAN_802_11_SSID));
 
 out:
 	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
@@ -422,15 +472,15 @@ void libertas_association_worker(struct work_struct *work)
 	lbs_deb_enter(LBS_DEB_ASSOC);
 
 	mutex_lock(&adapter->lock);
-	assoc_req = adapter->assoc_req;
-	adapter->assoc_req = NULL;
+	assoc_req = adapter->pending_assoc_req;
+	adapter->pending_assoc_req = NULL;
+	adapter->in_progress_assoc_req = assoc_req;
 	mutex_unlock(&adapter->lock);
 
 	if (!assoc_req)
 		goto done;
 
-	lbs_deb_assoc("ASSOC: starting new association request: flags = 0x%lX\n",
-		assoc_req->flags);
+	print_assoc_req(__func__, assoc_req);
 
 	/* If 'any' SSID was specified, find an SSID to associate with */
 	if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)
@@ -562,7 +612,9 @@ lbs_deb_assoc("ASSOC(:%d) wpa_keys: ret = %d\n", __LINE__, ret);
 		if (success) {
 			lbs_deb_assoc("ASSOC: association attempt successful. "
 				"Associated to '%s' (" MAC_FMT ")\n",
-				assoc_req->ssid.ssid, MAC_ARG(assoc_req->bssid));
+				escape_essid(adapter->curbssparams.ssid.ssid,
+				             adapter->curbssparams.ssid.ssidlength),
+				MAC_ARG(adapter->curbssparams.bssid));
 			libertas_prepare_and_send_command(priv,
 				cmd_802_11_rssi,
 				0, cmd_option_waitforrsp, 0, NULL);
@@ -581,6 +633,10 @@ out:
 		lbs_deb_assoc("ASSOC: reconfiguration attempt unsuccessful: %d\n",
 			ret);
 	}
+
+	mutex_lock(&adapter->lock);
+	adapter->in_progress_assoc_req = NULL;
+	mutex_unlock(&adapter->lock);
 	kfree(assoc_req);
 
 done:
@@ -595,9 +651,10 @@ struct assoc_request * wlan_get_association_request(wlan_adapter *adapter)
 {
 	struct assoc_request * assoc_req;
 
-	if (!adapter->assoc_req) {
-		adapter->assoc_req = kzalloc(sizeof(struct assoc_request), GFP_KERNEL);
-		if (!adapter->assoc_req) {
+	if (!adapter->pending_assoc_req) {
+		adapter->pending_assoc_req = kzalloc(sizeof(struct assoc_request),
+		                                     GFP_KERNEL);
+		if (!adapter->pending_assoc_req) {
 			lbs_pr_info("Not enough memory to allocate association"
 				" request!\n");
 			return NULL;
@@ -607,15 +664,18 @@ struct assoc_request * wlan_get_association_request(wlan_adapter *adapter)
 	/* Copy current configuration attributes to the association request,
 	 * but don't overwrite any that are already set.
 	 */
-	assoc_req = adapter->assoc_req;
+	assoc_req = adapter->pending_assoc_req;
 	if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
-		memcpy(&assoc_req->ssid, adapter->curbssparams.ssid.ssid,
-			adapter->curbssparams.ssid.ssidlength);
+		memcpy(&assoc_req->ssid, &adapter->curbssparams.ssid,
+		       sizeof(struct WLAN_802_11_SSID));
 	}
 
 	if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
 		assoc_req->channel = adapter->curbssparams.channel;
 
+	if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags))
+		assoc_req->band = adapter->curbssparams.band;
+
 	if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags))
 		assoc_req->mode = adapter->inframode;
 
@@ -656,7 +716,7 @@ struct assoc_request * wlan_get_association_request(wlan_adapter *adapter)
 		assoc_req->wpa_ie_len = adapter->wpa_ie_len;
 	}
 
+	print_assoc_req(__func__, assoc_req);
+
 	return assoc_req;
 }
-
-
diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h
index f9b2ad4..b5eddf8 100644
--- a/drivers/net/wireless/libertas/assoc.h
+++ b/drivers/net/wireless/libertas/assoc.h
@@ -21,9 +21,9 @@ static inline void wlan_postpone_association_work(wlan_private *priv)
 static inline void wlan_cancel_association_work(wlan_private *priv)
 {
 	cancel_delayed_work(&priv->assoc_work);
-	if (priv->adapter->assoc_req) {
-		kfree(priv->adapter->assoc_req);
-		priv->adapter->assoc_req = NULL;
+	if (priv->adapter->pending_assoc_req) {
+		kfree(priv->adapter->pending_assoc_req);
+		priv->adapter->pending_assoc_req = NULL;
 	}
 }
 
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index 7f2d32e..752787b 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -67,27 +67,19 @@ void libertas_mac_event_disconnected(wlan_private * priv)
 	lbs_deb_cmd("Previous SSID=%s, ssid length=%u\n",
 	       adapter->previousssid.ssid, adapter->previousssid.ssidlength);
 
-	/* reset internal flags */
-	adapter->secinfo.WPAenabled = 0;
-	adapter->secinfo.WPA2enabled = 0;
-	adapter->wpa_ie_len = 0;
-	adapter->secinfo.auth1xalg = WLAN_1X_AUTH_ALG_NONE;
-	adapter->secinfo.Encryptionmode = CIPHER_NONE;
-
 	adapter->connect_status = libertas_disconnected;
 
-	/* 
-	 * memorize the previous SSID and BSSID
-	 * it could be used for re-assoc
-	 */
+	/* Save previous SSID and BSSID for possible reassociation */
 	memcpy(&adapter->previousssid,
 	       &adapter->curbssparams.ssid, sizeof(struct WLAN_802_11_SSID));
 	memcpy(adapter->previousbssid,
 	       adapter->curbssparams.bssid, ETH_ALEN);
 
-	/* need to erase the current SSID and BSSID info */
-	adapter->pattemptedbssdesc = NULL;
-	memset(&adapter->curbssparams, 0, sizeof(adapter->curbssparams));
+	/* Clear out associated SSID and BSSID since connection is
+	 * no longer valid.
+	 */
+	memset(&adapter->curbssparams.bssid, 0, ETH_ALEN);
+	memset(&adapter->curbssparams.ssid, 0, sizeof(struct WLAN_802_11_SSID));
 
 	if (adapter->psstate != PS_STATE_FULL_POWER) {
 		/* make firmware to exit PS mode */
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 9f6a8c2..2e5c7c4 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -65,7 +65,6 @@ struct wlan_802_11_security {
 
 /** Current Basic Service Set State Structure */
 struct current_bss_params {
-	struct bss_descriptor bssdescriptor;
 	/** bssid */
 	u8 bssid[ETH_ALEN];
 	/** ssid */
@@ -170,18 +169,20 @@ struct _wlan_private {
 struct assoc_request {
 #define ASSOC_FLAG_SSID			1
 #define ASSOC_FLAG_CHANNEL		2
-#define ASSOC_FLAG_MODE			3
-#define ASSOC_FLAG_BSSID		4
-#define ASSOC_FLAG_WEP_KEYS		5
-#define ASSOC_FLAG_WEP_TX_KEYIDX	6
-#define ASSOC_FLAG_WPA_MCAST_KEY	7
-#define ASSOC_FLAG_WPA_UCAST_KEY	8
-#define ASSOC_FLAG_SECINFO		9
-#define ASSOC_FLAG_WPA_IE		10
+#define ASSOC_FLAG_BAND			3
+#define ASSOC_FLAG_MODE			4
+#define ASSOC_FLAG_BSSID		5
+#define ASSOC_FLAG_WEP_KEYS		6
+#define ASSOC_FLAG_WEP_TX_KEYIDX	7
+#define ASSOC_FLAG_WPA_MCAST_KEY	8
+#define ASSOC_FLAG_WPA_UCAST_KEY	9
+#define ASSOC_FLAG_SECINFO		10
+#define ASSOC_FLAG_WPA_IE		11
 	unsigned long flags;
 
 	struct WLAN_802_11_SSID ssid;
 	u8 channel;
+	u8 band;
 	enum WLAN_802_11_NETWORK_INFRASTRUCTURE mode;
 	u8 bssid[ETH_ALEN];
 
@@ -198,6 +199,9 @@ struct assoc_request {
 	/** WPA Information Elements*/
 	u8 wpa_ie[MAX_WPA_IE_LEN];
 	u8 wpa_ie_len;
+
+	/* BSS to associate with for infrastructure of Ad-Hoc join */
+	struct bss_descriptor bss;
 };
 
 /** Wlan adapter data structure*/
@@ -253,8 +257,6 @@ struct _wlan_adapter {
 
 	enum WLAN_802_11_NETWORK_INFRASTRUCTURE inframode;
 
-	struct bss_descriptor *pattemptedbssdesc;
-
 	struct WLAN_802_11_SSID previousssid;
 	u8 previousbssid[ETH_ALEN];
 
@@ -323,7 +325,8 @@ struct _wlan_adapter {
 	u16 locallisteninterval;
 	u16 nullpktinterval;
 
-	struct assoc_request * assoc_req;
+	struct assoc_request * pending_assoc_req;
+	struct assoc_request * in_progress_assoc_req;
 
 	/** Encryption parameter */
 	struct wlan_802_11_security secinfo;
diff --git a/drivers/net/wireless/libertas/fw.c b/drivers/net/wireless/libertas/fw.c
index afea86e..6c3af1f 100644
--- a/drivers/net/wireless/libertas/fw.c
+++ b/drivers/net/wireless/libertas/fw.c
@@ -188,7 +188,8 @@ static void wlan_init_adapter(wlan_private * priv)
 	adapter->secinfo.Encryptionmode = CIPHER_NONE;
 	adapter->inframode = wlan802_11infrastructure;
 
-	adapter->assoc_req = NULL;
+	adapter->pending_assoc_req = NULL;
+	adapter->in_progress_assoc_req = NULL;
 
 	/* Initialize scan result lists */
 	INIT_LIST_HEAD(&adapter->network_free_list);
@@ -198,7 +199,6 @@ static void wlan_init_adapter(wlan_private * priv)
 			      &adapter->network_free_list);
 	}
 
-	adapter->pattemptedbssdesc = NULL;
 	mutex_init(&adapter->lock);
 
 	adapter->prescan = 1;
diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c
index 8346247..41e0c3f 100644
--- a/drivers/net/wireless/libertas/join.c
+++ b/drivers/net/wireless/libertas/join.c
@@ -7,6 +7,7 @@
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
 #include <linux/wireless.h>
+#include <linux/etherdevice.h>
 
 #include <net/iw_handler.h>
 
@@ -14,6 +15,7 @@
 #include "decl.h"
 #include "join.h"
 #include "dev.h"
+#include "assoc.h"
 
 /**
  *  @brief This function finds out the common rates between rate1 and rate2.
@@ -116,7 +118,7 @@ int libertas_do_adhocstop_ioctl(wlan_private * priv)
  *
  *  @return          0-success, otherwise fail
  */
-int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc)
+int wlan_associate(wlan_private * priv, struct assoc_request * assoc_req)
 {
 	wlan_adapter *adapter = priv->adapter;
 	int ret;
@@ -125,13 +127,13 @@ int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc)
 
 	ret = libertas_prepare_and_send_command(priv, cmd_802_11_authenticate,
 				    0, cmd_option_waitforrsp,
-				    0, pbssdesc->bssid);
+				    0, assoc_req->bss.bssid);
 
 	if (ret)
 		goto done;
 
 	/* set preamble to firmware */
-	if (adapter->capinfo.shortpreamble && pbssdesc->cap.shortpreamble)
+	if (adapter->capinfo.shortpreamble && assoc_req->bss.cap.shortpreamble)
 		adapter->preamble = cmd_type_short_preamble;
 	else 
 		adapter->preamble = cmd_type_long_preamble;
@@ -139,7 +141,7 @@ int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc)
 	libertas_set_radio_control(priv);
 
 	ret = libertas_prepare_and_send_command(priv, cmd_802_11_associate,
-				    0, cmd_option_waitforrsp, 0, pbssdesc);
+				    0, cmd_option_waitforrsp, 0, assoc_req);
 
 done:
 	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
@@ -153,7 +155,7 @@ done:
  *  @param adhocssid    The ssid of the Adhoc Network
  *  @return             0--success, -1--fail
  */
-int libertas_start_adhoc_network(wlan_private * priv, struct WLAN_802_11_SSID *adhocssid)
+int libertas_start_adhoc_network(wlan_private * priv, struct assoc_request * assoc_req)
 {
 	wlan_adapter *adapter = priv->adapter;
 	int ret = 0;
@@ -170,12 +172,11 @@ int libertas_start_adhoc_network(wlan_private * priv, struct WLAN_802_11_SSID *a
 
 	libertas_set_radio_control(priv);
 
-	lbs_deb_join("curbssparams.channel = %d\n",
-	       adapter->curbssparams.channel);
-	lbs_deb_join("curbssparams.band = %d\n", adapter->curbssparams.band);
+	lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel);
+	lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band);
 
 	ret = libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_start,
-				    0, cmd_option_waitforrsp, 0, adhocssid);
+				    0, cmd_option_waitforrsp, 0, assoc_req);
 
 	return ret;
 }
@@ -189,35 +190,34 @@ int libertas_start_adhoc_network(wlan_private * priv, struct WLAN_802_11_SSID *a
  *
  *  @return             0--success, -1--fail
  */
-int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor * pbssdesc)
+int libertas_join_adhoc_network(wlan_private * priv, struct assoc_request * assoc_req)
 {
 	wlan_adapter *adapter = priv->adapter;
+	struct bss_descriptor * bss = &assoc_req->bss;
 	int ret = 0;
 
 	lbs_deb_join("libertas_join_adhoc_network: CurBss.ssid =%s\n",
 	       adapter->curbssparams.ssid.ssid);
 	lbs_deb_join("libertas_join_adhoc_network: CurBss.ssid_len =%u\n",
 	       adapter->curbssparams.ssid.ssidlength);
-	lbs_deb_join("libertas_join_adhoc_network: ssid =%s\n", pbssdesc->ssid.ssid);
-	lbs_deb_join("libertas_join_adhoc_network: ssid len =%u\n",
-	       pbssdesc->ssid.ssidlength);
+	lbs_deb_join("libertas_join_adhoc_network: ssid = '%s'\n",
+		bss->ssid.ssid);
+	lbs_deb_join("libertas_join_adhoc_network: ssid len = %u\n",
+		bss->ssid.ssidlength);
 
 	/* check if the requested SSID is already joined */
 	if (adapter->curbssparams.ssid.ssidlength
-	    && !libertas_SSID_cmp(&pbssdesc->ssid, &adapter->curbssparams.ssid)
-	    && (adapter->curbssparams.bssdescriptor.inframode ==
-		wlan802_11ibss)) {
-
-        lbs_deb_join(
+	    && !libertas_SSID_cmp(&bss->ssid, &adapter->curbssparams.ssid)
+	    && (adapter->inframode == wlan802_11ibss)) {
+		lbs_deb_join(
 		       "ADHOC_J_CMD: New ad-hoc SSID is the same as current, "
 		       "not attempting to re-join");
-
 		return -1;
 	}
 
 	/*Use shortpreamble only when both creator and card supports
 	   short preamble */
-	if (!pbssdesc->cap.shortpreamble || !adapter->capinfo.shortpreamble) {
+	if (!bss->cap.shortpreamble || !adapter->capinfo.shortpreamble) {
 		lbs_deb_join("AdhocJoin: Long preamble\n");
 		adapter->preamble = cmd_type_long_preamble;
 	} else {
@@ -227,15 +227,14 @@ int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor * pbs
 
 	libertas_set_radio_control(priv);
 
-	lbs_deb_join("curbssparams.channel = %d\n",
-	       adapter->curbssparams.channel);
-	lbs_deb_join("curbssparams.band = %c\n", adapter->curbssparams.band);
+	lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
+	lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
 
 	adapter->adhoccreate = 0;
 
 	ret = libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_join,
 				    0, cmd_option_waitforrsp,
-				    OID_802_11_SSID, pbssdesc);
+				    OID_802_11_SSID, assoc_req);
 
 	return ret;
 }
@@ -268,61 +267,65 @@ int libertas_idle_off(wlan_private * priv)
 {
 	wlan_adapter *adapter = priv->adapter;
 	const u8 zeromac[] = { 0, 0, 0, 0, 0, 0 };
+	struct assoc_request * assoc_req;
+	struct bss_descriptor * found = NULL;
 	u8 * prev_bssid = &adapter->previousbssid[0];
 	struct WLAN_802_11_SSID * prev_ssid = &adapter->previousssid;
-	struct bss_descriptor * found;
 	int ret = 0;
+	int use_bssid = 1;
 
 	lbs_deb_enter(LBS_DEB_JOIN);
 
 	if (adapter->connect_status == libertas_disconnected)
 		goto out;
 
-	if (adapter->inframode == wlan802_11ibss) {
-		ret = libertas_prepare_and_send_command(priv,
-					    cmd_802_11_ad_hoc_start,
-					    0,
-					    cmd_option_waitforrsp,
-					    0, prev_ssid);
-		goto out;
-	}
-
-	if (adapter->inframode != wlan802_11infrastructure) {
-		lbs_deb_join("Unknown adapter mode.");
+	if (compare_ether_addr(prev_bssid, zeromac) == 0) {
+		/* No saved BSS to re-join */
 		goto out;
 	}
 
-	if (memcmp(prev_bssid, zeromac, sizeof(zeromac)) == 0)
-		goto out;
-
 	lbs_deb_join("Previous SSID = %s\n", prev_ssid->ssid);
-	lbs_deb_join("Previous BSSID = %02x:%02x:%02x:%02x:%02x:%02x:\n",
-	       prev_bssid[0], prev_bssid[1], prev_bssid[2],
-	       prev_bssid[3], prev_bssid[4], prev_bssid[5]);
+	lbs_deb_join("Previous BSSID = " MAC_FMT "\n", MAC_ARG(prev_bssid));
+
+	if (adapter->inframode == wlan802_11ibss) {
+		use_bssid = 0;
+		goto assoc;
+	}
 
-	found = libertas_find_SSID_in_list(adapter, prev_ssid,
-			prev_bssid, adapter->inframode);
+	/* Try to use the previous BSSID in infrastructure mode */
+	found = libertas_find_SSID_in_list(adapter, prev_ssid, prev_bssid,
+			adapter->inframode);
 	if (found == NULL) {
 		libertas_send_specific_BSSID_scan(priv, prev_bssid, 0);
 		found = libertas_find_SSID_in_list(adapter, prev_ssid,
 				prev_bssid, adapter->inframode);
+		if (found == NULL) {
+			/* Couldn't find the previous BSSID, so just try the
+			 * previous SSID instead.
+			 */
+			use_bssid = 0;
+		}
 	}
 
-	if (found == NULL) {
-		/* If the BSSID could not be found, try just the SSID */
-		found = libertas_find_SSID_in_list(adapter, prev_ssid,
-				NULL, adapter->inframode);
-	}
+assoc:
+	mutex_lock(&adapter->lock);
+	/* Get or create the current association request */
+	assoc_req = wlan_get_association_request(adapter);
+	if (assoc_req) {
+		if (use_bssid) {
+			memcpy(&assoc_req->bssid, &prev_bssid, ETH_ALEN);
+			set_bit(ASSOC_FLAG_BSSID, &assoc_req->flags);
+		}
 
-	if (found == NULL) {
-		libertas_send_specific_SSID_scan(priv, prev_ssid, 0);
-		found = libertas_find_SSID_in_list(adapter, prev_ssid,
-				NULL, adapter->inframode);
+		memcpy(&assoc_req->ssid, &prev_ssid,
+		       sizeof(struct WLAN_802_11_SSID));
+		set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
+		wlan_postpone_association_work(priv);
+	} else {
+		ret = -ENOMEM;
 	}
 
-	if (found) {
-		ret = wlan_associate(priv, found);
-	}
+	mutex_unlock(&adapter->lock);
 
 out:
 	lbs_deb_join("\nwlanidle is off");
@@ -341,23 +344,16 @@ int libertas_idle_on(wlan_private * priv)
 	wlan_adapter *adapter = priv->adapter;
 	int ret = 0;
 
-	if (adapter->connect_status == libertas_connected) {
-		if (adapter->inframode == wlan802_11infrastructure) {
-			lbs_deb_join("Previous SSID = %s\n",
-			       adapter->previousssid.ssid);
-			memmove(&adapter->previousssid,
-				&adapter->curbssparams.ssid,
-				sizeof(struct WLAN_802_11_SSID));
-			libertas_send_deauth(priv);
-
-		} else if (adapter->inframode == wlan802_11ibss) {
-			ret = libertas_stop_adhoc_network(priv);
-		}
+	if (adapter->connect_status != libertas_connected)
+		return 0;
 
+	if (adapter->inframode == wlan802_11infrastructure) {
+		libertas_send_deauth(priv);
+	} else if (adapter->inframode == wlan802_11ibss) {
+		ret = libertas_stop_adhoc_network(priv);
 	}
 
 	lbs_deb_join("\nwlanidle is on");
-
 	return ret;
 }
 
@@ -424,7 +420,8 @@ int libertas_cmd_80211_associate(wlan_private * priv,
 	wlan_adapter *adapter = priv->adapter;
 	struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
 	int ret = 0;
-	struct bss_descriptor *pbssdesc;
+	struct assoc_request * assoc_req = pdata_buf;
+	struct bss_descriptor * bss = &assoc_req->bss;
 	u8 *card_rates;
 	u8 *pos;
 	int card_rates_size;
@@ -437,7 +434,6 @@ int libertas_cmd_80211_associate(wlan_private * priv,
 
 	lbs_deb_enter(LBS_DEB_JOIN);
 
-	pbssdesc = pdata_buf;
 	pos = (u8 *) passo;
 
 	if (!adapter) {
@@ -447,11 +443,7 @@ int libertas_cmd_80211_associate(wlan_private * priv,
 
 	cmd->command = cpu_to_le16(cmd_802_11_associate);
 
-	/* Save so we know which BSS Desc to use in the response handler */
-	adapter->pattemptedbssdesc = pbssdesc;
-
-	memcpy(passo->peerstaaddr,
-	       pbssdesc->bssid, sizeof(passo->peerstaaddr));
+	memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr));
 	pos += sizeof(passo->peerstaaddr);
 
 	/* set the listen interval */
@@ -464,8 +456,8 @@ int libertas_cmd_80211_associate(wlan_private * priv,
 
 	ssid = (struct mrvlietypes_ssidparamset *) pos;
 	ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
-	ssid->header.len = pbssdesc->ssid.ssidlength;
-	memcpy(ssid->ssid, pbssdesc->ssid.ssid, ssid->header.len);
+	ssid->header.len = bss->ssid.ssidlength;
+	memcpy(ssid->ssid, bss->ssid.ssid, ssid->header.len);
 	pos += sizeof(ssid->header) + ssid->header.len;
 	ssid->header.len = cpu_to_le16(ssid->header.len);
 
@@ -473,7 +465,7 @@ int libertas_cmd_80211_associate(wlan_private * priv,
 	phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
 	phy->header.len = sizeof(phy->fh_ds.dsparamset);
 	memcpy(&phy->fh_ds.dsparamset,
-	       &pbssdesc->phyparamset.dsparamset.currentchan,
+	       &bss->phyparamset.dsparamset.currentchan,
 	       sizeof(phy->fh_ds.dsparamset));
 	pos += sizeof(phy->header) + phy->header.len;
 	phy->header.len = cpu_to_le16(phy->header.len);
@@ -487,7 +479,7 @@ int libertas_cmd_80211_associate(wlan_private * priv,
 	rates = (struct mrvlietypes_ratesparamset *) pos;
 	rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
 
-	memcpy(&rates->rates, &pbssdesc->libertas_supported_rates, WLAN_SUPPORTED_RATES);
+	memcpy(&rates->rates, &bss->libertas_supported_rates, WLAN_SUPPORTED_RATES);
 
 	card_rates = libertas_supported_rates;
 	card_rates_size = sizeof(libertas_supported_rates);
@@ -504,12 +496,12 @@ int libertas_cmd_80211_associate(wlan_private * priv,
 	pos += sizeof(rates->header) + rates->header.len;
 	rates->header.len = cpu_to_le16(rates->header.len);
 
-	if (adapter->secinfo.WPAenabled || adapter->secinfo.WPA2enabled) {
+	if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
 		rsn = (struct mrvlietypes_rsnparamset *) pos;
-		rsn->header.type = (u16) adapter->wpa_ie[0];	/* WPA_IE or WPA2_IE */
+		rsn->header.type = (u16) assoc_req->wpa_ie[0];	/* WPA_IE or WPA2_IE */
 		rsn->header.type = cpu_to_le16(rsn->header.type);
-		rsn->header.len = (u16) adapter->wpa_ie[1];
-		memcpy(rsn->rsnie, &adapter->wpa_ie[2], rsn->header.len);
+		rsn->header.len = (u16) assoc_req->wpa_ie[1];
+		memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], rsn->header.len);
 		lbs_dbg_hex("ASSOC_CMD: RSN IE", (u8 *) rsn,
 			sizeof(rsn->header) + rsn->header.len);
 		pos += sizeof(rsn->header) + rsn->header.len;
@@ -518,7 +510,7 @@ int libertas_cmd_80211_associate(wlan_private * priv,
 
 	/* update curbssparams */
 	adapter->curbssparams.channel =
-	    (pbssdesc->phyparamset.dsparamset.currentchan);
+	    (bss->phyparamset.dsparamset.currentchan);
 
 	/* Copy the infra. association rates into Current BSS state structure */
 	memcpy(&adapter->curbssparams.datarates, &rates->rates,
@@ -527,12 +519,12 @@ int libertas_cmd_80211_associate(wlan_private * priv,
 	lbs_deb_join("ASSOC_CMD: rates->header.len = %d\n", rates->header.len);
 
 	/* set IBSS field */
-	if (pbssdesc->inframode == wlan802_11infrastructure) {
+	if (bss->inframode == wlan802_11infrastructure) {
 #define CAPINFO_ESS_MODE 1
 		passo->capinfo.ess = CAPINFO_ESS_MODE;
 	}
 
-	if (libertas_parse_dnld_countryinfo_11d(priv)) {
+	if (libertas_parse_dnld_countryinfo_11d(priv, bss)) {
 		ret = -1;
 		goto done;
 	}
@@ -540,7 +532,7 @@ int libertas_cmd_80211_associate(wlan_private * priv,
 	cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
 
 	/* set the capability info at last */
-	memcpy(&tmpcap, &pbssdesc->cap, sizeof(passo->capinfo));
+	memcpy(&tmpcap, &bss->cap, sizeof(passo->capinfo));
 	tmpcap &= CAPINFO_MASK;
 	lbs_deb_join("ASSOC_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
 	       tmpcap, CAPINFO_MASK);
@@ -553,7 +545,7 @@ done:
 }
 
 int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
-				 struct cmd_ds_command *cmd, void *pssid)
+				 struct cmd_ds_command *cmd, void *pdata_buf)
 {
 	wlan_adapter *adapter = priv->adapter;
 	struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
@@ -561,8 +553,7 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
 	int cmdappendsize = 0;
 	int i;
 	u16 tmpcap;
-	struct bss_descriptor *pbssdesc;
-	struct WLAN_802_11_SSID *ssid = pssid;
+	struct assoc_request * assoc_req = pdata_buf;
 
 	lbs_deb_enter(LBS_DEB_JOIN);
 
@@ -573,9 +564,6 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
 
 	cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_start);
 
-	pbssdesc = &adapter->curbssparams.bssdescriptor;
-	adapter->pattemptedbssdesc = pbssdesc;
-
 	/*
 	 * Fill in the parameters for 2 data structures:
 	 *   1. cmd_ds_802_11_ad_hoc_start command
@@ -589,19 +577,13 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
 	 */
 
 	memset(adhs->SSID, 0, IW_ESSID_MAX_SIZE);
-
-	memcpy(adhs->SSID, ssid->ssid, ssid->ssidlength);
+	memcpy(adhs->SSID, assoc_req->ssid.ssid, assoc_req->ssid.ssidlength);
 
 	lbs_deb_join("ADHOC_S_CMD: SSID = %s\n", adhs->SSID);
 
-	memset(pbssdesc->ssid.ssid, 0, IW_ESSID_MAX_SIZE);
-	memcpy(pbssdesc->ssid.ssid, ssid->ssid, ssid->ssidlength);
-
-	pbssdesc->ssid.ssidlength = ssid->ssidlength;
-
 	/* set the BSS type */
 	adhs->bsstype = cmd_bss_type_ibss;
-	pbssdesc->inframode = wlan802_11ibss;
+	adapter->inframode = wlan802_11ibss;
 	adhs->beaconperiod = adapter->beaconperiod;
 
 	/* set Physical param set */
@@ -611,16 +593,12 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
 	adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
 	adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
 
-	WARN_ON(!adapter->curbssparams.channel);
+	WARN_ON(!assoc_req->channel);
 
 	lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
-	       adapter->curbssparams.channel);
+	       assoc_req->channel);
 
-	pbssdesc->channel = adapter->curbssparams.channel;
-	adhs->phyparamset.dsparamset.currentchan = adapter->curbssparams.channel;
-
-	memcpy(&pbssdesc->phyparamset,
-	       &adhs->phyparamset, sizeof(union ieeetypes_phyparamset));
+	adhs->phyparamset.dsparamset.currentchan = assoc_req->channel;
 
 	/* set IBSS param set */
 #define IBSS_PARA_IE_ID   6
@@ -629,28 +607,22 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
 	adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
 	adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
 	adhs->ssparamset.ibssparamset.atimwindow = adapter->atimwindow;
-	memcpy(&pbssdesc->ssparamset,
-	       &adhs->ssparamset, sizeof(union IEEEtypes_ssparamset));
 
 	/* set capability info */
 	adhs->cap.ess = 0;
 	adhs->cap.ibss = 1;
-	pbssdesc->cap.ibss = 1;
 
 	/* probedelay */
 	adhs->probedelay = cpu_to_le16(cmd_scan_probe_delay_time);
 
 	/* set up privacy in adapter->scantable[i] */
-	if (adapter->secinfo.WEPstatus == wlan802_11WEPenabled) {
-
+	if (assoc_req->secinfo.WEPstatus == wlan802_11WEPenabled) {
 #define AD_HOC_CAP_PRIVACY_ON 1
 		lbs_deb_join("ADHOC_S_CMD: WEPstatus set, privacy to WEP\n");
-		pbssdesc->privacy = wlan802_11privfilter8021xWEP;
 		adhs->cap.privacy = AD_HOC_CAP_PRIVACY_ON;
 	} else {
 		lbs_deb_join("ADHOC_S_CMD: WEPstatus NOT set, Setting "
 		       "privacy to ACCEPT ALL\n");
-		pbssdesc->privacy = wlan802_11privfilteracceptall;
 	}
 
 	memset(adhs->datarate, 0, sizeof(adhs->datarate));
@@ -712,7 +684,8 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
 {
 	wlan_adapter *adapter = priv->adapter;
 	struct cmd_ds_802_11_ad_hoc_join *padhocjoin = &cmd->params.adj;
-	struct bss_descriptor *pbssdesc = pdata_buf;
+	struct assoc_request * assoc_req = pdata_buf;
+	struct bss_descriptor *bss = &assoc_req->bss;
 	int cmdappendsize = 0;
 	int ret = 0;
 	u8 *card_rates;
@@ -722,27 +695,22 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
 
 	lbs_deb_enter(LBS_DEB_JOIN);
 
-	adapter->pattemptedbssdesc = pbssdesc;
-
 	cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_join);
 
 	padhocjoin->bssdescriptor.bsstype = cmd_bss_type_ibss;
 
-	padhocjoin->bssdescriptor.beaconperiod = pbssdesc->beaconperiod;
+	padhocjoin->bssdescriptor.beaconperiod = bss->beaconperiod;
 
-	memcpy(&padhocjoin->bssdescriptor.BSSID,
-	       &pbssdesc->bssid, ETH_ALEN);
-
-	memcpy(&padhocjoin->bssdescriptor.SSID,
-	       &pbssdesc->ssid.ssid, pbssdesc->ssid.ssidlength);
+	memcpy(&padhocjoin->bssdescriptor.BSSID, &bss->bssid, ETH_ALEN);
+	memcpy(&padhocjoin->bssdescriptor.SSID, &bss->ssid.ssid, bss->ssid.ssidlength);
 
 	memcpy(&padhocjoin->bssdescriptor.phyparamset,
-	       &pbssdesc->phyparamset, sizeof(union ieeetypes_phyparamset));
+	       &bss->phyparamset, sizeof(union ieeetypes_phyparamset));
 
 	memcpy(&padhocjoin->bssdescriptor.ssparamset,
-	       &pbssdesc->ssparamset, sizeof(union IEEEtypes_ssparamset));
+	       &bss->ssparamset, sizeof(union IEEEtypes_ssparamset));
 
-	memcpy(&tmpcap, &pbssdesc->cap, sizeof(struct ieeetypes_capinfo));
+	memcpy(&tmpcap, &bss->cap, sizeof(struct ieeetypes_capinfo));
 	tmpcap &= CAPINFO_MASK;
 
 	lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
@@ -751,14 +719,9 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
 	       sizeof(struct ieeetypes_capinfo));
 
 	/* information on BSSID descriptor passed to FW */
-    lbs_deb_join(
-	       "ADHOC_J_CMD: BSSID = %2x-%2x-%2x-%2x-%2x-%2x, SSID = %s\n",
-	       padhocjoin->bssdescriptor.BSSID[0],
-	       padhocjoin->bssdescriptor.BSSID[1],
-	       padhocjoin->bssdescriptor.BSSID[2],
-	       padhocjoin->bssdescriptor.BSSID[3],
-	       padhocjoin->bssdescriptor.BSSID[4],
-	       padhocjoin->bssdescriptor.BSSID[5],
+	lbs_deb_join(
+	       "ADHOC_J_CMD: BSSID = " MAC_FMT ", SSID = '%s'\n",
+	       MAC_ARG(padhocjoin->bssdescriptor.BSSID),
 	       padhocjoin->bssdescriptor.SSID);
 
 	lbs_deb_join("ADHOC_J_CMD: Data Rate = %x\n",
@@ -774,14 +737,14 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
 	/* Copy Data rates from the rates recorded in scan response */
 	memset(padhocjoin->bssdescriptor.datarates, 0,
 	       sizeof(padhocjoin->bssdescriptor.datarates));
-	memcpy(padhocjoin->bssdescriptor.datarates, pbssdesc->datarates,
+	memcpy(padhocjoin->bssdescriptor.datarates, bss->datarates,
 	       min(sizeof(padhocjoin->bssdescriptor.datarates),
-		   sizeof(pbssdesc->datarates)));
+		   sizeof(bss->datarates)));
 
 	card_rates = libertas_supported_rates;
 	card_rates_size = sizeof(libertas_supported_rates);
 
-	adapter->curbssparams.channel = pbssdesc->channel;
+	adapter->curbssparams.channel = bss->channel;
 
 	if (get_common_rates(adapter, padhocjoin->bssdescriptor.datarates,
 			     sizeof(padhocjoin->bssdescriptor.datarates),
@@ -805,9 +768,9 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
 	       adapter->curbssparams.numofrates);
 
 	padhocjoin->bssdescriptor.ssparamset.ibssparamset.atimwindow =
-	    cpu_to_le16(pbssdesc->atimwindow);
+	    cpu_to_le16(bss->atimwindow);
 
-	if (adapter->secinfo.WEPstatus == wlan802_11WEPenabled) {
+	if (assoc_req->secinfo.WEPstatus == wlan802_11WEPenabled) {
 		padhocjoin->bssdescriptor.cap.privacy = AD_HOC_CAP_PRIVACY_ON;
 	}
 
@@ -827,7 +790,7 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
 		}
 	}
 
-	if (libertas_parse_dnld_countryinfo_11d(priv)) {
+	if (libertas_parse_dnld_countryinfo_11d(priv, bss)) {
 		ret = -1;
 		goto done;
 	}
@@ -855,17 +818,23 @@ int libertas_ret_80211_associate(wlan_private * priv,
 	int ret = 0;
 	union iwreq_data wrqu;
 	struct ieeetypes_assocrsp *passocrsp;
-	struct bss_descriptor *pbssdesc;
+	struct bss_descriptor * bss;
 
 	lbs_deb_enter(LBS_DEB_JOIN);
 
+	if (!adapter->in_progress_assoc_req) {
+		lbs_deb_join("ASSOC_RESP: no in-progress association request\n");
+		ret = -1;
+		goto done;
+	}
+	bss = &adapter->in_progress_assoc_req->bss;
+
 	passocrsp = (struct ieeetypes_assocrsp *) & resp->params;
 
 	if (passocrsp->statuscode) {
-
 		libertas_mac_event_disconnected(priv);
 
-        lbs_deb_join("ASSOC_RESP: Association failed, status code = %d\n",
+		lbs_deb_join("ASSOC_RESP: Association failed, status code = %d\n",
 		     passocrsp->statuscode);
 
 		ret = -1;
@@ -878,22 +847,12 @@ int libertas_ret_80211_associate(wlan_private * priv,
 	/* Send a Media Connected event, according to the Spec */
 	adapter->connect_status = libertas_connected;
 
-	/* Set the attempted BSSID Index to current */
-	pbssdesc = adapter->pattemptedbssdesc;
+	lbs_deb_join("ASSOC_RESP: %s\n", bss->ssid.ssid);
 
-	lbs_deb_join("ASSOC_RESP: %s\n", pbssdesc->ssid.ssid);
-
-	/* Set the new SSID to current SSID */
+	/* Update current SSID and BSSID */
 	memcpy(&adapter->curbssparams.ssid,
-	       &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID));
-
-	/* Set the new BSSID (AP's MAC address) to current BSSID */
-	memcpy(adapter->curbssparams.bssid,
-	       pbssdesc->bssid, ETH_ALEN);
-
-	/* Make a copy of current BSSID descriptor */
-	memcpy(&adapter->curbssparams.bssdescriptor,
-	       pbssdesc, sizeof(struct bss_descriptor));
+	       &bss->ssid, sizeof(struct WLAN_802_11_SSID));
+	memcpy(adapter->curbssparams.bssid, bss->bssid, ETH_ALEN);
 
 	lbs_deb_join("ASSOC_RESP: currentpacketfilter is %x\n",
 	       adapter->currentpacketfilter);
@@ -943,30 +902,31 @@ int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
 	u16 result = le16_to_cpu(resp->result);
 	struct cmd_ds_802_11_ad_hoc_result *padhocresult;
 	union iwreq_data wrqu;
-	struct bss_descriptor *pbssdesc;
+	struct bss_descriptor *bss;
 
 	lbs_deb_enter(LBS_DEB_JOIN);
 
 	padhocresult = &resp->params.result;
 
-	lbs_deb_join("ADHOC_S_RESP: size = %d\n", le16_to_cpu(resp->size));
-	lbs_deb_join("ADHOC_S_RESP: command = %x\n", command);
-	lbs_deb_join("ADHOC_S_RESP: result = %x\n", result);
+	lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size));
+	lbs_deb_join("ADHOC_RESP: command = %x\n", command);
+	lbs_deb_join("ADHOC_RESP: result = %x\n", result);
 
-	pbssdesc = adapter->pattemptedbssdesc;
+	if (!adapter->in_progress_assoc_req) {
+		lbs_deb_join("ADHOC_RESP: no in-progress association request\n");
+		ret = -1;
+		goto done;
+	}
+	bss = &adapter->in_progress_assoc_req->bss;
 
 	/*
 	 * Join result code 0 --> SUCCESS
 	 */
 	if (result) {
-		lbs_deb_join("ADHOC_RESP failed\n");
+		lbs_deb_join("ADHOC_RESP: failed\n");
 		if (adapter->connect_status == libertas_connected) {
 			libertas_mac_event_disconnected(priv);
 		}
-
-		memset(&adapter->curbssparams.bssdescriptor,
-		       0x00, sizeof(adapter->curbssparams.bssdescriptor));
-
 		ret = -1;
 		goto done;
 	}
@@ -975,29 +935,22 @@ int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
 	 * Now the join cmd should be successful
 	 * If BSSID has changed use SSID to compare instead of BSSID
 	 */
-	lbs_deb_join("ADHOC_J_RESP  %s\n", pbssdesc->ssid.ssid);
+	lbs_deb_join("ADHOC_RESP: %s\n", bss->ssid.ssid);
 
 	/* Send a Media Connected event, according to the Spec */
 	adapter->connect_status = libertas_connected;
 
 	if (command == cmd_ret_802_11_ad_hoc_start) {
 		/* Update the created network descriptor with the new BSSID */
-		memcpy(pbssdesc->bssid, padhocresult->BSSID, ETH_ALEN);
-	} else {
-
-		/* Make a copy of current BSSID descriptor, only needed for join since
-		 *   the current descriptor is already being used for adhoc start
-		 */
-		memmove(&adapter->curbssparams.bssdescriptor,
-			pbssdesc, sizeof(struct bss_descriptor));
+		memcpy(bss->bssid, padhocresult->BSSID, ETH_ALEN);
 	}
 
 	/* Set the BSSID from the joined/started descriptor */
-	memcpy(&adapter->curbssparams.bssid, pbssdesc->bssid, ETH_ALEN);
+	memcpy(&adapter->curbssparams.bssid, bss->bssid, ETH_ALEN);
 
 	/* Set the new SSID to current SSID */
-	memcpy(&adapter->curbssparams.ssid,
-	       &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID));
+	memcpy(&adapter->curbssparams.ssid, &bss->ssid,
+	       sizeof(struct WLAN_802_11_SSID));
 
 	netif_carrier_on(priv->dev);
 	netif_wake_queue(priv->dev);
diff --git a/drivers/net/wireless/libertas/join.h b/drivers/net/wireless/libertas/join.h
index 98efc6a..9432454 100644
--- a/drivers/net/wireless/libertas/join.h
+++ b/drivers/net/wireless/libertas/join.h
@@ -12,6 +12,7 @@
 #define _WLAN_JOIN_H
 
 #include "defs.h"
+#include "dev.h"
 
 struct cmd_ds_command;
 extern int libertas_cmd_80211_authenticate(wlan_private * priv,
@@ -24,7 +25,7 @@ extern int libertas_cmd_80211_ad_hoc_stop(wlan_private * priv,
 				       struct cmd_ds_command *cmd);
 extern int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
 					struct cmd_ds_command *cmd,
-					void *pssid);
+					void *pdata_buf);
 extern int libertas_cmd_80211_deauthenticate(wlan_private * priv,
 					  struct cmd_ds_command *cmd);
 extern int libertas_cmd_80211_associate(wlan_private * priv,
@@ -50,8 +51,9 @@ struct WLAN_802_11_SSID;
 struct bss_descriptor;
 
 extern int libertas_start_adhoc_network(wlan_private * priv,
-			     struct WLAN_802_11_SSID *adhocssid);
-extern int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor *pbssdesc);
+			     struct assoc_request * assoc_req);
+extern int libertas_join_adhoc_network(wlan_private * priv,
+				struct assoc_request * assoc_req);
 extern int libertas_stop_adhoc_network(wlan_private * priv);
 
 extern int libertas_send_deauthentication(wlan_private * priv);
@@ -59,6 +61,6 @@ extern int libertas_send_deauth(wlan_private * priv);
 
 extern int libertas_do_adhocstop_ioctl(wlan_private * priv);
 
-int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc);
+int wlan_associate(wlan_private * priv, struct assoc_request * assoc_req);
 
 #endif
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 9232566..f5b786f 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -245,24 +245,10 @@ static void wlan_scan_process_results(wlan_private * priv)
 	struct bss_descriptor * iter_bss;
 	int i = 0;
 
-	mutex_lock(&adapter->lock);
-
-	if (adapter->connect_status != libertas_connected)
-		goto debug_print;
-
-	/* try to find the current BSSID in the scan list */
-	list_for_each_entry (iter_bss, &adapter->network_list, list) {
-		if (libertas_SSID_cmp(&iter_bss->ssid, &adapter->curbssparams.ssid))
-			continue;
-		if (memcmp(adapter->curbssparams.bssid, iter_bss->bssid, ETH_ALEN))
-			continue;
-		/* Make a copy of current BSSID descriptor */
-		memcpy(&adapter->curbssparams.bssdescriptor, iter_bss,
-		       sizeof(struct bss_descriptor));
-		break;
-	}
+	if (adapter->connect_status == libertas_connected)
+		return;
 
-debug_print:
+	mutex_lock(&adapter->lock);
 	list_for_each_entry (iter_bss, &adapter->network_list, list) {
 		lbs_deb_scan("Scan:(%02d) " MAC_FMT ", RSSI[%03d], SSID[%s]\n",
 		       i++,
@@ -270,7 +256,6 @@ debug_print:
 		       iter_bss->bssid[3], iter_bss->bssid[4], iter_bss->bssid[5],
 		       (s32) iter_bss->rssi, iter_bss->ssid.ssid);
 	}
-
 	mutex_unlock(&adapter->lock);
 }
 





More information about the libertas-dev mailing list