libertas: Don't sleep inside get_wireless_stats

Marcelo Tosatti mtosatti at redhat.unroutablecom
Sun Dec 24 04:30:49 EST 2006


Commit:     cd0665ce1df6fdcc0034b202ff7d8b45ddaa1d66
Parent:     c911ada952d9aaf29309a69edc29a063413fa956
commit cd0665ce1df6fdcc0034b202ff7d8b45ddaa1d66
Author:     Marcelo Tosatti <mtosatti at redhat.com>
AuthorDate: Fri Dec 22 18:47:46 2006 -0200
Commit:     Marcelo Tosatti <mtosatti at redhat.com>
CommitDate: Fri Dec 22 18:47:46 2006 -0200

    libertas: Don't sleep inside get_wireless_stats
    
    get_wireless_stats holds either dev_base_lock (from dev_seq_start,
    /proc path) or rtnl_lock (from net ioctl path).
    
    Call RSSI/GET_LOG during association, and use such cached stats. Also
    update them by sending RSSI/GET_LOG commands asynchronously.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
---
 drivers/net/wireless/libertas/wlan_assoc.c |    7 +++
 drivers/net/wireless/libertas/wlan_wext.c  |   57 +++++++++++++---------------
 2 files changed, 33 insertions(+), 31 deletions(-)

diff --git a/drivers/net/wireless/libertas/wlan_assoc.c b/drivers/net/wireless/libertas/wlan_assoc.c
index 485b1e7..f37180d 100644
--- a/drivers/net/wireless/libertas/wlan_assoc.c
+++ b/drivers/net/wireless/libertas/wlan_assoc.c
@@ -506,6 +506,13 @@ dprintk(1, "ASSOC(:%d) wpa_keys: ret = %
 			dprintk(1, "ASSOC: association attempt successful. "
 				"Associated to '%s' (" MAC_FMT ")\n",
 				assoc_req->ssid.Ssid, MAC_ARG(assoc_req->bssid));
+			libertas_prepare_and_send_command(priv,
+				HostCmd_CMD_802_11_RSSI,
+				0, HostCmd_OPTION_WAITFORRSP, 0, NULL);
+
+			libertas_prepare_and_send_command(priv,
+				HostCmd_CMD_802_11_GET_LOG,
+				0, HostCmd_OPTION_WAITFORRSP, 0, NULL);
 		} else {
 			
 			ret = WLAN_STATUS_FAILURE;
diff --git a/drivers/net/wireless/libertas/wlan_wext.c b/drivers/net/wireless/libertas/wlan_wext.c
index f7c07db..1e25dcc 100644
--- a/drivers/net/wireless/libertas/wlan_wext.c
+++ b/drivers/net/wireless/libertas/wlan_wext.c
@@ -1692,12 +1692,12 @@ static struct iw_statistics *wlan_get_wi
 	};
 	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;
+	u32 tx_retries;
 
 	ENTER();
 
@@ -1707,13 +1707,6 @@ static struct iw_statistics *wlan_get_wi
 	if (Adapter->MediaConnectStatus != WlanMediaStateConnected)
 		goto out;
 
-	/* send RSSI command to get beacon RSSI/NF, valid only if associated */
-	ret = libertas_prepare_and_send_command(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],
@@ -1746,36 +1739,38 @@ static struct iw_statistics *wlan_get_wi
 
 	/* Quality by TX errors */
 	priv->wstats.discard.retries = priv->stats.tx_errors;
-	ret = libertas_prepare_and_send_command(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 = tx_retries;
-		priv->wstats.discard.misc = Adapter->LogMsg.ackfailure;
-	}
+	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 = 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 | IW_QUAL_DBM;
 	stats_valid = 1;
 
+	/* update stats asynchronously for future calls */
+	libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_RSSI, 0, 
+					0, 0, NULL);
+	libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_GET_LOG, 0,
+					0, 0, NULL);
 out:
 	if (!stats_valid) {
 		priv->wstats.miss.beacon = 0;


More information about the Commits-kernel mailing list