100a23bdaSmrg/* 200a23bdaSmrg * Copyright (C) 2017 Etnaviv Project 300a23bdaSmrg * Copyright (C) 2017 Zodiac Inflight Innovations 400a23bdaSmrg * 500a23bdaSmrg * Permission is hereby granted, free of charge, to any person obtaining a 600a23bdaSmrg * copy of this software and associated documentation files (the "Software"), 700a23bdaSmrg * to deal in the Software without restriction, including without limitation 800a23bdaSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 900a23bdaSmrg * and/or sell copies of the Software, and to permit persons to whom the 1000a23bdaSmrg * Software is furnished to do so, subject to the following conditions: 1100a23bdaSmrg * 1200a23bdaSmrg * The above copyright notice and this permission notice (including the next 1300a23bdaSmrg * paragraph) shall be included in all copies or substantial portions of the 1400a23bdaSmrg * Software. 1500a23bdaSmrg * 1600a23bdaSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1700a23bdaSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1800a23bdaSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1900a23bdaSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2000a23bdaSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2100a23bdaSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2200a23bdaSmrg * SOFTWARE. 2300a23bdaSmrg * 2400a23bdaSmrg * Authors: 2500a23bdaSmrg * Christian Gmeiner <christian.gmeiner@gmail.com> 2600a23bdaSmrg */ 2700a23bdaSmrg 2800a23bdaSmrg#include "etnaviv_priv.h" 2900a23bdaSmrg 3000a23bdaSmrgstatic int etna_perfmon_query_signals(struct etna_perfmon *pm, struct etna_perfmon_domain *dom) 3100a23bdaSmrg{ 3200a23bdaSmrg struct etna_device *dev = pm->pipe->gpu->dev; 3300a23bdaSmrg struct drm_etnaviv_pm_signal req = { 3400a23bdaSmrg .pipe = pm->pipe->id, 3500a23bdaSmrg .domain = dom->id 3600a23bdaSmrg }; 3700a23bdaSmrg 3800a23bdaSmrg do { 3900a23bdaSmrg struct etna_perfmon_signal *sig; 4000a23bdaSmrg int ret; 4100a23bdaSmrg 4200a23bdaSmrg ret = drmCommandWriteRead(dev->fd, DRM_ETNAVIV_PM_QUERY_SIG, &req, sizeof(req)); 4300a23bdaSmrg if (ret) 4400a23bdaSmrg break; 4500a23bdaSmrg 4600a23bdaSmrg sig = calloc(1, sizeof(*sig)); 4700a23bdaSmrg if (!sig) 4800a23bdaSmrg return -ENOMEM; 4900a23bdaSmrg 5000a23bdaSmrg INFO_MSG("perfmon signal:"); 5100a23bdaSmrg INFO_MSG("id = %d", req.id); 5200a23bdaSmrg INFO_MSG("name = %s", req.name); 5300a23bdaSmrg 5400a23bdaSmrg sig->domain = dom; 5500a23bdaSmrg sig->signal = req.id; 5600a23bdaSmrg strncpy(sig->name, req.name, sizeof(sig->name)); 5700a23bdaSmrg list_addtail(&sig->head, &dom->signals); 5800a23bdaSmrg } while (req.iter != 0xffff); 5900a23bdaSmrg 6000a23bdaSmrg return 0; 6100a23bdaSmrg} 6200a23bdaSmrg 6300a23bdaSmrgstatic int etna_perfmon_query_domains(struct etna_perfmon *pm) 6400a23bdaSmrg{ 6500a23bdaSmrg struct etna_device *dev = pm->pipe->gpu->dev; 6600a23bdaSmrg struct drm_etnaviv_pm_domain req = { 6700a23bdaSmrg .pipe = pm->pipe->id 6800a23bdaSmrg }; 6900a23bdaSmrg 7000a23bdaSmrg do { 7100a23bdaSmrg struct etna_perfmon_domain *dom; 7200a23bdaSmrg int ret; 7300a23bdaSmrg 7400a23bdaSmrg ret = drmCommandWriteRead(dev->fd, DRM_ETNAVIV_PM_QUERY_DOM, &req, sizeof(req)); 7500a23bdaSmrg if (ret) 7600a23bdaSmrg break; 7700a23bdaSmrg 7800a23bdaSmrg dom = calloc(1, sizeof(*dom)); 7900a23bdaSmrg if (!dom) 8000a23bdaSmrg return -ENOMEM; 8100a23bdaSmrg 8200a23bdaSmrg list_inithead(&dom->signals); 8300a23bdaSmrg dom->id = req.id; 8400a23bdaSmrg strncpy(dom->name, req.name, sizeof(dom->name)); 8500a23bdaSmrg list_addtail(&dom->head, &pm->domains); 8600a23bdaSmrg 8700a23bdaSmrg INFO_MSG("perfmon domain:"); 8800a23bdaSmrg INFO_MSG("id = %d", req.id); 8900a23bdaSmrg INFO_MSG("name = %s", req.name); 9000a23bdaSmrg INFO_MSG("nr_signals = %d", req.nr_signals); 9100a23bdaSmrg 9200a23bdaSmrg /* Query all available signals for this domain. */ 9300a23bdaSmrg if (req.nr_signals > 0) { 9400a23bdaSmrg ret = etna_perfmon_query_signals(pm, dom); 9500a23bdaSmrg if (ret) 9600a23bdaSmrg return ret; 9700a23bdaSmrg } 9800a23bdaSmrg } while (req.iter != 0xff); 9900a23bdaSmrg 10000a23bdaSmrg return 0; 10100a23bdaSmrg} 10200a23bdaSmrg 10300a23bdaSmrgstatic void etna_perfmon_free_signals(struct etna_perfmon_domain *dom) 10400a23bdaSmrg{ 10500a23bdaSmrg struct etna_perfmon_signal *sig, *next; 10600a23bdaSmrg 10700a23bdaSmrg LIST_FOR_EACH_ENTRY_SAFE(sig, next, &dom->signals, head) { 10800a23bdaSmrg list_del(&sig->head); 10900a23bdaSmrg free(sig); 11000a23bdaSmrg } 11100a23bdaSmrg} 11200a23bdaSmrg 11300a23bdaSmrgstatic void etna_perfmon_free_domains(struct etna_perfmon *pm) 11400a23bdaSmrg{ 11500a23bdaSmrg struct etna_perfmon_domain *dom, *next; 11600a23bdaSmrg 11700a23bdaSmrg LIST_FOR_EACH_ENTRY_SAFE(dom, next, &pm->domains, head) { 11800a23bdaSmrg etna_perfmon_free_signals(dom); 11900a23bdaSmrg list_del(&dom->head); 12000a23bdaSmrg free(dom); 12100a23bdaSmrg } 12200a23bdaSmrg} 12300a23bdaSmrg 1247cdc0497Smrgdrm_public struct etna_perfmon *etna_perfmon_create(struct etna_pipe *pipe) 12500a23bdaSmrg{ 12600a23bdaSmrg struct etna_perfmon *pm; 12700a23bdaSmrg int ret; 12800a23bdaSmrg 12900a23bdaSmrg pm = calloc(1, sizeof(*pm)); 13000a23bdaSmrg if (!pm) { 13100a23bdaSmrg ERROR_MSG("allocation failed"); 13200a23bdaSmrg return NULL; 13300a23bdaSmrg } 13400a23bdaSmrg 13500a23bdaSmrg list_inithead(&pm->domains); 13600a23bdaSmrg pm->pipe = pipe; 13700a23bdaSmrg 13800a23bdaSmrg /* query all available domains and sources for this device */ 13900a23bdaSmrg ret = etna_perfmon_query_domains(pm); 14000a23bdaSmrg if (ret) 14100a23bdaSmrg goto fail; 14200a23bdaSmrg 14300a23bdaSmrg return pm; 14400a23bdaSmrg 14500a23bdaSmrgfail: 14600a23bdaSmrg etna_perfmon_del(pm); 14700a23bdaSmrg return NULL; 14800a23bdaSmrg} 14900a23bdaSmrg 1507cdc0497Smrgdrm_public void etna_perfmon_del(struct etna_perfmon *pm) 15100a23bdaSmrg{ 15200a23bdaSmrg if (!pm) 15300a23bdaSmrg return; 15400a23bdaSmrg 15500a23bdaSmrg etna_perfmon_free_domains(pm); 15600a23bdaSmrg free(pm); 15700a23bdaSmrg} 15800a23bdaSmrg 1597cdc0497Smrgdrm_public struct etna_perfmon_domain *etna_perfmon_get_dom_by_name(struct etna_perfmon *pm, const char *name) 16000a23bdaSmrg{ 16100a23bdaSmrg struct etna_perfmon_domain *dom; 16200a23bdaSmrg 16300a23bdaSmrg if (pm) { 16400a23bdaSmrg LIST_FOR_EACH_ENTRY(dom, &pm->domains, head) { 16500a23bdaSmrg if (!strcmp(dom->name, name)) 16600a23bdaSmrg return dom; 16700a23bdaSmrg } 16800a23bdaSmrg } 16900a23bdaSmrg 17000a23bdaSmrg return NULL; 17100a23bdaSmrg} 17200a23bdaSmrg 1737cdc0497Smrgdrm_public struct etna_perfmon_signal *etna_perfmon_get_sig_by_name(struct etna_perfmon_domain *dom, const char *name) 17400a23bdaSmrg{ 17500a23bdaSmrg struct etna_perfmon_signal *signal; 17600a23bdaSmrg 17700a23bdaSmrg if (dom) { 17800a23bdaSmrg LIST_FOR_EACH_ENTRY(signal, &dom->signals, head) { 17900a23bdaSmrg if (!strcmp(signal->name, name)) 18000a23bdaSmrg return signal; 18100a23bdaSmrg } 18200a23bdaSmrg } 18300a23bdaSmrg 18400a23bdaSmrg return NULL; 18500a23bdaSmrg} 186