diff options
| author | Yun Park <yunp@codeaurora.org> | 2016-08-17 10:17:46 -0700 |
|---|---|---|
| committer | qcabuildsw <qcabuildsw@localhost> | 2016-12-05 20:09:06 -0800 |
| commit | 19a6b3793db4c2a660db4940351420b4d05a6a12 (patch) | |
| tree | a432cdd032f835073e0b8549e7b8bdd2941c0ea3 | |
| parent | d9e1483b4644dcc236ed3f1d4ef09b451c78de91 (diff) | |
qcacld-3.0: IPA uC: Fix crash when resume pended events after driver unload
qcacld-2.0 to qcacld-3.0 propagation
When pended HDD IPA events are resumed after driver unloading, a crash
happens, since resources are already freed up.
Fix by not pending events while driver unloading is in progress.
Change-Id: Id744aa6e683850ce25c875ab6b5ffabdca733e5d
CRs-Fixed: 987180
| -rw-r--r-- | core/hdd/src/wlan_hdd_ipa.c | 70 |
1 files changed, 37 insertions, 33 deletions
diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 0dddbab6d7cd..3e0bb39d98e7 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -3889,45 +3889,49 @@ 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) && - ((hdd_ipa->resource_loading) || - (hdd_ipa->resource_unloading))) { - unsigned int pending_event_count; - struct ipa_uc_pending_event *pending_event = NULL; + if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) { + if (hdd_ipa->resource_loading) { + unsigned int pending_event_count; - hdd_err("IPA resource %s inprogress", - hdd_ipa->resource_loading ? "load":"unload"); + struct ipa_uc_pending_event *pending_event = NULL; - qdf_mutex_acquire(&hdd_ipa->event_lock); + hdd_err("IPA resource %s inprogress", + hdd_ipa->resource_loading ? "load":"unload"); - pending_event_count = qdf_list_size(&hdd_ipa->pending_event); - if (pending_event_count >= HDD_IPA_MAX_PENDING_EVENT_COUNT) { - hdd_notice("Reached max pending event count"); - qdf_list_remove_front(&hdd_ipa->pending_event, - (qdf_list_node_t **)&pending_event); - } else { - pending_event = - (struct ipa_uc_pending_event *)qdf_mem_malloc( - sizeof(struct ipa_uc_pending_event)); - } + qdf_mutex_acquire(&hdd_ipa->event_lock); - if (!pending_event) { - hdd_err("Pending event memory alloc fail"); - qdf_mutex_release(&hdd_ipa->event_lock); - return -ENOMEM; - } + pending_event_count = qdf_list_size(&hdd_ipa->pending_event); + if (pending_event_count >= HDD_IPA_MAX_PENDING_EVENT_COUNT) { + hdd_notice("Reached max pending event count"); + qdf_list_remove_front(&hdd_ipa->pending_event, + (qdf_list_node_t **)&pending_event); + } else { + pending_event = + (struct ipa_uc_pending_event *)qdf_mem_malloc( + sizeof(struct ipa_uc_pending_event)); + } - 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); + if (!pending_event) { + hdd_err("Pending event memory alloc fail"); + qdf_mutex_release(&hdd_ipa->event_lock); + return -ENOMEM; + } - qdf_mutex_release(&hdd_ipa->event_lock); - return 0; + 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->event_lock); + return 0; + } else if (hdd_ipa->resource_unloading) { + hdd_err("%s: IPA resource unload inprogress", __func__); + return 0; + } } hdd_ipa->stats.event[type]++; |
