hc
2024-05-16 8d2a02b24d66aa359e83eebc1ed3c0f85367a1cb
kernel/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline_io.c
....@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
22 /*
33 *
4
- * (C) COPYRIGHT 2019-2021 ARM Limited. All rights reserved.
4
+ * (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved.
55 *
66 * This program is free software and is provided to you under the terms of the
77 * GNU General Public License version 2 as published by the Free Software
....@@ -24,26 +24,74 @@
2424 #include "mali_kbase_tracepoints.h"
2525 #include "mali_kbase_timeline.h"
2626
27
-#include <linux/delay.h>
27
+#include <device/mali_kbase_device.h>
28
+
2829 #include <linux/poll.h>
30
+#include <linux/version_compat_defs.h>
31
+#include <linux/anon_inodes.h>
32
+
33
+/* Explicitly include epoll header for old kernels. Not required from 4.16. */
34
+#if KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE
35
+#include <uapi/linux/eventpoll.h>
36
+#endif
37
+
38
+static int kbase_unprivileged_global_profiling;
39
+
40
+/**
41
+ * kbase_unprivileged_global_profiling_set - set permissions for unprivileged processes
42
+ *
43
+ * @val: String containing value to set. Only strings representing positive
44
+ * integers are accepted as valid; any non-positive integer (including 0)
45
+ * is rejected.
46
+ * @kp: Module parameter associated with this method.
47
+ *
48
+ * This method can only be used to enable permissions for unprivileged processes,
49
+ * if they are disabled: for this reason, the only values which are accepted are
50
+ * strings representing positive integers. Since it's impossible to disable
51
+ * permissions once they're set, any integer which is non-positive is rejected,
52
+ * including 0.
53
+ *
54
+ * Return: 0 if success, otherwise error code.
55
+ */
56
+static int kbase_unprivileged_global_profiling_set(const char *val, const struct kernel_param *kp)
57
+{
58
+ int new_val;
59
+ int ret = kstrtoint(val, 0, &new_val);
60
+
61
+ if (ret == 0) {
62
+ if (new_val < 1)
63
+ return -EINVAL;
64
+
65
+ kbase_unprivileged_global_profiling = 1;
66
+ }
67
+
68
+ return ret;
69
+}
70
+
71
+static const struct kernel_param_ops kbase_global_unprivileged_profiling_ops = {
72
+ .get = param_get_int,
73
+ .set = kbase_unprivileged_global_profiling_set,
74
+};
75
+
76
+module_param_cb(kbase_unprivileged_global_profiling, &kbase_global_unprivileged_profiling_ops,
77
+ &kbase_unprivileged_global_profiling, 0600);
2978
3079 /* The timeline stream file operations functions. */
3180 static ssize_t kbasep_timeline_io_read(struct file *filp, char __user *buffer,
3281 size_t size, loff_t *f_pos);
33
-static unsigned int kbasep_timeline_io_poll(struct file *filp,
34
- poll_table *wait);
82
+static __poll_t kbasep_timeline_io_poll(struct file *filp, poll_table *wait);
3583 static int kbasep_timeline_io_release(struct inode *inode, struct file *filp);
3684 static int kbasep_timeline_io_fsync(struct file *filp, loff_t start, loff_t end,
3785 int datasync);
3886
39
-/* The timeline stream file operations structure. */
40
-const struct file_operations kbasep_tlstream_fops = {
41
- .owner = THIS_MODULE,
42
- .release = kbasep_timeline_io_release,
43
- .read = kbasep_timeline_io_read,
44
- .poll = kbasep_timeline_io_poll,
45
- .fsync = kbasep_timeline_io_fsync,
46
-};
87
+static bool timeline_is_permitted(void)
88
+{
89
+#if KERNEL_VERSION(5, 8, 0) <= LINUX_VERSION_CODE
90
+ return kbase_unprivileged_global_profiling || perfmon_capable();
91
+#else
92
+ return kbase_unprivileged_global_profiling || capable(CAP_SYS_ADMIN);
93
+#endif
94
+}
4795
4896 /**
4997 * kbasep_timeline_io_packet_pending - check timeline streams for pending
....@@ -115,7 +163,7 @@
115163 * @hdr_size: Header size.
116164 * @hdr_btc: Pointer to the remaining number of bytes to copy.
117165 *
118
- * Returns: 0 if success, -1 otherwise.
166
+ * Return: 0 if success, -1 otherwise.
119167 */
120168 static inline int copy_stream_header(char __user *buffer, size_t size,
121169 ssize_t *copy_len, const char *hdr,
....@@ -140,7 +188,7 @@
140188 }
141189
142190 /**
143
- * kbasep_timeline_copy_header - copy timeline headers to the user
191
+ * kbasep_timeline_copy_headers - copy timeline headers to the user
144192 *
145193 * @timeline: Timeline instance
146194 * @buffer: Pointer to the buffer provided by user
....@@ -152,7 +200,7 @@
152200 * to the user, and if so, sends them. copy_len is respectively
153201 * updated.
154202 *
155
- * Returns: 0 if success, -1 if copy_to_user has failed.
203
+ * Return: 0 if success, -1 if copy_to_user has failed.
156204 */
157205 static inline int kbasep_timeline_copy_headers(struct kbase_timeline *timeline,
158206 char __user *buffer, size_t size,
....@@ -289,9 +337,11 @@
289337 * kbasep_timeline_io_poll - poll timeline stream for packets
290338 * @filp: Pointer to file structure
291339 * @wait: Pointer to poll table
292
- * Return: POLLIN if data can be read without blocking, otherwise zero
340
+ *
341
+ * Return: EPOLLIN | EPOLLRDNORM if data can be read without blocking,
342
+ * otherwise zero, or EPOLLHUP | EPOLLERR on error.
293343 */
294
-static unsigned int kbasep_timeline_io_poll(struct file *filp, poll_table *wait)
344
+static __poll_t kbasep_timeline_io_poll(struct file *filp, poll_table *wait)
295345 {
296346 struct kbase_tlstream *stream;
297347 unsigned int rb_idx;
....@@ -301,78 +351,115 @@
301351 KBASE_DEBUG_ASSERT(wait);
302352
303353 if (WARN_ON(!filp->private_data))
304
- return -EFAULT;
354
+ return EPOLLHUP | EPOLLERR;
305355
306356 timeline = (struct kbase_timeline *)filp->private_data;
307357
308358 /* If there are header bytes to copy, read will not block */
309359 if (kbasep_timeline_has_header_data(timeline))
310
- return POLLIN;
360
+ return EPOLLIN | EPOLLRDNORM;
311361
312362 poll_wait(filp, &timeline->event_queue, wait);
313363 if (kbasep_timeline_io_packet_pending(timeline, &stream, &rb_idx))
314
- return POLLIN;
315
- return 0;
364
+ return EPOLLIN | EPOLLRDNORM;
365
+
366
+ return (__poll_t)0;
316367 }
368
+
369
+int kbase_timeline_io_acquire(struct kbase_device *kbdev, u32 flags)
370
+{
371
+ /* The timeline stream file operations structure. */
372
+ static const struct file_operations kbasep_tlstream_fops = {
373
+ .owner = THIS_MODULE,
374
+ .release = kbasep_timeline_io_release,
375
+ .read = kbasep_timeline_io_read,
376
+ .poll = kbasep_timeline_io_poll,
377
+ .fsync = kbasep_timeline_io_fsync,
378
+ };
379
+ int err;
380
+
381
+ if (!timeline_is_permitted())
382
+ return -EPERM;
383
+
384
+ if (WARN_ON(!kbdev) || (flags & ~BASE_TLSTREAM_FLAGS_MASK))
385
+ return -EINVAL;
386
+
387
+ err = kbase_timeline_acquire(kbdev, flags);
388
+ if (err)
389
+ return err;
390
+
391
+ err = anon_inode_getfd("[mali_tlstream]", &kbasep_tlstream_fops, kbdev->timeline,
392
+ O_RDONLY | O_CLOEXEC);
393
+ if (err < 0)
394
+ kbase_timeline_release(kbdev->timeline);
395
+
396
+ return err;
397
+}
398
+
399
+#if IS_ENABLED(CONFIG_DEBUG_FS)
400
+static int kbasep_timeline_io_open(struct inode *in, struct file *file)
401
+{
402
+ struct kbase_device *const kbdev = in->i_private;
403
+
404
+ if (WARN_ON(!kbdev))
405
+ return -EFAULT;
406
+
407
+ file->private_data = kbdev->timeline;
408
+ return kbase_timeline_acquire(kbdev, BASE_TLSTREAM_FLAGS_MASK &
409
+ ~BASE_TLSTREAM_JOB_DUMPING_ENABLED);
410
+}
411
+
412
+void kbase_timeline_io_debugfs_init(struct kbase_device *const kbdev)
413
+{
414
+ static const struct file_operations kbasep_tlstream_debugfs_fops = {
415
+ .owner = THIS_MODULE,
416
+ .open = kbasep_timeline_io_open,
417
+ .release = kbasep_timeline_io_release,
418
+ .read = kbasep_timeline_io_read,
419
+ .poll = kbasep_timeline_io_poll,
420
+ .fsync = kbasep_timeline_io_fsync,
421
+ };
422
+ struct dentry *file;
423
+
424
+ if (WARN_ON(!kbdev) || WARN_ON(IS_ERR_OR_NULL(kbdev->mali_debugfs_directory)))
425
+ return;
426
+
427
+ file = debugfs_create_file("tlstream", 0400, kbdev->mali_debugfs_directory, kbdev,
428
+ &kbasep_tlstream_debugfs_fops);
429
+
430
+ if (IS_ERR_OR_NULL(file))
431
+ dev_warn(kbdev->dev, "Unable to create timeline debugfs entry");
432
+}
433
+#else
434
+/*
435
+ * Stub function for when debugfs is disabled
436
+ */
437
+void kbase_timeline_io_debugfs_init(struct kbase_device *const kbdev)
438
+{
439
+}
440
+#endif
317441
318442 /**
319443 * kbasep_timeline_io_release - release timeline stream descriptor
320444 * @inode: Pointer to inode structure
321445 * @filp: Pointer to file structure
322446 *
323
- * Return always return zero
447
+ * Return: always return zero
324448 */
325449 static int kbasep_timeline_io_release(struct inode *inode, struct file *filp)
326450 {
327
- struct kbase_timeline *timeline;
328
- ktime_t elapsed_time;
329
- s64 elapsed_time_ms, time_to_sleep;
330
-
331
- KBASE_DEBUG_ASSERT(inode);
332
- KBASE_DEBUG_ASSERT(filp);
333
- KBASE_DEBUG_ASSERT(filp->private_data);
334
-
335451 CSTD_UNUSED(inode);
336452
337
- timeline = (struct kbase_timeline *)filp->private_data;
338
-
339
- /* Get the amount of time passed since the timeline was acquired and ensure
340
- * we sleep for long enough such that it has been at least
341
- * TIMELINE_HYSTERESIS_TIMEOUT_MS amount of time between acquire and release.
342
- * This prevents userspace from spamming acquire and release too quickly.
343
- */
344
- elapsed_time = ktime_sub(ktime_get(), timeline->last_acquire_time);
345
- elapsed_time_ms = ktime_to_ms(elapsed_time);
346
- time_to_sleep = MIN(TIMELINE_HYSTERESIS_TIMEOUT_MS,
347
- TIMELINE_HYSTERESIS_TIMEOUT_MS - elapsed_time_ms);
348
- if (time_to_sleep > 0)
349
- msleep(time_to_sleep);
350
-
351
-#if MALI_USE_CSF
352
- kbase_csf_tl_reader_stop(&timeline->csf_tl_reader);
353
-#endif
354
-
355
- /* Stop autoflush timer before releasing access to streams. */
356
- atomic_set(&timeline->autoflush_timer_active, 0);
357
- del_timer_sync(&timeline->autoflush_timer);
358
-
359
- atomic_set(timeline->timeline_flags, 0);
453
+ kbase_timeline_release(filp->private_data);
360454 return 0;
361455 }
362456
363457 static int kbasep_timeline_io_fsync(struct file *filp, loff_t start, loff_t end,
364458 int datasync)
365459 {
366
- struct kbase_timeline *timeline;
367
-
368460 CSTD_UNUSED(start);
369461 CSTD_UNUSED(end);
370462 CSTD_UNUSED(datasync);
371463
372
- if (WARN_ON(!filp->private_data))
373
- return -EFAULT;
374
-
375
- timeline = (struct kbase_timeline *)filp->private_data;
376
-
377
- return kbase_timeline_streams_flush(timeline);
464
+ return kbase_timeline_streams_flush(filp->private_data);
378465 }