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) {
 }
 
 
+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)
 {
                        return 1;
        }
 
+       if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
+               if (assoc_req->channel != adapter->curbssparams.channel)
+                       return 1;
+       }
+
        return 0;
 }
 
                }
        }
 
+       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);
 
 
        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);
        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));
        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],
 
        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
 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;
 }
 
 /**