diff mbox series

[RFC,v2,7/8] drm/panthor: Add suspend/resume handling for the performance counters

Message ID 20241211165024.490748-8-lukas.zapolskas@arm.com (mailing list archive)
State New, archived
Headers show
Series drm/panthor: Add performance counters with manual sampling mode | expand

Commit Message

Lukas Zapolskas Dec. 11, 2024, 4:50 p.m. UTC
Signed-off-by: Lukas Zapolskas <lukas.zapolskas@arm.com>
---
 drivers/gpu/drm/panthor/panthor_device.c |  3 +
 drivers/gpu/drm/panthor/panthor_perf.c   | 86 ++++++++++++++++++++++++
 drivers/gpu/drm/panthor/panthor_perf.h   |  2 +
 3 files changed, 91 insertions(+)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
index 1a81a436143b..69536fbdb5ef 100644
--- a/drivers/gpu/drm/panthor/panthor_device.c
+++ b/drivers/gpu/drm/panthor/panthor_device.c
@@ -475,6 +475,7 @@  int panthor_device_resume(struct device *dev)
 		ret = drm_WARN_ON(&ptdev->base, panthor_fw_resume(ptdev));
 		if (!ret) {
 			panthor_sched_resume(ptdev);
+			panthor_perf_resume(ptdev);
 		} else {
 			panthor_mmu_suspend(ptdev);
 			panthor_gpu_suspend(ptdev);
@@ -543,6 +544,7 @@  int panthor_device_suspend(struct device *dev)
 	    drm_dev_enter(&ptdev->base, &cookie)) {
 		cancel_work_sync(&ptdev->reset.work);
 
+		panthor_perf_suspend(ptdev);
 		/* We prepare everything as if we were resetting the GPU.
 		 * The end of the reset will happen in the resume path though.
 		 */
@@ -561,6 +563,7 @@  int panthor_device_suspend(struct device *dev)
 			panthor_mmu_resume(ptdev);
 			drm_WARN_ON(&ptdev->base, panthor_fw_resume(ptdev));
 			panthor_sched_resume(ptdev);
+			panthor_perf_resume(ptdev);
 			drm_dev_exit(cookie);
 		}
 
diff --git a/drivers/gpu/drm/panthor/panthor_perf.c b/drivers/gpu/drm/panthor/panthor_perf.c
index d62d97c448da..727e66074eab 100644
--- a/drivers/gpu/drm/panthor/panthor_perf.c
+++ b/drivers/gpu/drm/panthor/panthor_perf.c
@@ -433,6 +433,17 @@  static void panthor_perf_em_zero(struct panthor_perf_enable_masks *em)
 		bitmap_zero(em->mask[i], PANTHOR_PERF_EM_BITS);
 }
 
+static bool panthor_perf_em_empty(const struct panthor_perf_enable_masks *const em)
+{
+	bool empty = true;
+	size_t i = 0;
+
+	for (i = DRM_PANTHOR_PERF_BLOCK_FW; i <= DRM_PANTHOR_PERF_BLOCK_LAST; i++)
+		empty &= bitmap_empty(em->mask[i], PANTHOR_PERF_EM_BITS);
+
+	return empty;
+}
+
 static void panthor_perf_destroy_em_kref(struct kref *em_kref)
 {
 	struct panthor_perf_enable_masks *em = container_of(em_kref, typeof(*em), refs);
@@ -1652,6 +1663,81 @@  void panthor_perf_session_destroy(struct panthor_file *pfile, struct panthor_per
 	}
 }
 
+static int panthor_perf_sampler_resume(struct panthor_perf_sampler *sampler)
+{
+	int ret;
+
+	if (!atomic_read(&sampler->enabled_clients))
+		return 0;
+
+	if (!panthor_perf_em_empty(sampler->em)) {
+		guard(mutex)(&sampler->config_lock);
+		panthor_perf_fw_write_em(sampler, sampler->em);
+	}
+
+	ret = panthor_perf_fw_start_sampling(sampler->ptdev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int panthor_perf_sampler_suspend(struct panthor_perf_sampler *sampler)
+{
+	int ret;
+
+	if (!atomic_read(&sampler->enabled_clients))
+		return 0;
+
+	ret = panthor_perf_fw_stop_sampling(sampler->ptdev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+/**
+ * panthor_perf_suspend - Prepare the performance counter subsystem for system suspend.
+ * @ptdev: Panthor device.
+ *
+ * Indicate to the performance counters that the system is suspending.
+ *
+ * This function must not be used to handle MCU power state transitions: just before MCU goes
+ * from on to any inactive state, an automatic sample will be performed by the firmware, and
+ * the performance counter firmware state will be restored on warm boot.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int panthor_perf_suspend(struct panthor_device *ptdev)
+{
+	struct panthor_perf *perf = ptdev->perf;
+
+	if (!perf)
+		return 0;
+
+	return panthor_perf_sampler_suspend(&perf->sampler);
+}
+
+/**
+ * panthor_perf_resume - Resume the performance counter subsystem after system resumption.
+ * @ptdev: Panthor device.
+ *
+ * Indicate to the performance counters that the system has resumed. This must not be used
+ * to handle MCU state transitions, for the same reasons as detailed in the kerneldoc for
+ * @panthor_perf_suspend.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int panthor_perf_resume(struct panthor_device *ptdev)
+{
+	struct panthor_perf *perf = ptdev->perf;
+
+	if (!perf)
+		return 0;
+
+	return panthor_perf_sampler_resume(&perf->sampler);
+}
+
 /**
  * panthor_perf_unplug - Terminate the performance counter subsystem.
  * @ptdev: Panthor device.
diff --git a/drivers/gpu/drm/panthor/panthor_perf.h b/drivers/gpu/drm/panthor/panthor_perf.h
index 3485e4a55e15..a22a511a0809 100644
--- a/drivers/gpu/drm/panthor/panthor_perf.h
+++ b/drivers/gpu/drm/panthor/panthor_perf.h
@@ -16,6 +16,8 @@  struct panthor_perf;
 void panthor_perf_info_init(struct panthor_device *ptdev);
 
 int panthor_perf_init(struct panthor_device *ptdev);
+int panthor_perf_suspend(struct panthor_device *ptdev);
+int panthor_perf_resume(struct panthor_device *ptdev);
 void panthor_perf_unplug(struct panthor_device *ptdev);
 
 int panthor_perf_session_setup(struct panthor_device *ptdev, struct panthor_perf *perf,