|
@@ -1874,127 +1874,92 @@ QDF_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, int8_t *snr)
|
|
return QDF_STATUS_SUCCESS;
|
|
return QDF_STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
|
|
-/**
|
|
|
|
- * hdd_get_link_speed_cb() - Get link speed callback function
|
|
|
|
- * @pLinkSpeed: pointer to the link speed record
|
|
|
|
- * @pContext: pointer to the user context passed to SME
|
|
|
|
- *
|
|
|
|
- * This function is passed as the callback function to
|
|
|
|
- * sme_get_link_speed() by wlan_hdd_get_linkspeed_for_peermac(). By
|
|
|
|
- * agreement a &struct linkspeedContext is passed as @pContext. If
|
|
|
|
- * the context is valid, then the contents of @pLinkSpeed are copied
|
|
|
|
- * into the adapter record referenced by @pContext where they can be
|
|
|
|
- * subsequently retrieved. If the context is invalid, then this
|
|
|
|
- * function does nothing since it is assumed the caller has already
|
|
|
|
- * timed-out and destroyed the context.
|
|
|
|
- *
|
|
|
|
- * Return: None.
|
|
|
|
- */
|
|
|
|
|
|
+struct linkspeed_priv {
|
|
|
|
+ tSirLinkSpeedInfo linkspeed_info;
|
|
|
|
+};
|
|
|
|
+
|
|
static void
|
|
static void
|
|
-hdd_get_link_speed_cb(tSirLinkSpeedInfo *pLinkSpeed, void *pContext)
|
|
|
|
|
|
+hdd_get_link_speed_cb(tSirLinkSpeedInfo *linkspeed_info, void *context)
|
|
{
|
|
{
|
|
- struct linkspeedContext *pLinkSpeedContext;
|
|
|
|
- hdd_adapter_t *pAdapter;
|
|
|
|
|
|
+ struct hdd_request *request;
|
|
|
|
+ struct linkspeed_priv *priv;
|
|
|
|
|
|
- if ((NULL == pLinkSpeed) || (NULL == pContext)) {
|
|
|
|
- hdd_err("Bad param, pLinkSpeed [%p] pContext [%p]",
|
|
|
|
- pLinkSpeed, pContext);
|
|
|
|
|
|
+ if (!linkspeed_info) {
|
|
|
|
+ hdd_err("NULL linkspeed");
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- spin_lock(&hdd_context_lock);
|
|
|
|
- pLinkSpeedContext = pContext;
|
|
|
|
- pAdapter = pLinkSpeedContext->pAdapter;
|
|
|
|
-
|
|
|
|
- /* there is a race condition that exists between this callback
|
|
|
|
- * function and the caller since the caller could time out either
|
|
|
|
- * before or while this code is executing. we use a spinlock to
|
|
|
|
- * serialize these actions
|
|
|
|
- */
|
|
|
|
|
|
|
|
- if ((NULL == pAdapter) ||
|
|
|
|
- (LINK_CONTEXT_MAGIC != pLinkSpeedContext->magic)) {
|
|
|
|
- /* the caller presumably timed out so there is nothing
|
|
|
|
- * we can do
|
|
|
|
- */
|
|
|
|
- spin_unlock(&hdd_context_lock);
|
|
|
|
- hdd_warn("Invalid context, pAdapter [%p] magic [%08x]",
|
|
|
|
- pAdapter, pLinkSpeedContext->magic);
|
|
|
|
|
|
+ request = hdd_request_get(context);
|
|
|
|
+ if (!request) {
|
|
|
|
+ hdd_err("Obsolete request");
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- /* context is valid so caller is still waiting */
|
|
|
|
-
|
|
|
|
- /* paranoia: invalidate the magic */
|
|
|
|
- pLinkSpeedContext->magic = 0;
|
|
|
|
-
|
|
|
|
- /* copy over the stats. do so as a struct copy */
|
|
|
|
- pAdapter->ls_stats = *pLinkSpeed;
|
|
|
|
-
|
|
|
|
- /* notify the caller */
|
|
|
|
- complete(&pLinkSpeedContext->completion);
|
|
|
|
-
|
|
|
|
- /* serialization is complete */
|
|
|
|
- spin_unlock(&hdd_context_lock);
|
|
|
|
|
|
+ priv = hdd_request_priv(request);
|
|
|
|
+ priv->linkspeed_info = *linkspeed_info;
|
|
|
|
+ hdd_request_complete(request);
|
|
|
|
+ hdd_request_put(request);
|
|
}
|
|
}
|
|
|
|
|
|
-/**
|
|
|
|
- * wlan_hdd_get_linkspeed_for_peermac() - Get link speed for a peer
|
|
|
|
- * @pAdapter: adapter upon which the peer is active
|
|
|
|
- * @macAddress: MAC address of the peer
|
|
|
|
- *
|
|
|
|
- * This function will send a query to SME for the linkspeed of the
|
|
|
|
- * given peer, and then wait for the callback to be invoked.
|
|
|
|
- *
|
|
|
|
- * Return: QDF_STATUS_SUCCESS if linkspeed data is available,
|
|
|
|
- * otherwise a QDF_STATUS_E_** error.
|
|
|
|
- */
|
|
|
|
-QDF_STATUS wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *pAdapter,
|
|
|
|
- struct qdf_mac_addr macAddress) {
|
|
|
|
|
|
+int wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *adapter,
|
|
|
|
+ struct qdf_mac_addr *mac_address,
|
|
|
|
+ uint32_t *linkspeed)
|
|
|
|
+{
|
|
|
|
+ int ret;
|
|
QDF_STATUS status;
|
|
QDF_STATUS status;
|
|
- unsigned long rc;
|
|
|
|
- static struct linkspeedContext context;
|
|
|
|
- tSirLinkSpeedInfo linkspeed_req;
|
|
|
|
|
|
+ void *cookie;
|
|
|
|
+ tSirLinkSpeedInfo *linkspeed_info;
|
|
|
|
+ struct hdd_request *request;
|
|
|
|
+ struct linkspeed_priv *priv;
|
|
|
|
+ static const struct hdd_request_params params = {
|
|
|
|
+ .priv_size = sizeof(*priv),
|
|
|
|
+ .timeout_ms = WLAN_WAIT_TIME_STATS,
|
|
|
|
+ };
|
|
|
|
|
|
- if (NULL == pAdapter) {
|
|
|
|
- hdd_err("pAdapter is NULL");
|
|
|
|
- return QDF_STATUS_E_FAULT;
|
|
|
|
|
|
+ if ((!adapter) || (!linkspeed)) {
|
|
|
|
+ hdd_err("NULL argument");
|
|
|
|
+ return -EINVAL;
|
|
}
|
|
}
|
|
- init_completion(&context.completion);
|
|
|
|
- context.pAdapter = pAdapter;
|
|
|
|
- context.magic = LINK_CONTEXT_MAGIC;
|
|
|
|
|
|
|
|
- qdf_copy_macaddr(&linkspeed_req.peer_macaddr, &macAddress);
|
|
|
|
- status = sme_get_link_speed(WLAN_HDD_GET_HAL_CTX(pAdapter),
|
|
|
|
- &linkspeed_req,
|
|
|
|
- &context, hdd_get_link_speed_cb);
|
|
|
|
- if (QDF_STATUS_SUCCESS != status) {
|
|
|
|
|
|
+ request = hdd_request_alloc(¶ms);
|
|
|
|
+ if (!request) {
|
|
|
|
+ hdd_err("Request allocation failure");
|
|
|
|
+ ret = -ENOMEM;
|
|
|
|
+ goto return_cached_value;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ cookie = hdd_request_cookie(request);
|
|
|
|
+ priv = hdd_request_priv(request);
|
|
|
|
+
|
|
|
|
+ linkspeed_info = &priv->linkspeed_info;
|
|
|
|
+ qdf_copy_macaddr(&linkspeed_info->peer_macaddr, mac_address);
|
|
|
|
+ status = sme_get_link_speed(WLAN_HDD_GET_HAL_CTX(adapter),
|
|
|
|
+ linkspeed_info,
|
|
|
|
+ cookie, hdd_get_link_speed_cb);
|
|
|
|
+ if (QDF_IS_STATUS_ERROR(status)) {
|
|
hdd_err("Unable to retrieve statistics for link speed");
|
|
hdd_err("Unable to retrieve statistics for link speed");
|
|
- } else {
|
|
|
|
- rc = wait_for_completion_timeout
|
|
|
|
- (&context.completion,
|
|
|
|
- msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
|
|
|
|
- if (!rc) {
|
|
|
|
- hdd_err("SME timed out while retrieving link speed");
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* either we never sent a request, we sent a request and
|
|
|
|
- * received a response or we sent a request and timed out. if
|
|
|
|
- * we never sent a request or if we sent a request and got a
|
|
|
|
- * response, we want to clear the magic out of paranoia. if
|
|
|
|
- * we timed out there is a race condition such that the
|
|
|
|
- * callback function could be executing at the same time we
|
|
|
|
- * are. of primary concern is if the callback function had
|
|
|
|
- * already verified the "magic" but had not yet set the
|
|
|
|
- * completion variable when a timeout occurred. we serialize
|
|
|
|
- * these activities by invalidating the magic while holding a
|
|
|
|
- * shared spinlock which will cause us to block if the
|
|
|
|
- * callback is currently executing
|
|
|
|
|
|
+ ret = qdf_status_to_os_return(status);
|
|
|
|
+ goto cleanup;
|
|
|
|
+ }
|
|
|
|
+ ret = hdd_request_wait_for_response(request);
|
|
|
|
+ if (ret) {
|
|
|
|
+ hdd_err("SME timed out while retrieving link speed");
|
|
|
|
+ goto cleanup;
|
|
|
|
+ }
|
|
|
|
+ adapter->estimated_linkspeed = linkspeed_info->estLinkSpeed;
|
|
|
|
+
|
|
|
|
+cleanup:
|
|
|
|
+ /*
|
|
|
|
+ * either we never sent a request, we sent a request and
|
|
|
|
+ * received a response or we sent a request and timed out.
|
|
|
|
+ * regardless we are done with the request.
|
|
*/
|
|
*/
|
|
- spin_lock(&hdd_context_lock);
|
|
|
|
- context.magic = 0;
|
|
|
|
- spin_unlock(&hdd_context_lock);
|
|
|
|
- return QDF_STATUS_SUCCESS;
|
|
|
|
|
|
+ hdd_request_put(request);
|
|
|
|
+
|
|
|
|
+return_cached_value:
|
|
|
|
+ *linkspeed = adapter->estimated_linkspeed;
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -2031,17 +1996,16 @@ int wlan_hdd_get_link_speed(hdd_adapter_t *sta_adapter, uint32_t *link_speed)
|
|
/* we are not connected so we don't have a classAstats */
|
|
/* we are not connected so we don't have a classAstats */
|
|
*link_speed = 0;
|
|
*link_speed = 0;
|
|
} else {
|
|
} else {
|
|
- QDF_STATUS status;
|
|
|
|
struct qdf_mac_addr bssid;
|
|
struct qdf_mac_addr bssid;
|
|
|
|
|
|
qdf_copy_macaddr(&bssid, &hdd_stactx->conn_info.bssId);
|
|
qdf_copy_macaddr(&bssid, &hdd_stactx->conn_info.bssId);
|
|
|
|
|
|
- status = wlan_hdd_get_linkspeed_for_peermac(sta_adapter, bssid);
|
|
|
|
- if (!QDF_IS_STATUS_SUCCESS(status)) {
|
|
|
|
|
|
+ ret = wlan_hdd_get_linkspeed_for_peermac(sta_adapter, &bssid,
|
|
|
|
+ link_speed);
|
|
|
|
+ if (ret) {
|
|
hdd_err("Unable to retrieve SME linkspeed");
|
|
hdd_err("Unable to retrieve SME linkspeed");
|
|
- return -EINVAL;
|
|
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
- *link_speed = sta_adapter->ls_stats.estLinkSpeed;
|
|
|
|
/* linkspeed in units of 500 kbps */
|
|
/* linkspeed in units of 500 kbps */
|
|
*link_speed = (*link_speed) / 500;
|
|
*link_speed = (*link_speed) / 500;
|
|
}
|
|
}
|