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