summary refs log tree commit diff
path: root/drivers/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/libertas/assoc.c81
-rw-r--r--drivers/net/wireless/libertas/dev.h1
-rw-r--r--drivers/net/wireless/libertas/fw.c2
-rw-r--r--drivers/net/wireless/libertas/join.c13
-rw-r--r--drivers/net/wireless/libertas/wext.c182
5 files changed, 117 insertions, 162 deletions
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index 4bc128fa5848..3f2dfaf879c5 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -22,6 +22,10 @@ static int assoc_helper_essid(wlan_private *priv,
 
 	lbs_deb_enter(LBS_DEB_ASSOC);
 
+	/* FIXME: take channel into account when picking SSIDs if a channel
+	 * is set.
+	 */
+
 	lbs_deb_assoc("New SSID requested: %s\n", assoc_req->ssid.ssid);
 	if (assoc_req->mode == IW_MODE_INFRA) {
 		if (adapter->prescan) {
@@ -158,6 +162,69 @@ done:
 }
 
 
+static int update_channel(wlan_private * priv)
+{
+	/* the channel in f/w could be out of sync, get the current channel */
+	return libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
+				    cmd_opt_802_11_rf_channel_get,
+				    cmd_option_waitforrsp, 0, NULL);
+}
+
+static int assoc_helper_channel(wlan_private *priv,
+                                struct assoc_request * assoc_req)
+{
+	wlan_adapter *adapter = priv->adapter;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_ASSOC);
+
+	ret = update_channel(priv);
+	if (ret < 0) {
+		lbs_deb_assoc("ASSOC: channel: error getting channel.");
+	}
+
+	if (assoc_req->channel == adapter->curbssparams.channel)
+		goto done;
+
+	lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
+	       adapter->curbssparams.channel, assoc_req->channel);
+
+	ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
+				cmd_opt_802_11_rf_channel_set,
+				cmd_option_waitforrsp, 0, &assoc_req->channel);
+	if (ret < 0) {
+		lbs_deb_assoc("ASSOC: channel: error setting channel.");
+	}
+
+	ret = update_channel(priv);
+	if (ret < 0) {
+		lbs_deb_assoc("ASSOC: channel: error getting channel.");
+	}
+
+	if (assoc_req->channel != adapter->curbssparams.channel) {
+		lbs_deb_assoc("ASSOC: channel: failed to update channel to %d",
+		              assoc_req->channel);
+		goto done;
+	}
+
+	if (   assoc_req->secinfo.wep_enabled
+	    &&   (assoc_req->wep_keys[0].len
+	       || assoc_req->wep_keys[1].len
+	       || assoc_req->wep_keys[2].len
+	       || assoc_req->wep_keys[3].len)) {
+		/* Make sure WEP keys are re-sent to firmware */
+		set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
+	}
+
+	/* Must restart/rejoin adhoc networks after channel change */
+	set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
+
+done:
+	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+	return ret;
+}
+
+
 static int assoc_helper_wep_keys(wlan_private *priv,
                                  struct assoc_request * assoc_req)
 {
@@ -334,6 +401,11 @@ static int should_stop_adhoc(wlan_adapter *adapter,
 			return 1;
 	}
 
+	if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
+		if (assoc_req->channel != adapter->curbssparams.channel)
+			return 1;
+	}
+
 	return 0;
 }
 
@@ -423,6 +495,15 @@ lbs_deb_assoc("ASSOC(:%d) mode: ret = %d\n", __LINE__, ret);
 		}
 	}
 
