Skip to content

Commit

Permalink
[PATCH] libertas: make association paths consistent
Browse files Browse the repository at this point in the history
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.

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 ef9a264 commit e76850d
Show file tree
Hide file tree
Showing 10 changed files with 215 additions and 211 deletions.
6 changes: 3 additions & 3 deletions drivers/net/wireless/libertas/11d.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
Expand Down
4 changes: 3 additions & 1 deletion drivers/net/wireless/libertas/11d.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
106 changes: 83 additions & 23 deletions drivers/net/wireless/libertas/assoc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
static const char *libertas_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,
libertas_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)
{
Expand All @@ -36,10 +86,8 @@ static int assoc_helper_essid(wlan_private *priv,
NULL, IW_MODE_INFRA);
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);
Expand All @@ -55,14 +103,16 @@ static int assoc_helper_essid(wlan_private *priv,
IW_MODE_ADHOC);
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);
Expand All @@ -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 == IW_MODE_INFRA) {
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 == IW_MODE_ADHOC) {
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);
Expand Down Expand Up @@ -421,15 +471,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)
Expand Down Expand Up @@ -561,7 +611,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));
libertas_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);
Expand All @@ -580,6 +632,10 @@ lbs_deb_assoc("ASSOC(:%d) wpa_keys: ret = %d\n", __LINE__, ret);
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:
Expand All @@ -594,9 +650,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;
Expand All @@ -606,15 +663,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->mode;

Expand Down Expand Up @@ -655,7 +715,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;
}


6 changes: 3 additions & 3 deletions drivers/net/wireless/libertas/assoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down
18 changes: 6 additions & 12 deletions drivers/net/wireless/libertas/cmdresp.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,25 +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->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 */
Expand Down
27 changes: 15 additions & 12 deletions drivers/net/wireless/libertas/dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,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 */
Expand Down Expand Up @@ -168,18 +167,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;
u8 mode;
u8 bssid[ETH_ALEN];

Expand All @@ -196,6 +197,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*/
Expand Down Expand Up @@ -252,8 +256,6 @@ struct _wlan_adapter {
/* IW_MODE_* */
u8 mode;

struct bss_descriptor *pattemptedbssdesc;

struct WLAN_802_11_SSID previousssid;
u8 previousbssid[ETH_ALEN];

Expand Down Expand Up @@ -322,7 +324,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;
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/libertas/fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,8 @@ static void wlan_init_adapter(wlan_private * priv)
adapter->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
adapter->mode = IW_MODE_INFRA;

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);
Expand All @@ -195,7 +196,6 @@ static void wlan_init_adapter(wlan_private * priv)
&adapter->network_free_list);
}

adapter->pattemptedbssdesc = NULL;
mutex_init(&adapter->lock);

adapter->prescan = 1;
Expand Down
Loading

0 comments on commit e76850d

Please sign in to comment.