aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2013-02-13 00:29:11 -0500
committerBen Skeggs <bskeggs@redhat.com>2013-11-08 00:40:05 -0500
commitaa4d7a4d55ab375b2f1c894ba680186e4a7c6fd6 (patch)
tree4c88b0a8f6e8e5cd1256228f06331dd31495748b
parent2984506fb6172712f83e573319baf7dbd0eb9028 (diff)
drm/nouveau/perfmon: initial infrastructure to expose performance counters
Internal use only at this point. Userspace later. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/Makefile9
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/base.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv40.c17
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv50.c15
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nvc0.c10
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nve0.c5
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/base.c449
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/daemon.c109
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nv40.c143
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nv40.h26
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nv50.c70
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nv84.c78
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nva3.c96
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nvc0.c173
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nvc0.h17
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nve0.c162
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nvf0.c71
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/priv.h91
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/class.h31
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/device.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/include/engine/perfmon.h39
22 files changed, 1616 insertions, 2 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
index 3859958581c2..7805ebc7255a 100644
--- a/drivers/gpu/drm/nouveau/Makefile
+++ b/drivers/gpu/drm/nouveau/Makefile
@@ -246,6 +246,15 @@ nouveau-y += core/engine/mpeg/nv40.o
246nouveau-y += core/engine/mpeg/nv44.o 246nouveau-y += core/engine/mpeg/nv44.o
247nouveau-y += core/engine/mpeg/nv50.o 247nouveau-y += core/engine/mpeg/nv50.o
248nouveau-y += core/engine/mpeg/nv84.o 248nouveau-y += core/engine/mpeg/nv84.o
249nouveau-y += core/engine/perfmon/base.o
250nouveau-y += core/engine/perfmon/daemon.o
251nouveau-y += core/engine/perfmon/nv40.o
252nouveau-y += core/engine/perfmon/nv50.o
253nouveau-y += core/engine/perfmon/nv84.o
254nouveau-y += core/engine/perfmon/nva3.o
255nouveau-y += core/engine/perfmon/nvc0.o
256nouveau-y += core/engine/perfmon/nve0.o
257nouveau-y += core/engine/perfmon/nvf0.o
249nouveau-y += core/engine/ppp/nv98.o 258nouveau-y += core/engine/ppp/nv98.o
250nouveau-y += core/engine/ppp/nvc0.o 259nouveau-y += core/engine/ppp/nvc0.o
251nouveau-y += core/engine/software/nv04.o 260nouveau-y += core/engine/software/nv04.o
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/base.c b/drivers/gpu/drm/nouveau/core/engine/device/base.c
index 894985aa84f3..f775f43f3f77 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c
@@ -77,6 +77,7 @@ static const u64 disable_map[] = {
77 [NVDEV_SUBDEV_THERM] = NV_DEVICE_DISABLE_CORE, 77 [NVDEV_SUBDEV_THERM] = NV_DEVICE_DISABLE_CORE,
78 [NVDEV_SUBDEV_PWR] = NV_DEVICE_DISABLE_CORE, 78 [NVDEV_SUBDEV_PWR] = NV_DEVICE_DISABLE_CORE,
79 [NVDEV_ENGINE_DMAOBJ] = NV_DEVICE_DISABLE_CORE, 79 [NVDEV_ENGINE_DMAOBJ] = NV_DEVICE_DISABLE_CORE,
80 [NVDEV_ENGINE_PERFMON] = NV_DEVICE_DISABLE_CORE,
80 [NVDEV_ENGINE_FIFO] = NV_DEVICE_DISABLE_FIFO, 81 [NVDEV_ENGINE_FIFO] = NV_DEVICE_DISABLE_FIFO,
81 [NVDEV_ENGINE_SW] = NV_DEVICE_DISABLE_FIFO, 82 [NVDEV_ENGINE_SW] = NV_DEVICE_DISABLE_FIFO,
82 [NVDEV_ENGINE_GR] = NV_DEVICE_DISABLE_GRAPH, 83 [NVDEV_ENGINE_GR] = NV_DEVICE_DISABLE_GRAPH,
@@ -123,7 +124,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
123 ret = nouveau_parent_create(parent, nv_object(device), oclass, 0, NULL, 124 ret = nouveau_parent_create(parent, nv_object(device), oclass, 0, NULL,
124 (1ULL << NVDEV_ENGINE_DMAOBJ) | 125 (1ULL << NVDEV_ENGINE_DMAOBJ) |
125 (1ULL << NVDEV_ENGINE_FIFO) | 126 (1ULL << NVDEV_ENGINE_FIFO) |
126 (1ULL << NVDEV_ENGINE_DISP), &devobj); 127 (1ULL << NVDEV_ENGINE_DISP) |
128 (1ULL << NVDEV_ENGINE_PERFMON), &devobj);
127 *pobject = nv_object(devobj); 129 *pobject = nv_object(devobj);
128 if (ret) 130 if (ret)
129 return ret; 131 return ret;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
index 7bcc4c9ce13f..97458cba2bef 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
@@ -43,6 +43,7 @@
43#include <engine/graph.h> 43#include <engine/graph.h>
44#include <engine/mpeg.h> 44#include <engine/mpeg.h>
45#include <engine/disp.h> 45#include <engine/disp.h>
46#include <engine/perfmon.h>
46 47
47int 48int
48nv40_identify(struct nouveau_device *device) 49nv40_identify(struct nouveau_device *device)
@@ -68,6 +69,7 @@ nv40_identify(struct nouveau_device *device)
68 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 69 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
69 device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; 70 device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass;
70 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 71 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass;
72 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
71 break; 73 break;
72 case 0x41: 74 case 0x41:
73 device->cname = "NV41"; 75 device->cname = "NV41";
@@ -89,6 +91,7 @@ nv40_identify(struct nouveau_device *device)
89 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 91 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
90 device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; 92 device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass;
91 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 93 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass;
94 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
92 break; 95 break;
93 case 0x42: 96 case 0x42:
94 device->cname = "NV42"; 97 device->cname = "NV42";
@@ -110,6 +113,7 @@ nv40_identify(struct nouveau_device *device)
110 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 113 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
111 device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; 114 device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass;
112 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 115 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass;
116 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
113 break; 117 break;
114 case 0x43: 118 case 0x43:
115 device->cname = "NV43"; 119 device->cname = "NV43";
@@ -131,6 +135,7 @@ nv40_identify(struct nouveau_device *device)
131 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 135 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
132 device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass; 136 device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass;
133 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 137 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass;
138 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
134 break; 139 break;
135 case 0x45: 140 case 0x45:
136 device->cname = "NV45"; 141 device->cname = "NV45";
@@ -152,6 +157,7 @@ nv40_identify(struct nouveau_device *device)
152 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 157 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
153 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 158 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
154 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 159 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass;
160 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
155 break; 161 break;
156 case 0x47: 162 case 0x47:
157 device->cname = "G70"; 163 device->cname = "G70";
@@ -173,6 +179,7 @@ nv40_identify(struct nouveau_device *device)
173 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 179 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
174 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 180 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
175 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 181 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass;
182 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
176 break; 183 break;
177 case 0x49: 184 case 0x49:
178 device->cname = "G71"; 185 device->cname = "G71";
@@ -194,6 +201,7 @@ nv40_identify(struct nouveau_device *device)
194 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 201 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
195 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 202 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
196 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 203 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass;
204 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
197 break; 205 break;
198 case 0x4b: 206 case 0x4b:
199 device->cname = "G73"; 207 device->cname = "G73";
@@ -215,6 +223,7 @@ nv40_identify(struct nouveau_device *device)
215 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 223 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
216 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 224 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
217 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 225 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass;
226 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
218 break; 227 break;
219 case 0x44: 228 case 0x44:
220 device->cname = "NV44"; 229 device->cname = "NV44";
@@ -236,6 +245,7 @@ nv40_identify(struct nouveau_device *device)
236 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 245 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
237 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 246 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
238 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 247 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass;
248 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
239 break; 249 break;
240 case 0x46: 250 case 0x46:
241 device->cname = "G72"; 251 device->cname = "G72";
@@ -257,6 +267,7 @@ nv40_identify(struct nouveau_device *device)
257 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 267 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
258 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 268 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
259 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 269 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass;
270 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
260 break; 271 break;
261 case 0x4a: 272 case 0x4a:
262 device->cname = "NV44A"; 273 device->cname = "NV44A";
@@ -278,6 +289,7 @@ nv40_identify(struct nouveau_device *device)
278 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 289 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
279 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 290 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
280 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 291 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass;
292 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
281 break; 293 break;
282 case 0x4c: 294 case 0x4c:
283 device->cname = "C61"; 295 device->cname = "C61";
@@ -299,6 +311,7 @@ nv40_identify(struct nouveau_device *device)
299 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 311 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
300 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 312 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
301 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 313 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass;
314 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
302 break; 315 break;
303 case 0x4e: 316 case 0x4e:
304 device->cname = "C51"; 317 device->cname = "C51";
@@ -320,6 +333,7 @@ nv40_identify(struct nouveau_device *device)
320 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 333 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
321 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 334 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
322 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 335 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass;
336 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
323 break; 337 break;
324 case 0x63: 338 case 0x63:
325 device->cname = "C73"; 339 device->cname = "C73";
@@ -341,6 +355,7 @@ nv40_identify(struct nouveau_device *device)
341 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 355 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
342 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 356 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
343 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 357 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass;
358 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
344 break; 359 break;
345 case 0x67: 360 case 0x67:
346 device->cname = "C67"; 361 device->cname = "C67";
@@ -362,6 +377,7 @@ nv40_identify(struct nouveau_device *device)
362 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 377 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
363 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 378 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
364 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 379 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass;
380 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
365 break; 381 break;
366 case 0x68: 382 case 0x68:
367 device->cname = "C68"; 383 device->cname = "C68";
@@ -383,6 +399,7 @@ nv40_identify(struct nouveau_device *device)
383 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass; 399 device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
384 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass; 400 device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
385 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass; 401 device->oclass[NVDEV_ENGINE_DISP ] = &nv04_disp_oclass;
402 device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
386 break; 403 break;
387 default: 404 default:
388 nv_fatal(device, "unknown Curie chipset\n"); 405 nv_fatal(device, "unknown Curie chipset\n");
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
index f44a2baecc79..671a6f4f4d94 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
@@ -50,6 +50,7 @@
50#include <engine/ppp.h> 50#include <engine/ppp.h>
51#include <engine/copy.h> 51#include <engine/copy.h>
52#include <engine/disp.h> 52#include <engine/disp.h>
53#include <engine/perfmon.h>
53 54
54int 55int
55nv50_identify(struct nouveau_device *device) 56nv50_identify(struct nouveau_device *device)
@@ -77,6 +78,7 @@ nv50_identify(struct nouveau_device *device)
77 device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass; 78 device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
78 device->oclass[NVDEV_ENGINE_MPEG ] = &nv50_mpeg_oclass; 79 device->oclass[NVDEV_ENGINE_MPEG ] = &nv50_mpeg_oclass;
79 device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass; 80 device->oclass[NVDEV_ENGINE_DISP ] = &nv50_disp_oclass;
81 device->oclass[NVDEV_ENGINE_PERFMON] = nv50_perfmon_oclass;
80 break; 82 break;
81 case 0x84: 83 case 0x84:
82 device->cname = "G84"; 84 device->cname = "G84";
@@ -103,6 +105,7 @@ nv50_identify(struct nouveau_device *device)
103 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; 105 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
104 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; 106 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
105 device->oclass[NVDEV_ENGINE_DISP ] = &nv84_disp_oclass; 107 device->oclass[NVDEV_ENGINE_DISP ] = &nv84_disp_oclass;
108 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
106 break; 109 break;
107 case 0x86: 110 case 0x86:
108 device->cname = "G86"; 111 device->cname = "G86";
@@ -129,6 +132,7 @@ nv50_identify(struct nouveau_device *device)
129 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; 132 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
130 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; 133 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
131 device->oclass[NVDEV_ENGINE_DISP ] = &nv84_disp_oclass; 134 device->oclass[NVDEV_ENGINE_DISP ] = &nv84_disp_oclass;
135 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
132 break; 136 break;
133 case 0x92: 137 case 0x92:
134 device->cname = "G92"; 138 device->cname = "G92";
@@ -155,6 +159,7 @@ nv50_identify(struct nouveau_device *device)
155 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; 159 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
156 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; 160 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
157 device->oclass[NVDEV_ENGINE_DISP ] = &nv84_disp_oclass; 161 device->oclass[NVDEV_ENGINE_DISP ] = &nv84_disp_oclass;
162 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
158 break; 163 break;
159 case 0x94: 164 case 0x94:
160 device->cname = "G94"; 165 device->cname = "G94";
@@ -181,6 +186,7 @@ nv50_identify(struct nouveau_device *device)
181 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; 186 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
182 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; 187 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
183 device->oclass[NVDEV_ENGINE_DISP ] = &nv94_disp_oclass; 188 device->oclass[NVDEV_ENGINE_DISP ] = &nv94_disp_oclass;
189 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
184 break; 190 break;
185 case 0x96: 191 case 0x96:
186 device->cname = "G96"; 192 device->cname = "G96";
@@ -207,6 +213,7 @@ nv50_identify(struct nouveau_device *device)
207 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; 213 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
208 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; 214 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
209 device->oclass[NVDEV_ENGINE_DISP ] = &nv94_disp_oclass; 215 device->oclass[NVDEV_ENGINE_DISP ] = &nv94_disp_oclass;
216 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
210 break; 217 break;
211 case 0x98: 218 case 0x98:
212 device->cname = "G98"; 219 device->cname = "G98";
@@ -233,6 +240,7 @@ nv50_identify(struct nouveau_device *device)
233 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass; 240 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass;
234 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; 241 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
235 device->oclass[NVDEV_ENGINE_DISP ] = &nv94_disp_oclass; 242 device->oclass[NVDEV_ENGINE_DISP ] = &nv94_disp_oclass;
243 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
236 break; 244 break;
237 case 0xa0: 245 case 0xa0:
238 device->cname = "G200"; 246 device->cname = "G200";
@@ -259,6 +267,7 @@ nv50_identify(struct nouveau_device *device)
259 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass; 267 device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
260 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass; 268 device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
261 device->oclass[NVDEV_ENGINE_DISP ] = &nva0_disp_oclass; 269 device->oclass[NVDEV_ENGINE_DISP ] = &nva0_disp_oclass;
270 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
262 break; 271 break;
263 case 0xaa: 272 case 0xaa:
264 device->cname = "MCP77/MCP78"; 273 device->cname = "MCP77/MCP78";
@@ -285,6 +294,7 @@ nv50_identify(struct nouveau_device *device)
285 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass; 294 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass;
286 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; 295 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
287 device->oclass[NVDEV_ENGINE_DISP ] = &nv94_disp_oclass; 296 device->oclass[NVDEV_ENGINE_DISP ] = &nv94_disp_oclass;
297 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
288 break; 298 break;
289 case 0xac: 299 case 0xac:
290 device->cname = "MCP79/MCP7A"; 300 device->cname = "MCP79/MCP7A";
@@ -311,6 +321,7 @@ nv50_identify(struct nouveau_device *device)
311 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass; 321 device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass;
312 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; 322 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
313 device->oclass[NVDEV_ENGINE_DISP ] = &nv94_disp_oclass; 323 device->oclass[NVDEV_ENGINE_DISP ] = &nv94_disp_oclass;
324 device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
314 break; 325 break;
315 case 0xa3: 326 case 0xa3:
316 device->cname = "GT215"; 327 device->cname = "GT215";
@@ -339,6 +350,7 @@ nv50_identify(struct nouveau_device *device)
339 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; 350 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
340 device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass; 351 device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass;
341 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 352 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass;
353 device->oclass[NVDEV_ENGINE_PERFMON] = nva3_perfmon_oclass;
342 break; 354 break;
343 case 0xa5: 355 case 0xa5:
344 device->cname = "GT216"; 356 device->cname = "GT216";
@@ -366,6 +378,7 @@ nv50_identify(struct nouveau_device *device)
366 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; 378 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
367 device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass; 379 device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass;
368 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 380 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass;
381 device->oclass[NVDEV_ENGINE_PERFMON] = nva3_perfmon_oclass;
369 break; 382 break;
370 case 0xa8: 383 case 0xa8:
371 device->cname = "GT218"; 384 device->cname = "GT218";
@@ -393,6 +406,7 @@ nv50_identify(struct nouveau_device *device)
393 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; 406 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
394 device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass; 407 device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass;
395 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 408 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass;
409 device->oclass[NVDEV_ENGINE_PERFMON] = nva3_perfmon_oclass;
396 break; 410 break;
397 case 0xaf: 411 case 0xaf:
398 device->cname = "MCP89"; 412 device->cname = "MCP89";
@@ -420,6 +434,7 @@ nv50_identify(struct nouveau_device *device)
420 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass; 434 device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
421 device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass; 435 device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass;
422 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 436 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass;
437 device->oclass[NVDEV_ENGINE_PERFMON] = nva3_perfmon_oclass;
423 break; 438 break;
424 default: 439 default:
425 nv_fatal(device, "unknown Tesla chipset\n"); 440 nv_fatal(device, "unknown Tesla chipset\n");
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
index 7db87cf231c7..94d5090d8eb9 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
@@ -50,6 +50,7 @@
50#include <engine/ppp.h> 50#include <engine/ppp.h>
51#include <engine/copy.h> 51#include <engine/copy.h>
52#include <engine/disp.h> 52#include <engine/disp.h>
53#include <engine/perfmon.h>
53 54
54int 55int
55nvc0_identify(struct nouveau_device *device) 56nvc0_identify(struct nouveau_device *device)
@@ -84,6 +85,7 @@ nvc0_identify(struct nouveau_device *device)
84 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 85 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
85 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; 86 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass;
86 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 87 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass;
88 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
87 break; 89 break;
88 case 0xc4: 90 case 0xc4:
89 device->cname = "GF104"; 91 device->cname = "GF104";
@@ -114,6 +116,7 @@ nvc0_identify(struct nouveau_device *device)
114 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 116 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
115 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; 117 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass;
116 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 118 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass;
119 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
117 break; 120 break;
118 case 0xc3: 121 case 0xc3:
119 device->cname = "GF106"; 122 device->cname = "GF106";
@@ -143,6 +146,7 @@ nvc0_identify(struct nouveau_device *device)
143 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 146 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
144 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 147 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
145 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 148 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass;
149 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
146 break; 150 break;
147 case 0xce: 151 case 0xce:
148 device->cname = "GF114"; 152 device->cname = "GF114";
@@ -173,6 +177,7 @@ nvc0_identify(struct nouveau_device *device)
173 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 177 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
174 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; 178 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass;
175 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 179 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass;
180 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
176 break; 181 break;
177 case 0xcf: 182 case 0xcf:
178 device->cname = "GF116"; 183 device->cname = "GF116";
@@ -203,6 +208,7 @@ nvc0_identify(struct nouveau_device *device)
203 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 208 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
204 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; 209 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass;
205 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 210 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass;
211 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
206 break; 212 break;
207 case 0xc1: 213 case 0xc1:
208 device->cname = "GF108"; 214 device->cname = "GF108";
@@ -232,6 +238,7 @@ nvc0_identify(struct nouveau_device *device)
232 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 238 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
233 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 239 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
234 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 240 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass;
241 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
235 break; 242 break;
236 case 0xc8: 243 case 0xc8:
237 device->cname = "GF110"; 244 device->cname = "GF110";
@@ -262,6 +269,7 @@ nvc0_identify(struct nouveau_device *device)
262 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 269 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
263 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass; 270 device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass;
264 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass; 271 device->oclass[NVDEV_ENGINE_DISP ] = &nva3_disp_oclass;
272 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
265 break; 273 break;
266 case 0xd9: 274 case 0xd9:
267 device->cname = "GF119"; 275 device->cname = "GF119";
@@ -291,6 +299,7 @@ nvc0_identify(struct nouveau_device *device)
291 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 299 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
292 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 300 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
293 device->oclass[NVDEV_ENGINE_DISP ] = &nvd0_disp_oclass; 301 device->oclass[NVDEV_ENGINE_DISP ] = &nvd0_disp_oclass;
302 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
294 break; 303 break;
295 case 0xd7: 304 case 0xd7:
296 device->cname = "GF117"; 305 device->cname = "GF117";
@@ -319,6 +328,7 @@ nvc0_identify(struct nouveau_device *device)
319 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 328 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
320 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; 329 device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
321 device->oclass[NVDEV_ENGINE_DISP ] = &nvd0_disp_oclass; 330 device->oclass[NVDEV_ENGINE_DISP ] = &nvd0_disp_oclass;
331 device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
322 break; 332 break;
323 default: 333 default:
324 nv_fatal(device, "unknown Fermi chipset\n"); 334 nv_fatal(device, "unknown Fermi chipset\n");
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
index 90b095c0875f..f3a7c1b3ea7c 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
@@ -50,6 +50,7 @@
50#include <engine/bsp.h> 50#include <engine/bsp.h>
51#include <engine/vp.h> 51#include <engine/vp.h>
52#include <engine/ppp.h> 52#include <engine/ppp.h>
53#include <engine/perfmon.h>
53 54
54int 55int
55nve0_identify(struct nouveau_device *device) 56nve0_identify(struct nouveau_device *device)
@@ -85,6 +86,7 @@ nve0_identify(struct nouveau_device *device)
85 device->oclass[NVDEV_ENGINE_BSP ] = &nve0_bsp_oclass; 86 device->oclass[NVDEV_ENGINE_BSP ] = &nve0_bsp_oclass;
86 device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass; 87 device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass;
87 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 88 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
89 device->oclass[NVDEV_ENGINE_PERFMON] = &nve0_perfmon_oclass;
88 break; 90 break;
89 case 0xe7: 91 case 0xe7:
90 device->cname = "GK107"; 92 device->cname = "GK107";
@@ -116,6 +118,7 @@ nve0_identify(struct nouveau_device *device)
116 device->oclass[NVDEV_ENGINE_BSP ] = &nve0_bsp_oclass; 118 device->oclass[NVDEV_ENGINE_BSP ] = &nve0_bsp_oclass;
117 device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass; 119 device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass;
118 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 120 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
121 device->oclass[NVDEV_ENGINE_PERFMON] = &nve0_perfmon_oclass;
119 break; 122 break;
120 case 0xe6: 123 case 0xe6:
121 device->cname = "GK106"; 124 device->cname = "GK106";
@@ -147,6 +150,7 @@ nve0_identify(struct nouveau_device *device)
147 device->oclass[NVDEV_ENGINE_BSP ] = &nve0_bsp_oclass; 150 device->oclass[NVDEV_ENGINE_BSP ] = &nve0_bsp_oclass;
148 device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass; 151 device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass;
149 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 152 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
153 device->oclass[NVDEV_ENGINE_PERFMON] = &nve0_perfmon_oclass;
150 break; 154 break;
151 case 0xf0: 155 case 0xf0:
152 device->cname = "GK110"; 156 device->cname = "GK110";
@@ -180,6 +184,7 @@ nve0_identify(struct nouveau_device *device)
180 device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass; 184 device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass;
181 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; 185 device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
182#endif 186#endif
187 device->oclass[NVDEV_ENGINE_PERFMON] = &nvf0_perfmon_oclass;
183 break; 188 break;
184 case 0x108: 189 case 0x108:
185 device->cname = "GK208"; 190 device->cname = "GK208";
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
index 3f4f35cc3848..434bb4b0fa2e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
@@ -1138,7 +1138,7 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
1138 if (ret) 1138 if (ret)
1139 return ret; 1139 return ret;
1140 1140
1141 nv_subdev(priv)->unit = 0x18001000; 1141 nv_subdev(priv)->unit = 0x08001000;
1142 nv_subdev(priv)->intr = nvc0_graph_intr; 1142 nv_subdev(priv)->intr = nvc0_graph_intr;
1143 1143
1144 priv->base.units = nvc0_graph_units; 1144 priv->base.units = nvc0_graph_units;
diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/base.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/base.c
new file mode 100644
index 000000000000..e9c5e51943ef
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/base.c
@@ -0,0 +1,449 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include <core/option.h>
26#include <core/class.h>
27
28#include <subdev/clock.h>
29
30#include "priv.h"
31
32#define QUAD_MASK 0x0f
33#define QUAD_FREE 0x01
34
35static struct nouveau_perfsig *
36nouveau_perfsig_find_(struct nouveau_perfdom *dom, const char *name, u32 size)
37{
38 char path[64];
39 int i;
40
41 if (name[0] != '/') {
42 for (i = 0; i < dom->signal_nr; i++) {
43 if ( dom->signal[i].name &&
44 !strncmp(name, dom->signal[i].name, size))
45 return &dom->signal[i];
46 }
47 } else {
48 for (i = 0; i < dom->signal_nr; i++) {
49 snprintf(path, sizeof(path), "/%s/%02x", dom->name, i);
50 if (!strncmp(name, path, size))
51 return &dom->signal[i];
52 }
53 }
54
55 return NULL;
56}
57
58struct nouveau_perfsig *
59nouveau_perfsig_find(struct nouveau_perfmon *ppm, const char *name, u32 size,
60 struct nouveau_perfdom **pdom)
61{
62 struct nouveau_perfdom *dom = *pdom;
63 struct nouveau_perfsig *sig;
64
65 if (dom == NULL) {
66 list_for_each_entry(dom, &ppm->domains, head) {
67 sig = nouveau_perfsig_find_(dom, name, size);
68 if (sig) {
69 *pdom = dom;
70 return sig;
71 }
72 }
73
74 return NULL;
75 }
76
77 return nouveau_perfsig_find_(dom, name, size);
78}
79
80struct nouveau_perfctr *
81nouveau_perfsig_wrap(struct nouveau_perfmon *ppm, const char *name,
82 struct nouveau_perfdom **pdom)
83{
84 struct nouveau_perfsig *sig;
85 struct nouveau_perfctr *ctr;
86
87 sig = nouveau_perfsig_find(ppm, name, strlen(name), pdom);
88 if (!sig)
89 return NULL;
90
91 ctr = kzalloc(sizeof(*ctr), GFP_KERNEL);
92 if (ctr) {
93 ctr->signal[0] = sig;
94 ctr->logic_op = 0xaaaa;
95 }
96
97 return ctr;
98}
99
100/*******************************************************************************
101 * Perfmon object classes
102 ******************************************************************************/
103static int
104nouveau_perfctr_query(struct nouveau_object *object, u32 mthd,
105 void *data, u32 size)
106{
107 struct nouveau_device *device = nv_device(object);
108 struct nouveau_perfmon *ppm = (void *)object->engine;
109 struct nouveau_perfdom *dom = NULL, *chk;
110 struct nv_perfctr_query *args = data;
111 const bool all = nouveau_boolopt(device->cfgopt, "NvPmShowAll", false);
112 const bool raw = nouveau_boolopt(device->cfgopt, "NvPmUnnamed", all);
113 const char *name;
114 int tmp = 0, di, si;
115 char path[64];
116
117 if (size < sizeof(*args))
118 return -EINVAL;
119
120 di = (args->iter & 0xff000000) >> 24;
121 si = (args->iter & 0x00ffffff) - 1;
122
123 list_for_each_entry(chk, &ppm->domains, head) {
124 if (tmp++ == di) {
125 dom = chk;
126 break;
127 }
128 }
129
130 if (dom == NULL || si >= (int)dom->signal_nr)
131 return -EINVAL;
132
133 if (si >= 0) {
134 if (raw || !(name = dom->signal[si].name)) {
135 snprintf(path, sizeof(path), "/%s/%02x", dom->name, si);
136 name = path;
137 }
138
139 if (args->name)
140 strncpy(args->name, name, args->size);
141 args->size = strlen(name) + 1;
142 }
143
144 do {
145 while (++si < dom->signal_nr) {
146 if (all || dom->signal[si].name) {
147 args->iter = (di << 24) | ++si;
148 return 0;
149 }
150 }
151 si = -1;
152 di = di + 1;
153 dom = list_entry(dom->head.next, typeof(*dom), head);
154 } while (&dom->head != &ppm->domains);
155
156 args->iter = 0xffffffff;
157 return 0;
158}
159
160static int
161nouveau_perfctr_sample(struct nouveau_object *object, u32 mthd,
162 void *data, u32 size)
163{
164 struct nouveau_perfmon *ppm = (void *)object->engine;
165 struct nouveau_perfctr *ctr, *tmp;
166 struct nouveau_perfdom *dom;
167 struct nv_perfctr_sample *args = data;
168
169 if (size < sizeof(*args))
170 return -EINVAL;
171 ppm->sequence++;
172
173 list_for_each_entry(dom, &ppm->domains, head) {
174 /* sample previous batch of counters */
175 if (dom->quad != QUAD_MASK) {
176 dom->func->next(ppm, dom);
177 tmp = NULL;
178 while (!list_empty(&dom->list)) {
179 ctr = list_first_entry(&dom->list,
180 typeof(*ctr), head);
181 if (ctr->slot < 0) break;
182 if ( tmp && tmp == ctr) break;
183 if (!tmp) tmp = ctr;
184 dom->func->read(ppm, dom, ctr);
185 ctr->slot = -1;
186 list_move_tail(&ctr->head, &dom->list);
187 }
188 }
189
190 dom->quad = QUAD_MASK;
191
192 /* setup next batch of counters for sampling */
193 list_for_each_entry(ctr, &dom->list, head) {
194 ctr->slot = ffs(dom->quad) - 1;
195 if (ctr->slot < 0)
196 break;
197 dom->quad &= ~(QUAD_FREE << ctr->slot);
198 dom->func->init(ppm, dom, ctr);
199 }
200
201 if (dom->quad != QUAD_MASK)
202 dom->func->next(ppm, dom);
203 }
204
205 return 0;
206}
207
208static int
209nouveau_perfctr_read(struct nouveau_object *object, u32 mthd,
210 void *data, u32 size)
211{
212 struct nouveau_perfctr *ctr = (void *)object;
213 struct nv_perfctr_read *args = data;
214
215 if (size < sizeof(*args))
216 return -EINVAL;
217 if (!ctr->clk)
218 return -EAGAIN;
219
220 args->clk = ctr->clk;
221 args->ctr = ctr->ctr;
222 return 0;
223}
224
225static void
226nouveau_perfctr_dtor(struct nouveau_object *object)
227{
228 struct nouveau_perfctr *ctr = (void *)object;
229 if (ctr->head.next)
230 list_del(&ctr->head);
231 nouveau_object_destroy(&ctr->base);
232}
233
234static int
235nouveau_perfctr_ctor(struct nouveau_object *parent,
236 struct nouveau_object *engine,
237 struct nouveau_oclass *oclass, void *data, u32 size,
238 struct nouveau_object **pobject)
239{
240 struct nouveau_perfmon *ppm = (void *)engine;
241 struct nouveau_perfdom *dom = NULL;
242 struct nouveau_perfsig *sig[4] = {};
243 struct nouveau_perfctr *ctr;
244 struct nv_perfctr_class *args = data;
245 int ret, i;
246
247 if (size < sizeof(*args))
248 return -EINVAL;
249
250 for (i = 0; i < ARRAY_SIZE(args->signal) && args->signal[i].name; i++) {
251 sig[i] = nouveau_perfsig_find(ppm, args->signal[i].name,
252 args->signal[i].size, &dom);
253 if (!sig[i])
254 return -EINVAL;
255 }
256
257 ret = nouveau_object_create(parent, engine, oclass, 0, &ctr);
258 *pobject = nv_object(ctr);
259 if (ret)
260 return ret;
261
262 ctr->slot = -1;
263 ctr->logic_op = args->logic_op;
264 ctr->signal[0] = sig[0];
265 ctr->signal[1] = sig[1];
266 ctr->signal[2] = sig[2];
267 ctr->signal[3] = sig[3];
268 if (dom)
269 list_add_tail(&ctr->head, &dom->list);
270 return 0;
271}
272
273static struct nouveau_ofuncs
274nouveau_perfctr_ofuncs = {
275 .ctor = nouveau_perfctr_ctor,
276 .dtor = nouveau_perfctr_dtor,
277 .init = nouveau_object_init,
278 .fini = nouveau_object_fini,
279};
280
281static struct nouveau_omthds
282nouveau_perfctr_omthds[] = {
283 { NV_PERFCTR_QUERY, NV_PERFCTR_QUERY, nouveau_perfctr_query },
284 { NV_PERFCTR_SAMPLE, NV_PERFCTR_SAMPLE, nouveau_perfctr_sample },
285 { NV_PERFCTR_READ, NV_PERFCTR_READ, nouveau_perfctr_read },
286 {}
287};
288
289struct nouveau_oclass
290nouveau_perfmon_sclass[] = {
291 { .handle = NV_PERFCTR_CLASS,
292 .ofuncs = &nouveau_perfctr_ofuncs,
293 .omthds = nouveau_perfctr_omthds,
294 },
295 {},
296};
297
298/*******************************************************************************
299 * PPM context
300 ******************************************************************************/
301static void
302nouveau_perfctx_dtor(struct nouveau_object *object)
303{
304 struct nouveau_perfmon *ppm = (void *)object->engine;
305 mutex_lock(&nv_subdev(ppm)->mutex);
306 ppm->context = NULL;
307 mutex_unlock(&nv_subdev(ppm)->mutex);
308}
309
310static int
311nouveau_perfctx_ctor(struct nouveau_object *parent,
312 struct nouveau_object *engine,
313 struct nouveau_oclass *oclass, void *data, u32 size,
314 struct nouveau_object **pobject)
315{
316 struct nouveau_perfmon *ppm = (void *)engine;
317 struct nouveau_perfctx *ctx;
318 int ret;
319
320 ret = nouveau_engctx_create(parent, engine, oclass, NULL,
321 0, 0, 0, &ctx);
322 *pobject = nv_object(ctx);
323 if (ret)
324 return ret;
325
326 mutex_lock(&nv_subdev(ppm)->mutex);
327 if (ppm->context == NULL)
328 ppm->context = ctx;
329 mutex_unlock(&nv_subdev(ppm)->mutex);
330
331 if (ctx != ppm->context)
332 return -EBUSY;
333
334 return 0;
335}
336
337struct nouveau_oclass
338nouveau_perfmon_cclass = {
339 .handle = NV_ENGCTX(PERFMON, 0x00),
340 .ofuncs = &(struct nouveau_ofuncs) {
341 .ctor = nouveau_perfctx_ctor,
342 .dtor = nouveau_perfctx_dtor,
343 .init = _nouveau_engctx_init,
344 .fini = _nouveau_engctx_fini,
345 },
346};
347
348/*******************************************************************************
349 * PPM engine/subdev functions
350 ******************************************************************************/
351int
352nouveau_perfdom_new(struct nouveau_perfmon *ppm, const char *name, u32 mask,
353 u32 base, u32 size_unit, u32 size_domain,
354 const struct nouveau_specdom *spec)
355{
356 const struct nouveau_specdom *sdom;
357 const struct nouveau_specsig *ssig;
358 struct nouveau_perfdom *dom;
359 int i;
360
361 for (i = 0; i == 0 || mask; i++) {
362 u32 addr = base + (i * size_unit);
363 if (i && !(mask & (1 << i)))
364 continue;
365
366 sdom = spec;
367 while (sdom->signal_nr) {
368 dom = kzalloc(sizeof(*dom) + sdom->signal_nr *
369 sizeof(*dom->signal), GFP_KERNEL);
370 if (!dom)
371 return -ENOMEM;
372
373 if (mask) {
374 snprintf(dom->name, sizeof(dom->name),
375 "%s/%02x/%02x", name, i,
376 (int)(sdom - spec));
377 } else {
378 snprintf(dom->name, sizeof(dom->name),
379 "%s/%02x", name, (int)(sdom - spec));
380 }
381
382 list_add_tail(&dom->head, &ppm->domains);
383 INIT_LIST_HEAD(&dom->list);
384 dom->func = sdom->func;
385 dom->addr = addr;
386 dom->quad = QUAD_MASK;
387 dom->signal_nr = sdom->signal_nr;
388
389 ssig = (sdom++)->signal;
390 while (ssig->name) {
391 dom->signal[ssig->signal].name = ssig->name;
392 ssig++;
393 }
394
395 addr += size_domain;
396 }
397
398 mask &= ~(1 << i);
399 }
400
401 return 0;
402}
403
404int
405_nouveau_perfmon_fini(struct nouveau_object *object, bool suspend)
406{
407 struct nouveau_perfmon *ppm = (void *)object;
408 return nouveau_engine_fini(&ppm->base, suspend);
409}
410
411int
412_nouveau_perfmon_init(struct nouveau_object *object)
413{
414 struct nouveau_perfmon *ppm = (void *)object;
415 return nouveau_engine_init(&ppm->base);
416}
417
418void
419_nouveau_perfmon_dtor(struct nouveau_object *object)
420{
421 struct nouveau_perfmon *ppm = (void *)object;
422 struct nouveau_perfdom *dom, *tmp;
423
424 list_for_each_entry_safe(dom, tmp, &ppm->domains, head) {
425 list_del(&dom->head);
426 kfree(dom);
427 }
428
429 nouveau_engine_destroy(&ppm->base);
430}
431
432int
433nouveau_perfmon_create_(struct nouveau_object *parent,
434 struct nouveau_object *engine,
435 struct nouveau_oclass *oclass,
436 int length, void **pobject)
437{
438 struct nouveau_perfmon *ppm;
439 int ret;
440
441 ret = nouveau_engine_create_(parent, engine, oclass, true, "PPM",
442 "perfmon", length, pobject);
443 ppm = *pobject;
444 if (ret)
445 return ret;
446
447 INIT_LIST_HEAD(&ppm->domains);
448 return 0;
449}
diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/daemon.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/daemon.c
new file mode 100644
index 000000000000..50696cc7b7d7
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/daemon.c
@@ -0,0 +1,109 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "priv.h"
26
27static void
28pwr_perfctr_init(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom,
29 struct nouveau_perfctr *ctr)
30{
31 u32 mask = 0x00000000;
32 u32 ctrl = 0x00000001;
33 int i;
34
35 for (i = 0; i < ARRAY_SIZE(ctr->signal) && ctr->signal[i]; i++)
36 mask |= 1 << (ctr->signal[i] - dom->signal);
37
38 nv_wr32(ppm, 0x10a504 + (ctr->slot * 0x10), mask);
39 nv_wr32(ppm, 0x10a50c + (ctr->slot * 0x10), ctrl);
40 nv_wr32(ppm, 0x10a50c + (ppm->last * 0x10), 0x00000003);
41}
42
43static void
44pwr_perfctr_read(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom,
45 struct nouveau_perfctr *ctr)
46{
47 ctr->ctr = ppm->pwr[ctr->slot];
48 ctr->clk = ppm->pwr[ppm->last];
49}
50
51static void
52pwr_perfctr_next(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom)
53{
54 int i;
55
56 for (i = 0; i <= ppm->last; i++) {
57 ppm->pwr[i] = nv_rd32(ppm, 0x10a508 + (i * 0x10));
58 nv_wr32(ppm, 0x10a508 + (i * 0x10), 0x80000000);
59 }
60}
61
62static const struct nouveau_funcdom
63pwr_perfctr_func = {
64 .init = pwr_perfctr_init,
65 .read = pwr_perfctr_read,
66 .next = pwr_perfctr_next,
67};
68
69const struct nouveau_specdom
70nva3_perfmon_pwr[] = {
71 { 0x20, (const struct nouveau_specsig[]) {
72 { 0x00, "pwr_gr_idle" },
73 { 0x04, "pwr_bsp_idle" },
74 { 0x05, "pwr_vp_idle" },
75 { 0x06, "pwr_ppp_idle" },
76 { 0x13, "pwr_ce0_idle" },
77 {}
78 }, &pwr_perfctr_func },
79 {}
80};
81
82const struct nouveau_specdom
83nvc0_perfmon_pwr[] = {
84 { 0x20, (const struct nouveau_specsig[]) {
85 { 0x00, "pwr_gr_idle" },
86 { 0x04, "pwr_bsp_idle" },
87 { 0x05, "pwr_vp_idle" },
88 { 0x06, "pwr_ppp_idle" },
89 { 0x13, "pwr_ce0_idle" },
90 { 0x14, "pwr_ce1_idle" },
91 {}
92 }, &pwr_perfctr_func },
93 {}
94};
95
96const struct nouveau_specdom
97nve0_perfmon_pwr[] = {
98 { 0x20, (const struct nouveau_specsig[]) {
99 { 0x00, "pwr_gr_idle" },
100 { 0x04, "pwr_bsp_idle" },
101 { 0x05, "pwr_vp_idle" },
102 { 0x06, "pwr_ppp_idle" },
103 { 0x13, "pwr_ce0_idle" },
104 { 0x14, "pwr_ce1_idle" },
105 { 0x15, "pwr_ce2_idle" },
106 {}
107 }, &pwr_perfctr_func },
108 {}
109};
diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nv40.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/nv40.c
new file mode 100644
index 000000000000..b2a10785adb1
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nv40.c
@@ -0,0 +1,143 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "nv40.h"
26
27/*******************************************************************************
28 * Perfmon object classes
29 ******************************************************************************/
30
31/*******************************************************************************
32 * PPM context
33 ******************************************************************************/
34
35/*******************************************************************************
36 * PPM engine/subdev functions
37 ******************************************************************************/
38
39static void
40nv40_perfctr_init(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom,
41 struct nouveau_perfctr *ctr)
42{
43 struct nv40_perfmon_priv *priv = (void *)ppm;
44 struct nv40_perfmon_cntr *cntr = (void *)ctr;
45 u32 log = ctr->logic_op;
46 u32 src = 0x00000000;
47 int i;
48
49 for (i = 0; i < 4 && ctr->signal[i]; i++)
50 src |= (ctr->signal[i] - dom->signal) << (i * 8);
51
52 nv_wr32(priv, 0x00a7c0 + dom->addr, 0x00000001);
53 nv_wr32(priv, 0x00a400 + dom->addr + (cntr->base.slot * 0x40), src);
54 nv_wr32(priv, 0x00a420 + dom->addr + (cntr->base.slot * 0x40), log);
55}
56
57static void
58nv40_perfctr_read(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom,
59 struct nouveau_perfctr *ctr)
60{
61 struct nv40_perfmon_priv *priv = (void *)ppm;
62 struct nv40_perfmon_cntr *cntr = (void *)ctr;
63
64 switch (cntr->base.slot) {
65 case 0: cntr->base.ctr = nv_rd32(priv, 0x00a700 + dom->addr); break;
66 case 1: cntr->base.ctr = nv_rd32(priv, 0x00a6c0 + dom->addr); break;
67 case 2: cntr->base.ctr = nv_rd32(priv, 0x00a680 + dom->addr); break;
68 case 3: cntr->base.ctr = nv_rd32(priv, 0x00a740 + dom->addr); break;
69 }
70 cntr->base.clk = nv_rd32(priv, 0x00a600 + dom->addr);
71}
72
73static void
74nv40_perfctr_next(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom)
75{
76 struct nv40_perfmon_priv *priv = (void *)ppm;
77 if (priv->sequence != ppm->sequence) {
78 nv_wr32(priv, 0x400084, 0x00000020);
79 priv->sequence = ppm->sequence;
80 }
81}
82
83const struct nouveau_funcdom
84nv40_perfctr_func = {
85 .init = nv40_perfctr_init,
86 .read = nv40_perfctr_read,
87 .next = nv40_perfctr_next,
88};
89
90static const struct nouveau_specdom
91nv40_perfmon[] = {
92 { 0x20, (const struct nouveau_specsig[]) {
93 {}
94 }, &nv40_perfctr_func },
95 { 0x20, (const struct nouveau_specsig[]) {
96 {}
97 }, &nv40_perfctr_func },
98 { 0x20, (const struct nouveau_specsig[]) {
99 {}
100 }, &nv40_perfctr_func },
101 { 0x20, (const struct nouveau_specsig[]) {
102 {}
103 }, &nv40_perfctr_func },
104 { 0x20, (const struct nouveau_specsig[]) {
105 {}
106 }, &nv40_perfctr_func },
107 {}
108};
109
110int
111nv40_perfmon_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
112 struct nouveau_oclass *oclass, void *data, u32 size,
113 struct nouveau_object **pobject)
114{
115 struct nv40_perfmon_oclass *mclass = (void *)oclass;
116 struct nv40_perfmon_priv *priv;
117 int ret;
118
119 ret = nouveau_perfmon_create(parent, engine, oclass, &priv);
120 *pobject = nv_object(priv);
121 if (ret)
122 return ret;
123
124 ret = nouveau_perfdom_new(&priv->base, "pm", 0, 0, 0, 4, mclass->doms);
125 if (ret)
126 return ret;
127
128 nv_engine(priv)->cclass = &nouveau_perfmon_cclass;
129 nv_engine(priv)->sclass = nouveau_perfmon_sclass;
130 return 0;
131}
132
133struct nouveau_oclass *
134nv40_perfmon_oclass = &(struct nv40_perfmon_oclass) {
135 .base.handle = NV_ENGINE(PERFMON, 0x40),
136 .base.ofuncs = &(struct nouveau_ofuncs) {
137 .ctor = nv40_perfmon_ctor,
138 .dtor = _nouveau_perfmon_dtor,
139 .init = _nouveau_perfmon_init,
140 .fini = _nouveau_perfmon_fini,
141 },
142 .doms = nv40_perfmon,
143}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nv40.h b/drivers/gpu/drm/nouveau/core/engine/perfmon/nv40.h
new file mode 100644
index 000000000000..1b5792d1df14
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nv40.h
@@ -0,0 +1,26 @@
1#ifndef __NVKM_PM_NV40_H__
2#define __NVKM_PM_NV40_H__
3
4#include "priv.h"
5
6struct nv40_perfmon_oclass {
7 struct nouveau_oclass base;
8 const struct nouveau_specdom *doms;
9};
10
11struct nv40_perfmon_priv {
12 struct nouveau_perfmon base;
13 u32 sequence;
14};
15
16int nv40_perfmon_ctor(struct nouveau_object *, struct nouveau_object *,
17 struct nouveau_oclass *, void *data, u32 size,
18 struct nouveau_object **pobject);
19
20struct nv40_perfmon_cntr {
21 struct nouveau_perfctr base;
22};
23
24extern const struct nouveau_funcdom nv40_perfctr_func;
25
26#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nv50.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/nv50.c
new file mode 100644
index 000000000000..94217691fe67
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nv50.c
@@ -0,0 +1,70 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "nv40.h"
26
27/*******************************************************************************
28 * Perfmon object classes
29 ******************************************************************************/
30
31/*******************************************************************************
32 * PPM context
33 ******************************************************************************/
34
35/*******************************************************************************
36 * PPM engine/subdev functions
37 ******************************************************************************/
38
39static const struct nouveau_specdom
40nv50_perfmon[] = {
41 { 0x040, (const struct nouveau_specsig[]) {
42 {}
43 }, &nv40_perfctr_func },
44 { 0x100, (const struct nouveau_specsig[]) {
45 { 0xc8, "gr_idle" },
46 {}
47 }, &nv40_perfctr_func },
48 { 0x100, (const struct nouveau_specsig[]) {
49 {}
50 }, &nv40_perfctr_func },
51 { 0x020, (const struct nouveau_specsig[]) {
52 {}
53 }, &nv40_perfctr_func },
54 { 0x040, (const struct nouveau_specsig[]) {
55 {}
56 }, &nv40_perfctr_func },
57 {}
58};
59
60struct nouveau_oclass *
61nv50_perfmon_oclass = &(struct nv40_perfmon_oclass) {
62 .base.handle = NV_ENGINE(PERFMON, 0x50),
63 .base.ofuncs = &(struct nouveau_ofuncs) {
64 .ctor = nv40_perfmon_ctor,
65 .dtor = _nouveau_perfmon_dtor,
66 .init = _nouveau_perfmon_init,
67 .fini = _nouveau_perfmon_fini,
68 },
69 .doms = nv50_perfmon,
70}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nv84.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/nv84.c
new file mode 100644
index 000000000000..9232c7fc6253
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nv84.c
@@ -0,0 +1,78 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "nv40.h"
26
27/*******************************************************************************
28 * Perfmon object classes
29 ******************************************************************************/
30
31/*******************************************************************************
32 * PPM context
33 ******************************************************************************/
34
35/*******************************************************************************
36 * PPM engine/subdev functions
37 ******************************************************************************/
38
39static const struct nouveau_specdom
40nv84_perfmon[] = {
41 { 0x20, (const struct nouveau_specsig[]) {
42 {}
43 }, &nv40_perfctr_func },
44 { 0x20, (const struct nouveau_specsig[]) {
45 {}
46 }, &nv40_perfctr_func },
47 { 0x20, (const struct nouveau_specsig[]) {
48 {}
49 }, &nv40_perfctr_func },
50 { 0x20, (const struct nouveau_specsig[]) {
51 {}
52 }, &nv40_perfctr_func },
53 { 0x20, (const struct nouveau_specsig[]) {
54 {}
55 }, &nv40_perfctr_func },
56 { 0x20, (const struct nouveau_specsig[]) {
57 {}
58 }, &nv40_perfctr_func },
59 { 0x20, (const struct nouveau_specsig[]) {
60 {}
61 }, &nv40_perfctr_func },
62 { 0x20, (const struct nouveau_specsig[]) {
63 {}
64 }, &nv40_perfctr_func },
65 {}
66};
67
68struct nouveau_oclass *
69nv84_perfmon_oclass = &(struct nv40_perfmon_oclass) {
70 .base.handle = NV_ENGINE(PERFMON, 0x84),
71 .base.ofuncs = &(struct nouveau_ofuncs) {
72 .ctor = nv40_perfmon_ctor,
73 .dtor = _nouveau_perfmon_dtor,
74 .init = _nouveau_perfmon_init,
75 .fini = _nouveau_perfmon_fini,
76 },
77 .doms = nv84_perfmon,
78}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nva3.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/nva3.c
new file mode 100644
index 000000000000..6197ebdeb648
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nva3.c
@@ -0,0 +1,96 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "nv40.h"
26
27/*******************************************************************************
28 * Perfmon object classes
29 ******************************************************************************/
30
31/*******************************************************************************
32 * PPM context
33 ******************************************************************************/
34
35/*******************************************************************************
36 * PPM engine/subdev functions
37 ******************************************************************************/
38
39static const struct nouveau_specdom
40nva3_perfmon[] = {
41 { 0x20, (const struct nouveau_specsig[]) {
42 {}
43 }, &nv40_perfctr_func },
44 { 0x20, (const struct nouveau_specsig[]) {
45 {}
46 }, &nv40_perfctr_func },
47 { 0x20, (const struct nouveau_specsig[]) {
48 {}
49 }, &nv40_perfctr_func },
50 { 0x20, (const struct nouveau_specsig[]) {
51 {}
52 }, &nv40_perfctr_func },
53 { 0x20, (const struct nouveau_specsig[]) {
54 {}
55 }, &nv40_perfctr_func },
56 { 0x20, (const struct nouveau_specsig[]) {
57 {}
58 }, &nv40_perfctr_func },
59 { 0x20, (const struct nouveau_specsig[]) {
60 {}
61 }, &nv40_perfctr_func },
62 { 0x20, (const struct nouveau_specsig[]) {
63 {}
64 }, &nv40_perfctr_func },
65 {}
66};
67
68static int
69nva3_perfmon_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
70 struct nouveau_oclass *oclass, void *data, u32 size,
71 struct nouveau_object **object)
72{
73 int ret = nv40_perfmon_ctor(parent, engine, oclass, data, size, object);
74 if (ret == 0) {
75 struct nv40_perfmon_priv *priv = (void *)*object;
76 ret = nouveau_perfdom_new(&priv->base, "pwr", 0, 0, 0, 0,
77 nva3_perfmon_pwr);
78 if (ret)
79 return ret;
80
81 priv->base.last = 3;
82 }
83 return ret;
84}
85
86struct nouveau_oclass *
87nva3_perfmon_oclass = &(struct nv40_perfmon_oclass) {
88 .base.handle = NV_ENGINE(PERFMON, 0xa3),
89 .base.ofuncs = &(struct nouveau_ofuncs) {
90 .ctor = nva3_perfmon_ctor,
91 .dtor = _nouveau_perfmon_dtor,
92 .init = _nouveau_perfmon_init,
93 .fini = _nouveau_perfmon_fini,
94 },
95 .doms = nva3_perfmon,
96}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/nvc0.c
new file mode 100644
index 000000000000..74b241042502
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nvc0.c
@@ -0,0 +1,173 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "nvc0.h"
26
27/*******************************************************************************
28 * Perfmon object classes
29 ******************************************************************************/
30
31/*******************************************************************************
32 * PPM context
33 ******************************************************************************/
34
35/*******************************************************************************
36 * PPM engine/subdev functions
37 ******************************************************************************/
38
39static const struct nouveau_specdom
40nvc0_perfmon_hub[] = {
41 {}
42};
43
44static const struct nouveau_specdom
45nvc0_perfmon_gpc[] = {
46 {}
47};
48
49static const struct nouveau_specdom
50nvc0_perfmon_part[] = {
51 {}
52};
53
54static void
55nvc0_perfctr_init(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom,
56 struct nouveau_perfctr *ctr)
57{
58 struct nvc0_perfmon_priv *priv = (void *)ppm;
59 struct nvc0_perfmon_cntr *cntr = (void *)ctr;
60 u32 log = ctr->logic_op;
61 u32 src = 0x00000000;
62 int i;
63
64 for (i = 0; i < 4 && ctr->signal[i]; i++)
65 src |= (ctr->signal[i] - dom->signal) << (i * 8);
66
67 nv_wr32(priv, dom->addr + 0x09c, 0x00040002);
68 nv_wr32(priv, dom->addr + 0x100, 0x00000000);
69 nv_wr32(priv, dom->addr + 0x040 + (cntr->base.slot * 0x08), src);
70 nv_wr32(priv, dom->addr + 0x044 + (cntr->base.slot * 0x08), log);
71}
72
73static void
74nvc0_perfctr_read(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom,
75 struct nouveau_perfctr *ctr)
76{
77 struct nvc0_perfmon_priv *priv = (void *)ppm;
78 struct nvc0_perfmon_cntr *cntr = (void *)ctr;
79
80 switch (cntr->base.slot) {
81 case 0: cntr->base.ctr = nv_rd32(priv, dom->addr + 0x08c); break;
82 case 1: cntr->base.ctr = nv_rd32(priv, dom->addr + 0x088); break;
83 case 2: cntr->base.ctr = nv_rd32(priv, dom->addr + 0x080); break;
84 case 3: cntr->base.ctr = nv_rd32(priv, dom->addr + 0x090); break;
85 }
86 cntr->base.clk = nv_rd32(priv, dom->addr + 0x070);
87}
88
89static void
90nvc0_perfctr_next(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom)
91{
92 struct nvc0_perfmon_priv *priv = (void *)ppm;
93 nv_wr32(priv, dom->addr + 0x06c, dom->signal_nr - 0x40 + 0x27);
94 nv_wr32(priv, dom->addr + 0x0ec, 0x00000011);
95}
96
97const struct nouveau_funcdom
98nvc0_perfctr_func = {
99 .init = nvc0_perfctr_init,
100 .read = nvc0_perfctr_read,
101 .next = nvc0_perfctr_next,
102};
103
104int
105nvc0_perfmon_fini(struct nouveau_object *object, bool suspend)
106{
107 struct nvc0_perfmon_priv *priv = (void *)object;
108 nv_mask(priv, 0x000200, 0x10000000, 0x00000000);
109 nv_mask(priv, 0x000200, 0x10000000, 0x10000000);
110 return nouveau_perfmon_fini(&priv->base, suspend);
111}
112
113static int
114nvc0_perfmon_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
115 struct nouveau_oclass *oclass, void *data, u32 size,
116 struct nouveau_object **pobject)
117{
118 struct nvc0_perfmon_priv *priv;
119 u32 mask;
120 int ret;
121
122 ret = nouveau_perfmon_create(parent, engine, oclass, &priv);
123 *pobject = nv_object(priv);
124 if (ret)
125 return ret;
126
127 ret = nouveau_perfdom_new(&priv->base, "pwr", 0, 0, 0, 0,
128 nvc0_perfmon_pwr);
129 if (ret)
130 return ret;
131
132 /* HUB */
133 ret = nouveau_perfdom_new(&priv->base, "hub", 0, 0x1b0000, 0, 0x200,
134 nvc0_perfmon_hub);
135 if (ret)
136 return ret;
137
138 /* GPC */
139 mask = (1 << nv_rd32(priv, 0x022430)) - 1;
140 mask &= ~nv_rd32(priv, 0x022504);
141 mask &= ~nv_rd32(priv, 0x022584);
142
143 ret = nouveau_perfdom_new(&priv->base, "gpc", mask, 0x180000,
144 0x1000, 0x200, nvc0_perfmon_gpc);
145 if (ret)
146 return ret;
147
148 /* PART */
149 mask = (1 << nv_rd32(priv, 0x022438)) - 1;
150 mask &= ~nv_rd32(priv, 0x022548);
151 mask &= ~nv_rd32(priv, 0x0225c8);
152
153 ret = nouveau_perfdom_new(&priv->base, "part", mask, 0x1a0000,
154 0x1000, 0x200, nvc0_perfmon_part);
155 if (ret)
156 return ret;
157
158 nv_engine(priv)->cclass = &nouveau_perfmon_cclass;
159 nv_engine(priv)->sclass = nouveau_perfmon_sclass;
160 priv->base.last = 7;
161 return 0;
162}
163
164struct nouveau_oclass
165nvc0_perfmon_oclass = {
166 .handle = NV_ENGINE(PERFMON, 0xc0),
167 .ofuncs = &(struct nouveau_ofuncs) {
168 .ctor = nvc0_perfmon_ctor,
169 .dtor = _nouveau_perfmon_dtor,
170 .init = _nouveau_perfmon_init,
171 .fini = nvc0_perfmon_fini,
172 },
173};
diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/perfmon/nvc0.h
new file mode 100644
index 000000000000..f66bca484263
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nvc0.h
@@ -0,0 +1,17 @@
1#ifndef __NVKM_PM_NVC0_H__
2#define __NVKM_PM_NVC0_H__
3
4#include "priv.h"
5
6struct nvc0_perfmon_priv {
7 struct nouveau_perfmon base;
8};
9
10struct nvc0_perfmon_cntr {
11 struct nouveau_perfctr base;
12};
13
14extern const struct nouveau_funcdom nvc0_perfctr_func;
15int nvc0_perfmon_fini(struct nouveau_object *, bool);
16
17#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nve0.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/nve0.c
new file mode 100644
index 000000000000..71d718c12075
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nve0.c
@@ -0,0 +1,162 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "nvc0.h"
26
27/*******************************************************************************
28 * Perfmon object classes
29 ******************************************************************************/
30
31/*******************************************************************************
32 * PPM context
33 ******************************************************************************/
34
35/*******************************************************************************
36 * PPM engine/subdev functions
37 ******************************************************************************/
38
39static const struct nouveau_specdom
40nve0_perfmon_hub[] = {
41 { 0x60, (const struct nouveau_specsig[]) {
42 { 0x47, "hub00_user_0" },
43 {}
44 }, &nvc0_perfctr_func },
45 { 0x40, (const struct nouveau_specsig[]) {
46 { 0x27, "hub01_user_0" },
47 {}
48 }, &nvc0_perfctr_func },
49 { 0x60, (const struct nouveau_specsig[]) {
50 { 0x47, "hub02_user_0" },
51 {}
52 }, &nvc0_perfctr_func },
53 { 0x60, (const struct nouveau_specsig[]) {
54 { 0x47, "hub03_user_0" },
55 {}
56 }, &nvc0_perfctr_func },
57 { 0x40, (const struct nouveau_specsig[]) {
58 { 0x03, "host_mmio_rd" },
59 { 0x27, "hub04_user_0" },
60 {}
61 }, &nvc0_perfctr_func },
62 { 0x60, (const struct nouveau_specsig[]) {
63 { 0x47, "hub05_user_0" },
64 {}
65 }, &nvc0_perfctr_func },
66 { 0xc0, (const struct nouveau_specsig[]) {
67 { 0x74, "host_fb_rd3x" },
68 { 0x75, "host_fb_rd3x_2" },
69 { 0xa7, "hub06_user_0" },
70 {}
71 }, &nvc0_perfctr_func },
72 { 0x60, (const struct nouveau_specsig[]) {
73 { 0x47, "hub07_user_0" },
74 {}
75 }, &nvc0_perfctr_func },
76 {}
77};
78
79static const struct nouveau_specdom
80nve0_perfmon_gpc[] = {
81 { 0xe0, (const struct nouveau_specsig[]) {
82 { 0xc7, "gpc00_user_0" },
83 {}
84 }, &nvc0_perfctr_func },
85 {}
86};
87
88static const struct nouveau_specdom
89nve0_perfmon_part[] = {
90 { 0x60, (const struct nouveau_specsig[]) {
91 { 0x47, "part00_user_0" },
92 {}
93 }, &nvc0_perfctr_func },
94 { 0x60, (const struct nouveau_specsig[]) {
95 { 0x47, "part01_user_0" },
96 {}
97 }, &nvc0_perfctr_func },
98 {}
99};
100
101static int
102nve0_perfmon_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
103 struct nouveau_oclass *oclass, void *data, u32 size,
104 struct nouveau_object **pobject)
105{
106 struct nvc0_perfmon_priv *priv;
107 u32 mask;
108 int ret;
109
110 ret = nouveau_perfmon_create(parent, engine, oclass, &priv);
111 *pobject = nv_object(priv);
112 if (ret)
113 return ret;
114
115 /* PDAEMON */
116 ret = nouveau_perfdom_new(&priv->base, "pwr", 0, 0, 0, 0,
117 nve0_perfmon_pwr);
118 if (ret)
119 return ret;
120
121 /* HUB */
122 ret = nouveau_perfdom_new(&priv->base, "hub", 0, 0x1b0000, 0, 0x200,
123 nve0_perfmon_hub);
124 if (ret)
125 return ret;
126
127 /* GPC */
128 mask = (1 << nv_rd32(priv, 0x022430)) - 1;
129 mask &= ~nv_rd32(priv, 0x022504);
130 mask &= ~nv_rd32(priv, 0x022584);
131
132 ret = nouveau_perfdom_new(&priv->base, "gpc", mask, 0x180000,
133 0x1000, 0x200, nve0_perfmon_gpc);
134 if (ret)
135 return ret;
136
137 /* PART */
138 mask = (1 << nv_rd32(priv, 0x022438)) - 1;
139 mask &= ~nv_rd32(priv, 0x022548);
140 mask &= ~nv_rd32(priv, 0x0225c8);
141
142 ret = nouveau_perfdom_new(&priv->base, "part", mask, 0x1a0000,
143 0x1000, 0x200, nve0_perfmon_part);
144 if (ret)
145 return ret;
146
147 nv_engine(priv)->cclass = &nouveau_perfmon_cclass;
148 nv_engine(priv)->sclass = nouveau_perfmon_sclass;
149 priv->base.last = 7;
150 return 0;
151}
152
153struct nouveau_oclass
154nve0_perfmon_oclass = {
155 .handle = NV_ENGINE(PERFMON, 0xe0),
156 .ofuncs = &(struct nouveau_ofuncs) {
157 .ctor = nve0_perfmon_ctor,
158 .dtor = _nouveau_perfmon_dtor,
159 .init = _nouveau_perfmon_init,
160 .fini = nvc0_perfmon_fini,
161 },
162};
diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/nvf0.c
new file mode 100644
index 000000000000..47256f78a895
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nvf0.c
@@ -0,0 +1,71 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "nvc0.h"
26
27/*******************************************************************************
28 * Perfmon object classes
29 ******************************************************************************/
30
31/*******************************************************************************
32 * PPM context
33 ******************************************************************************/
34
35/*******************************************************************************
36 * PPM engine/subdev functions
37 ******************************************************************************/
38
39static int
40nvf0_perfmon_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
41 struct nouveau_oclass *oclass, void *data, u32 size,
42 struct nouveau_object **pobject)
43{
44 struct nvc0_perfmon_priv *priv;
45 int ret;
46
47 ret = nouveau_perfmon_create(parent, engine, oclass, &priv);
48 *pobject = nv_object(priv);
49 if (ret)
50 return ret;
51
52 ret = nouveau_perfdom_new(&priv->base, "pwr", 0, 0, 0, 0,
53 nve0_perfmon_pwr);
54 if (ret)
55 return ret;
56
57 nv_engine(priv)->cclass = &nouveau_perfmon_cclass;
58 nv_engine(priv)->sclass = nouveau_perfmon_sclass;
59 return 0;
60}
61
62struct nouveau_oclass
63nvf0_perfmon_oclass = {
64 .handle = NV_ENGINE(PERFMON, 0xf0),
65 .ofuncs = &(struct nouveau_ofuncs) {
66 .ctor = nvf0_perfmon_ctor,
67 .dtor = _nouveau_perfmon_dtor,
68 .init = _nouveau_perfmon_init,
69 .fini = nvc0_perfmon_fini,
70 },
71};
diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/priv.h b/drivers/gpu/drm/nouveau/core/engine/perfmon/priv.h
new file mode 100644
index 000000000000..0ac8714fe0ba
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/priv.h
@@ -0,0 +1,91 @@
1#ifndef __NVKM_PERFMON_PRIV_H__
2#define __NVKM_PERFMON_PRIV_H__
3
4#include <engine/perfmon.h>
5
6struct nouveau_perfctr {
7 struct nouveau_object base;
8 struct list_head head;
9 struct nouveau_perfsig *signal[4];
10 int slot;
11 u32 logic_op;
12 u32 clk;
13 u32 ctr;
14};
15
16extern struct nouveau_oclass nouveau_perfmon_sclass[];
17
18struct nouveau_perfctx {
19 struct nouveau_engctx base;
20};
21
22extern struct nouveau_oclass nouveau_perfmon_cclass;
23
24struct nouveau_specsig {
25 u8 signal;
26 const char *name;
27};
28
29struct nouveau_perfsig {
30 const char *name;
31};
32
33struct nouveau_perfdom;
34struct nouveau_perfctr *
35nouveau_perfsig_wrap(struct nouveau_perfmon *, const char *,
36 struct nouveau_perfdom **);
37
38struct nouveau_specdom {
39 u16 signal_nr;
40 const struct nouveau_specsig *signal;
41 const struct nouveau_funcdom *func;
42};
43
44extern const struct nouveau_specdom nva3_perfmon_pwr[];
45extern const struct nouveau_specdom nvc0_perfmon_pwr[];
46extern const struct nouveau_specdom nve0_perfmon_pwr[];
47
48struct nouveau_perfdom {
49 struct list_head head;
50 struct list_head list;
51 const struct nouveau_funcdom *func;
52 char name[32];
53 u32 addr;
54 u8 quad;
55 u32 signal_nr;
56 struct nouveau_perfsig signal[];
57};
58
59struct nouveau_funcdom {
60 void (*init)(struct nouveau_perfmon *, struct nouveau_perfdom *,
61 struct nouveau_perfctr *);
62 void (*read)(struct nouveau_perfmon *, struct nouveau_perfdom *,
63 struct nouveau_perfctr *);
64 void (*next)(struct nouveau_perfmon *, struct nouveau_perfdom *);
65};
66
67int nouveau_perfdom_new(struct nouveau_perfmon *, const char *, u32,
68 u32, u32, u32, const struct nouveau_specdom *);
69
70#define nouveau_perfmon_create(p,e,o,d) \
71 nouveau_perfmon_create_((p), (e), (o), sizeof(**d), (void **)d)
72#define nouveau_perfmon_dtor(p) ({ \
73 struct nouveau_perfmon *c = (p); \
74 _nouveau_perfmon_dtor(nv_object(c)); \
75})
76#define nouveau_perfmon_init(p) ({ \
77 struct nouveau_perfmon *c = (p); \
78 _nouveau_perfmon_init(nv_object(c)); \
79})
80#define nouveau_perfmon_fini(p,s) ({ \
81 struct nouveau_perfmon *c = (p); \
82 _nouveau_perfmon_fini(nv_object(c), (s)); \
83})
84
85int nouveau_perfmon_create_(struct nouveau_object *, struct nouveau_object *,
86 struct nouveau_oclass *, int, void **);
87void _nouveau_perfmon_dtor(struct nouveau_object *);
88int _nouveau_perfmon_init(struct nouveau_object *);
89int _nouveau_perfmon_fini(struct nouveau_object *, bool);
90
91#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h
index cf9e73c014ab..a30fd990afc8 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/class.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/class.h
@@ -98,6 +98,37 @@ struct nv_dma_class {
98 u32 conf0; 98 u32 conf0;
99}; 99};
100 100
101/* Perfmon counter class
102 *
103 * XXXX: NV_PERFCTR
104 */
105#define NV_PERFCTR_CLASS 0x0000ffff
106#define NV_PERFCTR_QUERY 0x00000000
107#define NV_PERFCTR_SAMPLE 0x00000001
108#define NV_PERFCTR_READ 0x00000002
109
110struct nv_perfctr_class {
111 u16 logic_op;
112 struct {
113 char __user *name; /*XXX: use cfu when exposed to userspace */
114 u32 size;
115 } signal[4];
116};
117
118struct nv_perfctr_query {
119 u32 iter;
120 u32 size;
121 char __user *name; /*XXX: use ctu when exposed to userspace */
122};
123
124struct nv_perfctr_sample {
125};
126
127struct nv_perfctr_read {
128 u32 ctr;
129 u32 clk;
130};
131
101/* DMA FIFO channel classes 132/* DMA FIFO channel classes
102 * 133 *
103 * 006b: NV03_CHANNEL_DMA 134 * 006b: NV03_CHANNEL_DMA
diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h
index 0709ed520eb2..ac2881d1776a 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/device.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/device.h
@@ -54,6 +54,7 @@ enum nv_subdev_type {
54 NVDEV_ENGINE_VIC, 54 NVDEV_ENGINE_VIC,
55 NVDEV_ENGINE_VENC, 55 NVDEV_ENGINE_VENC,
56 NVDEV_ENGINE_DISP, 56 NVDEV_ENGINE_DISP,
57 NVDEV_ENGINE_PERFMON,
57 58
58 NVDEV_SUBDEV_NR, 59 NVDEV_SUBDEV_NR,
59}; 60};
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/perfmon.h b/drivers/gpu/drm/nouveau/core/include/engine/perfmon.h
new file mode 100644
index 000000000000..49b0024910fe
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/engine/perfmon.h
@@ -0,0 +1,39 @@
1#ifndef __NVKM_PERFMON_H__
2#define __NVKM_PERFMON_H__
3
4#include <core/device.h>
5#include <core/engine.h>
6#include <core/engctx.h>
7#include <core/class.h>
8
9struct nouveau_perfdom;
10struct nouveau_perfctr;
11struct nouveau_perfmon {
12 struct nouveau_engine base;
13
14 struct nouveau_perfctx *context;
15 void *profile_data;
16
17 struct list_head domains;
18 u32 sequence;
19
20 /*XXX: temp for daemon backend */
21 u32 pwr[8];
22 u32 last;
23};
24
25static inline struct nouveau_perfmon *
26nouveau_perfmon(void *obj)
27{
28 return (void *)nv_device(obj)->subdev[NVDEV_ENGINE_PERFMON];
29}
30
31extern struct nouveau_oclass *nv40_perfmon_oclass;
32extern struct nouveau_oclass *nv50_perfmon_oclass;
33extern struct nouveau_oclass *nv84_perfmon_oclass;
34extern struct nouveau_oclass *nva3_perfmon_oclass;
35extern struct nouveau_oclass nvc0_perfmon_oclass;
36extern struct nouveau_oclass nve0_perfmon_oclass;
37extern struct nouveau_oclass nvf0_perfmon_oclass;
38
39#endif