blob: ef9ac0f7b633d93aacba71878695b4fa3af11de2 [file] [log] [blame]
/*
*
* (C) COPYRIGHT 2014-2015 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 licence.
*
* A copy of the licence is included with the program, and can also be obtained
* from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#ifndef _KBASE_GATOR_API_H_
#define _KBASE_GATOR_API_H_
/**
* @brief This file describes the API used by Gator to fetch hardware counters.
*/
/* This define is used by the gator kernel module compile to select which DDK
* API calling convention to use. If not defined (legacy DDK) gator assumes
* version 1. The version to DDK release mapping is:
* Version 1 API: DDK versions r1px, r2px
* Version 2 API: DDK versions r3px, r4px
* Version 3 API: DDK version r5p0 and newer
*
* API Usage
* =========
*
* 1] Call kbase_gator_hwcnt_init_names() to return the list of short counter
* names for the GPU present in this device.
*
* 2] Create a kbase_gator_hwcnt_info structure and set the counter enables for
* the counters you want enabled. The enables can all be set for simplicity in
* most use cases, but disabling some will let you minimize bandwidth impact.
*
* 3] Call kbase_gator_hwcnt_init() using the above structure, to create a
* counter context. On successful return the DDK will have populated the
* structure with a variety of useful information.
*
* 4] Call kbase_gator_hwcnt_dump_irq() to queue a non-blocking request for a
* counter dump. If this returns a non-zero value the request has been queued,
* otherwise the driver has been unable to do so (typically because of another
* user of the instrumentation exists concurrently).
*
* 5] Call kbase_gator_hwcnt_dump_complete() to test whether the previously
* requested dump has been succesful. If this returns non-zero the counter dump
* has resolved, but the value of *success must also be tested as the dump
* may have not been successful. If it returns zero the counter dump was
* abandoned due to the device being busy (typically because of another
* user of the instrumentation exists concurrently).
*
* 6] Process the counters stored in the buffer pointed to by ...
*
* kbase_gator_hwcnt_info->kernel_dump_buffer
*
* In pseudo code you can find all of the counters via this approach:
*
*
* hwcnt_info # pointer to kbase_gator_hwcnt_info structure
* hwcnt_name # pointer to name list
*
* u32 * hwcnt_data = (u32*)hwcnt_info->kernel_dump_buffer
*
* # Iterate over each 64-counter block in this GPU configuration
* for( i = 0; i < hwcnt_info->nr_hwc_blocks; i++) {
* hwc_type type = hwcnt_info->hwc_layout[i];
*
* # Skip reserved type blocks - they contain no counters at all
* if( type == RESERVED_BLOCK ) {
* continue;
* }
*
* size_t name_offset = type * 64;
* size_t data_offset = i * 64;
*
* # Iterate over the names of the counters in this block type
* for( j = 0; j < 64; j++) {
* const char * name = hwcnt_name[name_offset+j];
*
* # Skip empty name strings - there is no counter here
* if( name[0] == '\0' ) {
* continue;
* }
*
* u32 data = hwcnt_data[data_offset+j];
*
* printk( "COUNTER: %s DATA: %u\n", name, data );
* }
* }
*
*
* Note that in most implementations you typically want to either SUM or
* AVERAGE multiple instances of the same counter if, for example, you have
* multiple shader cores or multiple L2 caches. The most sensible view for
* analysis is to AVERAGE shader core counters, but SUM L2 cache and MMU
* counters.
*
* 7] Goto 4, repeating until you want to stop collecting counters.
*
* 8] Release the dump resources by calling kbase_gator_hwcnt_term().
*
* 9] Release the name table resources by calling
* kbase_gator_hwcnt_term_names(). This function must only be called if
* init_names() returned a non-NULL value.
**/
#define MALI_DDK_GATOR_API_VERSION 3
enum hwc_type {
JM_BLOCK = 0,
TILER_BLOCK,
SHADER_BLOCK,
MMU_L2_BLOCK,
RESERVED_BLOCK
};
struct kbase_gator_hwcnt_info {
/* Passed from Gator to kbase */
/* the bitmask of enabled hardware counters for each counter block */
uint16_t bitmask[4];
/* Passed from kbase to Gator */
/* ptr to counter dump memory */
void *kernel_dump_buffer;
/* size of counter dump memory */
uint32_t size;
/* the ID of the Mali device */
uint32_t gpu_id;
/* the number of shader cores in the GPU */
uint32_t nr_cores;
/* the number of core groups */
uint32_t nr_core_groups;
/* the memory layout of the performance counters */
enum hwc_type *hwc_layout;
/* the total number of hardware couter blocks */
uint32_t nr_hwc_blocks;
};
/**
* @brief Opaque block of Mali data which Gator needs to return to the API later.
*/
struct kbase_gator_hwcnt_handles;
/**
* @brief Initialize the resources Gator needs for performance profiling.
*
* @param in_out_info A pointer to a structure containing the enabled counters passed from Gator and all the Mali
* specific information that will be returned to Gator. On entry Gator must have populated the
* 'bitmask' field with the counters it wishes to enable for each class of counter block.
* Each entry in the array corresponds to a single counter class based on the "hwc_type"
* enumeration, and each bit corresponds to an enable for 4 sequential counters (LSB enables
* the first 4 counters in the block, and so on). See the GPU counter array as returned by
* kbase_gator_hwcnt_get_names() for the index values of each counter for the curernt GPU.
*
* @return Pointer to an opaque handle block on success, NULL on error.
*/
extern struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info *in_out_info);
/**
* @brief Free all resources once Gator has finished using performance counters.
*
* @param in_out_info A pointer to a structure containing the enabled counters passed from Gator and all the
* Mali specific information that will be returned to Gator.
* @param opaque_handles A wrapper structure for kbase structures.
*/
extern void kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info *in_out_info, struct kbase_gator_hwcnt_handles *opaque_handles);
/**
* @brief Poll whether a counter dump is successful.
*
* @param opaque_handles A wrapper structure for kbase structures.
* @param[out] success Non-zero on success, zero on failure.
*
* @return Zero if the dump is still pending, non-zero if the dump has completed. Note that a
* completed dump may not have dumped succesfully, so the caller must test for both
* a completed and successful dump before processing counters.
*/
extern uint32_t kbase_gator_instr_hwcnt_dump_complete(struct kbase_gator_hwcnt_handles *opaque_handles, uint32_t * const success);
/**
* @brief Request the generation of a new counter dump.
*
* @param opaque_handles A wrapper structure for kbase structures.
*
* @return Zero if the hardware device is busy and cannot handle the request, non-zero otherwise.
*/
extern uint32_t kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles *opaque_handles);
/**
* @brief This function is used to fetch the names table based on the Mali device in use.
*
* @param[out] total_counters The total number of counters short names in the Mali devices' list.
*
* @return Pointer to an array of strings of length *total_counters.
*/
extern const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_counters);
/**
* @brief This function is used to terminate the use of the names table.
*
* This function must only be called if the initial call to kbase_gator_hwcnt_init_names returned a non-NULL value.
*/
extern void kbase_gator_hwcnt_term_names(void);
#endif