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