/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note OR MIT */

/*
 * (C) COPYRIGHT 2023-2024 ARM Limited or its affiliates. All rights reserved.
 */

/*
 * Part of the Mali reference arbiter
 */

#ifndef _MALI_ARBITER_GPU_SUBINSTANCE_H_
#define _MALI_ARBITER_GPU_SUBINSTANCE_H_

#include <linux/kernel.h>
#include <mali_arbiter/mali_arbiter.h>
#include "mali_arbiter_internal.h"

struct mali_arb;
struct mali_arb_gpu_subinstance;

/**
 * enum mali_arb_gsi_flags - gpu-subinstance flags
 * @GSI_FLAG_SLICE_ASSIGNED: Set when slice is assigned to the gpu-subinstance.
 * @GSI_FLAG_MAX: Maximum valid index.
 *
 * Runtime flags that are set by arbiter-core submodule.
 */
enum mali_arb_gsi_flags { GSI_FLAG_SLICE_ASSIGNED, GSI_FLAG_MAX };


/**
 * mali_arbiter_gsi_create() - Creates a gpu-subinstance
 * @dev: arbiter device data
 * @gsi_idx: gpu-subinstance index within resource-group
 * @gsi_cb: gpu-subinstance callbacks
 * @arb_hndl: gpu-arbiter handler for callbacks
 *
 * This function does not set the module fields.
 *
 * Return: A new gpu-subinstance, or NULL if the memory could not be allocated
 */
struct mali_arb_gpu_subinstance *mali_arbiter_gsi_create(struct device *dev, u32 gsi_idx,
							 struct mali_arb_gsi_cb gsi_cb,
							 struct mali_arb *arb_hndl);

/**
 * mali_arbiter_gsi_destroy() - Destroy a gpu-subinstance
 * @gsi_ptr: gpu-subinstance to be destroyed
 *
 * This function release all the resources associated to a gpu-subinstance
 */
void mali_arbiter_gsi_destroy(struct mali_arb_gpu_subinstance *gsi_ptr);

/**
 * mali_arbiter_gsi_register_assign_if() - Register VM assign interface
 * @gsi_ptr: Pointer to gpu-subinstance private data.
 * @vm_assign: GPU to VM assign interfaces.
 *
 * Register a VM assign interface to be used by the Arbiter to assign a
 * gpu-subinstance to a specific VM. If hardware separation is not supported,
 * just the interface index 0 (see vm_assign_interface) should be registered.
 *
 * Return:
 * * 0		- successful.
 * * -EINVAL	- invalid argument.
 * * -EFAULT	- failed with software fault.
 */
int mali_arbiter_gsi_register_assign_if(struct mali_arb_gpu_subinstance *gsi_ptr,
					struct vm_assign_interface vm_assign);

/**
 * mali_arbiter_gsi_unregister_assign_if() - Unregister VM assign interface
 * @gsi_ptr: Pointer to gpu-subinstance private data.
 *
 * Unregister the VM assign interface of index if_id from the Arbiter. If
 * hardware separation is not supported, just the interface index zero (see
 * vm_assign_interface) should have been registered (see arb_reg_assign_if).
 */
void mali_arbiter_gsi_unregister_assign_if(struct mali_arb_gpu_subinstance *gsi_ptr);

/**
 * mali_arbiter_gsi_start() - Start a gpu-subinstance
 * @gsi_ptr: gpu-subinstance to be started
 *
 * This function will start the gpu-subinstance and start to assign VMs to it.
 */
void mali_arbiter_gsi_start(struct mali_arb_gpu_subinstance *gsi_ptr);

/**
 * mali_arbiter_gsi_stop() - Stop a gpu-subinstance
 * @gsi_ptr: gpu-subinstance to be paused
 *
 * This function will stop the gpu-subinstance and remove assigned VMs from it.
 * No VMs will be assigned while being stopped.
 */
void mali_arbiter_gsi_stop(struct mali_arb_gpu_subinstance *gsi_ptr);

/**
 * mali_arbiter_gsi_remove_vm() - remove VM from gpu-subinstance
 * @gsi_ptr: gpu-subinstance private data.
 * @rem_vm: Private Arbiter VM data that is being removed.
 *
 * This function removes rem_vm from the gsi_ptr.
 * It will be stopped if it is an active VM for the gpu-subinstance.
 * It will be removed from req_list if it's requested.
 *
 * Return: 1 when rem_vm was requested, 0 when not.
 */
