ソースを参照

qcacld-3.0: Reset IPA disconnect events(AP/STA) during SSR

This is a qcacld-2.0 to qcacld-3.0 propagation.

IPA disconnect events(WLAN_AP_DISCONNECT/WLAN_STA_DISCONNECT)
are not sent to IPA driver in case of SSR. This is resulting
in mismatch between IPA driver and HOST driver, and headers in
IPA can't be freed, which causes memory overflow after multiple
times SSR.

Change-Id: I9c84cc84d943d6e3c6604db7b859127a7af5a654
CRs-Fixed: 1069083
jge 8 年 前
コミット
620378686e
1 ファイル変更123 行追加38 行削除
  1. 123 38
      core/hdd/src/wlan_hdd_ipa.c

+ 123 - 38
core/hdd/src/wlan_hdd_ipa.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -2265,48 +2265,75 @@ static void hdd_ipa_msg_free_fn(void *buff, uint32_t len, uint32_t type)
 	qdf_mem_free(buff);
 }
 
-
 /**
- * hdd_ipa_send_disconnect() - ipa send disconnect clients
- * adapter: pointer to hdd adapter
- * Send disconnect evnt to IPA driver during SSR
+ * hdd_ipa_uc_send_evt() - send event to ipa
+ * @hdd_ctx: pointer to hdd context
+ * @type: event type
+ * @mac_addr: pointer to mac address
+ *
+ * Send event to IPA driver
  *
  * Return: 0 - Success
  */
-static int hdd_ipa_send_disconnect(hdd_adapter_t *adapter)
+static int hdd_ipa_uc_send_evt(hdd_adapter_t *adapter,
+	enum ipa_wlan_event type, uint8_t *mac_addr)
 {
+	struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
 	struct ipa_msg_meta meta;
 	struct ipa_wlan_msg *msg;
 	int ret = 0;
+
+	meta.msg_len = sizeof(struct ipa_wlan_msg);
+	msg = qdf_mem_malloc(meta.msg_len);
+	if (msg == NULL) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+			"msg allocation failed");
+		return -ENOMEM;
+	}
+
+	meta.msg_type = type;
+	strlcpy(msg->name, adapter->dev->name,
+		IPA_RESOURCE_NAME_MAX);
+	memcpy(msg->mac_addr, mac_addr, ETH_ALEN);
+	HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "%s: Evt: %d",
+		msg->name, meta.msg_type);
+	ret = ipa_send_msg(&meta, msg, hdd_ipa_msg_free_fn);
+	if (ret) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+			"%s: Evt: %d fail:%d",
+			msg->name, meta.msg_type,  ret);
+		qdf_mem_free(msg);
+		return ret;
+	}
+
+	hdd_ipa->stats.num_send_msg++;
+
+	return ret;
+}
+
+/**
+ * hdd_ipa_uc_disconnect_client() - send client disconnect event
+ * @hdd_ctx: pointer to hdd adapter
+ *
+ * Send disconnect client event to IPA driver during SSR
+ *
+ * Return: 0 - Success
+ */
+static int hdd_ipa_uc_disconnect_client(hdd_adapter_t *adapter)
+{
+	struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
+	int ret = 0;
 	int i;
 
 	for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
 		if (qdf_is_macaddr_broadcast(&adapter->aStaInfo[i].macAddrSTA))
 			continue;
 		if ((adapter->aStaInfo[i].isUsed) &&
-			(!adapter->aStaInfo[i].isDeauthInProgress)) {
-			meta.msg_len = sizeof(struct ipa_wlan_msg);
-			msg = qdf_mem_malloc(meta.msg_len);
-			if (msg == NULL) {
-				HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-					"msg allocation failed");
-				return -ENOMEM;
-			}
-			meta.msg_type = WLAN_CLIENT_DISCONNECT;
-			strlcpy(msg->name, adapter->dev->name,
-				IPA_RESOURCE_NAME_MAX);
-			memcpy(msg->mac_addr, adapter->aStaInfo[i].macAddrSTA.bytes,
-				ETH_ALEN);
-				HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "%s: Evt: %d",
-				msg->name, meta.msg_type);
-			ret = ipa_send_msg(&meta, msg, hdd_ipa_msg_free_fn);
-			if (ret) {
-				HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-					"%s: Evt: %d fail:%d",
-					msg->name, meta.msg_type,  ret);
-				qdf_mem_free(msg);
-				return ret;
-			}
+		   (!adapter->aStaInfo[i].isDeauthInProgress) &&
+		   hdd_ipa->sap_num_connected_sta) {
+			hdd_ipa_uc_send_evt(adapter, WLAN_CLIENT_DISCONNECT,
+				adapter->aStaInfo[i].macAddrSTA.bytes);
+			hdd_ipa->sap_num_connected_sta--;
 		}
 	}
 
