Bläddra i källkod

qcacld-3.0: Add Wait for uptree operations in dsc for vdev transitions

Currently host driver does not wait for uptree operations in dsc
before it starts vdev transitios, which may lead to memory domain
mismatch.

For example, if modules are closed because of idle shutdown, memory
domain in host driver will be init domain and at that time if some
psoc ops starts, memory allocated as part of this ops will be
allocated in init domain and if at the same time if vdev up starts
which will trigger the vdev trans and will start the modules and change
the memory domain to active domain, now when the memory allocated as
part of psoc operation is released on psoc ops completion will be
released in the active domain which leads the memory domain mismatch.

In current issue, host driver closes the modules because of idle
shutdown and changes the memory domain to init domain, now host driver
receives get features vendor command and starts psoc operation which
allocates memory in init domain, while this psoc operation is still in
progress, host driver receives interface create which starts vdev
operation and changes the memory domain to active domain as part of
start modules. Now, when ongoing psoc operation completes, it
releases the momory in active domain, which results in memory
domain mismatch.

To fix this issue, before starting vdev transition, add wait for uptree
operations in dsc tree, which includes wait for psoc operations and
driver operations as this issue is possible with the driver operations
as well.

Change-Id: I2cf395ebb94cafca728926a6617fdc34a073755a
CRs-Fixed: 3621530
Ashish Kumar Dhanotiya 1 år sedan
förälder
incheckning
bc1d0241e5

+ 13 - 1
components/dsc/inc/wlan_dsc_vdev.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2018-2019, 2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -167,4 +167,16 @@ uint8_t dsc_vdev_get_cached_cmd(struct dsc_vdev *vdev);
  */
 void dsc_vdev_cache_command(struct dsc_vdev *vdev, uint8_t cmd_id);
 
+/*
+ * dsc_vdev_wait_for_uptree_ops() - Wait for any uptree operations
+ * @vdev: The DSC vdev
+ *
+ * This function checks and waits for any uptree operations if there is any
+ * uptree operation is in progress.
+ *
+ * Return: None.
+ */
+
+void dsc_vdev_wait_for_uptree_ops(struct dsc_vdev *vdev);
+
 #endif /* __WLAN_DSC_VDEV_H */

+ 32 - 1
components/dsc/src/wlan_dsc_vdev.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -104,6 +104,37 @@ void dsc_vdev_destroy(struct dsc_vdev **out_vdev)
 	__dsc_vdev_destroy(out_vdev);
 }
 
+static void __dsc_vdev_wait_for_uptree_ops(struct dsc_vdev *vdev)
+{
+	bool wait;
+
+	if (!dsc_assert(vdev))
+		return;
+
+	__dsc_driver_lock(vdev);
+	wait = vdev->psoc->ops.count > 0;
+	if (wait)
+		qdf_event_reset(&vdev->psoc->ops.event);
+	__dsc_driver_unlock(vdev);
+
+	if (wait)
+		qdf_wait_single_event(&vdev->psoc->ops.event, 0);
+
+	__dsc_driver_lock(vdev);
+	wait = vdev->psoc->driver->ops.count > 0;
+	if (wait)
+		qdf_event_reset(&vdev->psoc->driver->ops.event);
+	__dsc_driver_unlock(vdev);
+
+	if (wait)
+		qdf_wait_single_event(&vdev->psoc->driver->ops.event, 0);
+}
+
+void dsc_vdev_wait_for_uptree_ops(struct dsc_vdev *vdev)
+{
+	__dsc_vdev_wait_for_uptree_ops(vdev);
+}
+
 #define __dsc_vdev_can_op(vdev) __dsc_vdev_can_trans(vdev)
 
 /*

+ 29 - 2
os_if/sync/src/osif_vdev_sync.c

@@ -238,6 +238,29 @@ __osif_vdev_sync_start_wait_callback(struct net_device *net_dev,
 	return 0;
 }
 
+/**
+ * osif_vdev_sync_wait_for_uptree_ops - Wait for psoc/driver operations
+ * @vdev_sync: vdev sync pointer
+ *
+ * If there are any psoc/driver operations are taking place, then vdev
+ * trans/ops should wait for these operations to be completed to avoid
+ * memory domain mismatch issues. For example, if modules are closed
+ * because of idle shutdown, memory domain will be init domain and at
+ * that time if some psoc ops starts, memory allocated as part of this
+ * ops will be allocated in init domain and if at the same time if vdev
+ * up starts which will trigger the vdev trans and will start the
+ * modules and change the memory domain to active domain, now when the
+ * memory allocated as part of psoc operation is release on psoc ops
+ * completion will be released in the active domain which leads the
+ * memory domain mismatch.
+ *
+ * Return: None.
+ */
+static void osif_vdev_sync_wait_for_uptree_ops(struct osif_vdev_sync *vdev_sync)
+{
+	dsc_vdev_wait_for_uptree_ops(vdev_sync->dsc_vdev);
+}
+
 int __osif_vdev_sync_trans_start(struct net_device *net_dev,
 				 struct osif_vdev_sync **out_vdev_sync,
 				 const char *desc)
@@ -249,8 +272,10 @@ int __osif_vdev_sync_trans_start(struct net_device *net_dev,
 						dsc_vdev_trans_start);
 	osif_vdev_sync_unlock();
 
-	if (!errno)
+	if (!errno) {
 		osif_vdev_sync_wait_for_ops(*out_vdev_sync);
+		osif_vdev_sync_wait_for_uptree_ops(*out_vdev_sync);
+	}
 
 	return errno;
 }
@@ -266,8 +291,10 @@ int __osif_vdev_sync_trans_start_wait(struct net_device *net_dev,
 						     out_vdev_sync, desc,
 						     dsc_vdev_trans_start_wait);
 
-	if (!errno)
+	if (!errno) {
 		osif_vdev_sync_wait_for_ops(*out_vdev_sync);
+		osif_vdev_sync_wait_for_uptree_ops(*out_vdev_sync);
+	}
 
 	return errno;
 }