+	if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
+		ret = assoc_helper_channel(priv, assoc_req);
+		if (ret) {
+			lbs_deb_assoc("ASSOC(:%d) channel: ret = %d\n",
+			              __LINE__, ret);
+			goto out;
+		}
+	}
+
 	if (   test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)
 	    || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
 		ret = assoc_helper_wep_keys(priv, assoc_req);
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 41d8a4cdd43b..4ca60d9323b4 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -287,7 +287,6 @@ struct _wlan_adapter {
 	u32 txantenna;
 	u32 rxantenna;
 
-	u8 adhocchannel;
 	u32 fragthsd;
 	u32 rtsthsd;
 
diff --git a/drivers/net/wireless/libertas/fw.c b/drivers/net/wireless/libertas/fw.c
index 56b272d62a86..2e535ef7e803 100644
--- a/drivers/net/wireless/libertas/fw.c
+++ b/drivers/net/wireless/libertas/fw.c
@@ -220,8 +220,6 @@ static void wlan_init_adapter(wlan_private * priv)
 	memset(&adapter->capinfo, 0, sizeof(adapter->capinfo));
 	adapter->capinfo.shortpreamble = SHORT_PREAMBLE_ALLOWED;
 
-	adapter->adhocchannel = DEFAULT_AD_HOC_CHANNEL;
-
 	adapter->psmode = wlan802_11powermodecam;
 	adapter->multipledtim = MRVDRV_DEFAULT_MULTIPLE_DTIM;
 
diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c
index c9111b877067..a11ce3a6f611 100644
--- a/drivers/net/wireless/libertas/join.c
+++ b/drivers/net/wireless/libertas/join.c
@@ -158,7 +158,6 @@ int libertas_start_adhoc_network(wlan_private * priv, struct WLAN_802_11_SSID *a
 
 	libertas_set_radio_control(priv);
 
-	lbs_deb_join("Adhoc channel = %d\n", adapter->adhocchannel);
 	lbs_deb_join("curbssparams.channel = %d\n",
 	       adapter->curbssparams.channel);
 	lbs_deb_join("curbssparams.band = %d\n", adapter->curbssparams.band);
@@ -513,15 +512,13 @@ 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->adhocchannel);
+	WARN_ON(!adapter->curbssparams.channel);
 
 	lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
-	       adapter->adhocchannel);
-
-	adapter->curbssparams.channel = adapter->adhocchannel;
+	       adapter->curbssparams.channel);
 
-	pbssdesc->channel = adapter->adhocchannel;
-	adhs->phyparamset.dsparamset.currentchan = adapter->adhocchannel;
+	pbssdesc->channel = adapter->curbssparams.channel;
+	adhs->phyparamset.dsparamset.currentchan = adapter->curbssparams.channel;
 
 	memcpy(&pbssdesc->phyparamset,
 	       &adhs->phyparamset, sizeof(union ieeetypes_phyparamset));
@@ -909,7 +906,7 @@ int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
 	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
 
 	lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
