/* * 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 #include #include #include #include #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; }