mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-22 12:14:01 +08:00
[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: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
90e8eafc93
commit
fcdb53dbc7
@ -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");
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
if (adapter->connect_status != libertas_connected)
|
||||
goto out;
|
||||
|
||||
lbs_deb_wext("channel changed while in IBSS\n");
|
||||
lbs_deb_wext("channel changed while in IBSS\n");
|
||||
|
||||
/* Copy the current ssid */
|
||||
memcpy(&curadhocssid, &adapter->curbssparams.ssid,
|
||||
sizeof(struct WLAN_802_11_SSID));
|
||||
/* 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);
|
||||
/* Exit Adhoc mode */
|
||||
lbs_deb_wext("in changeadhocchannel(): sending Adhoc stop\n");
|
||||
ret = libertas_stop_adhoc_network(priv);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
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 */
|
||||
join_bss = libertas_find_SSID_in_list(adapter, &curadhocssid, NULL,
|
||||
IW_MODE_ADHOC);
|
||||
|
||||
// find out the BSSID that matches the current SSID
|
||||
i = 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:
|
||||
|
Loading…
Reference in New Issue
Block a user