summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjge <jge@codeaurora.org>2016-12-09 10:44:33 +0800
committerqcabuildsw <qcabuildsw@localhost>2017-01-13 02:56:34 -0800
commit1cbe2f5322e7da9e383f1f5ca98912542864fc70 (patch)
tree597aa9abe08f898e6234ed9740850298001709e0
parent5a7f3f1d8bf6c7e846ee2a7ad1790662248ea13a (diff)
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
-rw-r--r--core/hdd/src/wlan_hdd_ipa.c159
1 files changed, 122 insertions, 37 deletions
diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c
index 530bc26d4a88..28a2ae16ffe3 100644
--- a/core/hdd/src/wlan_hdd_ipa.c
+++ b/core/hdd/src/wlan_hdd_ipa.c
@@ -2600,48 +2600,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--;
}
}
@@ -2649,25 +2676,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;
@@ -2693,8 +2777,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++) {