summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/assoc.c
diff options
context:
space:
mode:
authorDan Williams2007-05-25 22:46:33 +0200
committerJohn W. Linville2007-06-11 20:28:42 +0200
commitef9a264b7a288a07c43ddb244c4f9ab0e8df90e4 (patch)
tree67dad09f719d1e91cb168143db2215b9a84dd942 /drivers/net/wireless/libertas/assoc.c
parent[PATCH] libertas: fix oops on rmmod (diff)
downloadkernel-qcow2-linux-ef9a264b7a288a07c43ddb244c4f9ab0e8df90e4.tar.gz
kernel-qcow2-linux-ef9a264b7a288a07c43ddb244c4f9ab0e8df90e4.tar.xz
kernel-qcow2-linux-ef9a264b7a288a07c43ddb244c4f9ab0e8df90e4.zip
[PATCH] libertas: move channel changing into association framework
Handle channel changes through the deferred association framework rather than directly. Fixes errors when setting channels along with other parameters like mode and SSID. Signed-off-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas/assoc.c')
-rw-r--r--drivers/net/wireless/libertas/assoc.c81
1 files changed, 81 insertions, 0 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);