1aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs/* 2aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * Copyright 2013 Red Hat Inc. 3aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * 4aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * Permission is hereby granted, free of charge, to any person obtaining a 5aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * copy of this software and associated documentation files (the "Software"), 6aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * to deal in the Software without restriction, including without limitation 7aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * and/or sell copies of the Software, and to permit persons to whom the 9aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * Software is furnished to do so, subject to the following conditions: 10aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * 11aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * The above copyright notice and this permission notice shall be included in 12aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * all copies or substantial portions of the Software. 13aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * 14aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * OTHER DEALINGS IN THE SOFTWARE. 21aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * 22aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * Authors: Ben Skeggs 23aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs */ 24aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 2596af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs#include <core/client.h> 26aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs#include <core/option.h> 2796af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs#include <nvif/unpack.h> 2896af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs#include <nvif/class.h> 2996af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs#include <nvif/ioctl.h> 30aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 31aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs#include <subdev/clock.h> 32aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 33aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs#include "priv.h" 34aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 35aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs#define QUAD_MASK 0x0f 36aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs#define QUAD_FREE 0x01 37aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 38aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsstatic struct nouveau_perfsig * 39aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsnouveau_perfsig_find_(struct nouveau_perfdom *dom, const char *name, u32 size) 40aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs{ 41aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs char path[64]; 42aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs int i; 43aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 44aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (name[0] != '/') { 45aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs for (i = 0; i < dom->signal_nr; i++) { 46aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if ( dom->signal[i].name && 47aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs !strncmp(name, dom->signal[i].name, size)) 48aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return &dom->signal[i]; 49aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 50aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } else { 51aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs for (i = 0; i < dom->signal_nr; i++) { 52aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs snprintf(path, sizeof(path), "/%s/%02x", dom->name, i); 53aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (!strncmp(name, path, size)) 54aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return &dom->signal[i]; 55aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 56aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 57aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 58aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return NULL; 59aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs} 60aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 61aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsstruct nouveau_perfsig * 62aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsnouveau_perfsig_find(struct nouveau_perfmon *ppm, const char *name, u32 size, 63aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfdom **pdom) 64aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs{ 65aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfdom *dom = *pdom; 66aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfsig *sig; 67aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 68aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (dom == NULL) { 69aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs list_for_each_entry(dom, &ppm->domains, head) { 70aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs sig = nouveau_perfsig_find_(dom, name, size); 71aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (sig) { 72aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs *pdom = dom; 73aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return sig; 74aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 75aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 76aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 77aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return NULL; 78aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 79aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 80aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return nouveau_perfsig_find_(dom, name, size); 81aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs} 82aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 83aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsstruct nouveau_perfctr * 84aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsnouveau_perfsig_wrap(struct nouveau_perfmon *ppm, const char *name, 85aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfdom **pdom) 86aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs{ 87aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfsig *sig; 88aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfctr *ctr; 89aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 90aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs sig = nouveau_perfsig_find(ppm, name, strlen(name), pdom); 91aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (!sig) 92aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return NULL; 93aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 94aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ctr = kzalloc(sizeof(*ctr), GFP_KERNEL); 95aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (ctr) { 96aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ctr->signal[0] = sig; 97aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ctr->logic_op = 0xaaaa; 98aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 99aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 100aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return ctr; 101aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs} 102aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 103aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs/******************************************************************************* 104aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * Perfmon object classes 105aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ******************************************************************************/ 106aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsstatic int 10796af8222cef78ab4d92186d5e10880dc78395415Ben Skeggsnouveau_perfctr_query(struct nouveau_object *object, void *data, u32 size) 108aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs{ 10996af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs union { 11096af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs struct nvif_perfctr_query_v0 v0; 11196af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs } *args = data; 112aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_device *device = nv_device(object); 113aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfmon *ppm = (void *)object->engine; 114aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfdom *dom = NULL, *chk; 115aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs const bool all = nouveau_boolopt(device->cfgopt, "NvPmShowAll", false); 116aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs const bool raw = nouveau_boolopt(device->cfgopt, "NvPmUnnamed", all); 117aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs const char *name; 118aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs int tmp = 0, di, si; 11996af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs int ret; 12096af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs 12196af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs nv_ioctl(object, "perfctr query size %d\n", size); 12296af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs if (nvif_unpack(args->v0, 0, 0, false)) { 12396af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs nv_ioctl(object, "perfctr query vers %d iter %08x\n", 12496af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs args->v0.version, args->v0.iter); 12596af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs di = (args->v0.iter & 0xff000000) >> 24; 12696af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs si = (args->v0.iter & 0x00ffffff) - 1; 12796af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs } else 12896af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs return ret; 129aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 130aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs list_for_each_entry(chk, &ppm->domains, head) { 131aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (tmp++ == di) { 132aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs dom = chk; 133aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs break; 134aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 135aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 136aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 137aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (dom == NULL || si >= (int)dom->signal_nr) 138aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return -EINVAL; 139aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 140aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (si >= 0) { 141aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (raw || !(name = dom->signal[si].name)) { 14296af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs snprintf(args->v0.name, sizeof(args->v0.name), 14396af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs "/%s/%02x", dom->name, si); 14496af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs } else { 14596af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs strncpy(args->v0.name, name, sizeof(args->v0.name)); 146aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 147aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 148aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 149aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs do { 150aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs while (++si < dom->signal_nr) { 151aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (all || dom->signal[si].name) { 15296af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs args->v0.iter = (di << 24) | ++si; 153aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return 0; 154aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 155aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 156aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs si = -1; 157aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs di = di + 1; 158aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs dom = list_entry(dom->head.next, typeof(*dom), head); 159aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } while (&dom->head != &ppm->domains); 160aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 16196af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs args->v0.iter = 0xffffffff; 162aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return 0; 163aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs} 164aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 165aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsstatic int 16696af8222cef78ab4d92186d5e10880dc78395415Ben Skeggsnouveau_perfctr_sample(struct nouveau_object *object, void *data, u32 size) 167aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs{ 16896af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs union { 16996af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs struct nvif_perfctr_sample none; 17096af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs } *args = data; 171aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfmon *ppm = (void *)object->engine; 172aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfctr *ctr, *tmp; 173aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfdom *dom; 17496af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs int ret; 175aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 17696af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs nv_ioctl(object, "perfctr sample size %d\n", size); 17796af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs if (nvif_unvers(args->none)) { 17896af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs nv_ioctl(object, "perfctr sample\n"); 17996af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs } else 18096af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs return ret; 181aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ppm->sequence++; 182aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 183aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs list_for_each_entry(dom, &ppm->domains, head) { 184aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs /* sample previous batch of counters */ 185aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (dom->quad != QUAD_MASK) { 186aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs dom->func->next(ppm, dom); 187aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs tmp = NULL; 188aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs while (!list_empty(&dom->list)) { 189aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ctr = list_first_entry(&dom->list, 190aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs typeof(*ctr), head); 191aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (ctr->slot < 0) break; 192aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if ( tmp && tmp == ctr) break; 193aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (!tmp) tmp = ctr; 194aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs dom->func->read(ppm, dom, ctr); 195aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ctr->slot = -1; 196aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs list_move_tail(&ctr->head, &dom->list); 197aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 198aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 199aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 200aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs dom->quad = QUAD_MASK; 201aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 202aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs /* setup next batch of counters for sampling */ 203aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs list_for_each_entry(ctr, &dom->list, head) { 204aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ctr->slot = ffs(dom->quad) - 1; 205aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (ctr->slot < 0) 206aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs break; 207aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs dom->quad &= ~(QUAD_FREE << ctr->slot); 208aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs dom->func->init(ppm, dom, ctr); 209aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 210aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 211aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (dom->quad != QUAD_MASK) 212aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs dom->func->next(ppm, dom); 213aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 214aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 215aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return 0; 216aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs} 217aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 218aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsstatic int 21996af8222cef78ab4d92186d5e10880dc78395415Ben Skeggsnouveau_perfctr_read(struct nouveau_object *object, void *data, u32 size) 220aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs{ 22196af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs union { 22296af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs struct nvif_perfctr_read_v0 v0; 22396af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs } *args = data; 224aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfctr *ctr = (void *)object; 22596af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs int ret; 22696af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs 22796af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs nv_ioctl(object, "perfctr read size %d\n", size); 22896af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs if (nvif_unpack(args->v0, 0, 0, false)) { 22996af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs nv_ioctl(object, "perfctr read vers %d\n", args->v0.version); 23096af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs } else 23196af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs return ret; 232aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 233aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (!ctr->clk) 234aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return -EAGAIN; 235aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 23696af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs args->v0.clk = ctr->clk; 23796af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs args->v0.ctr = ctr->ctr; 238aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return 0; 239aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs} 240aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 24196af8222cef78ab4d92186d5e10880dc78395415Ben Skeggsstatic int 24296af8222cef78ab4d92186d5e10880dc78395415Ben Skeggsnouveau_perfctr_mthd(struct nouveau_object *object, u32 mthd, 24396af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs void *data, u32 size) 24496af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs{ 24596af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs switch (mthd) { 24696af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs case NVIF_PERFCTR_V0_QUERY: 24796af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs return nouveau_perfctr_query(object, data, size); 24896af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs case NVIF_PERFCTR_V0_SAMPLE: 24996af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs return nouveau_perfctr_sample(object, data, size); 25096af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs case NVIF_PERFCTR_V0_READ: 25196af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs return nouveau_perfctr_read(object, data, size); 25296af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs default: 25396af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs break; 25496af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs } 25596af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs return -EINVAL; 25696af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs} 25796af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs 258aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsstatic void 259aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsnouveau_perfctr_dtor(struct nouveau_object *object) 260aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs{ 261aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfctr *ctr = (void *)object; 262aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (ctr->head.next) 263aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs list_del(&ctr->head); 264aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs nouveau_object_destroy(&ctr->base); 265aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs} 266aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 267aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsstatic int 268aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsnouveau_perfctr_ctor(struct nouveau_object *parent, 269aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_object *engine, 270aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_oclass *oclass, void *data, u32 size, 271aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_object **pobject) 272aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs{ 27396af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs union { 27496af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs struct nvif_perfctr_v0 v0; 27596af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs } *args = data; 276aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfmon *ppm = (void *)engine; 277aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfdom *dom = NULL; 278aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfsig *sig[4] = {}; 279aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfctr *ctr; 280aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs int ret, i; 281aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 28296af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs nv_ioctl(parent, "create perfctr size %d\n", size); 28396af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs if (nvif_unpack(args->v0, 0, 0, false)) { 28496af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs nv_ioctl(parent, "create perfctr vers %d logic_op %04x\n", 28596af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs args->v0.version, args->v0.logic_op); 28696af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs } else 28796af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs return ret; 288aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 28996af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs for (i = 0; i < ARRAY_SIZE(args->v0.name) && args->v0.name[i][0]; i++) { 29096af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs sig[i] = nouveau_perfsig_find(ppm, args->v0.name[i], 29196af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs strnlen(args->v0.name[i], 29296af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs sizeof(args->v0.name[i])), 29396af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs &dom); 294aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (!sig[i]) 295aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return -EINVAL; 296aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 297aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 298aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ret = nouveau_object_create(parent, engine, oclass, 0, &ctr); 299aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs *pobject = nv_object(ctr); 300aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (ret) 301aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return ret; 302aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 303aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ctr->slot = -1; 30496af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs ctr->logic_op = args->v0.logic_op; 305aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ctr->signal[0] = sig[0]; 306aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ctr->signal[1] = sig[1]; 307aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ctr->signal[2] = sig[2]; 308aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ctr->signal[3] = sig[3]; 309aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (dom) 310aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs list_add_tail(&ctr->head, &dom->list); 311aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return 0; 312aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs} 313aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 314aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsstatic struct nouveau_ofuncs 315aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsnouveau_perfctr_ofuncs = { 316aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs .ctor = nouveau_perfctr_ctor, 317aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs .dtor = nouveau_perfctr_dtor, 318aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs .init = nouveau_object_init, 319aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs .fini = nouveau_object_fini, 32096af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs .mthd = nouveau_perfctr_mthd, 321aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs}; 322aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 323aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsstruct nouveau_oclass 324aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsnouveau_perfmon_sclass[] = { 32596af8222cef78ab4d92186d5e10880dc78395415Ben Skeggs { .handle = NVIF_IOCTL_NEW_V0_PERFCTR, 326aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs .ofuncs = &nouveau_perfctr_ofuncs, 327aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs }, 328aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs {}, 329aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs}; 330aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 331aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs/******************************************************************************* 332aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * PPM context 333aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ******************************************************************************/ 334aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsstatic void 335aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsnouveau_perfctx_dtor(struct nouveau_object *object) 336aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs{ 337aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfmon *ppm = (void *)object->engine; 338aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs mutex_lock(&nv_subdev(ppm)->mutex); 339cbb4cf8bdffd943fa7cff724232b57b0e6891095Samuel Pitoiset nouveau_engctx_destroy(&ppm->context->base); 340aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ppm->context = NULL; 341aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs mutex_unlock(&nv_subdev(ppm)->mutex); 342aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs} 343aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 344aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsstatic int 345aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsnouveau_perfctx_ctor(struct nouveau_object *parent, 346aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_object *engine, 347aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_oclass *oclass, void *data, u32 size, 348aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_object **pobject) 349aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs{ 350aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfmon *ppm = (void *)engine; 351aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfctx *ctx; 352aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs int ret; 353aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 354aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ret = nouveau_engctx_create(parent, engine, oclass, NULL, 355aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 0, 0, 0, &ctx); 356aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs *pobject = nv_object(ctx); 357aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (ret) 358aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return ret; 359aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 360aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs mutex_lock(&nv_subdev(ppm)->mutex); 361aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (ppm->context == NULL) 362aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ppm->context = ctx; 363aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs mutex_unlock(&nv_subdev(ppm)->mutex); 364aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 365aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (ctx != ppm->context) 366aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return -EBUSY; 367aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 368aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return 0; 369aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs} 370aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 371aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsstruct nouveau_oclass 372aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsnouveau_perfmon_cclass = { 373aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs .handle = NV_ENGCTX(PERFMON, 0x00), 374aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs .ofuncs = &(struct nouveau_ofuncs) { 375aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs .ctor = nouveau_perfctx_ctor, 376aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs .dtor = nouveau_perfctx_dtor, 377aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs .init = _nouveau_engctx_init, 378aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs .fini = _nouveau_engctx_fini, 379aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs }, 380aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs}; 381aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 382aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs/******************************************************************************* 383aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs * PPM engine/subdev functions 384aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ******************************************************************************/ 385aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsint 386aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsnouveau_perfdom_new(struct nouveau_perfmon *ppm, const char *name, u32 mask, 387aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs u32 base, u32 size_unit, u32 size_domain, 388aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs const struct nouveau_specdom *spec) 389aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs{ 390aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs const struct nouveau_specdom *sdom; 391aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs const struct nouveau_specsig *ssig; 392aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfdom *dom; 393aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs int i; 394aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 395aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs for (i = 0; i == 0 || mask; i++) { 396aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs u32 addr = base + (i * size_unit); 397aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (i && !(mask & (1 << i))) 398aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs continue; 399aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 400aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs sdom = spec; 401aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs while (sdom->signal_nr) { 402aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs dom = kzalloc(sizeof(*dom) + sdom->signal_nr * 403aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs sizeof(*dom->signal), GFP_KERNEL); 404aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (!dom) 405aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return -ENOMEM; 406aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 407aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (mask) { 408aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs snprintf(dom->name, sizeof(dom->name), 409aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs "%s/%02x/%02x", name, i, 410aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs (int)(sdom - spec)); 411aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } else { 412aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs snprintf(dom->name, sizeof(dom->name), 413aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs "%s/%02x", name, (int)(sdom - spec)); 414aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 415aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 416aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs list_add_tail(&dom->head, &ppm->domains); 417aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs INIT_LIST_HEAD(&dom->list); 418aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs dom->func = sdom->func; 419aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs dom->addr = addr; 420aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs dom->quad = QUAD_MASK; 421aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs dom->signal_nr = sdom->signal_nr; 422aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 423aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ssig = (sdom++)->signal; 424aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs while (ssig->name) { 425aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs dom->signal[ssig->signal].name = ssig->name; 426aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ssig++; 427aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 428aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 429aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs addr += size_domain; 430aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 431aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 432aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs mask &= ~(1 << i); 433aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 434aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 435aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return 0; 436aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs} 437aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 438aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsint 439aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs_nouveau_perfmon_fini(struct nouveau_object *object, bool suspend) 440aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs{ 441aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfmon *ppm = (void *)object; 442aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return nouveau_engine_fini(&ppm->base, suspend); 443aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs} 444aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 445aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsint 446aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs_nouveau_perfmon_init(struct nouveau_object *object) 447aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs{ 448aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfmon *ppm = (void *)object; 449aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return nouveau_engine_init(&ppm->base); 450aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs} 451aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 452aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsvoid 453aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs_nouveau_perfmon_dtor(struct nouveau_object *object) 454aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs{ 455aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfmon *ppm = (void *)object; 456aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfdom *dom, *tmp; 457aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 458aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs list_for_each_entry_safe(dom, tmp, &ppm->domains, head) { 459aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs list_del(&dom->head); 460aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs kfree(dom); 461aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs } 462aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 463aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs nouveau_engine_destroy(&ppm->base); 464aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs} 465aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 466aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsint 467aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggsnouveau_perfmon_create_(struct nouveau_object *parent, 468aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_object *engine, 469aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_oclass *oclass, 470aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs int length, void **pobject) 471aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs{ 472aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs struct nouveau_perfmon *ppm; 473aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs int ret; 474aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 475aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ret = nouveau_engine_create_(parent, engine, oclass, true, "PPM", 476aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs "perfmon", length, pobject); 477aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs ppm = *pobject; 478aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs if (ret) 479aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return ret; 480aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs 481aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs INIT_LIST_HEAD(&ppm->domains); 482aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs return 0; 483aa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6Ben Skeggs} 484