summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Diver <diverj@google.com>2024-01-19 12:00:12 +0000
committerJack Diver <diverj@google.com>2024-02-28 18:26:40 +0000
commiteb7183da312cbc8deabe384779a79a43214a20a9 (patch)
treebfcc7fa1caef6598e23d62614946da693e0e834b
parentfffc58d2b4f70d6655f5022c026e0614df4411e4 (diff)
downloadgpu-eb7183da312cbc8deabe384779a79a43214a20a9.tar.gz
mali_kbase: Repurpose liveness ioctl as SLC signal
Bug: 321199350 Test: gfxbench Signed-off-by: Jack Diver <diverj@google.com> (cherry picked from https://partner-android-review.googlesource.com/q/commit:57ef78bad803aab9d83325f80349f33727af9af8) Merged-In: I94ff92333cae9b9c54f27af550777fc21da06cb7 Change-Id: I94ff92333cae9b9c54f27af550777fc21da06cb7
-rw-r--r--mali_kbase/platform/pixel/mali_kbase_config_platform.h14
-rw-r--r--mali_kbase/platform/pixel/pixel_gpu_slc.c153
-rw-r--r--mali_kbase/platform/pixel/pixel_gpu_slc.h21
3 files changed, 174 insertions, 14 deletions
diff --git a/mali_kbase/platform/pixel/mali_kbase_config_platform.h b/mali_kbase/platform/pixel/mali_kbase_config_platform.h
index 47b1318..f4ae8dc 100644
--- a/mali_kbase/platform/pixel/mali_kbase_config_platform.h
+++ b/mali_kbase/platform/pixel/mali_kbase_config_platform.h
@@ -307,6 +307,7 @@ struct gpu_dvfs_metrics_uid_stats;
* @itmon.nb: The ITMON notifier block.
* @itmon.pa: The faulting physical address.
* @itmon.active: Active count, non-zero while a search is active.
+ * @slc_demand: Tracks demand for SLC space
*/
struct pixel_context {
struct kbase_device *kbdev;
@@ -423,19 +424,26 @@ struct pixel_context {
atomic_t active;
} itmon;
#endif
+#ifndef PIXEL_GPU_SLC_ACPM_SIGNAL
+ atomic_t slc_demand;
+#endif /* PIXEL_GPU_SLC_ACPM_SIGNAL */
};
/**
* struct pixel_platform_data - Per kbase_context Pixel specific platform data
*
- * @kctx: Handle to the parent kctx
- * @stats: Tracks the dvfs metrics for the UID associated with this context
- * @slc_vote: Tracks whether this context is voting for slc
+ * @kctx: Handle to the parent kctx
+ * @stats: Tracks the dvfs metrics for the UID associated with this context
+ * @slc_vote: Tracks whether this context is voting for slc
+ * @slc_demand: Tracks demand for SLC space
*/
struct pixel_platform_data {
struct kbase_context *kctx;
struct gpu_dvfs_metrics_uid_stats* stats;
int slc_vote;
+#ifndef PIXEL_GPU_SLC_ACPM_SIGNAL
+ atomic_t slc_demand;
+#endif /* PIXEL_GPU_SLC_ACPM_SIGNAL */
};
#endif /* _KBASE_CONFIG_PLATFORM_H_ */
diff --git a/mali_kbase/platform/pixel/pixel_gpu_slc.c b/mali_kbase/platform/pixel/pixel_gpu_slc.c
index cf330af..1aac4d8 100644
--- a/mali_kbase/platform/pixel/pixel_gpu_slc.c
+++ b/mali_kbase/platform/pixel/pixel_gpu_slc.c
@@ -48,6 +48,73 @@ static bool transition(int *v, int old, int new)
return cond;
}
+#ifndef PIXEL_GPU_SLC_ACPM_SIGNAL
+/**
+ * struct gpu_slc_liveness_update_info - Buffer info, and live ranges
+ *
+ * @buffer_sizes: Array of buffer sizes
+ * @buffer_count: Number of elements in the va and sizes buffers
+ * @live_ranges: Array of &struct kbase_pixel_gpu_slc_liveness_mark denoting live ranges for
+ * each buffer
+ * @live_ranges_count: Number of elements in the live ranges buffer
+ */
+struct gpu_slc_liveness_update_info {
+ u64* buffer_sizes;
+ u64 buffer_count;
+ struct kbase_pixel_gpu_slc_liveness_mark* live_ranges;
+ u64 live_ranges_count;
+};
+
+/**
+ * gpu_slc_liveness_update - Respond to a liveness update by trying to put the new buffers into free
+ * SLC space, and resizing the partition to meet demand.
+ *
+ * @kctx: The &struct kbase_context corresponding to a user space context which sent the liveness
+ * update
+ * @info: See struct gpu_slc_liveness_update_info
+ */
+static void gpu_slc_liveness_update(struct kbase_context* kctx,
+ struct gpu_slc_liveness_update_info* info)
+{
+ struct kbase_device* kbdev = kctx->kbdev;
+ struct pixel_context *pc = kbdev->platform_context;
+ struct pixel_platform_data *kctx_pd = kctx->platform_data;
+ s64 current_demand = 0, peak_demand = 0, old_demand;
+ int i;
+
+ dev_dbg(kbdev->dev, "pixel: buffer liveness update received");
+
+ for (i = 0; i < info->live_ranges_count; ++i)
+ {
+ u64 size;
+ u32 index = info->live_ranges[i].index;
+
+ if (unlikely(index >= info->buffer_count))
+ continue;
+
+ size = info->buffer_sizes[index];
+
+ switch (info->live_ranges[i].type)
+ {
+ case KBASE_PIXEL_GPU_LIVE_RANGE_BEGIN:
+ /* Update demand as though there's no size limit */
+ current_demand += size;
+ peak_demand = max(peak_demand, current_demand);
+ break;
+ case KBASE_PIXEL_GPU_LIVE_RANGE_END:
+ current_demand -= size;
+ break;
+ }
+ }
+
+ /* Indicates a missing live range end marker */
+ WARN_ON_ONCE(current_demand != 0);
+
+ /* Update the demand */
+ old_demand = atomic_xchg(&kctx_pd->slc_demand, peak_demand);
+ atomic_add(peak_demand - old_demand, &pc->slc_demand);
+}
+
/**
* gpu_pixel_handle_buffer_liveness_update_ioctl() - See gpu_slc_liveness_update
*
@@ -61,9 +128,74 @@ static bool transition(int *v, int old, int new)
int gpu_pixel_handle_buffer_liveness_update_ioctl(struct kbase_context* kctx,
struct kbase_ioctl_buffer_liveness_update* update)
{
- (void)kctx, (void)update;
- return 0;
+ int err = -EINVAL;
+ struct gpu_slc_liveness_update_info info;
+ u64* buff = NULL;
+ u64 total_buff_size;
+
+ /* Compute the sizes of the user space arrays that we need to copy */
+ u64 const buffer_info_size = sizeof(u64) * update->buffer_count;
+ u64 const live_ranges_size =
+ sizeof(struct kbase_pixel_gpu_slc_liveness_mark) * update->live_ranges_count;
+
+ /* Guard against overflows and empty sizes */
+ if (!buffer_info_size || !live_ranges_size)
+ goto done;
+ if (U64_MAX / sizeof(u64) < update->buffer_count)
+ goto done;
+ if (U64_MAX / sizeof(struct kbase_pixel_gpu_slc_liveness_mark) < update->live_ranges_count)
+ goto done;
+ /* Guard against nullptr */
+ if (!update->live_ranges_address || !update->buffer_sizes_address)
+ goto done;
+ /* Calculate the total buffer size required and detect overflows */
+ if ((U64_MAX - live_ranges_size) < buffer_info_size)
+ goto done;
+
+ total_buff_size = buffer_info_size + live_ranges_size;
+
+ /* Allocate the memory we require to copy from user space */
+ buff = kmalloc(total_buff_size, GFP_KERNEL);
+ if (buff == NULL) {
+ dev_err(kctx->kbdev->dev, "pixel: failed to allocate buffer for liveness update");
+ err = -ENOMEM;
+ goto done;
+ }
+
+ /* Set up the info struct by pointing into the allocation. All 8 byte aligned */
+ info = (struct gpu_slc_liveness_update_info){
+ .buffer_sizes = buff,
+ .buffer_count = update->buffer_count,
+ .live_ranges = (struct kbase_pixel_gpu_slc_liveness_mark*)(buff + update->buffer_count),
+ .live_ranges_count = update->live_ranges_count,
+ };
+
+ /* Copy the data from user space */
+ err = copy_from_user(
+ info.live_ranges, u64_to_user_ptr(update->live_ranges_address), live_ranges_size);
+ if (err) {
+ dev_err(kctx->kbdev->dev, "pixel: failed to copy live ranges");
+ err = -EFAULT;
+ goto done;
+ }
+
+ err = copy_from_user(
+ info.buffer_sizes, u64_to_user_ptr(update->buffer_sizes_address), buffer_info_size);
+ if (err) {
+ dev_err(kctx->kbdev->dev, "pixel: failed to copy buffer sizes");
+ err = -EFAULT;
+ goto done;
+ }
+
+ /* Execute an slc update */
+ gpu_slc_liveness_update(kctx, &info);
+
+done:
+ kfree(buff);
+
+ return err;
}
+#endif /* PIXEL_GPU_SLC_ACPM_SIGNAL */
/**
* gpu_slc_kctx_init() - Called when a kernel context is created
@@ -93,6 +225,15 @@ void gpu_slc_kctx_term(struct kbase_context *kctx)
/* Contexts can be terminated without being idled first */
if (transition(&pd->slc_vote, VOTING, IDLE))
pixel_mgm_slc_dec_refcount(kctx->kbdev->mgm_dev);
+
+#ifndef PIXEL_GPU_SLC_ACPM_SIGNAL
+ {
+ struct pixel_context* pc = kctx->kbdev->platform_context;
+ /* Deduct the usage and demand, freeing that SLC space for the next update */
+ u64 kctx_demand = atomic_xchg(&pd->slc_demand, 0);
+ atomic_sub(kctx_demand, &pc->slc_demand);
+ }
+#endif /* PIXEL_GPU_SLC_ACPM_SIGNAL */
}
/**
@@ -132,7 +273,15 @@ void gpu_slc_kctx_idle(struct kbase_context *kctx)
*/
void gpu_slc_tick_tock(struct kbase_device *kbdev)
{
+#ifndef PIXEL_GPU_SLC_ACPM_SIGNAL
+ struct pixel_context* pc = kbdev->platform_context;
+ /* Threshold of 4MB */
+ u64 signal = atomic_read(&pc->slc_demand) / (4 << 20);
+
+ pixel_mgm_slc_update_signal(kbdev->mgm_dev, signal);
+#else
pixel_mgm_slc_update_signal(kbdev->mgm_dev, 0);
+#endif /* PIXEL_GPU_SLC_ACPM_SIGNAL */
}
/**
diff --git a/mali_kbase/platform/pixel/pixel_gpu_slc.h b/mali_kbase/platform/pixel/pixel_gpu_slc.h
index cca2af9..8a59df0 100644
--- a/mali_kbase/platform/pixel/pixel_gpu_slc.h
+++ b/mali_kbase/platform/pixel/pixel_gpu_slc.h
@@ -8,9 +8,6 @@
#define _PIXEL_GPU_SLC_H_
#ifdef CONFIG_MALI_PIXEL_GPU_SLC
-int gpu_pixel_handle_buffer_liveness_update_ioctl(struct kbase_context* kctx,
- struct kbase_ioctl_buffer_liveness_update* update);
-
int gpu_slc_init(struct kbase_device *kbdev);
void gpu_slc_term(struct kbase_device *kbdev);
@@ -25,12 +22,6 @@ void gpu_slc_kctx_idle(struct kbase_context *kctx);
void gpu_slc_tick_tock(struct kbase_device *kbdev);
#else
-static int __maybe_unused gpu_pixel_handle_buffer_liveness_update_ioctl(struct kbase_context* kctx,
- struct kbase_ioctl_buffer_liveness_update* update)
-{
- return (void)kctx, (void)update, 0;
-}
-
static int __maybe_unused gpu_slc_init(struct kbase_device *kbdev) { return (void)kbdev, 0; }
static void __maybe_unused gpu_slc_term(struct kbase_device *kbdev) { (void)kbdev; }
@@ -46,4 +37,16 @@ static void __maybe_unused gpu_slc_kctx_idle(struct kbase_context *kctx) { (void
static void __maybe_unused gpu_slc_tick_tock(struct kbase_device *kbdev) { (void)kbdev; }
#endif /* CONFIG_MALI_PIXEL_GPU_SLC */
+#if defined(CONFIG_MALI_PIXEL_GPU_SLC) && !defined(PIXEL_GPU_SLC_ACPM_SIGNAL)
+int
+gpu_pixel_handle_buffer_liveness_update_ioctl(struct kbase_context* kctx,
+ struct kbase_ioctl_buffer_liveness_update* update);
+#else
+static int __maybe_unused gpu_pixel_handle_buffer_liveness_update_ioctl(struct kbase_context* kctx,
+ struct kbase_ioctl_buffer_liveness_update* update)
+{
+ return (void)kctx, (void)update, 0;
+}
+#endif
+
#endif /* _PIXEL_GPU_SLC_H_ */