Commit fcdb53db authored by Dan Williams's avatar Dan Williams Committed by John W. Linville

[PATCH] libertas: make scan result handling more flexible

- use a linked list for scan results
- age scan results
- pass bss_descriptors around instead of indexes into the scan table
- lock access to the scan results
- stop returning EAGAIN from SIOCGIWSCAN handler
Signed-off-by: default avatarDan Williams <dcbw@redhat.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 90e8eafc
......@@ -18,7 +18,7 @@ static int assoc_helper_essid(wlan_private *priv,
{
wlan_adapter *adapter = priv->adapter;
int ret = 0;
int i;
struct bss_descriptor * bss;
lbs_deb_enter(LBS_DEB_ASSOC);
......@@ -28,17 +28,13 @@ static int assoc_helper_essid(wlan_private *priv,
libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 1);
}
i = libertas_find_SSID_in_list(adapter, &assoc_req->ssid,
bss = libertas_find_SSID_in_list(adapter, &assoc_req->ssid,
NULL, IW_MODE_INFRA);
if (i >= 0) {
lbs_deb_assoc(
"SSID found in scan list ... associating...\n");
ret = wlan_associate(priv, &adapter->scantable[i]);
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,
&adapter->scantable[i].bssid,
ETH_ALEN);
memcpy(&assoc_req->bssid, bss->bssid, ETH_ALEN);
}
} else {
lbs_deb_assoc("SSID '%s' not found; cannot associate\n",
......@@ -51,11 +47,11 @@ static int assoc_helper_essid(wlan_private *priv,
libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 0);
/* Search for the requested SSID in the scan table */
i = libertas_find_SSID_in_list(adapter, &assoc_req->ssid, NULL,
bss = libertas_find_SSID_in_list(adapter, &assoc_req->ssid, NULL,
IW_MODE_ADHOC);
if (i >= 0) {
lbs_deb_assoc("SSID found at %d in List, so join\n", ret);
libertas_join_adhoc_network(priv, &adapter->scantable[i]);
if (bss != NULL) {
lbs_deb_assoc("SSID found joining\n");
libertas_join_adhoc_network(priv, bss);
} else {
/* else send START command */
lbs_deb_assoc("SSID not found in list, so creating adhoc"
......@@ -74,28 +70,28 @@ static int assoc_helper_bssid(wlan_private *priv,
struct assoc_request * assoc_req)
{
wlan_adapter *adapter = priv->adapter;
int i, ret = 0;
int ret = 0;
struct bss_descriptor * bss;
lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID" MAC_FMT "\n",
MAC_ARG(assoc_req->bssid));
/* Search for index position in list for requested MAC */
i = libertas_find_BSSID_in_list(adapter, assoc_req->bssid,
bss = libertas_find_BSSID_in_list(adapter, assoc_req->bssid,
assoc_req->mode);
if (i < 0) {
if (bss == NULL) {
lbs_deb_assoc("ASSOC: WAP: BSSID " MAC_FMT " not found, "
"cannot associate.\n", MAC_ARG(assoc_req->bssid));
goto out;
}
if (assoc_req->mode == IW_MODE_INFRA) {
ret = wlan_associate(priv, &adapter->scantable[i]);
lbs_deb_assoc("ASSOC: return from wlan_associate(bssd) was %d\n", ret);
ret = wlan_associate(priv, bss);
lbs_deb_assoc("ASSOC: wlan_associate(bssid) returned %d\n", ret);
} else if (assoc_req->mode == IW_MODE_ADHOC) {
libertas_join_adhoc_network(priv, &adapter->scantable[i]);
libertas_join_adhoc_network(priv, bss);
}
memcpy(&assoc_req->ssid, &adapter->scantable[i].ssid,
sizeof(struct WLAN_802_11_SSID));
memcpy(&assoc_req->ssid, &bss->ssid, sizeof(struct WLAN_802_11_SSID));
out:
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
......
......@@ -63,35 +63,34 @@ static ssize_t libertas_getscantable(struct file *file, char __user *userbuf,
int numscansdone = 0, res;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
struct bss_descriptor * iter_bss;
pos += snprintf(buf+pos, len-pos,
"# | ch | ss | bssid | cap | TSF | Qual | SSID \n");
while (numscansdone < priv->adapter->numinscantable) {
struct bss_descriptor *pbssinfo;
mutex_lock(&priv->adapter->lock);
list_for_each_entry (iter_bss, &priv->adapter->network_list, list) {
u16 cap;
pbssinfo = &priv->adapter->scantable[numscansdone];
memcpy(&cap, &pbssinfo->cap, sizeof(cap));
memcpy(&cap, &iter_bss->cap, sizeof(cap));
pos += snprintf(buf+pos, len-pos,
"%02u| %03d | %03ld | %02x:%02x:%02x:%02x:%02x:%02x |",
numscansdone, pbssinfo->channel, pbssinfo->rssi,
pbssinfo->bssid[0], pbssinfo->bssid[1],
pbssinfo->bssid[2], pbssinfo->bssid[3],
pbssinfo->bssid[4], pbssinfo->bssid[5]);
numscansdone, iter_bss->channel, iter_bss->rssi,
iter_bss->bssid[0], iter_bss->bssid[1],
iter_bss->bssid[2], iter_bss->bssid[3],
iter_bss->bssid[4], iter_bss->bssid[5]);
pos += snprintf(buf+pos, len-pos, " %04x-", cap);
pos += snprintf(buf+pos, len-pos, "%c%c%c |",
pbssinfo->cap.ibss ? 'A' : 'I',
pbssinfo->cap.privacy ? 'P' : ' ',
pbssinfo->cap.spectrummgmt ? 'S' : ' ');
pos += snprintf(buf+pos, len-pos, " %08llx |", pbssinfo->networktsf);
pos += snprintf(buf+pos, len-pos, " %d |",
SCAN_RSSI(priv->adapter->scantable[numscansdone].rssi));
pos += snprintf(buf+pos, len-pos, " %s\n", pbssinfo->ssid.ssid);
iter_bss->cap.ibss ? 'A' : 'I',
iter_bss->cap.privacy ? 'P' : ' ',
iter_bss->cap.spectrummgmt ? 'S' : ' ');
pos += snprintf(buf+pos, len-pos, " %08llx |", iter_bss->networktsf);
pos += snprintf(buf+pos, len-pos, " %d |", SCAN_RSSI(iter_bss->rssi));
pos += snprintf(buf+pos, len-pos, " %s\n", iter_bss->ssid.ssid);
numscansdone++;
}
mutex_unlock(&priv->adapter->lock);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
......
......@@ -127,7 +127,6 @@ static inline void lbs_dbg_hex(char *prompt, u8 * buf, int len)
#define MRVDRV_NUM_OF_CMD_BUFFER 10
#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024)
#define MRVDRV_MAX_CHANNEL_SIZE 14
#define MRVDRV_MAX_BSSID_LIST 64
#define MRVDRV_ASSOCIATION_TIME_OUT 255
#define MRVDRV_SNAP_HEADER_LEN 8
......
......@@ -257,8 +257,10 @@ struct _wlan_adapter {
struct WLAN_802_11_SSID previousssid;
u8 previousbssid[ETH_ALEN];
struct bss_descriptor *scantable;
u32 numinscantable;
/* Scan results list */
struct list_head network_list;
struct list_head network_free_list;
struct bss_descriptor *networks;
u8 scantype;
u32 scanmode;
......
......@@ -126,18 +126,17 @@ done:
static int wlan_allocate_adapter(wlan_private * priv)
{
u32 ulbufsize;
size_t bufsize;
wlan_adapter *adapter = priv->adapter;
struct bss_descriptor *ptempscantable;
/* Allocate buffer to store the BSSID list */
ulbufsize = sizeof(struct bss_descriptor) * MRVDRV_MAX_BSSID_LIST;
if (!(ptempscantable = kzalloc(ulbufsize, GFP_KERNEL))) {
bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor);
adapter->networks = kzalloc(bufsize, GFP_KERNEL);
if (!adapter->networks) {
lbs_pr_err("Out of memory allocating beacons\n");
libertas_free_adapter(priv);
return -1;
return -ENOMEM;
}
adapter->scantable = ptempscantable;
/* Allocate the command buffers */
libertas_allocate_cmd_buffer(priv);
......@@ -188,7 +187,14 @@ static void wlan_init_adapter(wlan_private * priv)
adapter->assoc_req = NULL;
adapter->numinscantable = 0;
/* Initialize scan result lists */
INIT_LIST_HEAD(&adapter->network_free_list);
INIT_LIST_HEAD(&adapter->network_list);
for (i = 0; i < MAX_NETWORK_COUNT; i++) {
list_add_tail(&adapter->networks[i].list,
&adapter->network_free_list);
}
adapter->pattemptedbssdesc = NULL;
mutex_init(&adapter->lock);
......@@ -291,11 +297,9 @@ void libertas_free_adapter(wlan_private * priv)
lbs_deb_fw("free command_timer\n");
del_timer(&adapter->command_timer);
lbs_deb_fw("free scantable\n");
if (adapter->scantable) {
kfree(adapter->scantable);
adapter->scantable = NULL;
}
lbs_deb_fw("free scan results table\n");
kfree(adapter->networks);
adapter->networks = NULL;
/* Free the adapter object itself */
lbs_deb_fw("free adapter\n");
......
This diff is collapsed.
......@@ -156,9 +156,9 @@ struct bss_descriptor {
u8 mode;
u8 libertas_supported_rates[WLAN_SUPPORTED_RATES];
int extra_ie;
u8 timestamp[8]; //!< TSF value included in the beacon/probe response
unsigned long last_scanned;
union ieeetypes_phyparamset phyparamset;
union IEEEtypes_ssparamset ssparamset;
struct ieeetypes_capinfo cap;
......@@ -172,14 +172,21 @@ struct bss_descriptor {
size_t wpa_ie_len;
u8 rsn_ie[MAX_WPA_IE_LEN];
size_t rsn_ie_len;
struct list_head list;
};
extern int libertas_SSID_cmp(struct WLAN_802_11_SSID *ssid1,
struct WLAN_802_11_SSID *ssid2);
extern int libertas_find_SSID_in_list(wlan_adapter * adapter, struct WLAN_802_11_SSID *ssid,
u8 * bssid, u8 mode);
int libertas_find_best_SSID_in_list(wlan_adapter * adapter, u8 mode);
extern int libertas_find_BSSID_in_list(wlan_adapter * adapter, u8 * bssid, u8 mode);
struct WLAN_802_11_SSID *ssid2);
struct bss_descriptor * libertas_find_SSID_in_list(wlan_adapter * adapter,
struct WLAN_802_11_SSID *ssid, u8 * bssid, u8 mode);
struct bss_descriptor * libertas_find_best_SSID_in_list(wlan_adapter * adapter,
u8 mode);
extern struct bss_descriptor * libertas_find_BSSID_in_list(wlan_adapter * adapter,
u8 * bssid, u8 mode);
int libertas_find_best_network_SSID(wlan_private * priv,
struct WLAN_802_11_SSID *pSSID,
......
......@@ -189,6 +189,8 @@ static int setcurrentchannel(wlan_private * priv, int 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;
......@@ -214,43 +216,38 @@ static int changeadhocchannel(wlan_private * priv, int channel)
goto out;
}
if (adapter->connect_status == libertas_connected) {
int i;
struct WLAN_802_11_SSID curadhocssid;
lbs_deb_wext("channel changed while in IBSS\n");
if (adapter->connect_status != libertas_connected)
goto out;
/* Copy the current ssid */
memcpy(&curadhocssid, &adapter->curbssparams.ssid,
sizeof(struct WLAN_802_11_SSID));
lbs_deb_wext("channel changed while in IBSS\n");
/* Exit Adhoc mode */
lbs_deb_wext("in changeadhocchannel(): sending Adhoc stop\n");
ret = libertas_stop_adhoc_network(priv);
/* Copy the current ssid */
memcpy(&curadhocssid, &adapter->curbssparams.ssid,
sizeof(struct WLAN_802_11_SSID));
if (ret)
goto out;
/* 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, 0);
/* 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, 0);
// find out the BSSID that matches the current SSID
i = libertas_find_SSID_in_list(adapter, &curadhocssid, NULL,
IW_MODE_ADHOC);
/* find out the BSSID that matches the current SSID */
join_bss = libertas_find_SSID_in_list(adapter, &curadhocssid, NULL,
IW_MODE_ADHOC);
if (i >= 0) {
lbs_deb_wext("SSID found at %d in list,"
"so join\n", i);
libertas_join_adhoc_network(priv, &adapter->scantable[i]);
} else {
// else send START command
lbs_deb_wext("SSID not found in list, "
"creating AdHoc with SSID '%s'\n",
curadhocssid.ssid);
libertas_start_adhoc_network(priv, &curadhocssid);
} // end of else (START command)
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:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment