Subject: Correct the cfg80211 bss signal strenth format

BOO # 10279 - Strength in list-service is always 100, which is wrong

ar6003_cfg80211_rssi_signal_fix.patch is based on  an accepted patch -
kernel-adaptation-mrst-2.6.37.6-92.2 and ar6003_cfg_syncup_v2.patch.

Signed-off-by: Samuel Chang <samu...@qca.qualcomm.com>
diff -ruN kernel-2.6.37.6-92.2/drivers/staging/ar6003/include/common/wmi.h kernel-2.6.37.6-92.2_cfg80211_fix_patch/drivers/staging/ar6003/include/common/wmi.h
--- kernel-2.6.37.6-92.2/drivers/staging/ar6003/include/common/wmi.h	2011-06-15 02:06:12.863498128 +0800
+++ kernel-2.6.37.6-92.2_cfg80211_fix_patch/drivers/staging/ar6003/include/common/wmi.h	2011-06-29 08:31:52.440455388 +0800
@@ -552,6 +552,11 @@
     LEAP_AUTH           = 0x04,  /* different from IEEE_AUTH_MODE definitions */
 } DOT11_AUTH_MODE;
 
+enum {
+	AUTH_IDLE,
+	AUTH_OPEN_IN_PROGRESS,
+};
+
 typedef enum {
     NONE_AUTH           = 0x01,
     WPA_AUTH            = 0x02,
diff -ruN kernel-2.6.37.6-92.2/drivers/staging/ar6003/os/linux/ar6000_drv.c kernel-2.6.37.6-92.2_cfg80211_fix_patch/drivers/staging/ar6003/os/linux/ar6000_drv.c
--- kernel-2.6.37.6-92.2/drivers/staging/ar6003/os/linux/ar6000_drv.c	2011-06-15 02:06:12.859498118 +0800
+++ kernel-2.6.37.6-92.2_cfg80211_fix_patch/drivers/staging/ar6003/os/linux/ar6000_drv.c	2011-06-29 09:34:20.847042734 +0800
@@ -1946,6 +1946,8 @@
         SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy));
         wdev->netdev = dev;
         arPriv->arNetworkType = INFRA_NETWORK;
+        ar->smeState = SME_DISCONNECTED;
+		 arPriv->arAutoAuthStage = AUTH_IDLE;
 #endif /* ATH6K_CONFIG_CFG80211 */
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
diff -ruN kernel-2.6.37.6-92.2/drivers/staging/ar6003/os/linux/cfg80211.c kernel-2.6.37.6-92.2_cfg80211_fix_patch/drivers/staging/ar6003/os/linux/cfg80211.c
--- kernel-2.6.37.6-92.2/drivers/staging/ar6003/os/linux/cfg80211.c	2011-06-28 20:57:34.000000000 +0800
+++ kernel-2.6.37.6-92.2_cfg80211_fix_patch/drivers/staging/ar6003/os/linux/cfg80211.c	2011-06-29 11:09:42.519414972 +0800
@@ -169,6 +169,10 @@
     case NL80211_AUTHTYPE_NETWORK_EAP:
         arPriv->arDot11AuthMode = LEAP_AUTH;
         break;
+	case NL80211_AUTHTYPE_AUTOMATIC:
+        arPriv->arDot11AuthMode = OPEN_AUTH;
+        arPriv->arAutoAuthStage = AUTH_OPEN_IN_PROGRESS;
+        break;
     default:
         arPriv->arDot11AuthMode = OPEN_AUTH;
         AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
@@ -249,6 +253,7 @@
     unsigned char *ie = sme->ie;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
+	ar->smeState = SME_CONNECTING;
 
     if(ar->arWmiReady == FALSE) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready yet\n", __func__));
@@ -302,12 +307,6 @@
             return -EINTR;
         }
     }
