blob: 415830b056fc69da8ac72c451493ac6bcab2f37e [file] [log] [blame]
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define FARF_ERROR 1
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "HAP_farf.h"
#include "verify.h"
#include "remote.h"
#include "rpcmem.h"
#include "AEEstd.h"
#include "adsp_perf.h"
#include "fastrpc_perf.h"
#include "fastrpc_internal.h"
#include "fastrpc_apps_user.h"
#ifdef ANDROID_P
#define PERF_KEY_KERNEL "vendor.fastrpc.perf.kernel"
#define PERF_KEY_ADSP "vendor.fastrpc.perf.adsp"
#define PERF_KEY_FREQ "vendor.fastrpc.perf.freq"
#else
#define PERF_KEY_KERNEL "fastrpc.perf.kernel"
#define PERF_KEY_ADSP "fastrpc.perf.adsp"
#define PERF_KEY_FREQ "fastrpc.perf.freq"
#endif
#define PERF_MODE 2
#define PERF_OFF 0
#define PERF_KERNEL_MASK (0x1)
#define PERF_ADSP_MASK (0x2)
#define PERF_KEY_STR_MAX (2*1024)
#define PERF_MAX_NUM_KEYS 64
#define PERF_NS_TO_US(n) ((n)/1000)
#define IS_KEY_ENABLED(name) (!std_strncmp((name), "perf_invoke_count", 17) || \
!std_strncmp((name), "perf_mod_invoke", 15) || \
!std_strncmp((name), "perf_rsp", 8) || \
!std_strncmp((name), "perf_hdr_sync_flush", 19) || \
!std_strncmp((name), "perf_sync_flush", 15) || \
!std_strncmp((name), "perf_hdr_sync_inv", 17) || \
!std_strncmp((name), "perf_sync_inv", 13)) \
struct perf_keys {
int64 data[PERF_MAX_NUM_KEYS];
int numKeys;
int maxLen;
int enable;
char *keys;
};
struct fastrpc_perf {
int count;
int freq;
int perf_on;
struct perf_keys kernel;
struct perf_keys dsp;
};
struct fastrpc_perf gperf;
static int perf_kernel_getkeys(int dev) {
int nErr = 0;
bail:
return nErr;
}
static void get_perf_kernel(int dev, remote_handle handle, uint32_t sc) {
bail:
return;
}
static void get_perf_adsp(remote_handle handle, uint32_t sc) {
int nErr = 0;
struct fastrpc_perf *p = &gperf;
struct perf_keys *pdsp = &gperf.dsp;
int ii;
char *token;
char *keystr = pdsp->keys;
VERIFY(0 == adsp_perf_get_usecs(pdsp->data, PERF_MAX_NUM_KEYS));
VERIFY(pdsp->maxLen < PERF_KEY_STR_MAX);
VERIFY(pdsp->numKeys < PERF_MAX_NUM_KEYS);
FARF(ALWAYS, "\nFastRPC dsp perf for handle 0x%x sc 0x%x\n", handle, sc);
for(ii = 0; ii < pdsp->numKeys; ii++) {
token = keystr;
keystr += strlen(token) + 1;
VERIFY(token);
if (!pdsp->data[ii])
continue;
if (!std_strncmp(token, "perf_invoke_count",17)) {
FARF(ALWAYS, "fastrpc.dsp.%-20s : %lld \n", token, pdsp->data[ii]);
} else {
FARF(ALWAYS, "fastrpc.dsp.%-20s : %lld us\n", token, pdsp->data[ii]);
}
}
bail:
return;
}
void fastrpc_perf_update(int dev, remote_handle handle, uint32_t sc) {
int nErr = 0;
struct fastrpc_perf *p = &gperf;
if (!(p->perf_on && !IS_STATIC_HANDLE(handle) && p->freq > 0))
return;
p->count++;
if (p->count % p->freq != 0)
return;
if (p->kernel.enable)
get_perf_kernel(dev, handle, sc);
if (p->dsp.enable)
get_perf_adsp(handle, sc);
bail:
return;
}
static int perf_dsp_enable(void) {
int nErr = 0;
int numKeys = 0, maxLen = 0;
char *keys = NULL;
int ii;
keys = (char *)rpcmem_alloc_internal(0, RPCMEM_HEAP_DEFAULT, PERF_KEY_STR_MAX);
VERIFY(gperf.dsp.keys = keys);
std_memset(keys, 0, PERF_KEY_STR_MAX);
VERIFY(0 == adsp_perf_get_keys(keys, PERF_KEY_STR_MAX, &maxLen, &numKeys));
VERIFY(maxLen < PERF_KEY_STR_MAX);
gperf.dsp.maxLen = maxLen;
gperf.dsp.numKeys = numKeys;
for(ii = 0; ii < numKeys; ii++) {
char *name = keys;
keys += strlen(name) + 1;
if (IS_KEY_ENABLED(name))
VERIFY(0 == adsp_perf_enable(ii));
}
FARF(HIGH, "keys enable done maxLen %d numKeys %d", maxLen, numKeys);
bail:
return nErr;
}
int fastrpc_perf_init(int dev) {
int nErr = 0;
struct fastrpc_perf *p = &gperf;
struct perf_keys *pk = &gperf.kernel;
struct perf_keys *pd = &gperf.dsp;
pk->enable = FASTRPC_PROPERTY_GET_INT32(PERF_KEY_KERNEL, 0);
pd->enable = FASTRPC_PROPERTY_GET_INT32(PERF_KEY_ADSP, 0);
p->perf_on = (pk->enable || pd->enable) ? PERF_MODE : PERF_OFF;
p->freq = FASTRPC_PROPERTY_GET_INT32(PERF_KEY_FREQ, 1000);
VERIFY(p->freq > 0);
p->count = 0;
if (pk->enable) {
//VERIFY(!ioctl(dev, FASTRPC_IOCTL_SETMODE, PERF_MODE));
VERIFY(NULL != (pk->keys = (char *)calloc(sizeof(char), PERF_KEY_STR_MAX)));
VERIFY(0 == perf_kernel_getkeys(dev));
}
if (pd->enable)
perf_dsp_enable();
bail:
if (nErr) {
FARF(HIGH, "fastrpc perf init failed");
p->perf_on = 0;
}
return nErr;
}
void fastrpc_perf_deinit(void) {
struct fastrpc_perf *p = &gperf;
if (p->kernel.keys){
free(p->kernel.keys);
p->kernel.keys = NULL;
}
if (p->dsp.keys){
rpcmem_free_internal(p->dsp.keys);
p->dsp.keys = NULL;
}
return;
}