Skip to content

Commit

Permalink
[PATCH] libertas: move channel changing into association framework
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Dan Williams authored and John W. Linville committed Jun 11, 2007
1 parent d43fb8e commit ef9a264
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 162 deletions.
81 changes: 81 additions & 0 deletions drivers/net/wireless/libertas/assoc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -158,6 +162,69 @@ static int assoc_helper_mode(wlan_private *priv,
}


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)
{
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
Expand Down
1 change: 0 additions & 1 deletion drivers/net/wireless/libertas/dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,6 @@ struct _wlan_adapter {
u32 txantenna;
u32 rxantenna;

u8 adhocchannel;
u32 fragthsd;
u32 rtsthsd;

Expand Down
2 changes: 0 additions & 2 deletions drivers/net/wireless/libertas/fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
13 changes: 5 additions & 8 deletions drivers/net/wireless/libertas/join.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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],
Expand Down
182 changes: 31 additions & 151 deletions drivers/net/wireless/libertas/wext.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1228,82 +1131,59 @@ static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
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;
}

/**
Expand Down

0 comments on commit ef9a264

Please sign in to comment.