-    up(&arPriv->arPrivSem);
-    
-    if(down_interruptible(&arPriv->arPrivSem)) {
-        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, couldn't get access\n", __func__));
-        return -ERESTARTSYS;
-    }
 
     if(arPriv->arConnected == TRUE &&
        arPriv->arSsidLen == sme->ssid_len &&
@@ -316,7 +315,9 @@
         status = wmi_reconnect_cmd(arPriv->arWmi,
                                    arSta->arReqBssid,
                                    arPriv->arChannelHint);
-        
+
+		up(&arPriv->arPrivSem);
+
         if (status != A_OK) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_reconnect_cmd failed\n", __func__));
             return -EIO;
@@ -461,6 +462,7 @@
     unsigned char *ptr_ie_buf = ie_buf;
     unsigned char *ieeemgmtbuf = NULL;
     A_UINT8 source_mac[ATH_MAC_LEN];
+    AR_SOFTC_T     *ar     = arPriv->arSoftc;
 
     A_UINT8 assocReqIeOffset = sizeof(A_UINT16)  +  /* capinfo*/
                                sizeof(A_UINT16);    /* listen interval */
@@ -474,6 +476,7 @@
 
     assocReqLen -= assocReqIeOffset;
     assocRespLen -= assocRespIeOffset;
+    arPriv->arAutoAuthStage = AUTH_IDLE;
 
     if((ADHOC_NETWORK & networkType)) {
         if(NL80211_IFTYPE_ADHOC != arPriv->wdev->iftype) {
@@ -502,7 +505,15 @@
                            ((ADHOC_NETWORK & networkType) ? WLAN_CAPABILITY_IBSS : WLAN_CAPABILITY_ESS),
                            ((ADHOC_NETWORK & networkType) ? WLAN_CAPABILITY_IBSS : WLAN_CAPABILITY_ESS));
 
-    if(!bss) {
+	/*
+	 * Earlier we were updating the cfg about bss by making a beacon frame
+	 * only if the entry for bss is not there. This can have some issue if
+	 * ROAM event is generated and a heavy traffic is ongoing. The ROAM
+	 * event is handled through a work queue and by the time it really gets
+	 * handled, BSS would have been aged out. So it is better to update the
+	 * cfg about BSS irrespective of its entry being present right now or
+	 * not.
+	 */
         if (ADHOC_NETWORK & networkType) {
             /* construct 802.11 mgmt beacon */
             if(ptr_ie_buf) {
@@ -543,6 +554,7 @@
         if(!ieeemgmtbuf) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                             ("%s: ieeeMgmtbuf alloc error\n", __func__));
+		 cfg80211_put_bss(bss);
             return;
         }
 
@@ -572,7 +584,6 @@
                                         signal, GFP_ATOMIC);
         A_FREE(ieeemgmtbuf);
         cfg80211_put_bss(bss);
-    }
 
     if((ADHOC_NETWORK & networkType)) {
         cfg80211_ibss_joined(arPriv->arNetDev, bssid, GFP_ATOMIC);
@@ -581,6 +592,7 @@
 
     if (FALSE == arPriv->arConnected) {
         /* inform connect result to cfg80211 */
+		 ar->smeState = SME_DISCONNECTED;
         cfg80211_connect_result(arPriv->arNetDev, bssid,
                                 assocReqIe, assocReqLen,
                                 assocRespIe, assocRespLen,
@@ -642,6 +654,14 @@
                                A_UINT8 *bssid, A_UINT8 assocRespLen,
                                A_UINT8 *assocInfo, A_UINT16 protocolReasonStatus)
 {
+    A_UINT16 status;
+	AR_SOFTC_STA_T *arSta  = &arPriv->arSta;
+	AR_SOFTC_T *ar = (AR_SOFTC_T *)arPriv->arSoftc;
+
+	if (arPriv->scan_request) {
+		cfg80211_scan_done(arPriv->scan_request, true);
+        arPriv->scan_request = NULL;
+    }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: reason=%u\n", __func__, reason));
 
@@ -664,18 +684,74 @@
         }
     }
 
-    if(FALSE == arPriv->arConnected) {
+	if(true == arSta->arConnectPending) {
         if(NO_NETWORK_AVAIL == reason) {
             /* connect cmd failed */
-            cfg80211_connect_result(arPriv->arNetDev, bssid,
-                                    NULL, 0,
-                                    NULL, 0,
-                                    WLAN_STATUS_UNSPECIFIED_FAILURE,
-                                    GFP_ATOMIC);
-        }
+            wmi_disconnect_cmd(arPriv->arWmi);
+        } else if (reason == DISCONNECT_CMD) {
+		if (arPriv->arAutoAuthStage) {
+			/*
+			 * If the current auth algorithm is open try shared
+			 * and make autoAuthStage idle. We do not make it
+			 * leap for now being.
+			 */
+			if (arPriv->arDot11AuthMode == OPEN_AUTH) {
+				struct ar_key *key = NULL;
+				key = &arPriv->keys[arPriv->arDefTxKeyIndex];
+				if (down_interruptible(&ar->arSem)) {
+					AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, couldn't get access\n", __func__));
+					return;
+				}
+
+				arPriv->arDot11AuthMode = SHARED_AUTH;
+				arPriv->arAutoAuthStage = AUTH_IDLE;
+
+				wmi_addKey_cmd(arPriv->arWmi, arPriv->arDefTxKeyIndex,
+						arPriv->arPairwiseCrypto,
+						GROUP_USAGE | TX_USAGE,
+						key->key_len,
+						NULL,
+						key->key, KEY_OP_INIT_VAL, NULL,
+						NO_SYNC_WMIFLAG);
+
+				status = wmi_connect_cmd(arPriv->arWmi,
+							 arPriv->arNetworkType,
+							 arPriv->arDot11AuthMode,
+							 arPriv->arAuthMode,
+							 arPriv->arPairwiseCrypto,
+							 arPriv->arPairwiseCryptoLen,
+							 arPriv->arGroupCrypto,
+							 arPriv->arGroupCryptoLen,
+							 arPriv->arSsidLen,
+							 arPriv->arSsid,
+							 arSta->arReqBssid,
+							 arPriv->arChannelHint,
+							 arSta->arConnectCtrlFlags);
+				up(&ar->arSem);
+
+			} else if (arPriv->arDot11AuthMode == SHARED_AUTH) {
+				/* should not reach here */
+			}
+		} else {
+			arSta->arConnectPending = false;
+			if (ar->smeState == SME_CONNECTING) {
+				cfg80211_connect_result(arPriv->arNetDev, bssid,
+							NULL, 0,
+							NULL, 0,
+							WLAN_STATUS_UNSPECIFIED_FAILURE,
+							GFP_ATOMIC);
+			} else {
+				cfg80211_disconnected(arPriv->arNetDev,
+						      reason,
+						      NULL, 0,
+						      GFP_ATOMIC);
+			}
+			ar->smeState = SME_DISCONNECTED;
+		}
+	}
     } else {
-        /* connection loss due to disconnect cmd or low rssi */
-        cfg80211_disconnected(arPriv->arNetDev, reason, NULL, 0, GFP_ATOMIC);
+	    if (reason != DISCONNECT_CMD)
+		    wmi_disconnect_cmd(arPriv->arWmi);
     }
 }
 
@@ -812,10 +888,11 @@
     if(arPriv->scan_request)
     {
         /* Translate data to cfg80211 mgmt format */
+	if (arPriv->arWmi)
         wmi_iterate_nodes(arPriv->arWmi, ar6k_cfg80211_scan_node, arPriv->wdev->wiphy);
 
-        cfg80211_scan_done(arPriv->scan_request,
-                          (status & A_ECANCELED) ? true : false);
+	cfg80211_scan_done(arPriv->scan_request,
+            ((status & A_ECANCELED) || (status & A_EBUSY)) ? true : false);
 
         if(arPriv->scan_request->n_ssids &&
            arPriv->scan_request->ssids[0].ssid_len) {
@@ -1026,6 +1103,7 @@
     AR_SOFTC_T     *ar     = arPriv->arSoftc;
     struct ar_key *key = NULL;
     A_STATUS status = A_OK;
+    u8 key_usage;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index));
 
@@ -1052,17 +1130,20 @@
         return -EINVAL;
     }
 
