[OLPC-devel] [PATCH] wireless/libertas: miscellaneous fixes

Dan Williams dcbw at redhat.com
Fri Jun 23 23:58:26 EDT 2006


- Do SET_NETDEV_DEV so the device/driver links are created in sysfs for
the net class device, makes HAL and NetworkManager less angry
- Fix up the re-association code so it actually compiles
- Do wireless quality reporting ipw-style
- Hook up SIOCSIWENCODE so people can actually use encrypted APs

Signed-off-by: Dan Williams <dcbw at redhat.com>

(try #2, wrong list address on first mail, same patch in both)

--- a/drivers/net/wireless/libertas/if_usb.c	2006-06-23 17:21:43.000000000 -0400
+++ b/drivers/net/wireless/libertas/if_usb.c	2006-06-23 23:00:54.000000000 -0400
@@ -888,6 +888,8 @@
 		return WLAN_STATUS_FAILURE;
 	}
 
+	SET_NETDEV_DEV(cardp->eth_dev, &(cardp->udev->dev));
+
 	PRINTM(INFO, "udev pointer is at %p\n", cardp->udev);
 
 	LEAVE();
--- a/drivers/net/wireless/libertas/wlan_decl.h	2006-06-23 17:21:43.000000000 -0400
+++ b/drivers/net/wireless/libertas/wlan_decl.h	2006-06-23 23:08:05.000000000 -0400
@@ -80,7 +80,7 @@
 void command_timer_fn(unsigned long data);
 
 #ifdef REASSOCIATION
-void reassoc_timer_fn(void data);
+void reassoc_timer_fn(unsigned long data);
 #endif				/* REASSOCIATION */
 
 int wlan_set_essid(struct net_device *dev, struct iw_request_info *info,
--- a/drivers/net/wireless/libertas/wlan_dev.h	2006-06-23 17:21:43.000000000 -0400
+++ b/drivers/net/wireless/libertas/wlan_dev.h	2006-06-23 23:04:56.000000000 -0400
@@ -248,7 +248,7 @@
 #ifdef REASSOCIATION
 	/** Reassociation on and off */
 	u8 Reassoc_on;
-	SEMAPHORE ReassocSem;
+	struct semaphore ReassocSem;
 #endif				/* REASSOCIATION */
 
 	u8 ATIMEnabled;
--- a/drivers/net/wireless/libertas/wlan_wext.c	2006-06-23 17:21:43.000000000 -0400
+++ b/drivers/net/wireless/libertas/wlan_wext.c	2006-06-23 23:32:03.000000000 -0400
@@ -819,7 +819,7 @@
 
 	ENTER();
 
-	del_timer(&Adapter->MrvDrvTimer);
+	del_timer(&Adapter->reassoc_timer);
 
 	Adapter->Reassoc_on = FALSE;
 
@@ -1792,12 +1792,17 @@
 	/*
 	 * Set the qual, level and noise range values 
 	 */
-	/*
-	 * need to put the right values here 
-	 */
-	range->max_qual.qual = 10;
+	range->max_qual.qual = 100;
 	range->max_qual.level = 0;
 	range->max_qual.noise = 0;
+	range->max_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+
+	range->avg_qual.qual = 70;
+	/* TODO: Find real 'good' to 'bad' threshold value for RSSI */
+	range->avg_qual.level = 0;
+	range->avg_qual.noise = 0;
+	range->avg_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+
 	range->sensitivity = 0;
 
 	/*
@@ -2005,7 +2010,7 @@
 	(iw_handler) wlan_get_txpow,	/* SIOCGIWTXPOW */
 	(iw_handler) wlan_set_retry,	/* SIOCSIWRETRY */
 	(iw_handler) wlan_get_retry,	/* SIOCGIWRETRY */
-	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) wlan_set_encode,	/* SIOCSIWENCODE */
 	(iw_handler) wlan_get_encode,	/* SIOCGIWENCODE */
 	(iw_handler) wlan_set_power,	/* SIOCSIWPOWER */
 	(iw_handler) wlan_get_power,	/* SIOCGIWPOWER */
