Przeglądaj źródła

qcacld-3.0: Use request manager for linkspeed

We are transitioning to the new request manager framework. Change
wlan_hdd_get_linkspeed_for_peermac() and hdd_get_link_speed_cb() to
this framework. Note that this framework provides the infrastructure
to pass data from the response thread to the request thread and hence
eliminates the need to maintain tSirLinkSpeedInfo in the HDD adapter
struct.

Change-Id: I27cdbb986b23c4895f7e6e444697994f26bc6ea1
CRs-Fixed: 2005313
Jeff Johnson 8 lat temu
rodzic
commit
e50427c7a8

+ 3 - 9
core/hdd/inc/wlan_hdd_main.h

@@ -309,15 +309,8 @@
  * threads will be serialized.
  * threads will be serialized.
  */
  */
 
 
-struct linkspeedContext {
-	struct completion completion;
-	hdd_adapter_t *pAdapter;
-	unsigned int magic;
-};
-
 extern spinlock_t hdd_context_lock;
 extern spinlock_t hdd_context_lock;
 
 
-#define LINK_CONTEXT_MAGIC  0x4C494E4B  /* LINKSPEED */
 #define BPF_CONTEXT_MAGIC 0x4575354    /* BPF */
 #define BPF_CONTEXT_MAGIC 0x4575354    /* BPF */
 
 
 /* MAX OS Q block time value in msec
 /* MAX OS Q block time value in msec
@@ -962,8 +955,9 @@ struct hdd_adapter_s {
 	struct net_device_stats stats;
 	struct net_device_stats stats;
 	/** HDD statistics*/
 	/** HDD statistics*/
 	hdd_stats_t hdd_stats;
 	hdd_stats_t hdd_stats;
-	/** linkspeed statistics */
-	tSirLinkSpeedInfo ls_stats;
+
+	/* estimated link speed */
+	uint32_t estimated_linkspeed;
 
 
 	uint8_t sessionId;
 	uint8_t sessionId;
 
 

+ 14 - 2
core/hdd/inc/wlan_hdd_wext.h

@@ -355,8 +355,20 @@ extern int hdd_priv_get_data(struct iw_point *p_priv_data,
 
 
 extern void *mem_alloc_copy_from_user_helper(const void *wrqu_data, size_t len);
 extern void *mem_alloc_copy_from_user_helper(const void *wrqu_data, size_t len);
 
 
-extern QDF_STATUS wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *pAdapter,
-					     struct qdf_mac_addr mac_address);
+/**
+ * wlan_hdd_get_linkspeed_for_peermac() - Get link speed for a peer
+ * @adapter: adapter upon which the peer is active
+ * @mac_address: MAC address of the peer
+ * @linkspeed: pointer to memory where returned link speed is to be placed
+ *
+ * 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: 0 if linkspeed data is available, negative errno otherwise
+ */
+int wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *adapter,
+				       struct qdf_mac_addr *mac_address,
+				       uint32_t *linkspeed);
 void hdd_clear_roam_profile_ie(hdd_adapter_t *pAdapter);
 void hdd_clear_roam_profile_ie(hdd_adapter_t *pAdapter);
 
 
 uint8_t *wlan_hdd_get_vendor_oui_ie_ptr(uint8_t *oui, uint8_t oui_size,
 uint8_t *wlan_hdd_get_vendor_oui_ie_ptr(uint8_t *oui, uint8_t oui_size,

+ 4 - 6
core/hdd/src/wlan_hdd_hostapd.c

@@ -5153,15 +5153,13 @@ int __iw_get_softap_linkspeed(struct net_device *dev,
 		hdd_err("Invalid peer macaddress");
 		hdd_err("Invalid peer macaddress");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
-	status = wlan_hdd_get_linkspeed_for_peermac(pHostapdAdapter,
-						    macAddress);
-	if (!QDF_IS_STATUS_SUCCESS(status)) {
+	rc = wlan_hdd_get_linkspeed_for_peermac(pHostapdAdapter, &macAddress,
+						&link_speed);
+	if (!rc) {
 		hdd_err("Unable to retrieve SME linkspeed");
 		hdd_err("Unable to retrieve SME linkspeed");
-		return -EINVAL;
+		return rc;
 	}
 	}
 
 
-	link_speed = pHostapdAdapter->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;
 	wrqu->data.length = len;
 	wrqu->data.length = len;

+ 73 - 109
core/hdd/src/wlan_hdd_wext.c

@@ -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(&params);
+	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;
 	}
 	}