Преглед на файлове

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
Amit Mehta преди 2 години
родител
ревизия
b389b5b1bd

+ 52 - 0
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 */

+ 1 - 0
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;

+ 4 - 7
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) {

+ 92 - 8
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 */
+

+ 12 - 10
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))

+ 2 - 0
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);