-	 if (arPriv->arAuthMode < WPA_AUTH) {
-    	arPriv->arDefTxKeyIndex = key_index;
-    	key = &arPriv->keys[arPriv->arDefTxKeyIndex];
-    	status = wmi_addKey_cmd(arPriv->arWmi, arPriv->arDefTxKeyIndex,
-                            arPriv->arPairwiseCrypto, GROUP_USAGE | TX_USAGE,
+    key_usage = GROUP_USAGE;
+    if (WEP_CRYPT == arPriv->arPairwiseCrypto) {
+        key_usage |= TX_USAGE;
+    }
+
+    arPriv->arDefTxKeyIndex = key_index;
+    key = &arPriv->keys[arPriv->arDefTxKeyIndex];
+    status = wmi_addKey_cmd(arPriv->arWmi, arPriv->arDefTxKeyIndex,
+                            arPriv->arPairwiseCrypto, key_usage,
                             key->key_len, key->seq, key->key, KEY_OP_INIT_VAL,
                             NULL, SYNC_BOTH_WMIFLAG);
-    	if (status != A_OK) {
-        	return -EIO;
-    	}
-	}
+    if (status != A_OK) {
+        return -EIO;
+    }
     return 0;
 }
 
@@ -1469,6 +1550,152 @@
     WLAN_CIPHER_SUITE_CCMP,
 };
 