@@ -2314,25 +2341,82 @@ static int hdd_ipa_send_disconnect(hdd_adapter_t *adapter)
 }
 
 /**
- * hdd_ipa_uc_disconnect_client() - disconnect ipa sap clients
- * hdd_ctx: pointer to hdd context
- * Send disconnect evnt to IPA driver during SSR
+ * hdd_ipa_uc_disconnect_ap() - send ap disconnect event
+ * @hdd_ctx: pointer to hdd adapter
+ *
+ * Send disconnect ap event to IPA driver during SSR
  *
  * Return: 0 - Success
  */
-static int hdd_ipa_uc_disconnect_client(hdd_context_t *hdd_ctx)
+
+static int hdd_ipa_uc_disconnect_ap(hdd_adapter_t *adapter)
+{
+	int ret = 0;
+
+	if (adapter->ipa_context)
+		hdd_ipa_uc_send_evt(adapter, WLAN_AP_DISCONNECT,
+			adapter->dev->dev_addr);
+
+	return ret;
+}
+
+#ifdef IPA_UC_STA_OFFLOAD
+/**
+ * hdd_ipa_uc_disconnect_sta() - send sta disconnect event
+ * @hdd_ctx: pointer to hdd adapter
+ *
+ * Send disconnect sta event to IPA driver during SSR
+ *
+ * Return: 0 - Success
+ */
+static int hdd_ipa_uc_disconnect_sta(hdd_adapter_t *adapter)
+{
+	hdd_station_ctx_t *pHddStaCtx;
+	struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
+	int ret = 0;
+
+	if (hdd_ipa_uc_sta_is_enabled(hdd_ipa) &&
+	    hdd_ipa->sta_connected) {
+		pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+		hdd_ipa_uc_send_evt(adapter, WLAN_STA_DISCONNECT,
+			pHddStaCtx->conn_info.bssId);
+	}
+
+	return ret;
+}
+#else
+static int hdd_ipa_uc_disconnect_sta(hdd_adapter_t *adapter)
+{
+	return 0;
+}
+
+#endif
+
+/**
+ * hdd_ipa_uc_disconnect() - send disconnect ipa event
+ * @hdd_ctx: pointer to hdd context
+ *
+ * Send disconnect event to IPA driver during SSR
+ *
+ * Return: 0 - Success
+ */
+static int hdd_ipa_uc_disconnect(hdd_context_t *hdd_ctx)
 {
 	hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
 	QDF_STATUS status;
 	hdd_adapter_t *adapter;
 	int ret = 0;
 
-
 	status =  hdd_get_front_adapter(hdd_ctx, &adapter_node);
 	while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
 		adapter = adapter_node->pAdapter;
-		if (adapter->device_mode == QDF_SAP_MODE)
-			hdd_ipa_send_disconnect(adapter);
+		if (adapter->device_mode == QDF_SAP_MODE) {
+			hdd_ipa_uc_disconnect_client(adapter);
+			hdd_ipa_uc_disconnect_ap(adapter);
+		} else if (adapter->device_mode == QDF_STA_MODE) {
+			hdd_ipa_uc_disconnect_sta(adapter);
+		}
+
 		status = hdd_get_next_adapter(
 				hdd_ctx, adapter_node, &next);
 		adapter_node = next;
@@ -2358,8 +2442,9 @@ static int __hdd_ipa_uc_ssr_deinit(void)
 	if ((!hdd_ipa) || (!hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)))
 		return 0;
 
-	/* send disconnect to ipa driver for connected clients */
-	hdd_ipa_uc_disconnect_client(hdd_ipa->hdd_ctx);
+	/* send disconnect to ipa driver */
+	hdd_ipa_uc_disconnect(hdd_ipa->hdd_ctx);
+
 	/* Clean up HDD IPA interfaces */
 	for (idx = 0; (hdd_ipa->num_iface > 0) &&
 		(idx < HDD_IPA_MAX_IFACE); idx++) {