浏览代码

[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>
Dan Williams 18 年之前
父节点
当前提交
fcdb53dbc7

+ 18 - 22
drivers/net/wireless/libertas/assoc.c

@@ -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);

+ 15 - 16
drivers/net/wireless/libertas/debugfs.c

@@ -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);
 

+ 0 - 1
drivers/net/wireless/libertas/defs.h

@@ -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
 

+ 4 - 2
drivers/net/wireless/libertas/dev.h

@@ -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;

+ 17 - 13
drivers/net/wireless/libertas/fw.c

@@ -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");

文件差异内容过多而无法显示
+ 474 - 580
drivers/net/wireless/libertas/scan.c


+ 14 - 7
drivers/net/wireless/libertas/scan.h

@@ -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,

+ 28 - 31
drivers/net/wireless/libertas/wext.c

@@ -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:

部分文件因为文件数量过多而无法显示