From 18cb483d82d1faa4fa04d07f458124391bcacaf4 Mon Sep 17 00:00:00 2001 From: Alan Chen Date: Fri, 15 Nov 2019 16:40:17 -0800 Subject: [PATCH] qcacld-3.0: Create new hdd_adapter_iterate() function Currently, there is a problem in hdd_for_each_adapter(), as it is checking for the NDI adapter only in an infinite loop. Create hdd_adapter_iterate() in order to iterate through all adapters properly. Change-Id: Ib0e22d0f46d6311d44de3ee48b3202376a42f209 CRs-Fixed: 2568906 --- core/hdd/inc/wlan_hdd_main.h | 38 +++++++++++++++++++++++++++++++ core/hdd/src/wlan_hdd_main.c | 43 ++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 0c2261c53fd4..3cef5ca740c7 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -2049,6 +2049,44 @@ QDF_STATUS hdd_add_adapter_back(struct hdd_context *hdd_ctx, QDF_STATUS hdd_add_adapter_front(struct hdd_context *hdd_ctx, struct hdd_adapter *adapter); +/** + * typedef hdd_adapter_iterate_cb() – Iteration callback function + * @adapter: current adapter of interest + * @context: user context supplied to the iterator + * + * This specifies the type of a callback function to supply to + * hdd_adapter_iterate(). + * + * Return: + * * QDF_STATUS_SUCCESS if further iteration should continue + * * QDF_STATUS_E_ABORTED if further iteration should be aborted + */ +typedef QDF_STATUS (*hdd_adapter_iterate_cb)(struct hdd_adapter *adapter, + void *context); + +/** + * hdd_adapter_iterate() – Safely iterate over all adapters + * @cb: callback function to invoke for each adapter + * @context: user-supplied context to pass to @cb + * + * This function will iterate over all of the adapters known to the system in + * a safe manner, invoking the callback function for each adapter. + * The callback function will be invoked in the same context/thread as the + * caller without any additional locks in force. + * Iteration continues until either the callback has been invoked for all + * adapters or a callback returns a value of QDF_STATUS_E_ABORTED to indicate + * that further iteration should cease. + * + * Return: + * * QDF_STATUS_E_ABORTED if any callback function returns that value + * * QDF_STATUS_E_FAILURE if the callback was not invoked for all adapters due + * to concurrency (i.e. adapter was deleted while iterating) + * * QDF_STATUS_SUCCESS if @cb was invoked for each adapter and none returned + * an error + */ +QDF_STATUS hdd_adapter_iterate(hdd_adapter_iterate_cb cb, + void *context); + /** * hdd_for_each_adapter - adapter iterator macro * @hdd_ctx: the global HDD context diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 2ab846d3273d..d48bd92c627a 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -7160,6 +7160,49 @@ QDF_STATUS hdd_add_adapter_front(struct hdd_context *hdd_ctx, return status; } +QDF_STATUS hdd_adapter_iterate(hdd_adapter_iterate_cb cb, void *context) +{ + struct hdd_context *hdd_ctx; + struct hdd_adapter *cache[HDD_MAX_ADAPTERS]; + struct hdd_adapter *adapter; + uint32_t n_cache = 0; + QDF_STATUS ret = QDF_STATUS_SUCCESS; + QDF_STATUS status; + int i; + + hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + if (unlikely(!hdd_ctx)) { + hdd_err("HDD context is Null"); + return QDF_STATUS_E_FAILURE; + } + + qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock); + for (hdd_get_front_adapter_no_lock(hdd_ctx, &adapter); adapter; + hdd_get_next_adapter_no_lock(hdd_ctx, adapter, &adapter)) { + cache[n_cache++] = adapter; + } + qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock); + + for (i = 0; i < n_cache - 1; i++) { + adapter = hdd_adapter_get_by_reference(hdd_ctx, cache[i]); + if (!adapter) { + /* + * detected remove while iterating + * concurrency failure + */ + ret = QDF_STATUS_E_FAILURE; + continue; + } + + status = cb(adapter, context); + hdd_adapter_put(adapter); + if (status != QDF_STATUS_SUCCESS) + return status; + } + + return ret; +} + struct hdd_adapter *hdd_get_adapter_by_rand_macaddr( struct hdd_context *hdd_ctx, tSirMacAddr mac_addr) {