| .. | .. |
|---|
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note |
|---|
| 2 | 2 | /* |
|---|
| 3 | 3 | * |
|---|
| 4 | | - * (C) COPYRIGHT 2019-2021 ARM Limited. All rights reserved. |
|---|
| 4 | + * (C) COPYRIGHT 2019-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 |
|---|
| .. | .. |
|---|
| 45 | 45 | #include <linux/slab.h> |
|---|
| 46 | 46 | #include <linux/spinlock.h> |
|---|
| 47 | 47 | #include <linux/version.h> |
|---|
| 48 | +#include <linux/version_compat_defs.h> |
|---|
| 48 | 49 | #include <linux/wait.h> |
|---|
| 49 | 50 | |
|---|
| 51 | +/* Explicitly include epoll header for old kernels. Not required from 4.16. */ |
|---|
| 52 | +#if KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE |
|---|
| 53 | +#include <uapi/linux/eventpoll.h> |
|---|
| 54 | +#endif |
|---|
| 55 | + |
|---|
| 56 | +/* Define static_assert(). |
|---|
| 57 | + * |
|---|
| 58 | + * The macro was introduced in kernel 5.1. But older vendor kernels may define |
|---|
| 59 | + * it too. |
|---|
| 60 | + */ |
|---|
| 50 | 61 | #if KERNEL_VERSION(5, 1, 0) <= LINUX_VERSION_CODE |
|---|
| 51 | 62 | #include <linux/build_bug.h> |
|---|
| 52 | | -#else |
|---|
| 63 | +#elif !defined(static_assert) |
|---|
| 53 | 64 | // Stringify the expression if no message is given. |
|---|
| 54 | 65 | #define static_assert(e, ...) __static_assert(e, #__VA_ARGS__, #e) |
|---|
| 55 | 66 | #define __static_assert(e, msg, ...) _Static_assert(e, msg) |
|---|
| 56 | | -#endif |
|---|
| 57 | | - |
|---|
| 58 | | -#if KERNEL_VERSION(4, 16, 0) >= LINUX_VERSION_CODE |
|---|
| 59 | | -typedef unsigned int __poll_t; |
|---|
| 60 | | -#endif |
|---|
| 61 | | - |
|---|
| 62 | | -#ifndef ENOTSUP |
|---|
| 63 | | -#define ENOTSUP EOPNOTSUPP |
|---|
| 64 | 67 | #endif |
|---|
| 65 | 68 | |
|---|
| 66 | 69 | /* The module printing prefix */ |
|---|
| .. | .. |
|---|
| 204 | 207 | */ |
|---|
| 205 | 208 | static inline bool reader_changes_is_valid_size(const size_t size) |
|---|
| 206 | 209 | { |
|---|
| 207 | | - typedef struct reader_changes changes_t; |
|---|
| 208 | | - const size_t elem_size = sizeof(*((changes_t *)0)->data); |
|---|
| 209 | | - const size_t size_size = sizeof(((changes_t *)0)->size); |
|---|
| 210 | + const size_t elem_size = sizeof(*((struct reader_changes *)0)->data); |
|---|
| 211 | + const size_t size_size = sizeof(((struct reader_changes *)0)->size); |
|---|
| 210 | 212 | const size_t size_max = (1ull << (size_size * 8)) - 1; |
|---|
| 211 | 213 | |
|---|
| 212 | 214 | return is_power_of_2(size) && /* Is a power of two */ |
|---|
| .. | .. |
|---|
| 223 | 225 | * |
|---|
| 224 | 226 | * Return: |
|---|
| 225 | 227 | * (0, U16_MAX] - the number of data elements allocated |
|---|
| 226 | | - * -EINVAL - a pointer was invalid |
|---|
| 227 | | - * -ENOTSUP - we do not support allocation of the context |
|---|
| 228 | 228 | * -ERANGE - the requested memory size was invalid |
|---|
| 229 | 229 | * -ENOMEM - could not allocate the memory |
|---|
| 230 | | - * -EADDRINUSE - the buffer memory was already allocated |
|---|
| 231 | 230 | */ |
|---|
| 232 | 231 | static int reader_changes_init(struct reader_changes *const changes, |
|---|
| 233 | 232 | const size_t size) |
|---|
| .. | .. |
|---|
| 622 | 621 | * |
|---|
| 623 | 622 | * Return: |
|---|
| 624 | 623 | * * 0 - no data ready |
|---|
| 625 | | - * * POLLIN - state changes have been buffered |
|---|
| 626 | | - * * -EBADF - the file descriptor did not have an attached reader |
|---|
| 627 | | - * * -EINVAL - the IO control arguments were invalid |
|---|
| 624 | + * * EPOLLIN | EPOLLRDNORM - state changes have been buffered |
|---|
| 625 | + * * EPOLLHUP | EPOLLERR - IO control arguments were invalid or the file |
|---|
| 626 | + * descriptor did not have an attached reader. |
|---|
| 628 | 627 | */ |
|---|
| 629 | 628 | static __poll_t reader_poll(struct file *const file, |
|---|
| 630 | 629 | struct poll_table_struct *const wait) |
|---|
| 631 | 630 | { |
|---|
| 632 | 631 | struct reader *reader; |
|---|
| 633 | 632 | struct reader_changes *changes; |
|---|
| 633 | + __poll_t mask = 0; |
|---|
| 634 | 634 | |
|---|
| 635 | 635 | if (unlikely(!file || !wait)) |
|---|
| 636 | | - return -EINVAL; |
|---|
| 636 | + return EPOLLHUP | EPOLLERR; |
|---|
| 637 | 637 | |
|---|
| 638 | 638 | reader = file->private_data; |
|---|
| 639 | 639 | if (unlikely(!reader)) |
|---|
| 640 | | - return -EBADF; |
|---|
| 640 | + return EPOLLHUP | EPOLLERR; |
|---|
| 641 | 641 | |
|---|
| 642 | 642 | changes = &reader->changes; |
|---|
| 643 | | - |
|---|
| 644 | 643 | if (reader_changes_count(changes) >= changes->threshold) |
|---|
| 645 | | - return POLLIN; |
|---|
| 644 | + return EPOLLIN | EPOLLRDNORM; |
|---|
| 646 | 645 | |
|---|
| 647 | 646 | poll_wait(file, &reader->wait_queue, wait); |
|---|
| 648 | 647 | |
|---|
| 649 | | - return (reader_changes_count(changes) > 0) ? POLLIN : 0; |
|---|
| 648 | + if (reader_changes_count(changes) > 0) |
|---|
| 649 | + mask |= EPOLLIN | EPOLLRDNORM; |
|---|
| 650 | + |
|---|
| 651 | + return mask; |
|---|
| 650 | 652 | } |
|---|
| 651 | 653 | |
|---|
| 652 | 654 | /* The file operations virtual function table */ |
|---|
| .. | .. |
|---|
| 662 | 664 | static const size_t kbase_kinstr_jm_readers_max = 16; |
|---|
| 663 | 665 | |
|---|
| 664 | 666 | /** |
|---|
| 665 | | - * kbasep_kinstr_jm_release() - Invoked when the reference count is dropped |
|---|
| 667 | + * kbase_kinstr_jm_release() - Invoked when the reference count is dropped |
|---|
| 666 | 668 | * @ref: the context reference count |
|---|
| 667 | 669 | */ |
|---|
| 668 | 670 | static void kbase_kinstr_jm_release(struct kref *const ref) |
|---|
| .. | .. |
|---|
| 733 | 735 | } |
|---|
| 734 | 736 | |
|---|
| 735 | 737 | /** |
|---|
| 736 | | - * readers_del() - Deletes a reader from the list of readers |
|---|
| 738 | + * kbase_kinstr_jm_readers_del() - Deletes a reader from the list of readers |
|---|
| 737 | 739 | * @ctx: the instrumentation context |
|---|
| 738 | 740 | * @reader: the reader to delete |
|---|
| 739 | 741 | */ |
|---|
| .. | .. |
|---|
| 812 | 814 | kbase_kinstr_jm_ref_put(ctx); |
|---|
| 813 | 815 | } |
|---|
| 814 | 816 | |
|---|
| 815 | | -/** |
|---|
| 816 | | - * timestamp() - Retrieves the current monotonic nanoseconds |
|---|
| 817 | | - * Return: monotonic nanoseconds timestamp. |
|---|
| 818 | | - */ |
|---|
| 819 | | -static u64 timestamp(void) |
|---|
| 820 | | -{ |
|---|
| 821 | | - struct timespec ts; |
|---|
| 822 | | - long ns; |
|---|
| 823 | | - |
|---|
| 824 | | - getrawmonotonic(&ts); |
|---|
| 825 | | - ns = ((long)(ts.tv_sec) * NSEC_PER_SEC) + ts.tv_nsec; |
|---|
| 826 | | - if (unlikely(ns < 0)) |
|---|
| 827 | | - return 0; |
|---|
| 828 | | - return ((u64)(ns)); |
|---|
| 829 | | -} |
|---|
| 830 | | - |
|---|
| 831 | 817 | void kbasep_kinstr_jm_atom_state( |
|---|
| 832 | 818 | struct kbase_jd_atom *const katom, |
|---|
| 833 | 819 | const enum kbase_kinstr_jm_reader_atom_state state) |
|---|
| .. | .. |
|---|
| 836 | 822 | struct kbase_kinstr_jm *const ctx = kctx->kinstr_jm; |
|---|
| 837 | 823 | const u8 id = kbase_jd_atom_id(kctx, katom); |
|---|
| 838 | 824 | struct kbase_kinstr_jm_atom_state_change change = { |
|---|
| 839 | | - .timestamp = timestamp(), .atom = id, .state = state |
|---|
| 825 | + .timestamp = ktime_get_raw_ns(), .atom = id, .state = state |
|---|
| 840 | 826 | }; |
|---|
| 841 | 827 | struct reader *reader; |
|---|
| 842 | 828 | struct hlist_bl_node *node; |
|---|