| .. | .. |
|---|
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note |
|---|
| 2 | 2 | /* |
|---|
| 3 | 3 | * |
|---|
| 4 | | - * (C) COPYRIGHT 2015-2021 ARM Limited. All rights reserved. |
|---|
| 4 | + * (C) COPYRIGHT 2015-2023 ARM Limited. All rights reserved. |
|---|
| 5 | 5 | * |
|---|
| 6 | 6 | * This program is free software and is provided to you under the terms of the |
|---|
| 7 | 7 | * GNU General Public License version 2 as published by the Free Software |
|---|
| .. | .. |
|---|
| 24 | 24 | #include "mali_kbase_tracepoints.h" |
|---|
| 25 | 25 | |
|---|
| 26 | 26 | #include <mali_kbase.h> |
|---|
| 27 | | -#include <mali_kbase_jm.h> |
|---|
| 28 | | - |
|---|
| 29 | | -#include <linux/anon_inodes.h> |
|---|
| 30 | 27 | #include <linux/atomic.h> |
|---|
| 31 | 28 | #include <linux/file.h> |
|---|
| 32 | 29 | #include <linux/mutex.h> |
|---|
| .. | .. |
|---|
| 35 | 32 | #include <linux/stringify.h> |
|---|
| 36 | 33 | #include <linux/timer.h> |
|---|
| 37 | 34 | #include <linux/wait.h> |
|---|
| 38 | | - |
|---|
| 35 | +#include <linux/delay.h> |
|---|
| 39 | 36 | |
|---|
| 40 | 37 | /* The period of autoflush checker execution in milliseconds. */ |
|---|
| 41 | 38 | #define AUTOFLUSH_INTERVAL 1000 /* ms */ |
|---|
| .. | .. |
|---|
| 184 | 181 | } |
|---|
| 185 | 182 | #endif /* CONFIG_MALI_BIFROST_DEVFREQ */ |
|---|
| 186 | 183 | |
|---|
| 187 | | -int kbase_timeline_io_acquire(struct kbase_device *kbdev, u32 flags) |
|---|
| 184 | +int kbase_timeline_acquire(struct kbase_device *kbdev, u32 flags) |
|---|
| 188 | 185 | { |
|---|
| 189 | | - int ret = 0; |
|---|
| 186 | + int err = 0; |
|---|
| 190 | 187 | u32 timeline_flags = TLSTREAM_ENABLED | flags; |
|---|
| 191 | | - struct kbase_timeline *timeline = kbdev->timeline; |
|---|
| 188 | + struct kbase_timeline *timeline; |
|---|
| 189 | + int rcode; |
|---|
| 192 | 190 | |
|---|
| 193 | | - if (!atomic_cmpxchg(timeline->timeline_flags, 0, timeline_flags)) { |
|---|
| 194 | | - int rcode; |
|---|
| 191 | + if (WARN_ON(!kbdev) || WARN_ON(flags & ~BASE_TLSTREAM_FLAGS_MASK)) |
|---|
| 192 | + return -EINVAL; |
|---|
| 193 | + |
|---|
| 194 | + timeline = kbdev->timeline; |
|---|
| 195 | + if (WARN_ON(!timeline)) |
|---|
| 196 | + return -EFAULT; |
|---|
| 197 | + |
|---|
| 198 | + if (atomic_cmpxchg(timeline->timeline_flags, 0, timeline_flags)) |
|---|
| 199 | + return -EBUSY; |
|---|
| 195 | 200 | |
|---|
| 196 | 201 | #if MALI_USE_CSF |
|---|
| 197 | | - if (flags & BASE_TLSTREAM_ENABLE_CSFFW_TRACEPOINTS) { |
|---|
| 198 | | - ret = kbase_csf_tl_reader_start( |
|---|
| 199 | | - &timeline->csf_tl_reader, kbdev); |
|---|
| 200 | | - if (ret) |
|---|
| 201 | | - { |
|---|
| 202 | | - atomic_set(timeline->timeline_flags, 0); |
|---|
| 203 | | - return ret; |
|---|
| 204 | | - } |
|---|
| 205 | | - } |
|---|
| 206 | | -#endif |
|---|
| 207 | | - ret = anon_inode_getfd( |
|---|
| 208 | | - "[mali_tlstream]", |
|---|
| 209 | | - &kbasep_tlstream_fops, |
|---|
| 210 | | - timeline, |
|---|
| 211 | | - O_RDONLY | O_CLOEXEC); |
|---|
| 212 | | - if (ret < 0) { |
|---|
| 202 | + if (flags & BASE_TLSTREAM_ENABLE_CSFFW_TRACEPOINTS) { |
|---|
| 203 | + err = kbase_csf_tl_reader_start(&timeline->csf_tl_reader, kbdev); |
|---|
| 204 | + if (err) { |
|---|
| 213 | 205 | atomic_set(timeline->timeline_flags, 0); |
|---|
| 214 | | -#if MALI_USE_CSF |
|---|
| 215 | | - kbase_csf_tl_reader_stop(&timeline->csf_tl_reader); |
|---|
| 216 | | -#endif |
|---|
| 217 | | - return ret; |
|---|
| 206 | + return err; |
|---|
| 218 | 207 | } |
|---|
| 208 | + } |
|---|
| 209 | +#endif |
|---|
| 219 | 210 | |
|---|
| 220 | | - /* Reset and initialize header streams. */ |
|---|
| 221 | | - kbase_tlstream_reset( |
|---|
| 222 | | - &timeline->streams[TL_STREAM_TYPE_OBJ_SUMMARY]); |
|---|
| 211 | + /* Reset and initialize header streams. */ |
|---|
| 212 | + kbase_tlstream_reset(&timeline->streams[TL_STREAM_TYPE_OBJ_SUMMARY]); |
|---|
| 223 | 213 | |
|---|
| 224 | | - timeline->obj_header_btc = obj_desc_header_size; |
|---|
| 225 | | - timeline->aux_header_btc = aux_desc_header_size; |
|---|
| 226 | | - |
|---|
| 227 | | - /* Start autoflush timer. */ |
|---|
| 228 | | - atomic_set(&timeline->autoflush_timer_active, 1); |
|---|
| 229 | | - rcode = mod_timer( |
|---|
| 230 | | - &timeline->autoflush_timer, |
|---|
| 231 | | - jiffies + msecs_to_jiffies(AUTOFLUSH_INTERVAL)); |
|---|
| 232 | | - CSTD_UNUSED(rcode); |
|---|
| 214 | + timeline->obj_header_btc = obj_desc_header_size; |
|---|
| 215 | + timeline->aux_header_btc = aux_desc_header_size; |
|---|
| 233 | 216 | |
|---|
| 234 | 217 | #if !MALI_USE_CSF |
|---|
| 235 | | - /* If job dumping is enabled, readjust the software event's |
|---|
| 236 | | - * timeout as the default value of 3 seconds is often |
|---|
| 237 | | - * insufficient. |
|---|
| 238 | | - */ |
|---|
| 239 | | - if (flags & BASE_TLSTREAM_JOB_DUMPING_ENABLED) { |
|---|
| 240 | | - dev_info(kbdev->dev, |
|---|
| 241 | | - "Job dumping is enabled, readjusting the software event's timeout\n"); |
|---|
| 242 | | - atomic_set(&kbdev->js_data.soft_job_timeout_ms, |
|---|
| 243 | | - 1800000); |
|---|
| 244 | | - } |
|---|
| 218 | + /* If job dumping is enabled, readjust the software event's |
|---|
| 219 | + * timeout as the default value of 3 seconds is often |
|---|
| 220 | + * insufficient. |
|---|
| 221 | + */ |
|---|
| 222 | + if (flags & BASE_TLSTREAM_JOB_DUMPING_ENABLED) { |
|---|
| 223 | + dev_info(kbdev->dev, |
|---|
| 224 | + "Job dumping is enabled, readjusting the software event's timeout\n"); |
|---|
| 225 | + atomic_set(&kbdev->js_data.soft_job_timeout_ms, 1800000); |
|---|
| 226 | + } |
|---|
| 245 | 227 | #endif /* !MALI_USE_CSF */ |
|---|
| 246 | 228 | |
|---|
| 247 | | - /* Summary stream was cleared during acquire. |
|---|
| 248 | | - * Create static timeline objects that will be |
|---|
| 249 | | - * read by client. |
|---|
| 250 | | - */ |
|---|
| 251 | | - kbase_create_timeline_objects(kbdev); |
|---|
| 229 | + /* Summary stream was cleared during acquire. |
|---|
| 230 | + * Create static timeline objects that will be |
|---|
| 231 | + * read by client. |
|---|
| 232 | + */ |
|---|
| 233 | + kbase_create_timeline_objects(kbdev); |
|---|
| 252 | 234 | |
|---|
| 253 | 235 | #ifdef CONFIG_MALI_BIFROST_DEVFREQ |
|---|
| 254 | | - /* Devfreq target tracepoints are only fired when the target |
|---|
| 255 | | - * changes, so we won't know the current target unless we |
|---|
| 256 | | - * send it now. |
|---|
| 257 | | - */ |
|---|
| 258 | | - kbase_tlstream_current_devfreq_target(kbdev); |
|---|
| 236 | + /* Devfreq target tracepoints are only fired when the target |
|---|
| 237 | + * changes, so we won't know the current target unless we |
|---|
| 238 | + * send it now. |
|---|
| 239 | + */ |
|---|
| 240 | + kbase_tlstream_current_devfreq_target(kbdev); |
|---|
| 259 | 241 | #endif /* CONFIG_MALI_BIFROST_DEVFREQ */ |
|---|
| 260 | 242 | |
|---|
| 261 | | - } else { |
|---|
| 262 | | - ret = -EBUSY; |
|---|
| 263 | | - } |
|---|
| 243 | + /* Start the autoflush timer. |
|---|
| 244 | + * We must do this after creating timeline objects to ensure we |
|---|
| 245 | + * don't auto-flush the streams which will be reset during the |
|---|
| 246 | + * summarization process. |
|---|
| 247 | + */ |
|---|
| 248 | + atomic_set(&timeline->autoflush_timer_active, 1); |
|---|
| 249 | + rcode = mod_timer(&timeline->autoflush_timer, |
|---|
| 250 | + jiffies + msecs_to_jiffies(AUTOFLUSH_INTERVAL)); |
|---|
| 251 | + CSTD_UNUSED(rcode); |
|---|
| 264 | 252 | |
|---|
| 265 | | - if (ret >= 0) |
|---|
| 266 | | - timeline->last_acquire_time = ktime_get(); |
|---|
| 253 | + timeline->last_acquire_time = ktime_get_raw(); |
|---|
| 267 | 254 | |
|---|
| 268 | | - return ret; |
|---|
| 255 | + return err; |
|---|
| 256 | +} |
|---|
| 257 | + |
|---|
| 258 | +void kbase_timeline_release(struct kbase_timeline *timeline) |
|---|
| 259 | +{ |
|---|
| 260 | + ktime_t elapsed_time; |
|---|
| 261 | + s64 elapsed_time_ms, time_to_sleep; |
|---|
| 262 | + |
|---|
| 263 | + if (WARN_ON(!timeline) || WARN_ON(!atomic_read(timeline->timeline_flags))) |
|---|
| 264 | + return; |
|---|
| 265 | + |
|---|
| 266 | + /* Get the amount of time passed since the timeline was acquired and ensure |
|---|
| 267 | + * we sleep for long enough such that it has been at least |
|---|
| 268 | + * TIMELINE_HYSTERESIS_TIMEOUT_MS amount of time between acquire and release. |
|---|
| 269 | + * This prevents userspace from spamming acquire and release too quickly. |
|---|
| 270 | + */ |
|---|
| 271 | + elapsed_time = ktime_sub(ktime_get_raw(), timeline->last_acquire_time); |
|---|
| 272 | + elapsed_time_ms = ktime_to_ms(elapsed_time); |
|---|
| 273 | + time_to_sleep = (elapsed_time_ms < 0 ? TIMELINE_HYSTERESIS_TIMEOUT_MS : |
|---|
| 274 | + TIMELINE_HYSTERESIS_TIMEOUT_MS - elapsed_time_ms); |
|---|
| 275 | + if (time_to_sleep > 0) |
|---|
| 276 | + msleep_interruptible(time_to_sleep); |
|---|
| 277 | + |
|---|
| 278 | +#if MALI_USE_CSF |
|---|
| 279 | + kbase_csf_tl_reader_stop(&timeline->csf_tl_reader); |
|---|
| 280 | +#endif |
|---|
| 281 | + |
|---|
| 282 | + /* Stop autoflush timer before releasing access to streams. */ |
|---|
| 283 | + atomic_set(&timeline->autoflush_timer_active, 0); |
|---|
| 284 | + del_timer_sync(&timeline->autoflush_timer); |
|---|
| 285 | + |
|---|
| 286 | + atomic_set(timeline->timeline_flags, 0); |
|---|
| 269 | 287 | } |
|---|
| 270 | 288 | |
|---|
| 271 | 289 | int kbase_timeline_streams_flush(struct kbase_timeline *timeline) |
|---|
| .. | .. |
|---|
| 273 | 291 | enum tl_stream_type stype; |
|---|
| 274 | 292 | bool has_bytes = false; |
|---|
| 275 | 293 | size_t nbytes = 0; |
|---|
| 276 | | -#if MALI_USE_CSF |
|---|
| 277 | | - int ret = kbase_csf_tl_reader_flush_buffer(&timeline->csf_tl_reader); |
|---|
| 278 | 294 | |
|---|
| 279 | | - if (ret > 0) |
|---|
| 280 | | - has_bytes = true; |
|---|
| 295 | + if (WARN_ON(!timeline)) |
|---|
| 296 | + return -EINVAL; |
|---|
| 297 | + |
|---|
| 298 | +#if MALI_USE_CSF |
|---|
| 299 | + { |
|---|
| 300 | + int ret = kbase_csf_tl_reader_flush_buffer(&timeline->csf_tl_reader); |
|---|
| 301 | + |
|---|
| 302 | + if (ret > 0) |
|---|
| 303 | + has_bytes = true; |
|---|
| 304 | + } |
|---|
| 281 | 305 | #endif |
|---|
| 282 | 306 | |
|---|
| 283 | 307 | for (stype = 0; stype < TL_STREAM_TYPE_COUNT; stype++) { |
|---|