diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 41fcbce3ef66..3a5ab4c6aefb 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -2373,6 +2373,22 @@ QDF_STATUS hdd_adapter_iterate(hdd_adapter_iterate_cb cb, (adapter) ? dev_hold(adapter->dev) : (false), \ qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock) +/** + * __hdd_take_ref_and_fetch_front_adapter_safe - Helper macro to lock, fetch + * front and next adapters, take ref and unlock. + * @hdd_ctx: the global HDD context + * @adapter: an hdd_adapter pointer to use as a cursor + * @next_adapter: hdd_adapter pointer to next adapter + */ +#define __hdd_take_ref_and_fetch_front_adapter_safe(hdd_ctx, adapter, \ + next_adapter) \ + qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock), \ + hdd_get_front_adapter_no_lock(hdd_ctx, &adapter), \ + (adapter) ? dev_hold(adapter->dev) : (false), \ + hdd_get_next_adapter_no_lock(hdd_ctx, adapter, &next_adapter), \ + (next_adapter) ? dev_hold(next_adapter->dev) : (false), \ + qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock) + /** * __hdd_take_ref_and_fetch_next_adapter - Helper macro to lock, fetch next * adapter, take ref and unlock. @@ -2385,6 +2401,21 @@ QDF_STATUS hdd_adapter_iterate(hdd_adapter_iterate_cb cb, (adapter) ? dev_hold(adapter->dev) : (false), \ qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock) +/** + * __hdd_take_ref_and_fetch_next_adapter_safe - Helper macro to lock, fetch next + * adapter, take ref and unlock. + * @hdd_ctx: the global HDD context + * @adapter: hdd_adapter pointer to use as a cursor + * @next_adapter: hdd_adapter pointer to next adapter + */ +#define __hdd_take_ref_and_fetch_next_adapter_safe(hdd_ctx, adapter, \ + next_adapter) \ + qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock), \ + adapter = next_adapter, \ + hdd_get_next_adapter_no_lock(hdd_ctx, adapter, &next_adapter), \ + (next_adapter) ? dev_hold(next_adapter->dev) : (false), \ + qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock) + /** * __hdd_is_adapter_valid - Helper macro to return true/false for valid adapter. * @adapter: an hdd_adapter pointer to use as a cursor @@ -2417,6 +2448,41 @@ QDF_STATUS hdd_adapter_iterate(hdd_adapter_iterate_cb cb, __hdd_is_adapter_valid(adapter); \ __hdd_take_ref_and_fetch_next_adapter(hdd_ctx, adapter)) +/** + * hdd_for_each_adapter_dev_held_safe - Adapter iterator with dev_hold called + * in a delete safe manner + * @hdd_ctx: the global HDD context + * @adapter: an hdd_adapter pointer to use as a cursor + * @next_adapter: hdd_adapter pointer to the next adapter + * + * This iterator will take the reference of the netdev associated with the + * given adapter so as to prevent it from being removed in other context. It + * also takes the reference of the next adapter if exist. This avoids infinite + * loop due to deletion of the adapter list entry inside the loop. Deletion of + * list entry will make the list entry to point to self. If the control goes + * inside the loop body then the dev_hold has been invoked. + * + * ***** NOTE ***** + * Before the end of each iteration, dev_put(adapter->dev) must be + * called. Not calling this will keep hold of a reference, thus preventing + * unregister of the netdevice. If the loop is terminated in between with + * return/goto/break statements, dev_put(next_adapter->dev) must be done + * along with dev_put(adapter->dev) before termination of the loop. + * + * Usage example: + * hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter) { + * + * + * dev_put(adapter->dev) + * } + */ +#define hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter) \ + for (__hdd_take_ref_and_fetch_front_adapter_safe(hdd_ctx, adapter, \ + next_adapter); \ + __hdd_is_adapter_valid(adapter); \ + __hdd_take_ref_and_fetch_next_adapter_safe(hdd_ctx, adapter, \ + next_adapter)) + /** * wlan_hdd_get_adapter_by_vdev_id_from_objmgr() - Fetch adapter from objmgr * using vdev_id.