wlan: add support to return link capacity calculated by firmware
Firmware calculates the Link Capacity, which determines the
maximum throughput current link can support. Add support
in the driver to fetch Link Capacity and return it in an
ioctl.
CRs-Fixed: 483043
Change-Id: I16c2e1fadc7e1166f89fa6d9c302b9b5ee8275a5
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index a577451..aabedd8 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -2607,46 +2607,71 @@
{
hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+ hdd_context_t *pHddCtx;
char *pLinkSpeed = (char*)extra;
- v_U16_t link_speed;
+ v_U32_t link_speed;
unsigned short staId;
- int len = sizeof(v_U16_t)+1;
+ int len = sizeof(v_U32_t)+1;
v_BYTE_t macAddress[VOS_MAC_ADDR_SIZE];
VOS_STATUS status;
- int rc;
+ int rc, valid;
+
+ pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
+
+ valid = wlan_hdd_validate_context(pHddCtx);
+
+ if (0 != valid)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context not valid"));
+ return valid;
+ }
if ( hdd_string_to_hex ((char *)wrqu->data.pointer, wrqu->data.length, macAddress ) )
{
- hddLog(VOS_TRACE_LEVEL_FATAL, "ERROR: Command not found");
+ hddLog(VOS_TRACE_LEVEL_FATAL, FL("ERROR: Command not found"));
return -EINVAL;
}
status = hdd_softap_GetStaId(pHostapdAdapter, (v_MACADDR_t *)macAddress, (void *)(&staId));
- if (!VOS_IS_STATUS_SUCCESS(status ))
+ if (!VOS_IS_STATUS_SUCCESS(status))
{
- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, FL("ERROR: HDD Failed to find sta id!!"));
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("ERROR: HDD Failed to find sta id!!"));
link_speed = 0;
}
else
{
status = wlan_hdd_get_classAstats_for_station(pHostapdAdapter , staId);
+
if (!VOS_IS_STATUS_SUCCESS(status ))
{
- hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve SME statistics", __func__);
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("Unable to retrieve SME statistics"));
return -EINVAL;
}
- link_speed =(int)pHostapdAdapter->hdd_stats.ClassA_stat.tx_rate/2;
+
+ WLANTL_GetSTALinkCapacity(pHddCtx->pvosContext,
+ staId, &link_speed);
+
+ link_speed = link_speed / 10;
+
+ if (0 == link_speed)
+ {
+ /* The linkspeed returned by HAL is in units of 500kbps.
+ * converting it to mbps.
+ * This is required to support legacy firmware which does
+ * not return link capacity.
+ */
+ link_speed =(int)pHostapdAdapter->hdd_stats.ClassA_stat.tx_rate/2;
+ }
}
wrqu->data.length = len;
- rc = snprintf(pLinkSpeed, len, "%u", link_speed);
+ rc = snprintf(pLinkSpeed, len, "%lu", link_speed);
+
if ((rc < 0) || (rc >= len))
{
// encoding or length error?
- hddLog(VOS_TRACE_LEVEL_ERROR,
- "%s: Unable to encode link speed, got [%s]",
- __func__, pLinkSpeed);
+ hddLog(VOS_TRACE_LEVEL_ERROR,FL( "Unable to encode link speed"));
return -EIO;
}
@@ -2768,7 +2793,7 @@
IW_PRIV_TYPE_BYTE | QCSAP_MAX_WSC_IE, 0, "ap_stats" },
{ QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED,
IW_PRIV_TYPE_CHAR | 18,
- IW_PRIV_TYPE_CHAR | 3, "getLinkSpeed" },
+ IW_PRIV_TYPE_CHAR | 5, "getLinkSpeed" },
{ QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "" },
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index 69660cb..9ae360c 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -2329,17 +2329,22 @@
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *pHddCtx;
char *pLinkSpeed = (char*)extra;
- int len = sizeof(v_U16_t) + 1;
- v_U16_t link_speed;
+ int len = sizeof(v_U32_t) + 1;
+ v_U32_t link_speed;
hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
- int rc;
+ VOS_STATUS status;
+ int rc, valid;
- if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
+ pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+
+ valid = wlan_hdd_validate_context(pHddCtx);
+
+ if (0 != valid)
{
- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
- "%s:LOGP in Progress. Ignore!!!", __func__);
- return -EBUSY;
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid"));
+ return valid;
}
if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
@@ -2349,21 +2354,40 @@
}
else
{
- wlan_hdd_get_classAstats(pAdapter);
- //The linkspeed returned by HAL is in units of 500kbps.
- //converting it to mbps
- link_speed = pAdapter->hdd_stats.ClassA_stat.tx_rate/2;
+ status = wlan_hdd_get_classAstats(pAdapter);
+
+ if (!VOS_IS_STATUS_SUCCESS(status ))
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("Unable to retrieve SME statistics"));
+ return -EINVAL;
+ }
+
+ /* Unit of link capacity is obtained from the TL API is MbpsX10 */
+ WLANTL_GetSTALinkCapacity(WLAN_HDD_GET_CTX(pAdapter)->pvosContext,
+ (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
+ &link_speed);
+
+ link_speed = link_speed / 10;
+
+ if (0 == link_speed)
+ {
+ /* The linkspeed returned by HAL is in units of 500kbps.
+ * converting it to mbps.
+ * This is required to support legacy firmware which does
+ * not return link capacity.
+ */
+ link_speed = pAdapter->hdd_stats.ClassA_stat.tx_rate/2;
+ }
+
}
wrqu->data.length = len;
// return the linkspeed in the format required by the WiFi Framework
- rc = snprintf(pLinkSpeed, len, "%u", link_speed);
+ rc = snprintf(pLinkSpeed, len, "%lu", link_speed);
if ((rc < 0) || (rc >= len))
{
// encoding or length error?
- hddLog(VOS_TRACE_LEVEL_ERROR,
- "%s: Unable to encode link speed, got [%s]",
- __func__,pLinkSpeed);
+ hddLog(VOS_TRACE_LEVEL_ERROR,FL("Unable to encode link speed"));
return -EIO;
}
@@ -6890,7 +6914,7 @@
{
WLAN_GET_LINK_SPEED,
IW_PRIV_TYPE_CHAR | 18,
- IW_PRIV_TYPE_CHAR | 3, "getLinkSpeed" },
+ IW_PRIV_TYPE_CHAR | 5, "getLinkSpeed" },
};
diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c
index 28acdc7..56de945 100644
--- a/CORE/SME/src/csr/csrApiRoam.c
+++ b/CORE/SME/src/csr/csrApiRoam.c
@@ -13829,6 +13829,7 @@
v_PVOID_t pvosGCtx;
v_S7_t rssi = 0;
tANI_U32 *pRssi = NULL;
+ tANI_U32 linkCapacity;
pSmeStatsRsp = (tAniGetPEStatsRsp *)pSirMsg;
if(pSmeStatsRsp->rc)
{
@@ -13926,13 +13927,27 @@
{
pRssi = (tANI_U32*)pStats;
rssi = (v_S7_t)*pRssi;
+ pStats += sizeof(tANI_U32);
+ length -= sizeof(tANI_U32);
}
else
{
/* If riva is not sending rssi, continue to use the hack */
rssi = RSSI_HACK_BMPS;
}
+
WDA_UpdateRssiBmps(pvosGCtx, pSmeStatsRsp->staId, rssi);
+
+ if (length != 0)
+ {
+ linkCapacity = *(tANI_U32*)pStats;
+ }
+ else
+ {
+ linkCapacity = 0;
+ }
+
+ WDA_UpdateLinkCapacity(pvosGCtx, pSmeStatsRsp->staId, linkCapacity);
post_update:
//make sure to update the pe stats req list
pEntry = csrRoamFindInPeStatsReqList(pMac, pSmeStatsRsp->statsMask);
diff --git a/CORE/TL/inc/wlan_qct_tl.h b/CORE/TL/inc/wlan_qct_tl.h
index bf48b51..00209bb 100644
--- a/CORE/TL/inc/wlan_qct_tl.h
+++ b/CORE/TL/inc/wlan_qct_tl.h
@@ -2666,4 +2666,74 @@
+/*===============================================================================
+ FUNCTION WLANTL_UpdateLinkCapacity
+
+ DESCRIPTION This function updates the STA's Link Capacity in TL
+
+ DEPENDENCIES None
+
+ PARAMETERS
+
+ pvosGCtx VOS context VOS Global context
+ staId Station ID Station ID
+ linkCapacity linkCapacity Link Capacity
+
+ RETURN None
+
+ SIDE EFFECTS none
+ ===============================================================================*/
+
+void
+WLANTL_UpdateLinkCapacity
+(
+ v_PVOID_t pvosGCtx,
+ v_U8_t staId,
+ v_U32_t linkCapacity);
+
+/*===========================================================================
+
+ FUNCTION WLANTL_GetSTALinkCapacity
+
+ DESCRIPTION
+
+ Returns Link Capacity of a particular STA.
+
+ DEPENDENCIES
+
+ A station must have been registered before its state can be retrieved.
+
+
+ PARAMETERS
+
+ IN
+ pvosGCtx: pointer to the global vos context; a handle to TL's
+ control block can be extracted from its context
+ ucSTAId: identifier of the station
+
+ OUT
+ plinkCapacity: the current link capacity the connection to
+ the given station
+
+
+ RETURN VALUE
+
+ The result code associated with performing the operation
+
+ VOS_STATUS_E_INVAL: Input parameters are invalid
+ VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to
+ TL cb is NULL ; access would cause a page fault
+ VOS_STATUS_E_EXISTS: Station was not registered
+ VOS_STATUS_SUCCESS: Everything is good :)
+
+ SIDE EFFECTS
+
+============================================================================*/
+VOS_STATUS
+WLANTL_GetSTALinkCapacity
+(
+ v_PVOID_t pvosGCtx,
+ v_U8_t ucSTAId,
+ v_U32_t *plinkCapacity
+);
#endif /* #ifndef WLAN_QCT_WLANTL_H */
diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c
index 0716816..7879c26 100644
--- a/CORE/TL/src/wlan_qct_tl.c
+++ b/CORE/TL/src/wlan_qct_tl.c
@@ -11789,3 +11789,131 @@
pTLCb->atlSTAClients[staId]->rssiAvgBmps = rssi;
}
}
+
+/*===============================================================================
+ FUNCTION WLANTL_UpdateLinkCapacity
+
+ DESCRIPTION This function updates the STA's Link Capacity in TL
+
+ DEPENDENCIES None
+
+ PARAMETERS
+
+ pvosGCtx VOS context VOS Global context
+ staId Station ID Station ID
+ linkCapacity linkCapacity Link Capacity
+
+ RETURN None
+
+ SIDE EFFECTS none
+ ===============================================================================*/
+
+void WLANTL_UpdateLinkCapacity(v_PVOID_t pvosGCtx, v_U8_t staId, v_U32_t linkCapacity)
+{
+ WLANTL_CbType* pTLCb = VOS_GET_TL_CB(pvosGCtx);
+
+ if (NULL != pTLCb && NULL != pTLCb->atlSTAClients[staId])
+ {
+ pTLCb->atlSTAClients[staId]->linkCapacity = linkCapacity;
+ }
+}
+
+
+/*===========================================================================
+
+ FUNCTION WLANTL_GetSTALinkCapacity
+
+ DESCRIPTION
+
+ Returns Link Capacity of a particular STA.
+
+ DEPENDENCIES
+
+ A station must have been registered before its state can be retrieved.
+
+
+ PARAMETERS
+
+ IN
+ pvosGCtx: pointer to the global vos context; a handle to TL's
+ control block can be extracted from its context
+ ucSTAId: identifier of the station
+
+ OUT
+ plinkCapacity: the current link capacity the connection to
+ the given station
+
+
+ RETURN VALUE
+
+ The result code associated with performing the operation
+
+ VOS_STATUS_E_INVAL: Input parameters are invalid
+ VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to
+ TL cb is NULL ; access would cause a page fault
+ VOS_STATUS_E_EXISTS: Station was not registered
+ VOS_STATUS_SUCCESS: Everything is good :)
+
+ SIDE EFFECTS
+
+============================================================================*/
+VOS_STATUS
+WLANTL_GetSTALinkCapacity
+(
+ v_PVOID_t pvosGCtx,
+ v_U8_t ucSTAId,
+ v_U32_t *plinkCapacity
+)
+{
+ WLANTL_CbType* pTLCb = NULL;
+ /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+ /*------------------------------------------------------------------------
+ Sanity check
+ ------------------------------------------------------------------------*/
+ if ( NULL == plinkCapacity )
+ {
+ TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+ FL("WLAN TL:Invalid parameter")));
+ return VOS_STATUS_E_INVAL;
+ }
+
+ if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
+ {
+ TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+ FL("WLAN TL:Invalid station id")));
+ return VOS_STATUS_E_FAULT;
+ }
+
+ /*------------------------------------------------------------------------
+ Extract TL control block and check existance
+ ------------------------------------------------------------------------*/
+ pTLCb = VOS_GET_TL_CB(pvosGCtx);
+ if ( NULL == pTLCb )
+ {
+ TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+ FL("WLAN TL:Invalid TL pointer from pvosGCtx")));
+ return VOS_STATUS_E_FAULT;
+ }
+
+ if ( NULL == pTLCb->atlSTAClients[ucSTAId] )
+ {
+ TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+ FL("WLAN TL:Client Memory was not allocated")));
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ if ( 0 == pTLCb->atlSTAClients[ucSTAId]->ucExists )
+ {
+ TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
+ FL("WLAN TL:Station was not previously registered")));
+ return VOS_STATUS_E_EXISTS;
+ }
+
+ /*------------------------------------------------------------------------
+ Get STA state
+ ------------------------------------------------------------------------*/
+ *plinkCapacity = pTLCb->atlSTAClients[ucSTAId]->linkCapacity;
+
+ return VOS_STATUS_SUCCESS;
+}/* WLANTL_GetSTALinkCapacity */
diff --git a/CORE/TL/src/wlan_qct_tli.h b/CORE/TL/src/wlan_qct_tli.h
index a8fa010..e6cd5b1 100644
--- a/CORE/TL/src/wlan_qct_tli.h
+++ b/CORE/TL/src/wlan_qct_tli.h
@@ -39,6 +39,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+
#ifndef WLAN_QCT_TLI_H
#define WLAN_QCT_TLI_H
@@ -52,8 +53,6 @@
This file contains the internal declarations used within wlan transport
layer module.
- Copyright (c) 2008 QUALCOMM Incorporated. All Rights Reserved.
- Qualcomm Confidential and Proprietary
===========================================================================*/
@@ -636,6 +635,8 @@
1 then we have to encrypt the data irrespective of TL
state (CONNECTED/AUTHENTICATED) */
v_U8_t ptkInstalled;
+
+ v_U32_t linkCapacity;
}WLANTL_STAClientType;
/*---------------------------------------------------------------------------
diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h
index 6443ebb..d930d64 100644
--- a/CORE/WDA/inc/wlan_qct_wda.h
+++ b/CORE/WDA/inc/wlan_qct_wda.h
@@ -1122,6 +1122,9 @@
#define WDA_UpdateRssiBmps(pvosGCtx, staId, rssi) \
WLANTL_UpdateRssiBmps(pvosGCtx, staId, rssi)
+#define WDA_UpdateLinkCapacity(pvosGCtx, staId, linkCapacity) \
+ WLANTL_UpdateLinkCapacity(pvosGCtx, staId, linkCapacity)
+
#ifdef WLAN_PERF
/*==========================================================================
FUNCTION WDA_TLI_FastHwFwdDataFrame
diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c
index 478863b..4f4104b 100644
--- a/CORE/WDA/src/wlan_qct_wda.c
+++ b/CORE/WDA/src/wlan_qct_wda.c
@@ -4920,7 +4920,6 @@
pGetPEStatsRspParams->msgType = wdiGetStatsRsp->usMsgType;
pGetPEStatsRspParams->msgLen = sizeof(tAniGetPEStatsRsp) +
(wdiGetStatsRsp->usMsgLen - sizeof(WDI_GetStatsRspParamsType));
- pGetPEStatsRspParams->msgLen = wdiGetStatsRsp->usMsgLen + sizeof(tANI_U8);
//Fill the Session Id Properly in PE
pGetPEStatsRspParams->sessionId = 0;