/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
/*
|
*
|
* (C) COPYRIGHT 2018, 2020-2021 ARM Limited. All rights reserved.
|
*
|
* This program is free software and is provided to you under the terms of the
|
* GNU General Public License version 2 as published by the Free Software
|
* Foundation, and any use by you of this program is subject to the terms
|
* of such GNU license.
|
*
|
* This program is distributed in the hope that it will be useful,
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* GNU General Public License for more details.
|
*
|
* You should have received a copy of the GNU General Public License
|
* along with this program; if not, you can access it online at
|
* http://www.gnu.org/licenses/gpl-2.0.html.
|
*
|
*/
|
|
/**
|
* Hardware counter context API.
|
*/
|
|
#ifndef _KBASE_HWCNT_CONTEXT_H_
|
#define _KBASE_HWCNT_CONTEXT_H_
|
|
#include <linux/types.h>
|
#include <linux/workqueue.h>
|
|
struct kbase_hwcnt_backend_interface;
|
struct kbase_hwcnt_context;
|
|
/**
|
* kbase_hwcnt_context_init() - Initialise a hardware counter context.
|
* @iface: Non-NULL pointer to a hardware counter backend interface.
|
* @out_hctx: Non-NULL pointer to where the pointer to the created context will
|
* be stored on success.
|
*
|
* On creation, the disable count of the context will be 0.
|
* A hardware counter accumulator can be acquired using a created context.
|
*
|
* Return: 0 on success, else error code.
|
*/
|
int kbase_hwcnt_context_init(
|
const struct kbase_hwcnt_backend_interface *iface,
|
struct kbase_hwcnt_context **out_hctx);
|
|
/**
|
* kbase_hwcnt_context_term() - Terminate a hardware counter context.
|
* @hctx: Pointer to context to be terminated.
|
*/
|
void kbase_hwcnt_context_term(struct kbase_hwcnt_context *hctx);
|
|
/**
|
* kbase_hwcnt_context_metadata() - Get the hardware counter metadata used by
|
* the context, so related counter data
|
* structures can be created.
|
* @hctx: Non-NULL pointer to the hardware counter context.
|
*
|
* Return: Non-NULL pointer to metadata, or NULL on error.
|
*/
|
const struct kbase_hwcnt_metadata *kbase_hwcnt_context_metadata(
|
struct kbase_hwcnt_context *hctx);
|
|
/**
|
* kbase_hwcnt_context_disable() - Increment the disable count of the context.
|
* @hctx: Non-NULL pointer to the hardware counter context.
|
*
|
* If a call to this function increments the disable count from 0 to 1, and
|
* an accumulator has been acquired, then a counter dump will be performed
|
* before counters are disabled via the backend interface.
|
*
|
* Subsequent dumps via the accumulator while counters are disabled will first
|
* return the accumulated dump, then will return dumps with zeroed counters.
|
*
|
* After this function call returns, it is guaranteed that counters will not be
|
* enabled via the backend interface.
|
*/
|
void kbase_hwcnt_context_disable(struct kbase_hwcnt_context *hctx);
|
|
/**
|
* kbase_hwcnt_context_disable_atomic() - Increment the disable count of the
|
* context if possible in an atomic
|
* context.
|
* @hctx: Non-NULL pointer to the hardware counter context.
|
*
|
* This function will only succeed if hardware counters are effectively already
|
* disabled, i.e. there is no accumulator, the disable count is already
|
* non-zero, or the accumulator has no counters set.
|
*
|
* After this function call returns true, it is guaranteed that counters will
|
* not be enabled via the backend interface.
|
*
|
* Return: True if the disable count was incremented, else False.
|
*/
|
bool kbase_hwcnt_context_disable_atomic(struct kbase_hwcnt_context *hctx);
|
|
/**
|
* kbase_hwcnt_context_enable() - Decrement the disable count of the context.
|
* @hctx: Non-NULL pointer to the hardware counter context.
|
*
|
* If a call to this function decrements the disable count from 1 to 0, and
|
* an accumulator has been acquired, then counters will be re-enabled via the
|
* backend interface.
|
*
|
* If an accumulator has been acquired and enabling counters fails for some
|
* reason, the accumulator will be placed into an error state.
|
*
|
* It is only valid to call this function one time for each prior returned call
|
* to kbase_hwcnt_context_disable.
|
*
|
* The spinlock documented in the backend interface that was passed in to
|
* kbase_hwcnt_context_init() must be held before calling this function.
|
*/
|
void kbase_hwcnt_context_enable(struct kbase_hwcnt_context *hctx);
|
|
/**
|
* kbase_hwcnt_context_queue_work() - Queue hardware counter related async
|
* work on a workqueue specialized for
|
* hardware counters.
|
* @hctx: Non-NULL pointer to the hardware counter context.
|
* @work: Non-NULL pointer to work to queue.
|
*
|
* Return: false if work was already on a queue, true otherwise.
|
*
|
* Performance counter related work is high priority, short running, and
|
* generally CPU locality is unimportant. There is no standard workqueue that
|
* can service this flavor of work.
|
*
|
* Rather than have each user of counters define their own workqueue, we have
|
* a centralized one in here that anybody using this hardware counter API
|
* should use.
|
*
|
* Before the context is destroyed, all work submitted must have been completed.
|
* Given that the work enqueued via this function is likely to be hardware
|
* counter related and will therefore use the context object, this is likely
|
* to be behavior that will occur naturally.
|
*
|
* Historical note: prior to this centralized workqueue, the system_highpri_wq
|
* was used. This was generally fine, except when a particularly long running,
|
* higher priority thread ended up scheduled on the enqueuing CPU core. Given
|
* that hardware counters requires tight integration with power management,
|
* this meant progress through the power management states could be stalled
|
* for however long that higher priority thread took.
|
*/
|
bool kbase_hwcnt_context_queue_work(struct kbase_hwcnt_context *hctx,
|
struct work_struct *work);
|
|
#endif /* _KBASE_HWCNT_CONTEXT_H_ */
|