+bool is_rate_legacy(s32 rate)
+{
+	static const s32 legacy[] = { 1000, 2000, 5500, 11000,
+				      6000, 9000, 12000, 18000, 24000,
+				      36000, 48000, 54000 };
+	u8 i;
+
+	for (i = 0; i < ARRAY_SIZE(legacy); i++) {
+		if (rate == legacy[i])
+			return true;
+	}
+
+	return false;
+}
+
+bool is_rate_ht20(s32 rate, u8 *mcs, bool *sgi)
+{
+	static const s32 ht20[] = { 6500, 13000, 19500, 26000, 39000,
+				    52000, 58500, 65000, 72200 };
+	u8 i;
+
+	for (i = 0; i < ARRAY_SIZE(ht20); i++) {
+		if (rate == ht20[i]) {
+			if (i == ARRAY_SIZE(ht20) - 1)
+				/* last rate uses sgi */
+				*sgi = true;
+			else
+				*sgi = false;
+
+			*mcs = i;
+			return true;
+		}
+	}
+	return false;
+}
+
+bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi)
+{
+	static const s32 ht40[] = { 13500, 27000, 40500, 54000,
+				    81000, 108000, 121500, 135000,
+				    150000 };
+	u8 i;
+
+	for (i = 0; i < ARRAY_SIZE(ht40); i++) {
+		if (rate == ht40[i]) {
+			if (i == ARRAY_SIZE(ht40) - 1)
+				/* last rate uses sgi */
+				*sgi = true;
+			else
+				*sgi = false;
+
+			*mcs = i;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static int ar6k_get_station(struct wiphy *wiphy, struct net_device *dev,
+			    u8 *mac, struct station_info *sinfo)
+{
+	AR_SOFTC_DEV_T *arPriv = (AR_SOFTC_DEV_T *)ar6k_priv(dev);
+	AR_SOFTC_T     *ar     = arPriv->arSoftc;
+	long left;
+	bool sgi;
+	s32 rate;
+	int ret;
+	u8 mcs;
+
+	if (memcmp(mac, arPriv->arBssid, ETH_ALEN) != 0)
+		return -ENOENT;
+
+	if (down_interruptible(&ar->arSem))
+		return -EBUSY;
+
+	arPriv->statsUpdatePending = true;
+
+	ret = wmi_get_stats_cmd(arPriv->arWmi);
+
+	if (ret != 0) {
+		up(&ar->arSem);
+		return -EIO;
+	}
+
+	left = wait_event_interruptible_timeout(arPriv->arEvent,
+						arPriv->statsUpdatePending == false,
+						wmitimeout * HZ);
+
+	up(&ar->arSem);
+
+	if (left == 0)
+		return -ETIMEDOUT;
+	else if (left < 0)
+		return left;
+
+	if (arPriv->arTargetStats.rx_bytes) {
+		sinfo->rx_bytes = arPriv->arTargetStats.rx_bytes;
+		sinfo->filled |= STATION_INFO_RX_BYTES;
+		sinfo->rx_packets = arPriv->arTargetStats.rx_packets;
+		sinfo->filled |= STATION_INFO_RX_PACKETS;
+	}
+
+	if (arPriv->arTargetStats.tx_bytes) {
+		sinfo->tx_bytes = arPriv->arTargetStats.tx_bytes;
+		sinfo->filled |= STATION_INFO_TX_BYTES;
+		sinfo->tx_packets = arPriv->arTargetStats.tx_packets;
+		sinfo->filled |= STATION_INFO_TX_PACKETS;
+	}
+
+	sinfo->signal = arPriv->arTargetStats.cs_rssi;
+	sinfo->filled |= STATION_INFO_SIGNAL;
+
+	rate = arPriv->arTargetStats.tx_unicast_rate;
+
+	if (is_rate_legacy(rate)) {
+		sinfo->txrate.legacy = rate / 100;
+	} else if (is_rate_ht20(rate, &mcs, &sgi)) {
+		if (sgi) {
+			sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+			sinfo->txrate.mcs = mcs - 1;
+		} else {
+			sinfo->txrate.mcs = mcs;
+		}
+
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+	} else if (is_rate_ht40(rate, &mcs, &sgi)) {
+		if (sgi) {
+			sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+			sinfo->txrate.mcs = mcs - 1;
+		} else {
+			sinfo->txrate.mcs = mcs;
+		}
+
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+	} else {
+		WARN(1, "invalid rate: %d", rate);
+		return 0;
+	}
+
+	sinfo->filled |= STATION_INFO_TX_BITRATE;
+
+	return 0;
+}
+
 static struct
 cfg80211_ops ar6k_cfg80211_ops = {
     .change_virtual_intf = ar6k_cfg80211_change_iface,
@@ -1489,6 +1716,7 @@
     .set_power_mgmt = ar6k_cfg80211_set_power_mgmt,
     .join_ibss = ar6k_cfg80211_join_ibss,
     .leave_ibss = ar6k_cfg80211_leave_ibss,
+    .get_station = ar6k_get_station,
 };
 
 struct wireless_dev *
diff -ruN kernel-2.6.37.6-92.2/drivers/staging/ar6003/os/linux/include/ar6000_drv.h kernel-2.6.37.6-92.2_cfg80211_fix_patch/drivers/staging/ar6003/os/linux/include/ar6000_drv.h
--- kernel-2.6.37.6-92.2/drivers/staging/ar6003/os/linux/include/ar6000_drv.h	2011-06-15 02:06:12.863498128 +0800
+++ kernel-2.6.37.6-92.2_cfg80211_fix_patch/drivers/staging/ar6003/os/linux/include/ar6000_drv.h	2011-06-29 08:32:44.112711621 +0800
@@ -427,6 +427,13 @@
     A_UINT8     seq_len;
     A_UINT32    cipher;
 };
+
+enum {
+    SME_DISCONNECTED,
+    SME_CONNECTING,
+    SME_CONNECTED
+};
+
 #endif /* ATH6K_CONFIG_CFG80211 */
 
 
@@ -574,6 +581,7 @@
     A_UINT8                 rxMetaVersion;
     A_INT32                 (*exitCallback)(void *config);  /* generic callback at AR6K exit */
     HIF_DEVICE_OS_DEVICE_INFO   osDevInfo;
+    A_UINT32                smeState;
     A_UINT16                arWlanPowerState;
     A_BOOL                  arPlatPowerOff;
     USER_RSSI_CPENSATION    rssi_compensation_param;
@@ -729,6 +737,7 @@
     AR_SOFTC_T              *arSoftc;
     A_UINT8                 arHoldConnection;
     A_UINT8                 num_sta;
+    A_UINT8                 arAutoAuthStage;
 }AR_SOFTC_DEV_T;
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
Subject: Correct the cfg80211 bss signal strenth format

Signed-off-by: Samuel Chang <samu...@qca.qualcomm.com>

diff -ruN kernel-2.6.37.6-24.3_cfg80211_fix_patch_1/drivers/staging/ar6003/os/linux/cfg80211.c kernel-2.6.37.6-24.3_cfg80211_rssi_patch_1.1/drivers/staging/ar6003/os/linux/cfg80211.c
--- kernel-2.6.37.6-24.3_cfg80211_fix_patch_1/drivers/staging/ar6003/os/linux/cfg80211.c	2011-06-29 11:09:42.519414000 +0800
+++ kernel-2.6.37.6-24.3_cfg80211_rssi_patch_1.1/drivers/staging/ar6003/os/linux/cfg80211.c	2011-07-06 14:58:11.257184423 +0800
@@ -804,7 +804,7 @@
 
     freq    = cie->ie_chan;
     channel = ieee80211_get_channel(wiphy, freq);
-    signal  = ni->ni_snr * 100;
+    signal  = ni->ni_snr * 100 - 9500;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
                     ("%s: bssid %02x:%02x:%02x:%02x:%02x:%02x channel %d freq %d size %d\n",
_______________________________________________
MeeGo-kernel mailing list
MeeGo-kernel@lists.meego.com
http://lists.meego.com/listinfo/meego-kernel

Reply via email to