-	lbs_deb_join("ADHOC_RESP: channel = %d\n", adapter->adhocchannel);
+	lbs_deb_join("ADHOC_RESP: channel = %d\n", adapter->curbssparams.channel);
 	lbs_deb_join("ADHOC_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n",
 	       padhocresult->BSSID[0], padhocresult->BSSID[1],
 	       padhocresult->BSSID[2], padhocresult->BSSID[3],
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 518371a76c36..40dd08018b49 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -157,103 +157,6 @@ static struct chan_freq_power *find_cfp_by_band_and_freq(wlan_adapter * adapter,
 	return cfp;
 }
 
-static int updatecurrentchannel(wlan_private * priv)
-{
-	int ret;
-
-	/*
-	 ** the channel in f/w could be out of sync, get the current channel
-	 */
-	ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
-				    cmd_opt_802_11_rf_channel_get,
-				    cmd_option_waitforrsp, 0, NULL);
-
-	lbs_deb_wext("current channel %d\n",
-	       priv->adapter->curbssparams.channel);
-
-	return ret;
-}
-
-static int setcurrentchannel(wlan_private * priv, int channel)
-{
-	lbs_deb_wext("set channel %d\n", channel);
-
-	/*
-	 **  Current channel is not set to adhocchannel requested, set channel
-	 */
-	return (libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
-				      cmd_opt_802_11_rf_channel_set,
-				      cmd_option_waitforrsp, 0, &channel));
-}
-
-static int changeadhocchannel(wlan_private * priv, int channel)
-{
-	int ret = 0;
-	struct WLAN_802_11_SSID curadhocssid;
-	struct bss_descriptor * join_bss = NULL;
-	wlan_adapter *adapter = priv->adapter;
-
-	adapter->adhocchannel = channel;
-
-	updatecurrentchannel(priv);
-
-	if (adapter->curbssparams.channel == adapter->adhocchannel) {
-		/* adhocchannel is set to the current channel already */
-		goto out;
-	}
-
-	lbs_deb_wext("updating channel from %d to %d\n",
-	       adapter->curbssparams.channel, adapter->adhocchannel);
-
-	setcurrentchannel(priv, adapter->adhocchannel);
-
-	updatecurrentchannel(priv);
-
-	if (adapter->curbssparams.channel != adapter->adhocchannel) {
-		lbs_deb_wext("failed to updated channel to %d, channel = %d\n",
-		       adapter->adhocchannel, adapter->curbssparams.channel);
-		ret = -1;
-		goto out;
-	}
-
-	if (adapter->connect_status != libertas_connected)
-		goto out;
-
-	lbs_deb_wext("channel changed while in IBSS\n");
-
-	/* Copy the current ssid */
-	memcpy(&curadhocssid, &adapter->curbssparams.ssid,
-	       sizeof(struct WLAN_802_11_SSID));
-
-	/* Exit Adhoc mode */
-	lbs_deb_wext("in changeadhocchannel(): sending Adhoc stop\n");
-	ret = libertas_stop_adhoc_network(priv);
-	if (ret)
-		goto out;
-
-	/* Scan for the network, do not save previous results.  Stale
-	 *   scan data will cause us to join a non-existant adhoc network
-	 */
-	libertas_send_specific_SSID_scan(priv, &curadhocssid, 1);
-
-	/* find out the BSSID that matches the current SSID */
-	join_bss = libertas_find_SSID_in_list(adapter, &curadhocssid, NULL,
-			   IW_MODE_ADHOC);
-
-	if (join_bss) {
-		lbs_deb_wext("SSID found in list, so join\n");
-		libertas_join_adhoc_network(priv, join_bss);
-	} else {
-		lbs_deb_wext("SSID not found in list, "
-		       "creating AdHoc with SSID '%s'\n",
-		       curadhocssid.ssid);
-		libertas_start_adhoc_network(priv, &curadhocssid);
-	}
-
-out:
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
 
 /**
  *  @brief Set Radio On/OFF
@@ -1228,82 +1131,59 @@ out:
 static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info,
 		  struct iw_freq *fwrq, char *extra)
 {
-	int ret = 0;
+	int ret = -EINVAL;
 	wlan_private *priv = dev->priv;
 	wlan_adapter *adapter = priv->adapter;
-	int rc = -EINPROGRESS;	/* Call commit handler */
 	struct chan_freq_power *cfp;
+	struct assoc_request * assoc_req;
 
 	lbs_deb_enter(LBS_DEB_WEXT);
 
-	/*
-	 * If setting by frequency, convert to a channel
-	 */
-	if (fwrq->e == 1) {
+	mutex_lock(&adapter->lock);
+	assoc_req = wlan_get_association_request(adapter);
+	if (!assoc_req) {
+		ret = -ENOMEM;
+		goto out;
+	}
 
+	/* If setting by frequency, convert to a channel */
+	if (fwrq->e == 1) {
 		long f = fwrq->m / 100000;
-		int c = 0;
 
 		cfp = find_cfp_by_band_and_freq(adapter, 0, f);
 		if (!cfp) {
 			lbs_deb_wext("invalid freq %ld\n", f);
-			return -EINVAL;
+			goto out;
 		}
 
-		c = (int)cfp->channel;
-
-		if (c < 0)
-			return -EINVAL;
-
 		fwrq->e = 0;
-		fwrq->m = c;
+		fwrq->m = (int) cfp->channel;
 	}
 
-	/*
-	 * Setting by channel number
-	 */
+	/* Setting by channel number */
 	if (fwrq->m > 1000 || fwrq->e > 0) {
-		rc = -EOPNOTSUPP;
-	} else {
-		int channel = fwrq->m;
+		goto out;
+	}
 
-		cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, channel);
-		if (!cfp) {
-			rc = -EINVAL;
-		} else {
-			if (adapter->mode == IW_MODE_ADHOC) {
-				rc = changeadhocchannel(priv, channel);
-				/*  If station is WEP enabled, send the
-				 *  command to set WEP in firmware
-				 */
-				if (adapter->secinfo.wep_enabled) {
-					lbs_deb_wext("set_freq: WEP enabled\n");
-					ret = libertas_prepare_and_send_command(priv,
-								    cmd_802_11_set_wep,
-								    cmd_act_add,
-								    cmd_option_waitforrsp,
-								    0,
-								    NULL);
-
-					if (ret) {
-						rc = ret;
-						goto out;
-					}
-
-					adapter->currentpacketfilter |=
-					    cmd_act_mac_wep_enable;
-
-					libertas_set_mac_packet_filter(priv);
-				}
-			} else {
-				rc = -EOPNOTSUPP;
-			}
-		}
+	cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, fwrq->m);
+	if (!cfp) {
+		goto out;
 	}
 
+	assoc_req->channel = fwrq->m;
+	ret = 0;
+
 out:
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", rc);
-	return rc;
+	if (ret == 0) {
+		set_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags);
+		wlan_postpone_association_work(priv);
+	} else {
+		wlan_cancel_association_work(priv);
+	}
+	mutex_unlock(&adapter->lock);
+
+	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+	return ret;
 }
 
 /**