@@ -4655,46 +4660,116 @@
  */
 struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
 {
+	enum {
+		POOR = 30,
+		FAIR = 60,
+		GOOD = 80,
+		VERY_GOOD = 90,
+		EXCELLENT = 95,
+		PERFECT = 100
+	};
 	wlan_private *priv = dev->priv;
 	wlan_adapter *Adapter = priv->adapter;
 	int ret = WLAN_STATUS_SUCCESS;
+	u32 rssi_qual;
+	u32 tx_qual;
+	u32 quality = 0;
+	int stats_valid = 0;
+	u8 rssi;
 
 	ENTER();
 
 	priv->wstats.status = Adapter->InfrastructureMode;
-	priv->wstats.discard.retries = priv->stats.tx_errors;
+
+	/* If we're not associated, all quality values are meaningless */
+	if (Adapter->MediaConnectStatus != WlanMediaStateConnected)
+		goto out;
 
 	/* send RSSI command to get beacon RSSI/NF, valid only if associated */
 	ret = PrepareAndSendCommand(priv,
 				    HostCmd_CMD_802_11_RSSI,
 				    0, HostCmd_OPTION_WAITFORRSP, 0, NULL);
+	if (ret)
+		goto out;
 
+	/* Quality by RSSI */
 	priv->wstats.qual.level =
 	    CAL_RSSI(Adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
-		     Adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
-	priv->wstats.qual.noise = CAL_NF(Adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
-	if (Adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0
-	    && Adapter->MediaConnectStatus == WlanMediaStateConnected)
+	     Adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
+
+	if (Adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
 		priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
-	else
+	} else {
 		priv->wstats.qual.noise =
 		    CAL_NF(Adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
-	priv->wstats.qual.qual = 0;
+	}
 
 	PRINTM(INFO, "Signal Level = %#x\n", priv->wstats.qual.level);
 	PRINTM(INFO, "Noise = %#x\n", priv->wstats.qual.noise);
 
+	rssi = priv->wstats.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE;
+	if (rssi < 15)
+		rssi_qual = rssi * POOR / 10;
+	else if (rssi < 20)
+		rssi_qual = (rssi - 15) * (FAIR - POOR) / 5 + POOR;
+	else if (rssi < 30)
+		rssi_qual = (rssi - 20) * (GOOD - FAIR) / 5 + FAIR;
+	else if (rssi < 40)
+		rssi_qual = (rssi - 30) * (VERY_GOOD - GOOD) /
+		    10 + GOOD;
+	else
+		rssi_qual = (rssi - 40) * (PERFECT - VERY_GOOD) /
+		    10 + VERY_GOOD;
+	quality = rssi_qual;
+
+	/* Quality by TX errors */
+	priv->wstats.discard.retries = priv->stats.tx_errors;
 	ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_GET_LOG,
 				    0, HostCmd_OPTION_WAITFORRSP, 0, NULL);
-
 	if (!ret) {
+		u32 tx_retries = Adapter->LogMsg.retry;
+
+		if (tx_retries > 75)
+			tx_qual = (90 - tx_retries) * POOR / 15;
+		else if (tx_retries > 70)
+			tx_qual = (75 - tx_retries) * (FAIR - POOR) / 5 + POOR;
+		else if (tx_retries > 65)
+			tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR;
+		else if (tx_retries > 50)
+			tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) /
+			    15 + GOOD;
+		else
+			tx_qual = (50 - tx_retries) *
+			    (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
+		quality = min(quality, tx_qual);
+
 		priv->wstats.discard.code = Adapter->LogMsg.wepundecryptable;
 		priv->wstats.discard.fragment = Adapter->LogMsg.fcserror;
-		priv->wstats.discard.retries = Adapter->LogMsg.retry;
+		priv->wstats.discard.retries = tx_retries;
 		priv->wstats.discard.misc = Adapter->LogMsg.ackfailure;
 	}
 
+	/* Calculate quality */
+	priv->wstats.qual.qual = max(quality, (u32)100);
+	priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED;
+	stats_valid = 1;
+
+out:
+	if (!stats_valid) {
+		priv->wstats.miss.beacon = 0;
+		priv->wstats.discard.retries = 0;
+		priv->wstats.qual.qual = 0;
+		priv->wstats.qual.level = 0;
+		priv->wstats.qual.noise = 0;
+		priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED;
+		priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID |
+		    IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
+	}
+
+	LEAVE ();
 	return &priv->wstats;
+
+
 }
 
 /** 





More information about the Devel mailing list