From 21ec490dbd71227ab1a6c4e7516ee9e9b373dfa7 Mon Sep 17 00:00:00 2001 From: Yun Park Date: Tue, 24 Apr 2018 12:11:01 -0700 Subject: [PATCH] qcacld-3.0: Cleanup interface when loading/unloading timeout When AP_DISCONNECT event occurs during IPA resource unloading in progress, timeout could happen since suspending FW IPA Rx pipe took much time. This could cause a subsequent AP_CONNECT event failed since no interface is available. Fix this by - Adapter struct sanity check using hdd_validate_adapter() - Call hdd_ipa_cleanup_iface() for AP_DISCONNECT/STA_DISCONNECT event in loading/unloading timeout case - Assert when no interface is available in hdd_ipa_setup_iface() Change-Id: Ie96e4f0e96ccffacf4ce5fcc976636c440214873 CRs-Fixed: 2208347 --- components/ipa/core/src/wlan_ipa_core.c | 21 +++++++++++++++++++++ core/hdd/src/wlan_hdd_ipa.c | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/components/ipa/core/src/wlan_ipa_core.c b/components/ipa/core/src/wlan_ipa_core.c index 06ea4dc5fa84..2d47ea9695b6 100644 --- a/components/ipa/core/src/wlan_ipa_core.c +++ b/components/ipa/core/src/wlan_ipa_core.c @@ -1070,6 +1070,13 @@ static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx, } } + if (WLAN_IPA_MAX_IFACE == ipa_ctx->num_iface) { + ipa_err("Max interface reached %d", WLAN_IPA_MAX_IFACE); + status = QDF_STATUS_E_NOMEM; + QDF_ASSERT(0); + goto end; + } + for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) { if (ipa_ctx->iface_context[i].tl_context == NULL) { iface_context = &(ipa_ctx->iface_context[i]); @@ -1080,6 +1087,7 @@ static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx, if (iface_context == NULL) { ipa_err("All the IPA interfaces are in use"); status = QDF_STATUS_E_NOMEM; + QDF_ASSERT(0); goto end; } @@ -1338,6 +1346,19 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode, qdf_mutex_release(&ipa_ctx->ipa_lock); + /* Cleanup interface */ + if (type == QDF_IPA_STA_DISCONNECT || + type == QDF_IPA_AP_DISCONNECT) { + for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) { + iface_ctx = &ipa_ctx->iface_context[i]; + + if (iface_ctx->dev == net_dev) + break; + } + if (iface_ctx) + wlan_ipa_cleanup_iface(iface_ctx); + } + return QDF_STATUS_SUCCESS; } ipa_info("IPA resource %s completed", diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index f9bed5e1bfb8..69ff23e46a7b 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -353,7 +353,7 @@ void hdd_ipa_send_skb_to_network(qdf_nbuf_t skb, qdf_netdev_t dev) unsigned int cpu_index; uint8_t staid; - if (!adapter || adapter->magic != WLAN_HDD_ADAPTER_MAGIC) { + if (hdd_validate_adapter(adapter)) { QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG, "Invalid adapter: 0x%pK", adapter); kfree_skb(skb);