From b389b5b1bd0a0ddc276d28bd10c7f9eb06c5ec94 Mon Sep 17 00:00:00 2001 From: Amit Mehta Date: Tue, 17 May 2022 05:37:50 -0700 Subject: [PATCH] qcacld-3.0: Add vdev lock to dp component Add vdev lock to DP component to protect against vdev parallel delete while accessing vdev from DP interface, also introduce get and put APIs. Change-Id: I4ee838e1dea0caf9936ced13d6ddce6646333f6b CRs-Fixed: 3198876 --- components/dp/core/inc/wlan_dp_objmgr.h | 52 +++++++++ components/dp/core/inc/wlan_dp_priv.h | 1 + .../dp/core/src/wlan_dp_bus_bandwidth.c | 11 +- components/dp/core/src/wlan_dp_main.c | 100 ++++++++++++++++-- components/dp/core/src/wlan_dp_nud_tracking.c | 22 ++-- .../dp/dispatcher/src/wlan_dp_ucfg_api.c | 2 + 6 files changed, 163 insertions(+), 25 deletions(-) diff --git a/components/dp/core/inc/wlan_dp_objmgr.h b/components/dp/core/inc/wlan_dp_objmgr.h index c95d47d5b5..713ed5f706 100644 --- a/components/dp/core/inc/wlan_dp_objmgr.h +++ b/components/dp/core/inc/wlan_dp_objmgr.h @@ -100,4 +100,56 @@ dp_psoc_get_priv(struct wlan_objmgr_psoc *psoc) return dp_ctx; } + +/** + * dp_objmgr_get_vdev_by_user() - Get reference of vdev from dp_intf + * with user id + * @dp_intf: dp dp_intf + * @dbgid: reference count dbg id + * + * Return: pointer to vdev object for success, NULL for failure + */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +#define dp_objmgr_get_vdev_by_user(dp_intf, dbgid) \ + __dp_objmgr_get_vdev_by_user(dp_intf, dbgid, __func__, __LINE__) +struct wlan_objmgr_vdev * +__dp_objmgr_get_vdev_by_user(struct wlan_dp_intf *dp_intf, + wlan_objmgr_ref_dbgid id, + const char *func, + int line); +#else +#define dp_objmgr_get_vdev_by_user(dp_intf, dbgid) \ + __dp_objmgr_get_vdev_by_user(dp_intf, dbgid, __func__) +struct wlan_objmgr_vdev * +__dp_objmgr_get_vdev_by_user(struct wlan_dp_intf *dp_intf, + wlan_objmgr_ref_dbgid id, + const char *func); +#endif + +/** + * dp_objmgr_put_vdev_by_user() - Release reference of vdev object with + * user id + * @vdev: pointer to vdev object + * @dbgid: reference count dbg id + * + * This API releases vdev object reference which was acquired using + * dp_objmgr_get_vdev_by_user(). + * + * Return: void + */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +#define dp_objmgr_put_vdev_by_user(vdev, dbgid) \ + __dp_objmgr_put_vdev_by_user(vdev, dbgid, __func__, __LINE__) +void +__dp_objmgr_put_vdev_by_user(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id, const char *func, + int line); +#else +#define dp_objmgr_put_vdev_by_user(vdev, dbgid) \ + __dp_objmgr_put_vdev_by_user(vdev, dbgid, __func__) +void +__dp_objmgr_put_vdev_by_user(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id, const char *func); +#endif + #endif /* __WLAN_DP_OBJMGR_H */ diff --git a/components/dp/core/inc/wlan_dp_priv.h b/components/dp/core/inc/wlan_dp_priv.h index 423660c753..fdf52ae3d5 100644 --- a/components/dp/core/inc/wlan_dp_priv.h +++ b/components/dp/core/inc/wlan_dp_priv.h @@ -286,6 +286,7 @@ struct wlan_dp_intf { qdf_list_node_t node; struct wlan_objmgr_vdev *vdev; + qdf_spinlock_t vdev_lock; qdf_netdev_t dev; /**Device TX/RX statistics*/ struct dp_stats dp_stats; diff --git a/components/dp/core/src/wlan_dp_bus_bandwidth.c b/components/dp/core/src/wlan_dp_bus_bandwidth.c index 585a64134f..62eeed40d5 100644 --- a/components/dp/core/src/wlan_dp_bus_bandwidth.c +++ b/components/dp/core/src/wlan_dp_bus_bandwidth.c @@ -1690,17 +1690,14 @@ static void __dp_bus_bw_work_handler(struct wlan_dp_psoc_context *dp_ctx) dp_ctx->bw_vote_time = curr_time_us; dp_for_each_intf_held_safe(dp_ctx, dp_intf, dp_intf_next) { - vdev = dp_intf->vdev; + vdev = dp_objmgr_get_vdev_by_user(dp_intf, WLAN_DP_ID); if (!vdev) continue; - if (dp_comp_vdev_get_ref(vdev)) - continue; - if ((dp_intf->device_mode == QDF_STA_MODE || dp_intf->device_mode == QDF_P2P_CLIENT_MODE) && !ucfg_cm_is_vdev_active(vdev)) { - dp_comp_vdev_put_ref(vdev); + dp_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID); continue; } @@ -1708,7 +1705,7 @@ static void __dp_bus_bw_work_handler(struct wlan_dp_psoc_context *dp_ctx) dp_intf->device_mode == QDF_P2P_GO_MODE) && !dp_ctx->dp_ops.dp_is_ap_active(ctx, dp_intf->intf_id)) { - dp_comp_vdev_put_ref(vdev); + dp_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID); continue; } @@ -1774,7 +1771,7 @@ static void __dp_bus_bw_work_handler(struct wlan_dp_psoc_context *dp_ctx) QDF_NET_DEV_STATS_TX_BYTES(&dp_intf->stats); qdf_spin_unlock_bh(&dp_ctx->bus_bw_lock); connected = true; - dp_comp_vdev_put_ref(vdev); + dp_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID); } if (!connected) { diff --git a/components/dp/core/src/wlan_dp_main.c b/components/dp/core/src/wlan_dp_main.c index 0a650bb7b4..e32ed9e7c9 100644 --- a/components/dp/core/src/wlan_dp_main.c +++ b/components/dp/core/src/wlan_dp_main.c @@ -638,15 +638,10 @@ static void __dp_process_mic_error(struct wlan_dp_intf *dp_intf) { struct wlan_dp_psoc_callbacks *ops = &dp_intf->dp_ctx->dp_ops; - struct wlan_objmgr_vdev *vdev = dp_intf->vdev; + struct wlan_objmgr_vdev *vdev; + vdev = dp_objmgr_get_vdev_by_user(dp_intf, WLAN_DP_ID); if (!vdev) { - dp_err("vdev is NULL"); - return; - } - - if (dp_comp_vdev_get_ref(vdev)) { - dp_err("vdev ref get error"); return; } @@ -662,7 +657,7 @@ __dp_process_mic_error(struct wlan_dp_intf *dp_intf) else dp_err("Invalid interface type:%d", dp_intf->device_mode); - dp_comp_vdev_put_ref(vdev); + dp_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID); } /** @@ -901,8 +896,10 @@ dp_vdev_obj_create_notification(struct wlan_objmgr_vdev *vdev, void *arg) } dp_intf->device_mode = wlan_vdev_mlme_get_opmode(vdev); + qdf_spin_lock_bh(&dp_intf->vdev_lock); dp_intf->intf_id = vdev->vdev_objmgr.vdev_id; dp_intf->vdev = vdev; + qdf_spin_unlock_bh(&dp_intf->vdev_lock); qdf_atomic_init(&dp_intf->num_active_task); if (dp_intf->device_mode == QDF_SAP_MODE || @@ -965,7 +962,9 @@ dp_vdev_obj_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg) } qdf_mem_zero(&dp_intf->conn_info, sizeof(struct wlan_dp_conn_info)); dp_intf->intf_id = WLAN_UMAC_VDEV_ID_MAX; + qdf_spin_lock_bh(&dp_intf->vdev_lock); dp_intf->vdev = NULL; + qdf_spin_unlock_bh(&dp_intf->vdev_lock); status = wlan_objmgr_vdev_component_obj_detach(vdev, WLAN_COMP_DP, (void *)dp_intf); @@ -1423,3 +1422,88 @@ QDF_STATUS dp_get_arp_stats_event_handler(struct wlan_objmgr_psoc *psoc, wlan_objmgr_vdev_release_ref(vdev, WLAN_DP_ID); return QDF_STATUS_SUCCESS; } + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev * +__dp_objmgr_get_vdev_by_user(struct wlan_dp_intf *dp_intf, + wlan_objmgr_ref_dbgid id, + const char *func, int line) +{ + struct wlan_objmgr_vdev *vdev; + QDF_STATUS status; + + if (!dp_intf) { + dp_err("dp_intf is NULL (via %s, id %d)", func, id); + return NULL; + } + + qdf_spin_lock_bh(&dp_intf->vdev_lock); + vdev = dp_intf->vdev; + if (vdev) { + status = wlan_objmgr_vdev_try_get_ref_debug(vdev, id, func, + line); + if (QDF_IS_STATUS_ERROR(status)) + vdev = NULL; + } + qdf_spin_unlock_bh(&dp_intf->vdev_lock); + + if (!vdev) + dp_debug("VDEV is NULL (via %s, id %d)", func, id); + + return vdev; +} + +void +__dp_objmgr_put_vdev_by_user(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id, const char *func, + int line) +{ + if (!vdev) { + dp_err("VDEV is NULL (via %s, id %d)", func, id); + return; + } + + wlan_objmgr_vdev_release_ref_debug(vdev, id, func, line); +} +#else +struct wlan_objmgr_vdev * +__dp_objmgr_get_vdev_by_user(struct wlan_dp_intf *dp_intf, + wlan_objmgr_ref_dbgid id, + const char *func) +{ + struct wlan_objmgr_vdev *vdev; + QDF_STATUS status; + + if (!dp_intf) { + dp_err("dp_intf is NULL (via %s, id %d)", func, id); + return NULL; + } + + qdf_spin_lock_bh(&dp_intf->vdev_lock); + vdev = dp_intf->vdev; + if (vdev) { + status = wlan_objmgr_vdev_try_get_ref(vdev, id); + if (QDF_IS_STATUS_ERROR(status)) + vdev = NULL; + } + qdf_spin_unlock_bh(&dp_intf->vdev_lock); + + if (!vdev) + dp_debug("VDEV is NULL (via %s, id %d)", func, id); + + return vdev; +} + +void +__dp_objmgr_put_vdev_by_user(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id, const char *func) +{ + if (!vdev) { + dp_err("VDEV is NULL (via %s, id %d)", func, id); + return; + } + + wlan_objmgr_vdev_release_ref(vdev, id); +} +#endif /* WLAN_OBJMGR_REF_ID_TRACE */ + diff --git a/components/dp/core/src/wlan_dp_nud_tracking.c b/components/dp/core/src/wlan_dp_nud_tracking.c index fdaf668c7a..95eb317f6b 100644 --- a/components/dp/core/src/wlan_dp_nud_tracking.c +++ b/components/dp/core/src/wlan_dp_nud_tracking.c @@ -136,19 +136,14 @@ void dp_nud_reset_tracking(struct wlan_dp_intf *dp_intf) */ static void dp_nud_stats_info(struct wlan_dp_intf *dp_intf) { - struct wlan_objmgr_vdev *vdev = dp_intf->vdev; + struct wlan_objmgr_vdev *vdev; struct dp_nud_tx_rx_stats *tx_rx_stats = &dp_intf->nud_tracking.tx_rx_stats; struct wlan_dp_psoc_callbacks *cb = &dp_intf->dp_ctx->dp_ops; uint32_t pause_map; + vdev = dp_objmgr_get_vdev_by_user(dp_intf, WLAN_DP_ID); if (!vdev) { - dp_err("vdev is NULL"); - return; - } - - if (dp_comp_vdev_get_ref(vdev)) { - dp_err("vdev ref get error"); return; } @@ -162,12 +157,12 @@ static void dp_nud_stats_info(struct wlan_dp_intf *dp_intf) dp_info("NUD Gateway Rx : %d", qdf_atomic_read(&tx_rx_stats->gw_rx_packets)); - cb->os_if_dp_nud_stats_info(dp_intf->vdev); + cb->os_if_dp_nud_stats_info(vdev); pause_map = cb->dp_get_pause_map(cb->callback_ctx, dp_intf->intf_id); dp_info("Current pause_map value %x", pause_map); - dp_comp_vdev_put_ref(vdev); + dp_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID); } /** @@ -338,6 +333,7 @@ static void dp_nud_filter_netevent(struct qdf_mac_addr *netdev_addr, int status; struct wlan_dp_intf *dp_intf; struct wlan_dp_psoc_context *dp_ctx; + struct wlan_objmgr_vdev *vdev; dp_ctx = dp_get_context(); if (!dp_ctx) @@ -363,10 +359,16 @@ static void dp_nud_filter_netevent(struct qdf_mac_addr *netdev_addr, if (dp_intf->device_mode != QDF_STA_MODE) return; - if (!ucfg_cm_is_vdev_active(dp_intf->vdev)) { + vdev = dp_objmgr_get_vdev_by_user(dp_intf, WLAN_DP_ID); + if (!vdev) + return; + + if (!ucfg_cm_is_vdev_active(vdev)) { + dp_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID); dp_info("Not in Connected State"); return; } + dp_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID); if (!qdf_is_macaddr_equal(&dp_intf->nud_tracking.gw_mac_addr, gw_mac_addr)) diff --git a/components/dp/dispatcher/src/wlan_dp_ucfg_api.c b/components/dp/dispatcher/src/wlan_dp_ucfg_api.c index 3f5415dd8d..e4db9eb9fe 100644 --- a/components/dp/dispatcher/src/wlan_dp_ucfg_api.c +++ b/components/dp/dispatcher/src/wlan_dp_ucfg_api.c @@ -80,6 +80,7 @@ ucfg_dp_create_intf(struct wlan_objmgr_psoc *psoc, dp_intf->dev = ndev; dp_intf->intf_id = WLAN_UMAC_VDEV_ID_MAX; qdf_copy_macaddr(&dp_intf->mac_addr, intf_addr); + qdf_spinlock_create(&dp_intf->vdev_lock); qdf_spin_lock_bh(&dp_ctx->intf_list_lock); qdf_list_insert_front(&dp_ctx->intf_list, &dp_intf->node); @@ -116,6 +117,7 @@ ucfg_dp_destroy_intf(struct wlan_objmgr_psoc *psoc, dp_periodic_sta_stats_mutex_destroy(dp_intf); dp_nud_deinit_tracking(dp_intf); dp_mic_deinit_work(dp_intf); + qdf_spinlock_destroy(&dp_intf->vdev_lock); qdf_spin_lock_bh(&dp_ctx->intf_list_lock); qdf_list_remove_node(&dp_ctx->intf_list, &dp_intf->node);