.. | .. |
---|
1 | 1 | // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note |
---|
2 | 2 | /* |
---|
3 | 3 | * |
---|
4 | | - * (C) COPYRIGHT 2011-2021 ARM Limited. All rights reserved. |
---|
| 4 | + * (C) COPYRIGHT 2011-2022 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 |
---|
.. | .. |
---|
20 | 20 | */ |
---|
21 | 21 | |
---|
22 | 22 | #include "mali_kbase_vinstr.h" |
---|
23 | | -#include "mali_kbase_hwcnt_virtualizer.h" |
---|
24 | | -#include "mali_kbase_hwcnt_types.h" |
---|
| 23 | +#include "hwcnt/mali_kbase_hwcnt_virtualizer.h" |
---|
| 24 | +#include "hwcnt/mali_kbase_hwcnt_types.h" |
---|
25 | 25 | #include <uapi/gpu/arm/bifrost/mali_kbase_hwcnt_reader.h> |
---|
26 | | -#include "mali_kbase_hwcnt_gpu.h" |
---|
| 26 | +#include "hwcnt/mali_kbase_hwcnt_gpu.h" |
---|
| 27 | +#include "hwcnt/mali_kbase_hwcnt_gpu_narrow.h" |
---|
27 | 28 | #include <uapi/gpu/arm/bifrost/mali_kbase_ioctl.h> |
---|
28 | 29 | #include "mali_malisw.h" |
---|
29 | 30 | #include "mali_kbase_debug.h" |
---|
.. | .. |
---|
37 | 38 | #include <linux/mutex.h> |
---|
38 | 39 | #include <linux/poll.h> |
---|
39 | 40 | #include <linux/slab.h> |
---|
| 41 | +#include <linux/version_compat_defs.h> |
---|
40 | 42 | #include <linux/workqueue.h> |
---|
| 43 | + |
---|
| 44 | +/* Explicitly include epoll header for old kernels. Not required from 4.16. */ |
---|
| 45 | +#if KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE |
---|
| 46 | +#include <uapi/linux/eventpoll.h> |
---|
| 47 | +#endif |
---|
41 | 48 | |
---|
42 | 49 | /* Hwcnt reader API version */ |
---|
43 | 50 | #define HWCNT_READER_API 1 |
---|
.. | .. |
---|
55 | 62 | * @metadata: Hardware counter metadata provided by virtualizer. |
---|
56 | 63 | * @metadata_user: API compatible hardware counter metadata provided by vinstr. |
---|
57 | 64 | * For compatibility with the user driver interface, this |
---|
58 | | - * contains a "truncated" version of the HWCNT metadata limited |
---|
59 | | - * to 64 entries per block. NULL when not required. |
---|
| 65 | + * contains a narrowed version of the HWCNT metadata limited |
---|
| 66 | + * to 64 entries per block of 32 bits each. |
---|
60 | 67 | * @lock: Lock protecting all vinstr state. |
---|
61 | 68 | * @suspend_count: Suspend reference count. If non-zero, timer and worker are |
---|
62 | 69 | * prevented from being re-scheduled. |
---|
.. | .. |
---|
68 | 75 | struct kbase_vinstr_context { |
---|
69 | 76 | struct kbase_hwcnt_virtualizer *hvirt; |
---|
70 | 77 | const struct kbase_hwcnt_metadata *metadata; |
---|
71 | | - const struct kbase_hwcnt_metadata *metadata_user; |
---|
| 78 | + const struct kbase_hwcnt_metadata_narrow *metadata_user; |
---|
72 | 79 | struct mutex lock; |
---|
73 | 80 | size_t suspend_count; |
---|
74 | 81 | size_t client_count; |
---|
.. | .. |
---|
89 | 96 | * occur. If 0, not a periodic client. |
---|
90 | 97 | * @enable_map: Counters enable map. |
---|
91 | 98 | * @tmp_buf: Temporary buffer to use before handing dump to client. |
---|
92 | | - * @dump_bufs: Array of dump buffers allocated by this client. |
---|
93 | | - * @dump_bufs_meta: Metadata of dump buffers. |
---|
| 99 | + * @dump_bufs: Array of narrow dump buffers allocated by this client. |
---|
| 100 | + * @dump_bufs_meta: Metadata of hwcnt reader client buffers. |
---|
94 | 101 | * @meta_idx: Index of metadata being accessed by userspace. |
---|
95 | 102 | * @read_idx: Index of buffer read by userspace. |
---|
96 | 103 | * @write_idx: Index of buffer being written by dump worker. |
---|
.. | .. |
---|
104 | 111 | u32 dump_interval_ns; |
---|
105 | 112 | struct kbase_hwcnt_enable_map enable_map; |
---|
106 | 113 | struct kbase_hwcnt_dump_buffer tmp_buf; |
---|
107 | | - struct kbase_hwcnt_dump_buffer_array dump_bufs; |
---|
| 114 | + struct kbase_hwcnt_dump_buffer_narrow_array dump_bufs; |
---|
108 | 115 | struct kbase_hwcnt_reader_metadata *dump_bufs_meta; |
---|
109 | 116 | atomic_t meta_idx; |
---|
110 | 117 | atomic_t read_idx; |
---|
.. | .. |
---|
112 | 119 | wait_queue_head_t waitq; |
---|
113 | 120 | }; |
---|
114 | 121 | |
---|
115 | | -static unsigned int kbasep_vinstr_hwcnt_reader_poll( |
---|
116 | | - struct file *filp, |
---|
117 | | - poll_table *wait); |
---|
| 122 | +static __poll_t kbasep_vinstr_hwcnt_reader_poll(struct file *filp, poll_table *wait); |
---|
118 | 123 | |
---|
119 | 124 | static long kbasep_vinstr_hwcnt_reader_ioctl( |
---|
120 | 125 | struct file *filp, |
---|
.. | .. |
---|
190 | 195 | unsigned int write_idx; |
---|
191 | 196 | unsigned int read_idx; |
---|
192 | 197 | struct kbase_hwcnt_dump_buffer *tmp_buf; |
---|
193 | | - struct kbase_hwcnt_dump_buffer *dump_buf; |
---|
| 198 | + struct kbase_hwcnt_dump_buffer_narrow *dump_buf; |
---|
194 | 199 | struct kbase_hwcnt_reader_metadata *meta; |
---|
195 | 200 | u8 clk_cnt; |
---|
196 | 201 | |
---|
.. | .. |
---|
223 | 228 | * variant will explicitly zero any non-enabled counters to ensure |
---|
224 | 229 | * nothing except exactly what the user asked for is made visible. |
---|
225 | 230 | * |
---|
226 | | - * If the metadata in vinstr (vctx->metadata_user) is not NULL, it means |
---|
227 | | - * vinstr has the truncated metadata, so do a narrow copy since |
---|
228 | | - * virtualizer has a bigger buffer but user only needs part of it. |
---|
229 | | - * otherwise we do a full copy. |
---|
| 231 | + * A narrow copy is required since virtualizer has a bigger buffer |
---|
| 232 | + * but user only needs part of it. |
---|
230 | 233 | */ |
---|
231 | | - if (vcli->vctx->metadata_user) |
---|
232 | | - kbase_hwcnt_dump_buffer_copy_strict_narrow(dump_buf, tmp_buf, |
---|
233 | | - &vcli->enable_map); |
---|
234 | | - else |
---|
235 | | - kbase_hwcnt_dump_buffer_copy_strict(dump_buf, tmp_buf, |
---|
236 | | - &vcli->enable_map); |
---|
| 234 | + kbase_hwcnt_dump_buffer_copy_strict_narrow(dump_buf, tmp_buf, |
---|
| 235 | + &vcli->enable_map); |
---|
237 | 236 | |
---|
238 | 237 | clk_cnt = vcli->vctx->metadata->clk_cnt; |
---|
239 | 238 | |
---|
.. | .. |
---|
362 | 361 | * kbasep_vinstr_dump_timer() - Dump timer that schedules the dump worker for |
---|
363 | 362 | * execution as soon as possible. |
---|
364 | 363 | * @timer: Timer structure. |
---|
| 364 | + * |
---|
| 365 | + * Return: HRTIMER_NORESTART always. |
---|
365 | 366 | */ |
---|
366 | 367 | static enum hrtimer_restart kbasep_vinstr_dump_timer(struct hrtimer *timer) |
---|
367 | 368 | { |
---|
.. | .. |
---|
388 | 389 | |
---|
389 | 390 | kbase_hwcnt_virtualizer_client_destroy(vcli->hvcli); |
---|
390 | 391 | kfree(vcli->dump_bufs_meta); |
---|
391 | | - kbase_hwcnt_dump_buffer_array_free(&vcli->dump_bufs); |
---|
| 392 | + kbase_hwcnt_dump_buffer_narrow_array_free(&vcli->dump_bufs); |
---|
392 | 393 | kbase_hwcnt_dump_buffer_free(&vcli->tmp_buf); |
---|
393 | 394 | kbase_hwcnt_enable_map_free(&vcli->enable_map); |
---|
394 | 395 | kfree(vcli); |
---|
.. | .. |
---|
446 | 447 | /* Enable all the available clk_enable_map. */ |
---|
447 | 448 | vcli->enable_map.clk_enable_map = (1ull << vctx->metadata->clk_cnt) - 1; |
---|
448 | 449 | |
---|
449 | | - if (vctx->metadata_user) |
---|
450 | | - /* Use vinstr's truncated metadata to alloc dump buffers which |
---|
451 | | - * interact with clients. |
---|
452 | | - */ |
---|
453 | | - errcode = |
---|
454 | | - kbase_hwcnt_dump_buffer_array_alloc(vctx->metadata_user, |
---|
455 | | - setup->buffer_count, |
---|
456 | | - &vcli->dump_bufs); |
---|
457 | | - else |
---|
458 | | - /* Use metadata from virtualizer to allocate dump buffers if |
---|
459 | | - * vinstr doesn't have the truncated metadata. |
---|
460 | | - */ |
---|
461 | | - errcode = kbase_hwcnt_dump_buffer_array_alloc( |
---|
462 | | - vctx->metadata, setup->buffer_count, &vcli->dump_bufs); |
---|
| 450 | + /* Use vinstr's narrowed metadata to alloc narrow dump buffers which |
---|
| 451 | + * interact with clients. |
---|
| 452 | + */ |
---|
| 453 | + errcode = kbase_hwcnt_dump_buffer_narrow_array_alloc( |
---|
| 454 | + vctx->metadata_user, setup->buffer_count, &vcli->dump_bufs); |
---|
463 | 455 | if (errcode) |
---|
464 | 456 | goto error; |
---|
465 | 457 | |
---|
.. | .. |
---|
504 | 496 | |
---|
505 | 497 | vctx->hvirt = hvirt; |
---|
506 | 498 | vctx->metadata = metadata; |
---|
507 | | - vctx->metadata_user = NULL; |
---|
508 | | - errcode = kbase_hwcnt_gpu_metadata_create_truncate_64( |
---|
509 | | - &vctx->metadata_user, metadata); |
---|
| 499 | + errcode = kbase_hwcnt_gpu_metadata_narrow_create(&vctx->metadata_user, |
---|
| 500 | + metadata); |
---|
510 | 501 | if (errcode) |
---|
511 | 502 | goto err_metadata_create; |
---|
512 | 503 | |
---|
.. | .. |
---|
530 | 521 | if (!vctx) |
---|
531 | 522 | return; |
---|
532 | 523 | |
---|
533 | | - cancel_work_sync(&vctx->dump_work); |
---|
534 | | - |
---|
535 | 524 | /* Non-zero client count implies client leak */ |
---|
536 | 525 | if (WARN_ON(vctx->client_count != 0)) { |
---|
537 | 526 | struct kbase_vinstr_client *pos, *n; |
---|
.. | .. |
---|
543 | 532 | } |
---|
544 | 533 | } |
---|
545 | 534 | |
---|
546 | | - if (vctx->metadata_user) |
---|
547 | | - kbase_hwcnt_metadata_destroy(vctx->metadata_user); |
---|
| 535 | + cancel_work_sync(&vctx->dump_work); |
---|
| 536 | + kbase_hwcnt_gpu_metadata_narrow_destroy(vctx->metadata_user); |
---|
548 | 537 | |
---|
549 | 538 | WARN_ON(vctx->client_count != 0); |
---|
550 | 539 | kfree(vctx); |
---|
.. | .. |
---|
930 | 919 | } |
---|
931 | 920 | |
---|
932 | 921 | /** |
---|
933 | | - * The hwcnt reader's ioctl command - get API version. |
---|
| 922 | + * kbasep_vinstr_hwcnt_reader_ioctl_get_api_version() - get API version ioctl |
---|
| 923 | + * command. |
---|
934 | 924 | * @cli: The non-NULL pointer to the client |
---|
935 | 925 | * @arg: Command's argument. |
---|
936 | 926 | * @size: Size of arg. |
---|
937 | 927 | * |
---|
938 | | - * @return 0 on success, else error code. |
---|
| 928 | + * Return: 0 on success, else error code. |
---|
939 | 929 | */ |
---|
940 | 930 | static long kbasep_vinstr_hwcnt_reader_ioctl_get_api_version( |
---|
941 | 931 | struct kbase_vinstr_client *cli, unsigned long arg, size_t size) |
---|
.. | .. |
---|
1006 | 996 | cli, (u32 __user *)arg); |
---|
1007 | 997 | break; |
---|
1008 | 998 | case _IOC_NR(KBASE_HWCNT_READER_GET_BUFFER_SIZE): |
---|
1009 | | - if (cli->vctx->metadata_user) |
---|
1010 | | - rcode = put_user( |
---|
1011 | | - (u32)cli->vctx->metadata_user->dump_buf_bytes, |
---|
1012 | | - (u32 __user *)arg); |
---|
1013 | | - else |
---|
1014 | | - rcode = put_user( |
---|
1015 | | - (u32)cli->vctx->metadata->dump_buf_bytes, |
---|
1016 | | - (u32 __user *)arg); |
---|
| 999 | + rcode = put_user((u32)cli->vctx->metadata_user->dump_buf_bytes, |
---|
| 1000 | + (u32 __user *)arg); |
---|
1017 | 1001 | break; |
---|
1018 | 1002 | case _IOC_NR(KBASE_HWCNT_READER_DUMP): |
---|
1019 | 1003 | rcode = kbasep_vinstr_hwcnt_reader_ioctl_dump(cli); |
---|
.. | .. |
---|
1055 | 1039 | * @filp: Non-NULL pointer to file structure. |
---|
1056 | 1040 | * @wait: Non-NULL pointer to poll table. |
---|
1057 | 1041 | * |
---|
1058 | | - * Return: POLLIN if data can be read without blocking, 0 if data can not be |
---|
1059 | | - * read without blocking, else error code. |
---|
| 1042 | + * Return: EPOLLIN | EPOLLRDNORM if data can be read without blocking, 0 if |
---|
| 1043 | + * data can not be read without blocking, else EPOLLHUP | EPOLLERR. |
---|
1060 | 1044 | */ |
---|
1061 | | -static unsigned int kbasep_vinstr_hwcnt_reader_poll( |
---|
1062 | | - struct file *filp, |
---|
1063 | | - poll_table *wait) |
---|
| 1045 | +static __poll_t kbasep_vinstr_hwcnt_reader_poll(struct file *filp, poll_table *wait) |
---|
1064 | 1046 | { |
---|
1065 | 1047 | struct kbase_vinstr_client *cli; |
---|
1066 | 1048 | |
---|
1067 | 1049 | if (!filp || !wait) |
---|
1068 | | - return -EINVAL; |
---|
| 1050 | + return EPOLLHUP | EPOLLERR; |
---|
1069 | 1051 | |
---|
1070 | 1052 | cli = filp->private_data; |
---|
1071 | 1053 | if (!cli) |
---|
1072 | | - return -EINVAL; |
---|
| 1054 | + return EPOLLHUP | EPOLLERR; |
---|
1073 | 1055 | |
---|
1074 | 1056 | poll_wait(filp, &cli->waitq, wait); |
---|
1075 | 1057 | if (kbasep_vinstr_hwcnt_reader_buffer_ready(cli)) |
---|
1076 | | - return POLLIN; |
---|
1077 | | - return 0; |
---|
| 1058 | + return EPOLLIN | EPOLLRDNORM; |
---|
| 1059 | + |
---|
| 1060 | + return (__poll_t)0; |
---|
1078 | 1061 | } |
---|
1079 | 1062 | |
---|
1080 | 1063 | /** |
---|