diff options
author | Jack Diver <diverj@google.com> | 2024-01-19 12:00:12 +0000 |
---|---|---|
committer | Jack Diver <diverj@google.com> | 2024-02-28 18:26:40 +0000 |
commit | eb7183da312cbc8deabe384779a79a43214a20a9 (patch) | |
tree | bfcc7fa1caef6598e23d62614946da693e0e834b /mali_kbase/platform/pixel | |
parent | fffc58d2b4f70d6655f5022c026e0614df4411e4 (diff) | |
download | gpu-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
Diffstat (limited to 'mali_kbase/platform/pixel')
-rw-r--r-- | mali_kbase/platform/pixel/mali_kbase_config_platform.h | 14 | ||||
-rw-r--r-- | mali_kbase/platform/pixel/pixel_gpu_slc.c | 153 | ||||
-rw-r--r-- | mali_kbase/platform/pixel/pixel_gpu_slc.h | 21 |
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_ */ |