summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYun Park <yunp@codeaurora.org>2017-03-30 15:38:33 -0700
committerYun Park <yunp@codeaurora.org>2017-04-01 10:30:53 -0700
commit90590ec040baff960c7b90758e1c92bd73217676 (patch)
tree50ccfd49444b68c6fa4ae0239420aa0441e4be48
parent09371808dbe505b096948453fc0730d2ed820c75 (diff)
qcacld-3.0: HDD IPA event handler waits resource load/unload complete
There is a race condition bewteen CLIENT_DISCONNECT and AP_DISCONNECT, which causes short HDD IPA interfaces, so AP_CONNECT failed afterward. HDD IPA event handler waits IPA resource load/unload complete. Once timed out, add the event in a pending queue for loading icase or ignore it for unloading case. Remove redundant CLIENT_DISCONNECT event from del_sta. Change-Id: I671ecec6f236d52a1b51cb78b9c7466f2cde82aa CRs-Fixed: 2027714
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.c13
-rw-r--r--core/hdd/src/wlan_hdd_ipa.c109
2 files changed, 70 insertions, 52 deletions
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index b0ff7de8adae..7e442feb62d2 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -15233,14 +15233,6 @@ int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
pAdapter->aStaInfo[i].
macAddrSTA.bytes,
QDF_MAC_ADDR_SIZE);
- if (hdd_ipa_uc_is_enabled(pHddCtx)) {
- hdd_ipa_wlan_evt(pAdapter,
- pAdapter->
- aStaInfo[i].
- ucSTAId,
- HDD_IPA_CLIENT_DISCONNECT,
- mac);
- }
hdd_debug("Delete STA with MAC::"
MAC_ADDRESS_STR,
MAC_ADDR_ARRAY(mac));
@@ -15281,11 +15273,6 @@ int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
return -ENOENT;
}
- if (hdd_ipa_uc_is_enabled(pHddCtx)) {
- hdd_ipa_wlan_evt(pAdapter, staId,
- HDD_IPA_CLIENT_DISCONNECT, mac);
- }
-
if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
true) {
hdd_debug("Skip DEL STA as deauth is in progress::"
diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c
index 370def6c968b..aed8f2f86c6d 100644
--- a/core/hdd/src/wlan_hdd_ipa.c
+++ b/core/hdd/src/wlan_hdd_ipa.c
@@ -503,6 +503,7 @@ struct hdd_ipa_priv {
struct completion ipa_uc_sharing_stats_comp;
struct completion ipa_uc_set_quota_comp;
#endif
+ struct completion ipa_resource_comp;
};
#define HDD_IPA_WLAN_FRAG_HEADER sizeof(struct frag_header)
@@ -634,6 +635,8 @@ static struct hdd_ipa_tx_hdr ipa_tx_hdr = {
#define IPA_UC_SET_QUOTA_WAIT_TIME 500
#endif
+#define IPA_RESOURCE_COMP_WAIT_TIME 100
+
static struct hdd_ipa_priv *ghdd_ipa;
/* Local Function Prototypes */
@@ -1685,6 +1688,7 @@ static int hdd_ipa_uc_enable_pipes(struct hdd_ipa_priv *hdd_ipa)
__func__, result);
return result;
}
+ INIT_COMPLETION(hdd_ipa->ipa_resource_comp);
ol_txrx_ipa_uc_set_active(cds_ctx->pdev_txrx_ctx, true, false);
hdd_ipa->ipa_pipes_down = false;
return 0;
@@ -1801,6 +1805,7 @@ static void hdd_ipa_uc_handle_last_discon(struct hdd_ipa_priv *hdd_ipa)
}
hdd_ipa->resource_unloading = true;
+ INIT_COMPLETION(hdd_ipa->ipa_resource_comp);
HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "%s: Disable FW RX PIPE", __func__);
ol_txrx_ipa_uc_set_active(cds_ctx->pdev_txrx_ctx, false, false);
HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "%s: Disable FW TX PIPE", __func__);
@@ -2073,6 +2078,7 @@ static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt)
hdd_ipa->activated_fw_pipe++;
if (HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) {
hdd_ipa->resource_loading = false;
+ complete(&hdd_ipa->ipa_resource_comp);
if (hdd_ipa->wdi_enabled == false) {
hdd_ipa->wdi_enabled = true;
if (hdd_ipa_uc_send_wdi_control_msg(true) == 0)
@@ -2092,14 +2098,16 @@ static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt)
qdf_mutex_acquire(&hdd_ipa->ipa_lock);
hdd_ipa->activated_fw_pipe--;
if (!hdd_ipa->activated_fw_pipe) {
+ /*
+ * Async return success from FW
+ * Disable/suspend all the PIPEs
+ */
hdd_ipa_uc_disable_pipes(hdd_ipa);
if (hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
ipa_rm_release_resource(
IPA_RM_RESOURCE_WLAN_PROD);
- /* Sync return success from IPA
- * Enable/resume all the PIPEs
- */
hdd_ipa->resource_unloading = false;
+ complete(&hdd_ipa->ipa_resource_comp);
hdd_ipa_uc_proc_pending_event(hdd_ipa);
hdd_ipa->pending_cons_req = false;
}
@@ -2514,7 +2522,6 @@ static void __hdd_ipa_wdi_meter_notifier_cb(enum ipa_wdi_meter_evt_type evt,
}
INIT_COMPLETION(hdd_ipa->ipa_uc_sharing_stats_comp);
- INIT_COMPLETION(hdd_ipa->ipa_uc_set_quota_comp);
hdd_ipa_uc_sharing_stats_request(adapter,
wdi_sap_stats->reset_stats);
ret = wait_for_completion_timeout(
@@ -2570,6 +2577,7 @@ static void __hdd_ipa_wdi_meter_notifier_cb(enum ipa_wdi_meter_evt_type evt,
return;
}
+ INIT_COMPLETION(hdd_ipa->ipa_uc_set_quota_comp);
hdd_ipa_uc_set_quota(adapter, ipa_set_quota->set_quota,
ipa_set_quota->quota_bytes);
@@ -5290,51 +5298,72 @@ static int __hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id,
/*
* During IPA UC resource loading/unloading new events can be issued.
- * Store the events separately and handle them later.
*/
- if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
- if (hdd_ipa->resource_loading) {
- unsigned int pending_event_count;
- struct ipa_uc_pending_event *pending_event = NULL;
+ if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx) &&
+ (hdd_ipa->resource_loading || hdd_ipa->resource_unloading)) {
+ unsigned int pending_event_count;
+ struct ipa_uc_pending_event *pending_event = NULL;
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "%s:IPA resource %s inprogress",
+ hdd_ipa_wlan_event_to_str(type),
+ hdd_ipa->resource_loading ?
+ "load" : "unload");
+
+ /* Wait until completion of the long/unloading */
+ ret = wait_for_completion_timeout(&hdd_ipa->ipa_resource_comp,
+ msecs_to_jiffies(IPA_RESOURCE_COMP_WAIT_TIME));
+ if (!ret) {
+ /*
+ * If timed out, store the events separately and
+ * handle them later.
+ */
HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "IPA resource load inprogress");
+ "IPA resource %s timed out",
+ hdd_ipa->resource_loading ?
+ "load" : "unload");
- qdf_mutex_acquire(&hdd_ipa->ipa_lock);
+ if (hdd_ipa->resource_loading) {
+ qdf_mutex_acquire(&hdd_ipa->ipa_lock);
- pending_event_count =
+ pending_event_count =
qdf_list_size(&hdd_ipa->pending_event);
- if (pending_event_count >=
- HDD_IPA_MAX_PENDING_EVENT_COUNT) {
- hdd_debug("Reached max pending event count");
- qdf_list_remove_front(&hdd_ipa->pending_event,
- (qdf_list_node_t **)&pending_event);
- } else {
- pending_event =
- qdf_mem_malloc(sizeof(*pending_event));
- }
+ if (pending_event_count >=
+ HDD_IPA_MAX_PENDING_EVENT_COUNT) {
+ hdd_debug(
+ "Reached max pending event count");
+ qdf_list_remove_front(
+ &hdd_ipa->pending_event,
+ (qdf_list_node_t **)&pending_event);
+ } else {
+ pending_event =
+ qdf_mem_malloc(
+ sizeof(*pending_event));
+ }
- if (!pending_event) {
- HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
- "Pending event memory alloc fail");
- qdf_mutex_release(&hdd_ipa->ipa_lock);
- return -ENOMEM;
- }
+ if (!pending_event) {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "Pending event memory alloc fail");
+ qdf_mutex_release(&hdd_ipa->ipa_lock);
+ return -ENOMEM;
+ }
- pending_event->adapter = adapter;
- pending_event->sta_id = sta_id;
- pending_event->type = type;
- qdf_mem_copy(pending_event->mac_addr,
- mac_addr,
- QDF_MAC_ADDR_SIZE);
- qdf_list_insert_back(&hdd_ipa->pending_event,
- &pending_event->node);
+ pending_event->adapter = adapter;
+ pending_event->sta_id = sta_id;
+ pending_event->type = type;
+ qdf_mem_copy(pending_event->mac_addr,
+ mac_addr, QDF_MAC_ADDR_SIZE);
+ qdf_list_insert_back(&hdd_ipa->pending_event,
+ &pending_event->node);
- qdf_mutex_release(&hdd_ipa->ipa_lock);
- return 0;
- } else if (hdd_ipa->resource_unloading) {
- hdd_err("IPA resource unload inprogress");
+ qdf_mutex_release(&hdd_ipa->ipa_lock);
+ }
return 0;
+ } else {
+ HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+ "IPA resource %s completed",
+ hdd_ipa->resource_loading ?
+ "load" : "unload");
}
}
@@ -5866,6 +5895,8 @@ static QDF_STATUS __hdd_ipa_init(hdd_context_t *hdd_ctx)
}
}
+ init_completion(&hdd_ipa->ipa_resource_comp);
+
EXIT();
return QDF_STATUS_SUCCESS;