bool mali_arbiter_gsi_remove_vm(struct mali_arb_gpu_subinstance *gsi_ptr,
				struct mali_arb_priv_data *rem_vm);

/**
 * mali_arbiter_gsi_get_utilisation() - Get gpu-subinstance utilization info
 * @gsi_ptr: Pointer to gpu-subinstance private data.
 * @gsi_busytime: Out-param that will contain the gpu-subinstance busy time.
 * @gsi_totaltime: Out-param that will contain the gpu-subinstance total time.
 *
 * Called from arbiter-core for DVFS to get GPU busytime and totaltime
 * since last request.
 */
void mali_arbiter_gsi_get_utilisation(struct mali_arb_gpu_subinstance *gsi_ptr, u32 *gsi_busytime,
				      u32 *gsi_totaltime);

/**
 * mali_arbiter_gsi_update_freq() - update gpu-subinstance clock frequency
 * @gsi_ptr: Target gpu-subinstance object to update the clock frequency.
 * @new_freq: New clock frequency.
 *
 * This function updates gpu-subinstance clock frequency.
 */
void mali_arbiter_gsi_update_freq(struct mali_arb_gpu_subinstance *gsi_ptr, u32 new_freq);

/**
 * mali_arbiter_gsi_flag_set - Set gpu-subinstance flag
 * @gsi_ptr: gpu-subinstance private data.
 * @flag: bit mask that has all flags to be set.
 */
void mali_arbiter_gsi_flag_set(struct mali_arb_gpu_subinstance *gsi_ptr,
			       enum mali_arb_gsi_flags flag);

/**
 * mali_arbiter_gsi_flag_clear - Clear gpu-subinstance config
 * @gsi_ptr: gpu-subinstance private data.
 * @flag: bit mask that has all flags to be cleared.
 */
void mali_arbiter_gsi_flag_clear(struct mali_arb_gpu_subinstance *gsi_ptr,
				 enum mali_arb_gsi_flags flag);

/**
 * mali_arbiter_gsi_gpu_stopped() - gpu_stopped message handler
 * @arb_vm: Opaque pointer to the Arbiter VM data populated by the arbiter
 *          during the registration.
 * @gsi_ptr: A gpu-subinstance private data.
 * @req_again: VM has work pending and still wants the GPU
 *
 * VM must no longer use the GPU once this function has been called until
 * gpu_granted has been called by the Arbiter.
 */
void mali_arbiter_gsi_gpu_stopped(struct mali_arb_priv_data *arb_vm,
				  struct mali_arb_gpu_subinstance *gsi_ptr, bool req_again);

/**
 * mali_arbiter_gsi_gpu_request() - gpu_request message handler
 * @arb_vm: Opaque pointer to the Arbiter VM data populated by the arbiter
 *          during the registration.
 * @gsi_ptr: A gpu-subinstance private data.
 *
 * Called by a VM comms device to request GPU time. The Arbiter should respond
 * when ready with a callback to gpu_granted.
 */
void mali_arbiter_gsi_gpu_request(struct mali_arb_priv_data *arb_vm,
				  struct mali_arb_gpu_subinstance *gsi_ptr);

/**
 * mali_arbiter_gsi_gpu_active() - gpu_active message handler
 * @arb_vm: Opaque pointer to the Arbiter VM data populated by the arbiter
 *          during the registration.
 * @gsi_ptr: A gpu-subinstance private data.
 *
 * Called by a VM comms device to notify the Arbiter that the VM is busy using
 * the GPU. This information can be useful in making scheduling decisions.
 */
void mali_arbiter_gsi_gpu_active(struct mali_arb_priv_data *arb_vm,
				 struct mali_arb_gpu_subinstance *gsi_ptr);

/**
 * mali_arbiter_gsi_gpu_idle() - gpu_idle message handler
 * @arb_vm: Opaque pointer to the Arbiter VM data populated by the arbiter
 *          during the registration.
 * @gsi_ptr: A gpu-subinstance private data.
 *
 * Called by a VM to notify the Arbiter that it is no longer using the GPU. This
 * information can be useful in making scheduling decisions.
 */
void mali_arbiter_gsi_gpu_idle(struct mali_arb_priv_data *arb_vm,
			       struct mali_arb_gpu_subinstance *gsi_ptr);

#endif /* _MALI_ARBITER_GPU_SUBINSTANCE_H_ */
